summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2007-06-05 15:40:36 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2007-06-05 15:40:36 (GMT)
commitda929510d630ae3ba14e1c088debd4e5726b200f (patch)
treeea0d4153d26ae500ae0ef180adf549ce083b6374
parentc72914018e247321c06ff167e5ff0e46a3b41553 (diff)
downloadhdf5-da929510d630ae3ba14e1c088debd4e5726b200f.zip
hdf5-da929510d630ae3ba14e1c088debd4e5726b200f.tar.gz
hdf5-da929510d630ae3ba14e1c088debd4e5726b200f.tar.bz2
[svn-r13835] Description:
Incremental step forward in fixing problems with fill values that have a variable-length datatype. This set of changes fixes problems with the copying the property list values. Tested On: Mac OS X/32 10.4.9 (amazon) Linux/32 2.6 (chicago) Linux/64 2.6 (chicago2)
-rw-r--r--src/H5A.c1
-rw-r--r--src/H5D.c53
-rw-r--r--src/H5Dio.c127
-rw-r--r--src/H5Dpkg.h2
-rw-r--r--src/H5Dprivate.h5
-rw-r--r--src/H5Ofill.c230
-rw-r--r--src/H5Pdcpl.c32
-rw-r--r--src/H5S.c3
-rw-r--r--src/H5Sprivate.h5
-rw-r--r--src/H5Sselect.c1
-rw-r--r--test/fillval.c95
11 files changed, 442 insertions, 112 deletions
diff --git a/src/H5A.c b/src/H5A.c
index 0ed8089..d6a0d32 100644
--- a/src/H5A.c
+++ b/src/H5A.c
@@ -22,6 +22,7 @@
/* Private header files */
#include "H5private.h" /* Generic Functions */
#include "H5Apkg.h" /* Attributes */
+#include "H5Dprivate.h" /* Datasets */
#include "H5Eprivate.h" /* Error handling */
#include "H5FLprivate.h" /* Free Lists */
#include "H5Gprivate.h" /* Groups */
diff --git a/src/H5D.c b/src/H5D.c
index d987d51..e7e90b0 100644
--- a/src/H5D.c
+++ b/src/H5D.c
@@ -91,6 +91,10 @@ H5D_dxpl_cache_t H5D_def_dxpl_cache;
/* Library Private Variables */
/*****************************/
+/* Declare extern the free list to manage blocks of type conversion data */
+H5FL_BLK_EXTERN(type_conv);
+
+
/*******************/
/* Local Variables */
/*******************/
@@ -1485,11 +1489,56 @@ H5Dget_create_plist(hid_t dset_id)
if(H5P_get(new_plist, H5D_CRT_FILL_VALUE_NAME, &copied_fill) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get fill value")
- /* Copy the dataset type into the fill value message */
- if(copied_fill.type==NULL)
+ /* Check if there is a fill value, but no type yet */
+ if(copied_fill.buf != NULL && copied_fill.type == NULL) {
+ H5T_path_t *tpath; /* Conversion information*/
+
+ /* Copy the dataset type into the fill value message */
if(NULL==(copied_fill.type=H5T_copy(dset->shared->type, H5T_COPY_TRANSIENT)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to copy dataset datatype for fill value")
+ /* Set up type conversion function */
+ if(NULL == (tpath = H5T_path_find(dset->shared->type, copied_fill.type, NULL, NULL, H5AC_ind_dxpl_id)))
+ HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest data types")
+
+ /* Convert disk form of fill value into memory form */
+ if(!H5T_path_noop(tpath)) {
+ hid_t dst_id, src_id; /* Source & destination datatypes for type conversion */
+ uint8_t *bkg_buf = NULL; /* Background conversion buffer */
+ size_t bkg_size; /* Size of background buffer */
+
+ /* Wrap copies of types to convert */
+ dst_id = H5I_register(H5I_DATATYPE, H5T_copy(copied_fill.type, H5T_COPY_TRANSIENT));
+ if(dst_id < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy/register datatype")
+ src_id = H5I_register(H5I_DATATYPE, H5T_copy(dset->shared->type, H5T_COPY_ALL));
+ if(src_id < 0) {
+ H5I_dec_ref(dst_id);
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy/register datatype")
+ } /* end if */
+
+ /* Allocate a background buffer */
+ bkg_size = MAX(H5T_get_size(copied_fill.type), H5T_get_size(dset->shared->type));
+ if(H5T_path_bkg(tpath) && NULL == (bkg_buf = H5FL_BLK_CALLOC(type_conv, bkg_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Convert fill value */
+ if(H5T_convert(tpath, src_id, dst_id, (size_t)1, (size_t)0, (size_t)0, copied_fill.buf, bkg_buf, H5AC_ind_dxpl_id) < 0) {
+ H5I_dec_ref(src_id);
+ H5I_dec_ref(dst_id);
+ if(bkg_buf)
+ H5FL_BLK_FREE(type_conv, bkg_buf);
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "datatype conversion failed")
+ } /* end if */
+
+ /* Release local resources */
+ H5I_dec_ref(src_id);
+ H5I_dec_ref(dst_id);
+ if(bkg_buf)
+ H5FL_BLK_FREE(type_conv, bkg_buf);
+ } /* end if */
+ } /* end if */
+
/* Set back the fill value property to property list */
if(H5P_set(new_plist, H5D_CRT_FILL_VALUE_NAME, &copied_fill) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to set property list fill value")
diff --git a/src/H5Dio.c b/src/H5Dio.c
index 57b7376..f488d86 100644
--- a/src/H5Dio.c
+++ b/src/H5Dio.c
@@ -269,79 +269,92 @@ H5D_fill(const void *fill, const H5T_t *fill_type, void *buf, const H5T_t *buf_t
/* 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")
+ } /* end if */
+ else {
+ /* Set up type conversion function */
+ if(NULL == (tpath = H5T_path_find(fill_type, buf_type, NULL, NULL, dxpl_id)))
+ HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest data types")
- HGOTO_DONE(ret_value);
- }
-
- /* Set up type conversion function */
- if(NULL == (tpath = H5T_path_find(fill_type, buf_type, NULL, NULL, dxpl_id)))
- 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")
- }
+ 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")
- /* Copy the user's data into the buffer for conversion */
- HDmemcpy(tconv_buf,fill,src_type_size);
+ 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")
+ } /* end if */
- 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.
- */
+ /* Copy the user's data into the buffer for conversion */
+ HDmemcpy(tconv_buf,fill,src_type_size);
- /* Get the number of elements */
- nelmts = H5S_get_simple_extent_npoints(space);
+ 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.
+ */
- /* 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")
+ /* Get the number of elements */
+ nelmts = H5S_get_simple_extent_npoints(space);
- /* 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(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 */
+ /* Allocate a temporary buffer */
+ if(NULL == (tmp_buf = H5FL_BLK_MALLOC(type_conv, (size_t)nelmts * buf_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
- /* 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")
+/* XXX: Should replicate the fill value into the temp. buffer elements, then
+ * type convert the temp. buffer, then scatter the temp. buffer elements
+ * to the user's buffer. - QAK, 2007/05/31
+ */
+ /* 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)) {
+ /* Allocate a background buffer */
+ if(NULL == (bkg_buf = H5FL_BLK_CALLOC(type_conv, (size_t)nelmts * buf_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ 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 */
- /* 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")
+ /* Copy the final data into the memory buffer */
+ HDmemcpy(buf, tmp_buf, (size_t)nelmts*dst_type_size);
} /* end if */
+ else {
+ /* Convert disk buffer into memory buffer */
+ if(!H5T_path_noop(tpath)) {
+ /* 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")
+
+ /* 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 */
- /* 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")
+ } /* end else */
+ } /* end else */
done:
- if (tmp_buf)
+ if(src_id != (-1) && H5I_dec_ref(src_id) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
+ if(dst_id != (-1) && H5I_dec_ref(dst_id) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
+ if(tmp_buf)
H5FL_BLK_FREE(type_conv,tmp_buf);
- if (tconv_buf)
+ if(tconv_buf)
H5FL_BLK_FREE(type_elem,tconv_buf);
- if (bkg_buf) {
+ if(bkg_buf) {
if(TRUE == H5T_detect_class(fill_type, H5T_VLEN))
- H5FL_BLK_FREE(type_conv,bkg_buf);
+ H5FL_BLK_FREE(type_conv, bkg_buf);
else
- H5FL_BLK_FREE(type_elem,bkg_buf);
- }
+ H5FL_BLK_FREE(type_elem, bkg_buf);
+ } /* end if */
+
FUNC_LEAVE_NOAPI(ret_value)
} /* H5D_fill() */
diff --git a/src/H5Dpkg.h b/src/H5Dpkg.h
index fdf25ab..85473d0 100644
--- a/src/H5Dpkg.h
+++ b/src/H5Dpkg.h
@@ -198,8 +198,6 @@ extern H5D_dxpl_cache_t H5D_def_dxpl_cache;
H5_DLL herr_t H5D_alloc_storage (H5F_t *f, hid_t dxpl_id, H5D_t *dset, H5D_time_alloc_t time_alloc,
hbool_t update_time, hbool_t full_overwrite);
-H5_DLL herr_t H5D_vlen_reclaim(hid_t type_id, H5S_t *space, hid_t plist_id,
- void *buf);
/* Functions that perform serial I/O operations */
H5_DLL herr_t H5D_select_fscat (H5D_io_info_t *io_info,
diff --git a/src/H5Dprivate.h b/src/H5Dprivate.h
index 8451d5d..d32d140 100644
--- a/src/H5Dprivate.h
+++ b/src/H5Dprivate.h
@@ -25,6 +25,7 @@
/* Private headers needed by this file */
#include "H5FDprivate.h" /* File drivers */
#include "H5Oprivate.h" /* Object headers */
+#include "H5Sprivate.h" /* Dataspaces */
/**************************/
/* Library Private Macros */
@@ -239,6 +240,10 @@ H5_DLL herr_t H5D_flush(const H5F_t *f, hid_t dxpl_id, unsigned flags);
H5_DLL herr_t H5D_get_dxpl_cache(hid_t dxpl_id, H5D_dxpl_cache_t **cache);
H5_DLL herr_t H5D_get_dxpl_cache_real(hid_t dxpl_id, H5D_dxpl_cache_t *cache);
+/* Functions that operate on vlen data */
+H5_DLL herr_t H5D_vlen_reclaim(hid_t type_id, H5S_t *space, hid_t plist_id,
+ void *buf);
+
/* Functions that operate on contiguous storage */
H5_DLL herr_t H5D_contig_delete(H5F_t *f, hid_t dxpl_id,
const H5O_layout_t *layout);
diff --git a/src/H5Ofill.c b/src/H5Ofill.c
index f97a9d4..2bdce23 100644
--- a/src/H5Ofill.c
+++ b/src/H5Ofill.c
@@ -23,12 +23,14 @@
#define H5O_PACKAGE /*suppress error about including H5Opkg */
#include "H5private.h" /* Generic Functions */
+#include "H5Dprivate.h" /* Datasets */
#include "H5Eprivate.h" /* Error handling */
#include "H5FLprivate.h" /* Free Lists */
#include "H5Iprivate.h" /* IDs */
#include "H5MMprivate.h" /* Memory management */
#include "H5Opkg.h" /* Object header functions */
#include "H5Pprivate.h" /* Property lists */
+#include "H5Sprivate.h" /* Dataspaces */
static void *H5O_fill_new_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p);
@@ -96,6 +98,9 @@ H5FL_DEFINE(H5O_fill_new_t);
/* Declare a free list to manage the H5O_fill_t struct */
H5FL_DEFINE(H5O_fill_t);
+/* Declare extern the free list to manage blocks of type conversion data */
+H5FL_BLK_EXTERN(type_conv);
+
/*-------------------------------------------------------------------------
* Function: H5O_fill_new_decode
@@ -303,6 +308,101 @@ H5O_fill_encode(H5F_t UNUSED *f, uint8_t *p, const void *_mesg)
/*-------------------------------------------------------------------------
+ * Function: H5O_fill_copy_dyn
+ *
+ * Purpose: Copy dynamic fill value fields
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, May 31, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_fill_copy_dyn(H5O_fill_t *dest, const H5O_fill_t *mesg)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5O_fill_copy_dyn)
+
+ HDassert(dest);
+ HDassert(mesg);
+
+ /* Copy data type of fill value */
+ if(mesg->type) {
+ if(NULL == (dest->type = H5T_copy(mesg->type, H5T_COPY_TRANSIENT)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy fill value data type");
+ } /* end if */
+ else
+ dest->type = NULL;
+
+ /* Copy fill value and its size */
+ if(mesg->buf) {
+ H5_CHECK_OVERFLOW(mesg->size,ssize_t,size_t);
+ if(NULL == (dest->buf = H5MM_malloc((size_t)mesg->size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fill value");
+ HDmemcpy(dest->buf, mesg->buf, (size_t)mesg->size);
+
+ /* Check for needing to convert/copy fill value */
+ if(mesg->type) {
+ H5T_path_t *tpath; /* Conversion information */
+
+ /* Set up type conversion function */
+ if(NULL == (tpath = H5T_path_find(mesg->type, dest->type, NULL, NULL, H5AC_ind_dxpl_id)))
+ HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest data types")
+
+ /* If necessary, convert fill value datatypes (which copies VL components, etc.) */
+ if(!H5T_path_noop(tpath)) {
+ hid_t dst_id, src_id; /* Source & destination datatypes for type conversion */
+ uint8_t *bkg_buf = NULL; /* Background conversion buffer */
+ size_t bkg_size; /* Size of background buffer */
+
+ /* Wrap copies of types to convert */
+ dst_id = H5I_register(H5I_DATATYPE, H5T_copy(dest->type, H5T_COPY_TRANSIENT));
+ if(dst_id < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy/register datatype")
+ src_id = H5I_register(H5I_DATATYPE, H5T_copy(mesg->type, H5T_COPY_ALL));
+ if(src_id < 0) {
+ H5I_dec_ref(dst_id);
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy/register datatype")
+ } /* end if */
+
+ /* Allocate a background buffer */
+ bkg_size = MAX(H5T_get_size(dest->type), H5T_get_size(mesg->type));
+ if(H5T_path_bkg(tpath) && NULL == (bkg_buf = H5FL_BLK_CALLOC(type_conv, bkg_size))) {
+ H5I_dec_ref(src_id);
+ H5I_dec_ref(dst_id);
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ } /* end if */
+
+ /* Convert fill value */
+ if(H5T_convert(tpath, src_id, dst_id, (size_t)1, (size_t)0, (size_t)0, dest->buf, bkg_buf, H5AC_ind_dxpl_id) < 0) {
+ H5I_dec_ref(src_id);
+ H5I_dec_ref(dst_id);
+ if(bkg_buf)
+ H5FL_BLK_FREE(type_conv, bkg_buf);
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "datatype conversion failed")
+ } /* end if */
+
+ /* Release the background buffer */
+ H5I_dec_ref(src_id);
+ H5I_dec_ref(dst_id);
+ if(bkg_buf)
+ H5FL_BLK_FREE(type_conv, bkg_buf);
+ } /* end if */
+ } /* end if */
+ } /* end if */
+ else
+ dest->buf = NULL;
+ dest->size = mesg->size;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_fill_copy_dyn() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5O_fill_new_copy
*
* Purpose: Copies a message from _MESG to _DEST, allocating _DEST if
@@ -335,24 +435,12 @@ H5O_fill_new_copy(const void *_mesg, void *_dest, unsigned UNUSED update_flags)
if (!dest && NULL==(dest=H5FL_MALLOC(H5O_fill_new_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill message");
- /* Copy data type of fill value */
- if (mesg->type) {
- if(NULL==(dest->type=H5T_copy(mesg->type, H5T_COPY_TRANSIENT)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy fill value data type");
- } /* end if */
- else
- dest->type=NULL;
+ /* Shallow copy basic fields */
+ *dest = *mesg;
- /* Copy fill value and its size */
- if (mesg->buf) {
- H5_CHECK_OVERFLOW(mesg->size,ssize_t,size_t);
- if (NULL==(dest->buf=H5MM_malloc((size_t)mesg->size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill value");
- HDmemcpy(dest->buf, mesg->buf, (size_t)mesg->size);
- } /* end if */
- else
- dest->buf=NULL;
- dest->size = mesg->size;
+ /* Copy dynamic fields */
+ if(H5O_fill_copy_dyn((H5O_fill_t *)dest, (const H5O_fill_t *)mesg) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTCOPY, NULL, "couldn't copy fill message");
/* Copy three fill value attributes */
dest->alloc_time = mesg->alloc_time;
@@ -407,21 +495,12 @@ H5O_fill_copy(const void *_mesg, void *_dest, unsigned UNUSED update_flags)
if (!dest && NULL==(dest=H5FL_CALLOC(H5O_fill_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill message");
- if (mesg->type) {
- if(NULL==(dest->type=H5T_copy(mesg->type, H5T_COPY_TRANSIENT)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy fill value data type");
- } /* end if */
- else
- dest->type=NULL;
+ /* Shallow copy basic fields */
+ *dest = *mesg;
- if (mesg->buf) {
- if (NULL==(dest->buf=H5MM_malloc(mesg->size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill value");
- HDmemcpy(dest->buf, mesg->buf, mesg->size);
- } /* end if */
- else
- dest->buf=NULL;
- dest->size = mesg->size;
+ /* Copy dynamic fields */
+ if(H5O_fill_copy_dyn((H5O_fill_t *)dest, (const H5O_fill_t *)mesg) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTCOPY, NULL, "couldn't copy fill message");
/* Set return value */
ret_value = dest;
@@ -434,10 +513,10 @@ done:
H5T_close(dest->type);
if (!_dest)
H5FL_FREE(H5O_fill_t,dest);
- }
+ } /* end if */
FUNC_LEAVE_NOAPI(ret_value);
-}
+} /* end H5O_fill_copy() */
/*-------------------------------------------------------------------------
@@ -515,6 +594,72 @@ H5O_fill_size(const H5F_t UNUSED *f, const void *_mesg)
/*-------------------------------------------------------------------------
+ * Function: H5O_fill_reset_dyn
+ *
+ * Purpose: Resets dynamic fill value fields
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Monday, January 22, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_fill_reset_dyn(H5O_fill_t *fill, ssize_t size_val)
+{
+ hid_t fill_type_id = -1; /* Datatype ID for fill value datatype when reclaiming VL fill values */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5O_fill_reset_dyn)
+
+ HDassert(fill);
+
+ if(fill->buf) {
+ if(fill->type && H5T_detect_class(fill->type, H5T_VLEN) > 0) {
+ H5T_t *fill_type; /* Copy of fill value datatype */
+ H5S_t *fill_space; /* Scalar dataspace for fill value element */
+
+ /* Copy the fill value datatype and get an ID for it */
+ if(NULL == (fill_type = H5T_copy(fill->type, H5T_COPY_TRANSIENT)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy fill value datatype")
+ if((fill_type_id = H5I_register(H5I_DATATYPE, fill_type)) < 0) {
+ H5T_close(fill_type);
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register fill value datatype")
+ } /* end if */
+
+ /* Create a scalar dataspace for the fill value element */
+ if(NULL == (fill_space = H5S_create(H5S_SCALAR)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create scalar dataspace")
+
+ /* Reclaim any variable length components of the fill value */
+ if(H5D_vlen_reclaim(fill_type_id, fill_space, H5P_DATASET_XFER_DEFAULT, fill->buf) < 0) {
+ H5S_close(fill_space);
+ HGOTO_ERROR(H5E_DATASET, H5E_BADITER, FAIL, "unable to reclaim variable-length fill value data")
+ } /* end if */
+
+ /* Release the scalar fill value dataspace */
+ H5S_close(fill_space);
+ } /* end if */
+
+ /* Release the fill value buffer now */
+ fill->buf = H5MM_xfree(fill->buf);
+ } /* end if */
+ fill->size = size_val;
+ if(fill->type) {
+ H5T_close(fill->type);
+ fill->type = NULL;
+ } /* end if */
+
+done:
+ if(fill_type_id > 0)
+ H5I_dec_ref(fill_type_id);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_fill_reset_dyn() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5O_fill_new_reset
*
* Purpose: Resets a new message to an initial state. The new fill value
@@ -539,13 +684,9 @@ H5O_fill_new_reset(void *_mesg)
assert(mesg);
- if(mesg->buf)
- mesg->buf = H5MM_xfree(mesg->buf);
- mesg->size = -1;
- if (mesg->type) {
- H5T_close(mesg->type);
- mesg->type = NULL;
- }
+ /* Reset dynamic fields */
+ H5O_fill_reset_dyn((H5O_fill_t *)mesg, -1);
+
mesg->alloc_time = (H5D_alloc_time_t)0;
mesg->fill_time = (H5D_fill_time_t)0;
mesg->fill_defined = FALSE;
@@ -577,13 +718,8 @@ H5O_fill_reset(void *_mesg)
assert(mesg);
- if(mesg->buf)
- mesg->buf = H5MM_xfree(mesg->buf);
- mesg->size = 0;
- if (mesg->type) {
- H5T_close(mesg->type);
- mesg->type = NULL;
- }
+ /* Reset dynamic fields */
+ H5O_fill_reset_dyn(mesg, 0);
FUNC_LEAVE_NOAPI(SUCCEED);
}
diff --git a/src/H5Pdcpl.c b/src/H5Pdcpl.c
index 58cca67..1604355 100644
--- a/src/H5Pdcpl.c
+++ b/src/H5Pdcpl.c
@@ -36,6 +36,9 @@
/* Static function prototypes */
static herr_t H5P_set_layout(H5P_genplist_t *plist, H5D_layout_t layout);
+/* Declare extern the free list to manage blocks of type conversion data */
+H5FL_BLK_EXTERN(type_conv);
+
/*-------------------------------------------------------------------------
* Function: H5P_set_layout
@@ -1246,7 +1249,6 @@ herr_t
H5Pset_fill_value(hid_t plist_id, hid_t type_id, const void *value)
{
H5O_fill_t fill;
- H5T_t *type = NULL;
H5P_genplist_t *plist; /* Property list pointer */
herr_t ret_value=SUCCEED; /* return value */
@@ -1266,6 +1268,10 @@ H5Pset_fill_value(hid_t plist_id, hid_t type_id, const void *value)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't reset fill value");
if(value) {
+ H5T_t *type; /* Datatype for fill value */
+ H5T_path_t *tpath; /* Conversion information */
+
+ /* Retrieve pointer to datatype */
if (NULL==(type=H5I_object_verify(type_id, H5I_DATATYPE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
@@ -1276,6 +1282,30 @@ H5Pset_fill_value(hid_t plist_id, hid_t type_id, const void *value)
if (NULL==(fill.buf=H5MM_malloc(fill.size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "memory allocation failed for fill value");
HDmemcpy(fill.buf, value, fill.size);
+
+ /* Set up type conversion function */
+ if(NULL == (tpath = H5T_path_find(type, type, NULL, NULL, H5AC_ind_dxpl_id)))
+ HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest data types")
+
+ /* If necessary, convert fill value datatypes (which copies VL components, etc.) */
+ if(!H5T_path_noop(tpath)) {
+ uint8_t *bkg_buf = NULL; /* Background conversion buffer */
+
+ /* Allocate a background buffer */
+ if(H5T_path_bkg(tpath) && NULL == (bkg_buf = H5FL_BLK_CALLOC(type_conv, (size_t)fill.size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Convert the fill value */
+ if(H5T_convert(tpath, type_id, type_id, (size_t)1, (size_t)0, (size_t)0, fill.buf, bkg_buf, H5AC_ind_dxpl_id) < 0) {
+ if(bkg_buf)
+ H5FL_BLK_FREE(type_conv, bkg_buf);
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "datatype conversion failed")
+ } /* end if */
+
+ /* Release the background buffer */
+ if(bkg_buf)
+ H5FL_BLK_FREE(type_conv, bkg_buf);
+ } /* end if */
} else {
fill.type = fill.buf = NULL;
fill.size = (size_t)-1;
diff --git a/src/H5S.c b/src/H5S.c
index fb1f349..4598af2 100644
--- a/src/H5S.c
+++ b/src/H5S.c
@@ -29,7 +29,6 @@
#include "H5Spkg.h" /* Dataspaces */
/* Local static function prototypes */
-static H5S_t * H5S_create(H5S_class_t type);
static herr_t H5S_set_extent_simple (H5S_t *space, unsigned rank,
const hsize_t *dims, const hsize_t *max);
static htri_t H5S_is_simple(const H5S_t *sdim);
@@ -289,7 +288,7 @@ H5S_term_interface(void)
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-static H5S_t *
+H5S_t *
H5S_create(H5S_class_t type)
{
H5S_t *ret_value;
diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h
index 558fb93..d316c38 100644
--- a/src/H5Sprivate.h
+++ b/src/H5Sprivate.h
@@ -21,9 +21,11 @@
#include "H5Spublic.h"
+/* Public headers needed by this file */
+#include "H5Dpublic.h" /* Datasets */
+
/* Private headers needed by this file */
#include "H5private.h" /* Generic Functions */
-#include "H5Dprivate.h" /* Dataset functions */
#include "H5Fprivate.h" /* Files */
#include "H5Gprivate.h" /* Groups */
#include "H5Oprivate.h" /* Object headers */
@@ -207,6 +209,7 @@ H5_DLL H5S_t *H5S_read(const struct H5G_entry_t *ent, hid_t dxpl_id);
H5_DLL int H5S_extend(H5S_t *space, const hsize_t *size);
H5_DLL int H5S_set_extent(H5S_t *space, const hsize_t *size);
H5_DLL herr_t H5S_set_extent_real(H5S_t *space, const hsize_t *size);
+H5_DLL H5S_t *H5S_create(H5S_class_t type);
H5_DLL H5S_t *H5S_create_simple(unsigned rank, const hsize_t dims[/*rank*/],
const hsize_t maxdims[/*rank*/]);
H5_DLL herr_t H5S_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE *stream,
diff --git a/src/H5Sselect.c b/src/H5Sselect.c
index 298f54c..5b4d868 100644
--- a/src/H5Sselect.c
+++ b/src/H5Sselect.c
@@ -23,6 +23,7 @@
#include "H5private.h" /* Generic Functions */
+#include "H5Dprivate.h" /* Datasets */
#include "H5Eprivate.h" /* Error handling */
#include "H5FLprivate.h" /* Free Lists */
#include "H5Iprivate.h" /* IDs */
diff --git a/test/fillval.c b/test/fillval.c
index 13f1d2e..2a63f4b 100644
--- a/test/fillval.c
+++ b/test/fillval.c
@@ -217,6 +217,100 @@ test_getset(void)
/*-------------------------------------------------------------------------
+ * Function: test_getset_vl
+ *
+ * Purpose: Tests the H5Pget_fill_value() and H5Pset_fill_value()
+ * functions, using variable-length datatype.
+ *
+ * Return: Success: 0
+ * Failure: number of errors
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, May 31, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_getset_vl(hid_t fapl)
+{
+ hsize_t dims[1] = {2};
+ hid_t fileid = (-1), spaceid = (-1), typeid = (-1), datasetid = (-1), plistid = (-1);
+ char fill_value[] = "aaaa";
+ char orig_fill_value[] = "aaaa";
+ char *f1 = fill_value;
+ char *f2;
+ char filename[1024];
+
+ TESTING("property lists, with variable-length datatype");
+
+ /* Create string type. */
+ if((typeid = H5Tcopy(H5T_C_S1)) < 0) TEST_ERROR
+ if(H5Tset_size(typeid, H5T_VARIABLE) < 0) TEST_ERROR
+
+ /* Set up dataset creation property list, with fill value */
+ if((plistid = H5Pcreate(H5P_DATASET_CREATE)) < 0) TEST_ERROR
+ if(H5Pset_fill_value(plistid, typeid, &f1) < 0) TEST_ERROR
+
+ /* Modify original fill value string */
+ fill_value[0] = 'b';
+
+ /* Retrieve fill value from property */
+ if(H5Pget_fill_value(plistid, typeid, &f2) < 0) TEST_ERROR
+
+ /* Verify that the fill value is the original value */
+ if(HDstrcmp(f2, orig_fill_value)) TEST_ERROR
+
+ /* Release the fill value retrieved */
+ HDfree(f2);
+
+ /* Open file. */
+ h5_fixname(FILENAME[0], fapl, filename, sizeof filename);
+ if((fileid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
+
+ /* Write an dataset of this type. */
+ if((spaceid = H5Screate_simple(1, dims, NULL)) < 0) TEST_ERROR
+ if((datasetid = H5Dcreate(fileid, "Dataset", typeid, spaceid, plistid)) < 0) TEST_ERROR
+
+ /* Close IDs (except datatype) */
+ if(H5Dclose(datasetid) < 0) TEST_ERROR
+ if(H5Pclose(plistid) < 0) TEST_ERROR
+ if(H5Sclose(spaceid) < 0) TEST_ERROR
+ if(H5Fclose(fileid) < 0) TEST_ERROR
+
+
+ /* Re-open file, group & dataset */
+ if((fileid = H5Fopen(filename, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) TEST_ERROR
+ if((datasetid = H5Dopen(fileid, "Dataset")) < 0) TEST_ERROR
+
+ /* Get dataset's creation property list */
+ if((plistid = H5Dget_create_plist(datasetid)) < 0) TEST_ERROR
+
+ /* Query fill value */
+ if(H5Pget_fill_value(plistid, typeid, &f2) < 0) TEST_ERROR
+
+ /* Verify that the fill value is the original value */
+ if(HDstrcmp(f2, orig_fill_value)) TEST_ERROR
+
+ /* Release the fill value retrieved */
+ HDfree(f2);
+
+ /* Close IDs */
+ if(H5Dclose(datasetid) < 0) TEST_ERROR
+ if(H5Fclose(fileid) < 0) TEST_ERROR
+ if(H5Pclose(plistid) < 0) TEST_ERROR
+ if(H5Tclose(typeid) < 0) TEST_ERROR
+
+ PASSED();
+ return 0;
+
+ error:
+ H5E_BEGIN_TRY {
+ } H5E_END_TRY;
+ return 1;
+} /* end test_getset_vl() */
+
+
+/*-------------------------------------------------------------------------
* Function: test_create
*
* Purpose: Tests creating datasets that have fill values.
@@ -1433,6 +1527,7 @@ main(int argc, char *argv[])
fapl = h5_fileaccess();
nerrors += test_getset();
+ nerrors += test_getset_vl(fapl);
/* Chunked storage layout tests */
if (test_chunk) {