diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2007-06-05 15:40:36 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2007-06-05 15:40:36 (GMT) |
commit | da929510d630ae3ba14e1c088debd4e5726b200f (patch) | |
tree | ea0d4153d26ae500ae0ef180adf549ce083b6374 | |
parent | c72914018e247321c06ff167e5ff0e46a3b41553 (diff) | |
download | hdf5-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.c | 1 | ||||
-rw-r--r-- | src/H5D.c | 53 | ||||
-rw-r--r-- | src/H5Dio.c | 127 | ||||
-rw-r--r-- | src/H5Dpkg.h | 2 | ||||
-rw-r--r-- | src/H5Dprivate.h | 5 | ||||
-rw-r--r-- | src/H5Ofill.c | 230 | ||||
-rw-r--r-- | src/H5Pdcpl.c | 32 | ||||
-rw-r--r-- | src/H5S.c | 3 | ||||
-rw-r--r-- | src/H5Sprivate.h | 5 | ||||
-rw-r--r-- | src/H5Sselect.c | 1 | ||||
-rw-r--r-- | test/fillval.c | 95 |
11 files changed, 442 insertions, 112 deletions
@@ -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 */ @@ -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; @@ -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) { |