diff options
author | Vailin Choi <vchoi@hdfgroup.org> | 2014-01-08 17:09:23 (GMT) |
---|---|---|
committer | Vailin Choi <vchoi@hdfgroup.org> | 2014-01-08 17:09:23 (GMT) |
commit | a196a4f351abed0670c10bc50887bd4e56dd4775 (patch) | |
tree | cc56e2d57884eae938e6606624d0c619d6dfe541 /test | |
parent | 955c0736022947649441634f7ee3dc5c973085d4 (diff) | |
download | hdf5-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.am | 47 | ||||
-rw-r--r-- | test/Makefile.in | 90 | ||||
-rw-r--r-- | test/accum.c | 13 | ||||
-rw-r--r-- | test/accum_swmr_reader.c | 2 | ||||
-rw-r--r-- | test/bad_compound.h5 | bin | 2208 -> 2208 bytes | |||
-rw-r--r-- | test/btree_idx_1_6.h5 | bin | 6350 -> 6350 bytes | |||
-rw-r--r-- | test/corrupt_stab_msg.h5 | bin | 2928 -> 2928 bytes | |||
-rw-r--r-- | test/deflate.h5 | bin | 6240 -> 6240 bytes | |||
-rw-r--r-- | test/family_v16_00000.h5 | bin | 5120 -> 5120 bytes | |||
-rw-r--r-- | test/file_image.c | 96 | ||||
-rw-r--r-- | test/filespace_1_6.h5 | bin | 2448 -> 2448 bytes | |||
-rw-r--r-- | test/fill_old.h5 | bin | 2560 -> 2560 bytes | |||
-rw-r--r-- | test/flush2.c | 68 | ||||
-rw-r--r-- | test/group_old.h5 | bin | 1952 -> 1952 bytes | |||
-rw-r--r-- | test/h5test.c | 53 | ||||
-rw-r--r-- | test/h5test.h | 6 | ||||
-rw-r--r-- | test/mergemsg.h5 | bin | 3472 -> 3472 bytes | |||
-rw-r--r-- | test/multi_file_v16-s.h5 | bin | 2048 -> 2048 bytes | |||
-rw-r--r-- | test/swmr_addrem_writer.c | 3 | ||||
-rw-r--r-- | test/swmr_common.c | 2 | ||||
-rw-r--r-- | test/swmr_common.h | 4 | ||||
-rw-r--r-- | test/swmr_remove_writer.c | 3 | ||||
-rw-r--r-- | test/swmr_sparse_writer.c | 5 | ||||
-rw-r--r-- | test/swmr_start_write.c | 691 | ||||
-rw-r--r-- | test/swmr_writer.c | 3 | ||||
-rw-r--r-- | test/tarrold.h5 | bin | 6032 -> 6032 bytes | |||
-rw-r--r-- | test/test_filters_be.h5 | bin | 5720 -> 5720 bytes | |||
-rw-r--r-- | test/test_filters_le.h5 | bin | 5720 -> 5720 bytes | |||
-rw-r--r-- | test/test_swmr.c | 2104 | ||||
-rwxr-xr-x | test/testswmr.sh | 139 | ||||
-rw-r--r-- | test/tfile.c | 1683 | ||||
-rw-r--r-- | test/th5s.h5 | bin | 2049 -> 2049 bytes | |||
-rw-r--r-- | test/tlayouto.h5 | bin | 1576 -> 1576 bytes | |||
-rw-r--r-- | test/tmtimen.h5 | bin | 1576 -> 1576 bytes | |||
-rw-r--r-- | test/tmtimeo.h5 | bin | 2052 -> 2052 bytes | |||
-rw-r--r-- | test/use.h | 27 | ||||
-rw-r--r-- | test/use_append_chunk.c | 11 | ||||
-rw-r--r-- | test/use_append_mchunks.c | 11 | ||||
-rw-r--r-- | test/use_common.c | 14 |
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 Binary files differindex 1834a2e..1c96318 100644 --- a/test/bad_compound.h5 +++ b/test/bad_compound.h5 diff --git a/test/btree_idx_1_6.h5 b/test/btree_idx_1_6.h5 Binary files differindex b1ac4da..92f939b 100644 --- a/test/btree_idx_1_6.h5 +++ b/test/btree_idx_1_6.h5 diff --git a/test/corrupt_stab_msg.h5 b/test/corrupt_stab_msg.h5 Binary files differindex 4fa287c..a00616d 100644 --- a/test/corrupt_stab_msg.h5 +++ b/test/corrupt_stab_msg.h5 diff --git a/test/deflate.h5 b/test/deflate.h5 Binary files differindex 2f62e25..e33af4f 100644 --- a/test/deflate.h5 +++ b/test/deflate.h5 diff --git a/test/family_v16_00000.h5 b/test/family_v16_00000.h5 Binary files differindex ac75ea9..aaa3dad 100644 --- a/test/family_v16_00000.h5 +++ b/test/family_v16_00000.h5 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 Binary files differindex 5afc718..c8aa9df 100644 --- a/test/filespace_1_6.h5 +++ b/test/filespace_1_6.h5 diff --git a/test/fill_old.h5 b/test/fill_old.h5 Binary files differindex e77f519..4dd7740 100644 --- a/test/fill_old.h5 +++ b/test/fill_old.h5 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 Binary files differindex 58f66f8..2440103 100644 --- a/test/group_old.h5 +++ b/test/group_old.h5 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 Binary files differindex 3a9e352..55c3135 100644 --- a/test/mergemsg.h5 +++ b/test/mergemsg.h5 diff --git a/test/multi_file_v16-s.h5 b/test/multi_file_v16-s.h5 Binary files differindex e990e95..2d4de48 100644 --- a/test/multi_file_v16-s.h5 +++ b/test/multi_file_v16-s.h5 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 Binary files differindex 7747ce4..048838c 100644 --- a/test/tarrold.h5 +++ b/test/tarrold.h5 diff --git a/test/test_filters_be.h5 b/test/test_filters_be.h5 Binary files differindex c4c127b..aadb372 100644 --- a/test/test_filters_be.h5 +++ b/test/test_filters_be.h5 diff --git a/test/test_filters_le.h5 b/test/test_filters_le.h5 Binary files differindex ff8b846..c29fa0a 100644 --- a/test/test_filters_le.h5 +++ b/test/test_filters_le.h5 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 Binary files differindex 7a0bfb3..bc2b666 100644 --- a/test/th5s.h5 +++ b/test/th5s.h5 diff --git a/test/tlayouto.h5 b/test/tlayouto.h5 Binary files differindex a038e68..3322020 100644 --- a/test/tlayouto.h5 +++ b/test/tlayouto.h5 diff --git a/test/tmtimen.h5 b/test/tmtimen.h5 Binary files differindex 96e5fb3..007a6b6 100644 --- a/test/tmtimen.h5 +++ b/test/tmtimen.h5 diff --git a/test/tmtimeo.h5 b/test/tmtimeo.h5 Binary files differindex 8cacf4a..c9dfcc4 100644 --- a/test/tmtimeo.h5 +++ b/test/tmtimeo.h5 @@ -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 */ |