From bd66cdd5d6b46ddb9b275903baffcbeaaff65204 Mon Sep 17 00:00:00 2001 From: Mohamad Chaarawi Date: Tue, 22 Jul 2014 14:54:51 -0500 Subject: [svn-r25468] some code refactoring to align trunk with VOL branch. tested with h5committest. --- MANIFEST | 1 + src/CMakeLists.txt | 1 + src/H5A.c | 1074 +--------------------- src/H5Adeprec.c | 7 +- src/H5Aint.c | 1152 ++++++++++++++++++++++++ src/H5Apkg.h | 14 +- src/H5D.c | 193 +--- src/H5Dint.c | 269 ++++++ src/H5Dio.c | 111 +-- src/H5Dprivate.h | 3 + src/H5F.c | 1963 +---------------------------------------- src/H5Fint.c | 2051 +++++++++++++++++++++++++++++++++++++++++++ src/H5Fpkg.h | 6 + src/H5Fprivate.h | 1 + src/Makefile.am | 2 +- src/Makefile.in | 29 +- test/testfiles/err_compat_1 | 5 +- 17 files changed, 3660 insertions(+), 3222 deletions(-) create mode 100644 src/H5Fint.c diff --git a/MANIFEST b/MANIFEST index a02497f..685022f 100644 --- a/MANIFEST +++ b/MANIFEST @@ -673,6 +673,7 @@ ./src/H5Fdeprec.c ./src/H5Fefc.c ./src/H5Ffake.c +./src/H5Fint.c ./src/H5Fio.c ./src/H5Fmount.c ./src/H5Fmpi.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8fd232b..d5d57d4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -162,6 +162,7 @@ IDE_GENERATED_PROPERTIES ("H5EA" "${H5EA_HDRS}" "${H5EA_SRCS}" ) set (H5F_SRCS ${HDF5_SRC_DIR}/H5F.c + ${HDF5_SRC_DIR}/H5Fint.c ${HDF5_SRC_DIR}/H5Faccum.c ${HDF5_SRC_DIR}/H5Fcwfs.c ${HDF5_SRC_DIR}/H5Fdbg.c diff --git a/src/H5A.c b/src/H5A.c index 9a51214..a414689 100644 --- a/src/H5A.c +++ b/src/H5A.c @@ -63,10 +63,6 @@ typedef struct H5A_iter_cb1 { /* Local Prototypes */ /********************/ -static herr_t H5A_open_common(const H5G_loc_t *loc, H5A_t *attr); -static herr_t H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf, hid_t dxpl_id); -static herr_t H5A_read(const H5A_t *attr, const H5T_t *mem_type, void *buf, hid_t dxpl_id); - /*********************/ /* Package Variables */ @@ -229,6 +225,7 @@ hid_t H5Acreate2(hid_t loc_id, const char *attr_name, hid_t type_id, hid_t space_id, hid_t acpl_id, hid_t UNUSED aapl_id) { + H5A_t *attr = NULL; /* Attribute created */ H5G_loc_t loc; /* Object location */ H5T_t *type; /* Datatype to use for attribute */ H5S_t *space; /* Dataspace to use for attribute */ @@ -252,10 +249,18 @@ H5Acreate2(hid_t loc_id, const char *attr_name, hid_t type_id, hid_t space_id, HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") /* Go do the real work for attaching the attribute to the dataset */ - if((ret_value = H5A_create(&loc, attr_name, type, space, acpl_id, H5AC_dxpl_id)) < 0) + if(NULL == (attr = H5A_create(&loc, attr_name, type, space, acpl_id, H5AC_dxpl_id))) HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to create attribute") + /* Register the new attribute and get an ID for it */ + if((ret_value = H5I_register(H5I_ATTR, attr, TRUE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register attribute for ID") + done: + /* Cleanup on failure */ + if(ret_value < 0 && attr && H5A_close(attr) < 0) + HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "can't close attribute") + FUNC_LEAVE_API(ret_value) } /* H5Acreate2() */ @@ -296,6 +301,7 @@ H5Acreate_by_name(hid_t loc_id, const char *obj_name, const char *attr_name, hid_t type_id, hid_t space_id, hid_t acpl_id, hid_t UNUSED aapl_id, hid_t lapl_id) { + H5A_t *attr = NULL; /* Attribute created */ H5G_loc_t loc; /* Object location */ H5G_loc_t obj_loc; /* Location used to open group */ H5G_name_t obj_path; /* Opened object group hier. path */ @@ -336,185 +342,21 @@ H5Acreate_by_name(hid_t loc_id, const char *obj_name, const char *attr_name, loc_found = TRUE; /* Go do the real work for attaching the attribute to the dataset */ - if((ret_value = H5A_create(&obj_loc, attr_name, type, space, acpl_id, H5AC_dxpl_id)) < 0) + if(NULL == (attr = H5A_create(&obj_loc, attr_name, type, space, acpl_id, H5AC_dxpl_id))) HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to create attribute") -done: - /* Release resources */ - if(loc_found && H5G_loc_free(&obj_loc) < 0) - HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't free location") - - FUNC_LEAVE_API(ret_value) -} /* H5Acreate_by_name() */ - - -/*------------------------------------------------------------------------- - * Function: H5A_create - * - * Purpose: - * This is the guts of creating an attribute. - * Usage: - * hid_t H5A_create(ent, name, type, space) - * const H5G_entry_t *ent; IN: Pointer to symbol table entry for object to attribute - * const char *name; IN: Name of attribute - * H5T_t *type; IN: Datatype of attribute - * H5S_t *space; IN: Dataspace of attribute - * hid_t acpl_id IN: Attribute creation property list - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * April 2, 1998 - * - *------------------------------------------------------------------------- - */ -hid_t -H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type, - const H5S_t *space, hid_t acpl_id, hid_t dxpl_id) -{ - H5A_t *attr = NULL; /* Attribute created */ - hssize_t snelmts; /* elements in attribute */ - size_t nelmts; /* elements in attribute */ - htri_t tri_ret; /* htri_t return value */ - hid_t ret_value; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT_TAG(dxpl_id, loc->oloc->addr, FAIL) - - /* check args */ - HDassert(loc); - HDassert(name); - HDassert(type); - HDassert(space); - - /* Check for existing attribute with same name */ - /* (technically, the "attribute create" operation will fail for a duplicated - * name, but it's going to be hard to unwind all the special cases on - * failure, so just check first, for now - QAK) - */ - if((tri_ret = H5O_attr_exists(loc->oloc, name, H5AC_ind_dxpl_id)) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "error checking attributes") - else if(tri_ret > 0) - HGOTO_ERROR(H5E_ATTR, H5E_ALREADYEXISTS, FAIL, "attribute already exists") - - /* Check if the dataspace has an extent set (or is NULL) */ - if(!(H5S_has_extent(space))) - HGOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, "dataspace extent has not been set") - - /* Check if the datatype is "sensible" for use in a dataset */ - if(H5T_is_sensible(type) != TRUE) - HGOTO_ERROR(H5E_ATTR, H5E_BADTYPE, FAIL, "datatype is not sensible") - - /* Build the attribute information */ - if(NULL == (attr = H5FL_CALLOC(H5A_t))) - HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, "memory allocation failed for attribute info") - - if(NULL == (attr->shared = H5FL_CALLOC(H5A_shared_t))) - HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, "can't allocate shared attr structure") - - /* If the creation property list is H5P_DEFAULT, use the default character encoding */ - if(acpl_id == H5P_DEFAULT) - attr->shared->encoding = H5F_DEFAULT_CSET; - else { - H5P_genplist_t *ac_plist; /* ACPL Property list */ - - /* Get a local copy of the attribute creation property list */ - if(NULL == (ac_plist = (H5P_genplist_t *)H5I_object(acpl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list") - - if(H5P_get(ac_plist, H5P_STRCRT_CHAR_ENCODING_NAME, &(attr->shared->encoding)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get character encoding flag") - } /* end else */ - - /* Copy the attribute name */ - attr->shared->name = H5MM_xstrdup(name); - - /* Copy datatype */ - if(NULL == (attr->shared->dt = H5T_copy(type, H5T_COPY_ALL))) - HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get shared datatype info") - - /* Mark datatype as being on disk now */ - if(H5T_set_loc(attr->shared->dt, loc->oloc->file, H5T_LOC_DISK) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location") - - /* Set the latest format for datatype, if requested */ - if(H5F_USE_LATEST_FORMAT(loc->oloc->file)) - if(H5T_set_latest_version(attr->shared->dt) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set latest version of datatype") - - /* Copy the dataspace for the attribute */ - attr->shared->ds = H5S_copy(space, FALSE, TRUE); - - /* Set the latest format for dataspace, if requested */ - if(H5F_USE_LATEST_FORMAT(loc->oloc->file)) - if(H5S_set_latest_version(attr->shared->ds) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set latest version of dataspace") - - /* Copy the object header information */ - if(H5O_loc_copy(&(attr->oloc), loc->oloc, H5_COPY_DEEP) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to copy entry") - - /* Deep copy of the group hierarchy path */ - if(H5G_name_copy(&(attr->path), loc->path, H5_COPY_DEEP) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "unable to copy path") - - /* Check if any of the pieces should be (or are already) shared in the - * SOHM table - */ - if(H5SM_try_share(attr->oloc.file, dxpl_id, NULL, 0, H5O_DTYPE_ID, attr->shared->dt, NULL) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "trying to share datatype failed") - if(H5SM_try_share(attr->oloc.file, dxpl_id, NULL, 0, H5O_SDSPACE_ID, attr->shared->ds, NULL) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "trying to share dataspace failed") - - /* Check whether datatype is committed & increment ref count - * (to maintain ref. count incr/decr similarity with "shared message" - * type of datatype sharing) - */ - if(H5T_committed(attr->shared->dt)) { - /* Increment the reference count on the shared datatype */ - if(H5T_link(attr->shared->dt, 1, dxpl_id) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared datatype link count") - } /* end if */ - - /* Compute the size of pieces on disk. This is either the size of the - * datatype and dataspace messages themselves, or the size of the "shared" - * messages if either or both of them are shared. - */ - attr->shared->dt_size = H5O_msg_raw_size(attr->oloc.file, H5O_DTYPE_ID, FALSE, attr->shared->dt); - attr->shared->ds_size = H5O_msg_raw_size(attr->oloc.file, H5O_SDSPACE_ID, FALSE, attr->shared->ds); - - /* Get # of elements for attribute's dataspace */ - if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->shared->ds)) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, FAIL, "dataspace is invalid") - H5_ASSIGN_OVERFLOW(nelmts, snelmts, hssize_t, size_t); - - HDassert(attr->shared->dt_size > 0); - HDassert(attr->shared->ds_size > 0); - attr->shared->data_size = nelmts * H5T_GET_SIZE(attr->shared->dt); - - /* Hold the symbol table entry (and file) open */ - if(H5O_open(&(attr->oloc)) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open") - attr->obj_opened = TRUE; - - /* Set the version to encode the attribute with */ - if(H5A_set_version(attr->oloc.file, attr) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "unable to update attribute version") - - /* Insert the attribute into the object header */ - if(H5O_attr_create(&(attr->oloc), dxpl_id, attr) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to create attribute in object header") - /* Register the new attribute and get an ID for it */ if((ret_value = H5I_register(H5I_ATTR, attr, TRUE)) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register attribute for ID") - done: - /* Cleanup on failure */ + /* Release resources */ + if(loc_found && H5G_loc_free(&obj_loc) < 0) + HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't free location") if(ret_value < 0 && attr && H5A_close(attr) < 0) HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "can't close attribute") - FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL) -} /* H5A_create() */ + FUNC_LEAVE_API(ret_value) +} /* H5Acreate_by_name() */ /*-------------------------------------------------------------------------- @@ -712,192 +554,6 @@ done: } /* H5Aopen_by_idx() */ -/*------------------------------------------------------------------------- - * Function: H5A_open_common - * - * Purpose: - * Finishes initializing an attributes the open - * - * Usage: - * herr_t H5A_open_common(loc, name, dxpl_id) - * const H5G_loc_t *loc; IN: Pointer to group location for object - * H5A_t *attr; IN/OUT: Pointer to attribute to initialize - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * December 18, 2006 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5A_open_common(const H5G_loc_t *loc, H5A_t *attr) -{ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT - - /* check args */ - HDassert(loc); - HDassert(attr); - -#if defined(H5_USING_MEMCHECKER) || !defined(NDEBUG) - /* Clear object location */ - if(H5O_loc_reset(&(attr->oloc)) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to reset location") -#endif /* H5_USING_MEMCHECKER */ - - /* Free any previous group hier. path */ - if(H5G_name_free(&(attr->path)) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release group hier. path") - - /* Deep copy of the symbol table entry */ - if(H5O_loc_copy(&(attr->oloc), loc->oloc, H5_COPY_DEEP) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to copy entry") - - /* Deep copy of the group hier. path */ - if(H5G_name_copy(&(attr->path), loc->path, H5_COPY_DEEP) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "unable to copy entry") - - /* Hold the symbol table entry (and file) open */ - if(H5O_open(&(attr->oloc)) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open") - attr->obj_opened = TRUE; - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5A_open_common() */ - - -/*------------------------------------------------------------------------- - * Function: H5A_open_by_idx - * - * Purpose: Open an attribute according to its index order - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * April 2, 1998 - * - *------------------------------------------------------------------------- - */ -H5A_t * -H5A_open_by_idx(const H5G_loc_t *loc, const char *obj_name, H5_index_t idx_type, - H5_iter_order_t order, hsize_t n, hid_t lapl_id, hid_t dxpl_id) -{ - H5G_loc_t obj_loc; /* Location used to open group */ - H5G_name_t obj_path; /* Opened object group hier. path */ - H5O_loc_t obj_oloc; /* Opened object object location */ - hbool_t loc_found = FALSE; /* Entry at 'obj_name' found */ - H5A_t *attr = NULL; /* Attribute from object header */ - H5A_t *ret_value; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT - - /* check args */ - HDassert(loc); - HDassert(obj_name); - - /* Set up opened group location to fill in */ - obj_loc.oloc = &obj_oloc; - obj_loc.path = &obj_path; - H5G_loc_reset(&obj_loc); - - /* Find the object's location */ - if(H5G_loc_find(loc, obj_name, &obj_loc/*out*/, lapl_id, dxpl_id) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "object not found") - loc_found = TRUE; - - /* Read in attribute from object header */ - if(NULL == (attr = H5O_attr_open_by_idx(obj_loc.oloc, idx_type, order, n, dxpl_id))) - HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to load attribute info from object header") - - /* Finish initializing attribute */ - if(H5A_open_common(&obj_loc, attr) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to initialize attribute") - - /* Set return value */ - ret_value = attr; - -done: - /* Release resources */ - if(loc_found && H5G_loc_free(&obj_loc) < 0) - HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, NULL, "can't free location") - - /* Cleanup on failure */ - if(ret_value == NULL) - if(attr && H5A_close(attr) < 0) - HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute") - - FUNC_LEAVE_NOAPI(ret_value) -} /* H5A_open_by_idx() */ - - -/*------------------------------------------------------------------------- - * Function: H5A_open_by_name - * - * Purpose: Open an attribute in an object header, according to it's name - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * December 11, 2006 - * - *------------------------------------------------------------------------- - */ -H5A_t * -H5A_open_by_name(const H5G_loc_t *loc, const char *obj_name, const char *attr_name, - hid_t lapl_id, hid_t dxpl_id) -{ - H5G_loc_t obj_loc; /* Location used to open group */ - H5G_name_t obj_path; /* Opened object group hier. path */ - H5O_loc_t obj_oloc; /* Opened object object location */ - hbool_t loc_found = FALSE; /* Entry at 'obj_name' found */ - H5A_t *attr = NULL; /* Attribute from object header */ - H5A_t *ret_value; /* Return value */ - - FUNC_ENTER_NOAPI(NULL) - - /* check args */ - HDassert(loc); - HDassert(obj_name); - HDassert(attr_name); - - /* Set up opened group location to fill in */ - obj_loc.oloc = &obj_oloc; - obj_loc.path = &obj_path; - H5G_loc_reset(&obj_loc); - - /* Find the object's location */ - if(H5G_loc_find(loc, obj_name, &obj_loc/*out*/, lapl_id, dxpl_id) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "object not found") - loc_found = TRUE; - - /* Read in attribute from object header */ - if(NULL == (attr = H5O_attr_open_by_name(obj_loc.oloc, attr_name, dxpl_id))) - HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to load attribute info from object header") - - /* Finish initializing attribute */ - if(H5A_open_common(loc, attr) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to initialize attribute") - - /* Set return value */ - ret_value = attr; - -done: - /* Release resources */ - if(loc_found && H5G_loc_free(&obj_loc) < 0) - HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, NULL, "can't free location") - - /* Cleanup on failure */ - if(ret_value == NULL) - if(attr && H5A_close(attr) < 0) - HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute") - - FUNC_LEAVE_NOAPI(ret_value) -} /* H5A_open_by_name() */ - - /*-------------------------------------------------------------------------- NAME H5Awrite @@ -943,120 +599,6 @@ done: /*-------------------------------------------------------------------------- NAME - H5A_write - PURPOSE - Actually write out data to an attribute - USAGE - herr_t H5A_write (attr, mem_type, buf) - H5A_t *attr; IN: Attribute to write - const H5T_t *mem_type; IN: Memory datatype of buffer - const void *buf; IN: Buffer of data to write - RETURNS - Non-negative on success/Negative on failure - - DESCRIPTION - This function writes a complete attribute to disk. ---------------------------------------------------------------------------*/ -static herr_t -H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf, hid_t dxpl_id) -{ - uint8_t *tconv_buf = NULL; /* datatype conv buffer */ - hbool_t tconv_owned = FALSE; /* Whether the datatype conv buffer is owned by attribute */ - uint8_t *bkg_buf = NULL; /* temp conversion buffer */ - hssize_t snelmts; /* elements in attribute */ - size_t nelmts; /* elements in attribute */ - H5T_path_t *tpath = NULL; /* conversion information*/ - hid_t src_id = -1, dst_id = -1;/* temporary type atoms */ - 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; - - FUNC_ENTER_NOAPI_NOINIT_TAG(dxpl_id, attr->oloc.addr, FAIL) - - HDassert(attr); - HDassert(mem_type); - HDassert(buf); - - /* Get # of elements for attribute's dataspace */ - if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->shared->ds)) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, FAIL, "dataspace is invalid") - H5_ASSIGN_OVERFLOW(nelmts, snelmts, hssize_t, size_t); - - /* If there's actually data elements for the attribute, make a copy of the data passed in */ - if(nelmts > 0) { - /* Get the memory and file datatype sizes */ - src_type_size = H5T_GET_SIZE(mem_type); - dst_type_size = H5T_GET_SIZE(attr->shared->dt); - - /* Convert memory buffer into disk buffer */ - /* Set up type conversion function */ - if(NULL == (tpath = H5T_path_find(mem_type, attr->shared->dt, NULL, NULL, dxpl_id, FALSE))) - HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dst datatypes") - - /* Check for type conversion required */ - if(!H5T_path_noop(tpath)) { - if((src_id = H5I_register(H5I_DATATYPE, H5T_copy(mem_type, H5T_COPY_ALL), FALSE)) < 0 || - (dst_id = H5I_register(H5I_DATATYPE, H5T_copy(attr->shared->dt, H5T_COPY_ALL), FALSE)) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, FAIL, "unable to register types for conversion") - - /* Get the maximum buffer size needed and allocate it */ - buf_size = nelmts * MAX(src_type_size, dst_type_size); - if(NULL == (tconv_buf = H5FL_BLK_MALLOC(attr_buf, buf_size))) - HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, "memory allocation failed") - if(NULL == (bkg_buf = H5FL_BLK_CALLOC(attr_buf, buf_size))) - HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, "memory allocation failed") - - /* Copy the user's data into the buffer for conversion */ - HDmemcpy(tconv_buf, buf, (src_type_size * nelmts)); - - /* Perform datatype conversion */ - if(H5T_convert(tpath, src_id, dst_id, nelmts, (size_t)0, (size_t)0, tconv_buf, bkg_buf, dxpl_id) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "datatype conversion failed") - - /* Free the previous attribute data buffer, if there is one */ - if(attr->shared->data) - attr->shared->data = H5FL_BLK_FREE(attr_buf, attr->shared->data); - - /* Set the pointer to the attribute data to the converted information */ - attr->shared->data = tconv_buf; - tconv_owned = TRUE; - } /* end if */ - /* No type conversion necessary */ - else { - HDassert(dst_type_size == src_type_size); - - /* Allocate the attribute buffer, if there isn't one */ - if(attr->shared->data == NULL) - if(NULL == (attr->shared->data = H5FL_BLK_MALLOC(attr_buf, dst_type_size * nelmts))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") - - /* Copy the attribute data into the user's buffer */ - HDmemcpy(attr->shared->data, buf, (dst_type_size * nelmts)); - } /* end else */ - - /* Modify the attribute in the object header */ - if(H5O_attr_write(&(attr->oloc), dxpl_id, attr) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to modify attribute") - } /* end if */ - -done: - /* Release resources */ - if(src_id >= 0 && H5I_dec_ref(src_id) < 0) - HDONE_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to close temporary object") - if(dst_id >= 0 && H5I_dec_ref(dst_id) < 0) - HDONE_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to close temporary object") - if(tconv_buf && !tconv_owned) - tconv_buf = H5FL_BLK_FREE(attr_buf, tconv_buf); - if(bkg_buf) - bkg_buf = H5FL_BLK_FREE(attr_buf, bkg_buf); - - FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL) -} /* H5A_write() */ - - -/*-------------------------------------------------------------------------- - NAME H5Aread PURPOSE Read in data from an attribute @@ -1100,109 +642,6 @@ done: /*-------------------------------------------------------------------------- NAME - H5A_read - PURPOSE - Actually read in data from an attribute - USAGE - herr_t H5A_read (attr, mem_type, buf) - H5A_t *attr; IN: Attribute to read - const H5T_t *mem_type; IN: Memory datatype of buffer - void *buf; IN: Buffer for data to read - RETURNS - Non-negative on success/Negative on failure - - DESCRIPTION - This function reads a complete attribute from disk. ---------------------------------------------------------------------------*/ -static herr_t -H5A_read(const H5A_t *attr, const H5T_t *mem_type, void *buf, hid_t dxpl_id) -{ - uint8_t *tconv_buf = NULL; /* datatype conv buffer*/ - uint8_t *bkg_buf = NULL; /* background buffer */ - hssize_t snelmts; /* elements in attribute */ - size_t nelmts; /* elements in attribute*/ - H5T_path_t *tpath = NULL; /* type conversion info */ - hid_t src_id = -1, dst_id = -1;/* temporary type atoms*/ - 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; - - FUNC_ENTER_NOAPI_NOINIT - - HDassert(attr); - HDassert(mem_type); - HDassert(buf); - - /* Create buffer for data to store on disk */ - if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->shared->ds)) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, FAIL, "dataspace is invalid") - H5_ASSIGN_OVERFLOW(nelmts, snelmts, hssize_t, size_t); - - if(nelmts > 0) { - /* Get the memory and file datatype sizes */ - src_type_size = H5T_GET_SIZE(attr->shared->dt); - dst_type_size = H5T_GET_SIZE(mem_type); - - /* Check if the attribute has any data yet, if not, fill with zeroes */ - if(attr->obj_opened && !attr->shared->data) - HDmemset(buf, 0, (dst_type_size * nelmts)); - else { /* Attribute exists and has a value */ - /* Convert memory buffer into disk buffer */ - /* Set up type conversion function */ - if(NULL == (tpath = H5T_path_find(attr->shared->dt, mem_type, NULL, NULL, dxpl_id, FALSE))) - HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dst datatypes") - - /* Check for type conversion required */ - if(!H5T_path_noop(tpath)) { - if((src_id = H5I_register(H5I_DATATYPE, H5T_copy(attr->shared->dt, H5T_COPY_ALL), FALSE)) < 0 || - (dst_id = H5I_register(H5I_DATATYPE, H5T_copy(mem_type, H5T_COPY_ALL), FALSE)) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, FAIL, "unable to register types for conversion") - - /* Get the maximum buffer size needed and allocate it */ - buf_size = nelmts * MAX(src_type_size, dst_type_size); - if(NULL == (tconv_buf = H5FL_BLK_MALLOC(attr_buf, buf_size))) - HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "memory allocation failed") - if(NULL == (bkg_buf = H5FL_BLK_CALLOC(attr_buf, buf_size))) - HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "memory allocation failed") - - /* Copy the attribute data into the buffer for conversion */ - HDmemcpy(tconv_buf, attr->shared->data, (src_type_size * nelmts)); - - /* Perform datatype conversion. */ - if(H5T_convert(tpath, src_id, dst_id, nelmts, (size_t)0, (size_t)0, tconv_buf, bkg_buf, dxpl_id) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "datatype conversion failed") - - /* Copy the converted data into the user's buffer */ - HDmemcpy(buf, tconv_buf, (dst_type_size * nelmts)); - } /* end if */ - /* No type conversion necessary */ - else { - HDassert(dst_type_size == src_type_size); - - /* Copy the attribute data into the user's buffer */ - HDmemcpy(buf, attr->shared->data, (dst_type_size * nelmts)); - } /* end else */ - } /* end else */ - } /* end if */ - -done: - /* Release resources */ - if(src_id >= 0 && H5I_dec_ref(src_id) < 0) - HDONE_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to close temporary object") - if(dst_id >= 0 && H5I_dec_ref(dst_id) < 0) - HDONE_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to close temporary object") - if(tconv_buf) - tconv_buf = H5FL_BLK_FREE(attr_buf, tconv_buf); - if(bkg_buf) - bkg_buf = H5FL_BLK_FREE(attr_buf, bkg_buf); - - FUNC_LEAVE_NOAPI(ret_value) -} /* H5A_read() */ - - -/*-------------------------------------------------------------------------- - NAME H5Aget_space PURPOSE Gets a copy of the dataspace for an attribute @@ -1221,7 +660,6 @@ hid_t H5Aget_space(hid_t attr_id) { H5A_t *attr; /* Attribute object for ID */ - H5S_t *ds = NULL; /* Copy of dataspace for attribute */ hid_t ret_value; FUNC_ENTER_API(FAIL) @@ -1231,18 +669,10 @@ H5Aget_space(hid_t attr_id) if(NULL == (attr = (H5A_t *)H5I_object_verify(attr_id, H5I_ATTR))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute") - /* Copy the attribute's dataspace */ - if(NULL == (ds = H5S_copy(attr->shared->ds, FALSE, TRUE))) - HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to copy dataspace") - - /* Atomize */ - if((ret_value = H5I_register(H5I_DATASPACE, ds, TRUE)) < 0) - HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace atom") + if((ret_value = H5A_get_space(attr)) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL, "can't get space ID of attribute") done: - if(ret_value < 0 && ds) - (void)H5S_close(ds); - FUNC_LEAVE_API(ret_value) } /* H5Aget_space() */ @@ -1267,7 +697,6 @@ hid_t H5Aget_type(hid_t attr_id) { H5A_t *attr; /* Attribute object for ID */ - H5T_t *dt = NULL; /* Copy of attribute's datatype */ hid_t ret_value; /* Return value */ FUNC_ENTER_API(FAIL) @@ -1277,36 +706,10 @@ H5Aget_type(hid_t attr_id) if(NULL == (attr = (H5A_t *)H5I_object_verify(attr_id, H5I_ATTR))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute") - /* Patch the datatype's "top level" file pointer */ - if(H5T_patch_file(attr->shared->dt, attr->oloc.file) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to patch datatype's file pointer") - - /* - * Copy the attribute's datatype. If the type is a named type then - * reopen the type before returning it to the user. Make the type - * read-only. - */ - if(NULL == (dt = H5T_copy(attr->shared->dt, H5T_COPY_REOPEN))) - HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to copy datatype") - - /* Mark any datatypes as being in memory now */ - if(H5T_set_loc(dt, NULL, H5T_LOC_MEMORY) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location") - - /* Lock copied type */ - if(H5T_lock(dt, FALSE) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to lock transient datatype") - - /* Atomize */ - if((ret_value = H5I_register(H5I_DATATYPE, dt, TRUE)) < 0) - HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register datatype ID") + if((ret_value = H5A_get_type(attr)) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL, "can't get space ID of attribute") done: - if(ret_value < 0) { - if(dt && H5T_close(dt) < 0) - HDONE_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, FAIL, "unable to release datatype") - } /* end if */ - FUNC_LEAVE_API(ret_value) } /* H5Aget_type() */ @@ -1334,9 +737,6 @@ hid_t H5Aget_create_plist(hid_t attr_id) { H5A_t *attr; /* Attribute object for ID */ - H5P_genplist_t *plist; /* Default property list */ - hid_t new_plist_id; /* ID of ACPL to return */ - H5P_genplist_t *new_plist; /* ACPL to return */ hid_t ret_value; FUNC_ENTER_API(FAIL) @@ -1347,20 +747,9 @@ H5Aget_create_plist(hid_t attr_id) /* Get attribute and default attribute creation property list*/ if(NULL == (attr = (H5A_t *)H5I_object_verify(attr_id, H5I_ATTR))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute") - if(NULL == (plist = (H5P_genplist_t *)H5I_object(H5P_LST_ATTRIBUTE_CREATE_ID_g))) - HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "can't get default ACPL") - - /* Create the property list object to return */ - if((new_plist_id = H5P_copy_plist(plist, TRUE)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "unable to copy attribute creation properties") - if(NULL == (new_plist = (H5P_genplist_t *)H5I_object(new_plist_id))) - HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "can't get property list") - - /* Set the character encoding on the new property list */ - if(H5P_set(new_plist, H5P_STRCRT_CHAR_ENCODING_NAME, &(attr->shared->encoding)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set character encoding") - ret_value = new_plist_id; + if((ret_value = H5A_get_create_plist(attr)) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL, "can't get creation property list for attr") done: FUNC_LEAVE_API(ret_value) @@ -1412,53 +801,6 @@ done: } /* H5Aget_name() */ -/*-------------------------------------------------------------------------- - NAME - H5A_get_name - PURPOSE - Private function for H5Aget_name. Gets a copy of the name for an - attribute - RETURNS - This function returns the length of the attribute's name (which may be - longer than 'buf_size') on success or negative for failure. - DESCRIPTION - This function retrieves the name of an attribute for an attribute ID. - Up to 'buf_size' characters are stored in 'buf' followed by a '\0' string - terminator. If the name of the attribute is longer than 'buf_size'-1, - the string terminator is stored in the last position of the buffer to - properly terminate the string. ---------------------------------------------------------------------------*/ -ssize_t -H5A_get_name(H5A_t *attr, size_t buf_size, char *buf) -{ - size_t copy_len, nbytes; - ssize_t ret_value; - - FUNC_ENTER_NOAPI(FAIL) - - /* get the real attribute length */ - nbytes = HDstrlen(attr->shared->name); - HDassert((ssize_t)nbytes >= 0); /*overflow, pretty unlikely --rpm*/ - - /* compute the string length which will fit into the user's buffer */ - copy_len = MIN(buf_size - 1, nbytes); - - /* Copy all/some of the name */ - if(buf && copy_len > 0) { - HDmemcpy(buf, attr->shared->name, copy_len); - - /* Terminate the string */ - buf[copy_len]='\0'; - } /* end if */ - - /* Set return value */ - ret_value = (ssize_t)nbytes; - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5A_get_name() */ - - /*------------------------------------------------------------------------- * Function: H5Aget_name_by_idx * @@ -1723,47 +1065,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5A_get_info - * - * Purpose: Retrieve information about an attribute. - * - * Return: Success: Non-negative - * Failure: Negative - * - * Programmer: Quincey Koziol - * February 6, 2007 - * - *------------------------------------------------------------------------- - */ -herr_t -H5A_get_info(const H5A_t *attr, H5A_info_t *ainfo) -{ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(FAIL) - - /* Check args */ - HDassert(attr); - HDassert(ainfo); - - /* Set info for attribute */ - ainfo->cset = attr->shared->encoding; - ainfo->data_size = attr->shared->data_size; - if(attr->shared->crt_idx == H5O_MAX_CRT_ORDER_IDX) { - ainfo->corder_valid = FALSE; - ainfo->corder = 0; - } /* end if */ - else { - ainfo->corder_valid = TRUE; - ainfo->corder = attr->shared->crt_idx; - } /* end else */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5A_get_info() */ - - -/*------------------------------------------------------------------------- * Function: H5Arename * * Purpose: Rename an attribute @@ -1779,7 +1080,6 @@ done: herr_t H5Arename(hid_t loc_id, const char *old_name, const char *new_name) { - H5G_loc_t loc; /* Object location */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) @@ -1790,14 +1090,18 @@ H5Arename(hid_t loc_id, const char *old_name, const char *new_name) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "name is nil") if(H5I_ATTR == H5I_get_type(loc_id)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute") - if(H5G_loc(loc_id, & loc) < 0) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") /* Avoid thrashing things if the names are the same */ - if(HDstrcmp(old_name, new_name)) - /* Call attribute rename routine */ + if(HDstrcmp(old_name, new_name)) { + H5G_loc_t loc; /* Object location */ + + if(H5G_loc(loc_id, & loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + + /* Call private attribute rename routine */ if(H5O_attr_rename(loc.oloc, H5AC_dxpl_id, old_name, new_name) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTRENAME, FAIL, "can't rename attribute") + } /* end if */ done: FUNC_LEAVE_API(ret_value) @@ -1821,11 +1125,6 @@ herr_t H5Arename_by_name(hid_t loc_id, const char *obj_name, const char *old_attr_name, const char *new_attr_name, hid_t lapl_id) { - H5G_loc_t loc; /* Object location */ - H5G_loc_t obj_loc; /* Location used to open group */ - H5G_name_t obj_path; /* Opened object group hier. path */ - H5O_loc_t obj_oloc; /* Opened object object location */ - hbool_t loc_found = FALSE; /* Entry at 'obj_name' found */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) @@ -1835,8 +1134,6 @@ H5Arename_by_name(hid_t loc_id, const char *obj_name, const char *old_attr_name, /* check arguments */ if(H5I_ATTR == H5I_get_type(loc_id)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute") - if(H5G_loc(loc_id, &loc) < 0) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") if(!obj_name || !*obj_name) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no object name") if(!old_attr_name || !*old_attr_name) @@ -1851,26 +1148,17 @@ H5Arename_by_name(hid_t loc_id, const char *obj_name, const char *old_attr_name, /* Avoid thrashing things if the names are the same */ if(HDstrcmp(old_attr_name, new_attr_name)) { - /* Set up opened group location to fill in */ - obj_loc.oloc = &obj_oloc; - obj_loc.path = &obj_path; - H5G_loc_reset(&obj_loc); - - /* Find the object's location */ - if(H5G_loc_find(&loc, obj_name, &obj_loc/*out*/, lapl_id, H5AC_ind_dxpl_id) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "object not found") - loc_found = TRUE; - - /* Call attribute rename routine */ - if(H5O_attr_rename(obj_loc.oloc, H5AC_dxpl_id, old_attr_name, new_attr_name) < 0) + H5G_loc_t loc; /* Object location */ + + if(H5G_loc(loc_id, & loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + + /* Call private attribute rename routine */ + if(H5A_rename_by_name(loc, obj_name, old_attr_name, new_attr_name, lapl_id) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTRENAME, FAIL, "can't rename attribute") } /* end if */ done: - /* Release resources */ - if(loc_found && H5G_loc_free(&obj_loc) < 0) - HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't free location") - FUNC_LEAVE_API(ret_value) } /* H5Arename_by_name() */ @@ -2297,271 +1585,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5A_copy - * - * Purpose: Copies attribute OLD_ATTR. - * - * Return: Success: Pointer to a new copy of the OLD_ATTR argument. - * - * Failure: NULL - * - * Programmer: Robb Matzke - * Thursday, December 4, 1997 - * - * Modification:Raymond Lu - * 4 June 2008 - * Changed some attribute information to be shared. - * - *------------------------------------------------------------------------- - */ -H5A_t * -H5A_copy(H5A_t *_new_attr, const H5A_t *old_attr) -{ - H5A_t *new_attr = NULL; - hbool_t allocated_attr = FALSE; /* Whether the attribute was allocated */ - H5A_t *ret_value = NULL; /* Return value */ - - FUNC_ENTER_NOAPI(NULL) - - /* check args */ - HDassert(old_attr); - - /* Allocate attribute structure */ - if(_new_attr == NULL) { - if(NULL == (new_attr = H5FL_CALLOC(H5A_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - allocated_attr = TRUE; - } /* end if */ - else - new_attr = _new_attr; - - /* Copy the top level of the attribute */ - new_attr->sh_loc = old_attr->sh_loc; - - /* Deep copy of the group hierarchy path */ - if(H5G_name_copy(&(new_attr->path), &(old_attr->path), H5_COPY_DEEP) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "unable to copy path") - - /* Share some attribute information */ - new_attr->shared = old_attr->shared; - - /* Increment reference count for shared object */ - new_attr->shared->nrefs++; - - /* Don't open the object header for a copy */ - new_attr->obj_opened = FALSE; - - /* Set the return value */ - ret_value = new_attr; - -done: - if(ret_value == NULL) - if(allocated_attr && new_attr && H5A_close(new_attr) < 0) - HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute") - - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5A_copy() */ - - -/*------------------------------------------------------------------------- - * Function: H5A_free - * - * Purpose: Frees all memory associated with an attribute, but does not - * free the H5A_t structure (which should be done in H5T_close). - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * Monday, November 15, 2004 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5A_free(H5A_t *attr) -{ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(FAIL) - - HDassert(attr); - - /* Free dynamicly allocated items */ - if(attr->shared->name) { - H5MM_xfree(attr->shared->name); - attr->shared->name = NULL; - } - if(attr->shared->dt) { - if(H5T_close(attr->shared->dt) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release datatype info") - attr->shared->dt = NULL; - } - if(attr->shared->ds) { - if(H5S_close(attr->shared->ds) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release dataspace info") - attr->shared->ds = NULL; - } - if(attr->shared->data) - attr->shared->data = H5FL_BLK_FREE(attr_buf, attr->shared->data); - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5A_free() */ - - -/*------------------------------------------------------------------------- - * Function: H5A_close - * - * Purpose: Frees an attribute and all associated memory. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Monday, December 8, 1997 - * - * Modifications: - * Raymond Lu - * 4 June 2008 - * Changed some attribute object information to be shared. - *------------------------------------------------------------------------- - */ -herr_t -H5A_close(H5A_t *attr) -{ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(FAIL) - - HDassert(attr); - HDassert(attr->shared); - - /* Close the object's symbol-table entry */ - if(attr->obj_opened && (H5O_close(&(attr->oloc)) < 0)) - HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release object header info") - - /* Reference count can be 0. It only happens when H5A_create fails. */ - if(attr->shared->nrefs <= 1) { - /* Free dynamicly allocated items */ - if(H5A_free(attr) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release attribute info") - - /* Destroy shared attribute struct */ - attr->shared = H5FL_FREE(H5A_shared_t, attr->shared); - } /* end if */ - else { - /* There are other references to the shared part of the attribute. - * Only decrement the reference count. */ - --attr->shared->nrefs; - } /* end else */ - - /* Free group hierarchy path */ - if(H5G_name_free(&(attr->path)) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release group hier. path") - - attr->shared = NULL; - attr = H5FL_FREE(H5A_t, attr); - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5A_close() */ - - -/*------------------------------------------------------------------------- - * Function: H5A_oloc - * - * Purpose: Return the object location for an attribute. It's the - * object location for the object to which the attribute - * belongs, not the attribute itself. - * - * Return: Success: Ptr to entry - * Failure: NULL - * - * Programmer: Robb Matzke - * Thursday, August 6, 1998 - * - *------------------------------------------------------------------------- - */ -H5O_loc_t * -H5A_oloc(H5A_t *attr) -{ - H5O_loc_t *ret_value; /* Return value */ - - FUNC_ENTER_NOAPI(NULL) - - HDassert(attr); - - /* Set return value */ - ret_value = &(attr->oloc); - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5A_oloc() */ - - -/*------------------------------------------------------------------------- - * Function: H5A_nameof - * - * Purpose: Return the group hier. path for an attribute. It's the - * group hier. path for the object to which the attribute - * belongs, not the attribute itself. - * - * Return: Success: Ptr to entry - * Failure: NULL - * - * Programmer: Quincey Koziol - * Monday, September 12, 2005 - * - *------------------------------------------------------------------------- - */ -H5G_name_t * -H5A_nameof(H5A_t *attr) -{ - H5G_name_t *ret_value; /* Return value */ - - FUNC_ENTER_NOAPI(NULL) - - HDassert(attr); - - /* Set return value */ - ret_value=&(attr->path); - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5A_nameof() */ - - -/*------------------------------------------------------------------------- - * Function: H5A_type - * - * Purpose: Return the datatype for an attribute. - * - * Return: Success: Ptr to entry - * Failure: NULL - * - * Programmer: Neil Fortner - * Friday, November 11, 2011 - * - *------------------------------------------------------------------------- - */ -H5T_t * -H5A_type(const H5A_t *attr) -{ - H5T_t *ret_value; /* Return value */ - - FUNC_ENTER_NOAPI(NULL) - - HDassert(attr); - - /* Set return value */ - ret_value = attr->shared->dt; - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5A_type() */ - - -/*------------------------------------------------------------------------- * Function: H5Aexists * * Purpose: Checks if an attribute with a given name exists on an opened @@ -2619,10 +1642,6 @@ H5Aexists_by_name(hid_t loc_id, const char *obj_name, const char *attr_name, hid_t lapl_id) { H5G_loc_t loc; /* Object location */ - H5G_loc_t obj_loc; /* Location used to open group */ - H5G_name_t obj_path; /* Opened object group hier. path */ - H5O_loc_t obj_oloc; /* Opened object object location */ - hbool_t loc_found = FALSE; /* Entry at 'obj_name' found */ htri_t ret_value; /* Return value */ FUNC_ENTER_API(FAIL) @@ -2643,25 +1662,10 @@ H5Aexists_by_name(hid_t loc_id, const char *obj_name, const char *attr_name, if(TRUE != H5P_isa_class(lapl_id, H5P_LINK_ACCESS)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link access property list ID") - /* Set up opened group location to fill in */ - obj_loc.oloc = &obj_oloc; - obj_loc.path = &obj_path; - H5G_loc_reset(&obj_loc); - - /* Find the object's location */ - if(H5G_loc_find(&loc, obj_name, &obj_loc/*out*/, lapl_id, H5AC_ind_dxpl_id) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "object not found") - loc_found = TRUE; - - /* Check if the attribute exists */ - if((ret_value = H5O_attr_exists(obj_loc.oloc, attr_name, H5AC_ind_dxpl_id)) < 0) + if((ret_value = H5A_exists_by_name(loc, obj_name, attr_name, lapl_id)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "unable to determine if attribute exists") done: - /* Release resources */ - if(loc_found && H5G_loc_free(&obj_loc) < 0) - HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't free location") - FUNC_LEAVE_API(ret_value) } /* H5Aexists_by_name() */ diff --git a/src/H5Adeprec.c b/src/H5Adeprec.c index 6194150..6342e18 100644 --- a/src/H5Adeprec.c +++ b/src/H5Adeprec.c @@ -162,6 +162,7 @@ hid_t H5Acreate1(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id, hid_t plist_id) { + H5A_t *attr = NULL; /* Attribute created */ H5G_loc_t loc; /* Object location */ H5T_t *type; /* Datatype to use for attribute */ H5S_t *space; /* Dataspace to use for attribute */ @@ -185,9 +186,13 @@ H5Acreate1(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id, HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") /* Go do the real work for attaching the attribute to the dataset */ - if((ret_value = H5A_create(&loc, name, type, space, plist_id, H5AC_dxpl_id)) < 0) + if((attr = H5A_create(&loc, name, type, space, plist_id, H5AC_dxpl_id)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to create attribute") + /* Register the new attribute and get an ID for it */ + if((ret_value = H5I_register(H5I_ATTR, attr, TRUE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register attribute for ID") + done: FUNC_LEAVE_API(ret_value) } /* H5Acreate1() */ diff --git a/src/H5Aint.c b/src/H5Aint.c index ab9bece..625bfa9 100644 --- a/src/H5Aint.c +++ b/src/H5Aint.c @@ -119,6 +119,1108 @@ H5FL_SEQ_DEFINE(H5A_t_ptr); /*------------------------------------------------------------------------- + * Function: H5A_create + * + * Purpose: + * This is the guts of creating an attribute. + * Usage: + * hid_t H5A_create(ent, name, type, space) + * const H5G_entry_t *ent; IN: Pointer to symbol table entry for object to attribute + * const char *name; IN: Name of attribute + * H5T_t *type; IN: Datatype of attribute + * H5S_t *space; IN: Dataspace of attribute + * hid_t acpl_id IN: Attribute creation property list + * + * Return: attribute structure on success, NULL on Failure. + * + * Programmer: Quincey Koziol + * April 2, 1998 + * + *------------------------------------------------------------------------- + */ +H5A_t * +H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type, + const H5S_t *space, hid_t acpl_id, hid_t dxpl_id) +{ + H5A_t *attr = NULL; /* Attribute created */ + hssize_t snelmts; /* elements in attribute */ + size_t nelmts; /* elements in attribute */ + htri_t tri_ret; /* htri_t return value */ + H5A_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_TAG(dxpl_id, loc->oloc->addr, NULL) + + /* check args */ + HDassert(loc); + HDassert(name); + HDassert(type); + HDassert(space); + + /* Check for existing attribute with same name */ + /* (technically, the "attribute create" operation will fail for a duplicated + * name, but it's going to be hard to unwind all the special cases on + * failure, so just check first, for now - QAK) + */ + if((tri_ret = H5O_attr_exists(loc->oloc, name, H5AC_ind_dxpl_id)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "error checking attributes") + else if(tri_ret > 0) + HGOTO_ERROR(H5E_ATTR, H5E_ALREADYEXISTS, NULL, "attribute already exists") + + /* Check if the dataspace has an extent set (or is NULL) */ + if(!(H5S_has_extent(space))) + HGOTO_ERROR(H5E_ATTR, H5E_BADVALUE, NULL, "dataspace extent has not been set") + + /* Check if the datatype is "sensible" for use in a dataset */ + if(H5T_is_sensible(type) != TRUE) + HGOTO_ERROR(H5E_ATTR, H5E_BADTYPE, NULL, "datatype is not sensible") + + /* Build the attribute information */ + if(NULL == (attr = H5FL_CALLOC(H5A_t))) + HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, NULL, "memory allocation failed for attribute info") + + if(NULL == (attr->shared = H5FL_CALLOC(H5A_shared_t))) + HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, NULL, "can't allocate shared attr structure") + + /* If the creation property list is H5P_DEFAULT, use the default character encoding */ + if(acpl_id == H5P_DEFAULT) + attr->shared->encoding = H5F_DEFAULT_CSET; + else { + H5P_genplist_t *ac_plist; /* ACPL Property list */ + + /* Get a local copy of the attribute creation property list */ + if(NULL == (ac_plist = (H5P_genplist_t *)H5I_object(acpl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a property list") + + if(H5P_get(ac_plist, H5P_STRCRT_CHAR_ENCODING_NAME, &(attr->shared->encoding)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get character encoding flag") + } /* end else */ + + /* Copy the attribute name */ + attr->shared->name = H5MM_xstrdup(name); + + /* Copy datatype */ + if(NULL == (attr->shared->dt = H5T_copy(type, H5T_COPY_ALL))) + HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, NULL, "can't get shared datatype info") + + /* Mark datatype as being on disk now */ + if(H5T_set_loc(attr->shared->dt, loc->oloc->file, H5T_LOC_DISK) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "invalid datatype location") + + /* Set the latest format for datatype, if requested */ + if(H5F_USE_LATEST_FORMAT(loc->oloc->file)) + if(H5T_set_latest_version(attr->shared->dt) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set latest version of datatype") + + /* Copy the dataspace for the attribute */ + attr->shared->ds = H5S_copy(space, FALSE, TRUE); + + /* Set the latest format for dataspace, if requested */ + if(H5F_USE_LATEST_FORMAT(loc->oloc->file)) + if(H5S_set_latest_version(attr->shared->ds) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set latest version of dataspace") + + /* Copy the object header information */ + if(H5O_loc_copy(&(attr->oloc), loc->oloc, H5_COPY_DEEP) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to copy entry") + + /* Deep copy of the group hierarchy path */ + if(H5G_name_copy(&(attr->path), loc->path, H5_COPY_DEEP) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "unable to copy path") + + /* Check if any of the pieces should be (or are already) shared in the + * SOHM table + */ + if(H5SM_try_share(attr->oloc.file, dxpl_id, NULL, 0, H5O_DTYPE_ID, attr->shared->dt, NULL) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, NULL, "trying to share datatype failed") + if(H5SM_try_share(attr->oloc.file, dxpl_id, NULL, 0, H5O_SDSPACE_ID, attr->shared->ds, NULL) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, NULL, "trying to share dataspace failed") + + /* Check whether datatype is committed & increment ref count + * (to maintain ref. count incr/decr similarity with "shared message" + * type of datatype sharing) + */ + if(H5T_committed(attr->shared->dt)) { + /* Increment the reference count on the shared datatype */ + if(H5T_link(attr->shared->dt, 1, dxpl_id) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, NULL, "unable to adjust shared datatype link count") + } /* end if */ + + /* Compute the size of pieces on disk. This is either the size of the + * datatype and dataspace messages themselves, or the size of the "shared" + * messages if either or both of them are shared. + */ + attr->shared->dt_size = H5O_msg_raw_size(attr->oloc.file, H5O_DTYPE_ID, FALSE, attr->shared->dt); + attr->shared->ds_size = H5O_msg_raw_size(attr->oloc.file, H5O_SDSPACE_ID, FALSE, attr->shared->ds); + + /* Get # of elements for attribute's dataspace */ + if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->shared->ds)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, NULL, "dataspace is invalid") + H5_ASSIGN_OVERFLOW(nelmts, snelmts, hssize_t, size_t); + + HDassert(attr->shared->dt_size > 0); + HDassert(attr->shared->ds_size > 0); + attr->shared->data_size = nelmts * H5T_GET_SIZE(attr->shared->dt); + + /* Hold the symbol table entry (and file) open */ + if(H5O_open(&(attr->oloc)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to open") + attr->obj_opened = TRUE; + + /* Set the version to encode the attribute with */ + if(H5A_set_version(attr->oloc.file, attr) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "unable to update attribute version") + + /* Insert the attribute into the object header */ + if(H5O_attr_create(&(attr->oloc), dxpl_id, attr) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, NULL, "unable to create attribute in object header") + + ret_value = attr; +done: + if(NULL == ret_value && attr && H5A_close(attr)) + HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute") + FUNC_LEAVE_NOAPI_TAG(ret_value, NULL) +} /* H5A_create() */ + + +/*------------------------------------------------------------------------- + * Function: H5A_open_common + * + * Purpose: + * Finishes initializing an attributes the open + * + * Usage: + * herr_t H5A_open_common(loc, name, dxpl_id) + * const H5G_loc_t *loc; IN: Pointer to group location for object + * H5A_t *attr; IN/OUT: Pointer to attribute to initialize + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * December 18, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5A_open_common(const H5G_loc_t *loc, H5A_t *attr) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* check args */ + HDassert(loc); + HDassert(attr); + +#if defined(H5_USING_MEMCHECKER) || !defined(NDEBUG) + /* Clear object location */ + if(H5O_loc_reset(&(attr->oloc)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to reset location") +#endif /* H5_USING_MEMCHECKER */ + + /* Free any previous group hier. path */ + if(H5G_name_free(&(attr->path)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release group hier. path") + + /* Deep copy of the symbol table entry */ + if(H5O_loc_copy(&(attr->oloc), loc->oloc, H5_COPY_DEEP) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to copy entry") + + /* Deep copy of the group hier. path */ + if(H5G_name_copy(&(attr->path), loc->path, H5_COPY_DEEP) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "unable to copy entry") + + /* Hold the symbol table entry (and file) open */ + if(H5O_open(&(attr->oloc)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open") + attr->obj_opened = TRUE; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5A_open_common() */ + + +/*------------------------------------------------------------------------- + * Function: H5A_open_by_idx + * + * Purpose: Open an attribute according to its index order + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * April 2, 1998 + * + *------------------------------------------------------------------------- + */ +H5A_t * +H5A_open_by_idx(const H5G_loc_t *loc, const char *obj_name, H5_index_t idx_type, + H5_iter_order_t order, hsize_t n, hid_t lapl_id, hid_t dxpl_id) +{ + H5G_loc_t obj_loc; /* Location used to open group */ + H5G_name_t obj_path; /* Opened object group hier. path */ + H5O_loc_t obj_oloc; /* Opened object object location */ + hbool_t loc_found = FALSE; /* Entry at 'obj_name' found */ + H5A_t *attr = NULL; /* Attribute from object header */ + H5A_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* check args */ + HDassert(loc); + HDassert(obj_name); + + /* Set up opened group location to fill in */ + obj_loc.oloc = &obj_oloc; + obj_loc.path = &obj_path; + H5G_loc_reset(&obj_loc); + + /* Find the object's location */ + if(H5G_loc_find(loc, obj_name, &obj_loc/*out*/, lapl_id, dxpl_id) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "object not found") + loc_found = TRUE; + + /* Read in attribute from object header */ + if(NULL == (attr = H5O_attr_open_by_idx(obj_loc.oloc, idx_type, order, n, dxpl_id))) + HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to load attribute info from object header") + + /* Finish initializing attribute */ + if(H5A_open_common(&obj_loc, attr) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to initialize attribute") + + /* Set return value */ + ret_value = attr; + +done: + /* Release resources */ + if(loc_found && H5G_loc_free(&obj_loc) < 0) + HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, NULL, "can't free location") + + /* Cleanup on failure */ + if(ret_value == NULL) + if(attr && H5A_close(attr) < 0) + HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute") + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5A_open_by_idx() */ + + +/*------------------------------------------------------------------------- + * Function: H5A_open_by_name + * + * Purpose: Open an attribute in an object header, according to it's name + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * December 11, 2006 + * + *------------------------------------------------------------------------- + */ +H5A_t * +H5A_open_by_name(const H5G_loc_t *loc, const char *obj_name, const char *attr_name, + hid_t lapl_id, hid_t dxpl_id) +{ + H5G_loc_t obj_loc; /* Location used to open group */ + H5G_name_t obj_path; /* Opened object group hier. path */ + H5O_loc_t obj_oloc; /* Opened object object location */ + hbool_t loc_found = FALSE; /* Entry at 'obj_name' found */ + H5A_t *attr = NULL; /* Attribute from object header */ + H5A_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(NULL) + + /* check args */ + HDassert(loc); + HDassert(obj_name); + HDassert(attr_name); + + /* Set up opened group location to fill in */ + obj_loc.oloc = &obj_oloc; + obj_loc.path = &obj_path; + H5G_loc_reset(&obj_loc); + + /* Find the object's location */ + if(H5G_loc_find(loc, obj_name, &obj_loc/*out*/, lapl_id, dxpl_id) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "object not found") + loc_found = TRUE; + + /* Read in attribute from object header */ + if(NULL == (attr = H5O_attr_open_by_name(obj_loc.oloc, attr_name, dxpl_id))) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to load attribute info from object header") + + /* Finish initializing attribute */ + if(H5A_open_common(loc, attr) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to initialize attribute") + + /* Set return value */ + ret_value = attr; + +done: + /* Release resources */ + if(loc_found && H5G_loc_free(&obj_loc) < 0) + HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, NULL, "can't free location") + + /* Cleanup on failure */ + if(ret_value == NULL) + if(attr && H5A_close(attr) < 0) + HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute") + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5A_open_by_name() */ + + +/*-------------------------------------------------------------------------- + NAME + H5A_write + PURPOSE + Actually write out data to an attribute + USAGE + herr_t H5A_write (attr, mem_type, buf) + H5A_t *attr; IN: Attribute to write + const H5T_t *mem_type; IN: Memory datatype of buffer + const void *buf; IN: Buffer of data to write + RETURNS + Non-negative on success/Negative on failure + + DESCRIPTION + This function writes a complete attribute to disk. +--------------------------------------------------------------------------*/ +herr_t +H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf, hid_t dxpl_id) +{ + uint8_t *tconv_buf = NULL; /* datatype conv buffer */ + hbool_t tconv_owned = FALSE; /* Whether the datatype conv buffer is owned by attribute */ + uint8_t *bkg_buf = NULL; /* temp conversion buffer */ + hssize_t snelmts; /* elements in attribute */ + size_t nelmts; /* elements in attribute */ + H5T_path_t *tpath = NULL; /* conversion information*/ + hid_t src_id = -1, dst_id = -1;/* temporary type atoms */ + 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; + + FUNC_ENTER_NOAPI_NOINIT_TAG(dxpl_id, attr->oloc.addr, FAIL) + + HDassert(attr); + HDassert(mem_type); + HDassert(buf); + + /* Get # of elements for attribute's dataspace */ + if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->shared->ds)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, FAIL, "dataspace is invalid") + H5_ASSIGN_OVERFLOW(nelmts, snelmts, hssize_t, size_t); + + /* If there's actually data elements for the attribute, make a copy of the data passed in */ + if(nelmts > 0) { + /* Get the memory and file datatype sizes */ + src_type_size = H5T_GET_SIZE(mem_type); + dst_type_size = H5T_GET_SIZE(attr->shared->dt); + + /* Convert memory buffer into disk buffer */ + /* Set up type conversion function */ + if(NULL == (tpath = H5T_path_find(mem_type, attr->shared->dt, NULL, NULL, dxpl_id, FALSE))) + HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dst datatypes") + + /* Check for type conversion required */ + if(!H5T_path_noop(tpath)) { + if((src_id = H5I_register(H5I_DATATYPE, H5T_copy(mem_type, H5T_COPY_ALL), FALSE)) < 0 || + (dst_id = H5I_register(H5I_DATATYPE, H5T_copy(attr->shared->dt, H5T_COPY_ALL), FALSE)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, FAIL, "unable to register types for conversion") + + /* Get the maximum buffer size needed and allocate it */ + buf_size = nelmts * MAX(src_type_size, dst_type_size); + if(NULL == (tconv_buf = H5FL_BLK_MALLOC(attr_buf, buf_size))) + HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, "memory allocation failed") + if(NULL == (bkg_buf = H5FL_BLK_CALLOC(attr_buf, buf_size))) + HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, "memory allocation failed") + + /* Copy the user's data into the buffer for conversion */ + HDmemcpy(tconv_buf, buf, (src_type_size * nelmts)); + + /* Perform datatype conversion */ + if(H5T_convert(tpath, src_id, dst_id, nelmts, (size_t)0, (size_t)0, tconv_buf, bkg_buf, dxpl_id) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "datatype conversion failed") + + /* Free the previous attribute data buffer, if there is one */ + if(attr->shared->data) + attr->shared->data = H5FL_BLK_FREE(attr_buf, attr->shared->data); + + /* Set the pointer to the attribute data to the converted information */ + attr->shared->data = tconv_buf; + tconv_owned = TRUE; + } /* end if */ + /* No type conversion necessary */ + else { + HDassert(dst_type_size == src_type_size); + + /* Allocate the attribute buffer, if there isn't one */ + if(attr->shared->data == NULL) + if(NULL == (attr->shared->data = H5FL_BLK_MALLOC(attr_buf, dst_type_size * nelmts))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Copy the attribute data into the user's buffer */ + HDmemcpy(attr->shared->data, buf, (dst_type_size * nelmts)); + } /* end else */ + + /* Modify the attribute in the object header */ + if(H5O_attr_write(&(attr->oloc), dxpl_id, attr) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to modify attribute") + } /* end if */ + +done: + /* Release resources */ + if(src_id >= 0 && H5I_dec_ref(src_id) < 0) + HDONE_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to close temporary object") + if(dst_id >= 0 && H5I_dec_ref(dst_id) < 0) + HDONE_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to close temporary object") + if(tconv_buf && !tconv_owned) + tconv_buf = H5FL_BLK_FREE(attr_buf, tconv_buf); + if(bkg_buf) + bkg_buf = H5FL_BLK_FREE(attr_buf, bkg_buf); + + FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL) +} /* H5A_write() */ + + +/*-------------------------------------------------------------------------- + NAME + H5A_read + PURPOSE + Actually read in data from an attribute + USAGE + herr_t H5A_read (attr, mem_type, buf) + H5A_t *attr; IN: Attribute to read + const H5T_t *mem_type; IN: Memory datatype of buffer + void *buf; IN: Buffer for data to read + RETURNS + Non-negative on success/Negative on failure + + DESCRIPTION + This function reads a complete attribute from disk. +--------------------------------------------------------------------------*/ +herr_t +H5A_read(const H5A_t *attr, const H5T_t *mem_type, void *buf, hid_t dxpl_id) +{ + uint8_t *tconv_buf = NULL; /* datatype conv buffer*/ + uint8_t *bkg_buf = NULL; /* background buffer */ + hssize_t snelmts; /* elements in attribute */ + size_t nelmts; /* elements in attribute*/ + H5T_path_t *tpath = NULL; /* type conversion info */ + hid_t src_id = -1, dst_id = -1;/* temporary type atoms*/ + 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; + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(attr); + HDassert(mem_type); + HDassert(buf); + + /* Create buffer for data to store on disk */ + if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->shared->ds)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, FAIL, "dataspace is invalid") + H5_ASSIGN_OVERFLOW(nelmts, snelmts, hssize_t, size_t); + + if(nelmts > 0) { + /* Get the memory and file datatype sizes */ + src_type_size = H5T_GET_SIZE(attr->shared->dt); + dst_type_size = H5T_GET_SIZE(mem_type); + + /* Check if the attribute has any data yet, if not, fill with zeroes */ + if(attr->obj_opened && !attr->shared->data) + HDmemset(buf, 0, (dst_type_size * nelmts)); + else { /* Attribute exists and has a value */ + /* Convert memory buffer into disk buffer */ + /* Set up type conversion function */ + if(NULL == (tpath = H5T_path_find(attr->shared->dt, mem_type, NULL, NULL, dxpl_id, FALSE))) + HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dst datatypes") + + /* Check for type conversion required */ + if(!H5T_path_noop(tpath)) { + if((src_id = H5I_register(H5I_DATATYPE, H5T_copy(attr->shared->dt, H5T_COPY_ALL), FALSE)) < 0 || + (dst_id = H5I_register(H5I_DATATYPE, H5T_copy(mem_type, H5T_COPY_ALL), FALSE)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, FAIL, "unable to register types for conversion") + + /* Get the maximum buffer size needed and allocate it */ + buf_size = nelmts * MAX(src_type_size, dst_type_size); + if(NULL == (tconv_buf = H5FL_BLK_MALLOC(attr_buf, buf_size))) + HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "memory allocation failed") + if(NULL == (bkg_buf = H5FL_BLK_CALLOC(attr_buf, buf_size))) + HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Copy the attribute data into the buffer for conversion */ + HDmemcpy(tconv_buf, attr->shared->data, (src_type_size * nelmts)); + + /* Perform datatype conversion. */ + if(H5T_convert(tpath, src_id, dst_id, nelmts, (size_t)0, (size_t)0, tconv_buf, bkg_buf, dxpl_id) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "datatype conversion failed") + + /* Copy the converted data into the user's buffer */ + HDmemcpy(buf, tconv_buf, (dst_type_size * nelmts)); + } /* end if */ + /* No type conversion necessary */ + else { + HDassert(dst_type_size == src_type_size); + + /* Copy the attribute data into the user's buffer */ + HDmemcpy(buf, attr->shared->data, (dst_type_size * nelmts)); + } /* end else */ + } /* end else */ + } /* end if */ + +done: + /* Release resources */ + if(src_id >= 0 && H5I_dec_ref(src_id) < 0) + HDONE_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to close temporary object") + if(dst_id >= 0 && H5I_dec_ref(dst_id) < 0) + HDONE_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to close temporary object") + if(tconv_buf) + tconv_buf = H5FL_BLK_FREE(attr_buf, tconv_buf); + if(bkg_buf) + bkg_buf = H5FL_BLK_FREE(attr_buf, bkg_buf); + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5A_read() */ + + +/*------------------------------------------------------------------------- + * Function: H5A_get_space + * + * Purpose: Returns and ID for the dataspace of the attribute. + * + * Return: Success: ID for dataspace + * + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * March, 2012 + * + *------------------------------------------------------------------------- + */ +hid_t +H5A_get_space(H5A_t *attr) +{ + H5S_t *ds = NULL; + hid_t ret_value = FAIL; + + FUNC_ENTER_NOAPI_NOINIT + + /* Copy the attribute's dataspace */ + if(NULL == (ds = H5S_copy(attr->shared->ds, FALSE, TRUE))) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to copy dataspace") + + /* Atomize */ + if((ret_value = H5I_register(H5I_DATASPACE, ds, TRUE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace atom") + +done: + if(ret_value < 0 && ds) { + if(H5S_close(ds) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataspace") + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5A_get_space() */ + + +/*------------------------------------------------------------------------- + * Function: H5A_get_type + * + * Purpose: Returns and ID for the datatype of the dataset. + * + * Return: Success: ID for datatype + * + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * March, 2012 + * + *------------------------------------------------------------------------- + */ +hid_t +H5A_get_type(H5A_t *attr) +{ + H5T_t *dt = NULL; + hid_t ret_value = FAIL; + + FUNC_ENTER_NOAPI_NOINIT + + /* Patch the datatype's "top level" file pointer */ + if(H5T_patch_file(attr->shared->dt, attr->oloc.file) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to patch datatype's file pointer") + + /* + * Copy the attribute's datatype. If the type is a named type then + * reopen the type before returning it to the user. Make the type + * read-only. + */ + if(NULL == (dt = H5T_copy(attr->shared->dt, H5T_COPY_REOPEN))) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to copy datatype") + + /* Mark any datatypes as being in memory now */ + if(H5T_set_loc(dt, NULL, H5T_LOC_MEMORY) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location") + + /* Lock copied type */ + if(H5T_lock(dt, FALSE) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to lock transient datatype") + + /* Create an atom */ + if((ret_value = H5I_register(H5I_DATATYPE, dt, TRUE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register datatype") + +done: + if(ret_value < 0) { + if(dt && H5T_close(dt) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release datatype") + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5A_get_type() */ + + +/*-------------------------------------------------------------------------- + NAME + H5A_get_create_plist + PURPOSE + private version of H5Aget_create_plist + RETURNS + This function returns the ID of a copy of the attribute's creation + property list, or negative on failure. + + ERRORS + + DESCRIPTION + This function returns a copy of the creation property list for + an attribute. The resulting ID must be closed with H5Pclose() or + resource leaks will occur. +--------------------------------------------------------------------------*/ +hid_t +H5A_get_create_plist(H5A_t* attr) +{ + H5P_genplist_t *plist; /* Default property list */ + hid_t new_plist_id; /* ID of ACPL to return */ + H5P_genplist_t *new_plist; /* ACPL to return */ + hid_t ret_value; + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (plist = (H5P_genplist_t *)H5I_object(H5P_LST_ATTRIBUTE_CREATE_ID_g))) + HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "can't get default ACPL") + + /* Create the property list object to return */ + if((new_plist_id = H5P_copy_plist(plist, TRUE)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "unable to copy attribute creation properties") + if(NULL == (new_plist = (H5P_genplist_t *)H5I_object(new_plist_id))) + HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "can't get property list") + + /* Set the character encoding on the new property list */ + if(H5P_set(new_plist, H5P_STRCRT_CHAR_ENCODING_NAME, &(attr->shared->encoding)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set character encoding") + + ret_value = new_plist_id; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5Aget_create_plist() */ + + +/*-------------------------------------------------------------------------- + NAME + H5A_get_name + PURPOSE + Private function for H5Aget_name. Gets a copy of the name for an + attribute + RETURNS + This function returns the length of the attribute's name (which may be + longer than 'buf_size') on success or negative for failure. + DESCRIPTION + This function retrieves the name of an attribute for an attribute ID. + Up to 'buf_size' characters are stored in 'buf' followed by a '\0' string + terminator. If the name of the attribute is longer than 'buf_size'-1, + the string terminator is stored in the last position of the buffer to + properly terminate the string. +--------------------------------------------------------------------------*/ +ssize_t +H5A_get_name(H5A_t *attr, size_t buf_size, char *buf) +{ + size_t copy_len, nbytes; + ssize_t ret_value; + + FUNC_ENTER_NOAPI_NOERR + + /* get the real attribute length */ + nbytes = HDstrlen(attr->shared->name); + HDassert((ssize_t)nbytes >= 0); /*overflow, pretty unlikely --rpm*/ + + /* compute the string length which will fit into the user's buffer */ + copy_len = MIN(buf_size - 1, nbytes); + + /* Copy all/some of the name */ + if(buf && copy_len > 0) { + HDmemcpy(buf, attr->shared->name, copy_len); + + /* Terminate the string */ + buf[copy_len]='\0'; + } /* end if */ + + /* Set return value */ + ret_value = (ssize_t)nbytes; + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5A_get_name() */ + + +/*------------------------------------------------------------------------- + * Function: H5A_get_info + * + * Purpose: Retrieve information about an attribute. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * February 6, 2007 + * + *------------------------------------------------------------------------- + */ +herr_t +H5A_get_info(const H5A_t *attr, H5A_info_t *ainfo) +{ + FUNC_ENTER_NOAPI_NOERR + + /* Check args */ + HDassert(attr); + HDassert(ainfo); + + /* Set info for attribute */ + ainfo->cset = attr->shared->encoding; + ainfo->data_size = attr->shared->data_size; + if(attr->shared->crt_idx == H5O_MAX_CRT_ORDER_IDX) { + ainfo->corder_valid = FALSE; + ainfo->corder = 0; + } /* end if */ + else { + ainfo->corder_valid = TRUE; + ainfo->corder = attr->shared->crt_idx; + } /* end else */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5A_get_info() */ + + +/*------------------------------------------------------------------------- + * Function: H5A_copy + * + * Purpose: Copies attribute OLD_ATTR. + * + * Return: Success: Pointer to a new copy of the OLD_ATTR argument. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * Thursday, December 4, 1997 + * + * Modification:Raymond Lu + * 4 June 2008 + * Changed some attribute information to be shared. + * + *------------------------------------------------------------------------- + */ +H5A_t * +H5A_copy(H5A_t *_new_attr, const H5A_t *old_attr) +{ + H5A_t *new_attr = NULL; + hbool_t allocated_attr = FALSE; /* Whether the attribute was allocated */ + H5A_t *ret_value = NULL; /* Return value */ + + FUNC_ENTER_NOAPI(NULL) + + /* check args */ + HDassert(old_attr); + + /* Allocate attribute structure */ + if(_new_attr == NULL) { + if(NULL == (new_attr = H5FL_CALLOC(H5A_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + allocated_attr = TRUE; + } /* end if */ + else + new_attr = _new_attr; + + /* Copy the top level of the attribute */ + new_attr->sh_loc = old_attr->sh_loc; + + /* Deep copy of the group hierarchy path */ + if(H5G_name_copy(&(new_attr->path), &(old_attr->path), H5_COPY_DEEP) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "unable to copy path") + + /* Share some attribute information */ + new_attr->shared = old_attr->shared; + + /* Increment reference count for shared object */ + new_attr->shared->nrefs++; + + /* Don't open the object header for a copy */ + new_attr->obj_opened = FALSE; + + /* Set the return value */ + ret_value = new_attr; + +done: + if(ret_value == NULL) + if(allocated_attr && new_attr && H5A_close(new_attr) < 0) + HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5A_copy() */ + + +/*------------------------------------------------------------------------- + * Function: H5A_free + * + * Purpose: Frees all memory associated with an attribute, but does not + * free the H5A_t structure (which should be done in H5T_close). + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Monday, November 15, 2004 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5A_free(H5A_t *attr) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + HDassert(attr); + + /* Free dynamicly allocated items */ + if(attr->shared->name) { + H5MM_xfree(attr->shared->name); + attr->shared->name = NULL; + } + if(attr->shared->dt) { + if(H5T_close(attr->shared->dt) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release datatype info") + attr->shared->dt = NULL; + } + if(attr->shared->ds) { + if(H5S_close(attr->shared->ds) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release dataspace info") + attr->shared->ds = NULL; + } + if(attr->shared->data) + attr->shared->data = H5FL_BLK_FREE(attr_buf, attr->shared->data); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5A_free() */ + + +/*------------------------------------------------------------------------- + * Function: H5A_close + * + * Purpose: Frees an attribute and all associated memory. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Monday, December 8, 1997 + * + * Modifications: + * Raymond Lu + * 4 June 2008 + * Changed some attribute object information to be shared. + *------------------------------------------------------------------------- + */ +herr_t +H5A_close(H5A_t *attr) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + HDassert(attr); + HDassert(attr->shared); + + /* Close the object's symbol-table entry */ + if(attr->obj_opened && (H5O_close(&(attr->oloc)) < 0)) + HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release object header info") + + /* Reference count can be 0. It only happens when H5A_create fails. */ + if(attr->shared->nrefs <= 1) { + /* Free dynamicly allocated items */ + if(H5A_free(attr) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release attribute info") + + /* Destroy shared attribute struct */ + attr->shared = H5FL_FREE(H5A_shared_t, attr->shared); + } /* end if */ + else { + /* There are other references to the shared part of the attribute. + * Only decrement the reference count. */ + --attr->shared->nrefs; + } /* end else */ + + /* Free group hierarchy path */ + if(H5G_name_free(&(attr->path)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release group hier. path") + + attr->shared = NULL; + attr = H5FL_FREE(H5A_t, attr); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5A_close() */ + + +/*------------------------------------------------------------------------- + * Function: H5A_oloc + * + * Purpose: Return the object location for an attribute. It's the + * object location for the object to which the attribute + * belongs, not the attribute itself. + * + * Return: Success: Ptr to entry + * Failure: NULL + * + * Programmer: Robb Matzke + * Thursday, August 6, 1998 + * + *------------------------------------------------------------------------- + */ +H5O_loc_t * +H5A_oloc(H5A_t *attr) +{ + H5O_loc_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOERR + + HDassert(attr); + + /* Set return value */ + ret_value = &(attr->oloc); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5A_oloc() */ + + +/*------------------------------------------------------------------------- + * Function: H5A_nameof + * + * Purpose: Return the group hier. path for an attribute. It's the + * group hier. path for the object to which the attribute + * belongs, not the attribute itself. + * + * Return: Success: Ptr to entry + * Failure: NULL + * + * Programmer: Quincey Koziol + * Monday, September 12, 2005 + * + *------------------------------------------------------------------------- + */ +H5G_name_t * +H5A_nameof(H5A_t *attr) +{ + H5G_name_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOERR + + HDassert(attr); + + /* Set return value */ + ret_value=&(attr->path); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5A_nameof() */ + + +/*------------------------------------------------------------------------- + * Function: H5A_type + * + * Purpose: Return the datatype for an attribute. + * + * Return: Success: Ptr to entry + * Failure: NULL + * + * Programmer: Neil Fortner + * Friday, November 11, 2011 + * + *------------------------------------------------------------------------- + */ +H5T_t * +H5A_type(const H5A_t *attr) +{ + H5T_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOERR + + HDassert(attr); + + /* Set return value */ + ret_value = attr->shared->dt; + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5A_type() */ + + +/*------------------------------------------------------------------------- + * Function: H5A_exists_by_name + * + * Purpose: Private version of H5Aexists_by_name + * + * Return: Success: TRUE/FALSE + * Failure: Negative + * + * Programmer: Quincey Koziol + * Thursday, November 1, 2007 + * + *------------------------------------------------------------------------- + */ +htri_t +H5A_exists_by_name(H5G_loc_t loc, const char *obj_name, const char *attr_name, + hid_t lapl_id) +{ + H5G_loc_t obj_loc; /* Location used to open group */ + H5G_name_t obj_path; /* Opened object group hier. path */ + H5O_loc_t obj_oloc; /* Opened object object location */ + hbool_t loc_found = FALSE; /* Entry at 'obj_name' found */ + htri_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Set up opened group location to fill in */ + obj_loc.oloc = &obj_oloc; + obj_loc.path = &obj_path; + H5G_loc_reset(&obj_loc); + + /* Find the object's location */ + if(H5G_loc_find(&loc, obj_name, &obj_loc/*out*/, lapl_id, H5AC_ind_dxpl_id) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "object not found") + loc_found = TRUE; + + /* Check if the attribute exists */ + if((ret_value = H5O_attr_exists(obj_loc.oloc, attr_name, H5AC_ind_dxpl_id)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "unable to determine if attribute exists") + +done: + /* Release resources */ + if(loc_found && H5G_loc_free(&obj_loc) < 0) + HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't free location") + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5A_exists_by_name() */ + + +/*------------------------------------------------------------------------- * Function: H5A__compact_build_table_cb * * Purpose: Object header iterator callback routine to copy attribute @@ -1259,3 +2361,53 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5A_dense_post_copy_file_all */ + +/*------------------------------------------------------------------------- + * Function: H5A_rename_by_name + * + * Purpose: Private version of H5Arename_by_name + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * February 20, 2007 + * + *------------------------------------------------------------------------- + */ +herr_t +H5A_rename_by_name(H5G_loc_t loc, const char *obj_name, const char *old_attr_name, + const char *new_attr_name, hid_t lapl_id) +{ + H5G_loc_t obj_loc; /* Location used to open group */ + H5G_name_t obj_path; /* Opened object group hier. path */ + H5O_loc_t obj_oloc; /* Opened object object location */ + hbool_t loc_found = FALSE; /* Entry at 'obj_name' found */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Avoid thrashing things if the names are the same */ + if(HDstrcmp(old_attr_name, new_attr_name)) { + /* Set up opened group location to fill in */ + obj_loc.oloc = &obj_oloc; + obj_loc.path = &obj_path; + H5G_loc_reset(&obj_loc); + + /* Find the object's location */ + if(H5G_loc_find(&loc, obj_name, &obj_loc/*out*/, lapl_id, H5AC_ind_dxpl_id) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "object not found") + loc_found = TRUE; + + /* Call attribute rename routine */ + if(H5O_attr_rename(obj_loc.oloc, H5AC_dxpl_id, old_attr_name, new_attr_name) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTRENAME, FAIL, "can't rename attribute") + } /* end if */ + +done: + /* Release resources */ + if(loc_found && H5G_loc_free(&obj_loc) < 0) + HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't free location") + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5A_rename_by_name() */ diff --git a/src/H5Apkg.h b/src/H5Apkg.h index fa26a9a..efa2b74 100644 --- a/src/H5Apkg.h +++ b/src/H5Apkg.h @@ -186,19 +186,29 @@ H5_DLLVAR const H5B2_class_t H5A_BT2_CORDER[1]; /* Function prototypes for H5A package scope */ H5_DLL herr_t H5A_init(void); H5_DLL herr_t H5A__term_deprec_interface(void); -H5_DLL hid_t H5A_create(const H5G_loc_t *loc, const char *name, +H5_DLL H5A_t *H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type, const H5S_t *space, hid_t acpl_id, hid_t dxpl_id); -H5_DLL H5A_t * H5A_open_by_name(const H5G_loc_t *loc, const char *obj_name, +H5_DLL H5A_t *H5A_open_by_name(const H5G_loc_t *loc, const char *obj_name, const char *attr_name, hid_t lapl_id, hid_t dxpl_id); H5_DLL H5A_t *H5A_open_by_idx(const H5G_loc_t *loc, const char *obj_name, H5_index_t idx_type, H5_iter_order_t order, hsize_t n, hid_t lapl_id, hid_t dxpl_id); +H5_DLL herr_t H5A_open_common(const H5G_loc_t *loc, H5A_t *attr); +H5_DLL herr_t H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf, hid_t dxpl_id); +H5_DLL herr_t H5A_read(const H5A_t *attr, const H5T_t *mem_type, void *buf, hid_t dxpl_id); H5_DLL ssize_t H5A_get_name(H5A_t *attr, size_t buf_size, char *buf); H5_DLL H5A_t *H5A_copy(H5A_t *new_attr, const H5A_t *old_attr); H5_DLL herr_t H5A_get_info(const H5A_t *attr, H5A_info_t *ainfo); +H5_DLL hid_t H5A_get_type(H5A_t *attr); +H5_DLL hid_t H5A_get_space(H5A_t *attr); +H5_DLL hid_t H5A_get_create_plist(H5A_t* attr); H5_DLL herr_t H5A_free(H5A_t *attr); H5_DLL herr_t H5A_close(H5A_t *attr); H5_DLL htri_t H5A_get_ainfo(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5O_ainfo_t *ainfo); H5_DLL herr_t H5A_set_version(const H5F_t *f, H5A_t *attr); +H5_DLL herr_t H5A_rename_by_name(H5G_loc_t loc, const char *obj_name, const char *old_attr_name, + const char *new_attr_name, hid_t lapl_id); +H5_DLL htri_t H5A_exists_by_name(H5G_loc_t loc, const char *obj_name, const char *attr_name, + hid_t lapl_id); /* Attribute "dense" storage routines */ H5_DLL herr_t H5A_dense_create(H5F_t *f, hid_t dxpl_id, H5O_ainfo_t *ainfo); diff --git a/src/H5D.c b/src/H5D.c index 11d8d40..a81fb8b 100644 --- a/src/H5D.c +++ b/src/H5D.c @@ -450,7 +450,6 @@ hid_t H5Dget_space(hid_t dset_id) { H5D_t *dset = NULL; - H5S_t *space = NULL; hid_t ret_value; FUNC_ENTER_API(FAIL) @@ -460,22 +459,10 @@ H5Dget_space(hid_t dset_id) if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") - /* Read the dataspace message and return a dataspace object */ - if(NULL == (space = H5S_copy(dset->shared->space, FALSE, TRUE))) + if((ret_value = H5D_get_space(dset)) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to get dataspace") - /* Create an atom */ - if((ret_value = H5I_register (H5I_DATASPACE, space, TRUE)) < 0) - HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace") - done: - if(ret_value < 0) { - if(space!=NULL) { - if(H5S_close(space) < 0) - HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataspace") - } /* end if */ - } /* end if */ - FUNC_LEAVE_API(ret_value) } @@ -504,7 +491,7 @@ H5Dget_space_status(hid_t dset_id, H5D_space_status_t *allocation) H5TRACE2("e", "i*Ds", dset_id, allocation); /* Check arguments */ - if(NULL==(dset=(H5D_t *)H5I_object_verify(dset_id, H5I_DATASET))) + if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") /* Read dataspace address and return */ @@ -537,7 +524,6 @@ H5Dget_type(hid_t dset_id) { H5D_t *dset; /* Dataset */ - H5T_t *dt = NULL; /* Datatype to return */ hid_t ret_value; /* Return value */ FUNC_ENTER_API(FAIL) @@ -547,32 +533,10 @@ H5Dget_type(hid_t dset_id) if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") - /* Patch the datatype's "top level" file pointer */ - if(H5T_patch_file(dset->shared->type, dset->oloc.file) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to patch datatype's file pointer") - - /* Copy the dataset's datatype */ - if(NULL == (dt = H5T_copy(dset->shared->type, H5T_COPY_REOPEN))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to copy datatype") - - /* Mark any datatypes as being in memory now */ - if(H5T_set_loc(dt, NULL, H5T_LOC_MEMORY) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location") - - /* Lock copied type */ - if(H5T_lock(dt, FALSE) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to lock transient datatype") - - /* Create an atom */ - if((ret_value = H5I_register(H5I_DATATYPE, dt, TRUE)) < 0) - HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register datatype") + if((ret_value = H5D_get_type(dset)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to get dataspace") done: - if(ret_value < 0) { - if(dt && H5T_close(dt) < 0) - HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release datatype") - } /* end if */ - FUNC_LEAVE_API(ret_value) } /* end H5Dget_type() */ @@ -607,7 +571,7 @@ H5Dget_create_plist(hid_t dset_id) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") if((ret_value = H5D_get_create_plist(dataset)) < 0) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "Can't get creation plist") done: FUNC_LEAVE_API(ret_value) @@ -615,123 +579,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5D_get_create_plist - * - * Purpose: Private function for H5Dget_create_plist - * - * Return: Success: ID for a copy of the dataset creation - * property list. The template should be - * released by calling H5P_close(). - * - * Failure: FAIL - * - * Programmer: Robb Matzke - * Tuesday, February 3, 1998 - * - *------------------------------------------------------------------------- - */ -hid_t -H5D_get_create_plist(H5D_t *dset) -{ - H5P_genplist_t *dcpl_plist; /* Dataset's DCPL */ - H5P_genplist_t *new_plist; /* Copy of dataset's DCPL */ - H5O_fill_t copied_fill; /* Fill value to tweak */ - hid_t new_dcpl_id = FAIL; - hid_t ret_value; /* Return value */ - - FUNC_ENTER_NOAPI(FAIL) - - /* Check args */ - if(NULL == (dcpl_plist = (H5P_genplist_t *)H5I_object(dset->shared->dcpl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list") - - /* Copy the creation property list */ - if((new_dcpl_id = H5P_copy_plist(dcpl_plist, TRUE)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to copy the creation property list") - if(NULL == (new_plist = (H5P_genplist_t *)H5I_object(new_dcpl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list") - - /* Retrieve any object creation properties */ - if(H5O_get_create_plist(&dset->oloc, H5AC_ind_dxpl_id, new_plist) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get object creation info") - - /* Get the fill value property */ - if(H5P_get(new_plist, H5D_CRT_FILL_VALUE_NAME, &copied_fill) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get fill value") - - /* Check if there is a fill value, but no type yet */ - if(copied_fill.buf != NULL && copied_fill.type == NULL) { - H5T_path_t *tpath; /* Conversion information*/ - - /* Copy the dataset type into the fill value message */ - if(NULL == (copied_fill.type = H5T_copy(dset->shared->type, H5T_COPY_TRANSIENT))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to copy dataset datatype for fill value") - - /* Set up type conversion function */ - if(NULL == (tpath = H5T_path_find(dset->shared->type, copied_fill.type, NULL, NULL, H5AC_ind_dxpl_id, FALSE))) - HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest data types") - - /* Convert disk form of fill value into memory form */ - if(!H5T_path_noop(tpath)) { - hid_t dst_id, src_id; /* Source & destination datatypes for type conversion */ - uint8_t *bkg_buf = NULL; /* Background conversion buffer */ - size_t bkg_size; /* Size of background buffer */ - - /* Wrap copies of types to convert */ - dst_id = H5I_register(H5I_DATATYPE, H5T_copy(copied_fill.type, H5T_COPY_TRANSIENT), FALSE); - if(dst_id < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy/register datatype") - src_id = H5I_register(H5I_DATATYPE, H5T_copy(dset->shared->type, H5T_COPY_ALL), FALSE); - if(src_id < 0) { - H5I_dec_ref(dst_id); - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy/register datatype") - } /* end if */ - - /* Allocate a background buffer */ - bkg_size = MAX(H5T_GET_SIZE(copied_fill.type), H5T_GET_SIZE(dset->shared->type)); - if(H5T_path_bkg(tpath) && NULL == (bkg_buf = H5FL_BLK_CALLOC(type_conv, bkg_size))) { - H5I_dec_ref(src_id); - H5I_dec_ref(dst_id); - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") - } /* end if */ - - /* Convert fill value */ - if(H5T_convert(tpath, src_id, dst_id, (size_t)1, (size_t)0, (size_t)0, copied_fill.buf, bkg_buf, H5AC_ind_dxpl_id) < 0) { - H5I_dec_ref(src_id); - H5I_dec_ref(dst_id); - if(bkg_buf) - bkg_buf = H5FL_BLK_FREE(type_conv, bkg_buf); - HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "datatype conversion failed") - } /* end if */ - - /* Release local resources */ - if(H5I_dec_ref(src_id) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "unable to close temporary object") - if(H5I_dec_ref(dst_id) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "unable to close temporary object") - if(bkg_buf) - bkg_buf = H5FL_BLK_FREE(type_conv, bkg_buf); - } /* end if */ - } /* end if */ - - /* Set back the fill value property to property list */ - if(H5P_set(new_plist, H5D_CRT_FILL_VALUE_NAME, &copied_fill) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to set property list fill value") - - /* Set the return value */ - ret_value = new_dcpl_id; - -done: - if(ret_value < 0) - if(new_dcpl_id > 0) - if(H5I_dec_app_ref(new_dcpl_id) < 0) - HDONE_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "unable to close temporary object") - - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5D_get_create_plist() */ - - -/*------------------------------------------------------------------------- * Function: H5Dget_access_plist * * Purpose: Returns a copy of the dataset creation property list. @@ -768,9 +615,6 @@ hid_t H5Dget_access_plist(hid_t dset_id) { H5D_t *dset; /* Dataset structure */ - H5P_genplist_t *old_plist; /* Default DAPL */ - H5P_genplist_t *new_plist; /* New DAPL */ - hid_t new_dapl_id = FAIL; hid_t ret_value; /* Return value */ FUNC_ENTER_API(FAIL) @@ -780,33 +624,10 @@ H5Dget_access_plist(hid_t dset_id) if (NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") - /* Make a copy of the default dataset access property list */ - if (NULL == (old_plist = (H5P_genplist_t *)H5I_object(H5P_LST_DATASET_ACCESS_ID_g))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list") - if ((new_dapl_id = H5P_copy_plist(old_plist, TRUE)) < 0) - HGOTO_ERROR(H5E_INTERNAL, H5E_CANTINIT, FAIL, "can't copy dataset access property list") - if (NULL == (new_plist = (H5P_genplist_t *)H5I_object(new_dapl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list") - - /* If the dataset is chunked then copy the rdcc parameters */ - if (dset->shared->layout.type == H5D_CHUNKED) { - if (H5P_set(new_plist, H5D_ACS_DATA_CACHE_NUM_SLOTS_NAME, &(dset->shared->cache.chunk.nslots)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set data cache number of slots") - if (H5P_set(new_plist, H5D_ACS_DATA_CACHE_BYTE_SIZE_NAME, &(dset->shared->cache.chunk.nbytes_max)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set data cache byte size") - if (H5P_set(new_plist, H5D_ACS_PREEMPT_READ_CHUNKS_NAME, &(dset->shared->cache.chunk.w0)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set preempt read chunks") - } /* end if */ - - /* Set the return value */ - ret_value = new_dapl_id; + if((ret_value = H5D_get_access_plist(dset)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "Can't get access plist") done: - if(ret_value < 0) - if(new_dapl_id >= 0) - if(H5I_dec_app_ref(new_dapl_id) < 0) - HDONE_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "unable to close temporary object") - FUNC_LEAVE_API(ret_value) } /* end H5Dget_access_plist() */ diff --git a/src/H5Dint.c b/src/H5Dint.c index 88367d6..6c61d28 100644 --- a/src/H5Dint.c +++ b/src/H5Dint.c @@ -103,6 +103,9 @@ H5FL_BLK_EXTERN(sieve_buf); /* Declare the external free list to manage the H5D_chunk_info_t struct */ H5FL_EXTERN(H5D_chunk_info_t); +/* Declare extern the free list to manage blocks of type conversion data */ +H5FL_BLK_EXTERN(type_conv); + /* Define a static "default" dataset structure to use to initialize new datasets */ static H5D_shared_t H5D_def_dset; @@ -2456,3 +2459,269 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5D_flush() */ + +/*------------------------------------------------------------------------- + * Function: H5D_get_create_plist + * + * Purpose: Private function for H5Dget_create_plist + * + * Return: Success: ID for a copy of the dataset creation + * property list. The template should be + * released by calling H5P_close(). + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Tuesday, February 3, 1998 + * + *------------------------------------------------------------------------- + */ +hid_t +H5D_get_create_plist(H5D_t *dset) +{ + H5P_genplist_t *dcpl_plist; /* Dataset's DCPL */ + H5P_genplist_t *new_plist; /* Copy of dataset's DCPL */ + H5O_fill_t copied_fill; /* Fill value to tweak */ + hid_t new_dcpl_id = FAIL; + hid_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Check args */ + if(NULL == (dcpl_plist = (H5P_genplist_t *)H5I_object(dset->shared->dcpl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list") + + /* Copy the creation property list */ + if((new_dcpl_id = H5P_copy_plist(dcpl_plist, TRUE)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to copy the creation property list") + if(NULL == (new_plist = (H5P_genplist_t *)H5I_object(new_dcpl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list") + + /* Retrieve any object creation properties */ + if(H5O_get_create_plist(&dset->oloc, H5AC_ind_dxpl_id, new_plist) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get object creation info") + + /* Get the fill value property */ + if(H5P_get(new_plist, H5D_CRT_FILL_VALUE_NAME, &copied_fill) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get fill value") + + /* Check if there is a fill value, but no type yet */ + if(copied_fill.buf != NULL && copied_fill.type == NULL) { + H5T_path_t *tpath; /* Conversion information*/ + + /* Copy the dataset type into the fill value message */ + if(NULL == (copied_fill.type = H5T_copy(dset->shared->type, H5T_COPY_TRANSIENT))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to copy dataset datatype for fill value") + + /* Set up type conversion function */ + if(NULL == (tpath = H5T_path_find(dset->shared->type, copied_fill.type, NULL, NULL, H5AC_ind_dxpl_id, FALSE))) + HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest data types") + + /* Convert disk form of fill value into memory form */ + if(!H5T_path_noop(tpath)) { + hid_t dst_id, src_id; /* Source & destination datatypes for type conversion */ + uint8_t *bkg_buf = NULL; /* Background conversion buffer */ + size_t bkg_size; /* Size of background buffer */ + + /* Wrap copies of types to convert */ + dst_id = H5I_register(H5I_DATATYPE, H5T_copy(copied_fill.type, H5T_COPY_TRANSIENT), FALSE); + if(dst_id < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy/register datatype") + src_id = H5I_register(H5I_DATATYPE, H5T_copy(dset->shared->type, H5T_COPY_ALL), FALSE); + if(src_id < 0) { + H5I_dec_ref(dst_id); + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy/register datatype") + } /* end if */ + + /* Allocate a background buffer */ + bkg_size = MAX(H5T_GET_SIZE(copied_fill.type), H5T_GET_SIZE(dset->shared->type)); + if(H5T_path_bkg(tpath) && NULL == (bkg_buf = H5FL_BLK_CALLOC(type_conv, bkg_size))) { + H5I_dec_ref(src_id); + H5I_dec_ref(dst_id); + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + } /* end if */ + + /* Convert fill value */ + if(H5T_convert(tpath, src_id, dst_id, (size_t)1, (size_t)0, (size_t)0, copied_fill.buf, bkg_buf, H5AC_ind_dxpl_id) < 0) { + H5I_dec_ref(src_id); + H5I_dec_ref(dst_id); + if(bkg_buf) + bkg_buf = H5FL_BLK_FREE(type_conv, bkg_buf); + HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "datatype conversion failed") + } /* end if */ + + /* Release local resources */ + if(H5I_dec_ref(src_id) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "unable to close temporary object") + if(H5I_dec_ref(dst_id) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "unable to close temporary object") + if(bkg_buf) + bkg_buf = H5FL_BLK_FREE(type_conv, bkg_buf); + } /* end if */ + } /* end if */ + + /* Set back the fill value property to property list */ + if(H5P_set(new_plist, H5D_CRT_FILL_VALUE_NAME, &copied_fill) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to set property list fill value") + + /* Set the return value */ + ret_value = new_dcpl_id; + +done: + if(ret_value < 0) + if(new_dcpl_id > 0) + if(H5I_dec_app_ref(new_dcpl_id) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "unable to close temporary object") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D_get_create_plist() */ + + +/*------------------------------------------------------------------------- + * Function: H5D_get_access_plist + * + * Purpose: Returns a copy of the dataset access property list. + * + * Return: Success: ID for a copy of the dataset access + * property list. + * + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * March, 2012 + * + *------------------------------------------------------------------------- + */ +hid_t +H5D_get_access_plist(H5D_t *dset) +{ + H5P_genplist_t *old_plist; /* Default DAPL */ + H5P_genplist_t *new_plist; /* New DAPL */ + hid_t new_dapl_id = FAIL; + hid_t ret_value = FAIL; + + FUNC_ENTER_NOAPI_NOINIT + + /* Make a copy of the default dataset access property list */ + if (NULL == (old_plist = (H5P_genplist_t *)H5I_object(H5P_LST_DATASET_ACCESS_ID_g))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list") + if ((new_dapl_id = H5P_copy_plist(old_plist, TRUE)) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTINIT, FAIL, "can't copy dataset access property list") + if (NULL == (new_plist = (H5P_genplist_t *)H5I_object(new_dapl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list") + + /* If the dataset is chunked then copy the rdcc parameters */ + if (dset->shared->layout.type == H5D_CHUNKED) { + if (H5P_set(new_plist, H5D_ACS_DATA_CACHE_NUM_SLOTS_NAME, &(dset->shared->cache.chunk.nslots)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set data cache number of slots") + if (H5P_set(new_plist, H5D_ACS_DATA_CACHE_BYTE_SIZE_NAME, &(dset->shared->cache.chunk.nbytes_max)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set data cache byte size") + if (H5P_set(new_plist, H5D_ACS_PREEMPT_READ_CHUNKS_NAME, &(dset->shared->cache.chunk.w0)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set preempt read chunks") + } /* end if */ + + /* Set the return value */ + ret_value = new_dapl_id; + +done: + if(ret_value < 0) { + if(new_dapl_id > 0) + if(H5I_dec_app_ref(new_dapl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "can't free") + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D_get_access_plist() */ + + +/*------------------------------------------------------------------------- + * Function: H5D_get_space + * + * Purpose: Returns and ID for the dataspace of the dataset. + * + * Return: Success: ID for dataspace + * + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * March, 2012 + * + *------------------------------------------------------------------------- + */ +hid_t +H5D_get_space(H5D_t *dset) +{ + H5S_t *space = NULL; + hid_t ret_value = FAIL; + + FUNC_ENTER_NOAPI_NOINIT + + /* Read the data space message and return a data space object */ + if(NULL == (space = H5S_copy(dset->shared->space, FALSE, TRUE))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to get data space") + + /* Create an atom */ + if((ret_value = H5I_register (H5I_DATASPACE, space, TRUE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register data space") + +done: + if(ret_value < 0) { + if(space!=NULL) { + if(H5S_close(space) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataspace") + } /* end if */ + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D_get_space() */ + + +/*------------------------------------------------------------------------- + * Function: H5D_get_type + * + * Purpose: Returns and ID for the datatype of the dataset. + * + * Return: Success: ID for datatype + * + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * March, 2012 + * + *------------------------------------------------------------------------- + */ +hid_t +H5D_get_type(H5D_t *dset) +{ + H5T_t *dt = NULL; + hid_t ret_value = FAIL; + + FUNC_ENTER_NOAPI_NOINIT + + /* Patch the datatype's "top level" file pointer */ + if(H5T_patch_file(dset->shared->type, dset->oloc.file) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to patch datatype's file pointer") + + /* Copy the dataset's datatype */ + if(NULL == (dt = H5T_copy(dset->shared->type, H5T_COPY_REOPEN))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to copy datatype") + + /* Mark any datatypes as being in memory now */ + if(H5T_set_loc(dt, NULL, H5T_LOC_MEMORY) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location") + + /* Lock copied type */ + if(H5T_lock(dt, FALSE) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to lock transient datatype") + + if((ret_value = H5I_register(H5I_DATATYPE, dt, TRUE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register datatype") + +done: + if(ret_value < 0) { + if(dt && H5T_close(dt) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release datatype") + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D_get_type() */ diff --git a/src/H5Dio.c b/src/H5Dio.c index 90e4983..b91d7f8 100644 --- a/src/H5Dio.c +++ b/src/H5Dio.c @@ -55,8 +55,8 @@ static herr_t H5D__write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, const H5S_t *file_space, hid_t dset_xfer_plist, const void *buf); -static herr_t H5D__pre_write(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, - hid_t file_space_id, hid_t dxpl_id, const void *buf); +static herr_t H5D__pre_write(H5D_t *dset, hbool_t direct_write, hid_t mem_type_id, + const H5S_t *mem_space, const H5S_t *file_space, hid_t dxpl_id, const void *buf); /* Setup/teardown routines */ static herr_t H5D__ioinfo_init(H5D_t *dset, @@ -212,16 +212,62 @@ herr_t H5Dwrite(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, hid_t dxpl_id, const void *buf) { + H5D_t *dset = NULL; + H5P_genplist_t *plist; /* Property list pointer */ + const H5S_t *mem_space = NULL; + const H5S_t *file_space = NULL; + hbool_t direct_write = FALSE; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE6("e", "iiiii*x", dset_id, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf); - if(!dset_id) + /* check arguments */ + if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") + if(NULL == dset->oloc.file) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file") + + /* Get the default dataset transfer property list if the user didn't provide one */ + if(H5P_DEFAULT == dxpl_id) + dxpl_id= H5P_DATASET_XFER_DEFAULT; + else + if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms") + + /* Get the dataset transfer property list */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list") + + /* Retrieve the 'direct write' flag */ + if(H5P_get(plist, H5D_XFER_DIRECT_CHUNK_WRITE_FLAG_NAME, &direct_write) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "error getting flag for direct chunk write") + + /* Check dataspace selections if this is not a direct write */ + if(!direct_write) { + if(mem_space_id < 0 || file_space_id < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") + + if(H5S_ALL != mem_space_id) { + if(NULL == (mem_space = (const H5S_t *)H5I_object_verify(mem_space_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") + + /* Check for valid selection */ + if(H5S_SELECT_VALID(mem_space) != TRUE) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "memory selection+offset not within extent") + } /* end if */ + if(H5S_ALL != file_space_id) { + if(NULL == (file_space = (const H5S_t *)H5I_object_verify(file_space_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") - if(H5D__pre_write(dset_id, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf) < 0) + /* Check for valid selection */ + if(H5S_SELECT_VALID(file_space) != TRUE) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "file selection+offset not within extent") + } /* end if */ + } + + if(H5D__pre_write(dset, direct_write, mem_type_id, mem_space, file_space, dxpl_id, buf) < 0) HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't prepare for writing data") done: @@ -242,39 +288,17 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5D__pre_write(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, - hid_t file_space_id, hid_t dxpl_id, const void *buf) +H5D__pre_write(H5D_t *dset, hbool_t direct_write, hid_t mem_type_id, + const H5S_t *mem_space, const H5S_t *file_space, + hid_t dxpl_id, const void *buf) { - H5D_t *dset = NULL; - H5P_genplist_t *plist; /* Property list pointer */ - hbool_t direct_write = FALSE; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC - /* check arguments */ - if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") - if(NULL == dset->oloc.file) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file") - - /* Get the default dataset transfer property list if the user didn't provide one */ - if(H5P_DEFAULT == dxpl_id) - dxpl_id= H5P_DATASET_XFER_DEFAULT; - else - if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms") - - /* Get the dataset transfer property list */ - if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list") - - /* Retrieve the 'direct write' flag */ - if(H5P_get(plist, H5D_XFER_DIRECT_CHUNK_WRITE_FLAG_NAME, &direct_write) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "error getting flag for direct chunk write") - /* Direct chunk write */ if(direct_write) { + H5P_genplist_t *plist; /* Property list pointer */ uint32_t direct_filters; hsize_t *direct_offset; uint32_t direct_datasize; @@ -283,6 +307,10 @@ H5D__pre_write(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, hsize_t internal_offset[H5O_LAYOUT_NDIMS]; int i; + /* Get the dataset transfer property list */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list") + if(H5D_CHUNKED != dset->shared->layout.type) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a chunked dataset") @@ -319,29 +347,6 @@ H5D__pre_write(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write chunk directly") } /* end if */ else { /* Normal write */ - const H5S_t *mem_space = NULL; - const H5S_t *file_space = NULL; - - if(mem_space_id < 0 || file_space_id < 0) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") - - if(H5S_ALL != mem_space_id) { - if(NULL == (mem_space = (const H5S_t *)H5I_object_verify(mem_space_id, H5I_DATASPACE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") - - /* Check for valid selection */ - if(H5S_SELECT_VALID(mem_space) != TRUE) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "memory selection+offset not within extent") - } /* end if */ - if(H5S_ALL != file_space_id) { - if(NULL == (file_space = (const H5S_t *)H5I_object_verify(file_space_id, H5I_DATASPACE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") - - /* Check for valid selection */ - if(H5S_SELECT_VALID(file_space) != TRUE) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "file selection+offset not within extent") - } /* end if */ - /* write raw data */ if(H5D__write(dset, mem_type_id, mem_space, file_space, dxpl_id, buf) < 0) HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data") diff --git a/src/H5Dprivate.h b/src/H5Dprivate.h index d4ecedc..0b8b76f 100644 --- a/src/H5Dprivate.h +++ b/src/H5Dprivate.h @@ -163,6 +163,9 @@ H5_DLL H5G_name_t *H5D_nameof(H5D_t *dataset); H5_DLL H5T_t *H5D_typeof(const H5D_t *dset); H5_DLL herr_t H5D_flush(const H5F_t *f, hid_t dxpl_id); H5_DLL hid_t H5D_get_create_plist(H5D_t *dset); +H5_DLL hid_t H5D_get_access_plist(H5D_t *dset); +H5_DLL hid_t H5D_get_space(H5D_t *dset); +H5_DLL hid_t H5D_get_type(H5D_t *dset); /* Functions that operate on vlen data */ H5_DLL herr_t H5D_vlen_reclaim(hid_t type_id, H5S_t *space, hid_t plist_id, diff --git a/src/H5F.c b/src/H5F.c index ed95322..f25f00f 100644 --- a/src/H5F.c +++ b/src/H5F.c @@ -20,7 +20,7 @@ #define H5F_PACKAGE /*suppress error about including H5Fpkg */ /* Interface initialization */ -#define H5_INTERFACE_INIT_FUNC H5F_init_interface +#define H5_INTERFACE_INIT_FUNC H5F__init_pub_interface /***********/ @@ -50,22 +50,6 @@ /* Local Typedefs */ /******************/ -/* Struct only used by functions H5F_get_objects and H5F_get_objects_cb */ -typedef struct H5F_olist_t { - H5I_type_t obj_type; /* Type of object to look for */ - hid_t *obj_id_list; /* Pointer to the list of open IDs to return */ - size_t *obj_id_count; /* Number of open IDs */ - struct { - hbool_t local; /* Set flag for "local" file searches */ - union { - H5F_file_t *shared; /* Pointer to shared file to look inside */ - const H5F_t *file; /* Pointer to file to look inside */ - } ptr; - } file_info; - size_t list_index; /* Current index in open ID array */ - size_t max_nobjs; /* Maximum # of IDs to put into array */ -} H5F_olist_t; - /********************/ /* Package Typedefs */ @@ -75,14 +59,7 @@ typedef struct H5F_olist_t { /********************/ /* Local Prototypes */ /********************/ -static herr_t H5F_get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_list, hbool_t app_ref, size_t *obj_id_count_ptr); -static int H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key); -static H5F_t *H5F_new(H5F_file_t *shared, unsigned flags, hid_t fcpl_id, - hid_t fapl_id, H5FD_t *lf); -static herr_t H5F_build_actual_name(const H5F_t *f, const H5P_genplist_t *fapl, - const char *name, char ** /*out*/ actual_name); -static herr_t H5F_dest(H5F_t *f, hid_t dxpl_id, hbool_t flush); -static herr_t H5F_close(H5F_t *f); + /*********************/ @@ -99,11 +76,6 @@ static herr_t H5F_close(H5F_t *f); /* Local Variables */ /*******************/ -/* Declare a free list to manage the H5F_t struct */ -H5FL_DEFINE(H5F_t); - -/* Declare a free list to manage the H5F_file_t struct */ -H5FL_DEFINE(H5F_file_t); /* File ID class */ static const H5I_class_t H5I_FILE_CLS[1] = {{ @@ -113,6 +85,35 @@ static const H5I_class_t H5I_FILE_CLS[1] = {{ (H5I_free_t)H5F_close /* Callback routine for closing objects of this class */ }}; + +/*-------------------------------------------------------------------------- +NAME + H5F__init_pub_interface -- Initialize interface-specific information +USAGE + herr_t H5F__init_pub_interface() +RETURNS + Non-negative on success/Negative on failure +DESCRIPTION + Initializes any interface-specific data or routines. (Just calls + H5F_init() currently). + +--------------------------------------------------------------------------*/ +static herr_t +H5F__init_pub_interface(void) +{ + herr_t ret_value = SUCCEED; /* Return value */ + FUNC_ENTER_STATIC + + /* + * Initialize the atom group for the file IDs. + */ + if(H5I_register_type(H5I_FILE_CLS) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to initialize interface") + + ret_value = H5F_init(); +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5F__init_pub_interface() */ /*------------------------------------------------------------------------- @@ -142,37 +143,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5F_init_interface - * - * Purpose: Initialize interface-specific information. - * - * Return: Success: non-negative - * Failure: negative - * - * Programmer: Robb Matzke - * Friday, November 20, 1998 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5F_init_interface(void) -{ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT - - /* - * Initialize the atom group for the file IDs. - */ - if(H5I_register_type(H5I_FILE_CLS) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to initialize interface") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5F_init_interface() */ - - -/*------------------------------------------------------------------------- * Function: H5F_term_interface * * Purpose: Terminate this interface: free all memory and reset global @@ -301,109 +271,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5F_get_access_plist - * - * Purpose: Returns a copy of the file access property list of the - * specified file. - * - * NOTE: Make sure that, if you are going to overwrite - * information in the copied property list that was - * previously opened and assigned to the property list, then - * you must close it before overwriting the values. - * - * Return: Success: Object ID for a copy of the file access - * property list. - * - * Failure: FAIL - * - * Programmer: Quincey Koziol - * Wednesday, May 25, 2005 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -hid_t -H5F_get_access_plist(H5F_t *f, hbool_t app_ref) -{ - H5P_genplist_t *new_plist; /* New property list */ - H5P_genplist_t *old_plist; /* Old property list */ - void *driver_info=NULL; - unsigned efc_size = 0; - hid_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI(FAIL) - - /* Check args */ - HDassert(f); - - /* Make a copy of the default file access property list */ - if(NULL == (old_plist = (H5P_genplist_t *)H5I_object(H5P_LST_FILE_ACCESS_ID_g))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list") - if((ret_value = H5P_copy_plist(old_plist, app_ref)) < 0) - HGOTO_ERROR(H5E_INTERNAL, H5E_CANTINIT, FAIL, "can't copy file access property list") - if(NULL == (new_plist = (H5P_genplist_t *)H5I_object(ret_value))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list") - - /* Copy properties of the file access property list */ - if(H5P_set(new_plist, H5F_ACS_META_CACHE_INIT_CONFIG_NAME, &(f->shared->mdc_initCacheCfg)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set initial metadata cache resize config.") - if(H5P_set(new_plist, H5F_ACS_DATA_CACHE_NUM_SLOTS_NAME, &(f->shared->rdcc_nslots)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set data cache number of slots") - if(H5P_set(new_plist, H5F_ACS_DATA_CACHE_BYTE_SIZE_NAME, &(f->shared->rdcc_nbytes)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set data cache byte size") - if(H5P_set(new_plist, H5F_ACS_PREEMPT_READ_CHUNKS_NAME, &(f->shared->rdcc_w0)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set preempt read chunks") - if(H5P_set(new_plist, H5F_ACS_ALIGN_THRHD_NAME, &(f->shared->threshold)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set alignment threshold") - if(H5P_set(new_plist, H5F_ACS_ALIGN_NAME, &(f->shared->alignment)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set alignment") - if(H5P_set(new_plist, H5F_ACS_GARBG_COLCT_REF_NAME, &(f->shared->gc_ref)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set garbage collect reference") - if(H5P_set(new_plist, H5F_ACS_META_BLOCK_SIZE_NAME, &(f->shared->meta_aggr.alloc_size)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set metadata cache size") - if(H5P_set(new_plist, H5F_ACS_SIEVE_BUF_SIZE_NAME, &(f->shared->sieve_buf_size)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't sieve buffer size") - if(H5P_set(new_plist, H5F_ACS_SDATA_BLOCK_SIZE_NAME, &(f->shared->sdata_aggr.alloc_size)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set 'small data' cache size") - if(H5P_set(new_plist, H5F_ACS_LATEST_FORMAT_NAME, &(f->shared->latest_format)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set 'latest format' flag") - if(f->shared->efc) - efc_size = H5F_efc_max_nfiles(f->shared->efc); - if(H5P_set(new_plist, H5F_ACS_EFC_SIZE_NAME, &efc_size) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set elink file cache size") - - /* - * Since we're resetting the driver ID and info, close them if they - * exist in this new property list. - */ - if(H5P_facc_close(ret_value, NULL) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTFREE, FAIL, "can't free the old driver information") - - /* Increment the reference count on the driver ID and insert it into the property list */ - if(H5I_inc_ref(f->shared->lf->driver_id, FALSE) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTINC, FAIL, "unable to increment ref count on VFL driver") - if(H5P_set(new_plist, H5F_ACS_FILE_DRV_ID_NAME, &(f->shared->lf->driver_id)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file driver ID") - - /* Set the driver "info" in the property list */ - driver_info = H5FD_fapl_get(f->shared->lf); - if(driver_info != NULL && H5P_set(new_plist, H5F_ACS_FILE_DRV_INFO_NAME, &driver_info) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file driver info") - - /* Set the file close degree appropriately */ - if(f->shared->fc_degree == H5F_CLOSE_DEFAULT && H5P_set(new_plist, H5F_ACS_CLOSE_DEGREE_NAME, &(f->shared->lf->cls->fc_degree)) < 0) { - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file close degree") - } else if(f->shared->fc_degree != H5F_CLOSE_DEFAULT && H5P_set(new_plist, H5F_ACS_CLOSE_DEGREE_NAME, &(f->shared->fc_degree)) < 0) { - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file close degree") - } - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5F_get_access_plist() */ - - -/*------------------------------------------------------------------------- * Function: H5Fget_obj_count * * Purpose: Public function returning the number of opened object IDs @@ -445,38 +312,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5F_get_obj_count - * - * Purpose: Private function return the number of opened object IDs - * (files, datasets, groups, datatypes) in the same file. - * - * Return: SUCCEED on success, FAIL on failure. - * - * Programmer: Raymond Lu - * Wednesday, Dec 5, 2001 - * - *------------------------------------------------------------------------- - */ -herr_t -H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref, size_t *obj_id_count_ptr) -{ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI(FAIL) - - /* Sanity check */ - HDassert(obj_id_count_ptr); - - /* Perform the query */ - if((ret_value = H5F_get_objects(f, types, 0, NULL, app_ref, obj_id_count_ptr)) < 0) - HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_objects failed") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5F_get_obj_count() */ - - -/*------------------------------------------------------------------------- * Function: H5Fget_object_ids * * Purpose: Public function to return a list of opened object IDs. @@ -525,253 +360,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5F_get_obj_ids - * - * Purpose: Private function to return a list of opened object IDs. - * - * Return: Non-negative on success; can't fail. - * - * Programmer: Raymond Lu - * Wednesday, Dec 5, 2001 - * - *------------------------------------------------------------------------- - */ -herr_t -H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *oid_list, hbool_t app_ref, size_t *obj_id_count_ptr) -{ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(FAIL) - - /* Sanity check */ - HDassert(obj_id_count_ptr); - - /* Perform the query */ - if((ret_value = H5F_get_objects(f, types, max_objs, oid_list, app_ref, obj_id_count_ptr)) < 0) - HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_objects failed") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5F_get_obj_ids() */ - - -/*--------------------------------------------------------------------------- - * Function: H5F_get_objects - * - * Purpose: This function is called by H5F_get_obj_count or - * H5F_get_obj_ids to get number of object IDs and/or a - * list of opened object IDs (in return value). - * Return: Non-negative on success; Can't fail. - * - * Programmer: Raymond Lu - * Wednesday, Dec 5, 2001 - * - *--------------------------------------------------------------------------- - */ -static herr_t -H5F_get_objects(const H5F_t *f, unsigned types, size_t max_nobjs, hid_t *obj_id_list, hbool_t app_ref, size_t *obj_id_count_ptr) -{ - size_t obj_id_count=0; /* Number of open IDs */ - H5F_olist_t olist; /* Structure to hold search results */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT - - /* Sanity check */ - HDassert(obj_id_count_ptr); - - /* Set up search information */ - olist.obj_id_list = (max_nobjs==0 ? NULL : obj_id_list); - olist.obj_id_count = &obj_id_count; - olist.list_index = 0; - olist.max_nobjs = max_nobjs; - - /* Determine if we are searching for local or global objects */ - if(types & H5F_OBJ_LOCAL) { - olist.file_info.local = TRUE; - olist.file_info.ptr.file = f; - } /* end if */ - else { - olist.file_info.local = FALSE; - olist.file_info.ptr.shared = f ? f->shared : NULL; - } /* end else */ - - /* Iterate through file IDs to count the number, and put their - * IDs on the object list. */ - if(types & H5F_OBJ_FILE) { - olist.obj_type = H5I_FILE; - if(H5I_iterate(H5I_FILE, H5F_get_objects_cb, &olist, app_ref) < 0) - HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(1)") - } /* end if */ - - /* If the caller just wants to count the number of objects (OLIST.MAX_NOBJS is zero), - * or the caller wants to get the list of IDs and the list isn't full, - * search through dataset IDs to count number of datasets, and put their - * IDs on the object list */ - if(!olist.max_nobjs || (olist.max_nobjs && olist.list_indexobj_type == H5I_FILE) { - if((olist->file_info.local && - (!olist->file_info.ptr.file || (olist->file_info.ptr.file && (H5F_t*)obj_ptr == olist->file_info.ptr.file) )) - || (!olist->file_info.local && - ( !olist->file_info.ptr.shared || (olist->file_info.ptr.shared && ((H5F_t*)obj_ptr)->shared == olist->file_info.ptr.shared) ))) { - add_obj = TRUE; - } - } /* end if */ - else { /* either count opened object IDs or put the IDs on the list */ - H5O_loc_t *oloc; /* Group entry info for object */ - - switch(olist->obj_type) { - case H5I_ATTR: - oloc = H5A_oloc((H5A_t *)obj_ptr); - break; - - case H5I_GROUP: - oloc = H5G_oloc((H5G_t *)obj_ptr); - break; - - case H5I_DATASET: - oloc = H5D_oloc((H5D_t *)obj_ptr); - break; - - case H5I_DATATYPE: - if(H5T_is_named((H5T_t*)obj_ptr)==TRUE) - oloc = H5T_oloc((H5T_t*)obj_ptr); - else - oloc = NULL; - break; - - case H5I_UNINIT: - case H5I_BADID: - case H5I_FILE: - case H5I_DATASPACE: - case H5I_REFERENCE: - case H5I_VFL: - case H5I_GENPROP_CLS: - case H5I_GENPROP_LST: - case H5I_ERROR_CLASS: - case H5I_ERROR_MSG: - case H5I_ERROR_STACK: - case H5I_NTYPES: - default: - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5_ITER_ERROR, "unknown data object") - } /* end switch */ - - if((olist->file_info.local && - ( (!olist->file_info.ptr.file && olist->obj_type == H5I_DATATYPE && H5T_is_immutable((H5T_t *)obj_ptr) == FALSE) - || (!olist->file_info.ptr.file && olist->obj_type != H5I_DATATYPE) - || (oloc && oloc->file == olist->file_info.ptr.file))) - || (!olist->file_info.local && - ((!olist->file_info.ptr.shared && olist->obj_type == H5I_DATATYPE && H5T_is_immutable((H5T_t *)obj_ptr) == FALSE) - || (!olist->file_info.ptr.shared && olist->obj_type != H5I_DATATYPE) - || (oloc && oloc->file && oloc->file->shared == olist->file_info.ptr.shared)))) { - add_obj = TRUE; - } /* end if */ - } /* end else */ - - if(TRUE==add_obj) { - /* Add the object's ID to the ID list, if appropriate */ - if(olist->obj_id_list) { - olist->obj_id_list[olist->list_index] = obj_id; - olist->list_index++; - } /* end if */ - - /* Increment the number of open objects */ - if(olist->obj_id_count) - (*olist->obj_id_count)++; - - /* Check if we've filled up the array. Return H5_ITER_STOP only if - * we have filled up the array. Otherwise return H5_ITER_CONT(RET_VALUE is - * preset to H5_ITER_CONT) because H5I_iterate needs the return value of - * H5_ITER_CONT to continue the iteration. */ - if(olist->max_nobjs>0 && olist->list_index>=olist->max_nobjs) - HGOTO_DONE(H5_ITER_STOP) /* Indicate that the iterator should stop */ - } - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5F_get_objects_cb() */ - - -/*------------------------------------------------------------------------- * Function: H5Fget_vfd_handle * * Purpose: Returns a pointer to the file handle of the low-level file @@ -834,8 +422,6 @@ done: htri_t H5Fis_hdf5(const char *name) { - H5FD_t *file = NULL; /* Low-level file struct */ - haddr_t sig_addr; /* Address of hdf5 file signature */ htri_t ret_value; /* Return value */ FUNC_ENTER_API(FAIL) @@ -845,608 +431,17 @@ H5Fis_hdf5(const char *name) if(!name || !*name) HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "no file name specified") - /* Open the file at the virtual file layer */ - if(NULL == (file = H5FD_open(name, H5F_ACC_RDONLY, H5P_FILE_ACCESS_DEFAULT, HADDR_UNDEF))) - HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to open file") - - /* The file is an hdf5 file if the hdf5 file signature can be found */ - if(H5FD_locate_signature(file, H5AC_ind_dxpl_g, &sig_addr) < 0) - HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "unable to locate file signature") - ret_value = (HADDR_UNDEF != sig_addr); + /* call the private is_HDF5 function */ + if((ret_value = H5F_is_hdf5(name)) < 0) + HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "unable open file") done: - /* Close the file */ - if(file) - if(H5FD_close(file) < 0 && ret_value >= 0) - HDONE_ERROR(H5E_IO, H5E_CANTCLOSEFILE, FAIL, "unable to close file") FUNC_LEAVE_API(ret_value) } /* end H5Fis_hdf5() */ /*------------------------------------------------------------------------- - * Function: H5F_new - * - * Purpose: Creates a new file object and initializes it. The - * H5Fopen and H5Fcreate functions then fill in various - * fields. If SHARED is a non-null pointer then the shared info - * to which it points has the reference count incremented. - * Otherwise a new, empty shared info struct is created and - * initialized with the specified file access property list. - * - * Errors: - * - * Return: Success: Ptr to a new file struct. - * - * Failure: NULL - * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jul 18 1997 - * - *------------------------------------------------------------------------- - */ -static H5F_t * -H5F_new(H5F_file_t *shared, unsigned flags, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf) -{ - H5F_t *f = NULL, *ret_value; - - FUNC_ENTER_NOAPI_NOINIT - - if(NULL == (f = H5FL_CALLOC(H5F_t))) - HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, NULL, "can't allocate top file structure") - f->file_id = -1; - - if(shared) { - HDassert(lf == NULL); - f->shared = shared; - } /* end if */ - else { - H5P_genplist_t *plist; /* Property list */ - unsigned efc_size; /* External file cache size */ - size_t u; /* Local index variable */ - - HDassert(lf != NULL); - if(NULL == (f->shared = H5FL_CALLOC(H5F_file_t))) - HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, NULL, "can't allocate shared file structure") - - f->shared->flags = flags; - f->shared->sohm_addr = HADDR_UNDEF; - f->shared->sohm_vers = HDF5_SHAREDHEADER_VERSION; - for(u = 0; u < NELMTS(f->shared->fs_addr); u++) - f->shared->fs_addr[u] = HADDR_UNDEF; - f->shared->accum.loc = HADDR_UNDEF; - f->shared->lf = lf; - - /* - * Copy the file creation and file access property lists into the - * new file handle. We do this early because some values might need - * to change as the file is being opened. - */ - if(NULL == (plist = (H5P_genplist_t *)H5I_object(fcpl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not property list") - f->shared->fcpl_id = H5P_copy_plist(plist, FALSE); - - /* Get the FCPL values to cache */ - if(H5P_get(plist, H5F_CRT_ADDR_BYTE_NUM_NAME, &f->shared->sizeof_addr) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get byte number for address") - if(H5P_get(plist, H5F_CRT_OBJ_BYTE_NUM_NAME, &f->shared->sizeof_size) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get byte number for object size") - if(H5P_get(plist, H5F_CRT_SHMSG_NINDEXES_NAME, &f->shared->sohm_nindexes) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get number of SOHM indexes") - HDassert(f->shared->sohm_nindexes < 255); - if(H5P_get(plist, H5F_CRT_FILE_SPACE_STRATEGY_NAME, &f->shared->fs_strategy) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get file space strategy") - if(H5P_get(plist, H5F_CRT_FREE_SPACE_THRESHOLD_NAME, &f->shared->fs_threshold) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get free-space section threshold") - - /* Get the FAPL values to cache */ - if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not file access property list") - if(H5P_get(plist, H5F_ACS_META_CACHE_INIT_CONFIG_NAME, &(f->shared->mdc_initCacheCfg)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get initial metadata cache resize config") - if(H5P_get(plist, H5F_ACS_DATA_CACHE_NUM_SLOTS_NAME, &(f->shared->rdcc_nslots)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get data cache number of slots") - if(H5P_get(plist, H5F_ACS_DATA_CACHE_BYTE_SIZE_NAME, &(f->shared->rdcc_nbytes)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get data cache byte size") - if(H5P_get(plist, H5F_ACS_PREEMPT_READ_CHUNKS_NAME, &(f->shared->rdcc_w0)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get preempt read chunk") - if(H5P_get(plist, H5F_ACS_ALIGN_THRHD_NAME, &(f->shared->threshold)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get alignment threshold") - if(H5P_get(plist, H5F_ACS_ALIGN_NAME, &(f->shared->alignment)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get alignment") - if(H5P_get(plist, H5F_ACS_GARBG_COLCT_REF_NAME,&(f->shared->gc_ref)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get garbage collect reference") - if(H5P_get(plist, H5F_ACS_SIEVE_BUF_SIZE_NAME, &(f->shared->sieve_buf_size)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get sieve buffer size") - if(H5P_get(plist, H5F_ACS_LATEST_FORMAT_NAME, &(f->shared->latest_format)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get 'latest format' flag") - if(H5P_get(plist, H5F_ACS_META_BLOCK_SIZE_NAME, &(f->shared->meta_aggr.alloc_size)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get metadata cache size") - f->shared->meta_aggr.feature_flag = H5FD_FEAT_AGGREGATE_METADATA; - if(H5P_get(plist, H5F_ACS_SDATA_BLOCK_SIZE_NAME, &(f->shared->sdata_aggr.alloc_size)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get 'small data' cache size") - f->shared->sdata_aggr.feature_flag = H5FD_FEAT_AGGREGATE_SMALLDATA; - if(H5P_get(plist, H5F_ACS_EFC_SIZE_NAME, &efc_size) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get elink file cache size") - if(efc_size > 0) - if(NULL == (f->shared->efc = H5F_efc_create(efc_size))) - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "can't create external file cache") - - /* Get the VFD values to cache */ - f->shared->maxaddr = H5FD_get_maxaddr(lf); - if(!H5F_addr_defined(f->shared->maxaddr)) - HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad maximum address from VFD") - if(H5FD_get_feature_flags(lf, &f->shared->feature_flags) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get feature flags from VFD") - if(H5FD_get_fs_type_map(lf, f->shared->fs_type_map) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get free space type mapping from VFD") - if(H5MF_init_merge_flags(f) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "problem initializing free space merge flags") - f->shared->tmp_addr = f->shared->maxaddr; - /* Disable temp. space allocation for parallel I/O (for now) */ - /* (When we've arranged to have the relocated metadata addresses (and - * sizes) broadcast during the "end of epoch" metadata operations, - * this can be enabled - QAK) - */ - /* (This should be disabled when the metadata journaling branch is - * merged into the trunk and journaling is enabled, at least until - * we make it work. - QAK) - */ - f->shared->use_tmp_space = !H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI); - - /* - * Create a metadata cache with the specified number of elements. - * The cache might be created with a different number of elements and - * the access property list should be updated to reflect that. - */ - if(H5AC_create(f, &(f->shared->mdc_initCacheCfg)) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create metadata cache") - - /* Create the file's "open object" information */ - if(H5FO_create(f) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create open object data structure") - - /* Add new "shared" struct to list of open files */ - if(H5F_sfile_add(f->shared) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to append to list of open files") - } /* end else */ - - f->shared->nrefs++; - - /* Create the file's "top open object" information */ - if(H5FO_top_create(f) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create open object data structure") - - /* Set return value */ - ret_value = f; - -done: - if(!ret_value && f) { - if(!shared) { - /* Attempt to clean up some of the shared file structures */ - if(f->shared->efc) - if(H5F_efc_destroy(f->shared->efc) < 0) - HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, NULL, "can't destroy external file cache") - if(f->shared->fcpl_id > 0) - if(H5I_dec_ref(f->shared->fcpl_id) < 0) - HDONE_ERROR(H5E_FILE, H5E_CANTDEC, NULL, "can't close property list") - - f->shared = H5FL_FREE(H5F_file_t, f->shared); - } /* end if */ - f = H5FL_FREE(H5F_t, f); - } /* end if */ - - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5F_new() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_dest - * - * Purpose: Destroys a file structure. This function flushes the cache - * but doesn't do any other cleanup other than freeing memory - * for the file struct. The shared info for the file is freed - * only when its reference count reaches zero. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jul 18 1997 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5F_dest(H5F_t *f, hid_t dxpl_id, hbool_t flush) -{ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT - - /* Sanity check */ - HDassert(f); - HDassert(f->shared); - - if(1 == f->shared->nrefs) { - H5F_io_info_t fio_info; /* I/O info for operation */ - - /* Flush at this point since the file will be closed. - * Only try to flush the file if it was opened with write access, and if - * the caller requested a flush. - */ - if((H5F_ACC_RDWR & H5F_INTENT(f)) && flush) - if(H5F_flush(f, dxpl_id, TRUE) < 0) - /* Push error, but keep going*/ - HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache") - - /* Release the external file cache */ - if(f->shared->efc) { - if(H5F_efc_destroy(f->shared->efc) < 0) - /* Push error, but keep going*/ - HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't destroy external file cache") - f->shared->efc = NULL; - } /* end if */ - - /* Release objects that depend on the superblock being initialized */ - if(f->shared->sblock) { - /* Shutdown file free space manager(s) */ - /* (We should release the free space information now (before truncating - * the file and before the metadata cache is shut down) since the - * free space manager is holding some data structures in memory - * and also because releasing free space can shrink the file's - * 'eoa' value) - */ - if(H5F_ACC_RDWR & H5F_INTENT(f)) { - if(H5MF_close(f, dxpl_id) < 0) - /* Push error, but keep going*/ - HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release file free space info") - - /* Flush the file again (if requested), as shutting down the - * free space manager may dirty some data structures again. - */ - if(flush) - if(H5F_flush(f, dxpl_id, TRUE) < 0) - /* Push error, but keep going*/ - HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache") - } /* end if */ - - /* Unpin the superblock, since we're about to destroy the cache */ - if(H5AC_unpin_entry(f->shared->sblock) < 0) - /* Push error, but keep going*/ - HDONE_ERROR(H5E_FSPACE, H5E_CANTUNPIN, FAIL, "unable to unpin superblock") - f->shared->sblock = NULL; - } /* end if */ - - /* Remove shared file struct from list of open files */ - if(H5F_sfile_remove(f->shared) < 0) - /* Push error, but keep going*/ - HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file") - - /* Shutdown the metadata cache */ - if(H5AC_dest(f, dxpl_id)) - /* Push error, but keep going*/ - HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file") - - /* - * Do not close the root group since we didn't count it, but free - * the memory associated with it. - */ - if(f->shared->root_grp) { - /* Free the root group */ - if(H5G_root_free(f->shared->root_grp) < 0) - /* Push error, but keep going*/ - HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file") - f->shared->root_grp = NULL; - } /* end if */ - - /* Set up I/O info for operation */ - fio_info.f = f; - if(NULL == (fio_info.dxpl = (H5P_genplist_t *)H5I_object(dxpl_id))) - HDONE_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list") - - /* Destroy other components of the file */ - if(H5F__accum_reset(&fio_info, TRUE) < 0) - /* Push error, but keep going*/ - HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file") - if(H5FO_dest(f) < 0) - /* Push error, but keep going*/ - HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file") - f->shared->cwfs = (struct H5HG_heap_t **)H5MM_xfree(f->shared->cwfs); - if(H5G_node_close(f) < 0) - /* Push error, but keep going*/ - HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file") - - /* Destroy file creation properties */ - if(H5I_GENPROP_LST != H5I_get_type(f->shared->fcpl_id)) - /* Push error, but keep going*/ - HDONE_ERROR(H5E_FILE, H5E_BADTYPE, FAIL, "not a property list") - if(H5I_dec_ref(f->shared->fcpl_id) < 0) - /* Push error, but keep going*/ - HDONE_ERROR(H5E_FILE, H5E_CANTDEC, FAIL, "can't close property list") - - /* Only truncate the file on an orderly close, with write-access */ - if(f->closing && (H5F_ACC_RDWR & H5F_INTENT(f))) { - /* Truncate the file to the current allocated size */ - if(H5FD_truncate(f->shared->lf, dxpl_id, (unsigned)TRUE) < 0) - /* Push error, but keep going*/ - HDONE_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "low level truncate failed") - } /* end if */ - - /* Close the file */ - if(H5FD_close(f->shared->lf) < 0) - /* Push error, but keep going*/ - HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close file") - - /* Free mount table */ - f->shared->mtab.child = (H5F_mount_t *)H5MM_xfree(f->shared->mtab.child); - f->shared->mtab.nalloc = 0; - - /* Destroy shared file struct */ - f->shared = (H5F_file_t *)H5FL_FREE(H5F_file_t, f->shared); - - } else if(f->shared->nrefs > 0) { - /* - * There are other references to the shared part of the file. - * Only decrement the reference count. - */ - --f->shared->nrefs; - } - - /* Free the non-shared part of the file */ - f->open_name = (char *)H5MM_xfree(f->open_name); - f->actual_name = (char *)H5MM_xfree(f->actual_name); - f->extpath = (char *)H5MM_xfree(f->extpath); - if(H5FO_top_dest(f) < 0) - HDONE_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "problems closing file") - f->shared = NULL; - f = H5FL_FREE(H5F_t, f); - - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5F_dest() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_open - * - * Purpose: Opens (or creates) a file. This function understands the - * following flags which are similar in nature to the Posix - * open(2) flags. - * - * H5F_ACC_RDWR: Open with read/write access. If the file is - * currently open for read-only access then it - * will be reopened. Absence of this flag - * implies read-only access. - * - * H5F_ACC_CREAT: Create a new file if it doesn't exist yet. - * The permissions are 0666 bit-wise AND with - * the current umask. H5F_ACC_WRITE must also - * be specified. - * - * H5F_ACC_EXCL: This flag causes H5F_open() to fail if the - * file already exists. - * - * H5F_ACC_TRUNC: The file is truncated and a new HDF5 superblock - * is written. This operation will fail if the - * file is already open. - * - * Unlinking the file name from the group directed graph while - * the file is opened causes the file to continue to exist but - * one will not be able to upgrade the file from read-only - * access to read-write access by reopening it. Disk resources - * for the file are released when all handles to the file are - * closed. NOTE: This paragraph probably only applies to Unix; - * deleting the file name in other OS's has undefined results. - * - * The CREATE_PARMS argument is optional. A null pointer will - * cause the default file creation parameters to be used. - * - * The ACCESS_PARMS argument is optional. A null pointer will - * cause the default file access parameters to be used. - * - * Return: Success: A new file pointer. - * Failure: NULL - * - * Programmer: Robb Matzke - * Tuesday, September 23, 1997 - * - *------------------------------------------------------------------------- - */ -H5F_t * -H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, - hid_t dxpl_id) -{ - H5F_t *file = NULL; /*the success return value */ - H5F_file_t *shared = NULL; /*shared part of `file' */ - H5FD_t *lf = NULL; /*file driver part of `shared' */ - unsigned tent_flags; /*tentative flags */ - H5FD_class_t *drvr; /*file driver class info */ - H5P_genplist_t *a_plist; /*file access property list */ - H5F_close_degree_t fc_degree; /*file close degree */ - H5F_t *ret_value; /*actual return value */ - - FUNC_ENTER_NOAPI(NULL) - - /* - * If the driver has a `cmp' method then the driver is capable of - * determining when two file handles refer to the same file and the - * library can insure that when the application opens a file twice - * that the two handles coordinate their operations appropriately. - * Otherwise it is the application's responsibility to never open the - * same file more than once at a time. - */ - if(NULL == (drvr = H5FD_get_class(fapl_id))) - HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "unable to retrieve VFL class") - - /* - * Opening a file is a two step process. First we try to open the - * file in a way which doesn't affect its state (like not truncating - * or creating it) so we can compare it with files that are already - * open. If that fails then we try again with the full set of flags - * (only if they're different than the original failed attempt). - * However, if the file driver can't distinquish between files then - * there's no reason to open the file tentatively because it's the - * application's responsibility to prevent this situation (there's no - * way for us to detect it here anyway). - */ - if(drvr->cmp) - tent_flags = flags & ~(H5F_ACC_CREAT|H5F_ACC_TRUNC|H5F_ACC_EXCL); - else - tent_flags = flags; - - if(NULL == (lf = H5FD_open(name, tent_flags, fapl_id, HADDR_UNDEF))) { - if(tent_flags == flags) { -#ifndef H5_USING_MEMCHECKER - time_t mytime = HDtime(NULL); - - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file: time = %s, name = '%s', tent_flags = %x", HDctime(&mytime), name, tent_flags) -#else /* H5_USING_MEMCHECKER */ - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file: name = '%s', tent_flags = %x", name, tent_flags) -#endif /* H5_USING_MEMCHECKER */ - } /* end if */ - H5E_clear_stack(NULL); - tent_flags = flags; - if(NULL == (lf = H5FD_open(name, tent_flags, fapl_id, HADDR_UNDEF))) { -#ifndef H5_USING_MEMCHECKER - time_t mytime = HDtime(NULL); - - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file: time = %s, name = '%s', tent_flags = %x", HDctime(&mytime), name, tent_flags) -#else /* H5_USING_MEMCHECKER */ - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file: name = '%s', tent_flags = %x", name, tent_flags) -#endif /* H5_USING_MEMCHECKER */ - } /* end if */ - } /* end if */ - - /* Is the file already open? */ - if((shared = H5F_sfile_search(lf)) != NULL) { - /* - * The file is already open, so use that one instead of the one we - * just opened. We only one one H5FD_t* per file so one doesn't - * confuse the other. But fail if this request was to truncate the - * file (since we can't do that while the file is open), or if the - * request was to create a non-existent file (since the file already - * exists), or if the new request adds write access (since the - * readers don't expect the file to change under them). - */ - if(H5FD_close(lf) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to close low-level file info") - if(flags & H5F_ACC_TRUNC) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to truncate a file which is already open") - if(flags & H5F_ACC_EXCL) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "file exists") - if((flags & H5F_ACC_RDWR) && 0 == (shared->flags & H5F_ACC_RDWR)) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "file is already open for read-only") - - /* Allocate new "high-level" file struct */ - if((file = H5F_new(shared, flags, fcpl_id, fapl_id, NULL)) == NULL) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to create new file object") - } /* end if */ - else { - /* Check if tentative open was good enough */ - if(flags != tent_flags) { - /* - * This file is not yet open by the library and the flags we used to - * open it are different than the desired flags. Close the tentative - * file and open it for real. - */ - if(H5FD_close(lf) < 0) { - file = NULL; /*to prevent destruction of wrong file*/ - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to close low-level file info") - } /* end if */ - if(NULL == (lf = H5FD_open(name, flags, fapl_id, HADDR_UNDEF))) { - file = NULL; /*to prevent destruction of wrong file*/ - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file") - } /* end if */ - } /* end if */ - - if(NULL == (file = H5F_new(NULL, flags, fcpl_id, fapl_id, lf))) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to create new file object") - } /* end else */ - - /* Retain the name the file was opened with */ - file->open_name = H5MM_xstrdup(name); - - /* Short cuts */ - shared = file->shared; - lf = shared->lf; - - /* - * Read or write the file superblock, depending on whether the file is - * empty or not. - */ - if(0 == H5FD_get_eof(lf) && (flags & H5F_ACC_RDWR)) { - /* - * We've just opened a fresh new file (or truncated one). We need - * to create & write the superblock. - */ - - /* Initialize information about the superblock and allocate space for it */ - /* (Writes superblock extension messages, if there are any) */ - if(H5F_super_init(file, dxpl_id) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to allocate file superblock") - - /* Create and open the root group */ - /* (This must be after the space for the superblock is allocated in - * the file, since the superblock must be at offset 0) - */ - if(H5G_mkroot(file, dxpl_id, TRUE) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create/open root group") - } else if (1 == shared->nrefs) { - /* Read the superblock if it hasn't been read before. */ - if(H5F_super_read(file, dxpl_id) < 0) - HGOTO_ERROR(H5E_FILE, H5E_READERROR, NULL, "unable to read superblock") - - /* Open the root group */ - if(H5G_mkroot(file, dxpl_id, FALSE) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to read root group") - } /* end if */ - - /* Get the file access property list, for future queries */ - if(NULL == (a_plist = (H5P_genplist_t *)H5I_object(fapl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not file access property list") - - /* - * Decide the file close degree. If it's the first time to open the - * file, set the degree to access property list value; if it's the - * second time or later, verify the access property list value matches - * the degree in shared file structure. - */ - if(H5P_get(a_plist, H5F_ACS_CLOSE_DEGREE_NAME, &fc_degree) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get file close degree") - - if(shared->nrefs == 1) { - if(fc_degree == H5F_CLOSE_DEFAULT) - shared->fc_degree = lf->cls->fc_degree; - else - shared->fc_degree = fc_degree; - } else if(shared->nrefs > 1) { - if(fc_degree == H5F_CLOSE_DEFAULT && shared->fc_degree != lf->cls->fc_degree) - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "file close degree doesn't match") - if(fc_degree != H5F_CLOSE_DEFAULT && fc_degree != shared->fc_degree) - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "file close degree doesn't match") - } /* end if */ - - /* Formulate the absolute path for later search of target file for external links */ - if(H5_build_extpath(name, &file->extpath) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to build extpath") - - /* Formulate the actual file name, after following symlinks, etc. */ - if(H5F_build_actual_name(file, a_plist, name, &file->actual_name) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to build actual name") - - /* Success */ - ret_value = file; - -done: - if(!ret_value && file) - if(H5F_dest(file, dxpl_id, FALSE) < 0) - HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, NULL, "problems closing file") - - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5F_open() */ - - -/*------------------------------------------------------------------------- * Function: H5Fcreate * * Purpose: This is the primary function for creating HDF5 files . The @@ -1741,297 +736,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5F_flush - * - * Purpose: Flushes cached data. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Aug 29 1997 - * - *------------------------------------------------------------------------- - */ -herr_t -H5F_flush(H5F_t *f, hid_t dxpl_id, hbool_t closing) -{ - H5F_io_info_t fio_info; /* I/O info for operation */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(FAIL) - - /* Sanity check arguments */ - HDassert(f); - - /* Flush any cached dataset storage raw data */ - if(H5D_flush(f, dxpl_id) < 0) - /* Push error, but keep going*/ - HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush dataset cache") - - /* Release any space allocated to space aggregators, so that the eoa value - * corresponds to the end of the space written to in the file. - */ - /* (needs to happen before cache flush, with superblock write, since the - * 'eoa' value is written in superblock -QAK) - */ - if(H5MF_free_aggrs(f, dxpl_id) < 0) - /* Push error, but keep going*/ - HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release file space") - - /* Flush the entire metadata cache */ - if(H5AC_flush(f, dxpl_id) < 0) - /* Push error, but keep going*/ - HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush metadata cache") - - /* Set up I/O info for operation */ - fio_info.f = f; - if(NULL == (fio_info.dxpl = (H5P_genplist_t *)H5I_object(dxpl_id))) - HDONE_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list") - - /* Flush out the metadata accumulator */ - if(H5F__accum_flush(&fio_info) < 0) - /* Push error, but keep going*/ - HDONE_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "unable to flush metadata accumulator") - - /* Flush file buffers to disk. */ - if(H5FD_flush(f->shared->lf, dxpl_id, closing) < 0) - /* Push error, but keep going*/ - HDONE_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "low level flush failed") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5F_flush() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_close - * - * Purpose: Closes a file or causes the close operation to be pended. - * This function is called two ways: from the API it gets called - * by H5Fclose->H5I_dec_ref->H5F_close when H5I_dec_ref() - * decrements the file ID reference count to zero. The file ID - * is removed from the H5I_FILE group by H5I_dec_ref() just - * before H5F_close() is called. If there are open object - * headers then the close is pended by moving the file to the - * H5I_FILE_CLOSING ID group (the f->closing contains the ID - * assigned to file). - * - * This function is also called directly from H5O_close() when - * the last object header is closed for the file and the file - * has a pending close. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Tuesday, September 23, 1997 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5F_close(H5F_t *f) -{ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT - - /* Sanity check */ - HDassert(f); - HDassert(f->file_id > 0); /* This routine should only be called when a file ID's ref count drops to zero */ - - /* Perform checks for "semi" file close degree here, since closing the - * file is not allowed if there are objects still open */ - if(f->shared->fc_degree == H5F_CLOSE_SEMI) { - unsigned nopen_files = 0; /* Number of open files in file/mount hierarchy */ - unsigned nopen_objs = 0; /* Number of open objects in file/mount hierarchy */ - - /* Get the number of open objects and open files on this file/mount hierarchy */ - if(H5F_mount_count_ids(f, &nopen_files, &nopen_objs) < 0) - HGOTO_ERROR(H5E_SYM, H5E_MOUNT, FAIL, "problem checking mount hierarchy") - - /* If there are no other file IDs open on this file/mount hier., but - * there are still open objects, issue an error and bail out now, - * without decrementing the file ID's reference count and triggering - * a "real" attempt at closing the file */ - if(nopen_files == 1 && nopen_objs > 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, there are objects still open") - } /* end if */ - - /* Reset the file ID for this file */ - f->file_id = -1; - - /* Attempt to close the file/mount hierarchy */ - if(H5F_try_close(f) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5F_close() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_try_close - * - * Purpose: Attempts to close a file due to one of several actions: - * - The reference count on the file ID dropped to zero - * - The last open object was closed in the file - * - The file was unmounted - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * Tuesday, July 19, 2005 - * - *------------------------------------------------------------------------- - */ -herr_t -H5F_try_close(H5F_t *f) -{ - unsigned nopen_files = 0; /* Number of open files in file/mount hierarchy */ - unsigned nopen_objs = 0; /* Number of open objects in file/mount hierarchy */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT - - /* Sanity check */ - HDassert(f); - HDassert(f->shared); - - /* Check if this file is already in the process of closing */ - if(f->closing) - HGOTO_DONE(SUCCEED) - - /* Get the number of open objects and open files on this file/mount hierarchy */ - if(H5F_mount_count_ids(f, &nopen_files, &nopen_objs) < 0) - HGOTO_ERROR(H5E_SYM, H5E_MOUNT, FAIL, "problem checking mount hierarchy") - - /* - * Close file according to close degree: - * - * H5F_CLOSE_WEAK: if there are still objects open, wait until - * they are all closed. - * H5F_CLOSE_SEMI: if there are still objects open, return fail; - * otherwise, close file. - * H5F_CLOSE_STRONG: if there are still objects open, close them - * first, then close file. - */ - switch(f->shared->fc_degree) { - case H5F_CLOSE_WEAK: - /* - * If file or object IDS are still open then delay deletion of - * resources until they have all been closed. Flush all - * caches and update the object header anyway so that failing to - * close all objects isn't a major problem. - */ - if((nopen_files + nopen_objs) > 0) - HGOTO_DONE(SUCCEED) - break; - - case H5F_CLOSE_SEMI: - /* Can leave safely if file IDs are still open on this file */ - if(nopen_files > 0) - HGOTO_DONE(SUCCEED) - - /* Sanity check: If close degree if "semi" and we have gotten this - * far and there are objects left open, bail out now */ - HDassert(nopen_files == 0 && nopen_objs == 0); - - /* If we've gotten this far (ie. there are no open objects in the file), fall through to flush & close */ - break; - - case H5F_CLOSE_STRONG: - /* If there are other open files in the hierarchy, we can leave now */ - if(nopen_files > 0) - HGOTO_DONE(SUCCEED) - - /* If we've gotten this far (ie. there are no open file IDs in the file/mount hierarchy), fall through to flush & close */ - break; - - case H5F_CLOSE_DEFAULT: - default: - HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, unknown file close degree") - } /* end switch */ - - /* Mark this file as closing (prevents re-entering file shutdown code below) */ - f->closing = TRUE; - - /* If the file close degree is "strong", close all the open objects in this file */ - if(f->shared->fc_degree == H5F_CLOSE_STRONG) { - HDassert(nopen_files == 0); - - /* Forced close of all opened objects in this file */ - if(f->nopen_objs > 0) { - size_t obj_count; /* # of open objects */ - hid_t objs[128]; /* Array of objects to close */ - herr_t result; /* Local result from obj ID query */ - size_t u; /* Local index variable */ - - /* Get the list of IDs of open dataset, group, & attribute objects */ - while((result = H5F_get_obj_ids(f, H5F_OBJ_LOCAL | H5F_OBJ_DATASET | H5F_OBJ_GROUP | H5F_OBJ_ATTR, (int)(sizeof(objs) / sizeof(objs[0])), objs, FALSE, &obj_count)) <= 0 - && obj_count != 0 ) { - - /* Try to close all the open objects in this file */ - for(u = 0; u < obj_count; u++) - if(H5I_dec_ref(objs[u]) < 0) - HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object") - } /* end while */ - if(result < 0) - HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_obj_ids failed(1)") - - /* Get the list of IDs of open named datatype objects */ - /* (Do this separately from the dataset & attribute IDs, because - * they could be using one of the named datatypes and then the - * open named datatype ID will get closed twice) - */ - while((result = H5F_get_obj_ids(f, H5F_OBJ_LOCAL | H5F_OBJ_DATATYPE, (int)(sizeof(objs) / sizeof(objs[0])), objs, FALSE, &obj_count)) <= 0 - && obj_count != 0) { - - /* Try to close all the open objects in this file */ - for(u = 0; u < obj_count; u++) - if(H5I_dec_ref(objs[u]) < 0) - HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object") - } /* end while */ - if(result < 0) - HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_obj_ids failed(2)") - } /* end if */ - } /* end if */ - - /* Check if this is a child file in a mounting hierarchy & proceed up the - * hierarchy if so. - */ - if(f->parent) - if(H5F_try_close(f->parent) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close parent file") - - /* Unmount and close each child before closing the current file. */ - if(H5F_close_mounts(f) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't unmount child files") - - /* If there is more than one reference to the shared file struct and the - * file has an external file cache, we should see if it can be closed. This - * can happen if a cycle is formed with external file caches */ - if(f->shared->efc && (f->shared->nrefs > 1)) - if(H5F_efc_try_close(f) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't attempt to close EFC") - - /* Delay flush until the shared file struct is closed, in H5F_dest. If the - * application called H5Fclose, it would have been flushed in that function - * (unless it will have been flushed in H5F_dest anyways). */ - - /* - * Destroy the H5F_t struct and decrement the reference count for the - * shared H5F_file_t struct. If the reference count for the H5F_file_t - * struct reaches zero then destroy it also. - */ - if(H5F_dest(f, H5AC_dxpl_id, TRUE) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "problems closing file") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5F_try_close() */ - - -/*------------------------------------------------------------------------- * Function: H5Fclose * * Purpose: This function closes the file specified by FILE_ID by @@ -2196,382 +900,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5F_get_id - * - * Purpose: Get the file ID, incrementing it, or "resurrecting" it as - * appropriate. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Raymond Lu - * Oct 29, 2003 - * - *------------------------------------------------------------------------- - */ -hid_t -H5F_get_id(H5F_t *file, hbool_t app_ref) -{ - hid_t ret_value; - - FUNC_ENTER_NOAPI_NOINIT - - HDassert(file); - - if(file->file_id == -1) { - /* Get an atom for the file */ - if((file->file_id = H5I_register(H5I_FILE, file, app_ref)) < 0) - HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize file") - } else { - /* Increment reference count on atom. */ - if(H5I_inc_ref(file->file_id, app_ref) < 0) - HGOTO_ERROR(H5E_ATOM, H5E_CANTSET, FAIL, "incrementing file ID failed") - } /* end else */ - - ret_value = file->file_id; - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5F_get_id() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_incr_nopen_objs - * - * Purpose: Increment the number of open objects for a file. - * - * Return: Success: The number of open objects, after the increment - * - * Failure: (can't happen) - * - * Programmer: Quincey Koziol - * koziol@hdfgroup.org - * Mar 6 2007 - * - *------------------------------------------------------------------------- - */ -unsigned -H5F_incr_nopen_objs(H5F_t *f) -{ - /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOERR - - HDassert(f); - - FUNC_LEAVE_NOAPI(++f->nopen_objs) -} /* end H5F_incr_nopen_objs() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_decr_nopen_objs - * - * Purpose: Decrement the number of open objects for a file. - * - * Return: Success: The number of open objects, after the decrement - * - * Failure: (can't happen) - * - * Programmer: Quincey Koziol - * koziol@hdfgroup.org - * Mar 6 2007 - * - *------------------------------------------------------------------------- - */ -unsigned -H5F_decr_nopen_objs(H5F_t *f) -{ - /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOERR - - HDassert(f); - - FUNC_LEAVE_NOAPI(--f->nopen_objs) -} /* end H5F_decr_nopen_objs() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_build_actual_name - * - * Purpose: Retrieve the name of a file, after following symlinks, etc. - * - * Note: Currently only working for "POSIX I/O compatible" VFDs - * - * Return: Success: 0 - * Failure: -1 - * - * Programmer: Quincey Koziol - * November 25, 2009 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5F_build_actual_name(const H5F_t *f, const H5P_genplist_t *fapl, const char *name, - char **actual_name/*out*/) -{ - hid_t new_fapl_id = -1; /* ID for duplicated FAPL */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT - - /* Sanity check */ - HDassert(f); - HDassert(fapl); - HDassert(name); - HDassert(actual_name); - - /* Clear actual name pointer to begin with */ - *actual_name = NULL; - -/* Assume that if the OS can't create symlinks, that we don't need to worry - * about resolving them either. -QAK - */ -#ifdef H5_HAVE_SYMLINK - /* Check for POSIX I/O compatible file handle */ - if(H5F_HAS_FEATURE(f, H5FD_FEAT_POSIX_COMPAT_HANDLE)) { - h5_stat_t lst; /* Stat info from lstat() call */ - - /* Call lstat() on the file's name */ - if(HDlstat(name, &lst) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't retrieve stat info for file") - - /* Check for symbolic link */ - if(S_IFLNK == (lst.st_mode & S_IFMT)) { - H5P_genplist_t *new_fapl; /* Duplicated FAPL */ - int *fd; /* POSIX I/O file descriptor */ - h5_stat_t st; /* Stat info from stat() call */ - h5_stat_t fst; /* Stat info from fstat() call */ - char realname[PATH_MAX]; /* Fully resolved path name of file */ - hbool_t want_posix_fd; /* Flag for retrieving file descriptor from VFD */ - - /* Perform a sanity check that the file or link wasn't switched - * between when we opened it and when we called lstat(). This is - * according to the security best practices for lstat() documented - * here: https://www.securecoding.cert.org/confluence/display/seccode/POS35-C.+Avoid+race+conditions+while+checking+for+the+existence+of+a+symbolic+link - */ - - /* Copy the FAPL object to modify */ - if((new_fapl_id = H5P_copy_plist(fapl, FALSE)) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, FAIL, "unable to copy file access property list") - if(NULL == (new_fapl = (H5P_genplist_t *)H5I_object(new_fapl_id))) - HGOTO_ERROR(H5E_FILE, H5E_CANTCREATE, FAIL, "can't get property list") - - /* Set the character encoding on the new property list */ - want_posix_fd = TRUE; - if(H5P_set(new_fapl, H5F_ACS_WANT_POSIX_FD_NAME, &want_posix_fd) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set character encoding") - - /* Retrieve the file handle */ - if(H5F_get_vfd_handle(f, new_fapl_id, (void **)&fd) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't retrieve POSIX file descriptor") - - /* Stat the filename we're resolving */ - if(HDstat(name, &st) < 0) - HSYS_GOTO_ERROR(H5E_FILE, H5E_BADFILE, FAIL, "unable to stat file") - - /* Stat the file we opened */ - if(HDfstat(*fd, &fst) < 0) - HSYS_GOTO_ERROR(H5E_FILE, H5E_BADFILE, FAIL, "unable to fstat file") - - /* Verify that the files are really the same */ - if(st.st_mode != fst.st_mode || st.st_ino != fst.st_ino || st.st_dev != fst.st_dev) - HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "files' st_ino or st_dev fields changed!") - - /* Get the resolved path for the file name */ - if(NULL == HDrealpath(name, realname)) - HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't retrieve real path for file") - - /* Duplicate the resolved path for the file name */ - if(NULL == (*actual_name = (char *)H5MM_strdup(realname))) - HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "can't duplicate real path") - } /* end if */ - } /* end if */ -#endif /* H5_HAVE_SYMLINK */ - - /* Check if we've resolved the file's name */ - if(NULL == *actual_name) { - /* Just duplicate the name used to open the file */ - if(NULL == (*actual_name = (char *)H5MM_strdup(name))) - HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "can't duplicate open name") - } /* end else */ - -done: - /* Close the property list */ - if(new_fapl_id > 0) - if(H5I_dec_app_ref(new_fapl_id) < 0) - HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "can't close duplicated FAPL") - - FUNC_LEAVE_NOAPI(ret_value) -} /* H5F_build_actual_name() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_addr_encode_len - * - * Purpose: Encodes an address into the buffer pointed to by *PP and - * then increments the pointer to the first byte after the - * address. An undefined value is stored as all 1's. - * - * Return: void - * - * Programmer: Robb Matzke - * Friday, November 7, 1997 - * - *------------------------------------------------------------------------- - */ -void -H5F_addr_encode_len(size_t addr_len, uint8_t **pp/*in,out*/, haddr_t addr) -{ - unsigned u; /* Local index variable */ - - /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOERR - - HDassert(addr_len); - HDassert(pp && *pp); - - if(H5F_addr_defined(addr)) { - for(u = 0; u < addr_len; u++) { - *(*pp)++ = (uint8_t)(addr & 0xff); - addr >>= 8; - } /* end for */ - HDassert("overflow" && 0 == addr); - } /* end if */ - else { - for(u = 0; u < addr_len; u++) - *(*pp)++ = 0xff; - } /* end else */ - - FUNC_LEAVE_NOAPI_VOID -} /* end H5F_addr_encode_len() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_addr_encode - * - * Purpose: Encodes an address into the buffer pointed to by *PP and - * then increments the pointer to the first byte after the - * address. An undefined value is stored as all 1's. - * - * Return: void - * - * Programmer: Robb Matzke - * Friday, November 7, 1997 - * - *------------------------------------------------------------------------- - */ -void -H5F_addr_encode(const H5F_t *f, uint8_t **pp/*in,out*/, haddr_t addr) -{ - /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOERR - - HDassert(f); - - H5F_addr_encode_len(H5F_SIZEOF_ADDR(f), pp, addr); - - FUNC_LEAVE_NOAPI_VOID -} /* end H5F_addr_encode() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_addr_decode_len - * - * Purpose: Decodes an address from the buffer pointed to by *PP and - * updates the pointer to point to the next byte after the - * address. - * - * If the value read is all 1's then the address is returned - * with an undefined value. - * - * Return: void - * - * Programmer: Robb Matzke - * Friday, November 7, 1997 - * - *------------------------------------------------------------------------- - */ -void -H5F_addr_decode_len(size_t addr_len, const uint8_t **pp/*in,out*/, haddr_t *addr_p/*out*/) -{ - hbool_t all_zero = TRUE; /* True if address was all zeroes */ - unsigned u; /* Local index variable */ - - /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOERR - - HDassert(addr_len); - HDassert(pp && *pp); - HDassert(addr_p); - - /* Reset value in destination */ - *addr_p = 0; - - /* Decode bytes from address */ - for(u = 0; u < addr_len; u++) { - uint8_t c; /* Local decoded byte */ - - /* Get decoded byte (and advance pointer) */ - c = *(*pp)++; - - /* Check for non-undefined address byte value */ - if(c != 0xff) - all_zero = FALSE; - - if(u < sizeof(*addr_p)) { - haddr_t tmp = c; /* Local copy of address, for casting */ - - /* Shift decoded byte to correct position */ - tmp <<= (u * 8); /*use tmp to get casting right */ - - /* Merge into already decoded bytes */ - *addr_p |= tmp; - } /* end if */ - else - if(!all_zero) - HDassert(0 == **pp); /*overflow */ - } /* end for */ - - /* If 'all_zero' is still TRUE, the address was entirely composed of '0xff' - * bytes, which is the encoded form of 'HADDR_UNDEF', so set the destination - * to that value */ - if(all_zero) - *addr_p = HADDR_UNDEF; - - FUNC_LEAVE_NOAPI_VOID -} /* end H5F_addr_decode_len() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_addr_decode - * - * Purpose: Decodes an address from the buffer pointed to by *PP and - * updates the pointer to point to the next byte after the - * address. - * - * If the value read is all 1's then the address is returned - * with an undefined value. - * - * Return: void - * - * Programmer: Robb Matzke - * Friday, November 7, 1997 - * - *------------------------------------------------------------------------- - */ -void -H5F_addr_decode(const H5F_t *f, const uint8_t **pp/*in,out*/, haddr_t *addr_p/*out*/) -{ - /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOERR - - HDassert(f); - - H5F_addr_decode_len(H5F_SIZEOF_ADDR(f), pp, addr_p); - - FUNC_LEAVE_NOAPI_VOID -} /* end H5F_addr_decode() */ - - -/*------------------------------------------------------------------------- * Function: H5Fget_freespace * * Purpose: Retrieves the amount of free space in the file. @@ -2699,8 +1027,6 @@ ssize_t H5Fget_file_image(hid_t file_id, void *buf_ptr, size_t buf_len) { H5F_t *file; /* File object for file ID */ - H5FD_t *fd_ptr; /* file driver */ - haddr_t eoa; /* End of file address */ ssize_t ret_value; /* Return value */ FUNC_ENTER_API(FAIL) @@ -2709,79 +1035,11 @@ H5Fget_file_image(hid_t file_id, void *buf_ptr, size_t buf_len) /* Check args */ if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE))) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID") - if(!file || !file->shared || !file->shared->lf) - HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "file_id yields invalid file pointer") - fd_ptr = file->shared->lf; - if(!fd_ptr->cls) - HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "fd_ptr yields invalid class pointer") - - /* the address space used by the split and multi file drivers is not - * a good fit for this call. Since the plan is to depreciate these - * drivers anyway, don't bother to do a "force fit". - * - * The following clause tests for the multi file driver, and fails - * if the supplied file has the multi file driver as its top level - * file driver. However, this test will not work if there is some - * other file driver sitting on top of the multi file driver. - * - * I'm not sure if this is possible at present, but in all likelyhood, - * it will become possible in the future. On the other hand, we may - * remove the split/multi file drivers before then. - * - * I am leaving this solution in for now, but we should review it, - * and improve the solution if necessary. - * - * JRM -- 11/11/22 - */ - if(HDstrcmp(fd_ptr->cls->name, "multi") == 0) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Not supported for multi file driver.") - - /* While the family file driver is conceptually fully compatible - * with the get file image operation, it sets a file driver message - * in the super block that prevents the image being opened with any - * driver other than the family file driver. Needless to say, this - * rather defeats the purpose of the get file image operation. - * - * While this problem is quire solvable, the required time and - * resources are lacking at present. Hence, for now, we don't - * allow the get file image operation to be perfomed on files - * opened with the family file driver. - * - * Observe that the following test only looks at the top level - * driver, and fails if there is some other driver sitting on to - * of the family file driver. - * - * I don't think this can happen at present, but that may change - * in the future. - * JRM -- 12/21/11 - */ - if(HDstrcmp(fd_ptr->cls->name, "family") == 0) - HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "Not supported for family file driver.") + /* call private get_file_image function */ + if((ret_value = H5F_get_file_image(file, buf_ptr, buf_len)) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get file image") - /* Go get the actual file size */ - if(HADDR_UNDEF == (eoa = H5FD_get_eoa(file->shared->lf, H5FD_MEM_DEFAULT))) - HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get file size") - - /* set ret_value = to eoa -- will overwrite this if appropriate */ - ret_value = (ssize_t)eoa; - - /* test to see if a buffer was provided -- if not, we are done */ - if(buf_ptr != NULL) { - size_t space_needed; /* size of file image */ - - /* Check for buffer too small */ - if((haddr_t)buf_len < eoa) - HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "supplied buffer too small") - - space_needed = (size_t)eoa; - - /* read in the file image */ - /* (Note compensation for base address addition in internal routine) */ - if(H5FD_read(fd_ptr, H5AC_ind_dxpl_g, H5FD_MEM_DEFAULT, 0, space_needed, buf_ptr) < 0) - HGOTO_ERROR(H5E_FILE, H5E_READERROR, FAIL, "file image read request failed") - } /* end if */ - done: FUNC_LEAVE_API(ret_value) } /* H5Fget_file_image() */ @@ -3209,150 +1467,3 @@ H5Fclear_elink_file_cache(hid_t file_id) done: FUNC_LEAVE_API(ret_value) } /* end H5Fclear_elink_file_cache() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_set_grp_btree_shared - * - * Purpose: Set the grp_btree_shared field with a valid ref-count pointer. - * - * Return: Success: SUCCEED - * Failure: FAIL - * - * Programmer: Quincey Koziol - * 7/19/11 - * - *------------------------------------------------------------------------- - */ -herr_t -H5F_set_grp_btree_shared(H5F_t *f, H5UC_t *rc) -{ - /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOERR - - /* Sanity check */ - HDassert(f); - HDassert(f->shared); - HDassert(rc); - - f->shared->grp_btree_shared = rc; - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5F_set_grp_btree_shared() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_set_sohm_addr - * - * Purpose: Set the sohm_addr field with a new value. - * - * Return: Success: SUCCEED - * Failure: FAIL - * - * Programmer: Quincey Koziol - * 7/20/11 - * - *------------------------------------------------------------------------- - */ -herr_t -H5F_set_sohm_addr(H5F_t *f, haddr_t addr) -{ - /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOERR - - /* Sanity check */ - HDassert(f); - HDassert(f->shared); - - f->shared->sohm_addr = addr; - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5F_set_sohm_addr() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_set_sohm_vers - * - * Purpose: Set the sohm_vers field with a new value. - * - * Return: Success: SUCCEED - * Failure: FAIL - * - * Programmer: Quincey Koziol - * 7/20/11 - * - *------------------------------------------------------------------------- - */ -herr_t -H5F_set_sohm_vers(H5F_t *f, unsigned vers) -{ - /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOERR - - /* Sanity check */ - HDassert(f); - HDassert(f->shared); - - f->shared->sohm_vers = vers; - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5F_set_sohm_vers() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_set_sohm_nindexes - * - * Purpose: Set the sohm_nindexes field with a new value. - * - * Return: Success: SUCCEED - * Failure: FAIL - * - * Programmer: Quincey Koziol - * 7/20/11 - * - *------------------------------------------------------------------------- - */ -herr_t -H5F_set_sohm_nindexes(H5F_t *f, unsigned nindexes) -{ - /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOERR - - /* Sanity check */ - HDassert(f); - HDassert(f->shared); - - f->shared->sohm_nindexes = nindexes; - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5F_set_sohm_nindexes() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_set_store_msg_crt_idx - * - * Purpose: Set the store_msg_crt_idx field with a new value. - * - * Return: Success: SUCCEED - * Failure: FAIL - * - * Programmer: Quincey Koziol - * 7/20/11 - * - *------------------------------------------------------------------------- - */ -herr_t -H5F_set_store_msg_crt_idx(H5F_t *f, hbool_t flag) -{ - /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOERR - - /* Sanity check */ - HDassert(f); - HDassert(f->shared); - - f->shared->store_msg_crt_idx = flag; - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5F_set_store_msg_crt_idx() */ - diff --git a/src/H5Fint.c b/src/H5Fint.c new file mode 100644 index 0000000..48a8d1f --- /dev/null +++ b/src/H5Fint.c @@ -0,0 +1,2051 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5F_PACKAGE /*suppress error about including H5Fpkg */ + +/* Interface initialization */ +#define H5_INTERFACE_INIT_FUNC H5F_init_interface + + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Aprivate.h" /* Attributes */ +#include "H5ACprivate.h" /* Metadata cache */ +#include "H5Dprivate.h" /* Datasets */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Fpkg.h" /* File access */ +#include "H5FDprivate.h" /* File drivers */ +#include "H5Gprivate.h" /* Groups */ +#include "H5Iprivate.h" /* IDs */ +#include "H5MFprivate.h" /* File memory management */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5Pprivate.h" /* Property lists */ +#include "H5SMprivate.h" /* Shared Object Header Messages */ +#include "H5Tprivate.h" /* Datatypes */ + + +/****************/ +/* Local Macros */ +/****************/ + +/******************/ +/* Local Typedefs */ +/******************/ + +/* Struct only used by functions H5F_get_objects and H5F_get_objects_cb */ +typedef struct H5F_olist_t { + H5I_type_t obj_type; /* Type of object to look for */ + hid_t *obj_id_list; /* Pointer to the list of open IDs to return */ + size_t *obj_id_count; /* Number of open IDs */ + struct { + hbool_t local; /* Set flag for "local" file searches */ + union { + H5F_file_t *shared; /* Pointer to shared file to look inside */ + const H5F_t *file; /* Pointer to file to look inside */ + } ptr; + } file_info; + size_t list_index; /* Current index in open ID array */ + size_t max_nobjs; /* Maximum # of IDs to put into array */ +} H5F_olist_t; + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + +static int H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key); +static herr_t H5F_build_actual_name(const H5F_t *f, const H5P_genplist_t *fapl, + const char *name, char ** /*out*/ actual_name);/* Declare a free list to manage the H5F_t struct */ + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + +/* Declare a free list to manage the H5F_t struct */ +H5FL_DEFINE(H5F_t); + +/* Declare a free list to manage the H5F_file_t struct */ +H5FL_DEFINE(H5F_file_t); + + +/*------------------------------------------------------------------------- + * Function: H5F_init_interface + * + * Purpose: Initialize interface-specific information. + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Robb Matzke + * Friday, November 20, 1998 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5F_init_interface(void) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_init_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_get_access_plist + * + * Purpose: Returns a copy of the file access property list of the + * specified file. + * + * NOTE: Make sure that, if you are going to overwrite + * information in the copied property list that was + * previously opened and assigned to the property list, then + * you must close it before overwriting the values. + * + * Return: Success: Object ID for a copy of the file access + * property list. + * + * Failure: FAIL + * + * Programmer: Quincey Koziol + * Wednesday, May 25, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +hid_t +H5F_get_access_plist(H5F_t *f, hbool_t app_ref) +{ + H5P_genplist_t *new_plist; /* New property list */ + H5P_genplist_t *old_plist; /* Old property list */ + void *driver_info=NULL; + unsigned efc_size = 0; + hid_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(FAIL) + + /* Check args */ + HDassert(f); + + /* Make a copy of the default file access property list */ + if(NULL == (old_plist = (H5P_genplist_t *)H5I_object(H5P_LST_FILE_ACCESS_ID_g))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list") + if((ret_value = H5P_copy_plist(old_plist, app_ref)) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTINIT, FAIL, "can't copy file access property list") + if(NULL == (new_plist = (H5P_genplist_t *)H5I_object(ret_value))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list") + + /* Copy properties of the file access property list */ + if(H5P_set(new_plist, H5F_ACS_META_CACHE_INIT_CONFIG_NAME, &(f->shared->mdc_initCacheCfg)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set initial metadata cache resize config.") + if(H5P_set(new_plist, H5F_ACS_DATA_CACHE_NUM_SLOTS_NAME, &(f->shared->rdcc_nslots)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set data cache number of slots") + if(H5P_set(new_plist, H5F_ACS_DATA_CACHE_BYTE_SIZE_NAME, &(f->shared->rdcc_nbytes)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set data cache byte size") + if(H5P_set(new_plist, H5F_ACS_PREEMPT_READ_CHUNKS_NAME, &(f->shared->rdcc_w0)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set preempt read chunks") + if(H5P_set(new_plist, H5F_ACS_ALIGN_THRHD_NAME, &(f->shared->threshold)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set alignment threshold") + if(H5P_set(new_plist, H5F_ACS_ALIGN_NAME, &(f->shared->alignment)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set alignment") + if(H5P_set(new_plist, H5F_ACS_GARBG_COLCT_REF_NAME, &(f->shared->gc_ref)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set garbage collect reference") + if(H5P_set(new_plist, H5F_ACS_META_BLOCK_SIZE_NAME, &(f->shared->meta_aggr.alloc_size)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set metadata cache size") + if(H5P_set(new_plist, H5F_ACS_SIEVE_BUF_SIZE_NAME, &(f->shared->sieve_buf_size)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't sieve buffer size") + if(H5P_set(new_plist, H5F_ACS_SDATA_BLOCK_SIZE_NAME, &(f->shared->sdata_aggr.alloc_size)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set 'small data' cache size") + if(H5P_set(new_plist, H5F_ACS_LATEST_FORMAT_NAME, &(f->shared->latest_format)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set 'latest format' flag") + if(f->shared->efc) + efc_size = H5F_efc_max_nfiles(f->shared->efc); + if(H5P_set(new_plist, H5F_ACS_EFC_SIZE_NAME, &efc_size) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set elink file cache size") + + /* + * Since we're resetting the driver ID and info, close them if they + * exist in this new property list. + */ + if(H5P_facc_close(ret_value, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTFREE, FAIL, "can't free the old driver information") + + /* Increment the reference count on the driver ID and insert it into the property list */ + if(H5I_inc_ref(f->shared->lf->driver_id, FALSE) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINC, FAIL, "unable to increment ref count on VFL driver") + if(H5P_set(new_plist, H5F_ACS_FILE_DRV_ID_NAME, &(f->shared->lf->driver_id)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file driver ID") + + /* Set the driver "info" in the property list */ + driver_info = H5FD_fapl_get(f->shared->lf); + if(driver_info != NULL && H5P_set(new_plist, H5F_ACS_FILE_DRV_INFO_NAME, &driver_info) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file driver info") + + /* Set the file close degree appropriately */ + if(f->shared->fc_degree == H5F_CLOSE_DEFAULT && H5P_set(new_plist, H5F_ACS_CLOSE_DEGREE_NAME, &(f->shared->lf->cls->fc_degree)) < 0) { + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file close degree") + } else if(f->shared->fc_degree != H5F_CLOSE_DEFAULT && H5P_set(new_plist, H5F_ACS_CLOSE_DEGREE_NAME, &(f->shared->fc_degree)) < 0) { + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file close degree") + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_get_access_plist() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_get_obj_count + * + * Purpose: Private function return the number of opened object IDs + * (files, datasets, groups, datatypes) in the same file. + * + * Return: SUCCEED on success, FAIL on failure. + * + * Programmer: Raymond Lu + * Wednesday, Dec 5, 2001 + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref, size_t *obj_id_count_ptr) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity check */ + HDassert(obj_id_count_ptr); + + /* Perform the query */ + if((ret_value = H5F_get_objects(f, types, 0, NULL, app_ref, obj_id_count_ptr)) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_objects failed") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_get_obj_count() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_get_obj_ids + * + * Purpose: Private function to return a list of opened object IDs. + * + * Return: Non-negative on success; can't fail. + * + * Programmer: Raymond Lu + * Wednesday, Dec 5, 2001 + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *oid_list, hbool_t app_ref, size_t *obj_id_count_ptr) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity check */ + HDassert(obj_id_count_ptr); + + /* Perform the query */ + if((ret_value = H5F_get_objects(f, types, max_objs, oid_list, app_ref, obj_id_count_ptr)) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_objects failed") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_get_obj_ids() */ + + +/*--------------------------------------------------------------------------- + * Function: H5F_get_objects + * + * Purpose: This function is called by H5F_get_obj_count or + * H5F_get_obj_ids to get number of object IDs and/or a + * list of opened object IDs (in return value). + * Return: Non-negative on success; Can't fail. + * + * Programmer: Raymond Lu + * Wednesday, Dec 5, 2001 + * + *--------------------------------------------------------------------------- + */ +herr_t +H5F_get_objects(const H5F_t *f, unsigned types, size_t max_nobjs, hid_t *obj_id_list, hbool_t app_ref, size_t *obj_id_count_ptr) +{ + size_t obj_id_count=0; /* Number of open IDs */ + H5F_olist_t olist; /* Structure to hold search results */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Sanity check */ + HDassert(obj_id_count_ptr); + + /* Set up search information */ + olist.obj_id_list = (max_nobjs==0 ? NULL : obj_id_list); + olist.obj_id_count = &obj_id_count; + olist.list_index = 0; + olist.max_nobjs = max_nobjs; + + /* Determine if we are searching for local or global objects */ + if(types & H5F_OBJ_LOCAL) { + olist.file_info.local = TRUE; + olist.file_info.ptr.file = f; + } /* end if */ + else { + olist.file_info.local = FALSE; + olist.file_info.ptr.shared = f ? f->shared : NULL; + } /* end else */ + + /* Iterate through file IDs to count the number, and put their + * IDs on the object list. */ + if(types & H5F_OBJ_FILE) { + olist.obj_type = H5I_FILE; + if(H5I_iterate(H5I_FILE, H5F_get_objects_cb, &olist, app_ref) < 0) + HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(1)") + } /* end if */ + + /* If the caller just wants to count the number of objects (OLIST.MAX_NOBJS is zero), + * or the caller wants to get the list of IDs and the list isn't full, + * search through dataset IDs to count number of datasets, and put their + * IDs on the object list */ + if(!olist.max_nobjs || (olist.max_nobjs && olist.list_indexobj_type == H5I_FILE) { + if((olist->file_info.local && + (!olist->file_info.ptr.file || (olist->file_info.ptr.file && (H5F_t*)obj_ptr == olist->file_info.ptr.file) )) + || (!olist->file_info.local && + ( !olist->file_info.ptr.shared || (olist->file_info.ptr.shared && ((H5F_t*)obj_ptr)->shared == olist->file_info.ptr.shared) ))) { + add_obj = TRUE; + } + } /* end if */ + else { /* either count opened object IDs or put the IDs on the list */ + H5O_loc_t *oloc; /* Group entry info for object */ + + switch(olist->obj_type) { + case H5I_ATTR: + oloc = H5A_oloc((H5A_t *)obj_ptr); + break; + + case H5I_GROUP: + oloc = H5G_oloc((H5G_t *)obj_ptr); + break; + + case H5I_DATASET: + oloc = H5D_oloc((H5D_t *)obj_ptr); + break; + + case H5I_DATATYPE: + if(H5T_is_named((H5T_t*)obj_ptr)==TRUE) + oloc = H5T_oloc((H5T_t*)obj_ptr); + else + oloc = NULL; + break; + + case H5I_UNINIT: + case H5I_BADID: + case H5I_FILE: + case H5I_DATASPACE: + case H5I_REFERENCE: + case H5I_VFL: + case H5I_GENPROP_CLS: + case H5I_GENPROP_LST: + case H5I_ERROR_CLASS: + case H5I_ERROR_MSG: + case H5I_ERROR_STACK: + case H5I_NTYPES: + default: + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5_ITER_ERROR, "unknown data object") + } /* end switch */ + + if((olist->file_info.local && + ( (!olist->file_info.ptr.file && olist->obj_type == H5I_DATATYPE && H5T_is_immutable((H5T_t *)obj_ptr) == FALSE) + || (!olist->file_info.ptr.file && olist->obj_type != H5I_DATATYPE) + || (oloc && oloc->file == olist->file_info.ptr.file))) + || (!olist->file_info.local && + ((!olist->file_info.ptr.shared && olist->obj_type == H5I_DATATYPE && H5T_is_immutable((H5T_t *)obj_ptr) == FALSE) + || (!olist->file_info.ptr.shared && olist->obj_type != H5I_DATATYPE) + || (oloc && oloc->file && oloc->file->shared == olist->file_info.ptr.shared)))) { + add_obj = TRUE; + } /* end if */ + } /* end else */ + + if(TRUE==add_obj) { + /* Add the object's ID to the ID list, if appropriate */ + if(olist->obj_id_list) { + olist->obj_id_list[olist->list_index] = obj_id; + olist->list_index++; + } /* end if */ + + /* Increment the number of open objects */ + if(olist->obj_id_count) + (*olist->obj_id_count)++; + + /* Check if we've filled up the array. Return H5_ITER_STOP only if + * we have filled up the array. Otherwise return H5_ITER_CONT(RET_VALUE is + * preset to H5_ITER_CONT) because H5I_iterate needs the return value of + * H5_ITER_CONT to continue the iteration. */ + if(olist->max_nobjs>0 && olist->list_index>=olist->max_nobjs) + HGOTO_DONE(H5_ITER_STOP) /* Indicate that the iterator should stop */ + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_get_objects_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_is_hdf5 + * + * Purpose: Check the file signature to detect an HDF5 file. + * + * Bugs: This function is not robust: it only uses the default file + * driver when attempting to open the file when in fact it + * should use all known file drivers. + * + * Return: Success: TRUE/FALSE + * + * Failure: Negative + * + * Programmer: Unknown + * + * Modifications: + * Robb Matzke, 1999-08-02 + * Rewritten to use the virtual file layer. + *------------------------------------------------------------------------- + */ +htri_t +H5F_is_hdf5(const char *name) +{ + H5FD_t *file = NULL; /* Low-level file struct */ + haddr_t sig_addr; /* Addess of hdf5 file signature */ + htri_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Open the file at the virtual file layer */ + if(NULL == (file = H5FD_open(name, H5F_ACC_RDONLY, H5P_FILE_ACCESS_DEFAULT, HADDR_UNDEF))) + HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to open file") + + /* The file is an hdf5 file if the hdf5 file signature can be found */ + if(H5FD_locate_signature(file, H5AC_ind_dxpl_g, &sig_addr) < 0) + HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "unable to locate file signature") + ret_value = (HADDR_UNDEF != sig_addr); + +done: + /* Close the file */ + if(file) + if(H5FD_close(file) < 0 && ret_value >= 0) + HDONE_ERROR(H5E_IO, H5E_CANTCLOSEFILE, FAIL, "unable to close file") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_is_hdf5() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_new + * + * Purpose: Creates a new file object and initializes it. The + * H5Fopen and H5Fcreate functions then fill in various + * fields. If SHARED is a non-null pointer then the shared info + * to which it points has the reference count incremented. + * Otherwise a new, empty shared info struct is created and + * initialized with the specified file access property list. + * + * Errors: + * + * Return: Success: Ptr to a new file struct. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jul 18 1997 + * + *------------------------------------------------------------------------- + */ +H5F_t * +H5F_new(H5F_file_t *shared, unsigned flags, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf) +{ + H5F_t *f = NULL, *ret_value; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (f = H5FL_CALLOC(H5F_t))) + HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, NULL, "can't allocate top file structure") + f->file_id = -1; + + if(shared) { + HDassert(lf == NULL); + f->shared = shared; + } /* end if */ + else { + H5P_genplist_t *plist; /* Property list */ + unsigned efc_size; /* External file cache size */ + size_t u; /* Local index variable */ + + HDassert(lf != NULL); + if(NULL == (f->shared = H5FL_CALLOC(H5F_file_t))) + HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, NULL, "can't allocate shared file structure") + + f->shared->flags = flags; + f->shared->sohm_addr = HADDR_UNDEF; + f->shared->sohm_vers = HDF5_SHAREDHEADER_VERSION; + for(u = 0; u < NELMTS(f->shared->fs_addr); u++) + f->shared->fs_addr[u] = HADDR_UNDEF; + f->shared->accum.loc = HADDR_UNDEF; + f->shared->lf = lf; + + /* + * Copy the file creation and file access property lists into the + * new file handle. We do this early because some values might need + * to change as the file is being opened. + */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(fcpl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not property list") + f->shared->fcpl_id = H5P_copy_plist(plist, FALSE); + + /* Get the FCPL values to cache */ + if(H5P_get(plist, H5F_CRT_ADDR_BYTE_NUM_NAME, &f->shared->sizeof_addr) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get byte number for address") + if(H5P_get(plist, H5F_CRT_OBJ_BYTE_NUM_NAME, &f->shared->sizeof_size) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get byte number for object size") + if(H5P_get(plist, H5F_CRT_SHMSG_NINDEXES_NAME, &f->shared->sohm_nindexes) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get number of SOHM indexes") + HDassert(f->shared->sohm_nindexes < 255); + if(H5P_get(plist, H5F_CRT_FILE_SPACE_STRATEGY_NAME, &f->shared->fs_strategy) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get file space strategy") + if(H5P_get(plist, H5F_CRT_FREE_SPACE_THRESHOLD_NAME, &f->shared->fs_threshold) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get free-space section threshold") + + /* Get the FAPL values to cache */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not file access property list") + if(H5P_get(plist, H5F_ACS_META_CACHE_INIT_CONFIG_NAME, &(f->shared->mdc_initCacheCfg)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get initial metadata cache resize config") + if(H5P_get(plist, H5F_ACS_DATA_CACHE_NUM_SLOTS_NAME, &(f->shared->rdcc_nslots)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get data cache number of slots") + if(H5P_get(plist, H5F_ACS_DATA_CACHE_BYTE_SIZE_NAME, &(f->shared->rdcc_nbytes)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get data cache byte size") + if(H5P_get(plist, H5F_ACS_PREEMPT_READ_CHUNKS_NAME, &(f->shared->rdcc_w0)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get preempt read chunk") + if(H5P_get(plist, H5F_ACS_ALIGN_THRHD_NAME, &(f->shared->threshold)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get alignment threshold") + if(H5P_get(plist, H5F_ACS_ALIGN_NAME, &(f->shared->alignment)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get alignment") + if(H5P_get(plist, H5F_ACS_GARBG_COLCT_REF_NAME,&(f->shared->gc_ref)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get garbage collect reference") + if(H5P_get(plist, H5F_ACS_SIEVE_BUF_SIZE_NAME, &(f->shared->sieve_buf_size)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get sieve buffer size") + if(H5P_get(plist, H5F_ACS_LATEST_FORMAT_NAME, &(f->shared->latest_format)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get 'latest format' flag") + if(H5P_get(plist, H5F_ACS_META_BLOCK_SIZE_NAME, &(f->shared->meta_aggr.alloc_size)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get metadata cache size") + f->shared->meta_aggr.feature_flag = H5FD_FEAT_AGGREGATE_METADATA; + if(H5P_get(plist, H5F_ACS_SDATA_BLOCK_SIZE_NAME, &(f->shared->sdata_aggr.alloc_size)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get 'small data' cache size") + f->shared->sdata_aggr.feature_flag = H5FD_FEAT_AGGREGATE_SMALLDATA; + if(H5P_get(plist, H5F_ACS_EFC_SIZE_NAME, &efc_size) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get elink file cache size") + if(efc_size > 0) + if(NULL == (f->shared->efc = H5F_efc_create(efc_size))) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "can't create external file cache") + + /* Get the VFD values to cache */ + f->shared->maxaddr = H5FD_get_maxaddr(lf); + if(!H5F_addr_defined(f->shared->maxaddr)) + HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad maximum address from VFD") + if(H5FD_get_feature_flags(lf, &f->shared->feature_flags) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get feature flags from VFD") + if(H5FD_get_fs_type_map(lf, f->shared->fs_type_map) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get free space type mapping from VFD") + if(H5MF_init_merge_flags(f) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "problem initializing free space merge flags") + f->shared->tmp_addr = f->shared->maxaddr; + /* Disable temp. space allocation for parallel I/O (for now) */ + /* (When we've arranged to have the relocated metadata addresses (and + * sizes) broadcast during the "end of epoch" metadata operations, + * this can be enabled - QAK) + */ + /* (This should be disabled when the metadata journaling branch is + * merged into the trunk and journaling is enabled, at least until + * we make it work. - QAK) + */ + f->shared->use_tmp_space = !H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI); + + /* + * Create a metadata cache with the specified number of elements. + * The cache might be created with a different number of elements and + * the access property list should be updated to reflect that. + */ + if(H5AC_create(f, &(f->shared->mdc_initCacheCfg)) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create metadata cache") + + /* Create the file's "open object" information */ + if(H5FO_create(f) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create open object data structure") + + /* Add new "shared" struct to list of open files */ + if(H5F_sfile_add(f->shared) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to append to list of open files") + } /* end else */ + + f->shared->nrefs++; + + /* Create the file's "top open object" information */ + if(H5FO_top_create(f) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create open object data structure") + + /* Set return value */ + ret_value = f; + +done: + if(!ret_value && f) { + if(!shared) { + /* Attempt to clean up some of the shared file structures */ + if(f->shared->efc) + if(H5F_efc_destroy(f->shared->efc) < 0) + HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, NULL, "can't destroy external file cache") + if(f->shared->fcpl_id > 0) + if(H5I_dec_ref(f->shared->fcpl_id) < 0) + HDONE_ERROR(H5E_FILE, H5E_CANTDEC, NULL, "can't close property list") + + f->shared = H5FL_FREE(H5F_file_t, f->shared); + } /* end if */ + f = H5FL_FREE(H5F_t, f); + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_new() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_dest + * + * Purpose: Destroys a file structure. This function flushes the cache + * but doesn't do any other cleanup other than freeing memory + * for the file struct. The shared info for the file is freed + * only when its reference count reaches zero. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jul 18 1997 + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_dest(H5F_t *f, hid_t dxpl_id, hbool_t flush) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Sanity check */ + HDassert(f); + HDassert(f->shared); + + if(1 == f->shared->nrefs) { + H5F_io_info_t fio_info; /* I/O info for operation */ + + /* Flush at this point since the file will be closed. + * Only try to flush the file if it was opened with write access, and if + * the caller requested a flush. + */ + if((H5F_ACC_RDWR & H5F_INTENT(f)) && flush) + if(H5F_flush(f, dxpl_id, TRUE) < 0) + /* Push error, but keep going*/ + HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache") + + /* Release the external file cache */ + if(f->shared->efc) { + if(H5F_efc_destroy(f->shared->efc) < 0) + /* Push error, but keep going*/ + HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't destroy external file cache") + f->shared->efc = NULL; + } /* end if */ + + /* Release objects that depend on the superblock being initialized */ + if(f->shared->sblock) { + /* Shutdown file free space manager(s) */ + /* (We should release the free space information now (before truncating + * the file and before the metadata cache is shut down) since the + * free space manager is holding some data structures in memory + * and also because releasing free space can shrink the file's + * 'eoa' value) + */ + if(H5F_ACC_RDWR & H5F_INTENT(f)) { + if(H5MF_close(f, dxpl_id) < 0) + /* Push error, but keep going*/ + HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release file free space info") + + /* Flush the file again (if requested), as shutting down the + * free space manager may dirty some data structures again. + */ + if(flush) + if(H5F_flush(f, dxpl_id, TRUE) < 0) + /* Push error, but keep going*/ + HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache") + } /* end if */ + + /* Unpin the superblock, since we're about to destroy the cache */ + if(H5AC_unpin_entry(f->shared->sblock) < 0) + /* Push error, but keep going*/ + HDONE_ERROR(H5E_FSPACE, H5E_CANTUNPIN, FAIL, "unable to unpin superblock") + f->shared->sblock = NULL; + } /* end if */ + + /* Remove shared file struct from list of open files */ + if(H5F_sfile_remove(f->shared) < 0) + /* Push error, but keep going*/ + HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file") + + /* Shutdown the metadata cache */ + if(H5AC_dest(f, dxpl_id)) + /* Push error, but keep going*/ + HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file") + + /* + * Do not close the root group since we didn't count it, but free + * the memory associated with it. + */ + if(f->shared->root_grp) { + /* Free the root group */ + if(H5G_root_free(f->shared->root_grp) < 0) + /* Push error, but keep going*/ + HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file") + f->shared->root_grp = NULL; + } /* end if */ + + /* Set up I/O info for operation */ + fio_info.f = f; + if(NULL == (fio_info.dxpl = (H5P_genplist_t *)H5I_object(dxpl_id))) + HDONE_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list") + + /* Destroy other components of the file */ + if(H5F__accum_reset(&fio_info, TRUE) < 0) + /* Push error, but keep going*/ + HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file") + if(H5FO_dest(f) < 0) + /* Push error, but keep going*/ + HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file") + f->shared->cwfs = (struct H5HG_heap_t **)H5MM_xfree(f->shared->cwfs); + if(H5G_node_close(f) < 0) + /* Push error, but keep going*/ + HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file") + + /* Destroy file creation properties */ + if(H5I_GENPROP_LST != H5I_get_type(f->shared->fcpl_id)) + /* Push error, but keep going*/ + HDONE_ERROR(H5E_FILE, H5E_BADTYPE, FAIL, "not a property list") + if(H5I_dec_ref(f->shared->fcpl_id) < 0) + /* Push error, but keep going*/ + HDONE_ERROR(H5E_FILE, H5E_CANTDEC, FAIL, "can't close property list") + + /* Only truncate the file on an orderly close, with write-access */ + if(f->closing && (H5F_ACC_RDWR & H5F_INTENT(f))) { + /* Truncate the file to the current allocated size */ + if(H5FD_truncate(f->shared->lf, dxpl_id, (unsigned)TRUE) < 0) + /* Push error, but keep going*/ + HDONE_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "low level truncate failed") + } /* end if */ + + /* Close the file */ + if(H5FD_close(f->shared->lf) < 0) + /* Push error, but keep going*/ + HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close file") + + /* Free mount table */ + f->shared->mtab.child = (H5F_mount_t *)H5MM_xfree(f->shared->mtab.child); + f->shared->mtab.nalloc = 0; + + /* Destroy shared file struct */ + f->shared = (H5F_file_t *)H5FL_FREE(H5F_file_t, f->shared); + + } else if(f->shared->nrefs > 0) { + /* + * There are other references to the shared part of the file. + * Only decrement the reference count. + */ + --f->shared->nrefs; + } + + /* Free the non-shared part of the file */ + f->open_name = (char *)H5MM_xfree(f->open_name); + f->actual_name = (char *)H5MM_xfree(f->actual_name); + f->extpath = (char *)H5MM_xfree(f->extpath); + if(H5FO_top_dest(f) < 0) + HDONE_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "problems closing file") + f->shared = NULL; + f = H5FL_FREE(H5F_t, f); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_dest() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_open + * + * Purpose: Opens (or creates) a file. This function understands the + * following flags which are similar in nature to the Posix + * open(2) flags. + * + * H5F_ACC_RDWR: Open with read/write access. If the file is + * currently open for read-only access then it + * will be reopened. Absence of this flag + * implies read-only access. + * + * H5F_ACC_CREAT: Create a new file if it doesn't exist yet. + * The permissions are 0666 bit-wise AND with + * the current umask. H5F_ACC_WRITE must also + * be specified. + * + * H5F_ACC_EXCL: This flag causes H5F_open() to fail if the + * file already exists. + * + * H5F_ACC_TRUNC: The file is truncated and a new HDF5 superblock + * is written. This operation will fail if the + * file is already open. + * + * Unlinking the file name from the group directed graph while + * the file is opened causes the file to continue to exist but + * one will not be able to upgrade the file from read-only + * access to read-write access by reopening it. Disk resources + * for the file are released when all handles to the file are + * closed. NOTE: This paragraph probably only applies to Unix; + * deleting the file name in other OS's has undefined results. + * + * The CREATE_PARMS argument is optional. A null pointer will + * cause the default file creation parameters to be used. + * + * The ACCESS_PARMS argument is optional. A null pointer will + * cause the default file access parameters to be used. + * + * Return: Success: A new file pointer. + * Failure: NULL + * + * Programmer: Robb Matzke + * Tuesday, September 23, 1997 + * + *------------------------------------------------------------------------- + */ +H5F_t * +H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, + hid_t dxpl_id) +{ + H5F_t *file = NULL; /*the success return value */ + H5F_file_t *shared = NULL; /*shared part of `file' */ + H5FD_t *lf = NULL; /*file driver part of `shared' */ + unsigned tent_flags; /*tentative flags */ + H5FD_class_t *drvr; /*file driver class info */ + H5P_genplist_t *a_plist; /*file access property list */ + H5F_close_degree_t fc_degree; /*file close degree */ + H5F_t *ret_value; /*actual return value */ + + FUNC_ENTER_NOAPI(NULL) + + /* + * If the driver has a `cmp' method then the driver is capable of + * determining when two file handles refer to the same file and the + * library can insure that when the application opens a file twice + * that the two handles coordinate their operations appropriately. + * Otherwise it is the application's responsibility to never open the + * same file more than once at a time. + */ + if(NULL == (drvr = H5FD_get_class(fapl_id))) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "unable to retrieve VFL class") + + /* + * Opening a file is a two step process. First we try to open the + * file in a way which doesn't affect its state (like not truncating + * or creating it) so we can compare it with files that are already + * open. If that fails then we try again with the full set of flags + * (only if they're different than the original failed attempt). + * However, if the file driver can't distinquish between files then + * there's no reason to open the file tentatively because it's the + * application's responsibility to prevent this situation (there's no + * way for us to detect it here anyway). + */ + if(drvr->cmp) + tent_flags = flags & ~(H5F_ACC_CREAT|H5F_ACC_TRUNC|H5F_ACC_EXCL); + else + tent_flags = flags; + + if(NULL == (lf = H5FD_open(name, tent_flags, fapl_id, HADDR_UNDEF))) { + if(tent_flags == flags) { +#ifndef H5_USING_MEMCHECKER + time_t mytime = HDtime(NULL); + + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file: time = %s, name = '%s', tent_flags = %x", HDctime(&mytime), name, tent_flags) +#else /* H5_USING_MEMCHECKER */ + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file: name = '%s', tent_flags = %x", name, tent_flags) +#endif /* H5_USING_MEMCHECKER */ + } /* end if */ + H5E_clear_stack(NULL); + tent_flags = flags; + if(NULL == (lf = H5FD_open(name, tent_flags, fapl_id, HADDR_UNDEF))) { +#ifndef H5_USING_MEMCHECKER + time_t mytime = HDtime(NULL); + + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file: time = %s, name = '%s', tent_flags = %x", HDctime(&mytime), name, tent_flags) +#else /* H5_USING_MEMCHECKER */ + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file: name = '%s', tent_flags = %x", name, tent_flags) +#endif /* H5_USING_MEMCHECKER */ + } /* end if */ + } /* end if */ + + /* Is the file already open? */ + if((shared = H5F_sfile_search(lf)) != NULL) { + /* + * The file is already open, so use that one instead of the one we + * just opened. We only one one H5FD_t* per file so one doesn't + * confuse the other. But fail if this request was to truncate the + * file (since we can't do that while the file is open), or if the + * request was to create a non-existent file (since the file already + * exists), or if the new request adds write access (since the + * readers don't expect the file to change under them). + */ + if(H5FD_close(lf) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to close low-level file info") + if(flags & H5F_ACC_TRUNC) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to truncate a file which is already open") + if(flags & H5F_ACC_EXCL) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "file exists") + if((flags & H5F_ACC_RDWR) && 0 == (shared->flags & H5F_ACC_RDWR)) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "file is already open for read-only") + + /* Allocate new "high-level" file struct */ + if((file = H5F_new(shared, flags, fcpl_id, fapl_id, NULL)) == NULL) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to create new file object") + } /* end if */ + else { + /* Check if tentative open was good enough */ + if(flags != tent_flags) { + /* + * This file is not yet open by the library and the flags we used to + * open it are different than the desired flags. Close the tentative + * file and open it for real. + */ + if(H5FD_close(lf) < 0) { + file = NULL; /*to prevent destruction of wrong file*/ + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to close low-level file info") + } /* end if */ + if(NULL == (lf = H5FD_open(name, flags, fapl_id, HADDR_UNDEF))) { + file = NULL; /*to prevent destruction of wrong file*/ + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file") + } /* end if */ + } /* end if */ + + if(NULL == (file = H5F_new(NULL, flags, fcpl_id, fapl_id, lf))) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to create new file object") + } /* end else */ + + /* Retain the name the file was opened with */ + file->open_name = H5MM_xstrdup(name); + + /* Short cuts */ + shared = file->shared; + lf = shared->lf; + + /* + * Read or write the file superblock, depending on whether the file is + * empty or not. + */ + if(0 == H5FD_get_eof(lf) && (flags & H5F_ACC_RDWR)) { + /* + * We've just opened a fresh new file (or truncated one). We need + * to create & write the superblock. + */ + + /* Initialize information about the superblock and allocate space for it */ + /* (Writes superblock extension messages, if there are any) */ + if(H5F_super_init(file, dxpl_id) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to allocate file superblock") + + /* Create and open the root group */ + /* (This must be after the space for the superblock is allocated in + * the file, since the superblock must be at offset 0) + */ + if(H5G_mkroot(file, dxpl_id, TRUE) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create/open root group") + } else if (1 == shared->nrefs) { + /* Read the superblock if it hasn't been read before. */ + if(H5F_super_read(file, dxpl_id) < 0) + HGOTO_ERROR(H5E_FILE, H5E_READERROR, NULL, "unable to read superblock") + + /* Open the root group */ + if(H5G_mkroot(file, dxpl_id, FALSE) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to read root group") + } /* end if */ + + /* Get the file access property list, for future queries */ + if(NULL == (a_plist = (H5P_genplist_t *)H5I_object(fapl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not file access property list") + + /* + * Decide the file close degree. If it's the first time to open the + * file, set the degree to access property list value; if it's the + * second time or later, verify the access property list value matches + * the degree in shared file structure. + */ + if(H5P_get(a_plist, H5F_ACS_CLOSE_DEGREE_NAME, &fc_degree) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get file close degree") + + if(shared->nrefs == 1) { + if(fc_degree == H5F_CLOSE_DEFAULT) + shared->fc_degree = lf->cls->fc_degree; + else + shared->fc_degree = fc_degree; + } else if(shared->nrefs > 1) { + if(fc_degree == H5F_CLOSE_DEFAULT && shared->fc_degree != lf->cls->fc_degree) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "file close degree doesn't match") + if(fc_degree != H5F_CLOSE_DEFAULT && fc_degree != shared->fc_degree) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "file close degree doesn't match") + } /* end if */ + + /* Formulate the absolute path for later search of target file for external links */ + if(H5_build_extpath(name, &file->extpath) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to build extpath") + + /* Formulate the actual file name, after following symlinks, etc. */ + if(H5F_build_actual_name(file, a_plist, name, &file->actual_name) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to build actual name") + + /* Success */ + ret_value = file; + +done: + if(!ret_value && file) + if(H5F_dest(file, dxpl_id, FALSE) < 0) + HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, NULL, "problems closing file") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_open() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_flush + * + * Purpose: Flushes cached data. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 29 1997 + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_flush(H5F_t *f, hid_t dxpl_id, hbool_t closing) +{ + H5F_io_info_t fio_info; /* I/O info for operation */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity check arguments */ + HDassert(f); + + /* Flush any cached dataset storage raw data */ + if(H5D_flush(f, dxpl_id) < 0) + /* Push error, but keep going*/ + HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush dataset cache") + + /* Release any space allocated to space aggregators, so that the eoa value + * corresponds to the end of the space written to in the file. + */ + /* (needs to happen before cache flush, with superblock write, since the + * 'eoa' value is written in superblock -QAK) + */ + if(H5MF_free_aggrs(f, dxpl_id) < 0) + /* Push error, but keep going*/ + HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release file space") + + /* Flush the entire metadata cache */ + if(H5AC_flush(f, dxpl_id) < 0) + /* Push error, but keep going*/ + HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush metadata cache") + + /* Set up I/O info for operation */ + fio_info.f = f; + if(NULL == (fio_info.dxpl = (H5P_genplist_t *)H5I_object(dxpl_id))) + HDONE_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list") + + /* Flush out the metadata accumulator */ + if(H5F__accum_flush(&fio_info) < 0) + /* Push error, but keep going*/ + HDONE_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "unable to flush metadata accumulator") + + /* Flush file buffers to disk. */ + if(H5FD_flush(f->shared->lf, dxpl_id, closing) < 0) + /* Push error, but keep going*/ + HDONE_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "low level flush failed") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_flush() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_close + * + * Purpose: Closes a file or causes the close operation to be pended. + * This function is called two ways: from the API it gets called + * by H5Fclose->H5I_dec_ref->H5F_close when H5I_dec_ref() + * decrements the file ID reference count to zero. The file ID + * is removed from the H5I_FILE group by H5I_dec_ref() just + * before H5F_close() is called. If there are open object + * headers then the close is pended by moving the file to the + * H5I_FILE_CLOSING ID group (the f->closing contains the ID + * assigned to file). + * + * This function is also called directly from H5O_close() when + * the last object header is closed for the file and the file + * has a pending close. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Tuesday, September 23, 1997 + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_close(H5F_t *f) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Sanity check */ + HDassert(f); + HDassert(f->file_id > 0); /* This routine should only be called when a file ID's ref count drops to zero */ + + /* Perform checks for "semi" file close degree here, since closing the + * file is not allowed if there are objects still open */ + if(f->shared->fc_degree == H5F_CLOSE_SEMI) { + unsigned nopen_files = 0; /* Number of open files in file/mount hierarchy */ + unsigned nopen_objs = 0; /* Number of open objects in file/mount hierarchy */ + + /* Get the number of open objects and open files on this file/mount hierarchy */ + if(H5F_mount_count_ids(f, &nopen_files, &nopen_objs) < 0) + HGOTO_ERROR(H5E_SYM, H5E_MOUNT, FAIL, "problem checking mount hierarchy") + + /* If there are no other file IDs open on this file/mount hier., but + * there are still open objects, issue an error and bail out now, + * without decrementing the file ID's reference count and triggering + * a "real" attempt at closing the file */ + if(nopen_files == 1 && nopen_objs > 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, there are objects still open") + } /* end if */ + + /* Reset the file ID for this file */ + f->file_id = -1; + + /* Attempt to close the file/mount hierarchy */ + if(H5F_try_close(f) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_close() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_try_close + * + * Purpose: Attempts to close a file due to one of several actions: + * - The reference count on the file ID dropped to zero + * - The last open object was closed in the file + * - The file was unmounted + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, July 19, 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_try_close(H5F_t *f) +{ + unsigned nopen_files = 0; /* Number of open files in file/mount hierarchy */ + unsigned nopen_objs = 0; /* Number of open objects in file/mount hierarchy */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Sanity check */ + HDassert(f); + HDassert(f->shared); + + /* Check if this file is already in the process of closing */ + if(f->closing) + HGOTO_DONE(SUCCEED) + + /* Get the number of open objects and open files on this file/mount hierarchy */ + if(H5F_mount_count_ids(f, &nopen_files, &nopen_objs) < 0) + HGOTO_ERROR(H5E_SYM, H5E_MOUNT, FAIL, "problem checking mount hierarchy") + + /* + * Close file according to close degree: + * + * H5F_CLOSE_WEAK: if there are still objects open, wait until + * they are all closed. + * H5F_CLOSE_SEMI: if there are still objects open, return fail; + * otherwise, close file. + * H5F_CLOSE_STRONG: if there are still objects open, close them + * first, then close file. + */ + switch(f->shared->fc_degree) { + case H5F_CLOSE_WEAK: + /* + * If file or object IDS are still open then delay deletion of + * resources until they have all been closed. Flush all + * caches and update the object header anyway so that failing to + * close all objects isn't a major problem. + */ + if((nopen_files + nopen_objs) > 0) + HGOTO_DONE(SUCCEED) + break; + + case H5F_CLOSE_SEMI: + /* Can leave safely if file IDs are still open on this file */ + if(nopen_files > 0) + HGOTO_DONE(SUCCEED) + + /* Sanity check: If close degree if "semi" and we have gotten this + * far and there are objects left open, bail out now */ + HDassert(nopen_files == 0 && nopen_objs == 0); + + /* If we've gotten this far (ie. there are no open objects in the file), fall through to flush & close */ + break; + + case H5F_CLOSE_STRONG: + /* If there are other open files in the hierarchy, we can leave now */ + if(nopen_files > 0) + HGOTO_DONE(SUCCEED) + + /* If we've gotten this far (ie. there are no open file IDs in the file/mount hierarchy), fall through to flush & close */ + break; + + case H5F_CLOSE_DEFAULT: + default: + HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, unknown file close degree") + } /* end switch */ + + /* Mark this file as closing (prevents re-entering file shutdown code below) */ + f->closing = TRUE; + + /* If the file close degree is "strong", close all the open objects in this file */ + if(f->shared->fc_degree == H5F_CLOSE_STRONG) { + HDassert(nopen_files == 0); + + /* Forced close of all opened objects in this file */ + if(f->nopen_objs > 0) { + size_t obj_count; /* # of open objects */ + hid_t objs[128]; /* Array of objects to close */ + herr_t result; /* Local result from obj ID query */ + size_t u; /* Local index variable */ + + /* Get the list of IDs of open dataset, group, & attribute objects */ + while((result = H5F_get_obj_ids(f, H5F_OBJ_LOCAL | H5F_OBJ_DATASET | H5F_OBJ_GROUP | H5F_OBJ_ATTR, (int)(sizeof(objs) / sizeof(objs[0])), objs, FALSE, &obj_count)) <= 0 + && obj_count != 0 ) { + + /* Try to close all the open objects in this file */ + for(u = 0; u < obj_count; u++) + if(H5I_dec_ref(objs[u]) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object") + } /* end while */ + if(result < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_obj_ids failed(1)") + + /* Get the list of IDs of open named datatype objects */ + /* (Do this separately from the dataset & attribute IDs, because + * they could be using one of the named datatypes and then the + * open named datatype ID will get closed twice) + */ + while((result = H5F_get_obj_ids(f, H5F_OBJ_LOCAL | H5F_OBJ_DATATYPE, (int)(sizeof(objs) / sizeof(objs[0])), objs, FALSE, &obj_count)) <= 0 + && obj_count != 0) { + + /* Try to close all the open objects in this file */ + for(u = 0; u < obj_count; u++) + if(H5I_dec_ref(objs[u]) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object") + } /* end while */ + if(result < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_obj_ids failed(2)") + } /* end if */ + } /* end if */ + + /* Check if this is a child file in a mounting hierarchy & proceed up the + * hierarchy if so. + */ + if(f->parent) + if(H5F_try_close(f->parent) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close parent file") + + /* Unmount and close each child before closing the current file. */ + if(H5F_close_mounts(f) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't unmount child files") + + /* If there is more than one reference to the shared file struct and the + * file has an external file cache, we should see if it can be closed. This + * can happen if a cycle is formed with external file caches */ + if(f->shared->efc && (f->shared->nrefs > 1)) + if(H5F_efc_try_close(f) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't attempt to close EFC") + + /* Delay flush until the shared file struct is closed, in H5F_dest. If the + * application called H5Fclose, it would have been flushed in that function + * (unless it will have been flushed in H5F_dest anyways). */ + + /* + * Destroy the H5F_t struct and decrement the reference count for the + * shared H5F_file_t struct. If the reference count for the H5F_file_t + * struct reaches zero then destroy it also. + */ + if(H5F_dest(f, H5AC_dxpl_id, TRUE) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "problems closing file") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_try_close() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_get_id + * + * Purpose: Get the file ID, incrementing it, or "resurrecting" it as + * appropriate. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Raymond Lu + * Oct 29, 2003 + * + *------------------------------------------------------------------------- + */ +hid_t +H5F_get_id(H5F_t *file, hbool_t app_ref) +{ + hid_t ret_value; + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(file); + + if(file->file_id == -1) { + /* Get an atom for the file */ + if((file->file_id = H5I_register(H5I_FILE, file, app_ref)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize file") + } else { + /* Increment reference count on atom. */ + if(H5I_inc_ref(file->file_id, app_ref) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTSET, FAIL, "incrementing file ID failed") + } /* end else */ + + ret_value = file->file_id; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_get_id() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_incr_nopen_objs + * + * Purpose: Increment the number of open objects for a file. + * + * Return: Success: The number of open objects, after the increment + * + * Failure: (can't happen) + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Mar 6 2007 + * + *------------------------------------------------------------------------- + */ +unsigned +H5F_incr_nopen_objs(H5F_t *f) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOERR + + HDassert(f); + + FUNC_LEAVE_NOAPI(++f->nopen_objs) +} /* end H5F_incr_nopen_objs() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_decr_nopen_objs + * + * Purpose: Decrement the number of open objects for a file. + * + * Return: Success: The number of open objects, after the decrement + * + * Failure: (can't happen) + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Mar 6 2007 + * + *------------------------------------------------------------------------- + */ +unsigned +H5F_decr_nopen_objs(H5F_t *f) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOERR + + HDassert(f); + + FUNC_LEAVE_NOAPI(--f->nopen_objs) +} /* end H5F_decr_nopen_objs() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_build_actual_name + * + * Purpose: Retrieve the name of a file, after following symlinks, etc. + * + * Note: Currently only working for "POSIX I/O compatible" VFDs + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Quincey Koziol + * November 25, 2009 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5F_build_actual_name(const H5F_t *f, const H5P_genplist_t *fapl, const char *name, + char **actual_name/*out*/) +{ + hid_t new_fapl_id = -1; /* ID for duplicated FAPL */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Sanity check */ + HDassert(f); + HDassert(fapl); + HDassert(name); + HDassert(actual_name); + + /* Clear actual name pointer to begin with */ + *actual_name = NULL; + +/* Assume that if the OS can't create symlinks, that we don't need to worry + * about resolving them either. -QAK + */ +#ifdef H5_HAVE_SYMLINK + /* Check for POSIX I/O compatible file handle */ + if(H5F_HAS_FEATURE(f, H5FD_FEAT_POSIX_COMPAT_HANDLE)) { + h5_stat_t lst; /* Stat info from lstat() call */ + + /* Call lstat() on the file's name */ + if(HDlstat(name, &lst) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't retrieve stat info for file") + + /* Check for symbolic link */ + if(S_IFLNK == (lst.st_mode & S_IFMT)) { + H5P_genplist_t *new_fapl; /* Duplicated FAPL */ + int *fd; /* POSIX I/O file descriptor */ + h5_stat_t st; /* Stat info from stat() call */ + h5_stat_t fst; /* Stat info from fstat() call */ + char realname[PATH_MAX]; /* Fully resolved path name of file */ + hbool_t want_posix_fd; /* Flag for retrieving file descriptor from VFD */ + + /* Perform a sanity check that the file or link wasn't switched + * between when we opened it and when we called lstat(). This is + * according to the security best practices for lstat() documented + * here: https://www.securecoding.cert.org/confluence/display/seccode/POS35-C.+Avoid+race+conditions+while+checking+for+the+existence+of+a+symbolic+link + */ + + /* Copy the FAPL object to modify */ + if((new_fapl_id = H5P_copy_plist(fapl, FALSE)) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, FAIL, "unable to copy file access property list") + if(NULL == (new_fapl = (H5P_genplist_t *)H5I_object(new_fapl_id))) + HGOTO_ERROR(H5E_FILE, H5E_CANTCREATE, FAIL, "can't get property list") + + /* Set the character encoding on the new property list */ + want_posix_fd = TRUE; + if(H5P_set(new_fapl, H5F_ACS_WANT_POSIX_FD_NAME, &want_posix_fd) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set character encoding") + + /* Retrieve the file handle */ + if(H5F_get_vfd_handle(f, new_fapl_id, (void **)&fd) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't retrieve POSIX file descriptor") + + /* Stat the filename we're resolving */ + if(HDstat(name, &st) < 0) + HSYS_GOTO_ERROR(H5E_FILE, H5E_BADFILE, FAIL, "unable to stat file") + + /* Stat the file we opened */ + if(HDfstat(*fd, &fst) < 0) + HSYS_GOTO_ERROR(H5E_FILE, H5E_BADFILE, FAIL, "unable to fstat file") + + /* Verify that the files are really the same */ + if(st.st_mode != fst.st_mode || st.st_ino != fst.st_ino || st.st_dev != fst.st_dev) + HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "files' st_ino or st_dev fields changed!") + + /* Get the resolved path for the file name */ + if(NULL == HDrealpath(name, realname)) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't retrieve real path for file") + + /* Duplicate the resolved path for the file name */ + if(NULL == (*actual_name = (char *)H5MM_strdup(realname))) + HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "can't duplicate real path") + } /* end if */ + } /* end if */ +#endif /* H5_HAVE_SYMLINK */ + + /* Check if we've resolved the file's name */ + if(NULL == *actual_name) { + /* Just duplicate the name used to open the file */ + if(NULL == (*actual_name = (char *)H5MM_strdup(name))) + HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "can't duplicate open name") + } /* end else */ + +done: + /* Close the property list */ + if(new_fapl_id > 0) + if(H5I_dec_app_ref(new_fapl_id) < 0) + HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "can't close duplicated FAPL") + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5F_build_actual_name() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_addr_encode_len + * + * Purpose: Encodes an address into the buffer pointed to by *PP and + * then increments the pointer to the first byte after the + * address. An undefined value is stored as all 1's. + * + * Return: void + * + * Programmer: Robb Matzke + * Friday, November 7, 1997 + * + *------------------------------------------------------------------------- + */ +void +H5F_addr_encode_len(size_t addr_len, uint8_t **pp/*in,out*/, haddr_t addr) +{ + unsigned u; /* Local index variable */ + + /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOERR + + HDassert(addr_len); + HDassert(pp && *pp); + + if(H5F_addr_defined(addr)) { + for(u = 0; u < addr_len; u++) { + *(*pp)++ = (uint8_t)(addr & 0xff); + addr >>= 8; + } /* end for */ + HDassert("overflow" && 0 == addr); + } /* end if */ + else { + for(u = 0; u < addr_len; u++) + *(*pp)++ = 0xff; + } /* end else */ + + FUNC_LEAVE_NOAPI_VOID +} /* end H5F_addr_encode_len() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_addr_encode + * + * Purpose: Encodes an address into the buffer pointed to by *PP and + * then increments the pointer to the first byte after the + * address. An undefined value is stored as all 1's. + * + * Return: void + * + * Programmer: Robb Matzke + * Friday, November 7, 1997 + * + *------------------------------------------------------------------------- + */ +void +H5F_addr_encode(const H5F_t *f, uint8_t **pp/*in,out*/, haddr_t addr) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOERR + + HDassert(f); + + H5F_addr_encode_len(H5F_SIZEOF_ADDR(f), pp, addr); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5F_addr_encode() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_addr_decode_len + * + * Purpose: Decodes an address from the buffer pointed to by *PP and + * updates the pointer to point to the next byte after the + * address. + * + * If the value read is all 1's then the address is returned + * with an undefined value. + * + * Return: void + * + * Programmer: Robb Matzke + * Friday, November 7, 1997 + * + *------------------------------------------------------------------------- + */ +void +H5F_addr_decode_len(size_t addr_len, const uint8_t **pp/*in,out*/, haddr_t *addr_p/*out*/) +{ + hbool_t all_zero = TRUE; /* True if address was all zeroes */ + unsigned u; /* Local index variable */ + + /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOERR + + HDassert(addr_len); + HDassert(pp && *pp); + HDassert(addr_p); + + /* Reset value in destination */ + *addr_p = 0; + + /* Decode bytes from address */ + for(u = 0; u < addr_len; u++) { + uint8_t c; /* Local decoded byte */ + + /* Get decoded byte (and advance pointer) */ + c = *(*pp)++; + + /* Check for non-undefined address byte value */ + if(c != 0xff) + all_zero = FALSE; + + if(u < sizeof(*addr_p)) { + haddr_t tmp = c; /* Local copy of address, for casting */ + + /* Shift decoded byte to correct position */ + tmp <<= (u * 8); /*use tmp to get casting right */ + + /* Merge into already decoded bytes */ + *addr_p |= tmp; + } /* end if */ + else + if(!all_zero) + HDassert(0 == **pp); /*overflow */ + } /* end for */ + + /* If 'all_zero' is still TRUE, the address was entirely composed of '0xff' + * bytes, which is the encoded form of 'HADDR_UNDEF', so set the destination + * to that value */ + if(all_zero) + *addr_p = HADDR_UNDEF; + + FUNC_LEAVE_NOAPI_VOID +} /* end H5F_addr_decode_len() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_addr_decode + * + * Purpose: Decodes an address from the buffer pointed to by *PP and + * updates the pointer to point to the next byte after the + * address. + * + * If the value read is all 1's then the address is returned + * with an undefined value. + * + * Return: void + * + * Programmer: Robb Matzke + * Friday, November 7, 1997 + * + *------------------------------------------------------------------------- + */ +void +H5F_addr_decode(const H5F_t *f, const uint8_t **pp/*in,out*/, haddr_t *addr_p/*out*/) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOERR + + HDassert(f); + + H5F_addr_decode_len(H5F_SIZEOF_ADDR(f), pp, addr_p); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5F_addr_decode() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_set_grp_btree_shared + * + * Purpose: Set the grp_btree_shared field with a valid ref-count pointer. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Quincey Koziol + * 7/19/11 + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_set_grp_btree_shared(H5F_t *f, H5UC_t *rc) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOERR + + /* Sanity check */ + HDassert(f); + HDassert(f->shared); + HDassert(rc); + + f->shared->grp_btree_shared = rc; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5F_set_grp_btree_shared() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_set_sohm_addr + * + * Purpose: Set the sohm_addr field with a new value. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Quincey Koziol + * 7/20/11 + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_set_sohm_addr(H5F_t *f, haddr_t addr) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOERR + + /* Sanity check */ + HDassert(f); + HDassert(f->shared); + + f->shared->sohm_addr = addr; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5F_set_sohm_addr() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_set_sohm_vers + * + * Purpose: Set the sohm_vers field with a new value. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Quincey Koziol + * 7/20/11 + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_set_sohm_vers(H5F_t *f, unsigned vers) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOERR + + /* Sanity check */ + HDassert(f); + HDassert(f->shared); + + f->shared->sohm_vers = vers; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5F_set_sohm_vers() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_set_sohm_nindexes + * + * Purpose: Set the sohm_nindexes field with a new value. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Quincey Koziol + * 7/20/11 + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_set_sohm_nindexes(H5F_t *f, unsigned nindexes) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOERR + + /* Sanity check */ + HDassert(f); + HDassert(f->shared); + + f->shared->sohm_nindexes = nindexes; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5F_set_sohm_nindexes() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_set_store_msg_crt_idx + * + * Purpose: Set the store_msg_crt_idx field with a new value. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Quincey Koziol + * 7/20/11 + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_set_store_msg_crt_idx(H5F_t *f, hbool_t flag) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOERR + + /* Sanity check */ + HDassert(f); + HDassert(f->shared); + + f->shared->store_msg_crt_idx = flag; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5F_set_store_msg_crt_idx() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_get_file_image + * + * Purpose: Private version of H5Fget_file_image + * + * Return: Success: Bytes copied / number of bytes needed. + * Failure: negative value + * + * Programmer: John Mainzer + * 11/15/11 + * + *------------------------------------------------------------------------- + */ +ssize_t +H5F_get_file_image(H5F_t *file, void *buf_ptr, size_t buf_len) +{ + H5FD_t *fd_ptr; /* file driver */ + haddr_t eoa; /* End of file address */ + ssize_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Check args */ + if(!file || !file->shared || !file->shared->lf) + HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "file_id yields invalid file pointer") + fd_ptr = file->shared->lf; + if(!fd_ptr->cls) + HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "fd_ptr yields invalid class pointer") + + /* the address space used by the split and multi file drivers is not + * a good fit for this call. Since the plan is to depreciate these + * drivers anyway, don't bother to do a "force fit". + * + * The following clause tests for the multi file driver, and fails + * if the supplied file has the multi file driver as its top level + * file driver. However, this test will not work if there is some + * other file driver sitting on top of the multi file driver. + * + * I'm not sure if this is possible at present, but in all likelyhood, + * it will become possible in the future. On the other hand, we may + * remove the split/multi file drivers before then. + * + * I am leaving this solution in for now, but we should review it, + * and improve the solution if necessary. + * + * JRM -- 11/11/22 + */ + if(HDstrcmp(fd_ptr->cls->name, "multi") == 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Not supported for multi file driver.") + + /* While the family file driver is conceptually fully compatible + * with the get file image operation, it sets a file driver message + * in the super block that prevents the image being opened with any + * driver other than the family file driver. Needless to say, this + * rather defeats the purpose of the get file image operation. + * + * While this problem is quire solvable, the required time and + * resources are lacking at present. Hence, for now, we don't + * allow the get file image operation to be perfomed on files + * opened with the family file driver. + * + * Observe that the following test only looks at the top level + * driver, and fails if there is some other driver sitting on to + * of the family file driver. + * + * I don't think this can happen at present, but that may change + * in the future. + * JRM -- 12/21/11 + */ + if(HDstrcmp(fd_ptr->cls->name, "family") == 0) + HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "Not supported for family file driver.") + + /* Go get the actual file size */ + if(HADDR_UNDEF == (eoa = H5FD_get_eoa(file->shared->lf, H5FD_MEM_DEFAULT))) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get file size") + + /* set ret_value = to eoa -- will overwrite this if appropriate */ + ret_value = (ssize_t)eoa; + + /* test to see if a buffer was provided -- if not, we are done */ + if(buf_ptr != NULL) { + size_t space_needed; /* size of file image */ + + /* Check for buffer too small */ + if((haddr_t)buf_len < eoa) + HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "supplied buffer too small") + + space_needed = (size_t)eoa; + + /* read in the file image */ + /* (Note compensation for base address addition in internal routine) */ + if(H5FD_read(fd_ptr, H5AC_ind_dxpl_g, H5FD_MEM_DEFAULT, 0, space_needed, buf_ptr) < 0) + HGOTO_ERROR(H5E_FILE, H5E_READERROR, FAIL, "file image read request failed") + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5F_get_file_image() */ diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h index 9f48070..53fe0d9 100644 --- a/src/H5Fpkg.h +++ b/src/H5Fpkg.h @@ -292,7 +292,13 @@ H5_DLLVAR const H5AC_class_t H5AC_SUPERBLOCK[1]; /* General routines */ H5_DLL herr_t H5F_init(void); H5_DLL herr_t H5F__term_deprec_interface(void); +H5F_t *H5F_new(H5F_file_t *shared, unsigned flags, hid_t fcpl_id, + hid_t fapl_id, H5FD_t *lf); +herr_t H5F_dest(H5F_t *f, hid_t dxpl_id, hbool_t flush); H5_DLL herr_t H5F_flush(H5F_t *f, hid_t dxpl_id, hbool_t closing); +H5_DLL htri_t H5F_is_hdf5(const char *name); +H5_DLL herr_t H5F_get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_list, hbool_t app_ref, size_t *obj_id_count_ptr); +H5_DLL herr_t H5F_close(H5F_t *f); /* File mount related routines */ H5_DLL herr_t H5F_close_mounts(H5F_t *f); diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index fc0a01e..fe81edc 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -598,6 +598,7 @@ H5_DLL unsigned H5F_get_nopen_objs(const H5F_t *f); H5_DLL unsigned H5F_incr_nopen_objs(H5F_t *f); H5_DLL unsigned H5F_decr_nopen_objs(H5F_t *f); H5_DLL hid_t H5F_get_file_id(const H5F_t *f); +H5_DLL ssize_t H5F_get_file_image(H5F_t *f, void *buf_ptr, size_t buf_len); H5_DLL H5F_t *H5F_get_parent(const H5F_t *f); H5_DLL unsigned H5F_get_nmounts(const H5F_t *f); H5_DLL hid_t H5F_get_access_plist(H5F_t *f, hbool_t app_ref); diff --git a/src/Makefile.am b/src/Makefile.am index adc3032..4b55144 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -52,7 +52,7 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \ H5E.c H5Edeprec.c H5Eint.c \ H5EA.c H5EAcache.c H5EAdbg.c H5EAdblkpage.c H5EAdblock.c H5EAhdr.c \ H5EAiblock.c H5EAint.c H5EAsblock.c H5EAstat.c H5EAtest.c \ - H5F.c H5Faccum.c H5Fcwfs.c \ + H5F.c H5Fint.c H5Faccum.c H5Fcwfs.c \ H5Fdbg.c H5Fdeprec.c H5Fefc.c H5Ffake.c H5Fio.c \ H5Fmount.c H5Fmpi.c H5Fquery.c \ H5Fsfile.c H5Fsuper.c H5Fsuper_cache.c H5Ftest.c \ diff --git a/src/Makefile.in b/src/Makefile.in index b08463c..552fa61 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -158,19 +158,19 @@ am_libhdf5_la_OBJECTS = H5.lo H5checksum.lo H5dbg.lo H5system.lo \ H5Dtest.lo H5E.lo H5Edeprec.lo H5Eint.lo H5EA.lo H5EAcache.lo \ H5EAdbg.lo H5EAdblkpage.lo H5EAdblock.lo H5EAhdr.lo \ H5EAiblock.lo H5EAint.lo H5EAsblock.lo H5EAstat.lo H5EAtest.lo \ - H5F.lo H5Faccum.lo H5Fcwfs.lo H5Fdbg.lo H5Fdeprec.lo H5Fefc.lo \ - H5Ffake.lo H5Fio.lo H5Fmount.lo H5Fmpi.lo H5Fquery.lo \ - H5Fsfile.lo H5Fsuper.lo H5Fsuper_cache.lo H5Ftest.lo H5FA.lo \ - H5FAcache.lo H5FAdbg.lo H5FAdblock.lo H5FAdblkpage.lo \ - H5FAhdr.lo H5FAstat.lo H5FAtest.lo H5FD.lo H5FDcore.lo \ - H5FDdirect.lo H5FDfamily.lo H5FDint.lo H5FDlog.lo H5FDmpi.lo \ - H5FDmpio.lo H5FDmulti.lo H5FDsec2.lo H5FDspace.lo H5FDstdio.lo \ - H5FL.lo H5FO.lo H5FS.lo H5FScache.lo H5FSdbg.lo H5FSsection.lo \ - H5FSstat.lo H5FStest.lo H5G.lo H5Gbtree2.lo H5Gcache.lo \ - H5Gcompact.lo H5Gdense.lo H5Gdeprec.lo H5Gent.lo H5Gint.lo \ - H5Glink.lo H5Gloc.lo H5Gname.lo H5Gnode.lo H5Gobj.lo H5Goh.lo \ - H5Groot.lo H5Gstab.lo H5Gtest.lo H5Gtraverse.lo H5HF.lo \ - H5HFbtree2.lo H5HFcache.lo H5HFdbg.lo H5HFdblock.lo \ + H5F.lo H5Fint.lo H5Faccum.lo H5Fcwfs.lo H5Fdbg.lo H5Fdeprec.lo \ + H5Fefc.lo H5Ffake.lo H5Fio.lo H5Fmount.lo H5Fmpi.lo \ + H5Fquery.lo H5Fsfile.lo H5Fsuper.lo H5Fsuper_cache.lo \ + H5Ftest.lo H5FA.lo H5FAcache.lo H5FAdbg.lo H5FAdblock.lo \ + H5FAdblkpage.lo H5FAhdr.lo H5FAstat.lo H5FAtest.lo H5FD.lo \ + H5FDcore.lo H5FDdirect.lo H5FDfamily.lo H5FDint.lo H5FDlog.lo \ + H5FDmpi.lo H5FDmpio.lo H5FDmulti.lo H5FDsec2.lo H5FDspace.lo \ + H5FDstdio.lo H5FL.lo H5FO.lo H5FS.lo H5FScache.lo H5FSdbg.lo \ + H5FSsection.lo H5FSstat.lo H5FStest.lo H5G.lo H5Gbtree2.lo \ + H5Gcache.lo H5Gcompact.lo H5Gdense.lo H5Gdeprec.lo H5Gent.lo \ + H5Gint.lo H5Glink.lo H5Gloc.lo H5Gname.lo H5Gnode.lo H5Gobj.lo \ + H5Goh.lo H5Groot.lo H5Gstab.lo H5Gtest.lo H5Gtraverse.lo \ + H5HF.lo H5HFbtree2.lo H5HFcache.lo H5HFdbg.lo H5HFdblock.lo \ H5HFdtable.lo H5HFhdr.lo H5HFhuge.lo H5HFiblock.lo H5HFiter.lo \ H5HFman.lo H5HFsection.lo H5HFspace.lo H5HFstat.lo H5HFtest.lo \ H5HFtiny.lo H5HG.lo H5HGcache.lo H5HGdbg.lo H5HGquery.lo \ @@ -758,7 +758,7 @@ libhdf5_la_SOURCES = H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \ H5E.c H5Edeprec.c H5Eint.c \ H5EA.c H5EAcache.c H5EAdbg.c H5EAdblkpage.c H5EAdblock.c H5EAhdr.c \ H5EAiblock.c H5EAint.c H5EAsblock.c H5EAstat.c H5EAtest.c \ - H5F.c H5Faccum.c H5Fcwfs.c \ + H5F.c H5Fint.c H5Faccum.c H5Fcwfs.c \ H5Fdbg.c H5Fdeprec.c H5Fefc.c H5Ffake.c H5Fio.c \ H5Fmount.c H5Fmpi.c H5Fquery.c \ H5Fsfile.c H5Fsuper.c H5Fsuper_cache.c H5Ftest.c \ @@ -1054,6 +1054,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fdeprec.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fefc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Ffake.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fint.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fio.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fmount.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fmpi.Plo@am__quote@ diff --git a/test/testfiles/err_compat_1 b/test/testfiles/err_compat_1 index 3a85b86..d471e13 100644 --- a/test/testfiles/err_compat_1 +++ b/test/testfiles/err_compat_1 @@ -54,9 +54,6 @@ HDF5-DIAG: Error detected in HDF5 (version (number)) thread (IDs): #001: (file name) line (number) in test_error2(): H5Dwrite shouldn't succeed major: Error API minor: Write failed - #002: (file name) line (number) in H5Dwrite(): can't prepare for writing data - major: Dataset - minor: Write failed - #003: (file name) line (number) in H5D__pre_write(): not a dataset + #002: (file name) line (number) in H5Dwrite(): not a dataset major: Invalid arguments to routine minor: Inappropriate type -- cgit v0.12