AMPI #952: update ROMIO to MPICH2-1.4.1p1
[charm.git] / src / libs / ck-libs / ampi / romio / adio / ad_piofs / ad_piofs_write.c
blob3f6417108bcf8331082ad04d4d7a99e38a950468
1 /* -*- Mode: C; c-basic-offset:4 ; -*- */
2 /*
4 * Copyright (C) 1997 University of Chicago.
5 * See COPYRIGHT notice in top-level directory.
6 */
8 #include "ad_piofs.h"
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;
16 #ifndef PRINT_ERR_MSG
17 static char myname[] = "ADIOI_PIOFS_WRITECONTIG";
18 #endif
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);
36 fd->fp_ind += err;
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);
42 #endif
44 if (err == -1) {
45 #ifdef MPICH2
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;
50 #else
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);
54 #endif
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
64 *error_code)
66 /* Since PIOFS does not support file locking, can't do buffered writes
67 as on Unix */
69 /* offset is in units of etype relative to the filetype. */
71 ADIOI_Flatlist_node *flat_buf, *flat_file;
72 struct iovec *iov;
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;
82 #ifndef PRINT_ERR_MSG
83 static char myname[] = "ADIOI_PIOFS_WRITESTRIDED";
84 #endif
86 if (fd->atomicity) {
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;
97 return;
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);
125 k = 0;
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];
134 k = (k+1)%16;
136 if (!k) {
137 err = writev(fd->fd_sys, iov, 16);
138 if (err == -1) err_flag = 1;
142 if (k) {
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;
149 ADIOI_Free(iov);
150 if (err_flag) {
151 #ifdef MPICH2
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;
156 #else /* MPICH-1 */
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);
160 #endif
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;
174 disp = fd->disp;
176 if (file_ptr_type == ADIO_INDIVIDUAL) {
177 offset = fd->fp_ind; /* in bytes */
178 n_filetypes = -1;
179 flag = 0;
180 while (!flag) {
181 n_filetypes++;
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]
185 >= offset) {
186 st_index = i;
187 fwr_size = disp + flat_file->indices[i] +
188 (ADIO_Offset) n_filetypes*filetype_extent
189 + flat_file->blocklens[i] - offset;
190 flag = 1;
191 break;
196 else {
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;
202 sum = 0;
203 for (i=0; i<flat_file->count; i++) {
204 sum += flat_file->blocklens[i];
205 if (sum > size_in_filetype) {
206 st_index = i;
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]);
210 break;
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
221 common case. */
223 i = 0;
224 j = st_index;
225 off = offset;
226 fwr_size = ADIOI_MIN(fwr_size, bufsize);
227 while (i < bufsize) {
228 if (fwr_size) {
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;
235 i += fwr_size;
237 if (off + fwr_size < disp + flat_file->indices[j] +
238 flat_file->blocklens[j] + (ADIO_Offset) n_filetypes*filetype_extent)
239 off += fwr_size;
240 /* did not reach end of contiguous block in filetype.
241 no more I/O needed. off is incremented by fwr_size. */
242 else {
243 if (j < (flat_file->count - 1)) j++;
244 else {
245 j = 0;
246 n_filetypes++;
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);
254 else {
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];
263 j = st_index;
264 off = offset;
265 bwr_size = flat_buf->blocklens[0];
267 while (num < bufsize) {
268 size = ADIOI_MIN(fwr_size, bwr_size);
269 if (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++;
281 else {
282 j = 0;
283 n_filetypes++;
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) {
291 indx += 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;
300 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) {
305 off += size;
306 new_fwr_size -= size;
309 num += size;
310 fwr_size = new_fwr_size;
311 bwr_size = new_bwr_size;
315 if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind = off;
316 if (err_flag) {
317 #ifdef MPICH2
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;
322 #else /* MPICH-1 */
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);
326 #endif
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. */
337 #endif
339 if (!buftype_is_contig) ADIOI_Delete_flattened(datatype);