summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvchoi-hdfgroup <55293060+vchoi-hdfgroup@users.noreply.github.com>2022-06-04 02:46:43 (GMT)
committerGitHub <noreply@github.com>2022-06-04 02:46:43 (GMT)
commitb34aa88f486e9d8e90a33fd1cf55d7e6033eb9a9 (patch)
treee3384c2e32187a8a872f18126c9186f5ccd382e8
parentcfdc7f262f1f5d1d58fd719b82c9580ad01f32d1 (diff)
parent86c725c319e14e60e7f3e34d9c93713db50fc6c4 (diff)
downloadhdf5-b34aa88f486e9d8e90a33fd1cf55d7e6033eb9a9.zip
hdf5-b34aa88f486e9d8e90a33fd1cf55d7e6033eb9a9.tar.gz
hdf5-b34aa88f486e9d8e90a33fd1cf55d7e6033eb9a9.tar.bz2
Merge pull request #1800 from vchoi-hdfgroup/merge_john_tarball
Merge john tarball
-rw-r--r--src/H5.c1
-rw-r--r--src/H5FD.c226
-rw-r--r--src/H5FDcore.c60
-rw-r--r--src/H5FDdevelop.h4
-rw-r--r--src/H5FDdirect.c60
-rw-r--r--src/H5FDfamily.c64
-rw-r--r--src/H5FDlog.c61
-rw-r--r--src/H5FDmpio.c8
-rw-r--r--src/H5FDmulti.c15
-rw-r--r--src/H5FDpublic.h1
-rw-r--r--src/H5FDros3.c60
-rw-r--r--src/H5FDsec2.c15
-rw-r--r--src/H5FDstdio.c62
-rw-r--r--src/H5FDvfd_swmr.c765
-rw-r--r--src/H5FDvfd_swmr.h39
-rw-r--r--src/H5Fint.c157
-rw-r--r--src/H5Fprivate.h2
-rw-r--r--src/H5Fvfd_swmr.c74
-rw-r--r--src/H5Pfapl.c3
-rw-r--r--test/vfd_swmr.c22
20 files changed, 1162 insertions, 537 deletions
diff --git a/src/H5.c b/src/H5.c
index 8fbd874..29c21e6 100644
--- a/src/H5.c
+++ b/src/H5.c
@@ -463,6 +463,7 @@ H5_term_library(void)
do {
pending = 0;
for (i = 0; i < NELMTS(terminator); i++) {
+
if (terminator[i].completed)
continue;
if (pending != 0 && terminator[i].await_prior)
diff --git a/src/H5FD.c b/src/H5FD.c
index 0f38848..7e5596f 100644
--- a/src/H5FD.c
+++ b/src/H5FD.c
@@ -51,12 +51,6 @@
/* Package Typedefs */
/********************/
-/* H5FD wrapper for VFD SWMR. Allows use as a BSD TAILQ element. */
-typedef struct H5FD_wrap_t {
- TAILQ_ENTRY(H5FD_wrap_t) link; /* Linkage for list of all VFDs. */
- H5FD_t *file; /* Pointer to wrapped VFD struct */
-} H5FD_wrap_t;
-
/********************/
/* Local Prototypes */
/********************/
@@ -89,8 +83,6 @@ static herr_t H5FD__query(const H5FD_t *f, unsigned long *flags /*out*/);
*/
static unsigned long H5FD_file_serial_no_g;
-static TAILQ_HEAD(_all_vfds, H5FD_wrap_t) all_vfds = TAILQ_HEAD_INITIALIZER(all_vfds);
-
/* File driver ID class */
static const H5I_class_t H5I_VFL_CLS[1] = {{
H5I_VFL, /* ID class value */
@@ -714,104 +706,6 @@ done:
}
/*-------------------------------------------------------------------------
- * Function: H5FD__dedup
- *
- * Purpose: Helper routine for H5FD_deduplicate
- *
- * Compares `self` and `other` using the dedup callback of
- * `self` (if it has one); otherwise compares using `H5FDcmp()`.
- *
- * No `dedup' callback:
- *
- * If `self` has no de-duplication method, compare `self` and
- * `other` using `H5FDcmp()` and return `self` if they're equal
- * and `other` if unequal.
- *
- * `dedup' callback present:
- *
- * If `self` does have a de-duplication callback, invoke it and
- * return the method's result: `other` if it duplicates `self`,
- * `self` if `other` does NOT duplicate it, NULL if `other`
- * conflicts with `self` or if there is an error.
- *
- * Return: Success: `self' or `other', as described above
- *
- * Failure: NULL
- *
- * Note: Unlike H5FD_deduplicate(), this routine does not free `self`
- * under any circumstances.
- *
- *-------------------------------------------------------------------------
- *
- */
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_deduplicate
- *
- * Purpose: Search the already-opened VFD instances for an instance
- * similar to the instance `file` newly-opened using file access
- * properties given by `fapl_id`.
- *
- * Return: It's complicated...
- *
- * If there is an already-open instance that is functionally
- * identical to `file`, close `file` and return the already
- * open instance.
- *
- * If there is an already open instance that conflicts with
- * `file` because, for example, its file-access properties are
- * incompatible with `fapl_id`'s or, for another example, it is
- * under exclusive control by a third VFD instance, then close
- * `file` and return `NULL`.
- *
- * Otherwise, return `file` to indicate that there are no
- * identical or conflicting VFD instances already open.
- *-------------------------------------------------------------------------
- */
-H5FD_t *
-H5FD_deduplicate(H5FD_t *file, hid_t fapl_id)
-{
- H5FD_wrap_t *item;
- H5FD_t * ret_value = file;
-
- FUNC_ENTER_NOAPI(NULL)
-
- TAILQ_FOREACH(item, &all_vfds, link)
- {
- /* Skip "self" */
- if (item->file == file)
- continue;
-
- /* Skip files with exclusive owners, for now */
- if (item->file->exc_owner != NULL)
- continue;
-
- if ((ret_value = H5FD_vfd_swmr_dedup(item->file, file, fapl_id)) != file)
- goto done;
- }
-
- /* If we reach this stage, then we identified neither a conflict nor a
- * duplicate. If any lower VFD with an exclusive owner matches `file`,
- * return NULL to indicate the conflict.
- */
- TAILQ_FOREACH(item, &all_vfds, link)
- {
- if (item->file == file || item->file->exc_owner == NULL)
- continue;
-
- if (H5FD_cmp(file, item->file) == 0)
- HGOTO_ERROR(H5E_VFL, H5E_FILEOPEN, NULL,
- "found a conflicting open file when searching for duplicates")
- }
-
-done:
- if (ret_value != file && H5FD_close(file) < 0)
- HDONE_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, NULL, "could not close file")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_deduplicate() */
-
-/*-------------------------------------------------------------------------
* Function: H5FD_open
*
* Purpose: Private version of H5FDopen()
@@ -825,14 +719,13 @@ done:
H5FD_t *
H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
{
- H5FD_class_t * driver; /* VFD for file */
- H5FD_t * file = NULL; /* VFD file struct */
- H5FD_driver_prop_t driver_prop; /* Property for driver ID & info */
- H5P_genplist_t * plist; /* Property list pointer */
- unsigned long driver_flags = 0; /* File-inspecific driver feature flags */
- H5FD_file_image_info_t file_image_info; /* Initial file image */
- H5FD_wrap_t * swmr_wrapper = NULL; /* H5FD wrapper for SWMR queue */
- H5FD_t * ret_value = NULL; /* Return value */
+ H5FD_class_t * driver; /* VFD for file */
+ H5FD_t * file = NULL; /* VFD file struct */
+ H5FD_driver_prop_t driver_prop; /* Property for driver ID & info */
+ H5P_genplist_t * plist; /* Property list pointer */
+ unsigned long driver_flags = 0; /* File-inspecific driver feature flags */
+ H5FD_file_image_info_t file_image_info; /* Initial file image */
+ H5FD_t * ret_value = NULL; /* Return value */
FUNC_ENTER_NOAPI(NULL)
@@ -874,8 +767,6 @@ H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
if (NULL == (file = (driver->open)(name, flags, fapl_id, maxaddr)))
HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, NULL, "open failed")
- file->exc_owner = NULL;
-
/* Set the file access flags */
file->access_flags = flags;
@@ -907,12 +798,6 @@ H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
/* (This will be changed later, when the superblock is located) */
file->base_addr = 0;
- /* Create and insert a SWMR wrapper for the file */
- if (NULL == (swmr_wrapper = H5MM_calloc(sizeof(H5FD_wrap_t))))
- HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, NULL, "unable to allocate file wrap struct")
- swmr_wrapper->file = file;
- TAILQ_INSERT_TAIL(&all_vfds, swmr_wrapper, link);
-
/* Set return value */
ret_value = file;
@@ -969,8 +854,6 @@ herr_t
H5FD_close(H5FD_t *file)
{
const H5FD_class_t *driver;
- H5FD_wrap_t * item;
- H5FD_wrap_t * temp = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
@@ -984,18 +867,6 @@ H5FD_close(H5FD_t *file)
if (H5I_dec_ref(file->driver_id) < 0)
HGOTO_ERROR(H5E_VFL, H5E_CANTDEC, FAIL, "can't close driver ID")
- TAILQ_FOREACH(item, &all_vfds, link)
- {
- if (item->file->exc_owner == file)
- item->file->exc_owner = NULL;
- if (item->file == file)
- temp = item;
- }
-
- HDassert(temp);
- TAILQ_REMOVE(&all_vfds, temp, link);
- H5MM_xfree(temp);
-
/* Dispatch to the driver for actual close. If the driver fails to
* close the file then the file will be in an unusable state.
*/
@@ -1050,37 +921,100 @@ done:
*
* Failure: Must never fail.
*
+ * Changes: Re-worked function to use H5FD_ctl() to obtain the terminal
+ * VFDs for f1 and f2. Typically, these are the same thing,
+ * however, if there is an intervening pass through VFD
+ * (i.e. splitter of vfd swrmr reader vfd), using the terminal
+ * VFD for the comparison will avoid some false negatives.
+ *
+ * Note, however, that we will still fail to detect the
+ * case in which a give file is opened twice with different
+ * terminal VFDs.
+ *
+ * JRM -- 5/5/22
+ *
*-------------------------------------------------------------------------
*/
+
int
H5FD_cmp(const H5FD_t *f1, const H5FD_t *f2)
{
- int ret_value = -1; /* Return value */
+ const H5FD_t *term_f1 = f1;
+ const H5FD_t *term_f2 = f2;
+ herr_t ctl_result;
+ int ret_value = -1; /* Return value */
FUNC_ENTER_NOAPI_NOERR; /* return value is arbitrary */
- if ((!f1 || !f1->cls) && (!f2 || !f2->cls))
+ /* For each of f1 and f2, check to see if the ctl call is defined. If it is,
+ * use the ctl call to try to obtain the terminal VFD. Since this function
+ * is not allowed to fail, discard the error stack if either of the ctl call
+ * fail.
+ */
+ if ((f1) && (f1->cls) && (f1->cls->ctl)) {
+
+ H5E_BEGIN_TRY
+ {
+ ctl_result = H5FD_ctl(f1, H5FD_CTL__GET_TERMINAL_VFD,
+ H5FD_CTL__FAIL_IF_UNKNOWN_FLAG | H5FD_CTL__ROUTE_TO_TERMINAL_VFD_FLAG, NULL,
+ (void **)(&term_f1));
+ }
+ H5E_END_TRY;
+
+ /* if the ctl call failed, set term_f1 equal to f1. This will probably be
+ * wrong -- but it will be no worse than using the top level VFD unconditionally.
+ */
+ if (ctl_result != SUCCEED) {
+
+ H5E_clear_stack(NULL);
+
+ term_f1 = f1;
+ }
+ }
+
+ if ((f2) && (f2->cls) && (f2->cls->ctl)) {
+
+ H5E_BEGIN_TRY
+ {
+ ctl_result = H5FD_ctl(f2, H5FD_CTL__GET_TERMINAL_VFD,
+ H5FD_CTL__FAIL_IF_UNKNOWN_FLAG | H5FD_CTL__ROUTE_TO_TERMINAL_VFD_FLAG, NULL,
+ (void **)(&term_f2));
+ }
+ H5E_END_TRY;
+
+ /* if the ctl call failed, set term_f1 equal to f1. This will probably be
+ * wrong -- but it will be no worse than using the top level VFD unconditionally.
+ */
+ if (ctl_result != SUCCEED) {
+
+ H5E_clear_stack(NULL);
+
+ term_f2 = f2;
+ }
+ }
+
+ if ((!term_f1 || !term_f1->cls) && (!term_f2 || !term_f2->cls))
HGOTO_DONE(0)
- if (!f1 || !f1->cls)
+ if (!term_f1 || !term_f1->cls)
HGOTO_DONE(-1)
- if (!f2 || !f2->cls)
+ if (!term_f2 || !term_f2->cls)
HGOTO_DONE(1)
- if (f1->cls < f2->cls)
+ if (term_f1->cls < term_f2->cls)
HGOTO_DONE(-1)
- if (f1->cls > f2->cls)
+ if (term_f1->cls > term_f2->cls)
HGOTO_DONE(1)
/* Files are same driver; no cmp callback */
- if (!f1->cls->cmp) {
- if (f1 < f2)
+ if (!term_f1->cls->cmp) {
+ if (term_f1 < term_f2)
HGOTO_DONE(-1)
- if (f1 > f2)
+ if (term_f1 > term_f2)
HGOTO_DONE(1)
HGOTO_DONE(0)
}
/* Dispatch to driver */
- ret_value = (f1->cls->cmp)(f1, f2);
+ ret_value = (term_f1->cls->cmp)(term_f1, term_f2);
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5FDcore.c b/src/H5FDcore.c
index a207e9e..e09e250 100644
--- a/src/H5FDcore.c
+++ b/src/H5FDcore.c
@@ -149,6 +149,8 @@ static herr_t H5FD__core_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing
static herr_t H5FD__core_lock(H5FD_t *_file, hbool_t rw);
static herr_t H5FD__core_unlock(H5FD_t *_file);
static herr_t H5FD__core_delete(const char *filename, hid_t fapl_id);
+static herr_t H5FD__core_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void *input,
+ void **output);
static inline const H5FD_core_fapl_t *H5FD__core_get_default_config(void);
static const H5FD_class_t H5FD_core_g = {
@@ -185,7 +187,7 @@ static const H5FD_class_t H5FD_core_g = {
H5FD__core_lock, /* lock */
H5FD__core_unlock, /* unlock */
H5FD__core_delete, /* del */
- NULL, /* ctl */
+ H5FD__core_ctl, /* ctl */
H5FD_FLMAP_DICHOTOMY /* fl_map */
};
@@ -1755,3 +1757,59 @@ H5FD__core_delete(const char *filename, hid_t fapl_id)
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FD__core_delete() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD__core_ctl
+ *
+ * Purpose: Core VFD version of the ctl callback.
+ *
+ * The desired operation is specified by the op_code
+ * parameter.
+ *
+ * The flags parameter controls management of op_codes that
+ * are unknown to the callback
+ *
+ * The input and output parameters allow op_code specific
+ * input and output
+ *
+ * At present, the only op code supported is
+ * H5FD_CTL__GET_TERMINAL_VFD, which is used to obtain a
+ * pointer to the instance of H5FD_t associated with the
+ * terminal VFD. This allows comparison of files whose
+ * terminal VFD may have overlying pass through VFDs.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Changes: None.
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD__core_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void H5_ATTR_UNUSED *input,
+ void **output)
+{
+ H5FD_core_t *file = (H5FD_core_t *)_file;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE
+
+ /* Sanity checks */
+ HDassert(file);
+
+ switch (op_code) {
+
+ case H5FD_CTL__GET_TERMINAL_VFD:
+ HDassert(output);
+ *output = (void *)(file);
+ break;
+
+ /* Unknown op code */
+ default:
+ if (flags & H5FD_CTL__FAIL_IF_UNKNOWN_FLAG)
+ HGOTO_ERROR(H5E_VFL, H5E_FCNTL, FAIL, "unknown op_code and fail if unknown flag is set")
+ break;
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD__core_ctl() */
diff --git a/src/H5FDdevelop.h b/src/H5FDdevelop.h
index 32cd36f..be3b545 100644
--- a/src/H5FDdevelop.h
+++ b/src/H5FDdevelop.h
@@ -217,10 +217,6 @@ struct H5FD_t {
haddr_t maxaddr; /* For this file, overrides class */
haddr_t base_addr; /* Base address for HDF5 data w/in file */
- H5FD_t *exc_owner; /* Pointer to an exclusive owner
- * or NULL if none.
- */
-
/* Space allocation management fields */
hsize_t threshold; /* Threshold for alignment */
hsize_t alignment; /* Allocation alignment */
diff --git a/src/H5FDdirect.c b/src/H5FDdirect.c
index a6139da..66843e9 100644
--- a/src/H5FDdirect.c
+++ b/src/H5FDdirect.c
@@ -140,6 +140,8 @@ static herr_t H5FD__direct_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closi
static herr_t H5FD__direct_lock(H5FD_t *_file, hbool_t rw);
static herr_t H5FD__direct_unlock(H5FD_t *_file);
static herr_t H5FD__direct_delete(const char *filename, hid_t fapl_id);
+static herr_t H5FD__direct_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void *input,
+ void **output);
static const H5FD_class_t H5FD_direct_g = {
H5FD_DIRECT_VALUE, /* value */
@@ -175,7 +177,7 @@ static const H5FD_class_t H5FD_direct_g = {
H5FD__direct_lock, /* lock */
H5FD__direct_unlock, /* unlock */
H5FD__direct_delete, /* del */
- NULL, /* ctl */
+ H5FD__direct_ctl, /* ctl */
H5FD_FLMAP_DICHOTOMY /* fl_map */
};
@@ -1421,4 +1423,60 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FD__direct_delete() */
+/*-------------------------------------------------------------------------
+ * Function: H5FD__direct_ctl
+ *
+ * Purpose: Direct VFD version of the ctl callback.
+ *
+ * The desired operation is specified by the op_code
+ * parameter.
+ *
+ * The flags parameter controls management of op_codes that
+ * are unknown to the callback
+ *
+ * The input and output parameters allow op_code specific
+ * input and output
+ *
+ * At present, the only op code supported is
+ * H5FD_CTL__GET_TERMINAL_VFD, which is used to obtain the
+ * instance of H5FD_t associated with the terminal
+ * VFD. This allows comparison of files whose terminal
+ * VFD may have overlying pass through VFDs.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Changes: None.
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD__direct_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void H5_ATTR_UNUSED *input,
+ void **output)
+{
+ H5FD_direct_t *file = (H5FD_direct_t *)_file;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE
+
+ /* Sanity checks */
+ HDassert(file);
+
+ switch (op_code) {
+
+ case H5FD_CTL__GET_TERMINAL_VFD:
+ HDassert(output);
+ *output = (void *)(file);
+ break;
+
+ /* Unknown op code */
+ default:
+ if (flags & H5FD_CTL__FAIL_IF_UNKNOWN_FLAG)
+ HGOTO_ERROR(H5E_VFL, H5E_FCNTL, FAIL, "unknown op_code and fail if unknown flag is set")
+ break;
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD__direct_ctl() */
+
#endif /* H5_HAVE_DIRECT */
diff --git a/src/H5FDfamily.c b/src/H5FDfamily.c
index b4cf58e..185ca4e 100644
--- a/src/H5FDfamily.c
+++ b/src/H5FDfamily.c
@@ -109,6 +109,8 @@ static herr_t H5FD__family_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closi
static herr_t H5FD__family_lock(H5FD_t *_file, hbool_t rw);
static herr_t H5FD__family_unlock(H5FD_t *_file);
static herr_t H5FD__family_delete(const char *filename, hid_t fapl_id);
+static herr_t H5FD__family_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void *input,
+ void **output);
/* The class struct */
static const H5FD_class_t H5FD_family_g = {
@@ -145,7 +147,7 @@ static const H5FD_class_t H5FD_family_g = {
H5FD__family_lock, /* lock */
H5FD__family_unlock, /* unlock */
H5FD__family_delete, /* del */
- NULL, /* ctl */
+ H5FD__family_ctl, /* ctl */
H5FD_FLMAP_DICHOTOMY /* fl_map */
};
@@ -1580,3 +1582,63 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FD__family_delete() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD__family_ctl
+ *
+ * Purpose: Family VFD version of the ctl callback.
+ *
+ * The desired operation is specified by the op_code
+ * parameter.
+ *
+ * The flags parameter controls management of op_codes that
+ * are unknown to the callback
+ *
+ * The input and output parameters allow op_code specific
+ * input and output
+ *
+ * At present, the only op code supported is
+ * H5FD_CTL__GET_TERMINAL_VFD, which is used to obtain the
+ * instance of H5FD_t associated with the terminal
+ * VFD. This allows comparison of files whose terminal
+ * VFD may have overlying pass through VFDs.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD__family_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void H5_ATTR_UNUSED *input,
+ void **output)
+{
+ H5FD_family_t *file = (H5FD_family_t *)_file;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE
+
+ /* Sanity checks */
+ HDassert(file);
+
+ switch (op_code) {
+
+ case H5FD_CTL__GET_TERMINAL_VFD:
+ /* On can argue as to whether the family VFD should be regarded as terminal.
+ * It is treated as such here, as it is the lowest VFD through which all I/O
+ * request pass.
+ *
+ * For now at least, this works as this is the level at which files are compared.
+ */
+ HDassert(output);
+ *output = (void *)(file);
+ break;
+
+ /* Unknown op code */
+ default:
+ if (flags & H5FD_CTL__FAIL_IF_UNKNOWN_FLAG)
+ HGOTO_ERROR(H5E_VFL, H5E_FCNTL, FAIL, "unknown op_code and fail if unknown flag is set")
+ break;
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD__sec2_ctl() */
diff --git a/src/H5FDlog.c b/src/H5FDlog.c
index 1c8ff7d..a920cd9 100644
--- a/src/H5FDlog.c
+++ b/src/H5FDlog.c
@@ -178,6 +178,8 @@ static herr_t H5FD__log_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing)
static herr_t H5FD__log_lock(H5FD_t *_file, hbool_t rw);
static herr_t H5FD__log_unlock(H5FD_t *_file);
static herr_t H5FD__log_delete(const char *filename, hid_t fapl_id);
+static herr_t H5FD__log_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void *input,
+ void **output);
static const H5FD_class_t H5FD_log_g = {
H5FD_LOG_VALUE, /* value */
@@ -213,7 +215,7 @@ static const H5FD_class_t H5FD_log_g = {
H5FD__log_lock, /* lock */
H5FD__log_unlock, /* unlock */
H5FD__log_delete, /* del */
- NULL, /* ctl */
+ H5FD__log_ctl, /* ctl */
H5FD_FLMAP_DICHOTOMY /* fl_map */
};
@@ -1789,3 +1791,60 @@ H5FD__log_delete(const char *filename, hid_t H5_ATTR_UNUSED fapl_id)
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FD__log_delete() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD__log_ctl
+ *
+ * Purpose: log VFD version of the ctl callback.
+ *
+ * The desired operation is specified by the op_code
+ * parameter.
+ *
+ * The flags parameter controls management of op_codes that
+ * are unknown to the callback
+ *
+ * The input and output parameters allow op_code specific
+ * input and output
+ *
+ * At present, the only op code supported is
+ * H5FD_CTL__GET_TERMINAL_VFD, which is used to obtain the
+ * instance of H5FD_t associated with the terminal
+ * VFD. This allows comparison of files whose terminal
+ * VFD may have overlying pass through VFDs.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Changes: Added support for H5FD_CTL__GET_TERMINAL_VFD.
+ * JRM -- 5/4/22
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD__log_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void H5_ATTR_UNUSED *input,
+ void **output)
+{
+ H5FD_log_t *file = (H5FD_log_t *)_file;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE
+
+ /* Sanity checks */
+ HDassert(file);
+
+ switch (op_code) {
+
+ case H5FD_CTL__GET_TERMINAL_VFD:
+ HDassert(output);
+ *output = (void *)(file);
+ break;
+
+ /* Unknown op code */
+ default:
+ if (flags & H5FD_CTL__FAIL_IF_UNKNOWN_FLAG)
+ HGOTO_ERROR(H5E_VFL, H5E_FCNTL, FAIL, "unknown op_code and fail if unknown flag is set")
+ break;
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD__log_ctl() */
diff --git a/src/H5FDmpio.c b/src/H5FDmpio.c
index 6a168c7..cd59285 100644
--- a/src/H5FDmpio.c
+++ b/src/H5FDmpio.c
@@ -1918,6 +1918,9 @@ done:
*
* Programmer: JRM -- 8/3/21
*
+ * Changes: Added support for H5FD_CTL__GET_TERMINAL_VFD.
+ * JRM -- 5/4/22
+ *
*-------------------------------------------------------------------------
*/
static herr_t
@@ -1953,6 +1956,11 @@ H5FD__mpio_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void H5_AT
**((int **)output) = file->mpi_size;
break;
+ case H5FD_CTL__GET_TERMINAL_VFD:
+ HDassert(output);
+ *output = (void *)(file);
+ break;
+
default: /* unknown op code */
if (flags & H5FD_CTL__FAIL_IF_UNKNOWN_FLAG) {
diff --git a/src/H5FDmulti.c b/src/H5FDmulti.c
index d9a6ce9..faf4b87 100644
--- a/src/H5FDmulti.c
+++ b/src/H5FDmulti.c
@@ -2243,6 +2243,9 @@ H5_MULTI_GCC_DIAG_ON("format-nonliteral")
*
* Return: Non-negative on success/Negative on failure
*
+ * Changes: Added support for H5FD_CTL__GET_TERMINAL_VFD.
+ * JRM -- 5/4/22
+ *
*-------------------------------------------------------------------------
*/
static herr_t
@@ -2261,6 +2264,18 @@ H5FD_multi_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void *inpu
H5Eclear2(H5E_DEFAULT);
switch (op_code) {
+
+ case H5FD_CTL__GET_TERMINAL_VFD:
+ /* One can argue as to whether the multi VFD should be regarded as terminal.
+ * It is treated as such here, as it is the lowest VFD through which all I/O
+ * request pass.
+ *
+ * For now at least, this works as this is the level at which files are compared.
+ */
+ assert(output);
+ *output = (void *)(file);
+ break;
+
/* Unknown op code */
default:
if (flags & H5FD_CTL__FAIL_IF_UNKNOWN_FLAG)
diff --git a/src/H5FDpublic.h b/src/H5FDpublic.h
index 9411874..94ab92b 100644
--- a/src/H5FDpublic.h
+++ b/src/H5FDpublic.h
@@ -203,6 +203,7 @@
#define H5FD_CTL__MEM_ALLOC 5
#define H5FD_CTL__MEM_FREE 6
#define H5FD_CTL__MEM_COPY 7
+#define H5FD_CTL__GET_TERMINAL_VFD 8
/* ctl function flags: */
diff --git a/src/H5FDros3.c b/src/H5FDros3.c
index 4b15616..3aae108 100644
--- a/src/H5FDros3.c
+++ b/src/H5FDros3.c
@@ -233,6 +233,8 @@ static herr_t H5FD__ros3_read(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, ha
static herr_t H5FD__ros3_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr, size_t size,
const void *buf);
static herr_t H5FD__ros3_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
+static herr_t H5FD__ros3_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void *input,
+ void **output);
static herr_t H5FD__ros3_validate_config(const H5FD_ros3_fapl_t *fa);
@@ -270,7 +272,7 @@ static const H5FD_class_t H5FD_ros3_g = {
NULL, /* lock */
NULL, /* unlock */
NULL, /* del */
- NULL, /* ctl */
+ H5FD__ros3_ctl, /* ctl */
H5FD_FLMAP_DICHOTOMY /* fl_map */
};
@@ -1563,4 +1565,60 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FD__ros3_truncate() */
+/*-------------------------------------------------------------------------
+ * Function: H5FD__ros3_ctl
+ *
+ * Purpose: ROS3 VFD version of the ctl callback.
+ *
+ * The desired operation is specified by the op_code
+ * parameter.
+ *
+ * The flags parameter controls management of op_codes that
+ * are unknown to the callback
+ *
+ * The input and output parameters allow op_code specific
+ * input and output
+ *
+ * At present, the only op code supported is
+ * H5FD_CTL__GET_TERMINAL_VFD, which is used to obtain the
+ * instance of H5FD_t associated with the terminal
+ * VFD. This allows comparison of files whose terminal
+ * VFD may have overlying pass through VFDs.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Changes: None,
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD__ros3_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void H5_ATTR_UNUSED *input,
+ void **output)
+{
+ H5FD_ros3_t *file = (H5FD_ros3_t *)_file;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE
+
+ /* Sanity checks */
+ HDassert(file);
+
+ switch (op_code) {
+
+ case H5FD_CTL__GET_TERMINAL_VFD:
+ HDassert(output);
+ *output = (void *)(file);
+ break;
+
+ /* Unknown op code */
+ default:
+ if (flags & H5FD_CTL__FAIL_IF_UNKNOWN_FLAG)
+ HGOTO_ERROR(H5E_VFL, H5E_FCNTL, FAIL, "unknown op_code and fail if unknown flag is set")
+ break;
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD__ros3_ctl() */
+
#endif /* H5_HAVE_ROS3_VFD */
diff --git a/src/H5FDsec2.c b/src/H5FDsec2.c
index accacb6..b88605c 100644
--- a/src/H5FDsec2.c
+++ b/src/H5FDsec2.c
@@ -1064,15 +1064,20 @@ done:
* The input and output parameters allow op_code specific
* input and output
*
- * At present, no op codes are supported by this VFD.
+ * At present, the only op code supported is
+ * H5FD_CTL__GET_TERMINAL_VFD, which is used in the
+ * comparison of files under layers of pass through VFDs.
*
* Return: Non-negative on success/Negative on failure
*
+ * Changes: Added support for H5FD_CTL__GET_TERMINAL_VFD.
+ * JRM -- 5/4/22
+ *
*-------------------------------------------------------------------------
*/
static herr_t
H5FD__sec2_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void H5_ATTR_UNUSED *input,
- void H5_ATTR_UNUSED **output)
+ void **output)
{
H5FD_sec2_t *file = (H5FD_sec2_t *)_file;
herr_t ret_value = SUCCEED;
@@ -1083,6 +1088,12 @@ H5FD__sec2_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void H5_AT
HDassert(file);
switch (op_code) {
+
+ case H5FD_CTL__GET_TERMINAL_VFD:
+ HDassert(output);
+ *output = (void *)(file);
+ break;
+
/* Unknown op code */
default:
if (flags & H5FD_CTL__FAIL_IF_UNKNOWN_FLAG)
diff --git a/src/H5FDstdio.c b/src/H5FDstdio.c
index b59aae3..ad59bc9 100644
--- a/src/H5FDstdio.c
+++ b/src/H5FDstdio.c
@@ -181,6 +181,8 @@ static herr_t H5FD_stdio_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing
static herr_t H5FD_stdio_lock(H5FD_t *_file, hbool_t rw);
static herr_t H5FD_stdio_unlock(H5FD_t *_file);
static herr_t H5FD_stdio_delete(const char *filename, hid_t fapl_id);
+static herr_t H5FD__stdio_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void *input,
+ void **output);
static const H5FD_class_t H5FD_stdio_g = {
H5_VFD_STDIO, /* value */
@@ -216,7 +218,7 @@ static const H5FD_class_t H5FD_stdio_g = {
H5FD_stdio_lock, /* lock */
H5FD_stdio_unlock, /* unlock */
H5FD_stdio_delete, /* del */
- NULL, /* ctl */
+ H5FD__stdio_ctl, /* ctl */
H5FD_FLMAP_DICHOTOMY /* fl_map */
};
@@ -1233,6 +1235,64 @@ H5FD_stdio_delete(const char *filename, hid_t /*UNUSED*/ fapl_id)
return 0;
} /* end H5FD_stdio_delete() */
+/*-------------------------------------------------------------------------
+ * Function: H5FD__stdio_ctl
+ *
+ * Purpose: Sec2 VFD version of the ctl callback.
+ *
+ * The desired operation is specified by the op_code
+ * parameter.
+ *
+ * The flags parameter controls management of op_codes that
+ * are unknown to the callback
+ *
+ * The input and output parameters allow op_code specific
+ * input and output
+ *
+ * At present, the only op code supported is
+ * H5FD_CTL__GET_TERMINAL_VFD, which is used to obtain the
+ * instance of H5FD_t associated with the terminal
+ * VFD. This allows comparison of files whose terminal
+ * VFD may have overlying pass through VFDs.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Changes: None.
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD__stdio_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void /* UNUSED */ *input,
+ void **output)
+{
+ static const char *func = "H5FD__stdio_ctl"; /* Function Name for error reporting */
+ H5FD_stdio_t * file = (H5FD_stdio_t *)_file;
+
+ /* Clear the error stack */
+ H5Eclear2(H5E_DEFAULT);
+
+ /* Quiet compiler */
+ (void)input;
+
+ switch (op_code) {
+
+ case H5FD_CTL__GET_TERMINAL_VFD:
+ assert(output);
+ *output = (void *)(file);
+ break;
+
+ /* Unknown op code */
+ default:
+ if (flags & H5FD_CTL__FAIL_IF_UNKNOWN_FLAG)
+ H5Epush_ret(func, H5E_ERR_CLS, H5E_VFL, H5E_FCNTL,
+ "unknown op_code and fail if unknown flag is set", -1);
+ break;
+ }
+
+ return (0); /* SUCCEED */
+
+} /* end H5FD__stdio_ctl() */
+
#ifdef H5private_H
/*
* This is not related to the functionality of the driver code.
diff --git a/src/H5FDvfd_swmr.c b/src/H5FDvfd_swmr.c
index 892d084..a8f588d 100644
--- a/src/H5FDvfd_swmr.c
+++ b/src/H5FDvfd_swmr.c
@@ -34,6 +34,8 @@ static hid_t H5FD_VFD_SWMR_g = 0;
typedef struct H5FD_vfd_swmr_t {
H5FD_t pub; /* public stuff, must be first */
+ H5FD_vfd_swmr_reader_fapl_t fa; /* driver-specific file access properties */
+
/* HDF5 file */
char hdf5_filename[H5FD_MAX_FILENAME_LEN]; /* Name of the HDF5 file from open */
H5FD_t *hdf5_file_lf; /* Driver info for the HDF5 file */
@@ -56,11 +58,6 @@ typedef struct H5FD_vfd_swmr_t {
hbool_t pb_configured; /* Sanity-checking flag set when page buffer is configured */
H5F_vfd_swmr_config_t config; /* VFD SWMR configuration */
- /* Flag set if the file is a SWMR writer.
- * All methods on a write-mode SWMR VFD instance are passed
- * to the lower VFD instance.
- */
- hbool_t writer;
/*
* Indicate whether we are in make_believe state or not
*/
@@ -73,6 +70,9 @@ typedef struct H5FD_vfd_swmr_t {
/* Prototypes */
static herr_t H5FD__vfd_swmr_term(void);
+static void * H5FD__vfd_swmr_fapl_get(H5FD_t *_file);
+static void * H5FD__vfd_swmr_fapl_copy(const void *_old_fa);
+static herr_t H5FD__vfd_swmr_fapl_free(void *_fapl);
static H5FD_t *H5FD__vfd_swmr_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr);
static herr_t H5FD__vfd_swmr_close(H5FD_t *_file);
static int H5FD__vfd_swmr_cmp(const H5FD_t *_f1, const H5FD_t *_f2);
@@ -88,6 +88,8 @@ static herr_t H5FD__vfd_swmr_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_i
static herr_t H5FD__vfd_swmr_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
static herr_t H5FD__vfd_swmr_lock(H5FD_t *_file, hbool_t rw);
static herr_t H5FD__vfd_swmr_unlock(H5FD_t *_file);
+static herr_t H5FD__vfd_swmr_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void *input,
+ void **output);
/* VFD SWMR */
static htri_t H5FD__vfd_swmr_header_deserialize(H5FD_vfd_swmr_t *, H5FD_vfd_swmr_md_header *);
@@ -96,46 +98,49 @@ static htri_t H5FD__vfd_swmr_index_deserialize(const H5FD_vfd_swmr_t *file, H5FD
static herr_t H5FD__vfd_swmr_load_hdr_and_idx(H5FD_vfd_swmr_t *, hbool_t);
static const H5FD_class_t H5FD_vfd_swmr_g = {
- H5FD_VFD_SWMR_VALUE, /* value */
- "vfd_swmr", /* name */
- MAXADDR, /* maxaddr */
- H5F_CLOSE_WEAK, /* fc_degree */
- H5FD__vfd_swmr_term, /* terminate */
- NULL, /* sb_size */
- NULL, /* sb_encode */
- NULL, /* sb_decode */
- 0, /* fapl_size */
- NULL, /* fapl_get */
- NULL, /* fapl_copy */
- NULL, /* fapl_free */
- 0, /* dxpl_size */
- NULL, /* dxpl_copy */
- NULL, /* dxpl_free */
- H5FD__vfd_swmr_open, /* open */
- H5FD__vfd_swmr_close, /* close */
- H5FD__vfd_swmr_cmp, /* cmp */
- H5FD__vfd_swmr_query, /* query */
- NULL, /* get_type_map */
- NULL, /* alloc */
- NULL, /* free */
- H5FD__vfd_swmr_get_eoa, /* get_eoa */
- H5FD__vfd_swmr_set_eoa, /* set_eoa */
- H5FD__vfd_swmr_get_eof, /* get_eof */
- H5FD__vfd_swmr_get_handle, /* get_handle */
- H5FD__vfd_swmr_read, /* read */
- H5FD__vfd_swmr_write, /* write */
- NULL, /* flush */
- H5FD__vfd_swmr_truncate, /* truncate */
- H5FD__vfd_swmr_lock, /* lock */
- H5FD__vfd_swmr_unlock, /* unlock */
- NULL, /* del */
- NULL, /* ctl */
- H5FD_FLMAP_DICHOTOMY /* fl_map */
+ H5FD_VFD_SWMR_VALUE, /* value */
+ "vfd_swmr", /* name */
+ MAXADDR, /* maxaddr */
+ H5F_CLOSE_WEAK, /* fc_degree */
+ H5FD__vfd_swmr_term, /* terminate */
+ NULL, /* sb_size */
+ NULL, /* sb_encode */
+ NULL, /* sb_decode */
+ sizeof(H5FD_vfd_swmr_reader_fapl_t), /* fapl_size */
+ H5FD__vfd_swmr_fapl_get, /* fapl_get */
+ H5FD__vfd_swmr_fapl_copy, /* fapl_copy */
+ H5FD__vfd_swmr_fapl_free, /* fapl_free */
+ 0, /* dxpl_size */
+ NULL, /* dxpl_copy */
+ NULL, /* dxpl_free */
+ H5FD__vfd_swmr_open, /* open */
+ H5FD__vfd_swmr_close, /* close */
+ H5FD__vfd_swmr_cmp, /* cmp */
+ H5FD__vfd_swmr_query, /* query */
+ NULL, /* get_type_map */
+ NULL, /* alloc */
+ NULL, /* free */
+ H5FD__vfd_swmr_get_eoa, /* get_eoa */
+ H5FD__vfd_swmr_set_eoa, /* set_eoa */
+ H5FD__vfd_swmr_get_eof, /* get_eof */
+ H5FD__vfd_swmr_get_handle, /* get_handle */
+ H5FD__vfd_swmr_read, /* read */
+ H5FD__vfd_swmr_write, /* write */
+ NULL, /* flush */
+ H5FD__vfd_swmr_truncate, /* truncate */
+ H5FD__vfd_swmr_lock, /* lock */
+ H5FD__vfd_swmr_unlock, /* unlock */
+ NULL, /* del */
+ H5FD__vfd_swmr_ctl, /* ctl */
+ H5FD_FLMAP_DICHOTOMY /* fl_map */
};
/* Declare a free list to manage the H5FD_vfd_swmr_t struct */
H5FL_DEFINE_STATIC(H5FD_vfd_swmr_t);
+/* Declare a free list to manage the H5FD_vfd_swmr_reader_config_t struct */
+H5FL_DEFINE_STATIC(H5FD_vfd_swmr_reader_fapl_t);
+
/* Declare a free list to manage the H5FD_vfd_swmr_idx_entry_t sequence information */
H5FL_SEQ_DEFINE(H5FD_vfd_swmr_idx_entry_t);
@@ -187,32 +192,301 @@ H5FD__vfd_swmr_term(void)
} /* end H5FD__vfd_swmr_term() */
/*-------------------------------------------------------------------------
- * Function: H5Pset_fapl_vfd_swmr (Not yet)
+ * Function: H5FD__vfd_swmr_fapl_get
+ *
+ * Purpose: Returns a file access property list which indicates how the
+ * specified file is being accessed. The return list could be
+ * used to access another file the same way.
+ *
+ * Return: Success: Ptr to new file access property list with all
+ * members copied from the file struct.
+ * Failure: NULL
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5FD__vfd_swmr_fapl_get(H5FD_t *_file)
+{
+ H5FD_vfd_swmr_t *file = (H5FD_vfd_swmr_t *)_file;
+ void * ret_value = NULL;
+
+ FUNC_ENTER_PACKAGE_NOERR
+
+ ret_value = H5FD__vfd_swmr_fapl_copy(&(file->fa));
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* end H5FD__vfd_swmr_fapl_get() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD__vfd_swmr_fapl_copy
+ *
+ * Purpose: Copies the file access properties.
+ *
+ * Return: Success: Pointer to a new property list info structure.
+ * Failure: NULL
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5FD__vfd_swmr_fapl_copy(const void *_old_fa)
+{
+ const H5FD_vfd_swmr_reader_fapl_t *old_fa_ptr = (const H5FD_vfd_swmr_reader_fapl_t *)_old_fa;
+ H5FD_vfd_swmr_reader_fapl_t * new_fa_ptr = NULL;
+ void * ret_value = NULL;
+
+ FUNC_ENTER_PACKAGE
+
+ HDassert(old_fa_ptr);
+ HDassert(old_fa_ptr->magic == H5FD_VFD_SWMR_READER_MAGIC);
+
+ new_fa_ptr = H5FL_CALLOC(H5FD_vfd_swmr_reader_fapl_t);
+ if (NULL == new_fa_ptr)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, NULL, "unable to allocate vfd swmr FAPL")
+
+ H5MM_memcpy(new_fa_ptr, old_fa_ptr, sizeof(H5FD_vfd_swmr_reader_fapl_t));
+
+ ret_value = (void *)new_fa_ptr;
+
+done:
+ if (NULL == ret_value) {
+ if (new_fa_ptr) {
+ new_fa_ptr->magic = 0;
+ new_fa_ptr = H5FL_FREE(H5FD_vfd_swmr_reader_fapl_t, new_fa_ptr);
+ }
+ }
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* end H5FD__vfd_swmr_fapl_copy() */
+
+/*--------------------------------------------------------------------------
+ * Function: H5FD__vfd_swmr_fapl_free
+ *
+ * Purpose: Releases the file access lists
+ *
+ * Return: SUCCEED/FAIL
+ *--------------------------------------------------------------------------
+ */
+static herr_t
+H5FD__vfd_swmr_fapl_free(void *_fapl)
+{
+ H5FD_vfd_swmr_reader_fapl_t *fapl = (H5FD_vfd_swmr_reader_fapl_t *)_fapl;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE
+
+ /* Check arguments */
+ if ((NULL == fapl) || (fapl->magic != H5FD_VFD_SWMR_READER_MAGIC))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL or invalid H5FD_vfd_swmr_reader_fapl_t *")
+
+ /* Free the property list */
+ fapl->magic = 0;
+ fapl = H5FL_FREE(H5FD_vfd_swmr_reader_fapl_t, fapl);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* end H5FD__vfd_swmr_fapl_free() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5P_pop_vfd_swmr_reader_vfd_off_fapl
+ *
+ * Purpose: After a file has been opened in VFD SWMR reader mode, we
+ * must pop the vfd swmr reader driver entry off the supplied
+ * fapl. If we don't, and the fapl is used to open a second
+ * file (i.e. via virtual data sets), we would have multiple
+ * vfd swmr reader driver entries pushed on the vfd stack.
+ *
+ * Do this as follows:
*
- * Purpose: Modify the file access property list to use the H5FD_SWMR
- * driver
+ * 1) Read the file driver entry from the supplied fapl. Verify
+ * that it specifies the vfd swmr reader VFD.
+ *
+ * 2) Read the file driver entry from the sub fapl specified
+ * in the vfd swmr reader vfd fapl entry. Set the file
+ * driver entry on the supplied fapl equal to that on
+ * the sub-fapl.
+ *
+ * 3) Discard the sub-fapl? Not sure if this is necessary.
*
* Return: SUCCEED/FAIL
*
+ * Programmer JRM -- 4/28/22
+ *
*-------------------------------------------------------------------------
*/
herr_t
-H5Pset_fapl_vfd_swmr(hid_t fapl_id)
+H5P_pop_vfd_swmr_reader_vfd_off_fapl(hid_t fapl_id)
{
- H5P_genplist_t *plist; /* Property list pointer */
- herr_t ret_value;
+ H5FD_driver_prop_t driver_prop; /* Property for driver ID & info */
+ H5P_genplist_t * plist_ptr = NULL;
+ hid_t sub_fapl_id;
+ H5P_genplist_t * sub_plist_ptr = NULL;
+ herr_t ret_value = SUCCEED;
- FUNC_ENTER_API(FAIL)
- H5TRACE1("e", "i", fapl_id);
+ FUNC_ENTER_NOAPI(FAIL)
- if (NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS)))
+ /* sanity checks -- get ptr to plist in passing */
+ if (NULL == (plist_ptr = H5P_object_verify(fapl_id, H5P_FILE_ACCESS)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")
- ret_value = H5P_set_driver(plist, H5FD_VFD_SWMR, NULL, NULL);
+ /* 1) Read the file driver entry from the supplied fapl. Verify
+ * that it specifies the vfd swmr reader VFD.
+ */
+
+ /* get the driver property from the supplied fapl */
+ if (H5P_peek(plist_ptr, H5F_ACS_FILE_DRV_NAME, &driver_prop) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get file driver ID & info")
+
+ /* verify that it specifies the vfd swrm reader vfd */
+ if (driver_prop.driver_id != H5FD_VFD_SWMR)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "fapl driver prop not vfd swmr reader")
+
+ if ((((const H5FD_vfd_swmr_reader_fapl_t *)(driver_prop.driver_info)) == NULL) ||
+ (((const H5FD_vfd_swmr_reader_fapl_t *)(driver_prop.driver_info))->magic !=
+ H5FD_VFD_SWMR_READER_MAGIC))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "fapl driver info invalid")
+
+ sub_fapl_id = ((const H5FD_vfd_swmr_reader_fapl_t *)(driver_prop.driver_info))->fapl_id;
+
+ /* 2) Read the file driver entry from the sub fapl specified
+ * in the vfd swmr reader vfd fapl entry. Set the file
+ * driver entry on the supplied fapl equal to that on
+ * the sub-fapl.
+ */
+ /* get a pointer to the sub-fapl */
+ if (NULL == (sub_plist_ptr = (H5P_genplist_t *)H5I_object(sub_fapl_id)))
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get sub-fapl pointer")
+
+ /* get the driver property from the sub-fapl */
+ if (H5P_peek(sub_plist_ptr, H5F_ACS_FILE_DRV_NAME, &driver_prop) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get sub-fapl file driver ID & info")
+
+ /* insert the driver info from the sub-fapl into the supplied fapl. There is
+ * some question in my mind as to whether I should be making a copy of the
+ * info and string obtained above. While I don't think it is necessary,
+ * if we get occult failures, this is a good place to look.
+ *
+ * Note that for now, the driver info on the sub-fapl should only specify the
+ * sec2 VFD -- which has NULL info and config string. Thus, if it is an
+ * issue, it may not appear immediately.
+ */
+ if (H5P_set_driver(plist_ptr, driver_prop.driver_id, driver_prop.driver_info,
+ driver_prop.driver_config_str) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't set driver on supplied fapl")
+
+ /* 3) Discard the sub-fapl? Not sure if this is necessary. Will wait on this for now. */
done:
- FUNC_LEAVE_API(ret_value)
-} /* end H5Pset_fapl_vfd_swmr() */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* end H5P_pop_vfd_swmr_reader_vfd_off_fapl() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5P_push_vfd_swmr_reader_vfd_on_fapl
+ *
+ * Purpose: When a file is opened in VFD SWMR reader mode, we must
+ * adjust the fapl so as to push the VFD SWMR reader vfd on
+ * the VFD stack specified in the fapl.
+ *
+ * Do this as follows:
+ *
+ * 1) Copy the file driver from the supplied fapl. Note
+ * that due to potential VFD stacking, we can't verify
+ * that this VFD supports vfd swmr. This will have to
+ * wait until after the file is opened.
+ *
+ * 2) Create a new FAPL, and set the file driver obtained
+ * in 1) in the new FAPL.
+ *
+ * 3) Allocate a new instance of H5FD_vfd_swmr_reader_config_t,
+ * load it with the ID of the FAPL created in 2, and use
+ * it to overwrite the file driver entry in the supplied
+ * FAPL.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer JRM -- 4/28/22
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5P_push_vfd_swmr_reader_vfd_on_fapl(hid_t fapl_id)
+{
+ H5FD_driver_prop_t driver_prop; /* Property for driver ID & info */
+ H5FD_vfd_swmr_reader_fapl_t *info = NULL;
+ H5P_genplist_t * plist_ptr = NULL;
+ hid_t sub_fapl_id;
+ H5P_genplist_t * sub_plist_ptr = NULL;
+ H5P_genclass_t * pclass = NULL;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* sanity checks -- get ptr to plist in passing */
+ if (NULL == (plist_ptr = H5P_object_verify(fapl_id, H5P_FILE_ACCESS)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")
+
+ /* 1) Copy the file driver from the supplied fapl. Note
+ * that due to potential VFD stacking, we can't verify
+ * that this VFD supports vfd swmr. This will have to
+ * wait until after the file is opened.
+ */
+
+ /* get the driver property from the supplied fapl */
+ if (H5P_peek(plist_ptr, H5F_ACS_FILE_DRV_NAME, &driver_prop) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get init driver ID & info")
+
+ /* 2) Create a new FAPL, and set the file driver obtained in 1) in the new FAPL. */
+
+ /* create a new FAPL */
+ if (NULL == (pclass = (H5P_genclass_t *)H5I_object_verify(H5P_FILE_ACCESS, H5I_GENPROP_CLS)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a property list class");
+
+ if ((sub_fapl_id = H5P_create_id(pclass, TRUE)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTCREATE, H5I_INVALID_HID, "unable to create fapl");
+
+ /* get a pointer to it */
+ if (NULL == (sub_plist_ptr = (H5P_genplist_t *)H5I_object(sub_fapl_id)))
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get sub-fapl pointer")
+
+ /* insert the driver info from the base fapl into the sub-fapl. There is
+ * some question in my mind as to whether I should be making a copy of the
+ * info and string obtained above. While I don't think it is necessary,
+ * if we get occult failures, this is a good place to look.
+ *
+ * Note that for now, the driver info being inserted in sub-fapl should only specify
+ * the sec2 VFD -- which has NULL info and config string. Thus, if it is an
+ * issue, it may not appear immediately.
+ */
+ if (H5P_set_driver(sub_plist_ptr, driver_prop.driver_id, driver_prop.driver_info,
+ driver_prop.driver_config_str) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't set driver on sub-fapl")
+
+ /* 3) Allocate a new instance of H5FD_vfd_swmr_reader_config_t,
+ * load it with the ID of the FAPL created in 2, and use
+ * it to overwrite the file driver entry in the supplied
+ * FAPL.
+ */
+
+ info = H5FL_CALLOC(H5FD_vfd_swmr_reader_fapl_t);
+ if (NULL == info)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "unable to allocate vfd swmr fapl struct")
+
+ /* initialize the vfd swmr reader vfd info */
+ info->magic = H5FD_VFD_SWMR_READER_MAGIC;
+ info->fapl_id = sub_fapl_id;
+
+ /* set the driver on the main fapl */
+ ret_value = H5P_set_driver(plist_ptr, H5FD_VFD_SWMR, info, NULL);
+
+done:
+ if (info)
+ info = H5FL_FREE(H5FD_vfd_swmr_reader_fapl_t, info);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* end H5P_push_vfd_swmr_reader_vfd_on_fapl() */
/*-------------------------------------------------------------------------
* Function: H5FD__swmr_reader_open
@@ -271,60 +545,6 @@ done:
} /* end H5FD__swmr_reader_open() */
/*-------------------------------------------------------------------------
- *
- * Function: H5FD__vfd_swmr_build_md_path_name
- *
- * Purpose: To construct the metadata file's full name based on config's
- * md_file_path and md_file_name. See RFC for details.
- *
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: Vailin Choi -- 1/13/2022
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5FD__vfd_swmr_build_md_path_name(H5F_vfd_swmr_config_t *config, const char *hdf5_filename,
- char *name /*out*/)
-{
- size_t tot_len = 0;
- size_t tmp_len = 0;
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_PACKAGE
-
- if ((tot_len = HDstrlen(config->md_file_path)) != 0) {
-
- /* md_file_path + '/' */
- if (++tot_len > H5F__MAX_VFD_SWMR_FILE_NAME_LEN)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, FAIL, "md_file_path and md_file_name exceeds maximum");
- HDstrcat(name, config->md_file_path);
- HDstrcat(name, "/");
- }
-
- if ((tmp_len = HDstrlen(config->md_file_name)) != 0) {
- if ((tot_len += tmp_len) > H5F__MAX_VFD_SWMR_FILE_NAME_LEN)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, FAIL, "md_file_path and md_file_name exceeds maximum");
- HDstrcat(name, config->md_file_name);
- }
- else {
- /* Automatic generation of metadata file name based on hdf5_filename + '.md' */
- if ((tot_len += (HDstrlen(hdf5_filename) + 3)) > H5F__MAX_VFD_SWMR_FILE_NAME_LEN)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, FAIL, "md_file_path and md_file_name maximum");
-
- HDstrcat(name, hdf5_filename);
- HDstrcat(name, VFD_SWMR_MD_SUFFIX);
- }
-
-done:
-
- FUNC_LEAVE_NOAPI(ret_value)
-
-} /* H5FD__vfd_swmr_build_md_path_name() */
-
-/*-------------------------------------------------------------------------
* Function: H5FD__vfd_swmr_create_make_believe_data
*
* Purpose: Set up pretend data when make_believe is true
@@ -377,15 +597,19 @@ H5FD__vfd_swmr_create_make_believe_data(H5FD_vfd_swmr_t *_file)
static H5FD_t *
H5FD__vfd_swmr_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
{
- H5FD_vfd_swmr_t * file = NULL;
- size_t page_buf_size;
- H5P_genplist_t * plist;
- H5F_vfd_swmr_config_t *vfd_swmr_config;
- H5FD_t * ret_value = NULL; /* Return value */
- htri_t is_hdf5;
+ H5FD_vfd_swmr_t * file = NULL;
+ size_t page_buf_size;
+ H5P_genplist_t * plist;
+ H5F_vfd_swmr_config_t * vfd_swmr_config;
+ const H5FD_vfd_swmr_reader_fapl_t *fa_ptr = NULL;
+ H5FD_t * ret_value = NULL; /* Return value */
+ htri_t is_hdf5;
FUNC_ENTER_PACKAGE
+ /* VFD SWMR reader VFD should only be called to open a file read only */
+ HDassert((H5F_ACC_RDWR & flags) == 0);
+
/* Get file access property list */
if (NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list")
@@ -404,12 +628,33 @@ H5FD__vfd_swmr_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t max
if (NULL == (file = H5FL_CALLOC(H5FD_vfd_swmr_t)))
HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, NULL, "unable to allocate file struct")
+ /* get the vfd swrm reader fapl entry. */
+ if (H5P_peek_driver(plist) != H5FD_VFD_SWMR)
+ HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, NULL, "incorrect VFL driver");
+
+ fa_ptr = (const H5FD_vfd_swmr_reader_fapl_t *)H5P_peek_driver_info(plist);
+ if (NULL == fa_ptr)
+ HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, NULL, "bad VFL driver info");
+
+ HDassert(fa_ptr->magic == H5FD_VFD_SWMR_READER_MAGIC); /* sanity check */
+
+ /* the fapl id stored in fa_ptr->fapl_id should contain a driver entry that
+ * specifies a VFD that supports VFD SWMR. Since there may be a stack of
+ * VFDs, we can't check this until after file open. Further, the vfd swmr
+ * reader vfd is currently hard coded to use the sec2 vfd as its underlying
+ * vfd. Thus we just save a copy of the H5FD_vfd_swmr_reader_fapl_t for
+ * now.
+ */
+ H5MM_memcpy(&(file->fa), fa_ptr, sizeof(H5FD_vfd_swmr_reader_fapl_t));
+
vfd_swmr_config = &file->config;
/* Get VFD SWMR configuration */
if (H5P_get(plist, H5F_ACS_VFD_SWMR_CONFIG_NAME, vfd_swmr_config) < 0)
HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "can't get VFD SWMR config info")
+ HDassert(!vfd_swmr_config->writer);
+
file->md_fd = -1;
file->hdf5_file_lf = NULL;
file->md_pages_reserved = vfd_swmr_config->md_pages_reserved;
@@ -419,13 +664,11 @@ H5FD__vfd_swmr_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t max
file->hdf5_filename[sizeof(file->hdf5_filename) - 1] = '\0';
/* Retain a copy of the metadata file name */
- if (H5FD__vfd_swmr_build_md_path_name(vfd_swmr_config, name, file->md_file_path_name) < 0)
+ if (H5F_vfd_swmr_build_md_path_name(vfd_swmr_config, name, file->md_file_path_name) < 0)
HGOTO_ERROR(H5E_VFL, H5E_OPENERROR, NULL, "building md_file_path and md_file_name failed")
file->md_file_path_name[sizeof(file->md_file_path_name) - 1] = '\0';
- file->writer = vfd_swmr_config->writer;
-
/* Make sure the hdf5 file exists and is valid */
is_hdf5 = H5F__is_hdf5(name, H5P_FILE_ACCESS_DEFAULT);
@@ -448,8 +691,6 @@ H5FD__vfd_swmr_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t max
if ((file->hdf5_file_lf = H5FD_open(name, flags, H5P_FILE_ACCESS_DEFAULT, maxaddr)) == NULL)
HGOTO_ERROR(H5E_VFL, H5E_CANTOPENFILE, NULL, "can't set driver info");
- file->hdf5_file_lf->exc_owner = &file->pub;
-
/* set pb_configured to FALSE. This field should not exist, but
* until we modify the file open procedure to create the page buffer
* before there is any file I/O when opening a file VFD SWMR reader,
@@ -474,40 +715,6 @@ done:
} /* end H5FD__vfd_swmr_open() */
/*-------------------------------------------------------------------------
- * Function: H5FD__swmr_reader_close
- *
- * Purpose: Perform the reader-only aspects of closing in VFD SWMR mode:
- * optionally log and always release the histogram of ticks spent
- * in API calls, close the shadow file, release the shadow index.
- *
- * Return: void
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5FD__swmr_reader_close(H5FD_vfd_swmr_t *file)
-{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_PACKAGE
-
- if (file->api_elapsed_ticks != NULL)
- H5MM_xfree(file->api_elapsed_ticks);
-
- /* Close the metadata file */
- if (file->md_fd >= 0 && HDclose(file->md_fd) < 0)
- /* Push error, but keep going */
- HDONE_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, FAIL, "unable to close the metadata file");
-
- /* Free the index entries */
- if (file->md_index.num_entries && file->md_index.entries)
- file->md_index.entries = H5FL_SEQ_FREE(H5FD_vfd_swmr_idx_entry_t, file->md_index.entries);
-
- FUNC_LEAVE_NOAPI(ret_value)
-
-} /* end H5FD__swmr_reader_close() */
-
-/*-------------------------------------------------------------------------
* Function: H5FD__vfd_swmr_close
*
* Purpose: Handle closing for VFD SWMR driver
@@ -529,10 +736,6 @@ H5FD__vfd_swmr_close(H5FD_t *_file)
FUNC_ENTER_PACKAGE
if (file->hdf5_file_lf != NULL) {
- if (file->hdf5_file_lf->exc_owner != NULL) {
- HDassert(file->hdf5_file_lf->exc_owner == &file->pub);
- file->hdf5_file_lf->exc_owner = NULL;
- }
/* Close the underlying file */
if (H5FD_close(file->hdf5_file_lf) < 0)
@@ -540,8 +743,17 @@ H5FD__vfd_swmr_close(H5FD_t *_file)
HDONE_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, FAIL, "unable to close the HDF5 file")
}
- if (!file->writer)
- H5FD__swmr_reader_close(file);
+ if (file->api_elapsed_ticks != NULL)
+ H5MM_xfree(file->api_elapsed_ticks);
+
+ /* Close the metadata file */
+ if (file->md_fd >= 0 && HDclose(file->md_fd) < 0)
+ /* Push error, but keep going */
+ HDONE_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, FAIL, "unable to close the metadata file");
+
+ /* Free the index entries */
+ if (file->md_index.num_entries && file->md_index.entries)
+ file->md_index.entries = H5FL_SEQ_FREE(H5FD_vfd_swmr_idx_entry_t, file->md_index.entries);
/* Release the driver info */
file = H5FL_FREE(H5FD_vfd_swmr_t, file);
@@ -577,141 +789,6 @@ H5FD__vfd_swmr_cmp(const H5FD_t *_f1, const H5FD_t *_f2)
} /* end H5FD__vfd__swmr_cmp() */
/*-------------------------------------------------------------------------
- * Function: H5FD_vfd_swmr_dedup (original description with H5P_FILE_ACCESS_ANY_VFD)
- *
- * Purpose: Compare the already-opened VFD instance `_self` with the
- * VFD instance `_other` newly-opened with file-access properties
- * `fapl_id` and indicate whether the instances duplicate each
- * other, if they conflict with each other, or if they are
- * dissimilar.
- *
- * If `_self` duplicates `_other`, return `_self`.
- *
- * Return NULL on error, or if `_other` and `_self` refer to the
- * same file but the file-access properties, `fapl_id`, conflict
- * with the properties of `_self`.
- *
- * If `_other` neither duplicates nor conflicts with `_self`,
- * then return `_other`.
- *
- * NOTE: Judging duplicate/conflicting/dissimilar VFD instances
- *
- * `_self` DUPLICATES `_other` if `_other` is also an instance
- * of SWMR class, the instances' lower files are equal under
- * `H5FD_cmp()`, and the file-access properties of `_self` match
- * `fapl_id`. The wildcard `fapl_id` value,
- * `H5P_FILE_ACCESS_ANY_VFD`, matches all.
- *
- * `_self` also DUPLICATES `_other` if `_other` is not a SWMR
- * instance, but it equals the lower file of `_self` under
- * `H5FD_cmp()`, and `fapl_id` is `H5P_FILE_ACCESS_ANY_VFD`.
- *
- * `_self` and `_other` CONFLICT if both are SWMR instances
- * referring to the same lower file, and their file-access
- * properties differ.
- *
- * `_self` and `_other` CONFLICT if `_other` is not a SWMR
- * instance, it equals the lower file of `_self`, and `fapl_id`
- * is not equal to `H5P_FILE_ACCESS_ANY_VFD`.
- *
- * Return: Success: `_self' or `_other', as described above
- * Failure: NULL
- *-------------------------------------------------------------------------
- */
-/*-------------------------------------------------------------------------
- * Function: H5FD_vfd_swmr_dedup (modified version without H5P_FILE_ACCESS_ANY_VFD)
- *
- * Purpose: Compare the already-opened VFD instance `_self` with the
- * VFD instance `_other` newly-opened with file-access properties
- * `fapl_id` and indicate whether the instances duplicate each
- * other, if they conflict with each other, or if they are
- * dissimilar.
- *
- * If `_self` duplicates `_other`, return `_self`.
- *
- * Return NULL on error, or if `_other` and `_self` refer to the
- * same file but the file-access properties, `fapl_id`, conflict
- * with the properties of `_self`.
- *
- * If `_other` neither duplicates nor conflicts with `_self`,
- * then return `_other`.
- *
- * NOTE: Judging duplicate/conflicting/dissimilar VFD instances
- *
- * `_self` DUPLICATES `_other` if `_other` is also an instance
- * of SWMR class, the instances' lower files are equal under
- * `H5FD_cmp()`, and the file-access properties of `_self` match
- * `fapl_id`.
- *
- * `_self` and `_other` CONFLICT if both are SWMR instances
- * referring to the same lower file, and their file-access
- * properties differ.
- *
- * `_self` and `_other` CONFLICT if `_other` is not a SWMR
- * instance, it equals the lower file of `_self`.
- *
- * Return: Success: `_self' or `_other', as described above
- * Failure: NULL
- *-------------------------------------------------------------------------
- */
-H5FD_t *
-H5FD_vfd_swmr_dedup(H5FD_t *_self, H5FD_t *_other, hid_t fapl_id)
-{
- H5FD_vfd_swmr_t *self = (H5FD_vfd_swmr_t *)_self;
- H5FD_t * ret_value = NULL;
-
- FUNC_ENTER_NOAPI(NULL);
-
- /* Not VFD SWMR */
- if (_self->driver_id != H5FD_VFD_SWMR_g) {
- if (H5FD_cmp(_self, _other) == 0)
- HGOTO_DONE(_self)
- else
- HGOTO_DONE(_other)
- }
-
- /* VFD SWMR */
- if (_self->cls == _other->cls) {
- H5FD_vfd_swmr_t * other = (H5FD_vfd_swmr_t *)_other;
- H5P_genplist_t * plist;
- H5F_vfd_swmr_config_t *config;
- hbool_t equal_configs;
-
- if (H5FD_cmp(self->hdf5_file_lf, other->hdf5_file_lf) != 0)
- HGOTO_DONE(_other)
-
- /* If fapl_id != _ANY_VFD, then we have either a duplicate or
- * a conflict. If the VFD SWMR parameters match, then
- * return `self` to indicate a duplicate. Otherwise, return
- * NULL to indicate a mismatch.
- */
- if (NULL == (plist = H5I_object(fapl_id)))
- HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "could not get fapl")
-
- if ((config = H5MM_malloc(sizeof(*config))) == NULL)
- HGOTO_ERROR(H5E_VFL, H5E_BADTYPE, NULL, "could not allocate config")
- if (H5P_get(plist, H5F_ACS_VFD_SWMR_CONFIG_NAME, config) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "cannot get VFD SWMR config")
-
- equal_configs = HDmemcmp(&self->config, config, sizeof(*config)) == 0;
-
- H5MM_xfree(config);
-
- if (equal_configs)
- HGOTO_DONE(_self)
-
- HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "inconsistent VFD SWMR config")
- }
- else if (H5FD_cmp(self->hdf5_file_lf, _other) == 0)
- ret_value = NULL;
- else
- ret_value = _other;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5FD_vfd_swmr_dedup() */
-
-/*-------------------------------------------------------------------------
* Function: H5FD__vfd_swmr_query
*
* Purpose: Set the flags that this VFL driver is capable of supporting.
@@ -924,9 +1001,6 @@ H5FD__vfd_swmr_read(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id
herr_t ret_value = SUCCEED;
char * p = buf;
- if (file->writer)
- return H5FD_read(file->hdf5_file_lf, type, addr, size, buf);
-
FUNC_ENTER_PACKAGE
HDassert(file && file->pub.cls);
@@ -1027,50 +1101,44 @@ done:
/*-------------------------------------------------------------------------
* Function: H5FD__vfd_swmr_write
*
- * Purpose: Writes SIZE bytes of data to FILE beginning at address ADDR
- * from buffer BUF according to data transfer properties in
- * DXPL_ID.
+ * Purpose: As the VFD SWMR reader VFD is only use on files that are
+ * opened read only, this function should be unreachable.
*
- * Return: SUCCEED/FAIL
+ * Return: FAIL
*-------------------------------------------------------------------------
*/
static herr_t
-H5FD__vfd_swmr_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id, haddr_t addr, size_t size,
- const void *buf)
+H5FD__vfd_swmr_write(H5FD_t H5_ATTR_UNUSED *_file, H5FD_mem_t H5_ATTR_UNUSED type,
+ hid_t H5_ATTR_UNUSED dxpl_id, haddr_t H5_ATTR_UNUSED addr, size_t H5_ATTR_UNUSED size,
+ const void H5_ATTR_UNUSED *buf)
{
- H5FD_vfd_swmr_t *file = (H5FD_vfd_swmr_t *)_file;
+ FUNC_ENTER_PACKAGE_NOERR /* Yes, even though this pushes an error on the stack */
- /* This routine should only be called if the VFD instance is opened
- * for writing.
- */
- HDassert(file->writer);
+ HERROR(H5E_CACHE, H5E_SYSTEM, "called unreachable fcn.");
+
+ FUNC_LEAVE_NOAPI(FAIL)
- return H5FD_write(file->hdf5_file_lf, type, addr, size, buf);
} /* end H5FD__vfd_swmr_write() */
/*-------------------------------------------------------------------------
* Function: H5FD_vfd_swmr_truncate
*
- * Purpose: Makes sure that the true file size is the same (or larger)
- * than the end-of-address for the underlying HDF5 file
+ * Purpose: As the VFD SWMR reader VFD is only use on files that are
+ * opened read only, this function should be unreachable.
*
- * Return: SUCCEED/FAIL
+ * Return: FAIL
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5FD__vfd_swmr_truncate(H5FD_t *_file, hid_t H5_ATTR_UNUSED dxpl_id, hbool_t closing)
+H5FD__vfd_swmr_truncate(H5FD_t H5_ATTR_UNUSED *_file, hid_t H5_ATTR_UNUSED dxpl_id,
+ hbool_t H5_ATTR_UNUSED closing)
{
- H5FD_vfd_swmr_t *file = (H5FD_vfd_swmr_t *)_file; /* VFD SWMR file struct */
+ FUNC_ENTER_PACKAGE_NOERR /* Yes, even though this pushes an error on the stack */
- FUNC_ENTER_PACKAGE_NOERR
-
- /* This routine should only be called if the VFD instance is opened
- * for writing.
- */
- HDassert(file->writer);
+ HERROR(H5E_CACHE, H5E_SYSTEM, "called unreachable fcn.");
- FUNC_LEAVE_NOAPI(H5FD_truncate(file->hdf5_file_lf, closing))
+ FUNC_LEAVE_NOAPI(FAIL)
}
/*-------------------------------------------------------------------------
@@ -1128,6 +1196,65 @@ done:
} /* end H5FD__vfd_swmr_unlock() */
/*-------------------------------------------------------------------------
+ * Function: H5FD__vfd_swmr_ctl
+ *
+ * Purpose: VFD SWMR reader VFD version of the ctl callback.
+ *
+ * The desired operation is specified by the op_code
+ * parameter.
+ *
+ * The flags parameter controls management of op_codes that
+ * are unknown to the callback
+ *
+ * The input and output parameters allow op_code specific
+ * input and output
+ *
+ * At present, this VFD supports no op codes of its own and
+ * simply passes ctl calls on to the underlying VFD.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD__vfd_swmr_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void *input, void **output)
+{
+ H5FD_vfd_swmr_t *file = (H5FD_vfd_swmr_t *)_file;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE
+
+ /* Sanity checks */
+ HDassert(file);
+
+ switch (op_code) {
+
+ /* Unknown op code */
+ default:
+ if (flags & H5FD_CTL__ROUTE_TO_TERMINAL_VFD_FLAG) {
+ /* Pass ctl call down to R/W channel VFD */
+ if (H5FDctl(file->hdf5_file_lf, op_code, flags, input, output) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_FCNTL, FAIL, "VFD ctl request failed")
+ }
+ else {
+ /* If no valid VFD routing flag is specified, fail for unknown op code
+ * if H5FD_CTL__FAIL_IF_UNKNOWN_FLAG flag is set.
+ */
+ if (flags & H5FD_CTL__FAIL_IF_UNKNOWN_FLAG)
+ HGOTO_ERROR(H5E_VFL, H5E_FCNTL, FAIL,
+ "VFD ctl request failed (unknown op code and fail if unknown flag is set)")
+ }
+
+ break;
+ }
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* end H5FD__vfd_swmr_ctl() */
+
+/*-------------------------------------------------------------------------
* Function: H5FD__vfd_swmr_load_hdr_and_idx()
*
* Purpose: Load and decode the header and index in the metadata file
diff --git a/src/H5FDvfd_swmr.h b/src/H5FDvfd_swmr.h
index dfd8d19..95e7979 100644
--- a/src/H5FDvfd_swmr.h
+++ b/src/H5FDvfd_swmr.h
@@ -19,12 +19,49 @@
#define H5FD_VFD_SWMR (H5FDperform_init(H5FD_vfd_swmr_init))
#define H5FD_VFD_SWMR_VALUE H5_VFD_SWMR
+/* Semi-unique constant used to help identify structure pointers */
+#define H5FD_VFD_SWMR_READER_MAGIC 0xABC123
+
+/* ----------------------------------------------------------------------------
+ * Structure: H5FD_vfd_swmr_reader_fapl_t
+ *
+ * Structure for configuring the VFD SWMR reader VFD. This structure and the
+ * associated FAPL entry and get / set routines are for HDF5 library use only,
+ * and should never be seen by the user.
+ *
+ * When a file is opened in VFD SWMR mode, the VFD SWMR reader VFD is inserted
+ * at the top of the user supplied (or default) VFD stack.
+ *
+ * The fields of this structure are discussed indvidually below. Note that
+ * there is no version field, since this structure should not be accessible
+ * to the user. The set of fields is quite limited, as most of the necessary
+ * configuration data is taken from the VFD SWMR configuration FAPL entry
+ *
+ * magic (int32_t)
+ * Semi-unique number, used to sanity-check that a given pointer is
+ * likely (or not) to be this structure type. MUST be first.
+ * If magic is not H5FD_VFD_SWMR_READER_MAGIC, the structure (and/or
+ * pointer to) must be considered invalid.
+ *
+ * fapl_id (hid_t)
+ * Library-given identification number of the FAPL containing the user
+ * supplied VFD stack. Must be set to H5P_DEFAULT or contain a file
+ * driver entry specifying a VFD that supports VFD SWMR
+ *
+ * ----------------------------------------------------------------------------
+ */
+typedef struct H5FD_vfd_swmr_reader_fapl_t {
+ int32_t magic;
+ hid_t fapl_id;
+} H5FD_vfd_swmr_reader_fapl_t;
+
#ifdef __cplusplus
extern "C" {
#endif
H5_DLL hid_t H5FD_vfd_swmr_init(void);
-H5_DLL herr_t H5Pset_fapl_vfd_swmr(hid_t fapl_id);
+H5_DLL herr_t H5P_pop_vfd_swmr_reader_vfd_off_fapl(hid_t fapl_id);
+H5_DLL herr_t H5P_push_vfd_swmr_reader_vfd_on_fapl(hid_t fapl_id);
#ifdef __cplusplus
}
diff --git a/src/H5Fint.c b/src/H5Fint.c
index 9880126..2f384fc 100644
--- a/src/H5Fint.c
+++ b/src/H5Fint.c
@@ -38,6 +38,10 @@
#include "H5Tprivate.h" /* Datatypes */
#include "H5VLprivate.h" /* Virtual Object Layer */
+#if 1 /* JRM */ /* probably want to re-work this */
+#include "H5FDvfd_swmr.h"
+#endif /* JRM */
+
#include "H5VLnative_private.h" /* Native VOL connector */
/****************/
@@ -1803,49 +1807,48 @@ done:
H5F_t *
H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
{
- H5F_t * file = NULL; /*the success return value */
- H5F_shared_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 */
- size_t page_buf_size;
- unsigned page_buf_min_meta_perc = 0;
- unsigned page_buf_min_raw_perc = 0;
- hbool_t set_flag = FALSE; /* Set the status_flags in the superblock */
- hbool_t clear = FALSE; /* Clear the status_flags */
- hbool_t evict_on_close; /* Evict on close value from plist */
- hbool_t use_file_locking = TRUE; /* Using file locks? */
- hbool_t ci_load = FALSE; /* Whether MDC ci load requested */
- hbool_t ci_write = FALSE; /* Whether MDC ci write requested */
- hbool_t file_create = FALSE; /* Creating a new file or not */
- H5F_vfd_swmr_config_t * vfd_swmr_config_ptr = NULL; /* Points to VFD SMWR config info */
- H5F_generate_md_ck_cb_t cb_info = {NULL}; /* For VFD SWMR NFS testing:
- initialize the callback to generate
- checksums for metadata files */
- H5F_t *ret_value = NULL; /* Actual return value */
+ H5F_t * file = NULL; /*the success return value */
+ H5F_shared_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 */
+ size_t page_buf_size;
+ unsigned page_buf_min_meta_perc = 0;
+ unsigned page_buf_min_raw_perc = 0;
+ hbool_t vfd_swmr = FALSE; /* TRUE iff opening file with VFD SWMR */
+ hbool_t vfd_swmr_writer = FALSE; /* TRUE iff opening file as VFD SWMR */
+ /* writer. */
+ hbool_t pop_vfd_swmr_reader_vfd = FALSE; /* Flag set when the VFD SWMR reader VFD */
+ /* has been pushed on the supplied fapl */
+ /* and must be popped before return. */
+ hbool_t set_flag = FALSE; /* Set the status_flags in the superblock */
+ hbool_t clear = FALSE; /* Clear the status_flags */
+ hbool_t evict_on_close; /* Evict on close value from plist */
+ hbool_t use_file_locking = TRUE; /* Using file locks? */
+ hbool_t ci_load = FALSE; /* Whether MDC ci load requested */
+ hbool_t ci_write = FALSE; /* Whether MDC ci write requested */
+ hbool_t file_create = FALSE; /* Creating a new file or not */
+ H5F_vfd_swmr_config_t * vfd_swmr_config_ptr = NULL; /* Points to VFD SMWR config info */
+ H5F_generate_md_ck_cb_t cb_info = {NULL}; /* For VFD SWMR NFS testing:
+ initialize the callback to generate
+ checksums for metadata files */
+ H5F_t *ret_value = NULL; /* 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")
-
/* 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")
- /* Check if we are using file locking */
- if (H5F__check_if_using_file_locks(a_plist, &use_file_locking) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "unable to get file locking flag")
+ /* start by testing to see if we are opening the file VFD SWMR reader. If
+ * we are, we must "push" the vfd swrm reader vfd on the vfd "stack" supplied
+ * by the user in the fapl. Since the user may use the fapl elsewhere, we
+ * must "pop" the vfd swmr reader vfd off the vfd "stack" before we return.
+ *
+ * In passing, collect the VFD SWMR configuration info for later use.
+ */
/* Allocate space for VFD SWMR configuration info */
if (NULL == (vfd_swmr_config_ptr = H5MM_calloc(sizeof(H5F_vfd_swmr_config_t))))
@@ -1857,18 +1860,78 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
/* When configured with VFD SWMR */
if (vfd_swmr_config_ptr->version) {
+
+ /* get the page buffer size and verify that it is greater than zero. Note
+ * that this get of the page buffer size is redundant -- we do it again
+ * below.
+ */
+ if (H5P_get(a_plist, H5F_ACS_PAGE_BUFFER_SIZE_NAME, &page_buf_size) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "can't get page buffer size");
+
+ if (page_buf_size == 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "page buffering must be enabled")
+
+ /* Paged allocation must also be enabled, but the page buffer
+ * initialization (H5PB_create) will detect a conflicting configuration
+ * and return an error.
+ */
+
+ /* Legacy SWMR and VFD SWMR are incompatible. Fail if the legacy SWMR flags are set */
+ if ((flags & H5F_ACC_SWMR_WRITE) || (flags & H5F_ACC_SWMR_READ))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "Legacy and VFD SWMR are incompatible")
+
/* Verify that file access flags are consistent with VFD SWMR configuration */
if ((flags & H5F_ACC_RDWR) && !vfd_swmr_config_ptr->writer)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "file access is writer but VFD SWMR config is reader")
if ((flags & H5F_ACC_RDWR) == 0 && vfd_swmr_config_ptr->writer)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "file access is reader but VFD SWMR config is writer")
+ if (((flags & H5F_ACC_RDWR) == 0) && (!vfd_swmr_config_ptr->writer)) {
+
+ vfd_swmr = TRUE;
+
+ /* We are opening a file as a VFD SWMR reader. Push the vfd swrm reader vfd on the
+ * vfd stack specified in the fapl. Set the pop_vfd_swmr_reader flag to trigger a
+ * pop of the vfd swmr reader vfd on exit from this function.
+ */
+ if (H5P_push_vfd_swmr_reader_vfd_on_fapl(fapl_id) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "can't push VFD SWMR reader VFD on FAPL");
+
+ pop_vfd_swmr_reader_vfd = TRUE;
+ }
+ else if ((flags & H5F_ACC_RDWR) && (vfd_swmr_config_ptr->writer)) {
+
+ vfd_swmr = TRUE;
+ vfd_swmr_writer = TRUE;
+ }
+
+ /* if we get to this point, vfd_swmr must be TRUE. */
+ HDassert(vfd_swmr);
+
/* Retrieve the private property for VFD SWMR testing */
if (H5P_get(a_plist, H5F_ACS_GENERATE_MD_CK_CB_NAME, &cb_info) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get generate_md_ck_cb info")
+ }
- if (!vfd_swmr_config_ptr->writer)
- use_file_locking = FALSE;
+ /*
+ * 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")
+
+ /* Check if we are using file locking */
+ if (H5F__check_if_using_file_locks(a_plist, &use_file_locking) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "unable to get file locking flag")
+
+ /* turn off file locking unconditionally if the file is being opened VFD SWMR reader */
+ if ((vfd_swmr) && (!vfd_swmr_writer)) {
+
+ use_file_locking = FALSE;
}
/*
@@ -1901,8 +1964,6 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
/* Avoid reusing a virtual file opened exclusively by a second virtual
* file, or opening the same file twice with different parameters.
*/
- if ((lf = H5FD_deduplicate(lf, fapl_id)) == NULL)
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "an already-open file conflicts with '%s'", name)
/* Is the file already open? */
if ((shared = H5F__sfile_search(lf)) != NULL) {
@@ -1916,6 +1977,8 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
* readers don't expect the file to change under them), or if the
* SWMR write/read access flags don't agree.
*/
+ 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)
@@ -1932,6 +1995,17 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL,
"SWMR read access flag not the same for file that is already open")
+ /* fail if VFD SWMR configurations disagree */
+ if (HDmemcmp(&(shared->vfd_swmr_config), vfd_swmr_config_ptr, sizeof(H5F_vfd_swmr_config_t)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL,
+ "VFD SWMR configuration not the same for file that is already open")
+
+ /* Arguably, we should fail if there is a page size mismatch. However, if I read
+ * the code correctly, the page size and page buffer configuration from the open file
+ * will domininate. Thus, there probably isn't a functional issue. That said,
+ * this should be thought about.
+ */
+
/* 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")
@@ -2220,6 +2294,9 @@ done:
if (vfd_swmr_config_ptr)
H5MM_free(vfd_swmr_config_ptr);
+ if ((pop_vfd_swmr_reader_vfd) && (H5P_pop_vfd_swmr_reader_vfd_off_fapl(fapl_id) < 0))
+ HDONE_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "can't pop vfd swrm reader vfd off vfd stack")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F_open() */
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
index c594ed8..e5d3339 100644
--- a/src/H5Fprivate.h
+++ b/src/H5Fprivate.h
@@ -1218,6 +1218,8 @@ H5_DLL herr_t H5F_get_vfd_handle(const H5F_t *file, hid_t fapl, void **file_han
/* VFD SWMR functions */
H5_DLL hbool_t H5F_get_use_vfd_swmr(const H5F_t *f);
H5_DLL herr_t H5F_vfd_swmr_init(H5F_t *f, hbool_t file_create);
+H5_DLL herr_t H5F_vfd_swmr_build_md_path_name(H5F_vfd_swmr_config_t *config, const char *hdf5_filename,
+ char *name /*out*/);
H5_DLL herr_t H5F_vfd_swmr_close_or_flush(H5F_t *f, hbool_t closing);
H5_DLL herr_t H5F_update_vfd_swmr_metadata_file(H5F_t *f, uint32_t index_len,
H5FD_vfd_swmr_idx_entry_t *index);
diff --git a/src/H5Fvfd_swmr.c b/src/H5Fvfd_swmr.c
index 9c4360e..702c362 100644
--- a/src/H5Fvfd_swmr.c
+++ b/src/H5Fvfd_swmr.c
@@ -49,8 +49,9 @@
/* Local Macros */
/****************/
-#define NANOSECS_PER_SECOND 1000000000 /* nanoseconds per second */
-#define NANOSECS_PER_TENTH_SEC 100000000 /* nanoseconds per 0.1 second */
+#define VFD_SWMR_MD_FILE_SUFFIX ".md"
+#define NANOSECS_PER_SECOND 1000000000 /* nanoseconds per second */
+#define NANOSECS_PER_TENTH_SEC 100000000 /* nanoseconds per 0.1 second */
/* Declare an array of string to identify the VFD SMWR Log tags.
* Note this array is used to generate the entry tag by the log reporting macro
@@ -186,8 +187,13 @@ H5F_vfd_swmr_init(H5F_t *f, hbool_t file_create)
shared->vfd_swmr_writer = TRUE;
shared->tick_num = 0;
- /* Retrieve the metadata filename built with md_file_path and md_file_name */
- H5FD_vfd_swmr_get_md_path_name(f->shared->lf, &shared->md_file_path_name);
+ /* Allocate space for the (possibly constructed) metadata file name */
+ if (NULL == (shared->md_file_path_name = H5MM_calloc((H5FD_MAX_FILENAME_LEN + 1) * sizeof(char))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate memory for mdc log file name")
+
+ if (H5F_vfd_swmr_build_md_path_name(&(shared->vfd_swmr_config), f->open_name,
+ shared->md_file_path_name) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to build metadata file name")
if (((shared->vfd_swmr_md_fd = HDopen(shared->md_file_path_name, O_CREAT | O_RDWR | O_TRUNC,
H5_POSIX_CREATE_MODE_RW))) < 0)
@@ -281,6 +287,66 @@ done:
} /* H5F_vfd_swmr_init() */
/*-------------------------------------------------------------------------
+ *
+ * Function: H5F_vfd_swmr_build_md_path_name
+ *
+ * Purpose: To construct the metadata file's full name based on config's
+ * md_file_path and md_file_name. See RFC for details.
+ *
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Vailin Choi -- 1/13/2022
+ *
+ * Changes: Moved to H5Fvfd_swmr.c from H5FDvfd_swmr.c, and renamed
+ * accordingly. Changed FUNC_ENTER_PACKAGE to
+ * FUNC_ENTER_NOAPI. Converted to a private function so
+ * that it can be called in H5FDvfd_swmr.c
+ *
+ * JRM -- 5/17/22
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_vfd_swmr_build_md_path_name(H5F_vfd_swmr_config_t *config, const char *hdf5_filename, char *name /*out*/)
+{
+ size_t tot_len = 0;
+ size_t tmp_len = 0;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ if ((tot_len = HDstrlen(config->md_file_path)) != 0) {
+
+ /* md_file_path + '/' */
+ if (++tot_len > H5F__MAX_VFD_SWMR_FILE_NAME_LEN)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, FAIL, "md_file_path and md_file_name exceeds maximum");
+ HDstrcat(name, config->md_file_path);
+ HDstrcat(name, "/");
+ }
+
+ if ((tmp_len = HDstrlen(config->md_file_name)) != 0) {
+ if ((tot_len += tmp_len) > H5F__MAX_VFD_SWMR_FILE_NAME_LEN)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, FAIL, "md_file_path and md_file_name exceeds maximum");
+ HDstrcat(name, config->md_file_name);
+ }
+ else {
+ /* Automatic generation of metadata file name based on hdf5_filename + '.md' */
+ if ((tot_len += (HDstrlen(hdf5_filename) + 3)) > H5F__MAX_VFD_SWMR_FILE_NAME_LEN)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, FAIL, "md_file_path and md_file_name maximum");
+
+ HDstrcat(name, hdf5_filename);
+ HDstrcat(name, VFD_SWMR_MD_FILE_SUFFIX);
+ }
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5F_vfd_swmr_build_md_path_name() */
+
+/*-------------------------------------------------------------------------
* Function: H5F_vfd_swmr_close_or_flush
*
* Purpose: Used by the VFD SWMR writer when the HDF5 file is closed
diff --git a/src/H5Pfapl.c b/src/H5Pfapl.c
index f900965..d6beece 100644
--- a/src/H5Pfapl.c
+++ b/src/H5Pfapl.c
@@ -6283,9 +6283,6 @@ H5Pset_vfd_swmr_config(hid_t plist_id, H5F_vfd_swmr_config_t *config_ptr)
if (H5P_set(plist, H5F_ACS_VFD_SWMR_CONFIG_NAME, config_ptr) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set metadata cache initial config")
- if (H5P_set_driver(plist, H5FD_VFD_SWMR, NULL, NULL) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set VFD SWMR driver info");
-
done:
FUNC_LEAVE_API(ret_value)
} /* H5Pset_vfd_swmr_config() */
diff --git a/test/vfd_swmr.c b/test/vfd_swmr.c
index 924da07..e3149f2 100644
--- a/test/vfd_swmr.c
+++ b/test/vfd_swmr.c
@@ -5402,12 +5402,12 @@ test_vfds_same_file_opens(hid_t orig_fapl, const char *env_h5_drvr)
if (H5Pclose(fapl) < 0)
FAIL_STACK_ERROR;
-#if 0 /* Use test cases #4 and #5 when John's changes are merged */
- /*
- * Case #4
+#if 1 /* Use test cases #4 and #5 when John's changes are merged */
+ /*
+ * Case #4
* --Open the file as writer with both legacy SWMR and VFD SWMR configured .
* --NOTE: The open should fail when John's changes are merged but for now it succeeds.
- */
+ */
/*
* Set up VFD SWMR configuration as writer in fapl
@@ -5416,8 +5416,7 @@ test_vfds_same_file_opens(hid_t orig_fapl, const char *env_h5_drvr)
/* config, tick_len, max_lag, presume_posix_semantics, writer,
* maintain_metadata_file, generate_updater_files, flush_raw_data, md_pages_reserved,
* md_file_path, md_file_name, updater_file_path */
- init_vfd_swmr_config(config, 4, 10, FALSE, TRUE, TRUE, FALSE, TRUE, 2, NULL,
- MD_FILENAME, NULL);
+ init_vfd_swmr_config(config, 4, 10, FALSE, TRUE, TRUE, FALSE, TRUE, 2, NULL, MD_FILENAME, NULL);
if ((fapl = H5Pcopy(orig_fapl)) < 0)
FAIL_STACK_ERROR;
@@ -5442,18 +5441,17 @@ test_vfds_same_file_opens(hid_t orig_fapl, const char *env_h5_drvr)
if (H5Pclose(fapl) < 0)
FAIL_STACK_ERROR;
- /*
+ /*
* Case #5:
* --Open the file as reader with both legacy SWMR and VFD SWMR configured .
* --NOTE: The open should fail when John's changes are merged but for now it succeeds.
- */
+ */
/* config, tick_len, max_lag, presume_posix_semantics, writer,
* maintain_metadata_file, generate_updater_files, flush_raw_data, md_pages_reserved,
* md_file_path, md_file_name, updater_file_path */
/* NOTE: Set "presume_posix_semantics" to TRUE and "writer" to FALSE */
- init_vfd_swmr_config(config, 4, 10, TRUE, FALSE, TRUE, FALSE, TRUE, 2, NULL,
- MD_FILENAME, NULL);
+ init_vfd_swmr_config(config, 4, 10, TRUE, FALSE, TRUE, FALSE, TRUE, 2, NULL, MD_FILENAME, NULL);
if ((fapl = H5Pcopy(orig_fapl)) < 0)
FAIL_STACK_ERROR;
@@ -5469,11 +5467,11 @@ test_vfds_same_file_opens(hid_t orig_fapl, const char *env_h5_drvr)
}
H5E_END_TRY;
/* Change the section of code inside the "for loop" to TEST_ERROR when John's changes are merged */
- if(fid1 >= 0) {
+ if (fid1 >= 0) {
printf("The reader open succeeds which shouldn't be\n");
if (H5Fclose(fid1) < 0)
FAIL_STACK_ERROR;
- }
+ }
if (H5Pclose(fapl) < 0)
FAIL_STACK_ERROR;