diff options
Diffstat (limited to 'hl/src/H5DO.c')
-rw-r--r-- | hl/src/H5DO.c | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/hl/src/H5DO.c b/hl/src/H5DO.c index 99dbd93..bfadfaa 100644 --- a/hl/src/H5DO.c +++ b/hl/src/H5DO.c @@ -97,3 +97,195 @@ done: return(ret_value); } /* end H5DOwrite_chunk() */ + +/* + * Function: H5DOappend() + * + * Purpose: To append elements to a dataset. + * axis: the dataset dimension (zero-based) for the append + * extension: the # of elements to append for the axis-th dimension + * memtype: the datatype + * buf: buffer with data for the append + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Vailin Choi; Jan 2014 + * + * Note: + * This routine is copied from the fast forward feature branch: features/hdf5_ff + * src/H5FF.c:H5DOappend() with the following modifications: + * 1) Remove and replace macro calls such as + * FUNC_ENTER_API, H5TRACE, HGOTO_ERROR + * accordingly because hl does not have these macros + * 2) Replace H5I_get_type() by H5Iget_type() + * 3) Replace H5P_isa_class() by H5Pisa_class() + * 4) Fix a bug in the following: replace extension by size[axis] + * if(extension < old_size) { + * ret_value = FAIL; + * goto done; + * } + */ +herr_t +H5DOappend(hid_t dset_id, hid_t dxpl_id, unsigned axis, size_t extension, + hid_t memtype, const void *buf) +{ + hbool_t created_dxpl = FALSE; /* Whether we created a DXPL */ + hsize_t size[H5S_MAX_RANK]; /* The new size (after extension */ + hsize_t old_size = 0; /* The size of the dimension to be extended */ + int sndims; /* Number of dimensions in dataspace (signed) */ + unsigned ndims; /* Number of dimensions in dataspace */ + hid_t space_id = FAIL; /* Old file space */ + hid_t new_space_id = FAIL; /* New file space (after extension) */ + hid_t mem_space_id = FAIL; /* Memory space for data buffer */ + hssize_t snelmts; /* Number of elements in selection (signed) */ + hsize_t nelmts; /* Number of elements in selection */ + hid_t dapl = FAIL; /* Dataset access property list */ + + hsize_t start[H5S_MAX_RANK]; /* H5Sselect_Hyperslab: starting offset */ + hsize_t count[H5S_MAX_RANK]; /* H5Sselect_hyperslab: # of blocks to select */ + hsize_t stride[H5S_MAX_RANK]; /* H5Sselect_hyperslab: # of elements to move when selecting */ + hsize_t block[H5S_MAX_RANK]; /* H5Sselect_hyperslab: # of elements in a block */ + + hsize_t *boundary = NULL; /* Boundary set in append flush property */ + H5D_append_cb_t append_cb; /* Callback function set in append flush property */ + void *udata; /* User data set in append flush property */ + hbool_t hit = FALSE; /* Boundary is hit or not */ + hsize_t k; /* Local index variable */ + unsigned u; /* Local index variable */ + herr_t ret_value = FAIL; /* Return value */ + + /* check arguments */ + if(H5I_DATASET != H5Iget_type(dset_id)) + goto done; + + /* If the user passed in a default DXPL, create one to pass to H5Dwrite() */ + if(H5P_DEFAULT == dxpl_id) { + if((dxpl_id = H5Pcreate(H5P_DATASET_XFER)) < 0) + goto done; + created_dxpl = TRUE; + } /* end if */ + else if(TRUE != H5Pisa_class(dxpl_id, H5P_DATASET_XFER)) + goto done; + + /* Get the dataspace of the dataset */ + if(FAIL == (space_id = H5Dget_space(dset_id))) + goto done; + + /* Get the rank of this dataspace */ + if((sndims = H5Sget_simple_extent_ndims(space_id)) < 0) + goto done; + ndims = (unsigned)sndims; + + /* Verify correct axis */ + if(axis >= ndims) + goto done; + + /* Get the dimensions sizes of the dataspace */ + if(H5Sget_simple_extent_dims(space_id, size, NULL) < 0) + goto done; + + /* Adjust the dimension size of the requested dimension, + but first record the old dimension size */ + old_size = size[axis]; + size[axis] += extension; + if(size[axis] < old_size) + goto done; + + /* Set the extent of the dataset to the new dimension */ + if(H5Dset_extent(dset_id, size) < 0) + goto done; + + /* Get the new dataspace of the dataset */ + if(FAIL == (new_space_id = H5Dget_space(dset_id))) + goto done; + + /* Select a hyperslab corresponding to the append operation */ + for(u = 0 ; u < ndims ; u++) { + start[u] = 0; + stride[u] = 1; + count[u] = size[u]; + block[u] = 1; + if(u == axis) { + count[u] = extension; + start[u] = old_size; + } /* end if */ + } /* end for */ + if(FAIL == H5Sselect_hyperslab(new_space_id, H5S_SELECT_SET, start, stride, count, block)) + goto done; + + /* The # of elemnts in the new extended dataspace */ + if((snelmts = H5Sget_select_npoints(new_space_id)) < 0) + goto done; + nelmts = (hsize_t)snelmts; + + /* create a memory space */ + mem_space_id = H5Screate_simple(1, &nelmts, NULL); + + /* Write the data */ + if(H5Dwrite(dset_id, memtype, mem_space_id, new_space_id, dxpl_id, buf) < 0) + goto done; + + /* Obtain the dataset's access property list */ + if((dapl = H5Dget_access_plist(dset_id)) < 0) + goto done; + + /* Allocate the boundary array */ + boundary = (hsize_t *)HDmalloc(ndims * sizeof(hsize_t)); + + /* Retrieve the append flush property */ + if(H5Pget_append_flush(dapl, ndims, boundary, &append_cb, &udata) < 0) + goto done; + + /* No boundary for this axis */ + if(boundary[axis] == 0) + goto done; + + /* Determine whether a boundary is hit or not */ + for(k = start[axis]; k < size[axis]; k++) + if(!((k + 1) % boundary[axis])) { + hit = TRUE; + break; + } + + if(hit) { /* Hit the boundary */ + /* Invoke callback if there is one */ + if(append_cb && append_cb(dset_id, size, udata) < 0) + goto done; + + /* Do a dataset flush */ + if(H5Dflush(dset_id) < 0) + goto done; + } /* end if */ + + /* Indicate success */ + ret_value = SUCCEED; + +done: + /* Close dxpl if we created it vs. one was passed in */ + if(created_dxpl) { + if(H5Pclose(dxpl_id) < 0) + ret_value = FAIL; + } /* end if */ + + /* Close old dataspace */ + if(space_id != FAIL && H5Sclose(space_id) < 0) + ret_value = FAIL; + + /* Close new dataspace */ + if(new_space_id != FAIL && H5Sclose(new_space_id) < 0) + ret_value = FAIL; + + /* Close memory dataspace */ + if(mem_space_id != FAIL && H5Sclose(mem_space_id) < 0) + ret_value = FAIL; + + /* Close the dataset access property list */ + if(dapl != FAIL && H5Pclose(dapl) < 0) + ret_value = FAIL; + + if(boundary) + HDfree(boundary); + + return ret_value; +} /* H5DOappend() */ + |