From d5a62239587f7cc5de301fa5c6b0919807689818 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Thu, 5 Apr 2012 21:57:06 -0500 Subject: [svn-r22254] Description: Bring r22085:22251 from trunk to revise_chunks branch. Also tackle some testing issues in test/objcopy.c test and clean up some warnings. Tested on: FreeBSD/32 8.2 (loyalty) w/gcc4.6, w/C++ & FORTRAN, in debug mode FreeBSD/64 8.2 (freedom) w/gcc4.6, w/C++ & FORTRAN, in debug mode Linux/32 2.6 (jam) w/PGI compilers, w/default API=1.8.x, w/C++ & FORTRAN, w/threadsafe, in debug mode Linux/64-amd64 2.6 (koala) w/Intel compilers, w/default API=1.6.x, w/C++ & FORTRAN, in production mode Solaris/32 2.10 (linew) w/deprecated symbols disabled, w/C++ & FORTRAN, w/szip filter, w/threadsafe, in production mode Linux/PPC 2.6 (ostrich) w/C++ & FORTRAN, w/threadsafe, in debug mode Linux/64-ia64 2.6 (ember) w/Intel compilers, w/paralle, C++ & FORTRAN, in production mode Mac OS X/32 10.7.3 (amazon) in debug mode Mac OS X/32 10.7.3 (amazon) w/C++ & FORTRAN, w/threadsafe, in production mode Mac OS X/32 10.7.3 (amazon) w/parallel, in debug mode --- CMakeLists.txt | 4 +- MANIFEST | 62 +- README.txt | 2 +- bin/trace | 2 + c++/COPYING | 0 c++/examples/run-c++-ex.sh.in | 0 c++/examples/testh5c++.sh.in | 0 c++/src/H5AtomType.cpp | 8 +- c++/src/H5Attribute.cpp | 25 +- c++/src/H5CommonFG.cpp | 58 +- c++/src/H5DataSet.cpp | 48 +- c++/src/H5DataSpace.cpp | 8 +- c++/src/H5DataType.cpp | 44 +- c++/src/H5DcreatProp.cpp | 8 +- c++/src/H5DxferProp.cpp | 4 +- c++/src/H5FaccProp.cpp | 66 +- c++/src/H5FcreatProp.cpp | 10 +- c++/src/H5File.cpp | 26 +- c++/src/H5Group.cpp | 30 +- c++/src/H5IdComponent.cpp | 10 +- c++/src/H5Library.cpp | 4 +- c++/src/H5Object.cpp | 24 +- c++/src/H5PredType.cpp | 8 +- c++/src/H5PredType.h | 17 +- c++/src/H5PropList.cpp | 2 +- c++/src/H5StrType.cpp | 4 +- c++/src/Makefile.in | 2 +- c++/src/h5c++.in | 2 +- c++/test/dsets.cpp | 75 + config/COPYING | 0 config/Makefile.am.blank | 0 config/cmake/CTestCustom.cmake | 3 +- config/cmake/ConfigureChecks.cmake | 16 +- config/cmake/FindSZIP.cmake | 18 +- config/cmake/H5pubconf.h.in | 3 + config/cmake/HDFLibMacros.cmake | 87 +- config/cmake/HDFMacros.cmake | 16 +- config/gnu-flags | 76 +- config/lt_vers.am | 2 +- configure | 56 +- configure.in | 37 +- examples/run-c-ex.sh.in | 0 examples/testh5cc.sh.in | 0 fortran/COPYING | 0 fortran/examples/run-fortran-ex.sh.in | 0 fortran/examples/testh5fc.sh.in | 0 fortran/src/H5Of.c | 57 + fortran/src/H5Off.f90 | 175 +- fortran/src/H5Pff.f90 | 35 +- fortran/src/H5f90proto.h | 7 +- fortran/src/Makefile.in | 2 +- fortran/src/h5fc.in | 2 +- fortran/src/hdf5_fortrandll.def | 1 + fortran/src/phdf5_fortrandll.def | 1 + fortran/test/CMakeLists.txt | 3 + fortran/test/tH5O.f90 | 256 +- hl/COPYING | 0 hl/Makefile.in | 0 hl/c++/COPYING | 0 hl/c++/examples/run-hlc++-ex.sh.in | 0 hl/c++/src/Makefile.in | 2 +- hl/examples/run-hlc-ex.sh.in | 0 hl/fortran/COPYING | 0 hl/fortran/examples/run-hlfortran-ex.sh.in | 0 hl/fortran/src/H5DSfc.c | 4 +- hl/fortran/src/H5DSff.f90 | 0 hl/fortran/src/H5IMfc.c | 0 hl/fortran/src/H5IMff.f90 | 0 hl/fortran/src/H5LTf90proto.h | 3 +- hl/fortran/src/H5LTfc.c | 32 +- hl/fortran/src/H5LTff.f90 | 16 +- hl/fortran/src/H5TBfc.c | 0 hl/fortran/src/H5TBff.f90 | 0 hl/fortran/src/Makefile.in | 2 +- hl/fortran/test/tstds.f90 | 10 +- hl/fortran/test/tstimage.f90 | 0 hl/fortran/test/tstlite.f90 | 53 +- hl/fortran/test/tsttable.f90 | 0 hl/src/COPYING | 0 hl/src/H5LT.c | 571 ++- hl/src/H5LTpublic.h | 18 + hl/src/Makefile.in | 2 +- hl/test/COPYING | 0 hl/test/Makefile.am | 5 +- hl/test/Makefile.in | 30 +- hl/test/h5hltest.h | 6 +- hl/test/test_file_image.c | 518 +++ hl/test/test_lite.c | 31 +- hl/tools/COPYING | 0 perform/COPYING | 0 release_docs/RELEASE.txt | 47 +- src/H5A.c | 30 + src/H5Aint.c | 10 + src/H5Apkg.h | 26 - src/H5Aprivate.h | 32 + src/H5Bcache.c | 4 + src/H5Dchunk.c | 2 +- src/H5Dcontig.c | 13 +- src/H5Dint.c | 3 +- src/H5Dio.c | 2 + src/H5Dlayout.c | 22 +- src/H5Doh.c | 50 +- src/H5E.c | 12 +- src/H5Edefin.h | 1 + src/H5Einit.h | 5 + src/H5Epubgen.h | 2 + src/H5Eterm.h | 3 +- src/H5F.c | 284 +- src/H5FD.c | 82 +- src/H5FDcore.c | 436 ++- src/H5FDfamily.c | 2 +- src/H5FDlog.c | 2 +- src/H5FDmpio.c | 94 + src/H5FDprivate.h | 30 +- src/H5FDpublic.h | 40 + src/H5FDsec2.c | 2 +- src/H5FDstdio.c | 670 ++-- src/H5FSprivate.h | 2 +- src/H5FSsection.c | 2 +- src/H5Fmpi.c | 82 + src/H5Fprivate.h | 5 +- src/H5Fpublic.h | 5 + src/H5Gname.c | 11 +- src/H5Goh.c | 3 +- src/H5HF.c | 33 - src/H5HFbtree2.c | 8 +- src/H5HFdbg.c | 195 +- src/H5HFhuge.c | 4 +- src/H5HFiblock.c | 146 +- src/H5HFpkg.h | 19 +- src/H5HFsection.c | 52 +- src/H5HFspace.c | 181 +- src/H5I.c | 144 +- src/H5Iprivate.h | 2 +- src/H5MF.c | 4 +- src/H5MFdbg.c | 4 +- src/H5O.c | 6 +- src/H5Oainfo.c | 14 +- src/H5Oattr.c | 1 + src/H5Oattribute.c | 22 +- src/H5Ocopy.c | 813 +++- src/H5Odtype.c | 38 + src/H5Oefl.c | 8 +- src/H5Ofill.c | 2 + src/H5Olayout.c | 8 +- src/H5Olinfo.c | 16 +- src/H5Olink.c | 16 +- src/H5Omessage.c | 6 +- src/H5Opkg.h | 15 +- src/H5Opline.c | 1 + src/H5Oprivate.h | 22 +- src/H5Opublic.h | 11 +- src/H5Osdspace.c | 1 + src/H5Oshared.c | 17 +- src/H5Oshared.h | 21 +- src/H5Ostab.c | 18 +- src/H5Ostorage.c | 8 +- src/H5Pdcpl.c | 2 +- src/H5Pfapl.c | 497 +++ src/H5Pint.c | 54 +- src/H5Pocpl.c | 0 src/H5Pocpypl.c | 447 ++- src/H5Ppkg.h | 1 + src/H5Ppublic.h | 11 + src/H5Ptest.c | 52 +- src/H5SM.c | 5 +- src/H5SMbtree2.c | 0 src/H5SMpkg.h | 0 src/H5SMprivate.h | 0 src/H5T.c | 3 +- src/H5Toh.c | 3 +- src/H5Ztrans.c | 174 +- src/H5err.txt | 1 + src/H5private.h | 2 + src/H5public.h | 4 +- src/H5win32defs.h | 6 +- src/Makefile.am | 0 src/Makefile.in | 2 +- src/hdf5.lnt | 0 test/CMakeLists.txt | 3 + test/COPYING | 0 test/Makefile.am | 4 +- test/Makefile.in | 69 +- test/corrupt_stab_msg.h5 | Bin test/cross_read.c | 0 test/fheap.c | 145 +- test/file_image.c | 1335 +++++++ test/file_image_core_test.h5 | Bin 0 -> 18528 bytes test/gen_cross.c | 0 test/gen_file_image.c | 91 + test/istore.c | 71 +- test/objcopy.c | 4058 +++++++++++++++++++- test/reserved.c | 0 test/swmr_sparse_writer.c | 2 +- testpar/CMakeLists.txt | 1 + testpar/COPYING | 0 testpar/Makefile.am | 4 +- testpar/Makefile.in | 12 +- testpar/t_dset.c | 325 ++ testpar/t_file_image.c | 395 ++ testpar/testphdf5.c | 19 + testpar/testphdf5.h | 4 + tools/COPYING | 0 tools/h5diff/CMakeLists.txt | 30 + tools/h5diff/h5diffgentest.c | 263 +- tools/h5diff/testfiles/h5diff_101w.txt | 0 tools/h5diff/testfiles/h5diff_102w.txt | 0 tools/h5diff/testfiles/h5diff_20.txt | 2 +- tools/h5diff/testfiles/h5diff_21.txt | 2 +- tools/h5diff/testfiles/h5diff_22.txt | 2 +- tools/h5diff/testfiles/h5diff_222.txt | 3 + tools/h5diff/testfiles/h5diff_223.txt | 4 + tools/h5diff/testfiles/h5diff_224.txt | 4 + tools/h5diff/testfiles/h5diff_300.txt | 0 tools/h5diff/testfiles/h5diff_485.txt | 11 + tools/h5diff/testfiles/h5diff_486.txt | 11 + tools/h5diff/testfiles/h5diff_487.txt | 12 + tools/h5diff/testfiles/h5diff_505.txt | 2 +- tools/h5diff/testfiles/h5diff_507.txt | 2 +- tools/h5diff/testfiles/h5diff_509.txt | 2 +- tools/h5diff/testfiles/h5diff_515.txt | 7 +- tools/h5diff/testfiles/h5diff_517.txt | 7 +- .../h5diff/testfiles/h5diff_enum_invalid_values.h5 | Bin tools/h5diff/testfiles/h5diff_exclude3-1.h5 | Bin 0 -> 4792 bytes tools/h5diff/testfiles/h5diff_exclude3-2.h5 | Bin 0 -> 2176 bytes tools/h5diff/testfiles/h5diff_links.h5 | Bin tools/h5diff/testfiles/non_comparables1.h5 | Bin 6568 -> 8628 bytes tools/h5diff/testfiles/non_comparables2.h5 | Bin 6584 -> 8644 bytes tools/h5diff/testh5diff.sh | 22 + tools/h5dump/h5dump.c | 7 + tools/h5dump/h5dumpgentest.c | 2 +- tools/h5dump/testh5dump.sh.in | 6 +- tools/h5dump/testh5dumpxml.sh.in | 0 tools/h5import/Makefile.in | 0 tools/h5import/h5import.c | 0 tools/h5import/h5import.h | 0 tools/h5import/h5importtest.c | 0 tools/h5import/testfiles/binfp64.conf | 0 tools/h5import/testfiles/binin16.conf | 0 tools/h5import/testfiles/binin32.conf | 0 tools/h5import/testfiles/binin8.conf | 0 tools/h5import/testfiles/binuin16.conf | 0 tools/h5import/testfiles/binuin32.conf | 0 tools/h5import/testfiles/txtfp32.conf | 0 tools/h5import/testfiles/txtfp32.txt | 0 tools/h5import/testfiles/txtfp64.conf | 0 tools/h5import/testfiles/txtfp64.txt | 0 tools/h5import/testfiles/txtin16.conf | 0 tools/h5import/testfiles/txtin32.conf | 0 tools/h5import/testfiles/txtin8.conf | 0 tools/h5import/testfiles/txtuin16.conf | 0 tools/h5import/testfiles/txtuin32.conf | 0 tools/h5import/testfiles/txtuin32.txt | 0 tools/h5jam/testfiles/u10.txt | 0 tools/h5jam/testfiles/u511.txt | 0 tools/h5jam/testfiles/u512.txt | 0 tools/h5jam/testfiles/u513.txt | 0 tools/h5ls/testh5ls.sh.in | 40 +- tools/h5repack/CMakeLists.txt | 70 +- tools/h5repack/h5repack.c | 5 +- tools/h5repack/h5repack.h | 5 +- tools/h5repack/h5repack.sh.in | 61 +- tools/h5repack/h5repack_copy.c | 154 +- tools/h5repack/h5repack_main.c | 70 +- tools/h5repack/h5repacktst.c | 181 +- tools/h5stat/h5stat.c | 281 +- tools/lib/h5diff.c | 395 +- tools/lib/h5diff.h | 2 +- tools/lib/h5tools.c | 2 +- tools/misc/h5cc.in | 2 +- tools/misc/h5redeploy.in | 0 tools/testfiles/h5dump-help.txt | 7 + tools/testfiles/tnofilename-with-packed-bits.ddl | 7 + tools/testfiles/tpbitsIncomplete.ddl | 7 + tools/testfiles/tpbitsLengthExceeded.ddl | 7 + tools/testfiles/tpbitsLengthPositive.ddl | 7 + tools/testfiles/tpbitsMaxExceeded.ddl | 7 + tools/testfiles/tpbitsOffsetExceeded.ddl | 7 + tools/testfiles/tpbitsOffsetNegative.ddl | 7 + vms/COPYING | 0 vms/src/h5pubconf.h | 6 +- windows/COPYING | 0 windows/examples/testExamples_exp_output.txt | 0 windows/src/H5pubconf.h | 6 +- 284 files changed, 13632 insertions(+), 2488 deletions(-) mode change 100755 => 100644 c++/COPYING mode change 100755 => 100644 c++/examples/run-c++-ex.sh.in mode change 100755 => 100644 c++/examples/testh5c++.sh.in mode change 100755 => 100644 c++/src/h5c++.in mode change 100755 => 100644 config/COPYING mode change 100755 => 100644 config/Makefile.am.blank mode change 100755 => 100644 examples/run-c-ex.sh.in mode change 100755 => 100644 examples/testh5cc.sh.in mode change 100755 => 100644 fortran/COPYING mode change 100755 => 100644 fortran/examples/run-fortran-ex.sh.in mode change 100755 => 100644 fortran/examples/testh5fc.sh.in mode change 100755 => 100644 fortran/src/h5fc.in mode change 100755 => 100644 hl/COPYING mode change 100755 => 100644 hl/Makefile.in mode change 100755 => 100644 hl/c++/COPYING mode change 100755 => 100644 hl/c++/examples/run-hlc++-ex.sh.in mode change 100755 => 100644 hl/examples/run-hlc-ex.sh.in mode change 100755 => 100644 hl/fortran/COPYING mode change 100755 => 100644 hl/fortran/examples/run-hlfortran-ex.sh.in mode change 100755 => 100644 hl/fortran/src/H5DSfc.c mode change 100755 => 100644 hl/fortran/src/H5DSff.f90 mode change 100755 => 100644 hl/fortran/src/H5IMfc.c mode change 100755 => 100644 hl/fortran/src/H5IMff.f90 mode change 100755 => 100644 hl/fortran/src/H5LTf90proto.h mode change 100755 => 100644 hl/fortran/src/H5LTfc.c mode change 100755 => 100644 hl/fortran/src/H5LTff.f90 mode change 100755 => 100644 hl/fortran/src/H5TBfc.c mode change 100755 => 100644 hl/fortran/src/H5TBff.f90 mode change 100755 => 100644 hl/fortran/test/tstimage.f90 mode change 100755 => 100644 hl/fortran/test/tsttable.f90 mode change 100755 => 100644 hl/src/COPYING mode change 100755 => 100644 hl/test/COPYING create mode 100644 hl/test/test_file_image.c mode change 100755 => 100644 hl/tools/COPYING mode change 100755 => 100644 perform/COPYING mode change 100755 => 100644 src/H5Pocpl.c mode change 100755 => 100644 src/H5Pocpypl.c mode change 100755 => 100644 src/H5SM.c mode change 100755 => 100644 src/H5SMbtree2.c mode change 100755 => 100644 src/H5SMpkg.h mode change 100755 => 100644 src/H5SMprivate.h mode change 100755 => 100644 src/Makefile.am mode change 100755 => 100644 src/hdf5.lnt mode change 100755 => 100644 test/COPYING mode change 100755 => 100644 test/corrupt_stab_msg.h5 mode change 100755 => 100644 test/cross_read.c create mode 100644 test/file_image.c create mode 100644 test/file_image_core_test.h5 mode change 100755 => 100644 test/gen_cross.c create mode 100644 test/gen_file_image.c mode change 100755 => 100644 test/objcopy.c mode change 100755 => 100644 test/reserved.c mode change 100755 => 100644 testpar/COPYING create mode 100644 testpar/t_file_image.c mode change 100755 => 100644 tools/COPYING mode change 100755 => 100644 tools/h5diff/testfiles/h5diff_101w.txt mode change 100755 => 100644 tools/h5diff/testfiles/h5diff_102w.txt create mode 100644 tools/h5diff/testfiles/h5diff_223.txt create mode 100644 tools/h5diff/testfiles/h5diff_224.txt mode change 100755 => 100644 tools/h5diff/testfiles/h5diff_300.txt create mode 100644 tools/h5diff/testfiles/h5diff_485.txt create mode 100644 tools/h5diff/testfiles/h5diff_486.txt create mode 100644 tools/h5diff/testfiles/h5diff_487.txt mode change 100755 => 100644 tools/h5diff/testfiles/h5diff_enum_invalid_values.h5 create mode 100644 tools/h5diff/testfiles/h5diff_exclude3-1.h5 create mode 100644 tools/h5diff/testfiles/h5diff_exclude3-2.h5 mode change 100755 => 100644 tools/h5diff/testfiles/h5diff_links.h5 mode change 100755 => 100644 tools/h5dump/testh5dumpxml.sh.in mode change 100755 => 100644 tools/h5import/Makefile.in mode change 100755 => 100644 tools/h5import/h5import.c mode change 100755 => 100644 tools/h5import/h5import.h mode change 100755 => 100644 tools/h5import/h5importtest.c mode change 100755 => 100644 tools/h5import/testfiles/binfp64.conf mode change 100755 => 100644 tools/h5import/testfiles/binin16.conf mode change 100755 => 100644 tools/h5import/testfiles/binin32.conf mode change 100755 => 100644 tools/h5import/testfiles/binin8.conf mode change 100755 => 100644 tools/h5import/testfiles/binuin16.conf mode change 100755 => 100644 tools/h5import/testfiles/binuin32.conf mode change 100755 => 100644 tools/h5import/testfiles/txtfp32.conf mode change 100755 => 100644 tools/h5import/testfiles/txtfp32.txt mode change 100755 => 100644 tools/h5import/testfiles/txtfp64.conf mode change 100755 => 100644 tools/h5import/testfiles/txtfp64.txt mode change 100755 => 100644 tools/h5import/testfiles/txtin16.conf mode change 100755 => 100644 tools/h5import/testfiles/txtin32.conf mode change 100755 => 100644 tools/h5import/testfiles/txtin8.conf mode change 100755 => 100644 tools/h5import/testfiles/txtuin16.conf mode change 100755 => 100644 tools/h5import/testfiles/txtuin32.conf mode change 100755 => 100644 tools/h5import/testfiles/txtuin32.txt mode change 100755 => 100644 tools/h5jam/testfiles/u10.txt mode change 100755 => 100644 tools/h5jam/testfiles/u511.txt mode change 100755 => 100644 tools/h5jam/testfiles/u512.txt mode change 100755 => 100644 tools/h5jam/testfiles/u513.txt mode change 100755 => 100644 tools/h5repack/h5repack.sh.in mode change 100755 => 100644 tools/misc/h5cc.in mode change 100755 => 100644 tools/misc/h5redeploy.in mode change 100755 => 100644 vms/COPYING mode change 100755 => 100644 windows/COPYING mode change 100755 => 100644 windows/examples/testExamples_exp_output.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index fe8a5f8..5543b48 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -919,6 +919,7 @@ IF (NOT HDF5_EXTERNALLY_CONFIGURED AND NOT HDF5_NO_PACKAGES) SET (CPACK_PACKAGE_VENDOR "HDF Group") SET (CPACK_PACKAGE_NAME "${HDF5_PACKAGE_NAME}") SET (CPACK_PACKAGE_INSTALL_DIRECTORY "${HDF5_PACKAGE_NAME}") + SET (CPACK_PACKAGE_INSTALL_REGISTRY_KEY "${HDF5_PACKAGE_NAME}-${HDF5_PACKAGE_VERSION}-${LIB_TYPE}") SET (CPACK_PACKAGE_VERSION "${HDF5_PACKAGE_VERSION}") SET (CPACK_PACKAGE_VERSION_MAJOR "${HDF5_PACKAGE_VERSION_MAJOR}") SET (CPACK_PACKAGE_VERSION_MINOR "${HDF5_PACKAGE_VERSION_MINOR}") @@ -935,8 +936,9 @@ IF (NOT HDF5_EXTERNALLY_CONFIGURED AND NOT HDF5_NO_PACKAGES) SET (CPACK_NSIS_PACKAGE_NAME "HDF5 ${HDF5_PACKAGE_VERSION}") ELSE (WIN32) SET (CPACK_RPM_COMPONENT_INSTALL ON) + SET (CPACK_ARCHIVE_COMPONENT_INSTALL ON) + SET (CPACK_COMPONENTS_ALL_IN_ONE_PACKAGE ON) ENDIF (WIN32) - SET (CPACK_MONOLITHIC_INSTALL ON) INCLUDE(InstallRequiredSystemLibraries) diff --git a/MANIFEST b/MANIFEST index 24da67a..f598e25 100644 --- a/MANIFEST +++ b/MANIFEST @@ -972,34 +972,37 @@ ./test/filespace_1_8.h5 ./test/filespace_1_6.h5 ./test/freespace.c +./test/file_image.c +./test/file_image_core_test.h5 ./test/fill_old.h5 ./test/fillval.c ./test/filter_fail.c ./test/flush1.c ./test/flush2.c ./test/flushrefresh.c -./test/gen_bad_ohdr.c _DO_NOT_DISTRIBUTE_ -./test/gen_bad_compound.c _DO_NOT_DISTRIBUTE_ -./test/gen_bogus.c _DO_NOT_DISTRIBUTE_ -./test/gen_cross.c _DO_NOT_DISTRIBUTE_ -./test/gen_deflate.c _DO_NOT_DISTRIBUTE_ -./test/gen_filespace.c _DO_NOT_DISTRIBUTE_ -./test/gen_idx.c _DO_NOT_DISTRIBUTE_ -./test/gen_mergemsg.c _DO_NOT_DISTRIBUTE_ -./test/gen_new_array.c _DO_NOT_DISTRIBUTE_ -./test/gen_new_fill.c _DO_NOT_DISTRIBUTE_ -./test/gen_new_group.c _DO_NOT_DISTRIBUTE_ -./test/gen_new_mtime.c _DO_NOT_DISTRIBUTE_ -./test/gen_new_super.c _DO_NOT_DISTRIBUTE_ -./test/gen_noencoder.c _DO_NOT_DISTRIBUTE_ -./test/gen_nullspace.c _DO_NOT_DISTRIBUTE_ -./test/gen_old_array.c _DO_NOT_DISTRIBUTE_ -./test/gen_old_group.c _DO_NOT_DISTRIBUTE_ -./test/gen_old_layout.c _DO_NOT_DISTRIBUTE_ -./test/gen_old_mtime.c _DO_NOT_DISTRIBUTE_ -./test/gen_sizes_lheap.c _DO_NOT_DISTRIBUTE_ -./test/gen_specmetaread.c _DO_NOT_DISTRIBUTE_ -./test/gen_udlinks.c _DO_NOT_DISTRIBUTE_ +./test/gen_bad_ohdr.c _DO_NOT_DISTRIBUTE_ +./test/gen_bad_compound.c _DO_NOT_DISTRIBUTE_ +./test/gen_bogus.c _DO_NOT_DISTRIBUTE_ +./test/gen_cross.c _DO_NOT_DISTRIBUTE_ +./test/gen_deflate.c _DO_NOT_DISTRIBUTE_ +./test/gen_file_image.c _DO_NOT_DISTRIBUTE_ +./test/gen_filespace.c _DO_NOT_DISTRIBUTE_ +./test/gen_idx.c _DO_NOT_DISTRIBUTE_ +./test/gen_mergemsg.c _DO_NOT_DISTRIBUTE_ +./test/gen_new_array.c _DO_NOT_DISTRIBUTE_ +./test/gen_new_fill.c _DO_NOT_DISTRIBUTE_ +./test/gen_new_group.c _DO_NOT_DISTRIBUTE_ +./test/gen_new_mtime.c _DO_NOT_DISTRIBUTE_ +./test/gen_new_super.c _DO_NOT_DISTRIBUTE_ +./test/gen_noencoder.c _DO_NOT_DISTRIBUTE_ +./test/gen_nullspace.c _DO_NOT_DISTRIBUTE_ +./test/gen_old_array.c _DO_NOT_DISTRIBUTE_ +./test/gen_old_group.c _DO_NOT_DISTRIBUTE_ +./test/gen_old_layout.c _DO_NOT_DISTRIBUTE_ +./test/gen_old_mtime.c _DO_NOT_DISTRIBUTE_ +./test/gen_sizes_lheap.c _DO_NOT_DISTRIBUTE_ +./test/gen_specmetaread.c _DO_NOT_DISTRIBUTE_ +./test/gen_udlinks.c _DO_NOT_DISTRIBUTE_ ./test/getname.c ./test/gheap.c ./test/group_old.h5 @@ -1101,6 +1104,7 @@ ./testpar/t_cache.c ./testpar/t_dset.c ./testpar/t_file.c +./testpar/t_file_image.c ./testpar/t_mdset.c ./testpar/t_mpi.c ./testpar/t_ph5basic.c @@ -1838,6 +1842,8 @@ ./tools/h5diff/testfiles/h5diff_220.txt ./tools/h5diff/testfiles/h5diff_221.txt ./tools/h5diff/testfiles/h5diff_222.txt +./tools/h5diff/testfiles/h5diff_223.txt +./tools/h5diff/testfiles/h5diff_224.txt ./tools/h5diff/testfiles/h5diff_300.txt ./tools/h5diff/testfiles/h5diff_400.txt ./tools/h5diff/testfiles/h5diff_401.txt @@ -1886,6 +1892,9 @@ ./tools/h5diff/testfiles/h5diff_482.txt ./tools/h5diff/testfiles/h5diff_483.txt ./tools/h5diff/testfiles/h5diff_484.txt +./tools/h5diff/testfiles/h5diff_485.txt +./tools/h5diff/testfiles/h5diff_486.txt +./tools/h5diff/testfiles/h5diff_487.txt ./tools/h5diff/testfiles/h5diff_500.txt ./tools/h5diff/testfiles/h5diff_501.txt ./tools/h5diff/testfiles/h5diff_502.txt @@ -1942,6 +1951,8 @@ ./tools/h5diff/testfiles/h5diff_exclude1-2.h5 ./tools/h5diff/testfiles/h5diff_exclude2-1.h5 ./tools/h5diff/testfiles/h5diff_exclude2-2.h5 +./tools/h5diff/testfiles/h5diff_exclude3-1.h5 +./tools/h5diff/testfiles/h5diff_exclude3-2.h5 ./tools/h5diff/testfiles/h5diff_comp_vl_strs.h5 ./tools/h5diff/testfiles/h5diff_dset_zero_dim_size1.h5 ./tools/h5diff/testfiles/h5diff_dset_zero_dim_size2.h5 @@ -1986,12 +1997,12 @@ ./tools/h5jam/getub.c # test files for jam -./tools/h5jam/testfiles/twithub.h5 -./tools/h5jam/testfiles/twithub513.h5 ./tools/h5jam/testfiles/h5jam-help.txt ./tools/h5jam/testfiles/h5unjam-help.txt -./tools/h5jam/testfiles/u10.txt ./tools/h5jam/testfiles/tall.h5 +./tools/h5jam/testfiles/twithub.h5 +./tools/h5jam/testfiles/twithub513.h5 +./tools/h5jam/testfiles/u10.txt ./tools/h5jam/testfiles/u511.txt ./tools/h5jam/testfiles/u512.txt ./tools/h5jam/testfiles/u513.txt @@ -2102,6 +2113,7 @@ ./hl/test/pal_rgb.h ./hl/test/sepia.pal ./hl/test/test_ds.c +./hl/test/test_file_image.c ./hl/test/test_image.c ./hl/test/test_ld.c ./hl/test/test_ld.h5 diff --git a/README.txt b/README.txt index 31e8024..54356a8 100644 --- a/README.txt +++ b/README.txt @@ -1,4 +1,4 @@ -HDF5 version 1.9.111-FA_a5 currently under development +HDF5 version 1.9.113-FA_a5 currently under development Please refer to the release_docs/INSTALL file for installation instructions. ------------------------------------------------------------------------------ diff --git a/bin/trace b/bin/trace index bfaae19..a35e106 100755 --- a/bin/trace +++ b/bin/trace @@ -109,6 +109,7 @@ $Source = ""; "H5FD_t" => "x", "H5FD_class_t" => "x", "H5FD_stream_fapl_t" => "x", + "H5FD_file_image_callbacks_t" => "x", "H5G_iterate_t" => "x", "H5G_info_t" => "x", "H5I_free_t" => "x", @@ -119,6 +120,7 @@ $Source = ""; "H5MM_free_t" => "x", "H5O_info_t" => "x", "H5O_iterate_t" => "x", + "H5O_mcdt_search_cb_t" => "x", "H5P_cls_create_func_t" => "x", "H5P_cls_copy_func_t" => "x", "H5P_cls_close_func_t" => "x", diff --git a/c++/COPYING b/c++/COPYING old mode 100755 new mode 100644 diff --git a/c++/examples/run-c++-ex.sh.in b/c++/examples/run-c++-ex.sh.in old mode 100755 new mode 100644 diff --git a/c++/examples/testh5c++.sh.in b/c++/examples/testh5c++.sh.in old mode 100755 new mode 100644 diff --git a/c++/src/H5AtomType.cpp b/c++/src/H5AtomType.cpp index 773fc5d..975cad6 100644 --- a/c++/src/H5AtomType.cpp +++ b/c++/src/H5AtomType.cpp @@ -98,7 +98,7 @@ H5T_order_t AtomType::getOrder() const //-------------------------------------------------------------------------- // Function: AtomType::getOrder ///\brief This is an overloaded member function, provided for convenience. -/// It takes a reference to a \c std::string for the buffer that +/// It takes a reference to a \c H5std_string for the buffer that /// provide the text description of the returned byte order. /// The text description can be either of the following: /// "Little endian byte ordering (0)"; @@ -178,7 +178,7 @@ size_t AtomType::getPrecision() const ///\exception H5::DataTypeIException ///\par Description /// For information, please see C layer Reference Manuat at: -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5T.html#Datatype-SetPrecision +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5T.html#Datatype-SetPrecision // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- void AtomType::setPrecision( size_t precision ) const @@ -198,7 +198,7 @@ void AtomType::setPrecision( size_t precision ) const ///\exception H5::DataTypeIException ///\par Description /// For information, please see C layer Reference Manuat at: -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5T.html#Datatype-GetOffset +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5T.html#Datatype-GetOffset // Programmer Binh-Minh Ribler - 2000 // Modification // 12/05/00: due to C API change @@ -225,7 +225,7 @@ int AtomType::getOffset() const ///\exception H5::DataTypeIException ///\par Description /// For information, please see C layer Reference Manuat at: -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5T.html#Datatype-SetOffset +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5T.html#Datatype-SetOffset // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- void AtomType::setOffset( size_t offset ) const diff --git a/c++/src/H5Attribute.cpp b/c++/src/H5Attribute.cpp index dad347f..226ae5c 100644 --- a/c++/src/H5Attribute.cpp +++ b/c++/src/H5Attribute.cpp @@ -198,7 +198,7 @@ void Attribute::read(const DataType& mem_type, H5std_string& strg) const //-------------------------------------------------------------------------- size_t Attribute::getInMemDataSize() const { - char *func = "Attribute::getInMemDataSize"; + const char *func = "Attribute::getInMemDataSize"; // Get the data type of this attribute hid_t mem_type_id = H5Aget_type(id); @@ -207,7 +207,8 @@ size_t Attribute::getInMemDataSize() const throw AttributeIException(func, "H5Aget_type failed"); } - // Get the data type's size + // Get the data type's size by first getting its native type then getting + // the native type's size. hid_t native_type = H5Tget_native_type(mem_type_id, H5T_DIR_DEFAULT); if (native_type < 0) { @@ -219,7 +220,18 @@ size_t Attribute::getInMemDataSize() const throw AttributeIException(func, "H5Tget_size failed"); } - // Get number of elements of the attribute + // Close the native type and the datatype of this attribute. + if (H5Tclose(native_type) < 0) + { + throw DataSetIException(func, "H5Tclose(native_type) failed"); + } + if (H5Tclose(mem_type_id) < 0) + { + throw DataSetIException(func, "H5Tclose(mem_type_id) failed"); + } + + // Get number of elements of the attribute by first getting its dataspace + // then getting the number of elements in the dataspace hid_t space_id = H5Aget_space(id); if (space_id < 0) { @@ -231,6 +243,12 @@ size_t Attribute::getInMemDataSize() const throw AttributeIException(func, "H5Sget_simple_extent_npoints failed"); } + // Close the dataspace + if (H5Sclose(space_id) < 0) + { + throw DataSetIException(func, "H5Sclose failed"); + } + // Calculate and return the size of the data size_t data_size = type_size * num_elements; return(data_size); @@ -451,7 +469,6 @@ void Attribute::p_read_fixed_len(const DataType& mem_type, H5std_string& strg) c //-------------------------------------------------------------------------- void Attribute::p_read_variable_len(const DataType& mem_type, H5std_string& strg) const { - // Prepare and call C API to read attribute. char *strg_C; diff --git a/c++/src/H5CommonFG.cpp b/c++/src/H5CommonFG.cpp index 5b93bd5..6a8609f 100644 --- a/c++/src/H5CommonFG.cpp +++ b/c++/src/H5CommonFG.cpp @@ -31,7 +31,7 @@ #include "H5DataSet.h" #include "H5File.h" #include "H5Alltypes.h" -#include "H5private.h" // for HDstrcpy +#include "H5private.h" // for HDstrcpy // There are a few comments that are common to most of the functions // defined in this file so they are listed here. @@ -101,7 +101,7 @@ Group CommonFG::createGroup( const char* name, size_t size_hint ) const // Function: CommonFG::createGroup ///\brief This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes an -/// \c std::string for \a name. +/// \c H5std_string for \a name. // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- Group CommonFG::createGroup( const H5std_string& name, size_t size_hint ) const @@ -139,7 +139,7 @@ Group CommonFG::openGroup( const char* name ) const // Function: CommonFG::openGroup ///\brief This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes an -/// \c std::string for \a name. +/// \c H5std_string for \a name. // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- Group CommonFG::openGroup( const H5std_string& name ) const @@ -183,7 +183,7 @@ DataSet CommonFG::createDataSet( const char* name, const DataType& data_type, co // Function: CommonFG::createDataSet ///\brief This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes an -/// \c std::string for \a name. +/// \c H5std_string for \a name. // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- DataSet CommonFG::createDataSet( const H5std_string& name, const DataType& data_type, const DataSpace& data_space, const DSetCreatPropList& create_plist ) const @@ -218,7 +218,7 @@ DataSet CommonFG::openDataSet( const char* name ) const // Function: CommonFG::openDataSet ///\brief This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes an -/// \c std::string for \a name. +/// \c H5std_string for \a name. // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- DataSet CommonFG::openDataSet( const H5std_string& name ) const @@ -275,7 +275,7 @@ void CommonFG::link( H5L_type_t link_type, const char* curr_name, const char* ne // Function: CommonFG::link ///\brief This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes an -/// \c std::string for \a curr_name and \a new_name. +/// \c H5std_string for \a curr_name and \a new_name. // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- void CommonFG::link( H5L_type_t link_type, const H5std_string& curr_name, const H5std_string& new_name ) const @@ -305,7 +305,7 @@ void CommonFG::unlink( const char* name ) const // Function: CommonFG::unlink ///\brief This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes an -/// \c std::string for \a name. +/// \c H5std_string for \a name. // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- void CommonFG::unlink( const H5std_string& name ) const @@ -322,8 +322,8 @@ void CommonFG::unlink( const H5std_string& name ) const ///\note /// Exercise care in moving groups as it is possible to render /// data in a file inaccessible with Group::move. Please refer -/// to the Group Interface in the HDF5 User's Guide at: -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/Groups.html +/// to the Group Interface in the HDF5 User's Guide for details at: +/// http://www.hdfgroup.org/HDF5/doc/UG/UG_frame09Groups.html // Programmer Binh-Minh Ribler - 2000 // Modification // 2007: QAK modified to use H5L APIs - BMR @@ -341,7 +341,7 @@ void CommonFG::move( const char* src, const char* dst ) const // Function: CommonFG::move ///\brief This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes an -/// \c std::string for \a src and \a dst. +/// \c H5std_string for \a src and \a dst. // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- void CommonFG::move( const H5std_string& src, const H5std_string& dst ) const @@ -360,7 +360,7 @@ void CommonFG::move( const H5std_string& src, const H5std_string& dst ) const ///\par Description /// For more information, please refer to the C layer Reference /// Manual at: -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5G.html#Group-GetObjinfo +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5G.html#Group-GetObjinfo // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- void CommonFG::getObjinfo( const char* name, hbool_t follow_link, H5G_stat_t& statbuf ) const @@ -376,7 +376,7 @@ void CommonFG::getObjinfo( const char* name, hbool_t follow_link, H5G_stat_t& st // Function: CommonFG::getObjinfo ///\brief This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes an -/// \c std::string for \a name. +/// \c H5std_string for \a name. // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- void CommonFG::getObjinfo( const H5std_string& name, hbool_t follow_link, H5G_stat_t& statbuf ) const @@ -405,7 +405,7 @@ void CommonFG::getObjinfo( const char* name, H5G_stat_t& statbuf ) const // Function: CommonFG::getObjinfo ///\brief This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes an -/// \c std::string for \a name. +/// \c H5std_string for \a name. // Programmer Binh-Minh Ribler - Nov, 2005 //-------------------------------------------------------------------------- void CommonFG::getObjinfo( const H5std_string& name, H5G_stat_t& statbuf ) const @@ -462,7 +462,7 @@ H5std_string CommonFG::getLinkval( const char* name, size_t size ) const // Function: CommonFG::getLinkval ///\brief This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes an -/// \c std::string for \a name. +/// \c H5std_string for \a name. // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- H5std_string CommonFG::getLinkval( const H5std_string& name, size_t size ) const @@ -503,7 +503,7 @@ void CommonFG::setComment( const char* name, const char* comment ) const // Function: CommonFG::setComment ///\brief This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes an -/// \c std::string for \a name and \a comment. +/// \c H5std_string for \a name and \a comment. // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- void CommonFG::setComment( const H5std_string& name, const H5std_string& comment ) const @@ -535,7 +535,7 @@ void CommonFG::removeComment(const char* name) const // Function: CommonFG::removeComment ///\brief This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes an -/// \c std::string for \a name. +/// \c H5std_string for \a name. // Programmer Binh-Minh Ribler - May 2005 //-------------------------------------------------------------------------- void CommonFG::removeComment(const H5std_string& name) const @@ -596,7 +596,7 @@ H5std_string CommonFG::getComment( const char* name, size_t bufsize ) const // Function: CommonFG::getComment ///\brief This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes an -/// \c std::string for \a name. +/// \c H5std_string for \a name. // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- H5std_string CommonFG::getComment( const H5std_string& name, size_t bufsize ) const @@ -633,7 +633,7 @@ void CommonFG::mount( const char* name, H5File& child, PropList& plist ) const // Function: CommonFG::mount ///\brief This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes an -/// \c std::string for \a name. +/// \c H5std_string for \a name. // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- void CommonFG::mount( const H5std_string& name, H5File& child, PropList& plist ) const @@ -664,7 +664,7 @@ void CommonFG::unmount( const char* name ) const // Function: CommonFG::unmount ///\brief This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes an -/// \c std::string for \a name. +/// \c H5std_string for \a name. // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- void CommonFG::unmount( const H5std_string& name ) const @@ -699,7 +699,7 @@ DataType CommonFG::openDataType( const char* name ) const // Function: CommonFG::openDataType ///\brief This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes an -/// \c std::string for \a name. +/// \c H5std_string for \a name. // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- DataType CommonFG::openDataType( const H5std_string& name ) const @@ -734,7 +734,7 @@ ArrayType CommonFG::openArrayType( const char* name ) const // Function: CommonFG::openArrayType ///\brief This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes an -/// \c std::string for \a name. +/// \c H5std_string for \a name. // Programmer Binh-Minh Ribler - Jul, 2005 //-------------------------------------------------------------------------- ArrayType CommonFG::openArrayType( const H5std_string& name ) const @@ -769,7 +769,7 @@ CompType CommonFG::openCompType( const char* name ) const // Function: CommonFG::openCompType ///\brief This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes an -/// \c std::string for \a name. +/// \c H5std_string for \a name. // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- CompType CommonFG::openCompType( const H5std_string& name ) const @@ -804,7 +804,7 @@ EnumType CommonFG::openEnumType( const char* name ) const // Function: CommonFG::openEnumType ///\brief This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes an -/// \c std::string for \a name. +/// \c H5std_string for \a name. // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- EnumType CommonFG::openEnumType( const H5std_string& name ) const @@ -839,7 +839,7 @@ IntType CommonFG::openIntType( const char* name ) const // Function: CommonFG::openIntType ///\brief This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes an -/// \c std::string for \a name. +/// \c H5std_string for \a name. // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- IntType CommonFG::openIntType( const H5std_string& name ) const @@ -874,7 +874,7 @@ FloatType CommonFG::openFloatType( const char* name ) const // Function: CommonFG::openFloatType ///\brief This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes an -/// \c std::string for \a name. +/// \c H5std_string for \a name. // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- FloatType CommonFG::openFloatType( const H5std_string& name ) const @@ -909,7 +909,7 @@ StrType CommonFG::openStrType( const char* name ) const // Function: CommonFG::openStrType ///\brief This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes an -/// \c std::string for \a name. +/// \c H5std_string for \a name. // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- StrType CommonFG::openStrType( const H5std_string& name ) const @@ -944,7 +944,7 @@ VarLenType CommonFG::openVarLenType( const char* name ) const // Function: CommonFG::openVarLenType ///\brief This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes an -/// \c std::string for \a name. +/// \c H5std_string for \a name. // Programmer Binh-Minh Ribler - Jul, 2005 //-------------------------------------------------------------------------- VarLenType CommonFG::openVarLenType( const H5std_string& name ) const @@ -980,7 +980,7 @@ int CommonFG::iterateElems( const char* name, int *idx, H5G_iterate_t op , void* // Function: CommonFG::iterateElems ///\brief This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes an -/// \c std::string for \a name. +/// \c H5std_string for \a name. // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- int CommonFG::iterateElems( const H5std_string& name, int *idx, H5G_iterate_t op , void* op_data ) @@ -1073,7 +1073,7 @@ ssize_t CommonFG::getObjnameByIdx(hsize_t idx, char* name, size_t size) const // Function: CommonFG::getObjnameByIdx ///\brief This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes an -/// \c std::string for \a name. +/// \c H5std_string for \a name. // Programmer Binh-Minh Ribler - January, 2003 //-------------------------------------------------------------------------- ssize_t CommonFG::getObjnameByIdx(hsize_t idx, H5std_string& name, size_t size) const diff --git a/c++/src/H5DataSet.cpp b/c++/src/H5DataSet.cpp index 7351bbf..f7aaa72 100644 --- a/c++/src/H5DataSet.cpp +++ b/c++/src/H5DataSet.cpp @@ -238,7 +238,8 @@ size_t DataSet::getInMemDataSize() const throw DataSetIException(func, "H5Dget_type failed"); } - // Get the data type's size + // Get the data type's size by first getting its native type then getting + // the native type's size. hid_t native_type = H5Tget_native_type(mem_type_id, H5T_DIR_DEFAULT); if (native_type < 0) { @@ -250,8 +251,19 @@ size_t DataSet::getInMemDataSize() const throw DataSetIException(func, "H5Tget_size failed"); } - // Get number of elements of the dataset - hid_t space_id = H5Dget_space(id); // first get its data space + // Close the native type and the datatype of this dataset. + if (H5Tclose(native_type) < 0) + { + throw DataSetIException(func, "H5Tclose(native_type) failed"); + } + if (H5Tclose(mem_type_id) < 0) + { + throw DataSetIException(func, "H5Tclose(mem_type_id) failed"); + } + + // Get number of elements of the dataset by first getting its dataspace, + // then getting the number of elements in the dataspace + hid_t space_id = H5Dget_space(id); if (space_id < 0) { throw DataSetIException(func, "H5Dget_space failed"); @@ -262,6 +274,12 @@ size_t DataSet::getInMemDataSize() const throw DataSetIException(func, "H5Sget_simple_extent_npoints failed"); } + // Close the dataspace + if (H5Sclose(space_id) < 0) + { + throw DataSetIException(func, "H5Sclose failed"); + } + // Calculate and return the size of the data size_t data_size = type_size * num_elements; return(data_size); @@ -411,7 +429,7 @@ void DataSet::read( void* buf, const DataType& mem_type, const DataSpace& mem_sp //-------------------------------------------------------------------------- // Function: DataSet::read ///\brief This is an overloaded member function, provided for convenience. -/// It takes a reference to a \c std::string for the buffer. +/// It takes a reference to a \c H5std_string for the buffer. ///\param buf - IN: Buffer for read data ///\param mem_type - IN: Memory datatype ///\param mem_space - IN: Memory dataspace @@ -487,7 +505,7 @@ void DataSet::write( const void* buf, const DataType& mem_type, const DataSpace& //-------------------------------------------------------------------------- // Function: DataSet::write ///\brief This is an overloaded member function, provided for convenience. -/// It takes a reference to a \c std::string for the buffer. +/// It takes a reference to a \c H5std_string for the buffer. // Programmer Binh-Minh Ribler - 2000 // Modification // Jul 2009 @@ -571,7 +589,7 @@ int DataSet::iterateElems( void* buf, const DataType& type, const DataSpace& spa /// For more information, please see the Description section in /// C layer Reference Manual at: ///\par -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5D.html#Dataset-Extend +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5D.html#Dataset-Extend // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- void DataSet::extend( const hsize_t* size ) const @@ -631,14 +649,14 @@ void DataSet::fillMemBuf(void *buf, DataType& buf_type, DataSpace& space) // Function: DataSet::getObjType ///\brief Retrieves the type of object that an object reference points to. ///\param ref_type - IN: Type of reference to query, valid values are: -/// \li \c H5R_OBJECT \tReference is an object reference. -/// \li \c H5R_DATASET_REGION \tReference is a dataset region reference. +/// \li \c H5R_OBJECT - Reference is an object reference. +/// \li \c H5R_DATASET_REGION - Reference is a dataset region reference. ///\param ref - IN: Reference to query ///\return An object type, which can be one of the following: -/// \li \c H5G_LINK (0) \tObject is a symbolic link. -/// \li \c H5G_GROUP (1) \tObject is a group. -/// \li \c H5G_DATASET (2) \tObject is a dataset. -/// \li \c H5G_TYPE Object (3) \tis a named datatype +/// \li \c H5G_LINK (0) - Object is a symbolic link. +/// \li \c H5G_GROUP (1) - Object is a group. +/// \li \c H5G_DATASET (2) - Object is a dataset. +/// \li \c H5G_TYPE (3) - Object is a named datatype ///\exception H5::DataSetIException // Programmer Binh-Minh Ribler - May, 2004 //-------------------------------------------------------------------------- @@ -656,9 +674,9 @@ H5G_obj_t DataSet::getObjType(void *ref, H5R_type_t ref_type) const //-------------------------------------------------------------------------- // Function: DataSet::getRegion ///\brief Retrieves a dataspace with the region pointed to selected. +///\param ref - IN: Reference to get region of ///\param ref_type - IN: Type of reference to get region of - default /// to H5R_DATASET_REGION -///\param ref - IN: Reference to get region of ///\return DataSpace instance ///\exception H5::DataSetIException // Programmer Binh-Minh Ribler - May, 2004 @@ -676,7 +694,7 @@ DataSpace DataSet::getRegion(void *ref, H5R_type_t ref_type) const //-------------------------------------------------------------------------- // Function: DataSet::getId -// Purpose: Get the id of this attribute +///\brief Get the id of this dataset. // Description: // Class hierarchy is revised to address bugzilla 1068. Class // AbstractDs and Attribute are moved out of H5Object. In @@ -758,7 +776,7 @@ void DataSet::p_read_variable_len(const hid_t mem_type_id, const hid_t mem_space //-------------------------------------------------------------------------- // Function: DataSet::p_setId (private) -///\brief Sets the identifier of this object to a new value. +///\brief Sets the identifier of this dataset to a new value. /// ///\exception H5::IdComponentException when the attempt to close the HDF5 /// object fails diff --git a/c++/src/H5DataSpace.cpp b/c++/src/H5DataSpace.cpp index 2c6fd37..755ca5b 100644 --- a/c++/src/H5DataSpace.cpp +++ b/c++/src/H5DataSpace.cpp @@ -408,7 +408,7 @@ hssize_t DataSpace::getSelectElemNpoints () const ///\par Description /// For more information, please refer to the C layer Reference /// Manual at: -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5S.html#Dataspace-SelectElemPointList +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5S.html#Dataspace-SelectElemPointList // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- void DataSpace::getSelectElemPointlist ( hsize_t startpoint, hsize_t numpoints, hsize_t *buf ) const @@ -432,7 +432,7 @@ void DataSpace::getSelectElemPointlist ( hsize_t startpoint, hsize_t numpoints, ///\par Description /// For more information, please refer to the C layer Reference /// Manual at: -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5S.html#Dataspace-SelectBounds +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5S.html#Dataspace-SelectBounds // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- void DataSpace::getSelectBounds ( hsize_t* start, hsize_t* end ) const @@ -458,7 +458,7 @@ void DataSpace::getSelectBounds ( hsize_t* start, hsize_t* end ) const ///\par Description /// For more information, please refer to the C layer Reference /// Manual at: -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5S.html#Dataspace-SelectElements +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5S.html#Dataspace-SelectElements // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- void DataSpace::selectElements ( H5S_seloper_t op, const size_t num_elements, const hsize_t *coord) const @@ -540,7 +540,7 @@ bool DataSpace::selectValid () const ///\par Description /// For more information, please refer to the C layer Reference /// Manual at: -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5S.html#Dataspace-SelectHyperslab +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5S.html#Dataspace-SelectHyperslab // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- void DataSpace::selectHyperslab( H5S_seloper_t op, const hsize_t *count, const hsize_t *start, const hsize_t *stride, const hsize_t *block ) const diff --git a/c++/src/H5DataType.cpp b/c++/src/H5DataType.cpp index e13b330..3edb163 100644 --- a/c++/src/H5DataType.cpp +++ b/c++/src/H5DataType.cpp @@ -52,16 +52,14 @@ namespace H5 { // Function: DataType overloaded constructor ///\brief Creates a datatype using an existing datatype's id ///\param existing_id - IN: Id of the existing datatype -///\param predefined - IN: Indicates whether or not this datatype is -/// a predefined datatype; default to \c false // Description // Constructor creates a copy of an existing DataType using -// its id. The argument "predefined" is default to false; -// when a default datatype is created, this argument is set -// to true so H5Tclose will not be called on it later. - need -// a reassessment after changing to the new ref counting mech. -// - BMR 5/2004 +// its id. // Programmer Binh-Minh Ribler - 2000 +// Modification +// Dec, 2005 +// Removed second argument, "predefined", after changing to the +// new ref counting mechanism that relies on C's ref counting. //-------------------------------------------------------------------------- DataType::DataType(const hid_t existing_id) : H5Object() { @@ -210,7 +208,7 @@ void DataType::copy( const DataType& like_type ) ///\param dset - IN: Dataset ///\exception H5::DataTypeIException // Programmer Binh-Minh Ribler - Jan, 2007 -///\parDescription +///\par Description /// The resulted dataset will be transient and modifiable. //-------------------------------------------------------------------------- void DataType::copy(const DataSet& dset) @@ -517,7 +515,7 @@ DataType DataType::getSuper() const ///\exception H5::DataTypeIException ///\par Description /// For more information, please see: -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5T.html#Datatype-Register +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5T.html#Datatype-Register // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- void DataType::registerFunc( H5T_pers_t pers, const char* name, const DataType& dest, H5T_conv_t func ) const @@ -794,17 +792,33 @@ void DataType::close() // Programmer Binh-Minh Ribler - 2000 // Modification // - Replaced resetIdComponent() with decRefCount() to use C -// library ID reference counting mechanism - BMR, Jun 1, 2004 +// library ID reference counting mechanism - BMR, Jun 1, 2004 // - Replaced decRefCount with close() to let the C library -// handle the reference counting - BMR, Jun 1, 2006 +// handle the reference counting - BMR, Jun 1, 2006 +// - Added the use of H5CPP_EXITED to terminate the HDF5 library +// and elimiate previous memory leaks. See comments in the +// header file "H5PredType.h" for details. - BMR, Mar 30, 2012 //-------------------------------------------------------------------------- DataType::~DataType() { - try { - close(); - } catch (Exception close_error) { - cerr << inMemFunc("~DataType - ") << close_error.getDetailMsg() << endl; + try + { + /* If this is the object AtExit, terminate the HDF5 library. This is + to eliminate memory leaks due to the library being re-initiated + (after the program has ended) and not re-terminated. */ + if (id == H5CPP_EXITED) + { + herr_t ret_value = H5close(); + if (ret_value == FAIL) + throw DataTypeIException(inMemFunc("~DataType - "), "H5close failed"); } + // Close the HDF5 datatype + else + close(); + } + catch (Exception close_error) { + cerr << inMemFunc("~DataType - ") << close_error.getDetailMsg() << endl; + } } #ifndef H5_NO_NAMESPACE } // end namespace diff --git a/c++/src/H5DcreatProp.cpp b/c++/src/H5DcreatProp.cpp index 981085d..ece435c 100644 --- a/c++/src/H5DcreatProp.cpp +++ b/c++/src/H5DcreatProp.cpp @@ -106,8 +106,8 @@ int DSetCreatPropList::getChunk( int max_ndims, hsize_t* dim ) const ///\param layout - IN: Type of storage layout for raw data ///\exception H5::PropListIException ///\par Description -/// For information on setting layout type, please refer to -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5P.html#Property-SetLayout +/// For information on valid layout types, please refer to +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5P.html#Property-SetLayout // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- void DSetCreatPropList::setLayout(H5D_layout_t layout) const @@ -211,7 +211,7 @@ void DSetCreatPropList::setSzip(unsigned int options_mask, unsigned int pixels_p ///\par /// For information on setting fill value, please refer to the /// C layer Reference Manual at: -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5P.html#Property-SetFillValue +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5P.html#Property-SetFillValue // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- void DSetCreatPropList::setFillValue( const DataType& fvalue_type, const void* value ) const @@ -459,7 +459,7 @@ bool DSetCreatPropList::allFiltersAvail() ///\par Description /// Please refer to the Reference Manual of \c H5Pset_shuffle for /// details. -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5P.html#Property-SetShuffle +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5P.html#Property-SetShuffle // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- void DSetCreatPropList::setShuffle() const diff --git a/c++/src/H5DxferProp.cpp b/c++/src/H5DxferProp.cpp index 0f7faa2..0785735 100644 --- a/c++/src/H5DxferProp.cpp +++ b/c++/src/H5DxferProp.cpp @@ -309,7 +309,7 @@ void DSetMemXferPropList::getMulti(hid_t *memb_dxpl) ///\exception H5::PropListIException ///\par Description /// For detail, please refer to the C layer Reference Manual at: -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5P.html#Property-SetSmallData +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5P.html#Property-SetSmallData // Programmer: Binh-Minh Ribler - April, 2004 //-------------------------------------------------------------------------- void DSetMemXferPropList::setSmallDataBlockSize(hsize_t size) @@ -349,7 +349,7 @@ hsize_t DSetMemXferPropList::getSmallDataBlockSize() ///\par Description /// For information, please refer to the C layer Reference /// Manual at: -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5P.html#Property-SetHyperVectorSize +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5P.html#Property-SetHyperVectorSize // Programmer: Binh-Minh Ribler - April, 2004 //-------------------------------------------------------------------------- void DSetMemXferPropList::setHyperVectorSize(size_t vector_size) diff --git a/c++/src/H5FaccProp.cpp b/c++/src/H5FaccProp.cpp index f2ab0f3..4fb3836 100644 --- a/c++/src/H5FaccProp.cpp +++ b/c++/src/H5FaccProp.cpp @@ -76,7 +76,7 @@ void FileAccPropList::setStdio() const /// driver was set for the property list. The driver ID is /// only valid as long as the file driver remains registered. /// Valid driver identifiers can be found at: -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5P.html#Property-GetDriver +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5P.html#Property-GetDriver ///\exception H5::PropListIException // Programmer: Binh-Minh Ribler - April, 2004 //-------------------------------------------------------------------------- @@ -99,7 +99,7 @@ hid_t FileAccPropList::getDriver() const ///\par Description /// For a list of valid driver identifiers, please see the C /// layer Reference Manual at: -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5P.html#Property-GetDriver +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5P.html#Property-SetDriver // Programmer: Binh-Minh Ribler - April, 2004 //-------------------------------------------------------------------------- void FileAccPropList::setDriver(hid_t new_driver_id, const void *new_driver_info) const @@ -157,7 +157,7 @@ hsize_t FileAccPropList::getFamilyOffset() const ///\par Description /// For more details on the use of \c H5FD_CORE driver, please /// refer to -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5P.html#Property-SetFaplCore +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5P.html#Property-SetFaplCore // Programmer: Binh-Minh Ribler - April, 2004 //-------------------------------------------------------------------------- void FileAccPropList::setCore (size_t increment, hbool_t backing_store) const @@ -261,7 +261,7 @@ FileAccPropList FileAccPropList::getFamily(hsize_t& memb_size) const ///\exception H5::PropListIException ///\par Description /// Temporary - For information, please refer to: -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5P.html#Property-SetFaplSplit +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5P.html#Property-SetFaplSplit // Programmer: Binh-Minh Ribler - April, 2004 //-------------------------------------------------------------------------- void FileAccPropList::setSplit( FileAccPropList& meta_plist, FileAccPropList& raw_plist, const char* meta_ext, const char* raw_ext ) const @@ -292,47 +292,9 @@ void FileAccPropList::setSplit( FileAccPropList& meta_plist, FileAccPropList& ra setSplit( meta_plist, raw_plist, meta_ext.c_str(), raw_ext.c_str() ); } -#ifdef H5_HAVE_STREAM // for Stream Virtual File Driver -//-------------------------------------------------------------------------- -// Function: FileAccPropList::getStream -///\brief Retrieves the streaming I/O driver settings -///\return The streaming I/O file access property list structure -/// For detail on this structure, please refer to -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5P.html#Property-SetFaplStream -///\exception H5::PropListIException -// Programmer: Binh-Minh Ribler - April, 2004 -//-------------------------------------------------------------------------- -H5FD_stream_fapl_t FileAccPropList::getStream() const -{ - H5FD_stream_fapl_t fapl; - herr_t ret_value = H5Pget_fapl_stream(id, &fapl); - if( ret_value < 0 ) - { - throw PropListIException("FileAccPropList::getStream", "H5Pget_fapl_stream failed"); - } - return(fapl); -} - -//-------------------------------------------------------------------------- -// Function: FileAccPropList::setStream -///\brief Modifies this file access property list to use the Stream -/// driver. -///\param fapl - IN: The streaming I/O file access property list -///\exception H5::PropListIException -///\par Description -/// For detail on \a fapl, please refer to -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5P.html#Property-SetFaplStream -// Programmer: Binh-Minh Ribler - April, 2004 -//-------------------------------------------------------------------------- -void FileAccPropList::setStream(H5FD_stream_fapl_t &fapl) const -{ - herr_t ret_value = H5Pset_fapl_stream (id, &fapl); - if( ret_value < 0 ) - { - throw PropListIException("FileAccPropList::setStream", "H5Pset_fapl_stream failed"); - } -} -#endif // Stream Virtual File Driver +// Stream Virtual File Driver had been removed from the main library. +// FileAccPropList::[s,g]etStream are now removed from the C++ API. +// -BMR, March, 2012 //-------------------------------------------------------------------------- // Function: FileAccPropList::getSieveBufSize @@ -360,7 +322,7 @@ size_t FileAccPropList::getSieveBufSize() const ///\exception H5::PropListIException ///\par Description /// For detail on data sieving, please refer to -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5P.html#Property-SetSieveBufSize +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5P.html#Property-SetSieveBufSize // Programmer: Binh-Minh Ribler - April, 2004 //-------------------------------------------------------------------------- void FileAccPropList::setSieveBufSize(size_t bufsize) const @@ -380,7 +342,7 @@ void FileAccPropList::setSieveBufSize(size_t bufsize) const ///\exception H5::PropListIException ///\par Description /// For more detail, please see the C layer Reference Manual at: -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5P.html#Property-SetMetaBlockSize +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5P.html#Property-SetMetaBlockSize // Programmer: Binh-Minh Ribler - April, 2004 //-------------------------------------------------------------------------- void FileAccPropList::setMetaBlockSize(hsize_t &block_size) const @@ -420,7 +382,7 @@ hsize_t FileAccPropList::getMetaBlockSize() const ///\exception H5::PropListIException ///\par Description /// For detail on \a flags, please refer to -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5P.html#Property-SetFaplStream +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5P.html#Property-SetFaplLog // Programmer: Binh-Minh Ribler - April, 2004 //-------------------------------------------------------------------------- void FileAccPropList::setLog(const char *logfile, unsigned flags, size_t buf_size) const @@ -477,7 +439,7 @@ void FileAccPropList::setSec2() const /// The parameter \a alignment must have a positive value. /// /// For detail on \a setting alignment, please refer to -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5P.html#Property-SetAlignment +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5P.html#Property-SetAlignment // Programmer: Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- void FileAccPropList::setAlignment( hsize_t threshold, hsize_t alignment ) const @@ -514,7 +476,7 @@ void FileAccPropList::getAlignment( hsize_t &threshold, hsize_t &alignment ) con ///\exception H5::PropListIException ///\par Description /// More details and valid values for \a dtype can be found at: -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5P.html#Property-SetMultiType +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5P.html#Property-SetMultiType // Programmer: Binh-Minh Ribler - April, 2004 //-------------------------------------------------------------------------- void FileAccPropList::setMultiType(H5FD_mem_t dtype) const @@ -533,7 +495,7 @@ void FileAccPropList::setMultiType(H5FD_mem_t dtype) const ///\exception H5::PropListIException ///\par Description /// More details and possible returned values can be found at: -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5P.html#Property-GetMultiType +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5P.html#Property-GetMultiType // Programmer: Binh-Minh Ribler - April, 2004 //-------------------------------------------------------------------------- H5FD_mem_t FileAccPropList::getMultiType() const @@ -634,7 +596,7 @@ H5F_close_degree_t FileAccPropList::getFcloseDegree() ///\exception H5::PropListIException ///\par Description /// For detail on \a fapl, please refer to -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5P.html#Property-SetFaplStream +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5P.html#Property-SetGCReferences // Programmer: Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- void FileAccPropList::setGcReferences( unsigned gc_ref ) const diff --git a/c++/src/H5FcreatProp.cpp b/c++/src/H5FcreatProp.cpp index 53d18f6..8d9965e 100644 --- a/c++/src/H5FcreatProp.cpp +++ b/c++/src/H5FcreatProp.cpp @@ -128,7 +128,7 @@ hsize_t FileCreatPropList::getUserblock() const ///\par Description /// For information on setting sizes, please refer to the /// C layer Reference Manual at: -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5P.html#Property-SetSizes +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5P.html#Property-SetSizes // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- void FileCreatPropList::setSizes( size_t sizeof_addr, size_t sizeof_size ) const @@ -168,7 +168,7 @@ void FileCreatPropList::getSizes( size_t& sizeof_addr, size_t& sizeof_size ) con ///\exception H5::PropListIException ///\par Description /// For information, please see the C layer Reference Manual at: -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5P.html#Property-SetSymK +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5P.html#Property-SetSymK // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- void FileCreatPropList::setSymk( unsigned ik, unsigned lk ) const @@ -189,7 +189,7 @@ void FileCreatPropList::setSymk( unsigned ik, unsigned lk ) const ///\exception H5::PropListIException ///\par Description /// For information, please see -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5P.html#Property-SetSymK +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5P.html#Property-GetSymK // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- void FileCreatPropList::getSymk( unsigned& ik, unsigned& lk ) const @@ -210,7 +210,7 @@ void FileCreatPropList::getSymk( unsigned& ik, unsigned& lk ) const ///\exception H5::PropListIException ///\par Description /// For information, please see the C layer Reference Manual at: -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5P.html#Property-SetIstoreK +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5P.html#Property-SetIstoreK // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- void FileCreatPropList::setIstorek( unsigned ik ) const @@ -230,7 +230,7 @@ void FileCreatPropList::setIstorek( unsigned ik ) const ///\exception H5::PropListIException ///\par Description /// For information, please see -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5P.html#Property-SetIstoreK +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5P.html#Property-GetIstoreK // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- unsigned FileCreatPropList::getIstorek() const diff --git a/c++/src/H5File.cpp b/c++/src/H5File.cpp index a773489..da0241f 100644 --- a/c++/src/H5File.cpp +++ b/c++/src/H5File.cpp @@ -76,7 +76,7 @@ H5File::H5File() : IdComponent(), id(0) {} /// For info on file creation in the case of an already-open file, /// please refer to the \b Special \b case section in the C layer /// Reference Manual at: -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5F.html#File-Create +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5F.html#File-Create // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- H5File::H5File( const char* name, unsigned int flags, const FileCreatPropList& create_plist, const FileAccPropList& access_plist ) : IdComponent(0) @@ -88,7 +88,7 @@ H5File::H5File( const char* name, unsigned int flags, const FileCreatPropList& c // Function: H5File overloaded constructor ///\brief This is another overloaded constructor. It differs from the /// above constructor only in the type of the \a name argument. -///\param name - IN: Name of the file - \c std::string +///\param name - IN: Name of the file - \c H5std_string ///\param flags - IN: File access flags ///\param create_plist - IN: File creation property list, used when /// modifying default file meta-data. Default to @@ -191,8 +191,8 @@ bool H5File::isHdf5(const char* name) //-------------------------------------------------------------------------- // Function: H5File::isHdf5 ///\brief This is an overloaded member function, provided for convenience. -/// It takes an \c std::string for \a name. -///\param name - IN: Name of the file - \c std::string +/// It takes an \c H5std_string for \a name. +///\param name - IN: Name of the file - \c H5std_string // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- bool H5File::isHdf5(const H5std_string& name ) @@ -231,8 +231,8 @@ void H5File::openFile(const char* name, unsigned int flags, const FileAccPropLis //-------------------------------------------------------------------------- // Function: H5File::openFile ///\brief This is an overloaded member function, provided for convenience. -/// It takes an \c std::string for \a name. -///\param name - IN: Name of the file - \c std::string +/// It takes an \c H5std_string for \a name. +///\param name - IN: Name of the file - \c H5std_string ///\param flags - IN: File access flags ///\param access_plist - IN: File access property list. Default to /// FileAccPropList::DEFAULT @@ -512,8 +512,8 @@ H5std_string H5File::getFileName() const ///\brief Retrieves the type of object that an object reference points to. ///\param ref - IN: Reference to query ///\param ref_type - IN: Type of reference, valid values are: -/// \li \c H5R_OBJECT \tReference is an object reference. -/// \li \c H5R_DATASET_REGION \tReference is a dataset region reference. +/// \li \c H5R_OBJECT - Reference is an object reference +/// \li \c H5R_DATASET_REGION - Reference is a dataset region reference ///\return Object type, which can be one of the following: /// \li \c H5G_LINK - Object is a symbolic link. /// \li \c H5G_GROUP - Object is a group. @@ -600,9 +600,9 @@ void H5File::p_reference(void* ref, const char* name, hid_t space_id, H5R_type_t ///\param name - IN: Name of the object to be referenced ///\param dataspace - IN: Dataspace with selection ///\param ref_type - IN: Type of reference to query, valid values are: -/// \li \c H5R_OBJECT \tReference is an object reference. -/// \li \c H5R_DATASET_REGION \tReference is a dataset region -/// reference. - this is the default +/// \li \c H5R_OBJECT - Reference is an object reference +/// \li \c H5R_DATASET_REGION - Reference is a dataset region +/// reference - this is the default ///\exception H5::IdComponentException // Programmer Binh-Minh Ribler - May, 2004 //-------------------------------------------------------------------------- @@ -643,9 +643,9 @@ void H5File::reference(void* ref, const char* name) const // Function: H5File::reference ///\brief This is an overloaded function, provided for your convenience. /// It differs from the above function in that it takes an -/// \c std::string for the object's name. +/// \c H5std_string for the object's name. ///\param ref - IN: Reference pointer -///\param name - IN: Name of the object to be referenced - \c std::string +///\param name - IN: Name of the object to be referenced - \c H5std_string // Programmer Binh-Minh Ribler - May, 2004 //-------------------------------------------------------------------------- void H5File::reference(void* ref, const H5std_string& name) const diff --git a/c++/src/H5Group.cpp b/c++/src/H5Group.cpp index afcc7eb..6ec2dbb 100644 --- a/c++/src/H5Group.cpp +++ b/c++/src/H5Group.cpp @@ -79,7 +79,7 @@ hid_t Group::getLocId() const //-------------------------------------------------------------------------- // Function: Group overloaded constructor ///\brief Creates a Group object using the id of an existing group. -///\param group_id - IN: Id of an existing group +///\param existing_id - IN: Id of an existing group // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- Group::Group(const hid_t existing_id) : H5Object() @@ -153,13 +153,13 @@ Group::Group(Attribute& attr, const void* ref, H5R_type_t ref_type) : H5Object() ///\brief Retrieves the type of object that an object reference points to. ///\param ref - IN: Reference to query ///\param ref_type - IN: Type of reference to query, valid values are: -/// \li \c H5R_OBJECT \tReference is an object reference. -/// \li \c H5R_DATASET_REGION \tReference is a dataset region reference. +/// \li \c H5R_OBJECT - Reference is an object reference. +/// \li \c H5R_DATASET_REGION - Reference is a dataset region reference. ///\return An object type, which can be one of the following: -/// H5G_LINK Object is a symbolic link. -/// H5G_GROUP Object is a group. -/// H5G_DATASET Object is a dataset. -/// H5G_TYPE Object is a named datatype +/// \li \c H5G_LINK (0) - Object is a symbolic link. +/// \li \c H5G_GROUP (1) - Object is a group. +/// \li \c H5G_DATASET (2) - Object is a dataset. +/// \li \c H5G_TYPE (3) - Object is a named datatype ///\exception H5::GroupIException // Programmer Binh-Minh Ribler - May, 2004 //-------------------------------------------------------------------------- @@ -199,10 +199,10 @@ DataSpace Group::getRegion(void *ref, H5R_type_t ref_type) const // Purpose: Get the id of this attribute // Modification: // May 2008 - BMR -// Class hierarchy is revised to address bugzilla 1068. Class -// AbstractDS and Attribute are moved out of H5Object. In -// addition, member IdComponent::id is moved into subclasses, and -// IdComponent::getId now becomes pure virtual function. +// Class hierarchy is revised to address bugzilla 1068. Class +// AbstractDS and Attribute are moved out of H5Object. In +// addition, member IdComponent::id is moved into subclasses, and +// IdComponent::getId now becomes pure virtual function. // Programmer Binh-Minh Ribler - May, 2008 //-------------------------------------------------------------------------- hid_t Group::getId() const @@ -215,11 +215,11 @@ hid_t Group::getId() const ///\brief Sets the identifier of this object to a new value. /// ///\exception H5::IdComponentException when the attempt to close the HDF5 -/// object fails +/// object fails // Description: -// The underlaying reference counting in the C library ensures -// that the current valid id of this object is properly closed. -// Then the object's id is reset to the new id. +// The underlaying reference counting in the C library ensures +// that the current valid id of this object is properly closed. +// Then the object's id is reset to the new id. // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- void Group::p_setId(const hid_t new_id) diff --git a/c++/src/H5IdComponent.cpp b/c++/src/H5IdComponent.cpp index 1cac0c1..9f96277 100644 --- a/c++/src/H5IdComponent.cpp +++ b/c++/src/H5IdComponent.cpp @@ -13,11 +13,13 @@ * access to either file, you may request a copy from help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -#ifdef H5_VMS +#ifdef OLD_HEADER_FILENAME +#include +#else #include -#endif /*H5_VMS*/ - +#endif #include + #include "H5Include.h" #include "H5Exception.h" #include "H5Library.h" @@ -129,7 +131,7 @@ int IdComponent::getCounter() const //-------------------------------------------------------------------------- // Function: hdfObjectType ///\brief Given an id, returns the type of the object. -///return a valid HDF object type, which may be one of the following: +///\return a valid HDF object type, which may be one of the following: /// \li \c H5I_FILE /// \li \c H5I_GROUP /// \li \c H5I_DATATYPE diff --git a/c++/src/H5Library.cpp b/c++/src/H5Library.cpp index e7557b3..ecc5141 100644 --- a/c++/src/H5Library.cpp +++ b/c++/src/H5Library.cpp @@ -106,7 +106,7 @@ void H5Library::getLibVersion( unsigned& majnum, unsigned& minnum, unsigned& rel ///\par Description /// For information about library version, please refer to /// the C layer Reference Manual at: -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5.html#Library-VersCheck +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5.html#Library-VersCheck // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- void H5Library::checkVersion(unsigned majnum, unsigned minnum, unsigned relnum) @@ -161,7 +161,7 @@ void H5Library::garbageCollect() /// Setting a value of -1 for a limit means no limit of that type. /// For more information on free list limits, please refer to C /// layer Reference Manual at: -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5.html#Library-SetFreeListLimits +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5.html#Library-SetFreeListLimits // Programmer Binh-Minh Ribler - May, 2004 //-------------------------------------------------------------------------- void H5Library::setFreeListLimits(int reg_global_lim, int reg_list_lim, diff --git a/c++/src/H5Object.cpp b/c++/src/H5Object.cpp index e25c255..3c85502 100644 --- a/c++/src/H5Object.cpp +++ b/c++/src/H5Object.cpp @@ -124,7 +124,7 @@ Attribute H5Object::createAttribute( const char* name, const DataType& data_type // Function: H5Object::createAttribute ///\brief This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes -/// a reference to an \c std::string for \a name. +/// a reference to an \c H5std_string for \a name. // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- Attribute H5Object::createAttribute( const H5std_string& name, const DataType& data_type, const DataSpace& data_space, const PropList& create_plist ) const @@ -158,7 +158,7 @@ Attribute H5Object::openAttribute( const char* name ) const // Function: H5Object::openAttribute ///\brief This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes -/// a reference to an \c std::string for \a name. +/// a reference to an \c H5std_string for \a name. // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- Attribute H5Object::openAttribute( const H5std_string& name ) const @@ -194,15 +194,17 @@ Attribute H5Object::openAttribute( const unsigned int idx ) const ///\brief Iterates a user's function over all the attributes of an H5 /// object, which may be a group, dataset or named datatype. ///\param user_op - IN: User's function to operate on each attribute -///\param idx - IN/OUT: Starting (IN) and ending (OUT) attribute indices +///\param _idx - IN/OUT: Starting (IN) and ending (OUT) attribute indices ///\param op_data - IN: User's data to pass to user's operator function ///\return Returned value of the last operator if it was non-zero, or /// zero if all attributes were processed ///\exception H5::AttributeIException ///\par Description +/// The signature of user_op is +/// void (*)(H5::H5Object&, H5std_string, void*). /// For information, please refer to the C layer Reference Manual /// at: -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5A.html#Annot-Iterate +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5A.html#Annot-Iterate // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- int H5Object::iterateAttrs( attr_operator_t user_op, unsigned *_idx, void *op_data ) @@ -267,7 +269,7 @@ void H5Object::removeAttr( const char* name ) const // Function: H5Object::removeAttr ///\brief This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes -/// a reference to an \c std::string for \a name. +/// a reference to an \c H5std_string for \a name. // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- void H5Object::removeAttr( const H5std_string& name ) const @@ -294,7 +296,7 @@ void H5Object::renameAttr(const char* oldname, const char* newname) const // Function: H5Object::renameAttr ///\brief This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes -/// a reference to an \c std::string for the names. +/// a reference to an \c H5std_string for the names. // Programmer Binh-Minh Ribler - Mar, 2005 //-------------------------------------------------------------------------- void H5Object::renameAttr(const H5std_string& oldname, const H5std_string& newname) const @@ -366,9 +368,9 @@ void H5Object::p_reference(void* ref, const char* name, hid_t space_id, H5R_type ///\param name - IN: Name of the object to be referenced ///\param dataspace - IN: Dataspace with selection ///\param ref_type - IN: Type of reference to query, valid values are: -/// \li \c H5R_OBJECT \tReference is an object reference. -/// \li \c H5R_DATASET_REGION \tReference is a dataset region -/// reference. - this is the default +/// \li \c H5R_OBJECT - Reference is an object reference. +/// \li \c H5R_DATASET_REGION - Reference is a dataset region +/// reference. - this is the default ///\exception H5::IdComponentException // Programmer Binh-Minh Ribler - May, 2004 //-------------------------------------------------------------------------- @@ -410,9 +412,9 @@ void H5Object::reference(void* ref, const char* name) const // Function: H5Object::reference ///\brief This is an overloaded function, provided for your convenience. /// It differs from the above function in that it takes an -/// \c std::string for the object's name. +/// \c H5std_string for the object's name. ///\param ref - IN: Reference pointer -///\param name - IN: Name of the object to be referenced - \c std::string +///\param name - IN: Name of the object to be referenced - \c H5std_string // Programmer Binh-Minh Ribler - May, 2004 //-------------------------------------------------------------------------- void H5Object::reference(void* ref, const H5std_string& name) const diff --git a/c++/src/H5PredType.cpp b/c++/src/H5PredType.cpp index 347f02f..9dfc760 100644 --- a/c++/src/H5PredType.cpp +++ b/c++/src/H5PredType.cpp @@ -44,7 +44,10 @@ namespace H5 { //-------------------------------------------------------------------------- PredType::PredType( const hid_t predtype_id ) : AtomType( predtype_id ) { - id = H5Tcopy(predtype_id); + if (predtype_id == H5CPP_EXITED) + id = predtype_id; + else + id = H5Tcopy(predtype_id); } //-------------------------------------------------------------------------- @@ -62,7 +65,8 @@ PredType::PredType() : AtomType() {} //-------------------------------------------------------------------------- PredType::PredType( const PredType& original ) : AtomType( original ) {} -const PredType PredType::NotAtexit; // only for atexit/global dest. problem +// Flag to terminate HDF5 library in DataType::~DataType +const PredType PredType::AtExit(H5CPP_EXITED); // Definition of pre-defined types const PredType PredType::C_S1( H5T_C_S1 ); diff --git a/c++/src/H5PredType.h b/c++/src/H5PredType.h index 69abfcb..9cb1c65 100644 --- a/c++/src/H5PredType.h +++ b/c++/src/H5PredType.h @@ -26,9 +26,17 @@ namespace H5 { #endif +/* This constant is defined for a workaround to eliminate memory leaks due to + the library being re-initiated when PredType destructors are invoked. A + PredType instant with H5CPP_EXITED as the value of its "id" is constructed + before the other PredType objects are created. At exit, when this special + PredType object is to be destructed, no HDF5 library function will be called + and the library will be terminated. -BMR, Mar 30, 2012 */ +#define H5CPP_EXITED -3 // -3 is less likely to be used elsewhere + class H5_DLLCPP PredType : public AtomType { public: - // Returns this class name + ///\brief Returns this class name virtual H5std_string fromClass () const { return("PredType"); } // Makes a copy of the predefined type and stores the new @@ -229,9 +237,10 @@ class H5_DLLCPP PredType : public AtomType { #endif // DOXYGEN_SHOULD_SKIP_THIS private: - // added this to work around the atexit/global destructor problem - // temporarily - it'll prevent the use of atexit to clean up - static const PredType NotAtexit; // not working yet + // Added this to work around the atexit/global destructor problem. + // It'll help to terminate the library after other PredType instances + // are closed. -BMR, Mar 30, 2012 + static const PredType AtExit; protected: #ifndef DOXYGEN_SHOULD_SKIP_THIS diff --git a/c++/src/H5PropList.cpp b/c++/src/H5PropList.cpp index 550c90d..ceea15f 100644 --- a/c++/src/H5PropList.cpp +++ b/c++/src/H5PropList.cpp @@ -570,7 +570,7 @@ void PropList::setProperty(const H5std_string& name, void* value) const /// It differs from the above function only in what arguments it /// accepts. ///\param name - IN: Name of property to set - \c H5std_string -///\param strg - IN: Value for the property is a \c std::string +///\param strg - IN: Value for the property is a \c H5std_string // Programmer: Binh-Minh Ribler - April, 2004 //-------------------------------------------------------------------------- void PropList::setProperty(const H5std_string& name, H5std_string& strg) const diff --git a/c++/src/H5StrType.cpp b/c++/src/H5StrType.cpp index e632c4d..a906b72 100644 --- a/c++/src/H5StrType.cpp +++ b/c++/src/H5StrType.cpp @@ -87,7 +87,7 @@ StrType::StrType( const PredType& pred_type, const size_t& size ) : AtomType() // Function: StrType overloaded constructor ///\brief Creates a string datatype with a specified length ///\param dummy - IN: To simplify calling the previous constructor -// and avoid prototype clash with another constructor +/// and avoid prototype clash with another constructor ///\param size - IN: Length of the new string type ///\exception H5::DataTypeIException ///\par Description @@ -209,7 +209,7 @@ H5T_str_t StrType::getStrpad() const ///\exception H5::DataTypeIException ///\par Description /// For detail, please refer to the C layer Reference Manual at: -/// http://hdf.ncsa.uiuc.edu/HDF5/doc/RM_H5T.html#Datatype-SetStrpad +/// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5T.html#Datatype-SetStrpad // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- void StrType::setStrpad( H5T_str_t strpad ) const diff --git a/c++/src/Makefile.in b/c++/src/Makefile.in index f3e8e5d..3f99980 100644 --- a/c++/src/Makefile.in +++ b/c++/src/Makefile.in @@ -431,7 +431,7 @@ CHECK_CLEANFILES = *.chkexe *.chklog *.clog # Add libtool shared library version numbers to the HDF5 library # See libtool versioning documentation online. LT_VERS_INTERFACE = 6 -LT_VERS_REVISION = 101 +LT_VERS_REVISION = 103 LT_VERS_AGE = 0 # Include src directory diff --git a/c++/src/h5c++.in b/c++/src/h5c++.in old mode 100755 new mode 100644 index 39d3d2a..20435eb --- a/c++/src/h5c++.in +++ b/c++/src/h5c++.in @@ -208,7 +208,7 @@ for arg in $@ ; do get_output_file="yes" fi ;; - -E|-M) + -E|-M|-MT) allargs="$allargs $arg" compile_args="$compile_args $arg" dash_c="yes" diff --git a/c++/test/dsets.cpp b/c++/test/dsets.cpp index ee1a206..26abace 100644 --- a/c++/test/dsets.cpp +++ b/c++/test/dsets.cpp @@ -268,6 +268,77 @@ test_simple_io( H5File& file) } // test_simple_io /*------------------------------------------------------------------------- + * Function: test_datasize + * + * Purpose: Tests DataSet::getInMemDataSize(). + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Binh-Minh Ribler + * Thursday, March 22, 2012 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +test_datasize() +{ + + SUBTEST("DataSet::getInMemDataSize()"); + + int points[100][200]; + int check[100][200]; + int i, j, n; + + try + { + // Open FILE1. + H5File file(FILE1, H5F_ACC_RDWR, FileCreatPropList::DEFAULT, FileAccPropList::DEFAULT); + + // Open dataset DSET_SIMPLE_IO_NAME. + DataSet dset = file.openDataSet (DSET_SIMPLE_IO_NAME); + + // Get the dataset's dataspace to calculate the size for verification. + DataSpace space(dset.getSpace()); + + // Get the dimension sizes. + hsize_t dims[2]; + int n_dims = space.getSimpleExtentDims(dims); + + // Calculate the supposed size. Size of each value is int (4), from + // test_simple_io. + int expected_size = 4 * dims[0] * dims[1]; + + // getInMemDataSize() returns the in memory size of the data. + size_t ds_size = dset.getInMemDataSize(); + + // Verify the data size. + if (ds_size != expected_size) + { + H5_FAILED(); + cerr << " Expected data size = " << expected_size; + cerr << " but dset.getInMemDataSize() returned " << ds_size << endl; + throw Exception("test_compression", "Failed in testing DataSet::getInMemDataSize()"); + } + + PASSED(); + return 0; + } // end try + + // catch all dataset, space, plist exceptions + catch (Exception E) + { + cerr << " FAILED" << endl; + cerr << " <<< " << E.getDetailMsg() << " >>>" << endl << endl; + + return -1; + } +} // test_datasize + +/*------------------------------------------------------------------------- * Function: test_tconv * * Purpose: Test some simple data type conversion stuff. @@ -1004,6 +1075,10 @@ void test_dset() nerrors += test_compression(file)<0 ?1:0; nerrors += test_multiopen (file)<0 ?1:0; nerrors += test_types(file)<0 ?1:0; + + // Close the file before testing data size. + file.close(); + nerrors += test_datasize() <0 ? 1:0; } catch (Exception E) { diff --git a/config/COPYING b/config/COPYING old mode 100755 new mode 100644 diff --git a/config/Makefile.am.blank b/config/Makefile.am.blank old mode 100755 new mode 100644 diff --git a/config/cmake/CTestCustom.cmake b/config/cmake/CTestCustom.cmake index 43ef451..e708a00 100755 --- a/config/cmake/CTestCustom.cmake +++ b/config/cmake/CTestCustom.cmake @@ -5,9 +5,10 @@ SET (CTEST_CUSTOM_WARNING_EXCEPTION "H5detect.c.[0-9]+.[ \t]*:[ \t]*warning C4090:" "H5detect.c.[0-9]+.[ \t]*:[ \t]*warning:[ \t]*passing argument" "H5detect.c[0-9 \t:]*warning:[ \t]*passing argument" + "H5detect.c[0-9 \t:]*note:[ \t]*expected .void .. but argument is of type .volatile" + "include/string.h[0-9 \t:]*note:[ \t]*expected .void .. but argument is of type .volatile" "note:[ \t]*expected .void .. but argument is of type .volatile" "H5Tconv.c[0-9 \t:]*warning:[ \t]*comparison is always false due to limited range of data type" - "testhdf5.h.[0-9]+.[ \t]*:[ \t]*warning C4005" "H5Ztrans.c.[0-9]+.[ \t]*:[ \t]*warning C4244" "SZIP.src.*:[ \t]*warning" "POSIX name for this item is deprecated" diff --git a/config/cmake/ConfigureChecks.cmake b/config/cmake/ConfigureChecks.cmake index 963152c..0a078b6 100644 --- a/config/cmake/ConfigureChecks.cmake +++ b/config/cmake/ConfigureChecks.cmake @@ -129,6 +129,10 @@ ENDMACRO (CHECK_LIBRARY_EXISTS_CONCAT) SET (WINDOWS) IF (WIN32) + IF (MINGW) + SET (H5_HAVE_MINGW 1) + SET (WINDOWS 1) # MinGW tries to imitate Windows + ENDIF (MINGW) SET (H5_HAVE_WIN32_API 1) IF (NOT UNIX AND NOT CYGWIN AND NOT MINGW) SET (WINDOWS 1) @@ -174,7 +178,9 @@ IF (WINDOWS) SET (H5_HAVE_DIFFTIME 1) SET (H5_HAVE_LONGJMP 1) SET (H5_STDC_HEADERS 1) - SET (H5_HAVE_GETHOSTNAME 1) + IF (NOT MINGW) + SET (H5_HAVE_GETHOSTNAME 1) + ENDIF (NOT MINGW) SET (H5_HAVE_GETCONSOLESCREENBUFFERINFO 1) SET (H5_HAVE_FUNCTION 1) SET (H5_GETTIMEOFDAY_GIVES_TZ 1) @@ -295,7 +301,6 @@ ENDIF (H5_HAVE_STDINT_H AND CMAKE_CXX_COMPILER_LOADED) SET (LINUX_LFS 0) SET (HDF5_EXTRA_FLAGS) -#IF (CMAKE_SYSTEM MATCHES "Linux-([3-9]\\.[0-9]|2\\.[4-9])\\.") IF (NOT WINDOWS) # Linux Specific flags SET (HDF5_EXTRA_FLAGS -D_POSIX_SOURCE -D_BSD_SOURCE) @@ -331,7 +336,6 @@ IF (NOT WINDOWS) ENDIF (HDF5_ENABLE_LARGE_FILE) SET (CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} ${HDF5_EXTRA_FLAGS}) ENDIF (NOT WINDOWS) -#ENDIF (CMAKE_SYSTEM MATCHES "Linux-([3-9]\\.[0-9]|2\\.[4-9])\\.") ADD_DEFINITIONS (${HDF5_EXTRA_FLAGS}) @@ -632,7 +636,8 @@ ENDIF (NOT WINDOWS) #----------------------------------------------------------------------------- # Check if InitOnceExecuteOnce is available #----------------------------------------------------------------------------- -IF (WINDOWS AND NOT HDF5_NO_IOEO_TEST) +IF (WINDOWS) + IF (NOT HDF5_NO_IOEO_TEST) MESSAGE (STATUS "Checking for InitOnceExecuteOnce:") IF("${H5_HAVE_IOEO}" MATCHES "^${H5_HAVE_IOEO}$") IF (LARGEFILE) @@ -690,7 +695,8 @@ IF (WINDOWS AND NOT HDF5_NO_IOEO_TEST) "Return value: ${HAVE_IOEO_EXITCODE}\n") ENDIF("${HAVE_IOEO_EXITCODE}" EQUAL 0) ENDIF("${H5_HAVE_IOEO}" MATCHES "^${H5_HAVE_IOEO}$") -ENDIF (WINDOWS AND NOT HDF5_NO_IOEO_TEST) + ENDIF (NOT HDF5_NO_IOEO_TEST) +ENDIF (WINDOWS) #----------------------------------------------------------------------------- diff --git a/config/cmake/FindSZIP.cmake b/config/cmake/FindSZIP.cmake index 6118f7a..b358862 100644 --- a/config/cmake/FindSZIP.cmake +++ b/config/cmake/FindSZIP.cmake @@ -44,11 +44,11 @@ MACRO (SZIP_ADJUST_LIB_VARS basename) # if the generator supports configuration types then set # optimized and debug libraries, or if the CMAKE_BUILD_TYPE has a value IF (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE) - SET (${basename}_LIBRARY optimized ${${basename}_LIBRARY_RELEASE} debug ${${basename}_LIBRARY_DEBUG}) + SET (${basename}_LIBRARY optimized ${${basename}_LIBRARY_RELEASE} debug ${${basename}_LIBRARY_DEBUG}) ELSE(CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE) - # if there are no configuration types and CMAKE_BUILD_TYPE has no value - # then just use the release libraries - SET (${basename}_LIBRARY ${${basename}_LIBRARY_RELEASE} ) + # if there are no configuration types and CMAKE_BUILD_TYPE has no value + # then just use the release libraries + SET (${basename}_LIBRARY ${${basename}_LIBRARY_RELEASE} ) ENDIF (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE) SET (${basename}_LIBRARIES optimized ${${basename}_LIBRARY_RELEASE} debug ${${basename}_LIBRARY_DEBUG}) ENDIF (${basename}_LIBRARY_DEBUG AND ${basename}_LIBRARY_RELEASE) @@ -90,13 +90,13 @@ FIND_PATH (SZIP_INCLUDE_DIR NO_DEFAULT_PATH ) -IF (WIN32 AND NOT MINGW) +IF (WIN32) SET (SZIP_SEARCH_DEBUG_NAMES "sz_d;libsz_d") - SET (SZIP_SEARCH_RELEASE_NAMES "sz;libsz") -ELSE (WIN32 AND NOT MINGW) + SET (SZIP_SEARCH_RELEASE_NAMES "sz;libsz;libszip") +ELSE (WIN32) SET (SZIP_SEARCH_DEBUG_NAMES "sz_d") - SET (SZIP_SEARCH_RELEASE_NAMES "sz") -ENDIF (WIN32 AND NOT MINGW) + SET (SZIP_SEARCH_RELEASE_NAMES "sz;szip") +ENDIF (WIN32) # Look for the library. FIND_LIBRARY (SZIP_LIBRARY_DEBUG diff --git a/config/cmake/H5pubconf.h.in b/config/cmake/H5pubconf.h.in index b2567b5..80406a3 100644 --- a/config/cmake/H5pubconf.h.in +++ b/config/cmake/H5pubconf.h.in @@ -6,6 +6,9 @@ /* Define if the Windows virtual file driver should be compiled */ #cmakedefine H5_HAVE_WINDOWS @H5_HAVE_WINDOWS@ +/* Define if using MinGW */ +#cmakedefine H5_HAVE_MINGW @H5_HAVE_MINGW@ + /* Define if on the Windows platform and default WIN32 API */ #cmakedefine H5_HAVE_WIN32_API @H5_HAVE_WIN32_API@ diff --git a/config/cmake/HDFLibMacros.cmake b/config/cmake/HDFLibMacros.cmake index 23c81da..b9c1fbb 100644 --- a/config/cmake/HDFLibMacros.cmake +++ b/config/cmake/HDFLibMacros.cmake @@ -37,11 +37,11 @@ MACRO (EXTERNAL_JPEG_LIBRARY compress_type libtype jpeg_pic) EXTERNALPROJECT_GET_PROPERTY (JPEG BINARY_DIR SOURCE_DIR) IF (${CMAKE_BUILD_TYPE} MATCHES "Debug") - IF (WIN32 AND NOT MINGW) + IF (WIN32) SET (JPEG_LIB_NAME "jpeg_D") - ELSE (WIN32 AND NOT MINGW) + ELSE (WIN32) SET (JPEG_LIB_NAME "jpeg_debug") - ENDIF (WIN32 AND NOT MINGW) + ENDIF (WIN32) ELSE (${CMAKE_BUILD_TYPE} MATCHES "Debug") SET (JPEG_LIB_NAME "jpeg") ENDIF (${CMAKE_BUILD_TYPE} MATCHES "Debug") @@ -51,12 +51,19 @@ MACRO (EXTERNAL_JPEG_LIBRARY compress_type libtype jpeg_pic) ADD_DEPENDENCIES (jpeg JPEG) IF (${libtype} MATCHES "SHARED") - IF (WIN32 AND NOT MINGW) - SET_TARGET_PROPERTIES(jpeg PROPERTIES - IMPORTED_IMPLIB "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${BLDTYPE}/${CMAKE_IMPORT_LIBRARY_PREFIX}${JPEG_LIB_NAME}${CMAKE_IMPORT_LIBRARY_SUFFIX}" - IMPORTED_LOCATION "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${BLDTYPE}/${CMAKE_IMPORT_LIBRARY_PREFIX}${JPEG_LIB_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}" - ) - ELSE (WIN32 AND NOT MINGW) + IF (WIN32) + IF (MINGW) + SET_TARGET_PROPERTIES(jpeg PROPERTIES + IMPORTED_IMPLIB "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${JPEG_LIB_NAME}.lib" + IMPORTED_LOCATION "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${JPEG_LIB_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}" + ) + ELSE (MINGW) + SET_TARGET_PROPERTIES(jpeg PROPERTIES + IMPORTED_IMPLIB "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${BLDTYPE}/${CMAKE_IMPORT_LIBRARY_PREFIX}${JPEG_LIB_NAME}${CMAKE_IMPORT_LIBRARY_SUFFIX}" + IMPORTED_LOCATION "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${BLDTYPE}/${CMAKE_IMPORT_LIBRARY_PREFIX}${JPEG_LIB_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}" + ) + ENDIF (MINGW) + ELSE (WIN32) IF (CYGWIN) SET_TARGET_PROPERTIES(jpeg PROPERTIES IMPORTED_IMPLIB "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${CMAKE_IMPORT_LIBRARY_PREFIX}${JPEG_LIB_NAME}${CMAKE_IMPORT_LIBRARY_SUFFIX}" @@ -69,7 +76,7 @@ MACRO (EXTERNAL_JPEG_LIBRARY compress_type libtype jpeg_pic) SOVERSION "${JPEG_VERSION_STRING}" ) ENDIF (CYGWIN) - ENDIF (WIN32 AND NOT MINGW) + ENDIF (WIN32) ELSE (${libtype} MATCHES "SHARED") IF (WIN32 AND NOT MINGW) SET_TARGET_PROPERTIES(jpeg PROPERTIES @@ -144,11 +151,11 @@ MACRO (EXTERNAL_SZIP_LIBRARY compress_type libtype encoding) EXTERNALPROJECT_GET_PROPERTY (SZIP BINARY_DIR SOURCE_DIR) IF (${CMAKE_BUILD_TYPE} MATCHES "Debug") - IF (WIN32 AND NOT MINGW) + IF (WIN32) SET (SZIP_LIB_NAME "szip_D") - ELSE (WIN32 AND NOT MINGW) + ELSE (WIN32) SET (SZIP_LIB_NAME "szip_debug") - ENDIF (WIN32 AND NOT MINGW) + ENDIF (WIN32) ELSE (${CMAKE_BUILD_TYPE} MATCHES "Debug") SET (SZIP_LIB_NAME "szip") ENDIF (${CMAKE_BUILD_TYPE} MATCHES "Debug") @@ -158,12 +165,19 @@ MACRO (EXTERNAL_SZIP_LIBRARY compress_type libtype encoding) ADD_DEPENDENCIES (szip SZIP) IF (${libtype} MATCHES "SHARED") - IF (WIN32 AND NOT MINGW) - SET_TARGET_PROPERTIES(szip PROPERTIES - IMPORTED_IMPLIB "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${BLDTYPE}/${CMAKE_IMPORT_LIBRARY_PREFIX}${SZIP_LIB_NAME}${CMAKE_IMPORT_LIBRARY_SUFFIX}" - IMPORTED_LOCATION "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${BLDTYPE}/${CMAKE_IMPORT_LIBRARY_PREFIX}${SZIP_LIB_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}" - ) - ELSE (WIN32 AND NOT MINGW) + IF (WIN32) + IF (MINGW) + SET_TARGET_PROPERTIES(szip PROPERTIES + IMPORTED_IMPLIB "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${SZIP_LIB_NAME}.lib" + IMPORTED_LOCATION "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${SZIP_LIB_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}" + ) + ELSE (MINGW) + SET_TARGET_PROPERTIES(szip PROPERTIES + IMPORTED_IMPLIB "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${BLDTYPE}/${CMAKE_IMPORT_LIBRARY_PREFIX}${SZIP_LIB_NAME}${CMAKE_IMPORT_LIBRARY_SUFFIX}" + IMPORTED_LOCATION "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${BLDTYPE}/${CMAKE_IMPORT_LIBRARY_PREFIX}${SZIP_LIB_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}" + ) + ENDIF (MINGW) + ELSE (WIN32) IF (CYGWIN) SET_TARGET_PROPERTIES(szip PROPERTIES IMPORTED_IMPLIB "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${CMAKE_IMPORT_LIBRARY_PREFIX}${SZIP_LIB_NAME}${CMAKE_IMPORT_LIBRARY_SUFFIX}" @@ -176,7 +190,7 @@ MACRO (EXTERNAL_SZIP_LIBRARY compress_type libtype encoding) SOVERSION "${SZIP_VERSION_STRING}" ) ENDIF (CYGWIN) - ENDIF (WIN32 AND NOT MINGW) + ENDIF (WIN32) ELSE (${libtype} MATCHES "SHARED") IF (WIN32 AND NOT MINGW) SET_TARGET_PROPERTIES(szip PROPERTIES @@ -249,17 +263,17 @@ MACRO (EXTERNAL_ZLIB_LIBRARY compress_type libtype) EXTERNALPROJECT_GET_PROPERTY (ZLIB BINARY_DIR SOURCE_DIR) IF (${CMAKE_BUILD_TYPE} MATCHES "Debug") - IF (WIN32 AND NOT MINGW) + IF (WIN32) SET (ZLIB_LIB_NAME "zlib_D") - ELSE (WIN32 AND NOT MINGW) + ELSE (WIN32) SET (ZLIB_LIB_NAME "z_debug") - ENDIF (WIN32 AND NOT MINGW) + ENDIF (WIN32) ELSE (${CMAKE_BUILD_TYPE} MATCHES "Debug") - IF (WIN32 AND NOT MINGW) + IF (WIN32) SET (ZLIB_LIB_NAME "zlib") - ELSE (WIN32 AND NOT MINGW) + ELSE (WIN32) SET (ZLIB_LIB_NAME "z") - ENDIF (WIN32 AND NOT MINGW) + ENDIF (WIN32) ENDIF (${CMAKE_BUILD_TYPE} MATCHES "Debug") # Create imported target szip @@ -267,12 +281,19 @@ MACRO (EXTERNAL_ZLIB_LIBRARY compress_type libtype) ADD_DEPENDENCIES (zlib ZLIB) IF (${libtype} MATCHES "SHARED") - IF (WIN32 AND NOT MINGW) - SET_TARGET_PROPERTIES(zlib PROPERTIES - IMPORTED_IMPLIB "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${BLDTYPE}/${CMAKE_IMPORT_LIBRARY_PREFIX}${ZLIB_LIB_NAME}${CMAKE_IMPORT_LIBRARY_SUFFIX}" - IMPORTED_LOCATION "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${BLDTYPE}/${CMAKE_IMPORT_LIBRARY_PREFIX}${ZLIB_LIB_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}" - ) - ELSE (WIN32 AND NOT MINGW) + IF (WIN32) + IF (MINGW) + SET_TARGET_PROPERTIES(zlib PROPERTIES + IMPORTED_IMPLIB "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${ZLIB_LIB_NAME}.lib" + IMPORTED_LOCATION "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${ZLIB_LIB_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}" + ) + ELSE (MINGW) + SET_TARGET_PROPERTIES(zlib PROPERTIES + IMPORTED_IMPLIB "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${BLDTYPE}/${CMAKE_IMPORT_LIBRARY_PREFIX}${ZLIB_LIB_NAME}${CMAKE_IMPORT_LIBRARY_SUFFIX}" + IMPORTED_LOCATION "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${BLDTYPE}/${CMAKE_IMPORT_LIBRARY_PREFIX}${ZLIB_LIB_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}" + ) + ENDIF (MINGW) + ELSE (WIN32) IF (CYGWIN) SET_TARGET_PROPERTIES(zlib PROPERTIES IMPORTED_IMPLIB "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${CMAKE_IMPORT_LIBRARY_PREFIX}${ZLIB_LIB_NAME}${CMAKE_IMPORT_LIBRARY_SUFFIX}" @@ -285,7 +306,7 @@ MACRO (EXTERNAL_ZLIB_LIBRARY compress_type libtype) SOVERSION "${ZLIB_VERSION_STRING}" ) ENDIF (CYGWIN) - ENDIF (WIN32 AND NOT MINGW) + ENDIF (WIN32) ELSE (${libtype} MATCHES "SHARED") IF (WIN32 AND NOT MINGW) SET_TARGET_PROPERTIES(zlib PROPERTIES diff --git a/config/cmake/HDFMacros.cmake b/config/cmake/HDFMacros.cmake index 6a1ead7..0d3ab5f 100644 --- a/config/cmake/HDFMacros.cmake +++ b/config/cmake/HDFMacros.cmake @@ -35,29 +35,29 @@ ENDMACRO (IDE_SOURCE_PROPERTIES) #------------------------------------------------------------------------------- MACRO (TARGET_NAMING target libtype) - IF (WIN32 AND NOT MINGW) + IF (WIN32) IF (${libtype} MATCHES "SHARED") SET_TARGET_PROPERTIES (${target} PROPERTIES OUTPUT_NAME "${target}dll") ENDIF (${libtype} MATCHES "SHARED") - ENDIF (WIN32 AND NOT MINGW) + ENDIF (WIN32) ENDMACRO (TARGET_NAMING) #------------------------------------------------------------------------------- MACRO (HDF_SET_LIB_OPTIONS libtarget libname libtype) # message (STATUS "${libname} libtype: ${libtype}") IF (${libtype} MATCHES "SHARED") - IF (WIN32 AND NOT MINGW) + IF (WIN32) SET (LIB_RELEASE_NAME "${libname}") SET (LIB_DEBUG_NAME "${libname}_D") - ELSE (WIN32 AND NOT MINGW) + ELSE (WIN32) SET (LIB_RELEASE_NAME "${libname}") SET (LIB_DEBUG_NAME "${libname}_debug") - ENDIF (WIN32 AND NOT MINGW) + ENDIF (WIN32) ELSE (${libtype} MATCHES "SHARED") - IF (WIN32 AND NOT MINGW) + IF (WIN32) SET (LIB_RELEASE_NAME "lib${libname}") SET (LIB_DEBUG_NAME "lib${libname}_D") - ELSE (WIN32 AND NOT MINGW) + ELSE (WIN32) # if the generator supports configuration types or if the CMAKE_BUILD_TYPE has a value IF (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE) SET (LIB_RELEASE_NAME "${libname}") @@ -66,7 +66,7 @@ MACRO (HDF_SET_LIB_OPTIONS libtarget libname libtype) SET (LIB_RELEASE_NAME "lib${libname}") SET (LIB_DEBUG_NAME "lib${libname}_debug") ENDIF (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE) - ENDIF (WIN32 AND NOT MINGW) + ENDIF (WIN32) ENDIF (${libtype} MATCHES "SHARED") SET_TARGET_PROPERTIES (${libtarget} diff --git a/config/gnu-flags b/config/gnu-flags index 38ea4e4..40aa1da 100644 --- a/config/gnu-flags +++ b/config/gnu-flags @@ -186,10 +186,84 @@ esac # the information from the previous version and adding modifications to that. case "$cc_vendor-$cc_version" in +# Closer to the gcc 4.8 release, we should check for additional flags to +# include and break it out into it's own section, like the other versions +# below. -QAK + gcc-4.[78]*) + # Replace -ansi flag with -std=c99 flag + H5_CFLAGS="`echo $H5_CFLAGS | sed -e 's/-ansi/-std=c99/g'`" + + # Append warning flags + # Don't use the '-Wtraditional' flag, we're way past having K&R C code + # H5_CFLAGS="$H5_CFLAGS -Wtraditional" + # Don't use the '-Wtraditional-conversion' flag, there's too many warnings + # from GCC's assert macro + # H5_CFLAGS="$H5_CFLAGS -Wtraditional-conversion" + + # Append warning flags from gcc-3* case + # (don't use -Wpadded flag for normal builds, many of the warnings its + # issuing can't be fixed and they are making it hard to detect other, + # more important warnings) + #H5_CFLAGS="$H5_CFLAGS -Wfloat-equal -Wmissing-format-attribute -Wpadded" + H5_CFLAGS="$H5_CFLAGS -Wfloat-equal -Wmissing-format-attribute" + + # Append warning flags from gcc-3.2* case + H5_CFLAGS="$H5_CFLAGS -Wmissing-noreturn -Wpacked -Wdisabled-optimization" + + # Enable more format checking flags, beyond the basic -Wformat included + # in -Wall + H5_CFLAGS="$H5_CFLAGS -Wformat=2" + + # The "unreachable code" warning appears to be reliable now... + # (this warning was removed in gcc 4.5+) + #H5_CFLAGS="$H5_CFLAGS -Wunreachable-code" + + # Append warning flags from gcc-3.3* case + H5_CFLAGS="$H5_CFLAGS -Wendif-labels" + + # Append warning flags from gcc-3.4* case + H5_CFLAGS="$H5_CFLAGS -Wdeclaration-after-statement -Wold-style-definition -Winvalid-pch" + + # Replace old -W flag with new -Wextra flag + H5_CFLAGS="`echo $H5_CFLAGS | sed -e 's/-W\ /-Wextra\ /g'`" + + # Append more extra warning flags that only gcc4.0+ know about + H5_CFLAGS="$H5_CFLAGS -Wvariadic-macros -Winit-self -Wmissing-include-dirs -Wswitch-default -Wswitch-enum -Wunused-macros" + + # Append more extra warning flags that only gcc 4.1+ know about + H5_CFLAGS="$H5_CFLAGS -Wunsafe-loop-optimizations -Wc++-compat" + + # Append more extra warning flags that only gcc 4.2+ know about + H5_CFLAGS="$H5_CFLAGS -Wstrict-overflow" + + # Append more extra warning flags that only gcc 4.3+ know about + # + # Technically, variable-length arrays are part of the C99 standard, but + # we should approach them a bit cautiously... -QAK + H5_CFLAGS="$H5_CFLAGS -Wlogical-op -Wlarger-than=2048 -Wvla" + + # Append more extra warning flags that only gcc 4.4+ know about + H5_CFLAGS="$H5_CFLAGS -Wsync-nand -Wframe-larger-than=16384 -Wpacked-bitfield-compat" + + # Append more extra warning flags that only gcc 4.5+ know about + H5_CFLAGS="$H5_CFLAGS -Wstrict-overflow=5 -Wjump-misses-init -Wunsuffixed-float-constants" + + # Append more extra warning flags that only gcc 4.6+ know about + H5_CFLAGS="$H5_CFLAGS -Wdouble-promotion -Wsuggest-attribute=const -Wtrampolines" + + # Append more extra warning flags that only gcc 4.7+ know about + H5_CFLAGS="$H5_CFLAGS -Wstack-usage=8192 -Wvector-operation-performance" + + # Try out the new "stack protector" feature in gcc 4.1 + # (Strictly speaking this isn't really a "warning" flag, so it's added to + # the debugging flags) + #DEBUG_CFLAGS="$DEBUG_CFLAGS -Wstack-protector -fstack-protector-all" + ;; + # Closer to the gcc 4.7 release, we should check for additional flags to # include and break it out into it's own section, like the other versions # below. -QAK - gcc-4.[67]*) + gcc-4.6*) # Replace -ansi flag with -std=c99 flag H5_CFLAGS="`echo $H5_CFLAGS | sed -e 's/-ansi/-std=c99/g'`" diff --git a/config/lt_vers.am b/config/lt_vers.am index c137d57..c492a0c 100644 --- a/config/lt_vers.am +++ b/config/lt_vers.am @@ -17,7 +17,7 @@ # Add libtool shared library version numbers to the HDF5 library # See libtool versioning documentation online. LT_VERS_INTERFACE = 6 -LT_VERS_REVISION = 101 +LT_VERS_REVISION = 103 LT_VERS_AGE = 0 ## If the API changes *at all*, increment LT_VERS_INTERFACE and diff --git a/configure b/configure index 60a4cd2..9216956 100755 --- a/configure +++ b/configure @@ -1,7 +1,7 @@ #! /bin/sh -# From configure.in Id: configure.in 21544 2011-10-13 13:28:44Z derobins . +# From configure.in Id: configure.in 22105 2012-03-21 15:10:17Z koziol . # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.68 for HDF5 1.9.111-FA_a5. +# Generated by GNU Autoconf 2.68 for HDF5 1.9.113-FA_a5. # # Report bugs to . # @@ -571,8 +571,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='HDF5' PACKAGE_TARNAME='hdf5' -PACKAGE_VERSION='1.9.111-FA_a5' -PACKAGE_STRING='HDF5 1.9.111-FA_a5' +PACKAGE_VERSION='1.9.113-FA_a5' +PACKAGE_STRING='HDF5 1.9.113-FA_a5' PACKAGE_BUGREPORT='help@hdfgroup.org' PACKAGE_URL='' @@ -1463,7 +1463,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures HDF5 1.9.111-FA_a5 to adapt to many kinds of systems. +\`configure' configures HDF5 1.9.113-FA_a5 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1533,7 +1533,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of HDF5 1.9.111-FA_a5:";; + short | recursive ) echo "Configuration of HDF5 1.9.113-FA_a5:";; esac cat <<\_ACEOF @@ -1726,7 +1726,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -HDF5 configure 1.9.111-FA_a5 +HDF5 configure 1.9.113-FA_a5 generated by GNU Autoconf 2.68 Copyright (C) 2010 Free Software Foundation, Inc. @@ -2815,7 +2815,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by HDF5 $as_me 1.9.111-FA_a5, which was +It was created by HDF5 $as_me 1.9.113-FA_a5, which was generated by GNU Autoconf 2.68. Invocation command line was $ $0 $@ @@ -3636,7 +3636,7 @@ fi # Define the identity of the package. PACKAGE='hdf5' - VERSION='1.9.111-FA_a5' + VERSION='1.9.113-FA_a5' cat >>confdefs.h <<_ACEOF @@ -21550,22 +21550,6 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu -case $host_os in - linux* | freebsd* ) - # If gcc is not used, need to set $wl to use "-Wl," - if $CC -v 2>&1 | grep '^gcc' > /dev/null ; then - : using gcc - else - echo 'fixing $wl in' $ofile -ed - $ofile < /dev/null -/^wl=""/s//wl="-Wl,"/ -w -q -EOF - fi - ;; -esac - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we should install only statically linked executables" >&5 $as_echo_n "checking if we should install only statically linked executables... " >&6; } # Check whether --enable-static_exec was given. @@ -30608,7 +30592,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by HDF5 $as_me 1.9.111-FA_a5, which was +This file was extended by HDF5 $as_me 1.9.113-FA_a5, which was generated by GNU Autoconf 2.68. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -30674,7 +30658,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -HDF5 config.status 1.9.111-FA_a5 +HDF5 config.status 1.9.113-FA_a5 configured by $0, generated by GNU Autoconf 2.68, with options \\"\$ac_cs_config\\" @@ -33472,7 +33456,7 @@ Usage: $0 [OPTIONS] Report bugs to ." lt_cl_version="\ -HDF5 config.lt 1.9.111-FA_a5 +HDF5 config.lt 1.9.113-FA_a5 configured by $0, generated by GNU Autoconf 2.68. Copyright (C) 2010 Free Software Foundation, Inc. @@ -34965,6 +34949,22 @@ touch ./config/stamp2 # Finally the makefiles test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 +case $host_os in + linux* | freebsd* ) + # If gcc is not used, need to set $wl to use "-Wl," + if $CC -v 2>&1 | grep '^gcc' > /dev/null ; then + : using gcc + else + echo 'fixing $wl in' $ofile +ed - $ofile < /dev/null +g/^wl=""/s//wl="-Wl,"/ +w +q +EOF + fi + ;; +esac + if (./libtool --features | grep '^enable shared libraries' > /dev/null); then enable_shared=yes else diff --git a/configure.in b/configure.in index 0fb5290..6d65538 100644 --- a/configure.in +++ b/configure.in @@ -26,7 +26,7 @@ dnl dnl NOTE: Don't forget to change the version number here when we do a dnl release!!! dnl -AC_INIT([HDF5], [1.9.111-FA_a5], [help@hdfgroup.org]) +AC_INIT([HDF5], [1.9.113-FA_a5], [help@hdfgroup.org]) AC_CONFIG_SRCDIR([src/H5.c]) AM_CONFIG_HEADER([src/H5config.h]) @@ -1022,24 +1022,6 @@ dnl or disabled, it should happen before these macros. AC_LIBTOOL_DLOPEN AM_PROG_LIBTOOL -dnl Post processing to patch up some deficiencies in libtool (as of -dnl Libtool 1.5.14) -case $host_os in - linux* | freebsd* ) - # If gcc is not used, need to set $wl to use "-Wl," - if $CC -v 2>&1 | grep '^gcc' > /dev/null ; then - : using gcc - else - echo 'fixing $wl in' $ofile -ed - $ofile < /dev/null -/^wl=""/s//wl="-Wl,"/ -w -q -EOF - fi - ;; -esac - dnl ---------------------------------------------------------------------- dnl Check if we should install only statically linked executables. dnl This check needs to occur after libtool is initialized because @@ -4469,6 +4451,23 @@ touch ./config/stamp2 # Finally the makefiles test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 +dnl Post processing to patch up some deficiencies in libtool +case $host_os in + linux* | freebsd* ) + # If gcc is not used, need to set $wl to use "-Wl," + if $CC -v 2>&1 | grep '^gcc' > /dev/null ; then + : using gcc + else + echo 'fixing $wl in' $ofile +ed - $ofile < /dev/null +g/^wl=""/s//wl="-Wl,"/ +w +q +EOF + fi + ;; +esac + dnl Are we compiling static libraries, shared libraries, or both? This dnl is only used for the libhdf5.settings file. We can't just look at dnl $enable_static and $enable_shared because if they're yes the ltconfig diff --git a/examples/run-c-ex.sh.in b/examples/run-c-ex.sh.in old mode 100755 new mode 100644 diff --git a/examples/testh5cc.sh.in b/examples/testh5cc.sh.in old mode 100755 new mode 100644 diff --git a/fortran/COPYING b/fortran/COPYING old mode 100755 new mode 100644 diff --git a/fortran/examples/run-fortran-ex.sh.in b/fortran/examples/run-fortran-ex.sh.in old mode 100755 new mode 100644 diff --git a/fortran/examples/testh5fc.sh.in b/fortran/examples/testh5fc.sh.in old mode 100755 new mode 100644 diff --git a/fortran/src/H5Of.c b/fortran/src/H5Of.c index 0df433a..531f09c 100644 --- a/fortran/src/H5Of.c +++ b/fortran/src/H5Of.c @@ -334,3 +334,60 @@ nh5oget_info_by_name_c (hid_t_f *loc_id, _fcd name, size_t_f *namelen, hid_t_f * return ret_value; } +/* ***if* H5Of/H5Ocopy_c + * NAME + * H5Ocopy_c + * PURPOSE + * Calls H5Ocopy + * INPUTS + * src_loc_id - Object identifier indicating the location of the source object to be copied + * src_name - Name of the source object to be copied + * src_name_len - Length of src_name + * dst_loc_id - Location identifier specifying the destination + * dst_name - Name to be assigned to the new copy + * dst_name_len - Length of dst_name + * ocpypl_id - Object copy property list + * lcpl_id - Link creation property list for the new hard link + * + * RETURNS + * 0 on success, -1 on failure + * AUTHOR + * M. Scot Breitenfeld + * March 14, 2012 + * SOURCE +*/ +int_f +nh5ocopy_c (hid_t_f *src_loc_id, _fcd src_name, size_t_f *src_name_len, + hid_t_f *dst_loc_id, _fcd dst_name, size_t_f *dst_name_len, + hid_t_f *ocpypl_id, hid_t_f *lcpl_id ) +/******/ +{ + char *c_src_name = NULL; /* Buffer to hold C string */ + char *c_dst_name = NULL; /* Buffer to hold C string */ + + int_f ret_value = 0; /* Return value */ + + /* + * Convert FORTRAN name to C name + */ + if((c_src_name = HD5f2cstring(src_name, (size_t)*src_name_len)) == NULL) + HGOTO_DONE(FAIL); + if((c_dst_name = HD5f2cstring(dst_name, (size_t)*dst_name_len)) == NULL) + HGOTO_DONE(FAIL); + + /* + * Call H5Ocopy function. + */ + if(H5Ocopy( (hid_t)*src_loc_id, c_src_name, (hid_t)*dst_loc_id, c_dst_name, + (hid_t)*ocpypl_id, (hid_t)*lcpl_id) < 0) + HGOTO_DONE(FAIL); + + done: + if(c_src_name) + HDfree(c_src_name); + if(c_dst_name) + HDfree(c_dst_name); + + return ret_value; + +} diff --git a/fortran/src/H5Off.f90 b/fortran/src/H5Off.f90 index e69fdb5..4f1ea18 100644 --- a/fortran/src/H5Off.f90 +++ b/fortran/src/H5Off.f90 @@ -49,33 +49,32 @@ CONTAINS ! ! PURPOSE ! Creates a hard link to an object in an HDF5 file. -! INPUTS +! +! Inputs: ! object_id - Object to be linked. ! new_loc_id - File or group identifier specifying location at which object is to be linked. ! new_link_name - Name of link to be created, relative to new_loc_id. -! OUTPUTS -! hdferr: - error code -! Success: 0 -! Failure: -1 -! OPTIONAL PARAMETERS +! +! Outputs: +! hdferr - Returns 0 if successful and -1 if fails. +! +! Optional parameters: ! lcpl_id - Link creation property list identifier. ! lapl_id - Link access property list identifier. +! ! AUTHOR ! M. Scot Breitenfeld ! April 21, 2008 ! -! SOURCE +! Fortran90 Interface: SUBROUTINE h5olink_f(object_id, new_loc_id, new_link_name, hdferr, lcpl_id, lapl_id) IMPLICIT NONE - INTEGER(HID_T), INTENT(IN) :: object_id ! Object to be linked - INTEGER(HID_T), INTENT(IN) :: new_loc_id ! File or group identifier specifying - ! location at which object is to be linked. - CHARACTER(LEN=*), INTENT(IN) :: new_link_name ! Name of link to be created, relative to new_loc_id. - INTEGER, INTENT(OUT) :: hdferr ! Error code - ! Success: 0 - ! Failure: -1 - INTEGER(HID_T), OPTIONAL, INTENT(IN) :: lcpl_id ! Link creation property list identifier. - INTEGER(HID_T), OPTIONAL, INTENT(IN) :: lapl_id ! Link creation property list identifier. + INTEGER(HID_T) , INTENT(IN) :: object_id + INTEGER(HID_T) , INTENT(IN) :: new_loc_id + CHARACTER(LEN=*), INTENT(IN) :: new_link_name + INTEGER , INTENT(OUT) :: hdferr + INTEGER(HID_T) , INTENT(IN), OPTIONAL :: lcpl_id + INTEGER(HID_T) , INTENT(IN), OPTIONAL :: lapl_id !***** INTEGER(HID_T) :: lapl_id_default INTEGER(HID_T) :: lcpl_id_default @@ -115,33 +114,33 @@ CONTAINS ! ! NAME ! h5oopen_f +! ! PURPOSE ! Opens an object in an HDF5 file by location identifier and path name. ! -! INPUTS -! loc_id - File or group identifier +! Inputs: +! loc_id - File or group identifier. ! name - Path to the object, relative to loc_id. -! OUTPUTS -! obj_id - Object identifier for the opened object -! hdferr: - error code -! Success: 0 -! Failure: -1 -! OPTIONAL PARAMETERS -! lapl_id - Access property list identifier for the link pointing to the object +! +! Outputs: +! obj_id - Object identifier for the opened object. +! hdferr - Returns 0 if successful and -1 if fails. +! +! Optional parameters: +! lapl_id - Access property list identifier for the link pointing to the object. ! ! AUTHOR ! M. Scot Breitenfeld ! April 18, 2008 -! SOURCE +! +! Fortran90 Interface: SUBROUTINE h5oopen_f(loc_id, name, obj_id, hdferr, lapl_id) IMPLICIT NONE - INTEGER(HID_T), INTENT(IN) :: loc_id ! File or group identifier - CHARACTER(LEN=*), INTENT(IN) :: name ! Path to the object, relative to loc_id - INTEGER(HID_T), INTENT(OUT) :: obj_id ! Object identifier for the opened object - INTEGER, INTENT(OUT) :: hdferr ! Error code - ! Success: 0 - ! Failure: -1 - INTEGER(HID_T), OPTIONAL, INTENT(IN) :: lapl_id ! Attribute access property list + INTEGER(HID_T) , INTENT(IN) :: loc_id + CHARACTER(LEN=*), INTENT(IN) :: name + INTEGER(HID_T) , INTENT(OUT) :: obj_id + INTEGER , INTENT(OUT) :: hdferr + INTEGER(HID_T) , INTENT(IN), OPTIONAL :: lapl_id !***** INTEGER(HID_T) :: lapl_id_default INTEGER(SIZE_T) :: namelen @@ -178,20 +177,21 @@ CONTAINS ! PURPOSE ! Closes an object in an HDF5 file. ! -! INPUTS -! object_id - Object identifier -! OUTPUTS -! hdferr - Returns 0 if successful and -1 if fails +! Inputs: +! object_id - Object identifier. +! +! Outputs: +! hdferr - Returns 0 if successful and -1 if fails. ! ! AUTHOR ! M. Scot Breitenfeld ! December 17, 2008 ! -! SOURCE +! Fortran90 Interface: SUBROUTINE h5oclose_f(object_id, hdferr) IMPLICIT NONE - INTEGER(HID_T), INTENT(IN) :: object_id - INTEGER, INTENT(OUT) :: hdferr + INTEGER(HID_T), INTENT(IN) :: object_id + INTEGER , INTENT(OUT) :: hdferr !***** INTERFACE INTEGER FUNCTION h5oclose_c(object_id) @@ -214,25 +214,25 @@ CONTAINS ! PURPOSE ! Opens an object using its address within an HDF5 file. ! -! INPUTS -! loc_id - File or group identifier -! addr - Object’s address in the file -! OUTPUTS: -! obj_id - Object identifier for the opened object -! hdferr - Returns 0 if successful and -1 if fails +! Inputs: +! loc_id - File or group identifier. +! addr - Object’s address in the file. +! +! Outputs: +! obj_id - Object identifier for the opened object. +! hdferr - Returns 0 if successful and -1 if fails. ! ! AUTHOR ! M. Scot Breitenfeld ! September 14, 2009 ! -! SOURCE +! Fortran90 Interface: SUBROUTINE h5oopen_by_addr_f(loc_id, addr, obj_id, hdferr) IMPLICIT NONE - INTEGER(HID_T), INTENT(IN) :: loc_id ! File or group identifier - INTEGER(HADDR_T), INTENT(IN) :: addr ! Object’s address in the file - INTEGER(HID_T), INTENT(OUT) :: obj_id ! Object identifier for the opened object - INTEGER, INTENT(OUT) :: hdferr ! Error code: - ! 0 on success and -1 on failure + INTEGER(HID_T) , INTENT(IN) :: loc_id + INTEGER(HADDR_T), INTENT(IN) :: addr + INTEGER(HID_T) , INTENT(OUT) :: obj_id + INTEGER , INTENT(OUT) :: hdferr !***** INTERFACE INTEGER FUNCTION h5oopen_by_addr_c(loc_id, addr, obj_id) @@ -249,6 +249,77 @@ CONTAINS hdferr = h5oopen_by_addr_c(loc_id, addr, obj_id) END SUBROUTINE h5oopen_by_addr_f +! +!****s* H5O/h5ocopy_f +! NAME +! h5ocopy_f +! +! PURPOSE +! Copies an object in an HDF5 file. +! +! Inputs: +! src_loc_id - Object identifier indicating the location of the source object to be copied. +! src_name - Name of the source object to be copied. +! dst_loc_id - Location identifier specifying the destination. +! dst_name - Name to be assigned to the new copy. +! +! Optional parameters: +! ocpypl_id - Object copy property list. +! lcpl_id - Link creation property list for the new hard link. +! +! Outputs: +! hdferr - Returns 0 if successful and -1 if fails. +! +! AUTHOR +! M. Scot Breitenfeld +! March 14, 2012 +! +! Fortran90 Interface: + SUBROUTINE h5ocopy_f(src_loc_id, src_name, dst_loc_id, dst_name, hdferr, ocpypl_id, lcpl_id) + IMPLICIT NONE + INTEGER(HID_T) , INTENT(IN) :: src_loc_id + CHARACTER(LEN=*), INTENT(IN) :: src_name + INTEGER(HID_T) , INTENT(IN) :: dst_loc_id + CHARACTER(LEN=*), INTENT(IN) :: dst_name + INTEGER , INTENT(OUT) :: hdferr + INTEGER(HID_T) , INTENT(IN), OPTIONAL :: ocpypl_id + INTEGER(HID_T) , INTENT(IN), OPTIONAL :: lcpl_id +!***** + + INTEGER(SIZE_T) :: src_name_len, dst_name_len + INTEGER(HID_T) :: ocpypl_id_default, lcpl_id_default + + INTERFACE + INTEGER FUNCTION h5ocopy_c(src_loc_id, src_name, src_name_len, & + dst_loc_id, dst_name, dst_name_len, ocpypl_id_default, lcpl_id_default) + USE H5GLOBAL + !DEC$IF DEFINED(HDF5F90_WINDOWS) + !DEC$ATTRIBUTES C,reference,decorate,alias:'H5OCOPY_C'::h5ocopy_c + !DEC$ENDIF + !DEC$ATTRIBUTES reference :: src_name, dst_name + INTEGER(HID_T) , INTENT(IN) :: src_loc_id + CHARACTER(LEN=*), INTENT(IN) :: src_name + INTEGER(HID_T) , INTENT(IN) :: dst_loc_id + CHARACTER(LEN=*), INTENT(IN) :: dst_name + INTEGER(HID_T) , INTENT(IN) :: ocpypl_id_default + INTEGER(HID_T) , INTENT(IN) :: lcpl_id_default + INTEGER(SIZE_T) :: src_name_len, dst_name_len + + END FUNCTION h5ocopy_c + END INTERFACE + + src_name_len = LEN(src_name) + dst_name_len = LEN(dst_name) + + ocpypl_id_default = H5P_DEFAULT_F + IF(PRESENT(ocpypl_id)) ocpypl_id_default = ocpypl_id + lcpl_id_default = H5P_DEFAULT_F + IF(PRESENT(lcpl_id)) lcpl_id_default = lcpl_id + + hdferr = h5ocopy_c(src_loc_id, src_name, src_name_len, & + dst_loc_id, dst_name, dst_name_len, ocpypl_id_default, lcpl_id_default) + + END SUBROUTINE h5ocopy_f END MODULE H5O diff --git a/fortran/src/H5Pff.f90 b/fortran/src/H5Pff.f90 index 2d874d0..d50e3b9 100644 --- a/fortran/src/H5Pff.f90 +++ b/fortran/src/H5Pff.f90 @@ -53,11 +53,23 @@ CONTAINS ! INPUTS ! class - type of the property class to be created. ! Possible values are: -! H5P_FILE_CREATE_F -! H5P_FILE_ACCESS_F -! H5P_DATASET_CREATE_F -! H5P_DATASET_XFER_F -! H5P_FILE_MOUNT_F +! H5P_OBJECT_CREATE_F +! H5P_FILE_CREATE_F +! H5P_FILE_ACCESS_F +! H5P_DATASET_CREATE_F +! H5P_DATASET_ACCESS_F +! H5P_DATASET_XFER_F +! H5P_FILE_MOUNT_F +! H5P_GROUP_CREATE_F +! H5P_GROUP_ACCESS_F +! H5P_DATATYPE_CREATE_F +! H5P_DATATYPE_ACCESS_F +! H5P_STRING_CREATE_F +! H5P_ATTRIBUTE_CREATE _F +! H5P_OBJECT_COPY_F +! H5P_LINK_CREATE_F +! H5P_LINK_ACCESS_F +! ! OUTPUTS ! prp_id - property list identifier ! hdferr - error code @@ -76,16 +88,9 @@ CONTAINS ! Fortran90 Interface: SUBROUTINE h5pcreate_f(class, prp_id, hdferr) IMPLICIT NONE - INTEGER(HID_T), INTENT(IN) :: class ! The type of the property list - ! to be created. Possible values are: - ! H5P_FILE_CREATE_F - ! H5P_FILE_ACCESS_F - ! H5P_DATASET_CREATE_F - ! H5P_DATASET_XFER_F - ! H5P_FILE_MOUNT_F - INTEGER(HID_T), INTENT(OUT) :: prp_id ! Property list identifier - INTEGER, INTENT(OUT) :: hdferr ! Error code - ! 0 on success and -1 on failure + INTEGER(HID_T), INTENT(IN) :: class + INTEGER(HID_T), INTENT(OUT) :: prp_id + INTEGER , INTENT(OUT) :: hdferr !***** ! INTEGER, EXTERNAL :: h5pcreate_c ! MS FORTRAN needs explicit interface for C functions called here. diff --git a/fortran/src/H5f90proto.h b/fortran/src/H5f90proto.h index 89957a4..a504653 100644 --- a/fortran/src/H5f90proto.h +++ b/fortran/src/H5f90proto.h @@ -805,10 +805,12 @@ H5_FCDLL int_f nh5tconvert_c(hid_t_f *src_id, hid_t_f *dst_id, size_t_f *nelmts, #define nh5olink_c H5_FC_FUNC_(h5olink_c, H5OLINK_C) #define nh5oopen_c H5_FC_FUNC_(h5oopen_c, H5OOPEN_C) -#define nh5oclose_c H5_FC_FUNC_(h5oclose_c, H5OCLOSE_C) +#define nh5oclose_c H5_FC_FUNC_(h5oclose_c, H5OCLOSE_C) #define nh5ovisit_c H5_FC_FUNC_(h5ovisit_c,H5OVISIT_C) #define nh5oget_info_by_name_c H5_FC_FUNC_(h5oget_info_by_name_c ,H5OGET_INFO_BY_NAME_C) #define nh5oopen_by_addr_c H5_FC_FUNC_(h5oopen_by_addr_c, H5OOPEN_BY_ADDR_C) +#define nh5ocopy_c H5_FC_FUNC_(h5ocopy_c, H5OCOPY_C) + H5_FCDLL int_f nh5oopen_c (hid_t_f *loc_id, _fcd name, size_t_f *namelen, hid_t_f *lapl_id, hid_t_f *obj_id); H5_FCDLL int_f nh5oclose_c (hid_t_f *object_id ); @@ -818,6 +820,9 @@ H5_FCDLL int_f nh5olink_c (hid_t_f *object_id, hid_t_f *new_loc_id, _fcd name, s H5_FCDLL int_f nh5ovisit_c (hid_t_f *group_id, int_f *index_type, int_f *order, H5O_iterate_t op, void *op_data); H5_FCDLL int_f nh5oget_info_by_name_c (hid_t_f *loc_id, _fcd name, size_t_f *namelen,hid_t_f *lapl_id, H5O_info_t_f *object_info); +H5_FCDLL int_f nh5ocopy_c (hid_t_f *src_loc_id, _fcd src_name, size_t_f *src_name_len, + hid_t_f *dst_loc_id, _fcd dst_name, size_t_f *dst_name_len, + hid_t_f *ocpypl_id, hid_t_f *lcpl_id ); /* * Functions from H5Pf.c */ diff --git a/fortran/src/Makefile.in b/fortran/src/Makefile.in index 0ccaf33..c963c83 100644 --- a/fortran/src/Makefile.in +++ b/fortran/src/Makefile.in @@ -478,7 +478,7 @@ CHECK_CLEANFILES = *.chkexe *.chklog *.clog # Add libtool shared library version numbers to the HDF5 library # See libtool versioning documentation online. LT_VERS_INTERFACE = 6 -LT_VERS_REVISION = 101 +LT_VERS_REVISION = 103 LT_VERS_AGE = 0 # Include src directory in both Fortran and C flags (C compiler is used diff --git a/fortran/src/h5fc.in b/fortran/src/h5fc.in old mode 100755 new mode 100644 index 9e9409d..2d7b5b4 --- a/fortran/src/h5fc.in +++ b/fortran/src/h5fc.in @@ -189,7 +189,7 @@ for arg in $@ ; do get_output_file="yes" fi ;; - -E|-M) + -E|-M|-MT) allargs="$allargs $arg" compile_args="$compile_args $arg" dash_c="yes" diff --git a/fortran/src/hdf5_fortrandll.def b/fortran/src/hdf5_fortrandll.def index 6b3aad8..29e83f5 100644 --- a/fortran/src/hdf5_fortrandll.def +++ b/fortran/src/hdf5_fortrandll.def @@ -284,6 +284,7 @@ H5L_mp_H5LIS_REGISTERED_F H5L_mp_H5LMOVE_F H5L_mp_H5LGET_NAME_BY_IDX_F ; H5O +H5O_mp_H5OCOPY_F H5O_mp_H5OLINK_F H5O_mp_H5OOPEN_F H5O_mp_H5OOPEN_BY_ADDR_F diff --git a/fortran/src/phdf5_fortrandll.def b/fortran/src/phdf5_fortrandll.def index a4bc9eb..7a196cd 100644 --- a/fortran/src/phdf5_fortrandll.def +++ b/fortran/src/phdf5_fortrandll.def @@ -284,6 +284,7 @@ H5L_mp_H5LIS_REGISTERED_F H5L_mp_H5LMOVE_F H5L_mp_H5LGET_NAME_BY_IDX_F ; H5O +H5O_mp_H5OCOPY_F H5O_mp_H5OLINK_F H5O_mp_H5OOPEN_F H5O_mp_H5OOPEN_BY_ADDR_F diff --git a/fortran/test/CMakeLists.txt b/fortran/test/CMakeLists.txt index e6ddbaf..d19baea 100644 --- a/fortran/test/CMakeLists.txt +++ b/fortran/test/CMakeLists.txt @@ -73,6 +73,7 @@ SET_TARGET_PROPERTIES (testhdf5_fortran PROPERTIES LINKER_LANGUAGE Fortran) SET_TARGET_PROPERTIES (testhdf5_fortran PROPERTIES FOLDER test/fortran) ADD_TEST (NAME testhdf5_fortran COMMAND $) +SET_TESTS_PROPERTIES(testhdf5_fortran PROPERTIES PASS_REGULAR_EXPRESSION "[ ]*0 error.s") #-- Adding test for testhdf5_fortran_1_8 ADD_EXECUTABLE (testhdf5_fortran_1_8 @@ -96,6 +97,7 @@ SET_TARGET_PROPERTIES (testhdf5_fortran_1_8 PROPERTIES LINKER_LANGUAGE Fortran) SET_TARGET_PROPERTIES (testhdf5_fortran_1_8 PROPERTIES FOLDER test/fortran) ADD_TEST (NAME testhdf5_fortran_1_8 COMMAND $) +SET_TESTS_PROPERTIES(testhdf5_fortran_1_8 PROPERTIES PASS_REGULAR_EXPRESSION "[ ]*0 error.s") #-- Adding test for fortranlib_test_F03 IF (FORTRAN_HAVE_ISO_C_BINDING AND HDF5_ENABLE_F2003) @@ -121,6 +123,7 @@ IF (FORTRAN_HAVE_ISO_C_BINDING AND HDF5_ENABLE_F2003) SET_TARGET_PROPERTIES (fortranlib_test_F03 PROPERTIES FOLDER test/fortran) ADD_TEST (NAME fortranlib_test_F03 COMMAND $) + SET_TESTS_PROPERTIES(fortranlib_test_F03 PROPERTIES PASS_REGULAR_EXPRESSION "[ ]*0 error.s") ENDIF (FORTRAN_HAVE_ISO_C_BINDING AND HDF5_ENABLE_F2003) #-- Adding test for fflush1 diff --git a/fortran/test/tH5O.f90 b/fortran/test/tH5O.f90 index d871e59..247d1d0 100644 --- a/fortran/test/tH5O.f90 +++ b/fortran/test/tH5O.f90 @@ -72,6 +72,7 @@ SUBROUTINE test_h5o_link(total_error) INTEGER(HID_T) :: type_id INTEGER(HID_T) :: fapl_id INTEGER(HID_T) :: lcpl_id + INTEGER(HID_T) :: ocpypl_id INTEGER(HID_T) :: mem_space_id, file_space_id, xfer_prp CHARACTER(LEN=11), PARAMETER :: TEST_FILENAME = 'TestFile.h5' INTEGER, PARAMETER :: TEST6_DIM1 = 2, TEST6_DIM2 = 5 @@ -82,52 +83,65 @@ SUBROUTINE test_h5o_link(total_error) INTEGER, PARAMETER :: TRUE = 1, FALSE = 0 - LOGICAL :: committed ! /* Whether the named datatype is committed */ + LOGICAL :: committed ! /* Whether the named datatype is committed INTEGER :: i, n, j - INTEGER :: error ! /* Value returned from API calls */ - - ! /* Initialize the raw data */ + INTEGER :: error ! /* Value returned from API calls + + CHARACTER(LEN=14) :: NAME_DATATYPE_SIMPLE="H5T_NATIVE_INT" + CHARACTER(LEN=16) :: NAME_DATATYPE_SIMPLE2="H5T_NATIVE_INT-2" + INTEGER(HID_T) :: tid, tid2 + LOGICAL :: flag + + ! Data for tested h5ocopy_f + CHARACTER(LEN=3) , PARAMETER :: dataset = "DS1" + INTEGER , PARAMETER :: dim0 = 4 + + INTEGER(HSIZE_T), DIMENSION(1:1) :: dims2 = (/dim0/) ! size read/write buffer + INTEGER , DIMENSION(1:dim0) :: wdata2, & ! Write buffer + rdata2 ! Read buffer + + ! Initialize the raw data DO i = 1, TEST6_DIM1 DO j = 1, TEST6_DIM2 wdata(i,j) = i*j ENDDO ENDDO - ! /* Create the dataspace */ + ! Create the dataspace CALL h5screate_simple_f(2, dims, space_id, error) CALL check("h5screate_simple_f",error,total_error) - ! /* Create LCPL with intermediate group creation flag set */ + ! Create LCPL with intermediate group creation flag set CALL H5Pcreate_f(H5P_LINK_CREATE_F, lcpl_id, error) CALL check("h5Pcreate_f",error,total_error) CALL H5Pset_create_inter_group_f(lcpl_id, TRUE, error) CALL check("H5Pset_create_inter_group_f",error,total_error) - ! /* Loop over using new group format */ + ! Loop over using new group format ! for(new_format = FALSE; new_format <= TRUE; new_format++) { - !/* Make a FAPL that uses the "use the latest version of the format" bounds */ + ! Make a FAPL that uses the "use the latest version of the format" bounds CALL H5Pcreate_f(H5P_FILE_ACCESS_F,fapl_id,error) CALL check("h5Pcreate_f",error,total_error) - ! /* Set the "use the latest version of the format" bounds for creating objects in the file */ + ! Set the "use the latest version of the format" bounds for creating objects in the file CALL H5Pset_libver_bounds_f(fapl_id, H5F_LIBVER_LATEST_F, H5F_LIBVER_LATEST_F, error) CALL check("H5Pset_libver_bounds_f",error, total_error) !!$ ret = H5Pset_libver_bounds(fapl_id, (new_format ? H5F_LIBVER_LATEST : H5F_LIBVER_EARLIEST), H5F_LIBVER_LATEST); - ! /* Create a new HDF5 file */ + ! Create a new HDF5 file CALL H5Fcreate_f(TEST_FILENAME, H5F_ACC_TRUNC_F, file_id, error, H5P_DEFAULT_F, fapl_id) CALL check("H5Fcreate_f", error, total_error) - ! /* Close the FAPL */ + ! Close the FAPL CALL h5pclose_f(fapl_id, error) CALL check("h5pclose_f",error,total_error) - ! /* Create and commit a datatype with no name */ + ! Create and commit a datatype with no name CALL H5Tcopy_f( H5T_NATIVE_INTEGER, type_id, error) CALL check("H5Tcopy_F",error,total_error) @@ -138,27 +152,27 @@ SUBROUTINE test_h5o_link(total_error) CALL check("H5Tcommitted_f",error,total_error) CALL verifyLogical("H5Tcommitted_f", committed, .TRUE., total_error) - ! /* Create a dataset with no name using the committed datatype*/ + ! Create a dataset with no name using the committed datatype CALL H5Dcreate_anon_f(file_id, type_id, space_id, dset_id, error ) ! using no optional parameters CALL check("H5Dcreate_anon_f",error,total_error) - ! /* Verify that we can write to and read from the dataset */ + ! Verify that we can write to and read from the dataset - ! /* Write the data to the dataset */ + ! Write the data to the dataset !EP CALL h5dwrite_f(dset_id, H5T_NATIVE_INTEGER, wdata, dims, error, & !EP mem_space_id=H5S_ALL_F, file_space_id=H5S_ALL_F, xfer_prp = H5P_DEFAULT_F) CALL h5dwrite_f(dset_id, H5T_NATIVE_INTEGER, wdata, dims, error) CALL check("h5dwrite_f", error, total_error) - ! /* Read the data back */ + ! Read the data back !EP CALL h5dread_f(dset_id, H5T_NATIVE_INTEGER, rdata, dims, error, & !EP mem_space_id=H5S_ALL_F, file_space_id=H5S_ALL_F, xfer_prp = H5P_DEFAULT_F) CALL h5dread_f(dset_id, H5T_NATIVE_INTEGER, rdata, dims, error) CALL check("h5dread_f", error, total_error) - ! /* Verify the data */ + ! Verify the data DO i = 1, TEST6_DIM1 DO j = 1, TEST6_DIM2 CALL VERIFY("H5Dread_f",wdata(i,j),rdata(i,j),total_error) @@ -166,31 +180,31 @@ SUBROUTINE test_h5o_link(total_error) ENDDO ENDDO - ! /* Create a group with no name*/ + ! Create a group with no name CALL H5Gcreate_anon_f(file_id, group_id, error) CALL check("H5Gcreate_anon", error, total_error) - ! /* Link nameless datatype into nameless group */ + ! Link nameless datatype into nameless group CALL H5Olink_f(type_id, group_id, "datatype", error, H5P_DEFAULT_F) CALL check("H5Olink_f", error, total_error) - ! /* Link nameless dataset into nameless group with intermediate group */ + ! Link nameless dataset into nameless group with intermediate group CALL H5Olink_f(dset_id, group_id, "inter_group/dataset", error, lcpl_id, H5P_DEFAULT_F) CALL check("H5Olink_f", error, total_error) - ! /* Close IDs for dataset and datatype */ + ! Close IDs for dataset and datatype CALL h5dclose_f(dset_id, error) CALL check("h5dclose_f", error, total_error) CALL h5tclose_f(type_id, error) CALL check("h5tclose_f", error, total_error) - ! /* Re-open datatype using new link */ + ! Re-open datatype using new link CALL H5Topen_f(group_id, "datatype", type_id, error) CALL check("h5topen_f", error, total_error) - ! /* Link nameless group to root group and close the group ID*/ + ! Link nameless group to root group and close the group ID CALL H5Olink_f(group_id, file_id, "/group", error) CALL check("H5Olink_f", error, total_error) @@ -198,46 +212,162 @@ SUBROUTINE test_h5o_link(total_error) CALL h5gclose_f(group_id, error) CALL check("h5gclose_f",error,total_error) - ! /* Open dataset through root group and verify its data */ + ! Open dataset through root group and verify its data CALL H5Dopen_f(file_id, "/group/inter_group/dataset", dset_id, error) CALL check("test_lcpl.h5dopen_f", error, total_error) - ! /* Read data from dataset */ + ! Read data from dataset !EP CALL h5dread_f(dset_id, H5T_NATIVE_INTEGER, rdata, dims, error, & !EP H5S_ALL_F, H5S_ALL_F, xfer_prp = H5P_DEFAULT_F) CALL h5dread_f(dset_id, H5T_NATIVE_INTEGER, rdata, dims, error) CALL check("h5dread_f", error, total_error) - ! /* Verify the data */ + ! Verify the data DO i = 1, TEST6_DIM1 DO j = 1, TEST6_DIM2 CALL VERIFY("H5Dread",wdata(i,j),rdata(i,j),total_error) ENDDO ENDDO - ! /* Close open IDs */ + ! Close open IDs CALL h5dclose_f(dset_id, error) CALL check("h5dclose_f",error,total_error) CALL h5tclose_f(type_id, error) CALL check("h5tclose_f",error,total_error) - CALL h5fclose_f(file_id, error) - CALL check("h5fclose_f",error,total_error) - ! /* Close remaining IDs */ + ! Close remaining IDs CALL h5sclose_f(space_id, error) CALL check("h5sclose_f",error,total_error) CALL h5pclose_f(lcpl_id,error) CALL check("h5pclose_f", error, total_error) + ! ********************* + ! CHECK H5OCOPY_F + ! ********************* + + DO i = 1, dim0 + wdata2(i) = i-1 + ENDDO + ! + ! Create dataspace. Setting size to be the current size. + ! + CALL h5screate_simple_f(1, dims2, space_id, error) + CALL check("h5screate_simple_f", error, total_error) + ! + ! Create intermediate groups + ! + CALL h5gcreate_f(file_id,"/G1",group_id,error) + CALL check("h5gcreate_f", error, total_error) + CALL h5gcreate_f(file_id,"/G1/G2",group_id,error) + CALL check("h5gcreate_f", error, total_error) + CALL h5gcreate_f(file_id,"/G1/G2/G3",group_id,error) + CALL check("h5gcreate_f", error, total_error) + ! + ! Create the dataset + ! + CALL h5dcreate_f(group_id, dataset, H5T_STD_I32LE, space_id, dset_id, error) + CALL check("h5dcreate_f", error, total_error) + ! + ! Write the data to the dataset. + ! + CALL h5dwrite_f(dset_id, H5T_NATIVE_INTEGER, wdata2, dims2, error) + CALL check("h5dwrite_f", error, total_error) + ! + ! Close and release resources. + ! + CALL h5dclose_f(dset_id , error) + CALL check(" h5dclose_f", error, total_error) + CALL h5sclose_f(space_id, error) + CALL check("h5sclose_f", error, total_error) + CALL h5gclose_f(group_id, error) + CALL check("h5gclose_f", error, total_error) + ! + ! create property to pass copy options + ! + CALL h5pcreate_f(H5P_LINK_CREATE_F, lcpl_id, error) + CALL check("h5Pcreate_f", error, total_error) + + CALL h5pset_create_inter_group_f(lcpl_id, TRUE, error) + CALL check("H5Pset_create_inter_group_f", error, total_error) + ! + ! Check optional parameter lcpl_id, this would fail if lcpl_id was not specified + ! + CALL h5ocopy_f(file_id, "/G1/G2/G3/DS1", file_id, "/G1/G_cp1/DS2", error, lcpl_id=lcpl_id) + CALL check("h5ocopy_f -- W/ OPTION: lcpl_id", error ,total_error) + + CALL h5pclose_f(lcpl_id, error) + CALL check("h5pclose_f",error,total_error) + + CALL h5pcreate_f(H5P_OBJECT_COPY_F, ocpypl_id, error) + CALL check("h5Pcreate_f",error,total_error) + + CALL h5pset_copy_object_f(ocpypl_id, H5O_COPY_SHALLOW_HIERARCHY_F, error) + CALL check("H5Pset_copy_object_f",error,total_error) + + CALL h5ocopy_f(file_id, "/G1/G2", file_id, "/G1/G_cp2", error, ocpypl_id=ocpypl_id) + CALL check("h5ocopy_f",error,total_error) + + ! Makes sure the "DS1" dataset was not copied since we set a + ! flag to copy only immediate members of a group. + ! Therefore, this should fail. + CALL h5dopen_f(file_id, "/G1/G_cp2/DS1", dset_id, error) + IF(error.EQ.0)THEN + CALL check("h5ocopy_f -- W/ OPTION: ocpypl_id", -1, total_error) + ENDIF + + CALL h5pclose_f(ocpypl_id, error) + CALL check("h5pclose_f",error,total_error) + + ! create datatype + CALL h5tcopy_f(H5T_NATIVE_INTEGER, tid, error) + CALL check("h5tcopy_f", error, total_error) + + ! create named datatype + CALL h5tcommit_f(file_id, NAME_DATATYPE_SIMPLE, tid, error) + CALL check("h5tcommit_f", error, total_error) + + ! close the datatype + CALL h5tclose_f(tid, error) + CALL check("h5tclose_f",error) + + CALL h5ocopy_f(file_id, NAME_DATATYPE_SIMPLE, file_id, NAME_DATATYPE_SIMPLE2, error) + CALL check("h5ocopy_f",error,total_error) + + ! open the datatype for copy + CALL h5topen_f(file_id, NAME_DATATYPE_SIMPLE, tid, error) + CALL check("h5topen_f",error,total_error) + + ! open the copied datatype + CALL h5topen_f(file_id, NAME_DATATYPE_SIMPLE2, tid2, error) + CALL check("h5topen_f",error,total_error) + + ! Compare the datatypes + CALL h5tequal_f(tid, tid2, flag, error) + IF(.NOT.flag)THEN + WRITE(*,*) "h5ocopy_f FAILED" + total_error = total_error + 1 + ENDIF + + ! close the destination datatype + CALL h5tclose_f(tid, error) + CALL check("h5tclose_f",error,total_error) + + ! close the destination datatype + CALL h5tclose_f(tid2, error) + CALL check("h5tclose_f",error,total_error) + + CALL h5fclose_f(file_id, error) + CALL check("h5fclose_f",error,total_error) + END SUBROUTINE test_h5o_link -!/**************************************************************** +!*************************************************************** !** !** test_h5o_plist(): Test object creation properties !** -!****************************************************************/ +!*************************************************************** SUBROUTINE test_h5o_plist(total_error) @@ -246,31 +376,31 @@ SUBROUTINE test_h5o_plist(total_error) IMPLICIT NONE INTEGER, INTENT(OUT) :: total_error - INTEGER(hid_t) :: fid !/* HDF5 File ID */ - INTEGER(hid_t) :: grp, dset, dtype, dspace !/* Object identifiers */ - INTEGER(hid_t) :: fapl !/* File access property list */ - INTEGER(hid_t) :: gcpl, dcpl, tcpl !/* Object creation properties */ - INTEGER :: def_max_compact, def_min_dense !/* Default phase change parameters */ - INTEGER :: max_compact, min_dense !/* Actual phase change parameters */ - INTEGER :: error !/* Value returned from API calls */ + INTEGER(hid_t) :: fid ! HDF5 File ID + INTEGER(hid_t) :: grp, dset, dtype, dspace ! Object identifiers + INTEGER(hid_t) :: fapl ! File access property list + INTEGER(hid_t) :: gcpl, dcpl, tcpl ! Object creation properties + INTEGER :: def_max_compact, def_min_dense ! Default phase change parameters + INTEGER :: max_compact, min_dense ! Actual phase change parameters + INTEGER :: error ! Value returned from API calls CHARACTER(LEN=7), PARAMETER :: TEST_FILENAME = 'test.h5' ! PRINT*,'Testing object creation properties' - !/* Make a FAPL that uses the "use the latest version of the format" flag */ + ! Make a FAPL that uses the "use the latest version of the format" flag CALL H5Pcreate_f(H5P_FILE_ACCESS_F, fapl, error) CALL check("H5Pcreate_f", error, total_error) - ! /* Set the "use the latest version of the format" bounds for creating objects in the file */ + ! Set the "use the latest version of the format" bounds for creating objects in the file CALL H5Pset_libver_bounds_f(fapl, H5F_LIBVER_LATEST_F, H5F_LIBVER_LATEST_F, error) CALL check("H5Pcreate_f", error, total_error) - ! /* Create a new HDF5 file */ + ! Create a new HDF5 file CALL H5Fcreate_f(TEST_FILENAME, H5F_ACC_TRUNC_F, fid, error, access_prp=fapl) CALL check("H5Fcreate_f", error, total_error) - ! /* Create group, dataset & named datatype creation property lists */ + ! Create group, dataset & named datatype creation property lists CALL H5Pcreate_f(H5P_GROUP_CREATE_F, gcpl, error) CALL check("H5Pcreate_f", error, total_error) CALL H5Pcreate_f(H5P_DATASET_CREATE_F, dcpl, error) @@ -278,11 +408,11 @@ SUBROUTINE test_h5o_plist(total_error) CALL H5Pcreate_f(H5P_DATATYPE_CREATE_F, tcpl, error) CALL check("H5Pcreate_f", error, total_error) - ! /* Retrieve default attribute phase change values */ + ! Retrieve default attribute phase change values CALL H5Pget_attr_phase_change_f(gcpl, def_max_compact, def_min_dense, error) CALL check("H5Pget_attr_phase_change_f", error, total_error) - ! /* Set non-default attribute phase change values on each creation property list */ + ! Set non-default attribute phase change values on each creation property list CALL H5Pset_attr_phase_change_f(gcpl, def_max_compact+1, def_min_dense-1, error) CALL check("H5Pget_attr_phase_change_f", error, total_error) CALL H5Pset_attr_phase_change_f(dcpl, def_max_compact+1, def_min_dense-1, error) @@ -290,7 +420,7 @@ SUBROUTINE test_h5o_plist(total_error) CALL H5Pset_attr_phase_change_f(tcpl, def_max_compact+1, def_min_dense-1, error) CALL check("H5Pget_attr_phase_change_f", error, total_error) - ! /* Retrieve attribute phase change values on each creation property list and verify */ + ! Retrieve attribute phase change values on each creation property list and verify CALL H5Pget_attr_phase_change_f(gcpl, max_compact, min_dense, error) CALL check("H5Pget_attr_phase_change_f", error, total_error) CALL VERIFY("H5Pget_attr_phase_change_f", max_compact, (def_max_compact + 1), total_error) @@ -307,18 +437,18 @@ SUBROUTINE test_h5o_plist(total_error) CALL VERIFY("H5Pget_attr_phase_change_f", min_dense, (def_min_dense - 1), total_error) - !/* Create a group, dataset, and committed datatype within the file, - ! * using the respective type of creation property lists. - ! */ + ! Create a group, dataset, and committed datatype within the file, + ! using the respective type of creation property lists. + ! - !/* Create the group anonymously and link it in */ + ! Create the group anonymously and link it in CALL H5Gcreate_anon_f(fid, grp, error, gcpl_id=gcpl) CALL check("H5Gcreate_anon_f", error, total_error) CALL H5Olink_f(grp, fid, "group", error) CALL check("H5Olink_f", error, total_error) - ! /* Commit the type inside the group anonymously and link it in */ + ! Commit the type inside the group anonymously and link it in CALL h5tcopy_f(H5T_NATIVE_INTEGER, dtype, error) CALL check("h5tcopy_f", error, total_error) @@ -328,11 +458,11 @@ SUBROUTINE test_h5o_plist(total_error) CALL H5Olink_f(dtype, fid, "datatype", error) CALL check("H5Olink_f", error, total_error) - ! /* Create the dataspace for the dataset. */ + ! Create the dataspace for the dataset. CALL h5screate_f(H5S_SCALAR_F, dspace, error) CALL check("h5screate_f",error,total_error) - ! /* Create the dataset anonymously and link it in */ + ! Create the dataset anonymously and link it in CALL H5Dcreate_anon_f(fid, H5T_NATIVE_INTEGER, dspace, dset, error, dcpl ) CALL check("H5Dcreate_anon_f",error,total_error) @@ -343,7 +473,7 @@ SUBROUTINE test_h5o_plist(total_error) CALL check("h5sclose_f",error,total_error) - ! /* Close current creation property lists */ + ! Close current creation property lists CALL h5pclose_f(gcpl,error) CALL check("h5pclose_f", error, total_error) CALL h5pclose_f(dcpl,error) @@ -351,7 +481,7 @@ SUBROUTINE test_h5o_plist(total_error) CALL h5pclose_f(tcpl,error) CALL check("h5pclose_f", error, total_error) - ! /* Retrieve each object's creation property list */ + ! Retrieve each object's creation property list CALL H5Gget_create_plist_f(grp, gcpl, error) CALL check("H5Gget_create_plist", error, total_error) @@ -363,7 +493,7 @@ SUBROUTINE test_h5o_plist(total_error) CALL check("H5Dget_create_plist_f", error, total_error) - ! /* Retrieve attribute phase change values on each creation property list and verify */ + ! Retrieve attribute phase change values on each creation property list and verify CALL H5Pget_attr_phase_change_f(gcpl, max_compact, min_dense, error) CALL check("H5Pget_attr_phase_change_f", error, total_error) CALL VERIFY("H5Pget_attr_phase_change_f", max_compact, (def_max_compact + 1), total_error) @@ -380,7 +510,7 @@ SUBROUTINE test_h5o_plist(total_error) CALL VERIFY("H5Pget_attr_phase_change_f", min_dense, (def_min_dense - 1), total_error) - !/* Close current objects */ + ! Close current objects CALL h5pclose_f(gcpl,error) CALL check("h5pclose_f", error, total_error) @@ -398,11 +528,11 @@ SUBROUTINE test_h5o_plist(total_error) CALL check("h5dclose_f",error,total_error) CALL h5fclose_f(fid, error) CALL check("h5fclose_f",error,total_error) - ! /* Re-open the file and check that the object creation properties persist */ + ! Re-open the file and check that the object creation properties persist CALL h5fopen_f(TEST_FILENAME, H5F_ACC_RDONLY_F, fid, error, access_prp=fapl) CALL check("H5fopen_f",error,total_error) - ! /* Re-open objects */ + ! Re-open objects CALL H5Gopen_f(fid, "group", grp, error) CALL check("h5gopen_f", error, total_error) @@ -412,7 +542,7 @@ SUBROUTINE test_h5o_plist(total_error) CALL H5Dopen_f(fid, "dataset", dset, error) CALL check("h5dopen_f", error, total_error) - ! /* Retrieve each object's creation property list */ + ! Retrieve each object's creation property list CALL H5Gget_create_plist_f(grp, gcpl, error) CALL check("H5Gget_create_plist", error, total_error) @@ -423,7 +553,7 @@ SUBROUTINE test_h5o_plist(total_error) CALL check("H5Dget_create_plist_f", error, total_error) - ! /* Retrieve attribute phase change values on each creation property list and verify */ + ! Retrieve attribute phase change values on each creation property list and verify CALL H5Pget_attr_phase_change_f(gcpl, max_compact, min_dense, error) CALL check("H5Pget_attr_phase_change_f", error, total_error) CALL VERIFY("H5Pget_attr_phase_change_f", max_compact, (def_max_compact + 1), total_error) @@ -440,7 +570,7 @@ SUBROUTINE test_h5o_plist(total_error) CALL VERIFY("H5Pget_attr_phase_change_f", min_dense, (def_min_dense - 1), total_error) - ! /* Close current objects */ + ! Close current objects CALL h5pclose_f(gcpl,error) CALL check("h5pclose_f", error, total_error) @@ -459,7 +589,7 @@ SUBROUTINE test_h5o_plist(total_error) CALL h5fclose_f(fid, error) CALL check("h5fclose_f",error,total_error) - ! /* Close the FAPL */ + ! Close the FAPL CALL H5Pclose_f(fapl, error) CALL check("H5Pclose_f", error, total_error) diff --git a/hl/COPYING b/hl/COPYING old mode 100755 new mode 100644 diff --git a/hl/Makefile.in b/hl/Makefile.in old mode 100755 new mode 100644 diff --git a/hl/c++/COPYING b/hl/c++/COPYING old mode 100755 new mode 100644 diff --git a/hl/c++/examples/run-hlc++-ex.sh.in b/hl/c++/examples/run-hlc++-ex.sh.in old mode 100755 new mode 100644 diff --git a/hl/c++/src/Makefile.in b/hl/c++/src/Makefile.in index d9db5de..af3203d 100644 --- a/hl/c++/src/Makefile.in +++ b/hl/c++/src/Makefile.in @@ -421,7 +421,7 @@ CHECK_CLEANFILES = *.chkexe *.chklog *.clog # Add libtool shared library version numbers to the HDF5 library # See libtool versioning documentation online. LT_VERS_INTERFACE = 6 -LT_VERS_REVISION = 101 +LT_VERS_REVISION = 103 LT_VERS_AGE = 0 # Include src directory diff --git a/hl/examples/run-hlc-ex.sh.in b/hl/examples/run-hlc-ex.sh.in old mode 100755 new mode 100644 diff --git a/hl/fortran/COPYING b/hl/fortran/COPYING old mode 100755 new mode 100644 diff --git a/hl/fortran/examples/run-hlfortran-ex.sh.in b/hl/fortran/examples/run-hlfortran-ex.sh.in old mode 100755 new mode 100644 diff --git a/hl/fortran/src/H5DSfc.c b/hl/fortran/src/H5DSfc.c old mode 100755 new mode 100644 index 6816347..3135cfa --- a/hl/fortran/src/H5DSfc.c +++ b/hl/fortran/src/H5DSfc.c @@ -283,7 +283,7 @@ nh5dsget_label_c(hid_t_f *did, int_f *idx, _fcd label, size_t_f *size) * Convert C name to FORTRAN and place it in the given buffer */ - HD5packFstring(c_label, _fcdtocp(label), (size_t)*size+1); + HD5packFstring(c_label, _fcdtocp(label), (size_t)*size); done: *size = (size_t_f)size_c; /* Don't subtract '1' because H5DSget_label doesn't include the @@ -332,7 +332,7 @@ nh5dsget_scale_name_c(hid_t_f *did, _fcd name, size_t_f *size) * Convert C name to FORTRAN and place it in the given buffer */ if(size_c != 0) { - HD5packFstring(c_scale_name, _fcdtocp(name), (size_t)*size+1); + HD5packFstring(c_scale_name, _fcdtocp(name), (size_t)*size); *size = (size_t_f)size_c-1; /* (-1) because we don't include the NULL ending in the length*/ } else { *size = (size_t_f)size_c; /* if NULL then no name was found */ diff --git a/hl/fortran/src/H5DSff.f90 b/hl/fortran/src/H5DSff.f90 old mode 100755 new mode 100644 diff --git a/hl/fortran/src/H5IMfc.c b/hl/fortran/src/H5IMfc.c old mode 100755 new mode 100644 diff --git a/hl/fortran/src/H5IMff.f90 b/hl/fortran/src/H5IMff.f90 old mode 100755 new mode 100644 diff --git a/hl/fortran/src/H5LTf90proto.h b/hl/fortran/src/H5LTf90proto.h old mode 100755 new mode 100644 index 205871c..8618fc6 --- a/hl/fortran/src/H5LTf90proto.h +++ b/hl/fortran/src/H5LTf90proto.h @@ -1140,7 +1140,8 @@ nh5ltget_attribute_string_c(hid_t_f *loc_id, _fcd dsetname, int_f *attrnamelen, _fcd attrname, - void *buf); + _fcd buf, + size_t_f *buf_size); HDF5_HL_F90CSTUBDLL int_f diff --git a/hl/fortran/src/H5LTfc.c b/hl/fortran/src/H5LTfc.c old mode 100755 new mode 100644 index c0b7695..674636d --- a/hl/fortran/src/H5LTfc.c +++ b/hl/fortran/src/H5LTfc.c @@ -17,8 +17,7 @@ #include "H5LTprivate.h" #include "H5LTf90proto.h" - - +#include "H5Eprivate.h" /*------------------------------------------------------------------------- * Function: H5LTmake_dataset_c @@ -1719,13 +1718,13 @@ nh5ltget_attribute_string_c(hid_t_f *loc_id, _fcd dsetname, int_f *attrnamelen, _fcd attrname, - void *buf) + _fcd buf, size_t_f *buf_size) { int ret_value = -1; herr_t ret; - hid_t c_loc_id; char *c_name = NULL; char *c_attrname = NULL; + char *c_buf = NULL; int c_namelen; int c_attrnamelen; @@ -1741,26 +1740,33 @@ nh5ltget_attribute_string_c(hid_t_f *loc_id, c_attrname = (char *)HD5f2cstring(attrname, c_attrnamelen); if (c_attrname == NULL) goto done; - /* - * Call H5LTget_attribute_int function. - */ - c_loc_id = (hid_t)*loc_id; - - ret = H5LTget_attribute_string(c_loc_id,c_name,c_attrname,buf); + * Allocate buffer to hold C attribute string + */ + if ((c_buf = HDmalloc((size_t)*buf_size + 1)) == NULL) + goto done; + /* + * Call H5LTget_attribute_int function. + */ + ret = H5LTget_attribute_string((hid_t)*loc_id,c_name,c_attrname,c_buf); if (ret < 0) goto done; - ret_value = 0; + /* + * Convert C name to FORTRAN and place it in the given buffer + */ + HD5packFstring(c_buf, _fcdtocp(buf), (size_t)*buf_size); + ret_value = 0; done: if(c_name!=NULL) free(c_name); if(c_attrname!=NULL) free(c_attrname); - + if(c_buf!=NULL) + free(c_buf); return ret_value; } @@ -2157,7 +2163,7 @@ nh5ltpath_valid_c(hid_t_f *loc_id, /* * convert FORTRAN name to C name */ - if( NULL == (c_path = (char *)HD5f2cstring(path, (int)*pathlen))) + if( NULL == (c_path = (char *)HD5f2cstring(path, (size_t)*pathlen))) goto done; check_object_valid = FALSE; diff --git a/hl/fortran/src/H5LTff.f90 b/hl/fortran/src/H5LTff.f90 old mode 100755 new mode 100644 index 7d53ab7..0302b61 --- a/hl/fortran/src/H5LTff.f90 +++ b/hl/fortran/src/H5LTff.f90 @@ -5969,9 +5969,10 @@ CONTAINS CHARACTER(len=*), INTENT(inout) :: buf ! data buffer INTEGER :: namelen ! name length INTEGER :: attrlen ! name length + INTEGER(size_t) :: buf_size ! buf size INTERFACE - INTEGER FUNCTION h5ltget_attribute_string_c(loc_id,namelen,dset_name,attrlen,attr_name,buf) + INTEGER FUNCTION h5ltget_attribute_string_c(loc_id,namelen,dset_name,attrlen,attr_name,buf,buf_size) USE h5global !DEC$IF DEFINED(HDF5F90_WINDOWS) !DEC$ATTRIBUTES C,reference,decorate,alias:'H5LTGET_ATTRIBUTE_STRING_C'::h5ltget_attribute_string_c @@ -5984,12 +5985,15 @@ CONTAINS CHARACTER(len=*), INTENT(in) :: dset_name ! name of the dataset CHARACTER(len=*), INTENT(in) :: attr_name ! name of the attribute CHARACTER(len=*), INTENT(inout) :: buf ! data buffer + INTEGER(size_t) :: buf_size ! data buffer size END FUNCTION h5ltget_attribute_string_c END INTERFACE namelen = LEN(dset_name) attrlen = LEN(attr_name) - errcode = h5ltget_attribute_string_c(loc_id,namelen,dset_name,attrlen,attr_name,buf) + buf_size = LEN(buf) + + errcode = h5ltget_attribute_string_c(loc_id,namelen,dset_name,attrlen,attr_name,buf,buf_size) END SUBROUTINE h5ltget_attribute_string_f @@ -6335,7 +6339,7 @@ CONTAINS !DEC$attributes dllexport :: h5ltpath_valid_f !DEC$endif ! - INTEGER(hid_t) , INTENT(IN) :: loc_id ! File or group identifier. + INTEGER(hid_t) , INTENT(IN) :: loc_id ! An identifier of an object in the file. CHARACTER(LEN=*), INTENT(IN) :: path ! Path to the object to check, relative to loc_id. LOGICAL , INTENT(IN) :: check_object_valid ! Indicates whether to check if the final component ! of the path resolves to a valid object @@ -6360,14 +6364,16 @@ CONTAINS END FUNCTION h5ltpath_valid_c END INTERFACE + ! Initialize + path_valid = .FALSE. + errcode = 0 + check_object_valid_c = 0 IF(check_object_valid) check_object_valid_c = 1 pathlen = LEN(path) status = h5ltpath_valid_c(loc_id, path, pathlen, check_object_valid_c) - path_valid = .FALSE. - errcode = 0 IF(status.EQ.1)THEN path_valid = .TRUE. ELSE IF(status.LT.0)THEN diff --git a/hl/fortran/src/H5TBfc.c b/hl/fortran/src/H5TBfc.c old mode 100755 new mode 100644 diff --git a/hl/fortran/src/H5TBff.f90 b/hl/fortran/src/H5TBff.f90 old mode 100755 new mode 100644 diff --git a/hl/fortran/src/Makefile.in b/hl/fortran/src/Makefile.in index 4056a1b..e9ec78f 100644 --- a/hl/fortran/src/Makefile.in +++ b/hl/fortran/src/Makefile.in @@ -436,7 +436,7 @@ CHECK_CLEANFILES = *.chkexe *.chklog *.clog # Add libtool shared library version numbers to the HDF5 library # See libtool versioning documentation online. LT_VERS_INTERFACE = 6 -LT_VERS_REVISION = 101 +LT_VERS_REVISION = 103 LT_VERS_AGE = 0 INCLUDES = -I$(top_srcdir)/src -I$(top_srcdir)/hl/src -I$(top_builddir)/hl/src \ -I$(top_srcdir)/fortran/src -I$(top_builddir)/fortran/src diff --git a/hl/fortran/test/tstds.f90 b/hl/fortran/test/tstds.f90 index 8817989..c73e1c4 100644 --- a/hl/fortran/test/tstds.f90 +++ b/hl/fortran/test/tstds.f90 @@ -186,7 +186,10 @@ SUBROUTINE test_testds(err) name_len = 25 name = '' CALL H5DSget_scale_name_f(dsid, name, name_len, err) - IF(err.LT.0.OR.name_len.NE.21.OR.TRIM(name).NE."Dimension Scale Set 1")THEN + IF(err.LT.0 .OR. & + name_len.NE.21 .OR. & + TRIM(name).NE."Dimension Scale Set 1" .OR. & + name(22:25).NE.' ')THEN err = FAILED CALL write_test_status(err) RETURN @@ -293,7 +296,10 @@ SUBROUTINE test_testds(err) label_len = 25 label = '' CALL H5DSget_label_f(did, DIM2, label, label_len, err) - IF(err.LT.0.OR.label(1:label_len).NE."Label12".OR.label_len.NE.7)THEN + IF(err.LT.0.OR. & + label(1:label_len).NE."Label12" .OR. & + label_len.NE.7 .OR. & + label(8:25).NE.' ')THEN err = FAILED CALL write_test_status(err) RETURN diff --git a/hl/fortran/test/tstimage.f90 b/hl/fortran/test/tstimage.f90 old mode 100755 new mode 100644 diff --git a/hl/fortran/test/tstlite.f90 b/hl/fortran/test/tstlite.f90 index 9329dba..0b5a138 100644 --- a/hl/fortran/test/tstlite.f90 +++ b/hl/fortran/test/tstlite.f90 @@ -1342,7 +1342,9 @@ SUBROUTINE test_attributes() IMPLICIT NONE CHARACTER(len=9), PARAMETER :: filename = "dsetf5.h5"! File name + CHARACTER(len=9), PARAMETER :: filename1 ="tattr.h5" ! C written attribute file INTEGER(HID_T) :: file_id ! File identifier + INTEGER(HID_T) :: file_id1 INTEGER, PARAMETER :: DIM1 = 10; ! Dimension of array CHARACTER(LEN=5), PARAMETER :: attrname1 = "attr1" ! Attribute name CHARACTER(LEN=5), PARAMETER :: attrname2 = "attr2" ! Attribute name @@ -1350,9 +1352,11 @@ SUBROUTINE test_attributes() CHARACTER(LEN=5), PARAMETER :: attrname4 = "attr4" ! Attribute name CHARACTER(LEN=5), PARAMETER :: attrname5 = "attr5" ! Attribute name CHARACTER(LEN=8), PARAMETER :: buf1 = "mystring" ! Data buffer + CHARACTER(LEN=16), PARAMETER :: buf_c = "string attribute" CHARACTER(LEN=8) :: bufr1 ! Data buffer CHARACTER(LEN=10) :: bufr1_lg ! Data buffer - CHARACTER(LEN=6) :: bufr1_sm ! Data buffer + CHARACTER(LEN=16) :: bufr_c ! Data buffer + CHARACTER(LEN=18) :: bufr_c_lg ! Data buffer INTEGER, DIMENSION(DIM1) :: buf2 ! Data buffer INTEGER, DIMENSION(DIM1) :: bufr2 ! Data buffer REAL, DIMENSION(DIM1) :: buf3 ! Data buffer @@ -1370,6 +1374,7 @@ SUBROUTINE test_attributes() INTEGER :: rank = 1 ! Dataset rank CHARACTER(LEN=5), PARAMETER :: dsetname1 = "dset1" ! Dataset name INTEGER, DIMENSION(DIM1) :: buf ! Data buffer + ! ! Initialize FORTRAN predefined datatypes. @@ -1488,15 +1493,12 @@ SUBROUTINE test_attributes() CALL passed() - - !------------------------------------------------------------------------- ! string !------------------------------------------------------------------------- CALL test_begin(' Set/Get attributes string ') - ! ! write attribute. ! @@ -1530,19 +1532,36 @@ SUBROUTINE test_attributes() STOP ENDIF - ! - ! read attribute into a fortran character buf that is smaller then buf1. - ! - CALL h5ltget_attribute_string_f(file_id,dsetname1,attrname5,bufr1_sm,errcode) - - ! - ! compare read and write buffers. - ! - IF ( buf1(1:6) .NE. bufr1_sm(1:6) ) THEN - PRINT *, 'smaller read buffer differs from write buffer' - PRINT *, buf1, ' and ', bufr1_sm - STOP - ENDIF + ! + ! ** Test reading a string that was created with a C program ** + ! + +!!$ CALL h5fopen_f(filename1, H5F_ACC_RDONLY_F, file_id1, errcode) +!!$ +!!$ CALL h5ltget_attribute_string_f(file_id1, "/", "attr5", bufr_c, errcode) +!!$ ! +!!$ ! compare read and write buffers. +!!$ ! +!!$ IF ( bufr_c .NE. buf_c ) THEN +!!$ PRINT *, 'read buffer differs from write buffer' +!!$ PRINT *, bufr1, ' and ', buf_c +!!$ STOP +!!$ ENDIF +!!$ ! +!!$ ! read attribute into a fortran character buf that is larger then buf_c. +!!$ ! +!!$ CALL h5ltget_attribute_string_f(file_id1, "/", "attr5", bufr_c_lg, errcode) +!!$ +!!$ ! +!!$ ! compare read and write buffers, make sure C NULL character was removed. +!!$ ! +!!$ IF ( buf_c(1:16) .NE. bufr_c_lg(1:16) .AND. bufr_c_lg(17:18) .NE. ' ' ) THEN +!!$ PRINT *, 'larger read buffer differs from write buffer' +!!$ PRINT *, buf_c, ' and ', bufr_c_lg +!!$ STOP +!!$ ENDIF + +!!$ CALL h5fclose_f(file_id1, errcode) CALL passed() diff --git a/hl/fortran/test/tsttable.f90 b/hl/fortran/test/tsttable.f90 old mode 100755 new mode 100644 diff --git a/hl/src/COPYING b/hl/src/COPYING old mode 100755 new mode 100644 diff --git a/hl/src/H5LT.c b/hl/src/H5LT.c index eeaceeb..678642f 100644 --- a/hl/src/H5LT.c +++ b/hl/src/H5LT.c @@ -17,6 +17,7 @@ #include #include #include + #include "H5LTprivate.h" #include "H5private.h" @@ -31,7 +32,461 @@ char *myinput; size_t indent = 0; +/* File Image operations + + A file image is a representation of an HDF5 file in a memory + buffer. In order to perform operations on an image in a similar way + to a file, the application buffer is copied to a FAPL buffer, which + in turn is copied to a VFD buffer. Buffer copying can decrease + performance, especially when using large file images. A solution to + this issue is to simulate the copying of the application buffer, + when actually the same buffer is used for the FAPL and the VFD. + This is implemented by using callbacks that simulate the standard + functions for memory management (additional callbacks are used for + the management of associated data structures). From the application + standpoint, a file handle can be obtained from a file image by using + the API routine H5LTopen_file_image(). This function takes a flag + argument that indicates the HDF5 library how to handle the given image; + several flag values can be combined by using the bitwise OR operator. + Valid flag values include: + + H5LT_FILE_IMAGE_OPEN_RW indicates the HDF5 library to open the file + image in read/write mode. Default is read-only mode. + + H5LT_FILE_IMAGE_DONT_COPY indicates the HDF5 library to not copy the + supplied user buffer; the same buffer will be handled by the FAPL and + the VFD driver. Default operation copies the user buffer to the FAPL and + VFD driver. + + H5LT_FILE_IMAGE_DONT_RELEASE indicates the HDF5 library to not release + the buffer handled by the FAPL and the VFD upon closing. This flag value + is only applicable when the flag value H5LT_FILE_IMAGE_DONT_COPY is set as + well. The application is responsible to release the image buffer. +*/ + +/* Data structure to pass application data to callbacks. */ +typedef struct { + void *app_image_ptr; /* Pointer to application buffer */ + size_t app_image_size; /* Size of application buffer */ + void *fapl_image_ptr; /* Pointer to FAPL buffer */ + size_t fapl_image_size; /* Size of FAPL buffer */ + int fapl_ref_count; /* Reference counter for FAPL buffer */ + void *vfd_image_ptr; /* Pointer to VFD buffer */ + size_t vfd_image_size; /* Size of VFD buffer */ + int vfd_ref_count; /* Reference counter for VFD buffer */ + unsigned flags; /* Flags indicate how the file image will */ + /* be open */ + int ref_count; /* Reference counter on udata struct */ +} H5LT_file_image_ud_t; + +/* callbacks prototypes for file image ops */ +static void *image_malloc(size_t size, H5FD_file_image_op_t file_image_op, void *udata); +static void *image_memcpy(void *dest, const void *src, size_t size, H5FD_file_image_op_t file_image_op, void *udata); +static void *image_realloc(void *ptr, size_t size, H5FD_file_image_op_t file_image_op, void *udata); +static herr_t image_free(void *ptr, H5FD_file_image_op_t file_image_op, void *udata); +static void *udata_copy(void *udata); +static herr_t udata_free(void *udata); + +/* Definition of callbacks for file image operations. */ + + +/*------------------------------------------------------------------------- +* Function: image_malloc +* +* Purpose: Simulates malloc() function to avoid copying file images. +* The application buffer is set to the buffer on only one FAPL. +* Then the FAPL buffer can be copied to other FAPL buffers or +* to only one VFD buffer. +* +* Return: Address of "allocated" buffer, if successful. Otherwise, it returns +* NULL. +* +* Programmer: Christian Chilan +* +* Date: October 3, 2011 +* +*------------------------------------------------------------------------- +*/ +static void * +image_malloc(size_t size, H5FD_file_image_op_t file_image_op, void *_udata) +{ + H5LT_file_image_ud_t *udata = (H5LT_file_image_ud_t *)_udata; + void * return_value = NULL; + + /* callback is only used if the application buffer is not actually copied */ + if (!(udata->flags & H5LT_FILE_IMAGE_DONT_COPY)) + goto out; + + switch ( file_image_op ) { + /* the app buffer is "copied" to only one FAPL. Afterwards, FAPLs can be "copied" */ + case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_SET: + if (udata->app_image_ptr == NULL) + goto out; + if (udata->app_image_size != size) + goto out; + if (udata->fapl_image_ptr != NULL) + goto out; + if (udata->fapl_image_size != 0) + goto out; + if (udata->fapl_ref_count != 0) + goto out; + + udata->fapl_image_ptr = udata->app_image_ptr; + udata->fapl_image_size = udata->app_image_size; + return_value = udata->fapl_image_ptr; + udata->fapl_ref_count++; + break; + + case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_COPY: + if (udata->fapl_image_ptr == NULL) + goto out; + if (udata->fapl_image_size != size) + goto out; + if (udata->fapl_ref_count == 0) + goto out; + return_value = udata->fapl_image_ptr; + udata->fapl_ref_count++; + break; + + case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_GET: + goto out; + + case H5FD_FILE_IMAGE_OP_FILE_OPEN: + /* FAPL buffer is "copied" to only one VFD buffer */ + if (udata->vfd_image_ptr != NULL) + goto out; + if (udata->vfd_image_size != 0) + goto out; + if (udata->vfd_ref_count != 0) + goto out; + if (udata->fapl_image_ptr == NULL) + goto out; + if (udata->fapl_image_size != size) + goto out; + if (udata->fapl_ref_count == 0) + goto out; + + udata->vfd_image_ptr = udata->fapl_image_ptr; + udata->vfd_image_size = size; + udata->vfd_ref_count++; + return_value = udata->vfd_image_ptr; + break; + + /* added unused labels to shut the compiler up */ + case H5FD_FILE_IMAGE_OP_NO_OP: + case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_CLOSE: + case H5FD_FILE_IMAGE_OP_FILE_RESIZE: + case H5FD_FILE_IMAGE_OP_FILE_CLOSE: + default: + goto out; + } /* end switch */ + + return(return_value); + +out: + return NULL; +} /* end image_malloc() */ + + +/*------------------------------------------------------------------------- +* Function: image_memcpy +* +* Purpose: Simulates memcpy() function to avoid copying file images. +* The image buffer can be set to only one FAPL buffer, and +* "copied" to only one VFD buffer. The FAPL buffer can be +* "copied" to other FAPLs buffers. +* +* Return: The address of the destination buffer, if successful. Otherwise, it +* returns NULL. +* +* Programmer: Christian Chilan +* +* Date: October 3, 2011 +* +*------------------------------------------------------------------------- +*/ +static void * +image_memcpy(void *dest, const void *src, size_t size, H5FD_file_image_op_t file_image_op, + void *_udata) +{ + H5LT_file_image_ud_t *udata = (H5LT_file_image_ud_t *)_udata; + + /* callback is only used if the application buffer is not actually copied */ + if (!(udata->flags & H5LT_FILE_IMAGE_DONT_COPY)) + goto out; + + switch(file_image_op) { + case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_SET: + if (dest != udata->fapl_image_ptr) + goto out; + if (src != udata->app_image_ptr) + goto out; + if (size != udata->fapl_image_size) + goto out; + if (size != udata->app_image_size) + goto out; + if (udata->fapl_ref_count == 0) + goto out; + break; + + case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_COPY: + if (dest != udata->fapl_image_ptr) + goto out; + if (src != udata->fapl_image_ptr) + goto out; + if (size != udata->fapl_image_size) + goto out; + if (udata->fapl_ref_count < 2) + goto out; + break; + + case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_GET: + goto out; + + case H5FD_FILE_IMAGE_OP_FILE_OPEN: + if (dest != udata->vfd_image_ptr) + goto out; + if (src != udata->fapl_image_ptr) + goto out; + if (size != udata->vfd_image_size) + goto out; + if (size != udata->fapl_image_size) + goto out; + if (udata->fapl_ref_count == 0) + goto out; + if (udata->vfd_ref_count != 1) + goto out; + break; + + /* added unused labels to shut the compiler up */ + case H5FD_FILE_IMAGE_OP_NO_OP: + case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_CLOSE: + case H5FD_FILE_IMAGE_OP_FILE_RESIZE: + case H5FD_FILE_IMAGE_OP_FILE_CLOSE: + default: + goto out; + } /* end switch */ + + return(dest); + +out: + return NULL; +} /* end image_memcpy() */ + + +/*------------------------------------------------------------------------- +* Function: image_realloc +* +* Purpose: Reallocates the shared application image buffer and updates data +* structures that manage buffer "copying". +* +* Return: Address of reallocated buffer, if successful. Otherwise, it returns +* NULL. +* +* Programmer: Christian Chilan +* +* Date: October 3, 2011 +* +*------------------------------------------------------------------------- +*/ +static void * +image_realloc(void *ptr, size_t size, H5FD_file_image_op_t file_image_op, void *_udata) +{ + H5LT_file_image_ud_t *udata = (H5LT_file_image_ud_t *)_udata; + void * return_value = NULL; + + /* callback is only used if the application buffer is not actually copied */ + if (!(udata->flags & H5LT_FILE_IMAGE_DONT_COPY)) + goto out; + + /* realloc() is not allowed when the HDF5 library won't release the image + buffer because reallocation may change the address of the buffer. The + new address cannot be communicated to the application to release it. */ + if (udata->flags & H5LT_FILE_IMAGE_DONT_RELEASE) + goto out; + + /* realloc() is not allowed if the image is open in read-only mode */ + if (!(udata->flags & H5LT_FILE_IMAGE_OPEN_RW)) + goto out; + + if (file_image_op == H5FD_FILE_IMAGE_OP_FILE_RESIZE) { + if (udata->vfd_image_ptr != ptr) + goto out; + + if (udata->vfd_ref_count != 1) + goto out; + + if (NULL == (udata->vfd_image_ptr = HDrealloc(ptr, size))) + goto out; + + udata->vfd_image_size = size; + return_value = udata->vfd_image_ptr; + } /* end if */ + else + goto out; + + return(return_value); + +out: + return NULL; +} /* end image_realloc() */ + + +/*------------------------------------------------------------------------- +* Function: image_free +* +* Purpose: Simulates deallocation of FAPL and VFD buffers by decreasing +* reference counters. Shared application buffer is actually +* deallocated if there are no outstanding references. +* +* Return: SUCCEED or FAIL +* +* Programmer: Christian Chilan +* +* Date: October 3, 2011 +* +*------------------------------------------------------------------------- +*/ +static herr_t +image_free(void *ptr, H5FD_file_image_op_t file_image_op, void *_udata) +{ + H5LT_file_image_ud_t *udata = (H5LT_file_image_ud_t *)_udata; + + /* callback is only used if the application buffer is not actually copied */ + if (!(udata->flags & H5LT_FILE_IMAGE_DONT_COPY)) + goto out; + + switch(file_image_op) { + case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_CLOSE: + if (udata->fapl_image_ptr != ptr) + goto out; + if (udata->fapl_ref_count == 0) + goto out; + + udata->fapl_ref_count--; + + /* release the shared buffer only if indicated by the respective flag and there are no outstanding references */ + if (udata->fapl_ref_count == 0 && udata->vfd_ref_count == 0 && + !(udata->flags & H5LT_FILE_IMAGE_DONT_RELEASE)) { + HDfree(udata->fapl_image_ptr); + udata->app_image_ptr = NULL; + udata->fapl_image_ptr = NULL; + udata->vfd_image_ptr = NULL; + } /* end if */ + break; + + case H5FD_FILE_IMAGE_OP_FILE_CLOSE: + if (udata->vfd_image_ptr != ptr) + goto out; + if (udata->vfd_ref_count != 1) + goto out; + + udata->vfd_ref_count--; + + /* release the shared buffer only if indicated by the respective flag and there are no outstanding references */ + if (udata->fapl_ref_count == 0 && udata->vfd_ref_count == 0 && + !(udata->flags & H5LT_FILE_IMAGE_DONT_RELEASE)) { + HDfree(udata->vfd_image_ptr); + udata->app_image_ptr = NULL; + udata->fapl_image_ptr = NULL; + udata->vfd_image_ptr = NULL; + } /* end if */ + break; + + /* added unused labels to keep the compiler quite */ + case H5FD_FILE_IMAGE_OP_NO_OP: + case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_SET: + case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_COPY: + case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_GET: + case H5FD_FILE_IMAGE_OP_FILE_OPEN: + case H5FD_FILE_IMAGE_OP_FILE_RESIZE: + default: + goto out; + } /* end switch */ + + return(SUCCEED); + +out: + return(FAIL); +} /* end image_free() */ + + +/*------------------------------------------------------------------------- +* Function: udata_copy +* +* Purpose: Simulates the copying of the user data structure utilized in the +* management of the "copying" of file images. +* +* Return: Address of "newly allocated" structure, if successful. Otherwise, it +* returns NULL. +* +* Programmer: Christian Chilan +* +* Date: October 3, 2011 +* +*------------------------------------------------------------------------- +*/ +static void * +udata_copy(void *_udata) +{ + H5LT_file_image_ud_t *udata = (H5LT_file_image_ud_t *)_udata; + + /* callback is only used if the application buffer is not actually copied */ + if (!(udata->flags & H5LT_FILE_IMAGE_DONT_COPY)) + goto out; + if (udata->ref_count == 0) + goto out; + + udata->ref_count++; + + return(udata); + +out: + return NULL; +} /* end udata_copy */ + + +/*------------------------------------------------------------------------- +* Function: udata_free +* +* Purpose: Simulates deallocation of the user data structure utilized in the +* management of the "copying" of file images. The data structure is +* actually deallocated when there are no outstanding references. +* +* Return: SUCCEED or FAIL +* +* Programmer: Christian Chilan +* +* Date: October 3, 2011 +* +*------------------------------------------------------------------------- +*/ +static herr_t +udata_free(void *_udata) +{ + H5LT_file_image_ud_t *udata = (H5LT_file_image_ud_t *)_udata; + + /* callback is only used if the application buffer is not actually copied */ + if (!(udata->flags & H5LT_FILE_IMAGE_DONT_COPY)) + goto out; + if (udata->ref_count == 0) + goto out; + + udata->ref_count--; + + /* checks that there are no references outstanding before deallocating udata */ + if (udata->ref_count == 0 && udata->fapl_ref_count == 0 && + udata->vfd_ref_count == 0) + HDfree(udata); + + return(SUCCEED); + +out: + return(FAIL); +} /* end udata_free */ + +/* End of callbacks definitions for file image operations */ /*------------------------------------------------------------------------- * @@ -388,6 +843,120 @@ out: return -1; } + +/*------------------------------------------------------------------------- +* Function: H5LTopen_file_image +* +* Purpose: Open a user supplied file image using the core file driver. +* +* Return: File identifier, Failure: -1 +* +* Programmer: Christian Chilan +* +* Date: October 3, 2011 +* +*------------------------------------------------------------------------- +*/ +hid_t H5LTopen_file_image(void *buf_ptr, size_t buf_size, unsigned flags) +{ + hid_t fapl, file_id; /* HDF5 identifiers */ + unsigned file_open_flags;/* Flags for image open */ + char file_name[64]; /* Filename buffer */ + size_t alloc_incr; /* Buffer allocation increment */ + size_t min_incr = 65536; /* Minimum buffer increment */ + double buf_prcnt = 0.1f; /* Percentage of buffer size to set + as increment */ + static long file_name_counter; + H5FD_file_image_callbacks_t callbacks = {&image_malloc, &image_memcpy, + &image_realloc, &image_free, + &udata_copy, &udata_free, + (void *)NULL}; + + /* check arguments */ + if (buf_ptr == NULL) + goto out; + if (buf_size == 0) + goto out; + if (flags & (unsigned)~(H5LT_FILE_IMAGE_ALL)) + goto out; + + /* Create FAPL to transmit file image */ + if ((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0) + goto out; + + /* set allocation increment to a percentage of the supplied buffer size, or + * a pre-defined minimum increment value, whichever is larger + */ + if ((buf_prcnt * buf_size) > min_incr) + alloc_incr = (size_t)(buf_prcnt * buf_size); + else + alloc_incr = min_incr; + + /* Configure FAPL to use the core file driver */ + if (H5Pset_fapl_core(fapl, alloc_incr, FALSE) < 0) + goto out; + + /* Set callbacks for file image ops ONLY if the file image is NOT copied */ + if (flags & H5LT_FILE_IMAGE_DONT_COPY) { + H5LT_file_image_ud_t *udata; /* Pointer to udata structure */ + + /* Allocate buffer to communicate user data to callbacks */ + if (NULL == (udata = (H5LT_file_image_ud_t *)HDmalloc(sizeof(H5LT_file_image_ud_t)))) + goto out; + + /* Initialize udata with info about app buffer containing file image and flags */ + udata->app_image_ptr = buf_ptr; + udata->app_image_size = buf_size; + udata->fapl_image_ptr = NULL; + udata->fapl_image_size = 0; + udata->fapl_ref_count = 0; + udata->vfd_image_ptr = NULL; + udata->vfd_image_size = 0; + udata->vfd_ref_count = 0; + udata->flags = flags; + udata->ref_count = 1; /* corresponding to the first FAPL */ + + /* copy address of udata into callbacks */ + callbacks.udata = (void *)udata; + + /* Set file image callbacks */ + if (H5Pset_file_image_callbacks(fapl, &callbacks) < 0) { + HDfree(udata); + goto out; + } /* end if */ + } /* end if */ + + /* Assign file image in user buffer to FAPL */ + if (H5Pset_file_image(fapl, buf_ptr, buf_size) < 0) + goto out; + + /* set file open flags */ + if (flags & H5LT_FILE_IMAGE_OPEN_RW) + file_open_flags = H5F_ACC_RDWR; + else + file_open_flags = H5F_ACC_RDONLY; + + /* define a unique file name */ + HDsnprintf(file_name, (sizeof(file_name) - 1), "file_image_%ld", file_name_counter++); + + /* Assign file image in FAPL to the core file driver */ + if ((file_id = H5Fopen(file_name, file_open_flags, fapl)) < 0) + goto out; + + /* Close FAPL */ + if (H5Pclose(fapl) < 0) + goto out; + + /* Return file identifier */ + return file_id; + +out: + H5E_BEGIN_TRY { + H5Pclose(fapl); + } H5E_END_TRY; + return -1; +} /* end H5LTopen_file_image() */ + /*------------------------------------------------------------------------- * Function: H5LT_read_dataset @@ -1801,7 +2370,7 @@ print_enum(hid_t type, char* str, size_t *str_len, hbool_t no_ubuf, size_t indt) out: if(0 == nmembs) { - HDsnprintf(tmp_str, TMP_LEN, "\n%*s ", indt + 4, ""); + HDsnprintf(tmp_str, TMP_LEN, "\n%*s ", (int)(indt + 4), ""); str = realloc_and_append(no_ubuf, str_len, str, tmp_str); } /* end if */ diff --git a/hl/src/H5LTpublic.h b/hl/src/H5LTpublic.h index 6efae68..929c6bd 100644 --- a/hl/src/H5LTpublic.h +++ b/hl/src/H5LTpublic.h @@ -16,6 +16,15 @@ #ifndef _H5LTpublic_H #define _H5LTpublic_H +/* Flag definitions for H5LTopen_file_image() */ +#define H5LT_FILE_IMAGE_OPEN_RW 0x0001 /* Open image for read-write */ +#define H5LT_FILE_IMAGE_DONT_COPY 0x0002 /* The HDF5 lib won't copy */ +/* user supplied image buffer. The same image is open with the core driver. */ +#define H5LT_FILE_IMAGE_DONT_RELEASE 0x0004 /* The HDF5 lib won't */ +/* deallocate user supplied image buffer. The user application is reponsible */ +/* for doing so. */ +#define H5LT_FILE_IMAGE_ALL 0x0007 + typedef enum H5LT_lang_t { H5LT_LANG_ERR = -1, /*this is the first*/ H5LT_DDL = 0, /*for DDL*/ @@ -344,6 +353,15 @@ H5_HLDLL herr_t H5LTfind_attribute( hid_t loc_id, const char *name ); H5_HLDLL htri_t H5LTpath_valid(hid_t loc_id, const char *path, hbool_t check_object_valid); +/*------------------------------------------------------------------------- + * + * File image operations functions + * + *------------------------------------------------------------------------- + */ + +H5_HLDLL hid_t H5LTopen_file_image(void *buf_ptr, size_t buf_size, unsigned flags); + #ifdef __cplusplus } #endif diff --git a/hl/src/Makefile.in b/hl/src/Makefile.in index cb89235..4dc491e 100644 --- a/hl/src/Makefile.in +++ b/hl/src/Makefile.in @@ -420,7 +420,7 @@ CHECK_CLEANFILES = *.chkexe *.chklog *.clog # Add libtool shared library version numbers to the HDF5 library # See libtool versioning documentation online. LT_VERS_INTERFACE = 6 -LT_VERS_REVISION = 101 +LT_VERS_REVISION = 103 LT_VERS_AGE = 0 # This library is our main target. diff --git a/hl/test/COPYING b/hl/test/COPYING old mode 100755 new mode 100644 diff --git a/hl/test/Makefile.am b/hl/test/Makefile.am index 9bd5e7a..0e7b018 100644 --- a/hl/test/Makefile.am +++ b/hl/test/Makefile.am @@ -33,7 +33,8 @@ 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_table test_ds test_packet test_ld +TEST_PROG=test_lite test_image test_file_image test_table test_ds test_packet \ + test_ld check_PROGRAMS=$(TEST_PROG) ld_monitor ld_extend # These programs generate test files for the tests. They don't need to be @@ -49,7 +50,7 @@ endif # Temporary files. These files are the ones created by running `make test'. CHECK_CLEANFILES+=combine_tables[1-2].h5 test_ds[1-9].h5 test_image[1-3].h5 \ - test_lite[1-2].h5 test_table.h5 test_packet_table.h5 \ + file_img[1-2].h5 test_lite[1-2].h5 test_table.h5 test_packet_table.h5 \ test_packet_compress.h5 test_detach.h5 DISTCLEANFILES=test_ld.sh diff --git a/hl/test/Makefile.in b/hl/test/Makefile.in index 9a95e16..c7c9a55 100644 --- a/hl/test/Makefile.in +++ b/hl/test/Makefile.in @@ -70,8 +70,8 @@ CONFIG_HEADER = $(top_builddir)/src/H5config.h CONFIG_CLEAN_FILES = H5srcdir_str.h test_ld.sh CONFIG_CLEAN_VPATH_FILES = am__EXEEXT_1 = test_lite$(EXEEXT) test_image$(EXEEXT) \ - test_table$(EXEEXT) test_ds$(EXEEXT) test_packet$(EXEEXT) \ - test_ld$(EXEEXT) + test_file_image$(EXEEXT) test_table$(EXEEXT) test_ds$(EXEEXT) \ + test_packet$(EXEEXT) test_ld$(EXEEXT) am__EXEEXT_2 = gen_test_ds$(EXEEXT) gen_test_ld$(EXEEXT) PROGRAMS = $(noinst_PROGRAMS) gen_test_ds_SOURCES = gen_test_ds.c @@ -97,6 +97,10 @@ test_ds_SOURCES = test_ds.c test_ds_OBJECTS = test_ds.$(OBJEXT) test_ds_LDADD = $(LDADD) test_ds_DEPENDENCIES = $(LIBH5_HL) $(LIBH5TEST) $(LIBHDF5) +test_file_image_SOURCES = test_file_image.c +test_file_image_OBJECTS = test_file_image.$(OBJEXT) +test_file_image_LDADD = $(LDADD) +test_file_image_DEPENDENCIES = $(LIBH5_HL) $(LIBH5TEST) $(LIBHDF5) test_image_SOURCES = test_image.c test_image_OBJECTS = test_image.$(OBJEXT) test_image_LDADD = $(LDADD) @@ -144,11 +148,11 @@ AM_V_GEN = $(am__v_GEN_$(V)) am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) am__v_GEN_0 = @echo " GEN " $@; SOURCES = gen_test_ds.c gen_test_ld.c ld_extend.c ld_monitor.c \ - test_ds.c test_image.c test_ld.c test_lite.c test_packet.c \ - test_table.c + test_ds.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_extend.c ld_monitor.c \ - test_ds.c test_image.c test_ld.c test_lite.c test_packet.c \ - test_table.c + test_ds.c test_file_image.c test_image.c test_ld.c test_lite.c \ + test_packet.c test_table.c ETAGS = etags CTAGS = ctags am__tty_colors = \ @@ -442,9 +446,9 @@ TRACE = perl $(top_srcdir)/bin/trace # Temporary files. These files are the ones created by running `make test'. CHECK_CLEANFILES = *.chkexe *.chklog *.clog combine_tables[1-2].h5 \ - test_ds[1-9].h5 test_image[1-3].h5 test_lite[1-2].h5 \ - test_table.h5 test_packet_table.h5 test_packet_compress.h5 \ - test_detach.h5 + test_ds[1-9].h5 test_image[1-3].h5 file_img[1-2].h5 \ + test_lite[1-2].h5 test_table.h5 test_packet_table.h5 \ + test_packet_compress.h5 test_detach.h5 # Test script TEST_SCRIPT = test_ld.sh @@ -456,7 +460,9 @@ 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_table test_ds test_packet test_ld +TEST_PROG = test_lite test_image test_file_image test_table test_ds test_packet \ + test_ld + # 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 @@ -552,6 +558,9 @@ ld_monitor$(EXEEXT): $(ld_monitor_OBJECTS) $(ld_monitor_DEPENDENCIES) test_ds$(EXEEXT): $(test_ds_OBJECTS) $(test_ds_DEPENDENCIES) @rm -f test_ds$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ds_OBJECTS) $(test_ds_LDADD) $(LIBS) +test_file_image$(EXEEXT): $(test_file_image_OBJECTS) $(test_file_image_DEPENDENCIES) + @rm -f test_file_image$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_file_image_OBJECTS) $(test_file_image_LDADD) $(LIBS) test_image$(EXEEXT): $(test_image_OBJECTS) $(test_image_DEPENDENCIES) @rm -f test_image$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_image_OBJECTS) $(test_image_LDADD) $(LIBS) @@ -579,6 +588,7 @@ distclean-compile: @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)/test_ds.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@ diff --git a/hl/test/h5hltest.h b/hl/test/h5hltest.h index 466a0e1..809c4ec 100644 --- a/hl/test/h5hltest.h +++ b/hl/test/h5hltest.h @@ -23,9 +23,6 @@ #ifndef _H5HLTEST_H #define _H5HLTEST_H -/* Get the HDF5 public header */ -#include "hdf5.h" - /* Get the HDF5 test header */ #include "h5test.h" @@ -36,5 +33,8 @@ #define TESTING2(WHAT) {printf("%-70s", "Testing " WHAT); fflush(stdout);} #define TESTING3(WHAT) {printf("%-70s", "" WHAT); fflush(stdout);} +/* Implrements verbose 'assert' with 'goto error' exit */ +#define VERIFY(condition, string) do { if (!(condition)) FAIL_PUTS_ERROR(string) } while(0) + #endif /* _H5HLTEST_H */ diff --git a/hl/test/test_file_image.c b/hl/test/test_file_image.c new file mode 100644 index 0000000..9729421 --- /dev/null +++ b/hl/test/test_file_image.c @@ -0,0 +1,518 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* 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 "h5hltest.h" +#include "H5LTpublic.h" + +#define DSET_NAME "dset" + +#define RANK 2 + +/* Test of file image operations. + + The following code provides a means to thoroughly test the file image + operations. Main objectives are testing operations with multiple open + images and using all possible flag combinations, which are set in the + main calling routine. Since the number of open images and flag combinations + may differ, the flag combinations are assigned to the images in round-robin + fashion. In order to simulate a realistic operation environment, the code + operates on as many open objects as possible by using several for-loops + instead of using a single loop that opens image i, accesses it, and closes + it. The first loop creates the files and obtains images using the function + H5Fget_file_image(); two images are set incorrectly (one image is filled + with "wrong" data while the other image is not valid). The second loop opens + the images using the function H5LTopen_file_image(), and test whether the + images have been copied in accordance to the H5LT_FILE_IMAGE_DONT_COPY flag. + The third loop reads the open images and verifies that the contents are + correct. The fourth loop first perform writes in the images that do not + extend the image, and then performs writes that extend the images. The fifth + loop reads the extended images and verify that the content are correct. The + sixth and final loop closes the file images and deallocates the image + buffers if appropriate. */ + +/*------------------------------------------------------------------------- +* test file image operations +*------------------------------------------------------------------------- +*/ +static int +test_file_image(size_t open_images, size_t nflags, unsigned *flags) +{ + hid_t *file_id, *dset_id, file_space, plist; /* HDF5 ids */ + hsize_t dims1[RANK] = {2,3}; /* original dimension of datasets */ + hsize_t max_dims[RANK] = {H5S_UNLIMITED, H5S_UNLIMITED}; + int data1[6] = {1,2,3,4,5,6}; /* original contents of dataset */ + int data2[6] = {7,8,9,10,11,12}; /* "wrong" contents of dataset */ + hsize_t dims3[RANK]; /* array to read dataset dimensions */ + int data3[15]; /* array to read dataset contents */ + hsize_t dims4[RANK] = {3,5}; /* extended dimensions of datasets */ + int data4[15] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; + /* extended contents of dataset */ + ssize_t *buf_size; /* pointer to array of buffer sizes */ + void **buf_ptr; /* pointer to array of pointers to image buffers */ + char **filename; /* pointer to array of pointers to filenames */ + unsigned *input_flags; /* pointer to array of flag combinations */ + size_t i, j, k, nrow, n_values; + herr_t status1; + void *handle_ptr = NULL; /* pointers to driver buffer */ + unsigned char **core_buf_ptr_ptr = NULL; + + VERIFY(open_images > 1 , "The number of open images must be greater than 1"); + + VERIFY(nflags > 0, "The number of flag combinations must be greater than 0"); + + /* allocate array of flags for open images */ + if (NULL == (input_flags = (unsigned *)HDmalloc(sizeof(unsigned) * open_images))) + FAIL_PUTS_ERROR("malloc() failed"); + + /* allocate array of pointers for each of the open images */ + if (NULL == (buf_ptr = (void **)malloc(sizeof(void *) * open_images))) + FAIL_PUTS_ERROR("malloc() failed"); + + /* allocate array to store the name of each of the open images */ + if (NULL == (filename = (char **)malloc(sizeof(char *) * open_images))) + FAIL_PUTS_ERROR("malloc() failed"); + + /* allocate array to store the size of each of the open images */ + if (NULL == (buf_size = (ssize_t *)malloc(sizeof(ssize_t) * open_images))) + FAIL_PUTS_ERROR("malloc() failed"); + + /* allocate array for each of the file identifiers */ + if (NULL == (file_id = (hid_t *)malloc(sizeof(hid_t) * open_images))) + FAIL_PUTS_ERROR("malloc() failed"); + + /* allocate array for each of the dataset identifiers */ + if (NULL == (dset_id = (hid_t *)malloc(sizeof(hid_t) * open_images))) + FAIL_PUTS_ERROR("malloc() failed"); + + TESTING("get file images"); + + /* create several file images */ + for (i = 0; i < open_images; i++) { + + /* populate array for flags combinations */ + input_flags[i] = flags[(nflags + i) % nflags]; + + /* allocate name buffer for image i */ + filename[i] = (char *)HDmalloc(sizeof(char) * 32); + + /* create file name */ + sprintf(filename[i], "image_file%d.h5", (int)i); + + /* create file */ + if ((file_id[i] = H5Fcreate(filename[i], H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) + FAIL_PUTS_ERROR("H5Fcreate() failed"); + + /* define dataspace for the dataset */ + if ((file_space = H5Screate_simple(RANK, dims1, max_dims)) < 0) + FAIL_PUTS_ERROR("H5Screate_simple() failed"); + + /* create dataset property list */ + if ((plist = H5Pcreate(H5P_DATASET_CREATE)) < 0) + FAIL_PUTS_ERROR("H5Pcreate() failed"); + + /* set property list to create chunked dataset */ + if (H5Pset_chunk(plist, RANK, dims1) < 0) + FAIL_PUTS_ERROR("H5Pset_chunk() failed"); + + /* create and write an integer type dataset named "dset" */ + if ((dset_id[i] = H5Dcreate2(file_id[i], DSET_NAME, H5T_NATIVE_INT, file_space, H5P_DEFAULT, plist, H5P_DEFAULT)) < 0) + FAIL_PUTS_ERROR("H5Dcreate() failed"); + + /* dataset in open image 1 is written with "wrong" data */ + if (i == 1) { + if (H5Dwrite(dset_id[i], H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data2) < 0) + FAIL_PUTS_ERROR("H5Dwrite() failed"); + } /* end if*/ + /* dataset in the rest of the open images is written with correct data */ + else { + if (H5Dwrite(dset_id[i], H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data1) < 0) + FAIL_PUTS_ERROR("H5Dwrite() failed"); + } /* end else */ + + /* flush into the file */ + if (H5Fflush(file_id[i], H5F_SCOPE_LOCAL) < 0) + FAIL_PUTS_ERROR("H5Fflush() failed"); + + /* close dataset property list */ + if (H5Pclose(plist) < 0) + FAIL_PUTS_ERROR("H5Pclose() failed"); + + /* close dataspace */ + if (H5Sclose(file_space) < 0) + FAIL_PUTS_ERROR("H5Sclose() failed"); + + /* close dataset */ + if (H5Dclose(dset_id[i]) < 0) + 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) + FAIL_PUTS_ERROR("H5Fget_file_image() failed"); + + /* allocate buffer for the file image i */ + if (NULL == (buf_ptr[i] = (void *)HDmalloc((size_t)buf_size[i]))) + FAIL_PUTS_ERROR("malloc() failed"); + + /* buffer for file image 2 is filled with counter data (non-valid image) */ + if (i == 2) { + for (j = 0; j < (size_t)buf_size[i]; j++) + ((char*)(buf_ptr[i]))[j] = (char)j; + } /* end if */ + /* buffers for the rest of the file images are filled with data from the respective files */ + else { + if ((buf_size[i] = H5Fget_file_image(file_id[i], buf_ptr[i], (size_t)buf_size[i])) < 0) + FAIL_PUTS_ERROR("H5Fget_file_image() failed"); + } /* end else */ + + /* file close */ + if (H5Fclose (file_id[i]) < 0) + FAIL_PUTS_ERROR("H5Fclose() failed"); + } /* end for */ + + PASSED(); + + TESTING("open file images and check image copies"); + + /* open the file images with the core driver for data access */ + for (i = 0; i < open_images; i++) { + /* open file image 2 filled with counter data (non-valid image) */ + if (i == 2) { + H5E_BEGIN_TRY { + /* attempt to set file image in the core driver */ + file_id[i] = H5LTopen_file_image(buf_ptr[i], (size_t)buf_size[i], input_flags[i]); + } H5E_END_TRY + + VERIFY(file_id[i] < 0, "H5LTopen_file_image() should have failed"); + } /* end if */ + /* open rest of valid file images */ + else { + /* set file image in the core driver */ + if ((file_id[i] = H5LTopen_file_image(buf_ptr[i], (size_t)buf_size[i], input_flags[i])) < 0) + FAIL_PUTS_ERROR("H5LTopen_file_image() failed"); + + /* get pointer to the image buffer of the core driver */ + if (H5Fget_vfd_handle(file_id[i], H5P_DEFAULT, &handle_ptr) < 0) + FAIL_PUTS_ERROR("H5Fget_vfd_handle() failed"); + + core_buf_ptr_ptr = (unsigned char **)handle_ptr; + + /* test whether the user buffer has been copied or not */ + if (input_flags[i] & H5LT_FILE_IMAGE_DONT_COPY) + VERIFY(*core_buf_ptr_ptr == buf_ptr[i], "vfd buffer and user buffer should have been the same"); + 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"); + } /* end else */ + } /* end for */ + + PASSED(); + + TESTING("read file images"); + + /* read open file images and verify data */ + for (i = 0; i < open_images; i++) { + /* if opening the file image failed, continue next iteration */ + if (file_id[i] < 0) { + HDassert(i == 2); + continue; + } /* end if */ + + /* open dataset in file image */ + if ((dset_id[i] = H5Dopen2(file_id[i], DSET_NAME, H5P_DEFAULT)) < 0) + FAIL_PUTS_ERROR("H5Dopen() failed"); + + /* get dataspace for the dataset */ + if ((file_space = H5Dget_space(dset_id[i])) < 0) + FAIL_PUTS_ERROR("H5Dget_space() failed"); + + /* get dimensions for the dataset */ + if (H5Sget_simple_extent_dims(file_space, dims3, NULL) < 0) + FAIL_PUTS_ERROR("H5Sget_simple_extent_dims() failed"); + + /* read dataset */ + if (H5Dread(dset_id[i], H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data3) < 0) + FAIL_PUTS_ERROR("H5Dread() failed"); + + /* compute number of elements in dataset */ + n_values = (size_t)(dims3[0] * dims3[1]); + + /* determine the number of rows in dataset */ + nrow = (size_t)dims3[1]; + + /* verify contents for file image 1 with "wrong" data */ + if (i == 1) { + /* compare file image values with original data */ + for (j = 0; j < n_values / nrow; j++) + for (k = 0; k < nrow; k++) + if (data3[j * nrow + k ] == data1[j * nrow + k ]) + FAIL_PUTS_ERROR("comparison of image values with original data should have failed"); + } /* end if */ + /* verify contents for the rest of the file images */ + else { + /* compare file image values with original data */ + for (j = 0; j < n_values / nrow; j++) + for (k = 0; k < nrow; k++) + if (data3[j * nrow + k ] != data1[j * nrow + k ]) + FAIL_PUTS_ERROR("comparison of image values with original data failed"); + } /* end else */ + + /* close dataspace */ + if (H5Sclose (file_space) < 0) + FAIL_PUTS_ERROR("H5Sclose() failed"); + } /* end for */ + + PASSED(); + + TESTING("write and extend file images"); + + /* write open file images and verify data */ + for (i = 0; i < open_images; i++) { + /* if opening the file image failed, continue next iteration */ + if (file_id[i] < 0) { + HDassert(i == 2); + continue; + } /* end if */ + + /* test data write when file image access is read-only */ + if (!(input_flags[i] & H5LT_FILE_IMAGE_OPEN_RW)) { + /* write dataset without extending it */ + H5E_BEGIN_TRY { + status1 = H5Dwrite(dset_id[i], H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data1); + } H5E_END_TRY; + + VERIFY(status1 < 0, "H5Dwrite() should have failed"); + + /* extend dimensions of dataset */ + H5E_BEGIN_TRY { + status1 = H5Dset_extent(dset_id[i], dims4); + } H5E_END_TRY; + + VERIFY(status1 < 0, "H5Dset_extent() should have failed"); + + /* write extended dataset */ + H5E_BEGIN_TRY { + status1 = H5Dwrite(dset_id[i], H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data4); + } H5E_END_TRY; + + VERIFY(status1 < 0, "H5Dwrite() should have failed"); + + /* close dataset */ + if (H5Dclose(dset_id[i]) < 0) + FAIL_PUTS_ERROR("H5Dclose() failed"); + } /* end if */ + /* test data write where file image access is read-write */ + else { + if ((input_flags[i] & H5LT_FILE_IMAGE_DONT_COPY) && (input_flags[i] & H5LT_FILE_IMAGE_DONT_RELEASE)) { +/* This test is disabled currently, since the new attribute causes the file + * to increase in size, but the realloc call in H5FD_core_write() fails, causing + * the flush operation to fail and the file to fail to close, eventually + * triggering the "infinite loop shutting down the library" problem. + * + * In theory, we could address this through a variety of methods, ranging from + * ignoring failures in H5F_dest() (when called from H5F_try_close()), to + * allocating space more aggressively when creating the attribute, etc. + * + * For now, we will just leave the test commented out and assume that + * application developers who mark their file image as "don't copy" won't + * be likely candidates for modifying their data. - QAK - March 29, 2012 + */ +#if 0 + int attr_rank = 1; + hsize_t attr_dims[] = {4096}; + int attr_data[4096]; + hid_t attr_space_id = -1; + hid_t attr_id = -1; + herr_t status2; + size_t l; + + if ((attr_space_id = H5Screate_simple(attr_rank, attr_dims, attr_dims)) < 0) + FAIL_PUTS_ERROR("attr_space H5Screate_simple() failed"); + + if((attr_id = H5Acreate_by_name(dset_id[i], ".", "int array_addr", H5T_NATIVE_INT, attr_space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) + FAIL_PUTS_ERROR("H5Acreate_by_name() failed"); + + for(l = 0; l < 4096; l++) + attr_data[l] = (int)l; + + /* write data to the attribute and then flush the file. One or the other should + * should trigger an extension to the EOA, which in turn should cause the realloc + * callback to fail. + */ + H5E_BEGIN_TRY { + status1 = status2 = -1; + + status1 = H5Awrite(attr_id, H5T_NATIVE_INT, (const void *)attr_data); + if(status1 >= 0) + status2 = H5Fflush(file_id[i], H5F_SCOPE_GLOBAL); + + VERIFY(status1 < 0 || status2 < 0, "writing and flushing attr should have failed"); + } H5E_END_TRY; + + /* close attr and attr_space -- expect errors on close */ + H5E_BEGIN_TRY { + H5Sclose(attr_space_id); + H5Aclose(attr_id); + } H5E_END_TRY; +#endif + file_id[i] = -1; + } /* end if */ + else { + /* write dataset without extending it */ + if (H5Dwrite(dset_id[i], H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data1) < 0) + FAIL_PUTS_ERROR("H5Dwrite() failed"); + + /* extend dimensions of dataset */ + if (H5Dset_extent(dset_id[i], dims4) < 0) + FAIL_PUTS_ERROR("H5Dset_extent() failed"); + + /* write extended dataset */ + if (H5Dwrite(dset_id[i], H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data4) < 0) + FAIL_PUTS_ERROR("H5Dwrite() failed"); + + /* close dataset */ + if (H5Dclose(dset_id[i]) < 0) + FAIL_PUTS_ERROR("H5Dclose() failed"); + } /* end else */ + } /* end else */ + } /* end for */ + + PASSED(); + + TESTING("read extended file images"); + + /* read open file images and verify data */ + for (i = 0; i < open_images; i++) { + /* if opening the file image failed, continue next iteration */ + if ((file_id[i] < 0) || (!(input_flags[i] & H5LT_FILE_IMAGE_OPEN_RW ))) + continue; + + /* open dataset in file image */ + if ((dset_id[i] = H5Dopen2(file_id[i], DSET_NAME, H5P_DEFAULT)) < 0) + FAIL_PUTS_ERROR("H5Dopen() failed"); + + /* get dataspace for the dataset */ + if ((file_space = H5Dget_space(dset_id[i])) < 0) + FAIL_PUTS_ERROR("H5Dget_space() failed"); + + /* get dimensions for the dataset */ + if (H5Sget_simple_extent_dims(file_space, dims3, NULL) < 0) + FAIL_PUTS_ERROR("H5Sget_simple_extent_dims() failed"); + + /* read dataset */ + if (H5Dread(dset_id[i], H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data3) < 0) + FAIL_PUTS_ERROR("H5Dread() failed"); + + /* compute number of elements in dataset */ + n_values = (size_t)(dims3[0] * dims3[1]); + + /* determine the number of rows in dataset */ + nrow = (size_t)dims3[1]; + + /* verify contents for the file images */ + for (j = 0; j < n_values / nrow; j++) + for (k = 0; k < nrow; k++) + if (data3[j * nrow + k ] != data4[j * nrow + k ]) + FAIL_PUTS_ERROR("comparison of image values with original data failed"); + + /* close dataspace */ + if (H5Sclose (file_space) < 0) + FAIL_PUTS_ERROR("H5Sclose() failed"); + + /* close dataset */ + if (H5Dclose(dset_id[i]) < 0) + FAIL_PUTS_ERROR("H5Dclose() failed"); + } /* end for */ + + PASSED() + + TESTING("close file images"); + + /* close file images and release buffer if appropriate */ + for (i = 0; i < open_images; i++) { + /* close file is appropriate */ + if (file_id[i] >= 0) { + /* close file image */ + if (H5Fclose(file_id[i]) < 0) + FAIL_PUTS_ERROR("H5Fclose() failed"); + } /* end if */ + + /* delete test data files */ + if (HDremove(filename[i]) < 0) + FAIL_PUTS_ERROR("HDremove() failed"); + + /* free shared buffer if appropriate */ + if (!(input_flags[i] & H5LT_FILE_IMAGE_DONT_COPY) || (input_flags[i] & H5LT_FILE_IMAGE_DONT_RELEASE)) { + VERIFY(buf_ptr[i] != NULL, "buffer pointer must be non NULL"); + HDfree(buf_ptr[i]); + } /* end if */ + + } /* end for */ + + /* release temporary working buffers */ + HDfree(filename); + HDfree(file_id); + HDfree(dset_id); + HDfree(buf_ptr); + HDfree(buf_size); + HDfree(input_flags); + + PASSED(); + + H5close(); + + return 0; + +error: + H5_FAILED(); + return -1; +} + +/*------------------------------------------------------------------------- +* the main program +*------------------------------------------------------------------------- +*/ +int main( void ) +{ + int nerrors = 0; + size_t open_images = 10; /* number of open file images */ + size_t nflags = 8; /* number of flag combinations */ + unsigned flags[8]; /* array with flag combinations */ + + /* set flag combinations for testing */ + flags[0] = 0; + flags[1] = H5LT_FILE_IMAGE_DONT_RELEASE; + flags[2] = H5LT_FILE_IMAGE_DONT_COPY; + flags[3] = H5LT_FILE_IMAGE_DONT_COPY | H5LT_FILE_IMAGE_DONT_RELEASE; + flags[4] = H5LT_FILE_IMAGE_OPEN_RW; + flags[5] = H5LT_FILE_IMAGE_OPEN_RW | H5LT_FILE_IMAGE_DONT_RELEASE; + flags[6] = H5LT_FILE_IMAGE_OPEN_RW | H5LT_FILE_IMAGE_DONT_COPY; + flags[7] = H5LT_FILE_IMAGE_OPEN_RW | H5LT_FILE_IMAGE_DONT_COPY | H5LT_FILE_IMAGE_DONT_RELEASE; + + /* Test file image operations. The flag combinations are assigned to file images in round-robin fashion */ + nerrors += test_file_image(open_images, nflags, flags) < 0? 1 : 0; + + if (nerrors) goto error; + printf("File image tests passed.\n"); + return 0; + +error: + printf("***** %d IMAGE TEST%s FAILED! *****\n",nerrors, 1 == nerrors ? "" : "S"); + return 1; +} + diff --git a/hl/test/test_lite.c b/hl/test/test_lite.c index 59da1f1..eb00cd7 100644 --- a/hl/test/test_lite.c +++ b/hl/test/test_lite.c @@ -1841,8 +1841,11 @@ static int test_valid_path(void) * / / \ * G2 DS4 G7 * | (hard link (dangled soft link - * | to /G1/DS3) to /G1/G20 ) - * / \ + * | to /G1/DS3) to /G1/G20 ) + * | + * | + * | --- Gcyc (soft link to /G1) + * / \ * / \ * G5 \ * (soft link G6 (external link /G1 in FILENAME4) @@ -1901,7 +1904,7 @@ static int test_valid_path(void) goto out; /* - * Create a group named "/G3/G5" in the file. + * Create a hard link */ if(H5Lcreate_hard(file_id, "/G2/DS4", file_id, "/G1/DS3",H5P_DEFAULT, H5P_DEFAULT)<0) goto out; @@ -1917,6 +1920,12 @@ static int test_valid_path(void) if(H5Lcreate_soft("/G2", file_id, "/G1/G2/G5", H5P_DEFAULT, H5P_DEFAULT)<0) goto out; + /* + * Create a cyclic soft link + */ + if(H5Lcreate_soft("/G1", file_id, "/G1/G2/Gcyc", H5P_DEFAULT, H5P_DEFAULT)<0) + goto out; + if(H5Gclose(group)<0) goto out; @@ -2007,6 +2016,12 @@ static int test_valid_path(void) if( (path_valid = H5LTpath_valid(file_id, "/G1/G2/G5", TRUE)) != TRUE) goto out; + if( (path_valid = H5LTpath_valid(file_id, "/G1/G2/Gcyc/DS1", FALSE)) != TRUE) + goto out; + + if( (path_valid = H5LTpath_valid(file_id, "/G1/G2/Gcyc/DS1", TRUE)) != TRUE) + goto out; + if( (path_valid = H5LTpath_valid(file_id, "/G2", TRUE)) != TRUE) goto out; @@ -2092,6 +2107,12 @@ static int test_valid_path(void) if( (path_valid = H5LTpath_valid(file_id, "/G1/G2/G6/ExternalLink", TRUE)) != TRUE) goto out; + if( (path_valid = H5LTpath_valid(file_id, "/G1/G2/Gcyc/G2/G6/ExternalLink/DS1", TRUE)) != TRUE) + goto out; + + if( (path_valid = H5LTpath_valid(file_id, "/G1/G2/Gcyc/G2/G6/ExternalLink/G20", FALSE)) != TRUE) + goto out; + if( (path_valid = H5LTpath_valid(file_id, "/G1/G2/G6/ExternalLink/DS1", TRUE)) != TRUE) goto out; @@ -2102,6 +2123,10 @@ static int test_valid_path(void) if( (path_valid = H5LTpath_valid(file_id, "/G1/G2/G6/ExternalLink/G20", TRUE)) == TRUE) goto out; + if( (path_valid = H5LTpath_valid(file_id, "/G1/G2/Gcyc/G2/G6/ExternalLink/G20", TRUE)) == TRUE) + goto out; + + if(H5Fclose(file_id)<0) goto out; diff --git a/hl/tools/COPYING b/hl/tools/COPYING old mode 100755 new mode 100644 diff --git a/perform/COPYING b/perform/COPYING old mode 100755 new mode 100644 diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index 00df5c6..91b4694 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -1,4 +1,4 @@ -HDF5 version 1.9.111-FA_a5 currently under development +HDF5 version 1.9.113-FA_a5 currently under development ================================================================================ @@ -93,6 +93,11 @@ New Features Library: -------- + - The data sieve buffer size was for all the datasets in the file. It + could waste memory if any dataset size is smaller than the sieve buffer + size. Now the library picks the smaller one between the dataset size + and the sieve buffer size from the file access property. See Issue 7934. + (SLU - 2012/4/2) - I added a new parameter of object access property list to the function H5Rdereference (Issue 2763). It's called H5Rdereference2 now. The former H5Rdereference function has been deprecated to H5Rdereference1. (SLU - @@ -172,6 +177,11 @@ New Features Fortran Library: ---------------- + + - Added for the C API the Fortran wrapper: + h5ocopy_f (MSB - 2012/03/22) + + HDF5 Fortran library was enhanced to support Fortran 2003 standard. The following features are available when the HDF5 library is configured using --enable-fortran --enable-fortran2003 configure flags AND @@ -352,7 +362,7 @@ New Features - New API: h5ltpath_valid (Fortran: h5ltpath_valid_f) which checks if a path is correct and determines if a link resolves to a valid - object and does not dangle. (MSB- 2012/3/15) + object and checks that the link does not dangle. (MSB- 2012/3/15) Documentation ------------- @@ -368,6 +378,16 @@ Bug Fixes since HDF5-1.8.0 release Library ------- + - Fixed an error that would occur when copying an object with attribute + creation order tracked and indexed. (NAF - 2012/3/28 - HDFFV-7762) + - Fixed a bug in H5Ocopy(): When copying an opened object, call the + object's flush class action to ensure that cached data is flushed + so that H5Ocopy will get the correct data. + (VC - 2012/3/27 - HDFFV-7853) + - When an application tries to write or read many small data chunks and + runs out of memory, the library had a seg fault. The fix is to + return the error stack with proper information. (SLU - 2012/3/23. + Issue 7785) - H5Pset_data_transform had seg fault in some cases like x*-100. It works correctly now and handles other cases like 100-x or 2/x. (SLU - 2012/3/15. Issue 7922) @@ -379,6 +399,10 @@ Bug Fixes since HDF5-1.8.0 release 2012/1/25. Issue 7756) - Fixed a seg fault that could occur when shrinking a dataset with chunks larger than 1 MB. (NAF - 2011/11/30 - HDFFV-7833) + - Fixed a bug that could cause file corruption when copying named + datatypes to a file using shared messages. (NAF - 2011/11/14) + - Fixed a bug that could cause H5Oget_info to return the wrong address + after copying a named datatype. (NAF - 2011/11/14) - The library allowed the conversion of strings between ASCII and UTF8 (Issue 7582). We have corrected it to report an error under this situation. (SLU - 2011/11/8) @@ -593,6 +617,12 @@ Bug Fixes since HDF5-1.8.0 release Configuration ------------- + - Fixed Makefile issue in which "-Wl," was not properly specified + prior to -rpath when building parallel fortran libraries with + an Intel compiler. (MAM - 2012/03/26) + - Makefiles generated by other packages using h5cc as the compiler + no longer error when 'make' is invoked more than once in order + to 'rebuild' after changes to source. (MAM - 2012/03/26) - Added --enable-fortran2003 flag to enable Fortran2003 support in the HDF5 Fortran library. The flag should be used along with the --enable-fortran flag and takes affect only when Fortran compiler @@ -666,6 +696,15 @@ Bug Fixes since HDF5-1.8.0 release Tools ----- + - h5diff: Fixed failure for comparing same named object with different + object types in comparing groups. Prior to the fix, h5diff resulted + in error. After the fix, h5diff detects such case as non-comparable + and display messages accordingly. HDFFV-7664 (JKM 2012/03/28) + - h5diff: If unique objects exists only in one file and try to exclude + the unique objects with --exclude-path option, h5diff missed + excluding some objects. + Fixed to exclude objects correctly in such case. + HDFFV-7837 (JKM 2012/03/20) - h5dump: Added tools library error stack to properly catch error information generated within the library. HDFFV-7958 (ADB 2012/03/12) @@ -873,6 +912,10 @@ Bug Fixes since HDF5-1.8.0 release Fortran High-Level APIs: ------ + + - Lite: The h5ltget_attribute_string_f used to return the C NULL character in the + returned character buffer. The returned Fortran charactor buffer now does + not return the C NULL character. (MSB - 2012/3/23) - Lite: The h5ltget_dataset_info_f function (gets information about a dataset) was not correctly returning the dimension array. (PVN - 2009/3/23) - Lite: the h5ltread_dataset_string_f and h5ltget_attribute_string_f functions diff --git a/src/H5A.c b/src/H5A.c index cc6a7a5..63a908d 100644 --- a/src/H5A.c +++ b/src/H5A.c @@ -2523,6 +2523,36 @@ done: /*------------------------------------------------------------------------- + * Function: H5A_type + * + * Purpose: Return the datatype for an attribute. + * + * Return: Success: Ptr to entry + * Failure: NULL + * + * Programmer: Neil Fortner + * Friday, November 11, 2011 + * + *------------------------------------------------------------------------- + */ +H5T_t * +H5A_type(const H5A_t *attr) +{ + H5T_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(NULL) + + HDassert(attr); + + /* Set return value */ + ret_value = attr->shared->dt; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5A_type() */ + + +/*------------------------------------------------------------------------- * Function: H5Aexists * * Purpose: Checks if an attribute with a given name exists on an opened diff --git a/src/H5Aint.c b/src/H5Aint.c index 8475330..74c5590 100644 --- a/src/H5Aint.c +++ b/src/H5Aint.c @@ -795,6 +795,12 @@ H5A_set_version(const H5F_t *f, H5A_t *attr) * * Purpose: Copies a message from _MESG to _DEST in file * + * Note that this function assumes that it is copying *all* + * the attributes in the object, specifically when it copies + * the creation order from source to destination. If this is + * to be used to copy only a single attribute, then the + * creation order must be handled differently. -NAF + * * Return: Success: Ptr to _DEST * * Failure: NULL @@ -849,6 +855,7 @@ H5A_attr_copy_file(const H5A_t *attr_src, H5F_t *file_dst, hbool_t *recompute_si /* Copy attribute's name */ attr_dst->shared->name = H5MM_strdup(attr_src->shared->name); HDassert(attr_dst->shared->name); + attr_dst->shared->encoding = attr_src->shared->encoding; /* Copy attribute's datatype */ /* If source is named, we will keep dst as named, but we will not actually @@ -1003,6 +1010,9 @@ H5A_attr_copy_file(const H5A_t *attr_src, H5F_t *file_dst, hbool_t *recompute_si } /* end else */ } /* end if(attr_src->shared->data) */ + /* Copy the creation order */ + attr_dst->shared->crt_idx = attr_src->shared->crt_idx; + /* Recompute the version to encode the destination attribute */ if(H5A_set_version(file_dst, attr_dst) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "unable to update attribute version") diff --git a/src/H5Apkg.h b/src/H5Apkg.h index 20aa5b9..26c8dff 100644 --- a/src/H5Apkg.h +++ b/src/H5Apkg.h @@ -158,29 +158,6 @@ typedef struct { H5A_t **attrs; /* Pointer to array of attribute pointers */ } H5A_attr_table_t; -/* Attribute iteration operator for internal library callbacks */ -typedef herr_t (*H5A_lib_iterate_t)(const H5A_t *attr, void *op_data); - -/* Describe kind of callback to make for each attribute */ -typedef enum H5A_attr_iter_op_type_t { -#ifndef H5_NO_DEPRECATED_SYMBOLS - H5A_ATTR_OP_APP, /* Application callback */ -#endif /* H5_NO_DEPRECATED_SYMBOLS */ - H5A_ATTR_OP_APP2, /* Revised application callback */ - H5A_ATTR_OP_LIB /* Library internal callback */ -} H5A_attr_iter_op_type_t; - -typedef struct H5A_attr_iter_op_t { - H5A_attr_iter_op_type_t op_type; - union { -#ifndef H5_NO_DEPRECATED_SYMBOLS - H5A_operator1_t app_op; /* Application callback for each attribute */ -#endif /* H5_NO_DEPRECATED_SYMBOLS */ - H5A_operator2_t app_op2; /* Revised application callback for each attribute */ - H5A_lib_iterate_t lib_op; /* Library internal callback for each attribute */ - } u; -} H5A_attr_iter_op_t; - /*****************************/ /* Package Private Variables */ @@ -268,9 +245,6 @@ H5_DLL herr_t H5O_attr_write(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr); H5_DLL herr_t H5O_attr_rename(const H5O_loc_t *loc, hid_t dxpl_id, const char *old_name, const char *new_name); -H5_DLL herr_t H5O_attr_iterate(hid_t loc_id, hid_t dxpl_id, H5_index_t idx_type, - H5_iter_order_t order, hsize_t skip, hsize_t *last_attr, - const H5A_attr_iter_op_t *op, void *op_data); H5_DLL herr_t H5O_attr_remove(const H5O_loc_t *loc, const char *name, hid_t dxpl_id); H5_DLL herr_t H5O_attr_remove_by_idx(const H5O_loc_t *loc, H5_index_t idx_type, diff --git a/src/H5Aprivate.h b/src/H5Aprivate.h index 0c0e519..6646fa2 100644 --- a/src/H5Aprivate.h +++ b/src/H5Aprivate.h @@ -24,6 +24,8 @@ /* Private headers needed by this file */ #include "H5Gprivate.h" /* Groups */ +#include "H5Oprivate.h" /* Object headers */ +#include "H5Tprivate.h" /* Datatypes */ /**************************/ @@ -38,6 +40,29 @@ /* Forward references of package typedefs */ typedef struct H5A_t H5A_t; +/* Attribute iteration operator for internal library callbacks */ +typedef herr_t (*H5A_lib_iterate_t)(const H5A_t *attr, void *op_data); + +/* Describe kind of callback to make for each attribute */ +typedef enum H5A_attr_iter_op_type_t { +#ifndef H5_NO_DEPRECATED_SYMBOLS + H5A_ATTR_OP_APP, /* Application callback */ +#endif /* H5_NO_DEPRECATED_SYMBOLS */ + H5A_ATTR_OP_APP2, /* Revised application callback */ + H5A_ATTR_OP_LIB /* Library internal callback */ +} H5A_attr_iter_op_type_t; + +typedef struct H5A_attr_iter_op_t { + H5A_attr_iter_op_type_t op_type; + union { +#ifndef H5_NO_DEPRECATED_SYMBOLS + H5A_operator1_t app_op; /* Application callback for each attribute */ +#endif /* H5_NO_DEPRECATED_SYMBOLS */ + H5A_operator2_t app_op2; /* Revised application callback for each attribute */ + H5A_lib_iterate_t lib_op; /* Library internal callback for each attribute */ + } u; +} H5A_attr_iter_op_t; + /*****************************/ /* Library-private Variables */ @@ -51,6 +76,13 @@ typedef struct H5A_t H5A_t; /* General attribute routines */ H5_DLL struct H5O_loc_t *H5A_oloc(H5A_t *attr); H5_DLL H5G_name_t *H5A_nameof(H5A_t *attr); +H5_DLL H5T_t *H5A_type(const H5A_t *attr); +H5_DLL herr_t H5O_attr_iterate_real(hid_t loc_id, const H5O_loc_t *loc, + hid_t dxpl_id, H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, + hsize_t *last_attr, const H5A_attr_iter_op_t *attr_op, void *op_data); +H5_DLL herr_t H5O_attr_iterate(hid_t loc_id, hid_t dxpl_id, H5_index_t idx_type, + H5_iter_order_t order, hsize_t skip, hsize_t *last_attr, + const H5A_attr_iter_op_t *op, void *op_data); #endif /* _H5Aprivate_H */ diff --git a/src/H5Bcache.c b/src/H5Bcache.c index 191766c..8022743 100644 --- a/src/H5Bcache.c +++ b/src/H5Bcache.c @@ -153,6 +153,10 @@ H5B_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata) /* entries used */ UINT16DECODE(p, bt->nchildren); + /* Check if bt->nchildren is greater than two_k */ + if(bt->nchildren > shared->two_k) + HGOTO_ERROR(H5E_BTREE, H5E_BADVALUE, NULL, "number of children is greater than maximum") + /* sibling pointers */ H5F_addr_decode(udata->f, (const uint8_t **)&p, &(bt->left)); H5F_addr_decode(udata->f, (const uint8_t **)&p, &(bt->right)); diff --git a/src/H5Dchunk.c b/src/H5Dchunk.c index 06e6ee1..aff686c 100644 --- a/src/H5Dchunk.c +++ b/src/H5Dchunk.c @@ -1002,7 +1002,7 @@ H5D_free_chunk_info(void *item, void UNUSED *key, void UNUSED *opdata) H5S_select_all(chunk_info->fspace, TRUE); /* Close the chunk's memory dataspace, if it's not shared */ - if(!chunk_info->mspace_shared) + if(!chunk_info->mspace_shared && chunk_info->mspace) (void)H5S_close(chunk_info->mspace); /* Free the actual chunk info */ diff --git a/src/H5Dcontig.c b/src/H5Dcontig.c index 674582d..c1ff68c 100644 --- a/src/H5Dcontig.c +++ b/src/H5Dcontig.c @@ -420,6 +420,7 @@ H5D_contig_construct(H5F_t *f, H5D_t *dset) hsize_t nelmts; /* Number of elements in dataspace */ size_t dt_size; /* Size of datatype */ hsize_t tmp_size; /* Temporary holder for raw data size */ + size_t tmp_sieve_buf_size; /* Temporary holder for sieve buffer size */ hsize_t dim[H5O_LAYOUT_NDIMS]; /* Current size of data in elements */ hsize_t max_dim[H5O_LAYOUT_NDIMS]; /* Maximum size of data in elements */ int ndims; /* Rank of dataspace */ @@ -464,8 +465,15 @@ H5D_contig_construct(H5F_t *f, H5D_t *dset) /* Assign the dataset's contiguous storage size */ dset->shared->layout.storage.u.contig.size = tmp_size; - /* Get the sieve buffer size for this dataset */ - dset->shared->cache.contig.sieve_buf_size = H5F_SIEVE_BUF_SIZE(f); + /* Get the sieve buffer size for the file */ + tmp_sieve_buf_size = H5F_SIEVE_BUF_SIZE(f); + + /* Adjust the sieve buffer size to the smaller one between the dataset size and the buffer size + * from the file access property. (SLU - 2012/3/30) */ + if(tmp_size < tmp_sieve_buf_size) + dset->shared->cache.contig.sieve_buf_size = tmp_size; + else + dset->shared->cache.contig.sieve_buf_size = tmp_sieve_buf_size; done: FUNC_LEAVE_NOAPI(ret_value) @@ -965,6 +973,7 @@ H5D_contig_writevv_sieve_cb(hsize_t dst_off, hsize_t src_off, size_t len, /* Allocate room for the data sieve buffer */ if(NULL == (dset_contig->sieve_buf = H5FL_BLK_MALLOC(sieve_buf, dset_contig->sieve_buf_size))) HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "memory allocation failed") + #ifdef H5_CLEAR_MEMORY if(dset_contig->sieve_size > len) HDmemset(dset_contig->sieve_buf + len, 0, (dset_contig->sieve_size - len)); diff --git a/src/H5Dint.c b/src/H5Dint.c index 584626c..c9e64cb 100644 --- a/src/H5Dint.c +++ b/src/H5Dint.c @@ -2569,7 +2569,8 @@ H5D_flush(const H5F_t *f, hid_t dxpl_id) udata.dxpl_id = dxpl_id; /* Iterate over all the open datasets */ - H5I_search(H5I_DATASET, H5D_flush_cb, &udata, FALSE); + if(H5I_iterate(H5I_DATASET, H5D_flush_cb, &udata, FALSE) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_BADITER, FAIL, "unable to flush cached dataset info") done: FUNC_LEAVE_NOAPI(ret_value) diff --git a/src/H5Dio.c b/src/H5Dio.c index 248ea9e..06e4417 100644 --- a/src/H5Dio.c +++ b/src/H5Dio.c @@ -434,6 +434,7 @@ H5D_read(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, || dataset->shared->layout.type == H5D_COMPACT); /* Call storage method's I/O initialization routine */ + HDmemset(&fm, 0, sizeof(H5D_chunk_map_t)); if(io_info.layout_ops.io_init && (*io_info.layout_ops.io_init)(&io_info, &type_info, nelmts, file_space, mem_space, &fm) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize I/O info") io_op_init = TRUE; @@ -657,6 +658,7 @@ H5D_write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, #endif /*H5_HAVE_PARALLEL*/ /* Call storage method's I/O initialization routine */ + HDmemset(&fm, 0, sizeof(H5D_chunk_map_t)); if(io_info.layout_ops.io_init && (*io_info.layout_ops.io_init)(&io_info, &type_info, nelmts, file_space, mem_space, &fm) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize I/O info") io_op_init = TRUE; diff --git a/src/H5Dlayout.c b/src/H5Dlayout.c index c217283..d463fde 100644 --- a/src/H5Dlayout.c +++ b/src/H5Dlayout.c @@ -632,6 +632,10 @@ H5D_layout_oh_read(H5D_t *dataset, hid_t dxpl_id, hid_t dapl_id, H5P_genplist_t switch(dataset->shared->layout.type) { case H5D_CONTIGUOUS: + { + hsize_t tmp_size; /* Temporary holder for raw data size */ + size_t tmp_sieve_buf_size; /* Temporary holder for sieve buffer size */ + /* Compute the size of the contiguous storage for versions of the * layout message less than version 3 because versions 1 & 2 would * truncate the dimension sizes to 32-bits of information. - QAK 5/26/04 @@ -640,7 +644,6 @@ H5D_layout_oh_read(H5D_t *dataset, hid_t dxpl_id, hid_t dapl_id, H5P_genplist_t hssize_t snelmts; /* Temporary holder for number of elements in dataspace */ hsize_t nelmts; /* Number of elements in dataspace */ size_t dt_size; /* Size of datatype */ - hsize_t tmp_size; /* Temporary holder for raw data size */ /* Retrieve the number of elements in the dataspace */ if((snelmts = H5S_GET_EXTENT_NPOINTS(dataset->shared->space)) < 0) @@ -660,10 +663,19 @@ H5D_layout_oh_read(H5D_t *dataset, hid_t dxpl_id, hid_t dapl_id, H5P_genplist_t /* Assign the dataset's contiguous storage size */ dataset->shared->layout.storage.u.contig.size = tmp_size; - } /* end if */ - - /* Get the sieve buffer size for this dataset */ - dataset->shared->cache.contig.sieve_buf_size = H5F_SIEVE_BUF_SIZE(dataset->oloc.file); + } else + tmp_size = dataset->shared->layout.storage.u.contig.size; + + /* Get the sieve buffer size for the file */ + tmp_sieve_buf_size = H5F_SIEVE_BUF_SIZE(dataset->oloc.file); + + /* Adjust the sieve buffer size to the smaller one between the dataset size and the buffer size + * from the file access property. (SLU - 2012/3/30) */ + if(tmp_size < tmp_sieve_buf_size) + dataset->shared->cache.contig.sieve_buf_size = tmp_size; + else + dataset->shared->cache.contig.sieve_buf_size = tmp_sieve_buf_size; + } break; case H5D_CHUNKED: diff --git a/src/H5Doh.c b/src/H5Doh.c index db7cae1..aac473b 100644 --- a/src/H5Doh.c +++ b/src/H5Doh.c @@ -56,6 +56,8 @@ 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); + /*********************/ /* Package Variables */ @@ -81,7 +83,8 @@ const H5O_obj_class_t H5O_OBJ_DATASET[1] = {{ H5O_dset_open, /* open an object of this class */ H5O_dset_create, /* create an object of this class */ H5O_dset_get_oloc, /* get an object header location for an object */ - H5O_dset_bh_info /* get the index & heap info for an object */ + H5O_dset_bh_info, /* get the index & heap info for an object */ + H5O_dset_flush /* flush an opened object of this class */ }}; /* Declare a free list to manage the H5D_copy_file_ud_t struct */ @@ -444,3 +447,48 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_dset_bh_info() */ + +/*------------------------------------------------------------------------- + * Function: H5O_dset_flush + * + * Purpose: To flush any dataset information cached in memory + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Vailin Choi + * February 2012 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_dset_flush(H5G_loc_t *obj_loc, hid_t dxpl_id) +{ + H5D_t *dset; /* Dataset opened */ + H5O_type_t obj_type; /* Type of object at location */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(obj_loc); + HDassert(obj_loc->oloc); + + /* Check that the object found is the correct type */ + if(H5O_obj_type(obj_loc->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, NULL, "unable to release dataset") + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_dset_flush() */ diff --git a/src/H5E.c b/src/H5E.c index 4e14887..e74211e 100644 --- a/src/H5E.c +++ b/src/H5E.c @@ -107,7 +107,7 @@ static H5E_cls_t *H5E_register_class(const char *cls_name, const char *lib_name, const char *version); static herr_t H5E_unregister_class(H5E_cls_t *cls); static ssize_t H5E_get_class_name(const H5E_cls_t *cls, char *name, size_t size); -static int H5E_close_msg_cb(void *obj_ptr, hid_t obj_id, void *key); +static int H5E_close_msg_cb(void *obj_ptr, hid_t obj_id, void *udata); static herr_t H5E_close_msg(H5E_msg_t *err); static H5E_msg_t *H5E_create_msg(H5E_cls_t *cls, H5E_type_t msg_type, const char *msg); static H5E_t *H5E_get_current_stack(void); @@ -543,8 +543,8 @@ H5E_unregister_class(H5E_cls_t *cls) HDassert(cls); /* Iterate over all the messages and delete those in this error class */ - /* (Ignore return value, since callback isn't designed to return a particular object) */ - (void)H5I_search(H5I_ERROR_MSG, H5E_close_msg_cb, cls, FALSE); + if(H5I_iterate(H5I_ERROR_MSG, H5E_close_msg_cb, cls, FALSE) < 0) + HGOTO_ERROR(H5E_ERROR, H5E_BADITER, FAIL, "unable to free all messages in this error class") /* Free error class structure */ if(H5E_free_class(cls) < 0) @@ -631,7 +631,7 @@ H5E_get_class_name(const H5E_cls_t *cls, char *name, size_t size) /*------------------------------------------------------------------------- * Function: H5E_close_msg_cb * - * Purpose: H5I_search callback function to close error messages in the + * Purpose: H5I_iterate callback function to close error messages in the * error class. * * Return: Non-negative value on success/Negative on failure @@ -642,10 +642,10 @@ H5E_get_class_name(const H5E_cls_t *cls, char *name, size_t size) *------------------------------------------------------------------------- */ static int -H5E_close_msg_cb(void *obj_ptr, hid_t obj_id, void *key) +H5E_close_msg_cb(void *obj_ptr, hid_t obj_id, void *udata) { H5E_msg_t *err_msg = (H5E_msg_t*)obj_ptr; - H5E_cls_t *cls = (H5E_cls_t*)key; + H5E_cls_t *cls = (H5E_cls_t*)udata; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT diff --git a/src/H5Edefin.h b/src/H5Edefin.h index 887c2bb..ee284c4 100644 --- a/src/H5Edefin.h +++ b/src/H5Edefin.h @@ -93,6 +93,7 @@ hid_t H5E_CANTRELEASE_g = FAIL; /* Unable to release object */ hid_t H5E_CANTGET_g = FAIL; /* Can't get value */ hid_t H5E_CANTSET_g = FAIL; /* Can't set value */ hid_t H5E_DUPCLASS_g = FAIL; /* Duplicate class name in parent class */ +hid_t H5E_SETDISALLOWED_g = FAIL; /* Disallowed operation */ /* Free space errors */ hid_t H5E_CANTMERGE_g = FAIL; /* Can't merge objects */ diff --git a/src/H5Einit.h b/src/H5Einit.h index 802c94a..6881e48 100644 --- a/src/H5Einit.h +++ b/src/H5Einit.h @@ -339,6 +339,11 @@ if((msg = H5E_create_msg(cls, H5E_MINOR, "Duplicate class name in parent class") HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") if((H5E_DUPCLASS_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") +assert(H5E_SETDISALLOWED_g==(-1)); +if((msg = H5E_create_msg(cls, H5E_MINOR, "Disallowed operation"))==NULL) + HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") +if((H5E_SETDISALLOWED_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") /* Free space errors */ assert(H5E_CANTMERGE_g==(-1)); diff --git a/src/H5Epubgen.h b/src/H5Epubgen.h index f6a20f2..967b248 100644 --- a/src/H5Epubgen.h +++ b/src/H5Epubgen.h @@ -155,9 +155,11 @@ H5_DLLVAR hid_t H5E_CANTRELEASE_g; /* Unable to release object */ #define H5E_CANTGET (H5OPEN H5E_CANTGET_g) #define H5E_CANTSET (H5OPEN H5E_CANTSET_g) #define H5E_DUPCLASS (H5OPEN H5E_DUPCLASS_g) +#define H5E_SETDISALLOWED (H5OPEN H5E_SETDISALLOWED_g) H5_DLLVAR hid_t H5E_CANTGET_g; /* Can't get value */ H5_DLLVAR hid_t H5E_CANTSET_g; /* Can't set value */ H5_DLLVAR hid_t H5E_DUPCLASS_g; /* Duplicate class name in parent class */ +H5_DLLVAR hid_t H5E_SETDISALLOWED_g; /* Disallowed operation */ /* Free space errors */ #define H5E_CANTMERGE (H5OPEN H5E_CANTMERGE_g) diff --git a/src/H5Eterm.h b/src/H5Eterm.h index 921b3b6..5edcd34 100644 --- a/src/H5Eterm.h +++ b/src/H5Eterm.h @@ -94,7 +94,8 @@ H5E_CANTRELEASE_g= /* Property list errors */ H5E_CANTGET_g= H5E_CANTSET_g= -H5E_DUPCLASS_g= +H5E_DUPCLASS_g= +H5E_SETDISALLOWED_g= /* Free space errors */ H5E_CANTMERGE_g= diff --git a/src/H5F.c b/src/H5F.c index d152448..2e14e34 100644 --- a/src/H5F.c +++ b/src/H5F.c @@ -52,7 +52,7 @@ typedef struct H5F_olist_t { } H5F_olist_t; /* PRIVATE PROTOTYPES */ -static size_t H5F_get_objects(const H5F_t *f, unsigned types, size_t max_objs, hid_t *obj_id_list, hbool_t app_ref); +static herr_t H5F_get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_list, hbool_t app_ref, size_t *obj_id_count_ptr); static int H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key); static H5F_t *H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf); @@ -363,11 +363,6 @@ done: * * Programmer: Raymond Lu * Wednesday, Dec 5, 2001 - * Modification: - * Raymond Lu - * 24 September 2008 - * Changed the return value to ssize_t to accommadate - * potential large number of objects. * *------------------------------------------------------------------------- */ @@ -375,18 +370,24 @@ ssize_t H5Fget_obj_count(hid_t file_id, unsigned types) { H5F_t *f = NULL; /* File to query */ - ssize_t ret_value; /* Return value */ + size_t obj_count = 0; /* Number of opened objects */ + ssize_t ret_value; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE2("Zs", "iIu", file_id, types); + /* Check arguments */ if(file_id != (hid_t)H5F_OBJ_ALL && (NULL == (f = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file id") if(0 == (types & H5F_OBJ_ALL)) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not an object type") - /* H5F_get_obj_count doesn't fail */ - ret_value = (ssize_t)H5F_get_obj_count(f, types, TRUE); + /* Perform the query */ + if(H5F_get_obj_count(f, types, TRUE, &obj_count) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_obj_count failed") + + /* Set the return value */ + ret_value = (ssize_t)obj_count; done: FUNC_LEAVE_API(ret_value) @@ -399,31 +400,30 @@ done: * Purpose: Private function return the number of opened object IDs * (files, datasets, groups, datatypes) in the same file. * - * Return: Non-negative on success; can't fail. + * Return: SUCCEED on success, FAIL on failure. * * Programmer: Raymond Lu * Wednesday, Dec 5, 2001 * - * Modification: - * Raymond Lu - * 24 September 2008 - * Changed the return value to size_t to accommadate - * potential large number of objects. - * *------------------------------------------------------------------------- */ -size_t -H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref) +herr_t +H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref, size_t *obj_id_count_ptr) { - size_t ret_value; /* Return value */ + herr_t ret_value = SUCCEED; - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity check */ + HDassert(obj_id_count_ptr); - /* H5F_get_objects doesn't fail */ - ret_value = H5F_get_objects(f, types, 0, NULL, app_ref); + /* Perform the query */ + if((ret_value = H5F_get_objects(f, types, 0, NULL, app_ref, obj_id_count_ptr)) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_objects failed") +done: FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5F_get_obj_count() */ /*------------------------------------------------------------------------- @@ -448,19 +448,25 @@ ssize_t H5Fget_obj_ids(hid_t file_id, unsigned types, size_t max_objs, hid_t *oid_list) { H5F_t *f = NULL; /* File to query */ - ssize_t ret_value; /* Return value */ + size_t obj_id_count = 0; /* Number of open objects */ + ssize_t ret_value; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE4("Zs", "iIuz*i", file_id, types, max_objs, oid_list); + /* Check arguments */ if(file_id != (hid_t)H5F_OBJ_ALL && (NULL == (f = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file id") if(0 == (types & H5F_OBJ_ALL)) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not an object type") HDassert(oid_list); - /* H5F_get_objects doesn't fail */ - ret_value = (ssize_t)H5F_get_obj_ids(f, types, max_objs, oid_list, TRUE); + /* Perform the query */ + if(H5F_get_obj_ids(f, types, max_objs, oid_list, TRUE, &obj_id_count) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_obj_ids failed") + + /* Set the return value */ + ret_value = (ssize_t)obj_id_count; done: FUNC_LEAVE_API(ret_value) @@ -477,26 +483,25 @@ done: * Programmer: Raymond Lu * Wednesday, Dec 5, 2001 * - * Modification: - * Raymond Lu - * 24 September 2008 - * Changed the return value and MAX_OBJTS to size_t to accommadate - * potential large number of objects. - * *------------------------------------------------------------------------- */ -size_t -H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *oid_list, hbool_t app_ref) +herr_t +H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *oid_list, hbool_t app_ref, size_t *obj_id_count_ptr) { - size_t ret_value; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity check */ + HDassert(obj_id_count_ptr); - /* H5F_get_objects doesn't fail */ - ret_value = H5F_get_objects(f, types, max_objs, oid_list, app_ref); + /* Perform the query */ + if((ret_value = H5F_get_objects(f, types, max_objs, oid_list, app_ref, obj_id_count_ptr)) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_objects failed") +done: FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5F_get_obj_ids() */ /*--------------------------------------------------------------------------- @@ -512,14 +517,18 @@ H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *oid_list * *--------------------------------------------------------------------------- */ -static size_t -H5F_get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_list, hbool_t app_ref) +static herr_t +H5F_get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_list, hbool_t app_ref, size_t *obj_id_count_ptr) { size_t obj_id_count=0; /* Number of open IDs */ H5F_olist_t olist; /* Structure to hold search results */ - size_t ret_value; /* Return value */ + htri_t type_exists; /* Whether objects of a type are open */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_NOAPI_NOINIT + + /* Sanity check */ + HDassert(obj_id_count_ptr); /* Set up search information */ olist.obj_id_list = (max_index==0 ? NULL : obj_id_list); @@ -537,45 +546,50 @@ H5F_get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_ olist.file_info.ptr.shared = f ? f->shared : NULL; } /* end else */ - /* Search through file IDs to count the number, and put their - * IDs on the object list. H5I_search returns NULL if no object - * is found, so don't return failure in this function. */ + /* Iterate through file IDs to count the number, and put their + * IDs on the object list. */ if(types & H5F_OBJ_FILE) { olist.obj_type = H5I_FILE; - (void)H5I_search(H5I_FILE, H5F_get_objects_cb, &olist, app_ref); + if(H5I_iterate(H5I_FILE, H5F_get_objects_cb, &olist, app_ref) < 0) + HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(1)") } /* end if */ /* Search through dataset IDs to count number of datasets, and put their * IDs on the object list */ if(types & H5F_OBJ_DATASET) { olist.obj_type = H5I_DATASET; - (void)H5I_search(H5I_DATASET, H5F_get_objects_cb, &olist, app_ref); - } + if(H5I_iterate(H5I_DATASET, H5F_get_objects_cb, &olist, app_ref) < 0) + HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(2)") + } /* end if */ /* Search through group IDs to count number of groups, and put their * IDs on the object list */ if(types & H5F_OBJ_GROUP) { olist.obj_type = H5I_GROUP; - (void)H5I_search(H5I_GROUP, H5F_get_objects_cb, &olist, app_ref); - } + if(H5I_iterate(H5I_GROUP, H5F_get_objects_cb, &olist, app_ref) < 0) + HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(3)") + } /* end if */ /* Search through datatype IDs to count number of named datatypes, and put their * IDs on the object list */ if(types & H5F_OBJ_DATATYPE) { olist.obj_type = H5I_DATATYPE; - (void)H5I_search(H5I_DATATYPE, H5F_get_objects_cb, &olist, app_ref); - } + if(H5I_iterate(H5I_DATATYPE, H5F_get_objects_cb, &olist, app_ref) < 0) + HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(4)") + } /* end if */ /* Search through attribute IDs to count number of attributes, and put their * IDs on the object list */ if(types & H5F_OBJ_ATTR) { olist.obj_type = H5I_ATTR; - (void)H5I_search(H5I_ATTR, H5F_get_objects_cb, &olist, app_ref); - } + if(H5I_iterate(H5I_ATTR, H5F_get_objects_cb, &olist, app_ref) < 0) + HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(5)") + } /* end if */ /* Set the number of objects currently open */ - ret_value = obj_id_count; + *obj_id_count_ptr = obj_id_count; +done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5F_get_objects() */ @@ -593,8 +607,6 @@ H5F_get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_ * Programmer: Raymond Lu * Wednesday, Dec 5, 2001 * - * Modification: - * *------------------------------------------------------------------------- */ static int @@ -626,8 +638,8 @@ H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key) /* Check if we've filled up the array. Return TRUE only if * we have filled up the array. Otherwise return FALSE(RET_VALUE is - * preset to FALSE) because H5I_search needs the return value of FALSE - * to continue searching. */ + * preset to FALSE) because H5I_iterate needs the return value of + * FALSE to continue the iteration. */ if(olist->max_index>0 && olist->list_index>=olist->max_index) HGOTO_DONE(TRUE) /* Indicate that the iterator should stop */ } @@ -691,8 +703,8 @@ H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key) /* Check if we've filled up the array. Return TRUE only if * we have filled up the array. Otherwise return FALSE(RET_VALUE is - * preset to FALSE) because H5I_search needs the return value of FALSE - * to continue searching. */ + * preset to FALSE) because H5I_iterate needs the return value of + * FALSE to continue iterating. */ if(olist->max_index>0 && olist->list_index>=olist->max_index) HGOTO_DONE(TRUE) /* Indicate that the iterator should stop */ } /* end if */ @@ -1798,8 +1810,6 @@ done: * Programmer: Quincey Koziol * Tuesday, July 19, 2005 * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t @@ -1881,27 +1891,36 @@ H5F_try_close(H5F_t *f) if(f->nopen_objs > 0) { size_t obj_count; /* # of open objects */ hid_t objs[128]; /* Array of objects to close */ + herr_t result; /* Local result from obj ID query */ size_t u; /* Local index variable */ /* Get the list of IDs of open dataset, group, & attribute objects */ - while((obj_count = H5F_get_obj_ids(f, H5F_OBJ_LOCAL|H5F_OBJ_DATASET|H5F_OBJ_GROUP|H5F_OBJ_ATTR, (int)(sizeof(objs)/sizeof(objs[0])), objs, FALSE)) != 0) { + while((result = H5F_get_obj_ids(f, H5F_OBJ_LOCAL | H5F_OBJ_DATASET | H5F_OBJ_GROUP | H5F_OBJ_ATTR, (int)(sizeof(objs) / sizeof(objs[0])), objs, FALSE, &obj_count)) <= 0 + && obj_count != 0 ) { + /* Try to close all the open objects in this file */ for(u = 0; u < obj_count; u++) if(H5I_dec_ref(objs[u]) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object") } /* end while */ + if(result < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_obj_ids failed(1)") /* Get the list of IDs of open named datatype objects */ /* (Do this separately from the dataset & attribute IDs, because * they could be using one of the named datatypes and then the * open named datatype ID will get closed twice) */ - while((obj_count = H5F_get_obj_ids(f, H5F_OBJ_LOCAL|H5F_OBJ_DATATYPE, (int)(sizeof(objs)/sizeof(objs[0])), objs, FALSE)) != 0) { + while((result = H5F_get_obj_ids(f, H5F_OBJ_LOCAL | H5F_OBJ_DATATYPE, (int)(sizeof(objs) / sizeof(objs[0])), objs, FALSE, &obj_count)) <= 0 + && obj_count != 0) { + /* Try to close all the open objects in this file */ for(u = 0; u < obj_count; u++) if(H5I_dec_ref(objs[u]) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object") } /* end while */ + if(result < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_obj_ids failed(2)") } /* end if */ } /* end if */ @@ -2574,6 +2593,139 @@ done: /*------------------------------------------------------------------------- + * Function: H5Fget_file_image + * + * Purpose: If a buffer is provided (via the buf_ptr argument) and is + * big enough (size in buf_len argument), load *buf_ptr with + * an image of the open file whose ID is provided in the + * file_id parameter, and return the number of bytes copied + * to the buffer. + * + * If the buffer exists, but is too small to contain an image + * of the indicated file, return a negative number. + * + * Finally, if no buffer is provided, return the size of the + * buffer needed. This value is simply the eoa of the target + * file. + * + * Note that any user block is skipped. + * + * Also note that the function may not be used on files + * opened with either the split/multi file driver or the + * family file driver. + * + * In the former case, the sparse address space makes the + * get file image operation impractical, due to the size of + * the image typically required. + * + * In the case of the family file driver, the problem is + * the driver message in the super block, which will prevent + * the image being opened with any driver other than the + * family file driver -- which negates the purpose of the + * operation. This can be fixed, but no resources for + * this now. + * + * Return: Success: Bytes copied / number of bytes needed. + * Failure: negative value + * + * Programmer: John Mainzer + * 11/15/11 + * + *------------------------------------------------------------------------- + */ +ssize_t +H5Fget_file_image(hid_t file_id, void *buf_ptr, size_t buf_len) +{ + H5F_t *file; /* File object for file ID */ + H5FD_t *fd_ptr; /* file driver */ + haddr_t eoa; /* End of file address */ + ssize_t ret_value; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE3("Zs", "i*xz", file_id, buf_ptr, buf_len); + + /* Check args */ + if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID") + if(!file || !file->shared || !file->shared->lf) + HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "file_id yields invalid file pointer") + fd_ptr = file->shared->lf; + if(!fd_ptr->cls) + HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "fd_ptr yields invalid class pointer") + + /* the address space used by the split and multi file drivers is not + * a good fit for this call. Since the plan is to depreciate these + * drivers anyway, don't bother to do a "force fit". + * + * The following clause tests for the multi file driver, and fails + * if the supplied file has the multi file driver as its top level + * file driver. However, this test will not work if there is some + * other file driver sitting on top of the multi file driver. + * + * I'm not sure if this is possible at present, but in all likelyhood, + * it will become possible in the future. On the other hand, we may + * remove the split/multi file drivers before then. + * + * I am leaving this solution in for now, but we should review it, + * and improve the solution if necessary. + * + * JRM -- 11/11/22 + */ + if(HDstrcmp(fd_ptr->cls->name, "multi") == 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Not supported for multi file driver.") + + /* While the family file driver is conceptually fully compatible + * with the get file image operation, it sets a file driver message + * in the super block that prevents the image being opened with any + * driver other than the family file driver. Needless to say, this + * rather defeats the purpose of the get file image operation. + * + * While this problem is quire solvable, the required time and + * resources are lacking at present. Hence, for now, we don't + * allow the get file image operation to be perfomed on files + * opened with the family file driver. + * + * Observe that the following test only looks at the top level + * driver, and fails if there is some other driver sitting on to + * of the family file driver. + * + * I don't think this can happen at present, but that may change + * in the future. + * JRM -- 12/21/11 + */ + if(HDstrcmp(fd_ptr->cls->name, "family") == 0) + HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "Not supported for family file driver.") + + + /* Go get the actual file size */ + if(HADDR_UNDEF == (eoa = H5FD_get_eoa(file->shared->lf, H5FD_MEM_DEFAULT))) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get file size") + + /* set ret_value = to eoa -- will overwrite this if appropriate */ + ret_value = (ssize_t)eoa; + + /* 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 */ + + /* Check for buffer too small */ + if((haddr_t)buf_len < eoa) + HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "supplied buffer too small") + + space_needed = (size_t)eoa; + + /* 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) + HGOTO_ERROR(H5E_FILE, H5E_READERROR, FAIL, "file image read request failed") + } /* end if */ + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Fget_file_image() */ + + +/*------------------------------------------------------------------------- * Function: H5Fget_mdc_config * * Purpose: Retrieves the current automatic cache resize configuration diff --git a/src/H5FD.c b/src/H5FD.c index 66fa3b9..18b0eb6 100644 --- a/src/H5FD.c +++ b/src/H5FD.c @@ -70,6 +70,10 @@ static herr_t H5FD_pl_copy(void *(*copy_func)(const void *), size_t pl_size, static herr_t H5FD_pl_close(hid_t driver_id, herr_t (*free_func)(void *), void *pl); static herr_t H5FD_free_cls(H5FD_class_t *cls); +static herr_t H5FD_fapl_copy(hid_t driver_id, const void *fapl, void **copied_fapl); +static herr_t H5FD_dxpl_copy(hid_t driver_id, const void *dxpl, void **copied_dxpl); +static int H5FD_query(const H5FD_t *f, unsigned long *flags/*out*/); +static int H5FD_driver_query(const H5FD_class_t *driver, unsigned long *flags/*out*/); /*********************/ /* Package Variables */ @@ -750,17 +754,15 @@ done: * Programmer: Robb Matzke * Tuesday, August 3, 1999 * - * Modifications: - * *------------------------------------------------------------------------- */ -herr_t +static herr_t H5FD_fapl_copy(hid_t driver_id, const void *old_fapl, void **copied_fapl) { H5FD_class_t *driver; herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOINIT /* Check args */ if(NULL == (driver = (H5FD_class_t *)H5I_object(driver_id))) @@ -871,17 +873,15 @@ done: * Programmer: Robb Matzke * Tuesday, August 3, 1999 * - * Modifications: - * *------------------------------------------------------------------------- */ -herr_t +static herr_t H5FD_dxpl_copy(hid_t driver_id, const void *old_dxpl, void **copied_dxpl) { H5FD_class_t *driver; herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOINIT /* Check args */ if(NULL == (driver = (H5FD_class_t *)H5I_object(driver_id))) @@ -1039,6 +1039,8 @@ H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr) H5FD_t *file = NULL; /* VFD file struct */ hid_t driver_id = -1; /* VFD ID */ H5P_genplist_t *plist; /* Property list pointer */ + unsigned long driver_flags = 0; /* File-inspecific driver feature flags */ + H5FD_file_image_info_t file_image_info; /* Initial file image */ H5FD_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI(NULL) @@ -1061,6 +1063,19 @@ H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr) if(NULL == driver->open) HGOTO_ERROR(H5E_VFL, H5E_UNSUPPORTED, NULL, "file driver has no `open' method") + /* Query driver flag */ + H5FD_driver_query(driver, &driver_flags); + + /* Get initial file image info */ + if(H5P_get(plist, H5F_ACS_FILE_IMAGE_INFO_NAME, &file_image_info) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get file image info") + + /* If an image is provided, make sure the driver supports this feature */ + HDassert(((file_image_info.buffer != NULL) && (file_image_info.size > 0)) || + ((file_image_info.buffer == NULL) && (file_image_info.size == 0))); + if((file_image_info.buffer != NULL) && !(driver_flags & H5FD_FEAT_ALLOW_FILE_IMAGE)) + HGOTO_ERROR(H5E_VFL, H5E_UNSUPPORTED, NULL, "file image set, but not supported.") + /* Dispatch to file driver */ if(HADDR_UNDEF == maxaddr) maxaddr = driver->maxaddr; @@ -1318,19 +1333,17 @@ done: * Programmer: Quincey Koziol * Friday, August 25, 2000 * - * Modifications: - * *------------------------------------------------------------------------- */ -int +static int H5FD_query(const H5FD_t *f, unsigned long *flags/*out*/) { - int ret_value=0; + int ret_value = 0; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOINIT - assert(f); - assert(flags); + HDassert(f); + HDassert(flags); /* Check for query driver and call it */ if(f->cls->query) @@ -1340,7 +1353,44 @@ H5FD_query(const H5FD_t *f, unsigned long *flags/*out*/) done: FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5FD_query() */ + + +/*------------------------------------------------------------------------- +* Function: H5FD_driver_query +* +* Purpose: Similar to H5FD_query(), but intended for cases when we don't +* have a file available (e.g. before one is opened). Since we +* can't use the file to get the driver, the driver is passed in +* as a parameter. +* +* Return: Success: non-negative +* Failure: negative +* +* Programmer: Jacob Gruber +* Wednesday, August 17, 2011 +* +*------------------------------------------------------------------------- +*/ +static int +H5FD_driver_query(const H5FD_class_t *driver, unsigned long *flags/*out*/) +{ + int ret_value = 0; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(driver); + HDassert(flags); + + /* Check for the driver to query and then query it */ + if(driver->query) + ret_value = (driver->query)(NULL, flags); + else + *flags = 0; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_driver_query() */ /*------------------------------------------------------------------------- diff --git a/src/H5FDcore.c b/src/H5FDcore.c index 7fa0e7c..cc48e51 100644 --- a/src/H5FDcore.c +++ b/src/H5FDcore.c @@ -38,8 +38,24 @@ /* The driver identification number, initialized at runtime */ static hid_t H5FD_CORE_g = 0; -/* - * The description of a file belonging to this driver. The `eoa' and `eof' +/* Since Windows doesn't follow the rest of the world when it comes + * to POSIX I/O types, some typedefs and constants are needed to avoid + * making the code messy with #ifdefs. + * NOTE: These are only used when writing data to the backing store on + * file close. + */ +#ifdef H5_HAVE_WIN32_API +typedef unsigned int h5_core_io_t; +typedef int h5_core_io_ret_t; +static int H5_CORE_MAX_IO_BYTES_g = INT_MAX; +#else +/* Unix, everyone else */ +typedef size_t h5_core_io_t; +typedef ssize_t h5_core_io_ret_t; +static size_t H5_CORE_MAX_IO_BYTES_g = SSIZET_MAX; +#endif /* H5_HAVE_WIN32_API */ + +/* The description of a file belonging to this driver. The `eoa' and `eof' * determine the amount of hdf5 address space in use and the high-water mark * of the file (the current size of the underlying memory). */ @@ -54,8 +70,7 @@ typedef struct H5FD_core_t { int fd; /*backing store file descriptor */ /* Information for determining uniqueness of a file with a backing store */ #ifndef H5_HAVE_WIN32_API - /* - * On most systems the combination of device and i-node number uniquely + /* On most systems the combination of device and i-node number uniquely * identify a file. */ dev_t device; /*file device number */ @@ -65,19 +80,28 @@ typedef struct H5FD_core_t { ino_t inode; /*file i-node number */ #endif /*H5_VMS*/ #else - /* - * On H5_HAVE_WIN32_API the low-order word of a unique identifier associated with the - * file and the volume serial number uniquely identify a file. This number - * (which, both? -rpm) may change when the system is restarted or when the - * file is opened. After a process opens a file, the identifier is - * constant until the file is closed. An application can use this - * identifier and the volume serial number to determine whether two - * handles refer to the same file. + /* Files in windows are uniquely identified by the volume serial + * number and the file index (both low and high parts). + * + * There are caveats where these numbers can change, especially + * on FAT file systems. On NTFS, however, a file should keep + * those numbers the same until renamed or deleted (though you + * can use ReplaceFile() on NTFS to keep the numbers the same + * while renaming). + * + * See the MSDN "BY_HANDLE_FILE_INFORMATION Structure" entry for + * more information. + * + * http://msdn.microsoft.com/en-us/library/aa363788(v=VS.85).aspx */ - DWORD fileindexlo; - DWORD fileindexhi; -#endif + DWORD nFileIndexLow; + DWORD nFileIndexHigh; + DWORD dwVolumeSerialNumber; + + HANDLE hFile; /* Native windows file handle */ +#endif /* H5_HAVE_WIN32_API */ hbool_t dirty; /*changes not saved? */ + H5FD_file_image_callbacks_t fi_callbacks; /* file image callbacks */ /* Information from file open flags, for SWMR access */ hbool_t swmr_read; /* Whether the file is open for SWMR read access */ @@ -92,8 +116,7 @@ typedef struct H5FD_core_fapl_t { /* Allocate memory in multiples of this size by default */ #define H5FD_CORE_INCREMENT 8192 -/* - * These macros check for overflow of various quantities. These macros +/* These macros check for overflow of various quantities. These macros * assume that file_offset_t is signed and haddr_t and size_t are unsigned. * * ADDR_OVERFLOW: Checks whether a file address of type `haddr_t' @@ -203,8 +226,6 @@ H5FD_core_init_interface(void) * Programmer: Robb Matzke * Thursday, July 29, 1999 * - * Modifications: - * *------------------------------------------------------------------------- */ hid_t @@ -261,15 +282,6 @@ H5FD_core_term(void) * Programmer: Robb Matzke * Thursday, February 19, 1998 * - * Modifications: - * Robb Matzke, 1999-10-19 - * Added the BACKING_STORE argument. If set then the entire file - * contents are flushed to a file with the same name as this - * core file. - * - * Raymond Lu, 2001-10-25 - * Changed the file access list to the new generic list. - * *------------------------------------------------------------------------- */ herr_t @@ -308,14 +320,6 @@ done: * Programmer: Robb Matzke * Tuesday, August 10, 1999 * - * Modifications: - * Robb Matzke, 1999-10-19 - * Added the BACKING_STORE argument. - * - * Raymond Lu - * 2001-10-25 - * Changed file access list to the new generic property list. - * *------------------------------------------------------------------------- */ herr_t @@ -358,8 +362,6 @@ done: * Programmer: Robb Matzke * Friday, August 13, 1999 * - * Modifications: - * *------------------------------------------------------------------------- */ static void * @@ -399,16 +401,6 @@ done: * Programmer: Robb Matzke * Thursday, July 29, 1999 * - * Modifications: - * Robb Matzke, 1999-10-19 - * The backing store file is created and opened if specified. - * - * Raymond Lu, 2006-11-30 - * Enabled the driver to read an existing file depending on - * the setting of the backing_store and file open flags. - * - * Allen Byrne, 2008-1-23 - * changed if of fapl_id to assert *------------------------------------------------------------------------- */ static H5FD_t * @@ -420,11 +412,11 @@ H5FD_core_open(const char *name, unsigned flags, hid_t fapl_id, H5FD_core_fapl_t *fa=NULL; H5P_genplist_t *plist; /* Property list pointer */ #ifdef H5_HAVE_WIN32_API - HFILE filehandle; struct _BY_HANDLE_FILE_INFORMATION fileinfo; #endif h5_stat_t sb; int fd=-1; + H5FD_file_image_info_t file_image_info; H5FD_t *ret_value; FUNC_ENTER_NOAPI_NOINIT @@ -447,10 +439,32 @@ H5FD_core_open(const char *name, unsigned flags, hid_t fapl_id, if(H5F_ACC_CREAT & flags) o_flags |= O_CREAT; if(H5F_ACC_EXCL & flags) o_flags |= O_EXCL; + /* Retrieve initial file image info */ + if(H5P_get(plist, H5F_ACS_FILE_IMAGE_INFO_NAME, &file_image_info) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get initial file image info") + + /* If the file image exists and this is an open, make sure the file doesn't exist */ + HDassert(((file_image_info.buffer != NULL) && (file_image_info.size > 0)) || + ((file_image_info.buffer == NULL) && (file_image_info.size == 0))); + if((file_image_info.buffer != NULL) && !(H5F_ACC_CREAT & flags)) { + if(HDopen(name, o_flags, 0666) >= 0) + HGOTO_ERROR(H5E_FILE, H5E_FILEEXISTS, NULL, "file already exists") + + /* If backing store is requested, create and stat the file + * Note: We are forcing the O_CREAT flag here, even though this is + * technically an open. + */ + if(fa->backing_store) { + if((fd = HDopen(name, o_flags | O_CREAT, 0666)) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to create file") + if(HDfstat(fd, &sb) < 0) + HSYS_GOTO_ERROR(H5E_FILE, H5E_BADFILE, NULL, "unable to fstat file") + } /* end if */ + } /* end if */ /* Open backing store, and get stat() from file. The only case that backing * store is off is when the backing_store flag is off and H5F_ACC_CREAT is * on. */ - if(fa->backing_store || !(H5F_ACC_CREAT & flags)) { + else if(fa->backing_store || !(H5F_ACC_CREAT & flags)) { if(fa && (fd = HDopen(name, o_flags, 0666)) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file") if(HDfstat(fd, &sb) < 0) @@ -464,8 +478,7 @@ H5FD_core_open(const char *name, unsigned flags, hid_t fapl_id, if(name && *name) file->name = H5MM_xstrdup(name); - /* - * The increment comes from either the file access property list or the + /* The increment comes from either the file access property list or the * default value. But if the file access property list was zero then use * the default value instead. */ @@ -474,13 +487,22 @@ H5FD_core_open(const char *name, unsigned flags, hid_t fapl_id, /* If save data in backing store. */ file->backing_store = fa->backing_store; + /* Save file image callbacks */ + file->fi_callbacks = file_image_info.callbacks; + if(fd >= 0) { /* Retrieve information for determining uniqueness of file */ #ifdef H5_HAVE_WIN32_API - filehandle = _get_osfhandle(fd); - (void)GetFileInformationByHandle((HANDLE)filehandle, &fileinfo); - file->fileindexhi = fileinfo.nFileIndexHigh; - file->fileindexlo = fileinfo.nFileIndexLow; + file->hFile = (HANDLE)_get_osfhandle(fd); + if(INVALID_HANDLE_VALUE == file->hFile) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to get Windows file handle") + + if(!GetFileInformationByHandle((HANDLE)file->hFile, &fileinfo)) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to get Windows file information") + + file->nFileIndexHigh = fileinfo.nFileIndexHigh; + file->nFileIndexLow = fileinfo.nFileIndexLow; + file->dwVolumeSerialNumber = fileinfo.dwVolumeSerialNumber; #else /* H5_HAVE_WIN32_API */ file->device = sb.st_dev; #ifdef H5_VMS @@ -499,20 +521,70 @@ H5FD_core_open(const char *name, unsigned flags, hid_t fapl_id, size_t size; /* Retrieve file size */ - size = (size_t)sb.st_size; + if(file_image_info.buffer && file_image_info.size > 0) + size = file_image_info.size; + else + size = (size_t)sb.st_size; /* Check if we should allocate the memory buffer and read in existing data */ if(size) { - /* Allocate memory for the file's data */ - if(NULL == (file->mem = (unsigned char*)H5MM_malloc(size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate memory block") + /* Allocate memory for the file's data, using the file image callback if available. */ + if(file->fi_callbacks.image_malloc) { + if(NULL == (file->mem = (unsigned char*)file->fi_callbacks.image_malloc(size, H5FD_FILE_IMAGE_OP_FILE_OPEN, file->fi_callbacks.udata))) + HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, "image malloc callback failed") + } /* end if */ + else { + if(NULL == (file->mem = (unsigned char*)H5MM_malloc(size))) + HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, "unable to allocate memory block") + } /* end else */ /* Set up data structures */ file->eof = size; - /* Read in existing data */ - if(HDread(file->fd, file->mem, size) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to read file") + /* If there is an initial file image, copy it, using the callback if possible */ + if(file_image_info.buffer && file_image_info.size > 0) { + if(file->fi_callbacks.image_memcpy) { + if(file->mem != file->fi_callbacks.image_memcpy(file->mem, file_image_info.buffer, size, H5FD_FILE_IMAGE_OP_FILE_OPEN, file->fi_callbacks.udata)) + HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, NULL, "image_memcpy callback failed") + } /* end if */ + else + HDmemcpy(file->mem, file_image_info.buffer, size); + } /* end if */ + /* Read in existing data from the file if there is no image */ + else { + /* Read in existing data, being careful of interrupted system calls, + * partial results, and the end of the file. + */ + while(size > 0) { + h5_core_io_t bytes_in = 0; /* # of bytes to read */ + h5_core_io_ret_t bytes_read = -1; /* # of bytes actually read */ + + /* Trying to read more bytes than the return type can handle is + * undefined behavior in POSIX. + */ + if(size > H5_CORE_MAX_IO_BYTES_g) + bytes_in = H5_CORE_MAX_IO_BYTES_g; + else + bytes_in = (h5_core_io_t)size; + + do { + bytes_read = HDread(file->fd, file->mem, bytes_in); + } while(-1 == bytes_read && EINTR == errno); + + if(-1 == bytes_read) { /* error */ + int myerrno = errno; + time_t mytime = HDtime(NULL); + HDoff_t myoffset = HDlseek(file->fd, (HDoff_t)0, SEEK_CUR); + + HGOTO_ERROR(H5E_IO, H5E_READERROR, NULL, "file read failed: time = %s, filename = '%s', file descriptor = %d, errno = %d, error message = '%s', file->mem = %p, size = %lu, offset = %llu", HDctime(&mytime), file->name, file->fd, myerrno, HDstrerror(myerrno), file->mem, (unsigned long)size, (unsigned long long)myoffset); + } /* end if */ + + HDassert(bytes_read >= 0); + HDassert((size_t)bytes_read <= size); + + size -= (size_t)bytes_read; + } /* end while */ + } /* end else */ } /* end if */ } /* end if */ @@ -559,8 +631,15 @@ H5FD_core_close(H5FD_t *_file) HDclose(file->fd); if(file->name) H5MM_xfree(file->name); - if(file->mem) - H5MM_xfree(file->mem); + if(file->mem) { + /* Use image callback if available */ + if(file->fi_callbacks.image_free) { + if(file->fi_callbacks.image_free(file->mem, H5FD_FILE_IMAGE_OP_FILE_CLOSE, file->fi_callbacks.udata) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "image_free callback failed") + } /* end if */ + else + H5MM_xfree(file->mem); + } /* end if */ HDmemset(file, 0, sizeof(H5FD_core_t)); H5MM_xfree(file); @@ -585,13 +664,6 @@ done: * Programmer: Robb Matzke * Thursday, July 29, 1999 * - * Modifications: - * Neil Fortner - * Tuesday, March 9, 2010 - * Modified function to compare low level file information if - * a backing store is opened for both files, similar to the - * sec2 file driver. - * *------------------------------------------------------------------------- */ static int @@ -606,11 +678,14 @@ H5FD_core_cmp(const H5FD_t *_f1, const H5FD_t *_f2) if(f1->fd >= 0 && f2->fd >= 0) { /* Compare low level file information for backing store */ #ifdef H5_HAVE_WIN32_API - if (f1->fileindexhi < f2->fileindexhi) HGOTO_DONE(-1) - if (f1->fileindexhi > f2->fileindexhi) HGOTO_DONE(1) + if(f1->dwVolumeSerialNumber < f2->dwVolumeSerialNumber) HGOTO_DONE(-1) + if(f1->dwVolumeSerialNumber > f2->dwVolumeSerialNumber) HGOTO_DONE(1) - if (f1->fileindexlo < f2->fileindexlo) HGOTO_DONE(-1) - if (f1->fileindexlo > f2->fileindexlo) HGOTO_DONE(1) + if(f1->nFileIndexHigh < f2->nFileIndexHigh) HGOTO_DONE(-1) + if(f1->nFileIndexHigh > f2->nFileIndexHigh) HGOTO_DONE(1) + + if(f1->nFileIndexLow < f2->nFileIndexLow) HGOTO_DONE(-1) + if(f1->nFileIndexLow > f2->nFileIndexLow) HGOTO_DONE(1) #else #ifdef H5_DEV_T_IS_SCALAR @@ -685,9 +760,11 @@ H5FD_core_query(const H5FD_t * _file, unsigned long *flags /* out */) *flags |= H5FD_FEAT_ACCUMULATE_METADATA; /* OK to accumulate metadata for faster writes */ *flags |= H5FD_FEAT_DATA_SIEVE; /* OK to perform data sieving for faster raw data reads & writes */ *flags |= H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */ + *flags |= H5FD_FEAT_ALLOW_FILE_IMAGE; /* OK to use file image feature with this VFD */ + *flags |= H5FD_FEAT_CAN_USE_FILE_IMAGE_CALLBACKS; /* OK to use file image callbacks with this VFD */ /* If the backing store is open, a POSIX file handle is available */ - if(file->fd >= 0 && file->backing_store) + if(file && file->fd >= 0 && file->backing_store) *flags |= H5FD_FEAT_POSIX_COMPAT_HANDLE; /* VFD handle is POSIX I/O call compatible */ } /* end if */ @@ -709,11 +786,6 @@ H5FD_core_query(const H5FD_t * _file, unsigned long *flags /* out */) * Programmer: Robb Matzke * Monday, August 2, 1999 * - * Modifications: - * Raymond Lu - * 21 Dec. 2006 - * Added the parameter TYPE. It's only used for MULTI driver. - * *------------------------------------------------------------------------- */ static haddr_t @@ -741,11 +813,6 @@ H5FD_core_get_eoa(const H5FD_t *_file, H5FD_mem_t UNUSED type) * Programmer: Robb Matzke * Thursday, July 29, 1999 * - * Modifications: - * Raymond Lu - * 21 Dec. 2006 - * Added the parameter TYPE. It's only used for MULTI driver. - * *------------------------------------------------------------------------- */ static herr_t @@ -782,8 +849,6 @@ done: * Programmer: Robb Matzke * Thursday, July 29, 1999 * - * Modifications: - * *------------------------------------------------------------------------- */ static haddr_t @@ -807,8 +872,6 @@ H5FD_core_get_eof(const H5FD_t *_file) * Programmer: Raymond Lu * Sept. 16, 2002 * - * Modifications: - * *------------------------------------------------------------------------- */ static herr_t @@ -874,8 +937,6 @@ done: * Programmer: Robb Matzke * Thursday, July 29, 1999 * - * Modifications: - * *------------------------------------------------------------------------- */ /* ARGSUSED */ @@ -888,8 +949,8 @@ H5FD_core_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, hadd FUNC_ENTER_NOAPI_NOINIT - assert(file && file->pub.cls); - assert(buf); + HDassert(file && file->pub.cls); + HDassert(buf); /* Check for overflow conditions */ if (HADDR_UNDEF == addr) @@ -947,8 +1008,6 @@ done: * Programmer: Robb Matzke * Thursday, July 29, 1999 * - * Modifications: - * *------------------------------------------------------------------------- */ /* ARGSUSED */ @@ -985,9 +1044,16 @@ H5FD_core_write(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, had if((addr + size) % file->increment) new_eof += file->increment; - /* (Re)allocate memory for the file buffer */ - if(NULL == (x = (unsigned char *)H5MM_realloc(file->mem, new_eof))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory block of %llu bytes", (unsigned long long)new_eof) + /* (Re)allocate memory for the file buffer, using callbacks if available */ + if(file->fi_callbacks.image_realloc) { + if(NULL == (x = (unsigned char *)file->fi_callbacks.image_realloc(file->mem, new_eof, H5FD_FILE_IMAGE_OP_FILE_RESIZE, file->fi_callbacks.udata))) + HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "unable to allocate memory block of %llu bytes with callback", (unsigned long long)new_eof) + } /* end if */ + else { + if(NULL == (x = (unsigned char *)H5MM_realloc(file->mem, new_eof))) + HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "unable to allocate memory block of %llu bytes", (unsigned long long)new_eof) + } /* end else */ + #ifdef H5_CLEAR_MEMORY HDmemset(x + file->eof, 0, (size_t)(new_eof - file->eof)); #endif /* H5_CLEAR_MEMORY */ @@ -998,6 +1064,8 @@ HDmemset(x + file->eof, 0, (size_t)(new_eof - file->eof)); /* Write from BUF to memory */ HDmemcpy(file->mem + addr, buf, size); + + /* Mark memory buffer as modified */ file->dirty = TRUE; done: @@ -1018,10 +1086,6 @@ done: * Programmer: Robb Matzke * Friday, October 15, 1999 * - * Modifications: - * Raymond Lu, 2006-11-30 - * Added a condition check for backing store flag, for an - * existing file can be opened for read and write now. *------------------------------------------------------------------------- */ /* ARGSUSED */ @@ -1040,19 +1104,40 @@ H5FD_core_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing) if (0!=HDlseek(file->fd, (off_t)0, SEEK_SET)) HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "error seeking in backing store") + + while (size > 0) { - while (size) { - ssize_t n; - - H5_CHECK_OVERFLOW(size,hsize_t,size_t); - n = HDwrite(file->fd, ptr, (size_t)size); - if (n<0 && EINTR==errno) - continue; - if (n<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "error writing backing store") - ptr += (size_t)n; - size -= (size_t)n; - } + h5_core_io_t bytes_in = 0; /* # of bytes to write */ + h5_core_io_ret_t bytes_wrote = -1; /* # of bytes written */ + + /* Trying to write more bytes than the return type can handle is + * undefined behavior in POSIX. + */ + if(size > H5_CORE_MAX_IO_BYTES_g) + bytes_in = H5_CORE_MAX_IO_BYTES_g; + else + bytes_in = (h5_core_io_t)size; + + do { + bytes_wrote = HDwrite(file->fd, ptr, bytes_in); + } while(-1 == bytes_wrote && EINTR == errno); + + if(-1 == bytes_wrote) { /* error */ + int myerrno = errno; + time_t mytime = HDtime(NULL); + HDoff_t myoffset = HDlseek(file->fd, (HDoff_t)0, SEEK_CUR); + + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "write to backing store failed: time = %s, filename = '%s', file descriptor = %d, errno = %d, error message = '%s', ptr = %p, size = %lu, offset = %llu", HDctime(&mytime), file->name, file->fd, myerrno, HDstrerror(myerrno), ptr, (unsigned long)size, (unsigned long long)myoffset); + } /* end if */ + + HDassert(bytes_wrote > 0); + HDassert((size_t)bytes_wrote <= size); + + size -= (size_t)bytes_wrote; + ptr = (unsigned char *)ptr + bytes_wrote; + + } /* end while */ + file->dirty = FALSE; } @@ -1067,6 +1152,28 @@ done: * Purpose: Makes sure that the true file size is the same (or larger) * than the end-of-address. * + * Addendum -- 12/2/11 + * For file images opened with the core file driver, it is + * necessary that we avoid reallocating the core file driver's + * buffer uneccessarily. + * + * To this end, I have made the following functional changes + * to this function. + * + * If we are closing, and there is no backing store, this + * function becomes a no-op. + * + * If we are closing, and there is backing store, we set the + * eof to equal the eoa, and truncate the backing store to + * the new eof + * + * If we are not closing, we realloc the buffer to size equal + * to the smallest multiple of the allocation increment that + * equals or exceeds the eoa and set the eof accordingly. + * Note that we no longer truncate the backing store to the + * new eof if applicable. + * -- JRM + * * Return: Success: Non-negative * Failure: Negative * @@ -1077,7 +1184,7 @@ done: */ /* ARGSUSED */ static herr_t -H5FD_core_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t UNUSED closing) +H5FD_core_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t closing) { H5FD_core_t *file = (H5FD_core_t*)_file; size_t new_eof; /* New size of memory buffer */ @@ -1087,40 +1194,81 @@ H5FD_core_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t UNUSED closing) HDassert(file); - /* Determine new size of memory buffer */ - H5_ASSIGN_OVERFLOW(new_eof, file->increment * (file->eoa / file->increment), hsize_t, size_t); - if(file->eoa % file->increment) - new_eof += file->increment; + /* if we are closing and not using backing store, do nothing */ + if(!closing || file->backing_store) { + if(closing) /* set eof to eoa */ + new_eof = file->eoa; + else { /* set eof to smallest multiple of increment that exceeds eoa */ + /* Determine new size of memory buffer */ + H5_ASSIGN_OVERFLOW(new_eof, file->increment * (file->eoa / file->increment), hsize_t, size_t); + if(file->eoa % file->increment) + new_eof += file->increment; + } /* end else */ + + /* Extend the file to make sure it's large enough */ + if(!H5F_addr_eq(file->eof, (haddr_t)new_eof)) { + unsigned char *x; /* Pointer to new buffer for file data */ + + /* (Re)allocate memory for the file buffer, using callback if available */ + if(file->fi_callbacks.image_realloc) { + if(NULL == (x = (unsigned char *)file->fi_callbacks.image_realloc(file->mem, new_eof, H5FD_FILE_IMAGE_OP_FILE_RESIZE, file->fi_callbacks.udata))) + HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "unable to allocate memory block with callback") + } /* end if */ + else { + if(NULL == (x = (unsigned char *)H5MM_realloc(file->mem, new_eof))) + HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "unable to allocate memory block") + } /* end else */ - /* Extend the file to make sure it's large enough */ - if(!H5F_addr_eq(file->eof, (haddr_t)new_eof)) { - unsigned char *x; /* Pointer to new buffer for file data */ - - /* (Re)allocate memory for the file buffer */ - if(NULL == (x = (unsigned char *)H5MM_realloc(file->mem, new_eof))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory block") #ifdef H5_CLEAR_MEMORY -if(file->eof < new_eof) - HDmemset(x + file->eof, 0, (size_t)(new_eof - file->eof)); + if(file->eof < new_eof) + HDmemset(x + file->eof, 0, (size_t)(new_eof - file->eof)); #endif /* H5_CLEAR_MEMORY */ - file->mem = x; + file->mem = x; - /* Update backing store, if using it */ - if(file->fd >= 0 && file->backing_store) { + /* Update backing store, if using it and if closing */ + if(closing && (file->fd >= 0) && file->backing_store) { +#ifdef H5_HAVE_WIN32_API + LARGE_INTEGER li; /* 64-bit (union) integer for SetFilePointer() call */ + DWORD dwPtrLow; /* Low-order pointer bits from SetFilePointer() + * Only used as an error code here. + */ + DWORD dwError; /* DWORD error code from GetLastError() */ + BOOL bError; /* Boolean error flag */ + + /* Windows uses this odd QuadPart union for 32/64-bit portability */ + li.QuadPart = (__int64)file->eoa; + + /* Extend the file to make sure it's large enough. + * + * Since INVALID_SET_FILE_POINTER can technically be a valid return value + * from SetFilePointer(), we also need to check GetLastError(). + */ + dwPtrLow = SetFilePointer(file->hFile, li.LowPart, &li.HighPart, FILE_BEGIN); + if(INVALID_SET_FILE_POINTER == dwPtrLow) { + dwError = GetLastError(); + if(dwError != NO_ERROR ) + HGOTO_ERROR(H5E_FILE, H5E_FILEOPEN, FAIL, "unable to set file pointer") + } + + bError = SetEndOfFile(file->hFile); + if(0 == bError) + HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly") +#else /* H5_HAVE_WIN32_API */ #ifdef H5_VMS - /* Reset seek offset to the beginning of the file, so that the file isn't - * re-extended later. This may happen on Open VMS. */ - if(-1 == HDlseek(file->fd, 0, SEEK_SET)) - HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position") -#endif + /* Reset seek offset to the beginning of the file, so that the file isn't + * re-extended later. This may happen on Open VMS. */ + if(-1 == HDlseek(file->fd, (HDoff_t)0, SEEK_SET)) + HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position") +#endif /* H5_VMS */ + if(-1 == HDftruncate(file->fd, (HDoff_t)new_eof)) + HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly") +#endif /* H5_HAVE_WIN32_API */ + } /* end if */ - if(-1 == HDftruncate(file->fd, (off_t)new_eof)) - HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly") + /* Update the eof value */ + file->eof = new_eof; } /* end if */ - - /* Update the eof value */ - file->eof = new_eof; - } /* end if */ + } /* end if(file->eof < file->eoa) */ done: FUNC_LEAVE_NOAPI(ret_value) diff --git a/src/H5FDfamily.c b/src/H5FDfamily.c index 17683ce..6f6d757 100644 --- a/src/H5FDfamily.c +++ b/src/H5FDfamily.c @@ -995,7 +995,7 @@ H5FD_family_query(const H5FD_t * _file, unsigned long *flags /* out */) *flags |= H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */ /* Check for flags that are set by h5repart */ - if(file->repart_members) + if(file && file->repart_members) *flags |= H5FD_FEAT_DIRTY_SBLK_LOAD; /* Mark the superblock dirty when it is loaded (so the family member sizes are rewritten) */ } /* end if */ diff --git a/src/H5FDlog.c b/src/H5FDlog.c index bfd0b07..2026153 100644 --- a/src/H5FDlog.c +++ b/src/H5FDlog.c @@ -928,7 +928,7 @@ H5FD_log_query(const H5FD_t *_file, unsigned long *flags /* out */) *flags |= H5FD_FEAT_POSIX_COMPAT_HANDLE; /* VFD handle is POSIX I/O call compatible */ /* Check for flags that are set by h5repart */ - if(file->fam_to_sec2) + if(file && file->fam_to_sec2) *flags |= H5FD_FEAT_IGNORE_DRVRINFO; /* Ignore the driver info when file is opened (which eliminates it) */ } /* end if */ diff --git a/src/H5FDmpio.c b/src/H5FDmpio.c index d780ceb..6dbe831 100644 --- a/src/H5FDmpio.c +++ b/src/H5FDmpio.c @@ -876,6 +876,100 @@ fprintf(stderr, "leaving H5FD_mpio_fapl_free\n"); /*------------------------------------------------------------------------- + * Function: H5FD_set_mpio_atomicity + * + * Purpose: Sets the atomicity mode + * + * Return: Success: Non-negative + * + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * Feb 14, 2012 + * + *------------------------------------------------------------------------- + */ +herr_t +H5FD_set_mpio_atomicity(H5FD_t *_file, hbool_t flag) +{ + H5FD_mpio_t *file = (H5FD_mpio_t*)_file; + int mpi_code; /* MPI return code */ + int temp_flag; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#ifdef H5FDmpio_DEBUG + if (H5FD_mpio_Debug[(int)'t']) + fprintf(stdout, "Entering H5FD_set_mpio_atomicity\n"); +#endif + + if (FALSE == flag) + temp_flag = 0; + else + temp_flag = 1; + + /* set atomicity value */ + if (MPI_SUCCESS != (mpi_code=MPI_File_set_atomicity(file->f, temp_flag))) + HMPI_GOTO_ERROR(FAIL, "MPI_File_set_atomicity", mpi_code) + +done: +#ifdef H5FDmpio_DEBUG + if (H5FD_mpio_Debug[(int)'t']) + fprintf(stdout, "Leaving H5FD_set_mpio_atomicity\n"); +#endif + FUNC_LEAVE_NOAPI(ret_value) +} + + +/*------------------------------------------------------------------------- + * Function: H5FD_get_mpio_atomicity + * + * Purpose: Returns the atomicity mode + * + * Return: Success: Non-negative + * + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * Feb 14, 2012 + * + *------------------------------------------------------------------------- + */ +herr_t +H5FD_get_mpio_atomicity(H5FD_t *_file, hbool_t *flag) +{ + H5FD_mpio_t *file = (H5FD_mpio_t*)_file; + int mpi_code; /* MPI return code */ + int temp_flag; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#ifdef H5FDmpio_DEBUG + if (H5FD_mpio_Debug[(int)'t']) + fprintf(stdout, "Entering H5FD_get_mpio_atomicity\n"); +#endif + + /* get atomicity value */ + if (MPI_SUCCESS != (mpi_code=MPI_File_get_atomicity(file->f, &temp_flag))) + HMPI_GOTO_ERROR(FAIL, "MPI_File_get_atomicity", mpi_code) + + if (0 != temp_flag) + *flag = TRUE; + else + *flag = FALSE; + +done: +#ifdef H5FDmpio_DEBUG + if (H5FD_mpio_Debug[(int)'t']) + fprintf(stdout, "Leaving H5FD_get_mpio_atomicity\n"); +#endif + FUNC_LEAVE_NOAPI(ret_value) +} + + +/*------------------------------------------------------------------------- * Function: H5FD_mpio_open * * Purpose: Opens a file with name NAME. The FLAGS are a bit field with diff --git a/src/H5FDprivate.h b/src/H5FDprivate.h index fe770d2..9c19562 100644 --- a/src/H5FDprivate.h +++ b/src/H5FDprivate.h @@ -52,6 +52,29 @@ typedef enum { } H5FD_file_op_t; +/* Define structure to hold initial file image and other relevant information */ +typedef struct { + void *buffer; + size_t size; + H5FD_file_image_callbacks_t callbacks; +} H5FD_file_image_info_t; + +/* Define default file image info */ +#define H5FD_DEFAULT_FILE_IMAGE_INFO { \ + /* file image buffer */ NULL, \ + /* buffer size */ 0, \ + { /* Callbacks */ \ + /* image_malloc */ NULL, \ + /* image_memcpy */ NULL, \ + /* image_realloc */ NULL, \ + /* image_free */ NULL, \ + /* udata_copy */ NULL, \ + /* udata_free */ NULL, \ + /* udata */ NULL, \ + } \ +} + + /*****************************/ /* Library Private Variables */ /*****************************/ @@ -72,17 +95,14 @@ H5_DLL herr_t H5FD_sb_encode(H5FD_t *file, char *name/*out*/, uint8_t *buf); H5_DLL herr_t H5FD_sb_decode(H5FD_t *file, const char *name, const uint8_t *buf); H5_DLL void *H5FD_fapl_get(H5FD_t *file); H5_DLL herr_t H5FD_fapl_open(struct H5P_genplist_t *plist, hid_t driver_id, const void *driver_info); -H5_DLL herr_t H5FD_fapl_copy(hid_t driver_id, const void *fapl, void **copied_fapl); H5_DLL herr_t H5FD_fapl_close(hid_t driver_id, void *fapl); H5_DLL herr_t H5FD_dxpl_open(struct H5P_genplist_t *plist, hid_t driver_id, const void *driver_info); -H5_DLL herr_t H5FD_dxpl_copy(hid_t driver_id, const void *dxpl, void **copied_dxpl); H5_DLL herr_t H5FD_dxpl_close(hid_t driver_id, void *dxpl); H5_DLL hid_t H5FD_register(const void *cls, size_t size, hbool_t app_ref); H5_DLL H5FD_t *H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr); H5_DLL herr_t H5FD_close(H5FD_t *file); H5_DLL int H5FD_cmp(const H5FD_t *f1, const H5FD_t *f2); -H5_DLL int H5FD_query(const H5FD_t *f, unsigned long *flags/*out*/); H5_DLL haddr_t H5FD_alloc(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type, struct H5F_t *f, hsize_t size, haddr_t *align_addr, hsize_t *align_size); H5_DLL herr_t H5FD_free(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type, struct H5F_t *f, @@ -105,6 +125,10 @@ 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); H5_DLL haddr_t H5FD_get_base_addr(const H5FD_t *file); +#ifdef H5_HAVE_PARALLEL +H5_DLL herr_t H5FD_set_mpio_atomicity(H5FD_t *file, hbool_t flag); +H5_DLL herr_t H5FD_get_mpio_atomicity(H5FD_t *file, hbool_t *flag); +#endif /* H5_HAVE_PARALLEL */ #endif /* !_H5FDprivate_H */ diff --git a/src/H5FDpublic.h b/src/H5FDpublic.h index f495e2d..ab19c68 100644 --- a/src/H5FDpublic.h +++ b/src/H5FDpublic.h @@ -222,6 +222,19 @@ typedef enum H5F_mem_t H5FD_mem_t; * instead of the default H5D_ALLOC_TIME_LATE */ #define H5FD_FEAT_ALLOCATE_EARLY 0x00000200 + /* + * Defining the H5FD_FEAT_ALLOW_FILE_IMAGE for a VFL driver means that + * the driver is able to use a file image in the fapl as the initial + * contents of a file. + */ +#define H5FD_FEAT_ALLOW_FILE_IMAGE 0x00000400 + /* + * Defining the H5FD_FEAT_CAN_USE_FILE_IMAGE_CALLBACKS for a VFL driver + * means that the driver is able to use callbacks to make a copy of the + * image to store in memory. + */ +#define H5FD_FEAT_CAN_USE_FILE_IMAGE_CALLBACKS 0x00000800 + /* Forward declaration */ typedef struct H5FD_t H5FD_t; @@ -291,6 +304,33 @@ struct H5FD_t { hsize_t alignment; /* Allocation alignment */ }; +/* Define enum for the source of file image callbacks */ +typedef enum { + H5FD_FILE_IMAGE_OP_NO_OP, + H5FD_FILE_IMAGE_OP_PROPERTY_LIST_SET, + H5FD_FILE_IMAGE_OP_PROPERTY_LIST_COPY, + H5FD_FILE_IMAGE_OP_PROPERTY_LIST_GET, + H5FD_FILE_IMAGE_OP_PROPERTY_LIST_CLOSE, + H5FD_FILE_IMAGE_OP_FILE_OPEN, + H5FD_FILE_IMAGE_OP_FILE_RESIZE, + H5FD_FILE_IMAGE_OP_FILE_CLOSE, +} H5FD_file_image_op_t; + +/* Define structure to hold file image callbacks */ +typedef struct { + void *(*image_malloc)(size_t size, H5FD_file_image_op_t file_image_op, + void *udata); + void *(*image_memcpy)(void *dest, const void *src, size_t size, + H5FD_file_image_op_t file_image_op, void *udata); + void *(*image_realloc)(void *ptr, size_t size, + H5FD_file_image_op_t file_image_op, void *udata); + herr_t (*image_free)(void *ptr, H5FD_file_image_op_t file_image_op, + void *udata); + void *(*udata_copy)(void *udata); + herr_t (*udata_free)(void *udata); + void *udata; +} H5FD_file_image_callbacks_t; + #ifdef __cplusplus extern "C" { #endif diff --git a/src/H5FDsec2.c b/src/H5FDsec2.c index d1e62f9..a0a7c50 100644 --- a/src/H5FDsec2.c +++ b/src/H5FDsec2.c @@ -570,7 +570,7 @@ H5FD_sec2_query(const H5FD_t *_file, unsigned long *flags /* out */) *flags |= H5FD_FEAT_POSIX_COMPAT_HANDLE; /* VFD handle is POSIX I/O call compatible */ /* Check for flags that are set by h5repart */ - if(file->fam_to_sec2) + if(file && file->fam_to_sec2) *flags |= H5FD_FEAT_IGNORE_DRVRINFO; /* Ignore the driver info when file is opened (which eliminates it) */ } /* end if */ diff --git a/src/H5FDstdio.c b/src/H5FDstdio.c index 5c40d15..50a1593 100644 --- a/src/H5FDstdio.c +++ b/src/H5FDstdio.c @@ -13,37 +13,33 @@ * access to either file, you may request a copy from help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* - * Programmer: Robb Matzke - * Wednesday, October 22, 1997 - * - * Purpose: This is the Posix stdio.h I/O subclass of H5Flow. - * It also serves as an example of coding a simple file driver, - * therefore, it should not use any non-public definitions. +/* Programmer: Robb Matzke + * Wednesday, October 22, 1997 * - * Notes: Ported to the new H5FD architecture on 10/18/99 - QAK + * Purpose: The C STDIO virtual file driver which only uses calls from stdio.h. + * This also serves as an example of coding a simple file driver, + * therefore, it should not use any non-public definitions. * + * NOTE: This driver is not as well tested as the standard SEC2 driver + * and is not intended for production use! */ #include +#include #include #include #include -/* Disable certain warnings in PC-Lint: */ -/*lint --emacro( {534, 830}, H5P_FILE_ACCESS) */ -/*lint --emacro( {534, 830}, H5F_ACC_RDWR, H5F_ACC_EXCL) */ -/*lint -esym( 534, H5Eclear2, H5Epush2) */ - #include "hdf5.h" -#ifdef H5_HAVE_STDIO_H -#include -#endif #ifdef H5_HAVE_UNISTD_H #include #endif #ifdef H5_HAVE_WIN32_API +/* The following two defines must be before any windows headers are included */ +#define WIN32_LEAN_AND_MEAN /* Exclude rarely-used stuff from Windows headers */ +#define NOGDI /* Exclude Graphic Display Interface macros */ + #include #include @@ -54,7 +50,6 @@ #endif - #ifdef MAX #undef MAX #endif /* MAX */ @@ -63,6 +58,9 @@ /* The driver identification number, initialized at runtime */ static hid_t H5FD_STDIO_g = 0; +/* The maximum number of bytes which can be written in a single I/O operation */ +static size_t H5_STDIO_MAX_IO_BYTES_g = (size_t)-1; + /* File operations */ typedef enum { H5FD_STDIO_OP_UNKNOWN=0, @@ -71,46 +69,60 @@ typedef enum { H5FD_STDIO_OP_SEEK=3 } H5FD_stdio_file_op; -/* - * The description of a file belonging to this driver. The `eoa' and `eof' +/* The description of a file belonging to this driver. The 'eoa' and 'eof' * determine the amount of hdf5 address space in use and the high-water mark - * of the file (the current size of the underlying Unix file). The `pos' + * of the file (the current size of the underlying Unix file). The 'pos' * value is used to eliminate file position updates when they would be a * no-op. Unfortunately we've found systems that use separate file position * indicators for reading and writing so the lseek can only be eliminated if * the current operation is the same as the previous operation. When opening - * a file the `eof' will be set to the current file size, `eoa' will be set - * to zero, `pos' will be set to H5F_ADDR_UNDEF (as it is when an error - * occurs), and `op' will be set to H5F_OP_UNKNOWN. + * a file the 'eof' will be set to the current file size, 'eoa' will be set + * to zero, 'pos' will be set to H5F_ADDR_UNDEF (as it is when an error + * occurs), and 'op' will be set to H5F_OP_UNKNOWN. */ typedef struct H5FD_stdio_t { - H5FD_t pub; /*public stuff, must be first */ - FILE * fp; /*the file handle */ - haddr_t eoa; /*end of allocated region */ - haddr_t eof; /*end of file; current file size*/ - haddr_t pos; /*current file I/O position */ - H5FD_stdio_file_op op; /*last operation */ - unsigned write_access; /* Flag to indicate the file was opened with write access */ + H5FD_t pub; /* public stuff, must be first */ + FILE *fp; /* the file handle */ + int fd; /* file descriptor (for truncate) */ + haddr_t eoa; /* end of allocated region */ + haddr_t eof; /* end of file; current file size */ + haddr_t pos; /* current file I/O position */ + unsigned write_access; /* Flag to indicate the file was opened with write access */ + H5FD_stdio_file_op op; /* last operation */ #ifndef H5_HAVE_WIN32_API - /* - * On most systems the combination of device and i-node number uniquely - * identify a file. + /* On most systems the combination of device and i-node number uniquely + * identify a file. Note that Cygwin, MinGW and other Windows POSIX + * environments have the stat function (which fakes inodes) + * and will use the 'device + inodes' scheme as opposed to the + * Windows code further below. */ - dev_t device; /*file device number */ - ino_t inode; /*file i-node number */ + dev_t device; /* file device number */ +#ifdef H5_VMS + ino_t inode[3]; /* file i-node number */ #else - /* - * On H5_HAVE_WIN32_API the low-order word of a unique identifier associated with the - * file and the volume serial number uniquely identify a file. This number - * (which, both? -rpm) may change when the system is restarted or when the - * file is opened. After a process opens a file, the identifier is - * constant until the file is closed. An application can use this - * identifier and the volume serial number to determine whether two - * handles refer to the same file. + ino_t inode; /* file i-node number */ +#endif /* H5_VMS */ +#else + /* Files in windows are uniquely identified by the volume serial + * number and the file index (both low and high parts). + * + * There are caveats where these numbers can change, especially + * on FAT file systems. On NTFS, however, a file should keep + * those numbers the same until renamed or deleted (though you + * can use ReplaceFile() on NTFS to keep the numbers the same + * while renaming). + * + * See the MSDN "BY_HANDLE_FILE_INFORMATION Structure" entry for + * more information. + * + * http://msdn.microsoft.com/en-us/library/aa363788(v=VS.85).aspx */ - DWORD fileindexlo; - DWORD fileindexhi; -#endif + DWORD nFileIndexLow; + DWORD nFileIndexHigh; + DWORD dwVolumeSerialNumber; + + HANDLE hFile; /* Native windows file handle */ +#endif /* H5_HAVE_WIN32_API */ /* Information from file open flags, for SWMR access */ hbool_t swmr_read; /* Whether the file is open for SWMR read access */ @@ -118,11 +130,13 @@ typedef struct H5FD_stdio_t { /* Use similar structure as in H5private.h by defining Windows stuff first. */ #ifdef H5_HAVE_WIN32_API - # define file_fseek _fseeki64 - # define file_offset_t __int64 - # define file_ftruncate _chsize_s /* Supported in VS 2005 or newer */ - # define file_ftell _ftelli64 -#endif +#ifndef H5_HAVE_MINGW + #define file_fseek _fseeki64 + #define file_offset_t __int64 + #define file_ftruncate _chsize_s /* Supported in VS 2005 or newer */ + #define file_ftell _ftelli64 +#endif /* H5_HAVE_MINGW */ +#endif /* H5_HAVE_WIN32_API */ /* Use file_xxx to indicate these are local macros, avoiding confusing * with the global HD_xxx macros. @@ -131,20 +145,19 @@ typedef struct H5FD_stdio_t { */ #ifndef file_fseek #ifdef H5_HAVE_FSEEKO64 - # define file_fseek fseeko64 - # define file_offset_t off64_t - # define file_ftruncate ftruncate64 - # define file_ftell ftello64 + #define file_fseek fseeko64 + #define file_offset_t off64_t + #define file_ftruncate ftruncate64 + #define file_ftell ftello64 #else - # define file_fseek fseeko - # define file_offset_t off_t - # define file_ftruncate ftruncate - # define file_ftell ftello - #endif -#endif - -/* - * These macros check for overflow of various quantities. These macros + #define file_fseek fseeko + #define file_offset_t off_t + #define file_ftruncate ftruncate + #define file_ftell ftello + #endif /* H5_HAVE_FSEEKO64 */ +#endif /* file_fseek */ + +/* These macros check for overflow of various quantities. These macros * assume that file_offset_t is signed and haddr_t and size_t are unsigned. * * ADDR_OVERFLOW: Checks whether a file address of type `haddr_t' @@ -185,38 +198,38 @@ static herr_t H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing); static herr_t H5FD_stdio_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing); static const H5FD_class_t H5FD_stdio_g = { - "stdio", /*name */ - MAXADDR, /*maxaddr */ - H5F_CLOSE_WEAK, /* fc_degree */ - H5FD_stdio_term, /*terminate */ - NULL, /*sb_size */ - NULL, /*sb_encode */ - NULL, /*sb_decode */ - 0, /*fapl_size */ - NULL, /*fapl_get */ - NULL, /*fapl_copy */ - NULL, /*fapl_free */ - 0, /*dxpl_size */ - NULL, /*dxpl_copy */ - NULL, /*dxpl_free */ - H5FD_stdio_open, /*open */ - H5FD_stdio_close, /*close */ - H5FD_stdio_cmp, /*cmp */ - H5FD_stdio_query, /*query */ - NULL, /*get_type_map */ - H5FD_stdio_alloc, /*alloc */ - NULL, /*free */ - H5FD_stdio_get_eoa, /*get_eoa */ - H5FD_stdio_set_eoa, /*set_eoa */ - H5FD_stdio_get_eof, /*get_eof */ - H5FD_stdio_get_handle, /*get_handle */ - H5FD_stdio_read, /*read */ - H5FD_stdio_write, /*write */ - H5FD_stdio_flush, /*flush */ - H5FD_stdio_truncate, /*truncate */ - NULL, /*lock */ - NULL, /*unlock */ - H5FD_FLMAP_SINGLE /*fl_map */ + "stdio", /* name */ + MAXADDR, /* maxaddr */ + H5F_CLOSE_WEAK, /* fc_degree */ + H5FD_stdio_term, /* terminate */ + NULL, /* sb_size */ + NULL, /* sb_encode */ + NULL, /* sb_decode */ + 0, /* fapl_size */ + NULL, /* fapl_get */ + NULL, /* fapl_copy */ + NULL, /* fapl_free */ + 0, /* dxpl_size */ + NULL, /* dxpl_copy */ + NULL, /* dxpl_free */ + H5FD_stdio_open, /* open */ + H5FD_stdio_close, /* close */ + H5FD_stdio_cmp, /* cmp */ + H5FD_stdio_query, /* query */ + NULL, /* get_type_map */ + H5FD_stdio_alloc, /* alloc */ + NULL, /* free */ + H5FD_stdio_get_eoa, /* get_eoa */ + H5FD_stdio_set_eoa, /* set_eoa */ + H5FD_stdio_get_eof, /* get_eof */ + H5FD_stdio_get_handle, /* get_handle */ + H5FD_stdio_read, /* read */ + H5FD_stdio_write, /* write */ + H5FD_stdio_flush, /* flush */ + H5FD_stdio_truncate, /* truncate */ + NULL, /* lock */ + NULL, /* unlock */ + H5FD_FLMAP_SINGLE /* fl_map */ }; @@ -233,9 +246,6 @@ static const H5FD_class_t H5FD_stdio_g = { * Programmer: Robb Matzke * Thursday, July 29, 1999 * - * Modifications: - * Stolen from the sec2 driver - QAK, 10/18/99 - * *------------------------------------------------------------------------- */ hid_t @@ -246,8 +256,8 @@ H5FD_stdio_init(void) if (H5I_VFL!=H5Iget_type(H5FD_STDIO_g)) H5FD_STDIO_g = H5FDregister(&H5FD_stdio_g); - return(H5FD_STDIO_g); -} + return H5FD_STDIO_g; +} /* end H5FD_stdio_init() */ /*--------------------------------------------------------------------------- @@ -266,7 +276,7 @@ static herr_t H5FD_stdio_term(void) { /* Reset VFL ID */ - H5FD_STDIO_g=0; + H5FD_STDIO_g = 0; return 0; } /* end H5FD_stdio_term() */ @@ -284,15 +294,12 @@ H5FD_stdio_term(void) * Programmer: Robb Matzke * Thursday, February 19, 1998 * - * Modifications: - * Stolen from the sec2 driver - QAK, 10/18/99 - * *------------------------------------------------------------------------- */ herr_t H5Pset_fapl_stdio(hid_t fapl_id) { - static const char *func="H5FDset_fapl_stdio"; /*for error reporting*/ + static const char *func = "H5FDset_fapl_stdio"; /*for error reporting*/ /*NO TRACE*/ @@ -303,7 +310,7 @@ H5Pset_fapl_stdio(hid_t fapl_id) H5Epush_ret(func, H5E_ERR_CLS, H5E_PLIST, H5E_BADTYPE, "not a file access property list", -1) return H5Pset_driver(fapl_id, H5FD_STDIO, NULL); -} +} /* end H5Pset_fapl_stdio() */ /*------------------------------------------------------------------------- @@ -311,50 +318,44 @@ H5Pset_fapl_stdio(hid_t fapl_id) * * Purpose: Create and/or opens a Standard C file as an HDF5 file. * - * Bugs: H5F_ACC_EXCL has a race condition. (? -QAK) - * * Errors: - * IO CANTOPENFILE File doesn't exist and CREAT wasn't - * specified. - * IO CANTOPENFILE Fopen failed. - * IO FILEEXISTS File exists but CREAT and EXCL were - * specified. + * IO CANTOPENFILE File doesn't exist and CREAT wasn't + * specified. + * IO CANTOPENFILE fopen() failed. + * IO FILEEXISTS File exists but CREAT and EXCL were + * specified. * - * Return: Success: A pointer to a new file data structure. The - * public fields will be initialized by the - * caller, which is always H5FD_open(). + * Return: + * Success: A pointer to a new file data structure. The + * public fields will be initialized by the + * caller, which is always H5FD_open(). * - * Failure: NULL + * Failure: NULL * * Programmer: Robb Matzke * Wednesday, October 22, 1997 * - * Modifications: - * Ported to VFL/H5FD layer - QAK, 10/18/99 - * *------------------------------------------------------------------------- */ static H5FD_t * H5FD_stdio_open( const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr) { - FILE *f = NULL; - unsigned write_access=0; /* File opened with write access? */ - H5FD_stdio_t *file=NULL; - static const char *func="H5FD_stdio_open"; /* Function Name for error reporting */ + FILE *f = NULL; + unsigned write_access = 0; /* File opened with write access? */ + H5FD_stdio_t *file = NULL; + static const char *func = "H5FD_stdio_open"; /* Function Name for error reporting */ #ifdef H5_HAVE_WIN32_API - HFILE filehandle; - struct _BY_HANDLE_FILE_INFORMATION fileinfo; - int fd; + struct _BY_HANDLE_FILE_INFORMATION fileinfo; #else /* H5_HAVE_WIN32_API */ - struct stat sb; + struct stat sb; #endif /* H5_HAVE_WIN32_API */ /* Sanity check on file offsets */ - assert(sizeof(file_offset_t)>=sizeof(size_t)); + assert(sizeof(file_offset_t) >= sizeof(size_t)); - /* Shut compiler up */ - fapl_id=fapl_id; + /* Quiet compiler */ + fapl_id = fapl_id; /* Clear the error stack */ H5Eclear2(H5E_DEFAULT); @@ -362,15 +363,16 @@ H5FD_stdio_open( const char *name, unsigned flags, hid_t fapl_id, /* Check arguments */ if (!name || !*name) H5Epush_ret(func, H5E_ERR_CLS, H5E_ARGS, H5E_BADVALUE, "invalid file name", NULL) - if (0==maxaddr || HADDR_UNDEF==maxaddr) + if (0 == maxaddr || HADDR_UNDEF == maxaddr) H5Epush_ret(func, H5E_ERR_CLS, H5E_ARGS, H5E_BADRANGE, "bogus maxaddr", NULL) if (ADDR_OVERFLOW(maxaddr)) H5Epush_ret(func, H5E_ERR_CLS, H5E_ARGS, H5E_OVERFLOW, "maxaddr too large", NULL) + /* Attempt to open/create the file */ if (access(name, F_OK) < 0) { if ((flags & H5F_ACC_CREAT) && (flags & H5F_ACC_RDWR)) { f = fopen(name, "wb+"); - write_access=1; /* Note the write access */ + write_access = 1; /* Note the write access */ } else H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_CANTOPENFILE, "file doesn't exist and CREAT wasn't specified", NULL) @@ -381,7 +383,7 @@ H5FD_stdio_open( const char *name, unsigned flags, hid_t fapl_id, f = fopen(name, "wb+"); else f = fopen(name, "rb+"); - write_access=1; /* Note the write access */ + write_access = 1; /* Note the write access */ } else { f = fopen(name, "rb"); } @@ -396,35 +398,50 @@ H5FD_stdio_open( const char *name, unsigned flags, hid_t fapl_id, file->fp = f; file->op = H5FD_STDIO_OP_SEEK; file->pos = HADDR_UNDEF; - file->write_access=write_access; /* Note the write_access for later */ + file->write_access = write_access; /* Note the write_access for later */ if(file_fseek(file->fp, (file_offset_t)0, SEEK_END) < 0) { file->op = H5FD_STDIO_OP_UNKNOWN; } else { - file_offset_t x = file_ftell (file->fp); - assert (x>=0); + file_offset_t x = file_ftell(file->fp); + assert (x >= 0); file->eof = (haddr_t)x; } - /* The unique key */ + /* Get the file descriptor (needed for truncate and some Windows information) */ + file->fd = fileno(file->fp); + if(file->fd < 0) + H5Epush_ret(func, H5E_ERR_CLS, H5E_FILE, H5E_CANTOPENFILE, "unable to get file descriptor", NULL); + + #ifdef H5_HAVE_WIN32_API -/*#error "Needs correct fileindexhi & fileindexlo, code below is from sec2 driver"*/ - fd = _fileno(f); - filehandle = _get_osfhandle(fd); - (void)GetFileInformationByHandle((HANDLE)filehandle, &fileinfo); - file->fileindexhi = fileinfo.nFileIndexHigh; - file->fileindexlo = fileinfo.nFileIndexLow; -#else - fstat(fileno(file->fp), &sb); + file->hFile = (HANDLE)_get_osfhandle(file->fd); + if(INVALID_HANDLE_VALUE == file->hFile) + H5Epush_ret(func, H5E_ERR_CLS, H5E_FILE, H5E_CANTOPENFILE, "unable to get Windows file handle", NULL); + + if(!GetFileInformationByHandle((HANDLE)file->hFile, &fileinfo)) + H5Epush_ret(func, H5E_ERR_CLS, H5E_FILE, H5E_CANTOPENFILE, "unable to get Windows file desinformationcriptor", NULL); + + file->nFileIndexHigh = fileinfo.nFileIndexHigh; + file->nFileIndexLow = fileinfo.nFileIndexLow; + file->dwVolumeSerialNumber = fileinfo.dwVolumeSerialNumber; +#else /* H5_HAVE_WIN32_API */ + fstat(file->fd, &sb); file->device = sb.st_dev; +#ifdef H5_VMS + file->inode[0] = sb.st_ino[0]; + file->inode[1] = sb.st_ino[1]; + file->inode[2] = sb.st_ino[2]; +#else /* H5_VMS */ file->inode = sb.st_ino; -#endif +#endif /* H5_VMS */ +#endif /* H5_HAVE_WIN32_API */ /* Check for SWMR reader access */ if(flags & H5F_ACC_SWMR_READ) file->swmr_read = 1; return((H5FD_t*)file); -} /* end H5FD_stdio_open() */ +} /* end H5FD_stdio_open() */ /*------------------------------------------------------------------------- @@ -440,16 +457,13 @@ H5FD_stdio_open( const char *name, unsigned flags, hid_t fapl_id, * Programmer: Robb Matzke * Wednesday, October 22, 1997 * - * Modifications: - * Ported to VFL/H5FD layer - QAK, 10/18/99 - * *------------------------------------------------------------------------- */ static herr_t H5FD_stdio_close(H5FD_t *_file) { H5FD_stdio_t *file = (H5FD_stdio_t*)_file; - static const char *func="H5FD_stdio_close"; /* Function Name for error reporting */ + static const char *func = "H5FD_stdio_close"; /* Function Name for error reporting */ /* Clear the error stack */ H5Eclear2(H5E_DEFAULT); @@ -459,8 +473,8 @@ H5FD_stdio_close(H5FD_t *_file) free(file); - return(0); -} + return 0; +} /* end H5FD_stdio_close() */ /*------------------------------------------------------------------------- @@ -469,17 +483,14 @@ H5FD_stdio_close(H5FD_t *_file) * Purpose: Compares two files belonging to this driver using an * arbitrary (but consistent) ordering. * - * Return: Success: A value like strcmp() + * Return: + * Success: A value like strcmp() * - * Failure: never fails (arguments were checked by the - * caller). + * Failure: never fails (arguments were checked by the caller). * * Programmer: Robb Matzke * Thursday, July 29, 1999 * - * Modifications: - * Stolen from the sec2 driver - QAK, 10/18/99 - * *------------------------------------------------------------------------- */ static int @@ -492,30 +503,37 @@ H5FD_stdio_cmp(const H5FD_t *_f1, const H5FD_t *_f2) H5Eclear2(H5E_DEFAULT); #ifdef H5_HAVE_WIN32_API - if (f1->fileindexhi < f2->fileindexhi) return -1; - if (f1->fileindexhi > f2->fileindexhi) return 1; + if(f1->dwVolumeSerialNumber < f2->dwVolumeSerialNumber) return -1; + if(f1->dwVolumeSerialNumber > f2->dwVolumeSerialNumber) return 1; - if (f1->fileindexlo < f2->fileindexlo) return -1; - if (f1->fileindexlo > f2->fileindexlo) return 1; + if(f1->nFileIndexHigh < f2->nFileIndexHigh) return -1; + if(f1->nFileIndexHigh > f2->nFileIndexHigh) return 1; -#else + if(f1->nFileIndexLow < f2->nFileIndexLow) return -1; + if(f1->nFileIndexLow > f2->nFileIndexLow) return 1; +#else /* H5_HAVE_WIN32_API */ #ifdef H5_DEV_T_IS_SCALAR - if (f1->device < f2->device) return -1; - if (f1->device > f2->device) return 1; + if(f1->device < f2->device) return -1; + if(f1->device > f2->device) return 1; #else /* H5_DEV_T_IS_SCALAR */ /* If dev_t isn't a scalar value on this system, just use memcmp to * determine if the values are the same or not. The actual return value * shouldn't really matter... */ - if(memcmp(&(f1->device),&(f2->device),sizeof(dev_t))<0) return -1; - if(memcmp(&(f1->device),&(f2->device),sizeof(dev_t))>0) return 1; + if(memcmp(&(f1->device),&(f2->device),sizeof(dev_t)) < 0) return -1; + if(memcmp(&(f1->device),&(f2->device),sizeof(dev_t)) > 0) return 1; #endif /* H5_DEV_T_IS_SCALAR */ +#ifdef H5_VMS + if(memcmp(&(f1->inode), &(f2->inode), 3 * sizeof(ino_t)) < 0) return -1; + if(memcmp(&(f1->inode), &(f2->inode), 3 * sizeof(ino_t)) > 0) return 1; +#else /* H5_VMS */ + if(f1->inode < f2->inode) return -1; + if(f1->inode > f2->inode) return 1; +#endif /* H5_VMS */ +#endif /* H5_HAVE_WIN32_API */ - if (f1->inode < f2->inode) return -1; - if (f1->inode > f2->inode) return 1; -#endif return 0; -} +} /* H5FD_stdio_cmp() */ /*------------------------------------------------------------------------- @@ -531,14 +549,12 @@ H5FD_stdio_cmp(const H5FD_t *_f1, const H5FD_t *_f2) * Programmer: Quincey Koziol * Friday, August 25, 2000 * - * Modifications: - * *------------------------------------------------------------------------- */ static herr_t H5FD_stdio_query(const H5FD_t *_f, unsigned long *flags /* out */) { - /* Shut compiler up */ + /* Quiet the compiler */ _f=_f; /* Set the VFL feature flags that this driver supports */ @@ -550,37 +566,35 @@ H5FD_stdio_query(const H5FD_t *_f, unsigned long *flags /* out */) *flags|=H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */ } - return(0); -} + return 0; +} /* end H5FD_stdio_query() */ /*------------------------------------------------------------------------- * Function: H5FD_stdio_alloc * - * Purpose: Allocates file memory. If fseeko isn't available, makes + * Purpose: Allocates file memory. If fseeko isn't available, makes * sure the file size isn't bigger than 2GB because the * parameter OFFSET of fseek is of the type LONG INT, limiting * the file size to 2GB. * - * Return: Success: Address of new memory + * Return: + * Success: Address of new memory * - * Failure: HADDR_UNDEF + * Failure: HADDR_UNDEF * * Programmer: Raymond Lu * 30 March 2007 * - * Modifications: - * *------------------------------------------------------------------------- */ static haddr_t H5FD_stdio_alloc(H5FD_t *_file, H5FD_mem_t /*UNUSED*/ type, hid_t /*UNUSED*/ dxpl_id, hsize_t size) { - H5FD_stdio_t *file = (H5FD_stdio_t*)_file; - haddr_t addr; - haddr_t ret_value; /* Return value */ + H5FD_stdio_t *file = (H5FD_stdio_t*)_file; + haddr_t addr; - /* Shut compiler up */ + /* Quiet compiler */ type = type; dxpl_id = dxpl_id; @@ -599,19 +613,16 @@ H5FD_stdio_alloc(H5FD_t *_file, H5FD_mem_t /*UNUSED*/ type, hid_t /*UNUSED*/ dxp file->eoa = addr + size; - /* Set return value */ - ret_value = addr; - - return(ret_value); -} /* H5FD_stdio_alloc() */ + return addr; +} /* end H5FD_stdio_alloc() */ /*------------------------------------------------------------------------- * Function: H5FD_stdio_get_eoa * * Purpose: Gets the end-of-address marker for the file. The EOA marker - * is the first address past the last byte allocated in the - * format address space. + * is the first address past the last byte allocated in the + * format address space. * * Return: Success: The end-of-address marker. * @@ -620,28 +631,21 @@ H5FD_stdio_alloc(H5FD_t *_file, H5FD_mem_t /*UNUSED*/ type, hid_t /*UNUSED*/ dxp * Programmer: Robb Matzke * Monday, August 2, 1999 * - * Modifications: - * Stolen from the sec2 driver - QAK, 10/18/99 - * - * Raymond Lu - * 21 Dec. 2006 - * Added the parameter TYPE. It's only used for MULTI driver. - * *------------------------------------------------------------------------- */ static haddr_t -H5FD_stdio_get_eoa(const H5FD_t *_file, H5FD_mem_t /*unused*/ type) +H5FD_stdio_get_eoa(const H5FD_t *_file, H5FD_mem_t /*UNUSED*/ type) { - const H5FD_stdio_t *file = (const H5FD_stdio_t *)_file; + const H5FD_stdio_t *file = (const H5FD_stdio_t *)_file; /* Clear the error stack */ H5Eclear2(H5E_DEFAULT); - /* Shut compiler up */ + /* Quiet compiler */ type = type; - return(file->eoa); -} + return file->eoa; +} /* end H5FD_stdio_get_eoa() */ /*------------------------------------------------------------------------- @@ -653,33 +657,27 @@ H5FD_stdio_get_eoa(const H5FD_t *_file, H5FD_mem_t /*unused*/ type) * * Return: Success: 0 * - * Failure: -1 + * Failure: Does not fail * * Programmer: Robb Matzke * Thursday, July 29, 1999 * - * Modifications: - * Stolen from the sec2 driver - QAK, 10/18/99 - * - * Raymond Lu - * 21 Dec. 2006 - * Added the parameter TYPE. It's only used for MULTI driver. *------------------------------------------------------------------------- */ static herr_t -H5FD_stdio_set_eoa(H5FD_t *_file, H5FD_mem_t /*unused*/ type, haddr_t addr) +H5FD_stdio_set_eoa(H5FD_t *_file, H5FD_mem_t /*UNUSED*/ type, haddr_t addr) { H5FD_stdio_t *file = (H5FD_stdio_t*)_file; /* Clear the error stack */ H5Eclear2(H5E_DEFAULT); - /* Shut compiler up */ + /* Quiet the compiler */ type = type; file->eoa = addr; - return(0); + return 0; } @@ -699,9 +697,6 @@ H5FD_stdio_set_eoa(H5FD_t *_file, H5FD_mem_t /*unused*/ type, haddr_t addr) * Programmer: Robb Matzke * Thursday, July 29, 1999 * - * Modifications: - * Stolen from the sec2 driver - QAK, 10/18/99 - * *------------------------------------------------------------------------- */ static haddr_t @@ -712,8 +707,8 @@ H5FD_stdio_get_eof(const H5FD_t *_file) /* Clear the error stack */ H5Eclear2(H5E_DEFAULT); - return(MAX(file->eof, file->eoa)); -} + return MAX(file->eof, file->eoa); +} /* end H5FD_stdio_get_eof() */ /*------------------------------------------------------------------------- @@ -726,64 +721,56 @@ H5FD_stdio_get_eof(const H5FD_t *_file) * Programmer: Raymond Lu * Sept. 16, 2002 * - * Modifications: - * *------------------------------------------------------------------------- */ static herr_t H5FD_stdio_get_handle(H5FD_t *_file, hid_t fapl, void** file_handle) { H5FD_stdio_t *file = (H5FD_stdio_t *)_file; - static const char *func="H5FD_stdio_get_handle"; /* Function Name for error reporting */ + static const char *func = "H5FD_stdio_get_handle"; /* Function Name for error reporting */ - /* Shut compiler up */ - fapl=fapl; + /* Quiet the compiler */ + fapl = fapl; /* Clear the error stack */ H5Eclear2(H5E_DEFAULT); *file_handle = &(file->fp); - if(*file_handle==NULL) + if(*file_handle == NULL) H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_WRITEERROR, "get handle failed", -1) - return(0); -} + + return 0; +} /* end H5FD_stdio_get_handle() */ /*------------------------------------------------------------------------- - * Function: H5F_stdio_read + * Function: H5FD_stdio_read * * Purpose: Reads SIZE bytes beginning at address ADDR in file LF and * places them in buffer BUF. Reading past the logical or * physical end of file returns zeros instead of failing. * * Errors: - * IO READERROR Fread failed. - * IO SEEKERROR Fseek failed. + * IO READERROR fread failed. + * IO SEEKERROR fseek failed. * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * Wednesday, October 22, 1997 * - * Modifications: - * June 2, 1998 Albert Cheng - * Added xfer_mode argument - * - * Ported to VFL/H5FD layer - QAK, 10/18/99 - * *------------------------------------------------------------------------- */ static herr_t H5FD_stdio_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size, void *buf/*out*/) { - size_t n; H5FD_stdio_t *file = (H5FD_stdio_t*)_file; - static const char *func="H5FD_stdio_read"; /* Function Name for error reporting */ + static const char *func = "H5FD_stdio_read"; /* Function Name for error reporting */ - /* Shut compiler up */ - type=type; - dxpl_id=dxpl_id; + /* Quiet the compiler */ + type = type; + dxpl_id = dxpl_id; /* Clear the error stack */ H5Eclear2(H5E_DEFAULT); @@ -804,16 +791,14 @@ H5FD_stdio_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, siz /* Check easy cases */ if (0 == size) - return(0); + return 0; if ((haddr_t)addr >= file->eof) { memset(buf, 0, size); - return(0); + return 0; } - /* - * Seek to the correct file position. - */ - if (!(file->op == H5FD_STDIO_OP_READ || file->op==H5FD_STDIO_OP_SEEK) || + /* Seek to the correct file position. */ + if (!(file->op == H5FD_STDIO_OP_READ || file->op == H5FD_STDIO_OP_SEEK) || file->pos != addr) { if (file_fseek(file->fp, (file_offset_t)addr, SEEK_SET) < 0) { file->op = H5FD_STDIO_OP_UNKNOWN; @@ -823,59 +808,70 @@ H5FD_stdio_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, siz file->pos = addr; } - /* - * Read zeros past the logical end of file (physical is handled below) - */ + /* Read zeros past the logical end of file (physical is handled below) */ if (addr + size > file->eof) { size_t nbytes = (size_t) (addr + size - file->eof); memset((unsigned char *)buf + size - nbytes, 0, nbytes); size -= nbytes; } - /* - * Read the data. Since we're reading single-byte values, a partial read + /* Read the data. Since we're reading single-byte values, a partial read * will advance the file position by N. If N is zero or an error * occurs then the file position is undefined. */ - n = fread(buf, (size_t)1, size, file->fp); - if(n == 0 && ferror(file->fp)) { - file->op = H5FD_STDIO_OP_UNKNOWN; - file->pos = HADDR_UNDEF; - H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_READERROR, "fread failed", -1) - } else if (n < size) { - memset((unsigned char *)buf + n, 0, (size - n)); - } + while(size > 0) { - /* - * Update the file position data. - */ + size_t bytes_in = 0; /* # of bytes to read */ + size_t bytes_read = 0; /* # of bytes actually read */ + size_t item_size = 1; /* size of items in bytes */ + + if(size > H5_STDIO_MAX_IO_BYTES_g) + bytes_in = H5_STDIO_MAX_IO_BYTES_g; + else + bytes_in = size; + + bytes_read = fread(buf, item_size, bytes_in, file->fp); + + if(0 == bytes_read && ferror(file->fp)) { /* error */ + file->op = H5FD_STDIO_OP_UNKNOWN; + file->pos = HADDR_UNDEF; + H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_READERROR, "fread failed", -1) + } /* end if */ + + if(0 == bytes_read && feof(file->fp)) { + /* end of file but not end of format address space */ + memset((unsigned char *)buf, 0, size); + break; + } /* end if */ + + size -= bytes_read; + addr += (haddr_t)bytes_read; + buf = (char *)buf + bytes_read; + } /* end while */ + + /* Update the file position data. */ file->op = H5FD_STDIO_OP_READ; - file->pos = addr+n; /*checked for overflow above*/ - return(0); + file->pos = addr; + + return 0; } /*------------------------------------------------------------------------- - * Function: H5F_stdio_write + * Function: H5FD_stdio_write * * Purpose: Writes SIZE bytes from the beginning of BUF into file LF at * file address ADDR. * * Errors: - * IO SEEKERROR Fseek failed. - * IO WRITEERROR Fwrite failed. + * IO SEEKERROR fseek failed. + * IO WRITEERROR fwrite failed. * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * Wednesday, October 22, 1997 * - * Modifications: - * June 2, 1998 Albert Cheng - * Added xfer_mode argument - * - * Ported to VFL/H5FD layer - QAK, 10/18/99 - * *------------------------------------------------------------------------- */ static herr_t @@ -883,26 +879,24 @@ H5FD_stdio_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size, const void *buf) { H5FD_stdio_t *file = (H5FD_stdio_t*)_file; - static const char *func="H5FD_stdio_write"; /* Function Name for error reporting */ + static const char *func = "H5FD_stdio_write"; /* Function Name for error reporting */ - /* Shut compiler up */ - dxpl_id=dxpl_id; - type=type; + /* Quiet the compiler */ + dxpl_id = dxpl_id; + type = type; /* Clear the error stack */ H5Eclear2(H5E_DEFAULT); /* Check for overflow conditions */ - if (HADDR_UNDEF==addr) + if (HADDR_UNDEF == addr) H5Epush_ret (func, H5E_ERR_CLS, H5E_IO, H5E_OVERFLOW, "file address overflowed", -1) if (REGION_OVERFLOW(addr, size)) H5Epush_ret (func, H5E_ERR_CLS, H5E_IO, H5E_OVERFLOW, "file address overflowed", -1) - if (addr+size>file->eoa) + if (addr+size > file->eoa) H5Epush_ret (func, H5E_ERR_CLS, H5E_IO, H5E_OVERFLOW, "file address overflowed", -1) - /* - * Seek to the correct file position. - */ + /* Seek to the correct file position. */ if ((file->op != H5FD_STDIO_OP_WRITE && file->op != H5FD_STDIO_OP_SEEK) || file->pos != addr) { if (file_fseek(file->fp, (file_offset_t)addr, SEEK_SET) < 0) { @@ -913,33 +907,51 @@ H5FD_stdio_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, file->pos = addr; } - /* - * Write the buffer. On successful return, the file position will be - * advanced by the number of bytes read. Otherwise nobody knows where it - * is. + /* Write the buffer. On successful return, the file position will be + * advanced by the number of bytes read. On failure, the file position is + * undefined. */ - if(size != fwrite(buf, (size_t)1, size, file->fp)) { - file->op = H5FD_STDIO_OP_UNKNOWN; - file->pos = HADDR_UNDEF; - H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_WRITEERROR, "fwrite failed", -1) + while(size > 0) { + + size_t bytes_in = 0; /* # of bytes to write */ + size_t bytes_wrote = 0; /* # of bytes written */ + size_t item_size = 1; /* size of items in bytes */ + + if(size > H5_STDIO_MAX_IO_BYTES_g) + bytes_in = H5_STDIO_MAX_IO_BYTES_g; + else + bytes_in = size; + + bytes_wrote = fwrite(buf, item_size, bytes_in, file->fp); + + if(bytes_wrote != bytes_in || (0 == bytes_wrote && ferror(file->fp))) { /* error */ + file->op = H5FD_STDIO_OP_UNKNOWN; + file->pos = HADDR_UNDEF; + H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_WRITEERROR, "fwrite failed", -1) + } /* end if */ + + assert(bytes_wrote > 0); + assert((size_t)bytes_wrote <= size); + + size -= bytes_wrote; + addr += (haddr_t)bytes_wrote; + buf = (const char *)buf + bytes_wrote; } - /* - * Update seek optimizing data. - */ + /* Update seek optimizing data. */ file->op = H5FD_STDIO_OP_WRITE; - file->pos = addr + size; + file->pos = addr; /* Update EOF if necessary */ - if (file->pos>file->eof) + if (file->pos > file->eof) file->eof = file->pos; - return(0); + return 0; } /*------------------------------------------------------------------------- - * Function: H5F_stdio_flush + * Function: H5FD_stdio_flush * * Purpose: Makes sure that all data is on disk. * @@ -960,7 +972,7 @@ H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing) H5FD_stdio_t *file = (H5FD_stdio_t*)_file; static const char *func = "H5FD_stdio_flush"; /* Function Name for error reporting */ - /* Shut compiler up */ + /* Quiet the compiler */ dxpl_id = dxpl_id; /* Clear the error stack */ @@ -968,7 +980,6 @@ H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing) /* Only try to flush the file if we have write access */ if(file->write_access) { - /* Flush */ if(!closing) { if(fflush(file->fp) < 0) H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_WRITEERROR, "fflush failed", -1) @@ -979,12 +990,12 @@ H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing) } /* end if */ } /* end if */ - return(0); + return 0; } /* end H5FD_stdio_flush() */ /*------------------------------------------------------------------------- - * Function: H5F_stdio_truncate + * Function: H5FD_stdio_truncate * * Purpose: Makes sure that the true file size is the same (or larger) * than the end-of-address. @@ -998,9 +1009,6 @@ H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing) * Programmer: Quincey Koziol * Thursday, January 31, 2008 * - * Modifications: - * Vailin Choi; June 2010 - * Fix for window failures manifested from tests in mf.c. *------------------------------------------------------------------------- */ static herr_t @@ -1009,7 +1017,7 @@ H5FD_stdio_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing) H5FD_stdio_t *file = (H5FD_stdio_t*)_file; static const char *func = "H5FD_stdio_truncate"; /* Function Name for error reporting */ - /* Shut compiler up */ + /* Quiet the compiler */ dxpl_id = dxpl_id; closing = closing; @@ -1020,30 +1028,42 @@ H5FD_stdio_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing) if(file->write_access) { /* Makes sure that the true file size is the same as the end-of-address. */ if(file->eoa != file->eof) { - int fd = fileno(file->fp); /* File descriptor for HDF5 file */ #ifdef H5_HAVE_WIN32_API - HFILE filehandle; /* Windows file handle */ - LARGE_INTEGER li; /* 64-bit integer for SetFilePointer() call */ + LARGE_INTEGER li; /* 64-bit (union) integer for SetFilePointer() call */ + DWORD dwPtrLow; /* Low-order pointer bits from SetFilePointer() + * Only used as an error code here. + */ + DWORD dwError; /* DWORD error code from GetLastError() */ + BOOL bError; /* Boolean error flag */ - /* Reset seek offset to beginning of file, so that file isn't re-extended later */ + /* Reset seek offset to beginning of file, so that file isn't re-extended later */ rewind(file->fp); - /* Map the posix file handle to a Windows file handle */ - filehandle = _get_osfhandle(fd); - - /* Translate 64-bit integers into form Windows wants */ - /* [This algorithm is from the Windows documentation for SetFilePointer()] */ - li.QuadPart = (LONGLONG)file->eoa; - (void)SetFilePointer((HANDLE)filehandle, li.LowPart, &li.HighPart, FILE_BEGIN); - if(SetEndOfFile((HANDLE)filehandle) == 0) + /* Windows uses this odd QuadPart union for 32/64-bit portability */ + li.QuadPart = (__int64)file->eoa; + + /* Extend the file to make sure it's large enough. + * + * Since INVALID_SET_FILE_POINTER can technically be a valid return value + * from SetFilePointer(), we also need to check GetLastError(). + */ + dwPtrLow = SetFilePointer(file->hFile, li.LowPart, &li.HighPart, FILE_BEGIN); + if(INVALID_SET_FILE_POINTER == dwPtrLow) { + dwError = GetLastError(); + if(dwError != NO_ERROR ) + H5Epush_ret(func, H5E_ERR_CLS, H5E_FILE, H5E_FILEOPEN, "unable to set file pointer", -1) + } + + bError = SetEndOfFile(file->hFile); + if(0 == bError) H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_SEEKERROR, "unable to truncate/extend file properly", -1) #else /* H5_HAVE_WIN32_API */ /* Reset seek offset to beginning of file, so that file isn't re-extended later */ rewind(file->fp); /* Truncate file to proper length */ - if(-1 == file_ftruncate(fd, (file_offset_t)file->eoa)) + if(-1 == file_ftruncate(file->fd, (file_offset_t)file->eoa)) H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_SEEKERROR, "unable to truncate/extend file properly", -1) #endif /* H5_HAVE_WIN32_API */ @@ -1058,10 +1078,10 @@ H5FD_stdio_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing) else { /* Double-check for problems */ if(file->eoa > file->eof) - H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_TRUNCATED, "eoa>eof!", -1) - } /* end else */ + H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_TRUNCATED, "eoa > eof!", -1) + } /* end else */ - return(0); + return 0; } /* end H5FD_stdio_truncate() */ diff --git a/src/H5FSprivate.h b/src/H5FSprivate.h index ca7104c..f6a0034 100644 --- a/src/H5FSprivate.h +++ b/src/H5FSprivate.h @@ -155,7 +155,7 @@ typedef struct H5FS_stat_t { } H5FS_stat_t; /* Typedef for iteration operations */ -typedef herr_t (*H5FS_operator_t)(const H5FS_section_info_t *sect, +typedef herr_t (*H5FS_operator_t)(H5FS_section_info_t *sect, void *operator_data/*in,out*/); diff --git a/src/H5FSsection.c b/src/H5FSsection.c index 914fa58..0f126c2 100644 --- a/src/H5FSsection.c +++ b/src/H5FSsection.c @@ -2244,7 +2244,7 @@ H5FS_sect_assert(const H5FS_t *fspace) hsize_t separate_obj; /* The number of separate objects managed */ FUNC_ENTER_NOAPI_NOINIT_NOERR -#ifndef QAK +#ifdef QAK HDfprintf(stderr, "%s: fspace->tot_sect_count = %Hu\n", "H5FS_sect_assert", fspace->tot_sect_count); #endif /* QAK */ diff --git a/src/H5Fmpi.c b/src/H5Fmpi.c index 4fd04f6..966528a 100644 --- a/src/H5Fmpi.c +++ b/src/H5Fmpi.c @@ -38,6 +38,8 @@ #include "H5Eprivate.h" /* Error handling */ #include "H5Fpkg.h" /* File access */ #include "H5FDmpi.h" /* MPI-based file drivers */ +#include "H5FDprivate.h" /* File drivers */ +#include "H5Iprivate.h" /* IDs */ /****************/ @@ -177,5 +179,85 @@ H5F_mpi_get_size(const H5F_t *f) done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5F_mpi_get_size() */ + + +/*------------------------------------------------------------------------- + * Function: H5Fset_mpi_atomicity + * + * Purpose: Sets the atomicity mode + * + * Return: Success: Non-negative + * + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * Feb 14, 2012 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Fset_mpi_atomicity(hid_t file_id, hbool_t flag) +{ + H5F_t *file; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "ib", file_id, flag); + + /* Check args */ + if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID") + + /* Check VFD */ + if(!IS_H5FD_MPIO(file)) + HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "incorrect VFL driver, must use MPI-I/O driver") + + /* set atomicity value */ + if (H5FD_set_mpio_atomicity (file->shared->lf, flag) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set atomicity flag") + +done: + FUNC_LEAVE_API(ret_value) +} + + +/*------------------------------------------------------------------------- + * Function: H5Fget_mpi_atomicity + * + * Purpose: Returns the atomicity mode + * + * Return: Success: Non-negative + * + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * Feb 14, 2012 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Fget_mpi_atomicity(hid_t file_id, hbool_t *flag) +{ + H5F_t *file; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "i*b", file_id, flag); + + /* Check args */ + if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID") + + /* Check VFD */ + if(!IS_H5FD_MPIO(file)) + HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "incorrect VFL driver, must use MPI-I/O driver") + + /* get atomicity value */ + if (H5FD_get_mpio_atomicity (file->shared->lf, flag) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get atomicity flag") + +done: + FUNC_LEAVE_API(ret_value) +} #endif /* H5_HAVE_PARALLEL */ diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index 7eb7753..7335198 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -417,6 +417,7 @@ 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_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 */ /* ======================== File Mount properties ====================*/ #define H5F_MNT_SYM_LOCAL_NAME "local" /* Whether absolute symlinks local to file. */ @@ -528,8 +529,8 @@ H5_DLL H5F_t *H5F_get_parent(const H5F_t *f); H5_DLL unsigned H5F_get_nmounts(const H5F_t *f); H5_DLL hid_t H5F_get_access_plist(H5F_t *f, hbool_t app_ref); H5_DLL hid_t H5F_get_id(H5F_t *file, hbool_t app_ref); -H5_DLL size_t H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref); -H5_DLL size_t H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *obj_id_list, hbool_t app_ref); +H5_DLL herr_t H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref, size_t *obj_id_count_ptr); +H5_DLL herr_t H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *oid_list, hbool_t app_ref, size_t *obj_id_count_ptr); H5_DLL haddr_t H5F_get_next_proxy_addr(const H5F_t *f); /* Functions than retrieve values set/cached from the superblock/FCPL */ diff --git a/src/H5Fpublic.h b/src/H5Fpublic.h index 1f0e6d6..b0907e0 100644 --- a/src/H5Fpublic.h +++ b/src/H5Fpublic.h @@ -209,6 +209,7 @@ H5_DLL herr_t H5Fmount(hid_t loc, const char *name, hid_t child, hid_t plist); H5_DLL herr_t H5Funmount(hid_t loc, const char *name); H5_DLL hssize_t H5Fget_freespace(hid_t file_id); H5_DLL herr_t H5Fget_filesize(hid_t file_id, hsize_t *size); +H5_DLL ssize_t H5Fget_file_image(hid_t file_id, void * buf_ptr, size_t buf_len); H5_DLL herr_t H5Fget_mdc_config(hid_t file_id, H5AC_cache_config_t * config_ptr); H5_DLL herr_t H5Fset_mdc_config(hid_t file_id, @@ -225,6 +226,10 @@ H5_DLL herr_t H5Fget_info2(hid_t obj_id, H5F_info2_t *finfo); 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); +#ifdef H5_HAVE_PARALLEL +H5_DLL herr_t H5Fset_mpi_atomicity(hid_t file_id, hbool_t flag); +H5_DLL herr_t H5Fget_mpi_atomicity(hid_t file_id, hbool_t *flag); +#endif /* H5_HAVE_PARALLEL */ /* Symbols defined for compatibility with previous versions of the HDF5 API. * diff --git a/src/H5Gname.c b/src/H5Gname.c index 62875dc..576d866 100644 --- a/src/H5Gname.c +++ b/src/H5Gname.c @@ -782,7 +782,7 @@ done: /*------------------------------------------------------------------------- * Function: H5G_name_replace_cb * - * Purpose: H5I_search callback function to replace group entry names + * Purpose: H5I_iterate callback function to replace group entry names * * Return: Success: 0, Failure: -1 * @@ -1166,15 +1166,18 @@ H5G_name_replace(const H5O_link_t *lnk, H5G_names_op_t op, H5F_t *src_file, /* Search through group IDs */ if(search_group) - H5I_search(H5I_GROUP, H5G_name_replace_cb, &names, FALSE); + if(H5I_iterate(H5I_GROUP, H5G_name_replace_cb, &names, FALSE) < 0) + HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over groups") /* Search through dataset IDs */ if(search_dataset) - H5I_search(H5I_DATASET, H5G_name_replace_cb, &names, FALSE); + if(H5I_iterate(H5I_DATASET, H5G_name_replace_cb, &names, FALSE) < 0) + HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over datasets") /* Search through datatype IDs */ if(search_datatype) - H5I_search(H5I_DATATYPE, H5G_name_replace_cb, &names, FALSE); + if(H5I_iterate(H5I_DATATYPE, H5G_name_replace_cb, &names, FALSE) < 0) + HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over datatypes") } /* end if */ } /* end if */ diff --git a/src/H5Goh.c b/src/H5Goh.c index 194e3ec..c6115db 100644 --- a/src/H5Goh.c +++ b/src/H5Goh.c @@ -81,7 +81,8 @@ const H5O_obj_class_t H5O_OBJ_GROUP[1] = {{ H5O_group_open, /* open an object of this class */ H5O_group_create, /* create an object of this class */ H5O_group_get_oloc, /* get an object header location for an object */ - H5O_group_bh_info /* get the index & heap info for an object */ + H5O_group_bh_info, /* get the index & heap info for an object */ + NULL /* flush an opened object of this class */ }}; /* Declare the external free list to manage the H5O_ginfo_t struct */ diff --git a/src/H5HF.c b/src/H5HF.c index 801fa8c..a9750c9 100644 --- a/src/H5HF.c +++ b/src/H5HF.c @@ -156,9 +156,6 @@ H5HF_create(H5F_t *f, hid_t dxpl_id, const H5HF_create_t *cparam) H5HF_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI(NULL) -#ifdef QAK -HDfprintf(stderr, "%s: Called\n", FUNC); -#endif /* QAK */ /* * Check arguments. @@ -234,14 +231,8 @@ H5HF_open(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr) HDassert(H5F_addr_defined(fh_addr)); /* Load the heap header into memory */ -#ifdef QAK -HDfprintf(stderr, "%s: fh_addr = %a\n", FUNC, fh_addr); -#endif /* QAK */ if(NULL == (hdr = H5HF_hdr_protect(f, dxpl_id, fh_addr, H5AC_READ))) HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap header") -#ifdef QAK -HDfprintf(stderr, "%s: hdr->rc = %u, hdr->fspace = %p\n", FUNC, hdr->rc, hdr->fspace); -#endif /* QAK */ /* Check for pending heap deletion */ if(hdr->pending_delete) @@ -362,10 +353,6 @@ H5HF_insert(H5HF_t *fh, hid_t dxpl_id, size_t size, const void *obj, FUNC_ENTER_NOAPI(FAIL) -#ifdef QAK -HDfprintf(stderr, "%s: size = %Zu\n", FUNC, size); -#endif /* QAK */ - /* Sanity check */ HDassert(fh); HDassert(obj); @@ -407,9 +394,6 @@ HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "'write once' managed blocks not su } /* end else */ done: -#ifdef QAK -HDfprintf(stderr, "%s: Leaving, ret_value = %d\n", FUNC, ret_value); -#endif /* QAK */ FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_insert() */ @@ -581,9 +565,6 @@ H5HF_write(H5HF_t *fh, hid_t dxpl_id, void *_id, hbool_t UNUSED *id_changed, herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) -#ifdef QAK -HDfprintf(stderr, "%s: Called\n", FUNC); -#endif /* QAK */ /* * Check arguments. @@ -721,9 +702,6 @@ H5HF_remove(H5HF_t *fh, hid_t dxpl_id, const void *_id) herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) -#ifdef QAK -HDfprintf(stderr, "%s: Called\n", FUNC); -#endif /* QAK */ /* * Check arguments. @@ -815,17 +793,9 @@ H5HF_close(H5HF_t *fh, hid_t dxpl_id) * a reference loop and the objects couldn't be removed from * the metadata cache - QAK) */ -#ifdef QAK -HDfprintf(stderr, "%s; fh->hdr->man_iter_off = %Hu\n", FUNC, fh->hdr->man_iter_off); -HDfprintf(stderr, "%s; fh->hdr->man_size = %Hu\n", FUNC, fh->hdr->man_size); -HDfprintf(stderr, "%s; fh->hdr->rc = %Zu\n", FUNC, fh->hdr->rc); -#endif /* QAK */ if(H5HF_man_iter_ready(&fh->hdr->next_block)) if(H5HF_man_iter_reset(&fh->hdr->next_block) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't reset block iterator") -#ifdef QAK -HDfprintf(stderr, "%s; After iterator reset fh->hdr->rc = %Zu\n", FUNC, fh->hdr->rc); -#endif /* QAK */ /* Shut down the huge object information */ /* (Can't put this in header "destroy" routine, because it has @@ -901,9 +871,6 @@ H5HF_delete(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr) HDassert(H5F_addr_defined(fh_addr)); /* Lock the heap header into memory */ -#ifdef QAK -HDfprintf(stderr, "%s: fh_addr = %a\n", FUNC, fh_addr); -#endif /* QAK */ if(NULL == (hdr = H5HF_hdr_protect(f, dxpl_id, fh_addr, H5AC_WRITE))) HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap header") diff --git a/src/H5HFbtree2.c b/src/H5HFbtree2.c index 023344c..34b74d7 100644 --- a/src/H5HFbtree2.c +++ b/src/H5HFbtree2.c @@ -352,7 +352,7 @@ HDfprintf(stderr, "%s: nrecord = {%a, %Hu, %Hu}\n", "H5HF_huge_bt2_indir_found", herr_t H5HF_huge_bt2_indir_remove(const void *nrecord, void *_udata) { - H5HF_huge_remove_ud1_t *udata = (H5HF_huge_remove_ud1_t *)_udata; /* User callback data */ + H5HF_huge_remove_ud_t *udata = (H5HF_huge_remove_ud_t *)_udata; /* User callback data */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -570,7 +570,7 @@ HDfprintf(stderr, "%s: nrecord = {%a, %Hu, %x, %Hu, %Hu}\n", "H5HF_huge_bt2_filt herr_t H5HF_huge_bt2_filt_indir_remove(const void *nrecord, void *_udata) { - H5HF_huge_remove_ud1_t *udata = (H5HF_huge_remove_ud1_t *)_udata; /* User callback data */ + H5HF_huge_remove_ud_t *udata = (H5HF_huge_remove_ud_t *)_udata; /* User callback data */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -759,7 +759,7 @@ H5HF_huge_bt2_filt_indir_debug(FILE *stream, const H5F_t UNUSED *f, hid_t UNUSED herr_t H5HF_huge_bt2_dir_remove(const void *nrecord, void *_udata) { - H5HF_huge_remove_ud1_t *udata = (H5HF_huge_remove_ud1_t *)_udata; /* User callback data */ + H5HF_huge_remove_ud_t *udata = (H5HF_huge_remove_ud_t *)_udata; /* User callback data */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -984,7 +984,7 @@ HDfprintf(stderr, "%s: nrecord = {%a, %Hu, %x, %Hu}\n", "H5HF_huge_bt2_filt_dir_ herr_t H5HF_huge_bt2_filt_dir_remove(const void *nrecord, void *_udata) { - H5HF_huge_remove_ud1_t *udata = (H5HF_huge_remove_ud1_t *)_udata; /* User callback data */ + H5HF_huge_remove_ud_t *udata = (H5HF_huge_remove_ud_t *)_udata; /* User callback data */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT diff --git a/src/H5HFdbg.c b/src/H5HFdbg.c index 4289c02..caaedc7 100644 --- a/src/H5HFdbg.c +++ b/src/H5HFdbg.c @@ -172,39 +172,31 @@ H5HF_dtable_debug(H5HF_dtable_t *dtable, FILE *stream, int indent, int fwidth) /*------------------------------------------------------------------------- - * Function: H5HF_hdr_debug + * Function: H5HF_hdr_print * - * Purpose: Prints debugging info about a fractal heap header. + * Purpose: Prints info about a fractal heap header. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Feb 24 2006 + * koziol@hdfgroup.org + * Feb 23 2012 * *------------------------------------------------------------------------- */ -herr_t -H5HF_hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int fwidth) +void +H5HF_hdr_print(const H5HF_hdr_t *hdr, hid_t dxpl_id, hbool_t dump_internal, FILE *stream, int indent, int fwidth) { - H5HF_hdr_t *hdr = NULL; /* Fractal heap header info */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOINIT /* * Check arguments. */ - HDassert(f); - HDassert(H5F_addr_defined(addr)); + HDassert(hdr); HDassert(stream); HDassert(indent >= 0); HDassert(fwidth >= 0); - /* Load the fractal heap header */ - if(NULL == (hdr = H5HF_hdr_protect(f, dxpl_id, addr, H5AC_READ))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap header") - /* Print opening message */ HDfprintf(stream, "%*sFractal Heap Header...\n", indent, ""); @@ -277,10 +269,66 @@ H5HF_hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, "Filter mask for root direct block:", hdr->pline_root_direct_filter_mask); } /* end if */ - H5O_debug_id(H5O_PLINE_ID, f, dxpl_id, &(hdr->pline), stream, + H5O_debug_id(H5O_PLINE_ID, hdr->f, dxpl_id, &(hdr->pline), stream, indent + 3, MAX(0, fwidth - 3)); } /* end if */ + /* Print internal (runtime) information, if requested */ + if(dump_internal) { + HDfprintf(stream, "%*sFractal Heap Header Internal Information:\n", indent, ""); + + /* Dump root iblock, if there is one */ + HDfprintf(stream, "%*s%-*s %x\n", indent + 3, "", MAX(0, fwidth - 3), + "Root indirect block flags:", + hdr->root_iblock_flags); + HDfprintf(stream, "%*s%-*s %p\n", indent + 3, "", MAX(0, fwidth - 3), + "Root indirect block pointer:", + hdr->root_iblock); + if(hdr->root_iblock) + H5HF_iblock_print(hdr->root_iblock, dump_internal, stream, indent + 3, fwidth); + } /* end if */ + + FUNC_LEAVE_NOAPI_VOID +} /* end H5HF_hdr_print() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_hdr_debug + * + * Purpose: Prints debugging info about a fractal heap header. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 24 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int fwidth) +{ + H5HF_hdr_t *hdr = NULL; /* Fractal heap header info */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* + * Check arguments. + */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(stream); + HDassert(indent >= 0); + HDassert(fwidth >= 0); + + /* Load the fractal heap header */ + if(NULL == (hdr = H5HF_hdr_protect(f, dxpl_id, addr, H5AC_READ))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap header") + + /* Print the information about the heap's header */ + H5HF_hdr_print(hdr, dxpl_id, FALSE, stream, indent, fwidth); + done: if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, addr, hdr, H5AC__NO_FLAGS_SET) < 0) HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release fractal heap header") @@ -303,9 +351,9 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5HF_dblock_debug_cb(const H5FS_section_info_t *_sect, void *_udata) +H5HF_dblock_debug_cb(H5FS_section_info_t *_sect, void *_udata) { - const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Section to dump info */ + H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Section to dump info */ H5HF_debug_iter_ud1_t *udata = (H5HF_debug_iter_ud1_t *)_udata; /* User data for callbacks */ haddr_t sect_start, sect_end; /* Section's beginning and ending offsets */ haddr_t dblock_start, dblock_end; /* Direct block's beginning and ending offsets */ @@ -501,51 +549,39 @@ done: /*------------------------------------------------------------------------- - * Function: H5HF_iblock_debug + * Function: H5HF_iblock_print * * Purpose: Prints debugging info about a fractal heap indirect block. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 7 2006 + * koziol@hdfgroup.org + * Feb 23 2012 * *------------------------------------------------------------------------- */ -herr_t -H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, - int indent, int fwidth, haddr_t hdr_addr, unsigned nrows) +void +H5HF_iblock_print(const H5HF_indirect_t *iblock, + hbool_t dump_internal, FILE *stream, int indent, int fwidth) { - H5HF_hdr_t *hdr = NULL; /* Fractal heap header info */ - H5HF_indirect_t *iblock = NULL; /* Fractal heap direct block info */ - hbool_t did_protect; /* Whether we protected the indirect block or not */ + const H5HF_hdr_t *hdr; /* Pointer to heap's header */ char temp_str[64]; /* Temporary string, for formatting */ size_t u, v; /* Local index variable */ - herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOINIT /* * Check arguments. */ - HDassert(f); - HDassert(H5F_addr_defined(addr)); + HDassert(iblock); + HDassert(iblock->hdr); HDassert(stream); HDassert(indent >= 0); HDassert(fwidth >= 0); - HDassert(H5F_addr_defined(hdr_addr)); - HDassert(nrows > 0); - /* Load the fractal heap header */ - if(NULL == (hdr = H5HF_hdr_protect(f, dxpl_id, hdr_addr, H5AC_READ))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap header") - - /* - * Load the heap indirect block - */ - if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, addr, nrows, NULL, 0, FALSE, H5AC_READ, &did_protect))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap indirect block") + /* Set up convenience variables */ + hdr = iblock->hdr; /* Print opening message */ HDfprintf(stream, "%*sFractal Heap Indirect Block...\n", indent, ""); @@ -623,6 +659,75 @@ H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, HDfprintf(stream, "%*s%-*s\n", indent + 3, "", MAX(0, fwidth - 3), ""); + /* Print internal (runtime) information, if requested */ + if(dump_internal) { + HDfprintf(stream, "%*sFractal Indirect Block Internal Information:\n", indent, ""); + + /* Print general information */ + HDfprintf(stream, "%*s%-*s %Zu\n", indent + 3, "", MAX(0, fwidth - 3), + "Reference count:", + iblock->rc); + + /* Print parent's information */ + HDfprintf(stream, "%*s%-*s %p\n", indent + 3, "", MAX(0, fwidth - 3), + "Parent indirect block address:", + iblock->parent); + if(iblock->parent) + H5HF_iblock_print(iblock->parent, TRUE, stream, indent + 6, fwidth); + } /* end if */ + + FUNC_LEAVE_NOAPI_VOID +} /* end H5HF_iblock_print() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_iblock_debug + * + * Purpose: Prints debugging info about a fractal heap indirect block. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 7 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, + int indent, int fwidth, haddr_t hdr_addr, unsigned nrows) +{ + H5HF_hdr_t *hdr = NULL; /* Fractal heap header info */ + H5HF_indirect_t *iblock = NULL; /* Fractal heap direct block info */ + hbool_t did_protect; /* Whether we protected the indirect block or not */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* + * Check arguments. + */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(stream); + HDassert(indent >= 0); + HDassert(fwidth >= 0); + HDassert(H5F_addr_defined(hdr_addr)); + HDassert(nrows > 0); + + /* Load the fractal heap header */ + if(NULL == (hdr = H5HF_hdr_protect(f, dxpl_id, hdr_addr, H5AC_READ))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap header") + + /* + * Load the heap indirect block + */ + if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, addr, nrows, NULL, 0, FALSE, H5AC_READ, &did_protect))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap indirect block") + + /* Print the information about the heap's indirect block */ + H5HF_iblock_print(iblock, FALSE, stream, indent, fwidth); + done: if(iblock && H5HF_man_iblock_unprotect(iblock, dxpl_id, H5AC__NO_FLAGS_SET, did_protect) < 0) HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release fractal heap direct block") @@ -647,9 +752,9 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5HF_sects_debug_cb(const H5FS_section_info_t *_sect, void *_udata) +H5HF_sects_debug_cb(H5FS_section_info_t *_sect, void *_udata) { - const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Section to dump info */ + H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Section to dump info */ H5HF_debug_iter_ud2_t *udata = (H5HF_debug_iter_ud2_t *)_udata; /* User data for callbacks */ herr_t ret_value = SUCCEED; /* Return value */ diff --git a/src/H5HFhuge.c b/src/H5HFhuge.c index 3bbd137..6f0b48e 100644 --- a/src/H5HFhuge.c +++ b/src/H5HFhuge.c @@ -899,7 +899,7 @@ done: herr_t H5HF_huge_remove(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id) { - H5HF_huge_remove_ud1_t udata; /* User callback data for v2 B-tree remove call */ + H5HF_huge_remove_ud_t udata; /* User callback data for v2 B-tree remove call */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -1072,7 +1072,7 @@ done: herr_t H5HF_huge_delete(H5HF_hdr_t *hdr, hid_t dxpl_id) { - H5HF_huge_remove_ud1_t udata; /* User callback data for v2 B-tree remove call */ + H5HF_huge_remove_ud_t udata; /* User callback data for v2 B-tree remove call */ H5B2_remove_t op; /* Callback for v2 B-tree removal */ herr_t ret_value = SUCCEED; /* Return value */ diff --git a/src/H5HFiblock.c b/src/H5HFiblock.c index 6c19b4f..342e228 100644 --- a/src/H5HFiblock.c +++ b/src/H5HFiblock.c @@ -140,8 +140,17 @@ H5HF_iblock_pin(H5HF_indirect_t *iblock) else { /* Check for pinning the root indirect block */ if(iblock->block_off == 0) { - HDassert(iblock->hdr->root_iblock == NULL); - iblock->hdr->root_iblock = iblock; + /* Sanity check - shouldn't be recursively pinning root indirect block */ + HDassert(0 == (iblock->hdr->root_iblock_flags & H5HF_ROOT_IBLOCK_PINNED)); + + /* Check if we should set the root iblock pointer */ + if(0 == iblock->hdr->root_iblock_flags) { + HDassert(NULL == iblock->hdr->root_iblock); + iblock->hdr->root_iblock = iblock; + } /* end if */ + + /* Indicate that the root indirect block is pinned */ + iblock->hdr->root_iblock_flags |= H5HF_ROOT_IBLOCK_PINNED; } /* end if */ } /* end if */ @@ -192,12 +201,21 @@ H5HF_iblock_unpin(H5HF_indirect_t *iblock) par_iblock->child_iblocks[indir_idx] = NULL; } /* end if */ else { - /* Check for unpinning the root indirect block */ + /* Check for root indirect block */ if(iblock->block_off == 0) { - HDassert(iblock->hdr->root_iblock); - iblock->hdr->root_iblock = NULL; + /* Sanity check - shouldn't be recursively unpinning root indirect block */ + HDassert(iblock->hdr->root_iblock_flags & H5HF_ROOT_IBLOCK_PINNED); + + /* Check if we should reset the root iblock pointer */ + if(H5HF_ROOT_IBLOCK_PINNED == iblock->hdr->root_iblock_flags) { + HDassert(NULL != iblock->hdr->root_iblock); + iblock->hdr->root_iblock = NULL; + } /* end if */ + + /* Indicate that the root indirect block is unpinned */ + iblock->hdr->root_iblock_flags &= ~(H5HF_ROOT_IBLOCK_PINNED); } /* end if */ - } /* end if */ + } /* end else */ /* Mark block as evictable again */ if(H5AC_unpin_entry(iblock) < 0) @@ -273,18 +291,23 @@ H5HF_iblock_decr(H5HF_indirect_t *iblock) /* Mark block as evictable again when no child blocks depend on it */ if(iblock->rc == 0) { - if(H5HF_iblock_unpin(iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPIN, FAIL, "unable to unpin fractal heap indirect block") + H5HF_hdr_t *hdr; /* Fractal heap header */ + haddr_t iblock_addr; /* Address of fractal heap */ + hbool_t expunge_iblock = FALSE; /* Whether to expunge indirect block from heap */ + + /* Set up convenience variables */ + hdr = iblock->hdr; + iblock_addr = iblock->addr; if(iblock->nchildren == 0) { /* Check for deleting root indirect block (and no root direct block) */ - if(iblock->block_off == 0 && iblock->hdr->man_dtable.curr_root_rows > 0) { + if(iblock->block_off == 0 && hdr->man_dtable.curr_root_rows > 0) { /* Reset root pointer information */ - iblock->hdr->man_dtable.curr_root_rows = 0; - iblock->hdr->man_dtable.table_addr = HADDR_UNDEF; + hdr->man_dtable.curr_root_rows = 0; + hdr->man_dtable.table_addr = HADDR_UNDEF; /* Reset header information back to "empty heap" state */ - if(H5HF_hdr_empty(iblock->hdr) < 0) + if(H5HF_hdr_empty(hdr) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't make heap empty") } /* end if */ @@ -297,8 +320,18 @@ H5HF_iblock_decr(H5HF_indirect_t *iblock) iblock->par_entry = 0; } /* end if */ + /* Mark indirect block for removal from the metadata cache */ + expunge_iblock = TRUE; + } /* end if */ + + /* Unpin the indirect block */ + if(H5HF_iblock_unpin(iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPIN, FAIL, "unable to unpin fractal heap indirect block") + + /* Check for expunging the indirect block from the metadata cache */ + if(expunge_iblock) { /* Evict the indirect block from the metadata cache */ - if(H5AC_expunge_entry(iblock->hdr->f, H5AC_dxpl_id, H5AC_FHEAP_IBLOCK, iblock->addr, H5AC__FREE_FILE_SPACE_FLAG) < 0) + if(H5AC_expunge_entry(hdr->f, H5AC_dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, H5AC__FREE_FILE_SPACE_FLAG) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "unable to remove indirect block from cache") } /* end if */ } /* end if */ @@ -420,6 +453,10 @@ H5HF_man_iblock_root_create(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t min_dblock_si hdr->pline_root_direct_filter_mask = 0; } /* end if */ + /* Scan free space sections to set any 'parent' pointers to new indirect block */ + if(H5HF_space_create_root(hdr, dxpl_id, iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTSET, FAIL, "can't set free space section info to new root indirect block") + /* Unlock first (previously the root) direct block */ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, hdr->man_dtable.table_addr, dblock, H5AC__NO_FLAGS_SET) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block") @@ -859,6 +896,11 @@ H5HF_man_iblock_root_revert(H5HF_indirect_t *root_iblock, hid_t dxpl_id) if(H5HF_hdr_adjust_heap(hdr, (hsize_t)hdr->man_dtable.cparam.start_block_size, (hssize_t)hdr->man_dtable.row_tot_dblock_free[0]) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, FAIL, "can't increase space to cover root direct block") + /* Scan free space sections to reset any 'parent' pointers */ + if(H5HF_space_revert_root(hdr, dxpl_id) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRESET, FAIL, "can't reset free space section info") + + done: if(dblock && H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__NO_FLAGS_SET) < 0) HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block") @@ -1126,11 +1168,20 @@ H5HF_man_iblock_protect(H5HF_hdr_t *hdr, hid_t dxpl_id, haddr_t iblock_addr, else { /* Check for root indirect block */ if(H5F_addr_eq(iblock_addr, hdr->man_dtable.table_addr)) { - /* Check for pointer to pinned indirect block in root */ - if(hdr->root_iblock) + /* Check for valid pointer to pinned indirect block in root */ + if(H5HF_ROOT_IBLOCK_PINNED == hdr->root_iblock_flags) { + /* Sanity check */ + HDassert(NULL != hdr->root_iblock); + + /* Return the pointer to the pinned root indirect block */ iblock = hdr->root_iblock; - else + } /* end if */ + else { + /* Sanity check */ + HDassert(NULL == hdr->root_iblock); + should_protect = TRUE; + } /* end else */ } /* end if */ else should_protect = TRUE; @@ -1158,6 +1209,21 @@ H5HF_man_iblock_protect(H5HF_hdr_t *hdr, hid_t dxpl_id, haddr_t iblock_addr, /* Set the indirect block's address */ iblock->addr = iblock_addr; + /* Check for root indirect block */ + if(iblock->block_off == 0) { + /* Sanity check - shouldn't be recursively protecting root indirect block */ + HDassert(0 == (hdr->root_iblock_flags & H5HF_ROOT_IBLOCK_PROTECTED)); + + /* Check if we should set the root iblock pointer */ + if(0 == hdr->root_iblock_flags) { + HDassert(NULL == hdr->root_iblock); + hdr->root_iblock = iblock; + } /* end if */ + + /* Indicate that the root indirect block is protected */ + hdr->root_iblock_flags |= H5HF_ROOT_IBLOCK_PROTECTED; + } /* end if */ + /* Indicate that the indirect block was protected */ *did_protect = TRUE; } /* end if */ @@ -1202,6 +1268,21 @@ H5HF_man_iblock_unprotect(H5HF_indirect_t *iblock, hid_t dxpl_id, /* Check if we previously protected this indirect block */ /* (as opposed to using an existing pointer to a pinned child indirect block) */ if(did_protect) { + /* Check for root indirect block */ + if(iblock->block_off == 0) { + /* Sanity check - shouldn't be recursively unprotecting root indirect block */ + HDassert(iblock->hdr->root_iblock_flags & H5HF_ROOT_IBLOCK_PROTECTED); + + /* Check if we should reset the root iblock pointer */ + if(H5HF_ROOT_IBLOCK_PROTECTED == iblock->hdr->root_iblock_flags) { + HDassert(NULL != iblock->hdr->root_iblock); + iblock->hdr->root_iblock = NULL; + } /* end if */ + + /* Indicate that the root indirect block is unprotected */ + iblock->hdr->root_iblock_flags &= ~(H5HF_ROOT_IBLOCK_PROTECTED); + } /* end if */ + /* Unprotect the indirect block */ if(H5AC_unprotect(iblock->hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock->addr, iblock, cache_flags) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") @@ -1215,7 +1296,7 @@ done: /*------------------------------------------------------------------------- * Function: H5HF_man_iblock_attach * - * Purpose: Attach a block to an indirect block + * Purpose: Attach a child block (direct or indirect) to an indirect block * * Return: SUCCEED/FAIL * @@ -1243,7 +1324,7 @@ H5HF_man_iblock_attach(H5HF_indirect_t *iblock, unsigned entry, haddr_t child_ad if(H5HF_iblock_incr(iblock) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block") - /* Point at the direct block */ + /* Point at the child block */ iblock->ents[entry].addr = child_addr; /* Check for I/O filters on this heap */ @@ -1280,7 +1361,7 @@ done: /*------------------------------------------------------------------------- * Function: H5HF_man_iblock_detach * - * Purpose: Detach a block from an indirect block + * Purpose: Detach a child block (direct or indirect) from an indirect block * * Return: SUCCEED/FAIL * @@ -1293,6 +1374,7 @@ done: herr_t H5HF_man_iblock_detach(H5HF_indirect_t *iblock, hid_t dxpl_id, unsigned entry) { + unsigned row; /* Row for entry */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -1306,16 +1388,14 @@ H5HF_man_iblock_detach(H5HF_indirect_t *iblock, hid_t dxpl_id, unsigned entry) /* Reset address of entry */ iblock->ents[entry].addr = HADDR_UNDEF; + /* Compute row for entry */ + row = entry / iblock->hdr->man_dtable.cparam.width; + /* Check for I/O filters on this heap */ if(iblock->hdr->filter_len > 0) { - unsigned row; /* Row for entry */ - /* Sanity check */ HDassert(iblock->filt_ents); - /* Compute row for entry */ - row = entry / iblock->hdr->man_dtable.cparam.width; - /* If this is a direct block, reset its initial size */ if(row < iblock->hdr->man_dtable.max_direct_rows) { iblock->filt_ents[entry].size = 0; @@ -1323,6 +1403,24 @@ H5HF_man_iblock_detach(H5HF_indirect_t *iblock, hid_t dxpl_id, unsigned entry) } /* end if */ } /* end if */ + /* Check for indirect block being detached */ + if(row >= iblock->hdr->man_dtable.max_direct_rows) { + unsigned indir_idx; /* Index in parent's child iblock pointer array */ + + /* Sanity check */ + HDassert(iblock->child_iblocks); + + /* Compute index in child iblock pointer array */ + indir_idx = entry - (iblock->hdr->man_dtable.max_direct_rows + * iblock->hdr->man_dtable.cparam.width); + + /* Sanity check */ + HDassert(iblock->child_iblocks[indir_idx]); + + /* Reset pointer to child indirect block in parent */ + iblock->child_iblocks[indir_idx] = NULL; + } /* end if */ + /* Decrement the # of child blocks */ /* (If the number of children drop to 0, the indirect block will be * removed from the heap when its ref. count drops to zero and the diff --git a/src/H5HFpkg.h b/src/H5HFpkg.h index 2746302..498c45e 100644 --- a/src/H5HFpkg.h +++ b/src/H5HFpkg.h @@ -174,6 +174,11 @@ #define H5HF_OP_MODIFY 0x0001 /* Operation will modify object */ #define H5HF_OP_FLAGS (H5HF_OP_MODIFY) /* Bit-wise OR of all op flags */ +/* Flags for 'root_iblock_flags' field in header */ +#define H5HF_ROOT_IBLOCK_PINNED 0x01 +#define H5HF_ROOT_IBLOCK_PROTECTED 0x02 + + /****************************/ /* Package Private Typedefs */ /****************************/ @@ -342,7 +347,8 @@ typedef struct H5HF_hdr_t { hbool_t pending_delete; /* Heap is pending deletion */ uint8_t sizeof_size; /* Size of file sizes */ uint8_t sizeof_addr; /* Size of file addresses */ - struct H5HF_indirect_t *root_iblock; /* Pointer to pinned root indirect block */ + struct H5HF_indirect_t *root_iblock; /* Pointer to root indirect block */ + unsigned root_iblock_flags; /* Flags to indicate whether root indirect block is pinned/protected */ H5FS_t *fspace; /* Free space list for objects in heap */ H5HF_block_iter_t next_block; /* Block iterator for searching for next block with space */ H5B2_t *huge_bt2; /* v2 B-tree handle for huge objects */ @@ -457,14 +463,14 @@ typedef struct H5HF_huge_bt2_filt_dir_rec_t { typedef struct { H5HF_hdr_t *hdr; /* Fractal heap header */ hid_t dxpl_id; /* DXPL ID for operation */ -} H5HF_sect_add_ud1_t; +} H5HF_sect_add_ud_t; /* User data for v2 B-tree 'remove' callback on 'huge' objects */ typedef struct { H5HF_hdr_t *hdr; /* Fractal heap header (in) */ hid_t dxpl_id; /* DXPL ID for operation (in) */ hsize_t obj_len; /* Length of object removed (out) */ -} H5HF_huge_remove_ud1_t; +} H5HF_huge_remove_ud_t; /* User data for fractal heap header cache client callback */ typedef struct H5HF_hdr_cache_ud_t { @@ -701,10 +707,14 @@ H5_DLL herr_t H5HF_tiny_op(H5HF_hdr_t *hdr, const uint8_t *id, H5_DLL herr_t H5HF_tiny_remove(H5HF_hdr_t *fh, const uint8_t *id); /* Debugging routines for dumping file structures */ +H5_DLL void H5HF_hdr_print(const H5HF_hdr_t *hdr, hid_t dxpl_id, + hbool_t dump_internal, FILE *stream, int indent, int fwidth); H5_DLL herr_t H5HF_hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int fwidth); H5_DLL herr_t H5HF_dblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int fwidth, haddr_t hdr_addr, size_t nrec); +H5_DLL void H5HF_iblock_print(const H5HF_indirect_t *iblock, hbool_t dump_internal, + FILE *stream, int indent, int fwidth); H5_DLL herr_t H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int fwidth, haddr_t hdr_addr, unsigned nrows); @@ -733,6 +743,9 @@ H5_DLL herr_t H5HF_space_add(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *node, unsigned flags); H5_DLL htri_t H5HF_space_find(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t request, H5HF_free_section_t **node); +H5_DLL herr_t H5HF_space_revert_root(const H5HF_hdr_t *hdr, hid_t dxpl_id); +H5_DLL herr_t H5HF_space_create_root(const H5HF_hdr_t *hdr, hid_t dxpl_id, + H5HF_indirect_t *root_iblock); H5_DLL herr_t H5HF_space_size(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t *fs_size); H5_DLL herr_t H5HF_space_remove(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *node); diff --git a/src/H5HFsection.c b/src/H5HFsection.c index 38d9381..87fa069 100644 --- a/src/H5HFsection.c +++ b/src/H5HFsection.c @@ -665,42 +665,6 @@ H5HF_sect_single_dblock_info(H5HF_hdr_t *hdr, hid_t dxpl_id, HDassert(dblock_addr); HDassert(dblock_size); - /* Check for section in first direct block of heap */ - if(sect->sect_info.addr < hdr->man_dtable.cparam.start_block_size) { - /* Check for heap changing from direct <-> indirect root (or vice versa) - * while section was live. - */ - if(sect->u.single.parent) { - /* Check for heap converting from indirect root to direct root while section was live */ - if(hdr->man_dtable.curr_root_rows == 0) { - /* Release hold on parent indirect block */ - if(H5HF_iblock_decr(sect->u.single.parent) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on section's indirect block") - - /* Reset parent information */ - sect->u.single.parent = NULL; - sect->u.single.par_entry = 0; - } /* end if */ - else { - /* Check for heap converting from indirect to direct and back - * to indirect again, which would indicate a different - * indirect root block would be used for the parent of - * this section and the actual root indirect block. - */ - if(H5HF_sect_single_locate_parent(hdr, dxpl_id, TRUE, sect) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get section's parent info") - } /* end else */ - } /* end if */ - else { - /* Check for heap converting from direct root to indirect root while section was live */ - if(hdr->man_dtable.curr_root_rows != 0) { - /* Look up indirect block information for section */ - if(H5HF_sect_single_locate_parent(hdr, dxpl_id, FALSE, sect) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get section's parent info") - } /* end if */ - } /* end else */ - } /* end if */ - /* Check for root direct block */ if(hdr->man_dtable.curr_root_rows == 0) { /* Retrieve direct block info from heap header */ @@ -860,7 +824,7 @@ H5HF_sect_single_add(H5FS_section_info_t *_sect, unsigned *flags, void *_udata) */ if(!(*flags & H5FS_ADD_DESERIALIZING)) { H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Fractal heap free section */ - H5HF_sect_add_ud1_t *udata = (H5HF_sect_add_ud1_t *)_udata; /* User callback data */ + H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata; /* User callback data */ H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */ hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */ @@ -992,7 +956,7 @@ H5HF_sect_single_merge(H5FS_section_info_t *_sect1, H5FS_section_info_t *_sect2, { H5HF_free_section_t *sect1 = (H5HF_free_section_t *)_sect1; /* Fractal heap free section */ H5HF_free_section_t *sect2 = (H5HF_free_section_t *)_sect2; /* Fractal heap free section */ - H5HF_sect_add_ud1_t *udata = (H5HF_sect_add_ud1_t *)_udata; /* User callback data */ + H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata; /* User callback data */ H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */ hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */ herr_t ret_value = SUCCEED; /* Return value */ @@ -1050,7 +1014,7 @@ static htri_t H5HF_sect_single_can_shrink(const H5FS_section_info_t *_sect, void *_udata) { const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Fractal heap free section */ - H5HF_sect_add_ud1_t *udata = (H5HF_sect_add_ud1_t *)_udata; /* User callback data */ + H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata; /* User callback data */ H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */ htri_t ret_value = FALSE; /* Return value */ @@ -1105,7 +1069,7 @@ static herr_t H5HF_sect_single_shrink(H5FS_section_info_t **_sect, void UNUSED *_udata) { H5HF_free_section_t **sect = (H5HF_free_section_t **)_sect; /* Fractal heap free section */ - H5HF_sect_add_ud1_t *udata = (H5HF_sect_add_ud1_t *)_udata; /* User callback data */ + H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata; /* User callback data */ H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */ hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */ H5HF_direct_t *dblock; /* Pointer to direct block for section */ @@ -1814,7 +1778,7 @@ H5HF_sect_row_merge(H5FS_section_info_t *_sect1, H5FS_section_info_t *_sect2, { H5HF_free_section_t *sect1 = (H5HF_free_section_t *)_sect1; /* Fractal heap free section */ H5HF_free_section_t *sect2 = (H5HF_free_section_t *)_sect2; /* Fractal heap free section */ - H5HF_sect_add_ud1_t *udata = (H5HF_sect_add_ud1_t *)_udata; /* User callback data */ + H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata; /* User callback data */ H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */ hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */ herr_t ret_value = SUCCEED; /* Return value */ @@ -1881,7 +1845,7 @@ static htri_t H5HF_sect_row_can_shrink(const H5FS_section_info_t *_sect, void UNUSED *_udata) { const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Fractal heap free section */ - H5HF_sect_add_ud1_t *udata = (H5HF_sect_add_ud1_t *)_udata; /* User callback data */ + H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata; /* User callback data */ H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */ htri_t ret_value = FALSE; /* Return value */ @@ -1919,7 +1883,7 @@ H5HF_sect_row_shrink(H5FS_section_info_t **_sect, void *_udata) { H5HF_free_section_t **sect = (H5HF_free_section_t **)_sect; /* Fractal heap free section */ H5HF_free_section_t *top_indir_sect; /* Top indirect section for row */ - H5HF_sect_add_ud1_t *udata = (H5HF_sect_add_ud1_t *)_udata; /* User callback data */ + H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata; /* User callback data */ H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */ hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */ herr_t ret_value = SUCCEED; /* Return value */ @@ -2161,7 +2125,7 @@ H5HF_sect_indirect_iblock_off(const H5HF_free_section_t *sect) * * Purpose: Get the "top" indirect section * - * Return: Pointer to the top indirect sectin (can't fail) + * Return: Pointer to the top indirect section (can't fail) * * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu diff --git a/src/H5HFspace.c b/src/H5HFspace.c index cec9b3a..01330d3 100644 --- a/src/H5HFspace.c +++ b/src/H5HFspace.c @@ -168,7 +168,7 @@ herr_t H5HF_space_add(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *node, unsigned flags) { - H5HF_sect_add_ud1_t udata; /* User data for free space manager 'add' */ + H5HF_sect_add_ud_t udata; /* User data for free space manager 'add' */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -246,6 +246,185 @@ done: /*------------------------------------------------------------------------- + * Function: H5HF_space_revert_root_cb + * + * Purpose: Callback routine from iterator, to reset 'parent' pointers in + * sections, when the heap is changing from having a root indirect + * block to a direct block. + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Feb 24 2012 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_space_revert_root_cb(H5FS_section_info_t *_sect, void UNUSED *_udata) +{ + H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Section to dump info */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* + * Check arguments. + */ + HDassert(sect); + + /* Only modify "live" single blocks... */ + if(sect->sect_info.type == H5HF_FSPACE_SECT_SINGLE && sect->sect_info.state == H5FS_SECT_LIVE) { + /* Release hold on previous indirect block (we must have one) */ + HDassert(sect->u.single.parent); + if(H5HF_iblock_decr(sect->u.single.parent) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on section's indirect block") + + /* Reset parent information */ + sect->u.single.parent = NULL; + sect->u.single.par_entry = 0; + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_space_revert_root_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_space_revert_root + * + * Purpose: Reset 'parent' pointers in sections, when the heap is + * changing from having a root indirect block to a direct block. + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Feb 23 2012 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_space_revert_root(const H5HF_hdr_t *hdr, hid_t dxpl_id) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* + * Check arguments. + */ + HDassert(hdr); + + /* Only need to scan the sections if the free space has been initialized */ + if(hdr->fspace) { + /* Iterate over all sections, reseting the parent pointers in 'single' sections */ + if(H5FS_sect_iterate(hdr->f, dxpl_id, hdr->fspace, H5HF_space_revert_root_cb, NULL) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_BADITER, FAIL, "can't iterate over sections to reset parent pointers") + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_space_revert_root() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_space_create_root_cb + * + * Purpose: Callback routine from iterator, to set 'parent' pointers in + * sections to newly created root indirect block, when the heap + * is changing from having a root direct block to an indirect block. + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Feb 24 2012 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_space_create_root_cb(H5FS_section_info_t *_sect, void *_udata) +{ + H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Section to dump info */ + H5HF_indirect_t *root_iblock = (H5HF_indirect_t *)_udata; /* User data for callback */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* + * Check arguments. + */ + HDassert(sect); + HDassert(root_iblock); + + /* Sanity check sections */ + /* (If we are switching from a direct block for the root block of the heap, */ + /* there should only be 'single' type sections. -QAK) */ + HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_SINGLE); + + /* Increment ref. count on new root indirect block */ + if(H5HF_iblock_incr(root_iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on section's indirect block") + + /* Set parent info ("live" section must _NOT_ have a parent right now) */ + if(sect->sect_info.state == H5FS_SECT_SERIALIZED) + sect->sect_info.state = H5FS_SECT_LIVE; /* Mark "live" now */ + else + HDassert(!sect->u.single.parent); + sect->u.single.parent = root_iblock; + sect->u.single.par_entry = 0; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_space_create_root_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_space_create_root + * + * Purpose: Set 'parent' pointers in sections to new indirect block, when + * the heap is changing from having a root direct block to a + * indirect block. + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Feb 24 2012 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_space_create_root(const H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_indirect_t *root_iblock) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(root_iblock); + + /* Only need to scan the sections if the free space has been initialized */ + if(hdr->fspace) { + /* Iterate over all sections, seting the parent pointers in 'single' sections to the new indirect block */ + if(H5FS_sect_iterate(hdr->f, dxpl_id, hdr->fspace, H5HF_space_create_root_cb, root_iblock) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_BADITER, FAIL, "can't iterate over sections to set parent pointers") + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_space_create_root() */ + + +/*------------------------------------------------------------------------- * Function: H5HF_space_size * * Purpose: Query the size of the heap's free space info on disk diff --git a/src/H5I.c b/src/H5I.c index fb4ce5a..b28b3e7 100644 --- a/src/H5I.c +++ b/src/H5I.c @@ -108,6 +108,11 @@ typedef struct { H5I_id_info_t **id_list; /*pointer to an array of ptrs to IDs */ } H5I_id_type_t; +typedef struct { + H5I_search_func_t app_cb; /* Application's callback routine */ + void *app_key; /* Application's "key" (user data) */ + void *ret_obj; /* Object to return */ +} H5I_search_ud_t; /*-------------------- Locally scoped variables -----------------------------*/ @@ -127,6 +132,7 @@ H5FL_DEFINE_STATIC(H5I_id_info_t); /*--------------------- Local function prototypes ---------------------------*/ static H5I_id_info_t *H5I_find_id(hid_t id); +static int H5I_search_cb(void *obj, hid_t id, void *udata); #ifdef H5I_DEBUG_OUTPUT static herr_t H5I_debug(H5I_type_t type); #endif /* H5I_DEBUG_OUTPUT */ @@ -1982,6 +1988,40 @@ done: /*------------------------------------------------------------------------- + * Function: H5I_search_cb + * + * Purpose: Callback routine for H5Isearch, when it calls H5I_iterate. + * Calls "user" callback search function, and then sets return + * value, based on the result of that callback. + * + * Return: Success: The first object in the type for which FUNC + * returns non-zero. NULL if FUNC returned zero + * for every object in the type. + * Failure: NULL + * + * Programmer: Quincey Koziol + * Friday, March 30, 2012 + * + *------------------------------------------------------------------------- + */ +static int +H5I_search_cb(void *obj, hid_t id, void *_udata) +{ + H5I_search_ud_t *udata = (H5I_search_ud_t *)_udata; /* User data for callback */ + int ret_value; /* Callback return value */ + + FUNC_ENTER_NOAPI_NOINIT + + ret_value = (*udata->app_cb)(obj, id, udata->app_key); + if(ret_value > 0) + udata->ret_obj = obj; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5I_search_cb() */ + + +/*------------------------------------------------------------------------- * Function: H5Isearch * * Purpose: Apply function FUNC to each member of type TYPE and return a @@ -2008,14 +2048,27 @@ done: void * H5Isearch(H5I_type_t type, H5I_search_func_t func, void *key) { - void * ret_value; /* Return value */ + H5I_search_ud_t udata; /* Context for iteration */ + void *ret_value; /* Return value */ FUNC_ENTER_API(NULL) + /* Check arguments */ if(H5I_IS_LIB_TYPE(type)) HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "cannot call public function on library type") - ret_value = H5I_search(type, func, key, TRUE); + /* Set up udata struct */ + udata.app_cb = func; + udata.app_key = key; + udata.ret_obj = NULL; + + /* Note that H5I_iterate returns an error code. We ignore it + * here, as we can't do anything with it without revising the API. + */ + H5I_iterate(type, H5I_search_cb, &udata, TRUE); + + /* Set return value */ + ret_value = udata.ret_obj; done: FUNC_LEAVE_API(ret_value) @@ -2023,62 +2076,71 @@ done: /*------------------------------------------------------------------------- - * Function: H5I_search + * Function: H5I_iterate * - * Purpose: Apply function FUNC to each member of type TYPE and return a - * pointer to the first object for which FUNC returns non-zero. - * The FUNC should take a pointer to the object and the KEY as - * arguments and return non-zero to terminate the search (zero - * to continue). + * Purpose: Apply function FUNC to each member of type TYPE (with + * non-zero application reference count if app_ref is TRUE). + * Stop if FUNC returns a non zero value (i.e. anything + * other than H5_ITER_CONT). * - * Limitation: Currently there is no way to start searching from where a - * previous search left off. + * If FUNC returns a positive value (i.e. H5_ITER_STOP), + * return SUCCEED. * - * Return: Success: The first object in the type for which FUNC - * returns non-zero. NULL if FUNC returned zero - * for every object in the type. - * Failure: NULL + * If FUNC returns a negative value (i.e. H5_ITER_ERROR), + * return FAIL. + * + * The FUNC should take a pointer to the object and the + * udata as arguments and return non-zero to terminate + * siteration, and zero to continue. * - * Programmer: Robb Matzke - * Friday, February 19, 1999 + * Limitation: Currently there is no way to start the iteration from + * where a previous iteration left off. + * + * Return: Success: SUCCEED + * Failure: FAIL * - * Modifications: Neil Fortner - * Wednesday, October 1, 2008 - * Added app_ref parameter. When set to TRUE, the function will only - * operate on ids that have a nonzero application reference count. + * Programmer: John Mainzer + * Monday, December 6, 2011 * *------------------------------------------------------------------------- */ -void * -H5I_search(H5I_type_t type, H5I_search_func_t func, void *key, hbool_t app_ref) +herr_t +H5I_iterate(H5I_type_t type, H5I_search_func_t func, void *udata, hbool_t app_ref) { - H5I_id_type_t *type_ptr; /*ptr to the type */ - void *ret_value = NULL; /*return value */ + H5I_id_type_t *type_ptr; /*ptr to the type */ + herr_t ret_value = SUCCEED; /*return value */ - FUNC_ENTER_NOAPI(NULL) + FUNC_ENTER_NOAPI(FAIL) /* Check arguments */ if(type <= H5I_BADID || type >= H5I_next_type) - HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "invalid type number") + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number") type_ptr = H5I_id_type_list_g[type]; - if(type_ptr == NULL || type_ptr->count <= 0) - HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "invalid type") - /* Only iterate through hash table if there are IDs in group */ - if(type_ptr->ids > 0) { - H5I_id_info_t *id_ptr; /*ptr to the new ID */ - H5I_id_info_t *next_id; /*ptr to the next ID */ - unsigned i; /*counter */ + /* Only iterate through hash table if it is initialized and there are IDs in group */ + if(type_ptr && type_ptr->count > 0 && type_ptr->ids > 0) { + unsigned u; /* Counter */ /* Start at the beginning of the array */ - for(i = 0; i < type_ptr->hash_size; i++) { - id_ptr = type_ptr->id_list[i]; + for(u = 0; u < type_ptr->hash_size; u++) { + H5I_id_info_t *id_ptr; /* Ptr to the new ID */ + + id_ptr = type_ptr->id_list[u]; while(id_ptr) { - next_id = id_ptr->next; /* Protect against ID being deleted in callback */ - /* (Casting away const OK -QAK) */ - if((!app_ref || id_ptr->app_count) && (*func)((void *)id_ptr->obj_ptr, id_ptr->id, key)) - /* (Casting away const OK -QAK) */ - HGOTO_DONE((void *)id_ptr->obj_ptr); /*found the item*/ + H5I_id_info_t *next_id; /* Ptr to the next ID */ + + /* Protect against ID being deleted in callback */ + next_id = id_ptr->next; + if((!app_ref) || (id_ptr->app_count > 0)) { + herr_t cb_ret_val; /* Callback return value */ + + /* (Casting away const OK) */ + cb_ret_val = (*func)((void *)id_ptr->obj_ptr, id_ptr->id, udata); + if(cb_ret_val > 0) + HGOTO_DONE(SUCCEED) /* terminate iteration early */ + else if(cb_ret_val < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "func failed") + } /* end if */ id_ptr = next_id; } /* end while */ } /* end for */ @@ -2086,7 +2148,7 @@ H5I_search(H5I_type_t type, H5I_search_func_t func, void *key, hbool_t app_ref) done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5I_search() */ +} /* end H5I_iterate() */ /*------------------------------------------------------------------------- diff --git a/src/H5Iprivate.h b/src/H5Iprivate.h index 7b93d39..bb767ca 100644 --- a/src/H5Iprivate.h +++ b/src/H5Iprivate.h @@ -63,7 +63,7 @@ H5_DLL H5I_type_t H5I_get_type(hid_t id); H5_DLL hid_t H5I_get_file_id(hid_t obj_id, hbool_t app_ref); H5_DLL void *H5I_remove(hid_t id); H5_DLL void *H5I_remove_verify(hid_t id, H5I_type_t id_type); -H5_DLL void *H5I_search(H5I_type_t type, H5I_search_func_t func, void *key, hbool_t app_ref); +H5_DLL herr_t H5I_iterate(H5I_type_t type, H5I_search_func_t func, void *udata, hbool_t app_ref); H5_DLL int H5I_get_ref(hid_t id, hbool_t app_ref); H5_DLL int H5I_inc_ref(hid_t id, hbool_t app_ref); H5_DLL int H5I_dec_ref(hid_t id); diff --git a/src/H5MF.c b/src/H5MF.c index fce151e..f9ca256 100644 --- a/src/H5MF.c +++ b/src/H5MF.c @@ -1172,9 +1172,9 @@ HDfprintf(stderr, "%s: Leaving\n", FUNC); *------------------------------------------------------------------------- */ static herr_t -H5MF_sects_cb(const H5FS_section_info_t *_sect, void *_udata) +H5MF_sects_cb(H5FS_section_info_t *_sect, void *_udata) { - const H5MF_free_section_t *sect = (const H5MF_free_section_t *)_sect; + H5MF_free_section_t *sect = (H5MF_free_section_t *)_sect; H5MF_sect_iter_ud_t *udata = (H5MF_sect_iter_ud_t *)_udata; FUNC_ENTER_NOAPI_NOINIT_NOERR diff --git a/src/H5MFdbg.c b/src/H5MFdbg.c index bdc811f..d6fc5ce 100644 --- a/src/H5MFdbg.c +++ b/src/H5MFdbg.c @@ -99,9 +99,9 @@ typedef struct { *------------------------------------------------------------------------- */ static herr_t -H5MF_sects_debug_cb(const H5FS_section_info_t *_sect, void *_udata) +H5MF_sects_debug_cb(H5FS_section_info_t *_sect, void *_udata) { - const H5MF_free_section_t *sect = (const H5MF_free_section_t *)_sect; /* Section to dump info */ + H5MF_free_section_t *sect = (H5MF_free_section_t *)_sect; /* Section to dump info */ H5MF_debug_iter_ud_t *udata = (H5MF_debug_iter_ud_t *)_udata; /* User data for callbacks */ herr_t ret_value = SUCCEED; /* Return value */ diff --git a/src/H5O.c b/src/H5O.c index 5cefabc..c43236a 100644 --- a/src/H5O.c +++ b/src/H5O.c @@ -79,12 +79,12 @@ typedef struct { /********************/ static herr_t H5O_delete_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh); -static const H5O_obj_class_t *H5O_obj_class(const H5O_loc_t *loc, hid_t dxpl_id); static herr_t H5O_obj_type_real(H5O_t *oh, H5O_type_t *obj_type); static herr_t H5O_visit(hid_t loc_id, const char *obj_name, H5_index_t idx_type, H5_iter_order_t order, H5O_iterate_t op, void *op_data, hid_t lapl_id, hid_t dxpl_id); static herr_t H5O_get_hdr_info_real(const H5O_t *oh, H5O_hdr_info_t *hdr); +static const H5O_obj_class_t *H5O_obj_class_real(H5O_t *oh); /*********************/ @@ -2365,7 +2365,7 @@ H5O_obj_type_real(H5O_t *oh, H5O_type_t *obj_type) * *------------------------------------------------------------------------- */ -static const H5O_obj_class_t * +const H5O_obj_class_t * H5O_obj_class(const H5O_loc_t *loc, hid_t dxpl_id) { H5O_t *oh = NULL; /* Object header for location */ @@ -2402,7 +2402,7 @@ done: * *------------------------------------------------------------------------- */ -const H5O_obj_class_t * +static const H5O_obj_class_t * H5O_obj_class_real(H5O_t *oh) { size_t i; /* Local index variable */ diff --git a/src/H5Oainfo.c b/src/H5Oainfo.c index ff4cc5d..b207ea2 100644 --- a/src/H5Oainfo.c +++ b/src/H5Oainfo.c @@ -46,11 +46,11 @@ static herr_t H5O_ainfo_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, static herr_t H5O_ainfo_pre_copy_file(H5F_t *file_src, const void *mesg_src, hbool_t *deleted, const H5O_copy_t *cpy_info, void *udata); static void *H5O_ainfo_copy_file(H5F_t *file_src, void *mesg_src, - H5F_t *file_dst, hbool_t *recompute_size, H5O_copy_t *cpy_info, void *udata, - hid_t dxpl_id); + H5F_t *file_dst, hbool_t *recompute_size, unsigned *mesg_flags, + H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id); static herr_t H5O_ainfo_post_copy_file(const H5O_loc_t *src_oloc, - const void *mesg_src, H5O_loc_t *dst_oloc, void *mesg_dst, hid_t dxpl_id, - H5O_copy_t *cpy_info); + const void *mesg_src, H5O_loc_t *dst_oloc, void *mesg_dst, + unsigned *mesg_flags, hid_t dxpl_id, H5O_copy_t *cpy_info); static herr_t H5O_ainfo_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); @@ -403,7 +403,8 @@ H5O_ainfo_pre_copy_file(H5F_t UNUSED *file_src, const void UNUSED *native_src, */ static void * H5O_ainfo_copy_file(H5F_t *file_src, void *mesg_src, H5F_t *file_dst, - hbool_t UNUSED *recompute_size, H5O_copy_t *cpy_info, void UNUSED *udata, hid_t dxpl_id) + hbool_t UNUSED *recompute_size, unsigned UNUSED *mesg_flags, + H5O_copy_t *cpy_info, void UNUSED *udata, hid_t dxpl_id) { H5O_ainfo_t *ainfo_src = (H5O_ainfo_t *)mesg_src; H5O_ainfo_t *ainfo_dst = NULL; @@ -468,7 +469,8 @@ done: */ static herr_t H5O_ainfo_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, - H5O_loc_t *dst_oloc, void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info) + H5O_loc_t *dst_oloc, void *mesg_dst, unsigned UNUSED *mesg_flags, + hid_t dxpl_id, H5O_copy_t *cpy_info) { const H5O_ainfo_t *ainfo_src = (const H5O_ainfo_t *)mesg_src; herr_t ret_value = SUCCEED; /* Return value */ diff --git a/src/H5Oattr.c b/src/H5Oattr.c index 8cd243b..510d64f 100644 --- a/src/H5Oattr.c +++ b/src/H5Oattr.c @@ -61,6 +61,7 @@ static herr_t H5O_attr_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, #define H5O_SHARED_COPY_FILE_REAL H5O_attr_copy_file #define H5O_SHARED_POST_COPY_FILE H5O_attr_shared_post_copy_file #define H5O_SHARED_POST_COPY_FILE_REAL H5O_attr_post_copy_file +#undef H5O_SHARED_POST_COPY_FILE_UPD #define H5O_SHARED_DEBUG H5O_attr_shared_debug #define H5O_SHARED_DEBUG_REAL H5O_attr_debug #include "H5Oshared.h" /* Shared Object Header Message Callbacks */ diff --git a/src/H5Oattribute.c b/src/H5Oattribute.c index fbfc140..30ec732 100644 --- a/src/H5Oattribute.c +++ b/src/H5Oattribute.c @@ -135,9 +135,6 @@ typedef struct { /********************/ /* Local Prototypes */ /********************/ -static herr_t H5O_attr_iterate_real(hid_t loc_id, const H5O_loc_t *loc, - hid_t dxpl_id, H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, - hsize_t *last_attr, const H5A_attr_iter_op_t *attr_op, void *op_data); static htri_t H5O_attr_find_opened_attr(const H5O_loc_t *loc, H5A_t **attr, const char* name_to_open); @@ -437,8 +434,10 @@ H5O_attr_open_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/, unsigned sequence, if(NULL == (udata->attr = H5A_copy(NULL, (H5A_t *)mesg->native))) HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "unable to copy attribute") - /* Assign [somewhat arbitrary] creation order value, for older versions of the format */ - if(oh->version == H5O_VERSION_1) + /* Assign [somewhat arbitrary] creation order value, for older versions + * of the format or if creation order is not tracked */ + if(oh->version == H5O_VERSION_1 + || !(oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED)) udata->attr->shared->crt_idx = sequence; /* Stop iterating */ @@ -704,18 +703,23 @@ H5O_attr_find_opened_attr(const H5O_loc_t *loc, H5A_t **attr, const char* name_t HGOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, "can't get file serial number") /* Count all opened attributes */ - num_open_attr = H5F_get_obj_count(loc->file, H5F_OBJ_ATTR | H5F_OBJ_LOCAL, FALSE); + if(H5F_get_obj_count(loc->file, H5F_OBJ_ATTR | H5F_OBJ_LOCAL, FALSE, &num_open_attr) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't count opened attributes") /* Find out whether the attribute has been opened */ if(num_open_attr) { + size_t check_num_attr; /* Number of open attribute IDs */ size_t u; /* Local index variable */ /* Allocate space for the attribute ID list */ if(NULL == (attr_id_list = (hid_t *)H5MM_malloc(num_open_attr * sizeof(hid_t)))) - HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "unable to allocate memory for attribute ID list") + HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, "unable to allocate memory for attribute ID list") /* Retrieve the IDs of all opened attributes */ - H5F_get_obj_ids(loc->file, H5F_OBJ_ATTR | H5F_OBJ_LOCAL, num_open_attr, attr_id_list, FALSE); + if(H5F_get_obj_ids(loc->file, H5F_OBJ_ATTR | H5F_OBJ_LOCAL, num_open_attr, attr_id_list, FALSE, &check_num_attr) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get IDs of opened attributes") + if(check_num_attr != num_open_attr) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "open attribute count mismatch") /* Iterate over the attributes */ for(u = 0; u < num_open_attr; u++) { @@ -1260,7 +1264,7 @@ done: * *------------------------------------------------------------------------- */ -static herr_t +herr_t H5O_attr_iterate_real(hid_t loc_id, const H5O_loc_t *loc, hid_t dxpl_id, H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_attr, const H5A_attr_iter_op_t *attr_op, void *op_data) diff --git a/src/H5Ocopy.c b/src/H5Ocopy.c index dd649ff..7b812ec 100644 --- a/src/H5Ocopy.c +++ b/src/H5Ocopy.c @@ -34,10 +34,12 @@ /* Headers */ /***********/ #include "H5private.h" /* Generic Functions */ +#include "H5Aprivate.h" /* Attributes */ #include "H5Eprivate.h" /* Error handling */ #include "H5FLprivate.h" /* Free lists */ #include "H5Iprivate.h" /* IDs */ #include "H5HGprivate.h" /* Global Heaps */ +#include "H5FOprivate.h" /* File objects */ #include "H5Lprivate.h" /* Links */ #include "H5MFprivate.h" /* File memory management */ #include "H5MMprivate.h" /* Memory management */ @@ -54,6 +56,20 @@ /* Local Typedefs */ /******************/ +/* Key object for skiplist of committed datatypes */ +typedef struct H5O_copy_search_comm_dt_key_t { + H5T_t *dt; /* Datatype */ + unsigned long fileno; /* File number */ +} H5O_copy_search_comm_dt_key_t; + +/* Callback struct for building a list of committed datatypes */ +typedef struct H5O_copy_search_comm_dt_ud_t { + H5SL_t *dst_dt_list; /* Skip list of committed datatypes */ + H5G_loc_t *dst_root_loc; /* Starting location for iteration */ + H5O_loc_t obj_oloc; /* Object location (for attribute iteration callback) */ + hid_t dxpl_id; /* Dataset transfer property list id */ +} H5O_copy_search_comm_dt_ud_t; + /********************/ /* Package Typedefs */ @@ -65,14 +81,23 @@ /********************/ static herr_t H5O_copy_free_addrmap_cb(void *item, void *key, void *op_data); -static herr_t H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, +static herr_t H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out*/, hid_t dxpl_id, H5O_copy_t *cpy_info, H5O_type_t *obj_type, void **udata); -static herr_t H5O_copy_header(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, - hid_t dxpl_id, unsigned cpy_option); +static herr_t H5O_copy_header(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out*/, + hid_t dxpl_id, hid_t ocpypl_id); static herr_t H5O_copy_obj(H5G_loc_t *src_loc, H5G_loc_t *dst_loc, const char *dst_name, hid_t ocpypl_id, hid_t lcpl_id); static herr_t H5O_copy_obj_by_ref(H5O_loc_t *src_oloc, hid_t dxpl_id, H5O_loc_t *dst_oloc, H5G_loc_t *dst_root_loc, H5O_copy_t *cpy_info); +static herr_t H5O_copy_free_comm_dt_cb(void *item, void *key, void *op_data); +static int H5O_copy_comm_dt_cmp(const void *dt1, const void *dt2); +static herr_t H5O_copy_search_comm_dt_cb(hid_t group, const char *name, + const H5L_info_t *linfo, void *udata); +static htri_t H5O_copy_search_comm_dt(H5F_t *file_src, H5O_t *oh_src, + H5O_loc_t *oloc_dst/*in, out*/, hid_t dxpl_id, H5O_copy_t *cpy_info); +static herr_t H5O_copy_insert_comm_dt(H5F_t *file_src, H5O_t *oh_src, + H5O_loc_t *oloc_dst, hid_t dxpl_id, H5O_copy_t *cpy_info); + /*********************/ /* Package Variables */ @@ -81,6 +106,12 @@ static herr_t H5O_copy_obj_by_ref(H5O_loc_t *src_oloc, hid_t dxpl_id, /* Declare a free list to manage the H5O_addr_map_t struct */ H5FL_DEFINE(H5O_addr_map_t); +/* Declare a free list to manage the H5O_copy_search_comm_dt_key_t struct */ +H5FL_DEFINE(H5O_copy_search_comm_dt_key_t); + +/* Declare a free list to manage haddr_t variables */ +H5FL_DEFINE(haddr_t); + /*****************************/ /* Library Private Variables */ @@ -281,11 +312,19 @@ done: * Programmer: Peter Cao * May 30, 2005 * + * Modifications: + * Vailin Choi; Feb 2012 + * Bug fix for HDFFV-7853 + * When the object is opened, call the object's flush class action + * to ensure that cached data is flushed so that H5Ocopy will get + * the correct data. + * *------------------------------------------------------------------------- */ static herr_t -H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, - hid_t dxpl_id, H5O_copy_t *cpy_info, H5O_type_t *obj_type, void **udata) +H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out*/, + hid_t dxpl_id, H5O_copy_t *cpy_info, H5O_type_t *obj_type, + void **udata /*out*/) { H5O_addr_map_t *addr_map = NULL; /* Address mapping of object copied */ H5O_t *oh_src = NULL; /* Object header for source object */ @@ -316,19 +355,85 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, HDassert(oloc_dst->file); HDassert(cpy_info); + /* Get pointer to object class for this object */ + if((obj_class = H5O_obj_class(oloc_src, dxpl_id)) == NULL) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to determine object type") + + /* 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 */ + + 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; + H5G_name_reset(tmp_loc.path); + + /* Flush the object of this class */ + if(obj_class->flush && obj_class->flush(&tmp_loc, dxpl_id) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTFLUSH, FAIL, "unable to flush object") + } + /* Get source object header */ if(NULL == (oh_src = H5O_protect(oloc_src, dxpl_id, H5AC_READ))) HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header") - /* Get pointer to object class for this object */ - if(NULL == (obj_class = H5O_obj_class_real(oh_src))) - HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to determine object type") - /* Retrieve user data for particular type of object to copy */ if(obj_class->get_copy_file_udata && (NULL == (cpy_udata = (obj_class->get_copy_file_udata)()))) HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to retrieve copy user data") + /* If we are merging committed datatypes, check for a match in the destination + * file now */ + if(cpy_info->merge_comm_dt && obj_class->type == H5O_TYPE_NAMED_DATATYPE) { + unsigned long fileno_src; /* fileno for source file */ + unsigned long fileno_dst; /* fileno for destination file */ + htri_t merge; /* Whether we found a match in the destination file */ + + /* Check if the source and dest file are the same. If so, just return + * the source object address */ + H5F_GET_FILENO(oloc_src->file, fileno_src); + H5F_GET_FILENO(oloc_dst->file, fileno_dst); + if(fileno_src == fileno_dst) { + merge = TRUE; + oloc_dst->addr = oloc_src->addr; + } /* end if */ + else + /* Search for a matching committed datatype, building the list if + * necessary */ + if((merge = H5O_copy_search_comm_dt(oloc_src->file, oh_src, oloc_dst, dxpl_id, cpy_info)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't search for matching committed datatype") + + if(merge) { + /* Found a match, add to skip list and exit */ + /* Allocate space for the address mapping of the object copied */ + if(NULL == (addr_map = H5FL_MALLOC(H5O_addr_map_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Insert the address mapping for the found object into the copied + * list */ + addr_map->src_obj_pos.fileno = fileno_src; + addr_map->src_obj_pos.addr = oloc_src->addr; + addr_map->dst_addr = oloc_dst->addr; + addr_map->is_locked = TRUE; /* We've locked the object currently */ + addr_map->inc_ref_count = 0; /* Start with no additional ref counts to add */ + addr_map->obj_class = obj_class; + addr_map->udata = cpy_udata; + + /* Insert into skip list */ + if(H5SL_insert(cpy_info->map_list, addr_map, &(addr_map->src_obj_pos)) < 0) { + addr_map = H5FL_FREE(H5O_addr_map_t, addr_map); + HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert object into skip list") + } /* end if */ + + HGOTO_DONE(SUCCEED) + } /* end if */ + } /* end if */ + /* Flush any dirty messages in source object header to update the header chunks */ if(H5O_flush_msgs(oloc_src->file, oh_src) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTFLUSH, FAIL, "unable to flush object header messages") @@ -470,38 +575,33 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, /* copy this message into destination file */ if(copy_type->copy_file) { - htri_t is_shared; /* Whether message is shared */ hbool_t recompute_size; /* Whether copy_file callback created a shared message */ + unsigned mesg_flags; /* Message flags */ /* Decode the message if necessary. */ H5O_LOAD_NATIVE(oloc_src->file, dxpl_id, 0, oh_src, mesg_src, FAIL) + /* Get destination message flags, and unset shared and shareable + * flags. mesg_dst->flags will contain the original flags for now. + */ + mesg_flags = (unsigned)mesg_dst->flags & ~H5O_MSG_FLAG_SHARED + & ~H5O_MSG_FLAG_SHAREABLE; + /* Copy the source message */ recompute_size = FALSE; - if((mesg_dst->native = H5O_msg_copy_file(copy_type, - oloc_src->file, mesg_src->native, oloc_dst->file, - &recompute_size, cpy_info, cpy_udata, dxpl_id)) == NULL) + if((mesg_dst->native = H5O_msg_copy_file(copy_type, oloc_src->file, + mesg_src->native, oloc_dst->file, &recompute_size, + &mesg_flags, cpy_info, cpy_udata, dxpl_id)) == NULL) HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object header message") - /* Check if new message is shared */ - if((is_shared = H5O_msg_is_shared(copy_type->id, mesg_dst->native)) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to query message's shared status") - - /* In being copied, the message may have become shared or stopped - * being shared, set/unset its sharing flag. + /* Check if the sharing state changed, and recompute the size if so */ - if(is_shared && !(mesg_dst->flags & H5O_MSG_FLAG_SHARED)) { - mesg_dst->flags |= H5O_MSG_FLAG_SHARED; - - /* Recompute message size (mesg_dst->native is really shared) */ - recompute_size = TRUE; - } /* end if */ - else if(!is_shared && (mesg_dst->flags & H5O_MSG_FLAG_SHARED)) { - mesg_dst->flags &= ~H5O_MSG_FLAG_SHARED; - - /* Recompute message size (msg_dest->native is no longer shared) */ + if(!(mesg_flags & H5O_MSG_FLAG_SHARED) + != !(mesg_dst->flags & H5O_MSG_FLAG_SHARED)) recompute_size = TRUE; - } /* end if */ + + /* Set destination message flags */ + mesg_dst->flags = (uint8_t)mesg_flags; /* Recompute message's size */ /* (its sharing status or one of its components (for attributes) @@ -671,6 +771,13 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, oloc_dst->addr = addr_new; + /* If we are merging committed datatypes and this is a committed datatype, insert + * the copied datatype into the list of committed datatypes in the target file. + */ + if(cpy_info->merge_comm_dt && obj_class->type == H5O_TYPE_NAMED_DATATYPE) + if(H5O_copy_insert_comm_dt(oloc_src->file, oh_src, oloc_dst, dxpl_id, cpy_info) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't insert committed datatype into destination list") + /* Allocate space for the address mapping of the object copied */ if(NULL == (addr_map = H5FL_MALLOC(H5O_addr_map_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") @@ -686,8 +793,10 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, addr_map->udata = cpy_udata; /* Insert into skip list */ - if(H5SL_insert(cpy_info->map_list, addr_map, &(addr_map->src_obj_pos)) < 0) + if(H5SL_insert(cpy_info->map_list, addr_map, &(addr_map->src_obj_pos)) < 0) { + addr_map = H5FL_FREE(H5O_addr_map_t, addr_map); HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert object into skip list") + } /* end if */ /* "post copy" loop over messages, to fix up any messages which require a complete * object header for destination object @@ -716,17 +825,26 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, HDassert(copy_type); if(copy_type->post_copy_file && mesg_src->native) { + unsigned mesg_flags; /* Message flags */ + /* Sanity check destination message */ HDassert(mesg_dst->type == mesg_src->type); HDassert(mesg_dst->native); + /* Get destination message flags. mesg_dst->flags will contain the + * original flags for now. */ + mesg_flags = (unsigned)mesg_dst->flags; + /* the object header is needed in the post copy for shared message */ cpy_info->oh_dst = oh_dst; /* Perform "post copy" operation on message */ if((copy_type->post_copy_file)(oloc_src, mesg_src->native, oloc_dst, - mesg_dst->native, dxpl_id, cpy_info) < 0) + mesg_dst->native, &mesg_flags, dxpl_id, cpy_info) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to perform 'post copy' operation on message") + + /* Verify that the flags did not change */ + HDassert(mesg_flags == (unsigned) mesg_dst->flags); } /* end if */ } /* end for */ @@ -797,9 +915,9 @@ done: *------------------------------------------------------------------------- */ herr_t -H5O_copy_header_map(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, +H5O_copy_header_map(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out*/, hid_t dxpl_id, H5O_copy_t *cpy_info, hbool_t inc_depth, - H5O_type_t *obj_type, void **udata) + H5O_type_t *obj_type, void **udata /*out*/) { H5O_addr_map_t *addr_map = NULL; /* Address mapping of object copied */ H5_obj_t src_obj_pos; /* Position of source object */ @@ -937,9 +1055,13 @@ H5O_copy_free_addrmap_cb(void *_item, void UNUSED *key, void UNUSED *op_data) */ static herr_t H5O_copy_header(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, - hid_t dxpl_id, unsigned cpy_option) + hid_t dxpl_id, hid_t ocpypl_id) { H5O_copy_t cpy_info; /* Information for copying object */ + H5P_genplist_t *ocpy_plist; /* Object copy property list created */ + H5O_copy_dtype_merge_list_t *dt_list = NULL; /* List of datatype merge suggestions */ + H5O_mcdt_cb_info_t cb_info; /* Callback info struct */ + unsigned cpy_option = 0; /* Copy options */ herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI_NOINIT @@ -949,6 +1071,22 @@ H5O_copy_header(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, HDassert(H5F_addr_defined(oloc_src->addr)); HDassert(oloc_dst->file); + /* Get the copy property list */ + if(NULL == (ocpy_plist = (H5P_genplist_t *)H5I_object(ocpypl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list") + + /* Retrieve the copy parameters */ + if(H5P_get(ocpy_plist, H5O_CPY_OPTION_NAME, &cpy_option) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get object copy flag") + + /* Retrieve the marge committed datatype list */ + if(H5P_get(ocpy_plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &dt_list) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get merge committed datatype list") + + /* Get callback info */ + if(H5P_get(ocpy_plist, H5O_CPY_MCDT_SEARCH_CB_NAME, &cb_info) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get callback info") + /* Convert copy flags into copy struct */ HDmemset(&cpy_info, 0, sizeof(H5O_copy_t)); if((cpy_option & H5O_COPY_SHALLOW_HIERARCHY_FLAG) > 0) { @@ -968,9 +1106,18 @@ H5O_copy_header(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, cpy_info.copy_without_attr = TRUE; if((cpy_option & H5O_COPY_PRESERVE_NULL_FLAG) > 0) cpy_info.preserve_null = TRUE; + if((cpy_option & H5O_COPY_MERGE_COMMITTED_DTYPE_FLAG) > 0) + cpy_info.merge_comm_dt = TRUE; + + /* Add dt_list to copy struct */ + cpy_info.dst_dt_suggestion_list = dt_list; + + /* Add set callback information */ + cpy_info.mcdt_cb = cb_info.func; + cpy_info.mcdt_ud = cb_info.user_data; /* Create a skip list to keep track of which objects are copied */ - if((cpy_info.map_list = H5SL_create(H5SL_TYPE_OBJ, NULL)) == NULL) + if(NULL == (cpy_info.map_list = H5SL_create(H5SL_TYPE_OBJ, NULL))) HGOTO_ERROR(H5E_SLIST, H5E_CANTCREATE, FAIL, "cannot make skip list") /* copy the object from the source file to the destination file */ @@ -980,6 +1127,8 @@ H5O_copy_header(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, done: if(cpy_info.map_list) H5SL_destroy(cpy_info.map_list, H5O_copy_free_addrmap_cb, NULL); + if(cpy_info.dst_dt_list) + H5SL_destroy(cpy_info.dst_dt_list, H5O_copy_free_comm_dt_cb, NULL); FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_copy_header() */ @@ -1001,14 +1150,12 @@ static herr_t H5O_copy_obj(H5G_loc_t *src_loc, H5G_loc_t *dst_loc, const char *dst_name, hid_t ocpypl_id, hid_t lcpl_id) { - H5P_genplist_t *ocpy_plist=NULL; /* Object copy property list created */ - hid_t dxpl_id=H5AC_dxpl_id; H5G_name_t new_path; /* Copied object group hier. path */ H5O_loc_t new_oloc; /* Copied object object location */ H5G_loc_t new_loc; /* Group location of object copied */ H5F_t *cached_dst_file; /* Cached destination file */ - hbool_t entry_inserted=FALSE; /* Flag to indicate that the new entry was inserted into a group */ - unsigned cpy_option = 0; /* Copy options */ + hbool_t entry_inserted = FALSE; /* Flag to indicate that the new entry was inserted into a group */ + hid_t dxpl_id = H5AC_dxpl_id; /* DXPL for operation */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -1019,14 +1166,6 @@ H5O_copy_obj(H5G_loc_t *src_loc, H5G_loc_t *dst_loc, const char *dst_name, HDassert(dst_loc->oloc->file); HDassert(dst_name); - /* Get the copy property list */ - if(NULL == (ocpy_plist = (H5P_genplist_t *)H5I_object(ocpypl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list") - - /* Retrieve the copy parameters */ - if(H5P_get(ocpy_plist, H5O_CPY_OPTION_NAME, &cpy_option) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get object copy flag") - /* Set up copied object location to fill in */ new_loc.oloc = &new_oloc; new_loc.path = &new_path; @@ -1039,7 +1178,7 @@ H5O_copy_obj(H5G_loc_t *src_loc, H5G_loc_t *dst_loc, const char *dst_name, cached_dst_file = dst_loc->oloc->file; /* Copy the object from the source file to the destination file */ - if(H5O_copy_header(src_loc->oloc, &new_oloc, dxpl_id, cpy_option) < 0) + if(H5O_copy_header(src_loc->oloc, &new_oloc, dxpl_id, ocpypl_id) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object") /* Patch dst_loc. Again, this can be removed once oloc's point to shared @@ -1255,3 +1394,579 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_copy_expand_ref() */ + +/*------------------------------------------------------------------------- + * Function: H5O_copy_free_comm_dt_cb + * + * Purpose: Frees the merge committed dt skip list key and object. + * + * Return: SUCCEED (never fails) + * + * Programmer: Neil Fortner + * Oct 6 2011 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_copy_free_comm_dt_cb(void *item, void *_key, void UNUSED *op_data) +{ + haddr_t *addr = (haddr_t *)item; + H5O_copy_search_comm_dt_key_t *key = (H5O_copy_search_comm_dt_key_t *)_key; + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(addr); + HDassert(key); + HDassert(key->dt); + + key->dt = (H5T_t *)H5O_msg_free(H5O_DTYPE_ID, key->dt); + key = H5FL_FREE(H5O_copy_search_comm_dt_key_t, key); + addr = H5FL_FREE(haddr_t, addr); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5O_copy_free_comm_dt_cb */ + + +/*------------------------------------------------------------------------- + * Function: H5O_copy_comm_dt_cmp + * + * Purpose: Skiplist callback used to compare 2 keys for the merge + * committed dt list. Mostly a wrapper for H5T_cmp. + * + * Return: 0 if key1 and key2 are equal. + * <0 if key1 is less than key2. + * >0 if key1 is greater than key2. + * + * Programmer: Neil Fortner + * Oct 6 2011 + * + *------------------------------------------------------------------------- + */ +static int +H5O_copy_comm_dt_cmp(const void *_key1, const void *_key2) +{ + const H5O_copy_search_comm_dt_key_t *key1 = (const H5O_copy_search_comm_dt_key_t *)_key1; + const H5O_copy_search_comm_dt_key_t *key2 = (const H5O_copy_search_comm_dt_key_t *)_key2; + int ret_value = 0; + + FUNC_ENTER_NOAPI_NOINIT + + /* Check fileno. It is unlikely to be different so check if they are equal + * first so only one comparison needs to be made. */ + if(key1->fileno != key2->fileno) { + if(key1->fileno < key2->fileno) + HGOTO_DONE(-1) + if(key1->fileno > key2->fileno) + HGOTO_DONE(1) + } /* end if */ + + ret_value = H5T_cmp(key1->dt, key2->dt, FALSE); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_copy_comm_dt_cmp */ + + +/*------------------------------------------------------------------------- + * Function: H5O_copy_search_comm_dt_attr_cb + * + * Purpose: Callback for H5O_attr_iterate_real from + * H5O_copy_search_comm_dt_check. Checks if the attribute's + * datatype is committed. If it is, adds it to the merge + * committed dt skiplist present in udata if it does not match + * any already present. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Neil Fortner + * Nov 3 2011 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_copy_search_comm_dt_attr_cb(const H5A_t *attr, void *_udata) +{ + H5O_copy_search_comm_dt_ud_t *udata = (H5O_copy_search_comm_dt_ud_t *)_udata; + H5T_t *dt = NULL; /* Datatype */ + H5O_copy_search_comm_dt_key_t *key = NULL; /* Skiplist key */ + haddr_t *addr = NULL; /* Destination address */ + hbool_t obj_inserted = FALSE; /* Object inserted into skip list */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Sanity checks */ + HDassert(attr); + HDassert(udata); + HDassert(udata->dst_dt_list); + HDassert(H5F_addr_defined(udata->obj_oloc.addr)); + + /* Get attribute datatype */ + if(NULL == (dt = H5A_type(attr))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't get attribute datatype") + + /* Check if the datatype is committed and search the skip list if so */ + if(H5T_committed(dt)) { + /* Allocate key */ + if(NULL == (key = H5FL_MALLOC(H5O_copy_search_comm_dt_key_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Copy datatype into key */ + if(NULL == (key->dt = (H5T_t *)H5O_msg_copy(H5O_DTYPE_ID, dt, NULL))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to copy datatype message") + + /* Get datatype object fileno */ + H5F_GET_FILENO(udata->obj_oloc.file, key->fileno); + + if(!H5SL_search(udata->dst_dt_list, key)) { + /* Allocate destination address */ + if(NULL == (addr = H5FL_MALLOC(haddr_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Add the destination datatype to the skip list */ + *addr = ((H5O_shared_t *)(key->dt))->u.loc.oh_addr; + if(H5SL_insert(udata->dst_dt_list, addr, key) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert object into skip list") + obj_inserted = TRUE; + } /* end if */ + } /* end if */ + +done: + /* Release resources */ + if(!obj_inserted) { + if(key) { + if(key->dt) + key->dt = (H5T_t *)H5O_msg_free(H5O_DTYPE_ID, key->dt); + key = H5FL_FREE(H5O_copy_search_comm_dt_key_t, key); + } /* end if */ + if(addr) { + HDassert(ret_value < 0); + addr = H5FL_FREE(haddr_t, addr); + } /* end if */ + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_copy_search_comm_dt_attr_cb */ + + +/*------------------------------------------------------------------------- + * Function: H5O_copy_search_comm_dt_check + * + * Purpose: Check if the object at obj_oloc is or contains a reference + * to a committed datatype. If it does, adds it to the merge + * committed dt skiplist present in udata if it does not match + * any already present. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Neil Fortner + * Nov 3 2011 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_copy_search_comm_dt_check(H5O_loc_t *obj_oloc, + H5O_copy_search_comm_dt_ud_t *udata) +{ + H5O_copy_search_comm_dt_key_t *key = NULL; /* Skiplist key */ + haddr_t *addr = NULL; /* Destination address */ + hbool_t obj_inserted = FALSE; /* Object inserted into skip list */ + H5O_info_t oinfo; /* Object info */ + H5A_attr_iter_op_t attr_op; /* Attribute iteration operator */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Sanity checks */ + HDassert(obj_oloc); + HDassert(udata); + HDassert(udata->dst_dt_list); + HDassert(udata->dst_root_loc); + + /* Get the object's info */ + if(H5O_get_info(obj_oloc, udata->dxpl_id, TRUE, &oinfo) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to get object info") + + /* Check if the object is a datatype, a dataset using a committed + * datatype, or contains an attribute using a committed datatype */ + if(oinfo.type == H5O_TYPE_NAMED_DATATYPE) { + /* Allocate key */ + if(NULL == (key = H5FL_MALLOC(H5O_copy_search_comm_dt_key_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Read the destination datatype */ + if(NULL == (key->dt = (H5T_t *)H5O_msg_read(obj_oloc, H5O_DTYPE_ID, NULL, udata->dxpl_id))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't read DTYPE message") + + /* Get destination object fileno */ + H5F_GET_FILENO(obj_oloc->file, key->fileno); + + /* Check if the datatype is already present in the skip list */ + if(!H5SL_search(udata->dst_dt_list, key)) { + /* Allocate destination address */ + if(NULL == (addr = H5FL_MALLOC(haddr_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Add the destination datatype to the skip list */ + *addr = obj_oloc->addr; + if(H5SL_insert(udata->dst_dt_list, addr, key) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert object into skip list") + obj_inserted = TRUE; + } /* end if */ + } /* end if */ + else if(oinfo.type == H5O_TYPE_DATASET) { + /* Allocate key */ + if(NULL == (key = H5FL_MALLOC(H5O_copy_search_comm_dt_key_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Read the destination datatype */ + if(NULL == (key->dt = (H5T_t *)H5O_msg_read(obj_oloc, H5O_DTYPE_ID, NULL, udata->dxpl_id))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't read DTYPE message") + + /* Check if the datatype is committed and search the skip list if so + */ + if(H5T_committed(key->dt)) { + /* Get datatype object fileno */ + H5F_GET_FILENO(obj_oloc->file, key->fileno); + + if(!H5SL_search(udata->dst_dt_list, key)) { + /* Allocate destination address */ + if(NULL == (addr = H5FL_MALLOC(haddr_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Add the destination datatype to the skip list */ + *addr = ((H5O_shared_t *)(key->dt))->u.loc.oh_addr; + if(H5SL_insert(udata->dst_dt_list, addr, key) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert object into skip list") + obj_inserted = TRUE; + } /* end if */ + } /* end if */ + } /* end else */ + + /* Search within attributes */ + attr_op.op_type = H5A_ATTR_OP_LIB; + 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) + HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "error iterating over attributes"); + +done: + /* Release resources */ + if(!obj_inserted) { + if(key) { + if(key->dt) + key->dt = (H5T_t *)H5O_msg_free(H5O_DTYPE_ID, key->dt); + key = H5FL_FREE(H5O_copy_search_comm_dt_key_t, key); + } /* end if */ + if(addr) { + HDassert(ret_value < 0); + addr = H5FL_FREE(haddr_t, addr); + } /* end if */ + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_copy_search_comm_dt_check */ + + +/*------------------------------------------------------------------------- + * Function: H5O_copy_search_comm_dt_cb + * + * Purpose: H5G_visit callback to add committed datatypes to the merge + * committed dt skiplist. Mostly a wrapper for + * H5O_copy_search_comm_dt_check. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Neil Fortner + * Oct 6 2011 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_copy_search_comm_dt_cb(hid_t UNUSED group, const char *name, + const H5L_info_t *linfo, void *_udata) +{ + H5O_copy_search_comm_dt_ud_t *udata = (H5O_copy_search_comm_dt_ud_t *)_udata; /* Skip list of dtypes in dest file */ + H5G_loc_t obj_loc; /* Location of object */ + H5O_loc_t obj_oloc; /* Object's object location */ + H5G_name_t obj_path; /* Object's group hier. path */ + hbool_t obj_found = FALSE; /* Object at 'name' found */ + herr_t ret_value = H5_ITER_CONT; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Sanity checks */ + HDassert(name); + HDassert(linfo); + HDassert(udata); + HDassert(udata->dst_dt_list); + HDassert(udata->dst_root_loc); + + /* Check if this is a hard link */ + if(linfo->type == H5L_TYPE_HARD) { + /* Set up opened group location to fill in */ + obj_loc.oloc = &obj_oloc; + obj_loc.path = &obj_path; + H5G_loc_reset(&obj_loc); + + /* Find the object */ + if(H5G_loc_find(udata->dst_root_loc, name, &obj_loc/*out*/, H5P_LINK_ACCESS_DEFAULT, udata->dxpl_id) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, H5_ITER_ERROR, "object not found") + obj_found = TRUE; + + /* Check object and add to skip list if appropriate */ + if(H5O_copy_search_comm_dt_check(&obj_oloc, udata) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, H5_ITER_ERROR, "can't check object") + } /* end if */ + +done: + /* Release resources */ + if(obj_found && H5G_loc_free(&obj_loc) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, H5_ITER_ERROR, "can't free location") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_copy_search_comm_dt_cb */ + + +/*------------------------------------------------------------------------- + * Function: H5O_copy_search_comm_dt + * + * Purpose: Checks if the committed datatype present in oh_src matches any + * in the destination file, building the destination file + * skiplist as necessary. + * + * Return: TRUE if a match is found in the destination file + * - oloc_dst will contain the address + * FALSE if a match is not found + * Negative on failure + * + * Programmer: Neil Fortner + * Sep 27 2011 + * + *------------------------------------------------------------------------- + */ +static htri_t +H5O_copy_search_comm_dt(H5F_t *file_src, H5O_t *oh_src, + H5O_loc_t *oloc_dst/*in, out*/, hid_t dxpl_id, H5O_copy_t *cpy_info) +{ + H5O_copy_search_comm_dt_key_t *key = NULL; /* Skiplist key */ + haddr_t *dst_addr; /* Destination datatype address */ + H5G_loc_t dst_root_loc = {NULL, NULL}; /* Destination root group location */ + H5O_copy_search_comm_dt_ud_t udata; /* Group iteration user data */ + herr_t ret_value = FALSE; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Sanity checks */ + HDassert(oh_src); + HDassert(oloc_dst); + HDassert(oloc_dst->file); + HDassert(H5F_FILE_ID(oloc_dst->file) >= 0); + HDassert(cpy_info); + + /* Allocate key */ + if(NULL == (key = H5FL_MALLOC(H5O_copy_search_comm_dt_key_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Read the source datatype */ + if(NULL == (key->dt = (H5T_t *)H5O_msg_read_oh(file_src, dxpl_id, oh_src, H5O_DTYPE_ID, NULL))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't read DTYPE message") + + /* Get destination object fileno */ + H5F_GET_FILENO(oloc_dst->file, key->fileno); + + /* Check if the destination dtype list exists, create it if it does not */ + if(!cpy_info->dst_dt_list) { + /* Create the skip list */ + if(NULL == (cpy_info->dst_dt_list = H5SL_create(H5SL_TYPE_GENERIC, H5O_copy_comm_dt_cmp))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCREATE, FAIL, "can't create skip list for committed datatypes") + + /* Add suggested types to list, if they are present */ + if(cpy_info->dst_dt_suggestion_list) { + H5O_copy_dtype_merge_list_t *suggestion = cpy_info->dst_dt_suggestion_list; + H5G_loc_t obj_loc; /* Location of object */ + H5O_loc_t obj_oloc; /* Object's object location */ + H5G_name_t obj_path; /* Object's group hier. path */ + + /* Set up the root group in the destination file */ + if(NULL == (dst_root_loc.oloc = H5G_oloc(H5G_rootof(oloc_dst->file)))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location for root group") + if(NULL == (dst_root_loc.path = H5G_nameof(H5G_rootof(oloc_dst->file)))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get path for root group") + + /* Set up opened group location to fill in */ + obj_loc.oloc = &obj_oloc; + obj_loc.path = &obj_path; + H5G_loc_reset(&obj_loc); + + /* Build udata */ + udata.dst_dt_list = cpy_info->dst_dt_list; + udata.dst_root_loc = &dst_root_loc; + udata.obj_oloc.file = NULL; + udata.obj_oloc.addr = HADDR_UNDEF; + udata.dxpl_id = dxpl_id; + + /* Walk through the list of datatype suggestions */ + while(suggestion) { + /* Find the object */ + if(H5G_loc_find(&dst_root_loc, suggestion->path, &obj_loc/*out*/, H5P_LINK_ACCESS_DEFAULT, dxpl_id) < 0) + /* Ignore errors - i.e. suggestions not present in + * destination file */ + H5E_clear_stack(NULL); + else + /* Check object and add to skip list if appropriate */ + if(H5O_copy_search_comm_dt_check(&obj_oloc, &udata) < 0) { + if(H5G_loc_free(&obj_loc) < 0) + HERROR(H5E_OHDR, H5E_CANTRELEASE, "can't free location"); + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't check object") + } /* end if */ + + /* Free location */ + if(H5G_loc_free(&obj_loc) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "can't free location"); + + /* Advance the suggestion pointer */ + suggestion = suggestion->next; + } /* end while */ + } /* end if */ + } + + if(!cpy_info->dst_dt_list_complete) { + /* Search for the type in the destination file, and return its address + * if found, but only if the list is populated with and only with + * suggested types. We will search complete lists later. */ + if(cpy_info->dst_dt_suggestion_list + && NULL != (dst_addr = (haddr_t *)H5SL_search( + cpy_info->dst_dt_list, key))) { + oloc_dst->addr = *dst_addr; + ret_value = TRUE; + } /* end if */ + else { + H5O_mcdt_search_ret_t search_cb_ret = H5O_MCDT_SEARCH_CONT; + + /* Make callback to see if we should search destination file */ + if(cpy_info->mcdt_cb) + if((search_cb_ret = cpy_info->mcdt_cb(cpy_info->mcdt_ud)) == H5O_MCDT_SEARCH_ERROR) + HGOTO_ERROR(H5E_OHDR, H5E_CALLBACK, FAIL, "callback returned error") + + if(search_cb_ret == H5O_MCDT_SEARCH_CONT) { + /* Build the complete dst dt list */ + /* Set up the root group in the destination file, if necessary */ + if(!dst_root_loc.oloc) { + HDassert(!dst_root_loc.path); + if(NULL == (dst_root_loc.oloc = H5G_oloc(H5G_rootof(oloc_dst->file)))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location for root group") + if(NULL == (dst_root_loc.path = H5G_nameof(H5G_rootof(oloc_dst->file)))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get path for root group") + } /* end if */ + else + HDassert(dst_root_loc.path); + + /* Build udata. Note that this may be done twice in some cases, but + * it should be rare and should be cheaper on average than trying to + * keep track of whether it was done before. */ + udata.dst_dt_list = cpy_info->dst_dt_list; + udata.dst_root_loc = &dst_root_loc; + udata.obj_oloc.file = NULL; + udata.obj_oloc.addr = HADDR_UNDEF; + udata.dxpl_id = dxpl_id; + + /* Traverse the destination file, adding committed datatypes to the skip + * list */ + if(H5G_visit(H5F_FILE_ID(oloc_dst->file), "/", H5_INDEX_NAME, H5_ITER_NATIVE, H5O_copy_search_comm_dt_cb, &udata, H5P_LINK_ACCESS_DEFAULT, dxpl_id) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "object visitation failed") + cpy_info->dst_dt_list_complete = TRUE; + } /* end if */ + else + if(search_cb_ret != H5O_MCDT_SEARCH_STOP) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unknown return value for callback") + } /* end if */ + } /* end if */ + + /* Search for the type in the destination file, and return its address if + * found, but only if the list is complete */ + if(cpy_info->dst_dt_list_complete) { + if(NULL != (dst_addr = (haddr_t *)H5SL_search(cpy_info->dst_dt_list, key))) { + oloc_dst->addr = *dst_addr; + ret_value = TRUE; + } /* end if */ + } /* end if */ + +done: + if(key) { + if(key->dt) + key->dt = (H5T_t *)H5O_msg_free(H5O_DTYPE_ID, key->dt); + key = H5FL_FREE(H5O_copy_search_comm_dt_key_t, key); + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_copy_search_comm_dt */ + + +/*------------------------------------------------------------------------- + * Function: H5O_copy_insert_comm_dt + * + * Purpose: Insert the committed datatype at oloc_dst into the merge committed + * dt skiplist. The datatype must not be present already. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Neil Fortner + * Oct 6 2011 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_copy_insert_comm_dt(H5F_t *file_src, H5O_t *oh_src, H5O_loc_t *oloc_dst, + hid_t dxpl_id, H5O_copy_t *cpy_info) +{ + H5O_copy_search_comm_dt_key_t *key = NULL; /* Skiplist key */ + haddr_t *addr = NULL; /* Destination object address */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Sanity checks */ + HDassert(oh_src); + HDassert(oloc_dst); + HDassert(oloc_dst->file); + HDassert(oloc_dst->addr != HADDR_UNDEF); + HDassert(cpy_info); + HDassert(cpy_info->dst_dt_list); + + /* Allocate key */ + if(NULL == (key = H5FL_MALLOC(H5O_copy_search_comm_dt_key_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Read the datatype. Read from the source file because the destination + * object could be changed in the post-copy. */ + if(NULL == (key->dt = (H5T_t *)H5O_msg_read_oh(file_src, dxpl_id, oh_src, H5O_DTYPE_ID, NULL))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't read DTYPE message") + + /* Get destination object fileno */ + H5F_GET_FILENO(oloc_dst->file, key->fileno); + + /* Allocate destination address */ + if(NULL == (addr = H5FL_MALLOC(haddr_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Add the destination datatype to the skip list */ + *addr = oloc_dst->addr; + if(H5SL_insert(cpy_info->dst_dt_list, addr, key) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert object into skip list") + +done: + if(ret_value < 0) { + if(key) { + if(key->dt) + key->dt = (H5T_t *)H5O_msg_free(H5O_DTYPE_ID, key->dt); + key = H5FL_FREE(H5O_copy_search_comm_dt_key_t, key); + } /* end if */ + if(addr) + addr = H5FL_FREE(haddr_t, addr); + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_copy_insert_comm_dt */ + diff --git a/src/H5Odtype.c b/src/H5Odtype.c index 9ccb51b..1b602c7 100644 --- a/src/H5Odtype.c +++ b/src/H5Odtype.c @@ -43,6 +43,9 @@ static herr_t H5O_dtype_pre_copy_file(H5F_t *file_src, const void *mesg_src, static void *H5O_dtype_copy_file(H5F_t *file_src, const H5O_msg_class_t *mesg_type, void *native_src, H5F_t *file_dst, hbool_t *recompute_size, H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id); +static herr_t H5O_dtype_shared_post_copy_upd(const H5O_loc_t *src_oloc, + const void *mesg_src, H5O_loc_t *dst_oloc, void *mesg_dst, hid_t dxpl_id, + H5O_copy_t *cpy_info); static herr_t H5O_dtype_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); @@ -63,6 +66,7 @@ static herr_t H5O_dtype_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, #define H5O_SHARED_COPY_FILE_REAL H5O_dtype_copy_file #define H5O_SHARED_POST_COPY_FILE H5O_dtype_shared_post_copy_file #undef H5O_SHARED_POST_COPY_FILE_REAL +#define H5O_SHARED_POST_COPY_FILE_UPD H5O_dtype_shared_post_copy_upd #define H5O_SHARED_DEBUG H5O_dtype_shared_debug #define H5O_SHARED_DEBUG_REAL H5O_dtype_debug #include "H5Oshared.h" /* Shared Object Header Message Callbacks */ @@ -1575,6 +1579,40 @@ done: } /* end H5O_dtype_copy_file() */ +/*------------------------------------------------------------------------- + * Function: H5O_dtype_shared_post_copy_upd + * + * Purpose: Update a message after the shared message operations + * during the post-copy loop + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Neil Fortner + * November 8, 2011 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_dtype_shared_post_copy_upd(const H5O_loc_t UNUSED *src_oloc, + const void UNUSED *mesg_src, H5O_loc_t UNUSED *dst_oloc, void *mesg_dst, + hid_t UNUSED dxpl_id, H5O_copy_t UNUSED *cpy_info) +{ + H5T_t *dt_dst = (H5T_t *)mesg_dst; /* Destination datatype */ + + FUNC_ENTER_NOAPI_NOINIT + + if(dt_dst->sh_loc.type == H5O_SHARE_TYPE_COMMITTED) { + HDassert(H5T_committed(dt_dst)); + dt_dst->oloc.file = dt_dst->sh_loc.file; + dt_dst->oloc.addr = dt_dst->sh_loc.u.loc.oh_addr; + } /* end if */ + else + HDassert(!H5T_committed(dt_dst)); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5O_dtype_shared_post_copy_upd */ + + /*-------------------------------------------------------------------------- NAME H5O_dtype_debug diff --git a/src/H5Oefl.c b/src/H5Oefl.c index e4b21f0..3630cf4 100644 --- a/src/H5Oefl.c +++ b/src/H5Oefl.c @@ -36,8 +36,8 @@ static void *H5O_efl_copy(const void *_mesg, void *_dest); static size_t H5O_efl_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg); static herr_t H5O_efl_reset(void *_mesg); static void *H5O_efl_copy_file(H5F_t *file_src, void *mesg_src, - H5F_t *file_dst, hbool_t *recompute_size, H5O_copy_t *cpy_info, - void *udata, hid_t dxpl_id); + H5F_t *file_dst, hbool_t *recompute_size, unsigned *mesg_flags, + H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id); static herr_t H5O_efl_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); @@ -455,8 +455,8 @@ done: */ static void * H5O_efl_copy_file(H5F_t UNUSED *file_src, void *mesg_src, H5F_t *file_dst, - hbool_t UNUSED *recompute_size, H5O_copy_t UNUSED *cpy_info, - void UNUSED *_udata, hid_t dxpl_id) + hbool_t UNUSED *recompute_size, unsigned UNUSED *mesg_flags, + H5O_copy_t UNUSED *cpy_info, void UNUSED *_udata, hid_t dxpl_id) { H5O_efl_t *efl_src = (H5O_efl_t *) mesg_src; H5O_efl_t *efl_dst = NULL; diff --git a/src/H5Ofill.c b/src/H5Ofill.c index 9fa6108..f5569dc 100644 --- a/src/H5Ofill.c +++ b/src/H5Ofill.c @@ -63,6 +63,7 @@ static herr_t H5O_fill_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE *s #undef H5O_SHARED_COPY_FILE_REAL #define H5O_SHARED_POST_COPY_FILE H5O_fill_shared_post_copy_file #undef H5O_SHARED_POST_COPY_FILE_REAL +#undef H5O_SHARED_POST_COPY_FILE_UPD #define H5O_SHARED_DEBUG H5O_fill_shared_debug #define H5O_SHARED_DEBUG_REAL H5O_fill_debug #include "H5Oshared.h" /* Shared Object Header Message Callbacks */ @@ -95,6 +96,7 @@ static herr_t H5O_fill_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE *s #undef H5O_SHARED_POST_COPY_FILE #define H5O_SHARED_POST_COPY_FILE H5O_fill_new_shared_post_copy_file #undef H5O_SHARED_POST_COPY_FILE_REAL +#undef H5O_SHARED_POST_COPY_FILE_UPD #undef H5O_SHARED_DEBUG #define H5O_SHARED_DEBUG H5O_fill_new_shared_debug #undef H5O_SHARED_DEBUG_REAL diff --git a/src/H5Olayout.c b/src/H5Olayout.c index 8946d9b..4a4c88e 100644 --- a/src/H5Olayout.c +++ b/src/H5Olayout.c @@ -49,8 +49,8 @@ static herr_t H5O_layout_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, static herr_t H5O_layout_pre_copy_file(H5F_t *file_src, const void *mesg_src, hbool_t *deleted, const H5O_copy_t *cpy_info, void *_udata); static void *H5O_layout_copy_file(H5F_t *file_src, void *mesg_src, - H5F_t *file_dst, hbool_t *recompute_size, H5O_copy_t *cpy_info, - void *udata, hid_t dxpl_id); + H5F_t *file_dst, hbool_t *recompute_size, unsigned *mesg_flags, + H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id); static herr_t H5O_layout_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); @@ -807,8 +807,8 @@ done: */ static void * H5O_layout_copy_file(H5F_t *file_src, void *mesg_src, H5F_t *file_dst, - hbool_t UNUSED *recompute_size, H5O_copy_t *cpy_info, void *_udata, - hid_t dxpl_id) + hbool_t UNUSED *recompute_size, unsigned UNUSED *mesg_flags, + H5O_copy_t *cpy_info, void *_udata, hid_t dxpl_id) { H5D_copy_file_ud_t *udata = (H5D_copy_file_ud_t *)_udata; /* Dataset copying user data */ H5O_layout_t *layout_src = (H5O_layout_t *) mesg_src; diff --git a/src/H5Olinfo.c b/src/H5Olinfo.c index acdd1e1..e96483a 100644 --- a/src/H5Olinfo.c +++ b/src/H5Olinfo.c @@ -46,10 +46,11 @@ static herr_t H5O_linfo_free(void *_mesg); static herr_t H5O_linfo_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, void *_mesg); static void *H5O_linfo_copy_file(H5F_t *file_src, void *native_src, - H5F_t *file_dst, hbool_t *recompute_size, H5O_copy_t *cpy_info, - void *udata, hid_t dxpl_id); -static herr_t H5O_linfo_post_copy_file(const H5O_loc_t *parent_src_oloc, const void *mesg_src, H5O_loc_t *dst_oloc, - void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info); + H5F_t *file_dst, hbool_t *recompute_size, unsigned *mesg_flags, + H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id); +static herr_t H5O_linfo_post_copy_file(const H5O_loc_t *parent_src_oloc, + const void *mesg_src, H5O_loc_t *dst_oloc, void *mesg_dst, + unsigned *mesg_flags, hid_t dxpl_id, H5O_copy_t *cpy_info); static herr_t H5O_linfo_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); @@ -379,8 +380,8 @@ done: */ static void * H5O_linfo_copy_file(H5F_t UNUSED *file_src, void *native_src, H5F_t *file_dst, - hbool_t UNUSED *recompute_size, H5O_copy_t *cpy_info, void *_udata, - hid_t dxpl_id) + hbool_t UNUSED *recompute_size, unsigned UNUSED *mesg_flags, + H5O_copy_t *cpy_info, void *_udata, hid_t dxpl_id) { H5O_linfo_t *linfo_src = (H5O_linfo_t *) native_src; H5O_linfo_t *linfo_dst = NULL; @@ -501,7 +502,8 @@ done: */ static herr_t H5O_linfo_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, - H5O_loc_t *dst_oloc, void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info) + H5O_loc_t *dst_oloc, void *mesg_dst, unsigned UNUSED *mesg_flags, + hid_t dxpl_id, H5O_copy_t *cpy_info) { const H5O_linfo_t *linfo_src = (const H5O_linfo_t *)mesg_src; H5O_linfo_t *linfo_dst = (H5O_linfo_t *)mesg_dst; diff --git a/src/H5Olink.c b/src/H5Olink.c index ccc6d0e..88c9e28 100644 --- a/src/H5Olink.c +++ b/src/H5Olink.c @@ -49,10 +49,11 @@ static herr_t H5O_link_free(void *_mesg); static herr_t H5O_link_pre_copy_file(H5F_t *file_src, const void *mesg_src, hbool_t *deleted, const H5O_copy_t *cpy_info, void *udata); static void *H5O_link_copy_file(H5F_t *file_src, void *native_src, - H5F_t *file_dst, hbool_t *recompute_size, H5O_copy_t *cpy_info, void *udata, - hid_t dxpl_id); -static herr_t H5O_link_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, H5O_loc_t *dst_oloc, - void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info); + H5F_t *file_dst, hbool_t *recompute_size, unsigned *mesg_flags, + H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id); +static herr_t H5O_link_post_copy_file(const H5O_loc_t *src_oloc, + const void *mesg_src, H5O_loc_t *dst_oloc, void *mesg_dst, + unsigned *mesg_flags, hid_t dxpl_id, H5O_copy_t *cpy_info); static herr_t H5O_link_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); @@ -710,8 +711,8 @@ H5O_link_pre_copy_file(H5F_t UNUSED *file_src, const void UNUSED *native_src, */ static void * H5O_link_copy_file(H5F_t UNUSED *file_src, void *native_src, H5F_t UNUSED *file_dst, - hbool_t UNUSED *recompute_size, H5O_copy_t UNUSED *cpy_info, void UNUSED *udata, - hid_t UNUSED dxpl_id) + hbool_t UNUSED *recompute_size, unsigned UNUSED *mesg_flags, + H5O_copy_t UNUSED *cpy_info, void UNUSED *udata, hid_t UNUSED dxpl_id) { H5O_link_t *link_src = (H5O_link_t *)native_src; void *ret_value; /* Return value */ @@ -751,7 +752,8 @@ done: */ static herr_t H5O_link_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, - H5O_loc_t *dst_oloc, void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info) + H5O_loc_t *dst_oloc, void *mesg_dst, unsigned UNUSED *mesg_flags, + hid_t dxpl_id, H5O_copy_t *cpy_info) { const H5O_link_t *link_src = (const H5O_link_t *)mesg_src; H5O_link_t *link_dst = (H5O_link_t *)mesg_dst; diff --git a/src/H5Omessage.c b/src/H5Omessage.c index f12c835..c9a0997 100644 --- a/src/H5Omessage.c +++ b/src/H5Omessage.c @@ -1855,7 +1855,7 @@ done: void * H5O_msg_copy_file(const H5O_msg_class_t *type, H5F_t *file_src, void *native_src, H5F_t *file_dst, hbool_t *recompute_size, - H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id) + unsigned *mesg_flags, H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id) { void *ret_value; @@ -1873,7 +1873,7 @@ H5O_msg_copy_file(const H5O_msg_class_t *type, H5F_t *file_src, /* The copy_file callback will return an H5O_shared_t only if the message * to be copied is a committed datatype. */ - if(NULL == (ret_value = (type->copy_file)(file_src, native_src, file_dst, recompute_size, cpy_info, udata, dxpl_id))) + if(NULL == (ret_value = (type->copy_file)(file_src, native_src, file_dst, recompute_size, mesg_flags, cpy_info, udata, dxpl_id))) HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy object header message to file") done: @@ -1986,7 +1986,7 @@ H5O_copy_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx, HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to copy message to object header") /* Update the message flags */ - idx_msg->flags = mesg_flags; + idx_msg->flags = (uint8_t)mesg_flags; /* Mark the message as modified */ idx_msg->dirty = TRUE; diff --git a/src/H5Opkg.h b/src/H5Opkg.h index d7b8450..4108578 100644 --- a/src/H5Opkg.h +++ b/src/H5Opkg.h @@ -234,8 +234,8 @@ struct H5O_msg_class_t { herr_t (*set_share)(void*, const H5O_shared_t*); /* Set shared information */ htri_t (*can_share)(const void *); /* Is message allowed to be shared? */ herr_t (*pre_copy_file)(H5F_t *, const void *, hbool_t *, const H5O_copy_t *, void *); /*"pre copy" action when copying native value to file */ - void *(*copy_file)(H5F_t *, void *, H5F_t *, hbool_t *, H5O_copy_t *, void *, hid_t); /*copy native value to file */ - herr_t (*post_copy_file)(const H5O_loc_t *, const void *, H5O_loc_t *, void *, hid_t, H5O_copy_t *); /*"post copy" action when copying native value to file */ + void *(*copy_file)(H5F_t *, void *, H5F_t *, hbool_t *, unsigned *, H5O_copy_t *, void *, hid_t); /*copy native value to file */ + herr_t (*post_copy_file)(const H5O_loc_t *, const void *, H5O_loc_t *, void *, unsigned *, hid_t, H5O_copy_t *); /*"post copy" action when copying native value to file */ herr_t (*get_crt_index)(const void *, H5O_msg_crt_idx_t *); /* Get message's creation index */ herr_t (*set_crt_index)(void *, H5O_msg_crt_idx_t); /* Set message's creation index */ herr_t (*debug)(H5F_t*, hid_t, const void*, FILE*, int, int); @@ -325,6 +325,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 */ } H5O_obj_class_t; /* Node in skip list to map addresses from one file to another during object header copy */ @@ -530,7 +531,7 @@ H5_DLL herr_t H5O_msg_flush(H5F_t *f, H5O_t *oh, H5O_mesg_t *mesg); H5_DLL herr_t H5O_flush_msgs(H5F_t *f, H5O_t *oh); H5_DLL hid_t H5O_open_by_loc(const H5G_loc_t *obj_loc, hid_t lapl_id, hid_t dxpl_id, hbool_t app_ref); H5_DLL herr_t H5O_delete_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, H5O_mesg_t *mesg); -H5_DLL const H5O_obj_class_t *H5O_obj_class_real(H5O_t *oh); +H5_DLL const H5O_obj_class_t * H5O_obj_class(const H5O_loc_t *loc, hid_t dxpl_id); H5_DLL int H5O_link_oh(H5F_t *f, int adjust, hid_t dxpl_id, H5O_t *oh, hbool_t *deleted); H5_DLL herr_t H5O_inc_rc(H5O_t *oh); H5_DLL herr_t H5O_dec_rc(H5O_t *oh); @@ -552,7 +553,7 @@ H5_DLL herr_t H5O_msg_remove_real(H5F_t *f, H5O_t *oh, const H5O_msg_class_t *ty int sequence, H5O_operator_t op, void *op_data, hbool_t adj_link, hid_t dxpl_id); H5_DLL void *H5O_msg_copy_file(const H5O_msg_class_t *type, H5F_t *file_src, void *mesg_src, H5F_t *file_dst, hbool_t *recompute_size, - H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id); + unsigned *mesg_flags, H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id); H5_DLL herr_t H5O_msg_iterate_real(H5F_t *f, H5O_t *oh, const H5O_msg_class_t *type, const H5O_mesg_operator_t *op, void *op_data, hid_t dxpl_id); @@ -589,10 +590,12 @@ H5_DLL herr_t H5O_shared_link(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, const H5O_msg_class_t *mesg_type, H5O_shared_t *sh_mesg); H5_DLL herr_t H5O_shared_copy_file(H5F_t *file_src, H5F_t *file_dst, const H5O_msg_class_t *mesg_type, const void *_native_src, void *_native_dst, - hbool_t *recompute_size, H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id); + hbool_t *recompute_size, unsigned *mesg_flags, H5O_copy_t *cpy_info, + void *udata, hid_t dxpl_id); H5_DLL herr_t H5O_shared_post_copy_file (H5F_t *f, const H5O_msg_class_t *mesg_type, const H5O_shared_t *shared_src, - H5O_shared_t *shared_dst, hid_t dxpl_id, H5O_copy_t *cpy_info); + H5O_shared_t *shared_dst, unsigned *mesg_flags, hid_t dxpl_id, + H5O_copy_t *cpy_info); H5_DLL herr_t H5O_shared_debug(const H5O_shared_t *mesg, FILE *stream, int indent, int fwidth); diff --git a/src/H5Opline.c b/src/H5Opline.c index 89ce865..f626106 100644 --- a/src/H5Opline.c +++ b/src/H5Opline.c @@ -61,6 +61,7 @@ static herr_t H5O_pline_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, #undef H5O_SHARED_COPY_FILE_REAL #define H5O_SHARED_POST_COPY_FILE H5O_pline_shared_post_copy_file #undef H5O_SHARED_POST_COPY_FILE_REAL +#undef H5O_SHARED_POST_COPY_FILE_UPD #define H5O_SHARED_DEBUG H5O_pline_shared_debug #define H5O_SHARED_DEBUG_REAL H5O_pline_debug #include "H5Oshared.h" /* Shared Object Header Message Callbacks */ diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h index c5074f9..36ba8a4 100644 --- a/src/H5Oprivate.h +++ b/src/H5Oprivate.h @@ -99,7 +99,9 @@ typedef struct H5O_t H5O_t; #endif /* H5O_ENABLE_BAD_MESG_COUNT */ /* ========= Object Copy properties ============ */ -#define H5O_CPY_OPTION_NAME "copy object" /* Copy options */ +#define H5O_CPY_OPTION_NAME "copy object" /* Copy options */ +#define H5O_CPY_MERGE_COMM_DT_LIST_NAME "merge committed dtype list" /* List of datatype paths to search in the dest file for merging */ +#define H5O_CPY_MCDT_SEARCH_CB_NAME "committed dtype list search" /* Callback function when the search for a matching committed datatype is complete */ /* If the module using this macro is allowed access to the private variables, access them directly */ #ifdef H5O_PACKAGE @@ -133,6 +135,18 @@ typedef struct H5O_loc_t { * its file's count of open objects. */ } H5O_loc_t; +/* Typedef for linked list of datatype merge suggestions */ +typedef struct H5O_copy_dtype_merge_list_t { + char *path; /* Path to datatype in destination file */ + struct H5O_copy_dtype_merge_list_t *next; /* Next object in list */ +} H5O_copy_dtype_merge_list_t; + +/* Structure for callback property before searching the global list of committed datatypes at destination */ +typedef struct H5O_mcdt_cb_info_t { + H5O_mcdt_search_cb_t func; + void *user_data; +} H5O_mcdt_cb_info_t; + /* Settings/flags for copying an object */ typedef struct H5O_copy_t { hbool_t copy_shallow; /* Flag to perform shallow hierarchy copy */ @@ -141,10 +155,16 @@ typedef struct H5O_copy_t { hbool_t expand_ref; /* Flag to expand object references */ hbool_t copy_without_attr; /* Flag to not copy attributes */ hbool_t preserve_null; /* Flag to not delete NULL messages */ + hbool_t merge_comm_dt; /* Flag to merge committed datatypes in dest file */ + H5O_copy_dtype_merge_list_t *dst_dt_suggestion_list; /* Suggestions for merging committed datatypes */ int curr_depth; /* Current depth in hierarchy copied */ int max_depth; /* Maximum depth in hierarchy to copy */ H5SL_t *map_list; /* Skip list to hold address mappings */ + H5SL_t *dst_dt_list; /* Skip list to hold committed datatypes in dest file */ + hbool_t dst_dt_list_complete; /* Whether the destination datatype list is complete (i.e. not only populated with "suggestions" from H5Padd_merge_committed_dtype_path) */ H5O_t *oh_dst; /* The destination object header */ + H5O_mcdt_search_cb_t mcdt_cb; /* The callback to invoke before searching the global list of committed datatypes at destination */ + void *mcdt_ud; /* User data passed to callback */ } H5O_copy_t; /* Header message IDs */ diff --git a/src/H5Opublic.h b/src/H5Opublic.h index 546508a..4fee641 100644 --- a/src/H5Opublic.h +++ b/src/H5Opublic.h @@ -43,7 +43,8 @@ #define H5O_COPY_EXPAND_REFERENCE_FLAG (0x0008u) /* Copy objects that are pointed by references */ #define H5O_COPY_WITHOUT_ATTR_FLAG (0x0010u) /* Copy object without copying attributes */ #define H5O_COPY_PRESERVE_NULL_FLAG (0x0020u) /* Copy NULL messages (empty space) */ -#define H5O_COPY_ALL (0x003Fu) /* All object copying flags (for internal checking) */ +#define H5O_COPY_MERGE_COMMITTED_DTYPE_FLAG (0x0040u) /* Merge committed datatypes in dest file */ +#define H5O_COPY_ALL (0x007Fu) /* All object copying flags (for internal checking) */ /* Flags for shared message indexes. * Pass these flags in using the mesg_type_flags parameter in @@ -131,6 +132,14 @@ typedef uint32_t H5O_msg_crt_idx_t; typedef herr_t (*H5O_iterate_t)(hid_t obj, const char *name, const H5O_info_t *info, void *op_data); +typedef enum H5O_mcdt_search_ret_t { + H5O_MCDT_SEARCH_ERROR = -1, /* Abort H5Ocopy */ + H5O_MCDT_SEARCH_CONT, /* Continue the global search of all committed datatypes in the destination file */ + H5O_MCDT_SEARCH_STOP /* Stop the search, but continue copying. The committed datatype will be copied but not merged. */ +} H5O_mcdt_search_ret_t; + +/* Callback to invoke when completing the search for a matching committed datatype from the committed dtype list */ +typedef H5O_mcdt_search_ret_t (*H5O_mcdt_search_cb_t)(void *op_data); /********************/ /* Public Variables */ diff --git a/src/H5Osdspace.c b/src/H5Osdspace.c index 8ae73f7..905c4e9 100644 --- a/src/H5Osdspace.c +++ b/src/H5Osdspace.c @@ -55,6 +55,7 @@ static herr_t H5O_sdspace_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, #undef H5O_SHARED_COPY_FILE_REAL #define H5O_SHARED_POST_COPY_FILE H5O_sdspace_shared_post_copy_file #undef H5O_SHARED_POST_COPY_FILE_REAL +#undef H5O_SHARED_POST_COPY_FILE_UPD #define H5O_SHARED_DEBUG H5O_sdspace_shared_debug #define H5O_SHARED_DEBUG_REAL H5O_sdspace_debug #include "H5Oshared.h" /* Shared Object Header Message Callbacks */ diff --git a/src/H5Oshared.c b/src/H5Oshared.c index 4cc30e8..c29e2c7 100644 --- a/src/H5Oshared.c +++ b/src/H5Oshared.c @@ -589,8 +589,8 @@ done: herr_t H5O_shared_copy_file(H5F_t *file_src, H5F_t *file_dst, const H5O_msg_class_t *mesg_type, const void *_native_src, void *_native_dst, - hbool_t UNUSED *recompute_size, H5O_copy_t *cpy_info, void UNUSED *udata, - hid_t dxpl_id) + hbool_t UNUSED *recompute_size, unsigned *mesg_flags, H5O_copy_t *cpy_info, + void UNUSED *udata, hid_t dxpl_id) { const H5O_shared_t *shared_src = (const H5O_shared_t *)_native_src; /* Alias to shared info in native source */ H5O_shared_t *shared_dst = (H5O_shared_t *)_native_dst; /* Alias to shared info in native destination message */ @@ -621,16 +621,18 @@ H5O_shared_copy_file(H5F_t *file_src, H5F_t *file_dst, /* Set copied metadata tag */ H5_BEGIN_TAG(dxpl_id, H5AC__COPIED_TAG, FAIL); - if(H5SM_try_share(file_dst, dxpl_id, NULL, H5SM_DEFER, mesg_type->id, _native_dst, NULL) < 0) + if(H5SM_try_share(file_dst, dxpl_id, NULL, H5SM_DEFER, mesg_type->id, _native_dst, mesg_flags) < 0) HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to determine if message should be shared") /* Reset metadata tag */ H5_END_TAG(FAIL); } /* end if */ - else + else { /* Mark the message as committed - as it will be committed in post copy */ H5O_UPDATE_SHARED(shared_dst, H5O_SHARE_TYPE_COMMITTED, file_dst, mesg_type->id, 0, HADDR_UNDEF) + *mesg_flags |= H5O_MSG_FLAG_SHARED; + } /* end else */ done: FUNC_LEAVE_NOAPI(ret_value) @@ -657,8 +659,8 @@ done: */ herr_t H5O_shared_post_copy_file(H5F_t *f, const H5O_msg_class_t *mesg_type, - const H5O_shared_t *shared_src, H5O_shared_t *shared_dst, hid_t dxpl_id, - H5O_copy_t *cpy_info) + const H5O_shared_t *shared_src, H5O_shared_t *shared_dst, + unsigned *mesg_flags, hid_t dxpl_id, H5O_copy_t *cpy_info) { herr_t ret_value = SUCCEED; /* Return value */ @@ -675,6 +677,7 @@ H5O_shared_post_copy_file(H5F_t *f, const H5O_msg_class_t *mesg_type, H5O_loc_t src_oloc; /* Copy the shared object from source to destination */ + H5O_loc_reset(&dst_oloc); dst_oloc.file = f; src_oloc.file = shared_src->file; src_oloc.addr = shared_src->u.loc.oh_addr; @@ -688,7 +691,7 @@ H5O_shared_post_copy_file(H5F_t *f, const H5O_msg_class_t *mesg_type, else /* Share the message */ if(H5SM_try_share(f, dxpl_id, NULL, H5SM_WAS_DEFERRED, mesg_type->id, - shared_dst, NULL) < 0) + shared_dst, mesg_flags) < 0) HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "can't share message") done: diff --git a/src/H5Oshared.h b/src/H5Oshared.h index ddacc25..3ec5709 100644 --- a/src/H5Oshared.h +++ b/src/H5Oshared.h @@ -320,7 +320,8 @@ done: */ static H5_inline void * H5O_SHARED_COPY_FILE(H5F_t *file_src, void *_native_src, H5F_t *file_dst, - hbool_t *recompute_size, H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id) + hbool_t *recompute_size, unsigned *mesg_flags, H5O_copy_t *cpy_info, + void *udata, hid_t dxpl_id) { void *dst_mesg = NULL; /* Destination message */ void *ret_value; /* Return value */ @@ -348,8 +349,8 @@ H5O_SHARED_COPY_FILE(H5F_t *file_src, void *_native_src, H5F_t *file_dst, HDmemset(dst_mesg, 0, sizeof(H5O_shared_t)); /* Handle sharing destination message */ - if(H5O_shared_copy_file(file_src, file_dst, H5O_SHARED_TYPE, - _native_src, dst_mesg, recompute_size, cpy_info, udata, dxpl_id) < 0) + if(H5O_shared_copy_file(file_src, file_dst, H5O_SHARED_TYPE, _native_src, + dst_mesg, recompute_size, mesg_flags, cpy_info, udata, dxpl_id) < 0) HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, NULL, "unable to determine if message should be shared") /* Set return value */ @@ -383,7 +384,8 @@ done: */ static H5_inline herr_t H5O_SHARED_POST_COPY_FILE(const H5O_loc_t *oloc_src, const void *mesg_src, - H5O_loc_t *oloc_dst, void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info) + H5O_loc_t *oloc_dst, void *mesg_dst, unsigned *mesg_flags, hid_t dxpl_id, + H5O_copy_t *cpy_info) { const H5O_shared_t *shared_src = (const H5O_shared_t *)mesg_src; /* Alias to shared info in native source */ H5O_shared_t *shared_dst = (H5O_shared_t *)mesg_dst; /* Alias to shared info in native destination */ @@ -405,7 +407,7 @@ H5O_SHARED_POST_COPY_FILE(const H5O_loc_t *oloc_src, const void *mesg_src, #endif /* H5O_SHARED_POST_COPY_FILE */ #ifdef H5O_SHARED_POST_COPY_FILE_REAL - /* Call native message's copy file callback to copy the message */ + /* Call native message's post copy file callback to copy the message */ if(H5O_SHARED_POST_COPY_FILE_REAL(oloc_src, mesg_src, oloc_dst, mesg_dst, dxpl_id, cpy_info) <0 ) HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy native message to another file") #endif /* H5O_SHARED_POST_COPY_FILE_REAL */ @@ -414,9 +416,16 @@ H5O_SHARED_POST_COPY_FILE(const H5O_loc_t *oloc_src, const void *mesg_src, * production if the DEFER pass determined it will not be shared; debug mode * verifies that it is indeed the case */ if(H5O_shared_post_copy_file(oloc_dst->file, H5O_SHARED_TYPE, - shared_src, shared_dst, dxpl_id, cpy_info) < 0) + shared_src, shared_dst, mesg_flags, dxpl_id, cpy_info) < 0) HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to fix shared message in post copy") +#ifdef H5O_SHARED_POST_COPY_FILE_UPD + /* Call native message's post copy file update callback to update the + * message */ + if(H5O_SHARED_POST_COPY_FILE_UPD(oloc_src, mesg_src, oloc_dst, mesg_dst, dxpl_id, cpy_info) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to update native message") +#endif /* H5O_SHARED_POST_COPY_FILE_UPD */ + /* Make sure that if the the source or destination is committed, both are * committed */ HDassert((shared_src->type == H5O_SHARE_TYPE_COMMITTED) diff --git a/src/H5Ostab.c b/src/H5Ostab.c index 3e9a5b5..a28d8ea 100644 --- a/src/H5Ostab.c +++ b/src/H5Ostab.c @@ -44,10 +44,11 @@ static size_t H5O_stab_size(const H5F_t *f, hbool_t disable_shared, const void * static herr_t H5O_stab_free(void *_mesg); static herr_t H5O_stab_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, void *_mesg); static void *H5O_stab_copy_file(H5F_t *file_src, void *native_src, - H5F_t *file_dst, hbool_t *recompute_size, H5O_copy_t *cpy_info, void *_udata, - hid_t dxpl_id); -static herr_t H5O_stab_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, H5O_loc_t *dst_oloc, - void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info); + H5F_t *file_dst, hbool_t *recompute_size, unsigned *mesg_flags, + H5O_copy_t *cpy_info, void *_udata, hid_t dxpl_id); +static herr_t H5O_stab_post_copy_file(const H5O_loc_t *src_oloc, + const void *mesg_src, H5O_loc_t *dst_oloc, void *mesg_dst, + unsigned *mesg_flags, hid_t dxpl_id, H5O_copy_t *cpy_info); static herr_t H5O_stab_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); @@ -307,8 +308,8 @@ done: */ static void * H5O_stab_copy_file(H5F_t *file_src, void *native_src, H5F_t *file_dst, - hbool_t UNUSED *recompute_size, H5O_copy_t UNUSED *cpy_info, void *_udata, - hid_t dxpl_id) + hbool_t UNUSED *recompute_size, unsigned UNUSED *mesg_flags, + H5O_copy_t UNUSED *cpy_info, void *_udata, hid_t dxpl_id) { H5O_stab_t *stab_src = (H5O_stab_t *) native_src; H5O_stab_t *stab_dst = NULL; @@ -370,8 +371,9 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5O_stab_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, H5O_loc_t *dst_oloc, - void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info) +H5O_stab_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, + H5O_loc_t *dst_oloc, void *mesg_dst, unsigned UNUSED *mesg_flags, + hid_t dxpl_id, H5O_copy_t *cpy_info) { const H5O_stab_t *stab_src = (const H5O_stab_t *)mesg_src; H5O_stab_t *stab_dst = (H5O_stab_t *)mesg_dst; diff --git a/src/H5Ostorage.c b/src/H5Ostorage.c index c23b54b..8d99231 100644 --- a/src/H5Ostorage.c +++ b/src/H5Ostorage.c @@ -57,8 +57,8 @@ static herr_t H5O_storage_free(void *_mesg); static herr_t H5O_storage_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, void *_mesg); static void *H5O_storage_copy_file(H5F_t *file_src, void *mesg_src, - H5F_t *file_dst, hbool_t *recompute_size, H5O_copy_t *cpy_info, - void *udata, hid_t dxpl_id); + H5F_t *file_dst, hbool_t *recompute_size, unsigned UNUSED *mesg_flags, + H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id); static herr_t H5O_storage_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); @@ -522,8 +522,8 @@ done: */ static void * H5O_storage_copy_file(H5F_t *file_src, void *mesg_src, H5F_t *file_dst, - hbool_t UNUSED *recompute_size, H5O_copy_t *cpy_info, void *_udata, - hid_t dxpl_id) + hbool_t UNUSED *recompute_size, unsigned UNUSED *mesg_flags, + H5O_copy_t *cpy_info, void *_udata, hid_t dxpl_id) { H5D_copy_file_ud_t *udata = (H5D_copy_file_ud_t *)_udata; /* Dataset copying user data */ H5O_storage_t *storage_src = (H5O_storage_t *)mesg_src; diff --git a/src/H5Pdcpl.c b/src/H5Pdcpl.c index 9ea4f7f..c39e224 100644 --- a/src/H5Pdcpl.c +++ b/src/H5Pdcpl.c @@ -393,7 +393,7 @@ H5P_dcrt_layout_cmp(const void *_layout1, const void *_layout2, size_t UNUSED si /* Sanity check */ HDassert(layout1); - HDassert(layout1); + HDassert(layout2); HDassert(size == sizeof(H5O_layout_t)); /* Check for different layout type */ diff --git a/src/H5Pfapl.c b/src/H5Pfapl.c index c3371c9..7f72c85 100644 --- a/src/H5Pfapl.c +++ b/src/H5Pfapl.c @@ -40,6 +40,7 @@ #include "H5Fprivate.h" /* Files */ #include "H5FDprivate.h" /* File drivers */ #include "H5Iprivate.h" /* IDs */ +#include "H5MMprivate.h" /* Memory Management */ #include "H5Ppkg.h" /* Property lists */ /* Includes needed to set as default file driver */ @@ -122,6 +123,12 @@ /* Definition for external file cache size */ #define H5F_ACS_EFC_SIZE_SIZE sizeof(unsigned) #define H5F_ACS_EFC_SIZE_DEF 0 +/* Definition of pointer to initial file image info */ +#define H5F_ACS_FILE_IMAGE_INFO_SIZE sizeof(H5FD_file_image_info_t) +#define H5F_ACS_FILE_IMAGE_INFO_DEF H5FD_DEFAULT_FILE_IMAGE_INFO +#define H5F_ACS_FILE_IMAGE_INFO_DEL H5P_file_image_info_del +#define H5F_ACS_FILE_IMAGE_INFO_COPY H5P_file_image_info_copy +#define H5F_ACS_FILE_IMAGE_INFO_CLOSE H5P_file_image_info_close /******************/ @@ -149,6 +156,10 @@ static herr_t H5P_facc_reg_prop(H5P_genclass_t *pclass); static herr_t H5P_facc_create(hid_t fapl_id, void *copy_data); static herr_t H5P_facc_copy(hid_t new_plist_t, hid_t old_plist_t, void *copy_data); +/* File image info property callbacks */ +static herr_t H5P_file_image_info_del(hid_t prop_id, const char *name, size_t size, void *value); +static herr_t H5P_file_image_info_copy(const char *name, size_t size, void *value); +static herr_t H5P_file_image_info_close(const char *name, size_t size, void *value); /*********************/ /* Package Variables */ @@ -215,6 +226,7 @@ H5P_facc_reg_prop(H5P_genclass_t *pclass) hbool_t latest_format = H5F_ACS_LATEST_FORMAT_DEF; /* Default setting for "use the latest version of the format" flag */ hbool_t want_posix_fd = H5F_ACS_WANT_POSIX_FD_DEF; /* Default setting for retrieving 'handle' from core VFD */ unsigned efc_size = H5F_ACS_EFC_SIZE_DEF; /* Default external file cache size */ + H5FD_file_image_info_t file_image_info = H5F_ACS_FILE_IMAGE_INFO_DEF; /* Default file image info and callbacks */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -300,6 +312,10 @@ H5P_facc_reg_prop(H5P_genclass_t *pclass) if(H5P_register_real(pclass, H5F_ACS_EFC_SIZE_NAME, H5F_ACS_EFC_SIZE_SIZE, &efc_size, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + /* Register the initial file image info */ + if(H5P_register_real(pclass, H5F_ACS_FILE_IMAGE_INFO_NAME, H5F_ACS_FILE_IMAGE_INFO_SIZE, &file_image_info, NULL, NULL, NULL, H5F_ACS_FILE_IMAGE_INFO_DEL, H5F_ACS_FILE_IMAGE_INFO_COPY, NULL, H5F_ACS_FILE_IMAGE_INFO_CLOSE) < 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() */ @@ -2101,3 +2117,484 @@ done: FUNC_LEAVE_API(ret_value) } /* end H5Pget_elink_file_cache_size() */ + +/*------------------------------------------------------------------------- + * Function: H5Pset_file_image + * + * Purpose: Sets the initial file image. Some file drivers can initialize + * the starting data in a file from a buffer. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Jacob Gruber + * Thurday, August 11, 2011 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pset_file_image(hid_t fapl_id, void *buf_ptr, size_t buf_len) +{ + H5P_genplist_t *fapl; /* Property list pointer */ + H5FD_file_image_info_t image_info; /* File image info */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE3("e", "i*xz", fapl_id, buf_ptr, buf_len); + + /* validate parameters */ + if(!(((buf_ptr == NULL) && (buf_len == 0)) || ((buf_ptr != NULL) && (buf_len > 0)))) + HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "inconsistant buf_ptr and buf_len"); + + /* Get the plist structure */ + if(NULL == (fapl = H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Get old image info */ + if(H5P_get(fapl, H5F_ACS_FILE_IMAGE_INFO_NAME, &image_info) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get old file image pointer") + + /* Release previous buffer, if it exists */ + if(image_info.buffer != NULL) { + if(image_info.callbacks.image_free) { + if(SUCCEED != image_info.callbacks.image_free(image_info.buffer, H5FD_FILE_IMAGE_OP_PROPERTY_LIST_SET, image_info.callbacks.udata)) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "image_free callback failed") + } /* end if */ + else + H5MM_xfree(image_info.buffer); + } /* end if */ + + /* Update struct */ + if(buf_ptr) { + /* Allocate memory */ + if(image_info.callbacks.image_malloc) { + if(NULL == (image_info.buffer = image_info.callbacks.image_malloc(buf_len, + H5FD_FILE_IMAGE_OP_PROPERTY_LIST_SET, image_info.callbacks.udata))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "image malloc callback failed") + } /* end if */ + else + if(NULL == (image_info.buffer = H5MM_malloc(buf_len))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory block") + + /* Copy data */ + if(image_info.callbacks.image_memcpy) { + if(image_info.buffer != image_info.callbacks.image_memcpy(image_info.buffer, + buf_ptr, buf_len, H5FD_FILE_IMAGE_OP_PROPERTY_LIST_SET, + image_info.callbacks.udata)) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTCOPY, FAIL, "image_memcpy callback failed") + } /* end if */ + else + HDmemcpy(image_info.buffer, buf_ptr, buf_len); + } /* end if */ + else + image_info.buffer = NULL; + + image_info.size = buf_len; + + /* Set values */ + if(H5P_set(fapl, H5F_ACS_FILE_IMAGE_INFO_NAME, &image_info) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file image info") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pset_file_image() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pget_file_image + * + * Purpose: If the file image exists and buf_ptr_ptr is not NULL, + * allocate a buffer of the correct size, copy the image into + * the new buffer, and return the buffer to the caller in + * *buf_ptr_ptr. Do this using the file image callbacks + * if defined. + * + * NB: It is the responsibility of the caller to free the + * buffer whose address is returned in *buf_ptr_ptr. Do + * this using free if the file image callbacks are not + * defined, or with whatever method is appropriate if + * the callbacks are defined. + * + * If buf_ptr_ptr is not NULL, and no image exists, set + * *buf_ptr_ptr to NULL. + * + * If buf_len_ptr is not NULL, set *buf_len_ptr equal + * to the length of the file image if it exists, and + * to 0 if it does not. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Jacob Gruber + * Thurday, August 11, 2011 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pget_file_image(hid_t fapl_id, void **buf_ptr_ptr, size_t *buf_len_ptr) +{ + H5P_genplist_t *fapl; /* Property list pointer */ + H5FD_file_image_info_t image_info; /* File image info */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE3("e", "i**x*z", fapl_id, buf_ptr_ptr, buf_len_ptr); + + /* Get the plist structure */ + if(NULL == (fapl = H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Get values */ + if(H5P_get(fapl, H5F_ACS_FILE_IMAGE_INFO_NAME, &image_info) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get file image info") + + /* verify file image field consistancy */ + HDassert(((image_info.buffer != NULL) && (image_info.size > 0)) || + ((image_info.buffer == NULL) && (image_info.size == 0))); + + /* Set output size */ + if(buf_len_ptr != NULL) + *buf_len_ptr = image_info.size; + + /* Duplicate the image if desired, using callbacks if available */ + if(buf_ptr_ptr != NULL) { + void * copy_ptr = NULL; /* Copy of memory image */ + + if(image_info.buffer != NULL) { + /* Allocate memory */ + if(image_info.callbacks.image_malloc) { + if(NULL == (copy_ptr = image_info.callbacks.image_malloc(image_info.size, + H5FD_FILE_IMAGE_OP_PROPERTY_LIST_GET, image_info.callbacks.udata))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "image malloc callback failed") + } /* end if */ + else + if(NULL == (copy_ptr = H5MM_malloc(image_info.size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate copy") + + /* Copy data */ + if(image_info.callbacks.image_memcpy) { + if(copy_ptr != image_info.callbacks.image_memcpy(copy_ptr, image_info.buffer, + image_info.size, H5FD_FILE_IMAGE_OP_PROPERTY_LIST_GET, + image_info.callbacks.udata)) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTCOPY, FAIL, "image_memcpy callback failed") + } /* end if */ + else + HDmemcpy(copy_ptr, image_info.buffer, image_info.size); + } /* end if */ + + *buf_ptr_ptr = copy_ptr; + } /* end if */ + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pget_file_image */ + + +/*------------------------------------------------------------------------- + * Function: H5Pset_file_image_callbacks + * + * Purpose: Sets the callbacks for file images. Some file drivers allow + * the use of user-defined callbacks for allocating, freeing and + * copying the drivers internal buffer, potentially allowing a + * clever user to do optimizations such as avoiding large mallocs + * and memcpys or to perform detailed logging. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Jacob Gruber + * Thurday, August 11, 2011 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pset_file_image_callbacks(hid_t fapl_id, H5FD_file_image_callbacks_t *callbacks_ptr) +{ + H5P_genplist_t *fapl; /* Property list pointer */ + H5FD_file_image_info_t info; /* File image info */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "i*x", fapl_id, callbacks_ptr); + + /* Get the plist structure */ + if(NULL == (fapl = H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Get old info */ + if(H5P_get(fapl, H5F_ACS_FILE_IMAGE_INFO_NAME, &info) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get old file image info") + + /* verify file image field consistancy */ + HDassert(((info.buffer != NULL) && (info.size > 0)) || + ((info.buffer == NULL) && (info.size == 0))); + + /* Make sure a file image hasn't already been set */ + if(info.buffer != NULL || info.size > 0) + HGOTO_ERROR(H5E_PLIST, H5E_SETDISALLOWED, FAIL, "setting callbacks when an image is already set is forbidden. It could cause memory leaks.") + + /* verify that callbacks_ptr is not NULL */ + if(NULL == callbacks_ptr) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL callbacks_ptr") + + /* Make sure udata callbacks are going to be set if udata is going to be set */ + if(callbacks_ptr->udata) + if(callbacks_ptr->udata_copy == NULL || callbacks_ptr->udata_free == NULL) + HGOTO_ERROR(H5E_PLIST, H5E_SETDISALLOWED, FAIL, "udata callbacks must be set if udata is set") + + /* Release old udata if it exists */ + if(info.callbacks.udata != NULL) { + HDassert(info.callbacks.udata_free); + if(info.callbacks.udata_free(info.callbacks.udata) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "udata_free callback failed") + } /* end if */ + + /* Update struct */ + info.callbacks = *callbacks_ptr; + + if(callbacks_ptr->udata) { + HDassert(callbacks_ptr->udata_copy); + HDassert(callbacks_ptr->udata_free); + if((info.callbacks.udata = callbacks_ptr->udata_copy(callbacks_ptr->udata)) == NULL) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't copy the suppplied udata") + } /* end if */ + + /* Set values */ + if(H5P_set(fapl, H5F_ACS_FILE_IMAGE_INFO_NAME, &info) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file image info") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pset_file_image_callbacks() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pget_file_image_callbacks + * + * Purpose: Sets the callbacks for file images. Some file drivers allow + * the use of user-defined callbacks for allocating, freeing and + * copying the drivers internal buffer, potentially allowing a + * clever user to do optimizations such as avoiding large mallocs + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Jacob Gruber + * Thurday, August 11, 2011 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pget_file_image_callbacks(hid_t fapl_id, H5FD_file_image_callbacks_t *callbacks_ptr) +{ + H5P_genplist_t *fapl; /* Property list pointer */ + H5FD_file_image_info_t info; /* File image info */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "i*x", fapl_id, callbacks_ptr); + + /* Get the plist structure */ + if(NULL == (fapl = H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Get old info */ + if(H5P_get(fapl, H5F_ACS_FILE_IMAGE_INFO_NAME, &info) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get file image info") + + /* verify file image field consistancy */ + HDassert(((info.buffer != NULL) && (info.size > 0)) || + ((info.buffer == NULL) && (info.size == 0))); + + /* verify that callbacks_ptr is not NULL */ + if(NULL == callbacks_ptr) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL callbacks_ptr") + + /* Transfer values to parameters */ + *callbacks_ptr = info.callbacks; + + /* Copy udata if it exists */ + if(info.callbacks.udata != NULL) { + HDassert(info.callbacks.udata_copy); + if((callbacks_ptr->udata = info.callbacks.udata_copy(info.callbacks.udata)) == 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't copy udata") + } /* end if */ + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pget_file_image_callbacks() */ + + +/*------------------------------------------------------------------------- + * Function: H5P_file_image_info_del + * + * Purpose: Delete callback for the file image info property, called + * when the property is deleted from the plist. The buffer + * and udata may need to be freed, possibly using their + * respective callbacks so the default free won't work. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Jacob Gruber + * Thurday, August 11, 2011 + * + *------------------------------------------------------------------------- + */ +herr_t +H5P_file_image_info_del(hid_t UNUSED prop_id, const char UNUSED *name, size_t UNUSED size, void *value) +{ + H5FD_file_image_info_t info; /* Image info struct */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + if(value) { + info = *(H5FD_file_image_info_t *)value; + + /* verify file image field consistancy */ + HDassert(((info.buffer != NULL) && (info.size > 0)) || + ((info.buffer == NULL) && (info.size == 0))); + + if(info.buffer && info.size > 0) { + /* Free buffer */ + if(info.callbacks.image_free) { + if(info.callbacks.image_free(info.buffer, H5FD_FILE_IMAGE_OP_PROPERTY_LIST_CLOSE, info.callbacks.udata) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "image_free callback failed") + } /* end if */ + else + free(info.buffer); + } /* end if */ + + /* Free udata if it exists */ + if(info.callbacks.udata) { + if(NULL == info.callbacks.udata_free) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "udata_free not defined") + + if(info.callbacks.udata_free(info.callbacks.udata) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "udata_free callback failed") + } /* end if */ + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P_file_image_info_del() */ + + +/*------------------------------------------------------------------------- + * Function: H5P_file_image_info_copy + * + * Purpose: Copy callback for the file image info property. The buffer + * and udata may need to be copied, possibly using their + * respective callbacks so the default copy won't work. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Jacob Gruber + * Thurday, August 11, 2011 + * + *------------------------------------------------------------------------- + */ +herr_t +H5P_file_image_info_copy(const char UNUSED *name, size_t UNUSED size, void *value) +{ + H5FD_file_image_info_t *info; /* Image info struct */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + if(value) { + info = (H5FD_file_image_info_t *)value; + + /* verify file image field consistancy */ + HDassert(((info->buffer != NULL) && (info->size > 0)) || + ((info->buffer == NULL) && (info->size == 0))); + + if(info->buffer && info->size > 0) { + void *old_buffer; /* Pointer to old image buffer */ + + /* Store the old buffer */ + old_buffer = info->buffer; + + /* Allocate new buffer */ + if(info->callbacks.image_malloc) { + if(NULL == (info->buffer = info->callbacks.image_malloc(info->size, + H5FD_FILE_IMAGE_OP_PROPERTY_LIST_COPY, info->callbacks.udata))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "image malloc callback failed") + } /* end if */ + else { + if(NULL == (info->buffer = H5MM_malloc(info->size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory block") + } /* end else */ + + /* Copy data to new buffer */ + if(info->callbacks.image_memcpy) { + if(info->buffer != info->callbacks.image_memcpy(info->buffer, old_buffer, + info->size, H5FD_FILE_IMAGE_OP_PROPERTY_LIST_COPY, + info->callbacks.udata)) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTCOPY, FAIL, "image_memcpy callback failed") + } /* end if */ + else + HDmemcpy(info->buffer, old_buffer, info->size); + } /* end if */ + } /* end if */ + + /* Copy udata if it exists */ + if(info->callbacks.udata) { + void *old_udata = info->callbacks.udata; + + if(NULL == info->callbacks.udata_copy) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "udata_copy not defined") + + info->callbacks.udata = info->callbacks.udata_copy(old_udata); + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P_file_image_info_copy() */ + + +/*------------------------------------------------------------------------- + * Function: H5P_file_image_info_close + * + * Purpose: Close callback for the file image info property. The buffer + * and udata may need to be freed, possibly using their + * respective callbacks so the standard free won't work. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Jacob Gruber + * Thurday, August 11, 2011 + * + *------------------------------------------------------------------------- + */ +herr_t +H5P_file_image_info_close(const char UNUSED *name, size_t UNUSED size, void *value) +{ + H5FD_file_image_info_t info; /* Image info struct */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + if(value) { + info = *(H5FD_file_image_info_t *)value; + + if(info.buffer != NULL && info.size > 0) { + /* Free buffer */ + if(info.callbacks.image_free) { + if(info.callbacks.image_free(info.buffer, H5FD_FILE_IMAGE_OP_PROPERTY_LIST_CLOSE, + info.callbacks.udata) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "image_free callback failed") + } /* end if */ + else + H5MM_xfree(info.buffer); + } /* end if */ + } /* end if */ + + /* Free udata if it exists */ + if(info.callbacks.udata) { + if(NULL == info.callbacks.udata_free) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "udata_free not defined") + if(info.callbacks.udata_free(info.callbacks.udata) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "udata_free callback failed") + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P_file_image_info_close() */ + diff --git a/src/H5Pint.c b/src/H5Pint.c index 08b8af6..46a06a0 100644 --- a/src/H5Pint.c +++ b/src/H5Pint.c @@ -51,6 +51,7 @@ typedef struct { const H5P_genclass_t *parent; /* Pointer to parent class */ const char *name; /* Pointer to name to check */ + H5P_genclass_t *new_class; /* Pointer to class during path traversal */ } H5P_check_class_t; @@ -1358,11 +1359,11 @@ H5P_access_class(H5P_genclass_t *pclass, H5P_class_mod_t mod) /*-------------------------------------------------------------------------- NAME - H5P_check_class + H5P_open_class_path_cb PURPOSE Internal callback routine to check for duplicated names in parent class. USAGE - int H5P_check_class(obj, id, key) + int H5P_open_class_path_cb(obj, id, key) H5P_genclass_t *obj; IN: Pointer to class hid_t id; IN: ID of object being looked at const void *key; IN: Pointer to information used to compare @@ -1378,27 +1379,29 @@ H5P_access_class(H5P_genclass_t *pclass, H5P_class_mod_t mod) REVISION LOG --------------------------------------------------------------------------*/ static int -H5P_check_class(void *_obj, hid_t UNUSED id, void *_key) +H5P_open_class_path_cb(void *_obj, hid_t UNUSED id, void *_key) { - H5P_genclass_t *obj=(H5P_genclass_t *)_obj; /* Pointer to the class for this ID */ - const H5P_check_class_t *key=(const H5P_check_class_t *)_key; /* Pointer to key information for comparison */ - int ret_value=0; /* Return value */ + H5P_genclass_t *obj = (H5P_genclass_t *)_obj; /* Pointer to the class for this ID */ + H5P_check_class_t *key = (H5P_check_class_t *)_key; /* Pointer to key information for comparison */ + int ret_value = 0; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOERR HDassert(obj); - HDassert(H5I_GENPROP_CLS==H5I_get_type(id)); + HDassert(H5I_GENPROP_CLS == H5I_get_type(id)); HDassert(key); /* Check if the class object has the same parent as the new class */ - if(obj->parent==key->parent) { + if(obj->parent == key->parent) { /* Check if they have the same name */ - if(HDstrcmp(obj->name,key->name)==0) - ret_value=1; /* Indicate a match */ + if(HDstrcmp(obj->name, key->name) == 0) { + key->new_class = obj; + ret_value = 1; /* Indicate a match */ + } /* end if */ } /* end if */ FUNC_LEAVE_NOAPI(ret_value) -} /* end H5P_check_class() */ +} /* end H5P_open_class_path_cb() */ /*-------------------------------------------------------------------------- @@ -4555,8 +4558,8 @@ H5P_open_class_path(const char *path) char *curr_name; /* Pointer to current component of path name */ char *delimit; /* Pointer to path delimiter during traversal */ H5P_genclass_t *curr_class; /* Pointer to class during path traversal */ - H5P_genclass_t *ret_value; /* Return value */ H5P_check_class_t check_info; /* Structure to hold the information for checking duplicate names */ + H5P_genclass_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -4569,20 +4572,24 @@ H5P_open_class_path(const char *path) /* Find the generic property class with this full path */ curr_name = tmp_path; curr_class = NULL; - while((delimit=HDstrchr(curr_name,'/'))!=NULL) { + while(NULL != (delimit = HDstrchr(curr_name, '/'))) { /* Change the delimiter to terminate the string */ - *delimit='\0'; + *delimit = '\0'; /* Set up the search structure */ - check_info.parent=curr_class; - check_info.name=curr_name; + check_info.parent = curr_class; + check_info.name = curr_name; + check_info.new_class = NULL; /* Find the class with this name & parent by iterating over the open classes */ - if(NULL == (curr_class = (H5P_genclass_t *)H5I_search(H5I_GENPROP_CLS, H5P_check_class, &check_info, FALSE))) - HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, NULL, "can't locate class") + if(H5I_iterate(H5I_GENPROP_CLS, H5P_open_class_path_cb, &check_info, FALSE) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_BADITER, NULL, "can't iterate over classes") + else if(NULL == check_info.new_class) + HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, NULL, "can't locate class") /* Advance the pointer in the path to the start of the next component */ - curr_name=delimit+1; + curr_class = check_info.new_class; + curr_name = delimit + 1; } /* end while */ /* Should be pointing to the last component in the path name now... */ @@ -4590,13 +4597,16 @@ H5P_open_class_path(const char *path) /* Set up the search structure */ check_info.parent = curr_class; check_info.name = curr_name; + check_info.new_class = NULL; /* Find the class with this name & parent by iterating over the open classes */ - if(NULL == (curr_class = (H5P_genclass_t *)H5I_search(H5I_GENPROP_CLS, H5P_check_class, &check_info, FALSE))) + if(H5I_iterate(H5I_GENPROP_CLS, H5P_open_class_path_cb, &check_info, FALSE) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_BADITER, NULL, "can't iterate over classes") + else if(NULL == check_info.new_class) HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, NULL, "can't locate class") /* Copy it */ - if(NULL == (ret_value = H5P_copy_pclass(curr_class))) + if(NULL == (ret_value = H5P_copy_pclass(check_info.new_class))) HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, NULL, "can't copy property class") done: @@ -4604,7 +4614,7 @@ done: H5MM_xfree(tmp_path); FUNC_LEAVE_NOAPI(ret_value) -} /* H5P_open_class_path() */ +} /* H5P_open_class_path() */ /*-------------------------------------------------------------------------- diff --git a/src/H5Pocpl.c b/src/H5Pocpl.c old mode 100755 new mode 100644 diff --git a/src/H5Pocpypl.c b/src/H5Pocpypl.c old mode 100755 new mode 100644 index af50d80..23f8e4b --- a/src/H5Pocpypl.c +++ b/src/H5Pocpypl.c @@ -35,7 +35,9 @@ /***********/ #include "H5private.h" /* Generic Functions */ #include "H5Eprivate.h" /* Error handling */ +#include "H5FLprivate.h" /* Free Lists */ #include "H5Iprivate.h" /* IDs */ +#include "H5MMprivate.h" /* Memory management */ #include "H5Ppkg.h" /* Property lists */ @@ -47,7 +49,13 @@ /* Definitions for copy options */ #define H5O_CPY_OPTION_SIZE sizeof(unsigned) #define H5O_CPY_OPTION_DEF 0 - +/* Definitions for merge committed dtype list */ +#define H5O_CPY_MERGE_COMM_DT_LIST_SIZE sizeof(char *) +#define H5O_CPY_MERGE_COMM_DT_LIST_DEF NULL +#define H5O_CPY_MERGE_COMM_DT_LIST_CMP H5P_ocpy_merge_comm_dt_list_cmp +/* Definitions for callback function when completing the search for a matching committed datatype from the committed dtype list */ +#define H5O_CPY_MCDT_SEARCH_CB_SIZE sizeof(H5O_mcdt_cb_info_t) +#define H5O_CPY_MCDT_SEARCH_CB_DEF {NULL,NULL} /******************/ /* Local Typedefs */ @@ -63,8 +71,17 @@ /* Local Prototypes */ /********************/ +/* General routines */ +static H5O_copy_dtype_merge_list_t *H5P_free_merge_comm_dtype_list(H5O_copy_dtype_merge_list_t *dt_list); + /* Property class callbacks */ static herr_t H5P_ocpy_reg_prop(H5P_genclass_t *pclass); +static herr_t H5P_ocpy_copy(hid_t dst_plist_id, hid_t src_plist_id, + void *copy_data); +static herr_t H5P_ocpy_close(hid_t ocpypl_id, void *close_data); + +/* Property callbacks */ +static int H5P_ocpy_merge_comm_dt_list_cmp(const void *value1, const void *value2, size_t size); /*********************/ @@ -80,9 +97,9 @@ const H5P_libclass_t H5P_CLS_OCPY[1] = {{ H5P_ocpy_reg_prop, /* Default property registration routine */ NULL, /* Class creation callback */ NULL, /* Class creation callback info */ - NULL, /* Class copy callback */ + H5P_ocpy_copy, /* Class copy callback */ NULL, /* Class copy callback info */ - NULL, /* Class close callback */ + H5P_ocpy_close, /* Class close callback */ NULL /* Class close callback info */ }}; @@ -96,6 +113,9 @@ const H5P_libclass_t H5P_CLS_OCPY[1] = {{ /* Local Variables */ /*******************/ +/* Declare a free list to manage the H5O_copy_dtype_merge_list_t struct */ +H5FL_DEFINE(H5O_copy_dtype_merge_list_t); + /*------------------------------------------------------------------------- @@ -109,10 +129,12 @@ const H5P_libclass_t H5P_CLS_OCPY[1] = {{ * October 31, 2006 *------------------------------------------------------------------------- */ -herr_t +static herr_t H5P_ocpy_reg_prop(H5P_genclass_t *pclass) { unsigned ocpy_option = H5O_CPY_OPTION_DEF; /* Default object copy flags */ + H5O_copy_dtype_merge_list_t *merge_comm_dtype_list = H5O_CPY_MERGE_COMM_DT_LIST_DEF; /* Default merge committed dtype list */ + H5O_mcdt_cb_info_t mcdt_cb = H5O_CPY_MCDT_SEARCH_CB_DEF; /* Default callback before searching the global list of committed datatypes at destination */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -121,12 +143,222 @@ H5P_ocpy_reg_prop(H5P_genclass_t *pclass) if(H5P_register_real(pclass, H5O_CPY_OPTION_NAME, H5O_CPY_OPTION_SIZE, &ocpy_option, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + /* Register merge named dtype list property */ + if(H5P_register_real(pclass, H5O_CPY_MERGE_COMM_DT_LIST_NAME, H5O_CPY_MERGE_COMM_DT_LIST_SIZE, &merge_comm_dtype_list, NULL, NULL, NULL, NULL, NULL, H5O_CPY_MERGE_COMM_DT_LIST_CMP, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + + /* Register property for callback when completing the search for a matching named datatype from the named dtype list */ + if(H5P_register_real(pclass, H5O_CPY_MCDT_SEARCH_CB_NAME, H5O_CPY_MCDT_SEARCH_CB_SIZE, &mcdt_cb, 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_ocpy_reg_prop() */ /*------------------------------------------------------------------------- + * Function: H5P_ocpy_copy + * + * Purpose: Callback routine which is called whenever any object + * copy property list is copied. This routine copies + * the properties from the old list to the new list. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Neil Fortner + * Friday, October 28, 2011 + * + *------------------------------------------------------------------------- + */ +/* ARGSUSED */ +static herr_t +H5P_ocpy_copy(hid_t dst_plist_id, hid_t src_plist_id, void UNUSED *copy_data) +{ + H5O_copy_dtype_merge_list_t *src_dt_list, *dst_dt_list = NULL; /* Source & destination merge named datatype lists */ + H5O_copy_dtype_merge_list_t *dst_dt_list_tail = NULL, *tmp_dt_list = NULL; /* temporary merge named datatype lists */ + H5P_genplist_t *src_plist; /* Pointer to source property list */ + H5P_genplist_t *dst_plist; /* Pointer to destination property list */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Verify property list IDs */ + if(NULL == (dst_plist = (H5P_genplist_t *)H5I_object(dst_plist_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an object copy property list") + if(NULL == (src_plist = (H5P_genplist_t *)H5I_object(src_plist_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an object copy property list") + + /* Get the merge committed dtype list property from the old property list */ + if(H5P_get(src_plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &src_dt_list) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get merge named dtype list") + + /* Make copy of merge committed dtype list */ + while(src_dt_list) { + /* Copy src_dt_list */ + if(NULL == (tmp_dt_list = H5FL_CALLOC(H5O_copy_dtype_merge_list_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + if(NULL == (tmp_dt_list->path = H5MM_strdup(src_dt_list->path))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Add copied node to dest dtype list */ + if(dst_dt_list_tail) { + dst_dt_list_tail->next = tmp_dt_list; + dst_dt_list_tail = tmp_dt_list; + } /* end if */ + else { + dst_dt_list = tmp_dt_list; + dst_dt_list_tail = tmp_dt_list; + } /* end else */ + tmp_dt_list = NULL; + + /* Advance src_dt_list pointer */ + src_dt_list = src_dt_list->next; + } /* end while */ + + /* Set the merge named dtype list property for the destination property list + */ + if(H5P_set(dst_plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &dst_dt_list) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set merge committed dtype list") + +done: + if(ret_value < 0) { + dst_dt_list = H5P_free_merge_comm_dtype_list(dst_dt_list); + if(tmp_dt_list) { + tmp_dt_list->path = (char *)H5MM_xfree(tmp_dt_list->path); + tmp_dt_list = H5FL_FREE(H5O_copy_dtype_merge_list_t, tmp_dt_list); + } /* end if */ + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P_ocpy_copy() */ + + +/*------------------------------------------------------------------------- + * Function: H5P_ocpy_close + * + * Purpose: Callback routine which is called whenever any object copy + * property list is closed. This routine performs any generic + * cleanup needed on the properties the library put into the + * list. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Neil Fortner + * Friday, October 28, 2011 + * + *------------------------------------------------------------------------- + */ +/* ARGSUSED */ +static herr_t +H5P_ocpy_close(hid_t ocpypl_id, void UNUSED *close_data) +{ + H5O_copy_dtype_merge_list_t *dt_list; /* Merge named datatype list */ + H5P_genplist_t *plist; /* Property list */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Check arguments */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(ocpypl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an object copy property list") + + /* Get the merge named dtype list property from the old property list */ + if(H5P_get(plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &dt_list) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get merge named dtype list") + + /* Free the merge named dtype list */ + dt_list = H5P_free_merge_comm_dtype_list(dt_list); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P_ocpy_close() */ + + +/*------------------------------------------------------------------------- + * Function: H5P_ocpy_merge_comm_dt_list_cmp + * + * Purpose: Callback routine which is called whenever the merge + * named dtype property in the object copy property list + * is compared. + * + * Return: positive if VALUE1 is greater than VALUE2, negative if + * VALUE2 is greater than VALUE1 and zero if VALUE1 and + * VALUE2 are equal. + * + * Programmer: Neil Fortner + * Friday, October 28, 2011 + * + *------------------------------------------------------------------------- + */ +static int +H5P_ocpy_merge_comm_dt_list_cmp(const void *_dt_list1, const void *_dt_list2, + size_t UNUSED size) +{ + const H5O_copy_dtype_merge_list_t *dt_list1 = *(H5O_copy_dtype_merge_list_t * const *)_dt_list1, /* Create local aliases for values */ + *dt_list2 = *(H5O_copy_dtype_merge_list_t * const *)_dt_list2; + herr_t ret_value = 0; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Sanity check */ + HDassert(_dt_list1); + HDassert(_dt_list2); + HDassert(size == sizeof(H5O_copy_dtype_merge_list_t *)); + + /* Walk through the lists, comparing each path. For the lists to be the + * same, the paths must be in the same order. */ + while(dt_list1 && dt_list2) { + /* Compare paths */ + ret_value = HDstrcmp(dt_list1->path, dt_list2->path); + if(ret_value != 0) HGOTO_DONE(ret_value) + + /* Advance to next node */ + dt_list1 = dt_list1->next; + dt_list2 = dt_list2->next; + } /* end while */ + + /* Check if one list is longer than the other */ + if(dt_list1) HGOTO_DONE(1) + if(dt_list2) HGOTO_DONE(-1) + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P_ocpy_merge_comm_dt_list_cmp() */ + + +/*------------------------------------------------------------------------- + * Function: H5P_free_merge_comm_dtype_list + * + * Purpose: Frees the provided merge named dtype list + * + * Return: NULL + * + * Programmer: Neil Fortner + * October 27, 2011 + *------------------------------------------------------------------------- + */ +static H5O_copy_dtype_merge_list_t * +H5P_free_merge_comm_dtype_list(H5O_copy_dtype_merge_list_t *dt_list) +{ + H5O_copy_dtype_merge_list_t *tmp_node; + + FUNC_ENTER_NOAPI_NOINIT + + /* Free the list */ + while(dt_list) { + tmp_node = dt_list->next; + (void)H5MM_xfree(dt_list->path); + (void)H5FL_FREE(H5O_copy_dtype_merge_list_t, dt_list); + dt_list = tmp_node; + } /* end while */ + + FUNC_LEAVE_NOAPI(NULL); +} /* H5P_free_merge_comm_dtype_list */ + + +/*------------------------------------------------------------------------- * Function: H5Pset_copy_object * * Purpose: Set properties when copying an object (group, dataset, and datatype) @@ -207,3 +439,210 @@ done: FUNC_LEAVE_API(ret_value) } /* end H5Pget_copy_object() */ + +/*------------------------------------------------------------------------- + * Function: H5Padd_merge_committed_dtype_path + * + * Purpose: Adds path to the list of paths to search first in the + * target file when merging committed datatypes during H5Ocopy + * (i.e. when using the H5O_COPY_MERGE_COMMITTED_DTYPE_FLAG flag + * as set by H5Pset_copy_object). If the source named + * dataype is not found in the list of paths created by this + * function, the entire file will be searched. + * + * Usage: H5Padd_merge_committed_dtype_path(plist_id, path) + * hid_t plist_id; IN: Property list to copy object + * const char *path; IN: Path to add to list + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Neil Fortner + * October 27, 2011 + *------------------------------------------------------------------------- + */ +herr_t +H5Padd_merge_committed_dtype_path(hid_t plist_id, const char *path) +{ + H5P_genplist_t *plist; /* Property list pointer */ + H5O_copy_dtype_merge_list_t *old_list; /* Merge committed dtype list currently present */ + H5O_copy_dtype_merge_list_t *new_obj = NULL; /* New object to add to list */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "i*s", plist_id, path); + + /* Check parameters */ + if(!path) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no path specified") + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(plist_id, H5P_OBJECT_COPY))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Get dtype list */ + if(H5P_get(plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &old_list) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get merge named dtype list") + + /* Add the new path to the list */ + if(NULL == (new_obj = H5FL_CALLOC(H5O_copy_dtype_merge_list_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + if(NULL == (new_obj->path = H5MM_strdup(path))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + new_obj->next = old_list; + + /* Update the list stored in the property list */ + if(H5P_set(plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &new_obj) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set merge named dtype list") + +done: + if(ret_value < 0) + if(new_obj) { + new_obj->path = (char *)H5MM_xfree(new_obj->path); + new_obj = H5FL_FREE(H5O_copy_dtype_merge_list_t, new_obj); + } /* end if */ + + FUNC_LEAVE_API(ret_value) +} /* end H5Padd_merge_committed_dtype_path() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pfree_merge_committed_dtype_paths + * + * Purpose: Frees and clears the list of paths created by + * H5Padd_merge_committed_dtype_path. A new list may then be + * created by calling H5Padd_merge_committed_dtype_path again. + * + * Usage: H5Pfree_merge_committed_dtype_paths(plist_id) + * hid_t plist_id; IN: Property list to copy object + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Neil Fortner + * October 27, 2011 + *------------------------------------------------------------------------- + */ +herr_t +H5Pfree_merge_committed_dtype_paths(hid_t plist_id) +{ + H5P_genplist_t *plist; /* Property list pointer */ + H5O_copy_dtype_merge_list_t *dt_list; /* Merge committed dtype list currently present */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE1("e", "i", plist_id); + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(plist_id, H5P_OBJECT_COPY))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Get dtype list */ + if(H5P_get(plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &dt_list) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get merge committed dtype list") + + /* Free dtype list */ + dt_list = H5P_free_merge_comm_dtype_list(dt_list); + + /* Update the list stored in the property list (to NULL) */ + if(H5P_set(plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &dt_list) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set merge committed dtype list") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pfree_merge_committed_dtype_paths() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pset_mcdt_search_cb + * + * Purpose: Set the callback function when a matching committed datatype is not found + * from the list of paths stored in the object copy property list. + * H5Ocopy will invoke this callback before searching all committed datatypes + * at destination. + * + * Usage: H5Pset_mcdt_search_cb(plist_id, H5O_mcdt_search_cb_t func, void *op_data) + * hid_t plist_id; IN: Property list to copy object + * H5O_mcdt_search_cb_t func; IN: The callback function + * void *op_data; IN: The user data + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Vailin Choi; November 28, 2011 + *------------------------------------------------------------------------- + */ +herr_t +H5Pset_mcdt_search_cb(hid_t plist_id, H5O_mcdt_search_cb_t func, void *op_data) +{ + H5P_genplist_t *plist; /* Property list pointer */ + H5O_mcdt_cb_info_t cb_info; /* Callback info struct */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE3("e", "ix*x", plist_id, func, op_data); + + /* 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 && op_data) + 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_OBJECT_COPY))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Populate the callback info struct */ + cb_info.func = func; + cb_info.user_data = op_data; + + /* Set callback info */ + if(H5P_set(plist, H5O_CPY_MCDT_SEARCH_CB_NAME, &cb_info) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set callback info") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pset_mcdt_search_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pget_mcdt_search_cb + * + * Purpose: Retrieves the callback function and user data from the specified + * object copy property list. + * + * Usage: H5Pget_mcdt_search_cb(plist_id, H5O_mcdt_search_cb_t *func, void **op_data) + * hid_t plist_id; IN: Property list to copy object + * H5O_mcdt_search_cb_t *func; OUT: The callback function + * void **op_data; OUT: The user data + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Vailin Choi; November 29, 2011 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pget_mcdt_search_cb(hid_t plist_id, H5O_mcdt_search_cb_t *func, void **op_data) +{ + H5P_genplist_t *plist; /* Property list pointer */ + H5O_mcdt_cb_info_t cb_info; /* Callback info struct */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE3("e", "i*x**x", plist_id, func, op_data); + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(plist_id, H5P_OBJECT_COPY))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Get callback info */ + if(H5P_get(plist, H5O_CPY_MCDT_SEARCH_CB_NAME, &cb_info) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get callback info") + + if(func) + *func = cb_info.func; + + if(op_data) + *op_data = cb_info.user_data; + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pget_mcdt_search_cb() */ + diff --git a/src/H5Ppkg.h b/src/H5Ppkg.h index 1e71049..7cc3c21 100644 --- a/src/H5Ppkg.h +++ b/src/H5Ppkg.h @@ -196,6 +196,7 @@ H5_DLL herr_t H5P_get_filter(const H5Z_filter_info_t *filter, H5_DLL char *H5P_get_class_path_test(hid_t pclass_id); H5_DLL hid_t H5P_open_class_path_test(const char *path); H5_DLL herr_t H5P_reset_external_file_test(hid_t dcpl_id); +H5_DLL herr_t H5P_reset_layout_test(hid_t dcpl_id); #endif /* H5P_TESTING */ #endif /* _H5Ppkg_H */ diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h index 68627d4..de6019e 100644 --- a/src/H5Ppublic.h +++ b/src/H5Ppublic.h @@ -30,6 +30,7 @@ #include "H5FDpublic.h" #include "H5Ipublic.h" #include "H5Lpublic.h" +#include "H5Opublic.h" #include "H5MMpublic.h" #include "H5Tpublic.h" #include "H5Zpublic.h" @@ -321,6 +322,12 @@ H5_DLL herr_t H5Pget_libver_bounds(hid_t plist_id, H5F_libver_t *low, H5F_libver_t *high); H5_DLL herr_t H5Pset_elink_file_cache_size(hid_t plist_id, unsigned efc_size); H5_DLL herr_t H5Pget_elink_file_cache_size(hid_t plist_id, unsigned *efc_size); +H5_DLL herr_t H5Pset_file_image(hid_t fapl_id, void *buf_ptr, size_t buf_len); +H5_DLL herr_t H5Pget_file_image(hid_t fapl_id, void **buf_ptr_ptr, size_t *buf_len_ptr); +H5_DLL herr_t H5Pset_file_image_callbacks(hid_t fapl_id, + H5FD_file_image_callbacks_t *callbacks_ptr); +H5_DLL herr_t H5Pget_file_image_callbacks(hid_t fapl_id, + H5FD_file_image_callbacks_t *callbacks_ptr); /* Dataset creation property list (DCPL) routines */ H5_DLL herr_t H5Pset_layout(hid_t plist_id, H5D_layout_t layout); @@ -429,6 +436,10 @@ H5_DLL herr_t H5Pget_elink_cb(hid_t lapl_id, H5L_elink_traverse_t *func, void ** /* Object copy property list (OCPYPL) routines */ H5_DLL herr_t H5Pset_copy_object(hid_t plist_id, unsigned crt_intmd); H5_DLL herr_t H5Pget_copy_object(hid_t plist_id, unsigned *crt_intmd /*out*/); +H5_DLL herr_t H5Padd_merge_committed_dtype_path(hid_t plist_id, const char *path); +H5_DLL herr_t H5Pfree_merge_committed_dtype_paths(hid_t plist_id); +H5_DLL herr_t H5Pset_mcdt_search_cb(hid_t plist_id, H5O_mcdt_search_cb_t func, void *op_data); +H5_DLL herr_t H5Pget_mcdt_search_cb(hid_t plist_id, H5O_mcdt_search_cb_t *func, void **op_data); /* Symbols defined for compatibility with previous versions of the HDF5 API. * diff --git a/src/H5Ptest.c b/src/H5Ptest.c index b36da6a..0463299 100644 --- a/src/H5Ptest.c +++ b/src/H5Ptest.c @@ -165,9 +165,59 @@ H5P_reset_external_file_test(hid_t dcpl_id) /* set external file list */ if(H5P_set(plist, H5D_CRT_EXT_FILE_LIST_NAME, &efl) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get external file list") + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set external file list") done: FUNC_LEAVE_NOAPI(ret_value) } /* H5P_reset_external_file_test() */ + +/*-------------------------------------------------------------------------- + NAME + H5P_reset_layout_test + PURPOSE + Routine to reset layout message + USAGE + herr_t H5P_reset_layout_test(plist) + hid_t dcpl_id; IN: the property list + + RETURNS + Non-negative on success/Negative on failure + + PROGRAMMER + Quincey Koziol + April 5, 2012 +--------------------------------------------------------------------------*/ +herr_t +H5P_reset_layout_test(hid_t dcpl_id) +{ + H5O_layout_t layout; /* Layout message */ + H5P_genplist_t *plist; /* Property list */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Check arguments */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dcpl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list") + + /* Get layout message */ + if(H5P_get(plist, H5D_CRT_LAYOUT_NAME, &layout) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get layout") + + /* Clean up any values set for the layout */ + if(H5O_msg_reset(H5O_LAYOUT_ID, &layout) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "can't release layout info") + + /* Set layout message */ + if(H5P_set(plist, H5D_CRT_LAYOUT_NAME, &layout) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set layout") + + /* Remove layout message */ + if(H5P_remove(dcpl_id, plist, H5D_CRT_LAYOUT_NAME) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTDELETE, FAIL, "can't delete layout message property") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5P_reset_layout_test() */ + diff --git a/src/H5SM.c b/src/H5SM.c old mode 100755 new mode 100644 index 8c00d34..62efb50 --- a/src/H5SM.c +++ b/src/H5SM.c @@ -1099,7 +1099,7 @@ H5SM_try_share(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, unsigned defer_flags, /* Set flags if this message was "written" without error and wasn't a * 'defer' attempt; it is now either fully shared or "shareable". */ - if(mesg_flags && !(defer_flags & H5SM_DEFER)) { + if(mesg_flags) { if(((H5O_shared_t *)mesg)->type == H5O_SHARE_TYPE_HERE) *mesg_flags |= H5O_MSG_FLAG_SHAREABLE; else { @@ -1109,7 +1109,8 @@ H5SM_try_share(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, unsigned defer_flags, } /* end if */ done: - HDassert(!ret_value || ((H5O_shared_t *)mesg)->type == H5O_SHARE_TYPE_HERE + HDassert((ret_value != TRUE) + || ((H5O_shared_t *)mesg)->type == H5O_SHARE_TYPE_HERE || ((H5O_shared_t *)mesg)->type == H5O_SHARE_TYPE_SOHM); #ifndef NDEBUG /* If we previously deferred this operation, make sure the saved message diff --git a/src/H5SMbtree2.c b/src/H5SMbtree2.c old mode 100755 new mode 100644 diff --git a/src/H5SMpkg.h b/src/H5SMpkg.h old mode 100755 new mode 100644 diff --git a/src/H5SMprivate.h b/src/H5SMprivate.h old mode 100755 new mode 100644 diff --git a/src/H5T.c b/src/H5T.c index 01bd6c1..5786523 100644 --- a/src/H5T.c +++ b/src/H5T.c @@ -1449,7 +1449,8 @@ H5T_term_interface(void) H5T_g.asoft = 0; /* Unlock all datatypes, then free them */ - H5I_search(H5I_DATATYPE, H5T_unlock_cb, NULL, FALSE); + /* note that we are ignoring the return value from H5I_iterate() */ + H5I_iterate(H5I_DATATYPE, H5T_unlock_cb, NULL, FALSE); H5I_dec_type_ref(H5I_DATATYPE); /* Reset all the datatype IDs */ diff --git a/src/H5Toh.c b/src/H5Toh.c index 5878075..be853f1 100644 --- a/src/H5Toh.c +++ b/src/H5Toh.c @@ -77,7 +77,8 @@ const H5O_obj_class_t H5O_OBJ_DATATYPE[1] = {{ H5O_dtype_open, /* open an object of this class */ H5O_dtype_create, /* create an object of this class */ H5O_dtype_get_oloc, /* get an object header location for an object */ - NULL /* get the index & heap info for an object */ + NULL, /* get the index & heap info for an object */ + NULL /* flush an opened object of this class */ }}; diff --git a/src/H5Ztrans.c b/src/H5Ztrans.c index 2a2796d..48948a7 100644 --- a/src/H5Ztrans.c +++ b/src/H5Ztrans.c @@ -107,6 +107,11 @@ static void H5Z_XFORM_DEBUG(H5Z_node *tree); static void H5Z_print(H5Z_node *tree, FILE *stream); #endif /* H5Z_XFORM_DEBUG */ +/* PGCC (11.8-0) has trouble with the command *p++ = *p OP tree_val. It increments P first before + * doing the operation. So I break down the command into two lines: + * *p = *p OP tree_val; p++; + * Actually, the behavior of *p++ = *p OP tree_val is undefined. (SLU - 2012/3/19) + */ #define H5Z_XFORM_DO_OP1(RESL,RESR,TYPE,OP,SIZE) \ { \ size_t u; \ @@ -119,8 +124,10 @@ static void H5Z_print(H5Z_node *tree, FILE *stream); tree_val = ((RESR).type==H5Z_XFORM_INTEGER ? (double)(RESR).value.int_val : (RESR).value.float_val); \ p = (TYPE*)(RESL).value.dat_val; \ \ - for(u=0; u<(SIZE); u++) \ - *p++ = *p OP tree_val; \ + for(u=0; u<(SIZE); u++) { \ + *p = *p OP tree_val; \ + p++; \ + } \ } \ else if(((RESR).type == H5Z_XFORM_SYMBOL) && ((RESL).type != H5Z_XFORM_SYMBOL)) \ { \ @@ -134,16 +141,20 @@ static void H5Z_print(H5Z_node *tree, FILE *stream); tree_val = ((RESL).type==H5Z_XFORM_INTEGER ? (double)(RESL).value.int_val : (RESL).value.float_val); \ \ p = (TYPE*)(RESR).value.dat_val; \ - for(u=0; u<(SIZE); u++) \ - *p++ = tree_val OP *p; \ + for(u=0; u<(SIZE); u++) { \ + *p = tree_val OP *p; \ + p++; \ + } \ } \ else if( ((RESL).type == H5Z_XFORM_SYMBOL) && ((RESR).type==H5Z_XFORM_SYMBOL)) \ { \ TYPE* pl = (TYPE*)(RESL).value.dat_val; \ TYPE* pr = (TYPE*)(RESR).value.dat_val; \ \ - for(u=0; u<(SIZE); u++) \ - *pl++ = *pl OP *pr++; \ + for(u=0; u<(SIZE); u++) { \ + *pl = *pl OP *pr; \ + pl++; pr++; \ + } \ } \ else \ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Unexpected type conversion operation") \ @@ -242,7 +253,6 @@ static void H5Z_print(H5Z_node *tree, FILE *stream); } #endif /*H5_SIZEOF_LONG_DOUBLE */ - #define H5Z_XFORM_DO_OP3(OP) \ { \ if((tree->lchild->type == H5Z_XFORM_INTEGER) && (tree->rchild->type==H5Z_XFORM_INTEGER)) \ @@ -267,9 +277,27 @@ static void H5Z_print(H5Z_node *tree, FILE *stream); } \ } +#define H5Z_XFORM_DO_OP4(TYPE) \ +{ \ + if ((ret_value = (H5Z_node*) H5MM_malloc(sizeof(H5Z_node))) == NULL) \ + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "Ran out of memory trying to copy parse tree") \ + else \ + { \ + ret_value->type = (TYPE); \ + ret_value->lchild = (H5Z_node*) H5Z_xform_copy_tree(tree->lchild, dat_val_pointers, new_dat_val_pointers); \ + ret_value->rchild = (H5Z_node*) H5Z_xform_copy_tree(tree->rchild, dat_val_pointers, new_dat_val_pointers); \ + } \ +} + +#define H5Z_XFORM_DO_OP5(TYPE, SIZE) \ +{ \ + TYPE val = ((tree->type == H5Z_XFORM_INTEGER) ? (TYPE)tree->value.int_val : (TYPE)tree->value.float_val); \ + H5V_array_fill(array, &val, sizeof(TYPE), (SIZE)); \ +} + /* The difference of this macro from H5Z_XFORM_DO_OP3 is that it handles the operations when the left operand is empty, like -x or +x. * The reason that it's seperated from H5Z_XFORM_DO_OP3 is because compilers don't accept operations like *x or /x. So in H5Z_do_op, - * these two macros are called in different ways. + * these two macros are called in different ways. (SLU 2012/3/20) */ #define H5Z_XFORM_DO_OP6(OP) \ { \ @@ -309,26 +337,6 @@ static void H5Z_print(H5Z_node *tree, FILE *stream); } \ } -#define H5Z_XFORM_DO_OP4(TYPE) \ -{ \ - if ((ret_value = (H5Z_node*) H5MM_malloc(sizeof(H5Z_node))) == NULL) \ - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "Ran out of memory trying to copy parse tree") \ - else \ - { \ - ret_value->type = (TYPE); \ - ret_value->lchild = (H5Z_node*) H5Z_xform_copy_tree(tree->lchild, dat_val_pointers, new_dat_val_pointers); \ - ret_value->rchild = (H5Z_node*) H5Z_xform_copy_tree(tree->rchild, dat_val_pointers, new_dat_val_pointers); \ - } \ -} - -#define H5Z_XFORM_DO_OP5(TYPE, SIZE) \ -{ \ - TYPE val = ((tree->type == H5Z_XFORM_INTEGER) ? (TYPE)tree->value.int_val : (TYPE)tree->value.float_val); \ - H5V_array_fill(array, &val, sizeof(TYPE), (SIZE)); \ -} - - - /* * Programmer: Bill Wendling * 25. August 2003 @@ -1310,61 +1318,6 @@ H5Z_xform_copy_tree(H5Z_node* tree, H5Z_datval_ptrs* dat_val_pointers, H5Z_datva /*------------------------------------------------------------------------- - * Function: H5Z_xform_reduce_tree - * Purpose: Simplifies parse tree passed in by performing any obvious - * and trivial arithemtic calculations. - * - * Return: None. - * Programmer: Leon Arber - * April 1, 2004. - * Modifications: - * - *------------------------------------------------------------------------- - */ -void -H5Z_xform_reduce_tree(H5Z_node* tree) -{ - FUNC_ENTER_NOAPI_NOINIT_NOERR - - if(tree) { - if((tree->type == H5Z_XFORM_DIVIDE) || (tree->type == H5Z_XFORM_MULT)) - { - if(H5Z_op_is_numbs(tree)) - H5Z_do_op(tree); - else - { - H5Z_xform_reduce_tree(tree->lchild); - if(H5Z_op_is_numbs(tree)) - H5Z_do_op(tree); - else { - H5Z_xform_reduce_tree(tree->rchild); - if(H5Z_op_is_numbs(tree)) - H5Z_do_op(tree); - } - } - } else if((tree->type == H5Z_XFORM_PLUS) || (tree->type == H5Z_XFORM_MINUS)) { - if(H5Z_op_is_numbs2(tree)) - H5Z_do_op(tree); - else - { - H5Z_xform_reduce_tree(tree->lchild); - if(H5Z_op_is_numbs2(tree)) - H5Z_do_op(tree); - else { - H5Z_xform_reduce_tree(tree->rchild); - if(H5Z_op_is_numbs2(tree)) - H5Z_do_op(tree); - } - } - } - - } - - FUNC_LEAVE_NOAPI_VOID; -} - - -/*------------------------------------------------------------------------- * Function: H5Z_op_is_numbs * Purpose: Internal function to facilitate the condition check in * H5Z_xform_reduce_tree to reduce the bulkiness of the code. @@ -1422,6 +1375,61 @@ H5Z_op_is_numbs2(H5Z_node* _tree) /*------------------------------------------------------------------------- + * Function: H5Z_xform_reduce_tree + * Purpose: Simplifies parse tree passed in by performing any obvious + * and trivial arithemtic calculations. + * + * Return: None. + * Programmer: Leon Arber + * April 1, 2004. + * Modifications: + * + *------------------------------------------------------------------------- + */ +void +H5Z_xform_reduce_tree(H5Z_node* tree) +{ + FUNC_ENTER_NOAPI_NOINIT_NOERR + + if(tree) { + if((tree->type == H5Z_XFORM_DIVIDE) || (tree->type == H5Z_XFORM_MULT)) + { + if(H5Z_op_is_numbs(tree)) + H5Z_do_op(tree); + else + { + H5Z_xform_reduce_tree(tree->lchild); + if(H5Z_op_is_numbs(tree)) + H5Z_do_op(tree); + else { + H5Z_xform_reduce_tree(tree->rchild); + if(H5Z_op_is_numbs(tree)) + H5Z_do_op(tree); + } + } + } else if((tree->type == H5Z_XFORM_PLUS) || (tree->type == H5Z_XFORM_MINUS)) { + if(H5Z_op_is_numbs2(tree)) + H5Z_do_op(tree); + else + { + H5Z_xform_reduce_tree(tree->lchild); + if(H5Z_op_is_numbs2(tree)) + H5Z_do_op(tree); + else { + H5Z_xform_reduce_tree(tree->rchild); + if(H5Z_op_is_numbs2(tree)) + H5Z_do_op(tree); + } + } + } + + } + + FUNC_LEAVE_NOAPI_VOID; +} + + +/*------------------------------------------------------------------------- * Function: H5Z_do_op * Purpose: If the root of the tree passed in points to a simple * arithmetic operation and the left and right subtrees are both diff --git a/src/H5err.txt b/src/H5err.txt index 71d27a6..b4cb28b 100644 --- a/src/H5err.txt +++ b/src/H5err.txt @@ -220,6 +220,7 @@ MINOR, DSPACE, H5E_CANTCOMPARE, Can't compare objects MINOR, PLIST, H5E_CANTGET, Can't get value MINOR, PLIST, H5E_CANTSET, Can't set value MINOR, PLIST, H5E_DUPCLASS, Duplicate class name in parent class +MINOR, PLIST, H5E_SETDISALLOWED, Disallowed operation # Link errors MINOR, LINK, H5E_TRAVERSE, Link traversal failure diff --git a/src/H5private.h b/src/H5private.h index e01edd2..37480cb 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -151,7 +151,9 @@ #ifdef H5_HAVE_WIN32_API +/* The following two defines must be before any windows headers are included */ #define WIN32_LEAN_AND_MEAN /* Exclude rarely-used stuff from Windows headers */ +#define NOGDI /* Exclude Graphic Display Interface macros */ #ifdef H5_HAVE_WINSOCK_H #include diff --git a/src/H5public.h b/src/H5public.h index 6253d63..5469a6f 100644 --- a/src/H5public.h +++ b/src/H5public.h @@ -75,10 +75,10 @@ extern "C" { /* Version numbers */ #define H5_VERS_MAJOR 1 /* For major interface/format changes */ #define H5_VERS_MINOR 9 /* For minor interface/format changes */ -#define H5_VERS_RELEASE 111 /* For tweaks, bug-fixes, or development */ +#define H5_VERS_RELEASE 113 /* For tweaks, bug-fixes, or development */ #define H5_VERS_SUBRELEASE "FA_a5" /* For pre-releases like snap0 */ /* Empty string for real releases. */ -#define H5_VERS_INFO "HDF5 library version: 1.9.111-FA_a5" /* Full version string */ +#define H5_VERS_INFO "HDF5 library version: 1.9.113-FA_a5" /* Full version string */ #define H5check() H5check_version(H5_VERS_MAJOR,H5_VERS_MINOR, \ H5_VERS_RELEASE) diff --git a/src/H5win32defs.h b/src/H5win32defs.h index 5f886d1..e9b87625 100644 --- a/src/H5win32defs.h +++ b/src/H5win32defs.h @@ -33,9 +33,7 @@ typedef __int64 h5_stat_size_t; #define HDdup(F) _dup(F) #define HDfdopen(N,S) _fdopen(N,S) #define HDfileno(F) _fileno(F) -#define HDfseek(F,O,W) _fseeki64(F,O,W) #define HDfstat(F,B) _fstati64(F,B) -#define HDftruncate(F,L) _chsize_s(F,L) #define HDisatty(F) _isatty(F) #define HDgetcwd(S,Z) _getcwd(S,Z) #define HDgetdcwd(D,S,Z) _getdcwd(D,S,Z) @@ -91,4 +89,8 @@ struct timezone { * type cannot be cast as a ulong like other systems. */ #define HDpthread_self_ulong() ((unsigned long)GetCurrentThreadId()) +#ifndef H5_HAVE_MINGW +#define HDftruncate(F,L) _chsize_s(F,L) +#define HDfseek(F,O,W) _fseeki64(F,O,W) +#endif #endif /* H5_HAVE_WIN32_API */ diff --git a/src/Makefile.am b/src/Makefile.am old mode 100755 new mode 100644 diff --git a/src/Makefile.in b/src/Makefile.in index bf7f62d..4d226cd 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -486,7 +486,7 @@ CHECK_CLEANFILES = *.chkexe *.chklog *.clog # Add libtool shared library version numbers to the HDF5 library # See libtool versioning documentation online. LT_VERS_INTERFACE = 6 -LT_VERS_REVISION = 101 +LT_VERS_REVISION = 103 LT_VERS_AGE = 0 H5detect_CFLAGS = -g $(AM_CFLAGS) diff --git a/src/hdf5.lnt b/src/hdf5.lnt old mode 100755 new mode 100644 diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a2577b9..a6ff10b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -87,6 +87,7 @@ SET (HDF5_REFERENCE_TEST_FILES family_v16_00003.h5 filespace_1_6.h5 filespace_1_8.h5 + file_image_core_test.h5 fill_old.h5 filter_error.h5 group_old.h5 @@ -307,6 +308,7 @@ SET (H5_TESTS tcheck_version testmeta #links_env + file_image ) FOREACH (test ${H5_TESTS}) @@ -630,6 +632,7 @@ IF (HDF5_BUILD_GENERATORS AND NOT BUILD_SHARED_LIBS) gen_filespace gen_specmetaread gen_sizes_lheap + gen_file_image ) FOREACH (gen ${H5_GENERATORS}) diff --git a/test/COPYING b/test/COPYING old mode 100755 new mode 100644 diff --git a/test/Makefile.am b/test/Makefile.am index df093b7..d5cd2b5 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -43,7 +43,7 @@ TEST_PROG= testhdf5 lheap ohdr stab gheap cache cache_api cache_tagging \ big mtime fillval mount flush1 flush2 app_ref enum \ set_extent ttsafe \ getname vfd ntypes dangle dtransform reserved cross_read \ - freespace mf farray earray btree2 fheap + freespace mf farray earray btree2 fheap file_image bin_PROGRAMS=swmr_generator swmr_reader swmr_writer swmr_remove_reader \ swmr_remove_writer swmr_addrem_writer swmr_sparse_reader swmr_sparse_writer @@ -68,7 +68,7 @@ check_PROGRAMS=$(TEST_PROG) error_test err_compat tcheck_version testmeta links_ BUILD_ALL_PROGS=gen_bad_ohdr gen_bogus gen_cross gen_deflate gen_filters gen_idx gen_new_array \ gen_new_fill gen_new_group gen_new_mtime gen_new_super gen_noencoder \ gen_nullspace gen_udlinks space_overflow gen_filespace gen_specmetaread \ - gen_sizes_lheap + gen_sizes_lheap gen_file_image if BUILD_ALL_CONDITIONAL noinst_PROGRAMS=$(BUILD_ALL_PROGS) diff --git a/test/Makefile.in b/test/Makefile.in index d462da7..d7467f1 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -100,7 +100,8 @@ am__EXEEXT_1 = testhdf5$(EXEEXT) lheap$(EXEEXT) ohdr$(EXEEXT) \ ttsafe$(EXEEXT) getname$(EXEEXT) vfd$(EXEEXT) ntypes$(EXEEXT) \ dangle$(EXEEXT) dtransform$(EXEEXT) reserved$(EXEEXT) \ cross_read$(EXEEXT) freespace$(EXEEXT) mf$(EXEEXT) \ - farray$(EXEEXT) earray$(EXEEXT) btree2$(EXEEXT) fheap$(EXEEXT) + farray$(EXEEXT) earray$(EXEEXT) btree2$(EXEEXT) fheap$(EXEEXT) \ + file_image$(EXEEXT) am__EXEEXT_2 = gen_bad_ohdr$(EXEEXT) gen_bogus$(EXEEXT) \ gen_cross$(EXEEXT) gen_deflate$(EXEEXT) gen_filters$(EXEEXT) \ gen_idx$(EXEEXT) gen_new_array$(EXEEXT) gen_new_fill$(EXEEXT) \ @@ -108,7 +109,8 @@ am__EXEEXT_2 = gen_bad_ohdr$(EXEEXT) gen_bogus$(EXEEXT) \ gen_new_super$(EXEEXT) gen_noencoder$(EXEEXT) \ gen_nullspace$(EXEEXT) gen_udlinks$(EXEEXT) \ space_overflow$(EXEEXT) gen_filespace$(EXEEXT) \ - gen_specmetaread$(EXEEXT) gen_sizes_lheap$(EXEEXT) + gen_specmetaread$(EXEEXT) gen_sizes_lheap$(EXEEXT) \ + gen_file_image$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) accum_SOURCES = accum.c accum_OBJECTS = accum.$(OBJEXT) @@ -206,6 +208,10 @@ fheap_SOURCES = fheap.c fheap_OBJECTS = fheap.$(OBJEXT) fheap_LDADD = $(LDADD) fheap_DEPENDENCIES = libh5test.la $(LIBHDF5) +file_image_SOURCES = file_image.c +file_image_OBJECTS = file_image.$(OBJEXT) +file_image_LDADD = $(LDADD) +file_image_DEPENDENCIES = libh5test.la $(LIBHDF5) fillval_SOURCES = fillval.c fillval_OBJECTS = fillval.$(OBJEXT) fillval_LDADD = $(LDADD) @@ -246,6 +252,10 @@ gen_deflate_SOURCES = gen_deflate.c gen_deflate_OBJECTS = gen_deflate.$(OBJEXT) gen_deflate_LDADD = $(LDADD) gen_deflate_DEPENDENCIES = libh5test.la $(LIBHDF5) +gen_file_image_SOURCES = gen_file_image.c +gen_file_image_OBJECTS = gen_file_image.$(OBJEXT) +gen_file_image_LDADD = $(LDADD) +gen_file_image_DEPENDENCIES = libh5test.la $(LIBHDF5) gen_filespace_SOURCES = gen_filespace.c gen_filespace_OBJECTS = gen_filespace.$(OBJEXT) gen_filespace_LDADD = $(LDADD) @@ -466,9 +476,28 @@ SOURCES = $(libh5test_la_SOURCES) accum.c app_ref.c big.c bittests.c \ btree2.c cache.c cache_api.c cache_tagging.c cmpd_dset.c \ cross_read.c dangle.c dsets.c dt_arith.c dtransform.c dtypes.c \ earray.c efc.c enum.c err_compat.c error_test.c extend.c \ - external.c farray.c fheap.c fillval.c filter_fail.c flush1.c \ - flush2.c flushrefresh.c freespace.c gen_bad_ohdr.c gen_bogus.c \ - gen_cross.c gen_deflate.c gen_filespace.c gen_filters.c \ + external.c farray.c fheap.c file_image.c fillval.c \ + filter_fail.c flush1.c flush2.c flushrefresh.c freespace.c \ + gen_bad_ohdr.c gen_bogus.c gen_cross.c gen_deflate.c \ + gen_file_image.c gen_filespace.c gen_filters.c gen_idx.c \ + gen_new_array.c gen_new_fill.c gen_new_group.c gen_new_mtime.c \ + gen_new_super.c gen_noencoder.c gen_nullspace.c \ + gen_sizes_lheap.c gen_specmetaread.c gen_udlinks.c getname.c \ + gheap.c hyperslab.c istore.c lheap.c links.c links_env.c mf.c \ + mount.c mtime.c ntypes.c objcopy.c ohdr.c pool.c reserved.c \ + 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) unlink.c vfd.c +DIST_SOURCES = $(libh5test_la_SOURCES) accum.c app_ref.c big.c \ + bittests.c btree2.c cache.c cache_api.c cache_tagging.c \ + cmpd_dset.c cross_read.c dangle.c dsets.c dt_arith.c \ + dtransform.c dtypes.c earray.c efc.c enum.c err_compat.c \ + error_test.c extend.c external.c farray.c fheap.c file_image.c \ + fillval.c filter_fail.c flush1.c flush2.c flushrefresh.c \ + freespace.c gen_bad_ohdr.c gen_bogus.c gen_cross.c \ + gen_deflate.c gen_file_image.c gen_filespace.c gen_filters.c \ gen_idx.c gen_new_array.c gen_new_fill.c gen_new_group.c \ gen_new_mtime.c gen_new_super.c gen_noencoder.c \ gen_nullspace.c gen_sizes_lheap.c gen_specmetaread.c \ @@ -480,24 +509,6 @@ SOURCES = $(libh5test_la_SOURCES) accum.c app_ref.c big.c bittests.c \ swmr_sparse_writer.c swmr_writer.c tcheck_version.c \ $(testhdf5_SOURCES) testmeta.c $(ttsafe_SOURCES) unlink.c \ vfd.c -DIST_SOURCES = $(libh5test_la_SOURCES) accum.c app_ref.c big.c \ - bittests.c btree2.c cache.c cache_api.c cache_tagging.c \ - cmpd_dset.c cross_read.c dangle.c dsets.c dt_arith.c \ - dtransform.c dtypes.c earray.c efc.c enum.c err_compat.c \ - error_test.c extend.c external.c farray.c fheap.c fillval.c \ - filter_fail.c flush1.c flush2.c flushrefresh.c freespace.c \ - gen_bad_ohdr.c gen_bogus.c gen_cross.c gen_deflate.c \ - gen_filespace.c gen_filters.c gen_idx.c gen_new_array.c \ - gen_new_fill.c gen_new_group.c gen_new_mtime.c gen_new_super.c \ - gen_noencoder.c gen_nullspace.c gen_sizes_lheap.c \ - gen_specmetaread.c gen_udlinks.c getname.c gheap.c hyperslab.c \ - istore.c lheap.c links.c links_env.c mf.c mount.c mtime.c \ - ntypes.c objcopy.c ohdr.c pool.c reserved.c 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) unlink.c vfd.c ETAGS = etags CTAGS = ctags am__tty_colors = \ @@ -839,7 +850,7 @@ TEST_PROG = testhdf5 lheap ohdr stab gheap cache cache_api cache_tagging \ big mtime fillval mount flush1 flush2 app_ref enum \ set_extent ttsafe \ getname vfd ntypes dangle dtransform reserved cross_read \ - freespace mf farray earray btree2 fheap + freespace mf farray earray btree2 fheap file_image # These programs generate test files for the tests. They don't need to be @@ -852,7 +863,7 @@ TEST_PROG = testhdf5 lheap ohdr stab gheap cache cache_api cache_tagging \ BUILD_ALL_PROGS = gen_bad_ohdr gen_bogus gen_cross gen_deflate gen_filters gen_idx gen_new_array \ gen_new_fill gen_new_group gen_new_mtime gen_new_super gen_noencoder \ gen_nullspace gen_udlinks space_overflow gen_filespace gen_specmetaread \ - gen_sizes_lheap + gen_sizes_lheap gen_file_image # The libh5test library provides common support code for the tests. @@ -1086,6 +1097,9 @@ farray$(EXEEXT): $(farray_OBJECTS) $(farray_DEPENDENCIES) fheap$(EXEEXT): $(fheap_OBJECTS) $(fheap_DEPENDENCIES) @rm -f fheap$(EXEEXT) $(AM_V_CCLD)$(LINK) $(fheap_OBJECTS) $(fheap_LDADD) $(LIBS) +file_image$(EXEEXT): $(file_image_OBJECTS) $(file_image_DEPENDENCIES) + @rm -f file_image$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(file_image_OBJECTS) $(file_image_LDADD) $(LIBS) fillval$(EXEEXT): $(fillval_OBJECTS) $(fillval_DEPENDENCIES) @rm -f fillval$(EXEEXT) $(AM_V_CCLD)$(LINK) $(fillval_OBJECTS) $(fillval_LDADD) $(LIBS) @@ -1116,6 +1130,9 @@ gen_cross$(EXEEXT): $(gen_cross_OBJECTS) $(gen_cross_DEPENDENCIES) gen_deflate$(EXEEXT): $(gen_deflate_OBJECTS) $(gen_deflate_DEPENDENCIES) @rm -f gen_deflate$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gen_deflate_OBJECTS) $(gen_deflate_LDADD) $(LIBS) +gen_file_image$(EXEEXT): $(gen_file_image_OBJECTS) $(gen_file_image_DEPENDENCIES) + @rm -f gen_file_image$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gen_file_image_OBJECTS) $(gen_file_image_LDADD) $(LIBS) gen_filespace$(EXEEXT): $(gen_filespace_OBJECTS) $(gen_filespace_DEPENDENCIES) @rm -f gen_filespace$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gen_filespace_OBJECTS) $(gen_filespace_LDADD) $(LIBS) @@ -1283,6 +1300,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/external.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/farray.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fheap.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file_image.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fillval.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/filter_fail.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flush1.Po@am__quote@ @@ -1293,6 +1311,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen_bogus.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen_cross.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen_deflate.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen_file_image.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen_filespace.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen_filters.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen_idx.Po@am__quote@ diff --git a/test/corrupt_stab_msg.h5 b/test/corrupt_stab_msg.h5 old mode 100755 new mode 100644 diff --git a/test/cross_read.c b/test/cross_read.c old mode 100755 new mode 100644 diff --git a/test/fheap.c b/test/fheap.c index 2cb8796..e4aa137 100644 --- a/test/fheap.c +++ b/test/fheap.c @@ -415,13 +415,20 @@ add_obj(H5HF_t *fh, hid_t dxpl, size_t obj_off, if(keep_ids) { /* Check for needing to increase size of heap ID array */ if(keep_ids->num_ids + 1 > keep_ids->alloc_ids) { + unsigned char *tmp_ids; + size_t *tmp_lens; + size_t *tmp_offs; + keep_ids->alloc_ids = MAX(1024, (keep_ids->alloc_ids * 2)); - if(NULL == (keep_ids->ids = (unsigned char *)H5MM_realloc(keep_ids->ids, id_len * keep_ids->alloc_ids))) + if(NULL == (tmp_ids = (unsigned char *)H5MM_realloc(keep_ids->ids, id_len * keep_ids->alloc_ids))) TEST_ERROR - if(NULL == (keep_ids->lens = (size_t *)H5MM_realloc(keep_ids->lens, sizeof(size_t) * keep_ids->alloc_ids))) + keep_ids->ids = tmp_ids; + if(NULL == (tmp_lens = (size_t *)H5MM_realloc(keep_ids->lens, sizeof(size_t) * keep_ids->alloc_ids))) TEST_ERROR - if(NULL == (keep_ids->offs = (size_t *)H5MM_realloc(keep_ids->offs, sizeof(size_t) * keep_ids->alloc_ids))) + keep_ids->lens = tmp_lens; + if(NULL == (tmp_offs = (size_t *)H5MM_realloc(keep_ids->offs, sizeof(size_t) * keep_ids->alloc_ids))) TEST_ERROR + keep_ids->offs = tmp_offs; } /* end if */ /* Append the object info onto the array */ @@ -501,6 +508,7 @@ get_fill_size(const fheap_test_param_t *tparam) case FHEAP_TEST_FILL_SINGLE: return((size_t)0); + case FHEAP_TEST_FILL_N: default: HDassert(0 && "Unknown bulk fill type?!?"); } /* end switch */ @@ -6446,7 +6454,7 @@ test_man_remove_bogus(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpa /* seed = (unsigned long)1155438845; */ HDfprintf(stderr, "Random # seed was: %lu\n", seed); #endif /* QAK */ - HDsrandom(seed); + HDsrandom((unsigned)seed); /* Set heap ID to random (non-null) value */ heap_id[0] = H5HF_ID_VERS_CURR | H5HF_ID_TYPE_MAN; @@ -7587,6 +7595,117 @@ error: } H5E_END_TRY; return(1); } /* test_man_remove_three_larger() */ + + +/*------------------------------------------------------------------------- + * Function: test_man_incr_insert_remove + * + * Purpose: Test incremental insert & removal of objects in heap + * + * Return: Success: 0 + * Failure: 1 + * + * Programmer: Quincey Koziol + * Sunday, April 1, 2012 + * + *------------------------------------------------------------------------- + */ +static unsigned +test_man_incr_insert_remove(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tparam) +{ + hid_t file = -1; /* File ID */ + hid_t dxpl = H5P_DATASET_XFER_DEFAULT; /* DXPL to use */ + char filename[FHEAP_FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5HF_t *fh = NULL; /* Fractal heap wrapper */ + haddr_t fh_addr; /* Address of fractal heap */ + unsigned char heap_id[100][MAX_HEAP_ID_LEN]; /* Heap ID for object inserted */ + struct a_type_t1 { + char a[10]; + char b[29]; + } obj1, obj2; /* Objects to insert/remove */ + size_t id_len; /* Size of fractal heap IDs */ + fheap_heap_state_t state; /* State of fractal heap */ + int i, j; + + /* 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((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + STACK_ERROR + + /* Ignore metadata tags in the file's cache */ + if(H5AC_ignore_tags(f) < 0) + STACK_ERROR + + /* Create absolute heap */ + if(NULL == (fh = H5HF_create(f, dxpl, cparam))) + FAIL_STACK_ERROR + if(H5HF_get_id_len(fh, &id_len) < 0) + FAIL_STACK_ERROR + if(id_len > HEAP_ID_LEN) + FAIL_STACK_ERROR + if(H5HF_get_heap_addr(fh, &fh_addr) < 0) + FAIL_STACK_ERROR + if(!H5F_addr_defined(fh_addr)) + FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* + * Test incremental insert and removal + */ + TESTING("incremental object insertion and removal") + + for(i = 0; i < 100; i++) { + sprintf(obj1.b, "%s%d", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", i); + + for(j = 0; j < i; j++) { + sprintf(obj2.b, "%s%d", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", j); + + if(H5HF_remove(fh, dxpl, heap_id[j]) < 0) + FAIL_STACK_ERROR + if(H5HF_insert(fh, dxpl, (sizeof(obj2)), &obj2, heap_id[j]) < 0) + FAIL_STACK_ERROR + } /* end for */ + + /* Check for closing & re-opening the heap */ + if(reopen_heap(f, dxpl, &fh, fh_addr, tparam) < 0) + TEST_ERROR + + /* Insert object */ + HDmemset(heap_id[i], 0, id_len); + if(H5HF_insert(fh, dxpl, (sizeof(obj1)), &obj1, heap_id[i]) < 0) + FAIL_STACK_ERROR + } /* end for */ + + /* Close the fractal heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Close the file */ + if(H5Fclose(file) < 0) + TEST_ERROR + + /* All tests passed */ + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + if(fh) + H5HF_close(fh, dxpl); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_man_incr_insert_remove() */ #endif /* QAK */ #ifndef QAK @@ -15413,7 +15532,7 @@ test_random(hsize_t size_limit, hid_t fapl, H5HF_create_t *cparam, fheap_test_pa /* seed = (unsigned long)1156158635; */ HDfprintf(stderr, "Random # seed was: %lu\n", seed); #endif /* QAK */ - HDsrandom(seed); + HDsrandom((unsigned)seed); /* Loop over adding objects to the heap, until the size limit is reached */ total_obj_added = 0; @@ -15617,7 +15736,7 @@ test_random_pow2(hsize_t size_limit, hid_t fapl, H5HF_create_t *cparam, fheap_te /* seed = (unsigned long)1155181717; */ HDfprintf(stderr, "Random # seed was: %lu\n", seed); #endif /* QAK */ - HDsrandom(seed); + HDsrandom((unsigned)seed); /* Loop over adding objects to the heap, until the size limit is reached */ total_obj_added = 0; @@ -15831,7 +15950,7 @@ test_write(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tparam) filter_class.set_local = NULL; filter_class.filter = test_write_filter; if(H5Zregister(&filter_class) < 0) TEST_ERROR - if(H5Z_append(&tmp_cparam.pline, H5Z_FILTER_RESERVED + 43, 0, 0, NULL) < 0) + if(H5Z_append(&tmp_cparam.pline, H5Z_FILTER_RESERVED + 43, 0, (size_t)0, NULL) < 0) FAIL_STACK_ERROR test_write_filter_called = FALSE; } /* end if */ @@ -16285,6 +16404,7 @@ curr_test = FHEAP_TEST_NORMAL; break; /* An unknown test? */ + case FHEAP_TEST_NTESTS: default: goto error; } /* end switch */ @@ -16333,6 +16453,7 @@ fill = FHEAP_TEST_FILL_LARGE; break; /* An unknown test? */ + case FHEAP_TEST_FILL_N: default: goto error; } /* end switch */ @@ -16341,8 +16462,12 @@ fill = FHEAP_TEST_FILL_LARGE; * Test fractal heap managed object insertion */ +#ifndef QAK /* "Weird" sized objects */ nerrors += test_man_insert_weird(fapl, &small_cparam, &tparam); +#else /* QAK */ +HDfprintf(stderr, "Uncomment tests!\n"); +#endif /* QAK */ #ifdef ALL_INSERT_TESTS /* "Standard" sized objects, building from simple to complex heaps */ @@ -16404,6 +16529,10 @@ HDfprintf(stderr, "Uncomment tests!\n"); nerrors += test_man_remove_three_larger(fapl, &small_cparam, &tparam); tparam.del_dir = FHEAP_DEL_REVERSE; nerrors += test_man_remove_three_larger(fapl, &small_cparam, &tparam); + + /* Incremental insert & removal */ + tparam.del_dir = FHEAP_DEL_FORWARD; + nerrors += test_man_incr_insert_remove(fapl, &small_cparam, &tparam); #else /* QAK */ HDfprintf(stderr, "Uncomment tests!\n"); #endif /* QAK */ @@ -16445,6 +16574,8 @@ tparam.drain_half = FHEAP_DEL_DRAIN_ALL; nerrors += test_man_remove_2nd_indirect(fapl, &small_cparam, &tparam); nerrors += test_man_remove_3rd_indirect(fapl, &small_cparam, &tparam); } /* end else */ +#else /* QAK */ +HDfprintf(stderr, "Uncomment tests!\n"); #endif /* QAK */ #ifndef QAK diff --git a/test/file_image.c b/test/file_image.c new file mode 100644 index 0000000..7c2c3ff --- /dev/null +++ b/test/file_image.c @@ -0,0 +1,1335 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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: file_image +* +* Test setting file images +* +*************************************************************/ + +#include "h5test.h" +#include "H5srcdir.h" +#include "H5Fprivate.h" /* required to test property removals */ +#define VERIFY(condition, string) do { if (!(condition)) FAIL_PUTS_ERROR(string) } while(0) + +/* Values for callback bit field */ +#define MALLOC 0x01 +#define MEMCPY 0x02 +#define REALLOC 0x04 +#define FREE 0x08 +#define UDATA_COPY 0x10 +#define UDATA_FREE 0x20 + +#define RANK 2 +#define DIM0 1024 +#define DIM1 32 +#define DSET_NAME "test_dset" + +#define FAMILY_SIZE (2 * 1024) + +const char *FILENAME[] = { + "file_image_core_test", + NULL +}; + +/* need a second file name array, as the first file name array contains + * files we don't want to delete on cleanup. + */ +const char *FILENAME2[] = { + "sec2_get_file_image_test", + "stdio_get_file_image_test", + "core_get_file_image_test", + "family_get_file_image_test", + "multi_get_file_image_test", + "split_get_file_image_test", + "get_file_image_error_rejection_test", + NULL +}; + +typedef struct { + unsigned char used_callbacks; /* Bitfield for tracking callbacks */ + H5FD_file_image_op_t malloc_src; /* Source of file image callbacks */ + H5FD_file_image_op_t memcpy_src; + H5FD_file_image_op_t realloc_src; + H5FD_file_image_op_t free_src; +} udata_t; + + +/****************************************************************************** + * Function: test_properties + * + * Purpose: Tests that the file image properties (buffer pointer and length) + * are set properly. Image callbacks are not set in this test. + * + * Returns: Success: 0 + * Failure: 1 + * + * Programmer: Jacob Gruber + * Monday, August 22, 2011 + * + ****************************************************************************** + */ +static int +test_properties(void) +{ + hid_t fapl_1; + hid_t fapl_2; + char *buffer; + int count = 10; + void *temp; + char *temp2; + int i; + size_t size; + size_t temp_size; + + TESTING("File image property list functions"); + + /* Initialize file image buffer + * + * Note: this image will not contain a valid HDF5 file, as it complicates testing + * property list functions. In the file driver tests further down, this will + * not be the case. + */ + size = (size_t)count * sizeof(char); + buffer = (char *)HDmalloc(size); + for(i = 0; i < count - 1; i++) + buffer[i] = (char)(65 + i); + buffer[count] = '\0'; + + /* Create fapl */ + if((fapl_1 = H5Pcreate(H5P_FILE_ACCESS)) < 0) FAIL_STACK_ERROR + + /* Get file image stuff */ + if(H5Pget_file_image(fapl_1, (void **)&temp, &temp_size) < 0) FAIL_STACK_ERROR + + /* Check default values */ + VERIFY(temp == NULL, "Default pointer is wrong"); + VERIFY(temp_size == 0, "Default size is wrong"); + + /* Set file image stuff */ + if(H5Pset_file_image(fapl_1, (void *)buffer, size) < 0) FAIL_STACK_ERROR + + /* Get the same */ + if(H5Pget_file_image(fapl_1, (void **)&temp, &temp_size) < 0) FAIL_STACK_ERROR + + /* Check that sizes are the same, and that the buffers are identical but separate */ + VERIFY(temp != NULL, "temp is null!"); + VERIFY(temp_size == size, "Sizes of buffers don't match"); + VERIFY(temp != buffer, "Retrieved buffer is the same as original"); + VERIFY(0 == HDmemcmp(temp, buffer, size), "Buffers contain different data"); + + /* Copy the fapl */ + if((fapl_2 = H5Pcopy(fapl_1)) < 0) FAIL_STACK_ERROR + + /* Get values from the new fapl */ + if(H5Pget_file_image(fapl_2, (void **)&temp2, &temp_size) < 0) FAIL_STACK_ERROR + + /* Check that sizes are the same, and that the buffers are identical but separate */ + VERIFY(temp_size == size,"Sizes of buffers don't match"); + VERIFY(temp2 != NULL,"Recieved buffer not set"); + VERIFY(temp2 != buffer, "Retrieved buffer is the same as original"); + VERIFY(temp2 != temp, "Retrieved buffer is the same as previously retrieved buffer"); + VERIFY(0 == HDmemcmp(temp2, buffer, size),"Buffers contain different data"); + + /* Close everything */ + if(H5Pclose(fapl_1) < 0) FAIL_STACK_ERROR + if(H5Pclose(fapl_2) < 0) FAIL_STACK_ERROR + HDfree(buffer); + HDfree(temp); + HDfree(temp2); + + PASSED(); + return 0; + +error: + return 1; +} /* end test_properties() */ + +/****************************************************************************** + * Function: malloc_cb + * + * Purpose: This function allows calls to the malloc callback to be tracked. + * + * Returns: The result of a standard malloc + * + * Programmer: Jacob Gruber + * Monday, August 22, 2011 + * + ****************************************************************************** + */ +static void * +malloc_cb(size_t size, H5FD_file_image_op_t op, void *udata) +{ + udata_t *u = (udata_t *)udata; + + u->used_callbacks |= MALLOC; + u->malloc_src = op; + return HDmalloc(size); +} + +/****************************************************************************** + * Function: memcpy_cb + * + * Purpose: This function allows calls to the memcpy callback to be tracked. + * + * Returns: The result of a standard memcpy + * + * Programmer: Jacob Gruber + * Monday, August 22, 2011 + * + ****************************************************************************** + */ +static void * +memcpy_cb(void *dest, const void *src, size_t size, H5FD_file_image_op_t op, void *udata) +{ + udata_t *u = (udata_t *)udata; + + u->used_callbacks |= MEMCPY; + u->memcpy_src = op; + return HDmemcpy(dest, src, size); +} + +/****************************************************************************** + * Function: realloc_cb + * + * Purpose: This function allows calls to the realloc callback to be tracked. + * + * Returns: The result of a standard realloc + * + * Programmer: Jacob Gruber + * Monday, August 22, 2011 + * + ****************************************************************************** + */ +static void * +realloc_cb(void *ptr, size_t size, H5FD_file_image_op_t op, void *udata) +{ + udata_t *u = (udata_t *)udata; + + u->used_callbacks |= REALLOC; + u->realloc_src = op; + return HDrealloc(ptr,size); +} + +/****************************************************************************** + * Function: free_cb + * + * Purpose: This function allows calls to the free callback to be tracked. + * + * Programmer: Jacob Gruber + * Monday, August 22, 2011 + * + ****************************************************************************** + */ +static herr_t +free_cb(void *ptr, H5FD_file_image_op_t op, void *udata) +{ + udata_t *u = (udata_t *)udata; + + u->used_callbacks |= FREE; + u->free_src = op; + HDfree(ptr); + return(SUCCEED); +} + +/****************************************************************************** + * Function: udata_copy_cb + * + * Purpose: This function allows calls to the udata_copy callback to be tracked. + * No copying actualy takes place; it is easier to deal with only one + * instance of the udata. + * + * Returns: A pointer to the same udata that was passed in. + * + * Programmer: Jacob Gruber + * Monday, August 22, 2011 + * + ****************************************************************************** + */ +static void * +udata_copy_cb(void *udata) +{ + udata_t *u = (udata_t *)udata; + + u->used_callbacks |= UDATA_COPY; + return udata; +} + +/****************************************************************************** + * Function: udata_free_cb + * + * Purpose: This function allows calls to the udata_free callback to be tracked. + * + * Note: this callback doesn't actually do anything. Since the + * udata_copy callback doesn't copy, only one instance of the udata + * is kept alive and such it must be freed explicitly at the end of the tests. + * + * Programmer: Jacob Gruber + * Monday, August 22, 2011 + * + ****************************************************************************** + */ +static herr_t +udata_free_cb(void *udata) +{ + udata_t *u = (udata_t *)udata; + + u->used_callbacks |= UDATA_FREE; + return(SUCCEED); +} + +/****************************************************************************** + * Function: reset_udata + * + * Purpose: Resets the udata to default values. This facilitates storing only + * the results of a single operation in the udata. + * + * Programmer: Jacob Gruber + * Monday, August 22, 2011 + * + ****************************************************************************** + */ +static void +reset_udata(udata_t *u) +{ + u->used_callbacks = 0; + u->malloc_src = u->memcpy_src = u->realloc_src = u->free_src = H5FD_FILE_IMAGE_OP_NO_OP; +} + +/****************************************************************************** + * Function: test_callbacks + * + * Purpose: Tests that callbacks are called properly in property list functions. + * + * Programmer: Jacob Gruber + * Monday, August 22, 2011 + * + ****************************************************************************** + */ +static int +test_callbacks(void) +{ + H5FD_file_image_callbacks_t real_callbacks = {&malloc_cb, &memcpy_cb, &realloc_cb, + &free_cb, &udata_copy_cb, &udata_free_cb, NULL}; + H5FD_file_image_callbacks_t null_callbacks = {NULL, NULL, NULL, NULL, NULL, NULL, NULL}; + H5FD_file_image_callbacks_t callbacks; + hid_t fapl_1; + hid_t fapl_2; + udata_t *udata; + char *file_image; + char *temp_file_image; + int count = 10; + int i; + size_t size; + size_t temp_size; + + TESTING("Callback use in property list operations"); + + /* Allocate and initialize udata */ + udata = (udata_t *)HDmalloc(sizeof(udata_t)); + reset_udata(udata); + + /* copy the address of the user data into read_callbacks */ + real_callbacks.udata = (void *)udata; + + /* Allocate and initialize file image buffer */ + size = (size_t)count * sizeof(char); + file_image = (char *)HDmalloc(size); + for(i = 0; i < count - 1; i++) + file_image[i] = (char)(65 + i); + file_image[count] = '\0'; + + /* Create fapl */ + if((fapl_1 = H5Pcreate(H5P_FILE_ACCESS)) < 0) FAIL_STACK_ERROR + + /* Get file image stuff */ + callbacks = real_callbacks; + if(H5Pget_file_image_callbacks(fapl_1, &callbacks) < 0) FAIL_STACK_ERROR + + /* Check default values */ + VERIFY(callbacks.image_malloc == NULL, "Default malloc callback is wrong"); + VERIFY(callbacks.image_memcpy == NULL, "Default memcpy callback is wrong"); + VERIFY(callbacks.image_realloc == NULL, "Default realloc callback is wrong"); + VERIFY(callbacks.image_free == NULL, "Default free callback is wrong"); + VERIFY(callbacks.udata_copy == NULL, "Default udata copy callback is wrong"); + VERIFY(callbacks.udata_free == NULL, "Default udata free callback is wrong"); + VERIFY(callbacks.udata == NULL, "Default udata is wrong"); + + + /* Set file image callbacks */ + callbacks = real_callbacks; + if(H5Pset_file_image_callbacks(fapl_1, &callbacks) < 0) FAIL_STACK_ERROR + + /* Get file image callbacks */ + callbacks = null_callbacks; + if(H5Pget_file_image_callbacks(fapl_1, &callbacks) < 0) FAIL_STACK_ERROR + + /* Verify values */ + VERIFY(callbacks.image_malloc == &malloc_cb, "malloc callback was not set or retrieved properly"); + VERIFY(callbacks.image_memcpy == &memcpy_cb, "memcpy callback was not set or retrieved properly"); + VERIFY(callbacks.image_realloc == &realloc_cb, "realloc callback was not set or retrieved properly"); + VERIFY(callbacks.image_free == &free_cb, "free callback was not set or retrieved properly"); + VERIFY(callbacks.udata_copy == &udata_copy_cb, "udata copy callback was not set or retrieved properly"); + VERIFY(callbacks.udata_free == &udata_free_cb, "udata free callback was not set or retrieved properly"); + VERIFY(callbacks.udata == udata, "udata was not set or retrieved properly"); + + + /* + * Check callbacks in internal function without a previously set file image + */ + + /* Copy fapl */ + reset_udata(udata); + if((fapl_2 = H5Pcopy(fapl_1)) < 0) FAIL_STACK_ERROR + + /* Verify that the property's copy callback used the correct image callbacks */ + VERIFY(udata->used_callbacks == (UDATA_COPY), "Copying a fapl with no image used incorrect callbacks"); + + /* Close fapl */ + reset_udata(udata); + if(H5Pclose(fapl_2) < 0) FAIL_STACK_ERROR + + /* Verify that the udata free callback was used */ + VERIFY(udata->used_callbacks == (UDATA_FREE), "Closing a fapl with no image used incorrect callbacks"); + + /* Copy again */ + if((fapl_2 = H5Pcopy(fapl_1)) < 0) FAIL_STACK_ERROR + + /* Remove property from fapl */ + reset_udata(udata); + if(H5Premove(fapl_2, H5F_ACS_FILE_IMAGE_INFO_NAME) < 0) FAIL_STACK_ERROR + + /* Verify that the property's delete callback was called using the correct image callbacks */ + VERIFY(udata->used_callbacks == (UDATA_FREE), "Removing a property from a fapl with no image used incorrect callbacks"); + + /* Close it again */ + if(H5Pclose(fapl_2) < 0) FAIL_STACK_ERROR + + /* Get file image */ + reset_udata(udata); + if(H5Pget_file_image(fapl_1, (void **)&temp_file_image, &temp_size) < 0) FAIL_STACK_ERROR + + /* Verify that the correct callbacks were used */ + VERIFY(udata->used_callbacks == 0, "attempting to retrieve the image from a fapl without an image has an unexpected callback"); + + /* Set file image */ + reset_udata(udata); + if(H5Pset_file_image(fapl_1, (void *)file_image, size) < 0) FAIL_STACK_ERROR + + VERIFY(udata->used_callbacks == (MALLOC | MEMCPY), "Setting a file image (first time) used incorrect callbacks"); + + /* + * Check callbacks in internal functions with a previously set file image + */ + + /* Copy fapl */ + reset_udata(udata); + if((fapl_2 = H5Pcopy(fapl_1)) < 0) FAIL_STACK_ERROR + + /* Verify that the property's copy callback used the correct image callbacks */ + VERIFY(udata->used_callbacks == (MALLOC | MEMCPY | UDATA_COPY), "Copying a fapl with an image used incorrect callbacks"); + VERIFY(udata->malloc_src == H5FD_FILE_IMAGE_OP_PROPERTY_LIST_COPY, "malloc callback has wrong source"); + VERIFY(udata->memcpy_src == H5FD_FILE_IMAGE_OP_PROPERTY_LIST_COPY, "memcpy callback has wrong source"); + + /* Close fapl */ + reset_udata(udata); + if(H5Pclose(fapl_2) < 0) FAIL_STACK_ERROR + + /* Verify that the udata free callback was used */ + VERIFY(udata->used_callbacks == (FREE | UDATA_FREE), "Closing a fapl with an image used incorrect callbacks"); + VERIFY(udata->free_src == H5FD_FILE_IMAGE_OP_PROPERTY_LIST_CLOSE, "free callback has wrong source"); + + /* Copy again */ + if((fapl_2 = H5Pcopy(fapl_1)) < 0) FAIL_STACK_ERROR + + /* Remove property from fapl */ + reset_udata(udata); + if(H5Premove(fapl_2, H5F_ACS_FILE_IMAGE_INFO_NAME) < 0) FAIL_STACK_ERROR + + /* Verify that the property's delete callback was called using the correct image callbacks */ + VERIFY(udata->used_callbacks == (FREE | UDATA_FREE), "Removing a property from a fapl with an image used incorrect callbacks"); + VERIFY(udata->free_src == H5FD_FILE_IMAGE_OP_PROPERTY_LIST_CLOSE, "free callback has wrong source"); + + /* Close it again */ + if(H5Pclose(fapl_2) < 0) FAIL_STACK_ERROR + + /* Get file image */ + reset_udata(udata); + if(H5Pget_file_image(fapl_1, (void **)&temp_file_image, &temp_size) < 0) FAIL_STACK_ERROR + + /* Verify that the correct callbacks were used */ + VERIFY(udata->used_callbacks == (MALLOC | MEMCPY), "attempting to retrieve the image from a fapl with an image has an unexpected callback"); + VERIFY(udata->malloc_src == H5FD_FILE_IMAGE_OP_PROPERTY_LIST_GET, "malloc callback has wrong source"); + VERIFY(udata->memcpy_src == H5FD_FILE_IMAGE_OP_PROPERTY_LIST_GET, "memcpy callback has wrong source"); + + /* Set file image */ + reset_udata(udata); + if(H5Pset_file_image(fapl_1, (void *)file_image, size) < 0) FAIL_STACK_ERROR + + VERIFY(udata->used_callbacks == (FREE | MALLOC | MEMCPY), "Setting a file image (second time) used incorrect callbacks"); + VERIFY(udata->malloc_src == H5FD_FILE_IMAGE_OP_PROPERTY_LIST_SET, "malloc callback has wrong source"); + VERIFY(udata->memcpy_src == H5FD_FILE_IMAGE_OP_PROPERTY_LIST_SET, "memcpy callback has wrong source"); + VERIFY(udata->free_src == H5FD_FILE_IMAGE_OP_PROPERTY_LIST_SET, "freec callback has wrong source"); + + /* Close stuff */ + if(H5Pclose(fapl_1) < 0) FAIL_STACK_ERROR + HDfree(file_image); + HDfree(temp_file_image); + HDfree(udata); + + PASSED(); + return 0; + +error: + return 1; +} /* test_callbacks() */ + +/****************************************************************************** + * Function: test_core + * + * Purpose: Tests that callbacks are called properly in the core VFD and + * that the initial file image works properly. + * + * Programmer: Jacob Gruber + * Monday, August 22, 2011 + * + ****************************************************************************** + */ +static int +test_core(void) +{ + hid_t fapl; + hid_t file; + hid_t dset; + hid_t space; + udata_t *udata; + unsigned char *file_image; + char filename[1024]; + char src_dir_filename[1024]; + const char *tmp = NULL; + size_t size; + hsize_t dims[2]; + int fd; + h5_stat_t sb; + herr_t ret; + H5FD_file_image_callbacks_t callbacks = {&malloc_cb, &memcpy_cb, &realloc_cb, + &free_cb, &udata_copy_cb, &udata_free_cb, NULL}; + + TESTING("Initial file image and callbacks in Core VFD"); + + /* Create fapl */ + fapl = h5_fileaccess(); + VERIFY(fapl >= 0, "fapl creation failed"); + + /* Set up the core VFD */ + ret = H5Pset_fapl_core(fapl, 0, 0); + VERIFY(ret >= 0, "setting core driver in fapl failed"); + + tmp = h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + VERIFY(tmp != NULL, "h5_fixname failed"); + + /* convert file name to srcdir file name. Make a copy as + * H5_get_srcdir_filename() simply sets up the file name in its + * own buffer each time it is called -- overwriting the previous + * value. + */ + tmp = H5_get_srcdir_filename(filename); + VERIFY(tmp != NULL, "H5_get_srcdir_filename failed"); + VERIFY(strlen(tmp) < 1023, "srcdir file name too long."); + HDstrncpy(src_dir_filename, tmp, 1023); + src_dir_filename[1023] = '\0'; + + /* Allocate and initialize udata */ + udata = (udata_t *)HDmalloc(sizeof(udata_t)); + VERIFY(udata != NULL, "udata malloc failed"); + + /* copy the address of the udata into the callbacks structure */ + callbacks.udata = (void *)udata; + + /* Set file image callbacks */ + ret = H5Pset_file_image_callbacks(fapl, &callbacks); + VERIFY(ret >= 0, "set image callbacks failed"); + + /* Test open (no file image) */ + reset_udata(udata); + file = H5Fopen(src_dir_filename, H5F_ACC_RDWR, fapl); + VERIFY(file >= 0, "H5Fopen failed"); + VERIFY(udata->used_callbacks == MALLOC, "opening a core file used the wrong callbacks"); + VERIFY(udata->malloc_src == H5FD_FILE_IMAGE_OP_FILE_OPEN, "Malloc callback came from wrong sourc in core open"); + + /* Close file */ + reset_udata(udata); + ret = H5Fclose(file); + VERIFY(ret >= 0, "H5Fclose failed"); + VERIFY(udata->used_callbacks == FREE, "Closing a core file used the wrong callbacks"); + VERIFY(udata->free_src == H5FD_FILE_IMAGE_OP_FILE_CLOSE, "Free callback came from wrong sourc in core close"); + + /* Reopen file */ + file = H5Fopen(src_dir_filename, H5F_ACC_RDWR, fapl); + VERIFY(file >= 0, "H5Fopen failed"); + + /* Set up a new dset */ + dims[0] = DIM0; + dims[1] = DIM1; + space = H5Screate_simple(RANK, dims, dims); + VERIFY(space >= 0, "H5Screate failed"); + + /* Create new dset, invoking H5FD_core_write */ + reset_udata(udata); + dset = H5Dcreate2(file, DSET_NAME, H5T_NATIVE_INT, space, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + VERIFY(dset >=0, "H5Dcreate failed"); + + /* Flush the write and check the realloc callback */ + ret = H5Fflush(file, H5F_SCOPE_LOCAL); + VERIFY(ret >= 0, "H5Fflush failed"); + VERIFY(udata->used_callbacks == (REALLOC), "core write used the wrong callbacks"); + VERIFY(udata->realloc_src == H5FD_FILE_IMAGE_OP_FILE_RESIZE, "Realloc callback came from wrong source in core write"); + + /* Close dset and space */ + ret = H5Dclose(dset); + VERIFY(ret >= 0, "H5Dclose failed"); + ret = H5Sclose(space); + VERIFY(ret >= 0, "H5Sclose failed"); + + /* Test file close */ + reset_udata(udata); + ret = H5Fclose(file); + VERIFY(ret >= 0, "H5Fclose failed"); + VERIFY(udata->used_callbacks == (FREE), "Closing a core file used the wrong callbacks"); + VERIFY(udata->free_src == H5FD_FILE_IMAGE_OP_FILE_CLOSE, "Free callback came from wrong sourc in core close"); + + /* Create file image buffer */ + fd = HDopen(src_dir_filename, O_RDONLY, 0666); + VERIFY(fd > 0, "open failed"); + ret = HDfstat(fd, &sb); + VERIFY(ret == 0, "fstat failed"); + size = (size_t)sb.st_size; + file_image = (unsigned char *)HDmalloc(size); + HDread(fd, file_image, size); + ret = HDclose(fd); + VERIFY(ret == 0, "close failed"); + + /* Set file image in plist */ + if(H5Pset_file_image(fapl, file_image, size) < 0) FAIL_STACK_ERROR + + /* Test open with file image */ + if((file = H5Fopen("dne.h5", H5F_ACC_RDWR, fapl)) < 0) FAIL_STACK_ERROR + if(H5Fclose(file) < 0) FAIL_STACK_ERROR + + /* Release resources */ + h5_cleanup(FILENAME, fapl); + HDfree(udata); + HDfree(file_image); + + PASSED(); + + return 0; + +error: + return 1; +} /* end test_core() */ + +/****************************************************************************** + * Function: test_get_file_image + * + * Purpose: Test the H5Fget_file_image() call. + * + * Programmer: John Mainzer + * Tuesday, November 15, 2011 + * + ****************************************************************************** + */ +static int +test_get_file_image(const char * test_banner, + const int file_name_num, + hid_t fapl) +{ + char file_name[1024] = "\0"; + void * insertion_ptr = NULL; + void * image_ptr = NULL; + void * file_image_ptr = NULL; + hbool_t is_family_file = FALSE; + hbool_t identical; + int data[100]; + int i; + int fd = -1; + int result; + hid_t driver = -1; + hid_t file_id = -1; + hid_t dset_id = -1; + hid_t space_id = -1; + hid_t core_fapl_id = -1; + hid_t core_file_id = -1; + herr_t err; + hsize_t dims[2]; + ssize_t bytes_read; + ssize_t image_size; + ssize_t file_size; + h5_stat_t stat_buf; + + TESTING(test_banner); + + /* set flag if we are dealing with a family file */ + driver = H5Pget_driver(fapl); + VERIFY(driver >= 0, "H5Pget_driver(fapl) failed"); + + if(driver == H5FD_FAMILY) + is_family_file = TRUE; + + /* setup the file name */ + h5_fixname(FILENAME2[file_name_num], fapl, file_name, sizeof(file_name)); + VERIFY(HDstrlen(file_name)>0, "h5_fixname failed"); + + /* create the file */ + file_id = H5Fcreate(file_name, 0, H5P_DEFAULT, fapl); + VERIFY(file_id >= 0, "H5Fcreate() failed."); + + /* Set up data space for new new data set */ + dims[0] = 10; + dims[1] = 10; + space_id = H5Screate_simple(2, dims, dims); + VERIFY(space_id >= 0, "H5Screate() failed"); + + /* Create a dataset */ + dset_id = H5Dcreate2(file_id, "dset 0", H5T_NATIVE_INT, space_id, + H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + VERIFY(dset_id >=0, "H5Dcreate() failed"); + + /* write some data to the data set */ + for (i = 0; i < 100; i++) + data[i] = i; + err = H5Dwrite(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, (void *)data); + VERIFY(err >= 0, "H5Dwrite() failed."); + + /* Flush the file */ + err = H5Fflush(file_id, H5F_SCOPE_GLOBAL); + VERIFY(err >= 0, "H5Fflush failed"); + + /* get the size of the file */ + image_size = H5Fget_file_image(file_id, NULL, (size_t)0); + VERIFY(image_size > 0, "H5Fget_file_image(1) failed."); + + /* allocate a buffer of the appropriate size */ + image_ptr = HDmalloc((size_t)image_size); + VERIFY(image_ptr != NULL, "HDmalloc(1) failed."); + + /* load the image of the file into the buffer */ + bytes_read = H5Fget_file_image(file_id, image_ptr, (size_t)image_size); + VERIFY(bytes_read == image_size, "H5Fget_file_image(2) failed."); + + /* Close dset and space */ + err = H5Dclose(dset_id); + VERIFY(err >= 0, "H5Dclose failed"); + err = H5Sclose(space_id); + VERIFY(err >= 0, "H5Sclose failed"); + + /* close the test file */ + err = H5Fclose(file_id); + VERIFY(err == SUCCEED, "H5Fclose(file_id) failed."); + + if(is_family_file) { + char member_file_name[1024]; + ssize_t bytes_to_read; + ssize_t member_size; + ssize_t size_remaining; + + i = 0; + file_size = 0; + + do { + HDsnprintf(member_file_name, 1024, file_name, i); + + /* get the size of the member file */ + result = HDstat(member_file_name, &stat_buf); + VERIFY(result == 0, "HDstat() failed."); + + member_size = (ssize_t)stat_buf.st_size; + + i++; + file_size += member_size; + } while(member_size > 0); + + /* Since we use the eoa to calculate the image size, the file size + * may be larger. This is OK, as long as (in this specialized instance) + * the remainder of the file is all '\0's. + */ + VERIFY(file_size >= image_size, "file size != image size."); + + /* allocate a buffer for the test file image */ + file_image_ptr = HDmalloc((size_t)file_size); + VERIFY(file_image_ptr != NULL, "HDmalloc(2f) failed."); + + size_remaining = image_size; + insertion_ptr = file_image_ptr; + i = 0; + + while(size_remaining > 0) { + /* construct the member file name */ + HDsnprintf(member_file_name, 1024, file_name, i); + + /* open the test file using standard I/O calls */ + fd = HDopen(member_file_name, O_RDONLY, 0666); + VERIFY(fd >= 0, "HDopen() failed."); + + if(size_remaining >= FAMILY_SIZE ){ + bytes_to_read = FAMILY_SIZE; + size_remaining -= FAMILY_SIZE; + } else { + bytes_to_read = size_remaining; + size_remaining = 0; + } + + /* read the member file from disk into the buffer */ + bytes_read = HDread(fd, insertion_ptr, (size_t)bytes_to_read); + VERIFY(bytes_read == bytes_to_read, "HDread() failed."); + + insertion_ptr = (void *)(((char *)insertion_ptr) + bytes_to_read); + + i++; + + /* close the test file */ + result = HDclose(fd); + VERIFY(result == 0, "HDclose() failed."); + } + } else { + /* get the size of the test file */ + result = HDstat(file_name, &stat_buf); + VERIFY(result == 0, "HDstat() failed."); + + /* Since we use the eoa to calculate the image size, the file size + * may be larger. This is OK, as long as (in this specialized instance) + * the remainder of the file is all '\0's. + */ + file_size = (ssize_t)stat_buf.st_size; + + /* with latest mods to truncate call in core file drive, + * file size should match image size + */ + VERIFY(file_size == image_size, "file size != image size."); + + /* allocate a buffer for the test file image */ + file_image_ptr = HDmalloc((size_t)file_size); + VERIFY(file_image_ptr != NULL, "HDmalloc(2) failed."); + + /* open the test file using standard I/O calls */ + fd = HDopen(file_name, O_RDONLY, 0666); + VERIFY(fd >= 0, "HDopen() 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."); + + /* close the test file */ + result = HDclose(fd); + VERIFY(result == 0, "HDclose() failed."); + } + + /* verify that the file and the image contain the same data */ + identical = TRUE; + i = 0; + while((i < (int)image_size) && identical) { + if(((char *)image_ptr)[i] != ((char *)file_image_ptr)[i]) + identical = FALSE; + i++; + } + VERIFY(identical, "file and image differ."); + + + /* finally, verify that we can use the core file driver to open the image */ + + /* create fapl for core file driver */ + core_fapl_id = H5Pcreate(H5P_FILE_ACCESS); + VERIFY(core_fapl_id >=0, "H5Pcreate() failed"); + + /* setup core_fapl_id to use the core file driver */ + err = H5Pset_fapl_core(core_fapl_id, (size_t)(64 * 1024), FALSE); + VERIFY(err == SUCCEED, "H5Pset_fapl_core() failed."); + + /* Set file image in core fapl */ + err = H5Pset_file_image(core_fapl_id, image_ptr, (size_t)image_size); + VERIFY(err == SUCCEED, "H5Pset_file_image() failed."); + + /* open the file image with the core file driver */ + core_file_id = H5Fopen("nonesuch", H5F_ACC_RDWR, core_fapl_id); + VERIFY(core_file_id >= 0, "H5Fopen() of file image failed."); + + /* close the file image with the core file driver */ + err = H5Fclose(core_file_id); + VERIFY(err == SUCCEED, "H5Fclose(core_file_id) failed."); + + /* dicard core fapl */ + err = H5Pclose(core_fapl_id); + VERIFY(err == SUCCEED, "H5Pclose(core_fapl_id) failed."); + + /* tidy up */ + result = h5_cleanup(FILENAME2, fapl); + VERIFY(result != 0, "h5_cleanup() failed."); + + /* discard the image buffer if it exists */ + if(image_ptr != NULL) + HDfree(image_ptr); + + /* discard the image buffer if it exists */ + if(file_image_ptr != NULL) + HDfree(file_image_ptr); + + PASSED(); + + return 0; + +error: + return 1; +} /* end test_get_file_image() */ + +/****************************************************************************** + * Function: test_get_file_image_error_rejection + * + * Purpose: Verify that H5Fget_file_image() rejects invalid input. + * + * Programmer: John Mainzer + * Tuesday, November 22, 2011 + * + ****************************************************************************** + */ + +#define TYPE_SLICE ((haddr_t)0x10000LL) + +static int +test_get_file_image_error_rejection(void) +{ + const char *memb_name[H5FD_MEM_NTYPES]; + char file_name[1024] = "\0"; + void * image_ptr = NULL; + int data[100]; + int i; + int result; + hid_t fapl_id = -1; + hid_t file_id = -1; + hid_t dset_id = -1; + hid_t space_id = -1; + herr_t err; + hsize_t dims[2]; + ssize_t bytes_read; + ssize_t image_size; + hid_t memb_fapl[H5FD_MEM_NTYPES]; + haddr_t memb_addr[H5FD_MEM_NTYPES]; + H5FD_mem_t mt; + H5FD_mem_t memb_map[H5FD_MEM_NTYPES]; + + + TESTING("H5Fget_file_image() error rejection"); + + /************************ Sub-Test #1 ********************************/ + /* set up a test file, and try to get its image with a buffer that is + * too small. Call to H5Fget_file_image() should fail. + * + * Since we have already done the necessary setup, verify that + * H5Fget_file_image() will fail with: + * + * bad file id, or + * + * good id, but not a file id + */ + + + /* setup fapl -- driver type doesn't matter much, so make it stdio */ + fapl_id = H5Pcreate(H5P_FILE_ACCESS); + VERIFY(fapl_id >= 0, "H5Pcreate(1) failed"); + + err = H5Pset_fapl_stdio(fapl_id); + VERIFY(err >= 0, "H5Pset_fapl_stdio() failed"); + + /* setup the file name */ + h5_fixname(FILENAME2[6], fapl_id, file_name, sizeof(file_name)); + VERIFY(HDstrlen(file_name)>0, "h5_fixname failed"); + + /* create the file */ + file_id = H5Fcreate(file_name, 0, H5P_DEFAULT, fapl_id); + VERIFY(file_id >= 0, "H5Fcreate() failed."); + + /* Set up data space for new new data set */ + dims[0] = 10; + dims[1] = 10; + space_id = H5Screate_simple(2, dims, dims); + VERIFY(space_id >= 0, "H5Screate() failed"); + + /* Create a dataset */ + dset_id = H5Dcreate2(file_id, "dset 0", H5T_NATIVE_INT, space_id, + H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + VERIFY(dset_id >=0, "H5Dcreate() failed"); + + /* write some data to the data set */ + for (i = 0; i < 100; i++) + data[i] = i; + err = H5Dwrite(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void *)data); + VERIFY(err >= 0, "H5Dwrite() failed."); + + /* Flush the file */ + err = H5Fflush(file_id, H5F_SCOPE_GLOBAL); + VERIFY(err >= 0, "H5Fflush failed"); + + /* get the size of the file */ + image_size = H5Fget_file_image(file_id, NULL, (size_t)0); + VERIFY(image_size > 0, "H5Fget_file_image(1 -- test 1) failed."); + + /* allocate a buffer of the appropriate size */ + image_ptr = HDmalloc((size_t)image_size); + VERIFY(image_ptr != NULL, "HDmalloc(1) failed."); + + /* load the image of the file into the buffer */ + H5E_BEGIN_TRY { + bytes_read = H5Fget_file_image(file_id, image_ptr, (size_t)(image_size - 1)); + } H5E_END_TRY; + VERIFY(bytes_read < 0, "H5Fget_file_image(2 -- test 1) succeeded."); + + /* Call H5Fget_file_image() with good buffer and buffer size, + * but non-existant file_id. Should fail. + */ + H5E_BEGIN_TRY { + bytes_read = H5Fget_file_image((hid_t)0, image_ptr, (size_t)(image_size)); + } H5E_END_TRY; + VERIFY(bytes_read < 0, "H5Fget_file_image(3 -- test 1) succeeded."); + + /* Call H5Fget_file_image() with good buffer and buffer size, + * but a file_id of the wrong type. Should fail. + */ + H5E_BEGIN_TRY { + bytes_read = H5Fget_file_image(dset_id, image_ptr, (size_t)(image_size)); + } H5E_END_TRY; + VERIFY(bytes_read < 0, "H5Fget_file_image(4 -- test 1) succeeded."); + + /* Close dset and space */ + err = H5Dclose(dset_id); + VERIFY(err >= 0, "H5Dclose failed"); + err = H5Sclose(space_id); + VERIFY(err >= 0, "H5Sclose failed"); + + /* close the test file */ + err = H5Fclose(file_id); + VERIFY(err == SUCCEED, "H5Fclose(file_id) failed."); + + /* tidy up */ + result = h5_cleanup(FILENAME2, fapl_id); + VERIFY(result != 0, "h5_cleanup(1) failed."); + + /* discard the image buffer if it exists */ + if(image_ptr != NULL) + HDfree(image_ptr); + + /************************** Test #2 **********************************/ + /* set up a multi file driver test file, and try to get its image + * with H5Fget_file_image(). Attempt should fail. + */ + + /* setup parameters for multi file driver */ + for(mt = (H5FD_mem_t)0; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) { + memb_addr[mt] = HADDR_UNDEF; + memb_fapl[mt] = H5P_DEFAULT; + memb_map[mt] = H5FD_MEM_DRAW; + memb_name[mt] = NULL; + } + + memb_map[H5FD_MEM_SUPER] = H5FD_MEM_SUPER; + memb_fapl[H5FD_MEM_SUPER] = H5P_DEFAULT; + memb_name[H5FD_MEM_SUPER] = "%s-s.h5"; + memb_addr[H5FD_MEM_SUPER] = 0; + + memb_map[H5FD_MEM_BTREE] = H5FD_MEM_BTREE; + memb_fapl[H5FD_MEM_BTREE] = H5P_DEFAULT; + memb_name[H5FD_MEM_BTREE] = "%s-b.h5"; + memb_addr[H5FD_MEM_BTREE] = memb_addr[H5FD_MEM_SUPER] + TYPE_SLICE; + + memb_map[H5FD_MEM_DRAW] = H5FD_MEM_DRAW; + memb_fapl[H5FD_MEM_DRAW] = H5P_DEFAULT; + memb_name[H5FD_MEM_DRAW] = "%s-r.h5"; + memb_addr[H5FD_MEM_DRAW] = memb_addr[H5FD_MEM_BTREE] + TYPE_SLICE; + + memb_map[H5FD_MEM_GHEAP] = H5FD_MEM_GHEAP; + memb_fapl[H5FD_MEM_GHEAP] = H5P_DEFAULT; + memb_name[H5FD_MEM_GHEAP] = "%s-g.h5"; + memb_addr[H5FD_MEM_GHEAP] = memb_addr[H5FD_MEM_DRAW] + TYPE_SLICE; + + memb_map[H5FD_MEM_LHEAP] = H5FD_MEM_LHEAP; + memb_fapl[H5FD_MEM_LHEAP] = H5P_DEFAULT; + memb_name[H5FD_MEM_LHEAP] = "%s-l.h5"; + memb_addr[H5FD_MEM_LHEAP] = memb_addr[H5FD_MEM_GHEAP] + TYPE_SLICE; + + memb_map[H5FD_MEM_OHDR] = H5FD_MEM_OHDR; + memb_fapl[H5FD_MEM_OHDR] = H5P_DEFAULT; + memb_name[H5FD_MEM_OHDR] = "%s-o.h5"; + memb_addr[H5FD_MEM_OHDR] = memb_addr[H5FD_MEM_LHEAP] + TYPE_SLICE; + + /* setup fapl */ + fapl_id = H5Pcreate(H5P_FILE_ACCESS); + VERIFY(fapl_id >= 0, "H5Pcreate(2) failed"); + + /* setup the fapl for the multi file driver */ + err = H5Pset_fapl_multi(fapl_id, memb_map, memb_fapl, memb_name, + memb_addr, FALSE); + VERIFY(err >= 0, "H5Pset_fapl_multi failed"); + + /* setup the file name */ + h5_fixname(FILENAME2[4], fapl_id, file_name, sizeof(file_name)); + VERIFY(HDstrlen(file_name)>0, "h5_fixname failed"); + + /* create the file */ + file_id = H5Fcreate(file_name, 0, H5P_DEFAULT, fapl_id); + VERIFY(file_id >= 0, "H5Fcreate() failed."); + + /* Set up data space for new new data set */ + dims[0] = 10; + dims[1] = 10; + space_id = H5Screate_simple(2, dims, dims); + VERIFY(space_id >= 0, "H5Screate() failed"); + + /* Create a dataset */ + dset_id = H5Dcreate2(file_id, "dset 0", H5T_NATIVE_INT, space_id, + H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + VERIFY(dset_id >=0, "H5Dcreate() failed"); + + /* write some data to the data set */ + for (i = 0; i < 100; i++) + data[i] = i; + err = H5Dwrite(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void *)data); + VERIFY(err >= 0, "H5Dwrite() failed."); + + /* Flush the file */ + err = H5Fflush(file_id, H5F_SCOPE_GLOBAL); + VERIFY(err >= 0, "H5Fflush failed"); + + /* attempt to get the size of the file -- should fail */ + H5E_BEGIN_TRY { + image_size = H5Fget_file_image(file_id, NULL, (size_t)0); + } H5E_END_TRY; + VERIFY(image_size == -1, "H5Fget_file_image(5) succeeded."); + + /* Close dset and space */ + err = H5Dclose(dset_id); + VERIFY(err >= 0, "H5Dclose failed"); + err = H5Sclose(space_id); + VERIFY(err >= 0, "H5Sclose failed"); + + /* close the test file */ + err = H5Fclose(file_id); + VERIFY(err == SUCCEED, "H5Fclose(2) failed."); + + /* tidy up */ + result = h5_cleanup(FILENAME2, fapl_id); + VERIFY(result != 0, "h5_cleanup(2 failed."); + + /************************** Test #3 **********************************/ + /* set up a split file driver test file, and try to get its image + * with H5Fget_file_image(). Attempt should fail. + */ + + /* create fapl */ + fapl_id = H5Pcreate(H5P_FILE_ACCESS); + VERIFY(fapl_id >= 0, "H5Pcreate(3) failed"); + + /* setup the fapl for the split file driver */ + err = H5Pset_fapl_split(fapl_id, "-m.h5", H5P_DEFAULT, "-r.h5", H5P_DEFAULT); + VERIFY(err >= 0, "H5Pset_fapl_split failed"); + + /* setup the file name */ + h5_fixname(FILENAME2[5], fapl_id, file_name, sizeof(file_name)); + VERIFY(HDstrlen(file_name)>0, "h5_fixname failed"); + + /* create the file */ + file_id = H5Fcreate(file_name, 0, H5P_DEFAULT, fapl_id); + VERIFY(file_id >= 0, "H5Fcreate() failed."); + + /* Set up data space for new new data set */ + dims[0] = 10; + dims[1] = 10; + space_id = H5Screate_simple(2, dims, dims); + VERIFY(space_id >= 0, "H5Screate() failed"); + + /* Create a dataset */ + dset_id = H5Dcreate2(file_id, "dset 0", H5T_NATIVE_INT, space_id, + H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + VERIFY(dset_id >=0, "H5Dcreate() failed"); + + /* write some data to the data set */ + for (i = 0; i < 100; i++) + data[i] = i; + err = H5Dwrite(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void *)data); + VERIFY(err >= 0, "H5Dwrite() failed."); + + /* Flush the file */ + err = H5Fflush(file_id, H5F_SCOPE_GLOBAL); + VERIFY(err >= 0, "H5Fflush failed"); + + /* attempt to get the size of the file -- should fail */ + H5E_BEGIN_TRY { + image_size = H5Fget_file_image(file_id, NULL, (size_t)0); + } H5E_END_TRY; + VERIFY(image_size == -1, "H5Fget_file_image(6) succeeded."); + + /* Close dset and space */ + err = H5Dclose(dset_id); + VERIFY(err >= 0, "H5Dclose failed"); + err = H5Sclose(space_id); + VERIFY(err >= 0, "H5Sclose failed"); + + /* close the test file */ + err = H5Fclose(file_id); + VERIFY(err == SUCCEED, "H5Fclose(2) failed."); + + + /************************** Test #4 **********************************/ + /* set up a family file driver test file, and try to get its image + * with H5Fget_file_image(). Attempt should fail. + */ + + /* create fapl */ + fapl_id = H5Pcreate(H5P_FILE_ACCESS); + VERIFY(fapl_id >= 0, "H5Pcreate(3) failed"); + + err = H5Pset_fapl_family(fapl_id, (hsize_t)FAMILY_SIZE, H5P_DEFAULT); + VERIFY(err >= 0, "H5Pset_fapl_family failed"); + + h5_fixname(FILENAME2[3], fapl_id, file_name, sizeof(file_name)); + VERIFY(HDstrlen(file_name)>0, "h5_fixname failed"); + + /* create the file */ + file_id = H5Fcreate(file_name, 0, H5P_DEFAULT, fapl_id); + VERIFY(file_id >= 0, "H5Fcreate() failed."); + + /* Set up data space for new new data set */ + dims[0] = 10; + dims[1] = 10; + space_id = H5Screate_simple(2, dims, dims); + VERIFY(space_id >= 0, "H5Screate() failed"); + + /* Create a dataset */ + dset_id = H5Dcreate2(file_id, "dset 0", H5T_NATIVE_INT, space_id, + H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + VERIFY(dset_id >=0, "H5Dcreate() failed"); + + /* write some data to the data set */ + for (i = 0; i < 100; i++) + data[i] = i; + err = H5Dwrite(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void *)data); + VERIFY(err >= 0, "H5Dwrite() failed."); + + /* Flush the file */ + err = H5Fflush(file_id, H5F_SCOPE_GLOBAL); + VERIFY(err >= 0, "H5Fflush failed"); + + /* attempt to get the size of the file -- should fail */ + H5E_BEGIN_TRY { + image_size = H5Fget_file_image(file_id, NULL, (size_t)0); + } H5E_END_TRY; + VERIFY(image_size == -1, "H5Fget_file_image(7) succeeded."); + + /* Close dset and space */ + err = H5Dclose(dset_id); + VERIFY(err >= 0, "H5Dclose failed"); + err = H5Sclose(space_id); + VERIFY(err >= 0, "H5Sclose failed"); + + /* close the test file */ + err = H5Fclose(file_id); + VERIFY(err == SUCCEED, "H5Fclose(2) failed."); + + /* tidy up */ + result = h5_cleanup(FILENAME2, fapl_id); + VERIFY(result != 0, "h5_cleanup(2 failed."); + + PASSED(); + + return 0; + +error: + return 1; +} + +int +main(void) +{ + int errors = 0; + hid_t fapl; + + h5_reset(); + + printf("Testing File Image Functionality.\n"); + + errors += test_properties(); + errors += test_callbacks(); + errors += test_core(); + + /* test H5Fget_file_image() with sec2 driver */ + fapl = H5Pcreate(H5P_FILE_ACCESS); + if(0 > H5Pset_fapl_sec2(fapl)) + 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(0 > H5Pset_fapl_stdio(fapl)) + 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(0 > H5Pset_fapl_core(fapl, (size_t)(64 *1024), TRUE)) + errors++; + else + errors += test_get_file_image("H5Fget_file_image() with core driver", + 2, fapl); + +#if 0 + /* at present, H5Fget_file_image() rejects files opened with the + * family file driver, due to the addition of a driver info message + * in the super block. This message prevents the image being opened + * with any driver other than the family file driver, which sort of + * defeats the purpose of the get file image operation. + * + * While this issues is quite fixable, we don't have time or resources + * for this right now. Once we do, the following code should be + * suitable for testing the fix. + */ + /* test H5Fget_file_image() with family file driver */ + fapl = H5Pcreate(H5P_FILE_ACCESS); + if(H5Pset_fapl_family(fapl, (hsize_t)FAMILY_SIZE, H5P_DEFAULT) < 0) + errors++; + else + errors += test_get_file_image("H5Fget_file_image() with family driver", + 3, fapl); +#endif + + errors += test_get_file_image_error_rejection(); + + + if(errors) { + printf("***** %d File Image TEST%s FAILED! *****\n", + errors, errors > 1 ? "S" : ""); + return 1; + } + + printf("All File Image tests passed.\n"); + return 0; +} + diff --git a/test/file_image_core_test.h5 b/test/file_image_core_test.h5 new file mode 100644 index 0000000..1cc5130 Binary files /dev/null and b/test/file_image_core_test.h5 differ diff --git a/test/gen_cross.c b/test/gen_cross.c old mode 100755 new mode 100644 diff --git a/test/gen_file_image.c b/test/gen_file_image.c new file mode 100644 index 0000000..bc9de29 --- /dev/null +++ b/test/gen_file_image.c @@ -0,0 +1,91 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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: Quincey Koziol + * Friday, March 30, 2012 + * + * Purpose: Create a simple file for use with the file image tests. + * + */ +#include "hdf5.h" + +#define TESTFILE "file_image_core_test.h5" + +/* 2-D dataset with fixed dimensions */ +#define SPACE_RANK 2 +#define SPACE_DIM1 128 +#define SPACE_DIM2 32 + +/* Dataset data */ +int data[SPACE_DIM1][SPACE_DIM2]; + + +/*------------------------------------------------------------------------- + * Function: main + * + * Purpose: + * + * Return: Success: + * + * Failure: + * + * Programmer: Quincey Koziol + * Friday, March 30, 2012 + * + *------------------------------------------------------------------------- + */ +int +main(void) +{ + hid_t file, space, dset; + hsize_t dims[SPACE_RANK] = {SPACE_DIM1, SPACE_DIM2}; + size_t i, j; /* Local index variables */ + + /* Initialize the data */ + for(i = 0; i < SPACE_DIM1; i++) + for(j = 0; j < SPACE_DIM2; j++) + data[i][j] = (int)(j % 5); + + /* Create the file */ + file = H5Fcreate(TESTFILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + if(file < 0) + printf("file < 0!\n"); + + /* Create the dataspace */ + space = H5Screate_simple(SPACE_RANK, dims, NULL); + if(space < 0) + printf("space < 0!\n"); + + /* Create the compressed dataset */ + dset = H5Dcreate2(file, "Dataset1", H5T_NATIVE_INT, space, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + if(dset < 0) + printf("dset < 0!\n"); + + /* Write the data to the dataset */ + if(H5Dwrite(dset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data) < 0) + printf("H5Dwrite() failed!\n"); + + /* Close everything */ + if(H5Dclose(dset) < 0) + printf("H5Dclose() failed!\n"); + if(H5Sclose(space) < 0) + printf("H5Sclose() failed!\n"); + if(H5Fclose(file) < 0) + printf("H5Fclose() failed!\n"); + + return 0; +} + diff --git a/test/istore.c b/test/istore.c index 3ae8da7..f99e835 100644 --- a/test/istore.c +++ b/test/istore.c @@ -54,6 +54,42 @@ hsize_t zero[H5O_LAYOUT_NDIMS]; /*------------------------------------------------------------------------- + * Function: is_sparse + * + * Purpose: Determines if the file system of the current working + * directory supports holes. + * + * Return: Success: Non-zero if holes are supported; zero + * otherwise. + * + * Failure: zero + * + * Programmer: Robb Matzke + * Wednesday, July 15, 1998 + * + *------------------------------------------------------------------------- + */ +static int +is_sparse(void) +{ + int fd; + h5_stat_t sb; + + if ((fd=HDopen("x.h5", O_RDWR|O_TRUNC|O_CREAT, 0666)) < 0) return 0; + if (HDlseek(fd, (off_t)(1024*1024), SEEK_SET)!=1024*1024) return 0; + if (5!=HDwrite(fd, "hello", (size_t)5)) return 0; + if (HDclose(fd) < 0) return 0; + if (HDstat("x.h5", &sb) < 0) return 0; + if (HDremove("x.h5") < 0) return 0; +#ifdef H5_HAVE_STAT_ST_BLOCKS + return ((unsigned long)sb.st_blocks*512 < (unsigned long)sb.st_size); +#else + return (0); +#endif +} + + +/*------------------------------------------------------------------------- * Function: print_array * * Purpose: Prints the values in an array @@ -431,7 +467,7 @@ error: */ static herr_t test_sparse(hid_t f, const char *prefix, size_t nblocks, - size_t nx, size_t ny, size_t nz) + size_t nx, size_t ny, size_t nz, int skip_test) { hid_t dataset; /* Dataset ID */ hid_t fspace; /* Dataset's file dataspace */ @@ -463,6 +499,10 @@ test_sparse(hid_t f, const char *prefix, size_t nblocks, sprintf(s, "istore sparse: %s", dims); TESTING(s); + if(skip_test){ + SKIPPED() + return SUCCEED; + } buf = (uint8_t *)HDmalloc(nx * ny * nz); HDmemset(buf, 128, nx * ny * nz); @@ -565,6 +605,8 @@ main(int argc, char *argv[]) unsigned size_of_test; unsigned u; /* Local index variable */ char filename[1024]; + int skip_test = 0; + int has_sparse_support = 0; /* Parse arguments or assume these tests (`small', `medium' ) */ if (1 == argc) { @@ -598,6 +640,12 @@ main(int argc, char *argv[]) /* Set the random # seed */ HDsrandom((unsigned)HDtime(NULL)); + /* Check to see if the file system supports POSIX-style sparse files. + * Windows NTFS does not, so we want to avoid tests which create + * very large files. + */ + has_sparse_support = is_sparse(); + /* Reset library */ h5_reset(); fapl = h5_fileaccess(); @@ -640,24 +688,31 @@ main(int argc, char *argv[]) status = test_extend(file, "extend", (size_t)10, (size_t)400, (size_t)10); nerrors += status < 0 ? 1 : 0; } + skip_test = 0; if (size_of_test & TEST_SMALL) { - status = test_sparse(file, "sparse", (size_t)100, (size_t)5, (size_t)0, (size_t)0); + status = test_sparse(file, "sparse", (size_t)100, (size_t)5, (size_t)0, (size_t)0, skip_test); nerrors += status < 0 ? 1 : 0; - status = test_sparse(file, "sparse", (size_t)100, (size_t)3, (size_t)4, (size_t)0); + status = test_sparse(file, "sparse", (size_t)100, (size_t)3, (size_t)4, (size_t)0, skip_test); nerrors += status < 0 ? 1 : 0; - status = test_sparse(file, "sparse", (size_t)100, (size_t)2, (size_t)3, (size_t)4); + status = test_sparse(file, "sparse", (size_t)100, (size_t)2, (size_t)3, (size_t)4, skip_test); nerrors += status < 0 ? 1 : 0; } if (size_of_test & TEST_MEDIUM) { - status = test_sparse(file, "sparse", (size_t)1000, (size_t)30, (size_t)0, (size_t)0); + status = test_sparse(file, "sparse", (size_t)1000, (size_t)30, (size_t)0, (size_t)0, skip_test); nerrors += status < 0 ? 1 : 0; - status = test_sparse(file, "sparse", (size_t)2000, (size_t)7, (size_t)3, (size_t)0); + status = test_sparse(file, "sparse", (size_t)2000, (size_t)7, (size_t)3, (size_t)0, skip_test); nerrors += status < 0 ? 1 : 0; - status = test_sparse(file, "sparse", (size_t)2000, (size_t)4, (size_t)2, (size_t)3); + status = test_sparse(file, "sparse", (size_t)2000, (size_t)4, (size_t)2, (size_t)3, skip_test); nerrors += status < 0 ? 1 : 0; } + skip_test = !has_sparse_support; if (size_of_test & TEST_LARGE) { - status = test_sparse(file, "sparse", (size_t)800, (size_t)50, (size_t)50, (size_t)50); + /* This test is skipped if there is no POSIX-style sparse file support + * e.g.: Windows NTFS filesystems + */ + status = test_sparse(file, "sparse", (size_t)800, (size_t)50, (size_t)50, (size_t)50, skip_test); + if(skip_test) + printf(" The current VFD does not support sparse files on this platform.\n"); nerrors += status < 0 ? 1 : 0; } diff --git a/test/objcopy.c b/test/objcopy.c old mode 100755 new mode 100644 index 8fb8bbe..f5555e8 --- a/test/objcopy.c +++ b/test/objcopy.c @@ -53,6 +53,7 @@ const char *FILENAME[] = { "objcopy_src", "objcopy_dst", "objcopy_ext", + "objcopy_src2", NULL }; @@ -79,6 +80,7 @@ const char *FILENAME[] = { #define NAME_DATATYPE_VL_VL "vlen of vlen of int" #define NAME_DATASET_SIMPLE "dataset_simple" #define NAME_DATASET_SIMPLE2 "dataset_simple_copy" +#define NAME_DATASET_SIMPLE3 "dataset_simple_another_copy" #define NAME_DATASET_COMPOUND "dataset_compound" #define NAME_DATASET_CHUNKED "dataset_chunked" #define NAME_DATASET_CHUNKED2 "dataset_chunked2" @@ -99,6 +101,9 @@ const char *FILENAME[] = { #define NAME_GROUP_UNCOPIED "/uncopied" #define NAME_GROUP_EMPTY "/empty" #define NAME_GROUP_TOP "/g0" +#define NAME_GROUP_TOP2 "/g1" +#define NAME_GROUP_TOP3 "/g2" +#define NAME_GROUP_TOP4 "/g3" #define NAME_GROUP_SUB "/g0/g00" #define NAME_GROUP_SUB_2 "/g0/g01" #define NAME_GROUP_SUB_SUB "/g0/g00/g000" @@ -134,6 +139,9 @@ const char *FILENAME[] = { #define NUM_WIDE_LOOP_GROUPS 10 #define NUM_DATASETS 10 +#define COPY_OPEN_OBJ_NAME "CopyOpenObj" +#define COPY_OPEN_OBJ_SIZE sizeof(hbool_t) + char src_obj_full_name[215]; /* the full path + name of the object to be copied */ unsigned num_attributes_g; /* Number of attributes created */ @@ -554,12 +562,17 @@ test_copy_attach_attributes(hid_t loc_id, hid_t type_id) char attr_name[ATTR_NAME_LEN]; int attr_data[2]; hsize_t dim1 = 2; + hid_t acpl = -1; unsigned u; int ret_value = -1; if((sid = H5Screate_simple(1, &dim1, NULL)) < 0 ) goto done; + /* Create attribute creation plist */ + if((acpl = H5Pcreate(H5P_ATTRIBUTE_CREATE)) < 0) + goto done; + for(u = 0; u < num_attributes_g; u++) { sprintf(attr_name, "%u attr", u); @@ -567,7 +580,16 @@ test_copy_attach_attributes(hid_t loc_id, hid_t type_id) attr_data[0] = (int)(100 * u); attr_data[1] = (int)(200 * u); - if((aid = H5Acreate2(loc_id, attr_name, type_id, sid, H5P_DEFAULT, H5P_DEFAULT)) < 0) + /* Set attribute character set (alternate) */ + if(u % 2) { + if(H5Pset_char_encoding(acpl, H5T_CSET_ASCII) < 0) + goto done; + } /* end if */ + else + if(H5Pset_char_encoding(acpl, H5T_CSET_UTF8) < 0) + goto done; + + if((aid = H5Acreate2(loc_id, attr_name, type_id, sid, acpl, H5P_DEFAULT)) < 0) goto done; if(H5Awrite(aid, H5T_NATIVE_INT, attr_data) < 0) @@ -586,6 +608,8 @@ done: H5Sclose(sid); if(aid > 0) H5Aclose(aid); + if(acpl > 0) + H5Pclose(acpl); return ret_value; } @@ -609,11 +633,15 @@ test_copy_attach_paired_attributes(hid_t loc_id, hid_t loc_id2, hid_t type_id) hid_t aid = -1, sid = -1; char attr_name[ATTR_NAME_LEN]; int attr_data[2]; + hid_t acpl = -1; unsigned u; hsize_t dim1 = 2; if((sid = H5Screate_simple(1, &dim1, NULL)) < 0 ) goto done; + /* Create attribute creation plist */ + if((acpl = H5Pcreate(H5P_ATTRIBUTE_CREATE)) < 0) goto done; + for(u = 0; u < num_attributes_g; u++) { sprintf(attr_name, "%u attr", u); @@ -621,6 +649,13 @@ test_copy_attach_paired_attributes(hid_t loc_id, hid_t loc_id2, hid_t type_id) attr_data[0] = (int)(100 * u); attr_data[1] = (int)(200 * u); + /* Set attribute character set (alternate) */ + if(u % 2) { + if(H5Pset_char_encoding(acpl, H5T_CSET_ASCII) < 0) goto done; + } /* end if */ + else + if(H5Pset_char_encoding(acpl, H5T_CSET_UTF8) < 0) goto done; + /* Add attribute to first object */ if((aid = H5Acreate2(loc_id, attr_name, type_id, sid, H5P_DEFAULT, H5P_DEFAULT)) < 0) goto done; if(H5Awrite(aid, H5T_NATIVE_INT, attr_data) < 0) goto done; @@ -633,6 +668,7 @@ test_copy_attach_paired_attributes(hid_t loc_id, hid_t loc_id2, hid_t type_id) } if(H5Sclose(sid) < 0) goto done; + if(H5Pclose(acpl) < 0) goto done; return 0; @@ -641,6 +677,8 @@ done: H5Sclose(sid); if(aid > 0) H5Aclose(aid); + if(acpl > 0) + H5Pclose(acpl); return -1; } /* end test_copy_attach_paired_attributes() */ @@ -666,10 +704,22 @@ compare_attribute(hid_t aid, hid_t aid2, hid_t pid, const void *wbuf, hid_t obj_ size_t elmt_size; /* Size of datatype */ htri_t is_committed; /* If the datatype is committed */ htri_t is_committed2; /* If the datatype is committed */ + H5A_info_t ainfo; /* Attribute info */ + H5A_info_t ainfo2; /* Attribute info */ hssize_t nelmts; /* # of elements in dataspace */ void *rbuf = NULL; /* Buffer for reading raw data */ void *rbuf2 = NULL; /* Buffer for reading raw data */ + /* Check the character sets are equal */ + if(H5Aget_info(aid, &ainfo) < 0) TEST_ERROR + if(H5Aget_info(aid2, &ainfo2) < 0) TEST_ERROR + if(ainfo.cset != ainfo2.cset) TEST_ERROR + + /* Check the creation orders are equal (if appropriate) */ + if(ainfo.corder_valid != ainfo2.corder_valid) TEST_ERROR + if(ainfo.corder_valid) + if(ainfo.corder != ainfo2.corder) TEST_ERROR + /* Check the datatypes are equal */ /* Open the datatype for the source attribute */ @@ -1138,6 +1188,18 @@ compare_datasets(hid_t did, hid_t did2, hid_t pid, const void *wbuf) void *rbuf2 = NULL; /* Buffer for reading raw data */ H5D_space_status_t space_status; /* Dataset's raw data space status */ H5D_space_status_t space_status2; /* Dataset's raw data space status */ + hbool_t copy_open_obj = FALSE; /* Indicate if we are copying open objects */ + + /* Retrieve the private "copy open object" property from the property list, if it's non-DEFAULT */ + if(pid != H5P_DEFAULT) { + htri_t copy_open_obj_exists; + + if((copy_open_obj_exists = H5Pexist(pid, COPY_OPEN_OBJ_NAME)) < 0) TEST_ERROR + if(copy_open_obj_exists) { + if(H5Pget(pid, COPY_OPEN_OBJ_NAME, ©_open_obj) < 0) + TEST_ERROR + } /* end if */ + } /* end if */ /* Check the datatypes are equal */ @@ -1210,20 +1272,22 @@ compare_datasets(hid_t did, hid_t did2, hid_t pid, const void *wbuf) if(offset1 != offset2) TEST_ERROR if(size1 != size2) TEST_ERROR - if(strcmp(name1, name2) != 0) TEST_ERROR + if(HDstrcmp(name1, name2) != 0) TEST_ERROR } - /* Remove external file information from the dcpls */ - /* Remove default property causes memory leak - if(H5Premove(dcpl, H5D_CRT_EXT_FILE_LIST_NAME) < 0) TEST_ERROR - if(H5Premove(dcpl2, H5D_CRT_EXT_FILE_LIST_NAME) < 0) TEST_ERROR - */ - - /* reset external file information from the dcpls */ + /* Reset external file information from the dcpls */ + /* (Directly removing default property causes memory leak) */ if (H5P_reset_external_file_test(dcpl) < 0) TEST_ERROR if (H5P_reset_external_file_test(dcpl2) < 0) TEST_ERROR } + /* Check for copying open objects */ + if(copy_open_obj) { + /* Reset layout information from the dcpls */ + if(H5P_reset_layout_test(dcpl) < 0) TEST_ERROR + if(H5P_reset_layout_test(dcpl2) < 0) TEST_ERROR + } /* end if */ + /* Compare the rest of the dataset creation property lists */ if(H5Pequal(dcpl, dcpl2) != TRUE) TEST_ERROR @@ -1285,7 +1349,9 @@ compare_datasets(hid_t did, hid_t did2, hid_t pid, const void *wbuf) /* Release raw data buffers */ HDfree(rbuf); + rbuf = NULL; HDfree(rbuf2); + rbuf2 = NULL; /* close the source dataspace */ if(H5Sclose(sid) < 0) TEST_ERROR @@ -8628,231 +8694,3519 @@ error: /*------------------------------------------------------------------------- - * Function: test_copy_option + * Function: test_copy_attr_crt_order * - * Purpose: Create a group in SRC file and copy it to DST file + * Purpose: Tests copying attributes with creation order tracked, with + * and without creation order being indexed. * * Return: Success: 0 * Failure: number of errors * - * Programmer: Peter Cao - * March 11, 2006 - * - * Modifications: + * Programmer: Neil Fortner + * Friday, January 20, 2012 * *------------------------------------------------------------------------- */ static int -test_copy_option(hid_t fcpl_src, hid_t fcpl_dst, hid_t src_fapl, hid_t dst_fapl, - unsigned flag, hbool_t crt_intermediate_grp, const char* test_desciption) +test_copy_attr_crt_order(hid_t fcpl_src, hid_t fcpl_dst, hid_t src_fapl, hid_t dst_fapl) { - hid_t fid_src = -1, fid_dst = -1, fid_ext = -1; /* File IDs */ - hid_t sid = -1; /* Dataspace ID */ - hid_t did = -1; /* Dataset ID */ - hid_t gid=-1, gid2=-1, gid_ref=-1; /* Group IDs */ - hid_t gid_sub=-1, gid_sub_sub=-1; /* Sub-group ID */ - hid_t pid=-1, lcpl_id=-1; /* Property IDs */ - unsigned cpy_flags; /* Object copy flags */ - int depth = -1; /* Copy depth */ - hsize_t dim2d[2]; - int buf[DIM_SIZE_1][DIM_SIZE_2]; - int i, j; + hid_t fid1 = -1, fid2 = -1; /* File IDs */ + hid_t gcplid = -1; /* Group creation property list ID */ + hid_t gid1 = -1, gid2 = -1; /* Group IDs */ char src_filename[NAME_BUF_SIZE]; char dst_filename[NAME_BUF_SIZE]; - TESTING(test_desciption); - - /* set initial data values */ - for (i=0; i 0) { - /* Create group to copy */ - if((gid = H5Gcreate2(fid_src, NAME_GROUP_LINK, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR - if(H5Lcreate_soft(NAME_DATASET_SUB_SUB, fid_src, NAME_LINK_SOFT, H5P_DEFAULT, H5P_DEFAULT) < 0) FAIL_STACK_ERROR - if(H5Lcreate_soft("nowhere", fid_src, NAME_LINK_SOFT_DANGLE, H5P_DEFAULT, H5P_DEFAULT) < 0) FAIL_STACK_ERROR - if(H5Gclose(gid) < 0) FAIL_STACK_ERROR + /* Open groups with creation order tracked and indexed */ + if((gid1 = H5Gopen2(fid1, NAME_GROUP_TOP2, H5P_DEFAULT)) < 0) TEST_ERROR + if((gid2 = H5Gopen2(fid2, NAME_GROUP_TOP2, H5P_DEFAULT)) < 0) TEST_ERROR - /* Create group to compare with */ - if((gid = H5Gcreate2(fid_src, NAME_GROUP_LINK2, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR - if(H5Lcreate_hard(fid_src, NAME_DATASET_SUB_SUB, H5L_SAME_LOC, NAME_LINK_SOFT2, H5P_DEFAULT, H5P_DEFAULT) < 0) FAIL_STACK_ERROR - if(H5Lcreate_soft("nowhere", fid_src, NAME_LINK_SOFT_DANGLE2, H5P_DEFAULT, H5P_DEFAULT) < 0) FAIL_STACK_ERROR - if(H5Gclose(gid) < 0) FAIL_STACK_ERROR - } /* end if */ + /* Compare the attributes */ + if(compare_std_attributes(gid1, gid2, H5P_DEFAULT) != TRUE) TEST_ERROR - if((flag & H5O_COPY_EXPAND_EXT_LINK_FLAG) > 0) { - char ext_filename[NAME_BUF_SIZE]; + /* Close groups */ + if(H5Gclose(gid1) < 0) TEST_ERROR + if(H5Gclose(gid2) < 0) TEST_ERROR - h5_fixname(FILENAME[2], src_fapl, ext_filename, sizeof ext_filename); + /* Close */ + if(H5Fclose(fid1) < 0) TEST_ERROR + if(H5Fclose(fid2) < 0) TEST_ERROR - /* Create the external file and dataset */ - if((fid_ext = H5Fcreate(ext_filename, H5F_ACC_TRUNC, fcpl_src, src_fapl)) < 0) TEST_ERROR - if((sid = H5Screate_simple(2, dim2d, NULL)) < 0) TEST_ERROR - if((did = H5Dcreate2(fid_ext, NAME_DATASET_SIMPLE, H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR - if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR - if(H5Dclose(did) < 0) TEST_ERROR - if(H5Fclose(fid_ext) < 0) TEST_ERROR + PASSED(); + return 0; - /* Create group to copy */ - if(!(flag & H5O_COPY_EXPAND_SOFT_LINK_FLAG)) { - if((gid = H5Gcreate2(fid_src, NAME_GROUP_LINK, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR - } /* end if */ - else - if((gid = H5Gopen2(fid_src, NAME_GROUP_LINK, H5P_DEFAULT)) < 0) TEST_ERROR - if(H5Lcreate_external(ext_filename, NAME_DATASET_SIMPLE, fid_src, NAME_LINK_EXTERN, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR - if(H5Lcreate_external("no_file", "no_object", fid_src, NAME_LINK_EXTERN_DANGLE, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR - if(H5Gclose(gid) < 0) TEST_ERROR +error: + H5E_BEGIN_TRY { + H5Gclose(gid1); + H5Gclose(gid2); + H5Pclose(gcplid); + H5Fclose(fid1); + H5Fclose(fid2); + } H5E_END_TRY; + return 1; +} /* end test_copy_attr_crt_order */ - /* Create group to compare with */ - if(!(flag & H5O_COPY_EXPAND_SOFT_LINK_FLAG)) { - if((gid = H5Gcreate2(fid_src, NAME_GROUP_LINK2, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR - } /* end if */ - else - if((gid = H5Gopen2(fid_src, NAME_GROUP_LINK2, H5P_DEFAULT)) < 0) TEST_ERROR - if((did = H5Dcreate2(fid_src, NAME_LINK_EXTERN2, H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR - if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR - if(H5Lcreate_external("no_file", "no_object", fid_src, NAME_LINK_EXTERN_DANGLE2, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR - if(H5Dclose(did) < 0) TEST_ERROR - if(H5Gclose(gid) < 0) TEST_ERROR + +/*------------------------------------------------------------------------- + * Function: test_copy_committed_datatype_merge + * + * Purpose: Tests the "merge committed datatypes" feature of H5Ocopy. + * + * Return: Success: 0 + * Failure: number of errors + * + * Programmer: Neil Fortner + * Tuesday, October 11, 2011 + * + *------------------------------------------------------------------------- + */ +static int +test_copy_committed_datatype_merge(hid_t fcpl_src, hid_t fcpl_dst, hid_t src_fapl, + hid_t dst_fapl, hbool_t reopen) +{ + hid_t fid_src1 = -1, fid_src2 = -1, fid_dst = -1; /* File IDs */ + hid_t tid = -1; /* Datatype ID */ + hid_t sid = -1; /* Dataspace ID */ + hid_t did = -1; /* Dataset ID */ + hid_t ocpypl_id = -1; /* Object copy plist ID */ + unsigned int i; /* Local index variables */ + hsize_t dim1d[1]; /* Dataset dimensions */ + int buf[DIM_SIZE_1]; /* Buffer for writing data */ + H5O_info_t oinfo; /* Object info */ + haddr_t exp_addr; /* Expected object address */ + char src1_filename[NAME_BUF_SIZE]; + char src2_filename[NAME_BUF_SIZE]; + char dst_filename[NAME_BUF_SIZE]; - /* Close dataspace */ - if(H5Sclose(sid) < 0) TEST_ERROR + if(reopen) { + TESTING("H5Ocopy(): merging committed datatypes with reopen") } /* end if */ + else + TESTING("H5Ocopy(): merging committed datatypes") - if((flag & H5O_COPY_EXPAND_REFERENCE_FLAG) > 0) { - if((gid_ref = H5Gcreate2(fid_src, NAME_GROUP_REF, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + /* set initial data values */ + for(i = 0; i < DIM_SIZE_1; i++) + buf[i] = (int)i; - /* create an attribute of object references */ - if(attach_ref_attr(fid_src, gid_ref) < 0) TEST_ERROR + /* Initialize the filenames */ + h5_fixname(FILENAME[0], src_fapl, src1_filename, sizeof src1_filename); + h5_fixname(FILENAME[3], src_fapl, src2_filename, sizeof src2_filename); + h5_fixname(FILENAME[1], dst_fapl, dst_filename, sizeof dst_filename); - /* create an attribute of region references */ - if(attach_reg_ref_attr(fid_src, gid_ref) < 0) TEST_ERROR + /* Reset file address checking info */ + addr_reset(); - /* create a dataset of region references */ - if(create_reg_ref_dataset(fid_src, gid_ref) < 0) TEST_ERROR + /* create source files */ + if((fid_src1 = H5Fcreate(src1_filename, H5F_ACC_TRUNC, fcpl_src, src_fapl)) < 0) TEST_ERROR + if((fid_src2 = H5Fcreate(src2_filename, H5F_ACC_TRUNC, fcpl_src, src_fapl)) < 0) TEST_ERROR - /* Close group holding reference objects */ - if(H5Gclose(gid_ref) < 0) TEST_ERROR - } /* end if */ + /* Set dataspace dimensions */ + dim1d[0]=DIM_SIZE_1; - /* close the SRC file */ - if(H5Fclose(fid_src) < 0) TEST_ERROR + /* create dataspace */ + if((sid = H5Screate_simple(1, dim1d, NULL)) < 0) TEST_ERROR - /* open the source file with read-only */ - /* (except when expanding soft links */ - if((flag & H5O_COPY_EXPAND_SOFT_LINK_FLAG) > 0) { - if((fid_src = H5Fopen(src_filename, H5F_ACC_RDWR, src_fapl)) < 0) TEST_ERROR - } /* end if */ - else - if((fid_src = H5Fopen(src_filename, H5F_ACC_RDONLY, src_fapl)) < 0) TEST_ERROR + /* + * Populate source file 1 + */ + /* create datatype */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)TEST_ERROR - /* create destination file */ - if((fid_dst = H5Fcreate(dst_filename, H5F_ACC_TRUNC, fcpl_dst, dst_fapl)) < 0) TEST_ERROR + /* committed data type */ + if((H5Tcommit2(fid_src1, NAME_DATATYPE_SIMPLE, tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR - /* Create an uncopied object in destination file so that addresses in source and destination - files aren't the same */ - if(H5Gclose(H5Gcreate2(fid_dst, NAME_GROUP_UNCOPIED, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + /* create dataset at SRC file */ + if((did = H5Dcreate2(fid_src1, NAME_DATASET_SIMPLE, tid, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR - /* create property to pass copy options */ - if((pid = H5Pcreate(H5P_OBJECT_COPY)) < 0) TEST_ERROR + /* write data into file */ + if(H5Dwrite(did, tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR - /* set options for object copy */ - if(H5Pset_copy_object(pid, flag) < 0) TEST_ERROR + /* close the datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR - /* Verify object copy flags */ - if(H5Pget_copy_object(pid, &cpy_flags) < 0) TEST_ERROR - if(cpy_flags != flag) TEST_ERROR + /* close the dataset */ + if(H5Dclose(did) < 0) TEST_ERROR - /* copy the group from SRC to DST */ - if(crt_intermediate_grp) { - /* Create link creation plist to pass in intermediate group creation */ - if((lcpl_id = H5Pcreate(H5P_LINK_CREATE)) < 0) TEST_ERROR - if(H5Pset_create_intermediate_group(lcpl_id, TRUE) < 0) TEST_ERROR + /* close the SRC file 1 */ + if(H5Fclose(fid_src1) < 0) TEST_ERROR - if(H5Ocopy(fid_src, NAME_GROUP_TOP, fid_dst, "/new_g0/new_g00", pid, lcpl_id) < 0) TEST_ERROR + /* + * Populate source file 2 + */ + /* create datatype */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)TEST_ERROR - if(H5Pclose(lcpl_id) < 0) TEST_ERROR + /* committed data type */ + if((H5Tcommit2(fid_src2, NAME_DATATYPE_SIMPLE, tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR - /* open the group for copy */ - if((gid = H5Gopen2(fid_src, NAME_GROUP_TOP, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR + /* create dataset at SRC file */ + if((did = H5Dcreate2(fid_src2, NAME_DATASET_SIMPLE, tid, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR - /* open the destination group */ - if((gid2 = H5Gopen2(fid_dst, "/new_g0/new_g00", H5P_DEFAULT)) < 0) FAIL_STACK_ERROR + /* write data into file */ + if(H5Dwrite(did, tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR - } else if(((flag & H5O_COPY_EXPAND_SOFT_LINK_FLAG) > 0) - || ((flag & H5O_COPY_EXPAND_EXT_LINK_FLAG) > 0)) { - if(H5Ocopy(fid_src, NAME_GROUP_LINK, fid_dst, NAME_GROUP_LINK, pid, H5P_DEFAULT) < 0) TEST_ERROR + /* close the datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR - if((flag & H5O_COPY_EXPAND_SOFT_LINK_FLAG) > 0) - /* Unlink dataset to copy from original location */ - /* (So group comparison works properly) */ - if(H5Ldelete(fid_src, NAME_DATASET_SUB_SUB, H5P_DEFAULT) < 0) FAIL_STACK_ERROR + /* close the dataset */ + if(H5Dclose(did) < 0) TEST_ERROR - /* open the group for copy */ - if((gid = H5Gopen2(fid_src, NAME_GROUP_LINK2, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR + /* close the SRC file 1 */ + if(H5Fclose(fid_src2) < 0) TEST_ERROR - /* open the destination group */ - if((gid2 = H5Gopen2(fid_dst, NAME_GROUP_LINK, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR - } else if(flag & (H5O_COPY_WITHOUT_ATTR_FLAG | H5O_COPY_PRESERVE_NULL_FLAG)) { - if(H5Ocopy(fid_src, NAME_GROUP_TOP, fid_dst, NAME_GROUP_TOP, pid, H5P_DEFAULT) < 0) TEST_ERROR + /* open the source files with read-only */ + if((fid_src1 = H5Fopen(src1_filename, H5F_ACC_RDONLY, src_fapl)) < 0) TEST_ERROR + if((fid_src2 = H5Fopen(src2_filename, H5F_ACC_RDONLY, src_fapl)) < 0) TEST_ERROR + + /* Create ocpl and set merge named dtype flag */ + if((ocpypl_id = H5Pcreate(H5P_OBJECT_COPY)) < 0) TEST_ERROR + if(H5Pset_copy_object(ocpypl_id, H5O_COPY_MERGE_COMMITTED_DTYPE_FLAG) < 0) TEST_ERROR + + /* + * First copy each entire file to the destination file (each with their own + * group), and verify the committed datatypes are merged + */ + /* create destination file */ + if((fid_dst = H5Fcreate(dst_filename, H5F_ACC_TRUNC, fcpl_dst, dst_fapl)) < 0) TEST_ERROR + + /* Create an uncopied object in destination file so that addresses in source and destination files aren't the same */ + if(H5Gclose(H5Gcreate2(fid_dst, NAME_GROUP_UNCOPIED, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* copy SRC1 to DST */ + if(H5Ocopy(fid_src1, "/", fid_dst, NAME_GROUP_TOP, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + /* copy SRC2 to DST */ + if(H5Ocopy(fid_src2, "/", fid_dst, NAME_GROUP_TOP2, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + if(reopen) { + /* Reopen file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDONLY, dst_fapl)) < 0) TEST_ERROR + } /* end if */ + + /* Open SRC1 committed dtype, get address */ + if((tid = H5Topen2(fid_dst, NAME_GROUP_TOP "/" NAME_DATATYPE_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + + /* Open SRC1 dset dtype, check address */ + if((did = H5Dopen2(fid_dst, NAME_GROUP_TOP "/" NAME_DATASET_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Open SRC2 committed dtype, check address */ + if((tid = H5Topen2(fid_dst, NAME_GROUP_TOP2 "/" NAME_DATATYPE_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + + /* Open SRC2 dset dtype, check address */ + if((did = H5Dopen2(fid_dst, NAME_GROUP_TOP2 "/" NAME_DATASET_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Close destination file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + /* + * Now copy only the datasets to the destination file, and verify the committed + * datatypes are merged + */ + /* recreate destination file */ + if((fid_dst = H5Fcreate(dst_filename, H5F_ACC_TRUNC, fcpl_dst, dst_fapl)) < 0) TEST_ERROR + + /* Create an uncopied object in destination file so that addresses in source and destination files aren't the same */ + if(H5Gclose(H5Gcreate2(fid_dst, NAME_GROUP_UNCOPIED, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* copy SRC1 to DST */ + if(H5Ocopy(fid_src1, NAME_DATASET_SIMPLE, fid_dst, NAME_DATASET_SIMPLE, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + /* copy SRC2 to DST */ + if(H5Ocopy(fid_src2, NAME_DATASET_SIMPLE, fid_dst, NAME_DATASET_SIMPLE2, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + if(reopen) { + /* Reopen file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDONLY, dst_fapl)) < 0) TEST_ERROR + } /* end if */ + + /* Open SRC1 dset dtype, get address */ + if((did = H5Dopen2(fid_dst, NAME_DATASET_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Open SRC2 dset dtype, check address */ + if((did = H5Dopen2(fid_dst, NAME_DATASET_SIMPLE2, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Close destination file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + /* close the SRC files */ + if(H5Fclose(fid_src1) < 0) TEST_ERROR + if(H5Fclose(fid_src2) < 0) TEST_ERROR + + /* close property list */ + if(H5Pclose(ocpypl_id) < 0) TEST_ERROR + + /* close dataspace */ + if(H5Sclose(sid) < 0) TEST_ERROR + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Fclose(fid_src1); + H5Fclose(fid_src2); + H5Fclose(fid_dst); + H5Tclose(tid); + H5Sclose(sid); + H5Dclose(did); + H5Pclose(ocpypl_id); + } H5E_END_TRY; + return 1; +} /* end test_copy_committed_datatype_merge */ + + +/*------------------------------------------------------------------------- + * Function: test_copy_committed_datatype_merge_same_file + * + * Purpose: Tests the "merge committed datatypes" feature of H5Ocopy, + * while copying to the same file. + * + * Return: Success: 0 + * Failure: number of errors + * + * Programmer: Neil Fortner + * Tuesday, October 11, 2011 + * + *------------------------------------------------------------------------- + */ +static int +test_copy_committed_datatype_merge_same_file(hid_t fcpl, hid_t fapl, hbool_t reopen) +{ + hid_t fid = -1; /* File ID */ + hid_t tid = -1; /* Datatype ID */ + hid_t sid = -1; /* Dataspace ID */ + hid_t did = -1; /* Dataset ID */ + hid_t gid = -1; /* Group ID */ + hid_t ocpypl_id = -1; /* Object copy plist ID */ + unsigned int i; /* Local index variables */ + hsize_t dim1d[1]; /* Dataset dimensions */ + int buf[DIM_SIZE_1]; /* Buffer for writing data */ + H5O_info_t oinfo; /* Object info */ + haddr_t exp_addr; /* Expected object address */ + char filename[NAME_BUF_SIZE]; + + if(reopen) + TESTING("H5Ocopy(): merging committed datatypes to the source file with reopen") + else + TESTING("H5Ocopy(): merging committed datatypes to the source file") + + /* set initial data values */ + for(i = 0; i < DIM_SIZE_1; i++) + buf[i] = (int)i; + + /* Initialize the filename */ + h5_fixname(FILENAME[0], fapl, filename, sizeof filename); + + /* Reset file address checking info */ + addr_reset(); + + /* create file */ + if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl, fapl)) < 0) TEST_ERROR + + /* Set dataspace dimensions */ + dim1d[0]=DIM_SIZE_1; + + /* create dataspace */ + if((sid = H5Screate_simple(1, dim1d, NULL)) < 0) TEST_ERROR + + /* + * Populate first group + */ + /* Create group */ + if((gid = H5Gcreate2(fid, NAME_GROUP_TOP, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* create datatype */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)TEST_ERROR + + /* committed data type */ + if((H5Tcommit2(fid, NAME_GROUP_TOP "/" NAME_DATATYPE_SIMPLE, tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* create dataset */ + if((did = H5Dcreate2(fid, NAME_GROUP_TOP "/" NAME_DATASET_SIMPLE, tid, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* write data into file */ + if(H5Dwrite(did, tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR + + /* close the datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR + + /* close the dataset */ + if(H5Dclose(did) < 0) TEST_ERROR + + /* close the group */ + if(H5Gclose(gid) < 0) TEST_ERROR + + /* + * Populate second group + */ + /* Create group */ + if((gid = H5Gcreate2(fid, NAME_GROUP_TOP2, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* create datatype */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)TEST_ERROR + + /* committed data type */ + if((H5Tcommit2(fid, NAME_GROUP_TOP2 "/" NAME_DATATYPE_SIMPLE, tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* create dataset */ + if((did = H5Dcreate2(fid, NAME_GROUP_TOP2 "/" NAME_DATASET_SIMPLE, tid, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* write data into file */ + if(H5Dwrite(did, tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR + + /* close the datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR + + /* close the dataset */ + if(H5Dclose(did) < 0) TEST_ERROR + + /* close the group */ + if(H5Gclose(gid) < 0) TEST_ERROR + + + /* Create ocpl and set merge committed dtype flag */ + if((ocpypl_id = H5Pcreate(H5P_OBJECT_COPY)) < 0) TEST_ERROR + if(H5Pset_copy_object(ocpypl_id, H5O_COPY_MERGE_COMMITTED_DTYPE_FLAG) < 0) TEST_ERROR + + /* + * First copy each group to the destination group 3 (each with their own + * group), and verify the committed datatypes are merged as expected. All + * datatypes copied should reference (share an address with) the + * corresponding source datatype. + */ + /* Create destination group */ + if((gid = H5Gcreate2(fid, NAME_GROUP_TOP3, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR + + /* copy group 1 to DST */ + if(H5Ocopy(fid, NAME_GROUP_TOP, fid, NAME_GROUP_TOP3 "/" NAME_GROUP_TOP, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + /* copy group 2 to DST */ + if(H5Ocopy(fid, NAME_GROUP_TOP2, fid, NAME_GROUP_TOP3 "/" NAME_GROUP_TOP2, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + if(reopen) { + /* Reopen file */ + if(H5Fclose(fid) < 0) TEST_ERROR + if((fid = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) TEST_ERROR + } /* end if */ + + /* Open group 1 source committed dtype, get address */ + if((tid = H5Topen2(fid, NAME_GROUP_TOP "/" NAME_DATATYPE_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + + /* Open group 1 source dset dtype, check address */ + if((did = H5Dopen2(fid, NAME_GROUP_TOP "/" NAME_DATASET_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Open group 1 committed dtype, check address */ + if((tid = H5Topen2(fid, NAME_GROUP_TOP3 "/" NAME_GROUP_TOP "/" NAME_DATATYPE_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + + /* Open group 1 dset dtype, check address */ + if((did = H5Dopen2(fid, NAME_GROUP_TOP3 "/" NAME_GROUP_TOP "/" NAME_DATASET_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Open group 2 source committed dtype, get address and make sure it is + * different from group 1 source committed dtype */ + if((tid = H5Topen2(fid, NAME_GROUP_TOP2 "/" NAME_DATATYPE_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr == exp_addr) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + + /* Open group 2 source dset dtype, check address */ + if((did = H5Dopen2(fid, NAME_GROUP_TOP2 "/" NAME_DATASET_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Open group 2 committed dtype, check address */ + if((tid = H5Topen2(fid, NAME_GROUP_TOP3 "/" NAME_GROUP_TOP2 "/" NAME_DATATYPE_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + + /* Open group 2 dset dtype, check address */ + if((did = H5Dopen2(fid, NAME_GROUP_TOP3 "/" NAME_GROUP_TOP2 "/" NAME_DATASET_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* + * Now copy only the datasets to the destination group, and verify the committed + * datatypes are merged as expected + */ + /* Create destination group */ + if((gid = H5Gcreate2(fid, NAME_GROUP_TOP4, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR + + /* copy SRC1 to DST */ + if(H5Ocopy(fid, NAME_GROUP_TOP "/" NAME_DATASET_SIMPLE, fid, NAME_GROUP_TOP4 "/" NAME_DATASET_SIMPLE, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + /* copy SRC2 to DST */ + if(H5Ocopy(fid, NAME_GROUP_TOP2 "/" NAME_DATASET_SIMPLE, fid, NAME_GROUP_TOP4 "/" NAME_DATASET_SIMPLE2, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + if(reopen) { + /* Reopen file */ + if(H5Fclose(fid) < 0) TEST_ERROR + if((fid = H5Fopen(filename, H5F_ACC_RDONLY, fapl)) < 0) TEST_ERROR + } /* end if */ + + /* Open group 1 source dset dtype, get address */ + if((did = H5Dopen2(fid, NAME_GROUP_TOP "/" NAME_DATASET_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Open group 1 dset dtype, check address */ + if((did = H5Dopen2(fid, NAME_GROUP_TOP4 "/" NAME_DATASET_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Open group 2 source dset dtype, get address and make sure it is + * different from group 1 source dset dtype */ + if((did = H5Dopen2(fid, NAME_GROUP_TOP2 "/" NAME_DATASET_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr == exp_addr) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Open group 2 dset dtype, check address */ + if((did = H5Dopen2(fid, NAME_GROUP_TOP4 "/" NAME_DATASET_SIMPLE2, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Close file */ + if(H5Fclose(fid) < 0) TEST_ERROR + + /* close property list */ + if(H5Pclose(ocpypl_id) < 0) TEST_ERROR + + /* close dataspace */ + if(H5Sclose(sid) < 0) TEST_ERROR + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Fclose(fid); + H5Tclose(tid); + H5Sclose(sid); + H5Dclose(did); + H5Pclose(ocpypl_id); + } H5E_END_TRY; + return 1; +} /* end test_copy_committed_datatype_merge_same_file */ + + + +/*------------------------------------------------------------------------- + * Function: test_copy_committed_dt_merge_sugg + * + * Purpose: Tests the "merge committed datatypes" feature of H5Ocopy, and + * uses the suggestion list feature + * (H5Padd_merge_committed_dtype_path). + * + * Return: Success: 0 + * Failure: number of errors + * + * Programmer: Neil Fortner + * Thursday, November 3, 2011 + * + *------------------------------------------------------------------------- + */ +static int +test_copy_committed_dt_merge_sugg(hid_t fcpl_src, hid_t fcpl_dst, hid_t src_fapl, + hid_t dst_fapl, hbool_t reopen) +{ + hid_t fid_src = -1, fid_dst = -1; /* File IDs */ + hid_t tid = -1; /* Datatype ID */ + hid_t sid = -1; /* Dataspace ID */ + hid_t did = -1; /* Dataset ID */ + hid_t ocpypl_id = -1; /* Object copy plist ID */ + unsigned int i; /* Local index variables */ + hsize_t dim1d[1]; /* Dataset dimensions */ + int buf[DIM_SIZE_1]; /* Buffer for writing data */ + H5O_info_t oinfo; /* Object info */ + haddr_t exp_addr; /* Expected object address */ + char src_filename[NAME_BUF_SIZE]; + char dst_filename[NAME_BUF_SIZE]; + + if(reopen) + TESTING("H5Ocopy(): merging committed datatypes with suggestions and reopen") + else + TESTING("H5Ocopy(): merging committed datatypes with suggestions") + + /* set initial data values */ + for(i = 0; i < DIM_SIZE_1; i++) + buf[i] = (int)i; + + /* Initialize the filenames */ + h5_fixname(FILENAME[0], src_fapl, src_filename, sizeof src_filename); + h5_fixname(FILENAME[1], dst_fapl, dst_filename, sizeof dst_filename); + + /* Reset file address checking info */ + addr_reset(); + + /* create source file */ + if((fid_src = H5Fcreate(src_filename, H5F_ACC_TRUNC, fcpl_src, src_fapl)) < 0) TEST_ERROR + + /* Set dataspace dimensions */ + dim1d[0]=DIM_SIZE_1; + + /* create dataspace */ + if((sid = H5Screate_simple(1, dim1d, NULL)) < 0) TEST_ERROR + + /* + * Populate source file + */ + /* create datatype */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)TEST_ERROR + + /* committed data type */ + if((H5Tcommit2(fid_src, NAME_DATATYPE_SIMPLE, tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* create dataset at SRC file */ + if((did = H5Dcreate2(fid_src, NAME_DATASET_SIMPLE, tid, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* write data into file */ + if(H5Dwrite(did, tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR + + /* close the datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR + + /* close the dataset */ + if(H5Dclose(did) < 0) TEST_ERROR + + /* close the SRC file */ + if(H5Fclose(fid_src) < 0) TEST_ERROR + + /* create destination file */ + if((fid_dst = H5Fcreate(dst_filename, H5F_ACC_TRUNC, fcpl_dst, dst_fapl)) < 0) TEST_ERROR + + /* + * Populate destination file + */ + /* create datatype */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)TEST_ERROR + + /* committed data type "a" */ + if((H5Tcommit2(fid_dst, "/a", tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* close the datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR + + /* create datatype */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)TEST_ERROR + + /* committed data type "b" */ + if((H5Tcommit2(fid_dst, "/b", tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* close the datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR + + /* close the DST file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + + /* open the source file with read-only */ + if((fid_src = H5Fopen(src_filename, H5F_ACC_RDONLY, src_fapl)) < 0) TEST_ERROR + + /* Create ocpl and set merge committed dtype flag */ + if((ocpypl_id = H5Pcreate(H5P_OBJECT_COPY)) < 0) TEST_ERROR + if(H5Pset_copy_object(ocpypl_id, H5O_COPY_MERGE_COMMITTED_DTYPE_FLAG) < 0) TEST_ERROR + + /* + * First copy dataset using "/b" as a suggestion, and verify that it uses + * datatype "b" in the destination file + */ + /* Add datatype suggestion */ + if(H5Padd_merge_committed_dtype_path(ocpypl_id, "/b") < 0) TEST_ERROR + + /* open destination file */ + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDWR, dst_fapl)) < 0) TEST_ERROR + + /* copy SRC dset to DST */ + if(H5Ocopy(fid_src, NAME_DATASET_SIMPLE, fid_dst, NAME_DATASET_SIMPLE, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + if(reopen) { + /* Reopen file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDONLY, dst_fapl)) < 0) TEST_ERROR + } /* end if */ + + /* Open committed dtype "b", get address */ + if((tid = H5Topen2(fid_dst, "/b", H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + + /* Open dset dtype, check address */ + if((did = H5Dopen2(fid_dst, NAME_DATASET_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Close destination file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + /* + * Now free suggestions, copy dataset without any suggestions, and verify + * that it uses datatype "a" in the destination file + */ + /* Free suggestions */ + if(H5Pfree_merge_committed_dtype_paths(ocpypl_id) < 0) TEST_ERROR + + /* open destination file */ + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDWR, dst_fapl)) < 0) TEST_ERROR + + /* Delete destination dataset */ + + /* copy SRC dset to DST */ + if(H5Ocopy(fid_src, NAME_DATASET_SIMPLE, fid_dst, NAME_DATASET_SIMPLE2, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + if(reopen) { + /* Reopen file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDONLY, dst_fapl)) < 0) TEST_ERROR + } /* end if */ + + /* Open committed dtype "a", get address */ + if((tid = H5Topen2(fid_dst, "/a", H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + + /* Open dset 2 dtype, check address */ + if((did = H5Dopen2(fid_dst, NAME_DATASET_SIMPLE2, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Open committed dtype "b", get address */ + if((tid = H5Topen2(fid_dst, "/b", H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + + /* Open dset dtype, check address */ + if((did = H5Dopen2(fid_dst, NAME_DATASET_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Close destination file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + /* close the SRC file */ + if(H5Fclose(fid_src) < 0) TEST_ERROR + + /* close property list */ + if(H5Pclose(ocpypl_id) < 0) TEST_ERROR + + /* close dataspace */ + if(H5Sclose(sid) < 0) TEST_ERROR + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Fclose(fid_src); + H5Fclose(fid_dst); + H5Tclose(tid); + H5Sclose(sid); + H5Dclose(did); + H5Pclose(ocpypl_id); + } H5E_END_TRY; + return 1; +} /* end test_copy_committed_dt_merge_sugg */ + + +/*------------------------------------------------------------------------- + * Function: test_copy_committed_dt_merge_attr + * + * Purpose: Tests the "merge committed datatypes" feature of H5Ocopy, with + * an attribute using an anonymous committed type in the + * destination. + * + * Return: Success: 0 + * Failure: number of errors + * + * Programmer: Neil Fortner + * Thursday, November 3, 2011 + * + *------------------------------------------------------------------------- + */ +static int +test_copy_committed_dt_merge_attr(hid_t fcpl_src, hid_t fcpl_dst, hid_t src_fapl, + hid_t dst_fapl, hbool_t reopen) +{ + hid_t fid_src = -1, fid_dst = -1; /* File IDs */ + hid_t tid = -1; /* Datatype ID */ + hid_t sid = -1; /* Dataspace ID */ + hid_t did = -1; /* Dataset ID */ + hid_t aid = -1; /* Attribute ID */ + hid_t gid = -1; /* Group ID */ + hid_t ocpypl_id = -1; /* Object copy plist ID */ + unsigned int i; /* Local index variables */ + hsize_t dim1d[1]; /* Dataset dimensions */ + int buf[DIM_SIZE_1]; /* Buffer for writing data */ + H5O_info_t oinfo; /* Object info */ + haddr_t exp_addr; /* Expected object address */ + char src_filename[NAME_BUF_SIZE]; + char dst_filename[NAME_BUF_SIZE]; + + if(reopen) + TESTING("H5Ocopy(): merging committed datatypes with attributes and reopen") + else + TESTING("H5Ocopy(): merging committed datatypes with attributes") + + /* set initial data values */ + for(i = 0; i < DIM_SIZE_1; i++) + buf[i] = (int)i; + + /* Initialize the filenames */ + h5_fixname(FILENAME[0], src_fapl, src_filename, sizeof src_filename); + h5_fixname(FILENAME[1], dst_fapl, dst_filename, sizeof dst_filename); + + /* Reset file address checking info */ + addr_reset(); + + /* create source file */ + if((fid_src = H5Fcreate(src_filename, H5F_ACC_TRUNC, fcpl_src, src_fapl)) < 0) TEST_ERROR + + /* Set dataspace dimensions */ + dim1d[0]=DIM_SIZE_1; + + /* create dataspace */ + if((sid = H5Screate_simple(1, dim1d, NULL)) < 0) TEST_ERROR + + /* + * Populate source file + */ + /* create datatype */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)TEST_ERROR + + /* committed data type */ + if((H5Tcommit2(fid_src, NAME_DATATYPE_SIMPLE, tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* create dataset at SRC file */ + if((did = H5Dcreate2(fid_src, NAME_DATASET_SIMPLE, tid, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* write data into file */ + if(H5Dwrite(did, tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR + + /* close the datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR + + /* close the dataset */ + if(H5Dclose(did) < 0) TEST_ERROR + + /* close the SRC file */ + if(H5Fclose(fid_src) < 0) TEST_ERROR + + /* create destination file */ + if((fid_dst = H5Fcreate(dst_filename, H5F_ACC_TRUNC, fcpl_dst, dst_fapl)) < 0) TEST_ERROR + + /* + * Populate destination file + */ + /* Create group */ + if((gid = H5Gcreate2(fid_dst, NAME_GROUP_TOP, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* create datatype */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)TEST_ERROR + + /* create anonymous committed data type */ + if((H5Tcommit_anon(fid_dst, tid, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* create attribute at SRC file */ + if((aid = H5Acreate2(gid, "attr", tid, sid, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* write data into file */ + if(H5Awrite(aid, tid, buf) < 0) TEST_ERROR + + /* close the datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR + + /* close the attribute */ + if(H5Aclose(aid) < 0) TEST_ERROR + + /* close the group */ + if(H5Gclose(gid) < 0) TEST_ERROR + + /* close the DST file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + + /* open the source file with read-only */ + if((fid_src = H5Fopen(src_filename, H5F_ACC_RDONLY, src_fapl)) < 0) TEST_ERROR + + /* Create ocpl and set merge committed dtype flag */ + if((ocpypl_id = H5Pcreate(H5P_OBJECT_COPY)) < 0) TEST_ERROR + if(H5Pset_copy_object(ocpypl_id, H5O_COPY_MERGE_COMMITTED_DTYPE_FLAG) < 0) TEST_ERROR + + /* + * Copy dataset and verify that it uses the same committed datatype as the + * already existing attribute in the destination file. + */ + /* open destination file */ + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDWR, dst_fapl)) < 0) TEST_ERROR + + /* copy SRC dset to DST */ + if(H5Ocopy(fid_src, NAME_DATASET_SIMPLE, fid_dst, NAME_DATASET_SIMPLE, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + if(reopen) { + /* Reopen file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDONLY, dst_fapl)) < 0) TEST_ERROR + } /* end if */ + + /* Open attribute dtype, get address */ + if((aid = H5Aopen_by_name(fid_dst, NAME_GROUP_TOP, "attr", H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Aget_type(aid)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Aclose(aid) < 0) TEST_ERROR + + /* Open dset dtype, check address */ + if((did = H5Dopen2(fid_dst, NAME_DATASET_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Close destination file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + /* close the SRC file */ + if(H5Fclose(fid_src) < 0) TEST_ERROR + + /* close property list */ + if(H5Pclose(ocpypl_id) < 0) TEST_ERROR + + /* close dataspace */ + if(H5Sclose(sid) < 0) TEST_ERROR + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Fclose(fid_src); + H5Fclose(fid_dst); + H5Tclose(tid); + H5Sclose(sid); + H5Dclose(did); + H5Aclose(aid); + H5Gclose(gid); + H5Pclose(ocpypl_id); + } H5E_END_TRY; + return 1; +} /* end test_copy_committed_dt_merge_attr */ + +/* + * Defines used for the committed datatype tests + */ +#define SRC_ROOT_GROUP "src_root" +#define ROOT_NDT_INT "root_ndt_int" +#define GROUP_NDT_SHORT "group_ndt_short" + +#define SRC_GRP "src_grp" +#define DST_GRP "dst_grp" +#define DST_GRP2 "dst_grp2" + +#define SRC_NDT_SHORT "src_ndt_short" +#define SRC_NDT_INT "src_ndt_int" +#define SRC_NDT_INT2 "src_ndt_int2" +#define SRC_NDT_FLOAT "src_ndt_float" +#define SRC_NDT_DOUBLE "src_ndt_double" + +#define DST_NDT_SHORT "dst_ndt_short" +#define DST_NDT_INT "dst_ndt_int" +#define DST_NDT_FLOAT "dst_ndt_float" +#define DST_NDT_DOUBLE "dst_ndt_double" + +#define SRC_NDT_DSET "src_ndt_dset" +#define SRC_NDT_DSET2 "src_ndt_dset2" +#define SRC_NDT_DSET3 "src_ndt_dset3" + +#define SRC_DSET "src_dset" +#define SRC_DSET1 "src_dset1" + +#define SRC_ATTR "src_attr" + +#define DST_ATTR_ANON_SHORT "dst_attr_anon_short" +#define DST_ATTR_ANON_INT "dst_attr_anon_int" + +#define DST_ATTR "dst_attr" +#define DST_ATTR2 "dst_attr2" + +/*------------------------------------------------------------------------- + * Function: test_copy_cdt_hier_merge + * + * Purpose: Tests the "merge committed datatypes" feature of H5Ocopy: + * SRC file: + * Create committed datatypes at / and /g0 + * Create datasets with native type and committed datatypes at /g0 + * DST file: + * Create attributes with anonymous committed datatypes at /uncopied + * + * Copy / at SRC to DST + * Copy /g0 at SRC to DST + * Copy the datasets in /g0 at SRC to DST /uncopied + * Verify that committed datatypes are copied and merged correctly + * + * Return: Success: 0 + * Failure: number of errors + * + * Programmer: Vailin Choi; January 2012 + * + *------------------------------------------------------------------------- + */ +static int +test_copy_cdt_hier_merge(hid_t fcpl_src, hid_t fcpl_dst, hid_t src_fapl, hid_t dst_fapl, hbool_t reopen) +{ + hid_t fid_src = -1, fid_dst = -1; /* File IDs */ + hid_t tid = -1; /* Datatype ID */ + hid_t sid = -1; /* Dataspace ID */ + hid_t did = -1; /* Dataset ID */ + hid_t gid = -1; /* Group IDs */ + hid_t f_tid = -1; /* Datatype ID for root group */ + hid_t g_tid = -1; /* Datatype ID for group */ + hid_t anon_tid = -1; /* Anonymous datatype */ + hid_t aid = -1; /* Attribute ID */ + hid_t ocpypl_id = -1; /* Object copy plist ID */ + int i; /* Local index variable */ + hsize_t dim1d[1]; /* dimension sizes */ + int buf[DIM_SIZE_1]; /* Buffer for data */ + haddr_t exp_addr_int, exp_addr_short; /* Expected object addresses */ + H5O_info_t oinfo; /* Object info */ + char src_filename[NAME_BUF_SIZE]; /* Source file name */ + char dst_filename[NAME_BUF_SIZE]; /* Destination file name */ + + if(reopen) + TESTING("H5Ocopy(): hier. of committed datatypes and merging with reopen") + else + TESTING("H5Ocopy(): hier. of committed datatypes and merging ") + + /* set initial data values */ + for (i=0; icalled++; + return(udata->search_action); +} /* mcdt_search_cb() */ + +static int +test_copy_set_mcdt_search_cb(hid_t fcpl_src, hid_t fcpl_dst, hid_t src_fapl, + hid_t dst_fapl, hbool_t reopen) +{ + hid_t fid_src = -1, fid_dst = -1; /* File IDs */ + hid_t tid = -1; /* Datatype ID */ + hid_t sid = -1; /* Dataspace ID */ + hid_t did = -1; /* Dataset ID */ + hid_t ocpypl_id = -1; /* Object copy plist ID */ + unsigned int i; /* Local index variables */ + hsize_t dim1d[1]; /* Dataset dimensions */ + int buf[DIM_SIZE_1]; /* Buffer for writing data */ + H5O_info_t oinfo; /* Object info */ + haddr_t exp_addr; /* Expected object address */ + char src_filename[NAME_BUF_SIZE]; + char dst_filename[NAME_BUF_SIZE]; + mcdt_search_cb_ud cb_udata; /* User data for callback */ + + if(reopen) + TESTING("H5Ocopy(): H5Pset_mcdt_search_cb and reopen") + else + TESTING("H5Ocopy(): H5Pset_mcdt_search_cb") + + /* set initial data values */ + for(i = 0; i < DIM_SIZE_1; i++) + buf[i] = (int)i; + + /* Initialize the filenames */ + h5_fixname(FILENAME[0], src_fapl, src_filename, sizeof src_filename); + h5_fixname(FILENAME[1], dst_fapl, dst_filename, sizeof dst_filename); + + /* Reset file address checking info */ + addr_reset(); + + /* create source file */ + if((fid_src = H5Fcreate(src_filename, H5F_ACC_TRUNC, fcpl_src, src_fapl)) < 0) TEST_ERROR + + /* Set dataspace dimensions */ + dim1d[0]=DIM_SIZE_1; + + /* create dataspace */ + if((sid = H5Screate_simple(1, dim1d, NULL)) < 0) TEST_ERROR + + /* + * Populate source file + */ + /* create datatype */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)TEST_ERROR + + /* named data type */ + if((H5Tcommit2(fid_src, NAME_DATATYPE_SIMPLE, tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* create dataset at SRC file */ + if((did = H5Dcreate2(fid_src, NAME_DATASET_SIMPLE, tid, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* write data into file */ + if(H5Dwrite(did, tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR + + /* close the datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR + + /* close the dataset */ + if(H5Dclose(did) < 0) TEST_ERROR + + /* close the SRC file */ + if(H5Fclose(fid_src) < 0) TEST_ERROR + + /* create destination file */ + if((fid_dst = H5Fcreate(dst_filename, H5F_ACC_TRUNC, fcpl_dst, dst_fapl)) < 0) TEST_ERROR + + /* Create an uncopied group in destination file */ + if(H5Gclose(H5Gcreate2(fid_dst, NAME_GROUP_UNCOPIED, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* + * Populate destination file + */ + /* create datatype */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)TEST_ERROR + + /* committed data type "a" */ + if((H5Tcommit2(fid_dst, "/a", tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* close the datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR + + /* create datatype */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)TEST_ERROR + + /* committed data type "b" */ + if((H5Tcommit2(fid_dst, "/b", tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* close the datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR + + /* close the DST file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + + /* open the source file with read-only */ + if((fid_src = H5Fopen(src_filename, H5F_ACC_RDONLY, src_fapl)) < 0) TEST_ERROR + + /* Create ocpl and set merge committed dtype flag */ + if((ocpypl_id = H5Pcreate(H5P_OBJECT_COPY)) < 0) TEST_ERROR + if(H5Pset_copy_object(ocpypl_id, H5O_COPY_MERGE_COMMITTED_DTYPE_FLAG) < 0) TEST_ERROR + + /* + * First copy dataset using "/b" as a suggestion, and verify that it uses + * datatype "b" in the destination file + */ + /* Add datatype suggestion */ + if(H5Padd_merge_committed_dtype_path(ocpypl_id, "/b") < 0) TEST_ERROR + + /* open destination file */ + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDWR, dst_fapl)) < 0) TEST_ERROR + + /* copy SRC dset to DST */ + if(H5Ocopy(fid_src, NAME_DATASET_SIMPLE, fid_dst, NAME_DATASET_SIMPLE, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + if(reopen) { + /* Reopen file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDONLY, dst_fapl)) < 0) TEST_ERROR + } /* end if */ + + /* Open committed dtype "b", get address */ + if((tid = H5Topen2(fid_dst, "/b", H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + + /* Open dset dtype, check address */ + if((did = H5Dopen2(fid_dst, NAME_DATASET_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Close destination file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + /* + * Set callback to continue the search + */ + cb_udata.search_action = H5O_MCDT_SEARCH_CONT; + cb_udata.called = 0; + + /* Free suggestions */ + if(H5Pfree_merge_committed_dtype_paths(ocpypl_id) < 0) TEST_ERROR + + /* Add datatype suggestion to group "/uncopied" */ + if(H5Padd_merge_committed_dtype_path(ocpypl_id, NAME_GROUP_UNCOPIED) < 0) TEST_ERROR + + /* Continue the global search */ + if(H5Pset_mcdt_search_cb(ocpypl_id, mcdt_search_cb, &cb_udata) < 0) + TEST_ERROR + + /* open destination file */ + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDWR, dst_fapl)) < 0) TEST_ERROR + + /* copy SRC dset to DST */ + if(H5Ocopy(fid_src, NAME_DATASET_SIMPLE, fid_dst, NAME_DATASET_SIMPLE2, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + /* Verify callback has been called exactly once */ + if(cb_udata.called != 1) TEST_ERROR + + if(reopen) { + /* Reopen file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDONLY, dst_fapl)) < 0) TEST_ERROR + } /* end if */ + + /* Open committed dtype "a", get address */ + if((tid = H5Topen2(fid_dst, "/a", H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + + /* Open copied dataset and its dtype, check address */ + if((did = H5Dopen2(fid_dst, NAME_DATASET_SIMPLE2, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Close destination file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + + /* + * Stop the search, default action is to create an anonymous committed datatype + */ + cb_udata.search_action = H5O_MCDT_SEARCH_STOP; + cb_udata.called = 0; + + /* open destination file */ + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDWR, dst_fapl)) < 0) TEST_ERROR + + /* copy SRC dset to DST */ + if(H5Ocopy(fid_src, NAME_DATASET_SIMPLE, fid_dst, NAME_DATASET_SIMPLE3, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + /* Verify callback has been called exactly once */ + if(cb_udata.called != 1) TEST_ERROR + + if(reopen) { + /* Reopen file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDONLY, dst_fapl)) < 0) TEST_ERROR + } /* end if */ + + /* Open committed dtype "a", get address */ + if((tid = H5Topen2(fid_dst, "/a", H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + + /* Open the copied dataset and get its dtype, addresses should not be equal */ + if((did = H5Dopen2(fid_dst, NAME_DATASET_SIMPLE3, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr == exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Open committed dtype "b", get address */ + if((tid = H5Topen2(fid_dst, "/b", H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + + /* Open the copied dataset and get its dtype, addresses should not be equal */ + if((did = H5Dopen2(fid_dst, NAME_DATASET_SIMPLE3, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr == exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Close destination file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + + /* + * Stop the search, default action is to create an anonymous committed datatype. + * Disable suggestion list. + */ + cb_udata.search_action = H5O_MCDT_SEARCH_STOP; + cb_udata.called = 0; + + /* Free suggestions */ + if(H5Pfree_merge_committed_dtype_paths(ocpypl_id) < 0) TEST_ERROR + + /* open destination file */ + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDWR, dst_fapl)) < 0) TEST_ERROR + + /* Delete dataset */ + if(H5Ldelete(fid_dst, NAME_DATASET_SIMPLE3, H5P_DEFAULT) < 0) TEST_ERROR + + /* copy SRC dset to DST */ + if(H5Ocopy(fid_src, NAME_DATASET_SIMPLE, fid_dst, NAME_DATASET_SIMPLE3, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + /* Verify callback has been called exactly once */ + if(cb_udata.called != 1) TEST_ERROR + + if(reopen) { + /* Reopen file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDONLY, dst_fapl)) < 0) TEST_ERROR + } /* end if */ + + /* Open committed dtype "a", get address */ + if((tid = H5Topen2(fid_dst, "/a", H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + + /* Open the copied dataset and get its dtype, addresses should not be equal */ + if((did = H5Dopen2(fid_dst, NAME_DATASET_SIMPLE3, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr == exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Open committed dtype "b", get address */ + if((tid = H5Topen2(fid_dst, "/b", H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + + /* Open the copied dataset and get its dtype, addresses should not be equal */ + if((did = H5Dopen2(fid_dst, NAME_DATASET_SIMPLE3, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr == exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Close destination file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + /* close the SRC file */ + if(H5Fclose(fid_src) < 0) TEST_ERROR + + /* close property list */ + if(H5Pclose(ocpypl_id) < 0) TEST_ERROR + + /* close dataspace */ + if(H5Sclose(sid) < 0) TEST_ERROR + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Fclose(fid_src); + H5Fclose(fid_dst); + H5Tclose(tid); + H5Sclose(sid); + H5Dclose(did); + H5Pclose(ocpypl_id); + } H5E_END_TRY; + return 1; +} /* end test_copy_set_mcdt_search_cb */ + + +/*------------------------------------------------------------------------- + * Function: test_copy_set_get_mcdt_cb + * + * Purpose: Tests for the "H5Pset/get_mcdt_search_cb" feature of H5Ocopy. + * + * Return: Success: 0 + * Failure: number of errors + * + * Programmer: Vailin Choi; January 2012 + * + *------------------------------------------------------------------------- + */ + +/* The user callback functions */ +static H5O_mcdt_search_ret_t +mcdt_search_cbA(void *_udata) +{ + H5O_mcdt_search_ret_t *action = (H5O_mcdt_search_ret_t *)_udata; + + return(*action); +} /* mcdt_search_cb() */ + +static H5O_mcdt_search_ret_t +mcdt_search_cbB(void *_udata) +{ + H5O_mcdt_search_ret_t *action = (H5O_mcdt_search_ret_t *)_udata; + + return(*action); +} /* mnt_search_cb() */ + +/* The main test function */ +static int +test_copy_set_get_mcdt_search_cb(hid_t fcpl_src, hid_t fcpl_dst, hid_t src_fapl, + hid_t dst_fapl, hbool_t reopen) +{ + hid_t fid_src = -1, fid_dst = -1; /* File IDs */ + hid_t tid = -1; /* Datatype ID */ + hid_t sid = -1; /* Dataspace ID */ + hid_t did = -1; /* Dataset ID */ + hid_t ocpypl_id = -1; /* Object copy plist ID */ + unsigned int i; /* Local index variables */ + hsize_t dim1d[1]; /* Dataset dimensions */ + int buf[DIM_SIZE_1]; /* Buffer for writing data */ + char src_filename[NAME_BUF_SIZE]; + char dst_filename[NAME_BUF_SIZE]; + H5O_mcdt_search_cb_t mcdt_cb = NULL; /* The callback function */ + H5O_mcdt_search_ret_t mcdt_udataA; /* User data for callback */ + H5O_mcdt_search_ret_t mcdt_udataB; /* User data for callback */ + H5O_mcdt_search_ret_t *mcdt_udata_p = NULL; /* Pointer to user data for callback */ + + if(reopen) + TESTING("H5Ocopy(): H5Pset/get_mcdt_search_cb and reopen") + else + TESTING("H5Ocopy(): H5Pset/get_mcdt_search_cb") + + /* set initial data values */ + for(i = 0; i < DIM_SIZE_1; i++) + buf[i] = (int)i; + + /* Initialize the filenames */ + h5_fixname(FILENAME[0], src_fapl, src_filename, sizeof src_filename); + h5_fixname(FILENAME[1], dst_fapl, dst_filename, sizeof dst_filename); + + /* Reset file address checking info */ + addr_reset(); + + /* create source file */ + if((fid_src = H5Fcreate(src_filename, H5F_ACC_TRUNC, fcpl_src, src_fapl)) < 0) TEST_ERROR + + /* Set dataspace dimensions */ + dim1d[0]=DIM_SIZE_1; + + /* create dataspace */ + if((sid = H5Screate_simple(1, dim1d, NULL)) < 0) TEST_ERROR + + /* + * Populate source file + */ + /* create datatype */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)TEST_ERROR + + /* committed data type */ + if((H5Tcommit2(fid_src, NAME_DATATYPE_SIMPLE, tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* create dataset at SRC file */ + if((did = H5Dcreate2(fid_src, NAME_DATASET_SIMPLE, tid, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* write data into file */ + if(H5Dwrite(did, tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR + + /* close the datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR + + /* close the dataset */ + if(H5Dclose(did) < 0) TEST_ERROR + + /* close the SRC file */ + if(H5Fclose(fid_src) < 0) TEST_ERROR + + /* create destination file */ + if((fid_dst = H5Fcreate(dst_filename, H5F_ACC_TRUNC, fcpl_dst, dst_fapl)) < 0) TEST_ERROR + + /* Create an uncopied group in destination file */ + if(H5Gclose(H5Gcreate2(fid_dst, NAME_GROUP_UNCOPIED, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* + * Populate destination file + */ + /* create datatype */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)TEST_ERROR + + /* committed data type "a" */ + if((H5Tcommit2(fid_dst, "/a", tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* close the datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR + + /* create datatype */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)TEST_ERROR + + /* committed data type "b" */ + if((H5Tcommit2(fid_dst, "/b", tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* close the datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR + + /* close the DST file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + + /* open the source file with read-only */ + if((fid_src = H5Fopen(src_filename, H5F_ACC_RDONLY, src_fapl)) < 0) TEST_ERROR + + /* Create ocpl and set merge committed dtype flag */ + if((ocpypl_id = H5Pcreate(H5P_OBJECT_COPY)) < 0) TEST_ERROR + if(H5Pset_copy_object(ocpypl_id, H5O_COPY_MERGE_COMMITTED_DTYPE_FLAG) < 0) TEST_ERROR + + /* + * First copy dataset using "/b" as a suggestion, and verify that it uses + * datatype "b" in the destination file + */ + /* Add datatype suggestion */ + if(H5Padd_merge_committed_dtype_path(ocpypl_id, "/b") < 0) TEST_ERROR + + /* open destination file */ + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDWR, dst_fapl)) < 0) TEST_ERROR + + /* copy SRC dset to DST */ + if(H5Ocopy(fid_src, NAME_DATASET_SIMPLE, fid_dst, NAME_DATASET_SIMPLE, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + if(reopen) { + /* Reopen file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDONLY, dst_fapl)) < 0) TEST_ERROR + } /* end if */ + + /* Verify "get" routine functionality */ + if(H5Pget_mcdt_search_cb(ocpypl_id, &mcdt_cb, (void **) &mcdt_udata_p) < 0) TEST_ERROR + + if(mcdt_cb != NULL) TEST_ERROR + if(mcdt_udata_p != NULL) TEST_ERROR + + /* Close destination file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + /* + * Set callback to continue the search + */ + mcdt_udataA = H5O_MCDT_SEARCH_CONT; + + /* Free suggestions */ + if(H5Pfree_merge_committed_dtype_paths(ocpypl_id) < 0) TEST_ERROR + + /* Add datatype suggestion to group "/uncopied" */ + if(H5Padd_merge_committed_dtype_path(ocpypl_id, NAME_GROUP_UNCOPIED) < 0) TEST_ERROR + + /* Continue the global search */ + if(H5Pset_mcdt_search_cb(ocpypl_id, mcdt_search_cbA, &mcdt_udataA) < 0) + TEST_ERROR + + /* open the destination file */ + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDWR, dst_fapl)) < 0) TEST_ERROR + + /* copy SRC dset to DST */ + if(H5Ocopy(fid_src, NAME_DATASET_SIMPLE, fid_dst, NAME_DATASET_SIMPLE2, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + if(reopen) { + /* Reopen file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDONLY, dst_fapl)) < 0) TEST_ERROR + } /* end if */ + + mcdt_cb = NULL; + mcdt_udata_p = NULL; + + /* Verify "get" routine functionality */ + if(H5Pget_mcdt_search_cb(ocpypl_id, &mcdt_cb, (void **) &mcdt_udata_p) < 0) TEST_ERROR + + if(mcdt_cb != mcdt_search_cbA) TEST_ERROR + if(mcdt_udata_p != &mcdt_udataA) TEST_ERROR + + /* Close destination file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + + /* + * Stop the search, default action is to create an anonymous committed datatype + */ + mcdt_udataB = H5O_MCDT_SEARCH_STOP; + + if(H5Pset_mcdt_search_cb(ocpypl_id, mcdt_search_cbA, &mcdt_udataB) < 0) + TEST_ERROR + + /* open destination file */ + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDWR, dst_fapl)) < 0) TEST_ERROR + + /* copy SRC dset to DST */ + if(H5Ocopy(fid_src, NAME_DATASET_SIMPLE, fid_dst, NAME_DATASET_SIMPLE3, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + if(reopen) { + /* Reopen file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDONLY, dst_fapl)) < 0) TEST_ERROR + } /* end if */ + + mcdt_cb = NULL; + mcdt_udata_p = NULL; + + /* Verify "get" routine functionality */ + if(H5Pget_mcdt_search_cb(ocpypl_id, &mcdt_cb, (void **) &mcdt_udata_p) < 0) TEST_ERROR + + if(mcdt_cb != mcdt_search_cbA) TEST_ERROR + if(mcdt_udata_p != &mcdt_udataB) TEST_ERROR + + /* Close destination file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + /* Free suggestions */ + if(H5Pfree_merge_committed_dtype_paths(ocpypl_id) < 0) TEST_ERROR + + if(H5Pset_mcdt_search_cb(ocpypl_id, mcdt_search_cbB, &mcdt_udataB) < 0) + TEST_ERROR + + /* open destination file */ + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDWR, dst_fapl)) < 0) TEST_ERROR + + /* Delete dataset */ + if(H5Ldelete(fid_dst, NAME_DATASET_SIMPLE3, H5P_DEFAULT) < 0) TEST_ERROR + + /* copy SRC dset to DST */ + if(H5Ocopy(fid_src, NAME_DATASET_SIMPLE, fid_dst, NAME_DATASET_SIMPLE3, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + if(reopen) { + /* Reopen file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDONLY, dst_fapl)) < 0) TEST_ERROR + } /* end if */ + + mcdt_cb = NULL; + mcdt_udata_p = NULL; + + /* Verify "get" routine functionality */ + if(H5Pget_mcdt_search_cb(ocpypl_id, &mcdt_cb, (void **) &mcdt_udata_p) < 0) TEST_ERROR + + if(mcdt_cb != mcdt_search_cbB) TEST_ERROR + if(mcdt_udata_p != &mcdt_udataB) TEST_ERROR + + /* Close destination file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + /* close the SRC file */ + if(H5Fclose(fid_src) < 0) TEST_ERROR + + /* close property list */ + if(H5Pclose(ocpypl_id) < 0) TEST_ERROR + + /* close dataspace */ + if(H5Sclose(sid) < 0) TEST_ERROR + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Fclose(fid_src); + H5Fclose(fid_dst); + H5Tclose(tid); + H5Sclose(sid); + H5Dclose(did); + H5Pclose(ocpypl_id); + } H5E_END_TRY; + return 1; +} /* end test_copy_set_get_mcdt_search_cb */ + + +/*------------------------------------------------------------------------- + * Function: test_copy_option + * + * Purpose: Create a group in SRC file and copy it to DST file + * + * Return: Success: 0 + * Failure: number of errors + * + * Programmer: Peter Cao + * March 11, 2006 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +test_copy_option(hid_t fcpl_src, hid_t fcpl_dst, hid_t src_fapl, hid_t dst_fapl, + unsigned flag, hbool_t crt_intermediate_grp, const char* test_desciption) +{ + hid_t fid_src = -1, fid_dst = -1, fid_ext = -1; /* File IDs */ + hid_t sid = -1; /* Dataspace ID */ + hid_t did = -1; /* Dataset ID */ + hid_t gid=-1, gid2=-1, gid_ref=-1; /* Group IDs */ + hid_t gid_sub=-1, gid_sub_sub=-1; /* Sub-group ID */ + hid_t pid=-1, lcpl_id=-1; /* Property IDs */ + unsigned cpy_flags; /* Object copy flags */ + int depth = -1; /* Copy depth */ + hsize_t dim2d[2]; + int buf[DIM_SIZE_1][DIM_SIZE_2]; + int i, j; + char src_filename[NAME_BUF_SIZE]; + char dst_filename[NAME_BUF_SIZE]; + + TESTING(test_desciption); + + /* set initial data values */ + for (i=0; i 0) { + /* Create group to copy */ + if((gid = H5Gcreate2(fid_src, NAME_GROUP_LINK, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR + if(H5Lcreate_soft(NAME_DATASET_SUB_SUB, fid_src, NAME_LINK_SOFT, H5P_DEFAULT, H5P_DEFAULT) < 0) FAIL_STACK_ERROR + if(H5Lcreate_soft("nowhere", fid_src, NAME_LINK_SOFT_DANGLE, H5P_DEFAULT, H5P_DEFAULT) < 0) FAIL_STACK_ERROR + if(H5Gclose(gid) < 0) FAIL_STACK_ERROR + + /* Create group to compare with */ + if((gid = H5Gcreate2(fid_src, NAME_GROUP_LINK2, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR + if(H5Lcreate_hard(fid_src, NAME_DATASET_SUB_SUB, H5L_SAME_LOC, NAME_LINK_SOFT2, H5P_DEFAULT, H5P_DEFAULT) < 0) FAIL_STACK_ERROR + if(H5Lcreate_soft("nowhere", fid_src, NAME_LINK_SOFT_DANGLE2, H5P_DEFAULT, H5P_DEFAULT) < 0) FAIL_STACK_ERROR + if(H5Gclose(gid) < 0) FAIL_STACK_ERROR + } /* end if */ + + if((flag & H5O_COPY_EXPAND_EXT_LINK_FLAG) > 0) { + char ext_filename[NAME_BUF_SIZE]; + + h5_fixname(FILENAME[2], src_fapl, ext_filename, sizeof ext_filename); + + /* Create the external file and dataset */ + if((fid_ext = H5Fcreate(ext_filename, H5F_ACC_TRUNC, fcpl_src, src_fapl)) < 0) TEST_ERROR + if((sid = H5Screate_simple(2, dim2d, NULL)) < 0) TEST_ERROR + if((did = H5Dcreate2(fid_ext, NAME_DATASET_SIMPLE, H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + if(H5Fclose(fid_ext) < 0) TEST_ERROR + + /* Create group to copy */ + if(!(flag & H5O_COPY_EXPAND_SOFT_LINK_FLAG)) { + if((gid = H5Gcreate2(fid_src, NAME_GROUP_LINK, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + } /* end if */ + else + if((gid = H5Gopen2(fid_src, NAME_GROUP_LINK, H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Lcreate_external(ext_filename, NAME_DATASET_SIMPLE, fid_src, NAME_LINK_EXTERN, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR + if(H5Lcreate_external("no_file", "no_object", fid_src, NAME_LINK_EXTERN_DANGLE, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Create group to compare with */ + if(!(flag & H5O_COPY_EXPAND_SOFT_LINK_FLAG)) { + if((gid = H5Gcreate2(fid_src, NAME_GROUP_LINK2, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + } /* end if */ + else + if((gid = H5Gopen2(fid_src, NAME_GROUP_LINK2, H5P_DEFAULT)) < 0) TEST_ERROR + if((did = H5Dcreate2(fid_src, NAME_LINK_EXTERN2, H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR + if(H5Lcreate_external("no_file", "no_object", fid_src, NAME_LINK_EXTERN_DANGLE2, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Close dataspace */ + if(H5Sclose(sid) < 0) TEST_ERROR + } /* end if */ + + if((flag & H5O_COPY_EXPAND_REFERENCE_FLAG) > 0) { + if((gid_ref = H5Gcreate2(fid_src, NAME_GROUP_REF, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* create an attribute of object references */ + if(attach_ref_attr(fid_src, gid_ref) < 0) TEST_ERROR + + /* create an attribute of region references */ + if(attach_reg_ref_attr(fid_src, gid_ref) < 0) TEST_ERROR + + /* create a dataset of region references */ + if(create_reg_ref_dataset(fid_src, gid_ref) < 0) TEST_ERROR + + /* Close group holding reference objects */ + if(H5Gclose(gid_ref) < 0) TEST_ERROR + } /* end if */ + + /* close the SRC file */ + if(H5Fclose(fid_src) < 0) TEST_ERROR + + /* open the source file with read-only */ + /* (except when expanding soft links */ + if((flag & H5O_COPY_EXPAND_SOFT_LINK_FLAG) > 0) { + if((fid_src = H5Fopen(src_filename, H5F_ACC_RDWR, src_fapl)) < 0) TEST_ERROR + } /* end if */ + else + if((fid_src = H5Fopen(src_filename, H5F_ACC_RDONLY, src_fapl)) < 0) TEST_ERROR + + /* create destination file */ + if((fid_dst = H5Fcreate(dst_filename, H5F_ACC_TRUNC, fcpl_dst, dst_fapl)) < 0) TEST_ERROR + + /* Create an uncopied object in destination file so that addresses in source and destination + files aren't the same */ + if(H5Gclose(H5Gcreate2(fid_dst, NAME_GROUP_UNCOPIED, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* create property to pass copy options */ + if((pid = H5Pcreate(H5P_OBJECT_COPY)) < 0) TEST_ERROR + + /* set options for object copy */ + if(H5Pset_copy_object(pid, flag) < 0) TEST_ERROR + + /* Verify object copy flags */ + if(H5Pget_copy_object(pid, &cpy_flags) < 0) TEST_ERROR + if(cpy_flags != flag) TEST_ERROR + + /* copy the group from SRC to DST */ + if(crt_intermediate_grp) { + /* Create link creation plist to pass in intermediate group creation */ + if((lcpl_id = H5Pcreate(H5P_LINK_CREATE)) < 0) TEST_ERROR + if(H5Pset_create_intermediate_group(lcpl_id, TRUE) < 0) TEST_ERROR + + if(H5Ocopy(fid_src, NAME_GROUP_TOP, fid_dst, "/new_g0/new_g00", pid, lcpl_id) < 0) TEST_ERROR + + if(H5Pclose(lcpl_id) < 0) TEST_ERROR + + /* open the group for copy */ + if((gid = H5Gopen2(fid_src, NAME_GROUP_TOP, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR + + /* open the destination group */ + if((gid2 = H5Gopen2(fid_dst, "/new_g0/new_g00", H5P_DEFAULT)) < 0) FAIL_STACK_ERROR + + } else if(((flag & H5O_COPY_EXPAND_SOFT_LINK_FLAG) > 0) + || ((flag & H5O_COPY_EXPAND_EXT_LINK_FLAG) > 0)) { + if(H5Ocopy(fid_src, NAME_GROUP_LINK, fid_dst, NAME_GROUP_LINK, pid, H5P_DEFAULT) < 0) TEST_ERROR + + if((flag & H5O_COPY_EXPAND_SOFT_LINK_FLAG) > 0) + /* Unlink dataset to copy from original location */ + /* (So group comparison works properly) */ + if(H5Ldelete(fid_src, NAME_DATASET_SUB_SUB, H5P_DEFAULT) < 0) FAIL_STACK_ERROR + + /* open the group for copy */ + if((gid = H5Gopen2(fid_src, NAME_GROUP_LINK2, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR + + /* open the destination group */ + if((gid2 = H5Gopen2(fid_dst, NAME_GROUP_LINK, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR + + } else if(flag & (H5O_COPY_WITHOUT_ATTR_FLAG | H5O_COPY_PRESERVE_NULL_FLAG)) { + if(H5Ocopy(fid_src, NAME_GROUP_TOP, fid_dst, NAME_GROUP_TOP, pid, H5P_DEFAULT) < 0) TEST_ERROR /* open the group for copy */ if((gid = H5Gopen2(fid_src, NAME_GROUP_TOP, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR @@ -8919,6 +12273,337 @@ error: /*------------------------------------------------------------------------- + * Function: test_copy_dataset_open + * + * Purpose: To ensure that H5Ocopy() copies data of opened dataset correctly. + * This is for bug fix HDFFV-7853. + * + * Test Case 1: + * Create a dataset with attributes in SRC file + * Copy the opened dataset to another location in the same file + * Copy the opened dataset to DST file + * Close the dataset + * + * Test Case 2: + * Reopen the dataset, write new data to the dataset + * Copy the opened dataset to another location in the same file + * Copy the opened dataset to to DST file + * Close the dataset + * + * Test Case 3: + * Create a committed datatype + * Create a dataset with the committed datatype in SRC file + * Open the committed datatype + * Copy the opened dataset (with the opened committed datatype) to another location in the same file + * Copy the opened dataset (with the opened committed datatype) to DST file + * Close the dataset and the committed datatype + * + * Test Case 4: + * Create a group with attributes, create a dataset in the group + * Copy the opened group (together with the opened dataset) to another location in the same file + * Copy the opened group (together with the opened dataset) to DST file + * Close the group and the dataset + * + * Return: Success: 0 + * Failure: number of errors + * + * Programmer: Vailin Choi + * Feb 7, 2012 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +test_copy_dataset_open(hid_t fcpl_src, hid_t fcpl_dst, hid_t src_fapl, hid_t dst_fapl) +{ + hid_t fid_src = -1, fid_dst = -1; /* File IDs */ + hid_t sid = -1; /* Dataspace ID */ + hid_t tid = -1; /* Datatype ID */ + hid_t did = -1, did2 = -1; /* Dataset IDs */ + hid_t gid = -1, gid2 = -1; /* Group IDs */ + hid_t ocpl = -1; /* Object copy property list ID */ + int buf[DIM_SIZE_1][DIM_SIZE_2]; /* Buffer for writing data */ + int newbuf[DIM_SIZE_1][DIM_SIZE_2]; /* Buffer for writing data */ + hsize_t dim2d[2]; /* Dataset dimensions */ + hbool_t copy_open_obj = TRUE; /* Property to indicate we are copying open objects */ + int i, j; /* local index variables */ + char src_filename[NAME_BUF_SIZE]; + char dst_filename[NAME_BUF_SIZE]; + + TESTING("H5Ocopy(): copying objects while opened"); + + /* Initialize write buffer */ + for (i=0; i= 0), ""); + + /* create the file collectively */ + fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, acc_tpl); + VRFY((fid >= 0), "H5Fcreate succeeded"); + + /* Release file-access template */ + ret = H5Pclose(acc_tpl); + VRFY((ret >= 0), "H5Pclose succeeded"); + + /* setup dimensionality object */ + dims[0] = dim0; + dims[1] = dim1; + sid = H5Screate_simple (RANK, dims, NULL); + VRFY((sid >= 0), "H5Screate_simple succeeded"); + + /* create datasets */ + dataset1 = H5Dcreate2(fid, DATASETNAME5, H5T_NATIVE_INT, sid, + H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + VRFY((dataset1 >= 0), "H5Dcreate2 succeeded"); + + dataset2 = H5Dcreate2(fid, DATASETNAME6, H5T_NATIVE_INT, sid, + H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + VRFY((dataset2 >= 0), "H5Dcreate2 succeeded"); + + /* initialize datasets to 0s */ + if (0 == mpi_rank) { + ret = H5Dwrite(dataset1, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, write_buf); + VRFY((ret >= 0), "H5Dwrite dataset1 succeeded"); + + ret = H5Dwrite(dataset2, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, write_buf); + VRFY((ret >= 0), "H5Dwrite dataset2 succeeded"); + } + + ret = H5Dclose(dataset1); + VRFY((ret >= 0), "H5Dclose succeeded"); + ret = H5Dclose(dataset2); + VRFY((ret >= 0), "H5Dclose succeeded"); + ret = H5Sclose(sid); + VRFY((ret >= 0), "H5Sclose succeeded"); + ret = H5Fclose(fid); + VRFY((ret >= 0), "H5Fclose succeeded"); + + MPI_Barrier (comm); + + /* make sure setting atomicity fails on a serial file ID */ + /* open the file collectively */ + fid=H5Fopen(filename,H5F_ACC_RDWR,H5P_DEFAULT); + VRFY((fid >= 0), "H5Fopen succeeed"); + + /* should fail */ + ret = H5Fset_mpi_atomicity (fid , TRUE); + VRFY((ret == FAIL), "H5Fset_mpi_atomicity failed"); + + ret = H5Fclose(fid); + VRFY((ret >= 0), "H5Fclose succeeded"); + + MPI_Barrier (comm); + + /* setup file access template */ + acc_tpl = create_faccess_plist(comm, info, facc_type, use_gpfs); + VRFY((acc_tpl >= 0), ""); + + /* open the file collectively */ + fid=H5Fopen(filename,H5F_ACC_RDWR,acc_tpl); + VRFY((fid >= 0), "H5Fopen succeeded"); + + /* Release file-access template */ + ret = H5Pclose(acc_tpl); + VRFY((ret >= 0), "H5Pclose succeeded"); + + ret = H5Fset_mpi_atomicity (fid , TRUE); + VRFY((ret >= 0), "H5Fset_mpi_atomicity succeeded"); + + /* open dataset1 (contiguous case) */ + dataset1 = H5Dopen2(fid, DATASETNAME5, H5P_DEFAULT); + VRFY((dataset1 >= 0), "H5Dopen2 succeeded"); + + if (0 == mpi_rank) { + for (i=0 ; i= 0), "atomcity get failed"); + VRFY((atomicity == TRUE), "atomcity set failed"); + + MPI_Barrier (comm); + + /* Process 0 writes contiguously to the entire dataset */ + if (0 == mpi_rank) { + ret = H5Dwrite(dataset1, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, write_buf); + VRFY((ret >= 0), "H5Dwrite dataset1 succeeded"); + } + /* The other processes read the entire dataset */ + else { + ret = H5Dread(dataset1, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, read_buf); + VRFY((ret >= 0), "H5Dwrite() dataset multichunk write succeeded"); + } + + if(VERBOSE_MED) { + i=0;j=0;k=0; + for (i=0 ; i= 0), "H5D close succeeded"); + + /* release data buffers */ + if(write_buf) free(write_buf); + if(read_buf) free(read_buf); + + /* open dataset2 (non-contiguous case) */ + dataset2 = H5Dopen2(fid, DATASETNAME6, H5P_DEFAULT); + VRFY((dataset2 >= 0), "H5Dopen2 succeeded"); + + /* allocate memory for data buffer */ + write_buf = (int *)calloc(buf_size, sizeof(int)); + VRFY((write_buf != NULL), "write_buf malloc succeeded"); + /* allocate memory for data buffer */ + read_buf = (int *)calloc(buf_size, sizeof(int)); + VRFY((read_buf != NULL), "read_buf malloc succeeded"); + + for (i=0 ; i= 0), "atomcity get failed"); + VRFY((atomicity == TRUE), "atomcity set failed"); + + + block[0] = dim0/mpi_size - 1; + block[1] = dim1/mpi_size - 1; + stride[0] = block[0] + 1; + stride[1] = block[1] + 1; + count[0] = mpi_size; + count[1] = mpi_size; + start[0] = 0; + start[1] = 0; + + /* create a file dataspace */ + file_dataspace = H5Dget_space (dataset2); + VRFY((file_dataspace >= 0), "H5Dget_space succeeded"); + ret = H5Sselect_hyperslab(file_dataspace, H5S_SELECT_SET, start, stride, count, block); + VRFY((ret >= 0), "H5Sset_hyperslab succeeded"); + + /* create a memory dataspace */ + mem_dataspace = H5Screate_simple (RANK, dims, NULL); + VRFY((mem_dataspace >= 0), ""); + + ret = H5Sselect_hyperslab(mem_dataspace, H5S_SELECT_SET, start, stride, count, block); + VRFY((ret >= 0), "H5Sset_hyperslab succeeded"); + + MPI_Barrier (comm); + + /* Process 0 writes to the dataset */ + if (0 == mpi_rank) { + ret = H5Dwrite(dataset2, H5T_NATIVE_INT, mem_dataspace, file_dataspace, + H5P_DEFAULT, write_buf); + VRFY((ret >= 0), "H5Dwrite dataset2 succeeded"); + } + /* All processes wait for the write to finish. This works because + atomicity is set to true */ + MPI_Barrier (comm); + /* The other processes read the entire dataset */ + if (0 != mpi_rank) { + ret = H5Dread(dataset2, H5T_NATIVE_INT, mem_dataspace, file_dataspace, + H5P_DEFAULT, read_buf); + VRFY((ret >= 0), "H5Dread dataset2 succeeded"); + } + + if(VERBOSE_MED) { + if (mpi_rank == 1) { + i=0;j=0;k=0; + for (i=0 ; i= mpi_rank*(block[0]+1)) { + break; + } + if ((i+1)%(block[0]+1)==0) { + k += dim1; + continue; + } + for (j=0 ; j= mpi_rank*(block[1]+1)) { + k += dim1 - mpi_rank*(block[1]+1); + break; + } + if ((j+1)%(block[1]+1)==0) { + k++; + continue; + } + else if (compare != read_buf[k]) { + printf("Atomicity Test Failed Process %d: read_buf[%d] is %d, should be %d\n", mpi_rank, k, read_buf[k], compare); + nerrors++; + } + k ++; + } + } + } + + ret = H5Dclose(dataset2); + VRFY((ret >= 0), "H5Dclose succeeded"); + ret = H5Sclose(file_dataspace); + VRFY((ret >= 0), "H5Sclose succeeded"); + ret = H5Sclose(mem_dataspace); + VRFY((ret >= 0), "H5Sclose succeeded"); + + /* release data buffers */ + if(write_buf) free(write_buf); + if(read_buf) free(read_buf); + + ret = H5Fclose(fid); + VRFY((ret >= 0), "H5Fclose succeeded"); + +} diff --git a/testpar/t_file_image.c b/testpar/t_file_image.c new file mode 100644 index 0000000..544ba32 --- /dev/null +++ b/testpar/t_file_image.c @@ -0,0 +1,395 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Parallel tests for file image operations + */ + +#include "testphdf5.h" + +/* file_image_daisy_chain_test + * + * Process zero: + * + * 1) Creates a core file with an integer vector data set of + * length n (= mpi_size), + * + * 2) Initializes the vector to zero in * location 0, and to -1 + * everywhere else. + * + * 3) Flushes the core file, and gets an image of it. Closes + * the core file. + * + * 4) Sends the image to process 1. + * + * 5) Awaits receipt on a file image from process n-1. + * + * 6) opens the image received from process n-1, verifies that + * it contains a vector of length equal to mpi_size, and + * that the vector contains (0, 1, 2, ... n-1) + * + * 7) closes the core file and exits. + * + * Process i (0 < i < n) + * + * 1) Await receipt of file image from process (i - 1). + * + * 2) Open the image with the core file driver, verify that i + * contains a vector v of length, and that v[j] = j for + * 0 <= j < i, and that v[j] == -1 for i <= j < n + * + * 3) Set v[i] = i in the core file. + * + * 4) Flush the core file and send it to process (i + 1) % n. + * + * 5) close the core file and exit. + * + * Test fails on a hang (if an image is not received), or on invalid data. + * + * JRM -- 11/28/11 + */ +void +file_image_daisy_chain_test(void) +{ + char file_name[1024] = "\0"; + int mpi_size, mpi_rank; + int mpi_result; + int i; + int space_ndims; + MPI_Status rcvstat; + int * vector_ptr = NULL; + hid_t fapl_id = -1; + hid_t file_id; /* file IDs */ + hid_t dset_id = -1; + hid_t dset_type_id = -1; + hid_t space_id = -1; + herr_t err; + hsize_t dims[1]; + void * image_ptr = NULL; + ssize_t bytes_read; + ssize_t image_len; + hbool_t vector_ok = TRUE; + htri_t tri_result; + + + /* set up MPI parameters */ + MPI_Comm_size(MPI_COMM_WORLD, &mpi_size); + MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank); + + /* setup file name */ + HDsnprintf(file_name, 1024, "file_image_daisy_chain_test_%05d.h5", + (int)mpi_rank); + + if(mpi_rank == 0) { + + /* 1) Creates a core file with an integer vector data set + * of length mpi_size, + */ + fapl_id = H5Pcreate(H5P_FILE_ACCESS); + VRFY((fapl_id >= 0), "creating fapl"); + + err = H5Pset_fapl_core(fapl_id, (size_t)(64 *1024), FALSE); + VRFY((err >= 0), "setting core file driver in fapl."); + + file_id = H5Fcreate(file_name, 0, H5P_DEFAULT, fapl_id); + VRFY((file_id >= 0), "created core file"); + + dims[0] = (hsize_t)mpi_size; + space_id = H5Screate_simple(1, dims, dims); + VRFY((space_id >= 0), "created data space"); + + dset_id = H5Dcreate2(file_id, "v", H5T_NATIVE_INT, space_id, + H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + VRFY((dset_id >= 0), "created data set"); + + + /* 2) Initialize the vector to zero in location 0, and + * to -1 everywhere else. + */ + + vector_ptr = (int *)HDmalloc((size_t)(mpi_size) * sizeof(int)); + VRFY((vector_ptr != NULL), "allocated in memory representation of vector"); + + vector_ptr[0] = 0; + for(i = 1; i < mpi_size; i++) + vector_ptr[i] = -1; + + err = H5Dwrite(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void *)vector_ptr); + VRFY((err >= 0), "wrote initial data to vector."); + + HDfree(vector_ptr); + vector_ptr = NULL; + + + /* 3) Flush the core file, and get an image of it. Close + * the core file. + */ + err = H5Fflush(file_id, H5F_SCOPE_GLOBAL); + VRFY((err >= 0), "flushed core file."); + + image_len = H5Fget_file_image(file_id, NULL, (size_t)0); + VRFY((image_len > 0), "got image file size"); + + image_ptr = (void *)HDmalloc((size_t)image_len); + VRFY(image_ptr != NULL, "allocated file image buffer."); + + bytes_read = H5Fget_file_image(file_id, image_ptr, (size_t)image_len); + VRFY(bytes_read == image_len, "wrote file into image buffer"); + + err = H5Sclose(space_id); + VRFY((err >= 0), "closed data space."); + + err = H5Dclose(dset_id); + VRFY((err >= 0), "closed data set."); + + err = H5Fclose(file_id); + VRFY((err >= 0), "closed core file(1)."); + + err = H5Pclose(fapl_id); + VRFY((err >= 0), "closed fapl(1)."); + + + /* 4) Send the image to process 1. */ + + mpi_result = MPI_Ssend((void *)(&image_len), (int)sizeof(ssize_t), + MPI_BYTE, 1, 0, MPI_COMM_WORLD); + VRFY((mpi_result == MPI_SUCCESS), "sent image size to process 1"); + + mpi_result = MPI_Ssend((void *)image_ptr, (int)image_len, + MPI_BYTE, 1, 0, MPI_COMM_WORLD); + VRFY((mpi_result == MPI_SUCCESS), "sent image to process 1"); + + HDfree(image_ptr); + image_ptr = NULL; + image_len = 0; + + + /* 5) Await receipt on a file image from process n-1. */ + + mpi_result = MPI_Recv((void *)(&image_len), (int)sizeof(ssize_t), + MPI_BYTE, mpi_size - 1, 0, MPI_COMM_WORLD, + &rcvstat); + VRFY((mpi_result == MPI_SUCCESS), "received image len from process n-1"); + + image_ptr = (void *)HDmalloc((size_t)image_len); + VRFY(image_ptr != NULL, "allocated file image receive buffer."); + + mpi_result = MPI_Recv((void *)image_ptr, (int)image_len, + MPI_BYTE, mpi_size - 1, 0, MPI_COMM_WORLD, + &rcvstat); + VRFY((mpi_result == MPI_SUCCESS), \ + "received file image from process n-1"); + + /* 6) open the image received from process n-1, verify that + * it contains a vector of length equal to mpi_size, and + * that the vector contains (0, 1, 2, ... n-1). + */ + fapl_id = H5Pcreate(H5P_FILE_ACCESS); + VRFY((fapl_id >= 0), "creating fapl"); + + err = H5Pset_fapl_core(fapl_id, (size_t)(64 *1024), FALSE); + VRFY((err >= 0), "setting core file driver in fapl."); + + err = H5Pset_file_image(fapl_id, image_ptr, (size_t)image_len); + VRFY((err >= 0), "set file image in fapl."); + + file_id = H5Fopen(file_name, H5F_ACC_RDWR, fapl_id); + VRFY((file_id >= 0), "opened received file image file"); + + dset_id = H5Dopen2(file_id, "v", H5P_DEFAULT); + VRFY((dset_id >= 0), "opened data set"); + + dset_type_id = H5Dget_type(dset_id); + VRFY((dset_type_id >= 0), "obtained data set type"); + + tri_result = H5Tequal(dset_type_id, H5T_NATIVE_INT); + VRFY((tri_result == TRUE), "verified data set type"); + + space_id = H5Dget_space(dset_id); + VRFY((space_id >= 0), "opened data space"); + + space_ndims = H5Sget_simple_extent_ndims(space_id); + VRFY((space_ndims == 1), "verified data space num dims(1)"); + + space_ndims = H5Sget_simple_extent_dims(space_id, dims, NULL); + VRFY((space_ndims == 1), "verified data space num dims(2)"); + VRFY((dims[0] == (hsize_t)mpi_size), "verified data space dims"); + + vector_ptr = (int *)HDmalloc((size_t)(mpi_size) * sizeof(int)); + VRFY((vector_ptr != NULL), "allocated in memory rep of vector"); + + err = H5Dread(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void *)vector_ptr); + VRFY((err >= 0), "read received vector."); + + vector_ok = TRUE; + for(i = 0; i < mpi_size; i++) + if(vector_ptr[i] != i) + vector_ok = FALSE; + VRFY((vector_ok), "verified received vector."); + + /* 7) closes the core file and exit. */ + + err = H5Sclose(space_id); + VRFY((err >= 0), "closed data space."); + + err = H5Dclose(dset_id); + VRFY((err >= 0), "closed data set."); + + err = H5Fclose(file_id); + VRFY((err >= 0), "closed core file(1)."); + + err = H5Pclose(fapl_id); + VRFY((err >= 0), "closed fapl(1)."); + + HDfree(image_ptr); + image_ptr = NULL; + image_len = 0; + } else { + /* 1) Await receipt of file image from process (i - 1). */ + + mpi_result = MPI_Recv((void *)(&image_len), (int)sizeof(ssize_t), + MPI_BYTE, mpi_rank - 1, 0, MPI_COMM_WORLD, + &rcvstat); + VRFY((mpi_result == MPI_SUCCESS), \ + "received image size from process mpi_rank-1"); + + image_ptr = (void *)HDmalloc((size_t)image_len); + VRFY(image_ptr != NULL, "allocated file image receive buffer."); + + mpi_result = MPI_Recv((void *)image_ptr, (int)image_len, + MPI_BYTE, mpi_rank - 1, 0, MPI_COMM_WORLD, + &rcvstat); + VRFY((mpi_result == MPI_SUCCESS), \ + "received file image from process mpi_rank-1"); + + /* 2) Open the image with the core file driver, verify that it + * contains a vector v of length, and that v[j] = j for + * 0 <= j < i, and that v[j] == -1 for i <= j < n + */ + fapl_id = H5Pcreate(H5P_FILE_ACCESS); + VRFY((fapl_id >= 0), "creating fapl"); + + err = H5Pset_fapl_core(fapl_id, (size_t)(64 * 1024), FALSE); + VRFY((err >= 0), "setting core file driver in fapl."); + + err = H5Pset_file_image(fapl_id, image_ptr, (size_t)image_len); + VRFY((err >= 0), "set file image in fapl."); + + file_id = H5Fopen(file_name, H5F_ACC_RDWR, fapl_id); + H5Eprint2(H5P_DEFAULT, stderr); + VRFY((file_id >= 0), "opened received file image file"); + + dset_id = H5Dopen2(file_id, "v", H5P_DEFAULT); + VRFY((dset_id >= 0), "opened data set"); + + dset_type_id = H5Dget_type(dset_id); + VRFY((dset_type_id >= 0), "obtained data set type"); + + tri_result = H5Tequal(dset_type_id, H5T_NATIVE_INT); + VRFY((tri_result == TRUE), "verified data set type"); + + space_id = H5Dget_space(dset_id); + VRFY((space_id >= 0), "opened data space"); + + space_ndims = H5Sget_simple_extent_ndims(space_id); + VRFY((space_ndims == 1), "verified data space num dims(1)"); + + space_ndims = H5Sget_simple_extent_dims(space_id, dims, NULL); + VRFY((space_ndims == 1), "verified data space num dims(2)"); + VRFY((dims[0] == (hsize_t)mpi_size), "verified data space dims"); + + vector_ptr = (int *)HDmalloc((size_t)(mpi_size) * sizeof(int)); + VRFY((vector_ptr != NULL), "allocated in memory rep of vector"); + + err = H5Dread(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void *)vector_ptr); + VRFY((err >= 0), "read received vector."); + + vector_ok = TRUE; + for(i = 0; i < mpi_size; i++){ + if(i < mpi_rank) { + if(vector_ptr[i] != i) + vector_ok = FALSE; + } else { + if(vector_ptr[i] != -1) + vector_ok = FALSE; + } + } + VRFY((vector_ok), "verified received vector."); + + + /* 3) Set v[i] = i in the core file. */ + + vector_ptr[mpi_rank] = mpi_rank; + + err = H5Dwrite(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void *)vector_ptr); + VRFY((err >= 0), "wrote modified data to vector."); + + HDfree(vector_ptr); + vector_ptr = NULL; + + + /* 4) Flush the core file and send it to process (mpi_rank + 1) % n. */ + + err = H5Fflush(file_id, H5F_SCOPE_GLOBAL); + VRFY((err >= 0), "flushed core file."); + + image_len = H5Fget_file_image(file_id, NULL, (size_t)0); + VRFY((image_len > 0), "got (possibly modified) image file len"); + + image_ptr = (void *)HDrealloc((void *)image_ptr, (size_t)image_len); + VRFY(image_ptr != NULL, "re-allocated file image buffer."); + + bytes_read = H5Fget_file_image(file_id, image_ptr, (size_t)image_len); + VRFY(bytes_read == image_len, "wrote file into image buffer"); + + mpi_result = MPI_Ssend((void *)(&image_len), (int)sizeof(ssize_t), + MPI_BYTE, (mpi_rank + 1) % mpi_size, 0, + MPI_COMM_WORLD); + VRFY((mpi_result == MPI_SUCCESS), \ + "sent image size to process (mpi_rank + 1) % mpi_size"); + + mpi_result = MPI_Ssend((void *)image_ptr, (int)image_len, + MPI_BYTE, (mpi_rank + 1) % mpi_size, 0, + MPI_COMM_WORLD); + VRFY((mpi_result == MPI_SUCCESS), \ + "sent image to process (mpi_rank + 1) % mpi_size"); + + HDfree(image_ptr); + image_ptr = NULL; + image_len = 0; + + /* 5) close the core file and exit. */ + + err = H5Sclose(space_id); + VRFY((err >= 0), "closed data space."); + + err = H5Dclose(dset_id); + VRFY((err >= 0), "closed data set."); + + err = H5Fclose(file_id); + VRFY((err >= 0), "closed core file(1)."); + + err = H5Pclose(fapl_id); + VRFY((err >= 0), "closed fapl(1)."); + } + + return; + +} /* file_image_daisy_chain_test() */ + diff --git a/testpar/testphdf5.c b/testpar/testphdf5.c index e3c72ef..3a86642 100644 --- a/testpar/testphdf5.c +++ b/testpar/testphdf5.c @@ -502,6 +502,13 @@ int main(int argc, char **argv) "test actual io mode proprerty", PARATESTFILE); + if((mpi_size < 2) && MAINPROCESS) { + printf("File Image Ops daisy chain test needs at least 2 processes.\n"); + printf("File Image Ops daisy chain test will be skipped \n"); + } + AddTest((mpi_size < 2)? "-fiodc" : "fiodc", file_image_daisy_chain_test, NULL, + "file image ops daisy chain", NULL); + /* Display testing information */ TestInfo(argv[0]); @@ -512,6 +519,18 @@ int main(int argc, char **argv) /* Parse command line arguments */ TestParseCmdLine(argc, argv); + if((mpi_size < 2)&& MAINPROCESS ) { + printf("Atomicity tests need at least 2 processes to participate\n"); + printf("8 is more recommended.. Atomicity tests will be skipped \n"); + } + else if (facc_type != FACC_MPIO && MAINPROCESS) { + printf("Atomicity tests will not work with a non MPIO VFD\n"); + } + else if(mpi_size >= 2 && facc_type == FACC_MPIO){ + AddTest("atomicity", dataset_atomicity, NULL, + "dataset atomic updates", PARATESTFILE); + } + if (facc_type == FACC_MPIPOSIX && MAINPROCESS){ printf("===================================\n" " Using MPIPOSIX driver\n" diff --git a/testpar/testphdf5.h b/testpar/testphdf5.h index 11656f9..da11c62 100644 --- a/testpar/testphdf5.h +++ b/testpar/testphdf5.h @@ -43,6 +43,8 @@ enum H5TEST_COLL_CHUNK_API {API_NONE=0,API_LINK_HARD, #define DATASETNAME2 "Data2" #define DATASETNAME3 "Data3" #define DATASETNAME4 "Data4" +#define DATASETNAME5 "Data5" +#define DATASETNAME6 "Data6" /* Hyperslab layout styles */ #define BYROW 1 /* divide into slabs of rows */ @@ -225,6 +227,7 @@ void independent_group_read(void); void test_fapl_mpio_dup(void); void test_fapl_mpiposix_dup(void); void test_split_comm_access(void); +void dataset_atomicity(void); void dataset_writeInd(void); void dataset_writeAll(void); void extend_writeInd(void); @@ -266,6 +269,7 @@ void lower_dim_size_comp_test(void); void link_chunk_collective_io_test(void); void contig_hyperslab_dr_pio_test(ShapeSameTestMethods sstest_type); void checker_board_hyperslab_dr_pio_test(ShapeSameTestMethods sstest_type); +void file_image_daisy_chain_test(void); #ifdef H5_HAVE_FILTER_DEFLATE void compress_readAll(void); #endif /* H5_HAVE_FILTER_DEFLATE */ diff --git a/tools/COPYING b/tools/COPYING old mode 100755 new mode 100644 diff --git a/tools/h5diff/CMakeLists.txt b/tools/h5diff/CMakeLists.txt index f178f19..da2aaf9 100644 --- a/tools/h5diff/CMakeLists.txt +++ b/tools/h5diff/CMakeLists.txt @@ -84,6 +84,8 @@ IF (BUILD_TESTING) h5diff_220.txt h5diff_221.txt h5diff_222.txt + h5diff_223.txt + h5diff_224.txt h5diff_21.txt h5diff_22.txt h5diff_23.txt @@ -139,6 +141,9 @@ IF (BUILD_TESTING) h5diff_482.txt h5diff_483.txt h5diff_484.txt + h5diff_485.txt + h5diff_486.txt + h5diff_487.txt h5diff_50.txt h5diff_51.txt h5diff_52.txt @@ -253,6 +258,8 @@ IF (BUILD_TESTING) h5diff_exclude1-2.h5 h5diff_exclude2-1.h5 h5diff_exclude2-2.h5 + h5diff_exclude3-1.h5 + h5diff_exclude3-2.h5 h5diff_comp_vl_strs.h5 h5diff_attr_v_level1.h5 h5diff_attr_v_level2.h5 @@ -490,6 +497,9 @@ IF (BUILD_TESTING) # different structure and obj names SET (EXCLUDE_FILE2_1 h5diff_exclude2-1.h5) SET (EXCLUDE_FILE2_2 h5diff_exclude2-2.h5) + # Only one file contains unique objs. Common objs are same. + SET (EXCLUDE_FILE3_1 h5diff_exclude3-1.h5) + SET (EXCLUDE_FILE3_2 h5diff_exclude3-2.h5) # compound type with multiple vlen string types SET (COMP_VL_STRS_FILE h5diff_comp_vl_strs.h5) # container types (array,vlen) with multiple nested compound types @@ -569,6 +579,10 @@ IF (BUILD_TESTING) h5diff_221.out.err h5diff_222.out h5diff_222.out.err + h5diff_223.out + h5diff_223.out.err + h5diff_224.out + h5diff_224.out.err h5diff_21.out h5diff_21.out.err h5diff_22.out @@ -1156,6 +1170,12 @@ ADD_H5_TEST (h5diff_221 1 -c non_comparables1.h5 non_comparables2.h5 /g2) # All the rest comparables should display differences ADD_H5_TEST (h5diff_222 1 -c non_comparables1.h5 non_comparables2.h5) +# non-comparable test for common objects (same name) with different object types +# (HDFFV-7644) +ADD_H5_TEST (h5diff_223 0 -c non_comparables1.h5 non_comparables2.h5 /diffobjtypes) +# swap files +ADD_H5_TEST (h5diff_224 0 -c non_comparables2.h5 non_comparables1.h5 /diffobjtypes) + # ############################################################################## # # Links compare without --follow-symlinks nor --no-dangling-links # ############################################################################## @@ -1359,6 +1379,16 @@ ADD_H5_TEST (h5diff_483 1 -v --exclude-path "/group1" ${EXCLUDE_FILE2_1} ${EXCLU # Exclude from group compare ADD_H5_TEST (h5diff_484 0 -v --exclude-path "/dset3" ${EXCLUDE_FILE1_1} ${EXCLUDE_FILE1_2} /group1) +# +# Only one file contains unique objs. Common objs are same. +# (HDFFV-7837) +# +ADD_H5_TEST (h5diff_485 0 -v --exclude-path "/group1" h5diff_exclude3-1.h5 h5diff_exclude3-2.h5) +ADD_H5_TEST (h5diff_486 0 -v --exclude-path "/group1" h5diff_exclude3-2.h5 h5diff_exclude3-1.h5) +ADD_H5_TEST (h5diff_487 1 -v --exclude-path "/group1/dset" h5diff_exclude3-1.h5 h5diff_exclude3-2.h5) + + + # ############################################################################## # # diff various multiple vlen and fixed strings in a compound type dataset # ############################################################################## diff --git a/tools/h5diff/h5diffgentest.c b/tools/h5diff/h5diffgentest.c index 0b5d68f..eb4931d 100644 --- a/tools/h5diff/h5diffgentest.c +++ b/tools/h5diff/h5diffgentest.c @@ -79,6 +79,9 @@ hsize_t H5TOOLS_MALLOCSIZE = (128 * 1024 * 1024); /* different structure and obj names */ #define EXCLUDE_FILE2_1 "h5diff_exclude2-1.h5" #define EXCLUDE_FILE2_2 "h5diff_exclude2-2.h5" +/* only one file has unique objs */ +#define EXCLUDE_FILE3_1 "h5diff_exclude3-1.h5" +#define EXCLUDE_FILE3_2 "h5diff_exclude3-2.h5" /* compound type with multiple vlen string types */ #define COMP_VL_STRS_FILE "h5diff_comp_vl_strs.h5" /* attribute compre with verbose level */ @@ -146,6 +149,7 @@ static int test_group_recurse(const char *fname1, const char *fname2); static int test_group_recurse2(void); static int test_exclude_obj1(const char *fname1, const char *fname2); static int test_exclude_obj2(const char *fname1, const char *fname2); +static int test_exclude_obj3(const char *fname1, const char *fname2); static int test_comp_vlen_strings(const char *fname1, const char *grp_name, int is_file_new); static int test_attributes_verbose_level(const char *fname1, const char *fname2); static int test_enums(const char *fname); @@ -153,7 +157,8 @@ static void test_comps_array (const char *fname, const char *dset, const char *a static void test_comps_vlen (const char *fname, const char *dset,const char *attr, int diff, int is_file_new); static void test_comps_array_vlen (const char *fname, const char *dset, const char *attr, int diff, int is_file_new); static void test_comps_vlen_arry (const char *fname, const char *dset,const char *attr, int diff, int is_file_new); -static void test_non_comparables (const char *fname, int diff); +static void test_data_nocomparables (const char *fname, int diff); +static void test_objs_nocomparables (const char *fname1, const char *fname2); /* called by test_attributes() and test_datasets() */ static void write_attr_in(hid_t loc_id,const char* dset_name,hid_t fid,int make_diffs); @@ -225,6 +230,7 @@ int main(void) test_exclude_obj1(EXCLUDE_FILE1_1, EXCLUDE_FILE1_2); test_exclude_obj2(EXCLUDE_FILE2_1, EXCLUDE_FILE2_2); + test_exclude_obj3(EXCLUDE_FILE3_1, EXCLUDE_FILE3_2); /* diff various multiple vlen and fixlen string types in a compound dataset */ test_comp_vlen_strings(COMP_VL_STRS_FILE, "group", 1); @@ -257,8 +263,11 @@ int main(void) * comparable datasets and attributes. All the comparables should display * differences. */ - test_non_comparables(NON_COMPARBLES1,0); - test_non_comparables(NON_COMPARBLES2,5); + test_data_nocomparables(NON_COMPARBLES1,0); + test_data_nocomparables(NON_COMPARBLES2,5); + + /* common objects (same name) with different object types. HDFFV-7644 */ + test_objs_nocomparables(NON_COMPARBLES1, NON_COMPARBLES2); return 0; } @@ -3445,6 +3454,100 @@ out: /*------------------------------------------------------------------------- * +* Purpose: Create test files for excluding obj. +* Only one file contains unique objs. Common objs are same. +* Test : exclude unique objs to verify the rest are same +* - HDFFV-7837 +* +* Programmer: Jonathan Kim (Mar, 19, 2012) +* +*-------------------------------------------------------------------------*/ +static int test_exclude_obj3(const char *fname1, const char *fname2) +{ + hid_t fid1=0; + hid_t fid2=0; + hid_t gid1=0; + hsize_t dims2[2] = {2,4}; + int data1[4][2] = {{0,0},{0,0},{0,0},{0,0}}; + herr_t status = SUCCEED; + + /*----------------------------------------------------------------------- + * Create file(s) + *------------------------------------------------------------------------*/ + fid1 = H5Fcreate (fname1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + if (fid1 < 0) + { + fprintf(stderr, "Error: %s> H5Fcreate failed.\n", fname1); + status = FAIL; + goto out; + } + + fid2 = H5Fcreate (fname2, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + if (fid2 < 0) + { + fprintf(stderr, "Error: %s> H5Fcreate failed.\n", fname2); + status = FAIL; + goto out; + } + + + /*----------------------------------------------------------------------- + * Group + *------------------------------------------------------------------------*/ + /* file1 */ + gid1 = H5Gcreate2(fid1, "group1", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + if (gid1 < 0) + { + fprintf(stderr, "Error: %s> H5Gcreate2 failed.\n", fname1); + status = FAIL; + goto out; + } + + /*----------------------------------------------------------------------- + * Datasets + *------------------------------------------------------------------------*/ + /* file1 */ + status = write_dset(fid1,2,dims2,"dset1",H5T_NATIVE_INT,data1); + if (status == FAIL) + { + fprintf(stderr, "Error: %s> write_dset failed\n", fname1); + status = FAIL; + goto out; + } + + status = write_dset(gid1,2,dims2,"dset",H5T_NATIVE_INT,data1); + if (status == FAIL) + { + fprintf(stderr, "Error: %s> write_dset failed\n", fname1); + status = FAIL; + goto out; + } + + /* file2 */ + status = write_dset(fid2,2,dims2,"dset1",H5T_NATIVE_INT,data1); + if (status == FAIL) + { + fprintf(stderr, "Error: %s> write_dset failed\n", fname2); + status = FAIL; + goto out; + } + +out: + /*----------------------------------------------------------------------- + * Close + *-----------------------------------------------------------------------*/ + if(fid1) + H5Fclose(fid1); + if(fid2) + H5Fclose(fid2); + if(gid1) + H5Gclose(gid1); + + return status; +} + +/*------------------------------------------------------------------------- +* * Purpose: Create test files for multiple variable length string/string array * along with fixed length string/string array types in * a compound type dataset. @@ -4789,7 +4892,7 @@ static void test_comps_vlen_arry (const char * fname, const char *dset, const ch /*------------------------------------------------------------------------- -* Function: test_non_comparables +* Function: test_data_nocomparables * * Purpose: * Create test files with non-comparable dataset and attributes with @@ -4798,7 +4901,7 @@ static void test_comps_vlen_arry (const char * fname, const char *dset, const ch * *-------------------------------------------------------------------------*/ #define DIM_ARRY 3 -static void test_non_comparables (const char * fname, int make_diffs) +static void test_data_nocomparables (const char * fname, int make_diffs) { hid_t fid=0; hid_t gid1=0; @@ -4818,7 +4921,6 @@ static void test_non_comparables (const char * fname, int make_diffs) int rank_attr; char data1_str[DIM_ARRY][STR_SIZE]= {"ab","cd","ef"}; herr_t status = SUCCEED; - int i; void *dset_data_ptr1=NULL; void *dset_data_ptr2=NULL; void *dset_data_ptr3=NULL; @@ -5001,6 +5103,155 @@ out: } /*------------------------------------------------------------------------- +* Function: test_objs_nocomparables +* +* Purpose: +* Create test files with common objects (same name) but different object +* types. +* h5diff should show non-comparable output from these common objects. +*-------------------------------------------------------------------------*/ +static void test_objs_nocomparables(const char *fname1, const char *fname2) +{ + herr_t status = SUCCEED; + hid_t fid1=0; + hid_t fid2=0; + hid_t topgid1=0; + hid_t topgid2=0; + hid_t gid1=0; + hid_t did1=0; + hid_t tid1=0; + hid_t gid2=0; + hid_t did2=0; + hid_t tid2=0; + hsize_t dims[1] = {DIM_ARRY}; + int data1[DIM_ARRY] = {1,1,1}; + int data2[DIM_ARRY] = {2,2,2}; + + /*----------------------------------------------------------------------- + * Open file(s) to add objects + *------------------------------------------------------------------------*/ + /* file1 */ + fid1 = H5Fopen (fname1, H5F_ACC_RDWR, H5P_DEFAULT); + if (fid1 < 0) + { + fprintf(stderr, "Error: %s> H5Fopen failed.\n", fname1); + status = FAIL; + goto out; + } + + /* file2 */ + fid2 = H5Fopen (fname2, H5F_ACC_RDWR, H5P_DEFAULT); + if (fid2 < 0) + { + fprintf(stderr, "Error: %s> H5Fopen failed.\n", fname2); + status = FAIL; + goto out; + } + + /*----------------------------------------------------------------------- + * in file1 : add member objects + *------------------------------------------------------------------------*/ + /* parent group */ + topgid1 = H5Gcreate2(fid1, "diffobjtypes", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + if (topgid1 < 0) + { + fprintf(stderr, "Error: %s> H5Gcreate2 failed.\n", fname1); + status = FAIL; + goto out; + } + + /* dataset */ + status = write_dset(topgid1, 1, dims,"obj1", H5T_NATIVE_INT, data1); + if (status == FAIL) + { + fprintf(stderr, "Error: %s> write_dset failed\n", fname1); + goto out; + } + + /* group */ + gid1 = H5Gcreate2(topgid1, "obj2", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + if (gid1 < 0) + { + fprintf(stderr, "Error: %s> H5Gcreate2 failed.\n", fname1); + status = FAIL; + goto out; + } + + /* committed type */ + tid1 = H5Tcopy(H5T_NATIVE_INT); + status = H5Tcommit2(topgid1, "obj3", tid1, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + if (status < 0) + { + fprintf(stderr, "Error: %s> H5Tcommit2 failed.\n", fname1); + goto out; + } + + /*----------------------------------------------------------------------- + * in file2 : add member objects + *------------------------------------------------------------------------*/ + /* parent group */ + topgid2 = H5Gcreate2(fid2, "diffobjtypes", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + if (topgid2 < 0) + { + fprintf(stderr, "Error: %s> H5Gcreate2 failed.\n", fname2); + status = FAIL; + goto out; + } + + /* group */ + gid2 = H5Gcreate2(topgid2, "obj1", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + if (gid2 < 0) + { + fprintf(stderr, "Error: %s> H5Gcreate2 failed.\n", fname2); + status = FAIL; + goto out; + } + + /* committed type */ + tid2 = H5Tcopy(H5T_NATIVE_INT); + status = H5Tcommit2(topgid2, "obj2", tid2, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + if (status < 0) + { + fprintf(stderr, "Error: %s> H5Tcommit2 failed.\n", fname2); + goto out; + } + + /* dataset */ + status = write_dset(topgid2, 1, dims,"obj3", H5T_NATIVE_INT, data2); + if (status == FAIL) + { + fprintf(stderr, "Error: %s> write_dset failed\n", fname2); + goto out; + } + +out: + /*----------------------------------------------------------------------- + * Close IDs + *-----------------------------------------------------------------------*/ + if(fid1) + H5Fclose(fid1); + if(fid2) + H5Fclose(fid2); + if(topgid1) + H5Gclose(topgid1); + if(topgid2) + H5Gclose(topgid2); + if(did1) + H5Dclose(did1); + if(did2) + H5Dclose(did2); + if(gid1) + H5Gclose(gid1); + if(gid2) + H5Gclose(gid2); + if(tid1) + H5Tclose(tid1); + if(tid2) + H5Tclose(tid2); + +} + +/*------------------------------------------------------------------------- * Function: write_attr_in * * Purpose: write attributes in LOC_ID (dataset, group, named datatype) diff --git a/tools/h5diff/testfiles/h5diff_101w.txt b/tools/h5diff/testfiles/h5diff_101w.txt old mode 100755 new mode 100644 diff --git a/tools/h5diff/testfiles/h5diff_102w.txt b/tools/h5diff/testfiles/h5diff_102w.txt old mode 100755 new mode 100644 diff --git a/tools/h5diff/testfiles/h5diff_20.txt b/tools/h5diff/testfiles/h5diff_20.txt index 3edb543..09c20cb 100644 --- a/tools/h5diff/testfiles/h5diff_20.txt +++ b/tools/h5diff/testfiles/h5diff_20.txt @@ -1,4 +1,4 @@ - is of type H5G_DATASET and is of type H5G_GROUP +Not comparable: is of type H5G_DATASET and is of type H5G_GROUP -------------------------------- Some objects are not comparable -------------------------------- diff --git a/tools/h5diff/testfiles/h5diff_21.txt b/tools/h5diff/testfiles/h5diff_21.txt index 1479457..1c625fe 100644 --- a/tools/h5diff/testfiles/h5diff_21.txt +++ b/tools/h5diff/testfiles/h5diff_21.txt @@ -1,4 +1,4 @@ - is of type H5G_DATASET and is of type H5G_LINK +Not comparable: is of type H5G_DATASET and is of type H5G_LINK -------------------------------- Some objects are not comparable -------------------------------- diff --git a/tools/h5diff/testfiles/h5diff_22.txt b/tools/h5diff/testfiles/h5diff_22.txt index 3ccb06b..2ef22d0 100644 --- a/tools/h5diff/testfiles/h5diff_22.txt +++ b/tools/h5diff/testfiles/h5diff_22.txt @@ -1,4 +1,4 @@ - is of type H5G_DATASET and is of type H5G_TYPE +Not comparable: is of type H5G_DATASET and is of type H5G_TYPE -------------------------------- Some objects are not comparable -------------------------------- diff --git a/tools/h5diff/testfiles/h5diff_222.txt b/tools/h5diff/testfiles/h5diff_222.txt index bdecb8a..53c9464 100644 --- a/tools/h5diff/testfiles/h5diff_222.txt +++ b/tools/h5diff/testfiles/h5diff_222.txt @@ -1,3 +1,6 @@ +Not comparable: is of type H5G_DATASET and is of type H5G_GROUP +Not comparable: is of type H5G_GROUP and is of type H5G_TYPE +Not comparable: is of type H5G_TYPE and is of type H5G_DATASET Not comparable: is of class H5T_INTEGER and is of class H5T_STRING attribute: > and > 3 differences found diff --git a/tools/h5diff/testfiles/h5diff_223.txt b/tools/h5diff/testfiles/h5diff_223.txt new file mode 100644 index 0000000..c8e0f65 --- /dev/null +++ b/tools/h5diff/testfiles/h5diff_223.txt @@ -0,0 +1,4 @@ +Not comparable: is of type H5G_DATASET and is of type H5G_GROUP +Not comparable: is of type H5G_GROUP and is of type H5G_TYPE +Not comparable: is of type H5G_TYPE and is of type H5G_DATASET +EXIT CODE: 0 diff --git a/tools/h5diff/testfiles/h5diff_224.txt b/tools/h5diff/testfiles/h5diff_224.txt new file mode 100644 index 0000000..a4ebedb --- /dev/null +++ b/tools/h5diff/testfiles/h5diff_224.txt @@ -0,0 +1,4 @@ +Not comparable: is of type H5G_GROUP and is of type H5G_DATASET +Not comparable: is of type H5G_TYPE and is of type H5G_GROUP +Not comparable: is of type H5G_DATASET and is of type H5G_TYPE +EXIT CODE: 0 diff --git a/tools/h5diff/testfiles/h5diff_300.txt b/tools/h5diff/testfiles/h5diff_300.txt old mode 100755 new mode 100644 diff --git a/tools/h5diff/testfiles/h5diff_485.txt b/tools/h5diff/testfiles/h5diff_485.txt new file mode 100644 index 0000000..4175809 --- /dev/null +++ b/tools/h5diff/testfiles/h5diff_485.txt @@ -0,0 +1,11 @@ + +file1 file2 +--------------------------------------- + x x / + x x /dset1 + +group : and +0 differences found +dataset: and +0 differences found +EXIT CODE: 0 diff --git a/tools/h5diff/testfiles/h5diff_486.txt b/tools/h5diff/testfiles/h5diff_486.txt new file mode 100644 index 0000000..4175809 --- /dev/null +++ b/tools/h5diff/testfiles/h5diff_486.txt @@ -0,0 +1,11 @@ + +file1 file2 +--------------------------------------- + x x / + x x /dset1 + +group : and +0 differences found +dataset: and +0 differences found +EXIT CODE: 0 diff --git a/tools/h5diff/testfiles/h5diff_487.txt b/tools/h5diff/testfiles/h5diff_487.txt new file mode 100644 index 0000000..8555a71 --- /dev/null +++ b/tools/h5diff/testfiles/h5diff_487.txt @@ -0,0 +1,12 @@ + +file1 file2 +--------------------------------------- + x x / + x x /dset1 + x /group1 + +group : and +0 differences found +dataset: and +0 differences found +EXIT CODE: 1 diff --git a/tools/h5diff/testfiles/h5diff_505.txt b/tools/h5diff/testfiles/h5diff_505.txt index a220730..607b99b 100644 --- a/tools/h5diff/testfiles/h5diff_505.txt +++ b/tools/h5diff/testfiles/h5diff_505.txt @@ -1,4 +1,4 @@ - is of type H5G_GROUP and is of type H5G_LINK +Not comparable: is of type H5G_GROUP and is of type H5G_LINK -------------------------------- Some objects are not comparable -------------------------------- diff --git a/tools/h5diff/testfiles/h5diff_507.txt b/tools/h5diff/testfiles/h5diff_507.txt index 6176f3f..06b7fe6 100644 --- a/tools/h5diff/testfiles/h5diff_507.txt +++ b/tools/h5diff/testfiles/h5diff_507.txt @@ -1,4 +1,4 @@ - is of type H5G_GROUP and is of type H5G_UDLINK +Not comparable: is of type H5G_GROUP and is of type H5G_UDLINK -------------------------------- Some objects are not comparable -------------------------------- diff --git a/tools/h5diff/testfiles/h5diff_509.txt b/tools/h5diff/testfiles/h5diff_509.txt index a51ab35..2e3e87a 100644 --- a/tools/h5diff/testfiles/h5diff_509.txt +++ b/tools/h5diff/testfiles/h5diff_509.txt @@ -1,4 +1,4 @@ - is of type H5G_LINK and is of type H5G_UDLINK +Not comparable: is of type H5G_LINK and is of type H5G_UDLINK -------------------------------- Some objects are not comparable -------------------------------- diff --git a/tools/h5diff/testfiles/h5diff_515.txt b/tools/h5diff/testfiles/h5diff_515.txt index 077d463..263441d 100644 --- a/tools/h5diff/testfiles/h5diff_515.txt +++ b/tools/h5diff/testfiles/h5diff_515.txt @@ -17,8 +17,11 @@ dataset: and 0 differences found group : and 0 differences found -group : and -0 differences found +Not comparable: is of type H5G_GROUP and is of type H5G_UDLINK link : and 0 differences found +-------------------------------- +Some objects are not comparable +-------------------------------- +Use -c for a list of objects without details of differences. EXIT CODE: 1 diff --git a/tools/h5diff/testfiles/h5diff_517.txt b/tools/h5diff/testfiles/h5diff_517.txt index 1b6e24f..91c69fb 100644 --- a/tools/h5diff/testfiles/h5diff_517.txt +++ b/tools/h5diff/testfiles/h5diff_517.txt @@ -10,6 +10,9 @@ group1 group2 group : and 0 differences found -group : and -0 differences found +Not comparable: is of type H5G_GROUP and is of type H5G_UDLINK +-------------------------------- +Some objects are not comparable +-------------------------------- +Use -c for a list of objects without details of differences. EXIT CODE: 1 diff --git a/tools/h5diff/testfiles/h5diff_enum_invalid_values.h5 b/tools/h5diff/testfiles/h5diff_enum_invalid_values.h5 old mode 100755 new mode 100644 diff --git a/tools/h5diff/testfiles/h5diff_exclude3-1.h5 b/tools/h5diff/testfiles/h5diff_exclude3-1.h5 new file mode 100644 index 0000000..f9cc83d Binary files /dev/null and b/tools/h5diff/testfiles/h5diff_exclude3-1.h5 differ diff --git a/tools/h5diff/testfiles/h5diff_exclude3-2.h5 b/tools/h5diff/testfiles/h5diff_exclude3-2.h5 new file mode 100644 index 0000000..f811905 Binary files /dev/null and b/tools/h5diff/testfiles/h5diff_exclude3-2.h5 differ diff --git a/tools/h5diff/testfiles/h5diff_links.h5 b/tools/h5diff/testfiles/h5diff_links.h5 old mode 100755 new mode 100644 diff --git a/tools/h5diff/testfiles/non_comparables1.h5 b/tools/h5diff/testfiles/non_comparables1.h5 index 71b65c8..7dbb45d 100644 Binary files a/tools/h5diff/testfiles/non_comparables1.h5 and b/tools/h5diff/testfiles/non_comparables1.h5 differ diff --git a/tools/h5diff/testfiles/non_comparables2.h5 b/tools/h5diff/testfiles/non_comparables2.h5 index 188ceb9..a5e7014 100644 Binary files a/tools/h5diff/testfiles/non_comparables2.h5 and b/tools/h5diff/testfiles/non_comparables2.h5 differ diff --git a/tools/h5diff/testh5diff.sh b/tools/h5diff/testh5diff.sh index 005510f..c84c2b6 100755 --- a/tools/h5diff/testh5diff.sh +++ b/tools/h5diff/testh5diff.sh @@ -113,6 +113,8 @@ $SRC_H5DIFF_TESTFILES/h5diff_exclude1-1.h5 $SRC_H5DIFF_TESTFILES/h5diff_exclude1-2.h5 $SRC_H5DIFF_TESTFILES/h5diff_exclude2-1.h5 $SRC_H5DIFF_TESTFILES/h5diff_exclude2-2.h5 +$SRC_H5DIFF_TESTFILES/h5diff_exclude3-1.h5 +$SRC_H5DIFF_TESTFILES/h5diff_exclude3-2.h5 $SRC_H5DIFF_TESTFILES/h5diff_comp_vl_strs.h5 $SRC_H5DIFF_TESTFILES/compounds_array_vlen1.h5 $SRC_H5DIFF_TESTFILES/compounds_array_vlen2.h5 @@ -156,6 +158,8 @@ $SRC_H5DIFF_TESTFILES/h5diff_208.txt $SRC_H5DIFF_TESTFILES/h5diff_220.txt $SRC_H5DIFF_TESTFILES/h5diff_221.txt $SRC_H5DIFF_TESTFILES/h5diff_222.txt +$SRC_H5DIFF_TESTFILES/h5diff_223.txt +$SRC_H5DIFF_TESTFILES/h5diff_224.txt $SRC_H5DIFF_TESTFILES/h5diff_21.txt $SRC_H5DIFF_TESTFILES/h5diff_22.txt $SRC_H5DIFF_TESTFILES/h5diff_23.txt @@ -212,6 +216,9 @@ $SRC_H5DIFF_TESTFILES/h5diff_481.txt $SRC_H5DIFF_TESTFILES/h5diff_482.txt $SRC_H5DIFF_TESTFILES/h5diff_483.txt $SRC_H5DIFF_TESTFILES/h5diff_484.txt +$SRC_H5DIFF_TESTFILES/h5diff_485.txt +$SRC_H5DIFF_TESTFILES/h5diff_486.txt +$SRC_H5DIFF_TESTFILES/h5diff_487.txt $SRC_H5DIFF_TESTFILES/h5diff_50.txt $SRC_H5DIFF_TESTFILES/h5diff_51.txt $SRC_H5DIFF_TESTFILES/h5diff_52.txt @@ -824,6 +831,12 @@ if test -n "$pmode" -a "$mydomainname" = hdfgroup.uiuc.edu; then else TOOLTEST h5diff_222.txt -c non_comparables1.h5 non_comparables2.h5 fi + +# non-comparable test for common objects (same name) with different object types +# (HDFFV-7644) +TOOLTEST h5diff_223.txt -c non_comparables1.h5 non_comparables2.h5 /diffobjtypes +# swap files +TOOLTEST h5diff_224.txt -c non_comparables2.h5 non_comparables1.h5 /diffobjtypes # ############################################################################## # # Links compare without --follow-symlinks nor --no-dangling-links @@ -1035,6 +1048,15 @@ TOOLTEST h5diff_483.txt -v --exclude-path "/group1" h5diff_exclude2-1.h5 h5diff_ # Exclude from group compare TOOLTEST h5diff_484.txt -v --exclude-path "/dset3" h5diff_exclude1-1.h5 h5diff_exclude1-2.h5 /group1 +# +# Only one file contains unique objs. Common objs are same. +# (HDFFV-7837) +# +TOOLTEST h5diff_485.txt -v --exclude-path "/group1" h5diff_exclude3-1.h5 h5diff_exclude3-2.h5 +TOOLTEST h5diff_486.txt -v --exclude-path "/group1" h5diff_exclude3-2.h5 h5diff_exclude3-1.h5 +TOOLTEST h5diff_487.txt -v --exclude-path "/group1/dset" h5diff_exclude3-1.h5 h5diff_exclude3-2.h5 + + # ############################################################################## # # diff various multiple vlen and fixed strings in a compound type dataset # ############################################################################## diff --git a/tools/h5dump/h5dump.c b/tools/h5dump/h5dump.c index 650846a..2799d95 100644 --- a/tools/h5dump/h5dump.c +++ b/tools/h5dump/h5dump.c @@ -243,6 +243,9 @@ usage(const char *prog) HDfprintf(rawoutstream, " -e, --escape Escape non printing characters\n"); HDfprintf(rawoutstream, " -V, --version Print version number and exit\n"); HDfprintf(rawoutstream, " -a P, --attribute=P Print the specified attribute\n"); + HDfprintf(rawoutstream, " If an attribute name contains a slash (/), escape the\n"); + HDfprintf(rawoutstream, " slash with a preceding backslash (\\).\n"); + HDfprintf(rawoutstream, " (See example section below.)\n"); HDfprintf(rawoutstream, " -d P, --dataset=P Print the specified dataset\n"); HDfprintf(rawoutstream, " -y, --noindex Do not print array indices with the data\n"); HDfprintf(rawoutstream, " -p, --properties Print dataset filters, storage layout and fill value\n"); @@ -316,6 +319,10 @@ usage(const char *prog) HDfprintf(rawoutstream, "\n"); HDfprintf(rawoutstream, " h5dump -a /bar_none/foo quux.h5\n"); HDfprintf(rawoutstream, "\n"); + HDfprintf(rawoutstream, " Attribute \"high/low\" of the group /bar_none in the file quux.h5\n"); + HDfprintf(rawoutstream, "\n"); + HDfprintf(rawoutstream, " h5dump -a \"/bar_none/high\\/low\" quux.h5\n"); + HDfprintf(rawoutstream, "\n"); HDfprintf(rawoutstream, " 2) Selecting a subset from dataset /foo in file quux.h5\n"); HDfprintf(rawoutstream, "\n"); HDfprintf(rawoutstream, " h5dump -d /foo -s \"0,1\" -S \"1,1\" -c \"2,3\" -k \"2,2\" quux.h5\n"); diff --git a/tools/h5dump/h5dumpgentest.c b/tools/h5dump/h5dumpgentest.c index e3c072d..4114a94 100644 --- a/tools/h5dump/h5dumpgentest.c +++ b/tools/h5dump/h5dumpgentest.c @@ -437,7 +437,7 @@ gent_attribute(void) /* attribute 1 */ dims[0] = 24; space = H5Screate_simple(1, dims, NULL); - attr = H5Acreate2(root, "attr1", H5T_STD_I8BE, space, H5P_DEFAULT, H5P_DEFAULT); + attr = H5Acreate2(root, "/attr1", H5T_STD_I8BE, space, H5P_DEFAULT, H5P_DEFAULT); sprintf(buf, "attribute of root group"); H5Awrite(attr, H5T_NATIVE_SCHAR, buf); H5Sclose(space); diff --git a/tools/h5dump/testh5dump.sh.in b/tools/h5dump/testh5dump.sh.in index 771b5d5..4db9d5b 100644 --- a/tools/h5dump/testh5dump.sh.in +++ b/tools/h5dump/testh5dump.sh.in @@ -799,9 +799,9 @@ TOOLTEST tarray7.ddl --enable-error-stack tarray7.h5 TOOLTEST tarray8.ddl --enable-error-stack tarray8.h5 # test for wildcards in filename (does not work with cmake) -TOOLTEST3 tstarfile --enable-error-stack -H -d Dataset1 tarr*.h5 -TOOLTEST3 tqmarkfile --enable-error-stack -H -d Dataset1 tarray?.h5 -TOOLTEST tmultifile --enable-error-stack -H -d Dataset1 tarray2.h5 tarray3.h5 tarray4.h5 tarray5.h5 tarray6.h5 tarray7.h5 +# inconsistent across platforms TOOLTEST3 tstarfile.ddl --enable-error-stack -H -d Dataset1 tarr*.h5 +TOOLTEST3 tqmarkfile.ddl --enable-error-stack -H -d Dataset1 tarray?.h5 +TOOLTEST tmultifile.ddl --enable-error-stack -H -d Dataset1 tarray2.h5 tarray3.h5 tarray4.h5 tarray5.h5 tarray6.h5 tarray7.h5 # test for files with empty data TOOLTEST tempty.ddl --enable-error-stack tempty.h5 diff --git a/tools/h5dump/testh5dumpxml.sh.in b/tools/h5dump/testh5dumpxml.sh.in old mode 100755 new mode 100644 diff --git a/tools/h5import/Makefile.in b/tools/h5import/Makefile.in old mode 100755 new mode 100644 diff --git a/tools/h5import/h5import.c b/tools/h5import/h5import.c old mode 100755 new mode 100644 diff --git a/tools/h5import/h5import.h b/tools/h5import/h5import.h old mode 100755 new mode 100644 diff --git a/tools/h5import/h5importtest.c b/tools/h5import/h5importtest.c old mode 100755 new mode 100644 diff --git a/tools/h5import/testfiles/binfp64.conf b/tools/h5import/testfiles/binfp64.conf old mode 100755 new mode 100644 diff --git a/tools/h5import/testfiles/binin16.conf b/tools/h5import/testfiles/binin16.conf old mode 100755 new mode 100644 diff --git a/tools/h5import/testfiles/binin32.conf b/tools/h5import/testfiles/binin32.conf old mode 100755 new mode 100644 diff --git a/tools/h5import/testfiles/binin8.conf b/tools/h5import/testfiles/binin8.conf old mode 100755 new mode 100644 diff --git a/tools/h5import/testfiles/binuin16.conf b/tools/h5import/testfiles/binuin16.conf old mode 100755 new mode 100644 diff --git a/tools/h5import/testfiles/binuin32.conf b/tools/h5import/testfiles/binuin32.conf old mode 100755 new mode 100644 diff --git a/tools/h5import/testfiles/txtfp32.conf b/tools/h5import/testfiles/txtfp32.conf old mode 100755 new mode 100644 diff --git a/tools/h5import/testfiles/txtfp32.txt b/tools/h5import/testfiles/txtfp32.txt old mode 100755 new mode 100644 diff --git a/tools/h5import/testfiles/txtfp64.conf b/tools/h5import/testfiles/txtfp64.conf old mode 100755 new mode 100644 diff --git a/tools/h5import/testfiles/txtfp64.txt b/tools/h5import/testfiles/txtfp64.txt old mode 100755 new mode 100644 diff --git a/tools/h5import/testfiles/txtin16.conf b/tools/h5import/testfiles/txtin16.conf old mode 100755 new mode 100644 diff --git a/tools/h5import/testfiles/txtin32.conf b/tools/h5import/testfiles/txtin32.conf old mode 100755 new mode 100644 diff --git a/tools/h5import/testfiles/txtin8.conf b/tools/h5import/testfiles/txtin8.conf old mode 100755 new mode 100644 diff --git a/tools/h5import/testfiles/txtuin16.conf b/tools/h5import/testfiles/txtuin16.conf old mode 100755 new mode 100644 diff --git a/tools/h5import/testfiles/txtuin32.conf b/tools/h5import/testfiles/txtuin32.conf old mode 100755 new mode 100644 diff --git a/tools/h5import/testfiles/txtuin32.txt b/tools/h5import/testfiles/txtuin32.txt old mode 100755 new mode 100644 diff --git a/tools/h5jam/testfiles/u10.txt b/tools/h5jam/testfiles/u10.txt old mode 100755 new mode 100644 diff --git a/tools/h5jam/testfiles/u511.txt b/tools/h5jam/testfiles/u511.txt old mode 100755 new mode 100644 diff --git a/tools/h5jam/testfiles/u512.txt b/tools/h5jam/testfiles/u512.txt old mode 100755 new mode 100644 diff --git a/tools/h5jam/testfiles/u513.txt b/tools/h5jam/testfiles/u513.txt old mode 100755 new mode 100644 diff --git a/tools/h5ls/testh5ls.sh.in b/tools/h5ls/testh5ls.sh.in index dc78174..8f793ba3d 100644 --- a/tools/h5ls/testh5ls.sh.in +++ b/tools/h5ls/testh5ls.sh.in @@ -25,7 +25,7 @@ H5LS_BIN=`pwd`/$H5LS # The path of the tool binary CMP='cmp -s' DIFF='diff -c' CP='cp' -NLINES=20 # Max. lines of output to display if test fails +NLINES=20 # Max. lines of output to display if test fails WORDS_BIGENDIAN="@WORDS_BIGENDIAN@" @@ -213,7 +213,7 @@ TOOLTEST() { # any unexpected output from that stream too. TESTING $H5LS $@ ( - cd $TESTDIR + cd $TESTDIR $RUNSERIAL $H5LS_BIN "$@" ) >$actual 2>$actual_err @@ -225,37 +225,37 @@ TOOLTEST() { STDERR_FILTER $actual_err cat $actual_err >> $actual if [ $h5haveexitcode = 'yes' -a $exitcode -ne $retvalexpect ]; then - echo "*FAILED*" - nerrors="`expr $nerrors + 1`" - if [ yes = "$verbose" ]; then - echo "test returned with exit code $exitcode" - echo "test output: (up to $NLINES lines)" - head -$NLINES $actual - echo "***end of test output***" - echo "" - fi + echo "*FAILED*" + nerrors="`expr $nerrors + 1`" + if [ yes = "$verbose" ]; then + echo "test returned with exit code $exitcode" + echo "test output: (up to $NLINES lines)" + head -$NLINES $actual + echo "***end of test output***" + echo "" + fi elif [ ! -f $expect ]; then - # Create the expect file if it doesn't yet exist. + # Create the expect file if it doesn't yet exist. echo " CREATED" cp $actual $expect elif $CMP $expect $actual; then echo " PASSED" else echo "*FAILED*" - echo " Expected result differs from actual result" - nerrors="`expr $nerrors + 1`" - test yes = "$verbose" && $DIFF $expect $actual |sed 's/^/ /' + echo " Expected result differs from actual result" + nerrors="`expr $nerrors + 1`" + test yes = "$verbose" && $DIFF $expect $actual |sed 's/^/ /' fi # Clean up output file if test -z "$HDF5_NOCLEANUP"; then - rm -f $actual $actual_err $actual_sav $actual_err_sav + rm -f $actual $actual_err $actual_sav $actual_err_sav fi } ############################################################################## ############################################################################## -### T H E T E S T S ### +### T H E T E S T S ### ############################################################################## ############################################################################## # prepare for test @@ -327,9 +327,9 @@ TOOLTEST thlinks-nodangle-1.ls 0 -w80 --follow-symlinks --no-dangling-links thli # test for wildcards in filename (does not work with cmake) # this h5ls test script does not pass the filename properly like the h5dump test script??? -#TOOLTEST tstarfile 0 -w80 t*link.h5 -#TOOLTEST tqmarkfile 0 -w80 t?link.h5 -TOOLTEST tmultifile 0 -w80 thlink.h5 tslink.h5 +#TOOLTEST tstarfile.ls 0 -w80 t*link.h5 +#TOOLTEST tqmarkfile.ls 0 -w80 t?link.h5 +TOOLTEST tmultifile.ls 0 -w80 thlink.h5 tslink.h5 # tests for hard links TOOLTEST thlink-1.ls 0 -w80 thlink.h5 diff --git a/tools/h5repack/CMakeLists.txt b/tools/h5repack/CMakeLists.txt index 6460375..ae7a658 100644 --- a/tools/h5repack/CMakeLists.txt +++ b/tools/h5repack/CMakeLists.txt @@ -145,6 +145,31 @@ IF (BUILD_TESTING) ############################################################################## ############################################################################## + MACRO (ADD_H5_TEST_OLD testname testtype testfile) + IF (${testtype} STREQUAL "SKIP") + IF (NOT HDF5_ENABLE_USING_MEMCHECKER) + ADD_TEST ( + NAME H5REPACK-${testname}-SKIPPED + COMMAND ${CMAKE_COMMAND} -E echo "SKIP ${ARGN} -i ${PROJECT_BINARY_DIR}/testfiles/${testfile} -o ${PROJECT_BINARY_DIR}/testfiles/out.${testfile}" + ) + ENDIF (NOT HDF5_ENABLE_USING_MEMCHECKER) + ELSE (${testtype} STREQUAL "SKIP") + ADD_TEST ( + NAME H5REPACK-${testname} + COMMAND $ ${ARGN} -i ${PROJECT_BINARY_DIR}/testfiles/${testfile} -o ${PROJECT_BINARY_DIR}/testfiles/out.${testfile} + ) + IF (NOT "${last_test}" STREQUAL "") + SET_TESTS_PROPERTIES (H5REPACK-${testname} PROPERTIES DEPENDS ${last_test}) + ENDIF (NOT "${last_test}" STREQUAL "") + ADD_TEST ( + NAME H5REPACK-DIFF_${testname} + COMMAND $ ${PROJECT_BINARY_DIR}/testfiles/${testfile} ${PROJECT_BINARY_DIR}/testfiles/out.${testfile} + ) + SET_TESTS_PROPERTIES (H5REPACK-DIFF_${testname} PROPERTIES DEPENDS H5REPACK-${testname}) + SET (last_test "H5REPACK-DIFF_${testname}") + ENDIF (${testtype} STREQUAL "SKIP") + ENDMACRO (ADD_H5_TEST_OLD) + MACRO (ADD_H5_TEST testname testtype testfile) IF (${testtype} STREQUAL "SKIP") IF (NOT HDF5_ENABLE_USING_MEMCHECKER) @@ -261,6 +286,29 @@ IF (BUILD_TESTING) ENDIF (${testtype} STREQUAL "SKIP") ENDMACRO (ADD_H5_VERIFY_TEST) + MACRO (ADD_H5_TEST_META testname testfile) + ADD_TEST ( + NAME H5REPACK-${testname}_N + COMMAND $ ${PROJECT_BINARY_DIR}/testfiles/${testfile} ${PROJECT_BINARY_DIR}/testfiles/out_N.${testname}.h5 + ) + IF (NOT "${last_test}" STREQUAL "") + SET_TESTS_PROPERTIES (H5REPACK-${testname}_N PROPERTIES DEPENDS ${last_test}) + ENDIF (NOT "${last_test}" STREQUAL "") + ADD_TEST ( + NAME H5REPACK-${testname}_M + COMMAND $ ${ARGN} ${PROJECT_BINARY_DIR}/testfiles/${testfile} ${PROJECT_BINARY_DIR}/testfiles/out_M.${testname}.h5 + ) + IF (NOT "${last_test}" STREQUAL "") + SET_TESTS_PROPERTIES (H5REPACK-${testname}_M PROPERTIES DEPENDS ${last_test}) + ENDIF (NOT "${last_test}" STREQUAL "") + ADD_TEST (NAME H5REPACK-${testname} COMMAND ${CMAKE_COMMAND} -E compare_files ${PROJECT_BINARY_DIR}/testfiles/out_N.${testname}.h5 ${PROJECT_BINARY_DIR}/testfiles/out_M.${testname}.h5) + SET_TESTS_PROPERTIES (H5REPACK-${testname} PROPERTIES WILL_FAIL "true") + IF (NOT "${last_test}" STREQUAL "") + SET_TESTS_PROPERTIES (H5REPACK-${testname} PROPERTIES DEPENDS ${last_test}) + ENDIF (NOT "${last_test}" STREQUAL "") + SET (last_test "H5REPACK-${testname}") + ENDMACRO (ADD_H5_TEST_META) + ############################################################################## ############################################################################## ### T H E T E S T S ### @@ -278,8 +326,10 @@ IF (BUILD_TESTING) ./testfiles/h5repack_layout2.h5-v.out.err ./testfiles/h5repack_layout.h5-v.out ./testfiles/h5repack_layout.h5-v.out.err + ./testfiles/out.tfamily%05d.h5 ./testfiles/out.h5diff_attr1.h5 ./testfiles/out.h5repack_attr.h5 + ./testfiles/out.h5repack_attr_refs.h5 ./testfiles/out.h5repack_deflate.h5 ./testfiles/out.h5repack_early.h5 ./testfiles/out.h5repack_fill.h5 @@ -295,6 +345,10 @@ IF (BUILD_TESTING) ./testfiles/out.h5repack_refs.h5 ./testfiles/out.h5repack_shuffle.h5 ./testfiles/out.h5repack_soffset.h5 + ./testfiles/out_M.meta_short.h5 + ./testfiles/out_N.meta_short.h5 + ./testfiles/out_M.meta_long.h5 + ./testfiles/out_N.meta_long.h5 # from the h5repacktst h5repack_attr.h5 h5repack_attr_out.h5 @@ -762,7 +816,7 @@ IF (BUILD_TESTING) IF (NOT USE_FILTER_DEFLATE) SET (TESTTYPE "SKIP") ENDIF (NOT USE_FILTER_DEFLATE) -# ADD_H5_TEST (old_style_layout_short_switches ${TESTTYPE} ${arg}) + ADD_H5_TEST_OLD (old_style_layout_short_switches ${TESTTYPE} ${arg}) # add a userblock to file SET (arg ${FILE1} -u ${PROJECT_BINARY_DIR}/testfiles/ublock.bin -b 2048) @@ -783,16 +837,14 @@ IF (BUILD_TESTING) ADD_H5_TEST (committed_dt "TEST" ${FILE15}) # tests family driver (file is located in common testfiles folder, uses TOOLTEST1 -# ADD_H5_TEST ( family "FAMILY" ${FILE16}) + ADD_H5_TEST (family "TEST" ${FILE16}) # test various references (bug 1814 and 1726) ADD_H5_TEST (bug1814 "TEST" ${FILE_REF}) -# test attribute with various references in attribute of compund -# or vlen datatype -# (HDFFV-2605, 7513) -# TODO: include this test when code portion is completed. - ADD_H5_TEST (HDFFV-2605 "SKIP" ${FILE_ATTR_REF}) +# test attribute with various references (bug1797 / HDFFV-5932) +# the references in attribute of compund or vlen datatype + ADD_H5_TEST (HDFFV-5932 "TEST" ${FILE_ATTR_REF}) # Add test for memory leak in attirbute. This test is verified by CTEST. # 1. leak from vlen string @@ -801,6 +853,10 @@ IF (BUILD_TESTING) # Note: this test is experimental for sharing test file among tools ADD_H5_TEST (HDFFV-7840 "TEST" h5diff_attr1.h5) +# tests for metadata block size option ('-M') + ADD_H5_TEST_META (meta_short h5repack_layout.h5 -M 8192) + ADD_H5_TEST_META (meta_long h5repack_layout.h5 --metadata_block_size=8192) + IF (HDF5_TEST_VFD) # Run test with different Virtual File Driver FOREACH (vfd ${VFD_LIST}) diff --git a/tools/h5repack/h5repack.c b/tools/h5repack/h5repack.c index 05160d8..fb38bc6 100644 --- a/tools/h5repack/h5repack.c +++ b/tools/h5repack/h5repack.c @@ -87,11 +87,12 @@ int h5repack(const char* infile, */ int -h5repack_init(pack_opt_t *options, int verbose, int latest, +h5repack_init(pack_opt_t *options, int verbose, hbool_t latest, H5F_file_space_type_t strategy, hsize_t threshold) { int k, n; - HDmemset(options,0,sizeof(pack_opt_t)); + + HDmemset(options, 0, sizeof(pack_opt_t)); options->min_comp = 1024; options->verbose = verbose; options->latest = latest; diff --git a/tools/h5repack/h5repack.h b/tools/h5repack/h5repack.h index 8d009a4..2bbed0a 100644 --- a/tools/h5repack/h5repack.h +++ b/tools/h5repack/h5repack.h @@ -104,13 +104,14 @@ typedef struct { int verbose; /*verbose mode */ hsize_t min_comp; /*minimum size to compress, in bytes */ int use_native; /*use a native type in write */ - int latest; /*pack file with the latest file format */ + hbool_t latest; /*pack file with the latest file format */ int grp_compact; /* Set the maximum number of links to store as header messages in the group */ int grp_indexed; /* Set the minimum number of links to store in the indexed format */ int msg_size[8]; /* Minimum size of shared messages: dataspace, datatype, fill value, filter pipleline, attribute */ const char *ublock_filename; /* user block file name */ hsize_t ublock_size; /* user block size */ + hsize_t meta_block_size; /* metadata aggregation block size (for H5Pset_meta_block_size) */ hsize_t threshold; /* alignment threshold for H5Pset_alignment */ hsize_t alignment ; /* alignment for H5Pset_alignment */ H5F_file_space_type_t fs_strategy; /* File space handling strategy */ @@ -136,7 +137,7 @@ extern "C" { int h5repack(const char* infile, const char* outfile, pack_opt_t *options); int h5repack_addfilter(const char* str, pack_opt_t *options); int h5repack_addlayout(const char* str, pack_opt_t *options); -int h5repack_init(pack_opt_t *options, int verbose, int latest, +int h5repack_init(pack_opt_t *options, int verbose, hbool_t latest, H5F_file_space_type_t strategy, hsize_t threshold); int h5repack_end(pack_opt_t *options); int h5repack_verify(const char *in_fname, const char *out_fname, pack_opt_t *options); diff --git a/tools/h5repack/h5repack.sh.in b/tools/h5repack/h5repack.sh.in old mode 100755 new mode 100644 index c1cbba1..236c555 --- a/tools/h5repack/h5repack.sh.in +++ b/tools/h5repack/h5repack.sh.in @@ -147,20 +147,25 @@ COPY_TESTFILES_TO_TESTDIR() done } +# Print a $* message left justified in a field of 70 characters +# +MESSAGE() { + SPACES=" " + echo "$* $SPACES" | cut -c1-70 | tr -d '\012' +} + # 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' + MESSAGE "Testing $*" } # Print a line-line message left justified in a field of 70 characters # beginning with the word "Verifying". # VERIFY() { - SPACES=" " - echo "Verifying h5diff output $* $SPACES" | cut -c1-70 | tr -d '\012' + MESSAGE "Verifying h5diff output $*" } # Print a message that a test has been skipped (because a required filter @@ -385,6 +390,49 @@ TOOLTESTV() rm -f $actual $actual_err $actual_sav } +# TOOLTEST_META: +# Test metadata block size option. +# Reason to create a function here is to localize all special steps related to +# metadata block size option in one place. This is a quick solution. More +# thought out solution needed when there is more time. +# +# $1: test input file +# $2:$: metadata options (either "-M size" or "--metadata_block_size=size") +# +# Algorithm: +# Run it once without the metadata option ($2-$); +# Save the result output file; +# Run it second time with the metadata option; +# Verify the output file of second run is larger than the one of 1st run. +TOOLTEST_META() +{ + input_file=$1 + outfile="$TESTDIR/out.$1" + + # Use TOOLTEST_MAIN to run because it does not remove the output file. + # 1st run, without metadata option + TOOLTEST_MAIN $1 + # get the size of the first output file + size1=`wc -c $outfile | cut -d' ' -f1` + + # 2nd run with metadata option + TOOLTEST_MAIN $* + # get the size of the second output file + size2=`wc -c $outfile | cut -d' ' -f1` + + # verify sizes. + MESSAGE "Verify the sizes of both output files ($size1 vs $size2)" + if [ $size1 -lt $size2 ]; then + # pass + echo " PASSED" + else + #fail + echo "*FAILED*" + fi + + rm -f $outfile +} + # This is different from $srcdir/../../bin/output_filter.sh STDOUT_FILTER() { result_file=$1 @@ -801,7 +849,6 @@ TOOLTEST h5repack_refs.h5 # the references in attribute of compund or vlen datatype TOOLTEST h5repack_attr_refs.h5 - # Add test for memory leak in attirbute. This test is verified by CTEST. # 1. leak from vlen string # 2. leak from compound type without reference member @@ -809,6 +856,10 @@ TOOLTEST h5repack_attr_refs.h5 # Note: this test is experimental for sharing test file among tools TOOLTEST h5diff_attr1.h5 +# tests for metadata block size option ('-M') +TOOLTEST_META h5repack_layout.h5 -M 8192 +TOOLTEST_META h5repack_layout.h5 --metadata_block_size=8192 + if test $nerrors -eq 0 ; then echo "All $TESTNAME tests passed." exit $EXIT_SUCCESS diff --git a/tools/h5repack/h5repack_copy.c b/tools/h5repack/h5repack_copy.c index 55cf932..d38a15c 100644 --- a/tools/h5repack/h5repack_copy.c +++ b/tools/h5repack/h5repack_copy.c @@ -42,7 +42,7 @@ int _err_num = 0; \ char _msg[80]; \ H5Ewalk2(H5E_DEFAULT, H5E_WALK_DOWNWARD, walk_error_callback, &_err_num); \ - H5Eget_msg(_err_num, NULL, _msg, 80); \ + H5Eget_msg(_err_num, NULL, _msg, (size_t)80); \ error_msg("%s %s -- %s\n", #_fun, "failed", _msg); \ goto error; \ } \ @@ -132,23 +132,23 @@ int copy_objects(const char* fnamein, goto out; } - if(!options->fs_strategy) - { - if(H5Pget_file_space(fcpl_in, &options->fs_strategy, NULL) < 0) - { - error_msg("failed to retrieve file space strategy\n"); - goto out; - } - } - - if(!options->fs_threshold) - { - if(H5Pget_file_space(fcpl_in, NULL, &options->fs_threshold) < 0) - { - error_msg("failed to retrieve file space threshold\n"); - goto out; - } - } + if(!options->fs_strategy) + { + if(H5Pget_file_space(fcpl_in, &options->fs_strategy, NULL) < 0) + { + error_msg("failed to retrieve file space strategy\n"); + goto out; + } + } + + if(!options->fs_threshold) + { + if(H5Pget_file_space(fcpl_in, NULL, &options->fs_threshold) < 0) + { + error_msg("failed to retrieve file space threshold\n"); + goto out; + } + } if(H5Pclose(fcpl_in) < 0) { @@ -254,135 +254,113 @@ int copy_objects(const char* fnamein, } /* end if */ } /* end if */ } /* end if */ - - - - #if defined (H5REPACK_DEBUG_USER_BLOCK) - print_user_block(fnamein,fidin); + print_user_block(fnamein, fidin); #endif - /*------------------------------------------------------------------------- * set the new user userblock options in the FCPL (before H5Fcreate ) *------------------------------------------------------------------------- */ - if ( options->ublock_size > 0 ) { /* either use the FCPL already created or create a new one */ - if(fcpl != H5P_DEFAULT) + if(fcpl == H5P_DEFAULT) { - /* set user block size */ - if(H5Pset_userblock(fcpl, options->ublock_size) < 0) - { - error_msg("failed to set userblock size\n"); - goto out; - } - - } - - else - { - /* create a file creation property list */ if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0) { error_msg("fail to create a file creation property list\n"); goto out; } - - /* set user block size */ - if(H5Pset_userblock(fcpl, options->ublock_size) < 0) - { - error_msg("failed to set userblock size\n"); - goto out; - } - } - - + /* set user block size */ + if(H5Pset_userblock(fcpl, options->ublock_size) < 0) + { + error_msg("failed to set userblock size\n"); + goto out; + } } - /*------------------------------------------------------------------------- * set alignment options *------------------------------------------------------------------------- */ - - if ( options->alignment > 0 ) { /* either use the FAPL already created or create a new one */ - if (fapl != H5P_DEFAULT) + if (fapl == H5P_DEFAULT) { - - if (H5Pset_alignment(fapl, options->threshold, options->alignment) < 0) + /* create a file access property list */ + if ((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0) { - error_msg("failed to set alignment\n"); + error_msg("Could not create file access property list\n"); goto out; } - } - else + if (H5Pset_alignment(fapl, options->threshold, options->alignment) < 0) { + error_msg("failed to set alignment\n"); + goto out; + } + } + /*------------------------------------------------------------------------- + * set metadata block size option + *------------------------------------------------------------------------- + */ + if ( options->meta_block_size > 0 ) + { + /* either use the FAPL already created or create a new one */ + if (fapl == H5P_DEFAULT) + { /* create a file access property list */ if ((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0) { error_msg("Could not create file access property list\n"); goto out; } - - if (H5Pset_alignment(fapl, options->threshold, options->alignment) < 0) - { - error_msg("failed to set alignment\n"); - goto out; - } - } + if (H5Pset_meta_block_size(fapl, options->meta_block_size) < 0) + { + error_msg("failed to set metadata block size\n"); + goto out; + } } + /*------------------------------------------------------------------------- + * set free-space strategy options + *------------------------------------------------------------------------- + */ + /* either use the FCPL already created or create a new one */ - if(fcpl != H5P_DEFAULT) + if(fcpl == H5P_DEFAULT) { - /* set file space strategy and free space threshold */ - if(H5Pset_file_space(fcpl, options->fs_strategy, options->fs_threshold) < 0) - { - error_msg("failed to set file space strategy & threshold\n"); - goto out; - } + /* create a file creation property list */ + if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0) + { + error_msg("fail to create a file creation property list\n"); + goto out; + } } - else + + /* set file space strategy and free space threshold */ + if(H5Pset_file_space(fcpl, options->fs_strategy, options->fs_threshold) < 0) { - /* create a file creation property list */ - if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0) - { - error_msg("fail to create a file creation property list\n"); - goto out; - } - - /* set file space strategy and free space threshold */ - if(H5Pset_file_space(fcpl, options->fs_strategy, options->fs_threshold) < 0) - { - error_msg("failed to set file space strategy & threshold \n"); - goto out; - } + error_msg("failed to set file space strategy & threshold \n"); + goto out; } /*------------------------------------------------------------------------- * create the output file *------------------------------------------------------------------------- */ - - if(options->verbose) printf("Making file <%s>...\n",fnameout); - if((fidout = H5Fcreate(fnameout,H5F_ACC_TRUNC, fcpl, fapl)) < 0) { error_msg("<%s>: Could not create file\n", fnameout ); diff --git a/tools/h5repack/h5repack_main.c b/tools/h5repack/h5repack_main.c index a630559..b6b8bfa 100644 --- a/tools/h5repack/h5repack_main.c +++ b/tools/h5repack/h5repack_main.c @@ -35,7 +35,7 @@ const char *outfile = NULL; * Command-line options: The user can specify short or long-named * parameters. */ -static const char *s_opts = "hVvf:l:m:e:nLc:d:s:u:b:t:a:i:o:S:T:"; +static const char *s_opts = "hVvf:l:m:e:nLc:d:s:u:b:M:t:a:i:o:S:T:"; static struct long_options l_opts[] = { { "help", no_arg, 'h' }, { "version", no_arg, 'V' }, @@ -51,6 +51,7 @@ static struct long_options l_opts[] = { { "ssize", require_arg, 's' }, { "ublock", require_arg, 'u' }, { "block", require_arg, 'b' }, + { "metadata_block_size", require_arg, 'M' }, { "threshold", require_arg, 't' }, { "alignment", require_arg, 'a' }, { "infile", require_arg, 'i' }, /* -i for backward compability */ @@ -78,24 +79,6 @@ static struct long_options l_opts[] = { * * Comments: * - * Modifications: - * July 2004: Introduced the extra EC or NN option for SZIP - * October 2006: Added a new switch -n, that allows to write the dataset - * using a native type. The default to write is the file type. - * - * Modification: - * Peter Cao, June 13, 2007 - * Add "-L, --latest" option to pack a file with the latest file format - * PVN, November 19, 2007 - * adopted the syntax h5repack [OPTIONS] file1 file2 - * PVN, November 28, 2007 - * added support for multiple global filters - * PVN, May 16, 2008 - * added backward compatibility for -i infile -o outfile - * PVN, August 20, 2008 - * add a user block to repacked file (switches -u -b) - * PVN, August 28, 2008 - * add options to set alignment (H5Pset_alignment) (switches -t -a) *------------------------------------------------------------------------- */ int main(int argc, const char **argv) @@ -115,7 +98,7 @@ int main(int argc, const char **argv) HDexit(EXIT_FAILURE); /* initialize options */ - h5repack_init(&options, 0, 0, 0, (hsize_t)0); + h5repack_init(&options, 0, FALSE, H5F_FILE_SPACE_DEFAULT, (hsize_t)0); parse_command_line(argc, argv, &options); @@ -187,6 +170,7 @@ static void usage(const char *prog) printf(" -e E, --file=E Name of file E with the -f and -l options\n"); printf(" -u U, --ublock=U Name of file U with user block data to be added\n"); printf(" -b B, --block=B Size of user block to be added\n"); + printf(" -M A, --metadata_block_size=A Metadata block size for H5Pset_meta_block_size\n"); printf(" -t T, --threshold=T Threshold value for H5Pset_alignment\n"); printf(" -a A, --alignment=A Alignment value for H5Pset_alignment\n"); printf(" -f FILT, --filter=FILT Filter type\n"); @@ -370,36 +354,32 @@ void parse_command_line(int argc, const char **argv, pack_opt_t* options) break; case 'L': - options->latest = 1; + options->latest = TRUE; break; case 'c': - options->grp_compact = HDatoi( opt_arg ); - if (options->grp_compact>0) - options->latest = 1; /* must use latest format */ + if (options->grp_compact > 0) + options->latest = TRUE; /* must use latest format */ break; case 'd': - options->grp_indexed = HDatoi( opt_arg ); - if (options->grp_indexed>0) - options->latest = 1; /* must use latest format */ + if (options->grp_indexed > 0) + options->latest = TRUE; /* must use latest format */ break; case 's': - { - int idx = 0; int ssize = 0; - char *msgPtr = HDstrchr( opt_arg, ':'); - options->latest = 1; /* must use latest format */ + char *msgPtr = HDstrchr(opt_arg, ':'); + options->latest = TRUE; /* must use latest format */ if (msgPtr == NULL) { ssize = HDatoi( opt_arg ); - for (idx=0; idx<5; idx++) + for(idx = 0; idx < 5; idx++) options->msg_size[idx] = ssize; } else @@ -408,27 +388,20 @@ void parse_command_line(int argc, const char **argv, pack_opt_t* options) HDstrcpy(msgType, msgPtr+1); msgPtr[0] = '\0'; ssize = HDatoi( opt_arg ); - if (HDstrncmp(msgType, "dspace",6) == 0) { + if(HDstrncmp(msgType, "dspace",6) == 0) options->msg_size[0] = ssize; - } - else if (HDstrncmp(msgType, "dtype", 5) == 0) { + else if (HDstrncmp(msgType, "dtype", 5) == 0) options->msg_size[1] = ssize; - } - else if (HDstrncmp(msgType, "fill", 4) == 0) { + else if (HDstrncmp(msgType, "fill", 4) == 0) options->msg_size[2] = ssize; - } - else if (HDstrncmp(msgType, "pline", 5) == 0) { + else if (HDstrncmp(msgType, "pline", 5) == 0) options->msg_size[3] = ssize; - } - else if (HDstrncmp(msgType, "attr", 4) == 0) { + else if (HDstrncmp(msgType, "attr", 4) == 0) options->msg_size[4] = ssize; - } } } - break; - case 'u': options->ublock_filename = opt_arg; @@ -439,6 +412,11 @@ void parse_command_line(int argc, const char **argv, pack_opt_t* options) options->ublock_size = (hsize_t)HDatol( opt_arg ); break; + case 'M': + + options->meta_block_size = (hsize_t)HDatol( opt_arg ); + break; + case 't': options->threshold = (hsize_t)HDatol( opt_arg ); @@ -455,7 +433,7 @@ void parse_command_line(int argc, const char **argv, pack_opt_t* options) break; case 'S': - { + { char strategy[MAX_NC_NAME]; HDstrcpy(strategy, opt_arg); @@ -472,7 +450,7 @@ void parse_command_line(int argc, const char **argv, pack_opt_t* options) HDexit(EXIT_FAILURE); } break; - } + } case 'T': diff --git a/tools/h5repack/h5repacktst.c b/tools/h5repack/h5repacktst.c index 05eac2f..0caf72a 100644 --- a/tools/h5repack/h5repacktst.c +++ b/tools/h5repack/h5repacktst.c @@ -78,7 +78,6 @@ #define FNAME17OUT "h5repack_named_dtypes_out.h5" #define FNAME18 "h5repack_layout2.h5" -#define FNAME18OUT "h5repack_layout2_out.h5" #define FNAME_UB "ublock.bin" @@ -172,6 +171,8 @@ int main (void) diff_opt_t diff_options; hsize_t fs_size = 0; /* free space section threshold */ H5F_file_space_type_t fs_type = H5F_FILE_SPACE_DEFAULT; /* file space handling strategy */ + h5_stat_t file_stat; + h5_stat_size_t fsize1, fsize2; /* file sizes */ #if defined (H5_HAVE_FILTER_SZIP) int szip_can_encode = 0; #endif @@ -212,7 +213,7 @@ int main (void) TESTING(" copy of datasets (fill values)"); /* fs_type = 0; fs_size = 0 */ - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack(FNAME0,FNAME0OUT,&pack_options) < 0) GOERROR; @@ -232,7 +233,7 @@ int main (void) *------------------------------------------------------------------------- */ TESTING(" copy of datasets (all datatypes)"); - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack(FNAME1,FNAME1OUT,&pack_options) < 0) GOERROR; @@ -252,7 +253,7 @@ int main (void) *------------------------------------------------------------------------- */ TESTING(" copy of datasets (attributes)"); - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack(FNAME2,FNAME2OUT,&pack_options) < 0) GOERROR; @@ -271,7 +272,7 @@ int main (void) *------------------------------------------------------------------------- */ TESTING(" copy of datasets (hardlinks)"); - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack(FNAME3,FNAME3OUT,&pack_options) < 0) GOERROR; @@ -291,7 +292,7 @@ int main (void) *------------------------------------------------------------------------- */ TESTING(" copy of allocation early file"); - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack(FNAME5,FNAME5OUT,&pack_options) < 0) GOERROR; @@ -321,7 +322,7 @@ int main (void) *------------------------------------------------------------------------- */ - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addfilter("dset1:GZIP=9",&pack_options) < 0) GOERROR; @@ -348,7 +349,7 @@ int main (void) *------------------------------------------------------------------------- */ - if (h5repack_init (&pack_options, 0, 1, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, TRUE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addfilter("dset1:GZIP=9",&pack_options) < 0) GOERROR; @@ -376,7 +377,7 @@ int main (void) #ifdef H5_HAVE_FILTER_DEFLATE - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addfilter("GZIP=1",&pack_options) < 0) GOERROR; @@ -414,7 +415,7 @@ int main (void) */ if (szip_can_encode) { - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addfilter("dset2:SZIP=8,EC",&pack_options) < 0) GOERROR; @@ -446,7 +447,7 @@ int main (void) #if defined (H5_HAVE_FILTER_SZIP) if (szip_can_encode) { - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addfilter("SZIP=8,NN",&pack_options) < 0) GOERROR; @@ -477,7 +478,7 @@ int main (void) *------------------------------------------------------------------------- */ - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addfilter("dset1:SHUF",&pack_options) < 0) GOERROR; @@ -507,7 +508,7 @@ int main (void) #ifdef H5_HAVE_FILTER_SHUFFLE /* fs_type = H5F_FILE_SPACE_ALL_PERSIST; fs_size = 1 */ - if (h5repack_init (&pack_options, 0, 0, H5_INC_ENUM(H5F_file_space_type_t, fs_type), ++fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, H5_INC_ENUM(H5F_file_space_type_t, fs_type), ++fs_size) < 0) GOERROR; if (h5repack_addfilter("SHUF",&pack_options) < 0) GOERROR; @@ -536,7 +537,7 @@ int main (void) *------------------------------------------------------------------------- */ - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addfilter("dset1:FLET",&pack_options) < 0) GOERROR; @@ -566,7 +567,7 @@ int main (void) #ifdef H5_HAVE_FILTER_FLETCHER32 - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addfilter("FLET",&pack_options) < 0) GOERROR; @@ -594,7 +595,7 @@ int main (void) *------------------------------------------------------------------------- */ - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addlayout("dset1:CHUNK 20x10",&pack_options) < 0) GOERROR; @@ -640,7 +641,7 @@ int main (void) *------------------------------------------------------------------------- */ - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addlayout("dset1:CHUNK=20x10",&pack_options) < 0) GOERROR; @@ -662,7 +663,7 @@ int main (void) *------------------------------------------------------------------------- */ - if (h5repack_init (&pack_options, 0, 1, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, TRUE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addlayout("dset1:CHUNK=20x10",&pack_options) < 0) GOERROR; @@ -682,7 +683,7 @@ int main (void) */ TESTING(" adding layout chunked to all"); - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addlayout("CHUNK=20x10",&pack_options) < 0) GOERROR; @@ -703,7 +704,7 @@ int main (void) * test an individual object option *------------------------------------------------------------------------- */ - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addlayout("dset1:CONTI",&pack_options) < 0) GOERROR; @@ -724,7 +725,7 @@ int main (void) * test all objects option *------------------------------------------------------------------------- */ - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addlayout("CONTI",&pack_options) < 0) GOERROR; @@ -741,7 +742,7 @@ int main (void) * do the same test for a file with filters (chunked) *------------------------------------------------------------------------- */ - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addlayout("CONTI",&pack_options) < 0) GOERROR; @@ -763,7 +764,7 @@ int main (void) *------------------------------------------------------------------------- */ - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addlayout("dset1:COMPA",&pack_options) < 0) GOERROR; @@ -785,7 +786,7 @@ int main (void) */ /* fs_type = H5F_FILE_SPACE_ALL; fs_size = 2 */ - if (h5repack_init (&pack_options, 0, 0, H5_INC_ENUM(H5F_file_space_type_t, fs_type), ++fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, H5_INC_ENUM(H5F_file_space_type_t, fs_type), ++fs_size) < 0) GOERROR; if (h5repack_addlayout("COMPA",&pack_options) < 0) GOERROR; @@ -807,7 +808,7 @@ int main (void) * layout compact to contiguous conversion *------------------------------------------------------------------------- */ - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addlayout("dset_compact:CONTI",&pack_options) < 0) GOERROR; @@ -827,7 +828,7 @@ int main (void) * layout compact to chunk conversion *------------------------------------------------------------------------- */ - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addlayout("dset_compact:CHUNK=2x5",&pack_options) < 0) GOERROR; @@ -847,7 +848,7 @@ int main (void) * layout compact to compact conversion *------------------------------------------------------------------------- */ - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addlayout("dset_compact:COMPA",&pack_options) < 0) GOERROR; @@ -866,7 +867,7 @@ int main (void) * layout contiguous to compact conversion *------------------------------------------------------------------------- */ - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addlayout("dset_contiguous:COMPA",&pack_options) < 0) GOERROR; @@ -885,7 +886,7 @@ int main (void) * layout contiguous to chunk conversion *------------------------------------------------------------------------- */ - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addlayout("dset_contiguous:CHUNK=3x6",&pack_options) < 0) GOERROR; @@ -905,7 +906,7 @@ int main (void) * layout contiguous to contiguous conversion *------------------------------------------------------------------------- */ - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addlayout("dset_contiguous:CONTI",&pack_options) < 0) GOERROR; @@ -924,7 +925,7 @@ int main (void) * layout chunked to compact conversion *------------------------------------------------------------------------- */ - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addlayout("dset_chunk:COMPA",&pack_options) < 0) GOERROR; @@ -944,7 +945,7 @@ int main (void) * layout chunked to contiguous conversion *------------------------------------------------------------------------- */ - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addlayout("dset_chunk:CONTI",&pack_options) < 0) GOERROR; @@ -963,7 +964,7 @@ int main (void) * layout chunked to chunked conversion *------------------------------------------------------------------------- */ - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addlayout("dset_chunk:CHUNK=18x13",&pack_options) < 0) GOERROR; @@ -994,7 +995,7 @@ int main (void) #if defined (H5_HAVE_FILTER_SZIP) if (szip_can_encode) { /* fs_type = H5F_FILE_SPACE_AGGR_VFD; fs_size = 3 */ - if (h5repack_init (&pack_options, 0, 0, H5_INC_ENUM(H5F_file_space_type_t, fs_type), ++fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, H5_INC_ENUM(H5F_file_space_type_t, fs_type), ++fs_size) < 0) GOERROR; if (h5repack(FNAME7,FNAME7OUT,&pack_options) < 0) GOERROR; @@ -1019,7 +1020,7 @@ int main (void) #if defined (H5_HAVE_FILTER_SZIP) if (szip_can_encode) { - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addfilter("dset_szip:NONE",&pack_options) < 0) GOERROR; @@ -1044,7 +1045,7 @@ int main (void) TESTING(" copy of deflate filter"); #ifdef H5_HAVE_FILTER_DEFLATE - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack(FNAME8,FNAME8OUT,&pack_options) < 0) GOERROR; @@ -1064,7 +1065,7 @@ int main (void) TESTING(" removing deflate filter"); #ifdef H5_HAVE_FILTER_DEFLATE - if (h5repack_init (&pack_options, 0, 0, fs_type, ++fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, ++fs_size) < 0) GOERROR; if (h5repack_addfilter("dset_deflate:NONE",&pack_options) < 0) GOERROR; @@ -1087,7 +1088,7 @@ int main (void) TESTING(" copy of shuffle filter"); #ifdef H5_HAVE_FILTER_SHUFFLE - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack(FNAME9,FNAME9OUT,&pack_options) < 0) GOERROR; @@ -1106,7 +1107,7 @@ int main (void) TESTING(" removing shuffle filter"); #ifdef H5_HAVE_FILTER_SHUFFLE - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addfilter("dset_shuffle:NONE",&pack_options) < 0) GOERROR; @@ -1127,7 +1128,7 @@ int main (void) TESTING(" copy of fletcher filter"); #ifdef H5_HAVE_FILTER_FLETCHER32 - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack(FNAME10,FNAME10OUT,&pack_options) < 0) GOERROR; @@ -1146,7 +1147,7 @@ int main (void) TESTING(" removing fletcher filter"); #ifdef H5_HAVE_FILTER_FLETCHER32 - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addfilter("dset_fletcher32:NONE",&pack_options) < 0) GOERROR; @@ -1168,7 +1169,7 @@ int main (void) TESTING(" copy of nbit filter"); #ifdef H5_HAVE_FILTER_NBIT - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack(FNAME12,FNAME12OUT,&pack_options) < 0) GOERROR; @@ -1187,7 +1188,7 @@ int main (void) TESTING(" removing nbit filter"); #ifdef H5_HAVE_FILTER_NBIT - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addfilter("dset_nbit:NONE",&pack_options) < 0) GOERROR; @@ -1209,7 +1210,7 @@ int main (void) TESTING(" adding nbit filter"); #ifdef H5_HAVE_FILTER_NBIT - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addfilter("dset_int31:NBIT",&pack_options) < 0) GOERROR; @@ -1231,7 +1232,7 @@ int main (void) TESTING(" copy of scaleoffset filter"); #ifdef H5_HAVE_FILTER_SCALEOFFSET - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack(FNAME13,FNAME13OUT,&pack_options) < 0) GOERROR; @@ -1250,7 +1251,7 @@ int main (void) TESTING(" removing scaleoffset filter"); #ifdef H5_HAVE_FILTER_SCALEOFFSET - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addfilter("dset_scaleoffset:NONE",&pack_options) < 0) GOERROR; @@ -1272,7 +1273,7 @@ int main (void) TESTING(" adding scaleoffset filter"); #ifdef H5_HAVE_FILTER_SCALEOFFSET - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addfilter("dset_none:SOFF=31,IN",&pack_options) < 0) GOERROR; @@ -1311,7 +1312,7 @@ int main (void) if (szip_can_encode) { /* fs_type = H5F_FILE_SPACE_VFD; fs_size = 4 */ - if (h5repack_init (&pack_options, 0, 0, H5_INC_ENUM(H5F_file_space_type_t, fs_type), ++fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, H5_INC_ENUM(H5F_file_space_type_t, fs_type), ++fs_size) < 0) GOERROR; if (h5repack_addfilter("dset_deflate:SZIP=8,NN",&pack_options) < 0) GOERROR; @@ -1339,7 +1340,7 @@ int main (void) && defined (H5_HAVE_FILTER_FLETCHER32) && defined (H5_HAVE_FILTER_SHUFFLE) if (szip_can_encode) { - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addfilter("dset_szip:GZIP=1",&pack_options) < 0) GOERROR; @@ -1371,7 +1372,7 @@ int main (void) #if defined (H5_HAVE_FILTER_SZIP) && defined (H5_HAVE_FILTER_DEFLATE) \ && defined (H5_HAVE_FILTER_FLETCHER32) && defined (H5_HAVE_FILTER_SHUFFLE) - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addfilter("NONE",&pack_options) < 0) GOERROR; @@ -1395,7 +1396,7 @@ int main (void) */ TESTING(" big file"); - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack(FNAME14,FNAME14OUT,&pack_options) < 0) GOERROR; @@ -1412,7 +1413,7 @@ int main (void) *------------------------------------------------------------------------- */ TESTING(" external datasets"); - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack(FNAME15,FNAME15OUT,&pack_options) < 0) GOERROR; @@ -1429,7 +1430,7 @@ int main (void) *------------------------------------------------------------------------- */ TESTING(" file with userblock"); - if(h5repack_init(&pack_options, 0, 0, fs_type, fs_size) < 0) + if(h5repack_init(&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if(h5repack(FNAME16, FNAME16OUT, &pack_options) < 0) GOERROR; @@ -1448,7 +1449,7 @@ int main (void) *------------------------------------------------------------------------- */ TESTING(" latest file format options"); - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; pack_options.latest=1; pack_options.grp_compact=10; @@ -1478,7 +1479,7 @@ int main (void) #if defined (H5_HAVE_FILTER_DEFLATE) && defined (H5_HAVE_FILTER_SHUFFLE) - if (h5repack_init (&pack_options, 0, 0, fs_type, fs_size) < 0) + if (h5repack_init (&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if (h5repack_addfilter("GZIP=1",&pack_options) < 0) GOERROR; @@ -1507,7 +1508,7 @@ int main (void) #ifdef H5_HAVE_FILTER_DEFLATE - if(h5repack_init(&pack_options, 0, 0, fs_type, fs_size) < 0) + if(h5repack_init(&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; /* add the options for a user block size and user block filename */ @@ -1540,7 +1541,7 @@ int main (void) #ifdef H5_HAVE_FILTER_DEFLATE - if(h5repack_init(&pack_options, 0, 0, fs_type, fs_size) < 0) + if(h5repack_init(&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; /* add the options for aligment */ @@ -1594,7 +1595,7 @@ int main (void) */ TESTING(" file with committed datatypes"); - if(h5repack_init(&pack_options, 0, 0, fs_type, fs_size) < 0) + if(h5repack_init(&pack_options, 0, FALSE, fs_type, fs_size) < 0) GOERROR; if(h5repack(FNAME17, FNAME17OUT, &pack_options) < 0) @@ -1610,6 +1611,50 @@ int main (void) PASSED(); /*------------------------------------------------------------------------- + * test --metadata_block_size option + * Also verify that output file using the metadata_block_size option is + * larger than the output file one not using it. + * FNAME4 is used because it is the same as the test file used for the + * shell script version of this test (h5repack.sh). + *------------------------------------------------------------------------- + */ + TESTING(" metadata block size option"); + /* First run without metadata option. No need to verify the correctness */ + /* since this has been verified by earlier tests. Just record the file */ + /* size of the output file. */ + if(h5repack_init(&pack_options, 0, FALSE, H5F_FILE_SPACE_DEFAULT, (hsize_t)0) < 0) + GOERROR; + if(h5repack(FNAME4, FNAME4OUT, &pack_options) < 0) + GOERROR; + if(HDstat(FNAME4OUT, &file_stat) < 0) + GOERROR; + fsize1 = file_stat.st_size; + if(h5repack_end(&pack_options) < 0) + GOERROR; + + /* run it again with metadata option */ + if(h5repack_init(&pack_options, 0, FALSE, H5F_FILE_SPACE_DEFAULT, (hsize_t)0) < 0) + GOERROR; + pack_options.meta_block_size = 8192; + if(h5repack(FNAME4, FNAME4OUT, &pack_options) < 0) + GOERROR; + if(h5diff(FNAME4, FNAME4OUT, NULL, NULL, &diff_options) > 0) + GOERROR; + if(h5repack_verify(FNAME4, FNAME4OUT, &pack_options) <= 0) + GOERROR; + /* record the file size of the output file */ + if(HDstat(FNAME4OUT, &file_stat) < 0) + GOERROR; + fsize2 = file_stat.st_size; + /* verify second file size is larger than the first one */ + if(fsize2 <= fsize1) + GOERROR; + if(h5repack_end(&pack_options) < 0) + GOERROR; + PASSED(); + + + /*------------------------------------------------------------------------- * clean temporary test files *------------------------------------------------------------------------- */ @@ -3302,7 +3347,7 @@ make_userblock(void) /* Initialize userblock data */ for(u = 0; u < USERBLOCK_SIZE; u++) - ub[u] = 'a' + (u % 26); + ub[u] = 'a' + (char)(u % 26); /* Re-open HDF5 file, as "plain" file */ if((fd = HDopen(FNAME16, O_WRONLY, 0644)) < 0) @@ -3415,7 +3460,7 @@ make_userblock_file(void) /* initialize userblock data */ for(u = 0; u < USERBLOCK_SIZE; u++) - ub[u] = 'a' + (u % 26); + ub[u] = 'a' + (char)(u % 26); /* open file */ if((fd = HDopen(FNAME_UB,O_WRONLY|O_CREAT|O_TRUNC, 0644 )) < 0) @@ -3891,7 +3936,7 @@ int write_dset_in(hid_t loc_id, int l; buf52[i][j].p = malloc((i + 1) * sizeof(int)); - buf52[i][j].len = i + 1; + buf52[i][j].len = (size_t)(i + 1); for(l = 0; l < i + 1; l++) { if(make_diffs) @@ -4112,7 +4157,7 @@ int write_dset_in(hid_t loc_id, int l; buf53[i][j][k].p = malloc((i + 1) * sizeof(int)); - buf53[i][j][k].len = i + 1; + buf53[i][j][k].len = (size_t)(i + 1); for(l = 0; l < i + 1; l++) { if(make_diffs) @@ -4903,7 +4948,7 @@ int write_attr_in(hid_t loc_id, { int l; buf52[i][j].p = malloc((i + 1) * sizeof(int)); - buf52[i][j].len = i + 1; + buf52[i][j].len = (size_t)(i + 1); for (l = 0; l < i + 1; l++) if (make_diffs)((int *)buf52[i][j].p)[l] = 0; else ((int *)buf52[i][j].p)[l] = n++; @@ -5369,7 +5414,7 @@ int write_attr_in(hid_t loc_id, { int l; buf53[i][j][k].p = malloc((i + 1) * sizeof(int)); - buf53[i][j][k].len = i + 1; + buf53[i][j][k].len = (size_t)i + 1; for (l = 0; l < i + 1; l++) if (make_diffs) { @@ -5868,7 +5913,7 @@ static herr_t add_attr_with_regref(hid_t file_id, hid_t obj_id) } /* select elements space for reference */ - status = H5Sselect_elements (sid_regrefed_dset, H5S_SELECT_SET, 3, coords_regrefed_dset[0]); + status = H5Sselect_elements (sid_regrefed_dset, H5S_SELECT_SET, (size_t)3, coords_regrefed_dset[0]); if (status < 0) { fprintf(stderr, "Error: %s %d> H5Sselect_elements failed.\n", FUNC, __LINE__); @@ -6190,7 +6235,7 @@ static herr_t gen_region_ref(hid_t loc_id) } /* select elements space for reference */ - status = H5Sselect_elements (sid_trg, H5S_SELECT_SET, 4, coords[0]); + status = H5Sselect_elements (sid_trg, H5S_SELECT_SET, (size_t)4, coords[0]); if (status < 0) { fprintf(stderr, "Error: %s %d> H5Sselect_elements failed.\n", FUNC, __LINE__); @@ -6557,7 +6602,7 @@ static herr_t make_complex_attr_references(hid_t loc_id) /* * create the region reference */ - status = H5Sselect_elements (objsid, H5S_SELECT_SET, 4, coords[0]); + status = H5Sselect_elements (objsid, H5S_SELECT_SET, (size_t)4, coords[0]); if (status < 0) { fprintf(stderr, "Error: %s %d> H5Sselect_elements failed.\n", FUNC, __LINE__); @@ -6668,7 +6713,7 @@ static herr_t make_complex_attr_references(hid_t loc_id) /* * create region reference */ - status = H5Sselect_elements(objsid, H5S_SELECT_SET, 4, coords[0]); + status = H5Sselect_elements(objsid, H5S_SELECT_SET, (size_t)4, coords[0]); if (status < 0) { fprintf(stderr, "Error: %s %d> H5Sselect_elements failed.\n", FUNC, __LINE__); diff --git a/tools/h5stat/h5stat.c b/tools/h5stat/h5stat.c index e206f4f..99ea688 100644 --- a/tools/h5stat/h5stat.c +++ b/tools/h5stat/h5stat.c @@ -99,17 +99,17 @@ typedef struct iter_t { hsize_t attrs_heap_storage_size; /* fractal heap size for attributes (1.8) */ hsize_t SM_hdr_storage_size; /* header size for SOHM table (1.8) */ hsize_t SM_index_storage_size; /* index (btree & list) size for SOHM table (1.8) */ - hsize_t SM_heap_storage_size; /* fractal heap size for SOHM table (1.8) */ - hsize_t super_size; /* superblock size */ - hsize_t super_ext_size; /* superblock extension size */ - hsize_t ublk_size; /* user block size (if exists) */ - H5F_file_space_type_t fs_strategy; /* File space management strategy */ - hsize_t fs_threshold; /* Free-space section threshold */ - hsize_t free_space; /* amount of freespace in the file */ - hsize_t free_hdr; /* size of free space manager metadata in the file */ + hsize_t SM_heap_storage_size; /* fractal heap size for SOHM table (1.8) */ + hsize_t super_size; /* superblock size */ + hsize_t super_ext_size; /* superblock extension size */ + hsize_t ublk_size; /* user block size (if exists) */ + H5F_file_space_type_t fs_strategy; /* File space management strategy */ + hsize_t fs_threshold; /* Free-space section threshold */ + hsize_t free_space; /* amount of freespace in the file */ + hsize_t free_hdr; /* size of free space manager metadata in the file */ unsigned long num_small_sects[SIZE_SMALL_SECTS]; /* Size of small free-space sections */ - unsigned sect_nbins; /* Number of bins for free-space section sizes */ - unsigned long *sect_bins; /* Pointer to array of bins for free-space section sizes */ + unsigned sect_nbins; /* Number of bins for free-space section sizes */ + unsigned long *sect_bins; /* Pointer to array of bins for free-space section sizes */ hsize_t datasets_index_storage_size;/* meta size for chunked dataset's indexing type */ hsize_t datasets_heap_storage_size; /* heap size for dataset with external storage */ unsigned long nexternal; /* Number of external files for a dataset */ @@ -120,11 +120,11 @@ typedef struct iter_t { static int display_all = TRUE; /* Enable the printing of selected statistics */ -static int display_file = FALSE; /* display file information */ -static int display_group = FALSE; /* display groups information */ -static int display_dset = FALSE; /* display datasets information */ +static int display_file = FALSE; /* display file information */ +static int display_group = FALSE; /* display groups information */ +static int display_dset = FALSE; /* display datasets information */ static int display_dset_dtype_meta = FALSE; /* display datasets' datatype information */ -static int display_attr = FALSE; /* display attributes information */ +static int display_attr = FALSE; /* display attributes information */ static int display_free_sections = FALSE; /* display free space information */ static int display_summary = FALSE; /* display summary of file space information */ @@ -283,7 +283,7 @@ ceil_log10(unsigned long x) } /* end while */ return(ret); -} +} /* ceil_log10() */ /*------------------------------------------------------------------------- @@ -481,7 +481,7 @@ dataset_stats(iter_t *iter, const char *name, const H5O_info_t *oi) /* Object header's total size for H5D_COMPACT layout includes raw data size */ /* "storage" also includes H5D_COMPACT raw data size */ if(lout == H5D_COMPACT) - iter->dset_ohdr_info.total_size -= storage; + iter->dset_ohdr_info.total_size -= storage; /* Track the layout type for dataset */ (iter->dset_layouts[lout])++; @@ -495,7 +495,7 @@ dataset_stats(iter_t *iter, const char *name, const H5O_info_t *oi) iter->nexternal += (unsigned long)num_ext; iter->dset_external_storage_size += (unsigned long)storage; } else - iter->dset_storage_size += storage; + iter->dset_storage_size += storage; /* Gather dataspace statistics */ sid = H5Dget_space(did); @@ -602,6 +602,7 @@ dataset_stats(iter_t *iter, const char *name, const H5O_info_t *oi) return 0; } /* end dataset_stats() */ + /*------------------------------------------------------------------------- * Function: datatype_stats * @@ -791,11 +792,6 @@ freespace_stats(hid_t fid, iter_t *iter) * Programmer: Elena Pourmal * Saturday, August 12, 2006 * - * Modifications: - * Vailin Choi; October 2009 - * Turn on display_group_metadata, display_dset_metadata - * Add 'S' & 's' for printing free space info (previous checkin) - * *------------------------------------------------------------------------- */ static struct handler_t * @@ -812,103 +808,103 @@ parse_command_line(int argc, const char *argv[]) /* parse command line options */ while ((opt = get_option(argc, argv, s_opts, l_opts)) != EOF) { - switch ((char) opt) { - case 'h': - usage(h5tools_getprogname()); - h5tools_setstatus(EXIT_SUCCESS); - if (hand) { - for (i = 0; i < argc; i++) - if(hand[i].obj) { - free(hand[i].obj); - hand[i].obj=NULL; - } - - free(hand); - hand = NULL; - } - goto done; - break; + switch ((char)opt) { + case 'h': + usage(h5tools_getprogname()); + h5tools_setstatus(EXIT_SUCCESS); + if (hand) { + for (i = 0; i < argc; i++) + if(hand[i].obj) { + free(hand[i].obj); + hand[i].obj=NULL; + } + + free(hand); + hand = NULL; + } + goto done; + break; - case 'V': - print_version(h5tools_getprogname()); - h5tools_setstatus(EXIT_SUCCESS); - if (hand) { - for (i = 0; i < argc; i++) - if(hand[i].obj) { - free(hand[i].obj); - hand[i].obj=NULL; - } - - free(hand); - hand = NULL; - } - goto done; - break; + case 'V': + print_version(h5tools_getprogname()); + h5tools_setstatus(EXIT_SUCCESS); + if (hand) { + for (i = 0; i < argc; i++) + if(hand[i].obj) { + free(hand[i].obj); + hand[i].obj=NULL; + } + + free(hand); + hand = NULL; + } + goto done; + break; - case 'F': - display_all = FALSE; - display_file_metadata = TRUE; - break; + case 'F': + display_all = FALSE; + display_file_metadata = TRUE; + break; - case 'f': - display_all = FALSE; - display_file = TRUE; - break; + case 'f': + display_all = FALSE; + display_file = TRUE; + break; - case 'G': - display_all = FALSE; - display_group_metadata = TRUE; - break; + case 'G': + display_all = FALSE; + display_group_metadata = TRUE; + break; - case 'g': - display_all = FALSE; - display_group = TRUE; - break; + case 'g': + display_all = FALSE; + display_group = TRUE; + break; - case 'D': - display_all = FALSE; - display_dset_metadata = TRUE; - break; + case 'D': + display_all = FALSE; + display_dset_metadata = TRUE; + break; - case 'd': - display_all = FALSE; - display_dset = TRUE; - break; + case 'd': + display_all = FALSE; + display_dset = TRUE; + break; - case 'T': - display_all = FALSE; - display_dset_dtype_meta = TRUE; - break; + case 'T': + display_all = FALSE; + display_dset_dtype_meta = TRUE; + break; - case 'A': - display_all = FALSE; - display_attr = TRUE; - break; + case 'A': + display_all = FALSE; + display_attr = TRUE; + break; - case 's': - display_all = FALSE; - display_free_sections = TRUE; - break; + case 's': + display_all = FALSE; + display_free_sections = TRUE; + break; - case 'S': - display_all = FALSE; - display_summary = TRUE; - break; + case 'S': + display_all = FALSE; + display_summary = TRUE; + break; - case 'O': - display_all = FALSE; - display_object = TRUE; - for (i = 0; i < argc; i++) - if (!hand[i].obj) { - hand[i].obj = HDstrdup(opt_arg); - break; - } /* end if */ - break; + case 'O': + display_all = FALSE; + display_object = TRUE; + for(i = 0; i < argc; i++) + if(!hand[i].obj) { + hand[i].obj = HDstrdup(opt_arg); + break; + } /* end if */ + break; - default: - usage(h5tools_getprogname()); - h5tools_setstatus(EXIT_FAILURE); - goto error; + default: + usage(h5tools_getprogname()); + h5tools_setstatus(EXIT_FAILURE); + goto error; } /* end switch */ } /* end while */ @@ -964,7 +960,7 @@ iter_init(iter_t *iter, hid_t fid) iter->fid = fid; return 0; -} +} /* iter_init() */ /*------------------------------------------------------------------------- @@ -1174,7 +1170,7 @@ print_group_metadata(const iter_t *iter) printf("File space information for groups' metadata (in bytes):\n"); HDfprintf(stdout, "\tObject headers (total/unused): %Hu/%Hu\n", - iter->group_ohdr_info.total_size, iter->group_ohdr_info.free_size); + iter->group_ohdr_info.total_size, iter->group_ohdr_info.free_size); HDfprintf(stdout, "\tB-tree/List: %Hu\n", iter->groups_btree_storage_size); HDfprintf(stdout, "\tHeap: %Hu\n", iter->groups_heap_storage_size); @@ -1195,8 +1191,6 @@ print_group_metadata(const iter_t *iter) * Programmer: Elena Pourmal * Saturday, August 12, 2006 * - * Modifications: - * *------------------------------------------------------------------------- */ static herr_t @@ -1292,10 +1286,10 @@ print_dset_metadata(const iter_t *iter) printf("File space information for datasets' metadata (in bytes):\n"); HDfprintf(stdout, "\tObject headers (total/unused): %Hu/%Hu\n", - iter->dset_ohdr_info.total_size, iter->dset_ohdr_info.free_size); + iter->dset_ohdr_info.total_size, iter->dset_ohdr_info.free_size); HDfprintf(stdout, "\tIndex for Chunked datasets: %Hu\n", - iter->datasets_index_storage_size); + iter->datasets_index_storage_size); HDfprintf(stdout, "\tHeap: %Hu\n", iter->datasets_heap_storage_size); return 0; @@ -1311,11 +1305,7 @@ print_dset_metadata(const iter_t *iter) * * Failure: Never fails * - * Programmer: - * - * Modifications: - * Vailin Choi; October 2009 - * Moved from print_dataset_info() + * Programmer: Vailin Choi; October 2009 * *------------------------------------------------------------------------- */ @@ -1327,21 +1317,21 @@ print_dset_dtype_meta(const iter_t *iter) unsigned u; /* Local index variable */ if(iter->dset_ntypes) { - printf("Dataset datatype information:\n"); - printf("\t# of unique datatypes used by datasets: %lu\n", iter->dset_ntypes); - total = 0; - for(u = 0; u < iter->dset_ntypes; u++) { - H5Tencode(iter->dset_type_info[u].tid, NULL, &dtype_size); - printf("\tDataset datatype #%u:\n", u); - printf("\t\tCount (total/named) = (%lu/%lu)\n", - iter->dset_type_info[u].count, iter->dset_type_info[u].named); - printf("\t\tSize (desc./elmt) = (%lu/%lu)\n", (unsigned long)dtype_size, - (unsigned long)H5Tget_size(iter->dset_type_info[u].tid)); - H5Tclose(iter->dset_type_info[u].tid); - total += iter->dset_type_info[u].count; - } /* end for */ - printf("\tTotal dataset datatype count: %lu\n", total); - } + printf("Dataset datatype information:\n"); + printf("\t# of unique datatypes used by datasets: %lu\n", iter->dset_ntypes); + total = 0; + for(u = 0; u < iter->dset_ntypes; u++) { + H5Tencode(iter->dset_type_info[u].tid, NULL, &dtype_size); + printf("\tDataset datatype #%u:\n", u); + printf("\t\tCount (total/named) = (%lu/%lu)\n", + iter->dset_type_info[u].count, iter->dset_type_info[u].named); + printf("\t\tSize (desc./elmt) = (%lu/%lu)\n", (unsigned long)dtype_size, + (unsigned long)H5Tget_size(iter->dset_type_info[u].tid)); + H5Tclose(iter->dset_type_info[u].tid); + total += iter->dset_type_info[u].count; + } /* end for */ + printf("\tTotal dataset datatype count: %lu\n", total); + } /* end if */ return 0; } /* print_dset_dtype_meta() */ @@ -1446,7 +1436,7 @@ print_freespace_info(const iter_t *iter) return 0; } /* print_freespace_info() */ - + /*------------------------------------------------------------------------- * Function: print_storage_summary * @@ -1492,7 +1482,7 @@ print_storage_summary(const iter_t *iter) HDfprintf(stdout, " Amount/Percent of tracked free space: %Hu bytes/%3.1f%\n", iter->free_space, percent); - if(iter->filesize < (total_meta+iter->dset_storage_size+iter->free_space)) { + if(iter->filesize < (total_meta + iter->dset_storage_size + iter->free_space)) { unaccount = (total_meta + iter->dset_storage_size + iter->free_space) - iter->filesize; HDfprintf(stdout, " ??? File has %Hu more bytes accounted for than its size! ???\n", unaccount); } @@ -1501,12 +1491,11 @@ print_storage_summary(const iter_t *iter) HDfprintf(stdout, " Unaccounted space: %Hu bytes\n", unaccount); } - HDfprintf(stdout, "Total space: %Hu bytes\n", total_meta+iter->dset_storage_size+iter->free_space+unaccount); + HDfprintf(stdout, "Total space: %Hu bytes\n", total_meta + iter->dset_storage_size + iter->free_space + unaccount); if(iter->nexternal) HDfprintf(stdout, "External raw data: %Hu bytes\n", iter->dset_external_storage_size); - return 0; } /* print_storage_summary() */ @@ -1523,11 +1512,6 @@ print_storage_summary(const iter_t *iter) * Programmer: Elena Pourmal * Saturday, August 12, 2006 * - * Modifications: - * Vailin Choi; October 2009 - * Activate "display_group_metadata", "dislay_dset_metadata" and - * "display_dset_dtype_info". - * *------------------------------------------------------------------------- */ static void @@ -1560,7 +1544,7 @@ print_file_statistics(const iter_t *iter) if(display_attr) print_attr_info(iter); if(display_free_sections) print_freespace_info(iter); if(display_summary) print_storage_summary(iter); -} +} /* print_file_statistics() */ /*------------------------------------------------------------------------- @@ -1583,7 +1567,7 @@ static void print_object_statistics(const char *name) { printf("Object name %s\n", name); -} +} /* print_object_statistics() */ /*------------------------------------------------------------------------- @@ -1609,9 +1593,18 @@ print_statistics(const char *name, const iter_t *iter) print_object_statistics(name); else print_file_statistics(iter); -} +} /* print_statistics() */ +/*------------------------------------------------------------------------- + * Function: main + * + * Modifications: + * 2/2010; Vailin Choi + * Get the size of user block + * + *------------------------------------------------------------------------- + */ int main(int argc, const char *argv[]) { diff --git a/tools/lib/h5diff.c b/tools/lib/h5diff.c index c6353eb..306f914 100644 --- a/tools/lib/h5diff.c +++ b/tools/lib/h5diff.c @@ -270,12 +270,12 @@ static int is_exclude_path (char * path, h5trav_type_t type, diff_opt_t *options /* search objects in exclude list */ while (NULL != exclude_path_ptr) { - /* if given object is group, exclude its members as well */ + /* if exclude path is is group, exclude its members as well */ if (exclude_path_ptr->obj_type == H5TRAV_TYPE_GROUP) { ret_cmp = HDstrncmp(exclude_path_ptr->obj_path, path, HDstrlen(exclude_path_ptr->obj_path)); - if (ret_cmp == 0) + if (ret_cmp == 0) /* found matching members */ { /* check if given path belong to an excluding group, if so * exclude it as well. @@ -295,12 +295,13 @@ static int is_exclude_path (char * path, h5trav_type_t type, diff_opt_t *options else { ret_cmp = HDstrcmp(exclude_path_ptr->obj_path, path); - if (ret_cmp == 0) + if (ret_cmp == 0) /* found matching object */ { /* excluded non-group object */ ret = 1; - /* assign type as scan progress, which is sufficient to - * determine type for excluding groups from the above if. */ + /* remember the type of this maching object. + * if it's group, it can be used for excluding its member + * objects in this while() loop */ exclude_path_ptr->obj_type = type; break; /* while */ } @@ -443,9 +444,11 @@ static void build_match_list (const char *objname1, trav_info_t *info1, const ch infile[1] = 0; while(curr1 < info1->nused) { + path1_lp = (info1->paths[curr1].path) + path1_offset; + type1_l = info1->paths[curr1].type; + if(!is_exclude_path(path1_lp, type1_l, options)) { - path1_lp = (info1->paths[curr1].path) + path1_offset; trav_table_addflags(infile, path1_lp, info1->paths[curr1].type, table); } curr1++; @@ -456,9 +459,11 @@ static void build_match_list (const char *objname1, trav_info_t *info1, const ch infile[1] = 1; while(curr2 < info2->nused) { + path2_lp = (info2->paths[curr2].path) + path2_offset; + type2_l = info2->paths[curr2].type; + if (!is_exclude_path(path2_lp, type2_l, options)) { - path2_lp = (info2->paths[curr2].path) + path2_offset; trav_table_addflags(infile, path2_lp, info2->paths[curr2].type, table); } curr2++; @@ -1116,6 +1121,8 @@ hsize_t diff_match(hid_t file1_id, const char *grp1, trav_info_t *info1, char * obj2_fullpath = NULL; h5trav_type_t objtype; diff_args_t argdata; + size_t idx1 = 0; + size_t idx2 = 0; /* @@ -1155,17 +1162,6 @@ hsize_t diff_match(hid_t file1_id, const char *grp1, trav_info_t *info1, } } - /* objects with the same name but different HDF5 types */ - for( i = 0; i < table->nobjs; i++) - { - if ( table->objs[i].flags[0] && table->objs[i].flags[1] ) - { - if ( table->objs[i].type != table->objs[i].type ) - { - options->contents = 0; - } - } - } /*------------------------------------------------------------------------- * do the diff for common objects @@ -1200,8 +1196,18 @@ hsize_t diff_match(hid_t file1_id, const char *grp1, trav_info_t *info1, HDstrcpy(obj2_fullpath, grp2_path); HDstrcat(obj2_fullpath, table->objs[i].name); + /* get index to figure out type of the object in file1 */ + while ( info1->paths[idx1].path && + (HDstrcmp (obj1_fullpath, info1->paths[idx1].path) != 0) ) + idx1++; + /* get index to figure out type of the object in file2 */ + while ( info2->paths[idx2].path && + (HDstrcmp (obj2_fullpath, info2->paths[idx2].path) != 0) ) + idx2++; + /* Set argdata to pass other args into diff() */ - argdata.type = objtype; + argdata.type[0] = info1->paths[idx1].type; + argdata.type[1] = info2->paths[idx2].type; argdata.is_same_trgobj = table->objs[i].is_same_trgobj; options->cmn_objs = 1; @@ -1237,7 +1243,8 @@ hsize_t diff_match(hid_t file1_id, const char *grp1, trav_info_t *info1, HDstrcpy(args.name1, obj1_fullpath); HDstrcpy(args.name2, obj2_fullpath); args.options = *options; - args.argdata.type = objtype; + args.argdata.type[0] = info1->paths[idx1].type; + args.argdata.type[1] = info2->paths[idx2].type; args.argdata.is_same_trgobj = table->objs[i].is_same_trgobj; h5diffdebug2("busyTasks=%d\n", busyTasks); @@ -1571,176 +1578,9 @@ hsize_t diff_compare(hid_t file1_id, obj1type = info1->paths[i].type; obj2type = info2->paths[j].type; - /*----------------------------------------------------------------- - * follow link option, compare with target object - */ - if (options->follow_links) - { - /* pass how to handle printing warning to linkinfo option */ - if(print_warn(options)) - linkinfo1.opt.msg_mode = linkinfo2.opt.msg_mode = 1; - - /*------------------------------------------------------------ - * Soft links - *------------------------------------------------------------*/ - - /*-------------------------- - * if object1 soft link */ - if (obj1type == H5TRAV_TYPE_LINK) - { - /* get type of target object */ - l_ret = H5tools_get_symlink_info(file1_id, obj1name, &linkinfo1, TRUE); - /* dangling link */ - if (l_ret == 0) - { - if (options->no_dangle_links) - { - /* gangling link is error */ - if(options->m_verbose) - parallel_print("Warning: <%s> is a dangling link.\n", obj1name); - options->err_stat = 1; - goto out; - } - else - is_dangle_link1 = 1; - } - /* fail */ - else if(l_ret < 0) - { - options->err_stat = 1; - goto out; - } - else /* OK */ - { - /* target type for diff() */ - obj1type = linkinfo1.trg_type; - } - } - - /*----------------------------- - * if object2 is soft link */ - if (obj2type == H5TRAV_TYPE_LINK) - { - /* get type target object */ - l_ret = H5tools_get_symlink_info(file2_id, obj2name, &linkinfo2, TRUE); - /* dangling link */ - if (l_ret == 0) - { - if (options->no_dangle_links) - { - /* gangling link is error */ - if(options->m_verbose) - parallel_print("Warning: <%s> is a dangling link.\n", obj2name); - options->err_stat = 1; - goto out; - } - else - is_dangle_link2=1; - } - /* fail */ - else if(l_ret < 0) - { - options->err_stat = 1; - goto out; - } - else /* OK */ - { - /* target type for diff() */ - obj2type = linkinfo2.trg_type; - } - } - - /*------------------------------------------------------------ - * External links - *------------------------------------------------------------*/ - - /*-------------------------------- - * if object1 is external link */ - if (obj1type == H5TRAV_TYPE_UDLINK) - { - /* get type and name of target object */ - l_ret = H5tools_get_symlink_info(file1_id, obj1name, &linkinfo1, TRUE); - /* dangling link */ - if (l_ret == 0) - { - if (options->no_dangle_links) - { - /* gangling link is error */ - if(options->m_verbose) - parallel_print("Warning: <%s> is a dangling link.\n", obj1name); - options->err_stat = 1; - goto out; - } - else - is_dangle_link1 = 1; - } - /* fail */ - else if(l_ret < 0) - { - options->err_stat = 1; - goto out; - } - else /* OK */ - { - /* for external link */ - if(linkinfo1.linfo.type == H5L_TYPE_EXTERNAL) - obj1type = linkinfo1.trg_type; - } - } - - /*-------------------------------- - * if object2 is external link */ - if (obj2type == H5TRAV_TYPE_UDLINK) - { - /* get type and name of target object */ - l_ret = H5tools_get_symlink_info(file2_id, obj2name, &linkinfo2, TRUE); - /* dangling link */ - if (l_ret == 0) - { - if (options->no_dangle_links) - { - /* gangling link is error */ - if(options->m_verbose) - parallel_print("Warning: <%s> is a dangling link.\n", obj2name); - options->err_stat = 1; - goto out; - } - else - is_dangle_link2 = 1; - } - /* fail */ - else if(l_ret < 0) - { - options->err_stat = 1; - goto out; - } - else /* OK */ - { - /* for external link */ - if(linkinfo2.linfo.type == H5L_TYPE_EXTERNAL) - obj2type = linkinfo2.trg_type; - } - } - /* found dangling link */ - if (is_dangle_link1 || is_dangle_link2) - goto out; - } /* end of follow_links */ - - /* objects are not the same type */ - if (obj1type != obj2type) - { - if (options->m_verbose||options->m_list_not_cmp) - { - parallel_print("<%s> is of type %s and <%s> is of type %s\n", - obj1name, get_type(obj1type), - obj2name, get_type(obj2type)); - } - options->not_cmp=1; - goto out; - } - /* Set argdata to pass other args into diff() */ - argdata.type = obj1type; + argdata.type[0] = obj1type; + argdata.type[1] = obj2type; argdata.is_same_trgobj = 0; nfound = diff(file1_id, obj1name, @@ -1801,7 +1641,8 @@ out: * Return: Number of differences found * * Programmer: Jonathan Kim - * - add following links feature (Feb 11,2010) + * - Move follow symlinks code toward top. (March 2812) + * - Add following symlinks feature (Feb 11,2010) * - Change to use diff_args_t to pass the rest of args. * Passing through it instead of individual args provides smoother * extensibility through its members along with MPI code update for ph5diff @@ -1829,6 +1670,7 @@ hsize_t diff(hid_t file1_id, int is_dangle_link2 = 0; int is_hard_link = 0; hsize_t nfound = 0; + h5trav_type_t object_type; /* to get link info */ @@ -1843,52 +1685,86 @@ hsize_t diff(hid_t file1_id, if(print_warn(options)) linkinfo1.opt.msg_mode = linkinfo2.opt.msg_mode = 1; - /* - * Get target object info for obj1 and obj2 and check dangling links. - * (for hard-linked-objects, because diff() only get the obj1's type, - * so obj2's type should be check here when diff() is called from - * diff_match() for same-named objects with dangling link only one side.) - */ - - /* target object1 - get type and name */ - ret = H5tools_get_symlink_info(file1_id, path1, &linkinfo1, TRUE); - /* dangling link */ - if (ret == 0) + /* for symbolic links, take care follow symlink and no dangling link + * options */ + if (argdata->type[0] == H5TRAV_TYPE_LINK || + argdata->type[0] == H5TRAV_TYPE_UDLINK || + argdata->type[1] == H5TRAV_TYPE_LINK || + argdata->type[1] == H5TRAV_TYPE_UDLINK ) { - if (options->no_dangle_links) + /* + * check dangling links for path1 and path2 + */ + + /* target object1 - get type and name */ + ret = H5tools_get_symlink_info(file1_id, path1, &linkinfo1, TRUE); + /* dangling link */ + if (ret == 0) { - /* gangling link is error */ - if(options->m_verbose) - parallel_print("Warning: <%s> is a dangling link.\n", path1); - goto out; + if (options->no_dangle_links) + { + /* gangling link is error */ + if(options->m_verbose) + parallel_print("Warning: <%s> is a dangling link.\n", path1); + goto out; + } + else + is_dangle_link1 = 1; } - else - is_dangle_link1 = 1; - } - else if (ret < 0) - goto out; + else if (ret < 0) + goto out; - /* target object2 - get type and name */ - ret = H5tools_get_symlink_info(file2_id, path2, &linkinfo2, TRUE); - /* dangling link */ - if (ret == 0) - { - if (options->no_dangle_links) + /* target object2 - get type and name */ + ret = H5tools_get_symlink_info(file2_id, path2, &linkinfo2, TRUE); + /* dangling link */ + if (ret == 0) { - /* gangling link is error */ - if(options->m_verbose) - parallel_print("Warning: <%s> is a dangling link.\n", path2); + if (options->no_dangle_links) + { + /* gangling link is error */ + if(options->m_verbose) + parallel_print("Warning: <%s> is a dangling link.\n", path2); + goto out; + } + else + is_dangle_link2 = 1; + } + else if (ret < 0) goto out; + + /* found dangling link */ + if (is_dangle_link1 || is_dangle_link2) + goto out2; + + /* follow symbolic link option */ + if (options->follow_links) + { + if (linkinfo1.linfo.type == H5L_TYPE_SOFT || + linkinfo1.linfo.type == H5L_TYPE_EXTERNAL) + argdata->type[0] = linkinfo1.trg_type; + + if (linkinfo2.linfo.type == H5L_TYPE_SOFT || + linkinfo2.linfo.type == H5L_TYPE_EXTERNAL) + argdata->type[1] = linkinfo2.trg_type; } - else - is_dangle_link2 = 1; } - else if (ret < 0) - goto out; - - /* found dangling link */ - if (is_dangle_link1 || is_dangle_link2) + /* if objects are not the same type */ + if (argdata->type[0] != argdata->type[1]) + { + if (options->m_verbose||options->m_list_not_cmp) + { + parallel_print("Not comparable: <%s> is of type %s and <%s> is of type %s\n", + path1, get_type(argdata->type[0]), + path2, get_type(argdata->type[1])); + } + options->not_cmp=1; + /* TODO: will need to update non-comparable is different + * options->contents = 0; + */ goto out2; + } + else /* now both object types are same */ + object_type = argdata->type[0]; /* * If both points to the same target object, skip comparing details inside @@ -1898,17 +1774,17 @@ hsize_t diff(hid_t file1_id, * * Perform this to match the outputs as bypassing. */ - is_hard_link = (argdata->type == H5TRAV_TYPE_DATASET || - argdata->type == H5TRAV_TYPE_NAMED_DATATYPE || - argdata->type == H5TRAV_TYPE_GROUP); - if (options->follow_links || is_hard_link) + if (argdata->is_same_trgobj) { - if (argdata->is_same_trgobj) + is_hard_link = (object_type == H5TRAV_TYPE_DATASET || + object_type == H5TRAV_TYPE_NAMED_DATATYPE || + object_type == H5TRAV_TYPE_GROUP); + if (options->follow_links || is_hard_link) { /* print information is only verbose option is used */ if(options->m_verbose || options->m_report) { - switch(argdata->type) + switch(object_type) { case H5TRAV_TYPE_DATASET: do_print_objname("dataset", path1, path2, options); @@ -1930,7 +1806,7 @@ hsize_t diff(hid_t file1_id, break; default: parallel_print("Comparison not supported: <%s> and <%s> are of type %s\n", - path1, path2, get_type(argdata->type) ); + path1, path2, get_type(object_type) ); options->not_cmp = 1; break; } /* switch(type)*/ @@ -1938,11 +1814,12 @@ hsize_t diff(hid_t file1_id, print_found(nfound); } /* if(options->m_verbose || options->m_report) */ + /* exact same, so comparison is done */ goto out2; } } - switch(argdata->type) + switch(object_type) { /*---------------------------------------------------------------------- * H5TRAV_TYPE_DATASET @@ -2059,30 +1936,6 @@ hsize_t diff(hid_t file1_id, if(print_objname(options, nfound)) do_print_objname("link", path1, path2, options); - if (options->follow_links) - { - /* objects are not the same type */ - if (linkinfo1.trg_type != linkinfo2.trg_type) - { - if (options->m_verbose||options->m_list_not_cmp) - { - parallel_print("<%s> is of type %s and <%s> is of type %s\n", path1, get_type(linkinfo1.trg_type), path2, get_type(linkinfo2.trg_type)); - } - options->not_cmp=1; - goto out; - } - - /* Renew type in argdata to pass into diff(). - * For recursive call, argdata.is_same_trgobj is already - * set from initial call, so don't reset here */ - argdata->type = linkinfo1.trg_type; - - /* call self to compare target object */ - nfound += diff(file1_id, path1, - file2_id, path2, - options, argdata); - } - /* always print the number of differences found in verbose mode */ if(options->m_verbose) print_found(nfound); @@ -2116,28 +1969,6 @@ hsize_t diff(hid_t file1_id, if(print_objname(options, nfound)) do_print_objname("external link", path1, path2, options); - if (options->follow_links) - { - /* objects are not the same type */ - if (linkinfo1.trg_type != linkinfo2.trg_type) - { - if (options->m_verbose||options->m_list_not_cmp) - { - parallel_print("<%s> is of type %s and <%s> is of type %s\n", path1, get_type(linkinfo1.trg_type), path2, get_type(linkinfo2.trg_type)); - } - options->not_cmp=1; - goto out; - } - - /* Renew type in argdata to pass into diff(). - * For recursive call, argdata.is_same_trgobj is already - * set from initial call, so don't reset here */ - argdata->type = linkinfo1.trg_type; - - nfound = diff(file1_id, path1, - file2_id, path2, - options, argdata); - } } /* end if */ else { @@ -2167,7 +1998,7 @@ hsize_t diff(hid_t file1_id, default: if(options->m_verbose) parallel_print("Comparison not supported: <%s> and <%s> are of type %s\n", - path1, path2, get_type(argdata->type) ); + path1, path2, get_type(object_type) ); options->not_cmp = 1; break; } diff --git a/tools/lib/h5diff.h b/tools/lib/h5diff.h index 1ff4402..6985b68 100644 --- a/tools/lib/h5diff.h +++ b/tools/lib/h5diff.h @@ -28,7 +28,7 @@ * as it doesn't require interface change. *------------------------------------------------------------------------*/ typedef struct { - h5trav_type_t type; + h5trav_type_t type[2]; hbool_t is_same_trgobj; } diff_args_t; /*------------------------------------------------------------------------- diff --git a/tools/lib/h5tools.c b/tools/lib/h5tools.c index 5e173e8..17639bc 100644 --- a/tools/lib/h5tools.c +++ b/tools/lib/h5tools.c @@ -115,7 +115,7 @@ h5tools_init(void) if (!h5tools_init_g) { /* register the error class */ HDsnprintf(lib_str, sizeof(lib_str), "%d.%d.%d",H5_VERS_MAJOR, H5_VERS_MINOR, H5_VERS_RELEASE); - + H5tools_ERR_STACK_g = H5Ecreate_stack(); H5TOOLS_INIT_ERROR() diff --git a/tools/misc/h5cc.in b/tools/misc/h5cc.in old mode 100755 new mode 100644 index a1421a2..233c80a --- a/tools/misc/h5cc.in +++ b/tools/misc/h5cc.in @@ -220,7 +220,7 @@ for arg in $@ ; do get_output_file="yes" fi ;; - -E|-M) + -E|-M|-MT) allargs="$allargs $arg" compile_args="$compile_args $arg" dash_c="yes" diff --git a/tools/misc/h5redeploy.in b/tools/misc/h5redeploy.in old mode 100755 new mode 100644 diff --git a/tools/testfiles/h5dump-help.txt b/tools/testfiles/h5dump-help.txt index f04ed48..d8551ca 100644 --- a/tools/testfiles/h5dump-help.txt +++ b/tools/testfiles/h5dump-help.txt @@ -10,6 +10,9 @@ usage: h5dump [OPTIONS] files -e, --escape Escape non printing characters -V, --version Print version number and exit -a P, --attribute=P Print the specified attribute + If an attribute name contains a slash (/), escape the + slash with a preceding backslash (\). + (See example section below.) -d P, --dataset=P Print the specified dataset -y, --noindex Do not print array indices with the data -p, --properties Print dataset filters, storage layout and fill value @@ -81,6 +84,10 @@ usage: h5dump [OPTIONS] files h5dump -a /bar_none/foo quux.h5 + Attribute "high/low" of the group /bar_none in the file quux.h5 + + h5dump -a "/bar_none/high\/low" quux.h5 + 2) Selecting a subset from dataset /foo in file quux.h5 h5dump -d /foo -s "0,1" -S "1,1" -c "2,3" -k "2,2" quux.h5 diff --git a/tools/testfiles/tnofilename-with-packed-bits.ddl b/tools/testfiles/tnofilename-with-packed-bits.ddl index d3b12e3..050a3a3 100644 --- a/tools/testfiles/tnofilename-with-packed-bits.ddl +++ b/tools/testfiles/tnofilename-with-packed-bits.ddl @@ -10,6 +10,9 @@ usage: h5dump [OPTIONS] files -e, --escape Escape non printing characters -V, --version Print version number and exit -a P, --attribute=P Print the specified attribute + If an attribute name contains a slash (/), escape the + slash with a preceding backslash (\). + (See example section below.) -d P, --dataset=P Print the specified dataset -y, --noindex Do not print array indices with the data -p, --properties Print dataset filters, storage layout and fill value @@ -81,6 +84,10 @@ usage: h5dump [OPTIONS] files h5dump -a /bar_none/foo quux.h5 + Attribute "high/low" of the group /bar_none in the file quux.h5 + + h5dump -a "/bar_none/high\/low" quux.h5 + 2) Selecting a subset from dataset /foo in file quux.h5 h5dump -d /foo -s "0,1" -S "1,1" -c "2,3" -k "2,2" quux.h5 diff --git a/tools/testfiles/tpbitsIncomplete.ddl b/tools/testfiles/tpbitsIncomplete.ddl index 0da055b..5608d2b 100644 --- a/tools/testfiles/tpbitsIncomplete.ddl +++ b/tools/testfiles/tpbitsIncomplete.ddl @@ -10,6 +10,9 @@ usage: h5dump [OPTIONS] files -e, --escape Escape non printing characters -V, --version Print version number and exit -a P, --attribute=P Print the specified attribute + If an attribute name contains a slash (/), escape the + slash with a preceding backslash (\). + (See example section below.) -d P, --dataset=P Print the specified dataset -y, --noindex Do not print array indices with the data -p, --properties Print dataset filters, storage layout and fill value @@ -81,6 +84,10 @@ usage: h5dump [OPTIONS] files h5dump -a /bar_none/foo quux.h5 + Attribute "high/low" of the group /bar_none in the file quux.h5 + + h5dump -a "/bar_none/high\/low" quux.h5 + 2) Selecting a subset from dataset /foo in file quux.h5 h5dump -d /foo -s "0,1" -S "1,1" -c "2,3" -k "2,2" quux.h5 diff --git a/tools/testfiles/tpbitsLengthExceeded.ddl b/tools/testfiles/tpbitsLengthExceeded.ddl index 594d70c..f89b65f 100644 --- a/tools/testfiles/tpbitsLengthExceeded.ddl +++ b/tools/testfiles/tpbitsLengthExceeded.ddl @@ -10,6 +10,9 @@ usage: h5dump [OPTIONS] files -e, --escape Escape non printing characters -V, --version Print version number and exit -a P, --attribute=P Print the specified attribute + If an attribute name contains a slash (/), escape the + slash with a preceding backslash (\). + (See example section below.) -d P, --dataset=P Print the specified dataset -y, --noindex Do not print array indices with the data -p, --properties Print dataset filters, storage layout and fill value @@ -81,6 +84,10 @@ usage: h5dump [OPTIONS] files h5dump -a /bar_none/foo quux.h5 + Attribute "high/low" of the group /bar_none in the file quux.h5 + + h5dump -a "/bar_none/high\/low" quux.h5 + 2) Selecting a subset from dataset /foo in file quux.h5 h5dump -d /foo -s "0,1" -S "1,1" -c "2,3" -k "2,2" quux.h5 diff --git a/tools/testfiles/tpbitsLengthPositive.ddl b/tools/testfiles/tpbitsLengthPositive.ddl index 7b3b678..ba32aa6 100644 --- a/tools/testfiles/tpbitsLengthPositive.ddl +++ b/tools/testfiles/tpbitsLengthPositive.ddl @@ -10,6 +10,9 @@ usage: h5dump [OPTIONS] files -e, --escape Escape non printing characters -V, --version Print version number and exit -a P, --attribute=P Print the specified attribute + If an attribute name contains a slash (/), escape the + slash with a preceding backslash (\). + (See example section below.) -d P, --dataset=P Print the specified dataset -y, --noindex Do not print array indices with the data -p, --properties Print dataset filters, storage layout and fill value @@ -81,6 +84,10 @@ usage: h5dump [OPTIONS] files h5dump -a /bar_none/foo quux.h5 + Attribute "high/low" of the group /bar_none in the file quux.h5 + + h5dump -a "/bar_none/high\/low" quux.h5 + 2) Selecting a subset from dataset /foo in file quux.h5 h5dump -d /foo -s "0,1" -S "1,1" -c "2,3" -k "2,2" quux.h5 diff --git a/tools/testfiles/tpbitsMaxExceeded.ddl b/tools/testfiles/tpbitsMaxExceeded.ddl index 60bc2b1..16f953d 100644 --- a/tools/testfiles/tpbitsMaxExceeded.ddl +++ b/tools/testfiles/tpbitsMaxExceeded.ddl @@ -10,6 +10,9 @@ usage: h5dump [OPTIONS] files -e, --escape Escape non printing characters -V, --version Print version number and exit -a P, --attribute=P Print the specified attribute + If an attribute name contains a slash (/), escape the + slash with a preceding backslash (\). + (See example section below.) -d P, --dataset=P Print the specified dataset -y, --noindex Do not print array indices with the data -p, --properties Print dataset filters, storage layout and fill value @@ -81,6 +84,10 @@ usage: h5dump [OPTIONS] files h5dump -a /bar_none/foo quux.h5 + Attribute "high/low" of the group /bar_none in the file quux.h5 + + h5dump -a "/bar_none/high\/low" quux.h5 + 2) Selecting a subset from dataset /foo in file quux.h5 h5dump -d /foo -s "0,1" -S "1,1" -c "2,3" -k "2,2" quux.h5 diff --git a/tools/testfiles/tpbitsOffsetExceeded.ddl b/tools/testfiles/tpbitsOffsetExceeded.ddl index 5db6a91..446fe2d 100644 --- a/tools/testfiles/tpbitsOffsetExceeded.ddl +++ b/tools/testfiles/tpbitsOffsetExceeded.ddl @@ -10,6 +10,9 @@ usage: h5dump [OPTIONS] files -e, --escape Escape non printing characters -V, --version Print version number and exit -a P, --attribute=P Print the specified attribute + If an attribute name contains a slash (/), escape the + slash with a preceding backslash (\). + (See example section below.) -d P, --dataset=P Print the specified dataset -y, --noindex Do not print array indices with the data -p, --properties Print dataset filters, storage layout and fill value @@ -81,6 +84,10 @@ usage: h5dump [OPTIONS] files h5dump -a /bar_none/foo quux.h5 + Attribute "high/low" of the group /bar_none in the file quux.h5 + + h5dump -a "/bar_none/high\/low" quux.h5 + 2) Selecting a subset from dataset /foo in file quux.h5 h5dump -d /foo -s "0,1" -S "1,1" -c "2,3" -k "2,2" quux.h5 diff --git a/tools/testfiles/tpbitsOffsetNegative.ddl b/tools/testfiles/tpbitsOffsetNegative.ddl index 060fc37..747cf99 100644 --- a/tools/testfiles/tpbitsOffsetNegative.ddl +++ b/tools/testfiles/tpbitsOffsetNegative.ddl @@ -10,6 +10,9 @@ usage: h5dump [OPTIONS] files -e, --escape Escape non printing characters -V, --version Print version number and exit -a P, --attribute=P Print the specified attribute + If an attribute name contains a slash (/), escape the + slash with a preceding backslash (\). + (See example section below.) -d P, --dataset=P Print the specified dataset -y, --noindex Do not print array indices with the data -p, --properties Print dataset filters, storage layout and fill value @@ -81,6 +84,10 @@ usage: h5dump [OPTIONS] files h5dump -a /bar_none/foo quux.h5 + Attribute "high/low" of the group /bar_none in the file quux.h5 + + h5dump -a "/bar_none/high\/low" quux.h5 + 2) Selecting a subset from dataset /foo in file quux.h5 h5dump -d /foo -s "0,1" -S "1,1" -c "2,3" -k "2,2" quux.h5 diff --git a/vms/COPYING b/vms/COPYING old mode 100755 new mode 100644 diff --git a/vms/src/h5pubconf.h b/vms/src/h5pubconf.h index 893e46c..d45cd48 100644 --- a/vms/src/h5pubconf.h +++ b/vms/src/h5pubconf.h @@ -502,7 +502,7 @@ #define H5_PACKAGE_NAME "HDF5" /* Define to the full name and version of this package. */ -#define H5_PACKAGE_STRING "HDF5 1.9.111-FA_a5" +#define H5_PACKAGE_STRING "HDF5 1.9.113-FA_a5" /* Define to the one symbol short name of this package. */ #define H5_PACKAGE_TARNAME "hdf5" @@ -511,7 +511,7 @@ #define H5_PACKAGE_URL "" /* Define to the version of this package. */ -#define H5_PACKAGE_VERSION "1.9.111-FA_a5" +#define H5_PACKAGE_VERSION "1.9.113-FA_a5" /* Width for printf() for type `long long' or `__int64', use `ll' */ #define H5_PRINTF_LL_WIDTH "ll" @@ -674,7 +674,7 @@ /* #undef H5_USING_MEMCHECKER */ /* Version number of package */ -#define H5_VERSION "1.9.111-FA_a5" +#define H5_VERSION "1.9.113-FA_a5" /* Define if vsnprintf() returns the correct value for formatted strings that don't fit into size allowed */ diff --git a/windows/COPYING b/windows/COPYING old mode 100755 new mode 100644 diff --git a/windows/examples/testExamples_exp_output.txt b/windows/examples/testExamples_exp_output.txt old mode 100755 new mode 100644 diff --git a/windows/src/H5pubconf.h b/windows/src/H5pubconf.h index 3a30f87..75313d7 100644 --- a/windows/src/H5pubconf.h +++ b/windows/src/H5pubconf.h @@ -527,7 +527,7 @@ #define H5_PACKAGE_NAME "HDF5" /* Define to the full name and version of this package. */ -#define H5_PACKAGE_STRING "HDF5 1.9.111-FA_a5" +#define H5_PACKAGE_STRING "HDF5 1.9.113-FA_a5" /* Define to the one symbol short name of this package. */ #define H5_PACKAGE_TARNAME "hdf5" @@ -536,7 +536,7 @@ #define H5_PACKAGE_URL "" /* Define to the version of this package. */ -#define H5_PACKAGE_VERSION "1.9.111-FA_a5" +#define H5_PACKAGE_VERSION "1.9.113-FA_a5" /* Width for printf() for type `long long' or `__int64', use `ll' */ #define H5_PRINTF_LL_WIDTH "I64" @@ -707,7 +707,7 @@ /* #undef H5_USING_MEMCHECKER */ /* Version number of package */ -#define H5_VERSION "1.9.111-FA_a5" +#define H5_VERSION "1.9.113-FA_a5" /* Define if vsnprintf() returns the correct value for formatted strings that don't fit into size allowed */ -- cgit v0.12