summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/CMakeLists.txt19
-rw-r--r--test/Makefile.am29
-rw-r--r--test/cache_common.c11
-rw-r--r--test/cache_image.c31
-rw-r--r--test/cache_tagging.c53
-rw-r--r--test/earray.c4
-rw-r--r--test/enc_dec_plist_cross_platform.c117
-rw-r--r--test/err_compat.c6
-rw-r--r--test/farray.c4
-rw-r--r--test/fheap.c5
-rw-r--r--test/file_image.c2
-rw-r--r--test/gen_plist.c2
-rw-r--r--test/genall5.c3491
-rw-r--r--test/genall5.h63
-rw-r--r--test/h5test.c14
-rw-r--r--test/h5test.h4
-rw-r--r--test/hyperslab.c6
-rw-r--r--test/istore.c6
-rw-r--r--test/page_buffer.c1733
-rw-r--r--test/stubs.c25
-rw-r--r--test/supervise.subr32
-rw-r--r--test/swmr_addrem_writer.c2
-rw-r--r--test/swmr_common.c19
-rw-r--r--test/swmr_common.h2
-rw-r--r--test/swmr_reader.c2
-rw-r--r--test/swmr_remove_reader.c2
-rw-r--r--test/swmr_remove_writer.c2
-rw-r--r--test/swmr_sparse_reader.c5
-rw-r--r--test/swmr_sparse_writer.c2
-rw-r--r--test/swmr_start_write.c2
-rw-r--r--test/swmr_writer.c2
-rw-r--r--test/testfiles/err_compat_14
-rw-r--r--test/testfiles/plist_files/dcpl_32bebin221 -> 239 bytes
-rw-r--r--test/testfiles/plist_files/dcpl_32lebin221 -> 239 bytes
-rw-r--r--test/testfiles/plist_files/dcpl_64bebin221 -> 239 bytes
-rw-r--r--test/testfiles/plist_files/dcpl_64lebin221 -> 239 bytes
-rw-r--r--test/testfiles/plist_files/def_dcpl_32bebin132 -> 150 bytes
-rw-r--r--test/testfiles/plist_files/def_dcpl_32lebin132 -> 150 bytes
-rw-r--r--test/testfiles/plist_files/def_dcpl_64bebin132 -> 150 bytes
-rw-r--r--test/testfiles/plist_files/def_dcpl_64lebin132 -> 150 bytes
-rw-r--r--test/testfiles/plist_files/def_dxpl_32bebin225 -> 225 bytes
-rw-r--r--test/testfiles/plist_files/def_dxpl_32lebin225 -> 225 bytes
-rw-r--r--test/testfiles/plist_files/def_dxpl_64bebin225 -> 225 bytes
-rw-r--r--test/testfiles/plist_files/def_dxpl_64lebin225 -> 225 bytes
-rw-r--r--test/testfiles/plist_files/def_fapl_32bebin1651 -> 3745 bytes
-rw-r--r--test/testfiles/plist_files/def_fapl_32lebin1651 -> 3745 bytes
-rw-r--r--test/testfiles/plist_files/def_fapl_64bebin1651 -> 3745 bytes
-rw-r--r--test/testfiles/plist_files/def_fapl_64lebin1651 -> 3745 bytes
-rw-r--r--test/testfiles/plist_files/dxpl_32bebin229 -> 229 bytes
-rw-r--r--test/testfiles/plist_files/dxpl_32lebin229 -> 229 bytes
-rw-r--r--test/testfiles/plist_files/dxpl_64bebin229 -> 229 bytes
-rw-r--r--test/testfiles/plist_files/dxpl_64lebin229 -> 229 bytes
-rw-r--r--test/testfiles/plist_files/fapl_32bebin1653 -> 3747 bytes
-rw-r--r--test/testfiles/plist_files/fapl_32lebin1653 -> 3747 bytes
-rw-r--r--test/testfiles/plist_files/fapl_64bebin1653 -> 3747 bytes
-rw-r--r--test/testfiles/plist_files/fapl_64lebin1653 -> 3747 bytes
-rw-r--r--test/testfiles/plist_files/lapl_32bebin1756 -> 3850 bytes
-rw-r--r--test/testfiles/plist_files/lapl_32lebin1756 -> 3850 bytes
-rw-r--r--test/testfiles/plist_files/lapl_64bebin1756 -> 3850 bytes
-rw-r--r--test/testfiles/plist_files/lapl_64lebin1756 -> 3850 bytes
-rw-r--r--test/testvfdswmr.sh.in746
-rw-r--r--test/tmisc.c1
-rw-r--r--test/unlink.c2
-rw-r--r--test/vfd_swmr.c3474
-rw-r--r--test/vfd_swmr_addrem_writer.c502
-rw-r--r--test/vfd_swmr_bigset_writer.c1104
-rw-r--r--test/vfd_swmr_common.c262
-rw-r--r--test/vfd_swmr_common.h114
-rw-r--r--test/vfd_swmr_generator.c399
-rw-r--r--test/vfd_swmr_group_writer.c343
-rw-r--r--test/vfd_swmr_reader.c677
-rw-r--r--test/vfd_swmr_remove_reader.c596
-rw-r--r--test/vfd_swmr_remove_writer.c426
-rw-r--r--test/vfd_swmr_sparse_reader.c535
-rw-r--r--test/vfd_swmr_sparse_writer.c488
-rw-r--r--test/vfd_swmr_vlstr_reader.c232
-rw-r--r--test/vfd_swmr_vlstr_writer.c322
-rw-r--r--test/vfd_swmr_writer.c454
-rw-r--r--test/vfd_swmr_zoo_writer.c412
79 files changed, 14123 insertions, 2667 deletions
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 311d753..7e01d06 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -16,6 +16,8 @@ set (TEST_LIB_SOURCES
${HDF5_TEST_SOURCE_DIR}/cache_common.c
${HDF5_TEST_SOURCE_DIR}/external_common.c
${HDF5_TEST_SOURCE_DIR}/swmr_common.c
+ ${HDF5_TEST_SOURCE_DIR}/vfd_swmr_common.c
+ ${HDF5_TEST_SOURCE_DIR}/vds_swmr_common.c
)
set (TEST_LIB_HEADERS
@@ -24,6 +26,7 @@ set (TEST_LIB_HEADERS
${HDF5_TEST_SOURCE_DIR}/external_common.h
${HDF5_TEST_SOURCE_DIR}/external_fname.h
${HDF5_TEST_SOURCE_DIR}/swmr_common.h
+ ${HDF5_TEST_SOURCE_DIR}/vfd_swmr_common.h
)
if (NOT ONLY_SHARED_LIBS)
@@ -319,8 +322,8 @@ set (H5_TESTS_MULTIPLE
testhdf5
cache_image
ttsafe
- thread_id # special link
mirror_vfd
+ thread_id # special link
)
# Only build single source tests here
foreach (h5_test ${H5_TESTS})
@@ -500,6 +503,20 @@ foreach (h5_test ${H5_VDS_SWMR_TESTS})
ADD_H5_EXE(${h5_test})
endforeach ()
+set (H5_VFD_SWMR_TESTS
+ vds_swmr_addrem_writer
+ vfd_swmr_generator
+ vfd_swmr_reader
+ vfd_swmr_remove_reader
+ vfd_swmr_remove_writer
+ vfd_swmr_sparse_writer
+ vfd_swmr_writer
+)
+
+foreach (h5_test ${H5_VFD_SWMR_TESTS})
+ ADD_H5_EXE(${h5_test})
+endforeach ()
+
#-- Adding test for accum_swmr_reader
# This has to be copied to the test directory for execve() to find it
# and it can't be renamed (i.e., no <foo>-shared).
diff --git a/test/Makefile.am b/test/Makefile.am
index 7ebeae7..2b1d7d5 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -37,6 +37,7 @@ AM_CPPFLAGS+=-I$(top_srcdir)/src -I$(top_builddir)/src
# test_usecases.sh: use_append_chunk, use_append_mchunks, use_disable_mdc_flushes
TEST_SCRIPT = testerror.sh testlibinfo.sh testcheck_version.sh testlinks_env.sh testexternal_env.sh \
testswmr.sh testvds_env.sh testvdsswmr.sh testflushrefresh.sh test_usecases.sh testabort_fail.sh \
+ testvfdswmr.sh \
test_mirror.sh
SCRIPT_DEPEND = error_test$(EXEEXT) err_compat$(EXEEXT) links_env$(EXEEXT) \
external_env$(EXEEXT) filenotclosed$(EXEEXT) del_many_dense_attrs$(EXEEXT) \
@@ -44,7 +45,16 @@ SCRIPT_DEPEND = error_test$(EXEEXT) err_compat$(EXEEXT) links_env$(EXEEXT) \
swmr_generator$(EXEEXT) swmr_reader$(EXEEXT) swmr_writer$(EXEEXT) \
swmr_remove_reader$(EXEEXT) swmr_remove_writer$(EXEEXT) swmr_addrem_writer$(EXEEXT) \
swmr_sparse_reader$(EXEEXT) swmr_sparse_writer$(EXEEXT) swmr_start_write$(EXEEXT) \
- vds_env$(EXEEXT) vds_swmr_gen$(EXEEXT) vds_swmr_reader$(EXEEXT) vds_swmr_writer$(EXEEXT)
+ vfd_swmr_generator$(EXEEXT) vfd_swmr_reader$(EXEEXT) vfd_swmr_writer$(EXEEXT) \
+ vfd_swmr_remove_reader$(EXEEXT) vfd_swmr_remove_writer$(EXEEXT) \
+ vfd_swmr_addrem_writer$(EXEEXT) vfd_swmr_sparse_reader$(EXEEXT) \
+ vfd_swmr_sparse_writer$(EXEEXT) \
+ vfd_swmr_bigset_reader$(EXEEXT) vfd_swmr_bigset_writer$(EXEEXT) \
+ vfd_swmr_group_reader$(EXEEXT) vfd_swmr_group_writer$(EXEEXT) \
+ vfd_swmr_vlstr_reader$(EXEEXT) vfd_swmr_vlstr_writer$(EXEEXT) \
+ vfd_swmr_zoo_reader$(EXEEXT) vfd_swmr_zoo_writer$(EXEEXT) \
+ vds_env$(EXEEXT) \
+ vds_swmr_gen$(EXEEXT) vds_swmr_reader$(EXEEXT) vds_swmr_writer$(EXEEXT)
if HAVE_SHARED_CONDITIONAL
TEST_SCRIPT += test_filter_plugin.sh test_vol_plugin.sh
SCRIPT_DEPEND += filter_plugin$(EXEEXT) vol_plugin$(EXEEXT)
@@ -59,7 +69,7 @@ check_SCRIPTS = $(TEST_SCRIPT)
TEST_PROG= testhdf5 \
cache cache_api cache_image cache_tagging lheap ohdr \
stab gheap evict_on_close farray earray btree2 fheap \
- pool accum hyperslab istore bittests dt_arith page_buffer \
+ pool accum hyperslab istore bittests dt_arith page_buffer vfd_swmr \
dtypes dsets chunk_info cmpd_dset filter_fail extend direct_chunk \
external efc objcopy objcopy_ref links unlink twriteorder big mtime fillval mount \
flush1 flush2 app_ref enum set_extent ttsafe enc_dec_plist \
@@ -90,6 +100,13 @@ check_PROGRAMS=$(TEST_PROG) error_test err_compat tcheck_version \
use_append_chunk use_append_chunk_mirror use_append_mchunks use_disable_mdc_flushes \
swmr_generator swmr_start_write swmr_reader swmr_writer swmr_remove_reader \
swmr_remove_writer swmr_addrem_writer swmr_sparse_reader swmr_sparse_writer \
+ vfd_swmr_generator vfd_swmr_reader vfd_swmr_writer \
+ vfd_swmr_remove_reader vfd_swmr_remove_writer vfd_swmr_addrem_writer \
+ vfd_swmr_sparse_reader vfd_swmr_sparse_writer \
+ vfd_swmr_bigset_reader vfd_swmr_bigset_writer \
+ vfd_swmr_group_reader vfd_swmr_group_writer \
+ vfd_swmr_vlstr_reader vfd_swmr_vlstr_writer \
+ vfd_swmr_zoo_reader vfd_swmr_zoo_writer \
swmr_check_compat_vfd vds_env vds_swmr_gen vds_swmr_reader vds_swmr_writer \
mirror_vfd
if HAVE_SHARED_CONDITIONAL
@@ -139,7 +156,7 @@ else
noinst_LTLIBRARIES=libh5test.la
endif
-libh5test_la_SOURCES=h5test.c testframe.c cache_common.c swmr_common.c external_common.c
+libh5test_la_SOURCES=h5test.c testframe.c cache_common.c swmr_common.c external_common.c stubs.c vfd_swmr_common.c
# Use libhd5test.la to compile all of the tests
LDADD=libh5test.la $(LIBHDF5)
@@ -150,6 +167,12 @@ ttsafe_SOURCES=ttsafe.c ttsafe_dcreate.c ttsafe_error.c ttsafe_cancel.c \
cache_image_SOURCES=cache_image.c genall5.c
mirror_vfd_SOURCES=mirror_vfd.c genall5.c
+vfd_swmr_zoo_writer_SOURCES=vfd_swmr_zoo_writer.c genall5.c
+vfd_swmr_zoo_reader_SOURCES=vfd_swmr_zoo_writer.c genall5.c
+
+vfd_swmr_bigset_reader_SOURCES=vfd_swmr_bigset_writer.c
+vfd_swmr_group_reader_SOURCES=vfd_swmr_group_writer.c
+
VFD_LIST = sec2 stdio core core_paged split multi family
if DIRECT_VFD_CONDITIONAL
VFD_LIST += direct
diff --git a/test/cache_common.c b/test/cache_common.c
index 1dc13a1..651534d 100644
--- a/test/cache_common.c
+++ b/test/cache_common.c
@@ -269,6 +269,7 @@ static const H5C_class_t pico_class[1] = {{
NULL,
pico_free_icr,
NULL,
+ NULL,
}};
static const H5C_class_t nano_class[1] = {{
@@ -286,6 +287,7 @@ static const H5C_class_t nano_class[1] = {{
NULL,
nano_free_icr,
NULL,
+ NULL,
}};
static const H5C_class_t micro_class[1] = {{
@@ -303,6 +305,7 @@ static const H5C_class_t micro_class[1] = {{
NULL,
micro_free_icr,
NULL,
+ NULL,
}};
static const H5C_class_t tiny_class[1] = {{
@@ -320,6 +323,7 @@ static const H5C_class_t tiny_class[1] = {{
NULL,
tiny_free_icr,
NULL,
+ NULL,
}};
static const H5C_class_t small_class[1] = {{
@@ -337,6 +341,7 @@ static const H5C_class_t small_class[1] = {{
NULL,
small_free_icr,
NULL,
+ NULL,
}};
static const H5C_class_t medium_class[1] = {{
@@ -354,6 +359,7 @@ static const H5C_class_t medium_class[1] = {{
NULL,
medium_free_icr,
NULL,
+ NULL,
}};
static const H5C_class_t large_class[1] = {{
@@ -371,6 +377,7 @@ static const H5C_class_t large_class[1] = {{
NULL,
large_free_icr,
NULL,
+ NULL,
}};
static const H5C_class_t huge_class[1] = {{
@@ -388,6 +395,7 @@ static const H5C_class_t huge_class[1] = {{
NULL,
huge_free_icr,
NULL,
+ NULL,
}};
static const H5C_class_t monster_class[1] = {{
@@ -405,6 +413,7 @@ static const H5C_class_t monster_class[1] = {{
NULL,
monster_free_icr,
NULL,
+ NULL,
}};
static const H5C_class_t variable_class[1] = {{
@@ -422,6 +431,7 @@ static const H5C_class_t variable_class[1] = {{
NULL,
variable_free_icr,
NULL,
+ NULL,
}};
static const H5C_class_t notify_class[1] = {{
@@ -439,6 +449,7 @@ static const H5C_class_t notify_class[1] = {{
notify_notify,
notify_free_icr,
NULL,
+ NULL,
}};
/* callback table declaration */
diff --git a/test/cache_image.c b/test/cache_image.c
index 59689a9..d4002c7 100644
--- a/test/cache_image.c
+++ b/test/cache_image.c
@@ -22,7 +22,6 @@
/* global variable declarations: */
-
const char *FILENAMES[] = {
"cache_image_test",
NULL
@@ -4820,7 +4819,9 @@ cache_image_smoke_check_5(hbool_t single_file_vfd)
/* 3) Construct a "zoo" in the above group, and validate it. */
if ( pass )
- create_zoo(file_id, process_group_name, min_group);
+ pass = create_zoo(file_id, process_group_name,
+ (zoo_config_t){.proc_num = min_group, .skip_varlen = false,
+ .skip_compact = false});
#if H5C_COLLECT_CACHE_STATS
if ( pass ) {
@@ -4891,8 +4892,11 @@ cache_image_smoke_check_5(hbool_t single_file_vfd)
/* 6) Validate the "zoo" created in the previous file open. */
- if ( pass )
- validate_zoo(file_id, process_group_name, max_group);
+ if ( pass ) {
+ pass = validate_zoo(file_id, process_group_name,
+ (zoo_config_t){.proc_num = max_group, .skip_varlen = false,
+ .skip_compact = false});
+ }
#if H5C_COLLECT_CACHE_STATS
if ( pass ) {
@@ -4932,8 +4936,11 @@ cache_image_smoke_check_5(hbool_t single_file_vfd)
/* 8) Construct a "zoo" in the above group, and validate it. */
- if ( pass )
- create_zoo(file_id, process_group_name, max_group);
+ if ( pass ) {
+ pass = create_zoo(file_id, process_group_name,
+ (zoo_config_t){.proc_num = max_group, .skip_varlen = false,
+ .skip_compact = false});
+ }
if ( show_progress )
HDfprintf(stdout, "%s:L4 cp = %d, max_group = %d, pass = %d.\n",
@@ -4994,7 +5001,9 @@ cache_image_smoke_check_5(hbool_t single_file_vfd)
i = min_group;
while(pass && i <= max_group) {
HDsprintf(process_group_name, "/process_%d", i);
- validate_zoo(file_id, process_group_name, i++);
+ pass = validate_zoo(file_id, process_group_name,
+ (zoo_config_t){.proc_num = i++, .skip_varlen = false,
+ .skip_compact = false});
}
#if H5C_COLLECT_CACHE_STATS
@@ -5047,7 +5056,9 @@ cache_image_smoke_check_5(hbool_t single_file_vfd)
while ( ( pass ) && ( i <= max_group ) ) {
HDsprintf(process_group_name, "/process_%d", i);
- validate_zoo(file_id, process_group_name, i++);
+ pass = validate_zoo(file_id, process_group_name,
+ (zoo_config_t){.proc_num = i++, .skip_varlen = false,
+ .skip_compact = false});
}
#if H5C_COLLECT_CACHE_STATS
@@ -5111,7 +5122,9 @@ cache_image_smoke_check_5(hbool_t single_file_vfd)
i = min_group;
while ( ( pass ) && ( i <= max_group ) ) {
HDsprintf(process_group_name, "/process_%d", i);
- validate_zoo(file_id, process_group_name, i++);
+ pass = validate_zoo(file_id, process_group_name,
+ (zoo_config_t){.proc_num = i++, .skip_varlen = false,
+ .skip_compact = false});
}
#if H5C_COLLECT_CACHE_STATS
diff --git a/test/cache_tagging.c b/test/cache_tagging.c
index cf0cd8d..ddd63e4 100644
--- a/test/cache_tagging.c
+++ b/test/cache_tagging.c
@@ -443,7 +443,7 @@ check_file_creation_tags(hid_t fcpl_id, int type)
hid_t fid = -1; /* File Identifier */
#ifndef NDEBUG
int verbose = FALSE; /* verbose test outout */
-#endif /* NDEBUG */ /* end debugging functions */
+#endif
hid_t fapl = -1; /* File access prop list */
haddr_t root_tag = 0;
haddr_t sbe_tag = 0;
@@ -532,7 +532,7 @@ check_file_open_tags(hid_t fcpl, int type)
hid_t fid = -1; /* File Identifier */
#ifndef NDEBUG
int verbose = FALSE; /* verbose file outout */
-#endif /* NDEBUG */ /* end debugging functions */
+#endif
hid_t fapl = -1; /* File access prop list */
haddr_t root_tag; /* Root Group Tag */
haddr_t sbe_tag; /* Sblock Extension Tag */
@@ -647,7 +647,7 @@ check_group_creation_tags(void)
hid_t gid = -1; /* Group Identifier */
#ifndef NDEBUG
int verbose = FALSE; /* verbose file outout */
-#endif /* NDEBUG */ /* end debugging functions */
+#endif
hid_t fapl = -1; /* File access prop list */
haddr_t root_tag = HADDR_UNDEF; /* Root Group Tag */
haddr_t g_tag; /* Group Tag */
@@ -750,7 +750,7 @@ check_multi_group_creation_tags(void)
hid_t gid = -1; /* Group Identifier */
#ifndef NDEBUG
int verbose = FALSE; /* verbose file outout */
-#endif /* NDEBUG */ /* end debugging functions */
+#endif
char gname[16]; /* group name buffer */
int i = 0; /* iterator */
hid_t fapl = -1; /* File access prop list */
@@ -881,7 +881,7 @@ check_link_iteration_tags(void)
hid_t did = -1; /* Group Identifier */
#ifndef NDEBUG
int verbose = FALSE; /* verbose file outout */
-#endif /* NDEBUG */ /* end debugging functions */
+#endif
int i = 0; /* iterator */
haddr_t root_tag = 0; /* Root Group Tag Value */
char dsetname[500]; /* Name of dataset */
@@ -1003,7 +1003,7 @@ check_dense_attribute_tags(void)
hid_t dcpl = -1; /* Group Identifier */
#ifndef NDEBUG
int verbose = FALSE; /* verbose file outout */
-#endif /* NDEBUG */ /* end debugging functions */
+#endif
int i = 0; /* iterator */
hid_t fapl = -1; /* File access property list */
haddr_t d_tag = 0; /* Dataset tag value */
@@ -1187,7 +1187,7 @@ check_group_open_tags(void)
hid_t gid = -1; /* Group Identifier */
#ifndef NDEBUG
int verbose = FALSE; /* verbose file output */
-#endif /* NDEBUG */ /* end debugging functions */
+#endif
hid_t fapl = -1; /* File access prop list */
haddr_t root_tag = HADDR_UNDEF;
haddr_t g_tag;
@@ -1298,7 +1298,7 @@ check_attribute_creation_tags(hid_t fcpl, int type)
hid_t sid = -1; /* Dataspace Identifier */
#ifndef NDEBUG
int verbose = FALSE; /* verbose file outout */
-#endif /* NDEBUG */ /* end debugging functions */
+#endif
hid_t fapl = -1; /* File access prop list */
haddr_t root_tag = 0; /* Root group tag */
haddr_t g_tag = 0;
@@ -1434,7 +1434,7 @@ check_attribute_open_tags(hid_t fcpl, int type)
hid_t sid = -1; /* Dataspace Identifier */
#ifndef NDEBUG
int verbose = FALSE; /* verbose file outout */
-#endif /* NDEBUG */ /* end debugging functions */
+#endif
hid_t fapl = -1; /* File access prop list */
haddr_t root_tag = 0;
haddr_t g_tag = 0;
@@ -1573,7 +1573,7 @@ check_attribute_rename_tags(hid_t fcpl, int type)
hid_t sid = -1; /* Dataset Identifier */
#ifndef NDEBUG
int verbose = FALSE; /* verbose file outout */
-#endif /* NDEBUG */ /* end debugging functions */
+#endif
int *data = NULL; /* data buffer */
int i,j,k = 0; /* iterators */
hid_t fapl = -1; /* File access prop list */
@@ -1750,7 +1750,7 @@ check_attribute_delete_tags(hid_t fcpl, int type)
hid_t sid = -1; /* Dataset Identifier */
#ifndef NDEBUG
int verbose = FALSE; /* verbose file outout */
-#endif /* NDEBUG */ /* end debugging functions */
+#endif
int *data = NULL; /* data buffer */
int i,j,k = 0; /* iterators */
hid_t fapl = -1; /* File access prop list */
@@ -1918,7 +1918,7 @@ check_dataset_creation_tags(hid_t fcpl, int type)
hid_t sid = -1; /* Dataspace Identifier */
#ifndef NDEBUG
int verbose = FALSE; /* verbose file outout */
-#endif /* NDEBUG */ /* end debugging functions */
+#endif
hid_t dcpl = -1; /* dataset creation pl */
hsize_t cdims[2] = {1,1}; /* chunk dimensions */
int fillval = 0;
@@ -2053,7 +2053,7 @@ check_dataset_creation_earlyalloc_tags(hid_t fcpl, int type)
hid_t sid = -1; /* Dataspace Identifier */
#ifndef NDEBUG
int verbose = FALSE; /* verbose file outout */
-#endif /* NDEBUG */ /* end debugging functions */
+#endif
hid_t dcpl = -1; /* dataset creation pl */
hsize_t cdims[2] = {1,1}; /* chunk dimensions */
int fillval = 0;
@@ -2192,7 +2192,7 @@ check_dataset_open_tags(void)
hid_t sid = -1; /* Dataspace Identifier */
#ifndef NDEBUG
int verbose = FALSE; /* verbose file outout */
-#endif /* NDEBUG */ /* end debugging functions */
+#endif
hid_t dcpl = -1; /* dataset creation pl */
hsize_t cdims[2] = {1,1}; /* chunk dimensions */
int fillval = 0;
@@ -2320,7 +2320,7 @@ check_dataset_write_tags(void)
hid_t sid = -1; /* Dataspace Identifier */
#ifndef NDEBUG
int verbose = FALSE; /* verbose file outout */
-#endif /* NDEBUG */ /* end debugging functions */
+#endif
hid_t dcpl = -1; /* dataset creation pl */
hsize_t cdims[2] = {1,1}; /* chunk dimensions */
int fillval = 0;
@@ -2464,7 +2464,7 @@ check_attribute_write_tags(hid_t fcpl, int type)
hid_t sid = -1; /* Dataset Identifier */
#ifndef NDEBUG
int verbose = FALSE; /* verbose file outout */
-#endif /* NDEBUG */ /* end debugging functions */
+#endif
int *data = NULL; /* data buffer */
int i,j,k = 0; /* iterators */
hid_t fapl = -1; /* File access prop list */
@@ -2619,7 +2619,7 @@ check_dataset_read_tags(void)
hid_t sid = -1; /* Dataspace Identifier */
#ifndef NDEBUG
int verbose = FALSE; /* verbose file outout */
-#endif /* NDEBUG */ /* end debugging functions */
+#endif
hid_t dcpl = -1; /* dataset creation pl */
hsize_t cdims[2] = {1,1}; /* chunk dimensions */
int fillval = 0;
@@ -2758,7 +2758,7 @@ check_dataset_size_retrieval(void)
hid_t sid = -1; /* Dataspace Identifier */
#ifndef NDEBUG
int verbose = FALSE; /* verbose file outout */
-#endif /* NDEBUG */ /* end debugging functions */
+#endif
hid_t dcpl = -1; /* dataset creation pl */
hsize_t cdims[2] = {1,1}; /* chunk dimensions */
int fillval = 0;
@@ -2899,7 +2899,7 @@ check_dataset_extend_tags(void)
hid_t sid = -1; /* Dataspace Identifier */
#ifndef NDEBUG
int verbose = FALSE; /* verbose file outout */
-#endif /* NDEBUG */ /* end debugging functions */
+#endif
hid_t dcpl = -1; /* dataset creation pl */
hsize_t cdims[2] = {1,1}; /* chunk dimensions */
int fillval = 0;
@@ -3038,7 +3038,7 @@ check_object_info_tags(void)
hid_t gid = -1; /* Group Identifier */
#ifndef NDEBUG
int verbose = FALSE; /* verbose file output */
-#endif /* NDEBUG */ /* end debugging functions */
+#endif
hid_t fapl = -1; /* File access prop list */
haddr_t root_tag = HADDR_UNDEF;
haddr_t g_tag;
@@ -3152,7 +3152,7 @@ check_object_copy_tags(void)
hid_t gid = -1; /* Group Identifier */
#ifndef NDEBUG
int verbose = FALSE; /* verbose file output */
-#endif /* NDEBUG */ /* end debugging functions */
+#endif
hid_t fapl = -1; /* File access prop list */
haddr_t root_tag = HADDR_UNDEF;
haddr_t g_tag;
@@ -3275,7 +3275,7 @@ check_link_removal_tags(hid_t fcpl, int type)
hid_t gid = -1; /* Dataspace Identifier */
#ifndef NDEBUG
int verbose = FALSE; /* verbose file outout */
-#endif /* NDEBUG */ /* end debugging functions */
+#endif
hid_t dcpl = -1; /* dataset creation pl */
hsize_t cdims[2] = {1,1}; /* chunk dimensions */
int fillval = 0;
@@ -3436,7 +3436,7 @@ check_link_getname_tags(void)
hid_t gid = -1; /* Dataspace Identifier */
#ifndef NDEBUG
int verbose = FALSE; /* verbose file outout */
-#endif /* NDEBUG */ /* end debugging functions */
+#endif
hid_t dcpl = -1; /* dataset creation pl */
hsize_t cdims[2] = {1,1}; /* chunk dimensions */
int fillval = 0;
@@ -3587,7 +3587,7 @@ check_external_link_creation_tags(void)
hid_t gid = -1; /* Dataspace Identifier */
#ifndef NDEBUG
int verbose = FALSE; /* verbose file outout */
-#endif /* NDEBUG */ /* end debugging functions */
+#endif
hid_t fapl = -1; /* File access prop list */
haddr_t root_tag = 0;
@@ -3695,7 +3695,7 @@ check_external_link_open_tags(void)
hid_t xid = -1; /* Dataspace Identifier */
#ifndef NDEBUG
int verbose = FALSE; /* verbose file outout */
-#endif /* NDEBUG */ /* end debugging functions */
+#endif
H5O_native_info_t ninfo; /* Native object info struct */
hid_t fapl = -1; /* File access prop list */
haddr_t root_tag = 0;
@@ -3900,10 +3900,9 @@ check_invalid_tag_application(void)
#if H5C_DO_TAGGING_SANITY_CHECKS
error:
if(api_ctx_pushed) H5CX_pop();
-
- return 1;
#endif /* H5C_DO_TAGGING_SANITY_CHECKS */
+ return 1;
} /* check_invalid_tag_application */
diff --git a/test/earray.c b/test/earray.c
index 6597afd..82c482d 100644
--- a/test/earray.c
+++ b/test/earray.c
@@ -2106,7 +2106,7 @@ test_set_elmts(hid_t fapl, H5EA_create_t *cparam, earray_test_param_t *tparam,
/*
* Display testing message
*/
- TESTING(test_str);
+ TESTING("%s", test_str);
/* Create file & retrieve pointer to internal file object */
if(create_file(H5F_ACC_TRUNC, fapl, &file, &f) < 0)
@@ -2280,7 +2280,7 @@ test_skip_elmts(hid_t fapl, H5EA_create_t *cparam, earray_test_param_t *tparam,
/*
* Display testing message
*/
- TESTING(test_str);
+ TESTING("%s", test_str);
/* Create file & retrieve pointer to internal file object */
if(create_file(H5F_ACC_TRUNC, fapl, &file, &f) < 0)
diff --git a/test/enc_dec_plist_cross_platform.c b/test/enc_dec_plist_cross_platform.c
index f54f675..c4dec9f 100644
--- a/test/enc_dec_plist_cross_platform.c
+++ b/test/enc_dec_plist_cross_platform.c
@@ -156,73 +156,70 @@ error:
return 1;
}
+static hid_t
+read_and_decode_plist_file(const char *filename_prefix, unsigned config, char *filename, size_t filename_len)
+{
+ int fd;
+ size_t size;
+ const char *testfile;
+ void *buf = NULL;
+ hid_t plist = H5I_INVALID_HID;
+
+ /* Generate filename from prefix and configuration word */
+ if(HDsnprintf(filename, filename_len, "%s%s%s", filename_prefix,
+ config & CONFIG_64 ? "64" : "32",
+ config & CONFIG_LE ? "le" : "be") < 0)
+ TEST_ERROR
+
+ /* Read file 1 */
+ testfile = H5_get_srcdir_filename(filename);
+ if((fd = HDopen(testfile, O_RDONLY)) < 0)
+ TEST_ERROR
+ size = (size_t)HDlseek(fd, 0, SEEK_END);
+ HDlseek(fd, 0, SEEK_SET);
+ buf = HDmalloc(size);
+ if(HDread(fd, buf, size) < 0)
+ TEST_ERROR
+ HDclose(fd);
+
+ /* Decode property lists */
+ if((plist = H5Pdecode(buf)) < 0)
+ FAIL_STACK_ERROR
+error:
+ if (buf != NULL)
+ HDfree(buf);
+ return plist;
+}
+
static int
test_plists(const char *filename_prefix)
{
- unsigned config_1, config_2;
- int fd_1, fd_2;
- size_t size_1 = 0, size_2 = 0;
- void *buf_1 = NULL, *buf_2 = NULL;
- hid_t plist_1, plist_2;
- char filename[1024];
- const char *testfile;
+ int i;
+ unsigned config[2];
+ hid_t plist[2];
+ char filename[2][1024];
/* Iterate over all combinations of configurations */
- for(config_1 = 0; config_1 < (NCONFIG - 1); config_1++)
- for(config_2 = config_1 + 1; config_2 < NCONFIG; config_2++) {
- /* Generate filename for file 1 */
- if(HDsnprintf(filename, sizeof(filename), "%s%s%s", filename_prefix,
- config_1 & CONFIG_64 ? "64" : "32",
- config_1 & CONFIG_LE ? "le" : "be") < 0)
- TEST_ERROR
-
- /* Read file 1 */
- testfile = H5_get_srcdir_filename(filename);
- if((fd_1 = HDopen(testfile, O_RDONLY)) < 0)
- TEST_ERROR
- size_1 = (size_t)HDlseek(fd_1, (HDoff_t)0, SEEK_END);
- HDlseek(fd_1, (HDoff_t)0, SEEK_SET);
- buf_1 = (void *)HDmalloc(size_1);
- if(HDread(fd_1, buf_1, size_1) < 0)
- TEST_ERROR
- HDclose(fd_1);
-
- /* Generate filename for file 2 */
- if(HDsnprintf(filename, sizeof(filename), "%s%s%s", filename_prefix,
- config_2 & CONFIG_64 ? "64" : "32",
- config_2 & CONFIG_LE ? "le" : "be") < 0)
- TEST_ERROR
-
- /* Read file 1 */
- testfile = H5_get_srcdir_filename(filename);
- if((fd_2 = HDopen(testfile, O_RDONLY)) < 0)
- TEST_ERROR
- size_2 = (size_t)HDlseek(fd_2, (HDoff_t)0, SEEK_END);
- HDlseek(fd_2, (HDoff_t)0, SEEK_SET);
- buf_2 = (void *)HDmalloc(size_2);
- if(HDread(fd_2, buf_2, size_2) < 0)
- TEST_ERROR
- HDclose(fd_2);
-
- /* Decode property lists */
- if((plist_1 = H5Pdecode(buf_1)) < 0)
- FAIL_STACK_ERROR
- if((plist_2 = H5Pdecode(buf_2)) < 0)
- FAIL_STACK_ERROR
+ for(config[0] = 0; config[0] < (NCONFIG - 1); config[0]++) {
+ for(config[1] = config[0] + 1; config[1] < NCONFIG; config[1]++) {
+ for (i = 0; i < 2; i++) {
+ plist[i] = read_and_decode_plist_file(filename_prefix,
+ config[i], filename[i], sizeof(filename[i]));
+ if (plist[i] == H5I_INVALID_HID)
+ goto error;
+ }
/* Compare decoded property lists */
- if(!H5Pequal(plist_1, plist_2))
- FAIL_PUTS_ERROR("PLIST encoding/decoding comparison failed\n")
-
- /* Close */
- if((H5Pclose(plist_1)) < 0)
- FAIL_STACK_ERROR
- if((H5Pclose(plist_2)) < 0)
- FAIL_STACK_ERROR
-
- HDfree(buf_1);
- HDfree(buf_2);
- } /* end for */
+ if(!H5Pequal(plist[0], plist[1]))
+ FAIL_PRINTF_ERROR("PLIST encoding/decoding comparison failed, "
+ "%s != %s\n", filename[0], filename[1])
+
+ for (i = 0; i < 2; i++) {
+ if((H5Pclose(plist[i])) < 0)
+ FAIL_STACK_ERROR
+ }
+ }
+ }
return 1;
diff --git a/test/err_compat.c b/test/err_compat.c
index eb86760..bd317bf 100644
--- a/test/err_compat.c
+++ b/test/err_compat.c
@@ -241,7 +241,7 @@ test_error1(void)
herr_t ret;
TESTING("error API H5Eset/get_auto");
- HDfprintf(stderr, "\n");
+ printf("\n");
/* Create the data space */
dims[0] = DIM0;
@@ -338,6 +338,7 @@ test_error1(void)
if(dataset >= 0)
TEST_ERROR;
+ fprintf(stderr, "\n");
return 0;
error:
@@ -370,7 +371,7 @@ test_error2(hid_t file)
const char *FUNC_test_error="test_error2";
TESTING("error API based on data I/O");
- HDfprintf(stderr, "\n");
+ printf("\n");
/* Create the data space */
dims[0] = DIM0;
@@ -504,6 +505,7 @@ main(void)
/* Print out the errors on stack */
dump_error();
+ fprintf(stderr, "\n");
/* Empty error stack */
H5Eclear1();
diff --git a/test/farray.c b/test/farray.c
index b647b51..2cc79a1 100644
--- a/test/farray.c
+++ b/test/farray.c
@@ -1376,7 +1376,7 @@ test_set_elmts(hid_t fapl, H5FA_create_t *cparam, farray_test_param_t *tparam,
/*
* Display testing message
*/
- TESTING(test_str);
+ TESTING("%s", test_str);
/* Create file & retrieve pointer to internal file object */
if(create_file(fapl, &file, &f) < 0)
@@ -1531,7 +1531,7 @@ test_skip_elmts(hid_t fapl, H5FA_create_t *cparam, farray_test_param_t *tparam,
/*
* Display testing message
*/
- TESTING(test_str);
+ TESTING("%s", test_str);
/* Create file & retrieve pointer to internal file object */
if(create_file(fapl, &file, &f) < 0)
diff --git a/test/fheap.c b/test/fheap.c
index b1a0db0..b6d24f7 100644
--- a/test/fheap.c
+++ b/test/fheap.c
@@ -558,11 +558,8 @@ begin_test(fheap_test_param_t *tparam, const char *base_desc,
*/
del_str = get_del_string(tparam);
HDassert(del_str);
- test_desc = (char *)H5MM_malloc(HDstrlen(del_str) + HDstrlen(base_desc));
- HDsprintf(test_desc, base_desc, del_str);
- TESTING(test_desc);
+ TESTING(base_desc, del_str);
H5MM_xfree(del_str);
- H5MM_xfree(test_desc);
/* Initialize the heap ID structure */
HDmemset(keep_ids, 0, sizeof(fheap_heap_ids_t));
diff --git a/test/file_image.c b/test/file_image.c
index 0d4873a..bb16e6d 100644
--- a/test/file_image.c
+++ b/test/file_image.c
@@ -710,7 +710,7 @@ test_get_file_image(const char * test_banner,
hid_t fcpl = -1;
herr_t ret;
- TESTING(test_banner);
+ TESTING("%s", test_banner);
/* set flag if we are dealing with a family file */
driver = H5Pget_driver(fapl);
diff --git a/test/gen_plist.c b/test/gen_plist.c
index b6f5597..7f64aa4 100644
--- a/test/gen_plist.c
+++ b/test/gen_plist.c
@@ -469,7 +469,7 @@ encode_plist(hid_t plist_id, int little_endian, int word_length, const char *fil
if((ret = H5Pencode2(plist_id, NULL, &temp_size, H5P_DEFAULT)) < 0)
HDassert(ret > 0);
- temp_buf = (void *)HDmalloc(temp_size);
+ temp_buf = HDcalloc(1, temp_size);
HDassert(temp_buf);
if((ret = H5Pencode2(plist_id, temp_buf, &temp_size, H5P_DEFAULT)) < 0)
diff --git a/test/genall5.c b/test/genall5.c
index 3f55930..0a64f37 100644
--- a/test/genall5.c
+++ b/test/genall5.c
@@ -19,6 +19,8 @@
* of the same name.
*/
+#include <err.h>
+
#include "cache_common.h"
#include "genall5.h"
@@ -27,6 +29,70 @@
#define DSET_CHUNK_DIMS 1024
#define DSET_COMPACT_DIMS 4096
+typedef enum phase {PHASE_CREATE, PHASE_VALIDATE, PHASE_DELETE,
+ PHASE_VALIDATE_DELETION} phase_t;
+
+static bool rm_ns_grp_0(hid_t, const char *);
+static bool rm_ns_grp_c(hid_t, const char *, unsigned);
+static bool rm_ns_grp_d(hid_t, const char *, unsigned);
+static bool rm_os_grp_0(hid_t, const char *);
+static bool rm_os_grp_n(hid_t, const char *, int, unsigned);
+static bool rm_ds_ctg_i(hid_t, const char *, hbool_t);
+static bool rm_ds_chk_i(hid_t, const char *, hbool_t);
+static bool rm_ds_cpt_i(hid_t, const char *, hbool_t);
+static bool rm_ds_ctg_v(hid_t, const char *, hbool_t);
+
+static bool missing_ns_grp_0(hid_t, const char *);
+static bool missing_ns_grp_c(hid_t, const char *, unsigned);
+static bool missing_ns_grp_d(hid_t, const char *, unsigned);
+static bool missing_os_grp_0(hid_t, const char *);
+static bool missing_os_grp_n(hid_t, const char *, int, unsigned);
+static bool missing_ds_ctg_i(hid_t, const char *, hbool_t);
+static bool missing_ds_chk_i(hid_t, const char *, hbool_t);
+static bool missing_ds_cpt_i(hid_t, const char *, hbool_t);
+static bool missing_ds_ctg_v(hid_t, const char *, hbool_t);
+
+#define FN_ITEM_DEFN(__name, ...) \
+ typedef bool (*__name##fn_t)(__VA_ARGS__); \
+ static const __name##fn_t __name##_fntbl[] = \
+ {__name, vrfy_##__name, rm_##__name, missing_##__name}
+
+FN_ITEM_DEFN(ns_grp_0, hid_t, const char *);
+FN_ITEM_DEFN(ns_grp_c, hid_t, const char *, unsigned);
+FN_ITEM_DEFN(ns_grp_d, hid_t, const char *, unsigned);
+FN_ITEM_DEFN(os_grp_0, hid_t, const char *);
+FN_ITEM_DEFN(os_grp_n, hid_t, const char *, int, unsigned);
+FN_ITEM_DEFN(ds_ctg_i, hid_t, const char *, bool);
+FN_ITEM_DEFN(ds_chk_i, hid_t, const char *, bool);
+FN_ITEM_DEFN(ds_cpt_i, hid_t, const char *, bool);
+FN_ITEM_DEFN(ds_ctg_v, hid_t, const char *, bool);
+
+#undef FN_ITEM_DEFN
+
+static bool
+file_has_no_path(hid_t fid, const char *path)
+{
+ switch (H5Lexists(fid, path, H5P_DEFAULT)) {
+ case FALSE:
+ return true;
+ case TRUE:
+ failure_mssg = "H5Lexists unexpectedly true.";
+ return false;
+ default:
+ failure_mssg = "H5Lexists unexpectedly failed.";
+ return false;
+ }
+}
+
+static bool
+remove_from_file_path(hid_t fid, const char *path)
+{
+ if (H5Ldelete(fid, path, H5P_DEFAULT) < 0) {
+ failure_mssg = "H5Ldelete failed.";
+ return false;
+ }
+ return true;
+}
/*-------------------------------------------------------------------------
* Function: ns_grp_0
@@ -34,12 +100,10 @@
* Purpose: Create an empty "new style" group at the specified location
* in the specified file.
*
- * If pass is false on entry, do nothing.
- *
- * If an error is detected, set pass to FALSE, and set
+ * If an error is detected, return false, and set
* failure_mssg to point to an appropriate error message.
*
- * Return: void
+ * Return: true on success, false on failure.
*
* Programmer: John Mainzer
* 9/14/15
@@ -47,65 +111,62 @@
*-------------------------------------------------------------------------
*/
-void
-ns_grp_0(hid_t fid, const char *group_name) {
+static bool
+missing_ns_grp_0(hid_t fid, const char *group_name)
+{
+ return file_has_no_path(fid, group_name);
+}
+
+static bool
+rm_ns_grp_0(hid_t fid, const char *group_name)
+{
+ return remove_from_file_path(fid, group_name);
+}
+
+bool
+ns_grp_0(hid_t fid, const char *group_name)
+{
hid_t gid = -1;
hid_t gcpl = -1;
herr_t ret;
- if (pass) {
- gcpl = H5Pcreate(H5P_GROUP_CREATE);
+ gcpl = H5Pcreate(H5P_GROUP_CREATE);
- if (gcpl <= 0) {
- pass = FALSE;
- failure_mssg = "ns_grp_0: H5Pcreate() failed";
- }
- HDassert(gcpl > 0);
+ if (gcpl <= 0) {
+ failure_mssg = "ns_grp_0: H5Pcreate() failed";
+ return false;
}
- if (pass) {
- ret = H5Pset_link_creation_order(gcpl, H5P_CRT_ORDER_TRACKED);
+ ret = H5Pset_link_creation_order(gcpl, H5P_CRT_ORDER_TRACKED);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "ns_grp_0: H5Pset_link_creation_order() failed";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "ns_grp_0: H5Pset_link_creation_order() failed";
+ return false;
}
- if (pass) {
- gid = H5Gcreate2(fid, group_name, H5P_DEFAULT, gcpl, H5P_DEFAULT);
+ gid = H5Gcreate2(fid, group_name, H5P_DEFAULT, gcpl, H5P_DEFAULT);
- if (gid <= 0) {
- pass = FALSE;
- failure_mssg = "ns_grp_0: H5Gcreate2() failed";
- }
- HDassert(gid > 0);
+ if (gid <= 0) {
+ failure_mssg = "ns_grp_0: H5Gcreate2() failed";
+ return false;
}
- if (pass) {
- ret = H5Pclose(gcpl);
+ ret = H5Pclose(gcpl);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "ns_grp_0: H5Pclose(gcpl) failed";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "ns_grp_0: H5Pclose(gcpl) failed";
+ return false;
}
- if (pass) {
- ret = H5Gclose(gid);
+ ret = H5Gclose(gid);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "ns_grp_0: H5Gclose(gid) failed";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "ns_grp_0: H5Gclose(gid) failed";
+ return false;
}
- return;
-
-} /* ns_grp_0 */
+ return true;
+}
/*-------------------------------------------------------------------------
@@ -114,12 +175,10 @@ ns_grp_0(hid_t fid, const char *group_name) {
* Purpose: verify an empty "new style" group at the specified location
* in the specified file.
*
- * If pass is false on entry, do nothing.
- *
- * If an error is detected, set pass to FALSE, and set
+ * If an error is detected, return false, and set
* failure_mssg to point to an appropriate error message.
*
- * Return: void
+ * Return: true on success, false on failure.
*
* Programmer: John Mainzer
* 9/14/15
@@ -127,103 +186,76 @@ ns_grp_0(hid_t fid, const char *group_name) {
*-------------------------------------------------------------------------
*/
-void vrfy_ns_grp_0(hid_t fid, const char *group_name) {
+bool
+vrfy_ns_grp_0(hid_t fid, const char *group_name)
+{
hid_t gid = -1;
hid_t gcpl = -1;
H5G_info_t grp_info;
unsigned crt_order_flags = 0;
herr_t ret;
- if (pass) {
- gid = H5Gopen2(fid, group_name, H5P_DEFAULT);
+ gid = H5Gopen2(fid, group_name, H5P_DEFAULT);
- if (gid <= 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_0: H5Gopen2() failed";
- }
- HDassert(gid > 0);
+ if (gid <= 0) {
+ failure_mssg = "vrfy_ns_grp_0: H5Gopen2() failed";
+ return false;
}
- if (pass) {
- gcpl = H5Gget_create_plist(gid);
+ gcpl = H5Gget_create_plist(gid);
- if (gcpl <= 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_0: H5Gget_create_plist() failed";
- }
- HDassert(gcpl > 0);
+ if (gcpl <= 0) {
+ failure_mssg = "vrfy_ns_grp_0: H5Gget_create_plist() failed";
+ return false;
}
- if (pass) {
- ret = H5Pget_link_creation_order(gcpl, &crt_order_flags);
+ ret = H5Pget_link_creation_order(gcpl, &crt_order_flags);
- if (gcpl <= 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_0: H5Pget_link_creation_order() failed";
- }
- else if ( H5P_CRT_ORDER_TRACKED != crt_order_flags) {
- pass = FALSE;
- failure_mssg =
- "vrfy_ns_grp_0: H5P_CRT_ORDER_TRACKED != crt_order_flags";
- }
- HDassert(ret >= 0);
- HDassert(H5P_CRT_ORDER_TRACKED == crt_order_flags);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ns_grp_0: H5Pget_link_creation_order() failed";
+ return false;
+ } else if ( H5P_CRT_ORDER_TRACKED != crt_order_flags) {
+ failure_mssg =
+ "vrfy_ns_grp_0: H5P_CRT_ORDER_TRACKED != crt_order_flags";
+ return false;
}
- if (pass) {
- ret = H5Pclose(gcpl);
+ ret = H5Pclose(gcpl);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_0: H5Pclose() failed";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ns_grp_0: H5Pclose() failed";
+ return false;
}
- if (pass) {
- HDmemset(&grp_info, 0, sizeof(grp_info));
- ret = H5Gget_info(gid, &grp_info);
-
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_0: H5Gget_info() failed";
- }
- else if (H5G_STORAGE_TYPE_COMPACT != grp_info.storage_type) {
- pass = FALSE;
- failure_mssg =
- "vrfy_ns_grp_0: H5G_STORAGE_TYPE_COMPACT != grp_info.storage_type";
- }
- else if (0 != grp_info.nlinks) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_0: 0 != grp_info.nlinks";
- }
- else if (0 != grp_info.max_corder) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_0: 0 != grp_info.max_corder";
- }
- else if ( FALSE != grp_info.mounted) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_0: FALSE != grp_info.mounted";
- }
+ HDmemset(&grp_info, 0, sizeof(grp_info));
+ ret = H5Gget_info(gid, &grp_info);
- HDassert(ret >= 0);
- HDassert(H5G_STORAGE_TYPE_COMPACT == grp_info.storage_type);
- HDassert(0 == grp_info.nlinks);
- HDassert(0 == grp_info.max_corder);
- HDassert(false == grp_info.mounted);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ns_grp_0: H5Gget_info() failed";
+ return false;
+ } else if (H5G_STORAGE_TYPE_COMPACT != grp_info.storage_type) {
+ failure_mssg =
+ "vrfy_ns_grp_0: H5G_STORAGE_TYPE_COMPACT != grp_info.storage_type";
+ return false;
+ } else if (0 != grp_info.nlinks) {
+ failure_mssg = "vrfy_ns_grp_0: 0 != grp_info.nlinks";
+ return false;
+ } else if (0 != grp_info.max_corder) {
+ failure_mssg = "vrfy_ns_grp_0: 0 != grp_info.max_corder";
+ return false;
+ } else if ( FALSE != grp_info.mounted) {
+ failure_mssg = "vrfy_ns_grp_0: FALSE != grp_info.mounted";
+ return false;
}
- if (pass) {
- ret = H5Gclose(gid);
+ ret = H5Gclose(gid);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_0: H5Gclose() failed";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ns_grp_0: H5Gclose() failed";
+ return false;
}
- return;
+ return true;
} /* vrfy_ns_grp_0() */
@@ -233,12 +265,10 @@ void vrfy_ns_grp_0(hid_t fid, const char *group_name) {
* Purpose: Create a compact "new style" group, with 'nlinks'
* soft/hard/external links in it in the specified file.
*
- * If pass is false on entry, do nothing.
- *
- * If an error is detected, set pass to FALSE, and set
+ * If an error is detected, return false, and set
* failure_mssg to point to an appropriate error message.
*
- * Return: void
+ * Return: true on success, false on failure.
*
* Programmer: John Mainzer
* 9/14/15
@@ -246,127 +276,111 @@ void vrfy_ns_grp_0(hid_t fid, const char *group_name) {
*-------------------------------------------------------------------------
*/
-void
-ns_grp_c(hid_t fid, const char *group_name, unsigned nlinks) {
+static bool
+missing_ns_grp_c(hid_t fid, const char *group_name,
+ unsigned H5_ATTR_UNUSED nlinks)
+{
+ return file_has_no_path(fid, group_name);
+}
+
+static bool
+rm_ns_grp_c(hid_t fid, const char *group_name, unsigned H5_ATTR_UNUSED nlinks)
+{
+ return remove_from_file_path(fid, group_name);
+}
+
+bool
+ns_grp_c(hid_t fid, const char *group_name, unsigned nlinks)
+{
hid_t gid = -1;
hid_t gcpl = -1;
unsigned max_compact;
unsigned u;
herr_t ret;
- if (pass) {
- gcpl = H5Pcreate(H5P_GROUP_CREATE);
+ gcpl = H5Pcreate(H5P_GROUP_CREATE);
- if (gcpl <= 0) {
- pass = FALSE;
- failure_mssg = "ns_grp_c: H5Pcreate(H5P_GROUP_CREATE) failed";
- }
- HDassert(gcpl > 0);
+ if (gcpl <= 0) {
+ failure_mssg = "ns_grp_c: H5Pcreate(H5P_GROUP_CREATE) failed";
+ return false;
}
- if (pass) {
- ret = H5Pset_link_creation_order(gcpl, H5P_CRT_ORDER_TRACKED);
+ ret = H5Pset_link_creation_order(gcpl, H5P_CRT_ORDER_TRACKED);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "ns_grp_c: H5Pset_link_creation_order() failed";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "ns_grp_c: H5Pset_link_creation_order() failed";
+ return false;
}
- if (pass) {
- gid = H5Gcreate2(fid, group_name, H5P_DEFAULT, gcpl, H5P_DEFAULT);
+ gid = H5Gcreate2(fid, group_name, H5P_DEFAULT, gcpl, H5P_DEFAULT);
- if (gid <= 0) {
- pass = FALSE;
- failure_mssg = "ns_grp_c: H5Gcreate2() failed";
- }
- HDassert(gid > 0);
+ if (gid <= 0) {
+ failure_mssg = "ns_grp_c: H5Gcreate2() failed";
+ return false;
}
- if (pass) {
- max_compact = 0;
- ret = H5Pget_link_phase_change(gcpl, &max_compact, NULL);
-
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "ns_grp_c: H5Pget_link_phase_change() failed";
- }
- else if (nlinks <= 0) {
- pass = FALSE;
- failure_mssg = "ns_grp_c: nlinks <= 0";
- }
- else if (nlinks >= max_compact) {
- pass = FALSE;
- failure_mssg = "ns_grp_c: nlinks >= max_compact";
- }
+ max_compact = 0;
+ ret = H5Pget_link_phase_change(gcpl, &max_compact, NULL);
- HDassert(ret >= 0);
- HDassert(nlinks > 0);
- HDassert(nlinks < max_compact);
+ if (ret < 0) {
+ failure_mssg = "ns_grp_c: H5Pget_link_phase_change() failed";
+ return false;
+ } else if (nlinks <= 0) {
+ failure_mssg = "ns_grp_c: nlinks <= 0";
+ return false;
+ } else if (nlinks >= max_compact) {
+ failure_mssg = "ns_grp_c: nlinks >= max_compact";
+ return false;
}
- u = 0;
- while ((pass) && (u < nlinks)) {
+ for (u = 0; u < nlinks; u++) {
char linkname[16];
HDsprintf(linkname, "%u", u);
if (0 == (u % 3)) {
- ret = H5Lcreate_soft(group_name, gid, linkname, H5P_DEFAULT, H5P_DEFAULT);
+ ret = H5Lcreate_soft(group_name, gid, linkname, H5P_DEFAULT,
+ H5P_DEFAULT);
if (ret < 0) {
- pass = FALSE;
failure_mssg = "ns_grp_c: H5Lcreate_soft() failed";
+ return false;
}
- HDassert(ret >= 0);
- } /* end if */
- else if (1 == (u % 3)) {
+ } else if (1 == (u % 3)) {
ret = H5Lcreate_hard(fid, "/", gid, linkname, H5P_DEFAULT,
H5P_DEFAULT);
if (ret < 0) {
- pass = FALSE;
failure_mssg = "ns_grp_c: H5Lcreate_hard() failed";
+ return false;
}
- HDassert(ret >= 0);
- } /* end else-if */
- else {
+ } else {
HDassert(2 == (u % 3));
ret = H5Lcreate_external("external.h5", "/ext", gid, linkname,
H5P_DEFAULT, H5P_DEFAULT);
if (ret < 0) {
- pass = FALSE;
failure_mssg = "ns_grp_c: H5Lcreate_external() failed";
+ return false;
}
- HDassert(ret >= 0);
- } /* end else */
-
- u++;
- } /* end while() */
+ }
+ }
- if (pass) {
- ret = H5Pclose(gcpl);
+ ret = H5Pclose(gcpl);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "ns_grp_c: H5Pclose(gcpl) failed";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "ns_grp_c: H5Pclose(gcpl) failed";
+ return false;
}
- if (pass) {
- ret = H5Gclose(gid);
+ ret = H5Gclose(gid);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "ns_grp_c: H5Gclose(gid) failed";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "ns_grp_c: H5Gclose(gid) failed";
+ return false;
}
- return;
+ return true;
} /* ns_grp_c() */
@@ -377,12 +391,10 @@ ns_grp_c(hid_t fid, const char *group_name, unsigned nlinks) {
* Purpose: Verify a compact "new style" group, with 'nlinks'
* soft/hard/external links in it in the specified file.
*
- * If pass is false on entry, do nothing.
- *
- * If an error is detected, set pass to FALSE, and set
+ * If an error is detected, return false, and set
* failure_mssg to point to an appropriate error message.
*
- * Return: void
+ * Return: true on success, false on failure.
*
* Programmer: John Mainzer
* 9/14/15
@@ -390,8 +402,9 @@ ns_grp_c(hid_t fid, const char *group_name, unsigned nlinks) {
*-------------------------------------------------------------------------
*/
-void
-vrfy_ns_grp_c(hid_t fid, const char *group_name, unsigned nlinks) {
+bool
+vrfy_ns_grp_c(hid_t fid, const char *group_name, unsigned nlinks)
+{
hid_t gid = -1;
hid_t gcpl = -1;
H5G_info_t grp_info;
@@ -399,86 +412,60 @@ vrfy_ns_grp_c(hid_t fid, const char *group_name, unsigned nlinks) {
unsigned u;
herr_t ret;
- if (pass) {
- gid = H5Gopen2(fid, group_name, H5P_DEFAULT);
+ gid = H5Gopen2(fid, group_name, H5P_DEFAULT);
- if (gid <= 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_c: H5Gopen2() failed";
- }
- HDassert(gid > 0);
+ if (gid <= 0) {
+ failure_mssg = "vrfy_ns_grp_c: H5Gopen2() failed";
+ return false;
}
- if (pass) {
- gcpl = H5Gget_create_plist(gid);
+ gcpl = H5Gget_create_plist(gid);
- if (gcpl <= 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_c: H5Gget_create_plist(gid) failed";
- }
- HDassert(gcpl > 0);
+ if (gcpl <= 0) {
+ failure_mssg = "vrfy_ns_grp_c: H5Gget_create_plist(gid) failed";
+ return false;
}
- if (pass) {
- ret = H5Pget_link_creation_order(gcpl, &crt_order_flags);
+ ret = H5Pget_link_creation_order(gcpl, &crt_order_flags);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_c: H5Pget_link_creation_order() failed";
- }
- else if ( H5P_CRT_ORDER_TRACKED != crt_order_flags) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_c: H5P_CRT_ORDER_TRACKED != crt_order_flags";
- }
- HDassert(ret >= 0);
- HDassert(H5P_CRT_ORDER_TRACKED == crt_order_flags);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ns_grp_c: H5Pget_link_creation_order() failed";
+ return false;
+ } else if ( H5P_CRT_ORDER_TRACKED != crt_order_flags) {
+ failure_mssg =
+ "vrfy_ns_grp_c: H5P_CRT_ORDER_TRACKED != crt_order_flags";
+ return false;
}
- if (pass) {
- ret = H5Pclose(gcpl);
+ ret = H5Pclose(gcpl);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_c: H5Pclose() failed";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ns_grp_c: H5Pclose() failed";
+ return false;
}
- if (pass) {
- HDmemset(&grp_info, 0, sizeof(grp_info));
- ret = H5Gget_info(gid, &grp_info);
+ HDmemset(&grp_info, 0, sizeof(grp_info));
+ ret = H5Gget_info(gid, &grp_info);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_c: H5Gget_info() failed";
- }
- else if (H5G_STORAGE_TYPE_COMPACT != grp_info.storage_type) {
- pass = FALSE;
- failure_mssg =
- "vrfy_ns_grp_c: H5G_STORAGE_TYPE_COMPACT != grp_info.storage_type";
- }
- else if (nlinks != grp_info.nlinks) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_c: nlinks != grp_info.nlinks";
- }
- else if (nlinks != grp_info.max_corder) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_c: nlinks != grp_info.max_corder";
- }
- else if ( FALSE != grp_info.mounted) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_c: FALSE != grp_info.mounted";
- }
-
- HDassert(ret >= 0);
- HDassert(H5G_STORAGE_TYPE_COMPACT == grp_info.storage_type);
- HDassert(nlinks == grp_info.nlinks);
- HDassert(nlinks == grp_info.max_corder);
- HDassert(false == grp_info.mounted);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ns_grp_c: H5Gget_info() failed";
+ return false;
+ } else if (H5G_STORAGE_TYPE_COMPACT != grp_info.storage_type) {
+ failure_mssg =
+ "vrfy_ns_grp_c: H5G_STORAGE_TYPE_COMPACT != grp_info.storage_type";
+ return false;
+ } else if (nlinks != grp_info.nlinks) {
+ failure_mssg = "vrfy_ns_grp_c: nlinks != grp_info.nlinks";
+ return false;
+ } else if (nlinks != grp_info.max_corder) {
+ failure_mssg = "vrfy_ns_grp_c: nlinks != grp_info.max_corder";
+ return false;
+ } else if ( FALSE != grp_info.mounted) {
+ failure_mssg = "vrfy_ns_grp_c: FALSE != grp_info.mounted";
+ return false;
}
- u = 0;
- while ((pass) && (u < nlinks)) {
+ for (u = 0; u < nlinks; u++) {
H5L_info2_t lnk_info;
char linkname[16];
htri_t link_exists;
@@ -487,104 +474,82 @@ vrfy_ns_grp_c(hid_t fid, const char *group_name, unsigned nlinks) {
link_exists = H5Lexists(gid, linkname, H5P_DEFAULT);
if (link_exists < 0) {
- pass = FALSE;
failure_mssg = "vrfy_ns_grp_c: H5Lexists() failed";
+ return false;
}
- HDassert(link_exists >= 0);
HDmemset(&lnk_info, 0, sizeof(grp_info));
ret = H5Lget_info2(gid, linkname, &lnk_info, H5P_DEFAULT);
if (ret < 0) {
- pass = FALSE;
failure_mssg = "vrfy_ns_grp_c: H5Lget_info() failed";
- }
- else if ( TRUE != lnk_info.corder_valid) {
- pass = FALSE;
+ return false;
+ } else if ( TRUE != lnk_info.corder_valid) {
failure_mssg = "vrfy_ns_grp_c: TRUE != lnk_info.corder_valid";
- }
- else if (u != lnk_info.corder) {
- pass = FALSE;
+ return false;
+ } else if (u != lnk_info.corder) {
failure_mssg = "vrfy_ns_grp_c: u != lnk_info.corder";
- }
- else if (H5T_CSET_ASCII != lnk_info.cset) {
- pass = FALSE;
+ return false;
+ } else if (H5T_CSET_ASCII != lnk_info.cset) {
failure_mssg = "vrfy_ns_grp_c: H5T_CSET_ASCII != lnk_info.cset";
+ return false;
}
- HDassert(ret >= 0);
- HDassert(true == lnk_info.corder_valid);
- HDassert(u == lnk_info.corder);
- HDassert(H5T_CSET_ASCII == lnk_info.cset);
if (0 == (u % 3)) {
char *slinkval;
if (H5L_TYPE_SOFT != lnk_info.type) {
- pass = FALSE;
failure_mssg = "vrfy_ns_grp_c: H5L_TYPE_SOFT != lnk_info.type";
+ return false;
}
else if ((HDstrlen(group_name) + 1) != lnk_info.u.val_size) {
- pass = FALSE;
failure_mssg = "vrfy_ns_grp_c: (HDstrlen(group_name) + 1) != lnk_info.u.val_size";
+ return false;
}
- HDassert(H5L_TYPE_SOFT == lnk_info.type);
- HDassert((HDstrlen(group_name) + 1) == lnk_info.u.val_size);
- slinkval = (char *) HDmalloc(lnk_info.u.val_size);
+ slinkval = HDmalloc(lnk_info.u.val_size);
if (!slinkval) {
- pass = FALSE;
failure_mssg = "vrfy_ns_grp_c: HDmalloc of slinkval failed";
+ return false;
}
- HDassert(slinkval);
ret = H5Lget_val(gid, linkname, slinkval, lnk_info.u.val_size,
H5P_DEFAULT);
if (ret < 0) {
- pass = FALSE;
failure_mssg = "vrfy_ns_grp_c: H5Lget_val() failed";
- }
- else if (0 != HDstrcmp(slinkval, group_name)) {
- pass = FALSE;
+ HDfree(slinkval);
+ return false;
+ } else if (0 != HDstrcmp(slinkval, group_name)) {
failure_mssg = "vrfy_ns_grp_c: 0 != HDstrcmp(slinkval, group_name)";
+ HDfree(slinkval);
+ return false;
}
- HDassert(ret >= 0);
- HDassert(0 == HDstrcmp(slinkval, group_name));
HDfree(slinkval);
- } /* end if */
- else if (1 == (u % 3)) {
+ } else if (1 == (u % 3)) {
H5O_info2_t root_oinfo;
int token_cmp = 0;
if (H5L_TYPE_HARD != lnk_info.type) {
- pass = FALSE;
failure_mssg = "vrfy_ns_grp_c: H5L_TYPE_HARD != lnk_info.type";
+ return false;
}
- HDassert(H5L_TYPE_HARD == lnk_info.type);
HDmemset(&root_oinfo, 0, sizeof(root_oinfo));
ret = H5Oget_info3(fid, &root_oinfo, H5O_INFO_BASIC);
if (ret < 0) {
- pass = FALSE;
failure_mssg = "vrfy_ns_grp_c: H5Oget_info() failed.";
+ return false;
+ } else if(H5Otoken_cmp(fid, &root_oinfo.token, &lnk_info.u.token, &token_cmp) < 0) {
+ failure_mssg = "vrfy_ns_grp_c: H5Otoken_cmp() failed.";
+ return false;
+ } else if (token_cmp) {
+ failure_mssg = "vrfy_ns_grp_c: root_oinfo.token != lnk_info.u.token";
+ return false;
}
- else {
- if(H5Otoken_cmp(fid, &root_oinfo.token, &lnk_info.u.token, &token_cmp) < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_c: H5Otoken_cmp() failed.";
- }
-
- if (token_cmp) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_c: root_oinfo.token != lnk_info.u.token";
- }
- }
- HDassert(ret >= 0);
- HDassert(!token_cmp);
- } /* end else-if */
- else {
+ } else {
void *elinkval;
const char *file = NULL;
const char *path = NULL;
@@ -592,61 +557,53 @@ vrfy_ns_grp_c(hid_t fid, const char *group_name, unsigned nlinks) {
HDassert(2 == (u % 3));
if (H5L_TYPE_EXTERNAL != lnk_info.type) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_c: H5L_TYPE_EXTERNAL != lnk_info.type";
+ failure_mssg =
+ "vrfy_ns_grp_c: H5L_TYPE_EXTERNAL != lnk_info.type";
+ return false;
}
- HDassert(H5L_TYPE_EXTERNAL == lnk_info.type);
elinkval = HDmalloc(lnk_info.u.val_size);
if (!elinkval) {
- pass = FALSE;
failure_mssg = "vrfy_ns_grp_c: HDmalloc of elinkval failed.";
+ return false;
}
- HDassert(elinkval);
ret = H5Lget_val(gid, linkname, elinkval, lnk_info.u.val_size,
H5P_DEFAULT);
if (ret < 0) {
- pass = FALSE;
failure_mssg = "vrfy_ns_grp_c: H5Lget_val() failed.";
+ return false;
}
- HDassert(ret >= 0);
- ret = H5Lunpack_elink_val(elinkval, lnk_info.u.val_size, NULL, &file, &path);
+ ret = H5Lunpack_elink_val(elinkval, lnk_info.u.val_size, NULL,
+ &file, &path);
if (ret < 0) {
- pass = FALSE;
failure_mssg = "vrfy_ns_grp_c: H5Lunpack_elink_val() failed.";
- }
- else if (0 != HDstrcmp(file, "external.h5")) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_c: 0 != HDstrcmp(file, \"external.h5\")";
- }
- else if (0 != HDstrcmp(path, "/ext")) {
- pass = FALSE;
+ HDfree(elinkval);
+ return false;
+ } else if (0 != HDstrcmp(file, "external.h5")) {
+ failure_mssg =
+ "vrfy_ns_grp_c: 0 != HDstrcmp(file, \"external.h5\")";
+ HDfree(elinkval);
+ return false;
+ } else if (0 != HDstrcmp(path, "/ext")) {
failure_mssg = "vrfy_ns_grp_c: 0 != HDstrcmp(path, \"/ext\")";
+ HDfree(elinkval);
+ return false;
}
- HDassert(ret >= 0);
- HDassert(0 == HDstrcmp(file, "external.h5"));
- HDassert(0 == HDstrcmp(path, "/ext"));
-
HDfree(elinkval);
- } /* end else */
-
- u++;
- } /* end while */
+ }
+ }
- if (pass) {
- ret = H5Gclose(gid);
+ ret = H5Gclose(gid);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_c: H5Gclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ns_grp_c: H5Gclose() failed.";
+ return false;
}
- return;
+ return true;
} /* vrfy_ns_grp_c() */
@@ -656,12 +613,10 @@ vrfy_ns_grp_c(hid_t fid, const char *group_name, unsigned nlinks) {
* Purpose: Create a dense "new style" group, with 'nlinks'
* (soft/hard/external) links in it in the specified file.
*
- * If pass is false on entry, do nothing.
- *
- * If an error is detected, set pass to FALSE, and set
+ * If an error is detected, return false, and set
* failure_mssg to point to an appropriate error message.
*
- * Return: void
+ * Return: true on success, false on failure.
*
* Programmer: John Mainzer
* 9/14/15
@@ -669,62 +624,62 @@ vrfy_ns_grp_c(hid_t fid, const char *group_name, unsigned nlinks) {
*-------------------------------------------------------------------------
*/
-void
-ns_grp_d(hid_t fid, const char *group_name, unsigned nlinks) {
+static bool
+missing_ns_grp_d(hid_t fid, const char *group_name,
+ unsigned H5_ATTR_UNUSED nlinks)
+{
+ return file_has_no_path(fid, group_name);
+}
+
+static bool
+rm_ns_grp_d(hid_t fid, const char *group_name, unsigned H5_ATTR_UNUSED nlinks)
+{
+ return remove_from_file_path(fid, group_name);
+}
+
+bool
+ns_grp_d(hid_t fid, const char *group_name, unsigned nlinks)
+{
hid_t gid = -1;
hid_t gcpl = -1;
unsigned max_compact;
unsigned u;
herr_t ret;
- if (pass) {
- gcpl = H5Pcreate(H5P_GROUP_CREATE);
+ gcpl = H5Pcreate(H5P_GROUP_CREATE);
- if (gcpl <= 0) {
- pass = FALSE;
- failure_mssg = "ns_grp_d: H5Pcreate() failed.";
- }
- HDassert(gcpl > 0);
+ if (gcpl <= 0) {
+ failure_mssg = "ns_grp_d: H5Pcreate() failed.";
+ return false;
}
- if (pass) {
- ret = H5Pset_link_creation_order(gcpl, H5P_CRT_ORDER_TRACKED);
+ ret = H5Pset_link_creation_order(gcpl, H5P_CRT_ORDER_TRACKED);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "ns_grp_d: H5Pset_link_creation_order() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "ns_grp_d: H5Pset_link_creation_order() failed.";
+ return false;
}
- if (pass) {
- gid = H5Gcreate2(fid, group_name, H5P_DEFAULT, gcpl, H5P_DEFAULT);
+ gid = H5Gcreate2(fid, group_name, H5P_DEFAULT, gcpl, H5P_DEFAULT);
- if (gid <= 0) {
- pass = FALSE;
- failure_mssg = "ns_grp_d: H5Gcreate2() failed.";
- }
- HDassert(gid > 0);
+ if (gid <= 0) {
+ failure_mssg = "ns_grp_d: H5Gcreate2() failed.";
+ return false;
}
- if (pass) {
- max_compact = 0;
- ret = H5Pget_link_phase_change(gcpl, &max_compact, NULL);
+ max_compact = 0;
+ ret = H5Pget_link_phase_change(gcpl, &max_compact, NULL);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "ns_grp_d: H5Pget_link_phase_change() failed.";
- }
- else if (nlinks <= max_compact) {
- pass = FALSE;
- failure_mssg = "ns_grp_d: nlinks <= max_compact";
- }
- HDassert(ret >= 0);
- HDassert(nlinks > max_compact);
+ if (ret < 0) {
+ failure_mssg = "ns_grp_d: H5Pget_link_phase_change() failed.";
+ return false;
+ }
+ else if (nlinks <= max_compact) {
+ failure_mssg = "ns_grp_d: nlinks <= max_compact";
+ return false;
}
- u = 0;
- while ((pass) && (u < nlinks)) {
+ for (u = 0; u < nlinks; u++) {
char linkname[16];
HDsprintf(linkname, "%u", u);
@@ -734,58 +689,45 @@ ns_grp_d(hid_t fid, const char *group_name, unsigned nlinks) {
H5P_DEFAULT, H5P_DEFAULT);
if (ret < 0) {
- pass = FALSE;
failure_mssg = "ns_grp_d: H5Lcreate_soft() failed.";
+ return false;
}
- HDassert(ret >= 0);
- } /* end if */
- else if (1 == (u % 3)) {
+ } else if (1 == (u % 3)) {
ret = H5Lcreate_hard(fid, "/", gid, linkname,
H5P_DEFAULT, H5P_DEFAULT);
if (ret < 0) {
- pass = FALSE;
failure_mssg = "ns_grp_d: H5Lcreate_hard() failed.";
+ return false;
}
- HDassert(ret >= 0);
- } /* end else-if */
- else {
+ } else {
HDassert(2 == (u % 3));
ret = H5Lcreate_external("external.h5", "/ext", gid, linkname,
H5P_DEFAULT, H5P_DEFAULT);
if (ret < 0) {
- pass = FALSE;
failure_mssg = "ns_grp_d: H5Lcreate_external() failed.";
+ return false;
}
- HDassert(ret >= 0);
- } /* end else */
-
- u++;
- } /* end while */
+ }
+ }
- if (pass) {
- ret = H5Pclose(gcpl);
+ ret = H5Pclose(gcpl);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "ns_grp_d: H5Pclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "ns_grp_d: H5Pclose() failed.";
+ return false;
}
- if (pass) {
- ret = H5Gclose(gid);
+ ret = H5Gclose(gid);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "ns_grp_d: H5Gclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "ns_grp_d: H5Gclose() failed.";
+ return false;
}
- return;
+ return true;
} /* ns_grp_d() */
@@ -795,12 +737,10 @@ ns_grp_d(hid_t fid, const char *group_name, unsigned nlinks) {
* Purpose: Verify a dense "new style" group, with 'nlinks'
* soft/hard/external links in it in the specified file.
*
- * If pass is false on entry, do nothing.
- *
- * If an error is detected, set pass to FALSE, and set
+ * If an error is detected, return false, and set
* failure_mssg to point to an appropriate error message.
*
- * Return: void
+ * Return: true on success, false on failure.
*
* Programmer: John Mainzer
* 9/14/15
@@ -809,8 +749,9 @@ ns_grp_d(hid_t fid, const char *group_name, unsigned nlinks) {
*/
-void
-vrfy_ns_grp_d(hid_t fid, const char *group_name, unsigned nlinks) {
+bool
+vrfy_ns_grp_d(hid_t fid, const char *group_name, unsigned nlinks)
+{
hid_t gid = -1;
hid_t gcpl = -1;
H5G_info_t grp_info;
@@ -818,84 +759,59 @@ vrfy_ns_grp_d(hid_t fid, const char *group_name, unsigned nlinks) {
unsigned u;
herr_t ret;
- if (pass) {
- gid = H5Gopen2(fid, group_name, H5P_DEFAULT);
+ gid = H5Gopen2(fid, group_name, H5P_DEFAULT);
- if (gid <= 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_d: H5Gopen2() failed.";
- }
- HDassert(gid > 0);
+ if (gid <= 0) {
+ failure_mssg = "vrfy_ns_grp_d: H5Gopen2() failed.";
+ return false;
}
- if (pass) {
- gcpl = H5Gget_create_plist(gid);
+ gcpl = H5Gget_create_plist(gid);
- if (gcpl <= 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_d: H5Gget_create_plist() failed.";
- }
- HDassert(gcpl > 0);
+ if (gcpl <= 0) {
+ failure_mssg = "vrfy_ns_grp_d: H5Gget_create_plist() failed.";
+ return false;
}
- if (pass) {
- ret = H5Pget_link_creation_order(gcpl, &crt_order_flags);
+ ret = H5Pget_link_creation_order(gcpl, &crt_order_flags);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_d: H5Pget_link_creation_order() failed.";
- }
- else if (H5P_CRT_ORDER_TRACKED != crt_order_flags) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_d: H5P_CRT_ORDER_TRACKED != crt_order_flags";
- }
- HDassert(ret >= 0);
- HDassert(H5P_CRT_ORDER_TRACKED == crt_order_flags);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ns_grp_d: H5Pget_link_creation_order() failed.";
+ return false;
+ } else if (H5P_CRT_ORDER_TRACKED != crt_order_flags) {
+ failure_mssg =
+ "vrfy_ns_grp_d: H5P_CRT_ORDER_TRACKED != crt_order_flags";
+ return false;
}
- if (pass) {
- ret = H5Pclose(gcpl);
+ ret = H5Pclose(gcpl);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_d: H5Pclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ns_grp_d: H5Pclose() failed.";
+ return false;
}
- if (pass) {
- HDmemset(&grp_info, 0, sizeof(grp_info));
- ret = H5Gget_info(gid, &grp_info);
+ HDmemset(&grp_info, 0, sizeof(grp_info));
+ ret = H5Gget_info(gid, &grp_info);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_d: H5Gget_info() failed.";
- }
- else if (H5G_STORAGE_TYPE_DENSE != grp_info.storage_type) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_d: H5G_STORAGE_TYPE_DENSE != grp_info.storage_type";
- }
- else if (nlinks != grp_info.nlinks) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_d: nlinks != grp_info.nlinks";
- }
- else if (nlinks != grp_info.max_corder) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_d: nlinks != grp_info.max_corder";
- }
- else if ( FALSE != grp_info.mounted) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_d: FALSE != grp_info.mounted";
- }
- HDassert(ret >= 0);
- HDassert(H5G_STORAGE_TYPE_DENSE == grp_info.storage_type);
- HDassert(nlinks == grp_info.nlinks);
- HDassert(nlinks == grp_info.max_corder);
- HDassert(false == grp_info.mounted);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ns_grp_d: H5Gget_info() failed.";
+ return false;
+ } else if (H5G_STORAGE_TYPE_DENSE != grp_info.storage_type) {
+ failure_mssg = "vrfy_ns_grp_d: H5G_STORAGE_TYPE_DENSE != grp_info.storage_type";
+ return false;
+ } else if (nlinks != grp_info.nlinks) {
+ failure_mssg = "vrfy_ns_grp_d: nlinks != grp_info.nlinks";
+ return false;
+ } else if (nlinks != grp_info.max_corder) {
+ failure_mssg = "vrfy_ns_grp_d: nlinks != grp_info.max_corder";
+ return false;
+ } else if ( FALSE != grp_info.mounted) {
+ failure_mssg = "vrfy_ns_grp_d: FALSE != grp_info.mounted";
+ return false;
}
- u = 0;
- while ((pass) && (u < nlinks)) {
+ for (u = 0; u < nlinks; u++) {
H5L_info2_t lnk_info;
char linkname[16];
htri_t link_exists;
@@ -904,103 +820,80 @@ vrfy_ns_grp_d(hid_t fid, const char *group_name, unsigned nlinks) {
link_exists = H5Lexists(gid, linkname, H5P_DEFAULT);
if (link_exists < 0) {
- pass = FALSE;
failure_mssg = "vrfy_ns_grp_d: H5Lexists() failed.";
+ return false;
}
- HDassert(link_exists >= 0);
HDmemset(&lnk_info, 0, sizeof(grp_info));
ret = H5Lget_info2(gid, linkname, &lnk_info, H5P_DEFAULT);
if (ret < 0) {
- pass = FALSE;
failure_mssg = "vrfy_ns_grp_d: H5Lget_info() failed.";
- }
- else if (TRUE != lnk_info.corder_valid) {
- pass = FALSE;
+ return false;
+ } else if (TRUE != lnk_info.corder_valid) {
failure_mssg = "vrfy_ns_grp_d: TRUE != lnk_info.corder_valid";
- }
- else if (u != lnk_info.corder) {
- pass = FALSE;
+ return false;
+ } else if (u != lnk_info.corder) {
failure_mssg = "vrfy_ns_grp_d: u != lnk_info.corder";
- }
- else if (H5T_CSET_ASCII != lnk_info.cset) {
- pass = FALSE;
+ return false;
+ } else if (H5T_CSET_ASCII != lnk_info.cset) {
failure_mssg = "vrfy_ns_grp_d: H5T_CSET_ASCII != lnk_info.cset";
+ return false;
}
- HDassert(ret >= 0);
- HDassert(true == lnk_info.corder_valid);
- HDassert(u == lnk_info.corder);
- HDassert(H5T_CSET_ASCII == lnk_info.cset);
if (0 == (u % 3)) {
char *slinkval;
if (H5L_TYPE_SOFT != lnk_info.type) {
- pass = FALSE;
failure_mssg = "vrfy_ns_grp_d: H5L_TYPE_SOFT != lnk_info.type";
+ return false;
}
else if ((HDstrlen(group_name) + 1) != lnk_info.u.val_size) {
- pass = FALSE;
failure_mssg = "vrfy_ns_grp_d: H5L_TYPE_SOFT != lnk_info.type";
+ return false;
}
- HDassert(H5L_TYPE_SOFT == lnk_info.type);
- HDassert((HDstrlen(group_name) + 1) == lnk_info.u.val_size);
- slinkval = (char *) HDmalloc(lnk_info.u.val_size);
+ slinkval = HDmalloc(lnk_info.u.val_size);
if (!slinkval) {
- pass = FALSE;
failure_mssg = "vrfy_ns_grp_d: HDmalloc of slinkval failed";
+ return false;
}
- HDassert(slinkval);
ret = H5Lget_val(gid, linkname, slinkval, lnk_info.u.val_size,
- H5P_DEFAULT);
+ H5P_DEFAULT);
if (ret < 0) {
- pass = FALSE;
failure_mssg = "vrfy_ns_grp_d: H5Lget_val() failed";
- }
- else if (0 != HDstrcmp(slinkval, group_name)) {
- pass = FALSE;
+ HDfree(slinkval);
+ return false;
+ } else if (0 != HDstrcmp(slinkval, group_name)) {
failure_mssg = "vrfy_ns_grp_d: 0 != HDstrcmp(slinkval, group_name)";
+ HDfree(slinkval);
+ return false;
}
- HDassert(ret >= 0);
- HDassert(0 == HDstrcmp(slinkval, group_name));
-
HDfree(slinkval);
- } /* end if */
- else if (1 == (u % 3)) {
+ } else if (1 == (u % 3)) {
H5O_info2_t root_oinfo;
int token_cmp = 0;
if (H5L_TYPE_HARD != lnk_info.type) {
- pass = FALSE;
failure_mssg = "vrfy_ns_grp_d: H5L_TYPE_HARD != lnk_info.type";
+ return false;
}
- HDassert(H5L_TYPE_HARD == lnk_info.type);
HDmemset(&root_oinfo, 0, sizeof(root_oinfo));
ret = H5Oget_info3(fid, &root_oinfo, H5O_INFO_BASIC);
if (ret < 0) {
- pass = FALSE;
failure_mssg = "vrfy_ns_grp_d: H5Oget_info() failed.";
+ return false;
+ } else if(H5Otoken_cmp(fid, &root_oinfo.token, &lnk_info.u.token, &token_cmp) < 0) {
+ failure_mssg = "vrfy_ns_grp_d: H5Otoken_cmp() failed.";
+ return false;
+ } else if (token_cmp) {
+ failure_mssg = "vrfy_ns_grp_d: root_oinfo.token != lnk_info.u.token";
+ return false;
}
- else {
- if(H5Otoken_cmp(fid, &root_oinfo.token, &lnk_info.u.token, &token_cmp) < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_d: H5Otoken_cmp() failed.";
- }
-
- if (token_cmp) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_d: root_oinfo.token != lnk_info.u.token";
- }
- }
- HDassert(ret >= 0);
- HDassert(!token_cmp);
- } /* end else-if */
- else {
+ } else {
void *elinkval;
const char *file = NULL;
const char *path = NULL;
@@ -1008,61 +901,53 @@ vrfy_ns_grp_d(hid_t fid, const char *group_name, unsigned nlinks) {
HDassert(2 == (u % 3));
if (H5L_TYPE_EXTERNAL != lnk_info.type) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_d: H5L_TYPE_EXTERNAL != lnk_info.type";
+ failure_mssg =
+ "vrfy_ns_grp_d: H5L_TYPE_EXTERNAL != lnk_info.type";
+ return false;
}
- HDassert(H5L_TYPE_EXTERNAL == lnk_info.type);
elinkval = HDmalloc(lnk_info.u.val_size);
if (!elinkval) {
- pass = FALSE;
failure_mssg = "vrfy_ns_grp_d: HDmalloc of elinkval failed.";
+ return false;
}
- HDassert(elinkval);
ret = H5Lget_val(gid, linkname, elinkval, lnk_info.u.val_size,
- H5P_DEFAULT);
+ H5P_DEFAULT);
if (ret < 0) {
- pass = FALSE;
failure_mssg = "vrfy_ns_grp_d: H5Lget_val failed.";
+ return false;
}
- HDassert(ret >= 0);
- ret = H5Lunpack_elink_val(elinkval, lnk_info.u.val_size, NULL, &file, &path);
+ ret = H5Lunpack_elink_val(elinkval, lnk_info.u.val_size, NULL,
+ &file, &path);
if (ret < 0) {
- pass = FALSE;
failure_mssg = "vrfy_ns_grp_d: H5Lunpack_elink_val failed.";
- }
- else if (0 != HDstrcmp(file, "external.h5")) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_d: 0 != HDstrcmp(file, \"external.h5\").";
- }
- else if (0 != HDstrcmp(path, "/ext")) {
- pass = FALSE;
+ HDfree(elinkval);
+ return false;
+ } else if (0 != HDstrcmp(file, "external.h5")) {
+ failure_mssg =
+ "vrfy_ns_grp_d: 0 != HDstrcmp(file, \"external.h5\").";
+ HDfree(elinkval);
+ return false;
+ } else if (0 != HDstrcmp(path, "/ext")) {
failure_mssg = "vrfy_ns_grp_d: 0 != HDstrcmp(path, \"/ext\")";
+ HDfree(elinkval);
+ return false;
}
- HDassert(ret >= 0);
- HDassert(0 == HDstrcmp(file, "external.h5"));
- HDassert(0 == HDstrcmp(path, "/ext"));
-
HDfree(elinkval);
- } /* end else */
-
- u++;
- } /* end while() */
+ }
+ }
- if (pass) {
- ret = H5Gclose(gid);
+ ret = H5Gclose(gid);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ns_grp_d: H5Gclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ns_grp_d: H5Gclose() failed.";
+ return false;
}
- return;
+ return true;
} /* vrfy_ns_grp_d() */
@@ -1072,12 +957,10 @@ vrfy_ns_grp_d(hid_t fid, const char *group_name, unsigned nlinks) {
*
* Purpose: Create an empty "old style" group.
*
- * If pass is false on entry, do nothing.
- *
- * If an error is detected, set pass to FALSE, and set
+ * If an error is detected, return false, and set
* failure_mssg to point to an appropriate error message.
*
- * Return: void
+ * Return: true on success, false on failure.
*
* Programmer: John Mainzer
* 9/14/15
@@ -1085,7 +968,19 @@ vrfy_ns_grp_d(hid_t fid, const char *group_name, unsigned nlinks) {
*-------------------------------------------------------------------------
*/
-void
+static bool
+missing_os_grp_0(hid_t fid, const char *group_name)
+{
+ return file_has_no_path(fid, group_name);
+}
+
+static bool
+rm_os_grp_0(hid_t fid, const char *group_name)
+{
+ return remove_from_file_path(fid, group_name);
+}
+
+bool
os_grp_0(hid_t fid, const char *group_name)
{
hid_t gid = -1;
@@ -1094,66 +989,52 @@ os_grp_0(hid_t fid, const char *group_name)
herr_t ret;
- if ( pass ) { /* get the file's file access property list */
- fapl = H5Fget_access_plist(fid);
- if ( fapl <= 0 ) {
- pass = FALSE;
- failure_mssg = "os_grp_0: H5Fget_access_plist() failed.";
- }
- HDassert(fapl > 0);
+ /* get the file's file access property list */
+ fapl = H5Fget_access_plist(fid);
+ if ( fapl <= 0 ) {
+ failure_mssg = "os_grp_0: H5Fget_access_plist() failed.";
+ return false;
}
- if ( pass ) { /* get low and high bounds from fapl */
- ret = H5Pget_libver_bounds(fapl, &low, &high);
- if ( ret < 0 ) {
- pass = FALSE;
- failure_mssg = "os_grp_0: H5Pget_libver_bounds() failed(1).";
- }
- HDassert(ret >= 0);
+ /* get low and high bounds from fapl */
+ ret = H5Pget_libver_bounds(fapl, &low, &high);
+ if ( ret < 0 ) {
+ failure_mssg = "os_grp_0: H5Pget_libver_bounds() failed(1).";
+ return false;
}
- if ( pass ) { /* turn file format latest off */
- if(low >= H5F_LIBVER_V18) {
- ret = H5Fset_libver_bounds(fid, H5F_LIBVER_EARLIEST, high);
- if ( ret < 0 ) {
- pass = FALSE;
- failure_mssg = "os_grp_0: H5Fset_libver_bounds() failed(1).";
- }
- HDassert(ret >= 0);
+ /* turn file format latest off */
+ if(low >= H5F_LIBVER_V18) {
+ ret = H5Fset_libver_bounds(fid, H5F_LIBVER_EARLIEST, high);
+ if ( ret < 0 ) {
+ failure_mssg = "os_grp_0: H5Fset_libver_bounds() failed(1).";
+ return false;
}
}
- if ( pass ) {
- gid = H5Gcreate2(fid, group_name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
- if ( gid <= 0 ) {
- pass = FALSE;
- failure_mssg = "os_grp_0: H5Gcreate2() failed.";
- }
- HDassert(gid > 0);
+ gid = H5Gcreate2(fid, group_name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+ if ( gid <= 0 ) {
+ failure_mssg = "os_grp_0: H5Gcreate2() failed.";
+ return false;
}
- if ( pass ) {
- ret = H5Gclose(gid);
+ ret = H5Gclose(gid);
- if ( ret < 0 ) {
- pass = FALSE;
- failure_mssg = "os_grp_0: H5Gclose() failed.";
- }
- HDassert(ret >= 0);
+ if ( ret < 0 ) {
+ failure_mssg = "os_grp_0: H5Gclose() failed.";
+ return false;
}
- if ( pass ) { /* restore low and high bounds */
- if(low >= H5F_LIBVER_V18) {
- ret = H5Fset_libver_bounds(fid, low, high);
- if ( ret < 0 ) {
- pass = FALSE;
- failure_mssg = "os_grp_0: H5Fset_libver_bounds() failed(1).";
- }
- HDassert(ret >= 0);
+ /* restore low and high bounds */
+ if(low >= H5F_LIBVER_V18) {
+ ret = H5Fset_libver_bounds(fid, low, high);
+ if ( ret < 0 ) {
+ failure_mssg = "os_grp_0: H5Fset_libver_bounds() failed(1).";
+ return false;
}
}
- return;
+ return true;
} /* os_grp_0() */
@@ -1162,12 +1043,10 @@ os_grp_0(hid_t fid, const char *group_name)
*
* Purpose: Validate an empty "old style" group.
*
- * If pass is false on entry, do nothing.
- *
- * If an error is detected, set pass to FALSE, and set
+ * If an error is detected, return false, and set
* failure_mssg to point to an appropriate error message.
*
- * Return: void
+ * Return: true on success, false on failure.
*
* Programmer: John Mainzer
* 9/14/15
@@ -1175,102 +1054,74 @@ os_grp_0(hid_t fid, const char *group_name)
*-------------------------------------------------------------------------
*/
-void
-vrfy_os_grp_0(hid_t fid, const char *group_name) {
+bool
+vrfy_os_grp_0(hid_t fid, const char *group_name)
+{
hid_t gid = -1;
hid_t gcpl = -1;
H5G_info_t grp_info;
unsigned crt_order_flags = 0;
herr_t ret;
- if (pass) {
- gid = H5Gopen2(fid, group_name, H5P_DEFAULT);
+ gid = H5Gopen2(fid, group_name, H5P_DEFAULT);
- if (gid <= 0) {
- pass = FALSE;
- failure_mssg = "vrfy_os_grp_0: H5Gopen2() failed.";
- }
- HDassert(gid > 0);
+ if (gid <= 0) {
+ failure_mssg = "vrfy_os_grp_0: H5Gopen2() failed.";
+ return false;
}
- if (pass) {
- gcpl = H5Gget_create_plist(gid);
+ gcpl = H5Gget_create_plist(gid);
- if (gcpl <= 0) {
- pass = FALSE;
- failure_mssg = "vrfy_os_grp_0: H5Gget_create_plist() failed.";
- }
- HDassert(gcpl > 0);
+ if (gcpl <= 0) {
+ failure_mssg = "vrfy_os_grp_0: H5Gget_create_plist() failed.";
+ return false;
}
- if (pass) {
-
- ret = H5Pget_link_creation_order(gcpl, &crt_order_flags);
+ ret = H5Pget_link_creation_order(gcpl, &crt_order_flags);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_os_grp_0: H5Pget_link_creation_order() failed";
- }
- else if (0 != crt_order_flags) {
- pass = FALSE;
- failure_mssg = "vrfy_os_grp_0: 0 != crt_order_flags";
- }
- HDassert(ret >= 0);
- HDassert(0 == crt_order_flags);
+ if (ret < 0) {
+ failure_mssg = "vrfy_os_grp_0: H5Pget_link_creation_order() failed";
+ return false;
+ } else if (0 != crt_order_flags) {
+ failure_mssg = "vrfy_os_grp_0: 0 != crt_order_flags";
+ return false;
}
- if (pass) {
- ret = H5Pclose(gcpl);
+ ret = H5Pclose(gcpl);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_os_grp_0: H5Pclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "vrfy_os_grp_0: H5Pclose() failed.";
+ return false;
}
- if (pass) {
- HDmemset(&grp_info, 0, sizeof(grp_info));
- ret = H5Gget_info(gid, &grp_info);
+ HDmemset(&grp_info, 0, sizeof(grp_info));
+ ret = H5Gget_info(gid, &grp_info);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_os_grp_0: H5Gget_info() failed.";
- }
- else if (H5G_STORAGE_TYPE_SYMBOL_TABLE != grp_info.storage_type) {
- pass = FALSE;
- failure_mssg = "vrfy_os_grp_0: H5G_STORAGE_TYPE_SYMBOL_TABLE != grp_info.storage_type";
- }
- else if (0 != grp_info.nlinks) {
- pass = FALSE;
- failure_mssg = "vrfy_os_grp_0: 0 != grp_info.nlinks";
- }
- else if (0 != grp_info.max_corder) {
- pass = FALSE;
- failure_mssg = "vrfy_os_grp_0: 0 != grp_info.max_corder";
- }
- else if ( FALSE != grp_info.mounted) {
- pass = FALSE;
- failure_mssg = "vrfy_os_grp_0: FALSE != grp_info.mounted";
- }
- HDassert(ret >= 0);
- HDassert(H5G_STORAGE_TYPE_SYMBOL_TABLE == grp_info.storage_type);
- HDassert(0 == grp_info.nlinks);
- HDassert(0 == grp_info.max_corder);
- HDassert(false == grp_info.mounted);
+ if (ret < 0) {
+ failure_mssg = "vrfy_os_grp_0: H5Gget_info() failed.";
+ return false;
+ } else if (H5G_STORAGE_TYPE_SYMBOL_TABLE != grp_info.storage_type) {
+ failure_mssg = "vrfy_os_grp_0: H5G_STORAGE_TYPE_SYMBOL_TABLE != grp_info.storage_type";
+ return false;
+ } else if (0 != grp_info.nlinks) {
+ failure_mssg = "vrfy_os_grp_0: 0 != grp_info.nlinks";
+ return false;
+ } else if (0 != grp_info.max_corder) {
+ failure_mssg = "vrfy_os_grp_0: 0 != grp_info.max_corder";
+ return false;
+ } else if ( FALSE != grp_info.mounted) {
+ failure_mssg = "vrfy_os_grp_0: FALSE != grp_info.mounted";
+ return false;
}
- if (pass) {
- ret = H5Gclose(gid);
+ ret = H5Gclose(gid);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_os_grp_0: H5Gclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "vrfy_os_grp_0: H5Gclose() failed.";
+ return false;
}
- return;
+ return true;
} /* vrfy_os_grp_0() */
@@ -1280,12 +1131,10 @@ vrfy_os_grp_0(hid_t fid, const char *group_name) {
* Purpose: Create an "old style" group, with 'nlinks' soft/hard
* links in it.
*
- * If pass is false on entry, do nothing.
- *
- * If an error is detected, set pass to FALSE, and set
+ * If an error is detected, return false, and set
* failure_mssg to point to an appropriate error message.
*
- * Return: void
+ * Return: true on success, false on failure.
*
* Programmer: John Mainzer
* 9/14/15
@@ -1293,7 +1142,21 @@ vrfy_os_grp_0(hid_t fid, const char *group_name) {
*-------------------------------------------------------------------------
*/
-void
+static bool
+missing_os_grp_n(hid_t fid, const char *group_name, int H5_ATTR_UNUSED proc_num,
+ unsigned H5_ATTR_UNUSED nlinks)
+{
+ return file_has_no_path(fid, group_name);
+}
+
+static bool
+rm_os_grp_n(hid_t fid, const char *group_name, int H5_ATTR_UNUSED proc_num,
+ unsigned H5_ATTR_UNUSED nlinks)
+{
+ return remove_from_file_path(fid, group_name);
+}
+
+bool
os_grp_n(hid_t fid, const char *group_name, int proc_num, unsigned nlinks)
{
hid_t gid = -1;
@@ -1302,48 +1165,38 @@ os_grp_n(hid_t fid, const char *group_name, int proc_num, unsigned nlinks)
H5F_libver_t low, high;
herr_t ret;
- if ( pass ) { /* get the file's file access property list */
- fapl = H5Fget_access_plist(fid);
- if ( fapl <= 0 ) {
- pass = FALSE;
- failure_mssg = "os_grp_n: H5Fget_access_plist() failed.";
- }
- HDassert(fapl > 0);
+ /* get the file's file access property list */
+ fapl = H5Fget_access_plist(fid);
+ if ( fapl <= 0 ) {
+ failure_mssg = "os_grp_n: H5Fget_access_plist() failed.";
+ return false;
}
- if ( pass ) { /* get low and high bounds from fapl */
- ret = H5Pget_libver_bounds(fapl, &low, &high);
- if ( ret < 0 ) {
- pass = FALSE;
- failure_mssg = "os_grp_0: H5Pget_libver_bounds() failed(1).";
- }
- HDassert(ret >= 0);
+ /* get low and high bounds from fapl */
+ ret = H5Pget_libver_bounds(fapl, &low, &high);
+ if ( ret < 0 ) {
+ failure_mssg = "os_grp_0: H5Pget_libver_bounds() failed(1).";
+ return false;
}
- if ( pass ) { /* turn file format latest off */
- if(low >= H5F_LIBVER_V18) {
- ret = H5Fset_libver_bounds(fid, H5F_LIBVER_EARLIEST, high);
- if ( ret < 0 ) {
- pass = FALSE;
- failure_mssg = "os_grp_0: H5Fset_libver_bounds() failed(1).";
- }
- HDassert(ret >= 0);
+ /* turn file format latest off */
+ if(low >= H5F_LIBVER_V18) {
+ ret = H5Fset_libver_bounds(fid, H5F_LIBVER_EARLIEST, high);
+ if ( ret < 0 ) {
+ failure_mssg = "os_grp_0: H5Fset_libver_bounds() failed(1).";
+ return false;
}
}
- if ( pass ) {
- gid = H5Gcreate2(fid, group_name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
- if ( gid <= 0 ) {
- pass = FALSE;
- failure_mssg = "os_grp_n: H5Gcreate2() failed.";
- }
- HDassert(gid > 0);
+ gid = H5Gcreate2(fid, group_name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+ if ( gid <= 0 ) {
+ failure_mssg = "os_grp_n: H5Gcreate2() failed.";
+ return false;
}
HDassert(nlinks > 0);
- u = 0;
- while ( ( pass ) && ( u < nlinks ) ) {
+ for (u = 0; u < nlinks; u++) {
char linkname[32];
HDsprintf(linkname, "ln%d_%u", proc_num, u);
@@ -1351,47 +1204,37 @@ os_grp_n(hid_t fid, const char *group_name, int proc_num, unsigned nlinks)
if(0 == (u % 2)) {
ret = H5Lcreate_soft(group_name, gid, linkname, H5P_DEFAULT, H5P_DEFAULT);
if ( ret < 0 ) {
- pass = FALSE;
failure_mssg = "os_grp_n: H5Lcreate_soft() failed.";
+ return false;
}
- HDassert(ret >= 0);
- } /* end if */
- else {
+ } else {
HDassert(1 == (u % 2));
ret = H5Lcreate_hard(fid, "/", gid, linkname, H5P_DEFAULT, H5P_DEFAULT);
if ( ret < 0 ) {
- pass = FALSE;
failure_mssg = "os_grp_n: H5Lcreate_hard() failed.";
+ return false;
}
- HDassert(ret >= 0);
- } /* end else */
-
- u++;
- } /* end while */
+ }
+ }
- if ( pass ) {
- ret = H5Gclose(gid);
+ ret = H5Gclose(gid);
- if ( ret < 0 ) {
- pass = FALSE;
- failure_mssg = "os_grp_n: H5Gclose() failed.";
- }
- HDassert(ret >= 0);
+ if ( ret < 0 ) {
+ failure_mssg = "os_grp_n: H5Gclose() failed.";
+ return false;
}
- if ( pass ) { /* restore low and high bounds */
- if(low >= H5F_LIBVER_V18) {
- ret = H5Fset_libver_bounds(fid, low, high);
- if ( ret < 0 ) {
- pass = FALSE;
- failure_mssg = "os_grp_n: H5Fset_libver_bounds() failed(2).";
- }
- HDassert(ret >= 0);
+ /* restore low and high bounds */
+ if(low >= H5F_LIBVER_V18) {
+ ret = H5Fset_libver_bounds(fid, low, high);
+ if ( ret < 0 ) {
+ failure_mssg = "os_grp_n: H5Fset_libver_bounds() failed(2).";
+ return false;
}
}
- return;
+ return true;
} /* os_grp_n() */
@@ -1401,21 +1244,19 @@ os_grp_n(hid_t fid, const char *group_name, int proc_num, unsigned nlinks)
* Purpose: Validate an "old style" group with 'nlinks' soft/hard
* links in it.
*
- * If pass is false on entry, do nothing.
- *
- * If an error is detected, set pass to FALSE, and set
+ * If an error is detected, return false, and set
* failure_mssg to point to an appropriate error message.
*
- * Return: void
+ * Return: true on success, false on failure.
*
* Programmer: John Mainzer
* 9/14/15
*
*-------------------------------------------------------------------------
*/
-void
-vrfy_os_grp_n(hid_t fid, const char *group_name, int proc_num,
- unsigned nlinks) {
+bool
+vrfy_os_grp_n(hid_t fid, const char *group_name, int proc_num, unsigned nlinks)
+{
hid_t gid = -1;
hid_t gcpl = -1;
H5G_info_t grp_info;
@@ -1423,85 +1264,59 @@ vrfy_os_grp_n(hid_t fid, const char *group_name, int proc_num,
unsigned u;
herr_t ret;
- if (pass) {
- gid = H5Gopen2(fid, group_name, H5P_DEFAULT);
+ gid = H5Gopen2(fid, group_name, H5P_DEFAULT);
- if (gid <= 0) {
- pass = FALSE;
- failure_mssg = "vrfy_os_grp_n: H5Gopen2() failed";
- }
- HDassert(gid > 0);
+ if (gid <= 0) {
+ failure_mssg = "vrfy_os_grp_n: H5Gopen2() failed";
+ return false;
}
- if (pass) {
- gcpl = H5Gget_create_plist(gid);
+ gcpl = H5Gget_create_plist(gid);
- if (gcpl <= 0) {
- pass = FALSE;
- failure_mssg = "vrfy_os_grp_n: H5Gget_create_plist() failed";
- }
- HDassert(gcpl > 0);
+ if (gcpl <= 0) {
+ failure_mssg = "vrfy_os_grp_n: H5Gget_create_plist() failed";
+ return false;
}
- if (pass) {
- ret = H5Pget_link_creation_order(gcpl, &crt_order_flags);
+ ret = H5Pget_link_creation_order(gcpl, &crt_order_flags);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_os_grp_n: H5Pget_link_creation_order";
- }
- else if (0 != crt_order_flags) {
- pass = FALSE;
- failure_mssg = "vrfy_os_grp_n: 0 != crt_order_flags";
- }
- HDassert(ret >= 0);
- HDassert(0 == crt_order_flags);
+ if (ret < 0) {
+ failure_mssg = "vrfy_os_grp_n: H5Pget_link_creation_order";
+ return false;
+ } else if (0 != crt_order_flags) {
+ failure_mssg = "vrfy_os_grp_n: 0 != crt_order_flags";
+ return false;
}
- if (pass) {
- ret = H5Pclose(gcpl);
+ ret = H5Pclose(gcpl);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_os_grp_n: H5Pclose() failed";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "vrfy_os_grp_n: H5Pclose() failed";
+ return false;
}
- if (pass) {
- HDmemset(&grp_info, 0, sizeof(grp_info));
+ HDmemset(&grp_info, 0, sizeof(grp_info));
- ret = H5Gget_info(gid, &grp_info);
+ ret = H5Gget_info(gid, &grp_info);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_os_grp_n: H5Gget_info() failed";
- }
- else if (H5G_STORAGE_TYPE_SYMBOL_TABLE != grp_info.storage_type) {
- pass = FALSE;
- failure_mssg = "vrfy_os_grp_n: H5G_STORAGE_TYPE_SYMBOL_TABLE != grp_info.storage_type";
- }
- else if (nlinks != grp_info.nlinks) {
- pass = FALSE;
- failure_mssg = "vrfy_os_grp_n: nlinks != grp_info.nlinks";
- }
- else if (0 != grp_info.max_corder) {
- pass = FALSE;
- failure_mssg = "vrfy_os_grp_n: 0 != grp_info.max_corder";
- }
- else if ( FALSE != grp_info.mounted) {
- pass = FALSE;
- failure_mssg = "vrfy_os_grp_n: FALSE != grp_info.mounted";
- }
- HDassert(ret >= 0);
- HDassert(H5G_STORAGE_TYPE_SYMBOL_TABLE == grp_info.storage_type);
- HDassert(nlinks == grp_info.nlinks);
- HDassert(0 == grp_info.max_corder);
- HDassert(false == grp_info.mounted);
+ if (ret < 0) {
+ failure_mssg = "vrfy_os_grp_n: H5Gget_info() failed";
+ return false;
+ } else if (H5G_STORAGE_TYPE_SYMBOL_TABLE != grp_info.storage_type) {
+ failure_mssg = "vrfy_os_grp_n: H5G_STORAGE_TYPE_SYMBOL_TABLE != grp_info.storage_type";
+ return false;
+ } else if (nlinks != grp_info.nlinks) {
+ failure_mssg = "vrfy_os_grp_n: nlinks != grp_info.nlinks";
+ return false;
+ } else if (0 != grp_info.max_corder) {
+ failure_mssg = "vrfy_os_grp_n: 0 != grp_info.max_corder";
+ return false;
+ } else if ( FALSE != grp_info.mounted) {
+ failure_mssg = "vrfy_os_grp_n: FALSE != grp_info.mounted";
+ return false;
}
- u = 0;
- while ((pass) && (u < nlinks)) {
+ for (u = 0; u < nlinks; u++) {
H5L_info2_t lnk_info;
char linkname[32];
htri_t link_exists;
@@ -1510,8 +1325,8 @@ vrfy_os_grp_n(hid_t fid, const char *group_name, int proc_num,
link_exists = H5Lexists(gid, linkname, H5P_DEFAULT);
if (link_exists < 0) {
- pass = FALSE;
failure_mssg = "vrfy_os_grp_n: H5Lexists() failed";
+ return false;
}
HDassert(link_exists >= 0);
@@ -1519,107 +1334,84 @@ vrfy_os_grp_n(hid_t fid, const char *group_name, int proc_num,
ret = H5Lget_info2(gid, linkname, &lnk_info, H5P_DEFAULT);
if (ret < 0) {
- pass = FALSE;
failure_mssg = "vrfy_os_grp_n: H5Lget_info() failed";
+ return false;
}
else if ( FALSE != lnk_info.corder_valid) {
- pass = FALSE;
failure_mssg = "vrfy_os_grp_n: FALSE != lnk_info.corder_valid";
+ return false;
}
else if (H5T_CSET_ASCII != lnk_info.cset) {
- pass = FALSE;
failure_mssg = "vrfy_os_grp_n: H5T_CSET_ASCII != lnk_info.cset";
+ return false;
}
- HDassert(ret >= 0);
- HDassert(false == lnk_info.corder_valid);
- HDassert(H5T_CSET_ASCII == lnk_info.cset);
if (0 == (u % 2)) {
char *slinkval;
if (H5L_TYPE_SOFT != lnk_info.type) {
- pass = FALSE;
failure_mssg = "vrfy_os_grp_n: H5L_TYPE_SOFT != lnk_info.type";
- }
- else if ((HDstrlen(group_name) + 1) != lnk_info.u.val_size) {
- pass = FALSE;
+ return false;
+ } else if ((HDstrlen(group_name) + 1) != lnk_info.u.val_size) {
failure_mssg = "vrfy_os_grp_n: (HDstrlen(group_name) + 1) != lnk_info.u.val_size";
+ return false;
}
- HDassert(H5L_TYPE_SOFT == lnk_info.type);
- HDassert((HDstrlen(group_name) + 1) == lnk_info.u.val_size);
- slinkval = (char *) HDmalloc(lnk_info.u.val_size);
+ slinkval = HDmalloc(lnk_info.u.val_size);
if (!slinkval) {
- pass = FALSE;
failure_mssg = "vrfy_os_grp_n: HDmalloc of slinkval failed";
+ return false;
}
- HDassert(slinkval);
ret = H5Lget_val(gid, linkname, slinkval, lnk_info.u.val_size,
- H5P_DEFAULT);
+ H5P_DEFAULT);
if (ret < 0) {
- pass = FALSE;
failure_mssg = "vrfy_os_grp_n: H5Lget_val() failed";
- }
- else if (0 != HDstrcmp(slinkval, group_name)) {
- pass = FALSE;
+ HDfree(slinkval);
+ return false;
+ } else if (0 != HDstrcmp(slinkval, group_name)) {
failure_mssg = "vrfy_os_grp_n: 0 != HDstrcmp(slinkval, group_name)";
+ HDfree(slinkval);
+ return false;
}
- HDassert(ret >= 0);
- HDassert(0 == HDstrcmp(slinkval, group_name));
-
HDfree(slinkval);
- } /* end if */
- else {
+ } else {
H5O_info2_t root_oinfo;
int token_cmp = 0;
HDassert(1 == (u % 2));
if (H5L_TYPE_HARD != lnk_info.type) {
- pass = FALSE;
failure_mssg = "vrfy_os_grp_n: H5L_TYPE_HARD != lnk_info.type";
+ return false;
}
- HDassert(H5L_TYPE_HARD == lnk_info.type);
HDmemset(&root_oinfo, 0, sizeof(root_oinfo));
ret = H5Oget_info3(fid, &root_oinfo, H5O_INFO_BASIC);
if (ret < 0) {
- pass = FALSE;
failure_mssg = "vrfy_os_grp_n: H5Oget_info() failed.";
+ return false;
+ } else if(H5Otoken_cmp(fid, &root_oinfo.token, &lnk_info.u.token, &token_cmp) < 0) {
+ failure_mssg = "vrfy_os_grp_n: H5Otoken_cmp() failed.";
+ return false;
+ } else if (token_cmp) {
+ failure_mssg = "vrfy_os_grp_n: root_oinfo.token != lnk_info.u.token";
+ return false;
}
- else {
- if(H5Otoken_cmp(fid, &root_oinfo.token, &lnk_info.u.token, &token_cmp) < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_os_grp_n: H5Otoken_cmp() failed.";
- }
-
- if (token_cmp) {
- pass = FALSE;
- failure_mssg = "vrfy_os_grp_n: root_oinfo.token != lnk_info.u.token";
- }
- }
- HDassert(ret >= 0);
- HDassert(!token_cmp);
- } /* end else */
-
- u++;
- } /* end while */
+ }
+ }
- if (pass) {
- ret = H5Gclose(gid);
+ ret = H5Gclose(gid);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_os_grp_n: H5Gclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "vrfy_os_grp_n: H5Gclose() failed.";
+ return false;
}
- return;
+ return true;
} /* vrfy_os_grp_n() */
@@ -1630,20 +1422,32 @@ vrfy_os_grp_n(hid_t fid, const char *group_name, int proc_num,
* to the data set or not as indicated by the write_data
* parameter.
*
- * If pass is false on entry, do nothing.
- *
- * If an error is detected, set pass to FALSE, and set
+ * If an error is detected, return false, and set
* failure_mssg to point to an appropriate error message.
*
- * Return: void
+ * Return: true on success, false on failure.
*
* Programmer: John Mainzer
* 9/14/15
*
*-------------------------------------------------------------------------
*/
-void
-ds_ctg_i(hid_t fid, const char *dset_name, hbool_t write_data) {
+static bool
+missing_ds_ctg_i(hid_t fid, const char *dset_name,
+ hbool_t H5_ATTR_UNUSED write_data)
+{
+ return file_has_no_path(fid, dset_name);
+}
+
+static bool
+rm_ds_ctg_i(hid_t fid, const char *dset_name, hbool_t H5_ATTR_UNUSED write_data)
+{
+ return remove_from_file_path(fid, dset_name);
+}
+
+bool
+ds_ctg_i(hid_t fid, const char *dset_name, hbool_t write_data)
+{
int *wdata = NULL;
unsigned u;
hid_t dsid = -1;
@@ -1651,74 +1455,58 @@ ds_ctg_i(hid_t fid, const char *dset_name, hbool_t write_data) {
hsize_t dims[1] = { DSET_DIMS };
herr_t ret;
- if (pass) {
- sid = H5Screate_simple(1, dims, NULL);
+ sid = H5Screate_simple(1, dims, NULL);
- if (sid <= 0) {
- pass = FALSE;
- failure_mssg = "ds_ctg_i: H5Screate_simple() failed";
- }
- HDassert(sid > 0);
+ if (sid <= 0) {
+ failure_mssg = "ds_ctg_i: H5Screate_simple() failed";
+ return false;
}
- if (pass) {
- dsid = H5Dcreate2(fid, dset_name, H5T_NATIVE_INT, sid, H5P_DEFAULT,
- H5P_DEFAULT, H5P_DEFAULT);
+ dsid = H5Dcreate2(fid, dset_name, H5T_NATIVE_INT, sid, H5P_DEFAULT,
+ H5P_DEFAULT, H5P_DEFAULT);
- if (dsid <= 0) {
- pass = FALSE;
- failure_mssg = "ds_ctg_i: H5Dcreate2() failed";
- }
- HDassert(dsid > 0);
+ if (dsid <= 0) {
+ failure_mssg = "ds_ctg_i: H5Dcreate2() failed";
+ return false;
}
- if (pass) {
- ret = H5Sclose(sid);
+ ret = H5Sclose(sid);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "ds_ctg_i: H5Sclose() failed";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "ds_ctg_i: H5Sclose() failed";
+ return false;
}
- if ((pass) && (write_data)) {
- wdata = (int *) HDmalloc(sizeof(int) * DSET_DIMS);
+ if (write_data) {
+ wdata = HDmalloc(sizeof(int) * DSET_DIMS);
if (!wdata) {
- pass = FALSE;
failure_mssg = "ds_ctg_i: HDmalloc of wdata failed.";
+ return false;
}
- HDassert(wdata);
- }
- if ((pass) && (write_data)) {
for (u = 0; u < DSET_DIMS; u++)
wdata[u] = (int) u;
- ret = H5Dwrite(dsid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
- H5P_DEFAULT, wdata);
+ ret = H5Dwrite(dsid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT,
+ wdata);
+
+ HDfree(wdata);
if (ret < 0) {
- pass = FALSE;
failure_mssg = "ds_ctg_i: H5Dwrite() failed.";
+ return false;
}
- HDassert(ret >= 0);
-
- HDfree(wdata);
}
- if (pass) {
- ret = H5Dclose(dsid);
+ ret = H5Dclose(dsid);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "ds_ctg_i: H5Dclose() failed";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "ds_ctg_i: H5Dclose() failed";
+ return false;
}
- return;
+ return true;
} /* ds_ctg_i */
@@ -1728,20 +1516,19 @@ ds_ctg_i(hid_t fid, const char *dset_name, hbool_t write_data) {
* Purpose: Validate a contiguous datasets w/int datatypes. Validate
* data if indicated via the write_data parameter.
*
- * If pass is false on entry, do nothing.
- *
- * If an error is detected, set pass to FALSE, and set
+ * If an error is detected, return false, and set
* failure_mssg to point to an appropriate error message.
*
- * Return: void
+ * Return: true on success, false on failure.
*
* Programmer: John Mainzer
* 9/14/15
*
*-------------------------------------------------------------------------
*/
-void
-vrfy_ds_ctg_i(hid_t fid, const char *dset_name, hbool_t write_data) {
+bool
+vrfy_ds_ctg_i(hid_t fid, const char *dset_name, hbool_t write_data)
+{
int *rdata = NULL;
unsigned u;
hid_t dsid = -1;
@@ -1755,191 +1542,137 @@ vrfy_ds_ctg_i(hid_t fid, const char *dset_name, hbool_t write_data) {
htri_t type_equal;
herr_t ret;
- if (pass) {
- dsid = H5Dopen2(fid, dset_name, H5P_DEFAULT);
+ dsid = H5Dopen2(fid, dset_name, H5P_DEFAULT);
- if (dsid <= 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_i: H5Dopen2() failed.";
- }
- HDassert(dsid > 0);
+ if (dsid <= 0) {
+ failure_mssg = "vrfy_ds_ctg_i: H5Dopen2() failed.";
+ return false;
}
- if (pass) {
- sid = H5Dget_space(dsid);
+ sid = H5Dget_space(dsid);
- if (sid <= 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_i: H5Dget_space() failed.";
- }
- HDassert(sid > 0);
+ if (sid <= 0) {
+ failure_mssg = "vrfy_ds_ctg_i: H5Dget_space() failed.";
+ return false;
}
- if (pass) {
- ndims = H5Sget_simple_extent_ndims(sid);
+ ndims = H5Sget_simple_extent_ndims(sid);
- if (1 != ndims) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_i: 1 != ndims";
- }
- HDassert(1 == ndims);
+ if (1 != ndims) {
+ failure_mssg = "vrfy_ds_ctg_i: 1 != ndims";
+ return false;
}
- if (pass) {
- ret = H5Sget_simple_extent_dims(sid, dims, max_dims);
+ ret = H5Sget_simple_extent_dims(sid, dims, max_dims);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_i: H5Sget_simple_extent_dims() failed";
- }
- else if ( DSET_DIMS != dims[0]) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_i: DSET_DIMS != dims[0]";
- }
- else if ( DSET_DIMS != max_dims[0]) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_i: DSET_DIMS != max_dims[0]";
- }
- HDassert(ret >= 0);
- HDassert(DSET_DIMS == dims[0]);
- HDassert(DSET_DIMS == max_dims[0]);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ds_ctg_i: H5Sget_simple_extent_dims() failed";
+ return false;
+ } else if ( DSET_DIMS != dims[0]) {
+ failure_mssg = "vrfy_ds_ctg_i: DSET_DIMS != dims[0]";
+ return false;
+ } else if ( DSET_DIMS != max_dims[0]) {
+ failure_mssg = "vrfy_ds_ctg_i: DSET_DIMS != max_dims[0]";
+ return false;
}
- if (pass) {
- ret = H5Sclose(sid);
+ ret = H5Sclose(sid);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_i: H5Sclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ds_ctg_i: H5Sclose() failed.";
+ return false;
}
- if (pass) {
- tid = H5Dget_type(dsid);
+ tid = H5Dget_type(dsid);
- if (tid <= 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_i: H5Dget_type() failed.";
- }
- HDassert(tid > 0);
+ if (tid <= 0) {
+ failure_mssg = "vrfy_ds_ctg_i: H5Dget_type() failed.";
+ return false;
}
- if (pass) {
- type_equal = H5Tequal(tid, H5T_NATIVE_INT);
+ type_equal = H5Tequal(tid, H5T_NATIVE_INT);
- if (1 != type_equal) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_i: type not H5T_NATIVE_INT";
- }
- HDassert(1 == type_equal);
+ if (1 != type_equal) {
+ failure_mssg = "vrfy_ds_ctg_i: type not H5T_NATIVE_INT";
+ return false;
}
- if (pass) {
- ret = H5Tclose(tid);
+ ret = H5Tclose(tid);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_i: H5Tclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ds_ctg_i: H5Tclose() failed.";
+ return false;
}
- if (pass) {
- ret = H5Dget_space_status(dsid, &allocation);
+ ret = H5Dget_space_status(dsid, &allocation);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_i: H5Dget_space_status() failed.";
- }
- else if (write_data && (allocation != H5D_SPACE_STATUS_ALLOCATED)) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_i: write_data && allocation != H5D_SPACE_STATUS_ALLOCATED";
- }
- else if (!write_data
- && (allocation != H5D_SPACE_STATUS_NOT_ALLOCATED)) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_i: !write_data && allocation != H5D_SPACE_STATUS_NOT_ALLOCATED";
- }
- HDassert(ret >= 0);
- HDassert((write_data && allocation == H5D_SPACE_STATUS_ALLOCATED)
- || (!write_data && allocation == H5D_SPACE_STATUS_NOT_ALLOCATED));
+ if (ret < 0) {
+ failure_mssg = "vrfy_ds_ctg_i: H5Dget_space_status() failed.";
+ return false;
+ } else if (write_data && (allocation != H5D_SPACE_STATUS_ALLOCATED)) {
+ failure_mssg = "vrfy_ds_ctg_i: "
+ "write_data && allocation != H5D_SPACE_STATUS_ALLOCATED";
+ return false;
+ } else if (!write_data && (allocation != H5D_SPACE_STATUS_NOT_ALLOCATED)) {
+ failure_mssg = "vrfy_ds_ctg_i: "
+ "!write_data && allocation != H5D_SPACE_STATUS_NOT_ALLOCATED";
+ return false;
}
- if (pass) {
- dcpl = H5Dget_create_plist(dsid);
+ dcpl = H5Dget_create_plist(dsid);
- if (dcpl <= 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_i: H5Dget_create_plist() failed.";
- }
- HDassert(dcpl > 0);
+ if (dcpl <= 0) {
+ failure_mssg = "vrfy_ds_ctg_i: H5Dget_create_plist() failed.";
+ return false;
}
- if (pass) {
- layout = H5Pget_layout(dcpl);
+ layout = H5Pget_layout(dcpl);
- if (H5D_CONTIGUOUS != layout) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_i: H5D_CONTIGUOUS != layout";
- }
- HDassert(H5D_CONTIGUOUS == layout);
+ if (H5D_CONTIGUOUS != layout) {
+ failure_mssg = "vrfy_ds_ctg_i: H5D_CONTIGUOUS != layout";
+ return false;
}
- if (pass) {
- ret = H5Pclose(dcpl);
+ ret = H5Pclose(dcpl);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_i: H5Pclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ds_ctg_i: H5Pclose() failed.";
+ return false;
}
- if ((pass) && (write_data)) {
- rdata = (int *) HDmalloc(sizeof(int) * DSET_DIMS);
+ if (write_data) {
+ rdata = HDmalloc(sizeof(int) * DSET_DIMS);
if (!rdata) {
- pass = FALSE;
failure_mssg = "vrfy_ds_ctg_i: HDmalloc of rdata failed.";
+ return false;
}
- HDassert(rdata);
- }
- if ((pass) && (write_data)) {
- ret = H5Dread(dsid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
- H5P_DEFAULT, rdata);
+ ret = H5Dread(dsid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT,
+ rdata);
if (ret < 0) {
- pass = FALSE;
failure_mssg = "vrfy_ds_ctg_i: H5Dread() failed.";
+ return false;
}
- HDassert(ret >= 0);
- }
- if ((pass) && (write_data)) {
for (u = 0; u < DSET_DIMS; u++) {
if ((int) u != rdata[u]) {
- pass = FALSE;
failure_mssg = "vrfy_ds_ctg_i: u != rdata[u].";
- break;
+ HDfree(rdata);
+ return false;
}
- HDassert((int )u == rdata[u]);
}
-
HDfree(rdata);
- } /* end if */
+ }
- if (pass) {
- ret = H5Dclose(dsid);
+ ret = H5Dclose(dsid);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_i: H5Dclose() failed";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ds_ctg_i: H5Dclose() failed";
+ return false;
}
- return;
+ return true;
} /* vrfy_ds_ctg_i() */
@@ -1951,20 +1684,32 @@ vrfy_ds_ctg_i(hid_t fid, const char *dset_name, hbool_t write_data) {
* to the data set or not as indicated by the write_data
* parameter.
*
- * If pass is false on entry, do nothing.
- *
- * If an error is detected, set pass to FALSE, and set
+ * If an error is detected, return false, and set
* failure_mssg to point to an appropriate error message.
*
- * Return: void
+ * Return: true on success, false on failure.
*
* Programmer: John Mainzer
* 9/14/15
*
*-------------------------------------------------------------------------
*/
-void
-ds_chk_i(hid_t fid, const char *dset_name, hbool_t write_data) {
+static bool
+missing_ds_chk_i(hid_t fid, const char *dset_name,
+ hbool_t H5_ATTR_UNUSED write_data)
+{
+ return file_has_no_path(fid, dset_name);
+}
+
+static bool
+rm_ds_chk_i(hid_t fid, const char *dset_name, hbool_t H5_ATTR_UNUSED write_data)
+{
+ return remove_from_file_path(fid, dset_name);
+}
+
+bool
+ds_chk_i(hid_t fid, const char *dset_name, hbool_t write_data)
+{
int *wdata = NULL;
unsigned u;
hid_t dsid = -1;
@@ -1974,102 +1719,77 @@ ds_chk_i(hid_t fid, const char *dset_name, hbool_t write_data) {
hsize_t chunk_dims[1] = { DSET_CHUNK_DIMS };
herr_t ret;
- if (pass) {
- sid = H5Screate_simple(1, dims, NULL);
+ sid = H5Screate_simple(1, dims, NULL);
- if (sid <= 0) {
- pass = FALSE;
- failure_mssg = "ds_chk_i: H5Screate_simple() failed.";
- }
- HDassert(sid > 0);
+ if (sid <= 0) {
+ failure_mssg = "ds_chk_i: H5Screate_simple() failed.";
+ return false;
}
- if (pass) {
- dcpl = H5Pcreate(H5P_DATASET_CREATE);
+ dcpl = H5Pcreate(H5P_DATASET_CREATE);
- if (dcpl <= 0) {
- pass = FALSE;
- failure_mssg = "ds_chk_i: H5Pcreate() failed.";
- }
- HDassert(dcpl > 0);
+ if (dcpl <= 0) {
+ failure_mssg = "ds_chk_i: H5Pcreate() failed.";
+ return false;
}
- if (pass) {
- ret = H5Pset_chunk(dcpl, 1, chunk_dims);
+ ret = H5Pset_chunk(dcpl, 1, chunk_dims);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "ds_chk_i: H5Pset_chunk() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "ds_chk_i: H5Pset_chunk() failed.";
+ return false;
}
- if (pass) {
- dsid = H5Dcreate2(fid, dset_name, H5T_NATIVE_INT, sid,
- H5P_DEFAULT, dcpl, H5P_DEFAULT);
+ dsid = H5Dcreate2(fid, dset_name, H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl,
+ H5P_DEFAULT);
- if (dsid <= 0) {
- pass = FALSE;
- failure_mssg = "ds_chk_i: H5Dcreate2() failed";
- }
- HDassert(dsid > 0);
+ if (dsid <= 0) {
+ failure_mssg = "ds_chk_i: H5Dcreate2() failed";
+ return false;
}
- if (pass) {
- ret = H5Pclose(dcpl);
+ ret = H5Pclose(dcpl);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "ds_chk_i: H5Pclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "ds_chk_i: H5Pclose() failed.";
+ return false;
}
- if (pass) {
- ret = H5Sclose(sid);
+ ret = H5Sclose(sid);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "ds_chk_i: H5Sclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "ds_chk_i: H5Sclose() failed.";
+ return false;
}
- if ((pass) && (write_data)) {
- wdata = (int *) HDmalloc(sizeof(int) * DSET_DIMS);
+ if (write_data) {
+ wdata = HDmalloc(sizeof(int) * DSET_DIMS);
if (!wdata) {
- pass = FALSE;
failure_mssg = "ds_chk_i: HDmalloc of wdata failed.";
+ return false;
}
- HDassert(wdata);
- }
- if ((pass) && (write_data)) {
for (u = 0; u < DSET_DIMS; u++)
wdata[u] = (int) u;
- ret = H5Dwrite(dsid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
- H5P_DEFAULT, wdata);
+ ret = H5Dwrite(dsid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT,
+ wdata);
+ HDfree(wdata);
if (ret < 0) {
- pass = FALSE;
failure_mssg = "ds_chk_i: H5Dwrite() failed.";
+ return false;
}
- HDassert(ret >= 0);
- HDfree(wdata);
- } /* end if */
+ }
- if (pass) {
- ret = H5Dclose(dsid);
+ ret = H5Dclose(dsid);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "ds_chk_i: H5Dclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "ds_chk_i: H5Dclose() failed.";
+ return false;
}
- return;
+ return true;
} /* ds_chk_i */
@@ -2079,20 +1799,19 @@ ds_chk_i(hid_t fid, const char *dset_name, hbool_t write_data) {
* Purpose: Validate a chunked datasets w/int datatypes. Validate
* data if indicated via the write_data parameter.
*
- * If pass is false on entry, do nothing.
- *
- * If an error is detected, set pass to FALSE, and set
+ * If an error is detected, return false, and set
* failure_mssg to point to an appropriate error message.
*
- * Return: void
+ * Return: true on success, false on failure.
*
* Programmer: John Mainzer
* 9/14/15
*
*-------------------------------------------------------------------------
*/
-void
-vrfy_ds_chk_i(hid_t fid, const char *dset_name, hbool_t write_data) {
+bool
+vrfy_ds_chk_i(hid_t fid, const char *dset_name, hbool_t write_data)
+{
int *rdata = NULL;
unsigned u;
hid_t dsid = -1;
@@ -2106,204 +1825,145 @@ vrfy_ds_chk_i(hid_t fid, const char *dset_name, hbool_t write_data) {
htri_t type_equal;
herr_t ret;
- if (pass) {
- dsid = H5Dopen2(fid, dset_name, H5P_DEFAULT);
+ dsid = H5Dopen2(fid, dset_name, H5P_DEFAULT);
- if (dsid <= 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_chk_i: H5Dopen2() failed.";
- }
- HDassert(dsid > 0);
+ if (dsid <= 0) {
+ failure_mssg = "vrfy_ds_chk_i: H5Dopen2() failed.";
+ return false;
}
- if (pass) {
- sid = H5Dget_space(dsid);
+ sid = H5Dget_space(dsid);
- if (sid <= 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_chk_i: H5Dget_space() failed.";
- }
- HDassert(sid > 0);
+ if (sid <= 0) {
+ failure_mssg = "vrfy_ds_chk_i: H5Dget_space() failed.";
+ return false;
}
- if (pass) {
- ndims = H5Sget_simple_extent_ndims(sid);
+ ndims = H5Sget_simple_extent_ndims(sid);
- if (1 != ndims) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_chk_i: 1 != ndims";
- }
- HDassert(1 == ndims);
+ if (1 != ndims) {
+ failure_mssg = "vrfy_ds_chk_i: 1 != ndims";
+ return false;
}
- if (pass) {
- ret = H5Sget_simple_extent_dims(sid, dims, max_dims);
+ ret = H5Sget_simple_extent_dims(sid, dims, max_dims);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_chk_i: H5Sget_simple_extent_dims() failed";
- }
- else if ( DSET_DIMS != dims[0]) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_chk_i: DSET_DIMS != dims[0]";
- }
- else if ( DSET_DIMS != max_dims[0]) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_chk_i: DSET_DIMS != max_dims[0]";
- }
- HDassert(ret >= 0);
- HDassert(DSET_DIMS == dims[0]);
- HDassert(DSET_DIMS == max_dims[0]);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ds_chk_i: H5Sget_simple_extent_dims() failed";
+ return false;
+ } else if ( DSET_DIMS != dims[0]) {
+ failure_mssg = "vrfy_ds_chk_i: DSET_DIMS != dims[0]";
+ return false;
+ } else if ( DSET_DIMS != max_dims[0]) {
+ failure_mssg = "vrfy_ds_chk_i: DSET_DIMS != max_dims[0]";
+ return false;
}
- if (pass) {
- ret = H5Sclose(sid);
+ ret = H5Sclose(sid);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_chk_i: H5Sclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ds_chk_i: H5Sclose() failed.";
+ return false;
}
- if (pass) {
- tid = H5Dget_type(dsid);
+ tid = H5Dget_type(dsid);
- if (tid <= 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_chk_i: H5Dget_type() failed.";
- }
- HDassert(tid > 0);
+ if (tid <= 0) {
+ failure_mssg = "vrfy_ds_chk_i: H5Dget_type() failed.";
+ return false;
}
- if (pass) {
- type_equal = H5Tequal(tid, H5T_NATIVE_INT);
+ type_equal = H5Tequal(tid, H5T_NATIVE_INT);
- if (1 != type_equal) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_chk_i: tid != H5T_NATIVE_INT";
- }
- HDassert(1 == type_equal);
+ if (1 != type_equal) {
+ failure_mssg = "vrfy_ds_chk_i: tid != H5T_NATIVE_INT";
+ return false;
}
- if (pass) {
- ret = H5Tclose(tid);
+ ret = H5Tclose(tid);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_chk_i: H5Tclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ds_chk_i: H5Tclose() failed.";
+ return false;
}
- if (pass) {
- ret = H5Dget_space_status(dsid, &allocation);
+ ret = H5Dget_space_status(dsid, &allocation);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_chk_i: H5Dget_space_status() failed.";
- }
- else if (write_data && (allocation != H5D_SPACE_STATUS_ALLOCATED)) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_chk_i: write_data && allocation != H5D_SPACE_STATUS_ALLOCATED";
- }
- else if (!write_data && (allocation != H5D_SPACE_STATUS_NOT_ALLOCATED)) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_chk_i: !write_data && allocation != H5D_SPACE_STATUS_NOT_ALLOCATED";
- }
- HDassert(ret >= 0);
- HDassert((write_data && allocation == H5D_SPACE_STATUS_ALLOCATED)
- || (!write_data && allocation == H5D_SPACE_STATUS_NOT_ALLOCATED));
+ if (ret < 0) {
+ failure_mssg = "vrfy_ds_chk_i: H5Dget_space_status() failed.";
+ return false;
+ } else if (write_data && (allocation != H5D_SPACE_STATUS_ALLOCATED)) {
+ failure_mssg = "vrfy_ds_chk_i: write_data && allocation != H5D_SPACE_STATUS_ALLOCATED";
+ return false;
+ } else if (!write_data && (allocation != H5D_SPACE_STATUS_NOT_ALLOCATED)) {
+ failure_mssg = "vrfy_ds_chk_i: !write_data && allocation != H5D_SPACE_STATUS_NOT_ALLOCATED";
+ return false;
}
- if (pass) {
- dcpl = H5Dget_create_plist(dsid);
+ dcpl = H5Dget_create_plist(dsid);
- if (dcpl <= 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_chk_i: H5Dget_create_plist() failed.";
- }
- HDassert(dcpl > 0);
+ if (dcpl <= 0) {
+ failure_mssg = "vrfy_ds_chk_i: H5Dget_create_plist() failed.";
+ return false;
}
- if (pass) {
- layout = H5Pget_layout(dcpl);
+ layout = H5Pget_layout(dcpl);
- if (H5D_CHUNKED != layout) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_chk_i: H5D_CHUNKED != layout";
- }
- HDassert(H5D_CHUNKED == layout);
+ if (H5D_CHUNKED != layout) {
+ failure_mssg = "vrfy_ds_chk_i: H5D_CHUNKED != layout";
+ return false;
}
- if (pass) {
- ret = H5Pget_chunk(dcpl, 1, chunk_dims);
+ ret = H5Pget_chunk(dcpl, 1, chunk_dims);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_chk_i: H5Pget_chunk";
- }
- else if ( DSET_CHUNK_DIMS != chunk_dims[0]) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_chk_i: ";
- }
- HDassert(ret >= 0);
- HDassert(DSET_CHUNK_DIMS == chunk_dims[0]);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ds_chk_i: H5Pget_chunk";
+ return false;
+ } else if ( DSET_CHUNK_DIMS != chunk_dims[0]) {
+ failure_mssg = "vrfy_ds_chk_i: ";
+ return false;
}
- if (pass) {
- ret = H5Pclose(dcpl);
+ ret = H5Pclose(dcpl);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_chk_i: H5Pclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ds_chk_i: H5Pclose() failed.";
+ return false;
}
- if ((pass) && (write_data)) {
- rdata = (int *) HDmalloc(sizeof(int) * DSET_DIMS);
+ if (write_data) {
+ rdata = HDmalloc(sizeof(int) * DSET_DIMS);
if (!rdata) {
- pass = FALSE;
failure_mssg = "vrfy_ds_chk_i: HDmalloc of rdata failed.";
+ return false;
}
- HDassert(rdata);
- }
- if ((pass) && (write_data)) {
- ret = H5Dread(dsid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, rdata);
+ ret = H5Dread(dsid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT,
+ rdata);
if (ret < 0) {
- pass = FALSE;
failure_mssg = "vrfy_ds_chk_i: H5Dread() failed.";
+ return false;
}
- HDassert(ret >= 0);
- }
- if ((pass) && (write_data)) {
for (u = 0; u < DSET_DIMS; u++) {
if ((int) u != rdata[u]) {
- pass = FALSE;
failure_mssg = "vrfy_ds_chk_i: u != rdata[u]";
- break;
+ HDfree(rdata);
+ return false;
}
- HDassert((int )u == rdata[u]);
}
-
HDfree(rdata);
- } /* end if */
+ }
- if (pass) {
- ret = H5Dclose(dsid);
+ ret = H5Dclose(dsid);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_chk_i: H5Dclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ds_chk_i: H5Dclose() failed.";
+ return false;
}
- return;
+ return true;
} /* vrfy_ds_chk_i() */
@@ -2314,20 +1974,32 @@ vrfy_ds_chk_i(hid_t fid, const char *dset_name, hbool_t write_data) {
* to the data set or not as indicated by the write_data
* parameter.
*
- * If pass is false on entry, do nothing.
- *
- * If an error is detected, set pass to FALSE, and set
+ * If an error is detected, return false, and set
* failure_mssg to point to an appropriate error message.
*
- * Return: void
+ * Return: true on success, false on failure.
*
* Programmer: John Mainzer
* 9/14/15
*
*-------------------------------------------------------------------------
*/
-void
-ds_cpt_i(hid_t fid, const char *dset_name, hbool_t write_data) {
+static bool
+missing_ds_cpt_i(hid_t fid, const char *dset_name,
+ hbool_t H5_ATTR_UNUSED write_data)
+{
+ return file_has_no_path(fid, dset_name);
+}
+
+static bool
+rm_ds_cpt_i(hid_t fid, const char *dset_name, hbool_t H5_ATTR_UNUSED write_data)
+{
+ return remove_from_file_path(fid, dset_name);
+}
+
+bool
+ds_cpt_i(hid_t fid, const char *dset_name, hbool_t write_data)
+{
int *wdata = NULL;
unsigned u;
hid_t dsid = -1;
@@ -2336,104 +2008,78 @@ ds_cpt_i(hid_t fid, const char *dset_name, hbool_t write_data) {
hsize_t dims[1] = { DSET_COMPACT_DIMS };
herr_t ret;
- if (pass) {
- sid = H5Screate_simple(1, dims, NULL);
+ sid = H5Screate_simple(1, dims, NULL);
- if (sid <= 0) {
- pass = FALSE;
- failure_mssg = "ds_cpt_i: H5Screate_simple() failed.";
- }
- HDassert(sid > 0);
+ if (sid <= 0) {
+ failure_mssg = "ds_cpt_i: H5Screate_simple() failed.";
+ return false;
}
- if (pass) {
- dcpl = H5Pcreate(H5P_DATASET_CREATE);
+ dcpl = H5Pcreate(H5P_DATASET_CREATE);
- if (dcpl <= 0) {
- pass = FALSE;
- failure_mssg = "ds_cpt_i: H5Pcreate() failed.";
- }
- HDassert(dcpl > 0);
+ if (dcpl <= 0) {
+ failure_mssg = "ds_cpt_i: H5Pcreate() failed.";
+ return false;
}
- if (pass) {
- ret = H5Pset_layout(dcpl, H5D_COMPACT);
+ ret = H5Pset_layout(dcpl, H5D_COMPACT);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "ds_cpt_i: H5Pset_layout() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "ds_cpt_i: H5Pset_layout() failed.";
+ return false;
}
- if (pass) {
- dsid = H5Dcreate2(fid, dset_name, H5T_NATIVE_INT, sid,
- H5P_DEFAULT, dcpl, H5P_DEFAULT);
+ dsid = H5Dcreate2(fid, dset_name, H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl,
+ H5P_DEFAULT);
- if (dsid <= 0) {
- pass = FALSE;
- failure_mssg = "ds_cpt_i: H5Dcreate2() failed.";
- }
- HDassert(dsid > 0);
+ if (dsid <= 0) {
+ failure_mssg = "ds_cpt_i: H5Dcreate2() failed.";
+ return false;
}
- if (pass) {
- ret = H5Pclose(dcpl);
+ ret = H5Pclose(dcpl);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "ds_cpt_i: H5Pclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "ds_cpt_i: H5Pclose() failed.";
+ return false;
}
- if (pass) {
- ret = H5Sclose(sid);
+ ret = H5Sclose(sid);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "ds_cpt_i: H5Sclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "ds_cpt_i: H5Sclose() failed.";
+ return false;
}
- if ((pass) && (write_data)) {
- wdata = (int *) HDmalloc(sizeof(int) * DSET_COMPACT_DIMS);
+ if (write_data) {
+ wdata = HDmalloc(sizeof(int) * DSET_COMPACT_DIMS);
if (!wdata) {
- pass = FALSE;
failure_mssg = "ds_cpt_i: HDmalloc of wdata failed.";
+ return false;
}
- HDassert(wdata);
- }
- if ((pass) && (write_data)) {
for (u = 0; u < DSET_COMPACT_DIMS; u++)
wdata[u] = (int) u;
- ret = H5Dwrite(dsid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
- H5P_DEFAULT, wdata);
+ ret = H5Dwrite(dsid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT,
+ wdata);
+ HDfree(wdata);
if (ret < 0) {
- pass = FALSE;
failure_mssg = "ds_cpt_i: H5Dwrite() failed.";
+ return false;
}
- HDassert(ret >= 0);
-
- HDfree(wdata);
- } /* end if */
+ }
- if (pass) {
- ret = H5Dclose(dsid);
+ ret = H5Dclose(dsid);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "ds_cpt_i: H5Dclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "ds_cpt_i: H5Dclose() failed.";
+ return false;
}
- return;
+ return true;
} /* ds_cpt_i() */
@@ -2444,20 +2090,19 @@ ds_cpt_i(hid_t fid, const char *dset_name, hbool_t write_data) {
* Purpose: Validate a compact datasets w/int datatypes. Validate
* data if indicated via the write_data parameter.
*
- * If pass is false on entry, do nothing.
- *
- * If an error is detected, set pass to FALSE, and set
+ * If an error is detected, return false, and set
* failure_mssg to point to an appropriate error message.
*
- * Return: void
+ * Return: true on success, false on failure.
*
* Programmer: John Mainzer
* 9/14/15
*
*-------------------------------------------------------------------------
*/
-void
-vrfy_ds_cpt_i(hid_t fid, const char *dset_name, hbool_t write_data) {
+bool
+vrfy_ds_cpt_i(hid_t fid, const char *dset_name, hbool_t write_data)
+{
int *rdata = NULL;
unsigned u;
hid_t dsid = -1;
@@ -2471,186 +2116,133 @@ vrfy_ds_cpt_i(hid_t fid, const char *dset_name, hbool_t write_data) {
htri_t type_equal;
herr_t ret;
- if (pass) {
- dsid = H5Dopen2(fid, dset_name, H5P_DEFAULT);
+ dsid = H5Dopen2(fid, dset_name, H5P_DEFAULT);
- if (dsid <= 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_cpt_i: H5Dopen2() failed.";
- }
- HDassert(dsid > 0);
+ if (dsid <= 0) {
+ failure_mssg = "vrfy_ds_cpt_i: H5Dopen2() failed.";
+ return false;
}
- if (pass) {
- sid = H5Dget_space(dsid);
+ sid = H5Dget_space(dsid);
- if (sid <= 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_cpt_i: H5Dget_space() failed.";
- }
- HDassert(sid > 0);
+ if (sid <= 0) {
+ failure_mssg = "vrfy_ds_cpt_i: H5Dget_space() failed.";
+ return false;
}
- if (pass) {
- ndims = H5Sget_simple_extent_ndims(sid);
+ ndims = H5Sget_simple_extent_ndims(sid);
- if (1 != ndims) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_cpt_i: 1 != ndims";
- }
- HDassert(1 == ndims);
+ if (1 != ndims) {
+ failure_mssg = "vrfy_ds_cpt_i: 1 != ndims";
+ return false;
}
- if (pass) {
- ret = H5Sget_simple_extent_dims(sid, dims, max_dims);
+ ret = H5Sget_simple_extent_dims(sid, dims, max_dims);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_cpt_i: H5Sget_simple_extent_dims() failed";
- }
- else if ( DSET_COMPACT_DIMS != dims[0]) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_cpt_i: DSET_COMPACT_DIMS != dims[0]";
- }
- else if ( DSET_COMPACT_DIMS != max_dims[0]) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_cpt_i: DSET_COMPACT_DIMS != max_dims[0]";
- }
- HDassert(ret >= 0);
- HDassert(DSET_COMPACT_DIMS == dims[0]);
- HDassert(DSET_COMPACT_DIMS == max_dims[0]);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ds_cpt_i: H5Sget_simple_extent_dims() failed";
+ return false;
+ } else if ( DSET_COMPACT_DIMS != dims[0]) {
+ failure_mssg = "vrfy_ds_cpt_i: DSET_COMPACT_DIMS != dims[0]";
+ return false;
+ } else if ( DSET_COMPACT_DIMS != max_dims[0]) {
+ failure_mssg = "vrfy_ds_cpt_i: DSET_COMPACT_DIMS != max_dims[0]";
+ return false;
}
- if (pass) {
- ret = H5Sclose(sid);
+ ret = H5Sclose(sid);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_cpt_i: H5Sclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ds_cpt_i: H5Sclose() failed.";
+ return false;
}
- if (pass) {
- tid = H5Dget_type(dsid);
+ tid = H5Dget_type(dsid);
- if (tid <= 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_cpt_i: H5Dget_type() failed.";
- }
- HDassert(tid > 0);
+ if (tid <= 0) {
+ failure_mssg = "vrfy_ds_cpt_i: H5Dget_type() failed.";
+ return false;
}
- if (pass) {
- type_equal = H5Tequal(tid, H5T_NATIVE_INT);
+ type_equal = H5Tequal(tid, H5T_NATIVE_INT);
- if (1 != type_equal) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_cpt_i: type != H5T_NATIVE_INT";
- }
- HDassert(1 == type_equal);
+ if (1 != type_equal) {
+ failure_mssg = "vrfy_ds_cpt_i: type != H5T_NATIVE_INT";
+ return false;
}
- if (pass) {
- ret = H5Tclose(tid);
+ ret = H5Tclose(tid);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_cpt_i: H5Tclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ds_cpt_i: H5Tclose() failed.";
+ return false;
}
- if (pass) {
- ret = H5Dget_space_status(dsid, &allocation);
+ ret = H5Dget_space_status(dsid, &allocation);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_cpt_i: H5Dget_space_status() failed.";
- }
- else if (H5D_SPACE_STATUS_ALLOCATED != allocation) {
- pass = FALSE;
- failure_mssg =
- "vrfy_ds_cpt_i: H5D_SPACE_STATUS_ALLOCATED != allocation";
- }
- HDassert(ret >= 0);
- HDassert(H5D_SPACE_STATUS_ALLOCATED == allocation);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ds_cpt_i: H5Dget_space_status() failed.";
+ return false;
+ } else if (H5D_SPACE_STATUS_ALLOCATED != allocation) {
+ failure_mssg =
+ "vrfy_ds_cpt_i: H5D_SPACE_STATUS_ALLOCATED != allocation";
+ return false;
}
- if (pass) {
- dcpl = H5Dget_create_plist(dsid);
+ dcpl = H5Dget_create_plist(dsid);
- if (dcpl <= 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_cpt_i: H5Dget_create_plist() failed.";
- }
- HDassert(dcpl > 0);
+ if (dcpl <= 0) {
+ failure_mssg = "vrfy_ds_cpt_i: H5Dget_create_plist() failed.";
+ return false;
}
- if (pass) {
- layout = H5Pget_layout(dcpl);
+ layout = H5Pget_layout(dcpl);
- if (H5D_COMPACT != layout) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_cpt_i: H5D_COMPACT != layout";
- }
- HDassert(H5D_COMPACT == layout);
+ if (H5D_COMPACT != layout) {
+ failure_mssg = "vrfy_ds_cpt_i: H5D_COMPACT != layout";
+ return false;
}
- if (pass) {
- ret = H5Pclose(dcpl);
+ ret = H5Pclose(dcpl);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_cpt_i: H5Pclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ds_cpt_i: H5Pclose() failed.";
+ return false;
}
- if ((pass) && (write_data)) {
- rdata = (int *) HDmalloc(sizeof(int) * DSET_COMPACT_DIMS);
+ if (write_data) {
+ rdata = HDmalloc(sizeof(int) * DSET_COMPACT_DIMS);
if (!rdata) {
- pass = FALSE;
failure_mssg = "vrfy_ds_cpt_i: HDmalloc of rdata failed.";
+ return false;
}
- HDassert(rdata);
- }
- if ((pass) && (write_data)) {
- ret = H5Dread(dsid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
- H5P_DEFAULT, rdata);
+ ret = H5Dread(dsid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT,
+ rdata);
if (ret < 0) {
- pass = FALSE;
failure_mssg = "vrfy_ds_cpt_i: H5Dread() failed.";
+ return false;
}
- HDassert(ret >= 0);
- }
- if ((pass) && (write_data)) {
for (u = 0; u < DSET_COMPACT_DIMS; u++) {
if ((int) u != rdata[u]) {
- pass = FALSE;
failure_mssg = "vrfy_ds_cpt_i: (int)u != rdata[u]";
- break;
+ HDfree(rdata);
+ return false;
}
- HDassert((int )u == rdata[u]);
}
-
HDfree(rdata);
- } /* end if */
+ }
- if (pass) {
- ret = H5Dclose(dsid);
+ ret = H5Dclose(dsid);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_cpt_i: H5Dclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ds_cpt_i: H5Dclose() failed.";
+ return false;
}
- return;
+ return true;
} /* vrfy_ds_cpt_i() */
@@ -2661,20 +2253,32 @@ vrfy_ds_cpt_i(hid_t fid, const char *dset_name, hbool_t write_data) {
* Write data to the data set or not as indicated by the
* write_data parameter.
*
- * If pass is false on entry, do nothing.
- *
- * If an error is detected, set pass to FALSE, and set
+ * If an error is detected, return false, and set
* failure_mssg to point to an appropriate error message.
*
- * Return: void
+ * Return: true on success, false on failure.
*
* Programmer: John Mainzer
* 9/14/15
*
*-------------------------------------------------------------------------
*/
-void
-ds_ctg_v(hid_t fid, const char *dset_name, hbool_t write_data) {
+static bool
+missing_ds_ctg_v(hid_t fid, const char *dset_name,
+ hbool_t H5_ATTR_UNUSED write_data)
+{
+ return file_has_no_path(fid, dset_name);
+}
+
+static bool
+rm_ds_ctg_v(hid_t fid, const char *dset_name, hbool_t H5_ATTR_UNUSED write_data)
+{
+ return remove_from_file_path(fid, dset_name);
+}
+
+bool
+ds_ctg_v(hid_t fid, const char *dset_name, hbool_t write_data)
+{
hid_t dsid = -1;
hid_t sid = -1;
hid_t tid = -1;
@@ -2683,124 +2287,101 @@ ds_ctg_v(hid_t fid, const char *dset_name, hbool_t write_data) {
hvl_t *wdata = NULL;
unsigned u;
- if (pass) {
- sid = H5Screate_simple(1, dims, NULL);
+ sid = H5Screate_simple(1, dims, NULL);
- if (sid <= 0) {
- pass = FALSE;
- failure_mssg = "ds_ctg_v: H5Screate_simple";
- }
- HDassert(sid > 0);
+ if (sid <= 0) {
+ failure_mssg = "ds_ctg_v: H5Screate_simple";
+ return false;
}
- if (pass) {
- tid = H5Tvlen_create(H5T_NATIVE_INT);
+ tid = H5Tvlen_create(H5T_NATIVE_INT);
- if (tid <= 0) {
- pass = FALSE;
- failure_mssg = "ds_ctg_v: H5Tvlen_create() failed.";
- }
- HDassert(tid > 0);
+ if (tid <= 0) {
+ failure_mssg = "ds_ctg_v: H5Tvlen_create() failed.";
+ return false;
}
- if (pass) {
- dsid = H5Dcreate2(fid, dset_name, tid, sid, H5P_DEFAULT,
- H5P_DEFAULT, H5P_DEFAULT);
+ dsid = H5Dcreate2(fid, dset_name, tid, sid, H5P_DEFAULT,
+ H5P_DEFAULT, H5P_DEFAULT);
- if (dsid <= 0) {
- pass = FALSE;
- failure_mssg = "ds_ctg_v: H5Dcreate2() failed.";
- }
- HDassert(dsid > 0);
+ if (dsid <= 0) {
+ failure_mssg = "ds_ctg_v: H5Dcreate2() failed.";
+ return false;
}
- if ((pass) && (write_data)) {
- wdata = (hvl_t *) HDmalloc(sizeof(hvl_t) * DSET_SMALL_DIMS);
+ if (write_data) {
+ wdata = HDmalloc(sizeof(hvl_t) * DSET_SMALL_DIMS);
if (!wdata) {
- pass = FALSE;
failure_mssg = "ds_ctg_v: HDmalloc of wdata failed.";
+ return false;
}
- HDassert(wdata);
- }
- if ((pass) && (write_data)) {
for (u = 0; u < DSET_SMALL_DIMS; u++) {
int *tdata;
unsigned len;
unsigned v;
len = (u % 10) + 1;
- tdata = (int *) HDmalloc(sizeof(int) * len);
+ tdata = HDmalloc(sizeof(int) * len);
if (!tdata) {
- pass = FALSE;
failure_mssg = "ds_ctg_v: HDmalloc of tdata failed.";
- break;
+ while (u > 0)
+ free(wdata[u--].p);
+ HDfree(wdata);
+ return false;
}
- HDassert(tdata);
for (v = 0; v < len; v++)
tdata[v] = (int) (u + v);
wdata[u].len = len;
wdata[u].p = tdata;
- } /* end for */
- }
+ }
- if ((pass) && (write_data)) {
ret = H5Dwrite(dsid, tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, wdata);
if (ret < 0) {
- pass = FALSE;
failure_mssg = "ds_ctg_v: H5Dwrite() failed.";
+ for (u = 0; u < DSET_SMALL_DIMS; u++)
+ free(wdata[u].p);
+ HDfree(wdata);
+ return false;
}
- HDassert(ret >= 0);
- }
- if ((pass) && (write_data)) {
ret = H5Treclaim(tid, sid, H5P_DEFAULT, wdata);
+ HDfree(wdata);
+
if (ret < 0) {
- pass = FALSE;
failure_mssg = "ds_ctg_v: H5Treclaim() failed.";
+ return false;
}
- HDassert(ret >= 0);
-
- HDfree(wdata);
- } /* end if */
+ }
- if (pass) {
- ret = H5Sclose(sid);
+ ret = H5Sclose(sid);
- if (sid < 0) {
- pass = FALSE;
- failure_mssg = "ds_ctg_v: H5Sclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "ds_ctg_v: H5Sclose() failed.";
+ return false;
}
- if (pass) {
- ret = H5Tclose(tid);
+ ret = H5Tclose(tid);
- if (tid < 0) {
- pass = FALSE;
- failure_mssg = "ds_ctg_v: H5Tclose() failed.";
- }
- HDassert(ret >= 0);
+ if (tid < 0) {
+ failure_mssg = "ds_ctg_v: H5Tclose() failed.";
+ return false;
}
- if (pass) {
- ret = H5Dclose(dsid);
+ ret = H5Dclose(dsid);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "ds_ctg_v: H5Dclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "ds_ctg_v: H5Dclose() failed.";
+ return false;
}
- return;
+ return true;
} /* ds_ctg_v() */
@@ -2810,20 +2391,19 @@ ds_ctg_v(hid_t fid, const char *dset_name, hbool_t write_data) {
* Purpose: Validate a contiguous datasets w/variable-length datatypes.
* Validate data if indicated via the write_data parameter.
*
- * If pass is false on entry, do nothing.
- *
- * If an error is detected, set pass to FALSE, and set
+ * If an error is detected, return false, and set
* failure_mssg to point to an appropriate error message.
*
- * Return: void
+ * Return: true on success, false on failure.
*
* Programmer: John Mainzer
* 9/14/15
*
*-------------------------------------------------------------------------
*/
-void
-vrfy_ds_ctg_v(hid_t fid, const char *dset_name, hbool_t write_data) {
+bool
+vrfy_ds_ctg_v(hid_t fid, const char *dset_name, hbool_t write_data)
+{
hid_t dsid = -1;
hid_t sid = -1;
hid_t tid = -1;
@@ -2838,170 +2418,120 @@ vrfy_ds_ctg_v(hid_t fid, const char *dset_name, hbool_t write_data) {
unsigned u;
herr_t ret;
- if (pass) {
- dsid = H5Dopen2(fid, dset_name, H5P_DEFAULT);
+ dsid = H5Dopen2(fid, dset_name, H5P_DEFAULT);
- if (dsid <= 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_v: H5Dopen2() failed.";
- }
- HDassert(dsid > 0);
+ if (dsid <= 0) {
+ failure_mssg = "vrfy_ds_ctg_v: H5Dopen2() failed.";
+ return false;
}
- if (pass) {
- sid = H5Dget_space(dsid);
+ sid = H5Dget_space(dsid);
- if (sid <= 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_v: H5Dget_space() failed";
- }
- HDassert(sid > 0);
+ if (sid <= 0) {
+ failure_mssg = "vrfy_ds_ctg_v: H5Dget_space() failed";
+ return false;
}
- if (pass) {
- ndims = H5Sget_simple_extent_ndims(sid);
+ ndims = H5Sget_simple_extent_ndims(sid);
- if (1 != ndims) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_v: 1 != ndims";
- }
- HDassert(1 == ndims);
+ if (1 != ndims) {
+ failure_mssg = "vrfy_ds_ctg_v: 1 != ndims";
+ return false;
}
- if (pass) {
- ret = H5Sget_simple_extent_dims(sid, dims, max_dims);
+ ret = H5Sget_simple_extent_dims(sid, dims, max_dims);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_v: H5Sget_simple_extent_dims() failed.";
- }
- else if ( DSET_SMALL_DIMS != dims[0]) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_v: DSET_SMALL_DIMS != dims[0]";
- }
- else if ( DSET_SMALL_DIMS != max_dims[0]) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_v: DSET_SMALL_DIMS != max_dims[0]";
- }
- HDassert(ret >= 0);
- HDassert(DSET_SMALL_DIMS == dims[0]);
- HDassert(DSET_SMALL_DIMS == max_dims[0]);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ds_ctg_v: H5Sget_simple_extent_dims() failed.";
+ return false;
+ } else if ( DSET_SMALL_DIMS != dims[0]) {
+ failure_mssg = "vrfy_ds_ctg_v: DSET_SMALL_DIMS != dims[0]";
+ return false;
+ } else if ( DSET_SMALL_DIMS != max_dims[0]) {
+ failure_mssg = "vrfy_ds_ctg_v: DSET_SMALL_DIMS != max_dims[0]";
+ return false;
}
- if (pass) {
- tid = H5Dget_type(dsid);
+ tid = H5Dget_type(dsid);
- if (tid <= 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_v: H5Dget_type() failed.";
- }
- HDassert(tid > 0);
+ if (tid <= 0) {
+ failure_mssg = "vrfy_ds_ctg_v: H5Dget_type() failed.";
+ return false;
}
- if (pass) {
- tmp_tid = H5Tvlen_create(H5T_NATIVE_INT);
+ tmp_tid = H5Tvlen_create(H5T_NATIVE_INT);
- if (tmp_tid <= 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_v: H5Tvlen_create() failed.";
- }
- HDassert(tmp_tid > 0);
+ if (tmp_tid <= 0) {
+ failure_mssg = "vrfy_ds_ctg_v: H5Tvlen_create() failed.";
+ return false;
}
- if (pass) {
- type_equal = H5Tequal(tid, tmp_tid);
+ type_equal = H5Tequal(tid, tmp_tid);
- if (1 != type_equal) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_v: type != vlen H5T_NATIVE_INT";
- }
- HDassert(1 == type_equal);
+ if (1 != type_equal) {
+ failure_mssg = "vrfy_ds_ctg_v: type != vlen H5T_NATIVE_INT";
+ return false;
}
- if (pass) {
- ret = H5Tclose(tmp_tid);
+ ret = H5Tclose(tmp_tid);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_v: H5Tclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ds_ctg_v: H5Tclose() failed.";
+ return false;
}
- if (pass) {
- ret = H5Dget_space_status(dsid, &allocation);
+ ret = H5Dget_space_status(dsid, &allocation);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_v: H5Dget_space_status() failed";
- }
- else if (write_data && (allocation != H5D_SPACE_STATUS_ALLOCATED)) {
- pass = FALSE;
- failure_mssg =
- "vrfy_ds_ctg_v: write_data && allocation != H5D_SPACE_STATUS_ALLOCATED";
- }
- else if (!write_data
- && (allocation != H5D_SPACE_STATUS_NOT_ALLOCATED)) {
- pass = FALSE;
- failure_mssg =
- "vrfy_ds_ctg_v: !write_data && allocation != H5D_SPACE_STATUS_NOT_ALLOCATED";
- }
- HDassert(ret >= 0);
- HDassert((write_data && allocation == H5D_SPACE_STATUS_ALLOCATED)
- || (!write_data && allocation == H5D_SPACE_STATUS_NOT_ALLOCATED));
+ if (ret < 0) {
+ failure_mssg = "vrfy_ds_ctg_v: H5Dget_space_status() failed";
+ return false;
+ } else if (write_data && (allocation != H5D_SPACE_STATUS_ALLOCATED)) {
+ failure_mssg =
+ "vrfy_ds_ctg_v: write_data && allocation != H5D_SPACE_STATUS_ALLOCATED";
+ return false;
+ } else if (!write_data
+ && (allocation != H5D_SPACE_STATUS_NOT_ALLOCATED)) {
+ failure_mssg =
+ "vrfy_ds_ctg_v: !write_data && allocation != H5D_SPACE_STATUS_NOT_ALLOCATED";
+ return false;
}
- if (pass) {
- dcpl = H5Dget_create_plist(dsid);
+ dcpl = H5Dget_create_plist(dsid);
- if (dcpl <= 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_v: H5Dget_create_plist() failed.";
- }
- HDassert(dcpl > 0);
+ if (dcpl <= 0) {
+ failure_mssg = "vrfy_ds_ctg_v: H5Dget_create_plist() failed.";
+ return false;
}
- if (pass) {
- layout = H5Pget_layout(dcpl);
+ layout = H5Pget_layout(dcpl);
- if (H5D_CONTIGUOUS != layout) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_v: H5D_CONTIGUOUS != layout";
- }
- HDassert(H5D_CONTIGUOUS == layout);
+ if (H5D_CONTIGUOUS != layout) {
+ failure_mssg = "vrfy_ds_ctg_v: H5D_CONTIGUOUS != layout";
+ return false;
}
- if (pass) {
- ret = H5Pclose(dcpl);
+ ret = H5Pclose(dcpl);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_v: H5Pclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ds_ctg_v: H5Pclose() failed.";
+ return false;
}
- if ((pass) && (write_data)) {
- rdata = (hvl_t *) HDmalloc(sizeof(hvl_t) * DSET_SMALL_DIMS);
+ if (write_data) {
+ rdata = HDmalloc(sizeof(hvl_t) * DSET_SMALL_DIMS);
if (!rdata) {
- pass = FALSE;
failure_mssg = "vrfy_ds_ctg_v: HDmalloc of rdata failed.";
+ return false;
}
- HDassert(rdata);
- }
- if ((pass) && (write_data)) {
ret = H5Dread(dsid, tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, rdata);
if (ret < 0) {
- pass = FALSE;
failure_mssg = "vrfy_ds_ctg_v: H5Dread() failed.";
+ return false;
}
- HDassert(ret >= 0);
- }
- if ((pass) && (write_data)) {
for (u = 0; u < DSET_SMALL_DIMS; u++) {
unsigned len;
unsigned v;
@@ -3011,66 +2541,222 @@ vrfy_ds_ctg_v(hid_t fid, const char *dset_name, hbool_t write_data) {
int *tdata = (int *) rdata[u].p;
if (!tdata) {
- pass = FALSE;
failure_mssg = "vrfy_ds_ctg_v: !tdata";
- break;
- }
- else if ((int) (u + v) != tdata[v]) {
- pass = FALSE;
+ return false;
+ } else if ((int) (u + v) != tdata[v]) {
failure_mssg = "vrfy_ds_ctg_v: (int)(u + v) != tdata[v]";
- break;
+ return false;
}
- HDassert(tdata);
- HDassert((int )(u + v) == tdata[v]);
- } /* end for */
- } /* end for */
- }
+ }
+ }
- if ((pass) && (write_data)) {
ret = H5Treclaim(tid, sid, H5P_DEFAULT, rdata);
+ HDfree(rdata);
+
if (ret < 0) {
- pass = FALSE;
failure_mssg = "vrfy_ds_ctg_v: H5Treclaim() failed.";
+ return false;
}
- HDassert(ret >= 0);
-
- HDfree(rdata);
- } /* end if */
+ }
- if (pass) {
- ret = H5Sclose(sid);
+ ret = H5Sclose(sid);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_v: H5Sclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ds_ctg_v: H5Sclose() failed.";
+ return false;
}
- if (pass) {
- ret = H5Tclose(tid);
+ ret = H5Tclose(tid);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_v: H5Tclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ds_ctg_v: H5Tclose() failed.";
+ return false;
}
- if (pass) {
- ret = H5Dclose(dsid);
+ ret = H5Dclose(dsid);
- if (ret < 0) {
- pass = FALSE;
- failure_mssg = "vrfy_ds_ctg_v: H5Dclose() failed.";
- }
- HDassert(ret >= 0);
+ if (ret < 0) {
+ failure_mssg = "vrfy_ds_ctg_v: H5Dclose() failed.";
+ return false;
}
- return;
+ return true;
} /* vrfy_ds_ctg_v() */
+/* Create or, if `validate` is true, validate objects in file `fid` under
+ * group `full_path`. `proc_num` tells the processor number the test runs
+ * on. The set of objects to create/validate is chosen by `selector`.
+ *
+ * The valid selectors are consecutive and they start at 0.
+ *
+ * If the selected objects cannot be created/validated, `*okp` will be set
+ * to `false`, indicating that the selected objects could not be
+ * created/validated, and `failure_mmsg` set to a description of the error
+ * that occurred. If the objects can be created/validated, then `*okp`
+ * will be set to `true`.
+ *
+ * The program may also fail an assert()ion if the selected objects cannot
+ * be created/validated.
+ *
+ * Return `true` if the selector was valid, `false` if it was not.
+ */
+
+static bool
+create_or_validate_selection(hid_t fid, const char *full_path,
+ int selector, zoo_config_t config, phase_t phase, bool *okp)
+{
+ bool ok;
+
+ switch (selector) {
+ case 0: /* Add & verify an empty "new style" group */
+ ok = ns_grp_0_fntbl[phase](fid, full_path);
+ break;
+ case 1: /* Add & verify a compact "new style" group (3 link messages) */
+ ok = ns_grp_c_fntbl[phase](fid, full_path, 3);
+ break;
+ case 2:
+ /* Add & verify a dense "new style" group (w/300 links,
+ * in v2 B-tree & fractal heap)
+ */
+ ok = ns_grp_d_fntbl[phase](fid, full_path, 300);
+ break;
+ case 3: /* Add & verify an empty "old style" group to file */
+ ok = os_grp_0_fntbl[phase](fid, full_path);
+ break;
+ case 4:
+ /* Add & verify an "old style" group (w/300 links, in
+ * v1 B-tree & local heap) to file
+ */
+ ok = os_grp_n_fntbl[phase](fid, full_path, config.proc_num, 300);
+ break;
+ case 5:
+ /* Add & verify a contiguous dataset w/integer datatype (but no data)
+ * to file
+ */
+ ok = ds_ctg_i_fntbl[phase](fid, full_path, false);
+ break;
+ case 6:
+ /* Add & verify a contiguous dataset w/integer datatype (with data)
+ * to file
+ */
+ ok = ds_ctg_i_fntbl[phase](fid, full_path, true);
+ break;
+ case 7:
+ /* Add & verify a chunked dataset w/integer datatype (but no data)
+ * to file
+ */
+ ok = ds_chk_i_fntbl[phase](fid, full_path, false);
+ break;
+ case 8:
+ /* Add & verify a chunked dataset w/integer datatype (and data)
+ * to file
+ */
+ ok = ds_chk_i_fntbl[phase](fid, full_path, true);
+ break;
+ case 9:
+ /* Add & verify a compact dataset w/integer datatype (but no data)
+ * to file
+ */
+ ok = config.skip_compact ||
+ ds_cpt_i_fntbl[phase](fid, full_path, false);
+ break;
+ case 10:
+ /* Add & verify a compact dataset w/integer datatype (and data)
+ * to file
+ */
+ ok = config.skip_compact || ds_cpt_i_fntbl[phase](fid, full_path, true);
+ break;
+ case 11:
+ /* Add & verify a contiguous dataset w/variable-length datatype
+ * (but no data) to file
+ */
+ ok = config.skip_varlen || ds_ctg_v_fntbl[phase](fid, full_path, false);
+ break;
+ case 12:
+ /* Add & verify a contiguous dataset w/variable-length datatype
+ * (and data) to file
+ */
+ ok = config.skip_varlen || ds_ctg_v_fntbl[phase](fid, full_path, true);
+ break;
+ default:
+ return false;
+ }
+ *okp = ok;
+ return true;
+}
+
+/* Sleep for no more than `max_pause_msecs` milliseconds. */
+static void
+random_pause(unsigned int max_pause_msecs)
+{
+ struct timespec delay;
+ const uint64_t nsecs_per_sec = 1000 * 1000 * 1000;
+ uint64_t nsecs_per_msec, nsecs;
+
+ if (max_pause_msecs == 0)
+ return;
+
+ nsecs_per_msec = 1 + (uint64_t)random() % (1000 * 1000);
+ nsecs = max_pause_msecs * nsecs_per_msec;
+
+ delay.tv_sec = (time_t)(nsecs / nsecs_per_sec);
+ delay.tv_nsec = (long)(nsecs % nsecs_per_sec);
+ for (;;) {
+ if (nanosleep(&delay, &delay) == 0)
+ break;
+ if (errno == EINTR)
+ continue;
+ errx(EXIT_FAILURE, "%s: nanosleep", __func__);
+ }
+}
+
+/* Create and validate objects or, if `only_validate` is true, only
+ * validate objects in file `fid` under group `base_path`. `config.proc_num`
+ * tells the processor number the test runs on. If `config.skip_varlen` is
+ * true, do NOT perform tests that use variable-length data.
+ *
+ * Return true if all tests pass, false if any test fails.
+ */
+
+static bool
+tend_zoo(hid_t fid, const char *base_path, zoo_config_t config,
+ const phase_t *phase, size_t nphases)
+{
+ char full_path[1024];
+ int i, nwritten;
+ size_t j;
+ char *leafp;
+ bool ok = true;
+
+ nwritten = snprintf(full_path, sizeof(full_path), "%s/*", base_path);
+ if (nwritten < 0 || (size_t)nwritten >= sizeof(full_path)) {
+ failure_mssg = "tend_zoo: snprintf failed";
+ return false;
+ }
+
+ if ((leafp = strrchr(full_path, '*')) == NULL) {
+ failure_mssg = "tend_zoo: strrchr failed";
+ return false;
+ }
+
+ for (i = 0; ok; i++) {
+ assert('A' + i <= 'Z');
+ *leafp = (char)('A' + i);
+ for (j = 0; j < nphases; j++) {
+ if (!create_or_validate_selection(fid, full_path, i, config,
+ phase[j], &ok))
+ goto out;
+ if (phase[j] == PHASE_CREATE || phase[j] == PHASE_DELETE)
+ zoo_create_hook(fid);
+ }
+ random_pause(config.max_pause_msecs);
+ }
+out:
+ if (!ok)
+ warnx("%s: %s", __func__, failure_mssg);
+ return ok;
+}
/*-------------------------------------------------------------------------
* Function: create_zoo
@@ -3080,9 +2766,7 @@ vrfy_ds_ctg_v(hid_t fid, const char *dset_name, hbool_t write_data) {
* include instances of all on disk data structures used
* in the HDF5 library.
*
- * If pass is false on entry, do nothing.
- *
- * If an error is detected, set pass to FALSE, and set
+ * If an error is detected, return false, and set
* failure_mssg to point to an appropriate error message.
*
* This function was initially created to assist in testing
@@ -3092,214 +2776,16 @@ vrfy_ds_ctg_v(hid_t fid, const char *dset_name, hbool_t write_data) {
* the superblock.
*
* Note the associated validate_zoo() function.
- *
- * Return: void
- *
- * Programmer: John Mainzer
- * 9/14/15
- *
*-------------------------------------------------------------------------
*/
-void
-create_zoo(hid_t fid, const char *base_path, int proc_num)
+bool
+create_zoo(hid_t fid, const char *base_path, zoo_config_t config)
{
- char full_path[1024];
-
- HDassert(base_path);
-
- /* Add & verify an empty "new style" group */
- if ( pass ) {
- HDsprintf(full_path, "%s/A", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- ns_grp_0(fid, full_path);
- }
-
- if ( pass ) {
- HDsprintf(full_path, "%s/A", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- vrfy_ns_grp_0(fid, full_path);
- }
-
- /* Add & verify a compact "new style" group (3 link messages) */
- if ( pass ) {
- HDsprintf(full_path, "%s/B", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- ns_grp_c(fid, full_path, 3);
- }
-
- if ( pass ) {
- HDsprintf(full_path, "%s/B", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- vrfy_ns_grp_c(fid, full_path, 3);
- }
-
- /* Add & verify a dense "new style" group (w/300 links, in v2 B-tree &
- * fractal heap)
- */
- if ( pass ) {
- HDsprintf(full_path, "%s/C", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- ns_grp_d(fid, full_path, 300);
- }
-
- if ( pass ) {
- HDsprintf(full_path, "%s/C", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- vrfy_ns_grp_d(fid, full_path, 300);
- }
-
- /* Add & verify an empty "old style" group to file */
- if ( pass ) {
- HDsprintf(full_path, "%s/D", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- os_grp_0(fid, full_path);
- }
-
- if ( pass ) {
- HDsprintf(full_path, "%s/D", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- vrfy_os_grp_0(fid, full_path);
- }
-
- /* Add & verify an "old style" group (w/300 links, in v1 B-tree &
- * local heap) to file
- */
- if ( pass ) {
- HDsprintf(full_path, "%s/E", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- os_grp_n(fid, full_path, proc_num, 300);
- }
-
- if ( pass ) {
- HDsprintf(full_path, "%s/E", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- vrfy_os_grp_n(fid, full_path, proc_num, 300);
- }
-
- /* Add & verify a contiguous dataset w/integer datatype (but no data)
- * to file
- */
- if ( pass ) {
- HDsprintf(full_path, "%s/F", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- ds_ctg_i(fid, full_path, FALSE);
- }
-
- if ( pass ) {
- HDsprintf(full_path, "%s/F", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- vrfy_ds_ctg_i(fid, full_path, FALSE);
- }
-
- /* Add & verify a contiguous dataset w/integer datatype (with data)
- * to file
- */
- if ( pass ) {
- HDsprintf(full_path, "%s/G", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- ds_ctg_i(fid, full_path, TRUE);
- }
-
- if ( pass ) {
- HDsprintf(full_path, "%s/G", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- vrfy_ds_ctg_i(fid, full_path, TRUE);
- }
-
- /* Add & verify a chunked dataset w/integer datatype (but no data)
- * to file
- */
- if ( pass ) {
- HDsprintf(full_path, "%s/H", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- ds_chk_i(fid, full_path, FALSE);
- }
-
- if ( pass ) {
- HDsprintf(full_path, "%s/H", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- vrfy_ds_chk_i(fid, full_path, FALSE);
- }
-
- /* Add & verify a chunked dataset w/integer datatype (and data)
- * to file
- */
- if ( pass ) {
- HDsprintf(full_path, "%s/I", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- ds_chk_i(fid, full_path, TRUE);
- }
-
- if ( pass ) {
- HDsprintf(full_path, "%s/I", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- vrfy_ds_chk_i(fid, full_path, TRUE);
- }
-
- /* Add & verify a compact dataset w/integer datatype (but no data)
- * to file
- */
- if ( pass ) {
- HDsprintf(full_path, "%s/J", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- ds_cpt_i(fid, full_path, FALSE);
- }
-
- if ( pass ) {
- HDsprintf(full_path, "%s/J", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- vrfy_ds_cpt_i(fid, full_path, FALSE);
- }
-
- /* Add & verify a compact dataset w/integer datatype (and data)
- * to file
- */
- if ( pass ) {
- HDsprintf(full_path, "%s/K", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- ds_cpt_i(fid, full_path, TRUE);
- }
-
- if ( pass ) {
- HDsprintf(full_path, "%s/K", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- vrfy_ds_cpt_i(fid, full_path, TRUE);
- }
-
- /* Add & verify a contiguous dataset w/variable-length datatype
- * (but no data) to file
- */
- if ( pass ) {
- HDsprintf(full_path, "%s/L", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- ds_ctg_v(fid, full_path, FALSE);
- }
-
- if ( pass ) {
- HDsprintf(full_path, "%s/L", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- vrfy_ds_ctg_v(fid, full_path, FALSE);
- }
-
- /* Add & verify a contiguous dataset w/variable-length datatype
- * (and data) to file
- */
- if ( pass ) {
- HDsprintf(full_path, "%s/M", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- ds_ctg_v(fid, full_path, TRUE);
- }
-
- if ( pass ) {
- HDsprintf(full_path, "%s/M", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- vrfy_ds_ctg_v(fid, full_path, TRUE);
- }
-
- return;
-} /* create_zoo() */
+ const phase_t phase[] = {PHASE_CREATE, PHASE_VALIDATE};
+ return tend_zoo(fid, base_path, config, phase, NELMTS(phase));
+}
/*-------------------------------------------------------------------------
* Function: validate_zoo
@@ -3307,9 +2793,7 @@ create_zoo(hid_t fid, const char *base_path, int proc_num)
* Purpose: Given the path to a group in which a "zoo" has been
* constructed, validate the objects in the "zoo".
*
- * If pass is false on entry, do nothing.
- *
- * If an error is detected, set pass to FALSE, and set
+ * If an error is detected, return false, and set
* failure_mssg to point to an appropriate error message.
*
* This function was initially created to assist in testing
@@ -3318,134 +2802,31 @@ create_zoo(hid_t fid, const char *base_path, int proc_num)
* on disk structures that can occur with this version of
* the superblock.
*
- * Note the associated validate_zoo() function.
- *
- * Return: void
- *
- * Programmer: John Mainzer
- * 9/14/15
- *
+ * Note the associated create_zoo() function.
*-------------------------------------------------------------------------
*/
-void
-validate_zoo(hid_t fid, const char *base_path, int proc_num)
+bool
+validate_zoo(hid_t fid, const char *base_path, zoo_config_t config)
{
- char full_path[1024];
+ const phase_t phase[] = {PHASE_VALIDATE};
+
+ return tend_zoo(fid, base_path, config, phase, NELMTS(phase));
+}
+
+bool
+delete_zoo(hid_t fid, const char *base_path, zoo_config_t config)
+{
+ const phase_t phase[] = {PHASE_DELETE};
+
+ return tend_zoo(fid, base_path, config, phase, NELMTS(phase));
+}
+
+bool
+validate_deleted_zoo(hid_t fid, const char *base_path, zoo_config_t config)
+{
+ const phase_t phase[] = {PHASE_VALIDATE_DELETION};
- HDassert(base_path);
-
- /* validate an empty "new style" group */
- if ( pass ) {
- HDsprintf(full_path, "%s/A", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- vrfy_ns_grp_0(fid, full_path);
- }
-
- /* validate a compact "new style" group (3 link messages) */
- if ( pass ) {
- HDsprintf(full_path, "%s/B", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- vrfy_ns_grp_c(fid, full_path, 3);
- }
-
- /* validate a dense "new style" group (w/300 links, in v2 B-tree &
- * fractal heap)
- */
- if ( pass ) {
- HDsprintf(full_path, "%s/C", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- vrfy_ns_grp_d(fid, full_path, 300);
- }
-
- /* validate an empty "old style" group in file */
- if ( pass ) {
- HDsprintf(full_path, "%s/D", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- vrfy_os_grp_0(fid, full_path);
- }
-
- /* validate an "old style" group (w/300 links, in v1 B-tree &
- * local heap)
- */
- if ( pass ) {
- HDsprintf(full_path, "%s/E", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- vrfy_os_grp_n(fid, full_path, proc_num, 300);
- }
-
- /* validate a contiguous dataset w/integer datatype (but no data)
- * in file.
- */
- if ( pass ) {
- HDsprintf(full_path, "%s/F", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- vrfy_ds_ctg_i(fid, full_path, FALSE);
- }
-
- /* validate a contiguous dataset w/integer datatype (with data)
- * in file.
- */
- if ( pass ) {
- HDsprintf(full_path, "%s/G", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- vrfy_ds_ctg_i(fid, full_path, TRUE);
- }
-
- /* validate a chunked dataset w/integer datatype (but no data)
- * in file
- */
- if ( pass ) {
- HDsprintf(full_path, "%s/H", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- vrfy_ds_chk_i(fid, full_path, FALSE);
- }
-
- /* validate a chunked dataset w/integer datatype (and data)
- * in file
- */
- if ( pass ) {
- HDsprintf(full_path, "%s/I", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- vrfy_ds_chk_i(fid, full_path, TRUE);
- }
-
- /* Validate a compact dataset w/integer datatype (but no data)
- * in file
- */
- if ( pass ) {
- HDsprintf(full_path, "%s/J", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- vrfy_ds_cpt_i(fid, full_path, FALSE);
- }
-
- /* validate a compact dataset w/integer datatype (and data)
- * in file
- */
- if ( pass ) {
- HDsprintf(full_path, "%s/K", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- vrfy_ds_cpt_i(fid, full_path, TRUE);
- }
-
- /* validate a contiguous dataset w/variable-length datatype
- * (but no data) to file
- */
- if ( pass ) {
- HDsprintf(full_path, "%s/L", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- vrfy_ds_ctg_v(fid, full_path, FALSE);
- }
-
- /* validate a contiguous dataset w/variable-length datatype
- * (and data) to file
- */
- if ( pass ) {
- HDsprintf(full_path, "%s/M", base_path);
- HDassert(HDstrlen(full_path) < 1024);
- vrfy_ds_ctg_v(fid, full_path, TRUE);
- }
-
- return;
-} /* validate_zoo() */
+ return tend_zoo(fid, base_path, config, phase, NELMTS(phase));
+}
diff --git a/test/genall5.h b/test/genall5.h
index 20141de..a03ccce 100644
--- a/test/genall5.h
+++ b/test/genall5.h
@@ -11,41 +11,54 @@
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-/* Programmer: John Mainzer
- * 9/4/15
- *
- * This file contains declarations of all functions defined
- * in genall5.c
+/*
+ * This file contains declarations of all functions defined in genall5.c
*/
-void create_zoo(hid_t fid, const char *base_path, int proc_num);
-void validate_zoo(hid_t fid, const char *base_path, int proc_num);
+typedef struct _zoo_config {
+ int proc_num;
+ bool continue_on_failure;
+ bool skip_compact;
+ bool skip_varlen;
+ unsigned max_pause_msecs;
+} zoo_config_t;
-void ns_grp_0(hid_t fid, const char *group_name);
-void vrfy_ns_grp_0(hid_t fid, const char *group_name);
+bool create_zoo(hid_t, const char *, zoo_config_t);
+bool validate_zoo(hid_t, const char *, zoo_config_t);
+bool delete_zoo(hid_t, const char *, zoo_config_t);
+bool validate_deleted_zoo(hid_t, const char *, zoo_config_t);
-void ns_grp_c(hid_t fid, const char *group_name, unsigned nlinks);
-void vrfy_ns_grp_c(hid_t fid, const char *group_name, unsigned nlinks);
+bool ns_grp_0(hid_t fid, const char *group_name);
+bool vrfy_ns_grp_0(hid_t fid, const char *group_name);
-void ns_grp_d(hid_t fid, const char *group_name, unsigned nlinks);
-void vrfy_ns_grp_d(hid_t fid, const char *group_name, unsigned nlinks);
+bool ns_grp_c(hid_t fid, const char *group_name, unsigned nlinks);
+bool vrfy_ns_grp_c(hid_t fid, const char *group_name, unsigned nlinks);
-void os_grp_0(hid_t fid, const char *group_name);
-void vrfy_os_grp_0(hid_t fid, const char *group_name);
+bool ns_grp_d(hid_t fid, const char *group_name, unsigned nlinks);
+bool vrfy_ns_grp_d(hid_t fid, const char *group_name, unsigned nlinks);
-void os_grp_n(hid_t fid, const char *group_name, int proc_num, unsigned nlinks);
-void vrfy_os_grp_n(hid_t fid, const char *group_name, int proc_num,
+bool os_grp_0(hid_t fid, const char *group_name);
+bool vrfy_os_grp_0(hid_t fid, const char *group_name);
+
+bool os_grp_n(hid_t fid, const char *group_name, int proc_num, unsigned nlinks);
+bool vrfy_os_grp_n(hid_t fid, const char *group_name, int proc_num,
unsigned nlinks);
-void ds_ctg_i(hid_t fid, const char *dset_name, hbool_t write_data);
-void vrfy_ds_ctg_i(hid_t fid, const char *dset_name, hbool_t write_data);
+bool ds_ctg_i(hid_t fid, const char *dset_name, hbool_t write_data);
+bool vrfy_ds_ctg_i(hid_t fid, const char *dset_name, hbool_t write_data);
-void ds_chk_i(hid_t fid, const char *dset_name, hbool_t write_data);
-void vrfy_ds_chk_i(hid_t fid, const char *dset_name, hbool_t write_data);
+bool ds_chk_i(hid_t fid, const char *dset_name, hbool_t write_data);
+bool vrfy_ds_chk_i(hid_t fid, const char *dset_name, hbool_t write_data);
-void ds_cpt_i(hid_t fid, const char *dset_name, hbool_t write_data);
-void vrfy_ds_cpt_i(hid_t fid, const char *dset_name, hbool_t write_data);
+bool ds_cpt_i(hid_t fid, const char *dset_name, hbool_t write_data);
+bool vrfy_ds_cpt_i(hid_t fid, const char *dset_name, hbool_t write_data);
-void ds_ctg_v(hid_t fid, const char *dset_name, hbool_t write_data);
-void vrfy_ds_ctg_v(hid_t fid, const char *dset_name, hbool_t write_data);
+bool ds_ctg_v(hid_t fid, const char *dset_name, hbool_t write_data);
+bool vrfy_ds_ctg_v(hid_t fid, const char *dset_name, hbool_t write_data);
+/* Individual tests can override zoo_create_hook(), which is called
+ * after each step of create_zoo(). The `hid_t` argument identifies
+ * the file where the step was performed. The test library provides a
+ * default implementation of zoo_create_hook() that does nothing.
+ */
+void zoo_create_hook(hid_t);
diff --git a/test/h5test.c b/test/h5test.c
index 1b445dd..a13babc 100644
--- a/test/h5test.c
+++ b/test/h5test.c
@@ -150,7 +150,18 @@ h5_errors(hid_t estack, void H5_ATTR_UNUSED *client_data)
return 0;
}
-
+void
+h5_testing(const char *fmt, ...)
+{
+ va_list ap;
+ char buf[62 + 1]; /* room for 62-char field + NUL */
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+ printf("Testing %s", buf);
+ fflush(stdout);
+}
+
/*-------------------------------------------------------------------------
* Function: h5_clean_files
*
@@ -1941,6 +1952,7 @@ static const H5FD_class_t H5FD_dummy_g = {
NULL, /* truncate */
NULL, /* lock */
NULL, /* unlock */
+ NULL, /* dedup */
H5FD_FLMAP_DICHOTOMY /* fl_map */
};
diff --git a/test/h5test.h b/test/h5test.h
index 3eeb1f8..6a7ae85 100644
--- a/test/h5test.h
+++ b/test/h5test.h
@@ -101,7 +101,7 @@ H5TEST_DLLVAR MPI_Info h5_io_info_g; /* MPI INFO object for IO */
* spaces. If the h5_errors() is used for automatic error handling then
* the H5_FAILED() macro is invoked automatically when an API function fails.
*/
-#define TESTING(WHAT) {HDprintf("Testing %-62s",WHAT); HDfflush(stdout);}
+#define TESTING(...) h5_testing(__VA_ARGS__);
#define TESTING_2(WHAT) {HDprintf(" Testing %-60s",WHAT); HDfflush(stdout);}
#define PASSED() do {HDputs(" PASSED");HDfflush(stdout);} while (0)
#define H5_FAILED() {HDputs("*FAILED*");HDfflush(stdout);}
@@ -113,6 +113,7 @@ H5TEST_DLLVAR MPI_Info h5_io_info_g; /* MPI INFO object for IO */
#define FAIL_STACK_ERROR {H5_FAILED(); AT(); H5Eprint2(H5E_DEFAULT, stdout); \
goto error;}
#define FAIL_PUTS_ERROR(s) {H5_FAILED(); AT(); HDputs(s); goto error;}
+#define FAIL_PRINTF_ERROR(fmt, ...) {H5_FAILED(); AT(); HDprintf(fmt, __VA_ARGS__); goto error;}
/*
* Alarm definitions to wait up (terminate) a test that runs too long.
@@ -189,6 +190,7 @@ extern "C" {
#endif
/* Generally useful testing routines */
+H5TEST_DLL void h5_testing(const char *, ...) H5_ATTR_FORMAT(printf, 1, 2);
H5TEST_DLL void h5_clean_files(const char *base_name[], hid_t fapl);
H5TEST_DLL int h5_cleanup(const char *base_name[], hid_t fapl);
H5TEST_DLL char *h5_fixname(const char *base_name, hid_t fapl, char *fullname, size_t size);
diff --git a/test/hyperslab.c b/test/hyperslab.c
index e702023..4c84868 100644
--- a/test/hyperslab.c
+++ b/test/hyperslab.c
@@ -1051,8 +1051,7 @@ test_array_fill(size_t lo, size_t hi)
size_t u, v, w; /* Local index variables */
char s[256];
- HDsprintf(s, "array filling %4lu-%-4lu elements", (unsigned long)lo,(unsigned long)hi);
- TESTING(s);
+ TESTING("array filling %4zu-%-4zu elements", lo, hi);
/* Initialize */
if(NULL == (dst = (int *)HDcalloc(sizeof(int),ARRAY_FILL_SIZE * hi)))
@@ -1116,8 +1115,7 @@ test_array_offset_n_calc(size_t n, size_t x, size_t y, size_t z)
hsize_t new_coords[ARRAY_OFFSET_NDIMS]; /* X, Y & X coordinates of offset */
char s[256];
- HDsprintf(s, "array offset %4lux%4lux%4lu elements", (unsigned long)z,(unsigned long)y,(unsigned long)x);
- TESTING(s);
+ TESTING("array offset %4zux%4zux%4zu elements", z, y, x);
/* Initialize */
if(NULL == (a = (hsize_t *)HDmalloc(sizeof(hsize_t) * x * y *z)))
diff --git a/test/istore.c b/test/istore.c
index c8fe866..be6949e 100644
--- a/test/istore.c
+++ b/test/istore.c
@@ -280,8 +280,7 @@ test_extend(hid_t f, const char *prefix,
(unsigned long) nx, (unsigned long) ny, (unsigned long) nz);
}
- HDsprintf(s, "istore extend: %s", dims);
- TESTING(s);
+ TESTING("istore extend: %s", dims);
buf = (uint8_t *)HDmalloc(nx * ny * nz);
check = (uint8_t *)HDmalloc(nx * ny * nz);
whole = (uint8_t *)HDcalloc((size_t)1, nx * ny * nz);
@@ -493,8 +492,7 @@ test_sparse(hid_t f, const char *prefix, size_t nblocks,
(unsigned long) nx, (unsigned long) ny, (unsigned long) nz);
}
- HDsprintf(s, "istore sparse: %s", dims);
- TESTING(s);
+ TESTING("istore sparse: %s", dims);
if(skip_test){
SKIPPED()
return SUCCEED;
diff --git a/test/page_buffer.c b/test/page_buffer.c
index a508dc9..6b6de02 100644
--- a/test/page_buffer.c
+++ b/test/page_buffer.c
@@ -19,6 +19,9 @@
*
*************************************************************/
+#include <err.h>
+#include <libgen.h>
+
#include "h5test.h"
#include "H5CXprivate.h" /* API Contexts */
@@ -39,30 +42,156 @@
#define FILENAME_LEN 1024
+#ifndef H5_HAVE_PARALLEL
+#define NUM_DSETS 5
+#define NX 100
+#define NY 50
+#endif
+
+/* helper routines */
+#ifndef H5_HAVE_PARALLEL
+static unsigned create_file(char *filename, hid_t fcpl, hid_t fapl);
+static unsigned open_file(char *filename, hid_t fapl, hsize_t page_size, size_t page_buffer_size);
+#endif /* H5_HAVE_PARALLEL */
+
/* test routines */
#ifdef H5_HAVE_PARALLEL
static unsigned verify_page_buffering_disabled(hid_t orig_fapl,
const char *env_h5_drvr);
#else
-#define NUM_DSETS 5
-#define NX 100
-#define NY 50
-
static unsigned test_args(hid_t fapl, const char *env_h5_drvr);
-static unsigned test_raw_data_handling(hid_t orig_fapl, const char *env_h5_drvr);
+static unsigned test_raw_data_handling(hid_t orig_fapl, const char *env_h5_drvr,
+ bool);
static unsigned test_lru_processing(hid_t orig_fapl, const char *env_h5_drvr);
static unsigned test_min_threshold(hid_t orig_fapl, const char *env_h5_drvr);
static unsigned test_stats_collection(hid_t orig_fapl, const char *env_h5_drvr);
-
-/* helper routines */
-static unsigned create_file(char *filename, hid_t fcpl, hid_t fapl);
-static unsigned open_file(char *filename, hid_t fapl, hsize_t page_size, size_t page_buffer_size);
#endif /* H5_HAVE_PARALLEL */
-const char *FILENAME[] = {
- "filepaged",
- NULL
-};
+#define FILENAME "filepaged"
+static const char *namebases[] = {FILENAME, NULL};
+static const char *namebase = FILENAME;
+
+static hid_t
+paging_fcpl_create(const hsize_t pgsz)
+{
+ hid_t fcpl = H5I_INVALID_HID;
+
+ if ((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0)
+ goto error;
+ if (H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, 0, 1) < 0)
+ goto error;
+ if (H5Pset_file_space_page_size(fcpl, pgsz) < 0)
+ goto error;
+
+ return fcpl;
+error:
+ if (fcpl != H5I_INVALID_HID)
+ H5Pclose(fcpl);
+ return H5I_INVALID_HID;
+}
+
+static struct timespec
+print_elapsed_time(const struct timespec H5_ATTR_UNUSED *lastp,
+ const char H5_ATTR_UNUSED *fn, int H5_ATTR_UNUSED ln)
+{
+#if 0
+ uint64_t elapsed_ns;
+ struct timespec diff, now, last;
+#endif
+ struct timespec now;
+
+ if (clock_gettime(CLOCK_MONOTONIC, &now) == -1)
+ err(EXIT_FAILURE, "%s: clock_gettime", __func__);
+
+#if 0
+ last = (lastp == NULL) ? now : *lastp;
+
+ timespecsub(&now, &last, &diff);
+
+ elapsed_ns = (uint64_t)diff.tv_sec * (uint64_t)1000000000 + diff.tv_nsec;
+
+ printf("%5" PRIu64 ".%03" PRIu64 " %s.%d\n",
+ elapsed_ns / 1000000000, (elapsed_ns / 1000000) % 1000, fn, ln);
+#endif
+
+ return now;
+}
+
+static int
+swmr_fapl_augment(hid_t fapl, const char *filename, uint32_t max_lag)
+{
+ H5F_vfd_swmr_config_t config = {
+ .version = H5F__CURR_VFD_SWMR_CONFIG_VERSION
+ , .tick_len = 4
+ , .max_lag = max_lag
+ , .writer = true
+ , .md_pages_reserved = 128
+ };
+ const char *dname;
+ char *tname;
+
+ if ((tname = strdup(filename)) == NULL) {
+ HDfprintf(stderr, "temporary string allocation failed\n");
+ return -1;
+ }
+ dname = dirname(tname);
+ snprintf(config.md_file_path, sizeof(config.md_file_path),
+ "%s/my_md_file", dname);
+ free(tname);
+
+ /* Enable VFD SWMR configuration */
+ if(H5Pset_vfd_swmr_config(fapl, &config) < 0) {
+ HDfprintf(stderr, "H5Pset_vrd_swmr_config failed\n");
+ return -1;
+ }
+ return 0;
+}
+
+static bool
+pgbuf_read_each_equals(H5F_t *f, H5FD_mem_t ty, haddr_t addr, size_t nelts,
+ int *data, int val)
+{
+ size_t i;
+
+ /* Read all elements using the VFD. */
+ if (H5F_block_read(f, ty, addr, sizeof(int) * nelts, data) < 0)
+ FAIL_STACK_ERROR;
+
+ for (i = 0; i < nelts; i++) {
+ if (data[i] != val) {
+ printf("%s: read %d at data[%zu], expected %d\n", __func__,
+ data[i], i, val);
+ return false;
+ }
+ }
+ return true;
+error:
+ return false;
+}
+
+static bool
+vfd_read_each_equals(H5F_t *f, H5FD_mem_t ty, haddr_t addr, size_t nelts,
+ int *data, int val)
+{
+ size_t i;
+
+ /* Read all elements using the VFD. */
+ if (H5FD_read(f->shared->lf, ty, addr, sizeof(int) * nelts, data) < 0)
+ FAIL_STACK_ERROR;
+
+ for (i = 0; i < nelts; i++) {
+ if (data[i] != val) {
+#if 0
+ printf("%s: read %d at data[%d], expected %d\n", __func__,
+ data[i], i, val);
+#endif
+ return false;
+ }
+ }
+ return true;
+error:
+ return false;
+}
#ifndef H5_HAVE_PARALLEL
@@ -204,7 +333,7 @@ error:
HDfree(data);
} H5E_END_TRY;
return(1);
-} /* create_file */
+}
/*-------------------------------------------------------------------------
@@ -248,11 +377,11 @@ open_file(char *filename, hid_t fapl, hsize_t page_size,
if(NULL == (f = (H5F_t *)H5VL_object(file_id)))
FAIL_STACK_ERROR;
- if(f->shared->page_buf == NULL)
+ if(f->shared->pb_ptr == NULL)
FAIL_STACK_ERROR;
- if(f->shared->page_buf->page_size != page_size)
+ if(f->shared->pb_ptr->page_size != page_size)
FAIL_STACK_ERROR;
- if(f->shared->page_buf->max_size != page_buffer_size)
+ if(f->shared->pb_ptr->max_size != page_buffer_size)
FAIL_STACK_ERROR;
if((grp_id = H5Gopen2(file_id, "GROUP", H5P_DEFAULT)) < 0)
@@ -342,7 +471,7 @@ set_multi_split(const char *env_h5_drvr, hid_t fapl, hsize_t pagesize)
/* Set memb_addr aligned */
for(mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt++)
memb_addr[mt] = ((memb_addr[mt] + pagesize - 1) / pagesize) * pagesize;
- } /* end else */
+ }
/* Set multi driver with new FAPLs */
if(H5Pset_fapl_multi(fapl, memb_map, memb_fapl_arr, (const char * const *)memb_name, memb_addr, relax) < 0)
@@ -352,14 +481,14 @@ set_multi_split(const char *env_h5_drvr, hid_t fapl, hsize_t pagesize)
for(mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt++)
free(memb_name[mt]);
- } /* end if */
+ }
return 0;
error:
return 1;
-} /* set_multi_split() */
+}
#ifndef H5_HAVE_PARALLEL
@@ -382,6 +511,10 @@ error:
* Programmer: unknown
* ?? / ?? / ??
*
+ * Changes: Minor updates to adapt to new implementation of page
+ * buffer.
+ * JRM -- 10//26/18
+ *
*-------------------------------------------------------------------------
*/
@@ -396,7 +529,7 @@ test_args(hid_t orig_fapl, const char *env_h5_drvr)
TESTING("Settings for Page Buffering");
- h5_fixname(FILENAME[0], orig_fapl, filename, sizeof(filename));
+ h5_fixname(namebase, orig_fapl, filename, sizeof(filename));
if((fapl = H5Pcopy(orig_fapl)) < 0) TEST_ERROR
@@ -421,7 +554,7 @@ test_args(hid_t orig_fapl, const char *env_h5_drvr)
/* Test setting a page buffer with a size smaller than a single
* page size - should fail
*/
- if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, 0, (hsize_t)1) < 0)
+ if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, 0, 1) < 0)
TEST_ERROR;
if(H5Pset_file_space_page_size(fcpl, 512) < 0)
@@ -452,7 +585,7 @@ test_args(hid_t orig_fapl, const char *env_h5_drvr)
TEST_ERROR;
/* Test setting a page buffer with a size equal to a single page size */
- if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, 0, (hsize_t)1) < 0)
+ if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, 0, 1) < 0)
TEST_ERROR;
if(H5Pset_file_space_page_size(fcpl, 512) < 0)
@@ -471,7 +604,7 @@ test_args(hid_t orig_fapl, const char *env_h5_drvr)
/* Test setting a page buffer with a size slightly larger than a
* single page size
*/
- if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, 0, (hsize_t)1) < 0)
+ if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, 0, 1) < 0)
TEST_ERROR;
if(H5Pset_file_space_page_size(fcpl, 512) < 0)
@@ -491,7 +624,7 @@ test_args(hid_t orig_fapl, const char *env_h5_drvr)
/* Test setting a large page buffer size and page size */
- if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, 0, (hsize_t)1) < 0)
+ if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, 0, 1) < 0)
TEST_ERROR;
if(H5Pset_file_space_page_size(fcpl, 4194304) < 0)
@@ -511,7 +644,7 @@ test_args(hid_t orig_fapl, const char *env_h5_drvr)
/* Test setting a 512 byte page buffer size and page size */
- if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, 0, (hsize_t)1) < 0)
+ if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, 0, 1) < 0)
TEST_ERROR;
if(H5Pset_file_space_page_size(fcpl, 512) < 0)
@@ -541,20 +674,495 @@ error:
} /* test_args */
-/*-------------------------------------------------------------------------
+/*
+ * Function: test_mpmde_delay_basic()
+ *
+ * Purpose: Check that a multi-page metadata entry
+ * (MPMDE) is not written immediately to the HDF5 file in
+ * VFD SWMR mode, but it is buffered in the shadow file
+ * until max_lag + 1 ticks have elapsed. Furthermore,
+ * check that it appears *immediately* after max_lag + 1
+ * ticks, since the LRU list does not hold onto MPMDEs.
+ *
+ * Return: 0 if test is sucessful
+ * 1 if test fails
+ *
+ * Programmer: David Young
+ * 16 Sep 2019
+ */
+static unsigned
+test_mpmde_delay_basic(hid_t orig_fapl, const char *env_h5_drvr)
+{
+ char filename[FILENAME_LEN]; /* Filename to use */
+ hid_t file_id = -1; /* File ID */
+ hid_t fcpl = -1;
+ hid_t fapl = -1;
+ size_t i, num_elements = 2000;
+ int *data = NULL, *odata = NULL;
+ H5F_t *f;
+ const uint32_t max_lag = 5;
+ hsize_t pgsz = sizeof(int) * 200;
+ haddr_t addr;
+
+ TESTING("Multipage Metadata Delay Handling");
+
+ h5_fixname(namebase, orig_fapl, filename, sizeof(filename));
+
+ if ((fapl = H5Pcopy(orig_fapl)) < 0)
+ TEST_ERROR
+
+ if (set_multi_split(env_h5_drvr, fapl, pgsz) != 0)
+ TEST_ERROR;
+
+ if ((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0)
+ TEST_ERROR;
+ if (H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, 0, 1) < 0)
+ TEST_ERROR;
+ if (H5Pset_file_space_page_size(fcpl, pgsz) < 0)
+ TEST_ERROR;
+ if (H5Pset_page_buffer_size(fapl, 10 * pgsz, 0, 0) < 0)
+ TEST_ERROR;
+
+ if (swmr_fapl_augment(fapl, filename, max_lag) < 0)
+ TEST_ERROR;
+
+ if ((file_id = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl, fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Get a pointer to the internal file object */
+ if (NULL == (f = (H5F_t *)H5VL_object(file_id)))
+ FAIL_STACK_ERROR;
+
+ addr = H5MF_alloc(f, H5FD_MEM_BTREE, sizeof(int) * num_elements);
+ /* allocate space for 2000 elements */
+ if (HADDR_UNDEF == addr)
+ FAIL_STACK_ERROR;
+
+ if ((odata = (int *)HDcalloc(num_elements, sizeof(int))) == NULL)
+ TEST_ERROR;
+
+ if ((data = (int *)HDcalloc(num_elements, sizeof(int))) == NULL)
+ TEST_ERROR;
+
+ /* initialize all the elements to have a value of -1 */
+ for(i = 0; i < num_elements; i++)
+ odata[i] = -1;
+
+ if (H5F_block_write(f, H5FD_MEM_BTREE, addr, sizeof(int) * num_elements,
+ odata) < 0)
+ FAIL_STACK_ERROR;
+
+ /* H5Fvfd_swmr_end_tick() processes delayed writes before it increases
+ * the tick number, so it takes `max_lag + 1` times through this loop
+ * for a multi-page metadata write to make it to the HDF5 file.
+ */
+ for (i = 0; i < max_lag + 1; i++) {
+ /* All elements read using the VFD should be 0. */
+ if (!vfd_read_each_equals(f, H5FD_MEM_BTREE, addr, num_elements,
+ data, 0))
+ TEST_ERROR;
+ H5Fvfd_swmr_end_tick(file_id);
+ }
+
+ /* It is not necessary to flush the page buffer because delayed
+ * multi-page metadata buffers are flushed *immediately*
+ * when their delay elapses.
+ *
+ * (If we were waiting for a single-page metadata buffer to
+ * appear at the VFD layer, then it may reside in the LRU queue
+ * for a while.)
+ */
+#if 0
+ if (H5PB_flush(f) < 0)
+ FAIL_STACK_ERROR;
+#endif
+
+ /* All elements read using the VFD should be -1. */
+ if (!vfd_read_each_equals(f, H5FD_MEM_BTREE, addr, num_elements, data, -1))
+ TEST_ERROR;
+
+ if (H5Fclose(file_id) < 0)
+ FAIL_STACK_ERROR;
+ if (H5Pclose(fcpl) < 0)
+ FAIL_STACK_ERROR;
+ if (H5Pclose(fapl) < 0)
+ FAIL_STACK_ERROR;
+ HDfree(data);
+ HDfree(odata);
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ if (fapl != H5I_INVALID_HID)
+ H5Pclose(fapl);
+ if (fcpl != H5I_INVALID_HID)
+ H5Pclose(fcpl);
+ if (file_id != H5I_INVALID_HID)
+ H5Fclose(file_id);
+ if (data != NULL)
+ HDfree(data);
+ if (odata != NULL)
+ HDfree(odata);
+ } H5E_END_TRY;
+ return 1;
+}
+
+
+/*
+ * Function: test_spmde_lru_evict_basic()
+ *
+ * Purpose: Check that once a single-page metadata entry
+ * (SPMDE) is eligible to be written to the HDF5 file
+ * (because it has resided unchanged in the metadata file
+ * for max_lag + 1 ticks), filling the page buffer to
+ * capacity causes the entry to be flushed.
+ *
+ * Further check that the page was evicted by writing
+ * changes to the VFD layer ("under" the page buffer)
+ * and trying to read the changes back through the page
+ * buffer: stale page-buffer content should not shadow
+ * the changes.
+ *
+ * XXX
+ * XXX reduce duplication with test_spmde_delay_basic!
+ * XXX
+ *
+ * Return: 0 if test is sucessful
+ * 1 if test fails
+ *
+ * Programmer: David Young
+ * 16 Sep 2019
+ */
+static unsigned
+test_spmde_lru_evict_basic(hid_t orig_fapl, const char *env_h5_drvr)
+{
+ char filename[FILENAME_LEN]; /* Filename to use */
+ hid_t file_id = -1; /* File ID */
+ hid_t fcpl = -1;
+ hid_t fapl = -1;
+ size_t i, num_elements = 20;
+ int *data = NULL, *odata = NULL;
+ H5F_t *f;
+ const uint32_t max_lag = 5;
+ const hsize_t pgsz = sizeof(int) * 200;
+ const hsize_t pgbufsz = 10 * pgsz;
+ hsize_t ofs;
+ bool flushed;
+ struct timespec last;
+ haddr_t addr;
+ haddr_t pressure;
+
+ TESTING("Single Page Metadata Flush & Eviction Handling");
+
+ h5_fixname(namebase, orig_fapl, filename, sizeof(filename));
+
+ last = print_elapsed_time(NULL, __func__, __LINE__);
+ if ((fapl = H5Pcopy(orig_fapl)) < 0)
+ TEST_ERROR
+
+ if (set_multi_split(env_h5_drvr, fapl, pgsz) != 0)
+ TEST_ERROR;
+
+ if ((fcpl = paging_fcpl_create(pgsz)) < 0)
+ FAIL_STACK_ERROR;
+
+ if (H5Pset_page_buffer_size(fapl, pgbufsz, 0, 0) < 0)
+ FAIL_STACK_ERROR;
+
+ if (swmr_fapl_augment(fapl, filename, max_lag) < 0)
+ FAIL_STACK_ERROR;
+
+ if ((file_id = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl, fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Get a pointer to the internal file object */
+ if (NULL == (f = (H5F_t *)H5VL_object(file_id)))
+ FAIL_STACK_ERROR;
+
+ last = print_elapsed_time(&last, __func__, __LINE__);
+
+ /* Allocate a region whose pages we can write to force eviction of
+ * least-recently used pages.
+ */
+ pressure = H5MF_alloc(f, H5FD_MEM_BTREE, pgbufsz);
+ if (HADDR_UNDEF == pressure)
+ FAIL_STACK_ERROR;
+
+ /* Allocate a whole page for our 20 elements so that they do
+ * not share a "hot" page with something else.
+ */
+ addr = H5MF_alloc(f, H5FD_MEM_BTREE, pgsz);
+ if (HADDR_UNDEF == addr)
+ FAIL_STACK_ERROR;
+
+ if ((odata = (int *)HDcalloc(num_elements, sizeof(int))) == NULL)
+ TEST_ERROR;
+
+ if ((data = (int *)HDcalloc(num_elements, sizeof(int))) == NULL)
+ TEST_ERROR;
+
+ /* initialize all the elements to have a value of -1 */
+ for(i = 0; i < num_elements; i++)
+ odata[i] = -1;
+
+ if (H5F_block_write(f, H5FD_MEM_BTREE, addr, sizeof(int) * num_elements,
+ odata) < 0)
+ FAIL_STACK_ERROR;
+
+ last = print_elapsed_time(&last, __func__, __LINE__);
+
+ /* H5Fvfd_swmr_end_tick() processes delayed writes before it increases
+ * the tick number, so only after `max_lag + 1` times through this loop
+ * is a metadata write eligible to be written to the HDF5 file.
+ */
+ for (i = 0; i < max_lag + 1; i++) {
+ /* All elements read using the VFD should be 0. */
+ if (!vfd_read_each_equals(f, H5FD_MEM_BTREE, addr, num_elements,
+ data, 0))
+ TEST_ERROR;
+ H5Fvfd_swmr_end_tick(file_id);
+ }
+
+ last = print_elapsed_time(&last, __func__, __LINE__);
+
+ flushed = false;
+ /* We are waiting for a single-page metadata buffer to
+ * appear at the VFD layer, but it may reside in the LRU queue.
+ * Dirty new blocks to apply pressure on the page buffer so that
+ * it empties the LRU queue. Writing to N distinct pages,
+ * for N the number of pages in the page buffer, ought to do
+ * the trick.
+ */
+ for (ofs = 0; ofs < pgbufsz - pgsz * 2; ofs += pgsz) {
+ int tmp = -1;
+ if (H5F_block_write(f, H5FD_MEM_BTREE, pressure + ofs,
+ sizeof(tmp), &tmp) < 0)
+ FAIL_STACK_ERROR;
+ if (!flushed &&
+ vfd_read_each_equals(f, H5FD_MEM_BTREE, addr, num_elements,
+ data, -1)) {
+ flushed = true;
+#if 0
+ printf("Writing page %" PRIuHSIZE " flushed target page.\n",
+ ofs / pgsz);
+#endif
+ }
+ }
+
+ last = print_elapsed_time(&last, __func__, __LINE__);
+
+ if (!vfd_read_each_equals(f, H5FD_MEM_BTREE, addr, num_elements, data, -1))
+ TEST_ERROR;
+
+ /* initialize all the elements to have a value of -2 */
+ for(i = 0; i < num_elements; i++)
+ odata[i] = -2;
+ /* Write -2 to our target page using the VFD. */
+ if (H5FD_write(f->shared->lf, H5FD_MEM_BTREE, addr,
+ sizeof(int) * num_elements, odata) < 0)
+ FAIL_STACK_ERROR;
+
+ last = print_elapsed_time(&last, __func__, __LINE__);
+
+ /* All elements read through the page buffer should be -2. That is,
+ * no page-buffer entry should shadow the page.
+ */
+ if (!pgbuf_read_each_equals(f, H5FD_MEM_BTREE, addr, num_elements, data,
+ -2))
+ TEST_ERROR;
+
+ last = print_elapsed_time(&last, __func__, __LINE__);
+
+ /* Force ticks to occur so that H5Fclose() doesn't pause waiting
+ * for them to elapse.
+ */
+ for (i = 0; i < max_lag + 1; i++)
+ H5Fvfd_swmr_end_tick(file_id);
+
+ if (H5Fclose(file_id) < 0)
+ FAIL_STACK_ERROR;
+ if (H5Pclose(fcpl) < 0)
+ FAIL_STACK_ERROR;
+ if (H5Pclose(fapl) < 0)
+ FAIL_STACK_ERROR;
+ HDfree(data);
+ HDfree(odata);
+
+ last = print_elapsed_time(&last, __func__, __LINE__);
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ if (fapl != H5I_INVALID_HID)
+ H5Pclose(fapl);
+ if (fcpl != H5I_INVALID_HID)
+ H5Pclose(fcpl);
+ if (file_id != H5I_INVALID_HID)
+ H5Fclose(file_id);
+ if (data != NULL)
+ HDfree(data);
+ if (odata != NULL)
+ HDfree(odata);
+ } H5E_END_TRY;
+ return 1;
+}
+
+
+/*
+ * Function: test_spmde_delay_basic()
+ *
+ * Purpose: Check that a single-page metadata entry
+ * (SPMDE) is not written immediately to the HDF5 file in
+ * VFD SWMR mode, but it is buffered in the shadow file
+ * until max_lag + 1 ticks have elapsed.
+ *
+ * The LRU list will hold onto SPMDEs, so it's necessary to
+ * flush the page buffer to make sure the buffer is flushed
+ * to the VFD layer.
+ *
+ * XXX
+ * XXX reduce duplication with test_mpmde_delay_basic!
+ * XXX
+ *
+ * Return: 0 if test is sucessful
+ * 1 if test fails
+ *
+ * Programmer: David Young
+ * 16 Sep 2019
+ */
+static unsigned
+test_spmde_delay_basic(hid_t orig_fapl, const char *env_h5_drvr)
+{
+ char filename[FILENAME_LEN]; /* Filename to use */
+ hid_t file_id = -1; /* File ID */
+ hid_t fcpl = -1;
+ hid_t fapl = -1;
+ size_t i, num_elements = 20;
+ int *data = NULL, *odata = NULL;
+ H5F_t *f;
+ const uint32_t max_lag = 5;
+ hsize_t pgsz = sizeof(int) * 200;
+ haddr_t addr;
+
+ TESTING("Single Page Metadata Delay Handling");
+
+ h5_fixname(namebase, orig_fapl, filename, sizeof(filename));
+
+ if ((fapl = H5Pcopy(orig_fapl)) < 0)
+ TEST_ERROR
+
+ if (set_multi_split(env_h5_drvr, fapl, pgsz) != 0)
+ TEST_ERROR;
+
+ if ((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0)
+ TEST_ERROR;
+ if (H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, 0, 1) < 0)
+ TEST_ERROR;
+ if (H5Pset_file_space_page_size(fcpl, pgsz) < 0)
+ TEST_ERROR;
+ if (H5Pset_page_buffer_size(fapl, 10 * pgsz, 0, 0) < 0)
+ TEST_ERROR;
+
+ if (swmr_fapl_augment(fapl, filename, max_lag) < 0)
+ TEST_ERROR;
+
+ if ((file_id = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl, fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Get a pointer to the internal file object */
+ if (NULL == (f = (H5F_t *)H5VL_object(file_id)))
+ FAIL_STACK_ERROR;
+
+ addr = H5MF_alloc(f, H5FD_MEM_BTREE,
+ sizeof(int) * num_elements);
+ /* allocate space for 2000 elements */
+ if (HADDR_UNDEF == addr)
+ FAIL_STACK_ERROR;
+
+ if ((odata = (int *)HDcalloc(num_elements, sizeof(int))) == NULL)
+ TEST_ERROR;
+
+ if ((data = (int *)HDcalloc(num_elements, sizeof(int))) == NULL)
+ TEST_ERROR;
+
+ /* initialize all the elements to have a value of -1 */
+ for(i = 0; i < num_elements; i++)
+ odata[i] = -1;
+
+ if (H5F_block_write(f, H5FD_MEM_BTREE, addr, sizeof(int) * num_elements,
+ odata) < 0)
+ FAIL_STACK_ERROR;
+
+ /* H5Fvfd_swmr_end_tick() processes delayed writes before it increases
+ * the tick number, so only after `max_lag + 1` times through this loop
+ * is a metadata write eligible to be written to the HDF5 file.
+ */
+ for (i = 0; i < max_lag + 1; i++) {
+ /* All elements read using the VFD should be 0. */
+ if (!vfd_read_each_equals(f, H5FD_MEM_BTREE, addr, num_elements,
+ data, 0))
+ TEST_ERROR;
+ H5Fvfd_swmr_end_tick(file_id);
+ }
+
+ /* We are waiting for a single-page metadata buffer to
+ * appear at the VFD layer, but it may reside in the LRU queue
+ * for a while if we do not flush the page buffer.
+ */
+ if (H5PB_flush(f->shared) < 0)
+ FAIL_STACK_ERROR;
+
+ /* All elements read using the VFD should be -1. */
+ if (!vfd_read_each_equals(f, H5FD_MEM_BTREE, addr, num_elements, data, -1))
+ TEST_ERROR;
+
+ if (H5Fclose(file_id) < 0)
+ FAIL_STACK_ERROR;
+ if (H5Pclose(fcpl) < 0)
+ FAIL_STACK_ERROR;
+ if (H5Pclose(fapl) < 0)
+ FAIL_STACK_ERROR;
+ HDfree(data);
+ HDfree(odata);
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ if (fapl != H5I_INVALID_HID)
+ H5Pclose(fapl);
+ if (fcpl != H5I_INVALID_HID)
+ H5Pclose(fcpl);
+ if (file_id != H5I_INVALID_HID)
+ H5Fclose(file_id);
+ if (data != NULL)
+ HDfree(data);
+ if (odata != NULL)
+ HDfree(odata);
+ } H5E_END_TRY;
+ return 1;
+}
+
+
+/*
* Function: test_raw_data_handling()
*
- * Purpose: The purpose of this function appears to be a smoke check
- * of raw data reads and writes via the page buffer.
+ * Purpose: Check that raw data is written to the HDF5
+ * file when expected whether in VFD SWMR mode or not.
*
- * Any data mis-matches or failures reported by the HDF5
- * library result in test failure.
+ * Any data mis-matches or failures reported by the HDF5
+ * library result in test failure.
*
* Return: 0 if test is sucessful
* 1 if test fails
*
- * Programmer: unknown
- * ?? / ?? / ??
+ * Programmer: David Young
+ * 16 Sep 2019
*
* Changes: Added base_page_cnt field as supporting code. This allows
* the test to adjust to the number of page buffer pages
@@ -567,47 +1175,51 @@ error:
*
* JRM -- 2/23/17
*
- *-------------------------------------------------------------------------
+ * Minor changes to adapt to re-implementation of the
+ * page buffer.
+ *
+ * JRM -- 10/26/18
*/
/* Changes due to file space page size has a minimum size of 512 */
static unsigned
-test_raw_data_handling(hid_t orig_fapl, const char *env_h5_drvr)
+test_raw_data_handling(hid_t orig_fapl, const char *env_h5_drvr,
+ bool vfd_swmr_mode)
{
char filename[FILENAME_LEN]; /* Filename to use */
hid_t file_id = -1; /* File ID */
hid_t fcpl = -1;
hid_t fapl = -1;
- size_t base_page_cnt;
- size_t page_count = 0;
+ int64_t base_page_cnt;
+ int64_t page_count = 0;
int i, num_elements = 2000;
haddr_t addr = HADDR_UNDEF;
int *data = NULL;
H5F_t *f = NULL;
+ const uint32_t max_lag = 5;
- TESTING("Raw Data Handling");
+ TESTING("%sRaw Data Handling", vfd_swmr_mode ? "VFD SWMR " : "");
- h5_fixname(FILENAME[0], orig_fapl, filename, sizeof(filename));
+ h5_fixname(namebase, orig_fapl, filename, sizeof(filename));
- if((fapl = H5Pcopy(orig_fapl)) < 0)
+ if ((fapl = H5Pcopy(orig_fapl)) < 0)
TEST_ERROR
- if(set_multi_split(env_h5_drvr, fapl, sizeof(int)*200) != 0)
+ if (set_multi_split(env_h5_drvr, fapl, sizeof(int) * 200) != 0)
TEST_ERROR;
- if((data = (int *)HDcalloc((size_t)num_elements, sizeof(int))) == NULL)
+ if ((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0)
TEST_ERROR;
-
- if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0)
+ if (H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, 0, 1) < 0)
TEST_ERROR;
- if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, 0, (hsize_t)1) < 0)
+ if (H5Pset_file_space_page_size(fcpl, sizeof(int) * 200) < 0)
TEST_ERROR;
- if(H5Pset_file_space_page_size(fcpl, sizeof(int)*200) < 0)
- TEST_ERROR;
- if(H5Pset_page_buffer_size(fapl, sizeof(int)*2000, 0, 0) < 0)
+ if (H5Pset_page_buffer_size(fapl, sizeof(int) * 2000, 0, 0) < 0)
TEST_ERROR;
- if((file_id = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl, fapl)) < 0)
+ if (vfd_swmr_mode && swmr_fapl_augment(fapl, filename, max_lag) < 0)
+ TEST_ERROR;
+ if ((file_id = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl, fapl)) < 0)
FAIL_STACK_ERROR;
/* Get a pointer to the internal file object */
@@ -616,129 +1228,139 @@ test_raw_data_handling(hid_t orig_fapl, const char *env_h5_drvr)
/* opening the file inserts one or more pages into the page buffer.
* Get the number of pages inserted, and verify that it is the
- * the expected value.
+ * expected value.
*/
- base_page_cnt = H5SL_count(f->shared->page_buf->slist_ptr);
- if(base_page_cnt != 1)
+ base_page_cnt = f->shared->pb_ptr->curr_pages;
+ if (base_page_cnt != 2)
TEST_ERROR;
- /* allocate space for a 2000 elements */
- if(HADDR_UNDEF == (addr = H5MF_alloc(f, H5FD_MEM_DRAW, sizeof(int)*(size_t)num_elements)))
+ /* allocate space for 2000 elements */
+ if (HADDR_UNDEF == (addr = H5MF_alloc(f, H5FD_MEM_DRAW, sizeof(int) * (size_t)num_elements)))
FAIL_STACK_ERROR;
+ if ((data = (int *)HDcalloc((size_t)num_elements, sizeof(int))) == NULL)
+ TEST_ERROR;
+
/* initialize all the elements to have a value of -1 */
for(i=0 ; i<num_elements ; i++)
data[i] = -1;
- if(H5F_block_write(f, H5FD_MEM_DRAW, addr, sizeof(int)*(size_t)num_elements, data) < 0)
+ if (H5F_block_write(f, H5FD_MEM_DRAW, addr, sizeof(int) * (size_t)num_elements, data) < 0)
FAIL_STACK_ERROR;
- /* update the first 50 elements to have values 0-49 - this will be
+ /* update the first 100 elements to have values 0-99 - this will be
a page buffer update with 1 page resulting in the page
buffer. */
- /* Changes: 100 */
for(i=0 ; i<100 ; i++)
data[i] = i;
- if(H5F_block_write(f, H5FD_MEM_DRAW, addr, sizeof(int)*100, data) < 0)
+ if (H5F_block_write(f, H5FD_MEM_DRAW, addr, sizeof(int) * 100, data) < 0)
FAIL_STACK_ERROR;
page_count ++;
- if(H5SL_count(f->shared->page_buf->slist_ptr) != page_count + base_page_cnt)
+ if (f->shared->pb_ptr->curr_pages != page_count + base_page_cnt)
FAIL_STACK_ERROR;
/* update elements 300 - 450, with values 300 - - this will
bring two more pages into the page buffer. */
for(i=0 ; i<150 ; i++)
data[i] = i+300;
- if(H5F_block_write(f, H5FD_MEM_DRAW, addr+(sizeof(int)*300), sizeof(int)*150, data) < 0)
+ if (H5F_block_write(f, H5FD_MEM_DRAW, addr + (sizeof(int) * 300), sizeof(int) * 150, data) < 0)
FAIL_STACK_ERROR;
page_count += 2;
- if(H5SL_count(f->shared->page_buf->slist_ptr) != page_count + base_page_cnt)
+ if (f->shared->pb_ptr->curr_pages != page_count + base_page_cnt)
FAIL_STACK_ERROR;
/* update elements 100 - 300, this will go to disk but also update
existing pages in the page buffer. */
for(i=0 ; i<200 ; i++)
data[i] = i+100;
- if(H5F_block_write(f, H5FD_MEM_DRAW, addr+(sizeof(int)*100), sizeof(int)*200, data) < 0)
+ if (H5F_block_write(f, H5FD_MEM_DRAW, addr + (sizeof(int) * 100), sizeof(int) * 200, data) < 0)
FAIL_STACK_ERROR;
- if(H5SL_count(f->shared->page_buf->slist_ptr) != page_count + base_page_cnt)
+ if (f->shared->pb_ptr->curr_pages != page_count + base_page_cnt)
FAIL_STACK_ERROR;
/* Update elements 225-300 - this will update an existing page in the PB */
/* Changes: 450 - 600; 150 */
for(i=0 ; i<150 ; i++)
data[i] = i+450;
- if(H5F_block_write(f, H5FD_MEM_DRAW, addr+(sizeof(int)*450), sizeof(int)*150, data) < 0)
+ if (H5F_block_write(f, H5FD_MEM_DRAW, addr + (sizeof(int) * 450), sizeof(int) * 150, data) < 0)
FAIL_STACK_ERROR;
- if(H5SL_count(f->shared->page_buf->slist_ptr) != page_count + base_page_cnt)
+ if (f->shared->pb_ptr->curr_pages != page_count + base_page_cnt)
FAIL_STACK_ERROR;
/* Do a full page write to block 600-800 - should bypass the PB */
for(i=0 ; i<200 ; i++)
data[i] = i+600;
- if(H5F_block_write(f, H5FD_MEM_DRAW, addr+(sizeof(int)*600), sizeof(int)*200, data) < 0)
+ if (H5F_block_write(f, H5FD_MEM_DRAW, addr + (sizeof(int) * 600), sizeof(int) * 200, data) < 0)
FAIL_STACK_ERROR;
- if(H5SL_count(f->shared->page_buf->slist_ptr) != page_count + base_page_cnt)
+ if (f->shared->pb_ptr->curr_pages != page_count + base_page_cnt)
FAIL_STACK_ERROR;
/* read elements 800 - 1200, this should not affect the PB, and should read -1s */
- if(H5F_block_read(f, H5FD_MEM_DRAW, addr+(sizeof(int)*800), sizeof(int)*400, data) < 0)
+ if (H5F_block_read(f, H5FD_MEM_DRAW, addr + (sizeof(int) * 800), sizeof(int) * 400, data) < 0)
FAIL_STACK_ERROR;
for (i=0; i < 400; i++) {
- if(data[i] != -1) {
+ if (data[i] != -1) {
HDfprintf(stderr, "Read different values than written\n");
+ HDfprintf(stderr, "data[%d] = %d, %d expected.\n", i, data[i], -1);
FAIL_STACK_ERROR;
}
}
- if(H5SL_count(f->shared->page_buf->slist_ptr) != page_count + base_page_cnt)
+ if (f->shared->pb_ptr->curr_pages != page_count + base_page_cnt)
FAIL_STACK_ERROR;
/* read elements 1200 - 1201, this should read -1 and bring in an
* entire page of addr 1200
*/
- if(H5F_block_read(f, H5FD_MEM_DRAW, addr+(sizeof(int)*1200), sizeof(int)*1, data) < 0)
+ if (H5F_block_read(f, H5FD_MEM_DRAW, addr + (sizeof(int) * 1200), sizeof(int) * 1, data) < 0)
FAIL_STACK_ERROR;
for (i=0; i < 1; i++) {
- if(data[i] != -1) {
+ if (data[i] != -1) {
HDfprintf(stderr, "Read different values than written\n");
+ HDfprintf(stderr, "data[%d] = %d, %d expected.\n", i, data[i], -1);
TEST_ERROR;
}
}
page_count ++;
- if(H5SL_count(f->shared->page_buf->slist_ptr) != page_count + base_page_cnt)
+ if (f->shared->pb_ptr->curr_pages != page_count + base_page_cnt)
TEST_ERROR;
/* read elements 175 - 225, this should use the PB existing pages */
/* Changes: 350 - 450 */
/* read elements 175 - 225, this should use the PB existing pages */
- if(H5F_block_read(f, H5FD_MEM_DRAW, addr+(sizeof(int)*350), sizeof(int)*100, data) < 0)
+ if (H5F_block_read(f, H5FD_MEM_DRAW, addr + (sizeof(int) * 350), sizeof(int) * 100, data) < 0)
FAIL_STACK_ERROR;
for (i=0; i < 100; i++) {
- if(data[i] != i+350) {
+ if (data[i] != i + 350) {
HDfprintf(stderr, "Read different values than written\n");
+ HDfprintf(stderr, "data[%d] = %d, %d expected.\n", i, data[i],
+ i + 350);
TEST_ERROR;
}
}
- if(H5SL_count(f->shared->page_buf->slist_ptr) != page_count + base_page_cnt)
+ if (f->shared->pb_ptr->curr_pages != page_count + base_page_cnt)
TEST_ERROR;
/* read elements 0 - 800 using the VFD.. this should result in -1s
except for the writes that went through the PB (100-300 & 600-800) */
- if(H5FD_read(f->shared->lf, H5FD_MEM_DRAW, addr, sizeof(int)*800, data) < 0)
+ if (H5FD_read(f->shared->lf, H5FD_MEM_DRAW, addr, sizeof(int) * 800, data) < 0)
FAIL_STACK_ERROR;
i = 0;
while (i < 800) {
- if((i>=100 && i<300) || (i>=600)) {
- if(data[i] != i) {
+ if((i>=100 && i<300) || i >= 600) {
+ if (data[i] != i) {
HDfprintf(stderr, "Read different values than written\n");
+ HDfprintf(stderr, "data[%d] = %d, %d expected.\n",
+ i, data[i], i);
TEST_ERROR;
}
}
else {
- if(data[i] != -1) {
+ if (data[i] != -1) {
HDfprintf(stderr, "Read different values than written\n");
+ HDfprintf(stderr, "data[%d] = %d, %d expected.\n",
+ i, data[i], -1);
TEST_ERROR;
}
}
@@ -748,13 +1370,15 @@ test_raw_data_handling(hid_t orig_fapl, const char *env_h5_drvr)
/* read elements 0 - 800 using the PB.. this should result in all
* what we have written so far and should get the updates from the PB
*/
- if(H5F_block_read(f, H5FD_MEM_DRAW, addr, sizeof(int)*800, data) < 0)
+ if (H5F_block_read(f, H5FD_MEM_DRAW, addr, sizeof(int) * 800, data) < 0)
FAIL_STACK_ERROR;
- if(H5SL_count(f->shared->page_buf->slist_ptr) != page_count + base_page_cnt)
+ if (f->shared->pb_ptr->curr_pages != page_count + base_page_cnt)
TEST_ERROR;
for (i=0; i < 800; i++) {
- if(data[i] != i) {
+ if (data[i] != i) {
HDfprintf(stderr, "Read different values than written\n");
+ HDfprintf(stderr, "data[%d] = %d, %d expected.\n",
+ i, data[i], i);
TEST_ERROR;
}
}
@@ -765,41 +1389,45 @@ test_raw_data_handling(hid_t orig_fapl, const char *env_h5_drvr)
*/
for(i=0 ; i<1000 ; i++)
data[i] = 0;
- if(H5F_block_write(f, H5FD_MEM_DRAW, addr+(sizeof(int)*400), sizeof(int)*1000, data) < 0)
+ if (H5F_block_write(f, H5FD_MEM_DRAW, addr + (sizeof(int) * 400), sizeof(int) * 1000, data) < 0)
FAIL_STACK_ERROR;
page_count -= 2;
- if(H5SL_count(f->shared->page_buf->slist_ptr) != page_count + base_page_cnt)
+ if (f->shared->pb_ptr->curr_pages != page_count + base_page_cnt)
TEST_ERROR;
/* read elements 0 - 1000.. this should go to disk then update the
* buffer result 200-400 with existing pages
*/
- if(H5F_block_read(f, H5FD_MEM_DRAW, addr, sizeof(int)*1000, data) < 0)
+ if (H5F_block_read(f, H5FD_MEM_DRAW, addr, sizeof(int) * 1000, data) < 0)
FAIL_STACK_ERROR;
i=0;
while (i < 1000) {
if(i<400) {
- if(data[i] != i) {
+ if (data[i] != i) {
HDfprintf(stderr, "Read different values than written\n");
+ HDfprintf(stderr, "data[%d] = %d, %d expected.\n",
+ i, data[i], i);
TEST_ERROR;
}
}
else {
- if(data[i] != 0) {
+ if (data[i] != 0) {
HDfprintf(stderr, "Read different values than written\n");
+ HDfprintf(stderr, "data[%d] = %d, %d expected.\n",
+ i, data[i], 0);
TEST_ERROR;
}
}
i++;
}
- if(H5SL_count(f->shared->page_buf->slist_ptr) != page_count + base_page_cnt)
+ if (f->shared->pb_ptr->curr_pages != page_count + base_page_cnt)
TEST_ERROR;
- if(H5Fclose(file_id) < 0)
+ if (H5Fclose(file_id) < 0)
FAIL_STACK_ERROR;
- if(H5Pclose(fcpl) < 0)
+ if (H5Pclose(fcpl) < 0)
FAIL_STACK_ERROR;
- if(H5Pclose(fapl) < 0)
+ if (H5Pclose(fapl) < 0)
FAIL_STACK_ERROR;
HDfree(data);
@@ -808,10 +1436,13 @@ test_raw_data_handling(hid_t orig_fapl, const char *env_h5_drvr)
error:
H5E_BEGIN_TRY {
- H5Pclose(fapl);
- H5Pclose(fcpl);
- H5Fclose(file_id);
- if(data)
+ if (fapl != H5I_INVALID_HID)
+ H5Pclose(fapl);
+ if (fcpl != H5I_INVALID_HID)
+ H5Pclose(fcpl);
+ if (file_id != H5I_INVALID_HID)
+ H5Fclose(file_id);
+ if (data != NULL)
HDfree(data);
} H5E_END_TRY;
return 1;
@@ -832,17 +1463,12 @@ error:
*
* Programmer: unknown
* ?? / ?? / ??
+ *
+ * Changes: Reworked for new implementation of page buffer. Major
+ * change was adaption to the new implementation's greater
+ * respect for max_pages.
*
- * Changes: Added base_page_cnt field as supporting code. This allows
- * the test to adjust to the number of page buffer pages
- * accessed during file open / create.
- *
- * The test for the value of base_page_cnt just after file
- * open exists detect changes in library behavior. Assuming
- * any such change is not indicative of other issues, these
- * tests can be modified to reflect the change.
- *
- * JRM -- 2/23/17
+ * JRM -- 10/26/18
*
*
*-------------------------------------------------------------------------
@@ -852,11 +1478,10 @@ static unsigned
test_lru_processing(hid_t orig_fapl, const char *env_h5_drvr)
{
char filename[FILENAME_LEN]; /* Filename to use */
+ hbool_t page_exists;
hid_t file_id = -1; /* File ID */
hid_t fcpl = -1;
hid_t fapl = -1;
- size_t base_page_cnt;
- size_t page_count = 0;
int i;
int num_elements = 2000;
haddr_t addr = HADDR_UNDEF;
@@ -866,7 +1491,7 @@ test_lru_processing(hid_t orig_fapl, const char *env_h5_drvr)
TESTING("LRU Processing");
- h5_fixname(FILENAME[0], orig_fapl, filename, sizeof(filename));
+ h5_fixname(namebase, orig_fapl, filename, sizeof(filename));
if((fapl = H5Pcopy(orig_fapl)) < 0)
FAIL_STACK_ERROR
@@ -880,7 +1505,7 @@ test_lru_processing(hid_t orig_fapl, const char *env_h5_drvr)
if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0)
FAIL_STACK_ERROR;
- if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, 0, (hsize_t)1) < 0)
+ if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, 0, 1) < 0)
FAIL_STACK_ERROR;
if(H5Pset_file_space_page_size(fcpl, sizeof(int)*200) < 0)
@@ -897,28 +1522,25 @@ test_lru_processing(hid_t orig_fapl, const char *env_h5_drvr)
if(NULL == (f = (H5F_t *)H5VL_object(file_id)))
FAIL_STACK_ERROR;
- /* opening the file inserts one or more pages into the page buffer.
- * Get the number of pages inserted, and verify that it is the
- * the expected value.
- */
- base_page_cnt = H5SL_count(f->shared->page_buf->slist_ptr);
- if(base_page_cnt != 1)
- TEST_ERROR;
-
- /* allocate space for a 2000 elements */
- if(HADDR_UNDEF == (addr = H5MF_alloc(f, H5FD_MEM_DRAW, sizeof(int)*(size_t)num_elements)))
+ /* allocate space for 2000 elements */
+ if(HADDR_UNDEF == (addr = H5MF_alloc(f, H5FD_MEM_DRAW,
+ sizeof(int)*(size_t)num_elements)))
FAIL_STACK_ERROR;
/* initialize all the elements to have a value of -1 */
for(i=0 ; i<num_elements ; i++)
data[i] = -1;
- if(H5F_block_write(f, H5FD_MEM_DRAW, addr, sizeof(int)*(size_t)num_elements, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, addr,
+ sizeof(int)*(size_t)num_elements, data) < 0)
+ FAIL_STACK_ERROR;
+
+ /* there should be no raw data pages in the page buffer -- verify this */
+ if (f->shared->pb_ptr->curr_rd_pages != 0)
FAIL_STACK_ERROR;
/* update the first 100 elements to have values 0-99 - this will be
- * a page buffer update with 1 page resulting in the page
- * buffer.
+ * a page buffer update that loads page addr + 0 into the page buffer.
*/
for(i=0 ; i<100 ; i++)
data[i] = i;
@@ -926,126 +1548,142 @@ test_lru_processing(hid_t orig_fapl, const char *env_h5_drvr)
if(H5F_block_write(f, H5FD_MEM_DRAW, addr, sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- page_count ++;
+ /* verify addr + 0 is the only raw data page in the page buffer */
+ search_addr = addr;
+ if((H5PB_page_exists(f->shared, search_addr, &page_exists) < 0) || (!page_exists))
+ FAIL_STACK_ERROR;
+ if (f->shared->pb_ptr->curr_rd_pages != 1)
+ FAIL_STACK_ERROR;
- if(H5SL_count(f->shared->page_buf->slist_ptr) != page_count + base_page_cnt)
- TEST_ERROR;
/* update elements 300 - 450, with values 300 - 449 - this will
- * bring two pages into the page buffer and evict 0.
+ * bring two pages (addr + 200 & addr + 400) into the page buffer and
+ * evict addr + 0.
*/
for(i=0 ; i<150 ; i++)
data[i] = i+300;
- if(H5F_block_write(f, H5FD_MEM_DRAW, addr+(sizeof(int)*300), sizeof(int)*150, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, addr+(sizeof(int)*300),
+ sizeof(int)*150, data) < 0)
FAIL_STACK_ERROR;
- page_count = 2;
+ /* verify that addr + 200 and addr + 400 are the only raw data pages in
+ * the page buffer.
+ */
+ search_addr = addr + sizeof(int)*200;
+ if((H5PB_page_exists(f->shared, search_addr, &page_exists) < 0) || (!page_exists))
+ FAIL_STACK_ERROR;
+ search_addr = addr + sizeof(int)*400;
+ if((H5PB_page_exists(f->shared, search_addr, &page_exists) < 0) || (!page_exists))
+ FAIL_STACK_ERROR;
+ if (f->shared->pb_ptr->curr_rd_pages != 2)
+ FAIL_STACK_ERROR;
- /* at this point, the page buffer entry created at file open should
- * have been evicted -- thus no further need to consider base_page_cnt.
+ /* at this point, the page buffer entries created at file open should
+ * have been evicted.
*/
- if(H5SL_count(f->shared->page_buf->slist_ptr) != page_count)
+ if(f->shared->pb_ptr->curr_md_pages != 0)
FAIL_STACK_ERROR;
- /* The two pages should be the ones with address 100 and 200; 0
- should have been evicted */
- /* Changes: 200, 400 */
- search_addr = addr;
- if(NULL != H5SL_search(f->shared->page_buf->slist_ptr, &(search_addr)))
+
+ /* update elements 300-301, this will update page addr + 200 in
+ * page buffer and move it to the top of the LRU.
+ */
+ for(i=0 ; i<1 ; i++)
+ data[i] = i+300;
+ if(H5F_block_write(f, H5FD_MEM_DRAW, addr+(sizeof(int)*300),
+ sizeof(int)*2, data) < 0)
FAIL_STACK_ERROR;
+
+ /* verify that addr + 200 and addr + 400 are the only raw data pages in
+ * the page buffer.
+ */
search_addr = addr + sizeof(int)*200;
- if(NULL == H5SL_search(f->shared->page_buf->slist_ptr, &(search_addr)))
+ if((H5PB_page_exists(f->shared, search_addr, &page_exists) < 0) || (!page_exists))
FAIL_STACK_ERROR;
search_addr = addr + sizeof(int)*400;
- if(NULL == H5SL_search(f->shared->page_buf->slist_ptr, &(search_addr)))
+ if((H5PB_page_exists(f->shared, search_addr, &page_exists) < 0) || (!page_exists))
FAIL_STACK_ERROR;
-
- /* update elements 150-151, this will update existing pages in the
- page buffer and move it to the top of the LRU. */
- /* Changes: 300 - 301 */
- for(i=0 ; i<1 ; i++)
- data[i] = i+300;
- if(H5F_block_write(f, H5FD_MEM_DRAW, addr+(sizeof(int)*300), sizeof(int)*1, data) < 0)
+ if (f->shared->pb_ptr->curr_rd_pages != 2)
FAIL_STACK_ERROR;
- if(H5SL_count(f->shared->page_buf->slist_ptr) != page_count)
+ if(f->shared->pb_ptr->curr_pages != 2)
FAIL_STACK_ERROR;
- /* read elements 600 - 601, this should read -1 and bring in an
- entire page of addr 600, and evict page 200 */
- /* Changes: 1200 - 1201; 1200, 400 */
- if(H5F_block_read(f, H5FD_MEM_DRAW, addr+(sizeof(int)*1200), sizeof(int)*1, data) < 0)
+ /* read elements 1200 - 1201, this should read -1, bring in page
+ * addr + 1200, and evict page addr + 400
+ */
+ if(H5F_block_read(f, H5FD_MEM_DRAW, addr+(sizeof(int)*1200),
+ sizeof(int)*1, data) < 0)
FAIL_STACK_ERROR;
for (i=0; i < 1; i++) {
if(data[i] != -1) {
HDfprintf(stderr, "Read different values than written\n");
+ HDfprintf(stderr, "data[%d] = %d, %d expected.\n", i, data[i], -1);
TEST_ERROR;
- } /* end if */
- } /* end for */
- if(H5SL_count(f->shared->page_buf->slist_ptr) != page_count)
- FAIL_STACK_ERROR;
-
- /* Changes: 400 */
- search_addr = addr + sizeof(int)*400;
- if(NULL != H5SL_search(f->shared->page_buf->slist_ptr, &(search_addr)))
- FAIL_STACK_ERROR;
+ }
+ }
- /* Changes: 200 */
+ /* verify that addr + 200 and addr + 1200 are the only raw data pages in
+ * the page buffer.
+ */
search_addr = addr + sizeof(int)*200;
- if(NULL == H5SL_search(f->shared->page_buf->slist_ptr, &(search_addr)))
+ if((H5PB_page_exists(f->shared, search_addr, &page_exists) < 0) || (!page_exists))
FAIL_STACK_ERROR;
-
- /* Changes: 1200 */
search_addr = addr + sizeof(int)*1200;
- if(NULL == H5SL_search(f->shared->page_buf->slist_ptr, &(search_addr)))
+ if((H5PB_page_exists(f->shared, search_addr, &page_exists) < 0) || (!page_exists))
+ FAIL_STACK_ERROR;
+ if (f->shared->pb_ptr->curr_rd_pages != 2)
FAIL_STACK_ERROR;
- /* read elements 175 - 225, this should move 100 to the top, evict 600 and bring in 200 */
- /* Changes: 350 - 450; 200, 1200, 400 */
- if(H5F_block_read(f, H5FD_MEM_DRAW, addr+(sizeof(int)*350), sizeof(int)*100, data) < 0)
+ if(f->shared->pb_ptr->curr_pages != 2)
+ FAIL_STACK_ERROR;
+
+ /* read elements 350 - 450, this should load page addr + 400 and move
+ * it to the top of the LRU, and evict page addr + 1200.
+ */
+ if(H5F_block_read(f, H5FD_MEM_DRAW, addr+(sizeof(int)*350),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
for (i=0; i < 100; i++) {
if(data[i] != i+350) {
HDfprintf(stderr, "Read different values than written\n");
+ HDfprintf(stderr, "data[%d] = %d, %d expected.\n", i, data[i],
+ i + 350);
TEST_ERROR;
- } /* end if */
- } /* end for */
- if(H5SL_count(f->shared->page_buf->slist_ptr) != page_count)
- FAIL_STACK_ERROR;
-
- /* Changes: 1200 */
- search_addr = addr + sizeof(int)*1200;
- if(NULL != H5SL_search(f->shared->page_buf->slist_ptr, &(search_addr)))
- FAIL_STACK_ERROR;
+ }
+ }
- /* Changes: 200 */
+ /* verify that addr + 200 and addr + 400 are the only raw data pages in
+ * the page buffer.
+ */
search_addr = addr + sizeof(int)*200;
- if(NULL == H5SL_search(f->shared->page_buf->slist_ptr, &(search_addr)))
+ if((H5PB_page_exists(f->shared, search_addr, &page_exists) < 0) || (!page_exists))
FAIL_STACK_ERROR;
-
- /* Changes: 400 */
search_addr = addr + sizeof(int)*400;
- if(NULL == H5SL_search(f->shared->page_buf->slist_ptr, &(search_addr)))
+ if((H5PB_page_exists(f->shared, search_addr, &page_exists) < 0) || (!page_exists))
+ FAIL_STACK_ERROR;
+ if (f->shared->pb_ptr->curr_rd_pages != 2)
+ FAIL_STACK_ERROR;
+ if(f->shared->pb_ptr->curr_pages != 2)
FAIL_STACK_ERROR;
- /* update elements 200 - 700 to value 0, this will go to disk but
- also discarding existing pages from the PB (page 200). */
- /* Changes: 400 - 1400; 400 */
+
+ /* update elements 400 - 1400 to value 0, this will overwrite and
+ * evict page addr + 400.
+ */
for(i=0 ; i<1000 ; i++)
data[i] = 0;
- if(H5F_block_write(f, H5FD_MEM_DRAW, addr+(sizeof(int)*400), sizeof(int)*1000, data) < 0)
- FAIL_STACK_ERROR;
- page_count -= 1;
- if(H5SL_count(f->shared->page_buf->slist_ptr) != page_count)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, addr+(sizeof(int)*400),
+ sizeof(int)*1000, data) < 0)
FAIL_STACK_ERROR;
- /* Changes: 200 */
+ /* verify that addr + 200 is the only raw data page in the page buffer.
+ */
search_addr = addr + sizeof(int)*200;
- if(NULL == H5SL_search(f->shared->page_buf->slist_ptr, &(search_addr)))
+ if((H5PB_page_exists(f->shared, search_addr, &page_exists) < 0) || (!page_exists))
FAIL_STACK_ERROR;
-
- /* Changes: 400 */
- search_addr = addr + sizeof(int)*400;
- if(NULL != H5SL_search(f->shared->page_buf->slist_ptr, &(search_addr)))
+ if (f->shared->pb_ptr->curr_rd_pages != 1)
+ FAIL_STACK_ERROR;
+ if(f->shared->pb_ptr->curr_pages != 1)
FAIL_STACK_ERROR;
if(H5Fclose(file_id) < 0)
@@ -1061,10 +1699,13 @@ test_lru_processing(hid_t orig_fapl, const char *env_h5_drvr)
error:
H5E_BEGIN_TRY {
- H5Pclose(fapl);
- H5Pclose(fcpl);
- H5Fclose(file_id);
- if(data)
+ if (fapl != H5I_INVALID_HID)
+ H5Pclose(fapl);
+ if (fcpl != H5I_INVALID_HID)
+ H5Pclose(fcpl);
+ if (file_id != H5I_INVALID_HID)
+ H5Fclose(file_id);
+ if (data != NULL)
HDfree(data);
} H5E_END_TRY;
return 1;
@@ -1099,6 +1740,14 @@ error:
*
* JRM -- 2/23/17
*
+ * Reworked test for new implementatin of the page buffer.
+ * The major change was adapting the test for the new
+ * page buffers refusal to buffer any raw data when
+ * min_md_pages == max_pages, or any metadata pages wwhen
+ * min_rd_pages == max_pages.
+ *
+ * JRM -- 10/27/18
+ *
*-------------------------------------------------------------------------
*/
@@ -1109,12 +1758,11 @@ test_min_threshold(hid_t orig_fapl, const char *env_h5_drvr)
hid_t file_id = -1; /* File ID */
hid_t fcpl = -1;
hid_t fapl = -1;
- size_t base_raw_cnt = 0;
- size_t base_meta_cnt = 0;
- size_t page_count = 0;
+ int64_t base_raw_cnt = 0;
+ int64_t base_meta_cnt = 0;
int i;
int num_elements = 1000;
- H5PB_t *page_buf;
+ H5PB_t *pb_ptr;
haddr_t meta_addr = HADDR_UNDEF;
haddr_t raw_addr = HADDR_UNDEF;
int *data = NULL;
@@ -1122,7 +1770,7 @@ test_min_threshold(hid_t orig_fapl, const char *env_h5_drvr)
TESTING("Minimum Metadata threshold Processing");
HDprintf("\n");
- h5_fixname(FILENAME[0], orig_fapl, filename, sizeof(filename));
+ h5_fixname(namebase, orig_fapl, filename, sizeof(filename));
if((fapl = H5Pcopy(orig_fapl)) < 0)
TEST_ERROR
@@ -1136,7 +1784,7 @@ test_min_threshold(hid_t orig_fapl, const char *env_h5_drvr)
if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0)
FAIL_STACK_ERROR;
- if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, 0, (hsize_t)1) < 0)
+ if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, 0, 1) < 0)
FAIL_STACK_ERROR;
if(H5Pset_file_space_page_size(fcpl, sizeof(int)*200) < 0)
@@ -1161,35 +1809,35 @@ test_min_threshold(hid_t orig_fapl, const char *env_h5_drvr)
*/
HDassert(f);
HDassert(f->shared);
- HDassert(f->shared->page_buf);
+ HDassert(f->shared->pb_ptr);
- base_raw_cnt = f->shared->page_buf->raw_count;
- base_meta_cnt = f->shared->page_buf->meta_count;
+ base_raw_cnt = f->shared->pb_ptr->curr_rd_pages;
+ base_meta_cnt = f->shared->pb_ptr->curr_md_pages;
if(base_raw_cnt != 0)
TEST_ERROR;
- if(base_meta_cnt != 1)
+ if(base_meta_cnt != 2)
TEST_ERROR;
- page_buf = f->shared->page_buf;
+ pb_ptr = f->shared->pb_ptr;
- if(page_buf->min_meta_count != 5)
+ if(pb_ptr->min_md_pages != 5)
TEST_ERROR;
- if(page_buf->min_raw_count != 0)
+ if(pb_ptr->min_rd_pages != 0)
TEST_ERROR;
- if(HADDR_UNDEF == (meta_addr = H5MF_alloc(f, H5FD_MEM_SUPER, sizeof(int)*(size_t)num_elements)))
+ if(HADDR_UNDEF == (meta_addr = H5MF_alloc(f, H5FD_MEM_SUPER,
+ sizeof(int)*(size_t)num_elements)))
FAIL_STACK_ERROR;
- if(HADDR_UNDEF == (raw_addr = H5MF_alloc(f, H5FD_MEM_DRAW, sizeof(int)*(size_t)num_elements)))
+ if(HADDR_UNDEF == (raw_addr = H5MF_alloc(f, H5FD_MEM_DRAW,
+ sizeof(int)*(size_t)num_elements)))
FAIL_STACK_ERROR;
- /* write all raw data, this would end up in page buffer since there
- * is no metadata yet
- *
- * Not necessarily -- opening the file may may load a metadata page.
+ /* write all raw data. Since min_md_pages == max_pages, none of it
+ * should end up in the page buffer.
*/
for(i=0 ; i<100 ; i++)
data[i] = i;
@@ -1197,77 +1845,88 @@ test_min_threshold(hid_t orig_fapl, const char *env_h5_drvr)
if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr, sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*200), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*200),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*400), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*400),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*600), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*600),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*800), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*800),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- page_count += 5;
-
- if(H5SL_count(f->shared->page_buf->slist_ptr) != page_count)
+ if(f->shared->pb_ptr->curr_pages != base_meta_cnt)
FAIL_STACK_ERROR;
- if(page_buf->raw_count != 5 - base_meta_cnt)
+ if(pb_ptr->curr_rd_pages != 0)
TEST_ERROR;
/* write all meta data, this would end up in page buffer */
- if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr, sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr,
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*200), sizeof(int)*50, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*200),
+ sizeof(int)*50, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*400), sizeof(int)*50, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*400),
+ sizeof(int)*50, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_read(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*600), sizeof(int)*50, data) < 0)
+ if(H5F_block_read(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*600),
+ sizeof(int)*50, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_read(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*800), sizeof(int)*50, data) < 0)
+ if(H5F_block_read(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*800),
+ sizeof(int)*50, data) < 0)
FAIL_STACK_ERROR;
- if(H5SL_count(f->shared->page_buf->slist_ptr) != page_count)
+ if(f->shared->pb_ptr->curr_pages != 5)
FAIL_STACK_ERROR;
- if(page_buf->meta_count != 5)
+ if(pb_ptr->curr_md_pages != 5)
TEST_ERROR;
- if(page_buf->raw_count != 0)
+ if(pb_ptr->curr_rd_pages != 0)
TEST_ERROR;
/* write and read more raw data and make sure that they don't end up in
- * page buffer since the minimum metadata is actually the entire
* page buffer
*/
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*200), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*200),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*350), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*350),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_read(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*500), sizeof(int)*100, data) < 0)
+ if(H5F_block_read(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*500),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_read(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*750), sizeof(int)*100, data) < 0)
+ if(H5F_block_read(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*750),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_read(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*900), sizeof(int)*100, data) < 0)
+ if(H5F_block_read(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*900),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5SL_count(f->shared->page_buf->slist_ptr) != page_count)
+ if(f->shared->pb_ptr->curr_pages != 5)
FAIL_STACK_ERROR;
- if(page_buf->meta_count != 5)
+ if(pb_ptr->curr_md_pages != 5)
TEST_ERROR;
- if(page_buf->raw_count != 0)
+ if(pb_ptr->curr_rd_pages != 0)
TEST_ERROR;
if(H5Fclose(file_id) < 0)
@@ -1276,10 +1935,7 @@ test_min_threshold(hid_t orig_fapl, const char *env_h5_drvr)
HDprintf("\tMinimum raw data threshold = 100%%\n");
- page_count = 0;
-
/* keep 5 pages at max in the page buffer and 5 raw page minimum */
- /* Changes: 1000 */
if(H5Pset_page_buffer_size(fapl, sizeof(int)*1000, 0, 100) < 0)
TEST_ERROR;
@@ -1296,31 +1952,34 @@ test_min_threshold(hid_t orig_fapl, const char *env_h5_drvr)
*/
HDassert(f);
HDassert(f->shared);
- HDassert(f->shared->page_buf);
+ HDassert(f->shared->pb_ptr);
- base_raw_cnt = f->shared->page_buf->raw_count;
- base_meta_cnt = f->shared->page_buf->meta_count;
+ base_raw_cnt = f->shared->pb_ptr->curr_rd_pages;
+ base_meta_cnt = f->shared->pb_ptr->curr_md_pages;
if(base_raw_cnt != 0)
TEST_ERROR;
- if(base_meta_cnt != 1)
+ if(base_meta_cnt != 0)
TEST_ERROR;
- page_buf = f->shared->page_buf;
+ pb_ptr = f->shared->pb_ptr;
- if(page_buf->min_meta_count != 0)
+ if(pb_ptr->min_md_pages != 0)
TEST_ERROR;
- if(page_buf->min_raw_count != 5)
+ if(pb_ptr->min_rd_pages != 5)
FAIL_STACK_ERROR;
- if(HADDR_UNDEF == (meta_addr = H5MF_alloc(f, H5FD_MEM_SUPER, sizeof(int)*(size_t)num_elements)))
+ if(HADDR_UNDEF == (meta_addr = H5MF_alloc(f, H5FD_MEM_SUPER,
+ sizeof(int)*(size_t)num_elements)))
FAIL_STACK_ERROR;
- if(HADDR_UNDEF == (raw_addr = H5MF_alloc(f, H5FD_MEM_DRAW, sizeof(int)*(size_t)num_elements)))
+ if(HADDR_UNDEF == (raw_addr = H5MF_alloc(f, H5FD_MEM_DRAW,
+ sizeof(int)*(size_t)num_elements)))
TEST_ERROR;
- /* write all meta data, this would end up in page buffer since there
+ /* write all meta data, none of this should end up in the page buffer since
+ * min_rd_pages == max_pages
* is no raw data yet
*/
for(i=0 ; i<100 ; i++)
@@ -1329,86 +1988,97 @@ test_min_threshold(hid_t orig_fapl, const char *env_h5_drvr)
if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr, sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*200), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*200),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*400), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*400),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*600), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*600),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*800), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*800),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- page_count += 5;
-
- if(H5SL_count(f->shared->page_buf->slist_ptr) != page_count)
+ if(f->shared->pb_ptr->curr_pages != 0)
FAIL_STACK_ERROR;
- if(page_buf->meta_count != 5 - base_raw_cnt)
+ if(pb_ptr->curr_md_pages != 0)
TEST_ERROR;
/* write/read all raw data, this would end up in page buffer */
if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr, sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*200), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*200),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*400), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*400),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_read(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*600), sizeof(int)*100, data) < 0)
+ if(H5F_block_read(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*600),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_read(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*800), sizeof(int)*100, data) < 0)
+ if(H5F_block_read(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*800),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5SL_count(f->shared->page_buf->slist_ptr) != page_count)
+ if(f->shared->pb_ptr->curr_pages != 5)
FAIL_STACK_ERROR;
- if(page_buf->raw_count != 5)
+ if(pb_ptr->curr_rd_pages != 5)
TEST_ERROR;
- if(page_buf->meta_count != 0)
+ if(pb_ptr->curr_md_pages != 0)
TEST_ERROR;
/* write and read more meta data and make sure that they don't end up in
- * page buffer since the minimum metadata is actually the entire
* page buffer
*/
- if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*100), sizeof(int)*50, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*100),
+ sizeof(int)*50, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*350), sizeof(int)*50, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*350),
+ sizeof(int)*50, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_read(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*500), sizeof(int)*50, data) < 0)
+ if(H5F_block_read(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*500),
+ sizeof(int)*50, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_read(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*750), sizeof(int)*50, data) < 0)
+ if(H5F_block_read(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*750),
+ sizeof(int)*50, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_read(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*900), sizeof(int)*50, data) < 0)
+ if(H5F_block_read(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*900),
+ sizeof(int)*50, data) < 0)
FAIL_STACK_ERROR;
- if(H5SL_count(f->shared->page_buf->slist_ptr) != page_count)
+ if(f->shared->pb_ptr->curr_pages != 5)
FAIL_STACK_ERROR;
- if(page_buf->raw_count != 5)
+ if(pb_ptr->curr_rd_pages != 5)
TEST_ERROR;
- if(page_buf->meta_count != 0)
+ if(pb_ptr->curr_md_pages != 0)
TEST_ERROR;
if(H5Fclose(file_id) < 0)
FAIL_STACK_ERROR;
- HDprintf("\tMinimum metadata threshold = 40%%, Minimum rawdata threshold = 40%%\n");
- page_count = 0;
- /* keep 5 pages at max in the page buffer 2 meta pages, 2 raw pages
- * minimum
+ HDprintf("\tMinimum metadata threshold = 40%%, ");
+ HDprintf("Minimum rawdata threshold = 40%%\n");
+
+ /* keep 5 pages at max in the page buffer 2 meta pages, 2 raw pages
+ * minimum
*/
if(H5Pset_page_buffer_size(fapl, sizeof(int)*1000, 40, 40) < 0)
TEST_ERROR;
@@ -1428,33 +2098,41 @@ test_min_threshold(hid_t orig_fapl, const char *env_h5_drvr)
* metadata entry counts.
*/
+ base_raw_cnt = f->shared->pb_ptr->curr_rd_pages;
+ base_meta_cnt = f->shared->pb_ptr->curr_md_pages;
+
if(base_raw_cnt != 0)
TEST_ERROR;
- if(base_meta_cnt != 1)
+ if(base_meta_cnt != 2)
TEST_ERROR;
- page_buf = f->shared->page_buf;
- if(page_buf->min_meta_count != 2)
+ pb_ptr = f->shared->pb_ptr;
+
+ if(pb_ptr->min_md_pages != 2)
TEST_ERROR;
- if(page_buf->min_raw_count != 2)
+ if(pb_ptr->min_rd_pages != 2)
TEST_ERROR;
- if(HADDR_UNDEF == (meta_addr = H5MF_alloc(f, H5FD_MEM_SUPER, sizeof(int)*(size_t)num_elements)))
+ if(HADDR_UNDEF == (meta_addr = H5MF_alloc(f, H5FD_MEM_SUPER,
+ sizeof(int)*(size_t)num_elements)))
FAIL_STACK_ERROR;
- if(HADDR_UNDEF == (raw_addr = H5MF_alloc(f, H5FD_MEM_DRAW, sizeof(int)*(size_t)num_elements)))
+ if(HADDR_UNDEF == (raw_addr = H5MF_alloc(f, H5FD_MEM_DRAW,
+ sizeof(int)*(size_t)num_elements)))
FAIL_STACK_ERROR;
/* initialize all the elements to have a value of -1 */
for(i=0 ; i<num_elements ; i++)
data[i] = -1;
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr, sizeof(int)*(size_t)num_elements, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr,
+ sizeof(int)*(size_t)num_elements, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr, sizeof(int)*(size_t)num_elements, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr,
+ sizeof(int)*(size_t)num_elements, data) < 0)
FAIL_STACK_ERROR;
/* fill the page buffer with raw data */
@@ -1464,124 +2142,169 @@ test_min_threshold(hid_t orig_fapl, const char *env_h5_drvr)
if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr, sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*200), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*200),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*400), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*400),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*600), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*600),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*800), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*800),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- page_count += 5;
-
- if(H5SL_count(f->shared->page_buf->slist_ptr) != page_count)
+ if(f->shared->pb_ptr->curr_pages != 5)
TEST_ERROR;
- if(f->shared->page_buf->raw_count != 5 - base_meta_cnt)
+ if(f->shared->pb_ptr->curr_rd_pages != 5 - base_meta_cnt)
TEST_ERROR;
- /* add 3 meta entries evicting 3 raw entries */
+ /* add 3 meta entries evicting 1 raw entry */
if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr, sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*200), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*200),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*400), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*400),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5SL_count(f->shared->page_buf->slist_ptr) != page_count)
+ if(f->shared->pb_ptr->curr_pages != 5)
FAIL_STACK_ERROR;
- if(f->shared->page_buf->meta_count != 3)
+ if(f->shared->pb_ptr->curr_md_pages != 3)
TEST_ERROR;
- if(f->shared->page_buf->raw_count != 2)
+ if(f->shared->pb_ptr->curr_rd_pages != 2)
TEST_ERROR;
/* adding more meta entires should replace meta entries since raw data
* is at its minimum
*/
- if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*600), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*600),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*800), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*800),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(f->shared->page_buf->meta_count != 3)
+ if(f->shared->pb_ptr->curr_md_pages != 3)
TEST_ERROR;
- if(f->shared->page_buf->raw_count != 2)
+ if(f->shared->pb_ptr->curr_rd_pages != 2)
TEST_ERROR;
/* bring existing raw entires up the LRU */
- if(H5F_block_read(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*750), sizeof(int)*100, data) < 0)
+ if(H5F_block_read(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*750),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
/* adding 2 raw entries (even with 1 call) should only evict 1 meta
* entry and another raw entry
*/
- if(H5F_block_read(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*350), sizeof(int)*100, data) < 0)
+ if(H5F_block_read(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*350),
+ sizeof(int)*100, data) < 0)
+ FAIL_STACK_ERROR;
+
+ if(f->shared->pb_ptr->curr_md_pages != 2)
+ TEST_ERROR;
+
+ if(f->shared->pb_ptr->curr_rd_pages != 3)
+ TEST_ERROR;
+
+ /* read a metadata entry to force the flush of the metadata entries
+ * in the page buffer, and then read some raw data so that the metadata
+ * pages are at the bottom of the LRU.
+ *
+ * When we are done, should still have 2 metadata pages and 3 raw data
+ * pages in the page buffer
+ */
+
+ if(H5F_block_read(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*442),
+ sizeof(int)*100, data) < 0)
+ FAIL_STACK_ERROR;
+
+ if(H5F_block_read(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*150),
+ sizeof(int)*100, data) < 0)
+ FAIL_STACK_ERROR;
+
+ if(H5F_block_read(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*550),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(f->shared->page_buf->meta_count != 2)
+ if(f->shared->pb_ptr->curr_md_pages != 2)
TEST_ERROR;
- if(f->shared->page_buf->raw_count != 3)
+ if(f->shared->pb_ptr->curr_rd_pages != 3)
TEST_ERROR;
- /* adding 2 meta entries should replace 2 entires at the bottom of the LRU */
- if(H5F_block_read(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*98), sizeof(int)*100, data) < 0)
+ /* adding 2 meta entries should replace 2 entires at the bottom
+ * of the LRU
+ */
+ if(H5F_block_read(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*98),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_read(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*242), sizeof(int)*100, data) < 0)
+ if(H5F_block_read(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*242),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(f->shared->page_buf->meta_count != 2)
+ if(f->shared->pb_ptr->curr_md_pages != 2)
TEST_ERROR;
- if(f->shared->page_buf->raw_count != 3)
+ if(f->shared->pb_ptr->curr_rd_pages != 3)
TEST_ERROR;
if(H5Fclose(file_id) < 0)
FAIL_STACK_ERROR;
HDprintf("\tMinimum metadata threshold = 20%%\n");
- page_count = 0;
+
/* keep 5 pages at max in the page buffer and 1 meta page minimum */
if(H5Pset_page_buffer_size(fapl, sizeof(int)*1000, 39, 0) < 0)
TEST_ERROR;
+
/* create the file */
if((file_id = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl, fapl)) < 0)
FAIL_STACK_ERROR;
+
/* Get a pointer to the internal file object */
if(NULL == (f = (H5F_t *)H5VL_object(file_id)))
FAIL_STACK_ERROR;
- page_buf = f->shared->page_buf;
- if(page_buf->min_meta_count != 1)
+ pb_ptr = f->shared->pb_ptr;
+
+ if(pb_ptr->min_md_pages != 1)
TEST_ERROR;
- if(page_buf->min_raw_count != 0)
+ if(pb_ptr->min_rd_pages != 0)
TEST_ERROR;
- if(HADDR_UNDEF == (meta_addr = H5MF_alloc(f, H5FD_MEM_SUPER, sizeof(int)*(size_t)num_elements)))
+ if(HADDR_UNDEF == (meta_addr = H5MF_alloc(f, H5FD_MEM_SUPER,
+ sizeof(int)*(size_t)num_elements)))
FAIL_STACK_ERROR;
- if(HADDR_UNDEF == (raw_addr = H5MF_alloc(f, H5FD_MEM_DRAW, sizeof(int)*(size_t)num_elements)))
+ if(HADDR_UNDEF == (raw_addr = H5MF_alloc(f, H5FD_MEM_DRAW,
+ sizeof(int)*(size_t)num_elements)))
FAIL_STACK_ERROR;
/* initialize all the elements to have a value of -1 */
for(i=0 ; i<num_elements ; i++)
data[i] = -1;
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr, sizeof(int)*(size_t)num_elements, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr,
+ sizeof(int)*(size_t)num_elements, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr, sizeof(int)*(size_t)num_elements, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr,
+ sizeof(int)*(size_t)num_elements, data) < 0)
FAIL_STACK_ERROR;
/* fill the page buffer with raw data */
@@ -1591,90 +2314,105 @@ test_min_threshold(hid_t orig_fapl, const char *env_h5_drvr)
if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr, sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*200), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*200),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*400), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*400),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*600), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*600),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*800), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*800),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- page_count += 5;
-
- if(H5SL_count(f->shared->page_buf->slist_ptr) != page_count)
+ if(f->shared->pb_ptr->curr_pages != 5)
FAIL_STACK_ERROR;
+ if(f->shared->pb_ptr->curr_md_pages != 1)
+ TEST_ERROR;
+
+ if(f->shared->pb_ptr->curr_rd_pages != 4)
+ TEST_ERROR;
+
/* add 2 meta entries evicting 2 raw entries */
if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr, sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*200), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*200),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5SL_count(f->shared->page_buf->slist_ptr) != page_count)
+ if(f->shared->pb_ptr->curr_pages != 5)
FAIL_STACK_ERROR;
- if(f->shared->page_buf->meta_count != 2)
+ if(f->shared->pb_ptr->curr_md_pages != 3)
TEST_ERROR;
- if(f->shared->page_buf->raw_count != 3)
+ if(f->shared->pb_ptr->curr_rd_pages != 2)
TEST_ERROR;
/* bring the rest of the raw entries up the LRU */
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*500), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*500),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*700), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*700),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*900), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*900),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
/* write one more raw entry which replace one meta entry */
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*100), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*100),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5SL_count(f->shared->page_buf->slist_ptr) != page_count)
+ if(f->shared->pb_ptr->curr_pages != 5)
FAIL_STACK_ERROR;
- if(f->shared->page_buf->meta_count != 1)
+ if(f->shared->pb_ptr->curr_md_pages != 1)
TEST_ERROR;
- if(f->shared->page_buf->raw_count != 4)
+ if(f->shared->pb_ptr->curr_rd_pages != 4)
TEST_ERROR;
/* write one more raw entry which should replace another raw entry
* keeping min threshold of meta entries
*/
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*300), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*300),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5SL_count(f->shared->page_buf->slist_ptr) != page_count)
+ if(f->shared->pb_ptr->curr_pages != 5)
FAIL_STACK_ERROR;
- if(f->shared->page_buf->meta_count != 1)
+ if(f->shared->pb_ptr->curr_md_pages != 1)
TEST_ERROR;
- if(f->shared->page_buf->raw_count != 4)
+ if(f->shared->pb_ptr->curr_rd_pages != 4)
TEST_ERROR;
/* write a metadata entry that should replace the metadata entry
* at the bottom of the LRU
*/
- if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*500), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*500),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5SL_count(f->shared->page_buf->slist_ptr) != page_count)
+ if(f->shared->pb_ptr->curr_pages != 5)
FAIL_STACK_ERROR;
- if(f->shared->page_buf->meta_count != 1)
+ if(f->shared->pb_ptr->curr_md_pages != 1)
TEST_ERROR;
- if(f->shared->page_buf->raw_count != 4)
+ if(f->shared->pb_ptr->curr_rd_pages != 4)
TEST_ERROR;
if(H5Fclose(file_id) < 0)
@@ -1693,15 +2431,16 @@ test_min_threshold(hid_t orig_fapl, const char *env_h5_drvr)
return 0;
error:
-
H5E_BEGIN_TRY {
- H5Pclose(fapl);
- H5Pclose(fcpl);
- H5Fclose(file_id);
- if(data)
+ if (fapl != H5I_INVALID_HID)
+ H5Pclose(fapl);
+ if (fcpl != H5I_INVALID_HID)
+ H5Pclose(fcpl);
+ if (file_id != H5I_INVALID_HID)
+ H5Fclose(file_id);
+ if (data != NULL)
HDfree(data);
} H5E_END_TRY;
-
return 1;
} /* test_min_threshold */
@@ -1735,6 +2474,10 @@ error:
*
* JRM -- 2/23/17
*
+ * Reworked test for the new page buffer implementation.
+ *
+ * JRM -- 10/28/18
+ *
*-------------------------------------------------------------------------
*/
static unsigned
@@ -1746,8 +2489,8 @@ test_stats_collection(hid_t orig_fapl, const char *env_h5_drvr)
hid_t fapl = -1;
int i;
int num_elements = 1000;
- size_t base_raw_cnt = 0;
- size_t base_meta_cnt = 0;
+ int64_t base_raw_cnt = 0;
+ int64_t base_meta_cnt = 0;
haddr_t meta_addr = HADDR_UNDEF;
haddr_t raw_addr = HADDR_UNDEF;
int *data = NULL;
@@ -1755,7 +2498,7 @@ test_stats_collection(hid_t orig_fapl, const char *env_h5_drvr)
TESTING("Statistics Collection");
- h5_fixname(FILENAME[0], orig_fapl, filename, sizeof(filename));
+ h5_fixname(namebase, orig_fapl, filename, sizeof(filename));
if((fapl = H5Pcopy(orig_fapl)) < 0)
TEST_ERROR
@@ -1769,7 +2512,7 @@ test_stats_collection(hid_t orig_fapl, const char *env_h5_drvr)
if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0)
TEST_ERROR;
- if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, 0, (hsize_t)1) < 0)
+ if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, 0, 1) < 0)
TEST_ERROR;
if(H5Pset_file_space_page_size(fcpl, sizeof(int)*200) < 0)
@@ -1792,25 +2535,27 @@ test_stats_collection(hid_t orig_fapl, const char *env_h5_drvr)
*/
HDassert(f);
HDassert(f->shared);
- HDassert(f->shared->page_buf);
+ HDassert(f->shared->pb_ptr);
- base_raw_cnt = f->shared->page_buf->raw_count;
- base_meta_cnt = f->shared->page_buf->meta_count;
+ base_raw_cnt = f->shared->pb_ptr->curr_rd_pages;
+ base_meta_cnt = f->shared->pb_ptr->curr_md_pages;
if(base_raw_cnt != 0)
TEST_ERROR;
- if(base_meta_cnt != 1)
+ if(base_meta_cnt != 2)
TEST_ERROR;
/* reset statistics before we begin the tests */
if(H5Freset_page_buffering_stats(file_id) < 0)
FAIL_STACK_ERROR;
- if(HADDR_UNDEF == (meta_addr = H5MF_alloc(f, H5FD_MEM_SUPER, sizeof(int)*(size_t)num_elements)))
+ if(HADDR_UNDEF == (meta_addr = H5MF_alloc(f, H5FD_MEM_SUPER,
+ sizeof(int)*(size_t)num_elements)))
FAIL_STACK_ERROR;
- if(HADDR_UNDEF == (raw_addr = H5MF_alloc(f, H5FD_MEM_DRAW, sizeof(int)*(size_t)num_elements)))
+ if(HADDR_UNDEF == (raw_addr = H5MF_alloc(f, H5FD_MEM_DRAW,
+ sizeof(int)*(size_t)num_elements)))
FAIL_STACK_ERROR;
@@ -1818,10 +2563,12 @@ test_stats_collection(hid_t orig_fapl, const char *env_h5_drvr)
for(i=0 ; i<num_elements ; i++)
data[i] = -1;
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr, sizeof(int)*(size_t)num_elements, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr,
+ sizeof(int)*(size_t)num_elements, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr, sizeof(int)*(size_t)num_elements, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr,
+ sizeof(int)*(size_t)num_elements, data) < 0)
FAIL_STACK_ERROR;
for(i=0 ; i<200 ; i++)
@@ -1830,137 +2577,217 @@ test_stats_collection(hid_t orig_fapl, const char *env_h5_drvr)
if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr, sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*200), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*200),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*400), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*400),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr, sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*200), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*200),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*600), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*600),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*800), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*800),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*600), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*600),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*500), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*500),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*700), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*700),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*900), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*900),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*400), sizeof(int)*200, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*400),
+ sizeof(int)*200, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*100), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*100),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*300), sizeof(int)*100, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*300),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*800), sizeof(int)*182, data) < 0)
+ if(H5F_block_write(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*800),
+ sizeof(int)*182, data) < 0)
FAIL_STACK_ERROR;
if(H5F_block_read(f, H5FD_MEM_DRAW, raw_addr, sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_read(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*200), sizeof(int)*100, data) < 0)
+ if(H5F_block_read(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*200),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_read(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*400), sizeof(int)*100, data) < 0)
+ if(H5F_block_read(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*400),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
if(H5F_block_read(f, H5FD_MEM_SUPER, meta_addr, sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_read(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*200), sizeof(int)*100, data) < 0)
+ if(H5F_block_read(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*200),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_read(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*600), sizeof(int)*100, data) < 0)
+ if(H5F_block_read(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*600),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_read(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*800), sizeof(int)*100, data) < 0)
+ if(H5F_block_read(f, H5FD_MEM_DRAW, raw_addr+(sizeof(int)*800),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_read(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*400), sizeof(int)*100, data) < 0)
+ if(H5F_block_read(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*400),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_read(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*600), sizeof(int)*200, data) < 0)
+ if(H5F_block_read(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*600),
+ sizeof(int)*200, data) < 0)
FAIL_STACK_ERROR;
- if(H5F_block_read(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*800), sizeof(int)*100, data) < 0)
+ if(H5F_block_read(f, H5FD_MEM_SUPER, meta_addr+(sizeof(int)*800),
+ sizeof(int)*100, data) < 0)
FAIL_STACK_ERROR;
- if(f->shared->page_buf->accesses[0] != 8)
- TEST_ERROR;
- if(f->shared->page_buf->accesses[1] != 16)
- TEST_ERROR;
+ if ( ( f->shared->pb_ptr->accesses[0] != 9 ) ||
+ ( f->shared->pb_ptr->accesses[1] != 16 ) ||
+ ( f->shared->pb_ptr->accesses[2] != 0 ) ) {
- if(f->shared->page_buf->bypasses[0] != 3)
- TEST_ERROR;
- if(f->shared->page_buf->bypasses[1] != 1)
+ HDfprintf(stderr, "accesses[] = {%d, %d, %d}. {9, 16, 0} expected\n",
+ f->shared->pb_ptr->accesses[0],
+ f->shared->pb_ptr->accesses[1],
+ f->shared->pb_ptr->accesses[2]);
TEST_ERROR;
+ }
- if(f->shared->page_buf->hits[0] != 0)
- TEST_ERROR;
- if(f->shared->page_buf->hits[1] != 4)
- TEST_ERROR;
+ if ( ( f->shared->pb_ptr->bypasses[0] != 2 ) ||
+ ( f->shared->pb_ptr->bypasses[1] != 1 ) ||
+ ( f->shared->pb_ptr->bypasses[2] != 1 ) ) {
- if(f->shared->page_buf->misses[0] != 8)
+ HDfprintf(stderr, "bypasses[] = {%d, %d, %d}. {2, 1, 1} expected\n",
+ f->shared->pb_ptr->bypasses[0],
+ f->shared->pb_ptr->bypasses[1],
+ f->shared->pb_ptr->bypasses[2]);
TEST_ERROR;
- if(f->shared->page_buf->misses[1] != 11)
+ }
+
+ if ( ( f->shared->pb_ptr->hits[0] != 0 ) ||
+ ( f->shared->pb_ptr->hits[1] != 4 ) ||
+ ( f->shared->pb_ptr->hits[2] != 0 ) ) {
+
+ HDfprintf(stderr, "hits[] = {%d, %d, %d}. {0, 4, 0} expected\n",
+ f->shared->pb_ptr->hits[0],
+ f->shared->pb_ptr->hits[1],
+ f->shared->pb_ptr->hits[2]);
TEST_ERROR;
+ }
+
+ if ( ( f->shared->pb_ptr->misses[0] != 9 ) ||
+ ( f->shared->pb_ptr->misses[1] != 16 ) ||
+ ( f->shared->pb_ptr->misses[2] != 0 ) ) {
- if(f->shared->page_buf->evictions[0] != 5 + base_meta_cnt)
+ HDfprintf(stderr, "misses[] = {%d, %d, %d}. {9, 16, 0} expected\n",
+ f->shared->pb_ptr->misses[0],
+ f->shared->pb_ptr->misses[1],
+ f->shared->pb_ptr->misses[2]);
TEST_ERROR;
- if(f->shared->page_buf->evictions[1] != 9 + base_raw_cnt)
+ }
+
+ if ( ( f->shared->pb_ptr->evictions[0] != 7) ||
+ ( f->shared->pb_ptr->evictions[1] != 9) ||
+ ( f->shared->pb_ptr->evictions[2] != 0 ) ) {
+
+ HDfprintf(stderr, "evictions[] = {%d, %d, %d}. {%d, %d, 0} expected\n",
+ f->shared->pb_ptr->evictions[0],
+ f->shared->pb_ptr->evictions[1],
+ f->shared->pb_ptr->evictions[2], 7, 9);
TEST_ERROR;
+ }
{
- unsigned accesses[2];
- unsigned hits[2];
- unsigned misses[2];
- unsigned evictions[2];
- unsigned bypasses[2];
-
- if(H5Fget_page_buffering_stats(file_id, accesses, hits, misses, evictions, bypasses) < 0)
+ unsigned accesses[3];
+ unsigned hits[3];
+ unsigned misses[3];
+ unsigned evictions[3];
+ unsigned bypasses[3];
+
+ if(H5Fget_page_buffering_stats(file_id, accesses, hits, misses,
+ evictions, bypasses) < 0)
FAIL_STACK_ERROR;
- if(accesses[0] != 8)
- TEST_ERROR;
- if(accesses[1] != 16)
- TEST_ERROR;
- if(bypasses[0] != 3)
- TEST_ERROR;
- if(bypasses[1] != 1)
- TEST_ERROR;
- if(hits[0] != 0)
- TEST_ERROR;
- if(hits[1] != 4)
+ if ( ( accesses[0] != 9 ) ||
+ ( accesses[1] != 16 ) ||
+ ( accesses[2] != 0 ) ) {
+
+ HDfprintf(stderr,
+ "accesses[] = {%d, %d, %d}. {9, 16, 0} expected\n",
+ accesses[0], accesses[1], accesses[2]);
TEST_ERROR;
- if(misses[0] != 8)
+ }
+
+ if ( ( bypasses[0] != 2 ) ||
+ ( bypasses[1] != 1 ) ||
+ ( bypasses[2] != 1 ) ) {
+
+ HDfprintf(stderr, "bypasses[] = {%d, %d, %d}. {2, 1, 1} expected\n",
+ bypasses[0], bypasses[1], bypasses[2]);
TEST_ERROR;
- if(misses[1] != 11)
+ }
+
+ if ( ( hits[0] != 0 ) ||
+ ( hits[1] != 4 ) ||
+ ( hits[2] != 0 ) ) {
+
+ HDfprintf(stderr, "hits[] = {%d, %d, %d}. {0, 4, 0} expected\n",
+ hits[0], hits[1], hits[2]);
TEST_ERROR;
- if(evictions[0] != 5 + base_meta_cnt)
+ }
+
+ if ( ( misses[0] != 9 ) ||
+ ( misses[1] != 16 ) ||
+ ( misses[2] != 0 ) ) {
+
+ HDfprintf(stderr, "misses[] = {%d, %d, %d}. {9, 16, 0} expected\n",
+ misses[0], misses[1], misses[2]);
TEST_ERROR;
- if(evictions[1] != 9 + base_raw_cnt)
+ }
+
+ if ( ( evictions[0] != 7 ) ||
+ ( evictions[1] != 9 ) ||
+ ( evictions[2] != 0 ) ) {
+
+ HDfprintf(stderr,
+ "evictions[] = {%d, %d, %d}. {%d, %d, 0} expected\n",
+ evictions[0], evictions[1], evictions[2], 7, 9);
TEST_ERROR;
+ }
if(H5Freset_page_buffering_stats(file_id) < 0)
FAIL_STACK_ERROR;
- if(H5Fget_page_buffering_stats(file_id, accesses, hits, misses, evictions, bypasses) < 0)
+
+ if(H5Fget_page_buffering_stats(file_id, accesses, hits, misses,
+ evictions, bypasses) < 0)
FAIL_STACK_ERROR;
if(accesses[0] != 0)
@@ -1983,7 +2810,7 @@ test_stats_collection(hid_t orig_fapl, const char *env_h5_drvr)
TEST_ERROR;
if(evictions[1] != 0)
TEST_ERROR;
- } /* end block */
+ }
if(H5Fclose(file_id) < 0)
FAIL_STACK_ERROR;
@@ -1999,10 +2826,13 @@ test_stats_collection(hid_t orig_fapl, const char *env_h5_drvr)
error:
H5E_BEGIN_TRY {
- H5Pclose(fapl);
- H5Pclose(fcpl);
- H5Fclose(file_id);
- if(data)
+ if (fapl != H5I_INVALID_HID)
+ H5Pclose(fapl);
+ if (fcpl != H5I_INVALID_HID)
+ H5Pclose(fcpl);
+ if (file_id != H5I_INVALID_HID)
+ H5Fclose(file_id);
+ if (data != NULL)
HDfree(data);
} H5E_END_TRY;
@@ -2041,7 +2871,7 @@ verify_page_buffering_disabled(hid_t orig_fapl, const char *env_h5_drvr)
hid_t fapl = -1;
TESTING("Page Buffering Disabled");
- h5_fixname(FILENAME[0], orig_fapl, filename, sizeof(filename));
+ h5_fixname(namebase, orig_fapl, filename, sizeof(filename));
/* first, try to create a file with page buffering enabled */
@@ -2055,7 +2885,7 @@ verify_page_buffering_disabled(hid_t orig_fapl, const char *env_h5_drvr)
if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0)
FAIL_STACK_ERROR;
- if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, 0, (hsize_t)1) < 0)
+ if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, 0, 1) < 0)
FAIL_STACK_ERROR;
if(H5Pset_file_space_page_size(fcpl, 4096) < 0)
@@ -2078,7 +2908,7 @@ verify_page_buffering_disabled(hid_t orig_fapl, const char *env_h5_drvr)
if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0)
FAIL_STACK_ERROR;
- if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, 0, (hsize_t)1) < 0)
+ if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, 0, 1) < 0)
FAIL_STACK_ERROR;
if(H5Pset_file_space_page_size(fcpl, 4096) < 0)
@@ -2115,14 +2945,17 @@ verify_page_buffering_disabled(hid_t orig_fapl, const char *env_h5_drvr)
error:
H5E_BEGIN_TRY {
- H5Pclose(fapl);
- H5Pclose(fcpl);
- H5Fclose(file_id);
+ if (fapl != H5I_INVALID_HID)
+ H5Pclose(fapl);
+ if (fcpl != H5I_INVALID_HID)
+ H5Pclose(fcpl);
+ if (file_id != H5I_INVALID_HID)
+ H5Fclose(file_id);
} H5E_END_TRY;
return 1;
-} /* verify_page_buffering_disabled() */
+}
#endif /* H5_HAVE_PARALLEL */
@@ -2163,13 +2996,14 @@ main(void)
SKIPPED()
HDputs("Skip page buffering test because paged aggregation is disabled for multi/split drivers");
+ HDputs("Furthermore, VFD SWMR is not (yet) expected to work with multi/split drivers");
HDexit(EXIT_SUCCESS);
- } /* end if */
+ }
if((fapl = h5_fileaccess()) < 0) {
nerrors++;
PUTS_ERROR("Can't get VFD-dependent fapl")
- } /* end if */
+ }
/* Push API context */
if(H5CX_push() < 0) FAIL_STACK_ERROR
@@ -2183,14 +3017,18 @@ main(void)
#else /* H5_HAVE_PARALLEL */
nerrors += test_args(fapl, env_h5_drvr);
- nerrors += test_raw_data_handling(fapl, env_h5_drvr);
+ nerrors += test_raw_data_handling(fapl, env_h5_drvr, false);
+ nerrors += test_raw_data_handling(fapl, env_h5_drvr, true);
+ nerrors += test_spmde_delay_basic(fapl, env_h5_drvr);
+ nerrors += test_mpmde_delay_basic(fapl, env_h5_drvr);
+ nerrors += test_spmde_lru_evict_basic(fapl, env_h5_drvr);
nerrors += test_lru_processing(fapl, env_h5_drvr);
nerrors += test_min_threshold(fapl, env_h5_drvr);
nerrors += test_stats_collection(fapl, env_h5_drvr);
#endif /* H5_HAVE_PARALLEL */
- h5_clean_files(FILENAME, fapl);
+ h5_clean_files(namebases, fapl);
if(nerrors)
goto error;
@@ -2214,5 +3052,4 @@ error:
if(api_ctx_pushed) H5CX_pop();
HDexit(EXIT_FAILURE);
-} /* main() */
-
+}
diff --git a/test/stubs.c b/test/stubs.c
new file mode 100644
index 0000000..c04f1ba
--- /dev/null
+++ b/test/stubs.c
@@ -0,0 +1,25 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include "h5test.h"
+#include "genall5.h"
+
+/* The default, do-nothing implementation of zoo_create_hook(), which
+ * is called after each create_zoo() step.
+ */
+void
+zoo_create_hook(hid_t H5_ATTR_UNUSED fid)
+{
+ return;
+}
+
diff --git a/test/supervise.subr b/test/supervise.subr
new file mode 100644
index 0000000..d2b0395
--- /dev/null
+++ b/test/supervise.subr
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+#
+# catch_out_err_and_rc outbase command [arguments]
+#
+# Run `command` with any `arguments` provided. Redirect `command`'s
+# stderr and stdout to the file `outbase.out`. Record the result code
+# of `command` in `outbase.rc`.
+#
+catch_out_err_and_rc()
+{
+ if [ $# -lt 2 ]; then
+ echo "usage: catch_output_and_rc outbase command [arguments]" \
+ 1>&2
+ exit 1
+ fi
+ outbase=$1
+ shift
+ {
+ "$@" < ${STDIN_PATH:-/dev/stdin} > ${STDOUT_PATH:-/dev/stdout} &
+ echo $! > ${outbase}.pid
+ wait $(cat ${outbase}.pid)
+ echo $? > ${outbase}.rc
+ } 2>&1 | tee ${outbase}.out
+}
+
+#catch_out_err_and_rc xxlsxx ls smiles &
+
+#wait
+#echo result=$(cat xxlsxx.rc)
+
+#exit 0
diff --git a/test/swmr_addrem_writer.c b/test/swmr_addrem_writer.c
index 71e4929..7c79de4 100644
--- a/test/swmr_addrem_writer.c
+++ b/test/swmr_addrem_writer.c
@@ -193,7 +193,7 @@ addrem_records(hid_t fid, unsigned verbose, unsigned long nops, unsigned long fl
hid_t file_sid; /* Dataset's space ID */
/* Get a random dataset, according to the symbol distribution */
- symbol = choose_dataset();
+ symbol = choose_dataset(NULL, NULL);
/* Decide whether to shrink or expand, and by how much */
count[1] = (hsize_t)HDrandom() % (MAX_SIZE_CHANGE * 2) + 1;
diff --git a/test/swmr_common.c b/test/swmr_common.c
index 7ae1fad..0290fe5 100644
--- a/test/swmr_common.c
+++ b/test/swmr_common.c
@@ -109,8 +109,9 @@ char VDS_DSET_NAME[NAME_LEN] = "vds_dset";
*-------------------------------------------------------------------------
*/
symbol_info_t *
-choose_dataset(void)
+choose_dataset(unsigned *levelp, unsigned *offsetp)
{
+ static unsigned ncalls = 0;
unsigned level; /* The level of the dataset */
unsigned offset; /* The "offset" of the dataset at that level */
@@ -120,10 +121,19 @@ choose_dataset(void)
/* Determine the offset of the level */
offset = (unsigned)(HDrandom() % (int)symbol_count[level]);
+ ++ncalls;
+ if ((ncalls % 1000) == 0) {
+ fprintf(stderr, "%s: call %u chose level %u offset %u\n", __func__,
+ ncalls, level, offset);
+ }
+ if (levelp != NULL)
+ *levelp = level;
+ if (offsetp != NULL)
+ *offsetp = offset;
return &symbol_info[level][offset];
} /* end choose_dataset() */
-
+
/*-------------------------------------------------------------------------
* Function: create_symbol_datatype
*
@@ -217,13 +227,12 @@ generate_symbols(void)
unsigned u, v; /* Local index variables */
for(u = 0; u < NLEVELS; u++) {
- symbol_info[u] = (symbol_info_t *)HDmalloc(symbol_count[u] * sizeof(symbol_info_t));
+ symbol_info[u] = HDmalloc(symbol_count[u] * sizeof(symbol_info_t));
for(v = 0; v < symbol_count[u]; v++) {
char name_buf[64];
generate_name(name_buf, u, v);
- symbol_info[u][v].name = (char *)HDmalloc(HDstrlen(name_buf) + 1);
- HDstrcpy(symbol_info[u][v].name, name_buf);
+ symbol_info[u][v].name = HDstrdup(name_buf);
symbol_info[u][v].dsid = -1;
symbol_info[u][v].nrecords = 0;
} /* end for */
diff --git a/test/swmr_common.h b/test/swmr_common.h
index a0bc581..47f96b7 100644
--- a/test/swmr_common.h
+++ b/test/swmr_common.h
@@ -64,7 +64,7 @@ H5TEST_DLLVAR unsigned symbol_count[NLEVELS];
extern "C" {
#endif
-H5TEST_DLL symbol_info_t * choose_dataset(void);
+H5TEST_DLL symbol_info_t * choose_dataset(unsigned *, unsigned *);
H5TEST_DLL hid_t create_symbol_datatype(void);
H5TEST_DLL int generate_name(char *name_buf, unsigned level, unsigned count);
H5TEST_DLL int generate_symbols(void);
diff --git a/test/swmr_reader.c b/test/swmr_reader.c
index ee263e3..28a6597 100644
--- a/test/swmr_reader.c
+++ b/test/swmr_reader.c
@@ -250,7 +250,7 @@ read_records(const char *filename, hbool_t verbose, FILE *verbose_file,
symbol_info_t *sym; /* Symbol to use */
/* Determine the symbol, within all symbols */
- if(NULL == (sym = choose_dataset()))
+ if(NULL == (sym = choose_dataset(NULL, NULL)))
return -1;
sym_rand[v] = sym;
diff --git a/test/swmr_remove_reader.c b/test/swmr_remove_reader.c
index b02d16f..41f8437 100644
--- a/test/swmr_remove_reader.c
+++ b/test/swmr_remove_reader.c
@@ -247,7 +247,7 @@ read_records(const char *filename, unsigned verbose, unsigned long nseconds,
symbol_info_t *sym; /* Symbol to use */
/* Determine the symbol, within all symbols */
- if(NULL == (sym = choose_dataset()))
+ if(NULL == (sym = choose_dataset(NULL, NULL)))
return -1;
sym_rand[v] = sym;
diff --git a/test/swmr_remove_writer.c b/test/swmr_remove_writer.c
index 2bebab9..2db9493 100644
--- a/test/swmr_remove_writer.c
+++ b/test/swmr_remove_writer.c
@@ -179,7 +179,7 @@ remove_records(hid_t fid, unsigned verbose, unsigned long nshrinks, unsigned lon
hsize_t remove_size; /* Size to reduce dataset dimension by */
/* Get a random dataset, according to the symbol distribution */
- symbol = choose_dataset();
+ symbol = choose_dataset(NULL, NULL);
/* Shrink the dataset's dataspace */
remove_size = (hsize_t)HDrandom() % MAX_REMOVE_SIZE + 1;
diff --git a/test/swmr_sparse_reader.c b/test/swmr_sparse_reader.c
index 2d558df..cdf03ba 100644
--- a/test/swmr_sparse_reader.c
+++ b/test/swmr_sparse_reader.c
@@ -29,6 +29,7 @@
/* Headers */
/***********/
+#include <inttypes.h> /* for PRIu64 */
#include "h5test.h"
#include "swmr_common.h"
@@ -118,7 +119,7 @@ check_dataset(hid_t fid, unsigned verbose, const symbol_info_t *symbol, symbol_t
HDfprintf(stderr, "Symbol = '%s', location = %" PRIuMAX ",%" PRIuMAX "\n", symbol->name, (uintmax_t)start[0], (uintmax_t)start[1]);
/* Read record from dataset */
- record->rec_id = (uint64_t)ULLONG_MAX;
+ record->rec_id = UINT64_MAX;
if(H5Dread(dsid, symbol_tid, rec_sid, file_sid, H5P_DEFAULT, record) < 0)
return -1;
@@ -231,7 +232,7 @@ read_records(const char *filename, unsigned verbose, unsigned long nrecords,
unsigned long file_u; /* Attribute sequence number (writer's "u") */
/* Get a random dataset, according to the symbol distribution */
- symbol = choose_dataset();
+ symbol = choose_dataset(NULL, NULL);
/* Fill in "nrecords" field. Note that this depends on the writer
* using the same algorithm and "nrecords" */
diff --git a/test/swmr_sparse_writer.c b/test/swmr_sparse_writer.c
index 5173c71..e33ebd4 100644
--- a/test/swmr_sparse_writer.c
+++ b/test/swmr_sparse_writer.c
@@ -201,7 +201,7 @@ add_records(hid_t fid, unsigned verbose, unsigned long nrecords, unsigned long f
hbool_t corked; /* Whether the dataset was corked */
/* Get a random dataset, according to the symbol distribution */
- symbol = choose_dataset();
+ symbol = choose_dataset(NULL, NULL);
/* If this is the first time the dataset has been opened, extend it and
* add the sequence attribute */
diff --git a/test/swmr_start_write.c b/test/swmr_start_write.c
index fc7e7a5..5522795 100644
--- a/test/swmr_start_write.c
+++ b/test/swmr_start_write.c
@@ -257,7 +257,7 @@ add_records(hid_t fid, hbool_t verbose, FILE *verbose_file,
hid_t file_sid; /* Dataset's space ID */
/* Get a random dataset, according to the symbol distribution */
- symbol = choose_dataset();
+ symbol = choose_dataset(NULL, NULL);
/* Set the record's ID (equal to its position) */
record.rec_id = symbol->nrecords;
diff --git a/test/swmr_writer.c b/test/swmr_writer.c
index d4387aa..5db17ef 100644
--- a/test/swmr_writer.c
+++ b/test/swmr_writer.c
@@ -197,7 +197,7 @@ add_records(hid_t fid, hbool_t verbose, FILE *verbose_file,
hid_t file_sid; /* Dataset's space ID */
/* Get a random dataset, according to the symbol distribution */
- symbol = choose_dataset();
+ symbol = choose_dataset(NULL, NULL);
/* Set the record's ID (equal to its position) */
record.rec_id = symbol->nrecords;
diff --git a/test/testfiles/err_compat_1 b/test/testfiles/err_compat_1
index fc99f77..978c1f4 100644
--- a/test/testfiles/err_compat_1
+++ b/test/testfiles/err_compat_1
@@ -1,4 +1,6 @@
-Testing error API H5Eset/get_auto Testing error API based on data I/O All error API tests passed.
+Testing error API H5Eset/get_auto
+Testing error API based on data I/O
+All error API tests passed.
This program tests the Error API compatible with HDF5 version (number). There are supposed to be some error messages
********* Print error stack in HDF5 default way *********
HDF5-DIAG: Error detected in HDF5 (version (number)) thread (IDs):
diff --git a/test/testfiles/plist_files/dcpl_32be b/test/testfiles/plist_files/dcpl_32be
index 667c67f..c8241a6 100644
--- a/test/testfiles/plist_files/dcpl_32be
+++ b/test/testfiles/plist_files/dcpl_32be
Binary files differ
diff --git a/test/testfiles/plist_files/dcpl_32le b/test/testfiles/plist_files/dcpl_32le
index 667c67f..c8241a6 100644
--- a/test/testfiles/plist_files/dcpl_32le
+++ b/test/testfiles/plist_files/dcpl_32le
Binary files differ
diff --git a/test/testfiles/plist_files/dcpl_64be b/test/testfiles/plist_files/dcpl_64be
index 667c67f..c8241a6 100644
--- a/test/testfiles/plist_files/dcpl_64be
+++ b/test/testfiles/plist_files/dcpl_64be
Binary files differ
diff --git a/test/testfiles/plist_files/dcpl_64le b/test/testfiles/plist_files/dcpl_64le
index 667c67f..c8241a6 100644
--- a/test/testfiles/plist_files/dcpl_64le
+++ b/test/testfiles/plist_files/dcpl_64le
Binary files differ
diff --git a/test/testfiles/plist_files/def_dcpl_32be b/test/testfiles/plist_files/def_dcpl_32be
index 01b233c..0909391 100644
--- a/test/testfiles/plist_files/def_dcpl_32be
+++ b/test/testfiles/plist_files/def_dcpl_32be
Binary files differ
diff --git a/test/testfiles/plist_files/def_dcpl_32le b/test/testfiles/plist_files/def_dcpl_32le
index 01b233c..0909391 100644
--- a/test/testfiles/plist_files/def_dcpl_32le
+++ b/test/testfiles/plist_files/def_dcpl_32le
Binary files differ
diff --git a/test/testfiles/plist_files/def_dcpl_64be b/test/testfiles/plist_files/def_dcpl_64be
index 01b233c..0909391 100644
--- a/test/testfiles/plist_files/def_dcpl_64be
+++ b/test/testfiles/plist_files/def_dcpl_64be
Binary files differ
diff --git a/test/testfiles/plist_files/def_dcpl_64le b/test/testfiles/plist_files/def_dcpl_64le
index 01b233c..0909391 100644
--- a/test/testfiles/plist_files/def_dcpl_64le
+++ b/test/testfiles/plist_files/def_dcpl_64le
Binary files differ
diff --git a/test/testfiles/plist_files/def_dxpl_32be b/test/testfiles/plist_files/def_dxpl_32be
index b13f456..da29037 100644
--- a/test/testfiles/plist_files/def_dxpl_32be
+++ b/test/testfiles/plist_files/def_dxpl_32be
Binary files differ
diff --git a/test/testfiles/plist_files/def_dxpl_32le b/test/testfiles/plist_files/def_dxpl_32le
index b13f456..da29037 100644
--- a/test/testfiles/plist_files/def_dxpl_32le
+++ b/test/testfiles/plist_files/def_dxpl_32le
Binary files differ
diff --git a/test/testfiles/plist_files/def_dxpl_64be b/test/testfiles/plist_files/def_dxpl_64be
index b13f456..da29037 100644
--- a/test/testfiles/plist_files/def_dxpl_64be
+++ b/test/testfiles/plist_files/def_dxpl_64be
Binary files differ
diff --git a/test/testfiles/plist_files/def_dxpl_64le b/test/testfiles/plist_files/def_dxpl_64le
index b13f456..da29037 100644
--- a/test/testfiles/plist_files/def_dxpl_64le
+++ b/test/testfiles/plist_files/def_dxpl_64le
Binary files differ
diff --git a/test/testfiles/plist_files/def_fapl_32be b/test/testfiles/plist_files/def_fapl_32be
index 53ef572..6738cda 100644
--- a/test/testfiles/plist_files/def_fapl_32be
+++ b/test/testfiles/plist_files/def_fapl_32be
Binary files differ
diff --git a/test/testfiles/plist_files/def_fapl_32le b/test/testfiles/plist_files/def_fapl_32le
index 53ef572..6738cda 100644
--- a/test/testfiles/plist_files/def_fapl_32le
+++ b/test/testfiles/plist_files/def_fapl_32le
Binary files differ
diff --git a/test/testfiles/plist_files/def_fapl_64be b/test/testfiles/plist_files/def_fapl_64be
index 53ef572..6738cda 100644
--- a/test/testfiles/plist_files/def_fapl_64be
+++ b/test/testfiles/plist_files/def_fapl_64be
Binary files differ
diff --git a/test/testfiles/plist_files/def_fapl_64le b/test/testfiles/plist_files/def_fapl_64le
index 53ef572..6738cda 100644
--- a/test/testfiles/plist_files/def_fapl_64le
+++ b/test/testfiles/plist_files/def_fapl_64le
Binary files differ
diff --git a/test/testfiles/plist_files/dxpl_32be b/test/testfiles/plist_files/dxpl_32be
index 5ff2ea0..cac7e50 100644
--- a/test/testfiles/plist_files/dxpl_32be
+++ b/test/testfiles/plist_files/dxpl_32be
Binary files differ
diff --git a/test/testfiles/plist_files/dxpl_32le b/test/testfiles/plist_files/dxpl_32le
index 5ff2ea0..cac7e50 100644
--- a/test/testfiles/plist_files/dxpl_32le
+++ b/test/testfiles/plist_files/dxpl_32le
Binary files differ
diff --git a/test/testfiles/plist_files/dxpl_64be b/test/testfiles/plist_files/dxpl_64be
index 5ff2ea0..cac7e50 100644
--- a/test/testfiles/plist_files/dxpl_64be
+++ b/test/testfiles/plist_files/dxpl_64be
Binary files differ
diff --git a/test/testfiles/plist_files/dxpl_64le b/test/testfiles/plist_files/dxpl_64le
index 5ff2ea0..cac7e50 100644
--- a/test/testfiles/plist_files/dxpl_64le
+++ b/test/testfiles/plist_files/dxpl_64le
Binary files differ
diff --git a/test/testfiles/plist_files/fapl_32be b/test/testfiles/plist_files/fapl_32be
index d89a44c..807c04a 100644
--- a/test/testfiles/plist_files/fapl_32be
+++ b/test/testfiles/plist_files/fapl_32be
Binary files differ
diff --git a/test/testfiles/plist_files/fapl_32le b/test/testfiles/plist_files/fapl_32le
index d89a44c..807c04a 100644
--- a/test/testfiles/plist_files/fapl_32le
+++ b/test/testfiles/plist_files/fapl_32le
Binary files differ
diff --git a/test/testfiles/plist_files/fapl_64be b/test/testfiles/plist_files/fapl_64be
index d89a44c..807c04a 100644
--- a/test/testfiles/plist_files/fapl_64be
+++ b/test/testfiles/plist_files/fapl_64be
Binary files differ
diff --git a/test/testfiles/plist_files/fapl_64le b/test/testfiles/plist_files/fapl_64le
index d89a44c..807c04a 100644
--- a/test/testfiles/plist_files/fapl_64le
+++ b/test/testfiles/plist_files/fapl_64le
Binary files differ
diff --git a/test/testfiles/plist_files/lapl_32be b/test/testfiles/plist_files/lapl_32be
index eee238e..3db7163 100644
--- a/test/testfiles/plist_files/lapl_32be
+++ b/test/testfiles/plist_files/lapl_32be
Binary files differ
diff --git a/test/testfiles/plist_files/lapl_32le b/test/testfiles/plist_files/lapl_32le
index eee238e..3db7163 100644
--- a/test/testfiles/plist_files/lapl_32le
+++ b/test/testfiles/plist_files/lapl_32le
Binary files differ
diff --git a/test/testfiles/plist_files/lapl_64be b/test/testfiles/plist_files/lapl_64be
index eee238e..3db7163 100644
--- a/test/testfiles/plist_files/lapl_64be
+++ b/test/testfiles/plist_files/lapl_64be
Binary files differ
diff --git a/test/testfiles/plist_files/lapl_64le b/test/testfiles/plist_files/lapl_64le
index eee238e..3db7163 100644
--- a/test/testfiles/plist_files/lapl_64le
+++ b/test/testfiles/plist_files/lapl_64le
Binary files differ
diff --git a/test/testvfdswmr.sh.in b/test/testvfdswmr.sh.in
new file mode 100644
index 0000000..a355245
--- /dev/null
+++ b/test/testvfdswmr.sh.in
@@ -0,0 +1,746 @@
+#! /bin/bash
+#
+# Copyright by The HDF Group.
+# Copyright by the Board of Trustees of the University of Illinois.
+# All rights reserved.
+#
+# This file is part of HDF5. The full HDF5 copyright notice, including
+# terms governing use, modification, and redistribution, is contained in
+# the COPYING file, which can be found at the root of the source code
+# distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases.
+# If you do not have access to either file, you may request a copy from
+# help@hdfgroup.org.
+#
+# Tests for the vfd swmr feature.
+#
+###############################################################################
+# VFD SWMR concurrent tests which are modified from existing swmr concurrent tests.
+# This is copied and modified from testswmr.sh.in
+#
+###############################################################################
+
+srcdir=@srcdir@
+
+. ${srcdir}/supervise.subr
+
+###############################################################################
+## test parameters
+###############################################################################
+
+Nreaders=5 # number of readers to launch
+Nrdrs_spa=3 # number of sparse readers to launch
+Nrecords=400000 # number of records to write
+Nrecs_rem=40000 # number of times to shrink
+Nrecs_spa=20000 # number of records to write in the sparse test
+Nsecs_add=5 # number of seconds per read interval
+Nsecs_rem=3 # number of seconds per read interval
+Nsecs_addrem=8 # number of seconds per read interval
+nerrors=0
+nsofterrors=0 # soft errors are expected to occur some of the time
+ # on a couple of nondeterministic tests.
+
+###############################################################################
+## definitions for message file to coordinate test runs
+###############################################################################
+WRITER_MESSAGE=VFD_SWMR_WRITER_MESSAGE # The message file created by writer that the open is complete
+ # This should be the same as the define in "./swmr_common.h"
+MESSAGE_TIMEOUT=300 # Message timeout length in secs
+ # This should be the same as the define in "./h5test.h"
+
+###############################################################################
+## short hands and function definitions
+###############################################################################
+DPRINT=: # Set to "echo Debug:" for debugging printing,
+ # else ":" for noop.
+IFDEBUG=: # Set to null to turn on debugging, else ":" for noop.
+
+# Print a line-line message left justified in a field of 70 characters
+# beginning with the word "Testing".
+#
+TESTING() {
+ SPACES=" "
+ echo "Testing $* $SPACES" | cut -c1-70 | tr -d '\012'
+}
+
+# To wait for the writer message file or till the maximum # of seconds is reached
+# $1 is the message file to wait for
+# This performs similar function as the routine h5_wait_message() in test/h5test.c
+WAIT_MESSAGE() {
+ message=$1 # Get the name of the message file to wait for
+ t0=`date +%s` # Get current time in seconds
+ difft=0 # Initialize the time difference
+ mexist=0 # Indicate whether the message file is found
+ while [ $difft -lt $MESSAGE_TIMEOUT ] ; # Loop till message times out
+ do
+ t1=`date +%s` # Get current time in seconds
+ difft=`expr $t1 - $t0` # Calculate the time difference
+ if [ -e $message ]; then # If message file is found:
+ mexist=1 # indicate the message file is found
+ rm $message # remove the message file
+ break # get out of the while loop
+ fi
+ done;
+ if test $mexist -eq 0; then
+ # Issue warning that the writer message file is not found, continue with launching the reader(s)
+ echo warning: $WRITER_MESSAGE is not found after waiting $MESSAGE_TIMEOUT seconds
+ else
+ echo $WRITER_MESSAGE is found
+ fi
+}
+
+###############################################################################
+## Main
+##
+## Modifications:
+## Vailin Choi; July 2013
+## Add waiting of message file before launching the reader(s).
+## Due to the implementation of file locking, coordination
+## is needed in file opening for the writer/reader tests
+## to proceed as expected.
+##
+###############################################################################
+# The build (current) directory might be different than the source directory.
+if test -z "$srcdir"; then
+ srcdir=.
+fi
+
+# Check to see if the VFD specified by the HDF5_DRIVER environment variable
+# supports SWMR. ??? DO I NEED TO MODIFY THIS ????
+./swmr_check_compat_vfd
+rc=$?
+if [ $rc -ne 0 ] ; then
+ echo
+ echo "The VFD specified by the HDF5_DRIVER environment variable"
+ echo "does not support VFD SWMR."
+ echo
+ echo "VFD SWMR acceptance tests skipped"
+ echo
+ exit 0
+fi
+
+all_tests="generator expand shrink expand_shrink sparse vlstr_null vlstr_oob zoo groups"
+all_tests="${all_tests} few_big many_small"
+tests=${all_tests}
+
+if [ $# -gt 0 ]; then
+ tests=
+fi
+
+for t; do
+ if ! echo $all_tests | grep -q "\<${t}\>"; then
+ echo "$t: Unknown test, ${t}"
+ exit 1
+ fi
+ tests="${tests} ${t}"
+done
+
+echo tests=${tests}
+for t in ${tests}; do
+ eval do_${t}=yes
+done
+
+# HDF5 has several tests that create and delete signal files to communicate
+# between processes, and it seems that even though the names of the files are
+# different, occasionally the wrong file is deleted, interrupting the flow of
+# the test. Running each of these tests in its own directory should eliminate
+# the problem.
+rm -rf vfd_swmr_test
+mkdir vfd_swmr_test
+
+## With the --disable-shared option, swmr program files are built in the test
+## directory, otherwise they are in test/.libs with a corresponding wrapper
+## script in the test directory. The programs or wrapper scripts in test should
+## always be copied, swmr files in .libs should be copied only if they exists.
+#if [ -f .libs/vfd_swmr ]; then
+# mkdir vfd_swmr_test/.libs
+# for FILE in .libs/vfd_swmr*; do
+# case "$FILE" in
+# *.o) continue ;; ## don't copy the .o files
+# esac
+# cp $FILE vfd_swmr_test/.libs
+# done
+#fi
+
+cd vfd_swmr_test
+
+# Loop over index types
+for index_type in "-i ea" "-i b2"
+do
+ # Try without compression, only; uncomment "-c 5" to try with compression.
+
+ for compress in "" #"-c 5"
+ do
+ echo
+ echo "** Loop testing parameters: $index_type $compress"
+ echo
+ if [ ${do_generator:-no} = yes ]; then
+ echo
+ echo "## Generator test"
+ # Launch the Generator without VFD SWMR write
+ echo launch the vfd_swmr_generator
+ ../vfd_swmr_generator $compress $index_type
+ if test $? -ne 0; then
+ echo generator had error
+ nerrors=`expr $nerrors + 1`
+ fi
+
+ # Launch the Generator with VFD SWMR write
+ echo launch the vfd_swmr_generator with VFD SWMR write
+ ../vfd_swmr_generator -s $compress $index_type
+ if test $? -ne 0; then
+ echo generator had error
+ nerrors=`expr $nerrors + 1`
+ fi
+ fi
+
+ if [ ${do_expand:-no} = yes ]; then
+ echo
+ echo "## Writer test - test expanding the dataset"
+
+ # Launch the Generator
+ echo launch the vfd_swmr_generator with VFD SWMR write
+ ../vfd_swmr_generator -s $compress $index_type
+ if test $? -ne 0; then
+ echo generator had error
+ nerrors=`expr $nerrors + 1`
+ fi
+
+ # Remove any possible writer message file before launching writer
+ rm -f $WRITER_MESSAGE
+ #
+ # Launch the Writer
+ echo launch the vfd_swmr_writer
+ seed="" # Put -r <random seed> command here
+ catch_out_err_and_rc vfd_swmr_writer \
+ ../vfd_swmr_writer -o $Nrecords $seed &
+ pid_writer=$!
+ $DPRINT pid_writer=$pid_writer
+
+ # Wait for message from writer process before starting reader(s)
+ WAIT_MESSAGE $WRITER_MESSAGE
+ #
+ # Launch the Readers
+ #declare -a seeds=(<seed1> <seed2> <seed3> ... )
+ echo launch $Nreaders vfd_swmr_readers
+ pid_readers=""
+ n=0
+ while [ $n -lt $Nreaders ]; do
+ #seed="-r ${seeds[$n]}"
+ seed=""
+ catch_out_err_and_rc vfd_swmr_reader.$n \
+ ../vfd_swmr_reader $Nsecs_add $seed &
+ pid_readers="$pid_readers $!"
+ n=`expr $n + 1`
+ done
+ $DPRINT pid_readers=$pid_readers
+ $IFDEBUG ps
+
+ # Wait for the readers to finish before signalling the
+ # writer to quit: the writer holds the file open so that the
+ # readers will find the shadow file when they reopen
+ # the .h5 file.
+ wait $pid_readers
+ kill -USR1 $(cat vfd_swmr_writer.pid)
+ wait $pid_writer
+
+ # Collect exit codes of the readers
+ n=0
+ while [ $n -lt $Nreaders ]; do
+ if [ $(cat vfd_swmr_reader.$n.rc) -ne 0 ]; then
+ echo reader had error
+ nerrors=$((nerrors + 1))
+ fi
+ n=$((n + 1))
+ done
+
+ # Collect exit code of the writer
+ $DPRINT checked writer $pid_writer
+ if [ $(cat vfd_swmr_writer.rc) -ne 0 ]; then
+ echo writer had error
+ nerrors=$((nerrors + 1))
+ fi
+
+ # Clean up output files
+ rm -f vfd_swmr_writer.{out,rc}
+ rm -f vfd_swmr_reader.*.{out,rc}
+ fi
+
+ if [ ${do_shrink:-no} = yes ]; then
+ if [ ${do_expand:-no} != yes ]; then
+ echo "Cancelling the 'shrink' test: it depends on the .h5 file left behind by the 'expand' test." 1>&2
+ exit 1
+ fi
+ echo
+ echo "## Remove test - test shrinking the dataset"
+
+ # Remove any possible writer message file before launching writer
+ rm -f $WRITER_MESSAGE
+ # Launch the Remove Writer
+ echo launch the vfd_swmr_remove_writer
+ seed="" # Put -r <random seed> command here
+ catch_out_err_and_rc vfd_swmr_writer \
+ ../vfd_swmr_remove_writer -o $Nrecs_rem $seed &
+ pid_writer=$!
+ $DPRINT pid_writer=$pid_writer
+
+ # Wait for message from writer process before starting reader(s)
+ WAIT_MESSAGE $WRITER_MESSAGE
+ #
+ # Launch the Remove Readers
+ #declare -a seeds=(<seed1> <seed2> <seed3> ... )
+ n=0
+ pid_readers=""
+ echo launch $Nreaders swmr_remove_readers
+ while [ $n -lt $Nreaders ]; do
+ #seed="-r ${seeds[$n]}"
+ seed=""
+ catch_out_err_and_rc vfd_swmr_reader.$n \
+ ../vfd_swmr_remove_reader $Nsecs_rem $seed &
+ pid_readers="$pid_readers $!"
+ n=`expr $n + 1`
+ done
+ $DPRINT pid_readers=$pid_readers
+ $IFDEBUG ps
+
+ # Wait for the readers to finish before signalling the
+ # writer to quit: the writer holds the file open so that the
+ # readers will find the shadow file when they reopen
+ # the .h5 file.
+ wait $pid_readers
+ kill -USR1 $(cat vfd_swmr_writer.pid)
+ wait $pid_writer
+
+ # Collect exit codes of the readers
+ n=0
+ while [ $n -lt $Nreaders ]; do
+ if [ $(cat vfd_swmr_reader.$n.rc) -ne 0 ]; then
+ echo reader had error
+ nerrors=$((nerrors + 1))
+ fi
+ n=$((n + 1))
+ done
+
+ # Collect exit code of the writer
+ $DPRINT checked writer $pid_writer
+ if [ $(cat vfd_swmr_writer.rc) -ne 0 ]; then
+ echo writer had error
+ nerrors=$((nerrors + 1))
+ fi
+
+ # Clean up output files
+ rm -f vfd_swmr_writer.{out,rc}
+ rm -f vfd_swmr_reader.*.{out,rc}
+ fi
+
+ if [ ${do_expand_shrink:-no} = yes ]; then
+ echo
+ echo "## Expand/shrink test - randomly grow or shrink the dataset"
+
+ # Launch the Generator
+ echo launch the vfd_swmr_generator with VFD SWMR write
+ ../vfd_swmr_generator -s $compress $index_type
+ if test $? -ne 0; then
+ echo generator had error
+ nerrors=`expr $nerrors + 1`
+ fi
+
+ # Launch the Writer (not in parallel - just to rebuild the datasets)
+ echo launch the vfd_swmr_writer
+ seed="" # Put -r <random seed> command here
+ ../vfd_swmr_writer -W $Nrecords $seed
+ if test $? -ne 0; then
+ echo writer had error
+ nerrors=`expr $nerrors + 1`
+ fi
+
+ # Remove any possible writer message file before launching writer
+ rm -f $WRITER_MESSAGE
+ #
+ # Launch the Add/Remove Writer
+ echo launch the vfd_swmr_addrem_writer
+ seed="" # Put -r <random seed> command here
+ catch_out_err_and_rc vfd_swmr_writer \
+ ../vfd_swmr_addrem_writer $Nrecords $seed &
+ pid_writer=$!
+ $DPRINT pid_writer=$pid_writer
+
+ # Wait for message from writer process before starting reader(s)
+ WAIT_MESSAGE $WRITER_MESSAGE
+ #
+ # Launch the Add/Remove Readers
+ #declare -a seeds=(<seed1> <seed2> <seed3> ... )
+ n=0
+ pid_readers=""
+ echo launch $Nreaders vfd_swmr_remove_readers
+ while [ $n -lt $Nreaders ]; do
+ #seed="-r ${seeds[$n]}"
+ seed=""
+ catch_out_err_and_rc vfd_swmr_reader.$n \
+ ../vfd_swmr_remove_reader $Nsecs_addrem $seed &
+ pid_readers="$pid_readers $!"
+ n=`expr $n + 1`
+ done
+ $DPRINT pid_readers=$pid_readers
+ $IFDEBUG ps
+
+ # Wait for the readers to finish before signalling the
+ # writer to quit: the writer holds the file open so that the
+ # readers will find the shadow file when they reopen
+ # the .h5 file.
+ wait $pid_readers
+ kill -USR1 $(cat vfd_swmr_writer.pid)
+ wait $pid_writer
+
+ # Collect exit codes of the readers
+ n=0
+ while [ $n -lt $Nreaders ]; do
+ if [ $(cat vfd_swmr_reader.$n.rc) -ne 0 ]; then
+ echo reader had error
+ nerrors=$((nerrors + 1))
+ fi
+ n=$((n + 1))
+ done
+
+ # Collect exit code of the writer
+ $DPRINT checked writer $pid_writer
+ if [ ! -e vfd_swmr_writer.rc ] ||
+ [ $(cat vfd_swmr_writer.rc) -ne 0 ]; then
+ echo writer had error
+ nerrors=$((nerrors + 1))
+ fi
+
+ # Clean up output files
+ rm -f vfd_swmr_writer.{out,rc}
+ rm -f vfd_swmr_reader.*.{out,rc}
+ fi
+
+ if [ ${do_sparse:-no} = yes ]; then
+ echo
+ echo "## Sparse writer test - write random dataset locations"
+
+ # Launch the Generator
+ # NOTE: Random seed is shared between readers and writers and is
+ # created by the generator.
+ echo launch the vfd_swmr_generator with VFD SWMR write
+ seed="" # Put -r <random seed> command here
+ ../vfd_swmr_generator -s $compress $index_type $seed
+ if test $? -ne 0; then
+ echo generator had error
+ nerrors=`expr $nerrors + 1`
+ fi
+
+ # Remove any possible writer message file before launching writer
+ rm -f $WRITER_MESSAGE
+ # Launch the Sparse writer
+ echo launch the vfd_swmr_sparse_writer
+ catch_out_err_and_rc vfd_swmr_writer nice -n 20 \
+ ../vfd_swmr_sparse_writer $Nrecs_spa &
+ pid_writer=$!
+ $DPRINT pid_writer=$pid_writer
+
+ # Wait for message from writer process before starting reader(s)
+ WAIT_MESSAGE $WRITER_MESSAGE
+ #
+ # Launch the Sparse readers
+ n=0
+ pid_readers=""
+ echo launch $Nrdrs_spa vfd_swmr_sparse_readers
+ while [ $n -lt $Nrdrs_spa ]; do
+ # The sparse reader spits out a LOT of data so it's set to 'quiet'
+ catch_out_err_and_rc vfd_swmr_reader.$n \
+ ../vfd_swmr_sparse_reader -q $Nrecs_spa &
+ pid_readers="$pid_readers $!"
+ n=`expr $n + 1`
+ done
+ $DPRINT pid_readers=$pid_readers
+ $IFDEBUG ps
+
+ # Wait for the readers and the writer to finish.
+ echo "pid_readers=$pid_readers"
+ echo "pid_writer=$pid_writer"
+
+ # Wait for the readers to finish before signalling the
+ # writer to quit: the writer holds the file open so that the
+ # readers will find the shadow file when they reopen
+ # the .h5 file.
+ wait $pid_readers
+ kill -USR1 $(cat vfd_swmr_writer.pid)
+ wait $pid_writer
+
+ # Collect exit codes of the readers
+ n=0
+ while [ $n -lt $Nrdrs_spa ]; do
+ if [ $(cat vfd_swmr_reader.$n.rc) -ne 0 ]; then
+ echo reader had error
+ nerrors=$((nerrors + 1))
+ fi
+ n=$((n + 1))
+ done
+
+ # Collect exit code of the writer
+ $DPRINT checked writer $pid_writer
+ if [ $(cat vfd_swmr_writer.rc) -ne 0 ]; then
+ echo writer had error
+ nerrors=$((nerrors + 1))
+ fi
+
+ # Clean up output files
+ rm -f vfd_swmr_writer.{out,rc}
+ rm -f vfd_swmr_reader.*.{out,rc}
+ fi
+ done
+done
+
+#
+# Test variable-length strings, expecting errors.
+#
+for ty in null oob; do
+
+ if [ ${ty} = null ]; then
+ [ ${do_vlstr_null:-no} = no ] && continue
+ echo
+ echo "## VL string 1 - expect to read NULL"
+ else
+ [ ${do_vlstr_oob:-no} = no ] && continue
+ echo
+ echo "## VL string 2 - expect out-of-bounds access"
+ fi
+
+ echo launch vfd_swmr_vlstr_writer
+ catch_out_err_and_rc vfd_swmr_vlstr_writer \
+ ../vfd_swmr_vlstr_writer -n 500 -q -t ${ty} &
+ pid_writer=$!
+
+ # pause?
+
+ catch_out_err_and_rc vfd_swmr_vlstr_reader \
+ ../vfd_swmr_vlstr_reader -n 500 -q -t ${ty} &
+ pid_reader=$!
+
+ # Wait for the reader to finish before signalling the
+ # writer to quit: the writer holds the file open so that the
+ # reader will find the shadow file when it opens
+ # the .h5 file.
+ wait $pid_reader
+ kill -USR1 $(cat vfd_swmr_vlstr_writer.pid)
+ wait $pid_writer
+
+ # Collect exit code of the reader
+ if [ $(cat vfd_swmr_vlstr_reader.rc) -ne 0 ]; then
+ echo reader had error
+ nsofterrors=$((nsofterrors + 1))
+ fi
+
+ # Collect exit code of the writer
+ if [ $(cat vfd_swmr_vlstr_writer.rc) -ne 0 ]; then
+ echo writer had error
+ nerrors=$((nerrors + 1))
+ fi
+
+ # Clean up output files
+ rm -f vfd_swmr_vlstr_writer.{out,rc}
+ rm -f vfd_swmr_vlstr_reader.*.{out,rc}
+done
+
+#
+# Make sure that a "zoo"---the variety of HDF5 object types---can be
+# read and written by VFD SWMR.
+#
+if [ ${do_zoo:-no} = yes ]; then
+ [ -e ./fifo ] && rm -f ./fifo
+ mkfifo -m 0600 ./fifo
+ rm -f ./shared_tick_num
+ echo launch vfd_swmr_zoo_writer
+ STDIN_PATH="./fifo" catch_out_err_and_rc vfd_swmr_zoo_writer \
+ ../vfd_swmr_zoo_writer -m 1000 -q &
+ pid_writer=$!
+
+ STDOUT_PATH="./fifo" catch_out_err_and_rc vfd_swmr_zoo_reader \
+ ../vfd_swmr_zoo_reader -q -W &
+ pid_reader=$!
+
+ # Wait for the reader to finish before signalling the
+ # writer to quit: the writer holds the file open so that the
+ # reader will find the shadow file when it opens
+ # the .h5 file.
+ wait $pid_reader
+ kill -USR1 $(cat vfd_swmr_zoo_writer.pid)
+ wait $pid_writer
+
+ # Collect exit code of the reader
+ if [ $(cat vfd_swmr_zoo_reader.rc) -ne 0 ]; then
+ echo reader had error
+ nerrors=$((nerrors + 1))
+ fi
+
+ # Collect exit code of the writer
+ if [ $(cat vfd_swmr_zoo_writer.rc) -ne 0 ]; then
+ echo writer had error
+ nerrors=$((nerrors + 1))
+ fi
+
+ # Clean up output files
+ rm -f ./fifo
+ rm -f vfd_swmr_zoo_writer.{out,rc}
+ rm -f vfd_swmr_zoo_reader.*.{out,rc}
+fi
+
+#
+# Make sure that we can create 10000 groups while a reader waits
+# for each to appear.
+#
+if [ ${do_groups:-no} = yes ]; then
+ echo launch vfd_swmr_group_writer
+ catch_out_err_and_rc vfd_swmr_group_writer \
+ ../vfd_swmr_group_writer -q -u 10 -n 10000 &
+ pid_writer=$!
+
+ catch_out_err_and_rc vfd_swmr_group_reader \
+ ../vfd_swmr_group_reader -q -u 10 -n 10000 -W &
+ pid_reader=$!
+
+ # Wait for the reader to finish before signalling the
+ # writer to quit: the writer holds the file open so that the
+ # reader will find the shadow file when it opens
+ # the .h5 file.
+ wait $pid_reader
+ kill -USR1 $(cat vfd_swmr_group_writer.pid)
+ wait $pid_writer
+
+ # Collect exit code of the reader
+ if [ $(cat vfd_swmr_group_reader.rc) -ne 0 ]; then
+ echo reader had error
+ nerrors=$((nerrors + 1))
+ fi
+
+ # Collect exit code of the writer
+ if [ $(cat vfd_swmr_group_writer.rc) -ne 0 ]; then
+ echo writer had error
+ nerrors=$((nerrors + 1))
+ fi
+
+ # Clean up output files
+ rm -f vfd_swmr_group_writer.{out,rc}
+ rm -f vfd_swmr_group_reader.*.{out,rc}
+fi
+
+for options in "-d 1" "-d 2" "-d 1 -V" "-d 1 -M"; do
+ if [ ${do_many_small:-no} = no ]; then
+ continue
+ fi
+ #
+ # Test many small datasets of one and two dimensions.
+ #
+ # Perform 50 iterations on 1000 extensible datasets configured with
+ # 16x16 chunks of 32-bit unsigned integer elements,
+ # expanding each dataset by a chunk in one dimension (up to 50x1
+ # 16x16 chunks) on each iteration.
+ #
+ # Perform the test again, extending each dataset
+ # in *two* dimensions (up to 50x50 16x16 chunks).
+ #
+ echo launch vfd_swmr_bigset_writer many small, options $options
+ catch_out_err_and_rc vfd_swmr_bigset_writer \
+ ../vfd_swmr_bigset_writer -n 50 $options -s 1000 -r 16 -c 16 -q &
+ pid_writer=$!
+
+ catch_out_err_and_rc vfd_swmr_bigset_reader \
+ ../vfd_swmr_bigset_reader -n 50 $options -s 1000 -r 16 -c 16 -q -W &
+ pid_reader=$!
+
+ # Wait for the reader to finish before signalling the
+ # writer to quit: the writer holds the file open so that the
+ # reader will find the shadow file when it opens
+ # the .h5 file.
+ wait $pid_reader
+ kill -USR1 $(cat vfd_swmr_bigset_writer.pid)
+ wait $pid_writer
+
+ # Collect exit code of the reader
+ if [ $(cat vfd_swmr_bigset_reader.rc) -ne 0 ]; then
+ echo reader had error
+ nerrors=$((nerrors + 1))
+ fi
+
+ # Collect exit code of the writer
+ if [ $(cat vfd_swmr_bigset_writer.rc) -ne 0 ]; then
+ echo writer had error
+ nerrors=$((nerrors + 1))
+ fi
+
+ # Clean up output files
+ rm -f vfd_swmr_bigset_writer.{out,rc}
+ rm -f vfd_swmr_bigset_reader.*.{out,rc}
+done
+
+for options in "-d 1" "-d 2" "-d 1 -V" "-d 1 -M"; do
+ #
+ # Test a few big datasets of one and two dimensions.
+ #
+ # Perform 50 iterations on 5 extensible datasets configured with
+ # 256x256 chunks of 32-bit unsigned integer elements,
+ # expanding each dataset by a chunk in one dimension (up to 50x1
+ # 256x256 chunks) on each iteration.
+ #
+ # Perform the test again, extending each dataset
+ # in *two* dimensions (up to 50x50 256x256 chunks).
+ #
+ if [ ${do_few_big:-no} = no ]; then
+ continue
+ fi
+ echo launch vfd_swmr_bigset_writer few big, options $options
+ catch_out_err_and_rc vfd_swmr_bigset_writer \
+ ../vfd_swmr_bigset_writer -n 50 $options -s 40 -r 256 -c 256 -q &
+ pid_writer=$!
+
+ catch_out_err_and_rc vfd_swmr_bigset_reader \
+ ../vfd_swmr_bigset_reader -n 50 $options -s 40 -r 256 -c 256 -q -W &
+ pid_reader=$!
+
+ # Wait for the reader to finish before signalling the
+ # writer to quit: the writer holds the file open so that the
+ # reader will find the shadow file when it opens
+ # the .h5 file.
+ wait $pid_reader
+ kill -USR1 $(cat vfd_swmr_bigset_writer.pid)
+ wait $pid_writer
+
+ # Collect exit code of the reader
+ if [ $(cat vfd_swmr_bigset_reader.rc) -ne 0 ]; then
+ echo reader had error
+ nerrors=$((nerrors + 1))
+ fi
+
+ # Collect exit code of the writer
+ if [ $(cat vfd_swmr_bigset_writer.rc) -ne 0 ]; then
+ echo writer had error
+ nerrors=$((nerrors + 1))
+ fi
+
+ # Clean up output files
+ rm -f vfd_swmr_bigset_writer.{out,rc}
+ rm -f vfd_swmr_bigset_reader.*.{out,rc}
+done
+
+###############################################################################
+## Report and exit
+###############################################################################
+cd ..
+$DPRINT nerrors $nerrors nsofterrors $nsofterrors
+if test $nerrors -eq 0 ; then
+ echo "VFD SWMR tests passed."
+ if test $nsofterrors -ne 0 ; then
+ echo
+ echo "${nsofterrors} soft errors occurred. That's safe to ignore."
+ fi
+ if test -z "$HDF5_NOCLEANUP"; then
+ # delete the test directory
+ rm -rf vfd_swmr_test
+ fi
+ exit 0
+else
+ echo -n "VFD SWMR tests failed with $nerrors hard errors "
+ echo "and $nsofterrors soft errors."
+ exit 1
+fi
+
diff --git a/test/tmisc.c b/test/tmisc.c
index 6eb6872..f35daac 100644
--- a/test/tmisc.c
+++ b/test/tmisc.c
@@ -135,6 +135,7 @@ typedef struct
#ifndef H5_HAVE_PARALLEL
#define MISC8_DSETNAME2 "Dataset2"
#define MISC8_DSETNAME3 "Dataset3"
+#define MISC8_DSETNAME4 "Dataset4"
#define MISC8_DSETNAME6 "Dataset6"
#define MISC8_DSETNAME7 "Dataset7"
#define MISC8_DSETNAME9 "Dataset9"
diff --git a/test/unlink.c b/test/unlink.c
index 48dd79d..16d5d0c 100644
--- a/test/unlink.c
+++ b/test/unlink.c
@@ -1259,7 +1259,7 @@ test_create_unlink(const char *msg, hid_t fapl)
char groupname[1024];
char filename[1024];
- TESTING(msg);
+ TESTING("%s", msg);
/* Create file */
h5_fixname(FILENAME[3], fapl, filename, sizeof filename);
diff --git a/test/vfd_swmr.c b/test/vfd_swmr.c
new file mode 100644
index 0000000..d49629f
--- /dev/null
+++ b/test/vfd_swmr.c
@@ -0,0 +1,3474 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/***********************************************************
+*
+* Test program:
+*
+* Tests the VFD SWMR Feature.
+*
+*************************************************************/
+
+#include "H5queue.h"
+#include "h5test.h"
+#include "vfd_swmr_common.h"
+
+/*
+ * This file needs to access private information from the H5F package.
+ */
+
+#define H5F_FRIEND /*suppress error about including H5Fpkg */
+#define H5FD_FRIEND /*suppress error about including H5FDpkg */
+#define H5F_TESTING
+#define H5FD_TESTING
+#include "H5FDprivate.h"
+#include "H5Fpkg.h"
+#include "H5FDpkg.h"
+#include "H5Iprivate.h"
+
+#define H5FD_FRIEND /*suppress error about including H5FDpkg */
+#include "H5FDpkg.h"
+
+#define FS_PAGE_SIZE 512
+#define FILENAME "vfd_swmr_file.h5"
+#define MD_FILENAME "vfd_swmr_metadata_file"
+
+#define FILENAME2 "vfd_swmr_file2.h5"
+#define MD_FILENAME2 "vfd_swmr_metadata_file2"
+
+#define FILENAME3 "vfd_swmr_file3.h5"
+#define MD_FILENAME3 "vfd_swmr_metadata_file3"
+
+#define FNAME "non_vfd_swmr_file.h5"
+
+/* test routines for VFD SWMR */
+static unsigned test_fapl(void);
+static unsigned test_file_end_tick(void);
+static unsigned test_file_fapl(void);
+static unsigned test_writer_md(void);
+
+/* helper routines */
+static hid_t
+init_vfd_swmr_config_fapl(H5F_vfd_swmr_config_t *config, uint32_t tick_len, uint32_t max_lag,
+ hbool_t is_writer, uint32_t md_pages_reserved, const char *md_file_path, size_t pbuf_size);
+
+/*-------------------------------------------------------------------------
+ * Function: init_vfd_swmr_config_fapl
+ *
+ * Purpose: Helper routine to initialize the fields for VFD SWMR configuration
+ *
+ * Return: void
+ *
+ *-------------------------------------------------------------------------
+ */
+static hid_t
+init_vfd_swmr_config_fapl(H5F_vfd_swmr_config_t *config, uint32_t tick_len, uint32_t max_lag,
+ hbool_t is_writer, uint32_t md_pages_reserved, const char *md_file_path, size_t pbuf_size)
+{
+ hid_t fapl;
+
+ HDmemset(config, 0, sizeof(*config));
+
+ config->version = H5F__CURR_VFD_SWMR_CONFIG_VERSION;
+ config->tick_len = tick_len;
+ config->max_lag = max_lag;
+ config->writer = is_writer;
+ config->md_pages_reserved = md_pages_reserved;
+ HDstrcpy(config->md_file_path, md_file_path);
+
+ /* Create a copy of the file access property list */
+ if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0)
+ return H5I_INVALID_HID;
+
+ if(H5Pset_vfd_swmr_config(fapl, config) < 0) {
+ (void)H5Pclose(fapl);
+ return H5I_INVALID_HID;
+ }
+
+ /* Enable page buffering */
+ if(pbuf_size != 0 && H5Pset_page_buffer_size(fapl, pbuf_size, 0, 0) < 0) {
+ (void)H5Pclose(fapl);
+ return H5I_INVALID_HID;
+ }
+
+ return fapl;
+} /* init_vfd_swmr_config_fapl() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_fapl()
+ *
+ * Purpose: A) Verify that invalid info set in the fapl fails
+ * as expected (see the RFC for VFD SWMR):
+ * --version: should be a known version
+ * --tick_len: should be >= 0
+ * --max_lag: should be >= 3
+ * --md_pages_reserved: should be >= 2
+ * --md_file_path: should contain the metadata file path (POSIX)
+ * B) Verify that info set in the fapl is retrieved correctly.
+ *
+ * Return: 0 if test is sucessful
+ * 1 if test fails
+ *
+ * Programmer: Vailin Choi; July 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static unsigned
+test_fapl(void)
+{
+ hid_t fapl = -1; /* File access property list */
+ H5F_vfd_swmr_config_t *my_config = NULL; /* Configuration for VFD SWMR */
+ herr_t ret; /* Return value */
+
+ TESTING("Configure VFD SWMR with fapl");
+
+ /* Allocate memory for the configuration structure */
+ if((my_config = HDmalloc(sizeof(*my_config))) == NULL)
+ FAIL_STACK_ERROR;
+ HDmemset(my_config, 0, sizeof(*my_config));
+
+ /* Get a copy of the file access property list */
+ if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0)
+ TEST_ERROR;
+
+ /* Should get invalid VFD SWMR config info */
+ if(H5Pget_vfd_swmr_config(fapl, my_config) < 0)
+ TEST_ERROR;
+
+ /* Verify that the version is incorrect */
+ if(my_config->version >= H5F__CURR_VFD_SWMR_CONFIG_VERSION)
+ TEST_ERROR;
+
+ /* Should fail: version is 0 */
+ H5E_BEGIN_TRY {
+ ret = H5Pset_vfd_swmr_config(fapl, my_config);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR;
+
+ /* Set valid version */
+ my_config->version = H5F__CURR_VFD_SWMR_CONFIG_VERSION;
+
+ /* Set valid tick_len */
+ my_config->tick_len = 3;
+ /* Should fail: max_lag is 2 */
+ my_config->max_lag = 2;
+ H5E_BEGIN_TRY {
+ ret = H5Pset_vfd_swmr_config(fapl, my_config);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR;
+
+ /* Set valid max_lag */
+ my_config->max_lag = 3;
+ /* Should fail: md_pages_reserved is 0 */
+ H5E_BEGIN_TRY {
+ ret = H5Pset_vfd_swmr_config(fapl, my_config);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR;
+
+ /* Set valid md_pages_reserved */
+ my_config->md_pages_reserved = 2;
+ /* Should fail: empty md_file_path */
+ H5E_BEGIN_TRY {
+ ret = H5Pset_vfd_swmr_config(fapl, my_config);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR;
+
+ /* Set md_file_path */
+ HDstrcpy(my_config->md_file_path, MD_FILENAME);
+ my_config->writer = TRUE;
+
+ /* Should succeed in setting the configuration info */
+ if(H5Pset_vfd_swmr_config(fapl, my_config) < 0)
+ TEST_ERROR;
+
+ /* Clear the configuration structure */
+ HDmemset(my_config, 0, sizeof(H5F_vfd_swmr_config_t));
+
+ /* Retrieve the configuration info just set */
+ if(H5Pget_vfd_swmr_config(fapl, my_config) < 0)
+ TEST_ERROR;
+
+ /* Verify the configuration info */
+ if(my_config->version < H5F__CURR_VFD_SWMR_CONFIG_VERSION)
+ TEST_ERROR;
+ if(my_config->md_pages_reserved != 2)
+ TEST_ERROR;
+ if(HDstrcmp(my_config->md_file_path, MD_FILENAME) != 0)
+ TEST_ERROR;
+
+ /* Close the file access property list */
+ if(H5Pclose(fapl) < 0)
+ FAIL_STACK_ERROR;
+
+ if(my_config)
+ HDfree(my_config);
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(fapl);
+ } H5E_END_TRY;
+ if(my_config)
+ HDfree(my_config);
+ return 1;
+} /* test_fapl() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_file_fapl()
+ *
+ * Purpose: A) Verify that page buffering and paged aggregation
+ * have to be enabled for a file to be configured
+ * with VFD SWMR.
+ * B) Verify that the "writer" setting in the fapl's VFD
+ * SWMR configuration should be consistent with the
+ * file access flags.
+ * C) Verify the VFD SWMR configuration set in fapl
+ * used to create/open the file is the same as the
+ * configuration retrieved from the file's fapl.
+ *
+ * Return: 0 if test is sucessful
+ * 1 if test fails
+ *
+ * Programmer: Vailin Choi; July 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static unsigned
+test_file_fapl(void)
+{
+ hid_t fid = -1; /* File ID */
+ hid_t fid2 = -1; /* File ID */
+ hid_t fcpl = -1; /* File creation property list ID */
+ hid_t fapl1 = -1; /* File access property list ID */
+ hid_t fapl2 = -1; /* File access property list ID */
+ hid_t file_fapl = -1; /* File access property list ID associated with the file */
+ H5F_vfd_swmr_config_t *config1 = NULL; /* Configuration for VFD SWMR */
+ H5F_vfd_swmr_config_t *config2 = NULL; /* Configuration for VFD SWMR */
+ H5F_vfd_swmr_config_t *file_config = NULL; /* Configuration for VFD SWMR */
+
+ TESTING("VFD SWMR configuration for the file and fapl");
+
+ /* Should succeed without VFD SWMR configured */
+ if((fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR;
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Allocate memory for the configuration structure */
+ if((config1 = (H5F_vfd_swmr_config_t *)HDmalloc(sizeof(H5F_vfd_swmr_config_t))) == NULL)
+ FAIL_STACK_ERROR;
+ if((config2 = (H5F_vfd_swmr_config_t *)HDmalloc(sizeof(H5F_vfd_swmr_config_t))) == NULL)
+ FAIL_STACK_ERROR;
+ if((file_config = (H5F_vfd_swmr_config_t *)HDmalloc(sizeof(H5F_vfd_swmr_config_t))) == NULL)
+ FAIL_STACK_ERROR;
+
+ /* Configured as VFD SWMR reader + no page buffering */
+ fapl1 = init_vfd_swmr_config_fapl(config1, 4, 6, FALSE, 2, MD_FILENAME, 0);
+ if(fapl1 == H5I_INVALID_HID)
+ TEST_ERROR
+
+ /* Should fail to create: file access is writer but VFD SWMR config is reader */
+ H5E_BEGIN_TRY {
+ fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, fapl1);
+ } H5E_END_TRY;
+ if(fid >= 0)
+ TEST_ERROR;
+
+ if(H5Pclose(fapl1) < 0)
+ FAIL_STACK_ERROR
+
+ /* Configured as VFD SWMR writer + no page buffering */
+ fapl1 = init_vfd_swmr_config_fapl(config1, 4, 6, TRUE, 2, MD_FILENAME, 0);
+ if(fapl1 == H5I_INVALID_HID)
+ TEST_ERROR
+
+ /* Should fail to create: page buffering and paged aggregation not enabled */
+ H5E_BEGIN_TRY {
+ fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, fapl1);
+ } H5E_END_TRY;
+ if(fid >= 0)
+ TEST_ERROR;
+
+ /* Create a copy of the file creation property list */
+ if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set file space strategy */
+ if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, FALSE, 1) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should fail to create: no page buffering */
+ H5E_BEGIN_TRY {
+ fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, fapl1);
+ } H5E_END_TRY;
+ if(fid >= 0)
+ TEST_ERROR;
+
+ if(H5Pclose(fapl1) < 0)
+ FAIL_STACK_ERROR
+
+ /* Configured as VFD SWMR writer + page buffering */
+ fapl1 = init_vfd_swmr_config_fapl(config1, 4, 6, TRUE, 2, MD_FILENAME, 4096);
+ if(fapl1 == H5I_INVALID_HID)
+ TEST_ERROR
+
+ /* Should succeed to create the file: paged aggregation and page buffering enabled */
+ if((fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, fapl1)) < 0)
+ TEST_ERROR;
+
+ /* Get the file's file access property list */
+ if((file_fapl = H5Fget_access_plist(fid)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Retrieve the VFD SWMR configuration from file_fapl */
+ if(H5Pget_vfd_swmr_config(file_fapl, file_config) < 0)
+ TEST_ERROR;
+
+ /* Verify the retrieved info is the same as config1 */
+ if(HDmemcmp(config1, file_config, sizeof(H5F_vfd_swmr_config_t)) != 0)
+ TEST_ERROR;
+
+ /* Closing */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(file_fapl) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should fail to open: file access is reader but VFD SWMR config is writer */
+ H5E_BEGIN_TRY {
+ fid = H5Fopen(FILENAME, H5F_ACC_RDONLY, fapl1);
+ } H5E_END_TRY;
+ if(fid >= 0)
+ TEST_ERROR;
+
+ /* Should succeed to open: file access and VFD SWMR config are consistent */
+ if((fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl1)) < 0)
+ TEST_ERROR;
+
+ /* Get the file's file access property list */
+ if((file_fapl = H5Fget_access_plist(fid)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Clear info in file_config */
+ HDmemset(file_config, 0, sizeof(H5F_vfd_swmr_config_t));
+
+ /* Retrieve the VFD SWMR configuration from file_fapl */
+ if(H5Pget_vfd_swmr_config(file_fapl, file_config) < 0)
+ TEST_ERROR;
+
+ /* Verify the retrieved info is the same as config1 */
+ if(HDmemcmp(config1, file_config, sizeof(H5F_vfd_swmr_config_t)) != 0)
+ TEST_ERROR;
+
+ /* Closing */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(file_fapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(fapl1) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Set up different VFD SWMR configuration + page_buffering */
+ fapl2 = init_vfd_swmr_config_fapl(config2, 4, 10, TRUE, 2, MD_FILENAME, 4096);
+ if(fapl2 == H5I_INVALID_HID)
+ TEST_ERROR
+
+ /* Should succeed to open the file as VFD SWMR writer */
+ if((fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl2)) < 0)
+ TEST_ERROR;
+
+ /* Get the file's file access property list */
+ if((file_fapl = H5Fget_access_plist(fid)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Clear info in file_config */
+ HDmemset(file_config, 0, sizeof(H5F_vfd_swmr_config_t));
+
+ /* Retrieve the VFD SWMR configuration from file_fapl */
+ if(H5Pget_vfd_swmr_config(file_fapl, file_config) < 0)
+ TEST_ERROR;
+
+ /* Verify the retrieved info is NOT the same as config1 */
+ if(HDmemcmp(config1, file_config, sizeof(H5F_vfd_swmr_config_t)) == 0)
+ TEST_ERROR;
+
+ /* Verify the retrieved info is the same as config2 */
+ if(HDmemcmp(config2, file_config, sizeof(H5F_vfd_swmr_config_t)) != 0)
+ TEST_ERROR;
+
+ /* The file previously opened as VDF SWMR writer is still open */
+ /* with VFD SWMR configuration in config2 */
+
+ /* Set up as VFD SWMR writer in config1 but different from config2 */
+ fapl1 = init_vfd_swmr_config_fapl(config1, 3, 8, TRUE, 3, MD_FILENAME, 4096);
+ if(fapl1 == H5I_INVALID_HID)
+ TEST_ERROR;
+
+ /* Re-open the same file with config1 */
+ /* Should fail to open since config1 is different from config2 setting */
+ H5E_BEGIN_TRY {
+ fid2 = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl1);
+ } H5E_END_TRY;
+ if(fid2 >= 0)
+ TEST_ERROR;
+
+ /* Close fapl1 */
+ if(H5Pclose(fapl1) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Set up as VFD SWMR reader in config1 which is same as config2 */
+ fapl1 = init_vfd_swmr_config_fapl(config1, 4, 10, TRUE, 2, MD_FILENAME, 4096);
+ if(fapl1 == H5I_INVALID_HID)
+ TEST_ERROR;
+
+ /* Re-open the same file as VFD SWMR writer */
+ /* Should succeed since config1 is same as the setting in config2 */
+ if((fid2 = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl1)) < 0)
+ TEST_ERROR
+
+ /* Close fapl1 */
+ if(H5Pclose(fapl1) < 0)
+ FAIL_STACK_ERROR;
+
+ HDmemset(file_config, 0, sizeof(H5F_vfd_swmr_config_t));
+
+ /* Get the file's file access property list */
+ if((file_fapl = H5Fget_access_plist(fid)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Retrieve the VFD SWMR configuration from file_fapl */
+ if(H5Pget_vfd_swmr_config(file_fapl, file_config) < 0)
+ TEST_ERROR;
+
+ /* Should be the same as config1 */
+ if(HDmemcmp(config1, file_config, sizeof(H5F_vfd_swmr_config_t)) != 0)
+ TEST_ERROR;
+
+ /* Should be the the same as config2 */
+ if(HDmemcmp(config2, file_config, sizeof(H5F_vfd_swmr_config_t)) != 0)
+ TEST_ERROR;
+
+ /* Closing */
+ if(H5Fclose(fid2) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ if(H5Pclose(fapl2) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(file_fapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(fcpl) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Free buffers */
+ if(config1)
+ HDfree(config1);
+ if(config2)
+ HDfree(config2);
+ if(file_config)
+ HDfree(file_config);
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(fapl1);
+ H5Pclose(fapl2);
+ H5Pclose(file_fapl);
+ H5Pclose(fcpl);
+ H5Fclose(fid);
+ H5Fclose(fid2);
+ } H5E_END_TRY;
+ if(config1)
+ HDfree(config1);
+ if(config2)
+ HDfree(config2);
+ if(file_config)
+ HDfree(file_config);
+ return 1;
+} /* test_file_fapl() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_file_end_tick()
+ *
+ * Purpose: Verify the public routine H5Fvfd_swmr_end_tick() works
+ * as described in the RFC for VFD SWMR.
+ *
+ * Return: 0 if test is sucessful
+ * 1 if test fails
+ *
+ * Programmer: Vailin Choi; June 2020
+ *
+ *-------------------------------------------------------------------------
+ */
+static unsigned
+test_file_end_tick(void)
+{
+ hid_t fid1 = H5I_INVALID_HID; /* File ID */
+ hid_t fid2 = H5I_INVALID_HID; /* File ID */
+ hid_t fid3 = H5I_INVALID_HID; /* File ID */
+ hid_t fcpl = H5I_INVALID_HID; /* File creation property list ID */
+ hid_t fapl1 = H5I_INVALID_HID; /* File access property list ID */
+ hid_t fapl2 = H5I_INVALID_HID; /* File access property list ID */
+ hid_t fapl3 = H5I_INVALID_HID; /* File access property list ID */
+ H5F_vfd_swmr_config_t *config1 = NULL; /* Configuration for VFD SWMR */
+ H5F_vfd_swmr_config_t *config2 = NULL; /* Configuration for VFD SWMR */
+ H5F_vfd_swmr_config_t *config3 = NULL; /* Configuration for VFD SWMR */
+ H5F_t *f1, *f2, *f3; /* File pointer */
+ uint64_t s1 = 0; /* Saved tick_num */
+ uint64_t s2 = 0; /* Saved tick_num */
+ uint64_t s3 = 0; /* Saved tick_num */
+ int ret; /* Return status */
+
+ TESTING("H5Fvfd_swmr_end_tick()");
+
+ /* Create a file without VFD SWMR configured */
+ if((fid1 = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR;
+
+ /* Should fail to trigger EOT */
+ H5E_BEGIN_TRY {
+ ret = H5Fvfd_swmr_end_tick(fid1);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR;
+
+ /* Close the file */
+ if(H5Fclose(fid1) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Allocate memory for the configuration structure */
+ if((config1 = HDmalloc(sizeof(*config1))) == NULL)
+ FAIL_STACK_ERROR;
+ if((config2 = HDmalloc(sizeof(*config2))) == NULL)
+ FAIL_STACK_ERROR;
+ if((config3 = HDmalloc(sizeof(*config3))) == NULL)
+ FAIL_STACK_ERROR;
+
+ /* Configured file 1 as VFD SWMR writer + page buffering */
+ fapl1 = init_vfd_swmr_config_fapl(config1, 10, 15, TRUE, 2, MD_FILENAME, 4096);
+ if(fapl1 == H5I_INVALID_HID)
+ FAIL_STACK_ERROR;
+
+ /* Configured file 2 as VFD SWMR writer + page buffering */
+ fapl2 = init_vfd_swmr_config_fapl(config2, 5, 6, TRUE, 2, MD_FILENAME2, 4096);
+ if(fapl2 == H5I_INVALID_HID)
+ FAIL_STACK_ERROR;
+
+ /* Configured file 3 as VFD SWMR writer + page buffering */
+ fapl3 = init_vfd_swmr_config_fapl(config3, 3, 6, TRUE, 2, MD_FILENAME3, 4096);
+ if(fapl3 == H5I_INVALID_HID)
+ FAIL_STACK_ERROR;
+
+ /* Create a copy of the file creation property list */
+ if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set file space strategy */
+ if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, FALSE, 1) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Create file 1 with VFD SWMR writer */
+ if((fid1 = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, fapl1)) < 0)
+ TEST_ERROR;
+ /* Keep file 1 opened */
+
+ /* Create file 2 with VFD SWMR writer */
+ if((fid2 = H5Fcreate(FILENAME2, H5F_ACC_TRUNC, fcpl, fapl2)) < 0)
+ TEST_ERROR;
+ if(H5Fclose(fid2) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Create file 3 with VFD SWMR writer */
+ if((fid3 = H5Fcreate(FILENAME3, H5F_ACC_TRUNC, fcpl, fapl3)) < 0)
+ TEST_ERROR;
+ if(H5Fclose(fid3) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Open file 2 as VFD SWMR writer */
+ if((fid2 = H5Fopen(FILENAME2, H5F_ACC_RDWR, fapl2)) < 0)
+ TEST_ERROR;
+
+ /* Open file 3 as VFD SWMR writer */
+ if((fid3 = H5Fopen(FILENAME3, H5F_ACC_RDWR, fapl3)) < 0)
+ TEST_ERROR;
+
+ /* Get file pointer for the 3 files */
+ f1 = H5VL_object(fid1);
+ f2 = H5VL_object(fid2);
+ f3 = H5VL_object(fid3);
+
+ /* Saved tick_num for the 3 files */
+ s1 = f1->shared->tick_num;
+ s2 = f2->shared->tick_num;
+ s3 = f3->shared->tick_num;
+
+ /* Trigger EOT for file 2 */
+ if(H5Fvfd_swmr_end_tick(fid2) < 0)
+ TEST_ERROR;
+
+ /* file 2: tick_num should increase or at least same as previous tick_num */
+ if(f2->shared->tick_num < s2)
+ TEST_ERROR;
+
+ /* Disable EOT for file 2 */
+ if(H5Fvfd_swmr_disable_end_of_tick(fid2) < 0)
+ TEST_ERROR;
+
+ /* Should fail to trigger end of tick processing for file 2 */
+ H5E_BEGIN_TRY {
+ ret = H5Fvfd_swmr_end_tick(fid2);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR;
+
+ if(H5Fclose(fid2) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Trigger EOT for file 1 */
+ if(H5Fvfd_swmr_end_tick(fid1) < 0)
+ TEST_ERROR;
+
+ /* file 1: tick_num should increase or at least same as previous tick_num */
+ if(f1->shared->tick_num < s1)
+ TEST_ERROR;
+
+ if(H5Fclose(fid1) < 0)
+ FAIL_STACK_ERROR;
+
+
+ /* Trigger EOT for file 3 */
+ if(H5Fvfd_swmr_end_tick(fid3) < 0)
+ TEST_ERROR;
+
+ /* file 3: tick_num should increase or at least same as previous tick_num */
+ if(f3->shared->tick_num < s3)
+ TEST_ERROR;
+
+ if(H5Fclose(fid3) < 0)
+ FAIL_STACK_ERROR;
+
+
+ /* Closing */
+ if(H5Pclose(fapl1) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(fapl2) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(fapl3) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(fcpl) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Free buffers */
+ if(config1)
+ HDfree(config1);
+ if(config2)
+ HDfree(config2);
+ if(config3)
+ HDfree(config3);
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(fapl1);
+ H5Pclose(fapl2);
+ H5Pclose(fapl3);
+ H5Pclose(fcpl);
+ H5Fclose(fid1);
+ H5Fclose(fid2);
+ H5Fclose(fid3);
+ } H5E_END_TRY;
+
+ if(config1)
+ HDfree(config1);
+ if(config2)
+ HDfree(config2);
+ if(config3)
+ HDfree(config3);
+
+ return 1;
+} /* test_file_end_tick() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_writer_create_open_flush()
+ *
+ * Purpose: Verify info in the metadata file when:
+ * --creating the HDF5 file
+ * --flushing the HDF5 file
+ * --opening an existing HDF5 file
+ * It will call the internal testing routine
+ * H5F__vfd_swmr_writer_create_open_flush_test() to do the following:
+ * --Open the metadata file
+ * --Verify the file size is as expected (md_pages_reserved)
+ * --For file create:
+ * --No header magic is found
+ * --For file open or file flush:
+ * --Read and decode the header and index in the metadata file
+ * --Verify info in the header and index read from
+ * the metadata file is as expected (empty index)
+ *
+ * Return: 0 if test is sucessful
+ * 1 if test fails
+ *
+ * Programmer: Vailin Choi; October 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static unsigned
+test_writer_create_open_flush(void)
+{
+ hid_t fid = -1; /* File ID */
+ hid_t fapl = -1; /* File access property list */
+ hid_t fcpl = -1; /* File creation property list */
+ H5F_vfd_swmr_config_t *my_config = NULL; /* Configuration for VFD SWMR */
+
+ TESTING("Create/Open/Flush an HDF5 file for VFD SWMR");
+
+ /* Allocate memory for the configuration structure */
+ if((my_config = HDmalloc(sizeof(H5F_vfd_swmr_config_t))) == NULL)
+ FAIL_STACK_ERROR;
+
+ /* Set up the VFD SWMR configuration + page buffering */
+ fapl = init_vfd_swmr_config_fapl(my_config, 1, 3, TRUE, 2, MD_FILENAME, 4096);
+ if(fapl == H5I_INVALID_HID)
+ FAIL_STACK_ERROR;
+
+ /* Create a copy of the file creation property list */
+ if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set file space strategy */
+ if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, FALSE, 1) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Create an HDF5 file with VFD SWMR configured */
+ if((fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Verify info in metadata file when creating the HDF5 file */
+ if(H5F__vfd_swmr_writer_create_open_flush_test(fid, TRUE) < 0)
+ FAIL_STACK_ERROR;
+
+#ifdef LATER /* Will activate the test when flush is implemented */
+ /* Flush the HDF5 file */
+ if(H5Fflush(fid, H5F_SCOPE_GLOBAL) < 0)
+ FAIL_STACK_ERROR
+
+ /* Verify info in metadata file when flushing the HDF5 file */
+ if(H5F__vfd_swmr_writer_create_open_flush_test(fid, FALSE) < 0)
+ FAIL_STACK_ERROR
+#endif
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Re-open the file as VFD SWMR writer */
+ if((fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Verify info in metadata file when reopening the HDF5 file */
+ if(H5F__vfd_swmr_writer_create_open_flush_test(fid, FALSE) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Closing */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(fapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(fcpl) < 0)
+ FAIL_STACK_ERROR;
+
+ if(my_config)
+ HDfree(my_config);
+
+ PASSED();
+ return 0;
+
+error:
+ if(my_config)
+ HDfree(my_config);
+
+ H5E_BEGIN_TRY {
+ H5Pclose(fapl);
+ H5Pclose(fcpl);
+ H5Fclose(fid);
+ } H5E_END_TRY;
+
+ return 1;
+} /* test_writer_create_open_flush() */
+
+/* Sleep for `tenths` tenths of a second.
+ *
+ * This routine may quietly perform a too-short sleep if an error occurs
+ * in nanosleep(2).
+ */
+static void
+decisleep(uint32_t tenths)
+{
+ struct timespec delay = {.tv_sec = tenths / 10,
+ .tv_nsec = tenths * 100 * 1000 * 1000};
+
+ while (nanosleep(&delay, &delay) == -1 && errno == EINTR)
+ ; // do nothing
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_writer_md()
+ *
+ * Purpose: Verify info in the metadata file after updating with the
+ * constructed index: (A), (B), (C), (D)
+ * It will call the internal testing routine
+ * H5F__vfd_swmr_writer_md_test() to do the following:
+ * --Update the metadata file with the input index via the
+ * internal library routine H5F_update_vfd_swmr_metadata_file()
+ * --Verify the entries in the delayed list is as expected:
+ * --num_dl_entries
+ * --Open the metadata file, read and decode the header and index
+ * --Verify header and index info just read from the metadata
+ * file is as expected:
+ * --num_entries and index
+ *
+ * Return: 0 if test is sucessful
+ * 1 if test fails
+ *
+ * Programmer: Vailin Choi; October 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static unsigned
+test_writer_md(void)
+{
+ hid_t fid = -1; /* File ID */
+ hid_t fapl = -1; /* File access property list */
+ hid_t fcpl = -1; /* File creation property list */
+ const unsigned num_entries = 10; /* index size */
+ unsigned i = 0; /* Local index variables */
+ uint8_t *buf = NULL; /* Data page from the page buffer */
+ hid_t dcpl = -1; /* Dataset creation property list */
+ hid_t sid = -1; /* Dataspace ID */
+ hid_t did = -1; /* Dataset ID */
+ int *rwbuf = NULL; /* Data buffer for writing */
+ H5O_info_t oinfo; /* Object metadata information */
+ char dname[100]; /* Name of dataset */
+ hsize_t dims[2] = {50, 20}; /* Dataset dimension sizes */
+ hsize_t max_dims[2] = {H5S_UNLIMITED, H5S_UNLIMITED}; /* Dataset maximum dimension sizes */
+ hsize_t chunk_dims[2] = {2, 5}; /* Dataset chunked dimension sizes */
+ H5FD_vfd_swmr_idx_entry_t *index = NULL; /* Pointer to the index entries */
+ H5F_vfd_swmr_config_t *my_config = NULL; /* Configuration for VFD SWMR */
+
+ TESTING("Verify the metadata file for VFD SWMR writer");
+
+ /* Allocate memory for the configuration structure */
+ if((my_config = HDmalloc(sizeof(H5F_vfd_swmr_config_t))) == NULL)
+ FAIL_STACK_ERROR;
+
+ /* Set up the VFD SWMR configuration + page buffering */
+ fapl = init_vfd_swmr_config_fapl(my_config, 1, 3, TRUE, 256, MD_FILENAME, FS_PAGE_SIZE);
+ if(fapl == H5I_INVALID_HID)
+ FAIL_STACK_ERROR
+
+ /* Create a copy of the file creation property list */
+ if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set file space strategy */
+ if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, FALSE, 1) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pset_file_space_page_size(fcpl, FS_PAGE_SIZE) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Create an HDF5 file with VFD SWMR configured */
+ if((fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Allocate num_entries for the data buffer */
+ if((buf = HDcalloc(num_entries, FS_PAGE_SIZE)) == NULL)
+ FAIL_STACK_ERROR;
+
+ /* Allocate memory for num_entries index */
+ index = HDcalloc(num_entries, sizeof(H5FD_vfd_swmr_idx_entry_t));
+ if(NULL == index)
+ FAIL_STACK_ERROR;
+
+ /* (A) Construct index for updating the metadata file */
+ for(i = 0; i < num_entries; i++) {
+ index[i].hdf5_page_offset = 3 + 7 * i;
+ index[i].md_file_page_offset = 1 + (num_entries - i) * 5;
+ index[i].length = (uint32_t)FS_PAGE_SIZE;
+ index[i].entry_ptr = &buf[i * FS_PAGE_SIZE];
+ }
+
+ /* Update with index and verify info in the metadata file */
+ /* Also verify that 0 entries will be on the delayed list */
+ if(H5F__vfd_swmr_writer_md_test(fid, num_entries, index, 0) < 0)
+ TEST_ERROR
+
+ /* Create dataset creation property list */
+ if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set to use chunked dataset */
+ if(H5Pset_chunk(dcpl, 2, chunk_dims) < 0)
+ FAIL_STACK_ERROR
+
+ /* Create dataspace */
+ if((sid = H5Screate_simple(2, dims, max_dims)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Perform activities to ensure that max_lag ticks elapse */
+ for(i = 0; i < my_config->max_lag + 1; i++) {
+ decisleep(my_config->tick_len);
+
+ /* Create a chunked dataset */
+ sprintf(dname, "dset %d", i);
+ if((did = H5Dcreate2(fid, dname, H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Get dataset object header address */
+ if(H5Oget_info(did, &oinfo, H5O_INFO_BASIC) < 0)
+ FAIL_STACK_ERROR
+
+ /* Close the dataset */
+ if(H5Dclose(did) < 0)
+ FAIL_STACK_ERROR
+ }
+
+ /* (B) Update every other entry in the index */
+ for(i = 0; i < num_entries; i+= 2)
+ index[i].entry_ptr = &buf[i * FS_PAGE_SIZE];
+
+ /* Update with index and verify info in the metadata file */
+ /* Also verify that 5 entries will be on the delayed list */
+ if(H5F__vfd_swmr_writer_md_test(fid, num_entries, index, 5) < 0)
+ TEST_ERROR
+
+ /* Allocate memory for the read/write buffer */
+ if((rwbuf = HDmalloc(sizeof(*rwbuf) * (50 * 20))) == NULL)
+ FAIL_STACK_ERROR;
+ for(i = 0; i < (50 * 20); i++)
+ rwbuf[i] = (int)i;
+
+ /* Perform activities to ensure that max_lag ticks elapse */
+ for(i = 0; i < my_config->max_lag + 1; i++) {
+ decisleep(my_config->tick_len);
+
+ /* Open the dataset */
+ sprintf(dname, "dset %d", i);
+ if((did = H5Dopen2(fid, dname, H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Write to the dataset */
+ if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, rwbuf) < 0)
+ FAIL_STACK_ERROR
+
+ /* Get dataset object info */
+ if(H5Oget_info(did, &oinfo, H5O_INFO_BASIC) < 0)
+ FAIL_STACK_ERROR
+
+ /* Close the dataset */
+ if(H5Dclose(did) < 0)
+ FAIL_STACK_ERROR
+ }
+
+ /* (C) Update every 3 entry in the index */
+ for(i = 0; i < num_entries; i+= 3)
+ index[i].entry_ptr = &buf[i * FS_PAGE_SIZE];
+
+ /* Update with index and verify info in the metadata file */
+ /* Also verify that 4 entries will be on the delayed list */
+ if(H5F__vfd_swmr_writer_md_test(fid, num_entries, index, 4) < 0)
+ TEST_ERROR
+
+ /* Clear the read/write buffer */
+ HDmemset(rwbuf, 0, sizeof(sizeof(int) * (50 * 20)));
+
+ /* Perform activities to ensure that max_lag ticks elapse */
+ for(i = 0; i < my_config->max_lag + 1; i++) {
+ decisleep(my_config->tick_len);
+
+ /* Open the dataset */
+ sprintf(dname, "dset %d", i);
+ if((did = H5Dopen2(fid, dname, H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Read from the dataset */
+ if(H5Dread(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, rwbuf) < 0)
+ FAIL_STACK_ERROR
+
+ /* Get dataset object info */
+ if(H5Oget_info(did, &oinfo, H5O_INFO_BASIC) < 0)
+ FAIL_STACK_ERROR
+
+ /* Close the dataset */
+ if(H5Dclose(did) < 0)
+ FAIL_STACK_ERROR
+ }
+
+ /* (D) Update two entries in the index */
+ index[1].entry_ptr = &buf[1 * FS_PAGE_SIZE];
+ index[5].entry_ptr = &buf[5 * FS_PAGE_SIZE];
+
+ /* Update with index and verify info in the metadata file */
+ /* Also verify that 2 entries will be on the delayed list */
+ if(H5F__vfd_swmr_writer_md_test(fid, num_entries, index, 2) < 0)
+ TEST_ERROR
+
+ /* Closing */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Sclose(sid) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(dcpl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(fapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(fcpl) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Free resources */
+ if(my_config)
+ HDfree(my_config);
+ if(buf)
+ HDfree(buf);
+ if(rwbuf)
+ HDfree(rwbuf);
+ if(index)
+ HDfree(index);
+
+ PASSED();
+ return 0;
+
+error:
+ if(my_config)
+ HDfree(my_config);
+ if(buf)
+ HDfree(buf);
+ if(rwbuf)
+ HDfree(rwbuf);
+ if(index)
+ HDfree(index);
+
+ H5E_BEGIN_TRY {
+ H5Dclose(did);
+ H5Sclose(sid);
+ H5Pclose(dcpl);
+ H5Pclose(fapl);
+ H5Pclose(fcpl);
+ H5Fclose(fid);
+ } H5E_END_TRY;
+
+ return 1;
+} /* test_writer__md() */
+
+
+#if !(defined(H5_HAVE_FORK) && defined(H5_HAVE_WAITPID) && defined(H5_HAVE_FLOCK))
+
+static unsigned
+test_reader_md_concur(void)
+{
+ /* Output message about test being performed */
+ TESTING("Verify the metadata file for VFD SWMR reader");
+ SKIPPED();
+ HDputs(" Test skipped due to fork, waitpid, or flock not defined.");
+ return 0;
+
+} /* test_reader_md_concur() */
+
+static unsigned
+test_multiple_file_opens_concur(void)
+{
+ /* Output message about test being performed */
+ TESTING("EOT queue entries when opening files concurrently with VFD SWMR");
+ SKIPPED();
+ HDputs(" Test skipped due to fork, waitpid, or flock not defined.");
+ return 0;
+
+} /* test_multiple_file_opens_concur() */
+
+static unsigned
+test_disable_enable_eot_concur(void)
+
+ /* Output message about test being performed */
+ TESTING("Verify concurrent H5Fvfd_swmr_enable/disable_end_of_tick()");
+ SKIPPED();
+ HDputs(" Test skipped due to fork, waitpid, or flock not defined.");
+ return 0;
+
+} /* test_disable_enble_eot_concur() */
+
+#else /* defined(H5_HAVE_FORK && defined(H5_HAVE_WAITPID) && defined(H5_HAVE_FLOCK) */
+
+/*-------------------------------------------------------------------------
+ * Function: test_reader_md_concur()
+ *
+ * Purpose: Verify metadata file info updated by the writer is
+ * what the reader obtained from the metadata file:
+ * --Cases (A), (B), (C), (D), (E)
+ * NOTE: Changes for page buffering/cache are not in place yet.
+ * Index entries are constructed at the front end by the
+ * writer and verified at the back end by the reader.
+ *
+ * Return: 0 if test is sucessful
+ * 1 if test fails
+ *
+ * Programmer: Vailin Choi; October 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static unsigned
+test_reader_md_concur(void)
+{
+ unsigned i = 0; /* Local index variables */
+ uint8_t *buf = NULL; /* Data page from the page buffer */
+ hid_t dcpl = -1; /* Dataset creation property list */
+ hid_t sid = -1; /* Dataspace ID */
+ hid_t did = -1; /* Dataset ID */
+ int *rwbuf = NULL; /* Data buffer for writing */
+ H5O_info_t oinfo; /* Object metadata information */
+ char dname[100]; /* Name of dataset */
+ hsize_t dims[2] = {50, 20}; /* Dataset dimension sizes */
+ hsize_t max_dims[2] = /* Dataset maximum dimension sizes */
+ {H5S_UNLIMITED, H5S_UNLIMITED};
+ hsize_t chunk_dims[2] = {2, 5}; /* Dataset chunked dimension sizes */
+ unsigned num_entries = 0 ; /* Number of entries in the index */
+ H5FD_vfd_swmr_idx_entry_t *index = NULL; /* Pointer to the index entries */
+
+ hid_t fcpl = -1; /* File creation property list */
+ hid_t fid_writer = -1; /* File ID for writer */
+ hid_t fapl_writer = -1; /* File access property list for writer */
+ H5F_vfd_swmr_config_t *config_writer = NULL; /* VFD SWMR Configuration for writer */
+ pid_t tmppid; /* Child process ID returned by waitpid */
+ pid_t childpid = 0; /* Child process ID */
+ int child_status; /* Status passed to waitpid */
+ int child_wait_option=0; /* Options passed to waitpid */
+ int child_exit_val; /* Exit status of the child */
+
+ int parent_pfd[2]; /* Pipe for parent process as writer */
+ int child_pfd[2]; /* Pipe for child process as reader */
+ int notify = 0; /* Notification between parent and child */
+ H5F_t *file_writer; /* File pointer for writer */
+
+ TESTING("Verify the metadata file for VFD SWMR reader");
+
+ /* Allocate memory for the configuration structure */
+ if((config_writer = HDmalloc(sizeof(*config_writer))) == NULL)
+ FAIL_STACK_ERROR;
+
+ /* Set up the VFD SWMR configuration + page buffering */
+ fapl_writer = init_vfd_swmr_config_fapl(config_writer, 1, 3, TRUE, 256, MD_FILENAME, FS_PAGE_SIZE);
+ if(fapl_writer == H5I_INVALID_HID)
+ FAIL_STACK_ERROR;
+
+ /* Create a copy of the file creation property list */
+ if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set file space strategy */
+ if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, FALSE, 1) < 0)
+ FAIL_STACK_ERROR;
+
+ if(H5Pset_file_space_page_size(fcpl, FS_PAGE_SIZE) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Create an HDF5 file with VFD SWMR configured */
+ if((fid_writer = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, fapl_writer)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Close the file */
+ if(H5Fclose(fid_writer) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Create 2 pipes */
+ if(HDpipe(parent_pfd) < 0)
+ FAIL_STACK_ERROR
+
+ if(HDpipe(child_pfd) < 0)
+ FAIL_STACK_ERROR
+
+ /* Fork child process */
+ if((childpid = HDfork()) < 0)
+ FAIL_STACK_ERROR
+
+ /*
+ * Child process as reader
+ */
+ if(childpid == 0) {
+ int child_notify = 0; /* Notification between child and parent */
+ hid_t fid_reader = -1; /* File ID for reader */
+ hid_t fapl_reader = -1; /* File access property list for reader */
+ H5F_t *file_reader; /* File pointer for reader */
+ H5F_vfd_swmr_config_t *config_reader = NULL; /* VFD SWMR configuration for reader */
+ unsigned child_num_entries = 0; /* Number of entries passed to reader */
+ H5FD_vfd_swmr_idx_entry_t *child_index = NULL; /* Index passed to reader */
+
+ /* Close unused write end for writer pipe */
+ if(HDclose(parent_pfd[1]) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /* Close unused read end for reader pipe */
+ if(HDclose(child_pfd[0]) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /*
+ * Case A: reader
+ * --verify an empty index
+ */
+
+ /* Wait for notification 1 from parent to start verification */
+ while(child_notify != 1) {
+ if(HDread(parent_pfd[0], &child_notify, sizeof(int)) < 0)
+ HDexit(EXIT_FAILURE);
+ }
+
+ /* Allocate memory for the configuration structure */
+ if((config_reader = HDmalloc(sizeof(*config_reader))) == NULL)
+ HDexit(EXIT_FAILURE);
+
+ /* Set up the VFD SWMR configuration as reader + page buffering */
+ fapl_reader = init_vfd_swmr_config_fapl(config_reader, 1, 3, FALSE, 256, MD_FILENAME, FS_PAGE_SIZE);
+ if(fapl_reader == H5I_INVALID_HID)
+ HDexit(EXIT_FAILURE);
+
+ /* Open the test file as reader */
+ if((fid_reader = H5Fopen(FILENAME, H5F_ACC_RDONLY, fapl_reader)) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /* Get file pointer */
+ file_reader = H5VL_object(fid_reader);
+
+ /* Read and verify header and an empty index in the metadata file */
+ if(H5FD__vfd_swmr_reader_md_test(file_reader->shared->lf, 0, NULL) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /* Send notification 2 to parent that the verification is complete */
+ child_notify = 2;
+ if(HDwrite(child_pfd[1], &child_notify, sizeof(int)) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /*
+ * Case B: reader
+ * --verify index as sent from writer
+ */
+
+ /* Wait for notification 3 from parent to start verification */
+ while(child_notify != 3) {
+ if(HDread(parent_pfd[0], &child_notify, sizeof(int)) < 0)
+ HDexit(EXIT_FAILURE);
+ }
+
+ /* Read num_entries from writer pipe */
+ if(HDread(parent_pfd[0], &child_num_entries, sizeof(int)) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /* Free previous index */
+ if(child_index)
+ HDfree(child_index);
+
+ if(child_num_entries) {
+
+ /* Allocate memory for num_entries index */
+ if((child_index = HDcalloc(child_num_entries,
+ sizeof(*child_index))) == NULL)
+ HDexit(EXIT_FAILURE);
+
+ /* Read index from writer pipe */
+ if(HDread(parent_pfd[0], child_index,
+ child_num_entries * sizeof(*child_index)) < 0)
+ HDexit(EXIT_FAILURE);
+ }
+
+ /* Read and verify the expected header and index info in the
+ * metadata file
+ */
+ if(H5FD__vfd_swmr_reader_md_test(file_reader->shared->lf,
+ child_num_entries, child_index) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /* Send notification 4 to parent that the verification is complete */
+ child_notify = 4;
+ if(HDwrite(child_pfd[1], &child_notify, sizeof(int)) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /*
+ * Case C: reader
+ * --verify index as sent from writer
+ */
+
+ /* Wait for notification 5 from parent to start verification */
+ while(child_notify != 5) {
+ if(HDread(parent_pfd[0], &child_notify, sizeof(int)) < 0)
+ HDexit(EXIT_FAILURE);
+ }
+
+ /* Read num_entries from writer pipe */
+ if(HDread(parent_pfd[0], &child_num_entries, sizeof(int)) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /* Free previous index */
+ if(child_index)
+ HDfree(child_index);
+
+ if(child_num_entries) {
+ /* Allocate memory for num_entries index */
+ if((child_index = (H5FD_vfd_swmr_idx_entry_t *)
+ HDcalloc(child_num_entries,
+ sizeof(H5FD_vfd_swmr_idx_entry_t))) == NULL)
+ HDexit(EXIT_FAILURE);
+
+ /* Read index from writer pipe */
+ if(HDread(parent_pfd[0], child_index,
+ child_num_entries * sizeof(H5FD_vfd_swmr_idx_entry_t)) < 0)
+ HDexit(EXIT_FAILURE);
+ }
+
+ /* Read and verify the expected header and index info in the
+ * metadata file
+ */
+ if(H5FD__vfd_swmr_reader_md_test(file_reader->shared->lf,
+ child_num_entries, child_index) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /* Send notification 6 to parent that the verification is complete */
+ child_notify = 6;
+ if(HDwrite(child_pfd[1], &child_notify, sizeof(int)) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /*
+ * Case D: reader
+ * --verify index as sent from writer
+ */
+
+ /* Wait for notification 7 from parent to start verification */
+ while(child_notify != 7) {
+
+ if(HDread(parent_pfd[0], &child_notify, sizeof(int)) < 0)
+
+ HDexit(EXIT_FAILURE);
+ }
+
+ /* Read num_entries from writer pipe */
+ if(HDread(parent_pfd[0], &child_num_entries, sizeof(int)) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /* Free previous index */
+ if(child_index)
+ HDfree(child_index);
+
+ if(child_num_entries) {
+ /* Allocate memory for num_entries index */
+ if((child_index = (H5FD_vfd_swmr_idx_entry_t *)
+ HDcalloc(child_num_entries,
+ sizeof(H5FD_vfd_swmr_idx_entry_t))) == NULL)
+ HDexit(EXIT_FAILURE);
+
+ /* Read index from writer pipe */
+ if(HDread(parent_pfd[0], child_index,
+ child_num_entries * sizeof(H5FD_vfd_swmr_idx_entry_t)) < 0)
+ HDexit(EXIT_FAILURE);
+ }
+
+ /* Read and verify the expected header and index info in the
+ * metadata file
+ */
+ if(H5FD__vfd_swmr_reader_md_test(file_reader->shared->lf,
+ child_num_entries, child_index) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /* Send notification 8 to parent that the verification is complete */
+ child_notify = 8;
+ if(HDwrite(child_pfd[1], &child_notify, sizeof(int)) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /*
+ * Case E: reader
+ * --verify an empty index
+ */
+
+ /* Wait for notification 9 from parent to start verification */
+ while(child_notify != 9) {
+ if(HDread(parent_pfd[0], &child_notify, sizeof(int)) < 0)
+ HDexit(EXIT_FAILURE);
+ }
+
+ /* Read and verify header and an empty index in the metadata file */
+ if(H5FD__vfd_swmr_reader_md_test(file_reader->shared->lf, 0, NULL) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /* Free resources */
+ if(child_index)
+ HDfree(child_index);
+ if(config_reader)
+ HDfree(config_reader);
+
+ /* Closing */
+ if(H5Fclose(fid_reader) < 0)
+ HDexit(EXIT_FAILURE);
+ if(H5Pclose(fapl_reader) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /* Close the pipes */
+ if(HDclose(parent_pfd[0]) < 0)
+ HDexit(EXIT_FAILURE);
+ if(HDclose(child_pfd[1]) < 0)
+ HDexit(EXIT_FAILURE);
+
+ HDexit(EXIT_SUCCESS);
+ } /* end child process */
+
+ /*
+ * Parent process as writer
+ */
+
+ /* Close unused read end for writer pipe */
+ if(HDclose(parent_pfd[0]) < 0)
+ FAIL_STACK_ERROR
+
+ /* Close unused write end for reader pipe */
+ if(HDclose(child_pfd[1]) < 0)
+ FAIL_STACK_ERROR
+
+ /*
+ * Case A: writer
+ * --open the file as VFD SWMR writer
+ */
+
+ /* Open as VFD SWMR writer */
+ if((fid_writer = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl_writer)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Send notification 1 to reader to start verfication */
+ notify = 1;
+ if(HDwrite(parent_pfd[1], &notify, sizeof(int)) < 0)
+ FAIL_STACK_ERROR;
+
+ /*
+ * Case B: writer
+ * --create datasets to ensure ticks elapse
+ * --construct 12 entries in the index
+ * --update the metadata file with the index
+ */
+
+ /* Wait for notification 2 from reader that the verifcation is complete */
+ while(notify != 2) {
+ if(HDread(child_pfd[0], &notify, sizeof(int)) < 0)
+ FAIL_STACK_ERROR;
+ }
+
+ /* Create dataset creation property list */
+ if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set to use chunked dataset */
+ if(H5Pset_chunk(dcpl, 2, chunk_dims) < 0)
+ FAIL_STACK_ERROR
+
+ /* Create dataspace */
+ if((sid = H5Screate_simple(2, dims, max_dims)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Perform activities to ensure that ticks elapse */
+ for(i = 0; i < config_writer->max_lag + 1; i++) {
+ decisleep(config_writer->tick_len);
+
+ /* Create a chunked dataset */
+ sprintf(dname, "dset %d", i);
+ if((did = H5Dcreate2(fid_writer, dname, H5T_NATIVE_INT, sid,
+ H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Get dataset object header address */
+ if(H5Oget_info(did, &oinfo, H5O_INFO_BASIC) < 0)
+ FAIL_STACK_ERROR
+
+ /* Close the dataset */
+ if(H5Dclose(did) < 0)
+ FAIL_STACK_ERROR
+ }
+
+ num_entries = 12;
+
+ /* Allocate num_entries for the data buffer */
+ if((buf = HDcalloc(num_entries, FS_PAGE_SIZE)) == NULL)
+ FAIL_STACK_ERROR;
+
+ /* Allocate memory for num_entries index */
+ index = HDcalloc(num_entries, sizeof(H5FD_vfd_swmr_idx_entry_t));
+ if(NULL == index)
+ FAIL_STACK_ERROR;
+
+ /* Construct index for updating the metadata file */
+ for(i = 0; i < num_entries; i++) {
+ index[i].hdf5_page_offset = 3 + 7 * i;
+ index[i].md_file_page_offset = 1 + (num_entries - i) * 5;
+ index[i].length = (uint32_t)FS_PAGE_SIZE;
+ index[i].entry_ptr = &buf[i * FS_PAGE_SIZE];
+ }
+
+ /* Get the file pointer */
+ file_writer = H5VL_object(fid_writer);
+
+ /* Update the metadata file with the index */
+ if(H5F_update_vfd_swmr_metadata_file(file_writer, num_entries, index) < 0)
+ TEST_ERROR;
+
+ /* Send notification 3 to child to start verification */
+ notify = 3;
+ if(HDwrite(parent_pfd[1], &notify, sizeof(int)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Send num_entries to the reader */
+ if(HDwrite(parent_pfd[1], &num_entries, sizeof(int)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Send index to the reader */
+ if(HDwrite(parent_pfd[1], index,
+ num_entries * sizeof(H5FD_vfd_swmr_idx_entry_t)) < 0)
+ FAIL_STACK_ERROR;
+
+ /*
+ * Case C: writer
+ * --write to the datasets to ensure ticks elapse
+ * --update 3 entries in the index
+ * --update the metadata file with the index
+ */
+
+ /* Wait for notification 4 from reader that the verifcation is complete */
+ while(notify != 4) {
+ if(HDread(child_pfd[0], &notify, sizeof(int)) < 0)
+ FAIL_STACK_ERROR;
+ }
+
+ /* Allocate memory for the read/write buffer */
+ if((rwbuf = HDmalloc(sizeof(*rwbuf) * (50 * 20))) == NULL)
+ FAIL_STACK_ERROR;
+ for(i = 0; i < (50 * 20); i++)
+ rwbuf[i] = (int)i;
+
+ /* Perform activities to ensure that max_lag ticks elapse */
+ for(i = 0; i < config_writer->max_lag + 1; i++) {
+ decisleep(config_writer->tick_len);
+
+ /* Open the dataset */
+ sprintf(dname, "dset %d", i);
+ if((did = H5Dopen2(fid_writer, dname, H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Write to the dataset */
+ if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
+ H5P_DEFAULT, rwbuf) < 0)
+ FAIL_STACK_ERROR
+
+ /* Close the dataset */
+ if(H5Dclose(did) < 0)
+ FAIL_STACK_ERROR
+ }
+
+ /* Update 3 entries in the index */
+ num_entries = 3;
+ for(i = 0; i < num_entries; i++)
+ index[i].entry_ptr = &buf[i * FS_PAGE_SIZE];
+
+ /* Update the metadata file with the index */
+ if(H5F_update_vfd_swmr_metadata_file(file_writer, num_entries, index) < 0)
+ TEST_ERROR;
+
+ /* Send notification 5 to reader to start verification */
+ notify = 5;
+ if(HDwrite(parent_pfd[1], &notify, sizeof(int)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Send num_entries to the reader */
+ if(HDwrite(parent_pfd[1], &num_entries, sizeof(int)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Send index to the reader */
+ if(HDwrite(parent_pfd[1], index,
+ num_entries * sizeof(H5FD_vfd_swmr_idx_entry_t)) < 0)
+ FAIL_STACK_ERROR;
+
+ /*
+ * Case D: writer
+ * --read from the datasets to ensure ticks elapse
+ * --update 5 entries in the index
+ * --update the metadata file with the index
+ */
+
+ /* Wait for notification 6 from reader that the verifcation is complete */
+ while(notify != 6) {
+ if(HDread(child_pfd[0], &notify, sizeof(int)) < 0)
+ FAIL_STACK_ERROR;
+ }
+
+ /* Perform activities to ensure that max_lag ticks elapse */
+ for(i = 0; i < config_writer->max_lag + 1; i++) {
+ decisleep(config_writer->tick_len);
+
+ /* Open the dataset */
+ sprintf(dname, "dset %d", i);
+ if((did = H5Dopen2(fid_writer, dname, H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Read from the dataset */
+ if(H5Dread(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
+ H5P_DEFAULT, rwbuf) < 0)
+ FAIL_STACK_ERROR
+
+ /* Close the dataset */
+ if(H5Dclose(did) < 0)
+ FAIL_STACK_ERROR
+ }
+
+ /* Update 5 entries in the index */
+ num_entries = 5;
+ for(i = 0; i < num_entries; i++)
+ index[i].entry_ptr = &buf[i * FS_PAGE_SIZE];
+
+ /* Update the metadata file with the index */
+ if(H5F_update_vfd_swmr_metadata_file(file_writer, num_entries, index) < 0)
+ TEST_ERROR;
+
+ /* Send notification 7 to reader to start verification */
+ notify = 7;
+ if(HDwrite(parent_pfd[1], &notify, sizeof(int)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Send num_entries to the reader */
+ if(HDwrite(parent_pfd[1], &num_entries, sizeof(int)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Send index to the reader */
+ if(HDwrite(parent_pfd[1], index,
+ num_entries * sizeof(H5FD_vfd_swmr_idx_entry_t)) < 0)
+ FAIL_STACK_ERROR;
+
+ /*
+ * Case E: writer
+ * --write to the datasets again to ensure ticks elapse
+ * --update the metadata file with an empty index
+ */
+
+ /* Wait for notification 8 from reader that the verifcation is complete */
+ while(notify != 8) {
+ if(HDread(child_pfd[0], &notify, sizeof(int)) < 0)
+ FAIL_STACK_ERROR;
+ }
+
+ /* Perform activities to ensure that ticks elapse */
+ for(i = 0; i < config_writer->max_lag + 1; i++) {
+ decisleep(config_writer->tick_len);
+
+ /* Open the dataset */
+ sprintf(dname, "dset %d", i);
+ if((did = H5Dopen2(fid_writer, dname, H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Write to the dataset */
+ if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
+ H5P_DEFAULT, rwbuf) < 0)
+ FAIL_STACK_ERROR
+
+ /* Close the dataset */
+ if(H5Dclose(did) < 0)
+ FAIL_STACK_ERROR
+ }
+
+ /* Update the metadata file with 0 entries and NULL index */
+ if(H5F_update_vfd_swmr_metadata_file(file_writer, 0, NULL) < 0)
+ TEST_ERROR;
+
+ /* Send notification 8 to reader to start verification */
+ notify = 9;
+ if(HDwrite(parent_pfd[1], &notify, sizeof(int)) < 0)
+ FAIL_STACK_ERROR;
+
+ /*
+ * Done
+ */
+
+ /* Close the pipes */
+ if(HDclose(parent_pfd[1]) < 0)
+ FAIL_STACK_ERROR;
+ if(HDclose(child_pfd[0]) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Wait for child process to complete */
+ if((tmppid = HDwaitpid(childpid, &child_status, child_wait_option)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Check exit status of child process */
+ if(WIFEXITED(child_status)) {
+ if((child_exit_val = WEXITSTATUS(child_status)) != 0)
+ TEST_ERROR
+ } else { /* child process terminated abnormally */
+ TEST_ERROR
+ }
+
+ /* Closing */
+ if(H5Fclose(fid_writer) < 0)
+ FAIL_STACK_ERROR
+ if(H5Pclose(fapl_writer) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(fcpl) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Free resources */
+ if(config_writer)
+ HDfree(config_writer);
+ if(buf)
+ HDfree(buf);
+ if(rwbuf)
+ HDfree(rwbuf);
+ if(index)
+ HDfree(index);
+
+ PASSED();
+ return 0;
+
+error:
+ if(config_writer)
+ HDfree(config_writer);
+ if(buf)
+ HDfree(buf);
+ if(rwbuf)
+ HDfree(rwbuf);
+ if(index)
+ HDfree(index);
+
+ H5E_BEGIN_TRY {
+ H5Pclose(fapl_writer);
+ H5Fclose(fid_writer);
+ H5Pclose(fcpl);
+ } H5E_END_TRY;
+
+ return 1;
+} /* test_reader_md_concur() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_multiple_file_opens_concur()
+ *
+ * Purpose: Verify the entries on the EOT queue when opening files
+ * with and without VFD SWMR configured.
+ *
+ * Return: 0 if test is sucessful
+ * 1 if test fails
+ *
+ * Programmer: Vailin Choi; 11/18/2019
+ *
+ *-------------------------------------------------------------------------
+ */
+static unsigned
+test_multiple_file_opens_concur(void)
+{
+ hid_t fcpl = H5I_INVALID_HID;
+ pid_t tmppid; /* Child process ID returned by waitpid */
+ pid_t childpid = 0; /* Child process ID */
+ int child_status; /* Status passed to waitpid */
+ int child_wait_option=0; /* Options passed to waitpid */
+ int child_exit_val; /* Exit status of the child */
+ int parent_pfd[2]; /* Pipe for parent process as writer */
+ int child_pfd[2]; /* Pipe for child process as reader */
+ int notify = 0; /* Notification between parent and child */
+ hid_t fid1 = H5I_INVALID_HID, fid2 = H5I_INVALID_HID;
+ hid_t fapl1 = H5I_INVALID_HID, fapl2 = H5I_INVALID_HID;
+ H5F_vfd_swmr_config_t *config1 = NULL; /* VFD SWMR configuration */
+ H5F_vfd_swmr_config_t *config2 = NULL; /* VFD SWMR configuration */
+ H5F_t *f1, *f2; /* File pointer */
+ eot_queue_entry_t *curr;
+
+ TESTING("EOT queue entries when opening files concurrently with VFD SWMR");
+
+ /* Create a copy of the file creation property list */
+ if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set file space strategy */
+ if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, FALSE, 1) < 0)
+ FAIL_STACK_ERROR;
+
+ if(H5Pset_file_space_page_size(fcpl, FS_PAGE_SIZE) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Create file A */
+ if((fid1 = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Close the file */
+ if(H5Fclose(fid1) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Create file B */
+ if((fid2 = H5Fcreate(FILENAME2, H5F_ACC_TRUNC, fcpl, H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Close the file */
+ if(H5Fclose(fid2) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Create 2 pipes */
+ if(HDpipe(parent_pfd) < 0)
+ FAIL_STACK_ERROR
+
+ if(HDpipe(child_pfd) < 0)
+ FAIL_STACK_ERROR
+
+ /* Fork child process */
+ if((childpid = HDfork()) < 0)
+ FAIL_STACK_ERROR
+
+ /*
+ * Child process
+ */
+ if(childpid == 0) {
+ int child_notify = 0; /* Notification between child and parent */
+ hid_t fid_writer = -1; /* File ID for writer */
+ hid_t fapl_writer = -1; /* File access property list for writer */
+ H5F_vfd_swmr_config_t *config_writer = NULL; /* VFD SWMR configuration for reader */
+
+ /* Close unused write end for writer pipe */
+ if(HDclose(parent_pfd[1]) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /* Close unused read end for reader pipe */
+ if(HDclose(child_pfd[0]) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /*
+ * Set up and open file B as VFD SWMR writer
+ */
+
+ /* Wait for notification 1 from parent before opening file B */
+ while(child_notify != 1) {
+ if(HDread(parent_pfd[0], &child_notify, sizeof(int)) < 0)
+ HDexit(EXIT_FAILURE);
+ }
+
+ /* Allocate memory for VFD SMWR configuration */
+ if((config_writer = HDmalloc(sizeof(*config_writer))) == NULL)
+ HDexit(EXIT_FAILURE);
+
+
+ /* Set the VFD SWMR configuration in fapl_writer + page buffering */
+ fapl_writer = init_vfd_swmr_config_fapl(config_writer, 1, 3, TRUE, 256, MD_FILENAME2, FS_PAGE_SIZE);
+ if(fapl_writer == H5I_INVALID_HID)
+ HDexit(EXIT_FAILURE);
+
+ /* Open file B as VFD SWMR writer */
+ if((fid_writer = H5Fopen(FILENAME2, H5F_ACC_RDWR, fapl_writer)) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /* Send notification 2 to parent that file B is open */
+ child_notify = 2;
+ if(HDwrite(child_pfd[1], &child_notify, sizeof(int)) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /* Wait for notification 3 from parent before closing file B */
+ while(child_notify != 3) {
+ if(HDread(parent_pfd[0], &child_notify, sizeof(int)) < 0)
+ HDexit(EXIT_FAILURE);
+ }
+
+ if(config_writer )
+ HDfree(config_writer);
+
+ /* Close the file */
+ if(H5Fclose(fid_writer) < 0)
+ HDexit(EXIT_FAILURE);
+ if(H5Pclose(fapl_writer) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /* Send notification 4 to parent that file B is closed */
+ child_notify = 4;
+ if(HDwrite(child_pfd[1], &child_notify, sizeof(int)) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /* Close the pipes */
+ if(HDclose(parent_pfd[0]) < 0)
+ HDexit(EXIT_FAILURE);
+ if(HDclose(child_pfd[1]) < 0)
+ HDexit(EXIT_FAILURE);
+
+ HDexit(EXIT_SUCCESS);
+ } /* end child process */
+
+ /*
+ * Parent process
+ */
+
+ /* Close unused read end for writer pipe */
+ if(HDclose(parent_pfd[0]) < 0)
+ FAIL_STACK_ERROR
+
+ /* Close unused write end for reader pipe */
+ if(HDclose(child_pfd[1]) < 0)
+ FAIL_STACK_ERROR
+
+ /*
+ * Set up and open file A as VFD SWMR writer
+ */
+
+ /* Allocate memory for VFD SWMR configuration */
+ if((config1 = HDmalloc(sizeof(*config1))) == NULL)
+ FAIL_STACK_ERROR
+
+ /* Set the VFD SWMR configuration in fapl1 + page buffering */
+ fapl1 = init_vfd_swmr_config_fapl(config1, 7, 10, TRUE, 256, MD_FILENAME, FS_PAGE_SIZE);
+ if(fapl1 == H5I_INVALID_HID)
+ FAIL_STACK_ERROR
+
+ /* Open file A as VFD SWMR writer */
+ if((fid1 = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl1)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Get a pointer to the internal file object */
+ if(NULL == (f1 = H5VL_object(fid1)))
+ FAIL_STACK_ERROR
+
+ /* Head of EOT queue should be a writer */
+ if((curr = TAILQ_FIRST(&eot_queue_g)) == NULL || !curr->vfd_swmr_writer)
+ TEST_ERROR;
+
+ /* The EOT queue's first entry should be f1 */
+ if((curr = TAILQ_FIRST(&eot_queue_g)) == NULL || curr->vfd_swmr_file != f1)
+ TEST_ERROR;
+
+
+ /* Send notification 1 to child to open file B */
+ notify = 1;
+ if(HDwrite(parent_pfd[1], &notify, sizeof(int)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Wait for notification 2 from child that file B is open */
+ while(notify != 2) {
+ if(HDread(child_pfd[0], &notify, sizeof(int)) < 0)
+ FAIL_STACK_ERROR;
+ }
+
+ /* Open file B as VFD SWMR reader */
+
+ /* Allocate memory for VFD SWMR configuration */
+ if((config2 = HDmalloc(sizeof(*config2))) == NULL)
+ FAIL_STACK_ERROR
+
+ /* Set the VFD SWMR configuration in fapl2 + page buffering */
+ fapl2 = init_vfd_swmr_config_fapl(config2, 1, 3, FALSE, 256, MD_FILENAME2, FS_PAGE_SIZE);
+ if(fapl2 == H5I_INVALID_HID)
+ FAIL_STACK_ERROR
+
+ /* Open file B as VFD SWMR reader */
+ if((fid2 = H5Fopen(FILENAME2, H5F_ACC_RDONLY, fapl2)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Get a pointer to the internal file object */
+ if(NULL == (f2 = H5VL_object(fid2)))
+ FAIL_STACK_ERROR
+
+ /* Head of EOT queue should NOT be a writer */
+ if((curr = TAILQ_FIRST(&eot_queue_g)) != NULL && curr->vfd_swmr_writer)
+ TEST_ERROR;
+
+ /* The EOT queue's first entry should be f2 */
+ if((curr = TAILQ_FIRST(&eot_queue_g)) == NULL || curr->vfd_swmr_file != f2)
+ TEST_ERROR;
+
+ /* Send notification 3 to child to close file B */
+ notify = 3;
+ if(HDwrite(parent_pfd[1], &notify, sizeof(int)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Wait for notification 4 from child that file B is closed */
+ while(notify != 4) {
+ if(HDread(child_pfd[0], &notify, sizeof(int)) < 0)
+ FAIL_STACK_ERROR;
+ }
+
+ /*
+ * Done
+ */
+
+ /* Close the pipes */
+ if(HDclose(parent_pfd[1]) < 0)
+ FAIL_STACK_ERROR;
+ if(HDclose(child_pfd[0]) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Wait for child process to complete */
+ if((tmppid = HDwaitpid(childpid, &child_status, child_wait_option)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Check exit status of child process */
+ if(WIFEXITED(child_status)) {
+ if((child_exit_val = WEXITSTATUS(child_status)) != 0)
+ TEST_ERROR
+ } else { /* child process terminated abnormally */
+ TEST_ERROR
+ }
+
+ /* Closing */
+ if(H5Fclose(fid1) < 0)
+ FAIL_STACK_ERROR
+ if(H5Fclose(fid2) < 0)
+ FAIL_STACK_ERROR
+ if(H5Pclose(fapl1) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(fapl2) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(fcpl) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Free resources */
+ if(config1)
+ HDfree(config1);
+ if(config2)
+ HDfree(config2);
+
+ PASSED();
+ return 0;
+
+error:
+ if(config1)
+ HDfree(config1);
+ if(config2)
+ HDfree(config2);
+
+ H5E_BEGIN_TRY {
+ H5Pclose(fapl1);
+ H5Pclose(fapl2);
+ H5Fclose(fid1);
+ H5Fclose(fid2);
+ H5Pclose(fcpl);
+ } H5E_END_TRY;
+
+ return 1;
+} /* test_multiple_file_opens_concur() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_enable_disable_eot_concur()
+ *
+ * Purpose: Verify the public routines:
+ * H5Fvfd_swmr_disable_end_of_tick()
+ * H5Fvfd_swmr_enable_end_of_tick()
+ * enables/disables EOT when the files are opened
+ * concurrently.
+ *
+ * Return: 0 if test is sucessful
+ * 1 if test fails
+ *
+ * Programmer: Vailin Choi; June 2020
+ *
+ *-------------------------------------------------------------------------
+ */
+static unsigned
+test_disable_enable_eot_concur(void)
+{
+ hid_t fcpl = -1; /* File creation property list */
+ hid_t fid_writer = -1; /* File ID for writer */
+ hid_t fapl_writer = -1; /* File access property list for writer */
+ H5F_vfd_swmr_config_t *config_writer = NULL; /* VFD SWMR Configuration for writer */
+ pid_t tmppid; /* Child process ID returned by waitpid */
+ pid_t childpid = 0; /* Child process ID */
+ int child_status; /* Status passed to waitpid */
+ int child_wait_option=0; /* Options passed to waitpid */
+ int child_exit_val; /* Exit status of the child */
+
+ int parent_pfd[2]; /* Pipe for parent process as writer */
+ int child_pfd[2]; /* Pipe for child process as reader */
+ int notify = 0; /* Notification between parent and child */
+
+ TESTING("Verify concurrent H5Fvfd_swmr_enable/disable_end_of_tick()");
+
+ /* Allocate memory for the configuration structure */
+ if((config_writer = HDmalloc(sizeof(*config_writer))) == NULL)
+ FAIL_STACK_ERROR;
+
+ /* Set up the VFD SWMR configuration + page buffering */
+ fapl_writer = init_vfd_swmr_config_fapl(config_writer, 1, 3, TRUE, 256, MD_FILENAME, FS_PAGE_SIZE);
+ if(fapl_writer == H5I_INVALID_HID)
+ FAIL_STACK_ERROR;
+
+ /* Create a copy of the file creation property list */
+ if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set file space strategy */
+ if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, FALSE, 1) < 0)
+ FAIL_STACK_ERROR;
+
+ if(H5Pset_file_space_page_size(fcpl, FS_PAGE_SIZE) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Create an HDF5 file with VFD SWMR configured */
+ if((fid_writer = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, fapl_writer)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Close the file */
+ if(H5Fclose(fid_writer) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Create 2 pipes */
+ if(HDpipe(parent_pfd) < 0)
+ FAIL_STACK_ERROR
+
+ if(HDpipe(child_pfd) < 0)
+ FAIL_STACK_ERROR
+
+ /* Fork child process */
+ if((childpid = HDfork()) < 0)
+ FAIL_STACK_ERROR
+
+ /*
+ * Child process as reader
+ */
+ if(childpid == 0) {
+ int child_notify = 0; /* Notification between child and parent */
+ hid_t fid_reader = H5I_INVALID_HID; /* File ID for reader */
+ hid_t fid_reader2 = H5I_INVALID_HID; /* File ID for reader */
+ hid_t fid_reader3 = H5I_INVALID_HID; /* File ID for reader */
+ hid_t fapl_reader = H5I_INVALID_HID; /* File access property list for reader */
+ H5F_vfd_swmr_config_t *config_reader = NULL; /* VFD SWMR configuration */
+ H5F_t *file_reader; /* File pointer */
+ eot_queue_entry_t *curr; /* Pointer to an entry on the EOT queue */
+ unsigned count = 0; /* Counter */
+
+ /* Close unused write end for writer pipe */
+ if(HDclose(parent_pfd[1]) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /* Close unused read end for reader pipe */
+ if(HDclose(child_pfd[0]) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /*
+ * Open the file 3 times as VFD SWMR reader
+ * Enable and disable EOT for a file
+ * Verify the state of the EOT queue
+ */
+
+ /* Wait for notification 1 from parent to start verification */
+ while(child_notify != 1) {
+ if(HDread(parent_pfd[0], &child_notify, sizeof(int)) < 0)
+ HDexit(EXIT_FAILURE);
+ }
+
+ /* Allocate memory for the configuration structure */
+ if((config_reader = HDmalloc(sizeof(*config_reader))) == NULL)
+ HDexit(EXIT_FAILURE);
+
+ /* Set up the VFD SWMR configuration as reader + page buffering */
+ fapl_reader = init_vfd_swmr_config_fapl(config_reader, 1, 3, FALSE, 256, MD_FILENAME, FS_PAGE_SIZE);
+ if(fapl_reader == H5I_INVALID_HID)
+ FAIL_STACK_ERROR;
+
+ /* Open the test file as reader */
+ if((fid_reader = H5Fopen(FILENAME, H5F_ACC_RDONLY, fapl_reader)) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /* Open the same test file as reader (a second time) */
+ if((fid_reader2 = H5Fopen(FILENAME, H5F_ACC_RDONLY, fapl_reader)) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /* Open the same test file as reader (a third time) */
+ if((fid_reader3 = H5Fopen(FILENAME, H5F_ACC_RDONLY, fapl_reader)) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /* Verify the # of files on the EOT queue is 3 */
+ count = 0;
+ TAILQ_FOREACH(curr, &eot_queue_g, link)
+ count++;
+ if(count != 3)
+ HDexit(EXIT_FAILURE);
+
+ /* Disable EOT for the second opened file */
+ if(H5Fvfd_swmr_disable_end_of_tick(fid_reader2) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /* Verify the # of files on the EOT queue is 2 */
+ count = 0;
+ TAILQ_FOREACH(curr, &eot_queue_g, link)
+ count++;
+ if(count != 2)
+ HDexit(EXIT_FAILURE);
+
+ /* Get file pointer */
+ file_reader = H5VL_object(fid_reader2);
+
+ /* Should not find the second opened file on the EOT queue */
+ TAILQ_FOREACH(curr, &eot_queue_g, link) {
+ if(curr->vfd_swmr_file == file_reader)
+ break;
+ }
+ if(curr != NULL && curr->vfd_swmr_file == file_reader)
+ HDexit(EXIT_FAILURE);
+
+ /* Enable EOT for the second opened file again */
+ if(H5Fvfd_swmr_enable_end_of_tick(fid_reader2) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /* Verify the # of files on the EOT queue is 3 */
+ count = 0;
+ TAILQ_FOREACH(curr, &eot_queue_g, link)
+ count++;
+ if(count != 3)
+ HDexit(EXIT_FAILURE);
+
+ /* Should find the second opened file on the EOT queue */
+ TAILQ_FOREACH(curr, &eot_queue_g, link) {
+ if(curr->vfd_swmr_file == file_reader)
+ break;
+ }
+ if(curr == NULL || curr->vfd_swmr_file != file_reader)
+ HDexit(EXIT_FAILURE);
+
+ /* Closing */
+ if(H5Fclose(fid_reader) < 0)
+ HDexit(EXIT_FAILURE);
+ if(H5Fclose(fid_reader2) < 0)
+ HDexit(EXIT_FAILURE);
+ if(H5Fclose(fid_reader3) < 0)
+ HDexit(EXIT_FAILURE);
+ if(H5Pclose(fapl_reader) < 0)
+ HDexit(EXIT_FAILURE);
+ if(config_reader)
+ HDfree(config_reader);
+
+ /* Close the pipes */
+ if(HDclose(parent_pfd[0]) < 0)
+ HDexit(EXIT_FAILURE);
+ if(HDclose(child_pfd[1]) < 0)
+ HDexit(EXIT_FAILURE);
+
+ HDexit(EXIT_SUCCESS);
+ } /* end child process */
+
+ /*
+ * Parent process as writer
+ */
+
+ /* Close unused read end for writer pipe */
+ if(HDclose(parent_pfd[0]) < 0)
+ FAIL_STACK_ERROR
+
+ /* Close unused write end for reader pipe */
+ if(HDclose(child_pfd[1]) < 0)
+ FAIL_STACK_ERROR
+
+ /*
+ * Open the file as VFD SWMR writer
+ */
+
+ /* Open as VFD SWMR writer */
+ if((fid_writer = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl_writer)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Send notification 1 to reader to start verfication */
+ notify = 1;
+ if(HDwrite(parent_pfd[1], &notify, sizeof(int)) < 0)
+ FAIL_STACK_ERROR;
+
+ /*
+ * Done
+ */
+
+ /* Close the pipes */
+ if(HDclose(parent_pfd[1]) < 0)
+ FAIL_STACK_ERROR;
+ if(HDclose(child_pfd[0]) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Wait for child process to complete */
+ if((tmppid = HDwaitpid(childpid, &child_status, child_wait_option)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Check exit status of child process */
+ if(WIFEXITED(child_status)) {
+ if((child_exit_val = WEXITSTATUS(child_status)) != 0)
+ TEST_ERROR
+ } else { /* child process terminated abnormally */
+ TEST_ERROR
+ }
+
+ /* Closing */
+ if(H5Fclose(fid_writer) < 0)
+ FAIL_STACK_ERROR
+ if(H5Pclose(fapl_writer) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(fcpl) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Free resources */
+ if(config_writer)
+ HDfree(config_writer);
+
+ PASSED();
+ return 0;
+
+error:
+ if(config_writer)
+ HDfree(config_writer);
+
+ H5E_BEGIN_TRY {
+ H5Pclose(fapl_writer);
+ H5Fclose(fid_writer);
+ H5Pclose(fcpl);
+ } H5E_END_TRY;
+
+ return 1;
+} /* test_disable_enable_eot_concur() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_file_end_tick_concur()
+ *
+ * Purpose: Verify the public routine H5Fvfd_swmr_end_tick()
+ * triggers end of tick processing when the files
+ * are opened concurrently.
+ *
+ * Return: 0 if test is sucessful
+ * 1 if test fails
+ *
+ * Programmer: Vailin Choi; June 2020
+ *
+ *-------------------------------------------------------------------------
+ */
+static unsigned
+test_file_end_tick_concur(void)
+{
+ hid_t fcpl = -1; /* File creation property list */
+ hid_t fid_writer = -1; /* File ID for writer */
+ hid_t fapl_writer = -1; /* File access property list for writer */
+ H5F_vfd_swmr_config_t *config_writer = NULL; /* VFD SWMR Configuration for writer */
+ pid_t tmppid; /* Child process ID returned by waitpid */
+ pid_t childpid = 0; /* Child process ID */
+ int child_status; /* Status passed to waitpid */
+ int child_wait_option=0; /* Options passed to waitpid */
+ int child_exit_val; /* Exit status of the child */
+
+ int parent_pfd[2]; /* Pipe for parent process as writer */
+ int child_pfd[2]; /* Pipe for child process as reader */
+ int notify = 0; /* Notification between parent and child */
+
+ TESTING("Verify concurrent H5Fvfd_swmr_end_tick()");
+
+ /* Allocate memory for the configuration structure */
+ if((config_writer = HDmalloc(sizeof(*config_writer))) == NULL)
+ FAIL_STACK_ERROR;
+
+ /* Set up the VFD SWMR configuration + page buffering */
+ fapl_writer = init_vfd_swmr_config_fapl(config_writer, 1, 3, TRUE, 256, MD_FILENAME, FS_PAGE_SIZE);
+ if(fapl_writer == H5I_INVALID_HID)
+ FAIL_STACK_ERROR;
+
+ /* Create a copy of the file creation property list */
+ if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set file space strategy */
+ if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, FALSE, 1) < 0)
+ FAIL_STACK_ERROR;
+
+ if(H5Pset_file_space_page_size(fcpl, FS_PAGE_SIZE) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Create an HDF5 file with VFD SWMR configured */
+ if((fid_writer = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, fapl_writer)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Close the file */
+ if(H5Fclose(fid_writer) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Create 2 pipes */
+ if(HDpipe(parent_pfd) < 0)
+ FAIL_STACK_ERROR
+
+ if(HDpipe(child_pfd) < 0)
+ FAIL_STACK_ERROR
+
+ /* Fork child process */
+ if((childpid = HDfork()) < 0)
+ FAIL_STACK_ERROR
+
+ /*
+ * Child process as reader
+ */
+ if(childpid == 0) {
+ int child_notify = 0; /* Notification between child and parent */
+ hid_t fid_reader1 = H5I_INVALID_HID; /* File ID for reader */
+ hid_t fid_reader2 = H5I_INVALID_HID; /* File ID for reader */
+ hid_t fid_reader3 = H5I_INVALID_HID; /* File ID for reader */
+ hid_t fapl_reader = H5I_INVALID_HID; /* File access property list for reader */
+ H5F_vfd_swmr_config_t *config_reader = NULL; /* VFD SWMR configuration */
+ H5F_t *f1, *f2, *f3; /* File pointer */
+ uint64_t s1 = 0; /* Saved tick_num */
+ uint64_t s2 = 0; /* Saved tick_num */
+ uint64_t s3 = 0; /* Saved tick_num */
+
+ /* Close unused write end for writer pipe */
+ if(HDclose(parent_pfd[1]) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /* Close unused read end for reader pipe */
+ if(HDclose(child_pfd[0]) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /*
+ * Open the file 3 times as VFD SWMR reader
+ * Trigger EOT for the files
+ */
+
+ /* Wait for notification 1 from parent to start verification */
+ while(child_notify != 1) {
+ if(HDread(parent_pfd[0], &child_notify, sizeof(int)) < 0)
+ HDexit(EXIT_FAILURE);
+ }
+
+ /* Allocate memory for the configuration structure */
+ if((config_reader = HDmalloc(sizeof(*config_reader))) == NULL)
+ HDexit(EXIT_FAILURE);
+
+ /* Set up the VFD SWMR configuration as reader + page buffering */
+ fapl_reader = init_vfd_swmr_config_fapl(config_reader, 1, 3, FALSE, 256, MD_FILENAME, FS_PAGE_SIZE);
+ if(fapl_reader == H5I_INVALID_HID)
+ FAIL_STACK_ERROR;
+
+ /* Open the test file as reader */
+ if((fid_reader1 = H5Fopen(FILENAME, H5F_ACC_RDONLY, fapl_reader)) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /* Open the same test file as reader (a second time) */
+ if((fid_reader2 = H5Fopen(FILENAME, H5F_ACC_RDONLY, fapl_reader)) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /* Open the same test file as reader (a third time) */
+ if((fid_reader3 = H5Fopen(FILENAME, H5F_ACC_RDONLY, fapl_reader)) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /* Get file pointer */
+ f1 = H5VL_object(fid_reader1);
+ f2 = H5VL_object(fid_reader2);
+ f3 = H5VL_object(fid_reader3);
+
+ /* Saved tick_num for the 3 files */
+ s1 = f1->shared->tick_num;
+ s2 = f2->shared->tick_num;
+ s3 = f3->shared->tick_num;
+
+ /* Trigger EOT for the second opened file */
+ if(H5Fvfd_swmr_end_tick(fid_reader2) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /* Verify tick_num should not be less than the previous tick_num */
+ if(f2->shared->tick_num < s2)
+ HDexit(EXIT_FAILURE);
+
+ if(H5Fclose(fid_reader2) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /* Trigger EOT for the first opened file */
+ if(H5Fvfd_swmr_end_tick(fid_reader1) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /* Verify tick_num should not be less than the previous tick_num */
+ if(f1->shared->tick_num < s1)
+ HDexit(EXIT_FAILURE);
+
+ if(H5Fclose(fid_reader1) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /* Trigger end tick processing for the third opened file */
+ if(H5Fvfd_swmr_end_tick(fid_reader3) < 0)
+ HDexit(EXIT_FAILURE);
+
+ /* Verify tick_num should not be less than the previous tick_num */
+ if(f3->shared->tick_num < s3)
+ HDexit(EXIT_FAILURE);
+
+ if(H5Fclose(fid_reader3) < 0)
+ HDexit(EXIT_FAILURE);
+
+ if(H5Pclose(fapl_reader) < 0)
+ HDexit(EXIT_FAILURE);
+ if(config_reader)
+ HDfree(config_reader);
+
+ /* Close the pipes */
+ if(HDclose(parent_pfd[0]) < 0)
+ HDexit(EXIT_FAILURE);
+ if(HDclose(child_pfd[1]) < 0)
+ HDexit(EXIT_FAILURE);
+
+ HDexit(EXIT_SUCCESS);
+ } /* end child process */
+
+ /*
+ * Parent process as writer
+ */
+
+ /* Close unused read end for writer pipe */
+ if(HDclose(parent_pfd[0]) < 0)
+ FAIL_STACK_ERROR
+
+ /* Close unused write end for reader pipe */
+ if(HDclose(child_pfd[1]) < 0)
+ FAIL_STACK_ERROR
+
+ /*
+ * Open the file as VFD SWMR writer
+ */
+
+ /* Open as VFD SWMR writer */
+ if((fid_writer = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl_writer)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Send notification 1 to reader to start verfication */
+ notify = 1;
+ if(HDwrite(parent_pfd[1], &notify, sizeof(int)) < 0)
+ FAIL_STACK_ERROR;
+
+ /*
+ * Done
+ */
+
+ /* Close the pipes */
+ if(HDclose(parent_pfd[1]) < 0)
+ FAIL_STACK_ERROR;
+ if(HDclose(child_pfd[0]) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Wait for child process to complete */
+ if((tmppid = HDwaitpid(childpid, &child_status, child_wait_option)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Check exit status of child process */
+ if(WIFEXITED(child_status)) {
+ if((child_exit_val = WEXITSTATUS(child_status)) != 0)
+ TEST_ERROR
+ } else { /* child process terminated abnormally */
+ TEST_ERROR
+ }
+
+ /* Closing */
+ if(H5Fclose(fid_writer) < 0)
+ FAIL_STACK_ERROR
+ if(H5Pclose(fapl_writer) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(fcpl) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Free resources */
+ if(config_writer)
+ HDfree(config_writer);
+
+ PASSED();
+ return 0;
+
+error:
+ if(config_writer)
+ HDfree(config_writer);
+
+ H5E_BEGIN_TRY {
+ H5Pclose(fapl_writer);
+ H5Fclose(fid_writer);
+ H5Pclose(fcpl);
+ } H5E_END_TRY;
+
+ return 1;
+} /* test_file_end_tick_concur() */
+
+#endif /* !(defined(H5_HAVE_FORK) && defined(H5_HAVE_WAITPID) && defined(H5_HAVE_FLOCK)) */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_multiple_file_opens()
+ *
+ * Purpose: Verify the entries on the EOT queue when opening files
+ * with and without VFD SWMR configured.
+ *
+ * Return: 0 if test is sucessful
+ * 1 if test fails
+ *
+ * Programmer: Vailin Choi; 11/18/2019
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static unsigned
+test_multiple_file_opens(void)
+{
+ hid_t fid1 = -1; /* File ID */
+ hid_t fid2 = -1; /* File ID */
+ hid_t fid = -1; /* File ID */
+ hid_t fcpl = -1; /* File creation property list ID */
+ hid_t fapl1 = -1; /* File access property list ID */
+ hid_t fapl2 = -1; /* File access property list ID */
+ H5F_t *f1, *f2, *f; /* File pointer */
+ H5F_vfd_swmr_config_t *config1 = NULL; /* Configuration for VFD SWMR */
+ H5F_vfd_swmr_config_t *config2 = NULL; /* Configuration for VFD SWMR */
+ eot_queue_entry_t *curr;
+
+ TESTING("EOT queue entries when opening files with/without VFD SWMR");
+
+ /* Allocate memory for the configuration structure */
+ if((config1 = HDmalloc(sizeof(*config1))) == NULL)
+ FAIL_STACK_ERROR;
+ if((config2 = HDmalloc(sizeof(*config2))) == NULL)
+ FAIL_STACK_ERROR;
+
+ /* Configured as VFD SWMR writer + page buffering */
+ fapl1 = init_vfd_swmr_config_fapl(config1, 4, 6, TRUE, 2, MD_FILENAME, 4096);
+ if(fapl1 == H5I_INVALID_HID)
+ FAIL_STACK_ERROR;
+
+ /* Configured as VFD SWMR writer + page buffering */
+ fapl2 = init_vfd_swmr_config_fapl(config2, 4, 6, TRUE, 2, MD_FILENAME2, 4096);
+ if(fapl2 == H5I_INVALID_HID)
+ FAIL_STACK_ERROR;
+
+ /* Create a copy of the file creation property list */
+ if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set file space strategy */
+ if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, FALSE, 1) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Create a file without VFD SWMR */
+ if((fid = H5Fcreate(FNAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR;
+
+ /* Get a pointer to the internal file object */
+ if(NULL == (f = H5VL_object(fid)))
+ FAIL_STACK_ERROR
+
+ /* Verify the global vfd_swmr_writer_g is not set */
+ if((curr = TAILQ_FIRST(&eot_queue_g)) != NULL && curr->vfd_swmr_writer)
+ TEST_ERROR;
+ /* The EOT queue should be empty */
+ if(!TAILQ_EMPTY(&eot_queue_g))
+ TEST_ERROR;
+
+ /* Create a file with VFD SWMR writer */
+ if((fid1 = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, fapl1)) < 0)
+ TEST_ERROR;
+
+ /* Get a pointer to the internal file object */
+ if(NULL == (f1 = H5VL_object(fid1)))
+ FAIL_STACK_ERROR
+
+ /* Head of EOT queue should be a writer */
+ if((curr = TAILQ_FIRST(&eot_queue_g)) == NULL || !curr->vfd_swmr_writer)
+ TEST_ERROR;
+ /* The EOT queue should be initialized with the first entry equals to f1 */
+ if((curr = TAILQ_FIRST(&eot_queue_g)) == NULL || curr->vfd_swmr_file != f1)
+ TEST_ERROR;
+
+ /* Create another file with VFD SWMR writer */
+ if((fid2 = H5Fcreate(FILENAME2, H5F_ACC_TRUNC, fcpl, fapl2)) < 0)
+ TEST_ERROR;
+
+ /* Get a pointer to the internal file object */
+ if(NULL == (f2 = H5VL_object(fid2)))
+ FAIL_STACK_ERROR
+
+ /* Head of EOT queue should be a writer */
+ if((curr = TAILQ_FIRST(&eot_queue_g)) == NULL || !curr->vfd_swmr_writer)
+ TEST_ERROR;
+ /* The EOT queue's first entry should be f1 */
+ if((curr = TAILQ_FIRST(&eot_queue_g)) == NULL || curr->vfd_swmr_file != f1)
+ TEST_ERROR;
+
+ /* The file without VFD SWMR should not exist on the EOT queue */
+ TAILQ_FOREACH(curr, &eot_queue_g, link) {
+ if(curr->vfd_swmr_file == f)
+ TEST_ERROR
+ }
+
+ /* Close the first file with VFD SWMR */
+ if(H5Fclose(fid1) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Head of EOT queue should be a writer */
+ if((curr = TAILQ_FIRST(&eot_queue_g)) == NULL || !curr->vfd_swmr_writer)
+ TEST_ERROR;
+ /* The EOT queue's first entry should be f2 */
+ if((curr = TAILQ_FIRST(&eot_queue_g)) == NULL || curr->vfd_swmr_file != f2)
+ TEST_ERROR;
+
+ /* Close the second file with VFD SWMR */
+ if(H5Fclose(fid2) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Head of EOT queue should not be a writer */
+ if((curr = TAILQ_FIRST(&eot_queue_g)) != NULL && curr->vfd_swmr_writer)
+ TEST_ERROR;
+ /* The EOT queue should be empty */
+ if(!TAILQ_EMPTY(&eot_queue_g))
+ TEST_ERROR;
+
+ /* Closing */
+ if(H5Pclose(fapl1) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(fapl2) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(fcpl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Free buffers */
+ if(config1)
+ HDfree(config1);
+ if(config2)
+ HDfree(config2);
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(fapl1);
+ H5Pclose(fapl2);
+ H5Pclose(fcpl);
+ H5Fclose(fid);
+ H5Fclose(fid1);
+ H5Fclose(fid2);
+ } H5E_END_TRY;
+ if(config1)
+ HDfree(config1);
+ if(config2)
+ HDfree(config2);
+
+ return 1;
+} /* test_multiple_file_opens() */
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_same_file_opens()
+ *
+ * Purpose: Verify multiple opens of the same file as listed below:
+ *
+ * #1st open#
+ * #2nd open# VW VR W R
+ * ------------------
+ * VW | s f f f |
+ * VR | f f f f |
+ * W | f f s f |
+ * R | f f s s |
+ * ------------------
+ *
+ * Notations:
+ * W: H5F_ACC_RDWR
+ * R: H5F_ACC_RDONLY
+ * VW: VFD SWMR writer
+ * VR: VFD SWMR reader
+ *
+ * f: the open fails
+ * s: the open succeeds
+ *
+ * Return: 0 if test is sucessful
+ * 1 if test fails
+ *
+ * Programmer: Vailin Choi; October 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+static unsigned
+test_same_file_opens(void)
+{
+ hid_t fid = -1; /* File ID */
+ hid_t fid2 = -1; /* File ID */
+ hid_t fcpl = -1; /* File creation property list ID */
+ hid_t fapl1 = -1; /* File access property list ID */
+ hid_t fapl2 = -1; /* File access property list ID */
+ H5F_vfd_swmr_config_t *config1 = NULL; /* Configuration for VFD SWMR */
+ H5F_vfd_swmr_config_t *config2 = NULL; /* Configuration for VFD SWMR */
+
+ TESTING("Multiple opens of the same file with VFD SWMR configuration");
+
+ /* Should succeed without VFD SWMR configured */
+ if((fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR;
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Allocate memory for the configuration structure */
+ if((config1 = HDmalloc(sizeof(*config1))) == NULL)
+ FAIL_STACK_ERROR;
+ if((config2 = HDmalloc(sizeof(*config2))) == NULL)
+ FAIL_STACK_ERROR;
+
+ /* Create a copy of the file creation property list */
+ if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set file space strategy */
+ if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, FALSE, 1) < 0)
+ FAIL_STACK_ERROR;
+
+ /*
+ * Tests for first column
+ */
+
+ /* Create the test file */
+ if((fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, H5P_DEFAULT)) < 0)
+ TEST_ERROR;
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+
+ /* Set the VFD SWMR configuration in fapl1 + page buffering */
+ fapl1 = init_vfd_swmr_config_fapl(config1, 4, 10, TRUE, 2, MD_FILENAME, 4096);
+ if(fapl1 == H5I_INVALID_HID)
+ FAIL_STACK_ERROR;
+
+ /* Open the file as VFD SWMR writer */
+ /* Keep the file open */
+ if((fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl1)) < 0)
+ TEST_ERROR;
+
+ /* Open the same file again as VFD SWMR writer */
+ /* Should succeed: 1st open--VFD SWMR writer, 2nd open--VFD SWMR writer */
+ if((fid2 = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl1)) < 0)
+ TEST_ERROR;
+
+ /* Close the second file open */
+ if(H5Fclose(fid2) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Set the VFD SWMR configuration in fapl2 + page buffering */
+ fapl2 = init_vfd_swmr_config_fapl(config2, 3, 8, FALSE, 3, MD_FILENAME, 4096);
+ if(fapl2 == H5I_INVALID_HID)
+ FAIL_STACK_ERROR;
+
+ /* Open the same file again as VFD SWMR reader */
+ /* Should fail: 1st open--VFD SWMR writer, 2nd open--VFD SWMR reader */
+ H5E_BEGIN_TRY {
+ fid2 = H5Fopen(FILENAME, H5F_ACC_RDONLY, fapl2);
+ } H5E_END_TRY;
+ if(fid2 >= 0)
+ TEST_ERROR;
+
+ if(H5Pclose(fapl2) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Open the same file again as regular writer */
+ /* Should fail: 1st open--VFD SWMR writer, 2nd open--regular writer */
+ H5E_BEGIN_TRY {
+ fid2 = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT);
+ } H5E_END_TRY;
+ if(fid2 >= 0)
+ TEST_ERROR;
+
+ /* Open the same file again as regular reader */
+ /* Should fail: 1st open--VFD SWMR writer, 2nd open--regular reader */
+ H5E_BEGIN_TRY {
+ fid2 = H5Fopen(FILENAME, H5F_ACC_RDONLY, H5P_DEFAULT);
+ } H5E_END_TRY;
+ if(fid2 >= 0)
+ TEST_ERROR;
+
+ /* Close the 1st open file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+
+ /*
+ * Tests for second column
+ */
+
+ /* Set up as VFD SWMR reader + page buffering */
+ fapl1 = init_vfd_swmr_config_fapl(config1, 4, 10, FALSE, 2, MD_FILENAME, 4096);
+ if(fapl1 == H5I_INVALID_HID)
+ FAIL_STACK_ERROR;
+
+ /* Open the file as VFD SWMR reader */
+ /* Should fail because there is no metadata file */
+ /* Take a while to complete due to retries */
+ H5E_BEGIN_TRY {
+ fid = H5Fopen(FILENAME, H5F_ACC_RDONLY, fapl1);
+ } H5E_END_TRY;
+ if(fid >= 0)
+ TEST_ERROR;
+
+ if(H5Pclose(fapl1) < 0)
+ FAIL_STACK_ERROR;
+
+ /*
+ * Tests for third column
+ */
+
+ /* Open the file as regular writer */
+ /* Keep the file open */
+ if((fid = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0)
+ TEST_ERROR;
+
+ /* Set up as VFD SWMR writer + page buffering */
+ fapl1 = init_vfd_swmr_config_fapl(config1, 4, 10, TRUE, 2, MD_FILENAME, 4096);
+ if(fapl1 == H5I_INVALID_HID)
+ FAIL_STACK_ERROR;
+
+ /* Open the same file again as VFD SWMR writer */
+ /* Should fail: 1st open--regular writer, 2nd open--VFD SWMR writer */
+ H5E_BEGIN_TRY {
+ fid2 = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl1);
+ } H5E_END_TRY;
+ if(fid2 >= 0)
+ TEST_ERROR;
+
+ if(H5Pclose(fapl1) < 0)
+ FAIL_STACK_ERROR;
+
+
+ /* Open the same file again as regular writer */
+ /* Should succeed: 1st open--regular writer, 2nd open--regular writer */
+ if((fid2 = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0)
+ TEST_ERROR;
+
+ if(H5Fclose(fid2) < 0)
+ FAIL_STACK_ERROR;
+
+
+ /* Open the same file again as regular reader */
+ /* Should succeed: 1st open is writer, 2nd open is the same file as reader */
+ if((fid2 = H5Fopen(FILENAME, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0)
+ TEST_ERROR;
+
+ if(H5Fclose(fid2) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Close the 1st open file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /*
+ * Tests for fourth column
+ */
+
+ /* Open the file as regular reader */
+ /* keep the file open */
+ if((fid = H5Fopen(FILENAME, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0)
+ TEST_ERROR;
+
+ /* Set up as VFD SWMR writer + page buffering */
+ fapl1 = init_vfd_swmr_config_fapl(config1, 4, 10, TRUE, 2, MD_FILENAME, 4096);
+ if(fapl1 == H5I_INVALID_HID)
+ FAIL_STACK_ERROR;
+
+ /* Open the same file again as VFD SMWR writer */
+ /* Should fail: 1st open--regular reader, 2nd open--VFD SWMR writer */
+ H5E_BEGIN_TRY {
+ fid2 = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl1);
+ } H5E_END_TRY;
+ if(fid2 >= 0)
+ TEST_ERROR;
+
+ if(H5Pclose(fapl1) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Open the same file again as regular reader */
+ /* Should succeed: 1st open--regular reader, 2nd open--regular reader */
+ if((fid2 = H5Fopen(FILENAME, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0)
+ TEST_ERROR;
+
+ if(H5Fclose(fid2) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Open the same file again as regular writer */
+ /* Should fail: 1st open--regular reader, 2nd open--regular writer */
+ H5E_BEGIN_TRY {
+ fid2 = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT);
+ } H5E_END_TRY;
+ if(fid2 >= 0)
+ TEST_ERROR;
+
+ /* Close the 1st open file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ if(H5Pclose(fcpl) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Free buffers */
+ if(config1)
+ HDfree(config1);
+ if(config2)
+ HDfree(config2);
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(fapl1);
+ H5Pclose(fapl2);
+ H5Pclose(fcpl);
+ H5Fclose(fid);
+ H5Fclose(fid2);
+ } H5E_END_TRY;
+ if(config1)
+ HDfree(config1);
+ if(config2)
+ HDfree(config2);
+ return 1;
+} /* test_same_file_opens() */
+
+#ifndef _arraycount
+#define _arraycount(_a) (sizeof(_a)/sizeof(_a[0]))
+#endif
+
+static unsigned
+test_shadow_index_lookup(void)
+{
+ unsigned nerrors = 0;
+ H5FD_vfd_swmr_idx_entry_t *idx;
+ uint32_t size[] = {0, 1, 2, 3, 4, 0};
+ char vector[8];
+ unsigned seed = 1;
+ unsigned i, j, failj = UINT_MAX;
+ bool have_failj = false;
+ unsigned long tmpl;
+ char *ostate;
+ const char *seedvar = "H5_SHADOW_INDEX_SEED";
+ const char *failvar = "H5_SHADOW_INDEX_FAIL";
+
+ TESTING("Shadow-index lookups");
+
+ /* get seed from environment or else from time(3) */
+ switch (fetch_env_ulong(seedvar, UINT_MAX, &tmpl)) {
+ case -1:
+ nerrors = 1;
+ goto out;
+ case 0:
+ seed = (unsigned int)time(NULL);
+ break;
+ default:
+ seed = (unsigned int)tmpl;
+ break;
+ }
+
+ /* get forced-fail index from environment */
+ switch (fetch_env_ulong(failvar, UINT_MAX, &tmpl)) {
+ case -1:
+ nerrors = 1;
+ goto out;
+ case 0:
+ break;
+ default:
+ failj = (unsigned int)tmpl;
+ have_failj = true;
+ break;
+ }
+
+ ostate = initstate(seed, vector, _arraycount(vector));
+
+ size[5] = (uint32_t)(1024 + random() % (16 * 1024 * 1024 - 1024));
+
+ for (i = 0; i < _arraycount(size); i++) {
+ uint32_t cursize = size[i];
+ const uint64_t modulus = UINT64_MAX / MAX(1, cursize);
+ uint64_t pageno;
+
+ assert(modulus > 1); // so that modulus - 1 > 0, below
+
+ idx = (cursize == 0) ? NULL : calloc(cursize, sizeof(*idx));
+ if (idx == NULL && cursize != 0) {
+ fprintf(stderr, "couldn't allocate %" PRIu32 " indices\n",
+ cursize);
+ exit(EXIT_FAILURE);
+ }
+ for (pageno = (uint64_t)random() % modulus, j = 0;
+ j < cursize;
+ j++, pageno += 1 + (uint64_t)random() % (modulus - 1)) {
+ idx[j].hdf5_page_offset = pageno;
+ }
+ for (j = 0; j < cursize; j++) {
+ H5FD_vfd_swmr_idx_entry_t *found;
+
+ found = vfd_swmr_pageno_to_mdf_idx_entry(idx, cursize,
+ idx[j].hdf5_page_offset, false);
+ if ((have_failj && failj == j) || found != &idx[j])
+ break;
+ }
+ if (j < cursize) {
+ printf("\nshadow-index entry %d lookup, pageno %" PRIu64
+ ", index size %" PRIu32 ", seed %u", j,
+ idx[j].hdf5_page_offset, cursize, seed);
+ nerrors++;
+ }
+ if (idx != NULL)
+ free(idx);
+ }
+ (void)setstate(ostate);
+out:
+ if (nerrors == 0)
+ PASSED();
+ else
+ printf(" FAILED\n");
+ return nerrors;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: test_enable_disable_eot()
+ *
+ * Purpose: Verify the public routines:
+ * H5Fvfd_swmr_enable_end_of_tick()
+ * H5Fvfd_swmr_disable_end_of_tick()
+ * enables/disables EOT for the specified file
+ *
+ * Return: 0 if test is sucessful
+ * 1 if test fails
+ *
+ * Programmer: Vailin Choi; June 2020
+ *
+ *-------------------------------------------------------------------------
+ */
+static unsigned
+test_enable_disable_eot(void)
+{
+ hid_t fid = H5I_INVALID_HID; /* File ID */
+ hid_t fid1 = H5I_INVALID_HID; /* File ID */
+ hid_t fid2 = H5I_INVALID_HID; /* File ID */
+ hid_t fid3 = H5I_INVALID_HID; /* File ID */
+ hid_t fcpl = H5I_INVALID_HID; /* File creation property list ID */
+ hid_t fapl1 = H5I_INVALID_HID; /* File access property list ID */
+ hid_t fapl2 = H5I_INVALID_HID; /* File access property list ID */
+ hid_t fapl3 = H5I_INVALID_HID; /* File access property list ID */
+ H5F_t *f1, *f2, *f3; /* File pointer */
+ H5F_vfd_swmr_config_t *config1 = NULL; /* Configuration for VFD SWMR */
+ H5F_vfd_swmr_config_t *config2 = NULL; /* Configuration for VFD SWMR */
+ H5F_vfd_swmr_config_t *config3 = NULL; /* Configuration for VFD SWMR */
+ eot_queue_entry_t *curr; /* Pointer to an entry on the EOT queue */
+ unsigned count = 0; /* Counter */
+ herr_t ret; /* Return value */
+
+ TESTING("H5Fvfd_swmr_enable/disable_end_of_tick()");
+
+ /* Allocate memory for the configuration structure */
+ if((config1 = HDmalloc(sizeof(*config1))) == NULL)
+ FAIL_STACK_ERROR;
+ if((config2 = HDmalloc(sizeof(*config2))) == NULL)
+ FAIL_STACK_ERROR;
+ if((config3 = HDmalloc(sizeof(*config3))) == NULL)
+ FAIL_STACK_ERROR;
+
+ /* Configured first file as VFD SWMR writer + page buffering */
+ fapl1 = init_vfd_swmr_config_fapl(config1, 4, 6, TRUE, 2, MD_FILENAME, 4096);
+ if(fapl1 == H5I_INVALID_HID)
+ FAIL_STACK_ERROR;
+
+ /* Configured second file as VFD SWMR writer + page buffering */
+ fapl2 = init_vfd_swmr_config_fapl(config2, 4, 6, TRUE, 2, MD_FILENAME2, 4096);
+ if(fapl2 == H5I_INVALID_HID)
+ FAIL_STACK_ERROR;
+
+ /* Configured third file as VFD SWMR writer + page buffering */
+ fapl3 = init_vfd_swmr_config_fapl(config3, 4, 6, TRUE, 2, MD_FILENAME3, 4096);
+ if(fapl3 == H5I_INVALID_HID)
+ FAIL_STACK_ERROR;
+
+ /* Create a copy of the file creation property list */
+ if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set file space strategy */
+ if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, FALSE, 1) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Create a file without VFD SWMR */
+ if((fid = H5Fcreate(FNAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR;
+
+ /* Should fail to disable the file because VFD SWMR is not configured */
+ H5E_BEGIN_TRY {
+ ret = H5Fvfd_swmr_disable_end_of_tick(fid);
+ } H5E_END_TRY;
+ if(ret >=0)
+ TEST_ERROR
+
+ if(H5Fclose(fid) < 0)
+ TEST_ERROR
+
+ /* Create file 1 with VFD SWMR writer */
+ if((fid1 = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, fapl1)) < 0)
+ TEST_ERROR;
+
+ /* Create file 2 with VFD SWMR writer */
+ if((fid2 = H5Fcreate(FILENAME2, H5F_ACC_TRUNC, fcpl, fapl2)) < 0)
+ TEST_ERROR;
+
+ /* Create file 3 with VFD SWMR writer */
+ if((fid3 = H5Fcreate(FILENAME3, H5F_ACC_TRUNC, fcpl, fapl3)) < 0)
+ TEST_ERROR;
+
+ /* Should have 3 files on the EOT queue */
+ TAILQ_FOREACH(curr, &eot_queue_g, link)
+ count++;
+ if(count != 3)
+ TEST_ERROR;
+
+ /* Disable EOT for file 1 */
+ if(H5Fvfd_swmr_disable_end_of_tick(fid1) < 0)
+ TEST_ERROR
+
+ /* Disable file 1 again should fail because the file has just been disabled */
+ H5E_BEGIN_TRY {
+ ret = H5Fvfd_swmr_disable_end_of_tick(fid1);
+ } H5E_END_TRY;
+ if(ret >=0)
+ TEST_ERROR
+
+ /* Should have 2 files on the EOT queue */
+ count = 0;
+ TAILQ_FOREACH(curr, &eot_queue_g, link)
+ count++;
+ if(count != 2)
+ TEST_ERROR
+
+ /* Get a pointer to the internal file object */
+ if(NULL == (f1 = H5VL_object(fid1)))
+ FAIL_STACK_ERROR
+
+ /* Should not find file 1 on the EOT queue */
+ TAILQ_FOREACH(curr, &eot_queue_g, link) {
+ if(curr->vfd_swmr_file == f1)
+ break;
+ }
+ if(curr != NULL && curr->vfd_swmr_file == f1)
+ TEST_ERROR
+
+ /* Enable EOT for file 2 should fail because the file has not been disabled */
+ H5E_BEGIN_TRY {
+ ret = H5Fvfd_swmr_enable_end_of_tick(fid2);
+ } H5E_END_TRY;
+ if(ret >=0)
+ TEST_ERROR
+
+ /* Get a pointer to the internal file object */
+ if(NULL == (f2 = H5VL_object(fid2)))
+ FAIL_STACK_ERROR
+
+ /* File 2 should be on the EOT queue */
+ TAILQ_FOREACH(curr, &eot_queue_g, link) {
+ if(curr->vfd_swmr_file == f2)
+ break;
+ }
+ if(curr == NULL || curr->vfd_swmr_file != f2)
+ TEST_ERROR
+
+ /* Close file 3 */
+ if(H5Fclose(fid3) < 0)
+ TEST_ERROR
+
+ /* Open file 3 again without VFD SWMR writer */
+ if((fid3 = H5Fopen(FILENAME3, H5F_ACC_RDWR, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Get a pointer to the internal file object for file 3 */
+ if(NULL == (f3 = H5VL_object(fid3)))
+ FAIL_STACK_ERROR
+
+ /* File 3 should not exist on the EOT queue */
+ TAILQ_FOREACH(curr, &eot_queue_g, link) {
+ if(curr->vfd_swmr_file == f3)
+ break;
+ }
+ if(curr != NULL && curr->vfd_swmr_file == f3)
+ TEST_ERROR
+
+ /* Should have 2 files on the EOT queue */
+ count = 0;
+ TAILQ_FOREACH(curr, &eot_queue_g, link)
+ count++;
+ if(count != 1)
+ TEST_ERROR;
+
+ /* Should fail to enable file 3 */
+ H5E_BEGIN_TRY {
+ ret = H5Fvfd_swmr_enable_end_of_tick(fid3);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Should fail to disable file 3 */
+ H5E_BEGIN_TRY {
+ ret = H5Fvfd_swmr_disable_end_of_tick(fid3);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Closing */
+ if(H5Fclose(fid1) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Fclose(fid2) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Fclose(fid3) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(fapl1) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(fapl2) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(fapl3) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(fcpl) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Free buffers */
+ if(config1)
+ HDfree(config1);
+ if(config2)
+ HDfree(config2);
+ if(config3)
+ HDfree(config3);
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(fapl1);
+ H5Pclose(fapl2);
+ H5Pclose(fapl3);
+ H5Pclose(fcpl);
+ H5Fclose(fid);
+ H5Fclose(fid1);
+ H5Fclose(fid2);
+ H5Fclose(fid3);
+ } H5E_END_TRY;
+ if(config1)
+ HDfree(config1);
+ if(config2)
+ HDfree(config2);
+ if(config3)
+ HDfree(config3);
+
+ return 1;
+} /* test_enable_disable_eot() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: main()
+ *
+ * Purpose: Main function for VFD SWMR tests.
+ *
+ * Return: 0 if test is sucessful
+ * 1 if test fails
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+main(void)
+{
+ hid_t fapl = -1; /* File access property list for */
+ /* data files */
+ unsigned nerrors = 0; /* Cumulative error count */
+ char *lock_env_var = NULL; /* File locking env var pointer */
+ const char *env_h5_drvr = NULL; /* File Driver value from environment */
+ hbool_t use_file_locking; /* Read from env var */
+
+ /* Check the environment variable that determines if we care
+ * about file locking. File locking should be used unless explicitly
+ * disabled.
+ */
+ lock_env_var = HDgetenv("HDF5_USE_FILE_LOCKING");
+ if(lock_env_var && !HDstrcmp(lock_env_var, "FALSE"))
+ use_file_locking = FALSE;
+ else
+ use_file_locking = TRUE;
+
+ /* Get the VFD to use */
+ env_h5_drvr = HDgetenv("HDF5_DRIVER");
+ if(env_h5_drvr == NULL)
+ env_h5_drvr = "nomatch";
+
+ /* Temporary skip testing with multi/split drivers:
+ * Page buffering depends on paged aggregation which is
+ * currently disabled for multi/split drivers.
+ */
+ if((0 == HDstrcmp(env_h5_drvr, "multi")) ||
+ (0 == HDstrcmp(env_h5_drvr, "split"))) {
+
+ SKIPPED()
+ HDputs("Skip VFD SWMR test because paged aggregation is disabled for multi/split drivers");
+ HDexit(EXIT_SUCCESS);
+ } /* end if */
+
+ /* Set up */
+ h5_reset();
+
+ if((fapl = h5_fileaccess()) < 0) {
+ nerrors++;
+ PUTS_ERROR("Can't get VFD-dependent fapl")
+ } /* end if */
+
+ nerrors += test_fapl();
+
+ if(use_file_locking) {
+ nerrors += test_shadow_index_lookup();
+
+ nerrors += test_file_fapl();
+ nerrors += test_writer_create_open_flush();
+ nerrors += test_writer_md();
+ nerrors += test_reader_md_concur();
+
+ nerrors += test_multiple_file_opens();
+ nerrors += test_multiple_file_opens_concur();
+ nerrors += test_same_file_opens();
+
+ nerrors += test_enable_disable_eot();
+ nerrors += test_disable_enable_eot_concur();
+
+ nerrors += test_file_end_tick();
+ nerrors += test_file_end_tick_concur();
+ }
+
+ if(nerrors)
+ goto error;
+
+ HDputs("All VFD SWMR tests passed.");
+
+ HDexit(EXIT_SUCCESS);
+
+error:
+ HDprintf("***** %d VFD SWMR TEST%s FAILED! *****\n",
+ nerrors, nerrors > 1 ? "S" : "");
+
+ H5E_BEGIN_TRY {
+ H5Pclose(fapl);
+ } H5E_END_TRY;
+
+ HDexit(EXIT_FAILURE);
+}
diff --git a/test/vfd_swmr_addrem_writer.c b/test/vfd_swmr_addrem_writer.c
new file mode 100644
index 0000000..a8aefa9
--- /dev/null
+++ b/test/vfd_swmr_addrem_writer.c
@@ -0,0 +1,502 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: vfd_swmr_addrem_writer.c
+ * (copied and modified from swmr_addrem_writer.c)
+ *
+ * Purpose: Adds and removes data to a randomly selected subset of the
+ * datasets in the VFD SWMR test file.
+ *
+ * This program is intended to run concurrently with the
+ * vfd_swmr_reader program. It is also run AFTER a sequential
+ * (not concurrent!) invoking of vfd_swmr_writer so the writer
+ * can dump a bunch of data into the datasets. Otherwise,
+ * there wouldn't be much to shrink :)
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/***********/
+/* Headers */
+/***********/
+
+#include <err.h> /* errx(3) */
+#include <stdlib.h> /* EXIT_FAILURE */
+
+#include "h5test.h"
+#include "vfd_swmr_common.h"
+
+/****************/
+/* Local Macros */
+/****************/
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+static hid_t open_skeleton(const char *filename, unsigned verbose);
+static int addrem_records(hid_t fid, unsigned verbose, unsigned long nops,
+ unsigned long flush_count);
+static void usage(void);
+
+
+/*-------------------------------------------------------------------------
+ * Function: open_skeleton
+ *
+ * Purpose: Opens the SWMR HDF5 file and datasets.
+ *
+ * Parameters: const char *filename
+ * The filename of the SWMR HDF5 file to open
+ *
+ * unsigned verbose
+ * Whether or not to emit verbose console messages
+ *
+ * Return: Success: The file ID of the opened SWMR file
+ * The dataset IDs are stored in a global array
+ *
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static hid_t
+open_skeleton(const char *filename, unsigned verbose)
+{
+ hid_t dapl = H5I_INVALID_HID;
+ hid_t fid = -1; /* File ID for new HDF5 file */
+ hid_t fapl = -1; /* File access property list */
+ hid_t sid = -1; /* Dataspace ID */
+ hsize_t dim[2]; /* Dataspace dimension */
+ unsigned u, v; /* Local index variable */
+ H5F_vfd_swmr_config_t *config = NULL; /* Configuration for VFD SWMR */
+
+ HDassert(filename);
+
+ /* Create file access property list */
+ if((fapl = h5_fileaccess()) < 0)
+ goto error;
+
+ if ((dapl = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
+ errx(EXIT_FAILURE, "%s.%d: H5Pcreate failed", __func__, __LINE__);
+
+ if (H5Pset_chunk_cache(dapl, H5D_CHUNK_CACHE_NSLOTS_DEFAULT, 0,
+ H5D_CHUNK_CACHE_W0_DEFAULT) < 0)
+ errx(EXIT_FAILURE, "H5Pset_chunk_cache failed");
+
+ /* Set to use the latest library format */
+ if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
+ goto error;
+
+ /*
+ * Set up to open the file with VFD SWMR configured.
+ */
+
+ /* Enable page buffering */
+ if(H5Pset_page_buffer_size(fapl, 4096, 0, 0) < 0)
+ goto error;
+
+ /* Allocate memory for the configuration structure */
+ if((config = (H5F_vfd_swmr_config_t *)calloc(1, sizeof(H5F_vfd_swmr_config_t))) == NULL)
+ goto error;
+
+ config->version = H5F__CURR_VFD_SWMR_CONFIG_VERSION;
+ config->tick_len = 4;
+ config->max_lag = 5;
+ config->writer = TRUE;
+ config->md_pages_reserved = 128;
+ HDstrcpy(config->md_file_path, "./my_md_file");
+
+ /* Enable VFD SWMR configuration */
+ if(H5Pset_vfd_swmr_config(fapl, config) < 0)
+ goto error;
+
+ /* Open the file */
+ if((fid = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
+ goto error;
+
+ /* Close file access property list */
+ if(H5Pclose(fapl) < 0)
+ goto error;
+
+ if(config)
+ HDfree(config);
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "WRITER: Opening datasets\n");
+
+ /* Open the datasets */
+ for(u = 0; u < NLEVELS; u++)
+ for(v = 0; v < symbol_count[u]; v++) {
+ hid_t dsid;
+
+ if((dsid = H5Dopen2(fid, symbol_info[u][v].name, dapl)) < 0)
+ goto error;
+
+ symbol_info[u][v].dsid = dsid;
+
+ if((sid = H5Dget_space(symbol_info[u][v].dsid)) < 0)
+ goto error;
+ if(2 != H5Sget_simple_extent_ndims(sid))
+ goto error;
+ if(H5Sget_simple_extent_dims(sid, dim, NULL) < 0)
+ goto error;
+ symbol_info[u][v].nrecords = dim[1];
+
+ if(H5Sclose(sid) < 0)
+ goto error;
+ } /* end for */
+
+ return fid;
+
+error:
+ if(config)
+ HDfree(config);
+
+ H5E_BEGIN_TRY {
+ for(u = 0; u < NLEVELS; u++)
+ for(v = 0; v < symbol_count[u]; v++)
+ H5Dclose(symbol_info[u][v].dsid);
+ H5Sclose(sid);
+ H5Pclose(fapl);
+ H5Fclose(fid);
+ H5Pclose(dapl);
+ } H5E_END_TRY;
+
+ return -1;
+
+} /* open_skeleton() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: addrem_records
+ *
+ * Purpose: Adds/removes a specified number of records to random datasets
+ * to the SWMR test file.
+ *
+ * Parameters: hid_t fid
+ * The file ID of the SWMR HDF5 file
+ *
+ * unsigned verbose
+ * Whether or not to emit verbose console messages
+ *
+ * unsigned long nops
+ * # of records to read/write in the datasets
+ *
+ * unsigned long flush_count
+ * # of records to write before flushing the file to disk
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+addrem_records(hid_t fid, unsigned verbose, unsigned long nops, unsigned long flush_count)
+{
+ hid_t tid = -1; /* Datatype ID for records */
+ hid_t mem_sid = -1; /* Memory dataspace ID */
+ hid_t file_sid = -1; /* Dataset's space ID */
+ hsize_t start[2] = {0, 0}, count[2] = {1, 1}; /* Hyperslab selection values */
+ hsize_t dim[2] = {1, 0}; /* Dataspace dimensions */
+ symbol_t buf[MAX_SIZE_CHANGE]; /* Write buffer */
+ unsigned long op_to_flush; /* # of operations before flush */
+ unsigned long u, v; /* Local index variables */
+
+ HDassert(fid > 0);
+
+ /* Reset the buffer */
+ HDmemset(&buf, 0, sizeof(buf));
+
+ /* Create a dataspace for the record to add */
+ if((mem_sid = H5Screate_simple(2, count, NULL)) < 0)
+ goto error;
+
+ /* Create datatype for appending records */
+ if((tid = create_symbol_datatype()) < 0)
+ goto error;
+
+ /* Add and remove records to random datasets, according to frequency
+ * distribution */
+ op_to_flush = flush_count;
+ for(u=0; u<nops; u++) {
+ symbol_info_t *symbol; /* Symbol to write record to */
+
+ /* Get a random dataset, according to the symbol distribution */
+ symbol = choose_dataset(NULL, NULL);
+
+ /* Decide whether to shrink or expand, and by how much */
+ count[1] = (hsize_t)HDrandom() % (MAX_SIZE_CHANGE * 2) + 1;
+
+ if(count[1] > MAX_SIZE_CHANGE) {
+ /* Add records */
+ count[1] -= MAX_SIZE_CHANGE;
+
+ /* Set the buffer's IDs (equal to its position) */
+ for(v=0; v<count[1]; v++)
+ buf[v].rec_id = (uint64_t)symbol->nrecords + (uint64_t)v;
+
+ /* Set the memory space to the correct size */
+ if(H5Sset_extent_simple(mem_sid, 2, count, NULL) < 0)
+ goto error;
+
+ /* Get the coordinates to write */
+ start[1] = symbol->nrecords;
+
+ /* Extend the dataset's dataspace to hold the new record */
+ symbol->nrecords+= count[1];
+ dim[1] = symbol->nrecords;
+ if(H5Dset_extent(symbol->dsid, dim) < 0)
+ goto error;
+
+ /* Get the dataset's dataspace */
+ if((file_sid = H5Dget_space(symbol->dsid)) < 0)
+ goto error;
+
+ /* Choose the last record in the dataset */
+ if(H5Sselect_hyperslab(file_sid, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ goto error;
+
+ /* Write record to the dataset */
+ if(H5Dwrite(symbol->dsid, tid, mem_sid, file_sid, H5P_DEFAULT, &buf) < 0)
+ goto error;
+
+ if(H5Dflush(symbol->dsid) < 0)
+ goto error;
+
+ /* Close the dataset's dataspace */
+ if(H5Sclose(file_sid) < 0)
+ goto error;
+ } /* end if */
+ else {
+ /* Shrink the dataset's dataspace */
+ if(count[1] > symbol->nrecords)
+ symbol->nrecords = 0;
+ else
+ symbol->nrecords -= count[1];
+ dim[1] = symbol->nrecords;
+ if(H5Dset_extent(symbol->dsid, dim) < 0)
+ goto error;
+ } /* end else */
+
+ /* Check for flushing file */
+ if(flush_count > 0) {
+ /* Decrement count of records to write before flushing */
+ op_to_flush--;
+
+ /* Check for counter being reached */
+ if(0 == op_to_flush) {
+#ifdef TEMP_OUT
+ /* Flush contents of file */
+ if(H5Fflush(fid, H5F_SCOPE_GLOBAL) < 0)
+ return -1;
+#endif /* TEMP_OUT */
+
+ /* Reset flush counter */
+ op_to_flush = flush_count;
+ } /* end if */
+ } /* end if */
+ } /* end for */
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "WRITER: Closing datasets\n");
+
+ /* Close the datasets */
+ for(u = 0; u < NLEVELS; u++)
+ for(v = 0; v < symbol_count[u]; v++)
+ if(H5Dclose(symbol_info[u][v].dsid) < 0)
+ return -1;
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Sclose(mem_sid);
+ H5Sclose(file_sid);
+ H5Tclose(tid);
+
+ for(u = 0; u < NLEVELS; u++)
+ for(v = 0; v < symbol_count[u]; v++)
+ H5Dclose(symbol_info[u][v].dsid);
+
+ } H5E_END_TRY;
+
+ return -1;
+
+} /* addrem_records() */
+
+static void
+usage(void)
+{
+ printf("\n");
+ printf("Usage error!\n");
+ printf("\n");
+ printf("Usage: vfd_swmr_addrem_writer [-q] [-f <# of operations between flushing\n");
+ printf(" file contents>] [-r <random seed>] <# of operations>\n");
+ printf("\n");
+ printf("<# of operations between flushing file contents> should be 0 (for\n");
+ printf("no flushing) or between 1 and (<# of operations> - 1).\n");
+ printf("\n");
+ printf("<# of operations> must be specified.\n");
+ printf("\n");
+ printf("Defaults to verbose (no '-q' given), flushing every 1000 operations\n");
+ printf("('-f 1000'), and will generate a random seed (no -r given).\n");
+ printf("\n");
+ HDexit(1);
+} /* usage() */
+
+int main(int argc, const char *argv[])
+{
+ sigset_t oldset;
+ hid_t fid; /* File ID for file opened */
+ long nops = 0; /* # of times to grow or shrink the dataset */
+ long flush_count = 1000; /* # of records to write between flushing file */
+ unsigned verbose = 1; /* Whether to emit some informational messages */
+ unsigned use_seed = 0; /* Set to 1 if a seed was set on the command line */
+ unsigned random_seed = 0; /* Random # seed */
+ unsigned u; /* Local index variable */
+ int temp;
+
+ block_signals(&oldset);
+
+ /* Parse command line options */
+ if(argc < 2)
+ usage();
+ if(argc > 1) {
+ u = 1;
+ while(u < (unsigned)argc) {
+ if(argv[u][0] == '-') {
+ switch(argv[u][1]) {
+ /* # of records to write between flushing file */
+ case 'f':
+ flush_count = HDatol(argv[u + 1]);
+ if(flush_count < 0)
+ usage();
+ u += 2;
+ break;
+
+ /* Be quiet */
+ case 'q':
+ verbose = 0;
+ u++;
+ break;
+
+ /* Random # seed */
+ case 'r':
+ use_seed = 1;
+ temp = HDatoi(argv[u + 1]);
+ if(temp < 0)
+ usage();
+ else
+ random_seed = (unsigned)temp;
+ u += 2;
+ break;
+
+ default:
+ usage();
+ break;
+ } /* end switch */
+ } /* end if */
+ else {
+ /* Get the number of records to append */
+ nops = HDatol(argv[u]);
+ if(nops <= 0)
+ usage();
+
+ u++;
+ } /* end else */
+ } /* end while */
+ } /* end if */
+ if(nops <= 0)
+ usage();
+ if(flush_count >= nops)
+ usage();
+
+ /* Emit informational message */
+ if(verbose) {
+ HDfprintf(stderr, "WRITER: Parameters:\n");
+ HDfprintf(stderr, "\t# of operations between flushes = %ld\n", flush_count);
+ HDfprintf(stderr, "\t# of operations = %ld\n", nops);
+ } /* end if */
+
+ /* Set the random seed */
+ if(0 == use_seed) {
+ struct timeval t;
+ HDgettimeofday(&t, NULL);
+ random_seed = (unsigned)(t.tv_usec);
+ } /* end if */
+ HDsrandom(random_seed);
+ /* ALWAYS emit the random seed for possible debugging */
+ HDfprintf(stderr, "WRITER: Using writer random seed: %u\n", random_seed);
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "WRITER: Generating symbol names\n");
+
+ /* Generate dataset names */
+ if(generate_symbols() < 0)
+ return -1;
+
+ /* Emit informational message */
+ if(verbose) {
+ HDfprintf(stderr, "WRITER: Opening skeleton file: %s\n",
+ COMMON_FILENAME);
+ }
+
+ /* Open file skeleton */
+ if((fid = open_skeleton(COMMON_FILENAME, verbose)) < 0) {
+ HDfprintf(stderr, "WRITER: Error opening skeleton file!\n");
+ HDexit(1);
+ } /* end if */
+
+ /* Send a message to indicate "H5Fopen" is complete--releasing the file lock */
+ h5_send_message(WRITER_MESSAGE, NULL, NULL);
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "WRITER: Adding and removing records\n");
+
+ /* Grow and shrink datasets */
+ if(addrem_records(fid, verbose, (unsigned long)nops, (unsigned long)flush_count) < 0) {
+ HDfprintf(stderr, "WRITER: Error adding and removing records from datasets!\n");
+ HDexit(1);
+ } /* end if */
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "WRITER: Releasing symbols\n");
+
+ /* Clean up the symbols */
+ if(shutdown_symbols() < 0) {
+ HDfprintf(stderr, "WRITER: Error releasing symbols!\n");
+ HDexit(1);
+ } /* end if */
+
+ await_signal(fid);
+
+ restore_signals(&oldset);
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "WRITER: Closing objects\n");
+
+ /* Close objects opened */
+ if(H5Fclose(fid) < 0) {
+ HDfprintf(stderr, "WRITER: Error closing file!\n");
+ HDexit(1);
+ } /* end if */
+
+ return 0;
+} /* main() */
diff --git a/test/vfd_swmr_bigset_writer.c b/test/vfd_swmr_bigset_writer.c
new file mode 100644
index 0000000..6d65c8b
--- /dev/null
+++ b/test/vfd_swmr_bigset_writer.c
@@ -0,0 +1,1104 @@
+/*
+ * Copyright by The HDF Group.
+ * Copyright by the Board of Trustees of the University of Illinois.
+ * All rights reserved.
+ *
+ * This file is part of HDF5. The full HDF5 copyright notice, including
+ * terms governing use, modification, and redistribution, is contained in
+ * the COPYING file, which can be found at the root of the source code
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases.
+ * If you do not have access to either file, you may request a copy from
+ * help@hdfgroup.org.
+ */
+
+#include <err.h>
+#include <libgen.h>
+#include <time.h> /* nanosleep(2) */
+#include <unistd.h> /* getopt(3) */
+
+#define H5C_FRIEND /*suppress error about including H5Cpkg */
+#define H5F_FRIEND /*suppress error about including H5Fpkg */
+
+#include "hdf5.h"
+
+#include "H5Cpkg.h"
+#include "H5Fpkg.h"
+// #include "H5Iprivate.h"
+#include "H5HGprivate.h"
+#include "H5VLprivate.h"
+
+#include "testhdf5.h"
+#include "vfd_swmr_common.h"
+
+#define ROWS 256
+#define COLS 512
+#define RANK 2
+
+static const unsigned int hang_back = 3;
+
+typedef struct _base {
+ hsize_t row, col;
+} base_t;
+
+typedef struct _mat {
+ unsigned rows, cols;
+ uint32_t elt[1];
+} mat_t;
+
+typedef struct _quadrant {
+ hsize_t start[RANK];
+ hsize_t stride[RANK];
+ hsize_t block[RANK];
+ hsize_t count[RANK];
+ hid_t space, src_space;
+} quadrant_t;
+
+typedef struct _sources {
+ hid_t ul, ur, bl, br;
+} sources_t;
+
+#define MANY_FILES 4
+
+typedef struct {
+ hid_t *dataset;
+ sources_t *sources;
+ hid_t file[MANY_FILES];
+ hid_t dapl, filetype, memspace, one_by_one_sid, quadrant_dcpl;
+ unsigned ndatasets;
+ const char *filename[MANY_FILES];
+ char progname[PATH_MAX];
+ struct timespec update_interval;
+ struct {
+ quadrant_t ul, ur, bl, br, src;
+ } quadrants;
+ unsigned int cols, rows;
+ unsigned int asteps;
+ unsigned int nsteps;
+ bool two_dee;
+ bool wait_for_signal;
+ enum {vds_off, vds_single, vds_multi} vds;
+ bool use_vfd_swmr;
+ bool writer;
+ hsize_t chunk_dims[RANK];
+ hsize_t one_dee_max_dims[RANK];
+} state_t;
+
+static inline state_t
+state_initializer(void)
+{
+ return (state_t){
+ .memspace = H5I_INVALID_HID
+ , .dapl = H5I_INVALID_HID
+ , .file = {H5I_INVALID_HID, H5I_INVALID_HID,
+ H5I_INVALID_HID, H5I_INVALID_HID}
+ , .filetype = H5T_NATIVE_UINT32
+ , .one_by_one_sid = H5I_INVALID_HID
+ , .quadrant_dcpl = H5I_INVALID_HID
+ , .rows = ROWS
+ , .cols = COLS
+ , .ndatasets = 5
+ , .asteps = 10
+ , .nsteps = 100
+ , .filename = {"", "", "", ""}
+ , .two_dee = false
+ , .wait_for_signal = true
+ , .vds = vds_off
+ , .use_vfd_swmr = true
+ , .writer = true
+ , .one_dee_max_dims = {ROWS, H5S_UNLIMITED}
+ , .chunk_dims = {ROWS, COLS}
+ , .update_interval = (struct timespec){
+ .tv_sec = 0
+ , .tv_nsec = 1000000000UL / 30 /* 1/30 second */}};
+}
+
+static void state_init(state_t *, int, char **);
+
+static const hid_t badhid = H5I_INVALID_HID;
+
+static const hsize_t two_dee_max_dims[RANK] = {H5S_UNLIMITED, H5S_UNLIMITED};
+
+static uint32_t
+matget(const mat_t *mat, unsigned i, unsigned j)
+{
+ assert(i < mat->rows && j < mat->cols);
+
+ return mat->elt[i * mat->cols + j];
+}
+
+static void
+matset(mat_t *mat, unsigned i, unsigned j, uint32_t v)
+{
+ assert(i < mat->rows && j < mat->cols);
+
+ mat->elt[i * mat->cols + j] = v;
+}
+
+static mat_t *
+newmat(unsigned rows, unsigned cols)
+{
+ mat_t *mat;
+
+ mat = malloc(sizeof(*mat) + (rows * cols - 1) * sizeof(mat->elt[0]));
+
+ if (mat == NULL)
+ err(EXIT_FAILURE, "%s: malloc", __func__);
+
+ mat->rows = rows;
+ mat->cols = cols;
+
+ return mat;
+}
+
+static void
+usage(const char *progname)
+{
+ fprintf(stderr, "usage: %s [-S] [-W] [-a steps] [-b] [-c cols]\n"
+ " [-d dims]\n"
+ " [-n iterations] [-r rows] [-s datasets]\n"
+ " [-u milliseconds]\n"
+ "\n"
+ "-M: use virtual datasets and many source\n"
+ " files\n"
+ "-S: do not use VFD SWMR\n"
+ "-V: use virtual datasets and a single\n"
+ " source file\n"
+ "-W: do not wait for a signal before\n"
+ " exiting\n"
+ "-a steps: `steps` between adding attributes\n"
+ "-b: write data in big-endian byte order\n"
+ "-c cols: `cols` columns per chunk\n"
+ "-d 1|one|2|two|both: select dataset expansion in one or\n"
+ " both dimensions\n"
+ "-n iterations: how many times to expand each dataset\n"
+ "-r rows: `rows` rows per chunk\n"
+ "-s datasets: number of datasets to create\n"
+ "-u ms: milliseconds interval between updates\n"
+ " to %s.h5\n"
+ "\n",
+ progname, progname);
+ exit(EXIT_FAILURE);
+}
+
+static void
+make_quadrant_dataspace(state_t *s, quadrant_t *q)
+{
+ q->space = H5Screate_simple(NELMTS(s->chunk_dims), s->chunk_dims,
+ s->two_dee ? two_dee_max_dims : s->one_dee_max_dims);
+
+ if (q->space < 0) {
+ errx(EXIT_FAILURE, "%s.%d: H5Screate_simple failed",
+ __func__, __LINE__);
+ }
+
+ if (H5Sselect_hyperslab(q->space, H5S_SELECT_SET, q->start, q->stride,
+ q->count, q->block) < 0)
+ errx(EXIT_FAILURE, "%s: H5Sselect_hyperslab failed", __func__);
+}
+
+static void
+state_init(state_t *s, int argc, char **argv)
+{
+ unsigned long tmp;
+ int ch;
+ unsigned i;
+ const hsize_t dims = 1;
+ char tfile[PATH_MAX];
+ char *end;
+ unsigned long millis;
+ quadrant_t * const ul = &s->quadrants.ul,
+ * const ur = &s->quadrants.ur,
+ * const bl = &s->quadrants.bl,
+ * const br = &s->quadrants.br,
+ * const src = &s->quadrants.src;
+ const char *personality;
+
+ *s = state_initializer();
+ esnprintf(tfile, sizeof(tfile), "%s", argv[0]);
+ esnprintf(s->progname, sizeof(s->progname), "%s", basename(tfile));
+
+ while ((ch = getopt(argc, argv, "MSVWa:bc:d:n:qr:s:u:")) != -1) {
+ switch (ch) {
+ case 'M':
+ s->vds = vds_multi;
+ break;
+ case 'S':
+ s->use_vfd_swmr = false;
+ break;
+ case 'V':
+ s->vds = vds_single;
+ break;
+ case 'W':
+ s->wait_for_signal = false;
+ break;
+ case 'd':
+ if (strcmp(optarg, "1") == 0 ||
+ strcmp(optarg, "one") == 0)
+ s->two_dee = false;
+ else if (strcmp(optarg, "2") == 0 ||
+ strcmp(optarg, "two") == 0 ||
+ strcmp(optarg, "both") == 0)
+ s->two_dee = true;
+ else {
+ errx(EXIT_FAILURE,
+ "bad -d argument \"%s\"", optarg);
+ }
+ break;
+ case 'a':
+ case 'c':
+ case 'n':
+ case 'r':
+ case 's':
+ errno = 0;
+ tmp = strtoul(optarg, &end, 0);
+ if (end == optarg || *end != '\0') {
+ errx(EXIT_FAILURE, "couldn't parse `-%c` argument `%s`", ch,
+ optarg);
+ } else if (errno != 0) {
+ err(EXIT_FAILURE, "couldn't parse `-%c` argument `%s`", ch,
+ optarg);
+ } else if (tmp > UINT_MAX)
+ errx(EXIT_FAILURE, "`-%c` argument `%lu` too large", ch, tmp);
+
+ if ((ch == 'c' || ch == 'r') && tmp == 0) {
+ errx(EXIT_FAILURE, "`-%c` argument `%lu` must be >= 1", ch,
+ tmp);
+ }
+
+ if (ch == 'a')
+ s->asteps = (unsigned)tmp;
+ else if (ch == 'c')
+ s->cols = (unsigned)tmp;
+ else if (ch == 'n')
+ s->nsteps = (unsigned)tmp;
+ else if (ch == 'r')
+ s->rows = (unsigned)tmp;
+ else
+ s->ndatasets = (unsigned)tmp;
+ break;
+ case 'b':
+ s->filetype = H5T_STD_U32BE;
+ break;
+ case 'q':
+ verbosity = 0;
+ break;
+ case 'u':
+ errno = 0;
+ millis = strtoul(optarg, &end, 0);
+ if (millis == ULONG_MAX && errno == ERANGE) {
+ err(EXIT_FAILURE,
+ "option -p argument \"%s\"", optarg);
+ } else if (*end != '\0') {
+ errx(EXIT_FAILURE,
+ "garbage after -p argument \"%s\"", optarg);
+ }
+ s->update_interval.tv_sec = (time_t)(millis / 1000UL);
+ s->update_interval.tv_nsec =
+ (long)((millis * 1000000UL) % 1000000000UL);
+ break;
+ case '?':
+ default:
+ usage(s->progname);
+ break;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 0)
+ errx(EXIT_FAILURE, "unexpected command-line arguments");
+
+ if (s->vds != vds_off && s->two_dee) {
+ errx(EXIT_FAILURE,
+ "virtual datasets and 2D datasets are mutually exclusive");
+ }
+
+ s->chunk_dims[0] = s->rows;
+ s->chunk_dims[1] = s->cols;
+ s->one_dee_max_dims[0] = s->rows;
+ s->one_dee_max_dims[1] = H5S_UNLIMITED;
+
+ if (s->vds != vds_off) {
+ const hsize_t half_chunk_dims[RANK] = {s->rows / 2, s->cols / 2};
+ const hsize_t half_max_dims[RANK] = {s->rows / 2, H5S_UNLIMITED};
+
+ if ((s->quadrant_dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0) {
+ errx(EXIT_FAILURE, "%s.%d: H5Pcreate failed",
+ __func__, __LINE__);
+ }
+
+ if (H5Pset_chunk(s->quadrant_dcpl, RANK, half_chunk_dims) < 0)
+ errx(EXIT_FAILURE, "H5Pset_chunk failed");
+
+ *ul = (quadrant_t){
+ .start = {0, 0}
+ , .stride = {s->rows, s->cols}
+ , .block = {s->rows / 2, s->cols / 2}
+ , .count = {1, H5S_UNLIMITED}};
+
+ *ur = (quadrant_t){
+ .start = {s->rows / 2, 0}
+ , .stride = {s->rows, s->cols}
+ , .block = {s->rows / 2, s->cols / 2}
+ , .count = {1, H5S_UNLIMITED}};
+
+ *bl = (quadrant_t){
+ .start = {0, s->cols / 2}
+ , .stride = {s->rows, s->cols}
+ , .block = {s->rows / 2, s->cols / 2}
+ , .count = {1, H5S_UNLIMITED}};
+
+ *br = (quadrant_t){
+ .start = {s->rows / 2, s->cols / 2}
+ , .stride = {s->rows, s->cols}
+ , .block = {s->rows / 2, s->cols / 2}
+ , .count = {1, H5S_UNLIMITED}};
+
+ make_quadrant_dataspace(s, ul);
+ make_quadrant_dataspace(s, ur);
+ make_quadrant_dataspace(s, bl);
+ make_quadrant_dataspace(s, br);
+
+ *src = (quadrant_t){
+ .start = {0, 0}
+ , .stride = {s->rows / 2, s->cols / 2}
+ , .block = {s->rows / 2, s->cols / 2}
+ , .count = {1, H5S_UNLIMITED}};
+
+ src->space = H5Screate_simple(RANK, half_chunk_dims,
+ half_max_dims);
+
+ if (src->space < 0) {
+ errx(EXIT_FAILURE, "%s.%d: H5Screate_simple failed",
+ __func__, __LINE__);
+ }
+
+ if (H5Sselect_hyperslab(src->space, H5S_SELECT_SET, src->start,
+ src->stride, src->count, src->block) < 0)
+ errx(EXIT_FAILURE, "%s: H5Sselect_hyperslab failed", __func__);
+
+ ul->src_space = H5Screate_simple(RANK, half_chunk_dims, half_max_dims);
+
+ if (ul->src_space < 0) {
+ errx(EXIT_FAILURE, "%s.%d: H5Screate_simple failed",
+ __func__, __LINE__);
+ }
+
+ ur->src_space = H5Screate_simple(RANK, half_chunk_dims, half_max_dims);
+
+ if (ur->src_space < 0) {
+ errx(EXIT_FAILURE, "%s.%d: H5Screate_simple failed",
+ __func__, __LINE__);
+ }
+
+ bl->src_space = H5Screate_simple(RANK, half_chunk_dims, half_max_dims);
+
+ if (bl->src_space < 0) {
+ errx(EXIT_FAILURE, "%s.%d: H5Screate_simple failed",
+ __func__, __LINE__);
+ }
+
+ br->src_space = H5Screate_simple(RANK, half_chunk_dims, half_max_dims);
+
+ if (br->src_space < 0) {
+ errx(EXIT_FAILURE, "%s.%d: H5Screate_simple failed",
+ __func__, __LINE__);
+ }
+ }
+
+ /* space for attributes */
+ if ((s->one_by_one_sid = H5Screate_simple(1, &dims, &dims)) < 0)
+ errx(EXIT_FAILURE, "H5Screate_simple failed");
+
+ s->dataset = malloc(sizeof(*s->dataset) * s->ndatasets);
+ if (s->dataset == NULL)
+ err(EXIT_FAILURE, "could not allocate dataset handles");
+
+ s->sources = malloc(sizeof(*s->sources) * s->ndatasets);
+ if (s->sources == NULL)
+ err(EXIT_FAILURE, "could not allocate quadrant dataset handles");
+
+ for (i = 0; i < s->ndatasets; i++) {
+ s->dataset[i] = badhid;
+ s->sources[i].ul = s->sources[i].ur = s->sources[i].bl =
+ s->sources[i].br = badhid;
+ }
+
+ s->memspace = H5Screate_simple(RANK, s->chunk_dims, NULL);
+
+ if (s->memspace < 0) {
+ errx(EXIT_FAILURE, "%s.%d: H5Screate_simple failed",
+ __func__, __LINE__);
+ }
+
+ s->filename[0] = "vfd_swmr_bigset.h5";
+ if (s->vds == vds_multi) {
+ s->filename[1] = "vfd_swmr_bigset-ur.h5";
+ s->filename[2] = "vfd_swmr_bigset-bl.h5";
+ s->filename[3] = "vfd_swmr_bigset-br.h5";
+ } else {
+ s->filename[1] = s->filename[0];
+ s->filename[2] = s->filename[0];
+ s->filename[3] = s->filename[0];
+ }
+
+ personality = strstr(s->progname, "vfd_swmr_bigset_");
+
+ if (personality != NULL &&
+ strcmp(personality, "vfd_swmr_bigset_writer") == 0)
+ s->writer = true;
+ else if (personality != NULL &&
+ strcmp(personality, "vfd_swmr_bigset_reader") == 0)
+ s->writer = false;
+ else {
+ errx(EXIT_FAILURE,
+ "unknown personality, expected vfd_swmr_bigset_{reader,writer}");
+ }
+
+ if ((s->dapl = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
+ errx(EXIT_FAILURE, "%s.%d: H5Pcreate failed", __func__, __LINE__);
+
+ if (H5Pset_chunk_cache(s->dapl, 0, 0,
+ H5D_CHUNK_CACHE_W0_DEFAULT) < 0)
+ errx(EXIT_FAILURE, "H5Pset_chunk_cache failed");
+
+ if (s->vds != vds_off &&
+ H5Pset_virtual_view(s->dapl, H5D_VDS_FIRST_MISSING) < 0)
+ errx(EXIT_FAILURE, "H5Pset_virtual_view failed");
+}
+
+static void
+state_destroy(state_t *s)
+{
+ size_t i;
+
+ if (H5Pclose(s->dapl) < 0)
+ errx(EXIT_FAILURE, "H5Pclose(fapl)");
+
+ s->dapl = badhid;
+
+ if (s->vds != vds_off) {
+ quadrant_t * const ul = &s->quadrants.ul,
+ * const ur = &s->quadrants.ur,
+ * const bl = &s->quadrants.bl,
+ * const br = &s->quadrants.br;
+
+ if (H5Sclose(ul->src_space) < 0 ||
+ H5Sclose(ur->src_space) < 0 ||
+ H5Sclose(bl->src_space) < 0 ||
+ H5Sclose(br->src_space) < 0)
+ errx(EXIT_FAILURE, "H5Sclose failed");
+
+ ul->src_space = ur->src_space = bl->src_space = br->src_space = badhid;
+
+ if (H5Pclose(s->quadrant_dcpl) < 0)
+ errx(EXIT_FAILURE, "H5Pclose(dcpl)");
+
+ s->quadrant_dcpl = badhid;
+
+ /* TBD destroy spaces belonging to quadrants */
+ }
+
+ for (i = 0; i < NELMTS(s->file); i++) {
+ hid_t fid = s->file[i];
+
+ s->file[i] = badhid;
+
+ if (s->vds != vds_multi && i > 0)
+ continue;
+
+ if (H5Fclose(fid) < 0)
+ errx(EXIT_FAILURE, "H5Fclose");
+ }
+}
+
+static void
+create_extensible_dset(state_t *s, unsigned int which)
+{
+ quadrant_t * const ul = &s->quadrants.ul,
+ * const ur = &s->quadrants.ur,
+ * const bl = &s->quadrants.bl,
+ * const br = &s->quadrants.br,
+ * const src = &s->quadrants.src;
+ char dname[sizeof("/dataset-9999999999")];
+ char ul_dname[sizeof("/ul-dataset-9999999999")],
+ ur_dname[sizeof("/ur-dataset-9999999999")],
+ bl_dname[sizeof("/bl-dataset-9999999999")],
+ br_dname[sizeof("/br-dataset-9999999999")];
+ hid_t dcpl, ds, filespace;
+
+ assert(which < s->ndatasets);
+ assert(s->dataset[which] == badhid);
+
+ esnprintf(dname, sizeof(dname), "/dataset-%d", which);
+
+ if ((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0) {
+ errx(EXIT_FAILURE, "%s.%d: H5Pcreate failed",
+ __func__, __LINE__);
+ }
+
+ if (H5Pset_chunk(dcpl, RANK, s->chunk_dims) < 0)
+ errx(EXIT_FAILURE, "H5Pset_chunk failed");
+
+ if (s->vds != vds_off) {
+ sources_t * const srcs = &s->sources[which];
+
+ esnprintf(ul_dname, sizeof(ul_dname), "/ul-dataset-%d", which);
+ esnprintf(ur_dname, sizeof(ur_dname), "/ur-dataset-%d", which);
+ esnprintf(bl_dname, sizeof(bl_dname), "/bl-dataset-%d", which);
+ esnprintf(br_dname, sizeof(br_dname), "/br-dataset-%d", which);
+
+ srcs->ul = H5Dcreate2(s->file[0], ul_dname, s->filetype, ul->src_space,
+ H5P_DEFAULT, s->quadrant_dcpl, s->dapl);
+
+ if (srcs->ul < 0)
+ errx(EXIT_FAILURE, "H5Dcreate(, \"%s\", ) failed", ul_dname);
+
+ srcs->ur = H5Dcreate2(s->file[1], ur_dname, s->filetype, ur->src_space,
+ H5P_DEFAULT, s->quadrant_dcpl, s->dapl);
+
+ if (srcs->ur < 0)
+ errx(EXIT_FAILURE, "H5Dcreate(, \"%s\", ) failed", ur_dname);
+
+ srcs->bl = H5Dcreate2(s->file[2], bl_dname, s->filetype, bl->src_space,
+ H5P_DEFAULT, s->quadrant_dcpl, s->dapl);
+
+ if (srcs->bl < 0)
+ errx(EXIT_FAILURE, "H5Dcreate(, \"%s\", ) failed", bl_dname);
+
+ srcs->br = H5Dcreate2(s->file[3], br_dname, s->filetype, br->src_space,
+ H5P_DEFAULT, s->quadrant_dcpl, s->dapl);
+
+ if (srcs->br < 0)
+ errx(EXIT_FAILURE, "H5Dcreate(, \"%s\", ) failed", br_dname);
+
+ if (H5Pset_virtual(dcpl, ul->space, s->filename[0], ul_dname,
+ src->space) < 0)
+ errx(EXIT_FAILURE, "%s: H5Pset_virtual failed", __func__);
+
+ if (H5Pset_virtual(dcpl, ur->space, s->filename[1], ur_dname,
+ src->space) < 0)
+ errx(EXIT_FAILURE, "%s: H5Pset_virtual failed", __func__);
+
+ if (H5Pset_virtual(dcpl, bl->space, s->filename[2], bl_dname,
+ src->space) < 0)
+ errx(EXIT_FAILURE, "%s: H5Pset_virtual failed", __func__);
+
+ if (H5Pset_virtual(dcpl, br->space, s->filename[3], br_dname,
+ src->space) < 0)
+ errx(EXIT_FAILURE, "%s: H5Pset_virtual failed", __func__);
+ }
+
+ filespace = H5Screate_simple(NELMTS(s->chunk_dims), s->chunk_dims,
+ s->two_dee ? two_dee_max_dims : s->one_dee_max_dims);
+
+ if (filespace < 0) {
+ errx(EXIT_FAILURE, "%s.%d: H5Screate_simple failed",
+ __func__, __LINE__);
+ }
+
+ ds = H5Dcreate2(s->file[0], dname, s->filetype, filespace,
+ H5P_DEFAULT, dcpl, s->dapl);
+
+ if (ds < 0)
+ errx(EXIT_FAILURE, "H5Dcreate(, \"%s\", ) failed", dname);
+
+ if (H5Sclose(filespace) < 0)
+ errx(EXIT_FAILURE, "%s: H5Sclose failed", __func__);
+
+ if (H5Pclose(dcpl) < 0)
+ errx(EXIT_FAILURE, "%s: H5Pclose failed", __func__);
+
+ s->dataset[which] = ds;
+}
+
+static void
+close_extensible_dset(state_t *s, unsigned int which)
+{
+ char dname[sizeof("/dataset-9999999999")];
+ hid_t ds;
+
+ assert(which < s->ndatasets);
+
+ esnprintf(dname, sizeof(dname), "/dataset-%d", which);
+
+ ds = s->dataset[which];
+
+ if (H5Dclose(ds) < 0)
+ errx(EXIT_FAILURE, "H5Dclose failed for \"%s\"", dname);
+
+ s->dataset[which] = badhid;
+
+ if (s->vds != vds_off && s->writer) {
+ sources_t * const srcs = &s->sources[which];
+
+ if (H5Dclose(srcs->ul) < 0 || H5Dclose(srcs->ur) < 0 ||
+ H5Dclose(srcs->bl) < 0 || H5Dclose(srcs->br) < 0)
+ errx(EXIT_FAILURE, "H5Dclose failed");
+
+ srcs->ul = srcs->ur = srcs->bl = srcs->br = badhid;
+ }
+}
+
+static void
+open_extensible_dset(state_t *s, unsigned int which)
+{
+ hsize_t dims[RANK], maxdims[RANK];
+ char dname[sizeof("/dataset-9999999999")];
+ hid_t ds, filespace, ty;
+
+ assert(which < s->ndatasets);
+ assert(s->dataset[which] == badhid);
+
+ esnprintf(dname, sizeof(dname), "/dataset-%d", which);
+
+ ds = H5Dopen(s->file[0], dname, s->dapl);
+
+ if (ds < 0)
+ errx(EXIT_FAILURE, "H5Dopen(, \"%s\", ) failed", dname);
+
+ if ((ty = H5Dget_type(ds)) < 0)
+ errx(EXIT_FAILURE, "H5Dget_type failed");
+
+ if (H5Tequal(ty, s->filetype) <= 0)
+ errx(EXIT_FAILURE, "Unexpected data type");
+
+ if ((filespace = H5Dget_space(ds)) < 0)
+ errx(EXIT_FAILURE, "H5Dget_space failed");
+
+ if (H5Sget_simple_extent_ndims(filespace) != RANK)
+ errx(EXIT_FAILURE, "Unexpected rank");
+
+ if (H5Sget_simple_extent_dims(filespace, dims, maxdims) < 0)
+ errx(EXIT_FAILURE, "H5Sget_simple_extent_dims failed");
+
+ if (H5Sclose(filespace) < 0)
+ errx(EXIT_FAILURE, "H5Sclose failed");
+
+ filespace = badhid;
+
+ if (s->two_dee) {
+ if (maxdims[0] != two_dee_max_dims[0] ||
+ maxdims[1] != two_dee_max_dims[1] ||
+ maxdims[0] != maxdims[1]) {
+ errx(EXIT_FAILURE, "Unexpected maximum dimensions %"
+ PRIuHSIZE " x %" PRIuHSIZE, maxdims[0], maxdims[1]);
+ }
+ } else if (maxdims[0] != s->one_dee_max_dims[0] ||
+ maxdims[1] != s->one_dee_max_dims[1] ||
+ dims[0] != s->chunk_dims[0]) {
+ errx(EXIT_FAILURE, "Unexpected maximum dimensions %"
+ PRIuHSIZE " x %" PRIuHSIZE " or columns %" PRIuHSIZE,
+ maxdims[0], maxdims[1], dims[1]);
+ }
+
+ s->dataset[which] = ds;
+}
+
+static void
+set_or_verify_matrix(mat_t *mat, unsigned int which, base_t base, bool do_set)
+{
+ unsigned row, col;
+
+ for (row = 0; row < mat->rows; row++) {
+ for (col = 0; col < mat->cols; col++) {
+ uint32_t v;
+ hsize_t i = base.row + row,
+ j = base.col + col,
+ u;
+
+ if (j <= i)
+ u = (i + 1) * (i + 1) - 1 - j;
+ else
+ u = j * j + i;
+
+ assert(UINT32_MAX - u >= which);
+ v = (uint32_t)(u + which);
+ if (do_set)
+ matset(mat, row, col, v);
+ else if (matget(mat, row, col) != v) {
+ errx(EXIT_FAILURE, "matrix mismatch "
+ "at %" PRIuHSIZE ", %" PRIuHSIZE " (%u, %u), "
+ "read %" PRIu32 " expecting %" PRIu32,
+ i, j, row, col, matget(mat, row, col), v);
+ }
+ }
+ }
+}
+
+static void
+init_matrix(mat_t *mat, unsigned int which, base_t base)
+{
+ set_or_verify_matrix(mat, which, base, true);
+}
+
+static void
+verify_matrix(mat_t *mat, unsigned int which, base_t base)
+{
+ set_or_verify_matrix(mat, which, base, false);
+}
+
+static void
+verify_chunk(state_t *s, hid_t filespace,
+ mat_t *mat, unsigned which, base_t base)
+{
+ hsize_t offset[RANK] = {base.row, base.col};
+ herr_t status;
+ hid_t ds;
+
+ assert(which < s->ndatasets);
+
+ dbgf(1, "verifying chunk %" PRIuHSIZE ", %" PRIuHSIZE "\n",
+ base.row, base.col);
+
+ ds = s->dataset[which];
+
+ status = H5Sselect_hyperslab(filespace, H5S_SELECT_SET, offset,
+ NULL, s->chunk_dims, NULL);
+
+ if (status < 0)
+ errx(EXIT_FAILURE, "H5Sselect_hyperslab failed");
+
+ status = H5Dread(ds, H5T_NATIVE_UINT32, s->memspace, filespace,
+ H5P_DEFAULT, mat->elt);
+
+ if (status < 0)
+ errx(EXIT_FAILURE, "H5Dread failed");
+
+ verify_matrix(mat, which, base);
+}
+
+static void
+init_and_write_chunk(state_t *s, hid_t filespace,
+ mat_t *mat, unsigned which, base_t base)
+{
+ hsize_t offset[RANK] = {base.row, base.col};
+ herr_t status;
+ hid_t ds;
+
+ assert(which < s->ndatasets);
+
+ ds = s->dataset[which];
+
+ init_matrix(mat, which, base);
+
+ status = H5Sselect_hyperslab(filespace, H5S_SELECT_SET, offset,
+ NULL, s->chunk_dims, NULL);
+
+ if (status < 0)
+ errx(EXIT_FAILURE, "H5Sselect_hyperslab failed");
+
+ status = H5Dwrite(ds, H5T_NATIVE_UINT32, s->memspace, filespace,
+ H5P_DEFAULT, mat->elt);
+
+ if (status < 0)
+ errx(EXIT_FAILURE, "H5Dwrite failed");
+}
+
+static void
+verify_dset_attribute(hid_t ds, unsigned int which, unsigned int step)
+{
+ unsigned int read_step;
+ hid_t aid;
+ char name[sizeof("attr-9999999999")];
+
+ esnprintf(name, sizeof(name), "attr-%u", step);
+
+ dbgf(1, "verifying attribute %s on dataset %u equals %u\n", name, which,
+ step);
+
+ if ((aid = H5Aopen(ds, name, H5P_DEFAULT)) < 0)
+ errx(EXIT_FAILURE, "H5Aopen failed");
+
+ if (H5Aread(aid, H5T_NATIVE_UINT, &read_step) < 0)
+ errx(EXIT_FAILURE, "H5Aread failed");
+
+ if (H5Aclose(aid) < 0)
+ errx(EXIT_FAILURE, "H5Aclose failed");
+
+ if (read_step != step)
+ errx(EXIT_FAILURE, "expected %u read %u", step, read_step);
+}
+
+static void
+verify_extensible_dset(state_t *s, unsigned int which, mat_t *mat,
+ unsigned *stepp)
+{
+ hid_t ds, filespace;
+ hsize_t size[RANK];
+ base_t base, last;
+ unsigned int ncols, last_step, step;
+
+ assert(which < s->ndatasets);
+
+ ds = s->dataset[which];
+
+ if (H5Drefresh(ds) < 0)
+ errx(EXIT_FAILURE, "H5Drefresh failed");
+
+ filespace = H5Dget_space(ds);
+
+ if (filespace == badhid)
+ errx(EXIT_FAILURE, "H5Dget_space failed");
+
+ if (H5Sget_simple_extent_dims(filespace, size, NULL) < 0)
+ errx(EXIT_FAILURE, "H5Sget_simple_extent_dims failed");
+
+ ncols = (unsigned)(size[1] / s->chunk_dims[1]);
+ if (ncols < hang_back)
+ goto out;
+
+ last_step = ncols - hang_back;
+
+ for (step = *stepp; step <= last_step; step++) {
+ const unsigned ofs = step % 2;
+
+ dbgf(1, "%s: which %u step %u\n", __func__, which, step);
+
+ if (s->two_dee) {
+ size[0] = s->chunk_dims[0] * (1 + step);
+ size[1] = s->chunk_dims[1] * (1 + step);
+ last.row = s->chunk_dims[0] * step + ofs;
+ last.col = s->chunk_dims[1] * step + ofs;
+ } else {
+ size[0] = s->chunk_dims[0];
+ size[1] = s->chunk_dims[1] * (1 + step);
+ last.row = 0;
+ last.col = s->chunk_dims[1] * step + ofs;
+ }
+
+ dbgf(1, "new size %" PRIuHSIZE ", %" PRIuHSIZE "\n", size[0], size[1]);
+ dbgf(1, "last row %" PRIuHSIZE " col %" PRIuHSIZE "\n", last.row,
+ last.col);
+
+ if (s->two_dee) {
+
+ /* Down the right side, intersecting the bottom row. */
+ base.col = last.col;
+ for (base.row = ofs; base.row <= last.row;
+ base.row += s->chunk_dims[0]) {
+ verify_chunk(s, filespace, mat, which, base);
+ }
+
+ /* Across the bottom, stopping before the last column to
+ * avoid re-writing the bottom-right chunk.
+ */
+ base.row = last.row;
+ for (base.col = ofs; base.col < last.col;
+ base.col += s->chunk_dims[1]) {
+ verify_chunk(s, filespace, mat, which, base);
+ }
+ } else {
+ verify_chunk(s, filespace, mat, which, last);
+ }
+ if (s->asteps != 0 && step % s->asteps == 0)
+ verify_dset_attribute(ds, which, step);
+ }
+
+ *stepp = last_step;
+
+out:
+ if (H5Sclose(filespace) < 0)
+ errx(EXIT_FAILURE, "H5Sclose failed");
+}
+
+static void
+add_dset_attribute(const state_t *s, hid_t ds, hid_t sid, unsigned int which,
+ unsigned int step)
+{
+ hid_t aid;
+ char name[sizeof("attr-9999999999")];
+
+ esnprintf(name, sizeof(name), "attr-%u", step);
+
+ dbgf(1, "setting attribute %s on dataset %u to %u\n", name, which, step);
+
+ if ((aid = H5Acreate2(ds, name, s->filetype, sid, H5P_DEFAULT,
+ H5P_DEFAULT)) < 0)
+ errx(EXIT_FAILURE, "H5Acreate2 failed");
+
+ if (H5Awrite(aid, H5T_NATIVE_UINT, &step) < 0)
+ errx(EXIT_FAILURE, "H5Awrite failed");
+ if (H5Aclose(aid) < 0)
+ errx(EXIT_FAILURE, "H5Aclose failed");
+}
+
+static void
+write_extensible_dset(state_t *s, unsigned int which, unsigned int step,
+ mat_t *mat)
+{
+ hid_t ds, filespace;
+ hsize_t size[RANK];
+ base_t base, last;
+
+ dbgf(1, "%s: which %u step %u\n", __func__, which, step);
+
+ assert(which < s->ndatasets);
+
+ ds = s->dataset[which];
+
+ if (s->asteps != 0 && step % s->asteps == 0)
+ add_dset_attribute(s, ds, s->one_by_one_sid, which, step);
+
+ if (s->two_dee) {
+ size[0] = s->chunk_dims[0] * (1 + step);
+ size[1] = s->chunk_dims[1] * (1 + step);
+ last.row = s->chunk_dims[0] * step;
+ last.col = s->chunk_dims[1] * step;
+ } else {
+ size[0] = s->chunk_dims[0];
+ size[1] = s->chunk_dims[1] * (1 + step);
+ last.row = 0;
+ last.col = s->chunk_dims[1] * step;
+ }
+
+ dbgf(1, "new size %" PRIuHSIZE ", %" PRIuHSIZE "\n", size[0], size[1]);
+
+ if (s->vds != vds_off) {
+ const hsize_t half_size[RANK] = {size[0] / 2, size[1] / 2};
+ sources_t * const srcs = &s->sources[which];
+
+ if (H5Dset_extent(srcs->ul, half_size) < 0) {
+ errx(EXIT_FAILURE, "%s.%d: H5Dset_extent failed",
+ __func__, __LINE__);
+ }
+ if (H5Dset_extent(srcs->ur, half_size) < 0) {
+ errx(EXIT_FAILURE, "%s.%d: H5Dset_extent failed",
+ __func__, __LINE__);
+ }
+ if (H5Dset_extent(srcs->bl, half_size) < 0) {
+ errx(EXIT_FAILURE, "%s.%d: H5Dset_extent failed",
+ __func__, __LINE__);
+ }
+ if (H5Dset_extent(srcs->br, half_size) < 0) {
+ errx(EXIT_FAILURE, "%s.%d: H5Dset_extent failed",
+ __func__, __LINE__);
+ }
+
+ } else if (H5Dset_extent(ds, size) < 0)
+ errx(EXIT_FAILURE, "H5Dset_extent failed");
+
+ filespace = H5Dget_space(ds);
+
+ if (filespace == badhid)
+ errx(EXIT_FAILURE, "H5Dget_space failed");
+
+ if (s->two_dee) {
+ base.col = last.col;
+ for (base.row = 0; base.row <= last.row; base.row += s->chunk_dims[0]) {
+ dbgf(1, "writing chunk %" PRIuHSIZE ", %" PRIuHSIZE "\n",
+ base.row, base.col);
+ init_and_write_chunk(s, filespace, mat, which, base);
+ }
+
+ base.row = last.row;
+ for (base.col = 0; base.col < last.col; base.col += s->chunk_dims[1]) {
+ dbgf(1, "writing chunk %" PRIuHSIZE ", %" PRIuHSIZE "\n",
+ base.row, base.col);
+ init_and_write_chunk(s, filespace, mat, which, base);
+ }
+ } else {
+ init_and_write_chunk(s, filespace, mat, which, last);
+ }
+
+ if (H5Sclose(filespace) < 0)
+ errx(EXIT_FAILURE, "H5Sclose failed");
+}
+
+int
+main(int argc, char **argv)
+{
+ mat_t *mat;
+ hid_t fcpl;
+ sigset_t oldsigs;
+ herr_t ret;
+ unsigned step, which;
+ state_t s;
+ size_t i;
+
+ state_init(&s, argc, argv);
+
+ if ((mat = newmat(s.rows, s.cols)) == NULL)
+ err(EXIT_FAILURE, "%s: could not allocate matrix", __func__);
+
+ if ((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0)
+ errx(EXIT_FAILURE, "H5Pcreate");
+
+ ret = H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, false, 1);
+ if (ret < 0)
+ errx(EXIT_FAILURE, "H5Pset_file_space_strategy");
+
+ for (i = 0; i < NELMTS(s.file); i++) {
+ hid_t fapl;
+
+ if (s.vds != vds_multi && i > 0) {
+ s.file[i] = s.file[0];
+ continue;
+ }
+
+ fapl = vfd_swmr_create_fapl(s.writer, true, s.use_vfd_swmr,
+ "./metadata-%zu", i);
+
+ if (fapl < 0)
+ errx(EXIT_FAILURE, "vfd_swmr_create_fapl");
+
+ s.file[i] =
+ s.writer ? H5Fcreate(s.filename[i], H5F_ACC_TRUNC, fcpl, fapl)
+ : H5Fopen(s.filename[i], H5F_ACC_RDONLY, fapl);
+
+ if (s.file[i] == badhid)
+ errx(EXIT_FAILURE, s.writer ? "H5Fcreate" : "H5Fopen");
+
+ if (H5Pclose(fapl) < 0)
+ errx(EXIT_FAILURE, "H5Pclose(fapl)");
+ }
+
+ block_signals(&oldsigs);
+
+ if (s.writer) {
+ for (which = 0; which < s.ndatasets; which++)
+ create_extensible_dset(&s, which);
+
+ for (step = 0; step < s.nsteps; step++) {
+ for (which = 0; which < s.ndatasets; which++) {
+ dbgf(2, "step %d which %d\n", step, which);
+ write_extensible_dset(&s, which, step, mat);
+ if (s.ndatasets <= s.nsteps)
+ nanosleep(&s.update_interval, NULL);
+ }
+ if (s.ndatasets > s.nsteps)
+ nanosleep(&s.update_interval, NULL);
+ }
+ } else {
+ for (which = 0; which < s.ndatasets; which++)
+ open_extensible_dset(&s, which);
+
+ for (step = 0; hang_back + step < s.nsteps;) {
+ for (which = s.ndatasets; which-- > 0; ) {
+ dbgf(2, "step %d which %d\n", step, which);
+ verify_extensible_dset(&s, which, mat, &step);
+ if (s.ndatasets <= s.nsteps)
+ nanosleep(&s.update_interval, NULL);
+ }
+ if (s.ndatasets > s.nsteps)
+ nanosleep(&s.update_interval, NULL);
+ }
+ }
+
+ for (which = 0; which < s.ndatasets; which++)
+ close_extensible_dset(&s, which);
+
+ if (s.use_vfd_swmr && s.wait_for_signal)
+ await_signal(s.file[0]);
+
+ restore_signals(&oldsigs);
+
+ if (H5Pclose(fcpl) < 0)
+ errx(EXIT_FAILURE, "H5Pclose(fcpl)");
+
+ state_destroy(&s);
+
+ free(mat);
+
+ return EXIT_SUCCESS;
+}
diff --git a/test/vfd_swmr_common.c b/test/vfd_swmr_common.c
new file mode 100644
index 0000000..e4f4889
--- /dev/null
+++ b/test/vfd_swmr_common.c
@@ -0,0 +1,262 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: swmr_common.c
+ *
+ * Purpose: Utility functions for the SWMR test code.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/***********/
+/* Headers */
+/***********/
+
+#include <err.h> /* for err(3) */
+
+#include "h5test.h"
+#include "vfd_swmr_common.h"
+
+static const hid_t badhid = H5I_INVALID_HID;
+
+int verbosity = 2;
+
+void
+evsnprintf(char *buf, size_t bufsz, const char *fmt, va_list ap)
+{
+ int rc;
+
+ rc = vsnprintf(buf, bufsz, fmt, ap);
+
+ if (rc < 0)
+ err(EXIT_FAILURE, "%s: vsnprintf", __func__);
+ else if ((size_t)rc >= bufsz)
+ errx(EXIT_FAILURE, "%s: buffer too small", __func__);
+}
+
+void
+esnprintf(char *buf, size_t bufsz, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ evsnprintf(buf, bufsz, fmt, ap);
+ va_end(ap);
+}
+
+void
+dbgf(int level, const char *fmt, ...)
+{
+ va_list ap;
+
+ if (verbosity < level)
+ return;
+
+ va_start(ap, fmt);
+ (void)vfprintf(stderr, fmt, ap);
+ va_end(ap);
+}
+
+estack_state_t
+disable_estack(void)
+{
+ estack_state_t es = estack_get_state();
+
+ (void)H5Eset_auto(H5E_DEFAULT, NULL, NULL);
+
+ return es;
+}
+
+estack_state_t
+estack_get_state(void)
+{
+ estack_state_t es;
+
+ (void)H5Eget_auto(H5E_DEFAULT, &es.efunc, &es.edata);
+
+ return es;
+}
+
+void
+restore_estack(estack_state_t es)
+{
+ (void)H5Eset_auto(H5E_DEFAULT, es.efunc, es.edata);
+}
+
+void
+block_signals(sigset_t *oldset)
+{
+ sigset_t fullset;
+
+ if (sigfillset(&fullset) == -1) {
+ err(EXIT_FAILURE, "%s.%d: could not initialize signal masks",
+ __func__, __LINE__);
+ }
+
+ if (sigprocmask(SIG_BLOCK, &fullset, oldset) == -1)
+ err(EXIT_FAILURE, "%s.%d: sigprocmask", __func__, __LINE__);
+}
+
+void
+restore_signals(sigset_t *oldset)
+{
+ if (sigprocmask(SIG_SETMASK, oldset, NULL) == -1)
+ err(EXIT_FAILURE, "%s.%d: sigprocmask", __func__, __LINE__);
+}
+
+#if 0
+static const char *
+strsignal(int signum)
+{
+ switch (signum) {
+ case SIGUSR1:
+ return "SIGUSR1";
+ case SIGINT:
+ return "SIGINT";
+ case SIGPIPE:
+ return "SIGPIPE";
+ default:
+ return "<unknown>";
+ }
+}
+#endif
+
+void
+await_signal(hid_t fid)
+{
+ sigset_t sleepset;
+ struct timespec tick = {.tv_sec = 0, .tv_nsec = 1000000000 / 100};
+
+ if (sigfillset(&sleepset) == -1) {
+ err(EXIT_FAILURE, "%s.%d: could not initialize signal mask",
+ __func__, __LINE__);
+ }
+
+ /* Avoid deadlock: flush the file before waiting for the reader's
+ * message.
+ */
+ if (H5Fflush(fid, H5F_SCOPE_GLOBAL) < 0)
+ errx(EXIT_FAILURE, "%s: H5Fflush failed", __func__);
+
+ dbgf(1, "waiting for signal\n");
+
+ for (;;) {
+ const int rc = sigtimedwait(&sleepset, NULL, &tick);
+
+ if (rc != -1) {
+ fprintf(stderr, "Received %s, wrapping things up.\n",
+ strsignal(rc));
+ break;
+ } else if (rc == -1 && errno == EAGAIN) {
+ estack_state_t es;
+
+ /* Avoid deadlock with peer: periodically enter the API so that
+ * tick processing occurs and data is flushed so that the peer
+ * can see it.
+ *
+ * The call we make will fail, but that's ok,
+ * so squelch errors.
+ */
+ es = disable_estack();
+ (void)H5Aexists_by_name(fid, "nonexistent", "nonexistent",
+ H5P_DEFAULT);
+ restore_estack(es);
+ } else if (rc == -1)
+ err(EXIT_FAILURE, "%s: sigtimedwait", __func__);
+ }
+}
+
+hid_t
+vfd_swmr_create_fapl(bool writer, bool only_meta_pages, bool use_vfd_swmr,
+ const char *mdfile_fmtstr, ...)
+{
+ H5F_vfd_swmr_config_t config;
+ hid_t fapl;
+ va_list ap;
+
+ /* Create file access property list */
+ if((fapl = h5_fileaccess()) < 0) {
+ warnx("h5_fileaccess");
+ return badhid;
+ }
+
+ /* FOR NOW: set to use latest format, the "old" parameter is not used */
+ if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) {
+ warnx("H5Pset_libver_bounds");
+ return badhid;
+ }
+
+ /*
+ * Set up to open the file with VFD SWMR configured.
+ */
+
+ /* Enable page buffering */
+ if(H5Pset_page_buffer_size(fapl, 4096, only_meta_pages ? 100 : 0, 0) < 0) {
+ warnx("H5Pset_page_buffer_size");
+ return badhid;
+ }
+
+ memset(&config, 0, sizeof(config));
+
+ config.version = H5F__CURR_VFD_SWMR_CONFIG_VERSION;
+ config.tick_len = 4;
+ config.max_lag = 7;
+ config.writer = writer;
+ config.md_pages_reserved = 128;
+ va_start(ap, mdfile_fmtstr);
+ evsnprintf(config.md_file_path, sizeof(config.md_file_path),
+ mdfile_fmtstr, ap);
+ va_end(ap);
+
+ /* Enable VFD SWMR configuration */
+ if(use_vfd_swmr && H5Pset_vfd_swmr_config(fapl, &config) < 0) {
+ warnx("H5Pset_vfd_swmr_config");
+ return badhid;
+ }
+ return fapl;
+}
+
+/* Fetch a variable from the environment and parse it for unsigned long
+ * content. Return 0 if the variable is not present, -1 if it is present
+ * but it does not parse and compare less than `limit`, 1 if it's present,
+ * parses, and is in-bounds.
+ */
+int
+fetch_env_ulong(const char *varname, unsigned long limit, unsigned long *valp)
+{
+ char *end;
+ unsigned long ul;
+ char *tmp;
+
+ if ((tmp = getenv(varname)) == NULL)
+ return 0;
+
+ errno = 0;
+ ul = strtoul(tmp, &end, 0);
+ if (ul == ULONG_MAX && errno != 0) {
+ fprintf(stderr, "could not parse %s: %s\n", varname, strerror(errno));
+ return -1;
+ }
+ if (end == tmp || *end != '\0') {
+ fprintf(stderr, "could not parse %s\n", varname);
+ return -1;
+ }
+ if (ul > limit) {
+ fprintf(stderr, "%s (%lu) out of range\n", varname, ul);
+ return -1;
+ }
+ *valp = ul;
+ return 1;
+}
diff --git a/test/vfd_swmr_common.h b/test/vfd_swmr_common.h
new file mode 100644
index 0000000..8e1f877
--- /dev/null
+++ b/test/vfd_swmr_common.h
@@ -0,0 +1,114 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#ifndef _VFD_SWMR_COMMON_H
+#define _VFD_SWMR_COMMON_H
+
+/***********/
+/* Headers */
+/***********/
+
+#include <stdarg.h>
+#include "h5test.h"
+
+/**********/
+/* Macros */
+/**********/
+
+/* The maximum # of records to add/remove from the dataset in one step,
+ * used by vfd_swmr_addrem_writer and vfd_swmr_remove_reader.
+ */
+#define MAX_SIZE_CHANGE 10
+
+#define NLEVELS 5 /* # of datasets in the SWMR test file */
+
+#define NMAPPING 9
+
+#define COMMON_FILENAME "vfd_swmr_data.h5" /* SWMR test file name */
+#define DTYPE_SIZE 150 /* Data size in opaque type */
+
+/* The message sent by writer that the file open is done--releasing the file lock */
+#define WRITER_MESSAGE "VFD_SWMR_WRITER_MESSAGE"
+
+/************/
+/* Typedefs */
+/************/
+
+typedef struct _estack_state {
+ H5E_auto_t efunc;
+ void *edata;
+} estack_state_t;
+
+/* Information about a symbol/dataset */
+typedef struct {
+ char *name; /* Dataset name for symbol */
+ hid_t dsid; /* Dataset ID for symbol */
+ hsize_t nrecords; /* Number of records for the symbol */
+} symbol_info_t;
+
+/* A symbol's record */
+typedef struct {
+ uint64_t rec_id; /* ID for this record (unique in symbol) */
+ uint8_t info[DTYPE_SIZE]; /* "Other" information for this record */
+} symbol_t;
+
+typedef enum _testsel {
+ TEST_NONE = 0
+, TEST_NULL
+, TEST_OOB
+} testsel_t;
+
+/********************/
+/* Global Variables */
+/********************/
+H5TEST_DLLVAR symbol_info_t *symbol_info[NLEVELS];
+H5TEST_DLLVAR unsigned symbol_count[NLEVELS];
+
+/**************/
+/* Prototypes */
+/**************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+H5TEST_DLL estack_state_t estack_get_state(void);
+H5TEST_DLL estack_state_t disable_estack(void);
+H5TEST_DLL void restore_estack(estack_state_t);
+
+H5TEST_DLL symbol_info_t * choose_dataset(unsigned *, unsigned *);
+H5TEST_DLL hid_t create_symbol_datatype(void);
+H5TEST_DLL int generate_name(char *name_buf, unsigned level, unsigned count);
+H5TEST_DLL int generate_symbols(void);
+H5TEST_DLL int shutdown_symbols(void);
+H5TEST_DLL int print_metadata_retries_info(hid_t fid);
+
+H5TEST_DLL void block_signals(sigset_t *);
+H5TEST_DLL void restore_signals(sigset_t *);
+H5TEST_DLL void await_signal(hid_t);
+H5TEST_DLL hid_t vfd_swmr_create_fapl(bool, bool, bool, const char *, ...)
+ H5_ATTR_FORMAT(printf, 4, 5);
+
+H5TEST_DLL void dbgf(int, const char *, ...) H5_ATTR_FORMAT(printf, 2, 3);
+H5TEST_DLL void evsnprintf(char *, size_t, const char *, va_list);
+H5TEST_DLL void esnprintf(char *, size_t, const char *, ...)
+ H5_ATTR_FORMAT(printf, 3, 4);
+
+H5TEST_DLL int fetch_env_ulong(const char *, unsigned long, unsigned long *);
+
+#ifdef __cplusplus
+}
+#endif
+
+extern int verbosity;
+
+#endif /* _SWMR_COMMON_H */
diff --git a/test/vfd_swmr_generator.c b/test/vfd_swmr_generator.c
new file mode 100644
index 0000000..13fc941
--- /dev/null
+++ b/test/vfd_swmr_generator.c
@@ -0,0 +1,399 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: vfd_swmr_generator.c
+ * (copied and modified from swmr_generator.c)
+ *
+ * Purpose: Functions for building and setting up the VFD SWMR test file
+ * and datasets.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/***********/
+/* Headers */
+/***********/
+
+#include "h5test.h"
+#include "vfd_swmr_common.h"
+
+/*
+ * This file needs to access testing codefrom the H5O package.
+ */
+#define H5O_FRIEND /*suppress error about including H5Opkg */
+#define H5O_TESTING
+#include "H5Opkg.h" /* Object headers */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+#define CHUNK_SIZE 50 /* Chunk size for created datasets */
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+static int gen_skeleton(const char *filename, hbool_t verbose,
+ hbool_t vfd_swmr_write, int comp_level, const char *index_type,
+ unsigned random_seed);
+static void usage(void);
+
+
+/*-------------------------------------------------------------------------
+ * Function: gen_skeleton
+ *
+ * Purpose: Creates the HDF5 file and datasets which will be used in
+ * the SWMR testing.
+ *
+ * Parameters: const char *filename
+ * The SWMR test file's name.
+ *
+ * hbool_t verbose
+ * Whether verbose console output is desired.
+ *
+ * hbool_t vfd_swmr_write
+ * Whether to create the file with VFD SWMR writing enabled
+ *
+ * int comp_level
+ * The zlib compression level to use. -1 = no compression.
+ *
+ * const char *index_type
+ * The chunk index type (b1 | b2 | ea | fa)
+ *
+ * unsigned random_seed
+ * The random seed to store in the file. The sparse tests use
+ * this value.
+ *
+ * Return: Success: 0
+ * Failure: Can't fail
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+gen_skeleton(const char *filename, hbool_t verbose, hbool_t vfd_swmr_write,
+ int comp_level, const char *index_type, unsigned random_seed)
+{
+ hid_t fid; /* File ID for new HDF5 file */
+ hid_t fcpl; /* File creation property list */
+ hid_t fapl; /* File access property list */
+ hid_t dcpl; /* Dataset creation property list */
+ hid_t tid; /* Datatype for dataset elements */
+ hid_t sid; /* Dataspace ID */
+ hid_t aid; /* Attribute ID */
+ hsize_t dims[2] = {1, 0}; /* Dataset starting dimensions */
+ hsize_t max_dims[2] = {1, H5S_UNLIMITED}; /* Dataset maximum dimensions */
+ hsize_t chunk_dims[2] = {1, CHUNK_SIZE}; /* Chunk dimensions */
+#ifdef FILLVAL_WORKS
+ symbol_t fillval; /* Dataset fill value */
+#endif /* FILLVAL_WORKS */
+ unsigned u, v; /* Local index variable */
+ H5F_vfd_swmr_config_t *config = NULL; /* Configuration for VFD SWMR */
+
+ HDassert(filename);
+ HDassert(index_type);
+
+ /* Create file access property list */
+ if((fapl = h5_fileaccess()) < 0)
+ return -1;
+
+ /* Set to use the latest format with the latest chunk indexing */
+ /* FOR NOW: the parameter vfd_swmr_write is not used here as in swmr_generator.c */
+ if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
+ return -1;
+
+ /* There are two chunk indexes tested here.
+ * With one unlimited dimension, we get the extensible array index
+ * type, with two unlimited dimensions, we get a v2 B-tree.
+ */
+ if(!HDstrcmp(index_type, "b2"))
+ max_dims[0] = H5S_UNLIMITED;
+
+ /* Create file creation property list */
+ if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0)
+ return -1;
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "Creating file\n");
+
+ /*
+ * Set up to create the file with VFD SWMR write configured.
+ */
+
+ if(vfd_swmr_write) {
+ /* Set file space strategy to paged aggregation in fcpl */
+ if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, FALSE, 1) < 0)
+ return -1;
+
+ /* Enable page buffering in fapl */
+ if(H5Pset_page_buffer_size(fapl, 4096, 0, 0) < 0)
+ return -1;
+
+ /* Allocate memory for the VFD SWMR configuration structure */
+ if((config = (H5F_vfd_swmr_config_t *)HDcalloc(1, sizeof(H5F_vfd_swmr_config_t))) == NULL)
+ return -1;
+
+ config->version = H5F__CURR_VFD_SWMR_CONFIG_VERSION;
+ config->tick_len = 4;
+ config->max_lag = 10;
+ config->writer = TRUE;
+ config->md_pages_reserved = 128;
+ HDstrcpy(config->md_file_path, "my_md_file");
+
+ /* Enable VFD SWMR configuration in fapl */
+ if(H5Pset_vfd_swmr_config(fapl, config) < 0)
+ return -1;
+ }
+
+ /* Create the file with VFD SWMR write configured */
+ if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl, fapl)) < 0)
+ return -1;
+
+ /* Close file creation property list */
+ if(H5Pclose(fcpl) < 0)
+ return -1;
+
+ /* Close file access property list */
+ if(H5Pclose(fapl) < 0)
+ return -1;
+
+ /* Create attribute with (shared) random number seed - for sparse test */
+ if((sid = H5Screate(H5S_SCALAR)) < 0)
+ return -1;
+ if((aid = H5Acreate2(fid, "seed", H5T_NATIVE_UINT, sid, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ return -1;
+ if(H5Awrite(aid, H5T_NATIVE_UINT, &random_seed) < 0)
+ return -1;
+ if(H5Aclose(aid) < 0)
+ return -1;
+ if(H5Sclose(sid) < 0)
+ return -1;
+
+ /* Create datatype for creating datasets */
+ if((tid = create_symbol_datatype()) < 0)
+ return -1;
+
+ /* Create dataspace for creating datasets */
+ if((sid = H5Screate_simple(2, dims, max_dims)) < 0)
+ return -1;
+
+ /* Create dataset creation property list */
+ if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)
+ return -1;
+ if(H5Pset_chunk(dcpl, 2, chunk_dims) < 0)
+ return -1;
+ if(comp_level >= 0) {
+ if(H5Pset_deflate(dcpl, (unsigned)comp_level) < 0)
+ return -1;
+ } /* end if */
+#ifdef FILLVAL_WORKS
+ /* Currently fill values do not work because they can bump the dataspace
+ * message to the second object header chunk. We should enable the fillval
+ * here when this is fixed. -NAF 8/11/11 */
+ HDmemset(&fillval, 0, sizeof(fillval));
+ fillval.rec_id = (uint64_t)ULLONG_MAX;
+ if(H5Pset_fill_value(dcpl, tid, &fillval) < 0)
+ return -1;
+#endif /* FILLVAL_WORKS */
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "Creating datasets\n");
+
+#if 0 /* delete this once the race condiditon bug is fixed */ /* JRM */
+ sleep(1);
+#endif /* JRM */
+
+ /* Create the datasets */
+ for(u = 0; u < NLEVELS; u++)
+ for(v = 0; v < symbol_count[u]; v++) {
+ hid_t dsid; /* Dataset ID */
+ char name_buf[64];
+ hbool_t move_dataspace_message = FALSE; /* Whether to move the dataspace message out of object header chunk #0 */
+
+ generate_name(name_buf, u, v);
+ if((dsid = H5Dcreate2(fid, name_buf, tid, sid, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0)
+ return -1;
+
+ /* Determine if the dataspace message for this dataset should be
+ * moved out of chunk #0 of the object header
+ * (Set to TRUE for every fourth dataset)
+ */
+ move_dataspace_message = !(HDrandom() % 4);
+ if(move_dataspace_message) {
+ unsigned chunk_num; /* Object header chunk # for dataspace message */
+
+ /* Move the dataspace message to a new object header chunk */
+ if(H5O__msg_move_to_new_chunk_test(dsid, H5O_SDSPACE_ID) < 0)
+ return -1;
+
+ /* Retrieve the chunk # for the dataspace message */
+ chunk_num = UINT_MAX;
+ if(H5O__msg_get_chunkno_test(dsid, H5O_SDSPACE_ID, &chunk_num) < 0)
+ return -1;
+ /* Should not be in chunk #0 for now */
+ if(0 == chunk_num)
+ return -1;
+ } /* end if */
+
+ if(H5Dclose(dsid) < 0)
+ return -1;
+ } /* end for */
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "Closing objects\n");
+
+ /* Close everythign */
+ if(H5Pclose(dcpl) < 0)
+ return -1;
+ if(H5Sclose(sid) < 0)
+ return -1;
+ if(H5Tclose(tid) < 0)
+ return -1;
+
+ if(verbose)
+ HDfprintf(stderr, "Closing file\n");
+
+ if(H5Fclose(fid) < 0)
+ return -1;
+
+ /* Free the config structure */
+ if(config)
+ HDfree(config);
+ return 0;
+} /* end gen_skeleton() */
+
+static void
+usage(void)
+{
+ printf("\n");
+ printf("Usage error!\n");
+ printf("\n");
+ printf("Usage: swmr_generator [-q] [-s] [-c <deflate compression level>]\n");
+ printf(" [-i <index type>] [-r <random seed>]\n");
+ printf("\n");
+ printf("NOTE: The random seed option is only used by the sparse test. Other\n");
+ printf(" tests specify the random seed as a reader/writer option.\n");
+ printf("\n");
+ printf("<deflate compression level> should be -1 (for no compression) or 0-9\n");
+ printf("\n");
+ printf("<index type> should be b2 or ea\n");
+ printf("\n");
+ printf("Defaults to verbose (no '-q' given), no VFD_SWMR_WRITE mode (no '-s' given) no\n");
+ printf("compression ('-c -1'), v1 b-tree indexing (-i b1), and will generate a random\n");
+ printf("seed (no -r given).\n");
+ printf("\n");
+ HDexit(1);
+} /* end usage() */
+
+int main(int argc, const char *argv[])
+{
+ int comp_level = -1; /* Compression level (-1 is no compression) */
+ hbool_t verbose = TRUE; /* Whether to emit some informational messages */
+ hbool_t vfd_swmr_write = FALSE; /* Whether to create file with VFD SWMR access */
+ const char *index_type = "b1"; /* Chunk index type */
+ hbool_t use_seed = FALSE; /* Set to TRUE if a seed was set on the command line */
+ unsigned random_seed = 0; /* Random # seed */
+ unsigned u; /* Local index variables */
+ int temp;
+
+ /* Parse command line options */
+ if(argc > 1) {
+ u = 1;
+ while(u < (unsigned)argc) {
+ if(argv[u][0] == '-') {
+ switch(argv[u][1]) {
+ /* Compress dataset chunks */
+ case 'c':
+ comp_level = HDatoi(argv[u + 1]);
+ if(comp_level < -1 || comp_level > 9)
+ usage();
+ u += 2;
+ break;
+
+ /* Chunk index type */
+ case 'i':
+ index_type = argv[u + 1];
+ if(HDstrcmp(index_type, "ea")
+ && HDstrcmp(index_type, "b2"))
+ usage();
+ u += 2;
+ break;
+
+ /* Random # seed */
+ case 'r':
+ use_seed = TRUE;
+ temp = HDatoi(argv[u + 1]);
+ if(temp < 0)
+ usage();
+ else
+ random_seed = (unsigned)temp;
+ u += 2;
+ break;
+
+ /* Be quiet */
+ case 'q':
+ verbose = FALSE;
+ u++;
+ break;
+
+ /* Run with SWMR_WRITE */
+ case 's':
+ vfd_swmr_write = TRUE;
+ u++;
+ break;
+
+ default:
+ usage();
+ break;
+ } /* end switch */
+ } /* end if */
+ } /* end while */
+ } /* end if */
+
+ /* Emit informational message */
+ if(verbose) {
+ HDfprintf(stderr, "Parameters:\n");
+ HDfprintf(stderr, "\tswmr writes %s\n", vfd_swmr_write ? "on" : "off");
+ HDfprintf(stderr, "\tcompression level = %d\n", comp_level);
+ HDfprintf(stderr, "\tindex type = %s\n", index_type);
+ } /* end if */
+
+ /* Set the random seed */
+ if(!use_seed) {
+ struct timeval t;
+
+ HDgettimeofday(&t, NULL);
+ random_seed = (unsigned)(t.tv_usec);
+ } /* end if */
+ HDsrandom(random_seed);
+ /* ALWAYS emit the random seed for possible debugging */
+ HDfprintf(stderr, "Using generator random seed (used in sparse test only): %u\n", random_seed);
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "Generating skeleton file: %s\n", COMMON_FILENAME);
+
+ /* Generate file skeleton */
+ if(gen_skeleton(COMMON_FILENAME, verbose, vfd_swmr_write, comp_level, index_type, random_seed) < 0) {
+ HDfprintf(stderr, "Error generating skeleton file!\n");
+ HDexit(1);
+ } /* end if */
+
+ return 0;
+} /* main() */
diff --git a/test/vfd_swmr_group_writer.c b/test/vfd_swmr_group_writer.c
new file mode 100644
index 0000000..a1bea61
--- /dev/null
+++ b/test/vfd_swmr_group_writer.c
@@ -0,0 +1,343 @@
+/*
+ * Copyright by The HDF Group.
+ * Copyright by the Board of Trustees of the University of Illinois.
+ * All rights reserved.
+ *
+ * This file is part of HDF5. The full HDF5 copyright notice, including
+ * terms governing use, modification, and redistribution, is contained in
+ * the COPYING file, which can be found at the root of the source code
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases.
+ * If you do not have access to either file, you may request a copy from
+ * help@hdfgroup.org.
+ */
+
+#include <err.h>
+#include <libgen.h>
+#include <time.h> /* nanosleep(2) */
+#include <unistd.h> /* getopt(3) */
+
+#define H5F_FRIEND /*suppress error about including H5Fpkg */
+
+#include "hdf5.h"
+
+#include "H5Fpkg.h"
+// #include "H5Iprivate.h"
+#include "H5HGprivate.h"
+#include "H5VLprivate.h"
+
+#include "testhdf5.h"
+#include "vfd_swmr_common.h"
+
+typedef struct {
+ hid_t file, filetype, one_by_one_sid;
+ char filename[PATH_MAX];
+ char progname[PATH_MAX];
+ struct timespec update_interval;
+ unsigned int asteps;
+ unsigned int nsteps;
+ bool wait_for_signal;
+ bool use_vfd_swmr;
+} state_t;
+
+#define ALL_HID_INITIALIZER (state_t){ \
+ .file = H5I_INVALID_HID \
+ , .one_by_one_sid = H5I_INVALID_HID \
+ , .filename = "" \
+ , .filetype = H5T_NATIVE_UINT32 \
+ , .asteps = 10 \
+ , .nsteps = 100 \
+ , .wait_for_signal = true \
+ , .use_vfd_swmr = true \
+ , .update_interval = (struct timespec){ \
+ .tv_sec = 0 \
+ , .tv_nsec = 1000000000UL / 30 /* 1/30 second */}}
+
+static void state_init(state_t *, int, char **);
+
+static const hid_t badhid = H5I_INVALID_HID;
+
+static void
+usage(const char *progname)
+{
+ fprintf(stderr, "usage: %s [-S] [-W] [-a steps] [-b]\n"
+ " [-n iterations] [-u milliseconds]\n"
+ "\n"
+ "-S: do not use VFD SWMR\n"
+ "-W: do not wait for a signal before\n"
+ " exiting\n"
+ "-a steps: `steps` between adding attributes\n"
+ "-b: write data in big-endian byte order\n"
+ "-n iterations: how many times to expand each dataset\n"
+ "-u ms: milliseconds interval between updates\n"
+ " to %s.h5\n"
+ "\n",
+ progname, progname);
+ exit(EXIT_FAILURE);
+}
+
+static void
+state_init(state_t *s, int argc, char **argv)
+{
+ unsigned long tmp;
+ int ch;
+ const hsize_t dims = 1;
+ char tfile[PATH_MAX];
+ char *end;
+ unsigned long millis;
+
+ *s = ALL_HID_INITIALIZER;
+ esnprintf(tfile, sizeof(tfile), "%s", argv[0]);
+ esnprintf(s->progname, sizeof(s->progname), "%s", basename(tfile));
+
+ while ((ch = getopt(argc, argv, "SWa:bn:qu:")) != -1) {
+ switch (ch) {
+ case 'S':
+ s->use_vfd_swmr = false;
+ break;
+ case 'W':
+ s->wait_for_signal = false;
+ break;
+ case 'a':
+ case 'n':
+ errno = 0;
+ tmp = strtoul(optarg, &end, 0);
+ if (end == optarg || *end != '\0') {
+ errx(EXIT_FAILURE, "couldn't parse `-%c` argument `%s`", ch,
+ optarg);
+ } else if (errno != 0) {
+ err(EXIT_FAILURE, "couldn't parse `-%c` argument `%s`", ch,
+ optarg);
+ } else if (tmp > UINT_MAX)
+ errx(EXIT_FAILURE, "`-%c` argument `%lu` too large", ch, tmp);
+
+ if (ch == 'a')
+ s->asteps = (unsigned)tmp;
+ else
+ s->nsteps = (unsigned)tmp;
+ break;
+ case 'b':
+ s->filetype = H5T_STD_U32BE;
+ break;
+ case 'q':
+ verbosity = 0;
+ break;
+ case 'u':
+ errno = 0;
+ millis = strtoul(optarg, &end, 0);
+ if (millis == ULONG_MAX && errno == ERANGE) {
+ err(EXIT_FAILURE,
+ "option -p argument \"%s\"", optarg);
+ } else if (*end != '\0') {
+ errx(EXIT_FAILURE,
+ "garbage after -p argument \"%s\"", optarg);
+ }
+ s->update_interval.tv_sec = (time_t)(millis / 1000UL);
+ s->update_interval.tv_nsec =
+ (long)((millis * 1000000UL) % 1000000000UL);
+ dbgf(1, "%lu milliseconds between updates\n", millis);
+ break;
+ case '?':
+ default:
+ usage(s->progname);
+ break;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ /* space for attributes */
+ if ((s->one_by_one_sid = H5Screate_simple(1, &dims, &dims)) < 0)
+ errx(EXIT_FAILURE, "H5Screate_simple failed");
+
+ if (argc > 0)
+ errx(EXIT_FAILURE, "unexpected command-line arguments");
+
+ esnprintf(s->filename, sizeof(s->filename), "vfd_swmr_group.h5");
+}
+
+static void
+add_group_attribute(const state_t *s, hid_t g, hid_t sid, unsigned int which)
+{
+ hid_t aid;
+ char name[sizeof("attr-9999999999")];
+
+ esnprintf(name, sizeof(name), "attr-%u", which);
+
+ dbgf(1, "setting attribute %s on group %u to %u\n", name, which, which);
+
+ if ((aid = H5Acreate2(g, name, s->filetype, sid, H5P_DEFAULT,
+ H5P_DEFAULT)) < 0)
+ errx(EXIT_FAILURE, "H5Acreate2 failed");
+
+ if (H5Awrite(aid, H5T_NATIVE_UINT, &which) < 0)
+ errx(EXIT_FAILURE, "H5Awrite failed");
+ if (H5Aclose(aid) < 0)
+ errx(EXIT_FAILURE, "H5Aclose failed");
+}
+
+
+static void
+write_group(state_t *s, unsigned int which)
+{
+ char name[sizeof("/group-9999999999")];
+ hid_t g;
+
+ assert(which < s->nsteps);
+
+ esnprintf(name, sizeof(name), "/group-%d", which);
+
+ g = H5Gcreate2(s->file, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+
+ if (g < 0)
+ errx(EXIT_FAILURE, "H5Gcreate(, \"%s\", ) failed", name);
+
+ if (s->asteps != 0 && which % s->asteps == 0)
+ add_group_attribute(s, g, s->one_by_one_sid, which);
+
+ if (H5Gclose(g) < 0)
+ errx(EXIT_FAILURE, "H5Gclose failed");
+}
+
+static bool
+verify_group_attribute(hid_t g, unsigned int which)
+{
+ estack_state_t es;
+ unsigned int read_which;
+ hid_t aid;
+ char name[sizeof("attr-9999999999")];
+
+ esnprintf(name, sizeof(name), "attr-%u", which);
+
+ dbgf(1, "verifying attribute %s on group %u equals %u\n", name, which,
+ which);
+
+ es = disable_estack();
+ if ((aid = H5Aopen(g, name, H5P_DEFAULT)) < 0) {
+ restore_estack(es);
+ return false;
+ }
+
+ if (H5Aread(aid, H5T_NATIVE_UINT, &read_which) < 0) {
+ restore_estack(es);
+ if (H5Aclose(aid) < 0)
+ errx(EXIT_FAILURE, "H5Aclose failed");
+ return false;
+ }
+
+ restore_estack(es);
+
+ if (H5Aclose(aid) < 0)
+ errx(EXIT_FAILURE, "H5Aclose failed");
+
+ return read_which == which;
+}
+
+static bool
+verify_group(state_t *s, unsigned int which)
+{
+ char name[sizeof("/group-9999999999")];
+ hid_t g;
+ estack_state_t es;
+ bool result;
+
+ assert(which < s->nsteps);
+
+ esnprintf(name, sizeof(name), "/group-%d", which);
+
+ es = disable_estack();
+ g = H5Gopen(s->file, name, H5P_DEFAULT);
+ restore_estack(es);
+
+ if (g < 0)
+ return false;
+
+ if (s->asteps != 0 && which % s->asteps == 0)
+ result = verify_group_attribute(g, which);
+ else
+ result = true;
+
+ if (H5Gclose(g) < 0)
+ errx(EXIT_FAILURE, "H5Gclose failed");
+
+ return result;
+}
+
+int
+main(int argc, char **argv)
+{
+ hid_t fapl, fcpl;
+ sigset_t oldsigs;
+ herr_t ret;
+ unsigned step;
+ bool writer;
+ state_t s;
+ const char *personality;
+
+ state_init(&s, argc, argv);
+
+ personality = strstr(s.progname, "vfd_swmr_group_");
+
+ if (personality != NULL &&
+ strcmp(personality, "vfd_swmr_group_writer") == 0)
+ writer = true;
+ else if (personality != NULL &&
+ strcmp(personality, "vfd_swmr_group_reader") == 0)
+ writer = false;
+ else {
+ errx(EXIT_FAILURE,
+ "unknown personality, expected vfd_swmr_group_{reader,writer}");
+ }
+
+ fapl = vfd_swmr_create_fapl(writer, true, s.use_vfd_swmr, "./shadow");
+
+ if (fapl < 0)
+ errx(EXIT_FAILURE, "vfd_swmr_create_fapl");
+
+ if ((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0)
+ errx(EXIT_FAILURE, "H5Pcreate");
+
+ ret = H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, false, 1);
+ if (ret < 0)
+ errx(EXIT_FAILURE, "H5Pset_file_space_strategy");
+
+ if (writer)
+ s.file = H5Fcreate(s.filename, H5F_ACC_TRUNC, fcpl, fapl);
+ else
+ s.file = H5Fopen(s.filename, H5F_ACC_RDONLY, fapl);
+
+ if (s.file == badhid)
+ errx(EXIT_FAILURE, writer ? "H5Fcreate" : "H5Fopen");
+
+ block_signals(&oldsigs);
+
+ if (writer) {
+ for (step = 0; step < s.nsteps; step++) {
+ dbgf(2, "step %d\n", step);
+ write_group(&s, step);
+ nanosleep(&s.update_interval, NULL);
+ }
+ } else {
+ for (step = 0; step < s.nsteps;) {
+ dbgf(2, "step %d\n", step);
+ if (verify_group(&s, step))
+ step++;
+ nanosleep(&s.update_interval, NULL);
+ }
+ }
+
+ if (s.use_vfd_swmr && s.wait_for_signal)
+ await_signal(s.file);
+
+ restore_signals(&oldsigs);
+
+ if (H5Pclose(fapl) < 0)
+ errx(EXIT_FAILURE, "H5Pclose(fapl)");
+
+ if (H5Pclose(fcpl) < 0)
+ errx(EXIT_FAILURE, "H5Pclose(fcpl)");
+
+ if (H5Fclose(s.file) < 0)
+ errx(EXIT_FAILURE, "H5Fclose");
+
+ return EXIT_SUCCESS;
+}
diff --git a/test/vfd_swmr_reader.c b/test/vfd_swmr_reader.c
new file mode 100644
index 0000000..706c894
--- /dev/null
+++ b/test/vfd_swmr_reader.c
@@ -0,0 +1,677 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: vfd_swmr_reader.c
+ * (copied and modified from swmr_reader.c)
+ *
+ * Purpose: Reads data from a randomly selected subset of the datasets
+ * in the VFD SWMR test file.
+ *
+ * This program is intended to run concurrently with the
+ * vfd_swmr_writer program.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/***********/
+/* Headers */
+/***********/
+
+#include "h5test.h"
+#include "vfd_swmr_common.h"
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+static int check_dataset(hid_t fid, hbool_t verbose, FILE *verbose_file,
+ const char *sym_name, symbol_t *record, hid_t rec_sid);
+static int read_records(const char *filename, hbool_t verbose, FILE *verbose_file,
+ unsigned random_seed, unsigned long nseconds, unsigned poll_time,
+ unsigned ncommon, unsigned nrandom);
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+static hid_t symbol_tid = -1; /* The type ID for the SWMR datasets */
+
+
+/*-------------------------------------------------------------------------
+ * Function: check_dataset
+ *
+ * Purpose: For a given dataset, checks to make sure that the stated
+ * and actual sizes are the same. If they are not, then
+ * we have an inconsistent dataset due to a SWMR error.
+ *
+ * Parameters: hid_t fid
+ * The SWMR test file's ID.
+ *
+ * hbool_t verbose
+ * Whether verbose console output is desired.
+ *
+ * FILE *verbose_file
+ * File handle for verbose output
+ *
+ * const char *sym_name
+ * The name of the dataset from which to read.
+ *
+ * symbol_t *record
+ * Memory for the record. Must be pre-allocated.
+ *
+ * hid_t rec_sid
+ * The memory dataspace for access. It's always the same so
+ * there is no need to re-create it every time this function
+ * is called.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+check_dataset(hid_t fid, hbool_t verbose, FILE *verbose_file,
+ const char *sym_name, symbol_t *record, hid_t rec_sid)
+{
+ int fill_count = 0; /* # of times fill value (0) was read
+ * instead of the expected value.
+ */
+ hid_t dsid; /* Dataset ID */
+ hid_t file_sid; /* Dataset's space ID */
+ hssize_t snpoints; /* Number of elements in dataset */
+ hsize_t start[2] = {0, 0}, count[2] = {1, 1}; /* Hyperslab selection values */
+
+ HDassert(fid >= 0);
+ HDassert(sym_name);
+ HDassert(record);
+ HDassert(rec_sid >= 0);
+
+ /* Open dataset for symbol */
+ if((dsid = H5Dopen2(fid, sym_name, H5P_DEFAULT)) < 0) {
+ fprintf(stderr, "%s.%d: H5Dopen2 failed\n", __func__, __LINE__);
+ goto error;
+ }
+
+ /* Get the dataset's dataspace */
+ if((file_sid = H5Dget_space(dsid)) < 0) {
+ fprintf(stderr, "%s.%d: H5Dget_space failed\n", __func__, __LINE__);
+ goto error;
+ }
+
+ /* Get the number of elements (= records, for 1-D datasets) */
+ if((snpoints = H5Sget_simple_extent_npoints(file_sid)) < 0) {
+ fprintf(stderr, "%s.%d: H5Sget_simple_extent_npoints failed\n",
+ __func__, __LINE__);
+ goto error;
+ }
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(verbose_file, "READER: Symbol = '%s', # of records = %lld\n", sym_name, (long long)snpoints);
+
+ /* Check if there are records for symbol */
+ if(snpoints > 0) {
+ /* Choose the last record in the dataset */
+ start[1] = (hsize_t)(snpoints - 1);
+ if(H5Sselect_hyperslab(file_sid, H5S_SELECT_SET, start, NULL, count, NULL) < 0) {
+ fprintf(stderr, "%s.%d: H5Sselect_hyperslab failed\n",
+ __func__, __LINE__);
+ goto error;
+ }
+
+ /* Read record from dataset */
+ record->rec_id = UINT64_MAX;
+ if(H5Dread(dsid, symbol_tid, rec_sid, file_sid, H5P_DEFAULT, record) < 0) {
+ fprintf(stderr, "%s.%d: H5Dread failed\n", __func__, __LINE__);
+ goto error;
+ }
+
+ /* Verify record value */
+ if (record->rec_id != start[1] && record->rec_id == 0)
+ fill_count++;
+ else if (record->rec_id != start[1]) {
+ struct timeval tv;
+
+ HDgettimeofday(&tv, NULL);
+
+ if(verbose) {
+ HDfprintf(verbose_file, "*** READER ERROR ***\n");
+ HDfprintf(verbose_file, "Incorrect record value!\n");
+ HDfprintf(verbose_file,
+ "Time = %jd.%06jd, Symbol = '%s'"
+ ", # of records = %" PRIdHSIZE
+ ", record->rec_id = %" PRIu64 "\n",
+ (intmax_t)tv.tv_sec, (intmax_t)tv.tv_usec,
+ sym_name, snpoints, record->rec_id);
+ } /* end if */
+ fprintf(stderr,
+ "%s.%d: record value %" PRIu64 " != %" PRIuHSIZE "\n",
+ __func__, __LINE__, record->rec_id, start[1]);
+ goto error;
+ } /* end if */
+ } /* end if */
+
+ /* Close the dataset's dataspace */
+ if(H5Sclose(file_sid) < 0) {
+ fprintf(stderr, "%s.%d: H5Sclose failed\n", __func__, __LINE__);
+ goto error;
+ }
+
+ /* Close dataset for symbol */
+ if(H5Dclose(dsid) < 0) {
+ fprintf(stderr, "%s.%d: H5Dclose failed\n", __func__, __LINE__);
+ goto error;
+ }
+
+ return fill_count;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Sclose(file_sid);
+ H5Dclose(dsid);
+ } H5E_END_TRY;
+
+ return -1;
+} /* end check_dataset() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: read_records
+ *
+ * Purpose: For a given dataset, checks to make sure that the stated
+ * and actual sizes are the same. If they are not, then
+ * we have an inconsistent dataset due to a SWMR error.
+ *
+ * The "common" datasets are a random selection from among
+ * the level 0 datasets. The "random" datasets are a random
+ * selection from among all the file's datasets. This scheme
+ * ensures that the level 0 datasets are interrogated vigorously.
+ *
+ * Parameters: const char *filename
+ * The SWMR test file's name.
+ *
+ * hbool_t verbose
+ * Whether verbose console output is desired.
+ *
+ * FILE *verbose_file
+ * File handle for verbose output
+ *
+ * unsigned random_seed
+ * Random seed for the file (used for verbose logging)
+ *
+ * unsigned long nseconds
+ * The amount of time to read records (ns).
+ *
+ * unsigned poll_time
+ * The amount of time to sleep (s).
+ *
+ * unsigned ncommon
+ * The number of common/non-random datasets that will be opened.
+ *
+ * unsigned nrandom
+ * The number of random datasets that will be opened.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+read_records(const char *filename, hbool_t verbose, FILE *verbose_file,
+ unsigned random_seed, unsigned long nseconds, unsigned poll_time,
+ unsigned ncommon, unsigned nrandom)
+{
+ time_t start_time; /* Starting time */
+ time_t curr_time; /* Current time */
+ symbol_info_t **sym_com = NULL; /* Pointers to array of common dataset IDs */
+ symbol_info_t **sym_rand = NULL; /* Pointers to array of random dataset IDs */
+ hid_t mem_sid; /* Memory dataspace ID */
+ hid_t fid; /* SWMR test file ID */
+ hid_t fapl; /* file access property list */
+ symbol_t record; /* The record to read from the dataset */
+ unsigned v; /* Local index variable */
+ hbool_t use_log_vfd = FALSE; /* Use the log VFD (set this manually) */
+ H5F_vfd_swmr_config_t *config = NULL; /* Configuration for VFD SWMR */
+
+ HDassert(filename);
+ HDassert(nseconds != 0);
+ HDassert(poll_time != 0);
+
+ /* Reset the record */
+ /* (record's 'info' field might need to change for each record read, also) */
+ HDmemset(&record, 0, sizeof(record));
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(verbose_file, "READER: Choosing datasets\n");
+
+ /* Allocate space for 'common' datasets, if any */
+ if(ncommon > 0) {
+ /* Allocate array to hold pointers to symbols for common datasets */
+ if(NULL == (sym_com = (symbol_info_t **)HDmalloc(sizeof(symbol_info_t *) * ncommon))) {
+ fprintf(stderr, "%s.%d: malloc failed\n", __func__, __LINE__);
+ goto error;
+ }
+
+ /* Open the common datasets */
+ for(v = 0; v < ncommon; v++) {
+ unsigned offset; /* Offset of symbol to use */
+
+ /* Determine the offset of the symbol, within level 0 symbols */
+ /* (level 0 symbols are the most common symbols) */
+ offset = (unsigned)((unsigned)HDrandom() % symbol_count[0]);
+ sym_com[v] = &symbol_info[0][offset];
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(verbose_file, "READER: Common symbol #%u = '%s'\n", v, symbol_info[0][offset].name);
+ } /* end for */
+ } /* end if */
+
+ /* Allocate space for 'random' datasets, if any */
+ if(nrandom > 0) {
+ /* Allocate array to hold pointers to symbols for random datasets */
+ if(NULL == (sym_rand = (symbol_info_t **)HDmalloc(sizeof(symbol_info_t *) * nrandom))) {
+ fprintf(stderr, "%s.%d: malloc failed\n", __func__, __LINE__);
+ goto error;
+ }
+
+ /* Determine the random datasets */
+ for(v = 0; v < nrandom; v++) {
+ symbol_info_t *sym; /* Symbol to use */
+
+ /* Determine the symbol, within all symbols */
+ if(NULL == (sym = choose_dataset(NULL, NULL)))
+ return -1;
+ sym_rand[v] = sym;
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(verbose_file, "READER: Random symbol #%u = '%s'\n", v, sym->name);
+ } /* end for */
+ } /* end if */
+
+ /* Create a dataspace for the record to read */
+ if((mem_sid = H5Screate(H5S_SCALAR)) < 0) {
+ fprintf(stderr, "%s.%d: H5Screate failed\n", __func__, __LINE__);
+ goto error;
+ }
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(verbose_file, "READER: Going to open file and read records\n");
+
+ /* Get the starting time */
+ start_time = HDtime(NULL);
+ curr_time = start_time;
+
+ /* Create file access property list */
+ if((fapl = h5_fileaccess()) < 0) {
+ fprintf(stderr, "%s.%d: h5_fileaccess failed\n", __func__, __LINE__);
+ goto error;
+ }
+
+ /* Log I/O when verbose output it enbabled */
+ if(use_log_vfd) {
+ char verbose_name[1024];
+
+ HDsnprintf(verbose_name, sizeof(verbose_name), "vfd_swmr_reader.log.%u", random_seed);
+
+ H5Pset_fapl_log(fapl, verbose_name, H5FD_LOG_ALL, (size_t)(512 * 1024 * 1024));
+ } /* end if */
+
+ /*
+ * Set up to open the file with VFD SWMR configured.
+ */
+ /* Enable page buffering */
+ if(H5Pset_page_buffer_size(fapl, 4096, 0, 0) < 0) {
+ fprintf(stderr, "%s.%d: H5Pset_page_buffer_size failed\n",
+ __func__, __LINE__);
+ goto error;
+ }
+
+ /* Allocate memory for the configuration structure */
+ if((config = (H5F_vfd_swmr_config_t *)HDcalloc(1, sizeof(H5F_vfd_swmr_config_t))) == NULL) {
+ fprintf(stderr, "%s.%d: malloc failed\n", __func__, __LINE__);
+ goto error;
+ }
+
+ config->version = H5F__CURR_VFD_SWMR_CONFIG_VERSION;
+ config->tick_len = 4;
+ config->max_lag = 5;
+ config->writer = FALSE;
+ config->md_pages_reserved = 128;
+ HDstrcpy(config->md_file_path, "./my_md_file");
+
+ /* Enable VFD SWMR configuration */
+ if(H5Pset_vfd_swmr_config(fapl, config) < 0) {
+ fprintf(stderr, "%s.%d: H5Pset_vfd_swmr_config failed\n",
+ __func__, __LINE__);
+ goto error;
+ }
+
+ /* Loop over reading records until [at least] the correct # of seconds have passed */
+ while(curr_time < (time_t)(start_time + (time_t)nseconds)) {
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(verbose_file, "READER: Opening file: %s\n", filename);
+
+ /* Open the file with VFD SWMR configured */
+ /* Remove H5E_BEGIN_TRY/END_TRY if you want to see the error stack */
+ H5E_BEGIN_TRY {
+ fid = H5Fopen(filename, H5F_ACC_RDONLY, fapl);
+ } H5E_END_TRY;
+ if(fid < 0) {
+ HDfprintf(stderr, "READER: Error in opening the file: %s\n", filename);
+ goto error;
+ }
+
+ /* Check 'common' datasets, if any */
+ if(ncommon > 0) {
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(verbose_file, "READER: Checking common symbols after FILE OPEN\n");
+
+ /* Iterate over common datasets */
+ for(v = 0; v < ncommon; v++) {
+ /* Check common dataset */
+ const int fill_count =
+ check_dataset(fid, verbose, verbose_file, sym_com[v]->name,
+ &record, mem_sid);
+ if(fill_count < 0) {
+ fprintf(stderr, "%s.%d: check_dataset failed\n",
+ __func__, __LINE__);
+ goto error;
+ }
+ HDmemset(&record, 0, sizeof(record));
+ if (fill_count > 0) {
+ fprintf(stderr, "common dataset: read fill at %d records\n",
+ fill_count);
+ }
+ } /* end for */
+ } /* end if */
+
+ /* Check 'random' datasets, if any */
+ if(nrandom > 0) {
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(verbose_file, "READER: Checking random symbols after FILE OPEN\n");
+
+ /* Iterate over random datasets */
+ for(v = 0; v < nrandom; v++) {
+ /* Check random dataset */
+ const int fill_count = check_dataset(fid, verbose, verbose_file,
+ sym_rand[v]->name, &record, mem_sid);
+ if(fill_count < 0) {
+ fprintf(stderr, "%s.%d: check_dataset failed\n",
+ __func__, __LINE__);
+ goto error;
+ }
+ HDmemset(&record, 0, sizeof(record));
+ if (fill_count > 0) {
+ fprintf(stderr, "random dataset: read fill at %d records\n",
+ fill_count);
+ }
+ } /* end for */
+ } /* end if */
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(verbose_file, "READER: Closing file\n");
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0) {
+ fprintf(stderr, "%s.%d: H5Fclose failed\n", __func__, __LINE__);
+ goto error;
+ }
+
+ /* Sleep for the appropriate # of seconds */
+ HDsleep(poll_time);
+
+ /* Retrieve the current time */
+ curr_time = HDtime(NULL);
+ } /* end while */
+
+ /* Close the memory dataspace */
+ if(H5Sclose(mem_sid) < 0) {
+ fprintf(stderr, "%s.%d: H5Sclose failed\n", __func__, __LINE__);
+ goto error;
+ }
+
+ /* Close the fapl */
+ if(H5Pclose(fapl) < 0) {
+ fprintf(stderr, "%s.%d: H5Pclose failed\n", __func__, __LINE__);
+ goto error;
+ }
+
+ if(config)
+ HDfree(config);
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(verbose_file, "READER: Closing datasets\n");
+
+ /* Close 'random' datasets, if any */
+ if(nrandom > 0) {
+ /* Release array holding dataset ID's for random datasets */
+ HDfree(sym_rand);
+ } /* end if */
+
+ /* Close 'common' datasets, if any */
+ if(ncommon > 0) {
+ /* Release array holding dataset ID's for common datasets */
+ HDfree(sym_com);
+ } /* end if */
+
+ return 0;
+
+error:
+ if(config)
+ HDfree(config);
+
+ if(sym_rand)
+ HDfree(sym_rand);
+
+ if(sym_com)
+ HDfree(sym_com);
+
+ H5E_BEGIN_TRY {
+ H5Sclose(mem_sid);
+ H5Fclose(fid);
+ H5Pclose(fapl);
+ } H5E_END_TRY;
+
+ return -1;
+} /* end read_records() */
+
+static void
+usage(void)
+{
+ printf("\n");
+ printf("Usage error!\n");
+ printf("\n");
+ printf("Usage: vfd_swmr_reader [-q] [-s <# of seconds to sleep between polling>]\n");
+ printf(" [-h <# of common symbols to poll>] [-l <# of random symbols to poll>]\n");
+ printf(" [-r <random seed>] <# of seconds to test>\n");
+ printf("\n");
+ printf("<# of seconds to test> must be specified.\n");
+ printf("\n");
+ printf("Defaults to verbose (no '-q' given), 1 second between polling ('-s 1'),\n");
+ printf("5 common symbols to poll ('-h 5'), 10 random symbols to poll ('-l 10'),\n");
+ printf("and will generate a random seed (no -r given).\n");
+ printf("\n");
+ HDexit(1);
+}
+
+int main(int argc, const char *argv[])
+{
+ long nseconds = 0; /* # of seconds to test */
+ int poll_time = 1; /* # of seconds between polling */
+ int ncommon = 5; /* # of common symbols to poll */
+ int nrandom = 10; /* # of random symbols to poll */
+ hbool_t verbose = TRUE; /* Whether to emit some informational messages */
+ FILE *verbose_file = NULL; /* File handle for verbose output */
+ hbool_t use_seed = FALSE; /* Set to 1 if a seed was set on the command line */
+ unsigned random_seed = 0; /* Random # seed */
+ unsigned u; /* Local index variables */
+ int temp;
+
+ /* Parse command line options */
+ if(argc < 2)
+ usage();
+ if(argc > 1) {
+ u = 1;
+ while(u < (unsigned)argc) {
+ if(argv[u][0] == '-') {
+ switch(argv[u][1]) {
+ /* # of common symbols to poll */
+ case 'h':
+ ncommon = HDatoi(argv[u + 1]);
+ if(ncommon < 0)
+ usage();
+ u += 2;
+ break;
+
+ /* # of random symbols to poll */
+ case 'l':
+ nrandom = HDatoi(argv[u + 1]);
+ if(nrandom < 0)
+ usage();
+ u += 2;
+ break;
+
+ /* Be quiet */
+ case 'q':
+ verbose = FALSE;
+ u++;
+ break;
+
+ /* Random # seed */
+ case 'r':
+ use_seed = TRUE;
+ temp = HDatoi(argv[u + 1]);
+ if(temp < 0)
+ usage();
+ else
+ random_seed = (unsigned)temp;
+ u += 2;
+ break;
+
+ /* # of seconds between polling */
+ case 's':
+ poll_time = HDatoi(argv[u + 1]);
+ if(poll_time < 0)
+ usage();
+ u += 2;
+ break;
+
+ default:
+ usage();
+ break;
+ } /* end switch */
+ } /* end if */
+ else {
+ /* Get the number of records to append */
+ nseconds = HDatol(argv[u]);
+ if(nseconds <= 0)
+ usage();
+
+ u++;
+ } /* end else */
+ } /* end while */
+ } /* end if */
+ if(nseconds <= 0)
+ usage();
+ if(poll_time >= nseconds)
+ usage();
+
+ /* Set the random seed */
+ if(!use_seed) {
+ struct timeval t;
+
+ HDgettimeofday(&t, NULL);
+ random_seed = (unsigned)(t.tv_usec);
+ } /* end if */
+ HDsrandom(random_seed);
+
+ /* Open output file */
+ if(verbose) {
+ char verbose_name[1024];
+
+ HDsnprintf(verbose_name, sizeof(verbose_name), "vfd_swmr_reader.out.%u", random_seed);
+ if(NULL == (verbose_file = HDfopen(verbose_name, "w"))) {
+ HDfprintf(stderr, "READER: Can't open verbose output file!\n");
+ HDexit(1);
+ }
+ } /* end if */
+
+ /* Emit informational message */
+ if(verbose) {
+ HDfprintf(verbose_file, "READER: Parameters:\n");
+ HDfprintf(verbose_file, "\t# of seconds between polling = %d\n", poll_time);
+ HDfprintf(verbose_file, "\t# of common symbols to poll = %d\n", ncommon);
+ HDfprintf(verbose_file, "\t# of random symbols to poll = %d\n", nrandom);
+ HDfprintf(verbose_file, "\t# of seconds to test = %ld\n", nseconds);
+ } /* end if */
+
+ /* ALWAYS emit the random seed for possible debugging */
+ HDfprintf(stdout, "READER: Using reader random seed: %u\n", random_seed);
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(verbose_file, "READER: Generating symbol names\n");
+
+ /* Generate dataset names */
+ if(generate_symbols() < 0) {
+ HDfprintf(stderr, "READER: Error generating symbol names!\n");
+ HDexit(1);
+ } /* end if */
+
+ /* Create datatype for creating datasets */
+ if((symbol_tid = create_symbol_datatype()) < 0) {
+ HDfprintf(stderr, "READER: Error creating symbol datatype!\n");
+ HDexit(1);
+ }
+
+ /* Reading records from datasets */
+ if(read_records(COMMON_FILENAME, verbose, verbose_file, random_seed, (unsigned long)nseconds, (unsigned)poll_time, (unsigned)ncommon, (unsigned)nrandom) < 0) {
+ HDfprintf(stderr, "READER: Error reading records from datasets (random_seed = %u)!\n", random_seed);
+ HDexit(1);
+ } /* end if */
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(verbose_file, "READER: Releasing symbols\n");
+
+ /* Clean up the symbols */
+ if(shutdown_symbols() < 0) {
+ HDfprintf(stderr, "READER: Error releasing symbols!\n");
+ HDexit(1);
+ } /* end if */
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(verbose_file, "READER: Closing objects\n");
+
+ /* Close objects created */
+ if(H5Tclose(symbol_tid) < 0) {
+ HDfprintf(stderr, "READER: Error closing symbol datatype!\n");
+ HDexit(1);
+ } /* end if */
+
+ return 0;
+}
+
diff --git a/test/vfd_swmr_remove_reader.c b/test/vfd_swmr_remove_reader.c
new file mode 100644
index 0000000..3515987
--- /dev/null
+++ b/test/vfd_swmr_remove_reader.c
@@ -0,0 +1,596 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: vfd_swmr_remove_reader.c
+ * (copied and modified from swmr_remove_reader.c)
+ *
+ * Purpose: Reads data from a randomly selected subset of the datasets
+ * in the VFD SWMR test file. Unlike the regular reader, these
+ * datasets will be shrinking.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/***********/
+/* Headers */
+/***********/
+
+#include <err.h> /* errx(3) */
+#include <stdlib.h> /* EXIT_FAILURE */
+
+#include "h5test.h"
+#include "vfd_swmr_common.h"
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+static hid_t symbol_tid = -1;
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+static int check_dataset(hid_t, hid_t, unsigned, const char *,
+ symbol_t *, hid_t);
+static int read_records(const char *, unsigned, unsigned long,
+ unsigned, unsigned, unsigned);
+static void usage(void);
+
+
+/*-------------------------------------------------------------------------
+ * Function: check_dataset
+ *
+ * Purpose: For a given dataset, checks to make sure that the stated
+ * and actual sizes are the same. If they are not, then
+ * we have an inconsistent dataset due to a SWMR error.
+ *
+ * Parameters: hid_t fid
+ * The SWMR test file's ID.
+ *
+ * unsigned verbose
+ * Whether verbose console output is desired.
+ *
+ * const char *sym_name
+ * The name of the dataset from which to read.
+ *
+ * symbol_t *record
+ * Memory for the record. Must be pre-allocated.
+ *
+ * hid_t rec_sid
+ * The memory dataspace for access. It's always the same so
+ * there is no need to re-create it every time this function
+ * is called.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+check_dataset(hid_t fid, hid_t dapl, unsigned verbose, const char *sym_name, symbol_t *record,
+ hid_t rec_sid)
+{
+ hid_t dsid; /* Dataset ID */
+ hid_t file_sid; /* Dataset's space ID */
+ hssize_t snpoints; /* Number of elements in dataset */
+ hsize_t start[2] = {0, 0}, count[2] = {1, 1}; /* Hyperslab selection values */
+
+ HDassert(fid >= 0);
+ HDassert(sym_name);
+ HDassert(record);
+ HDassert(rec_sid >= 0);
+
+ /* Open dataset for symbol */
+ if((dsid = H5Dopen2(fid, sym_name, dapl)) < 0)
+ goto error;
+
+ /* Get the dataset's dataspace */
+ if((file_sid = H5Dget_space(dsid)) < 0)
+ goto error;
+
+ /* Get the number of elements (= records, for 1-D datasets) */
+ if((snpoints = H5Sget_simple_extent_npoints(file_sid)) < 0)
+ goto error;
+
+ /* Back off by one: it's possible that the metadata indicating
+ * `snpoints` available is new, but the data is stale, because
+ * a tick occurred on the writer between H5Dset_extent() and H5Dwrite().
+ */
+ snpoints -= MAX_SIZE_CHANGE;
+
+ /* Emit informational message */
+ if(verbose) {
+ HDfprintf(stderr, "READER: Symbol = '%s'"
+ ", # of records = %" PRIdHSIZE "\n", sym_name, snpoints);
+ }
+
+ /* Check if there are records for symbol */
+ if(snpoints > 0) {
+ /* Choose a random record in the dataset, choosing the last record half
+ * the time */
+ start[1] = (hsize_t)(HDrandom() % (snpoints * 2));
+ if(start[1] > (hsize_t)(snpoints - 1))
+ start[1] = (hsize_t)(snpoints - 1);
+ if(H5Sselect_hyperslab(file_sid, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ goto error;
+
+ /* Read record from dataset */
+#ifdef FILLVAL_WORKS
+ /* When shrinking the dataset, we cannot guarantee that the buffer will
+ * even be touched, unless there is a fill value. Since fill values do
+ * not work with SWMR currently (see note in swmr_generator.c), we
+ * simply initialize rec_id to 0. */
+ record->rec_id = (uint64_t)ULLONG_MAX - 1;
+#else /* FILLVAL_WORKS */
+ record->rec_id = (uint64_t)0;
+#endif /* FILLVAL_WORKS */
+ if(H5Dread(dsid, symbol_tid, rec_sid, file_sid, H5P_DEFAULT, record) < 0)
+ goto error;
+
+ /* Verify record value - note that it may be the fill value, because the
+ * chunk may be deleted before the object header has the updated
+ * dimensions */
+ if(record->rec_id != start[1] && record->rec_id != 0) {
+ HDfprintf(stderr, "*** READER: ERROR ***\n");
+ HDfprintf(stderr, "Incorrect record value!\n");
+ HDfprintf(stderr, "Symbol = '%s', # of records = %" PRIdHSIZE
+ ", record->rec_id = %" PRIx64 ", expected %" PRIxHSIZE "\n",
+ sym_name, snpoints, record->rec_id, start[1]);
+ return -1;
+ } /* end if */
+ } /* end if */
+
+ /* Close the dataset's dataspace */
+ if(H5Sclose(file_sid) < 0)
+ goto error;
+
+ /* Close dataset for symbol */
+ if(H5Dclose(dsid) < 0)
+ goto error;
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Sclose(file_sid);
+ H5Dclose(dsid);
+ } H5E_END_TRY;
+
+ return -1;
+} /* end check_dataset() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: read_records
+ *
+ * Purpose: For a given dataset, checks to make sure that the stated
+ * and actual sizes are the same. If they are not, then
+ * we have an inconsistent dataset due to a SWMR error.
+ *
+ * The "common" datasets are a random selection from among
+ * the level 0 datasets. The "random" datasets are a random
+ * selection from among all the file's datasets. This scheme
+ * ensures that the level 0 datasets are interrogated vigorously.
+ *
+ * Parameters: const char *filename
+ * The SWMR test file's name.
+ *
+ * unsigned verbose
+ * Whether verbose console output is desired.
+ *
+ * unsigned long nseconds
+ * The amount of time to read records (ns).
+ *
+ * unsigned poll_time
+ * The amount of time to sleep (s).
+ *
+ * unsigned ncommon
+ * The number of common/non-random datasets that will be opened.
+ *
+ * unsigned nrandom
+ * The number of random datasets that will be opened.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+read_records(const char *filename, unsigned verbose, unsigned long nseconds,
+ unsigned poll_time, unsigned ncommon, unsigned nrandom)
+{
+ time_t start_time; /* Starting time */
+ time_t curr_time; /* Current time */
+ symbol_info_t **sym_com = NULL; /* Pointers to array of common dataset IDs */
+ symbol_info_t **sym_rand = NULL; /* Pointers to array of random dataset IDs */
+ hid_t dapl;
+ hid_t mem_sid; /* Memory dataspace ID */
+ hid_t fid; /* SWMR test file ID */
+ hid_t fapl; /* File access property list */
+ symbol_t record; /* The record to add to the dataset */
+ unsigned v; /* Local index variable */
+ H5F_vfd_swmr_config_t *config = NULL; /* Configuration for VFD SWMR */
+
+ HDassert(filename);
+ HDassert(nseconds != 0);
+ HDassert(poll_time != 0);
+
+ /* Reset the record */
+ /* (record's 'info' field might need to change for each record written, also) */
+ HDmemset(&record, 0, sizeof(record));
+
+ if ((dapl = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
+ errx(EXIT_FAILURE, "%s.%d: H5Pcreate failed", __func__, __LINE__);
+
+ if (H5Pset_chunk_cache(dapl, H5D_CHUNK_CACHE_NSLOTS_DEFAULT, 0,
+ H5D_CHUNK_CACHE_W0_DEFAULT) < 0)
+ errx(EXIT_FAILURE, "H5Pset_chunk_cache failed");
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "READER: Choosing datasets\n");
+
+ /* Allocate space for 'common' datasets, if any */
+ if(ncommon > 0) {
+ /* Allocate array to hold pointers to symbols for common datasets */
+ if(NULL == (sym_com = (symbol_info_t **)HDmalloc(sizeof(symbol_info_t *) * ncommon)))
+ goto error;
+
+ /* Open the common datasets */
+ for(v = 0; v < ncommon; v++) {
+ unsigned offset; /* Offset of symbol to use */
+
+ /* Determine the offset of the symbol, within level 0 symbols */
+ /* (level 0 symbols are the most common symbols) */
+ offset = (unsigned)HDrandom() % symbol_count[0];
+ sym_com[v] = &symbol_info[0][offset];
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "READER: Common symbol #%u = '%s'\n", v, symbol_info[0][offset].name);
+ } /* end for */
+ } /* end if */
+
+ /* Allocate space for 'random' datasets, if any */
+ if(nrandom > 0) {
+ /* Allocate array to hold pointers to symbols for random datasets */
+ if(NULL == (sym_rand = (symbol_info_t **)HDmalloc(sizeof(symbol_info_t *) * nrandom)))
+ goto error;
+
+ /* Determine the random datasets */
+ for(v = 0; v < nrandom; v++) {
+ symbol_info_t *sym; /* Symbol to use */
+
+ /* Determine the symbol, within all symbols */
+ if(NULL == (sym = choose_dataset(NULL, NULL)))
+ goto error;
+ sym_rand[v] = sym;
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "READER: Random symbol #%u = '%s'\n", v, sym->name);
+ } /* end for */
+ } /* end if */
+
+ /* Create a dataspace for the record to read */
+ if((mem_sid = H5Screate(H5S_SCALAR)) < 0)
+ goto error;
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "READER: Reading records\n");
+
+ /* Get the starting time */
+ start_time = HDtime(NULL);
+ curr_time = start_time;
+
+ /* Create file access property list */
+ if((fapl = h5_fileaccess()) < 0)
+ goto error;
+
+ /*
+ * Set up to open the file with VFD SWMR configured.
+ */
+ /* Enable page buffering */
+ if(H5Pset_page_buffer_size(fapl, 4096, 0, 0) < 0)
+ goto error;
+
+ /* Allocate memory for the configuration structure */
+ if((config = (H5F_vfd_swmr_config_t *)HDcalloc(1, sizeof(H5F_vfd_swmr_config_t))) == NULL)
+ goto error;
+
+ config->version = H5F__CURR_VFD_SWMR_CONFIG_VERSION;
+ config->tick_len = 4;
+ config->max_lag = 5;
+ config->writer = FALSE;
+ config->md_pages_reserved = 128;
+ HDstrcpy(config->md_file_path, "./my_md_file");
+
+ /* Enable VFD SWMR configuration */
+ if(H5Pset_vfd_swmr_config(fapl, config) < 0)
+ goto error;
+
+ /* Loop over reading records until [at least] the correct # of seconds have passed */
+ while(curr_time < (time_t)(start_time + (time_t)nseconds)) {
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "READER: Opening file: %s\n", filename);
+
+ /* Open the file */
+ /* Remove H5E_BEGIN_TRY/END_TRY if you want to see the error stack */
+ H5E_BEGIN_TRY {
+ fid = H5Fopen(filename, H5F_ACC_RDONLY, fapl);
+ } H5E_END_TRY;
+ if(fid < 0) {
+ HDfprintf(stderr, "READER: Error in opening the file: %s\n", filename);
+ goto error;
+ }
+
+ /* Check 'common' datasets, if any */
+ if(ncommon > 0) {
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "READER: Checking common symbols\n");
+
+ /* Iterate over common datasets */
+ for(v = 0; v < ncommon; v++) {
+ /* Check common dataset */
+ if(check_dataset(fid, dapl, verbose, sym_com[v]->name, &record, mem_sid) < 0)
+ goto error;
+ HDmemset(&record, 0, sizeof(record));
+ } /* end for */
+ } /* end if */
+
+ /* Check 'random' datasets, if any */
+ if(nrandom > 0) {
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "READER: Checking random symbols\n");
+
+ /* Iterate over random datasets */
+ for(v = 0; v < nrandom; v++) {
+ /* Check random dataset */
+ if(check_dataset(fid, dapl, verbose, sym_rand[v]->name, &record, mem_sid) < 0)
+ goto error;
+ HDmemset(&record, 0, sizeof(record));
+ } /* end for */
+ } /* end if */
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "READER: Closing file\n");
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ goto error;
+
+ /* Sleep for the appropriate # of seconds */
+ HDsleep(poll_time);
+
+ /* Retrieve the current time */
+ curr_time = HDtime(NULL);
+ } /* end while */
+
+ /* Close the fapl */
+ if(H5Pclose(fapl) < 0)
+ goto error;
+
+ if(config)
+ HDfree(config);
+
+ /* Close the memory dataspace */
+ if(H5Sclose(mem_sid) < 0)
+ goto error;
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "READER: Closing datasets\n");
+
+ /* Close 'random' datasets, if any */
+ if(nrandom > 0) {
+ /* Release array holding dataset ID's for random datasets */
+ HDfree(sym_rand);
+ } /* end if */
+
+ /* Close 'common' datasets, if any */
+ if(ncommon > 0) {
+ /* Release array holding dataset ID's for common datasets */
+ HDfree(sym_com);
+ } /* end if */
+
+ return 0;
+
+error:
+ if(config)
+ HDfree(config);
+
+ if(sym_rand)
+ HDfree(sym_rand);
+
+ if(sym_com)
+ HDfree(sym_com);
+
+ H5E_BEGIN_TRY {
+ H5Sclose(mem_sid);
+ H5Fclose(fid);
+ H5Pclose(fapl);
+ H5Pclose(dapl);
+ } H5E_END_TRY;
+
+ return -1;
+
+} /* end read_records() */
+
+static void
+usage(void)
+{
+ printf("\n");
+ printf("Usage error!\n");
+ printf("\n");
+ printf("Usage: vfd_swmr_remove_reader [-q] [-s <# of seconds to sleep between\n");
+ printf(" polling>] [-h <# of common symbols to poll>] [-l <# of random symbols\n");
+ printf(" to poll>] [-r <random seed>] <# of seconds to test>\n");
+ printf("\n");
+ printf("Defaults to verbose (no '-q' given), 1 second between polling ('-s 1'),\n");
+ printf("5 common symbols to poll ('-h 5'), 10 random symbols to poll ('-l 10'),\n");
+ printf("and will generate a random seed (no -r given).\n");
+ printf("\n");
+ HDexit(1);
+}
+
+int main(int argc, const char *argv[])
+{
+ long nseconds = 0; /* # of seconds to test */
+ int poll_time = 1; /* # of seconds between polling */
+ int ncommon = 5; /* # of common symbols to poll */
+ int nrandom = 10; /* # of random symbols to poll */
+ unsigned verbose = 1; /* Whether to emit some informational messages */
+ unsigned use_seed = 0; /* Set to 1 if a seed was set on the command line */
+ unsigned random_seed = 0; /* Random # seed */
+ unsigned u; /* Local index variables */
+ int temp;
+
+ /* Parse command line options */
+ if(argc < 2)
+ usage();
+ if(argc > 1) {
+ u = 1;
+ while(u < (unsigned)argc) {
+ if(argv[u][0] == '-') {
+ switch(argv[u][1]) {
+ /* # of common symbols to poll */
+ case 'h':
+ ncommon = HDatoi(argv[u + 1]);
+ if(ncommon < 0)
+ usage();
+ u += 2;
+ break;
+
+ /* # of random symbols to poll */
+ case 'l':
+ nrandom = HDatoi(argv[u + 1]);
+ if(nrandom < 0)
+ usage();
+ u += 2;
+ break;
+
+ /* Be quiet */
+ case 'q':
+ verbose = 0;
+ u++;
+ break;
+
+ /* Random # seed */
+ case 'r':
+ use_seed = 1;
+ temp = HDatoi(argv[u + 1]);
+ if(temp < 0)
+ usage();
+ else
+ random_seed = (unsigned)temp;
+ u += 2;
+ break;
+
+ /* # of seconds between polling */
+ case 's':
+ poll_time = HDatoi(argv[u + 1]);
+ if(poll_time < 0)
+ usage();
+ u += 2;
+ break;
+
+ default:
+ usage();
+ break;
+ } /* end switch */
+ } /* end if */
+ else {
+ /* Get the number of records to append */
+ nseconds = HDatol(argv[u]);
+ if(nseconds <= 0)
+ usage();
+
+ u++;
+ } /* end else */
+ } /* end while */
+ } /* end if */
+ if(nseconds <= 0)
+ usage();
+ if(poll_time >= nseconds)
+ usage();
+
+ /* Emit informational message */
+ if(verbose) {
+ HDfprintf(stderr, "READER: Parameters:\n");
+ HDfprintf(stderr, "\t# of seconds between polling = %d\n", poll_time);
+ HDfprintf(stderr, "\t# of common symbols to poll = %d\n", ncommon);
+ HDfprintf(stderr, "\t# of random symbols to poll = %d\n", nrandom);
+ HDfprintf(stderr, "\t# of seconds to test = %ld\n", nseconds);
+ } /* end if */
+
+ /* Set the random seed */
+ if(0 == use_seed) {
+ struct timeval t;
+ HDgettimeofday(&t, NULL);
+ random_seed = (unsigned)(t.tv_usec);
+ } /* end if */
+ HDsrandom(random_seed);
+ /* ALWAYS emit the random seed for possible debugging */
+ HDfprintf(stderr, "READER: Using reader random seed: %u\n", random_seed);
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "READER: Generating symbol names\n");
+
+ /* Generate dataset names */
+ if(generate_symbols() < 0) {
+ HDfprintf(stderr, "READER: Error generating symbol names!\n");
+ HDexit(1);
+ } /* end if */
+
+ /* Create datatype for creating datasets */
+ if((symbol_tid = create_symbol_datatype()) < 0)
+ return -1;
+
+ /* Reading records from datasets */
+ if(read_records(COMMON_FILENAME, verbose, (unsigned long)nseconds, (unsigned)poll_time, (unsigned)ncommon, (unsigned)nrandom) < 0) {
+ HDfprintf(stderr, "READER: Error reading records from datasets!\n");
+ HDexit(1);
+ } /* end if */
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "READER: Releasing symbols\n");
+
+ /* Clean up the symbols */
+ if(shutdown_symbols() < 0) {
+ HDfprintf(stderr, "READER: Error releasing symbols!\n");
+ HDexit(1);
+ } /* end if */
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "READER: Closing objects\n");
+
+ /* Close objects created */
+ if(H5Tclose(symbol_tid) < 0) {
+ HDfprintf(stderr, "READER: Error closing symbol datatype!\n");
+ HDexit(1);
+ } /* end if */
+
+ return 0;
+}
diff --git a/test/vfd_swmr_remove_writer.c b/test/vfd_swmr_remove_writer.c
new file mode 100644
index 0000000..2ebe96f
--- /dev/null
+++ b/test/vfd_swmr_remove_writer.c
@@ -0,0 +1,426 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: vfd_swmr_remove_writer.c
+ * (copied and modified from swmr_remove_writer.c)
+ *
+ * Purpose: Removes data from a randomly selected subset of the datasets
+ * in the VFD SWMR test file.
+ *
+ * This program is intended to run concurrently with the
+ * vfd_swmr_remove_reader program. It is also run AFTER a sequential
+ * (not concurrent!) invoking of vfd_swmr_writer so the writer
+ * can dump a bunch of data into the datasets. Otherwise,
+ * there wouldn't be much to shrink :)
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/***********/
+/* Headers */
+/***********/
+
+#include "h5test.h"
+#include "vfd_swmr_common.h"
+
+/****************/
+/* Local Macros */
+/****************/
+
+/* The maximum number of records to remove in one step */
+#define MAX_REMOVE_SIZE 10
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+static hid_t open_skeleton(const char *filename, unsigned verbose, unsigned old);
+static int remove_records(hid_t fid, unsigned verbose, unsigned long nshrinks,
+ unsigned long flush_count);
+static void usage(void);
+
+
+/*-------------------------------------------------------------------------
+ * Function: open_skeleton
+ *
+ * Purpose: Opens the SWMR HDF5 file and datasets.
+ *
+ * Parameters: const char *filename
+ * The filename of the SWMR HDF5 file to open
+ *
+ * unsigned verbose
+ * Whether or not to emit verbose console messages
+ *
+ * Return: Success: The file ID of the opened SWMR file
+ * The dataset IDs are stored in a global array
+ *
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static hid_t
+open_skeleton(const char *filename, unsigned verbose,
+ unsigned old H5_ATTR_UNUSED)
+{
+ hid_t fid = -1; /* File ID for new HDF5 file */
+ hid_t fapl = -1; /* File access property list */
+ hid_t sid = -1; /* Dataspace ID */
+ hsize_t dim[2]; /* Dataspace dimensions */
+ unsigned u, v; /* Local index variable */
+ H5F_vfd_swmr_config_t *config = NULL; /* Configuration for VFD SWMR */
+
+ HDassert(filename);
+
+ /* Create file access property list */
+ if((fapl = h5_fileaccess()) < 0)
+ goto error;
+
+ /* FOR NOW: set to use latest format, the "old" parameter is not used */
+ if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
+ goto error;
+
+ /*
+ * Set up to open the file with VFD SWMR configured.
+ */
+
+ /* Enable page buffering */
+ if(H5Pset_page_buffer_size(fapl, 4096, 0, 0) < 0)
+ goto error;
+
+ /* Allocate memory for the configuration structure */
+ if((config = (H5F_vfd_swmr_config_t *)HDcalloc(1, sizeof(H5F_vfd_swmr_config_t))) == NULL)
+ goto error;
+
+ config->version = H5F__CURR_VFD_SWMR_CONFIG_VERSION;
+ config->tick_len = 4;
+ config->max_lag = 5;
+ config->writer = TRUE;
+ config->md_pages_reserved = 128;
+ HDstrcpy(config->md_file_path, "./my_md_file");
+
+ /* Enable VFD SWMR configuration */
+ if(H5Pset_vfd_swmr_config(fapl, config) < 0)
+ goto error;
+
+ /* Open the file */
+ if((fid = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
+ goto error;
+
+ /* Close file access property list */
+ if(H5Pclose(fapl) < 0)
+ goto error;
+
+ if(config)
+ HDfree(config);
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "WRITER: Opening datasets\n");
+
+ /* Open the datasets */
+ for(u = 0; u < NLEVELS; u++)
+ for(v = 0; v < symbol_count[u]; v++) {
+ if((symbol_info[u][v].dsid = H5Dopen2(fid, symbol_info[u][v].name, H5P_DEFAULT)) < 0)
+ goto error;
+ if((sid = H5Dget_space(symbol_info[u][v].dsid)) < 0)
+ goto error;
+ if(2 != H5Sget_simple_extent_ndims(sid))
+ goto error;
+ if(H5Sget_simple_extent_dims(sid, dim, NULL) < 0)
+ goto error;
+ symbol_info[u][v].nrecords = dim[1];
+
+ if(H5Sclose(sid) < 0)
+ goto error;
+ } /* end for */
+
+ return fid;
+
+error:
+ if(config)
+ HDfree(config);
+
+ H5E_BEGIN_TRY {
+ for(u = 0; u < NLEVELS; u++)
+ for(v = 0; v < symbol_count[u]; v++)
+ H5Dclose(symbol_info[u][v].dsid);
+ H5Sclose(sid);
+ H5Pclose(fapl);
+ H5Fclose(fid);
+ } H5E_END_TRY;
+
+ return -1;
+
+} /* open_skeleton() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: remove_records
+ *
+ * Purpose: Removes a specified number of records from random datasets in
+ * the SWMR test file.
+ *
+ * Parameters: hid_t fid
+ * The file ID of the SWMR HDF5 file
+ *
+ * unsigned verbose
+ * Whether or not to emit verbose console messages
+ *
+ * unsigned long nshrinks
+ * # of records to remove from the datasets
+ *
+ * unsigned long flush_count
+ * # of records to write before flushing the file to disk
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+remove_records(hid_t fid, unsigned verbose, unsigned long nshrinks, unsigned long flush_count)
+{
+ unsigned long shrink_to_flush; /* # of removals before flush */
+ hsize_t dim[2] = {1,0}; /* Dataspace dimensions */
+ unsigned long u, v; /* Local index variables */
+
+ HDassert(fid >= 0);
+
+ /* Remove records from random datasets, according to frequency distribution */
+ shrink_to_flush = flush_count;
+ for(u = 0; u < nshrinks; u++) {
+ symbol_info_t *symbol; /* Symbol to remove record from */
+ hsize_t remove_size; /* Size to reduce dataset dimension by */
+
+ /* Get a random dataset, according to the symbol distribution */
+ symbol = choose_dataset(NULL, NULL);
+
+ /* Shrink the dataset's dataspace */
+ remove_size = (hsize_t)HDrandom() % MAX_REMOVE_SIZE + 1;
+ if(remove_size > symbol->nrecords)
+ symbol->nrecords = 0;
+ else
+ symbol->nrecords -= remove_size;
+ dim[1] = symbol->nrecords;
+ if(H5Dset_extent(symbol->dsid, dim) < 0)
+ goto error;
+
+ /* Check for flushing file */
+ if(flush_count > 0) {
+ /* Decrement count of records to write before flushing */
+ shrink_to_flush--;
+
+ /* Check for counter being reached */
+ if(0 == shrink_to_flush) {
+#ifdef TEMP_OUT
+ /* Flush contents of file */
+ if(H5Fflush(fid, H5F_SCOPE_GLOBAL) < 0)
+ return -1;
+#endif
+
+ /* Reset flush counter */
+ shrink_to_flush = flush_count;
+ } /* end if */
+ } /* end if */
+ } /* end for */
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "WRITER: Closing datasets\n");
+
+ /* Close the datasets */
+ for(u = 0; u < NLEVELS; u++)
+ for(v = 0; v < symbol_count[u]; v++)
+ if(H5Dclose(symbol_info[u][v].dsid) < 0)
+ goto error;
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ for(u = 0; u < NLEVELS; u++)
+ for(v = 0; v < symbol_count[u]; v++)
+ H5Dclose(symbol_info[u][v].dsid);
+
+ } H5E_END_TRY;
+
+ return -1;
+} /* remove_records() */
+
+static void
+usage(void)
+{
+ printf("\n");
+ printf("Usage error!\n");
+ printf("\n");
+ printf("Usage: swmr_remove_writer [-q] [-o] [-f <# of shrinks between flushing\n");
+ printf(" file contents>] [-r <random seed>] <# of shrinks>\n");
+ printf("\n");
+ printf("<# of shrinks between flushing file contents> should be 0 (for no\n");
+ printf("flushing) or between 1 and (<# of shrinks> - 1)\n");
+ printf("\n");
+ printf("Defaults to verbose (no '-q' given), latest format when opening file (no '-o' given),\n");
+ printf("flushing every 1000 shrinks ('-f 1000'), and will generate a random seed (no -r given).\n");
+ printf("\n");
+ HDexit(1);
+} /* usage() */
+
+int main(int argc, const char *argv[])
+{
+ sigset_t oldset;
+ hid_t fid; /* File ID for file opened */
+ long nshrinks = 0; /* # of times to shrink the dataset */
+ long flush_count = 1000; /* # of records to write between flushing file */
+ unsigned verbose = 1; /* Whether to emit some informational messages */
+ unsigned old = 0; /* Whether to use non-latest-format when opening file */
+ unsigned use_seed = 0; /* Set to 1 if a seed was set on the command line */
+ unsigned random_seed = 0; /* Random # seed */
+ unsigned u; /* Local index variable */
+ int temp;
+
+ block_signals(&oldset);
+
+ /* Parse command line options */
+ if(argc < 2)
+ usage();
+ if(argc > 1) {
+ u = 1;
+ while(u < (unsigned)argc) {
+ if(argv[u][0] == '-') {
+ switch(argv[u][1]) {
+ /* # of records to write between flushing file */
+ case 'f':
+ flush_count = HDatol(argv[u + 1]);
+ if(flush_count < 0)
+ usage();
+ u += 2;
+ break;
+
+ /* Be quiet */
+ case 'q':
+ verbose = 0;
+ u++;
+ break;
+
+ /* Random # seed */
+ case 'r':
+ use_seed = 1;
+ temp = HDatoi(argv[u + 1]);
+ random_seed = (unsigned)temp;
+ u += 2;
+ break;
+
+ /* Use non-latest-format when opening file */
+ case 'o':
+ old = 1;
+ u++;
+ break;
+
+ default:
+ usage();
+ break;
+ } /* end switch */
+ } /* end if */
+ else {
+ /* Get the number of records to append */
+ nshrinks = HDatol(argv[u]);
+ if(nshrinks <= 0)
+ usage();
+
+ u++;
+ } /* end else */
+ } /* end while */
+ } /* end if */
+ if(nshrinks <= 0)
+ usage();
+ if(flush_count >= nshrinks)
+ usage();
+
+ /* Emit informational message */
+ if(verbose) {
+ HDfprintf(stderr, "WRITER: Parameters:\n");
+ HDfprintf(stderr, "\t# of shrinks between flushes = %ld\n", flush_count);
+ HDfprintf(stderr, "\t# of shrinks = %ld\n", nshrinks);
+ } /* end if */
+
+ /* Set the random seed */
+ if(0 == use_seed) {
+ struct timeval t;
+ HDgettimeofday(&t, NULL);
+ random_seed = (unsigned)(t.tv_usec);
+ } /* end if */
+ HDsrandom(random_seed);
+ /* ALWAYS emit the random seed for possible debugging */
+ HDfprintf(stderr, "WRITER: Using writer random seed: %u\n", random_seed);
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "WRITER: Generating symbol names\n");
+
+ /* Generate dataset names */
+ if(generate_symbols() < 0)
+ return -1;
+
+ /* Emit informational message */
+ if(verbose) {
+ HDfprintf(stderr, "WRITER: Opening skeleton file: %s\n",
+ COMMON_FILENAME);
+ }
+
+ /* Open file skeleton */
+ if((fid = open_skeleton(COMMON_FILENAME, verbose, old)) < 0) {
+ HDfprintf(stderr, "WRITER: Error opening skeleton file!\n");
+ HDexit(1);
+ } /* end if */
+
+ /* Send a message to indicate "H5Fopen" is complete--releasing the file lock */
+ h5_send_message(WRITER_MESSAGE, NULL, NULL);
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "WRITER: Removing records\n");
+
+ /* Remove records from datasets */
+ if(remove_records(fid, verbose, (unsigned long)nshrinks, (unsigned long)flush_count) < 0) {
+ HDfprintf(stderr, "WRITER: Error removing records from datasets!\n");
+ HDexit(1);
+ } /* end if */
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "WRITER: Releasing symbols\n");
+
+ /* Clean up the symbols */
+ if(shutdown_symbols() < 0) {
+ HDfprintf(stderr, "WRITER: Error releasing symbols!\n");
+ HDexit(1);
+ } /* end if */
+
+ await_signal(fid);
+
+ restore_signals(&oldset);
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "WRITER: Closing objects\n");
+
+ /* Close objects opened */
+ if(H5Fclose(fid) < 0) {
+ HDfprintf(stderr, "WRITER: Error closing file!\n");
+ HDexit(1);
+ } /* end if */
+
+ return 0;
+} /* main() */
diff --git a/test/vfd_swmr_sparse_reader.c b/test/vfd_swmr_sparse_reader.c
new file mode 100644
index 0000000..83fb886
--- /dev/null
+++ b/test/vfd_swmr_sparse_reader.c
@@ -0,0 +1,535 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: vfd_swmr_sparse_reader.c
+ * (copied and modified from swmr_sparse_reader.c)
+ *
+ * Purpose: Reads data from a randomly selected subset of the datasets
+ * in the VFD SWMR test file. Unlike the regular reader, these
+ * datasets will be shrinking.
+ *
+ * This program is intended to run concurrently with the
+ * vfd_swmr_sparse_writer program.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/***********/
+/* Headers */
+/***********/
+
+#include <inttypes.h> /* for PRIu64 */
+
+#include "h5test.h"
+#include "vfd_swmr_common.h"
+
+/****************/
+/* Local Macros */
+/****************/
+
+#define TIMEOUT 30
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+static hid_t symbol_tid = (-1);
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+static int check_dataset(hid_t fid, unsigned verbose, const symbol_info_t *symbol,
+ symbol_t *record, hid_t rec_sid);
+static int read_records(const char *filename, unsigned verbose, unsigned long nrecords,
+ unsigned poll_time, unsigned reopen_count);
+static void usage(void);
+
+
+/*-------------------------------------------------------------------------
+ * Function: check_dataset
+ *
+ * Purpose: For a given dataset, checks to make sure that the stated
+ * and actual sizes are the same. If they are not, then
+ * we have an inconsistent dataset due to a SWMR error.
+ *
+ * Parameters: hid_t fid
+ * The SWMR test file's ID.
+ *
+ * unsigned verbose
+ * Whether verbose console output is desired.
+ *
+ * const symbol_info_t *symbol
+ * The dataset from which to read (the ID is in the struct).
+ * Must be pre-allocated.
+ *
+ * symbol_t *record
+ * Memory for the record. Must be pre-allocated.
+ *
+ * hid_t rec_sid
+ * The memory dataspace for access. It's always the same so
+ * there is no need to re-create it every time this function
+ * is called.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+check_dataset(hid_t fid, unsigned verbose, const symbol_info_t *symbol, symbol_t *record,
+ hid_t rec_sid)
+{
+ hid_t dsid = -1; /* Dataset ID */
+ hid_t file_sid = -1; /* Dataset's space ID */
+ hsize_t start[2] = {0, 0}; /* Hyperslab selection values */
+ hsize_t count[2] = {1, 1}; /* Hyperslab selection values */
+
+ HDassert(fid >= 0);
+ HDassert(symbol);
+ HDassert(record);
+ HDassert(rec_sid >= 0);
+
+ /* Open dataset for symbol */
+ if((dsid = H5Dopen2(fid, symbol->name, H5P_DEFAULT)) < 0)
+ goto error;
+
+ /* Get the dataset's dataspace */
+ if((file_sid = H5Dget_space(dsid)) < 0)
+ goto error;
+
+ /* Choose the random record in the dataset (will be the same as chosen by
+ * the writer) */
+ start[1] = (hsize_t)HDrandom() % symbol->nrecords;
+ if(H5Sselect_hyperslab(file_sid, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ goto error;
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "READER: Symbol = '%s', nrecords = %Hu, name = %s, location = %Hu, %Hu\n", \
+ symbol->name, symbol->nrecords, symbol->name, start[0], start[1]);
+
+ /* Read record from dataset */
+ record->rec_id = UINT64_MAX;
+ if(H5Dread(dsid, symbol_tid, rec_sid, file_sid, H5P_DEFAULT, record) < 0)
+ goto error;
+
+ /* Verify record value */
+ if(record->rec_id != start[1]) {
+ HDfprintf(stderr, "*** READER: ERROR ***\n");
+ HDfprintf(stderr, "Incorrect record value!\n");
+ HDfprintf(stderr, "Symbol = '%s', location = %Hu, %Hu, record->rec_id = %" PRIu64 "\n", symbol->name, start[0], start[1], record->rec_id);
+ goto error;
+ } /* end if */
+
+ /* Close the dataset's dataspace */
+ if(H5Sclose(file_sid) < 0)
+ goto error;
+
+ /* Close dataset for symbol */
+ if(H5Dclose(dsid) < 0)
+ goto error;
+
+ return 0;
+
+error:
+
+ H5E_BEGIN_TRY {
+ H5Sclose(file_sid);
+ H5Dclose(dsid);
+ } H5E_END_TRY;
+
+ return -1;
+} /* end check_dataset() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: read_records
+ *
+ * Purpose: For a given dataset, checks to make sure that the stated
+ * and actual sizes are the same. If they are not, then
+ * we have an inconsistent dataset due to a SWMR error.
+ *
+ * Parameters: const char *filename
+ * The SWMR test file's name.
+ *
+ * unsigned verbose
+ * Whether verbose console output is desired.
+ *
+ * unsigned long nrecords
+ * The total number of records to read.
+ *
+ * unsigned poll_time
+ * The amount of time to sleep (s).
+ *
+ * unsigned reopen_count
+ *
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+read_records(const char *filename, unsigned verbose, unsigned long nrecords,
+ unsigned poll_time, unsigned reopen_count)
+{
+ hid_t fid = H5I_INVALID_HID;
+ hid_t aid = H5I_INVALID_HID;
+ time_t start_time; /* Starting time */
+ hid_t mem_sid = H5I_INVALID_HID;
+ symbol_t record; /* The record to add to the dataset */
+ unsigned seed; /* Seed for random number generator */
+ unsigned iter_to_reopen = reopen_count; /* # of iterations until reopen */
+ unsigned long u; /* Local index variable */
+ hid_t fapl = H5I_INVALID_HID;
+ H5F_vfd_swmr_config_t *config = NULL; /* Configuration for VFD SWMR */
+
+ HDassert(filename);
+ HDassert(poll_time != 0);
+
+ /* Create file access property list */
+ if((fapl = h5_fileaccess()) < 0)
+ goto error;
+
+ if(H5Pset_fclose_degree(fapl, H5F_CLOSE_SEMI) < 0)
+ goto error;
+
+ /*
+ * Set up to open the file with VFD SWMR configured.
+ */
+ /* Enable page buffering */
+ if(H5Pset_page_buffer_size(fapl, 4096, 0, 0) < 0)
+ goto error;
+
+ /* Allocate memory for the configuration structure */
+ if((config = HDcalloc(1, sizeof(H5F_vfd_swmr_config_t))) == NULL)
+ goto error;
+
+ config->version = H5F__CURR_VFD_SWMR_CONFIG_VERSION;
+ config->tick_len = 4;
+ config->max_lag = 5;
+ config->writer = FALSE;
+ config->md_pages_reserved = 128;
+ HDstrcpy(config->md_file_path, "./my_md_file");
+
+ /* Enable VFD SWMR configuration */
+ if(H5Pset_vfd_swmr_config(fapl, config) < 0)
+ goto error;
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "READER: Opening file: %s\n", filename);
+
+ /* Open the file */
+ /* Remove H5E_BEGIN_TRY/END_TRY to see the error stack if error */
+ H5E_BEGIN_TRY {
+ fid = H5Fopen(filename, H5F_ACC_RDONLY, fapl);
+ } H5E_END_TRY;
+ if(fid < 0) {
+ HDfprintf(stderr, "READER: Error in opening the file: %s\n", filename);
+ goto error;
+ } else
+ HDfprintf(stderr, "READER: SUCCESS in opening the file: %s\n", filename);
+
+ /* Seed the random number generator with the attribute in the file */
+ if((aid = H5Aopen(fid, "seed", H5P_DEFAULT)) < 0)
+ goto error;
+ if(H5Aread(aid, H5T_NATIVE_UINT, &seed) < 0)
+ goto error;
+ if(H5Aclose(aid) < 0)
+ goto error;
+ HDsrandom(seed);
+
+ /* Reset the record */
+ /* (record's 'info' field might need to change for each record written, also) */
+ HDmemset(&record, 0, sizeof(record));
+
+ /* Create a dataspace for the record to read */
+ if((mem_sid = H5Screate(H5S_SCALAR)) < 0)
+ goto error;
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "READER: Reading records\n");
+
+ /* Read records */
+ for(u = 0; u < nrecords; u++) {
+ unsigned level, offset;
+ symbol_info_t *symbol = NULL; /* Symbol (dataset) */
+ htri_t attr_exists; /* Whether the sequence number attribute exists */
+ unsigned long file_u; /* Attribute sequence number (writer's "u") */
+
+ /* Get a random dataset, according to the symbol distribution */
+ symbol = choose_dataset(&level, &offset);
+
+ /* Fill in "nrecords" field. Note that this depends on the writer
+ * using the same algorithm and "nrecords" */
+ symbol->nrecords = nrecords / 5;
+
+ /* Get the starting time */
+ if ((start_time = HDtime(NULL)) == (time_t)-1) {
+ fprintf(stderr, "READER: could not read time.\n");
+ goto error;
+ }
+
+ /* Wait until we can read the dataset */
+ for (;;) {
+ if((attr_exists = H5Aexists_by_name(fid, symbol->name, "seq", H5P_DEFAULT)) < 0)
+ goto error;
+
+ if(attr_exists) {
+ if((aid = H5Aopen_by_name(fid, symbol->name, "seq",
+ H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ goto error;
+ if(H5Aread(aid, H5T_NATIVE_ULONG, &file_u) < 0)
+ goto error;
+ if(H5Aclose(aid) < 0)
+ goto error;
+
+ if(file_u >= u)
+ break;
+ }
+
+ if(HDtime(NULL) >= (time_t)(start_time + (time_t)TIMEOUT)) {
+ HDfprintf(stderr,
+ "READER: Reader timed at record %lu level %u offset %u",
+ u, level, offset);
+ if (attr_exists) {
+ HDfprintf(stderr, ", read sequence %lu\n", file_u);
+ } else {
+ HDfprintf(stderr, ", read no sequence\n");
+ HDfprintf(stderr, ", read no sequence\n");
+ }
+ goto error;
+ }
+
+ HDsleep(poll_time);
+
+ if(verbose)
+ HDfprintf(stderr, "READER: Reopening file (do while loop): %s\n", filename);
+
+ if(print_metadata_retries_info(fid) < 0)
+ HDfprintf(stderr, "READER: Warning: could not obtain metadata retries info\n");
+
+ if(H5Fclose(fid) < 0)
+ goto error;
+
+ H5E_BEGIN_TRY {
+ fid = H5Fopen(filename, H5F_ACC_RDONLY, fapl);
+ } H5E_END_TRY;
+ if(fid < 0) {
+ HDfprintf(stderr, "READER: Error in reopening the file (do while loop): %s\n", filename);
+ goto error;
+ }
+ iter_to_reopen = reopen_count;
+ }
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "READER: Checking dataset %lu\n", u);
+
+ /* Check dataset */
+ if(check_dataset(fid, verbose, symbol, &record, mem_sid) < 0)
+ goto error;
+ HDmemset(&record, 0, sizeof(record));
+
+ /* Check for reopen */
+ iter_to_reopen--;
+ if(iter_to_reopen == 0) {
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "READER: Reopening file (iter_to_reopen): %s\n", filename);
+
+ /* Retrieve and print the collection of metadata read retries */
+ if(print_metadata_retries_info(fid) < 0)
+ HDfprintf(stderr, "READER: Warning: could not obtain metadata retries info\n");
+
+ /* Reopen the file */
+ if(H5Fclose(fid) < 0)
+ goto error;
+
+ /* Remove H5E_BEGIN_TRY/END_TRY to see the error stack if error */
+// H5E_BEGIN_TRY {
+ fid = H5Fopen(filename, H5F_ACC_RDONLY, fapl);
+ // } H5E_END_TRY;
+ if(fid < 0) {
+ HDfprintf(stderr, "READER: Error in reopening the file (iter_to_reopen): %s\n", filename);
+ goto error;
+ }
+
+ iter_to_reopen = reopen_count;
+ } /* end if */
+ } /* end while */
+
+ /* Retrieve and print the collection of metadata read retries */
+ if(print_metadata_retries_info(fid) < 0)
+ HDfprintf(stderr, "READER: Warning: could not obtain metadata retries info\n");
+
+ /* Close file */
+ if(H5Fclose(fid) < 0)
+ goto error;
+
+ /* Close the memory dataspace */
+ if(H5Sclose(mem_sid) < 0)
+ goto error;
+
+ /* Close the file access property list */
+ if(H5Pclose(fapl) < 0)
+ goto error;
+
+ if(config)
+ HDfree(config);
+
+ return 0;
+
+error:
+ if(config)
+ HDfree(config);
+
+ H5E_BEGIN_TRY {
+ H5Aclose(aid);
+ H5Sclose(mem_sid);
+ H5Fclose(fid);
+ H5Pclose(fapl);
+ } H5E_END_TRY;
+
+ return -1;
+} /* end read_records() */
+
+static void
+usage(void)
+{
+ printf("\n");
+ printf("Usage error!\n");
+ printf("\n");
+ printf("Usage: vfd_swmr_sparse_reader [-q] [-s <# of seconds to wait for writer>]\n");
+ printf(" [-n <# of reads between reopens>] <# of records>\n");
+ printf("\n");
+ printf("Defaults to verbose (no '-q' given), 1 second wait ('-s 1') and 1 read\n");
+ printf("between reopens ('-r 1')\n");
+ printf("\n");
+ printf("Note that the # of records *must* be the same as that supplied to\n");
+ printf("vfd_swmr_sparse_writer\n");
+ printf("\n");
+ HDexit(1);
+} /* end usage() */
+
+int main(int argc, const char *argv[])
+{
+ long nrecords = 0; /* # of records to read */
+ int poll_time = 1; /* # of seconds to sleep when waiting for writer */
+ int reopen_count = 1; /* # of reads between reopens */
+ unsigned verbose = 1; /* Whether to emit some informational messages */
+ unsigned u; /* Local index variables */
+
+ /* Parse command line options */
+ if(argc < 2)
+ usage();
+ if(argc > 1) {
+ u = 1;
+ while(u < (unsigned)argc) {
+ if(argv[u][0] == '-') {
+ switch(argv[u][1]) {
+ /* # of reads between reopens */
+ case 'n':
+ reopen_count = HDatoi(argv[u + 1]);
+ if(reopen_count < 0)
+ usage();
+ u += 2;
+ break;
+
+ /* Be quiet */
+ case 'q':
+ verbose = 0;
+ u++;
+ break;
+
+ /* # of seconds between polling */
+ case 's':
+ poll_time = HDatoi(argv[u + 1]);
+ if(poll_time < 0)
+ usage();
+ u += 2;
+ break;
+
+ default:
+ usage();
+ break;
+ } /* end switch */
+ } /* end if */
+ else {
+ /* Get the number of records to read */
+ nrecords = HDatol(argv[u]);
+ if(nrecords <= 0)
+ usage();
+
+ u++;
+ } /* end else */
+ } /* end while */
+ } /* end if */
+
+ /* Emit informational message */
+ if(verbose) {
+ HDfprintf(stderr, "READER: Parameters:\n");
+ HDfprintf(stderr, "\t# of seconds between polling = %d\n", poll_time);
+ HDfprintf(stderr, "\t# of reads between reopens = %d\n", reopen_count);
+ HDfprintf(stderr, "\t# of records to read = %ld\n", nrecords);
+ } /* end if */
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "READER: Generating symbol names\n");
+
+ /* Generate dataset names */
+ if(generate_symbols() < 0) {
+ HDfprintf(stderr, "READER: Error generating symbol names!\n");
+ HDexit(1);
+ } /* end if */
+
+ /* Create datatype for creating datasets */
+ if((symbol_tid = create_symbol_datatype()) < 0) {
+ HDfprintf(stderr, "READER: Error creating symbol datatype!\n");
+ HDexit(1);
+ }
+
+ /* Reading records from datasets */
+ if(read_records(COMMON_FILENAME, verbose, (unsigned long) nrecords, (unsigned)poll_time, (unsigned)reopen_count) < 0) {
+ HDfprintf(stderr, "READER: Error reading records from datasets!\n");
+ HDexit(1);
+ } /* end if */
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "READER: Releasing symbols\n");
+
+ /* Clean up the symbols */
+ if(shutdown_symbols() < 0) {
+ HDfprintf(stderr, "READER: Error releasing symbols!\n");
+ HDexit(1);
+ } /* end if */
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "READER: Closing objects\n");
+
+ /* Close objects created */
+ if(H5Tclose(symbol_tid) < 0) {
+ HDfprintf(stderr, "READER: Error closing symbol datatype!\n");
+ HDexit(1);
+ } /* end if */
+
+ return 0;
+} /* main() */
diff --git a/test/vfd_swmr_sparse_writer.c b/test/vfd_swmr_sparse_writer.c
new file mode 100644
index 0000000..5722558
--- /dev/null
+++ b/test/vfd_swmr_sparse_writer.c
@@ -0,0 +1,488 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+ /*-------------------------------------------------------------------------
+ *
+ * Created: vfd_swmr_sparse_writer.c
+ * (copied and modified from swmr_sparse_writer.c)
+ *
+ * Purpose: Writes data to a randomly selected subset of the datasets
+ * in the VFD_SWMR test file.
+ *
+ * This program is intended to run concurrently with the
+ * vfd_swmr_sparse_reader program.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/***********/
+/* Headers */
+/***********/
+#include <err.h>
+#include <signal.h>
+
+#include "h5test.h"
+#include "vfd_swmr_common.h"
+
+/****************/
+/* Local Macros */
+/****************/
+
+#ifdef OUT
+#define BUSY_WAIT 100000
+#endif /* OUT */
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+static hid_t open_skeleton(const char *filename, unsigned verbose);
+static int add_records(hid_t fid, unsigned verbose, unsigned long nrecords,
+ unsigned long flush_count);
+static void usage(void);
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: open_skeleton
+ *
+ * Purpose: Opens the SWMR HDF5 file and datasets.
+ *
+ * Parameters: const char *filename
+ * The filename of the SWMR HDF5 file to open
+ *
+ * unsigned verbose
+ * Whether or not to emit verbose console messages
+ *
+ * Return: Success: The file ID of the opened SWMR file
+ * The dataset IDs are stored in a global array
+ *
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static hid_t
+open_skeleton(const char *filename, unsigned verbose)
+{
+ hid_t fid = -1; /* File ID for new HDF5 file */
+ hid_t fapl = -1; /* File access property list */
+ hid_t aid = -1; /* Attribute ID */
+ unsigned seed; /* Seed for random number generator */
+ unsigned u, v; /* Local index variable */
+ H5F_vfd_swmr_config_t *config = NULL; /* Configuration for VFD SWMR */
+
+ HDassert(filename);
+
+ /* Create file access property list */
+ if((fapl = h5_fileaccess()) < 0)
+ goto error;
+
+ /* Set to use the latest library format */
+ if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
+ goto error;
+
+ /*
+ * Set up to open the file with VFD SWMR configured.
+ */
+
+ /* Enable page buffering */
+ if(H5Pset_page_buffer_size(fapl, 4096, 0, 0) < 0)
+ goto error;
+
+ /* Allocate memory for the configuration structure */
+ if((config = (H5F_vfd_swmr_config_t *)HDcalloc(1, sizeof(H5F_vfd_swmr_config_t))) == NULL)
+ goto error;
+
+ config->version = H5F__CURR_VFD_SWMR_CONFIG_VERSION;
+ config->tick_len = 4;
+ config->max_lag = 5;
+ config->writer = TRUE;
+ config->md_pages_reserved = 128;
+ HDstrcpy(config->md_file_path, "./my_md_file");
+
+ /* Enable VFD SWMR configuration */
+ if(H5Pset_vfd_swmr_config(fapl, config) < 0)
+ goto error;
+
+ /* Open the file */
+ if((fid = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
+ goto error;
+
+ /* Close file access property list */
+ if(H5Pclose(fapl) < 0)
+ goto error;
+
+ if(config)
+ HDfree(config);
+
+ /* Emit informational message */
+ if(verbose)
+ fprintf(stderr, "WRITER: Opening datasets\n");
+
+ /* Seed the random number generator with the attribute in the file */
+ if((aid = H5Aopen(fid, "seed", H5P_DEFAULT)) < 0)
+ goto error;
+ if(H5Aread(aid, H5T_NATIVE_UINT, &seed) < 0)
+ goto error;
+ if(H5Aclose(aid) < 0)
+ goto error;
+ HDsrandom(seed);
+
+ /* Open the datasets */
+ for(u = 0; u < NLEVELS; u++)
+ for(v = 0; v < symbol_count[u]; v++) {
+ if((symbol_info[u][v].dsid = H5Dopen2(fid, symbol_info[u][v].name, H5P_DEFAULT)) < 0)
+ return(-1);
+ symbol_info[u][v].nrecords = 0;
+ } /* end for */
+
+ return fid;
+
+error:
+ if(config)
+ HDfree(config);
+
+ H5E_BEGIN_TRY {
+ for(u = 0; u < NLEVELS; u++)
+ for(v = 0; v < symbol_count[u]; v++)
+ H5Dclose(symbol_info[u][v].dsid);
+ H5Aclose(aid);
+ H5Pclose(fapl);
+ H5Fclose(fid);
+ } H5E_END_TRY;
+
+ return -1;
+
+} /* open_skeleton() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: add_records
+ *
+ * Purpose: Writes a specified number of records to random datasets in
+ * the SWMR test file.
+ *
+ * Parameters: hid_t fid
+ * The file ID of the SWMR HDF5 file
+ *
+ * unsigned verbose
+ * Whether or not to emit verbose console messages
+ *
+ * unsigned long nrecords
+ * # of records to write to the datasets
+ *
+ * unsigned long flush_count
+ * # of records to write before flushing the file to disk
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+add_records(hid_t fid, unsigned verbose, unsigned long nrecords, unsigned long flush_count)
+{
+ hid_t tid = -1; /* Datatype ID for records */
+ hid_t mem_sid = -1; /* Memory dataspace ID */
+ hid_t file_sid = -1; /* Dataset's space ID */
+ hid_t aid = -1; /* Attribute ID */
+ hsize_t start[2] = {0, 0}; /* Hyperslab selection values */
+ hsize_t count[2] = {1, 1}; /* Hyperslab selection values */
+ symbol_t record; /* The record to add to the dataset */
+ unsigned long rec_to_flush; /* # of records left to write before flush */
+#ifdef OUT
+ volatile int dummy; /* Dummy varialbe for busy sleep */
+#endif /* OUT */
+ hsize_t dim[2] = {1,0}; /* Dataspace dimensions */
+ unsigned long u, v; /* Local index variables */
+
+ HDassert(fid >= 0);
+
+ /* Reset the record */
+ /* (record's 'info' field might need to change for each record written, also) */
+ HDmemset(&record, 0, sizeof(record));
+
+ /* Create a dataspace for the record to add */
+ if((mem_sid = H5Screate(H5S_SCALAR)) < 0)
+ goto error;
+
+ /* Create datatype for appending records */
+ if((tid = create_symbol_datatype()) < 0)
+ goto error;
+
+ /* Add records to random datasets, according to frequency distribution */
+ rec_to_flush = flush_count;
+ for(u = 0; u < nrecords; u++) {
+ symbol_info_t *symbol; /* Symbol to write record to */
+
+ /* Get a random dataset, according to the symbol distribution */
+ symbol = choose_dataset(NULL, NULL);
+
+ /* If this is the first time the dataset has been opened, extend it and
+ * add the sequence attribute */
+ if(symbol->nrecords == 0) {
+ symbol->nrecords = nrecords / 5;
+ dim[1] = symbol->nrecords;
+
+ if(H5Dset_extent(symbol->dsid, dim) < 0)
+ goto error;
+
+ if((file_sid = H5Screate(H5S_SCALAR)) < 0)
+ goto error;
+ if((aid = H5Acreate2(symbol->dsid, "seq", H5T_NATIVE_ULONG, file_sid, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ goto error;
+ if(H5Sclose(file_sid) < 0)
+ goto error;
+ } else if ((aid = H5Aopen(symbol->dsid, "seq", H5P_DEFAULT)) < 0)
+ goto error;
+
+ /* Get the coordinate to write */
+ start[1] = (hsize_t)HDrandom() % symbol->nrecords;
+
+ /* Set the record's ID (equal to its position) */
+ record.rec_id = start[1];
+
+ /* Get the dataset's dataspace */
+ if((file_sid = H5Dget_space(symbol->dsid)) < 0)
+ goto error;
+
+ /* Choose a random record in the dataset */
+ if(H5Sselect_hyperslab(file_sid, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ goto error;
+
+ /* Write record to the dataset */
+ if(H5Dwrite(symbol->dsid, tid, mem_sid, file_sid, H5P_DEFAULT, &record) < 0)
+ goto error;
+
+ /* Write the sequence number attribute. Since we synchronize the random
+ * number seed, the readers will always generate the same sequence of
+ * randomly chosen datasets and offsets. Therefore, and because of the
+ * flush dependencies on the object header, the reader will be
+ * guaranteed to see the written data if the sequence attribute is >=u.
+ */
+ if(H5Awrite(aid, H5T_NATIVE_ULONG, &u) < 0)
+ goto error;
+
+ /* Close the attribute */
+ if(H5Aclose(aid) < 0)
+ goto error;
+
+ /* Close the dataset's dataspace */
+ if(H5Sclose(file_sid) < 0)
+ goto error;
+
+ /* Check for flushing file */
+ if(flush_count > 0) {
+ /* Decrement count of records to write before flushing */
+ rec_to_flush--;
+
+ /* Check for counter being reached */
+ if(0 == rec_to_flush) {
+#ifdef TEMP_OUT
+ /* Flush contents of file */
+ if(H5Fflush(fid, H5F_SCOPE_GLOBAL) < 0)
+ return -1;
+#endif
+
+ /* Reset flush counter */
+ rec_to_flush = flush_count;
+ } /* end if */
+ } /* end if */
+
+#ifdef OUT
+ /* Busy wait, to let readers catch up */
+ /* If this is removed, also remove the BUSY_WAIT symbol
+ * at the top of the file.
+ */
+ dummy = 0;
+ for(v=0; v<BUSY_WAIT; v++)
+ dummy++;
+ if((unsigned long)dummy != v)
+ return -1;
+#endif /* OUT */
+
+ } /* end for */
+
+ /* Close the memory dataspace */
+ if(H5Sclose(mem_sid) < 0)
+ goto error;
+
+ /* Close the datatype */
+ if(H5Tclose(tid) < 0)
+ goto error;
+
+ /* Emit informational message */
+ if(verbose)
+ fprintf(stderr, "WRITER: Closing datasets\n");
+
+ /* Close the datasets */
+ for(u = 0; u < NLEVELS; u++)
+ for(v = 0; v < symbol_count[u]; v++)
+ if(H5Dclose(symbol_info[u][v].dsid) < 0)
+ goto error;
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Sclose(mem_sid);
+ H5Sclose(file_sid);
+ H5Tclose(tid);
+ H5Aclose(aid);
+
+ for(u = 0; u < NLEVELS; u++)
+ for(v = 0; v < symbol_count[u]; v++)
+ H5Dclose(symbol_info[u][v].dsid);
+
+ } H5E_END_TRY;
+
+ return -1;
+} /* add_records() */
+
+static void
+usage(void)
+{
+ printf("\n");
+ printf("Usage error!\n");
+ printf("\n");
+ printf("Usage: vfd_swmr_sparse_writer [-q] [-f <# of records to write between\n");
+ printf(" flushing file contents>] <# of records>\n");
+ printf("\n");
+ printf("<# of records to write between flushing file contents> should be 0\n");
+ printf("(for no flushing) or between 1 and (<# of records> - 1)\n");
+ printf("\n");
+ printf("Defaults to verbose (no '-q' given) and flushing every 1000 records\n");
+ printf("('-f 1000')\n");
+ printf("\n");
+ HDexit(1);
+} /* usage() */
+
+int main(int argc, const char *argv[])
+{
+ sigset_t oldset;
+ hid_t fid; /* File ID for file opened */
+ long nrecords = 0; /* # of records to append */
+ long flush_count = 1000; /* # of records to write between flushing file */
+ unsigned verbose = 1; /* Whether to emit some informational messages */
+ unsigned u; /* Local index variable */
+
+ block_signals(&oldset);
+
+ /* Parse command line options */
+ if(argc < 2)
+ usage();
+ if(argc > 1) {
+ u = 1;
+ while(u < (unsigned)argc) {
+ if(argv[u][0] == '-') {
+ switch(argv[u][1]) {
+ /* # of records to write between flushing file */
+ case 'f':
+ flush_count = HDatol(argv[u + 1]);
+ if(flush_count < 0)
+ usage();
+ u += 2;
+ break;
+
+ /* Be quiet */
+ case 'q':
+ verbose = 0;
+ u++;
+ break;
+
+ default:
+ usage();
+ break;
+ } /* end switch */
+ } /* end if */
+ else {
+ /* Get the number of records to append */
+ nrecords = HDatol(argv[u]);
+ if(nrecords <= 0)
+ usage();
+
+ u++;
+ } /* end else */
+ } /* end while */
+ } /* end if */
+ if(nrecords <= 0)
+ usage();
+ if(flush_count >= nrecords)
+ usage();
+
+ /* Emit informational message */
+ if(verbose) {
+ HDfprintf(stderr, "WRITER: Parameters:\n");
+ HDfprintf(stderr, "\t# of records between flushes = %ld\n", flush_count);
+ HDfprintf(stderr, "\t# of records to write = %ld\n", nrecords);
+ } /* end if */
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "WRITER: Generating symbol names\n");
+
+ /* Generate dataset names */
+ if(generate_symbols() < 0)
+ return -1;
+
+ /* Emit informational message */
+ if(verbose) {
+ HDfprintf(stderr, "WRITER: Opening skeleton file: %s\n",
+ COMMON_FILENAME);
+ }
+
+ /* Open file skeleton */
+ if((fid = open_skeleton(COMMON_FILENAME, verbose)) < 0) {
+ HDfprintf(stderr, "WRITER: Error opening skeleton file!\n");
+ HDexit(1);
+ } /* end if */
+
+ /* Send a message to indicate "H5Fopen" is complete--releasing the file lock */
+ h5_send_message(WRITER_MESSAGE, NULL, NULL);
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "WRITER: Adding records\n");
+
+ /* Append records to datasets */
+ if(add_records(fid, verbose, (unsigned long)nrecords, (unsigned long)flush_count) < 0) {
+ HDfprintf(stderr, "WRITER: Error appending records to datasets!\n");
+ HDexit(1);
+ } /* end if */
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "WRITER: Releasing symbols\n");
+
+ /* Clean up the symbols */
+ if(shutdown_symbols() < 0) {
+ HDfprintf(stderr, "WRITER: Error releasing symbols!\n");
+ HDexit(1);
+ } /* end if */
+
+ await_signal(fid);
+
+ restore_signals(&oldset);
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(stderr, "WRITER: Closing objects/file\n");
+
+ /* Close objects opened */
+ if(H5Fclose(fid) < 0) {
+ HDfprintf(stderr, "WRITER: Error closing file!\n");
+ HDexit(1);
+ } /* end if */
+
+ return 0;
+} /* main() */
diff --git a/test/vfd_swmr_vlstr_reader.c b/test/vfd_swmr_vlstr_reader.c
new file mode 100644
index 0000000..df9037729
--- /dev/null
+++ b/test/vfd_swmr_vlstr_reader.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright by The HDF Group.
+ * Copyright by the Board of Trustees of the University of Illinois.
+ * All rights reserved.
+ *
+ * This file is part of HDF5. The full HDF5 copyright notice, including
+ * terms governing use, modification, and redistribution, is contained in
+ * the COPYING file, which can be found at the root of the source code
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases.
+ * If you do not have access to either file, you may request a copy from
+ * help@hdfgroup.org.
+ */
+
+#include <err.h>
+#include <time.h> /* nanosleep(2) */
+#include <unistd.h> /* getopt(3) */
+
+#define H5C_FRIEND /*suppress error about including H5Cpkg */
+#define H5F_FRIEND /*suppress error about including H5Fpkg */
+
+#include "hdf5.h"
+
+#include "H5Cpkg.h"
+#include "H5Fpkg.h"
+// #include "H5Iprivate.h"
+#include "H5HGprivate.h"
+#include "H5VLprivate.h"
+
+#include "testhdf5.h"
+#include "vfd_swmr_common.h"
+
+typedef enum _step {
+ CREATE = 0
+, LENGTHEN
+, SHORTEN
+, DELETE
+, NSTEPS
+} step_t;
+
+static const hid_t badhid = H5I_INVALID_HID; // abbreviate
+static bool caught_out_of_bounds = false;
+static bool read_null = false;
+
+static bool
+read_vl_dset(hid_t dset, hid_t type, char **data)
+{
+ bool success;
+ estack_state_t es;
+
+ es = disable_estack();
+ success = H5Dread(dset, type, H5S_ALL, H5S_ALL, H5P_DEFAULT, data) >= 0;
+ if (*data == NULL) {
+ read_null = true;
+ return false;
+ }
+ restore_estack(es);
+
+ return success;
+}
+
+static void
+usage(const char *progname)
+{
+ fprintf(stderr, "usage: %s [-W] [-V] [-t (oob|null)] \n", progname);
+ fprintf(stderr, "\n -S: do not use VFD SWMR\n");
+ fprintf(stderr, " -n: number of test steps to perform\n");
+ fprintf(stderr, " -q: be quiet: few/no progress messages\n");
+ fprintf(stderr, " -t (oob|null): select out-of-bounds or NULL test\n");
+ exit(EXIT_FAILURE);
+}
+
+bool
+H5HG_trap(const char *reason)
+{
+ if (strcmp(reason, "out of bounds") == 0) {
+ caught_out_of_bounds = true;
+ return true;
+ }
+ return false;
+}
+
+int
+main(int argc, char **argv)
+{
+ hid_t fapl, fid, space, type;
+ hid_t dset[2];
+ char *content[2];
+ char name[2][96];
+ int ch, i, ntimes = 100;
+ unsigned long tmp;
+ bool use_vfd_swmr = true;
+ char *end;
+ const long millisec_in_nanosecs = 1000 * 1000;
+ const struct timespec delay =
+ {.tv_sec = 0, .tv_nsec = millisec_in_nanosecs * 11 / 10};
+ testsel_t sel = TEST_NONE;
+
+ assert(H5T_C_S1 != badhid);
+
+ while ((ch = getopt(argc, argv, "Sn:qt:")) != -1) {
+ switch(ch) {
+ case 'S':
+ use_vfd_swmr = false;
+ break;
+ case 'n':
+ errno = 0;
+ tmp = strtoul(optarg, &end, 0);
+ if (end == optarg || *end != '\0')
+ errx(EXIT_FAILURE, "couldn't parse `-n` argument `%s`", optarg);
+ else if (errno != 0)
+ err(EXIT_FAILURE, "couldn't parse `-n` argument `%s`", optarg);
+ else if (tmp > INT_MAX)
+ errx(EXIT_FAILURE, "`-n` argument `%lu` too large", tmp);
+ ntimes = (int)tmp;
+ break;
+ case 'q':
+ verbosity = 1;
+ break;
+ case 't':
+ if (strcmp(optarg, "oob") == 0)
+ sel = TEST_OOB;
+ else if (strcmp(optarg, "null") == 0)
+ sel = TEST_NULL;
+ else
+ usage(argv[0]);
+ break;
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+ argv += optind;
+ argc -= optind;
+
+ if (argc > 0)
+ errx(EXIT_FAILURE, "unexpected command-line arguments");
+
+ fapl = vfd_swmr_create_fapl(false, sel == TEST_OOB, use_vfd_swmr,
+ "./shadow");
+ if (fapl < 0)
+ errx(EXIT_FAILURE, "vfd_swmr_create_fapl");
+
+ fid = H5Fopen("vfd_swmr_vlstr.h5", H5F_ACC_RDONLY, fapl);
+
+ /* Create the VL string datatype and a scalar dataspace, or a
+ * fixed-length string datatype and a simple dataspace.
+ */
+ if ((type = H5Tcopy(H5T_C_S1)) == badhid)
+ errx(EXIT_FAILURE, "H5Tcopy");
+
+ /* Create the VL string datatype and a scalar dataspace */
+ if ((type = H5Tcopy(H5T_C_S1)) == badhid)
+ errx(EXIT_FAILURE, "H5Tcopy");
+
+ if (H5Tset_size(type, H5T_VARIABLE) < 0)
+ errx(EXIT_FAILURE, "H5Tset_size");
+ space = H5Screate(H5S_SCALAR);
+
+ if (space == badhid)
+ errx(EXIT_FAILURE, "H5Screate");
+
+ if (fid == badhid)
+ errx(EXIT_FAILURE, "H5Fcreate");
+
+ /* content 1 seq 1 short
+ * content 1 seq 1 long long long long long long long long
+ * content 1 seq 1 medium medium medium
+ */
+ for (i = 0;
+ !caught_out_of_bounds && i < ntimes;
+ (i % 2 == 0) ? nanosleep(&delay, NULL) : 0, i++) {
+ estack_state_t es;
+ const int ndsets = 2;
+ const int which = i % ndsets;
+ int nconverted;
+ struct {
+ int which;
+ int seq;
+ char tail[96];
+ } scanned_content;
+
+ dbgf(2, "iteration %d which %d", i, which);
+ (void)snprintf(name[which], sizeof(name[which]),
+ "dset-%d", which);
+ es = disable_estack();
+ dset[which] = H5Dopen(fid, name[which], H5P_DEFAULT);
+ restore_estack(es);
+ if (caught_out_of_bounds || dset[which] == badhid) {
+ dbgf(2, ": couldn't open\n");
+ continue;
+ }
+ if (!read_vl_dset(dset[which], type, &content[which])) {
+ H5Dclose(dset[which]);
+ dbgf(2, ": couldn't read\n");
+ continue;
+ }
+ nconverted = sscanf(content[which], "content %d seq %d %96s",
+ &scanned_content.which, &scanned_content.seq, scanned_content.tail);
+ if (nconverted != 3) {
+ dbgf(2, ": couldn't scan\n");
+ continue;
+ }
+ dbgf(2, ": read which %d seq %d tail %s\n",
+ scanned_content.which, scanned_content.seq, scanned_content.tail);
+ H5Dclose(dset[which]);
+ }
+
+ if (caught_out_of_bounds)
+ fprintf(stderr, "caught out of bounds\n");
+
+ if (read_null)
+ fprintf(stderr, "read NULL\n");
+
+ if (H5Pclose(fapl) < 0)
+ errx(EXIT_FAILURE, "H5Pclose(fapl)");
+
+ if (H5Tclose(type) < 0)
+ errx(EXIT_FAILURE, "H5Tclose");
+
+ if (H5Sclose(space) < 0)
+ errx(EXIT_FAILURE, "H5Sclose");
+
+ if (H5Fclose(fid) < 0)
+ errx(EXIT_FAILURE, "H5Fclose");
+
+ if (sel == TEST_OOB)
+ return caught_out_of_bounds ? EXIT_SUCCESS : EXIT_FAILURE;
+ else if (sel == TEST_NULL)
+ return read_null ? EXIT_SUCCESS : EXIT_FAILURE;
+
+ return EXIT_SUCCESS;
+}
diff --git a/test/vfd_swmr_vlstr_writer.c b/test/vfd_swmr_vlstr_writer.c
new file mode 100644
index 0000000..193e03c
--- /dev/null
+++ b/test/vfd_swmr_vlstr_writer.c
@@ -0,0 +1,322 @@
+/*
+ * Copyright by The HDF Group.
+ * Copyright by the Board of Trustees of the University of Illinois.
+ * All rights reserved.
+ *
+ * This file is part of HDF5. The full HDF5 copyright notice, including
+ * terms governing use, modification, and redistribution, is contained in
+ * the COPYING file, which can be found at the root of the source code
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases.
+ * If you do not have access to either file, you may request a copy from
+ * help@hdfgroup.org.
+ */
+
+#include <err.h>
+#include <time.h> /* nanosleep(2) */
+#include <unistd.h> /* getopt(3) */
+
+#define H5C_FRIEND /*suppress error about including H5Cpkg */
+#define H5F_FRIEND /*suppress error about including H5Fpkg */
+
+#include "hdf5.h"
+
+#include "H5Cpkg.h"
+#include "H5Fpkg.h"
+// #include "H5Iprivate.h"
+#include "H5HGprivate.h"
+#include "H5VLprivate.h"
+
+#include "testhdf5.h"
+#include "vfd_swmr_common.h"
+
+enum _step {
+ CREATE = 0
+, LENGTHEN
+, SHORTEN
+, DELETE
+, NSTEPS
+} step_t;
+
+static const hid_t badhid = H5I_INVALID_HID; // abbreviate
+static bool caught_out_of_bounds = false;
+
+static void
+write_vl_dset(hid_t dset, hid_t type, hid_t space, char *data)
+{
+ if (H5Dwrite(dset, type, space, space, H5P_DEFAULT, &data) < 0)
+ errx(EXIT_FAILURE, "%s: H5Dwrite", __func__);
+ if (H5Dflush(dset) < 0)
+ errx(EXIT_FAILURE, "%s: H5Dflush", __func__);
+}
+
+#if 0
+static hid_t
+initialize_dset(hid_t file, hid_t type, hid_t space, const char *name,
+ void *data)
+{
+ hid_t dset;
+
+ dset = H5Dcreate2(file, name, type, space, H5P_DEFAULT, H5P_DEFAULT,
+ H5P_DEFAULT);
+
+ if (dset == badhid)
+ errx(EXIT_FAILURE, "H5Dcreate2");
+
+ if (H5Dwrite(dset, type, H5S_ALL, H5S_ALL, H5P_DEFAULT, data) < 0)
+ errx(EXIT_FAILURE, "H5Dwrite");
+
+ if (H5Dflush(dset) < 0)
+ errx(EXIT_FAILURE, "%s: H5Dflush", __func__);
+
+ return dset;
+}
+
+static void
+rewrite_dset(hid_t dset, hid_t type, char *data)
+{
+ if (H5Dwrite(dset, type, H5S_ALL, H5S_ALL, H5P_DEFAULT, data) < 0)
+ errx(EXIT_FAILURE, "%s: H5Dwrite", __func__);
+ if (H5Dflush(dset) < 0)
+ errx(EXIT_FAILURE, "%s: H5Dflush", __func__);
+}
+#endif
+
+static hid_t
+create_vl_dset(hid_t file, hid_t type, hid_t space, const char *name)
+{
+ hid_t dset;
+
+ dset = H5Dcreate2(file, name, type, space, H5P_DEFAULT, H5P_DEFAULT,
+ H5P_DEFAULT);
+
+ if (dset == badhid)
+ errx(EXIT_FAILURE, "H5Dcreate2");
+
+ return dset;
+}
+
+static void
+print_cache_hits(H5C_t *cache)
+{
+ int i;
+
+ for (i = 0; i < H5AC_NTYPES; i++) {
+ dbgf(3, "type-%d cache hits %" PRId64 "%s\n",
+ i, cache->hits[i], (i == H5AC_GHEAP_ID) ? " *" : "");
+ }
+ dbgf(3, "\n");
+}
+
+static void
+usage(const char *progname)
+{
+ fprintf(stderr, "usage: %s [-W] [-V]\n", progname);
+ fprintf(stderr, "\n -W: do not wait for SIGINT or SIGUSR1\n");
+ fprintf(stderr, "\n -S: do not use VFD SWMR\n");
+ fprintf(stderr, " -f: use fixed-length string\n");
+ fprintf(stderr, " (default: variable-length string)\n");
+ fprintf(stderr, " -n: number of test steps to perform\n");
+ fprintf(stderr, " -q: be quiet: few/no progress messages\n");
+ fprintf(stderr, " -t (oob|null): select out-of-bounds or NULL test\n");
+ exit(EXIT_FAILURE);
+}
+
+bool
+H5HG_trap(const char *reason)
+{
+ if (strcmp(reason, "out of bounds") == 0) {
+ caught_out_of_bounds = true;
+ return false;
+ }
+ return true;
+}
+
+int
+main(int argc, char **argv)
+{
+ hid_t fapl, fcpl, fid, space, type;
+ hid_t dset[2];
+ char content[2][96];
+ char name[2][96];
+ H5F_t *f;
+ H5C_t *cache;
+ sigset_t oldsigs;
+ herr_t ret;
+ bool variable = true, wait_for_signal = true;
+ const hsize_t dims = 1;
+ int ch, i, ntimes = 100;
+ unsigned long tmp;
+ char *end;
+ bool use_vfd_swmr = true;
+ const struct timespec delay =
+ {.tv_sec = 0, .tv_nsec = 1000 * 1000 * 1000 / 10};
+ testsel_t sel = TEST_NONE;
+
+ assert(H5T_C_S1 != badhid);
+
+ while ((ch = getopt(argc, argv, "SWfn:qt:")) != -1) {
+ switch(ch) {
+ case 'S':
+ use_vfd_swmr = false;
+ break;
+ case 'W':
+ wait_for_signal = false;
+ break;
+ case 'f':
+ variable = false;
+ break;
+ case 'n':
+ errno = 0;
+ tmp = strtoul(optarg, &end, 0);
+ if (end == optarg || *end != '\0')
+ errx(EXIT_FAILURE, "couldn't parse `-n` argument `%s`", optarg);
+ else if (errno != 0)
+ err(EXIT_FAILURE, "couldn't parse `-n` argument `%s`", optarg);
+ else if (tmp > INT_MAX)
+ errx(EXIT_FAILURE, "`-n` argument `%lu` too large", tmp);
+ ntimes = (int)tmp;
+ break;
+ case 'q':
+ verbosity = 1;
+ break;
+ case 't':
+ if (strcmp(optarg, "oob") == 0)
+ sel = TEST_OOB;
+ else if (strcmp(optarg, "null") == 0)
+ sel = TEST_NULL;
+ else
+ usage(argv[0]);
+ break;
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+ argv += optind;
+ argc -= optind;
+
+ if (argc > 0)
+ errx(EXIT_FAILURE, "unexpected command-line arguments");
+
+ fapl = vfd_swmr_create_fapl(true, sel == TEST_OOB, use_vfd_swmr,
+ "./shadow");
+ if (fapl < 0)
+ errx(EXIT_FAILURE, "vfd_swmr_create_fapl");
+
+ if ((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0)
+ errx(EXIT_FAILURE, "H5Pcreate");
+
+ ret = H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, false, 1);
+ if (ret < 0)
+ errx(EXIT_FAILURE, "H5Pset_file_space_strategy");
+
+ fid = H5Fcreate("vfd_swmr_vlstr.h5", H5F_ACC_TRUNC, fcpl, fapl);
+
+ /* Create the VL string datatype and a scalar dataspace, or a
+ * fixed-length string datatype and a simple dataspace.
+ */
+ if ((type = H5Tcopy(H5T_C_S1)) == badhid)
+ errx(EXIT_FAILURE, "H5Tcopy");
+
+ /* Create the VL string datatype and a scalar dataspace */
+ if ((type = H5Tcopy(H5T_C_S1)) == badhid)
+ errx(EXIT_FAILURE, "H5Tcopy");
+
+ if (!variable) {
+ if (H5Tset_size(type, 32) < 0)
+ errx(EXIT_FAILURE, "H5Tset_size");
+ space = H5Screate_simple(1, &dims, NULL);
+ } else {
+ if (H5Tset_size(type, H5T_VARIABLE) < 0)
+ errx(EXIT_FAILURE, "H5Tset_size");
+ space = H5Screate(H5S_SCALAR);
+ }
+
+ if (space == badhid)
+ errx(EXIT_FAILURE, "H5Screate");
+
+ if ((f = H5VL_object_verify(fid, H5I_FILE)) == NULL)
+ errx(EXIT_FAILURE, "H5VL_object_verify");
+
+ cache = f->shared->cache;
+
+ if (fid == badhid)
+ errx(EXIT_FAILURE, "H5Fcreate");
+
+ block_signals(&oldsigs);
+
+ print_cache_hits(cache);
+
+ /* content 1 seq 1 short
+ * content 1 seq 1 long long long long long long long long
+ * content 1 seq 1 medium medium medium
+ */
+ for (i = 0; i < ntimes; i++) {
+ const int ndsets = 2;
+ const int step = i % NSTEPS;
+ const int which = (i / NSTEPS) % ndsets;
+ const int seq = i / (ndsets * NSTEPS);
+ dbgf(2, "iteration %d which %d step %d seq %d\n",
+ i, which, step, seq);
+ switch (step) {
+ case CREATE:
+ (void)snprintf(name[which], sizeof(name[which]),
+ "dset-%d", which);
+ (void)snprintf(content[which], sizeof(content[which]),
+ "content %d seq %d short", which, seq);
+ dset[which] =
+ create_vl_dset(fid, type, space, name[which]);
+ write_vl_dset(dset[which], type, space, content[which]);
+ break;
+ case LENGTHEN:
+ (void)snprintf(content[which], sizeof(content[which]),
+ "content %d seq %d long long long long long long long long",
+ which, seq);
+ write_vl_dset(dset[which], type, space, content[which]);
+ break;
+ case SHORTEN:
+ (void)snprintf(content[which], sizeof(content[which]),
+ "content %d seq %d medium medium medium",
+ which, seq);
+ write_vl_dset(dset[which], type, space, content[which]);
+ break;
+ case DELETE:
+ if (H5Dclose(dset[which]) < 0)
+ errx(EXIT_FAILURE, "H5Dclose");
+ if (H5Ldelete(fid, name[which], H5P_DEFAULT) < 0) {
+ errx(EXIT_FAILURE, "%s: H5Ldelete(, \"%s\", ) failed",
+ __func__, name[which]);
+ }
+ break;
+ default:
+ errx(EXIT_FAILURE, "%s: unknown step %d", __func__, step);
+ }
+ if (caught_out_of_bounds) {
+ fprintf(stderr, "caught out of bounds\n");
+ break;
+ }
+ nanosleep(&delay, NULL);
+ }
+
+ if (use_vfd_swmr && wait_for_signal)
+ await_signal(fid);
+
+ restore_signals(&oldsigs);
+
+ if (H5Pclose(fapl) < 0)
+ errx(EXIT_FAILURE, "H5Pclose(fapl)");
+
+ if (H5Pclose(fcpl) < 0)
+ errx(EXIT_FAILURE, "H5Pclose(fcpl)");
+
+ if (H5Tclose(type) < 0)
+ errx(EXIT_FAILURE, "H5Tclose");
+
+ if (H5Sclose(space) < 0)
+ errx(EXIT_FAILURE, "H5Sclose");
+
+ if (H5Fclose(fid) < 0)
+ errx(EXIT_FAILURE, "H5Fclose");
+
+ return EXIT_SUCCESS;
+}
diff --git a/test/vfd_swmr_writer.c b/test/vfd_swmr_writer.c
new file mode 100644
index 0000000..1d73dd6
--- /dev/null
+++ b/test/vfd_swmr_writer.c
@@ -0,0 +1,454 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: vfd_swmr_writer.c
+ * (copied and modified from swmr_writer.c)
+ *
+ * Purpose: Writes data to a randomly selected subset of the datasets
+ * in the VFD SWMR test file.
+ *
+ * This program is intended to run concurrently with the
+ * vfd_swmr_reader program.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/***********/
+/* Headers */
+/***********/
+
+#include <unistd.h> /* getopt(3) */
+
+#include "h5test.h"
+#include "vfd_swmr_common.h"
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+static hid_t open_skeleton(const char *filename, hbool_t verbose, FILE *verbose_file,
+ unsigned random_seed, hbool_t old);
+static int add_records(hid_t fid, hbool_t verbose, FILE *verbose_file,
+ unsigned long nrecords, unsigned long flush_count);
+static void usage(void);
+
+
+/*-------------------------------------------------------------------------
+ * Function: open_skeleton
+ *
+ * Purpose: Opens the SWMR HDF5 file and datasets.
+ *
+ * Parameters: const char *filename
+ * The filename of the SWMR HDF5 file to open
+ *
+ * hbool_t verbose
+ * Whether or not to emit verbose console messages
+ *
+ * FILE *verbose_file
+ * File handle for verbose output
+ *
+ * unsigned random_seed
+ * Random seed for the file (used for verbose logging)
+ *
+ * hbool_t old
+ * Whether to write in "old" file format
+ *
+ * Return: Success: The file ID of the opened SWMR file
+ * The dataset IDs are stored in a global array
+ *
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static hid_t
+open_skeleton(const char *filename, hbool_t verbose, FILE *verbose_file,
+ unsigned random_seed, hbool_t old H5_ATTR_UNUSED)
+{
+ hid_t fid; /* File ID for new HDF5 file */
+ hid_t fapl; /* File access property list */
+ unsigned u, v; /* Local index variable */
+ hbool_t use_log_vfd = FALSE; /* Use the log VFD (set this manually) */
+ H5F_vfd_swmr_config_t *config = NULL; /* Configuration for VFD SWMR */
+
+ HDassert(filename);
+
+ /* Create file access property list */
+ if((fapl = h5_fileaccess()) < 0)
+ return -1;
+
+ /* FOR NOW: set to use latest format, the "old" parameter is not used */
+ if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
+ return -1;
+
+ if(use_log_vfd) {
+ char verbose_name[1024];
+
+ HDsnprintf(verbose_name, sizeof(verbose_name), "vfd_swmr_writer.log.%u", random_seed);
+
+ H5Pset_fapl_log(fapl, verbose_name, H5FD_LOG_ALL, (size_t)(512 * 1024 * 1024));
+ } /* end if */
+
+ /*
+ * Set up to open the file with VFD SWMR configured.
+ */
+
+ /* Enable page buffering */
+ if(H5Pset_page_buffer_size(fapl, 4096, 0, 0) < 0)
+ return -1;
+
+ /* Allocate memory for the configuration structure */
+ if((config = (H5F_vfd_swmr_config_t *)HDcalloc(1, sizeof(H5F_vfd_swmr_config_t))) == NULL)
+ return -1;
+
+ config->version = H5F__CURR_VFD_SWMR_CONFIG_VERSION;
+ config->tick_len = 4;
+ config->max_lag = 5;
+ config->writer = TRUE;
+ config->md_pages_reserved = 128;
+ HDstrcpy(config->md_file_path, "./my_md_file");
+
+ /* Enable VFD SWMR configuration */
+ if(H5Pset_vfd_swmr_config(fapl, config) < 0)
+ return -1;
+
+ /* Open the file with VFD SWMR configured */
+ if((fid = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
+ return -1;
+
+ /* Close file access property list */
+ if(H5Pclose(fapl) < 0)
+ return -1;
+
+ if(config)
+ HDfree(config);
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(verbose_file, "WRITER: Opening datasets\n");
+
+ /* Open the datasets */
+ for(u = 0; u < NLEVELS; u++)
+ for(v = 0; v < symbol_count[u]; v++) {
+ if((symbol_info[u][v].dsid = H5Dopen2(fid, symbol_info[u][v].name, H5P_DEFAULT)) < 0)
+ return -1;
+ symbol_info[u][v].nrecords = 0;
+ } /* end for */
+
+ return fid;
+} /* open_skeleton() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: add_records
+ *
+ * Purpose: Writes a specified number of records to random datasets in
+ * the SWMR test file.
+ *
+ * Parameters: hid_t fid
+ * The file ID of the SWMR HDF5 file
+ *
+ * hbool_t verbose
+ * Whether or not to emit verbose console messages
+ *
+ * FILE *verbose_file
+ * File handle for verbose output
+ *
+ * unsigned long nrecords
+ * # of records to write to the datasets
+ *
+ * unsigned long flush_count
+ * # of records to write before flushing the file to disk
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+add_records(hid_t fid, hbool_t verbose, FILE *verbose_file,
+ unsigned long nrecords, unsigned long flush_count)
+{
+ hid_t tid; /* Datatype ID for records */
+ hid_t mem_sid; /* Memory dataspace ID */
+ hsize_t start[2] = {0, 0}, count[2] = {1, 1}; /* Hyperslab selection values */
+ hsize_t dim[2] = {1, 0}; /* Dataspace dimensions */
+ symbol_t record; /* The record to add to the dataset */
+ unsigned long rec_to_flush; /* # of records left to write before flush */
+ unsigned long u, v; /* Local index variables */
+
+ HDassert(fid >= 0);
+
+ /* Reset the record */
+ /* (record's 'info' field might need to change for each record written, also) */
+ HDmemset(&record, 0, sizeof(record));
+
+ /* Create a dataspace for the record to add */
+ if((mem_sid = H5Screate(H5S_SCALAR)) < 0)
+ return -1;
+
+ /* Create datatype for appending records */
+ if((tid = create_symbol_datatype()) < 0)
+ return -1;
+
+ /* Add records to random datasets, according to frequency distribution */
+ rec_to_flush = flush_count;
+ for(u = 0; u < nrecords; u++) {
+ symbol_info_t *symbol; /* Symbol to write record to */
+ hid_t file_sid; /* Dataset's space ID */
+
+ /* Get a random dataset, according to the symbol distribution */
+ symbol = choose_dataset(NULL, NULL);
+
+ /* Set the record's ID (equal to its position) */
+ record.rec_id = symbol->nrecords;
+
+ /* Get the coordinate to write */
+ start[1] = symbol->nrecords;
+
+ /* Extend the dataset's dataspace to hold the new record */
+ symbol->nrecords++;
+ dim[1] = symbol->nrecords;
+ if(H5Dset_extent(symbol->dsid, dim) < 0)
+ return -1;
+
+ /* Get the dataset's dataspace */
+ if((file_sid = H5Dget_space(symbol->dsid)) < 0)
+ return -1;
+
+ /* Choose the last record in the dataset */
+ if(H5Sselect_hyperslab(file_sid, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ return -1;
+
+ /* Write record to the dataset */
+ if(H5Dwrite(symbol->dsid, tid, mem_sid, file_sid, H5P_DEFAULT, &record) < 0)
+ return -1;
+
+ /* Close the dataset's dataspace */
+ if(H5Sclose(file_sid) < 0)
+ return -1;
+
+ /* Check for flushing file */
+ if(flush_count > 0) {
+ /* Decrement count of records to write before flushing */
+ rec_to_flush--;
+
+ /* Check for counter being reached */
+ if(0 == rec_to_flush) {
+#ifdef TEMP_OUT
+ /* Flush contents of file */
+ if(H5Fflush(fid, H5F_SCOPE_GLOBAL) < 0)
+ return -1;
+#endif /* TEMP_OUT */
+
+ /* Reset flush counter */
+ rec_to_flush = flush_count;
+ } /* end if */
+ } /* end if */
+ } /* end for */
+
+ /* Close the memory dataspace */
+ if(H5Sclose(mem_sid) < 0)
+ return -1;
+
+ /* Close the datatype */
+ if(H5Tclose(tid) < 0)
+ return -1;
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(verbose_file, "WRITER: Closing datasets\n");
+
+ /* Close the datasets */
+ for(u = 0; u < NLEVELS; u++)
+ for(v = 0; v < symbol_count[u]; v++)
+ if(H5Dclose(symbol_info[u][v].dsid) < 0)
+ return -1;
+
+ return 0;
+}
+
+static void
+usage(void)
+{
+ printf("\n");
+ printf("Usage error!\n");
+ printf("\n");
+ printf("Usage: vfd_swmr_writer [-q] [-o] [-f <# of records to write between flushing\n");
+ printf(" file contents>] [-r <random seed>] <# of records>\n");
+ printf("\n");
+ printf("<# of records to write between flushing file contents> should be 0\n");
+ printf("(for no flushing) or between 1 and (<# of records> - 1).\n");
+ printf("\n");
+ printf("<# of records> must be specified.\n");
+ printf("\n");
+ printf("Defaults to verbose (no '-q' given), latest format when opening file (no '-o' given),\n");
+ printf("flushing every 10000 records ('-f 10000'), and will generate a random seed (no -r given).\n");
+ printf("\n");
+ HDexit(1);
+}
+
+int
+main(int argc, char * const *argv)
+{
+ sigset_t oldset;
+ hid_t fid; /* File ID for file opened */
+ long nrecords = 0; /* # of records to append */
+ long flush_count = 10000; /* # of records to write between flushing file */
+ hbool_t verbose = TRUE; /* Whether to emit some informational messages */
+ FILE *verbose_file = NULL; /* File handle for verbose output */
+ hbool_t old = FALSE; /* Whether to use non-latest-format when opening file */
+ hbool_t use_seed = FALSE; /* Set to TRUE if a seed was set on the command line */
+ hbool_t wait_for_signal = TRUE;
+ unsigned random_seed = 0; /* Random # seed */
+ int ch, temp;
+
+ block_signals(&oldset);
+
+ while ((ch = getopt(argc, argv, "Wf:qr:o")) != -1) {
+ switch(ch) {
+ /* # of records to write between flushing file */
+ case 'f':
+ flush_count = HDatol(optarg);
+ if(flush_count < 0)
+ usage();
+ break;
+
+ /* Be quiet */
+ case 'q':
+ verbose = FALSE;
+ break;
+
+ /* Random # seed */
+ case 'r':
+ use_seed = TRUE;
+ temp = HDatoi(optarg);
+ random_seed = (unsigned)temp;
+ break;
+
+ case 'W':
+ wait_for_signal = FALSE;
+ break;
+
+ /* Use non-latest-format when opening file */
+ case 'o':
+ old = TRUE;
+ break;
+
+ default:
+ usage();
+ break;
+ }
+ }
+ argv += optind;
+ argc -= optind;
+ /* Parse command line options */
+ if(argc < 1)
+ usage();
+ /* Get the number of records to append */
+ nrecords = HDatol(argv[0]);
+ if(nrecords <= 0 || flush_count >= nrecords)
+ usage();
+
+ /* Set the random seed */
+ if(!use_seed) {
+ struct timeval t;
+
+ HDgettimeofday(&t, NULL);
+ random_seed = (unsigned)(t.tv_usec);
+ } /* end if */
+ HDsrandom(random_seed);
+
+ /* Open output file */
+ if(verbose) {
+ char verbose_name[1024];
+
+ HDsnprintf(verbose_name, sizeof(verbose_name), "vfd_swmr_writer.out.%u", random_seed);
+ if(NULL == (verbose_file = HDfopen(verbose_name, "w"))) {
+ HDfprintf(stderr, "WRITER: Can't open verbose output file!\n");
+ HDexit(1);
+ }
+ } /* end if */
+
+ /* Emit informational message */
+ if(verbose) {
+ HDfprintf(verbose_file, "WRITER: Parameters:\n");
+ HDfprintf(verbose_file, "\t# of records between flushes = %ld\n", flush_count);
+ HDfprintf(verbose_file, "\t# of records to write = %ld\n", nrecords);
+ } /* end if */
+
+ /* ALWAYS emit the random seed for possible debugging */
+ HDfprintf(stdout, "Using writer random seed: %u\n", random_seed);
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(verbose_file, "WRITER: Generating symbol names\n");
+
+ /* Generate dataset names */
+ if(generate_symbols() < 0)
+ return -1;
+
+ /* Emit informational message */
+ if(verbose) {
+ HDfprintf(verbose_file, "WRITER: Opening skeleton file: %s\n",
+ COMMON_FILENAME);
+ }
+
+ /* Open file skeleton */
+ if((fid = open_skeleton(COMMON_FILENAME, verbose, verbose_file, random_seed, old)) < 0) {
+ HDfprintf(stderr, "WRITER: Error opening skeleton file!\n");
+ HDexit(1);
+ } /* end if */
+
+ /* Send a message to indicate "H5Fopen" is complete--releasing the file lock */
+ h5_send_message(WRITER_MESSAGE, NULL, NULL);
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(verbose_file, "WRITER: Adding records\n");
+
+ /* Append records to datasets */
+ if(add_records(fid, verbose, verbose_file, (unsigned long)nrecords, (unsigned long)flush_count) < 0) {
+ HDfprintf(stderr, "WRITER: Error appending records to datasets!\n");
+ HDexit(1);
+ } /* end if */
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(verbose_file, "WRITER: Releasing symbols\n");
+
+ /* Clean up the symbols */
+ if(shutdown_symbols() < 0) {
+ HDfprintf(stderr, "WRITER: Error releasing symbols!\n");
+ HDexit(1);
+ } /* end if */
+
+ if (wait_for_signal)
+ await_signal(fid);
+
+ restore_signals(&oldset);
+
+ /* Emit informational message */
+ if(verbose)
+ HDfprintf(verbose_file, "WRITER: Closing objects/file\n");
+
+ /* Close objects opened */
+ if(H5Fclose(fid) < 0) {
+ HDfprintf(stderr, "WRITER: Error closing file!\n");
+ HDexit(1);
+ } /* end if */
+
+ return 0;
+}
+
diff --git a/test/vfd_swmr_zoo_writer.c b/test/vfd_swmr_zoo_writer.c
new file mode 100644
index 0000000..e2892ec
--- /dev/null
+++ b/test/vfd_swmr_zoo_writer.c
@@ -0,0 +1,412 @@
+/*
+ * Copyright by The HDF Group.
+ * Copyright by the Board of Trustees of the University of Illinois.
+ * All rights reserved.
+ *
+ * This file is part of HDF5. The full HDF5 copyright notice, including
+ * terms governing use, modification, and redistribution, is contained in
+ * the COPYING file, which can be found at the root of the source code
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases.
+ * If you do not have access to either file, you may request a copy from
+ * help@hdfgroup.org.
+ */
+
+#include <err.h>
+#include <libgen.h> /* basename(3) */
+#include <time.h> /* nanosleep(2) */
+#include <unistd.h> /* getopt(3) */
+
+#define H5C_FRIEND /* suppress error about including H5Cpkg */
+#define H5F_FRIEND /* suppress error about including H5Fpkg */
+
+#include "hdf5.h"
+
+#include "H5private.h"
+#include "H5retry_private.h"
+#include "H5Cpkg.h"
+#include "H5Fpkg.h"
+// #include "H5Iprivate.h"
+#include "H5HGprivate.h"
+#include "H5VLprivate.h"
+
+#include "testhdf5.h"
+#include "genall5.h"
+#include "vfd_swmr_common.h"
+
+#ifndef _arraycount
+#define _arraycount(_a) (sizeof(_a)/sizeof(_a[0]))
+#endif
+
+typedef struct _shared_ticks {
+ uint64_t reader_tick;
+} shared_ticks_t;
+
+typedef struct _tick_stats {
+ uint64_t writer_tried_increase;
+ uint64_t writer_aborted_increase;
+ uint64_t writer_read_shared_file;
+ uint64_t reader_tick_was_zero; // writer read reader tick equal to 0
+ uint64_t reader_tick_lead_writer; // writer read reader tick greater than
+ // proposed writer tick
+ uint64_t writer_lead_reader_by[1]; // proposed writer tick lead reader
+ // tick by `lead` ticks
+ // `writer_lead_reader_by[lead]`
+ // times, for `0 <= lead <= max_lag - 1`
+} tick_stats_t;
+
+static H5F_vfd_swmr_config_t swmr_config;
+static tick_stats_t *tick_stats = NULL;
+static const hid_t badhid = H5I_INVALID_HID;
+static bool writer;
+
+static void
+print_cache_hits(H5C_t *cache)
+{
+ int i;
+
+ for (i = 0; i < H5AC_NTYPES; i++) {
+ dbgf(3, "type-%d cache hits %" PRId64 "%s\n",
+ i, cache->hits[i], (i == H5AC_GHEAP_ID) ? " *" : "");
+ }
+ dbgf(3, "\n");
+}
+
+void
+zoo_create_hook(hid_t fid)
+{
+ dbgf(3, "%s: enter\n", __func__);
+ if (writer)
+ H5Fvfd_swmr_end_tick(fid);
+}
+
+static void
+usage(const char *progname)
+{
+ fprintf(stderr, "usage: %s [-C] [-S] [-W] [-a] [-e] [-m] [-q] [-v]\n",
+ progname);
+ fprintf(stderr, "\n -C: skip compact dataset tests\n");
+ fprintf(stderr, " -S: do not use VFD SWMR\n");
+ fprintf(stderr, " -W: do not wait for SIGINT or SIGUSR1\n");
+ fprintf(stderr, " -a: run all tests, including variable-length data\n");
+ fprintf(stderr, " -e: print error stacks\n");
+ fprintf(stderr, " -m ms: maximum `ms` milliseconds pause between\n");
+ fprintf(stderr, " each create/delete step\n");
+ fprintf(stderr, " -q: be quiet: few/no progress messages\n");
+ fprintf(stderr, " -v: be verbose: most progress messages\n");
+ exit(EXIT_FAILURE);
+}
+
+bool
+vfd_swmr_writer_may_increase_tick_to(uint64_t new_tick, bool wait_for_reader)
+{
+ static int fd = -1;
+ shared_ticks_t shared;
+ ssize_t nread;
+ h5_retry_t retry;
+ bool do_try;
+
+ dbgf(3, "%s: enter\n", __func__);
+
+ if (fd == -1) {
+ fd = open("./shared_tick_num", O_RDONLY);
+ if (fd == -1) {
+ warn("%s: open", __func__); // TBD ratelimit/silence this warning
+ return true;
+ }
+ assert(tick_stats == NULL);
+ tick_stats = calloc(1, sizeof(*tick_stats) +
+ (swmr_config.max_lag - 1) *
+ sizeof(tick_stats->writer_lead_reader_by[0]));
+ if (tick_stats == NULL)
+ err(EXIT_FAILURE, "%s: calloc", __func__);
+ }
+
+ tick_stats->writer_tried_increase++;
+
+ for (do_try = h5_retry_init(&retry, 14, 10 * 1000 * 1000,
+ 100 * 1000 * 1000);
+ do_try;
+ do_try = wait_for_reader && h5_retry_next(&retry)) {
+
+ tick_stats->writer_read_shared_file++;
+
+ if ((nread = pread(fd, &shared, sizeof(shared), 0)) == -1)
+ err(EXIT_FAILURE, "%s: pread", __func__);
+
+ if (nread != sizeof(shared))
+ errx(EXIT_FAILURE, "%s: pread", __func__);
+
+ // TBD convert endianness
+
+ if (shared.reader_tick == 0) {
+ tick_stats->reader_tick_was_zero++;
+ return true;
+ }
+
+ if (new_tick < shared.reader_tick) {
+ tick_stats->reader_tick_lead_writer++;
+ return true;
+ }
+ if (new_tick <= shared.reader_tick + swmr_config.max_lag - 1) {
+ uint64_t lead = new_tick - shared.reader_tick;
+ assert(lead <= swmr_config.max_lag - 1);
+ tick_stats->writer_lead_reader_by[lead]++;
+ return true;
+ }
+ }
+ if (wait_for_reader && !do_try)
+ errx(EXIT_FAILURE, "%s: timed out waiting for reader", __func__);
+
+ tick_stats->writer_aborted_increase++;
+
+ return false;
+}
+
+void
+vfd_swmr_reader_did_increase_tick_to(uint64_t new_tick)
+{
+ static int fd = -1;
+ shared_ticks_t shared;
+ ssize_t nwritten;
+
+ dbgf(3, "%s: enter\n", __func__);
+
+ if (fd == -1) {
+ // TBD create a temporary file, here, and move it to its final path
+ // after writing it.
+ fd = open("./shared_tick_num", O_RDWR|O_CREAT, 0600);
+ if (fd == -1)
+ err(EXIT_FAILURE, "%s: open", __func__);
+ }
+
+ shared.reader_tick = new_tick;
+
+ // TBD convert endianness
+
+ if ((nwritten = pwrite(fd, &shared, sizeof(shared), 0)) == -1)
+ errx(EXIT_FAILURE, "%s: pwrite", __func__);
+
+ if (nwritten != sizeof(shared))
+ errx(EXIT_FAILURE, "%s: pwrite", __func__);
+
+ if (new_tick == 0) {
+ if (unlink("./shared_tick_num") == -1)
+ warn("%s: unlink", __func__);
+ if (close(fd) == -1)
+ err(EXIT_FAILURE, "%s: close", __func__);
+ fd = -1;
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ hid_t fapl, fcpl, fid;
+ H5F_t *f;
+ H5C_t *cache;
+ sigset_t oldsigs;
+ herr_t ret;
+ zoo_config_t config = {
+ .proc_num = 0
+ , .skip_compact = false
+ , .skip_varlen = true
+ , .max_pause_msecs = 0
+ };
+ bool wait_for_signal;
+ int ch;
+ char vector[8];
+ unsigned seed;
+ unsigned long tmpl;
+ char *end, *ostate;
+ const char *seedvar = "H5_ZOO_STEP_SEED";
+ bool use_vfd_swmr = true;
+ bool print_estack = false;
+ const char *progname = basename(argv[0]);
+ const char *personality = strstr(progname, "vfd_swmr_zoo_");
+ estack_state_t es;
+ char step = 'b';
+
+ if (personality != NULL && strcmp(personality, "vfd_swmr_zoo_writer") == 0)
+ writer = wait_for_signal = true;
+ else if (personality != NULL &&
+ strcmp(personality, "vfd_swmr_zoo_reader") == 0)
+ writer = false;
+ else {
+ errx(EXIT_FAILURE,
+ "unknown personality, expected vfd_swmr_zoo_{reader,writer}");
+ }
+
+ if (writer)
+ config.max_pause_msecs = 50;
+
+ while ((ch = getopt(argc, argv, "CSWaem:qv")) != -1) {
+ switch(ch) {
+ case 'C':
+ config.skip_compact = true;
+ break;
+ case 'S':
+ use_vfd_swmr = false;
+ break;
+ case 'W':
+ wait_for_signal = false;
+ break;
+ case 'a':
+ config.skip_varlen = false;
+ break;
+ case 'e':
+ print_estack = true;
+ break;
+ case 'm':
+ errno = 0;
+ tmpl = strtoul(optarg, &end, 0);
+ if (end == optarg || *end != '\0')
+ errx(EXIT_FAILURE, "couldn't parse `-m` argument `%s`", optarg);
+ else if (errno != 0)
+ err(EXIT_FAILURE, "couldn't parse `-m` argument `%s`", optarg);
+ else if (tmpl > UINT_MAX)
+ errx(EXIT_FAILURE, "`-m` argument `%lu` too large", tmpl);
+ config.max_pause_msecs = (unsigned)tmpl;
+ break;
+ case 'q':
+ verbosity = 1;
+ break;
+ case 'v':
+ verbosity = 3;
+ break;
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+ argv += optind;
+ argc -= optind;
+
+ if (argc > 0)
+ errx(EXIT_FAILURE, "unexpected command-line arguments");
+
+ fapl = vfd_swmr_create_fapl(writer, true, use_vfd_swmr, "./shadow");
+
+ if (use_vfd_swmr && H5Pget_vfd_swmr_config(fapl, &swmr_config) < 0)
+ errx(EXIT_FAILURE, "H5Pget_vfd_swmr_config");
+
+ if (fapl < 0)
+ errx(EXIT_FAILURE, "vfd_swmr_create_fapl");
+
+ if (H5Pset_libver_bounds(fapl, H5F_LIBVER_EARLIEST, H5F_LIBVER_LATEST) < 0){
+ errx(EXIT_FAILURE, "%s.%d: H5Pset_libver_bounds", __func__, __LINE__);
+ }
+
+ if ((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0)
+ errx(EXIT_FAILURE, "H5Pcreate");
+
+ ret = H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, false, 1);
+ if (ret < 0)
+ errx(EXIT_FAILURE, "H5Pset_file_space_strategy");
+
+ if (writer)
+ fid = H5Fcreate("vfd_swmr_zoo.h5", H5F_ACC_TRUNC, fcpl, fapl);
+ else
+ fid = H5Fopen("vfd_swmr_zoo.h5", H5F_ACC_RDONLY, fapl);
+
+ if (fid == badhid)
+ errx(EXIT_FAILURE, writer ? "H5Fcreate" : "H5Fopen");
+
+ if ((f = H5VL_object_verify(fid, H5I_FILE)) == NULL)
+ errx(EXIT_FAILURE, "H5VL_object_verify");
+
+ cache = f->shared->cache;
+
+ if (wait_for_signal)
+ block_signals(&oldsigs);
+
+ print_cache_hits(cache);
+
+ es = print_estack ? estack_get_state() : disable_estack();
+ if (writer) {
+
+ dbgf(2, "Writing zoo...\n");
+
+ /* get seed from environment or else from time(3) */
+ switch (fetch_env_ulong(seedvar, UINT_MAX, &tmpl)) {
+ case -1:
+ errx(EXIT_FAILURE, "%s: fetch_env_ulong", __func__);
+ case 0:
+ seed = (unsigned int)time(NULL);
+ break;
+ default:
+ seed = (unsigned int)tmpl;
+ break;
+ }
+
+ dbgf(1, "To reproduce, set seed (%s) to %u.\n", seedvar, seed);
+
+ ostate = initstate(seed, vector, _arraycount(vector));
+
+ if (!create_zoo(fid, ".", config))
+ errx(EXIT_FAILURE, "create_zoo didn't pass self-check");
+
+ /* Avoid deadlock: flush the file before waiting for the reader's
+ * message.
+ */
+ if (H5Fflush(fid, H5F_SCOPE_GLOBAL) < 0)
+ errx(EXIT_FAILURE, "%s: H5Fflush failed", __func__);
+
+ if (read(STDIN_FILENO, &step, sizeof(step)) == -1)
+ err(EXIT_FAILURE, "read");
+
+ if (step != 'b')
+ errx(EXIT_FAILURE, "expected 'b' read '%c'", step);
+
+ if (!delete_zoo(fid, ".", config))
+ errx(EXIT_FAILURE, "delete_zoo failed");
+ (void)setstate(ostate);
+ } else {
+ dbgf(2, "Reading zoo...\n");
+
+ while (!validate_zoo(fid, ".", config))
+ ;
+
+ if (write(STDOUT_FILENO, &step, sizeof(step)) == -1)
+ err(EXIT_FAILURE, "write");
+ while (!validate_deleted_zoo(fid, ".", config))
+ ;
+ }
+ restore_estack(es);
+
+ if (use_vfd_swmr && wait_for_signal)
+ await_signal(fid);
+
+ if (writer && tick_stats != NULL) {
+ uint64_t lead;
+
+ dbgf(2, "writer tried tick increase %" PRIu64 "\n",
+ tick_stats->writer_tried_increase);
+ dbgf(2, "writer aborted tick increase %" PRIu64 "\n",
+ tick_stats->writer_aborted_increase);
+ dbgf(2, "writer read shared file %" PRIu64 "\n",
+ tick_stats->writer_read_shared_file);
+ dbgf(2, "writer read reader tick equal to 0 %" PRIu64 "\n",
+ tick_stats->reader_tick_was_zero);
+ dbgf(2, "writer read reader tick leading writer %" PRIu64 "\n",
+ tick_stats->reader_tick_lead_writer);
+
+ for (lead = 0; lead < swmr_config.max_lag; lead++) {
+ dbgf(2, "writer tick lead writer by %" PRIu64 " %" PRIu64 "\n",
+ lead, tick_stats->writer_lead_reader_by[lead]);
+ }
+ }
+
+ if (H5Pclose(fapl) < 0)
+ errx(EXIT_FAILURE, "H5Pclose(fapl)");
+
+ if (H5Pclose(fcpl) < 0)
+ errx(EXIT_FAILURE, "H5Pclose(fcpl)");
+
+ if (H5Fclose(fid) < 0)
+ errx(EXIT_FAILURE, "H5Fclose");
+
+ if (wait_for_signal)
+ restore_signals(&oldsigs);
+
+ return EXIT_SUCCESS;
+}