diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2003-05-07 21:52:24 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2003-05-07 21:52:24 (GMT) |
commit | 43e3b450214310728cbb6904211319a8459f06e4 (patch) | |
tree | 13cc61b9f713aa60fdcaf606665f03189689046d /src/H5Dseq.c | |
parent | db543f1a23194e81d0a984c346398e72bf4be87f (diff) | |
download | hdf5-43e3b450214310728cbb6904211319a8459f06e4.zip hdf5-43e3b450214310728cbb6904211319a8459f06e4.tar.gz hdf5-43e3b450214310728cbb6904211319a8459f06e4.tar.bz2 |
[svn-r6825] Purpose:
New feature/enhancement
Description:
Chunked datasets are handled poorly in several circumstances involving
certain selections and chunks that are too large for the chunk cache and/or
chunks with filters, causing the chunk to be read from disk multiple times.
Solution:
Rearrange raw data I/O infrastructure to handle chunked datasets in a much
more friendly way by creating a selection in memory and on disk for each chunk
in a chunked dataset and performing all of the I/O on that chunk at one time.
There are still some scalability (the current code attempts to
create a selection for all the chunks in the dataset, instead of just the
chunks that are accessed, requiring portions of the istore.c and fillval.c
tests to be commented out) and performance issues, but checking this in will
allow the changes to be tested by a much wider audience while I address the
remaining issues.
Platforms tested:
h5committested, FreeBSD 4.8 (sleipnir) serial & parallel, Linux 2.4 (eirene)
Diffstat (limited to 'src/H5Dseq.c')
-rw-r--r-- | src/H5Dseq.c | 754 |
1 files changed, 149 insertions, 605 deletions
diff --git a/src/H5Dseq.c b/src/H5Dseq.c index 113a8d5..5248b0a 100644 --- a/src/H5Dseq.c +++ b/src/H5Dseq.c @@ -70,22 +70,24 @@ static int interface_initialize_g = 0; */ herr_t H5F_seq_read(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, - H5P_genplist_t *dc_plist, const H5O_efl_t *efl, - const H5S_t *file_space, size_t elmt_size, + H5P_genplist_t *dc_plist, const H5D_storage_t *store, size_t seq_len, hsize_t dset_offset, void *buf/*out*/) { - herr_t ret_value=SUCCEED; /* Return value */ + hsize_t mem_off=0; /* Offset in memory */ + size_t mem_len=seq_len; /* Length in memory */ + size_t mem_curr_seq=0; /* "Current sequence" in memory */ + size_t dset_curr_seq=0; /* "Current sequence" in dataset */ + herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5F_seq_read, FAIL); /* Check args */ assert(f); assert(layout); - assert(efl); assert(buf); assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); - if (H5F_seq_readv(f, dxpl_id, layout, dc_plist, efl, file_space, elmt_size, 1, &seq_len, &dset_offset, buf)<0) + if (H5F_seq_readvv(f, dxpl_id, layout, dc_plist, store, 1, &dset_curr_seq, &seq_len, &dset_offset, 1, &mem_curr_seq, &mem_len, &mem_off, buf)<0) HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "vector read failed"); done: @@ -116,22 +118,24 @@ done: */ herr_t H5F_seq_write(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout, - H5P_genplist_t *dc_plist, const H5O_efl_t *efl, - const H5S_t *file_space, size_t elmt_size, + H5P_genplist_t *dc_plist, const H5D_storage_t *store, size_t seq_len, hsize_t dset_offset, const void *buf) { - herr_t ret_value=SUCCEED; /* Return value */ + hsize_t mem_off=0; /* Offset in memory */ + size_t mem_len=seq_len; /* Length in memory */ + size_t mem_curr_seq=0; /* "Current sequence" in memory */ + size_t dset_curr_seq=0; /* "Current sequence" in dataset */ + herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5F_seq_write, FAIL); /* Check args */ assert(f); assert(layout); - assert(efl); assert(buf); assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); - if (H5F_seq_writev(f, dxpl_id, layout, dc_plist, efl, file_space, elmt_size, 1, &seq_len, &dset_offset, buf)<0) + if (H5F_seq_writevv(f, dxpl_id, layout, dc_plist, store, 1, &dset_curr_seq, &seq_len, &dset_offset, 1, &mem_curr_seq, &mem_len, &mem_off, buf)<0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vector write failed"); done: @@ -140,7 +144,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5F_seq_readv + * Function: H5F_seq_readvv * * Purpose: Reads in a vector of byte sequences from a file dataset into a * buffer in in memory. The data is read from file F and the array's size @@ -152,53 +156,61 @@ done: * Bytes read into BUF are sequentially stored in the buffer, each sequence * from the vector stored directly after the previous. The number of * sequences is NSEQ. + * Purpose: Reads a vector of byte sequences from a vector of byte + * sequences in a file dataset into a buffer in memory. The data is + * read from file F and the array's size and storage information is in + * LAYOUT. External files and chunks are described according to the + * storage information, STORE. The vector of byte sequences offsets for + * the file is in the DSET_OFFSET_ARR array into the dataset (offsets are + * in terms of bytes) and the size of each sequence is in the DSET_LEN_ARR + * array. The vector of byte sequences offsets for memory is in the + * MEM_OFFSET_ARR array into the dataset (offsets are in terms of bytes) + * and the size of each sequence is in the MEM_LEN_ARR array. The total + * size of the file array is implied in the LAYOUT argument. The maximum + * number of sequences in the file dataset and the memory buffer are + * DSET_MAX_NSEQ & MEM_MAX_NSEQ respectively. The current sequence being + * operated on in the file dataset and the memory buffer are DSET_CURR_SEQ + * & MEM_CURR_SEQ respectively. The current sequence being operated on + * will be updated as a result of the operation, as will the offsets and + * lengths of the file dataset and memory buffer sequences. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol - * Wednesday, May 1, 2001 + * Wednesday, May 7, 2003 * * Modifications: * *------------------------------------------------------------------------- */ -herr_t -H5F_seq_readv(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, - H5P_genplist_t *dc_plist, const H5O_efl_t *efl, - const H5S_t *file_space, size_t elmt_size, - size_t nseq, size_t seq_len_arr[], hsize_t dset_offset_arr[], - void *_buf/*out*/) +ssize_t +H5F_seq_readvv(H5F_t *f, hid_t dxpl_id, const struct H5O_layout_t *layout, + struct H5P_genplist_t *dc_plist, const H5D_storage_t *store, + size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[], + size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[], + void *buf/*out*/) { - unsigned char *real_buf=(unsigned char *)_buf; /* Local pointer to buffer to fill */ - unsigned char *buf; /* Local pointer to buffer to fill */ - hsize_t dset_offset; /* Offset in dataset */ - hsize_t seq_len; /* Number of bytes to read */ - hsize_t dset_dims[H5O_LAYOUT_NDIMS]; /* dataspace dimensions */ - hssize_t mem_offset[H5O_LAYOUT_NDIMS]; /* offset of hyperslab in memory buffer */ - hssize_t coords[H5O_LAYOUT_NDIMS]; /* offset of hyperslab in dataspace */ - hsize_t hslab_size[H5O_LAYOUT_NDIMS]; /* hyperslab size in dataspace*/ - hsize_t down_size[H5O_LAYOUT_NDIMS]; /* Cumulative yperslab sizes (in elements) */ - hsize_t acc; /* Accumulator for hyperslab sizes (in elements) */ - int ndims; - hsize_t max_data; /*bytes in dataset */ - haddr_t addr=0; /*address in file */ - unsigned u; /*counters */ - size_t v; /*counters */ - int i,j; /*counters */ #ifdef H5_HAVE_PARALLEL H5FD_mpio_xfer_t xfer_mode=H5FD_MPIO_INDEPENDENT; #endif /* H5_HAVE_PARALLEL */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5F_seq_readv, FAIL); + FUNC_ENTER_NOAPI(H5F_seq_readvv, FAIL); /* Check args */ assert(f); + assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); /* Make certain we have the correct type of property list */ assert(layout); - assert(efl); - assert(real_buf); - /* Make certain we have the correct type of property list */ - assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); + assert(dc_plist); + assert(dset_curr_seq); + assert(*dset_curr_seq<dset_max_nseq); + assert(dset_len_arr); + assert(dset_offset_arr); + assert(mem_curr_seq); + assert(*mem_curr_seq<mem_max_nseq); + assert(mem_len_arr); + assert(mem_offset_arr); + assert(buf); #ifdef H5_HAVE_PARALLEL /* Get the transfer mode for MPIO transfers */ @@ -229,285 +241,52 @@ H5F_seq_readv(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, switch (layout->type) { case H5D_CONTIGUOUS: /* Read directly from file if the dataset is in an external file */ - if (efl->nused>0) { - /* Iterate through the sequence vectors */ - for(v=0; v<nseq; v++) { -#ifdef H5_HAVE_PARALLEL - if (H5FD_MPIO_COLLECTIVE==xfer_mode) { - /* - * Currently supports same number of collective access. Need to - * be changed LATER to combine all reads into one collective MPIO - * call. - */ - unsigned long max, min, temp; - - temp = seq_len_arr[v]; - assert(temp==seq_len_arr[v]); /* verify no overflow */ - MPI_Allreduce(&temp, &max, 1, MPI_UNSIGNED_LONG, MPI_MAX, - H5FD_mpio_communicator(f->shared->lf)); - MPI_Allreduce(&temp, &min, 1, MPI_UNSIGNED_LONG, MPI_MIN, - H5FD_mpio_communicator(f->shared->lf)); -#ifdef AKC - printf("seq_len=%lu, min=%lu, max=%lu\n", temp, min, max); -#endif - if (max != min) - HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, - "collective access with unequal number of blocks not supported yet"); - } -#endif /* H5_HAVE_PARALLEL */ - /* Note: We can't use data sieve buffers for datasets in external files - * because the 'addr' of all external files is set to 0 (above) and - * all datasets in external files would alias to the same set of - * file offsets, totally mixing up the data sieve buffer information. -QAK - */ - H5_CHECK_OVERFLOW(dset_offset_arr[v],hsize_t,haddr_t); - if (H5O_efl_read(f, efl, (haddr_t)dset_offset_arr[v], seq_len_arr[v], real_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "external data read failed"); - - /* Increment offset in buffer */ - real_buf += seq_len_arr[v]; - } /* end for */ + if (store && store->efl.nused>0) { + /* Note: We can't use data sieve buffers for datasets in external files + * because the 'addr' of all external files is set to 0 (above) and + * all datasets in external files would alias to the same set of + * file offsets, totally mixing up the data sieve buffer information. -QAK + */ + if((ret_value=H5O_efl_readvv(&(store->efl), + dset_max_nseq, dset_curr_seq, dset_len_arr, dset_offset_arr, + mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, + buf))<0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "external data read failed"); } else { + hsize_t max_data; /*bytes in dataset */ + unsigned u; /*counters */ + /* Compute the size of the dataset in bytes */ for(u=1, max_data=layout->dim[0]; u<layout->ndims; u++) max_data *= layout->dim[u]; /* Pass along the vector of sequences to read */ - if (H5F_contig_readv(f, max_data, H5FD_MEM_DRAW, layout->addr, nseq, seq_len_arr, dset_offset_arr, dxpl_id, real_buf)<0) + if((ret_value=H5F_contig_readvv(f, max_data, layout->addr, + dset_max_nseq, dset_curr_seq, dset_len_arr, dset_offset_arr, + mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, + dxpl_id, buf))<0) HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); } /* end else */ break; case H5D_CHUNKED: - /* - * This method is unable to access external raw data files - */ - if (efl->nused>0) - HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "chunking and external files are mutually exclusive"); - - /* Compute the file offset coordinates and hyperslab size */ - if((ndims=H5S_get_simple_extent_dims(file_space,dset_dims,NULL))<0) - HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "unable to retrieve dataspace dimensions"); - - /* Build the array of cumulative hyperslab sizes */ - /* (And set the memory offset to zero) */ - for(acc=1, i=(ndims-1); i>=0; i--) { - mem_offset[i]=0; - down_size[i]=acc; - acc*=dset_dims[i]; - } /* end for */ - mem_offset[ndims]=0; - - /* Brute-force, stupid way to implement the vectors, but too complex to do other ways... */ - for(v=0; v<nseq; v++) { - dset_offset=dset_offset_arr[v]; - seq_len=seq_len_arr[v]; - buf=real_buf; - - { - /* Set location in dataset from the dset_offset */ - addr=dset_offset; - - /* Convert the bytes into elements */ - seq_len/=elmt_size; - addr/=elmt_size; - - /* Compute the hyperslab offset from the address given */ - for(i=ndims-1; i>=0; i--) { - coords[i]=addr%dset_dims[i]; - addr/=dset_dims[i]; - } /* end for */ - coords[ndims]=0; /* No offset for element info */ - - /* - * Peel off initial partial hyperslabs until we've got a hyperslab which starts - * at coord[n]==0 for dimensions 1->(ndims-1) (i.e. starting at coordinate - * zero for all dimensions except the slowest changing one - */ - for(i=ndims-1; i>0 && seq_len>=down_size[i]; i--) { - hsize_t partial_size; /* Size of the partial hyperslab in bytes */ - - /* Check if we have a partial hyperslab in this lower dimension */ - if(coords[i]>0) { - /* Reset the partial hyperslab size */ - partial_size=1; - - /* Build the partial hyperslab information */ - for(j=0; j<ndims; j++) { - if(i==j) - hslab_size[j]=MIN(seq_len/down_size[i],dset_dims[i]-coords[i]); - else - if(j>i) - hslab_size[j]=dset_dims[j]; - else - hslab_size[j]=1; - partial_size*=hslab_size[j]; - } /* end for */ - hslab_size[ndims]=elmt_size; /* basic hyperslab size is the element */ - - /* Read in the partial hyperslab */ - if (H5F_istore_read(f, dxpl_id, layout, dc_plist, - hslab_size, mem_offset, coords, hslab_size, - buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "chunked read failed"); - - /* Increment the buffer offset */ - buf=(unsigned char *)buf+(partial_size*elmt_size); - - /* Decrement the length of the sequence to read */ - seq_len-=partial_size; - - /* Correct the coords array */ - coords[i]=0; - coords[i-1]++; - - /* Carry the coord array correction up the array, if the dimension is finished */ - while(i>0 && coords[i-1]==(hssize_t)dset_dims[i-1]) { - i--; - coords[i]=0; - if(i>0) { - coords[i-1]++; - assert(coords[i-1]<=(hssize_t)dset_dims[i-1]); - } /* end if */ - } /* end while */ - } /* end if */ - } /* end for */ - - /* Check if there is more than just a partial hyperslab to read */ - if(seq_len>=down_size[0]) { - hsize_t tmp_seq_len; /* Temp. size of the sequence in elements */ - hsize_t full_size; /* Size of the full hyperslab in bytes */ - - /* Get the sequence length for computing the hyperslab sizes */ - tmp_seq_len=seq_len; - - /* Reset the size of the hyperslab read in */ - full_size=1; - - /* Compute the hyperslab size from the length given */ - for(i=ndims-1; i>=0; i--) { - /* Check if the hyperslab is wider than the width of the dimension */ - if(tmp_seq_len>dset_dims[i]) { - assert(0==coords[i]); - hslab_size[i]=dset_dims[i]; - } /* end if */ - else - hslab_size[i]=tmp_seq_len; - - /* compute the number of elements read in */ - full_size*=hslab_size[i]; - - /* Fold the length into the length in the next highest dimension */ - tmp_seq_len/=dset_dims[i]; - - /* Make certain the hyperslab sizes don't go less than 1 for dimensions less than 0*/ - assert(tmp_seq_len>=1 || i==0); - } /* end for */ - hslab_size[ndims]=elmt_size; /* basic hyperslab size is the element */ - - /* Read the full hyperslab in */ - if (H5F_istore_read(f, dxpl_id, layout, dc_plist, - hslab_size, mem_offset, coords, hslab_size, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "chunked read failed"); - - /* Increment the buffer offset */ - buf=(unsigned char *)buf+(full_size*elmt_size); - - /* Decrement the sequence length left */ - seq_len-=full_size; - - /* Increment coordinate of slowest changing dimension */ - coords[0]+=hslab_size[0]; - - } /* end if */ - - /* - * Peel off final partial hyperslabs until we've finished reading all the data - */ - if(seq_len>0) { - hsize_t partial_size; /* Size of the partial hyperslab in bytes */ - - /* - * Peel off remaining partial hyperslabs, from the next-slowest dimension - * on down to the next-to-fastest changing dimension - */ - for(i=1; i<(ndims-1); i++) { - /* Check if there are enough elements to read in a row in this dimension */ - if(seq_len>=down_size[i]) { - /* Reset the partial hyperslab size */ - partial_size=1; - - /* Build the partial hyperslab information */ - for(j=0; j<ndims; j++) { - if(j<i) - hslab_size[j]=1; - else - if(j==i) - hslab_size[j]=seq_len/down_size[j]; - else - hslab_size[j]=dset_dims[j]; - - partial_size*=hslab_size[j]; - } /* end for */ - hslab_size[ndims]=elmt_size; /* basic hyperslab size is the element */ - - /* Read in the partial hyperslab */ - if (H5F_istore_read(f, dxpl_id, layout, dc_plist, - hslab_size, mem_offset, coords, hslab_size, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "chunked read failed"); - - /* Increment the buffer offset */ - buf=(unsigned char *)buf+(partial_size*elmt_size); - - /* Decrement the length of the sequence to read */ - seq_len-=partial_size; - - /* Correct the coords array */ - coords[i]=hslab_size[i]; - } /* end if */ - } /* end for */ - - /* Handle fastest changing dimension if there are any elements left */ - if(seq_len>0) { - assert(seq_len<dset_dims[ndims-1]); - - /* Reset the partial hyperslab size */ - partial_size=1; - - /* Build the partial hyperslab information */ - for(j=0; j<ndims; j++) { - if(j==(ndims-1)) - hslab_size[j]=seq_len; - else - hslab_size[j]=1; - - partial_size*=hslab_size[j]; - } /* end for */ - hslab_size[ndims]=elmt_size; /* basic hyperslab size is the element */ - - /* Read in the partial hyperslab */ - if (H5F_istore_read(f, dxpl_id, layout, dc_plist, - hslab_size, mem_offset, coords, hslab_size, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "chunked read failed"); - - /* Double-check the amount read in */ - assert(seq_len==partial_size); - } /* end if */ - } /* end if */ - } - /* Increment offset in buffer */ - real_buf += seq_len_arr[v]; - } /* end for */ - + assert(store); + if((ret_value=H5F_istore_readvv(f, dxpl_id, layout, dc_plist, store->chunk_coords, + dset_max_nseq, dset_curr_seq, dset_len_arr, dset_offset_arr, + mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, + buf))<0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "istore read failed"); break; case H5D_COMPACT: - /* Pass along the vector of sequences to read */ - if (H5F_compact_readv(f, layout, nseq, seq_len_arr, dset_offset_arr, dxpl_id, real_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); - + if((ret_value=H5F_compact_readvv(f, layout, + dset_max_nseq, dset_curr_seq, dset_len_arr, dset_offset_arr, + mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, + dxpl_id, buf))<0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "compact read failed"); break; + default: assert("not implemented yet" && 0); HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "unsupported storage layout"); @@ -515,69 +294,67 @@ H5F_seq_readv(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, done: FUNC_LEAVE_NOAPI(ret_value); -} /* H5F_seq_readv() */ +} /* H5F_seq_readvv() */ /*------------------------------------------------------------------------- - * Function: H5F_seq_writev + * Function: H5F_seq_writevv * * Purpose: Writes a vector of byte sequences from a buffer in memory into - * a file dataset. The data is written to file F and the array's size - * and storage information is in LAYOUT. External files are described - * according to the external file list, EFL. The vector of byte sequences - * offsets is in the DSET_OFFSET array into the dataset (offsets are in - * terms of bytes) and the size of each sequence is in the SEQ_LEN array. - * The total size of the file array is implied in the LAYOUT argument. - * Bytes written from BUF are sequentially stored in the buffer, each sequence - * from the vector stored directly after the previous. The number of - * sequences is NSEQ. + * a vector of byte sequences in a file dataset. The data is written to + * file F and the array's size and storage information is in LAYOUT. + * External files and chunks are described according to the storage + * information, STORE. The vector of byte sequences offsets for the file + * is in the DSET_OFFSET_ARR array into the dataset (offsets are in + * terms of bytes) and the size of each sequence is in the DSET_LEN_ARR + * array. The vector of byte sequences offsets for memory is in the + * MEM_OFFSET_ARR array into the dataset (offsets are in terms of bytes) + * and the size of each sequence is in the MEM_LEN_ARR array. The total + * size of the file array is implied in the LAYOUT argument. The maximum + * number of sequences in the file dataset and the memory buffer are + * DSET_MAX_NSEQ & MEM_MAX_NSEQ respectively. The current sequence being + * operated on in the file dataset and the memory buffer are DSET_CURR_SEQ + * & MEM_CURR_SEQ respectively. The current sequence being operated on + * will be updated as a result of the operation, as will the offsets and + * lengths of the file dataset and memory buffer sequences. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol - * Friday, July 6, 2001 + * Friday, May 2, 2003 * * Modifications: * *------------------------------------------------------------------------- */ -herr_t -H5F_seq_writev(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout, - H5P_genplist_t *dc_plist, const H5O_efl_t *efl, - const H5S_t *file_space, size_t elmt_size, - size_t nseq, size_t seq_len_arr[], hsize_t dset_offset_arr[], - const void *_buf) +ssize_t +H5F_seq_writevv(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, + struct H5P_genplist_t *dc_plist, const H5D_storage_t *store, + size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[], + size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[], + const void *buf) { - const unsigned char *real_buf=(const unsigned char *)_buf; /* Local pointer to buffer to fill */ - const unsigned char *buf; /* Local pointer to buffer to fill */ - hsize_t dset_offset; /* Offset in dataset */ - hsize_t seq_len; /* Number of bytes to read */ - hsize_t dset_dims[H5O_LAYOUT_NDIMS]; /* dataspace dimensions */ - hssize_t mem_offset[H5O_LAYOUT_NDIMS]; /* offset of hyperslab in memory buffer */ - hssize_t coords[H5O_LAYOUT_NDIMS]; /* offset of hyperslab in dataspace */ - hsize_t hslab_size[H5O_LAYOUT_NDIMS]; /* hyperslab size in dataspace*/ - hsize_t down_size[H5O_LAYOUT_NDIMS]; /* Cumulative hyperslab sizes (in elements) */ - hsize_t acc; /* Accumulator for hyperslab sizes (in elements) */ - int ndims; - hsize_t max_data; /*bytes in dataset */ - haddr_t addr; /*address in file */ - unsigned u; /*counters */ - size_t v; /*counters */ - int i,j; /*counters */ #ifdef H5_HAVE_PARALLEL H5FD_mpio_xfer_t xfer_mode=H5FD_MPIO_INDEPENDENT; #endif /* H5_HAVE_PARALLEL */ - herr_t ret_value = SUCCEED; /* Return value */ + ssize_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5F_seq_writev, FAIL); + FUNC_ENTER_NOAPI(H5F_seq_writevv, FAIL); /* Check args */ assert(f); + assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); /* Make certain we have the correct type of property list */ assert(layout); - assert(efl); - assert(real_buf); - /* Make certain we have the correct type of property list */ - assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); + assert(dc_plist); + assert(dset_curr_seq); + assert(*dset_curr_seq<dset_max_nseq); + assert(dset_len_arr); + assert(dset_offset_arr); + assert(mem_curr_seq); + assert(*mem_curr_seq<mem_max_nseq); + assert(mem_len_arr); + assert(mem_offset_arr); + assert(buf); #ifdef H5_HAVE_PARALLEL /* Get the transfer mode for MPIO transfers */ @@ -608,282 +385,50 @@ H5F_seq_writev(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout, switch (layout->type) { case H5D_CONTIGUOUS: /* Write directly to file if the dataset is in an external file */ - if (efl->nused>0) { - /* Iterate through the sequence vectors */ - for(v=0; v<nseq; v++) { -#ifdef H5_HAVE_PARALLEL - if (H5FD_MPIO_COLLECTIVE==xfer_mode) { - /* - * Currently supports same number of collective access. Need to - * be changed LATER to combine all reads into one collective MPIO - * call. - */ - unsigned long max, min, temp; - - temp = seq_len_arr[v]; - assert(temp==seq_len_arr[v]); /* verify no overflow */ - MPI_Allreduce(&temp, &max, 1, MPI_UNSIGNED_LONG, MPI_MAX, - H5FD_mpio_communicator(f->shared->lf)); - MPI_Allreduce(&temp, &min, 1, MPI_UNSIGNED_LONG, MPI_MIN, - H5FD_mpio_communicator(f->shared->lf)); -#ifdef AKC - printf("seq_len=%lu, min=%lu, max=%lu\n", temp, min, max); -#endif - if (max != min) - HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "collective access with unequal number of blocks not supported yet"); - } -#endif /* H5_HAVE_PARALLEL */ - /* Note: We can't use data sieve buffers for datasets in external files - * because the 'addr' of all external files is set to 0 (above) and - * all datasets in external files would alias to the same set of - * file offsets, totally mixing up the data sieve buffer information. -QAK - */ - H5_CHECK_OVERFLOW(dset_offset_arr[v],hsize_t,haddr_t); - if (H5O_efl_write(f, efl, (haddr_t)dset_offset_arr[v], seq_len_arr[v], real_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "external data write failed"); - - /* Increment offset in buffer */ - real_buf += seq_len_arr[v]; - } /* end for */ + if (store && store->efl.nused>0) { + /* Note: We can't use data sieve buffers for datasets in external files + * because the 'addr' of all external files is set to 0 (above) and + * all datasets in external files would alias to the same set of + * file offsets, totally mixing up the data sieve buffer information. -QAK + */ + if ((ret_value=H5O_efl_writevv(&(store->efl), + dset_max_nseq, dset_curr_seq, dset_len_arr, dset_offset_arr, + mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, + buf))<0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "external data write failed"); } else { + hsize_t max_data; /* Bytes in dataset */ + unsigned u; /* Local index variable */ + /* Compute the size of the dataset in bytes */ for(u=1, max_data=layout->dim[0]; u<layout->ndims; u++) max_data *= layout->dim[u]; /* Pass along the vector of sequences to write */ - if (H5F_contig_writev(f, max_data, H5FD_MEM_DRAW, layout->addr, nseq, seq_len_arr, dset_offset_arr, dxpl_id, real_buf)<0) + if ((ret_value=H5F_contig_writevv(f, max_data, layout->addr, + dset_max_nseq, dset_curr_seq, dset_len_arr, dset_offset_arr, + mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, + dxpl_id, buf))<0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); } /* end else */ break; case H5D_CHUNKED: - /* - * This method is unable to access external raw data files - */ - if (efl->nused>0) - HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "chunking and external files are mutually exclusive"); - - /* Compute the file offset coordinates and hyperslab size */ - if((ndims=H5S_get_simple_extent_dims(file_space,dset_dims,NULL))<0) - HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "unable to retrieve dataspace dimensions"); - - /* Build the array of cumulative hyperslab sizes */ - /* (And set the memory offset to zero) */ - for(acc=1, i=(ndims-1); i>=0; i--) { - mem_offset[i]=0; - down_size[i]=acc; - acc*=dset_dims[i]; - } /* end for */ - mem_offset[ndims]=0; - - /* Brute-force, stupid way to implement the vectors, but too complex to do other ways... */ - for(v=0; v<nseq; v++) { - dset_offset=dset_offset_arr[v]; - seq_len=seq_len_arr[v]; - buf=real_buf; - - { - /* Set location in dataset from the dset_offset */ - addr=dset_offset; - - /* Convert the bytes into elements */ - seq_len/=elmt_size; - addr/=elmt_size; - - /* Compute the hyperslab offset from the address given */ - for(i=ndims-1; i>=0; i--) { - coords[i]=addr%dset_dims[i]; - addr/=dset_dims[i]; - } /* end for */ - coords[ndims]=0; /* No offset for element info */ - - /* - * Peel off initial partial hyperslabs until we've got a hyperslab which starts - * at coord[n]==0 for dimensions 1->(ndims-1) (i.e. starting at coordinate - * zero for all dimensions except the slowest changing one - */ - for(i=ndims-1; i>0 && seq_len>=down_size[i]; i--) { - hsize_t partial_size; /* Size of the partial hyperslab in bytes */ - - /* Check if we have a partial hyperslab in this lower dimension */ - if(coords[i]>0) { - /* Reset the partial hyperslab size */ - partial_size=1; - - /* Build the partial hyperslab information */ - for(j=0; j<ndims; j++) { - if(i==j) - hslab_size[j]=MIN(seq_len/down_size[i],dset_dims[i]-coords[i]); - else - if(j>i) - hslab_size[j]=dset_dims[j]; - else - hslab_size[j]=1; - partial_size*=hslab_size[j]; - } /* end for */ - hslab_size[ndims]=elmt_size; /* basic hyperslab size is the element */ - - /* Write out the partial hyperslab */ - if (H5F_istore_write(f, dxpl_id, layout, dc_plist, - hslab_size, mem_offset,coords, hslab_size, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "chunked write failed"); - - /* Increment the buffer offset */ - buf=(const unsigned char *)buf+(partial_size*elmt_size); - - /* Decrement the length of the sequence to read */ - seq_len-=partial_size; - - /* Correct the coords array */ - coords[i]=0; - coords[i-1]++; - - /* Carry the coord array correction up the array, if the dimension is finished */ - while(i>0 && coords[i-1]==(hssize_t)dset_dims[i-1]) { - i--; - coords[i]=0; - if(i>0) { - coords[i-1]++; - assert(coords[i-1]<=(hssize_t)dset_dims[i-1]); - } /* end if */ - } /* end while */ - } /* end if */ - } /* end for */ - - /* Check if there is more than just a partial hyperslab to read */ - if(seq_len>=down_size[0]) { - hsize_t tmp_seq_len; /* Temp. size of the sequence in elements */ - hsize_t full_size; /* Size of the full hyperslab in bytes */ - - /* Get the sequence length for computing the hyperslab sizes */ - tmp_seq_len=seq_len; - - /* Reset the size of the hyperslab read in */ - full_size=1; - - /* Compute the hyperslab size from the length given */ - for(i=ndims-1; i>=0; i--) { - /* Check if the hyperslab is wider than the width of the dimension */ - if(tmp_seq_len>dset_dims[i]) { - assert(0==coords[i]); - hslab_size[i]=dset_dims[i]; - } /* end if */ - else - hslab_size[i]=tmp_seq_len; - - /* compute the number of elements read in */ - full_size*=hslab_size[i]; - - /* Fold the length into the length in the next highest dimension */ - tmp_seq_len/=dset_dims[i]; - - /* Make certain the hyperslab sizes don't go less than 1 for dimensions less than 0*/ - assert(tmp_seq_len>=1 || i==0); - } /* end for */ - hslab_size[ndims]=elmt_size; /* basic hyperslab size is the element */ - - /* Write the full hyperslab in */ - if (H5F_istore_write(f, dxpl_id, layout, dc_plist, - hslab_size, mem_offset, coords, hslab_size, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "chunked write failed"); - - /* Increment the buffer offset */ - buf=(const unsigned char *)buf+(full_size*elmt_size); - - /* Decrement the sequence length left */ - seq_len-=full_size; - - /* Increment coordinate of slowest changing dimension */ - coords[0]+=hslab_size[0]; - - } /* end if */ - - /* - * Peel off final partial hyperslabs until we've finished reading all the data - */ - if(seq_len>0) { - hsize_t partial_size; /* Size of the partial hyperslab in bytes */ - - /* - * Peel off remaining partial hyperslabs, from the next-slowest dimension - * on down to the next-to-fastest changing dimension - */ - for(i=1; i<(ndims-1); i++) { - /* Check if there are enough elements to read in a row in this dimension */ - if(seq_len>=down_size[i]) { - /* Reset the partial hyperslab size */ - partial_size=1; - - /* Build the partial hyperslab information */ - for(j=0; j<ndims; j++) { - if(j<i) - hslab_size[j]=1; - else - if(j==i) - hslab_size[j]=seq_len/down_size[j]; - else - hslab_size[j]=dset_dims[j]; - - partial_size*=hslab_size[j]; - } /* end for */ - hslab_size[ndims]=elmt_size; /* basic hyperslab size is the element */ - - /* Write out the partial hyperslab */ - if (H5F_istore_write(f, dxpl_id, layout, dc_plist, - hslab_size, mem_offset, coords, hslab_size, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "chunked write failed"); - - /* Increment the buffer offset */ - buf=(const unsigned char *)buf+(partial_size*elmt_size); - - /* Decrement the length of the sequence to read */ - seq_len-=partial_size; - - /* Correct the coords array */ - coords[i]=hslab_size[i]; - } /* end if */ - } /* end for */ - - /* Handle fastest changing dimension if there are any elements left */ - if(seq_len>0) { - assert(seq_len<dset_dims[ndims-1]); - - /* Reset the partial hyperslab size */ - partial_size=1; - - /* Build the partial hyperslab information */ - for(j=0; j<ndims; j++) { - if(j==(ndims-1)) - hslab_size[j]=seq_len; - else - hslab_size[j]=1; - - partial_size*=hslab_size[j]; - } /* end for */ - hslab_size[ndims]=elmt_size; /* basic hyperslab size is the element */ - - /* Write out the final partial hyperslab */ - if (H5F_istore_write(f, dxpl_id, layout, dc_plist, - hslab_size, mem_offset, coords, hslab_size, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "chunked write failed"); - - /* Double-check the amount read in */ - assert(seq_len==partial_size); - } /* end if */ - } /* end if */ - } - /* Increment offset in buffer */ - real_buf += seq_len_arr[v]; - } /* end for */ - + assert(store); + if((ret_value=H5F_istore_writevv(f, dxpl_id, layout, dc_plist, store->chunk_coords, + dset_max_nseq, dset_curr_seq, dset_len_arr, dset_offset_arr, + mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, + buf))<0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "istore write failed"); break; case H5D_COMPACT: - /* Pass along the vector of sequences to write */ - if (H5F_compact_writev(f, layout, nseq, seq_len_arr, dset_offset_arr, dxpl_id, real_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); - + if((ret_value=H5F_compact_writevv(f, layout, + dset_max_nseq, dset_curr_seq, dset_len_arr, dset_offset_arr, + mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, + dxpl_id, buf))<0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "compact write failed"); break; default: @@ -893,5 +438,4 @@ H5F_seq_writev(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout, done: FUNC_LEAVE_NOAPI(ret_value); -} /* H5F_seq_writev() */ - +} /* H5F_seq_writevv() */ |