summaryrefslogtreecommitdiffstats
path: root/src/H5Dint.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5Dint.c')
-rw-r--r--src/H5Dint.c166
1 files changed, 144 insertions, 22 deletions
diff --git a/src/H5Dint.c b/src/H5Dint.c
index a58ca56..9d588ae 100644
--- a/src/H5Dint.c
+++ b/src/H5Dint.c
@@ -63,9 +63,11 @@ 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_t *dataset, hbool_t full_overwrite,
- hsize_t old_dim[], 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));
@@ -1504,7 +1610,13 @@ H5D__open_oid(H5D_t *dataset, hid_t dapl_id, hid_t dxpl_id)
if((H5F_INTENT(dataset->oloc.file) & H5F_ACC_RDWR)
&& !(*dataset->shared->layout.ops->is_space_alloc)(&dataset->shared->layout.storage)
&& H5F_HAS_FEATURE(dataset->oloc.file, H5FD_FEAT_ALLOCATE_EARLY)) {
- if(H5D__alloc_storage(dataset, dxpl_id, H5D_ALLOC_OPEN, FALSE, NULL) < 0)
+ H5D_io_info_t io_info;
+
+ io_info.dset = dataset;
+ io_info.raw_dxpl_id = H5AC_rawdata_dxpl_id;
+ io_info.md_dxpl_id = dxpl_id;
+
+ if(H5D__alloc_storage(&io_info, H5D_ALLOC_OPEN, FALSE, NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize file storage")
} /* end if */
@@ -1652,6 +1764,9 @@ H5D_close(H5D_t *dataset)
if(dataset->shared->layout.ops->dest && (dataset->shared->layout.ops->dest)(dataset, H5AC_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) ||
@@ -1807,9 +1922,10 @@ H5D_typeof(const H5D_t *dset)
*-------------------------------------------------------------------------
*/
herr_t
-H5D__alloc_storage(const H5D_t *dset, hid_t dxpl_id, H5D_time_alloc_t time_alloc,
+H5D__alloc_storage(const H5D_io_info_t *io_info, H5D_time_alloc_t time_alloc,
hbool_t full_overwrite, hsize_t old_dim[])
{
+ const H5D_t *dset = io_info->dset; /* The dataset object */
H5F_t *f = dset->oloc.file; /* The dataset's file pointer */
H5O_layout_t *layout; /* The dataset's layout information */
hbool_t must_init_space = FALSE; /* Flag to indicate that space should be initialized */
@@ -1836,7 +1952,7 @@ H5D__alloc_storage(const H5D_t *dset, hid_t dxpl_id, H5D_time_alloc_t time_alloc
/* Check if we have a zero-sized dataset */
if(layout->storage.u.contig.size > 0) {
/* Reserve space in the file for the entire array */
- if(H5D__contig_alloc(f, dxpl_id, &layout->storage.u.contig/*out*/) < 0)
+ if(H5D__contig_alloc(f, io_info->md_dxpl_id, &layout->storage.u.contig/*out*/) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to initialize contiguous storage")
/* Indicate that we should initialize storage space */
@@ -1853,7 +1969,7 @@ H5D__alloc_storage(const H5D_t *dset, hid_t dxpl_id, H5D_time_alloc_t time_alloc
case H5D_CHUNKED:
if(!(*dset->shared->layout.ops->is_space_alloc)(&dset->shared->layout.storage)) {
/* Create the root of the index that manages chunked storage */
- if(H5D__chunk_create(dset /*in,out*/, dxpl_id) < 0)
+ if(H5D__chunk_create(dset /*in,out*/, io_info->md_dxpl_id) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to initialize chunked storage")
/* Indicate that we set the storage addr */
@@ -1926,7 +2042,7 @@ H5D__alloc_storage(const H5D_t *dset, hid_t dxpl_id, H5D_time_alloc_t time_alloc
* this is icky. -QAK
*/
if(!(dset->shared->dcpl_cache.fill.alloc_time == H5D_ALLOC_TIME_INCR && time_alloc == H5D_ALLOC_WRITE))
- if(H5D__init_storage(dset, full_overwrite, old_dim, dxpl_id) < 0)
+ if(H5D__init_storage(io_info, full_overwrite, old_dim) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize dataset with fill value")
} /* end if */
else {
@@ -1940,7 +2056,7 @@ H5D__alloc_storage(const H5D_t *dset, hid_t dxpl_id, H5D_time_alloc_t time_alloc
* the fill value _is_ set, do that now */
if(dset->shared->dcpl_cache.fill.fill_time == H5D_FILL_TIME_ALLOC ||
(dset->shared->dcpl_cache.fill.fill_time == H5D_FILL_TIME_IFSET && fill_status == H5D_FILL_VALUE_USER_DEFINED))
- if(H5D__init_storage(dset, full_overwrite, old_dim, dxpl_id) < 0)
+ if(H5D__init_storage(io_info, full_overwrite, old_dim) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize dataset with fill value")
} /* end else */
} /* end if */
@@ -1954,7 +2070,7 @@ H5D__alloc_storage(const H5D_t *dset, hid_t dxpl_id, H5D_time_alloc_t time_alloc
*/
if(time_alloc != H5D_ALLOC_CREATE && addr_set)
/* Mark the layout as dirty, for later writing to the file */
- if(H5D__mark(dset, dxpl_id, H5D_MARK_LAYOUT) < 0)
+ if(H5D__mark(dset, io_info->md_dxpl_id, H5D_MARK_LAYOUT) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to mark dataspace as dirty")
} /* end if */
@@ -1978,10 +2094,10 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5D__init_storage(const H5D_t *dset, hbool_t full_overwrite, hsize_t old_dim[],
- hid_t dxpl_id)
+H5D__init_storage(const H5D_io_info_t *io_info, hbool_t full_overwrite, hsize_t old_dim[])
{
- herr_t ret_value = SUCCEED; /* Return value */
+ const H5D_t *dset = io_info->dset; /* dataset pointer */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
@@ -1992,7 +2108,7 @@ H5D__init_storage(const H5D_t *dset, hbool_t full_overwrite, hsize_t old_dim[],
/* If we will be immediately overwriting the values, don't bother to clear them */
if(!full_overwrite) {
/* Fill the compact dataset storage */
- if(H5D__compact_fill(dset, dxpl_id) < 0)
+ if(H5D__compact_fill(dset, io_info->md_dxpl_id) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize compact dataset storage")
} /* end if */
break;
@@ -2001,7 +2117,7 @@ H5D__init_storage(const H5D_t *dset, hbool_t full_overwrite, hsize_t old_dim[],
/* Don't write default fill values to external files */
/* If we will be immediately overwriting the values, don't bother to clear them */
if((dset->shared->dcpl_cache.efl.nused == 0 || dset->shared->dcpl_cache.fill.buf) && !full_overwrite)
- if(H5D__contig_fill(dset, dxpl_id) < 0)
+ if(H5D__contig_fill(io_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to allocate all chunks of dataset")
break;
@@ -2017,7 +2133,7 @@ H5D__init_storage(const H5D_t *dset, hbool_t full_overwrite, hsize_t old_dim[],
if(old_dim == NULL)
old_dim = zero_dim;
- if(H5D__chunk_allocate(dset, dxpl_id, full_overwrite, old_dim) < 0)
+ if(H5D__chunk_allocate(io_info, full_overwrite, old_dim) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to allocate all chunks of dataset")
break;
} /* end block */
@@ -2486,10 +2602,16 @@ H5D__set_extent(H5D_t *dset, const hsize_t *size, hid_t dxpl_id)
} /* end if */
/* Allocate space for the new parts of the dataset, if appropriate */
- if(expand && dset->shared->dcpl_cache.fill.alloc_time == H5D_ALLOC_TIME_EARLY)
- if(H5D__alloc_storage(dset, dxpl_id, H5D_ALLOC_EXTEND, FALSE, curr_dims) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to extend dataset storage")
+ if(expand && dset->shared->dcpl_cache.fill.alloc_time == H5D_ALLOC_TIME_EARLY) {
+ H5D_io_info_t io_info;
+ io_info.dset = dset;
+ io_info.raw_dxpl_id = H5AC_rawdata_dxpl_id;
+ io_info.md_dxpl_id = dxpl_id;
+
+ if(H5D__alloc_storage(&io_info, H5D_ALLOC_EXTEND, FALSE, curr_dims) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to extend dataset storage")
+ }
/*-------------------------------------------------------------------------
* Remove chunk information in the case of chunked datasets
* This removal takes place only in case we are shrinking the dateset
@@ -2831,7 +2953,7 @@ H5D_get_create_plist(H5D_t *dset)
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_dxpl_id, FALSE)))
+ if(NULL == (tpath = H5T_path_find(dset->shared->type, copied_fill.type, NULL, NULL, H5AC_noio_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 */
@@ -2859,7 +2981,7 @@ H5D_get_create_plist(H5D_t *dset)
} /* 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_dxpl_id) < 0) {
+ if(H5T_convert(tpath, src_id, dst_id, (size_t)1, (size_t)0, (size_t)0, copied_fill.buf, bkg_buf, H5AC_noio_dxpl_id) < 0) {
H5I_dec_ref(src_id);
H5I_dec_ref(dst_id);
if(bkg_buf)