summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--release_docs/RELEASE.txt10
-rw-r--r--src/H5Dint.c52
-rw-r--r--src/H5Fint.c86
-rw-r--r--src/H5Oflush.c12
-rw-r--r--src/H5Oprivate.h2
-rw-r--r--test/swmr.c373
6 files changed, 504 insertions, 31 deletions
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt
index 5feb06b..e3932e1 100644
--- a/release_docs/RELEASE.txt
+++ b/release_docs/RELEASE.txt
@@ -170,6 +170,16 @@ Bug Fixes since HDF5-1.12.1 release
===================================
Library
-------
+ - Modified H5Fstart_swmr_write() to preserve DAPL properties
+
+ Internally, H5Fstart_swmr_write() closes and reopens the file in question
+ as part of its process for making the file SWMR-safe. Previously, when
+ the library reopened the file it would simply use the default access
+ properties. Modified the library to instead save these properties and use
+ them when reopening the file.
+
+ (NAF - 2022/07/18, HDFFV-11308)
+
- Converted an assertion on (possibly corrupt) file contents to a normal
error check
diff --git a/src/H5Dint.c b/src/H5Dint.c
index d38222a..ee4318a 100644
--- a/src/H5Dint.c
+++ b/src/H5Dint.c
@@ -3742,11 +3742,13 @@ done:
hid_t
H5D_get_access_plist(const H5D_t *dset)
{
- H5P_genplist_t *old_plist; /* Stored DAPL from dset */
- H5P_genplist_t *new_plist; /* New DAPL */
- H5P_genplist_t *def_fapl; /* Default FAPL */
- H5D_append_flush_t def_append_flush_info = {0}; /* Default append flush property */
- H5D_rdcc_t def_chunk_info; /* Default chunk cache property */
+ H5P_genplist_t *old_plist; /* Stored DAPL from dset */
+ H5P_genplist_t *new_plist; /* New DAPL */
+ H5P_genplist_t *def_dapl = NULL; /* Default DAPL */
+ H5D_append_flush_t def_append_flush_info = {0}; /* Default append flush property */
+ H5D_rdcc_t def_chunk_info; /* Default chunk cache property */
+ H5D_vds_view_t def_vds_view; /* Default virtual view property */
+ hsize_t def_vds_gap; /* Default virtual printf gap property */
hid_t new_dapl_id = FAIL;
hid_t ret_value = FAIL;
@@ -3775,23 +3777,23 @@ H5D_get_access_plist(const H5D_t *dset)
}
else {
/* Get the default FAPL */
- if (NULL == (def_fapl = (H5P_genplist_t *)H5I_object(H5P_LST_FILE_ACCESS_ID_g)))
+ if (NULL == (def_dapl = (H5P_genplist_t *)H5I_object(H5P_LST_DATASET_ACCESS_ID_g)))
HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, FAIL, "not a property list")
/* Set the data cache number of slots to the value of the default FAPL */
- if (H5P_get(def_fapl, H5D_ACS_DATA_CACHE_NUM_SLOTS_NAME, &def_chunk_info.nslots) < 0)
+ if (H5P_get(def_dapl, H5D_ACS_DATA_CACHE_NUM_SLOTS_NAME, &def_chunk_info.nslots) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get data number of slots");
if (H5P_set(new_plist, H5D_ACS_DATA_CACHE_NUM_SLOTS_NAME, &def_chunk_info.nslots) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set data cache number of slots")
/* Set the data cache byte size to the value of the default FAPL */
- if (H5P_get(def_fapl, H5D_ACS_DATA_CACHE_BYTE_SIZE_NAME, &def_chunk_info.nbytes_max) < 0)
+ if (H5P_get(def_dapl, H5D_ACS_DATA_CACHE_BYTE_SIZE_NAME, &def_chunk_info.nbytes_max) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get data cache byte size");
if (H5P_set(new_plist, H5D_ACS_DATA_CACHE_BYTE_SIZE_NAME, &def_chunk_info.nbytes_max) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set data cache byte size")
/* Set the preempt read chunks property to the value of the default FAPL */
- if (H5P_get(def_fapl, H5D_ACS_PREEMPT_READ_CHUNKS_NAME, &def_chunk_info.w0) < 0)
+ if (H5P_get(def_dapl, H5D_ACS_PREEMPT_READ_CHUNKS_NAME, &def_chunk_info.w0) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get preempt read chunks");
if (H5P_set(new_plist, H5D_ACS_PREEMPT_READ_CHUNKS_NAME, &def_chunk_info.w0) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set preempt read chunks")
@@ -3801,12 +3803,32 @@ H5D_get_access_plist(const H5D_t *dset)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set append flush property")
} /* end if-else */
- /* Set the VDS view & printf gap options */
- if (H5P_set(new_plist, H5D_ACS_VDS_VIEW_NAME, &(dset->shared->layout.storage.u.virt.view)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set VDS view")
- if (H5P_set(new_plist, H5D_ACS_VDS_PRINTF_GAP_NAME, &(dset->shared->layout.storage.u.virt.printf_gap)) <
- 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set VDS printf gap")
+ /* If the dataset is virtual then copy the VDS view & printf gap options.
+ * Otherwise, use the default values. */
+ if (dset->shared->layout.type == H5D_VIRTUAL) {
+ if (H5P_set(new_plist, H5D_ACS_VDS_VIEW_NAME, &(dset->shared->layout.storage.u.virt.view)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set VDS view")
+ if (H5P_set(new_plist, H5D_ACS_VDS_PRINTF_GAP_NAME,
+ &(dset->shared->layout.storage.u.virt.printf_gap)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set VDS printf gap")
+ }
+ else {
+ /* Get the default FAPL if necessary */
+ if (!def_dapl && NULL == (def_dapl = (H5P_genplist_t *)H5I_object(H5P_LST_DATASET_ACCESS_ID_g)))
+ HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, FAIL, "not a property list")
+
+ /* Set the data cache number of slots to the value of the default FAPL */
+ if (H5P_get(def_dapl, H5D_ACS_VDS_VIEW_NAME, &def_vds_view) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get VDS view");
+ if (H5P_set(new_plist, H5D_ACS_VDS_VIEW_NAME, &def_vds_view) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set VDS view")
+
+ /* Set the data cache byte size to the value of the default FAPL */
+ if (H5P_get(def_dapl, H5D_ACS_VDS_PRINTF_GAP_NAME, &def_vds_gap) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get VDS printf gap");
+ if (H5P_set(new_plist, H5D_ACS_VDS_PRINTF_GAP_NAME, &def_vds_gap) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set VDS printf gap")
+ }
/* Set the vds prefix option */
if (H5P_set(new_plist, H5D_ACS_VDS_PREFIX_NAME, &(dset->shared->vds_prefix)) < 0)
diff --git a/src/H5Fint.c b/src/H5Fint.c
index 1da8c01..dc86390 100644
--- a/src/H5Fint.c
+++ b/src/H5Fint.c
@@ -3596,6 +3596,7 @@ H5F__start_swmr_write(H5F_t *f)
size_t grp_dset_count = 0; /* # of open objects: groups & datasets */
size_t nt_attr_count = 0; /* # of opened named datatypes + opened attributes */
hid_t *obj_ids = NULL; /* List of ids */
+ hid_t *obj_apl_ids = NULL; /* List of access property lists */
H5G_loc_t *obj_glocs = NULL; /* Group location of the object */
H5O_loc_t *obj_olocs = NULL; /* Object location */
H5G_name_t *obj_paths = NULL; /* Group hierarchy path */
@@ -3654,13 +3655,20 @@ H5F__start_swmr_write(H5F_t *f)
if (grp_dset_count > 0) {
/* Allocate space for group and object locations */
if ((obj_ids = (hid_t *)H5MM_malloc(grp_dset_count * sizeof(hid_t))) == NULL)
- HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, FAIL, "can't allocate buffer for hid_t")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "can't allocate buffer for hid_t")
if ((obj_glocs = (H5G_loc_t *)H5MM_malloc(grp_dset_count * sizeof(H5G_loc_t))) == NULL)
- HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, FAIL, "can't allocate buffer for H5G_loc_t")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "can't allocate buffer for object group locations")
if ((obj_olocs = (H5O_loc_t *)H5MM_malloc(grp_dset_count * sizeof(H5O_loc_t))) == NULL)
- HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, FAIL, "can't allocate buffer for H5O_loc_t")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "can't allocate buffer for object locations")
if ((obj_paths = (H5G_name_t *)H5MM_malloc(grp_dset_count * sizeof(H5G_name_t))) == NULL)
- HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, FAIL, "can't allocate buffer for H5G_name_t")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "can't allocate buffer for object paths")
+
+ /* Taking a shortcut here to use calloc to initialize obj_apl_ids to all H5P_DEFAULT. If
+ * this changes in the future we'll need to either initialize this array to all H5P_DEFAULT
+ * or ensure 0 cannot be a valid value and check for 0 at cleanup. */
+ if ((obj_apl_ids = (hid_t *)H5MM_calloc(grp_dset_count * sizeof(hid_t))) == NULL)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "can't allocate buffer for hid_t")
+ HDassert(obj_apl_ids[0] == H5P_DEFAULT);
/* Get the list of opened object ids (groups & datasets) */
if (H5F_get_obj_ids(f, H5F_OBJ_GROUP | H5F_OBJ_DATASET, grp_dset_count, obj_ids, FALSE,
@@ -3682,20 +3690,67 @@ H5F__start_swmr_write(H5F_t *f)
/* Gather information about opened objects (groups, datasets) in the file */
/* (For refresh later on) */
for (u = 0; u < grp_dset_count; u++) {
- H5O_loc_t *oloc; /* object location */
+ void *obj = NULL; /* VOL object */
+ H5I_type_t type; /* Type of object for the ID */
H5G_loc_t tmp_loc;
+ /* Get object's type */
+ type = H5I_get_type(obj_ids[u]);
+
+ /* Get the object from the VOL */
+ if (NULL == (obj = H5VL_object(obj_ids[u])))
+ HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Get the object's access property list, if it is a dataset (access
+ * properties are not needed to reopen other object types currently)
+ */
+ switch (type) {
+ case H5I_GROUP:
+ /* Access properties not needed currently */
+ break;
+
+ case H5I_DATATYPE:
+ /* Access properties not needed currently */
+ break;
+
+ case H5I_DATASET:
+
+ /* Get dataset access properties */
+ if ((obj_apl_ids[u] = H5D_get_access_plist(obj)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL,
+ "unable to get dataset access property list")
+ break;
+
+ case H5I_MAP:
+ HGOTO_ERROR(H5E_FILE, H5E_BADTYPE, FAIL, "maps not supported in native VOL connector")
+
+ case H5I_UNINIT:
+ case H5I_BADID:
+ case H5I_FILE:
+ case H5I_DATASPACE:
+ case H5I_ATTR:
+ case H5I_VFL:
+ case H5I_VOL:
+ case H5I_GENPROP_CLS:
+ case H5I_GENPROP_LST:
+ case H5I_ERROR_CLASS:
+ case H5I_ERROR_MSG:
+ case H5I_ERROR_STACK:
+ case H5I_SPACE_SEL_ITER:
+ case H5I_NTYPES:
+ default:
+ HGOTO_ERROR(H5E_FILE, H5E_BADTYPE, FAIL,
+ "not a valid file object ID (dataset, group, or datatype)")
+ break;
+ } /* end switch */
+
/* Set up the id's group location */
obj_glocs[u].oloc = &obj_olocs[u];
obj_glocs[u].path = &obj_paths[u];
H5G_loc_reset(&obj_glocs[u]);
- /* get the id's object location */
- if ((oloc = H5O_get_loc(obj_ids[u])) == NULL)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an object")
-
/* Make deep local copy of object's location information */
- H5G_loc(obj_ids[u], &tmp_loc);
+ H5G_loc_real(obj, type, &tmp_loc);
H5G_loc_copy(&obj_glocs[u], &tmp_loc, H5_COPY_DEEP);
/* Close the object */
@@ -3755,7 +3810,7 @@ H5F__start_swmr_write(H5F_t *f)
/* Refresh (reopen) the objects (groups & datasets) in the file */
for (u = 0; u < grp_dset_count; u++)
- if (H5O_refresh_metadata_reopen(obj_ids[u], &obj_glocs[u], vol_connector, TRUE) < 0)
+ if (H5O_refresh_metadata_reopen(obj_ids[u], obj_apl_ids[u], &obj_glocs[u], vol_connector, TRUE) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't refresh-close object")
/* Unlock the file */
@@ -3764,7 +3819,6 @@ H5F__start_swmr_write(H5F_t *f)
done:
if (ret_value < 0 && setup) {
-
/* Re-enable accumulator */
f->shared->feature_flags |= (unsigned)H5FD_FEAT_ACCUMULATE_METADATA;
if (H5FD_set_feature_flags(f->shared->lf, f->shared->feature_flags) < 0)
@@ -3800,6 +3854,14 @@ done:
if (obj_paths)
H5MM_xfree(obj_paths);
+ /* Free access property lists */
+ if (obj_apl_ids) {
+ for (u = 0; u < grp_dset_count; u++)
+ if (obj_apl_ids[u] != H5P_DEFAULT && obj_apl_ids[u] >= 0 && H5I_dec_ref(obj_apl_ids[u]) < 0)
+ HDONE_ERROR(H5E_ATOM, H5E_CANTDEC, FAIL, "decrementing property list ID failed")
+ H5MM_xfree(obj_apl_ids);
+ }
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F__start_swmr_write() */
diff --git a/src/H5Oflush.c b/src/H5Oflush.c
index a622bd1..e02a084 100644
--- a/src/H5Oflush.c
+++ b/src/H5Oflush.c
@@ -334,7 +334,7 @@ H5O_refresh_metadata(hid_t oid, H5O_loc_t oloc)
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to refresh object")
/* Re-open the object, re-fetching its metadata */
- if ((H5O_refresh_metadata_reopen(oid, &obj_loc, connector, FALSE)) < 0)
+ if ((H5O_refresh_metadata_reopen(oid, H5P_DEFAULT, &obj_loc, connector, FALSE)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to refresh object")
/* Restore the number of references on the VOL connector */
@@ -439,7 +439,8 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5O_refresh_metadata_reopen(hid_t oid, H5G_loc_t *obj_loc, H5VL_t *vol_connector, hbool_t start_swmr)
+H5O_refresh_metadata_reopen(hid_t oid, hid_t apl_id, H5G_loc_t *obj_loc, H5VL_t *vol_connector,
+ hbool_t start_swmr)
{
void *object = NULL; /* Object for this operation */
H5I_type_t type; /* Type of object for the ID */
@@ -468,8 +469,13 @@ H5O_refresh_metadata_reopen(hid_t oid, H5G_loc_t *obj_loc, H5VL_t *vol_connector
break;
case H5I_DATASET:
+ /* Set dataset access property list in API context if appropriate */
+ if (H5CX_set_apl(&apl_id, H5P_CLS_DACC, oid, TRUE) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set access property list info")
+
/* Re-open the dataset */
- if (NULL == (object = H5D_open(obj_loc, H5P_DATASET_ACCESS_DEFAULT)))
+ if (NULL ==
+ (object = H5D_open(obj_loc, apl_id == H5P_DEFAULT ? H5P_DATASET_ACCESS_DEFAULT : apl_id)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "unable to open dataset")
if (!start_swmr) /* No need to handle multiple opens when H5Fstart_swmr_write() */
if (H5D_mult_refresh_reopen((H5D_t *)object) < 0)
diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h
index 44f383a..2f1e431 100644
--- a/src/H5Oprivate.h
+++ b/src/H5Oprivate.h
@@ -982,7 +982,7 @@ H5_DLL herr_t H5O_msg_get_flags(const H5O_loc_t *loc, unsigned type_id, uint8_t
H5_DLL herr_t H5O_flush(H5O_loc_t *oloc, hid_t obj_id);
H5_DLL herr_t H5O_flush_common(H5O_loc_t *oloc, hid_t obj_id);
H5_DLL herr_t H5O_refresh_metadata(hid_t oid, H5O_loc_t oloc);
-H5_DLL herr_t H5O_refresh_metadata_reopen(hid_t oid, H5G_loc_t *obj_loc, H5VL_t *vol_driver,
+H5_DLL herr_t H5O_refresh_metadata_reopen(hid_t oid, hid_t apl_id, H5G_loc_t *obj_loc, H5VL_t *vol_driver,
hbool_t start_swmr);
/* Cache corking functions */
diff --git a/test/swmr.c b/test/swmr.c
index e991aa8..7122663 100644
--- a/test/swmr.c
+++ b/test/swmr.c
@@ -56,6 +56,9 @@ const char *FILENAME[] = {"swmr0", /* 0 */
#define NAME_BUF_SIZE 1024 /* Length of file name */
+/* Epsilon for floating-point comparisons */
+#define FP_EPSILON 0.000001F
+
/* Tests for H5Pget/set_metadata_read_attempts(), H5Fget_metadata_read_retry_info */
static int test_metadata_read_attempts(hid_t in_fapl);
static int test_metadata_read_retry_info(hid_t in_fapl);
@@ -65,6 +68,7 @@ static int test_start_swmr_write(hid_t in_fapl, hbool_t new_format);
static int test_err_start_swmr_write(hid_t in_fapl, hbool_t new_format);
static int test_start_swmr_write_concur(hid_t in_fapl, hbool_t new_format);
static int test_start_swmr_write_stress_ohdr(hid_t in_fapl);
+static int test_start_swmr_write_persist_dapl(hid_t in_fapl);
/* Tests for H5Pget/set_object_flush_cb() */
static herr_t flush_cb(hid_t obj_id, void *_udata);
@@ -3180,6 +3184,374 @@ error:
} /* test_start_swmr_write_stress_ohdr() */
/*
+ * test_start_swmr_write_persist_dapl():
+ *
+ * Verify H5Fstart_swmr_write() doesn't wipe out dataset access properties for
+ * open datasets.
+ *
+ */
+static herr_t
+dummy_append_flush_cb(hid_t H5_ATTR_UNUSED dataset_id, hsize_t H5_ATTR_UNUSED *cur_dims,
+ void H5_ATTR_UNUSED *user_data)
+{
+ return SUCCEED;
+}
+
+static herr_t
+tssw_persist_dapl_verify(hid_t did, hid_t vdsid1, hid_t vdsid2, hsize_t boundary, H5D_append_cb_t append_func,
+ void *append_func_ud, size_t rdcc_nslots, size_t rdcc_nbytes, double rdcc_w0,
+ const char *efile_prefix, const char *virtual_prefix, hsize_t gap_size,
+ H5D_vds_view_t virtual_view)
+{
+ hid_t dapl = H5I_INVALID_HID;
+ hid_t vds_dapl1 = H5I_INVALID_HID;
+ hid_t vds_dapl2 = H5I_INVALID_HID;
+ hsize_t boundary_out = 0;
+ H5D_append_cb_t append_func_out = NULL;
+ void *append_func_ud_out = NULL;
+ size_t rdcc_nslots_out = 0;
+ size_t rdcc_nbytes_out = 0;
+ double rdcc_w0_out = 0.;
+ char efile_prefix_out[64];
+ char virtual_prefix_out[64];
+ hsize_t gap_size_out = 0;
+ H5D_vds_view_t virtual_view_out = H5D_VDS_LAST_AVAILABLE;
+
+ /* Get dataset access property lists */
+ if ((dapl = H5Dget_access_plist(did)) < 0)
+ TEST_ERROR;
+ if ((vds_dapl1 = H5Dget_access_plist(vdsid1)) < 0)
+ TEST_ERROR;
+ if ((vds_dapl2 = H5Dget_access_plist(vdsid2)) < 0)
+ TEST_ERROR;
+
+ /* Get append flush property and verify */
+ if (H5Pget_append_flush(dapl, 1, &boundary_out, &append_func_out, &append_func_ud_out) < 0)
+ TEST_ERROR;
+ if (boundary != boundary_out)
+ TEST_ERROR;
+ if (append_func != append_func_out)
+ TEST_ERROR;
+ if (append_func_ud != append_func_ud_out)
+ TEST_ERROR;
+
+ /* Get chunk cache property and verify */
+ if (H5Pget_chunk_cache(dapl, &rdcc_nslots_out, &rdcc_nbytes_out, &rdcc_w0_out) < 0)
+ TEST_ERROR;
+ if (rdcc_nslots != rdcc_nslots_out)
+ TEST_ERROR;
+ if (rdcc_nbytes != rdcc_nbytes_out)
+ TEST_ERROR;
+ if (HDfabs(rdcc_w0 - rdcc_w0_out) > (double)FP_EPSILON)
+ TEST_ERROR;
+
+ /* Get efile prefix property and verify */
+ if (H5Pget_efile_prefix(dapl, efile_prefix_out, sizeof(efile_prefix_out)) < 0)
+ TEST_ERROR;
+ if (HDstrncmp(efile_prefix, efile_prefix_out, sizeof(efile_prefix_out)))
+ TEST_ERROR;
+
+ /* Get virtual prefix property and verify */
+ if (H5Pget_virtual_prefix(vds_dapl1, virtual_prefix_out, sizeof(virtual_prefix_out)) < 0)
+ TEST_ERROR;
+ if (HDstrncmp(virtual_prefix, virtual_prefix_out, sizeof(virtual_prefix_out)))
+ TEST_ERROR;
+
+ /* Get virtual printf gap property and verify */
+ if (H5Pget_virtual_printf_gap(vds_dapl1, &gap_size_out) < 0)
+ TEST_ERROR;
+ if (gap_size != gap_size_out)
+ TEST_ERROR;
+
+ /* Get virtual view property and verify. Use vds_dapl2 since a VDS can't
+ * have both LAST_AVAILABLE and a printf gap set. vds1 has a printf gap and
+ * vds2 has LAST_AVAILABLE. */
+ if (H5Pget_virtual_view(vds_dapl2, &virtual_view_out) < 0)
+ TEST_ERROR;
+ if (virtual_view != virtual_view_out)
+ TEST_ERROR;
+
+ /* Close DAPLs */
+ if (H5Pclose(dapl) < 0)
+ TEST_ERROR;
+ if (H5Pclose(vds_dapl1) < 0)
+ TEST_ERROR;
+ if (H5Pclose(vds_dapl2) < 0)
+ TEST_ERROR;
+
+ return SUCCEED;
+
+error:
+ H5E_BEGIN_TRY
+ {
+ H5Pclose(dapl);
+ H5Pclose(vds_dapl1);
+ H5Pclose(vds_dapl2);
+ }
+ H5E_END_TRY;
+
+ return FAIL;
+} /* tssw_persist_dapl_verify() */
+
+static int
+test_start_swmr_write_persist_dapl(hid_t in_fapl)
+{
+ hid_t fid = H5I_INVALID_HID; /* File ID */
+ hid_t fapl = H5I_INVALID_HID; /* File access property */
+ hid_t dcpl = H5I_INVALID_HID; /* Dataset creation property */
+ hid_t vds_dcpl = H5I_INVALID_HID; /* Virtual dataset creation property */
+ hid_t dapl1 = H5I_INVALID_HID; /* Dataset access property */
+ hid_t dapl2 = H5I_INVALID_HID; /* Dataset access property */
+ hid_t did = H5I_INVALID_HID; /* Dataset ID */
+ hid_t vdsid1 = H5I_INVALID_HID; /* Virtual Dataset ID */
+ hid_t vdsid2 = H5I_INVALID_HID; /* Virtual Dataset ID */
+ hid_t sid = H5I_INVALID_HID; /* Dataspace IDs*/
+ hsize_t dim[1] = {1}; /* Dimension sizes */
+ hsize_t max_dim[1] = {H5S_UNLIMITED}; /* Maximum dimension sizes */
+ hsize_t chunk_dim[1] = {2}; /* Chunk dimension sizes */
+ hsize_t boundary = 23;
+ H5D_append_cb_t append_func = dummy_append_flush_cb;
+ void *append_func_ud = &boundary;
+ size_t rdcc_nslots = 125;
+ size_t rdcc_nbytes = 23434;
+ double rdcc_w0 = 0.68419;
+ const char *efile_prefix = "dummy_efile_prefix";
+ const char *virtual_prefix = "dummy_virtual_prefix";
+ hsize_t gap_size = 421;
+ H5D_vds_view_t virtual_view = H5D_VDS_FIRST_MISSING;
+ char filename[NAME_BUF_SIZE]; /* File name */
+
+ /* Get a copy of the parameter fapl (non-latest-format) */
+ if ((fapl = H5Pcopy(in_fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ TESTING("H5Fstart_swmr_write() persists DAPL settings");
+
+ /* Set to use the latest library format */
+ if (H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
+ TEST_ERROR;
+
+ /* Set the filename to use for this test (dependent on fapl) */
+ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename));
+
+ /* Create the file with SWMR write + non-latest-format */
+ if ((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR;
+
+ /* Create dapl with custom properties */
+ if ((dapl1 = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
+ TEST_ERROR;
+
+ /* Set append flush property */
+ boundary = 23;
+ if (H5Pset_append_flush(dapl1, 1, &boundary, dummy_append_flush_cb, append_func_ud) < 0)
+ TEST_ERROR;
+
+ /* Set chunk cache property */
+ if (H5Pset_chunk_cache(dapl1, rdcc_nslots, rdcc_nbytes, rdcc_w0) < 0)
+ TEST_ERROR;
+
+ /* Set efile prefix property */
+ if (H5Pset_efile_prefix(dapl1, efile_prefix) < 0)
+ TEST_ERROR;
+
+ /* Set virtual prefix property */
+ if (H5Pset_virtual_prefix(dapl1, virtual_prefix) < 0)
+ TEST_ERROR;
+
+ /* Set virtual printf gap property */
+ if (H5Pset_virtual_printf_gap(dapl1, gap_size) < 0)
+ TEST_ERROR;
+
+ /* Must create separate dapl2 for a different view, since the non-default
+ * view of FIRST_MISSING wipes out the printf gap setting */
+ if ((dapl2 = H5Pcopy(dapl1)) < 0)
+ TEST_ERROR;
+
+ /* Set virtual view property */
+ if (H5Pset_virtual_view(dapl2, virtual_view) < 0)
+ TEST_ERROR;
+
+ /*
+ * Case A: create file, create dataset
+ */
+
+ /* Create "dataset1" */
+ if ((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)
+ TEST_ERROR;
+ if (H5Pset_chunk(dcpl, 1, chunk_dim) < 0)
+ TEST_ERROR;
+ if ((sid = H5Screate_simple(1, dim, max_dim)) < 0)
+ TEST_ERROR;
+ if ((did = H5Dcreate2(fid, "dataset1", H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, dapl1)) < 0)
+ TEST_ERROR;
+
+ /* Create "vds1" */
+ if ((vds_dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)
+ TEST_ERROR;
+ if (H5Pset_layout(vds_dcpl, H5D_VIRTUAL) < 0)
+ TEST_ERROR;
+ if ((vdsid1 = H5Dcreate2(fid, "vds1", H5T_NATIVE_INT, sid, H5P_DEFAULT, vds_dcpl, dapl1)) < 0)
+ TEST_ERROR;
+
+ /* Create "vds2" */
+ if ((vdsid2 = H5Dcreate2(fid, "vds2", H5T_NATIVE_INT, sid, H5P_DEFAULT, vds_dcpl, dapl2)) < 0)
+ TEST_ERROR;
+
+ /* Enable swmr write */
+ if (H5Fstart_swmr_write(fid) < 0)
+ TEST_ERROR;
+
+ /* Verify dataset still has correct access properties */
+ if (tssw_persist_dapl_verify(did, vdsid1, vdsid2, boundary, append_func, append_func_ud, rdcc_nslots,
+ rdcc_nbytes, rdcc_w0, efile_prefix, virtual_prefix, gap_size,
+ virtual_view) < 0)
+ TEST_ERROR;
+
+ /* Close "dataset1" */
+ if (H5Dclose(did) < 0)
+ TEST_ERROR;
+
+ /* Close "vds1" */
+ if (H5Dclose(vdsid1) < 0)
+ TEST_ERROR;
+
+ /* Close "vds2" */
+ if (H5Dclose(vdsid2) < 0)
+ TEST_ERROR;
+
+ /* Close the file */
+ if (H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /*
+ * Case B: opened file, open dataset
+ */
+
+ /* Open the file again with write */
+ if ((fid = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
+ TEST_ERROR;
+
+ /* Open "dataset1", keep it open */
+ if ((did = H5Dopen2(fid, "dataset1", dapl1)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Open "vds1", keep it open */
+ if ((vdsid1 = H5Dopen2(fid, "vds1", dapl1)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Open "vds1", keep it open */
+ if ((vdsid2 = H5Dopen2(fid, "vds2", dapl2)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Enable swmr write */
+ if (H5Fstart_swmr_write(fid) < 0)
+ TEST_ERROR;
+
+ /* Verify dataset still has correct access properties */
+ if (tssw_persist_dapl_verify(did, vdsid1, vdsid2, boundary, append_func, append_func_ud, rdcc_nslots,
+ rdcc_nbytes, rdcc_w0, efile_prefix, virtual_prefix, gap_size,
+ virtual_view) < 0)
+ TEST_ERROR;
+
+ /* Close "dataset1" */
+ if (H5Dclose(did) < 0)
+ TEST_ERROR;
+
+ /* Close "vds1" */
+ if (H5Dclose(vdsid1) < 0)
+ TEST_ERROR;
+
+ /* Close "vds2" */
+ if (H5Dclose(vdsid2) < 0)
+ TEST_ERROR;
+
+ /* Close the file */
+ if (H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /*
+ * Case C: opened file, create dataset
+ */
+
+ /* Open the file again with write */
+ if ((fid = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
+ TEST_ERROR;
+
+ /* Create "dataset2" */
+ if ((did = H5Dcreate2(fid, "dataset2", H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, dapl1)) < 0)
+ TEST_ERROR;
+
+ /* Create "vds3" */
+ if ((vdsid1 = H5Dcreate2(fid, "vds3", H5T_NATIVE_INT, sid, H5P_DEFAULT, vds_dcpl, dapl1)) < 0)
+ TEST_ERROR;
+
+ /* Create "vds4" */
+ if ((vdsid2 = H5Dcreate2(fid, "vds4", H5T_NATIVE_INT, sid, H5P_DEFAULT, vds_dcpl, dapl2)) < 0)
+ TEST_ERROR;
+
+ /* Enable swmr write */
+ if (H5Fstart_swmr_write(fid) < 0)
+ TEST_ERROR;
+
+ /* Verify dataset still has correct access properties */
+ if (tssw_persist_dapl_verify(did, vdsid1, vdsid2, boundary, append_func, append_func_ud, rdcc_nslots,
+ rdcc_nbytes, rdcc_w0, efile_prefix, virtual_prefix, gap_size,
+ virtual_view) < 0)
+ TEST_ERROR;
+
+ /* Close "dataset1" */
+ if (H5Dclose(did) < 0)
+ TEST_ERROR;
+
+ /* Close "vds1" */
+ if (H5Dclose(vdsid1) < 0)
+ TEST_ERROR;
+
+ /* Close "vds2" */
+ if (H5Dclose(vdsid2) < 0)
+ TEST_ERROR;
+
+ /* Close the file */
+ if (H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Close dataspace, dapl, dcpl*/
+ if (H5Sclose(sid) < 0)
+ TEST_ERROR;
+ if (H5Pclose(dcpl) < 0)
+ TEST_ERROR;
+ if (H5Pclose(vds_dcpl) < 0)
+ TEST_ERROR;
+ if (H5Pclose(dapl1) < 0)
+ TEST_ERROR;
+ if (H5Pclose(dapl2) < 0)
+ TEST_ERROR;
+
+ PASSED();
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY
+ {
+ H5Fclose(fid);
+ H5Pclose(fapl);
+ H5Pclose(dcpl);
+ H5Pclose(vds_dcpl);
+ H5Pclose(dapl1);
+ H5Pclose(dapl2);
+ H5Dclose(did);
+ H5Dclose(vdsid1);
+ H5Dclose(vdsid2);
+ H5Sclose(sid);
+ }
+ H5E_END_TRY;
+
+ return -1;
+} /* test_start_swmr_write_persist_dapl() */
+
+/*
* Tests for H5Pset/get_object_flush_cb()
*/
@@ -7421,6 +7793,7 @@ main(void)
nerrors += test_start_swmr_write_concur(fapl, TRUE);
nerrors += test_start_swmr_write_concur(fapl, FALSE);
nerrors += test_start_swmr_write_stress_ohdr(fapl);
+ nerrors += test_start_swmr_write_persist_dapl(fapl);
/* Tests for H5Pget/set_object_flush_cb() */
nerrors += test_object_flush_cb(fapl);