summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2010-10-01 05:43:11 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2010-10-01 05:43:11 (GMT)
commit0574011fe87d79953d44d0824b0d0da5386b9060 (patch)
tree46004bc1811257bf0006a1afe9cee8ffc335917c
parentd4927395baf43d3c399d7a708d2bae96a88db494 (diff)
downloadhdf5-0574011fe87d79953d44d0824b0d0da5386b9060.zip
hdf5-0574011fe87d79953d44d0824b0d0da5386b9060.tar.gz
hdf5-0574011fe87d79953d44d0824b0d0da5386b9060.tar.bz2
[svn-r19499] Description:
Bring r19498 from trunk to 1.8 branch: Optimize the vector-vector memcpy() routine even further, for a total of ~2x speedup. :-) Make a generic vector-vector operation routine and convert other vector-vector read & write routines to use generic routine instead of multiple copies of the basic algorithm. Tested on: FreeBSD/32 6.3 (duty) in debug mode (h5committested on trunk)
-rw-r--r--src/H5Dchunk.c137
-rw-r--r--src/H5Dcontig.c973
-rw-r--r--src/H5Defl.c212
-rw-r--r--src/H5Dpkg.h8
-rw-r--r--src/H5Shyper.c5
-rw-r--r--src/H5V.c403
-rw-r--r--src/H5Vprivate.h11
7 files changed, 1087 insertions, 662 deletions
diff --git a/src/H5Dchunk.c b/src/H5Dchunk.c
index 9dcd0ec..f78b8cb 100644
--- a/src/H5Dchunk.c
+++ b/src/H5Dchunk.c
@@ -161,6 +161,13 @@ typedef struct H5D_chunk_it_ud4_t {
unsigned ndims; /* Number of dimensions for chunk/dataset */
} H5D_chunk_it_ud4_t;
+/* Callback info for nonexistent readvv operation */
+typedef struct H5D_chunk_readvv_ud_t {
+ unsigned char *rbuf; /* Read buffer to initialize */
+ H5D_t *dset; /* Dataset to operate on */
+ hid_t dxpl_id; /* DXPL for operation */
+} H5D_chunk_readvv_ud_t;
+
/********************/
/* Local Prototypes */
@@ -4922,6 +4929,55 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5D_nonexistent_readvv_cb
+ *
+ * Purpose: Callback operation for performing fill value I/O operation
+ * on memory buffer.
+ *
+ * Note: This algorithm is pretty inefficient about initializing and
+ * terminating the fill buffer info structure and it would be
+ * faster to refactor this into a "real" initialization routine,
+ * and a "vectorized fill" routine. -QAK
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * 30 Sep 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_nonexistent_readvv_cb(hsize_t UNUSED dst_off, hsize_t src_off, size_t len,
+ void *_udata)
+{
+ H5D_chunk_readvv_ud_t *udata = (H5D_chunk_readvv_ud_t *)_udata; /* User data for H5V_opvv() operator */
+ H5D_fill_buf_info_t fb_info; /* Dataset's fill buffer info */
+ hbool_t fb_info_init = FALSE; /* Whether the fill value buffer has been initialized */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_nonexistent_readvv_cb)
+
+ /* Initialize the fill value buffer */
+ if(H5D_fill_init(&fb_info, (udata->rbuf + src_off), NULL, NULL, NULL, NULL,
+ &udata->dset->shared->dcpl_cache.fill, udata->dset->shared->type,
+ udata->dset->shared->type_id, (size_t)0, len, udata->dxpl_id) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize fill buffer info")
+ fb_info_init = TRUE;
+
+ /* Check for VL datatype & fill the buffer with VL datatype fill values */
+ if(fb_info.has_vlen_fill_type && H5D_fill_refill_vl(&fb_info, fb_info.elmts_per_buf, udata->dxpl_id) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "can't refill fill value buffer")
+
+done:
+ /* Release the fill buffer info, if it's been initialized */
+ if(fb_info_init && H5D_fill_term(&fb_info) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release fill buffer info")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D_nonexistent_readvv_cb() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5D_nonexistent_readvv
*
* Purpose: When the chunk doesn't exist on disk and the chunk is bigger
@@ -4943,80 +4999,35 @@ done:
*/
static ssize_t
H5D_nonexistent_readvv(const H5D_io_info_t *io_info,
- size_t chunk_max_nseq, size_t *chunk_curr_seq, size_t chunk_len_arr[], hsize_t chunk_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[])
+ size_t chunk_max_nseq, size_t *chunk_curr_seq, size_t chunk_len_arr[], hsize_t chunk_off_arr[],
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_off_arr[])
{
- H5D_t *dset = io_info->dset; /* Local pointer to the dataset info */
- H5D_fill_buf_info_t fb_info; /* Dataset's fill buffer info */
- hbool_t fb_info_init = FALSE; /* Whether the fill value buffer has been initialized */
- size_t u, v; /* Local index variables */
- ssize_t ret_value = 0; /* Return value */
+ H5D_chunk_readvv_ud_t udata; /* User data for H5V_opvv() operator */
+ ssize_t ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5D_nonexistent_readvv)
/* Check args */
+ HDassert(io_info);
+ HDassert(chunk_curr_seq);
HDassert(chunk_len_arr);
- HDassert(chunk_offset_arr);
+ HDassert(chunk_off_arr);
+ HDassert(mem_curr_seq);
HDassert(mem_len_arr);
- HDassert(mem_offset_arr);
-
- /* Work through all the sequences */
- for(u = *mem_curr_seq, v = *chunk_curr_seq; u < mem_max_nseq && v < chunk_max_nseq; ) {
- unsigned char *buf; /* Temporary pointer into read buffer */
- size_t size; /* Size of sequence in bytes */
-
- /* Choose smallest buffer to write */
- if(chunk_len_arr[v] < mem_len_arr[u])
- size = chunk_len_arr[v];
- else
- size = mem_len_arr[u];
-
- /* Compute offset in memory */
- buf = (unsigned char *)io_info->u.rbuf + mem_offset_arr[u];
+ HDassert(mem_off_arr);
- /* Initialize the fill value buffer */
- if(H5D_fill_init(&fb_info, buf, NULL, NULL, NULL, NULL,
- &dset->shared->dcpl_cache.fill, dset->shared->type,
- dset->shared->type_id, (size_t)0, size, io_info->dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize fill buffer info")
- fb_info_init = TRUE;
-
- /* Check for VL datatype & fill the buffer with VL datatype fill values */
- if(fb_info.has_vlen_fill_type && H5D_fill_refill_vl(&fb_info, fb_info.elmts_per_buf, io_info->dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "can't refill fill value buffer")
+ /* Set up user data for H5V_opvv() */
+ udata.rbuf = (unsigned char *)io_info->u.rbuf;
+ udata.dset = io_info->dset;
+ udata.dxpl_id = io_info->dxpl_id;
- /* Release the fill buffer info */
- if(H5D_fill_term(&fb_info) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release fill buffer info")
- fb_info_init = FALSE;
-
- /* Update source information */
- chunk_len_arr[v] -= size;
- if(chunk_len_arr[v] == 0)
- v++;
- else
- chunk_offset_arr[v] += size;
-
- /* Update destination information */
- mem_len_arr[u] -= size;
- if(mem_len_arr[u] == 0)
- u++;
- else
- mem_offset_arr[u] += size;
-
- /* Increment number of bytes copied */
- ret_value += (ssize_t)size;
- } /* end for */
-
- /* Update current sequence vectors */
- *mem_curr_seq = u;
- *chunk_curr_seq = v;
+ /* Call generic sequence operation routine */
+ if((ret_value = H5V_opvv(chunk_max_nseq, chunk_curr_seq, chunk_len_arr, chunk_off_arr,
+ mem_max_nseq, mem_curr_seq, mem_len_arr, mem_off_arr,
+ H5D_nonexistent_readvv_cb, &udata)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTOPERATE, FAIL, "can't perform vectorized fill value init")
done:
- /* Release the fill buffer info, if it's been initialized */
- if(fb_info_init && H5D_fill_term(&fb_info) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release fill buffer info")
-
FUNC_LEAVE_NOAPI(ret_value)
} /* H5D_nonexistent_readvv() */
diff --git a/src/H5Dcontig.c b/src/H5Dcontig.c
index 78c07e6..9b4f338 100644
--- a/src/H5Dcontig.c
+++ b/src/H5Dcontig.c
@@ -55,6 +55,40 @@
/* Local Typedefs */
/******************/
+/* Callback info for sieve buffer readvv operation */
+typedef struct H5D_contig_readvv_sieve_ud_t {
+ H5F_t *file; /* File for dataset */
+ H5D_rdcdc_t *dset_contig; /* Cached information about contiguous data */
+ const H5D_contig_storage_t *store_contig; /* Contiguous storage info for this I/O operation */
+ unsigned char *rbuf; /* Pointer to buffer to fill */
+ hid_t dxpl_id; /* DXPL for operation */
+} H5D_contig_readvv_sieve_ud_t;
+
+/* Callback info for [plain] readvv operation */
+typedef struct H5D_contig_readvv_ud_t {
+ H5F_t *file; /* File for dataset */
+ haddr_t dset_addr; /* Address of dataset */
+ unsigned char *rbuf; /* Pointer to buffer to fill */
+ hid_t dxpl_id; /* DXPL for operation */
+} H5D_contig_readvv_ud_t;
+
+/* Callback info for sieve buffer writevv operation */
+typedef struct H5D_contig_writevv_sieve_ud_t {
+ H5F_t *file; /* File for dataset */
+ H5D_rdcdc_t *dset_contig; /* Cached information about contiguous data */
+ const H5D_contig_storage_t *store_contig; /* Contiguous storage info for this I/O operation */
+ const unsigned char *wbuf; /* Pointer to buffer to write */
+ hid_t dxpl_id; /* DXPL for operation */
+} H5D_contig_writevv_sieve_ud_t;
+
+/* Callback info for [plain] writevv operation */
+typedef struct H5D_contig_writevv_ud_t {
+ H5F_t *file; /* File for dataset */
+ haddr_t dset_addr; /* Address of dataset */
+ const unsigned char *wbuf; /* Pointer to buffer to write */
+ hid_t dxpl_id; /* DXPL for operation */
+} H5D_contig_writevv_ud_t;
+
/********************/
/* Local Prototypes */
@@ -65,6 +99,12 @@ static herr_t H5D_contig_construct(H5F_t *f, H5D_t *dset);
static herr_t H5D_contig_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
H5D_chunk_map_t *cm);
+static ssize_t H5D_contig_readvv(const H5D_io_info_t *io_info,
+ 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[]);
+static ssize_t H5D_contig_writevv(const H5D_io_info_t *io_info,
+ 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[]);
static herr_t H5D_contig_flush(H5D_t *dset, hid_t dxpl_id);
/* Helper routines */
@@ -600,572 +640,591 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5D_contig_readvv
+ * Function: H5D_contig_readvv_sieve_cb
*
- * Purpose: Reads some data vectors from a dataset into a buffer.
- * The data is contiguous. 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.
+ * Purpose: Callback operator for H5D_contig_readvv() with sieve buffer.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
- * Friday, May 3, 2001
- *
- * Notes:
- * Offsets in the sequences must be monotonically increasing
+ * Thursday, Sept 30, 2010
*
*-------------------------------------------------------------------------
*/
-ssize_t
-H5D_contig_readvv(const H5D_io_info_t *io_info,
- 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[])
+static herr_t
+H5D_contig_readvv_sieve_cb(hsize_t dst_off, hsize_t src_off, size_t len,
+ void *_udata)
{
- H5F_t *file = io_info->dset->oloc.file; /* File for dataset */
- H5D_rdcdc_t *dset_contig = &(io_info->dset->shared->cache.contig); /* Cached information about contiguous data */
- const H5D_contig_storage_t *store_contig = &(io_info->store->contig); /* Contiguous storage info for this I/O operation */
- unsigned char *buf = (unsigned char *)io_info->u.rbuf; /* Pointer to buffer to fill */
+ H5D_contig_readvv_sieve_ud_t *udata = (H5D_contig_readvv_sieve_ud_t *)_udata; /* User data for H5V_opvv() operator */
+ H5F_t *file = udata->file; /* File for dataset */
+ H5D_rdcdc_t *dset_contig = udata->dset_contig; /* Cached information about contiguous data */
+ const H5D_contig_storage_t *store_contig = udata->store_contig; /* Contiguous storage info for this I/O operation */
+ unsigned char *buf; /* Pointer to buffer to fill */
haddr_t addr; /* Actual address to read */
- size_t size; /* Size of sequence in bytes */
- size_t u, v; /* Counting variables */
- ssize_t ret_value = 0; /* Return value (Total size of sequence in bytes) */
-
- FUNC_ENTER_NOAPI(H5D_contig_readvv, FAIL)
-#ifdef QAK
-HDfprintf(stderr, "%s: dset_max_nseq = %Zu\n", FUNC, dset_max_nseq);
-HDfprintf(stderr, "%s: mem_max_nseq = %Zu\n", FUNC, mem_max_nseq);
-HDfprintf(stderr, "%s: *dset_curr_seq= %Zu\n", FUNC, *dset_curr_seq);
-HDfprintf(stderr, "%s: *mem_curr_seq= %Zu\n", FUNC, *mem_curr_seq);
-for(u = 0; u < dset_max_nseq; u++)
- HDfprintf(stderr, "%s: dset_len_arr[%Zu] = %Zu, dset_offset_arr[%Zu] = %Hu\n", FUNC, u, dset_len_arr[u], u, dset_offset_arr[u]);
-for(u = 0; u < mem_max_nseq; u++)
- HDfprintf(stderr, "%s: mem_len_arr[%Zu] = %Zu, mem_offset_arr[%Zu] = %Hu\n", FUNC, u, mem_len_arr[u], u, mem_offset_arr[u]);
-#endif /* QAK */
+ haddr_t sieve_start = HADDR_UNDEF, sieve_end = HADDR_UNDEF; /* Start & end locations of sieve buffer */
+ haddr_t contig_end; /* End locations of block to write */
+ size_t sieve_size = (size_t)-1; /* Size of sieve buffer */
+ haddr_t rel_eoa; /* Relative end of file address */
+ hsize_t max_data; /* Actual maximum size of data to cache */
+ herr_t ret_value = SUCCEED; /* Return value */
- /* Check args */
- HDassert(io_info);
- HDassert(io_info->dset);
- HDassert(io_info->store);
- HDassert(buf);
+ FUNC_ENTER_NOAPI_NOINIT(H5D_contig_readvv_sieve_cb)
- /* Check if data sieving is enabled */
- if(H5F_HAS_FEATURE(file, H5FD_FEAT_DATA_SIEVE)) {
- haddr_t sieve_start = HADDR_UNDEF, sieve_end = HADDR_UNDEF; /* Start & end locations of sieve buffer */
- haddr_t contig_end; /* End locations of block to write */
- size_t sieve_size = (size_t)-1; /* size of sieve buffer */
- haddr_t rel_eoa; /* Relative end of file address */
- hsize_t max_data; /* Actual maximum size of data to cache */
-
- /* Set offsets in sequence lists */
- u = *dset_curr_seq;
- v = *mem_curr_seq;
-
- /* Stash local copies of these value */
- if(dset_contig->sieve_buf != NULL) {
- sieve_start = dset_contig->sieve_loc;
- sieve_size = dset_contig->sieve_size;
- sieve_end = sieve_start+sieve_size;
+ /* Stash local copies of these value */
+ if(dset_contig->sieve_buf != NULL) {
+ sieve_start = dset_contig->sieve_loc;
+ sieve_size = dset_contig->sieve_size;
+ sieve_end = sieve_start + sieve_size;
+ } /* end if */
+
+ /* Compute offset on disk */
+ addr = store_contig->dset_addr + dst_off;
+
+ /* Compute offset in memory */
+ buf = udata->rbuf + src_off;
+
+ /* Check if the sieve buffer is allocated yet */
+ if(NULL == dset_contig->sieve_buf) {
+ /* Check if we can actually hold the I/O request in the sieve buffer */
+ if(len > dset_contig->sieve_buf_size) {
+ if(H5F_block_read(file, H5FD_MEM_DRAW, addr, len, udata->dxpl_id, buf) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "block read failed")
} /* end if */
+ else {
+ /* Allocate room for the data sieve buffer */
+ if(NULL == (dset_contig->sieve_buf = H5FL_BLK_MALLOC(sieve_buf, dset_contig->sieve_buf_size)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "memory allocation failed")
- /* 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];
+ /* Determine the new sieve buffer size & location */
+ dset_contig->sieve_loc = addr;
- /* Compute offset on disk */
- addr = store_contig->dset_addr + dset_offset_arr[u];
+ /* Make certain we don't read off the end of the file */
+ if(HADDR_UNDEF == (rel_eoa = H5F_get_eoa(file, H5FD_MEM_DRAW)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to determine file size")
- /* Compute offset in memory */
- buf = (unsigned char *)io_info->u.rbuf + mem_offset_arr[v];
+ /* Set up the buffer parameters */
+ max_data = store_contig->dset_size - dst_off;
- /* Check if the sieve buffer is allocated yet */
- if(dset_contig->sieve_buf == NULL) {
- /* Check if we can actually hold the I/O request in the sieve buffer */
- if(size>dset_contig->sieve_buf_size) {
- if(H5F_block_read(file, H5FD_MEM_DRAW, addr, size, io_info->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 == (dset_contig->sieve_buf = H5FL_BLK_MALLOC(sieve_buf, dset_contig->sieve_buf_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ /* Compute the size of the sieve buffer */
+ H5_ASSIGN_OVERFLOW(dset_contig->sieve_size, MIN3(rel_eoa - dset_contig->sieve_loc, max_data, dset_contig->sieve_buf_size), hsize_t, size_t);
- /* Determine the new sieve buffer size & location */
- dset_contig->sieve_loc = addr;
+ /* Read the new sieve buffer */
+ if(H5F_block_read(file, H5FD_MEM_DRAW, dset_contig->sieve_loc, dset_contig->sieve_size, udata->dxpl_id, dset_contig->sieve_buf) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "block read failed")
- /* Make certain we don't read off the end of the file */
- if(HADDR_UNDEF == (rel_eoa = H5F_get_eoa(file, H5FD_MEM_DRAW)))
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size")
+ /* Grab the data out of the buffer (must be first piece of data in buffer ) */
+ HDmemcpy(buf, dset_contig->sieve_buf, len);
- /* Set up the buffer parameters */
- max_data = store_contig->dset_size - dset_offset_arr[u];
+ /* Reset sieve buffer dirty flag */
+ dset_contig->sieve_dirty = FALSE;
- /* Compute the size of the sieve buffer */
- H5_ASSIGN_OVERFLOW(dset_contig->sieve_size, MIN3(rel_eoa - dset_contig->sieve_loc, max_data, dset_contig->sieve_buf_size), hsize_t, size_t);
+ /* Stash local copies of these value */
+ sieve_start = dset_contig->sieve_loc;
+ sieve_size = dset_contig->sieve_size;
+ sieve_end = sieve_start+sieve_size;
+ } /* end else */
+ } /* end if */
+ else {
+ /* Compute end of sequence to retrieve */
+ contig_end = addr + len - 1;
- /* Read the new sieve buffer */
- if(H5F_block_read(file, H5FD_MEM_DRAW, dset_contig->sieve_loc, dset_contig->sieve_size, io_info->dxpl_id, dset_contig->sieve_buf) < 0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed")
+ /* 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 = dset_contig->sieve_buf + (addr - sieve_start);
- /* Grab the data out of the buffer (must be first piece of data in buffer ) */
- HDmemcpy(buf, dset_contig->sieve_buf, size);
+ /* Grab the data out of the buffer */
+ HDmemcpy(buf, base_sieve_buf, len);
+ } /* 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(len > dset_contig->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(dset_contig->sieve_dirty) {
+ /* Write to file */
+ if(H5F_block_write(file, H5FD_MEM_DRAW, sieve_start, sieve_size, udata->dxpl_id, dset_contig->sieve_buf) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "block write failed")
- /* Reset sieve buffer dirty flag */
- dset_contig->sieve_dirty = 0;
+ /* Reset sieve buffer dirty flag */
+ dset_contig->sieve_dirty = FALSE;
+ } /* end if */
+ } /* end if */
- /* Stash local copies of these value */
- sieve_start = dset_contig->sieve_loc;
- sieve_size = dset_contig->sieve_size;
- sieve_end = sieve_start+sieve_size;
- } /* end else */
+ /* Read directly into the user's buffer */
+ if(H5F_block_read(file, H5FD_MEM_DRAW, addr, len, udata->dxpl_id, buf) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "block read failed")
} /* end if */
+ /* Element size fits within the buffer size */
else {
- /* 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=dset_contig->sieve_buf+(addr-sieve_start);
+ /* Flush the sieve buffer if it's dirty */
+ if(dset_contig->sieve_dirty) {
+ /* Write to file */
+ if(H5F_block_write(file, H5FD_MEM_DRAW, sieve_start, sieve_size, udata->dxpl_id, dset_contig->sieve_buf) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "block write failed")
- /* Grab the data out of the buffer */
- HDmemcpy(buf, base_sieve_buf, size);
+ /* Reset sieve buffer dirty flag */
+ dset_contig->sieve_dirty = FALSE;
} /* 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>dset_contig->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(dset_contig->sieve_dirty) {
- /* Write to file */
- if(H5F_block_write(file, H5FD_MEM_DRAW, sieve_start, sieve_size, io_info->dxpl_id, dset_contig->sieve_buf) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed")
-
- /* Reset sieve buffer dirty flag */
- dset_contig->sieve_dirty = 0;
- } /* end if */
- } /* end if */
-
- /* Read directly into the user's buffer */
- if(H5F_block_read(file, H5FD_MEM_DRAW, addr, size, io_info->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(dset_contig->sieve_dirty) {
- /* Write to file */
- if(H5F_block_write(file, H5FD_MEM_DRAW, sieve_start, sieve_size, io_info->dxpl_id, dset_contig->sieve_buf) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed")
- /* Reset sieve buffer dirty flag */
- dset_contig->sieve_dirty = 0;
- } /* end if */
+ /* Determine the new sieve buffer size & location */
+ dset_contig->sieve_loc = addr;
- /* Determine the new sieve buffer size & location */
- dset_contig->sieve_loc = addr;
-
- /* Make certain we don't read off the end of the file */
- if(HADDR_UNDEF == (rel_eoa = H5F_get_eoa(file, H5FD_MEM_DRAW)))
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size")
+ /* Make certain we don't read off the end of the file */
+ if(HADDR_UNDEF == (rel_eoa = H5F_get_eoa(file, H5FD_MEM_DRAW)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to determine file size")
- /* Only need this when resizing sieve buffer */
- max_data = store_contig->dset_size - dset_offset_arr[u];
+ /* Only need this when resizing sieve buffer */
+ max_data = store_contig->dset_size - dst_off;
- /* 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(dset_contig->sieve_size, MIN3(rel_eoa - dset_contig->sieve_loc, max_data, dset_contig->sieve_buf_size), hsize_t, size_t);
+ /* 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(dset_contig->sieve_size, MIN3(rel_eoa - dset_contig->sieve_loc, max_data, dset_contig->sieve_buf_size), hsize_t, size_t);
- /* Update local copies of sieve information */
- sieve_start = dset_contig->sieve_loc;
- sieve_size = dset_contig->sieve_size;
- sieve_end = sieve_start + sieve_size;
+ /* Update local copies of sieve information */
+ sieve_start = dset_contig->sieve_loc;
+ sieve_size = dset_contig->sieve_size;
+ sieve_end = sieve_start + sieve_size;
- /* Read the new sieve buffer */
- if(H5F_block_read(file, H5FD_MEM_DRAW, dset_contig->sieve_loc, dset_contig->sieve_size, io_info->dxpl_id, dset_contig->sieve_buf) < 0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed")
+ /* Read the new sieve buffer */
+ if(H5F_block_read(file, H5FD_MEM_DRAW, dset_contig->sieve_loc, dset_contig->sieve_size, udata->dxpl_id, dset_contig->sieve_buf) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "block read failed")
- /* Grab the data out of the buffer (must be first piece of data in buffer ) */
- HDmemcpy(buf, dset_contig->sieve_buf, size);
+ /* Grab the data out of the buffer (must be first piece of data in buffer ) */
+ HDmemcpy(buf, dset_contig->sieve_buf, len);
- /* Reset sieve buffer dirty flag */
- dset_contig->sieve_dirty = 0;
- } /* end else */
- } /* end else */
+ /* Reset sieve buffer dirty flag */
+ dset_contig->sieve_dirty = FALSE;
} /* end else */
+ } /* end else */
+ } /* end else */
- /* Update memory information */
- mem_len_arr[v] -= size;
- if(mem_len_arr[v] == 0)
- v++;
- else
- mem_offset_arr[v] += size;
-
- /* Update file information */
- dset_len_arr[u] -= size;
- if(dset_len_arr[u] == 0)
- u++;
- else
- dset_offset_arr[u] += size;
-
- /* Increment number of bytes copied */
- ret_value += (ssize_t)size;
- } /* end for */
- } /* end if */
- else {
- /* Work through all the sequences */
- 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];
-
- /* Compute offset on disk */
- addr = store_contig->dset_addr + dset_offset_arr[u];
-
- /* Compute offset in memory */
- buf = (unsigned char *)io_info->u.rbuf + mem_offset_arr[v];
-
- /* Write data */
- if(H5F_block_read(file, H5FD_MEM_DRAW, addr, size, io_info->dxpl_id, buf) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed")
-
- /* Update memory information */
- mem_len_arr[v] -= size;
- if(mem_len_arr[v] == 0)
- v++;
- else
- mem_offset_arr[v] += size;
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_contig_readvv_sieve_cb() */
- /* Update file information */
- dset_len_arr[u] -= size;
- if(dset_len_arr[u] == 0)
- u++;
- else
- dset_offset_arr[u] += size;
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_contig_readvv_cb
+ *
+ * Purpose: Callback operator for H5D_contig_readvv() without sieve buffer.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, Sept 30, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_contig_readvv_cb(hsize_t dst_off, hsize_t src_off, size_t len, void *_udata)
+{
+ H5D_contig_readvv_ud_t *udata = (H5D_contig_readvv_ud_t *)_udata; /* User data for H5V_opvv() operator */
+ herr_t ret_value = SUCCEED; /* Return value */
- /* Increment number of bytes copied */
- ret_value += (ssize_t)size;
- } /* end for */
- } /* end else */
+ FUNC_ENTER_NOAPI_NOINIT(H5D_contig_readvv_cb)
- /* Update current sequence vectors */
- *dset_curr_seq = u;
- *mem_curr_seq = v;
+ /* Write data */
+ if(H5F_block_read(udata->file, H5FD_MEM_DRAW, (udata->dset_addr + dst_off),
+ len, udata->dxpl_id, (udata->rbuf + src_off)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "block write failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_contig_readvv() */
+} /* end H5D_contig_readvv_cb() */
/*-------------------------------------------------------------------------
- * Function: H5D_contig_writevv
+ * Function: H5D_contig_readvv
*
- * Purpose: Writes some data vectors into a dataset from vectors into a
- * buffer. The address is the start of the dataset,
+ * Purpose: Reads some data vectors from a dataset into a buffer.
+ * The data is contiguous. 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
- * Friday, May 2, 2003
+ * Friday, May 3, 2001
*
* Notes:
* Offsets in the sequences must be monotonically increasing
*
*-------------------------------------------------------------------------
*/
-ssize_t
-H5D_contig_writevv(const H5D_io_info_t *io_info,
- 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[])
+static ssize_t
+H5D_contig_readvv(const H5D_io_info_t *io_info,
+ size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_off_arr[],
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_off_arr[])
{
- H5F_t *file = io_info->dset->oloc.file; /* File for dataset */
- H5D_rdcdc_t *dset_contig = &(io_info->dset->shared->cache.contig); /* Cached information about contiguous data */
- const H5D_contig_storage_t *store_contig = &(io_info->store->contig); /* Contiguous storage info for this I/O operation */
- const unsigned char *buf = (const unsigned char *)io_info->u.wbuf; /* Pointer to buffer to fill */
- haddr_t addr; /* Actual address to read */
- size_t size; /* Size of sequence in bytes */
- size_t u, v; /* Counting variables */
- ssize_t ret_value = 0; /* Return value (Size of sequence in bytes) */
+ ssize_t ret_value; /* Return value */
- FUNC_ENTER_NOAPI(H5D_contig_writevv, FAIL)
+ FUNC_ENTER_NOAPI_NOINIT(H5D_contig_readvv)
/* Check args */
HDassert(io_info);
- HDassert(io_info->dset);
- HDassert(io_info->store);
- HDassert(buf);
+ HDassert(dset_curr_seq);
+ HDassert(dset_len_arr);
+ HDassert(dset_off_arr);
+ HDassert(mem_curr_seq);
+ HDassert(mem_len_arr);
+ HDassert(mem_off_arr);
/* Check if data sieving is enabled */
- if(H5F_HAS_FEATURE(file, H5FD_FEAT_DATA_SIEVE)) {
- haddr_t sieve_start = HADDR_UNDEF, sieve_end = HADDR_UNDEF; /* Start & end locations of sieve buffer */
- haddr_t contig_end; /* End locations of block to write */
- size_t sieve_size = (size_t)-1; /* size of sieve buffer */
- haddr_t rel_eoa; /* Relative end of file address */
- hsize_t max_data; /* Actual maximum size of data to cache */
-
- /* Set offsets in sequence lists */
- u = *dset_curr_seq;
- v = *mem_curr_seq;
-
- /* Stash local copies of these values */
- if(dset_contig->sieve_buf != NULL) {
+ if(H5F_HAS_FEATURE(io_info->dset->oloc.file, H5FD_FEAT_DATA_SIEVE)) {
+ H5D_contig_readvv_sieve_ud_t udata; /* User data for H5V_opvv() operator */
+
+ /* Set up user data for H5V_opvv() */
+ udata.file = io_info->dset->oloc.file;
+ udata.dset_contig = &(io_info->dset->shared->cache.contig);
+ udata.store_contig = &(io_info->store->contig);
+ udata.rbuf = (unsigned char *)io_info->u.rbuf;
+ udata.dxpl_id = io_info->dxpl_id;
+
+ /* Call generic sequence operation routine */
+ if((ret_value = H5V_opvv(dset_max_nseq, dset_curr_seq, dset_len_arr, dset_off_arr,
+ mem_max_nseq, mem_curr_seq, mem_len_arr, mem_off_arr,
+ H5D_contig_readvv_sieve_cb, &udata)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTOPERATE, FAIL, "can't perform vectorized sieve buffer read")
+ } /* end if */
+ else {
+ H5D_contig_readvv_ud_t udata; /* User data for H5V_opvv() operator */
+
+ /* Set up user data for H5V_opvv() */
+ udata.file = io_info->dset->oloc.file;
+ udata.dset_addr = io_info->store->contig.dset_addr;
+ udata.rbuf = (unsigned char *)io_info->u.rbuf;
+ udata.dxpl_id = io_info->dxpl_id;
+
+ /* Call generic sequence operation routine */
+ if((ret_value = H5V_opvv(dset_max_nseq, dset_curr_seq, dset_len_arr, dset_off_arr,
+ mem_max_nseq, mem_curr_seq, mem_len_arr, mem_off_arr,
+ H5D_contig_readvv_cb, &udata)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTOPERATE, FAIL, "can't perform vectorized read")
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_contig_readvv() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_contig_writevv_sieve_cb
+ *
+ * Purpose: Callback operator for H5D_contig_writevv() with sieve buffer.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, Sept 30, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_contig_writevv_sieve_cb(hsize_t dst_off, hsize_t src_off, size_t len,
+ void *_udata)
+{
+ H5D_contig_writevv_sieve_ud_t *udata = (H5D_contig_writevv_sieve_ud_t *)_udata; /* User data for H5V_opvv() operator */
+ H5F_t *file = udata->file; /* File for dataset */
+ H5D_rdcdc_t *dset_contig = udata->dset_contig; /* Cached information about contiguous data */
+ const H5D_contig_storage_t *store_contig = udata->store_contig; /* Contiguous storage info for this I/O operation */
+ const unsigned char *buf; /* Pointer to buffer to fill */
+ haddr_t addr; /* Actual address to read */
+ haddr_t sieve_start = HADDR_UNDEF, sieve_end = HADDR_UNDEF; /* Start & end locations of sieve buffer */
+ haddr_t contig_end; /* End locations of block to write */
+ size_t sieve_size = (size_t)-1; /* size of sieve buffer */
+ haddr_t rel_eoa; /* Relative end of file address */
+ hsize_t max_data; /* Actual maximum size of data to cache */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_contig_writevv_sieve_cb)
+
+ /* Stash local copies of these values */
+ if(dset_contig->sieve_buf != NULL) {
+ sieve_start = dset_contig->sieve_loc;
+ sieve_size = dset_contig->sieve_size;
+ sieve_end = sieve_start + sieve_size;
+ } /* end if */
+
+ /* Compute offset on disk */
+ addr = store_contig->dset_addr + dst_off;
+
+ /* Compute offset in memory */
+ buf = udata->wbuf + src_off;
+
+ /* No data sieve buffer yet, go allocate one */
+ if(NULL == dset_contig->sieve_buf) {
+ /* Check if we can actually hold the I/O request in the sieve buffer */
+ if(len > dset_contig->sieve_buf_size) {
+ if(H5F_block_write(file, H5FD_MEM_DRAW, addr, len, udata->dxpl_id, buf) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "block write failed")
+ } /* end if */
+ else {
+ /* Allocate room for the data sieve buffer */
+ if(NULL == (dset_contig->sieve_buf = H5FL_BLK_MALLOC(sieve_buf, dset_contig->sieve_buf_size)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "memory allocation failed")
+#ifdef H5_CLEAR_MEMORY
+if(dset_contig->sieve_size > len)
+ HDmemset(dset_contig->sieve_buf + len, 0, (dset_contig->sieve_size - len));
+#endif /* H5_CLEAR_MEMORY */
+
+ /* Determine the new sieve buffer size & location */
+ dset_contig->sieve_loc = addr;
+
+ /* Make certain we don't read off the end of the file */
+ if(HADDR_UNDEF == (rel_eoa = H5F_get_eoa(file, H5FD_MEM_DRAW)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to determine file size")
+
+ /* Set up the buffer parameters */
+ max_data = store_contig->dset_size - dst_off;
+
+ /* Compute the size of the sieve buffer */
+ H5_ASSIGN_OVERFLOW(dset_contig->sieve_size, MIN3(rel_eoa - dset_contig->sieve_loc, max_data, dset_contig->sieve_buf_size), hsize_t, size_t);
+
+ /* Check if there is any point in reading the data from the file */
+ if(dset_contig->sieve_size > len) {
+ /* Read the new sieve buffer */
+ if(H5F_block_read(file, H5FD_MEM_DRAW, dset_contig->sieve_loc, dset_contig->sieve_size, udata->dxpl_id, dset_contig->sieve_buf) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "block read failed")
+ } /* end if */
+
+ /* Grab the data out of the buffer (must be first piece of data in buffer ) */
+ HDmemcpy(dset_contig->sieve_buf, buf, len);
+
+ /* Set sieve buffer dirty flag */
+ dset_contig->sieve_dirty = TRUE;
+
+ /* Stash local copies of these values */
sieve_start = dset_contig->sieve_loc;
sieve_size = dset_contig->sieve_size;
sieve_end = sieve_start + sieve_size;
+ } /* end else */
+ } /* end if */
+ else {
+ /* Compute end of sequence to retrieve */
+ contig_end = addr + len - 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 = dset_contig->sieve_buf + (addr - sieve_start);
+
+ /* Put the data into the sieve buffer */
+ HDmemcpy(base_sieve_buf, buf, len);
+
+ /* Set sieve buffer dirty flag */
+ dset_contig->sieve_dirty = TRUE;
} /* 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(len > dset_contig->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(dset_contig->sieve_dirty) {
+ /* Write to file */
+ if(H5F_block_write(file, H5FD_MEM_DRAW, sieve_start, sieve_size, udata->dxpl_id, dset_contig->sieve_buf) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "block write failed")
- /* 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];
+ /* Reset sieve buffer dirty flag */
+ dset_contig->sieve_dirty = FALSE;
+ } /* end if */
- /* Compute offset on disk */
- addr = store_contig->dset_addr + dset_offset_arr[u];
+ /* Force the sieve buffer to be re-read the next time */
+ dset_contig->sieve_loc = HADDR_UNDEF;
+ dset_contig->sieve_size = 0;
+ } /* end if */
+
+ /* Write directly from the user's buffer */
+ if(H5F_block_write(file, H5FD_MEM_DRAW, addr, len, udata->dxpl_id, buf) < 0)
+ HGOTO_ERROR(H5E_DATASET, 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 + len) == sieve_start || addr == sieve_end) &&
+ (len + sieve_size) <= dset_contig->sieve_buf_size &&
+ dset_contig->sieve_dirty) {
+ /* Prepend to existing sieve buffer */
+ if((addr + len) == sieve_start) {
+ /* Move existing sieve information to correct location */
+ HDmemmove(dset_contig->sieve_buf + len, dset_contig->sieve_buf, dset_contig->sieve_size);
+
+ /* Copy in new information (must be first in sieve buffer) */
+ HDmemcpy(dset_contig->sieve_buf, buf, len);
+
+ /* Adjust sieve location */
+ dset_contig->sieve_loc = addr;
- /* Compute offset in memory */
- buf = (const unsigned char *)io_info->u.wbuf + mem_offset_arr[v];
+ } /* end if */
+ /* Append to existing sieve buffer */
+ else {
+ /* Copy in new information */
+ HDmemcpy(dset_contig->sieve_buf + sieve_size, buf, len);
+ } /* end else */
- /* No data sieve buffer yet, go allocate one */
- if(NULL == dset_contig->sieve_buf) {
- /* Check if we can actually hold the I/O request in the sieve buffer */
- if(size>dset_contig->sieve_buf_size) {
- if(H5F_block_write(file, H5FD_MEM_DRAW, addr, size, io_info->dxpl_id, buf) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed")
+ /* Adjust sieve size */
+ dset_contig->sieve_size += len;
+
+ /* Update local copies of sieve information */
+ sieve_start = dset_contig->sieve_loc;
+ sieve_size = dset_contig->sieve_size;
+ sieve_end = sieve_start + sieve_size;
} /* end if */
+ /* Can't add the new data onto the existing sieve buffer */
else {
- /* Allocate room for the data sieve buffer */
- if(NULL == (dset_contig->sieve_buf = H5FL_BLK_MALLOC(sieve_buf, dset_contig->sieve_buf_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
-#ifdef H5_CLEAR_MEMORY
-if(dset_contig->sieve_size > size)
- HDmemset(dset_contig->sieve_buf + size, 0, (dset_contig->sieve_size - size));
-#endif /* H5_CLEAR_MEMORY */
+ /* Flush the sieve buffer if it's dirty */
+ if(dset_contig->sieve_dirty) {
+ /* Write to file */
+ if(H5F_block_write(file, H5FD_MEM_DRAW, sieve_start, sieve_size, udata->dxpl_id, dset_contig->sieve_buf) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "block write failed")
+
+ /* Reset sieve buffer dirty flag */
+ dset_contig->sieve_dirty = FALSE;
+ } /* end if */
/* Determine the new sieve buffer size & location */
dset_contig->sieve_loc = addr;
/* Make certain we don't read off the end of the file */
if(HADDR_UNDEF == (rel_eoa = H5F_get_eoa(file, H5FD_MEM_DRAW)))
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size")
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to determine file size")
- /* Set up the buffer parameters */
- max_data = store_contig->dset_size - dset_offset_arr[u];
+ /* Only need this when resizing sieve buffer */
+ max_data = store_contig->dset_size - dst_off;
/* 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(dset_contig->sieve_size, MIN3(rel_eoa - dset_contig->sieve_loc, max_data, dset_contig->sieve_buf_size), hsize_t, size_t);
- /* Check if there is any point in reading the data from the file */
- if(dset_contig->sieve_size>size) {
- /* Read the new sieve buffer */
- if(H5F_block_read(file, H5FD_MEM_DRAW, dset_contig->sieve_loc, dset_contig->sieve_size, io_info->dxpl_id, dset_contig->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(dset_contig->sieve_buf, buf, size);
-
- /* Set sieve buffer dirty flag */
- dset_contig->sieve_dirty = 1;
-
- /* Stash local copies of these values */
+ /* Update local copies of sieve information */
sieve_start = dset_contig->sieve_loc;
sieve_size = dset_contig->sieve_size;
sieve_end = sieve_start + sieve_size;
- } /* end else */
- } /* end if */
- else {
- /* 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 = dset_contig->sieve_buf + (addr - sieve_start);
+ /* Check if there is any point in reading the data from the file */
+ if(dset_contig->sieve_size > len) {
+ /* Read the new sieve buffer */
+ if(H5F_block_read(file, H5FD_MEM_DRAW, dset_contig->sieve_loc, dset_contig->sieve_size, udata->dxpl_id, dset_contig->sieve_buf) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "block read failed")
+ } /* end if */
- /* Put the data into the sieve buffer */
- HDmemcpy(base_sieve_buf, buf, size);
+ /* Grab the data out of the buffer (must be first piece of data in buffer ) */
+ HDmemcpy(dset_contig->sieve_buf, buf, len);
/* Set sieve buffer dirty flag */
- dset_contig->sieve_dirty = 1;
- } /* 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>dset_contig->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(dset_contig->sieve_dirty) {
- /* Write to file */
- if(H5F_block_write(file, H5FD_MEM_DRAW, sieve_start, sieve_size, io_info->dxpl_id, dset_contig->sieve_buf) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed")
-
- /* Reset sieve buffer dirty flag */
- dset_contig->sieve_dirty = 0;
- } /* end if */
-
- /* Force the sieve buffer to be re-read the next time */
- dset_contig->sieve_loc = HADDR_UNDEF;
- dset_contig->sieve_size = 0;
- } /* end if */
-
- /* Write directly from the user's buffer */
- if(H5F_block_write(file, H5FD_MEM_DRAW, addr, size, io_info->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) <= dset_contig->sieve_buf_size &&
- dset_contig->sieve_dirty) {
- /* Prepend to existing sieve buffer */
- if((addr + size) == sieve_start) {
- /* Move existing sieve information to correct location */
- HDmemmove(dset_contig->sieve_buf + size, dset_contig->sieve_buf, dset_contig->sieve_size);
-
- /* Copy in new information (must be first in sieve buffer) */
- HDmemcpy(dset_contig->sieve_buf, buf, size);
-
- /* Adjust sieve location */
- dset_contig->sieve_loc = addr;
-
- } /* end if */
- /* Append to existing sieve buffer */
- else {
- /* Copy in new information */
- HDmemcpy(dset_contig->sieve_buf + sieve_size, buf, size);
- } /* end else */
-
- /* Adjust sieve size */
- dset_contig->sieve_size += size;
-
- /* Update local copies of sieve information */
- sieve_start = dset_contig->sieve_loc;
- sieve_size = dset_contig->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(dset_contig->sieve_dirty) {
- /* Write to file */
- if(H5F_block_write(file, H5FD_MEM_DRAW, sieve_start, sieve_size, io_info->dxpl_id, dset_contig->sieve_buf) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed")
-
- /* Reset sieve buffer dirty flag */
- dset_contig->sieve_dirty = 0;
- } /* end if */
-
- /* Determine the new sieve buffer size & location */
- dset_contig->sieve_loc = addr;
-
- /* Make certain we don't read off the end of the file */
- if(HADDR_UNDEF == (rel_eoa = H5F_get_eoa(file, H5FD_MEM_DRAW)))
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size")
-
- /* Only need this when resizing sieve buffer */
- max_data = store_contig->dset_size - 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(dset_contig->sieve_size, MIN3(rel_eoa - dset_contig->sieve_loc, max_data, dset_contig->sieve_buf_size), hsize_t, size_t);
-
- /* Update local copies of sieve information */
- sieve_start = dset_contig->sieve_loc;
- sieve_size = dset_contig->sieve_size;
- sieve_end = sieve_start + sieve_size;
-
- /* Check if there is any point in reading the data from the file */
- if(dset_contig->sieve_size > size) {
- /* Read the new sieve buffer */
- if(H5F_block_read(file, H5FD_MEM_DRAW, dset_contig->sieve_loc, dset_contig->sieve_size, io_info->dxpl_id, dset_contig->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(dset_contig->sieve_buf, buf, size);
-
- /* Set sieve buffer dirty flag */
- dset_contig->sieve_dirty = 1;
- } /* end else */
- } /* end else */
+ dset_contig->sieve_dirty = TRUE;
} /* end else */
} /* end else */
+ } /* end else */
+ } /* end else */
- /* Update memory information */
- mem_len_arr[v] -= size;
- if(mem_len_arr[v] == 0)
- v++;
- else
- mem_offset_arr[v] += size;
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_contig_writevv_sieve_cb() */
- /* Update file information */
- dset_len_arr[u] -= size;
- if(dset_len_arr[u] == 0)
- u++;
- else
- dset_offset_arr[u] += size;
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_contig_writevv_cb
+ *
+ * Purpose: Callback operator for H5D_contig_writevv().
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, Sept 30, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_contig_writevv_cb(hsize_t dst_off, hsize_t src_off, size_t len, void *_udata)
+{
+ H5D_contig_writevv_ud_t *udata = (H5D_contig_writevv_ud_t *)_udata; /* User data for H5V_opvv() operator */
+ herr_t ret_value = SUCCEED; /* Return value */
- /* Increment number of bytes copied */
- ret_value += (ssize_t)size;
- } /* end for */
- } /* end if */
- else {
- /* Work through all the sequences */
- 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];
+ FUNC_ENTER_NOAPI_NOINIT(H5D_contig_writevv_cb)
- /* Compute offset on disk */
- addr = store_contig->dset_addr + dset_offset_arr[u];
+ /* Write data */
+ if(H5F_block_write(udata->file, H5FD_MEM_DRAW, (udata->dset_addr + dst_off), len, udata->dxpl_id, (udata->wbuf + src_off)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "block write failed")
- /* Compute offset in memory */
- buf = (const unsigned char *)io_info->u.wbuf + mem_offset_arr[v];
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_contig_writevv_cb() */
- /* Write data */
- if(H5F_block_write(file, H5FD_MEM_DRAW, addr, size, io_info->dxpl_id, buf) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed")
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_contig_writevv
+ *
+ * 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
+ * Friday, May 2, 2003
+ *
+ * Notes:
+ * Offsets in the sequences must be monotonically increasing
+ *
+ *-------------------------------------------------------------------------
+ */
+static ssize_t
+H5D_contig_writevv(const H5D_io_info_t *io_info,
+ size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_off_arr[],
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_off_arr[])
+{
+ ssize_t ret_value; /* Return value (Size of sequence in bytes) */
- /* Update memory information */
- mem_len_arr[v] -= size;
- if(mem_len_arr[v] == 0)
- v++;
- else
- mem_offset_arr[v] += size;
+ FUNC_ENTER_NOAPI_NOINIT(H5D_contig_writevv)
- /* Update file information */
- dset_len_arr[u] -= size;
- if(dset_len_arr[u] == 0)
- u++;
- else
- dset_offset_arr[u] += size;
+ /* Check args */
+ HDassert(io_info);
+ HDassert(dset_curr_seq);
+ HDassert(dset_len_arr);
+ HDassert(dset_off_arr);
+ HDassert(mem_curr_seq);
+ HDassert(mem_len_arr);
+ HDassert(mem_off_arr);
- /* Increment number of bytes copied */
- ret_value += (ssize_t)size;
- } /* end for */
+ /* Check if data sieving is enabled */
+ if(H5F_HAS_FEATURE(io_info->dset->oloc.file, H5FD_FEAT_DATA_SIEVE)) {
+ H5D_contig_writevv_sieve_ud_t udata; /* User data for H5V_opvv() operator */
+
+ /* Set up user data for H5V_opvv() */
+ udata.file = io_info->dset->oloc.file;
+ udata.dset_contig = &(io_info->dset->shared->cache.contig);
+ udata.store_contig = &(io_info->store->contig);
+ udata.wbuf = (const unsigned char *)io_info->u.wbuf;
+ udata.dxpl_id = io_info->dxpl_id;
+
+ /* Call generic sequence operation routine */
+ if((ret_value = H5V_opvv(dset_max_nseq, dset_curr_seq, dset_len_arr, dset_off_arr,
+ mem_max_nseq, mem_curr_seq, mem_len_arr, mem_off_arr,
+ H5D_contig_writevv_sieve_cb, &udata)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTOPERATE, FAIL, "can't perform vectorized sieve buffer write")
+ } /* end if */
+ else {
+ H5D_contig_writevv_ud_t udata; /* User data for H5V_opvv() operator */
+
+ /* Set up user data for H5V_opvv() */
+ udata.file = io_info->dset->oloc.file;
+ udata.dset_addr = io_info->store->contig.dset_addr;
+ udata.wbuf = (const unsigned char *)io_info->u.wbuf;
+ udata.dxpl_id = io_info->dxpl_id;
+
+ /* Call generic sequence operation routine */
+ if((ret_value = H5V_opvv(dset_max_nseq, dset_curr_seq, dset_len_arr, dset_off_arr,
+ mem_max_nseq, mem_curr_seq, mem_len_arr, mem_off_arr,
+ H5D_contig_writevv_cb, &udata)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTOPERATE, FAIL, "can't perform vectorized read")
} /* end else */
- /* Update current sequence vectors */
- *dset_curr_seq = u;
- *mem_curr_seq = v;
-
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_contig_writevv() */
diff --git a/src/H5Defl.c b/src/H5Defl.c
index 87471f1..bcb47a2 100644
--- a/src/H5Defl.c
+++ b/src/H5Defl.c
@@ -33,6 +33,7 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5Fprivate.h" /* Files */
#include "H5HLprivate.h" /* Local Heaps */
+#include "H5Vprivate.h" /* Vector and array functions */
/****************/
@@ -44,6 +45,18 @@
/* Local Typedefs */
/******************/
+/* Callback info for readvv operation */
+typedef struct H5D_efl_readvv_ud_t {
+ const H5O_efl_t *efl; /* Pointer to efl info */
+ unsigned char *rbuf; /* Read buffer */
+} H5D_efl_readvv_ud_t;
+
+/* Callback info for writevv operation */
+typedef struct H5D_efl_writevv_ud_t {
+ const H5O_efl_t *efl; /* Pointer to efl info */
+ const unsigned char *wbuf; /* Write buffer */
+} H5D_efl_writevv_ud_t;
+
/********************/
/* Local Prototypes */
@@ -398,6 +411,35 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5D_efl_readvv_cb
+ *
+ * Purpose: Callback operator for H5D_efl_readvv().
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, Sept 30, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_efl_readvv_cb(hsize_t dst_off, hsize_t src_off, size_t len, void *_udata)
+{
+ H5D_efl_readvv_ud_t *udata = (H5D_efl_readvv_ud_t *)_udata; /* User data for H5V_opvv() operator */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_efl_readvv_cb)
+
+ /* Read data */
+ if(H5D_efl_read(udata->efl, dst_off, len, (udata->rbuf + src_off)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "EFL read failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_efl_readvv_cb() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5D_efl_readvv
*
* Purpose: Reads data from an external file list. It is an error to
@@ -414,65 +456,67 @@ done:
*/
static ssize_t
H5D_efl_readvv(const H5D_io_info_t *io_info,
- 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[])
+ size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_off_arr[],
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_off_arr[])
{
- const H5O_efl_t *efl = &(io_info->store->efl); /* Pointer to efl info */
- unsigned char *buf; /* Pointer to buffer to write */
- haddr_t addr; /* Actual address to read */
- size_t size; /* Size of sequence in bytes */
- size_t u, v; /* Counting variables */
- ssize_t ret_value = 0; /* Return value (Total size of sequence in bytes) */
+ H5D_efl_readvv_ud_t udata; /* User data for H5V_opvv() operator */
+ ssize_t ret_value; /* Return value (Total size of sequence in bytes) */
FUNC_ENTER_NOAPI_NOINIT(H5D_efl_readvv)
/* Check args */
- HDassert(efl && efl->nused > 0);
+ HDassert(io_info);
+ HDassert(io_info->store->efl.nused > 0);
HDassert(io_info->u.rbuf);
+ HDassert(dset_curr_seq);
+ HDassert(dset_len_arr);
+ HDassert(dset_off_arr);
+ HDassert(mem_curr_seq);
+ HDassert(mem_len_arr);
+ HDassert(mem_off_arr);
+
+ /* Set up user data for H5V_opvv() */
+ udata.efl = &(io_info->store->efl);
+ udata.rbuf = (unsigned char *)io_info->u.rbuf;
+
+ /* Call generic sequence operation routine */
+ if((ret_value = H5V_opvv(dset_max_nseq, dset_curr_seq, dset_len_arr, dset_off_arr,
+ mem_max_nseq, mem_curr_seq, mem_len_arr, mem_off_arr,
+ H5D_efl_readvv_cb, &udata)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTOPERATE, FAIL, "can't perform vectorized EFL read")
- /* Work through all the sequences */
- 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];
-
- /* Compute offset on disk */
- addr = dset_offset_arr[u];
-
- /* Compute offset in memory */
- buf = (unsigned char *)io_info->u.rbuf + mem_offset_arr[v];
-
- /* Read data */
- if(H5D_efl_read(efl, addr, size, buf) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed")
-
- /* Update memory information */
- mem_len_arr[v] -= size;
- if(mem_len_arr[v] == 0)
- v++;
- else
- mem_offset_arr[v] += size;
-
- /* Update file information */
- dset_len_arr[u] -= size;
- if(dset_len_arr[u] == 0)
- u++;
- else
- dset_offset_arr[u] += size;
-
- /* Increment number of bytes copied */
- ret_value += (ssize_t)size;
- } /* end for */
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_efl_readvv() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_efl_writevv_cb
+ *
+ * Purpose: Callback operator for H5D_efl_writevv().
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, Sept 30, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_efl_writevv_cb(hsize_t dst_off, hsize_t src_off, size_t len, void *_udata)
+{
+ H5D_efl_writevv_ud_t *udata = (H5D_efl_writevv_ud_t *)_udata; /* User data for H5V_opvv() operator */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_efl_writevv_cb)
- /* Update current sequence vectors */
- *dset_curr_seq = u;
- *mem_curr_seq = v;
+ /* Write data */
+ if(H5D_efl_write(udata->efl, dst_off, len, (udata->wbuf + src_off)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "EFL write failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_efl_readvv() */
+} /* end H5D_efl_writevv_cb() */
/*-------------------------------------------------------------------------
@@ -492,62 +536,34 @@ done:
*/
static ssize_t
H5D_efl_writevv(const H5D_io_info_t *io_info,
- 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[])
+ size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_off_arr[],
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_off_arr[])
{
- const H5O_efl_t *efl = &(io_info->store->efl); /* Pointer to efl info */
- const unsigned char *buf; /* Pointer to buffer to write */
- haddr_t addr; /* Actual address to read */
- size_t size; /* Size of sequence in bytes */
- size_t u, v; /* Counting variables */
- ssize_t ret_value = 0; /* Return value (Total size of sequence in bytes) */
+ H5D_efl_writevv_ud_t udata; /* User data for H5V_opvv() operator */
+ ssize_t ret_value; /* Return value (Total size of sequence in bytes) */
FUNC_ENTER_NOAPI_NOINIT(H5D_efl_writevv)
/* Check args */
- HDassert(efl && efl->nused > 0);
+ HDassert(io_info);
+ HDassert(io_info->store->efl.nused > 0);
HDassert(io_info->u.wbuf);
-
- /* Work through all the sequences */
- 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];
-
- /* Compute offset on disk */
- addr = dset_offset_arr[u];
-
- /* Compute offset in memory */
- buf = (const unsigned char *)io_info->u.wbuf + mem_offset_arr[v];
-
- /* Write data */
- if(H5D_efl_write(efl, addr, size, buf) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed")
-
- /* Update memory information */
- mem_len_arr[v] -= size;
- if(mem_len_arr[v] == 0)
- v++;
- else
- mem_offset_arr[v] += size;
-
- /* Update file information */
- dset_len_arr[u] -= size;
- if(dset_len_arr[u] == 0)
- u++;
- else
- dset_offset_arr[u] += size;
-
- /* Increment number of bytes copied */
- ret_value += (ssize_t)size;
- } /* end for */
-
- /* Update current sequence vectors */
- *dset_curr_seq = u;
- *mem_curr_seq = v;
-
+ HDassert(dset_curr_seq);
+ HDassert(dset_len_arr);
+ HDassert(dset_off_arr);
+ HDassert(mem_curr_seq);
+ HDassert(mem_len_arr);
+ HDassert(mem_off_arr);
+
+ /* Set up user data for H5V_opvv() */
+ udata.efl = &(io_info->store->efl);
+ udata.wbuf = (const unsigned char *)io_info->u.wbuf;
+
+ /* Call generic sequence operation routine */
+ if((ret_value = H5V_opvv(dset_max_nseq, dset_curr_seq, dset_len_arr, dset_off_arr,
+ mem_max_nseq, mem_curr_seq, mem_len_arr, mem_off_arr,
+ H5D_efl_writevv_cb, &udata)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTOPERATE, FAIL, "can't perform vectorized EFL write")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_efl_writevv() */
diff --git a/src/H5Dpkg.h b/src/H5Dpkg.h
index 34bf1da..96acc58 100644
--- a/src/H5Dpkg.h
+++ b/src/H5Dpkg.h
@@ -394,7 +394,7 @@ typedef struct H5D_rdcdc_t {
haddr_t sieve_loc; /* File location (offset) of the data sieve buffer */
size_t sieve_size; /* Size of the data sieve buffer used (in bytes) */
size_t sieve_buf_size; /* Size of the data sieve buffer allocated (in bytes) */
- unsigned sieve_dirty; /* Flag to indicate that the data sieve buffer is dirty */
+ hbool_t sieve_dirty; /* Flag to indicate that the data sieve buffer is dirty */
} H5D_rdcdc_t;
/*
@@ -583,12 +583,6 @@ H5_DLL herr_t H5D_contig_read(H5D_io_info_t *io_info, const H5D_type_info_t *typ
H5_DLL herr_t H5D_contig_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
H5D_chunk_map_t *fm);
-H5_DLL ssize_t H5D_contig_readvv(const H5D_io_info_t *io_info,
- 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[]);
-H5_DLL ssize_t H5D_contig_writevv(const H5D_io_info_t *io_info,
- 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[]);
H5_DLL herr_t H5D_contig_copy(H5F_t *f_src, const H5O_storage_contig_t *storage_src,
H5F_t *f_dst, H5O_storage_contig_t *storage_dst, H5T_t *src_dtype,
H5O_copy_t *cpy_info, hid_t dxpl_id);
diff --git a/src/H5Shyper.c b/src/H5Shyper.c
index 45371dd..4aa887b 100644
--- a/src/H5Shyper.c
+++ b/src/H5Shyper.c
@@ -8652,6 +8652,10 @@ H5S_hyper_get_seq_list_single(const H5S_t *space, H5S_sel_iter_t *iter,
*nelem += elmt_remainder;
} /* end if */
+ /* Sanity check */
+ HDassert(*nseq > 0);
+ HDassert(*nelem > 0);
+
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5S_hyper_get_seq_list_single() */
@@ -8699,6 +8703,7 @@ H5S_hyper_get_seq_list(const H5S_t *space, unsigned UNUSED flags, H5S_sel_iter_t
/* Check args */
HDassert(space);
HDassert(iter);
+ HDassert(iter->elmt_left > 0);
HDassert(maxseq > 0);
HDassert(maxelem > 0);
HDassert(nseq);
diff --git a/src/H5V.c b/src/H5V.c
index 979b591..37d558f 100644
--- a/src/H5V.c
+++ b/src/H5V.c
@@ -24,6 +24,12 @@
#include "H5Oprivate.h"
#include "H5Vprivate.h"
+/* Local typedefs */
+typedef struct H5V_memcpy_ud_t {
+ unsigned char *dst; /* Pointer to destination buffer */
+ const unsigned char *src; /* Pointer to source buffer */
+} H5V_memcpy_ud_t;
+
/* Local macros */
#define H5V_HYPER_NDIMS H5O_LAYOUT_NDIMS
@@ -1149,9 +1155,9 @@ done:
*
*-------------------------------------------------------------------------
*/
-herr_t
-H5V_array_calc_pre(hsize_t offset, unsigned n, const hsize_t *total_size,
- const hsize_t *down, hsize_t *coords)
+static herr_t
+H5V_array_calc_pre(hsize_t offset, unsigned n, const hsize_t *down,
+ hsize_t *coords)
{
unsigned u; /* Local index variable */
@@ -1159,7 +1165,6 @@ H5V_array_calc_pre(hsize_t offset, unsigned n, const hsize_t *total_size,
/* Sanity check */
HDassert(n <= H5V_HYPER_NDIMS);
- HDassert(total_size);
HDassert(coords);
/* Compute the coordinates from the offset */
@@ -1210,7 +1215,7 @@ H5V_array_calc(hsize_t offset, unsigned n, const hsize_t *total_size, hsize_t *c
HGOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "can't compute down sizes")
/* Compute the coordinates from the offset */
- if(H5V_array_calc_pre(offset, n, total_size, idx, coords) < 0)
+ if(H5V_array_calc_pre(offset, n, idx, coords) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "can't compute coordinates")
done:
@@ -1287,6 +1292,212 @@ H5V_chunk_index(unsigned ndims, const hsize_t *coord, const uint32_t *chunk,
/*-------------------------------------------------------------------------
+ * Function: H5V_opvv
+ *
+ * Purpose: Perform an operation on a source & destination sequences
+ * of offset/length pairs. Each set of sequnces has an array
+ * of lengths, an array of offsets, the maximum number of
+ * sequences and the current sequence to start at in the sequence.
+ *
+ * There may be different numbers of bytes in the source and
+ * destination sequences, the operation stops when either the
+ * source or destination sequence runs out of information.
+ *
+ * Note: The algorithm in this routine is [basically] the same as for
+ * H5V_memcpyvv(). Changes should be made to both!
+ *
+ * Return: Non-negative # of bytes operated on, on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, September 30, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+ssize_t
+H5V_opvv(size_t dst_max_nseq, size_t *dst_curr_seq, size_t dst_len_arr[],
+ hsize_t dst_off_arr[],
+ size_t src_max_nseq, size_t *src_curr_seq, size_t src_len_arr[],
+ hsize_t src_off_arr[],
+ H5V_opvv_func_t op, void *op_data)
+{
+ hsize_t *max_dst_off_ptr, *max_src_off_ptr; /* Pointers to max. source and destination offset locations */
+ hsize_t *dst_off_ptr, *src_off_ptr; /* Pointers to source and destination offset arrays */
+ size_t *dst_len_ptr, *src_len_ptr; /* Pointers to source and destination length arrays */
+ hsize_t tmp_dst_off, tmp_src_off; /* Temporary source and destination offset values */
+ size_t tmp_dst_len, tmp_src_len; /* Temporary source and destination length values */
+ size_t acc_len; /* Accumulated length of sequences */
+ ssize_t ret_value = 0; /* Return value (Total size of sequence in bytes) */
+
+ FUNC_ENTER_NOAPI(H5V_opvv, FAIL)
+
+ /* Sanity check */
+ HDassert(dst_curr_seq);
+ HDassert(*dst_curr_seq < dst_max_nseq);
+ HDassert(dst_len_arr);
+ HDassert(dst_off_arr);
+ HDassert(src_curr_seq);
+ HDassert(*src_curr_seq < src_max_nseq);
+ HDassert(src_len_arr);
+ HDassert(src_off_arr);
+ HDassert(op);
+
+ /* Set initial offset & length pointers */
+ dst_len_ptr = dst_len_arr + *dst_curr_seq;
+ dst_off_ptr = dst_off_arr + *dst_curr_seq;
+ src_len_ptr = src_len_arr + *src_curr_seq;
+ src_off_ptr = src_off_arr + *src_curr_seq;
+
+ /* Get temporary source & destination sequence offsets & lengths */
+ tmp_dst_len = *dst_len_ptr;
+ tmp_dst_off = *dst_off_ptr;
+ tmp_src_len = *src_len_ptr;
+ tmp_src_off = *src_off_ptr;
+
+ /* Compute maximum offset pointer values */
+ max_dst_off_ptr = dst_off_arr + dst_max_nseq;
+ max_src_off_ptr = src_off_arr + src_max_nseq;
+
+/* Work through the sequences */
+/* (Choose smallest sequence available initially) */
+
+ /* Source sequence is less than destination sequence */
+ if(tmp_src_len < tmp_dst_len) {
+src_smaller:
+ acc_len = 0;
+ do {
+ /* Make operator callback */
+ if((*op)(tmp_dst_off, tmp_src_off, tmp_src_len, op_data) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_CANTOPERATE, FAIL, "can't perform operation")
+
+ /* Accumulate number of bytes copied */
+ acc_len += tmp_src_len;
+
+ /* Update destination length */
+ tmp_dst_off += tmp_src_len;
+ tmp_dst_len -= tmp_src_len;
+
+ /* Advance source offset & check for being finished */
+ src_off_ptr++;
+ if(src_off_ptr >= max_src_off_ptr) {
+ /* Roll accumulated changes into appropriate counters */
+ *dst_off_ptr = tmp_dst_off;
+ *dst_len_ptr = tmp_dst_len;
+
+ /* Done with sequences */
+ goto finished;
+ } /* end if */
+ tmp_src_off = *src_off_ptr;
+
+ /* Update source information */
+ src_len_ptr++;
+ tmp_src_len = *src_len_ptr;
+ } while(tmp_src_len < tmp_dst_len);
+
+ /* Roll accumulated sequence lengths into return value */
+ ret_value += (ssize_t)acc_len;
+
+ /* Transition to next state */
+ if(tmp_dst_len < tmp_src_len)
+ goto dst_smaller;
+ else
+ goto equal;
+ } /* end if */
+ /* Destination sequence is less than source sequence */
+ else if(tmp_dst_len < tmp_src_len) {
+dst_smaller:
+ acc_len = 0;
+ do {
+ /* Make operator callback */
+ if((*op)(tmp_dst_off, tmp_src_off, tmp_dst_len, op_data) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_CANTOPERATE, FAIL, "can't perform operation")
+
+ /* Accumulate number of bytes copied */
+ acc_len += tmp_dst_len;
+
+ /* Update source length */
+ tmp_src_off += tmp_dst_len;
+ tmp_src_len -= tmp_dst_len;
+
+ /* Advance destination offset & check for being finished */
+ dst_off_ptr++;
+ if(dst_off_ptr >= max_dst_off_ptr) {
+ /* Roll accumulated changes into appropriate counters */
+ *src_off_ptr = tmp_src_off;
+ *src_len_ptr = tmp_src_len;
+
+ /* Done with sequences */
+ goto finished;
+ } /* end if */
+ tmp_dst_off = *dst_off_ptr;
+
+ /* Update destination information */
+ dst_len_ptr++;
+ tmp_dst_len = *dst_len_ptr;
+ } while(tmp_dst_len < tmp_src_len);
+
+ /* Roll accumulated sequence lengths into return value */
+ ret_value += (ssize_t)acc_len;
+
+ /* Transition to next state */
+ if(tmp_src_len < tmp_dst_len)
+ goto src_smaller;
+ else
+ goto equal;
+ } /* end else-if */
+ /* Destination sequence and source sequence are same length */
+ else {
+equal:
+ acc_len = 0;
+ do {
+ /* Make operator callback */
+ if((*op)(tmp_dst_off, tmp_src_off, tmp_dst_len, op_data) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_CANTOPERATE, FAIL, "can't perform operation")
+
+ /* Accumulate number of bytes copied */
+ acc_len += tmp_dst_len;
+
+ /* Advance source & destination offset & check for being finished */
+ src_off_ptr++;
+ dst_off_ptr++;
+ if(src_off_ptr >= max_src_off_ptr || dst_off_ptr >= max_dst_off_ptr)
+ /* Done with sequences */
+ goto finished;
+ tmp_src_off = *src_off_ptr;
+ tmp_dst_off = *dst_off_ptr;
+
+ /* Update source information */
+ src_len_ptr++;
+ tmp_src_len = *src_len_ptr;
+
+ /* Update destination information */
+ dst_len_ptr++;
+ tmp_dst_len = *dst_len_ptr;
+ } while(tmp_dst_len == tmp_src_len);
+
+ /* Roll accumulated sequence lengths into return value */
+ ret_value += (ssize_t)acc_len;
+
+ /* Transition to next state */
+ if(tmp_dst_len < tmp_src_len)
+ goto dst_smaller;
+ else
+ goto src_smaller;
+ } /* end else */
+
+finished:
+ /* Roll accumulated sequence lengths into return value */
+ ret_value += (ssize_t)acc_len;
+
+ /* Update current sequence vectors */
+ *dst_curr_seq = (size_t)(dst_off_ptr - dst_off_arr);
+ *src_curr_seq = (size_t)(src_off_ptr - src_off_arr);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5V_opvv() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5V_memcpyvv
*
* Purpose: Given source and destination buffers in memory (SRC & DST)
@@ -1299,6 +1510,9 @@ H5V_chunk_index(unsigned ndims, const hsize_t *coord, const uint32_t *chunk,
* destination sequences, data copying stops when either the
* source or destination buffer runs out of sequence information.
*
+ * Note: The algorithm in this routine is [basically] the same as for
+ * H5V_opvv(). Changes should be made to both!
+ *
* Return: Non-negative # of bytes copied on success/Negative on failure
*
* Programmer: Quincey Koziol
@@ -1314,8 +1528,12 @@ H5V_memcpyvv(void *_dst,
{
unsigned char *dst; /* Destination buffer pointer */
const unsigned char *src; /* Source buffer pointer */
- size_t size; /* Size of sequence in bytes */
- size_t u,v; /* Local index variables */
+ hsize_t *max_dst_off_ptr, *max_src_off_ptr; /* Pointers to max. source and destination offset locations */
+ hsize_t *dst_off_ptr, *src_off_ptr; /* Pointers to source and destination offset arrays */
+ size_t *dst_len_ptr, *src_len_ptr; /* Pointers to source and destination length arrays */
+ size_t tmp_dst_len; /* Temporary dest. length value */
+ size_t tmp_src_len; /* Temporary source length value */
+ size_t acc_len; /* Accumulated length of sequences */
ssize_t ret_value = 0; /* Return value (Total size of sequence in bytes) */
FUNC_ENTER_NOAPI_NOFUNC(H5V_memcpyvv)
@@ -1332,44 +1550,159 @@ H5V_memcpyvv(void *_dst,
HDassert(src_len_arr);
HDassert(src_off_arr);
- /* Work through all the sequences */
- for(u = *dst_curr_seq, v = *src_curr_seq; u < dst_max_nseq && v < src_max_nseq; ) {
- /* Choose smallest buffer to write */
- if(src_len_arr[v] < dst_len_arr[u])
- size = src_len_arr[v];
- else
- size = dst_len_arr[u];
+ /* Set initial offset & length pointers */
+ dst_len_ptr = dst_len_arr + *dst_curr_seq;
+ dst_off_ptr = dst_off_arr + *dst_curr_seq;
+ src_len_ptr = src_len_arr + *src_curr_seq;
+ src_off_ptr = src_off_arr + *src_curr_seq;
+
+ /* Get temporary source & destination sequence lengths */
+ tmp_dst_len = *dst_len_ptr;
+ tmp_src_len = *src_len_ptr;
+
+ /* Compute maximum offset pointer values */
+ max_dst_off_ptr = dst_off_arr + dst_max_nseq;
+ max_src_off_ptr = src_off_arr + src_max_nseq;
+
+ /* Compute buffer offsets */
+ dst = (unsigned char *)_dst + *dst_off_ptr;
+ src = (const unsigned char *)_src + *src_off_ptr;
+
+/* Work through the sequences */
+/* (Choose smallest sequence available initially) */
+
+ /* Source sequence is less than destination sequence */
+ if(tmp_src_len < tmp_dst_len) {
+src_smaller:
+ acc_len = 0;
+ do {
+ /* Copy data */
+ HDmemcpy(dst, src, tmp_src_len);
+
+ /* Accumulate number of bytes copied */
+ acc_len += tmp_src_len;
+
+ /* Update destination length */
+ tmp_dst_len -= tmp_src_len;
+
+ /* Advance source offset & check for being finished */
+ src_off_ptr++;
+ if(src_off_ptr >= max_src_off_ptr) {
+ /* Roll accumulated changes into appropriate counters */
+ *dst_off_ptr += acc_len;
+ *dst_len_ptr = tmp_dst_len;
+
+ /* Done with sequences */
+ goto finished;
+ } /* end if */
- /* Compute offset on disk */
- dst = (unsigned char *)_dst + dst_off_arr[u];
+ /* Update destination pointer */
+ dst += tmp_src_len;
- /* Compute offset in memory */
- src = (const unsigned char *)_src + src_off_arr[v];
+ /* Update source information */
+ src_len_ptr++;
+ tmp_src_len = *src_len_ptr;
+ src = (const unsigned char *)_src + *src_off_ptr;
+ } while(tmp_src_len < tmp_dst_len);
- /* Copy data */
- HDmemcpy(dst, src, size);
+ /* Roll accumulated sequence lengths into return value */
+ ret_value += (ssize_t)acc_len;
- /* Update source information */
- src_len_arr[v] -= size;
- if(0 == src_len_arr[v])
- v++;
+ /* Transition to next state */
+ if(tmp_dst_len < tmp_src_len)
+ goto dst_smaller;
else
- src_off_arr[v] += size;
+ goto equal;
+ } /* end if */
+ /* Destination sequence is less than source sequence */
+ else if(tmp_dst_len < tmp_src_len) {
+dst_smaller:
+ acc_len = 0;
+ do {
+ /* Copy data */
+ HDmemcpy(dst, src, tmp_dst_len);
+
+ /* Accumulate number of bytes copied */
+ acc_len += tmp_dst_len;
+
+ /* Update source length */
+ tmp_src_len -= tmp_dst_len;
+
+ /* Advance destination offset & check for being finished */
+ dst_off_ptr++;
+ if(dst_off_ptr >= max_dst_off_ptr) {
+ /* Roll accumulated changes into appropriate counters */
+ *src_off_ptr += acc_len;
+ *src_len_ptr = tmp_src_len;
+
+ /* Done with sequences */
+ goto finished;
+ } /* end if */
+
+ /* Update source pointer */
+ src += tmp_dst_len;
+
+ /* Update destination information */
+ dst_len_ptr++;
+ tmp_dst_len = *dst_len_ptr;
+ dst = (unsigned char *)_dst + *dst_off_ptr;
+ } while(tmp_dst_len < tmp_src_len);
- /* Update destination information */
- dst_len_arr[u] -= size;
- if(0 == dst_len_arr[u])
- u++;
+ /* Roll accumulated sequence lengths into return value */
+ ret_value += (ssize_t)acc_len;
+
+ /* Transition to next state */
+ if(tmp_src_len < tmp_dst_len)
+ goto src_smaller;
+ else
+ goto equal;
+ } /* end else-if */
+ /* Destination sequence and source sequence are same length */
+ else {
+equal:
+ acc_len = 0;
+ do {
+ /* Copy data */
+ HDmemcpy(dst, src, tmp_dst_len);
+
+ /* Accumulate number of bytes copied */
+ acc_len += tmp_dst_len;
+
+ /* Advance source & destination offset & check for being finished */
+ src_off_ptr++;
+ dst_off_ptr++;
+ if(src_off_ptr >= max_src_off_ptr || dst_off_ptr >= max_dst_off_ptr)
+ /* Done with sequences */
+ goto finished;
+
+ /* Update source information */
+ src_len_ptr++;
+ tmp_src_len = *src_len_ptr;
+ src = (const unsigned char *)_src + *src_off_ptr;
+
+ /* Update destination information */
+ dst_len_ptr++;
+ tmp_dst_len = *dst_len_ptr;
+ dst = (unsigned char *)_dst + *dst_off_ptr;
+ } while(tmp_dst_len == tmp_src_len);
+
+ /* Roll accumulated sequence lengths into return value */
+ ret_value += (ssize_t)acc_len;
+
+ /* Transition to next state */
+ if(tmp_dst_len < tmp_src_len)
+ goto dst_smaller;
else
- dst_off_arr[u] += size;
+ goto src_smaller;
+ } /* end else */
- /* Increment number of bytes copied */
- ret_value += (ssize_t)size;
- } /* end for */
+finished:
+ /* Roll accumulated sequence lengths into return value */
+ ret_value += (ssize_t)acc_len;
/* Update current sequence vectors */
- *dst_curr_seq = u;
- *src_curr_seq = v;
+ *dst_curr_seq = (size_t)(dst_off_ptr - dst_off_arr);
+ *src_curr_seq = (size_t)(src_off_ptr - src_off_arr);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5V_memcpyvv() */
diff --git a/src/H5Vprivate.h b/src/H5Vprivate.h
index e25ff85..894ec5c 100644
--- a/src/H5Vprivate.h
+++ b/src/H5Vprivate.h
@@ -24,6 +24,10 @@
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
+/* Vector-Vector sequence operation callback */
+typedef herr_t (*H5V_opvv_func_t)(hsize_t dst_off, hsize_t src_off,
+ size_t len, void *udata);
+
/* Vector comparison functions like Fortran66 comparison operators */
#define H5V_vector_eq_s(N,V1,V2) (H5V_vector_cmp_s (N, V1, V2)==0)
#define H5V_vector_lt_s(N,V1,V2) (H5V_vector_cmp_s (N, V1, V2)<0)
@@ -83,12 +87,15 @@ H5_DLL hsize_t H5V_array_offset_pre(unsigned n,
const hsize_t *acc, const hsize_t *offset);
H5_DLL hsize_t H5V_array_offset(unsigned n, const hsize_t *total_size,
const hsize_t *offset);
-H5_DLL herr_t H5V_array_calc_pre(hsize_t offset, unsigned n, const hsize_t *total_size,
- const hsize_t *down, hsize_t *coords);
H5_DLL herr_t H5V_array_calc(hsize_t offset, unsigned n,
const hsize_t *total_size, hsize_t *coords);
H5_DLL herr_t H5V_chunk_index(unsigned ndims, const hsize_t *coord,
const uint32_t *chunk, const hsize_t *down_nchunks, hsize_t *chunk_idx);
+H5_DLL ssize_t H5V_opvv(size_t dst_max_nseq, size_t *dst_curr_seq, size_t dst_len_arr[],
+ hsize_t dst_off_arr[],
+ size_t src_max_nseq, size_t *src_curr_seq, size_t src_len_arr[],
+ hsize_t src_off_arr[],
+ H5V_opvv_func_t op, void *op_data);
H5_DLL ssize_t H5V_memcpyvv(void *_dst,
size_t dst_max_nseq, size_t *dst_curr_seq, size_t dst_len_arr[], hsize_t dst_off_arr[],
const void *_src,