00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 #include "adio.h"
00009 #include "adio_extern.h"
00010 
00011 #define ADIOI_BUFFERED_READ \
00012 { \
00013     if (req_off >= readbuf_off + readbuf_len) { \
00014     readbuf_off = req_off; \
00015     readbuf_len = (unsigned) (ADIOI_MIN(max_bufsize, end_offset-readbuf_off+1));\
00016     ADIO_ReadContig(fd, readbuf, readbuf_len, MPI_BYTE, \
00017               ADIO_EXPLICIT_OFFSET, readbuf_off, &status1, error_code); \
00018         if (*error_code != MPI_SUCCESS) return; \
00019     } \
00020     while (req_len > readbuf_off + readbuf_len - req_off) { \
00021   ADIOI_Assert((readbuf_off + readbuf_len - req_off) == (int) (readbuf_off + readbuf_len - req_off));\
00022     partial_read = (int) (readbuf_off + readbuf_len - req_off); \
00023     tmp_buf = (char *) ADIOI_Malloc(partial_read); \
00024     memcpy(tmp_buf, readbuf+readbuf_len-partial_read, partial_read); \
00025     ADIOI_Free(readbuf); \
00026     readbuf = (char *) ADIOI_Malloc(partial_read + max_bufsize); \
00027     memcpy(readbuf, tmp_buf, partial_read); \
00028     ADIOI_Free(tmp_buf); \
00029     readbuf_off += readbuf_len-partial_read; \
00030     readbuf_len = (unsigned) (partial_read + ADIOI_MIN(max_bufsize, \
00031                        end_offset-readbuf_off+1)); \
00032     ADIO_ReadContig(fd, readbuf+partial_read, readbuf_len-partial_read, \
00033              MPI_BYTE, ADIO_EXPLICIT_OFFSET, readbuf_off+partial_read, \
00034              &status1, error_code); \
00035         if (*error_code != MPI_SUCCESS) return; \
00036     } \
00037     ADIOI_Assert(req_len == (size_t)req_len); \
00038     memcpy((char *)buf + userbuf_off, readbuf+req_off-readbuf_off, req_len); \
00039 }
00040 
00041 
00042 void ADIOI_GEN_ReadStrided(ADIO_File fd, void *buf, int count,
00043                        MPI_Datatype datatype, int file_ptr_type,
00044                        ADIO_Offset offset, ADIO_Status *status, int
00045                        *error_code)
00046 {
00047 
00048 
00049 
00050 
00051     ADIOI_Flatlist_node *flat_buf, *flat_file;
00052     ADIO_Offset i_offset, new_brd_size, brd_size, size;
00053     int i, j, k, st_index=0;
00054     unsigned num, bufsize; 
00055     int n_etypes_in_filetype;
00056     ADIO_Offset n_filetypes, etype_in_filetype, st_n_filetypes, size_in_filetype;
00057     ADIO_Offset abs_off_in_filetype=0, new_frd_size, frd_size=0, st_frd_size;
00058     int filetype_size, etype_size, buftype_size, partial_read;
00059     MPI_Aint filetype_extent, buftype_extent; 
00060     int buf_count, buftype_is_contig, filetype_is_contig;
00061     ADIO_Offset userbuf_off, req_len, sum;
00062     ADIO_Offset off, req_off, disp, end_offset=0, readbuf_off, start_off;
00063     char *readbuf, *tmp_buf, *value;
00064     int info_flag;
00065     unsigned max_bufsize, readbuf_len;
00066     ADIO_Status status1;
00067 
00068     if (fd->hints->ds_read == ADIOI_HINT_DISABLE) {
00069         
00070 
00071 
00072     ADIOI_GEN_ReadStrided_naive(fd, 
00073                     buf,
00074                     count,
00075                     datatype,
00076                     file_ptr_type,
00077                     offset,
00078                     status,
00079                     error_code);
00080         return;
00081     }
00082 
00083     *error_code = MPI_SUCCESS;  
00084 
00085     ADIOI_Datatype_iscontig(datatype, &buftype_is_contig);
00086     ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig);
00087 
00088     MPI_Type_size(fd->filetype, &filetype_size);
00089     if ( ! filetype_size ) {
00090     *error_code = MPI_SUCCESS; 
00091     return;
00092     }
00093 
00094     MPI_Type_extent(fd->filetype, &filetype_extent);
00095     MPI_Type_size(datatype, &buftype_size);
00096     MPI_Type_extent(datatype, &buftype_extent);
00097     etype_size = fd->etype_size;
00098 
00099     ADIOI_Assert((buftype_size * count) == ((ADIO_Offset)(unsigned)buftype_size * (ADIO_Offset)count));
00100     bufsize = buftype_size * count;
00101 
00102 
00103 
00104     value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char));
00105     ADIOI_Info_get(fd->info, "ind_rd_buffer_size", MPI_MAX_INFO_VAL, value, 
00106                  &info_flag);
00107     max_bufsize = atoi(value);
00108     ADIOI_Free(value);
00109 
00110 
00111     if (!buftype_is_contig && filetype_is_contig) {
00112 
00113 
00114 
00115     ADIOI_Flatten_datatype(datatype);
00116     flat_buf = CtvAccess(ADIOI_Flatlist);
00117     while (flat_buf->type != datatype) flat_buf = flat_buf->next;
00118 
00119         off = (file_ptr_type == ADIO_INDIVIDUAL) ? fd->fp_ind : 
00120                  fd->disp + (ADIO_Offset)etype_size * offset;
00121 
00122     start_off = off;
00123     end_offset = off + bufsize - 1;
00124         readbuf_off = off;
00125         readbuf = (char *) ADIOI_Malloc(max_bufsize);
00126         readbuf_len = (unsigned) (ADIOI_MIN(max_bufsize, end_offset-readbuf_off+1));
00127 
00128 
00129         if ((fd->atomicity) && ADIO_Feature(fd, ADIO_LOCKS))
00130             ADIOI_WRITE_LOCK(fd, start_off, SEEK_SET, end_offset-start_off+1);
00131 
00132         ADIO_ReadContig(fd, readbuf, readbuf_len, MPI_BYTE, 
00133             ADIO_EXPLICIT_OFFSET, readbuf_off, &status1, error_code);
00134     if (*error_code != MPI_SUCCESS) return;
00135 
00136         for (j=0; j<count; j++) 
00137         {
00138               for (i=0; i<flat_buf->count; i++) {
00139                   userbuf_off = (ADIO_Offset)j*(ADIO_Offset)buftype_extent + flat_buf->indices[i];
00140       req_off = off;
00141       req_len = flat_buf->blocklens[i];
00142       ADIOI_BUFFERED_READ
00143                   off += flat_buf->blocklens[i];
00144               }
00145         }
00146 
00147         if ((fd->atomicity) && ADIO_Feature(fd, ADIO_LOCKS))
00148             ADIOI_UNLOCK(fd, start_off, SEEK_SET, end_offset-start_off+1);
00149 
00150         if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind = off;
00151 
00152     ADIOI_Free(readbuf); 
00153     }
00154 
00155     else {  
00156 
00157 
00158     flat_file = CtvAccess(ADIOI_Flatlist);
00159     while (flat_file->type != fd->filetype) flat_file = flat_file->next;
00160     disp = fd->disp;
00161 
00162     if (file_ptr_type == ADIO_INDIVIDUAL) {
00163         
00164             offset       = fd->fp_ind - disp;
00165             n_filetypes  = (offset - flat_file->indices[0]) / filetype_extent;
00166         offset -= (ADIO_Offset)n_filetypes * filetype_extent;
00167         
00168 
00169             
00170             for (i=0; i<flat_file->count; i++) {
00171                 ADIO_Offset dist;
00172                 if (flat_file->blocklens[i] == 0) continue;
00173                 dist = flat_file->indices[i] + flat_file->blocklens[i] - offset;
00174                 
00175         if (dist == 0) {
00176             i++;
00177             offset   = flat_file->indices[i];
00178             frd_size = flat_file->blocklens[i];
00179             break;
00180         }
00181         if (dist > 0) {
00182                     frd_size = dist;
00183             break;
00184         }
00185         }
00186             st_index = i;  
00187             offset += disp + (ADIO_Offset)n_filetypes*filetype_extent;
00188         }
00189     else {
00190         n_etypes_in_filetype = filetype_size/etype_size;
00191         n_filetypes = offset / n_etypes_in_filetype;
00192         etype_in_filetype = offset % n_etypes_in_filetype;
00193         size_in_filetype = etype_in_filetype * etype_size;
00194  
00195         sum = 0;
00196         for (i=0; i<flat_file->count; i++) {
00197         sum += flat_file->blocklens[i];
00198         if (sum > size_in_filetype) {
00199             st_index = i;
00200             frd_size = sum - size_in_filetype;
00201             abs_off_in_filetype = flat_file->indices[i] +
00202             size_in_filetype - (sum - flat_file->blocklens[i]);
00203             break;
00204         }
00205         }
00206 
00207         
00208         offset = disp + (ADIO_Offset) n_filetypes*filetype_extent + 
00209             abs_off_in_filetype;
00210     }
00211 
00212         start_off = offset;
00213 
00214     
00215 
00216 
00217     if (buftype_is_contig && bufsize <= frd_size) {
00218             ADIO_ReadContig(fd, buf, bufsize, MPI_BYTE, ADIO_EXPLICIT_OFFSET,
00219                              offset, status, error_code);
00220 
00221         if (file_ptr_type == ADIO_INDIVIDUAL) {
00222                 
00223 
00224         fd->fp_ind = offset + bufsize;
00225         if (bufsize == frd_size) {
00226             do {
00227             st_index++;
00228             if (st_index == flat_file->count) {
00229                 st_index = 0;
00230                 n_filetypes++;
00231             }
00232                     } while (flat_file->blocklens[st_index] == 0);
00233             fd->fp_ind = disp + flat_file->indices[st_index]
00234                                + n_filetypes*filetype_extent;
00235         }
00236         }
00237         fd->fp_sys_posn = -1;    
00238 #ifdef HAVE_STATUS_SET_BYTES
00239         MPIR_Status_set_bytes(status, datatype, bufsize);
00240 #endif 
00241             return;
00242     }
00243 
00244        
00245 
00246 
00247     st_frd_size = frd_size;
00248     st_n_filetypes = n_filetypes;
00249     i_offset = 0;
00250     j = st_index;
00251     off = offset;
00252     frd_size = ADIOI_MIN(st_frd_size, bufsize);
00253     while (i_offset < bufsize) {
00254         i_offset += frd_size;
00255         end_offset = off + frd_size - 1;
00256 
00257         j = (j+1) % flat_file->count;
00258             n_filetypes += (j == 0) ? 1 : 0;
00259             while (flat_file->blocklens[j]==0) {
00260         j = (j+1) % flat_file->count;
00261         n_filetypes += (j == 0) ? 1 : 0;
00262         }
00263         off = disp + flat_file->indices[j] + n_filetypes*(ADIO_Offset)filetype_extent;
00264         frd_size = ADIOI_MIN(flat_file->blocklens[j], bufsize-i_offset);
00265     }
00266 
00267 
00268         if ((fd->atomicity) && ADIO_Feature(fd, ADIO_LOCKS))
00269             ADIOI_WRITE_LOCK(fd, start_off, SEEK_SET, end_offset-start_off+1);
00270 
00271     readbuf_off = 0;
00272     readbuf_len = 0;
00273     readbuf = (char *) ADIOI_Malloc(max_bufsize);
00274 
00275     if (buftype_is_contig && !filetype_is_contig) {
00276 
00277 
00278 
00279 
00280         i_offset = 0;
00281         j = st_index;
00282         off = offset;
00283         n_filetypes = st_n_filetypes;
00284         frd_size = ADIOI_MIN(st_frd_size, bufsize);
00285         while (i_offset < bufsize) {
00286                 if (frd_size) { 
00287                     
00288  
00289             
00290 
00291 
00292             req_off = off;
00293             req_len = frd_size;
00294             userbuf_off = i_offset;
00295             ADIOI_BUFFERED_READ
00296         }
00297         i_offset += frd_size;
00298 
00299                 if (off + frd_size < disp + flat_file->indices[j] +
00300                    flat_file->blocklens[j] + n_filetypes*(ADIO_Offset)filetype_extent)
00301                        off += frd_size;
00302                 
00303 
00304                 else {
00305                     j = (j+1) % flat_file->count;
00306                     n_filetypes += (j == 0) ? 1 : 0;
00307                     while (flat_file->blocklens[j]==0) {
00308                         j = (j+1) % flat_file->count;
00309                         n_filetypes += (j == 0) ? 1 : 0;
00310                     }
00311             off = disp + flat_file->indices[j] + 
00312                                         n_filetypes*(ADIO_Offset)filetype_extent;
00313             frd_size = ADIOI_MIN(flat_file->blocklens[j], bufsize-i_offset);
00314         }
00315         }
00316     }
00317     else {
00318 
00319 
00320         ADIOI_Flatten_datatype(datatype);
00321         flat_buf = CtvAccess(ADIOI_Flatlist);
00322         while (flat_buf->type != datatype) flat_buf = flat_buf->next;
00323 
00324         k = num = buf_count = 0;
00325         i_offset = flat_buf->indices[0];
00326         j = st_index;
00327         off = offset;
00328         n_filetypes = st_n_filetypes;
00329         frd_size = st_frd_size;
00330         brd_size = flat_buf->blocklens[0];
00331 
00332         while (num < bufsize) {
00333         size = ADIOI_MIN(frd_size, brd_size);
00334         if (size) {
00335             
00336 
00337 
00338             req_off = off;
00339             req_len = size;
00340             userbuf_off = i_offset;
00341             ADIOI_BUFFERED_READ
00342         }
00343 
00344         new_frd_size = frd_size;
00345         new_brd_size = brd_size;
00346 
00347         if (size == frd_size) {
00348 
00349                     j = (j+1) % flat_file->count;
00350                     n_filetypes += (j == 0) ? 1 : 0;
00351                     while (flat_file->blocklens[j]==0) {
00352                         j = (j+1) % flat_file->count;
00353                         n_filetypes += (j == 0) ? 1 : 0;
00354                     }
00355             off = disp + flat_file->indices[j] + 
00356           n_filetypes*(ADIO_Offset)filetype_extent;
00357 
00358             new_frd_size = flat_file->blocklens[j];
00359             if (size != brd_size) {
00360             i_offset += size;
00361             new_brd_size -= size;
00362             }
00363         }
00364 
00365         if (size == brd_size) {
00366 
00367 
00368             k = (k + 1)%flat_buf->count;
00369             buf_count++;
00370             i_offset = ((ADIO_Offset)buftype_extent*(ADIO_Offset)(buf_count/flat_buf->count) +
00371             flat_buf->indices[k]);
00372             new_brd_size = flat_buf->blocklens[k];
00373             if (size != frd_size) {
00374             off += size;
00375             new_frd_size -= size;
00376             }
00377         }
00378     ADIOI_Assert(((ADIO_Offset)num + size) == (unsigned)(num + size));
00379         num += size;
00380         frd_size = new_frd_size;
00381                 brd_size = new_brd_size;
00382         }
00383     }
00384     
00385         if ((fd->atomicity) && ADIO_Feature(fd, ADIO_LOCKS))
00386             ADIOI_UNLOCK(fd, start_off, SEEK_SET, end_offset-start_off+1);
00387 
00388     if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind = off;
00389 
00390     ADIOI_Free(readbuf); 
00391     }
00392 
00393     fd->fp_sys_posn = -1;   
00394 
00395 #ifdef HAVE_STATUS_SET_BYTES
00396     MPIR_Status_set_bytes(status, datatype, bufsize);
00397 
00398 
00399 
00400 #endif
00401 
00402     if (!buftype_is_contig) ADIOI_Delete_flattened(datatype);
00403 }