summaryrefslogtreecommitdiffstats
path: root/src/H5Dscatgath.c
diff options
context:
space:
mode:
authorNeil Fortner <nfortne2@hdfgroup.org>2013-02-05 17:07:02 (GMT)
committerNeil Fortner <nfortne2@hdfgroup.org>2013-02-05 17:07:02 (GMT)
commit0e3517d34fb6b4c2c1016ea6be80f3046f6d8549 (patch)
tree9a0785d26e7444a3cc852f0f8864f1e372855c87 /src/H5Dscatgath.c
parentd7a07d62a486f28ca869416762a4b45c7befb45b (diff)
downloadhdf5-0e3517d34fb6b4c2c1016ea6be80f3046f6d8549.zip
hdf5-0e3517d34fb6b4c2c1016ea6be80f3046f6d8549.tar.gz
hdf5-0e3517d34fb6b4c2c1016ea6be80f3046f6d8549.tar.bz2
[svn-r23230] Purpose: Implement H5Dscatter and H5Dgather
Description: Adds 2 new API functions, H5Dscatter and H5Dgather. H5Dscatter retrieves data from a specified callback function and scatters it into a selection, defined by a supplied dataspace, within a supplied memory buffer. H5Dgather gathers data from a selection within a supplied memory buffer and passes it in a contiguous form to a supplied callback function. Added tests for these functions Tested: jam, ostrich, koala (h5committest); ummon
Diffstat (limited to 'src/H5Dscatgath.c')
-rw-r--r--src/H5Dscatgath.c200
1 files changed, 199 insertions, 1 deletions
diff --git a/src/H5Dscatgath.c b/src/H5Dscatgath.c
index 49b6132..74d6749 100644
--- a/src/H5Dscatgath.c
+++ b/src/H5Dscatgath.c
@@ -27,6 +27,7 @@
#include "H5Dpkg.h" /* Dataset functions */
#include "H5Eprivate.h" /* Error handling */
#include "H5FLprivate.h" /* Free Lists */
+#include "H5Iprivate.h" /* IDs */
/****************/
@@ -361,7 +362,7 @@ done:
* copies them into the gather buffer TGATH_BUF.
* Each element is ELMT_SIZE bytes and arranged in application
* memory according to SPACE.
- * The caller is requesting that at most NELMTS be gathered.
+ * The caller is requesting that exactly NELMTS be gathered.
*
* Return: Success: Number of elements copied.
* Failure: 0
@@ -899,3 +900,200 @@ H5D__compound_opt_write(size_t nelmts, const H5D_type_info_t *type_info)
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5D__compound_opt_write() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5Dscatter
+ *
+ * Purpose: Scatters data provided by the callback op to the
+ * destination buffer dst_buf, where the dimensions of
+ * dst_buf and the selection to be scattered to are specified
+ * by the dataspace dst_space_id. The type of the data to be
+ * scattered is specified by type_id.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * 14 Jan 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Dscatter(H5D_scatter_func_t op, void *op_data, hid_t type_id,
+ hid_t dst_space_id, void *dst_buf)
+{
+ H5T_t *type; /* Datatype */
+ H5S_t *dst_space; /* Dataspace */
+ H5S_sel_iter_t iter; /* Selection iteration info*/
+ hbool_t iter_init = FALSE; /* Selection iteration info has been initialized */
+ void *src_buf = NULL; /* Source (contiguous) data buffer */
+ size_t src_buf_nbytes = 0; /* Size of src_buf */
+ size_t type_size; /* Datatype element size */
+ hssize_t nelmts; /* Number of remaining elements in selection */
+ size_t nelmts_scatter = 0; /* Number of elements to scatter to dst_buf */
+ H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */
+ H5D_dxpl_cache_t *dxpl_cache = &_dxpl_cache; /* Data transfer property cache */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE5("e", "x*xii*x", op, op_data, type_id, dst_space_id, dst_buf);
+
+ /* Check args */
+ if(op == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid callback function pointer")
+ if(NULL == (type = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
+ if(NULL == (dst_space= (H5S_t *)H5I_object_verify(dst_space_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
+ if(dst_buf == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no destination buffer provided")
+
+ /* Fill the DXPL cache values for later use */
+ if(H5D__get_dxpl_cache(H5P_DATASET_XFER_DEFAULT, &dxpl_cache) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache")
+
+ /* Get datatype element size */
+ if(0 == (type_size = H5T_GET_SIZE(type)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get datatype size")
+
+ /* Get number of elements in dataspace */
+ if((nelmts = (hssize_t)H5S_GET_SELECT_NPOINTS(dst_space)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTCOUNT, FAIL, "unable to get number of elements in selection")
+
+ /* Initialize selection iterator */
+ if(H5S_select_iter_init(&iter, dst_space, type_size) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize selection iterator information")
+ iter_init = TRUE;
+
+ /* Loop until all data has been scattered */
+ while(nelmts > 0) {
+ /* Make callback to retrieve data */
+ if(op(&src_buf, &src_buf_nbytes, op_data) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CALLBACK, FAIL, "callback operator returned failure")
+
+ /* Calculate number of elements */
+ nelmts_scatter = src_buf_nbytes / type_size;
+
+ /* Check callback results */
+ if(!src_buf)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "callback did not return a buffer")
+ if(src_buf_nbytes == 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "callback returned a buffer size of 0")
+ if(src_buf_nbytes % type_size)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "buffer size is not a multiple of datatype size")
+ if(nelmts_scatter > (size_t)nelmts)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "callback returned more elements than in selection")
+
+ /* Scatter data */
+ if(H5D__scatter_mem(src_buf, dst_space, &iter, nelmts_scatter, dxpl_cache, dst_buf) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "scatter failed")
+
+ nelmts -= (hssize_t)nelmts_scatter;
+ } /* end while */
+
+done:
+ /* Release selection iterator */
+ if(iter_init) {
+ if(H5S_SELECT_ITER_RELEASE(&iter) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
+ } /* end if */
+
+ FUNC_LEAVE_API(ret_value)
+} /* H5Dscatter() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Dgather
+ *
+ * Purpose: Gathers data provided from the source buffer src_buf to
+ * contiguous buffer dst_buf, then calls the callback op.
+ * The dimensions of src_buf and the selection to be gathered
+ * are specified by the dataspace src_space_id. The type of
+ * the data to be gathered is specified by type_id.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * 16 Jan 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Dgather(hid_t src_space_id, void *src_buf, hid_t type_id, size_t dst_buf_size,
+ void *dst_buf, H5D_gather_func_t op, void *op_data)
+{
+ H5T_t *type; /* Datatype */
+ H5S_t *src_space; /* Dataspace */
+ H5S_sel_iter_t iter; /* Selection iteration info*/
+ hbool_t iter_init = FALSE; /* Selection iteration info has been initialized */
+ size_t type_size; /* Datatype element size */
+ hssize_t nelmts; /* Number of remaining elements in selection */
+ size_t dst_buf_nelmts; /* Number of elements that can fit in dst_buf */
+ size_t nelmts_gathered; /* Number of elements gathered from src_buf */
+ H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */
+ H5D_dxpl_cache_t *dxpl_cache = &_dxpl_cache; /* Data transfer property cache */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE7("e", "i*xiz*xx*x", src_space_id, src_buf, type_id, dst_buf_size,
+ dst_buf, op, op_data);
+
+ /* Check args */
+ if(NULL == (src_space= (H5S_t *)H5I_object_verify(src_space_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
+ if(src_buf == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no source buffer provided")
+ if(NULL == (type = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
+ if(dst_buf_size == 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "destination buffer size is 0")
+ if(dst_buf == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no destination buffer provided")
+ if(op == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid callback function pointer")
+
+ /* Fill the DXPL cache values for later use */
+ if(H5D__get_dxpl_cache(H5P_DATASET_XFER_DEFAULT, &dxpl_cache) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache")
+
+ /* Get datatype element size */
+ if(0 == (type_size = H5T_GET_SIZE(type)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get datatype size")
+
+ /* Get number of elements in dst_buf_size */
+ dst_buf_nelmts = dst_buf_size / type_size;
+ if(dst_buf_nelmts == 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "destination buffer is not large enough to hold one element")
+
+ /* Get number of elements in dataspace */
+ if((nelmts = (hssize_t)H5S_GET_SELECT_NPOINTS(src_space)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTCOUNT, FAIL, "unable to get number of elements in selection")
+
+ /* Initialize selection iterator */
+ if(H5S_select_iter_init(&iter, src_space, type_size) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize selection iterator information")
+ iter_init = TRUE;
+
+ /* Loop until all data has been scattered */
+ while(nelmts > 0) {
+ /* Gather data */
+ if(0 == (nelmts_gathered = H5D__gather_mem(src_buf, src_space, &iter, MIN(dst_buf_nelmts, (size_t)nelmts), dxpl_cache, dst_buf)))
+ HGOTO_ERROR(H5E_IO, H5E_CANTCOPY, FAIL, "gather failed")
+ HDassert(nelmts_gathered == MIN(dst_buf_nelmts, (size_t)nelmts));
+
+ /* Make callback to process dst_buf */
+ if(op(dst_buf, nelmts_gathered * type_size, op_data) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CALLBACK, FAIL, "callback operator returned failure")
+
+ nelmts -= (hssize_t)nelmts_gathered;
+ } /* end while */
+
+done:
+ /* Release selection iterator */
+ if(iter_init) {
+ if(H5S_SELECT_ITER_RELEASE(&iter) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
+ } /* end if */
+
+ FUNC_LEAVE_API(ret_value)
+} /* H5Dgather() */
+