diff options
author | Raymond Lu <songyulu@hdfgroup.org> | 2002-04-11 22:52:48 (GMT) |
---|---|---|
committer | Raymond Lu <songyulu@hdfgroup.org> | 2002-04-11 22:52:48 (GMT) |
commit | ce920c6c041c88a64b0553db538842f912ebda8e (patch) | |
tree | 3f3ebbafc532eb23a2ed43a7d4c5cfc07a609d58 /src/H5D.c | |
parent | 19c8cfa8617156fa99caa4349fecb40ab652753c (diff) | |
download | hdf5-ce920c6c041c88a64b0553db538842f912ebda8e.zip hdf5-ce920c6c041c88a64b0553db538842f912ebda8e.tar.gz hdf5-ce920c6c041c88a64b0553db538842f912ebda8e.tar.bz2 |
[svn-r5170]
Purpose:
New feature
Description:
Fill-value's behaviors for contiguous dataset have been redefined.
Basicly, dataset won't allocate space until it's necessary. Full details
are available at http://hdf.ncsa.uiuc.edu/RFC/Fill_Value, at this moment.
Platforms tested:
Linux 2.2.
Diffstat (limited to 'src/H5D.c')
-rw-r--r-- | src/H5D.c | 784 |
1 files changed, 553 insertions, 231 deletions
@@ -52,12 +52,15 @@ struct H5D_t { H5O_layout_t layout; /*data layout */ }; -/* Interface initialization? */ + static int interface_initialize_g = 0; #define INTERFACE_INIT H5D_init_interface static herr_t H5D_init_interface(void); static herr_t H5D_init_storage(H5D_t *dataset, const H5S_t *space); H5D_t * H5D_new(hid_t dcpl_id); +static herr_t H5D_fill(const void *fill, const H5T_t *fill_type, void *buf, + const H5T_t *buf_type, const H5S_t *space); +static herr_t H5D_get_space_status(H5D_t *dset, H5D_space_status_t *allocation); /* Declare a free list to manage the H5D_t struct */ H5FL_DEFINE_STATIC(H5D_t); @@ -173,6 +176,8 @@ H5D_init_interface(void) int chunk_ndims = H5D_CRT_CHUNK_DIM_DEF; hsize_t chunk_size[32] = H5D_CRT_CHUNK_SIZE_DEF; H5O_fill_t fill = H5D_CRT_FILL_VALUE_DEF; + H5D_space_time_t space_time = H5D_CRT_SPACE_TIME_DEF; + H5D_fill_time_t fill_time = H5D_CRT_FILL_TIME_DEF; H5O_efl_t efl = H5D_CRT_EXT_FILE_LIST_DEF; H5O_pline_t pline = H5D_CRT_DATA_PIPELINE_DEF; @@ -300,7 +305,15 @@ H5D_init_interface(void) /* Register the fill value property */ if(H5P_register(crt_pclass, H5D_CRT_FILL_VALUE_NAME, H5D_CRT_FILL_VALUE_SIZE, &fill, NULL, NULL, NULL, NULL, NULL, NULL) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class"); - + + /* Register the space allocation time property */ + if(H5P_register(crt_pclass, H5D_CRT_SPACE_TIME_NAME, H5D_CRT_SPACE_TIME_SIZE, &space_time, NULL, NULL, NULL, NULL, NULL, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class"); + + /* Register the fill value writing time property */ + if(H5P_register(crt_pclass, H5D_CRT_FILL_TIME_NAME, H5D_CRT_FILL_TIME_SIZE, &fill_time, NULL, NULL, NULL, NULL, NULL, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class"); + /* Register the external file list property */ if(H5P_register(crt_pclass, H5D_CRT_EXT_FILE_LIST_NAME, H5D_CRT_EXT_FILE_LIST_SIZE, &efl, NULL, NULL, NULL, NULL, NULL, NULL) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class"); @@ -407,8 +420,13 @@ H5D_crt_copy(hid_t new_plist_id, hid_t old_plist_id, void UNUSED *copy_data) /* Make copies of fill value, external file list, and data pipeline */ HDmemset(&dst_fill,0,sizeof(H5O_fill_t)); - if(NULL==H5O_copy(H5O_FILL, &src_fill, &dst_fill)) + if(src_fill.buf && (NULL==H5O_copy(H5O_FILL, &src_fill, &dst_fill))) { HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "can't copy fill value"); + } + else if (!src_fill.buf) { + dst_fill.type = dst_fill.buf = NULL; + dst_fill.size = src_fill.size; + } HDmemset(&dst_efl,0,sizeof(H5O_efl_t)); if(NULL==H5O_copy(H5O_EFL, &src_efl, &dst_efl)) HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "can't copy external file list"); @@ -905,6 +923,107 @@ H5D_get_space(H5D_t *dset) /*------------------------------------------------------------------------- + * Function: H5Dget_space_status + * + * Purpose: Returns the status of data space allocation. + * + * Return: + * Success: Non-negative + * + * Failture: Negative + * + * Programmer: Raymond Lu + * + * Modification: + * + *------------------------------------------------------------------------- + */ +herr_t H5Dget_space_status(hid_t dset_id, H5D_space_status_t *allocation) +{ + H5D_t *dset = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER(H5Dget_space_status, FAIL); + + /* Check arguments */ + if(H5I_DATASET != H5I_get_type(dset_id) || NULL==(dset=H5I_object(dset_id))) + HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset"); + + /* Read data space address and return */ + if(FAIL==(ret_value=H5D_get_space_status(dset, allocation))) + HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to get space status"); + +done: + FUNC_LEAVE(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5D_get_space_status + * + * Purpose: Returns the status of data space allocation. + * + * Return: + * Success: Non-negative + * + * Failture: Negative + * + * Programmer: Raymond Lu + * + * Modification: + * + *------------------------------------------------------------------------- + */ +static herr_t H5D_get_space_status(H5D_t *dset, H5D_space_status_t *allocation) +{ + H5S_t *space=NULL; /* Dataset's dataspace */ + hsize_t space_allocated; /* The number of bytes allocated for chunks */ + hssize_t total_elem; /* The total number of elements in dataspace */ + size_t type_size; /* The size of the datatype for the dataset */ + hsize_t full_size; /* The number of bytes in the dataset when fully populated */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER(H5D_get_space_status, FAIL); + + /* Get the dataset's dataspace */ + if((space=H5D_get_space(dset))==NULL) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to get dataspace"); + + /* Get the total number of elements in dataset's dataspace */ + if((total_elem=H5S_get_simple_extent_npoints(space))<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCOUNT, FAIL, "unable to get # of dataspace elements"); + + /* Get the size of the dataset's datatype */ + if((type_size=H5T_get_size(dset->type))==0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCOUNT, FAIL, "unable to get size of datatype"); + + /* Compute the maximum size of the dataset in bytes */ + H5_CHECK_OVERFLOW(total_elem,hssize_t,hsize_t); + full_size=((hsize_t)total_elem)*type_size; + + /* Difficult to error check, since the error value is 0 and 0 is a valid value... :-/ */ + space_allocated=H5D_get_storage_size(dset); + + /* Decide on how much of the space is allocated */ + if(space_allocated==0) + *allocation = H5D_SPACE_STATUS_NOT_ALLOCATED; + else if(space_allocated==full_size) + *allocation = H5D_SPACE_STATUS_ALLOCATED; + else { + /* Should only happen for chunked datasets currently */ + assert(dset->layout.type==H5D_CHUNKED); + + *allocation = H5D_SPACE_STATUS_PART_ALLOCATED; + } /* end else */ + +done: + if(space) + H5S_close(space); + FUNC_LEAVE(ret_value); +} + + +/*------------------------------------------------------------------------- * Function: H5Dget_type * * Purpose: Returns a copy of the file data type for a dataset. @@ -998,8 +1117,8 @@ H5Dget_create_plist(hid_t dset_id) { H5D_t *dset = NULL; H5O_fill_t copied_fill={NULL,0,NULL}; - H5P_genplist_t *dcpl_plist; - H5P_genplist_t *new_plist; + H5P_genplist_t *dcpl_plist; + H5P_genplist_t *new_plist; hid_t ret_value = FAIL; FUNC_ENTER (H5Dget_create_plist, FAIL); @@ -1379,6 +1498,11 @@ done: * Changed the way to retrieve and set property for generic property * list. * + * Raymond Lu, 26 Feb 2002 + * A new fill value message is added. Two properties, space allocation + * time and fill value writing time, govern space allocation and fill + * value writing. + * *------------------------------------------------------------------------- */ H5D_t * @@ -1396,9 +1520,13 @@ H5D_create(H5G_entry_t *loc, const char *name, const H5T_t *type, H5D_layout_t dcpl_layout; int chunk_ndims = 0; hsize_t chunk_size[32]={0}; - H5O_fill_t fill={NULL,0,NULL}; - H5P_genplist_t *plist; /* Property list */ - H5P_genplist_t *new_plist; /* New Property list */ + H5D_space_time_t space_time; + H5D_fill_time_t fill_time; + H5O_fill_t fill_prop={NULL,0,NULL}; + H5O_fill_new_t fill={NULL, 0, NULL, H5D_SPACE_ALLOC_LATE, H5D_FILL_TIME_ALLOC, TRUE}; + H5D_fill_value_t fill_status; + H5P_genplist_t *plist; /* Property list */ + H5P_genplist_t *new_plist; /* New Property list */ FUNC_ENTER(H5D_create, NULL); @@ -1528,14 +1656,49 @@ H5D_create(H5G_entry_t *loc, const char *name, const H5T_t *type, if (H5O_create(f, 256, &(new_dset->ent)) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to create dataset object header"); - /* Convert the fill value to the dataset type and write the message */ - if(H5P_get(new_plist, H5D_CRT_FILL_VALUE_NAME, &fill) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't retrieve fill value"); - if (H5O_fill_convert(&fill, new_dset->type) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to convert fill value to dataset type"); - if (fill.buf && H5O_modify(&(new_dset->ent), H5O_FILL, 0, H5O_FLAG_CONSTANT, &fill) < 0) + /* Retrieve properties of fill value and others. Copy them into new fill + * value struct. Convert the fill value to the dataset type and write + * the message */ + if(H5P_get(new_plist, H5D_CRT_SPACE_TIME_NAME, &space_time) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't retrieve space allocation time"); + if(H5P_get(new_plist, H5D_CRT_FILL_TIME_NAME, &fill_time) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't retrieve fill time"); + if(H5P_fill_value_defined(new_plist, &fill_status)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't tell if fill value defined"); + if(fill_status== H5D_FILL_VALUE_DEFAULT || fill_status==H5D_FILL_VALUE_USER_DEFINED) { + if(H5P_get(new_plist, H5D_CRT_FILL_VALUE_NAME, &fill_prop) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't retrieve fill value"); + if(NULL==H5O_copy(H5O_FILL, &fill_prop, &fill)) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT,NULL, "unable to copy fill value"); + if (fill_prop.buf && fill_prop.size>0 && H5O_fill_convert(&fill, new_dset->type) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to convert fill value to dataset type"); + fill.fill_defined = TRUE; + } else if(fill_status==H5D_FILL_VALUE_UNDEFINED) { + fill.size = -1; + fill.type = fill.buf = NULL; + fill.fill_defined = FALSE; + } else { + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, NULL, "unable to determine if fill value is defined"); + } /* end else */ + fill.space_time = space_time; + fill.fill_time = fill_time; + + if(fill.fill_defined == FALSE && fill_time != H5D_FILL_TIME_NEVER) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT,NULL, "unable to create dataset"); + /* Write new fill value message */ + if (H5O_modify(&(new_dset->ent), H5O_FILL_NEW, 0, H5O_FLAG_CONSTANT, + &fill) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to update fill value header message"); - if(H5P_set(new_plist, H5D_CRT_FILL_VALUE_NAME, &fill) < 0) + + H5O_reset(H5O_FILL, &fill_prop); + if(fill.buf && (NULL==H5O_copy(H5O_FILL, &fill, &fill_prop))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT,NULL,"unable to copy fill value"); + /* Write old fill value */ + if (fill_prop.buf && H5O_modify(&(new_dset->ent), H5O_FILL, 0, + H5O_FLAG_CONSTANT, &fill_prop) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, + "unable to update fill value header message"); + if(H5P_set(new_plist, H5D_CRT_FILL_VALUE_NAME, &fill_prop) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "can't set fill value"); /* Update the type and space header messages */ @@ -1563,16 +1726,34 @@ H5D_create(H5G_entry_t *loc, const char *name, const H5T_t *type, /* * Initialize storage. We assume that external storage is already * initialized by the caller, or at least will be before I/O is performed. + * For parallelization, space is always allocated now except using + * external storage. For contiguous layout, space is allocated now if + * space allocate time is early; otherwise delay allocation until H5Dwrite. */ +#ifdef H5_HAVE_PARALLEL + if (0==efl.nused && H5F_arr_create(f, &(new_dset->layout))<0) { + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, + "unable to initialize storage"); + } else if(0<efl.nused) { + new_dset->layout.addr = HADDR_UNDEF; + } +#else if (0==efl.nused) { - if (H5F_arr_create(f, &(new_dset->layout)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to initialize storage"); + if(dcpl_layout==H5D_CHUNKED || (dcpl_layout==H5D_CONTIGUOUS && + space_time==H5D_SPACE_ALLOC_EARLY)) { + if (H5F_arr_create(f, &(new_dset->layout))<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to initialize storage"); + } /* end if */ + else + new_dset->layout.addr = HADDR_UNDEF; + } else { new_dset->layout.addr = HADDR_UNDEF; } +#endif /* Update layout message */ - if (H5O_modify (&(new_dset->ent), H5O_LAYOUT, 0, H5O_FLAG_CONSTANT, &(new_dset->layout)) < 0) + if (H5O_modify (&(new_dset->ent), H5O_LAYOUT, 0, 0, &(new_dset->layout))<0) HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, NULL, "unable to update layout message"); /* Update external storage message */ @@ -1596,9 +1777,22 @@ H5D_create(H5G_entry_t *loc, const char *name, const H5T_t *type, HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, NULL, "unable to update external file list message"); } /* end if */ - /* Initialize the raw data */ + /* Initialize the raw data when it's + * 1. Parallel I/O + * 2. layout is contiguous, space allocation time is early, fill value + * writing time is upon allocation + * 3. external space is treated the same as internal except it's always + * assumed as early for space allocation time. */ +#ifdef H5_HAVE_PARALLEL if (H5D_init_storage(new_dset, space)<0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to initialize storage"); + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to initialize storage"); +#else + if(dcpl_layout==H5D_CHUNKED || (dcpl_layout==H5D_CONTIGUOUS && + fill_time==H5D_FILL_TIME_ALLOC && ((space_time==H5D_SPACE_ALLOC_EARLY && !efl.nused) || + (efl.nused)))) + if (H5D_init_storage(new_dset, space)<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to initialize storage"); +#endif /* Success */ ret_value = new_dset; @@ -1736,6 +1930,10 @@ done: * Tuesday, October 2, 2001 * Changed the way to set property for generic property list. * + * Raymond Lu + * Feb 26, 2002 + * A new fill value message and two new properties are added. + * *------------------------------------------------------------------------- */ H5D_t * @@ -1744,10 +1942,11 @@ H5D_open_oid(H5G_entry_t *ent) H5D_t *dataset = NULL; /*new dataset struct */ H5D_t *ret_value = NULL; /*return value */ H5S_t *space = NULL; /*data space */ - H5O_fill_t fill; - H5O_pline_t pline; - H5O_efl_t efl; - H5D_layout_t layout; + H5O_fill_new_t fill = {NULL, 0, NULL, H5D_SPACE_ALLOC_LATE, H5D_FILL_TIME_ALLOC, TRUE}; + H5O_fill_t fill_prop = {NULL, 0, NULL}; + H5O_pline_t pline; /* I/O pipeline information */ + H5O_efl_t efl; /* External file information */ + H5D_layout_t layout; /* Dataset layout */ int chunk_ndims; H5P_genplist_t *plist; /* Property list */ @@ -1777,14 +1976,38 @@ H5D_open_oid(H5G_entry_t *ent) if (NULL == (plist = H5I_object(dataset->dcpl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "can't get dataset creation property list"); - /* Get the optional fill value message */ - HDmemset(&fill,0,sizeof(H5O_fill_t)); - if(NULL == H5O_read(&(dataset->ent), H5O_FILL, 0, &fill)) { + /* Retrieve & release the previous fill-value settings */ + if(H5P_get(plist, H5D_CRT_FILL_VALUE_NAME, &fill_prop) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't get fill value"); + H5O_reset(H5O_FILL, &fill_prop); + + /* Get the new fill value message */ + if(NULL == H5O_read(&(dataset->ent), H5O_FILL_NEW, 0, &fill)) { H5E_clear(); HDmemset(&fill, 0, sizeof(fill)); } - - if(H5P_set(plist, H5D_CRT_FILL_VALUE_NAME, &fill) < 0) + if(fill.fill_defined) { + if(NULL==H5O_copy(H5O_FILL, &fill, &fill_prop)) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "can't copy fill value"); + } else { + /* For compatibility with v1.4. Retrieve the old fill value message. + * If size is 0, make it -1 for undefined. */ + if(NULL == H5O_read(&(dataset->ent), H5O_FILL, 0, &fill_prop)) { + H5E_clear(); + HDmemset(&fill_prop, 0, sizeof(fill_prop)); + } + if(fill_prop.size == 0) { + fill_prop.type = fill_prop.buf = NULL; + fill_prop.size = (size_t)-1; + } + } /* end else */ + + /* Set fill value properties */ + if(H5P_set(plist, H5D_CRT_FILL_VALUE_NAME, &fill_prop) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set fill value"); + if(H5P_set(plist, H5D_CRT_SPACE_TIME_NAME, &fill.space_time) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set fill value"); + if(H5P_set(plist, H5D_CRT_FILL_TIME_NAME, &fill.fill_time) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set fill value"); /* Get the optional filters message */ @@ -1837,13 +2060,13 @@ H5D_open_oid(H5G_entry_t *ent) HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, NULL, "not implemented yet"); } /* end switch */ - /* Get the external file list message, which might not exist */ - if( !H5F_addr_defined(dataset->layout.addr) ) { + /* Get the external file list message, which might not exist. Space is + * also undefined when space allocate time is H5D_SPACE_ALLOC_LATE. */ + if( !H5F_addr_defined(dataset->layout.addr)) { HDmemset(&efl,0,sizeof(H5O_efl_t)); - if(NULL == H5O_read(&(dataset->ent), H5O_EFL, 0, &efl)) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "storage address is undefined and no external file list"); - if(H5P_set(plist, H5D_CRT_EXT_FILE_LIST_NAME, &efl) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set external file list"); + if(NULL != H5O_read(&(dataset->ent), H5O_EFL, 0, &efl)) + if(H5P_set(plist, H5D_CRT_EXT_FILE_LIST_NAME, &efl) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set external file list"); } /* * Make sure all storage is properly initialized for chunked datasets. @@ -1967,6 +2190,11 @@ H5D_close(H5D_t *dataset) * Raymond Lu, 2001-10-2 * Changed the way to retrieve property for generic property list. * + * Raymond Lu, 2002-2-26 + * For the new fill value design, data space can either be allocated + * or not allocated at this stage. Fill value or data from space is + * returned to outgoing buffer. + * * QAK - 2002/04/02 * Removed the must_convert parameter and move preconditions to * H5S_<foo>_opt_possible() routine @@ -1977,37 +2205,39 @@ herr_t H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, const H5S_t *file_space, hid_t dxpl_id, void *buf/*out*/) { - hssize_t nelmts; /*number of elements */ - hsize_t smine_start; /*strip mine start loc */ - hsize_t n, smine_nelmts; /*elements per strip */ - uint8_t *tconv_buf = NULL; /*data type conv buffer */ - uint8_t *bkg_buf = NULL; /*background buffer */ + hssize_t nelmts; /*number of elements */ + hsize_t smine_start; /*strip mine start loc */ + hsize_t n, smine_nelmts; /*elements per strip */ + uint8_t *tconv_buf = NULL; /*data type conv buffer */ + uint8_t *bkg_buf = NULL; /*background buffer */ H5T_path_t *tpath = NULL; /*type conversion info */ - hid_t src_id = -1, dst_id = -1;/*temporary type atoms */ - H5S_conv_t *sconv=NULL; /*space conversion funcs*/ - H5S_sel_iter_t mem_iter; /*mem selection iteration info*/ - H5S_sel_iter_t bkg_iter; /*background iteration info*/ - H5S_sel_iter_t file_iter; /*file selection iter info*/ - herr_t ret_value = SUCCEED; /*return value */ - herr_t status; /*function return status*/ - size_t src_type_size; /*size of source type */ - size_t dst_type_size; /*size of destination type*/ - size_t target_size; /*desired buffer size */ - hsize_t request_nelmts; /*requested strip mine */ - H5T_bkg_t need_bkg; /*type of background buf*/ - H5S_t *free_this_space=NULL; /*data space to free */ + hid_t src_id = -1, dst_id = -1;/*temporary type atoms */ + H5S_conv_t *sconv=NULL; /*space conversion funcs*/ + H5S_sel_iter_t mem_iter; /*mem selection iteration info*/ + H5S_sel_iter_t bkg_iter; /*background iteration info*/ + H5S_sel_iter_t file_iter; /*file selection iter info*/ + herr_t ret_value = SUCCEED; /*return value */ + herr_t status=SUCCEED; /*function return status*/ + size_t src_type_size; /*size of source type */ + size_t dst_type_size; /*size of destination type*/ + size_t target_size; /*desired buffer size */ + hsize_t request_nelmts; /*requested strip mine */ + H5T_bkg_t need_bkg; /*type of background buf*/ + H5S_t *free_this_space=NULL; /*data space to free */ #ifdef H5_HAVE_PARALLEL - H5FD_mpio_dxpl_t *dx = NULL; - H5FD_mpio_xfer_t xfer_mode; /*xfer_mode for this request */ - hbool_t xfer_mode_changed=0; /*xfer_mode needs restore */ - hbool_t doing_mpio=0; /*This is an MPIO access */ + H5FD_mpio_dxpl_t *dx = NULL; + H5FD_mpio_xfer_t xfer_mode; /*xfer_mode for this request */ + hbool_t xfer_mode_changed=0; /*xfer_mode needs restore */ + hbool_t doing_mpio=0; /*This is an MPIO access */ #endif #ifdef H5S_DEBUG - H5_timer_t timer; + H5_timer_t timer; #endif - H5O_pline_t pline; - H5O_efl_t efl; - H5O_fill_t fill; + H5O_pline_t pline; /* I/O pipeline struct */ + H5O_efl_t efl; /* External File List info */ + H5O_fill_t fill; /* Fill value information */ + H5D_fill_time_t fill_time; /* When to write the fill values */ + H5D_fill_value_t fill_status; /* Whether/How the fill value is defined */ H5P_genplist_t *dx_plist=NULL; /* Property list */ H5P_genplist_t *dc_plist; /* Property list */ unsigned sconv_flags=0; /* Flags for the space conversion */ @@ -2074,6 +2304,39 @@ printf("%s: check 1.0, nelmts=%d, H5S_get_select_npoints(file_space)=%d\n",FUNC, if (nelmts!=H5S_get_select_npoints (file_space)) HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "src and dest data spaces have different sizes"); + /* Retrieve dataset properties */ + if(H5P_get(dc_plist, H5D_CRT_DATA_PIPELINE_NAME, &pline) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve data pipeline"); + if(H5P_fill_value_defined(dc_plist, &fill_status)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't tell if fill value defined"); + if((fill_status==H5D_FILL_VALUE_DEFAULT || fill_status==H5D_FILL_VALUE_USER_DEFINED) && H5P_get(dc_plist, H5D_CRT_FILL_VALUE_NAME, &fill) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL,"can't retrieve fill value"); + if(H5P_get(dc_plist, H5D_CRT_FILL_TIME_NAME, &fill_time) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL,"can't retrieve fill value"); + if(H5P_get(dc_plist, H5D_CRT_EXT_FILE_LIST_NAME, &efl) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve external file list"); + + /* If space hasn't been allocated and not using external storage, + * return fill value to buffer if fill time is upon allocation, or + * do nothing if fill time is never. */ + if(nelmts > 0 && efl.nused==0 && dataset->layout.type==H5D_CONTIGUOUS + && dataset->layout.addr==HADDR_UNDEF) { + + /* Should be impossible, but check anyway... */ + if(fill_status == H5D_FILL_VALUE_UNDEFINED && fill_time == H5D_FILL_TIME_ALLOC) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "read failed: dataset doesn't exist, no data can be read"); + + /* If we're never going to fill this dataset, just leave the junk in the user's buffer */ + if(fill_time == H5D_FILL_TIME_NEVER) + HGOTO_DONE(SUCCEED); + + /* Go fill the user's selection with the dataset's fill value */ + if(H5D_fill(fill.buf,fill.type,buf,mem_type,mem_space)<0) { + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "filling buf failed"); + } else + HGOTO_DONE(SUCCEED); + } /* end if */ + /* * Locate the type conversion function and data space conversion * functions, and set up the element numbering information. If a data @@ -2115,6 +2378,7 @@ printf("%s: check 1.0, nelmts=%d, H5S_get_select_npoints(file_space)=%d\n",FUNC, #ifdef QAK printf("%s: check 1.1, \n",FUNC); #endif /* QAK */ + /* * If there is no type conversion then try reading directly into the * application's buffer. This saves at least one mem-to-mem copy. @@ -2123,36 +2387,22 @@ printf("%s: check 1.1, \n",FUNC); #ifdef H5S_DEBUG H5_timer_begin(&timer); #endif - if(H5P_get(dc_plist, H5D_CRT_DATA_PIPELINE_NAME, &pline) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get pipeline"); - if(H5P_get(dc_plist, H5D_CRT_FILL_VALUE_NAME, &fill) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve fill value"); - if(H5P_get(dc_plist, H5D_CRT_EXT_FILE_LIST_NAME, &efl) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get external file list"); - status = (sconv->read)(dataset->ent.file, &(dataset->layout), &pline, - &fill, &efl, H5T_get_size(dataset->type), file_space, - mem_space, dxpl_id, buf/*out*/); + /* Sanity check dataset, then read it */ + assert(dataset->layout.addr!=HADDR_UNDEF || efl.nused>0); + status = (sconv->read)(dataset->ent.file, &(dataset->layout), + &pline, &fill, &efl, H5T_get_size(dataset->type), + file_space, mem_space, dxpl_id, buf/*out*/); +#ifdef H5S_DEBUG + H5_timer_end(&(sconv->stats[1].read_timer), &timer); + sconv->stats[1].read_nbytes += nelmts * H5T_get_size(dataset->type); + sconv->stats[1].read_ncalls++; +#endif - /* Supports only no conversion, type or space, for now. */ + /* Check return value from optimized read */ if (status<0) { HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "optimized read failed"); - } else { - /* direct xfer accomplished successfully */ -#ifdef H5S_DEBUG - H5_timer_end(&(sconv->stats[1].read_timer), &timer); - sconv->stats[1].read_nbytes += nelmts * - H5T_get_size(dataset->type); - sconv->stats[1].read_ncalls++; -#endif + } else HGOTO_DONE(SUCCEED); - } /* end else */ -#ifdef H5D_DEBUG - if (H5DEBUG(D)) { - fprintf (H5DEBUG(D), "H5D: data space conversion could not be " - "optimized for this case (using general method instead)\n"); - } /* end if */ -#endif - H5E_clear (); } /* end if */ #ifdef QAK @@ -2246,14 +2496,6 @@ printf("%s: check 2.0, src_type_size=%d, dst_type_size=%d, target_size=%d, min_e printf("%s: check 4.0, nelmts=%d, need_bkg=%d\n", FUNC,(int)nelmts,(int)need_bkg); #endif - /* Get some necessary information for later */ - if(H5P_get(dc_plist, H5D_CRT_DATA_PIPELINE_NAME, &pline) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve data pipeline"); - if(H5P_get(dc_plist, H5D_CRT_FILL_VALUE_NAME, &fill) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve fill value"); - if(H5P_get(dc_plist, H5D_CRT_EXT_FILE_LIST_NAME, &efl) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve external file list"); - /* Start strip mining... */ H5_CHECK_OVERFLOW(nelmts,hssize_t,hsize_t); for (smine_start=0; smine_start<(hsize_t)nelmts; smine_start+=smine_nelmts) { @@ -2272,11 +2514,11 @@ printf("%s: check 2.0, src_type_size=%d, dst_type_size=%d, target_size=%d, min_e #ifdef H5S_DEBUG H5_timer_begin(&timer); #endif - n = (sconv->f->gath)(dataset->ent.file, &(dataset->layout), &pline, - &fill, &efl, src_type_size, file_space, - &file_iter, smine_nelmts, dxpl_id, - tconv_buf/*out*/); - + /* Sanity check that space is allocated, then read data from it */ + assert(dataset->layout.addr!=HADDR_UNDEF || efl.nused > 0); + n = (sconv->f->gath)(dataset->ent.file, &(dataset->layout), + &pline, &fill, &efl, src_type_size, file_space, + &file_iter, smine_nelmts, dxpl_id, tconv_buf/*out*/); #ifdef H5S_DEBUG H5_timer_end(&(sconv->stats[1].gath_timer), &timer); @@ -2439,6 +2681,11 @@ done: * Raymond Lu, 2001-10-2 * Changed the way to retrieve property for generic property list. * + * Raymond Lu, 2002-2-26 + * For the new fill value design, space may not be allocated until + * this function is called. Allocate and initialize space if it + * hasn't been. + * * QAK - 2002/04/02 * Removed the must_convert parameter and move preconditions to * H5S_<foo>_opt_possible() routine @@ -2449,40 +2696,41 @@ herr_t H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, const H5S_t *file_space, hid_t dxpl_id, const void *buf) { - hssize_t nelmts; /*total number of elmts */ - hsize_t smine_start; /*strip mine start loc */ - hsize_t n, smine_nelmts; /*elements per strip */ - uint8_t *tconv_buf = NULL; /*data type conv buffer */ - uint8_t *bkg_buf = NULL; /*background buffer */ + hssize_t nelmts; /*total number of elmts */ + hsize_t smine_start; /*strip mine start loc */ + hsize_t n, smine_nelmts; /*elements per strip */ + uint8_t *tconv_buf = NULL; /*data type conv buffer */ + uint8_t *bkg_buf = NULL; /*background buffer */ H5T_path_t *tpath = NULL; /*type conversion info */ - hid_t src_id = -1, dst_id = -1;/*temporary type atoms */ + hid_t src_id = -1, dst_id = -1;/*temporary type atoms */ H5S_conv_t *sconv=NULL; /*space conversion funcs*/ - H5S_sel_iter_t mem_iter; /*memory selection iteration info*/ - H5S_sel_iter_t bkg_iter; /*background iteration info*/ - H5S_sel_iter_t file_iter; /*file selection iteration info*/ - herr_t ret_value = SUCCEED; /*return value */ - herr_t status; /*function return status*/ - size_t src_type_size; /*size of source type */ - size_t dst_type_size; /*size of destination type*/ - size_t target_size; /*desired buffer size */ - hsize_t request_nelmts; /*requested strip mine */ - H5T_bkg_t need_bkg; /*type of background buf*/ - H5S_t *free_this_space=NULL; /*data space to free */ + H5S_sel_iter_t mem_iter; /*memory selection iteration info*/ + H5S_sel_iter_t bkg_iter; /*background iteration info*/ + H5S_sel_iter_t file_iter; /*file selection iteration info*/ + herr_t ret_value = SUCCEED; /*return value */ + herr_t status; /*function return status*/ + size_t src_type_size; /*size of source type */ + size_t dst_type_size; /*size of destination type*/ + size_t target_size; /*desired buffer size */ + hsize_t request_nelmts; /*requested strip mine */ + H5T_bkg_t need_bkg; /*type of background buf*/ + H5S_t *free_this_space=NULL; /*data space to free */ #ifdef H5_HAVE_PARALLEL H5FD_mpio_dxpl_t *dx = NULL; - H5FD_mpio_xfer_t xfer_mode; /*xfer_mode for this request */ - hbool_t xfer_mode_changed=0; /*xfer_mode needs restore */ - hbool_t doing_mpio=0; /*This is an MPIO access */ + H5FD_mpio_xfer_t xfer_mode; /*xfer_mode for this request */ + hbool_t xfer_mode_changed=0; /*xfer_mode needs restore */ + hbool_t doing_mpio=0; /*This is an MPIO access */ #endif #ifdef H5S_DEBUG - H5_timer_t timer; + H5_timer_t timer; #endif - H5O_pline_t pline; - H5O_efl_t efl; - H5O_fill_t fill; - H5P_genplist_t *dx_plist=NULL; /* Property list */ - H5P_genplist_t *dc_plist; /* Property list */ - unsigned sconv_flags=0; /* Flags for the space conversion */ + H5O_pline_t pline; /* I/O Pipeline info */ + H5O_efl_t efl; /* External file list info */ + H5O_fill_t fill; /* Fill value info */ + H5D_fill_time_t fill_time; + H5P_genplist_t *dx_plist=NULL; /* Data transfer property list */ + H5P_genplist_t *dc_plist; /* Dataset creation roperty list */ + unsigned sconv_flags=0; /* Flags for the space conversion */ FUNC_ENTER(H5D_write, FAIL); @@ -2570,6 +2818,37 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, if (nelmts!=H5S_get_select_npoints (file_space)) HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "src and dest data spaces have different sizes"); + /* Retrieve properties. Allocate space and initialize the space with + * fill value if it has been done so. Remember, if H5D_write fails, + * need to deallocate space(?). */ + if(H5P_get(dc_plist, H5D_CRT_DATA_PIPELINE_NAME, &pline) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get data pipeline"); + if(H5P_get(dc_plist, H5D_CRT_FILL_VALUE_NAME, &fill) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get fill value"); + if(H5P_get(dc_plist, H5D_CRT_FILL_TIME_NAME, &fill_time) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve fill time"); + if(H5P_get(dc_plist, H5D_CRT_EXT_FILE_LIST_NAME, &efl) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get external file list"); + + /* Allocate data space and initialize it if it hasn't been. Also modify + * header message for layout(this is only for forward compatibility). */ + if(nelmts > 0 && efl.nused==0 && dataset->layout.type==H5D_CONTIGUOUS && + dataset->layout.addr==HADDR_UNDEF) { + /* Allocate storage */ + if(H5F_arr_create(dataset->ent.file, &(dataset->layout))<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize storage"); + + /* Initialize raw data */ + if(fill_time==H5D_FILL_TIME_ALLOC) + if(H5D_init_storage(dataset, file_space) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize dataset with fill value"); + + /* Update layout message */ + if (H5O_modify (&(dataset->ent), H5O_LAYOUT, 0, H5O_FLAG_CONSTANT, + &(dataset->layout)) < 0) + HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update layout message"); + } /* end if */ + /* * Locate the type conversion function and data space conversion * functions, and set up the element numbering information. If a data @@ -2618,16 +2897,12 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, #ifdef QAK printf("%s: check 0.7, H5T_IS_NOOP(path)=%d, sconv->write=%p\n", FUNC, (int)H5T_IS_NOOP(tpath), sconv->write); #endif /* QAK */ + if (H5T_IS_NOOP(tpath) && sconv->write) { + #ifdef H5S_DEBUG H5_timer_begin(&timer); #endif - if(H5P_get(dc_plist, H5D_CRT_DATA_PIPELINE_NAME, &pline) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get pipeline"); - if(H5P_get(dc_plist, H5D_CRT_FILL_VALUE_NAME, &fill) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve fill value"); - if(H5P_get(dc_plist, H5D_CRT_EXT_FILE_LIST_NAME, &efl) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get external file list"); status = (sconv->write)(dataset->ent.file, &(dataset->layout), &pline, &fill, &efl, H5T_get_size(dataset->type), file_space, mem_space, dxpl_id, buf/*out*/); @@ -2734,14 +3009,6 @@ printf("%s: check 2.0, src_type_size=%d, dst_type_size=%d, target_size=%d\n",FUN printf("%s: check 4.0, nelmts=%d, request_nelmts=%d, need_bkg=%d\n", FUNC,(int)nelmts,(int)request_nelmts,(int)need_bkg); #endif - /* Get some necessary information for later */ - if(H5P_get(dc_plist, H5D_CRT_DATA_PIPELINE_NAME, &pline) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get data pipeline"); - if(H5P_get(dc_plist, H5D_CRT_FILL_VALUE_NAME, &fill) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get fill value"); - if(H5P_get(dc_plist, H5D_CRT_EXT_FILE_LIST_NAME, &efl) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get external file list"); - /* Start strip mining... */ H5_CHECK_OVERFLOW(nelmts,hssize_t,hsize_t); for (smine_start=0; smine_start<(hsize_t)nelmts; smine_start+=smine_nelmts) { @@ -2888,6 +3155,7 @@ done: H5FL_BLK_FREE(bkgr_conv,bkg_buf); if (free_this_space) H5S_close(free_this_space); + FUNC_LEAVE(ret_value); } @@ -3106,15 +3374,14 @@ H5D_init_storage(H5D_t *dset, const H5S_t *space) switch (dset->layout.type) { case H5D_CONTIGUOUS: /* - * If the fill value is set then write it to the specified selection - * even if it is all zero. This allows the application to force - * filling when the underlying storage isn't initialized to zero. + * If the fill value is set then write it to the entire extent + * of the dataset. */ snpoints = H5S_get_simple_extent_npoints(space); assert(snpoints>=0); H5_ASSIGN_OVERFLOW(npoints,snpoints,hssize_t,size_t); - if (fill.buf && npoints==(size_t)H5S_get_select_npoints(space)) { + if (fill.buf) { /* * Fill the entire current extent with the fill value. We can do * this quite efficiently by making sure we copy the fill value @@ -3147,12 +3414,7 @@ H5D_init_storage(H5D_t *dset, const H5S_t *space) npoints -= MIN(ptsperbuf, npoints); addr += size; } /* end while */ - } else if(fill.buf) { - /* - * Fill the specified selection with the fill value. - */ - HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to initialize dataset with fill value"); - } + } /* end if */ break; case H5D_CHUNKED: @@ -3246,21 +3508,28 @@ H5Dget_storage_size(hid_t dset_id) hsize_t H5D_get_storage_size(H5D_t *dset) { - hsize_t size; - unsigned u; + unsigned u; /* Index variable */ + hsize_t ret_value=0; FUNC_ENTER(H5D_get_storage_size, 0); if (H5D_CHUNKED==dset->layout.type) { - size = H5F_istore_allocated(dset->ent.file, dset->layout.ndims, + ret_value = H5F_istore_allocated(dset->ent.file, dset->layout.ndims, dset->layout.addr); } else { - for (u=0, size=1; u<dset->layout.ndims; u++) { - size *= dset->layout.dim[u]; - } - } + /* Sanity Check */ + assert(dset->layout.type==H5D_CONTIGUOUS); + + /* Datasets which are not allocated yet are using no space on disk */ + if(dset->layout.addr == HADDR_UNDEF) + ret_value=0; + else { + for (u=0, ret_value=1; u<dset->layout.ndims; u++) + ret_value *= dset->layout.dim[u]; + } /* end else */ + } /* end else */ - FUNC_LEAVE(size); + FUNC_LEAVE(ret_value); } @@ -3597,16 +3866,16 @@ done: /*-------------------------------------------------------------------------- NAME - H5Dfill + H5D_fill PURPOSE - Fill a selection in memory with a value + Fill a selection in memory with a value (internal version) USAGE - herr_t H5Dfill(fill, fill_type, space, buf, buf_type) + herr_t H5Dfill(fill, fill_type, buf, buf_type, space) const void *fill; IN: Pointer to fill value to use - hid_t fill_type_id; IN: Datatype of the fill value + H5T_t *fill_type; 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 & + 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. @@ -3614,37 +3883,33 @@ done: 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 --------------------------------------------------------------------------*/ -herr_t -H5Dfill(const void *fill, hid_t fill_type_id, void *buf, hid_t buf_type_id, hid_t space_id) +static herr_t +H5D_fill(const void *fill, const H5T_t *fill_type, void *buf, const H5T_t *buf_type, const H5S_t *space) { - H5S_t *space; /* Dataspace */ - H5T_t *fill_type; /* Fill-value datatype */ - H5T_t *buf_type; /* Buffer datatype */ H5T_path_t *tpath = NULL; /* Conversion information*/ uint8_t *tconv_buf = NULL; /* Data type conv buffer */ uint8_t *bkg_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*/ size_t buf_size; /* Desired buffer size */ herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER (H5Dfill, FAIL); - H5TRACE5("e","xixii",fill,fill_type_id,buf,buf_type_id,space_id); + FUNC_ENTER (H5D_fill, FAIL); /* Check args */ - if (fill==NULL) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid fill value"); - if (buf==NULL) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid buffer"); - if (H5I_DATASPACE != H5I_get_type(space_id) || NULL == (space=H5I_object(space_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a dataspace"); - if (H5I_DATATYPE != H5I_get_type(fill_type_id) || NULL == (fill_type=H5I_object(fill_type_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a datatype"); - if (H5I_DATATYPE != H5I_get_type(buf_type_id) || NULL == (buf_type=H5I_object(buf_type_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a datatype"); + assert(buf); + assert(buf_type); + assert(space); + + /* Check for "default" fill value */ + if(fill_type==NULL) + fill_type=buf_type; /* Get the memory and file datatype sizes */ src_type_size = H5T_get_size(fill_type); @@ -3656,15 +3921,23 @@ H5Dfill(const void *fill, hid_t fill_type_id, void *buf, hid_t buf_type_id, hid_ 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(fill==NULL) + HDmemset(tconv_buf,0,src_type_size); + else + HDmemcpy(tconv_buf,fill,src_type_size); /* Convert memory buffer into disk buffer */ /* Set up type conversion function */ - if (NULL == (tpath = H5T_path_find(fill_type, buf_type, NULL, NULL))) + if (NULL == (tpath = H5T_path_find(fill_type, buf_type, NULL, NULL))) { HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest data types"); + } else if (!H5T_IS_NOOP(tpath)) { + if ((src_id = H5I_register(H5I_DATATYPE, H5T_copy(fill_type, H5T_COPY_ALL)))<0 || + (dst_id = H5I_register(H5I_DATATYPE, H5T_copy(buf_type, H5T_COPY_ALL)))<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register types for conversion"); + } /* Perform data type conversion */ - if (H5T_convert(tpath, fill_type_id, buf_type_id, (hsize_t)1, 0, 0, tconv_buf, bkg_buf, H5P_DEFAULT)<0) + if (H5T_convert(tpath, src_id, dst_id, (hsize_t)1, 0, 0, tconv_buf, bkg_buf, H5P_DEFAULT)<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "data type conversion failed"); /* Fill the selection in the memory buffer */ @@ -3679,9 +3952,104 @@ done: FUNC_LEAVE (ret_value); } /* H5Dfill() */ + +/*-------------------------------------------------------------------------- + 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 (H5Dfill, FAIL); + H5TRACE5("e","xixii",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 (H5I_DATASPACE != H5I_get_type(space_id) || NULL == (space=H5I_object(space_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a dataspace"); + if (H5I_DATATYPE != H5I_get_type(fill_type_id) || NULL == (fill_type=H5I_object(fill_type_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a datatype"); + if (H5I_DATATYPE != H5I_get_type(buf_type_id) || NULL == (buf_type=H5I_object(buf_type_id))) + 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)<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTENCODE, FAIL, "filling selection failed"); + +done: + FUNC_LEAVE (ret_value); +} /* H5Dfill() */ + +/*------------------------------------------------------------------------- + * Function: H5Ddebug + * + * Purpose: Prints various information about a dataset. This function is + * not to be documented in the API at this time. + * + * Return: Success: Non-negative + * + * Failure: Negative + * + * Programmer: Robb Matzke + * Wednesday, April 28, 1999 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Ddebug(hid_t dset_id, unsigned UNUSED flags) +{ + H5D_t *dset=NULL; + + FUNC_ENTER(H5Ddebug, FAIL); + H5TRACE2("e","iIu",dset_id,flags); + + /* Check args */ + if (H5I_DATASET!=H5I_get_type(dset_id) || + NULL==(dset=H5I_object(dset_id))) { + HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset"); + } + + /* Print B-tree information */ + if (H5D_CHUNKED==dset->layout.type) { + H5F_istore_dump_btree(dset->ent.file, stdout, dset->layout.ndims, + dset->layout.addr); + } else if (H5D_CONTIGUOUS==dset->layout.type) { + HDfprintf(stdout, " %-10s %a\n", "Address:", + dset->layout.addr); + } + + FUNC_LEAVE(SUCCEED); +} + + /*------------------------------------------------------------------------- * Function: H5Dset_extent * @@ -3879,49 +4247,3 @@ done: H5S_close( space ); FUNC_LEAVE( ret_value ); } - - - -/*------------------------------------------------------------------------- - * Function: H5Ddebug - * - * Purpose: Prints various information about a dataset. This function is - * not to be documented in the API at this time. - * - * Return: Success: Non-negative - * - * Failure: Negative - * - * Programmer: Robb Matzke - * Wednesday, April 28, 1999 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5Ddebug(hid_t dset_id, unsigned UNUSED flags) -{ - H5D_t *dset=NULL; - - FUNC_ENTER(H5Ddebug, FAIL); - H5TRACE2("e","iIu",dset_id,flags); - - /* Check args */ - if (H5I_DATASET!=H5I_get_type(dset_id) || - NULL==(dset=H5I_object(dset_id))) { - HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset"); - } - - /* Print B-tree information */ - if (H5D_CHUNKED==dset->layout.type) { - H5F_istore_dump_btree(dset->ent.file, stdout, dset->layout.ndims, - dset->layout.addr); - } else if (H5D_CONTIGUOUS==dset->layout.type) { - HDfprintf(stdout, " %-10s %a\n", "Address:", - dset->layout.addr); - } - - FUNC_LEAVE(SUCCEED); -} - |