root/ompi/mca/io/romio321/romio/adio/common/ad_write_str.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ADIOI_GEN_WriteStrided

   1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
   2 /* 
   3  *
   4  *   Copyright (C) 1997 University of Chicago. 
   5  *   See COPYRIGHT notice in top-level directory.
   6  */
   7 
   8 #include "adio.h"
   9 #include "adio_extern.h"
  10 
  11 #define ADIOI_BUFFERED_WRITE \
  12 { \
  13     if (req_off >= writebuf_off + writebuf_len) { \
  14         if (writebuf_len) { \
  15            ADIO_WriteContig(fd, writebuf, writebuf_len, MPI_BYTE, \
  16                   ADIO_EXPLICIT_OFFSET, writebuf_off, &status1, error_code); \
  17            if (!(fd->atomicity)) ADIOI_UNLOCK(fd, writebuf_off, SEEK_SET, writebuf_len); \
  18            if (*error_code != MPI_SUCCESS) { \
  19                *error_code = MPIO_Err_create_code(*error_code, \
  20                                                   MPIR_ERR_RECOVERABLE, myname, \
  21                                                   __LINE__, MPI_ERR_IO, \
  22                                                   "**iowswc", 0); \
  23                goto fn_exit; \
  24            } \
  25         } \
  26         writebuf_off = req_off; \
  27         writebuf_len = (unsigned) (ADIOI_MIN(max_bufsize,end_offset-writebuf_off+1));\
  28         if (!(fd->atomicity)) ADIOI_WRITE_LOCK(fd, writebuf_off, SEEK_SET, writebuf_len); \
  29         ADIO_ReadContig(fd, writebuf, writebuf_len, MPI_BYTE, \
  30                  ADIO_EXPLICIT_OFFSET, writebuf_off, &status1, error_code); \
  31         if (*error_code != MPI_SUCCESS) { \
  32             *error_code = MPIO_Err_create_code(*error_code, \
  33                                                MPIR_ERR_RECOVERABLE, myname, \
  34                                                __LINE__, MPI_ERR_IO, \
  35                                                "**iowsrc", 0); \
  36             goto fn_exit; \
  37         } \
  38     } \
  39     write_sz = (unsigned) (ADIOI_MIN(req_len, writebuf_off + writebuf_len - req_off)); \
  40     ADIOI_Assert((ADIO_Offset)write_sz == ADIOI_MIN(req_len, writebuf_off + writebuf_len - req_off));\
  41     memcpy(writebuf+req_off-writebuf_off, (char *)buf +userbuf_off, write_sz);\
  42     while (write_sz != req_len) { \
  43         ADIO_WriteContig(fd, writebuf, writebuf_len, MPI_BYTE, \
  44                   ADIO_EXPLICIT_OFFSET, writebuf_off, &status1, error_code); \
  45         if (!(fd->atomicity)) ADIOI_UNLOCK(fd, writebuf_off, SEEK_SET, writebuf_len); \
  46         if (*error_code != MPI_SUCCESS) { \
  47             *error_code = MPIO_Err_create_code(*error_code, \
  48                                                MPIR_ERR_RECOVERABLE, myname, \
  49                                                __LINE__, MPI_ERR_IO, \
  50                                                "**iowswc", 0); \
  51             goto fn_exit; \
  52         } \
  53         req_len -= write_sz; \
  54         userbuf_off += write_sz; \
  55         writebuf_off += writebuf_len; \
  56         writebuf_len = (unsigned) (ADIOI_MIN(max_bufsize,end_offset-writebuf_off+1));\
  57         if (!(fd->atomicity)) ADIOI_WRITE_LOCK(fd, writebuf_off, SEEK_SET, writebuf_len); \
  58         ADIO_ReadContig(fd, writebuf, writebuf_len, MPI_BYTE, \
  59                   ADIO_EXPLICIT_OFFSET, writebuf_off, &status1, error_code); \
  60         if (*error_code != MPI_SUCCESS) { \
  61             *error_code = MPIO_Err_create_code(*error_code, \
  62                                                MPIR_ERR_RECOVERABLE, myname, \
  63                                                __LINE__, MPI_ERR_IO, \
  64                                                "**iowsrc", 0); \
  65             goto fn_exit; \
  66         } \
  67         write_sz = ADIOI_MIN(req_len, writebuf_len); \
  68         memcpy(writebuf, (char *)buf + userbuf_off, write_sz);\
  69     } \
  70 }
  71 
  72 
  73 /* this macro is used when filetype is contig and buftype is not contig.
  74    it does not do a read-modify-write and does not lock*/
  75 #define ADIOI_BUFFERED_WRITE_WITHOUT_READ \
  76 { \
  77     if (req_off >= writebuf_off + writebuf_len) { \
  78         ADIO_WriteContig(fd, writebuf, writebuf_len, MPI_BYTE, \
  79                  ADIO_EXPLICIT_OFFSET, writebuf_off, &status1, error_code); \
  80         if (*error_code != MPI_SUCCESS) { \
  81             *error_code = MPIO_Err_create_code(*error_code, \
  82                                                MPIR_ERR_RECOVERABLE, myname, \
  83                                                __LINE__, MPI_ERR_IO, \
  84                                                "**iowswc", 0); \
  85             goto fn_exit; \
  86         } \
  87         writebuf_off = req_off; \
  88         writebuf_len = (unsigned) (ADIOI_MIN(max_bufsize,end_offset-writebuf_off+1));\
  89     } \
  90     write_sz = (unsigned) (ADIOI_MIN(req_len, writebuf_off + writebuf_len - req_off)); \
  91     ADIOI_Assert((ADIO_Offset)write_sz == ADIOI_MIN(req_len, writebuf_off + writebuf_len - req_off));\
  92     memcpy(writebuf+req_off-writebuf_off, (char *)buf +userbuf_off, write_sz);\
  93     while (write_sz != req_len) { \
  94         ADIO_WriteContig(fd, writebuf, writebuf_len, MPI_BYTE, \
  95                 ADIO_EXPLICIT_OFFSET, writebuf_off, &status1, error_code); \
  96         if (*error_code != MPI_SUCCESS) { \
  97             *error_code = MPIO_Err_create_code(*error_code, \
  98                                                MPIR_ERR_RECOVERABLE, myname, \
  99                                                __LINE__, MPI_ERR_IO, \
 100                                                "**iowswc", 0); \
 101             goto fn_exit; \
 102         } \
 103         req_len -= write_sz; \
 104         userbuf_off += write_sz; \
 105         writebuf_off += writebuf_len; \
 106         writebuf_len = (unsigned) (ADIOI_MIN(max_bufsize,end_offset-writebuf_off+1));\
 107         write_sz = ADIOI_MIN(req_len, writebuf_len); \
 108         memcpy(writebuf, (char *)buf + userbuf_off, write_sz);\
 109     } \
 110 }
 111 void ADIOI_GEN_WriteStrided(ADIO_File fd, const void *buf, int count,
 112                        MPI_Datatype datatype, int file_ptr_type,
 113                        ADIO_Offset offset, ADIO_Status *status, int
 114                        *error_code)
 115 {
 116 
 117 /* offset is in units of etype relative to the filetype. */
 118 
 119     ADIOI_Flatlist_node *flat_buf, *flat_file;
 120     ADIO_Offset i_offset, sum, size_in_filetype;
 121     int i, j, k, st_index=0;
 122     ADIO_Offset num, size, n_filetypes, etype_in_filetype, st_n_filetypes;
 123     ADIO_Offset n_etypes_in_filetype, abs_off_in_filetype=0;
 124     MPI_Count filetype_size, etype_size, buftype_size;
 125     MPI_Aint filetype_extent, buftype_extent, lb; 
 126     int buf_count, buftype_is_contig, filetype_is_contig;
 127     ADIO_Offset userbuf_off;
 128     ADIO_Offset off, req_off, disp, end_offset=0, writebuf_off, start_off;
 129     char *writebuf=NULL;
 130     unsigned writebuf_len, max_bufsize, write_sz;
 131     MPI_Aint bufsize;
 132     ADIO_Status status1;
 133     ADIO_Offset new_bwr_size, new_fwr_size, st_fwr_size, fwr_size=0, bwr_size, req_len;
 134     static char myname[] = "ADIOI_GEN_WriteStrided";
 135 
 136     if (fd->hints->ds_write == ADIOI_HINT_DISABLE) {
 137         /* if user has disabled data sieving on reads, use naive
 138          * approach instead.
 139          */
 140 
 141         ADIOI_GEN_WriteStrided_naive(fd, 
 142                                     buf,
 143                                     count,
 144                                     datatype,
 145                                     file_ptr_type,
 146                                     offset,
 147                                     status,
 148                                     error_code);
 149         return;
 150     }
 151 
 152 
 153     *error_code = MPI_SUCCESS;  /* changed below if error */
 154 
 155     ADIOI_Datatype_iscontig(datatype, &buftype_is_contig);
 156     ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig);
 157 
 158     MPI_Type_size_x(fd->filetype, &filetype_size);
 159     if ( ! filetype_size ) {
 160 #ifdef HAVE_STATUS_SET_BYTES
 161         MPIR_Status_set_bytes(status, datatype, 0);
 162 #endif
 163         *error_code = MPI_SUCCESS; 
 164         return;
 165     }
 166 
 167     MPI_Type_get_extent(fd->filetype, &lb, &filetype_extent);
 168     MPI_Type_size_x(datatype, &buftype_size);
 169     MPI_Type_get_extent(datatype, &lb, &buftype_extent);
 170     etype_size = fd->etype_size;
 171 
 172     ADIOI_Assert((buftype_size * count) == ((MPI_Count)buftype_size * (ADIO_Offset)count));
 173     bufsize = buftype_size * count;
 174 
 175 /* get max_bufsize from the info object. */
 176 
 177     max_bufsize = fd->hints->ind_wr_buffer_size;
 178 
 179     if (!buftype_is_contig && filetype_is_contig) {
 180 
 181 /* noncontiguous in memory, contiguous in file. */
 182 
 183         flat_buf = ADIOI_Flatten_and_find(datatype);
 184 
 185         off = (file_ptr_type == ADIO_INDIVIDUAL) ? fd->fp_ind : 
 186                  fd->disp + (ADIO_Offset)etype_size * offset;
 187 
 188         start_off = off;
 189         end_offset = off + bufsize - 1;
 190         writebuf_off = off;
 191         writebuf = (char *) ADIOI_Malloc(max_bufsize);
 192         writebuf_len = (unsigned) (ADIOI_MIN(max_bufsize, end_offset-writebuf_off+1));
 193 
 194 /* if atomicity is true, lock the region to be accessed */
 195         if (fd->atomicity) 
 196             ADIOI_WRITE_LOCK(fd, start_off, SEEK_SET, end_offset-start_off+1);
 197 
 198         for (j=0; j<count; j++) 
 199         {
 200               for (i=0; i<flat_buf->count; i++) {
 201                   userbuf_off = (ADIO_Offset)j*(ADIO_Offset)buftype_extent + flat_buf->indices[i];
 202       req_off = off;
 203       req_len = flat_buf->blocklens[i];
 204       ADIOI_BUFFERED_WRITE_WITHOUT_READ
 205                   off += flat_buf->blocklens[i];
 206               }
 207         }
 208 
 209         /* write the buffer out finally */
 210         ADIO_WriteContig(fd, writebuf, writebuf_len, MPI_BYTE, ADIO_EXPLICIT_OFFSET,
 211                         writebuf_off, &status1, error_code);
 212 
 213         if (fd->atomicity) 
 214             ADIOI_UNLOCK(fd, start_off, SEEK_SET, end_offset-start_off+1);
 215 
 216         if (*error_code != MPI_SUCCESS) goto fn_exit;
 217 
 218         if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind = off;
 219     }
 220 
 221     else {  /* noncontiguous in file */
 222 
 223 /* filetype already flattened in ADIO_Open */
 224         flat_file = ADIOI_Flatlist;
 225         while (flat_file->type != fd->filetype) flat_file = flat_file->next;
 226         disp = fd->disp;
 227 
 228         if (file_ptr_type == ADIO_INDIVIDUAL) {
 229         /* Wei-keng reworked type processing to be a bit more efficient */
 230             offset       = fd->fp_ind - disp;
 231             n_filetypes  = (offset - flat_file->indices[0]) / filetype_extent;
 232             offset      -= (ADIO_Offset)n_filetypes * filetype_extent;
 233             /* now offset is local to this extent */
 234 
 235             /* find the block where offset is located, skip blocklens[i]==0 */
 236             for (i=0; i<flat_file->count; i++) {
 237                 ADIO_Offset dist;
 238                 if (flat_file->blocklens[i] == 0) continue;
 239                 dist = flat_file->indices[i] + flat_file->blocklens[i] - offset;
 240                 /* fwr_size is from offset to the end of block i */
 241                 if (dist == 0) {
 242                     i++;
 243                     offset   = flat_file->indices[i];
 244                     fwr_size = flat_file->blocklens[i];
 245                     break;
 246                 }
 247                 if (dist > 0) {
 248                     fwr_size = dist;
 249                     break;
 250                 }
 251             }
 252             st_index = i;  /* starting index in flat_file->indices[] */
 253             offset += disp + (ADIO_Offset)n_filetypes*filetype_extent;
 254         }
 255         else {
 256             n_etypes_in_filetype = filetype_size/etype_size;
 257             n_filetypes = offset / n_etypes_in_filetype;
 258             etype_in_filetype = offset % n_etypes_in_filetype;
 259             size_in_filetype = etype_in_filetype * etype_size;
 260  
 261             sum = 0;
 262             for (i=0; i<flat_file->count; i++) {
 263                 sum += flat_file->blocklens[i];
 264                 if (sum > size_in_filetype) {
 265                     st_index = i;
 266                     fwr_size = sum - size_in_filetype;
 267                     abs_off_in_filetype = flat_file->indices[i] +
 268                         size_in_filetype - (sum - flat_file->blocklens[i]);
 269                     break;
 270                 }
 271             }
 272 
 273             /* abs. offset in bytes in the file */
 274             offset = disp + (ADIO_Offset) n_filetypes*filetype_extent + 
 275                     abs_off_in_filetype;
 276         }
 277 
 278         start_off = offset;
 279 
 280         /* Wei-keng Liao:write request is within single flat_file contig block*/
 281         /* this could happen, for example, with subarray types that are
 282          * actually fairly contiguous */
 283         if (buftype_is_contig && bufsize <= fwr_size) {
 284             /* though MPI api has an integer 'count' parameter, derived
 285              * datatypes might describe more bytes than can fit into an integer.
 286              * if we've made it this far, we can pass a count of original
 287              * datatypes, instead of a count of bytes (which might overflow)
 288              * Other WriteContig calls in this path are operating on data
 289              * sieving buffer */
 290             ADIO_WriteContig(fd, buf, count, datatype, ADIO_EXPLICIT_OFFSET,
 291                              offset, status, error_code);
 292 
 293             if (file_ptr_type == ADIO_INDIVIDUAL) {
 294                 /* update MPI-IO file pointer to point to the first byte 
 295                  * that can be accessed in the fileview. */
 296                 fd->fp_ind = offset + bufsize;
 297                 if (bufsize == fwr_size) {
 298                     do {
 299                         st_index++;
 300                         if (st_index == flat_file->count) {
 301                             st_index = 0;
 302                             n_filetypes++;
 303                         }
 304                     } while (flat_file->blocklens[st_index] == 0);
 305                     fd->fp_ind = disp + flat_file->indices[st_index]
 306                                + (ADIO_Offset)n_filetypes*filetype_extent;
 307                 }
 308             }
 309             fd->fp_sys_posn = -1;   /* set it to null. */ 
 310 #ifdef HAVE_STATUS_SET_BYTES
 311             MPIR_Status_set_bytes(status, datatype, bufsize);
 312 #endif 
 313             goto fn_exit;
 314         }
 315 
 316        /* Calculate end_offset, the last byte-offset that will be accessed.
 317          e.g., if start_offset=0 and 100 bytes to be write, end_offset=99*/
 318 
 319         st_fwr_size = fwr_size;
 320         st_n_filetypes = n_filetypes;
 321         i_offset = 0;
 322         j = st_index;
 323         off = offset;
 324         fwr_size = ADIOI_MIN(st_fwr_size, bufsize);
 325         while (i_offset < bufsize) {
 326             i_offset += fwr_size;
 327             end_offset = off + fwr_size - 1;
 328 
 329             j = (j+1) % flat_file->count;
 330             n_filetypes += (j == 0) ? 1 : 0;
 331             while (flat_file->blocklens[j]==0) {
 332                 j = (j+1) % flat_file->count;
 333                 n_filetypes += (j == 0) ? 1 : 0;
 334             }
 335 
 336             off = disp + flat_file->indices[j] + 
 337                     n_filetypes*(ADIO_Offset)filetype_extent;
 338             fwr_size = ADIOI_MIN(flat_file->blocklens[j], bufsize-i_offset);
 339         }
 340 
 341 /* if atomicity is true, lock the region to be accessed */
 342         if (fd->atomicity) 
 343             ADIOI_WRITE_LOCK(fd, start_off, SEEK_SET, end_offset-start_off+1);
 344 
 345         writebuf_off = 0;
 346         writebuf_len = 0;
 347         writebuf = (char *) ADIOI_Malloc(max_bufsize);
 348         memset(writebuf, -1, max_bufsize);
 349 
 350         if (buftype_is_contig && !filetype_is_contig) {
 351 
 352 /* contiguous in memory, noncontiguous in file. should be the most
 353    common case. */
 354 
 355             i_offset = 0;
 356             j = st_index;
 357             off = offset;
 358             n_filetypes = st_n_filetypes;
 359             fwr_size = ADIOI_MIN(st_fwr_size, bufsize);
 360             while (i_offset < bufsize) {
 361                 if (fwr_size) { 
 362                     /* TYPE_UB and TYPE_LB can result in 
 363                        fwr_size = 0. save system call in such cases */ 
 364                     /* lseek(fd->fd_sys, off, SEEK_SET);
 365                     err = write(fd->fd_sys, ((char *) buf) + i_offset, fwr_size);*/
 366 
 367                     req_off = off;
 368                     req_len = fwr_size;
 369                     userbuf_off = i_offset;
 370                     ADIOI_BUFFERED_WRITE
 371                 }
 372                 i_offset += fwr_size;
 373 
 374                 if (off + fwr_size < disp + flat_file->indices[j] +
 375                    flat_file->blocklens[j] + n_filetypes*(ADIO_Offset)filetype_extent)
 376                        off += fwr_size;
 377                 /* did not reach end of contiguous block in filetype.
 378                    no more I/O needed. off is incremented by fwr_size. */
 379                 else {
 380                     j = (j+1) % flat_file->count;
 381                     n_filetypes += (j == 0) ? 1 : 0;
 382                     while (flat_file->blocklens[j]==0) {
 383                         j = (j+1) % flat_file->count;
 384                         n_filetypes += (j == 0) ? 1 : 0;
 385                     }
 386                     off = disp + flat_file->indices[j] + 
 387                                     n_filetypes*(ADIO_Offset)filetype_extent;
 388                     fwr_size = ADIOI_MIN(flat_file->blocklens[j], 
 389                                     bufsize-i_offset);
 390                 }
 391             }
 392         }
 393         else {
 394 /* noncontiguous in memory as well as in file */
 395 
 396             flat_buf = ADIOI_Flatten_and_find(datatype);
 397 
 398             k = num = buf_count = 0;
 399             i_offset = flat_buf->indices[0];
 400             j = st_index;
 401             off = offset;
 402             n_filetypes = st_n_filetypes;
 403             fwr_size = st_fwr_size;
 404             bwr_size = flat_buf->blocklens[0];
 405 
 406             while (num < bufsize) {
 407                 size = ADIOI_MIN(fwr_size, bwr_size);
 408                 if (size) {
 409                     /* lseek(fd->fd_sys, off, SEEK_SET);
 410                     err = write(fd->fd_sys, ((char *) buf) + i_offset, size); */
 411 
 412                     req_off = off;
 413                     req_len = size;
 414                     userbuf_off = i_offset;
 415                     ADIOI_BUFFERED_WRITE
 416                 }
 417 
 418                 new_fwr_size = fwr_size;
 419                 new_bwr_size = bwr_size;
 420 
 421                 if (size == fwr_size) {
 422 /* reached end of contiguous block in file */
 423                     j = (j+1) % flat_file->count;
 424                     n_filetypes += (j == 0) ? 1 : 0;
 425                     while (flat_file->blocklens[j]==0) {
 426                         j = (j+1) % flat_file->count;
 427                         n_filetypes += (j == 0) ? 1 : 0;
 428                     }
 429 
 430                     off = disp + flat_file->indices[j] + 
 431                                       n_filetypes*(ADIO_Offset)filetype_extent;
 432 
 433                     new_fwr_size = flat_file->blocklens[j];
 434                     if (size != bwr_size) {
 435                         i_offset += size;
 436                         new_bwr_size -= size;
 437                     }
 438                 }
 439 
 440                 if (size == bwr_size) {
 441 /* reached end of contiguous block in memory */
 442 
 443                     k = (k + 1)%flat_buf->count;
 444                     buf_count++;
 445                     i_offset = (ADIO_Offset)buftype_extent*(ADIO_Offset)(buf_count/flat_buf->count) +
 446                         flat_buf->indices[k]; 
 447                     new_bwr_size = flat_buf->blocklens[k];
 448                     if (size != fwr_size) {
 449                         off += size;
 450                         new_fwr_size -= size;
 451                     }
 452                 }
 453                 num += size;
 454                 fwr_size = new_fwr_size;
 455                 bwr_size = new_bwr_size;
 456             }
 457         }
 458 
 459         /* write the buffer out finally */      
 460         if (writebuf_len) {
 461             ADIO_WriteContig(fd, writebuf, writebuf_len, MPI_BYTE, ADIO_EXPLICIT_OFFSET,
 462                         writebuf_off, &status1, error_code);
 463             if (!(fd->atomicity)) 
 464                 ADIOI_UNLOCK(fd, writebuf_off, SEEK_SET, writebuf_len);
 465             if (*error_code != MPI_SUCCESS) goto fn_exit;
 466         }
 467         if (fd->atomicity) 
 468             ADIOI_UNLOCK(fd, start_off, SEEK_SET, end_offset-start_off+1);
 469 
 470         if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind = off;
 471     }
 472 
 473     fd->fp_sys_posn = -1;   /* set it to null. */
 474 
 475 #ifdef HAVE_STATUS_SET_BYTES
 476     /* datatypes returning negagive values, probably related to tt 1893 */
 477     MPIR_Status_set_bytes(status, datatype, bufsize);
 478 /* This is a temporary way of filling in status. The right way is to 
 479    keep track of how much data was actually written by ADIOI_BUFFERED_WRITE. */
 480 #endif
 481 
 482     if (!buftype_is_contig) ADIOI_Delete_flattened(datatype);
 483 fn_exit:
 484     if (writebuf != NULL) ADIOI_Free(writebuf);
 485 }
 486 

/* [<][>][^][v][top][bottom][index][help] */