summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVailin Choi <vchoi@hdfgroup.org>2014-01-08 17:09:23 (GMT)
committerVailin Choi <vchoi@hdfgroup.org>2014-01-08 17:09:23 (GMT)
commita196a4f351abed0670c10bc50887bd4e56dd4775 (patch)
treecc56e2d57884eae938e6606624d0c619d6dfe541
parent955c0736022947649441634f7ee3dc5c973085d4 (diff)
downloadhdf5-a196a4f351abed0670c10bc50887bd4e56dd4775.zip
hdf5-a196a4f351abed0670c10bc50887bd4e56dd4775.tar.gz
hdf5-a196a4f351abed0670c10bc50887bd4e56dd4775.tar.bz2
[svn-r24622] Implementation (pending code review) for:
(A) SWMR related public routines: H5Fstart_swmr_write, H5Pget/set_append_flush, H5Pget/set_object_flush_cb. (B) File locking. Tested on jam, koala, ostrich, platypus.
-rwxr-xr-xconfigure5
-rw-r--r--configure.ac3
-rw-r--r--hl/src/H5DO.c205
-rw-r--r--hl/src/H5DOpublic.h7
-rw-r--r--hl/src/H5HLprivate2.h91
-rw-r--r--hl/src/H5LD.c2
-rw-r--r--hl/test/Makefile.am8
-rw-r--r--hl/test/Makefile.in65
-rw-r--r--hl/test/gen_test_ld.c14
-rw-r--r--hl/test/ld_extend.c151
-rw-r--r--hl/test/ld_monitor.c148
-rw-r--r--hl/test/ld_mx.c353
-rw-r--r--hl/test/test_dset_append.c1191
-rw-r--r--hl/test/test_file_image.c38
-rw-r--r--hl/test/test_ld.h5bin28336 -> 42955 bytes
-rw-r--r--hl/test/test_ld.sh.in46
-rw-r--r--hl/test/test_table_be.h5bin55912 -> 55912 bytes
-rw-r--r--hl/test/test_table_cray.h5bin55912 -> 55912 bytes
-rw-r--r--hl/test/test_table_le.h5bin53880 -> 53880 bytes
-rw-r--r--hl/tools/h5watch/h5watch.c2
-rw-r--r--hl/tools/h5watch/testh5watch.sh.in2
-rw-r--r--src/H5AC.c33
-rw-r--r--src/H5ACprivate.h2
-rw-r--r--src/H5C.c39
-rw-r--r--src/H5Cprivate.h4
-rw-r--r--src/H5D.c14
-rw-r--r--src/H5Dint.c97
-rw-r--r--src/H5Doh.c25
-rw-r--r--src/H5Dpkg.h1
-rw-r--r--src/H5Dprivate.h9
-rw-r--r--src/H5Dpublic.h3
-rw-r--r--src/H5F.c382
-rw-r--r--src/H5FD.c58
-rw-r--r--src/H5FDcore.c79
-rw-r--r--src/H5FDdirect.c78
-rw-r--r--src/H5FDprivate.h2
-rw-r--r--src/H5FDpublic.h4
-rw-r--r--src/H5FDsec2.c72
-rw-r--r--src/H5Fio.c49
-rw-r--r--src/H5Fpkg.h21
-rw-r--r--src/H5Fprivate.h13
-rw-r--r--src/H5Fpublic.h5
-rw-r--r--src/H5Fsuper.c2
-rw-r--r--src/H5G.c5
-rw-r--r--src/H5Ocopy.c29
-rw-r--r--src/H5Oflush.c54
-rw-r--r--src/H5Opkg.h2
-rw-r--r--src/H5Oprivate.h2
-rw-r--r--src/H5Pdapl.c130
-rw-r--r--src/H5Pfapl.c111
-rw-r--r--src/H5Ppublic.h7
-rw-r--r--src/H5T.c6
-rw-r--r--src/H5config.h.in3
-rw-r--r--src/H5private.h10
-rw-r--r--test/Makefile.am47
-rw-r--r--test/Makefile.in90
-rw-r--r--test/accum.c13
-rw-r--r--test/accum_swmr_reader.c2
-rw-r--r--test/bad_compound.h5bin2208 -> 2208 bytes
-rw-r--r--test/btree_idx_1_6.h5bin6350 -> 6350 bytes
-rw-r--r--test/corrupt_stab_msg.h5bin2928 -> 2928 bytes
-rw-r--r--test/deflate.h5bin6240 -> 6240 bytes
-rw-r--r--test/family_v16_00000.h5bin5120 -> 5120 bytes
-rw-r--r--test/file_image.c96
-rw-r--r--test/filespace_1_6.h5bin2448 -> 2448 bytes
-rw-r--r--test/fill_old.h5bin2560 -> 2560 bytes
-rw-r--r--test/flush2.c68
-rw-r--r--test/group_old.h5bin1952 -> 1952 bytes
-rw-r--r--test/h5test.c53
-rw-r--r--test/h5test.h6
-rw-r--r--test/mergemsg.h5bin3472 -> 3472 bytes
-rw-r--r--test/multi_file_v16-s.h5bin2048 -> 2048 bytes
-rw-r--r--test/swmr_addrem_writer.c3
-rw-r--r--test/swmr_common.c2
-rw-r--r--test/swmr_common.h4
-rw-r--r--test/swmr_remove_writer.c3
-rw-r--r--test/swmr_sparse_writer.c5
-rw-r--r--test/swmr_start_write.c691
-rw-r--r--test/swmr_writer.c3
-rw-r--r--test/tarrold.h5bin6032 -> 6032 bytes
-rw-r--r--test/test_filters_be.h5bin5720 -> 5720 bytes
-rw-r--r--test/test_filters_le.h5bin5720 -> 5720 bytes
-rw-r--r--test/test_swmr.c2104
-rwxr-xr-xtest/testswmr.sh139
-rw-r--r--test/tfile.c1683
-rw-r--r--test/th5s.h5bin2049 -> 2049 bytes
-rw-r--r--test/tlayouto.h5bin1576 -> 1576 bytes
-rw-r--r--test/tmtimen.h5bin1576 -> 1576 bytes
-rw-r--r--test/tmtimeo.h5bin2052 -> 2052 bytes
-rw-r--r--test/use.h27
-rw-r--r--test/use_append_chunk.c11
-rw-r--r--test/use_append_mchunks.c11
-rw-r--r--test/use_common.c14
-rw-r--r--tools/h5diff/testfiles/h5diff_hyper1.h5bin1052720 -> 1052720 bytes
-rw-r--r--tools/h5diff/testfiles/h5diff_hyper2.h5bin1052720 -> 1052720 bytes
-rw-r--r--tools/h5import/testfiles/binfp64.h5bin10760 -> 10760 bytes
-rw-r--r--tools/h5import/testfiles/binin16.h5bin10760 -> 10760 bytes
-rw-r--r--tools/h5import/testfiles/binin32.h5bin9472 -> 9472 bytes
-rw-r--r--tools/h5import/testfiles/binin8.h5bin10760 -> 10760 bytes
-rw-r--r--tools/h5import/testfiles/binuin16.h5bin10760 -> 10760 bytes
-rw-r--r--tools/h5import/testfiles/binuin32.h5bin6384 -> 6384 bytes
-rw-r--r--tools/h5import/testfiles/txtfp32.h5bin4192 -> 4192 bytes
-rw-r--r--tools/h5import/testfiles/txtfp64.h5bin9784 -> 9784 bytes
-rw-r--r--tools/h5import/testfiles/txtin16.h5bin9784 -> 9784 bytes
-rw-r--r--tools/h5import/testfiles/txtin32.h5bin4192 -> 4192 bytes
-rw-r--r--tools/h5import/testfiles/txtin8.h5bin9784 -> 9784 bytes
-rw-r--r--tools/h5import/testfiles/txtuin16.h5bin10240 -> 10240 bytes
-rw-r--r--tools/h5import/testfiles/txtuin32.h5bin6240 -> 6240 bytes
-rw-r--r--tools/h5repack/testfiles/h5repack_attr.h5bin20056 -> 20056 bytes
-rw-r--r--tools/h5repack/testfiles/h5repack_deflate.h5bin5962 -> 5962 bytes
-rw-r--r--tools/h5repack/testfiles/h5repack_early.h5bin2067224 -> 2067224 bytes
-rw-r--r--tools/h5repack/testfiles/h5repack_fill.h5bin2072 -> 2072 bytes
-rw-r--r--tools/h5repack/testfiles/h5repack_filters.h5bin29744 -> 29744 bytes
-rw-r--r--tools/h5repack/testfiles/h5repack_fletcher.h5bin7880 -> 7880 bytes
-rw-r--r--tools/h5repack/testfiles/h5repack_hlink.h5bin6576 -> 6576 bytes
-rw-r--r--tools/h5repack/testfiles/h5repack_layouto.h5bin1576 -> 1576 bytes
-rw-r--r--tools/h5repack/testfiles/h5repack_nbit.h5bin13776 -> 13776 bytes
-rw-r--r--tools/h5repack/testfiles/h5repack_shuffle.h5bin7864 -> 7864 bytes
-rw-r--r--tools/h5repack/testfiles/h5repack_soffset.h5bin11052 -> 11052 bytes
-rw-r--r--tools/h5stat/testfiles/h5stat_filters.h5bin46272 -> 46272 bytes
-rw-r--r--tools/misc/Makefile.am15
-rw-r--r--tools/misc/Makefile.in72
-rw-r--r--tools/misc/clear_open_chk.c72
-rw-r--r--tools/misc/h5clear.c137
-rw-r--r--tools/misc/h5clear_gentest.c238
-rw-r--r--tools/misc/testh5clear.sh.in135
-rw-r--r--tools/testfiles/family_file00000.h5bin1024 -> 1024 bytes
-rw-r--r--tools/testfiles/taindices.h5bin17160 -> 17160 bytes
-rw-r--r--tools/testfiles/tarray1.h5bin2112 -> 2112 bytes
-rw-r--r--tools/testfiles/tarray2.h5bin3008 -> 3008 bytes
-rw-r--r--tools/testfiles/tarray3.h5bin3200 -> 3200 bytes
-rw-r--r--tools/testfiles/tarray4.h5bin2176 -> 2176 bytes
-rw-r--r--tools/testfiles/tarray5.h5bin2368 -> 2368 bytes
-rw-r--r--tools/testfiles/tarray6.h5bin6400 -> 6400 bytes
-rw-r--r--tools/testfiles/tarray7.h5bin6400 -> 6400 bytes
-rw-r--r--tools/testfiles/tattr.h5bin3024 -> 3024 bytes
-rw-r--r--tools/testfiles/tattr2.h5bin33840 -> 33840 bytes
-rw-r--r--tools/testfiles/tbigdims.h5bin6192 -> 6192 bytes
-rw-r--r--tools/testfiles/tbitfields.h5bin2704 -> 2704 bytes
-rw-r--r--tools/testfiles/tchar.h5bin2356 -> 2356 bytes
-rw-r--r--tools/testfiles/tcompound.h5bin8192 -> 8192 bytes
-rw-r--r--tools/testfiles/tcompound2.h5bin13640 -> 13640 bytes
-rw-r--r--tools/testfiles/tcompound_complex.h5bin8192 -> 8192 bytes
-rw-r--r--tools/testfiles/tdatareg.h5bin5652 -> 5652 bytes
-rw-r--r--tools/testfiles/tdset.h5bin7648 -> 7648 bytes
-rw-r--r--tools/testfiles/tdset2.h5bin9936 -> 9936 bytes
-rw-r--r--tools/testfiles/tempty.h5bin4304 -> 4304 bytes
-rw-r--r--tools/testfiles/tenum.h5bin2128 -> 2128 bytes
-rw-r--r--tools/testfiles/tfamily00000.h5bin256 -> 256 bytes
-rw-r--r--tools/testfiles/tfcontents2.h5bin792 -> 792 bytes
-rw-r--r--tools/testfiles/tfvalues.h5bin9552 -> 9552 bytes
-rw-r--r--tools/testfiles/tgroup.h5bin11096 -> 11096 bytes
-rw-r--r--tools/testfiles/thlink.h5bin5536 -> 5536 bytes
-rw-r--r--tools/testfiles/thyperslab.h5bin1050880 -> 1050880 bytes
-rw-r--r--tools/testfiles/tlarge_objname.h5bin40008 -> 40008 bytes
-rw-r--r--tools/testfiles/tlonglinks.h5bin203168 -> 203168 bytes
-rw-r--r--tools/testfiles/tloop.h5bin3168 -> 3168 bytes
-rw-r--r--tools/testfiles/tloop2.h5bin3168 -> 3168 bytes
-rw-r--r--tools/testfiles/tmulti-s.h5bin2048 -> 2048 bytes
-rw-r--r--tools/testfiles/tname-amp.h5bin2880 -> 2880 bytes
-rw-r--r--tools/testfiles/tname-apos.h5bin2880 -> 2880 bytes
-rw-r--r--tools/testfiles/tname-gt.h5bin2880 -> 2880 bytes
-rw-r--r--tools/testfiles/tname-lt.h5bin2880 -> 2880 bytes
-rw-r--r--tools/testfiles/tname-quot.h5bin2880 -> 2880 bytes
-rw-r--r--tools/testfiles/tname-sp.h5bin2880 -> 2880 bytes
-rw-r--r--tools/testfiles/tnestedcomp.h5bin2072 -> 2072 bytes
-rw-r--r--tools/testfiles/tnodata.h5bin1412 -> 1412 bytes
-rw-r--r--tools/testfiles/tnullspace.h5bin3624 -> 3624 bytes
-rw-r--r--tools/testfiles/tobjref.h5bin2900 -> 2900 bytes
-rw-r--r--tools/testfiles/topaque.h5bin1744 -> 1744 bytes
-rw-r--r--tools/testfiles/tref-escapes-at.h5bin5849 -> 5849 bytes
-rw-r--r--tools/testfiles/tref-escapes.h5bin5536 -> 5536 bytes
-rw-r--r--tools/testfiles/tref.h5bin3004 -> 3004 bytes
-rw-r--r--tools/testfiles/tsaf.h5bin769444 -> 769444 bytes
-rw-r--r--tools/testfiles/tslink.h5bin1168 -> 1168 bytes
-rw-r--r--tools/testfiles/tsplit_file-m.h5bin2048 -> 2048 bytes
-rw-r--r--tools/testfiles/tstr.h5bin15608 -> 15608 bytes
-rw-r--r--tools/testfiles/tstr2.h5bin11096 -> 11096 bytes
-rw-r--r--tools/testfiles/tstr3.h5bin8736 -> 8736 bytes
-rw-r--r--tools/testfiles/tstring-at.h5bin1672 -> 1672 bytes
-rw-r--r--tools/testfiles/tstring.h5bin2160 -> 2160 bytes
-rw-r--r--tools/testfiles/tvldtypes1.h5bin8336 -> 8336 bytes
-rw-r--r--tools/testfiles/tvldtypes2.h5bin6208 -> 6208 bytes
-rw-r--r--tools/testfiles/tvldtypes3.h5bin6240 -> 6240 bytes
-rw-r--r--tools/testfiles/tvldtypes4.h5bin8192 -> 8192 bytes
-rw-r--r--tools/testfiles/tvldtypes5.h5bin8192 -> 8192 bytes
-rw-r--r--tools/testfiles/tvms.h5bin2288 -> 2288 bytes
187 files changed, 8481 insertions, 945 deletions
diff --git a/configure b/configure
index 05e5f54..9bf1372 100755
--- a/configure
+++ b/configure
@@ -22784,7 +22784,7 @@ fi
done
-for ac_header in sys/socket.h sys/types.h
+for ac_header in sys/socket.h sys/types.h sys/file.h
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
@@ -33212,7 +33212,7 @@ else
fi
-ac_config_files="$ac_config_files src/libhdf5.settings Makefile src/Makefile test/Makefile test/testcheck_version.sh test/testerror.sh test/testflushrefresh.sh test/H5srcdir_str.h test/testlibinfo.sh test/testlinks_env.sh test/test_plugin.sh test/test_usecases.sh testpar/Makefile testpar/testph5.sh perform/Makefile tools/Makefile tools/h5dump/Makefile tools/h5dump/testh5dump.sh tools/h5dump/testh5dumppbits.sh tools/h5dump/testh5dumpxml.sh tools/h5ls/testh5ls.sh tools/h5import/Makefile tools/h5import/h5importtestutil.sh tools/h5diff/Makefile tools/h5diff/testh5diff.sh tools/h5diff/testph5diff.sh tools/h5jam/Makefile tools/h5jam/testh5jam.sh tools/h5repack/Makefile tools/h5repack/h5repack.sh tools/h5repack/h5repack_plugin.sh tools/h5ls/Makefile tools/h5copy/Makefile tools/h5copy/testh5copy.sh tools/lib/Makefile tools/misc/Makefile tools/misc/h5cc tools/misc/testh5mkgrp.sh tools/misc/testh5repart.sh tools/h5stat/testh5stat.sh tools/h5stat/Makefile examples/Makefile examples/run-c-ex.sh examples/testh5cc.sh c++/Makefile c++/src/Makefile c++/src/h5c++ c++/test/Makefile c++/test/H5srcdir_str.h c++/examples/Makefile c++/examples/run-c++-ex.sh c++/examples/testh5c++.sh fortran/Makefile fortran/src/h5fc fortran/src/Makefile fortran/test/Makefile fortran/testpar/Makefile fortran/examples/Makefile fortran/examples/run-fortran-ex.sh fortran/examples/testh5fc.sh hl/Makefile hl/src/Makefile hl/test/Makefile hl/test/H5srcdir_str.h hl/test/test_ld.sh hl/tools/Makefile hl/tools/gif2h5/Makefile hl/tools/gif2h5/h52giftest.sh hl/tools/h5watch/Makefile hl/tools/h5watch/testh5watch.sh hl/examples/Makefile hl/examples/run-hlc-ex.sh hl/c++/Makefile hl/c++/src/Makefile hl/c++/test/Makefile hl/c++/examples/Makefile hl/c++/examples/run-hlc++-ex.sh hl/fortran/Makefile hl/fortran/src/Makefile hl/fortran/test/Makefile hl/fortran/examples/Makefile hl/fortran/examples/run-hlfortran-ex.sh"
+ac_config_files="$ac_config_files src/libhdf5.settings Makefile src/Makefile test/Makefile test/testcheck_version.sh test/testerror.sh test/testflushrefresh.sh test/H5srcdir_str.h test/testlibinfo.sh test/testlinks_env.sh test/test_plugin.sh test/test_usecases.sh testpar/Makefile testpar/testph5.sh perform/Makefile tools/Makefile tools/h5dump/Makefile tools/h5dump/testh5dump.sh tools/h5dump/testh5dumppbits.sh tools/h5dump/testh5dumpxml.sh tools/h5ls/testh5ls.sh tools/h5import/Makefile tools/h5import/h5importtestutil.sh tools/h5diff/Makefile tools/h5diff/testh5diff.sh tools/h5diff/testph5diff.sh tools/h5jam/Makefile tools/h5jam/testh5jam.sh tools/h5repack/Makefile tools/h5repack/h5repack.sh tools/h5repack/h5repack_plugin.sh tools/h5ls/Makefile tools/h5copy/Makefile tools/h5copy/testh5copy.sh tools/lib/Makefile tools/misc/Makefile tools/misc/h5cc tools/misc/testh5clear.sh tools/misc/testh5mkgrp.sh tools/misc/testh5repart.sh tools/h5stat/testh5stat.sh tools/h5stat/Makefile examples/Makefile examples/run-c-ex.sh examples/testh5cc.sh c++/Makefile c++/src/Makefile c++/src/h5c++ c++/test/Makefile c++/test/H5srcdir_str.h c++/examples/Makefile c++/examples/run-c++-ex.sh c++/examples/testh5c++.sh fortran/Makefile fortran/src/h5fc fortran/src/Makefile fortran/test/Makefile fortran/testpar/Makefile fortran/examples/Makefile fortran/examples/run-fortran-ex.sh fortran/examples/testh5fc.sh hl/Makefile hl/src/Makefile hl/test/Makefile hl/test/H5srcdir_str.h hl/test/test_ld.sh hl/tools/Makefile hl/tools/gif2h5/Makefile hl/tools/gif2h5/h52giftest.sh hl/tools/h5watch/Makefile hl/tools/h5watch/testh5watch.sh hl/examples/Makefile hl/examples/run-hlc-ex.sh hl/c++/Makefile hl/c++/src/Makefile hl/c++/test/Makefile hl/c++/examples/Makefile hl/c++/examples/run-hlc++-ex.sh hl/fortran/Makefile hl/fortran/src/Makefile hl/fortran/test/Makefile hl/fortran/examples/Makefile hl/fortran/examples/run-hlfortran-ex.sh"
cat >confcache <<\_ACEOF
@@ -34514,6 +34514,7 @@ do
"tools/lib/Makefile") CONFIG_FILES="$CONFIG_FILES tools/lib/Makefile" ;;
"tools/misc/Makefile") CONFIG_FILES="$CONFIG_FILES tools/misc/Makefile" ;;
"tools/misc/h5cc") CONFIG_FILES="$CONFIG_FILES tools/misc/h5cc" ;;
+ "tools/misc/testh5clear.sh") CONFIG_FILES="$CONFIG_FILES tools/misc/testh5clear.sh" ;;
"tools/misc/testh5mkgrp.sh") CONFIG_FILES="$CONFIG_FILES tools/misc/testh5mkgrp.sh" ;;
"tools/misc/testh5repart.sh") CONFIG_FILES="$CONFIG_FILES tools/misc/testh5repart.sh" ;;
"tools/h5stat/testh5stat.sh") CONFIG_FILES="$CONFIG_FILES tools/h5stat/testh5stat.sh" ;;
diff --git a/configure.ac b/configure.ac
index 63eea9a..210c2da 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1277,7 +1277,7 @@ AC_CHECK_FUNCS([clock_gettime],[have_clock_gettime="yes"],[have_clock_gettime="n
## Unix
AC_CHECK_HEADERS([sys/resource.h sys/time.h unistd.h sys/ioctl.h sys/stat.h])
-AC_CHECK_HEADERS([sys/socket.h sys/types.h])
+AC_CHECK_HEADERS([sys/socket.h sys/types.h sys/file.h])
AC_CHECK_HEADERS([stddef.h setjmp.h features.h])
AC_CHECK_HEADERS([dirent.h])
AC_CHECK_HEADERS([stdint.h], [C9x=yes])
@@ -4556,6 +4556,7 @@ AC_CONFIG_FILES([src/libhdf5.settings
tools/lib/Makefile
tools/misc/Makefile
tools/misc/h5cc
+ tools/misc/testh5clear.sh
tools/misc/testh5mkgrp.sh
tools/misc/testh5repart.sh
tools/h5stat/testh5stat.sh
diff --git a/hl/src/H5DO.c b/hl/src/H5DO.c
index 9cfd8c1..e93608e 100644
--- a/hl/src/H5DO.c
+++ b/hl/src/H5DO.c
@@ -135,3 +135,208 @@ done:
return ret_value;
}
+
+
+/*
+ * Function: H5DOappend()
+ *
+ * Purpose: To append elements to a dataset.
+ * axis: the dataset dimension (zero-based) for the append
+ * extension: the # of elements to append for the axis-th dimension
+ * memtype: the datatype
+ * buf: buffer with data for the append
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Vailin Choi; Jan 2014
+ *
+ * Note:
+ * This routine is copied from the fast forward feature branch: features/hdf5_ff
+ * src/H5FF.c:H5DOappend() with the following modifications:
+ * 1) Remove and replace macro calls such as
+ * FUNC_ENTER_API, H5TRACE, HGOTO_ERROR
+ * accordingly because hl does not have these macros
+ * 2) Replace H5I_get_type() by H5Iget_type()
+ * 3) Replace H5P_isa_class() by H5Pisa_class()
+ * 4) Fix a bug in the following: replace extension by size[axis]
+ * if(extension < old_size) {
+ * ret_value = FAIL;
+ * goto done;
+ * }
+ */
+herr_t
+H5DOappend(hid_t dset_id, hid_t dxpl_id, unsigned axis, size_t extension,
+ hid_t memtype, const void *buf)
+{
+
+ hsize_t size[H5S_MAX_RANK]; /* The new size (after extension */
+ hsize_t old_size=0; /* The size of the dimension to be extended */
+ int ndims, i; /* Number of dimensions in dataspace */
+ hid_t space_id = FAIL; /* Old file space */
+ hid_t new_space_id = FAIL; /* New file space (after extension) */
+ hid_t mem_space_id = FAIL; /* Memory space for data buffer */
+ hsize_t nelmts; /* Number of elements in selection */
+ hid_t dapl = FAIL; /* Dataset access property list */
+
+ hsize_t start[H5S_MAX_RANK]; /* H5Sselect_Hyperslab: starting offset */
+ hsize_t count[H5S_MAX_RANK]; /* H5Sselect_hyperslab: # of blocks to select */
+ hsize_t stride[H5S_MAX_RANK]; /* H5Sselect_hyperslab: # of elements to move when selecting */
+ hsize_t block[H5S_MAX_RANK]; /* H5Sselect_hyperslab: # of elements in a block */
+
+ hsize_t *boundary = NULL; /* Boundary set in append flush property */
+ H5D_append_cb_t append_cb; /* Callback function set in append flush property */
+ void *udata; /* User data set in append flush property */
+ hbool_t hit = FALSE; /* Boundary is hit or not */
+ hsize_t k; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ /* check arguments */
+ if(H5I_DATASET != H5Iget_type(dset_id)) {
+ ret_value = FAIL;
+ goto done;
+ }
+
+ /* Get the default dataset transfer property list if the user didn't provide one */
+ if(H5P_DEFAULT == dxpl_id)
+ dxpl_id = H5P_DATASET_XFER_DEFAULT;
+ else
+ if(TRUE != H5Pisa_class(dxpl_id, H5P_DATASET_XFER)) {
+ ret_value = FAIL;
+ goto done;
+ }
+
+ /* Get the dataspace of the dataset */
+ if(FAIL == (space_id = H5Dget_space(dset_id))) {
+ ret_value = FAIL;
+ goto done;
+ }
+
+ /* Get the rank of this dataspace */
+ if((ndims = H5Sget_simple_extent_ndims(space_id)) < 0) {
+ ret_value = FAIL;
+ goto done;
+ }
+
+ /* Verify correct axis */
+ if((int)axis >= ndims) {
+ ret_value = FAIL;
+ goto done;
+ }
+
+ /* Get the dimensions sizes of the dataspace */
+ if(H5Sget_simple_extent_dims(space_id, size, NULL) < 0) {
+ ret_value = FAIL;
+ goto done;
+ }
+
+ /* Adjust the dimension size of the requested dimension,
+ but first record the old dimension size */
+ old_size = size[axis];
+ size[axis] += extension;
+ if(size[axis] < old_size) {
+ ret_value = FAIL;
+ goto done;
+ }
+
+ /* Set the extent of the dataset to the new dimension */
+ if(H5Dset_extent(dset_id, size) < 0) {
+ ret_value = FAIL;
+ goto done;
+ }
+
+ /* Get the new dataspace of the dataset */
+ if(FAIL == (new_space_id = H5Dget_space(dset_id))) {
+ ret_value = FAIL;
+ goto done;
+ }
+
+ /* Select a hyperslab corresponding to the append operation */
+ for(i=0 ; i<ndims ; i++) {
+ start[i] = 0;
+ stride[i] = 1;
+ count[i] = size[i];
+ block[i] = 1;
+ if(i == (int)axis) {
+ count[i] = extension;
+ start[i] = old_size;
+ }
+ }
+ if(FAIL == H5Sselect_hyperslab(new_space_id, H5S_SELECT_SET, start, stride, count, block)) {
+ ret_value = FAIL;
+ goto done;
+ }
+
+ /* The # of elemnts in the new extended dataspace */
+ nelmts = H5Sget_select_npoints(new_space_id);
+
+ /* create a memory space */
+ mem_space_id = H5Screate_simple(1, &nelmts, NULL);
+
+ /* Write the data */
+ if(H5Dwrite(dset_id, memtype, mem_space_id, new_space_id, dxpl_id, buf) < 0) {
+ ret_value = FAIL;
+ goto done;
+ }
+
+ /* Obtain the dataset's access property list */
+ if((dapl = H5Dget_access_plist(dset_id)) < 0) {
+ ret_value = FAIL;
+ goto done;
+ }
+
+ /* Allocate the boundary array */
+ boundary = (hsize_t *)HDmalloc(ndims * sizeof(hsize_t));
+
+ /* Retrieve the append flush property */
+ if(H5Pget_append_flush(dapl, ndims, boundary, &append_cb, &udata) < 0) {
+ ret_value = FAIL;
+ goto done;
+ }
+
+ /* No boundary for this axis */
+ if(boundary[axis] == 0)
+ goto done;
+
+ /* Determine whether a boundary is hit or not */
+ for(k = start[axis]; k < size[axis]; k++)
+ if(!((k + 1) % boundary[axis])) {
+ hit = TRUE;
+ break;
+ }
+
+ if(hit) { /* Hit the boundary */
+ /* Invoke callback if there is one */
+ if(append_cb && append_cb(dset_id, size, udata) < 0) {
+ ret_value = FAIL;
+ goto done;
+ }
+ /* Does a dataset flush */
+ if(H5Dflush(dset_id) < 0) {
+ ret_value = FAIL;
+ goto done;
+ }
+ }
+
+done:
+ /* Close old dataspace */
+ if(space_id != FAIL && H5Sclose(space_id) < 0)
+ ret_value = FAIL;
+
+ /* Close new dataspace */
+ if(new_space_id != FAIL && H5Sclose(new_space_id) < 0)
+ ret_value = FAIL;
+
+ /* Close memory dataspace */
+ if(mem_space_id != FAIL && H5Sclose(mem_space_id) < 0)
+ ret_value = FAIL;
+
+ /* Close the dataset access property list */
+ if(dapl != FAIL && H5Pclose(dapl) < 0)
+ ret_value = FAIL;
+
+ if(boundary)
+ HDfree(boundary);
+
+ return ret_value;
+} /* H5DOappend() */
+
diff --git a/hl/src/H5DOpublic.h b/hl/src/H5DOpublic.h
index 774709e..34facc6 100644
--- a/hl/src/H5DOpublic.h
+++ b/hl/src/H5DOpublic.h
@@ -22,7 +22,7 @@ extern "C" {
/*-------------------------------------------------------------------------
*
- * Direct chunk write function
+ * Direct chunk write function, Dataset append operation
*
*-------------------------------------------------------------------------
*/
@@ -34,6 +34,11 @@ H5_HLDLL herr_t H5DOwrite_chunk(hid_t dset_id,
size_t data_size,
const void *buf);
+herr_t
+H5DOappend(hid_t dset_id, hid_t dxpl_id, unsigned axis, size_t extension,
+ hid_t memtype, const void *buf);
+
+
#ifdef __cplusplus
}
#endif
diff --git a/hl/src/H5HLprivate2.h b/hl/src/H5HLprivate2.h
index b7a9362..1b67c70 100644
--- a/hl/src/H5HLprivate2.h
+++ b/hl/src/H5HLprivate2.h
@@ -25,96 +25,5 @@
/* HDF5 private functions */
#include "H5private.h"
-/*
- * Status return values for the `herr_t' type.
- * Since some unix/c routines use 0 and -1 (or more precisely, non-negative
- * vs. negative) as their return code, and some assumption had been made in
- * the code about that, it is important to keep these constants the same
- * values. When checking the success or failure of an integer-valued
- * function, remember to compare against zero and not one of these two
- * values.
- */
-#define SUCCEED 0
-#define FAIL (-1)
-#define UFAIL (unsigned)(-1)
-
-/* minimum of two, three, or four values */
-#undef MIN
-#define MIN(a,b) (((a)<(b)) ? (a) : (b))
-#define MIN2(a,b) MIN(a,b)
-#define MIN3(a,b,c) MIN(a,MIN(b,c))
-#define MIN4(a,b,c,d) MIN(MIN(a,b),MIN(c,d))
-
-/* maximum of two, three, or four values */
-#undef MAX
-#define MAX(a,b) (((a)>(b)) ? (a) : (b))
-#define MAX2(a,b) MAX(a,b)
-#define MAX3(a,b,c) MAX(a,MAX(b,c))
-#define MAX4(a,b,c,d) MAX(MAX(a,b),MAX(c,d))
-
-/*
- * HDF Boolean type.
- */
-#ifndef FALSE
-# define FALSE 0
-#endif
-#ifndef TRUE
-# define TRUE 1
-#endif
-#ifndef HDassert
- #define HDassert(X) assert(X)
-#endif /* HDassert */
-#ifndef HDcalloc
- #define HDcalloc(N,Z) calloc(N,Z)
-#endif /* HDcalloc */
-#ifndef HDfflush
- #define HDfflush(F) fflush(F)
-#endif /* HDfflush */
-H5_DLL int HDfprintf (FILE *stream, const char *fmt, ...);
-#ifndef HDfree
- #define HDfree(M) free(M)
-#endif /* HDfree */
-#ifndef HDmemcpy
- #define HDmemcpy(X,Y,Z) memcpy((char*)(X),(const char*)(Y),Z)
-#endif /* HDmemcpy */
-#ifndef HDmemset
- #define HDmemset(X,C,Z) memset(X,C,Z)
-#endif /* HDmemset */
-#ifndef HDrealloc
- #define HDrealloc(M,Z) realloc(M,Z)
-#endif /* HDrealloc */
-#ifndef HDsleep
- #define HDsleep(N) sleep(N)
-#endif /* HDsleep */
-#ifndef HDstrcat
- #define HDstrcat(X,Y) strcat(X,Y)
-#endif /* HDstrcat */
-#ifndef HDstrcmp
- #define HDstrcmp(X,Y) strcmp(X,Y)
-#endif /* HDstrcmp */
-#ifndef HDstrlen
- #define HDstrlen(S) strlen(S)
-#endif /* HDstrlen */
-#ifndef HDstrrchr
- #define HDstrrchr(S,C) strrchr(S,C)
-#endif /* HDstrrchr */
-#ifndef HDstrtod
- #define HDstrtod(S,R) strtod(S,R)
-#endif /* HDstrtod */
-#ifndef HDstrtol
- #define HDstrtol(S,R,N) strtol(S,R,N)
-#endif /* HDstrtol */
-/*
- * And now for a couple non-Posix functions... Watch out for systems that
- * define these in terms of macros.
- */
-#if !defined strdup && !defined H5_HAVE_STRDUP
-extern char *strdup(const char *s);
-#endif
-
-#ifndef HDstrdup
- #define HDstrdup(S) strdup(S)
-#endif /* HDstrdup */
-
#endif /* _H5HLprivate2_H */
diff --git a/hl/src/H5LD.c b/hl/src/H5LD.c
index 409ecd7..f656e08 100644
--- a/hl/src/H5LD.c
+++ b/hl/src/H5LD.c
@@ -184,7 +184,7 @@ H5LD_construct_vector(char *fields, H5LD_memb_t *listv[]/*OUT*/, hid_t par_tid)
len = HDstrlen(fields_ptr)/2 + 2;
/* Allocate memory for an H5LD_memb_t for storing a field's info */
- if((memb = (H5LD_memb_t *)HDcalloc(1, sizeof(H5LD_memb_t))) == NULL) {
+ if((memb = (H5LD_memb_t *)HDcalloc((size_t)1, sizeof(H5LD_memb_t))) == NULL) {
ret_value = FAIL;
break;
}
diff --git a/hl/test/Makefile.am b/hl/test/Makefile.am
index b933c44..7e6a8e9 100644
--- a/hl/test/Makefile.am
+++ b/hl/test/Makefile.am
@@ -26,16 +26,16 @@ AM_CPPFLAGS+=-I. -I$(srcdir) -I$(top_builddir)/src -I$(top_srcdir)/src -I$(top_b
# Test script
TEST_SCRIPT = test_ld.sh
check_SCRIPTS = $(TEST_SCRIPT)
-SCRIPT_DEPEND = ld_monitor$(EXEEXT) ld_extend$(EXEEXT)
+SCRIPT_DEPEND = ld_mx$(EXEEXT)
# The tests depend on the hdf5, hdf5 test, and hdf5_hl libraries
LDADD=$(LIBH5_HL) $(LIBH5TEST) $(LIBHDF5)
# Test programs. These are our main targets. They should be listed in the
# order to be executed, generally most specific tests to least specific tests.
-TEST_PROG=test_lite test_image test_file_image test_table test_ds test_packet test_dset_opt
- test_ld
-check_PROGRAMS=$(TEST_PROG) ld_monitor ld_extend
+TEST_PROG=test_lite test_image test_file_image test_table test_ds test_packet test_dset_opt \
+ test_ld test_dset_append
+check_PROGRAMS=$(TEST_PROG) ld_mx
# These programs generate test files for the tests. They don't need to be
# compiled every time we want to test the library. However, putting
diff --git a/hl/test/Makefile.in b/hl/test/Makefile.in
index d043334..65be4d9 100644
--- a/hl/test/Makefile.in
+++ b/hl/test/Makefile.in
@@ -73,8 +73,7 @@ DIST_COMMON = $(srcdir)/H5srcdir_str.h.in $(srcdir)/Makefile.am \
$(top_srcdir)/bin/depcomp $(top_srcdir)/bin/mkinstalldirs \
$(top_srcdir)/config/commence.am \
$(top_srcdir)/config/conclude.am COPYING
-check_PROGRAMS = $(am__EXEEXT_1) ld_monitor$(EXEEXT) \
- ld_extend$(EXEEXT)
+check_PROGRAMS = $(am__EXEEXT_1) ld_mx$(EXEEXT)
@BUILD_ALL_CONDITIONAL_TRUE@noinst_PROGRAMS = $(am__EXEEXT_2)
TESTS = $(am__EXEEXT_1) $(TEST_SCRIPT)
subdir = hl/test
@@ -88,7 +87,8 @@ CONFIG_CLEAN_FILES = H5srcdir_str.h test_ld.sh
CONFIG_CLEAN_VPATH_FILES =
am__EXEEXT_1 = test_lite$(EXEEXT) test_image$(EXEEXT) \
test_file_image$(EXEEXT) test_table$(EXEEXT) test_ds$(EXEEXT) \
- test_packet$(EXEEXT) test_dset_opt$(EXEEXT)
+ test_packet$(EXEEXT) test_dset_opt$(EXEEXT) test_ld$(EXEEXT) \
+ test_dset_append$(EXEEXT)
am__EXEEXT_2 = gen_test_ds$(EXEEXT) gen_test_ld$(EXEEXT)
PROGRAMS = $(noinst_PROGRAMS)
gen_test_ds_SOURCES = gen_test_ds.c
@@ -103,18 +103,18 @@ gen_test_ld_SOURCES = gen_test_ld.c
gen_test_ld_OBJECTS = gen_test_ld.$(OBJEXT)
gen_test_ld_LDADD = $(LDADD)
gen_test_ld_DEPENDENCIES = $(LIBH5_HL) $(LIBH5TEST) $(LIBHDF5)
-ld_extend_SOURCES = ld_extend.c
-ld_extend_OBJECTS = ld_extend.$(OBJEXT)
-ld_extend_LDADD = $(LDADD)
-ld_extend_DEPENDENCIES = $(LIBH5_HL) $(LIBH5TEST) $(LIBHDF5)
-ld_monitor_SOURCES = ld_monitor.c
-ld_monitor_OBJECTS = ld_monitor.$(OBJEXT)
-ld_monitor_LDADD = $(LDADD)
-ld_monitor_DEPENDENCIES = $(LIBH5_HL) $(LIBH5TEST) $(LIBHDF5)
+ld_mx_SOURCES = ld_mx.c
+ld_mx_OBJECTS = ld_mx.$(OBJEXT)
+ld_mx_LDADD = $(LDADD)
+ld_mx_DEPENDENCIES = $(LIBH5_HL) $(LIBH5TEST) $(LIBHDF5)
test_ds_SOURCES = test_ds.c
test_ds_OBJECTS = test_ds.$(OBJEXT)
test_ds_LDADD = $(LDADD)
test_ds_DEPENDENCIES = $(LIBH5_HL) $(LIBH5TEST) $(LIBHDF5)
+test_dset_append_SOURCES = test_dset_append.c
+test_dset_append_OBJECTS = test_dset_append.$(OBJEXT)
+test_dset_append_LDADD = $(LDADD)
+test_dset_append_DEPENDENCIES = $(LIBH5_HL) $(LIBH5TEST) $(LIBHDF5)
test_dset_opt_SOURCES = test_dset_opt.c
test_dset_opt_OBJECTS = test_dset_opt.$(OBJEXT)
test_dset_opt_LDADD = $(LDADD)
@@ -127,6 +127,10 @@ test_image_SOURCES = test_image.c
test_image_OBJECTS = test_image.$(OBJEXT)
test_image_LDADD = $(LDADD)
test_image_DEPENDENCIES = $(LIBH5_HL) $(LIBH5TEST) $(LIBHDF5)
+test_ld_SOURCES = test_ld.c
+test_ld_OBJECTS = test_ld.$(OBJEXT)
+test_ld_LDADD = $(LDADD)
+test_ld_DEPENDENCIES = $(LIBH5_HL) $(LIBH5TEST) $(LIBHDF5)
test_lite_SOURCES = test_lite.c
test_lite_OBJECTS = test_lite.$(OBJEXT)
test_lite_LDADD = $(LDADD)
@@ -173,12 +177,12 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
-SOURCES = gen_test_ds.c gen_test_ld.c ld_extend.c ld_monitor.c \
- test_ds.c test_dset_opt.c test_file_image.c test_image.c \
- test_lite.c test_packet.c test_table.c
-DIST_SOURCES = gen_test_ds.c gen_test_ld.c ld_extend.c ld_monitor.c \
- test_ds.c test_dset_opt.c test_file_image.c test_image.c \
- test_lite.c test_packet.c test_table.c
+SOURCES = gen_test_ds.c gen_test_ld.c ld_mx.c test_ds.c \
+ test_dset_append.c test_dset_opt.c test_file_image.c \
+ test_image.c test_ld.c test_lite.c test_packet.c test_table.c
+DIST_SOURCES = gen_test_ds.c gen_test_ld.c ld_mx.c test_ds.c \
+ test_dset_append.c test_dset_opt.c test_file_image.c \
+ test_image.c test_ld.c test_lite.c test_packet.c test_table.c
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@@ -485,14 +489,16 @@ CHECK_CLEANFILES = *.chkexe *.chklog *.clog combine_tables[1-2].h5 \
# Test script
TEST_SCRIPT = test_ld.sh
check_SCRIPTS = $(TEST_SCRIPT)
-SCRIPT_DEPEND = ld_monitor$(EXEEXT) ld_extend$(EXEEXT)
+SCRIPT_DEPEND = ld_mx$(EXEEXT)
# The tests depend on the hdf5, hdf5 test, and hdf5_hl libraries
LDADD = $(LIBH5_HL) $(LIBH5TEST) $(LIBHDF5)
# Test programs. These are our main targets. They should be listed in the
# order to be executed, generally most specific tests to least specific tests.
-TEST_PROG = test_lite test_image test_file_image test_table test_ds test_packet test_dset_opt
+TEST_PROG = test_lite test_image test_file_image test_table test_ds test_packet test_dset_opt \
+ test_ld test_dset_append
+
# These programs generate test files for the tests. They don't need to be
# compiled every time we want to test the library. However, putting
@@ -584,15 +590,15 @@ gen_test_ds$(EXEEXT): $(gen_test_ds_OBJECTS) $(gen_test_ds_DEPENDENCIES) $(EXTRA
gen_test_ld$(EXEEXT): $(gen_test_ld_OBJECTS) $(gen_test_ld_DEPENDENCIES) $(EXTRA_gen_test_ld_DEPENDENCIES)
@rm -f gen_test_ld$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(gen_test_ld_OBJECTS) $(gen_test_ld_LDADD) $(LIBS)
-ld_extend$(EXEEXT): $(ld_extend_OBJECTS) $(ld_extend_DEPENDENCIES) $(EXTRA_ld_extend_DEPENDENCIES)
- @rm -f ld_extend$(EXEEXT)
- $(AM_V_CCLD)$(LINK) $(ld_extend_OBJECTS) $(ld_extend_LDADD) $(LIBS)
-ld_monitor$(EXEEXT): $(ld_monitor_OBJECTS) $(ld_monitor_DEPENDENCIES) $(EXTRA_ld_monitor_DEPENDENCIES)
- @rm -f ld_monitor$(EXEEXT)
- $(AM_V_CCLD)$(LINK) $(ld_monitor_OBJECTS) $(ld_monitor_LDADD) $(LIBS)
+ld_mx$(EXEEXT): $(ld_mx_OBJECTS) $(ld_mx_DEPENDENCIES) $(EXTRA_ld_mx_DEPENDENCIES)
+ @rm -f ld_mx$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(ld_mx_OBJECTS) $(ld_mx_LDADD) $(LIBS)
test_ds$(EXEEXT): $(test_ds_OBJECTS) $(test_ds_DEPENDENCIES) $(EXTRA_test_ds_DEPENDENCIES)
@rm -f test_ds$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(test_ds_OBJECTS) $(test_ds_LDADD) $(LIBS)
+test_dset_append$(EXEEXT): $(test_dset_append_OBJECTS) $(test_dset_append_DEPENDENCIES) $(EXTRA_test_dset_append_DEPENDENCIES)
+ @rm -f test_dset_append$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_dset_append_OBJECTS) $(test_dset_append_LDADD) $(LIBS)
test_dset_opt$(EXEEXT): $(test_dset_opt_OBJECTS) $(test_dset_opt_DEPENDENCIES) $(EXTRA_test_dset_opt_DEPENDENCIES)
@rm -f test_dset_opt$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(test_dset_opt_OBJECTS) $(test_dset_opt_LDADD) $(LIBS)
@@ -602,6 +608,9 @@ test_file_image$(EXEEXT): $(test_file_image_OBJECTS) $(test_file_image_DEPENDENC
test_image$(EXEEXT): $(test_image_OBJECTS) $(test_image_DEPENDENCIES) $(EXTRA_test_image_DEPENDENCIES)
@rm -f test_image$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(test_image_OBJECTS) $(test_image_LDADD) $(LIBS)
+test_ld$(EXEEXT): $(test_ld_OBJECTS) $(test_ld_DEPENDENCIES) $(EXTRA_test_ld_DEPENDENCIES)
+ @rm -f test_ld$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_ld_OBJECTS) $(test_ld_LDADD) $(LIBS)
test_lite$(EXEEXT): $(test_lite_OBJECTS) $(test_lite_DEPENDENCIES) $(EXTRA_test_lite_DEPENDENCIES)
@rm -f test_lite$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(test_lite_OBJECTS) $(test_lite_LDADD) $(LIBS)
@@ -620,12 +629,13 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen_test_ds.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen_test_ld.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ld_extend.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ld_monitor.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ld_mx.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ds.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_dset_append.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_dset_opt.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_file_image.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_image.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ld.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_lite.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_packet.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_table.Po@am__quote@
@@ -889,7 +899,6 @@ uninstall-am:
help:
@$(top_srcdir)/bin/makehelp
- test_ld
# lib/progs/tests targets recurse into subdirectories. build-* targets
# build files in this directory.
diff --git a/hl/test/gen_test_ld.c b/hl/test/gen_test_ld.c
index bf130df..3940180 100644
--- a/hl/test/gen_test_ld.c
+++ b/hl/test/gen_test_ld.c
@@ -144,6 +144,7 @@ int
main(void)
{
hid_t fid; /* File id */
+ hid_t fapl; /* File access property list */
hsize_t cur_dims[1]; /* Dimension sizes */
hsize_t max_dims[1]; /* Maximum dimension sizes */
hsize_t cur2_dims[2]; /* Current dimension sizes */
@@ -160,8 +161,16 @@ main(void)
set_t two_cbuf[TWO_DIMS0*TWO_DIMS1]; /* Buffer for data with compound type */
int i; /* Local index variable */
+ /* Create a file access property list */
+ if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0)
+ goto done;
+
+ /* Set to use latest library format */
+ if((H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST)) < 0)
+ goto done;
+
/* Create a file */
- if((fid = H5Fcreate(FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ if((fid = H5Fcreate(FILE, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
goto done;
/* Initialization for one-dimensional dataset */
@@ -334,6 +343,8 @@ main(void)
if(H5Tclose(esc_sub2_tid) < 0) goto done;
if(H5Tclose(esc_sub4_tid) < 0) goto done;
if(H5Tclose(esc_set_tid) < 0) goto done;
+
+ if(H5Pclose(fapl) < 0) goto done;
if(H5Fclose(fid) < 0) goto done;
exit(EXIT_SUCCESS);
@@ -353,6 +364,7 @@ done:
H5Dclose(scalar_did);
H5Sclose(scalar_sid);
+ H5Pclose(fapl);
H5Fclose(fid);
H5E_END_TRY
diff --git a/hl/test/ld_extend.c b/hl/test/ld_extend.c
deleted file mode 100644
index 3ddd883..0000000
--- a/hl/test/ld_extend.c
+++ /dev/null
@@ -1,151 +0,0 @@
-#include "H5HLprivate2.h"
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-/* Size of data buffer */
-#define TEST_BUF_SIZE 100
-
-/*
- * Test variations (incremental) for one-dimensional dataset:
- * Varies from 10->13->12->12->1->3
- */
-#define ONE_NTESTS 5
-int one_tests[ONE_NTESTS] = {3, -1, 0, -11, 2};
-
-/*
- * Test variations (incremental) for two-dimensional dataset:
- * Varies from {4,10}->{6,12}->{8,1}->{10,1}->
- * {3,3}->{2,2}->{1,2}->
- * {1,4}->{1,3}->{1,3}
- */
-#define TWO_NTESTS 9
-int two_tests[TWO_NTESTS][2] = { {2, 2}, {2, -11}, {2, 0},
- {-7, 2}, {-1, -1}, {-1, 0},
- {0, 2}, {0, -1}, {0, 0}
- };
-
-static int extend_dset(const char *file, char *dname);
-
-/*
- * Extend the specified dataset in the file with ld_monitor.c monitoring
- * the dataset on the other end:
- *
- * 1) Extend the dataset according to the variations: ONE_NTESTS, TWO_NTESTS
- * 2) Write to the dataset (currently, only for integer dataset)
- * 3) Flush the dataset
- */
-static int
-extend_dset(const char *file, char *dname)
-{
- hid_t fid; /* file id */
- hid_t did; /* dataset id */
- hid_t dtype; /* dataset's datatype */
- hid_t sid; /* dataspace id */
- int i, j, k; /* local index variable */
- int ndims; /* number of dimensions */
- int buf[TEST_BUF_SIZE]; /* buffer for data */
- hsize_t cur_dims[2]; /* current dimension sizes */
- hsize_t ext_dims[2]; /* new dimension sizes after extension */
-
- /* Open the file */
- if((fid = H5Fopen(file, H5F_ACC_RDWR, H5P_DEFAULT)) < 0)
- goto done;
-
- /* Open the dataset */
- if((did = H5Dopen2(fid, dname, H5P_DEFAULT)) < 0)
- goto done;
-
- /* Get the dataset's data space */
- if((sid = H5Dget_space(did)) < 0)
- goto done;
-
- /* Get the # of dimensions for the dataset */
- if((ndims = H5Sget_simple_extent_ndims(sid)) < 0)
- goto done;
-
- /* Initialize data written to the dataset */
- HDmemset(buf, 0, sizeof(buf));
- for(k = 0; k < TEST_BUF_SIZE; k++)
- buf[k] = k;
-
- /* Loop through different variations of extending the dataset */
- for(i = 0; i < (ndims == 1 ? ONE_NTESTS: TWO_NTESTS); i++) {
-
- sleep(2);
-
- /* Get the dataset's current dimension sizes */
- if(H5LDget_dset_dims(did, cur_dims) < 0)
- goto done;
-
- /* Set up the new extended dimension sizes */
- for(j = 0; j < ndims; j++)
- ext_dims[j] = cur_dims[j] + (ndims == 1 ? (hsize_t)one_tests[i] : (hsize_t)two_tests[i][j]);
-
- /* Extend the dataset */
- if(H5Dset_extent(did, ext_dims) < 0)
- goto done;
-
- /* Get the dataset's data type */
- if((dtype = H5Tget_native_type(H5Dget_type(did), H5T_DIR_DEFAULT)) < 0)
- goto done;
-
- /* Write to the whole dataset after extension */
- if(H5Dwrite(did, dtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0)
- goto done;
-
- /* Flush the data */
- if(H5Dflush(did) < 0)
- goto done;
-
- } /* end for ONE_NTESTS or TWO_NTESTS */
-
- /* Closing */
- if(H5Tclose(dtype) < 0) goto done;
- if(H5Sclose(sid) < 0) goto done;
- if(H5Dclose(did) < 0) goto done;
- if(H5Fclose(fid) < 0) goto done;
-
- return(0);
-
-done:
- H5E_BEGIN_TRY
- H5Tclose(dtype);
- H5Sclose(sid);
- H5Dclose(did);
- H5Fclose(fid);
- H5E_END_TRY
-
- return(-1);
-} /* extend_dset() */
-
-
-/* Usage: extend_dset xx.h5 dname */
-int
-main(int argc, const char *argv[])
-{
- char *dname = NULL; /* dataset name */
- char *fname = NULL; /* file name */
-
- if(argc != 3) {
- fprintf(stderr, "Should have file name and dataset name to be extended...\n");
- goto done;
- }
-
- /* Get the file and dataset names to be extended */
- fname = HDstrdup(argv[1]);
- dname = HDstrdup(argv[2]);
-
- /* Extend the specified dataset in the file */
- if(extend_dset(fname, dname) < 0)
- goto done;
-
- exit(EXIT_SUCCESS);
-
-done:
- if(dname) HDfree(dname);
- if(fname) HDfree(fname);
- exit(EXIT_FAILURE);
-} /* main() */
diff --git a/hl/test/ld_monitor.c b/hl/test/ld_monitor.c
deleted file mode 100644
index 7b90715..0000000
--- a/hl/test/ld_monitor.c
+++ /dev/null
@@ -1,148 +0,0 @@
-#include "H5HLprivate2.h"
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#define TEST_BUF_SIZE 100
-
-/*
- * Monitor the specified dataset in the file while ld_extend.c extending
- * and writing to the dataset on the other end:
- *
- * 1) Retrieve the dataset's current dimension sizes
- * 2) If there are changes in dimension sizes:
- * print the dimension sizes
- * retrieve the appended data and print them
- */
-static int
-monitor_dset(const char *fname, char *dname)
-{
- hid_t fid; /* dataset id */
- hid_t did; /* dataset id */
- hid_t sid; /* dataspace id */
- int ndims; /* # of dimensions in the dataspace */
- int i, u; /* local index variable */
- hsize_t cur_dims[H5S_MAX_RANK]; /* current dimension sizes */
- hsize_t prev_dims[H5S_MAX_RANK]; /* previous dimension sizes */
- int buf[TEST_BUF_SIZE]; /* Buffer for data */
- herr_t ret_value = 0; /* return value */
-
- /* Open the file with SWMR */
- if((fid = H5Fopen(fname, H5F_ACC_SWMR_READ, H5P_DEFAULT)) < 0)
- goto done;
-
- HDfprintf(stdout, "Monitoring dataset %s...\n", dname);
-
- /* Open the dataset for minitoring */
- if((did = H5Dopen2(fid, dname, H5P_DEFAULT)) < 0) {
- HDfprintf(stdout, "error in opening dataset \"%s\"\n", dname);
- ret_value = -1;
- goto done;
- }
-
- /* Get the dataset's data space */
- if((sid = H5Dget_space(did)) < 0) {
- HDfprintf(stdout, "error in getting dataspace id for dataset \"%s\"\n", dname);
- ret_value = -1;
- goto done;
- }
-
- /* Get the dataset's dimension sizes */
- if((ndims = H5Sget_simple_extent_dims(sid, prev_dims, NULL)) < 0) {
- HDfprintf(stdout, "unable to get dimensions sizes for \"%s\"\n", dname);
- ret_value = -1;
- goto done;
- }
-
- /* Monitor the dataset for changes */
- while(1) {
-
- /* Refresh the dataset */
- if(H5Drefresh(did) < 0) {
- ret_value = -1;
- goto done;
- }
-
- /* Get the dataset's current dimension sizes */
- if(H5LDget_dset_dims(did, cur_dims) < 0) {
- HDfprintf(stdout, "unable to get dimension sizes for \"%s\"\n", dname);
- ret_value = -1;
- goto done;
- }
-
- /* Check for changes in dimension sizes */
- for(u = 0; u < ndims; u++) {
- if(cur_dims[u] != prev_dims[u])
- break;
- }
-
- /* Printing only when there are changes */
- if(u < ndims) {
- /* Print the current dimension sizes */
- HDfprintf(stdout, "\n");
- for(i = 0; i < ndims; i++)
- HDfprintf(stdout, "%d ", (int)cur_dims[i]);
- HDfprintf(stdout, "\n");
-
- /* Get data appended to the dataset and print the data */
- HDmemset(buf, 0, sizeof(buf));
- if(H5LDget_dset_elmts(did, prev_dims, cur_dims, NULL, buf) >= 0) {
-
- for(i = 0; i < TEST_BUF_SIZE; i++) {
- if(i % 10)
- HDfprintf(stdout, "%d ", buf[i]);
- else
- HDfprintf(stdout, "\n%d ", buf[i]);
- }
- HDfprintf(stdout, "\n");
- }
-
- /* Flush the output to stdout */
- HDfflush(stdout);
- /* Update the dimension sizes */
- HDmemcpy(prev_dims, cur_dims, ndims * sizeof(hsize_t));
- }
-
- /* Sleep before next monitor */
- sleep(1);
- } /* end while */
-
-done:
- /* Closing */
- H5E_BEGIN_TRY
- H5Sclose(sid);
- H5Dclose(did);
- H5E_END_TRY
-
- return(ret_value);
-} /* monitor_dset() */
-
-/* usage: monitor xx.h5 dname */
-int
-main(int argc, const char *argv[])
-{
- char *dname = NULL; /* dataset name */
- char *fname = NULL; /* file name */
-
- if(argc != 3) {
- HDfprintf(stderr, "Should have file name and dataset name to be monitored...\n");
- goto done;
- }
-
- /* Get the file name and dataset name to be extended */
- fname = strdup(argv[1]);
- dname = strdup(argv[2]);
-
- /* only integer dataset */
- if(monitor_dset(fname, dname) < 0)
- goto done;
-
- exit(EXIT_SUCCESS);
-
-done:
- if(dname) free(dname);
- if(fname) free(fname);
- exit(EXIT_FAILURE);
-}
diff --git a/hl/test/ld_mx.c b/hl/test/ld_mx.c
new file mode 100644
index 0000000..9d45823
--- /dev/null
+++ b/hl/test/ld_mx.c
@@ -0,0 +1,353 @@
+#include "h5hltest.h"
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+/* Size of data buffer */
+#define TEST_BUF_SIZE 100
+
+/* Note: These two defines should be the same as the defines in test_ld.sh.in */
+/* The message sent by extend_dset that the file is done with file open releasing the file lock */
+#define WRITER_MESSAGE "LD_WRITER_MESSAGE"
+/* The message sent by monitor_dset that it is done setting up */
+#define READER_MESSAGE "LD_READER_MESSAGE"
+
+/*
+ * Test variations (incremental) for one-dimensional dataset:
+ * Varies from 10->13->12->12->1->3
+ */
+#define ONE_NTESTS 5
+int one_tests[ONE_NTESTS] = {3, -1, 0, -11, 2};
+
+/*
+ * Test variations (incremental) for two-dimensional dataset:
+ * Varies from {4,10}->{6,12}->{8,1}->{10,1}->
+ * {3,3}->{2,2}->{1,2}->
+ * {1,4}->{1,3}->{1,3}
+ */
+#define TWO_NTESTS 9
+int two_tests[TWO_NTESTS][2] = { {2, 2}, {2, -11}, {2, 0},
+ {-7, 2}, {-1, -1}, {-1, 0},
+ {0, 2}, {0, -1}, {0, 0}
+ };
+
+/*
+ * Extend the specified dataset in the file with "monitor_dset" monitoring
+ * the dataset on the other end:
+ * 1) Extend the dataset according to the variations: ONE_NTESTS, TWO_NTESTS
+ * 2) Write to the dataset (currently, only for integer dataset)
+ * 3) Flush the dataset
+ *
+ * Due to the implementation of file locking, coordination is needed in file
+ * opening for the writer/reader tests to proceed as expected:
+ * --it will send the WRITER_MESSAGE when the file open is done:
+ * to notify monitor_dset() to start monitoring the dataset
+ * --it will wait for the READER_MESSAGE from monitor_dset() before extending
+ * the dataset
+ */
+static int
+extend_dset(const char *file, char *dname)
+{
+ hid_t fid; /* file id */
+ hid_t fapl; /* file access property list */
+ hid_t did; /* dataset id */
+ hid_t dtype; /* dataset's datatype */
+ hid_t sid; /* dataspace id */
+ int i, j, k; /* local index variable */
+ int ndims; /* number of dimensions */
+ int buf[TEST_BUF_SIZE]; /* buffer for data */
+ hsize_t cur_dims[2]; /* current dimension sizes */
+ hsize_t ext_dims[2]; /* new dimension sizes after extension */
+
+ /* Create a file access property list */
+ if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0)
+ goto done;
+
+ /* Set to use latest library format */
+ if((H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST)) < 0)
+ goto done;
+
+ /* Open the file with SWMR write */
+ if((fid = H5Fopen(file, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl)) < 0)
+ goto done;
+
+ /* Send message that "extend_dset" (this routine) is done with H5Fopen--the file lock is released */
+ h5_send_message(WRITER_MESSAGE);
+
+ /* Open the dataset */
+ if((did = H5Dopen2(fid, dname, H5P_DEFAULT)) < 0)
+ goto done;
+
+ /* Get the dataset's data space */
+ if((sid = H5Dget_space(did)) < 0)
+ goto done;
+
+ /* Get the # of dimensions for the dataset */
+ if((ndims = H5Sget_simple_extent_ndims(sid)) < 0)
+ goto done;
+
+ /* Initialize data written to the dataset */
+ HDmemset(buf, 0, sizeof(buf));
+ for(k = 0; k < TEST_BUF_SIZE; k++)
+ buf[k] = k;
+
+ /* Wait for message from "monitor_dset" before starting to extend the dataset */
+ if(h5_wait_message(READER_MESSAGE) < 0)
+ goto done;
+
+ /* Loop through different variations of extending the dataset */
+ for(i = 0; i < (ndims == 1 ? ONE_NTESTS: TWO_NTESTS); i++) {
+ HDsleep(2);
+
+ /* Get the dataset's current dimension sizes */
+ if(H5LDget_dset_dims(did, cur_dims) < 0)
+ goto done;
+
+ /* Set up the new extended dimension sizes */
+ for(j = 0; j < ndims; j++)
+ ext_dims[j] = cur_dims[j] + (ndims == 1 ? (hsize_t)one_tests[i] : (hsize_t)two_tests[i][j]);
+
+ /* Extend the dataset */
+ if(H5Dset_extent(did, ext_dims) < 0)
+ goto done;
+
+ /* Get the dataset's data type */
+ if((dtype = H5Tget_native_type(H5Dget_type(did), H5T_DIR_DEFAULT)) < 0)
+ goto done;
+
+ /* Write to the whole dataset after extension */
+ if(H5Dwrite(did, dtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0)
+ goto done;
+
+ /* Flush the data */
+ if(H5Dflush(did) < 0)
+ goto done;
+
+ } /* end for ONE_NTESTS or TWO_NTESTS */
+
+ /* Closing */
+ if(H5Tclose(dtype) < 0) goto done;
+ if(H5Sclose(sid) < 0) goto done;
+ if(H5Dclose(did) < 0) goto done;
+ if(H5Pclose(fapl) < 0) goto done;
+ if(H5Fclose(fid) < 0) goto done;
+
+ return(0);
+
+done:
+ H5E_BEGIN_TRY
+ H5Tclose(dtype);
+ H5Sclose(sid);
+ H5Dclose(did);
+ H5Pclose(fapl);
+ H5Fclose(fid);
+ H5E_END_TRY
+
+ return(-1);
+} /* extend_dset() */
+
+
+/*
+ * Monitor the specified dataset in the file while "extend_dset" is extending
+ * and writing to the dataset on the other end:
+ *
+ * 1) Retrieve the dataset's current dimension sizes
+ * 2) If there are changes in dimension sizes:
+ * print the dimension sizes
+ * retrieve the appended data and print them
+ *
+ * Due to the implementation of file locking, coordination is needed in file
+ * opening for the writer/reader tests to proceed as expected:
+ * --it will wait for the WRITER_MESSAGE from extend_dset() before opening
+ * the test file
+ * --it will send the READER_MESSAGE when the setup is done:
+ * to notify extend_dset() to start extending the dataset
+ */
+static int
+monitor_dset(const char *fname, char *dname)
+{
+ hid_t fid; /* file id */
+ hid_t fapl; /* file access property list */
+ hid_t did; /* dataset id */
+ hid_t sid; /* dataspace id */
+ int ndims; /* # of dimensions in the dataspace */
+ int i, u; /* local index variable */
+ hsize_t cur_dims[H5S_MAX_RANK]; /* current dimension sizes */
+ hsize_t prev_dims[H5S_MAX_RANK]; /* previous dimension sizes */
+ int buf[TEST_BUF_SIZE]; /* Buffer for data */
+ herr_t ret_value = 0; /* return value */
+
+ /* Wait for message from "extend_dset" before opening the file */
+ if(h5_wait_message(WRITER_MESSAGE) < 0)
+ goto done;
+
+ /* Create a file access property list */
+ if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0)
+ goto done;
+
+ /* Set to use latest library format */
+ if((H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST)) < 0)
+ goto done;
+
+ /* Open the file with SWMR access */
+ if((fid = H5Fopen(fname, H5F_ACC_SWMR_READ, fapl)) < 0) {
+ ret_value = -1;
+ goto done;
+ }
+
+ HDfprintf(stdout, "Monitoring dataset %s...\n", dname);
+
+ /* Open the dataset for minitoring */
+ if((did = H5Dopen2(fid, dname, H5P_DEFAULT)) < 0) {
+ HDfprintf(stdout, "error in opening dataset \"%s\"\n", dname);
+ ret_value = -1;
+ goto done;
+ }
+
+ /* Get the dataset's data space */
+ if((sid = H5Dget_space(did)) < 0) {
+ HDfprintf(stdout, "error in getting dataspace id for dataset \"%s\"\n", dname);
+ ret_value = -1;
+ goto done;
+ }
+
+ /* Get the dataset's dimension sizes */
+ if((ndims = H5Sget_simple_extent_dims(sid, prev_dims, NULL)) < 0) {
+ HDfprintf(stdout, "unable to get dimensions sizes for \"%s\"\n", dname);
+ ret_value = -1;
+ goto done;
+ }
+
+ /* Send message that "monitor_dset" (this routine) is done with setting up */
+ h5_send_message(READER_MESSAGE);
+
+ /* Monitor the dataset for changes */
+ while(1) {
+
+ /* Refresh the dataset */
+ if(H5Drefresh(did) < 0) {
+ ret_value = -1;
+ goto done;
+ }
+
+ /* Get the dataset's current dimension sizes */
+ if(H5LDget_dset_dims(did, cur_dims) < 0) {
+ HDfprintf(stdout, "unable to get dimension sizes for \"%s\"\n", dname);
+ ret_value = -1;
+ goto done;
+ }
+
+ /* Check for changes in dimension sizes */
+ for(u = 0; u < ndims; u++) {
+ if(cur_dims[u] != prev_dims[u]) {
+ break;
+ }
+ }
+
+ /* Printing only when there are changes */
+ if(u < ndims) {
+ /* Print the current dimension sizes */
+ HDfprintf(stdout, "\n");
+ for(i = 0; i < ndims; i++)
+ HDfprintf(stdout, "%d ", (int)cur_dims[i]);
+ HDfprintf(stdout, "\n");
+
+ /* Get data appended to the dataset and print the data */
+ HDmemset(buf, 0, sizeof(buf));
+ if(H5LDget_dset_elmts(did, prev_dims, cur_dims, NULL, buf) >= 0) {
+
+ for(i = 0; i < TEST_BUF_SIZE; i++) {
+ if(i % 10)
+ HDfprintf(stdout, "%d ", buf[i]);
+ else
+ HDfprintf(stdout, "\n%d ", buf[i]);
+ }
+ HDfprintf(stdout, "\n");
+ }
+
+ /* Flush the output to stdout */
+ HDfflush(stdout);
+ /* Update the dimension sizes */
+ HDmemcpy(prev_dims, cur_dims, ndims * sizeof(hsize_t));
+ }
+ HDsleep(1);
+ } /* end for */
+
+done:
+ /* Closing */
+ H5E_BEGIN_TRY
+ H5Sclose(sid);
+ H5Dclose(did);
+ H5Pclose(fapl);
+ H5E_END_TRY
+
+ return(ret_value);
+} /* monitor_dset() */
+
+/* Usage:
+ * ld_mx -m fname dname -- to monitor the file's dataset
+ * or
+ * ld_mx -x fname dname -- to extend the file's dataset
+ */
+/* This file is a combination of ld_monitor.c and ld_extend.c which are svn deleted */
+int
+main(int argc, char *argv[])
+{
+ char *dname = NULL; /* dataset name */
+ char *fname = NULL; /* file name */
+ int opt = 0;
+ unsigned int monitor = 0, extend = 0;
+
+ if(argc != 4) {
+ fprintf(stderr, "Usage: ld_mx -m fname dname for monitoring the dataset 'dname' in the file 'fname'\n");
+ fprintf(stderr, "Usage: ld_mx -x fname dname for extending the dataset 'dname' in the file 'fname'\n");
+ goto done;
+ }
+ /* Parse command line options */
+ while((opt = getopt(argc, argv, "mx")) != -1) {
+ switch(opt) {
+ case 'm': /* monitor dataset */
+ monitor = 1;
+ break;
+
+ case 'x': /* extend dataset */
+ extend = 1;
+ break;
+ default:
+ printf("Invalid option encountered\n");
+ break;
+ }
+ }
+
+ if((extend && monitor) || (!extend && !monitor)) {
+ fprintf(stderr, "Usage: ldmx -m/-x fname dname\n");
+ goto done;
+ }
+
+ if(optind != 2) {
+ fprintf(stderr, "Usage: ldmx -m/-x fname dname\n");
+ goto done;
+ }
+
+ fname = HDstrdup(argv[optind++]);
+ dname = HDstrdup(argv[optind++]);
+
+
+ if(extend) {
+ if(extend_dset(fname, dname) < 0)
+ goto done;
+ } else if(monitor) {
+ if(monitor_dset(fname, dname) < 0)
+ goto done;
+ }
+
+ exit(EXIT_SUCCESS);
+
+done:
+ if(dname) HDfree(dname);
+ if(fname) HDfree(fname);
+ exit(EXIT_FAILURE);
+} /* main() */
diff --git a/hl/test/test_dset_append.c b/hl/test/test_dset_append.c
new file mode 100644
index 0000000..5710d78
--- /dev/null
+++ b/hl/test/test_dset_append.c
@@ -0,0 +1,1191 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+* 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. *
+* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdlib.h>
+#include <string.h>
+#include "h5hltest.h"
+#include "H5srcdir.h"
+#include "H5DOpublic.h"
+#include <math.h>
+
+#if defined(H5_HAVE_ZLIB_H) && !defined(H5_ZLIB_HEADER)
+# define H5_ZLIB_HEADER "zlib.h"
+#endif
+#if defined(H5_ZLIB_HEADER)
+# include H5_ZLIB_HEADER /* "zlib.h" */
+#endif
+
+#define FILE "test_append.h5"
+#define DNAME_UNLIM "dataset_unlim"
+#define DNAME_LESS "dataset_less"
+#define DNAME_VARY "dataset_vary"
+#define DNAME_LINE "dataset_line"
+#define DNAME_COLUMN "dataset_column"
+#define DBUGNAME1 "dataset_bug1"
+#define DBUGNAME2 "dataset_bug2"
+
+/* The callback function for the object flush property */
+static herr_t
+flush_func(hid_t obj_id, void *_udata)
+{
+ unsigned *flush_ct = (unsigned*)_udata;
+ ++(*flush_ct);
+ return 0;
+}
+
+/* The callback function for the append flush property */
+static herr_t
+append_func(hid_t dset_id, hsize_t *cur_dims, void *_udata)
+{
+ unsigned *append_ct = (unsigned *)_udata;
+ ++(*append_ct);
+ return 0;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: test_dataset_append_lines_columns
+ *
+ * Purpose: Verify that the object flush property and the append flush property
+ * are working properly when appending lines and columns to a dataset
+ * with 2 extendible dimensions.
+ *
+ * Return: Success: 0
+ * Failure: 1
+ *
+ * Programmer: Vailin Choi; Jan 2014
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_dataset_append_lines_columns(hid_t fid)
+{
+ hid_t did = -1; /* Dataset ID */
+ hid_t sid = -1; /* Dataspace ID */
+ hid_t dcpl = -1; /* A copy of dataset creation property */
+ hid_t dapl = -1; /* A copy of dataset access property */
+ hid_t ffapl = -1; /* The file's file access property list */
+
+ hsize_t dims[2] = {0, 10}; /* Current dimension sizes */
+ hsize_t maxdims[2] = {H5S_UNLIMITED, H5S_UNLIMITED}; /* Maximum dimension sizes */
+ hsize_t chunk_dims[2] = {2,5}; /* Chunk dimension sizes */
+ int lbuf[10], cbuf[6]; /* The data buffers */
+ int buf[6][13], rbuf[6][13]; /* The data buffers */
+ int i, j; /* Local index variables */
+
+ hsize_t boundary[2] = {1, 1}; /* Boundary sizes */
+ unsigned append_ct = 0; /* The # of appends */
+ unsigned *flush_ptr; /* Points to the flush counter */
+
+ TESTING("Append flush with H5DOappend()--append lines & columns");
+
+ /* Get the file's file access property list */
+ if((ffapl = H5Fget_access_plist(fid)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Set to 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;
+
+ /* Set append flush property */
+ if((dapl = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pset_append_flush(dapl, 2, boundary, append_func, &append_ct) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Create the dataset */
+ if((did = H5Dcreate2(fid, DNAME_UNLIM, H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, dapl)) < 0)
+ TEST_ERROR;
+
+ /* Append 6 lines to the dataset */
+ for(i = 0; i < 6; i++) {
+ for(j = 0; j < 10; j++)
+ lbuf[j] = buf[i][j] = (i*10) + (j+1);
+ if(H5DOappend(did, H5P_DEFAULT, 0, (size_t)1, H5T_NATIVE_INT, lbuf) < 0)
+ TEST_ERROR;
+ }
+
+ /* Verify the # of appends */
+ if(append_ct != 6)
+ TEST_ERROR;
+
+ /* Retrieve and verify object flush counts */
+ if(H5Pget_object_flush_cb(ffapl, NULL, (void **)&flush_ptr) < 0)
+ FAIL_STACK_ERROR;
+ if(*flush_ptr != 6)
+ TEST_ERROR;
+
+ /* Append 3 columns to the dataset */
+ for(i = 0; i < 3; i++) {
+ for(j = 0; j < 6; j++)
+ cbuf[j] = buf[j][i+10] = ((i*6) + (j+1)) * -1;
+ if(H5DOappend(did, H5P_DEFAULT, 1, (size_t)1, H5T_NATIVE_INT, cbuf) < 0)
+ TEST_ERROR;
+ }
+
+ /* Verify the # of appends */
+ if(append_ct != 9)
+ TEST_ERROR;
+
+ /* Retrieve and verify object flush counts */
+ if(H5Pget_object_flush_cb(ffapl, NULL, (void **)&flush_ptr) < 0)
+ FAIL_STACK_ERROR;
+ if(*flush_ptr != 9)
+ TEST_ERROR;
+
+ /* Read the dataset */
+ if(H5Dread(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, rbuf) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Verify the data */
+ for(i = 0; i < 6; i++)
+ for(j = 0; j < 13; j++)
+ if(buf[i][j] != rbuf[i][j])
+ TEST_ERROR;
+
+ /* Clear the buffer */
+ HDmemset(rbuf, 0, sizeof(rbuf));
+
+ /* Close the dataset */
+ if(H5Dclose(did) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Open the dataset again */
+ if((did = H5Dopen(fid, DNAME_UNLIM, H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Read the dataset */
+ if(H5Dread(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, rbuf) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Verify the data */
+ for(i = 0; i < 6; i++)
+ for(j = 0; j < 13; j++)
+ if(buf[i][j] != rbuf[i][j])
+ TEST_ERROR;
+
+ /* Closing */
+ if(H5Dclose(did) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Sclose(sid) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(dapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(dcpl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(ffapl) < 0)
+ FAIL_STACK_ERROR;
+
+ PASSED();
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(dapl);
+ H5Pclose(dcpl);
+ H5Pclose(sid);
+ H5Dclose(did);
+ H5Pclose(ffapl);
+ } H5E_END_TRY;
+
+ return 1;
+} /* test_dataset_append_lines_columns() */
+
+/*-------------------------------------------------------------------------
+ * Function: test_dataset_append_lines
+ *
+ * Purpose: Verify that the object flush property and the append flush property
+ * are working properly when appending lines to a dataset with
+ * one extendible dimension (line).
+ *
+ * Return: Success: 0
+ * Failure: 1
+ *
+ * Programmer: Vailin Choi; Jan 2014
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_dataset_append_lines(hid_t fid)
+{
+ hid_t did = -1; /* Dataset ID */
+ hid_t sid = -1; /* Dataspace ID */
+ hid_t dcpl = -1; /* A copy of dataset creation property */
+ hid_t dapl = -1; /* A copy of dataset access property */
+ hid_t ffapl = -1; /* The file's file access property list */
+
+ hsize_t dims[2] = {0, 10}; /* Current dimension sizes */
+ hsize_t maxdims[2] = {H5S_UNLIMITED, 10}; /* Maximum dimension sizes */
+ hsize_t chunk_dims[2] = {2,5}; /* Chunk dimension sizes */
+ int lbuf[10]; /* The data buffer */
+ int buf[6][10], rbuf[6][10]; /* The data buffers */
+ int i, j; /* Local index variables */
+
+ hsize_t boundary[2] = {1, 0}; /* Boundary sizes */
+ unsigned append_ct = 0; /* The # of appends */
+ unsigned *flush_ptr; /* Points to the flush counter */
+
+ TESTING("Append flush with H5DOappend()--append lines");
+
+ /* Get the file's file access property list */
+ if((ffapl = H5Fget_access_plist(fid)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Set to 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;
+
+ /* Set append flush property */
+ if((dapl = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pset_append_flush(dapl, 2, boundary, append_func, &append_ct) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Create the dataset */
+ if((did = H5Dcreate2(fid, DNAME_LINE, H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, dapl)) < 0)
+ TEST_ERROR;
+
+ /* Append 6 lines to the dataset */
+ for(i = 0; i < 6; i++) {
+ for(j = 0; j < 10; j++)
+ lbuf[j] = buf[i][j] = (i*10) + (j+1);
+ if(H5DOappend(did, H5P_DEFAULT, 0, (size_t)1, H5T_NATIVE_INT, lbuf) < 0)
+ TEST_ERROR;
+ }
+
+ /* Verify the # of appends */
+ if(append_ct != 6)
+ TEST_ERROR;
+
+ if(H5Pget_object_flush_cb(ffapl, NULL, (void **)&flush_ptr) < 0)
+ FAIL_STACK_ERROR;
+ if(*flush_ptr != 6)
+ TEST_ERROR;
+
+ /* Read the dataset */
+ if(H5Dread(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, rbuf) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Verify the data */
+ for(i = 0; i < 6; i++)
+ for(j = 0; j < 10; j++)
+ if(buf[i][j] != rbuf[i][j])
+ TEST_ERROR;
+
+ /* Clear the buffer */
+ HDmemset(rbuf, 0, sizeof(rbuf));
+
+ /* Close the dataset */
+ if(H5Dclose(did) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Open the dataset again */
+ if((did = H5Dopen(fid, DNAME_LINE, H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Read the dataset */
+ if(H5Dread(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, rbuf) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Verify the data */
+ for(i = 0; i < 6; i++)
+ for(j = 0; j < 10; j++)
+ if(buf[i][j] != rbuf[i][j])
+ TEST_ERROR;
+
+ /* Closing */
+ if(H5Dclose(did) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Sclose(sid) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(dapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(dcpl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(ffapl) < 0)
+ FAIL_STACK_ERROR;
+
+ PASSED();
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(dapl);
+ H5Pclose(dcpl);
+ H5Pclose(sid);
+ H5Dclose(did);
+ H5Pclose(ffapl);
+ } H5E_END_TRY;
+
+ return 1;
+} /* test_dataset_append_lines() */
+
+/*-------------------------------------------------------------------------
+ * Function: test_dataset_append_columns
+ *
+ * Purpose: Verify that the object flush property and the append flush property
+ * are working properly when appending columns to a dataset
+ * with one extendible dimension (column).
+ *
+ * Return: Success: 0
+ * Failure: 1
+ *
+ * Programmer: Vailin Choi; Jan 2014
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_dataset_append_columns(hid_t fid)
+{
+ hid_t did = -1; /* Dataset ID */
+ hid_t sid = -1; /* Dataspace ID */
+ hid_t dcpl = -1; /* A copy of dataset creation property */
+ hid_t dapl = -1; /* A copy of dataset access property */
+ hid_t ffapl = -1; /* The file's file access property list */
+
+ hsize_t dims[2] = {6, 0}; /* Current dimension sizes */
+ hsize_t maxdims[2] = {6, H5S_UNLIMITED}; /* Maximum dimension sizes */
+ hsize_t chunk_dims[2] = {2,5}; /* Chunk dimension sizes */
+ int cbuf[6]; /* The data buffer */
+ int buf[6][3], rbuf[6][3]; /* The data buffers */
+ int i, j; /* Local index variable */
+
+ hsize_t boundary[2] = {0, 1}; /* Boundary sizes */
+ unsigned append_ct = 0; /* The # of appends */
+ unsigned *flush_ptr; /* Points to the flush counter */
+
+ TESTING("Append flush with H5DOappend()--append columns");
+
+ /* Get the file's file access property list */
+ if((ffapl = H5Fget_access_plist(fid)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Set to 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;
+
+ /* Set append flush property */
+ if((dapl = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pset_append_flush(dapl, 2, boundary, append_func, &append_ct) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Create the dataset */
+ if((did = H5Dcreate2(fid, DNAME_COLUMN, H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, dapl)) < 0)
+ TEST_ERROR;
+
+ /* Append 3 columns to the dataset */
+ for(i = 0; i < 3; i++) {
+ for(j = 0; j < 6; j++)
+ cbuf[j] = buf[j][i] = ((i*6) + (j+1)) * -1;
+ if(H5DOappend(did, H5P_DEFAULT, 1, (size_t)1, H5T_NATIVE_INT, cbuf) < 0)
+ TEST_ERROR;
+ }
+
+ /* Verify the # of appends */
+ if(append_ct != 3)
+ TEST_ERROR;
+
+ /* Retrieve and verify object flush counts */
+ if(H5Pget_object_flush_cb(ffapl, NULL, (void **)&flush_ptr) < 0)
+ FAIL_STACK_ERROR;
+ if(*flush_ptr != 3)
+ TEST_ERROR;
+
+ /* Read the dataset */
+ if(H5Dread(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, rbuf) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Verify the data */
+ for(i = 0; i < 6; i++)
+ for(j = 0; j < 3; j++)
+ if(buf[i][j] != rbuf[i][j])
+ TEST_ERROR;
+
+ /* Clear the buffer */
+ HDmemset(rbuf, 0, sizeof(rbuf));
+
+ /* Close the dataset */
+ if(H5Dclose(did) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Open the dataset again */
+ if((did = H5Dopen(fid, DNAME_COLUMN, H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Read the dataset */
+ if(H5Dread(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, rbuf) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Verify the data */
+ for(i = 0; i < 6; i++)
+ for(j = 0; j < 3; j++)
+ if(buf[i][j] != rbuf[i][j])
+ TEST_ERROR;
+
+ /* Closing */
+ if(H5Dclose(did) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Sclose(sid) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(dapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(dcpl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(ffapl) < 0)
+ FAIL_STACK_ERROR;
+
+ PASSED();
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(dapl);
+ H5Pclose(dcpl);
+ H5Pclose(sid);
+ H5Dclose(did);
+ H5Pclose(ffapl);
+ } H5E_END_TRY;
+
+ return 1;
+} /* test_dataset_append_columns() */
+
+/*-------------------------------------------------------------------------
+ * Function: test_dataset_append_BUG1
+ *
+ * Purpose: Verify that the object flush property and the append flush property
+ * are working properly when appending lines and columns to an
+ * extendible dataset.
+ * A BUG occurs:
+ * when the extendible dataset is set up as follows:
+ * hsize_t dims[2] = {0, 10};
+ * hsize_t maxdims[2] = {H5S_UNLIMITED, 50};
+ * when append 6 lines and 3 columns to the dataset;
+ * The data is correct when the dataset is read at this point;
+ * The data is incorrect when the dataset is closed, opened again, and read at this point;
+ * NOTE: the problem does not occur when H5Dflush() is not performed for each line/column.
+ *
+ * Return: Success: 0
+ * Failure: 1
+ *
+ * Programmer: Vailin Choi; Jan 2014
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_dataset_append_BUG1(hid_t fid)
+{
+ hid_t did = -1; /* Dataset ID */
+ hid_t sid = -1; /* Dataspace ID */
+ hid_t dcpl = -1; /* Dataset creation property */
+ hid_t dapl = -1; /* Dataset access property */
+ hid_t ffapl = -1; /* The file's file access property list */
+
+ hsize_t dims[2] = {0, 10}; /* Current dimension sizes */
+ hsize_t maxdims[2] = {H5S_UNLIMITED, 50}; /* Maximum dimension sizes */
+ hsize_t chunk_dims[2] = {2,5}; /* Chunk dimension sizes */
+ int lbuf[10], cbuf[6]; /* The data buffers */
+ int buf[6][13], rbuf[6][13]; /* The data buffers */
+ int i, j; /* Local index variables */
+
+ hsize_t boundary[2] = {1, 1}; /* Boundary sizes */
+ unsigned append_ct = 0; /* The # of appends */
+ unsigned *flush_ptr; /* Points to the flush counter */
+
+ TESTING("Append flush with H5DOappend()--append lines & columns--BUG1");
+
+ /* Get the file's file access property list */
+ if((ffapl = H5Fget_access_plist(fid)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Set to 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;
+
+ /* Set append flush property */
+ if((dapl = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pset_append_flush(dapl, 2, boundary, append_func, &append_ct) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Create the dataset */
+ if((did = H5Dcreate2(fid, DBUGNAME1, H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, dapl)) < 0)
+ TEST_ERROR;
+
+ /* Append 6 lines to the dataset */
+ for(i = 0; i < 6; i++) {
+ for(j = 0; j < 10; j++)
+ lbuf[j] = buf[i][j] = (i*10) + (j+1);
+ if(H5DOappend(did, H5P_DEFAULT, 0, (size_t)1, H5T_NATIVE_INT, lbuf) < 0)
+ TEST_ERROR;
+ }
+
+ /* Verify the # of appends */
+ if(append_ct != 6)
+ TEST_ERROR;
+
+ /* Retrieve and verify object flush counts */
+ if(H5Pget_object_flush_cb(ffapl, NULL, (void **)&flush_ptr) < 0)
+ FAIL_STACK_ERROR;
+ if(*flush_ptr != 6)
+ TEST_ERROR;
+
+
+ /* Append 3 columns to the dataset */
+ for(i = 0; i < 3; i++) {
+ for(j = 0; j < 6; j++)
+ cbuf[j] = buf[j][i+10] = ((i*6) + (j+1)) * -1;
+ if(H5DOappend(did, H5P_DEFAULT, 1, (size_t)1, H5T_NATIVE_INT, cbuf) < 0)
+ TEST_ERROR;
+ }
+
+ /* Verify the # of appends */
+ if(append_ct != 9)
+ TEST_ERROR;
+
+ /* Retrieve and verify object flush counts */
+ if(H5Pget_object_flush_cb(ffapl, NULL, (void **)&flush_ptr) < 0)
+ FAIL_STACK_ERROR;
+ if(*flush_ptr != 9)
+ TEST_ERROR;
+
+ /* Read the dataset */
+ if(H5Dread(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, rbuf) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Verify the data */
+ for(i = 0; i < 6; i++)
+ for(j = 0; j < 13; j++)
+ if(buf[i][j] != rbuf[i][j])
+ TEST_ERROR;
+
+#ifdef BUG1
+ HDmemset(rbuf, 0, sizeof(rbuf));
+
+ /* Close the dataset */
+ if(H5Dclose(did) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Open the dataset again */
+ if((did = H5Dopen(fid, DBUGNAME1, H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Read the dataset */
+ if(H5Dread(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, rbuf) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Verify the data */
+ for(i = 0; i < 6; i++)
+ for(j = 0; j < 13; j++)
+ if(buf[i][j] != rbuf[i][j])
+ TEST_ERROR;
+#endif
+
+ /* Closing */
+ if(H5Dclose(did) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Sclose(sid) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(dapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(dcpl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(ffapl) < 0)
+ FAIL_STACK_ERROR;
+
+ PASSED();
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(dcpl);
+ H5Pclose(dapl);
+ H5Pclose(sid);
+ H5Dclose(did);
+ H5Pclose(ffapl);
+ } H5E_END_TRY;
+
+ return 1;
+} /* test_dataset_append_BUG1() */
+
+/*-------------------------------------------------------------------------
+ * Function: test_dataset_append_BUG2
+ *
+ * Purpose: Verify that the object flush property and the append flush property
+ * are working properly when appending lines and columns to an
+ * extendible dataset.
+ * A BUG occurs:
+ * when the extendible dataset is set up as follows:
+ * hsize_t dims[2] = {0, 10};
+ * hsize_t maxdims[2] = {50, H5S_UNLIMITED};
+ * when append 6 lines and 3 columns to the dataset;
+ * The data is correct when the dataset is read at this point;
+ * The data is incorrect when the dataset is closed, opened again, and read at this point;
+ * NOTE: the problem does not occur when H5Dflush() is not performed for each line/column.
+ *
+ * Return: Success: 0
+ * Failure: 1
+ *
+ * Programmer: Vailin Choi; Jan 2014
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_dataset_append_BUG2(hid_t fid)
+{
+ hid_t did = -1; /* Dataset ID */
+ hid_t sid = -1; /* Dataspace ID */
+ hid_t dcpl = -1; /* Dataset creation property */
+ hid_t dapl = -1; /* Dataset access property */
+ hid_t ffapl = -1; /* The file's file access property list */
+
+ hsize_t dims[2] = {0, 10}; /* Current dimension sizes */
+ hsize_t maxdims[2] = {50, H5S_UNLIMITED}; /* Maximum dimension sizes */
+ hsize_t chunk_dims[2] = {2,5}; /* Chunk dimension sizes */
+ int lbuf[10], cbuf[6]; /* Data buffers */
+ int buf[6][13], rbuf[6][13]; /* Data buffers */
+ int i, j; /* Local index variables */
+
+ hsize_t boundary[2] = {1, 1}; /* Boundary sizes */
+ unsigned append_ct = 0; /* The # of appends */
+ unsigned *flush_ptr; /* Points to the flush counter */
+
+ TESTING("Append flush with H5DOappend()--append lines & columns--BUG2");
+
+ /* Get the file's file access property list */
+ if((ffapl = H5Fget_access_plist(fid)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Set to 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;
+
+ /* Set append flush property */
+ if((dapl = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pset_append_flush(dapl, 2, boundary, append_func, &append_ct) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Create the dataset */
+ if((did = H5Dcreate2(fid, DBUGNAME2, H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, dapl)) < 0)
+ TEST_ERROR;
+
+ /* Append 6 lines to the dataset */
+ for(i = 0; i < 6; i++) {
+ for(j = 0; j < 10; j++)
+ lbuf[j] = buf[i][j] = (i*10) + (j+1);
+ if(H5DOappend(did, H5P_DEFAULT, 0, (size_t)1, H5T_NATIVE_INT, lbuf) < 0)
+ TEST_ERROR;
+ }
+
+ /* Verify the # of appends */
+ if(append_ct != 6)
+ TEST_ERROR;
+
+ /* Retrieve and verify object flush counts */
+ if(H5Pget_object_flush_cb(ffapl, NULL, (void **)&flush_ptr) < 0)
+ FAIL_STACK_ERROR;
+ if(*flush_ptr != 6)
+ TEST_ERROR;
+
+
+ /* Append 3 columns to the dataset */
+ for(i = 0; i < 3; i++) {
+ for(j = 0; j < 6; j++)
+ cbuf[j] = buf[j][i+10] = ((i*6) + (j+1)) * -1;
+ if(H5DOappend(did, H5P_DEFAULT, 1, (size_t)1, H5T_NATIVE_INT, cbuf) < 0)
+ TEST_ERROR;
+ }
+
+ /* Verify the # of appends */
+ if(append_ct != 9)
+ TEST_ERROR;
+
+ /* Retrieve and verify object flush counts */
+ if(H5Pget_object_flush_cb(ffapl, NULL, (void **)&flush_ptr) < 0)
+ FAIL_STACK_ERROR;
+ if(*flush_ptr != 9)
+ TEST_ERROR;
+
+ /* Read the dataset */
+ if(H5Dread(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, rbuf) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Verify the data */
+ for(i = 0; i < 6; i++)
+ for(j = 0; j < 13; j++)
+ if(buf[i][j] != rbuf[i][j])
+ TEST_ERROR;
+
+#ifdef BUG2
+ HDmemset(rbuf, 0, sizeof(rbuf));
+
+ /* Close the dataset */
+ if(H5Dclose(did) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Open the dataset again */
+ if((did = H5Dopen(fid, DBUGNAME2, H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Read the dataset */
+ if(H5Dread(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, rbuf) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Verify the data */
+ for(i = 0; i < 6; i++)
+ for(j = 0; j < 13; j++)
+ if(buf[i][j] != rbuf[i][j])
+ TEST_ERROR;
+#endif
+
+ /* Closing */
+ if(H5Dclose(did) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Sclose(sid) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(dapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(dcpl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(ffapl) < 0)
+ FAIL_STACK_ERROR;
+
+ PASSED();
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(dcpl);
+ H5Pclose(dapl);
+ H5Pclose(sid);
+ H5Dclose(did);
+ H5Pclose(ffapl);
+ } H5E_END_TRY;
+
+ return 1;
+} /* test_dataset_append_BUG2() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_dataset_append_less
+ *
+ * Purpose: Verify that the object flush property and the append flush property
+ * are working properly when appending lines and columns to an
+ * extendible dataset where the append size is less than the boundary
+ * size.
+ *
+ * Return: Success: 0
+ * Failure: 1
+ *
+ * Programmer: Vailin Choi; Jan 2014
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_dataset_append_less(hid_t fid)
+{
+ hid_t did = -1; /* Dataset ID */
+ hid_t sid = -1; /* Dataspace ID */
+ hid_t dcpl = -1; /* A copy of dataset creation property */
+ hid_t dapl = -1; /* A copy of dataset access property */
+ hid_t ffapl = -1; /* The file's file access property list */
+
+ hsize_t dims[2] = {0, 10}; /* Current dimension sizes */
+ hsize_t maxdims[2] = {100, 100}; /* Maximum dimension sizes */
+ hsize_t chunk_dims[2] = {2,5}; /* Chunk dimension sizes */
+ int lbuf[20], cbuf[6][3]; /* Data buffers */
+ int buf[6][13], rbuf[6][13]; /* Data buffers */
+ int i, j, k; /* Local index variables */
+
+ hsize_t boundary[2] = {3, 3}; /* Boundary sizes */
+ unsigned append_ct = 0; /* The # of appends */
+ unsigned *flush_ptr; /* Points to the flush counter */
+
+ TESTING("Append flush with H5DOappend()--append size < boundary size");
+
+ /* Get the file's file access property list */
+ if((ffapl = H5Fget_access_plist(fid)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Set to 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;
+
+ /* Set append flush property */
+ if((dapl = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pset_append_flush(dapl, 2, boundary, append_func, &append_ct) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Create the dataset */
+ if((did = H5Dcreate2(fid, DNAME_LESS, H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, dapl)) < 0)
+ TEST_ERROR;
+
+ /* Append to the dataset 2 lines at a time for 3 times */
+ for(i = 0, k = 0; i < 6; i++) {
+ for(j = 0; j < 10; j++, k++)
+ buf[i][j] = lbuf[k] = (i*10) + (j+1);
+
+ if((i + 1) % 2 == 0) {
+ if(H5DOappend(did, H5P_DEFAULT, 0, (size_t)2, H5T_NATIVE_INT, lbuf) < 0)
+ TEST_ERROR;
+ k = 0;
+ }
+ }
+
+ /* Verify the # of appends */
+ if(append_ct != 2)
+ TEST_ERROR;
+
+ /* Retrieve and verify object flush counts */
+ if(H5Pget_object_flush_cb(ffapl, NULL, (void **)&flush_ptr) < 0)
+ FAIL_STACK_ERROR;
+ if(*flush_ptr != 2)
+ TEST_ERROR;
+
+ /* Append to the dataset 3 columns at a time for 1 time */
+ for(i = 0; i < 3; i++) {
+ for(j = 0; j < 6; j++, k++)
+ cbuf[j][i] = buf[j][i+10] = ((i*6) + (j+1)) * -1;
+ }
+ if(H5DOappend(did, H5P_DEFAULT, 1, (size_t)3, H5T_NATIVE_INT, cbuf) < 0)
+ TEST_ERROR;
+
+ /* Verify the # of appends */
+ if(append_ct != 3)
+ TEST_ERROR;
+
+ /* Retrieve and verify object flush counts */
+ if(H5Pget_object_flush_cb(ffapl, NULL, (void **)&flush_ptr) < 0)
+ FAIL_STACK_ERROR;
+ if(*flush_ptr != 3)
+ TEST_ERROR;
+
+ /* Read the dataset */
+ if(H5Dread(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, rbuf) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Verify the data */
+ for(i = 0; i < 6; i++)
+ for(j = 0; j < 13; j++)
+ if(buf[i][j] != rbuf[i][j])
+ TEST_ERROR;
+
+ /* Clear the buffer */
+ HDmemset(rbuf, 0, sizeof(rbuf));
+
+ /* Close the dataset */
+ if(H5Dclose(did) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Open the dataset again */
+ if((did = H5Dopen(fid, DNAME_LESS, H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Read the dataset */
+ if(H5Dread(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, rbuf) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Verify the data */
+ for(i = 0; i < 6; i++)
+ for(j = 0; j < 13; j++)
+ if(buf[i][j] != rbuf[i][j])
+ TEST_ERROR;
+
+ /* Closing */
+ if(H5Dclose(did) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Sclose(sid) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(dapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(dcpl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(ffapl) < 0)
+ FAIL_STACK_ERROR;
+
+ PASSED();
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(dapl);
+ H5Pclose(dcpl);
+ H5Pclose(sid);
+ H5Dclose(did);
+ H5Pclose(ffapl);
+ } H5E_END_TRY;
+
+ return 1;
+} /* test_dataset_append_less() */
+
+/*-------------------------------------------------------------------------
+ * Function: test_dataset_append_vary
+ *
+ * Purpose: Verify that the object flush property and the append flush property
+ * are working properly when appending lines and columns to an
+ * extendible dataset where
+ * line: the append size is 3 times of the boundary size
+ * the append callback/flush is performed on the 1st boundary hit
+ * column: the boundary is greater than the append size
+ * the boundary is not hit at all
+ *
+ * Return: Success: 0
+ * Failure: 1
+ *
+ * Programmer: Vailin Choi; Jan 2014
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_dataset_append_vary(hid_t fid)
+{
+ hid_t did = -1; /* Dataset ID */
+ hid_t sid = -1; /* Dataspace ID */
+ hid_t dcpl = -1; /* A copy of dataset creation property */
+ hid_t dapl = -1; /* A copy of dataset access property */
+ hid_t ffapl = -1; /* The file's file access property list */
+
+ hsize_t dims[2] = {0, 10}; /* Current dimension sizes */
+ hsize_t maxdims[2] = {H5S_UNLIMITED, H5S_UNLIMITED}; /* Maximum dimension sizes */
+ hsize_t chunk_dims[2] = {2,5}; /* Chunk dimension sizes */
+ int lbuf[60], cbuf[6][3]; /* Data buffers */
+ int buf[6][13], rbuf[6][13]; /* Data buffers */
+ int i, j, k; /* Local index variables */
+
+ hsize_t boundary[2] = {3, 7}; /* Boundary sizes */
+ unsigned append_ct = 0; /* The # of appends */
+ unsigned *flush_ptr; /* Points to the flush counter */
+
+ TESTING("Append flush with H5DOappend()--append & boundary size vary");
+
+ /* Get the file's file access property list */
+ if((ffapl = H5Fget_access_plist(fid)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Set to 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;
+
+ /* Set append flush property */
+ if((dapl = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pset_append_flush(dapl, 2, boundary, append_func, &append_ct) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Create the dataset */
+ if((did = H5Dcreate2(fid, DNAME_VARY, H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, dapl)) < 0)
+ TEST_ERROR;
+
+ /* Append to the dataset 6 lines at a time for 1 time */
+ for(i = 0, k = 0; i < 6; i++) {
+ for(j = 0; j < 10; j++, k++)
+ buf[i][j] = lbuf[k] = (i*10) + (j+1);
+ }
+ if(H5DOappend(did, H5P_DEFAULT, 0, (size_t)6, H5T_NATIVE_INT, lbuf) < 0)
+ TEST_ERROR;
+
+ /* Verify the # of appends */
+ if(append_ct != 1)
+ TEST_ERROR;
+
+ /* Retrieve and verify object flush counts */
+ if(H5Pget_object_flush_cb(ffapl, NULL, (void **)&flush_ptr) < 0)
+ FAIL_STACK_ERROR;
+ if(*flush_ptr != 1)
+ TEST_ERROR;
+
+ /* Append to the dataset 3 columns at a time for 1 time */
+ for(i = 0; i < 3; i++) {
+ for(j = 0; j < 6; j++, k++)
+ cbuf[j][i] = buf[j][i+10] = ((i*6) + (j+1)) * -1;
+ }
+ if(H5DOappend(did, H5P_DEFAULT, 1, (size_t)3, H5T_NATIVE_INT, cbuf) < 0)
+ TEST_ERROR;
+
+ /* Verify the # of appends */
+ if(append_ct != 1)
+ TEST_ERROR;
+
+ /* Retrieve and verify object flush counts */
+ if(H5Pget_object_flush_cb(ffapl, NULL, (void **)&flush_ptr) < 0)
+ FAIL_STACK_ERROR;
+ if(*flush_ptr != 1)
+ TEST_ERROR;
+
+ /* Read the dataset */
+ if(H5Dread(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, rbuf) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Verify the data */
+ for(i = 0; i < 6; i++)
+ for(j = 0; j < 13; j++)
+ if(buf[i][j] != rbuf[i][j])
+ TEST_ERROR;
+
+ /* Clear the dataset */
+ HDmemset(rbuf, 0, sizeof(rbuf));
+
+ /* Close the dataset */
+ if(H5Dclose(did) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Open the dataset again */
+ if((did = H5Dopen(fid, DNAME_VARY, H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Read the dataset */
+ if(H5Dread(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, rbuf) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Verify the data */
+ for(i = 0; i < 6; i++)
+ for(j = 0; j < 13; j++)
+ if(buf[i][j] != rbuf[i][j])
+ TEST_ERROR;
+
+ /* Closing */
+ if(H5Dclose(did) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Sclose(sid) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(dapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(dcpl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(ffapl) < 0)
+ FAIL_STACK_ERROR;
+
+ PASSED();
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(dapl);
+ H5Pclose(dcpl);
+ H5Pclose(sid);
+ H5Dclose(did);
+ H5Pclose(ffapl);
+ } H5E_END_TRY;
+
+ return 1;
+} /* test_dataset_append_vary() */
+
+/*-------------------------------------------------------------------------
+ * Function: Main function
+ *
+ * Purpose: Test H5Pset/get_object_flush_cb() and H5Pset/get_append_flush()
+ * along with H5DOappend().
+ *
+ * Return: Success: 0
+ * Failure: 1
+ *
+ * Programmer: Vailin Choi; Jan 2014
+ *
+ *-------------------------------------------------------------------------
+ */
+int main(void)
+{
+ hid_t fid = -1; /* File ID */
+ hid_t fapl = -1; /* File access property list */
+ unsigned flush_ct = 0; /* The # of flushes */
+ int nerrors = 0; /* The # of errors encountered */
+
+ /* Get a copy of file access property list */
+ if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 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 object flush property */
+ if(H5Pset_object_flush_cb(fapl, flush_func, &flush_ct) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Create the test file */
+ if((fid = H5Fcreate(FILE, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ nerrors += test_dataset_append_lines_columns(fid);
+
+ flush_ct = 0; /* Reset flush counter */
+ nerrors += test_dataset_append_lines(fid);
+
+ flush_ct = 0; /* Reset flush counter */
+ nerrors += test_dataset_append_columns(fid);
+
+ flush_ct = 0; /* Reset flush counter */
+ nerrors += test_dataset_append_BUG1(fid);
+
+ flush_ct = 0; /* Reset flush counter */
+ nerrors += test_dataset_append_BUG2(fid);
+
+ flush_ct = 0; /* Reset flush counter */
+ nerrors += test_dataset_append_less(fid);
+
+ flush_ct = 0; /* Reset flush counter */
+ nerrors += test_dataset_append_vary(fid);
+
+ /* Closing */
+ if(H5Pclose(fapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Check for errors */
+ if(nerrors)
+ goto error;
+
+ return 0;
+
+error:
+ return 1;
+}
diff --git a/hl/test/test_file_image.c b/hl/test/test_file_image.c
index 831fa23..22ddd1a 100644
--- a/hl/test/test_file_image.c
+++ b/hl/test/test_file_image.c
@@ -20,6 +20,12 @@
#define RANK 2
+/* For superblock version 0, 1: the offset to "file consistency flags" is 20 with size of 4 bytes */
+/* The file consistency flags is the "status_flags" field in H5F_super_t */
+/* Note: the offset and size will be different when using superblock version 2 for the test file */
+#define SUPER_STATUS_FLAGS_OFF_V0_V1 20
+#define SUPER_STATUS_FLAGS_SIZE_V0_V1 4
+
/* Test of file image operations.
The following code provides a means to thoroughly test the file image
@@ -158,7 +164,7 @@ test_file_image(size_t open_images, size_t nflags, unsigned *flags)
FAIL_PUTS_ERROR("H5Dclose() failed");
/* get size of the file image i */
- if ((buf_size[i] = H5Fget_file_image(file_id[i], NULL, 0)) < 0)
+ if ((buf_size[i] = H5Fget_file_image(file_id[i], NULL, (size_t)0)) < 0)
FAIL_PUTS_ERROR("H5Fget_file_image() failed");
/* allocate buffer for the file image i */
@@ -214,10 +220,32 @@ test_file_image(size_t open_images, size_t nflags, unsigned *flags)
else
VERIFY(*core_buf_ptr_ptr != buf_ptr[i], "vfd buffer and user buffer should be different");
- /* test whether the contents of the user buffer and driver buffer */
- /* are equal. */
- if (HDmemcmp(*core_buf_ptr_ptr, buf_ptr[i], (size_t)buf_size[i]) != 0)
- FAIL_PUTS_ERROR("comparison of vfd and user buffer failed");
+ /*
+ * When the vfd and user buffers are different and H5LT_FILE_IMAGE_OPEN_RW is enabled,
+ * status_flags in the superblock needs to be cleared in the vfd buffer for
+ * the comparison to proceed as expected. The user buffer as returned from H5Fget_file_image()
+ * has already cleared status_flags. The superblock's status_flags is used for the
+ * implementation of file locking.
+ */
+ if(input_flags[i] & H5LT_FILE_IMAGE_OPEN_RW && !(input_flags[i] & H5LT_FILE_IMAGE_DONT_COPY)) {
+
+ void *tmp_ptr = HDmalloc((size_t)buf_size[i]);
+ /* Copy vfd buffer to a temporary buffer */
+ HDmemcpy(tmp_ptr, (void *)*core_buf_ptr_ptr, (size_t)buf_size[i]);
+ /* Clear status_flags in the superblock for the vfd buffer: file locking is using status_flags */
+ HDmemset((uint8_t *)tmp_ptr + SUPER_STATUS_FLAGS_OFF_V0_V1, (int)0, (size_t)SUPER_STATUS_FLAGS_SIZE_V0_V1);
+ /* Does the comparision */
+ if(HDmemcmp(tmp_ptr, buf_ptr[i], (size_t)buf_size[i]) != 0)
+ FAIL_PUTS_ERROR("comparison of TMP vfd and user buffer failed");
+ /* Free the temporary buffer */
+ if(tmp_ptr) HDfree(tmp_ptr);
+ } else {
+
+ /* test whether the contents of the user buffer and driver buffer */
+ /* are equal. */
+ if (HDmemcmp(*core_buf_ptr_ptr, buf_ptr[i], (size_t)buf_size[i]) != 0)
+ FAIL_PUTS_ERROR("comparison of vfd and user buffer failed");
+ }
} /* end else */
} /* end for */
diff --git a/hl/test/test_ld.h5 b/hl/test/test_ld.h5
index 40c4ff0..db34c25 100644
--- a/hl/test/test_ld.h5
+++ b/hl/test/test_ld.h5
Binary files differ
diff --git a/hl/test/test_ld.sh.in b/hl/test/test_ld.sh.in
index 69beea6..b263f2a 100644
--- a/hl/test/test_ld.sh.in
+++ b/hl/test/test_ld.sh.in
@@ -21,14 +21,14 @@ DEPRECATED_SYMBOLS="@DEPRECATED_SYMBOLS@"
CMP='cmp -s'
DIFF='diff -c'
-CP='cp'
-KILL='kill'
-SLEEP='sleep'
-LD_MONITOR=ld_monitor
+LD_MONITOR='ld_mx -m'
LD_MONITOR_BIN=`pwd`/$LD_MONITOR
-LD_EXTEND=ld_extend
+LD_EXTEND='ld_mx -x'
LD_EXTEND_BIN=`pwd`/$LD_EXTEND
-
+# These two message files should be the same as the two defines in ./ld_mx.c
+READER_MESSAGE='LD_READER_MESSAGE'
+WRITER_MESSAGE='LD_WRITER_MESSAGE'
+#
nerrors=0
verbose=yes
@@ -51,18 +51,24 @@ TESTING() {
# $2 -- the dataset name to be monitored and extended
# $3 -- the expected output from monitoring the dataset
TESTLD() {
- expect="$srcdir/testfiles/$3" # the expected output
- actual="./testfiles/$3.OUT" # the actual output
- FNAME="`basename $1 .h5`_$2.h5" # the HDF5 file
- $CP $srcdir/$1 ./$FNAME # copy the file to a temporary file
+ expect="$srcdir/testfiles/$3" # the expected output
+ actual="./testfiles/$3.OUT" # the actual output
+ FNAME="`basename $1 .h5`_$2.h5" # the HDF5 file
+ cp $srcdir/$1 ./$FNAME # copy the file to a temporary file
+#
+ rm -f $WRITER_MESSAGE # remove the message file just to be sure
+ rm -f $READER_MESSAGE # remove the message file just to be sure
+#
+ $LD_EXTEND_BIN $FNAME $2 & # extend the dataset
+ EXTEND_PID=$! # get the id of the "extend" process
$LD_MONITOR_BIN $FNAME $2 > $actual 2>&1 & # monitor the dataset in the file
- MONITOR_PID=$! # get the id of the monitor process
- $LD_EXTEND_BIN $FNAME $2 # extend the dataset
- echo "Sleeping for 3 seconds..."
- $SLEEP 3 # sleep to allow output to be flushed
- echo "Killing the monitor..."
- $KILL $MONITOR_PID # kill the monitor process
- if $CMP $expect $actual; then # compare the output with the expected output
+ MONITOR_PID=$! # get the id of the "monitor" process
+ wait $EXTEND_PID # wait for the completion of the "extend" process
+#
+ sleep 1 # sleep to ensure that the monitoring completes
+ kill $MONITOR_PID # kill the "monitor" process
+#
+ if $CMP $expect $actual; then # compare the output with the expected output
echo " PASSED"
else
echo "*FAILED*"
@@ -70,7 +76,7 @@ TESTLD() {
nerrors="`expr $nerrors + 1`"
test yes = "$verbose" && $DIFF $expect $actual |sed 's/^/ /'
fi
- if test -z "$HDF5_NOCLEANUP"; then # clean up output file, temporary HDF5 file
+ if test -z "$HDF5_NOCLEANUP"; then # clean up output file, temporary HDF5 file
rm -f $actual $FNAME
fi
}
@@ -84,9 +90,11 @@ TESTLD() {
# Monitor DSET_ONE while extending the dataset
TESTLD test_ld.h5 DSET_ONE test_ld_out1
#
+#
# Monitor DSET_TWO while extending the dataset
TESTLD test_ld.h5 DSET_TWO test_ld_out2
-
+#
+#
if test $nerrors -eq 0 ; then
echo "All high level H5LD concurrent tests passed."
fi
diff --git a/hl/test/test_table_be.h5 b/hl/test/test_table_be.h5
index 3639695..970018e 100644
--- a/hl/test/test_table_be.h5
+++ b/hl/test/test_table_be.h5
Binary files differ
diff --git a/hl/test/test_table_cray.h5 b/hl/test/test_table_cray.h5
index d22dce3..1fcd75b 100644
--- a/hl/test/test_table_cray.h5
+++ b/hl/test/test_table_cray.h5
Binary files differ
diff --git a/hl/test/test_table_le.h5 b/hl/test/test_table_le.h5
index 6c330fd..ee5b532 100644
--- a/hl/test/test_table_le.h5
+++ b/hl/test/test_table_le.h5
Binary files differ
diff --git a/hl/tools/h5watch/h5watch.c b/hl/tools/h5watch/h5watch.c
index d2a117d..b233055 100644
--- a/hl/tools/h5watch/h5watch.c
+++ b/hl/tools/h5watch/h5watch.c
@@ -30,6 +30,7 @@
#define FIELD_SEP "," /* nested field separator */
#define DEFAULT_RETRY 10 /* number of times to try opening the file */
+
/*
* Note:(see comments in hl/src/H5LDprivate.h)
* This tool uses private routines H5LD_construct_vector()and H5LD_clean_vector()
@@ -108,7 +109,6 @@ static struct long_options l_opts[] = {
{ NULL, 0, '\0' }
};
-
/*-------------------------------------------------------------------------
* Function: doprint()
*
diff --git a/hl/tools/h5watch/testh5watch.sh.in b/hl/tools/h5watch/testh5watch.sh.in
index 377dd89..7a9ce94 100644
--- a/hl/tools/h5watch/testh5watch.sh.in
+++ b/hl/tools/h5watch/testh5watch.sh.in
@@ -191,7 +191,7 @@ TEST_WATCH() {
wait $extend_pid # Wait for "extend" process to complete
extend_exit=$? # Collect "extend" process' exit code
sleep 1 # Sleep to make sure output is flushed
- kill $watch_pid # Kill h5watch
+ kill $watch_pid # Kill h5watch
#
if [ $extend_exit -ne 0 ]; then # Error returned from "extend" process
$ECHO "*FAILED*"
diff --git a/src/H5AC.c b/src/H5AC.c
index 46b5785..18da8de 100644
--- a/src/H5AC.c
+++ b/src/H5AC.c
@@ -730,6 +730,39 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5AC_evict
+ *
+ * Purpose: Evict all entries except the pinned entries
+ * in the cache.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Vailin Choi; Dec 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5AC_evict(H5F_t *f, hid_t dxpl_id)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(f->shared->cache);
+
+ /* Evict all entries in the cache except the pinned superblock entry */
+ if(H5C_evict(f, dxpl_id, H5AC_noblock_dxpl_id) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFREE, FAIL, "can't evict cache")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5AC_evict() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5AC_expunge_entry
*
* Purpose: Expunge the target entry from the cache without writing it
diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h
index ae4b9fc..acb3adc 100644
--- a/src/H5ACprivate.h
+++ b/src/H5ACprivate.h
@@ -333,6 +333,7 @@ H5_DLLVAR hid_t H5AC_ind_dxpl_id;
#define H5AC__TAKE_OWNERSHIP_FLAG H5C__TAKE_OWNERSHIP_FLAG
#define H5AC__FLUSH_LAST_FLAG H5C__FLUSH_LAST_FLAG
#define H5AC__FLUSH_COLLECTIVELY_FLAG H5C__FLUSH_COLLECTIVELY_FLAG
+#define H5AC__EVICT_ALLOW_LAST_PINS_FLAG H5C__EVICT_ALLOW_LAST_PINS_FLAG
/* #defines of flags used to report entry status in the
@@ -371,6 +372,7 @@ H5_DLL herr_t H5AC_move_entry(H5F_t *f, const H5AC_class_t *type,
haddr_t old_addr, haddr_t new_addr);
H5_DLL herr_t H5AC_dest(H5F_t *f, hid_t dxpl_id);
+H5_DLL herr_t H5AC_evict(H5F_t *f, hid_t dxpl_id);
H5_DLL herr_t H5AC_expunge_entry(H5F_t *f, hid_t dxpl_id,
const H5AC_class_t *type, haddr_t addr,
diff --git a/src/H5C.c b/src/H5C.c
index a76dbc4..cd2345c 100644
--- a/src/H5C.c
+++ b/src/H5C.c
@@ -1561,7 +1561,41 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5C_evict
*
+ * Purpose: Evict all except pinned entries in the cache
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Vailin Choi; Dec 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_evict(H5F_t * f,
+ hid_t primary_dxpl_id,
+ hid_t secondary_dxpl_id)
+{
+ H5C_t *cache_ptr = f->shared->cache;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+
+ /* Flush and invalidate all cache entries except the pinned entries */
+ if(H5C_flush_invalidate_cache(f, primary_dxpl_id, secondary_dxpl_id,
+ H5C__EVICT_ALLOW_LAST_PINS_FLAG) < 0 )
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to evict entries in the cache")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_evict() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5C_expunge_entry
*
* Purpose: Use this function to tell the cache to expunge an entry
@@ -7534,6 +7568,7 @@ H5C_flush_invalidate_cache(H5F_t * f,
int32_t cur_pel_len;
int32_t old_pel_len;
unsigned cooked_flags;
+ unsigned evict_flags;
H5SL_node_t * node_ptr = NULL;
H5C_cache_entry_t * entry_ptr = NULL;
H5C_cache_entry_t * next_entry_ptr = NULL;
@@ -7556,6 +7591,7 @@ H5C_flush_invalidate_cache(H5F_t * f,
* At present, only the H5C__FLUSH_CLEAR_ONLY_FLAG is kept.
*/
cooked_flags = flags & H5C__FLUSH_CLEAR_ONLY_FLAG;
+ evict_flags = flags & H5C__EVICT_ALLOW_LAST_PINS_FLAG;
/* remove ageout markers if present */
if ( cache_ptr->epoch_markers_active > 0 ) {
@@ -7932,6 +7968,8 @@ end_of_inner_loop:
if ( ( cur_pel_len > 0 ) && ( cur_pel_len >= old_pel_len ) ) {
+ if(evict_flags) HGOTO_DONE(TRUE)
+
/* The number of pinned entries is positive, and it is not
* declining. Scream and die.
*/
@@ -9664,7 +9702,6 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5C__mark_flush_dep_clean() */
-
#ifndef NDEBUG
/*-------------------------------------------------------------------------
diff --git a/src/H5Cprivate.h b/src/H5Cprivate.h
index b3aab86..581e89d 100644
--- a/src/H5Cprivate.h
+++ b/src/H5Cprivate.h
@@ -1069,6 +1069,7 @@ typedef struct H5C_auto_size_ctl_t
#define H5C__TAKE_OWNERSHIP_FLAG 0x1000
#define H5C__FLUSH_LAST_FLAG 0x2000
#define H5C__FLUSH_COLLECTIVELY_FLAG 0x4000
+#define H5C__EVICT_ALLOW_LAST_PINS_FLAG 0x8000
#ifdef H5_HAVE_PARALLEL
H5_DLL herr_t H5C_apply_candidate_list(H5F_t * f,
@@ -1106,6 +1107,9 @@ H5_DLL void H5C_def_auto_resize_rpt_fcn(H5C_t * cache_ptr,
H5_DLL herr_t H5C_dest(H5F_t * f,
hid_t primary_dxpl_id,
hid_t secondary_dxpl_id);
+H5_DLL herr_t H5C_evict(H5F_t * f,
+ hid_t primary_dxpl_id,
+ hid_t secondary_dxpl_id);
H5_DLL herr_t H5C_expunge_entry(H5F_t * f,
hid_t primary_dxpl_id,
diff --git a/src/H5D.c b/src/H5D.c
index 0eff024..ee251bf 100644
--- a/src/H5D.c
+++ b/src/H5D.c
@@ -766,12 +766,21 @@ H5Dget_access_plist(hid_t dset_id)
/* If the dataset is chunked then copy the rdcc parameters */
if (dset->shared->layout.type == H5D_CHUNKED) {
+ H5D_append_flush_t info;
+
if (H5P_set(new_plist, H5D_ACS_DATA_CACHE_NUM_SLOTS_NAME, &(dset->shared->cache.chunk.nslots)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set data cache number of slots")
if (H5P_set(new_plist, H5D_ACS_DATA_CACHE_BYTE_SIZE_NAME, &(dset->shared->cache.chunk.nbytes_max)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set data cache byte size")
if (H5P_set(new_plist, H5D_ACS_PREEMPT_READ_CHUNKS_NAME, &(dset->shared->cache.chunk.w0)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set preempt read chunks")
+
+ info.ndims = dset->shared->append_flush.ndims;
+ info.func = dset->shared->append_flush.func;
+ info.udata = dset->shared->append_flush.udata;
+ HDmemcpy(info.boundary, dset->shared->append_flush.boundary, sizeof(dset->shared->append_flush.boundary));
+ if(H5P_set(new_plist, H5D_ACS_APPEND_FLUSH_NAME, &info) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set append flush property")
} /* end if */
/* Set the return value */
@@ -1176,9 +1185,8 @@ H5Dflush(hid_t dset_id)
if(H5D__flush_real(dset, H5AC_dxpl_id) < 0)
HDONE_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to flush cached dataset info")
- /* Call private function to flush dataset object */
- if (H5O_flush_metadata(&dset->oloc, H5AC_dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTFLUSH, FAIL, "unable to flush dataset")
+ if(H5O_flush_common(&dset->oloc, dset_id) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTFLUSH, FAIL, "unable to flush dataset and object flush callback")
done:
FUNC_LEAVE_API(ret_value)
diff --git a/src/H5Dint.c b/src/H5Dint.c
index cbab788..71af859 100644
--- a/src/H5Dint.c
+++ b/src/H5Dint.c
@@ -70,7 +70,7 @@ static herr_t H5D__update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset,
static herr_t H5D__open_oid(H5D_t *dataset, hid_t dapl_id, hid_t dxpl_id);
static herr_t H5D__init_storage(H5D_t *dataset, hbool_t full_overwrite,
hsize_t old_dim[], hid_t dxpl_id);
-
+static herr_t H5D__append_flush_setup(H5D_t *dset, hid_t dapl_id);
/*********************/
/* Package Variables */
@@ -1163,6 +1163,9 @@ H5D__create(H5F_t *file, hid_t type_id, const H5S_t *space, hid_t dcpl_id,
/* Indicate that the layout information was initialized */
layout_init = TRUE;
+ if(H5D__append_flush_setup(new_dset, dapl_id) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINC, NULL, "unable to set up flush append property")
+
/* Add the dataset to the list of opened objects in the file */
if(H5FO_top_incr(new_dset->oloc.file, new_dset->oloc.addr) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINC, NULL, "can't incr object ref. count")
@@ -1264,6 +1267,7 @@ H5D_open(const H5G_loc_t *loc, hid_t dapl_id, hid_t dxpl_id)
/* We're the first dataset to use the the shared info */
dataset->shared->fo_count = 1;
+
} /* end if */
else {
/* Point to shared info */
@@ -1282,6 +1286,7 @@ H5D_open(const H5G_loc_t *loc, hid_t dapl_id, hid_t dxpl_id)
/* Increment object count for the object in the top file */
if(H5FO_top_incr(dataset->oloc.file, dataset->oloc.addr) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINC, NULL, "can't increment object count")
+
} /* end else */
ret_value = dataset;
@@ -1306,6 +1311,84 @@ done:
} /* end H5D_open() */
+/*
+ *-------------------------------------------------------------------------
+ * Function: H5D__flush_append_setup
+ *
+ * Purpose:
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D__append_flush_setup(H5D_t *dset, hid_t dapl_id)
+{
+ H5P_genplist_t *dapl; /* data access property list object pointer */
+ hsize_t curr_dims[H5S_MAX_RANK]; /* current dimension sizes */
+ hsize_t max_dims[H5S_MAX_RANK]; /* current dimension sizes */
+ int rank; /* dataspace # of dimensions */
+ int i; /* local index variable */
+ H5D_append_flush_t info;
+ herr_t ret_value = SUCCEED; /* return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* check args */
+ HDassert(dset);
+ HDassert(dset->shared);
+
+ dset->shared->append_flush.ndims = 0;
+ dset->shared->append_flush.func = NULL;
+ dset->shared->append_flush.udata = NULL;
+ HDmemset(dset->shared->append_flush.boundary, 0, sizeof(dset->shared->append_flush.boundary));
+
+ if(dapl_id != H5P_DATASET_ACCESS_DEFAULT && dset->shared->layout.type == H5D_CHUNKED) {
+ /* Get dataset access property list */
+ if(NULL == (dapl = (H5P_genplist_t *)H5I_object(dapl_id)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for dapl ID");
+
+ /* Check if append flush property exists */
+ if(H5P_exist_plist(dapl, H5D_ACS_APPEND_FLUSH_NAME) > 0) {
+
+ /* Get append flush property */
+ if(H5P_get(dapl, H5D_ACS_APPEND_FLUSH_NAME, &info) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get append flush info")
+ else if(info.ndims > 0) {
+
+ /* Get dataset rank */
+ if((rank = H5S_get_simple_extent_dims(dset->shared->space, curr_dims, max_dims)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get dataset dimensions")
+
+ if(info.ndims != rank)
+ HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "boundary dimension rank does not match dataset rank")
+
+ /* Validate boundary sizes */
+ for(i = 0; i < info.ndims; i++) {
+ if(info.boundary[i] != 0) /* when a non-zero boundary is set */
+ /* the dimension is extendible? */
+ if(max_dims[i] != H5S_UNLIMITED && max_dims[i] == curr_dims[i])
+ break;
+ }
+
+ if(i != info.ndims) /* at least one boundary dimension is not extendible */
+ HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "boundary dimension is not valid")
+
+ dset->shared->append_flush.ndims = info.ndims;
+ dset->shared->append_flush.func = info.func;
+ dset->shared->append_flush.udata = info.udata;
+ HDmemcpy(dset->shared->append_flush.boundary, info.boundary, sizeof(info.boundary));
+ }
+ }
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D__append_flush_setup() */
+
+
/*-------------------------------------------------------------------------
* Function: H5D__open_oid
*
@@ -1325,6 +1408,7 @@ H5D__open_oid(H5D_t *dataset, hid_t dapl_id, hid_t dxpl_id)
H5O_fill_t *fill_prop; /* Pointer to dataset's fill value info */
unsigned alloc_time_state; /* Allocation time state */
htri_t msg_exists; /* Whether a particular type of message exists */
+ hbool_t layout_init = FALSE; /* Flag to indicate that chunk information was initialized */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC_TAG(dxpl_id, dataset->oloc.addr, FAIL)
@@ -1362,6 +1446,13 @@ H5D__open_oid(H5D_t *dataset, hid_t dapl_id, hid_t dxpl_id)
if(H5D__layout_oh_read(dataset, dxpl_id, dapl_id, plist) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get layout/pline/efl info")
+ /* Indicate that the layout information was initialized */
+ layout_init = TRUE;
+
+ /* Set up flush append property */
+ if(H5D__append_flush_setup(dataset, dapl_id))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINC, FAIL, "unable to set up flush append property")
+
/* Point at dataset's copy, to cache it for later */
fill_prop = &dataset->shared->dcpl_cache.fill;
@@ -1441,6 +1532,10 @@ done:
if(H5F_addr_defined(dataset->oloc.addr) && H5O_close(&(dataset->oloc)) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release object header")
if(dataset->shared) {
+ if(dataset->shared->layout.type == H5D_CHUNKED && layout_init) {
+ if(H5D__chunk_dest(dataset->oloc.file, dxpl_id, dataset) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "unable to destroy chunk cache")
+ } /* end if */
if(dataset->shared->space && H5S_close(dataset->shared->space) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataspace")
if(dataset->shared->type) {
diff --git a/src/H5Doh.c b/src/H5Doh.c
index df4eed2..b7706b3 100644
--- a/src/H5Doh.c
+++ b/src/H5Doh.c
@@ -55,7 +55,7 @@ static void *H5O__dset_create(H5F_t *f, void *_crt_info, H5G_loc_t *obj_loc,
static H5O_loc_t *H5O__dset_get_oloc(hid_t obj_id);
static herr_t H5O__dset_bh_info(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
H5_ih_info_t *bh_info);
-static herr_t H5O__dset_flush(H5G_loc_t *obj_loc, hid_t dxpl_id);
+static herr_t H5O__dset_flush(void *_obj_ptr, hid_t dxpl_id);
/*********************/
@@ -457,34 +457,25 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5O__dset_flush(H5G_loc_t *obj_loc, hid_t dxpl_id)
+H5O__dset_flush(void *_obj_ptr, hid_t dxpl_id)
{
- H5D_t *dset = NULL; /* Dataset opened */
- H5O_type_t obj_type; /* Type of object at location */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5D_t *dset = (H5D_t *)_obj_ptr; /* Pointer to dataset object */
+ H5O_type_t obj_type; /* Type of object at location */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
- HDassert(obj_loc);
- HDassert(obj_loc->oloc);
+ HDassert(dset);
+ HDassert(&dset->oloc);
/* Check that the object found is the correct type */
- if(H5O_obj_type(obj_loc->oloc, &obj_type, dxpl_id) < 0)
+ if(H5O_obj_type(&dset->oloc, &obj_type, dxpl_id) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get object type")
-
if(obj_type != H5O_TYPE_DATASET)
HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, FAIL, "not a dataset")
- /* Open the dataset */
- if(NULL == (dset = H5D_open(obj_loc, H5P_DATASET_ACCESS_DEFAULT, dxpl_id)))
- HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "unable to open dataset")
-
if(H5D__flush_real(dset, dxpl_id) < 0)
HDONE_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to flush cached dataset info")
-
done:
- if(dset && H5D_close(dset) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataset")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O__dset_flush() */
-
diff --git a/src/H5Dpkg.h b/src/H5Dpkg.h
index 46d545d..ad0eb4d 100644
--- a/src/H5Dpkg.h
+++ b/src/H5Dpkg.h
@@ -461,6 +461,7 @@ typedef struct H5D_shared_t {
*/
H5D_rdcc_t chunk; /* Information about chunked data */
} cache;
+ H5D_append_flush_t append_flush; /* Append flush property information */
} H5D_shared_t;
struct H5D_t {
diff --git a/src/H5Dprivate.h b/src/H5Dprivate.h
index e154f60..0c7f1aa 100644
--- a/src/H5Dprivate.h
+++ b/src/H5Dprivate.h
@@ -52,6 +52,7 @@
#define H5D_ACS_DATA_CACHE_NUM_SLOTS_NAME "rdcc_nslots" /* Size of raw data chunk cache(slots) */
#define H5D_ACS_DATA_CACHE_BYTE_SIZE_NAME "rdcc_nbytes" /* Size of raw data chunk cache(bytes) */
#define H5D_ACS_PREEMPT_READ_CHUNKS_NAME "rdcc_w0" /* Preemption read chunks first */
+#define H5D_ACS_APPEND_FLUSH_NAME "append_flush" /* Append flush actions */
/* ======== Data transfer properties ======== */
#define H5D_XFER_MAX_TEMP_BUF_NAME "max_temp_buf" /* Maximum temp buffer size */
@@ -146,6 +147,14 @@ typedef struct H5D_copy_file_ud_t {
H5O_layout_t *src_layout; /* Copy of layout for dataset */
} H5D_copy_file_ud_t;
+/* Structure for dataset append flush property (H5Pset_append_flush) */
+typedef struct H5D_append_flush_t {
+ int ndims; /* The # of dimensions for "boundary" */
+ hsize_t boundary[H5S_MAX_RANK]; /* The dimension sizes for determining boundary */
+ H5D_append_cb_t func; /* The callback function */
+ void *udata; /* User data */
+} H5D_append_flush_t;
+
/*****************************/
/* Library Private Variables */
diff --git a/src/H5Dpublic.h b/src/H5Dpublic.h
index 44af139..62bae80 100644
--- a/src/H5Dpublic.h
+++ b/src/H5Dpublic.h
@@ -100,6 +100,9 @@ typedef enum H5D_fill_value_t {
H5D_FILL_VALUE_USER_DEFINED =2
} H5D_fill_value_t;
+/* Callback for H5Pset_append_flush() in a dataset access property list */
+typedef herr_t (*H5D_append_cb_t)(hid_t dataset_id, hsize_t *cur_dims, void *op_data);
+
/********************/
/* Public Variables */
/********************/
diff --git a/src/H5F.c b/src/H5F.c
index 46442b7..7760a21 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -83,6 +83,7 @@ static herr_t H5F_build_actual_name(const H5F_t *f, const H5P_genplist_t *fapl,
const char *name, char ** /*out*/ actual_name);
static herr_t H5F_dest(H5F_t *f, hid_t dxpl_id, hbool_t flush);
static herr_t H5F_close(H5F_t *f);
+static herr_t H5F_set_retries(H5F_t *f);
/*********************/
@@ -323,11 +324,12 @@ done:
hid_t
H5F_get_access_plist(H5F_t *f, hbool_t app_ref)
{
- H5P_genplist_t *new_plist; /* New property list */
- H5P_genplist_t *old_plist; /* Old property list */
+ H5P_genplist_t *new_plist; /* New property list */
+ H5P_genplist_t *old_plist; /* Old property list */
void *driver_info=NULL;
unsigned efc_size = 0;
- hid_t ret_value = SUCCEED;
+ H5F_object_flush_t flush_info; /* Object flush property values */
+ hid_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -367,6 +369,15 @@ H5F_get_access_plist(H5F_t *f, hbool_t app_ref)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set 'latest format' flag")
if(H5P_set(new_plist, H5F_ACS_METADATA_READ_ATTEMPTS_NAME, &(f->shared->read_attempts)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set 'latest format' flag")
+
+ /* Obtain object flush property values */
+ flush_info.func = f->shared->object_flush.func;
+ flush_info.udata = f->shared->object_flush.udata;
+
+ /* Set values */
+ if(H5P_set(new_plist, H5F_ACS_OBJECT_FLUSH_CB_NAME, &flush_info) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set object flush callback")
+
if(f->shared->efc)
efc_size = H5F_efc_max_nfiles(f->shared->efc);
if(H5P_set(new_plist, H5F_ACS_EFC_SIZE_NAME, &efc_size) < 0)
@@ -1012,28 +1023,24 @@ H5F_new(H5F_file_t *shared, unsigned flags, hid_t fcpl_id, hid_t fapl_id, H5FD_t
/* When opening file without SWMR access, the # of read attempts is always H5F_METADATA_READ_ATTEMPTS (set or not set) */
if(H5F_INTENT(f) & (H5F_ACC_SWMR_READ | H5F_ACC_SWMR_WRITE)) {
/* If no value for read attempts has been set, use the default */
- if(!f->shared->read_attempts)
- f->shared->read_attempts = H5F_SWMR_METADATA_READ_ATTEMPTS;
+ if(!f->shared->read_attempts)
+ f->shared->read_attempts = H5F_SWMR_METADATA_READ_ATTEMPTS;
- /* Turn off accumulator with SWMR */
- f->shared->feature_flags = lf->feature_flags & ~(unsigned)H5FD_FEAT_ACCUMULATE_METADATA;
- if(H5FD_set_feature_flags(lf, f->shared->feature_flags) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't set feature_flags in VFD")
+ /* Turn off accumulator with SWMR */
+ f->shared->feature_flags &= ~(unsigned)H5FD_FEAT_ACCUMULATE_METADATA;
+ if(H5FD_set_feature_flags(f->shared->lf, f->shared->feature_flags) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't set feature_flags in VFD")
} /* end if */
else
f->shared->read_attempts = H5F_METADATA_READ_ATTEMPTS;
- /* Determine the # of bins for metdata read retries */
- f->shared->retries_nbins = 0;
- if(f->shared->read_attempts > 1) {
- double tmp;
-
- tmp = HDlog10((double)(f->shared->read_attempts - 1));
- f->shared->retries_nbins = (unsigned)tmp + 1;
- } /* end if */
+ /* Determine the # of bins for metdata read retries */
+ if(H5F_set_retries(f) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "can't set retries and retries_nbins")
- /* Initialize the tracking for metadata read retries */
- HDmemset(f->shared->retries, 0, sizeof(f->shared->retries));
+ /* Get object flush callback information */
+ if(H5P_get(plist, H5F_ACS_OBJECT_FLUSH_CB_NAME, &(f->shared->object_flush)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get the # of read attempts")
/*
* Create a metadata cache with the specified number of elements.
@@ -1143,10 +1150,19 @@ H5F_dest(H5F_t *f, hid_t dxpl_id, hbool_t flush)
/* Flush the file again (if requested), as shutting down the
* free space manager may dirty some data structures again.
*/
- if(flush)
+ if(flush) {
+ /* Clear status_flags */
+ f->shared->sblock->status_flags &= ~H5F_SUPER_WRITE_ACCESS;
+ f->shared->sblock->status_flags &= ~H5F_SUPER_SWMR_WRITE_ACCESS;
+ /* Mark superblock dirty in cache, so change will get encoded */
+ /* Push error, but keep going*/
+ if(H5F_super_dirty(f) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, FAIL, "unable to mark superblock as dirty")
+
if(H5F_flush(f, dxpl_id, TRUE) < 0)
/* Push error, but keep going*/
HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache")
+ }
} /* end if */
/* Unpin the superblock, since we're about to destroy the cache */
@@ -1277,6 +1293,37 @@ H5F_dest(H5F_t *f, hid_t dxpl_id, hbool_t flush)
* The ACCESS_PARMS argument is optional. A null pointer will
* cause the default file access parameters to be used.
*
+ * The following two tables show results of file opens for single and concurrent access:
+ *
+ * SINGLE PROCESS ACCESS CONCURRENT ACCESS
+ *
+ * #1st open# #1st open#
+ * -- SR SR -- -- SR SR -- -- SR SR -- -- SR SR --
+ * -- -- SW SW SW SW -- -- -- -- SW SW SW SW -- --
+ * W W W W R R R R W W W W R R R R
+ * #2nd open# #2nd open#
+ * -------------------------- --------------------------
+ * -- -- W | s x x s x x f f | -- -- W | f x x f x x f f |
+ * SR -- W | x x x x x x x x | SR -- W | x x x x x x x x |
+ * SR SW W | x x x x x x x x | SR SW W | x x x x x x x x |
+ * -- SW W | f x x s x x f f | -- SW W | f x x f x x f f |
+ * -- SW R | x x x x x x x x | -- SW R | x x x x x x x x |
+ * SR SW R | x x x x x x x x | SR SW R | x x x x x x x x |
+ * SR -- R | s x x s x x s f | SR -- R | f x x s x x s s |
+ * -- -- R | s x x s x x s s | -- -- R | f x x f x x s s |
+ * -------------------------- --------------------------
+ *
+ * Notations:
+ * W: H5F_ACC_RDWR
+ * R: H5F_ACC_RDONLY
+ * SW: H5F_ACC_SWMR_WRITE
+ * SR: H5F_ACC_SWMR_READ
+ *
+ * x: the first open or second open itself fails due to invalid flags combination
+ * f: the open fails with flags combination from both the first and second opens
+ * s: the open succeeds with flags combination from both the first and second opens
+ *
+ *
* Return: Success: A new file pointer.
* Failure: NULL
*
@@ -1296,6 +1343,8 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id,
H5FD_class_t *drvr; /*file driver class info */
H5P_genplist_t *a_plist; /*file access property list */
H5F_close_degree_t fc_degree; /*file close degree */
+ hbool_t set_flag = FALSE; /*set the status_flags in the superblock */
+ hbool_t clear = FALSE; /*clear the status_flags */
H5F_t *ret_value; /*actual return value */
FUNC_ENTER_NOAPI(NULL)
@@ -1370,11 +1419,10 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id,
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "file exists")
if((flags & H5F_ACC_RDWR) && 0 == (shared->flags & H5F_ACC_RDWR))
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "file is already open for read-only")
- if(((flags & H5F_ACC_SWMR_WRITE) && 0 == (shared->flags & H5F_ACC_SWMR_WRITE))
- || (0 == (flags & H5F_ACC_SWMR_WRITE) && (shared->flags & H5F_ACC_SWMR_WRITE)))
+
+ if((flags & H5F_ACC_SWMR_WRITE) && 0 == (shared->flags & H5F_ACC_SWMR_WRITE))
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "SWMR write access flag not the same for file that is already open")
- if(((flags & H5F_ACC_SWMR_READ) && 0 == (shared->flags & H5F_ACC_SWMR_READ))
- || (0 == (flags & H5F_ACC_SWMR_READ) && (shared->flags & H5F_ACC_SWMR_READ)))
+ if((flags & H5F_ACC_SWMR_READ) && !((shared->flags & H5F_ACC_SWMR_WRITE) || (shared->flags & H5F_ACC_SWMR_READ) || (shared->flags & H5F_ACC_RDWR)))
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "SWMR read access flag not the same for file that is already open")
/* Allocate new "high-level" file struct */
@@ -1389,18 +1437,24 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id,
* open it are different than the desired flags. Close the tentative
* file and open it for real.
*/
- if(H5FD_close(lf) < 0) {
- file = NULL; /*to prevent destruction of wrong file*/
+ if(H5FD_close(lf) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to close low-level file info")
- } /* end if */
- if(NULL == (lf = H5FD_open(name, flags, fapl_id, HADDR_UNDEF))) {
- file = NULL; /*to prevent destruction of wrong file*/
+
+ if(NULL == (lf = H5FD_open(name, flags, fapl_id, HADDR_UNDEF)))
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file")
- } /* end if */
+
} /* end if */
- if(NULL == (file = H5F_new(NULL, flags, fcpl_id, fapl_id, lf)))
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to create new file object")
+ /* Place an advisory lock on the file */
+ if((H5FD_lock(lf, (hbool_t)((flags & H5F_ACC_RDWR) ? TRUE : FALSE)) < 0) ||
+ (NULL == (file = H5F_new(NULL, flags, fcpl_id, fapl_id, lf)))) {
+ if(H5FD_close(lf) < 0) /* Closing will remove the lock */
+ HDONE_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to close low-level file info")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to lock the file or initialize file structure")
+ }
+
+ /* Need to set status_flags in the superblock */
+ set_flag = TRUE;
} /* end else */
/* Retain the name the file was opened with */
@@ -1432,6 +1486,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id,
if(H5G_mkroot(file, dxpl_id, TRUE) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create/open root group")
} else if (1 == shared->nrefs) {
+
/* Read the superblock if it hasn't been read before. */
if(H5F_super_read(file, dxpl_id) < 0)
HGOTO_ERROR(H5E_FILE, H5E_READERROR, NULL, "unable to read superblock")
@@ -1455,6 +1510,16 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id,
if(H5P_get(a_plist, H5F_ACS_CLOSE_DEGREE_NAME, &fc_degree) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get file close degree")
+ /* This is a private property to clear the status_flags in the super block */
+ /* Use by h5clear and a routine in test/flush2.c to clear the test file's status_flags */
+ if(H5P_exist_plist(a_plist, H5F_ACS_CLEAR_STATUS_FLAGS_NAME) > 0) {
+ if(H5P_get(a_plist, H5F_ACS_CLEAR_STATUS_FLAGS_NAME, &clear) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get clearance for status_flags")
+ else if(clear) {
+ file->shared->sblock->status_flags = 0;
+ }
+ }
+
if(shared->nrefs == 1) {
if(fc_degree == H5F_CLOSE_DEFAULT)
shared->fc_degree = lf->cls->fc_degree;
@@ -1475,13 +1540,42 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id,
if(H5F_build_actual_name(file, a_plist, name, &file->actual_name) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to build actual name")
+ if(set_flag) {
+ if(H5F_INTENT(file) & H5F_ACC_RDWR) { /* Set and check consistency of status_flags */
+ if(file->shared->sblock->status_flags & H5F_SUPER_WRITE_ACCESS ||
+ file->shared->sblock->status_flags & H5F_SUPER_SWMR_WRITE_ACCESS)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "file is already open for write or SWMR write")
+
+ file->shared->sblock->status_flags |= H5F_SUPER_WRITE_ACCESS;
+
+ if(H5F_INTENT(file) & H5F_ACC_SWMR_WRITE) { /* Remove the file lock for SWMR_WRITE */
+ file->shared->sblock->status_flags |= H5F_SUPER_SWMR_WRITE_ACCESS;
+ if(H5FD_unlock(file->shared->lf) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to unlock the file")
+ }
+ /* Flush the superblock */
+ if(H5F_super_dirty(file) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, NULL, "unable to mark superblock as dirty")
+ if(H5F_flush_tagged_metadata(file, (haddr_t)0, H5AC_dxpl_id) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, NULL, "unable to flush superblock")
+ } else { /* H5F_ACC_RDONLY */
+ if(H5F_INTENT(file) & H5F_ACC_SWMR_READ) { /* Check consistency of status_flags */
+ if((file->shared->sblock->status_flags & H5F_SUPER_WRITE_ACCESS && !(file->shared->sblock->status_flags & H5F_SUPER_SWMR_WRITE_ACCESS))
+ || (!(file->shared->sblock->status_flags & H5F_SUPER_WRITE_ACCESS) && file->shared->sblock->status_flags & H5F_SUPER_SWMR_WRITE_ACCESS))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "file is not already open for SWMR writing")
+ } else if((file->shared->sblock->status_flags & H5F_SUPER_WRITE_ACCESS) ||
+ (file->shared->sblock->status_flags & H5F_SUPER_SWMR_WRITE_ACCESS))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "file is already open for writing")
+ }
+ } /* end if set_flag */
+
/* Success */
ret_value = file;
done:
if(!ret_value && file)
- if(H5F_dest(file, dxpl_id, FALSE) < 0)
- HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, NULL, "problems closing file")
+ if(H5F_dest(file, dxpl_id, FALSE) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, NULL, "problems closing file")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F_open() */
@@ -2116,9 +2210,17 @@ H5Fclose(hid_t file_id)
if((f->shared->nrefs > 1) && (H5F_INTENT(f) & H5F_ACC_RDWR)) {
if((nref = H5I_get_ref(file_id, FALSE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't get ID ref count")
- if(nref == 1)
+ if(nref == 1) {
+ if(f->shared->sblock) { /* Clear status_flags */
+ f->shared->sblock->status_flags &= ~H5F_SUPER_WRITE_ACCESS;
+ f->shared->sblock->status_flags &= ~H5F_SUPER_SWMR_WRITE_ACCESS;
+ /* Mark superblock dirty in cache, so change will get encoded */
+ if(H5F_super_dirty(f) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, FAIL, "unable to mark superblock as dirty")
+ }
if(H5F_flush(f, H5AC_dxpl_id, FALSE) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache")
+ }
} /* end if */
/*
@@ -2820,6 +2922,8 @@ H5Fget_file_image(hid_t file_id, void *buf_ptr, size_t buf_len)
/* test to see if a buffer was provided -- if not, we are done */
if(buf_ptr != NULL) {
size_t space_needed; /* size of file image */
+ hsize_t tmp;
+ size_t tmp_size;
/* Check for buffer too small */
if((haddr_t)buf_len < eoa)
@@ -2829,8 +2933,18 @@ H5Fget_file_image(hid_t file_id, void *buf_ptr, size_t buf_len)
/* read in the file image */
/* (Note compensation for base address addition in internal routine) */
- if(H5FD_read(fd_ptr, H5AC_ind_dxpl_id, H5FD_MEM_DEFAULT, 0, space_needed, buf_ptr) < 0)
+ if(H5FD_read(fd_ptr, H5AC_ind_dxpl_id, H5FD_MEM_DEFAULT, (haddr_t)0, space_needed, buf_ptr) < 0)
HGOTO_ERROR(H5E_FILE, H5E_READERROR, FAIL, "file image read request failed")
+
+ /* Offset to "status_flags" in the superblock */
+ tmp = H5F_SUPER_STATUS_FLAGS_OFF(file->shared->sblock->super_vers);
+ /* Size of "status_flags" depends on the superblock version */
+ tmp_size = H5F_SUPER_STATUS_FLAGS_SIZE(file->shared->sblock->super_vers);
+
+ /* Clear "status_flags" */
+ HDmemset((uint8_t *)(buf_ptr) + tmp, 0, tmp_size);
+
+
} /* end if */
done:
@@ -3551,3 +3665,199 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5F_track_metadata_read_retries() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_set_retries
+ *
+ * Purpose: To initialize data structures for read retries:
+ * --zero out "retries"
+ * --set up "retries_nbins" based on read_attempts
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Vailin Choi; November 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5F_set_retries(H5F_t *f)
+{
+ double tmp; /* Temporary variable */
+
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ /* Sanity check */
+ HDassert(f);
+
+ /* Initialize the tracking for metadata read retries */
+ HDmemset(f->shared->retries, 0, sizeof(f->shared->retries));
+
+ /* Initialize the # of bins for retries */
+ f->shared->retries_nbins = 0;
+ if(f->shared->read_attempts > 1) {
+ tmp = HDlog10((double)(f->shared->read_attempts - 1));
+ f->shared->retries_nbins = (unsigned)tmp + 1;
+ }
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5F_set_retries() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5Fstart_swmr_write
+ *
+ * Purpose: To enable SWMR writing mode for the file
+ * 1) Mark the file in SWMR writing mode
+ * 2) Set metadata read attempts and retries info
+ * 3) Disable accumulator
+ * 4) Flush the data buffers
+ * 5) Evict all cache entries except the superblock
+ * 6) Unlock the file
+ * Fail when:
+ * 1) There are opened objects
+ * 2) The file is not opened with latest library format
+ * 3) The file is not opened with H5F_ACC_RDWR
+ * 4) The file is already marked for SWMR writing
+ *
+ * Return: Non-negative on success/negative on failure
+ *
+ * Programmer:
+ * Vailin Choi; Dec 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Fstart_swmr_write(hid_t file_id)
+{
+ H5F_t *file; /* File info */
+ hbool_t setup = FALSE;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE1("e", "i", file_id);
+
+ /* check args */
+ if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
+
+ /* ???How about nopen_files from (H5F_mount_count_ids(file, &nopen_files, &nopen_objs) */
+ /* For now, just check nopen_objs */
+ if((H5F_addr_defined(file->shared->sblock->ext_addr) && file->nopen_objs > 1) ||
+ (!H5F_addr_defined(file->shared->sblock->ext_addr) && file->nopen_objs > 0))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't start SWMR writing, there are objects still open")
+
+ /* Should have write permission */
+ if((H5F_INTENT(file) & H5F_ACC_RDWR) == 0)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "no write intent on file")
+
+ /* Should be using latest library format */
+ if(!H5F_use_latest_format(file))
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "file not opened with latest library format")
+
+ /* Should not be marked for SWMR writing mode already */
+ if(file->shared->sblock->status_flags & H5F_SUPER_SWMR_WRITE_ACCESS)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "file already in SWMR writing mode")
+
+ HDassert(file->shared->sblock->status_flags & H5F_SUPER_WRITE_ACCESS);
+
+ /* Turn on SWMR write in shared file open flags */
+ file->shared->flags |= H5F_ACC_SWMR_WRITE;
+
+ /* Mark the file in SWMR writing mode */
+ file->shared->sblock->status_flags |= H5F_SUPER_SWMR_WRITE_ACCESS;
+
+ /* Set up metadata read attempts */
+ file->shared->read_attempts = H5F_SWMR_METADATA_READ_ATTEMPTS;
+
+ setup = TRUE;
+
+ /* Initialize "retries" and "retries_nbins" */
+ if(H5F_set_retries(file) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "can't set retries and retries_nbins")
+
+ /* Flush and reset the accumulator */
+ if(H5F_accum_reset(file, H5AC_dxpl_id, TRUE) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTRESET, FAIL, "can't reset accumulator")
+
+ /* Turn off usage of accumulator */
+ file->shared->feature_flags &= ~(unsigned)H5FD_FEAT_ACCUMULATE_METADATA;
+ if(H5FD_set_feature_flags(file->shared->lf, file->shared->feature_flags) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set feature_flags in VFD")
+
+ /* Mark superblock as dirty */
+ if(H5F_super_dirty(file) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, FAIL, "unable to mark superblock as dirty")
+
+ /* Flush data buffers */
+ if(H5F_flush(file, H5AC_dxpl_id, FALSE) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush file's cached information")
+
+ /* Evict all flushed entries in the cache except the pinned superblock */
+ if(H5F_evict_cache_entries(file, H5AC_dxpl_id) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to evict file's cached information")
+
+ /* Unlock the file */
+ if(H5FD_unlock(file->shared->lf) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to unlock the file")
+done:
+ if(ret_value < 0 && file && setup) {
+
+ /* Re-enable accumulator */
+ file->shared->feature_flags |= (unsigned)H5FD_FEAT_ACCUMULATE_METADATA;
+ if(H5FD_set_feature_flags(file->shared->lf, file->shared->feature_flags) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set feature_flags in VFD")
+
+ /* Reset the # of read attempts */
+ file->shared->read_attempts = H5F_METADATA_READ_ATTEMPTS;
+ if(H5F_set_retries(file) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "can't set retries and retries_nbins")
+
+ /* Un-set H5F_ACC_SWMR_WRITE in shared open flags */
+ file->shared->flags &= ~H5F_ACC_SWMR_WRITE;
+
+ /* Unmark the file: not in SWMR writing mode */
+ file->shared->sblock->status_flags &= ~(uint8_t)H5F_SUPER_SWMR_WRITE_ACCESS;
+
+ /* Mark superblock as dirty */
+ if(H5F_super_dirty(file) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, FAIL, "unable to mark superblock as dirty")
+
+ /* Flush the superblock */
+ if(H5F_flush_tagged_metadata(file, (haddr_t)0, H5AC_dxpl_id) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush superblock")
+ }
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Fstart_swmr_write() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_object_flush_cb
+ *
+ * Purpose: To invoke the callback function for object flush that is set
+ * in the file's access property list.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Vailin Choi; October 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_object_flush_cb(H5F_t *f, hid_t obj_id)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(f->shared);
+
+ /* Invoke object flush callback if there is one */
+ if(f->shared->object_flush.func && f->shared->object_flush.func(obj_id, f->shared->object_flush.udata) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "object flush callback returns error")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5F_object_flush_cb() */
diff --git a/src/H5FD.c b/src/H5FD.c
index 5f447ec..d677543 100644
--- a/src/H5FD.c
+++ b/src/H5FD.c
@@ -1909,6 +1909,64 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5FD_lock
+ *
+ * Purpose: Private version of H5FDlock()
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Vailin Choi; May 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FD_lock(H5FD_t *file, hbool_t rw)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ HDassert(file && file->cls);
+
+ if(file->cls->lock && (file->cls->lock)(file, rw) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTUPDATE, FAIL, "driver lock request failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_lock() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_unlock
+ *
+ * Purpose: Private version of H5FDunlock()
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Vailin Choi; May 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FD_unlock(H5FD_t *file)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ HDassert(file && file->cls);
+
+ if(file->cls->unlock && (file->cls->unlock)(file) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTUPDATE, FAIL, "driver unlock request failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_unlock() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5FD_get_fileno
*
* Purpose: Quick and dirty routine to retrieve the file's 'fileno' value
diff --git a/src/H5FDcore.c b/src/H5FDcore.c
index 559af82..8e4f05b 100644
--- a/src/H5FDcore.c
+++ b/src/H5FDcore.c
@@ -137,6 +137,8 @@ static herr_t H5FD_core_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, had
size_t size, const void *buf);
static herr_t H5FD_core_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing);
static herr_t H5FD_core_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
+static herr_t H5FD_core_lock(H5FD_t *_file, hbool_t rw);
+static herr_t H5FD_core_unlock(H5FD_t *_file);
static const H5FD_class_t H5FD_core_g = {
"core", /* name */
@@ -168,8 +170,8 @@ static const H5FD_class_t H5FD_core_g = {
H5FD_core_write, /* write */
H5FD_core_flush, /* flush */
H5FD_core_truncate, /* truncate */
- NULL, /* lock */
- NULL, /* unlock */
+ H5FD_core_lock, /* lock */
+ H5FD_core_unlock, /* unlock */
H5FD_FLMAP_DICHOTOMY /* fl_map */
};
@@ -1244,3 +1246,76 @@ H5FD_core_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t closing)
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FD_core_truncate() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_core_lock
+ *
+ * Purpose: To place an advisory lock on a file.
+ * The lock type to apply depends on the parameter "rw":
+ * TRUE--opens for write: an exclusive lock
+ * FALSE--opens for read: a shared lock
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Vailin Choi; May 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_core_lock(H5FD_t *_file, hbool_t rw)
+{
+ H5FD_core_t *file = (H5FD_core_t*)_file; /* VFD file struct */
+ int lock; /* The type of lock */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ HDassert(file);
+ if(file->fd >= 0) {
+
+ /* Determine the type of lock */
+ lock = rw ? LOCK_EX : LOCK_SH;
+
+ /* Place the lock with non-blocking */
+ if(HDflock(file->fd, lock | LOCK_NB) < 0)
+ HSYS_GOTO_ERROR(H5E_FILE, H5E_BADFILE, FAIL, "unable to flock file")
+ }
+ /* Otherwise a noop */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_core_lock() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_core_unlock
+ *
+ * Purpose: To remove the existing lock on the file
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Vailin Choi; May 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_core_unlock(H5FD_t *_file)
+{
+ H5FD_core_t *file = (H5FD_core_t*)_file; /* VFD file struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ HDassert(file);
+
+ if(file->fd >= 0) {
+
+ if(HDflock(file->fd, LOCK_UN) < 0)
+ HSYS_GOTO_ERROR(H5E_FILE, H5E_BADFILE, FAIL, "unable to flock (unlock) file")
+ }
+ /* Otherwise a noop */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_core_unlock() */
diff --git a/src/H5FDdirect.c b/src/H5FDdirect.c
index 3aa1c4f..a5a8426 100644
--- a/src/H5FDdirect.c
+++ b/src/H5FDdirect.c
@@ -147,6 +147,9 @@ static herr_t H5FD_direct_read(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, ha
static herr_t H5FD_direct_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr,
size_t size, const void *buf);
static herr_t H5FD_direct_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
+static herr_t H5FD_direct_lock(H5FD_t *_file, hbool_t rw);
+static herr_t H5FD_direct_unlock(H5FD_t *_file);
+
static const H5FD_class_t H5FD_direct_g = {
"direct", /*name */
@@ -177,10 +180,10 @@ static const H5FD_class_t H5FD_direct_g = {
H5FD_direct_read, /*read */
H5FD_direct_write, /*write */
NULL, /*flush */
- H5FD_direct_truncate, /*truncate */
- NULL, /*lock */
- NULL, /*unlock */
- H5FD_FLMAP_DICHOTOMY /*fl_map */
+ H5FD_direct_truncate, /*truncate */
+ H5FD_direct_lock, /*lock */
+ H5FD_direct_unlock, /*unlock */
+ H5FD_FLMAP_DICHOTOMY /*fl_map */
};
/* Declare a free list to manage the H5FD_direct_t struct */
@@ -1342,5 +1345,72 @@ H5FD_direct_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t UNUSED closing
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FD_direct_truncate() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_direct_lock
+ *
+ * Purpose: To place an advisory lock on a file.
+ * The lock type to apply depends on the parameter "rw":
+ * TRUE--opens for write: an exclusive lock
+ * FALSE--opens for read: a shared lock
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Vailin Choi; May 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_direct_lock(H5FD_t *_file, hbool_t rw)
+{
+ H5FD_direct_t *file = (H5FD_direct_t*)_file; /* VFD file struct */
+ int lock; /* The type of lock */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ HDassert(file);
+
+ /* Determine the type of lock */
+ int lock = rw ? LOCK_EX : LOCK_SH;
+
+ /* Place the lock with non-blocking */
+ if(HDflock(file->fd, lock | LOCK_NB) < 0)
+ HSYS_GOTO_ERROR(H5E_FILE, H5E_BADFILE, FAIL, "unable to flock file")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_direct_lock() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_direct_unlock
+ *
+ * Purpose: To remove the existing lock on the file
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Vailin Choi; May 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_direct_unlock(H5FD_t *_file)
+{
+ H5FD_direct_t *file = (H5FD_direct_t*)_file; /* VFD file struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ HDassert(file);
+
+ if(HDflock(file->fd, LOCK_UN) < 0)
+ HSYS_GOTO_ERROR(H5E_FILE, H5E_BADFILE, FAIL, "unable to flock (unlock) file")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_direct_unlock() */
+
#endif /* H5_HAVE_DIRECT */
diff --git a/src/H5FDprivate.h b/src/H5FDprivate.h
index b21ecca..1fb6033 100644
--- a/src/H5FDprivate.h
+++ b/src/H5FDprivate.h
@@ -142,6 +142,8 @@ H5_DLL herr_t H5FD_write(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type,
haddr_t addr, size_t size, const void *buf);
H5_DLL herr_t H5FD_flush(H5FD_t *file, hid_t dxpl_id, hbool_t closing);
H5_DLL herr_t H5FD_truncate(H5FD_t *file, hid_t dxpl_id, hbool_t closing);
+H5_DLL herr_t H5FD_lock(H5FD_t *file, hbool_t rw);
+H5_DLL herr_t H5FD_unlock(H5FD_t *file);
H5_DLL herr_t H5FD_get_fileno(const H5FD_t *file, unsigned long *filenum);
H5_DLL herr_t H5FD_get_vfd_handle(H5FD_t *file, hid_t fapl, void** file_handle);
H5_DLL herr_t H5FD_set_base_addr(H5FD_t *file, haddr_t base_addr);
diff --git a/src/H5FDpublic.h b/src/H5FDpublic.h
index ed50bc7..d54aae8 100644
--- a/src/H5FDpublic.h
+++ b/src/H5FDpublic.h
@@ -275,8 +275,8 @@ typedef struct H5FD_class_t {
haddr_t addr, size_t size, const void *buffer);
herr_t (*flush)(H5FD_t *file, hid_t dxpl_id, unsigned closing);
herr_t (*truncate)(H5FD_t *file, hid_t dxpl_id, hbool_t closing);
- herr_t (*lock)(H5FD_t *file, unsigned char *oid, unsigned lock_type, hbool_t last);
- herr_t (*unlock)(H5FD_t *file, unsigned char *oid, hbool_t last);
+ herr_t (*lock)(H5FD_t *file, hbool_t rw);
+ herr_t (*unlock)(H5FD_t *file);
H5FD_mem_t fl_map[H5FD_MEM_NTYPES];
} H5FD_class_t;
diff --git a/src/H5FDsec2.c b/src/H5FDsec2.c
index 86ef6c6..ec0bd97 100644
--- a/src/H5FDsec2.c
+++ b/src/H5FDsec2.c
@@ -148,6 +148,8 @@ static herr_t H5FD_sec2_read(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, hadd
static herr_t H5FD_sec2_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr,
size_t size, const void *buf);
static herr_t H5FD_sec2_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
+static herr_t H5FD_sec2_lock(H5FD_t *_file, hbool_t rw);
+static herr_t H5FD_sec2_unlock(H5FD_t *_file);
static const H5FD_class_t H5FD_sec2_g = {
"sec2", /* name */
@@ -179,8 +181,8 @@ static const H5FD_class_t H5FD_sec2_g = {
H5FD_sec2_write, /* write */
NULL, /* flush */
H5FD_sec2_truncate, /* truncate */
- NULL, /* lock */
- NULL, /* unlock */
+ H5FD_sec2_lock, /* lock */
+ H5FD_sec2_unlock, /* unlock */
H5FD_FLMAP_DICHOTOMY /* fl_map */
};
@@ -938,3 +940,69 @@ H5FD_sec2_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t UNUSED closing)
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FD_sec2_truncate() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_sec2_lock
+ *
+ * Purpose: To place an advisory lock on a file.
+ * The lock type to apply depends on the parameter "rw":
+ * TRUE--opens for write: an exclusive lock
+ * FALSE--opens for read: a shared lock
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Vailin Choi; May 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_sec2_lock(H5FD_t *_file, hbool_t rw)
+{
+ H5FD_sec2_t *file = (H5FD_sec2_t *)_file; /* VFD file struct */
+ int lock; /* The type of lock */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ HDassert(file);
+
+ /* Determine the type of lock */
+ lock = rw ? LOCK_EX : LOCK_SH;
+
+ /* Place the lock with non-blocking */
+ if(HDflock(file->fd, lock | LOCK_NB) < 0)
+ HSYS_GOTO_ERROR(H5E_FILE, H5E_BADFILE, FAIL, "unable to flock file")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_sec2_lock() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_sec2_unlock
+ *
+ * Purpose: To remove the existing lock on the file
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Vailin Choi; May 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_sec2_unlock(H5FD_t *_file)
+{
+ H5FD_sec2_t *file = (H5FD_sec2_t *)_file; /* VFD file struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ HDassert(file);
+
+ if(HDflock(file->fd, LOCK_UN) < 0)
+ HSYS_GOTO_ERROR(H5E_FILE, H5E_BADFILE, FAIL, "unable to flock (unlock) file")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_sec2_unlock() */
diff --git a/src/H5Fio.c b/src/H5Fio.c
index 5faeaca..d12a919 100644
--- a/src/H5Fio.c
+++ b/src/H5Fio.c
@@ -238,6 +238,55 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5F_evict_cache_entries
+ *
+ * Purpose: To revict all cache entries except the pinned superblock entry
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Vailin Choi; Dec 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_evict_cache_entries(H5F_t *f, hid_t dxpl_id)
+{
+ unsigned status = 0;
+ int32_t cur_num_entries;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ /* Evict all except pinned entries in the cache */
+ if(H5AC_evict(f, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTEXPUNGE, FAIL, "unable to evict all except pinned entries")
+
+ /* Retrieve status of the superblock */
+ if(H5AC_get_entry_status(f, (haddr_t)0, &status) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to get entry status")
+
+ /* Verify status of the superblock entry in the cache */
+ if(!(status & H5AC_ES__IN_CACHE) || !(status & H5AC_ES__IS_PINNED) ||
+ (status & H5AC_ES__IS_DIRTY) || (status & H5AC_ES__IS_PROTECTED))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to get entry status")
+
+ /* Get the number of cache entries */
+ if(H5AC_get_cache_size(f->shared->cache, NULL, NULL, NULL, &cur_num_entries) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5AC_get_cache_size() failed.")
+
+ /* Should be the only one left in the cache */
+ if(cur_num_entries != 1)
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "number of cache entries is not correct")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5F_evict_cache_entries() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5F_get_checksums
*
* Purpose: Decode checksum stored in the buffer
diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h
index 1cc631c..1407c27 100644
--- a/src/H5Fpkg.h
+++ b/src/H5Fpkg.h
@@ -60,7 +60,9 @@
/* Superblock status flags */
#define H5F_SUPER_WRITE_ACCESS 0x01
#define H5F_SUPER_FILE_OK 0x02
-#define H5F_SUPER_ALL_FLAGS (H5F_SUPER_WRITE_ACCESS | H5F_SUPER_FILE_OK)
+#define H5F_SUPER_SWMR_WRITE_ACCESS 0x04
+#define H5F_SUPER_ALL_FLAGS (H5F_SUPER_WRITE_ACCESS | H5F_SUPER_FILE_OK | H5F_SUPER_SWMR_WRITE_ACCESS)
+
/* Mask for removing private file access flags */
#define H5F_ACC_PUBLIC_FLAGS 0x007fu
@@ -126,6 +128,22 @@
#define H5F_SUPERBLOCK_SIZE(v, f) ( H5F_SUPERBLOCK_FIXED_SIZE \
+ H5F_SUPERBLOCK_VARLEN_SIZE(v, f))
+/* For superblock version 0 & 1:
+ Offset to the file consistency flags (status_flags) in the superblock (excluding H5F_SUPERBLOCK_FIXED_SIZE) */
+#define H5F_SUPER_STATUS_OFF_V01 \
+ (2 /* freespace, and root group versions */ \
+ + 1 /* reserved */ \
+ + 3 /* shared header vers, size of address, size of lengths */ \
+ + 1 /* reserved */ \
+ + 4) /* group leaf k, group internal k */
+
+#define H5F_SUPER_STATUS_OFF(v) (v >= 2 ? 2 : H5F_SUPER_STATUS_OFF_V01)
+
+/* Offset to the file consistency flags (status_flags) in the superblock */
+#define H5F_SUPER_STATUS_FLAGS_OFF(v) (H5F_SUPERBLOCK_FIXED_SIZE + H5F_SUPER_STATUS_OFF(v))
+
+/* Size of file consistency flags (status_flags) in the superblock */
+#define H5F_SUPER_STATUS_FLAGS_SIZE(v) (v >= 2 ? 1 : 4)
/* Forward declaration external file cache struct used below (defined in
* H5Fefc.c) */
@@ -260,6 +278,7 @@ struct H5F_file_t {
unsigned read_attempts; /* The # of reads to try when reading metadata with checksum */
unsigned retries_nbins; /* # of bins for each retries[] */
uint32_t *retries[H5AC_NTYPES]; /* Track # of read retries for metdata items with checksum */
+ H5F_object_flush_t object_flush; /* Information for object flush callback */
};
/*
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
index 8dd6ec3..140aa8a 100644
--- a/src/H5Fprivate.h
+++ b/src/H5Fprivate.h
@@ -41,6 +41,11 @@ typedef struct H5F_file_t H5F_file_t;
/* Block aggregation structure */
typedef struct H5F_blk_aggr_t H5F_blk_aggr_t;
+/* Structure for object flush callback property (H5Pset_object_flush_cb)*/
+typedef struct H5F_object_flush_t {
+ H5F_flush_cb_t func; /* The callback function */
+ void *udata; /* User data */
+} H5F_object_flush_t;
/*
* Encode and decode macros for file meta-data.
@@ -463,8 +468,10 @@ typedef struct H5F_blk_aggr_t H5F_blk_aggr_t;
#define H5F_ACS_LATEST_FORMAT_NAME "latest_format" /* 'Use latest format version' flag */
#define H5F_ACS_WANT_POSIX_FD_NAME "want_posix_fd" /* Internal: query the file descriptor from the core VFD, instead of the memory address */
#define H5F_ACS_METADATA_READ_ATTEMPTS_NAME "metadata_read_attempts" /* # of metadata read attempts */
+#define H5F_ACS_OBJECT_FLUSH_CB_NAME "object_flush_cb" /* Object flush callback */
#define H5F_ACS_EFC_SIZE_NAME "efc_size" /* Size of external file cache */
#define H5F_ACS_FILE_IMAGE_INFO_NAME "file_image_info" /* struct containing initial file image and callback info */
+#define H5F_ACS_CLEAR_STATUS_FLAGS_NAME "clear_status_flags" /* Whether to clear superblock status_flags (private property only used by h5clear) */
/* ======================== File Mount properties ====================*/
#define H5F_MNT_SYM_LOCAL_NAME "local" /* Whether absolute symlinks local to file. */
@@ -640,6 +647,8 @@ H5_DLL herr_t H5F_block_write(const H5F_t *f, H5FD_mem_t type, haddr_t addr,
/* Functions that flush or evict */
H5_DLL herr_t H5F_flush_tagged_metadata(H5F_t * f, haddr_t tag, hid_t dxpl_id);
H5_DLL herr_t H5F_evict_tagged_metadata(H5F_t * f, haddr_t tag, hid_t dxpl_id);
+H5_DLL herr_t H5F_evict_cache_entries(H5F_t *f, hid_t dxpl_id);
+
/* Functions that read & verify a piece of metadata with checksum */
H5_DLL herr_t H5F_read_check_metadata(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type,
@@ -650,6 +659,10 @@ H5_DLL herr_t H5F_get_checksums(const uint8_t *buf, size_t chk_size, uint32_t *s
/* Routine to track the # of retries */
H5_DLL herr_t H5F_track_metadata_read_retries(H5F_t *f, unsigned actype, unsigned retries);
+/* Routine to invoke callback function upon object flush */
+H5_DLL herr_t H5F_object_flush_cb(H5F_t *f, hid_t obj_id);
+
+
/* Address-related functions */
H5_DLL void H5F_addr_encode(const H5F_t *f, uint8_t **pp, haddr_t addr);
H5_DLL void H5F_addr_encode_len(size_t addr_len, uint8_t **pp, haddr_t addr);
diff --git a/src/H5Fpublic.h b/src/H5Fpublic.h
index c1d96ca..7db8cfe 100644
--- a/src/H5Fpublic.h
+++ b/src/H5Fpublic.h
@@ -193,6 +193,10 @@ typedef struct H5F_retry_info_t {
uint32_t *retries[H5F_NUM_METADATA_READ_RETRY_TYPES];
} H5F_retry_info_t;
+/* Callback for H5Pset_object_flush_cb() in a file access property list */
+typedef herr_t (*H5F_flush_cb_t)(hid_t object_id, void *udata);
+
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -231,6 +235,7 @@ H5_DLL herr_t H5Freset_mdc_hit_rate_stats(hid_t file_id);
H5_DLL ssize_t H5Fget_name(hid_t obj_id, char *name, size_t size);
H5_DLL herr_t H5Fget_info2(hid_t obj_id, H5F_info2_t *finfo);
H5_DLL herr_t H5Fget_metadata_read_retry_info(hid_t file_id, H5F_retry_info_t *info);
+H5_DLL herr_t H5Fstart_swmr_write(hid_t file_id);
H5_DLL ssize_t H5Fget_free_sections(hid_t file_id, H5F_mem_t type,
size_t nsects, H5F_sect_info_t *sect_info/*out*/);
H5_DLL herr_t H5Fclear_elink_file_cache(hid_t file_id);
diff --git a/src/H5Fsuper.c b/src/H5Fsuper.c
index a1c67ec..7858530 100644
--- a/src/H5Fsuper.c
+++ b/src/H5Fsuper.c
@@ -204,7 +204,7 @@ H5F_super_ext_create(H5F_t *f, hid_t dxpl_id, H5O_loc_t *ext_ptr)
* extension.
*/
H5O_loc_reset(ext_ptr);
- if(H5O_create(f, dxpl_id, 0, (size_t)1, H5P_GROUP_CREATE_DEFAULT, ext_ptr) < 0)
+ if(H5O_create(f, dxpl_id, (size_t)0, (size_t)1, H5P_GROUP_CREATE_DEFAULT, ext_ptr) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTCREATE, FAIL, "unable to create superblock extension")
/* Record the address of the superblock extension */
diff --git a/src/H5G.c b/src/H5G.c
index e16847d..30f498a 100644
--- a/src/H5G.c
+++ b/src/H5G.c
@@ -843,9 +843,8 @@ H5Gflush(hid_t group_id)
if(NULL == (grp = (H5G_t *)H5I_object_verify(group_id, H5I_GROUP)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group")
- /* Call private function to flush group object */
- if (H5O_flush_metadata(&grp->oloc, H5AC_dxpl_id) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTFLUSH, FAIL, "unable to flush group")
+ if(H5O_flush_common(&grp->oloc, group_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTFLUSH, FAIL, "unable to flush group and object flush callback")
done:
FUNC_LEAVE_API(ret_value)
diff --git a/src/H5Ocopy.c b/src/H5Ocopy.c
index 24eed35..13902aa 100644
--- a/src/H5Ocopy.c
+++ b/src/H5Ocopy.c
@@ -362,20 +362,33 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out*/,
/* Check if the object at the address is already open in the file */
if(H5FO_opened(oloc_src->file, oloc_src->addr) != NULL) {
- H5G_loc_t tmp_loc; /* Location of object */
- H5O_loc_t tmp_oloc; /* Location of object */
- H5G_name_t tmp_path; /* Object's path */
+ H5G_loc_t tmp_loc; /* Location of object */
+ H5O_loc_t tmp_oloc; /* Location of object */
+ H5G_name_t tmp_path; /* Object's path */
+ void *obj_ptr = NULL; /* Object pointer */
+ hid_t tmp_id = -1; /* Object ID */
tmp_loc.oloc = &tmp_oloc;
tmp_loc.path = &tmp_path;
tmp_oloc.file = oloc_src->file;
tmp_oloc.addr = oloc_src->addr;
- tmp_oloc.holding_file = oloc_src->holding_file;
+ tmp_oloc.holding_file = FALSE;
H5G_name_reset(tmp_loc.path);
- /* Flush the object of this class */
- if(obj_class->flush && obj_class->flush(&tmp_loc, dxpl_id) < 0)
+ /* Get a temporary ID */
+ if((tmp_id = obj_class->open(&tmp_loc, H5P_DEFAULT, dxpl_id, FALSE)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTFLUSH, FAIL, "unable to open object")
+
+ /* Get object pointer */
+ obj_ptr = H5I_object(tmp_id);
+
+ /* Flush the object */
+ if(obj_class->flush && obj_class->flush(obj_ptr, dxpl_id) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTFLUSH, FAIL, "unable to flush object")
+
+ /* Release the temporary ID */
+ if(tmp_id != -1 && H5I_dec_app_ref(tmp_id))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to close temporary ID")
}
/* Get source object header */
@@ -476,7 +489,7 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out*/,
oh_dst->alloc_nchunks = oh_dst->nchunks = 0;
/* Allocate memory for the chunk array - always start with 1 chunk */
- if(NULL == (oh_dst->chunk = H5FL_SEQ_MALLOC(H5O_chunk_t, 1)))
+ if(NULL == (oh_dst->chunk = H5FL_SEQ_MALLOC(H5O_chunk_t, (size_t)1)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Update number of allocated chunks. There are still no chunks used. */
@@ -1665,7 +1678,7 @@ H5O_copy_search_comm_dt_check(H5O_loc_t *obj_oloc,
attr_op.u.lib_op = H5O_copy_search_comm_dt_attr_cb;
udata->obj_oloc.file = obj_oloc->file;
udata->obj_oloc.addr = obj_oloc->addr;
- if(H5O_attr_iterate_real((hid_t)-1, obj_oloc, udata->dxpl_id, H5_INDEX_NAME, H5_ITER_NATIVE, 0, NULL, &attr_op, udata) < 0)
+ if(H5O_attr_iterate_real((hid_t)-1, obj_oloc, udata->dxpl_id, H5_INDEX_NAME, H5_ITER_NATIVE, (hsize_t)0, NULL, &attr_op, udata) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "error iterating over attributes");
done:
diff --git a/src/H5Oflush.c b/src/H5Oflush.c
index 06448fe..489afb2 100644
--- a/src/H5Oflush.c
+++ b/src/H5Oflush.c
@@ -48,7 +48,7 @@
/*-------------------------------------------------------------------------
- * Function: H5Oflush
+ * Function: H5Oflush
*
* Purpose: Flushes all buffers associated with an object to disk.
*
@@ -63,6 +63,8 @@ herr_t
H5Oflush(hid_t obj_id)
{
H5O_loc_t *oloc; /* object location */
+ void *obj_ptr; /* Pointer to object */
+ const H5O_obj_class_t *obj_class = NULL; /* Class of object */
herr_t ret_value = SUCCEED; /* return value */
FUNC_ENTER_API(FAIL)
@@ -71,15 +73,57 @@ H5Oflush(hid_t obj_id)
/* Check args */
if((oloc = H5O_get_loc(obj_id)) == NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an object")
-
- /* Private function */
- if (H5O_flush_metadata(oloc, H5AC_dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to flush object")
+
+ /* Get the object pointer */
+ if((obj_ptr = H5I_object(obj_id)) == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier")
+
+ /* Get the object class */
+ if((obj_class = H5O_obj_class(oloc, H5AC_dxpl_id)) == NULL)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to determine object class")
+
+ /* Flush the object of this class */
+ if(obj_class->flush && obj_class->flush(obj_ptr, H5AC_dxpl_id) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTFLUSH, FAIL, "unable to flush object")
+
+ /* Flush the object metadata and invoke flush callback */
+ if(H5O_flush_common(oloc, obj_id) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTFLUSH, FAIL, "unable to flush object and object flush callback")
done:
FUNC_LEAVE_API(ret_value)
} /* H5Oflush */
+/*-------------------------------------------------------------------------
+ * Function: H5O_flush_common
+ *
+ * Purpose: Flushes the object's metadata
+ * Invokes the user-defined callback if there is one.
+ *
+ * Return: Non-negative on success, negative on failure
+ *
+ * Programmer: Vailin Choi; Dec 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O_flush_common(H5O_loc_t *oloc, hid_t obj_id)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Private function */
+ if(H5O_flush_metadata(oloc, H5AC_dxpl_id) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTFLUSH, FAIL, "unable to flush object metadata")
+
+ /* Check to invoke callback */
+ if(H5F_object_flush_cb(oloc->file, obj_id) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTFLUSH, FAIL, "unable to do object flush callback")
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+}
+
/*-------------------------------------------------------------------------
* Function: H5O_flush_metadata
diff --git a/src/H5Opkg.h b/src/H5Opkg.h
index b9f074e..1955ec4 100644
--- a/src/H5Opkg.h
+++ b/src/H5Opkg.h
@@ -330,7 +330,7 @@ typedef struct H5O_obj_class_t {
void *(*create)(H5F_t *, void *, H5G_loc_t *, hid_t ); /*create an object of this class */
H5O_loc_t *(*get_oloc)(hid_t ); /*get the object header location for an object */
herr_t (*bh_info)(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5_ih_info_t *bh_info); /*get the index & heap info for an object */
- herr_t (*flush)(H5G_loc_t *loc, hid_t dxpl_id); /*flush an opened object of this class */
+ herr_t (*flush)(void *obj_ptr, hid_t dxpl_id); /*flush an opened object of this class */
} H5O_obj_class_t;
/* Node in skip list to map addresses from one file to another during object header copy */
diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h
index 1a0f76c..0c9e779 100644
--- a/src/H5Oprivate.h
+++ b/src/H5Oprivate.h
@@ -832,6 +832,8 @@ H5_DLL herr_t H5O_msg_unlock(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_
/* Object metadata flush/evict routines */
H5_DLL herr_t H5O_flush_metadata(const H5O_loc_t *oloc, hid_t dxpl_id);
H5_DLL herr_t H5O_refresh_metadata(hid_t oid, H5O_loc_t oloc, hid_t dxpl_id);
+H5_DLL herr_t H5O_flush_common(H5O_loc_t *oloc, hid_t obj_id);
+
/* Object copying routines */
H5_DLL herr_t H5O_copy_header_map(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
diff --git a/src/H5Pdapl.c b/src/H5Pdapl.c
index 5239fba..17b91a9 100644
--- a/src/H5Pdapl.c
+++ b/src/H5Pdapl.c
@@ -61,6 +61,11 @@
#define H5D_ACS_PREEMPT_READ_CHUNKS_DEF H5D_CHUNK_CACHE_W0_DEFAULT
#define H5D_ACS_PREEMPT_READ_CHUNKS_ENC H5P__encode_double
#define H5D_ACS_PREEMPT_READ_CHUNKS_DEC H5P__decode_double
+/* Definition for append flush */
+#define H5D_ACS_APPEND_FLUSH_SIZE sizeof(H5D_append_flush_t)
+#define H5D_ACS_APPEND_FLUSH_DEF {0,{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},NULL,NULL}
+
+
/******************/
/* Local Typedefs */
@@ -109,7 +114,7 @@ const H5P_libclass_t H5P_CLS_DACC[1] = {{
/*******************/
/* Local Variables */
/*******************/
-
+static const H5D_append_flush_t H5D_def_append_flush_g = H5D_ACS_APPEND_FLUSH_DEF; /* Default setting for append flush */
/*-------------------------------------------------------------------------
@@ -149,6 +154,10 @@ H5P__dacc_reg_prop(H5P_genclass_t *pclass)
NULL, NULL, NULL, H5D_ACS_PREEMPT_READ_CHUNKS_ENC, H5D_ACS_PREEMPT_READ_CHUNKS_DEC, NULL, NULL, NULL, NULL) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+ /* Register info for append flush */
+ if(H5P_register_real(pclass, H5D_ACS_APPEND_FLUSH_NAME, H5D_ACS_APPEND_FLUSH_SIZE, &H5D_def_append_flush_g,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5P__dacc_reg_prop() */
@@ -281,3 +290,122 @@ done:
FUNC_LEAVE_API(ret_value)
}
+
+/*-------------------------------------------------------------------------
+ * Function: H5Pset_append_flush
+ *
+ * Purpose: Sets the boundary, callback function, and user data in the
+ * property list.
+ * "ndims": number of array elements for boundary
+ * "boundary": used to determine whether the current dimension hits
+ * a boundary; if so, invoke the callback function and
+ * flush the dataset.
+ * "func": the callback function to invoke when the boundary is hit
+ * "udata": the user data to pass as parameter with the callback function
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Vailin Choi; Dec 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pset_append_flush(hid_t plist_id, int ndims, const hsize_t *boundary, H5D_append_cb_t func, void *udata)
+{
+ H5P_genplist_t *plist; /* property list pointer */
+ H5D_append_flush_t info;
+ unsigned u; /* local index variable */
+ herr_t ret_value = SUCCEED; /* return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE5("e", "iIs*hx*x", plist_id, ndims, boundary, func, udata);
+
+ /* Check arguments */
+ if(ndims <= 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dimensionality cannot be negative or zero")
+ if(ndims > H5S_MAX_RANK)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dimensionality is too large")
+ if(!boundary)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no boundary dimensions specified")
+
+ /* Check if the callback function is NULL and the user data is non-NULL.
+ * This is almost certainly an error as the user data will not be used. */
+ if(!func && udata)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "callback is NULL while user data is not")
+
+ /* Get the plist structure */
+ if(NULL == (plist = H5P_object_verify(plist_id, H5P_DATASET_ACCESS)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
+
+ /* Set up values */
+ info.ndims = ndims;
+ info.func = func;
+ info.udata = udata;
+
+ HDmemset(info.boundary, 0, sizeof(info.boundary));
+ /* boundary can be 0 to indicate no boundary is set */
+ for(u = 0; u < (unsigned)ndims; u++) {
+ if(boundary[u] != (boundary[u] & 0xffffffff)) /* negative value (including H5S_UNLIMITED) */
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "all boundary dimensions must be less than 2^32")
+ info.boundary[u] = boundary[u]; /* Store user's boundary dimensions */
+ }
+
+ /* Set values */
+ if(H5P_set(plist, H5D_ACS_APPEND_FLUSH_NAME, &info) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set append flush")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* H5Pset_append_flush() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Pget_append_flush()
+ *
+ * Purpose: Retrieves the boundary, callback function and user data set in
+ * property list.
+ * Note that the # of boundary sizes to retrieve will not exceed
+ * the parameter "ndims" and the ndims set previously via
+ * H5Pset_append_flush().
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Vailin Choi; Dec 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pget_append_flush(hid_t plist_id, int ndims, hsize_t boundary[], H5D_append_cb_t *func, void **udata)
+{
+ H5P_genplist_t *plist; /* property list pointer */
+ H5D_append_flush_t info;
+ int i; /* local index variable */
+ herr_t ret_value = SUCCEED; /* return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE5("e", "iIs*h*x**x", plist_id, ndims, boundary, func, udata);
+
+ /* Get the plist structure */
+ if(NULL == (plist = H5P_object_verify(plist_id, H5P_DATASET_ACCESS)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
+
+ /* Retrieve info for append flush */
+ if(H5P_get(plist, H5D_ACS_APPEND_FLUSH_NAME, &info) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get object flush callback")
+
+ /* Assign return values */
+ if(boundary) {
+ HDmemset(boundary, 0, ndims * sizeof(hsize_t));
+ if(info.ndims > 0) {
+ for(i = 0; i < info.ndims && i < ndims; i++)
+ boundary[i] = info.boundary[i];
+ }
+ }
+ if(func)
+ *func = info.func;
+ if(udata)
+ *udata = info.udata;
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* H5Pget_append_flush() */
diff --git a/src/H5Pfapl.c b/src/H5Pfapl.c
index 8a09ed9..dd63457 100644
--- a/src/H5Pfapl.c
+++ b/src/H5Pfapl.c
@@ -162,9 +162,16 @@
#define H5F_ACS_FILE_IMAGE_INFO_CLOSE H5P_file_image_info_close
/* Definition for # of metadata read attempts */
#define H5F_ACS_METADATA_READ_ATTEMPTS_SIZE sizeof(unsigned)
-#define H5F_ACS_METADATA_READ_ATTEMPTS_DEF 0
-#define H5F_ACS_METADATA_READ_ATTEMPTS_ENC H5P__encode_unsigned
-#define H5F_ACS_METADATA_READ_ATTEMPTS_DEC H5P__decode_unsigned
+#define H5F_ACS_METADATA_READ_ATTEMPTS_DEF 0
+#define H5F_ACS_METADATA_READ_ATTEMPTS_ENC H5P__encode_unsigned
+#define H5F_ACS_METADATA_READ_ATTEMPTS_DEC H5P__decode_unsigned
+/* Definition for object flush callback */
+#define H5F_ACS_OBJECT_FLUSH_CB_SIZE sizeof(H5F_object_flush_t)
+#define H5F_ACS_OBJECT_FLUSH_CB_DEF {NULL, NULL}
+/* Definition for status_flags in the superblock */
+#define H5F_ACS_CLEAR_STATUS_FLAGS_SIZE sizeof(hbool_t)
+#define H5F_ACS_CLEAR_STATUS_FLAGS_DEF FALSE
+
/******************/
/* Local Typedefs */
@@ -252,6 +259,8 @@ static const hbool_t H5F_def_want_posix_fd_g = H5F_ACS_WANT_POSIX_FD_DEF;
static const unsigned H5F_def_efc_size_g = H5F_ACS_EFC_SIZE_DEF; /* Default external file cache size */
static const H5FD_file_image_info_t H5F_def_file_image_info_g = H5F_ACS_FILE_IMAGE_INFO_DEF; /* Default file image info and callbacks */
static const unsigned H5F_def_metadata_read_attempts_g = H5F_ACS_METADATA_READ_ATTEMPTS_DEF; /* Default setting for the # of metadata read attempts */
+static const H5F_object_flush_t H5F_def_object_flush_cb_g = H5F_ACS_OBJECT_FLUSH_CB_DEF; /* Default setting for object flush callback */
+static const hbool_t H5F_def_clear_status_flags_g = H5F_ACS_CLEAR_STATUS_FLAGS_DEF; /* Default to clear the superblock status_flags */
/*-------------------------------------------------------------------------
@@ -407,6 +416,17 @@ H5P_facc_reg_prop(H5P_genclass_t *pclass)
NULL, NULL, NULL, NULL) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+ /* Register object flush callback */
+ if(H5P_register_real(pclass, H5F_ACS_OBJECT_FLUSH_CB_NAME, H5F_ACS_OBJECT_FLUSH_CB_SIZE, &H5F_def_object_flush_cb_g,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+
+ /* Register the private property of whether to clear the superblock status_flags. It's used by h5clear only. */
+ if(H5P_register_real(pclass, H5F_ACS_CLEAR_STATUS_FLAGS_NAME, H5F_ACS_CLEAR_STATUS_FLAGS_SIZE, &H5F_def_clear_status_flags_g,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5P_facc_reg_prop() */
@@ -2608,7 +2628,7 @@ H5P__facc_cache_config_enc(const void *value, void **_pp, size_t *size)
H5_ENCODE_UNSIGNED(*pp, config->close_trace_file);
- HDmemcpy(*pp, (const uint8_t *)(config->trace_file_name), H5AC__MAX_TRACE_FILE_NAME_LEN + 1);
+ HDmemcpy(*pp, (const uint8_t *)(config->trace_file_name), (size_t)(H5AC__MAX_TRACE_FILE_NAME_LEN + 1));
*pp += H5AC__MAX_TRACE_FILE_NAME_LEN + 1;
H5_ENCODE_UNSIGNED(*pp, config->evictions_enabled);
@@ -3074,3 +3094,86 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Pget_metadata_read_attempts() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5Pset_obj_flush_cb
+ *
+ * Purpose: Sets the callback function to invoke and the user data when an
+ * object flush occurs in the file.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Vailin Choi; Dec 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pset_object_flush_cb(hid_t plist_id, H5F_flush_cb_t func, void *udata)
+{
+ H5P_genplist_t *plist; /* Property list pointer */
+ H5F_object_flush_t flush_info;
+ herr_t ret_value = SUCCEED; /* return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE3("e", "ix*x", plist_id, func, udata);
+
+ /* Check if the callback function is NULL and the user data is non-NULL.
+ * This is almost certainly an error as the user data will not be used. */
+ if(!func && udata)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "callback is NULL while user data is not")
+
+ /* Get the plist structure */
+ if(NULL == (plist = H5P_object_verify(plist_id, H5P_FILE_ACCESS)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
+
+ /* Update property list */
+ flush_info.func = func;
+ flush_info.udata = udata;
+
+ /* Set values */
+ if(H5P_set(plist, H5F_ACS_OBJECT_FLUSH_CB_NAME, &flush_info) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set object flush callback")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* H5Pset_obj_flush_cb() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5Pget_obj_flush_cb
+ *
+ * Purpose: Retrieves the callback function and user data set in the
+ * property list for an object flush.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Vailin Choi; Dec 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pget_object_flush_cb(hid_t plist_id, H5F_flush_cb_t *func, void **udata)
+{
+ H5P_genplist_t *plist; /* Property list pointer */
+ H5F_object_flush_t flush_info;
+ herr_t ret_value = SUCCEED; /* return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE3("e", "i*x**x", plist_id, func, udata);
+
+ /* Get the plist structure */
+ if(NULL == (plist = H5P_object_verify(plist_id, H5P_FILE_ACCESS)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
+
+ /* Retrieve the callback function and user data */
+ if(H5P_get(plist, H5F_ACS_OBJECT_FLUSH_CB_NAME, &flush_info) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get object flush callback")
+
+ /* Assign return value */
+ if(func)
+ *func = flush_info.func;
+ if(udata)
+ *udata = flush_info.udata;
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* H5Pget_obj_flush_cb() */
diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h
index cbb6f6a..3979c82 100644
--- a/src/H5Ppublic.h
+++ b/src/H5Ppublic.h
@@ -346,6 +346,9 @@ H5_DLL herr_t H5Pget_file_image_callbacks(hid_t fapl_id,
H5FD_file_image_callbacks_t *callbacks_ptr);
H5_DLL herr_t H5Pset_metadata_read_attempts(hid_t plist_id, unsigned attempts);
H5_DLL herr_t H5Pget_metadata_read_attempts(hid_t plist_id, unsigned *attempts);
+H5_DLL herr_t H5Pset_object_flush_cb(hid_t plist_id, H5F_flush_cb_t func, void *udata);
+H5_DLL herr_t H5Pget_object_flush_cb(hid_t plist_id, H5F_flush_cb_t *func, void **udata);
+
/* Dataset creation property list (DCPL) routines */
H5_DLL herr_t H5Pset_layout(hid_t plist_id, H5D_layout_t layout);
@@ -384,6 +387,10 @@ H5_DLL herr_t H5Pget_chunk_cache(hid_t dapl_id,
size_t *rdcc_nslots/*out*/,
size_t *rdcc_nbytes/*out*/,
double *rdcc_w0/*out*/);
+H5_DLL herr_t H5Pset_append_flush(hid_t plist_id,
+ int ndims, const hsize_t boundary[], H5D_append_cb_t func, void *udata);
+H5_DLL herr_t H5Pget_append_flush(hid_t plist_id,
+ int dims, hsize_t boundary[], H5D_append_cb_t *func, void **udata);
/* Dataset xfer property list (DXPL) routines */
H5_DLL herr_t H5Pset_data_transform(hid_t plist_id, const char* expression);
diff --git a/src/H5T.c b/src/H5T.c
index d545c4e..71873fe 100644
--- a/src/H5T.c
+++ b/src/H5T.c
@@ -5419,9 +5419,9 @@ H5Tflush(hid_t type_id)
if(!H5T_is_named(dt))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a committed datatype")
- /* Call private function to flush datatype object */
- if (H5O_flush_metadata(&dt->oloc, H5AC_dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFLUSH, FAIL, "unable to flush datatype")
+ /* To flush metadata and invoke flush callback if there is */
+ if(H5O_flush_common(&dt->oloc, type_id) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFLUSH, FAIL, "unable to flush datatype and object flush callback")
done:
FUNC_LEAVE_API(ret_value)
diff --git a/src/H5config.h.in b/src/H5config.h.in
index 02bafd8..7a73f1e 100644
--- a/src/H5config.h.in
+++ b/src/H5config.h.in
@@ -346,6 +346,9 @@
/* Define to 1 if you have the `system' function. */
#undef HAVE_SYSTEM
+/* Define to 1 if you have the <sys/file.h> header file. */
+#undef HAVE_SYS_FILE_H
+
/* Define to 1 if you have the <sys/fpu.h> header file. */
#undef HAVE_SYS_FPU_H
diff --git a/src/H5private.h b/src/H5private.h
index f54bd9d..9b89d23 100644
--- a/src/H5private.h
+++ b/src/H5private.h
@@ -119,6 +119,13 @@
#endif
/*
+ * flock() in sys/file.h is used for the implemention of file locking.
+ */
+#ifdef H5_HAVE_SYS_FILE_H
+# include <sys/file.h>
+#endif
+
+/*
* Resource usage is not Posix.1 but HDF5 uses it anyway for some performance
* and debugging code if available.
*/
@@ -704,6 +711,9 @@ typedef struct {
#ifndef HDfileno
#define HDfileno(F) fileno(F)
#endif /* HDfileno */
+#ifndef HDflock
+ #define HDflock(F,L) flock(F,L)
+#endif /* HDflock */
#ifndef HDfloor
#define HDfloor(X) floor(X)
#endif /* HDfloor */
diff --git a/test/Makefile.am b/test/Makefile.am
index 5f814ec..f1465fc 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -23,10 +23,21 @@ include $(top_srcdir)/config/commence.am
INCLUDES=-I$(top_srcdir)/src -I$(top_builddir)/src
-# Test script for error_test and err_compat
+# Test scripts--
+# testerror.sh: err_compat, error_test
+# testlibinfo.sh:
+# testcheck_version.sh: tcheck_version
+# tetlinks_env.sh: links_env
+# testflushrefresh.sh: flushrefresh
+# test_usecases.sh: use_append_chunk, use_append_mchunks
+# testswmr.sh: swmr*
TEST_SCRIPT = testerror.sh testlibinfo.sh testcheck_version.sh testlinks_env.sh \
- $(srcdir)/testswmr.sh testflushrefresh.sh test_usecases.sh
-SCRIPT_DEPEND = error_test$(EXEEXT) err_compat$(EXEEXT) links_env$(EXEEXT)
+ testflushrefresh.sh test_usecases.sh $(srcdir)/testswmr.sh
+SCRIPT_DEPEND = error_test$(EXEEXT) err_compat$(EXEEXT) links_env$(EXEEXT) \
+ flushrefresh$(EXEEXT) use_append_chunk$(EXEEXT) use_append_mchunks$(EXEEXT) \
+ swmr_generator$(EXEEXT) swmr_reader$(EXEEXT) swmr_writer$(EXEEXT) \
+ swmr_remove_reader$(EXEEXT) swmr_remove_writer$(EXEEXT) swmr_addrem_writer$(EXEEXT) \
+ swmr_sparse_reader$(EXEEXT) swmr_sparse_writer$(EXEEXT) swmr_start_write$(EXEEXT)
if HAVE_SHARED_CONDITIONAL
TEST_SCRIPT += test_plugin.sh
SCRIPT_DEPEND += plugin$(EXEEXT)
@@ -43,25 +54,33 @@ check_SCRIPTS = $(TEST_SCRIPT)
# other current library code tests.
TEST_PROG= testhdf5 lheap ohdr stab gheap cache cache_api cache_tagging \
pool accum hyperslab istore bittests dt_arith \
- dtypes dsets cmpd_dset filter_fail extend external efc objcopy\
- links twriteorder unlink \
- big mtime fillval mount flush1 flush2 app_ref enum \
+ dtypes dsets cmpd_dset filter_fail extend external efc objcopy links unlink \
+ twriteorder big mtime fillval mount flush1 flush2 app_ref enum \
set_extent ttsafe enc_dec_plist enc_dec_plist_with_endianess\
getname vfd ntypes dangle dtransform reserved cross_read \
- freespace mf farray earray btree2 fheap file_image unregister
+ freespace mf farray earray btree2 fheap file_image unregister test_swmr
-bin_PROGRAMS=swmr_generator swmr_reader swmr_writer swmr_remove_reader \
+bin_PROGRAMS=swmr_generator swmr_start_write swmr_reader swmr_writer swmr_remove_reader \
swmr_remove_writer swmr_addrem_writer swmr_sparse_reader swmr_sparse_writer \
use_append_chunk use_append_mchunks atomic_writer atomic_reader accum_swmr_reader
-# List programs to be built when testing here. error_test and err_compat are
-# built at the same time as the other tests, but executed by testerror.sh.
+# List programs to be built when testing here.
+# error_test and err_compat are built at the same time as the other tests, but executed by testerror.sh.
# tcheck_version is used by testcheck_version.sh.
+# accum_swmr_reader is used by accum.c.
+# atomic_writer and atomic_reader are standalone programs.
+# links_env is used by testlinks_env.sh
+# flushrefresh is used by testflushrefresh.sh.
+# use_append_chunk and use_append_mchunks are used by test_usecases.sh
+# swmr* files are used by testswmr.sh.
# 'make check' doesn't run them directly, so they are not included in TEST_PROG.
# Also build testmeta, which is used for timings test. It builds quickly,
# and this lets automake keep all its test programs in one place.
-check_PROGRAMS=$(TEST_PROG) error_test err_compat tcheck_version testmeta links_env \
- flushrefresh
+check_PROGRAMS=$(TEST_PROG) error_test err_compat tcheck_version \
+ testmeta accum_swmr_reader atomic_writer atomic_reader \
+ links_env flushrefresh use_append_chunk use_append_mchunks \
+ swmr_generator swmr_start_write swmr_reader swmr_writer swmr_remove_reader \
+ swmr_remove_writer swmr_addrem_writer swmr_sparse_reader swmr_sparse_writer
if HAVE_SHARED_CONDITIONAL
check_PROGRAMS+= plugin
endif
@@ -160,10 +179,10 @@ CHECK_CLEANFILES+=accum.h5 cmpd_dset.h5 compact_dataset.h5 dataset.h5 \
new_multi_file_v16-r.h5 new_multi_file_v16-s.h5 \
split_get_file_image_test-m.h5 split_get_file_image_test-r.h5 \
file_image_core_test.h5.copy unregister_filter_1.h5 unregister_filter_2.h5 \
- swmr_data.h5 use_append_chunk.h5 use_append_mchunks.h5 \
+ swmr_data.h5 use_use_append_chunk.h5 use_append_mchunks.h5 \
flushrefresh.h5 flushrefresh_VERIFICATION_START \
flushrefresh_VERIFICATION_CHECKPOINT1 flushrefresh_VERIFICATION_CHECKPOINT2 \
- flushrefresh_VERIFICATION_DONE atomic_data accum_swmr_big.h5 ohdr_swmr.h5
+ flushrefresh_VERIFICATION_DONE atomic_data accum_swmr_big.h5 ohdr_swmr.h5 test_swmr.h5
# Sources for testhdf5 executable
testhdf5_SOURCES=testhdf5.c tarray.c tattr.c tchecksum.c tconfig.c tfile.c \
diff --git a/test/Makefile.in b/test/Makefile.in
index ce8c39a..7872c2c 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -79,16 +79,24 @@ DIST_COMMON = $(srcdir)/H5srcdir_str.h.in $(srcdir)/Makefile.am \
$(top_srcdir)/config/conclude.am COPYING
@HAVE_SHARED_CONDITIONAL_TRUE@am__append_1 = test_plugin.sh
@HAVE_SHARED_CONDITIONAL_TRUE@am__append_2 = plugin$(EXEEXT)
-bin_PROGRAMS = swmr_generator$(EXEEXT) swmr_reader$(EXEEXT) \
+bin_PROGRAMS = swmr_generator$(EXEEXT) swmr_start_write$(EXEEXT) \
+ swmr_reader$(EXEEXT) swmr_writer$(EXEEXT) \
+ swmr_remove_reader$(EXEEXT) swmr_remove_writer$(EXEEXT) \
+ swmr_addrem_writer$(EXEEXT) swmr_sparse_reader$(EXEEXT) \
+ swmr_sparse_writer$(EXEEXT) use_append_chunk$(EXEEXT) \
+ use_append_mchunks$(EXEEXT) atomic_writer$(EXEEXT) \
+ atomic_reader$(EXEEXT) accum_swmr_reader$(EXEEXT)
+check_PROGRAMS = $(am__EXEEXT_1) error_test$(EXEEXT) \
+ err_compat$(EXEEXT) tcheck_version$(EXEEXT) testmeta$(EXEEXT) \
+ accum_swmr_reader$(EXEEXT) atomic_writer$(EXEEXT) \
+ atomic_reader$(EXEEXT) links_env$(EXEEXT) \
+ flushrefresh$(EXEEXT) use_append_chunk$(EXEEXT) \
+ use_append_mchunks$(EXEEXT) swmr_generator$(EXEEXT) \
+ swmr_start_write$(EXEEXT) swmr_reader$(EXEEXT) \
swmr_writer$(EXEEXT) swmr_remove_reader$(EXEEXT) \
swmr_remove_writer$(EXEEXT) swmr_addrem_writer$(EXEEXT) \
swmr_sparse_reader$(EXEEXT) swmr_sparse_writer$(EXEEXT) \
- use_append_chunk$(EXEEXT) use_append_mchunks$(EXEEXT) \
- atomic_writer$(EXEEXT) atomic_reader$(EXEEXT) \
- accum_swmr_reader$(EXEEXT)
-check_PROGRAMS = $(am__EXEEXT_1) error_test$(EXEEXT) \
- err_compat$(EXEEXT) tcheck_version$(EXEEXT) testmeta$(EXEEXT) \
- links_env$(EXEEXT) flushrefresh$(EXEEXT) $(am__EXEEXT_2)
+ $(am__EXEEXT_2)
@HAVE_SHARED_CONDITIONAL_TRUE@am__append_3 = plugin
@BUILD_ALL_CONDITIONAL_TRUE@noinst_PROGRAMS = $(am__EXEEXT_3)
@DIRECT_VFD_CONDITIONAL_TRUE@am__append_4 = direct
@@ -168,7 +176,7 @@ am__EXEEXT_1 = testhdf5$(EXEEXT) lheap$(EXEEXT) ohdr$(EXEEXT) \
dt_arith$(EXEEXT) dtypes$(EXEEXT) dsets$(EXEEXT) \
cmpd_dset$(EXEEXT) filter_fail$(EXEEXT) extend$(EXEEXT) \
external$(EXEEXT) efc$(EXEEXT) objcopy$(EXEEXT) links$(EXEEXT) \
- twriteorder$(EXEEXT) unlink$(EXEEXT) big$(EXEEXT) \
+ unlink$(EXEEXT) twriteorder$(EXEEXT) big$(EXEEXT) \
mtime$(EXEEXT) fillval$(EXEEXT) mount$(EXEEXT) flush1$(EXEEXT) \
flush2$(EXEEXT) app_ref$(EXEEXT) enum$(EXEEXT) \
set_extent$(EXEEXT) ttsafe$(EXEEXT) enc_dec_plist$(EXEEXT) \
@@ -177,7 +185,7 @@ am__EXEEXT_1 = testhdf5$(EXEEXT) lheap$(EXEEXT) ohdr$(EXEEXT) \
dtransform$(EXEEXT) reserved$(EXEEXT) cross_read$(EXEEXT) \
freespace$(EXEEXT) mf$(EXEEXT) farray$(EXEEXT) earray$(EXEEXT) \
btree2$(EXEEXT) fheap$(EXEEXT) file_image$(EXEEXT) \
- unregister$(EXEEXT)
+ unregister$(EXEEXT) test_swmr$(EXEEXT)
@HAVE_SHARED_CONDITIONAL_TRUE@am__EXEEXT_2 = plugin$(EXEEXT)
am__EXEEXT_3 = gen_bad_ohdr$(EXEEXT) gen_bogus$(EXEEXT) \
gen_cross$(EXEEXT) gen_deflate$(EXEEXT) gen_filters$(EXEEXT) \
@@ -514,6 +522,10 @@ swmr_sparse_writer_SOURCES = swmr_sparse_writer.c
swmr_sparse_writer_OBJECTS = swmr_sparse_writer.$(OBJEXT)
swmr_sparse_writer_LDADD = $(LDADD)
swmr_sparse_writer_DEPENDENCIES = libh5test.la $(LIBHDF5)
+swmr_start_write_SOURCES = swmr_start_write.c
+swmr_start_write_OBJECTS = swmr_start_write.$(OBJEXT)
+swmr_start_write_LDADD = $(LDADD)
+swmr_start_write_DEPENDENCIES = libh5test.la $(LIBHDF5)
swmr_writer_SOURCES = swmr_writer.c
swmr_writer_OBJECTS = swmr_writer.$(OBJEXT)
swmr_writer_LDADD = $(LDADD)
@@ -522,6 +534,10 @@ tcheck_version_SOURCES = tcheck_version.c
tcheck_version_OBJECTS = tcheck_version.$(OBJEXT)
tcheck_version_LDADD = $(LDADD)
tcheck_version_DEPENDENCIES = libh5test.la $(LIBHDF5)
+test_swmr_SOURCES = test_swmr.c
+test_swmr_OBJECTS = test_swmr.$(OBJEXT)
+test_swmr_LDADD = $(LDADD)
+test_swmr_DEPENDENCIES = libh5test.la $(LIBHDF5)
am_testhdf5_OBJECTS = testhdf5.$(OBJEXT) tarray.$(OBJEXT) \
tattr.$(OBJEXT) tchecksum.$(OBJEXT) tconfig.$(OBJEXT) \
tfile.$(OBJEXT) tgenprop.$(OBJEXT) th5o.$(OBJEXT) \
@@ -624,10 +640,10 @@ SOURCES = $(libdynlib1_la_SOURCES) $(libdynlib2_la_SOURCES) \
set_extent.c space_overflow.c stab.c swmr_addrem_writer.c \
swmr_generator.c swmr_reader.c swmr_remove_reader.c \
swmr_remove_writer.c swmr_sparse_reader.c swmr_sparse_writer.c \
- swmr_writer.c tcheck_version.c $(testhdf5_SOURCES) testmeta.c \
- $(ttsafe_SOURCES) twriteorder.c unlink.c unregister.c \
- $(use_append_chunk_SOURCES) $(use_append_mchunks_SOURCES) \
- vfd.c
+ swmr_start_write.c swmr_writer.c tcheck_version.c test_swmr.c \
+ $(testhdf5_SOURCES) testmeta.c $(ttsafe_SOURCES) twriteorder.c \
+ unlink.c unregister.c $(use_append_chunk_SOURCES) \
+ $(use_append_mchunks_SOURCES) vfd.c
DIST_SOURCES = $(am__libdynlib1_la_SOURCES_DIST) \
$(am__libdynlib2_la_SOURCES_DIST) \
$(am__libdynlib3_la_SOURCES_DIST) $(libh5test_la_SOURCES) \
@@ -649,10 +665,10 @@ DIST_SOURCES = $(am__libdynlib1_la_SOURCES_DIST) \
set_extent.c space_overflow.c stab.c swmr_addrem_writer.c \
swmr_generator.c swmr_reader.c swmr_remove_reader.c \
swmr_remove_writer.c swmr_sparse_reader.c swmr_sparse_writer.c \
- swmr_writer.c tcheck_version.c $(testhdf5_SOURCES) testmeta.c \
- $(ttsafe_SOURCES) twriteorder.c unlink.c unregister.c \
- $(use_append_chunk_SOURCES) $(use_append_mchunks_SOURCES) \
- vfd.c
+ swmr_start_write.c swmr_writer.c tcheck_version.c test_swmr.c \
+ $(testhdf5_SOURCES) testmeta.c $(ttsafe_SOURCES) twriteorder.c \
+ unlink.c unregister.c $(use_append_chunk_SOURCES) \
+ $(use_append_mchunks_SOURCES) vfd.c
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@@ -977,21 +993,34 @@ CHECK_CLEANFILES = *.chkexe *.chklog *.clog accum.h5 cmpd_dset.h5 \
new_multi_file_v16-r.h5 new_multi_file_v16-s.h5 \
split_get_file_image_test-m.h5 split_get_file_image_test-r.h5 \
file_image_core_test.h5.copy unregister_filter_1.h5 \
- unregister_filter_2.h5 swmr_data.h5 use_append_chunk.h5 \
+ unregister_filter_2.h5 swmr_data.h5 use_use_append_chunk.h5 \
use_append_mchunks.h5 flushrefresh.h5 \
flushrefresh_VERIFICATION_START \
flushrefresh_VERIFICATION_CHECKPOINT1 \
flushrefresh_VERIFICATION_CHECKPOINT2 \
flushrefresh_VERIFICATION_DONE atomic_data accum_swmr_big.h5 \
- ohdr_swmr.h5
+ ohdr_swmr.h5 test_swmr.h5
INCLUDES = -I$(top_srcdir)/src -I$(top_builddir)/src
-# Test script for error_test and err_compat
+# Test scripts--
+# testerror.sh: err_compat, error_test
+# testlibinfo.sh:
+# testcheck_version.sh: tcheck_version
+# tetlinks_env.sh: links_env
+# testflushrefresh.sh: flushrefresh
+# test_usecases.sh: use_append_chunk, use_append_mchunks
+# testswmr.sh: swmr*
TEST_SCRIPT = testerror.sh testlibinfo.sh testcheck_version.sh \
- testlinks_env.sh $(srcdir)/testswmr.sh testflushrefresh.sh \
- test_usecases.sh $(am__append_1)
+ testlinks_env.sh testflushrefresh.sh test_usecases.sh \
+ $(srcdir)/testswmr.sh $(am__append_1)
SCRIPT_DEPEND = error_test$(EXEEXT) err_compat$(EXEEXT) \
- links_env$(EXEEXT) $(am__append_2)
+ links_env$(EXEEXT) flushrefresh$(EXEEXT) \
+ use_append_chunk$(EXEEXT) use_append_mchunks$(EXEEXT) \
+ swmr_generator$(EXEEXT) swmr_reader$(EXEEXT) \
+ swmr_writer$(EXEEXT) swmr_remove_reader$(EXEEXT) \
+ swmr_remove_writer$(EXEEXT) swmr_addrem_writer$(EXEEXT) \
+ swmr_sparse_reader$(EXEEXT) swmr_sparse_writer$(EXEEXT) \
+ swmr_start_write$(EXEEXT) $(am__append_2)
check_SCRIPTS = $(TEST_SCRIPT)
# These are our main targets. They should be listed in the order to be
@@ -1003,12 +1032,11 @@ check_SCRIPTS = $(TEST_SCRIPT)
# other current library code tests.
TEST_PROG = testhdf5 lheap ohdr stab gheap cache cache_api cache_tagging \
pool accum hyperslab istore bittests dt_arith \
- dtypes dsets cmpd_dset filter_fail extend external efc objcopy\
- links twriteorder unlink \
- big mtime fillval mount flush1 flush2 app_ref enum \
+ dtypes dsets cmpd_dset filter_fail extend external efc objcopy links unlink \
+ twriteorder big mtime fillval mount flush1 flush2 app_ref enum \
set_extent ttsafe enc_dec_plist enc_dec_plist_with_endianess\
getname vfd ntypes dangle dtransform reserved cross_read \
- freespace mf farray earray btree2 fheap file_image unregister
+ freespace mf farray earray btree2 fheap file_image unregister test_swmr
# These programs generate test files for the tests. They don't need to be
@@ -1486,12 +1514,18 @@ swmr_sparse_reader$(EXEEXT): $(swmr_sparse_reader_OBJECTS) $(swmr_sparse_reader_
swmr_sparse_writer$(EXEEXT): $(swmr_sparse_writer_OBJECTS) $(swmr_sparse_writer_DEPENDENCIES) $(EXTRA_swmr_sparse_writer_DEPENDENCIES)
@rm -f swmr_sparse_writer$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(swmr_sparse_writer_OBJECTS) $(swmr_sparse_writer_LDADD) $(LIBS)
+swmr_start_write$(EXEEXT): $(swmr_start_write_OBJECTS) $(swmr_start_write_DEPENDENCIES) $(EXTRA_swmr_start_write_DEPENDENCIES)
+ @rm -f swmr_start_write$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(swmr_start_write_OBJECTS) $(swmr_start_write_LDADD) $(LIBS)
swmr_writer$(EXEEXT): $(swmr_writer_OBJECTS) $(swmr_writer_DEPENDENCIES) $(EXTRA_swmr_writer_DEPENDENCIES)
@rm -f swmr_writer$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(swmr_writer_OBJECTS) $(swmr_writer_LDADD) $(LIBS)
tcheck_version$(EXEEXT): $(tcheck_version_OBJECTS) $(tcheck_version_DEPENDENCIES) $(EXTRA_tcheck_version_DEPENDENCIES)
@rm -f tcheck_version$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(tcheck_version_OBJECTS) $(tcheck_version_LDADD) $(LIBS)
+test_swmr$(EXEEXT): $(test_swmr_OBJECTS) $(test_swmr_DEPENDENCIES) $(EXTRA_test_swmr_DEPENDENCIES)
+ @rm -f test_swmr$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_swmr_OBJECTS) $(test_swmr_LDADD) $(LIBS)
testhdf5$(EXEEXT): $(testhdf5_OBJECTS) $(testhdf5_DEPENDENCIES) $(EXTRA_testhdf5_DEPENDENCIES)
@rm -f testhdf5$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(testhdf5_OBJECTS) $(testhdf5_LDADD) $(LIBS)
@@ -1613,6 +1647,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/swmr_remove_writer.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/swmr_sparse_reader.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/swmr_sparse_writer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/swmr_start_write.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/swmr_writer.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tarray.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tattr.Po@am__quote@
@@ -1620,6 +1655,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tchecksum.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tconfig.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcoords.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_swmr.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testframe.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testhdf5.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testmeta.Po@am__quote@
diff --git a/test/accum.c b/test/accum.c
index fc7546d..b37a1bd 100644
--- a/test/accum.c
+++ b/test/accum.c
@@ -1672,7 +1672,7 @@ test_random_write(void)
/* Allocate space for the write & read buffers */
wbuf = (uint8_t *)HDmalloc((size_t)RANDOM_BUF_SIZE);
HDassert(wbuf);
- rbuf = (uint8_t *)HDcalloc((size_t)RANDOM_BUF_SIZE, 1);
+ rbuf = (uint8_t *)HDcalloc((size_t)RANDOM_BUF_SIZE, (size_t)1);
HDassert(rbuf);
/* Initialize write buffer */
@@ -1815,6 +1815,14 @@ test_swmr_write_big(void)
TESTING("SWMR write of large metadata");
+ #if !(defined(H5_HAVE_FORK) && defined(H5_HAVE_WAITPID))
+
+ SKIPPED();
+ HDputs(" Test skipped due to fork or waitpid not defined.");
+ return 0;
+
+#else /* defined(H5_HAVE_FORK && defined(H5_HAVE_WAITPID) */
+
/* File access property list */
if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0)
FAIL_STACK_ERROR
@@ -1941,6 +1949,9 @@ error:
if(rbuf) HDfree(rbuf);
return 1;
+
+#endif
+
} /* end test_swmr_write_big() */
diff --git a/test/accum_swmr_reader.c b/test/accum_swmr_reader.c
index b9bf98d..034ed46 100644
--- a/test/accum_swmr_reader.c
+++ b/test/accum_swmr_reader.c
@@ -65,7 +65,7 @@ main(void)
FAIL_STACK_ERROR;
/* Verify the data read is correct */
- if(HDmemcmp(buf, rbuf, 1024) != 0)
+ if(HDmemcmp(buf, rbuf, (size_t)1024) != 0)
TEST_ERROR;
/* CLose the file */
diff --git a/test/bad_compound.h5 b/test/bad_compound.h5
index 1834a2e..1c96318 100644
--- a/test/bad_compound.h5
+++ b/test/bad_compound.h5
Binary files differ
diff --git a/test/btree_idx_1_6.h5 b/test/btree_idx_1_6.h5
index b1ac4da..92f939b 100644
--- a/test/btree_idx_1_6.h5
+++ b/test/btree_idx_1_6.h5
Binary files differ
diff --git a/test/corrupt_stab_msg.h5 b/test/corrupt_stab_msg.h5
index 4fa287c..a00616d 100644
--- a/test/corrupt_stab_msg.h5
+++ b/test/corrupt_stab_msg.h5
Binary files differ
diff --git a/test/deflate.h5 b/test/deflate.h5
index 2f62e25..e33af4f 100644
--- a/test/deflate.h5
+++ b/test/deflate.h5
Binary files differ
diff --git a/test/family_v16_00000.h5 b/test/family_v16_00000.h5
index ac75ea9..aaa3dad 100644
--- a/test/family_v16_00000.h5
+++ b/test/family_v16_00000.h5
Binary files differ
diff --git a/test/file_image.c b/test/file_image.c
index b1b9d47..2eea59b 100644
--- a/test/file_image.c
+++ b/test/file_image.c
@@ -41,6 +41,8 @@
#define FAMILY_SIZE (2 * 1024)
+#define USERBLOCK_SIZE 512
+
const char *FILENAME[] = {
"file_image_core_test",
NULL
@@ -549,7 +551,7 @@ test_core(void)
VERIFY(fapl >= 0, "fapl creation failed");
/* Set up the core VFD */
- ret = H5Pset_fapl_core(fapl, 0, 0);
+ ret = H5Pset_fapl_core(fapl, (size_t)0, 0);
VERIFY(ret >= 0, "setting core driver in fapl failed");
tmp = h5_fixname(FILENAME[0], fapl, filename, sizeof(filename));
@@ -665,12 +667,17 @@ error:
* Programmer: John Mainzer
* Tuesday, November 15, 2011
*
+ * Modifications:
+ * Vailin Choi; July 2013
+ * Add the creation of user block to the file as indicated by the parameter "user".
+ *
******************************************************************************
*/
static int
test_get_file_image(const char * test_banner,
const int file_name_num,
- hid_t fapl)
+ hid_t fapl,
+ hbool_t user)
{
char file_name[1024] = "\0";
void * insertion_ptr = NULL;
@@ -694,6 +701,8 @@ test_get_file_image(const char * test_banner,
ssize_t image_size;
ssize_t file_size;
h5_stat_t stat_buf;
+ hid_t fcpl = -1;
+ herr_t ret;
TESTING(test_banner);
@@ -708,8 +717,15 @@ test_get_file_image(const char * test_banner,
h5_fixname(FILENAME2[file_name_num], fapl, file_name, sizeof(file_name));
VERIFY(HDstrlen(file_name)>0, "h5_fixname failed");
+ fcpl = H5Pcreate(H5P_FILE_CREATE);
+ VERIFY(fcpl >= 0, "H5Pcreate");
+ if(user) {
+ ret = H5Pset_userblock(fcpl, (hsize_t)USERBLOCK_SIZE);
+ VERIFY(ret >=0, "H5Pset_userblock");
+ }
+
/* create the file */
- file_id = H5Fcreate(file_name, 0, H5P_DEFAULT, fapl);
+ file_id = H5Fcreate(file_name, 0, fcpl, fapl);
VERIFY(file_id >= 0, "H5Fcreate() failed.");
/* Set up data space for new new data set */
@@ -761,11 +777,15 @@ test_get_file_image(const char * test_banner,
ssize_t member_size;
ssize_t size_remaining;
+ /*
+ * Modifications need to be made to accommodate userblock when
+ * H5Fget_file_image() works for family driver
+ */
i = 0;
file_size = 0;
do {
- HDsnprintf(member_file_name, 1024, file_name, i);
+ HDsnprintf(member_file_name, (size_t)1024, file_name, i);
/* get the size of the member file */
result = HDstat(member_file_name, &stat_buf);
@@ -829,6 +849,10 @@ test_get_file_image(const char * test_banner,
* the remainder of the file is all '\0's.
*/
file_size = (ssize_t)stat_buf.st_size;
+ if(user) {
+ VERIFY(file_size > USERBLOCK_SIZE, "file size !> userblock size.");
+ file_size -= USERBLOCK_SIZE;
+ }
/* with latest mods to truncate call in core file drive,
* file size should match image size
@@ -843,6 +867,12 @@ test_get_file_image(const char * test_banner,
fd = HDopen(file_name, O_RDONLY, 0666);
VERIFY(fd >= 0, "HDopen() failed.");
+ if(user) {
+ /* Position at userblock */
+ ret = HDlseek(fd, (off_t)USERBLOCK_SIZE, SEEK_SET);
+ VERIFY(ret >= 0, "HDlseek() failed.");
+ }
+
/* read the test file from disk into the buffer */
bytes_read = HDread(fd, file_image_ptr, (size_t)file_size);
VERIFY(bytes_read == file_size, "HDread() failed.");
@@ -1278,13 +1308,18 @@ test_get_file_image_error_rejection(void)
error:
return 1;
-}
+} /* test_get_file_image_error_rejection() */
+/*
+ * Modifications:
+ * Add testing for file image with or without user block in the file.
+ */
int
main(void)
{
int errors = 0;
hid_t fapl;
+ hbool_t user;
h5_reset();
@@ -1294,29 +1329,34 @@ main(void)
errors += test_callbacks();
errors += test_core();
- /* test H5Fget_file_image() with sec2 driver */
- fapl = H5Pcreate(H5P_FILE_ACCESS);
- if(H5Pset_fapl_sec2(fapl) < 0)
- errors++;
- else
- errors += test_get_file_image("H5Fget_file_image() with sec2 driver",
- 0, fapl);
-
- /* test H5Fget_file_image() with stdio driver */
- fapl = H5Pcreate(H5P_FILE_ACCESS);
- if(H5Pset_fapl_stdio(fapl) < 0)
- errors++;
- else
- errors += test_get_file_image("H5Fget_file_image() with stdio driver",
- 1, fapl);
-
- /* test H5Fget_file_image() with core driver */
- fapl = H5Pcreate(H5P_FILE_ACCESS);
- if(H5Pset_fapl_core(fapl, (size_t)(64 *1024), TRUE) < 0)
- errors++;
- else
- errors += test_get_file_image("H5Fget_file_image() with core driver",
- 2, fapl);
+ /* Perform tests with/without user block */
+ for(user = FALSE; user <= TRUE; user++) {
+
+ /* test H5Fget_file_image() with sec2 driver */
+ fapl = H5Pcreate(H5P_FILE_ACCESS);
+ if(H5Pset_fapl_sec2(fapl) < 0)
+ errors++;
+ else
+ errors += test_get_file_image("H5Fget_file_image() with sec2 driver",
+ 0, fapl, user);
+
+ /* test H5Fget_file_image() with stdio driver */
+ fapl = H5Pcreate(H5P_FILE_ACCESS);
+ if(H5Pset_fapl_stdio(fapl) < 0)
+ errors++;
+ else
+ errors += test_get_file_image("H5Fget_file_image() with stdio driver",
+ 1, fapl, user);
+
+ /* test H5Fget_file_image() with core driver */
+ fapl = H5Pcreate(H5P_FILE_ACCESS);
+ if(H5Pset_fapl_core(fapl, (size_t)(64 *1024), TRUE) < 0)
+ errors++;
+ else
+ errors += test_get_file_image("H5Fget_file_image() with core driver",
+ 2, fapl, user);
+
+ } /* end for */
#if 0
/* at present, H5Fget_file_image() rejects files opened with the
diff --git a/test/filespace_1_6.h5 b/test/filespace_1_6.h5
index 5afc718..c8aa9df 100644
--- a/test/filespace_1_6.h5
+++ b/test/filespace_1_6.h5
Binary files differ
diff --git a/test/fill_old.h5 b/test/fill_old.h5
index e77f519..4dd7740 100644
--- a/test/fill_old.h5
+++ b/test/fill_old.h5
Binary files differ
diff --git a/test/flush2.c b/test/flush2.c
index 06dd086..8459087 100644
--- a/test/flush2.c
+++ b/test/flush2.c
@@ -24,6 +24,11 @@
*/
#include "h5test.h"
+/* Make this private property (defined in H5Fprivate.h) available */
+/* This is used in the helper routine clear_status_flags() */
+#define H5F_ACS_CLEAR_STATUS_FLAGS_NAME "clear_status_flags"
+
+
const char *FILENAME[] = {
"flush",
"noflush",
@@ -135,6 +140,53 @@ error:
return 1;
} /* end check_file() */
+/*-------------------------------------------------------------------------
+ * Function: clear_status_flags
+ *
+ * Purpose: To clear the status_flags in the superblock of the file.
+ * It is smilar to the tool "h5clear".
+ *
+ * Return: Success: 0
+ * Failure: 1
+ *
+ * Programmer: Vailin Choi
+ * July 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+clear_status_flags(char *name, hid_t fapl)
+{
+ hid_t new_fapl = -1;
+ hid_t fid = -1;
+ hbool_t clear = TRUE;
+
+ /* Get a copy of fapl */
+ if((new_fapl = H5Pcopy(fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Set this private property */
+ if(H5Pset(new_fapl, H5F_ACS_CLEAR_STATUS_FLAGS_NAME, &clear) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Has to open rw */
+ if((fid = H5Fopen(name, H5F_ACC_RDWR, new_fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /* CLose the property list */
+ if(H5Pclose(new_fapl) < 0)
+ FAIL_STACK_ERROR;
+
+ return 0;
+
+error:
+ return 1;
+} /* clear_status_flags() */
+
/*-------------------------------------------------------------------------
* Function: main
@@ -167,6 +219,13 @@ main(void)
/* Check the case where the file was flushed */
h5_fixname(FILENAME[0], fapl, name, sizeof name);
+
+ /* Clear the status_flags of the file which is flushed and exited in flush1.c */
+ if(clear_status_flags(name, fapl) < 0) {
+ H5_FAILED()
+ goto error;
+ }
+
if(check_file(name, fapl, FALSE)) {
H5_FAILED()
goto error;
@@ -182,6 +241,8 @@ main(void)
H5Eset_auto2(H5E_DEFAULT, NULL, NULL);
h5_fixname(FILENAME[1], fapl, name, sizeof name);
+ /* No need to clear the status_flags because this file is not flushed in flush1.c */
+ /* H5Fopen() in check_file() will just return error */
if(check_file(name, fapl, FALSE))
PASSED()
else
@@ -205,6 +266,13 @@ main(void)
H5Eset_auto2(H5E_DEFAULT, NULL, NULL);
h5_fixname(FILENAME[2], fapl, name, sizeof name);
+
+ /* Clear the status_flags of the file which is flushed and exited in flush1.c */
+ if(clear_status_flags(name, fapl) < 0) {
+ H5_FAILED()
+ goto error;
+ }
+
if(check_file(name, fapl, TRUE))
PASSED()
else
diff --git a/test/group_old.h5 b/test/group_old.h5
index 58f66f8..2440103 100644
--- a/test/group_old.h5
+++ b/test/group_old.h5
Binary files differ
diff --git a/test/h5test.c b/test/h5test.c
index 30a3adf..79b97cc 100644
--- a/test/h5test.c
+++ b/test/h5test.c
@@ -1231,3 +1231,56 @@ error:
return -1;
}
+/*
+ * To send a message by creating the file.
+ * This is a helper routine used in:
+ * 1) tfile.c: test_file_lock_concur() and test_file_lock_swmr_concur()
+ * 2) use_common.c
+ * 3) swmr_addrme_writer.c, swmr_remove_writer.c, swmr_sparse_writer.c, swmr_writer.c
+ */
+void
+h5_send_message(const char *file)
+{
+ FILE *id;
+
+ id = HDfopen(file, "w+");
+ HDfclose(id);
+} /* h5_send_message() */
+
+/*
+ * Repeatedly check for the message file.
+ * It will stop when the file exists or exceeds the timeout limit.
+ * This is a helper routine used in:
+ * 1) tfile.c: test_file_lock_concur() and test_file_lock_swmr_concur()
+ * 2) use_common.c
+ */
+int
+h5_wait_message(const char *file)
+{
+ FILE *id; /* File pointer */
+ time_t t0, t1; /* Time info */
+
+ /* Start timer */
+ HDtime(&t0);
+
+ /* Repeatedly check whether the file exists */
+ while((id = HDfopen(file, "r")) == NULL) {
+ /* Get current time */
+ HDtime(&t1);
+ /*
+ * Determine time difference--
+ * if waiting too long for the message, then it is
+ * unlikely the message will get sent, then fail rather
+ * than loop forever.
+ */
+ if(HDdifftime(t1, t0) > MESSAGE_TIMEOUT)
+ goto done;
+ }
+
+ if(id != NULL) HDfclose(id);
+ HDunlink(file);
+ return(1);
+
+done:
+ return(-1);
+} /* h5_wait_message() */
diff --git a/test/h5test.h b/test/h5test.h
index 7813b51..745fe85 100644
--- a/test/h5test.h
+++ b/test/h5test.h
@@ -136,6 +136,9 @@ H5TEST_DLLVAR MPI_Info h5_io_info_g; /* MPI INFO object for IO */
#define DBL_REL_EQUAL(X,Y,M) (fabs((Y-X)/X)<M)
#define LDBL_REL_EQUAL(X,Y,M) (fabsl((Y-X)/X)<M)
+/* The # of seconds to wait for the message file--used by h5_wait_message() */
+#define MESSAGE_TIMEOUT 300 /* Timeout in seconds */
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -194,6 +197,9 @@ H5TEST_DLL char* getenv_all(MPI_Comm comm, int root, const char* name);
/* Extern global variables */
H5TEST_DLLVAR int TestVerbosity;
+H5TEST_DLL void h5_send_message(const char *file);
+H5TEST_DLL int h5_wait_message(const char *file);
+
#ifdef __cplusplus
}
#endif
diff --git a/test/mergemsg.h5 b/test/mergemsg.h5
index 3a9e352..55c3135 100644
--- a/test/mergemsg.h5
+++ b/test/mergemsg.h5
Binary files differ
diff --git a/test/multi_file_v16-s.h5 b/test/multi_file_v16-s.h5
index e990e95..2d4de48 100644
--- a/test/multi_file_v16-s.h5
+++ b/test/multi_file_v16-s.h5
Binary files differ
diff --git a/test/swmr_addrem_writer.c b/test/swmr_addrem_writer.c
index c15854c..0df8dec 100644
--- a/test/swmr_addrem_writer.c
+++ b/test/swmr_addrem_writer.c
@@ -421,6 +421,9 @@ int main(int argc, const char *argv[])
exit(1);
} /* end if */
+ /* Send a message to indicate "H5Fopen" is complete--releasing the file lock */
+ h5_send_message(WRITER_MESSAGE);
+
/* Emit informational message */
if(verbose)
fprintf(stderr, "Adding and removing records\n");
diff --git a/test/swmr_common.c b/test/swmr_common.c
index 6cbd5e2..30e1b3e 100644
--- a/test/swmr_common.c
+++ b/test/swmr_common.c
@@ -125,7 +125,7 @@ create_symbol_datatype(void)
hid_t opaq_type_id; /* Datatype ID for opaque part of record */
/* Create opaque datatype to represent other information for this record */
- if((opaq_type_id = H5Tcreate(H5T_OPAQUE, DTYPE_SIZE)) < 0)
+ if((opaq_type_id = H5Tcreate(H5T_OPAQUE, (size_t)DTYPE_SIZE)) < 0)
return -1;
/* Create compound datatype for symbol */
diff --git a/test/swmr_common.h b/test/swmr_common.h
index b80ad12..49f55fa 100644
--- a/test/swmr_common.h
+++ b/test/swmr_common.h
@@ -25,6 +25,7 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "hdf5.h"
+#include "h5test.h"
/**********/
/* Macros */
@@ -44,6 +45,9 @@
#define FILENAME "swmr_data.h5" /* SWMR test file name */
#define DTYPE_SIZE 150 /* Data size in opaque type */
+/* The message sent by writer that the file open is done--releasing the file lock */
+#define WRITER_MESSAGE "SWMR_WRITER_MESSAGE"
+
/************/
/* Typedefs */
/************/
diff --git a/test/swmr_remove_writer.c b/test/swmr_remove_writer.c
index 33d8899..f8fc8d1 100644
--- a/test/swmr_remove_writer.c
+++ b/test/swmr_remove_writer.c
@@ -340,6 +340,9 @@ int main(int argc, const char *argv[])
exit(1);
} /* end if */
+ /* Send a message to indicate "H5Fopen" is complete--releasing the file lock */
+ h5_send_message(WRITER_MESSAGE);
+
/* Emit informational message */
if(verbose)
fprintf(stderr, "Removing records\n");
diff --git a/test/swmr_sparse_writer.c b/test/swmr_sparse_writer.c
index d30c86d..5866b38 100644
--- a/test/swmr_sparse_writer.c
+++ b/test/swmr_sparse_writer.c
@@ -293,12 +293,14 @@ add_records(hid_t fid, unsigned verbose, unsigned long nrecords, unsigned long f
} /* end if */
} /* end if */
+#ifdef OUT
/* Busy wait, to let readers catch up */
dummy = 0;
for(v=0; v<BUSY_WAIT; v++)
dummy++;
if((unsigned long)dummy != v)
return -1;
+#endif
} /* end for */
/* Close the memory dataspace */
@@ -415,6 +417,9 @@ int main(int argc, const char *argv[])
exit(1);
} /* end if */
+ /* Send a message to indicate "H5Fopen" is complete--releasing the file lock */
+ h5_send_message(WRITER_MESSAGE);
+
/* Emit informational message */
if(verbose)
fprintf(stderr, "Adding records\n");
diff --git a/test/swmr_start_write.c b/test/swmr_start_write.c
new file mode 100644
index 0000000..a124160
--- /dev/null
+++ b/test/swmr_start_write.c
@@ -0,0 +1,691 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: swmr_start_write.c
+ *
+ * Purpose: This program enables SWMR writing mode via H5Fstart_swmr_write().
+ * It writes data to a randomly selected subset of the datasets
+ * in the SWMR test file; and it is intended to run concurrently
+ * with the swmr_reader program.
+ *
+ * NOTE: The routines in this program are basically copied and modified from
+ * swmr*.c.
+ *-------------------------------------------------------------------------
+ */
+
+/***********/
+/* Headers */
+/***********/
+
+#include <assert.h>
+#include <sys/time.h>
+
+#include "swmr_common.h"
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+static hid_t create_file(const char *filename, unsigned verbose,
+ const char *index_type, unsigned random_seed);
+static int create_close_datasets(hid_t fid, int comp_level, unsigned verbose);
+static hid_t open_datasets(hid_t fid, unsigned verbose);
+static hid_t open_file(const char *filename, unsigned verbose);
+
+static int add_records(hid_t fid, unsigned verbose, unsigned long nrecords,
+ unsigned long flush_count);
+static void usage(void);
+
+#define CHUNK_SIZE 50 /* Chunk size for created datasets */
+
+
+/*-------------------------------------------------------------------------
+ * Function: create_file
+ *
+ * Purpose: Creates the HDF5 file (without SWMR access) which
+ * which will be used for testing H5Fstart_swmr_write().
+ *
+ * Parameters:
+ * filename: The SWMR test file's name.
+ * verbose: whether verbose console output is desired.
+ * index_type: The chunk index type (b1 | b2 | ea | fa)
+ * random_seed: The random seed to store in the file.
+ * The sparse tests use this value.
+ *
+ * Return: Success: the file ID
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static hid_t
+create_file(const char *filename, unsigned verbose,
+ const char *index_type, unsigned random_seed)
+{
+ hid_t fid; /* File ID for new HDF5 file */
+ hid_t fcpl; /* File creation property list */
+ hid_t fapl; /* File access property list */
+ hid_t sid; /* Dataspace ID */
+ hid_t aid; /* Attribute ID */
+ hsize_t max_dims[2] = {1, H5S_UNLIMITED}; /* Dataset maximum dimensions */
+#ifdef FILLVAL_WORKS
+ symbol_t fillval; /* Dataset fill value */
+#endif /* FILLVAL_WORKS */
+
+ assert(filename);
+ assert(index_type);
+
+ /* Create file access property list */
+ if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0)
+ return -1;
+
+ /* We ALWAYS select the latest file format for SWMR */
+ if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
+ return -1;
+
+ /* There are two chunk indexes tested here.
+ * With one unlimited dimension, we get the extensible array index
+ * type, with two unlimited dimensions, we get a v-2 B-tree.
+ */
+ if(!strcmp(index_type, "b2"))
+ max_dims[0] = H5S_UNLIMITED;
+
+#ifdef QAK
+ /* Increase the initial size of the metadata cache */
+ {
+ H5AC_cache_config_t mdc_config;
+
+ mdc_config.version = H5AC__CURR_CACHE_CONFIG_VERSION;
+ H5Pget_mdc_config(fapl, &mdc_config);
+ fprintf(stderr, "mdc_config.initial_size = %lu\n", (unsigned long)mdc_config.initial_size);
+ fprintf(stderr, "mdc_config.epoch_length = %lu\n", (unsigned long)mdc_config.epoch_length);
+ mdc_config.set_initial_size = 1;
+ mdc_config.initial_size = 16 * 1024 * 1024;
+ /* mdc_config.epoch_length = 5000; */
+ H5Pset_mdc_config(fapl, &mdc_config);
+ }
+#endif /* QAK */
+
+#ifdef QAK
+ H5Pset_small_data_block_size(fapl, (hsize_t)(50 * CHUNK_SIZE * DTYPE_SIZE));
+#endif /* QAK */
+
+#ifdef QAK
+ H5Pset_fapl_log(fapl, "append.log", H5FD_LOG_ALL, (size_t)(512 * 1024 * 1024));
+#endif /* QAK */
+
+ /* Create file creation property list */
+ if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0)
+ return -1;
+
+#ifdef QAK
+ H5Pset_link_phase_change(fcpl, 0, 0);
+#endif /* QAK */
+
+ /* Emit informational message */
+ if(verbose)
+ fprintf(stderr, "Creating file without SWMR access\n");
+
+ /* Create the file */
+ if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl, fapl)) < 0)
+ return -1;
+
+ /* Close file creation property list */
+ if(H5Pclose(fcpl) < 0)
+ return -1;
+
+ /* Close file access property list */
+ if(H5Pclose(fapl) < 0)
+ return -1;
+
+ /* Create attribute with (shared) random number seed - for sparse test */
+ if((sid = H5Screate(H5S_SCALAR)) < 0)
+ return -1;
+ if((aid = H5Acreate2(fid, "seed", H5T_NATIVE_UINT, sid, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ return -1;
+ if(H5Awrite(aid, H5T_NATIVE_UINT, &random_seed) < 0)
+ return -1;
+ if(H5Sclose(sid) < 0)
+ return -1;
+ if(H5Aclose(aid) < 0)
+ return -1;
+
+ return fid;
+} /* end create_file() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: create_close_datasets
+ *
+ * Purpose: Create and close datasets which will be used for testing
+ * H5Fstart_swmr_write().
+ *
+ * Parameters:
+ * fid: file ID for the SWMR test file
+ * comp_level: the compresssion level
+ * verbose: whether verbose console output is desired.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+create_close_datasets(hid_t fid, int comp_level, unsigned verbose)
+{
+ hid_t dcpl; /* Dataset creation property list */
+ hid_t tid; /* Datatype for dataset elements */
+ hid_t sid; /* Dataspace ID */
+ hsize_t dims[2] = {1, 0}; /* Dataset starting dimensions */
+ hsize_t max_dims[2] = {1, H5S_UNLIMITED}; /* Dataset maximum dimensions */
+ hsize_t chunk_dims[2] = {1, CHUNK_SIZE}; /* Chunk dimensions */
+ unsigned u, v; /* Local index variable */
+
+ /* Create datatype for creating datasets */
+ if((tid = create_symbol_datatype()) < 0)
+ return -1;
+
+ /* Create dataspace for creating datasets */
+ if((sid = H5Screate_simple(2, dims, max_dims)) < 0)
+ return -1;
+
+ /* Create dataset creation property list */
+ if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)
+ return -1;
+ if(H5Pset_chunk(dcpl, 2, chunk_dims) < 0)
+ return -1;
+ if(comp_level >= 0) {
+ if(H5Pset_deflate(dcpl, (unsigned)comp_level) < 0)
+ return -1;
+ } /* end if */
+
+ /* Emit informational message */
+ if(verbose)
+ fprintf(stderr, "Creating datasets\n");
+
+ /* Create the datasets */
+ for(u = 0; u < NLEVELS; u++)
+ for(v = 0; v < symbol_count[u]; v++) {
+ hid_t dsid; /* Dataset ID */
+ char name_buf[64];
+
+ generate_name(name_buf, u, v);
+ if((dsid = H5Dcreate2(fid, name_buf, tid, sid, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0)
+ return -1;
+
+ if(H5Dclose(dsid) < 0)
+ return -1;
+ } /* end for */
+
+ /* Closing */
+ if(H5Pclose(dcpl) < 0)
+ return -1;
+ if(H5Sclose(sid) < 0)
+ return -1;
+ if(H5Tclose(tid) < 0)
+ return -1;
+
+ return 0;
+} /* create_close_datasets() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: open_file
+ *
+ * Purpose: Opens the HDF5 test file without SWMR access.
+ *
+ * Parameters:
+ * filename: The filename of the HDF5 file to open
+ * verbose: whether or not to emit verbose console messages
+ *
+ * Return: Success: The file ID of the opened SWMR file
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static hid_t
+open_file(const char *filename, unsigned verbose)
+{
+ hid_t fid; /* File ID for new HDF5 file */
+ hid_t fapl; /* File access property list */
+
+ assert(filename);
+
+ /* Create file access property list */
+ if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0)
+ return -1;
+
+ /* Set to use the latest library format */
+ if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
+ return -1;
+
+ /* Emit informational message */
+ if(verbose)
+ fprintf(stderr, "Opening the file without SWMR access: %s\n", filename);
+
+ /* Open the file */
+ if((fid = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
+ return -1;
+
+ /* Close file access property list */
+ if(H5Pclose(fapl) < 0)
+ return -1;
+
+ return fid;
+} /* Open file() */
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: open_datasets
+ *
+ * Purpose: Opens the datasets.
+ *
+ * Parameters:
+* filename: the filename of the SWMR HDF5 file to open
+ * verbose: whether or not to emit verbose console messages
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+open_datasets(hid_t fid, unsigned verbose)
+{
+ unsigned u, v; /* Local index variable */
+
+ /* Emit informational message */
+ if(verbose)
+ fprintf(stderr, "Opening datasets\n");
+
+ /* Open the datasets */
+ for(u = 0; u < NLEVELS; u++)
+ for(v = 0; v < symbol_count[u]; v++) {
+ if((symbol_info[u][v].dsid = H5Dopen2(fid, symbol_info[u][v].name, H5P_DEFAULT)) < 0)
+ return -1;
+ symbol_info[u][v].nrecords = 0;
+ } /* end for */
+
+ return 0;
+} /* open_datasets() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: add_records
+ *
+ * Purpose: Writes a specified number of records to random datasets in
+ * the SWMR test file.
+ *
+ * Parameters:
+* fid: The file ID of the SWMR HDF5 file
+ * verbose: Whether or not to emit verbose console messages
+ * nrecords: # of records to write to the datasets
+ * flush_count: # of records to write before flushing the file to disk
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+add_records(hid_t fid, unsigned verbose, unsigned long nrecords, unsigned long flush_count)
+{
+ hid_t tid; /* Datatype ID for records */
+ hid_t mem_sid; /* Memory dataspace ID */
+ hsize_t start[2] = {0, 0}, count[2] = {1, 1}; /* Hyperslab selection values */
+ hsize_t dim[2] = {1, 0}; /* Dataspace dimensions */
+ symbol_t record; /* The record to add to the dataset */
+ H5AC_cache_config_t mdc_config_orig; /* Original metadata cache configuration */
+ H5AC_cache_config_t mdc_config_cork; /* Corked metadata cache configuration */
+ unsigned long rec_to_flush; /* # of records left to write before flush */
+ unsigned long u, v; /* Local index variables */
+
+ assert(fid >= 0);
+
+ /* Reset the record */
+ /* (record's 'info' field might need to change for each record written, also) */
+ memset(&record, 0, sizeof(record));
+
+ /* Create a dataspace for the record to add */
+ if((mem_sid = H5Screate(H5S_SCALAR)) < 0)
+ return -1;
+
+ /* Create datatype for appending records */
+ if((tid = create_symbol_datatype()) < 0)
+ return -1;
+
+ /* Get the current metadata cache configuration, and set up the corked
+ * configuration */
+ mdc_config_orig.version = H5AC__CURR_CACHE_CONFIG_VERSION;
+ if(H5Fget_mdc_config(fid, &mdc_config_orig) < 0)
+ return -1;
+ memcpy(&mdc_config_cork, &mdc_config_orig, sizeof(mdc_config_cork));
+ mdc_config_cork.evictions_enabled = FALSE;
+ mdc_config_cork.incr_mode = H5C_incr__off;
+ mdc_config_cork.flash_incr_mode = H5C_flash_incr__off;
+ mdc_config_cork.decr_mode = H5C_decr__off;
+
+ /* Add records to random datasets, according to frequency distribution */
+ rec_to_flush = flush_count;
+ for(u = 0; u < nrecords; u++) {
+ symbol_info_t *symbol; /* Symbol to write record to */
+ hid_t file_sid; /* Dataset's space ID */
+
+ /* Get a random dataset, according to the symbol distribution */
+ symbol = choose_dataset();
+
+ /* Set the record's ID (equal to its position) */
+ record.rec_id = symbol->nrecords;
+
+ /* Get the coordinate to write */
+ start[1] = symbol->nrecords;
+
+ /* Cork the metadata cache, to prevent the object header from being
+ * flushed before the data has been written */
+ /*if(H5Fset_mdc_config(fid, &mdc_config_cork) < 0)
+ return(-1);*/
+
+ /* Extend the dataset's dataspace to hold the new record */
+ symbol->nrecords++;
+ dim[1] = symbol->nrecords;
+ if(H5Dset_extent(symbol->dsid, dim) < 0)
+ return -1;
+
+ /* Get the dataset's dataspace */
+ if((file_sid = H5Dget_space(symbol->dsid)) < 0)
+ return -1;
+
+ /* Choose the last record in the dataset */
+ if(H5Sselect_hyperslab(file_sid, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ return -1;
+
+ /* Write record to the dataset */
+ if(H5Dwrite(symbol->dsid, tid, mem_sid, file_sid, H5P_DEFAULT, &record) < 0)
+ return -1;
+
+ /* Uncork the metadata cache */
+ /*if(H5Fset_mdc_config(fid, &mdc_config_orig) < 0)
+ return -1;*/
+
+ /* Close the dataset's dataspace */
+ if(H5Sclose(file_sid) < 0)
+ return -1;
+
+ /* Check for flushing file */
+ if(flush_count > 0) {
+ /* Decrement count of records to write before flushing */
+ rec_to_flush--;
+
+ /* Check for counter being reached */
+ if(0 == rec_to_flush) {
+ /* Flush contents of file */
+ if(H5Fflush(fid, H5F_SCOPE_GLOBAL) < 0)
+ return -1;
+
+ /* Reset flush counter */
+ rec_to_flush = flush_count;
+ } /* end if */
+ } /* end if */
+ } /* end for */
+
+ /* Close the memory dataspace */
+ if(H5Sclose(mem_sid) < 0)
+ return -1;
+
+ /* Close the datatype */
+ if(H5Tclose(tid) < 0)
+ return -1;
+
+ /* Emit informational message */
+ if(verbose)
+ fprintf(stderr, "Closing datasets\n");
+
+ /* Close the datasets */
+ for(u = 0; u < NLEVELS; u++)
+ for(v = 0; v < symbol_count[u]; v++)
+ if(H5Dclose(symbol_info[u][v].dsid) < 0)
+ return -1;
+
+ return 0;
+} /* add_records() */
+
+static void
+usage(void)
+{
+ printf("\n");
+ printf("Usage error!\n");
+ printf("\n");
+ printf("Usage: swmr_start_write [-f <# of records to write between flushing file contents>]\n");
+ printf(" [-i <index type>] [-c <deflate compression level>]\n");
+ printf(" [-r <random seed>] [-q] <# of records>\n");
+ printf("\n");
+ printf("<# of records to write between flushing file contents> should be 0\n");
+ printf("(for no flushing) or between 1 and (<# of records> - 1).\n");
+ printf("\n");
+ printf("<index type> should be b2 or ea\n");
+ printf("\n");
+ printf("<deflate compression level> should be -1 (for no compression) or 0-9\n");
+ printf("\n");
+ printf("<# of records> must be specified.\n");
+ printf("\n");
+ printf("Defaults to flushing every 10000 records ('-f 10000'),\n");
+ printf("v1 b-tree indexing (-i b1), compression ('-c -1'),\n");
+ printf("will generate a random seed (no -r given), and verbose (no '-q' given)\n");
+ printf("\n");
+ exit(1);
+} /* usage() */
+
+/*
+ * Can test with different scenarios as listed below. Scenario (1) is tested here.
+ * 1) create_file(), create_close_datasets(), H5Fstart_swmr_write(), open_datasets(), add_records(), H5Fclose().
+ * 2) create_file(), H5Fstart_swmr_write(), create_close_datasets(), open_datasets(), add_records(), H5Fclose().
+ * 3) create_file(), H5Fclose(),
+ * open_file(), create_close_datasets(), H5Fstart_swmr_write(), open_datasets(), add_records(), H5Fclose().
+ * 4) create_file(), create_close_datasets(), H5Fclose(),
+ * open_file(), H5Fstart_swmr_write(), open_datasets(), add_records(), H5Fclose().
+ * 5) create_file(), H5Fclose(),
+ * open_file(), H5Fstart_swmr_write(), create_close_datasets(), open_datasets(), add_records(), H5Fclose().
+ */
+int main(int argc, const char *argv[])
+{
+ hid_t fid; /* File ID for file opened */
+ long nrecords = 0; /* # of records to append */
+ long flush_count = 10000; /* # of records to write between flushing file */
+ unsigned verbose = 1; /* Whether to emit some informational messages */
+ unsigned use_seed = 0; /* Set to 1 if a seed was set on the command line */
+ unsigned random_seed = 0; /* Random # seed */
+ int comp_level = -1; /* Compression level (-1 is no compression) */
+ const char *index_type = "b1"; /* Chunk index type */
+ unsigned u; /* Local index variable */
+ int temp; /* Temporary variable */
+
+ /* Parse command line options */
+ if(argc < 2)
+ usage();
+ if(argc > 1) {
+ u = 1;
+ while(u < (unsigned)argc) {
+ if(argv[u][0] == '-') {
+ switch(argv[u][1]) {
+ /* Compress dataset chunks */
+ case 'c':
+ comp_level = atoi(argv[u + 1]);
+ if(comp_level < -1 || comp_level > 9)
+ usage();
+ u += 2;
+ break;
+
+ /* Chunk index type */
+ case 'i':
+ index_type = argv[u + 1];
+ if(strcmp(index_type, "ea")
+ && strcmp(index_type, "b2"))
+ usage();
+ u += 2;
+ break;
+
+ /* # of records to write between flushing file */
+ case 'f':
+ flush_count = atol(argv[u + 1]);
+ if(flush_count < 0)
+ usage();
+ u += 2;
+ break;
+
+ /* Be quiet */
+ case 'q':
+ verbose = 0;
+ u++;
+ break;
+
+ /* Random # seed */
+ case 'r':
+ use_seed = 1;
+ temp = atoi(argv[u + 1]);
+ if(temp < 0)
+ usage();
+ else
+ random_seed = (unsigned)temp;
+ u += 2;
+ break;
+
+ default:
+ usage();
+ break;
+ } /* end switch */
+ } /* end if */
+ else {
+ /* Get the number of records to append */
+ nrecords = atol(argv[u]);
+ if(nrecords <= 0)
+ usage();
+
+ u++;
+ } /* end else */
+ } /* end while */
+ } /* end if */
+
+ if(nrecords <= 0)
+ usage();
+ if(flush_count >= nrecords)
+ usage();
+
+ /* Emit informational message */
+ if(verbose) {
+ fprintf(stderr, "Parameters:\n");
+ fprintf(stderr, "\tindex type = %s\n", index_type);
+ fprintf(stderr, "\tcompression level = %d\n", comp_level);
+ fprintf(stderr, "\t# of records between flushes = %ld\n", flush_count);
+ fprintf(stderr, "\t# of records to write = %ld\n", nrecords);
+ } /* end if */
+
+ /* Set the random seed */
+ if(0 == use_seed) {
+ struct timeval t;
+ gettimeofday(&t, NULL);
+ random_seed = (unsigned)((t.tv_sec * 1000) + t.tv_usec);
+ } /* end if */
+ srandom(random_seed);
+ /* ALWAYS emit the random seed for possible debugging */
+ fprintf(stderr, "Using writer random seed: %u\n", random_seed);
+
+ /* Create the test file */
+ if((fid = create_file(FILENAME, verbose, index_type, random_seed)) < 0) {
+ fprintf(stderr, "Error creating the file...\n");
+ exit(1);
+ }
+
+ /* Create and close the datasets in the file */
+ if(create_close_datasets(fid, comp_level, verbose) < 0) {
+ fprintf(stderr, "Error creating datasets...\n");
+ exit(1);
+ }
+
+#ifdef OUT
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0) {
+ fprintf(stderr, "Error closing file!\n");
+ exit(1);
+ } /* end if */
+
+ /* Open the file */
+ if((fid = open_file(FILENAME, verbose)) < 0) {
+ fprintf(stderr, "Error opening the file...\n");
+ exit(1);
+ }
+#endif
+
+ /* Enable SWMR writing mode */
+ if(H5Fstart_swmr_write(fid) < 0) {
+ fprintf(stderr, "Error starting SWMR writing mode...\n");
+ exit(1);
+ }
+
+ /* Emit informational message */
+ if(verbose)
+ fprintf(stderr, "Generating symbol names\n");
+
+ /* Generate dataset names */
+ if(generate_symbols() < 0)
+ return -1;
+
+ /* Emit informational message */
+ if(verbose)
+ fprintf(stderr, "Opening datasets: %s\n", FILENAME);
+
+ /* Open the file's datasets */
+ if(open_datasets(fid, verbose) < 0) {
+ fprintf(stderr, "Error opening datasets...\n");
+ exit(1);
+ } /* end if */
+
+ /* Send a message to indicate "H5Fopen" is complete--releasing the file lock */
+ h5_send_message(WRITER_MESSAGE);
+
+ /* Emit informational message */
+ if(verbose)
+ fprintf(stderr, "Adding records\n");
+
+ /* Append records to datasets */
+ if(add_records(fid, verbose, (unsigned long)nrecords, (unsigned long)flush_count) < 0) {
+ fprintf(stderr, "Error appending records to datasets!\n");
+ exit(1);
+ } /* end if */
+
+ /* Emit informational message */
+ if(verbose)
+ fprintf(stderr, "Releasing symbols\n");
+
+ /* Clean up the symbols */
+ if(shutdown_symbols() < 0) {
+ fprintf(stderr, "Error releasing symbols!\n");
+ exit(1);
+ } /* end if */
+
+ /* Emit informational message */
+ if(verbose)
+ fprintf(stderr, "Closing the file\n");
+
+ /* Close objects opened */
+ if(H5Fclose(fid) < 0) {
+ fprintf(stderr, "Error closing file!\n");
+ exit(1);
+ } /* end if */
+
+ return 0;
+} /* main() */
diff --git a/test/swmr_writer.c b/test/swmr_writer.c
index 29438d3..3fe4780 100644
--- a/test/swmr_writer.c
+++ b/test/swmr_writer.c
@@ -388,6 +388,9 @@ int main(int argc, const char *argv[])
exit(1);
} /* end if */
+ /* Send a message to indicate "H5Fopen" is complete--releasing the file lock */
+ h5_send_message(WRITER_MESSAGE);
+
/* Emit informational message */
if(verbose)
fprintf(stderr, "Adding records\n");
diff --git a/test/tarrold.h5 b/test/tarrold.h5
index 7747ce4..048838c 100644
--- a/test/tarrold.h5
+++ b/test/tarrold.h5
Binary files differ
diff --git a/test/test_filters_be.h5 b/test/test_filters_be.h5
index c4c127b..aadb372 100644
--- a/test/test_filters_be.h5
+++ b/test/test_filters_be.h5
Binary files differ
diff --git a/test/test_filters_le.h5 b/test/test_filters_le.h5
index ff8b846..c29fa0a 100644
--- a/test/test_filters_le.h5
+++ b/test/test_filters_le.h5
Binary files differ
diff --git a/test/test_swmr.c b/test/test_swmr.c
new file mode 100644
index 0000000..bd46bc2
--- /dev/null
+++ b/test/test_swmr.c
@@ -0,0 +1,2104 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/***********************************************************
+*
+* Test program: test_swmr
+*
+* To test SWMR related public routines:
+* H5Fstart_swmr_write()
+* H5Pget/set_object_flush_cb()
+* H5Pget/set_append_flush()
+*
+*************************************************************/
+
+#include "hdf5.h"
+#include "h5test.h"
+#include "H5srcdir.h"
+
+/*
+ * This file needs to access private information from the H5F package.
+ * This file also needs to access the file testing code.
+ */
+#define H5F_PACKAGE
+#define H5F_TESTING
+#include "H5Fpkg.h" /* File access */
+
+const char *FILENAME[] = {
+ "test_swmr", /* 0 */
+ NULL
+};
+
+#define NAME_BUF_SIZE 1024 /* Length of file name */
+
+/* Name of message file that is used by test_start_swmr_write_concur() */
+#define DONE_MESSAGE "DONE_MESSAGE" /* The message file to create */
+
+/* Tests for H5Fstart_swmr_write() */
+static int test_start_swmr_write(hid_t in_fapl);
+static int test_err_start_swmr_write(hid_t in_fapl);
+static int test_start_swmr_write_concur(hid_t in_fapl);
+
+/* Tests for H5Pget/set_object_flush_cb() */
+static herr_t flush_cb(hid_t obj_id, void *_udata);
+static int test_object_flush_cb(hid_t in_fapl);
+
+/* Tests for H5Pget/set_append_flush() */
+static herr_t append_cb(hid_t dset_id, hsize_t *cur_dims, void *_udata);
+static herr_t append_cb2(hid_t dset_id, hsize_t *cur_dims, void *_udata);
+static int test_append_flush_generic(void);
+static int test_append_flush_dataset_chunked(hid_t in_fapl);
+static int test_append_flush_dataset_fixed(hid_t in_fapl);
+static int test_append_flush_dataset_multiple(hid_t in_fapl);
+
+/*
+ * Tests for H5Fstart_swmr_write()
+ */
+
+/*
+ * Verify SWMR writing is enabled via H5Fstart_swmr_write().
+ */
+static int
+test_start_swmr_write(hid_t in_fapl)
+{
+ hid_t fid = -1; /* File ID */
+ hid_t fapl = -1; /* A copy of file access property */
+ hid_t file_fapl = -1; /* File access property for the file */
+ hid_t did = -1; /* Dataset ID */
+ hid_t sid = -1; /* Dataspace ID */
+ hsize_t dims[2] = {5, 10}; /* Dimension sizes */
+ int buf[50]; /* Data buffer */
+ int i; /* Local index variable */
+ unsigned attempts; /* The retrieved # of read attempts */
+ char filename[NAME_BUF_SIZE]; /* File name */
+
+ TESTING("H5Fstart_swmr_write()");
+
+ /* Get a copy of the parameter fapl */
+ if((fapl = H5Pcopy(in_fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set to use the latest library format */
+ if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set the filename to use for this test (dependent on fapl) */
+ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename));
+
+ /* Create the file to work on */
+ if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Get the file's access_property list */
+ if((file_fapl = H5Fget_access_plist(fid)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Retrieve the # of read attempts from the file's fapl */
+ if(H5Pget_metadata_read_attempts(file_fapl, &attempts) < 0)
+ FAIL_STACK_ERROR
+
+ /* Close the property list */
+ if(H5Pclose(file_fapl) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should be 1 */
+ if(attempts != H5F_METADATA_READ_ATTEMPTS)
+ TEST_ERROR;
+
+ /* Create a dataset */
+ if((sid = H5Screate_simple(2, dims, NULL)) < 0)
+ FAIL_STACK_ERROR;
+ if((did = H5Dcreate2(fid, "dataset", H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Close the dataset */
+ if(H5Dclose(did) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Enable SWMR writing */
+ if(H5Fstart_swmr_write(fid) < 0)
+ TEST_ERROR;
+
+ /* Open the dataset */
+ if((did = H5Dopen2(fid, "dataset", H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Initialize data buffer */
+ for(i = 0; i < 50; i++)
+ buf[i] = i;
+
+ /* Write to the dataset */
+ if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Close the dataset */
+ if(H5Dclose(did) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Close the dataspace */
+ if(H5Sclose(sid) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Get the file's access_property list */
+ if((file_fapl = H5Fget_access_plist(fid)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Retrieve the # of read attempts from file's fapl */
+ if(H5Pget_metadata_read_attempts(file_fapl, &attempts) < 0)
+ FAIL_STACK_ERROR
+
+ /* Should be 100 */
+ if(attempts != H5F_SWMR_METADATA_READ_ATTEMPTS)
+ TEST_ERROR;
+
+ /* Closing */
+ if(H5Pclose(file_fapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(fapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ PASSED();
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Fclose(fid);
+ H5Pclose(fapl);
+ H5Pclose(file_fapl);
+ H5Dclose(did);
+ H5Sclose(sid);
+ } H5E_END_TRY;
+
+ return -1;
+} /* test_start_swmr_write() */
+
+/*
+ * Verify failures in enabling SWMR writing mode via H5Fstart_swmr_write():
+ * When creating a file:
+ * (1) the file is created with SWMR write access
+ * (2) the file is not created with the latest format
+ * (3) there are opened objects in the file
+ * When opening a file with the latest format:
+ * (1) the file is already opened with SWMR write access
+ * (2) the file is opened with read access only
+ * (3) the file is opened with SWMR read access only
+ * (4) there are opened objects in the file
+ * When opening a file without the latest format:
+ * (1) the file is not opened with the latest format
+ * (2) the file is opened with read access only
+ * (3) the file is opened with SWMR read access only
+ * When there are multiple opens for the file:
+ * (1) create a file, enable SWMR writing mode twice (fail second time)
+ * (2) create a file and enable SWMR writing mode
+ * reopen the same file and enable SWMR writing mode (fail)
+ * (3) create a file, open the same file
+ * enable SWMR writing for the file created
+ * enable SWMR writing for the file opened (fail)
+ */
+static int
+test_err_start_swmr_write(hid_t in_fapl)
+{
+ hid_t fid = -1; /* File ID */
+ hid_t fid2 = -1; /* File ID */
+ hid_t fapl = -1; /* A copy of file access property */
+ hid_t gid = -1; /* Group ID */
+ hid_t did = -1; /* Dataset ID */
+ hid_t sid = -1; /* Dataspace ID */
+ hid_t tid = -1; /* Datatype ID */
+ hsize_t dims[2] = {5, 10}; /* Dimension size */
+ herr_t ret; /* Return value */
+ char filename[NAME_BUF_SIZE]; /* File name */
+
+ /* Create a copy of the input parameter in_fapl */
+ if((fapl = H5Pcopy(in_fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set to use the latest library format */
+ if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set the filename to use for this test (dependent on fapl) */
+ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename));
+
+ TESTING("H5Fstart_swmr_write() failure conditions");
+
+ /*
+ * When creating a file:
+ */
+
+ /* Case 1 */
+
+ /* Cannot enable SWMR writing when the file is already in SWMR writing mode */
+ fid = H5Fcreate(filename, H5F_ACC_TRUNC|H5F_ACC_SWMR_WRITE, H5P_DEFAULT, fapl);
+ H5E_BEGIN_TRY {
+ ret = H5Fstart_swmr_write(fid);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Case 2 */
+
+ /* Cannot enable SWMR writing mode without latest format */
+ fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, in_fapl);
+ H5E_BEGIN_TRY {
+ ret = H5Fstart_swmr_write(fid);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should fail to create the file with SWMR write access when not using latest format */
+ H5E_BEGIN_TRY {
+ ret = H5Fcreate(filename, H5F_ACC_TRUNC|H5F_ACC_SWMR_WRITE, H5P_DEFAULT, in_fapl);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+
+ /* Case 3 */
+
+ /* Create a file with the latest format */
+ if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Create a group */
+ if((gid = H5Gcreate2(fid, "group", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Create a dataset in the group */
+ if((sid = H5Screate_simple(2, dims, NULL)) < 0)
+ FAIL_STACK_ERROR;
+ if((did = H5Dcreate2(gid, "dset", H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Should fail to enable SWMR writing mode: there are opened objects */
+ H5E_BEGIN_TRY {
+ ret = H5Fstart_swmr_write(fid);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR;
+
+ /* Close the dataset */
+ if(H5Dclose(did) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Fail to enable SWMR writing mode */
+ H5E_BEGIN_TRY {
+ ret = H5Fstart_swmr_write(fid);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR;
+
+ /* Close the group */
+ if(H5Gclose(gid) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should succeed in enabling SWMR writing */
+ if(H5Fstart_swmr_write(fid) < 0)
+ TEST_ERROR;
+
+ /* Closing */
+ if(H5Sclose(sid) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /*
+ * When opening a file with latest format:
+ */
+
+ /* Create and close a file with latest format */
+ if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Case 1 */
+
+ /* Open the file with SWMR write access */
+ if((fid = H5Fopen(filename, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Cannot enable SWMR writing when already in SWMR writing mode */
+ H5E_BEGIN_TRY {
+ ret = H5Fstart_swmr_write(fid);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Case 2 */
+
+ /* Open the file with read only access */
+ if((fid = H5Fopen(filename, H5F_ACC_RDONLY, fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should fail to enable SWMR writing when the file is opened with read only access */
+ H5E_BEGIN_TRY {
+ ret = H5Fstart_swmr_write(fid);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Case 3 */
+
+ /* Open the file file with SWMR read access */
+ if((fid = H5Fopen(filename, H5F_ACC_SWMR_READ, fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should fail to enable SWMR writing when the file is opened with SWMR read access only */
+ H5E_BEGIN_TRY {
+ ret = H5Fstart_swmr_write(fid);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Case 4 */
+
+ /* Open the file with latest format */
+ if((fid = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Create and commit a named datatype */
+ if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Tcommit2(fid, "TID", tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should fail to enable SWMR writing mode */
+ H5E_BEGIN_TRY {
+ ret = H5Fstart_swmr_write(fid);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR;
+
+ /* Close the datatype */
+ if(H5Tclose(tid) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should succeed in enabling SWMR writing */
+ if(H5Fstart_swmr_write(fid) < 0)
+ TEST_ERROR;
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /*
+ * Opening a file without latest format:
+ */
+
+ /* Case 1 */
+
+ /* Open the file without latest format */
+ if((fid = H5Fopen(filename, H5F_ACC_RDWR, in_fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should fail to enable SWMR writing mode */
+ H5E_BEGIN_TRY {
+ ret = H5Fstart_swmr_write(fid);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should fail to open the file with SWMR write access when not using latest format */
+ H5E_BEGIN_TRY {
+ ret = H5Fopen(filename, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, in_fapl);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Case 2 */
+
+ /* Open the file with read only */
+ if((fid = H5Fopen(filename, H5F_ACC_RDONLY, in_fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should fail to enable SWMR writing when the file is opened with read only */
+ H5E_BEGIN_TRY {
+ ret = H5Fstart_swmr_write(fid);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Case 3 */
+
+ /* Open the file with SWMR read only */
+ if((fid = H5Fopen(filename, H5F_ACC_SWMR_READ, in_fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should fail to enable SWMR writing mode when the file is opened with SWMR read only */
+ H5E_BEGIN_TRY {
+ ret = H5Fstart_swmr_write(fid);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /*
+ * Failure cases for multiple opens
+ */
+
+ /* Case 1 */
+
+ /* Create a file with latest format */
+ if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should succeed in enabling SWMR writing mode */
+ if(H5Fstart_swmr_write(fid) < 0)
+ TEST_ERROR
+
+ /* Should fail for a second call to start SWMR writing mode */
+ H5E_BEGIN_TRY {
+ ret = H5Fstart_swmr_write(fid);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+
+ /* Case 2 */
+
+ /* Create a file */
+ if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should succeed in starting SWMR writing mode */
+ if(H5Fstart_swmr_write(fid) < 0)
+ TEST_ERROR
+
+ /* Re-open the same file */
+ if((fid2 = H5Freopen(fid)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should fail to enable SWMR writing mode for fid2 */
+ H5E_BEGIN_TRY {
+ ret = H5Fstart_swmr_write(fid2);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Close the files */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Fclose(fid2) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Case 3 */
+
+ /* Create a file */
+ if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Open the same file */
+ if((fid2 = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should succeed in enabling SWMR writing mode for fid */
+ if(H5Fstart_swmr_write(fid) < 0)
+ TEST_ERROR
+
+ /* Should fail to enable SWMR writing mode for fid2 */
+ H5E_BEGIN_TRY {
+ ret = H5Fstart_swmr_write(fid2);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Close the files */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Fclose(fid2) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Close the file access property list */
+ if(H5Pclose(fapl) < 0)
+ FAIL_STACK_ERROR;
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Fclose(fid);
+ H5Pclose(fapl);
+ } H5E_END_TRY;
+
+ return -1;
+} /* test_err_start_swmr_write() */
+
+
+/*
+ * test_start_swmr_write_concur():
+ * Verify concurrent access for H5Fstart_swmr_write()--
+ * (1) Open a file with write access
+ * Concurrent open of the file with read & SWMR read (fail)
+ * (2) Open a file with write access; enable SWMR writing mode
+ * Concurrent open of the file with read & SWMR read (succeed)
+ * (3) Open a file with write access; enable SWMR writing mode
+ * Concurrent open of the file with read only (fail)
+ * (4) Open a file with write access; enable SWMR writing mode
+ * Concurrent open of the file with write access (fail)
+ * (5) Open a file with write access; enable SWMR writing mode
+ * Concurrent open of the file with write and SWMR write access (fail)
+ */
+static int
+test_start_swmr_write_concur(hid_t in_fapl)
+{
+ hid_t fid; /* File ID */
+ hid_t fapl; /* File access property list */
+ herr_t ret; /* Generic return value */
+ pid_t childpid=0; /* Child process ID */
+ pid_t tmppid; /* Child process ID returned by waitpid */
+ int child_status; /* Status passed to waitpid */
+ int child_wait_option=0; /* Options passed to waitpid */
+ int child_ret_value; /* Exit status of the child */
+ char filename[NAME_BUF_SIZE]; /* File name */
+
+ /* Output message about test being performed */
+ TESTING("Testing H5Fstart_swmr_write()--concurrent access");
+
+#if !(defined(H5_HAVE_FORK) && defined(H5_HAVE_WAITPID))
+
+ SKIPPED();
+ HDputs(" Test skipped due to fork or waitpid not defined.");
+
+#else /* defined(H5_HAVE_FORK && defined(H5_HAVE_WAITPID) */
+
+ if((fapl = H5Pcopy(in_fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set to use the latest library format */
+ if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set the filename to use for this test (dependent on fapl) */
+ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename));
+
+ /* Create the test file */
+ if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR
+
+ /* Remove the message file to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /*
+ * Case (1):
+ * Verify concurrent file open with H5F_ACC_RDONLY|H5F_ACC_SWMR_READ
+ * will fail without H5Fstart_swmr_write()
+ */
+
+ /* Fork child process */
+ if((childpid = HDfork()) < 0)
+ FAIL_STACK_ERROR
+
+ if(childpid == 0) { /* Child process */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Should fail */
+ H5E_BEGIN_TRY {
+ /* Open the test file */
+ ret = H5Fopen(filename, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ exit(1);
+ exit(0);
+ }
+
+ /* Open the test file */
+ if((fid = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ if((tmppid = HDwaitpid(childpid, &child_status, child_wait_option)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Check if child terminated normally */
+ if((ret = WIFEXITED(child_status)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Check exit status of child process */
+ if((child_ret_value = WEXITSTATUS(child_status)) != 0)
+ TEST_ERROR
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR
+
+
+ /*
+ * Case (2):
+ * Verify concurrent file open with H5F_ACC_RDONLY|H5F_ACC_SWMR_READ
+ * will succeed with H5Fstart_swmr_write()
+ */
+
+ /* Remove the message file to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ if((childpid = HDfork()) < 0)
+ FAIL_STACK_ERROR
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Should succeed in opening the test file */
+ if((child_fid = H5Fopen(filename, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl)) < 0) {
+ TEST_ERROR
+ exit(1);
+ }
+ if(H5Fclose(child_fid) < 0) {
+ FAIL_STACK_ERROR
+ exit(1);
+ }
+ exit(0);
+ }
+
+ /* Open the test file */
+ if((fid = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Enable SWMR writing mode */
+ if(H5Fstart_swmr_write(fid) < 0)
+ TEST_ERROR
+
+ /* Send the message that H5Fstart_swmr_write() completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ if((tmppid = HDwaitpid(childpid, &child_status, child_wait_option)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Check if child terminated normally */
+ if((ret = WIFEXITED(child_status)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Check exit status of child process */
+ if((child_ret_value = WEXITSTATUS(child_status)) != 0)
+ TEST_ERROR
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR
+
+ /*
+ * Case (3):
+ * Verify concurrent file open with H5F_ACC_RDONLY
+ * will fail with H5Fstart_swmr_write()
+ */
+
+ /* Remove the message file to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ if((childpid = HDfork()) < 0)
+ FAIL_STACK_ERROR
+
+
+ if(childpid == 0) { /* Child process */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Should fail in opening the test file */
+ H5E_BEGIN_TRY {
+ ret = H5Fopen(filename, H5F_ACC_RDONLY, fapl);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ exit(1);
+ exit(0);
+ }
+
+ /* Open the test file */
+ if((fid = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Enable SWMR writing mode */
+ if(H5Fstart_swmr_write(fid) < 0)
+ TEST_ERROR
+
+ /* Send the message that H5Fstart_swmr_write() completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ if((tmppid = HDwaitpid(childpid, &child_status, child_wait_option)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Check if child terminated normally */
+ if((ret = WIFEXITED(child_status)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Check exit status of child process */
+ if((child_ret_value = WEXITSTATUS(child_status)) != 0)
+ TEST_ERROR;
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR
+
+ /*
+ * Case (4):
+ * Verify concurrent file open with H5F_ACC_RDWR
+ * will fail with H5Fstart_swmr_write()
+ */
+
+ /* Remove the message file to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ if((childpid = HDfork()) < 0)
+ FAIL_STACK_ERROR
+
+
+ if(childpid == 0) { /* Child process */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Should fail in opening the test file */
+ H5E_BEGIN_TRY {
+ ret = H5Fopen(filename, H5F_ACC_RDWR, fapl);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ exit(1);
+ exit(0);
+ }
+
+ /* Open the test file */
+ if((fid = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Enable SWMR writing mode */
+ if(H5Fstart_swmr_write(fid) < 0)
+ TEST_ERROR
+
+ /* Send the message that H5Fstart_swmr_write() completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ if((tmppid = HDwaitpid(childpid, &child_status, child_wait_option)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Check if child terminated normally */
+ if((ret = WIFEXITED(child_status)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Check exit status of child process */
+ if((child_ret_value = WEXITSTATUS(child_status)) != 0)
+ TEST_ERROR;
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR
+
+ /*
+ * Case (5):
+ * Verify concurrent file open with H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE
+ * will fail with H5Fstart_swmr_write()
+ */
+
+ /* Remove the message file to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ if((childpid = HDfork()) < 0)
+ FAIL_STACK_ERROR
+
+
+ if(childpid == 0) { /* Child process */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Should fail in opening the test file */
+ H5E_BEGIN_TRY {
+ ret = H5Fopen(filename, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ exit(1);
+ exit(0);
+ }
+
+ /* Open the test file */
+ if((fid = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Enable SWMR writing mode */
+ if(H5Fstart_swmr_write(fid) < 0)
+ TEST_ERROR
+
+ /* Send the message that H5Fstart_swmr_write() completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ if((tmppid = HDwaitpid(childpid, &child_status, child_wait_option)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Check if child terminated normally */
+ if((ret = WIFEXITED(child_status)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Check exit status of child process */
+ if((child_ret_value = WEXITSTATUS(child_status)) != 0)
+ TEST_ERROR;
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR
+
+ /* Close the property list */
+ if(H5Pclose(fapl) < 0)
+ FAIL_STACK_ERROR
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(fapl);
+ H5Fclose(fid);
+ } H5E_END_TRY;
+
+ return -1;
+#endif
+
+} /* end test_start_swmr_write_concur() */
+
+
+/*
+ * Tests for H5Pset/get_object_flush_cb()
+ */
+
+/* The callback function for object flush property */
+static herr_t
+flush_cb(hid_t obj_id, void *_udata)
+{
+ unsigned *flush_ct = (unsigned*)_udata;
+ ++(*flush_ct);
+ return 0;
+}
+
+/*
+ * test_object_flush_cb()
+ * To verify the public routines H5Pget/set_object_flush_cb()
+ * work as specified:
+ * 1) To verify the failure condition in setting object flush property
+ * 2) To verify the object flush property values retrieved from a default
+ * file access property list.
+ * 3) To verify the object flush property values retrieved from a non-default
+ * file access property list.
+ * 4) To verify the object flush property values retrieved from a default
+ * file access property list of a file
+ * 5) To verify the object flush property values retrieved from a non-default
+ * file access property list of a file
+ * To verify the object flush callback is invoked when doing H5Oflush(),
+ * H5Dflush(), H5Gflush() and H5Tflush().
+ */
+static int
+test_object_flush_cb(hid_t in_fapl)
+{
+ hid_t fapl = -1; /* A copy of file access property list */
+ hid_t ffapl = -1; /* A file's file access property list */
+ hid_t fid = -1; /* File ID */
+ hid_t gid = -1; /* Group ID */
+ hid_t did1 = -1, did2 = -1; /* Dataset IDs */
+ hid_t sid = -1; /* Dataspace ID */
+ hsize_t dims[2] = {5, 10}; /* Dataset dimension sizes */
+ int buf[50]; /* Data buffer */
+ H5F_flush_cb_t ret_cb; /* The callback function set in object flush property */
+ void *ret_ct; /* The user data set in object flush property */
+ unsigned flush_ct = 0; /* The user data for object flush property */
+ char filename[NAME_BUF_SIZE]; /* File name */
+ int i; /* Local index variable */
+ herr_t ret; /* Generic return value */
+
+ TESTING("H5Pget/set_obj_flush_cb()");
+
+ /*
+ * Case (1)
+ * To verify the failure condition in setting object flush property
+ */
+ /* Should fail if the callback function is not defined but user data is defined */
+ H5E_BEGIN_TRY {
+ ret = H5Pset_object_flush_cb(fapl, NULL, &flush_ct);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /*
+ * Case (2)
+ * To verify the object flush property values retrieved from a
+ * default file access property list.
+ */
+
+ /* Create a copy of file access property list */
+ if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Retrieve object flush property values for the default file access property list */
+ if(H5Pget_object_flush_cb(fapl, &ret_cb, &ret_ct) < 0)
+ TEST_ERROR
+ /* Should be null */
+ if(ret_cb != NULL || ret_ct != NULL)
+ TEST_ERROR
+
+ /*
+ * Case (3)
+ * To verify the object flush property values retrieved from a
+ * non-default file access property list.
+ */
+ /* Set the object flush property */
+ if(H5Pset_object_flush_cb(fapl, flush_cb, &flush_ct) < 0)
+ TEST_ERROR
+
+ /* Increment the counter */
+ ++flush_ct;
+
+ /* Retrieve object flush property values for the non-default file access property list */
+ if(H5Pget_object_flush_cb(fapl, &ret_cb, &ret_ct) < 0)
+ TEST_ERROR
+
+ /* Verify expected values */
+ if(ret_cb != flush_cb || *(unsigned *)ret_ct != 1)
+ TEST_ERROR
+
+ /* Close the property list */
+ if(H5Pclose(fapl) < 0)
+ FAIL_STACK_ERROR;
+
+
+ /*
+ * Case (4)
+ * To verify the object flush property values retrieved from a
+ * default file access property list of a file
+ */
+
+ /* Reset values */
+ flush_ct = 0;
+ ret_cb = NULL;
+ ret_ct = NULL;
+
+ /* Make a copy of the input parameter in_fapl */
+ if((fapl = H5Pcopy(in_fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set to use the latest library format */
+ if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set the filename to use for this test (dependent on fapl) */
+ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename));
+
+ /* Create the test file: without setting object flush property in fapl */
+ if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Get the file's file access property list */
+ if((ffapl = H5Fget_access_plist(fid)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Retrieve the object flush property values */
+ if(H5Pget_object_flush_cb(ffapl, &ret_cb, &ret_ct) < 0)
+ TEST_ERROR
+
+ /* Verify expected values */
+ if(ret_cb != NULL || ret_ct != NULL)
+ TEST_ERROR
+
+ /* Closing */
+ if(H5Pclose(ffapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /*
+ * Cases (5)
+ * To verify the object flush property values retrieved from a non-default
+ * file access property list of a file.
+ * To verify the object flush callback is invoked when doing H5Oflush(),
+ * H5Dflush(), H5Gflush() and H5Tflush().
+ */
+ /* Reset values */
+ flush_ct = 0;
+ ret_cb = NULL;
+ ret_ct = NULL;
+
+ /* Set the object flush property */
+ if(H5Pset_object_flush_cb(fapl, flush_cb, &flush_ct) < 0)
+ FAIL_STACK_ERROR
+
+ /* Open the test file: with object flush property setting in fapl */
+ if((fid = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Create a dataset */
+ if((sid = H5Screate_simple(2, dims, dims)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Create a dataset */
+ if((did1 = H5Dcreate2(fid, "dataset1", H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Initialize data buffer */
+ for(i = 0; i < 50; i++)
+ buf[i] = i + 1;
+
+ /* Write to the dataset */
+ if(H5Dwrite(did1, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Flush the dataset object */
+ if(H5Oflush(did1) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Get the file's file access property list */
+ if((ffapl = H5Fget_access_plist(fid)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Retrieve the object flush property values */
+ if(H5Pget_object_flush_cb(ffapl, &ret_cb, &ret_ct) < 0)
+ TEST_ERROR
+
+ /* Verify expected values */
+ if(ret_cb != flush_cb || *(unsigned *)ret_ct != 1)
+ TEST_ERROR
+
+ /* Create a group */
+ if((gid = H5Gcreate2(fid, "group", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Flush the group */
+ if(H5Gflush(gid) < 0)
+ TEST_ERROR
+
+ /* Retrieve the object flush property values */
+ if(H5Pget_object_flush_cb(ffapl, &ret_cb, &ret_ct) < 0)
+ TEST_ERROR
+
+ /* Verify expected values */
+ if(ret_cb != flush_cb || *(unsigned *)ret_ct != 2)
+ TEST_ERROR
+
+ /* Create a dataset */
+ if((did2 = H5Dcreate2(gid, "dataset2", H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Flush the dataset */
+ if(H5Dflush(did2) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Retrieve the object flush property values */
+ if(H5Pget_object_flush_cb(ffapl, &ret_cb, &ret_ct) < 0)
+ TEST_ERROR
+
+ /* Verify expected values */
+ if(ret_cb != flush_cb || *(unsigned *)ret_ct != 3)
+ TEST_ERROR
+
+ /* Closing */
+ if(H5Sclose(sid) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Dclose(did1) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Dclose(did2) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Gclose(gid) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(fapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(ffapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ PASSED();
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(fapl);
+ H5Pclose(ffapl);
+ H5Sclose(sid);
+ H5Dclose(did1);
+ H5Dclose(did2);
+ H5Gclose(gid);
+ H5Fclose(fid);
+ } H5E_END_TRY;
+
+ return -1;
+} /* test_object_flush_cb() */
+
+/*
+ * Tests for H5Pset/get_append_flush()
+ */
+
+
+/* The callback function for append flush property */
+static herr_t
+append_cb(hid_t dset_id, hsize_t *cur_dims, void *_udata)
+{
+ unsigned *count = (unsigned *)_udata;
+ ++(*count++);
+ return 0;
+} /* append_cb() */
+
+
+/* The callback function for append flush property */
+static herr_t
+append_cb2(hid_t dset_id, hsize_t *cur_dims, void *_udata)
+{
+ unsigned *count = (unsigned *)_udata;
+ ++(*count++);
+ return 0;
+} /* append_cb2() */
+
+
+
+/*
+ * test_append_flush_generic()
+ * To verify H5Pget/set_append_flush() work as specified for
+ * a generic dataset access property list:
+ * 1) To verify the append flush property values retrieved from a default
+ * access property list.
+ * -- zero boundary, null callback function, null user data
+ * 2) To verify the failure conditions in setting append flush property:
+ * -- an invalid dataset rank: <= 0, > H5S_MAX_RANK
+ * -- undefined callback but defined user data
+ * -- no boundary specified
+ * -- invalid boundary size: H5S_UNLIMITED, negative value
+ * 3) To verify the append flush property values retrieved from a non-default
+ * access property list.
+ * -- the set callback function, the set user data
+ * -- the # of boundary sizes retrieved does not exceed MIN(input ndims, the ndims set)
+ */
+static int
+test_append_flush_generic(void)
+{
+ hid_t dapl = -1; /* A copy of dataset access property */
+ hsize_t boundary[3]; /* The boundary for append flush property */
+ unsigned count = 0; /* The user data for append flush property */
+ hsize_t ret_boundary[3]; /* The boundary set in append flush property */
+ H5D_append_cb_t ret_cb; /* The callback function set in append flush property */
+ unsigned *ret_count; /* The user data set in append flush property */
+ herr_t ret; /* The return value */
+
+ TESTING("H5Fget/set_append_flush() for a generic dataset access property list");
+
+
+ /*
+ * Case (1)
+ * To verify the retrieved append flush property values:
+ * -- zero boundary, null callback function, null user data
+ */
+
+ /* Create a copy of dataset access property list */
+ if((dapl = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Retrieve the append flush property values */
+ if(H5Pget_append_flush(dapl, 2, ret_boundary, &ret_cb, (void **)&ret_count) < 0)
+ FAIL_STACK_ERROR
+
+ /* Verify expected values */
+ if(ret_boundary[0] != 0 || ret_boundary[1] != 0)
+ TEST_ERROR;
+ if(ret_cb != NULL || ret_count != NULL)
+ TEST_ERROR
+
+ /* Close the property list */
+ if(H5Pclose(dapl) < 0)
+ FAIL_STACK_ERROR;
+
+ /*
+ * Case (2)
+ * To verify the failure conditions in setting append flush property:
+ * -- an invalid dataset rank: <= 0, > H5S_MAX_RANK
+ * -- no boundary specified
+ * -- undefined callback but defined user data
+ * -- invalid boundary size: H5S_UNLIMITED, negative value
+ */
+
+ /* Create a copy of dataset access property list */
+ if((dapl = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Invalid dataset rank: zero value */
+ H5E_BEGIN_TRY {
+ ret = H5Pset_append_flush(dapl, 0, NULL, NULL, &count);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Invalid dataset rank: negative value */
+ H5E_BEGIN_TRY {
+ ret = H5Pset_append_flush(dapl, -1, NULL, NULL, &count);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Invalid dataset rank: > H5S_MAX_RANK */
+ H5E_BEGIN_TRY {
+ ret = H5Pset_append_flush(dapl, H5S_MAX_RANK+1, NULL, NULL, &count);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* No boundary specified */
+ H5E_BEGIN_TRY {
+ ret = H5Pset_append_flush(dapl, 2, NULL, NULL, &count);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Set up a valid boundary */
+ boundary[0] = 1;
+ boundary[1] = 1;
+
+ /* Undefined callback function but defined user data */
+ H5E_BEGIN_TRY {
+ ret = H5Pset_append_flush(dapl, 2, boundary, NULL, &count);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Invalid boundary size: negative value */
+ boundary[0] = -1;
+ boundary[1] = 1;
+ H5E_BEGIN_TRY {
+ ret = H5Pset_append_flush(dapl, 2, boundary, append_cb, &count);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Invalid boundary size: H5S_UNLIMITED */
+ boundary[0] = 1;
+ boundary[1] = H5S_UNLIMITED;
+ H5E_BEGIN_TRY {
+ ret = H5Pset_append_flush(dapl, 2, boundary, append_cb, &count);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /*
+ * Case (3)
+ * To verify the append flush property values retrieved from a non-default
+ * access property list:
+ * -- the set callback function, the set user data
+ * -- the # of boundary sizes retrieved does not exceed MIN(input ndims, the ndims set)
+ */
+ boundary[0] = boundary[1] = 1;
+ boundary[2] = 0;
+ count = 1;
+ if(H5Pset_append_flush(dapl, 2, boundary, append_cb, &count) < 0)
+ FAIL_STACK_ERROR;
+ ++count;
+
+ /* Verify expected values: with boundary rank > set boundary rank */
+ if(H5Pget_append_flush(dapl, 3, ret_boundary, &ret_cb, (void **)&ret_count) < 0)
+ TEST_ERROR
+ if(ret_boundary[0] != 1 || ret_boundary[1] != 1 || boundary[2] != 0)
+ TEST_ERROR;
+ if(ret_cb == NULL || ret_count == NULL || *ret_count != 2)
+ TEST_ERROR
+
+ /* Verify expected values: with boundary rank < set boundary rank */
+ HDmemset(ret_boundary, 0, sizeof(ret_boundary));
+ if(H5Pget_append_flush(dapl, 1, ret_boundary, NULL, NULL) < 0)
+ TEST_ERROR
+ if(ret_boundary[0] != 1 || ret_boundary[1] != 0 || boundary[2] != 0)
+ TEST_ERROR;
+
+ /* Closing */
+ if(H5Pclose(dapl) < 0)
+ FAIL_STACK_ERROR;
+
+ PASSED();
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(dapl);
+ } H5E_END_TRY;
+
+ return -1;
+} /* test_append_flush_generic() */
+
+/*
+ * test_append_flush_dataset_chunked()
+ * To verify H5Pget/set_append_flush() work as specified for
+ * a chunked dataset's access property list:
+ * 1) To verify the append flush property values retrieved from a default access
+ * property list:
+ * -- zero boundary, null callback function, null user data
+ * 2) To verify failure in creating dataset when:
+ * -- the rank set in append flush property is not the same as the dataset's rank
+ * -- boundary (non-zero) is set for a non-extendible dimension
+ * 3) To verify the append flush property values retrieved from a non-default
+ * access property list:
+ * -- the set callback function, the set user data
+ * -- the # of boundary sizes retrieved does not exceed MIN(input ndims, the ndims set)
+ */
+static int
+test_append_flush_dataset_chunked(hid_t in_fapl)
+{
+ hid_t fid = -1; /* file ID */
+ hid_t fapl = -1; /* A copy of file access property */
+ hid_t did1 = -1, did2 = -1; /* The datset ID */
+ hid_t sid = -1; /* The dataspace ID */
+ hid_t dcpl = -1; /* A copy of dataset creation property */
+ hid_t dapl = -1; /* A copy of dataset access property */
+ hid_t ddapl = -1; /* The dataset access property of the opened dataset */
+
+ hsize_t boundary[3]; /* Boundary size */
+ unsigned count = 0; /* User data */
+
+ hsize_t ret_boundary[3]; /* Boundary size set in the append flush property */
+ H5D_append_cb_t ret_cb; /* The callback function set in the append flush property */
+ unsigned *ret_count; /* The user data set in the append flush property */
+
+ char filename[NAME_BUF_SIZE]; /* file name */
+
+ hsize_t dims[2] = {100, 0}; /* The dataset dimension sizes */
+ hsize_t maxdims[2] = {100, H5S_UNLIMITED}; /* The dataset maximum dimension sizes */
+ hsize_t chunk_dims[2] = {5,2}; /* The chunk dimesion sizes */
+
+ TESTING("H5Fget/set_append_flush() for a chunked dataset's access property list");
+
+ /*
+ * Case (1)--
+ * For a chunked dataset's access property list:
+ * --to verify the append flush property values retrieved from a default access
+ * a default access property list is:
+ * zero rank, zero boundary, null callback function, null user data
+ */
+
+ /* Get a copy of the input parameter in_fapl */
+ if((fapl = H5Pcopy(in_fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set to use the latest library format */
+ if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Set the filename to use for this test (dependent on fapl) */
+ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename));
+
+ /* Create the test file to work on */
+ if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Create a chunked dataset with 1 extendible dimension */
+ if((sid = H5Screate_simple(2, dims, maxdims)) < 0)
+ FAIL_STACK_ERROR;
+ if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)
+ FAIL_STACK_ERROR
+ if(H5Pset_chunk(dcpl, 2, chunk_dims) < 0)
+ FAIL_STACK_ERROR;
+ if((did1 = H5Dcreate2(fid, "dataset1", H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Get the dataset's access property list */
+ if((ddapl = H5Dget_access_plist(did1)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Retrieve the append flush property values */
+ if(H5Pget_append_flush(ddapl, 3, ret_boundary, &ret_cb, (void **)&ret_count) < 0)
+ TEST_ERROR
+
+ /* Verify expected values */
+ if(ret_boundary[0] != 0 || ret_boundary[1] != 0 || ret_boundary[2] != 0)
+ TEST_ERROR;
+ if(ret_cb != NULL || ret_count != NULL)
+ TEST_ERROR
+
+ /* Close the dataset's access property list */
+ if(H5Pclose(ddapl) < 0)
+ FAIL_STACK_ERROR;
+
+ /*
+ * Case (2)--
+ * For a chunked dataset's access property list:
+ * --to verify failure in creating the dataset when:
+ * --the rank set in append flush property is not the same as the dataset's rank
+ * -- boundary (non-zero) is set for a non-extendible dimension
+ * --to verify failure in opening the dataset
+ * -- boundary (non-zero) is set for a non-extendible dimension
+ */
+ /* Create a copy of dataset access property list */
+ if((dapl = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set boundary dimension rank > the rank of dataset to be created */
+ HDmemset(boundary, 0, sizeof(boundary));
+ if(H5Pset_append_flush(dapl, 3, boundary, NULL, NULL) < 0)
+ FAIL_STACK_ERROR
+
+ /* Should fail to Create the dataset */
+ H5E_BEGIN_TRY {
+ did2 = H5Dcreate2(fid, "dataset2", H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, dapl);
+ } H5E_END_TRY;
+ if(did2 >= 0)
+ TEST_ERROR
+
+ /* Set boundary for a non-extendible dimension */
+ boundary[0] = boundary[1] = 1;
+ if(H5Pset_append_flush(dapl, 2, boundary, NULL, NULL) < 0)
+ FAIL_STACK_ERROR
+
+ /* Should fail to create the dataset */
+ H5E_BEGIN_TRY {
+ did2 = H5Dcreate2(fid, "dataset2", H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, dapl);
+ } H5E_END_TRY;
+ if(did2 >= 0)
+ TEST_ERROR
+
+ /* Create and close the dataset */
+ if((did2 = H5Dcreate2(fid, "dataset2", H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Dclose(did2) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should fail to open the dataset */
+ H5E_BEGIN_TRY {
+ did2 = H5Dopen(fid, "dataset2", dapl);
+ } H5E_END_TRY;
+ if(did2 >= 0)
+ TEST_ERROR
+
+ /*
+ * Case (3)--
+ * For a chunked dataset's access property list:
+ * --To verify the append flush property values retrieved from a non-default
+ * access property list:
+ * -- the set callback function, the set user data
+ * -- the # of boundary sizes retrieved does not exceed MIN(input ndims, the ndims set)
+ */
+
+ boundary[0] = 0;
+ boundary[1] = 1;
+ if(H5Pset_append_flush(dapl, 2, boundary, append_cb, &count) < 0)
+ FAIL_STACK_ERROR
+ if((did2 = H5Dopen(fid, "dataset2", dapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Get the dataset's access property list */
+ if((ddapl = H5Dget_access_plist(did2)) < 0)
+ FAIL_STACK_ERROR
+
+ HDmemset(ret_boundary, 0, sizeof(ret_boundary));
+ ret_cb = NULL;
+ ret_count = NULL;
+ /* Retrieve the append flush property values */
+ if(H5Pget_append_flush(ddapl, 3, ret_boundary, &ret_cb, (void **)&ret_count) < 0)
+ TEST_ERROR
+
+ /* Verify expected values */
+ if(ret_cb != append_cb || ret_count != &count)
+ TEST_ERROR
+ if(ret_boundary[0] != 0 || ret_boundary[1] != 1 || ret_boundary[2] != 0)
+ TEST_ERROR
+
+ HDmemset(ret_boundary, 0, sizeof(ret_boundary));
+ /* Retrieve the append flush property values */
+ if(H5Pget_append_flush(ddapl, 1, ret_boundary, NULL, NULL) < 0)
+ TEST_ERROR
+ if(ret_boundary[0] != 0 || ret_boundary[1] != 0 || ret_boundary[2] != 0)
+ TEST_ERROR
+
+ /* Closing */
+ if(H5Pclose(ddapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(dapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(dcpl) < 0)
+ FAIL_STACK_ERROR;
+
+ if(H5Pclose(fapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Dclose(did1) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Dclose(did2) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Sclose(sid) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ PASSED();
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(dcpl);
+ H5Pclose(dapl);
+ H5Pclose(ddapl);
+ H5Dclose(did1);
+ H5Dclose(did2);
+ H5Pclose(fapl);
+ H5Sclose(sid);
+ H5Fclose(fid);
+ } H5E_END_TRY;
+
+ return -1;
+} /* test_append_flush_dataset_chunked() */
+
+/*
+ * test_append_flush_dataset_fixed():
+ * To verify H5Pget/set_append_flush() work as specified for
+ * a non-chunked (fixed size) dataset's access property list:
+ * (1) To verify success in creating the dataset--whatever is set for the append flush property setting
+ * (2) To verify that default append flush property values are retrieved for both
+ * default or non-default access property list:
+ * -- zero boundary, null callback function, null user data
+ */
+static int
+test_append_flush_dataset_fixed(hid_t in_fapl)
+{
+ hid_t fid = -1; /* file ID */
+ hid_t fapl = -1; /* A copy of file access property */
+ hid_t did1 = -1, did2 = -1; /* The datset ID */
+ hid_t sid = -1; /* The dataspace ID */
+ hid_t dapl = -1; /* A copy of dataset access property */
+ hid_t ddapl = -1; /* The dataset access property of the opened dataset */
+
+ hsize_t boundary[3]; /* Boundary size */
+ unsigned count = 0; /* User data */
+
+ hsize_t ret_boundary[3]; /* Boundary size set in the append flush property */
+ H5D_append_cb_t ret_cb; /* The callback function set in the append flush property */
+ unsigned *ret_count; /* The user data set in the append flush property */
+
+ char filename[NAME_BUF_SIZE]; /* file name */
+
+ hsize_t dims[1] = {100};
+
+ TESTING("H5Fget/set_append_flush() for a non-chunked dataset's access property list");
+
+ /*
+ * Case (1)--
+ * For a non-chunked dataset's access property list:
+ * --to verify the append flush property values retrieved from
+ * a default access property list is:
+ * zero boundary, null callback function, null user data
+ */
+
+ /* Get a copy of the input parameter in_fapl */
+ if((fapl = H5Pcopy(in_fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set to use the latest library format */
+ if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Set the filename to use for this test (dependent on fapl) */
+ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename));
+
+ /* Create the test file to work on */
+ if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Create a dataset */
+ if((sid = H5Screate_simple(1, dims, dims)) < 0)
+ FAIL_STACK_ERROR;
+ if((did1 = H5Dcreate2(fid, "dataset1", H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Get the dataset's access property list */
+ if((ddapl = H5Dget_access_plist(did1)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Retrieve the append flush property values */
+ if(H5Pget_append_flush(ddapl, 3, ret_boundary, &ret_cb, (void **)&ret_count) < 0)
+ TEST_ERROR
+
+ /* Verify expected values */
+ if(ret_boundary[0] != 0 || ret_boundary[1] != 0 || ret_boundary[2] != 0)
+ TEST_ERROR;
+ if(ret_cb != NULL || ret_count != NULL)
+ TEST_ERROR
+
+ /* Close the dataset's access property list */
+ if(H5Pclose(ddapl) < 0)
+ FAIL_STACK_ERROR;
+
+ /*
+ * Case (2)--
+ * For a non-chunked dataset's access property list:
+ * --to verify success in creating and opening the dataset even when append flush property
+ * is setup with error conditions:
+ * --the rank set in append flush property is not the same as the dataset's rank
+ * --boundary is set
+ * --to verify the append flush property values are:
+ * zero boundary, null callback function, null user data
+ */
+ /* Create a copy of dataset access property list */
+ if((dapl = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
+ FAIL_STACK_ERROR
+
+ boundary[0] = 1;
+ boundary[1] = boundary[2] = 0;
+ if(H5Pset_append_flush(dapl, 3, boundary, append_cb, &count) < 0)
+ FAIL_STACK_ERROR
+
+ /* Should succeed to create the dataset: append flush property has no effect */
+ if((did2 = H5Dcreate2(fid, "dataset2", H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, dapl)) < 0)
+ TEST_ERROR
+
+ /* Get the dataset's access property list */
+ if((ddapl = H5Dget_access_plist(did2)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Retrieve the append flush property values */
+ if(H5Pget_append_flush(ddapl, 3, ret_boundary, &ret_cb, (void **)&ret_count) < 0)
+ TEST_ERROR
+
+ /* Verify expected values */
+ if(ret_cb != NULL || ret_count != NULL)
+ TEST_ERROR
+ if(ret_boundary[0] != 0 || ret_boundary[1] != 0 || ret_boundary[2] != 0)
+ TEST_ERROR
+
+ /* Closing */
+ if(H5Pclose(ddapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Dclose(did2) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Should succeed in opening the dataset: append flush property has no effect */
+ if((did2 = H5Dopen(fid, "dataset2", dapl)) < 0)
+ TEST_ERROR
+
+ /* Get the dataset's access property list */
+ if((ddapl = H5Dget_access_plist(did2)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Retrieve the append flush property values */
+ if(H5Pget_append_flush(ddapl, 3, ret_boundary, &ret_cb, (void **)&ret_count) < 0)
+ TEST_ERROR
+
+ /* Verify expected values */
+ if(ret_cb != NULL || ret_count != NULL)
+ TEST_ERROR
+ if(ret_boundary[0] != 0 || ret_boundary[1] != 0 || ret_boundary[2] != 0)
+ TEST_ERROR
+
+ if(H5Dclose(did2) < 0)
+ FAIL_STACK_ERROR
+ /*
+ * Case (3)--
+ * For a non-chunked dataset's access property list:
+ * --To verify the append flush property values retrieved from a non-default
+ * access property list:
+ * zero boundary, null callback function, null user data
+ */
+
+ HDmemset(boundary, 0, sizeof(boundary));
+ if(H5Pset_append_flush(dapl, 1, boundary, append_cb, &count) < 0)
+ FAIL_STACK_ERROR
+ if((did2 = H5Dopen(fid, "dataset2", dapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Get the dataset's access property list */
+ if((ddapl = H5Dget_access_plist(did2)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Retrieve the append flush property values */
+ if(H5Pget_append_flush(ddapl, 1, ret_boundary, &ret_cb, (void **)&ret_count) < 0)
+ TEST_ERROR
+
+ /* Verify expected values */
+ if(ret_cb != NULL || ret_count != NULL)
+ TEST_ERROR
+ if(ret_boundary[0] != 0 || ret_boundary[1] != 0 || ret_boundary[2] != 0)
+ TEST_ERROR
+
+ /* Closing */
+ if(H5Pclose(ddapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(dapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(fapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Dclose(did1) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Dclose(did2) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Sclose(sid) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ PASSED();
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(dapl);
+ H5Pclose(ddapl);
+ H5Dclose(did1);
+ H5Dclose(did2);
+ H5Pclose(fapl);
+ H5Sclose(sid);
+ H5Fclose(fid);
+ } H5E_END_TRY;
+
+ return -1;
+} /* test_append_flush_dataset_fixed() */
+
+/*
+ * test_append_flush_multiple()
+ * To verify H5Pget/set_append_flush() work as specified for
+ * multiple opens of a dataset:
+ * (1) did1 = H5Dcreate(...dapl1...)
+ * did2 = H5Dopen2(...dapl2)
+ * H5Pget_append_flush(did1...)
+ * H5Pget_append_flush(did2...)
+ * -- should return append flush property values set in dapl1
+ * (2) H5Dcreate(...H5P_DEFAULT...)
+ * H5Dclose()
+ * did1 = H5Dopen(...dapl1)
+ * did2 = H5Dopen(..dapl2)
+ * H5Pget_append_flush(did1, ...)
+ * H5Pget_append_flush(did2, ...)
+ * -- should return append flush property values set in dapl1
+ * NOTE:
+ * FOR NOW: return the append flush property values of the create or the very first open
+ * LATER ON: should REJECT subsequent dataset open if append flush property values differ
+ */
+static int
+test_append_flush_dataset_multiple(hid_t in_fapl)
+{
+ hid_t fid = -1; /* file ID */
+ hid_t fapl = -1; /* A copy of file access property */
+ hid_t did1 = -1, did2 = -1; /* The datset ID */
+ hid_t sid = -1; /* The dataspace ID */
+ hid_t dcpl = -1; /* A copy of dataset creation property */
+ hid_t dapl1 = -1; /* A copy of dataset access property */
+ hid_t dapl2 = -1; /* A copy of dataset access property */
+ hid_t ddapl = -1; /* The dataset access property of the opened dataset */
+
+ hsize_t boundary1[3]; /* Boundary size */
+ hsize_t boundary2[3]; /* Boundary size */
+ unsigned count1 = 0; /* User data */
+ unsigned count2 = 0; /* User data */
+
+ hsize_t ret_boundary[3]; /* Boundary size set in the append flush property */
+ H5D_append_cb_t ret_cb; /* The callback function set in the append flush property */
+ unsigned *ret_count; /* The user data set in the append flush property */
+
+ char filename[NAME_BUF_SIZE]; /* file name */
+
+ hsize_t dims[2] = {0, 0}; /* The dataset dimension sizes */
+ hsize_t maxdims[2] = {H5S_UNLIMITED, H5S_UNLIMITED}; /* The dataset maximum dimension sizes */
+ hsize_t chunk_dims[2] = {5,2}; /* The chunk dimesion sizes */
+
+ TESTING("H5Fget/set_append_flush() for multiple opens of a chunked dataset");
+
+ /*
+ * Case (1)
+ * For a chunked dataset's access property list:
+ * did1 = H5Dcreate(...dapl1...)
+ * did2 = H5Dopen2(...dapl2)
+ * H5Pget_append_flush(did1...)
+ * H5Pget_append_flush(did2...)
+ * -- should return append flush property values set in dapl1
+ */
+
+ /* Create a copy of dataset access property list */
+ if((dapl1 = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
+ FAIL_STACK_ERROR
+ if((dapl2 = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
+ FAIL_STACK_ERROR
+
+ boundary1[0] = 0;
+ boundary1[1] = 1;
+ count1 = 0;
+ if(H5Pset_append_flush(dapl1, 2, boundary1, append_cb, &count1) < 0)
+ FAIL_STACK_ERROR
+ boundary2[0] = 1;
+ boundary2[1] = 0;
+ count2 = 0;
+ if(H5Pset_append_flush(dapl2, 2, boundary2, append_cb2, &count2) < 0)
+ FAIL_STACK_ERROR
+
+ /* Get a copy of the input parameter in_fapl */
+ if((fapl = H5Pcopy(in_fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set to use the latest library format */
+ if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set the filename to use for this test (dependent on fapl) */
+ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename));
+
+ /* Create the test file to work on */
+ if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Create a chunked dataset with 2 extendible dimensions */
+ if((sid = H5Screate_simple(2, dims, maxdims)) < 0)
+ FAIL_STACK_ERROR;
+ if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)
+ FAIL_STACK_ERROR
+ if(H5Pset_chunk(dcpl, 2, chunk_dims) < 0)
+ FAIL_STACK_ERROR;
+ if((did1 = H5Dcreate2(fid, "dataset1", H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, dapl1)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Open the dataset */
+ if((did2 = H5Dopen2(fid, "dataset1", dapl2)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Get the dataset's access property list for did1 */
+ if((ddapl = H5Dget_access_plist(did1)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Retrieve the append flush property values */
+ if(H5Pget_append_flush(ddapl, 3, ret_boundary, &ret_cb, (void **)&ret_count) < 0)
+ TEST_ERROR
+
+ /* Verify expected values: should be the setting in dapl1 */
+ if(ret_boundary[0] != 0 || ret_boundary[1] != 1 || ret_boundary[2] != 0)
+ TEST_ERROR;
+ if(ret_cb != append_cb || ret_count != &count1)
+ TEST_ERROR
+
+ /* Close the dataset's access property list */
+ if(H5Pclose(ddapl) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Get the dataset's access property list for did2 */
+ if((ddapl = H5Dget_access_plist(did2)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Retrieve the append flush property values */
+ if(H5Pget_append_flush(ddapl, 3, ret_boundary, &ret_cb, (void **)&ret_count) < 0)
+ TEST_ERROR
+
+ /* Verify expected values: should be the setting in dapl1 */
+ if(ret_boundary[0] != 0 || ret_boundary[1] != 1 || ret_boundary[2] != 0)
+ TEST_ERROR;
+ if(ret_cb != append_cb || ret_count != &count1)
+ TEST_ERROR
+
+ /* Close the dataset's access property list */
+ if(H5Pclose(ddapl) < 0)
+ FAIL_STACK_ERROR;
+ H5Dclose(did1);
+ H5Dclose(did2);
+
+ /*
+ * Case (2)
+ * For a chunked dataset's access property list:
+ * H5Dcreate(...H5P_DEFAULT...)
+ * H5Dclose()
+ * did1 = H5Dopen(...dapl1)
+ * did2 = H5Dopen(..dapl2)
+ * H5Pget_append_flush(did1, ...)
+ * H5Pget_append_flush(did2, ...)
+ * -- should return append flush property values set in dapl1
+ */
+ if((did1 = H5Dcreate2(fid, "dataset2", H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Dclose(did1) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Open the dataset with append flush setting in dapl2 */
+ if((did1 = H5Dopen2(fid, "dataset2", dapl2)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Open the dataset with append flush setting in dapl1 */
+ if((did2 = H5Dopen2(fid, "dataset2", dapl1)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Get the dataset's access property list for did1 */
+ if((ddapl = H5Dget_access_plist(did1)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Retrieve the append flush property values */
+ if(H5Pget_append_flush(ddapl, 3, ret_boundary, &ret_cb, (void **)&ret_count) < 0)
+ TEST_ERROR
+
+ /* Verify expected values: should be the setting in dapl2 */
+ if(ret_boundary[0] != 1 || ret_boundary[1] != 0 || ret_boundary[2] != 0)
+ TEST_ERROR;
+ if(ret_cb != append_cb2 || ret_count != &count2)
+ TEST_ERROR
+
+ /* Close the access property list */
+ if(H5Pclose(ddapl) < 0)
+ FAIL_STACK_ERROR;
+
+
+ /* Get the dataset's access property list for did2 */
+ if((ddapl = H5Dget_access_plist(did2)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Retrieve the append flush property values */
+ if(H5Pget_append_flush(ddapl, 3, ret_boundary, &ret_cb, (void **)&ret_count) < 0)
+ TEST_ERROR
+
+ /* Verify expected values: should be the setting in dapl2 */
+ if(ret_boundary[0] != 1 || ret_boundary[1] != 0 || ret_boundary[2] != 0)
+ TEST_ERROR;
+ if(ret_cb != append_cb2 || ret_count != &count2)
+ TEST_ERROR
+
+ /* Closing */
+ if(H5Pclose(ddapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(dapl2) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(dapl1) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(dcpl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Pclose(fapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Dclose(did1) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Dclose(did2) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Sclose(sid) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ PASSED();
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(dcpl);
+ H5Pclose(dapl1);
+ H5Pclose(dapl2);
+ H5Pclose(ddapl);
+ H5Dclose(did1);
+ H5Dclose(did2);
+ H5Pclose(fapl);
+ H5Sclose(sid);
+ H5Fclose(fid);
+ } H5E_END_TRY;
+
+ return -1;
+} /* test_append_flush_dataset_multiple() */
+
+/****************************************************************
+**
+** test_file(): Main low-level file I/O test routine.
+**
+****************************************************************/
+int
+main(void)
+{
+ int nerrors = 0; /* The # of errors */
+ hid_t fapl = -1; /* File access property list ID */
+
+ /* Set up */
+ h5_reset();
+
+ /* Get file access property list */
+ fapl = h5_fileaccess();
+
+ /* Tests on H5Fstart_swmr_write() */
+ nerrors += test_start_swmr_write(fapl);
+ nerrors += test_err_start_swmr_write(fapl);
+ nerrors += test_start_swmr_write_concur(fapl);
+
+ /* Tests for H5Pget/set_object_flush_cb() */
+ nerrors += test_object_flush_cb(fapl);
+
+ /* Tests on H5Pget/set_append_flush() */
+ nerrors += test_append_flush_generic();
+ nerrors += test_append_flush_dataset_chunked(fapl);
+ nerrors += test_append_flush_dataset_fixed(fapl);
+ nerrors += test_append_flush_dataset_multiple(fapl);
+
+ if(nerrors)
+ goto error;
+
+ printf("All tests passed for H5Fstart_swmr_write(), H5Pget/set_object_flush_cb(), H5Pget/set_append_flush().\n");
+
+ h5_cleanup(FILENAME, fapl);
+
+ return 0;
+
+error:
+ nerrors = MAX(1, nerrors);
+ printf("***** %d SWMR TEST%s FAILED! *****\n",
+ nerrors, 1 == nerrors ? "" : "S");
+ return 1;
+
+} /* main() */
diff --git a/test/testswmr.sh b/test/testswmr.sh
index 794910c..42e76ce 100755
--- a/test/testswmr.sh
+++ b/test/testswmr.sh
@@ -34,6 +34,14 @@ Nsecs_addrem=8 # number of seconds per read interval
nerrors=0
###############################################################################
+## definitions for message file to coordinate test runs
+###############################################################################
+WRITER_MESSAGE=SWMR_WRITER_MESSAGE # The message file created by writer that the open is complete
+ # This should be the same as the define in "./swmr_common.h"
+MESSAGE_TIMEOUT=300 # Message timeout length in secs
+ # This should be the same as the define in "./h5test.h"
+
+###############################################################################
## short hands and function definitions
###############################################################################
DPRINT=: # Set to "echo Debug:" for debugging printing,
@@ -48,8 +56,42 @@ TESTING() {
echo "Testing $* $SPACES" | cut -c1-70 | tr -d '\012'
}
+# To wait for the writer message file or till the maximum # of seconds is reached
+# $1 is the message file to wait for
+# This performs similar function as the routine h5_wait_message() in test/h5test.c
+WAIT_MESSAGE() {
+ message=$1 # Get the name of the message file to wait for
+ t0=`date +%s` # Get current time in seconds
+ difft=0 # Initialize the time difference
+ mexist=0 # Indicate whether the message file is found
+ while [ $difft -lt $MESSAGE_TIMEOUT ] ; # Loop till message times out
+ do
+ t1=`date +%s` # Get current time in seconds
+ difft=`expr $t1 - $t0` # Calculate the time difference
+ if [ -e $message ]; then # If message file is found:
+ mexist=1 # indicate the message file is found
+ rm $message # remove the message file
+ break # get out of the while loop
+ fi
+ done;
+ if test $mexist -eq 0; then
+ # Issue warning that the writer message file is not found, continue with launching the reader(s)
+ echo warning: $WRITER_MESSAGE is not found after waiting $MESSAGE_TIMEOUT seconds
+ else
+ echo $WRITER_MESSAGE is found
+ fi
+}
+
###############################################################################
## Main
+##
+## Modifications:
+## Vailin Choi; July 2013
+## Add waiting of message file before launching the reader(s).
+## Due to the implementation of file locking, coordination
+## is needed in file opening for the writer/reader tests
+## to proceed as expected.
+##
###############################################################################
# The build (current) directory might be different than the source directory.
if test -z "$srcdir"; then
@@ -103,6 +145,66 @@ do
echo
echo "###############################################################################"
+ echo "## Use H5Fstart_swmr_write() to enable SWMR writing mode"
+ echo "###############################################################################"
+
+ # Remove any possible writer message file before launching writer
+ rm -f $WRITER_MESSAGE
+ #
+ # Launch the Writer
+ echo launch the swmr_start_writer
+ seed="" # Put -r <random seed> command here
+ ./swmr_start_write $compress $index_type $Nrecords $seed &
+ pid_writer=$!
+ $DPRINT pid_writer=$pid_writer
+ #
+ # Wait for message from writer process before starting reader(s)
+ WAIT_MESSAGE $WRITER_MESSAGE
+
+ #
+ # Launch the Readers
+ #declare -a seeds=(<seed1> <seed2> <seed3> ... )
+ echo launch $Nreaders swmr_readers
+ pid_readers=""
+ n=0
+ while [ $n -lt $Nreaders ]; do
+ #seed="-r ${seeds[$n]}"
+ seed=""
+ ./swmr_reader $Nsecs_add $seed &
+ pid_readers="$pid_readers $!"
+ n=`expr $n + 1`
+ done
+ $DPRINT pid_readers=$pid_readers
+ $IFDEBUG ps
+
+ # Collect exit code of the readers first because they usually finish
+ # before the writer.
+ for xpid in $pid_readers; do
+ $DPRINT checked reader $xpid
+ wait $xpid
+ if test $? -ne 0; then
+ echo reader had error
+ nerrors=`expr $nerrors + 1`
+ fi
+ done
+
+ # Collect exit code of the writer
+ $DPRINT checked writer $pid_writer
+ wait $pid_writer
+ if test $? -ne 0; then
+ echo writer had error
+ nerrors=`expr $nerrors + 1`
+ fi
+
+ # Check for error and exit if one occured
+ $DPRINT nerrors=$nerrors
+ if test $nerrors -ne 0 ; then
+ echo "SWMR tests failed with $nerrors errors."
+ exit 1
+ fi
+
+ echo
+ echo "###############################################################################"
echo "## Writer test - test expanding the dataset"
echo "###############################################################################"
@@ -113,14 +215,19 @@ do
echo generator had error
nerrors=`expr $nerrors + 1`
fi
-
+ # Remove any possible writer message file before launching writer
+ rm -f $WRITER_MESSAGE
+ #
# Launch the Writer
echo launch the swmr_writer
seed="" # Put -r <random seed> command here
./swmr_writer $Nrecords $seed &
pid_writer=$!
$DPRINT pid_writer=$pid_writer
-
+ #
+ # Wait for message from writer process before starting reader(s)
+ WAIT_MESSAGE $WRITER_MESSAGE
+ #
# Launch the Readers
#declare -a seeds=(<seed1> <seed2> <seed3> ... )
echo launch $Nreaders swmr_readers
@@ -166,14 +273,19 @@ do
echo "###############################################################################"
echo "## Remove test - test shrinking the dataset"
echo "###############################################################################"
-
+ #
+ # Remove any possible writer message file before launching writer
+ rm -f $WRITER_MESSAGE
# Launch the Remove Writer
echo launch the swmr_remove_writer
seed="" # Put -r <random seed> command here
./swmr_remove_writer $Nrecs_rem $seed &
pid_writer=$!
$DPRINT pid_writer=$pid_writer
-
+ #
+ # Wait for message from writer process before starting reader(s)
+ WAIT_MESSAGE $WRITER_MESSAGE
+ #
# Launch the Remove Readers
#declare -a seeds=(<seed1> <seed2> <seed3> ... )
n=0
@@ -236,14 +348,20 @@ do
echo writer had error
nerrors=`expr $nerrors + 1`
fi
-
+ #
+ # Remove any possible writer message file before launching writer
+ rm -f $WRITER_MESSAGE
+ #
# Launch the Add/Remove Writer
echo launch the swmr_addrem_writer
seed="" # Put -r <random seed> command here
./swmr_addrem_writer $Nrecords $seed &
pid_writer=$!
$DPRINT pid_writer=$pid_writer
-
+ #
+ # Wait for message from writer process before starting reader(s)
+ WAIT_MESSAGE $WRITER_MESSAGE
+ #
# Launch the Add/Remove Readers
#declare -a seeds=(<seed1> <seed2> <seed3> ... )
n=0
@@ -300,13 +418,18 @@ do
echo generator had error
nerrors=`expr $nerrors + 1`
fi
-
+ #
+ # Remove any possible writer message file before launching writer
+ rm -f $WRITER_MESSAGE
# Launch the Sparse writer
echo launch the swmr_sparse_writer
nice -n 20 ./swmr_sparse_writer $Nrecs_spa &
pid_writer=$!
$DPRINT pid_writer=$pid_writer
-
+ #
+ # Wait for message from writer process before starting reader(s)
+ WAIT_MESSAGE $WRITER_MESSAGE
+ #
# Launch the Sparse readers
n=0
pid_readers=""
diff --git a/test/tfile.c b/test/tfile.c
index e2c7bf4..8d64b64 100644
--- a/test/tfile.c
+++ b/test/tfile.c
@@ -118,6 +118,9 @@
#define NGROUPS 2
#define NDSETS 4
+/* Name of message file that is used by test_file_lock_concur() and test_file_lock_swmr_concur() */
+#define DONE_MESSAGE "DONE_MESSAGE" /* The message file to create */
+
const char *OLD_FILENAME[] = { /* Files created under 1.6 branch and 1.8 branch */
"filespace_1_6.h5", /* 1.6 HDF5 file */
"filespace_1_8.h5" /* 1.8 HDF5 file */
@@ -144,6 +147,16 @@ test_obj_count_and_id(hid_t, hid_t, hid_t, hid_t, hid_t, hid_t);
static void
check_file_id(hid_t, hid_t);
+/* Helper routine used by test_rw_noupdate() */
+static int cal_chksum(const char *file, uint32_t *chksum);
+
+static void test_rw_noupdate(void);
+
+static void test_file_lock_same(void);
+static void test_file_lock_swmr_same(void);
+static void test_file_lock_concur(void);
+static void test_file_lock_swmr_concur(void);
+
/****************************************************************
**
** test_file_create(): Low-level file creation I/O test routine.
@@ -2312,6 +2325,104 @@ test_cached_stab_info(void)
CHECK(ret, FAIL, "H5Fclose");
} /* end test_cached_stab_info() */
+/*
+ * To calculate the checksum for a file.
+ * This is a helper routine for test_rw_noupdate().
+ */
+static int
+cal_chksum(const char *file, uint32_t *chksum)
+{
+ int curr_num_errs = GetTestNumErrs(); /* Retrieve the current # of errors */
+ int fdes = -1; /* File descriptor */
+ void *file_data = NULL; /* Copy of file data */
+ ssize_t bytes_read; /* # of bytes read */
+ h5_stat_t sb; /* Stat buffer for file */
+ herr_t ret; /* Generic return value */
+
+ /* Open the file */
+ fdes = HDopen(file, O_RDONLY, 0);
+ CHECK(fdes, FAIL, "HDopen");
+
+ /* Retrieve the file's size */
+ ret = HDfstat(fdes, &sb);
+ CHECK(fdes, FAIL, "HDfstat");
+
+ /* Allocate space for the file data */
+ file_data = HDmalloc((size_t)sb.st_size);
+ CHECK(file_data, NULL, "HDmalloc");
+
+ if(file_data) {
+ /* Read file's data into memory */
+ bytes_read = HDread(fdes, file_data, (size_t)sb.st_size);
+ CHECK(bytes_read == sb.st_size, FALSE, "HDmalloc");
+
+ /* Calculate checksum */
+ *chksum = H5_checksum_lookup3(file_data, sizeof(file_data), 0);
+
+ /* Free memory */
+ HDfree(file_data);
+ }
+
+ /* Close the file */
+ ret = HDclose(fdes);
+ CHECK(ret, FAIL, "HDclose");
+
+ return((GetTestNumErrs() == curr_num_errs) ? 0 : -1);
+} /* cal_chksum() */
+
+/****************************************************************
+**
+** test_rw_noupdate(): low-level file test routine.
+** This test checks to ensure that opening and closing a file
+** with read/write permissions does not write anything to the
+** file if the file does not change.
+** Due to the implementation of file locking (status_flags in
+** the superblock is used), this test is changed to use checksum
+** instead of timestamp to verify the file is not changed.
+**
+** Programmer: Vailin Choi; July 2013
+**
+*****************************************************************/
+static void
+test_rw_noupdate(void)
+{
+ herr_t ret; /* Generic return value */
+ hid_t fid; /* File ID */
+ uint32_t chksum1, chksum2; /* Checksum value */
+
+ /* Output message about test being performed */
+ MESSAGE(5, ("Testing to verify that nothing is written if nothing is changed.\n"));
+
+ /* Create and Close a HDF5 File */
+ fid = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fcreate");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Calculate checksum for the file */
+ ret = cal_chksum(FILE1, &chksum1);
+ CHECK(ret, FAIL, "HDopen");
+
+ /* Open and close File With Read/Write Permission */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Calculate checksum for the file */
+ ret = cal_chksum(FILE1, &chksum2);
+ CHECK(ret, FAIL, "HDopen");
+
+ /* The two checksums are the same, i.e. the file is not changed */
+ VERIFY(chksum1, chksum2, "Checksum");
+
+} /* end test_rw_noupdate() */
+
+#ifdef OUT
/****************************************************************
**
** test_rw_noupdate(): low-level file test routine.
@@ -2400,6 +2511,7 @@ test_rw_noupdate(void)
VERIFY(ret, 0, "Timestamp");
} /* end else */
} /* end test_rw_noupdate() */
+#endif
/****************************************************************
**
@@ -3501,268 +3613,6 @@ test_libver_macros2(void)
/****************************************************************
**
-** test_swmr_write(): low-level file test routine.
-** This test checks that the H5F_ACC_SWMR_WRITE access flag is
-** working properly.
-**
-*****************************************************************/
-static void
-test_swmr_write(void)
-{
- hid_t fid, fid2; /* File IDs */
- hid_t fapl; /* File access property list id */
- unsigned intent; /* File access flags */
- herr_t ret; /* Generic return value */
-
- /* Output message about test being performed */
- MESSAGE(5, ("Testing H5F_ACC_SWMR_WRITE access flag\n"));
-
- /* Create a file access property list */
- fapl = H5Pcreate(H5P_FILE_ACCESS);
- CHECK(fapl, FAIL, "H5Pcreate");
-
- /* Set to use the latest library format */
- ret = H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST);
- CHECK(ret, FAIL, "H5Pset_libver_bounds");
-
- /* Create file, without SWMR_WRITE flag */
- fid = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl);
- CHECK(fid, FAIL, "H5Fcreate");
-
- /* Get the intent & check that the SWMR_WRITE flag is not set */
- ret = H5Fget_intent(fid, &intent);
- CHECK(ret, FAIL, "H5Fget_intent");
- VERIFY(intent, H5F_ACC_RDWR, "H5Fget_intent");
-
- /* Try to reopen file w/SWMR_WRITE flag */
- H5E_BEGIN_TRY {
- fid2 = H5Fopen(FILE1, (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE), fapl);
- } H5E_END_TRY;
- VERIFY(fid2, FAIL, "H5Fopen");
-
- /* Close file */
- ret = H5Fclose(fid);
- CHECK(ret, FAIL, "H5Fclose");
-
-
- /* Attempt to open file, with SWMR_WRITE flag but not latest format */
- H5E_BEGIN_TRY {
- fid = H5Fopen(FILE1, (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE), H5P_DEFAULT);
- } H5E_END_TRY;
- VERIFY(fid, FAIL, "H5Fopen");
-
-
- /* Create file, with SWMR_WRITE flag */
- fid = H5Fcreate(FILE1, (H5F_ACC_TRUNC | H5F_ACC_SWMR_WRITE), H5P_DEFAULT, fapl);
- CHECK(fid, FAIL, "H5Fcreate");
-
- /* Get the intent & check that the SWMR_WRITE flag is set */
- ret = H5Fget_intent(fid, &intent);
- CHECK(ret, FAIL, "H5Fget_intent");
- VERIFY(intent, (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE), "H5Fget_intent");
-
- /* Try to reopen file w/o SWMR_WRITE flag */
- H5E_BEGIN_TRY {
- fid2 = H5Fopen(FILE1, H5F_ACC_RDWR, fapl);
- } H5E_END_TRY;
- VERIFY(fid2, FAIL, "H5Fopen");
-
- /* Reopen file, with read-write and SWMR_WRITE access */
- fid2 = H5Fopen(FILE1, (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE), fapl);
- CHECK(fid2, FAIL, "H5Fopen");
-
- /* Get the intent & check that the SWMR_WRITE flag is set */
- ret = H5Fget_intent(fid2, &intent);
- CHECK(ret, FAIL, "H5Fget_intent");
- VERIFY(intent, (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE), "H5Fget_intent");
-
- /* Close file */
- ret = H5Fclose(fid2);
- CHECK(ret, FAIL, "H5Fclose");
-
- /* Close file */
- ret = H5Fclose(fid);
- CHECK(ret, FAIL, "H5Fclose");
-
-
- /* Try to reopen file read-only w/SWMR_WRITE flag */
- H5E_BEGIN_TRY {
- fid = H5Fopen(FILE1, (H5F_ACC_RDONLY | H5F_ACC_SWMR_WRITE), fapl);
- } H5E_END_TRY;
- VERIFY(fid, FAIL, "H5Fopen");
-
-
- /* Reopen file, with read-write and SWMR_WRITE access */
- fid = H5Fopen(FILE1, (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE), fapl);
- CHECK(fid, FAIL, "H5Fopen");
-
- /* Get the intent & check that the SWMR_WRITE flag is set */
- ret = H5Fget_intent(fid, &intent);
- CHECK(ret, FAIL, "H5Fget_intent");
- VERIFY(intent, (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE), "H5Fget_intent");
-
- /* Try to reopen file w/o SWMR_WRITE flag */
- H5E_BEGIN_TRY {
- fid2 = H5Fopen(FILE1, H5F_ACC_RDWR, fapl);
- } H5E_END_TRY;
- VERIFY(fid2, FAIL, "H5Fopen");
-
- /* Reopen file, with read-write and SWMR_WRITE access */
- fid2 = H5Fopen(FILE1, (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE), fapl);
- CHECK(fid2, FAIL, "H5Fopen");
-
- /* Get the intent & check that the SWMR_WRITE flag is set */
- ret = H5Fget_intent(fid2, &intent);
- CHECK(ret, FAIL, "H5Fget_intent");
- VERIFY(intent, (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE), "H5Fget_intent");
-
- /* Close file */
- ret = H5Fclose(fid2);
- CHECK(ret, FAIL, "H5Fclose");
-
- /* Close file */
- ret = H5Fclose(fid);
- CHECK(ret, FAIL, "H5Fclose");
-
- /* Close the property list */
- ret = H5Pclose(fapl);
- CHECK(ret, FAIL, "H5Pclose");
-
-
- /* Create a file access property list */
- fapl = H5Pcreate(H5P_FILE_ACCESS);
- CHECK(fapl, FAIL, "H5Pcreate");
-
- /* Set a non-POSIX VFD */
- ret = H5Pset_fapl_stdio(fapl);
- CHECK(ret, FAIL, "H5Pset_fapl_stdio");
-
- /* Try to reopen file w/SWMR_WRITE flag & non-POSIX VFD */
- H5E_BEGIN_TRY {
- fid = H5Fopen(FILE1, (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE), fapl);
- } H5E_END_TRY;
- VERIFY(fid, FAIL, "H5Fopen");
-
- /* Close the property list */
- ret = H5Pclose(fapl);
- CHECK(ret, FAIL, "H5Pclose");
-
-} /* end test_swmr_write() */
-
-/****************************************************************
-**
-** test_swmr_read(): low-level file test routine.
-** This test checks that the H5F_ACC_SWMR_READ access flag is
-** working properly.
-**
-*****************************************************************/
-static void
-test_swmr_read(void)
-{
- hid_t fid, fid2; /* File IDs */
- hid_t fapl; /* File access property list id */
- unsigned intent; /* File access flags */
- herr_t ret; /* Generic return value */
-
- /* Output message about test being performed */
- MESSAGE(5, ("Testing H5F_ACC_SWMR_READ access flag\n"));
-
-
- /* Try to create file w/SWMR_READ flag */
- H5E_BEGIN_TRY {
- fid = H5Fcreate(FILE1, (H5F_ACC_TRUNC | H5F_ACC_SWMR_READ), H5P_DEFAULT, H5P_DEFAULT);
- } H5E_END_TRY;
- VERIFY(fid, FAIL, "H5Fcreate");
-
-
- /* Create file, without SWMR_READ flag */
- fid = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
- CHECK(fid, FAIL, "H5Fcreate");
-
- /* Get the intent & check that the SWMR_READ flag is not set */
- ret = H5Fget_intent(fid, &intent);
- CHECK(ret, FAIL, "H5Fget_intent");
- VERIFY(intent, H5F_ACC_RDWR, "H5Fget_intent");
-
- /* Try to reopen file w/SWMR_READ flag */
- H5E_BEGIN_TRY {
- fid2 = H5Fopen(FILE1, (H5F_ACC_RDWR | H5F_ACC_SWMR_READ), H5P_DEFAULT);
- } H5E_END_TRY;
- VERIFY(fid2, FAIL, "H5Fopen");
-
- /* Close file */
- ret = H5Fclose(fid);
- CHECK(ret, FAIL, "H5Fclose");
-
-
- /* Try to open file, with read-write access & SWMR_READ flag */
- H5E_BEGIN_TRY {
- fid = H5Fopen(FILE1, (H5F_ACC_RDWR | H5F_ACC_SWMR_READ), H5P_DEFAULT);
- } H5E_END_TRY;
- VERIFY(fid, FAIL, "H5Fopen");
-
-
- /* Attempt to open file, with SWMR_WRITE flag but not latest format */
- H5E_BEGIN_TRY {
- fid = H5Fopen(FILE1, (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE), H5P_DEFAULT);
- } H5E_END_TRY;
- VERIFY(fid, FAIL, "H5Fopen");
-
- /* Open file, with SWMR_READ flag (and non-latest format) */
- fid = H5Fopen(FILE1, (H5F_ACC_RDONLY | H5F_ACC_SWMR_READ), H5P_DEFAULT);
- CHECK(fid, FAIL, "H5Fopen");
-
- /* Get the intent & check that the SWMR_READ flag is set */
- ret = H5Fget_intent(fid, &intent);
- CHECK(ret, FAIL, "H5Fget_intent");
- VERIFY(intent, (H5F_ACC_RDONLY | H5F_ACC_SWMR_READ), "H5Fget_intent");
-
- /* Try to reopen file w/o SWMR_READ flag */
- H5E_BEGIN_TRY {
- fid2 = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
- } H5E_END_TRY;
- VERIFY(fid2, FAIL, "H5Fopen");
-
- /* Reopen file, with read-only and SWMR_READ access */
- fid2 = H5Fopen(FILE1, (H5F_ACC_RDONLY | H5F_ACC_SWMR_READ), H5P_DEFAULT);
- CHECK(fid2, FAIL, "H5Fopen");
-
- /* Get the intent & check that the SWMR_READ flag is set */
- ret = H5Fget_intent(fid2, &intent);
- CHECK(ret, FAIL, "H5Fget_intent");
- VERIFY(intent, (H5F_ACC_RDONLY | H5F_ACC_SWMR_READ), "H5Fget_intent");
-
- /* Close file */
- ret = H5Fclose(fid2);
- CHECK(ret, FAIL, "H5Fclose");
-
- /* Close file */
- ret = H5Fclose(fid);
- CHECK(ret, FAIL, "H5Fclose");
-
-
- /* Create a file access property list */
- fapl = H5Pcreate(H5P_FILE_ACCESS);
- CHECK(fapl, FAIL, "H5Pcreate");
-
- /* Set a non-POSIX VFD */
- ret = H5Pset_fapl_stdio(fapl);
- CHECK(ret, FAIL, "H5Pset_fapl_stdio");
-
- /* Try to reopen file w/SWMR_READ flag & non-POSIX VFD */
- H5E_BEGIN_TRY {
- fid = H5Fopen(FILE1, (H5F_ACC_RDONLY | H5F_ACC_SWMR_READ), fapl);
- } H5E_END_TRY;
- VERIFY(fid, FAIL, "H5Fopen");
-
- /* Close the property list */
- ret = H5Pclose(fapl);
- CHECK(ret, FAIL, "H5Pclose");
-
-} /* end test_swmr_read() */
-
-/****************************************************************
-**
** test_metadata_read_attempts():
** This test checks whether the following two public routines work as
** specified in the reference manuals:
@@ -5041,6 +4891,1305 @@ test_metadata_read_retry_info(void)
/****************************************************************
**
+** test_file_lock_same():
+** With the implementation of file locking, this test checks file
+** open with different combinations of flags.
+** This is for single process access.
+**
+*****************************************************************/
+static void
+test_file_lock_same(void)
+{
+ hid_t fid, fid2; /* File IDs */
+ unsigned intent; /* File access flags */
+ herr_t ret; /* Generic return value */
+
+ /* Output message about test being performed */
+ MESSAGE(5, ("Testing file open with different combinations of flags--single process access\n"));
+
+ /*
+ * Case 1: 1) RDWR 2) RDWR : should succeed
+ */
+ /* Create file */
+ fid = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fcreate");
+
+ /* Get and check file intent */
+ ret = H5Fget_intent(fid, &intent);
+ CHECK(ret, FAIL, "H5Fget_intent");
+ VERIFY(intent, H5F_ACC_RDWR, "H5Fget_intent");
+
+ /* Open the same file with RDWR */
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+
+ /* Get and check the intent */
+ ret = H5Fget_intent(fid2, &intent);
+ CHECK(ret, FAIL, "H5Fget_intent");
+ VERIFY(intent, H5F_ACC_RDWR, "H5Fget_intent");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Close file */
+ ret = H5Fclose(fid2);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 2: 1) RDWR 2) RDONLY : should succeed
+ */
+ /* Open file with RDWR */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fcreate");
+
+ /* Get and check the intent */
+ ret = H5Fget_intent(fid, &intent);
+ CHECK(ret, FAIL, "H5Fget_intent");
+ VERIFY(intent, H5F_ACC_RDWR, "H5Fget_intent");
+
+ /* Open file with RDONLY */
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+
+ /* Get and check the intent: should get intent from 1st open */
+ ret = H5Fget_intent(fid2, &intent);
+ CHECK(ret, FAIL, "H5Fget_intent");
+ VERIFY(intent, H5F_ACC_RDWR, "H5Fget_intent");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Close file */
+ ret = H5Fclose(fid2);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 3: 1) RDONLY 2) RDWR : should fail
+ */
+ /* Open file with RDONLY */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fcreate");
+
+ /* Get and check the intent */
+ ret = H5Fget_intent(fid, &intent);
+ CHECK(ret, FAIL, "H5Fget_intent");
+ VERIFY(intent, H5F_ACC_RDONLY, "H5Fget_intent");
+
+ /* Open file with RDWR should fail */
+ H5E_BEGIN_TRY {
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+ } H5E_END_TRY;
+ VERIFY(fid2, FAIL, "H5Fopen");
+
+ /* Close first file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 4: 1) RDONLY 2) RDONLY : should succeed
+ */
+ /* Open file with RDONLY */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fcreate");
+
+ /* Get and check the intent */
+ ret = H5Fget_intent(fid, &intent);
+ CHECK(ret, FAIL, "H5Fget_intent");
+ VERIFY(intent, H5F_ACC_RDONLY, "H5Fget_intent");
+
+ /* Open file with RDONLY */
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+
+ /* Get and check the intent */
+ ret = H5Fget_intent(fid2, &intent);
+ CHECK(ret, FAIL, "H5Fget_intent");
+ VERIFY(intent, H5F_ACC_RDONLY, "H5Fget_intent");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Close file */
+ ret = H5Fclose(fid2);
+ CHECK(ret, FAIL, "H5Fclose");
+
+} /* end test_file_lock_same() */
+
+/****************************************************************
+**
+** test_file_lock_swmr_same():
+** With the implementation of file locking, this test checks file
+** open with different combinations of flags + SWMR flags.
+** This is for single process access.
+**
+*****************************************************************/
+static void
+test_file_lock_swmr_same(void)
+{
+ hid_t fid, fid2; /* File IDs */
+ hid_t fapl; /* File access property list */
+ herr_t ret; /* Generic return value */
+
+ /* Output message about test being performed */
+ MESSAGE(5, ("Testing file open with different combinations of flags + SWMR flags--single process access\n"));
+
+ /* Create a file access property list */
+ fapl = H5Pcreate(H5P_FILE_ACCESS);
+ CHECK(fapl, FAIL, "H5Pcreate");
+
+ /* Set to use latest library format */
+ ret = H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST);
+ CHECK(ret, FAIL, "H5Pset_libver_bounds");
+
+ /* Create a file */
+ fid = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl);
+ CHECK(fid, FAIL, "H5Fcreate");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Cases a, b, c, d: H5Fopen failure cases
+ */
+
+ /*
+ * Case a: RDWR|SWRM_READ : should fail
+ */
+ H5E_BEGIN_TRY {
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_READ, fapl);
+ } H5E_END_TRY;
+ VERIFY(fid, FAIL, "H5Fopen");
+
+ /*
+ * Case b: RDWR|SWMM_WRTE|SWMR_READ : should fail
+ */
+ H5E_BEGIN_TRY {
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE|H5F_ACC_SWMR_READ, fapl);
+ } H5E_END_TRY;
+ VERIFY(fid, FAIL, "H5Fopen");
+
+ /*
+ * Case c: RDONLY|SWMM_WRITE : should fail
+ */
+ H5E_BEGIN_TRY {
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_WRITE, fapl);
+ } H5E_END_TRY;
+ VERIFY(fid, FAIL, "H5Fopen");
+
+ /*
+ * Case d: RDONLY|SWMM_WRITE|SWMR_READ : should fail
+ */
+ H5E_BEGIN_TRY {
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_WRITE|H5F_ACC_SWMR_READ, fapl);
+ } H5E_END_TRY;
+ VERIFY(fid, FAIL, "H5Fopen");
+
+ /*
+ * Cases 1 - 12: combinations of different flags for 1st and 2nd opens
+ */
+
+ /*
+ * Case 1: 1) RDWR 2) RDWR|SWMR_WRITE : should fail
+ */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ H5E_BEGIN_TRY {
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+ } H5E_END_TRY;
+ VERIFY(fid2, FAIL, "H5Fopen");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 2: 1) RDWR 2) RDONLY|SWMR_READ : should succeed
+ */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fopen");
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+ CHECK(fid2, FAIL, "H5Fopen");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+ ret = H5Fclose(fid2);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 3: 1) RDWR|SWMR_WRITE 2)RDWR : should succeed
+ */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+ CHECK(fid2, FAIL, "H5Fopen");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Close file */
+ ret = H5Fclose(fid2);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 4: 1) RDWR|SWMR_WRITE 2) RDWR|SWMR_WRITE : should succeed
+ */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+ CHECK(fid2, FAIL, "H5Fopen");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Close file */
+ ret = H5Fclose(fid2);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 5: 1) RDWR|SWMR_WRITE 2) RDONLY|SWMR_READ : should succeed
+ */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+ CHECK(fid2, FAIL, "H5Fopen");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Close file */
+ ret = H5Fclose(fid2);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 6: 1) RDWR|SWMR_WRITE 2) RDONLY : should succeed
+ */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+ CHECK(fid2, FAIL, "H5Fopen");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Close file */
+ ret = H5Fclose(fid2);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 7: 1) RDONLY|SWMR_READ 2)RDWR : should fail
+ */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ H5E_BEGIN_TRY {
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+ } H5E_END_TRY;
+ VERIFY(fid2, FAIL, "H5Fopen");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 8: 1) RDONLY|SWMR_READ 2) RDWR|SWMR_WRITE : should fail
+ */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ H5E_BEGIN_TRY {
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+ } H5E_END_TRY;
+ VERIFY(fid2, FAIL, "H5Fopen");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 9: 1) RDONLY|SWMR_READ 2) RDONLY|SWMR_READ : should succeed
+ */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+ CHECK(fid2, FAIL, "H5Fopen");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Close file */
+ ret = H5Fclose(fid2);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 10: 1) RDONLY|SWMR_READ 2) RDONLY : should succeed
+ */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+ CHECK(fid2, FAIL, "H5Fopen");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Close file */
+ ret = H5Fclose(fid2);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 11: 1) RDONLY 2) RDWR|SWMR_WRITE: should fail
+ */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ H5E_BEGIN_TRY {
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+ } H5E_END_TRY;
+ VERIFY(fid2, FAIL, "H5Fopen");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 12: 1) RDONLY 2) RDONLY|SWMR_READ : should fail
+ */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ H5E_BEGIN_TRY {
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+ } H5E_END_TRY;
+ VERIFY(fid2, FAIL, "H5Fopen");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Close the property list */
+ ret=H5Pclose(fapl);
+ CHECK(ret, FAIL, "H5Pclose");
+
+} /* end test_file_lock_swmr_same() */
+
+
+/****************************************************************
+**
+** test_file_lock_concur():
+** With the implementation of file locking, this test checks file
+** open with different combinations of flags.
+** This is for concurrent access.
+**
+*****************************************************************/
+static void
+test_file_lock_concur(void)
+{
+ hid_t fid; /* File ID */
+ herr_t ret; /* Generic return value */
+ pid_t childpid=0; /* Child process ID */
+ pid_t tmppid; /* Child process ID returned by waitpid */
+ int child_status; /* Status passed to waitpid */
+ int child_wait_option=0; /* Options passed to waitpid */
+ int child_ret_value; /* Exit status of the child */
+
+ /* Output message about test being performed */
+ MESSAGE(5, ("Testing file open with different combinations of flags--concurrent access\n"));
+
+#if !(defined(H5_HAVE_FORK) && defined(H5_HAVE_WAITPID))
+
+ SKIPPED();
+ HDputs(" Test skipped due to fork or waitpid not defined.");
+
+#else /* defined(H5_HAVE_FORK && defined(H5_HAVE_WAITPID) */
+
+ /* Create the test file */
+ fid = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 1: 1) RDWR 2) RDWR : should fail
+ */
+
+ /* Remove the message file to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Open the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+
+ /* Should fail */
+ if(child_fid == FAIL)
+ exit(0);
+ exit(1);
+ }
+
+ /* Open the test file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of the child */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 2: 1) RDWR 2) RDONLY : should fail
+ */
+ /* Remove the message file just to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Opens the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+
+ /* Should fail */
+ if(child_fid == FAIL)
+ exit(0);
+ exit(1);
+ }
+
+ /* Opens the test file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of the child */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ H5Fclose(fid);
+
+ /*
+ * Case 3: 1) RDONLY 2) RDWR : should fail
+ */
+
+ /* Remove the message file just to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Opens the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+
+ /* Should fail */
+ if(child_fid == FAIL)
+ exit(0);
+ exit(1);
+ }
+
+ /* Opens the test file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of child process */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 4: 1) RDONLY 2) RDONLY : should succeed
+ */
+
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+ herr_t child_ret; /* Return value */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Opens the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+
+ /* Should succeed */
+ if(child_fid >= 0) {
+ /* Close the file */
+ child_ret = H5Fclose(child_fid);
+ CHECK(child_ret, FAIL, "H5Fclose");
+ exit(0);
+ }
+ exit(1);
+ }
+ /* Create file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of child process */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+#endif
+
+} /* end test_file_lock_concur() */
+
+/****************************************************************
+**
+** test_file_lock_swmr_concur(): low-level file test routine.
+** With the implementation of file locking, this test checks file
+** open with different combinations of flags + SWMR flags.
+** This is for concurrent access.
+**
+*****************************************************************/
+static void
+test_file_lock_swmr_concur(void)
+{
+ hid_t fid; /* File ID */
+ hid_t fapl; /* File access property list */
+ herr_t ret; /* Generic return value */
+ pid_t childpid=0; /* Child process ID */
+ pid_t tmppid; /* Child process ID returned by waitpid */
+ int child_status; /* Status passed to waitpid */
+ int child_wait_option=0; /* Options passed to waitpid */
+ int child_ret_value; /* Exit status of the child */
+
+ /* Output message about test being performed */
+ MESSAGE(5, ("Testing file open with different combintations of flags + SWMR flags--concurrent access\n"));
+
+#if !(defined(H5_HAVE_FORK) && defined(H5_HAVE_WAITPID))
+
+ SKIPPED();
+ HDputs(" Test skipped due to fork or waitpid not defined.");
+
+#else /* defined(H5_HAVE_FORK && defined(H5_HAVE_WAITPID) */
+
+ /* Create a file access property list */
+ fapl = H5Pcreate(H5P_FILE_ACCESS);
+ CHECK(fapl, FAIL, "H5Pcreate");
+
+ /* Set to use latest library format */
+ ret = H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST);
+ CHECK(ret, FAIL, "H5Pset_libver_bounds");
+
+ /* Create the test file */
+ fid = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 1: 1) RDWR 2) RDWR|SWMR_WRITE : should fail
+ */
+
+ /* Remove the message file to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Open the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+
+ /* Should fail */
+ if(child_fid == FAIL)
+ exit(0);
+ exit(1);
+ }
+
+ /* Open the test file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of child process */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 2: 1) RDWR 2) RDONLY|SWMR_READ: should fail
+ */
+
+ /* Remove the message file to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Open the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+
+ /* Should fail */
+ if(child_fid == FAIL)
+ exit(0);
+ exit(1);
+ }
+
+ /* Open the test file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of child process */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 3: 1) RDWR|SWMR_WRITE 2) RDWR : should fail
+ */
+
+ /* Remove the message file to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Open the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+
+ /* Should fail */
+ if(child_fid == FAIL)
+ exit(0);
+ exit(1);
+ }
+
+ /* Open the test file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of child process */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 4: 1) RDWR|SWMR_WRITE 2) RDWR|SWMR_WRITE : should fail
+ */
+
+ /* Remove the message file just to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Open the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+
+ /* Should fail */
+ if(child_fid == FAIL)
+ exit(0);
+ exit(1);
+ }
+
+ /* Open the test file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of child process */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 5: 1) RDWR|SWMR_WRITE 2) RDONLY|SWMR_READ : should succeed
+ */
+
+ /* Remove the message file just to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+ herr_t child_ret; /* Return value */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Open the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+
+ /* Should succeed */
+ if(child_fid >= 0) {
+ child_ret = H5Fclose(child_fid);
+ CHECK(child_ret, FAIL, "H5Fclose");
+ exit(0);
+ }
+ exit(1);
+ }
+
+ /* Open the test file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of child process */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 6: 1) RDWR|SWMR_WRITE 2) RDONLY : should fail
+ */
+
+ /* Remove the message file just to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Open the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+ /* Should fail */
+ if(child_fid == FAIL)
+ exit(0);
+ exit(1);
+ }
+
+ /* Open the test file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of child process */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 7: 1) RDONLY|SWMR_READ 2) RDWR : should fail
+ */
+
+ /* Remove the message file just to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Open the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+ /* Should fail */
+ if(child_fid == FAIL)
+ exit(0);
+ exit(1);
+ }
+
+ /* Open the test file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of child process */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 8: 1) RDONLY|SWMR_READ 2) RDWR|SWMR_WRITE : should fail
+ */
+
+ /* Remove the message file just to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Open the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+ /* Should fail */
+ if(child_fid == FAIL)
+ exit(0);
+ exit(1);
+ }
+
+ /* Open the test file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of child process */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+
+ /*
+ * Case 9: 1) RDONLY|SWMR_READ 2) RDONLY|SWMR_READ : should succeed
+ */
+
+ /* Remove the message file just to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+ herr_t child_ret; /* Return value */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Open the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+
+ /* Should succeed */
+ if(child_fid >= 0) {
+ child_ret = H5Fclose(child_fid);
+ CHECK(child_ret, FAIL, "H5Fclose");
+ exit(0);
+ }
+ exit(1);
+ }
+
+ /* Open the test file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of child process */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 10: 1) RDONLY|SWMR_READ 2) RDONLY : should succeed
+ */
+
+ /* Remove the message file just to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+ herr_t child_ret; /* Return value */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Open the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+
+ /* Should succeed */
+ if(child_fid >= 0) {
+ child_ret = H5Fclose(child_fid);
+ CHECK(child_ret, FAIL, "H5Fclose");
+ exit(0);
+ }
+ exit(1);
+ }
+
+ /* Open the test file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of child process */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+
+ /*
+ * Case 11: 1) RDONLY 2) RDWR|SWMR_WRITE : should fail
+ */
+
+ /* Remove the message file just to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Open the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl);
+ /* Should fail */
+ if(child_fid == FAIL)
+ exit(0);
+ exit(1);
+ }
+ /* Open the test file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of child process */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*
+ * Case 12: 1) RDONLY 2) RDONLY|SWMR_READ : should succeed
+ */
+
+ /* Remove the message file just to be sure */
+ HDremove(DONE_MESSAGE);
+
+ /* Fork child process */
+ childpid = HDfork();
+ CHECK(childpid, FAIL, "fork");
+
+ if(childpid == 0) { /* Child process */
+ hid_t child_fid; /* File ID */
+ herr_t child_ret; /* Return value */
+
+ /* Wait till parent process completes the open */
+ if(h5_wait_message(DONE_MESSAGE) < 0)
+ exit(1);
+
+ /* Open the test file */
+ child_fid = H5Fopen(FILE1, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl);
+
+ /* Should succeed */
+ if(child_fid >= 0) {
+ child_ret = H5Fclose(child_fid);
+ CHECK(child_ret, FAIL, "H5Fclose");
+ exit(0);
+ }
+ exit(1);
+ }
+
+ /* Open the test file */
+ fid = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Send the message that the open completes */
+ h5_send_message(DONE_MESSAGE);
+
+ /* Wait for child process to complete */
+ tmppid = HDwaitpid(childpid, &child_status, child_wait_option);
+ CHECK(tmppid, FAIL, "waitpid");
+
+ /* Check if child terminated normally */
+ ret = WIFEXITED(child_status);
+ CHECK(ret, FAIL, "child process terminated abnormally");
+
+ /* Check exit status of child process */
+ child_ret_value = WEXITSTATUS(child_status);
+ VERIFY(child_ret_value, 0, "child process exited with non-zero code");
+
+ /* Close the file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Close the property list */
+ ret=H5Pclose(fapl);
+ CHECK(ret, FAIL, "H5Pclose");
+#endif
+
+} /* end test_file_lock_swmr_concur() */
+/****************************************************************
+**
** test_deprec():
** Test deprecated functionality.
**
@@ -5223,10 +6372,16 @@ test_file(void)
test_libver_bounds(); /* Test compatibility for file space management */
test_libver_macros(); /* Test the macros for library version comparison */
test_libver_macros2(); /* Test the macros for library version comparison */
- test_swmr_write(); /* Tests for SWMR write access flag */
- test_swmr_read(); /* Tests for SWMR read access flag */
test_metadata_read_attempts(); /* Tests for public routines H5Fget/set_metadata_read_attempts() */
test_metadata_read_retry_info(); /* Tests for public routine H5Fget_metadata_read_retry_info() */
+ /*
+ * The two tests: test_swmr_write() and test_swmr_read() are removed.
+ * They are covered by the following new tests.
+ */
+ test_file_lock_same(); /* Tests for file open flags--single process access */
+ test_file_lock_swmr_same(); /* Tests for file open flags+SWMR flags--single process access */
+ test_file_lock_concur(); /* Tests for file open flags--concurrent access */
+ test_file_lock_swmr_concur(); /* Tests for file open flags+SWMR flags--concurrent access */
#ifndef H5_NO_DEPRECATED_SYMBOLS
test_deprec(); /* Test deprecated routines */
#endif /* H5_NO_DEPRECATED_SYMBOLS */
diff --git a/test/th5s.h5 b/test/th5s.h5
index 7a0bfb3..bc2b666 100644
--- a/test/th5s.h5
+++ b/test/th5s.h5
Binary files differ
diff --git a/test/tlayouto.h5 b/test/tlayouto.h5
index a038e68..3322020 100644
--- a/test/tlayouto.h5
+++ b/test/tlayouto.h5
Binary files differ
diff --git a/test/tmtimen.h5 b/test/tmtimen.h5
index 96e5fb3..007a6b6 100644
--- a/test/tmtimen.h5
+++ b/test/tmtimen.h5
Binary files differ
diff --git a/test/tmtimeo.h5 b/test/tmtimeo.h5
index 8cacf4a..c9dfcc4 100644
--- a/test/tmtimeo.h5
+++ b/test/tmtimeo.h5
Binary files differ
diff --git a/test/use.h b/test/use.h
index 2d7c36d..45b4a49 100644
--- a/test/use.h
+++ b/test/use.h
@@ -21,7 +21,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "hdf5.h"
+#include "h5test.h"
/* Macro definitions */
#define Hgoto_error(val) {ret_value=val; goto done;}
@@ -33,6 +33,9 @@
#define UC_CTYPE short /* use case C data type */
#define UC_RANK 3 /* use case dataset rank */
+/* Name of message file that is sent by the writer */
+#define WRITER_MESSAGE "USE_WRITER_MESSAGE"
+
/* type declarations */
typedef enum part_t {
UC_READWRITE =0, /* both writer and reader */
@@ -62,23 +65,5 @@ int setup_parameters(int argc, char * const argv[]);
void show_parameters(void);
void usage(const char *prog);
int create_uc_file(void);
-int write_uc_file(void);
-int read_uc_file(void);
-
-/* private definitions of Standard functions */
-
-/* Standard POSIX functions */
-#define HDassert(s) assert(s)
-#define HDfree(s) free(s)
-#define HDgetenv(s) getenv(s)
-#define HDmalloc(s) malloc(s)
-#define HDmemcpy(X,C,Z) memcpy(X,C,Z)
-#define HDmemset(X,C,Z) memset(X,C,Z)
-#define HDperror(s) perror(s)
-#define HDstrcat(s1, s2) strcat(s1, s2)
-#define HDstrcmp(s1, s2) strcmp(s1, s2)
-#define HDstrcpy(s1, s2) strcpy(s1, s2)
-#define HDstrdup(s) strdup(s)
-#define HDstrlen(s) strlen(s)
-#define HDstrncpy(s1, s2, N) strncpy(s1, s2, N)
-#define HDstrrchr(s, c) strrchr(s, c)
+int write_uc_file(hbool_t tosend);
+int read_uc_file(hbool_t towait);
diff --git a/test/use_append_chunk.c b/test/use_append_chunk.c
index 2ec645e..a3219c2 100644
--- a/test/use_append_chunk.c
+++ b/test/use_append_chunk.c
@@ -118,12 +118,19 @@ main(int argc, char *argv[])
int child_wait_option=0;
int ret_value = 0;
int child_ret_value;
+ hbool_t send_wait = 0;
/* initialization */
if (setup_parameters(argc, argv) < 0){
Hgoto_error(1);
}
+ /* Determine the need to send/wait message file*/
+ if(UC_opts.launch == UC_READWRITE) {
+ HDunlink(WRITER_MESSAGE);
+ send_wait = 1;
+ }
+
/* ==============================================================*/
/* UC_READWRITE: create datafile, launch both reader and writer. */
/* UC_WRITER: create datafile, skip reader, launch writer. */
@@ -157,7 +164,7 @@ main(int argc, char *argv[])
/* child process launch the reader */
if(0 == childpid) {
printf("%d: launch reader process\n", mypid);
- if (read_uc_file() < 0){
+ if (read_uc_file(send_wait) < 0){
fprintf(stderr, "read_uc_file encountered error\n");
exit(1);
}
@@ -170,7 +177,7 @@ main(int argc, char *argv[])
/* ============= */
/* this process continues to launch the writer */
printf("%d: continue as the writer process\n", mypid);
- if (write_uc_file() < 0){
+ if (write_uc_file(send_wait) < 0){
fprintf(stderr, "write_uc_file encountered error\n");
Hgoto_error(1);
}
diff --git a/test/use_append_mchunks.c b/test/use_append_mchunks.c
index 113f75d..b19fe57 100644
--- a/test/use_append_mchunks.c
+++ b/test/use_append_mchunks.c
@@ -111,12 +111,19 @@ main(int argc, char *argv[])
int child_wait_option=0;
int ret_value = 0;
int child_ret_value;
+ hbool_t send_wait = 0;
/* initialization */
if (setup_parameters(argc, argv) < 0){
Hgoto_error(1);
}
+ /* Determine the need to send/wait message file*/
+ if(UC_opts.launch == UC_READWRITE) {
+ HDunlink(WRITER_MESSAGE);
+ send_wait = 1;
+ }
+
/* ==============================================================*/
/* UC_READWRITE: create datafile, launch both reader and writer. */
/* UC_WRITER: create datafile, skip reader, launch writer. */
@@ -150,7 +157,7 @@ main(int argc, char *argv[])
/* child process launch the reader */
if(0 == childpid) {
printf("%d: launch reader process\n", mypid);
- if (read_uc_file() < 0){
+ if (read_uc_file(send_wait) < 0){
fprintf(stderr, "read_uc_file encountered error\n");
exit(1);
}
@@ -163,7 +170,7 @@ main(int argc, char *argv[])
/* ============= */
/* this process continues to launch the writer */
printf("%d: continue as the writer process\n", mypid);
- if (write_uc_file() < 0){
+ if (write_uc_file(send_wait) < 0){
fprintf(stderr, "write_uc_file encountered error\n");
Hgoto_error(1);
}
diff --git a/test/use_common.c b/test/use_common.c
index c25f1f4..639e468 100644
--- a/test/use_common.c
+++ b/test/use_common.c
@@ -241,7 +241,7 @@ int create_uc_file(void)
*
* Return: 0 succeed; -1 fail.
*/
-int write_uc_file(void)
+int write_uc_file(hbool_t tosend)
{
hid_t fid; /* File ID for new HDF5 file */
hid_t dsid; /* dataset ID */
@@ -272,6 +272,10 @@ int write_uc_file(void)
return -1;
}
+ if(tosend)
+ /* Send a message that H5Fopen is complete--releasing the file lock */
+ h5_send_message(WRITER_MESSAGE);
+
/* Open the dataset of the program name */
if((dsid = H5Dopen2(fid, progname_g, H5P_DEFAULT)) < 0){
fprintf(stderr, "H5Dopen2 failed\n");
@@ -424,7 +428,7 @@ int write_uc_file(void)
*
* Return: 0 succeed; -1 fail.
*/
-int read_uc_file(void)
+int read_uc_file(hbool_t towait)
{
hid_t fid; /* File ID for new HDF5 file */
hid_t dsid; /* dataset ID */
@@ -442,6 +446,12 @@ int read_uc_file(void)
int nerrs;
int nonewplane;
+ /* Before reading, wait for the message that H5Fopen is complete--file lock is released */
+ if(towait && h5_wait_message(WRITER_MESSAGE) < 0) {
+ fprintf(stderr, "Cannot find writer message file...failed\n");
+ return -1;
+ }
+
name = UC_opts.filename;
/* Open the file */
diff --git a/tools/h5diff/testfiles/h5diff_hyper1.h5 b/tools/h5diff/testfiles/h5diff_hyper1.h5
index ceeff80..1fd47e1 100644
--- a/tools/h5diff/testfiles/h5diff_hyper1.h5
+++ b/tools/h5diff/testfiles/h5diff_hyper1.h5
Binary files differ
diff --git a/tools/h5diff/testfiles/h5diff_hyper2.h5 b/tools/h5diff/testfiles/h5diff_hyper2.h5
index 05a2eb1..ad2f468 100644
--- a/tools/h5diff/testfiles/h5diff_hyper2.h5
+++ b/tools/h5diff/testfiles/h5diff_hyper2.h5
Binary files differ
diff --git a/tools/h5import/testfiles/binfp64.h5 b/tools/h5import/testfiles/binfp64.h5
index 80e3a8a..5426edb 100644
--- a/tools/h5import/testfiles/binfp64.h5
+++ b/tools/h5import/testfiles/binfp64.h5
Binary files differ
diff --git a/tools/h5import/testfiles/binin16.h5 b/tools/h5import/testfiles/binin16.h5
index 0825bbc..6d89c63 100644
--- a/tools/h5import/testfiles/binin16.h5
+++ b/tools/h5import/testfiles/binin16.h5
Binary files differ
diff --git a/tools/h5import/testfiles/binin32.h5 b/tools/h5import/testfiles/binin32.h5
index fd8faa9..61cc507 100644
--- a/tools/h5import/testfiles/binin32.h5
+++ b/tools/h5import/testfiles/binin32.h5
Binary files differ
diff --git a/tools/h5import/testfiles/binin8.h5 b/tools/h5import/testfiles/binin8.h5
index a1d1a37..efd3ae0 100644
--- a/tools/h5import/testfiles/binin8.h5
+++ b/tools/h5import/testfiles/binin8.h5
Binary files differ
diff --git a/tools/h5import/testfiles/binuin16.h5 b/tools/h5import/testfiles/binuin16.h5
index c486c89..1af804c 100644
--- a/tools/h5import/testfiles/binuin16.h5
+++ b/tools/h5import/testfiles/binuin16.h5
Binary files differ
diff --git a/tools/h5import/testfiles/binuin32.h5 b/tools/h5import/testfiles/binuin32.h5
index 41699d7..e7d12d9 100644
--- a/tools/h5import/testfiles/binuin32.h5
+++ b/tools/h5import/testfiles/binuin32.h5
Binary files differ
diff --git a/tools/h5import/testfiles/txtfp32.h5 b/tools/h5import/testfiles/txtfp32.h5
index f74e003..bd41f06 100644
--- a/tools/h5import/testfiles/txtfp32.h5
+++ b/tools/h5import/testfiles/txtfp32.h5
Binary files differ
diff --git a/tools/h5import/testfiles/txtfp64.h5 b/tools/h5import/testfiles/txtfp64.h5
index b6ba4f5..41c4e9e 100644
--- a/tools/h5import/testfiles/txtfp64.h5
+++ b/tools/h5import/testfiles/txtfp64.h5
Binary files differ
diff --git a/tools/h5import/testfiles/txtin16.h5 b/tools/h5import/testfiles/txtin16.h5
index dc6c1ea..5089c97 100644
--- a/tools/h5import/testfiles/txtin16.h5
+++ b/tools/h5import/testfiles/txtin16.h5
Binary files differ
diff --git a/tools/h5import/testfiles/txtin32.h5 b/tools/h5import/testfiles/txtin32.h5
index 350333c..8d547cf 100644
--- a/tools/h5import/testfiles/txtin32.h5
+++ b/tools/h5import/testfiles/txtin32.h5
Binary files differ
diff --git a/tools/h5import/testfiles/txtin8.h5 b/tools/h5import/testfiles/txtin8.h5
index 42e7727..61b7165 100644
--- a/tools/h5import/testfiles/txtin8.h5
+++ b/tools/h5import/testfiles/txtin8.h5
Binary files differ
diff --git a/tools/h5import/testfiles/txtuin16.h5 b/tools/h5import/testfiles/txtuin16.h5
index 9ee166a..c43b875 100644
--- a/tools/h5import/testfiles/txtuin16.h5
+++ b/tools/h5import/testfiles/txtuin16.h5
Binary files differ
diff --git a/tools/h5import/testfiles/txtuin32.h5 b/tools/h5import/testfiles/txtuin32.h5
index 1a4dda5..aec3b0f 100644
--- a/tools/h5import/testfiles/txtuin32.h5
+++ b/tools/h5import/testfiles/txtuin32.h5
Binary files differ
diff --git a/tools/h5repack/testfiles/h5repack_attr.h5 b/tools/h5repack/testfiles/h5repack_attr.h5
index fe066db..3bc4906 100644
--- a/tools/h5repack/testfiles/h5repack_attr.h5
+++ b/tools/h5repack/testfiles/h5repack_attr.h5
Binary files differ
diff --git a/tools/h5repack/testfiles/h5repack_deflate.h5 b/tools/h5repack/testfiles/h5repack_deflate.h5
index 3a4b86d..86d66c0 100644
--- a/tools/h5repack/testfiles/h5repack_deflate.h5
+++ b/tools/h5repack/testfiles/h5repack_deflate.h5
Binary files differ
diff --git a/tools/h5repack/testfiles/h5repack_early.h5 b/tools/h5repack/testfiles/h5repack_early.h5
index 9b92890..0394bef 100644
--- a/tools/h5repack/testfiles/h5repack_early.h5
+++ b/tools/h5repack/testfiles/h5repack_early.h5
Binary files differ
diff --git a/tools/h5repack/testfiles/h5repack_fill.h5 b/tools/h5repack/testfiles/h5repack_fill.h5
index 21516cb..81c32d5 100644
--- a/tools/h5repack/testfiles/h5repack_fill.h5
+++ b/tools/h5repack/testfiles/h5repack_fill.h5
Binary files differ
diff --git a/tools/h5repack/testfiles/h5repack_filters.h5 b/tools/h5repack/testfiles/h5repack_filters.h5
index 042b8db..0600adb 100644
--- a/tools/h5repack/testfiles/h5repack_filters.h5
+++ b/tools/h5repack/testfiles/h5repack_filters.h5
Binary files differ
diff --git a/tools/h5repack/testfiles/h5repack_fletcher.h5 b/tools/h5repack/testfiles/h5repack_fletcher.h5
index 2f137b0..e4e2c05 100644
--- a/tools/h5repack/testfiles/h5repack_fletcher.h5
+++ b/tools/h5repack/testfiles/h5repack_fletcher.h5
Binary files differ
diff --git a/tools/h5repack/testfiles/h5repack_hlink.h5 b/tools/h5repack/testfiles/h5repack_hlink.h5
index 3d22728..b00f9a2 100644
--- a/tools/h5repack/testfiles/h5repack_hlink.h5
+++ b/tools/h5repack/testfiles/h5repack_hlink.h5
Binary files differ
diff --git a/tools/h5repack/testfiles/h5repack_layouto.h5 b/tools/h5repack/testfiles/h5repack_layouto.h5
index a038e68..3322020 100644
--- a/tools/h5repack/testfiles/h5repack_layouto.h5
+++ b/tools/h5repack/testfiles/h5repack_layouto.h5
Binary files differ
diff --git a/tools/h5repack/testfiles/h5repack_nbit.h5 b/tools/h5repack/testfiles/h5repack_nbit.h5
index 3ada112..c678f1c 100644
--- a/tools/h5repack/testfiles/h5repack_nbit.h5
+++ b/tools/h5repack/testfiles/h5repack_nbit.h5
Binary files differ
diff --git a/tools/h5repack/testfiles/h5repack_shuffle.h5 b/tools/h5repack/testfiles/h5repack_shuffle.h5
index d13cca7..6520193 100644
--- a/tools/h5repack/testfiles/h5repack_shuffle.h5
+++ b/tools/h5repack/testfiles/h5repack_shuffle.h5
Binary files differ
diff --git a/tools/h5repack/testfiles/h5repack_soffset.h5 b/tools/h5repack/testfiles/h5repack_soffset.h5
index 89ee99a..a9457d3 100644
--- a/tools/h5repack/testfiles/h5repack_soffset.h5
+++ b/tools/h5repack/testfiles/h5repack_soffset.h5
Binary files differ
diff --git a/tools/h5stat/testfiles/h5stat_filters.h5 b/tools/h5stat/testfiles/h5stat_filters.h5
index 5b5f4bb..cbd4467 100644
--- a/tools/h5stat/testfiles/h5stat_filters.h5
+++ b/tools/h5stat/testfiles/h5stat_filters.h5
Binary files differ
diff --git a/tools/misc/Makefile.am b/tools/misc/Makefile.am
index 0055f39..11e830e 100644
--- a/tools/misc/Makefile.am
+++ b/tools/misc/Makefile.am
@@ -24,21 +24,24 @@ include $(top_srcdir)/config/commence.am
INCLUDES=-I$(top_srcdir)/src -I$(top_srcdir)/tools/lib
#test script and program
-TEST_PROG=h5repart_gentest talign
-TEST_SCRIPT=testh5repart.sh testh5mkgrp.sh
+TEST_PROG=h5repart_gentest talign h5clear_gentest
+TEST_SCRIPT=testh5repart.sh testh5mkgrp.sh testh5clear.sh
-check_PROGRAMS=$(TEST_PROG) repart_test
+
+check_PROGRAMS=$(TEST_PROG) repart_test clear_open_chk
check_SCRIPTS=$(TEST_SCRIPT)
-SCRIPT_DEPEND=h5repart$(EXEEXT) h5mkgrp$(EXEEXT)
+SCRIPT_DEPEND=h5repart$(EXEEXT) h5mkgrp$(EXEEXT) h5clear$(EXEEXT)
+
# These are our main targets, the tools
-bin_PROGRAMS=h5debug h5repart h5mkgrp
+bin_PROGRAMS=h5debug h5repart h5mkgrp h5clear
bin_SCRIPTS=h5redeploy
# Add h5debug, h5repart, and h5mkgrp specific linker flags here
h5debug_LDFLAGS = $(LT_STATIC_EXEC) $(AM_LDFLAGS)
h5repart_LDFLAGS = $(LT_STATIC_EXEC) $(AM_LDFLAGS)
h5mkgrp_LDFLAGS = $(LT_STATIC_EXEC) $(AM_LDFLAGS)
+h5clear_LDFLAGS = $(LT_STATIC_EXEC) $(AM_LDFLAGS)
# Tell automake to clean h5redeploy script
CLEANFILES=h5redeploy
@@ -49,7 +52,7 @@ CLEANFILES=h5redeploy
CHECK_CLEANFILES+=*.h5 ../testfiles/fst_family*.h5 ../testfiles/scd_family*.h5
# These were generated by configure. Remove them only when distclean.
-DISTCLEANFILES=h5cc testh5repart.sh
+DISTCLEANFILES=h5cc testh5repart.sh testh5clear.sh
# All programs rely on hdf5 library and h5tools library
LDADD=$(LIBH5TOOLS) $(LIBHDF5)
diff --git a/tools/misc/Makefile.in b/tools/misc/Makefile.in
index 47bf60d..fad0215 100644
--- a/tools/misc/Makefile.in
+++ b/tools/misc/Makefile.in
@@ -69,13 +69,15 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
- $(srcdir)/h5cc.in $(srcdir)/testh5mkgrp.sh.in \
- $(srcdir)/testh5repart.sh.in $(top_srcdir)/bin/depcomp \
- $(top_srcdir)/bin/mkinstalldirs \
+ $(srcdir)/h5cc.in $(srcdir)/testh5clear.sh.in \
+ $(srcdir)/testh5mkgrp.sh.in $(srcdir)/testh5repart.sh.in \
+ $(top_srcdir)/bin/depcomp $(top_srcdir)/bin/mkinstalldirs \
$(top_srcdir)/config/commence.am \
$(top_srcdir)/config/conclude.am
-check_PROGRAMS = $(am__EXEEXT_1) repart_test$(EXEEXT)
-bin_PROGRAMS = h5debug$(EXEEXT) h5repart$(EXEEXT) h5mkgrp$(EXEEXT)
+check_PROGRAMS = $(am__EXEEXT_1) repart_test$(EXEEXT) \
+ clear_open_chk$(EXEEXT)
+bin_PROGRAMS = h5debug$(EXEEXT) h5repart$(EXEEXT) h5mkgrp$(EXEEXT) \
+ h5clear$(EXEEXT)
TESTS = $(am__EXEEXT_1) $(TEST_SCRIPT)
subdir = tools/misc
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -84,19 +86,36 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(SHELL) $(top_srcdir)/bin/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/src/H5config.h
-CONFIG_CLEAN_FILES = h5cc testh5mkgrp.sh testh5repart.sh
+CONFIG_CLEAN_FILES = h5cc testh5clear.sh testh5mkgrp.sh \
+ testh5repart.sh
CONFIG_CLEAN_VPATH_FILES =
am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)"
-am__EXEEXT_1 = h5repart_gentest$(EXEEXT) talign$(EXEEXT)
+am__EXEEXT_1 = h5repart_gentest$(EXEEXT) talign$(EXEEXT) \
+ h5clear_gentest$(EXEEXT)
PROGRAMS = $(bin_PROGRAMS)
-h5debug_SOURCES = h5debug.c
-h5debug_OBJECTS = h5debug.$(OBJEXT)
-h5debug_LDADD = $(LDADD)
-h5debug_DEPENDENCIES = $(LIBH5TOOLS) $(LIBHDF5)
+clear_open_chk_SOURCES = clear_open_chk.c
+clear_open_chk_OBJECTS = clear_open_chk.$(OBJEXT)
+clear_open_chk_LDADD = $(LDADD)
+clear_open_chk_DEPENDENCIES = $(LIBH5TOOLS) $(LIBHDF5)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
am__v_lt_1 =
+h5clear_SOURCES = h5clear.c
+h5clear_OBJECTS = h5clear.$(OBJEXT)
+h5clear_LDADD = $(LDADD)
+h5clear_DEPENDENCIES = $(LIBH5TOOLS) $(LIBHDF5)
+h5clear_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(h5clear_LDFLAGS) $(LDFLAGS) -o $@
+h5clear_gentest_SOURCES = h5clear_gentest.c
+h5clear_gentest_OBJECTS = h5clear_gentest.$(OBJEXT)
+h5clear_gentest_LDADD = $(LDADD)
+h5clear_gentest_DEPENDENCIES = $(LIBH5TOOLS) $(LIBHDF5)
+h5debug_SOURCES = h5debug.c
+h5debug_OBJECTS = h5debug.$(OBJEXT)
+h5debug_LDADD = $(LDADD)
+h5debug_DEPENDENCIES = $(LIBH5TOOLS) $(LIBHDF5)
h5debug_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(h5debug_LDFLAGS) $(LDFLAGS) -o $@
@@ -188,10 +207,10 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
-SOURCES = h5debug.c h5mkgrp.c h5repart.c h5repart_gentest.c \
- repart_test.c talign.c
-DIST_SOURCES = h5debug.c h5mkgrp.c h5repart.c h5repart_gentest.c \
- repart_test.c talign.c
+SOURCES = clear_open_chk.c h5clear.c h5clear_gentest.c h5debug.c \
+ h5mkgrp.c h5repart.c h5repart_gentest.c repart_test.c talign.c
+DIST_SOURCES = clear_open_chk.c h5clear.c h5clear_gentest.c h5debug.c \
+ h5mkgrp.c h5repart.c h5repart_gentest.c repart_test.c talign.c
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@@ -493,22 +512,23 @@ CHECK_CLEANFILES = *.chkexe *.chklog *.clog *.h5 \
INCLUDES = -I$(top_srcdir)/src -I$(top_srcdir)/tools/lib
#test script and program
-TEST_PROG = h5repart_gentest talign
-TEST_SCRIPT = testh5repart.sh testh5mkgrp.sh
+TEST_PROG = h5repart_gentest talign h5clear_gentest
+TEST_SCRIPT = testh5repart.sh testh5mkgrp.sh testh5clear.sh
check_SCRIPTS = $(TEST_SCRIPT)
-SCRIPT_DEPEND = h5repart$(EXEEXT) h5mkgrp$(EXEEXT)
+SCRIPT_DEPEND = h5repart$(EXEEXT) h5mkgrp$(EXEEXT) h5clear$(EXEEXT)
bin_SCRIPTS = h5redeploy
# Add h5debug, h5repart, and h5mkgrp specific linker flags here
h5debug_LDFLAGS = $(LT_STATIC_EXEC) $(AM_LDFLAGS)
h5repart_LDFLAGS = $(LT_STATIC_EXEC) $(AM_LDFLAGS)
h5mkgrp_LDFLAGS = $(LT_STATIC_EXEC) $(AM_LDFLAGS)
+h5clear_LDFLAGS = $(LT_STATIC_EXEC) $(AM_LDFLAGS)
# Tell automake to clean h5redeploy script
CLEANFILES = h5redeploy
# These were generated by configure. Remove them only when distclean.
-DISTCLEANFILES = h5cc testh5repart.sh
+DISTCLEANFILES = h5cc testh5repart.sh testh5clear.sh
# All programs rely on hdf5 library and h5tools library
LDADD = $(LIBH5TOOLS) $(LIBHDF5)
@@ -574,6 +594,8 @@ $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
$(am__aclocal_m4_deps):
h5cc: $(top_builddir)/config.status $(srcdir)/h5cc.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+testh5clear.sh: $(top_builddir)/config.status $(srcdir)/testh5clear.sh.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
testh5mkgrp.sh: $(top_builddir)/config.status $(srcdir)/testh5mkgrp.sh.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
testh5repart.sh: $(top_builddir)/config.status $(srcdir)/testh5repart.sh.in
@@ -633,6 +655,15 @@ clean-checkPROGRAMS:
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
echo " rm -f" $$list; \
rm -f $$list
+clear_open_chk$(EXEEXT): $(clear_open_chk_OBJECTS) $(clear_open_chk_DEPENDENCIES) $(EXTRA_clear_open_chk_DEPENDENCIES)
+ @rm -f clear_open_chk$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(clear_open_chk_OBJECTS) $(clear_open_chk_LDADD) $(LIBS)
+h5clear$(EXEEXT): $(h5clear_OBJECTS) $(h5clear_DEPENDENCIES) $(EXTRA_h5clear_DEPENDENCIES)
+ @rm -f h5clear$(EXEEXT)
+ $(AM_V_CCLD)$(h5clear_LINK) $(h5clear_OBJECTS) $(h5clear_LDADD) $(LIBS)
+h5clear_gentest$(EXEEXT): $(h5clear_gentest_OBJECTS) $(h5clear_gentest_DEPENDENCIES) $(EXTRA_h5clear_gentest_DEPENDENCIES)
+ @rm -f h5clear_gentest$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(h5clear_gentest_OBJECTS) $(h5clear_gentest_LDADD) $(LIBS)
h5debug$(EXEEXT): $(h5debug_OBJECTS) $(h5debug_DEPENDENCIES) $(EXTRA_h5debug_DEPENDENCIES)
@rm -f h5debug$(EXEEXT)
$(AM_V_CCLD)$(h5debug_LINK) $(h5debug_OBJECTS) $(h5debug_LDADD) $(LIBS)
@@ -693,6 +724,9 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clear_open_chk.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/h5clear.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/h5clear_gentest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/h5debug.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/h5mkgrp.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/h5repart.Po@am__quote@
diff --git a/tools/misc/clear_open_chk.c b/tools/misc/clear_open_chk.c
new file mode 100644
index 0000000..3a299ec
--- /dev/null
+++ b/tools/misc/clear_open_chk.c
@@ -0,0 +1,72 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+#include "hdf5.h"
+#include "H5private.h"
+#include "h5tools.h"
+
+static void usage(void);
+
+static void
+usage(void)
+{
+ HDfprintf(stdout, "\n");
+ HDfprintf(stdout, "Usage error!\n");
+ HDfprintf(stdout, "Usage: clear_open_chk filename\n");
+} /* usage() */
+
+/*-------------------------------------------------------------------------
+ * Function: main
+ *
+ * Purpose: To open the file which has zero or nonzero status_flags in
+ * the superblock.
+ *
+ * Return: 0 on success
+ * 1 on failure
+ *
+ * Programmer: Vailin Choi; July 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+main(int argc, char *argv[])
+{
+ char *fname; /* The HDF5 file name */
+ hid_t fid; /* File ID */
+
+ /* Check the # of arguments */
+ if(argc != 2) {
+ usage();
+ return(EXIT_FAILURE);
+ }
+
+ /* Get the file name */
+ fname = HDstrdup(argv[1]);
+
+ /* Try opening the file */
+ if((fid = h5tools_fopen(fname, H5F_ACC_RDWR, H5P_DEFAULT, NULL, NULL, (size_t)0)) < 0) {
+ HDfprintf(stdout, "\nclear_open_chk: cannot open the file\n");
+ return EXIT_FAILURE;
+ }
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0) {
+ HDfprintf(stdout, "\nclear_open_chk: cannot close the file\n");
+ return EXIT_FAILURE;
+ }
+
+ /* Return success */
+ return EXIT_SUCCESS;
+
+} /* main() */
diff --git a/tools/misc/h5clear.c b/tools/misc/h5clear.c
new file mode 100644
index 0000000..0be4f8f
--- /dev/null
+++ b/tools/misc/h5clear.c
@@ -0,0 +1,137 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Programmer:
+ *
+ * Purpose:
+ */
+
+#include "hdf5.h"
+#include "H5private.h"
+#include "h5tools.h"
+#include "h5tools_utils.h"
+
+/* Name of tool */
+#define PROGRAMNAME "h5clear"
+
+/* Make this private property (defined in H5Fprivate.h) available to h5clear. */
+#define H5F_ACS_CLEAR_STATUS_FLAGS_NAME "clear_status_flags"
+
+/*-------------------------------------------------------------------------
+ * Function: leave
+ *
+ * Purpose: Close the tools library and exit
+ *
+ * Return: Does not return
+ *
+ *-------------------------------------------------------------------------
+ */
+static void
+leave(int ret)
+{
+ h5tools_close();
+ HDexit(ret);
+
+} /* leave() */
+
+/*-------------------------------------------------------------------------
+ * Function: usage
+ *
+ * Purpose: Prints a usage message
+ *
+ * Return: void
+ *
+ *-------------------------------------------------------------------------
+ */
+static void
+usage(void)
+{
+ HDfprintf(stdout, "usage: h5clear filename\n");
+
+} /* usage() */
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: main
+ *
+ * Purpose:
+ *
+ * Return: Success:
+ * Failure:
+ *
+ * Programmer:
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+main (int argc, char *argv[])
+{
+ char *fname; /* File name */
+ hbool_t clear = TRUE; /* To clear the status_flags in the file's superblock */
+ hid_t fapl = -1; /* File access property list */
+ hid_t fid = -1; /* File ID */
+
+ h5tools_setprogname(PROGRAMNAME);
+ h5tools_setstatus(EXIT_SUCCESS);
+
+ /* Disable the HDF5 library's error reporting */
+ H5Eset_auto2(H5E_DEFAULT, NULL, NULL);
+
+ /* initialize h5tools lib */
+ h5tools_init();
+
+ /* Check for the # of arguments */
+ if(argc != 2) {
+ usage();
+ leave(EXIT_FAILURE);
+ }
+
+ /* Duplicate the file name */
+ fname = HDstrdup(argv[opt_ind]);
+
+ /* Get a copy of the file access property list */
+ if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0) {
+ error_msg("H5Pcreate\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Set to clear the status_flags in the file's superblock */
+ /* This is a private property used by h5clear only */
+ if(H5Pset(fapl, H5F_ACS_CLEAR_STATUS_FLAGS_NAME, &clear) < 0) {
+ error_msg("H5Pset\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if((fid = h5tools_fopen(fname, H5F_ACC_RDWR, fapl, NULL, NULL, (size_t)0)) < 0) {
+ error_msg("h5tools_fopen\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0) {
+ error_msg("H5Fclose\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* CLose the property list */
+ if(H5Pclose(fapl) < 0) {
+ error_msg("H5Pclose\n");
+ exit(EXIT_FAILURE);
+ }
+
+ return EXIT_SUCCESS;
+} /* main() */
diff --git a/tools/misc/h5clear_gentest.c b/tools/misc/h5clear_gentest.c
new file mode 100644
index 0000000..ae057e5
--- /dev/null
+++ b/tools/misc/h5clear_gentest.c
@@ -0,0 +1,238 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+#include "hdf5.h"
+#include "H5private.h"
+
+/* The HDF5 test files */
+const char *FILENAME[] = {
+ "h5clear_sec2.h5", /* 0 -- sec2 file */
+ "h5clear_core.h5", /* 1 -- core file */
+ "h5clear_fam_%05d.h5", /* 2 -- family files */
+ "h5clear_split", /* 3 -- split files */
+ "h5clear_invalid.h5" /* 4 -- sec2 file with invalid superblock version */
+};
+
+#define FAMILY_SIZE 1024U
+#define CORE_INCREMENT 1024U
+
+#define SUPER_VERS_OFF 8
+#define SUPER_VERS_SIZE 1
+#define SUPER_VERS_LATEST 2
+
+/*-------------------------------------------------------------------------
+ * Function: main
+ *
+ * Purpose: To create HDF5 files with non-zero status_flags in the superblock
+ * via flushing and exiting without closing the library.
+ *
+ * Due to file locking, status_flag in the superblock will be
+ * nonzero after H5Fcreate. The library will clear status_flags
+ * on file closing. This program, after "H5Fcreate" the files,
+ * exits without going through library closing. Thus, status_flags
+ * for these files are not cleared and users cannot open them.
+ *
+ * These files are used by "h5clear" to see if the tool clears
+ * status_flags properly so users can open the files afterwards.
+ *
+ * Return: Success: 0
+ * Failure: 1
+ *
+ * Programmer: Vailin Choi; July 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+main(void)
+{
+ hid_t fid; /* File ID */
+ hid_t fapl, new_fapl; /* File access property lists */
+ char fname[512]; /* File name */
+ hbool_t new_format; /* To use latest library format or not */
+ int fd; /* File descriptor */
+ uint8_t super_vers; /* Superblock version */
+ ssize_t bytes_written; /* The # of bytes written to the file */
+
+ /* Create a copy of the file access property list */
+ if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0)
+ goto error;
+
+ /* Copy the file access property list */
+ if((new_fapl = H5Pcopy(fapl)) < 0)
+ goto error;
+ /* Set to latest library format */
+ if(H5Pset_libver_bounds(new_fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
+ goto error;
+
+ /* Create file with/without latest library format */
+ for(new_format = FALSE; new_format <= TRUE; new_format++) {
+ hid_t fapl2, my_fapl; /* File access property lists */
+
+ /* Set to use the appropriate file access property list */
+ if(new_format)
+ fapl2 = new_fapl;
+ else
+ fapl2 = fapl;
+ /*
+ * Create a sec2 file
+ */
+ if((my_fapl = H5Pcopy(fapl2)) < 0)
+ goto error;
+ /* Create the file */
+ sprintf(fname, "%s%s", new_format? "latest_":"", FILENAME[0]);
+ if((fid = H5Fcreate(fname, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0)
+ goto error;
+
+ /* Flush the file */
+ if(H5Fflush(fid, H5F_SCOPE_GLOBAL) < 0)
+ goto error;
+
+ /* Close the property list */
+ if(H5Pclose(my_fapl) < 0)
+ goto error;
+
+ /*
+ * Create a core file
+ */
+ /* Create a copy of file access property list */
+ if((my_fapl = H5Pcopy(fapl2)) < 0)
+ goto error;
+
+ /* Setup the fapl for the family file driver */
+ if(H5Pset_fapl_core(my_fapl, (size_t)CORE_INCREMENT, TRUE) < 0)
+ goto error;
+
+ /* Create the file */
+ sprintf(fname, "%s%s", new_format? "latest_":"", FILENAME[1]);
+ if((fid = H5Fcreate(fname, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0)
+ goto error;
+
+ /* Flush the file */
+ if(H5Fflush(fid, H5F_SCOPE_GLOBAL) < 0)
+ goto error;
+
+ /* Close the property list */
+ if(H5Pclose(my_fapl) < 0)
+ goto error;
+
+ /*
+ * Create a family file
+ */
+ /* Create a copy of file access property list */
+ if((my_fapl = H5Pcopy(fapl2)) < 0)
+ goto error;
+
+ /* Setup the fapl for the family file driver */
+ if(H5Pset_fapl_family(my_fapl, (hsize_t)FAMILY_SIZE, H5P_DEFAULT) < 0)
+ goto error;
+
+ /* Create the file */
+ sprintf(fname, "%s%s", new_format? "latest_":"", FILENAME[2]);
+ if((fid = H5Fcreate(fname, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0)
+ goto error;
+
+ /* Flush the file */
+ if(H5Fflush(fid, H5F_SCOPE_GLOBAL) < 0)
+ goto error;
+
+ /* Close the property list */
+ if(H5Pclose(my_fapl) < 0)
+ goto error;
+
+ /*
+ * Create a split file
+ */
+ /* Create a copy of file access property list */
+ my_fapl = H5Pcopy(fapl2);
+
+ /* Setup the fapl for the split file driver */
+ H5Pset_fapl_split(my_fapl, "-m.h5", H5P_DEFAULT, "-r.h5", H5P_DEFAULT);
+
+ /* Create the file */
+ sprintf(fname, "%s%s", new_format? "latest_":"", FILENAME[3]);
+ if((fid = H5Fcreate(fname, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0)
+ goto error;
+
+ /* Flush the file */
+ if(H5Fflush(fid, H5F_SCOPE_GLOBAL) < 0)
+ goto error;
+
+ /* Close the property list */
+ if(H5Pclose(my_fapl) < 0)
+ goto error;
+
+ /*
+ * Create a sec2 file but change its superblock version #
+ */
+ /* Create a copy of file access property list */
+ if((my_fapl = H5Pcopy(fapl2)) < 0)
+ goto error;
+ /* Create the file */
+ sprintf(fname, "%s%s", new_format? "latest_":"", FILENAME[4]);
+ if((fid = H5Fcreate(fname, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0)
+ goto error;
+
+ /* Flush the file */
+ if(H5Fflush(fid, H5F_SCOPE_GLOBAL) < 0)
+ goto error;
+
+ /* Close the property list */
+ if(H5Pclose(my_fapl) < 0)
+ goto error;
+
+ /* Open the test file via system call "open" */
+ if((fd = HDopen(fname, O_RDWR, 0666)) < 0) {
+ HDfprintf(stdout, "cannot open the file\n");
+ goto error;
+ }
+
+ /* Position the file to superblock version via system call "lseek" */
+ if(HDlseek(fd, (off_t)SUPER_VERS_OFF, SEEK_SET) < 0) {
+ HDfprintf(stdout, "cannot lseek the file superblock version\n");
+ goto error;
+ }
+
+ /* Change to an incorrect superblock version */
+ super_vers = SUPER_VERS_LATEST + 1;
+ /* Write to the file via system call "write" */
+ if((bytes_written = HDwrite(fd, &super_vers, (size_t)SUPER_VERS_SIZE)) < 0) {
+ HDfprintf(stdout, "cannot write to the file with incorrect superblock version\n");
+ goto error;
+ }
+
+ /* Close the file via system call "close" */
+ if(HDclose(fd) < 0) {
+ HDfprintf(stdout, "cannot close the file\n");
+ goto error;
+ }
+
+ } /* end for */
+
+ /* Close the property lists */
+ if(H5Pclose(fapl) < 0)
+ goto error;
+ if(H5Pclose(new_fapl) < 0)
+ goto error;
+
+ fflush(stdout);
+ fflush(stderr);
+
+ /* Not going through library closing by calling _exit(0) with success */
+ HD_exit(0);
+
+error:
+
+ /* Exit with failure */
+ HD_exit(1);
+}
diff --git a/tools/misc/testh5clear.sh.in b/tools/misc/testh5clear.sh.in
new file mode 100644
index 0000000..8c98fed
--- /dev/null
+++ b/tools/misc/testh5clear.sh.in
@@ -0,0 +1,135 @@
+#! /bin/sh
+#
+# 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.
+#
+# Tests for the h5clear tool
+#
+srcdir=@srcdir@
+TESTNAME=h5clear
+EXIT_SUCCESS=0
+EXIT_FAILURE=1
+
+H5CLEAR=h5clear
+H5CLEAR_BIN=`pwd`/$H5CLEAR # The path of the tool binary
+
+GENTEST=h5clear_gentest # Generate test files
+GENTEST_BIN=`pwd`/$GENTEST # The path to the binary
+
+OPENCHK=clear_open_chk # Try opening the test file
+OPENCHK_BIN=`pwd`/$OPENCHK # The path to the binary
+
+SUCCEED=0
+FAIL=1
+
+nerrors=0
+verbose=yes
+
+test -d ../testfiles || mkdir ../testfiles
+
+# Print a line-line message left justified in a field of 70 characters
+# beginning with the word "Testing".
+#
+TESTING() {
+ SPACES=" "
+ echo "Testing $* $SPACES" | cut -c1-70 | tr -d '\012'
+}
+
+# Algorithm:
+# Try to open the test file--should fail
+# Use "h5clear" to clear the status_flags in the test file
+# Try to open the test file again--should succeed
+# $1 is the filename to H5Fopen() via h5clear
+TOOLTEST() {
+ TESTING $H5CLEAR $1
+ fname=$1
+ #
+ # Try to open the test file
+ $OPENCHK_BIN $fname
+ if test $? -eq $SUCCEED; then
+ echo ".....$OPENCHK: should fail"
+ nerrors=`expr $nerrors + 1`
+ else
+ # Run h5clear to clear the status_flags in the test file
+ $RUNSERIAL $H5CLEAR_BIN $fname
+ if test $? -ne $SUCCEED; then
+ echo ".....$H5CLEAR: should succeed"
+ nerrors=`expr $nerrors + 1`
+ else
+ # Try to open the test file again
+ $OPENCHK_BIN $fname
+ if test $? -ne $SUCCEED; then
+ echo "......$OPENCHK: should succeed"
+ nerrors=`expr $nerrors + 1`
+ else
+ echo "PASSED"
+ fi
+ fi
+ fi
+}
+
+# The input file has an incorrect superblock version #
+# Algorithm:
+# Use "h5clear" to clear status_flags in the test file--should fail not able to open the file
+# $1 is the filename to H5Fopen() via h5clear
+TOOLFAIL() {
+ TESTING $H5CLEAR $1
+ fname=$1
+ # Run h5clear to clear the status_flags in the test file
+ $RUNSERIAL $H5CLEAR_BIN $fname
+ if test $? -eq $SUCCEED; then
+ echo ".....$H5CLEAR: should fail"
+ nerrors=`expr $nerrors + 1`
+ else
+ echo "PASSED"
+ fi
+}
+##############################################################################
+##############################################################################
+### T H E T E S T S ###
+##############################################################################
+##############################################################################
+#
+$GENTEST_BIN # Create HDF5 test files
+if test $? -ne 0; then # Error returned from generating test files
+ echo "$GENTEST: .....fail in generating test files"
+ nerrors=`expr $nerrors + 1`
+else
+ TOOLTEST h5clear_sec2.h5
+ TOOLTEST h5clear_core.h5
+ TOOLTEST h5clear_fam_%05d.h5
+ TOOLTEST h5clear_split
+#
+# files created with latest library format
+ TOOLTEST latest_h5clear_sec2.h5
+ TOOLTEST latest_h5clear_core.h5
+ TOOLTEST latest_h5clear_fam_%05d.h5
+ TOOLTEST latest_h5clear_split
+#
+# files created with incorrect superblock version #
+TOOLFAIL h5clear_invalid.h5
+TOOLFAIL latest_h5clear_invalid.h5
+fi
+#
+# Clean up test files
+if test -z "$HDF5_NOCLEANUP"; then
+ rm -f h5clear_*.h5 latest_h5clear*.h5
+fi
+
+if test $nerrors -eq 0 ; then
+ echo "All $TESTNAME tests passed."
+ exit $EXIT_SUCCESS
+else
+ echo "$TESTNAME tests failed with $nerrors error(s)."
+ exit $EXIT_FAILURE
+fi
diff --git a/tools/testfiles/family_file00000.h5 b/tools/testfiles/family_file00000.h5
index 88f75ca..d86fb96 100644
--- a/tools/testfiles/family_file00000.h5
+++ b/tools/testfiles/family_file00000.h5
Binary files differ
diff --git a/tools/testfiles/taindices.h5 b/tools/testfiles/taindices.h5
index b482a21..c0e5a68 100644
--- a/tools/testfiles/taindices.h5
+++ b/tools/testfiles/taindices.h5
Binary files differ
diff --git a/tools/testfiles/tarray1.h5 b/tools/testfiles/tarray1.h5
index 90371f2..b39d966 100644
--- a/tools/testfiles/tarray1.h5
+++ b/tools/testfiles/tarray1.h5
Binary files differ
diff --git a/tools/testfiles/tarray2.h5 b/tools/testfiles/tarray2.h5
index e2e53e8..4c0b105 100644
--- a/tools/testfiles/tarray2.h5
+++ b/tools/testfiles/tarray2.h5
Binary files differ
diff --git a/tools/testfiles/tarray3.h5 b/tools/testfiles/tarray3.h5
index 580d846..dbc6031 100644
--- a/tools/testfiles/tarray3.h5
+++ b/tools/testfiles/tarray3.h5
Binary files differ
diff --git a/tools/testfiles/tarray4.h5 b/tools/testfiles/tarray4.h5
index b34efb8..142822b 100644
--- a/tools/testfiles/tarray4.h5
+++ b/tools/testfiles/tarray4.h5
Binary files differ
diff --git a/tools/testfiles/tarray5.h5 b/tools/testfiles/tarray5.h5
index 55ebf46..e597e3b 100644
--- a/tools/testfiles/tarray5.h5
+++ b/tools/testfiles/tarray5.h5
Binary files differ
diff --git a/tools/testfiles/tarray6.h5 b/tools/testfiles/tarray6.h5
index 7eb078c..d5ad021 100644
--- a/tools/testfiles/tarray6.h5
+++ b/tools/testfiles/tarray6.h5
Binary files differ
diff --git a/tools/testfiles/tarray7.h5 b/tools/testfiles/tarray7.h5
index 74089ea..a744ed5 100644
--- a/tools/testfiles/tarray7.h5
+++ b/tools/testfiles/tarray7.h5
Binary files differ
diff --git a/tools/testfiles/tattr.h5 b/tools/testfiles/tattr.h5
index d61def5..bceb228 100644
--- a/tools/testfiles/tattr.h5
+++ b/tools/testfiles/tattr.h5
Binary files differ
diff --git a/tools/testfiles/tattr2.h5 b/tools/testfiles/tattr2.h5
index c40f3f7..f062399 100644
--- a/tools/testfiles/tattr2.h5
+++ b/tools/testfiles/tattr2.h5
Binary files differ
diff --git a/tools/testfiles/tbigdims.h5 b/tools/testfiles/tbigdims.h5
index c54c2c3..50bf2fd 100644
--- a/tools/testfiles/tbigdims.h5
+++ b/tools/testfiles/tbigdims.h5
Binary files differ
diff --git a/tools/testfiles/tbitfields.h5 b/tools/testfiles/tbitfields.h5
index 11087f0..b1b7751 100644
--- a/tools/testfiles/tbitfields.h5
+++ b/tools/testfiles/tbitfields.h5
Binary files differ
diff --git a/tools/testfiles/tchar.h5 b/tools/testfiles/tchar.h5
index 4d23ea9..0391772 100644
--- a/tools/testfiles/tchar.h5
+++ b/tools/testfiles/tchar.h5
Binary files differ
diff --git a/tools/testfiles/tcompound.h5 b/tools/testfiles/tcompound.h5
index d1ec650..edef9d3 100644
--- a/tools/testfiles/tcompound.h5
+++ b/tools/testfiles/tcompound.h5
Binary files differ
diff --git a/tools/testfiles/tcompound2.h5 b/tools/testfiles/tcompound2.h5
index 98e80bd..482f9fd 100644
--- a/tools/testfiles/tcompound2.h5
+++ b/tools/testfiles/tcompound2.h5
Binary files differ
diff --git a/tools/testfiles/tcompound_complex.h5 b/tools/testfiles/tcompound_complex.h5
index 5c6274f..a0c90eb 100644
--- a/tools/testfiles/tcompound_complex.h5
+++ b/tools/testfiles/tcompound_complex.h5
Binary files differ
diff --git a/tools/testfiles/tdatareg.h5 b/tools/testfiles/tdatareg.h5
index 62a889f..631d6b0 100644
--- a/tools/testfiles/tdatareg.h5
+++ b/tools/testfiles/tdatareg.h5
Binary files differ
diff --git a/tools/testfiles/tdset.h5 b/tools/testfiles/tdset.h5
index 71dcb91..ae19cf4 100644
--- a/tools/testfiles/tdset.h5
+++ b/tools/testfiles/tdset.h5
Binary files differ
diff --git a/tools/testfiles/tdset2.h5 b/tools/testfiles/tdset2.h5
index 5e17cfd..f3e555b 100644
--- a/tools/testfiles/tdset2.h5
+++ b/tools/testfiles/tdset2.h5
Binary files differ
diff --git a/tools/testfiles/tempty.h5 b/tools/testfiles/tempty.h5
index d7d903f..f6d6b7a 100644
--- a/tools/testfiles/tempty.h5
+++ b/tools/testfiles/tempty.h5
Binary files differ
diff --git a/tools/testfiles/tenum.h5 b/tools/testfiles/tenum.h5
index b1300d8..5521fc4 100644
--- a/tools/testfiles/tenum.h5
+++ b/tools/testfiles/tenum.h5
Binary files differ
diff --git a/tools/testfiles/tfamily00000.h5 b/tools/testfiles/tfamily00000.h5
index a130bfd..70f6dcf 100644
--- a/tools/testfiles/tfamily00000.h5
+++ b/tools/testfiles/tfamily00000.h5
Binary files differ
diff --git a/tools/testfiles/tfcontents2.h5 b/tools/testfiles/tfcontents2.h5
index 1df0779..1514e28 100644
--- a/tools/testfiles/tfcontents2.h5
+++ b/tools/testfiles/tfcontents2.h5
Binary files differ
diff --git a/tools/testfiles/tfvalues.h5 b/tools/testfiles/tfvalues.h5
index a6af958..c238f44 100644
--- a/tools/testfiles/tfvalues.h5
+++ b/tools/testfiles/tfvalues.h5
Binary files differ
diff --git a/tools/testfiles/tgroup.h5 b/tools/testfiles/tgroup.h5
index 565fb67..7c5cd63 100644
--- a/tools/testfiles/tgroup.h5
+++ b/tools/testfiles/tgroup.h5
Binary files differ
diff --git a/tools/testfiles/thlink.h5 b/tools/testfiles/thlink.h5
index 6e0e7e1..0ad92d1 100644
--- a/tools/testfiles/thlink.h5
+++ b/tools/testfiles/thlink.h5
Binary files differ
diff --git a/tools/testfiles/thyperslab.h5 b/tools/testfiles/thyperslab.h5
index a730aa3..dc2c0db 100644
--- a/tools/testfiles/thyperslab.h5
+++ b/tools/testfiles/thyperslab.h5
Binary files differ
diff --git a/tools/testfiles/tlarge_objname.h5 b/tools/testfiles/tlarge_objname.h5
index 707d7b6..9e26283 100644
--- a/tools/testfiles/tlarge_objname.h5
+++ b/tools/testfiles/tlarge_objname.h5
Binary files differ
diff --git a/tools/testfiles/tlonglinks.h5 b/tools/testfiles/tlonglinks.h5
index f54e5f5..6c2cab4 100644
--- a/tools/testfiles/tlonglinks.h5
+++ b/tools/testfiles/tlonglinks.h5
Binary files differ
diff --git a/tools/testfiles/tloop.h5 b/tools/testfiles/tloop.h5
index d7a2f47..e54f91c 100644
--- a/tools/testfiles/tloop.h5
+++ b/tools/testfiles/tloop.h5
Binary files differ
diff --git a/tools/testfiles/tloop2.h5 b/tools/testfiles/tloop2.h5
index 995bfab..60d7ed2 100644
--- a/tools/testfiles/tloop2.h5
+++ b/tools/testfiles/tloop2.h5
Binary files differ
diff --git a/tools/testfiles/tmulti-s.h5 b/tools/testfiles/tmulti-s.h5
index 3feae49..bc2fafb 100644
--- a/tools/testfiles/tmulti-s.h5
+++ b/tools/testfiles/tmulti-s.h5
Binary files differ
diff --git a/tools/testfiles/tname-amp.h5 b/tools/testfiles/tname-amp.h5
index 27ab521..82f6316 100644
--- a/tools/testfiles/tname-amp.h5
+++ b/tools/testfiles/tname-amp.h5
Binary files differ
diff --git a/tools/testfiles/tname-apos.h5 b/tools/testfiles/tname-apos.h5
index 42d0fc3..9b49159 100644
--- a/tools/testfiles/tname-apos.h5
+++ b/tools/testfiles/tname-apos.h5
Binary files differ
diff --git a/tools/testfiles/tname-gt.h5 b/tools/testfiles/tname-gt.h5
index fabd154..1d2795e 100644
--- a/tools/testfiles/tname-gt.h5
+++ b/tools/testfiles/tname-gt.h5
Binary files differ
diff --git a/tools/testfiles/tname-lt.h5 b/tools/testfiles/tname-lt.h5
index 6b13375..e3dafe0 100644
--- a/tools/testfiles/tname-lt.h5
+++ b/tools/testfiles/tname-lt.h5
Binary files differ
diff --git a/tools/testfiles/tname-quot.h5 b/tools/testfiles/tname-quot.h5
index eb8d6cc..fd9e862 100644
--- a/tools/testfiles/tname-quot.h5
+++ b/tools/testfiles/tname-quot.h5
Binary files differ
diff --git a/tools/testfiles/tname-sp.h5 b/tools/testfiles/tname-sp.h5
index 0201efd..514eb8d 100644
--- a/tools/testfiles/tname-sp.h5
+++ b/tools/testfiles/tname-sp.h5
Binary files differ
diff --git a/tools/testfiles/tnestedcomp.h5 b/tools/testfiles/tnestedcomp.h5
index b777ee3..2912310 100644
--- a/tools/testfiles/tnestedcomp.h5
+++ b/tools/testfiles/tnestedcomp.h5
Binary files differ
diff --git a/tools/testfiles/tnodata.h5 b/tools/testfiles/tnodata.h5
index 8e0a89d..1e537f1 100644
--- a/tools/testfiles/tnodata.h5
+++ b/tools/testfiles/tnodata.h5
Binary files differ
diff --git a/tools/testfiles/tnullspace.h5 b/tools/testfiles/tnullspace.h5
index b5dac5d..d405061 100644
--- a/tools/testfiles/tnullspace.h5
+++ b/tools/testfiles/tnullspace.h5
Binary files differ
diff --git a/tools/testfiles/tobjref.h5 b/tools/testfiles/tobjref.h5
index ef42ff3..ecf3827 100644
--- a/tools/testfiles/tobjref.h5
+++ b/tools/testfiles/tobjref.h5
Binary files differ
diff --git a/tools/testfiles/topaque.h5 b/tools/testfiles/topaque.h5
index d56b594..669f4b7 100644
--- a/tools/testfiles/topaque.h5
+++ b/tools/testfiles/topaque.h5
Binary files differ
diff --git a/tools/testfiles/tref-escapes-at.h5 b/tools/testfiles/tref-escapes-at.h5
index 641513c..e3f0d6b 100644
--- a/tools/testfiles/tref-escapes-at.h5
+++ b/tools/testfiles/tref-escapes-at.h5
Binary files differ
diff --git a/tools/testfiles/tref-escapes.h5 b/tools/testfiles/tref-escapes.h5
index 6c7638b..766a840 100644
--- a/tools/testfiles/tref-escapes.h5
+++ b/tools/testfiles/tref-escapes.h5
Binary files differ
diff --git a/tools/testfiles/tref.h5 b/tools/testfiles/tref.h5
index 73b4be5..3a9899a 100644
--- a/tools/testfiles/tref.h5
+++ b/tools/testfiles/tref.h5
Binary files differ
diff --git a/tools/testfiles/tsaf.h5 b/tools/testfiles/tsaf.h5
index c84c5b6..75237ba 100644
--- a/tools/testfiles/tsaf.h5
+++ b/tools/testfiles/tsaf.h5
Binary files differ
diff --git a/tools/testfiles/tslink.h5 b/tools/testfiles/tslink.h5
index 753b62d..ab80d8f 100644
--- a/tools/testfiles/tslink.h5
+++ b/tools/testfiles/tslink.h5
Binary files differ
diff --git a/tools/testfiles/tsplit_file-m.h5 b/tools/testfiles/tsplit_file-m.h5
index a6eef73..d431c70 100644
--- a/tools/testfiles/tsplit_file-m.h5
+++ b/tools/testfiles/tsplit_file-m.h5
Binary files differ
diff --git a/tools/testfiles/tstr.h5 b/tools/testfiles/tstr.h5
index af5384f..ae6a012 100644
--- a/tools/testfiles/tstr.h5
+++ b/tools/testfiles/tstr.h5
Binary files differ
diff --git a/tools/testfiles/tstr2.h5 b/tools/testfiles/tstr2.h5
index d3b1588..b7d4802 100644
--- a/tools/testfiles/tstr2.h5
+++ b/tools/testfiles/tstr2.h5
Binary files differ
diff --git a/tools/testfiles/tstr3.h5 b/tools/testfiles/tstr3.h5
index 9f9112f..727dec5 100644
--- a/tools/testfiles/tstr3.h5
+++ b/tools/testfiles/tstr3.h5
Binary files differ
diff --git a/tools/testfiles/tstring-at.h5 b/tools/testfiles/tstring-at.h5
index aa17960..a477ee5 100644
--- a/tools/testfiles/tstring-at.h5
+++ b/tools/testfiles/tstring-at.h5
Binary files differ
diff --git a/tools/testfiles/tstring.h5 b/tools/testfiles/tstring.h5
index 667fe78..914a464 100644
--- a/tools/testfiles/tstring.h5
+++ b/tools/testfiles/tstring.h5
Binary files differ
diff --git a/tools/testfiles/tvldtypes1.h5 b/tools/testfiles/tvldtypes1.h5
index b5b2bd7..423dae8 100644
--- a/tools/testfiles/tvldtypes1.h5
+++ b/tools/testfiles/tvldtypes1.h5
Binary files differ
diff --git a/tools/testfiles/tvldtypes2.h5 b/tools/testfiles/tvldtypes2.h5
index 65bf63f..86ba20d 100644
--- a/tools/testfiles/tvldtypes2.h5
+++ b/tools/testfiles/tvldtypes2.h5
Binary files differ
diff --git a/tools/testfiles/tvldtypes3.h5 b/tools/testfiles/tvldtypes3.h5
index dd4aca7..66fd1d2 100644
--- a/tools/testfiles/tvldtypes3.h5
+++ b/tools/testfiles/tvldtypes3.h5
Binary files differ
diff --git a/tools/testfiles/tvldtypes4.h5 b/tools/testfiles/tvldtypes4.h5
index 70dc73e..016ad55 100644
--- a/tools/testfiles/tvldtypes4.h5
+++ b/tools/testfiles/tvldtypes4.h5
Binary files differ
diff --git a/tools/testfiles/tvldtypes5.h5 b/tools/testfiles/tvldtypes5.h5
index 776c020..71b924f 100644
--- a/tools/testfiles/tvldtypes5.h5
+++ b/tools/testfiles/tvldtypes5.h5
Binary files differ
diff --git a/tools/testfiles/tvms.h5 b/tools/testfiles/tvms.h5
index 9c243ff..d3b0b7c 100644
--- a/tools/testfiles/tvms.h5
+++ b/tools/testfiles/tvms.h5
Binary files differ