summaryrefslogtreecommitdiffstats
path: root/src/H5Dio.c
diff options
context:
space:
mode:
authorRaymond Lu <songyulu@hdfgroup.org>2007-03-20 20:39:23 (GMT)
committerRaymond Lu <songyulu@hdfgroup.org>2007-03-20 20:39:23 (GMT)
commite7f195023989d80131d343cc63b7a4557d03531d (patch)
tree9fc5c72a5cd6630068bdbecbe2f3c45fa0fd86d7 /src/H5Dio.c
parent5fe2a249cfaf6bc91babfa5fab028d2e1dccbfa8 (diff)
downloadhdf5-e7f195023989d80131d343cc63b7a4557d03531d.zip
hdf5-e7f195023989d80131d343cc63b7a4557d03531d.tar.gz
hdf5-e7f195023989d80131d343cc63b7a4557d03531d.tar.bz2
[svn-r13531] When a dataset is created and no data is written, but fill value is defined,
if there's VL type of data in the dataset, the address of the data is copied multiple times into the buffer, causing some trouble when the data is released. Instead, this checkin makes multiple copies of fill value first, then does conversion on each element so that each of them has a copy of the VL data. A test is added, too. Tested it on kagiso, sol, and copper.
Diffstat (limited to 'src/H5Dio.c')
-rw-r--r--src/H5Dio.c98
1 files changed, 77 insertions, 21 deletions
diff --git a/src/H5Dio.c b/src/H5Dio.c
index ceaf86c..f841f13 100644
--- a/src/H5Dio.c
+++ b/src/H5Dio.c
@@ -228,16 +228,23 @@ done:
parameter is NULL, use "buf_type" for the fill value datatype.
EXAMPLES
REVISION LOG
+ Raymond Lu - 20 March 2007
+ If there's VL type of data, the address of the data is copied multiple
+ times into the buffer, causing some trouble when the data is released.
+ Instead, make multiple copies of fill value first, then do conversion
+ on each element so that each of them has a copy of the VL data.
--------------------------------------------------------------------------*/
static herr_t
H5D_fill(const void *fill, const H5T_t *fill_type, void *buf, const H5T_t *buf_type, const H5S_t *space, hid_t dxpl_id)
{
H5T_path_t *tpath = NULL; /* Conversion information*/
uint8_t *tconv_buf = NULL; /* Data type conv buffer */
- uint8_t *bkg_buf = NULL; /* Temp conversion buffer */
+ uint8_t *bkg_buf = NULL; /* Background conversion buffer */
+ uint8_t *tmp_buf = NULL; /* Temp conversion buffer */
hid_t src_id = -1, dst_id = -1; /* Temporary type IDs */
size_t src_type_size; /* Size of source type */
size_t dst_type_size; /* Size of destination type*/
+ hssize_t nelmts; /* Number of data elements */
size_t buf_size; /* Desired buffer size */
herr_t ret_value=SUCCEED; /* Return value */
@@ -259,42 +266,91 @@ H5D_fill(const void *fill, const H5T_t *fill_type, void *buf, const H5T_t *buf_t
/* Get the maximum buffer size needed and allocate it */
buf_size=MAX(src_type_size,dst_type_size);
- if(NULL == (tconv_buf = H5FL_BLK_MALLOC(type_elem,buf_size)) || NULL==(bkg_buf = H5FL_BLK_CALLOC(type_elem,buf_size)))
+
+ /* Allocate space for conversion buffer */
+ if(NULL == (tconv_buf = H5FL_BLK_MALLOC(type_elem,buf_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
- /* Check for actual fill value to replicate */
- if(fill==NULL)
- /* If there's no fill value, just use zeros */
+ /* If there's no fill value, just use zeros */
+ if(fill==NULL) {
HDmemset(tconv_buf,0,dst_type_size);
- else {
- /* Copy the user's data into the buffer for conversion */
- HDmemcpy(tconv_buf,fill,src_type_size);
- /* Set up type conversion function */
- if(NULL == (tpath = H5T_path_find(fill_type, buf_type, NULL, NULL, dxpl_id, FALSE)))
- HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest data types")
+ /* Fill the selection in the memory buffer */
+ if(H5S_select_fill(tconv_buf, dst_type_size, space, buf) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTENCODE, FAIL, "filling selection failed")
+
+ HGOTO_DONE(ret_value);
+ }
+
+ /* Set up type conversion function */
+ if(NULL == (tpath = H5T_path_find(fill_type, buf_type, NULL, NULL, dxpl_id, FALSE)))
+ HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest data types")
+
+ if(!H5T_path_noop(tpath)) {
+ if((src_id = H5I_register(H5I_DATATYPE, H5T_copy(fill_type, H5T_COPY_ALL))) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register types for conversion")
+
+ if((dst_id = H5I_register(H5I_DATATYPE, H5T_copy(buf_type, H5T_COPY_ALL))) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register types for conversion")
+ }
+
+ /* Copy the user's data into the buffer for conversion */
+ HDmemcpy(tconv_buf,fill,src_type_size);
+
+ if(TRUE == H5T_detect_class(fill_type, H5T_VLEN)) {
+ /* If there's VL type of data, make multiple copies of fill value first,
+ * then do conversion on each element so that each of them has a copy
+ * of the VL data.
+ */
+
+ /* Get the number of elements */
+ nelmts = H5S_get_simple_extent_npoints(space);
- /* Convert memory buffer into disk buffer */
+ /* Allocate a temporary buffer and background buffer */
+ if(NULL == (tmp_buf = H5FL_BLK_MALLOC(type_conv,(size_t)nelmts*buf_size)) || NULL==(bkg_buf = H5FL_BLK_CALLOC(type_conv,(size_t)nelmts*buf_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Fill the selection in the temporary buffer */
+ if(H5S_select_fill(tconv_buf, src_type_size, space, tmp_buf) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTENCODE, FAIL, "filling selection failed")
+
+ /* Convert disk buffer into memory buffer */
if(!H5T_path_noop(tpath)) {
- if((src_id = H5I_register(H5I_DATATYPE, H5T_copy(fill_type, H5T_COPY_ALL))) < 0 ||
- (dst_id = H5I_register(H5I_DATATYPE, H5T_copy(buf_type, H5T_COPY_ALL))) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register types for conversion")
+ if(H5T_convert(tpath, src_id, dst_id, (size_t)nelmts, (size_t)0, (size_t)0, tmp_buf, bkg_buf, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "data type conversion failed")
+ } /* end if */
+ /* Copy the final data into the memory buffer */
+ HDmemcpy(buf, tmp_buf, (size_t)nelmts*dst_type_size);
+ } else {
+ /* If there's no VL type of data, do conversion first then fill the data into
+ * the memory buffer. */
+ if(NULL==(bkg_buf = H5FL_BLK_CALLOC(type_elem,buf_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Convert disk buffer into memory buffer */
+ if(!H5T_path_noop(tpath)) {
/* Perform data type conversion */
if(H5T_convert(tpath, src_id, dst_id, (size_t)1, (size_t)0, (size_t)0, tconv_buf, bkg_buf, dxpl_id) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "data type conversion failed")
} /* end if */
- } /* end if */
- /* Fill the selection in the memory buffer */
- if(H5S_select_fill(tconv_buf, dst_type_size, space, buf) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTENCODE, FAIL, "filling selection failed")
+ /* Fill the selection in the memory buffer */
+ if(H5S_select_fill(tconv_buf, dst_type_size, space, buf) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTENCODE, FAIL, "filling selection failed")
+ }
done:
+ if (tmp_buf)
+ H5FL_BLK_FREE(type_conv,tmp_buf);
if (tconv_buf)
H5FL_BLK_FREE(type_elem,tconv_buf);
- if (bkg_buf)
- H5FL_BLK_FREE(type_elem,bkg_buf);
+ if (bkg_buf) {
+ if(TRUE == H5T_detect_class(fill_type, H5T_VLEN))
+ H5FL_BLK_FREE(type_conv,bkg_buf);
+ else
+ H5FL_BLK_FREE(type_elem,bkg_buf);
+ }
FUNC_LEAVE_NOAPI(ret_value)
} /* H5D_fill() */