From 40160d4d740ff706520b396fd9367089e8e4e2a2 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Fri, 15 Jun 2007 12:52:25 -0500 Subject: [svn-r13870] Description: Fix writing variable-length datatype fill values for contiguous dataset storage Tested on: Mac OS X/32 10.4.9 (amazon) Linux/32 2.6 (chicago) Linux/64 2.6 (chicago2) --- src/H5Dcontig.c | 171 +++++++++++++++++++++++++++++-------- src/H5Dio.c | 109 ++++++++++++++---------- src/H5Sprivate.h | 4 +- src/H5Sselect.c | 6 +- test/tvltypes.c | 254 +++++++++++++++++++++++++++++++++++++------------------ 5 files changed, 376 insertions(+), 168 deletions(-) diff --git a/src/H5Dcontig.c b/src/H5Dcontig.c index 6cdee41..e4329ff 100644 --- a/src/H5Dcontig.c +++ b/src/H5Dcontig.c @@ -129,24 +129,31 @@ H5D_contig_fill(H5D_t *dset, hid_t dxpl_id) { H5D_storage_t store; /* Union of storage info for dataset */ H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */ - H5D_dxpl_cache_t *dxpl_cache=&_dxpl_cache; /* Data transfer property cache */ + H5D_dxpl_cache_t *dxpl_cache = &_dxpl_cache; /* Data transfer property cache */ hssize_t snpoints; /* Number of points in space (for error checking) */ size_t npoints; /* Number of points in space */ size_t ptsperbuf; /* Maximum # of points which fit in the buffer */ size_t elmt_size; /* Size of each element */ size_t bufsize = H5D_TEMP_BUF_SIZE; /* Size of buffer to write */ - size_t size; /* Current # of points to write */ hsize_t offset; /* Offset of dataset */ void *buf = NULL; /* Buffer for fill value writing */ #ifdef H5_HAVE_PARALLEL - MPI_Comm mpi_comm=MPI_COMM_NULL; /* MPI communicator for file */ - int mpi_rank=(-1); /* This process's rank */ + MPI_Comm mpi_comm = MPI_COMM_NULL; /* MPI communicator for file */ + int mpi_rank = (-1); /* This process's rank */ int mpi_code; /* MPI return code */ hbool_t blocks_written = FALSE; /* Flag to indicate that chunk was actually written */ hbool_t using_mpi = FALSE; /* Flag to indicate that the file is being accessed with an MPI-capable file driver */ #endif /* H5_HAVE_PARALLEL */ - int non_zero_fill_f = (-1); /* Indicate that a non-zero fill-value was used */ - herr_t ret_value = SUCCEED; /* Return value */ + htri_t non_zero_fill_f = (-1); /* Indicate that a non-zero fill-value was used */ + H5T_path_t *fill_to_mem_tpath; /* Datatype conversion path for converting the fill value to the memory buffer */ + H5T_path_t *mem_to_dset_tpath; /* Datatype conversion path for converting the memory buffer to the dataset elements */ + uint8_t *bkg_buf = NULL; /* Background conversion buffer */ + H5T_t *mem_type = NULL; /* Pointer to memory datatype */ + size_t mem_type_size, file_type_size; /* Size of datatype in memory and on disk */ + hid_t mem_tid = (-1); /* Memory version of disk datatype */ + size_t bkg_buf_size; /* Size of background buffer */ + hbool_t has_vlen_fill_type = FALSE; /* Whether the datatype for the fill value has a variable-length component */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5D_contig_fill, FAIL) @@ -156,6 +163,7 @@ H5D_contig_fill(H5D_t *dset, hid_t dxpl_id) HDassert(H5F_addr_defined(dset->shared->layout.u.contig.addr)); HDassert(dset->shared->layout.u.contig.size > 0); HDassert(dset->shared->space); + HDassert(dset->shared->type); #ifdef H5_HAVE_PARALLEL /* Retrieve MPI parameters */ @@ -185,46 +193,82 @@ H5D_contig_fill(H5D_t *dset, hid_t dxpl_id) #endif /* H5_HAVE_PARALLEL */ /* Initialize storage info for this dataset */ - store.contig.dset_addr=dset->shared->layout.u.contig.addr; - store.contig.dset_size=dset->shared->layout.u.contig.size; - - /* Get size of elements */ - elmt_size = H5T_get_size(dset->shared->type); - HDassert(elmt_size > 0); + store.contig.dset_addr = dset->shared->layout.u.contig.addr; + store.contig.dset_size = dset->shared->layout.u.contig.size; /* Get the number of elements in the dataset's dataspace */ snpoints = H5S_GET_EXTENT_NPOINTS(dset->shared->space); HDassert(snpoints >= 0); H5_ASSIGN_OVERFLOW(npoints, snpoints, hssize_t, size_t); - /* If fill value is not library default, use it to set the element size */ - if(dset->shared->dcpl_cache.fill.buf) - elmt_size = dset->shared->dcpl_cache.fill.size; - - /* - * Fill the entire current extent with the fill value. We can do - * this quite efficiently by making sure we copy the fill value - * in relatively large pieces. - */ - ptsperbuf = MAX(1, bufsize / elmt_size); - bufsize = ptsperbuf * elmt_size; - /* Fill the buffer with the user's fill value */ if(dset->shared->dcpl_cache.fill.buf) { - /* Allocate temporary buffer */ - if(NULL == (buf = H5FL_BLK_MALLOC(non_zero_fill, bufsize))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fill buffer") + /* Indicate that a non-zero fill buffer will be used */ + non_zero_fill_f = TRUE; + + /* Detect whether the datatype has a VL component */ + has_vlen_fill_type = H5T_detect_class(dset->shared->type, H5T_VLEN); + + /* If necessary, convert fill value datatypes (which copies VL components, etc.) */ + if(has_vlen_fill_type) { + /* Create temporary datatype for conversion operation */ + if(NULL == (mem_type = H5T_copy(dset->shared->type, H5T_COPY_REOPEN))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "unable to copy file datatype") + if((mem_tid = H5I_register(H5I_DATATYPE, mem_type)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register memory datatype") + + /* Retrieve sizes of memory & file datatypes */ + mem_type_size = H5T_get_size(mem_type); + HDassert(mem_type_size > 0); + file_type_size = H5T_get_size(dset->shared->type); + HDassert(file_type_size == (size_t)dset->shared->dcpl_cache.fill.size); + + /* If fill value is not library default, use it to set the element size */ + elmt_size = MAX(mem_type_size, file_type_size); + + /* Compute the number of elements that fit within a buffer to write */ + ptsperbuf = MIN(npoints, MAX(1, bufsize / elmt_size)); + bufsize = MAX(bufsize, ptsperbuf * elmt_size); + + /* Allocate temporary buffer */ + if(NULL == (buf = H5FL_BLK_MALLOC(non_zero_fill, bufsize))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fill buffer") + + /* Get the datatype conversion path for this operation */ + if(NULL == (fill_to_mem_tpath = H5T_path_find(dset->shared->type, mem_type, NULL, NULL, dxpl_id, FALSE))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert between src and dst datatypes") + + /* Allocate a background buffer, if necessary */ + bkg_buf_size = ptsperbuf * elmt_size; + if(H5T_path_bkg(fill_to_mem_tpath) && NULL == (bkg_buf = H5FL_BLK_MALLOC(type_conv, bkg_buf_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Get the inverse datatype conversion path for this operation */ + if(NULL == (mem_to_dset_tpath = H5T_path_find(mem_type, dset->shared->type, NULL, NULL, dxpl_id, FALSE))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert between src and dst datatypes") + + /* Allocate the background buffer, if necessary */ + if(H5T_path_bkg(mem_to_dset_tpath) && NULL == (bkg_buf = H5FL_BLK_MALLOC(type_conv, bkg_buf_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + } /* end if */ + else { + /* If fill value is not library default, use it to set the element size */ + elmt_size = dset->shared->dcpl_cache.fill.size; + + /* Compute the number of elements that fit within a buffer to write */ + ptsperbuf = MIN(npoints, MAX(1, bufsize / elmt_size)); + bufsize = MAX(bufsize, ptsperbuf * elmt_size); - H5V_array_fill(buf, dset->shared->dcpl_cache.fill.buf, elmt_size, ptsperbuf); + /* Allocate temporary buffer */ + if(NULL == (buf = H5FL_BLK_MALLOC(non_zero_fill, bufsize))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fill buffer") - /* Indicate that a non-zero fill buffer was used */ - non_zero_fill_f = 1; + /* Replicate the fill value into the cached buffer */ + H5V_array_fill(buf, dset->shared->dcpl_cache.fill.buf, elmt_size, ptsperbuf); + } /* end else */ } /* end if */ else { /* Fill the buffer with the default fill value */ - htri_t buf_avail; - - /* Check if there is an already zeroed out buffer available */ - buf_avail = H5FL_BLK_AVAIL(zero_fill, bufsize); + htri_t buf_avail = H5FL_BLK_AVAIL(zero_fill, bufsize); /* Check if there is an already zeroed out buffer available */ HDassert(buf_avail != FAIL); /* Allocate temporary buffer (zeroing it if no buffer is available) */ @@ -235,16 +279,59 @@ H5D_contig_fill(H5D_t *dset, hid_t dxpl_id) if(buf == NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fill buffer") + /* Retrieve size of elements */ + elmt_size = H5T_get_size(dset->shared->type); + HDassert(elmt_size > 0); + + /* Compute the number of elements that fit within a buffer to write */ + ptsperbuf = MIN(npoints, MAX(1, bufsize / elmt_size)); + /* Indicate that a zero fill buffer was used */ - non_zero_fill_f = 0; + non_zero_fill_f = FALSE; } /* end else */ /* Start at the beginning of the dataset */ offset = 0; + /* + * Fill the entire current extent with the fill value. We can do + * this quite efficiently by making sure we copy the fill value + * in relatively large pieces. + */ + /* Loop through writing the fill value to the dataset */ while(npoints > 0) { - size = MIN(ptsperbuf, npoints) * elmt_size; + size_t curr_points; /* Number of elements to write on this iteration of the loop */ + size_t size; /* Size of buffer to write */ + + /* Compute # of elements and buffer size to write for this iteration */ + curr_points = MIN(ptsperbuf, npoints); + size = curr_points * elmt_size; + + /* Check for VL datatype & non-default fill value */ + if(has_vlen_fill_type) { + /* Make a copy of the (disk-based) fill value into the buffer */ + HDmemcpy(buf, dset->shared->dcpl_cache.fill.buf, file_type_size); + + /* Reset the background buffer, if necessary */ + if(H5T_path_bkg(fill_to_mem_tpath)) + HDmemset(bkg_buf, 0, bkg_buf_size); + + /* Type convert the dataset buffer, to copy any VL components */ + if(H5T_convert(fill_to_mem_tpath, dset->shared->type_id, mem_tid, (size_t)1, (size_t)0, (size_t)0, buf, bkg_buf, dxpl_id) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "data type conversion failed") + + /* Replicate the fill value into the cached buffer */ + H5V_array_fill(buf, buf, mem_type_size, curr_points); + + /* Reset the background buffer, if necessary */ + if(H5T_path_bkg(mem_to_dset_tpath)) + HDmemset(bkg_buf, 0, bkg_buf_size); + + /* Type convert the dataset buffer, to copy any VL components */ + if(H5T_convert(mem_to_dset_tpath, mem_tid, dset->shared->type_id, curr_points, (size_t)0, (size_t)0, buf, bkg_buf, dxpl_id) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "data type conversion failed") + } /* end if */ #ifdef H5_HAVE_PARALLEL /* Check if this file is accessed with an MPI-capable file driver */ @@ -267,7 +354,7 @@ H5D_contig_fill(H5D_t *dset, hid_t dxpl_id) } /* end else */ #endif /* H5_HAVE_PARALLEL */ - npoints -= MIN(ptsperbuf, npoints); + npoints -= curr_points; offset += size; } /* end while */ @@ -294,6 +381,16 @@ done: H5FL_BLK_FREE(zero_fill, buf); } /* end if */ + /* Free other resources for vlen fill values */ + if(has_vlen_fill_type) { + if(mem_tid > 0) + H5I_dec_ref(mem_tid); + else if(mem_type) + H5T_close(mem_type); + if(bkg_buf) + H5FL_BLK_FREE(type_conv, bkg_buf); + } /* end if */ + FUNC_LEAVE_NOAPI(ret_value) } /* end H5D_contig_fill() */ diff --git a/src/H5Dio.c b/src/H5Dio.c index 3c36953..b494596 100644 --- a/src/H5Dio.c +++ b/src/H5Dio.c @@ -202,24 +202,22 @@ done: 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; /* 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 */ FUNC_ENTER_NOAPI_NOINIT(H5D_fill) /* Check args */ - assert(fill_type); - assert(buf); - assert(buf_type); - assert(space); + HDassert(fill_type); + HDassert(buf); + HDassert(buf_type); + HDassert(space); /* Make sure the dataspace has an extent set (or is NULL) */ if(!(H5S_has_extent(space))) @@ -230,25 +228,26 @@ H5D_fill(const void *fill, const H5T_t *fill_type, void *buf, const H5T_t *buf_t dst_type_size = H5T_get_size(buf_type); /* Get the maximum buffer size needed and allocate it */ - buf_size = MAX(src_type_size,dst_type_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") + buf_size = MAX(src_type_size, dst_type_size); /* If there's no fill value, just use zeros */ if(fill == NULL) { - HDmemset(tconv_buf, 0, dst_type_size); + /* Allocate space & initialize conversion buffer to zeros */ + if(NULL == (tconv_buf = H5FL_BLK_CALLOC(type_elem, buf_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation 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 if */ else { + H5T_path_t *tpath; /* Conversion path information */ + /* 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 datatype") + /* Construct source & destination datatype IDs, if we will need them */ 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") @@ -257,46 +256,65 @@ H5D_fill(const void *fill, const H5T_t *fill_type, void *buf, const H5T_t *buf_t HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register types for conversion") } /* end if */ - /* Copy the user's data into the buffer for conversion */ - HDmemcpy(tconv_buf, fill, src_type_size); - + /* 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. + */ 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. - */ + H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */ + H5D_dxpl_cache_t *dxpl_cache = &_dxpl_cache; /* Data transfer property cache */ + H5S_sel_iter_t mem_iter; /* Memory selection iteration info */ + hssize_t nelmts; /* Number of data elements */ - /* Get the number of elements */ - nelmts = H5S_get_simple_extent_npoints(space); + /* Get the number of elements in the selection */ + nelmts = H5S_GET_SELECT_NPOINTS(space); + HDassert(nelmts >= 0); + H5_CHECK_OVERFLOW(nelmts, hssize_t, size_t); /* 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") -/* 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(H5T_path_bkg(tpath) && NULL == (bkg_buf = H5FL_BLK_CALLOC(type_conv, (size_t)nelmts * buf_size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + /* Allocate a background buffer, if necessary */ + if(H5T_path_bkg(tpath) && NULL == (bkg_buf = H5FL_BLK_CALLOC(type_conv, (size_t)nelmts * buf_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") - /* Perform datatype 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, "datatype conversion failed") + /* Replicate the file's fill value into the temporary buffer */ + H5V_array_fill(tmp_buf, fill, src_type_size, (size_t)nelmts); + + /* Convert from file's fill value into memory form */ + 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") + + /* Fill the DXPL cache values for later use */ + if(H5D_get_dxpl_cache(dxpl_id, &dxpl_cache) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache") + + /* Create a selection iterator for scattering the elements to memory buffer */ + if(H5S_select_iter_init(&mem_iter, space, dst_type_size) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize memory selection information") + + /* Scatter the data into memory */ + if(H5D_select_mscat(tmp_buf, space, &mem_iter, (size_t)nelmts, dxpl_cache, buf/*out*/) < 0) { + H5S_SELECT_ITER_RELEASE(&mem_iter); + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "scatter failed") } /* end if */ - /* Copy the final data into the memory buffer */ - HDmemcpy(buf, tmp_buf, (size_t)nelmts * dst_type_size); + /* Release the selection iterator */ + if(H5S_SELECT_ITER_RELEASE(&mem_iter) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator") } else { + const uint8_t *fill_buf; /* Buffer to use for writing fill values */ + /* Convert disk buffer into memory buffer */ if(!H5T_path_noop(tpath)) { + /* 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") + + /* Copy the user's data into the buffer for conversion */ + HDmemcpy(tconv_buf, fill, src_type_size); + /* If there's no VL type of data, do conversion first then fill the data into * the memory buffer. */ if(H5T_path_bkg(tpath) && NULL == (bkg_buf = H5FL_BLK_CALLOC(type_elem, buf_size))) @@ -304,11 +322,16 @@ H5D_fill(const void *fill, const H5T_t *fill_type, void *buf, const H5T_t *buf_t /* Perform datatype 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, "datatype conversion failed") + HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "data type conversion failed") + + /* Point at temporary buffer */ + fill_buf = tconv_buf; } /* end if */ + else + fill_buf = fill; /* Fill the selection in the memory buffer */ - if(H5S_select_fill(tconv_buf, dst_type_size, space, buf) < 0) + if(H5S_select_fill(fill_buf, dst_type_size, space, buf) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTENCODE, FAIL, "filling selection failed") } /* end else */ } /* end else */ @@ -319,9 +342,9 @@ done: 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); + H5FL_BLK_FREE(type_conv, tmp_buf); if(tconv_buf) - H5FL_BLK_FREE(type_elem,tconv_buf); + H5FL_BLK_FREE(type_elem, tconv_buf); if(bkg_buf) { if(TRUE == H5T_detect_class(fill_type, H5T_VLEN)) H5FL_BLK_FREE(type_conv, bkg_buf); diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h index 4a40bee..1892e18 100644 --- a/src/H5Sprivate.h +++ b/src/H5Sprivate.h @@ -224,8 +224,8 @@ H5_DLL herr_t H5S_select_deserialize(H5S_t *space, const uint8_t *buf); H5_DLL H5S_sel_type H5S_get_select_type(const H5S_t *space); H5_DLL herr_t H5S_select_iterate(void *buf, hid_t type_id, const H5S_t *space, H5D_operator_t op, void *operator_data); -H5_DLL herr_t H5S_select_fill(void *fill, size_t fill_size, const H5S_t *space, - void *buf); +H5_DLL herr_t H5S_select_fill(const void *fill, size_t fill_size, + const H5S_t *space, void *buf); H5_DLL htri_t H5S_select_valid(const H5S_t *space); H5_DLL hssize_t H5S_get_select_npoints(const H5S_t *space); H5_DLL herr_t H5S_get_select_bounds(const H5S_t *space, hsize_t *start, hsize_t *end); diff --git a/src/H5Sselect.c b/src/H5Sselect.c index d36e217..666c8da 100644 --- a/src/H5Sselect.c +++ b/src/H5Sselect.c @@ -1434,12 +1434,12 @@ done: REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5S_select_fill(void *_fill, size_t fill_size, const H5S_t *space, void *_buf) +H5S_select_fill(const void *_fill, size_t fill_size, const H5S_t *space, void *_buf) { H5S_sel_iter_t iter; /* Selection iteration info */ hbool_t iter_init=0; /* Selection iteration info has been initialized */ uint8_t *buf; /* Current location in buffer */ - void *fill=_fill; /* Alias for fill-value buffer */ + const void *fill=_fill; /* Alias for fill-value buffer */ hssize_t nelmts; /* Number of elements in selection */ hsize_t off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets */ size_t len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths */ @@ -1503,7 +1503,7 @@ done: /* Release fill value, if allocated */ if(_fill==NULL && fill) - H5FL_BLK_FREE(type_elem,fill); + H5FL_BLK_FREE(type_elem, (void *)fill); /* casting away const OK - QAK */ FUNC_LEAVE_NOAPI(ret_value); } /* H5S_select_fill() */ diff --git a/test/tvltypes.c b/test/tvltypes.c index c41bf0e..446ba07 100644 --- a/test/tvltypes.c +++ b/test/tvltypes.c @@ -24,6 +24,7 @@ #include "testhdf5.h" #include "hdf5.h" +#include "H5Dprivate.h" #define FILENAME "tvltypes.h5" @@ -43,6 +44,11 @@ #define L2_INCM 8 #define L3_INCM 3 +/* 1-D dataset with fixed dimensions */ +#define SPACE4_RANK 1 +#define SPACE4_DIM_SMALL 128 +#define SPACE4_DIM_LARGE (H5D_TEMP_BUF_SIZE / 64) + void *test_vltypes_alloc_custom(size_t size, void *info); void test_vltypes_free_custom(void *mem, void *info); @@ -54,23 +60,21 @@ void test_vltypes_free_custom(void *mem, void *info); ** allocated. ** ****************************************************************/ -void *test_vltypes_alloc_custom(size_t size, void *info) +void *test_vltypes_alloc_custom(size_t size, void *mem_used) { - void *ret_value=NULL; /* Pointer to return */ - size_t *mem_used=(size_t *)info; /* Get the pointer to the memory used */ - size_t extra; /* Extra space needed */ - - /* - * This weird contortion is required on the DEC Alpha to keep the - * alignment correct - QAK - */ - extra=MAX(sizeof(void *),sizeof(size_t)); - - if((ret_value=HDmalloc(extra+size))!=NULL) { - *(size_t *)ret_value=size; - *mem_used+=size; + void *ret_value; /* Pointer to return */ + const size_t extra = MAX(sizeof(void *), sizeof(size_t)); /* Extra space needed */ + /* (This weird contortion is required on the + * DEC Alpha to keep the alignment correct - QAK) + */ + + if((ret_value = HDmalloc(extra + size)) != NULL) { + *(size_t *)ret_value = size; + *(size_t *)mem_used += size; } /* end if */ - ret_value=((unsigned char *)ret_value)+extra; + + ret_value = ((unsigned char *)ret_value) + extra; + return(ret_value); } @@ -82,21 +86,17 @@ void *test_vltypes_alloc_custom(size_t size, void *info) ** allocated. ** ****************************************************************/ -void test_vltypes_free_custom(void *_mem, void *info) +void test_vltypes_free_custom(void *_mem, void *mem_used) { - unsigned char *mem; - size_t *mem_used=(size_t *)info; /* Get the pointer to the memory used */ - size_t extra; /* Extra space needed */ - - /* - * This weird contortion is required on the DEC Alpha to keep the - * alignment correct - QAK - */ - extra=MAX(sizeof(void *),sizeof(size_t)); - - if(_mem!=NULL) { - mem=((unsigned char *)_mem)-extra; - *mem_used-=*(size_t *)mem; + if(_mem) { + const size_t extra = MAX(sizeof(void *), sizeof(size_t)); /* Extra space needed */ + /* (This weird contortion is required + * on the DEC Alpha to keep the + * alignment correct - QAK) + */ + unsigned char *mem = ((unsigned char *)_mem) - extra; /* Pointer to actual block allocated */ + + *(size_t *)mem_used -= *(size_t *)mem; HDfree(mem); } /* end if */ } @@ -2416,21 +2416,25 @@ test_vltypes_fill_value(void) hid_t file_id; hid_t dtype1_id = -1; hid_t str_id = -1; - hid_t dspace_id; + hid_t small_dspace_id; /* Dataspace ID for small datasets */ + hid_t large_dspace_id; /* Dataspace ID for large datasets */ + hid_t dset_dspace_id; /* Dataspace ID for a particular dataset */ hid_t scalar_dspace_id; /* Dataspace ID for scalar dataspace */ hid_t single_dspace_id; /* Dataspace ID for single element selection */ hsize_t single_offset[] = {2}; /* Offset of single element selection */ hsize_t single_block[] = {1}; /* Block size of single element selection */ hid_t dcpl_id, xfer_pid; hid_t dset_id; - hsize_t dim1[] = {SPACE3_DIM1}; + hsize_t small_dims[] = {SPACE4_DIM_SMALL}; + hsize_t large_dims[] = {SPACE4_DIM_LARGE}; + hsize_t dset_elmts; /* Number of elements in a particular dataset */ const dtype1_struct fill1 = {1, 2, "foobar", "", NULL, "\0", "dead", 3, 4.0, 100.0, 1.0, "liquid", "meter"}; const dtype1_struct wdata = {3, 4, "", NULL, "\0", "foo", "two", 6, 8.0, 200.0, 2.0, "solid", "yard"}; - dtype1_struct buf[SPACE3_DIM1]; - size_t mem_used=0; /* Memory used during allocation */ - H5D_layout_t layout; /* Dataset storage layout */ + dtype1_struct *rbuf = NULL; /* Buffer for reading data */ + size_t mem_used = 0; /* Memory used during allocation */ + H5D_layout_t layout; /* Dataset storage layout */ char dset_name1[64], dset_name2[64]; /* Dataset names */ - int i; + unsigned i; /* Output message about test being performed */ MESSAGE(5, ("Check fill value for VL data\n")); @@ -2489,9 +2493,17 @@ test_vltypes_fill_value(void) CHECK(ret, FAIL, "H5Tclose"); - /* Create the main dataspace to use */ - dspace_id = H5Screate_simple(SPACE3_RANK, dim1, NULL); - CHECK(dspace_id, FAIL, "H5Screate_simple"); + /* Allocate space for the buffer to read data */ + rbuf = HDmalloc(SPACE4_DIM_LARGE * sizeof(dtype1_struct)); + CHECK(rbuf, NULL, "HDmalloc"); + + + /* Create the small & large dataspaces to use */ + small_dspace_id = H5Screate_simple(SPACE4_RANK, small_dims, NULL); + CHECK(small_dspace_id, FAIL, "H5Screate_simple"); + + large_dspace_id = H5Screate_simple(SPACE4_RANK, large_dims, NULL); + CHECK(large_dspace_id, FAIL, "H5Screate_simple"); /* Create a scalar dataspace */ scalar_dspace_id = H5Screate(H5S_SCALAR); @@ -2509,7 +2521,9 @@ test_vltypes_fill_value(void) CHECK(file_id, FAIL, "H5Fcreate"); /* Create datasets with different storage layouts */ - for(layout = H5D_COMPACT; layout <= H5D_CHUNKED; layout++) { +HDfprintf(stderr, "Uncomment loop!\n"); +/* for(layout = H5D_COMPACT; layout <= H5D_CHUNKED; layout++) { */ + for(layout = H5D_COMPACT; layout <= H5D_CONTIGUOUS; layout++) { hid_t tmp_dcpl_id; /* Temporary copy of the dataset creation property list */ /* Make a copy of the dataset creation property list */ @@ -2521,6 +2535,7 @@ test_vltypes_fill_value(void) case H5D_COMPACT: HDstrcpy(dset_name1, "dataset1-compact"); HDstrcpy(dset_name2, "dataset2-compact"); + dset_dspace_id = small_dspace_id; ret = H5Pset_layout(tmp_dcpl_id, H5D_COMPACT); CHECK(ret, FAIL, "H5Pset_layout"); break; @@ -2528,14 +2543,16 @@ test_vltypes_fill_value(void) case H5D_CONTIGUOUS: HDstrcpy(dset_name1, "dataset1-contig"); HDstrcpy(dset_name2, "dataset2-contig"); + dset_dspace_id = large_dspace_id; break; case H5D_CHUNKED: { - hsize_t chunk_dims[1] = {SPACE3_DIM1 / 4}; + hsize_t chunk_dims[1] = {SPACE4_DIM_LARGE / 4}; HDstrcpy(dset_name1, "dataset1-chunked"); HDstrcpy(dset_name2, "dataset2-chunked"); + dset_dspace_id = large_dspace_id; ret = H5Pset_chunk(tmp_dcpl_id, 1, chunk_dims); CHECK(ret, FAIL, "H5Pset_chunk"); } @@ -2543,7 +2560,7 @@ test_vltypes_fill_value(void) } /* end switch */ /* Create first data set with default setting - no space is allocated */ - dset_id = H5Dcreate(file_id, dset_name1, dtype1_id, dspace_id, tmp_dcpl_id); + dset_id = H5Dcreate(file_id, dset_name1, dtype1_id, dset_dspace_id, tmp_dcpl_id); CHECK(dset_id, FAIL, "H5Dcreate"); ret = H5Dclose(dset_id); @@ -2557,7 +2574,7 @@ test_vltypes_fill_value(void) ret = H5Pset_alloc_time(tmp_dcpl_id, H5D_ALLOC_TIME_EARLY); CHECK(ret, FAIL, "H5Pset_alloc_time"); - dset_id = H5Dcreate(file_id, dset_name2, dtype1_id, dspace_id, tmp_dcpl_id); + dset_id = H5Dcreate(file_id, dset_name2, dtype1_id, dset_dspace_id, tmp_dcpl_id); CHECK(dset_id, FAIL, "H5Dcreate"); ret = H5Dclose(dset_id); @@ -2587,23 +2604,31 @@ test_vltypes_fill_value(void) CHECK(file_id, FAIL, "H5Fopen"); /* Read datasets with different storage layouts */ - for(layout = H5D_COMPACT; layout <= H5D_CHUNKED; layout++) { +HDfprintf(stderr, "Uncomment loop!\n"); +/* for(layout = H5D_COMPACT; layout <= H5D_CHUNKED; layout++) { */ + for(layout = H5D_COMPACT; layout <= H5D_CONTIGUOUS; layout++) { /* Layout specific actions */ switch(layout) { case H5D_COMPACT: HDstrcpy(dset_name1, "dataset1-compact"); HDstrcpy(dset_name2, "dataset2-compact"); + dset_dspace_id = small_dspace_id; + dset_elmts = SPACE4_DIM_SMALL; break; case H5D_CONTIGUOUS: HDstrcpy(dset_name1, "dataset1-contig"); HDstrcpy(dset_name2, "dataset2-contig"); + dset_dspace_id = large_dspace_id; + dset_elmts = SPACE4_DIM_LARGE; break; case H5D_CHUNKED: HDstrcpy(dset_name1, "dataset1-chunked"); HDstrcpy(dset_name2, "dataset2-chunked"); + dset_dspace_id = large_dspace_id; + dset_elmts = SPACE4_DIM_LARGE; break; } /* end switch */ @@ -2612,13 +2637,19 @@ test_vltypes_fill_value(void) CHECK(dset_id, FAIL, "H5Dopen"); /* Read in the data of fill value */ - ret = H5Dread(dset_id, dtype1_id, dspace_id, dspace_id, xfer_pid, buf); + ret = H5Dread(dset_id, dtype1_id, dset_dspace_id, dset_dspace_id, xfer_pid, rbuf); CHECK(ret, FAIL, "H5Dread"); /* Compare data read in */ - for(i=0; i