From a196a4f351abed0670c10bc50887bd4e56dd4775 Mon Sep 17 00:00:00 2001 From: Vailin Choi Date: Wed, 8 Jan 2014 12:09:23 -0500 Subject: [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. --- configure | 5 +- configure.ac | 3 +- hl/src/H5DO.c | 205 +++ hl/src/H5DOpublic.h | 7 +- hl/src/H5HLprivate2.h | 91 -- hl/src/H5LD.c | 2 +- hl/test/Makefile.am | 8 +- hl/test/Makefile.in | 65 +- hl/test/gen_test_ld.c | 14 +- hl/test/ld_extend.c | 151 -- hl/test/ld_monitor.c | 148 -- hl/test/ld_mx.c | 353 +++++ hl/test/test_dset_append.c | 1191 ++++++++++++++ hl/test/test_file_image.c | 38 +- hl/test/test_ld.h5 | Bin 28336 -> 42955 bytes hl/test/test_ld.sh.in | 46 +- hl/test/test_table_be.h5 | Bin 55912 -> 55912 bytes hl/test/test_table_cray.h5 | Bin 55912 -> 55912 bytes hl/test/test_table_le.h5 | Bin 53880 -> 53880 bytes hl/tools/h5watch/h5watch.c | 2 +- hl/tools/h5watch/testh5watch.sh.in | 2 +- src/H5AC.c | 33 + src/H5ACprivate.h | 2 + src/H5C.c | 39 +- src/H5Cprivate.h | 4 + src/H5D.c | 14 +- src/H5Dint.c | 97 +- src/H5Doh.c | 25 +- src/H5Dpkg.h | 1 + src/H5Dprivate.h | 9 + src/H5Dpublic.h | 3 + src/H5F.c | 382 ++++- src/H5FD.c | 58 + src/H5FDcore.c | 79 +- src/H5FDdirect.c | 78 +- src/H5FDprivate.h | 2 + src/H5FDpublic.h | 4 +- src/H5FDsec2.c | 72 +- src/H5Fio.c | 49 + src/H5Fpkg.h | 21 +- src/H5Fprivate.h | 13 + src/H5Fpublic.h | 5 + src/H5Fsuper.c | 2 +- src/H5G.c | 5 +- src/H5Ocopy.c | 29 +- src/H5Oflush.c | 54 +- src/H5Opkg.h | 2 +- src/H5Oprivate.h | 2 + src/H5Pdapl.c | 130 +- src/H5Pfapl.c | 111 +- src/H5Ppublic.h | 7 + src/H5T.c | 6 +- src/H5config.h.in | 3 + src/H5private.h | 10 + test/Makefile.am | 47 +- test/Makefile.in | 90 +- test/accum.c | 13 +- test/accum_swmr_reader.c | 2 +- test/bad_compound.h5 | Bin 2208 -> 2208 bytes test/btree_idx_1_6.h5 | Bin 6350 -> 6350 bytes test/corrupt_stab_msg.h5 | Bin 2928 -> 2928 bytes test/deflate.h5 | Bin 6240 -> 6240 bytes test/family_v16_00000.h5 | Bin 5120 -> 5120 bytes test/file_image.c | 96 +- test/filespace_1_6.h5 | Bin 2448 -> 2448 bytes test/fill_old.h5 | Bin 2560 -> 2560 bytes test/flush2.c | 68 + test/group_old.h5 | Bin 1952 -> 1952 bytes test/h5test.c | 53 + test/h5test.h | 6 + test/mergemsg.h5 | Bin 3472 -> 3472 bytes test/multi_file_v16-s.h5 | Bin 2048 -> 2048 bytes test/swmr_addrem_writer.c | 3 + test/swmr_common.c | 2 +- test/swmr_common.h | 4 + test/swmr_remove_writer.c | 3 + test/swmr_sparse_writer.c | 5 + test/swmr_start_write.c | 691 ++++++++ test/swmr_writer.c | 3 + test/tarrold.h5 | Bin 6032 -> 6032 bytes test/test_filters_be.h5 | Bin 5720 -> 5720 bytes test/test_filters_le.h5 | Bin 5720 -> 5720 bytes test/test_swmr.c | 2104 +++++++++++++++++++++++++ test/testswmr.sh | 139 +- test/tfile.c | 1711 ++++++++++++++++---- test/th5s.h5 | Bin 2049 -> 2049 bytes test/tlayouto.h5 | Bin 1576 -> 1576 bytes test/tmtimen.h5 | Bin 1576 -> 1576 bytes test/tmtimeo.h5 | Bin 2052 -> 2052 bytes test/use.h | 27 +- test/use_append_chunk.c | 11 +- test/use_append_mchunks.c | 11 +- test/use_common.c | 14 +- tools/h5diff/testfiles/h5diff_hyper1.h5 | Bin 1052720 -> 1052720 bytes tools/h5diff/testfiles/h5diff_hyper2.h5 | Bin 1052720 -> 1052720 bytes tools/h5import/testfiles/binfp64.h5 | Bin 10760 -> 10760 bytes tools/h5import/testfiles/binin16.h5 | Bin 10760 -> 10760 bytes tools/h5import/testfiles/binin32.h5 | Bin 9472 -> 9472 bytes tools/h5import/testfiles/binin8.h5 | Bin 10760 -> 10760 bytes tools/h5import/testfiles/binuin16.h5 | Bin 10760 -> 10760 bytes tools/h5import/testfiles/binuin32.h5 | Bin 6384 -> 6384 bytes tools/h5import/testfiles/txtfp32.h5 | Bin 4192 -> 4192 bytes tools/h5import/testfiles/txtfp64.h5 | Bin 9784 -> 9784 bytes tools/h5import/testfiles/txtin16.h5 | Bin 9784 -> 9784 bytes tools/h5import/testfiles/txtin32.h5 | Bin 4192 -> 4192 bytes tools/h5import/testfiles/txtin8.h5 | Bin 9784 -> 9784 bytes tools/h5import/testfiles/txtuin16.h5 | Bin 10240 -> 10240 bytes tools/h5import/testfiles/txtuin32.h5 | Bin 6240 -> 6240 bytes tools/h5repack/testfiles/h5repack_attr.h5 | Bin 20056 -> 20056 bytes tools/h5repack/testfiles/h5repack_deflate.h5 | Bin 5962 -> 5962 bytes tools/h5repack/testfiles/h5repack_early.h5 | Bin 2067224 -> 2067224 bytes tools/h5repack/testfiles/h5repack_fill.h5 | Bin 2072 -> 2072 bytes tools/h5repack/testfiles/h5repack_filters.h5 | Bin 29744 -> 29744 bytes tools/h5repack/testfiles/h5repack_fletcher.h5 | Bin 7880 -> 7880 bytes tools/h5repack/testfiles/h5repack_hlink.h5 | Bin 6576 -> 6576 bytes tools/h5repack/testfiles/h5repack_layouto.h5 | Bin 1576 -> 1576 bytes tools/h5repack/testfiles/h5repack_nbit.h5 | Bin 13776 -> 13776 bytes tools/h5repack/testfiles/h5repack_shuffle.h5 | Bin 7864 -> 7864 bytes tools/h5repack/testfiles/h5repack_soffset.h5 | Bin 11052 -> 11052 bytes tools/h5stat/testfiles/h5stat_filters.h5 | Bin 46272 -> 46272 bytes tools/misc/Makefile.am | 15 +- tools/misc/Makefile.in | 72 +- tools/misc/clear_open_chk.c | 72 + tools/misc/h5clear.c | 137 ++ tools/misc/h5clear_gentest.c | 238 +++ tools/misc/testh5clear.sh.in | 135 ++ tools/testfiles/family_file00000.h5 | Bin 1024 -> 1024 bytes tools/testfiles/taindices.h5 | Bin 17160 -> 17160 bytes tools/testfiles/tarray1.h5 | Bin 2112 -> 2112 bytes tools/testfiles/tarray2.h5 | Bin 3008 -> 3008 bytes tools/testfiles/tarray3.h5 | Bin 3200 -> 3200 bytes tools/testfiles/tarray4.h5 | Bin 2176 -> 2176 bytes tools/testfiles/tarray5.h5 | Bin 2368 -> 2368 bytes tools/testfiles/tarray6.h5 | Bin 6400 -> 6400 bytes tools/testfiles/tarray7.h5 | Bin 6400 -> 6400 bytes tools/testfiles/tattr.h5 | Bin 3024 -> 3024 bytes tools/testfiles/tattr2.h5 | Bin 33840 -> 33840 bytes tools/testfiles/tbigdims.h5 | Bin 6192 -> 6192 bytes tools/testfiles/tbitfields.h5 | Bin 2704 -> 2704 bytes tools/testfiles/tchar.h5 | Bin 2356 -> 2356 bytes tools/testfiles/tcompound.h5 | Bin 8192 -> 8192 bytes tools/testfiles/tcompound2.h5 | Bin 13640 -> 13640 bytes tools/testfiles/tcompound_complex.h5 | Bin 8192 -> 8192 bytes tools/testfiles/tdatareg.h5 | Bin 5652 -> 5652 bytes tools/testfiles/tdset.h5 | Bin 7648 -> 7648 bytes tools/testfiles/tdset2.h5 | Bin 9936 -> 9936 bytes tools/testfiles/tempty.h5 | Bin 4304 -> 4304 bytes tools/testfiles/tenum.h5 | Bin 2128 -> 2128 bytes tools/testfiles/tfamily00000.h5 | Bin 256 -> 256 bytes tools/testfiles/tfcontents2.h5 | Bin 792 -> 792 bytes tools/testfiles/tfvalues.h5 | Bin 9552 -> 9552 bytes tools/testfiles/tgroup.h5 | Bin 11096 -> 11096 bytes tools/testfiles/thlink.h5 | Bin 5536 -> 5536 bytes tools/testfiles/thyperslab.h5 | Bin 1050880 -> 1050880 bytes tools/testfiles/tlarge_objname.h5 | Bin 40008 -> 40008 bytes tools/testfiles/tlonglinks.h5 | Bin 203168 -> 203168 bytes tools/testfiles/tloop.h5 | Bin 3168 -> 3168 bytes tools/testfiles/tloop2.h5 | Bin 3168 -> 3168 bytes tools/testfiles/tmulti-s.h5 | Bin 2048 -> 2048 bytes tools/testfiles/tname-amp.h5 | Bin 2880 -> 2880 bytes tools/testfiles/tname-apos.h5 | Bin 2880 -> 2880 bytes tools/testfiles/tname-gt.h5 | Bin 2880 -> 2880 bytes tools/testfiles/tname-lt.h5 | Bin 2880 -> 2880 bytes tools/testfiles/tname-quot.h5 | Bin 2880 -> 2880 bytes tools/testfiles/tname-sp.h5 | Bin 2880 -> 2880 bytes tools/testfiles/tnestedcomp.h5 | Bin 2072 -> 2072 bytes tools/testfiles/tnodata.h5 | Bin 1412 -> 1412 bytes tools/testfiles/tnullspace.h5 | Bin 3624 -> 3624 bytes tools/testfiles/tobjref.h5 | Bin 2900 -> 2900 bytes tools/testfiles/topaque.h5 | Bin 1744 -> 1744 bytes tools/testfiles/tref-escapes-at.h5 | Bin 5849 -> 5849 bytes tools/testfiles/tref-escapes.h5 | Bin 5536 -> 5536 bytes tools/testfiles/tref.h5 | Bin 3004 -> 3004 bytes tools/testfiles/tsaf.h5 | Bin 769444 -> 769444 bytes tools/testfiles/tslink.h5 | Bin 1168 -> 1168 bytes tools/testfiles/tsplit_file-m.h5 | Bin 2048 -> 2048 bytes tools/testfiles/tstr.h5 | Bin 15608 -> 15608 bytes tools/testfiles/tstr2.h5 | Bin 11096 -> 11096 bytes tools/testfiles/tstr3.h5 | Bin 8736 -> 8736 bytes tools/testfiles/tstring-at.h5 | Bin 1672 -> 1672 bytes tools/testfiles/tstring.h5 | Bin 2160 -> 2160 bytes tools/testfiles/tvldtypes1.h5 | Bin 8336 -> 8336 bytes tools/testfiles/tvldtypes2.h5 | Bin 6208 -> 6208 bytes tools/testfiles/tvldtypes3.h5 | Bin 6240 -> 6240 bytes tools/testfiles/tvldtypes4.h5 | Bin 8192 -> 8192 bytes tools/testfiles/tvldtypes5.h5 | Bin 8192 -> 8192 bytes tools/testfiles/tvms.h5 | Bin 2288 -> 2288 bytes 187 files changed, 8495 insertions(+), 959 deletions(-) delete mode 100644 hl/test/ld_extend.c delete mode 100644 hl/test/ld_monitor.c create mode 100644 hl/test/ld_mx.c create mode 100644 hl/test/test_dset_append.c create mode 100644 test/swmr_start_write.c create mode 100644 test/test_swmr.c create mode 100644 tools/misc/clear_open_chk.c create mode 100644 tools/misc/h5clear.c create mode 100644 tools/misc/h5clear_gentest.c create mode 100644 tools/misc/testh5clear.sh.in 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(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 -#include -#include -#include -#include - -/* 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 -#include -#include -#include -#include - -#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 +#include +#include +#include +#include +#include + +/* 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 +#include +#include "h5hltest.h" +#include "H5srcdir.h" +#include "H5DOpublic.h" +#include + +#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 Binary files a/hl/test/test_ld.h5 and b/hl/test/test_ld.h5 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 Binary files a/hl/test/test_table_be.h5 and b/hl/test/test_table_be.h5 differ diff --git a/hl/test/test_table_cray.h5 b/hl/test/test_table_cray.h5 index d22dce3..1fcd75b 100644 Binary files a/hl/test/test_table_cray.h5 and b/hl/test/test_table_cray.h5 differ diff --git a/hl/test/test_table_le.h5 b/hl/test/test_table_le.h5 index 6c330fd..ee5b532 100644 Binary files a/hl/test/test_table_le.h5 and b/hl/test/test_table_le.h5 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 header file. */ +#undef HAVE_SYS_FILE_H + /* Define to 1 if you have the 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 +#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 Binary files a/test/bad_compound.h5 and b/test/bad_compound.h5 differ diff --git a/test/btree_idx_1_6.h5 b/test/btree_idx_1_6.h5 index b1ac4da..92f939b 100644 Binary files a/test/btree_idx_1_6.h5 and b/test/btree_idx_1_6.h5 differ diff --git a/test/corrupt_stab_msg.h5 b/test/corrupt_stab_msg.h5 index 4fa287c..a00616d 100644 Binary files a/test/corrupt_stab_msg.h5 and b/test/corrupt_stab_msg.h5 differ diff --git a/test/deflate.h5 b/test/deflate.h5 index 2f62e25..e33af4f 100644 Binary files a/test/deflate.h5 and b/test/deflate.h5 differ diff --git a/test/family_v16_00000.h5 b/test/family_v16_00000.h5 index ac75ea9..aaa3dad 100644 Binary files a/test/family_v16_00000.h5 and b/test/family_v16_00000.h5 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 Binary files a/test/filespace_1_6.h5 and b/test/filespace_1_6.h5 differ diff --git a/test/fill_old.h5 b/test/fill_old.h5 index e77f519..4dd7740 100644 Binary files a/test/fill_old.h5 and b/test/fill_old.h5 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 Binary files a/test/group_old.h5 and b/test/group_old.h5 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) +#include + +#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 ] [-c ]\n"); + printf(" [-r ] [-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(" should be b2 or ea\n"); + printf("\n"); + printf(" 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 Binary files a/test/tarrold.h5 and b/test/tarrold.h5 differ diff --git a/test/test_filters_be.h5 b/test/test_filters_be.h5 index c4c127b..aadb372 100644 Binary files a/test/test_filters_be.h5 and b/test/test_filters_be.h5 differ diff --git a/test/test_filters_le.h5 b/test/test_filters_le.h5 index ff8b846..c29fa0a 100644 Binary files a/test/test_filters_le.h5 and b/test/test_filters_le.h5 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 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=( ... ) + 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 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=( ... ) 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 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=( ... ) 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 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=( ... ) 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,23 +4891,1322 @@ test_metadata_read_retry_info(void) /**************************************************************** ** -** test_deprec(): -** Test deprecated functionality. +** 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. ** -****************************************************************/ -#ifndef H5_NO_DEPRECATED_SYMBOLS +*****************************************************************/ static void -test_deprec(void) +test_file_lock_same(void) { - hid_t file; /* File IDs for old & new files */ - hid_t fcpl; /* File creation property list */ - unsigned super; /* Superblock version # */ - unsigned freelist; /* Free list version # */ - unsigned stab; /* Symbol table entry version # */ - unsigned shhdr; /* Shared object header version # */ - H5F_info1_t finfo; /* global information about file */ - herr_t ret; /* Generic return value */ - + 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. +** +****************************************************************/ +#ifndef H5_NO_DEPRECATED_SYMBOLS +static void +test_deprec(void) +{ + hid_t file; /* File IDs for old & new files */ + hid_t fcpl; /* File creation property list */ + unsigned super; /* Superblock version # */ + unsigned freelist; /* Free list version # */ + unsigned stab; /* Symbol table entry version # */ + unsigned shhdr; /* Shared object header version # */ + H5F_info1_t finfo; /* global information about file */ + herr_t ret; /* Generic return value */ + /* Output message about test being performed */ MESSAGE(5, ("Testing deprecated routines\n")); @@ -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 Binary files a/test/th5s.h5 and b/test/th5s.h5 differ diff --git a/test/tlayouto.h5 b/test/tlayouto.h5 index a038e68..3322020 100644 Binary files a/test/tlayouto.h5 and b/test/tlayouto.h5 differ diff --git a/test/tmtimen.h5 b/test/tmtimen.h5 index 96e5fb3..007a6b6 100644 Binary files a/test/tmtimen.h5 and b/test/tmtimen.h5 differ diff --git a/test/tmtimeo.h5 b/test/tmtimeo.h5 index 8cacf4a..c9dfcc4 100644 Binary files a/test/tmtimeo.h5 and b/test/tmtimeo.h5 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 #include #include -#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 Binary files a/tools/h5diff/testfiles/h5diff_hyper1.h5 and b/tools/h5diff/testfiles/h5diff_hyper1.h5 differ diff --git a/tools/h5diff/testfiles/h5diff_hyper2.h5 b/tools/h5diff/testfiles/h5diff_hyper2.h5 index 05a2eb1..ad2f468 100644 Binary files a/tools/h5diff/testfiles/h5diff_hyper2.h5 and b/tools/h5diff/testfiles/h5diff_hyper2.h5 differ diff --git a/tools/h5import/testfiles/binfp64.h5 b/tools/h5import/testfiles/binfp64.h5 index 80e3a8a..5426edb 100644 Binary files a/tools/h5import/testfiles/binfp64.h5 and b/tools/h5import/testfiles/binfp64.h5 differ diff --git a/tools/h5import/testfiles/binin16.h5 b/tools/h5import/testfiles/binin16.h5 index 0825bbc..6d89c63 100644 Binary files a/tools/h5import/testfiles/binin16.h5 and b/tools/h5import/testfiles/binin16.h5 differ diff --git a/tools/h5import/testfiles/binin32.h5 b/tools/h5import/testfiles/binin32.h5 index fd8faa9..61cc507 100644 Binary files a/tools/h5import/testfiles/binin32.h5 and b/tools/h5import/testfiles/binin32.h5 differ diff --git a/tools/h5import/testfiles/binin8.h5 b/tools/h5import/testfiles/binin8.h5 index a1d1a37..efd3ae0 100644 Binary files a/tools/h5import/testfiles/binin8.h5 and b/tools/h5import/testfiles/binin8.h5 differ diff --git a/tools/h5import/testfiles/binuin16.h5 b/tools/h5import/testfiles/binuin16.h5 index c486c89..1af804c 100644 Binary files a/tools/h5import/testfiles/binuin16.h5 and b/tools/h5import/testfiles/binuin16.h5 differ diff --git a/tools/h5import/testfiles/binuin32.h5 b/tools/h5import/testfiles/binuin32.h5 index 41699d7..e7d12d9 100644 Binary files a/tools/h5import/testfiles/binuin32.h5 and b/tools/h5import/testfiles/binuin32.h5 differ diff --git a/tools/h5import/testfiles/txtfp32.h5 b/tools/h5import/testfiles/txtfp32.h5 index f74e003..bd41f06 100644 Binary files a/tools/h5import/testfiles/txtfp32.h5 and b/tools/h5import/testfiles/txtfp32.h5 differ diff --git a/tools/h5import/testfiles/txtfp64.h5 b/tools/h5import/testfiles/txtfp64.h5 index b6ba4f5..41c4e9e 100644 Binary files a/tools/h5import/testfiles/txtfp64.h5 and b/tools/h5import/testfiles/txtfp64.h5 differ diff --git a/tools/h5import/testfiles/txtin16.h5 b/tools/h5import/testfiles/txtin16.h5 index dc6c1ea..5089c97 100644 Binary files a/tools/h5import/testfiles/txtin16.h5 and b/tools/h5import/testfiles/txtin16.h5 differ diff --git a/tools/h5import/testfiles/txtin32.h5 b/tools/h5import/testfiles/txtin32.h5 index 350333c..8d547cf 100644 Binary files a/tools/h5import/testfiles/txtin32.h5 and b/tools/h5import/testfiles/txtin32.h5 differ diff --git a/tools/h5import/testfiles/txtin8.h5 b/tools/h5import/testfiles/txtin8.h5 index 42e7727..61b7165 100644 Binary files a/tools/h5import/testfiles/txtin8.h5 and b/tools/h5import/testfiles/txtin8.h5 differ diff --git a/tools/h5import/testfiles/txtuin16.h5 b/tools/h5import/testfiles/txtuin16.h5 index 9ee166a..c43b875 100644 Binary files a/tools/h5import/testfiles/txtuin16.h5 and b/tools/h5import/testfiles/txtuin16.h5 differ diff --git a/tools/h5import/testfiles/txtuin32.h5 b/tools/h5import/testfiles/txtuin32.h5 index 1a4dda5..aec3b0f 100644 Binary files a/tools/h5import/testfiles/txtuin32.h5 and b/tools/h5import/testfiles/txtuin32.h5 differ diff --git a/tools/h5repack/testfiles/h5repack_attr.h5 b/tools/h5repack/testfiles/h5repack_attr.h5 index fe066db..3bc4906 100644 Binary files a/tools/h5repack/testfiles/h5repack_attr.h5 and b/tools/h5repack/testfiles/h5repack_attr.h5 differ diff --git a/tools/h5repack/testfiles/h5repack_deflate.h5 b/tools/h5repack/testfiles/h5repack_deflate.h5 index 3a4b86d..86d66c0 100644 Binary files a/tools/h5repack/testfiles/h5repack_deflate.h5 and b/tools/h5repack/testfiles/h5repack_deflate.h5 differ diff --git a/tools/h5repack/testfiles/h5repack_early.h5 b/tools/h5repack/testfiles/h5repack_early.h5 index 9b92890..0394bef 100644 Binary files a/tools/h5repack/testfiles/h5repack_early.h5 and b/tools/h5repack/testfiles/h5repack_early.h5 differ diff --git a/tools/h5repack/testfiles/h5repack_fill.h5 b/tools/h5repack/testfiles/h5repack_fill.h5 index 21516cb..81c32d5 100644 Binary files a/tools/h5repack/testfiles/h5repack_fill.h5 and b/tools/h5repack/testfiles/h5repack_fill.h5 differ diff --git a/tools/h5repack/testfiles/h5repack_filters.h5 b/tools/h5repack/testfiles/h5repack_filters.h5 index 042b8db..0600adb 100644 Binary files a/tools/h5repack/testfiles/h5repack_filters.h5 and b/tools/h5repack/testfiles/h5repack_filters.h5 differ diff --git a/tools/h5repack/testfiles/h5repack_fletcher.h5 b/tools/h5repack/testfiles/h5repack_fletcher.h5 index 2f137b0..e4e2c05 100644 Binary files a/tools/h5repack/testfiles/h5repack_fletcher.h5 and b/tools/h5repack/testfiles/h5repack_fletcher.h5 differ diff --git a/tools/h5repack/testfiles/h5repack_hlink.h5 b/tools/h5repack/testfiles/h5repack_hlink.h5 index 3d22728..b00f9a2 100644 Binary files a/tools/h5repack/testfiles/h5repack_hlink.h5 and b/tools/h5repack/testfiles/h5repack_hlink.h5 differ diff --git a/tools/h5repack/testfiles/h5repack_layouto.h5 b/tools/h5repack/testfiles/h5repack_layouto.h5 index a038e68..3322020 100644 Binary files a/tools/h5repack/testfiles/h5repack_layouto.h5 and b/tools/h5repack/testfiles/h5repack_layouto.h5 differ diff --git a/tools/h5repack/testfiles/h5repack_nbit.h5 b/tools/h5repack/testfiles/h5repack_nbit.h5 index 3ada112..c678f1c 100644 Binary files a/tools/h5repack/testfiles/h5repack_nbit.h5 and b/tools/h5repack/testfiles/h5repack_nbit.h5 differ diff --git a/tools/h5repack/testfiles/h5repack_shuffle.h5 b/tools/h5repack/testfiles/h5repack_shuffle.h5 index d13cca7..6520193 100644 Binary files a/tools/h5repack/testfiles/h5repack_shuffle.h5 and b/tools/h5repack/testfiles/h5repack_shuffle.h5 differ diff --git a/tools/h5repack/testfiles/h5repack_soffset.h5 b/tools/h5repack/testfiles/h5repack_soffset.h5 index 89ee99a..a9457d3 100644 Binary files a/tools/h5repack/testfiles/h5repack_soffset.h5 and b/tools/h5repack/testfiles/h5repack_soffset.h5 differ diff --git a/tools/h5stat/testfiles/h5stat_filters.h5 b/tools/h5stat/testfiles/h5stat_filters.h5 index 5b5f4bb..cbd4467 100644 Binary files a/tools/h5stat/testfiles/h5stat_filters.h5 and b/tools/h5stat/testfiles/h5stat_filters.h5 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 Binary files a/tools/testfiles/family_file00000.h5 and b/tools/testfiles/family_file00000.h5 differ diff --git a/tools/testfiles/taindices.h5 b/tools/testfiles/taindices.h5 index b482a21..c0e5a68 100644 Binary files a/tools/testfiles/taindices.h5 and b/tools/testfiles/taindices.h5 differ diff --git a/tools/testfiles/tarray1.h5 b/tools/testfiles/tarray1.h5 index 90371f2..b39d966 100644 Binary files a/tools/testfiles/tarray1.h5 and b/tools/testfiles/tarray1.h5 differ diff --git a/tools/testfiles/tarray2.h5 b/tools/testfiles/tarray2.h5 index e2e53e8..4c0b105 100644 Binary files a/tools/testfiles/tarray2.h5 and b/tools/testfiles/tarray2.h5 differ diff --git a/tools/testfiles/tarray3.h5 b/tools/testfiles/tarray3.h5 index 580d846..dbc6031 100644 Binary files a/tools/testfiles/tarray3.h5 and b/tools/testfiles/tarray3.h5 differ diff --git a/tools/testfiles/tarray4.h5 b/tools/testfiles/tarray4.h5 index b34efb8..142822b 100644 Binary files a/tools/testfiles/tarray4.h5 and b/tools/testfiles/tarray4.h5 differ diff --git a/tools/testfiles/tarray5.h5 b/tools/testfiles/tarray5.h5 index 55ebf46..e597e3b 100644 Binary files a/tools/testfiles/tarray5.h5 and b/tools/testfiles/tarray5.h5 differ diff --git a/tools/testfiles/tarray6.h5 b/tools/testfiles/tarray6.h5 index 7eb078c..d5ad021 100644 Binary files a/tools/testfiles/tarray6.h5 and b/tools/testfiles/tarray6.h5 differ diff --git a/tools/testfiles/tarray7.h5 b/tools/testfiles/tarray7.h5 index 74089ea..a744ed5 100644 Binary files a/tools/testfiles/tarray7.h5 and b/tools/testfiles/tarray7.h5 differ diff --git a/tools/testfiles/tattr.h5 b/tools/testfiles/tattr.h5 index d61def5..bceb228 100644 Binary files a/tools/testfiles/tattr.h5 and b/tools/testfiles/tattr.h5 differ diff --git a/tools/testfiles/tattr2.h5 b/tools/testfiles/tattr2.h5 index c40f3f7..f062399 100644 Binary files a/tools/testfiles/tattr2.h5 and b/tools/testfiles/tattr2.h5 differ diff --git a/tools/testfiles/tbigdims.h5 b/tools/testfiles/tbigdims.h5 index c54c2c3..50bf2fd 100644 Binary files a/tools/testfiles/tbigdims.h5 and b/tools/testfiles/tbigdims.h5 differ diff --git a/tools/testfiles/tbitfields.h5 b/tools/testfiles/tbitfields.h5 index 11087f0..b1b7751 100644 Binary files a/tools/testfiles/tbitfields.h5 and b/tools/testfiles/tbitfields.h5 differ diff --git a/tools/testfiles/tchar.h5 b/tools/testfiles/tchar.h5 index 4d23ea9..0391772 100644 Binary files a/tools/testfiles/tchar.h5 and b/tools/testfiles/tchar.h5 differ diff --git a/tools/testfiles/tcompound.h5 b/tools/testfiles/tcompound.h5 index d1ec650..edef9d3 100644 Binary files a/tools/testfiles/tcompound.h5 and b/tools/testfiles/tcompound.h5 differ diff --git a/tools/testfiles/tcompound2.h5 b/tools/testfiles/tcompound2.h5 index 98e80bd..482f9fd 100644 Binary files a/tools/testfiles/tcompound2.h5 and b/tools/testfiles/tcompound2.h5 differ diff --git a/tools/testfiles/tcompound_complex.h5 b/tools/testfiles/tcompound_complex.h5 index 5c6274f..a0c90eb 100644 Binary files a/tools/testfiles/tcompound_complex.h5 and b/tools/testfiles/tcompound_complex.h5 differ diff --git a/tools/testfiles/tdatareg.h5 b/tools/testfiles/tdatareg.h5 index 62a889f..631d6b0 100644 Binary files a/tools/testfiles/tdatareg.h5 and b/tools/testfiles/tdatareg.h5 differ diff --git a/tools/testfiles/tdset.h5 b/tools/testfiles/tdset.h5 index 71dcb91..ae19cf4 100644 Binary files a/tools/testfiles/tdset.h5 and b/tools/testfiles/tdset.h5 differ diff --git a/tools/testfiles/tdset2.h5 b/tools/testfiles/tdset2.h5 index 5e17cfd..f3e555b 100644 Binary files a/tools/testfiles/tdset2.h5 and b/tools/testfiles/tdset2.h5 differ diff --git a/tools/testfiles/tempty.h5 b/tools/testfiles/tempty.h5 index d7d903f..f6d6b7a 100644 Binary files a/tools/testfiles/tempty.h5 and b/tools/testfiles/tempty.h5 differ diff --git a/tools/testfiles/tenum.h5 b/tools/testfiles/tenum.h5 index b1300d8..5521fc4 100644 Binary files a/tools/testfiles/tenum.h5 and b/tools/testfiles/tenum.h5 differ diff --git a/tools/testfiles/tfamily00000.h5 b/tools/testfiles/tfamily00000.h5 index a130bfd..70f6dcf 100644 Binary files a/tools/testfiles/tfamily00000.h5 and b/tools/testfiles/tfamily00000.h5 differ diff --git a/tools/testfiles/tfcontents2.h5 b/tools/testfiles/tfcontents2.h5 index 1df0779..1514e28 100644 Binary files a/tools/testfiles/tfcontents2.h5 and b/tools/testfiles/tfcontents2.h5 differ diff --git a/tools/testfiles/tfvalues.h5 b/tools/testfiles/tfvalues.h5 index a6af958..c238f44 100644 Binary files a/tools/testfiles/tfvalues.h5 and b/tools/testfiles/tfvalues.h5 differ diff --git a/tools/testfiles/tgroup.h5 b/tools/testfiles/tgroup.h5 index 565fb67..7c5cd63 100644 Binary files a/tools/testfiles/tgroup.h5 and b/tools/testfiles/tgroup.h5 differ diff --git a/tools/testfiles/thlink.h5 b/tools/testfiles/thlink.h5 index 6e0e7e1..0ad92d1 100644 Binary files a/tools/testfiles/thlink.h5 and b/tools/testfiles/thlink.h5 differ diff --git a/tools/testfiles/thyperslab.h5 b/tools/testfiles/thyperslab.h5 index a730aa3..dc2c0db 100644 Binary files a/tools/testfiles/thyperslab.h5 and b/tools/testfiles/thyperslab.h5 differ diff --git a/tools/testfiles/tlarge_objname.h5 b/tools/testfiles/tlarge_objname.h5 index 707d7b6..9e26283 100644 Binary files a/tools/testfiles/tlarge_objname.h5 and b/tools/testfiles/tlarge_objname.h5 differ diff --git a/tools/testfiles/tlonglinks.h5 b/tools/testfiles/tlonglinks.h5 index f54e5f5..6c2cab4 100644 Binary files a/tools/testfiles/tlonglinks.h5 and b/tools/testfiles/tlonglinks.h5 differ diff --git a/tools/testfiles/tloop.h5 b/tools/testfiles/tloop.h5 index d7a2f47..e54f91c 100644 Binary files a/tools/testfiles/tloop.h5 and b/tools/testfiles/tloop.h5 differ diff --git a/tools/testfiles/tloop2.h5 b/tools/testfiles/tloop2.h5 index 995bfab..60d7ed2 100644 Binary files a/tools/testfiles/tloop2.h5 and b/tools/testfiles/tloop2.h5 differ diff --git a/tools/testfiles/tmulti-s.h5 b/tools/testfiles/tmulti-s.h5 index 3feae49..bc2fafb 100644 Binary files a/tools/testfiles/tmulti-s.h5 and b/tools/testfiles/tmulti-s.h5 differ diff --git a/tools/testfiles/tname-amp.h5 b/tools/testfiles/tname-amp.h5 index 27ab521..82f6316 100644 Binary files a/tools/testfiles/tname-amp.h5 and b/tools/testfiles/tname-amp.h5 differ diff --git a/tools/testfiles/tname-apos.h5 b/tools/testfiles/tname-apos.h5 index 42d0fc3..9b49159 100644 Binary files a/tools/testfiles/tname-apos.h5 and b/tools/testfiles/tname-apos.h5 differ diff --git a/tools/testfiles/tname-gt.h5 b/tools/testfiles/tname-gt.h5 index fabd154..1d2795e 100644 Binary files a/tools/testfiles/tname-gt.h5 and b/tools/testfiles/tname-gt.h5 differ diff --git a/tools/testfiles/tname-lt.h5 b/tools/testfiles/tname-lt.h5 index 6b13375..e3dafe0 100644 Binary files a/tools/testfiles/tname-lt.h5 and b/tools/testfiles/tname-lt.h5 differ diff --git a/tools/testfiles/tname-quot.h5 b/tools/testfiles/tname-quot.h5 index eb8d6cc..fd9e862 100644 Binary files a/tools/testfiles/tname-quot.h5 and b/tools/testfiles/tname-quot.h5 differ diff --git a/tools/testfiles/tname-sp.h5 b/tools/testfiles/tname-sp.h5 index 0201efd..514eb8d 100644 Binary files a/tools/testfiles/tname-sp.h5 and b/tools/testfiles/tname-sp.h5 differ diff --git a/tools/testfiles/tnestedcomp.h5 b/tools/testfiles/tnestedcomp.h5 index b777ee3..2912310 100644 Binary files a/tools/testfiles/tnestedcomp.h5 and b/tools/testfiles/tnestedcomp.h5 differ diff --git a/tools/testfiles/tnodata.h5 b/tools/testfiles/tnodata.h5 index 8e0a89d..1e537f1 100644 Binary files a/tools/testfiles/tnodata.h5 and b/tools/testfiles/tnodata.h5 differ diff --git a/tools/testfiles/tnullspace.h5 b/tools/testfiles/tnullspace.h5 index b5dac5d..d405061 100644 Binary files a/tools/testfiles/tnullspace.h5 and b/tools/testfiles/tnullspace.h5 differ diff --git a/tools/testfiles/tobjref.h5 b/tools/testfiles/tobjref.h5 index ef42ff3..ecf3827 100644 Binary files a/tools/testfiles/tobjref.h5 and b/tools/testfiles/tobjref.h5 differ diff --git a/tools/testfiles/topaque.h5 b/tools/testfiles/topaque.h5 index d56b594..669f4b7 100644 Binary files a/tools/testfiles/topaque.h5 and b/tools/testfiles/topaque.h5 differ diff --git a/tools/testfiles/tref-escapes-at.h5 b/tools/testfiles/tref-escapes-at.h5 index 641513c..e3f0d6b 100644 Binary files a/tools/testfiles/tref-escapes-at.h5 and b/tools/testfiles/tref-escapes-at.h5 differ diff --git a/tools/testfiles/tref-escapes.h5 b/tools/testfiles/tref-escapes.h5 index 6c7638b..766a840 100644 Binary files a/tools/testfiles/tref-escapes.h5 and b/tools/testfiles/tref-escapes.h5 differ diff --git a/tools/testfiles/tref.h5 b/tools/testfiles/tref.h5 index 73b4be5..3a9899a 100644 Binary files a/tools/testfiles/tref.h5 and b/tools/testfiles/tref.h5 differ diff --git a/tools/testfiles/tsaf.h5 b/tools/testfiles/tsaf.h5 index c84c5b6..75237ba 100644 Binary files a/tools/testfiles/tsaf.h5 and b/tools/testfiles/tsaf.h5 differ diff --git a/tools/testfiles/tslink.h5 b/tools/testfiles/tslink.h5 index 753b62d..ab80d8f 100644 Binary files a/tools/testfiles/tslink.h5 and b/tools/testfiles/tslink.h5 differ diff --git a/tools/testfiles/tsplit_file-m.h5 b/tools/testfiles/tsplit_file-m.h5 index a6eef73..d431c70 100644 Binary files a/tools/testfiles/tsplit_file-m.h5 and b/tools/testfiles/tsplit_file-m.h5 differ diff --git a/tools/testfiles/tstr.h5 b/tools/testfiles/tstr.h5 index af5384f..ae6a012 100644 Binary files a/tools/testfiles/tstr.h5 and b/tools/testfiles/tstr.h5 differ diff --git a/tools/testfiles/tstr2.h5 b/tools/testfiles/tstr2.h5 index d3b1588..b7d4802 100644 Binary files a/tools/testfiles/tstr2.h5 and b/tools/testfiles/tstr2.h5 differ diff --git a/tools/testfiles/tstr3.h5 b/tools/testfiles/tstr3.h5 index 9f9112f..727dec5 100644 Binary files a/tools/testfiles/tstr3.h5 and b/tools/testfiles/tstr3.h5 differ diff --git a/tools/testfiles/tstring-at.h5 b/tools/testfiles/tstring-at.h5 index aa17960..a477ee5 100644 Binary files a/tools/testfiles/tstring-at.h5 and b/tools/testfiles/tstring-at.h5 differ diff --git a/tools/testfiles/tstring.h5 b/tools/testfiles/tstring.h5 index 667fe78..914a464 100644 Binary files a/tools/testfiles/tstring.h5 and b/tools/testfiles/tstring.h5 differ diff --git a/tools/testfiles/tvldtypes1.h5 b/tools/testfiles/tvldtypes1.h5 index b5b2bd7..423dae8 100644 Binary files a/tools/testfiles/tvldtypes1.h5 and b/tools/testfiles/tvldtypes1.h5 differ diff --git a/tools/testfiles/tvldtypes2.h5 b/tools/testfiles/tvldtypes2.h5 index 65bf63f..86ba20d 100644 Binary files a/tools/testfiles/tvldtypes2.h5 and b/tools/testfiles/tvldtypes2.h5 differ diff --git a/tools/testfiles/tvldtypes3.h5 b/tools/testfiles/tvldtypes3.h5 index dd4aca7..66fd1d2 100644 Binary files a/tools/testfiles/tvldtypes3.h5 and b/tools/testfiles/tvldtypes3.h5 differ diff --git a/tools/testfiles/tvldtypes4.h5 b/tools/testfiles/tvldtypes4.h5 index 70dc73e..016ad55 100644 Binary files a/tools/testfiles/tvldtypes4.h5 and b/tools/testfiles/tvldtypes4.h5 differ diff --git a/tools/testfiles/tvldtypes5.h5 b/tools/testfiles/tvldtypes5.h5 index 776c020..71b924f 100644 Binary files a/tools/testfiles/tvldtypes5.h5 and b/tools/testfiles/tvldtypes5.h5 differ diff --git a/tools/testfiles/tvms.h5 b/tools/testfiles/tvms.h5 index 9c243ff..d3b0b7c 100644 Binary files a/tools/testfiles/tvms.h5 and b/tools/testfiles/tvms.h5 differ -- cgit v0.12