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

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

DEFINITIONS

This source file includes following definitions.
  1. ADIOI_GEN_ReadStrided

   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_READ \
  12 { \
  13     if (req_off >= readbuf_off + readbuf_len) { \
  14         readbuf_off = req_off; \
  15         readbuf_len = (unsigned) (ADIOI_MIN(max_bufsize, end_offset-readbuf_off+1));\
  16         ADIO_ReadContig(fd, readbuf, readbuf_len, MPI_BYTE, \
  17               ADIO_EXPLICIT_OFFSET, readbuf_off, &status1, error_code); \
  18         if (*error_code != MPI_SUCCESS) return; \
  19     } \
  20     while (req_len > readbuf_off + readbuf_len - req_off) { \
  21   ADIOI_Assert((readbuf_off + readbuf_len - req_off) == (int) (readbuf_off + readbuf_len - req_off));\
  22         partial_read = (int) (readbuf_off + readbuf_len - req_off); \
  23         tmp_buf = (char *) ADIOI_Malloc(partial_read); \
  24         memcpy(tmp_buf, readbuf+readbuf_len-partial_read, partial_read); \
  25         ADIOI_Free(readbuf); \
  26         readbuf = (char *) ADIOI_Malloc(partial_read + max_bufsize); \
  27         memcpy(readbuf, tmp_buf, partial_read); \
  28         ADIOI_Free(tmp_buf); \
  29         readbuf_off += readbuf_len-partial_read; \
  30         readbuf_len = (unsigned) (partial_read + ADIOI_MIN(max_bufsize, \
  31                                        end_offset-readbuf_off+1)); \
  32         ADIO_ReadContig(fd, readbuf+partial_read, readbuf_len-partial_read, \
  33              MPI_BYTE, ADIO_EXPLICIT_OFFSET, readbuf_off+partial_read, \
  34              &status1, error_code); \
  35         if (*error_code != MPI_SUCCESS) return; \
  36     } \
  37     ADIOI_Assert((ADIO_Size) req_len == (size_t)req_len);                \
  38     memcpy((char *)buf + userbuf_off, readbuf+req_off-readbuf_off, req_len); \
  39 }
  40 
  41 
  42 void ADIOI_GEN_ReadStrided(ADIO_File fd, void *buf, int count,
  43                        MPI_Datatype datatype, int file_ptr_type,
  44                        ADIO_Offset offset, ADIO_Status *status, int
  45                        *error_code)
  46 {
  47 
  48 
  49 /* offset is in units of etype relative to the filetype. */
  50 
  51     ADIOI_Flatlist_node *flat_buf, *flat_file;
  52     ADIO_Offset i_offset, new_brd_size, brd_size, size;
  53     int i, j, k, st_index=0;
  54     MPI_Count num, bufsize;
  55     int n_etypes_in_filetype;
  56     ADIO_Offset n_filetypes, etype_in_filetype, st_n_filetypes, size_in_filetype;
  57     ADIO_Offset abs_off_in_filetype=0, new_frd_size, frd_size=0, st_frd_size;
  58     MPI_Count filetype_size, etype_size, buftype_size, partial_read;
  59     MPI_Aint filetype_extent, buftype_extent, lb; 
  60     int buf_count, buftype_is_contig, filetype_is_contig;
  61     ADIO_Offset userbuf_off, req_len, sum;
  62     ADIO_Offset off, req_off, disp, end_offset=0, readbuf_off, start_off;
  63     char *readbuf, *tmp_buf, *value;
  64     int info_flag;
  65     unsigned max_bufsize, readbuf_len;
  66     ADIO_Status status1;
  67 
  68     if (fd->hints->ds_read == ADIOI_HINT_DISABLE) {
  69         /* if user has disabled data sieving on reads, use naive
  70          * approach instead.
  71          */
  72         ADIOI_GEN_ReadStrided_naive(fd, 
  73                                     buf,
  74                                     count,
  75                                     datatype,
  76                                     file_ptr_type,
  77                                     offset,
  78                                     status,
  79                                     error_code);
  80         return;
  81     }
  82 
  83     *error_code = MPI_SUCCESS;  /* changed below if error */
  84 
  85     ADIOI_Datatype_iscontig(datatype, &buftype_is_contig);
  86     ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig);
  87 
  88     MPI_Type_size_x(fd->filetype, &filetype_size);
  89     if ( ! filetype_size ) {
  90 #ifdef HAVE_STATUS_SET_BYTES
  91         MPIR_Status_set_bytes(status, datatype, 0);
  92 #endif
  93         *error_code = MPI_SUCCESS; 
  94         return;
  95     }
  96 
  97     MPI_Type_get_extent(fd->filetype, &lb, &filetype_extent);
  98     MPI_Type_size_x(datatype, &buftype_size);
  99     MPI_Type_get_extent(datatype, &lb, &buftype_extent);
 100     etype_size = fd->etype_size;
 101 
 102     ADIOI_Assert((buftype_size * count) == ((ADIO_Offset)(MPI_Count)buftype_size * (ADIO_Offset)count));
 103     bufsize = buftype_size * count;
 104 
 105 /* get max_bufsize from the info object. */
 106 
 107     value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char));
 108     ADIOI_Info_get(fd->info, "ind_rd_buffer_size", MPI_MAX_INFO_VAL, value, 
 109                  &info_flag);
 110     max_bufsize = atoi(value);
 111     ADIOI_Free(value);
 112 
 113 
 114     if (!buftype_is_contig && filetype_is_contig) {
 115 
 116 /* noncontiguous in memory, contiguous in file. */
 117 
 118         flat_buf = ADIOI_Flatten_and_find(datatype);
 119 
 120         off = (file_ptr_type == ADIO_INDIVIDUAL) ? fd->fp_ind : 
 121                  fd->disp + (ADIO_Offset)etype_size * offset;
 122 
 123         start_off = off;
 124         end_offset = off + bufsize - 1;
 125         readbuf_off = off;
 126         readbuf = (char *) ADIOI_Malloc(max_bufsize);
 127         readbuf_len = (unsigned) (ADIOI_MIN(max_bufsize, end_offset-readbuf_off+1));
 128 
 129 /* if atomicity is true, lock (exclusive) the region to be accessed */
 130         if ((fd->atomicity) && ADIO_Feature(fd, ADIO_LOCKS))
 131             ADIOI_WRITE_LOCK(fd, start_off, SEEK_SET, end_offset-start_off+1);
 132 
 133         ADIO_ReadContig(fd, readbuf, readbuf_len, MPI_BYTE, 
 134             ADIO_EXPLICIT_OFFSET, readbuf_off, &status1, error_code);
 135         if (*error_code != MPI_SUCCESS) return;
 136 
 137         for (j=0; j<count; j++) 
 138         {
 139               for (i=0; i<flat_buf->count; i++) {
 140                   userbuf_off = (ADIO_Offset)j*(ADIO_Offset)buftype_extent + flat_buf->indices[i];
 141       req_off = off;
 142       req_len = flat_buf->blocklens[i];
 143       ADIOI_BUFFERED_READ
 144                   off += flat_buf->blocklens[i];
 145               }
 146         }
 147 
 148         if ((fd->atomicity) && ADIO_Feature(fd, ADIO_LOCKS))
 149             ADIOI_UNLOCK(fd, start_off, SEEK_SET, end_offset-start_off+1);
 150 
 151         if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind = off;
 152 
 153         ADIOI_Free(readbuf); 
 154     }
 155 
 156     else {  /* noncontiguous in file */
 157 
 158 /* filetype already flattened in ADIO_Open */
 159         flat_file = ADIOI_Flatlist;
 160         while (flat_file->type != fd->filetype) flat_file = flat_file->next;
 161         disp = fd->disp;
 162 
 163         if (file_ptr_type == ADIO_INDIVIDUAL) {
 164             /* Wei-keng reworked type processing to be a bit more efficient */
 165             offset       = fd->fp_ind - disp;
 166             n_filetypes  = (offset - flat_file->indices[0]) / filetype_extent;
 167             offset -= (ADIO_Offset)n_filetypes * filetype_extent;
 168             /* now offset is local to this extent */
 169 
 170             /* find the block where offset is located, skip blocklens[i]==0 */
 171             for (i=0; i<flat_file->count; i++) {
 172                 ADIO_Offset dist;
 173                 if (flat_file->blocklens[i] == 0) continue;
 174                 dist = flat_file->indices[i] + flat_file->blocklens[i] - offset;
 175                 /* frd_size is from offset to the end of block i */
 176                 if (dist == 0) {
 177                     i++;
 178                     offset   = flat_file->indices[i];
 179                     frd_size = flat_file->blocklens[i];
 180                     break;
 181                 }
 182                 if (dist > 0) {
 183                     frd_size = dist;
 184                     break;
 185                 }
 186             }
 187             st_index = i;  /* starting index in flat_file->indices[] */
 188             offset += disp + (ADIO_Offset)n_filetypes*filetype_extent;
 189         }
 190         else {
 191             n_etypes_in_filetype = filetype_size/etype_size;
 192             n_filetypes = offset / n_etypes_in_filetype;
 193             etype_in_filetype = offset % n_etypes_in_filetype;
 194             size_in_filetype = etype_in_filetype * etype_size;
 195  
 196             sum = 0;
 197             for (i=0; i<flat_file->count; i++) {
 198                 sum += flat_file->blocklens[i];
 199                 if (sum > size_in_filetype) {
 200                     st_index = i;
 201                     frd_size = sum - size_in_filetype;
 202                     abs_off_in_filetype = flat_file->indices[i] +
 203                         size_in_filetype - (sum - flat_file->blocklens[i]);
 204                     break;
 205                 }
 206             }
 207 
 208             /* abs. offset in bytes in the file */
 209             offset = disp + (ADIO_Offset) n_filetypes*filetype_extent + 
 210                     abs_off_in_filetype;
 211         }
 212 
 213         start_off = offset;
 214 
 215         /* Wei-keng Liao: read request is within a single flat_file contig
 216          * block e.g. with subarray types that actually describe the whole
 217          * array */
 218         if (buftype_is_contig && bufsize <= frd_size) {
 219             /* a count of bytes can overflow. operate on original type instead */
 220             ADIO_ReadContig(fd, buf, count, datatype, ADIO_EXPLICIT_OFFSET,
 221                              offset, status, error_code);
 222 
 223             if (file_ptr_type == ADIO_INDIVIDUAL) {
 224                 /* update MPI-IO file pointer to point to the first byte that 
 225                  * can be accessed in the fileview. */
 226                 fd->fp_ind = offset + bufsize;
 227                 if (bufsize == frd_size) {
 228                     do {
 229                         st_index++;
 230                         if (st_index == flat_file->count) {
 231                             st_index = 0;
 232                             n_filetypes++;
 233                         }
 234                     } while (flat_file->blocklens[st_index] == 0);
 235                     fd->fp_ind = disp + flat_file->indices[st_index]
 236                                + n_filetypes*filetype_extent;
 237                 }
 238             }
 239             fd->fp_sys_posn = -1;   /* set it to null. */ 
 240 #ifdef HAVE_STATUS_SET_BYTES
 241             MPIR_Status_set_bytes(status, datatype, bufsize);
 242 #endif 
 243             return;
 244         }
 245 
 246        /* Calculate end_offset, the last byte-offset that will be accessed.
 247          e.g., if start_offset=0 and 100 bytes to be read, end_offset=99*/
 248 
 249         st_frd_size = frd_size;
 250         st_n_filetypes = n_filetypes;
 251         i_offset = 0;
 252         j = st_index;
 253         off = offset;
 254         frd_size = ADIOI_MIN(st_frd_size, bufsize);
 255         while (i_offset < bufsize) {
 256             i_offset += frd_size;
 257             end_offset = off + frd_size - 1;
 258 
 259             j = (j+1) % flat_file->count;
 260             n_filetypes += (j == 0) ? 1 : 0;
 261             while (flat_file->blocklens[j]==0) {
 262                 j = (j+1) % flat_file->count;
 263                 n_filetypes += (j == 0) ? 1 : 0;
 264             }
 265             off = disp + flat_file->indices[j] + n_filetypes*(ADIO_Offset)filetype_extent;
 266             frd_size = ADIOI_MIN(flat_file->blocklens[j], bufsize-i_offset);
 267         }
 268 
 269 /* if atomicity is true, lock (exclusive) the region to be accessed */
 270         if ((fd->atomicity) && ADIO_Feature(fd, ADIO_LOCKS))
 271             ADIOI_WRITE_LOCK(fd, start_off, SEEK_SET, end_offset-start_off+1);
 272 
 273         readbuf_off = 0;
 274         readbuf_len = 0;
 275         readbuf = (char *) ADIOI_Malloc(max_bufsize);
 276 
 277         if (buftype_is_contig && !filetype_is_contig) {
 278 
 279 /* contiguous in memory, noncontiguous in file. should be the most
 280    common case. */
 281 
 282             i_offset = 0;
 283             j = st_index;
 284             off = offset;
 285             n_filetypes = st_n_filetypes;
 286             frd_size = ADIOI_MIN(st_frd_size, bufsize);
 287             while (i_offset < bufsize) {
 288                 if (frd_size) { 
 289                     /* TYPE_UB and TYPE_LB can result in 
 290                        frd_size = 0. save system call in such cases */ 
 291                     /* lseek(fd->fd_sys, off, SEEK_SET);
 292                     err = read(fd->fd_sys, ((char *) buf) + i, frd_size);*/
 293 
 294                     req_off = off;
 295                     req_len = frd_size;
 296                     userbuf_off = i_offset;
 297                     ADIOI_BUFFERED_READ
 298                 }
 299                 i_offset += frd_size;
 300 
 301                 if (off + frd_size < disp + flat_file->indices[j] +
 302                    flat_file->blocklens[j] + n_filetypes*(ADIO_Offset)filetype_extent)
 303                        off += frd_size;
 304                 /* did not reach end of contiguous block in filetype.
 305                    no more I/O needed. off is incremented by frd_size. */
 306                 else {
 307                     j = (j+1) % flat_file->count;
 308                     n_filetypes += (j == 0) ? 1 : 0;
 309                     while (flat_file->blocklens[j]==0) {
 310                         j = (j+1) % flat_file->count;
 311                         n_filetypes += (j == 0) ? 1 : 0;
 312                     }
 313                     off = disp + flat_file->indices[j] + 
 314                                         n_filetypes*(ADIO_Offset)filetype_extent;
 315                     frd_size = ADIOI_MIN(flat_file->blocklens[j], bufsize-i_offset);
 316                 }
 317             }
 318         }
 319         else {
 320 /* noncontiguous in memory as well as in file */
 321 
 322             flat_buf = ADIOI_Flatten_and_find(datatype);
 323 
 324             k = num = buf_count = 0;
 325             i_offset = flat_buf->indices[0];
 326             j = st_index;
 327             off = offset;
 328             n_filetypes = st_n_filetypes;
 329             frd_size = st_frd_size;
 330             brd_size = flat_buf->blocklens[0];
 331 
 332             while (num < bufsize) {
 333                 size = ADIOI_MIN(frd_size, brd_size);
 334                 if (size) {
 335                     /* lseek(fd->fd_sys, off, SEEK_SET);
 336                     err = read(fd->fd_sys, ((char *) buf) + i, size); */
 337 
 338                     req_off = off;
 339                     req_len = size;
 340                     userbuf_off = i_offset;
 341                     ADIOI_BUFFERED_READ
 342                 }
 343 
 344                 new_frd_size = frd_size;
 345                 new_brd_size = brd_size;
 346 
 347                 if (size == frd_size) {
 348 /* reached end of contiguous block in file */
 349                     j = (j+1) % flat_file->count;
 350                     n_filetypes += (j == 0) ? 1 : 0;
 351                     while (flat_file->blocklens[j]==0) {
 352                         j = (j+1) % flat_file->count;
 353                         n_filetypes += (j == 0) ? 1 : 0;
 354                     }
 355                     off = disp + flat_file->indices[j] + 
 356           n_filetypes*(ADIO_Offset)filetype_extent;
 357 
 358                     new_frd_size = flat_file->blocklens[j];
 359                     if (size != brd_size) {
 360                         i_offset += size;
 361                         new_brd_size -= size;
 362                     }
 363                 }
 364 
 365                 if (size == brd_size) {
 366 /* reached end of contiguous block in memory */
 367 
 368                     k = (k + 1)%flat_buf->count;
 369                     buf_count++;
 370                     i_offset = ((ADIO_Offset)buftype_extent*(ADIO_Offset)(buf_count/flat_buf->count) +
 371                         flat_buf->indices[k]);
 372                     new_brd_size = flat_buf->blocklens[k];
 373                     if (size != frd_size) {
 374                         off += size;
 375                         new_frd_size -= size;
 376                     }
 377                 }
 378     ADIOI_Assert(((ADIO_Offset)num + size) == (unsigned)(num + size));
 379                 num += size;
 380                 frd_size = new_frd_size;
 381                 brd_size = new_brd_size;
 382             }
 383         }
 384         
 385         if ((fd->atomicity) && ADIO_Feature(fd, ADIO_LOCKS))
 386             ADIOI_UNLOCK(fd, start_off, SEEK_SET, end_offset-start_off+1);
 387 
 388         if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind = off;
 389 
 390         ADIOI_Free(readbuf); /* malloced in the buffered_read macro */
 391     }
 392 
 393     fd->fp_sys_posn = -1;   /* set it to null. */
 394 
 395 #ifdef HAVE_STATUS_SET_BYTES
 396     MPIR_Status_set_bytes(status, datatype, bufsize);
 397 /* This is a temporary way of filling in status. The right way is to 
 398    keep track of how much data was actually read and placed in buf 
 399    by ADIOI_BUFFERED_READ. */
 400 #endif
 401 
 402     if (!buftype_is_contig) ADIOI_Delete_flattened(datatype);
 403 }

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