diff options
author | Dana Robinson <derobins@hdfgroup.org> | 2016-02-22 21:40:03 (GMT) |
---|---|---|
committer | Dana Robinson <derobins@hdfgroup.org> | 2016-02-22 21:40:03 (GMT) |
commit | 19a8216bd52b6a495c4bc989b7d01e9a7ecd46bf (patch) | |
tree | bf07b7366747d1519b628ea1c399bb5e8b654753 /src/H5Dint.c | |
parent | 7511d8b4691770a15f1ba9f7fcc242f038c79669 (diff) | |
download | hdf5-19a8216bd52b6a495c4bc989b7d01e9a7ecd46bf.zip hdf5-19a8216bd52b6a495c4bc989b7d01e9a7ecd46bf.tar.gz hdf5-19a8216bd52b6a495c4bc989b7d01e9a7ecd46bf.tar.bz2 |
[svn-r29182] Re-commit of HDFFV-8740 fix, which adds the ability to configure
external dataset storage path behavior.
This check-in fixes a bug in the original check-in where the
external path stored in the file struct was not copied on reopen
causing subsequent dataset operations to fail.
Tested on: 64-bit Ubuntu 15.10 (Linux 4.2.0 x86_64) gcc 5.2.1
autotools serial w/ fortran and C++
autotools parallel (MPICH 3.1.4) w/ fortran
Diffstat (limited to 'src/H5Dint.c')
-rw-r--r-- | src/H5Dint.c | 113 |
1 files changed, 111 insertions, 2 deletions
diff --git a/src/H5Dint.c b/src/H5Dint.c index 3e2d212..fe34718 100644 --- a/src/H5Dint.c +++ b/src/H5Dint.c @@ -63,6 +63,8 @@ static herr_t H5D__cache_dataspace_info(const H5D_t *dset); static herr_t H5D__init_space(H5F_t *file, const H5D_t *dset, const H5S_t *space); static herr_t H5D__update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset, hid_t dapl_id); +static herr_t H5D_build_extfile_prefix(const H5D_t *dset, hid_t dapl_id, + char **extfile_prefix); static herr_t H5D__open_oid(H5D_t *dataset, hid_t dapl_id, hid_t dxpl_id); static herr_t H5D__init_storage(const H5D_io_info_t *io_info, hbool_t full_overwrite, hsize_t old_dim[]); @@ -982,6 +984,84 @@ done: } /* end H5D__update_oh_info() */ +/*-------------------------------------------------------------------------- + * Function: H5D_build_extfile_prefix + * + * Purpose: Determine the external file prefix to be used and store + * it in extfile_prefix. Stores an empty string if no prefix + * should be used. + * + * Return: SUCCEED/FAIL + * + * Programmer: Steffen Kiess + * October 16, 2015 + *-------------------------------------------------------------------------- + */ +static herr_t +H5D_build_extfile_prefix(const H5D_t *dset, hid_t dapl_id, char **extfile_prefix /*out*/) +{ + char *prefix = NULL; /* prefix used to look for the file */ + char *extpath = NULL; /* absolute path of directory the HDF5 file is in */ + size_t extpath_len; /* length of extpath */ + size_t prefix_len; /* length of prefix */ + size_t extfile_prefix_len; /* length of expanded prefix */ + H5P_genplist_t *plist = NULL; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* Return value */ + + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(dset); + HDassert(dset->oloc.file); + + extpath = H5F_EXTPATH(dset->oloc.file); + HDassert(extpath); + + /* XXX: Future thread-safety note - getenv is not required + * to be reentrant. + */ + prefix = HDgetenv("HDF5_EXTFILE_PREFIX"); + + if(prefix == NULL || *prefix == '\0') { + /* Set prefix to value of H5D_ACS_EFILE_PREFIX_NAME property */ + if(NULL == (plist = H5P_object_verify(dapl_id, H5P_DATASET_ACCESS))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_peek(plist, H5D_ACS_EFILE_PREFIX_NAME, &prefix) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get external file prefix") + } /* end if */ + + /* Prefix has to be checked for NULL / empty string again because the + * code above might have updated it. + */ + if(prefix == NULL || *prefix == '\0' || HDstrcmp(prefix, ".") == 0) { + /* filename is interpreted as relative to the current directory, + * does not need to be expanded + */ + if(NULL == (*extfile_prefix = (char *)H5MM_strdup(""))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + } /* end if */ + else { + if (HDstrncmp(prefix, "${ORIGIN}", HDstrlen("${ORIGIN}")) == 0) { + /* Replace ${ORIGIN} at beginning of prefix by directory of HDF5 file */ + extpath_len = HDstrlen(extpath); + prefix_len = HDstrlen(prefix); + extfile_prefix_len = extpath_len + prefix_len - HDstrlen("${ORIGIN}") + 1; + + if(NULL == (*extfile_prefix = (char *)H5MM_malloc(extfile_prefix_len))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate buffer") + HDsnprintf(*extfile_prefix, extfile_prefix_len, "%s%s", extpath, prefix + HDstrlen("${ORIGIN}")); + } /* end if */ + else { + if(NULL == (*extfile_prefix = (char *)H5MM_strdup(prefix))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + } /* end else */ + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5D_build_extfile_prefix() */ + + /*------------------------------------------------------------------------- * Function: H5D__create * @@ -1151,6 +1231,10 @@ H5D__create(H5F_t *file, hid_t type_id, const H5S_t *space, hid_t dcpl_id, /* Indicate that the layout information was initialized */ layout_init = TRUE; + /* Set the external file prefix */ + if(H5D_build_extfile_prefix(new_dset, dapl_id, &new_dset->shared->extfile_prefix) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to initialize external file prefix") + /* Add the dataset to the list of opened objects in the file */ if(H5FO_top_incr(new_dset->oloc.file, new_dset->oloc.addr) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINC, NULL, "can't incr object ref. count") @@ -1195,6 +1279,7 @@ done: } /* end if */ if(new_dset->shared->dcpl_id != 0 && H5I_dec_ref(new_dset->shared->dcpl_id) < 0) HDONE_ERROR(H5E_DATASET, H5E_CANTDEC, NULL, "unable to decrement ref count on property list") + new_dset->shared->extfile_prefix = (char *)H5MM_xfree(new_dset->shared->extfile_prefix); new_dset->shared = H5FL_FREE(H5D_shared_t, new_dset->shared); } /* end if */ new_dset->oloc.file = NULL; @@ -1288,7 +1373,8 @@ H5D_open(const H5G_loc_t *loc, hid_t dapl_id, hid_t dxpl_id) { H5D_shared_t *shared_fo = NULL; H5D_t *dataset = NULL; - H5D_t *ret_value = NULL; /* Return value */ + char *extfile_prefix = NULL; /* Expanded external file prefix */ + H5D_t *ret_value = NULL; /* Return value */ FUNC_ENTER_NOAPI(NULL) @@ -1307,6 +1393,10 @@ H5D_open(const H5G_loc_t *loc, hid_t dapl_id, hid_t dxpl_id) if(H5G_name_copy(&(dataset->path), loc->path, H5_COPY_SHALLOW) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, NULL, "can't copy path") + /* Get the external file prefix */ + if(H5D_build_extfile_prefix(dataset, dapl_id, &extfile_prefix) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to initialize external file prefix") + /* Check if dataset was already open */ if(NULL == (shared_fo = (H5D_shared_t *)H5FO_opened(dataset->oloc.file, dataset->oloc.addr))) { /* Clear any errors from H5FO_opened() */ @@ -1326,6 +1416,12 @@ H5D_open(const H5G_loc_t *loc, hid_t dapl_id, hid_t dxpl_id) /* We're the first dataset to use the the shared info */ dataset->shared->fo_count = 1; + + /* Set the external file prefix */ + dataset->shared->extfile_prefix = extfile_prefix; + /* Prevent string from being freed during done: */ + extfile_prefix = NULL; + } /* end if */ else { /* Point to shared info */ @@ -1334,6 +1430,12 @@ H5D_open(const H5G_loc_t *loc, hid_t dapl_id, hid_t dxpl_id) /* Increment # of datasets using shared information */ shared_fo->fo_count++; + /* Check whether the external file prefix of the already open dataset + * matches the new external file prefix + */ + if(HDstrcmp(extfile_prefix, dataset->shared->extfile_prefix) != 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, NULL, "new external file prefix does not match external file prefix of already open dataset") + /* Check if the object has been opened through the top file yet */ if(H5FO_top_count(dataset->oloc.file, dataset->oloc.addr) == 0) { /* Open the object through this top file */ @@ -1350,11 +1452,15 @@ H5D_open(const H5G_loc_t *loc, hid_t dapl_id, hid_t dxpl_id) ret_value = dataset; done: + extfile_prefix = (char *)H5MM_xfree(extfile_prefix); + if(ret_value == NULL) { /* Free the location--casting away const*/ if(dataset) { - if(shared_fo == NULL) /* Need to free shared fo */ + if(shared_fo == NULL && dataset->shared) { /* Need to free shared fo */ + dataset->shared->extfile_prefix = (char *)H5MM_xfree(dataset->shared->extfile_prefix); dataset->shared = H5FL_FREE(H5D_shared_t, dataset->shared); + } H5O_loc_free(&(dataset->oloc)); H5G_name_free(&(dataset->path)); @@ -1658,6 +1764,9 @@ H5D_close(H5D_t *dataset) if(dataset->shared->layout.ops->dest && (dataset->shared->layout.ops->dest)(dataset, H5AC_ind_read_dxpl_id) < 0) HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "unable to destroy layout info") + /* Free the external file prefix */ + dataset->shared->extfile_prefix = (char *)H5MM_xfree(dataset->shared->extfile_prefix); + /* Release layout, fill-value, efl & pipeline messages */ if(dataset->shared->dcpl_id != H5P_DATASET_CREATE_DEFAULT) free_failed |= (H5O_msg_reset(H5O_PLINE_ID, &dataset->shared->dcpl_cache.pline) < 0) || |