From 4df97fe6eaf65f309d2cca8e8d89737483105374 Mon Sep 17 00:00:00 2001 From: Neil Fortner Date: Tue, 23 Aug 2022 11:08:20 -0500 Subject: Persist dataset access properties when using H5Fstart_swmr_write - merge to 1.10 (#2058) * Persist dataset access properties when using H5Fstart_swmr_write - merge to 1.12 branch (#2031) * Merge GitHub #1862 (HDFFV-11308) to 1.12 branch Persist dataset access properties when using H5Fstart_swmr_write (#1862) * Fix HDFFV-11308 - dataset access properties disappear when using H5Fstart_swmr_write. * Committing clang-format changes * Add test for H5Fstart_swmr_write() persisting DAPL settings. Fix bugs in the library exposed by this test. * Committing clang-format changes Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> * Fix bug in swmr.c introduced with recent merge (double_t) (#1913) * Fix HDFFV-11308 - dataset access properties disappear when using H5Fstart_swmr_write. * Committing clang-format changes * Add test for H5Fstart_swmr_write() persisting DAPL settings. Fix bugs in the library exposed by this test. * Committing clang-format changes * Replace accidental use of double_t in swmr.c with double. Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> * Add note to RELEASE.txt for HDFFV-11308 (#2029) * Add note to RELEASE.txt for HDFFV-11308 * Fix formatting error in RELEASE.txt * Committing clang-format changes * Fix inappropriate use of HGOTO_ERROR (#2055) Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> * Committing clang-format changes Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- release_docs/RELEASE.txt | 10 ++ src/H5Dint.c | 52 +++++-- src/H5Fint.c | 80 ++++++++-- src/H5Oflush.c | 11 +- src/H5Oprivate.h | 2 +- test/swmr.c | 373 +++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 498 insertions(+), 30 deletions(-) diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index e21c391..7b3ed57 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -163,6 +163,16 @@ Bug Fixes since HDF5-1.10.9 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 8105e53..16db10d 100644 --- a/src/H5Dint.c +++ b/src/H5Dint.c @@ -3512,11 +3512,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; @@ -3545,23 +3547,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") @@ -3571,12 +3573,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 8190227..24b306e 100644 --- a/src/H5Fint.c +++ b/src/H5Fint.c @@ -3441,6 +3441,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 */ @@ -3498,13 +3499,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, @@ -3513,18 +3521,61 @@ H5F__start_swmr_write(H5F_t *f) /* Refresh opened objects (groups, datasets) in the file */ for (u = 0; u < grp_dset_count; u++) { - H5O_loc_t *oloc; /* object location */ + 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'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: { + H5D_t *dset; /* Dataset object */ + + /* Get dataset object */ + if (NULL == (dset = (H5D_t *)H5I_object(obj_ids[u]))) + HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, FAIL, "can't find object for ID") + + /* Get dataset access properties */ + if ((obj_apl_ids[u] = H5D_get_access_plist(dset)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, + "unable to get dataset access property list") + break; + } + + case H5I_UNINIT: + case H5I_BADID: + case H5I_FILE: + case H5I_DATASPACE: + case H5I_ATTR: + case H5I_VFL: + case H5I_GENPROP_CLS: + case H5I_GENPROP_LST: + case H5I_ERROR_CLASS: + case H5I_ERROR_MSG: + case H5I_ERROR_STACK: + case H5I_NTYPES: + default: + HGOTO_ERROR(H5E_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_copy(&obj_glocs[u], &tmp_loc, H5_COPY_DEEP); @@ -3586,12 +3637,11 @@ 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], TRUE) < 0) + if (H5O_refresh_metadata_reopen(obj_ids[u], obj_apl_ids[u], &obj_glocs[u], TRUE) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't refresh-close object") 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) @@ -3632,6 +3682,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 6c5ad93..777f642 100644 --- a/src/H5Oflush.c +++ b/src/H5Oflush.c @@ -294,7 +294,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, FALSE)) < 0) + if ((H5O_refresh_metadata_reopen(oid, H5P_DEFAULT, &obj_loc, FALSE)) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to refresh object") } /* end if */ @@ -390,7 +390,7 @@ done: *------------------------------------------------------------------------- */ herr_t -H5O_refresh_metadata_reopen(hid_t oid, H5G_loc_t *obj_loc, hbool_t start_swmr) +H5O_refresh_metadata_reopen(hid_t oid, hid_t apl_id, H5G_loc_t *obj_loc, hbool_t start_swmr) { void *object = NULL; /* Object for this operation */ H5I_type_t type; /* Type of object for the ID */ @@ -418,8 +418,13 @@ H5O_refresh_metadata_reopen(hid_t oid, H5G_loc_t *obj_loc, hbool_t start_swmr) 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 3793d19..d0668cc 100644 --- a/src/H5Oprivate.h +++ b/src/H5Oprivate.h @@ -976,7 +976,7 @@ H5_DLL herr_t H5O_msg_get_flags(const H5O_loc_t *loc, unsigned type_id, uint8_t /* Object metadata flush/refresh routines */ 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, hbool_t start_swmr); +H5_DLL herr_t H5O_refresh_metadata_reopen(hid_t oid, hid_t apl_id, H5G_loc_t *obj_loc, hbool_t start_swmr); /* Object copying routines */ H5_DLL herr_t H5O_copy_header_map(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, diff --git a/test/swmr.c b/test/swmr.c index 473dda8..7dd5e75 100644 --- a/test/swmr.c +++ b/test/swmr.c @@ -55,6 +55,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); @@ -64,6 +67,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); @@ -3179,6 +3183,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() */ @@ -7422,6 +7794,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); -- cgit v0.12