diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2007-06-26 17:46:35 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2007-06-26 17:46:35 (GMT) |
commit | 1d7d79bbb724db9356a5a9f387b201098f2a5b8e (patch) | |
tree | bf33e486b4a30d5712f80a42d2e41c3d75dce1b7 /src/H5Dfill.c | |
parent | 4a9a1c90f3d1a398e7525034b1311696affb9d6d (diff) | |
download | hdf5-1d7d79bbb724db9356a5a9f387b201098f2a5b8e.zip hdf5-1d7d79bbb724db9356a5a9f387b201098f2a5b8e.tar.gz hdf5-1d7d79bbb724db9356a5a9f387b201098f2a5b8e.tar.bz2 |
[svn-r13918] Description:
Refactor fill value buffer code into one location, for better long-term
maintenance.
Tested on:
Mac OS X/32 10.4.10 (amazon)
Linux/32 2.6 (chicago)
Linux/64 2.6 (chicago2)
Diffstat (limited to 'src/H5Dfill.c')
-rw-r--r-- | src/H5Dfill.c | 667 |
1 files changed, 667 insertions, 0 deletions
diff --git a/src/H5Dfill.c b/src/H5Dfill.c new file mode 100644 index 0000000..89e3a6b --- /dev/null +++ b/src/H5Dfill.c @@ -0,0 +1,667 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5Dfill.c + * Jun 19 2007 + * Quincey Koziol <koziol@hdfgroup.org> + * + * Purpose: Fill value operations for datasets + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5D_PACKAGE /*suppress error about including H5Dpkg */ + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Dpkg.h" /* Dataset functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5FLprivate.h" /* Free Lists */ +#include "H5Iprivate.h" /* IDs */ +#include "H5Vprivate.h" /* Vector and array functions */ + + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + +/* Declare a free list to manage blocks of single datatype element data */ +H5FL_BLK_DEFINE(type_elem); + +/* Declare extern the free list to manage blocks of type conversion data */ +H5FL_BLK_EXTERN(type_conv); + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + +/* Declare the free list to manage blocks of non-zero fill-value data */ +H5FL_BLK_DEFINE_STATIC(non_zero_fill); + +/* Declare the free list to manage blocks of zero fill-value data */ +H5FL_BLK_DEFINE_STATIC(zero_fill); + + +/*-------------------------------------------------------------------------- + NAME + H5Dfill + PURPOSE + Fill a selection in memory with a value + USAGE + herr_t H5Dfill(fill, fill_type, space, buf, buf_type) + const void *fill; IN: Pointer to fill value to use + hid_t fill_type_id; IN: Datatype of the fill value + void *buf; IN/OUT: Memory buffer to fill selection within + hid_t buf_type_id; IN: Datatype of the elements in buffer + hid_t space_id; IN: Dataspace describing memory buffer & + containing selection to use. + RETURNS + Non-negative on success/Negative on failure. + DESCRIPTION + Use the selection in the dataspace to fill elements in a memory buffer. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + If "fill" parameter is NULL, use all zeros as fill value + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5Dfill(const void *fill, hid_t fill_type_id, void *buf, hid_t buf_type_id, hid_t space_id) +{ + H5S_t *space; /* Dataspace */ + H5T_t *fill_type; /* Fill-value datatype */ + H5T_t *buf_type; /* Buffer datatype */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Dfill, FAIL) + H5TRACE5("e", "*xi*xii", fill, fill_type_id, buf, buf_type_id, space_id); + + /* Check args */ + if(buf == NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid buffer") + if(NULL == (space = H5I_object_verify(space_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a dataspace") + if(NULL == (fill_type = H5I_object_verify(fill_type_id, H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a datatype") + if(NULL == (buf_type = H5I_object_verify(buf_type_id, H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a datatype") + + /* Fill the selection in the memory buffer */ + if(H5D_fill(fill, fill_type, buf, buf_type, space, H5AC_dxpl_id) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTENCODE, FAIL, "filling selection failed") + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Dfill() */ + + +/*-------------------------------------------------------------------------- + NAME + H5D_fill + PURPOSE + Fill a selection in memory with a value (internal version) + USAGE + herr_t H5D_fill(fill, fill_type, buf, buf_type, space) + const void *fill; IN: Pointer to fill value to use + H5T_t *fill_type; IN: Datatype of the fill value + void *buf; IN/OUT: Memory buffer to fill selection within + H5T_t *buf_type; IN: Datatype of the elements in buffer + H5S_t *space; IN: Dataspace describing memory buffer & + containing selection to use. + RETURNS + Non-negative on success/Negative on failure. + DESCRIPTION + Use the selection in the dataspace to fill elements in a memory buffer. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + If "fill" parameter is NULL, use all zeros as fill value. If "fill_type" + 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. +--------------------------------------------------------------------------*/ +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) +{ + 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 dst_type_size; /* Size of destination type*/ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5D_fill) + + /* Check args */ + 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))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspace extent has not been set") + + /* Get the memory datatype size */ + dst_type_size = H5T_get_size(buf_type); + + /* If there's no fill value, just use zeros */ + if(fill == NULL) { + /* Allocate space & initialize conversion buffer to zeros */ + if(NULL == (tconv_buf = H5FL_BLK_CALLOC(type_elem, dst_type_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 */ + size_t src_type_size; /* Size of source type */ + size_t buf_size; /* Desired buffer size */ + + /* Get the file datatype size */ + src_type_size = H5T_get_size(fill_type); + + /* Get the maximum buffer size needed and allocate it */ + buf_size = MAX(src_type_size, dst_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 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") + + 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 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)) { + 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 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") + + /* 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") + + /* 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 */ + + /* Release the selection iterator */ + if(H5S_SELECT_ITER_RELEASE(&mem_iter) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator") + } /* end if */ + 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))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* 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, "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(fill_buf, dst_type_size, space, buf) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTENCODE, FAIL, "filling selection failed") + } /* end else */ + } /* end else */ + +done: + 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) + 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); + else + H5FL_BLK_FREE(type_elem, bkg_buf); + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5D_fill() */ + + +/*------------------------------------------------------------------------- + * Function: H5D_fill_init + * + * Purpose: Initialize buffer filling operation + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * June 21, 2007 + * + *------------------------------------------------------------------------- + */ +herr_t +H5D_fill_init(H5D_fill_buf_info_t *fb_info, void *caller_fill_buf, + hbool_t alloc_vl_during_refill, + H5MM_allocate_t alloc_func, void *alloc_info, + H5MM_free_t free_func, void *free_info, + const H5O_fill_t *fill, const H5T_t *dset_type, hid_t dset_type_id, + size_t total_nelmts, size_t max_buf_size, hid_t dxpl_id) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5D_fill_init, FAIL) + + /* Check args */ + HDassert(fb_info); + HDassert(fill); + HDassert(dset_type); + HDassert(dset_type_id > 0); + + /* Reset fill buffer information */ + HDmemset(fb_info, 0, sizeof(*fb_info)); + + /* Cache constant information from the dataset */ + fb_info->fill = fill; + fb_info->file_type = dset_type; + fb_info->file_tid = dset_type_id; + fb_info->alloc_vl_during_refill = alloc_vl_during_refill; + fb_info->fill_alloc_func = alloc_func; + fb_info->fill_alloc_info = alloc_info; + fb_info->fill_free_func = free_func; + fb_info->fill_free_info = free_info; + + /* Fill the buffer with the user's fill value */ + if(fill->buf) { + /* Detect whether the datatype has a VL component */ + fb_info->has_vlen_fill_type = H5T_detect_class(dset_type, H5T_VLEN); + + /* If necessary, convert fill value datatypes (which copies VL components, etc.) */ + if(fb_info->has_vlen_fill_type) { + /* Create temporary datatype for conversion operation */ + if(NULL == (fb_info->mem_type = H5T_copy(dset_type, H5T_COPY_REOPEN))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "unable to copy file datatype") + if((fb_info->mem_tid = H5I_register(H5I_DATATYPE, fb_info->mem_type)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register memory datatype") + + /* Retrieve sizes of memory & file datatypes */ + fb_info->mem_elmt_size = H5T_get_size(fb_info->mem_type); + HDassert(fb_info->mem_elmt_size > 0); + fb_info->file_elmt_size = H5T_get_size(dset_type); + HDassert(fb_info->file_elmt_size == (size_t)fill->size); + + /* If fill value is not library default, use it to set the element size */ + fb_info->max_elmt_size = MAX(fb_info->mem_elmt_size, fb_info->file_elmt_size); + + /* Compute the number of elements that fit within a buffer to write */ + if(total_nelmts > 0) + fb_info->elmts_per_buf = MIN(total_nelmts, MAX(1, (max_buf_size / fb_info->max_elmt_size))); + else + fb_info->elmts_per_buf = max_buf_size / fb_info->max_elmt_size; + HDassert(fb_info->elmts_per_buf > 0); + + /* Compute the buffer size to use */ + fb_info->fill_buf_size = MIN(max_buf_size, (fb_info->elmts_per_buf * fb_info->max_elmt_size)); + + /* Allocate fill buffer */ + if(caller_fill_buf) { + fb_info->fill_buf = caller_fill_buf; + fb_info->use_caller_fill_buf = TRUE; + } /* end if */ + else { + if(alloc_vl_during_refill) + fb_info->fill_buf = NULL; + else { + if(alloc_func) + fb_info->fill_buf = alloc_func(fb_info->fill_buf_size, alloc_info); + else + fb_info->fill_buf = H5FL_BLK_MALLOC(non_zero_fill, fb_info->fill_buf_size); + if(NULL == fb_info->fill_buf) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fill buffer") + } /* end else */ + } /* end else */ + + /* Get the datatype conversion path for this operation */ + if(NULL == (fb_info->fill_to_mem_tpath = H5T_path_find(dset_type, fb_info->mem_type, NULL, NULL, dxpl_id, FALSE))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert between src and dst datatypes") + + /* Get the inverse datatype conversion path for this operation */ + if(NULL == (fb_info->mem_to_dset_tpath = H5T_path_find(fb_info->mem_type, dset_type, NULL, NULL, dxpl_id, FALSE))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert between src and dst datatypes") + + /* Check if we need to allocate a background buffer */ + if(H5T_path_bkg(fb_info->fill_to_mem_tpath) || H5T_path_bkg(fb_info->mem_to_dset_tpath)) { + /* Check for inverse datatype conversion needing a background buffer */ + /* (do this first, since it needs a larger buffer) */ + if(H5T_path_bkg(fb_info->mem_to_dset_tpath)) + fb_info->bkg_buf_size = fb_info->elmts_per_buf * fb_info->max_elmt_size; + else + fb_info->bkg_buf_size = fb_info->max_elmt_size; + + /* Allocate the background buffer */ + if(NULL == (fb_info->bkg_buf = H5FL_BLK_MALLOC(type_conv, fb_info->bkg_buf_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + } /* end if */ + } /* end if */ + else { + /* If fill value is not library default, use it to set the element size */ + fb_info->max_elmt_size = fb_info->file_elmt_size = fb_info->mem_elmt_size = fill->size; + + /* Compute the number of elements that fit within a buffer to write */ + if(total_nelmts > 0) + fb_info->elmts_per_buf = MIN(total_nelmts, MAX(1, (max_buf_size / fb_info->max_elmt_size))); + else + fb_info->elmts_per_buf = max_buf_size / fb_info->max_elmt_size; + HDassert(fb_info->elmts_per_buf > 0); + + /* Compute the buffer size to use */ + fb_info->fill_buf_size = MIN(max_buf_size, fb_info->elmts_per_buf * fb_info->max_elmt_size); + + /* Allocate temporary buffer */ + if(caller_fill_buf) { + fb_info->fill_buf = caller_fill_buf; + fb_info->use_caller_fill_buf = TRUE; + } /* end if */ + else { + if(alloc_func) + fb_info->fill_buf = alloc_func(fb_info->fill_buf_size, alloc_info); + else + fb_info->fill_buf = H5FL_BLK_MALLOC(non_zero_fill, fb_info->fill_buf_size); + if(NULL == fb_info->fill_buf) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fill buffer") + } /* end else */ + + /* Replicate the fill value into the cached buffer */ + H5V_array_fill(fb_info->fill_buf, fill->buf, fb_info->max_elmt_size, fb_info->elmts_per_buf); + } /* end else */ + } /* end if */ + else { /* Fill the buffer with the default fill value */ + /* Retrieve size of elements */ + fb_info->max_elmt_size = fb_info->file_elmt_size = fb_info->mem_elmt_size = H5T_get_size(dset_type); + HDassert(fb_info->max_elmt_size > 0); + + /* Compute the number of elements that fit within a buffer to write */ + if(total_nelmts > 0) + fb_info->elmts_per_buf = MIN(total_nelmts, MAX(1, (max_buf_size / fb_info->max_elmt_size))); + else + fb_info->elmts_per_buf = max_buf_size / fb_info->max_elmt_size; + HDassert(fb_info->elmts_per_buf > 0); + + /* Compute the buffer size to use */ + fb_info->fill_buf_size = MIN(max_buf_size, (fb_info->elmts_per_buf * fb_info->max_elmt_size)); + + /* Use (and zero) caller's buffer, if provided */ + if(caller_fill_buf) { + fb_info->fill_buf = caller_fill_buf; + fb_info->use_caller_fill_buf = TRUE; + + HDmemset(fb_info->fill_buf, 0, fb_info->fill_buf_size); + } /* end if */ + else { + if(alloc_func) { + fb_info->fill_buf = alloc_func(fb_info->fill_buf_size, alloc_info); + + HDmemset(fb_info->fill_buf, 0, fb_info->fill_buf_size); + } /* end if */ + else { + htri_t buf_avail = H5FL_BLK_AVAIL(zero_fill, fb_info->fill_buf_size); /* Check if there is an already zeroed out buffer available */ + HDassert(buf_avail != FAIL); + + /* Allocate temporary buffer (zeroing it if no buffer is available) */ + if(!buf_avail) + fb_info->fill_buf = H5FL_BLK_CALLOC(zero_fill, fb_info->fill_buf_size); + else + fb_info->fill_buf = H5FL_BLK_MALLOC(zero_fill, fb_info->fill_buf_size); + } /* end else */ + if(fb_info->fill_buf == NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fill buffer") + } /* end else */ + } /* end else */ + +done: + /* Cleanup on error */ + if(ret_value < 0) + if(H5D_fill_term(fb_info) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release fill buffer info") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D_fill_init() */ + + +/*------------------------------------------------------------------------- + * Function: H5D_fill_refill_vl + * + * Purpose: Refill fill value buffer that contains VL-datatype fill values + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * June 21, 2007 + * + *------------------------------------------------------------------------- + */ +herr_t +H5D_fill_refill_vl(H5D_fill_buf_info_t *fb_info, size_t nelmts, hid_t dxpl_id) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5D_fill_refill_vl, FAIL) + + /* Check args */ + HDassert(fb_info); + HDassert(fb_info->has_vlen_fill_type); + + /* Check if we should allocate the fill buffer now */ + if(fb_info->alloc_vl_during_refill) { + if(fb_info->fill_alloc_func) + fb_info->fill_buf = fb_info->fill_alloc_func(fb_info->fill_buf_size, fb_info->fill_alloc_info); + else + fb_info->fill_buf = H5FL_BLK_MALLOC(non_zero_fill, fb_info->fill_buf_size); + if(NULL == fb_info->fill_buf) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fill buffer") + } /* end if */ + + /* Make a copy of the (disk-based) fill value into the buffer */ + HDmemcpy(fb_info->fill_buf, fb_info->fill->buf, fb_info->file_elmt_size); + + /* Reset first element of background buffer, if necessary */ + if(H5T_path_bkg(fb_info->fill_to_mem_tpath)) + HDmemset(fb_info->bkg_buf, 0, fb_info->max_elmt_size); + + /* Type convert the dataset buffer, to copy any VL components */ + if(H5T_convert(fb_info->fill_to_mem_tpath, fb_info->file_tid, fb_info->mem_tid, (size_t)1, (size_t)0, (size_t)0, fb_info->fill_buf, fb_info->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(fb_info->fill_buf, fb_info->fill_buf, fb_info->mem_elmt_size, nelmts); + + /* Reset the entire background buffer, if necessary */ + if(H5T_path_bkg(fb_info->mem_to_dset_tpath)) + HDmemset(fb_info->bkg_buf, 0, fb_info->bkg_buf_size); + + /* Type convert the dataset buffer, to copy any VL components */ + if(H5T_convert(fb_info->mem_to_dset_tpath, fb_info->mem_tid, fb_info->file_tid, nelmts, (size_t)0, (size_t)0, fb_info->fill_buf, fb_info->bkg_buf, dxpl_id) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "data type conversion failed") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D_fill_refill_vl() */ + + +/*------------------------------------------------------------------------- + * Function: H5D_fill_release + * + * Purpose: Release fill value buffer + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * June 22, 2007 + * + *------------------------------------------------------------------------- + */ +herr_t +H5D_fill_release(H5D_fill_buf_info_t *fb_info) +{ + FUNC_ENTER_NOAPI_NOFUNC(H5D_fill_release) + + /* Check args */ + HDassert(fb_info); + HDassert(fb_info->fill); + + /* Free the buffer for fill values */ + if(!fb_info->use_caller_fill_buf && fb_info->fill_buf) { + if(fb_info->fill_free_func) + fb_info->fill_free_func(fb_info->fill_buf, fb_info->fill_free_info); + else { + if(fb_info->fill->buf) + H5FL_BLK_FREE(non_zero_fill, fb_info->fill_buf); + else + H5FL_BLK_FREE(zero_fill, fb_info->fill_buf); + } /* end else */ + fb_info->fill_buf = NULL; + } /* end if */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5D_fill_release() */ + + +/*------------------------------------------------------------------------- + * Function: H5D_fill_term + * + * Purpose: Release fill value buffer info + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * June 21, 2007 + * + *------------------------------------------------------------------------- + */ +herr_t +H5D_fill_term(H5D_fill_buf_info_t *fb_info) +{ + FUNC_ENTER_NOAPI_NOFUNC(H5D_fill_term) + + /* Check args */ + HDassert(fb_info); + + /* Free the buffer for fill values */ + H5D_fill_release(fb_info); + + /* Free other resources for vlen fill values */ + if(fb_info->has_vlen_fill_type) { + if(fb_info->mem_tid > 0) + H5I_dec_ref(fb_info->mem_tid); + else if(fb_info->mem_type) + H5T_close(fb_info->mem_type); + if(fb_info->bkg_buf) + H5FL_BLK_FREE(type_conv, fb_info->bkg_buf); + } /* end if */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5D_fill_term() */ + |