summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorVailin Choi <vchoi@hdfgroup.org>2014-01-08 17:09:23 (GMT)
committerVailin Choi <vchoi@hdfgroup.org>2014-01-08 17:09:23 (GMT)
commita196a4f351abed0670c10bc50887bd4e56dd4775 (patch)
treecc56e2d57884eae938e6606624d0c619d6dfe541 /test
parent955c0736022947649441634f7ee3dc5c973085d4 (diff)
downloadhdf5-a196a4f351abed0670c10bc50887bd4e56dd4775.zip
hdf5-a196a4f351abed0670c10bc50887bd4e56dd4775.tar.gz
hdf5-a196a4f351abed0670c10bc50887bd4e56dd4775.tar.bz2
[svn-r24622] Implementation (pending code review) for:
(A) SWMR related public routines: H5Fstart_swmr_write, H5Pget/set_append_flush, H5Pget/set_object_flush_cb. (B) File locking. Tested on jam, koala, ostrich, platypus.
Diffstat (limited to 'test')
-rw-r--r--test/Makefile.am47
-rw-r--r--test/Makefile.in90
-rw-r--r--test/accum.c13
-rw-r--r--test/accum_swmr_reader.c2
-rw-r--r--test/bad_compound.h5bin2208 -> 2208 bytes
-rw-r--r--test/btree_idx_1_6.h5bin6350 -> 6350 bytes
-rw-r--r--test/corrupt_stab_msg.h5bin2928 -> 2928 bytes
-rw-r--r--test/deflate.h5bin6240 -> 6240 bytes
-rw-r--r--test/family_v16_00000.h5bin5120 -> 5120 bytes
-rw-r--r--test/file_image.c96
-rw-r--r--test/filespace_1_6.h5bin2448 -> 2448 bytes
-rw-r--r--test/fill_old.h5bin2560 -> 2560 bytes
-rw-r--r--test/flush2.c68
-rw-r--r--test/group_old.h5bin1952 -> 1952 bytes
-rw-r--r--test/h5test.c53
-rw-r--r--test/h5test.h6
-rw-r--r--test/mergemsg.h5bin3472 -> 3472 bytes
-rw-r--r--test/multi_file_v16-s.h5bin2048 -> 2048 bytes
-rw-r--r--test/swmr_addrem_writer.c3
-rw-r--r--test/swmr_common.c2
-rw-r--r--test/swmr_common.h4
-rw-r--r--test/swmr_remove_writer.c3
-rw-r--r--test/swmr_sparse_writer.c5
-rw-r--r--test/swmr_start_write.c691
-rw-r--r--test/swmr_writer.c3
-rw-r--r--test/tarrold.h5bin6032 -> 6032 bytes
-rw-r--r--test/test_filters_be.h5bin5720 -> 5720 bytes
-rw-r--r--test/test_filters_le.h5bin5720 -> 5720 bytes
-rw-r--r--test/test_swmr.c2104
-rwxr-xr-xtest/testswmr.sh139
-rw-r--r--test/tfile.c1683
-rw-r--r--test/th5s.h5bin2049 -> 2049 bytes
-rw-r--r--test/tlayouto.h5bin1576 -> 1576 bytes
-rw-r--r--test/tmtimen.h5bin1576 -> 1576 bytes
-rw-r--r--test/tmtimeo.h5bin2052 -> 2052 bytes
-rw-r--r--test/use.h27
-rw-r--r--test/use_append_chunk.c11
-rw-r--r--test/use_append_mchunks.c11
-rw-r--r--test/use_common.c14
39 files changed, 4704 insertions, 371 deletions
diff --git a/test/Makefile.am b/test/Makefile.am
index 5f814ec..f1465fc 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -23,10 +23,21 @@ include $(top_srcdir)/config/commence.am
INCLUDES=-I$(top_srcdir)/src -I$(top_builddir)/src
-# Test script for error_test and err_compat
+# Test scripts--
+# testerror.sh: err_compat, error_test
+# testlibinfo.sh:
+# testcheck_version.sh: tcheck_version
+# tetlinks_env.sh: links_env
+# testflushrefresh.sh: flushrefresh
+# test_usecases.sh: use_append_chunk, use_append_mchunks
+# testswmr.sh: swmr*
TEST_SCRIPT = testerror.sh testlibinfo.sh testcheck_version.sh testlinks_env.sh \
- $(srcdir)/testswmr.sh testflushrefresh.sh test_usecases.sh
-SCRIPT_DEPEND = error_test$(EXEEXT) err_compat$(EXEEXT) links_env$(EXEEXT)
+ testflushrefresh.sh test_usecases.sh $(srcdir)/testswmr.sh
+SCRIPT_DEPEND = error_test$(EXEEXT) err_compat$(EXEEXT) links_env$(EXEEXT) \
+ flushrefresh$(EXEEXT) use_append_chunk$(EXEEXT) use_append_mchunks$(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)
if HAVE_SHARED_CONDITIONAL
TEST_SCRIPT += test_plugin.sh
SCRIPT_DEPEND += plugin$(EXEEXT)
@@ -43,25 +54,33 @@ check_SCRIPTS = $(TEST_SCRIPT)
# other current library code tests.
TEST_PROG= testhdf5 lheap ohdr stab gheap cache cache_api cache_tagging \
pool accum hyperslab istore bittests dt_arith \
- dtypes dsets cmpd_dset filter_fail extend external efc objcopy\
- links twriteorder unlink \
- big mtime fillval mount flush1 flush2 app_ref enum \
+ dtypes dsets cmpd_dset filter_fail extend external efc objcopy links unlink \
+ twriteorder big mtime fillval mount flush1 flush2 app_ref enum \
set_extent ttsafe enc_dec_plist enc_dec_plist_with_endianess\
getname vfd ntypes dangle dtransform reserved cross_read \
- freespace mf farray earray btree2 fheap file_image unregister
+ freespace mf farray earray btree2 fheap file_image unregister test_swmr
-bin_PROGRAMS=swmr_generator swmr_reader swmr_writer swmr_remove_reader \
+bin_PROGRAMS=swmr_generator swmr_start_write swmr_reader swmr_writer swmr_remove_reader \
swmr_remove_writer swmr_addrem_writer swmr_sparse_reader swmr_sparse_writer \
use_append_chunk use_append_mchunks atomic_writer atomic_reader accum_swmr_reader
-# List programs to be built when testing here. error_test and err_compat are
-# built at the same time as the other tests, but executed by testerror.sh.
+# List programs to be built when testing here.
+# error_test and err_compat are built at the same time as the other tests, but executed by testerror.sh.
# tcheck_version is used by testcheck_version.sh.
+# accum_swmr_reader is used by accum.c.
+# atomic_writer and atomic_reader are standalone programs.
+# links_env is used by testlinks_env.sh
+# flushrefresh is used by testflushrefresh.sh.
+# use_append_chunk and use_append_mchunks are used by test_usecases.sh
+# swmr* files are used by testswmr.sh.
# 'make check' doesn't run them directly, so they are not included in TEST_PROG.
# Also build testmeta, which is used for timings test. It builds quickly,
# and this lets automake keep all its test programs in one place.
-check_PROGRAMS=$(TEST_PROG) error_test err_compat tcheck_version testmeta links_env \
- flushrefresh
+check_PROGRAMS=$(TEST_PROG) error_test err_compat tcheck_version \
+ testmeta accum_swmr_reader atomic_writer atomic_reader \
+ links_env flushrefresh use_append_chunk use_append_mchunks \
+ swmr_generator swmr_start_write swmr_reader swmr_writer swmr_remove_reader \
+ swmr_remove_writer swmr_addrem_writer swmr_sparse_reader swmr_sparse_writer
if HAVE_SHARED_CONDITIONAL
check_PROGRAMS+= plugin
endif
@@ -160,10 +179,10 @@ CHECK_CLEANFILES+=accum.h5 cmpd_dset.h5 compact_dataset.h5 dataset.h5 \
new_multi_file_v16-r.h5 new_multi_file_v16-s.h5 \
split_get_file_image_test-m.h5 split_get_file_image_test-r.h5 \
file_image_core_test.h5.copy unregister_filter_1.h5 unregister_filter_2.h5 \
- swmr_data.h5 use_append_chunk.h5 use_append_mchunks.h5 \
+ swmr_data.h5 use_use_append_chunk.h5 use_append_mchunks.h5 \
flushrefresh.h5 flushrefresh_VERIFICATION_START \
flushrefresh_VERIFICATION_CHECKPOINT1 flushrefresh_VERIFICATION_CHECKPOINT2 \
- flushrefresh_VERIFICATION_DONE atomic_data accum_swmr_big.h5 ohdr_swmr.h5
+ flushrefresh_VERIFICATION_DONE atomic_data accum_swmr_big.h5 ohdr_swmr.h5 test_swmr.h5
# Sources for testhdf5 executable
testhdf5_SOURCES=testhdf5.c tarray.c tattr.c tchecksum.c tconfig.c tfile.c \
diff --git a/test/Makefile.in b/test/Makefile.in
index ce8c39a..7872c2c 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -79,16 +79,24 @@ DIST_COMMON = $(srcdir)/H5srcdir_str.h.in $(srcdir)/Makefile.am \
$(top_srcdir)/config/conclude.am COPYING
@HAVE_SHARED_CONDITIONAL_TRUE@am__append_1 = test_plugin.sh
@HAVE_SHARED_CONDITIONAL_TRUE@am__append_2 = plugin$(EXEEXT)
-bin_PROGRAMS = swmr_generator$(EXEEXT) swmr_reader$(EXEEXT) \
+bin_PROGRAMS = swmr_generator$(EXEEXT) swmr_start_write$(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) use_append_chunk$(EXEEXT) \
+ use_append_mchunks$(EXEEXT) atomic_writer$(EXEEXT) \
+ atomic_reader$(EXEEXT) accum_swmr_reader$(EXEEXT)
+check_PROGRAMS = $(am__EXEEXT_1) error_test$(EXEEXT) \
+ err_compat$(EXEEXT) tcheck_version$(EXEEXT) testmeta$(EXEEXT) \
+ accum_swmr_reader$(EXEEXT) atomic_writer$(EXEEXT) \
+ atomic_reader$(EXEEXT) links_env$(EXEEXT) \
+ flushrefresh$(EXEEXT) use_append_chunk$(EXEEXT) \
+ use_append_mchunks$(EXEEXT) swmr_generator$(EXEEXT) \
+ swmr_start_write$(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) \
- use_append_chunk$(EXEEXT) use_append_mchunks$(EXEEXT) \
- atomic_writer$(EXEEXT) atomic_reader$(EXEEXT) \
- accum_swmr_reader$(EXEEXT)
-check_PROGRAMS = $(am__EXEEXT_1) error_test$(EXEEXT) \
- err_compat$(EXEEXT) tcheck_version$(EXEEXT) testmeta$(EXEEXT) \
- links_env$(EXEEXT) flushrefresh$(EXEEXT) $(am__EXEEXT_2)
+ $(am__EXEEXT_2)
@HAVE_SHARED_CONDITIONAL_TRUE@am__append_3 = plugin
@BUILD_ALL_CONDITIONAL_TRUE@noinst_PROGRAMS = $(am__EXEEXT_3)
@DIRECT_VFD_CONDITIONAL_TRUE@am__append_4 = direct
@@ -168,7 +176,7 @@ am__EXEEXT_1 = testhdf5$(EXEEXT) lheap$(EXEEXT) ohdr$(EXEEXT) \
dt_arith$(EXEEXT) dtypes$(EXEEXT) dsets$(EXEEXT) \
cmpd_dset$(EXEEXT) filter_fail$(EXEEXT) extend$(EXEEXT) \
external$(EXEEXT) efc$(EXEEXT) objcopy$(EXEEXT) links$(EXEEXT) \
- twriteorder$(EXEEXT) unlink$(EXEEXT) big$(EXEEXT) \
+ unlink$(EXEEXT) twriteorder$(EXEEXT) big$(EXEEXT) \
mtime$(EXEEXT) fillval$(EXEEXT) mount$(EXEEXT) flush1$(EXEEXT) \
flush2$(EXEEXT) app_ref$(EXEEXT) enum$(EXEEXT) \
set_extent$(EXEEXT) ttsafe$(EXEEXT) enc_dec_plist$(EXEEXT) \
@@ -177,7 +185,7 @@ am__EXEEXT_1 = testhdf5$(EXEEXT) lheap$(EXEEXT) ohdr$(EXEEXT) \
dtransform$(EXEEXT) reserved$(EXEEXT) cross_read$(EXEEXT) \
freespace$(EXEEXT) mf$(EXEEXT) farray$(EXEEXT) earray$(EXEEXT) \
btree2$(EXEEXT) fheap$(EXEEXT) file_image$(EXEEXT) \
- unregister$(EXEEXT)
+ unregister$(EXEEXT) test_swmr$(EXEEXT)
@HAVE_SHARED_CONDITIONAL_TRUE@am__EXEEXT_2 = plugin$(EXEEXT)
am__EXEEXT_3 = gen_bad_ohdr$(EXEEXT) gen_bogus$(EXEEXT) \
gen_cross$(EXEEXT) gen_deflate$(EXEEXT) gen_filters$(EXEEXT) \
@@ -514,6 +522,10 @@ swmr_sparse_writer_SOURCES = swmr_sparse_writer.c
swmr_sparse_writer_OBJECTS = swmr_sparse_writer.$(OBJEXT)
swmr_sparse_writer_LDADD = $(LDADD)
swmr_sparse_writer_DEPENDENCIES = libh5test.la $(LIBHDF5)
+swmr_start_write_SOURCES = swmr_start_write.c
+swmr_start_write_OBJECTS = swmr_start_write.$(OBJEXT)
+swmr_start_write_LDADD = $(LDADD)
+swmr_start_write_DEPENDENCIES = libh5test.la $(LIBHDF5)
swmr_writer_SOURCES = swmr_writer.c
swmr_writer_OBJECTS = swmr_writer.$(OBJEXT)
swmr_writer_LDADD = $(LDADD)
@@ -522,6 +534,10 @@ tcheck_version_SOURCES = tcheck_version.c
tcheck_version_OBJECTS = tcheck_version.$(OBJEXT)
tcheck_version_LDADD = $(LDADD)
tcheck_version_DEPENDENCIES = libh5test.la $(LIBHDF5)
+test_swmr_SOURCES = test_swmr.c
+test_swmr_OBJECTS = test_swmr.$(OBJEXT)
+test_swmr_LDADD = $(LDADD)
+test_swmr_DEPENDENCIES = libh5test.la $(LIBHDF5)
am_testhdf5_OBJECTS = testhdf5.$(OBJEXT) tarray.$(OBJEXT) \
tattr.$(OBJEXT) tchecksum.$(OBJEXT) tconfig.$(OBJEXT) \
tfile.$(OBJEXT) tgenprop.$(OBJEXT) th5o.$(OBJEXT) \
@@ -624,10 +640,10 @@ SOURCES = $(libdynlib1_la_SOURCES) $(libdynlib2_la_SOURCES) \
set_extent.c space_overflow.c stab.c swmr_addrem_writer.c \
swmr_generator.c swmr_reader.c swmr_remove_reader.c \
swmr_remove_writer.c swmr_sparse_reader.c swmr_sparse_writer.c \
- swmr_writer.c tcheck_version.c $(testhdf5_SOURCES) testmeta.c \
- $(ttsafe_SOURCES) twriteorder.c unlink.c unregister.c \
- $(use_append_chunk_SOURCES) $(use_append_mchunks_SOURCES) \
- vfd.c
+ swmr_start_write.c swmr_writer.c tcheck_version.c test_swmr.c \
+ $(testhdf5_SOURCES) testmeta.c $(ttsafe_SOURCES) twriteorder.c \
+ unlink.c unregister.c $(use_append_chunk_SOURCES) \
+ $(use_append_mchunks_SOURCES) vfd.c
DIST_SOURCES = $(am__libdynlib1_la_SOURCES_DIST) \
$(am__libdynlib2_la_SOURCES_DIST) \
$(am__libdynlib3_la_SOURCES_DIST) $(libh5test_la_SOURCES) \
@@ -649,10 +665,10 @@ DIST_SOURCES = $(am__libdynlib1_la_SOURCES_DIST) \
set_extent.c space_overflow.c stab.c swmr_addrem_writer.c \
swmr_generator.c swmr_reader.c swmr_remove_reader.c \
swmr_remove_writer.c swmr_sparse_reader.c swmr_sparse_writer.c \
- swmr_writer.c tcheck_version.c $(testhdf5_SOURCES) testmeta.c \
- $(ttsafe_SOURCES) twriteorder.c unlink.c unregister.c \
- $(use_append_chunk_SOURCES) $(use_append_mchunks_SOURCES) \
- vfd.c
+ swmr_start_write.c swmr_writer.c tcheck_version.c test_swmr.c \
+ $(testhdf5_SOURCES) testmeta.c $(ttsafe_SOURCES) twriteorder.c \
+ unlink.c unregister.c $(use_append_chunk_SOURCES) \
+ $(use_append_mchunks_SOURCES) vfd.c
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@@ -977,21 +993,34 @@ CHECK_CLEANFILES = *.chkexe *.chklog *.clog accum.h5 cmpd_dset.h5 \
new_multi_file_v16-r.h5 new_multi_file_v16-s.h5 \
split_get_file_image_test-m.h5 split_get_file_image_test-r.h5 \
file_image_core_test.h5.copy unregister_filter_1.h5 \
- unregister_filter_2.h5 swmr_data.h5 use_append_chunk.h5 \
+ unregister_filter_2.h5 swmr_data.h5 use_use_append_chunk.h5 \
use_append_mchunks.h5 flushrefresh.h5 \
flushrefresh_VERIFICATION_START \
flushrefresh_VERIFICATION_CHECKPOINT1 \
flushrefresh_VERIFICATION_CHECKPOINT2 \
flushrefresh_VERIFICATION_DONE atomic_data accum_swmr_big.h5 \
- ohdr_swmr.h5
+ ohdr_swmr.h5 test_swmr.h5
INCLUDES = -I$(top_srcdir)/src -I$(top_builddir)/src
-# Test script for error_test and err_compat
+# Test scripts--
+# testerror.sh: err_compat, error_test
+# testlibinfo.sh:
+# testcheck_version.sh: tcheck_version
+# tetlinks_env.sh: links_env
+# testflushrefresh.sh: flushrefresh
+# test_usecases.sh: use_append_chunk, use_append_mchunks
+# testswmr.sh: swmr*
TEST_SCRIPT = testerror.sh testlibinfo.sh testcheck_version.sh \
- testlinks_env.sh $(srcdir)/testswmr.sh testflushrefresh.sh \
- test_usecases.sh $(am__append_1)
+ testlinks_env.sh testflushrefresh.sh test_usecases.sh \
+ $(srcdir)/testswmr.sh $(am__append_1)
SCRIPT_DEPEND = error_test$(EXEEXT) err_compat$(EXEEXT) \
- links_env$(EXEEXT) $(am__append_2)
+ links_env$(EXEEXT) flushrefresh$(EXEEXT) \
+ use_append_chunk$(EXEEXT) use_append_mchunks$(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) $(am__append_2)
check_SCRIPTS = $(TEST_SCRIPT)
# These are our main targets. They should be listed in the order to be
@@ -1003,12 +1032,11 @@ check_SCRIPTS = $(TEST_SCRIPT)
# other current library code tests.
TEST_PROG = testhdf5 lheap ohdr stab gheap cache cache_api cache_tagging \
pool accum hyperslab istore bittests dt_arith \
- dtypes dsets cmpd_dset filter_fail extend external efc objcopy\
- links twriteorder unlink \
- big mtime fillval mount flush1 flush2 app_ref enum \
+ dtypes dsets cmpd_dset filter_fail extend external efc objcopy links unlink \
+ twriteorder big mtime fillval mount flush1 flush2 app_ref enum \
set_extent ttsafe enc_dec_plist enc_dec_plist_with_endianess\
getname vfd ntypes dangle dtransform reserved cross_read \
- freespace mf farray earray btree2 fheap file_image unregister
+ freespace mf farray earray btree2 fheap file_image unregister test_swmr
# These programs generate test files for the tests. They don't need to be
@@ -1486,12 +1514,18 @@ swmr_sparse_reader$(EXEEXT): $(swmr_sparse_reader_OBJECTS) $(swmr_sparse_reader_
swmr_sparse_writer$(EXEEXT): $(swmr_sparse_writer_OBJECTS) $(swmr_sparse_writer_DEPENDENCIES) $(EXTRA_swmr_sparse_writer_DEPENDENCIES)
@rm -f swmr_sparse_writer$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(swmr_sparse_writer_OBJECTS) $(swmr_sparse_writer_LDADD) $(LIBS)
+swmr_start_write$(EXEEXT): $(swmr_start_write_OBJECTS) $(swmr_start_write_DEPENDENCIES) $(EXTRA_swmr_start_write_DEPENDENCIES)
+ @rm -f swmr_start_write$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(swmr_start_write_OBJECTS) $(swmr_start_write_LDADD) $(LIBS)
swmr_writer$(EXEEXT): $(swmr_writer_OBJECTS) $(swmr_writer_DEPENDENCIES) $(EXTRA_swmr_writer_DEPENDENCIES)
@rm -f swmr_writer$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(swmr_writer_OBJECTS) $(swmr_writer_LDADD) $(LIBS)
tcheck_version$(EXEEXT): $(tcheck_version_OBJECTS) $(tcheck_version_DEPENDENCIES) $(EXTRA_tcheck_version_DEPENDENCIES)
@rm -f tcheck_version$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(tcheck_version_OBJECTS) $(tcheck_version_LDADD) $(LIBS)
+test_swmr$(EXEEXT): $(test_swmr_OBJECTS) $(test_swmr_DEPENDENCIES) $(EXTRA_test_swmr_DEPENDENCIES)
+ @rm -f test_swmr$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_swmr_OBJECTS) $(test_swmr_LDADD) $(LIBS)
testhdf5$(EXEEXT): $(testhdf5_OBJECTS) $(testhdf5_DEPENDENCIES) $(EXTRA_testhdf5_DEPENDENCIES)
@rm -f testhdf5$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(testhdf5_OBJECTS) $(testhdf5_LDADD) $(LIBS)
@@ -1613,6 +1647,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/swmr_remove_writer.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/swmr_sparse_reader.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/swmr_sparse_writer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/swmr_start_write.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/swmr_writer.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tarray.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tattr.Po@am__quote@
@@ -1620,6 +1655,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tchecksum.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tconfig.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcoords.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_swmr.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testframe.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testhdf5.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testmeta.Po@am__quote@
diff --git a/test/accum.c b/test/accum.c
index fc7546d..b37a1bd 100644
--- a/test/accum.c
+++ b/test/accum.c
@@ -1672,7 +1672,7 @@ test_random_write(void)
/* Allocate space for the write & read buffers */
wbuf = (uint8_t *)HDmalloc((size_t)RANDOM_BUF_SIZE);
HDassert(wbuf);
- rbuf = (uint8_t *)HDcalloc((size_t)RANDOM_BUF_SIZE, 1);
+ rbuf = (uint8_t *)HDcalloc((size_t)RANDOM_BUF_SIZE, (size_t)1);
HDassert(rbuf);
/* Initialize write buffer */
@@ -1815,6 +1815,14 @@ test_swmr_write_big(void)
TESTING("SWMR write of large metadata");
+ #if !(defined(H5_HAVE_FORK) && defined(H5_HAVE_WAITPID))
+
+ SKIPPED();
+ HDputs(" Test skipped due to fork or waitpid not defined.");
+ return 0;
+
+#else /* defined(H5_HAVE_FORK && defined(H5_HAVE_WAITPID) */
+
/* File access property list */
if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0)
FAIL_STACK_ERROR
@@ -1941,6 +1949,9 @@ error:
if(rbuf) HDfree(rbuf);
return 1;
+
+#endif
+
} /* end test_swmr_write_big() */
diff --git a/test/accum_swmr_reader.c b/test/accum_swmr_reader.c
index b9bf98d..034ed46 100644
--- a/test/accum_swmr_reader.c
+++ b/test/accum_swmr_reader.c
@@ -65,7 +65,7 @@ main(void)
FAIL_STACK_ERROR;
/* Verify the data read is correct */
- if(HDmemcmp(buf, rbuf, 1024) != 0)
+ if(HDmemcmp(buf, rbuf, (size_t)1024) != 0)
TEST_ERROR;
/* CLose the file */
diff --git a/test/bad_compound.h5 b/test/bad_compound.h5
index 1834a2e..1c96318 100644
--- a/test/bad_compound.h5
+++ b/test/bad_compound.h5
Binary files differ
diff --git a/test/btree_idx_1_6.h5 b/test/btree_idx_1_6.h5
index b1ac4da..92f939b 100644
--- a/test/btree_idx_1_6.h5
+++ b/test/btree_idx_1_6.h5
Binary files differ
diff --git a/test/corrupt_stab_msg.h5 b/test/corrupt_stab_msg.h5
index 4fa287c..a00616d 100644
--- a/test/corrupt_stab_msg.h5
+++ b/test/corrupt_stab_msg.h5
Binary files differ
diff --git a/test/deflate.h5 b/test/deflate.h5
index 2f62e25..e33af4f 100644
--- a/test/deflate.h5
+++ b/test/deflate.h5
Binary files differ
diff --git a/test/family_v16_00000.h5 b/test/family_v16_00000.h5
index ac75ea9..aaa3dad 100644
--- a/test/family_v16_00000.h5
+++ b/test/family_v16_00000.h5
Binary files differ
diff --git a/test/file_image.c b/test/file_image.c
index b1b9d47..2eea59b 100644
--- a/test/file_image.c
+++ b/test/file_image.c
@@ -41,6 +41,8 @@
#define FAMILY_SIZE (2 * 1024)
+#define USERBLOCK_SIZE 512
+
const char *FILENAME[] = {
"file_image_core_test",
NULL
@@ -549,7 +551,7 @@ test_core(void)
VERIFY(fapl >= 0, "fapl creation failed");
/* Set up the core VFD */
- ret = H5Pset_fapl_core(fapl, 0, 0);
+ ret = H5Pset_fapl_core(fapl, (size_t)0, 0);
VERIFY(ret >= 0, "setting core driver in fapl failed");
tmp = h5_fixname(FILENAME[0], fapl, filename, sizeof(filename));
@@ -665,12 +667,17 @@ error:
* Programmer: John Mainzer
* Tuesday, November 15, 2011
*
+ * Modifications:
+ * Vailin Choi; July 2013
+ * Add the creation of user block to the file as indicated by the parameter "user".
+ *
******************************************************************************
*/
static int
test_get_file_image(const char * test_banner,
const int file_name_num,
- hid_t fapl)
+ hid_t fapl,
+ hbool_t user)
{
char file_name[1024] = "\0";
void * insertion_ptr = NULL;
@@ -694,6 +701,8 @@ test_get_file_image(const char * test_banner,
ssize_t image_size;
ssize_t file_size;
h5_stat_t stat_buf;
+ hid_t fcpl = -1;
+ herr_t ret;
TESTING(test_banner);
@@ -708,8 +717,15 @@ test_get_file_image(const char * test_banner,
h5_fixname(FILENAME2[file_name_num], fapl, file_name, sizeof(file_name));
VERIFY(HDstrlen(file_name)>0, "h5_fixname failed");
+ fcpl = H5Pcreate(H5P_FILE_CREATE);
+ VERIFY(fcpl >= 0, "H5Pcreate");
+ if(user) {
+ ret = H5Pset_userblock(fcpl, (hsize_t)USERBLOCK_SIZE);
+ VERIFY(ret >=0, "H5Pset_userblock");
+ }
+
/* create the file */
- file_id = H5Fcreate(file_name, 0, H5P_DEFAULT, fapl);
+ file_id = H5Fcreate(file_name, 0, fcpl, fapl);
VERIFY(file_id >= 0, "H5Fcreate() failed.");
/* Set up data space for new new data set */
@@ -761,11 +777,15 @@ test_get_file_image(const char * test_banner,
ssize_t member_size;
ssize_t size_remaining;
+ /*
+ * Modifications need to be made to accommodate userblock when
+ * H5Fget_file_image() works for family driver
+ */
i = 0;
file_size = 0;
do {
- HDsnprintf(member_file_name, 1024, file_name, i);
+ HDsnprintf(member_file_name, (size_t)1024, file_name, i);
/* get the size of the member file */
result = HDstat(member_file_name, &stat_buf);
@@ -829,6 +849,10 @@ test_get_file_image(const char * test_banner,
* the remainder of the file is all '\0's.
*/
file_size = (ssize_t)stat_buf.st_size;
+ if(user) {
+ VERIFY(file_size > USERBLOCK_SIZE, "file size !> userblock size.");
+ file_size -= USERBLOCK_SIZE;
+ }
/* with latest mods to truncate call in core file drive,
* file size should match image size
@@ -843,6 +867,12 @@ test_get_file_image(const char * test_banner,
fd = HDopen(file_name, O_RDONLY, 0666);
VERIFY(fd >= 0, "HDopen() failed.");
+ if(user) {
+ /* Position at userblock */
+ ret = HDlseek(fd, (off_t)USERBLOCK_SIZE, SEEK_SET);
+ VERIFY(ret >= 0, "HDlseek() failed.");
+ }
+
/* read the test file from disk into the buffer */
bytes_read = HDread(fd, file_image_ptr, (size_t)file_size);
VERIFY(bytes_read == file_size, "HDread() failed.");
@@ -1278,13 +1308,18 @@ test_get_file_image_error_rejection(void)
error:
return 1;
-}
+} /* test_get_file_image_error_rejection() */
+/*
+ * Modifications:
+ * Add testing for file image with or without user block in the file.
+ */
int
main(void)
{
int errors = 0;
hid_t fapl;
+ hbool_t user;
h5_reset();
@@ -1294,29 +1329,34 @@ main(void)
errors += test_callbacks();
errors += test_core();
- /* test H5Fget_file_image() with sec2 driver */
- fapl = H5Pcreate(H5P_FILE_ACCESS);
- if(H5Pset_fapl_sec2(fapl) < 0)
- errors++;
- else
- errors += test_get_file_image("H5Fget_file_image() with sec2 driver",
- 0, fapl);
-
- /* test H5Fget_file_image() with stdio driver */
- fapl = H5Pcreate(H5P_FILE_ACCESS);
- if(H5Pset_fapl_stdio(fapl) < 0)
- errors++;
- else
- errors += test_get_file_image("H5Fget_file_image() with stdio driver",
- 1, fapl);
-
- /* test H5Fget_file_image() with core driver */
- fapl = H5Pcreate(H5P_FILE_ACCESS);
- if(H5Pset_fapl_core(fapl, (size_t)(64 *1024), TRUE) < 0)
- errors++;
- else
- errors += test_get_file_image("H5Fget_file_image() with core driver",
- 2, fapl);
+ /* Perform tests with/without user block */
+ for(user = FALSE; user <= TRUE; user++) {
+
+ /* test H5Fget_file_image() with sec2 driver */
+ fapl = H5Pcreate(H5P_FILE_ACCESS);
+ if(H5Pset_fapl_sec2(fapl) < 0)
+ errors++;
+ else
+ errors += test_get_file_image("H5Fget_file_image() with sec2 driver",
+ 0, fapl, user);
+
+ /* test H5Fget_file_image() with stdio driver */
+ fapl = H5Pcreate(H5P_FILE_ACCESS);
+ if(H5Pset_fapl_stdio(fapl) < 0)
+ errors++;
+ else
+ errors += test_get_file_image("H5Fget_file_image() with stdio driver",
+ 1, fapl, user);
+
+ /* test H5Fget_file_image() with core driver */
+ fapl = H5Pcreate(H5P_FILE_ACCESS);
+ if(H5Pset_fapl_core(fapl, (size_t)(64 *1024), TRUE) < 0)
+ errors++;
+ else
+ errors += test_get_file_image("H5Fget_file_image() with core driver",
+ 2, fapl, user);
+
+ } /* end for */
#if 0
/* at present, H5Fget_file_image() rejects files opened with the
diff --git a/test/filespace_1_6.h5 b/test/filespace_1_6.h5
index 5afc718..c8aa9df 100644
--- a/test/filespace_1_6.h5
+++ b/test/filespace_1_6.h5
Binary files differ
diff --git a/test/fill_old.h5 b/test/fill_old.h5
index e77f519..4dd7740 100644
--- a/test/fill_old.h5
+++ b/test/fill_old.h5
Binary files differ
diff --git a/test/flush2.c b/test/flush2.c
index 06dd086..8459087 100644
--- a/test/flush2.c
+++ b/test/flush2.c
@@ -24,6 +24,11 @@
*/
#include "h5test.h"
+/* Make this private property (defined in H5Fprivate.h) available */
+/* This is used in the helper routine clear_status_flags() */
+#define H5F_ACS_CLEAR_STATUS_FLAGS_NAME "clear_status_flags"
+
+
const char *FILENAME[] = {
"flush",
"noflush",
@@ -135,6 +140,53 @@ error:
return 1;
} /* end check_file() */
+/*-------------------------------------------------------------------------
+ * Function: clear_status_flags
+ *
+ * Purpose: To clear the status_flags in the superblock of the file.
+ * It is smilar to the tool "h5clear".
+ *
+ * Return: Success: 0
+ * Failure: 1
+ *
+ * Programmer: Vailin Choi
+ * July 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+clear_status_flags(char *name, hid_t fapl)
+{
+ hid_t new_fapl = -1;
+ hid_t fid = -1;
+ hbool_t clear = TRUE;
+
+ /* Get a copy of fapl */
+ if((new_fapl = H5Pcopy(fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Set this private property */
+ if(H5Pset(new_fapl, H5F_ACS_CLEAR_STATUS_FLAGS_NAME, &clear) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Has to open rw */
+ if((fid = H5Fopen(name, H5F_ACC_RDWR, new_fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /* CLose the property list */
+ if(H5Pclose(new_fapl) < 0)
+ FAIL_STACK_ERROR;
+
+ return 0;
+
+error:
+ return 1;
+} /* clear_status_flags() */
+
/*-------------------------------------------------------------------------
* Function: main
@@ -167,6 +219,13 @@ main(void)
/* Check the case where the file was flushed */
h5_fixname(FILENAME[0], fapl, name, sizeof name);
+
+ /* Clear the status_flags of the file which is flushed and exited in flush1.c */
+ if(clear_status_flags(name, fapl) < 0) {
+ H5_FAILED()
+ goto error;
+ }
+
if(check_file(name, fapl, FALSE)) {
H5_FAILED()
goto error;
@@ -182,6 +241,8 @@ main(void)
H5Eset_auto2(H5E_DEFAULT, NULL, NULL);
h5_fixname(FILENAME[1], fapl, name, sizeof name);
+ /* No need to clear the status_flags because this file is not flushed in flush1.c */
+ /* H5Fopen() in check_file() will just return error */
if(check_file(name, fapl, FALSE))
PASSED()
else
@@ -205,6 +266,13 @@ main(void)
H5Eset_auto2(H5E_DEFAULT, NULL, NULL);
h5_fixname(FILENAME[2], fapl, name, sizeof name);
+
+ /* Clear the status_flags of the file which is flushed and exited in flush1.c */
+ if(clear_status_flags(name, fapl) < 0) {
+ H5_FAILED()
+ goto error;
+ }
+
if(check_file(name, fapl, TRUE))
PASSED()
else
diff --git a/test/group_old.h5 b/test/group_old.h5
index 58f66f8..2440103 100644
--- a/test/group_old.h5
+++ b/test/group_old.h5
Binary files differ
diff --git a/test/h5test.c b/test/h5test.c
index 30a3adf..79b97cc 100644
--- a/test/h5test.c
+++ b/test/h5test.c
@@ -1231,3 +1231,56 @@ error:
return -1;
}
+/*
+ * To send a message by creating the file.
+ * This is a helper routine used in:
+ * 1) tfile.c: test_file_lock_concur() and test_file_lock_swmr_concur()
+ * 2) use_common.c
+ * 3) swmr_addrme_writer.c, swmr_remove_writer.c, swmr_sparse_writer.c, swmr_writer.c
+ */
+void
+h5_send_message(const char *file)
+{
+ FILE *id;
+
+ id = HDfopen(file, "w+");
+ HDfclose(id);
+} /* h5_send_message() */
+
+/*
+ * Repeatedly check for the message file.
+ * It will stop when the file exists or exceeds the timeout limit.
+ * This is a helper routine used in:
+ * 1) tfile.c: test_file_lock_concur() and test_file_lock_swmr_concur()
+ * 2) use_common.c
+ */
+int
+h5_wait_message(const char *file)
+{
+ FILE *id; /* File pointer */
+ time_t t0, t1; /* Time info */
+
+ /* Start timer */
+ HDtime(&t0);
+
+ /* Repeatedly check whether the file exists */
+ while((id = HDfopen(file, "r")) == NULL) {
+ /* Get current time */
+ HDtime(&t1);
+ /*
+ * Determine time difference--
+ * if waiting too long for the message, then it is
+ * unlikely the message will get sent, then fail rather
+ * than loop forever.
+ */
+ if(HDdifftime(t1, t0) > MESSAGE_TIMEOUT)
+ goto done;
+ }
+
+ if(id != NULL) HDfclose(id);
+ HDunlink(file);
+ return(1);
+
+done:
+ return(-1);
+} /* h5_wait_message() */
diff --git a/test/h5test.h b/test/h5test.h
index 7813b51..745fe85 100644
--- a/test/h5test.h
+++ b/test/h5test.h
@@ -136,6 +136,9 @@ H5TEST_DLLVAR MPI_Info h5_io_info_g; /* MPI INFO object for IO */
#define DBL_REL_EQUAL(X,Y,M) (fabs((Y-X)/X)<M)
#define LDBL_REL_EQUAL(X,Y,M) (fabsl((Y-X)/X)<M)
+/* The # of seconds to wait for the message file--used by h5_wait_message() */
+#define MESSAGE_TIMEOUT 300 /* Timeout in seconds */
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -194,6 +197,9 @@ H5TEST_DLL char* getenv_all(MPI_Comm comm, int root, const char* name);
/* Extern global variables */
H5TEST_DLLVAR int TestVerbosity;
+H5TEST_DLL void h5_send_message(const char *file);
+H5TEST_DLL int h5_wait_message(const char *file);
+
#ifdef __cplusplus
}
#endif
diff --git a/test/mergemsg.h5 b/test/mergemsg.h5
index 3a9e352..55c3135 100644
--- a/test/mergemsg.h5
+++ b/test/mergemsg.h5
Binary files differ
diff --git a/test/multi_file_v16-s.h5 b/test/multi_file_v16-s.h5
index e990e95..2d4de48 100644
--- a/test/multi_file_v16-s.h5
+++ b/test/multi_file_v16-s.h5
Binary files differ
diff --git a/test/swmr_addrem_writer.c b/test/swmr_addrem_writer.c
index c15854c..0df8dec 100644
--- a/test/swmr_addrem_writer.c
+++ b/test/swmr_addrem_writer.c
@@ -421,6 +421,9 @@ int main(int argc, const char *argv[])
exit(1);
} /* end if */
+ /* Send a message to indicate "H5Fopen" is complete--releasing the file lock */
+ h5_send_message(WRITER_MESSAGE);
+
/* Emit informational message */
if(verbose)
fprintf(stderr, "Adding and removing records\n");
diff --git a/test/swmr_common.c b/test/swmr_common.c
index 6cbd5e2..30e1b3e 100644
--- a/test/swmr_common.c
+++ b/test/swmr_common.c
@@ -125,7 +125,7 @@ create_symbol_datatype(void)
hid_t opaq_type_id; /* Datatype ID for opaque part of record */
/* Create opaque datatype to represent other information for this record */
- if((opaq_type_id = H5Tcreate(H5T_OPAQUE, DTYPE_SIZE)) < 0)
+ if((opaq_type_id = H5Tcreate(H5T_OPAQUE, (size_t)DTYPE_SIZE)) < 0)
return -1;
/* Create compound datatype for symbol */
diff --git a/test/swmr_common.h b/test/swmr_common.h
index b80ad12..49f55fa 100644
--- a/test/swmr_common.h
+++ b/test/swmr_common.h
@@ -25,6 +25,7 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "hdf5.h"
+#include "h5test.h"
/**********/
/* Macros */
@@ -44,6 +45,9 @@
#define FILENAME "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 "SWMR_WRITER_MESSAGE"
+
/************/
/* Typedefs */
/************/
diff --git a/test/swmr_remove_writer.c b/test/swmr_remove_writer.c
index 33d8899..f8fc8d1 100644
--- a/test/swmr_remove_writer.c
+++ b/test/swmr_remove_writer.c
@@ -340,6 +340,9 @@ int main(int argc, const char *argv[])
exit(1);
} /* end if */
+ /* Send a message to indicate "H5Fopen" is complete--releasing the file lock */
+ h5_send_message(WRITER_MESSAGE);
+
/* Emit informational message */
if(verbose)
fprintf(stderr, "Removing records\n");
diff --git a/test/swmr_sparse_writer.c b/test/swmr_sparse_writer.c
index d30c86d..5866b38 100644
--- a/test/swmr_sparse_writer.c
+++ b/test/swmr_sparse_writer.c
@@ -293,12 +293,14 @@ add_records(hid_t fid, unsigned verbose, unsigned long nrecords, unsigned long f
} /* end if */
} /* end if */
+#ifdef OUT
/* Busy wait, to let readers catch up */
dummy = 0;
for(v=0; v<BUSY_WAIT; v++)
dummy++;
if((unsigned long)dummy != v)
return -1;
+#endif
} /* end for */
/* Close the memory dataspace */
@@ -415,6 +417,9 @@ int main(int argc, const char *argv[])
exit(1);
} /* end if */
+ /* Send a message to indicate "H5Fopen" is complete--releasing the file lock */
+ h5_send_message(WRITER_MESSAGE);
+
/* Emit informational message */
if(verbose)
fprintf(stderr, "Adding records\n");
diff --git a/test/swmr_start_write.c b/test/swmr_start_write.c
new file mode 100644
index 0000000..a124160
--- /dev/null
+++ b/test/swmr_start_write.c
@@ -0,0 +1,691 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: swmr_start_write.c
+ *
+ * Purpose: This program enables SWMR writing mode via H5Fstart_swmr_write().
+ * It writes data to a randomly selected subset of the datasets
+ * in the SWMR test file; and it is intended to run concurrently
+ * with the swmr_reader program.
+ *
+ * NOTE: The routines in this program are basically copied and modified from
+ * swmr*.c.
+ *-------------------------------------------------------------------------
+ */
+
+/***********/
+/* Headers */
+/***********/
+
+#include <assert.h>
+#include <sys/time.h>
+
+#include "swmr_common.h"
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+static hid_t create_file(const char *filename, unsigned verbose,
+ const char *index_type, unsigned random_seed);
+static int create_close_datasets(hid_t fid, int comp_level, unsigned verbose);
+static hid_t open_datasets(hid_t fid, unsigned verbose);
+static hid_t open_file(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);
+
+#define CHUNK_SIZE 50 /* Chunk size for created datasets */
+
+
+/*-------------------------------------------------------------------------
+ * Function: create_file
+ *
+ * Purpose: Creates the HDF5 file (without SWMR access) which
+ * which will be used for testing H5Fstart_swmr_write().
+ *
+ * Parameters:
+ * filename: The SWMR test file's name.
+ * verbose: whether verbose console output is desired.
+ * index_type: The chunk index type (b1 | b2 | ea | fa)
+ * random_seed: The random seed to store in the file.
+ * The sparse tests use this value.
+ *
+ * Return: Success: the file ID
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static hid_t
+create_file(const char *filename, unsigned verbose,
+ 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 sid; /* Dataspace ID */
+ hid_t aid; /* Attribute ID */
+ hsize_t max_dims[2] = {1, H5S_UNLIMITED}; /* Dataset maximum dimensions */
+#ifdef FILLVAL_WORKS
+ symbol_t fillval; /* Dataset fill value */
+#endif /* FILLVAL_WORKS */
+
+ assert(filename);
+ assert(index_type);
+
+ /* Create file access property list */
+ if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0)
+ return -1;
+
+ /* We ALWAYS select the latest file format for SWMR */
+ 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 v-2 B-tree.
+ */
+ if(!strcmp(index_type, "b2"))
+ max_dims[0] = H5S_UNLIMITED;
+
+#ifdef QAK
+ /* Increase the initial size of the metadata cache */
+ {
+ H5AC_cache_config_t mdc_config;
+
+ mdc_config.version = H5AC__CURR_CACHE_CONFIG_VERSION;
+ H5Pget_mdc_config(fapl, &mdc_config);
+ fprintf(stderr, "mdc_config.initial_size = %lu\n", (unsigned long)mdc_config.initial_size);
+ fprintf(stderr, "mdc_config.epoch_length = %lu\n", (unsigned long)mdc_config.epoch_length);
+ mdc_config.set_initial_size = 1;
+ mdc_config.initial_size = 16 * 1024 * 1024;
+ /* mdc_config.epoch_length = 5000; */
+ H5Pset_mdc_config(fapl, &mdc_config);
+ }
+#endif /* QAK */
+
+#ifdef QAK
+ H5Pset_small_data_block_size(fapl, (hsize_t)(50 * CHUNK_SIZE * DTYPE_SIZE));
+#endif /* QAK */
+
+#ifdef QAK
+ H5Pset_fapl_log(fapl, "append.log", H5FD_LOG_ALL, (size_t)(512 * 1024 * 1024));
+#endif /* QAK */
+
+ /* Create file creation property list */
+ if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0)
+ return -1;
+
+#ifdef QAK
+ H5Pset_link_phase_change(fcpl, 0, 0);
+#endif /* QAK */
+
+ /* Emit informational message */
+ if(verbose)
+ fprintf(stderr, "Creating file without SWMR access\n");
+
+ /* Create the file */
+ 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(H5Sclose(sid) < 0)
+ return -1;
+ if(H5Aclose(aid) < 0)
+ return -1;
+
+ return fid;
+} /* end create_file() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: create_close_datasets
+ *
+ * Purpose: Create and close datasets which will be used for testing
+ * H5Fstart_swmr_write().
+ *
+ * Parameters:
+ * fid: file ID for the SWMR test file
+ * comp_level: the compresssion level
+ * verbose: whether verbose console output is desired.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+create_close_datasets(hid_t fid, int comp_level, unsigned verbose)
+{
+ hid_t dcpl; /* Dataset creation property list */
+ hid_t tid; /* Datatype for dataset elements */
+ hid_t sid; /* Dataspace 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 */
+ unsigned u, v; /* Local index variable */
+
+ /* 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 */
+
+ /* Emit informational message */
+ if(verbose)
+ fprintf(stderr, "Creating datasets\n");
+
+ /* 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];
+
+ generate_name(name_buf, u, v);
+ if((dsid = H5Dcreate2(fid, name_buf, tid, sid, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0)
+ return -1;
+
+ if(H5Dclose(dsid) < 0)
+ return -1;
+ } /* end for */
+
+ /* Closing */
+ if(H5Pclose(dcpl) < 0)
+ return -1;
+ if(H5Sclose(sid) < 0)
+ return -1;
+ if(H5Tclose(tid) < 0)
+ return -1;
+
+ return 0;
+} /* create_close_datasets() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: open_file
+ *
+ * Purpose: Opens the HDF5 test file without SWMR access.
+ *
+ * Parameters:
+ * filename: The filename of the HDF5 file to open
+ * verbose: whether or not to emit verbose console messages
+ *
+ * Return: Success: The file ID of the opened SWMR file
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static hid_t
+open_file(const char *filename, unsigned verbose)
+{
+ hid_t fid; /* File ID for new HDF5 file */
+ hid_t fapl; /* File access property list */
+
+ assert(filename);
+
+ /* Create file access property list */
+ if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0)
+ return -1;
+
+ /* Set to use the latest library format */
+ if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
+ return -1;
+
+ /* Emit informational message */
+ if(verbose)
+ fprintf(stderr, "Opening the file without SWMR access: %s\n", filename);
+
+ /* Open the file */
+ if((fid = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
+ return -1;
+
+ /* Close file access property list */
+ if(H5Pclose(fapl) < 0)
+ return -1;
+
+ return fid;
+} /* Open file() */
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: open_datasets
+ *
+ * Purpose: Opens the datasets.
+ *
+ * Parameters:
+* filename: the filename of the SWMR HDF5 file to open
+ * verbose: whether or not to emit verbose console messages
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+open_datasets(hid_t fid, unsigned verbose)
+{
+ unsigned u, v; /* Local index variable */
+
+ /* Emit informational message */
+ if(verbose)
+ fprintf(stderr, "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 0;
+} /* open_datasets() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: add_records
+ *
+ * Purpose: Writes a specified number of records to random datasets in
+ * the SWMR test file.
+ *
+ * Parameters:
+* fid: The file ID of the SWMR HDF5 file
+ * verbose: Whether or not to emit verbose console messages
+ * nrecords: # of records to write to the datasets
+ * 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; /* 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 */
+ H5AC_cache_config_t mdc_config_orig; /* Original metadata cache configuration */
+ H5AC_cache_config_t mdc_config_cork; /* Corked metadata cache configuration */
+ unsigned long rec_to_flush; /* # of records left to write before flush */
+ unsigned long u, v; /* Local index variables */
+
+ assert(fid >= 0);
+
+ /* Reset the record */
+ /* (record's 'info' field might need to change for each record written, also) */
+ memset(&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;
+
+ /* Get the current metadata cache configuration, and set up the corked
+ * configuration */
+ mdc_config_orig.version = H5AC__CURR_CACHE_CONFIG_VERSION;
+ if(H5Fget_mdc_config(fid, &mdc_config_orig) < 0)
+ return -1;
+ memcpy(&mdc_config_cork, &mdc_config_orig, sizeof(mdc_config_cork));
+ mdc_config_cork.evictions_enabled = FALSE;
+ mdc_config_cork.incr_mode = H5C_incr__off;
+ mdc_config_cork.flash_incr_mode = H5C_flash_incr__off;
+ mdc_config_cork.decr_mode = H5C_decr__off;
+
+ /* 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();
+
+ /* Set the record's ID (equal to its position) */
+ record.rec_id = symbol->nrecords;
+
+ /* Get the coordinate to write */
+ start[1] = symbol->nrecords;
+
+ /* Cork the metadata cache, to prevent the object header from being
+ * flushed before the data has been written */
+ /*if(H5Fset_mdc_config(fid, &mdc_config_cork) < 0)
+ return(-1);*/
+
+ /* 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;
+
+ /* Uncork the metadata cache */
+ /*if(H5Fset_mdc_config(fid, &mdc_config_orig) < 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) {
+ /* Flush contents of file */
+ if(H5Fflush(fid, H5F_SCOPE_GLOBAL) < 0)
+ return -1;
+
+ /* 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)
+ fprintf(stderr, "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;
+} /* add_records() */
+
+static void
+usage(void)
+{
+ printf("\n");
+ printf("Usage error!\n");
+ printf("\n");
+ printf("Usage: swmr_start_write [-f <# of records to write between flushing file contents>]\n");
+ printf(" [-i <index type>] [-c <deflate compression level>]\n");
+ printf(" [-r <random seed>] [-q] <# 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("<index type> should be b2 or ea\n");
+ printf("\n");
+ printf("<deflate compression level> should be -1 (for no compression) or 0-9\n");
+ printf("\n");
+ printf("<# of records> must be specified.\n");
+ printf("\n");
+ printf("Defaults to flushing every 10000 records ('-f 10000'),\n");
+ printf("v1 b-tree indexing (-i b1), compression ('-c -1'),\n");
+ printf("will generate a random seed (no -r given), and verbose (no '-q' given)\n");
+ printf("\n");
+ exit(1);
+} /* usage() */
+
+/*
+ * Can test with different scenarios as listed below. Scenario (1) is tested here.
+ * 1) create_file(), create_close_datasets(), H5Fstart_swmr_write(), open_datasets(), add_records(), H5Fclose().
+ * 2) create_file(), H5Fstart_swmr_write(), create_close_datasets(), open_datasets(), add_records(), H5Fclose().
+ * 3) create_file(), H5Fclose(),
+ * open_file(), create_close_datasets(), H5Fstart_swmr_write(), open_datasets(), add_records(), H5Fclose().
+ * 4) create_file(), create_close_datasets(), H5Fclose(),
+ * open_file(), H5Fstart_swmr_write(), open_datasets(), add_records(), H5Fclose().
+ * 5) create_file(), H5Fclose(),
+ * open_file(), H5Fstart_swmr_write(), create_close_datasets(), open_datasets(), add_records(), H5Fclose().
+ */
+int main(int argc, const char *argv[])
+{
+ 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 */
+ 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 */
+ int comp_level = -1; /* Compression level (-1 is no compression) */
+ const char *index_type = "b1"; /* Chunk index type */
+ unsigned u; /* Local index variable */
+ int temp; /* Temporary variable */
+
+ /* 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]) {
+ /* Compress dataset chunks */
+ case 'c':
+ comp_level = atoi(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(strcmp(index_type, "ea")
+ && strcmp(index_type, "b2"))
+ usage();
+ u += 2;
+ break;
+
+ /* # of records to write between flushing file */
+ case 'f':
+ flush_count = atol(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 = atoi(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 */
+ nrecords = atol(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) {
+ fprintf(stderr, "Parameters:\n");
+ fprintf(stderr, "\tindex type = %s\n", index_type);
+ fprintf(stderr, "\tcompression level = %d\n", comp_level);
+ fprintf(stderr, "\t# of records between flushes = %ld\n", flush_count);
+ fprintf(stderr, "\t# of records to write = %ld\n", nrecords);
+ } /* end if */
+
+ /* Set the random seed */
+ if(0 == use_seed) {
+ struct timeval t;
+ gettimeofday(&t, NULL);
+ random_seed = (unsigned)((t.tv_sec * 1000) + t.tv_usec);
+ } /* end if */
+ srandom(random_seed);
+ /* ALWAYS emit the random seed for possible debugging */
+ fprintf(stderr, "Using writer random seed: %u\n", random_seed);
+
+ /* Create the test file */
+ if((fid = create_file(FILENAME, verbose, index_type, random_seed)) < 0) {
+ fprintf(stderr, "Error creating the file...\n");
+ exit(1);
+ }
+
+ /* Create and close the datasets in the file */
+ if(create_close_datasets(fid, comp_level, verbose) < 0) {
+ fprintf(stderr, "Error creating datasets...\n");
+ exit(1);
+ }
+
+#ifdef OUT
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0) {
+ fprintf(stderr, "Error closing file!\n");
+ exit(1);
+ } /* end if */
+
+ /* Open the file */
+ if((fid = open_file(FILENAME, verbose)) < 0) {
+ fprintf(stderr, "Error opening the file...\n");
+ exit(1);
+ }
+#endif
+
+ /* Enable SWMR writing mode */
+ if(H5Fstart_swmr_write(fid) < 0) {
+ fprintf(stderr, "Error starting SWMR writing mode...\n");
+ exit(1);
+ }
+
+ /* Emit informational message */
+ if(verbose)
+ fprintf(stderr, "Generating symbol names\n");
+
+ /* Generate dataset names */
+ if(generate_symbols() < 0)
+ return -1;
+
+ /* Emit informational message */
+ if(verbose)
+ fprintf(stderr, "Opening datasets: %s\n", FILENAME);
+
+ /* Open the file's datasets */
+ if(open_datasets(fid, verbose) < 0) {
+ fprintf(stderr, "Error opening datasets...\n");
+ exit(1);
+ } /* end if */
+
+ /* Send a message to indicate "H5Fopen" is complete--releasing the file lock */
+ h5_send_message(WRITER_MESSAGE);
+
+ /* Emit informational message */
+ if(verbose)
+ fprintf(stderr, "Adding records\n");
+
+ /* Append records to datasets */
+ if(add_records(fid, verbose, (unsigned long)nrecords, (unsigned long)flush_count) < 0) {
+ fprintf(stderr, "Error appending records to datasets!\n");
+ exit(1);
+ } /* end if */
+
+ /* Emit informational message */
+ if(verbose)
+ fprintf(stderr, "Releasing symbols\n");
+
+ /* Clean up the symbols */
+ if(shutdown_symbols() < 0) {
+ fprintf(stderr, "Error releasing symbols!\n");
+ exit(1);
+ } /* end if */
+
+ /* Emit informational message */
+ if(verbose)
+ fprintf(stderr, "Closing the file\n");
+
+ /* Close objects opened */
+ if(H5Fclose(fid) < 0) {
+ fprintf(stderr, "Error closing file!\n");
+ exit(1);
+ } /* end if */
+
+ return 0;
+} /* main() */
diff --git a/test/swmr_writer.c b/test/swmr_writer.c
index 29438d3..3fe4780 100644
--- a/test/swmr_writer.c
+++ b/test/swmr_writer.c
@@ -388,6 +388,9 @@ int main(int argc, const char *argv[])
exit(1);
} /* end if */
+ /* Send a message to indicate "H5Fopen" is complete--releasing the file lock */
+ h5_send_message(WRITER_MESSAGE);
+
/* Emit informational message */
if(verbose)
fprintf(stderr, "Adding records\n");
diff --git a/test/tarrold.h5 b/test/tarrold.h5
index 7747ce4..048838c 100644
--- a/test/tarrold.h5
+++ b/test/tarrold.h5
Binary files differ
diff --git a/test/test_filters_be.h5 b/test/test_filters_be.h5
index c4c127b..aadb372 100644
--- a/test/test_filters_be.h5
+++ b/test/test_filters_be.h5
Binary files differ
diff --git a/test/test_filters_le.h5 b/test/test_filters_le.h5
index ff8b846..c29fa0a 100644
--- a/test/test_filters_le.h5
+++ b/test/test_filters_le.h5
Binary files differ
diff --git a/test/test_swmr.c b/test/test_swmr.c
new file mode 100644
index 0000000..bd46bc2
--- /dev/null
+++ b/test/test_swmr.c
@@ -0,0 +1,2104 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/***********************************************************
+*
+* Test program: test_swmr
+*
+* To test SWMR related public routines:
+* H5Fstart_swmr_write()
+* H5Pget/set_object_flush_cb()
+* H5Pget/set_append_flush()
+*
+*************************************************************/
+
+#include "hdf5.h"
+#include "h5test.h"
+#include "H5srcdir.h"
+
+/*
+ * This file needs to access private information from the H5F package.
+ * This file also needs to access the file testing code.
+ */
+#define H5F_PACKAGE
+#define H5F_TESTING
+#include "H5Fpkg.h" /* File access */
+
+const char *FILENAME[] = {
+ "test_swmr", /* 0 */
+ NULL
+};
+
+#define NAME_BUF_SIZE 1024 /* Length of file name */
+
+/* Name of message file that is used by test_start_swmr_write_concur() */
+#define DONE_MESSAGE "DONE_MESSAGE" /* The message file to create */
+
+/* Tests for H5Fstart_swmr_write() */
+static int test_start_swmr_write(hid_t in_fapl);
+static int test_err_start_swmr_write(hid_t in_fapl);
+static int test_start_swmr_write_concur(hid_t in_fapl);
+
+/* Tests for H5Pget/set_object_flush_cb() */
+static herr_t flush_cb(hid_t obj_id, void *_udata);
+static int test_object_flush_cb(hid_t in_fapl);
+
+/* Tests for H5Pget/set_append_flush() */
+static herr_t append_cb(hid_t dset_id, hsize_t *cur_dims, void *_udata);
+static herr_t append_cb2(hid_t dset_id, hsize_t *cur_dims, void *_udata);
+static int test_append_flush_generic(void);
+static int test_append_flush_dataset_chunked(hid_t in_fapl);
+static int test_append_flush_dataset_fixed(hid_t in_fapl);
+static int test_append_flush_dataset_multiple(hid_t in_fapl);
+
+/*
+ * Tests for H5Fstart_swmr_write()
+ */
+
+/*
+ * Verify SWMR writing is enabled via H5Fstart_swmr_write().
+ */
+static int
+test_start_swmr_write(hid_t in_fapl)
+{
+ hid_t fid = -1; /* File ID */
+ hid_t fapl = -1; /* A copy of file access property */
+ hid_t file_fapl = -1; /* File access property for the file */
+ hid_t did = -1; /* Dataset ID */
+ hid_t sid = -1; /* Dataspace ID */
+ hsize_t dims[2] = {5, 10}; /* Dimension sizes */
+ int buf[50]; /* Data buffer */
+ int i; /* Local index variable */
+ unsigned attempts; /* The retrieved # of read attempts */
+ char filename[NAME_BUF_SIZE]; /* File name */
+
+ TESTING("H5Fstart_swmr_write()");
+
+ /* Get a copy of the parameter fapl */
+ if((fapl = H5Pcopy(in_fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set to use the latest library format */
+ if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set the filename to use for this test (dependent on fapl) */
+ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename));
+
+ /* Create the file to work on */
+ if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Get the file's access_property list */
+ if((file_fapl = H5Fget_access_plist(fid)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Retrieve the # of read attempts from the file's fapl */
+ if(H5Pget_metadata_read_attempts(file_fapl, &attempts) < 0)
+ FAIL_STACK_ERROR
+
+ /* Close the property list */
+ if(H5Pclose(file_fapl) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should be 1 */
+ if(attempts != H5F_METADATA_READ_ATTEMPTS)
+ TEST_ERROR;
+
+ /* Create a dataset */
+ if((sid = H5Screate_simple(2, dims, NULL)) < 0)
+ FAIL_STACK_ERROR;
+ if((did = H5Dcreate2(fid, "dataset", H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Close the dataset */
+ if(H5Dclose(did) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Enable SWMR writing */
+ if(H5Fstart_swmr_write(fid) < 0)
+ TEST_ERROR;
+
+ /* Open the dataset */
+ if((did = H5Dopen2(fid, "dataset", H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Initialize data buffer */
+ for(i = 0; i < 50; i++)
+ buf[i] = i;
+
+ /* Write to the dataset */
+ if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Close the dataset */
+ if(H5Dclose(did) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Close the dataspace */
+ if(H5Sclose(sid) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Get the file's access_property list */
+ if((file_fapl = H5Fget_access_plist(fid)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Retrieve the # of read attempts from file's fapl */
+ if(H5Pget_metadata_read_attempts(file_fapl, &attempts) < 0)
+ FAIL_STACK_ERROR
+
+ /* Should be 100 */
+ if(attempts != H5F_SWMR_METADATA_READ_ATTEMPTS)
+ TEST_ERROR;
+
+ /* Closing */
+ if(H5Pclose(file_fapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(fapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ PASSED();
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Fclose(fid);
+ H5Pclose(fapl);
+ H5Pclose(file_fapl);
+ H5Dclose(did);
+ H5Sclose(sid);
+ } H5E_END_TRY;
+
+ return -1;
+} /* test_start_swmr_write() */
+
+/*
+ * Verify failures in enabling SWMR writing mode via H5Fstart_swmr_write():
+ * When creating a file:
+ * (1) the file is created with SWMR write access
+ * (2) the file is not created with the latest format
+ * (3) there are opened objects in the file
+ * When opening a file with the latest format:
+ * (1) the file is already opened with SWMR write access
+ * (2) the file is opened with read access only
+ * (3) the file is opened with SWMR read access only
+ * (4) there are opened objects in the file
+ * When opening a file without the latest format:
+ * (1) the file is not opened with the latest format
+ * (2) the file is opened with read access only
+ * (3) the file is opened with SWMR read access only
+ * When there are multiple opens for the file:
+ * (1) create a file, enable SWMR writing mode twice (fail second time)
+ * (2) create a file and enable SWMR writing mode
+ * reopen the same file and enable SWMR writing mode (fail)
+ * (3) create a file, open the same file
+ * enable SWMR writing for the file created
+ * enable SWMR writing for the file opened (fail)
+ */
+static int
+test_err_start_swmr_write(hid_t in_fapl)
+{
+ hid_t fid = -1; /* File ID */
+ hid_t fid2 = -1; /* File ID */
+ hid_t fapl = -1; /* A copy of file access property */
+ hid_t gid = -1; /* Group ID */
+ hid_t did = -1; /* Dataset ID */
+ hid_t sid = -1; /* Dataspace ID */
+ hid_t tid = -1; /* Datatype ID */
+ hsize_t dims[2] = {5, 10}; /* Dimension size */
+ herr_t ret; /* Return value */
+ char filename[NAME_BUF_SIZE]; /* File name */
+
+ /* Create a copy of the input parameter in_fapl */
+ if((fapl = H5Pcopy(in_fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set to use the latest library format */
+ if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set the filename to use for this test (dependent on fapl) */
+ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename));
+
+ TESTING("H5Fstart_swmr_write() failure conditions");
+
+ /*
+ * When creating a file:
+ */
+
+ /* Case 1 */
+
+ /* Cannot enable SWMR writing when the file is already in SWMR writing mode */
+ fid = H5Fcreate(filename, H5F_ACC_TRUNC|H5F_ACC_SWMR_WRITE, H5P_DEFAULT, fapl);
+ H5E_BEGIN_TRY {
+ ret = H5Fstart_swmr_write(fid);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Case 2 */
+
+ /* Cannot enable SWMR writing mode without latest format */
+ fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, in_fapl);
+ H5E_BEGIN_TRY {
+ ret = H5Fstart_swmr_write(fid);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should fail to create the file with SWMR write access when not using latest format */
+ H5E_BEGIN_TRY {
+ ret = H5Fcreate(filename, H5F_ACC_TRUNC|H5F_ACC_SWMR_WRITE, H5P_DEFAULT, in_fapl);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+
+ /* Case 3 */
+
+ /* Create a file with the latest format */
+ if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Create a group */
+ if((gid = H5Gcreate2(fid, "group", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Create a dataset in the group */
+ if((sid = H5Screate_simple(2, dims, NULL)) < 0)
+ FAIL_STACK_ERROR;
+ if((did = H5Dcreate2(gid, "dset", H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Should fail to enable SWMR writing mode: there are opened objects */
+ H5E_BEGIN_TRY {
+ ret = H5Fstart_swmr_write(fid);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR;
+
+ /* Close the dataset */
+ if(H5Dclose(did) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Fail to enable SWMR writing mode */
+ H5E_BEGIN_TRY {
+ ret = H5Fstart_swmr_write(fid);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR;
+
+ /* Close the group */
+ if(H5Gclose(gid) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should succeed in enabling SWMR writing */
+ if(H5Fstart_swmr_write(fid) < 0)
+ TEST_ERROR;
+
+ /* Closing */
+ if(H5Sclose(sid) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /*
+ * When opening a file with latest format:
+ */
+
+ /* Create and close a file with latest format */
+ if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Case 1 */
+
+ /* Open the file with SWMR write access */
+ if((fid = H5Fopen(filename, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Cannot enable SWMR writing when already in SWMR writing mode */
+ H5E_BEGIN_TRY {
+ ret = H5Fstart_swmr_write(fid);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Case 2 */
+
+ /* Open the file with read only access */
+ if((fid = H5Fopen(filename, H5F_ACC_RDONLY, fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should fail to enable SWMR writing when the file is opened with read only access */
+ H5E_BEGIN_TRY {
+ ret = H5Fstart_swmr_write(fid);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Case 3 */
+
+ /* Open the file file with SWMR read access */
+ if((fid = H5Fopen(filename, H5F_ACC_SWMR_READ, fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should fail to enable SWMR writing when the file is opened with SWMR read access only */
+ H5E_BEGIN_TRY {
+ ret = H5Fstart_swmr_write(fid);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Case 4 */
+
+ /* Open the file with latest format */
+ if((fid = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Create and commit a named datatype */
+ if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Tcommit2(fid, "TID", tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should fail to enable SWMR writing mode */
+ H5E_BEGIN_TRY {
+ ret = H5Fstart_swmr_write(fid);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR;
+
+ /* Close the datatype */
+ if(H5Tclose(tid) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should succeed in enabling SWMR writing */
+ if(H5Fstart_swmr_write(fid) < 0)
+ TEST_ERROR;
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /*
+ * Opening a file without latest format:
+ */
+
+ /* Case 1 */
+
+ /* Open the file without latest format */
+ if((fid = H5Fopen(filename, H5F_ACC_RDWR, in_fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should fail to enable SWMR writing mode */
+ H5E_BEGIN_TRY {
+ ret = H5Fstart_swmr_write(fid);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should fail to open the file with SWMR write access when not using latest format */
+ H5E_BEGIN_TRY {
+ ret = H5Fopen(filename, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, in_fapl);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Case 2 */
+
+ /* Open the file with read only */
+ if((fid = H5Fopen(filename, H5F_ACC_RDONLY, in_fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should fail to enable SWMR writing when the file is opened with read only */
+ H5E_BEGIN_TRY {
+ ret = H5Fstart_swmr_write(fid);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Case 3 */
+
+ /* Open the file with SWMR read only */
+ if((fid = H5Fopen(filename, H5F_ACC_SWMR_READ, in_fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should fail to enable SWMR writing mode when the file is opened with SWMR read only */
+ H5E_BEGIN_TRY {
+ ret = H5Fstart_swmr_write(fid);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /*
+ * Failure cases for multiple opens
+ */
+
+ /* Case 1 */
+
+ /* Create a file with latest format */
+ if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should succeed in enabling SWMR writing mode */
+ if(H5Fstart_swmr_write(fid) < 0)
+ TEST_ERROR
+
+ /* Should fail for a second call to start SWMR writing mode */
+ H5E_BEGIN_TRY {
+ ret = H5Fstart_swmr_write(fid);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+
+ /* Case 2 */
+
+ /* Create a file */
+ if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should succeed in starting SWMR writing mode */
+ if(H5Fstart_swmr_write(fid) < 0)
+ TEST_ERROR
+
+ /* Re-open the same file */
+ if((fid2 = H5Freopen(fid)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should fail to enable SWMR writing mode for fid2 */
+ H5E_BEGIN_TRY {
+ ret = H5Fstart_swmr_write(fid2);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Close the files */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Fclose(fid2) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Case 3 */
+
+ /* Create a file */
+ if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Open the same file */
+ if((fid2 = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should succeed in enabling SWMR writing mode for fid */
+ if(H5Fstart_swmr_write(fid) < 0)
+ TEST_ERROR
+
+ /* Should fail to enable SWMR writing mode for fid2 */
+ H5E_BEGIN_TRY {
+ ret = H5Fstart_swmr_write(fid2);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Close the files */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Fclose(fid2) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Close the file access property list */
+ if(H5Pclose(fapl) < 0)
+ FAIL_STACK_ERROR;
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Fclose(fid);
+ H5Pclose(fapl);
+ } H5E_END_TRY;
+
+ return -1;
+} /* test_err_start_swmr_write() */
+
+
+/*
+ * test_start_swmr_write_concur():
+ * Verify concurrent access for H5Fstart_swmr_write()--
+ * (1) Open a file with write access
+ * Concurrent open of the file with read & SWMR read (fail)
+ * (2) Open a file with write access; enable SWMR writing mode
+ * Concurrent open of the file with read & SWMR read (succeed)
+ * (3) Open a file with write access; enable SWMR writing mode
+ * Concurrent open of the file with read only (fail)
+ * (4) Open a file with write access; enable SWMR writing mode
+ * Concurrent open of the file with write access (fail)
+ * (5) Open a file with write access; enable SWMR writing mode
+ * Concurrent open of the file with write and SWMR write access (fail)
+ */
+static int
+test_start_swmr_write_concur(hid_t in_fapl)
+{
+ hid_t fid; /* File ID */
+ hid_t fapl; /* File access property list */
+ herr_t ret; /* Generic return value */
+ pid_t childpid=0; /* Child process ID */
+ pid_t tmppid; /* Child process ID returned by waitpid */
+ int child_status; /* Status passed to waitpid */
+ int child_wait_option=0; /* Options passed to waitpid */
+ int child_ret_value; /* Exit status of the child */
+ char filename[NAME_BUF_SIZE]; /* File name */
+
+ /* Output message about test being performed */
+ TESTING("Testing H5Fstart_swmr_write()--concurrent access");
+
+#if !(defined(H5_HAVE_FORK) && defined(H5_HAVE_WAITPID))
+
+ SKIPPED();
+ HDputs(" Test skipped due to fork or waitpid not defined.");
+
+#else /* defined(H5_HAVE_FORK && defined(H5_HAVE_WAITPID) */
+
+ if((fapl = H5Pcopy(in_fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set to use the latest library format */
+ if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set the filename to use for this test (dependent on fapl) */
+ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename));
+
+ /* Create the test file */
+ if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR
+
+ /* Remove the message file to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /*
+ * Case (1):
+ * Verify concurrent file open with H5F_ACC_RDONLY|H5F_ACC_SWMR_READ
+ * will fail without H5Fstart_swmr_write()
+ */
+
+ /* Fork child process */
+ if((childpid = HDfork()) < 0)
+ FAIL_STACK_ERROR
+
+ if(childpid == 0) { /* Child process */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Should fail */
+ H5E_BEGIN_TRY {
+ /* Open the test file */
+ ret = H5Fopen(filename, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ exit(1);
+ exit(0);
+ }
+
+ /* Open the test file */
+ if((fid = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ if((tmppid = HDwaitpid(childpid, &child_status, child_wait_option)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Check if child terminated normally */
+ if((ret = WIFEXITED(child_status)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Check exit status of child process */
+ if((child_ret_value = WEXITSTATUS(child_status)) != 0)
+ TEST_ERROR
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR
+
+
+ /*
+ * Case (2):
+ * Verify concurrent file open with H5F_ACC_RDONLY|H5F_ACC_SWMR_READ
+ * will succeed with H5Fstart_swmr_write()
+ */
+
+ /* Remove the message file to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ if((childpid = HDfork()) < 0)
+ FAIL_STACK_ERROR
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Should succeed in opening the test file */
+ if((child_fid = H5Fopen(filename, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl)) < 0) {
+ TEST_ERROR
+ exit(1);
+ }
+ if(H5Fclose(child_fid) < 0) {
+ FAIL_STACK_ERROR
+ exit(1);
+ }
+ exit(0);
+ }
+
+ /* Open the test file */
+ if((fid = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Enable SWMR writing mode */
+ if(H5Fstart_swmr_write(fid) < 0)
+ TEST_ERROR
+
+ /* Send the message that H5Fstart_swmr_write() completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ if((tmppid = HDwaitpid(childpid, &child_status, child_wait_option)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Check if child terminated normally */
+ if((ret = WIFEXITED(child_status)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Check exit status of child process */
+ if((child_ret_value = WEXITSTATUS(child_status)) != 0)
+ TEST_ERROR
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR
+
+ /*
+ * Case (3):
+ * Verify concurrent file open with H5F_ACC_RDONLY
+ * will fail with H5Fstart_swmr_write()
+ */
+
+ /* Remove the message file to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ if((childpid = HDfork()) < 0)
+ FAIL_STACK_ERROR
+
+
+ if(childpid == 0) { /* Child process */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Should fail in opening the test file */
+ H5E_BEGIN_TRY {
+ ret = H5Fopen(filename, H5F_ACC_RDONLY, fapl);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ exit(1);
+ exit(0);
+ }
+
+ /* Open the test file */
+ if((fid = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Enable SWMR writing mode */
+ if(H5Fstart_swmr_write(fid) < 0)
+ TEST_ERROR
+
+ /* Send the message that H5Fstart_swmr_write() completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ if((tmppid = HDwaitpid(childpid, &child_status, child_wait_option)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Check if child terminated normally */
+ if((ret = WIFEXITED(child_status)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Check exit status of child process */
+ if((child_ret_value = WEXITSTATUS(child_status)) != 0)
+ TEST_ERROR;
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR
+
+ /*
+ * Case (4):
+ * Verify concurrent file open with H5F_ACC_RDWR
+ * will fail with H5Fstart_swmr_write()
+ */
+
+ /* Remove the message file to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ if((childpid = HDfork()) < 0)
+ FAIL_STACK_ERROR
+
+
+ if(childpid == 0) { /* Child process */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Should fail in opening the test file */
+ H5E_BEGIN_TRY {
+ ret = H5Fopen(filename, H5F_ACC_RDWR, fapl);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ exit(1);
+ exit(0);
+ }
+
+ /* Open the test file */
+ if((fid = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Enable SWMR writing mode */
+ if(H5Fstart_swmr_write(fid) < 0)
+ TEST_ERROR
+
+ /* Send the message that H5Fstart_swmr_write() completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ if((tmppid = HDwaitpid(childpid, &child_status, child_wait_option)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Check if child terminated normally */
+ if((ret = WIFEXITED(child_status)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Check exit status of child process */
+ if((child_ret_value = WEXITSTATUS(child_status)) != 0)
+ TEST_ERROR;
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR
+
+ /*
+ * Case (5):
+ * Verify concurrent file open with H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE
+ * will fail with H5Fstart_swmr_write()
+ */
+
+ /* Remove the message file to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ if((childpid = HDfork()) < 0)
+ FAIL_STACK_ERROR
+
+
+ if(childpid == 0) { /* Child process */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Should fail in opening the test file */
+ H5E_BEGIN_TRY {
+ ret = H5Fopen(filename, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ exit(1);
+ exit(0);
+ }
+
+ /* Open the test file */
+ if((fid = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Enable SWMR writing mode */
+ if(H5Fstart_swmr_write(fid) < 0)
+ TEST_ERROR
+
+ /* Send the message that H5Fstart_swmr_write() completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ if((tmppid = HDwaitpid(childpid, &child_status, child_wait_option)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Check if child terminated normally */
+ if((ret = WIFEXITED(child_status)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Check exit status of child process */
+ if((child_ret_value = WEXITSTATUS(child_status)) != 0)
+ TEST_ERROR;
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR
+
+ /* Close the property list */
+ if(H5Pclose(fapl) < 0)
+ FAIL_STACK_ERROR
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(fapl);
+ H5Fclose(fid);
+ } H5E_END_TRY;
+
+ return -1;
+#endif
+
+} /* end test_start_swmr_write_concur() */
+
+
+/*
+ * Tests for H5Pset/get_object_flush_cb()
+ */
+
+/* The callback function for object flush property */
+static herr_t
+flush_cb(hid_t obj_id, void *_udata)
+{
+ unsigned *flush_ct = (unsigned*)_udata;
+ ++(*flush_ct);
+ return 0;
+}
+
+/*
+ * test_object_flush_cb()
+ * To verify the public routines H5Pget/set_object_flush_cb()
+ * work as specified:
+ * 1) To verify the failure condition in setting object flush property
+ * 2) To verify the object flush property values retrieved from a default
+ * file access property list.
+ * 3) To verify the object flush property values retrieved from a non-default
+ * file access property list.
+ * 4) To verify the object flush property values retrieved from a default
+ * file access property list of a file
+ * 5) To verify the object flush property values retrieved from a non-default
+ * file access property list of a file
+ * To verify the object flush callback is invoked when doing H5Oflush(),
+ * H5Dflush(), H5Gflush() and H5Tflush().
+ */
+static int
+test_object_flush_cb(hid_t in_fapl)
+{
+ hid_t fapl = -1; /* A copy of file access property list */
+ hid_t ffapl = -1; /* A file's file access property list */
+ hid_t fid = -1; /* File ID */
+ hid_t gid = -1; /* Group ID */
+ hid_t did1 = -1, did2 = -1; /* Dataset IDs */
+ hid_t sid = -1; /* Dataspace ID */
+ hsize_t dims[2] = {5, 10}; /* Dataset dimension sizes */
+ int buf[50]; /* Data buffer */
+ H5F_flush_cb_t ret_cb; /* The callback function set in object flush property */
+ void *ret_ct; /* The user data set in object flush property */
+ unsigned flush_ct = 0; /* The user data for object flush property */
+ char filename[NAME_BUF_SIZE]; /* File name */
+ int i; /* Local index variable */
+ herr_t ret; /* Generic return value */
+
+ TESTING("H5Pget/set_obj_flush_cb()");
+
+ /*
+ * Case (1)
+ * To verify the failure condition in setting object flush property
+ */
+ /* Should fail if the callback function is not defined but user data is defined */
+ H5E_BEGIN_TRY {
+ ret = H5Pset_object_flush_cb(fapl, NULL, &flush_ct);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /*
+ * Case (2)
+ * To verify the object flush property values retrieved from a
+ * default file access property list.
+ */
+
+ /* Create a copy of file access property list */
+ if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Retrieve object flush property values for the default file access property list */
+ if(H5Pget_object_flush_cb(fapl, &ret_cb, &ret_ct) < 0)
+ TEST_ERROR
+ /* Should be null */
+ if(ret_cb != NULL || ret_ct != NULL)
+ TEST_ERROR
+
+ /*
+ * Case (3)
+ * To verify the object flush property values retrieved from a
+ * non-default file access property list.
+ */
+ /* Set the object flush property */
+ if(H5Pset_object_flush_cb(fapl, flush_cb, &flush_ct) < 0)
+ TEST_ERROR
+
+ /* Increment the counter */
+ ++flush_ct;
+
+ /* Retrieve object flush property values for the non-default file access property list */
+ if(H5Pget_object_flush_cb(fapl, &ret_cb, &ret_ct) < 0)
+ TEST_ERROR
+
+ /* Verify expected values */
+ if(ret_cb != flush_cb || *(unsigned *)ret_ct != 1)
+ TEST_ERROR
+
+ /* Close the property list */
+ if(H5Pclose(fapl) < 0)
+ FAIL_STACK_ERROR;
+
+
+ /*
+ * Case (4)
+ * To verify the object flush property values retrieved from a
+ * default file access property list of a file
+ */
+
+ /* Reset values */
+ flush_ct = 0;
+ ret_cb = NULL;
+ ret_ct = NULL;
+
+ /* Make a copy of the input parameter in_fapl */
+ if((fapl = H5Pcopy(in_fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set to use the latest library format */
+ if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set the filename to use for this test (dependent on fapl) */
+ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename));
+
+ /* Create the test file: without setting object flush property in fapl */
+ if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Get the file's file access property list */
+ if((ffapl = H5Fget_access_plist(fid)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Retrieve the object flush property values */
+ if(H5Pget_object_flush_cb(ffapl, &ret_cb, &ret_ct) < 0)
+ TEST_ERROR
+
+ /* Verify expected values */
+ if(ret_cb != NULL || ret_ct != NULL)
+ TEST_ERROR
+
+ /* Closing */
+ if(H5Pclose(ffapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /*
+ * Cases (5)
+ * To verify the object flush property values retrieved from a non-default
+ * file access property list of a file.
+ * To verify the object flush callback is invoked when doing H5Oflush(),
+ * H5Dflush(), H5Gflush() and H5Tflush().
+ */
+ /* Reset values */
+ flush_ct = 0;
+ ret_cb = NULL;
+ ret_ct = NULL;
+
+ /* Set the object flush property */
+ if(H5Pset_object_flush_cb(fapl, flush_cb, &flush_ct) < 0)
+ FAIL_STACK_ERROR
+
+ /* Open the test file: with object flush property setting in fapl */
+ if((fid = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Create a dataset */
+ if((sid = H5Screate_simple(2, dims, dims)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Create a dataset */
+ if((did1 = H5Dcreate2(fid, "dataset1", H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Initialize data buffer */
+ for(i = 0; i < 50; i++)
+ buf[i] = i + 1;
+
+ /* Write to the dataset */
+ if(H5Dwrite(did1, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Flush the dataset object */
+ if(H5Oflush(did1) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Get the file's file access property list */
+ if((ffapl = H5Fget_access_plist(fid)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Retrieve the object flush property values */
+ if(H5Pget_object_flush_cb(ffapl, &ret_cb, &ret_ct) < 0)
+ TEST_ERROR
+
+ /* Verify expected values */
+ if(ret_cb != flush_cb || *(unsigned *)ret_ct != 1)
+ TEST_ERROR
+
+ /* Create a group */
+ if((gid = H5Gcreate2(fid, "group", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Flush the group */
+ if(H5Gflush(gid) < 0)
+ TEST_ERROR
+
+ /* Retrieve the object flush property values */
+ if(H5Pget_object_flush_cb(ffapl, &ret_cb, &ret_ct) < 0)
+ TEST_ERROR
+
+ /* Verify expected values */
+ if(ret_cb != flush_cb || *(unsigned *)ret_ct != 2)
+ TEST_ERROR
+
+ /* Create a dataset */
+ if((did2 = H5Dcreate2(gid, "dataset2", H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Flush the dataset */
+ if(H5Dflush(did2) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Retrieve the object flush property values */
+ if(H5Pget_object_flush_cb(ffapl, &ret_cb, &ret_ct) < 0)
+ TEST_ERROR
+
+ /* Verify expected values */
+ if(ret_cb != flush_cb || *(unsigned *)ret_ct != 3)
+ TEST_ERROR
+
+ /* Closing */
+ if(H5Sclose(sid) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Dclose(did1) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Dclose(did2) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Gclose(gid) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(fapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(ffapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ PASSED();
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(fapl);
+ H5Pclose(ffapl);
+ H5Sclose(sid);
+ H5Dclose(did1);
+ H5Dclose(did2);
+ H5Gclose(gid);
+ H5Fclose(fid);
+ } H5E_END_TRY;
+
+ return -1;
+} /* test_object_flush_cb() */
+
+/*
+ * Tests for H5Pset/get_append_flush()
+ */
+
+
+/* The callback function for append flush property */
+static herr_t
+append_cb(hid_t dset_id, hsize_t *cur_dims, void *_udata)
+{
+ unsigned *count = (unsigned *)_udata;
+ ++(*count++);
+ return 0;
+} /* append_cb() */
+
+
+/* The callback function for append flush property */
+static herr_t
+append_cb2(hid_t dset_id, hsize_t *cur_dims, void *_udata)
+{
+ unsigned *count = (unsigned *)_udata;
+ ++(*count++);
+ return 0;
+} /* append_cb2() */
+
+
+
+/*
+ * test_append_flush_generic()
+ * To verify H5Pget/set_append_flush() work as specified for
+ * a generic dataset access property list:
+ * 1) To verify the append flush property values retrieved from a default
+ * access property list.
+ * -- zero boundary, null callback function, null user data
+ * 2) To verify the failure conditions in setting append flush property:
+ * -- an invalid dataset rank: <= 0, > H5S_MAX_RANK
+ * -- undefined callback but defined user data
+ * -- no boundary specified
+ * -- invalid boundary size: H5S_UNLIMITED, negative value
+ * 3) To verify the append flush property values retrieved from a non-default
+ * access property list.
+ * -- the set callback function, the set user data
+ * -- the # of boundary sizes retrieved does not exceed MIN(input ndims, the ndims set)
+ */
+static int
+test_append_flush_generic(void)
+{
+ hid_t dapl = -1; /* A copy of dataset access property */
+ hsize_t boundary[3]; /* The boundary for append flush property */
+ unsigned count = 0; /* The user data for append flush property */
+ hsize_t ret_boundary[3]; /* The boundary set in append flush property */
+ H5D_append_cb_t ret_cb; /* The callback function set in append flush property */
+ unsigned *ret_count; /* The user data set in append flush property */
+ herr_t ret; /* The return value */
+
+ TESTING("H5Fget/set_append_flush() for a generic dataset access property list");
+
+
+ /*
+ * Case (1)
+ * To verify the retrieved append flush property values:
+ * -- zero boundary, null callback function, null user data
+ */
+
+ /* Create a copy of dataset access property list */
+ if((dapl = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Retrieve the append flush property values */
+ if(H5Pget_append_flush(dapl, 2, ret_boundary, &ret_cb, (void **)&ret_count) < 0)
+ FAIL_STACK_ERROR
+
+ /* Verify expected values */
+ if(ret_boundary[0] != 0 || ret_boundary[1] != 0)
+ TEST_ERROR;
+ if(ret_cb != NULL || ret_count != NULL)
+ TEST_ERROR
+
+ /* Close the property list */
+ if(H5Pclose(dapl) < 0)
+ FAIL_STACK_ERROR;
+
+ /*
+ * Case (2)
+ * To verify the failure conditions in setting append flush property:
+ * -- an invalid dataset rank: <= 0, > H5S_MAX_RANK
+ * -- no boundary specified
+ * -- undefined callback but defined user data
+ * -- invalid boundary size: H5S_UNLIMITED, negative value
+ */
+
+ /* Create a copy of dataset access property list */
+ if((dapl = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Invalid dataset rank: zero value */
+ H5E_BEGIN_TRY {
+ ret = H5Pset_append_flush(dapl, 0, NULL, NULL, &count);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Invalid dataset rank: negative value */
+ H5E_BEGIN_TRY {
+ ret = H5Pset_append_flush(dapl, -1, NULL, NULL, &count);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Invalid dataset rank: > H5S_MAX_RANK */
+ H5E_BEGIN_TRY {
+ ret = H5Pset_append_flush(dapl, H5S_MAX_RANK+1, NULL, NULL, &count);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* No boundary specified */
+ H5E_BEGIN_TRY {
+ ret = H5Pset_append_flush(dapl, 2, NULL, NULL, &count);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Set up a valid boundary */
+ boundary[0] = 1;
+ boundary[1] = 1;
+
+ /* Undefined callback function but defined user data */
+ H5E_BEGIN_TRY {
+ ret = H5Pset_append_flush(dapl, 2, boundary, NULL, &count);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Invalid boundary size: negative value */
+ boundary[0] = -1;
+ boundary[1] = 1;
+ H5E_BEGIN_TRY {
+ ret = H5Pset_append_flush(dapl, 2, boundary, append_cb, &count);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Invalid boundary size: H5S_UNLIMITED */
+ boundary[0] = 1;
+ boundary[1] = H5S_UNLIMITED;
+ H5E_BEGIN_TRY {
+ ret = H5Pset_append_flush(dapl, 2, boundary, append_cb, &count);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /*
+ * Case (3)
+ * To verify the append flush property values retrieved from a non-default
+ * access property list:
+ * -- the set callback function, the set user data
+ * -- the # of boundary sizes retrieved does not exceed MIN(input ndims, the ndims set)
+ */
+ boundary[0] = boundary[1] = 1;
+ boundary[2] = 0;
+ count = 1;
+ if(H5Pset_append_flush(dapl, 2, boundary, append_cb, &count) < 0)
+ FAIL_STACK_ERROR;
+ ++count;
+
+ /* Verify expected values: with boundary rank > set boundary rank */
+ if(H5Pget_append_flush(dapl, 3, ret_boundary, &ret_cb, (void **)&ret_count) < 0)
+ TEST_ERROR
+ if(ret_boundary[0] != 1 || ret_boundary[1] != 1 || boundary[2] != 0)
+ TEST_ERROR;
+ if(ret_cb == NULL || ret_count == NULL || *ret_count != 2)
+ TEST_ERROR
+
+ /* Verify expected values: with boundary rank < set boundary rank */
+ HDmemset(ret_boundary, 0, sizeof(ret_boundary));
+ if(H5Pget_append_flush(dapl, 1, ret_boundary, NULL, NULL) < 0)
+ TEST_ERROR
+ if(ret_boundary[0] != 1 || ret_boundary[1] != 0 || boundary[2] != 0)
+ TEST_ERROR;
+
+ /* Closing */
+ if(H5Pclose(dapl) < 0)
+ FAIL_STACK_ERROR;
+
+ PASSED();
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(dapl);
+ } H5E_END_TRY;
+
+ return -1;
+} /* test_append_flush_generic() */
+
+/*
+ * test_append_flush_dataset_chunked()
+ * To verify H5Pget/set_append_flush() work as specified for
+ * a chunked dataset's access property list:
+ * 1) To verify the append flush property values retrieved from a default access
+ * property list:
+ * -- zero boundary, null callback function, null user data
+ * 2) To verify failure in creating dataset when:
+ * -- the rank set in append flush property is not the same as the dataset's rank
+ * -- boundary (non-zero) is set for a non-extendible dimension
+ * 3) To verify the append flush property values retrieved from a non-default
+ * access property list:
+ * -- the set callback function, the set user data
+ * -- the # of boundary sizes retrieved does not exceed MIN(input ndims, the ndims set)
+ */
+static int
+test_append_flush_dataset_chunked(hid_t in_fapl)
+{
+ hid_t fid = -1; /* file ID */
+ hid_t fapl = -1; /* A copy of file access property */
+ hid_t did1 = -1, did2 = -1; /* The datset ID */
+ hid_t sid = -1; /* The dataspace ID */
+ hid_t dcpl = -1; /* A copy of dataset creation property */
+ hid_t dapl = -1; /* A copy of dataset access property */
+ hid_t ddapl = -1; /* The dataset access property of the opened dataset */
+
+ hsize_t boundary[3]; /* Boundary size */
+ unsigned count = 0; /* User data */
+
+ hsize_t ret_boundary[3]; /* Boundary size set in the append flush property */
+ H5D_append_cb_t ret_cb; /* The callback function set in the append flush property */
+ unsigned *ret_count; /* The user data set in the append flush property */
+
+ char filename[NAME_BUF_SIZE]; /* file name */
+
+ hsize_t dims[2] = {100, 0}; /* The dataset dimension sizes */
+ hsize_t maxdims[2] = {100, H5S_UNLIMITED}; /* The dataset maximum dimension sizes */
+ hsize_t chunk_dims[2] = {5,2}; /* The chunk dimesion sizes */
+
+ TESTING("H5Fget/set_append_flush() for a chunked dataset's access property list");
+
+ /*
+ * Case (1)--
+ * For a chunked dataset's access property list:
+ * --to verify the append flush property values retrieved from a default access
+ * a default access property list is:
+ * zero rank, zero boundary, null callback function, null user data
+ */
+
+ /* Get a copy of the input parameter in_fapl */
+ if((fapl = H5Pcopy(in_fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set to use the latest library format */
+ if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Set the filename to use for this test (dependent on fapl) */
+ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename));
+
+ /* Create the test file to work on */
+ if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Create a chunked dataset with 1 extendible dimension */
+ if((sid = H5Screate_simple(2, dims, maxdims)) < 0)
+ FAIL_STACK_ERROR;
+ if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)
+ FAIL_STACK_ERROR
+ if(H5Pset_chunk(dcpl, 2, chunk_dims) < 0)
+ FAIL_STACK_ERROR;
+ if((did1 = H5Dcreate2(fid, "dataset1", H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Get the dataset's access property list */
+ if((ddapl = H5Dget_access_plist(did1)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Retrieve the append flush property values */
+ if(H5Pget_append_flush(ddapl, 3, ret_boundary, &ret_cb, (void **)&ret_count) < 0)
+ TEST_ERROR
+
+ /* Verify expected values */
+ if(ret_boundary[0] != 0 || ret_boundary[1] != 0 || ret_boundary[2] != 0)
+ TEST_ERROR;
+ if(ret_cb != NULL || ret_count != NULL)
+ TEST_ERROR
+
+ /* Close the dataset's access property list */
+ if(H5Pclose(ddapl) < 0)
+ FAIL_STACK_ERROR;
+
+ /*
+ * Case (2)--
+ * For a chunked dataset's access property list:
+ * --to verify failure in creating the dataset when:
+ * --the rank set in append flush property is not the same as the dataset's rank
+ * -- boundary (non-zero) is set for a non-extendible dimension
+ * --to verify failure in opening the dataset
+ * -- boundary (non-zero) is set for a non-extendible dimension
+ */
+ /* Create a copy of dataset access property list */
+ if((dapl = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set boundary dimension rank > the rank of dataset to be created */
+ HDmemset(boundary, 0, sizeof(boundary));
+ if(H5Pset_append_flush(dapl, 3, boundary, NULL, NULL) < 0)
+ FAIL_STACK_ERROR
+
+ /* Should fail to Create the dataset */
+ H5E_BEGIN_TRY {
+ did2 = H5Dcreate2(fid, "dataset2", H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, dapl);
+ } H5E_END_TRY;
+ if(did2 >= 0)
+ TEST_ERROR
+
+ /* Set boundary for a non-extendible dimension */
+ boundary[0] = boundary[1] = 1;
+ if(H5Pset_append_flush(dapl, 2, boundary, NULL, NULL) < 0)
+ FAIL_STACK_ERROR
+
+ /* Should fail to create the dataset */
+ H5E_BEGIN_TRY {
+ did2 = H5Dcreate2(fid, "dataset2", H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, dapl);
+ } H5E_END_TRY;
+ if(did2 >= 0)
+ TEST_ERROR
+
+ /* Create and close the dataset */
+ if((did2 = H5Dcreate2(fid, "dataset2", H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Dclose(did2) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should fail to open the dataset */
+ H5E_BEGIN_TRY {
+ did2 = H5Dopen(fid, "dataset2", dapl);
+ } H5E_END_TRY;
+ if(did2 >= 0)
+ TEST_ERROR
+
+ /*
+ * Case (3)--
+ * For a chunked dataset's access property list:
+ * --To verify the append flush property values retrieved from a non-default
+ * access property list:
+ * -- the set callback function, the set user data
+ * -- the # of boundary sizes retrieved does not exceed MIN(input ndims, the ndims set)
+ */
+
+ boundary[0] = 0;
+ boundary[1] = 1;
+ if(H5Pset_append_flush(dapl, 2, boundary, append_cb, &count) < 0)
+ FAIL_STACK_ERROR
+ if((did2 = H5Dopen(fid, "dataset2", dapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Get the dataset's access property list */
+ if((ddapl = H5Dget_access_plist(did2)) < 0)
+ FAIL_STACK_ERROR
+
+ HDmemset(ret_boundary, 0, sizeof(ret_boundary));
+ ret_cb = NULL;
+ ret_count = NULL;
+ /* Retrieve the append flush property values */
+ if(H5Pget_append_flush(ddapl, 3, ret_boundary, &ret_cb, (void **)&ret_count) < 0)
+ TEST_ERROR
+
+ /* Verify expected values */
+ if(ret_cb != append_cb || ret_count != &count)
+ TEST_ERROR
+ if(ret_boundary[0] != 0 || ret_boundary[1] != 1 || ret_boundary[2] != 0)
+ TEST_ERROR
+
+ HDmemset(ret_boundary, 0, sizeof(ret_boundary));
+ /* Retrieve the append flush property values */
+ if(H5Pget_append_flush(ddapl, 1, ret_boundary, NULL, NULL) < 0)
+ TEST_ERROR
+ if(ret_boundary[0] != 0 || ret_boundary[1] != 0 || ret_boundary[2] != 0)
+ TEST_ERROR
+
+ /* Closing */
+ if(H5Pclose(ddapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(dapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(dcpl) < 0)
+ FAIL_STACK_ERROR;
+
+ if(H5Pclose(fapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Dclose(did1) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Dclose(did2) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Sclose(sid) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ PASSED();
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(dcpl);
+ H5Pclose(dapl);
+ H5Pclose(ddapl);
+ H5Dclose(did1);
+ H5Dclose(did2);
+ H5Pclose(fapl);
+ H5Sclose(sid);
+ H5Fclose(fid);
+ } H5E_END_TRY;
+
+ return -1;
+} /* test_append_flush_dataset_chunked() */
+
+/*
+ * test_append_flush_dataset_fixed():
+ * To verify H5Pget/set_append_flush() work as specified for
+ * a non-chunked (fixed size) dataset's access property list:
+ * (1) To verify success in creating the dataset--whatever is set for the append flush property setting
+ * (2) To verify that default append flush property values are retrieved for both
+ * default or non-default access property list:
+ * -- zero boundary, null callback function, null user data
+ */
+static int
+test_append_flush_dataset_fixed(hid_t in_fapl)
+{
+ hid_t fid = -1; /* file ID */
+ hid_t fapl = -1; /* A copy of file access property */
+ hid_t did1 = -1, did2 = -1; /* The datset ID */
+ hid_t sid = -1; /* The dataspace ID */
+ hid_t dapl = -1; /* A copy of dataset access property */
+ hid_t ddapl = -1; /* The dataset access property of the opened dataset */
+
+ hsize_t boundary[3]; /* Boundary size */
+ unsigned count = 0; /* User data */
+
+ hsize_t ret_boundary[3]; /* Boundary size set in the append flush property */
+ H5D_append_cb_t ret_cb; /* The callback function set in the append flush property */
+ unsigned *ret_count; /* The user data set in the append flush property */
+
+ char filename[NAME_BUF_SIZE]; /* file name */
+
+ hsize_t dims[1] = {100};
+
+ TESTING("H5Fget/set_append_flush() for a non-chunked dataset's access property list");
+
+ /*
+ * Case (1)--
+ * For a non-chunked dataset's access property list:
+ * --to verify the append flush property values retrieved from
+ * a default access property list is:
+ * zero boundary, null callback function, null user data
+ */
+
+ /* Get a copy of the input parameter in_fapl */
+ if((fapl = H5Pcopy(in_fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set to use the latest library format */
+ if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Set the filename to use for this test (dependent on fapl) */
+ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename));
+
+ /* Create the test file to work on */
+ if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Create a dataset */
+ if((sid = H5Screate_simple(1, dims, dims)) < 0)
+ FAIL_STACK_ERROR;
+ if((did1 = H5Dcreate2(fid, "dataset1", H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Get the dataset's access property list */
+ if((ddapl = H5Dget_access_plist(did1)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Retrieve the append flush property values */
+ if(H5Pget_append_flush(ddapl, 3, ret_boundary, &ret_cb, (void **)&ret_count) < 0)
+ TEST_ERROR
+
+ /* Verify expected values */
+ if(ret_boundary[0] != 0 || ret_boundary[1] != 0 || ret_boundary[2] != 0)
+ TEST_ERROR;
+ if(ret_cb != NULL || ret_count != NULL)
+ TEST_ERROR
+
+ /* Close the dataset's access property list */
+ if(H5Pclose(ddapl) < 0)
+ FAIL_STACK_ERROR;
+
+ /*
+ * Case (2)--
+ * For a non-chunked dataset's access property list:
+ * --to verify success in creating and opening the dataset even when append flush property
+ * is setup with error conditions:
+ * --the rank set in append flush property is not the same as the dataset's rank
+ * --boundary is set
+ * --to verify the append flush property values are:
+ * zero boundary, null callback function, null user data
+ */
+ /* Create a copy of dataset access property list */
+ if((dapl = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
+ FAIL_STACK_ERROR
+
+ boundary[0] = 1;
+ boundary[1] = boundary[2] = 0;
+ if(H5Pset_append_flush(dapl, 3, boundary, append_cb, &count) < 0)
+ FAIL_STACK_ERROR
+
+ /* Should succeed to create the dataset: append flush property has no effect */
+ if((did2 = H5Dcreate2(fid, "dataset2", H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, dapl)) < 0)
+ TEST_ERROR
+
+ /* Get the dataset's access property list */
+ if((ddapl = H5Dget_access_plist(did2)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Retrieve the append flush property values */
+ if(H5Pget_append_flush(ddapl, 3, ret_boundary, &ret_cb, (void **)&ret_count) < 0)
+ TEST_ERROR
+
+ /* Verify expected values */
+ if(ret_cb != NULL || ret_count != NULL)
+ TEST_ERROR
+ if(ret_boundary[0] != 0 || ret_boundary[1] != 0 || ret_boundary[2] != 0)
+ TEST_ERROR
+
+ /* Closing */
+ if(H5Pclose(ddapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Dclose(did2) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should succeed in opening the dataset: append flush property has no effect */
+ if((did2 = H5Dopen(fid, "dataset2", dapl)) < 0)
+ TEST_ERROR
+
+ /* Get the dataset's access property list */
+ if((ddapl = H5Dget_access_plist(did2)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Retrieve the append flush property values */
+ if(H5Pget_append_flush(ddapl, 3, ret_boundary, &ret_cb, (void **)&ret_count) < 0)
+ TEST_ERROR
+
+ /* Verify expected values */
+ if(ret_cb != NULL || ret_count != NULL)
+ TEST_ERROR
+ if(ret_boundary[0] != 0 || ret_boundary[1] != 0 || ret_boundary[2] != 0)
+ TEST_ERROR
+
+ if(H5Dclose(did2) < 0)
+ FAIL_STACK_ERROR
+ /*
+ * Case (3)--
+ * For a non-chunked dataset's access property list:
+ * --To verify the append flush property values retrieved from a non-default
+ * access property list:
+ * zero boundary, null callback function, null user data
+ */
+
+ HDmemset(boundary, 0, sizeof(boundary));
+ if(H5Pset_append_flush(dapl, 1, boundary, append_cb, &count) < 0)
+ FAIL_STACK_ERROR
+ if((did2 = H5Dopen(fid, "dataset2", dapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Get the dataset's access property list */
+ if((ddapl = H5Dget_access_plist(did2)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Retrieve the append flush property values */
+ if(H5Pget_append_flush(ddapl, 1, ret_boundary, &ret_cb, (void **)&ret_count) < 0)
+ TEST_ERROR
+
+ /* Verify expected values */
+ if(ret_cb != NULL || ret_count != NULL)
+ TEST_ERROR
+ if(ret_boundary[0] != 0 || ret_boundary[1] != 0 || ret_boundary[2] != 0)
+ TEST_ERROR
+
+ /* Closing */
+ if(H5Pclose(ddapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(dapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(fapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Dclose(did1) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Dclose(did2) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Sclose(sid) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ PASSED();
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(dapl);
+ H5Pclose(ddapl);
+ H5Dclose(did1);
+ H5Dclose(did2);
+ H5Pclose(fapl);
+ H5Sclose(sid);
+ H5Fclose(fid);
+ } H5E_END_TRY;
+
+ return -1;
+} /* test_append_flush_dataset_fixed() */
+
+/*
+ * test_append_flush_multiple()
+ * To verify H5Pget/set_append_flush() work as specified for
+ * multiple opens of a dataset:
+ * (1) did1 = H5Dcreate(...dapl1...)
+ * did2 = H5Dopen2(...dapl2)
+ * H5Pget_append_flush(did1...)
+ * H5Pget_append_flush(did2...)
+ * -- should return append flush property values set in dapl1
+ * (2) H5Dcreate(...H5P_DEFAULT...)
+ * H5Dclose()
+ * did1 = H5Dopen(...dapl1)
+ * did2 = H5Dopen(..dapl2)
+ * H5Pget_append_flush(did1, ...)
+ * H5Pget_append_flush(did2, ...)
+ * -- should return append flush property values set in dapl1
+ * NOTE:
+ * FOR NOW: return the append flush property values of the create or the very first open
+ * LATER ON: should REJECT subsequent dataset open if append flush property values differ
+ */
+static int
+test_append_flush_dataset_multiple(hid_t in_fapl)
+{
+ hid_t fid = -1; /* file ID */
+ hid_t fapl = -1; /* A copy of file access property */
+ hid_t did1 = -1, did2 = -1; /* The datset ID */
+ hid_t sid = -1; /* The dataspace ID */
+ hid_t dcpl = -1; /* A copy of dataset creation property */
+ hid_t dapl1 = -1; /* A copy of dataset access property */
+ hid_t dapl2 = -1; /* A copy of dataset access property */
+ hid_t ddapl = -1; /* The dataset access property of the opened dataset */
+
+ hsize_t boundary1[3]; /* Boundary size */
+ hsize_t boundary2[3]; /* Boundary size */
+ unsigned count1 = 0; /* User data */
+ unsigned count2 = 0; /* User data */
+
+ hsize_t ret_boundary[3]; /* Boundary size set in the append flush property */
+ H5D_append_cb_t ret_cb; /* The callback function set in the append flush property */
+ unsigned *ret_count; /* The user data set in the append flush property */
+
+ char filename[NAME_BUF_SIZE]; /* file name */
+
+ hsize_t dims[2] = {0, 0}; /* The dataset dimension sizes */
+ hsize_t maxdims[2] = {H5S_UNLIMITED, H5S_UNLIMITED}; /* The dataset maximum dimension sizes */
+ hsize_t chunk_dims[2] = {5,2}; /* The chunk dimesion sizes */
+
+ TESTING("H5Fget/set_append_flush() for multiple opens of a chunked dataset");
+
+ /*
+ * Case (1)
+ * For a chunked dataset's access property list:
+ * did1 = H5Dcreate(...dapl1...)
+ * did2 = H5Dopen2(...dapl2)
+ * H5Pget_append_flush(did1...)
+ * H5Pget_append_flush(did2...)
+ * -- should return append flush property values set in dapl1
+ */
+
+ /* Create a copy of dataset access property list */
+ if((dapl1 = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
+ FAIL_STACK_ERROR
+ if((dapl2 = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
+ FAIL_STACK_ERROR
+
+ boundary1[0] = 0;
+ boundary1[1] = 1;
+ count1 = 0;
+ if(H5Pset_append_flush(dapl1, 2, boundary1, append_cb, &count1) < 0)
+ FAIL_STACK_ERROR
+ boundary2[0] = 1;
+ boundary2[1] = 0;
+ count2 = 0;
+ if(H5Pset_append_flush(dapl2, 2, boundary2, append_cb2, &count2) < 0)
+ FAIL_STACK_ERROR
+
+ /* Get a copy of the input parameter in_fapl */
+ if((fapl = H5Pcopy(in_fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set to use the latest library format */
+ if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set the filename to use for this test (dependent on fapl) */
+ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename));
+
+ /* Create the test file to work on */
+ if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Create a chunked dataset with 2 extendible dimensions */
+ if((sid = H5Screate_simple(2, dims, maxdims)) < 0)
+ FAIL_STACK_ERROR;
+ if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)
+ FAIL_STACK_ERROR
+ if(H5Pset_chunk(dcpl, 2, chunk_dims) < 0)
+ FAIL_STACK_ERROR;
+ if((did1 = H5Dcreate2(fid, "dataset1", H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, dapl1)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Open the dataset */
+ if((did2 = H5Dopen2(fid, "dataset1", dapl2)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Get the dataset's access property list for did1 */
+ if((ddapl = H5Dget_access_plist(did1)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Retrieve the append flush property values */
+ if(H5Pget_append_flush(ddapl, 3, ret_boundary, &ret_cb, (void **)&ret_count) < 0)
+ TEST_ERROR
+
+ /* Verify expected values: should be the setting in dapl1 */
+ if(ret_boundary[0] != 0 || ret_boundary[1] != 1 || ret_boundary[2] != 0)
+ TEST_ERROR;
+ if(ret_cb != append_cb || ret_count != &count1)
+ TEST_ERROR
+
+ /* Close the dataset's access property list */
+ if(H5Pclose(ddapl) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Get the dataset's access property list for did2 */
+ if((ddapl = H5Dget_access_plist(did2)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Retrieve the append flush property values */
+ if(H5Pget_append_flush(ddapl, 3, ret_boundary, &ret_cb, (void **)&ret_count) < 0)
+ TEST_ERROR
+
+ /* Verify expected values: should be the setting in dapl1 */
+ if(ret_boundary[0] != 0 || ret_boundary[1] != 1 || ret_boundary[2] != 0)
+ TEST_ERROR;
+ if(ret_cb != append_cb || ret_count != &count1)
+ TEST_ERROR
+
+ /* Close the dataset's access property list */
+ if(H5Pclose(ddapl) < 0)
+ FAIL_STACK_ERROR;
+ H5Dclose(did1);
+ H5Dclose(did2);
+
+ /*
+ * Case (2)
+ * For a chunked dataset's access property list:
+ * H5Dcreate(...H5P_DEFAULT...)
+ * H5Dclose()
+ * did1 = H5Dopen(...dapl1)
+ * did2 = H5Dopen(..dapl2)
+ * H5Pget_append_flush(did1, ...)
+ * H5Pget_append_flush(did2, ...)
+ * -- should return append flush property values set in dapl1
+ */
+ if((did1 = H5Dcreate2(fid, "dataset2", H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Dclose(did1) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Open the dataset with append flush setting in dapl2 */
+ if((did1 = H5Dopen2(fid, "dataset2", dapl2)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Open the dataset with append flush setting in dapl1 */
+ if((did2 = H5Dopen2(fid, "dataset2", dapl1)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Get the dataset's access property list for did1 */
+ if((ddapl = H5Dget_access_plist(did1)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Retrieve the append flush property values */
+ if(H5Pget_append_flush(ddapl, 3, ret_boundary, &ret_cb, (void **)&ret_count) < 0)
+ TEST_ERROR
+
+ /* Verify expected values: should be the setting in dapl2 */
+ if(ret_boundary[0] != 1 || ret_boundary[1] != 0 || ret_boundary[2] != 0)
+ TEST_ERROR;
+ if(ret_cb != append_cb2 || ret_count != &count2)
+ TEST_ERROR
+
+ /* Close the access property list */
+ if(H5Pclose(ddapl) < 0)
+ FAIL_STACK_ERROR;
+
+
+ /* Get the dataset's access property list for did2 */
+ if((ddapl = H5Dget_access_plist(did2)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Retrieve the append flush property values */
+ if(H5Pget_append_flush(ddapl, 3, ret_boundary, &ret_cb, (void **)&ret_count) < 0)
+ TEST_ERROR
+
+ /* Verify expected values: should be the setting in dapl2 */
+ if(ret_boundary[0] != 1 || ret_boundary[1] != 0 || ret_boundary[2] != 0)
+ TEST_ERROR;
+ if(ret_cb != append_cb2 || ret_count != &count2)
+ TEST_ERROR
+
+ /* Closing */
+ if(H5Pclose(ddapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(dapl2) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(dapl1) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(dcpl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(fapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Dclose(did1) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Dclose(did2) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Sclose(sid) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ PASSED();
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(dcpl);
+ H5Pclose(dapl1);
+ H5Pclose(dapl2);
+ H5Pclose(ddapl);
+ H5Dclose(did1);
+ H5Dclose(did2);
+ H5Pclose(fapl);
+ H5Sclose(sid);
+ H5Fclose(fid);
+ } H5E_END_TRY;
+
+ return -1;
+} /* test_append_flush_dataset_multiple() */
+
+/****************************************************************
+**
+** test_file(): Main low-level file I/O test routine.
+**
+****************************************************************/
+int
+main(void)
+{
+ int nerrors = 0; /* The # of errors */
+ hid_t fapl = -1; /* File access property list ID */
+
+ /* Set up */
+ h5_reset();
+
+ /* Get file access property list */
+ fapl = h5_fileaccess();
+
+ /* Tests on H5Fstart_swmr_write() */
+ nerrors += test_start_swmr_write(fapl);
+ nerrors += test_err_start_swmr_write(fapl);
+ nerrors += test_start_swmr_write_concur(fapl);
+
+ /* Tests for H5Pget/set_object_flush_cb() */
+ nerrors += test_object_flush_cb(fapl);
+
+ /* Tests on H5Pget/set_append_flush() */
+ nerrors += test_append_flush_generic();
+ nerrors += test_append_flush_dataset_chunked(fapl);
+ nerrors += test_append_flush_dataset_fixed(fapl);
+ nerrors += test_append_flush_dataset_multiple(fapl);
+
+ if(nerrors)
+ goto error;
+
+ printf("All tests passed for H5Fstart_swmr_write(), H5Pget/set_object_flush_cb(), H5Pget/set_append_flush().\n");
+
+ h5_cleanup(FILENAME, fapl);
+
+ return 0;
+
+error:
+ nerrors = MAX(1, nerrors);
+ printf("***** %d SWMR TEST%s FAILED! *****\n",
+ nerrors, 1 == nerrors ? "" : "S");
+ return 1;
+
+} /* main() */
diff --git a/test/testswmr.sh b/test/testswmr.sh
index 794910c..42e76ce 100755
--- a/test/testswmr.sh
+++ b/test/testswmr.sh
@@ -34,6 +34,14 @@ Nsecs_addrem=8 # number of seconds per read interval
nerrors=0
###############################################################################
+## definitions for message file to coordinate test runs
+###############################################################################
+WRITER_MESSAGE=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,
@@ -48,8 +56,42 @@ TESTING() {
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
@@ -103,6 +145,66 @@ do
echo
echo "###############################################################################"
+ echo "## Use H5Fstart_swmr_write() to enable SWMR writing mode"
+ echo "###############################################################################"
+
+ # Remove any possible writer message file before launching writer
+ rm -f $WRITER_MESSAGE
+ #
+ # Launch the Writer
+ echo launch the swmr_start_writer
+ seed="" # Put -r <random seed> command here
+ ./swmr_start_write $compress $index_type $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 swmr_readers
+ pid_readers=""
+ n=0
+ while [ $n -lt $Nreaders ]; do
+ #seed="-r ${seeds[$n]}"
+ seed=""
+ ./swmr_reader $Nsecs_add $seed &
+ pid_readers="$pid_readers $!"
+ n=`expr $n + 1`
+ done
+ $DPRINT pid_readers=$pid_readers
+ $IFDEBUG ps
+
+ # Collect exit code of the readers first because they usually finish
+ # before the writer.
+ for xpid in $pid_readers; do
+ $DPRINT checked reader $xpid
+ wait $xpid
+ if test $? -ne 0; then
+ echo reader had error
+ nerrors=`expr $nerrors + 1`
+ fi
+ done
+
+ # Collect exit code of the writer
+ $DPRINT checked writer $pid_writer
+ wait $pid_writer
+ if test $? -ne 0; then
+ echo writer had error
+ nerrors=`expr $nerrors + 1`
+ fi
+
+ # Check for error and exit if one occured
+ $DPRINT nerrors=$nerrors
+ if test $nerrors -ne 0 ; then
+ echo "SWMR tests failed with $nerrors errors."
+ exit 1
+ fi
+
+ echo
+ echo "###############################################################################"
echo "## Writer test - test expanding the dataset"
echo "###############################################################################"
@@ -113,14 +215,19 @@ do
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 swmr_writer
seed="" # Put -r <random seed> command here
./swmr_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 Readers
#declare -a seeds=(<seed1> <seed2> <seed3> ... )
echo launch $Nreaders swmr_readers
@@ -166,14 +273,19 @@ do
echo "###############################################################################"
echo "## Remove test - test shrinking the dataset"
echo "###############################################################################"
-
+ #
+ # Remove any possible writer message file before launching writer
+ rm -f $WRITER_MESSAGE
# Launch the Remove Writer
echo launch the swmr_remove_writer
seed="" # Put -r <random seed> command here
./swmr_remove_writer $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
@@ -236,14 +348,20 @@ do
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 swmr_addrem_writer
seed="" # Put -r <random seed> command here
./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
@@ -300,13 +418,18 @@ do
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 swmr_sparse_writer
nice -n 20 ./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=""
diff --git a/test/tfile.c b/test/tfile.c
index e2c7bf4..8d64b64 100644
--- a/test/tfile.c
+++ b/test/tfile.c
@@ -118,6 +118,9 @@
#define NGROUPS 2
#define NDSETS 4
+/* Name of message file that is used by test_file_lock_concur() and test_file_lock_swmr_concur() */
+#define DONE_MESSAGE "DONE_MESSAGE" /* The message file to create */
+
const char *OLD_FILENAME[] = { /* Files created under 1.6 branch and 1.8 branch */
"filespace_1_6.h5", /* 1.6 HDF5 file */
"filespace_1_8.h5" /* 1.8 HDF5 file */
@@ -144,6 +147,16 @@ test_obj_count_and_id(hid_t, hid_t, hid_t, hid_t, hid_t, hid_t);
static void
check_file_id(hid_t, hid_t);
+/* Helper routine used by test_rw_noupdate() */
+static int cal_chksum(const char *file, uint32_t *chksum);
+
+static void test_rw_noupdate(void);
+
+static void test_file_lock_same(void);
+static void test_file_lock_swmr_same(void);
+static void test_file_lock_concur(void);
+static void test_file_lock_swmr_concur(void);
+
/****************************************************************
**
** test_file_create(): Low-level file creation I/O test routine.
@@ -2312,6 +2325,104 @@ test_cached_stab_info(void)
CHECK(ret, FAIL, "H5Fclose");
} /* end test_cached_stab_info() */
+/*
+ * To calculate the checksum for a file.
+ * This is a helper routine for test_rw_noupdate().
+ */
+static int
+cal_chksum(const char *file, uint32_t *chksum)
+{
+ int curr_num_errs = GetTestNumErrs(); /* Retrieve the current # of errors */
+ int fdes = -1; /* File descriptor */
+ void *file_data = NULL; /* Copy of file data */
+ ssize_t bytes_read; /* # of bytes read */
+ h5_stat_t sb; /* Stat buffer for file */
+ herr_t ret; /* Generic return value */
+
+ /* Open the file */
+ fdes = HDopen(file, O_RDONLY, 0);
+ CHECK(fdes, FAIL, "HDopen");
+
+ /* Retrieve the file's size */
+ ret = HDfstat(fdes, &sb);
+ CHECK(fdes, FAIL, "HDfstat");
+
+ /* Allocate space for the file data */
+ file_data = HDmalloc((size_t)sb.st_size);
+ CHECK(file_data, NULL, "HDmalloc");
+
+ if(file_data) {
+ /* Read file's data into memory */
+ bytes_read = HDread(fdes, file_data, (size_t)sb.st_size);
+ CHECK(bytes_read == sb.st_size, FALSE, "HDmalloc");
+
+ /* Calculate checksum */
+ *chksum = H5_checksum_lookup3(file_data, sizeof(file_data), 0);
+
+ /* Free memory */
+ HDfree(file_data);
+ }
+
+ /* Close the file */
+ ret = HDclose(fdes);
+ CHECK(ret, FAIL, "HDclose");
+
+ return((GetTestNumErrs() == curr_num_errs) ? 0 : -1);
+} /* cal_chksum() */
+
+/****************************************************************
+**
+** test_rw_noupdate(): low-level file test routine.
+** This test checks to ensure that opening and closing a file
+** with read/write permissions does not write anything to the
+** file if the file does not change.
+** Due to the implementation of file locking (status_flags in
+** the superblock is used), this test is changed to use checksum
+** instead of timestamp to verify the file is not changed.
+**
+** Programmer: Vailin Choi; July 2013
+**
+*****************************************************************/
+static void
+test_rw_noupdate(void)
+{
+ herr_t ret; /* Generic return value */
+ hid_t fid; /* File ID */
+ uint32_t chksum1, chksum2; /* Checksum value */
+
+ /* Output message about test being performed */
+ MESSAGE(5, ("Testing to verify that nothing is written if nothing is changed.\n"));
+
+ /* Create and Close a HDF5 File */
+ fid = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fcreate");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Calculate checksum for the file */
+ ret = cal_chksum(FILE1, &chksum1);
+ CHECK(ret, FAIL, "HDopen");
+
+ /* Open and close File With Read/Write Permission */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Calculate checksum for the file */
+ ret = cal_chksum(FILE1, &chksum2);
+ CHECK(ret, FAIL, "HDopen");
+
+ /* The two checksums are the same, i.e. the file is not changed */
+ VERIFY(chksum1, chksum2, "Checksum");
+
+} /* end test_rw_noupdate() */
+
+#ifdef OUT
/****************************************************************
**
** test_rw_noupdate(): low-level file test routine.
@@ -2400,6 +2511,7 @@ test_rw_noupdate(void)
VERIFY(ret, 0, "Timestamp");
} /* end else */
} /* end test_rw_noupdate() */
+#endif
/****************************************************************
**
@@ -3501,268 +3613,6 @@ test_libver_macros2(void)
/****************************************************************
**
-** test_swmr_write(): low-level file test routine.
-** This test checks that the H5F_ACC_SWMR_WRITE access flag is
-** working properly.
-**
-*****************************************************************/
-static void
-test_swmr_write(void)
-{
- hid_t fid, fid2; /* File IDs */
- hid_t fapl; /* File access property list id */
- unsigned intent; /* File access flags */
- herr_t ret; /* Generic return value */
-
- /* Output message about test being performed */
- MESSAGE(5, ("Testing H5F_ACC_SWMR_WRITE access flag\n"));
-
- /* Create a file access property list */
- fapl = H5Pcreate(H5P_FILE_ACCESS);
- CHECK(fapl, FAIL, "H5Pcreate");
-
- /* Set to use the latest library format */
- ret = H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST);
- CHECK(ret, FAIL, "H5Pset_libver_bounds");
-
- /* Create file, without SWMR_WRITE flag */
- fid = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl);
- CHECK(fid, FAIL, "H5Fcreate");
-
- /* Get the intent & check that the SWMR_WRITE flag is not set */
- ret = H5Fget_intent(fid, &intent);
- CHECK(ret, FAIL, "H5Fget_intent");
- VERIFY(intent, H5F_ACC_RDWR, "H5Fget_intent");
-
- /* Try to reopen file w/SWMR_WRITE flag */
- H5E_BEGIN_TRY {
- fid2 = H5Fopen(FILE1, (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE), fapl);
- } H5E_END_TRY;
- VERIFY(fid2, FAIL, "H5Fopen");
-
- /* Close file */
- ret = H5Fclose(fid);
- CHECK(ret, FAIL, "H5Fclose");
-
-
- /* Attempt to open file, with SWMR_WRITE flag but not latest format */
- H5E_BEGIN_TRY {
- fid = H5Fopen(FILE1, (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE), H5P_DEFAULT);
- } H5E_END_TRY;
- VERIFY(fid, FAIL, "H5Fopen");
-
-
- /* Create file, with SWMR_WRITE flag */
- fid = H5Fcreate(FILE1, (H5F_ACC_TRUNC | H5F_ACC_SWMR_WRITE), H5P_DEFAULT, fapl);
- CHECK(fid, FAIL, "H5Fcreate");
-
- /* Get the intent & check that the SWMR_WRITE flag is set */
- ret = H5Fget_intent(fid, &intent);
- CHECK(ret, FAIL, "H5Fget_intent");
- VERIFY(intent, (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE), "H5Fget_intent");
-
- /* Try to reopen file w/o SWMR_WRITE flag */
- H5E_BEGIN_TRY {
- fid2 = H5Fopen(FILE1, H5F_ACC_RDWR, fapl);
- } H5E_END_TRY;
- VERIFY(fid2, FAIL, "H5Fopen");
-
- /* Reopen file, with read-write and SWMR_WRITE access */
- fid2 = H5Fopen(FILE1, (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE), fapl);
- CHECK(fid2, FAIL, "H5Fopen");
-
- /* Get the intent & check that the SWMR_WRITE flag is set */
- ret = H5Fget_intent(fid2, &intent);
- CHECK(ret, FAIL, "H5Fget_intent");
- VERIFY(intent, (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE), "H5Fget_intent");
-
- /* Close file */
- ret = H5Fclose(fid2);
- CHECK(ret, FAIL, "H5Fclose");
-
- /* Close file */
- ret = H5Fclose(fid);
- CHECK(ret, FAIL, "H5Fclose");
-
-
- /* Try to reopen file read-only w/SWMR_WRITE flag */
- H5E_BEGIN_TRY {
- fid = H5Fopen(FILE1, (H5F_ACC_RDONLY | H5F_ACC_SWMR_WRITE), fapl);
- } H5E_END_TRY;
- VERIFY(fid, FAIL, "H5Fopen");
-
-
- /* Reopen file, with read-write and SWMR_WRITE access */
- fid = H5Fopen(FILE1, (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE), fapl);
- CHECK(fid, FAIL, "H5Fopen");
-
- /* Get the intent & check that the SWMR_WRITE flag is set */
- ret = H5Fget_intent(fid, &intent);
- CHECK(ret, FAIL, "H5Fget_intent");
- VERIFY(intent, (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE), "H5Fget_intent");
-
- /* Try to reopen file w/o SWMR_WRITE flag */
- H5E_BEGIN_TRY {
- fid2 = H5Fopen(FILE1, H5F_ACC_RDWR, fapl);
- } H5E_END_TRY;
- VERIFY(fid2, FAIL, "H5Fopen");
-
- /* Reopen file, with read-write and SWMR_WRITE access */
- fid2 = H5Fopen(FILE1, (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE), fapl);
- CHECK(fid2, FAIL, "H5Fopen");
-
- /* Get the intent & check that the SWMR_WRITE flag is set */
- ret = H5Fget_intent(fid2, &intent);
- CHECK(ret, FAIL, "H5Fget_intent");
- VERIFY(intent, (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE), "H5Fget_intent");
-
- /* Close file */
- ret = H5Fclose(fid2);
- CHECK(ret, FAIL, "H5Fclose");
-
- /* Close file */
- ret = H5Fclose(fid);
- CHECK(ret, FAIL, "H5Fclose");
-
- /* Close the property list */
- ret = H5Pclose(fapl);
- CHECK(ret, FAIL, "H5Pclose");
-
-
- /* Create a file access property list */
- fapl = H5Pcreate(H5P_FILE_ACCESS);
- CHECK(fapl, FAIL, "H5Pcreate");
-
- /* Set a non-POSIX VFD */
- ret = H5Pset_fapl_stdio(fapl);
- CHECK(ret, FAIL, "H5Pset_fapl_stdio");
-
- /* Try to reopen file w/SWMR_WRITE flag & non-POSIX VFD */
- H5E_BEGIN_TRY {
- fid = H5Fopen(FILE1, (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE), fapl);
- } H5E_END_TRY;
- VERIFY(fid, FAIL, "H5Fopen");
-
- /* Close the property list */
- ret = H5Pclose(fapl);
- CHECK(ret, FAIL, "H5Pclose");
-
-} /* end test_swmr_write() */
-
-/****************************************************************
-**
-** test_swmr_read(): low-level file test routine.
-** This test checks that the H5F_ACC_SWMR_READ access flag is
-** working properly.
-**
-*****************************************************************/
-static void
-test_swmr_read(void)
-{
- hid_t fid, fid2; /* File IDs */
- hid_t fapl; /* File access property list id */
- unsigned intent; /* File access flags */
- herr_t ret; /* Generic return value */
-
- /* Output message about test being performed */
- MESSAGE(5, ("Testing H5F_ACC_SWMR_READ access flag\n"));
-
-
- /* Try to create file w/SWMR_READ flag */
- H5E_BEGIN_TRY {
- fid = H5Fcreate(FILE1, (H5F_ACC_TRUNC | H5F_ACC_SWMR_READ), H5P_DEFAULT, H5P_DEFAULT);
- } H5E_END_TRY;
- VERIFY(fid, FAIL, "H5Fcreate");
-
-
- /* Create file, without SWMR_READ flag */
- fid = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
- CHECK(fid, FAIL, "H5Fcreate");
-
- /* Get the intent & check that the SWMR_READ flag is not set */
- ret = H5Fget_intent(fid, &intent);
- CHECK(ret, FAIL, "H5Fget_intent");
- VERIFY(intent, H5F_ACC_RDWR, "H5Fget_intent");
-
- /* Try to reopen file w/SWMR_READ flag */
- H5E_BEGIN_TRY {
- fid2 = H5Fopen(FILE1, (H5F_ACC_RDWR | H5F_ACC_SWMR_READ), H5P_DEFAULT);
- } H5E_END_TRY;
- VERIFY(fid2, FAIL, "H5Fopen");
-
- /* Close file */
- ret = H5Fclose(fid);
- CHECK(ret, FAIL, "H5Fclose");
-
-
- /* Try to open file, with read-write access & SWMR_READ flag */
- H5E_BEGIN_TRY {
- fid = H5Fopen(FILE1, (H5F_ACC_RDWR | H5F_ACC_SWMR_READ), H5P_DEFAULT);
- } H5E_END_TRY;
- VERIFY(fid, FAIL, "H5Fopen");
-
-
- /* Attempt to open file, with SWMR_WRITE flag but not latest format */
- H5E_BEGIN_TRY {
- fid = H5Fopen(FILE1, (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE), H5P_DEFAULT);
- } H5E_END_TRY;
- VERIFY(fid, FAIL, "H5Fopen");
-
- /* Open file, with SWMR_READ flag (and non-latest format) */
- fid = H5Fopen(FILE1, (H5F_ACC_RDONLY | H5F_ACC_SWMR_READ), H5P_DEFAULT);
- CHECK(fid, FAIL, "H5Fopen");
-
- /* Get the intent & check that the SWMR_READ flag is set */
- ret = H5Fget_intent(fid, &intent);
- CHECK(ret, FAIL, "H5Fget_intent");
- VERIFY(intent, (H5F_ACC_RDONLY | H5F_ACC_SWMR_READ), "H5Fget_intent");
-
- /* Try to reopen file w/o SWMR_READ flag */
- H5E_BEGIN_TRY {
- fid2 = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
- } H5E_END_TRY;
- VERIFY(fid2, FAIL, "H5Fopen");
-
- /* Reopen file, with read-only and SWMR_READ access */
- fid2 = H5Fopen(FILE1, (H5F_ACC_RDONLY | H5F_ACC_SWMR_READ), H5P_DEFAULT);
- CHECK(fid2, FAIL, "H5Fopen");
-
- /* Get the intent & check that the SWMR_READ flag is set */
- ret = H5Fget_intent(fid2, &intent);
- CHECK(ret, FAIL, "H5Fget_intent");
- VERIFY(intent, (H5F_ACC_RDONLY | H5F_ACC_SWMR_READ), "H5Fget_intent");
-
- /* Close file */
- ret = H5Fclose(fid2);
- CHECK(ret, FAIL, "H5Fclose");
-
- /* Close file */
- ret = H5Fclose(fid);
- CHECK(ret, FAIL, "H5Fclose");
-
-
- /* Create a file access property list */
- fapl = H5Pcreate(H5P_FILE_ACCESS);
- CHECK(fapl, FAIL, "H5Pcreate");
-
- /* Set a non-POSIX VFD */
- ret = H5Pset_fapl_stdio(fapl);
- CHECK(ret, FAIL, "H5Pset_fapl_stdio");
-
- /* Try to reopen file w/SWMR_READ flag & non-POSIX VFD */
- H5E_BEGIN_TRY {
- fid = H5Fopen(FILE1, (H5F_ACC_RDONLY | H5F_ACC_SWMR_READ), fapl);
- } H5E_END_TRY;
- VERIFY(fid, FAIL, "H5Fopen");
-
- /* Close the property list */
- ret = H5Pclose(fapl);
- CHECK(ret, FAIL, "H5Pclose");
-
-} /* end test_swmr_read() */
-
-/****************************************************************
-**
** test_metadata_read_attempts():
** This test checks whether the following two public routines work as
** specified in the reference manuals:
@@ -5041,6 +4891,1305 @@ test_metadata_read_retry_info(void)
/****************************************************************
**
+** test_file_lock_same():
+** With the implementation of file locking, this test checks file
+** open with different combinations of flags.
+** This is for single process access.
+**
+*****************************************************************/
+static void
+test_file_lock_same(void)
+{
+ hid_t fid, fid2; /* File IDs */
+ unsigned intent; /* File access flags */
+ herr_t ret; /* Generic return value */
+
+ /* Output message about test being performed */
+ MESSAGE(5, ("Testing file open with different combinations of flags--single process access\n"));
+
+ /*
+ * Case 1: 1) RDWR 2) RDWR : should succeed
+ */
+ /* Create file */
+ fid = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fcreate");
+
+ /* Get and check file intent */
+ ret = H5Fget_intent(fid, &intent);
+ CHECK(ret, FAIL, "H5Fget_intent");
+ VERIFY(intent, H5F_ACC_RDWR, "H5Fget_intent");
+
+ /* Open the same file with RDWR */
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+
+ /* Get and check the intent */
+ ret = H5Fget_intent(fid2, &intent);
+ CHECK(ret, FAIL, "H5Fget_intent");
+ VERIFY(intent, H5F_ACC_RDWR, "H5Fget_intent");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Close file */
+ ret = H5Fclose(fid2);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 2: 1) RDWR 2) RDONLY : should succeed
+ */
+ /* Open file with RDWR */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fcreate");
+
+ /* Get and check the intent */
+ ret = H5Fget_intent(fid, &intent);
+ CHECK(ret, FAIL, "H5Fget_intent");
+ VERIFY(intent, H5F_ACC_RDWR, "H5Fget_intent");
+
+ /* Open file with RDONLY */
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+
+ /* Get and check the intent: should get intent from 1st open */
+ ret = H5Fget_intent(fid2, &intent);
+ CHECK(ret, FAIL, "H5Fget_intent");
+ VERIFY(intent, H5F_ACC_RDWR, "H5Fget_intent");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Close file */
+ ret = H5Fclose(fid2);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 3: 1) RDONLY 2) RDWR : should fail
+ */
+ /* Open file with RDONLY */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fcreate");
+
+ /* Get and check the intent */
+ ret = H5Fget_intent(fid, &intent);
+ CHECK(ret, FAIL, "H5Fget_intent");
+ VERIFY(intent, H5F_ACC_RDONLY, "H5Fget_intent");
+
+ /* Open file with RDWR should fail */
+ H5E_BEGIN_TRY {
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+ } H5E_END_TRY;
+ VERIFY(fid2, FAIL, "H5Fopen");
+
+ /* Close first file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 4: 1) RDONLY 2) RDONLY : should succeed
+ */
+ /* Open file with RDONLY */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fcreate");
+
+ /* Get and check the intent */
+ ret = H5Fget_intent(fid, &intent);
+ CHECK(ret, FAIL, "H5Fget_intent");
+ VERIFY(intent, H5F_ACC_RDONLY, "H5Fget_intent");
+
+ /* Open file with RDONLY */
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+
+ /* Get and check the intent */
+ ret = H5Fget_intent(fid2, &intent);
+ CHECK(ret, FAIL, "H5Fget_intent");
+ VERIFY(intent, H5F_ACC_RDONLY, "H5Fget_intent");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Close file */
+ ret = H5Fclose(fid2);
+ CHECK(ret, FAIL, "H5Fclose");
+
+} /* end test_file_lock_same() */
+
+/****************************************************************
+**
+** test_file_lock_swmr_same():
+** With the implementation of file locking, this test checks file
+** open with different combinations of flags + SWMR flags.
+** This is for single process access.
+**
+*****************************************************************/
+static void
+test_file_lock_swmr_same(void)
+{
+ hid_t fid, fid2; /* File IDs */
+ hid_t fapl; /* File access property list */
+ herr_t ret; /* Generic return value */
+
+ /* Output message about test being performed */
+ MESSAGE(5, ("Testing file open with different combinations of flags + SWMR flags--single process access\n"));
+
+ /* Create a file access property list */
+ fapl = H5Pcreate(H5P_FILE_ACCESS);
+ CHECK(fapl, FAIL, "H5Pcreate");
+
+ /* Set to use latest library format */
+ ret = H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST);
+ CHECK(ret, FAIL, "H5Pset_libver_bounds");
+
+ /* Create a file */
+ fid = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl);
+ CHECK(fid, FAIL, "H5Fcreate");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Cases a, b, c, d: H5Fopen failure cases
+ */
+
+ /*
+ * Case a: RDWR|SWRM_READ : should fail
+ */
+ H5E_BEGIN_TRY {
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_READ, fapl);
+ } H5E_END_TRY;
+ VERIFY(fid, FAIL, "H5Fopen");
+
+ /*
+ * Case b: RDWR|SWMM_WRTE|SWMR_READ : should fail
+ */
+ H5E_BEGIN_TRY {
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE|H5F_ACC_SWMR_READ, fapl);
+ } H5E_END_TRY;
+ VERIFY(fid, FAIL, "H5Fopen");
+
+ /*
+ * Case c: RDONLY|SWMM_WRITE : should fail
+ */
+ H5E_BEGIN_TRY {
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_WRITE, fapl);
+ } H5E_END_TRY;
+ VERIFY(fid, FAIL, "H5Fopen");
+
+ /*
+ * Case d: RDONLY|SWMM_WRITE|SWMR_READ : should fail
+ */
+ H5E_BEGIN_TRY {
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_WRITE|H5F_ACC_SWMR_READ, fapl);
+ } H5E_END_TRY;
+ VERIFY(fid, FAIL, "H5Fopen");
+
+ /*
+ * Cases 1 - 12: combinations of different flags for 1st and 2nd opens
+ */
+
+ /*
+ * Case 1: 1) RDWR 2) RDWR|SWMR_WRITE : should fail
+ */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ H5E_BEGIN_TRY {
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+ } H5E_END_TRY;
+ VERIFY(fid2, FAIL, "H5Fopen");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 2: 1) RDWR 2) RDONLY|SWMR_READ : should succeed
+ */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fopen");
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+ CHECK(fid2, FAIL, "H5Fopen");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+ ret = H5Fclose(fid2);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 3: 1) RDWR|SWMR_WRITE 2)RDWR : should succeed
+ */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+ CHECK(fid2, FAIL, "H5Fopen");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Close file */
+ ret = H5Fclose(fid2);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 4: 1) RDWR|SWMR_WRITE 2) RDWR|SWMR_WRITE : should succeed
+ */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+ CHECK(fid2, FAIL, "H5Fopen");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Close file */
+ ret = H5Fclose(fid2);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 5: 1) RDWR|SWMR_WRITE 2) RDONLY|SWMR_READ : should succeed
+ */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+ CHECK(fid2, FAIL, "H5Fopen");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Close file */
+ ret = H5Fclose(fid2);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 6: 1) RDWR|SWMR_WRITE 2) RDONLY : should succeed
+ */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+ CHECK(fid2, FAIL, "H5Fopen");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Close file */
+ ret = H5Fclose(fid2);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 7: 1) RDONLY|SWMR_READ 2)RDWR : should fail
+ */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ H5E_BEGIN_TRY {
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+ } H5E_END_TRY;
+ VERIFY(fid2, FAIL, "H5Fopen");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 8: 1) RDONLY|SWMR_READ 2) RDWR|SWMR_WRITE : should fail
+ */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ H5E_BEGIN_TRY {
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+ } H5E_END_TRY;
+ VERIFY(fid2, FAIL, "H5Fopen");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 9: 1) RDONLY|SWMR_READ 2) RDONLY|SWMR_READ : should succeed
+ */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+ CHECK(fid2, FAIL, "H5Fopen");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Close file */
+ ret = H5Fclose(fid2);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 10: 1) RDONLY|SWMR_READ 2) RDONLY : should succeed
+ */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+ CHECK(fid2, FAIL, "H5Fopen");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Close file */
+ ret = H5Fclose(fid2);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 11: 1) RDONLY 2) RDWR|SWMR_WRITE: should fail
+ */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ H5E_BEGIN_TRY {
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+ } H5E_END_TRY;
+ VERIFY(fid2, FAIL, "H5Fopen");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 12: 1) RDONLY 2) RDONLY|SWMR_READ : should fail
+ */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ H5E_BEGIN_TRY {
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+ } H5E_END_TRY;
+ VERIFY(fid2, FAIL, "H5Fopen");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Close the property list */
+ ret=H5Pclose(fapl);
+ CHECK(ret, FAIL, "H5Pclose");
+
+} /* end test_file_lock_swmr_same() */
+
+
+/****************************************************************
+**
+** test_file_lock_concur():
+** With the implementation of file locking, this test checks file
+** open with different combinations of flags.
+** This is for concurrent access.
+**
+*****************************************************************/
+static void
+test_file_lock_concur(void)
+{
+ hid_t fid; /* File ID */
+ herr_t ret; /* Generic return value */
+ pid_t childpid=0; /* Child process ID */
+ pid_t tmppid; /* Child process ID returned by waitpid */
+ int child_status; /* Status passed to waitpid */
+ int child_wait_option=0; /* Options passed to waitpid */
+ int child_ret_value; /* Exit status of the child */
+
+ /* Output message about test being performed */
+ MESSAGE(5, ("Testing file open with different combinations of flags--concurrent access\n"));
+
+#if !(defined(H5_HAVE_FORK) && defined(H5_HAVE_WAITPID))
+
+ SKIPPED();
+ HDputs(" Test skipped due to fork or waitpid not defined.");
+
+#else /* defined(H5_HAVE_FORK && defined(H5_HAVE_WAITPID) */
+
+ /* Create the test file */
+ fid = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 1: 1) RDWR 2) RDWR : should fail
+ */
+
+ /* Remove the message file to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Open the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+
+ /* Should fail */
+ if(child_fid == FAIL)
+ exit(0);
+ exit(1);
+ }
+
+ /* Open the test file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of the child */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 2: 1) RDWR 2) RDONLY : should fail
+ */
+ /* Remove the message file just to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Opens the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+
+ /* Should fail */
+ if(child_fid == FAIL)
+ exit(0);
+ exit(1);
+ }
+
+ /* Opens the test file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of the child */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ H5Fclose(fid);
+
+ /*
+ * Case 3: 1) RDONLY 2) RDWR : should fail
+ */
+
+ /* Remove the message file just to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Opens the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+
+ /* Should fail */
+ if(child_fid == FAIL)
+ exit(0);
+ exit(1);
+ }
+
+ /* Opens the test file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of child process */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 4: 1) RDONLY 2) RDONLY : should succeed
+ */
+
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+ herr_t child_ret; /* Return value */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Opens the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+
+ /* Should succeed */
+ if(child_fid >= 0) {
+ /* Close the file */
+ child_ret = H5Fclose(child_fid);
+ CHECK(child_ret, FAIL, "H5Fclose");
+ exit(0);
+ }
+ exit(1);
+ }
+ /* Create file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of child process */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+#endif
+
+} /* end test_file_lock_concur() */
+
+/****************************************************************
+**
+** test_file_lock_swmr_concur(): low-level file test routine.
+** With the implementation of file locking, this test checks file
+** open with different combinations of flags + SWMR flags.
+** This is for concurrent access.
+**
+*****************************************************************/
+static void
+test_file_lock_swmr_concur(void)
+{
+ hid_t fid; /* File ID */
+ hid_t fapl; /* File access property list */
+ herr_t ret; /* Generic return value */
+ pid_t childpid=0; /* Child process ID */
+ pid_t tmppid; /* Child process ID returned by waitpid */
+ int child_status; /* Status passed to waitpid */
+ int child_wait_option=0; /* Options passed to waitpid */
+ int child_ret_value; /* Exit status of the child */
+
+ /* Output message about test being performed */
+ MESSAGE(5, ("Testing file open with different combintations of flags + SWMR flags--concurrent access\n"));
+
+#if !(defined(H5_HAVE_FORK) && defined(H5_HAVE_WAITPID))
+
+ SKIPPED();
+ HDputs(" Test skipped due to fork or waitpid not defined.");
+
+#else /* defined(H5_HAVE_FORK && defined(H5_HAVE_WAITPID) */
+
+ /* Create a file access property list */
+ fapl = H5Pcreate(H5P_FILE_ACCESS);
+ CHECK(fapl, FAIL, "H5Pcreate");
+
+ /* Set to use latest library format */
+ ret = H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST);
+ CHECK(ret, FAIL, "H5Pset_libver_bounds");
+
+ /* Create the test file */
+ fid = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 1: 1) RDWR 2) RDWR|SWMR_WRITE : should fail
+ */
+
+ /* Remove the message file to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Open the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+
+ /* Should fail */
+ if(child_fid == FAIL)
+ exit(0);
+ exit(1);
+ }
+
+ /* Open the test file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of child process */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 2: 1) RDWR 2) RDONLY|SWMR_READ: should fail
+ */
+
+ /* Remove the message file to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Open the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+
+ /* Should fail */
+ if(child_fid == FAIL)
+ exit(0);
+ exit(1);
+ }
+
+ /* Open the test file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of child process */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 3: 1) RDWR|SWMR_WRITE 2) RDWR : should fail
+ */
+
+ /* Remove the message file to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Open the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+
+ /* Should fail */
+ if(child_fid == FAIL)
+ exit(0);
+ exit(1);
+ }
+
+ /* Open the test file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of child process */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 4: 1) RDWR|SWMR_WRITE 2) RDWR|SWMR_WRITE : should fail
+ */
+
+ /* Remove the message file just to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Open the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+
+ /* Should fail */
+ if(child_fid == FAIL)
+ exit(0);
+ exit(1);
+ }
+
+ /* Open the test file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of child process */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 5: 1) RDWR|SWMR_WRITE 2) RDONLY|SWMR_READ : should succeed
+ */
+
+ /* Remove the message file just to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+ herr_t child_ret; /* Return value */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Open the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+
+ /* Should succeed */
+ if(child_fid >= 0) {
+ child_ret = H5Fclose(child_fid);
+ CHECK(child_ret, FAIL, "H5Fclose");
+ exit(0);
+ }
+ exit(1);
+ }
+
+ /* Open the test file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of child process */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 6: 1) RDWR|SWMR_WRITE 2) RDONLY : should fail
+ */
+
+ /* Remove the message file just to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Open the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+ /* Should fail */
+ if(child_fid == FAIL)
+ exit(0);
+ exit(1);
+ }
+
+ /* Open the test file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of child process */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 7: 1) RDONLY|SWMR_READ 2) RDWR : should fail
+ */
+
+ /* Remove the message file just to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Open the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+ /* Should fail */
+ if(child_fid == FAIL)
+ exit(0);
+ exit(1);
+ }
+
+ /* Open the test file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of child process */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 8: 1) RDONLY|SWMR_READ 2) RDWR|SWMR_WRITE : should fail
+ */
+
+ /* Remove the message file just to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Open the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+ /* Should fail */
+ if(child_fid == FAIL)
+ exit(0);
+ exit(1);
+ }
+
+ /* Open the test file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of child process */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+
+ /*
+ * Case 9: 1) RDONLY|SWMR_READ 2) RDONLY|SWMR_READ : should succeed
+ */
+
+ /* Remove the message file just to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+ herr_t child_ret; /* Return value */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Open the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+
+ /* Should succeed */
+ if(child_fid >= 0) {
+ child_ret = H5Fclose(child_fid);
+ CHECK(child_ret, FAIL, "H5Fclose");
+ exit(0);
+ }
+ exit(1);
+ }
+
+ /* Open the test file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of child process */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 10: 1) RDONLY|SWMR_READ 2) RDONLY : should succeed
+ */
+
+ /* Remove the message file just to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+ herr_t child_ret; /* Return value */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Open the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+
+ /* Should succeed */
+ if(child_fid >= 0) {
+ child_ret = H5Fclose(child_fid);
+ CHECK(child_ret, FAIL, "H5Fclose");
+ exit(0);
+ }
+ exit(1);
+ }
+
+ /* Open the test file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of child process */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+
+ /*
+ * Case 11: 1) RDONLY 2) RDWR|SWMR_WRITE : should fail
+ */
+
+ /* Remove the message file just to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Open the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+ /* Should fail */
+ if(child_fid == FAIL)
+ exit(0);
+ exit(1);
+ }
+ /* Open the test file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of child process */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 12: 1) RDONLY 2) RDONLY|SWMR_READ : should succeed
+ */
+
+ /* Remove the message file just to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+ herr_t child_ret; /* Return value */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Open the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+
+ /* Should succeed */
+ if(child_fid >= 0) {
+ child_ret = H5Fclose(child_fid);
+ CHECK(child_ret, FAIL, "H5Fclose");
+ exit(0);
+ }
+ exit(1);
+ }
+
+ /* Open the test file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of child process */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Close the property list */
+ ret=H5Pclose(fapl);
+ CHECK(ret, FAIL, "H5Pclose");
+#endif
+
+} /* end test_file_lock_swmr_concur() */
+/****************************************************************
+**
** test_deprec():
** Test deprecated functionality.
**
@@ -5223,10 +6372,16 @@ test_file(void)
test_libver_bounds(); /* Test compatibility for file space management */
test_libver_macros(); /* Test the macros for library version comparison */
test_libver_macros2(); /* Test the macros for library version comparison */
- test_swmr_write(); /* Tests for SWMR write access flag */
- test_swmr_read(); /* Tests for SWMR read access flag */
test_metadata_read_attempts(); /* Tests for public routines H5Fget/set_metadata_read_attempts() */
test_metadata_read_retry_info(); /* Tests for public routine H5Fget_metadata_read_retry_info() */
+ /*
+ * The two tests: test_swmr_write() and test_swmr_read() are removed.
+ * They are covered by the following new tests.
+ */
+ test_file_lock_same(); /* Tests for file open flags--single process access */
+ test_file_lock_swmr_same(); /* Tests for file open flags+SWMR flags--single process access */
+ test_file_lock_concur(); /* Tests for file open flags--concurrent access */
+ test_file_lock_swmr_concur(); /* Tests for file open flags+SWMR flags--concurrent access */
#ifndef H5_NO_DEPRECATED_SYMBOLS
test_deprec(); /* Test deprecated routines */
#endif /* H5_NO_DEPRECATED_SYMBOLS */
diff --git a/test/th5s.h5 b/test/th5s.h5
index 7a0bfb3..bc2b666 100644
--- a/test/th5s.h5
+++ b/test/th5s.h5
Binary files differ
diff --git a/test/tlayouto.h5 b/test/tlayouto.h5
index a038e68..3322020 100644
--- a/test/tlayouto.h5
+++ b/test/tlayouto.h5
Binary files differ
diff --git a/test/tmtimen.h5 b/test/tmtimen.h5
index 96e5fb3..007a6b6 100644
--- a/test/tmtimen.h5
+++ b/test/tmtimen.h5
Binary files differ
diff --git a/test/tmtimeo.h5 b/test/tmtimeo.h5
index 8cacf4a..c9dfcc4 100644
--- a/test/tmtimeo.h5
+++ b/test/tmtimeo.h5
Binary files differ
diff --git a/test/use.h b/test/use.h
index 2d7c36d..45b4a49 100644
--- a/test/use.h
+++ b/test/use.h
@@ -21,7 +21,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "hdf5.h"
+#include "h5test.h"
/* Macro definitions */
#define Hgoto_error(val) {ret_value=val; goto done;}
@@ -33,6 +33,9 @@
#define UC_CTYPE short /* use case C data type */
#define UC_RANK 3 /* use case dataset rank */
+/* Name of message file that is sent by the writer */
+#define WRITER_MESSAGE "USE_WRITER_MESSAGE"
+
/* type declarations */
typedef enum part_t {
UC_READWRITE =0, /* both writer and reader */
@@ -62,23 +65,5 @@ int setup_parameters(int argc, char * const argv[]);
void show_parameters(void);
void usage(const char *prog);
int create_uc_file(void);
-int write_uc_file(void);
-int read_uc_file(void);
-
-/* private definitions of Standard functions */
-
-/* Standard POSIX functions */
-#define HDassert(s) assert(s)
-#define HDfree(s) free(s)
-#define HDgetenv(s) getenv(s)
-#define HDmalloc(s) malloc(s)
-#define HDmemcpy(X,C,Z) memcpy(X,C,Z)
-#define HDmemset(X,C,Z) memset(X,C,Z)
-#define HDperror(s) perror(s)
-#define HDstrcat(s1, s2) strcat(s1, s2)
-#define HDstrcmp(s1, s2) strcmp(s1, s2)
-#define HDstrcpy(s1, s2) strcpy(s1, s2)
-#define HDstrdup(s) strdup(s)
-#define HDstrlen(s) strlen(s)
-#define HDstrncpy(s1, s2, N) strncpy(s1, s2, N)
-#define HDstrrchr(s, c) strrchr(s, c)
+int write_uc_file(hbool_t tosend);
+int read_uc_file(hbool_t towait);
diff --git a/test/use_append_chunk.c b/test/use_append_chunk.c
index 2ec645e..a3219c2 100644
--- a/test/use_append_chunk.c
+++ b/test/use_append_chunk.c
@@ -118,12 +118,19 @@ main(int argc, char *argv[])
int child_wait_option=0;
int ret_value = 0;
int child_ret_value;
+ hbool_t send_wait = 0;
/* initialization */
if (setup_parameters(argc, argv) < 0){
Hgoto_error(1);
}
+ /* Determine the need to send/wait message file*/
+ if(UC_opts.launch == UC_READWRITE) {
+ HDunlink(WRITER_MESSAGE);
+ send_wait = 1;
+ }
+
/* ==============================================================*/
/* UC_READWRITE: create datafile, launch both reader and writer. */
/* UC_WRITER: create datafile, skip reader, launch writer. */
@@ -157,7 +164,7 @@ main(int argc, char *argv[])
/* child process launch the reader */
if(0 == childpid) {
printf("%d: launch reader process\n", mypid);
- if (read_uc_file() < 0){
+ if (read_uc_file(send_wait) < 0){
fprintf(stderr, "read_uc_file encountered error\n");
exit(1);
}
@@ -170,7 +177,7 @@ main(int argc, char *argv[])
/* ============= */
/* this process continues to launch the writer */
printf("%d: continue as the writer process\n", mypid);
- if (write_uc_file() < 0){
+ if (write_uc_file(send_wait) < 0){
fprintf(stderr, "write_uc_file encountered error\n");
Hgoto_error(1);
}
diff --git a/test/use_append_mchunks.c b/test/use_append_mchunks.c
index 113f75d..b19fe57 100644
--- a/test/use_append_mchunks.c
+++ b/test/use_append_mchunks.c
@@ -111,12 +111,19 @@ main(int argc, char *argv[])
int child_wait_option=0;
int ret_value = 0;
int child_ret_value;
+ hbool_t send_wait = 0;
/* initialization */
if (setup_parameters(argc, argv) < 0){
Hgoto_error(1);
}
+ /* Determine the need to send/wait message file*/
+ if(UC_opts.launch == UC_READWRITE) {
+ HDunlink(WRITER_MESSAGE);
+ send_wait = 1;
+ }
+
/* ==============================================================*/
/* UC_READWRITE: create datafile, launch both reader and writer. */
/* UC_WRITER: create datafile, skip reader, launch writer. */
@@ -150,7 +157,7 @@ main(int argc, char *argv[])
/* child process launch the reader */
if(0 == childpid) {
printf("%d: launch reader process\n", mypid);
- if (read_uc_file() < 0){
+ if (read_uc_file(send_wait) < 0){
fprintf(stderr, "read_uc_file encountered error\n");
exit(1);
}
@@ -163,7 +170,7 @@ main(int argc, char *argv[])
/* ============= */
/* this process continues to launch the writer */
printf("%d: continue as the writer process\n", mypid);
- if (write_uc_file() < 0){
+ if (write_uc_file(send_wait) < 0){
fprintf(stderr, "write_uc_file encountered error\n");
Hgoto_error(1);
}
diff --git a/test/use_common.c b/test/use_common.c
index c25f1f4..639e468 100644
--- a/test/use_common.c
+++ b/test/use_common.c
@@ -241,7 +241,7 @@ int create_uc_file(void)
*
* Return: 0 succeed; -1 fail.
*/
-int write_uc_file(void)
+int write_uc_file(hbool_t tosend)
{
hid_t fid; /* File ID for new HDF5 file */
hid_t dsid; /* dataset ID */
@@ -272,6 +272,10 @@ int write_uc_file(void)
return -1;
}
+ if(tosend)
+ /* Send a message that H5Fopen is complete--releasing the file lock */
+ h5_send_message(WRITER_MESSAGE);
+
/* Open the dataset of the program name */
if((dsid = H5Dopen2(fid, progname_g, H5P_DEFAULT)) < 0){
fprintf(stderr, "H5Dopen2 failed\n");
@@ -424,7 +428,7 @@ int write_uc_file(void)
*
* Return: 0 succeed; -1 fail.
*/
-int read_uc_file(void)
+int read_uc_file(hbool_t towait)
{
hid_t fid; /* File ID for new HDF5 file */
hid_t dsid; /* dataset ID */
@@ -442,6 +446,12 @@ int read_uc_file(void)
int nerrs;
int nonewplane;
+ /* Before reading, wait for the message that H5Fopen is complete--file lock is released */
+ if(towait && h5_wait_message(WRITER_MESSAGE) < 0) {
+ fprintf(stderr, "Cannot find writer message file...failed\n");
+ return -1;
+ }
+
name = UC_opts.filename;
/* Open the file */