summaryrefslogtreecommitdiffstats
path: root/src/H5Dcontig.c
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2003-05-07 21:52:24 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2003-05-07 21:52:24 (GMT)
commit43e3b450214310728cbb6904211319a8459f06e4 (patch)
tree13cc61b9f713aa60fdcaf606665f03189689046d /src/H5Dcontig.c
parentdb543f1a23194e81d0a984c346398e72bf4be87f (diff)
downloadhdf5-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/H5Dcontig.c')
-rw-r--r--src/H5Dcontig.c1271
1 files changed, 497 insertions, 774 deletions
diff --git a/src/H5Dcontig.c b/src/H5Dcontig.c
index 2593d83..3a14175 100644
--- a/src/H5Dcontig.c
+++ b/src/H5Dcontig.c
@@ -18,9 +18,8 @@
*
* Purpose:
* Contiguous dataset I/O functions. These routines are similar to
- * the H5F_istore_* routines and really only abstract away dealing
- * with the data sieve buffer from the H5F_arr_read/write and
- * H5F_seg_read/write.
+ * the H5F_istore_* routines and really only an abstract way of dealing
+ * with the data sieve buffer from H5F_seg_read/write.
*/
#define H5F_PACKAGE /*suppress error about including H5Fpkg */
@@ -34,6 +33,7 @@
#include "H5MFprivate.h" /*file memory management */
#include "H5Oprivate.h" /* Object headers */
#include "H5Pprivate.h" /* Property lists */
+#include "H5Sprivate.h" /* Dataspace functions */
#include "H5Vprivate.h" /* Vector and array functions */
/* MPIO, MPIPOSIX, & FPHDF5 drivers needed for special checks */
@@ -41,6 +41,11 @@
#include "H5FDmpio.h"
#include "H5FDmpiposix.h"
+/* Private prototypes */
+static herr_t
+H5F_contig_write(H5F_t *f, hsize_t max_data, haddr_t addr,
+ const size_t size, hid_t dxpl_id, const void *buf);
+
/* Interface initialization */
#define PABLO_MASK H5Fcontig_mask
static int interface_initialize_g = 0;
@@ -57,6 +62,48 @@ H5FL_BLK_DEFINE_STATIC(zero_fill);
/*-------------------------------------------------------------------------
+ * Function: H5F_contig_create
+ *
+ * Purpose: Allocate file space for a contiguously stored dataset
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * April 19, 2003
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_contig_create(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout)
+{
+ hsize_t size; /* Size of contiguous block of data */
+ unsigned u; /* Local index variable */
+ herr_t ret_value=SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5O_contig_create, FAIL);
+
+ /* check args */
+ assert(f);
+ assert(layout);
+
+ /* Compute size */
+ size=layout->dim[0];
+ for (u = 1; u < layout->ndims; u++)
+ size *= layout->dim[u];
+ assert (size>0);
+
+ /* Allocate space for the contiguous data */
+ if (HADDR_UNDEF==(layout->addr=H5MF_alloc(f, H5FD_MEM_DRAW, dxpl_id, size)))
+ HGOTO_ERROR (H5E_IO, H5E_NOSPACE, FAIL, "unable to reserve file space");
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5F_contig_create */
+
+
+/*-------------------------------------------------------------------------
* Function: H5F_contig_fill
*
* Purpose: Write fill values to a contiguously stored dataset.
@@ -75,8 +122,7 @@ H5FL_BLK_DEFINE_STATIC(zero_fill);
*/
herr_t
H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout,
- struct H5P_genplist_t *dc_plist, const struct H5O_efl_t *efl,
- const struct H5S_t *space,
+ struct H5P_genplist_t *dc_plist, const struct H5S_t *space,
const struct H5O_fill_t *fill, size_t elmt_size)
{
hssize_t snpoints; /* Number of points in space (for error checking) */
@@ -84,7 +130,7 @@ H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout,
size_t ptsperbuf; /* Maximum # of points which fit in the buffer */
size_t bufsize=64*1024; /* Size of buffer to write */
size_t size; /* Current # of points to write */
- hsize_t addr; /* Offset in dataset */
+ haddr_t addr; /* Offset of dataset */
void *buf = NULL; /* Buffer for fill value writing */
#ifdef H5_HAVE_PARALLEL
MPI_Comm mpi_comm=MPI_COMM_NULL; /* MPI communicator for file */
@@ -173,8 +219,8 @@ H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout,
* this quite efficiently by making sure we copy the fill value
* in relatively large pieces.
*/
- ptsperbuf = MAX(1, bufsize/elmt_size);
- bufsize = ptsperbuf*elmt_size;
+ ptsperbuf = MAX(1, bufsize/elmt_size);
+ bufsize = ptsperbuf*elmt_size;
/* Fill the buffer with the user's fill value */
if(fill->buf) {
@@ -207,7 +253,7 @@ H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout,
} /* end else */
/* Start at the beginning of the dataset */
- addr = 0;
+ addr = layout->addr;
/* Loop through writing the fill value to the dataset */
while (npoints>0) {
@@ -218,8 +264,7 @@ H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout,
if(using_mpi) {
/* Round-robin write the chunks out from only one process */
if(mpi_round==mpi_rank) {
- if (H5F_seq_write(f, dxpl_id, layout, dc_plist, efl, space,
- elmt_size, size, addr, buf)<0)
+ if (H5F_contig_write(f, size, addr, size, dxpl_id, buf)<0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to write fill value to dataset");
} /* end if */
++mpi_round;
@@ -230,8 +275,8 @@ H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout,
} /* end if */
else {
#endif /* H5_HAVE_PARALLEL */
- if (H5F_seq_write(f, dxpl_id, layout, dc_plist, efl, space,
- elmt_size, size, addr, buf)<0)
+ H5_CHECK_OVERFLOW(size,size_t,hsize_t);
+ if (H5F_contig_write(f, (hsize_t)size, addr, size, dxpl_id, buf)<0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to write fill value to dataset");
#ifdef H5_HAVE_PARALLEL
} /* end else */
@@ -314,44 +359,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5F_contig_read
- *
- * Purpose: Reads some data from a dataset into a buffer.
- * The data is contiguous. The address is relative to the base
- * address for the file.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Thursday, September 28, 2000
- *
- * Modifications:
- * Re-written in terms of the new readv call, QAK, 7/7/01
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5F_contig_read(H5F_t *f, hsize_t max_data, H5FD_mem_t type, haddr_t addr,
- size_t size, hid_t dxpl_id, void *buf/*out*/)
-{
- hsize_t offset=0; /* Offset for vector call */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5F_contig_read, FAIL);
-
- /* Check args */
- assert(f);
- assert(buf);
-
- if (H5F_contig_readv(f, max_data, type, addr, 1, &size, &offset, dxpl_id, buf)<0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "vector read failed");
-
-done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5F_contig_read() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5F_contig_write
*
* Purpose: Writes some data from a dataset into a buffer.
@@ -364,23 +371,28 @@ done:
* Thursday, September 28, 2000
*
* Modifications:
- * Re-written in terms of the new readv call, QAK, 7/7/01
+ * Re-written in terms of the new writevv call, QAK, 5/7/03
*
*-------------------------------------------------------------------------
*/
-herr_t
-H5F_contig_write(H5F_t *f, hsize_t max_data, H5FD_mem_t type, haddr_t addr, size_t size,
- hid_t dxpl_id, const void *buf)
+static herr_t
+H5F_contig_write(H5F_t *f, hsize_t max_data, haddr_t addr,
+ const size_t size, hid_t dxpl_id, const void *buf)
{
- hsize_t offset=0; /* Offset for vector call */
- herr_t ret_value=SUCCEED; /* Return value */
+ hsize_t dset_off=0; /* Offset in dataset */
+ hsize_t mem_off=0; /* Offset in memory */
+ size_t dset_len=size; /* Length in dataset */
+ size_t mem_len=size; /* 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_contig_write, FAIL);
assert (f);
assert (buf);
- if (H5F_contig_writev(f, max_data, type, addr, 1, &size, &offset, dxpl_id, buf)<0)
+ if (H5F_contig_writevv(f, max_data, addr, 1, &dset_curr_seq, &dset_len, &dset_off, 1, &mem_curr_seq, &mem_len, &mem_off, dxpl_id, buf)<0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vector write failed");
done:
@@ -389,7 +401,7 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5F_contig_readv
+ * Function: H5F_contig_readvv
*
* Purpose: Reads some data vectors from a dataset into a buffer.
* The data is contiguous. The address is the start of the dataset,
@@ -409,9 +421,10 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5F_contig_readv(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr,
- size_t nseq, size_t size_arr[], hsize_t offset_arr[], hid_t dxpl_id,
- void *_buf/*out*/)
+H5F_contig_readvv(H5F_t *f, hsize_t _max_data, haddr_t _addr,
+ 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[],
+ hid_t dxpl_id, void *_buf)
{
unsigned char *buf=(unsigned char *)_buf; /* Pointer to buffer to fill */
haddr_t abs_eoa; /* Absolute end of file address */
@@ -420,18 +433,10 @@ H5F_contig_readv(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr,
hsize_t max_data; /* Actual maximum size of data to cache */
size_t size; /* Size of sequence in bytes */
size_t u; /* Counting variable */
-#ifndef SLOW_WAY
- size_t max_seq; /* Maximum sequence to copy */
- haddr_t temp_end; /* Temporary end of buffer variable */
- size_t max_search; /* Maximum number of sequences to search */
- size_t mask; /* Bit mask */
- int bit_loc; /* Bit location of the leftmost '1' in max_search */
- size_t *size_arr_p; /* Pointer into the size array */
- hsize_t *offset_arr_p; /* Pointer into the offset array */
-#endif /* SLOW_WAY */
- herr_t ret_value=SUCCEED; /* Return value */
+ size_t v; /* Counting variable */
+ ssize_t ret_value=0; /* Return value */
- FUNC_ENTER_NOAPI(H5F_contig_readv, FAIL);
+ FUNC_ENTER_NOAPI(H5F_contig_readvv, FAIL);
/* Check args */
assert(f);
@@ -439,325 +444,143 @@ H5F_contig_readv(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr,
/* Check if data sieving is enabled */
if(f->shared->lf->feature_flags&H5FD_FEAT_DATA_SIEVE) {
+ haddr_t sieve_start, sieve_end; /* Start & end locations of sieve buffer */
+ haddr_t contig_end; /* End locations of block to write */
+ size_t sieve_size; /* size of sieve buffer */
+
+ /* Set offsets in sequence lists */
+ u=*dset_curr_seq;
+ v=*mem_curr_seq;
+
+ /* No data sieve buffer yet, go allocate one */
+ if(f->shared->sieve_buf==NULL) {
+ /* Choose smallest buffer to write */
+ if(mem_len_arr[v]<dset_len_arr[u])
+ size=mem_len_arr[v];
+ else
+ size=dset_len_arr[u];
+
+ /* Compute offset on disk */
+ addr=_addr+dset_offset_arr[u];
+
+ /* Compute offset in memory */
+ buf = (unsigned char *)_buf + mem_offset_arr[v];
+
+ /* Set up the buffer parameters */
+ max_data=_max_data-dset_offset_arr[u];
+
+ /* Check if we can actually hold the I/O request in the sieve buffer */
+ if(size>f->shared->sieve_buf_size) {
+ if (H5F_block_read(f, H5FD_MEM_DRAW, addr, size, dxpl_id, buf)<0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed");
+ } /* end if */
+ else {
+ /* Allocate room for the data sieve buffer */
+ if (NULL==(f->shared->sieve_buf=H5FL_BLK_MALLOC(sieve_buf,f->shared->sieve_buf_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
- /* Outer loop, guarantees working through all the sequences */
- for(u=0; u<nseq; ) {
-
- /* Try reading from the data sieve buffer */
- if(f->shared->sieve_buf) {
- haddr_t sieve_start, sieve_end; /* Start & end locations of sieve buffer */
- haddr_t contig_end; /* End locations of block to write */
- size_t sieve_size; /* size of sieve buffer */
-
- /* Stash local copies of these value */
- sieve_start=f->shared->sieve_loc;
- sieve_size=f->shared->sieve_size;
- sieve_end=sieve_start+sieve_size;
-
- /* Next-outer loop works through sequences as fast as possible */
- for(; u<nseq; ) {
- size=size_arr[u];
- addr=_addr+offset_arr[u];
-
- /* Compute end of sequence to retrieve */
- contig_end=addr+size-1;
-
- /* If entire read is within the sieve buffer, read it from the buffer */
- if(addr>=sieve_start && contig_end<sieve_end) {
- unsigned char *base_sieve_buf=f->shared->sieve_buf+(_addr-sieve_start);
- unsigned char *temp_sieve_buf;
- haddr_t temp_addr=_addr-1; /* Temporary address */
-
-#ifdef SLOW_WAY
- /* Retrieve all the sequences out of the current sieve buffer */
- while(contig_end<sieve_end) {
- /* Set the location within the sieve buffer to the correct offset */
- temp_sieve_buf=base_sieve_buf+offset_arr[u];
-
- /* Grab the data out of the buffer */
- HDmemcpy(buf,temp_sieve_buf,size_arr[u]);
-
- /* Increment offset in buffer */
- buf += size_arr[u];
-
- /* Increment sequence number, check for finished with sequences */
- if((++u) >= nseq)
- break;
-
- /* Re-compute end of sequence to retrieve */
- contig_end=temp_addr+offset_arr[u]+size_arr[u];
- } /* end while */
-#else /* SLOW_WAY */
- /* Find log2(n) where n is the number of elements to search */
-
- /* Set initial parameters */
- mask=(size_t)0xff<<((sizeof(size_t)-1)*8); /* Get a mask for the leftmost byte */
- max_search=((nseq-1)-u)+1; /* Compute 'n' for the log2 */
- assert(max_search>0); /* Sanity check */
- bit_loc=(sizeof(size_t)*8)-1; /* Initial bit location */
-
- /* Search for the first byte with a bit set */
- while((max_search & mask)==0) {
- mask>>=8;
- bit_loc-=8;
- } /* end while */
-
- /* Switch to searching for a bit */
- mask=1<<bit_loc;
- while((max_search & mask)==0) {
- mask>>=1;
- bit_loc--;
- } /* end while */
-
- /* location of the leftmost bit, plus 1, is log2(n) */
- max_seq=bit_loc+1;
-
- /* Don't walk off the array */
- max_seq=MIN(u+max_seq,nseq-1);
-
- /* Determine if a linear search is faster than a binary search */
- temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq];
- if(temp_end>=sieve_end) {
- /* Linear search is faster */
-
- /* Set the initial search values */
- max_seq=u;
- temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq];
-
- /* Search for the first sequence ending greater than the sieve buffer end */
- while(temp_end<sieve_end) {
- if(++max_seq>=nseq)
- break;
- temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq];
- } /* end while */
-
- /* Adjust back one element */
- max_seq--;
-
- } /* end if */
- else {
- size_t lo,hi; /* Low and high bounds for binary search */
- unsigned found=0; /* Flag to indicate bounds have been found */
-
- /* Binary search is faster */
-
- /* Find the value 'u' which will be beyond the end of the sieve buffer */
- lo=u;
- hi=nseq-1;
- max_seq=(lo+hi)/2;
- while(!found) {
- /* Get the address of the end of sequence for the 'max_seq' position */
- temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq];
-
- /* Current high bound is too large */
- if(temp_end>=sieve_end) {
- if((lo+1)<hi) {
- hi=max_seq;
- max_seq=(lo+hi)/2;
- } /* end if */
- else {
- found=1;
- } /* end else */
- } /* end if */
- /* Current low bound is too small */
- else {
- if((lo+1)<hi) {
- lo=max_seq;
- max_seq=(lo+hi+1)/2;
- } /* end if */
- else {
- found=1;
- } /* end else */
- } /* end else */
- } /* end while */
-
- /* Check for non-exact match */
- if(lo!=hi) {
- temp_end=temp_addr+offset_arr[hi]+size_arr[hi];
- if(temp_end<sieve_end)
- max_seq=hi;
- else
- max_seq=lo;
- } /* end if */
- } /* end else */
-
- /* Set the pointers to the correct locations in the offset & size arrays */
- size_arr_p=&size_arr[u];
- offset_arr_p=&offset_arr[u];
-
-#ifdef NO_DUFFS_DEVICE
- /* Retrieve all the sequences out of the current sieve buffer */
- while(u<=max_seq) {
- /* Set the location within the sieve buffer to the correct offset */
- temp_sieve_buf=base_sieve_buf+*offset_arr_p++;
-
- /* Grab the data out of the buffer */
- HDmemcpy(buf,temp_sieve_buf,*size_arr_p);
-
- /* Increment offset in buffer */
- buf += *size_arr_p++;
-
- /* Increment the offset in the array */
- u++;
- } /* end while */
-#else /* NO_DUFFS_DEVICE */
-{
- size_t seq_count;
-
- seq_count=(max_seq-u)+1;
- switch (seq_count % 4) {
- case 0:
- do
- {
- /* Set the location within the sieve buffer to the correct offset */
- temp_sieve_buf=base_sieve_buf+*offset_arr_p++;
-
- /* Grab the data out of the buffer */
- HDmemcpy(buf,temp_sieve_buf,*size_arr_p);
-
- /* Increment offset in buffer */
- buf += *size_arr_p++;
-
- /* Increment the offset in the array */
- u++;
-
- case 3:
- /* Set the location within the sieve buffer to the correct offset */
- temp_sieve_buf=base_sieve_buf+*offset_arr_p++;
-
- /* Grab the data out of the buffer */
- HDmemcpy(buf,temp_sieve_buf,*size_arr_p);
-
- /* Increment offset in buffer */
- buf += *size_arr_p++;
-
- /* Increment the offset in the array */
- u++;
-
- case 2:
- /* Set the location within the sieve buffer to the correct offset */
- temp_sieve_buf=base_sieve_buf+*offset_arr_p++;
-
- /* Grab the data out of the buffer */
- HDmemcpy(buf,temp_sieve_buf,*size_arr_p);
-
- /* Increment offset in buffer */
- buf += *size_arr_p++;
-
- /* Increment the offset in the array */
- u++;
-
- case 1:
- /* Set the location within the sieve buffer to the correct offset */
- temp_sieve_buf=base_sieve_buf+*offset_arr_p++;
-
- /* Grab the data out of the buffer */
- HDmemcpy(buf,temp_sieve_buf,*size_arr_p);
-
- /* Increment offset in buffer */
- buf += *size_arr_p++;
-
- /* Increment the offset in the array */
- u++;
-
- } while (u<=max_seq);
- } /* end switch */
-
-}
-#endif /* NO_DUFFS_DEVICE */
-#endif /* SLOW_WAY */
- } /* end if */
- /* Entire request is not within this data sieve buffer */
- else {
- /* Check if we can actually hold the I/O request in the sieve buffer */
- if(size>f->shared->sieve_buf_size) {
- /* Check for any overlap with the current sieve buffer */
- if((sieve_start>=addr && sieve_start<(contig_end+1))
- || ((sieve_end-1)>=addr && (sieve_end-1)<(contig_end+1))) {
- /* Flush the sieve buffer, if it's dirty */
- if(f->shared->sieve_dirty) {
- /* Write to file */
- if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed");
-
- /* Reset sieve buffer dirty flag */
- f->shared->sieve_dirty=0;
- } /* end if */
- } /* end if */
-
- /* Read directly into the user's buffer */
- if (H5F_block_read(f, type, addr, size, dxpl_id, buf)<0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed");
- } /* end if */
- /* Element size fits within the buffer size */
- else {
- /* Flush the sieve buffer if it's dirty */
- if(f->shared->sieve_dirty) {
- /* Write to file */
- if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed");
-
- /* Reset sieve buffer dirty flag */
- f->shared->sieve_dirty=0;
- } /* end if */
-
- /* Determine the new sieve buffer size & location */
- f->shared->sieve_loc=addr;
-
- /* Make certain we don't read off the end of the file */
- if (HADDR_UNDEF==(abs_eoa=H5FD_get_eoa(f->shared->lf)))
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size");
+ /* Determine the new sieve buffer size & location */
+ f->shared->sieve_loc=addr;
- /* Adjust absolute EOA address to relative EOA address */
- rel_eoa=abs_eoa-f->shared->base_addr;
+ /* Make certain we don't read off the end of the file */
+ if (HADDR_UNDEF==(abs_eoa=H5FD_get_eoa(f->shared->lf)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size");
- /* Only need this when resizing sieve buffer */
- max_data=_max_data-offset_arr[u];
+ /* Adjust absolute EOA address to relative EOA address */
+ rel_eoa=abs_eoa-f->shared->base_addr;
- /* Compute the size of the sieve buffer */
- /* Don't read off the end of the file, don't read past the end of the data element and don't read more than the buffer size */
- H5_ASSIGN_OVERFLOW(f->shared->sieve_size,MIN(rel_eoa-f->shared->sieve_loc,MIN(max_data,f->shared->sieve_buf_size)),hsize_t,size_t);
+ /* Compute the size of the sieve buffer */
+ H5_ASSIGN_OVERFLOW(f->shared->sieve_size,MIN(rel_eoa-f->shared->sieve_loc,MIN(max_data,f->shared->sieve_buf_size)),hsize_t,size_t);
- /* Update local copies of sieve information */
- sieve_start=f->shared->sieve_loc;
- sieve_size=f->shared->sieve_size;
- sieve_end=sieve_start+sieve_size;
+ /* Read the new sieve buffer */
+ if (H5F_block_read(f, H5FD_MEM_DRAW, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->sieve_buf)<0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed");
- /* Read the new sieve buffer */
- if (H5F_block_read(f, type, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->sieve_buf)<0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed");
+ /* Grab the data out of the buffer (must be first piece of data in buffer ) */
+ HDmemcpy(buf,f->shared->sieve_buf,size);
- /* Reset sieve buffer dirty flag */
- f->shared->sieve_dirty=0;
+ /* Reset sieve buffer dirty flag */
+ f->shared->sieve_dirty=0;
+ } /* end else */
- /* Grab the data out of the buffer (must be first piece of data in buffer ) */
- HDmemcpy(buf,f->shared->sieve_buf,size);
- } /* end else */
+ /* Update memory information */
+ mem_len_arr[v]-=size;
+ mem_offset_arr[v]+=size;
+ if(mem_len_arr[v]==0)
+ v++;
- /* Increment offset in buffer */
- buf += size_arr[u];
+ /* Update file information */
+ dset_len_arr[u]-=size;
+ dset_offset_arr[u]+=size;
+ if(dset_len_arr[u]==0)
+ u++;
- /* Increment sequence number */
- u++;
- } /* end else */
- } /* end for */
+ /* Increment number of bytes copied */
+ ret_value+=size;
+ } /* end if */
+
+ /* Stash local copies of these value */
+ sieve_start=f->shared->sieve_loc;
+ sieve_size=f->shared->sieve_size;
+ sieve_end=sieve_start+sieve_size;
+
+ /* Works through sequences as fast as possible */
+ for(; u<dset_max_nseq && v<mem_max_nseq; ) {
+ /* Choose smallest buffer to write */
+ if(mem_len_arr[v]<dset_len_arr[u])
+ size=mem_len_arr[v];
+ else
+ size=dset_len_arr[u];
+
+ /* Compute offset on disk */
+ addr=_addr+dset_offset_arr[u];
+
+ /* Compute offset in memory */
+ buf = (unsigned char *)_buf + mem_offset_arr[v];
+
+ /* Compute end of sequence to retrieve */
+ contig_end=addr+size-1;
+
+ /* If entire read is within the sieve buffer, read it from the buffer */
+ if(addr>=sieve_start && contig_end<sieve_end) {
+ unsigned char *base_sieve_buf=f->shared->sieve_buf+(addr-sieve_start);
+
+ /* Grab the data out of the buffer */
+ HDmemcpy(buf,base_sieve_buf,size);
} /* end if */
- /* No data sieve buffer yet, go allocate one */
+ /* Entire request is not within this data sieve buffer */
else {
- /* Set up the buffer parameters */
- size=size_arr[u];
- addr=_addr+offset_arr[u];
- max_data=_max_data-offset_arr[u];
-
/* Check if we can actually hold the I/O request in the sieve buffer */
if(size>f->shared->sieve_buf_size) {
- if (H5F_block_read(f, type, addr, size, dxpl_id, buf)<0)
+ /* Check for any overlap with the current sieve buffer */
+ if((sieve_start>=addr && sieve_start<(contig_end+1))
+ || ((sieve_end-1)>=addr && (sieve_end-1)<(contig_end+1))) {
+ /* Flush the sieve buffer, if it's dirty */
+ if(f->shared->sieve_dirty) {
+ /* Write to file */
+ if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed");
+
+ /* Reset sieve buffer dirty flag */
+ f->shared->sieve_dirty=0;
+ } /* end if */
+ } /* end if */
+
+ /* Read directly into the user's buffer */
+ if (H5F_block_read(f, H5FD_MEM_DRAW, addr, size, dxpl_id, buf)<0)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed");
} /* end if */
+ /* Element size fits within the buffer size */
else {
- /* Allocate room for the data sieve buffer */
- if (NULL==(f->shared->sieve_buf=H5FL_BLK_MALLOC(sieve_buf,f->shared->sieve_buf_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
+ /* Flush the sieve buffer if it's dirty */
+ if(f->shared->sieve_dirty) {
+ /* Write to file */
+ if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed");
+
+ /* Reset sieve buffer dirty flag */
+ f->shared->sieve_dirty=0;
+ } /* end if */
/* Determine the new sieve buffer size & location */
f->shared->sieve_loc=addr;
@@ -769,59 +592,103 @@ H5F_contig_readv(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr,
/* Adjust absolute EOA address to relative EOA address */
rel_eoa=abs_eoa-f->shared->base_addr;
+ /* Only need this when resizing sieve buffer */
+ max_data=_max_data-dset_offset_arr[u];
+
/* Compute the size of the sieve buffer */
+ /* Don't read off the end of the file, don't read past the end of the data element and don't read more than the buffer size */
H5_ASSIGN_OVERFLOW(f->shared->sieve_size,MIN(rel_eoa-f->shared->sieve_loc,MIN(max_data,f->shared->sieve_buf_size)),hsize_t,size_t);
+ /* Update local copies of sieve information */
+ sieve_start=f->shared->sieve_loc;
+ sieve_size=f->shared->sieve_size;
+ sieve_end=sieve_start+sieve_size;
+
/* Read the new sieve buffer */
- if (H5F_block_read(f, type, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->sieve_buf)<0)
+ if (H5F_block_read(f, H5FD_MEM_DRAW, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->sieve_buf)<0)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed");
- /* Reset sieve buffer dirty flag */
- f->shared->sieve_dirty=0;
-
/* Grab the data out of the buffer (must be first piece of data in buffer ) */
HDmemcpy(buf,f->shared->sieve_buf,size);
+
+ /* Reset sieve buffer dirty flag */
+ f->shared->sieve_dirty=0;
} /* end else */
+ } /* end else */
- /* Increment offset in buffer */
- buf += size_arr[u];
+ /* Update memory information */
+ mem_len_arr[v]-=size;
+ mem_offset_arr[v]+=size;
+ if(mem_len_arr[v]==0)
+ v++;
- /* Increment sequence number */
+ /* Update file information */
+ dset_len_arr[u]-=size;
+ dset_offset_arr[u]+=size;
+ if(dset_len_arr[u]==0)
u++;
- } /* end else */
+
+ /* Increment number of bytes copied */
+ ret_value+=size;
} /* end for */
} /* end if */
else {
/* Work through all the sequences */
- for(u=0; u<nseq; u++) {
- size=size_arr[u];
- addr=_addr+offset_arr[u];
+ for(u=*dset_curr_seq, v=*mem_curr_seq; u<dset_max_nseq && v<mem_max_nseq; ) {
+ /* Choose smallest buffer to write */
+ if(mem_len_arr[v]<dset_len_arr[u])
+ size=mem_len_arr[v];
+ else
+ size=dset_len_arr[u];
- if (H5F_block_read(f, type, addr, size, dxpl_id, buf)<0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed");
+ /* Compute offset on disk */
+ addr=_addr+dset_offset_arr[u];
+
+ /* Compute offset in memory */
+ buf = (unsigned char *)_buf + mem_offset_arr[v];
+
+ /* Write data */
+ if (H5F_block_read(f, H5FD_MEM_DRAW, addr, size, dxpl_id, buf)<0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed");
- /* Increment offset in buffer */
- buf += size_arr[u];
+ /* Update memory information */
+ mem_len_arr[v]-=size;
+ mem_offset_arr[v]+=size;
+ if(mem_len_arr[v]==0)
+ v++;
+
+ /* Update file information */
+ dset_len_arr[u]-=size;
+ dset_offset_arr[u]+=size;
+ if(dset_len_arr[u]==0)
+ u++;
+
+ /* Increment number of bytes copied */
+ ret_value+=size;
} /* end for */
} /* end else */
+ /* Update current sequence vectors */
+ *dset_curr_seq=u;
+ *mem_curr_seq=v;
+
done:
FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5F_contig_readv() */
+} /* end H5F_contig_readvv() */
/*-------------------------------------------------------------------------
- * Function: H5F_contig_writev
+ * Function: H5F_contig_writevv
*
- * Purpose: Writes some data vectors into a dataset from a buffer.
- * The data is contiguous. The address is the start of the dataset,
+ * Purpose: Writes some data vectors into a dataset from vectors into a
+ * buffer. The address is the start of the dataset,
* relative to the base address for the file and the offsets and
* sequence lengths are in bytes.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
- * Thursday, July 5, 2001
+ * Friday, May 2, 2003
*
* Notes:
* Offsets in the sequences must be monotonically increasing
@@ -830,10 +697,11 @@ done:
*
*-------------------------------------------------------------------------
*/
-herr_t
-H5F_contig_writev(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr,
- size_t nseq, size_t size_arr[], hsize_t offset_arr[], hid_t dxpl_id,
- const void *_buf)
+ssize_t
+H5F_contig_writevv(H5F_t *f, hsize_t _max_data, haddr_t _addr,
+ 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[],
+ hid_t dxpl_id, const void *_buf)
{
const unsigned char *buf=_buf; /* Pointer to buffer to fill */
haddr_t abs_eoa; /* Absolute end of file address */
@@ -842,18 +710,10 @@ H5F_contig_writev(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr,
hsize_t max_data; /* Actual maximum size of data to cache */
size_t size; /* Size of sequence in bytes */
size_t u; /* Counting variable */
-#ifndef SLOW_WAY
- size_t max_seq; /* Maximum sequence to copy */
- haddr_t temp_end; /* Temporary end of buffer variable */
- size_t max_search; /* Maximum number of sequences to search */
- size_t mask; /* Bit mask */
- int bit_loc; /* Bit location of the leftmost '1' in max_search */
- size_t *size_arr_p; /* Pointer into the size array */
- hsize_t *offset_arr_p; /* Pointer into the offset array */
-#endif /* SLOW_WAY */
- herr_t ret_value=SUCCEED; /* Return value */
+ size_t v; /* Counting variable */
+ ssize_t ret_value=0; /* Return value */
- FUNC_ENTER_NOAPI(H5F_contig_writev, FAIL);
+ FUNC_ENTER_NOAPI(H5F_contig_writevv, FAIL);
/* Check args */
assert(f);
@@ -861,421 +721,284 @@ H5F_contig_writev(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr,
/* Check if data sieving is enabled */
if(f->shared->lf->feature_flags&H5FD_FEAT_DATA_SIEVE) {
+ haddr_t sieve_start, sieve_end; /* Start & end locations of sieve buffer */
+ haddr_t contig_end; /* End locations of block to write */
+ size_t sieve_size; /* size of sieve buffer */
+
+ /* Set offsets in sequence lists */
+ u=*dset_curr_seq;
+ v=*mem_curr_seq;
+
+ /* No data sieve buffer yet, go allocate one */
+ if(f->shared->sieve_buf==NULL) {
+ /* Choose smallest buffer to write */
+ if(mem_len_arr[v]<dset_len_arr[u])
+ size=mem_len_arr[v];
+ else
+ size=dset_len_arr[u];
+
+ /* Compute offset on disk */
+ addr=_addr+dset_offset_arr[u];
+
+ /* Compute offset in memory */
+ buf = (const unsigned char *)_buf + mem_offset_arr[v];
+
+ /* Set up the buffer parameters */
+ max_data=_max_data-dset_offset_arr[u];
+
+ /* Check if we can actually hold the I/O request in the sieve buffer */
+ if(size>f->shared->sieve_buf_size) {
+ if (H5F_block_write(f, H5FD_MEM_DRAW, addr, size, dxpl_id, buf)<0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed");
+ } /* end if */
+ else {
+ /* Allocate room for the data sieve buffer */
+ if (NULL==(f->shared->sieve_buf=H5FL_BLK_MALLOC(sieve_buf,f->shared->sieve_buf_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
- /* Outer loop, guarantees working through all the sequences */
- for(u=0; u<nseq; ) {
-
- /* Try writing into the data sieve buffer */
- if(f->shared->sieve_buf) {
- haddr_t sieve_start, sieve_end; /* Start & end locations of sieve buffer */
- haddr_t contig_end; /* End locations of block to write */
- size_t sieve_size; /* size of sieve buffer */
-
- /* Stash local copies of these value */
- sieve_start=f->shared->sieve_loc;
- sieve_size=f->shared->sieve_size;
- sieve_end=sieve_start+sieve_size;
-
- /* Next-outer loop works through sequences as fast as possible */
- for(; u<nseq; ) {
- size=size_arr[u];
- addr=_addr+offset_arr[u];
-
- /* Compute end of sequence to retrieve */
- contig_end=addr+size-1;
-
- /* If entire write is within the sieve buffer, write it to the buffer */
- if(addr>=sieve_start && contig_end<sieve_end) {
- unsigned char *base_sieve_buf=f->shared->sieve_buf+(_addr-sieve_start);
- unsigned char *temp_sieve_buf;
- haddr_t temp_addr=_addr-1; /* Temporary address */
-
-#ifdef SLOW_WAY
- /* Retrieve all the sequences out of the current sieve buffer */
- while(contig_end<sieve_end) {
- /* Set the location within the sieve buffer to the correct offset */
- temp_sieve_buf=base_sieve_buf+offset_arr[u];
-
- /* Grab the data out of the buffer */
- HDmemcpy(temp_sieve_buf,buf,size_arr[u]);
-
- /* Increment offset in buffer */
- buf += size_arr[u];
-
- /* Increment sequence number, check for finished with sequences */
- if((++u) >= nseq)
- break;
-
- /* Re-compute end of sequence to retrieve */
- contig_end=temp_addr+offset_arr[u]+size_arr[u];
- } /* end while */
-#else /* SLOW_WAY */
- /* Find log2(n) where n is the number of elements to search */
-
- /* Set initial parameters */
- mask=(size_t)0xff<<((sizeof(size_t)-1)*8); /* Get a mask for the leftmost byte */
- max_search=((nseq-1)-u)+1; /* Compute 'n' for the log2 */
- assert(max_search>0); /* Sanity check */
- bit_loc=(sizeof(size_t)*8)-1; /* Initial bit location */
-
- /* Search for the first byte with a bit set */
- while((max_search & mask)==0) {
- mask>>=8;
- bit_loc-=8;
- } /* end while */
-
- /* Switch to searching for a bit */
- mask=1<<bit_loc;
- while((max_search & mask)==0) {
- mask>>=1;
- bit_loc--;
- } /* end while */
-
- /* location of the leftmost bit, plus 1, is log2(n) */
- max_seq=bit_loc+1;
-
- /* Don't walk off the array */
- max_seq=MIN(u+max_seq,nseq-1);
-
- /* Determine if a linear search is faster than a binary search */
- temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq];
- if(temp_end>=sieve_end) {
- /* Linear search is faster */
-
- /* Set the initial search values */
- max_seq=u;
- temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq];
-
- /* Search for the first sequence ending greater than the sieve buffer end */
- while(temp_end<sieve_end) {
- if(++max_seq>=nseq)
- break;
- temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq];
- } /* end while */
-
- /* Adjust back one element */
- max_seq--;
-
- } /* end if */
- else {
- size_t lo,hi; /* Low and high bounds for binary search */
- unsigned found=0; /* Flag to indicate bounds have been found */
-
- /* Binary search is faster */
-
- /* Find the value 'u' which will be beyond the end of the sieve buffer */
- lo=u;
- hi=nseq-1;
- max_seq=(lo+hi)/2;
- while(!found) {
- /* Get the address of the end of sequence for the 'max_seq' position */
- temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq];
-
- /* Current high bound is too large */
- if(temp_end>=sieve_end) {
- if((lo+1)<hi) {
- hi=max_seq;
- max_seq=(lo+hi)/2;
- } /* end if */
- else {
- found=1;
- } /* end else */
- } /* end if */
- /* Current low bound is too small */
- else {
- if((lo+1)<hi) {
- lo=max_seq;
- max_seq=(lo+hi+1)/2;
- } /* end if */
- else {
- found=1;
- } /* end else */
- } /* end else */
- } /* end while */
-
- /* Check for non-exact match */
- if(lo!=hi) {
- temp_end=temp_addr+offset_arr[hi]+size_arr[hi];
- if(temp_end<sieve_end)
- max_seq=hi;
- else
- max_seq=lo;
- } /* end if */
- } /* end else */
-
- /* Set the pointers to the correct locations in the offset & size arrays */
- size_arr_p=&size_arr[u];
- offset_arr_p=&offset_arr[u];
-
-#ifdef NO_DUFFS_DEVICE
- /* Retrieve all the sequences out of the current sieve buffer */
- while(u<=max_seq) {
- /* Set the location within the sieve buffer to the correct offset */
- temp_sieve_buf=base_sieve_buf+*offset_arr_p++;
+ /* Determine the new sieve buffer size & location */
+ f->shared->sieve_loc=addr;
- /* Grab the data out of the buffer */
- HDmemcpy(temp_sieve_buf,buf,*size_arr_p);
+ /* Make certain we don't read off the end of the file */
+ if (HADDR_UNDEF==(abs_eoa=H5FD_get_eoa(f->shared->lf)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size");
- /* Increment offset in buffer */
- buf += *size_arr_p++;
+ /* Adjust absolute EOA address to relative EOA address */
+ rel_eoa=abs_eoa-f->shared->base_addr;
- /* Increment the offset in the array */
- u++;
- } /* end while */
-#else /* NO_DUFFS_DEVICE */
-{
- size_t seq_count;
+ /* Compute the size of the sieve buffer */
+ H5_ASSIGN_OVERFLOW(f->shared->sieve_size,MIN(rel_eoa-f->shared->sieve_loc,MIN(max_data,f->shared->sieve_buf_size)),hsize_t,size_t);
- seq_count=(max_seq-u)+1;
- switch (seq_count % 4) {
- case 0:
- do
- {
- /* Set the location within the sieve buffer to the correct offset */
- temp_sieve_buf=base_sieve_buf+*offset_arr_p++;
+ /* Check if there is any point in reading the data from the file */
+ if(f->shared->sieve_size>size) {
+ /* Read the new sieve buffer */
+ if (H5F_block_read(f, H5FD_MEM_DRAW, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->sieve_buf)<0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed");
+ } /* end if */
- /* Grab the data out of the buffer */
- HDmemcpy(temp_sieve_buf,buf,*size_arr_p);
+ /* Grab the data out of the buffer (must be first piece of data in buffer ) */
+ HDmemcpy(f->shared->sieve_buf,buf,size);
- /* Increment offset in buffer */
- buf += *size_arr_p++;
+ /* Set sieve buffer dirty flag */
+ f->shared->sieve_dirty=1;
+ } /* end else */
- /* Increment the offset in the array */
- u++;
+ /* Update memory information */
+ mem_len_arr[v]-=size;
+ mem_offset_arr[v]+=size;
+ if(mem_len_arr[v]==0)
+ v++;
- case 3:
- /* Set the location within the sieve buffer to the correct offset */
- temp_sieve_buf=base_sieve_buf+*offset_arr_p++;
+ /* Update file information */
+ dset_len_arr[u]-=size;
+ dset_offset_arr[u]+=size;
+ if(dset_len_arr[u]==0)
+ u++;
- /* Grab the data out of the buffer */
- HDmemcpy(temp_sieve_buf,buf,*size_arr_p);
+ /* Increment number of bytes copied */
+ ret_value+=size;
+ } /* end if */
- /* Increment offset in buffer */
- buf += *size_arr_p++;
+ /* Stash local copies of these value */
+ sieve_start=f->shared->sieve_loc;
+ sieve_size=f->shared->sieve_size;
+ sieve_end=sieve_start+sieve_size;
+
+ /* Works through sequences as fast as possible */
+ for(; u<dset_max_nseq && v<mem_max_nseq; ) {
+ /* Choose smallest buffer to write */
+ if(mem_len_arr[v]<dset_len_arr[u])
+ size=mem_len_arr[v];
+ else
+ size=dset_len_arr[u];
- /* Increment the offset in the array */
- u++;
+ /* Compute offset on disk */
+ addr=_addr+dset_offset_arr[u];
- case 2:
- /* Set the location within the sieve buffer to the correct offset */
- temp_sieve_buf=base_sieve_buf+*offset_arr_p++;
+ /* Compute offset in memory */
+ buf = (const unsigned char *)_buf + mem_offset_arr[v];
- /* Grab the data out of the buffer */
- HDmemcpy(temp_sieve_buf,buf,*size_arr_p);
+ /* Compute end of sequence to retrieve */
+ contig_end=addr+size-1;
- /* Increment offset in buffer */
- buf += *size_arr_p++;
+ /* If entire write is within the sieve buffer, write it to the buffer */
+ if(addr>=sieve_start && contig_end<sieve_end) {
+ unsigned char *base_sieve_buf=f->shared->sieve_buf+(addr-sieve_start);
- /* Increment the offset in the array */
- u++;
+ /* Put the data into the sieve buffer */
+ HDmemcpy(base_sieve_buf,buf,size);
- case 1:
- /* Set the location within the sieve buffer to the correct offset */
- temp_sieve_buf=base_sieve_buf+*offset_arr_p++;
+ /* Set sieve buffer dirty flag */
+ f->shared->sieve_dirty=1;
- /* Grab the data out of the buffer */
- HDmemcpy(temp_sieve_buf,buf,*size_arr_p);
+ } /* end if */
+ /* Entire request is not within this data sieve buffer */
+ else {
+ /* Check if we can actually hold the I/O request in the sieve buffer */
+ if(size>f->shared->sieve_buf_size) {
+ /* Check for any overlap with the current sieve buffer */
+ if((sieve_start>=addr && sieve_start<(contig_end+1))
+ || ((sieve_end-1)>=addr && (sieve_end-1)<(contig_end+1))) {
+ /* Flush the sieve buffer, if it's dirty */
+ if(f->shared->sieve_dirty) {
+ /* Write to file */
+ if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed");
- /* Increment offset in buffer */
- buf += *size_arr_p++;
+ /* Reset sieve buffer dirty flag */
+ f->shared->sieve_dirty=0;
+ } /* end if */
- /* Increment the offset in the array */
- u++;
+ /* Force the sieve buffer to be re-read the next time */
+ f->shared->sieve_loc=HADDR_UNDEF;
+ f->shared->sieve_size=0;
+ } /* end if */
- } while (u<=max_seq);
- } /* end switch */
+ /* Write directly from the user's buffer */
+ if (H5F_block_write(f, H5FD_MEM_DRAW, addr, size, dxpl_id, buf)<0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed");
+ } /* end if */
+ /* Element size fits within the buffer size */
+ else {
+ /* Check if it is possible to (exactly) prepend or append to existing (dirty) sieve buffer */
+ if(((addr+size)==sieve_start || addr==sieve_end) &&
+ (size+sieve_size)<=f->shared->sieve_buf_size &&
+ f->shared->sieve_dirty) {
+ /* Prepend to existing sieve buffer */
+ if((addr+size)==sieve_start) {
+ /* Move existing sieve information to correct location */
+ HDmemmove(f->shared->sieve_buf+size,f->shared->sieve_buf,sieve_size);
+
+ /* Copy in new information (must be first in sieve buffer) */
+ HDmemcpy(f->shared->sieve_buf,buf,size);
+
+ /* Adjust sieve location */
+ f->shared->sieve_loc=addr;
+
+ } /* end if */
+ /* Append to existing sieve buffer */
+ else {
+ /* Copy in new information */
+ HDmemcpy(f->shared->sieve_buf+sieve_size,buf,size);
+ } /* end else */
-}
-#endif /* NO_DUFFS_DEVICE */
-#endif /* SLOW_WAY */
- /* Set sieve buffer dirty flag */
- f->shared->sieve_dirty=1;
+ /* Adjust sieve size */
+ f->shared->sieve_size += size;
+
+ /* Update local copies of sieve information */
+ sieve_start=f->shared->sieve_loc;
+ sieve_size=f->shared->sieve_size;
+ sieve_end=sieve_start+sieve_size;
} /* end if */
- /* Entire request is not within this data sieve buffer */
+ /* Can't add the new data onto the existing sieve buffer */
else {
- /* Check if we can actually hold the I/O request in the sieve buffer */
- if(size>f->shared->sieve_buf_size) {
- /* Check for any overlap with the current sieve buffer */
- if((sieve_start>=addr && sieve_start<(contig_end+1))
- || ((sieve_end-1)>=addr && (sieve_end-1)<(contig_end+1))) {
- /* Flush the sieve buffer, if it's dirty */
- if(f->shared->sieve_dirty) {
- /* Write to file */
- if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed");
-
- /* Reset sieve buffer dirty flag */
- f->shared->sieve_dirty=0;
- } /* end if */
-
- /* Force the sieve buffer to be re-read the next time */
- f->shared->sieve_loc=HADDR_UNDEF;
- f->shared->sieve_size=0;
- } /* end if */
-
- /* Write directly from the user's buffer */
- if (H5F_block_write(f, type, addr, size, dxpl_id, buf)<0)
+ /* Flush the sieve buffer if it's dirty */
+ if(f->shared->sieve_dirty) {
+ /* Write to file */
+ if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed");
+
+ /* Reset sieve buffer dirty flag */
+ f->shared->sieve_dirty=0;
} /* end if */
- /* Element size fits within the buffer size */
- else {
- /* Check if it is possible to (exactly) prepend or append to existing (dirty) sieve buffer */
- if(((addr+size)==sieve_start || addr==sieve_end) &&
- (size+sieve_size)<=f->shared->sieve_buf_size &&
- f->shared->sieve_dirty) {
- /* Prepend to existing sieve buffer */
- if((addr+size)==sieve_start) {
- /* Move existing sieve information to correct location */
- HDmemmove(f->shared->sieve_buf+size,f->shared->sieve_buf,sieve_size);
-
- /* Copy in new information (must be first in sieve buffer) */
- HDmemcpy(f->shared->sieve_buf,buf,size);
-
- /* Adjust sieve location */
- f->shared->sieve_loc=addr;
-
- } /* end if */
- /* Append to existing sieve buffer */
- else {
- /* Copy in new information */
- HDmemcpy(f->shared->sieve_buf+sieve_size,buf,size);
- } /* end else */
-
- /* Adjust sieve size */
- f->shared->sieve_size += size;
-
- /* Update local copies of sieve information */
- sieve_start=f->shared->sieve_loc;
- sieve_size=f->shared->sieve_size;
- sieve_end=sieve_start+sieve_size;
-
- } /* end if */
- /* Can't add the new data onto the existing sieve buffer */
- else {
- /* Flush the sieve buffer if it's dirty */
- if(f->shared->sieve_dirty) {
- /* Write to file */
- if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed");
-
- /* Reset sieve buffer dirty flag */
- f->shared->sieve_dirty=0;
- } /* end if */
-
- /* Determine the new sieve buffer size & location */
- f->shared->sieve_loc=addr;
-
- /* Make certain we don't read off the end of the file */
- if (HADDR_UNDEF==(abs_eoa=H5FD_get_eoa(f->shared->lf)))
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size");
-
- /* Adjust absolute EOA address to relative EOA address */
- rel_eoa=abs_eoa-f->shared->base_addr;
-
- /* Only need this when resizing sieve buffer */
- max_data=_max_data-offset_arr[u];
-
- /* Compute the size of the sieve buffer */
- /* Don't read off the end of the file, don't read past the end of the data element and don't read more than the buffer size */
- H5_ASSIGN_OVERFLOW(f->shared->sieve_size,MIN(rel_eoa-f->shared->sieve_loc,MIN(max_data,f->shared->sieve_buf_size)),hsize_t,size_t);
-
- /* Update local copies of sieve information */
- sieve_start=f->shared->sieve_loc;
- sieve_size=f->shared->sieve_size;
- sieve_end=sieve_start+sieve_size;
-
- /* Check if there is any point in reading the data from the file */
- if(f->shared->sieve_size>size) {
- /* Read the new sieve buffer */
- if (H5F_block_read(f, type, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->sieve_buf)<0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed");
- } /* end if */
-
- /* Grab the data out of the buffer (must be first piece of data in buffer ) */
- HDmemcpy(f->shared->sieve_buf,buf,size);
-
- /* Set sieve buffer dirty flag */
- f->shared->sieve_dirty=1;
-
- } /* end else */
- } /* end else */
- /* Increment offset in buffer */
- buf += size_arr[u];
+ /* Determine the new sieve buffer size & location */
+ f->shared->sieve_loc=addr;
- /* Increment sequence number */
- u++;
- } /* end else */
- } /* end for */
- } /* end if */
- /* No data sieve buffer yet, go allocate one */
- else {
- /* Set up the buffer parameters */
- size=size_arr[u];
- addr=_addr+offset_arr[u];
- max_data=_max_data-offset_arr[u];
+ /* Make certain we don't read off the end of the file */
+ if (HADDR_UNDEF==(abs_eoa=H5FD_get_eoa(f->shared->lf)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size");
- /* Check if we can actually hold the I/O request in the sieve buffer */
- if(size>f->shared->sieve_buf_size) {
- if (H5F_block_write(f, type, addr, size, dxpl_id, buf)<0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed");
- } /* end if */
- else {
- /* Allocate room for the data sieve buffer */
- if (NULL==(f->shared->sieve_buf=H5FL_BLK_MALLOC(sieve_buf,f->shared->sieve_buf_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
+ /* Adjust absolute EOA address to relative EOA address */
+ rel_eoa=abs_eoa-f->shared->base_addr;
- /* Determine the new sieve buffer size & location */
- f->shared->sieve_loc=addr;
+ /* Only need this when resizing sieve buffer */
+ max_data=_max_data-dset_offset_arr[u];
- /* Make certain we don't read off the end of the file */
- if (HADDR_UNDEF==(abs_eoa=H5FD_get_eoa(f->shared->lf)))
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size");
+ /* Compute the size of the sieve buffer */
+ /* Don't read off the end of the file, don't read past the end of the data element and don't read more than the buffer size */
+ H5_ASSIGN_OVERFLOW(f->shared->sieve_size,MIN(rel_eoa-f->shared->sieve_loc,MIN(max_data,f->shared->sieve_buf_size)),hsize_t,size_t);
- /* Adjust absolute EOA address to relative EOA address */
- rel_eoa=abs_eoa-f->shared->base_addr;
+ /* Update local copies of sieve information */
+ sieve_start=f->shared->sieve_loc;
+ sieve_size=f->shared->sieve_size;
+ sieve_end=sieve_start+sieve_size;
- /* Compute the size of the sieve buffer */
- H5_ASSIGN_OVERFLOW(f->shared->sieve_size,MIN(rel_eoa-f->shared->sieve_loc,MIN(max_data,f->shared->sieve_buf_size)),hsize_t,size_t);
+ /* Check if there is any point in reading the data from the file */
+ if(f->shared->sieve_size>size) {
+ /* Read the new sieve buffer */
+ if (H5F_block_read(f, H5FD_MEM_DRAW, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->sieve_buf)<0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed");
+ } /* end if */
- /* Check if there is any point in reading the data from the file */
- if(f->shared->sieve_size>size) {
- /* Read the new sieve buffer */
- if (H5F_block_read(f, type, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->sieve_buf)<0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed");
- } /* end if */
+ /* Grab the data out of the buffer (must be first piece of data in buffer ) */
+ HDmemcpy(f->shared->sieve_buf,buf,size);
- /* Grab the data out of the buffer (must be first piece of data in buffer ) */
- HDmemcpy(f->shared->sieve_buf,buf,size);
+ /* Set sieve buffer dirty flag */
+ f->shared->sieve_dirty=1;
- /* Set sieve buffer dirty flag */
- f->shared->sieve_dirty=1;
+ } /* end else */
} /* end else */
+ } /* end else */
- /* Increment offset in buffer */
- buf += size_arr[u];
+ /* Update memory information */
+ mem_len_arr[v]-=size;
+ mem_offset_arr[v]+=size;
+ if(mem_len_arr[v]==0)
+ v++;
- /* Increment sequence number */
+ /* Update file information */
+ dset_len_arr[u]-=size;
+ dset_offset_arr[u]+=size;
+ if(dset_len_arr[u]==0)
u++;
- } /* end else */
+
+ /* Increment number of bytes copied */
+ ret_value+=size;
} /* end for */
} /* end if */
else {
/* Work through all the sequences */
- for(u=0; u<nseq; u++) {
- size=size_arr[u];
- addr=_addr+offset_arr[u];
+ for(u=*dset_curr_seq, v=*mem_curr_seq; u<dset_max_nseq && v<mem_max_nseq; ) {
+ /* Choose smallest buffer to write */
+ if(mem_len_arr[v]<dset_len_arr[u])
+ size=mem_len_arr[v];
+ else
+ size=dset_len_arr[u];
- if (H5F_block_write(f, type, addr, size, dxpl_id, buf)<0)
+ /* Compute offset on disk */
+ addr=_addr+dset_offset_arr[u];
+
+ /* Compute offset in memory */
+ buf = (const unsigned char *)_buf + mem_offset_arr[v];
+
+ /* Write data */
+ if (H5F_block_write(f, H5FD_MEM_DRAW, addr, size, dxpl_id, buf)<0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed");
- /* Increment offset in buffer */
- buf += size_arr[u];
+ /* Update memory information */
+ mem_len_arr[v]-=size;
+ mem_offset_arr[v]+=size;
+ if(mem_len_arr[v]==0)
+ v++;
+
+ /* Update file information */
+ dset_len_arr[u]-=size;
+ dset_offset_arr[u]+=size;
+ if(dset_len_arr[u]==0)
+ u++;
+
+ /* Increment number of bytes copied */
+ ret_value+=size;
} /* end for */
} /* end else */
+ /* Update current sequence vectors */
+ *dset_curr_seq=u;
+ *mem_curr_seq=v;
+
done:
FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5F_contig_writev() */
+} /* end H5F_contig_writevv() */