diff options
author | Neil Fortner <nfortne2@hdfgroup.org> | 2013-02-05 17:07:02 (GMT) |
---|---|---|
committer | Neil Fortner <nfortne2@hdfgroup.org> | 2013-02-05 17:07:02 (GMT) |
commit | 0e3517d34fb6b4c2c1016ea6be80f3046f6d8549 (patch) | |
tree | 9a0785d26e7444a3cc852f0f8864f1e372855c87 /src/H5Dscatgath.c | |
parent | d7a07d62a486f28ca869416762a4b45c7befb45b (diff) | |
download | hdf5-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.c | 200 |
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() */ + |