1 /* -*- Mode: C; c-basic-offset:4 ; -*- */
4 * Copyright (C) 1997 University of Chicago.
5 * See COPYRIGHT notice in top-level directory.
9 #include "adio_extern.h"
11 void ADIOI_PIOFS_WriteContig(ADIO_File fd
, void *buf
, int count
,
12 MPI_Datatype datatype
, int file_ptr_type
,
13 ADIO_Offset offset
, ADIO_Status
*status
, int *error_code
)
15 int err
=-1, datatype_size
, len
;
17 static char myname
[] = "ADIOI_PIOFS_WRITECONTIG";
20 MPI_Type_size(datatype
, &datatype_size
);
21 len
= datatype_size
* count
;
23 if (file_ptr_type
== ADIO_EXPLICIT_OFFSET
) {
24 if (fd
->fp_sys_posn
!= offset
) {
25 llseek(fd
->fd_sys
, offset
, SEEK_SET
);
27 err
= write(fd
->fd_sys
, buf
, len
);
28 fd
->fp_sys_posn
= offset
+ err
;
29 /* individual file pointer not updated */
31 else { /* write from curr. location of ind. file pointer */
32 if (fd
->fp_sys_posn
!= fd
->fp_ind
) {
33 llseek(fd
->fd_sys
, fd
->fp_ind
, SEEK_SET
);
35 err
= write(fd
->fd_sys
, buf
, len
);
37 fd
->fp_sys_posn
= fd
->fp_ind
;
40 #ifdef HAVE_STATUS_SET_BYTES
41 if (err
!= -1) MPIR_Status_set_bytes(status
, datatype
, err
);
46 *error_code
= MPIR_Err_create_code(MPI_SUCCESS
, MPIR_ERR_RECOVERABLE
, myname
, __LINE__
, MPI_ERR_IO
, "**io",
47 "**io %s", strerror(errno
));
48 #elif defined(PRINT_ERR_MSG)
49 *error_code
= MPI_ERR_UNKNOWN
;
51 *error_code
= MPIR_Err_setmsg(MPI_ERR_IO
, MPIR_ADIO_ERROR
,
52 myname
, "I/O Error", "%s", strerror(errno
));
53 ADIOI_Error(fd
, *error_code
, myname
);
56 else *error_code
= MPI_SUCCESS
;
61 void ADIOI_PIOFS_WriteStrided(ADIO_File fd
, void *buf
, int count
,
62 MPI_Datatype datatype
, int file_ptr_type
,
63 ADIO_Offset offset
, ADIO_Status
*status
, int
66 /* Since PIOFS does not support file locking, can't do buffered writes
69 /* offset is in units of etype relative to the filetype. */
71 ADIOI_Flatlist_node
*flat_buf
, *flat_file
;
73 int i
, j
, k
, err
=-1, bwr_size
, fwr_size
=0, st_index
=0;
74 int bufsize
, num
, size
, sum
, n_etypes_in_filetype
, size_in_filetype
;
75 int n_filetypes
, etype_in_filetype
;
76 ADIO_Offset abs_off_in_filetype
=0;
77 int filetype_size
, etype_size
, buftype_size
;
78 MPI_Aint filetype_extent
, buftype_extent
, indx
;
79 int buf_count
, buftype_is_contig
, filetype_is_contig
;
80 ADIO_Offset off
, disp
;
81 int flag
, new_bwr_size
, new_fwr_size
, err_flag
=0;
83 static char myname
[] = "ADIOI_PIOFS_WRITESTRIDED";
87 FPRINTF(stderr
, "ROMIO cannot guarantee atomicity of noncontiguous accesses in atomic mode, as PIOFS doesn't support file locking. Use nonatomic mode and its associated semantics.\n");
88 MPI_Abort(MPI_COMM_WORLD
, 1);
91 ADIOI_Datatype_iscontig(datatype
, &buftype_is_contig
);
92 ADIOI_Datatype_iscontig(fd
->filetype
, &filetype_is_contig
);
94 MPI_Type_size(fd
->filetype
, &filetype_size
);
95 if ( ! filetype_size
) {
96 *error_code
= MPI_SUCCESS
;
100 MPI_Type_extent(fd
->filetype
, &filetype_extent
);
101 MPI_Type_size(datatype
, &buftype_size
);
102 MPI_Type_extent(datatype
, &buftype_extent
);
103 etype_size
= fd
->etype_size
;
105 bufsize
= buftype_size
* count
;
107 if (!buftype_is_contig
&& filetype_is_contig
) {
109 /* noncontiguous in memory, contiguous in file. use writev */
111 ADIOI_Flatten_datatype(datatype
);
112 flat_buf
= ADIOI_Flatlist
;
113 while (flat_buf
->type
!= datatype
) flat_buf
= flat_buf
->next
;
115 /* There is a limit of 16 on the number of iovecs for readv/writev! */
117 iov
= (struct iovec
*) ADIOI_Malloc(16*sizeof(struct iovec
));
119 if (file_ptr_type
== ADIO_EXPLICIT_OFFSET
) {
120 off
= fd
->disp
+ etype_size
* offset
;
121 llseek(fd
->fd_sys
, off
, SEEK_SET
);
123 else off
= llseek(fd
->fd_sys
, fd
->fp_ind
, SEEK_SET
);
126 for (j
=0; j
<count
; j
++)
127 for (i
=0; i
<flat_buf
->count
; i
++) {
128 iov
[k
].iov_base
= ((char *) buf
) + j
*buftype_extent
+
129 flat_buf
->indices
[i
];
130 iov
[k
].iov_len
= flat_buf
->blocklens
[i
];
131 /*FPRINTF(stderr, "%d %d\n", iov[k].iov_base, iov[k].iov_len);*/
133 off
+= flat_buf
->blocklens
[i
];
137 err
= writev(fd
->fd_sys
, iov
, 16);
138 if (err
== -1) err_flag
= 1;
143 err
= writev(fd
->fd_sys
, iov
, k
);
144 if (err
== -1) err_flag
= 1;
147 if (file_ptr_type
== ADIO_INDIVIDUAL
) fd
->fp_ind
= off
;
152 *error_code
= MPIR_Err_create_code(MPI_SUCCESS
, MPIR_ERR_RECOVERABLE
, myname
, __LINE__
, MPI_ERR_IO
, "**io",
153 "**io %s", strerror(errno
));
154 #elif defined(PRINT_ERR_MSG)
155 *error_code
= MPI_ERR_UNKNOWN
;
157 *error_code
= MPIR_Err_setmsg(MPI_ERR_IO
, MPIR_ADIO_ERROR
,
158 myname
, "I/O Error", "%s", strerror(errno
));
159 ADIOI_Error(fd
, *error_code
, myname
);
162 else *error_code
= MPI_SUCCESS
;
163 } /* if (!buftype_is_contig && filetype_is_contig) ... */
165 else { /* noncontiguous in file */
167 /* split up into several contiguous writes */
169 /* find starting location in the file */
171 /* filetype already flattened in ADIO_Open */
172 flat_file
= ADIOI_Flatlist
;
173 while (flat_file
->type
!= fd
->filetype
) flat_file
= flat_file
->next
;
176 if (file_ptr_type
== ADIO_INDIVIDUAL
) {
177 offset
= fd
->fp_ind
; /* in bytes */
182 for (i
=0; i
<flat_file
->count
; i
++) {
183 if (disp
+ flat_file
->indices
[i
] +
184 (ADIO_Offset
) n_filetypes
*filetype_extent
+ flat_file
->blocklens
[i
]
187 fwr_size
= disp
+ flat_file
->indices
[i
] +
188 (ADIO_Offset
) n_filetypes
*filetype_extent
189 + flat_file
->blocklens
[i
] - offset
;
197 n_etypes_in_filetype
= filetype_size
/etype_size
;
198 n_filetypes
= (int) (offset
/ n_etypes_in_filetype
);
199 etype_in_filetype
= (int) (offset
% n_etypes_in_filetype
);
200 size_in_filetype
= etype_in_filetype
* etype_size
;
203 for (i
=0; i
<flat_file
->count
; i
++) {
204 sum
+= flat_file
->blocklens
[i
];
205 if (sum
> size_in_filetype
) {
207 fwr_size
= sum
- size_in_filetype
;
208 abs_off_in_filetype
= flat_file
->indices
[i
] +
209 size_in_filetype
- (sum
- flat_file
->blocklens
[i
]);
214 /* abs. offset in bytes in the file */
215 offset
= disp
+ (ADIO_Offset
) n_filetypes
*filetype_extent
+ abs_off_in_filetype
;
218 if (buftype_is_contig
&& !filetype_is_contig
) {
220 /* contiguous in memory, noncontiguous in file. should be the most
226 fwr_size
= ADIOI_MIN(fwr_size
, bufsize
);
227 while (i
< bufsize
) {
229 /* TYPE_UB and TYPE_LB can result in
230 fwr_size = 0. save system call in such cases */
231 llseek(fd
->fd_sys
, off
, SEEK_SET
);
232 err
= write(fd
->fd_sys
, ((char *) buf
) + i
, fwr_size
);
233 if (err
== -1) err_flag
= 1;
237 if (off
+ fwr_size
< disp
+ flat_file
->indices
[j
] +
238 flat_file
->blocklens
[j
] + (ADIO_Offset
) n_filetypes
*filetype_extent
)
240 /* did not reach end of contiguous block in filetype.
241 no more I/O needed. off is incremented by fwr_size. */
243 if (j
< (flat_file
->count
- 1)) j
++;
248 off
= disp
+ flat_file
->indices
[j
] +
249 (ADIO_Offset
) n_filetypes
*filetype_extent
;
250 fwr_size
= ADIOI_MIN(flat_file
->blocklens
[j
], bufsize
-i
);
255 /* noncontiguous in memory as well as in file */
257 ADIOI_Flatten_datatype(datatype
);
258 flat_buf
= ADIOI_Flatlist
;
259 while (flat_buf
->type
!= datatype
) flat_buf
= flat_buf
->next
;
261 k
= num
= buf_count
= 0;
262 indx
= flat_buf
->indices
[0];
265 bwr_size
= flat_buf
->blocklens
[0];
267 while (num
< bufsize
) {
268 size
= ADIOI_MIN(fwr_size
, bwr_size
);
270 llseek(fd
->fd_sys
, off
, SEEK_SET
);
271 err
= write(fd
->fd_sys
, ((char *) buf
) + indx
, size
);
272 if (err
== -1) err_flag
= 1;
275 new_fwr_size
= fwr_size
;
276 new_bwr_size
= bwr_size
;
278 if (size
== fwr_size
) {
279 /* reached end of contiguous block in file */
280 if (j
< (flat_file
->count
- 1)) j
++;
286 off
= disp
+ flat_file
->indices
[j
] +
287 (ADIO_Offset
) n_filetypes
*filetype_extent
;
289 new_fwr_size
= flat_file
->blocklens
[j
];
290 if (size
!= bwr_size
) {
292 new_bwr_size
-= size
;
296 if (size
== bwr_size
) {
297 /* reached end of contiguous block in memory */
299 k
= (k
+ 1)%flat_buf
->count
;
301 indx
= buftype_extent
*(buf_count
/flat_buf
->count
) +
302 flat_buf
->indices
[k
];
303 new_bwr_size
= flat_buf
->blocklens
[k
];
304 if (size
!= fwr_size
) {
306 new_fwr_size
-= size
;
310 fwr_size
= new_fwr_size
;
311 bwr_size
= new_bwr_size
;
315 if (file_ptr_type
== ADIO_INDIVIDUAL
) fd
->fp_ind
= off
;
318 *error_code
= MPIR_Err_create_code(MPI_SUCCESS
, MPIR_ERR_RECOVERABLE
, myname
, __LINE__
, MPI_ERR_IO
, "**io",
319 "**io %s", strerror(errno
));
320 #elif defined(PRINT_ERR_MSG)
321 *error_code
= MPI_ERR_UNKNOWN
;
323 *error_code
= MPIR_Err_setmsg(MPI_ERR_IO
, MPIR_ADIO_ERROR
,
324 myname
, "I/O Error", "%s", strerror(errno
));
325 ADIOI_Error(fd
, *error_code
, myname
);
328 else *error_code
= MPI_SUCCESS
;
331 fd
->fp_sys_posn
= -1; /* set it to null. */
333 #ifdef HAVE_STATUS_SET_BYTES
334 MPIR_Status_set_bytes(status
, datatype
, bufsize
);
335 /* This is a temporary way of filling in status. The right way is to
336 keep track of how much data was actually written by ADIOI_BUFFERED_WRITE. */
339 if (!buftype_is_contig
) ADIOI_Delete_flattened(datatype
);