diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2010-07-20 16:51:49 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2010-07-20 16:51:49 (GMT) |
commit | de3a870bcd4953a3654b3e9dc92edab86fe858cd (patch) | |
tree | 8bf2fc6e0814f67b1388c23136aaff9e4a7cba96 | |
parent | 98754fa9d12090f5e048fdb05cc5e9ce9111676f (diff) | |
download | hdf5-de3a870bcd4953a3654b3e9dc92edab86fe858cd.zip hdf5-de3a870bcd4953a3654b3e9dc92edab86fe858cd.tar.gz hdf5-de3a870bcd4953a3654b3e9dc92edab86fe858cd.tar.bz2 |
[svn-r19110] Description:
Bring r19049:19109 from trunk to revise_chunks branch
Tested on:
FreeBSD/32 6.3 (duty) in debug mode
FreeBSD/64 6.3 (liberty) 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 (amani) 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 (heiwa) w/C++ & FORTRAN, w/threadsafe, in debug mode
Linux/64-ia64 2.6 (cobalt) w/Intel compilers, w/C++ & FORTRAN,
in production mode
Linux/64-amd64 2.6 (abe) w/parallel, w/FORTRAN, in debug mode
Mac OS X/32 10.6.4 (amazon) in debug mode
Mac OS X/32 10.6.4 (amazon) w/C++ & FORTRAN, w/threadsafe,
in production mode
Mac OS X/32 10.6.4 (amazon) w/parallel, in debug mode
147 files changed, 19936 insertions, 3042 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 5430cc7..cfae4d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,10 +78,6 @@ PROJECT (HDF5 C CXX) #----------------------------------------------------------------------------- # Basic HDF5 stuff here #----------------------------------------------------------------------------- -SET (H5_VERS_MAJOR 1) -SET (H5_VERS_MINOR 9) -SET (H5_VERS_RELEASE 72) -#----------------------------------------------------------------------------- SET (HDF5_PACKAGE "hdf5") SET (HDF5_PACKAGE_NAME "HDF5") SET (HDF5_PACKAGE_VERSION "${H5_VERS_MAJOR}.${H5_VERS_MINOR}.${H5_VERS_RELEASE}") @@ -89,7 +85,7 @@ SET (HDF5_PACKAGE_VERSION_MAJOR "${H5_VERS_MAJOR}.${H5_VERS_MINOR}") SET (HDF5_PACKAGE_VERSION_MINOR "${H5_VERS_RELEASE}") SET (HDF5_PACKAGE_STRING "${HDF5_PACKAGE_NAME} ${HDF5_PACKAGE_VERSION}") SET (HDF5_PACKAGE_TARNAME "hdf5") -SET (HDF5_PACKAGE_URL "htt://www.hdfgroup.org") +SET (HDF5_PACKAGE_URL "http://www.hdfgroup.org") SET (HDF5_PACKAGE_BUGREPORT "help@hdfgroup.org") #----------------------------------------------------------------------------- @@ -127,7 +123,7 @@ SET (HDF5_HL_F90_C_LIB_NAME "${HDF5_EXTERNAL_LIB_PREFIX}${HDF5_HL_F90_C_LIB_ #----------------------------------------------------------------------------- # Define some CMake variables for use later in the project #----------------------------------------------------------------------------- -SET (HDF5_RESOURCES_DIR ${HDF5_SOURCE_DIR}/Resources) +SET (HDF5_RESOURCES_DIR ${HDF5_SOURCE_DIR}/config/cmake) SET (HDF5_SRC_DIR ${HDF5_SOURCE_DIR}/src) SET (HDF5_TEST_SOURCE_DIR ${HDF5_SOURCE_DIR}/test) SET (HDF5_CPP_SOURCE_DIR ${HDF5_SOURCE_DIR}/c++) @@ -184,7 +180,7 @@ SET_GLOBAL_VARIABLE(HDF5_LIBRARIES_TO_EXPORT "") #----------------------------------------------------------------------------- # Run all the CMake configuration tests for our build environment #----------------------------------------------------------------------------- -INCLUDE (${HDF5_SOURCE_DIR}/ConfigureChecks.cmake) +INCLUDE (${HDF5_RESOURCES_DIR}/ConfigureChecks.cmake) #----------------------------------------------------------------------------- # Option to use legacy naming for windows libs/programs, default is legacy @@ -347,6 +343,18 @@ IF (CMAKE_COMPILER_IS_GNUCXX) ENDIF (CMAKE_COMPILER_IS_GNUCXX) #----------------------------------------------------------------------------- +# parse the full version number from H5public.h and include in H5_VERS_INFO +#----------------------------------------------------------------------------- +FILE (READ ${HDF5_SRC_DIR}/H5public.h _h5public_h_contents) +STRING (REGEX REPLACE ".*#define[ \t]+H5_VERS_MAJOR[ \t]+([0-9]*).*$" + "\\1" H5_VERS_MAJOR ${_h5public_h_contents}) +STRING (REGEX REPLACE ".*#define[ \t]+H5_VERS_MINOR[ \t]+([0-9]*).*$" + "\\1" H5_VERS_MINOR ${_h5public_h_contents}) +STRING (REGEX REPLACE ".*#define[ \t]+H5_VERS_RELEASE[ \t]+([0-9]*).*$" + "\\1" H5_VERS_RELEASE ${_h5public_h_contents}) +#MESSAGE (STATUS "VERSION: ${H5_VERS_MAJOR}.${H5_VERS_MINOR}.${H5_VERS_RELEASE}-${H5_VERS_SUBRELEASE}") + +#----------------------------------------------------------------------------- # All libs/tests/examples need the main include directories #----------------------------------------------------------------------------- INCLUDE_DIRECTORIES (${HDF5_BINARY_DIR} ${HDF5_SRC_DIR}) @@ -428,7 +436,7 @@ IF (HDF5_ENABLE_Z_LIB_SUPPORT) SET (H5_HAVE_ZLIB_H 1) SET (H5_HAVE_LIBZ 1) ENDIF (NOT H5_ZLIB_HEADER) - CONFIGURE_FILE (${HDF5_SOURCE_DIR}/Resources/hdf5_zlib.h.in ${HDF5_BINARY_DIR}/hdf5_zlib.h @ONLY) + CONFIGURE_FILE (${HDF5_RESOURCES_DIR}/hdf5_zlib.h.in ${HDF5_BINARY_DIR}/hdf5_zlib.h @ONLY) SET (LINK_LIBS ${LINK_LIBS} ${ZLIB_LIBRARIES}) INCLUDE_DIRECTORIES (${ZLIB_INCLUDE_DIRS}) MESSAGE (STATUS "Filter ZLIB is ON") @@ -437,7 +445,7 @@ ENDIF (HDF5_ENABLE_Z_LIB_SUPPORT) #----------------------------------------------------------------------------- # Option for SzLib support #----------------------------------------------------------------------------- -SET (CMAKE_MODULE_PATH ${HDF5_SOURCE_DIR}/Resources/CMake ${CMAKE_MODULE_PATH}) +SET (CMAKE_MODULE_PATH ${HDF5_RESOURCES_DIR} ${CMAKE_MODULE_PATH}) OPTION (HDF5_ENABLE_SZIP_SUPPORT "Use SZip Filter" OFF) IF (HDF5_ENABLE_SZIP_SUPPORT) FIND_PACKAGE (SZIP REQUIRED) @@ -478,7 +486,7 @@ ADD_SUBDIRECTORY (${HDF5_SOURCE_DIR}/src ${PROJECT_BINARY_DIR}/src) #----------------------------------------------------------------------------- IF (HDF5_BUILD_TOOLS AND BUILD_TESTING) SET (XLATE_UTILITY "xlatefile") - ADD_EXECUTABLE(${XLATE_UTILITY} ${HDF5_SOURCE_DIR}/Resources/xlatefile.c) + ADD_EXECUTABLE(${XLATE_UTILITY} ${HDF5_RESOURCES_DIR}/xlatefile.c) ENDIF (HDF5_BUILD_TOOLS AND BUILD_TESTING) #----------------------------------------------------------------------------- @@ -550,7 +558,7 @@ ENDIF (HDF5_BUILD_HL_LIB) #----------------------------------------------------------------------------- # Generate the H5pubconf.h file containing user settings needed by compilation #----------------------------------------------------------------------------- -CONFIGURE_FILE (${HDF5_SOURCE_DIR}/Resources/H5pubconf.h.in ${HDF5_BINARY_DIR}/H5pubconf.h @ONLY) +CONFIGURE_FILE (${HDF5_RESOURCES_DIR}/H5pubconf.h.in ${HDF5_BINARY_DIR}/H5pubconf.h @ONLY) #----------------------------------------------------------------------------- # Add file(s) to CMake Install @@ -598,7 +606,7 @@ SET (HDF5_VERSION_MAJOR @HDF5_PACKAGE_VERSION_MAJOR@) SET (HDF5_VERSION_MINOR @HDF5_PACKAGE_VERSION_MINOR@) CONFIGURE_FILE ( - ${HDF5_SOURCE_DIR}/Resources/HDF5-config.cmake.build.in + ${HDF5_RESOURCES_DIR}/HDF5-config.cmake.build.in ${HDF5_BINARY_DIR}/HDF5-config.cmake @ONLY ) @@ -609,7 +617,7 @@ INSTALL (CODE "SET (HDF5_INSTALL_SKIP_TARGETS 1) INCLUDE (${HDF5_BINARY_DIR}/HDF5-config.cmake) CONFIGURE_FILE ( - \"${HDF5_SOURCE_DIR}/Resources/HDF5-config.cmake.install.in\" + \"${HDF5_RESOURCES_DIR}/HDF5-config.cmake.install.in\" \"${CMAKE_INSTALL_PREFIX}/lib/HDF5-config.cmake\" @ONLY ) " @@ -162,6 +162,7 @@ ./fortran/examples/ph5example.f90 ./fortran/examples/refobjexample.f90 ./fortran/examples/refregexample.f90 +./fortran/examples/run-fortran-ex.sh.in ./fortran/examples/rwdsetexample.f90 ./fortran/examples/selectele.f90 ./fortran/examples/testh5fc.sh.in @@ -274,6 +275,7 @@ ./c++/examples/writedata.cpp ./c++/examples/Makefile.am ./c++/examples/Makefile.in +./c++/examples/run-c++-ex.sh.in ./c++/src/H5AbstractDs.cpp ./c++/src/H5AbstractDs.h @@ -861,6 +863,7 @@ ./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 @@ -928,6 +931,7 @@ ./test/trefer.c ./test/trefstr.c ./test/tselect.c +./test/tsizeslheap.h5 ./test/tskiplist.c ./test/tsohm.c ./test/ttst.c @@ -969,6 +973,7 @@ ./testpar/t_filter_read.c ./testpar/t_span_tree.c ./testpar/t_posix_compliant.c +./testpar/t_rank_projection.c ./testpar/testpar.h ./testpar/testphdf5.c ./testpar/testphdf5.h @@ -1170,7 +1175,6 @@ ./tools/testfiles/tall.h5 ./tools/testfiles/tarray1.ddl ./tools/testfiles/tarray1.h5 -./tools/testfiles/tarray1.ls ./tools/testfiles/tarray2.ddl ./tools/testfiles/tarray2.h5 ./tools/testfiles/tarray3.ddl @@ -1215,34 +1219,15 @@ ./tools/testfiles/tdset_idx.h5 ./tools/testfiles/tempty.ddl ./tools/testfiles/tempty.h5 -./tools/testfiles/tempty.ls ./tools/testfiles/tenum.h5 ./tools/testfiles/textlink.h5 ./tools/testfiles/textlink.h5.xml -./tools/testfiles/textlink-1.ls ./tools/testfiles/textlinkfar.ddl ./tools/testfiles/textlinkfar.h5 ./tools/testfiles/textlinksrc.ddl ./tools/testfiles/textlinksrc.h5 -./tools/testfiles/textlinksrc-1.ls -./tools/testfiles/textlinksrc-2.ls -./tools/testfiles/textlinksrc-3.ls -./tools/testfiles/textlinksrc-4.ls -./tools/testfiles/textlinksrc-5.ls -./tools/testfiles/textlinksrc-6.ls -./tools/testfiles/textlinksrc-7.ls -./tools/testfiles/textlinksrc-1-old.ls -./tools/testfiles/textlinksrc-2-old.ls -./tools/testfiles/textlinksrc-3-old.ls -./tools/testfiles/textlinksrc-6-old.ls -./tools/testfiles/textlinksrc-7-old.ls ./tools/testfiles/textlinktar.h5 ./tools/testfiles/tsoftlinks.h5 -./tools/testfiles/tsoftlinks-1.ls -./tools/testfiles/tsoftlinks-2.ls -./tools/testfiles/tsoftlinks-3.ls -./tools/testfiles/tsoftlinks-4.ls -./tools/testfiles/tsoftlinks-5.ls ./tools/testfiles/tfamily.ddl ./tools/testfiles/tfamily00000.h5 ./tools/testfiles/tfamily00001.h5 @@ -1304,7 +1289,6 @@ ./tools/testfiles/tstr-2.ddl ./tools/testfiles/tvldtypes1.ddl ./tools/testfiles/tvldtypes1.h5 -./tools/testfiles/tvldtypes1.ls ./tools/testfiles/tvldtypes2.ddl ./tools/testfiles/tvldtypes2.h5 ./tools/testfiles/tvldtypes3.ddl @@ -1319,7 +1303,6 @@ ./tools/testfiles/tudlink.h5.xml ./tools/testfiles/tudlink-1.ddl ./tools/testfiles/tudlink-2.ddl -./tools/testfiles/tudlink-1.ls ./tools/testfiles/tattr2.h5 ./tools/testfiles/tall-2A.ddl ./tools/testfiles/tall-2B.ddl @@ -1396,17 +1379,44 @@ ./tools/testfiles/tgroup-2.ls ./tools/testfiles/tgroup-3.ls ./tools/testfiles/tgroup.ls -./tools/testfiles/thlink-1.ls ./tools/testfiles/tloop-1.ls ./tools/testfiles/tnestcomp-1.ls ./tools/testfiles/tsaf.ls -./tools/testfiles/tslink-1.ls ./tools/testfiles/tstr-1.ls ./tools/testfiles/tattr2.ls +./tools/testfiles/tvldtypes1.ls ./tools/testfiles/tvldtypes2le.ls -./tools/testfiles/tdataregle.ls ./tools/testfiles/tvldtypes2be.ls +./tools/testfiles/tdataregle.ls ./tools/testfiles/tdataregbe.ls +./tools/testfiles/tarray1.ls +./tools/testfiles/tempty.ls +./tools/testfiles/thlink-1.ls +./tools/testfiles/tslink-1.ls +./tools/testfiles/textlink-1.ls +./tools/testfiles/textlinksrc-1.ls +./tools/testfiles/textlinksrc-2.ls +./tools/testfiles/textlinksrc-3.ls +./tools/testfiles/textlinksrc-4.ls +./tools/testfiles/textlinksrc-5.ls +./tools/testfiles/textlinksrc-6.ls +./tools/testfiles/textlinksrc-7.ls +./tools/testfiles/textlinksrc-1-old.ls +./tools/testfiles/textlinksrc-2-old.ls +./tools/testfiles/textlinksrc-3-old.ls +./tools/testfiles/textlinksrc-6-old.ls +./tools/testfiles/textlinksrc-7-old.ls +./tools/testfiles/tsoftlinks-1.ls +./tools/testfiles/tsoftlinks-2.ls +./tools/testfiles/tsoftlinks-3.ls +./tools/testfiles/tsoftlinks-4.ls +./tools/testfiles/tsoftlinks-5.ls +./tools/testfiles/textlinksrc-nodangle-1.ls +./tools/testfiles/textlinksrc-nodangle-2.ls +./tools/testfiles/tsoftlinks-nodangle-1.ls +./tools/testfiles/thlinks-nodangle-1.ls +./tools/testfiles/tudlink-1.ls + #additional test input and output for h5dump XML @@ -1725,6 +1735,8 @@ ./hl/examples/pal_rgb.h ./hl/examples/ptExampleFL.c ./hl/examples/ptExampleVL.c +./hl/examples/run-hl-ex.sh +./hl/examples/run-hlc-ex.sh.in ./hl/src/COPYING ./hl/src/Makefile.am ./hl/src/Makefile.in @@ -1806,6 +1818,7 @@ ./hl/fortran/examples/Makefile.am ./hl/fortran/examples/Makefile.in ./hl/fortran/examples/exlite.f90 +./hl/fortran/examples/run-hlfortran-ex.sh.in ./hl/fortran/src/H5IMcc.c ./hl/fortran/src/H5IMcc.h ./hl/fortran/src/H5IMfc.c @@ -1831,6 +1844,7 @@ ./hl/c++/examples/Makefile.in ./hl/c++/examples/ptExampleFL.cpp ./hl/c++/examples/ptExampleVL.cpp +./hl/c++/examples/run-hlc++-ex.sh.in ./hl/c++/src/H5PacketTable.h ./hl/c++/src/H5PacketTable.cpp ./hl/c++/src/Makefile.am @@ -1889,31 +1903,33 @@ ./vms/tools/testfiles/tperror.ddl # CMake-specific Files -./Resources/CMake/FindSZIP.cmake -./Resources/ConversionTests.c -./Resources/GetTimeOfDayTest.cpp -./Resources/HDF5Tests.c -./Resources/xlatefile.c -./Resources/CheckTypeSize.cmake -./Resources/H5cxx_config.h.in -./Resources/H5pubconf.h.in -./Resources/hdf5_zlib.h.in -./Resources/FindHDF5.cmake -./Resources/HDF5-config.cmake.build.in -./Resources/HDF5-config.cmake.install.in -./Resources/HDF5Macros.cmake -./Resources/libhdf5.settings.cmake.in -./Resources/cacheinit.cmake -./Resources/runTest.cmake -./Resources/CTestCustom.ctest +./config/cmake/FindSZIP.cmake +./config/cmake/ConversionTests.c +./config/cmake/GetTimeOfDayTest.cpp +./config/cmake/HDF5Tests.c +./config/cmake/xlatefile.c +./config/cmake/CheckTypeSize.cmake +./config/cmake/H5cxx_config.h.in +./config/cmake/H5pubconf.h.in +./config/cmake/hdf5_zlib.h.in +./config/cmake/FindHDF5.cmake +./config/cmake/HDF5-config.cmake.build.in +./config/cmake/HDF5-config.cmake.install.in +./config/cmake/HDF5Macros.cmake +./config/cmake/libhdf5.settings.cmake.in +./config/cmake/cacheinit.cmake +./config/cmake/runTest.cmake +./config/cmake/CTestCustom.ctest +./config/cmake/ConfigureChecks.cmake ./CMakeLists.txt -./ConfigureChecks.cmake ./CTestConfig.cmake ./c++/CMakeLists.txt ./c++/examples/CMakeLists.txt ./c++/src/CMakeLists.txt ./c++/test/CMakeLists.txt ./examples/CMakeLists.txt +./examples/run-all-ex.sh +./examples/run-c-ex.sh.in ./fortran/CMakeLists.txt ./fortran/examples/CMakeLists.txt ./fortran/src/CMakeLists.txt diff --git a/Makefile.am b/Makefile.am index 7acc2db..179fb17 100755 --- a/Makefile.am +++ b/Makefile.am @@ -125,17 +125,20 @@ mostlyclean-local: $(RM) -rf ii_files; \ fi +# 'make install' will now install examples, the same as 'make install-all'. +# 'make-install-all' will be redundant but will still work. +install: install-recursive install-examples +uninstall: uninstall-recursive uninstall-examples + # 'make install-all' also installs examples install-all: @$(MAKE) $(AM_MAKEFLAGS) install - @$(MAKE) $(AM_MAKEFLAGS) install-examples uninstall-all: @$(MAKE) $(AM_MAKEFLAGS) uninstall - @$(MAKE) $(AM_MAKEFLAGS) uninstall-examples # Install examples in this directory and recursively install-examples uninstall-examples: - @@SETX@; for d in examples $(HDF5_INTERFACES); do \ + @@SETX@; for d in examples $(HDF5_INTERFACES) $(HL); do \ (cd $$d && $(MAKE) $(AM_MAKEFLAGS) $@) || exit 1; \ done @@ -149,6 +152,9 @@ uninstall-doc: # `make check-install' or `make installcheck' checks that examples can # be successfully built installcheck-local: + if test -n "${DESTDIR}"; then \ + (cd ${DESTDIR}/$(bindir) && pwd && ./h5redeploy -force); \ + fi @(cd examples && $(MAKE) $(AM_MAKEFLAGS) $@) || exit 1; # check-install is just a synonym for installcheck diff --git a/Makefile.in b/Makefile.in index 8553153..fc2e887 100644 --- a/Makefile.in +++ b/Makefile.in @@ -172,6 +172,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -197,6 +198,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ @@ -778,10 +780,8 @@ check: check-recursive all-am: Makefile all-local installdirs: installdirs-recursive installdirs-am: -install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive -uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am @@ -950,17 +950,20 @@ mostlyclean-local: $(RM) -rf ii_files; \ fi +# 'make install' will now install examples, the same as 'make install-all'. +# 'make-install-all' will be redundant but will still work. +install: install-recursive install-examples +uninstall: uninstall-recursive uninstall-examples + # 'make install-all' also installs examples install-all: @$(MAKE) $(AM_MAKEFLAGS) install - @$(MAKE) $(AM_MAKEFLAGS) install-examples uninstall-all: @$(MAKE) $(AM_MAKEFLAGS) uninstall - @$(MAKE) $(AM_MAKEFLAGS) uninstall-examples # Install examples in this directory and recursively install-examples uninstall-examples: - @@SETX@; for d in examples $(HDF5_INTERFACES); do \ + @@SETX@; for d in examples $(HDF5_INTERFACES) $(HL); do \ (cd $$d && $(MAKE) $(AM_MAKEFLAGS) $@) || exit 1; \ done @@ -974,6 +977,9 @@ uninstall-doc: # `make check-install' or `make installcheck' checks that examples can # be successfully built installcheck-local: + if test -n "${DESTDIR}"; then \ + (cd ${DESTDIR}/$(bindir) && pwd && ./h5redeploy -force); \ + fi @(cd examples && $(MAKE) $(AM_MAKEFLAGS) $@) || exit 1; # check-install is just a synonym for installcheck @@ -1,4 +1,4 @@ -HDF5 version 1.9.73-FA_a4 currently under development +HDF5 version 1.9.75-FA_a4 currently under development Please refer to the release_docs/INSTALL file for installation instructions. ------------------------------------------------------------------------------ diff --git a/c++/CMakeLists.txt b/c++/CMakeLists.txt index b1edc06..7571e54 100644 --- a/c++/CMakeLists.txt +++ b/c++/CMakeLists.txt @@ -11,7 +11,7 @@ ENDIF (BUILD_SHARED_LIBS) #----------------------------------------------------------------------------- # Generate configure file #----------------------------------------------------------------------------- -CONFIGURE_FILE (${HDF5_SOURCE_DIR}/Resources/H5cxx_config.h.in +CONFIGURE_FILE (${HDF5_RESOURCES_DIR}/H5cxx_config.h.in ${HDF5_BINARY_DIR}/H5cxx_pubconf.h ) diff --git a/c++/Makefile.in b/c++/Makefile.in index e82d4a1..0fad20e 100644 --- a/c++/Makefile.in +++ b/c++/Makefile.in @@ -145,6 +145,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -170,6 +171,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ diff --git a/c++/examples/Makefile.am b/c++/examples/Makefile.am index f97a3f3..8a6a1d6 100644 --- a/c++/examples/Makefile.am +++ b/c++/examples/Makefile.am @@ -27,8 +27,9 @@ TEST_PROG=create readdata writedata compound extend_ds chunks h5group TEST_SCRIPT=testh5c++.sh # These are the example files to be installed -INSTALL_FILES=create.cpp readdata.cpp writedata.cpp compound.cpp \ +INSTALL_FILES=create.cpp readdata.cpp writedata.cpp compound.cpp \ extend_ds.cpp chunks.cpp h5group.cpp +INSTALL_SCRIPT_FILES = run-c++-ex.sh # Some of the examples depend on files created by running other examples readdata.chkexe_: create.chkexe_ @@ -38,7 +39,7 @@ chunks.chkexe_: extend_ds.chkexe_ CXX_API=yes # Where to install examples -EXAMPLEDIR=$(docdir)/hdf5/examples/c++ +EXAMPLEDIR=${DESTDIR}/$(exec_prefix)/share/hdf5_examples/c++ # How to build programs using h5c++ $(EXTRA_PROG): $(H5CPP) diff --git a/c++/examples/Makefile.in b/c++/examples/Makefile.in index 63ed0e9..c9662fd 100644 --- a/c++/examples/Makefile.in +++ b/c++/examples/Makefile.in @@ -55,7 +55,8 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ - $(srcdir)/testh5c++.sh.in $(top_srcdir)/config/commence.am \ + $(srcdir)/run-c++-ex.sh.in $(srcdir)/testh5c++.sh.in \ + $(top_srcdir)/config/commence.am \ $(top_srcdir)/config/conclude.am \ $(top_srcdir)/config/examples.am TESTS = @@ -66,7 +67,7 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/bin/mkinstalldirs CONFIG_HEADER = $(top_builddir)/src/H5config.h -CONFIG_CLEAN_FILES = testh5c++.sh +CONFIG_CLEAN_FILES = run-c++-ex.sh testh5c++.sh CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = @@ -111,6 +112,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -136,6 +138,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ @@ -337,15 +340,16 @@ TEST_PROG = create readdata writedata compound extend_ds chunks h5group TEST_SCRIPT = testh5c++.sh # These are the example files to be installed -INSTALL_FILES = create.cpp readdata.cpp writedata.cpp compound.cpp \ +INSTALL_FILES = create.cpp readdata.cpp writedata.cpp compound.cpp \ extend_ds.cpp chunks.cpp h5group.cpp +INSTALL_SCRIPT_FILES = run-c++-ex.sh # Tell conclude.am that these are C++ tests. CXX_API = yes # Where to install examples -EXAMPLEDIR = $(docdir)/hdf5/examples/c++ +EXAMPLEDIR = ${DESTDIR}/$(exec_prefix)/share/hdf5_examples/c++ # Assume that all tests in this directory are examples, and tell # conclude.am when to build them. @@ -404,6 +408,8 @@ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): +run-c++-ex.sh: $(top_builddir)/config.status $(srcdir)/run-c++-ex.sh.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ testh5c++.sh: $(top_builddir)/config.status $(srcdir)/testh5c++.sh.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ @@ -598,6 +604,8 @@ h5group: $(srcdir)/h5group.cpp # How to create EXAMPLEDIR if it doesn't already exist $(EXAMPLEDIR): -$(top_srcdir)/bin/mkdirs $@ +$(EXAMPLETOPDIR): + -$(top_srcdir)/bin/mkdirs $@ # Install and uninstall rules. We install the source files, not the # example programs themselves. @@ -612,10 +620,26 @@ install-examples: $(EXAMPLEDIR) $(INSTALL_FILES) (set -x; $(INSTALL) $(srcdir)/$$f $(EXAMPLEDIR)/. || exit 1);\ fi; \ done + @for f in X $(INSTALL_SCRIPT_FILES); do \ + if test $$f != X; then \ + (set -x; $(INSTALL) $$f $(EXAMPLEDIR)/. || exit 1);\ + fi; \ + done + @for f in X $(INSTALL_TOP_SCRIPT_FILES); do \ + if test $$f != X; then \ + (set -x; $(INSTALL) $(srcdir)/$$f $(EXAMPLETOPDIR)/. || exit 1); \ + fi; \ + done uninstall-examples: - @if test -n "$(INSTALL_FILES)" -a -d $(EXAMPLEDIR); then \ - set -x; cd $(EXAMPLEDIR) && $(RM) $(INSTALL_FILES); \ + @if test -n "$(INSTALL_FILES)" -a -d $(EXAMPLEDIR); then \ + set -x; cd $(EXAMPLEDIR) && $(RM) $(INSTALL_FILES); \ + fi + @if test -n "$(INSTALL_SCRIPT_FILES)" -a -d $(EXAMPLEDIR); then \ + set -x; cd $(EXAMPLEDIR) && $(RM) $(INSTALL_SCRIPT_FILES); \ + fi + @if test -n "$(INSTALL_TOP_SCRIPT_FILES)" -a -d $(EXAMPLETOPDIR); then \ + set -x; cd $(EXAMPLETOPDIR) && $(RM) $(INSTALL_TOP_SCRIPT_FILES); \ fi installcheck-local: diff --git a/c++/examples/run-c++-ex.sh.in b/c++/examples/run-c++-ex.sh.in new file mode 100755 index 0000000..79a4ccf --- /dev/null +++ b/c++/examples/run-c++-ex.sh.in @@ -0,0 +1,85 @@ +#! /bin/sh +# +# Copyright by The HDF Group. +# 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. + +# +# This file: run-c++-ex.sh +# Written by: Larry Knox +# Date: May 11, 2010 +# +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # +# This script will compile and run the c++ examples from source files # +# installed in .../share/hdf5_examples/c++ using h5c++. The # +# order for running programs with RunTest in the MAIN section below is taken # +# from the Makefile. The order is important since some of the test programs # +# use data files created by earlier test programs. Any future additions should # +# be placed accordingly. # +# # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +# Initializations +EXIT_SUCCESS=0 +EXIT_FAILURE=1 + +# Where the tool is installed. +prefix="${prefix:-${DESTDIR}/@prefix@}" +AR="@AR@" +RANLIB="@RANLIB@" +H5TOOL="h5c++" # The tool name +H5TOOL_BIN="${prefix}/bin/${H5TOOL}" # The path of the tool binary + +#### Run test #### +RunTest() +{ + Test=$1".cpp" + + echo + echo "################# $1 #################" + ${H5TOOL_BIN} $Test + if [ $? -ne 0 ] + then + echo "messed up compiling $Test" + exit 1 + fi + ./a.out +} + + + +################## MAIN ################## + +# Run tests +if [ $? -eq 0 ] +then + if (RunTest create &&\ + RunTest readdata &&\ + RunTest writedata &&\ + RunTest compound &&\ + RunTest extend_ds &&\ + RunTest chunks &&\ + RunTest h5group); then + EXIT_VALUE=${EXIT_SUCCESS} + else + EXIT_VALUE=${EXIT_FAILURE} + fi +fi + +# Cleanup +rm a.out +rm *.o +rm *.h5 +echo + +exit $EXIT_VALUE + diff --git a/c++/src/CMakeLists.txt b/c++/src/CMakeLists.txt index 2cf3d7b..fee9a6a 100644 --- a/c++/src/CMakeLists.txt +++ b/c++/src/CMakeLists.txt @@ -11,7 +11,7 @@ ENDIF (BUILD_SHARED_LIBS) #----------------------------------------------------------------------------- # Generate configure file #----------------------------------------------------------------------------- -CONFIGURE_FILE (${HDF5_SOURCE_DIR}/Resources/H5cxx_config.h.in +CONFIGURE_FILE (${HDF5_RESOURCES_DIR}/H5cxx_config.h.in ${HDF5_BINARY_DIR}/H5cxx_pubconf.h ) diff --git a/c++/src/Makefile.in b/c++/src/Makefile.in index 5ee5f64..5f7c6f3 100644 --- a/c++/src/Makefile.in +++ b/c++/src/Makefile.in @@ -167,6 +167,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -192,6 +193,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ @@ -390,7 +392,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 = 63 +LT_VERS_REVISION = 65 LT_VERS_AGE = 0 # Include src directory diff --git a/c++/test/Makefile.in b/c++/test/Makefile.in index 9e68dcd..e0bacda 100644 --- a/c++/test/Makefile.in +++ b/c++/test/Makefile.in @@ -134,6 +134,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -159,6 +160,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ diff --git a/config/apple b/config/apple index 8c4cc8e..10674fb 100644 --- a/config/apple +++ b/config/apple @@ -55,3 +55,33 @@ if test "X-" != "X-$enable_fortran"; then enable_shared="no" fi +# compiler version strings +case $CC in + *gcc*) + cc_version_info=`$CC $CFLAGS $H5_CFLAGS --version 2>&1 | grep -v 'PathScale' |\ + grep 'GCC' | sed 's/.*\((GCC) [-a-z0-9\. ]*.*\)/\1/'` + ;; + + *) + echo "No match to get cc_version_info for $CC" + ;; +esac + +case $FC in + *gfortran*) + fc_version_info=`$FC $FCFLAGS $H5_FCFLAGS --version 2>&1 |\ + grep 'GCC' | sed 's/\(.*(GCC) [-a-z0-9\. ]*\).*/\1/'` + ;; +esac + +# get c++ version info +case $CXX in + *g++*) + cxx_version_info=`$CXX $CXXFLAGS $H5_CXXFLAGS --version 2>&1 |\ + grep 'GCC' | sed 's/.*\((GCC) [-a-z0-9\. ]*.*\)/\1/'` + ;; + *) + echo "No match to get cxx_version_info for $CXX" + ;; +esac + diff --git a/Resources/CTestCustom.ctest b/config/cmake/CTestCustom.ctest index 23b4163..23b4163 100755 --- a/Resources/CTestCustom.ctest +++ b/config/cmake/CTestCustom.ctest diff --git a/Resources/CheckTypeSize.cmake b/config/cmake/CheckTypeSize.cmake index 2e83080..eca6e76 100644 --- a/Resources/CheckTypeSize.cmake +++ b/config/cmake/CheckTypeSize.cmake @@ -27,7 +27,7 @@ MACRO (HDF_CHECK_TYPE_SIZE TYPE VARIABLE) ENDIF (CMAKE_REQUIRED_LIBRARIES) TRY_RUN (${VARIABLE} HAVE_${VARIABLE} ${CMAKE_BINARY_DIR} - ${HDF5_PROJECT_DIR}/Resources/CheckTypeSize.c + ${HDF5_RESOURCES_DIR}/CheckTypeSize.c CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_TYPE_SIZE_FLAGS} "${CHECK_TYPE_SIZE_ADD_LIBRARIES}" OUTPUT_VARIABLE OUTPUT diff --git a/ConfigureChecks.cmake b/config/cmake/ConfigureChecks.cmake index 27fb1a8..47e6521 100644 --- a/ConfigureChecks.cmake +++ b/config/cmake/ConfigureChecks.cmake @@ -379,7 +379,7 @@ IF (NOT MSVC) IF ("H5_HAVE_TIME_GETTIMEOFDAY" MATCHES "^H5_HAVE_TIME_GETTIMEOFDAY$") TRY_COMPILE (HAVE_TIME_GETTIMEOFDAY ${CMAKE_BINARY_DIR} - ${HDF5_SOURCE_DIR}/Resources/GetTimeOfDayTest.cpp + ${HDF5_RESOURCES_DIR}/GetTimeOfDayTest.cpp COMPILE_DEFINITIONS -DTRY_TIME_H OUTPUT_VARIABLE OUTPUT ) @@ -391,7 +391,7 @@ IF (NOT MSVC) IF ("H5_HAVE_SYS_TIME_GETTIMEOFDAY" MATCHES "^H5_HAVE_SYS_TIME_GETTIMEOFDAY$") TRY_COMPILE (HAVE_SYS_TIME_GETTIMEOFDAY ${CMAKE_BINARY_DIR} - ${HDF5_SOURCE_DIR}/Resources/GetTimeOfDayTest.cpp + ${HDF5_RESOURCES_DIR}/GetTimeOfDayTest.cpp COMPILE_DEFINITIONS -DTRY_SYS_TIME_H OUTPUT_VARIABLE OUTPUT ) @@ -466,7 +466,7 @@ MACRO (HDF5_FUNCTION_TEST OTHER_TEST) # (STATUS "Performing ${OTHER_TEST}") TRY_COMPILE (${OTHER_TEST} ${CMAKE_BINARY_DIR} - ${HDF5_SOURCE_DIR}/Resources/HDF5Tests.c + ${HDF5_RESOURCES_DIR}//HDF5Tests.c CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS} "${OTHER_TEST_ADD_LIBRARIES}" OUTPUT_VARIABLE OUTPUT @@ -551,7 +551,7 @@ ENDIF (INLINE_TEST___inline__) #----------------------------------------------------------------------------- # Check how to print a Long Long integer #----------------------------------------------------------------------------- -SET (H5_H5_PRINTF_LL_WIDTH "H5_PRINTF_LL_WIDTH") +SET (H5_PRINTF_LL_WIDTH "H5_PRINTF_LL_WIDTH") IF (H5_PRINTF_LL_WIDTH MATCHES "^H5_PRINTF_LL_WIDTH$") SET (PRINT_LL_FOUND 0) MESSAGE (STATUS "Checking for appropriate format for 64 bit long:") @@ -562,7 +562,7 @@ IF (H5_PRINTF_LL_WIDTH MATCHES "^H5_PRINTF_LL_WIDTH$") ENDIF (H5_SIZEOF_LONG_LONG) TRY_RUN (HDF5_PRINTF_LL_TEST_RUN HDF5_PRINTF_LL_TEST_COMPILE ${HDF5_BINARY_DIR}/CMake - ${HDF5_SOURCE_DIR}/Resources/HDF5Tests.c + ${HDF5_RESOURCES_DIR}/HDF5Tests.c CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${CURRENT_TEST_DEFINITIONS} OUTPUT_VARIABLE OUTPUT ) @@ -616,7 +616,7 @@ MACRO (H5ConversionTests TEST msg) # MESSAGE (STATUS "===> ${TEST}") TRY_RUN (${TEST}_RUN ${TEST}_COMPILE ${HDF5_BINARY_DIR}/CMake - ${HDF5_SOURCE_DIR}/Resources/ConversionTests.c + ${HDF5_RESOURCES_DIR}/ConversionTests.c CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=-D${TEST}_TEST OUTPUT_VARIABLE OUTPUT ) diff --git a/Resources/ConversionTests.c b/config/cmake/ConversionTests.c index 0e24954..0e24954 100644 --- a/Resources/ConversionTests.c +++ b/config/cmake/ConversionTests.c diff --git a/Resources/FindHDF5.cmake b/config/cmake/FindHDF5.cmake index 4e448ca..4e448ca 100644 --- a/Resources/FindHDF5.cmake +++ b/config/cmake/FindHDF5.cmake diff --git a/Resources/CMake/FindSZIP.cmake b/config/cmake/FindSZIP.cmake index 190b0b5..190b0b5 100644 --- a/Resources/CMake/FindSZIP.cmake +++ b/config/cmake/FindSZIP.cmake diff --git a/Resources/GetTimeOfDayTest.cpp b/config/cmake/GetTimeOfDayTest.cpp index 3b5bf60..3b5bf60 100644 --- a/Resources/GetTimeOfDayTest.cpp +++ b/config/cmake/GetTimeOfDayTest.cpp diff --git a/Resources/H5cxx_config.h.in b/config/cmake/H5cxx_config.h.in index c4e1c03..c4e1c03 100644 --- a/Resources/H5cxx_config.h.in +++ b/config/cmake/H5cxx_config.h.in diff --git a/Resources/H5pubconf.h.in b/config/cmake/H5pubconf.h.in index 3f4bdc5..3f4bdc5 100644 --- a/Resources/H5pubconf.h.in +++ b/config/cmake/H5pubconf.h.in diff --git a/Resources/HDF5-config.cmake.build.in b/config/cmake/HDF5-config.cmake.build.in index 132e8be..132e8be 100644 --- a/Resources/HDF5-config.cmake.build.in +++ b/config/cmake/HDF5-config.cmake.build.in diff --git a/Resources/HDF5-config.cmake.install.in b/config/cmake/HDF5-config.cmake.install.in index 2c33edf..2c33edf 100644 --- a/Resources/HDF5-config.cmake.install.in +++ b/config/cmake/HDF5-config.cmake.install.in diff --git a/Resources/HDF5Macros.cmake b/config/cmake/HDF5Macros.cmake index cb1b300..8b30fbf 100644 --- a/Resources/HDF5Macros.cmake +++ b/config/cmake/HDF5Macros.cmake @@ -98,7 +98,7 @@ MACRO (H5_SET_LIB_OPTIONS libtarget libname libtype) IF (BUILD_SHARED_LIBS) IF (WIN32) - SET (LIBHDF_VERSION HDF5_PACKAGE_VERSION_MAJOR) + SET (LIBHDF_VERSION ${HDF5_PACKAGE_VERSION_MAJOR}) ELSE (WIN32) SET (LIBHDF_VERSION ${HDF5_PACKAGE_VERSION}) ENDIF (WIN32) diff --git a/Resources/HDF5Tests.c b/config/cmake/HDF5Tests.c index 35e7258..35e7258 100644 --- a/Resources/HDF5Tests.c +++ b/config/cmake/HDF5Tests.c diff --git a/Resources/cacheinit.cmake b/config/cmake/cacheinit.cmake index 7ca38e1..7ca38e1 100755 --- a/Resources/cacheinit.cmake +++ b/config/cmake/cacheinit.cmake diff --git a/Resources/hdf5_zlib.h.in b/config/cmake/hdf5_zlib.h.in index 104db27..104db27 100644 --- a/Resources/hdf5_zlib.h.in +++ b/config/cmake/hdf5_zlib.h.in diff --git a/Resources/libhdf5.settings.cmake.in b/config/cmake/libhdf5.settings.cmake.in index a3032e5..a3032e5 100644 --- a/Resources/libhdf5.settings.cmake.in +++ b/config/cmake/libhdf5.settings.cmake.in diff --git a/Resources/runTest.cmake b/config/cmake/runTest.cmake index 4218671..4218671 100644 --- a/Resources/runTest.cmake +++ b/config/cmake/runTest.cmake diff --git a/Resources/xlatefile.c b/config/cmake/xlatefile.c index c16f573..c16f573 100644 --- a/Resources/xlatefile.c +++ b/config/cmake/xlatefile.c diff --git a/config/examples.am b/config/examples.am index 28bd447..30ea717 100644 --- a/config/examples.am +++ b/config/examples.am @@ -30,6 +30,8 @@ ## ## INSTALL_FILES ## The source files that the examples use which should be installed. +## INSTALL_SCRIPT_FILES +## INSTALL_TOP_SCRIPT_FILES ## ## EXAMPLEDIR ## The directory into which examples should be installed. @@ -52,6 +54,8 @@ CLEANFILES=$(TEST_PROG) $(TEST_PROG_PARA) # How to create EXAMPLEDIR if it doesn't already exist $(EXAMPLEDIR): -$(top_srcdir)/bin/mkdirs $@ +$(EXAMPLETOPDIR): + -$(top_srcdir)/bin/mkdirs $@ # Install and uninstall rules. We install the source files, not the # example programs themselves. @@ -66,10 +70,26 @@ install-examples: $(EXAMPLEDIR) $(INSTALL_FILES) (set -x; $(INSTALL) $(srcdir)/$$f $(EXAMPLEDIR)/. || exit 1);\ fi; \ done + @for f in X $(INSTALL_SCRIPT_FILES); do \ + if test $$f != X; then \ + (set -x; $(INSTALL) $$f $(EXAMPLEDIR)/. || exit 1);\ + fi; \ + done + @for f in X $(INSTALL_TOP_SCRIPT_FILES); do \ + if test $$f != X; then \ + (set -x; $(INSTALL) $(srcdir)/$$f $(EXAMPLETOPDIR)/. || exit 1); \ + fi; \ + done uninstall-examples: - @if test -n "$(INSTALL_FILES)" -a -d $(EXAMPLEDIR); then \ - set -x; cd $(EXAMPLEDIR) && $(RM) $(INSTALL_FILES); \ + @if test -n "$(INSTALL_FILES)" -a -d $(EXAMPLEDIR); then \ + set -x; cd $(EXAMPLEDIR) && $(RM) $(INSTALL_FILES); \ + fi + @if test -n "$(INSTALL_SCRIPT_FILES)" -a -d $(EXAMPLEDIR); then \ + set -x; cd $(EXAMPLEDIR) && $(RM) $(INSTALL_SCRIPT_FILES); \ + fi + @if test -n "$(INSTALL_TOP_SCRIPT_FILES)" -a -d $(EXAMPLETOPDIR); then \ + set -x; cd $(EXAMPLETOPDIR) && $(RM) $(INSTALL_TOP_SCRIPT_FILES); \ fi installcheck-local: diff --git a/config/linux-gnulibc1 b/config/linux-gnulibc1 index 667f04e..26a0c3a 100644 --- a/config/linux-gnulibc1 +++ b/config/linux-gnulibc1 @@ -35,6 +35,7 @@ fi # Figure out Intel C compiler flags . $srcdir/config/intel-flags +echo "CC_BASENAME is $CC_BASENAME." # Use default Fortran 90 compiler according to what C compiler is used. if test "X-" = "X-$FC"; then case $CC_BASENAME in @@ -61,7 +62,7 @@ else ifc*|ifort*|pgf90*) ;; - *) + *f95*) # Figure out which compiler we are using: pgf90 or Absoft f95 RM='rm -f' tmpfile=/tmp/cmpver.$$ @@ -75,6 +76,10 @@ else fi fi $RM $tmpfile + fc_version_info=`$FC -V | grep Absoft` + ;; + + *) ;; esac fi @@ -131,3 +136,86 @@ fi hdf5_cv_mpi_special_collective_io_works=${hdf5_cv_mpi_special_collective_io_works='no'} hdf5_cv_mpi_complex_derived_datatype_works=${hdf5_cv_mpi_complex_derived_datatype_works='no'} +# compiler version strings +case $CC in + # whatever matches *pgcc* will also match *gcc*, so this one must come first + *pgcc*) + cc_version_info=`$CC $CFLAGS $H5_CFLAGS -V 2>&1 | grep 'pgcc'` + ;; + + *gcc*) + cc_version_info=`$CC $CFLAGS $H5_CFLAGS --version 2>&1 | grep -v 'PathScale' |\ + grep 'GCC' | sed 's/\(.*(GCC) [-a-z0-9\. ]*\).*/\1/'` + ;; + + *icc*) + cc_version_info=`$CC $CCFLAGS $H5_CCFLAGS -V 2>&1 | grep 'Version' |\ + sed 's/\(Intel.* Compiler\).*\( Version [a-z0-9\.]*\).*\( Build [0-9]*\)/\1\2\3/'` + ;; + + *) + echo "No match to get cc_version_info for $CC" + ;; +esac + +# get fortran version info +case $FC in + *gfortran*) + fc_version_info=`$FC $FCFLAGS $H5_FCFLAGS --version 2>&1 |\ + grep 'GCC' | sed 's/\(.*(GCC) [-a-z0-9\. ]*\).*/\1/'` + ;; + + *ifc*|*ifort*) + fc_version_info=`$FC $FCFLAGS $H5_FCFLAGS -V 2>&1 | grep 'Version' |\ + sed 's/\(Intel.* Compiler\).*\( Version [a-z0-9\.]*\).*\( Build [0-9]*\)/\1\2\3/'` + ;; + + *f95*) + # Figure out which compiler we are using: pgf90 or Absoft f95 + RM='rm -f' + tmpfile=/tmp/cmpver.$$ + $FC -V >$tmpfile + if test -s "$tmpfile"; then + if( grep -s 'Absoft' $tmpfile > /dev/null) then + FC_BASENAME=f95 + fi + fi + $RM $tmpfile + fc_version_info=`$FC -V | grep Absoft` + ;; + + *g95*) + fc_version_info=`$FC $FCFLAGS $H5_FCFLAGS --version 2>&1 |\ + grep 'GCC'` + ;; + + *pgf90*) + fc_version_info=`$FC $FCFLAGS $H5_FCFLAGS -V 2>&1 | grep 'pgf90'` + ;; + + *) + echo "No match to get fc_version_info for $FC" + ;; +esac + + +# get c++ version info +case $CXX in + *g++*) + cxx_version_info=`$CXX $CXXFLAGS $H5_CXXFLAGS --version 2>&1 |\ + grep 'GCC' | sed 's/\(.*(GCC) [-a-z0-9\. ]*\).*/\1/'` + ;; + *icpc*) + cxx_version_info=`$CXX $CXXFLAGS $H5_CXXFLAGS -V 2>&1 | grep 'Version' |\ + sed 's/\(Intel.* Compiler\).*\( Version [a-z0-9\.]*\).*\( Build [0-9]*\)/\1\2\3/'` + ;; + *pgCC*) + cxx_version_info=`$CXX $CXXFLAGS $H5_CXXFLAGS -V 2>&1 | grep 'pgCC'` + ;; + + + *) + echo "No match to get cxx_version_info for $CXX" + ;; +esac + diff --git a/config/lt_vers.am b/config/lt_vers.am index 71fa126..19b3066 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 = 63 +LT_VERS_REVISION = 65 LT_VERS_AGE = 0 ## If the API changes *at all*, increment LT_VERS_INTERFACE and diff --git a/config/solaris2.x b/config/solaris2.x index 5ef6415..cea71bd 100644 --- a/config/solaris2.x +++ b/config/solaris2.x @@ -111,3 +111,43 @@ if test -z "$cxx_flags_set"; then PROFILE_CPPFLAGS= cxx_flags_set=yes fi + +# compiler version strings +case $CC in + *cc*) + cc_version_info=`$CC $CFLAGS $H5_CFLAGS -V 2>&1 | grep 'Sun' |\ + sed 's/.*\(Sun.*\)/\1 /'` + ;; + + *) + echo "No match to get cc_version_info for $CC" + ;; +esac +echo "C compiler '$CC' is $cc_version_info" + +case $FC in + # The PGI and Intel compilers are automatically detected below + *f90*) + fc_version_info=`$FC $FCFLAGS $H5_FCFLAGS -V 2>&1 | grep 'Sun' |\ + sed 's/.*\(Sun.*\)/\1 /'` + ;; + + *) + echo "No match to get fc_version_info for $FC" + ;; +esac +echo "Fortran compiler '$FC' is $fc_version_info" + +# get c++ version info +case $CXX in + *CC*) + cxx_version_info=`$CXX $CXXFLAGS $H5_CXXFLAGS -V 2>&1 | grep 'Sun' |\ + sed 's/.*\(Sun.*\)/\1 /'` + ;; + + *) + echo "No match to get cxx_version_info for $CXX" + ;; +esac + + @@ -1,7 +1,7 @@ #! /bin/sh -# From configure.in Id: configure.in 18708 2010-05-05 17:18:50Z koziol . +# From configure.in Id: configure.in 19050 2010-07-06 19:45:35Z koziol . # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.65 for HDF5 1.9.73-FA_a4. +# Generated by GNU Autoconf 2.65 for HDF5 1.9.75-FA_a4. # # Report bugs to <help@hdfgroup.org>. # @@ -702,8 +702,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='HDF5' PACKAGE_TARNAME='hdf5' -PACKAGE_VERSION='1.9.73-FA_a4' -PACKAGE_STRING='HDF5 1.9.73-FA_a4' +PACKAGE_VERSION='1.9.75-FA_a4' +PACKAGE_STRING='HDF5 1.9.75-FA_a4' PACKAGE_BUGREPORT='help@hdfgroup.org' PACKAGE_URL='' @@ -768,6 +768,8 @@ HL_FOR HL DYNAMIC_DIRS ROOT +CXX_VERSION +FC_VERSION CC_VERSION WORDS_BIGENDIAN BYTESEX @@ -1574,7 +1576,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.73-FA_a4 to adapt to many kinds of systems. +\`configure' configures HDF5 1.9.75-FA_a4 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1644,7 +1646,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of HDF5 1.9.73-FA_a4:";; + short | recursive ) echo "Configuration of HDF5 1.9.75-FA_a4:";; esac cat <<\_ACEOF @@ -1830,7 +1832,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -HDF5 configure 1.9.73-FA_a4 +HDF5 configure 1.9.75-FA_a4 generated by GNU Autoconf 2.65 Copyright (C) 2009 Free Software Foundation, Inc. @@ -2914,7 +2916,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.73-FA_a4, which was +It was created by HDF5 $as_me 1.9.75-FA_a4, which was generated by GNU Autoconf 2.65. Invocation command line was $ $0 $@ @@ -3727,7 +3729,7 @@ fi # Define the identity of the package. PACKAGE='hdf5' - VERSION='1.9.73-FA_a4' + VERSION='1.9.75-FA_a4' cat >>confdefs.h <<_ACEOF @@ -7425,63 +7427,10 @@ $as_echo "none" >&6; } fi ;; - hcc) - PARALLEL=hcc - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mpirun_lam or mpirun" >&5 -$as_echo_n "checking for mpirun_lam or mpirun... " >&6; } - - cmd="`echo $CC | cut -f1 -d' '`" - if (echo $cmd | grep / >/dev/null); then - path="`echo $cmd | sed 's/\(.*\)\/.*$/\1/'`" - else - for path in `echo $PATH | ${TR} ":" " "`; do - if test -x $path/$cmd; then - break - fi - done - fi - - if test -x $path/mpirun_lam -o -x $path/mpirun; then - if test -x $path/mpirun_lam; then - cmd=mpirun_lam - else - cmd=mpirun - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $path/$cmd" >&5 -$as_echo "$path/$cmd" >&6; } - RUNSERIAL="${RUNSERIAL:-none}" - if test -z "$RUNPARALLEL"; then - RUNPARALLEL="$path/$cmd -np \$\${NPROCS:=3}" - fi - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 -$as_echo "none" >&6; } - fi - ;; - mpcc|mpcc_r) PARALLEL="$CC_BASENAME" ;; - cmpicc) - PARALLEL=cmpicc - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cmpirun" >&5 -$as_echo_n "checking for cmpirun... " >&6; } - - if test -x cmpirun; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: cmpirun" >&5 -$as_echo "cmpirun" >&6; } - RUNSERIAL="${RUNSERIAL:-none}" - - if test -z "$RUNPARALLEL"; then - RUNPARALLEL="cmpirun -np \$\${NPROCS:=3}" - fi - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 -$as_echo "none" >&6; } - fi - ;; - *) ;; esac @@ -8247,13 +8196,13 @@ if test "${lt_cv_nm_interface+set}" = set; then : else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext - (eval echo "\"\$as_me:8250: $ac_compile\"" >&5) + (eval echo "\"\$as_me:8199: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 - (eval echo "\"\$as_me:8253: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval echo "\"\$as_me:8202: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 - (eval echo "\"\$as_me:8256: output\"" >&5) + (eval echo "\"\$as_me:8205: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" @@ -9458,7 +9407,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 9461 "configure"' > conftest.$ac_ext + echo '#line 9410 "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -11777,11 +11726,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:11780: $lt_compile\"" >&5) + (eval echo "\"\$as_me:11729: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:11784: \$? = $ac_status" >&5 + echo "$as_me:11733: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -12116,11 +12065,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:12119: $lt_compile\"" >&5) + (eval echo "\"\$as_me:12068: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:12123: \$? = $ac_status" >&5 + echo "$as_me:12072: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -12221,11 +12170,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:12224: $lt_compile\"" >&5) + (eval echo "\"\$as_me:12173: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:12228: \$? = $ac_status" >&5 + echo "$as_me:12177: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -12276,11 +12225,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:12279: $lt_compile\"" >&5) + (eval echo "\"\$as_me:12228: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:12283: \$? = $ac_status" >&5 + echo "$as_me:12232: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -14707,7 +14656,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 14710 "configure" +#line 14659 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -14803,7 +14752,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 14806 "configure" +#line 14755 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -16775,11 +16724,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:16778: $lt_compile\"" >&5) + (eval echo "\"\$as_me:16727: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:16782: \$? = $ac_status" >&5 + echo "$as_me:16731: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -16874,11 +16823,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:16877: $lt_compile\"" >&5) + (eval echo "\"\$as_me:16826: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:16881: \$? = $ac_status" >&5 + echo "$as_me:16830: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -16926,11 +16875,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:16929: $lt_compile\"" >&5) + (eval echo "\"\$as_me:16878: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:16933: \$? = $ac_status" >&5 + echo "$as_me:16882: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -18443,11 +18392,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:18446: $lt_compile\"" >&5) + (eval echo "\"\$as_me:18395: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:18450: \$? = $ac_status" >&5 + echo "$as_me:18399: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -18542,11 +18491,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:18545: $lt_compile\"" >&5) + (eval echo "\"\$as_me:18494: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:18549: \$? = $ac_status" >&5 + echo "$as_me:18498: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -18594,11 +18543,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:18597: $lt_compile\"" >&5) + (eval echo "\"\$as_me:18546: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:18601: \$? = $ac_status" >&5 + echo "$as_me:18550: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -28260,8 +28209,44 @@ else fi done fi -if test -n "$cc_vendor" && test -n "$cc_version"; then - CC_VERSION="$CC_VERSION ($cc_vendor-$cc_version)" +if test -n "$cc_version_info"; then + CC_VERSION="$CC_VERSION ( $cc_version_info)" +fi + + +FC_NOFLAGS=`echo $FC | sed 's/ -.*//'` + +if `echo $FC_NOFLAGS | grep ^/ >/dev/null 2>&1`; then + FC_VERSION="$FC" +else + FC_VERSION="$FC"; + for x in `echo $PATH | sed -e 's/:/ /g'`; do + if test -x $x/$FC_NOFLAGS; then + FC_VERSION="$x/$FC" + break + fi + done +fi +if test -n "$fc_version_info"; then + FC_VERSION="$FC_VERSION ( $fc_version_info)" +fi + + +CXX_NOFLAGS=`echo $CXX | sed 's/ -.*//'` + +if `echo $CXX_NOFLAGS | grep ^/ >/dev/null 2>&1`; then + CXX_VERSION="$CXX" +else + CXX_VERSION="$FC"; + for x in `echo $PATH | sed -e 's/:/ /g'`; do + if test -x $x/$CXX_NOFLAGS; then + CXX_VERSION="$x/$CXX" + break + fi + done +fi +if test -n "$cxx_version_info"; then + CXX_VERSION="$CXX_VERSION ( $cxx_version_info)" fi if test -x /bin/pwd; then @@ -28630,7 +28615,7 @@ if test -n "$TESTPARALLEL"; then fi fi -ac_config_files="$ac_config_files src/libhdf5.settings Makefile src/Makefile test/Makefile test/testcheck_version.sh test/testerror.sh test/H5srcdir_str.h test/testlibinfo.sh testpar/Makefile testpar/testph5.sh perform/Makefile tools/Makefile tools/h5dump/Makefile tools/h5dump/testh5dump.sh tools/h5dump/testh5dumpxml.sh tools/h5ls/testh5ls.sh tools/h5import/Makefile tools/h5diff/Makefile tools/h5jam/Makefile tools/h5jam/testh5jam.sh tools/h5repack/Makefile tools/h5repack/h5repack.sh tools/h5ls/Makefile tools/h5copy/Makefile tools/lib/Makefile tools/misc/Makefile tools/misc/h5cc tools/misc/testh5repart.sh tools/h5stat/testh5stat.sh tools/h5stat/Makefile examples/Makefile examples/testh5cc.sh c++/Makefile c++/src/Makefile c++/src/h5c++ c++/test/Makefile c++/test/H5srcdir_str.h c++/examples/Makefile c++/examples/testh5c++.sh fortran/Makefile fortran/src/h5fc fortran/src/Makefile fortran/test/Makefile fortran/testpar/Makefile fortran/examples/Makefile fortran/examples/testh5fc.sh hl/Makefile hl/src/Makefile hl/test/Makefile hl/test/H5srcdir_str.h hl/tools/Makefile hl/tools/gif2h5/Makefile hl/examples/Makefile hl/c++/Makefile hl/c++/src/Makefile hl/c++/test/Makefile hl/c++/examples/Makefile hl/fortran/Makefile hl/fortran/src/Makefile hl/fortran/test/Makefile hl/fortran/examples/Makefile" +ac_config_files="$ac_config_files src/libhdf5.settings Makefile src/Makefile test/Makefile test/testcheck_version.sh test/testerror.sh test/H5srcdir_str.h test/testlibinfo.sh testpar/Makefile testpar/testph5.sh perform/Makefile tools/Makefile tools/h5dump/Makefile tools/h5dump/testh5dump.sh tools/h5dump/testh5dumpxml.sh tools/h5ls/testh5ls.sh tools/h5import/Makefile tools/h5diff/Makefile tools/h5jam/Makefile tools/h5jam/testh5jam.sh tools/h5repack/Makefile tools/h5repack/h5repack.sh tools/h5ls/Makefile tools/h5copy/Makefile tools/lib/Makefile tools/misc/Makefile tools/misc/h5cc tools/misc/testh5repart.sh tools/h5stat/testh5stat.sh tools/h5stat/Makefile examples/Makefile examples/run-c-ex.sh examples/testh5cc.sh c++/Makefile c++/src/Makefile c++/src/h5c++ c++/test/Makefile c++/test/H5srcdir_str.h c++/examples/Makefile c++/examples/run-c++-ex.sh c++/examples/testh5c++.sh fortran/Makefile fortran/src/h5fc fortran/src/Makefile fortran/test/Makefile fortran/testpar/Makefile fortran/examples/Makefile fortran/examples/run-fortran-ex.sh fortran/examples/testh5fc.sh hl/Makefile hl/src/Makefile hl/test/Makefile hl/test/H5srcdir_str.h hl/tools/Makefile hl/tools/gif2h5/Makefile hl/examples/Makefile hl/examples/run-hlc-ex.sh hl/c++/Makefile hl/c++/src/Makefile hl/c++/test/Makefile hl/c++/examples/Makefile hl/c++/examples/run-hlc++-ex.sh hl/fortran/Makefile hl/fortran/src/Makefile hl/fortran/test/Makefile hl/fortran/examples/Makefile hl/fortran/examples/run-hlfortran-ex.sh" cat >confcache <<\_ACEOF @@ -29211,7 +29196,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.73-FA_a4, which was +This file was extended by HDF5 $as_me 1.9.75-FA_a4, which was generated by GNU Autoconf 2.65. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -29277,7 +29262,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.73-FA_a4 +HDF5 config.status 1.9.75-FA_a4 configured by $0, generated by GNU Autoconf 2.65, with options \\"\$ac_cs_config\\" @@ -29871,6 +29856,7 @@ do "tools/h5stat/testh5stat.sh") CONFIG_FILES="$CONFIG_FILES tools/h5stat/testh5stat.sh" ;; "tools/h5stat/Makefile") CONFIG_FILES="$CONFIG_FILES tools/h5stat/Makefile" ;; "examples/Makefile") CONFIG_FILES="$CONFIG_FILES examples/Makefile" ;; + "examples/run-c-ex.sh") CONFIG_FILES="$CONFIG_FILES examples/run-c-ex.sh" ;; "examples/testh5cc.sh") CONFIG_FILES="$CONFIG_FILES examples/testh5cc.sh" ;; "c++/Makefile") CONFIG_FILES="$CONFIG_FILES c++/Makefile" ;; "c++/src/Makefile") CONFIG_FILES="$CONFIG_FILES c++/src/Makefile" ;; @@ -29878,6 +29864,7 @@ do "c++/test/Makefile") CONFIG_FILES="$CONFIG_FILES c++/test/Makefile" ;; "c++/test/H5srcdir_str.h") CONFIG_FILES="$CONFIG_FILES c++/test/H5srcdir_str.h" ;; "c++/examples/Makefile") CONFIG_FILES="$CONFIG_FILES c++/examples/Makefile" ;; + "c++/examples/run-c++-ex.sh") CONFIG_FILES="$CONFIG_FILES c++/examples/run-c++-ex.sh" ;; "c++/examples/testh5c++.sh") CONFIG_FILES="$CONFIG_FILES c++/examples/testh5c++.sh" ;; "fortran/Makefile") CONFIG_FILES="$CONFIG_FILES fortran/Makefile" ;; "fortran/src/h5fc") CONFIG_FILES="$CONFIG_FILES fortran/src/h5fc" ;; @@ -29885,6 +29872,7 @@ do "fortran/test/Makefile") CONFIG_FILES="$CONFIG_FILES fortran/test/Makefile" ;; "fortran/testpar/Makefile") CONFIG_FILES="$CONFIG_FILES fortran/testpar/Makefile" ;; "fortran/examples/Makefile") CONFIG_FILES="$CONFIG_FILES fortran/examples/Makefile" ;; + "fortran/examples/run-fortran-ex.sh") CONFIG_FILES="$CONFIG_FILES fortran/examples/run-fortran-ex.sh" ;; "fortran/examples/testh5fc.sh") CONFIG_FILES="$CONFIG_FILES fortran/examples/testh5fc.sh" ;; "hl/Makefile") CONFIG_FILES="$CONFIG_FILES hl/Makefile" ;; "hl/src/Makefile") CONFIG_FILES="$CONFIG_FILES hl/src/Makefile" ;; @@ -29893,14 +29881,17 @@ do "hl/tools/Makefile") CONFIG_FILES="$CONFIG_FILES hl/tools/Makefile" ;; "hl/tools/gif2h5/Makefile") CONFIG_FILES="$CONFIG_FILES hl/tools/gif2h5/Makefile" ;; "hl/examples/Makefile") CONFIG_FILES="$CONFIG_FILES hl/examples/Makefile" ;; + "hl/examples/run-hlc-ex.sh") CONFIG_FILES="$CONFIG_FILES hl/examples/run-hlc-ex.sh" ;; "hl/c++/Makefile") CONFIG_FILES="$CONFIG_FILES hl/c++/Makefile" ;; "hl/c++/src/Makefile") CONFIG_FILES="$CONFIG_FILES hl/c++/src/Makefile" ;; "hl/c++/test/Makefile") CONFIG_FILES="$CONFIG_FILES hl/c++/test/Makefile" ;; "hl/c++/examples/Makefile") CONFIG_FILES="$CONFIG_FILES hl/c++/examples/Makefile" ;; + "hl/c++/examples/run-hlc++-ex.sh") CONFIG_FILES="$CONFIG_FILES hl/c++/examples/run-hlc++-ex.sh" ;; "hl/fortran/Makefile") CONFIG_FILES="$CONFIG_FILES hl/fortran/Makefile" ;; "hl/fortran/src/Makefile") CONFIG_FILES="$CONFIG_FILES hl/fortran/src/Makefile" ;; "hl/fortran/test/Makefile") CONFIG_FILES="$CONFIG_FILES hl/fortran/test/Makefile" ;; "hl/fortran/examples/Makefile") CONFIG_FILES="$CONFIG_FILES hl/fortran/examples/Makefile" ;; + "hl/fortran/examples/run-hlfortran-ex.sh") CONFIG_FILES="$CONFIG_FILES hl/fortran/examples/run-hlfortran-ex.sh" ;; *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac diff --git a/configure.in b/configure.in index 7728fc3..4add00a 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.73-FA_a4], [help@hdfgroup.org]) +AC_INIT([HDF5], [1.9.75-FA_a4], [help@hdfgroup.org]) AC_CONFIG_SRCDIR([src/H5.c]) AM_CONFIG_HEADER([src/H5config.h]) @@ -741,65 +741,11 @@ case "$CC_BASENAME" in fi ;; - hcc) - dnl The LAM compiler. Use mpirun_lam or mpirun from the same directory - dnl if it exists. - PARALLEL=hcc - AC_MSG_CHECKING([for mpirun_lam or mpirun]) - - dnl Find the path where hcc is located - cmd="`echo $CC | cut -f1 -d' '`" - if (echo $cmd | grep / >/dev/null); then - path="`echo $cmd | sed 's/\(.*\)\/.*$/\1/'`" - else - for path in `echo $PATH | ${TR} ":" " "`; do - if test -x $path/$cmd; then - break - fi - done - fi - - dnl Is there an mpirun_lam or mpirun at that path? - if test -x $path/mpirun_lam -o -x $path/mpirun; then - if test -x $path/mpirun_lam; then - cmd=mpirun_lam - else - cmd=mpirun - fi - AC_MSG_RESULT([$path/$cmd]) - RUNSERIAL="${RUNSERIAL:-none}" - if test -z "$RUNPARALLEL"; then - RUNPARALLEL="$path/$cmd -np \$\${NPROCS:=3}" - fi - else - AC_MSG_RESULT([none]) - fi - ;; - mpcc|mpcc_r) dnl The IBM compiler PARALLEL="$CC_BASENAME" ;; - cmpicc) - dnl The ChaMPIon compiler on NCSA tungsten. The cmpirun command on tungsten - dnl isn't in the same path as cmpicc. - PARALLEL=cmpicc - AC_MSG_CHECKING([for cmpirun]) - - dnl Is there an cmpirun? - if test -x cmpirun; then - AC_MSG_RESULT([cmpirun]) - RUNSERIAL="${RUNSERIAL:-none}" - - if test -z "$RUNPARALLEL"; then - RUNPARALLEL="cmpirun -np \$\${NPROCS:=3}" - fi - else - AC_MSG_RESULT([none]) - fi - ;; - *) dnl Probably not a parallel compiler, but if `--enable-parallel' dnl is defined below then we're still building a parallel hdf5. @@ -3799,8 +3745,46 @@ else fi done fi -if test -n "$cc_vendor" && test -n "$cc_version"; then - CC_VERSION="$CC_VERSION ($cc_vendor-$cc_version)" +if test -n "$cc_version_info"; then + CC_VERSION="$CC_VERSION ( $cc_version_info)" +fi + +AC_SUBST([FC_VERSION]) +dnl Strip anything that looks like a flag off of $CC +FC_NOFLAGS=`echo $FC | sed 's/ -.*//'` + +if `echo $FC_NOFLAGS | grep ^/ >/dev/null 2>&1`; then + FC_VERSION="$FC" +else + FC_VERSION="$FC"; + for x in `echo $PATH | sed -e 's/:/ /g'`; do + if test -x $x/$FC_NOFLAGS; then + FC_VERSION="$x/$FC" + break + fi + done +fi +if test -n "$fc_version_info"; then + FC_VERSION="$FC_VERSION ( $fc_version_info)" +fi + +AC_SUBST([CXX_VERSION]) +dnl Strip anything that looks like a flag off of $CC +CXX_NOFLAGS=`echo $CXX | sed 's/ -.*//'` + +if `echo $CXX_NOFLAGS | grep ^/ >/dev/null 2>&1`; then + CXX_VERSION="$CXX" +else + CXX_VERSION="$FC"; + for x in `echo $PATH | sed -e 's/:/ /g'`; do + if test -x $x/$CXX_NOFLAGS; then + CXX_VERSION="$x/$CXX" + break + fi + done +fi +if test -n "$cxx_version_info"; then + CXX_VERSION="$CXX_VERSION ( $cxx_version_info)" fi dnl ---------------------------------------------------------------------- @@ -4158,6 +4142,7 @@ AC_CONFIG_FILES([src/libhdf5.settings tools/h5stat/testh5stat.sh tools/h5stat/Makefile examples/Makefile + examples/run-c-ex.sh examples/testh5cc.sh c++/Makefile c++/src/Makefile @@ -4165,6 +4150,7 @@ AC_CONFIG_FILES([src/libhdf5.settings c++/test/Makefile c++/test/H5srcdir_str.h c++/examples/Makefile + c++/examples/run-c++-ex.sh c++/examples/testh5c++.sh fortran/Makefile fortran/src/h5fc @@ -4172,6 +4158,7 @@ AC_CONFIG_FILES([src/libhdf5.settings fortran/test/Makefile fortran/testpar/Makefile fortran/examples/Makefile + fortran/examples/run-fortran-ex.sh fortran/examples/testh5fc.sh hl/Makefile hl/src/Makefile @@ -4180,14 +4167,17 @@ AC_CONFIG_FILES([src/libhdf5.settings hl/tools/Makefile hl/tools/gif2h5/Makefile hl/examples/Makefile + hl/examples/run-hlc-ex.sh hl/c++/Makefile hl/c++/src/Makefile hl/c++/test/Makefile hl/c++/examples/Makefile + hl/c++/examples/run-hlc++-ex.sh hl/fortran/Makefile hl/fortran/src/Makefile hl/fortran/test/Makefile - hl/fortran/examples/Makefile]) + hl/fortran/examples/Makefile + hl/fortran/examples/run-hlfortran-ex.sh]) AC_OUTPUT no_create=$saved_no_create diff --git a/examples/Makefile.am b/examples/Makefile.am index d3fe9c9..92830df 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -41,6 +41,10 @@ INSTALL_FILES = h5_write.c h5_read.c h5_extend_write.c h5_chunk_read.c \ h5_reference.c h5_drivers.c h5_extlink.c h5_elink_unix2win.c \ h5_ref2reg.c h5_shared_mesg.c ph5example.c +INSTALL_SCRIPT_FILES = run-c-ex.sh + +INSTALL_TOP_SCRIPT_FILES = run-all-ex.sh + # How to build examples, using installed version of h5cc if BUILD_PARALLEL_CONDITIONAL $(EXTRA_PROG): $(H5CC_PP) @@ -65,7 +69,8 @@ $(EXTLINK_DIRS): CHECK_CLEANFILES+=$(EXTLINK_DIRS) # Example directory -EXAMPLEDIR=$(docdir)/hdf5/examples/c +EXAMPLEDIR=${DESTDIR}/$(exec_prefix)/share/hdf5_examples/c +EXAMPLETOPDIR=${DESTDIR}/$(exec_prefix)/share/hdf5_examples # List dependencies for each program. Normally, automake would take # care of this for us, but if we tell automake about the programs it diff --git a/examples/Makefile.in b/examples/Makefile.in index 130aff9..7da3431 100644 --- a/examples/Makefile.in +++ b/examples/Makefile.in @@ -55,7 +55,8 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ - $(srcdir)/testh5cc.sh.in $(top_srcdir)/config/commence.am \ + $(srcdir)/run-c-ex.sh.in $(srcdir)/testh5cc.sh.in \ + $(top_srcdir)/config/commence.am \ $(top_srcdir)/config/conclude.am \ $(top_srcdir)/config/examples.am TESTS = @@ -66,7 +67,7 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/bin/mkinstalldirs CONFIG_HEADER = $(top_builddir)/src/H5config.h -CONFIG_CLEAN_FILES = testh5cc.sh +CONFIG_CLEAN_FILES = run-c-ex.sh testh5cc.sh CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = @@ -111,6 +112,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -136,6 +138,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ @@ -349,13 +352,16 @@ INSTALL_FILES = h5_write.c h5_read.c h5_extend_write.c h5_chunk_read.c \ h5_reference.c h5_drivers.c h5_extlink.c h5_elink_unix2win.c \ h5_ref2reg.c h5_shared_mesg.c ph5example.c +INSTALL_SCRIPT_FILES = run-c-ex.sh +INSTALL_TOP_SCRIPT_FILES = run-all-ex.sh # The external link examples demonstrate how to use paths; they need # directories to be created to do this. EXTLINK_DIRS = red blue u2w # Example directory -EXAMPLEDIR = $(docdir)/hdf5/examples/c +EXAMPLEDIR = ${DESTDIR}/$(exec_prefix)/share/hdf5_examples/c +EXAMPLETOPDIR = ${DESTDIR}/$(exec_prefix)/share/hdf5_examples # Assume that all tests in this directory are examples, and tell # conclude.am when to build them. @@ -414,6 +420,8 @@ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): +run-c-ex.sh: $(top_builddir)/config.status $(srcdir)/run-c-ex.sh.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ testh5cc.sh: $(top_builddir)/config.status $(srcdir)/testh5cc.sh.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ @@ -628,6 +636,8 @@ h5_shared_mesg: $(srcdir)/h5_shared_mesg.c # How to create EXAMPLEDIR if it doesn't already exist $(EXAMPLEDIR): -$(top_srcdir)/bin/mkdirs $@ +$(EXAMPLETOPDIR): + -$(top_srcdir)/bin/mkdirs $@ # Install and uninstall rules. We install the source files, not the # example programs themselves. @@ -642,10 +652,26 @@ install-examples: $(EXAMPLEDIR) $(INSTALL_FILES) (set -x; $(INSTALL) $(srcdir)/$$f $(EXAMPLEDIR)/. || exit 1);\ fi; \ done + @for f in X $(INSTALL_SCRIPT_FILES); do \ + if test $$f != X; then \ + (set -x; $(INSTALL) $$f $(EXAMPLEDIR)/. || exit 1);\ + fi; \ + done + @for f in X $(INSTALL_TOP_SCRIPT_FILES); do \ + if test $$f != X; then \ + (set -x; $(INSTALL) $(srcdir)/$$f $(EXAMPLETOPDIR)/. || exit 1); \ + fi; \ + done uninstall-examples: - @if test -n "$(INSTALL_FILES)" -a -d $(EXAMPLEDIR); then \ - set -x; cd $(EXAMPLEDIR) && $(RM) $(INSTALL_FILES); \ + @if test -n "$(INSTALL_FILES)" -a -d $(EXAMPLEDIR); then \ + set -x; cd $(EXAMPLEDIR) && $(RM) $(INSTALL_FILES); \ + fi + @if test -n "$(INSTALL_SCRIPT_FILES)" -a -d $(EXAMPLEDIR); then \ + set -x; cd $(EXAMPLEDIR) && $(RM) $(INSTALL_SCRIPT_FILES); \ + fi + @if test -n "$(INSTALL_TOP_SCRIPT_FILES)" -a -d $(EXAMPLETOPDIR); then \ + set -x; cd $(EXAMPLETOPDIR) && $(RM) $(INSTALL_TOP_SCRIPT_FILES); \ fi installcheck-local: diff --git a/examples/run-all-ex.sh b/examples/run-all-ex.sh new file mode 100755 index 0000000..e96b86f --- /dev/null +++ b/examples/run-all-ex.sh @@ -0,0 +1,40 @@ +#! /bin/sh +# +# Copyright by The HDF Group. +# 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. + +# +# This file: run-hl-ex.sh +# Written by: Larry Knox +# Date: May 11, 2010 +# +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # +# This script will run the scripts to compile and run the installed hdf5 # +# examples. # +# # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +if (echo "Run c examples" && \ + (cd c; sh ./run-c-ex.sh) && \ + echo "Run fortran examples" && \ + (cd fortran; sh ./run-fortran-ex.sh) && \ + echo "Run c++ examples" && \ + (cd c++; sh ./run-c++-ex.sh) && \ + echo "Run hl examples." && \ + (cd hl; sh ./run-hl-ex.sh)); then + echo "Done" + exit 0 +else + exit 1 +fi + diff --git a/examples/run-c-ex.sh.in b/examples/run-c-ex.sh.in new file mode 100755 index 0000000..09ff2fc --- /dev/null +++ b/examples/run-c-ex.sh.in @@ -0,0 +1,108 @@ +#! /bin/sh +# +# Copyright by The HDF Group. +# 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. + +# +# This file: run-c-ex.sh +# Written by: Larry Knox +# Date: May 11, 2010 +# +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # +# This script will compile and run the c examples from source files installed # +# in .../share/hdf5_examples/c using h5cc or h5pc. The order for running # +# programs with RunTest in the MAIN section below is taken from the Makefile. # +# The order is important since some of the test programs use data files created # +# by earlier test programs. Any future additions should be placed accordingly. # +# # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +# Initializations +EXIT_SUCCESS=0 +EXIT_FAILURE=1 + +# Where the tool is installed. +prefix="${prefix:-${DESTDIR}/@prefix@}" +PARALLEL=@PARALLEL@ # Am I in parallel mode? +AR="@AR@" +RANLIB="@RANLIB@" +if [ "$PARALLEL" = no ]; then + H5TOOL="h5cc" # The tool name +else + H5TOOL="h5pcc" # The tool name +fi +H5TOOL_BIN="${prefix}/bin/${H5TOOL}" # The path of the tool binary + +#### Run test #### +RunTest() +{ + Test=$1".c" + + echo + echo "################# $1 #################" + ${H5TOOL_BIN} $Test + if [ $? -ne 0 ] + then + echo "messed up compiling $Test" + exit 1 + fi + ./a.out +} + + + +################## MAIN ################## + +if ! test -d red; then + mkdir red +fi +if ! test -d blue; then + mkdir blue +fi +if ! test -d u2w; then + mkdir u2w +fi + +# Run tests +if [ $? -eq 0 ] +then + if (RunTest h5_write &&\ + RunTest h5_read &&\ + RunTest h5_extend_write &&\ + RunTest h5_chunk_read &&\ + RunTest h5_compound &&\ + RunTest h5_group &&\ + RunTest h5_select &&\ + RunTest h5_attribute &&\ + RunTest h5_mount &&\ + RunTest h5_reference &&\ + RunTest h5_drivers &&\ + RunTest h5_ref2reg &&\ + RunTest h5_extlink &&\ + RunTest h5_elink_unix2win &&\ + RunTest h5_shared_mesg); then + EXIT_VALUE=${EXIT_SUCCESS} + else + EXIT_VALUE=${EXIT_FAILURE} + fi +fi + +# Cleanup +rm a.out +rm *.o +rm *.h5 +rm -rf red blue u2w +echo + +exit $EXIT_VALUE + diff --git a/fortran/Makefile.in b/fortran/Makefile.in index be785e9..b772889 100644 --- a/fortran/Makefile.in +++ b/fortran/Makefile.in @@ -149,6 +149,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -174,6 +175,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ diff --git a/fortran/examples/Makefile.am b/fortran/examples/Makefile.am index 772cb13..f27f7ff 100644 --- a/fortran/examples/Makefile.am +++ b/fortran/examples/Makefile.am @@ -41,6 +41,7 @@ INSTALL_FILES=dsetexample.f90 fileexample.f90 rwdsetexample.f90 \ attrexample.f90 groupexample.f90 grpsexample.f90 grpdsetexample.f90 \ hyperslab.f90 selectele.f90 grpit.f90 refobjexample.f90 \ refregexample.f90 mountexample.f90 compound.f90 ph5example.f90 +INSTALL_SCRIPT_FILES = run-fortran-ex.sh # Mark this directory as part of the Fortran API FORTRAN_API=yes @@ -64,7 +65,7 @@ $(EXTRA_PROG): $(H5FC) endif # Tell automake how to install examples -EXAMPLEDIR=$(docdir)/hdf5/examples/fortran +EXAMPLEDIR=${DESTDIR}/$(exec_prefix)/share/hdf5_examples/fortran # List dependencies for each example. Normally, automake would take # care of this for us, but if we tell automake about the programs it diff --git a/fortran/examples/Makefile.in b/fortran/examples/Makefile.in index 2ac6630..25d3c9a 100644 --- a/fortran/examples/Makefile.in +++ b/fortran/examples/Makefile.in @@ -55,7 +55,8 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ - $(srcdir)/testh5fc.sh.in $(top_srcdir)/config/commence.am \ + $(srcdir)/run-fortran-ex.sh.in $(srcdir)/testh5fc.sh.in \ + $(top_srcdir)/config/commence.am \ $(top_srcdir)/config/conclude.am \ $(top_srcdir)/config/examples.am TESTS = @@ -66,7 +67,7 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/bin/mkinstalldirs CONFIG_HEADER = $(top_builddir)/src/H5config.h -CONFIG_CLEAN_FILES = testh5fc.sh +CONFIG_CLEAN_FILES = run-fortran-ex.sh testh5fc.sh CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = @@ -111,6 +112,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -136,6 +138,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ @@ -351,12 +354,13 @@ INSTALL_FILES = dsetexample.f90 fileexample.f90 rwdsetexample.f90 \ hyperslab.f90 selectele.f90 grpit.f90 refobjexample.f90 \ refregexample.f90 mountexample.f90 compound.f90 ph5example.f90 +INSTALL_SCRIPT_FILES = run-fortran-ex.sh # Mark this directory as part of the Fortran API FORTRAN_API = yes # Tell automake how to install examples -EXAMPLEDIR = $(docdir)/hdf5/examples/fortran +EXAMPLEDIR = ${DESTDIR}/$(exec_prefix)/share/hdf5_examples/fortran # Assume that all tests in this directory are examples, and tell # conclude.am when to build them. @@ -415,6 +419,8 @@ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): +run-fortran-ex.sh: $(top_builddir)/config.status $(srcdir)/run-fortran-ex.sh.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ testh5fc.sh: $(top_builddir)/config.status $(srcdir)/testh5fc.sh.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ @@ -626,6 +632,8 @@ ph5example: ph5example.f90 # How to create EXAMPLEDIR if it doesn't already exist $(EXAMPLEDIR): -$(top_srcdir)/bin/mkdirs $@ +$(EXAMPLETOPDIR): + -$(top_srcdir)/bin/mkdirs $@ # Install and uninstall rules. We install the source files, not the # example programs themselves. @@ -640,10 +648,26 @@ install-examples: $(EXAMPLEDIR) $(INSTALL_FILES) (set -x; $(INSTALL) $(srcdir)/$$f $(EXAMPLEDIR)/. || exit 1);\ fi; \ done + @for f in X $(INSTALL_SCRIPT_FILES); do \ + if test $$f != X; then \ + (set -x; $(INSTALL) $$f $(EXAMPLEDIR)/. || exit 1);\ + fi; \ + done + @for f in X $(INSTALL_TOP_SCRIPT_FILES); do \ + if test $$f != X; then \ + (set -x; $(INSTALL) $(srcdir)/$$f $(EXAMPLETOPDIR)/. || exit 1); \ + fi; \ + done uninstall-examples: - @if test -n "$(INSTALL_FILES)" -a -d $(EXAMPLEDIR); then \ - set -x; cd $(EXAMPLEDIR) && $(RM) $(INSTALL_FILES); \ + @if test -n "$(INSTALL_FILES)" -a -d $(EXAMPLEDIR); then \ + set -x; cd $(EXAMPLEDIR) && $(RM) $(INSTALL_FILES); \ + fi + @if test -n "$(INSTALL_SCRIPT_FILES)" -a -d $(EXAMPLEDIR); then \ + set -x; cd $(EXAMPLEDIR) && $(RM) $(INSTALL_SCRIPT_FILES); \ + fi + @if test -n "$(INSTALL_TOP_SCRIPT_FILES)" -a -d $(EXAMPLETOPDIR); then \ + set -x; cd $(EXAMPLETOPDIR) && $(RM) $(INSTALL_TOP_SCRIPT_FILES); \ fi installcheck-local: diff --git a/fortran/examples/run-fortran-ex.sh.in b/fortran/examples/run-fortran-ex.sh.in new file mode 100755 index 0000000..1564537 --- /dev/null +++ b/fortran/examples/run-fortran-ex.sh.in @@ -0,0 +1,98 @@ +#! /bin/sh +# +# Copyright by The HDF Group. +# 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. + +# +# This file: run-hlfortran-ex.sh +# Written by: Larry Knox +# Date: May 11, 2010 +# +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # +# This script will compile and run the fortran examples from source files # +# installed in .../share/hdf5_examples/fortran using h5fc or h5pfc. The # +# order for running programs with RunTest in the MAIN section below is taken # +# from the Makefile. The order is important since some of the test programs # +# use data files created by earlier test programs. Any future additions should # +# be placed accordingly. # +# # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +# Initializations +EXIT_SUCCESS=0 +EXIT_FAILURE=1 + +# Where the tool is installed. +prefix="${prefix:-${DESTDIR}/@prefix@}" +PARALLEL=@PARALLEL@ # Am I in parallel mode? +AR="@AR@" +RANLIB="@RANLIB@" +if [ "$PARALLEL" = no ]; then + H5TOOL="h5fc" # The tool name +else + H5TOOL="h5pfc" # The tool name +fi +H5TOOL_BIN="${prefix}/bin/${H5TOOL}" # The path of the tool binary + + +#### Run test #### +RunTest() +{ + Test=$1".f90" + + echo + echo "################# $1 #################" + ${H5TOOL_BIN} $Test + if [ $? -ne 0 ] + then + echo "messed up compiling $Test" + exit 1 + fi + ./a.out +} + + + +################## MAIN ################## + +# Run tests +if [ $? -eq 0 ] +then + if (RunTest dsetexample &&\ + RunTest fileexample &&\ + RunTest rwdsetexample &&\ + RunTest attrexample &&\ + RunTest groupexample &&\ + RunTest grpsexample &&\ + RunTest grpdsetexample &&\ + RunTest hyperslab &&\ + RunTest selectele &&\ + RunTest grpit &&\ + RunTest refobjexample &&\ + RunTest refregexample &&\ + RunTest mountexample &&\ + RunTest compound); then + EXIT_VALUE=${EXIT_SUCCESS} + else + EXIT_VALUE=${EXIT_FAILURE} + fi +fi + +# Cleanup +rm a.out +rm *.o +rm *.h5 +echo + +exit $EXIT_VALUE + diff --git a/fortran/src/Makefile.in b/fortran/src/Makefile.in index fe25387..aa474aa 100644 --- a/fortran/src/Makefile.in +++ b/fortran/src/Makefile.in @@ -201,6 +201,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -226,6 +227,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ @@ -424,7 +426,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 = 63 +LT_VERS_REVISION = 65 LT_VERS_AGE = 0 # Include src directory in both Fortran and C flags (C compiler is used diff --git a/fortran/test/Makefile.in b/fortran/test/Makefile.in index 515d66b..6ccba84 100644 --- a/fortran/test/Makefile.in +++ b/fortran/test/Makefile.in @@ -182,6 +182,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -207,6 +208,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ diff --git a/fortran/testpar/Makefile.in b/fortran/testpar/Makefile.in index 0a71e8b..c21be61 100644 --- a/fortran/testpar/Makefile.in +++ b/fortran/testpar/Makefile.in @@ -135,6 +135,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -160,6 +161,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ diff --git a/hl/Makefile.am b/hl/Makefile.am index d707557..3271575 100644 --- a/hl/Makefile.am +++ b/hl/Makefile.am @@ -43,7 +43,9 @@ DIST_SUBDIRS=src test tools c++ fortran examples # Install examples install-examples uninstall-examples: - @(cd examples && $(MAKE) $(AM_MAKEFLAGS) $@) || exit 1; + @@SETX@; for d in examples $(HDF5_INTERFACES); do \ + (cd $$d && $(MAKE) $(AM_MAKEFLAGS) $@) || exit 1; \ + done installcheck-local: @(cd examples && $(MAKE) $(AM_MAKEFLAGS) $@) || exit 1; diff --git a/hl/Makefile.in b/hl/Makefile.in index d44f082..99b9bb9 100755 --- a/hl/Makefile.in +++ b/hl/Makefile.in @@ -149,6 +149,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -174,6 +175,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ @@ -751,7 +753,9 @@ help: # Install examples install-examples uninstall-examples: - @(cd examples && $(MAKE) $(AM_MAKEFLAGS) $@) || exit 1; + @@SETX@; for d in examples $(HDF5_INTERFACES); do \ + (cd $$d && $(MAKE) $(AM_MAKEFLAGS) $@) || exit 1; \ + done installcheck-local: @(cd examples && $(MAKE) $(AM_MAKEFLAGS) $@) || exit 1; diff --git a/hl/c++/Makefile.in b/hl/c++/Makefile.in index 95b16b2..51a5d04 100644 --- a/hl/c++/Makefile.in +++ b/hl/c++/Makefile.in @@ -145,6 +145,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -170,6 +171,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ diff --git a/hl/c++/examples/Makefile.am b/hl/c++/examples/Makefile.am index 7ccc92b..da1580a 100644 --- a/hl/c++/examples/Makefile.am +++ b/hl/c++/examples/Makefile.am @@ -27,12 +27,13 @@ TEST_PROG=ptExampleFL ptExampleVL # These are the example files to be installed INSTALL_FILES=ptExampleFL.cpp ptExampleVL.cpp +INSTALL_SCRIPT_FILES = run-hlc++-ex.sh # Tell conclude.am that these are C++ tests. CXX_API=yes # Where to install examples -EXAMPLEDIR=$(docdir)/hdf5/examples/hl/c++ +EXAMPLEDIR=${DESTDIR}/$(exec_prefix)/share/hdf5_examples/hl/c++ # How to build programs using h5c++ $(EXTRA_PROG): $(H5CPP) diff --git a/hl/c++/examples/Makefile.in b/hl/c++/examples/Makefile.in index fd1a100..d178cb6 100644 --- a/hl/c++/examples/Makefile.in +++ b/hl/c++/examples/Makefile.in @@ -55,7 +55,7 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ - $(top_srcdir)/config/commence.am \ + $(srcdir)/run-hlc++-ex.sh.in $(top_srcdir)/config/commence.am \ $(top_srcdir)/config/conclude.am \ $(top_srcdir)/config/examples.am TESTS = @@ -66,7 +66,7 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/bin/mkinstalldirs CONFIG_HEADER = $(top_builddir)/src/H5config.h -CONFIG_CLEAN_FILES = +CONFIG_CLEAN_FILES = run-hlc++-ex.sh CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = @@ -111,6 +111,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -136,6 +137,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ @@ -337,12 +339,13 @@ TEST_PROG = ptExampleFL ptExampleVL # These are the example files to be installed INSTALL_FILES = ptExampleFL.cpp ptExampleVL.cpp +INSTALL_SCRIPT_FILES = run-hlc++-ex.sh # Tell conclude.am that these are C++ tests. CXX_API = yes # Where to install examples -EXAMPLEDIR = $(docdir)/hdf5/examples/hl/c++ +EXAMPLEDIR = ${DESTDIR}/$(exec_prefix)/share/hdf5_examples/hl/c++ # Assume that all tests in this directory are examples, and tell # conclude.am when to build them. @@ -401,6 +404,8 @@ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): +run-hlc++-ex.sh: $(top_builddir)/config.status $(srcdir)/run-hlc++-ex.sh.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ mostlyclean-libtool: -rm -f *.lo @@ -584,6 +589,8 @@ ptExampleVL: ptExampleVL.cpp # How to create EXAMPLEDIR if it doesn't already exist $(EXAMPLEDIR): -$(top_srcdir)/bin/mkdirs $@ +$(EXAMPLETOPDIR): + -$(top_srcdir)/bin/mkdirs $@ # Install and uninstall rules. We install the source files, not the # example programs themselves. @@ -598,10 +605,26 @@ install-examples: $(EXAMPLEDIR) $(INSTALL_FILES) (set -x; $(INSTALL) $(srcdir)/$$f $(EXAMPLEDIR)/. || exit 1);\ fi; \ done + @for f in X $(INSTALL_SCRIPT_FILES); do \ + if test $$f != X; then \ + (set -x; $(INSTALL) $$f $(EXAMPLEDIR)/. || exit 1);\ + fi; \ + done + @for f in X $(INSTALL_TOP_SCRIPT_FILES); do \ + if test $$f != X; then \ + (set -x; $(INSTALL) $(srcdir)/$$f $(EXAMPLETOPDIR)/. || exit 1); \ + fi; \ + done uninstall-examples: - @if test -n "$(INSTALL_FILES)" -a -d $(EXAMPLEDIR); then \ - set -x; cd $(EXAMPLEDIR) && $(RM) $(INSTALL_FILES); \ + @if test -n "$(INSTALL_FILES)" -a -d $(EXAMPLEDIR); then \ + set -x; cd $(EXAMPLEDIR) && $(RM) $(INSTALL_FILES); \ + fi + @if test -n "$(INSTALL_SCRIPT_FILES)" -a -d $(EXAMPLEDIR); then \ + set -x; cd $(EXAMPLEDIR) && $(RM) $(INSTALL_SCRIPT_FILES); \ + fi + @if test -n "$(INSTALL_TOP_SCRIPT_FILES)" -a -d $(EXAMPLETOPDIR); then \ + set -x; cd $(EXAMPLETOPDIR) && $(RM) $(INSTALL_TOP_SCRIPT_FILES); \ fi installcheck-local: diff --git a/hl/c++/examples/run-hlc++-ex.sh.in b/hl/c++/examples/run-hlc++-ex.sh.in new file mode 100755 index 0000000..4e6b1fb --- /dev/null +++ b/hl/c++/examples/run-hlc++-ex.sh.in @@ -0,0 +1,80 @@ +#! /bin/sh +# +# Copyright by The HDF Group. +# 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. + +# +# This file: run-hlc++-ex.sh +# Written by: Larry Knox +# Date: May 11, 2010 +# +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # +# This script will compile and run the c++ examples from source files # +# installed in .../share/hdf5_examples/hl/c++ using h5c++. The # +# order for running programs with RunTest in the MAIN section below is taken # +# from the Makefile. The order is important since some of the test programs # +# use data files created by earlier test programs. Any future additions should # +# be placed accordingly. # +# # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +# Initializations +EXIT_SUCCESS=0 +EXIT_FAILURE=1 + +# Where the tool is installed. +prefix="${prefix:-${DESTDIR}/@prefix@}" +AR="@AR@" +RANLIB="@RANLIB@" +H5TOOL="h5c++" # The tool name +H5TOOL_BIN="${prefix}/bin/${H5TOOL}" # The path of the tool binary + +#### Run test #### +RunTest() +{ + Test=$1".cpp" + + echo + echo "################# $1 #################" + ${H5TOOL_BIN} $Test + if [ $? -ne 0 ] + then + echo "messed up compiling $Test" + exit 1 + fi + ./a.out +} + + + +################## MAIN ################## + +# Run tests +if [ $? -eq 0 ] +then + if (RunTest ptExampleFL &&\ + RunTest ptExampleVL); then + EXIT_VALUE=${EXIT_SUCCESS} + else + EXIT_VALUE=${EXIT_FAILURE} + fi +fi + +# Cleanup +rm a.out +rm *.o +rm *.h5 +echo + +exit $EXIT_VALUE + diff --git a/hl/c++/src/Makefile.in b/hl/c++/src/Makefile.in index 325323a..9a88d4e 100644 --- a/hl/c++/src/Makefile.in +++ b/hl/c++/src/Makefile.in @@ -157,6 +157,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -182,6 +183,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ @@ -380,7 +382,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 = 63 +LT_VERS_REVISION = 65 LT_VERS_AGE = 0 # Include src directory diff --git a/hl/c++/test/Makefile.in b/hl/c++/test/Makefile.in index fc59115..decb2d6 100644 --- a/hl/c++/test/Makefile.in +++ b/hl/c++/test/Makefile.in @@ -131,6 +131,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -156,6 +157,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ diff --git a/hl/examples/Makefile.am b/hl/examples/Makefile.am index 9d601ee..64a29d4 100644 --- a/hl/examples/Makefile.am +++ b/hl/examples/Makefile.am @@ -26,7 +26,8 @@ if BUILD_PARALLEL_CONDITIONAL endif # Example directory -EXAMPLEDIR=$(docdir)/hdf5/examples/hl/c +EXAMPLEDIR=${DESTDIR}/$(exec_prefix)/share/hdf5_examples/hl/c +EXAMPLETOPDIR=${DESTDIR}/$(exec_prefix)/share/hdf5_examples/hl # Example programs. # Don't tell automake about them, because if it knew they were programs, @@ -41,7 +42,15 @@ TEST_PROG = ex_lite1 ex_lite2 ex_lite3 ptExampleFL ptExampleVL \ # Install files # List all file that should be installed in examples directory -INSTALL_FILES = ptExampleFL.c ptExampleVL.c +INSTALL_FILES = ex_lite1.c ex_lite2.c ex_lite3.c ptExampleFL.c ptExampleVL.c \ + ex_image1.c ex_image2.c \ + ex_table_01.c ex_table_02.c ex_table_03.c ex_table_04.c \ + ex_table_05.c ex_table_06.c ex_table_07.c ex_table_08.c \ + ex_table_09.c ex_table_10.c ex_table_11.c ex_table_12.c \ + ex_ds1.c image24pixel.txt image8.txt pal_rgb.h + +INSTALL_SCRIPT_FILES = run-hlc-ex.sh +INSTALL_TOP_SCRIPT_FILES = run-hl-ex.sh # Additional dependencies for each program are listed below. if BUILD_PARALLEL_CONDITIONAL diff --git a/hl/examples/Makefile.in b/hl/examples/Makefile.in index 2b18c3d..5f3e801 100644 --- a/hl/examples/Makefile.in +++ b/hl/examples/Makefile.in @@ -55,7 +55,7 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ - $(top_srcdir)/config/commence.am \ + $(srcdir)/run-hlc-ex.sh.in $(top_srcdir)/config/commence.am \ $(top_srcdir)/config/conclude.am \ $(top_srcdir)/config/examples.am TESTS = @@ -66,7 +66,7 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/bin/mkinstalldirs CONFIG_HEADER = $(top_builddir)/src/H5config.h -CONFIG_CLEAN_FILES = +CONFIG_CLEAN_FILES = run-hlc-ex.sh CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = @@ -111,6 +111,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -136,6 +137,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ @@ -333,7 +335,8 @@ CHECK_CLEANFILES = *.chkexe *.chklog *.clog *.h5 @BUILD_PARALLEL_CONDITIONAL_TRUE@TEST_PROG_PARA = # Example directory -EXAMPLEDIR = $(docdir)/hdf5/examples/hl/c +EXAMPLEDIR = ${DESTDIR}/$(exec_prefix)/share/hdf5_examples/hl/c +EXAMPLETOPDIR = ${DESTDIR}/$(exec_prefix)/share/hdf5_examples/hl # Example programs. # Don't tell automake about them, because if it knew they were programs, @@ -349,7 +352,15 @@ TEST_PROG = ex_lite1 ex_lite2 ex_lite3 ptExampleFL ptExampleVL \ # Install files # List all file that should be installed in examples directory -INSTALL_FILES = ptExampleFL.c ptExampleVL.c +INSTALL_FILES = ex_lite1.c ex_lite2.c ex_lite3.c ptExampleFL.c ptExampleVL.c \ + ex_image1.c ex_image2.c \ + ex_table_01.c ex_table_02.c ex_table_03.c ex_table_04.c \ + ex_table_05.c ex_table_06.c ex_table_07.c ex_table_08.c \ + ex_table_09.c ex_table_10.c ex_table_11.c ex_table_12.c \ + ex_ds1.c image24pixel.txt image8.txt pal_rgb.h + +INSTALL_SCRIPT_FILES = run-hlc-ex.sh +INSTALL_TOP_SCRIPT_FILES = run-hl-ex.sh # Assume that all tests in this directory are examples, and tell # conclude.am when to build them. @@ -408,6 +419,8 @@ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): +run-hlc-ex.sh: $(top_builddir)/config.status $(srcdir)/run-hlc-ex.sh.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ mostlyclean-libtool: -rm -f *.lo @@ -617,6 +630,8 @@ ex_table12: $(srcdir)/ex_table12.c # How to create EXAMPLEDIR if it doesn't already exist $(EXAMPLEDIR): -$(top_srcdir)/bin/mkdirs $@ +$(EXAMPLETOPDIR): + -$(top_srcdir)/bin/mkdirs $@ # Install and uninstall rules. We install the source files, not the # example programs themselves. @@ -631,10 +646,26 @@ install-examples: $(EXAMPLEDIR) $(INSTALL_FILES) (set -x; $(INSTALL) $(srcdir)/$$f $(EXAMPLEDIR)/. || exit 1);\ fi; \ done + @for f in X $(INSTALL_SCRIPT_FILES); do \ + if test $$f != X; then \ + (set -x; $(INSTALL) $$f $(EXAMPLEDIR)/. || exit 1);\ + fi; \ + done + @for f in X $(INSTALL_TOP_SCRIPT_FILES); do \ + if test $$f != X; then \ + (set -x; $(INSTALL) $(srcdir)/$$f $(EXAMPLETOPDIR)/. || exit 1); \ + fi; \ + done uninstall-examples: - @if test -n "$(INSTALL_FILES)" -a -d $(EXAMPLEDIR); then \ - set -x; cd $(EXAMPLEDIR) && $(RM) $(INSTALL_FILES); \ + @if test -n "$(INSTALL_FILES)" -a -d $(EXAMPLEDIR); then \ + set -x; cd $(EXAMPLEDIR) && $(RM) $(INSTALL_FILES); \ + fi + @if test -n "$(INSTALL_SCRIPT_FILES)" -a -d $(EXAMPLEDIR); then \ + set -x; cd $(EXAMPLEDIR) && $(RM) $(INSTALL_SCRIPT_FILES); \ + fi + @if test -n "$(INSTALL_TOP_SCRIPT_FILES)" -a -d $(EXAMPLETOPDIR); then \ + set -x; cd $(EXAMPLETOPDIR) && $(RM) $(INSTALL_TOP_SCRIPT_FILES); \ fi installcheck-local: diff --git a/hl/examples/run-hl-ex.sh b/hl/examples/run-hl-ex.sh new file mode 100755 index 0000000..0478f76 --- /dev/null +++ b/hl/examples/run-hl-ex.sh @@ -0,0 +1,36 @@ +#! /bin/sh +# +# Copyright by The HDF Group. +# 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. + +# +# This file: run-hl-ex.sh +# Written by: Larry Knox +# Date: May 11, 2010 +# +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # +# This script will run the scripts to compile and run the hdf5 hl examples. # +# # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +if (echo "Run hl c examples" && \ + (cd c; sh ./run-hlc-ex.sh) && \ + echo "Run hl fortran examples" && \ + (cd fortran; sh ./run-hlfortran-ex.sh) && \ + echo "Run hl c++ examples" && \ + (cd c++; sh ./run-hlc++-ex.sh)); then + echo "Finished running hl examples" + exit 0 +else + exit 1 +fi diff --git a/hl/examples/run-hlc-ex.sh.in b/hl/examples/run-hlc-ex.sh.in new file mode 100755 index 0000000..d66d9e0 --- /dev/null +++ b/hl/examples/run-hlc-ex.sh.in @@ -0,0 +1,102 @@ +#! /bin/sh +# +# Copyright by The HDF Group. +# 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. + +# +# This file: run-hlc-ex.sh +# Written by: Larry Knox +# Date: May 11, 2010 +# +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # +# This script will compile and run the c examples from source files installed # +# in .../share/hdf5_examples/hl/c using h5cc or h5pc. The order for running # +# programs with RunTest in the MAIN section below is taken from the Makefile. # +# The order is important since some of the test programs use data files created # +# by earlier test programs. Any future additions should be placed accordingly. # +# # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +# Initializations +EXIT_SUCCESS=0 +EXIT_FAILURE=1 + +# Where the tool is installed. +prefix="${prefix:-${DESTDIR}/@prefix@}" +PARALLEL=@PARALLEL@ # Am I in parallel mode? +AR="@AR@" +RANLIB="@RANLIB@" +if [ "$PARALLEL" = no ]; then + H5TOOL="h5cc" # The tool name +else + H5TOOL="h5pcc" # The tool name +fi +H5TOOL_BIN="${prefix}/bin/${H5TOOL}" # The path of the tool binary + +#### Run test #### +RunTest() +{ + Test=$1".c" + + echo + echo "################# $1 #################" + ${H5TOOL_BIN} $Test + if [ $? -ne 0 ] + then + echo "messed up compiling $Test" + exit 1 + fi + ./a.out +} + + + +################## MAIN ################## + +# Run tests +if [ $? -eq 0 ] +then + if (RunTest ex_lite1 &&\ + RunTest ex_lite2 &&\ + RunTest ex_lite3 &&\ + RunTest ptExampleFL &&\ + RunTest ptExampleVL &&\ + RunTest ex_image1 &&\ + RunTest ex_image2 &&\ + RunTest ex_table_01 &&\ + RunTest ex_table_02 &&\ + RunTest ex_table_03 &&\ + RunTest ex_table_04 &&\ + RunTest ex_table_05 && + RunTest ex_table_06 &&\ + RunTest ex_table_07 &&\ + RunTest ex_table_08 &&\ + RunTest ex_table_09 &&\ + RunTest ex_table_10 &&\ + RunTest ex_table_11 &&\ + RunTest ex_table_12 &&\ + RunTest ex_ds1); then + EXIT_VALUE=${EXIT_SUCCESS} + else + EXIT_VALUE=${EXIT_FAILURE} + fi +fi + +# Cleanup +rm a.out +rm *.o +rm *.h5 +echo + +exit $EXIT_VALUE + diff --git a/hl/fortran/Makefile.in b/hl/fortran/Makefile.in index c382dbd..76fea29 100644 --- a/hl/fortran/Makefile.in +++ b/hl/fortran/Makefile.in @@ -149,6 +149,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -174,6 +175,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ diff --git a/hl/fortran/examples/Makefile.am b/hl/fortran/examples/Makefile.am index d4775ac..acb4a02 100644 --- a/hl/fortran/examples/Makefile.am +++ b/hl/fortran/examples/Makefile.am @@ -34,7 +34,8 @@ endif TEST_PROG=exlite # List files to be installed here -INSTALL_FILES= +INSTALL_FILES= exlite.f90 +INSTALL_SCRIPT_FILES = run-hlfortran-ex.sh # Mark this directory as part of the Fortran API (this affects output # from tests in conclude.am) @@ -50,7 +51,7 @@ $(EXTRA_PROG): $(H5FC) endif # Tell automake how to install examples -EXAMPLEDIR=$(docdir)/hdf5/examples/hl/fortran +EXAMPLEDIR=${DESTDIR}/$(exec_prefix)/share/hdf5_examples/hl/fortran # List dependencies for each example. Normally, automake would take # care of this for us, but if we tell automake about the programs it diff --git a/hl/fortran/examples/Makefile.in b/hl/fortran/examples/Makefile.in index 5e5584f..366f42b 100644 --- a/hl/fortran/examples/Makefile.in +++ b/hl/fortran/examples/Makefile.in @@ -55,6 +55,7 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/run-hlfortran-ex.sh.in \ $(top_srcdir)/config/commence.am \ $(top_srcdir)/config/conclude.am \ $(top_srcdir)/config/examples.am @@ -66,7 +67,7 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/bin/mkinstalldirs CONFIG_HEADER = $(top_builddir)/src/H5config.h -CONFIG_CLEAN_FILES = +CONFIG_CLEAN_FILES = run-hlfortran-ex.sh CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = @@ -111,6 +112,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -136,6 +138,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ @@ -342,14 +345,15 @@ CHECK_CLEANFILES = *.chkexe *.chklog *.clog *.h5 TEST_PROG = exlite # List files to be installed here -INSTALL_FILES = +INSTALL_FILES = exlite.f90 +INSTALL_SCRIPT_FILES = run-hlfortran-ex.sh # Mark this directory as part of the Fortran API (this affects output # from tests in conclude.am) FORTRAN_API = yes # Tell automake how to install examples -EXAMPLEDIR = $(docdir)/hdf5/examples/hl/fortran +EXAMPLEDIR = ${DESTDIR}/$(exec_prefix)/share/hdf5_examples/hl/fortran # Assume that all tests in this directory are examples, and tell # conclude.am when to build them. @@ -408,6 +412,8 @@ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): +run-hlfortran-ex.sh: $(top_builddir)/config.status $(srcdir)/run-hlfortran-ex.sh.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ mostlyclean-libtool: -rm -f *.lo @@ -586,6 +592,8 @@ help: # How to create EXAMPLEDIR if it doesn't already exist $(EXAMPLEDIR): -$(top_srcdir)/bin/mkdirs $@ +$(EXAMPLETOPDIR): + -$(top_srcdir)/bin/mkdirs $@ # Install and uninstall rules. We install the source files, not the # example programs themselves. @@ -600,10 +608,26 @@ install-examples: $(EXAMPLEDIR) $(INSTALL_FILES) (set -x; $(INSTALL) $(srcdir)/$$f $(EXAMPLEDIR)/. || exit 1);\ fi; \ done + @for f in X $(INSTALL_SCRIPT_FILES); do \ + if test $$f != X; then \ + (set -x; $(INSTALL) $$f $(EXAMPLEDIR)/. || exit 1);\ + fi; \ + done + @for f in X $(INSTALL_TOP_SCRIPT_FILES); do \ + if test $$f != X; then \ + (set -x; $(INSTALL) $(srcdir)/$$f $(EXAMPLETOPDIR)/. || exit 1); \ + fi; \ + done uninstall-examples: - @if test -n "$(INSTALL_FILES)" -a -d $(EXAMPLEDIR); then \ - set -x; cd $(EXAMPLEDIR) && $(RM) $(INSTALL_FILES); \ + @if test -n "$(INSTALL_FILES)" -a -d $(EXAMPLEDIR); then \ + set -x; cd $(EXAMPLEDIR) && $(RM) $(INSTALL_FILES); \ + fi + @if test -n "$(INSTALL_SCRIPT_FILES)" -a -d $(EXAMPLEDIR); then \ + set -x; cd $(EXAMPLEDIR) && $(RM) $(INSTALL_SCRIPT_FILES); \ + fi + @if test -n "$(INSTALL_TOP_SCRIPT_FILES)" -a -d $(EXAMPLETOPDIR); then \ + set -x; cd $(EXAMPLETOPDIR) && $(RM) $(INSTALL_TOP_SCRIPT_FILES); \ fi installcheck-local: diff --git a/hl/fortran/examples/run-hlfortran-ex.sh.in b/hl/fortran/examples/run-hlfortran-ex.sh.in new file mode 100755 index 0000000..644a9b7 --- /dev/null +++ b/hl/fortran/examples/run-hlfortran-ex.sh.in @@ -0,0 +1,84 @@ +#! /bin/sh +# +# Copyright by The HDF Group. +# 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. + +# +# This file: run-hlfortran-ex.sh +# Written by: Larry Knox +# Date: May 11, 2010 +# +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # +# This script will compile and run the fortran examples from source files # +# installed in .../share/hdf5_examples/hl/fortran using h5fc or h5pfc. The # +# order for running programs with RunTest in the MAIN section below is taken # +# from the Makefile. The order is important since some of the test programs # +# use data files created by earlier test programs. Any future additions should # +# be placed accordingly. # +# # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +# Initializations +EXIT_SUCCESS=0 +EXIT_FAILURE=1 + +# Where the tool is installed. +prefix="${prefix:-${DESTDIR}/@prefix@}" +PARALLEL=@PARALLEL@ # Am I in parallel mode? +AR="@AR@" +RANLIB="@RANLIB@" +if [ "$PARALLEL" = no ]; then + H5TOOL="h5fc" # The tool name +else + H5TOOL="h5pfc" # The tool name +fi +H5TOOL_BIN="${prefix}/bin/${H5TOOL}" # The path of the tool binary + +#### Run test #### +RunTest() +{ + Test=$1".f90" + + echo + echo "################# $1 #################" + ${H5TOOL_BIN} $Test + if [ $? -ne 0 ] + then + echo "messed up compiling $Test" + exit 1 + fi + ./a.out +} + + + +################## MAIN ################## + +# Run tests +if [ $? -eq 0 ] +then + if (RunTest exlite); then + EXIT_VALUE=${EXIT_SUCCESS} + else + EXIT_VALUE=${EXIT_FAILURE} + fi +fi + +# Cleanup +rm a.out +rm *.o +rm *.h5 +echo + +exit $EXIT_VALUE + diff --git a/hl/fortran/src/Makefile.in b/hl/fortran/src/Makefile.in index bf1fe89..df7e6ef 100644 --- a/hl/fortran/src/Makefile.in +++ b/hl/fortran/src/Makefile.in @@ -166,6 +166,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -191,6 +192,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ @@ -389,7 +391,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 = 63 +LT_VERS_REVISION = 65 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/Makefile.in b/hl/fortran/test/Makefile.in index 1f73b79..7f9d48d 100644 --- a/hl/fortran/test/Makefile.in +++ b/hl/fortran/test/Makefile.in @@ -140,6 +140,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -165,6 +166,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ diff --git a/hl/src/Makefile.in b/hl/src/Makefile.in index e22494e..8fc14e0 100644 --- a/hl/src/Makefile.in +++ b/hl/src/Makefile.in @@ -157,6 +157,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -182,6 +183,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ @@ -380,7 +382,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 = 63 +LT_VERS_REVISION = 65 LT_VERS_AGE = 0 # This library is our main target. diff --git a/hl/test/Makefile.in b/hl/test/Makefile.in index a68831e..e2439b9 100644 --- a/hl/test/Makefile.in +++ b/hl/test/Makefile.in @@ -161,6 +161,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -186,6 +187,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ diff --git a/hl/tools/Makefile.in b/hl/tools/Makefile.in index f6d8563..0db2a25 100644 --- a/hl/tools/Makefile.in +++ b/hl/tools/Makefile.in @@ -146,6 +146,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -171,6 +172,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ diff --git a/hl/tools/gif2h5/Makefile.in b/hl/tools/gif2h5/Makefile.in index 70c78bf..cd60775 100644 --- a/hl/tools/gif2h5/Makefile.in +++ b/hl/tools/gif2h5/Makefile.in @@ -146,6 +146,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -171,6 +172,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ diff --git a/perform/Makefile.in b/perform/Makefile.in index f788e72..25a4766 100644 --- a/perform/Makefile.in +++ b/perform/Makefile.in @@ -182,6 +182,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -207,6 +208,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ diff --git a/release_docs/CMake.txt b/release_docs/CMake.txt index 8a9dd03..0e2f707 100755 --- a/release_docs/CMake.txt +++ b/release_docs/CMake.txt @@ -96,7 +96,7 @@ Notes: This short instruction is written for users who want to quickly build step on Windows. 5. The files that support building HDF5 with CMake are all the files in the - Resources folder, the CMakeLists.txt files in each source folder, and two + config/cmake folder, the CMakeLists.txt files in each source folder, and two additional files, ConfigureChecks.cmake and CTestConfig.cmake. The CTestConfig.cmake is specific to the internal testing performed by The HDF Group. It should be altered for the users installation and needs. diff --git a/release_docs/INSTALL_parallel b/release_docs/INSTALL_parallel index e8f8bad..04643b2 100644 --- a/release_docs/INSTALL_parallel +++ b/release_docs/INSTALL_parallel @@ -51,17 +51,21 @@ parallel HDF5 with one of the above, just set CC as it and configure. The "--enable-parallel" is optional in this case. $ CC=/usr/local/mpi/bin/mpicc ./configure --prefix=<install-directory> - $ make - $ make check + $ make # build the library + $ make check # verify the correctness + # Read the Details section about parallel tests. $ make install 2.2. IBM SP ----------- -Make sure your environment variables are set correctly to compile and execute -a single process mpi applications for the SP machine. Unfortunately, the -setting varies from machine to machine. E.g., the following works for the -IBM SP machine at LLNL. +During the build stage, the H5detect is compiled and executed to generate +the source file H5Tinit.c which is compiled as part of the HDF5 library. In +parallel mode, make sure your environment variables are set correctly to +execute a single process mpi application. Otherwise, multiple processes +attempt to write to the same H5Tinit.c file, resulting in a scrambled +source file. Unfortunately, the setting varies from machine to machine. +E.g., the following works for the IBM SP machine at LLNL. setenv MP_PROCS 1 setenv MP_NODES 1 @@ -104,6 +108,30 @@ Linux kernels 2.4 and greater. 2.4. Red Storm (Cray XT3) (for v1.8 and later) ------------------------- +Both serial and parallel HDF5 are supported in Red Storm. + +2.4.1 Building serial HDF5 for Red Storm +------------------------------------------ +The following steps are for building the serial HDF5 for the Red Storm +compute nodes. They would probably work for other Cray XT3 systems but have +not been verified. + +# Assume you already have a copy of HDF5 source code in directory `hdf5' and +# want to install the binary in directory `/project/hdf5/hdf5'. + +$ cd hdf5 +$ bin/yodconfigure configure +$ env RUNSERIAL="yod -sz 1" \ + CC=cc FC=ftn CXX=CC \ + ./configure --prefix=/project/hdf5/hdf5 +$ make +$ make check + +# if all is well, install the binary. +$ make install + +2.4.2 Building parallel HDF5 for Red Storm +------------------------------------------ The following steps are for building the Parallel HDF5 for the Red Storm compute nodes. They would probably work for other Cray XT3 systems but have not been verified. @@ -115,15 +143,47 @@ not been verified. $ cd hdf5 $ bin/yodconfigure configure $ env RUNSERIAL="yod -sz 1" RUNPARALLEL="yod -sz 3" \ - CC="mpicc -DRED_STORM" F9X=mpif90 \ - ./configure --disable-hl --without-zlib --disable-stream-vfd \ - --enable-parallel --prefix=/project/hdf5/phdf5 + CC=cc FC=ftn \ + ./configure --enable-parallel --prefix=/project/hdf5/phdf5 $ make $ make check # if all is well, install the binary. $ make install +2.4.3 Red Storm known problems +------------------------------ +For Red Storm, a Cray XT3 system, the yod command sometimes gives the +message, "yod allocation delayed for node recovery". This interferes with +test suites that do not expect seeing this message. To bypass this problem, +I launch the executables with a command shell script called "myyod" which +consists of the following lines. (You should set $RUNSERIAL and $RUNPARALLEL +to use myyod instead of yod.) +==== myyod ======= +#!/bin/sh +# sleep 2 seconds to allow time for the node recovery else it pops the +# message, +# yod allocation delayed for node recovery +sleep 2 +yod $* +==== end of myyod ======= + +For Red Storm, a Cray XT3 system, the tools/h5ls/testh5ls.sh will fail on +the test "Testing h5ls -w80 -r -g tgroup.h5" fails. This test is +expected to fail and exit with a non-zero code but the yod command does +not propagate the exit code of the executables. Yod always returns 0 if it +can launch the executable. The test suite shell expects a non-zero for +this particular test, therefore it concludes the test has failed when it +receives 0 from yod. To bypass this problem for now, change the following +lines in the tools/h5ls/testh5ls.sh. +======== Original ========= +# The following combination of arguments is expected to return an error message +# and return value 1 +TOOLTEST tgroup-1.ls 1 -w80 -r -g tgroup.h5 +======== Skip the test ========= +echo SKIP TOOLTEST tgroup-1.ls 1 -w80 -r -g tgroup.h5 +======== end of bypass ======== + 3. Detail explanation --------------------- @@ -169,10 +229,10 @@ For example, If a parallel library is being built then configure attempts to determine how to run a parallel application on one processor and on many processors. If the compiler is `mpicc' and the user hasn't specified values for RUNSERIAL and -RUNPARALLEL then configure chooses `mpirun' from the same directory as `mpicc': +RUNPARALLEL then configure chooses `mpiexec' from the same directory as `mpicc': - RUNSERIAL: /usr/local/mpi/bin/mpirun -np 1 - RUNPARALLEL: /usr/local/mpi/bin/mpirun -np $${NPROCS:=3} + RUNSERIAL: /usr/local/mpi/bin/mpiexec -np 1 + RUNPARALLEL: /usr/local/mpi/bin/mpiexec -np $${NPROCS:=3} The `$${NPROCS:=3}' will be substituted with the value of the NPROCS environment variable at the time `make check' is run (or the value 3). @@ -218,7 +278,7 @@ Appendix A. Sample programs --------------------------- Here are sample MPI-IO C and Fortran programs. You may use them to run simple tests of your MPI compilers and the parallel file system. The MPI commands -used here are mpicc, mpif90 and mpirun. Replace them with the commands of +used here are mpicc, mpif90 and mpiexec. Replace them with the commands of your system. The programs assume they run in the parallel file system. Thus they create @@ -229,10 +289,10 @@ programs to use a different file name. Example compiling and running: % mpicc Sample_mpio.c -o c.out -% mpirun -np 4 c.out +% mpiexec -np 4 c.out % mpif90 Sample_mpio.f90 -o f.out -% mpirun -np 4 f.out +% mpiexec -np 4 f.out ==> Sample_mpio.c <== diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index 3ea01a6..debc5ed 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -1,4 +1,4 @@ -HDF5 version 1.9.73-FA_a4 currently under development +HDF5 version 1.9.75-FA_a4 currently under development ================================================================================ @@ -164,6 +164,8 @@ New Features Tools: ------ + - h5ls: Add new flag --no-dangling-links. (refer to --help for details) + (JKM - 2010/06/15) - h5ls: Add new flag --follow-symlinks. (refer to --help for details) (JKM - 2010/05/25) - h5diff: Add new flag --no-dangling-links. (refer to --help for details) @@ -232,6 +234,10 @@ Bug Fixes since HDF5-1.8.0 release Library ------- + - Fixed a bug that could cause file corruption when using non-default + sizes of addresses and/or lengths. This bug could also cause + uncorrupted files with this property to be unreadable. This bug + was introduced in 1.8.5. (NAF - 2010/07/16 - 1951) - Fixed a file corruption bug that could happen when shrinking a compressed dataset. (NAF - 2010/05/20) - Fixed some memory leaks in VL datatype conversion when strings are @@ -380,6 +386,9 @@ Bug Fixes since HDF5-1.8.0 release Configuration ------------- + - Removed recognition of the parallel compilers of LAM(hcc) and + ChMPIon(cmpicc) since we have no access to these two MPI implementations + and cannot verify their correctness. (AKC - 2010/7/14 - Bug 1921) - Removed the following config files, as we no longer support them: config/dec-osf*, config/hpux11.00, config/irix5.x, config/powerpc-ibm-aix4.x config/rs6000-ibm-aix5.x config/unicos* @@ -125,14 +125,28 @@ static herr_t H5AC_check_if_write_permitted(const H5F_t *f, hid_t dxpl_id, hbool_t * write_permitted_ptr); -#ifdef H5_HAVE_PARALLEL -static herr_t H5AC_broadcast_clean_list(H5AC_t * cache_ptr); -#endif /* JRM */ - static herr_t H5AC_ext_config_2_int_config(H5AC_cache_config_t * ext_conf_ptr, H5C_auto_size_ctl_t * int_conf_ptr); #ifdef H5_HAVE_PARALLEL +static herr_t H5AC_broadcast_candidate_list(H5AC_t * cache_ptr, + int * num_entries_ptr, + haddr_t ** haddr_buf_ptr_ptr); + +static herr_t H5AC_broadcast_clean_list(H5AC_t * cache_ptr); + +static herr_t H5AC_construct_candidate_list(H5AC_t * cache_ptr, + H5AC_aux_t * aux_ptr, + int sync_point_op); + +static herr_t H5AC_copy_candidate_list_to_buffer(H5AC_t * cache_ptr, + int * num_entries_ptr, + haddr_t ** haddr_buf_ptr_ptr, + size_t * MPI_Offset_buf_size_ptr, + MPI_Offset ** MPI_Offset_buf_ptr_ptr); + +static herr_t H5AC_flush_entries(H5F_t *f); + static herr_t H5AC_log_deleted_entry(H5AC_t * cache_ptr, H5AC_info_t * entry_ptr, haddr_t addr, @@ -147,33 +161,55 @@ static herr_t H5AC_log_flushed_entry(H5C_t * cache_ptr, unsigned flags, int type_id); -#if 0 /* this is useful debugging code -- JRM */ -static herr_t H5AC_log_flushed_entry_dummy(H5C_t * cache_ptr, - haddr_t addr, - hbool_t was_dirty, - unsigned flags, - int type_id); -#endif /* JRM */ +static herr_t H5AC_log_moved_entry(const H5F_t * f, + haddr_t old_addr, + haddr_t new_addr); static herr_t H5AC_log_inserted_entry(H5F_t * f, H5AC_t * cache_ptr, H5AC_info_t * entry_ptr); +static herr_t H5AC_propagate_and_apply_candidate_list(H5F_t * f, + hid_t dxpl_id, + H5AC_t * cache_ptr); + static herr_t H5AC_propagate_flushed_and_still_clean_entries_list(H5F_t * f, hid_t dxpl_id, - H5AC_t * cache_ptr, - hbool_t do_barrier); + H5AC_t * cache_ptr); + +static herr_t H5AC_receive_candidate_list(H5AC_t * cache_ptr, + int * num_entries_ptr, + haddr_t ** haddr_buf_ptr_ptr); static herr_t H5AC_receive_and_apply_clean_list(H5F_t * f, hid_t primary_dxpl_id, hid_t secondary_dxpl_id, H5AC_t * cache_ptr); -static herr_t H5AC_log_moved_entry(const H5F_t * f, - haddr_t old_addr, - haddr_t new_addr); +static herr_t H5AC_tidy_cache_0_lists(H5AC_t * cache_ptr, + int num_candidates, + haddr_t * candidates_list_ptr); + +herr_t H5AC_rsp__dist_md_write__flush(H5F_t *f, + hid_t dxpl_id, + H5AC_t * cache_ptr); + +herr_t H5AC_rsp__dist_md_write__flush_to_min_clean(H5F_t *f, + hid_t dxpl_id, + H5AC_t * cache_ptr); + +herr_t H5AC_rsp__p0_only__flush(H5F_t *f, + hid_t dxpl_id, + H5AC_t * cache_ptr); + +herr_t H5AC_rsp__p0_only__flush_to_min_clean(H5F_t *f, + hid_t dxpl_id, + H5AC_t * cache_ptr); + +static herr_t H5AC_run_sync_point(H5F_t *f, + hid_t dxpl_id, + int sync_point_op); -static herr_t H5AC_flush_entries(H5F_t *f); #endif /* H5_HAVE_PARALLEL */ @@ -377,26 +413,6 @@ H5AC_term_interface(void) FUNC_LEAVE_NOAPI(n) } /* end H5AC_term_interface() */ - -/*------------------------------------------------------------------------- - * Function: H5AC_create - * - * Purpose: Initialize the cache just after a file is opened. The - * SIZE_HINT is the number of cache slots desired. If you - * pass an invalid value then H5AC_NSLOTS is used. You can - * turn off caching by using 1 for the SIZE_HINT value. - * - * Return: Success: Number of slots actually used. - * - * Failure: Negative - * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jul 9 1997 - * - *------------------------------------------------------------------------- - */ - static const char * H5AC_entry_type_names[H5AC_NTYPES] = { "B-tree nodes", @@ -429,19 +445,34 @@ static const char * H5AC_entry_type_names[H5AC_NTYPES] = "test entry" /* for testing only -- not used for actual files */ }; + +/*------------------------------------------------------------------------- + * Function: H5AC_create + * + * Purpose: Initialize the cache just after a file is opened. The + * SIZE_HINT is the number of cache slots desired. If you + * pass an invalid value then H5AC_NSLOTS is used. You can + * turn off caching by using 1 for the SIZE_HINT value. + * + * Return: Success: Number of slots actually used. + * + * Failure: Negative + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jul 9 1997 + * + *------------------------------------------------------------------------- + */ herr_t H5AC_create(const H5F_t *f, H5AC_cache_config_t *config_ptr) { - herr_t ret_value = SUCCEED; /* Return value */ - herr_t result; #ifdef H5_HAVE_PARALLEL char prefix[H5C__PREFIX_LEN] = ""; - MPI_Comm mpi_comm = MPI_COMM_NULL; - int mpi_rank = -1; - int mpi_size = -1; H5AC_aux_t * aux_ptr = NULL; #endif /* H5_HAVE_PARALLEL */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5AC_create, FAIL) @@ -451,97 +482,78 @@ H5AC_create(const H5F_t *f, HDcompile_assert(NELMTS(H5AC_entry_type_names) == H5AC_NTYPES); HDcompile_assert(H5C__MAX_NUM_TYPE_IDS == H5AC_NTYPES); - result = H5AC_validate_config(config_ptr); - - if ( result != SUCCEED ) { - - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Bad cache configuration"); - } + if(H5AC_validate_config(config_ptr) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Bad cache configuration") #ifdef H5_HAVE_PARALLEL - if ( IS_H5FD_MPI(f) ) { + if(IS_H5FD_MPI(f)) { + MPI_Comm mpi_comm; + int mpi_rank; + int mpi_size; - if ( (mpi_comm = H5F_mpi_get_comm(f)) == MPI_COMM_NULL ) { - - HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, \ - "can't get MPI communicator") - } - - if ( (mpi_rank = H5F_mpi_get_rank(f)) < 0 ) { + if(MPI_COMM_NULL == (mpi_comm = H5F_mpi_get_comm(f))) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't get MPI communicator") + if((mpi_rank = H5F_mpi_get_rank(f)) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't get mpi rank") - } - - if ( (mpi_size = H5F_mpi_get_size(f)) < 0 ) { + if((mpi_size = H5F_mpi_get_size(f)) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't get mpi size") - } /* There is no point in setting up the auxilary structure if size * is less than or equal to 1, as there will never be any processes * to broadcast the clean lists to. */ - if ( mpi_size > 1 ) { - - if ( NULL == (aux_ptr = H5FL_CALLOC(H5AC_aux_t)) ) { - - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \ - "Can't allocate H5AC auxilary structure.") - - } else { - - aux_ptr->magic = H5AC__H5AC_AUX_T_MAGIC; - aux_ptr->mpi_comm = mpi_comm; - aux_ptr->mpi_rank = mpi_rank; - aux_ptr->mpi_size = mpi_size; - aux_ptr->write_permitted = FALSE; - aux_ptr->dirty_bytes_threshold = - H5AC__DEFAULT_DIRTY_BYTES_THRESHOLD; - aux_ptr->dirty_bytes = 0; + if(mpi_size > 1) { + if(NULL == (aux_ptr = H5FL_CALLOC(H5AC_aux_t))) + HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "Can't allocate H5AC auxilary structure.") + + aux_ptr->magic = H5AC__H5AC_AUX_T_MAGIC; + aux_ptr->mpi_comm = mpi_comm; + aux_ptr->mpi_rank = mpi_rank; + aux_ptr->mpi_size = mpi_size; + aux_ptr->write_permitted = FALSE; + aux_ptr->dirty_bytes_threshold = H5AC__DEFAULT_DIRTY_BYTES_THRESHOLD; + aux_ptr->dirty_bytes = 0; + aux_ptr->metadata_write_strategy = H5AC__DEFAULT_METADATA_WRITE_STRATEGY; #if H5AC_DEBUG_DIRTY_BYTES_CREATION - aux_ptr->dirty_bytes_propagations = 0; - aux_ptr->unprotect_dirty_bytes = 0; - aux_ptr->unprotect_dirty_bytes_updates = 0; - aux_ptr->insert_dirty_bytes = 0; - aux_ptr->insert_dirty_bytes_updates = 0; - aux_ptr->move_dirty_bytes = 0; - aux_ptr->move_dirty_bytes_updates = 0; + aux_ptr->dirty_bytes_propagations = 0; + aux_ptr->unprotect_dirty_bytes = 0; + aux_ptr->unprotect_dirty_bytes_updates = 0; + aux_ptr->insert_dirty_bytes = 0; + aux_ptr->insert_dirty_bytes_updates = 0; + aux_ptr->move_dirty_bytes = 0; + aux_ptr->move_dirty_bytes_updates = 0; #endif /* H5AC_DEBUG_DIRTY_BYTES_CREATION */ - aux_ptr->d_slist_ptr = NULL; - aux_ptr->d_slist_len = 0; - aux_ptr->c_slist_ptr = NULL; - aux_ptr->c_slist_len = 0; - aux_ptr->write_done = NULL; - - sprintf(prefix, "%d:", mpi_rank); - } - - if ( mpi_rank == 0 ) { - - aux_ptr->d_slist_ptr = - H5SL_create(H5SL_TYPE_HADDR); - - if ( aux_ptr->d_slist_ptr == NULL ) { - - HGOTO_ERROR(H5E_CACHE, H5E_CANTCREATE, FAIL, - "can't create dirtied entry list.") - } - - aux_ptr->c_slist_ptr = - H5SL_create(H5SL_TYPE_HADDR); - - if ( aux_ptr->c_slist_ptr == NULL ) { - - HGOTO_ERROR(H5E_CACHE, H5E_CANTCREATE, FAIL, - "can't create cleaned entry list.") - } - } - } - - if ( aux_ptr != NULL ) { + aux_ptr->d_slist_ptr = NULL; + aux_ptr->d_slist_len = 0; + aux_ptr->c_slist_ptr = NULL; + aux_ptr->c_slist_len = 0; + aux_ptr->candidate_slist_ptr = NULL; + aux_ptr->candidate_slist_len = 0; + aux_ptr->write_done = NULL; + aux_ptr->sync_point_done = NULL; + + sprintf(prefix, "%d:", mpi_rank); + + if(mpi_rank == 0) { + if(NULL == (aux_ptr->d_slist_ptr = H5SL_create(H5SL_TYPE_HADDR))) + HGOTO_ERROR(H5E_CACHE, H5E_CANTCREATE, FAIL, "can't create dirtied entry list.") + + if(NULL == (aux_ptr->c_slist_ptr = H5SL_create(H5SL_TYPE_HADDR))) + HGOTO_ERROR(H5E_CACHE, H5E_CANTCREATE, FAIL, "can't create cleaned entry list.") + } /* end if */ - if ( aux_ptr->mpi_rank == 0 ) { + /* construct the candidate slist for all processes. + * when the distributed strategy is selected as all processes + * will use it in the case of a flush. + */ + if(NULL == (aux_ptr->candidate_slist_ptr = H5SL_create(H5SL_TYPE_HADDR))) + HGOTO_ERROR(H5E_CACHE, H5E_CANTCREATE, FAIL, "can't create candidate entry list.") + } /* end if */ + if(aux_ptr != NULL) { + if(aux_ptr->mpi_rank == 0) { f->shared->cache = H5C_create(H5AC__DEFAULT_MAX_CACHE_SIZE, H5AC__DEFAULT_MIN_CLEAN_SIZE, (H5AC_NTYPES - 1), @@ -550,25 +562,17 @@ H5AC_create(const H5F_t *f, TRUE, H5AC_log_flushed_entry, (void *)aux_ptr); - } else { - f->shared->cache = H5C_create(H5AC__DEFAULT_MAX_CACHE_SIZE, H5AC__DEFAULT_MIN_CLEAN_SIZE, (H5AC_NTYPES - 1), (const char **)H5AC_entry_type_names, + H5AC_check_if_write_permitted, + TRUE, NULL, - FALSE, -#if 0 /* this is useful debugging code -- keep it for a while */ /* JRM */ - H5AC_log_flushed_entry_dummy, -#else /* JRM */ - NULL, -#endif /* JRM */ (void *)aux_ptr); } - } else { - f->shared->cache = H5C_create(H5AC__DEFAULT_MAX_CACHE_SIZE, H5AC__DEFAULT_MIN_CLEAN_SIZE, (H5AC_NTYPES - 1), @@ -596,61 +600,40 @@ H5AC_create(const H5F_t *f, } #endif /* H5_HAVE_PARALLEL */ - if ( NULL == f->shared->cache ) { - + if(NULL == f->shared->cache) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") - } #ifdef H5_HAVE_PARALLEL - else if ( aux_ptr != NULL ) { - - result = H5C_set_prefix(f->shared->cache, prefix); - - if ( result != SUCCEED ) { - - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \ - "H5C_set_prefix() failed") - } - } + if(aux_ptr != NULL) { + if(H5C_set_prefix(f->shared->cache, prefix) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "H5C_set_prefix() failed") + } /* end if */ #endif /* H5_HAVE_PARALLEL */ - result = H5AC_set_cache_auto_resize_config(f->shared->cache, config_ptr); - - if ( result != SUCCEED ) { - - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \ - "auto resize configuration failed") - } + if(H5AC_set_cache_auto_resize_config(f->shared->cache, config_ptr) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "auto resize configuration failed") done: - #ifdef H5_HAVE_PARALLEL - /* if there is a failure, try to tidy up the auxilary structure */ - - if ( ret_value != SUCCEED ) { - - if ( aux_ptr != NULL ) { - - if ( aux_ptr->d_slist_ptr != NULL ) { - + if(ret_value < 0) { + if(aux_ptr != NULL) { + if(aux_ptr->d_slist_ptr != NULL) H5SL_close(aux_ptr->d_slist_ptr); - } - - if ( aux_ptr->c_slist_ptr != NULL ) { + if(aux_ptr->c_slist_ptr != NULL) H5SL_close(aux_ptr->c_slist_ptr); - } + + if(aux_ptr->candidate_slist_ptr != NULL) + H5SL_close(aux_ptr->candidate_slist_ptr); aux_ptr->magic = 0; - H5FL_FREE(H5AC_aux_t, aux_ptr); - aux_ptr = NULL; - } - } + aux_ptr = H5FL_FREE(H5AC_aux_t, aux_ptr); + } /* end if */ + } /* end if */ #endif /* H5_HAVE_PARALLEL */ FUNC_LEAVE_NOAPI(ret_value) - } /* H5AC_create() */ @@ -694,7 +677,7 @@ H5AC_dest(H5F_t *f, hid_t dxpl_id) #endif /* H5AC__TRACE_FILE_ENABLED */ #ifdef H5_HAVE_PARALLEL - aux_ptr = f->shared->cache->aux_ptr; + aux_ptr = (struct H5AC_aux_t *)(f->shared->cache->aux_ptr); if(aux_ptr) /* Sanity check */ HDassert(aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC); @@ -715,6 +698,8 @@ H5AC_dest(H5F_t *f, hid_t dxpl_id) H5SL_close(aux_ptr->d_slist_ptr); if(aux_ptr->c_slist_ptr != NULL) H5SL_close(aux_ptr->c_slist_ptr); + if(aux_ptr->candidate_slist_ptr != NULL) + H5SL_close(aux_ptr->candidate_slist_ptr); aux_ptr->magic = 0; H5FL_FREE(H5AC_aux_t, aux_ptr); aux_ptr = NULL; @@ -903,8 +888,6 @@ H5AC_get_entry_status(const H5F_t *f, haddr_t addr, unsigned * status_ptr) { - H5C_t *cache_ptr = f->shared->cache; - herr_t result; hbool_t in_cache; hbool_t is_dirty; hbool_t is_protected; @@ -917,50 +900,31 @@ H5AC_get_entry_status(const H5F_t *f, FUNC_ENTER_NOAPI(H5AC_get_entry_status, FAIL) - if ( ( cache_ptr == NULL ) || - ( cache_ptr->magic != H5C__H5C_T_MAGIC ) || - ( ! H5F_addr_defined(addr) ) || - ( status_ptr == NULL ) ) { - + if((f == NULL) || (!H5F_addr_defined(addr)) || (status_ptr == NULL)) HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Bad param(s) on entry.") - } - - result = H5C_get_entry_status(f, addr, &entry_size, &in_cache, - &is_dirty, &is_protected, &is_pinned, &is_flush_dep_parent, - &is_flush_dep_child); - - if ( result < 0 ) { - - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ - "H5C_get_entry_status() failed.") - } - if ( in_cache ) { + if(H5C_get_entry_status(f, addr, &entry_size, &in_cache, &is_dirty, + &is_protected, &is_pinned, &is_flush_dep_parent, &is_flush_dep_child) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5C_get_entry_status() failed.") + if(in_cache) { status |= H5AC_ES__IN_CACHE; - - if ( is_dirty ) + if(is_dirty) status |= H5AC_ES__IS_DIRTY; - - if ( is_protected ) + if(is_protected) status |= H5AC_ES__IS_PROTECTED; - - if ( is_pinned ) + if(is_pinned) status |= H5AC_ES__IS_PINNED; - - if ( is_flush_dep_parent ) + if(is_flush_dep_parent) status |= H5AC_ES__IS_FLUSH_DEP_PARENT; - - if ( is_flush_dep_child ) + if(is_flush_dep_child) status |= H5AC_ES__IS_FLUSH_DEP_CHILD; - } + } /* end if */ *status_ptr = status; done: - FUNC_LEAVE_NOAPI(ret_value) - } /* H5AC_get_entry_status() */ @@ -983,9 +947,6 @@ herr_t H5AC_set(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr, void *thing, unsigned int flags) { -#ifdef H5_HAVE_PARALLEL - H5AC_aux_t * aux_ptr = NULL; -#endif /* H5_HAVE_PARALLEL */ #if H5AC__TRACE_FILE_ENABLED char trace[128] = ""; size_t trace_entry_size = 0; @@ -1041,26 +1002,20 @@ H5AC_set(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr, #endif /* H5AC__TRACE_FILE_ENABLED */ #ifdef H5_HAVE_PARALLEL - if(NULL != (aux_ptr = f->shared->cache->aux_ptr)) { +{ + H5AC_aux_t *aux_ptr; + + if(NULL != (aux_ptr = (H5AC_aux_t *)f->shared->cache->aux_ptr)) { + /* Log the new entry */ if(H5AC_log_inserted_entry(f, f->shared->cache, (H5AC_info_t *)thing) < 0) HGOTO_ERROR(H5E_CACHE, H5E_CANTINS, FAIL, "H5AC_log_inserted_entry() failed") /* Check if we should try to flush */ - if(aux_ptr->dirty_bytes >= aux_ptr->dirty_bytes_threshold) { - hbool_t evictions_enabled; - - /* Query if evictions are allowed */ - if(H5C_get_evictions_enabled((const H5C_t *)f->shared->cache, &evictions_enabled) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, FAIL, "H5C_get_evictions_enabled() failed.") - - /* Flush if evictions are allowed */ - if(evictions_enabled) { - if(H5AC_propagate_flushed_and_still_clean_entries_list(f, - H5AC_noblock_dxpl_id, f->shared->cache, TRUE) < 0 ) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't propagate clean entries list.") - } /* end if */ - } /* end if */ + if(aux_ptr->dirty_bytes >= aux_ptr->dirty_bytes_threshold) + if(H5AC_run_sync_point(f, H5AC_noblock_dxpl_id, H5AC_SYNC_POINT_OP__FLUSH_TO_MIN_CLEAN) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't run sync point.") } /* end if */ +} #endif /* H5_HAVE_PARALLEL */ done: @@ -1109,7 +1064,7 @@ H5AC_mark_entry_dirty(void *thing) * occult errors. */ if((H5C_get_trace_file_ptr_from_entry(thing, &trace_file_ptr) >= 0) && - (NULL != trace_file_ptr)) + (NULL != trace_file_ptr)) sprintf(trace, "%s 0x%lx", FUNC, (unsigned long)(((H5C_cache_entry_t *)thing)->addr)); #endif /* H5AC__TRACE_FILE_ENABLED */ @@ -1160,15 +1115,14 @@ done: herr_t H5AC_move_entry(H5F_t *f, const H5AC_class_t *type, haddr_t old_addr, haddr_t new_addr) { - herr_t result; - herr_t ret_value=SUCCEED; /* Return value */ -#ifdef H5_HAVE_PARALLEL - H5AC_aux_t * aux_ptr = NULL; -#endif /* H5_HAVE_PARALLEL */ #if H5AC__TRACE_FILE_ENABLED char trace[128] = ""; FILE * trace_file_ptr = NULL; #endif /* H5AC__TRACE_FILE_ENABLED */ +#ifdef H5_HAVE_PARALLEL + H5AC_aux_t * aux_ptr; +#endif /* H5_HAVE_PARALLEL */ + herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5AC_move_entry, FAIL) @@ -1198,52 +1152,31 @@ H5AC_move_entry(H5F_t *f, const H5AC_class_t *type, haddr_t old_addr, haddr_t ne #endif /* H5AC__TRACE_FILE_ENABLED */ #ifdef H5_HAVE_PARALLEL - if ( NULL != (aux_ptr = f->shared->cache->aux_ptr) ) { + /* Log moving the entry */ + if(NULL != (aux_ptr = (H5AC_aux_t *)f->shared->cache->aux_ptr)) { if(H5AC_log_moved_entry(f, old_addr, new_addr) < 0) HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "can't log moved entry") - } + } /* end if */ #endif /* H5_HAVE_PARALLEL */ - result = H5C_move_entry(f->shared->cache, - type, - old_addr, - new_addr); - - if ( result < 0 ) { - - HGOTO_ERROR(H5E_CACHE, H5E_CANTMOVE, FAIL, \ - "H5C_move_entry() failed.") - } + if(H5C_move_entry(f->shared->cache, type, old_addr, new_addr) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTMOVE, FAIL, "H5C_move_entry() failed.") #ifdef H5_HAVE_PARALLEL /* Check if we should try to flush */ - if(aux_ptr && (aux_ptr->dirty_bytes >= aux_ptr->dirty_bytes_threshold)) { - hbool_t evictions_enabled; - - /* Query if evictions are allowed */ - if(H5C_get_evictions_enabled((const H5C_t *)f->shared->cache, &evictions_enabled) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, FAIL, "H5C_get_evictions_enabled() failed.") - - /* Flush if evictions are allowed */ - if(evictions_enabled) { - if(H5AC_propagate_flushed_and_still_clean_entries_list(f, - H5AC_noblock_dxpl_id, f->shared->cache, TRUE) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't propagate clean entries list.") - } /* end if */ + if(NULL != aux_ptr && aux_ptr->dirty_bytes >= aux_ptr->dirty_bytes_threshold) { + if(H5AC_run_sync_point(f, H5AC_noblock_dxpl_id, H5AC_SYNC_POINT_OP__FLUSH_TO_MIN_CLEAN) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't run sync point.") } /* end if */ #endif /* H5_HAVE_PARALLEL */ done: - #if H5AC__TRACE_FILE_ENABLED - if ( trace_file_ptr != NULL ) { - + if(trace_file_ptr != NULL) HDfprintf(trace_file_ptr, "%s %d\n", trace, (int)ret_value); - } #endif /* H5AC__TRACE_FILE_ENABLED */ FUNC_LEAVE_NOAPI(ret_value) - } /* H5AC_move_entry() */ @@ -1332,7 +1265,6 @@ H5AC_create_flush_dependency(void * parent_thing, void * child_thing) FUNC, (unsigned long)(((H5C_cache_entry_t *)parent_thing)->addr), (unsigned long)(((H5C_cache_entry_t *)child_thing)->addr)); - } /* end if */ #endif /* H5AC__TRACE_FILE_ENABLED */ if(H5C_create_flush_dependency(parent_thing, child_thing) < 0) @@ -1382,12 +1314,12 @@ H5AC_protect(H5F_t *f, { unsigned protect_flags = H5C__NO_FLAGS_SET; void * thing = (void *)NULL; - void * ret_value; /* Return value */ #if H5AC__TRACE_FILE_ENABLED char trace[128] = ""; size_t trace_entry_size = 0; FILE * trace_file_ptr = NULL; #endif /* H5AC__TRACE_FILE_ENABLED */ + void * ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5AC_protect, NULL) @@ -1416,7 +1348,7 @@ H5AC_protect(H5F_t *f, ( H5C_get_trace_file_ptr(f->shared->cache, &trace_file_ptr) >= 0) && ( trace_file_ptr != NULL ) ) { - char * rw_string; + const char * rw_string; if ( rw == H5AC_WRITE ) { @@ -1628,12 +1560,11 @@ H5AC_destroy_flush_dependency(void * parent_thing, void * child_thing) #if H5AC__TRACE_FILE_ENABLED if((H5C_get_trace_file_ptr_from_entry(parent_thing, &trace_file_ptr) >= 0) && - (NULL != trace_file_ptr)) - sprintf(trace, "%s %lx", + (NULL != trace_file_ptr)) + sprintf(trace, "%s %llx %llx", FUNC, - (unsigned long)(((H5C_cache_entry_t *)parent_thing)->addr), - (unsigned long)(((H5C_cache_entry_t *)child_thing)->addr)); - } /* end if */ + (unsigned long long)(((H5C_cache_entry_t *)parent_thing)->addr), + (unsigned long long)(((H5C_cache_entry_t *)child_thing)->addr)); #endif /* H5AC__TRACE_FILE_ENABLED */ if(H5C_destroy_flush_dependency(parent_thing, child_thing) < 0) @@ -1641,7 +1572,7 @@ H5AC_destroy_flush_dependency(void * parent_thing, void * child_thing) done: #if H5AC__TRACE_FILE_ENABLED - if( trace_file_ptr != NULL ) + if(trace_file_ptr != NULL) HDfprintf(trace_file_ptr, "%s %d\n", trace, (int)ret_value); #endif /* H5AC__TRACE_FILE_ENABLED */ @@ -1691,7 +1622,6 @@ herr_t H5AC_unprotect(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr, void *thing, unsigned flags) { - herr_t result; hbool_t dirtied; hbool_t deleted; #ifdef H5_HAVE_PARALLEL @@ -1741,93 +1671,92 @@ H5AC_unprotect(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr, /* Check if the size changed out from underneath us, if we're not deleting * the entry. */ - if ( dirtied && !deleted ) { + if(dirtied && !deleted) { size_t curr_size = 0; - if ( (type->size)(f, thing, &curr_size) < 0 ) { - - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGETSIZE, FAIL, \ - "Can't get size of thing") - } + if((type->size)(f, thing, &curr_size) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGETSIZE, FAIL, "Can't get size of thing") if(((H5AC_info_t *)thing)->size != curr_size) HGOTO_ERROR(H5E_CACHE, H5E_BADSIZE, FAIL, "size of entry changed") - } + } /* end if */ #ifdef H5_HAVE_PARALLEL - if ( ( dirtied ) && ( ((H5AC_info_t *)thing)->is_dirty == FALSE ) && - ( NULL != (aux_ptr = f->shared->cache->aux_ptr) ) ) { + if((dirtied) && (((H5AC_info_t *)thing)->is_dirty == FALSE) && + (NULL != (aux_ptr = (H5AC_aux_t *)f->shared->cache->aux_ptr))) { if(H5AC_log_dirtied_entry((H5AC_info_t *)thing, addr) < 0) HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "can't log dirtied entry") - } - - if ( ( (flags & H5C__DELETED_FLAG) != 0 ) && - ( NULL != (aux_ptr = f->shared->cache->aux_ptr) ) && - ( aux_ptr->mpi_rank == 0 ) ) { - - result = H5AC_log_deleted_entry(f->shared->cache, - (H5AC_info_t *)thing, - addr, - flags); - - if ( result < 0 ) { + } /* end if */ - HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \ - "H5AC_log_deleted_entry() failed.") - } - } + if((deleted) && + (NULL != (aux_ptr = (H5AC_aux_t *)(f->shared->cache->aux_ptr))) && + (aux_ptr->mpi_rank == 0)) { + if(H5AC_log_deleted_entry(f->shared->cache, (H5AC_info_t *)thing, addr, flags) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "H5AC_log_deleted_entry() failed.") + } /* end if */ #endif /* H5_HAVE_PARALLEL */ - result = H5C_unprotect(f, - dxpl_id, - H5AC_noblock_dxpl_id, - type, - addr, - thing, - flags); - - if ( result < 0 ) { - - HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \ - "H5C_unprotect() failed.") - } + if(H5C_unprotect(f, dxpl_id, H5AC_noblock_dxpl_id, type, addr, thing, flags) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "H5C_unprotect() failed.") #ifdef H5_HAVE_PARALLEL /* Check if we should try to flush */ - if(aux_ptr && (aux_ptr->dirty_bytes >= aux_ptr->dirty_bytes_threshold)) { - hbool_t evictions_enabled; - - /* Query if evictions are allowed */ - if(H5C_get_evictions_enabled((const H5C_t *)f->shared->cache, &evictions_enabled) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, FAIL, "H5C_get_evictions_enabled() failed.") - - /* Flush if evictions are allowed */ - if(evictions_enabled) { - if(H5AC_propagate_flushed_and_still_clean_entries_list(f, - H5AC_noblock_dxpl_id, f->shared->cache, TRUE) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't propagate clean entries list.") - } /* end if */ + if((aux_ptr != NULL) && (aux_ptr->dirty_bytes >= aux_ptr->dirty_bytes_threshold)) { + if(H5AC_run_sync_point(f, H5AC_noblock_dxpl_id, H5AC_SYNC_POINT_OP__FLUSH_TO_MIN_CLEAN) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't run sync point.") } /* end if */ #endif /* H5_HAVE_PARALLEL */ done: - #if H5AC__TRACE_FILE_ENABLED - if ( trace_file_ptr != NULL ) { - + if(trace_file_ptr != NULL) HDfprintf(trace_file_ptr, "%s %x %d\n", - trace, - (unsigned)flags, - (int)ret_value); - } + trace, (unsigned)flags, (int)ret_value); #endif /* H5AC__TRACE_FILE_ENABLED */ FUNC_LEAVE_NOAPI(ret_value) - } /* H5AC_unprotect() */ /*------------------------------------------------------------------------- + * Function: HA5C_set_sync_point_done_callback + * + * Purpose: Set the value of the sync_point_done callback. This + * callback is used by the parallel test code to verify + * that the expected writes and only the expected writes + * take place during a sync point. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: John Mainzer + * 5/9/10 + * + *------------------------------------------------------------------------- + */ +#ifdef H5_HAVE_PARALLEL +herr_t +H5AC_set_sync_point_done_callback(H5C_t * cache_ptr, + void (* sync_point_done)(int num_writes, haddr_t * written_entries_tbl)) +{ + H5AC_aux_t * aux_ptr; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5AC_set_sync_point_done_callback) + + HDassert(cache_ptr && (cache_ptr->magic == H5C__H5C_T_MAGIC)); + + aux_ptr = (H5AC_aux_t *)(cache_ptr->aux_ptr); + + HDassert( aux_ptr != NULL ); + HDassert( aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC ); + + aux_ptr->sync_point_done = sync_point_done; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5AC_set_sync_point_done_callback() */ +#endif /* H5_HAVE_PARALLEL */ + + +/*------------------------------------------------------------------------- * Function: HA5C_set_write_done_callback * * Purpose: Set the value of the write_done callback. This callback @@ -1846,29 +1775,20 @@ herr_t H5AC_set_write_done_callback(H5C_t * cache_ptr, void (* write_done)(void)) { - herr_t ret_value = SUCCEED; /* Return value */ - H5AC_aux_t * aux_ptr = NULL; + H5AC_aux_t * aux_ptr; - FUNC_ENTER_NOAPI(H5AC_set_write_done_callback, FAIL) + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5AC_set_write_done_callback) - /* This would normally be an assert, but we need to use an HGOTO_ERROR - * call to shut up the compiler. - */ - if ( ( ! cache_ptr ) || ( cache_ptr->magic != H5C__H5C_T_MAGIC ) ) { + HDassert(cache_ptr && (cache_ptr->magic == H5C__H5C_T_MAGIC)); - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Bad cache_ptr") - } - - aux_ptr = cache_ptr->aux_ptr; + aux_ptr = (H5AC_aux_t *)(cache_ptr->aux_ptr); HDassert( aux_ptr != NULL ); HDassert( aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC ); aux_ptr->write_done = write_done; -done: - FUNC_LEAVE_NOAPI(ret_value) - + FUNC_LEAVE_NOAPI(SUCCEED) } /* H5AC_set_write_done_callback() */ #endif /* H5_HAVE_PARALLEL */ @@ -1901,7 +1821,6 @@ H5AC_stats(const H5F_t *f) done: FUNC_LEAVE_NOAPI(ret_value) - } /* H5AC_stats() */ @@ -1959,13 +1878,8 @@ H5AC_get_cache_auto_resize_config(const H5AC_t * cache_ptr, "H5C_get_cache_auto_resize_config() failed.") } - result = H5C_get_evictions_enabled((const H5C_t *)cache_ptr, &evictions_enabled); - - if ( result < 0 ) { - - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ - "H5C_get_resize_enabled() failed.") - } + if(H5C_get_evictions_enabled((const H5C_t *)cache_ptr, &evictions_enabled) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5C_get_resize_enabled() failed.") if ( internal_config.rpt_fcn == NULL ) { @@ -2009,11 +1923,16 @@ H5AC_get_cache_auto_resize_config(const H5AC_t * cache_ptr, config_ptr->dirty_bytes_threshold = ((H5AC_aux_t *)(cache_ptr->aux_ptr))->dirty_bytes_threshold; + config_ptr->metadata_write_strategy = + ((H5AC_aux_t *)(cache_ptr->aux_ptr))->metadata_write_strategy; } else { #endif /* H5_HAVE_PARALLEL */ - config_ptr->dirty_bytes_threshold = H5AC__DEFAULT_DIRTY_BYTES_THRESHOLD; + config_ptr->dirty_bytes_threshold = + H5AC__DEFAULT_DIRTY_BYTES_THRESHOLD; + config_ptr->metadata_write_strategy = + H5AC__DEFAULT_METADATA_WRITE_STRATEGY; #ifdef H5_HAVE_PARALLEL } @@ -2212,24 +2131,6 @@ H5AC_set_cache_auto_resize_config(H5AC_t *cache_ptr, } } - if ( - ( - config_ptr->dirty_bytes_threshold - < - H5AC__MIN_DIRTY_BYTES_THRESHOLD - ) - || - ( - config_ptr->dirty_bytes_threshold - > - H5AC__MAX_DIRTY_BYTES_THRESHOLD - ) - ) { - - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, - "config_ptr->dirty_bytes_threshold out of range.") - } - if ( config_ptr->close_trace_file ) { if ( H5AC_close_trace_file(cache_ptr) < 0 ) { @@ -2263,6 +2164,9 @@ H5AC_set_cache_auto_resize_config(H5AC_t *cache_ptr, ((H5AC_aux_t *)(cache_ptr->aux_ptr))->dirty_bytes_threshold = config_ptr->dirty_bytes_threshold; + + ((H5AC_aux_t *)(cache_ptr->aux_ptr))->metadata_write_strategy = + config_ptr->metadata_write_strategy; } #endif /* H5_HAVE_PARALLEL */ @@ -2278,7 +2182,7 @@ done: ( trace_file_ptr != NULL ) ) { HDfprintf(trace_file_ptr, - "%s %d %d %d %d \"%s\" %d %d %d %f %d %d %ld %d %f %f %d %f %f %d %d %d %f %f %d %d %d %d %f %d %d\n", + "%s %d %d %d %d \"%s\" %d %d %d %f %d %d %ld %d %f %f %d %f %f %d %d %d %f %f %d %d %d %d %f %d %d %d\n", "H5AC_set_cache_auto_resize_config", trace_config.version, (int)(trace_config.rpt_fcn_enabled), @@ -2309,6 +2213,7 @@ done: (int)(trace_config.apply_empty_reserve), trace_config.empty_reserve, trace_config.dirty_bytes_threshold, + trace_config.metadata_write_strategy, (int)ret_value); } #endif /* H5AC__TRACE_FILE_ENABLED */ @@ -2343,45 +2248,28 @@ done: herr_t H5AC_validate_config(H5AC_cache_config_t * config_ptr) { - herr_t result; H5C_auto_size_ctl_t internal_config; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5AC_validate_config, FAIL) - if ( config_ptr == NULL ) { - + if(config_ptr == NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL config_ptr on entry.") - } - - if ( config_ptr->version != H5AC__CURR_CACHE_CONFIG_VERSION ) { + if(config_ptr->version != H5AC__CURR_CACHE_CONFIG_VERSION) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Unknown config version.") - } - if ( ( config_ptr->rpt_fcn_enabled != TRUE ) && - ( config_ptr->rpt_fcn_enabled != FALSE ) ) { + if((config_ptr->rpt_fcn_enabled != TRUE) && (config_ptr->rpt_fcn_enabled != FALSE)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "config_ptr->rpt_fcn_enabled must be either TRUE or FALSE.") - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, \ - "config_ptr->rpt_fcn_enabled must be either TRUE or FALSE.") - } - - if ( ( config_ptr->open_trace_file != TRUE ) && - ( config_ptr->open_trace_file != FALSE ) ) { - - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, \ - "config_ptr->open_trace_file must be either TRUE or FALSE.") - } + if((config_ptr->open_trace_file != TRUE) && (config_ptr->open_trace_file != FALSE)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "config_ptr->open_trace_file must be either TRUE or FALSE.") - if ( ( config_ptr->close_trace_file != TRUE ) && - ( config_ptr->close_trace_file != FALSE ) ) { - - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, \ - "config_ptr->close_trace_file must be either TRUE or FALSE.") - } + if((config_ptr->close_trace_file != TRUE) && (config_ptr->close_trace_file != FALSE)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "config_ptr->close_trace_file must be either TRUE or FALSE.") /* don't bother to test trace_file_name unless open_trace_file is TRUE */ - if ( config_ptr->open_trace_file ) { + if(config_ptr->open_trace_file) { size_t name_len; /* Can't really test the trace_file_name field without trying to @@ -2390,15 +2278,10 @@ H5AC_validate_config(H5AC_cache_config_t * config_ptr) */ name_len = HDstrlen(config_ptr->trace_file_name); - if ( name_len == 0 ) { - - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, \ - "config_ptr->trace_file_name is empty.") - - } else if ( name_len > H5AC__MAX_TRACE_FILE_NAME_LEN ) { - - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, \ - "config_ptr->trace_file_name too long.") + if(name_len == 0) { + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "config_ptr->trace_file_name is empty.") + } else if(name_len > H5AC__MAX_TRACE_FILE_NAME_LEN) { + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "config_ptr->trace_file_name too long.") } } @@ -2418,36 +2301,24 @@ H5AC_validate_config(H5AC_cache_config_t * config_ptr) "Can't disable evictions while auto-resize is enabled.") } - if ( config_ptr->dirty_bytes_threshold < H5AC__MIN_DIRTY_BYTES_THRESHOLD ) { - - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, - "dirty_bytes_threshold too small.") - } else - if ( config_ptr->dirty_bytes_threshold > H5AC__MAX_DIRTY_BYTES_THRESHOLD ) { - - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, - "dirty_bytes_threshold too big.") - } - - if ( H5AC_ext_config_2_int_config(config_ptr, &internal_config) != - SUCCEED ) { - - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ - "H5AC_ext_config_2_int_config() failed.") + if(config_ptr->dirty_bytes_threshold < H5AC__MIN_DIRTY_BYTES_THRESHOLD) { + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dirty_bytes_threshold too small.") + } else if(config_ptr->dirty_bytes_threshold > H5AC__MAX_DIRTY_BYTES_THRESHOLD) { + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dirty_bytes_threshold too big.") } - result = H5C_validate_resize_config(&internal_config, - H5C_RESIZE_CFG__VALIDATE_ALL); + if((config_ptr->metadata_write_strategy != H5AC_METADATA_WRITE_STRATEGY__PROCESS_0_ONLY) && + (config_ptr->metadata_write_strategy != H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "config_ptr->metadata_write_strategy out of range.") - if ( result != SUCCEED ) { + if(H5AC_ext_config_2_int_config(config_ptr, &internal_config) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5AC_ext_config_2_int_config() failed.") + if(H5C_validate_resize_config(&internal_config, H5C_RESIZE_CFG__VALIDATE_ALL) < 0) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "error(s) in new config.") - } done: - FUNC_LEAVE_NOAPI(ret_value) - } /* H5AC_validate_config() */ @@ -2620,12 +2491,192 @@ done: } /* H5AC_open_trace_file() */ +/*------------------------------------------------------------------------- + * Function: H5AC_add_candidate() + * + * Purpose: Add the supplied metadata entry address to the candidate + * list. Verify that each entry added does not appear in + * the list prior to its insertion. + * + * This function is intended for used in constructing list + * of entried to be flushed during sync points. It shouldn't + * be called anywhere else. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: John Mainzer + * 3/17/10 + * + *------------------------------------------------------------------------- + */ +#ifdef H5_HAVE_PARALLEL +herr_t +H5AC_add_candidate(H5AC_t * cache_ptr, + haddr_t addr) +{ + H5AC_aux_t * aux_ptr; + H5AC_slist_entry_t * slist_entry_ptr = NULL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5AC_add_candidate, FAIL) + + HDassert( cache_ptr != NULL ); + HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); + + aux_ptr = (H5AC_aux_t *)(cache_ptr->aux_ptr); + + HDassert( aux_ptr != NULL ); + HDassert( aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC ); + HDassert( aux_ptr->metadata_write_strategy == + H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED ); + HDassert( aux_ptr->candidate_slist_ptr != NULL ); + + /* If the supplied address appears in the candidate list, scream and die. */ + if(NULL != H5SL_search(aux_ptr->candidate_slist_ptr, (void *)(&addr))) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "entry already in candidate slist.") + + /* otherwise, construct an entry for the supplied address, and insert + * it into the candidate slist. + */ + if(NULL == (slist_entry_ptr = H5FL_CALLOC(H5AC_slist_entry_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "Can't allocate candidate slist entry .") + + slist_entry_ptr->magic = H5AC__H5AC_SLIST_ENTRY_T_MAGIC; + slist_entry_ptr->addr = addr; + + if(H5SL_insert(aux_ptr->candidate_slist_ptr, slist_entry_ptr, &(slist_entry_ptr->addr)) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTINSERT, FAIL, "can't insert entry into dirty entry slist.") + + aux_ptr->candidate_slist_len += 1; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5AC_add_candidate() */ +#endif /* H5_HAVE_PARALLEL */ + + /*************************************************************************/ /**************************** Private Functions: *************************/ /*************************************************************************/ /*------------------------------------------------------------------------- * + * Function: H5AC_broadcast_candidate_list() + * + * Purpose: Broadcast the contents of the process 0 candidate entry + * slist. In passing, also remove all entries from said + * list. As the application of this will be handled by + * the same functions on all processes, construct and + * return a copy of the list in the same format as that + * received by the other processes. Note that if this + * copy is returned in *haddr_buf_ptr_ptr, the caller + * must free it. + * + * This function must only be called by the process with + * MPI_rank 0. + * + * Return SUCCEED on success, and FAIL on failure. + * + * Return: Non-negative on success/Negative on failure. + * + * Programmer: John Mainzer, 7/1/05 + * + *------------------------------------------------------------------------- + */ +#ifdef H5_HAVE_PARALLEL +static herr_t +H5AC_broadcast_candidate_list(H5AC_t * cache_ptr, + int * num_entries_ptr, + haddr_t ** haddr_buf_ptr_ptr) +{ + herr_t result; + hbool_t success = FALSE; + H5AC_aux_t * aux_ptr = NULL; + haddr_t * haddr_buf_ptr = NULL; + MPI_Offset * MPI_Offset_buf_ptr = NULL; + size_t buf_size = 0; + int mpi_result; + int chk_num_entries = 0; + int num_entries = 0; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5AC_broadcast_candidate_list, FAIL) + + HDassert( cache_ptr != NULL ); + HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); + + aux_ptr = (H5AC_aux_t *)(cache_ptr->aux_ptr); + + HDassert( aux_ptr != NULL ); + HDassert( aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC ); + HDassert( aux_ptr->mpi_rank == 0 ); + HDassert( aux_ptr->metadata_write_strategy == + H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED ); + HDassert( aux_ptr->candidate_slist_ptr != NULL ); + HDassert( H5SL_count(aux_ptr->candidate_slist_ptr) == + (size_t)(aux_ptr->candidate_slist_len) ); + HDassert( num_entries_ptr != NULL ); + HDassert( *num_entries_ptr == 0 ); + HDassert( haddr_buf_ptr_ptr != NULL ); + HDassert( *haddr_buf_ptr_ptr == NULL ); + + /* First broadcast the number of entries in the list so that the + * receivers can set up buffers to receive them. If there aren't + * any, we are done. + */ + num_entries = aux_ptr->candidate_slist_len; + if(MPI_SUCCESS != (mpi_result = MPI_Bcast(&num_entries, 1, MPI_INT, 0, aux_ptr->mpi_comm))) + HMPI_GOTO_ERROR(FAIL, "MPI_Bcast failed 1", mpi_result) + + if(num_entries > 0) { + /* convert the candidate list into the format we + * are used to receiving from process 0, and also load it + * into a buffer for transmission. + */ + if(H5AC_copy_candidate_list_to_buffer(cache_ptr, &chk_num_entries, + &haddr_buf_ptr, &buf_size, &MPI_Offset_buf_ptr) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't construct candidate buffer.") + + HDassert( chk_num_entries == num_entries ); + HDassert( haddr_buf_ptr != NULL ); + HDassert( MPI_Offset_buf_ptr != NULL ); + HDassert( aux_ptr->candidate_slist_len == 0 ); + + /* Now broadcast the list of candidate entries -- if there is one. + * + * The peculiar structure of the following call to MPI_Bcast is + * due to MPI's (?) failure to believe in the MPI_Offset type. + * Thus the element type is MPI_BYTE, with size equal to the + * buf_size computed above. + */ + if(MPI_SUCCESS != (mpi_result = MPI_Bcast((void *)MPI_Offset_buf_ptr, (int)buf_size, MPI_BYTE, 0, aux_ptr->mpi_comm))) + HMPI_GOTO_ERROR(FAIL, "MPI_Bcast failed 2", mpi_result) + } /* end if */ + + success = TRUE; + +done: + if(MPI_Offset_buf_ptr != NULL) + MPI_Offset_buf_ptr = (MPI_Offset *)H5MM_xfree((void *)MPI_Offset_buf_ptr); + + if(success) { + /* Pass the number of entries and the buffer pointer + * back to the caller. Do this so that we can use the same code + * to apply the candidate list to all the processes. + */ + *num_entries_ptr = num_entries; + *haddr_buf_ptr_ptr = haddr_buf_ptr; + } else if(haddr_buf_ptr != NULL) { + haddr_buf_ptr = (haddr_t *)H5MM_xfree((void *)haddr_buf_ptr); + } + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5AC_broadcast_candidate_list() */ +#endif /* H5_HAVE_PARALLEL */ + + +/*------------------------------------------------------------------------- + * * Function: H5AC_broadcast_clean_list() * * Purpose: Broadcast the contents of the process 0 cleaned entry @@ -2650,6 +2701,7 @@ H5AC_broadcast_clean_list(H5AC_t * cache_ptr) { herr_t ret_value = SUCCEED; /* Return value */ haddr_t addr; + haddr_t * addr_buf_ptr = NULL; H5AC_aux_t * aux_ptr = NULL; H5SL_node_t * slist_node_ptr = NULL; H5AC_slist_entry_t * slist_entry_ptr = NULL; @@ -2657,14 +2709,14 @@ H5AC_broadcast_clean_list(H5AC_t * cache_ptr) size_t buf_size; int i = 0; int mpi_result; - int num_entries; + int num_entries = 0; FUNC_ENTER_NOAPI(H5AC_broadcast_clean_list, FAIL) HDassert( cache_ptr != NULL ); HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); - aux_ptr = (H5AC_aux_t *)(cache_ptr->aux_ptr); + aux_ptr = (H5AC_aux_t *)cache_ptr->aux_ptr; HDassert( aux_ptr != NULL ); HDassert( aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC ); @@ -2702,13 +2754,28 @@ H5AC_broadcast_clean_list(H5AC_t * cache_ptr) "memory allocation failed for clean entry buffer") } + /* if the sync_point_done callback is defined, allocate the + * addr buffer as well. + */ + if ( aux_ptr->sync_point_done != NULL ) { + + addr_buf_ptr = H5MM_malloc((size_t)(num_entries * sizeof(haddr_t))); + + if ( addr_buf_ptr == NULL ) { + + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \ + "memory allocation failed for addr buffer") + } + } + + /* now load the entry base addresses into the buffer, emptying the * cleaned entry list in passing */ while ( NULL != (slist_node_ptr = H5SL_first(aux_ptr->c_slist_ptr) ) ) { - slist_entry_ptr = H5SL_item(slist_node_ptr); + slist_entry_ptr = (H5AC_slist_entry_t *)H5SL_item(slist_node_ptr); HDassert(slist_entry_ptr->magic == H5AC__H5AC_SLIST_ENTRY_T_MAGIC); @@ -2716,6 +2783,11 @@ H5AC_broadcast_clean_list(H5AC_t * cache_ptr) addr = slist_entry_ptr->addr; + if ( addr_buf_ptr != NULL ) { + + addr_buf_ptr[i] = addr; + } + if ( H5FD_mpi_haddr_to_MPIOff(addr, &(buf_ptr[i])) < 0 ) { HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, \ @@ -2743,19 +2815,12 @@ H5AC_broadcast_clean_list(H5AC_t * cache_ptr) /* and also remove the matching entry from the dirtied list * if it exists. */ - if ( (slist_entry_ptr = H5SL_search(aux_ptr->d_slist_ptr, - (void *)(&addr))) != NULL ) { - - HDassert( slist_entry_ptr->magic == - H5AC__H5AC_SLIST_ENTRY_T_MAGIC ); + if((slist_entry_ptr = H5SL_search(aux_ptr->d_slist_ptr, (void *)(&addr))) != NULL) { + HDassert( slist_entry_ptr->magic == H5AC__H5AC_SLIST_ENTRY_T_MAGIC ); HDassert( slist_entry_ptr->addr == addr ); - if ( H5SL_remove(aux_ptr->d_slist_ptr, (void *)(&addr)) - != slist_entry_ptr ) { - - HGOTO_ERROR(H5E_CACHE, H5E_CANTDELETE, FAIL, \ - "Can't delete entry from dirty entry slist.") - } + if(H5SL_remove(aux_ptr->d_slist_ptr, (void *)(&addr)) != slist_entry_ptr) + HGOTO_ERROR(H5E_CACHE, H5E_CANTDELETE, FAIL, "Can't delete entry from dirty entry slist.") slist_entry_ptr->magic = 0; H5FL_FREE(H5AC_slist_entry_t, slist_entry_ptr); @@ -2764,8 +2829,7 @@ H5AC_broadcast_clean_list(H5AC_t * cache_ptr) aux_ptr->d_slist_len -= 1; HDassert( aux_ptr->d_slist_len >= 0 ); - } - + } /* end if */ } /* while */ @@ -2786,15 +2850,16 @@ H5AC_broadcast_clean_list(H5AC_t * cache_ptr) } } -done: - - if ( buf_ptr != NULL ) { + if(aux_ptr->sync_point_done != NULL) + (aux_ptr->sync_point_done)(num_entries, addr_buf_ptr); +done: + if(buf_ptr != NULL) buf_ptr = (MPI_Offset *)H5MM_xfree((void *)buf_ptr); - } + if(addr_buf_ptr != NULL) + addr_buf_ptr = (MPI_Offset *)H5MM_xfree((void *)addr_buf_ptr); FUNC_LEAVE_NOAPI(ret_value) - } /* H5AC_broadcast_clean_list() */ #endif /* H5_HAVE_PARALLEL */ @@ -2850,7 +2915,9 @@ H5AC_check_if_write_permitted(const H5F_t UNUSED * f, HDassert( aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC ); - if ( aux_ptr->mpi_rank == 0 ) { + if ( ( aux_ptr->mpi_rank == 0 ) || + ( aux_ptr->metadata_write_strategy == + H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED ) ) { write_permitted = aux_ptr->write_permitted; @@ -2871,6 +2938,222 @@ done: /*------------------------------------------------------------------------- + * Function: H5AC_construct_candidate_list() + * + * Purpose: In the parallel case when the metadata_write_strategy is + * H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED, process 0 uses + * this function to construct the list of cache entries to + * be flushed. This list is then propagated to the other + * caches, and then flushed in a distributed fashion. + * + * The sync_point_op parameter is used to determine the extent + * of the flush. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: John Mainzer + * 3/17/10 + * + *------------------------------------------------------------------------- + */ +#ifdef H5_HAVE_PARALLEL +herr_t +H5AC_construct_candidate_list(H5AC_t * cache_ptr, + H5AC_aux_t * aux_ptr, + int sync_point_op) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5AC_construct_candidate_list, FAIL) + + HDassert( cache_ptr != NULL ); + HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); + HDassert( aux_ptr != NULL ); + HDassert( aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC ); + HDassert( aux_ptr->metadata_write_strategy == + H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED ); + HDassert( ( sync_point_op == H5AC_SYNC_POINT_OP__FLUSH_CACHE ) || + ( aux_ptr->mpi_rank == 0 ) ); + HDassert( aux_ptr->d_slist_ptr != NULL ); + HDassert( aux_ptr->c_slist_ptr != NULL ); + HDassert( aux_ptr->c_slist_len == 0 ); + HDassert( aux_ptr->candidate_slist_ptr != NULL ); + HDassert( aux_ptr->candidate_slist_len == 0 ); + HDassert( ( sync_point_op == H5AC_SYNC_POINT_OP__FLUSH_TO_MIN_CLEAN ) || + ( sync_point_op == H5AC_SYNC_POINT_OP__FLUSH_CACHE ) ); + + switch(sync_point_op) { + case H5AC_SYNC_POINT_OP__FLUSH_TO_MIN_CLEAN: + if(H5C_construct_candidate_list__min_clean((H5C_t *)cache_ptr) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5C_construct_candidate_list__min_clean() failed.") + break; + + case H5AC_SYNC_POINT_OP__FLUSH_CACHE: + if(H5C_construct_candidate_list__clean_cache((H5C_t *)cache_ptr) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5C_construct_candidate_list__clean_cache() failed.") + break; + + default: + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unknown sync point operation.") + break; + } /* end switch */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5AC_construct_candidate_list() */ +#endif /* H5_HAVE_PARALLEL */ + + +/*------------------------------------------------------------------------- + * + * Function: H5AC_copy_candidate_list_to_buffer + * + * Purpose: Allocate buffer(s) and copy the contents of the candidate + * entry slist into it (them). In passing, remove all + * entries from the candidate slist. Note that the + * candidate slist must not be empty. + * + * If MPI_Offset_buf_ptr_ptr is not NULL, allocate a buffer + * of MPI_Offset, copy the contents of the candidate + * entry list into it with the appropriate conversions, + * and return the base address of the buffer in + * *MPI_Offset_buf_ptr. Note that this is the buffer + * used by process 0 to transmit the list of entries to + * be flushed to all other processes (in this file group). + * + * Similarly, allocate a buffer of haddr_t, load the contents + * of the candidate list into this buffer, and return its + * base address in *haddr_buf_ptr_ptr. Note that this + * latter buffer is constructed unconditionally. + * + * In passing, also remove all entries from the candidate + * entry slist. + * + * Return: Return SUCCEED on success, and FAIL on failure. + * + * Programmer: John Mainzer, 4/19/10 + * + *------------------------------------------------------------------------- + */ +#ifdef H5_HAVE_PARALLEL +static herr_t +H5AC_copy_candidate_list_to_buffer(H5AC_t * cache_ptr, + int * num_entries_ptr, + haddr_t ** haddr_buf_ptr_ptr, + size_t * MPI_Offset_buf_size_ptr, + MPI_Offset ** MPI_Offset_buf_ptr_ptr) +{ + herr_t ret_value = SUCCEED; /* Return value */ + hbool_t success = FALSE; + haddr_t addr; + H5AC_aux_t * aux_ptr = NULL; + H5SL_node_t * slist_node_ptr = NULL; + H5AC_slist_entry_t * slist_entry_ptr = NULL; + MPI_Offset * MPI_Offset_buf_ptr = NULL; + haddr_t * haddr_buf_ptr = NULL; + size_t buf_size; + int i = 0; + int num_entries = 0; + + FUNC_ENTER_NOAPI(H5AC_copy_candidate_list_to_buffer, FAIL) + + HDassert( cache_ptr != NULL ); + HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); + + aux_ptr = (H5AC_aux_t *)(cache_ptr->aux_ptr); + + HDassert( aux_ptr != NULL ); + HDassert( aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC ); + HDassert( aux_ptr->metadata_write_strategy == + H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED ); + HDassert( aux_ptr->candidate_slist_ptr != NULL ); + HDassert( H5SL_count(aux_ptr->candidate_slist_ptr) == + (size_t)(aux_ptr->candidate_slist_len) ); + HDassert( aux_ptr->candidate_slist_len > 0 ); + HDassert( num_entries_ptr != NULL ); + HDassert( *num_entries_ptr == 0 ); + HDassert( haddr_buf_ptr_ptr != NULL ); + HDassert( *haddr_buf_ptr_ptr == NULL ); + + num_entries = aux_ptr->candidate_slist_len; + + /* allocate a buffer(s) to store the list of candidate entry + * base addresses in + */ + if(MPI_Offset_buf_ptr_ptr != NULL) { + HDassert( MPI_Offset_buf_size_ptr != NULL ); + + /* allocate a buffer of MPI_Offset */ + buf_size = sizeof(MPI_Offset) * (size_t)num_entries; + if(NULL == (MPI_Offset_buf_ptr = (MPI_Offset *)H5MM_malloc(buf_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for MPI_Offset buffer") + } /* end if */ + + /* allocate a buffer of haddr_t */ + if(NULL == (haddr_buf_ptr = (haddr_t *)H5MM_malloc(sizeof(haddr_t) * (size_t)num_entries))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for haddr buffer") + + /* now load the entry base addresses into the buffer, emptying the + * candidate entry list in passing + */ + while(NULL != (slist_node_ptr = H5SL_first(aux_ptr->candidate_slist_ptr))) { + slist_entry_ptr = (H5AC_slist_entry_t *)H5SL_item(slist_node_ptr); + + HDassert(slist_entry_ptr->magic == H5AC__H5AC_SLIST_ENTRY_T_MAGIC); + HDassert( i < num_entries ); + + addr = slist_entry_ptr->addr; + haddr_buf_ptr[i] = addr; + if(MPI_Offset_buf_ptr != NULL) { + if(H5FD_mpi_haddr_to_MPIOff(addr, &(MPI_Offset_buf_ptr[i])) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "can't convert from haddr to MPI off") + } /* end if */ + + i++; + + /* now remove the entry from the cleaned entry list */ + if(H5SL_remove(aux_ptr->candidate_slist_ptr, (void *)(&addr)) != slist_entry_ptr) + HGOTO_ERROR(H5E_CACHE, H5E_CANTDELETE, FAIL, "Can't delete entry from candidate entry slist.") + + slist_entry_ptr->magic = 0; + H5FL_FREE(H5AC_slist_entry_t, slist_entry_ptr); + slist_entry_ptr = NULL; + + aux_ptr->candidate_slist_len -= 1; + + HDassert( aux_ptr->candidate_slist_len >= 0 ); + } /* while */ + HDassert( aux_ptr->candidate_slist_len == 0 ); + + success = TRUE; + +done: + if(success) { + /* Pass the number of entries and the buffer pointer + * back to the caller. + */ + *num_entries_ptr = num_entries; + *haddr_buf_ptr_ptr = haddr_buf_ptr; + + if(MPI_Offset_buf_ptr_ptr != NULL) { + HDassert( MPI_Offset_buf_ptr != NULL); + *MPI_Offset_buf_size_ptr = buf_size; + *MPI_Offset_buf_ptr_ptr = MPI_Offset_buf_ptr; + } /* end if */ + } /* end if */ + else { + if(MPI_Offset_buf_ptr != NULL) + MPI_Offset_buf_ptr = (MPI_Offset *)H5MM_xfree((void *)MPI_Offset_buf_ptr); + if(haddr_buf_ptr != NULL) + haddr_buf_ptr = (haddr_t *)H5MM_xfree((void *)haddr_buf_ptr); + } /* end else */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5AC_copy_candidate_list_to_buffer() */ +#endif /* H5_HAVE_PARALLEL */ + + +/*------------------------------------------------------------------------- * Function: H5AC_ext_config_2_int_config() * * Purpose: Utility function to translate an instance of @@ -2969,16 +3252,16 @@ H5AC_log_deleted_entry(H5AC_t * cache_ptr, haddr_t addr, unsigned int flags) { - herr_t ret_value = SUCCEED; /* Return value */ - H5AC_aux_t * aux_ptr = NULL; + H5AC_aux_t * aux_ptr; H5AC_slist_entry_t * slist_entry_ptr = NULL; + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5AC_log_deleted_entry, FAIL) HDassert( cache_ptr != NULL ); HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); - aux_ptr = cache_ptr->aux_ptr; + aux_ptr = (H5AC_aux_t *)(cache_ptr->aux_ptr); HDassert( aux_ptr != NULL ); HDassert( aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC ); @@ -2988,25 +3271,17 @@ H5AC_log_deleted_entry(H5AC_t * cache_ptr, HDassert( (flags & H5C__DELETED_FLAG) != 0 ); - if ( aux_ptr->mpi_rank == 0 ) { - + if(aux_ptr->mpi_rank == 0) { HDassert( aux_ptr->d_slist_ptr != NULL ); HDassert( aux_ptr->c_slist_ptr != NULL ); /* if the entry appears in the dirtied entry slist, remove it. */ - if ( (slist_entry_ptr = H5SL_search(aux_ptr->d_slist_ptr, - (void *)(&addr))) != NULL ) { - - HDassert( slist_entry_ptr->magic == - H5AC__H5AC_SLIST_ENTRY_T_MAGIC ); - HDassert( slist_entry_ptr->addr == addr ); - - if ( H5SL_remove(aux_ptr->d_slist_ptr, (void *)(&addr)) - != slist_entry_ptr ) { + if((slist_entry_ptr = (H5AC_slist_entry_t *)H5SL_search(aux_ptr->d_slist_ptr, (void *)(&addr))) != NULL) { + HDassert(slist_entry_ptr->magic == H5AC__H5AC_SLIST_ENTRY_T_MAGIC); + HDassert(slist_entry_ptr->addr == addr); - HGOTO_ERROR(H5E_CACHE, H5E_CANTDELETE, FAIL, \ - "Can't delete entry from dirty entry slist.") - } + if(H5SL_remove(aux_ptr->d_slist_ptr, (void *)(&addr)) != slist_entry_ptr) + HGOTO_ERROR(H5E_CACHE, H5E_CANTDELETE, FAIL, "Can't delete entry from dirty entry slist.") slist_entry_ptr->magic = 0; H5FL_FREE(H5AC_slist_entry_t, slist_entry_ptr); @@ -3015,22 +3290,15 @@ H5AC_log_deleted_entry(H5AC_t * cache_ptr, aux_ptr->d_slist_len -= 1; HDassert( aux_ptr->d_slist_len >= 0 ); - } + } /* end if */ /* if the entry appears in the cleaned entry slist, remove it. */ - if ( (slist_entry_ptr = H5SL_search(aux_ptr->c_slist_ptr, - (void *)(&addr))) != NULL ) { - - HDassert( slist_entry_ptr->magic == - H5AC__H5AC_SLIST_ENTRY_T_MAGIC ); - HDassert( slist_entry_ptr->addr == addr ); - - if ( H5SL_remove(aux_ptr->c_slist_ptr, (void *)(&addr)) - != slist_entry_ptr ) { + if((slist_entry_ptr = (H5AC_slist_entry_t *)H5SL_search(aux_ptr->c_slist_ptr, (void *)(&addr))) != NULL) { + HDassert(slist_entry_ptr->magic == H5AC__H5AC_SLIST_ENTRY_T_MAGIC); + HDassert(slist_entry_ptr->addr == addr); - HGOTO_ERROR(H5E_CACHE, H5E_CANTDELETE, FAIL, \ - "Can't delete entry from cleaned entry slist.") - } + if(H5SL_remove(aux_ptr->c_slist_ptr, (void *)(&addr)) != slist_entry_ptr) + HGOTO_ERROR(H5E_CACHE, H5E_CANTDELETE, FAIL, "Can't delete entry from cleaned entry slist.") slist_entry_ptr->magic = 0; H5FL_FREE(H5AC_slist_entry_t, slist_entry_ptr); @@ -3039,13 +3307,11 @@ H5AC_log_deleted_entry(H5AC_t * cache_ptr, aux_ptr->c_slist_len -= 1; HDassert( aux_ptr->c_slist_len >= 0 ); - } - } + } /* end if */ + } /* if */ done: - FUNC_LEAVE_NOAPI(ret_value) - } /* H5AC_log_deleted_entry() */ #endif /* H5_HAVE_PARALLEL */ @@ -3093,7 +3359,7 @@ H5AC_log_dirtied_entry(const H5AC_info_t * entry_ptr, HDassert( cache_ptr != NULL ); HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); - aux_ptr = cache_ptr->aux_ptr; + aux_ptr = (H5AC_aux_t *)(cache_ptr->aux_ptr); HDassert( aux_ptr != NULL ); HDassert( aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC ); @@ -3133,24 +3399,16 @@ H5AC_log_dirtied_entry(const H5AC_info_t * entry_ptr, #endif /* H5AC_DEBUG_DIRTY_BYTES_CREATION */ } - if ( H5SL_search(aux_ptr->c_slist_ptr, (void *)(&addr)) != NULL ) { - + if(H5SL_search(aux_ptr->c_slist_ptr, (void *)(&addr)) != NULL) { /* the entry is dirty. If it exists on the cleaned entries list, * remove it. */ - if ( (slist_entry_ptr = H5SL_search(aux_ptr->c_slist_ptr, - (void *)(&addr))) != NULL ) { - - HDassert( slist_entry_ptr->magic == - H5AC__H5AC_SLIST_ENTRY_T_MAGIC ); - HDassert( slist_entry_ptr->addr == addr ); + if((slist_entry_ptr = (H5AC_slist_entry_t *)H5SL_search(aux_ptr->c_slist_ptr, (void *)(&addr))) != NULL) { + HDassert(slist_entry_ptr->magic == H5AC__H5AC_SLIST_ENTRY_T_MAGIC); + HDassert(slist_entry_ptr->addr == addr); - if ( H5SL_remove(aux_ptr->c_slist_ptr, (void *)(&addr)) - != slist_entry_ptr ) { - - HGOTO_ERROR(H5E_CACHE, H5E_CANTDELETE, FAIL, \ - "Can't delete entry from clean entry slist.") - } + if(H5SL_remove(aux_ptr->c_slist_ptr, (void *)(&addr)) != slist_entry_ptr) + HGOTO_ERROR(H5E_CACHE, H5E_CANTDELETE, FAIL, "Can't delete entry from clean entry slist.") slist_entry_ptr->magic = 0; H5FL_FREE(H5AC_slist_entry_t, slist_entry_ptr); @@ -3159,8 +3417,8 @@ H5AC_log_dirtied_entry(const H5AC_info_t * entry_ptr, aux_ptr->c_slist_len -= 1; HDassert( aux_ptr->c_slist_len >= 0 ); - } - } + } /* end if */ + } /* end if */ } else { aux_ptr->dirty_bytes += entry_ptr->size; @@ -3200,34 +3458,6 @@ done: *------------------------------------------------------------------------- */ #ifdef H5_HAVE_PARALLEL -#if 0 /* This is useful debugging code. -- JRM */ -static herr_t -H5AC_log_flushed_entry_dummy(H5C_t * cache_ptr, - haddr_t addr, - hbool_t was_dirty, - unsigned flags, - int type_id) -{ - herr_t ret_value = SUCCEED; /* Return value */ - H5AC_aux_t * aux_ptr = NULL; - - FUNC_ENTER_NOAPI(H5AC_log_flushed_entry_dummy, FAIL) - - aux_ptr = cache_ptr->aux_ptr; - - if ( ( was_dirty ) && ( (flags & H5C__FLUSH_CLEAR_ONLY_FLAG) == 0 ) ) { - - HDfprintf(stdout, - "%d:H5AC_log_flushed_entry(): addr = %d, flags = %x, was_dirty = %d, type_id = %d\n", - (int)(aux_ptr->mpi_rank), (int)addr, flags, (int)was_dirty, type_id); - } -done: - - FUNC_LEAVE_NOAPI(ret_value) - -} /* H5AC_log_flushed_entry_dummy() */ -#endif /* JRM */ - static herr_t H5AC_log_flushed_entry(H5C_t * cache_ptr, haddr_t addr, @@ -3246,7 +3476,7 @@ H5AC_log_flushed_entry(H5C_t * cache_ptr, HDassert( cache_ptr != NULL ); HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); - aux_ptr = cache_ptr->aux_ptr; + aux_ptr = (H5AC_aux_t *)(cache_ptr->aux_ptr); HDassert( aux_ptr != NULL ); HDassert( aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC ); @@ -3261,7 +3491,8 @@ H5AC_log_flushed_entry(H5C_t * cache_ptr, * cleaned list and the dirtied list. */ - if ( (slist_entry_ptr = H5SL_search(aux_ptr->c_slist_ptr, + if ( (slist_entry_ptr = (H5AC_slist_entry_t *) + H5SL_search(aux_ptr->c_slist_ptr, (void *)(&addr))) != NULL ) { HDassert( slist_entry_ptr->magic == H5AC__H5AC_SLIST_ENTRY_T_MAGIC); @@ -3283,8 +3514,8 @@ H5AC_log_flushed_entry(H5C_t * cache_ptr, HDassert( aux_ptr->c_slist_len >= 0 ); } - if ( (slist_entry_ptr = H5SL_search(aux_ptr->d_slist_ptr, - (void *)(&addr))) != NULL ) { + if ( (slist_entry_ptr = (H5AC_slist_entry_t *) + H5SL_search(aux_ptr->d_slist_ptr, (void *)(&addr))) != NULL ) { HDassert( slist_entry_ptr->magic == H5AC__H5AC_SLIST_ENTRY_T_MAGIC); HDassert( slist_entry_ptr->addr == addr ); @@ -3364,62 +3595,47 @@ H5AC_log_inserted_entry(H5F_t * f, H5AC_t * cache_ptr, H5AC_info_t * entry_ptr) { + H5AC_aux_t * aux_ptr; herr_t ret_value = SUCCEED; /* Return value */ - H5AC_aux_t * aux_ptr = NULL; - H5AC_slist_entry_t * slist_entry_ptr = NULL; FUNC_ENTER_NOAPI(H5AC_log_inserted_entry, FAIL) - HDassert( cache_ptr != NULL ); - HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); + HDassert(cache_ptr != NULL); + HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC); - aux_ptr = cache_ptr->aux_ptr; + aux_ptr = (H5AC_aux_t *)(cache_ptr->aux_ptr); - HDassert( aux_ptr != NULL ); - HDassert( aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC ); + HDassert(aux_ptr != NULL); + HDassert(aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC); HDassert( entry_ptr != NULL ); - if ( aux_ptr->mpi_rank == 0 ) { - - HDassert( aux_ptr->d_slist_ptr != NULL ); - HDassert( aux_ptr->c_slist_ptr != NULL ); - - if ( H5SL_search(aux_ptr->d_slist_ptr, (void *)(&entry_ptr->addr)) == NULL ) { - - /* insert the address of the entry in the dirty entry list, and - * add its size to the dirty_bytes count. - */ - if ( NULL == (slist_entry_ptr = H5FL_CALLOC(H5AC_slist_entry_t)) ) { - - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \ - "Can't allocate dirty slist entry .") - } - - slist_entry_ptr->magic = H5AC__H5AC_SLIST_ENTRY_T_MAGIC; - slist_entry_ptr->addr = entry_ptr->addr; + if(aux_ptr->mpi_rank == 0) { + H5AC_slist_entry_t * slist_entry_ptr; - if ( H5SL_insert(aux_ptr->d_slist_ptr, slist_entry_ptr, - &(slist_entry_ptr->addr)) < 0 ) { + HDassert(aux_ptr->d_slist_ptr != NULL); + HDassert(aux_ptr->c_slist_ptr != NULL); - HGOTO_ERROR(H5E_CACHE, H5E_CANTINSERT, FAIL, \ - "can't insert entry into dirty entry slist.") - } + if(NULL != H5SL_search(aux_ptr->d_slist_ptr, (void *)(&entry_ptr->addr))) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Inserted entry already in dirty slist.") - aux_ptr->d_slist_len += 1; + /* insert the address of the entry in the dirty entry list, and + * add its size to the dirty_bytes count. + */ + if(NULL == (slist_entry_ptr = H5FL_CALLOC(H5AC_slist_entry_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "Can't allocate dirty slist entry .") - } else { + slist_entry_ptr->magic = H5AC__H5AC_SLIST_ENTRY_T_MAGIC; + slist_entry_ptr->addr = entry_ptr->addr; - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ - "Inserted entry already in dirty slist.") - } + if(H5SL_insert(aux_ptr->d_slist_ptr, slist_entry_ptr, &(slist_entry_ptr->addr)) < 0 ) + HGOTO_ERROR(H5E_CACHE, H5E_CANTINSERT, FAIL, "can't insert entry into dirty entry slist.") - if ( H5SL_search(aux_ptr->c_slist_ptr, (void *)(&entry_ptr->addr)) != NULL ) { + aux_ptr->d_slist_len += 1; - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ - "Inserted entry in clean slist.") - } - } + if(NULL != H5SL_search(aux_ptr->c_slist_ptr, (void *)(&entry_ptr->addr))) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Inserted entry in clean slist.") + } /* end if */ aux_ptr->dirty_bytes += entry_ptr->size; @@ -3429,9 +3645,7 @@ H5AC_log_inserted_entry(H5F_t * f, #endif /* H5AC_DEBUG_DIRTY_BYTES_CREATION */ done: - FUNC_LEAVE_NOAPI(ret_value) - } /* H5AC_log_inserted_entry() */ #endif /* H5_HAVE_PARALLEL */ @@ -3506,7 +3720,7 @@ H5AC_log_moved_entry(const H5F_t *f, HDassert( cache_ptr ); HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); - aux_ptr = cache_ptr->aux_ptr; + aux_ptr = (H5AC_aux_t *)(cache_ptr->aux_ptr); HDassert( aux_ptr != NULL ); HDassert( aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC ); @@ -3531,8 +3745,8 @@ H5AC_log_moved_entry(const H5F_t *f, /* if the entry appears in the cleaned entry slist, under its old * address, remove it. */ - if ( (slist_entry_ptr = H5SL_search(aux_ptr->c_slist_ptr, - (void *)(&old_addr))) != NULL ) { + if ( (slist_entry_ptr = (H5AC_slist_entry_t *) + H5SL_search(aux_ptr->c_slist_ptr, (void *)(&old_addr))) != NULL ) { HDassert( slist_entry_ptr->magic == H5AC__H5AC_SLIST_ENTRY_T_MAGIC ); @@ -3557,8 +3771,8 @@ H5AC_log_moved_entry(const H5F_t *f, /* if the entry appears in the dirtied entry slist under its old * address, remove it, but don't free it. Set addr to new_addr. */ - if ( (slist_entry_ptr = H5SL_search(aux_ptr->d_slist_ptr, - (void *)(&old_addr))) != NULL ) { + if ( (slist_entry_ptr = (H5AC_slist_entry_t *) + H5SL_search(aux_ptr->d_slist_ptr, (void *)(&old_addr))) != NULL ) { HDassert( slist_entry_ptr->magic == H5AC__H5AC_SLIST_ENTRY_T_MAGIC ); @@ -3634,27 +3848,223 @@ H5AC_log_moved_entry(const H5F_t *f, } done: - FUNC_LEAVE_NOAPI(ret_value) - } /* H5AC_log_moved_entry() */ #endif /* H5_HAVE_PARALLEL */ /*------------------------------------------------------------------------- + * Function: H5AC_propagate_and_apply_candidate_list + * + * Purpose: Prior to the addition of support for multiple metadata + * write strategies, in PHDF5, only the metadata cache with + * mpi rank 0 was allowed to write to file. All other + * metadata caches on processes with rank greater than 0 + * were required to retain dirty entries until they were + * notified that the entry was clean. + * + * This constraint is relaxed with the distributed + * metadata write strategy, in which a list of candidate + * metadata cache entries is constructed by the process 0 + * cache and then distributed to the caches of all the other + * processes. Once the listed is distributed, many (if not + * all) processes writing writing a unique subset of the + * entries, and marking the remainder clean. The subsets + * are chosen so that each entry in the list of candidates + * is written by exactly one cache, and all entries are + * marked as being clean in all caches. + * + * While the list of candidate cache entries is prepared + * elsewhere, this function is the main routine for distributing + * and applying the list. It must be run simultaniously on + * all processes that have the relevant file open. To ensure + * proper synchronization, there is a barrier at the beginning + * of this function. + * + * At present, this function is called under one of two + * circumstances: + * + * 1) Dirty byte creation exceeds some user specified value. + * + * While metadata reads may occur independently, all + * operations writing metadata must be collective. Thus + * all metadata caches see the same sequence of operations, + * and therefore the same dirty data creation. + * + * This fact is used to synchronize the caches for purposes + * of propagating the list of candidate entries, by simply + * calling this function from all caches whenever some user + * specified threshold on dirty data is exceeded. (the + * process 0 cache creates the candidate list just before + * calling this function). + * + * 2) Under direct user control -- this operation must be + * collective. + * + * The operations to be managed by this function are as + * follows: + * + * All processes: + * + * 1) Participate in an opening barrier. + * + * For the process with mpi rank 0: + * + * 1) Load the contents of the candidate list + * (candidate_slist_ptr) into a buffer, and broadcast that + * buffer to all the other caches. Clear the candidate + * list in passing. + * + * If there is a positive number of candidates, proceed with + * the following: + * + * 2) Apply the candidate entry list. + * + * 3) Particpate in a closing barrier. + * + * 4) Remove from the dirty list (d_slist_ptr) and from the + * flushed and still clean entries list (c_slist_ptr), + * all addresses that appeared in the candidate list, as + * these entries are now clean. + * + * + * For all processes with mpi rank greater than 0: + * + * 1) Receive the candidate entry list broadcast + * + * If there is a positive number of candidates, proceed with + * the following: + * + * 2) Apply the candidate entry list. + * + * 3) Particpate in a closing barrier. + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: John Mainzer + * 3/17/10 + * + *------------------------------------------------------------------------- + */ +#ifdef H5_HAVE_PARALLEL +static herr_t +H5AC_propagate_and_apply_candidate_list(H5F_t * f, + hid_t dxpl_id, + H5AC_t * cache_ptr) +{ + int mpi_code; + int num_candidates = 0; + haddr_t * candidates_list_ptr = NULL; + H5AC_aux_t * aux_ptr; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5AC_propagate_and_apply_candidate_list, FAIL) + + HDassert( cache_ptr != NULL ); + HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); + + aux_ptr = (H5AC_aux_t *)(cache_ptr->aux_ptr); + + HDassert( aux_ptr != NULL ); + HDassert( aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC ); + HDassert( aux_ptr->metadata_write_strategy == + H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED ); + + /* to prevent "messages from the future" we must synchronize all + * processes before we write any entries. + */ + if(MPI_SUCCESS != (mpi_code = MPI_Barrier(aux_ptr->mpi_comm))) + HMPI_GOTO_ERROR(FAIL, "MPI_Barrier failed 1", mpi_code) + + if(aux_ptr->mpi_rank == 0) { + if(H5AC_broadcast_candidate_list(cache_ptr, &num_candidates, &candidates_list_ptr) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't broadcast candidate slist.") + + HDassert( aux_ptr->candidate_slist_len == 0 ); + } /* end if */ + else { + if(H5AC_receive_candidate_list(cache_ptr, &num_candidates, &candidates_list_ptr) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't receive candidate broadcast.") + } /* end else */ + + if(num_candidates > 0) { + herr_t result; + + /* all processes apply the candidate list. + * H5C_apply_candidate_list() handles the details of + * distributing the writes across the processes. + */ + + aux_ptr->write_permitted = TRUE; + + result = H5C_apply_candidate_list(f, + dxpl_id, + dxpl_id, + cache_ptr, + num_candidates, + candidates_list_ptr, + aux_ptr->mpi_rank, + aux_ptr->mpi_size); + + aux_ptr->write_permitted = FALSE; + + if(result < 0) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't apply candidate list.") + + if(aux_ptr->write_done != NULL) + (aux_ptr->write_done)(); + + /* to prevent "messages from the past" we must synchronize all + * processes again before we go on. + */ + if(MPI_SUCCESS != (mpi_code = MPI_Barrier(aux_ptr->mpi_comm))) + HMPI_GOTO_ERROR(FAIL, "MPI_Barrier failed 2", mpi_code) + + if(aux_ptr->mpi_rank == 0) { + if(H5AC_tidy_cache_0_lists(cache_ptr, num_candidates, candidates_list_ptr) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't tidy up process 0 lists.") + } /* end if */ + } /* end if */ + + /* if it is defined, call the sync point done callback. Note + * that this callback is defined purely for testing purposes, + * and should be undefined under normal operating circumstances. + */ + if(aux_ptr->sync_point_done != NULL) + (aux_ptr->sync_point_done)(num_candidates, candidates_list_ptr); + +done: + if(candidates_list_ptr != NULL) + candidates_list_ptr = (haddr_t *)H5MM_xfree((void *)candidates_list_ptr); + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5AC_propagate_and_apply_candidate_list() */ +#endif /* H5_HAVE_PARALLEL */ + + +/*------------------------------------------------------------------------- * Function: H5AC_propagate_flushed_and_still_clean_entries_list * - * Purpose: In PHDF5, only the metadata cache with mpi rank 0 is allowed - * to write to file. All other metadata caches on processes - * with rank greater than 0 must retain dirty entries until - * they are notified that the entry is now clean. + * Purpose: In PHDF5, if the process 0 only metadata write strategy + * is selected, only the metadata cache with mpi rank 0 is + * allowed to write to file. All other metadata caches on + * processes with rank greater than 0 must retain dirty + * entries until they are notified that the entry is now + * clean. * - * This function is the main routine for that proceedure. - * It must be called simultaniously on all processes that - * have the relevant file open. To this end, there must - * be a barrier immediately prior to this call. + * This function is the main routine for handling this + * notification proceedure. It must be called + * simultaniously on all processes that have the relevant + * file open. To this end, it is called only during a + * sync point, with a barrier prior to the call. * - * Typicaly, this will be done one of two ways: + * Note that any metadata entry writes by process 0 will + * occur after the barrier and just before this call. + * + * Typicaly, calls to this function will be triggered in + * one of two ways: * * 1) Dirty byte creation exceeds some user specified value. * @@ -3677,14 +4087,11 @@ done: * * For the process with mpi rank 0: * - * 1) Enable writes, flush the cache to its min clean size, - * and then disable writes again. - * - * 2) Load the contents of the flushed and still clean entries + * 1) Load the contents of the flushed and still clean entries * list (c_slist_ptr) into a buffer, and broadcast that * buffer to all the other caches. * - * 3) Clear the flushed and still clean entries list + * 2) Clear the flushed and still clean entries list * (c_slist_ptr). * * @@ -3712,113 +4119,156 @@ done: herr_t H5AC_propagate_flushed_and_still_clean_entries_list(H5F_t * f, hid_t dxpl_id, - H5AC_t * cache_ptr, - hbool_t do_barrier) + H5AC_t * cache_ptr) { + H5AC_aux_t * aux_ptr; herr_t ret_value = SUCCEED; /* Return value */ - herr_t result; - int mpi_code; - H5AC_aux_t * aux_ptr = NULL; FUNC_ENTER_NOAPI(H5AC_propagate_flushed_and_still_clean_entries_list, FAIL) - HDassert( cache_ptr != NULL ); - HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); + HDassert(cache_ptr != NULL); + HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC); aux_ptr = (H5AC_aux_t *)(cache_ptr->aux_ptr); - HDassert( aux_ptr != NULL ); - HDassert( aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC ); - -#if H5AC_DEBUG_DIRTY_BYTES_CREATION - HDfprintf(stdout, - "%d:H5AC_propagate...:%d: (u/uu/i/iu/r/ru) = %d/%d/%d/%d/%d/%d\n", - (int)(aux_ptr->mpi_rank), - (int)(aux_ptr->dirty_bytes_propagations), - (int)(aux_ptr->unprotect_dirty_bytes), - (int)(aux_ptr->unprotect_dirty_bytes_updates), - (int)(aux_ptr->insert_dirty_bytes), - (int)(aux_ptr->insert_dirty_bytes_updates), - (int)(aux_ptr->move_dirty_bytes), - (int)(aux_ptr->move_dirty_bytes_updates)); -#endif /* H5AC_DEBUG_DIRTY_BYTES_CREATION */ - - if ( do_barrier ) { + HDassert(aux_ptr != NULL); + HDassert(aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC); + HDassert(aux_ptr->metadata_write_strategy == + H5AC_METADATA_WRITE_STRATEGY__PROCESS_0_ONLY); - /* to prevent "messages from the future" we must synchronize all - * processes before we start the flush. This synchronization may - * already be done -- hence the do_barrier parameter. - */ - - if ( MPI_SUCCESS != (mpi_code = MPI_Barrier(aux_ptr->mpi_comm)) ) { + if(aux_ptr->mpi_rank == 0) { + if(H5AC_broadcast_clean_list(cache_ptr) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't broadcast clean slist.") + HDassert( aux_ptr->c_slist_len == 0 ); + } /* end if */ + else { + if(H5AC_receive_and_apply_clean_list(f, dxpl_id, H5AC_noblock_dxpl_id, cache_ptr) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't receive and/or process clean slist broadcast.") + } /* end else */ - HMPI_GOTO_ERROR(FAIL, "MPI_Barrier failed", mpi_code) - } - } +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5AC_propagate_flushed_and_still_clean_entries_list() */ +#endif /* H5_HAVE_PARALLEL */ - if ( aux_ptr->mpi_rank == 0 ) { + +/*------------------------------------------------------------------------- + * + * Function: H5AC_receive_and_apply_clean_list() + * + * Purpose: Receive the list of cleaned entries from process 0, + * and mark the specified entries as clean. + * + * This function must only be called by the process with + * MPI_rank greater than 0. + * + * Return SUCCEED on success, and FAIL on failure. + * + * Return: Non-negative on success/Negative on failure. + * + * Programmer: John Mainzer, 7/4/05 + * + *------------------------------------------------------------------------- + */ +#ifdef H5_HAVE_PARALLEL +static herr_t +H5AC_receive_and_apply_clean_list(H5F_t * f, + hid_t primary_dxpl_id, + hid_t secondary_dxpl_id, + H5AC_t * cache_ptr) +{ + H5AC_aux_t * aux_ptr; + haddr_t * haddr_buf_ptr = NULL; + MPI_Offset * MPI_Offset_buf_ptr = NULL; + int mpi_result; + int num_entries = 0; + herr_t ret_value = SUCCEED; /* Return value */ - aux_ptr->write_permitted = TRUE; + FUNC_ENTER_NOAPI(H5AC_receive_and_apply_clean_list, FAIL) - result = H5C_flush_to_min_clean(f, dxpl_id, H5AC_noblock_dxpl_id); + HDassert( f != NULL ); + HDassert( f->shared->cache == cache_ptr ); - aux_ptr->write_permitted = FALSE; + HDassert( cache_ptr != NULL ); + HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); - if ( result < 0 ) { + aux_ptr = (H5AC_aux_t *)(cache_ptr->aux_ptr); - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ - "H5C_flush_to_min_clean() failed.") - } + HDassert( aux_ptr != NULL ); + HDassert( aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC ); + HDassert( aux_ptr->mpi_rank != 0 ); - if ( aux_ptr->write_done != NULL ) { + /* First receive the number of entries in the list so that we + * can set up a buffer to receive them. If there aren't + * any, we are done. + */ + if(MPI_SUCCESS != (mpi_result = MPI_Bcast(&num_entries, 1, MPI_INT, 0, aux_ptr->mpi_comm))) + HMPI_GOTO_ERROR(FAIL, "MPI_Bcast failed 1", mpi_result) - (aux_ptr->write_done)(); - } + if(num_entries > 0) { + size_t buf_size; + int i; - if ( H5AC_broadcast_clean_list(cache_ptr) < 0 ) { + /* allocate buffers to store the list of entry base addresses in */ + buf_size = sizeof(MPI_Offset) * (size_t)num_entries; + if(NULL == (MPI_Offset_buf_ptr = (MPI_Offset *)H5MM_malloc(buf_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for receive buffer") + if(NULL == (haddr_buf_ptr = (haddr_t *)H5MM_malloc(sizeof(haddr_t) * (size_t)num_entries))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for haddr buffer") - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ - "Can't broadcast clean slist.") - } + /* Now receive the list of cleaned entries + * + * The peculiar structure of the following call to MPI_Bcast is + * due to MPI's (?) failure to believe in the MPI_Offset type. + * Thus the element type is MPI_BYTE, with size equal to the + * buf_size computed above. + */ + if(MPI_SUCCESS != (mpi_result = MPI_Bcast((void *)MPI_Offset_buf_ptr, (int)buf_size, MPI_BYTE, 0, aux_ptr->mpi_comm))) + HMPI_GOTO_ERROR(FAIL, "MPI_Bcast failed 2", mpi_result) - HDassert( aux_ptr->c_slist_len == 0 ); + /* translate the MPI_Offsets to haddr_t */ + i = 0; + while(i < num_entries) { + haddr_buf_ptr[i] = H5FD_mpi_MPIOff_to_haddr(MPI_Offset_buf_ptr[i]); - } else { + if(haddr_buf_ptr[i] == HADDR_UNDEF) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "can't convert MPI off to haddr") - if ( H5AC_receive_and_apply_clean_list(f, dxpl_id, - H5AC_noblock_dxpl_id, - cache_ptr) < 0 ) { + i++; + } /* end while */ - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ - "Can't receive and/or process clean slist broadcast.") - } - } + /* mark the indicated entries as clean */ + if(H5C_mark_entries_as_clean(f, primary_dxpl_id, secondary_dxpl_id, + (int32_t)num_entries, &(haddr_buf_ptr[0])) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't mark entries clean.") + } /* end if */ - aux_ptr->dirty_bytes = 0; -#if H5AC_DEBUG_DIRTY_BYTES_CREATION - aux_ptr->dirty_bytes_propagations += 1; - aux_ptr->unprotect_dirty_bytes = 0; - aux_ptr->unprotect_dirty_bytes_updates = 0; - aux_ptr->insert_dirty_bytes = 0; - aux_ptr->insert_dirty_bytes_updates = 0; - aux_ptr->move_dirty_bytes = 0; - aux_ptr->move_dirty_bytes_updates = 0; -#endif /* H5AC_DEBUG_DIRTY_BYTES_CREATION */ + /* if it is defined, call the sync point done callback. Note + * that this callback is defined purely for testing purposes, + * and should be undefined under normal operating circumstances. + */ + if(aux_ptr->sync_point_done != NULL) + (aux_ptr->sync_point_done)(num_entries, haddr_buf_ptr); done: + if(MPI_Offset_buf_ptr != NULL) + MPI_Offset_buf_ptr = (MPI_Offset *)H5MM_xfree((void *)MPI_Offset_buf_ptr); + if(haddr_buf_ptr != NULL) + haddr_buf_ptr = (haddr_t *)H5MM_xfree((void *)haddr_buf_ptr); FUNC_LEAVE_NOAPI(ret_value) - -} /* H5AC_propagate_flushed_and_still_clean_entries_list() */ +} /* H5AC_receive_and_apply_clean_list() */ #endif /* H5_HAVE_PARALLEL */ /*------------------------------------------------------------------------- * - * Function: H5AC_receive_and_apply_clean_list() + * Function: H5AC_receive_candidate_list() * - * Purpose: Receive the list of cleaned entries from process 0, - * and mark the specified entries as clean. + * Purpose: Receive the list of candidate entries from process 0, + * and return it in a buffer pointed to by *haddr_buf_ptr_ptr. + * Note that the caller must free this buffer if it is + * returned. * * This function must only be called by the process with * MPI_rank greater than 0. @@ -3827,27 +4277,25 @@ done: * * Return: Non-negative on success/Negative on failure. * - * Programmer: John Mainzer, 7/4/05 + * Programmer: John Mainzer, 3/17/10 * *------------------------------------------------------------------------- */ #ifdef H5_HAVE_PARALLEL static herr_t -H5AC_receive_and_apply_clean_list(H5F_t * f, - hid_t primary_dxpl_id, - hid_t secondary_dxpl_id, - H5AC_t * cache_ptr) +H5AC_receive_candidate_list(H5AC_t * cache_ptr, + int * num_entries_ptr, + haddr_t ** haddr_buf_ptr_ptr) { - herr_t ret_value = SUCCEED; /* Return value */ - H5AC_aux_t * aux_ptr = NULL; + hbool_t success = FALSE; + H5AC_aux_t * aux_ptr; haddr_t * haddr_buf_ptr = NULL; MPI_Offset * MPI_Offset_buf_ptr = NULL; - size_t buf_size; - int i = 0; int mpi_result; int num_entries; + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5AC_receive_and_apply_clean_list, FAIL) + FUNC_ENTER_NOAPI(H5AC_receive_candidate_list, FAIL) HDassert( cache_ptr != NULL ); HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); @@ -3857,180 +4305,830 @@ H5AC_receive_and_apply_clean_list(H5F_t * f, HDassert( aux_ptr != NULL ); HDassert( aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC ); HDassert( aux_ptr->mpi_rank != 0 ); + HDassert( aux_ptr-> metadata_write_strategy == + H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED ); + + HDassert( num_entries_ptr != NULL ); + HDassert( *num_entries_ptr == 0 ); + + HDassert( haddr_buf_ptr_ptr != NULL ); + HDassert( *haddr_buf_ptr_ptr == NULL ); + /* First receive the number of entries in the list so that we * can set up a buffer to receive them. If there aren't * any, we are done. */ - mpi_result = MPI_Bcast(&num_entries, 1, MPI_INT, 0, aux_ptr->mpi_comm); - - if ( mpi_result != MPI_SUCCESS ) { - + if(MPI_SUCCESS != (mpi_result = MPI_Bcast(&num_entries, 1, MPI_INT, 0, aux_ptr->mpi_comm))) HMPI_GOTO_ERROR(FAIL, "MPI_Bcast failed 1", mpi_result) - } - if ( num_entries > 0 ) - { - /* allocate a buffers to store the list of entry base addresses in */ + if(num_entries > 0) { + size_t buf_size; + int i; + /* allocate buffers to store the list of entry base addresses in */ buf_size = sizeof(MPI_Offset) * (size_t)num_entries; - MPI_Offset_buf_ptr = (MPI_Offset *)H5MM_malloc(buf_size); + if(NULL == (MPI_Offset_buf_ptr = (MPI_Offset *)H5MM_malloc(buf_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for receive buffer") + if(NULL == (haddr_buf_ptr = (haddr_t *)H5MM_malloc(sizeof(haddr_t) * (size_t)num_entries))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for haddr buffer") - if ( MPI_Offset_buf_ptr == NULL ) { + /* Now receive the list of candidate entries + * + * The peculiar structure of the following call to MPI_Bcast is + * due to MPI's (?) failure to believe in the MPI_Offset type. + * Thus the element type is MPI_BYTE, with size equal to the + * buf_size computed above. + */ + if(MPI_SUCCESS != (mpi_result = MPI_Bcast((void *)MPI_Offset_buf_ptr, (int)buf_size, MPI_BYTE, 0, aux_ptr->mpi_comm))) + HMPI_GOTO_ERROR(FAIL, "MPI_Bcast failed 2", mpi_result) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \ - "memory allocation failed for receive buffer") - } + /* translate the MPI_Offsets to haddr_t */ + i = 0; + while(i < num_entries) { + haddr_buf_ptr[i] = H5FD_mpi_MPIOff_to_haddr(MPI_Offset_buf_ptr[i]); - haddr_buf_ptr = (haddr_t *)H5MM_malloc(sizeof(haddr_t) * - (size_t)num_entries); + if(haddr_buf_ptr[i] == HADDR_UNDEF) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "can't convert MPI off to haddr") - if ( haddr_buf_ptr == NULL ) { + i++; + } /* end while */ + } /* end if */ - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \ - "memory allocation failed for haddr buffer") - } + success = TRUE; +done: + if(MPI_Offset_buf_ptr != NULL) + MPI_Offset_buf_ptr = (MPI_Offset *)H5MM_xfree((void *)MPI_Offset_buf_ptr); - /* Now receive the list of cleaned entries - * - * The peculiar structure of the following call to MPI_Bcast is - * due to MPI's (?) failure to believe in the MPI_Offset type. - * Thus the element type is MPI_BYTE, with size equal to the - * buf_size computed above. + if(success) { + /* finally, pass the number of entries and the buffer pointer + * back to the caller. Do this so that we can use the same code + * to apply the candidate list to all the processes. */ + *num_entries_ptr = num_entries; + *haddr_buf_ptr_ptr = haddr_buf_ptr; + } /* end if */ + else { + if(haddr_buf_ptr != NULL) + haddr_buf_ptr = (haddr_t *)H5MM_xfree((void *)haddr_buf_ptr); + } /* end else */ - mpi_result = MPI_Bcast((void *)MPI_Offset_buf_ptr, (int)buf_size, - MPI_BYTE, 0, aux_ptr->mpi_comm); + FUNC_LEAVE_NOAPI(ret_value) +} /* H5AC_receive_candidate_list() */ +#endif /* H5_HAVE_PARALLEL */ - if ( mpi_result != MPI_SUCCESS ) { + +/*------------------------------------------------------------------------- + * Function: H5AC_rsp__dist_md_write__flush + * + * Purpose: Routine for handling the details of running a sync point + * that is triggered by a flush -- which in turn must have been + * triggered by either a flush API call or a file close -- + * when the distributed metadata write strategy is selected. + * + * Upon entry, each process generates it own candidate list, + * being a sorted list of all dirty metadata entries currently + * in the metadata cache. Note that this list must be idendical + * across all processes, as all processes see the same stream + * of dirty metadata coming in, and use the same lists of + * candidate entries at each sync point. (At first glance, this + * argument sounds circular, but think of it in the sense of + * a recursive proof). + * + * If this this list is empty, we are done, and the function + * returns + * + * Otherwise, after the sorted list dirty metadata entries is + * constructed, each process uses the same algorithm to assign + * each entry on the candidate list to exactly one process for + * flushing. + * + * At this point, all processes participate in a barrier to + * avoid messages from the past/future bugs. + * + * Each process then flushes the entries assigned to it, and + * marks all other entries on the candidate list as clean. + * + * Finally, all processes participate in a second barrier to + * avoid messages from the past/future bugs. + * + * At the end of this process, process 0 and only process 0 + * must tidy up its lists of dirtied and cleaned entries. + * These lists are not used in the distributed metadata write + * strategy, but they must be maintained should we shift + * to a strategy that uses them. + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: John Mainzer + * April 28, 2010 + * + *------------------------------------------------------------------------- + */ +#ifdef H5_HAVE_PARALLEL +herr_t +H5AC_rsp__dist_md_write__flush(H5F_t *f, + hid_t dxpl_id, + H5AC_t * cache_ptr) +{ + int mpi_code; + int num_entries = 0; + haddr_t * haddr_buf_ptr = NULL; + H5AC_aux_t * aux_ptr; + herr_t ret_value = SUCCEED; /* Return value */ - HMPI_GOTO_ERROR(FAIL, "MPI_Bcast failed 2", mpi_result) - } + FUNC_ENTER_NOAPI(H5AC_rsp__dist_md_write__flush, FAIL) + HDassert( f != NULL ); + HDassert( f->shared->cache == cache_ptr ); - /* translate the MPI_Offsets to haddr_t */ - i = 0; - while ( i < num_entries ) - { - haddr_buf_ptr[i] = H5FD_mpi_MPIOff_to_haddr(MPI_Offset_buf_ptr[i]); + HDassert( cache_ptr != NULL ); + HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); - if ( haddr_buf_ptr[i] == HADDR_UNDEF ) { + aux_ptr = (H5AC_aux_t *)(cache_ptr->aux_ptr); - HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, \ - "can't convert MPI off to haddr") - } + HDassert( aux_ptr != NULL ); + HDassert( aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC ); + HDassert( aux_ptr->metadata_write_strategy == + H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED ); - i++; - } + /* first construct the candidate list -- initially, this will be in the + * form of a skip list. We will convert it later. + */ + if(H5C_construct_candidate_list__clean_cache(cache_ptr) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't construct candidate list.") + if(aux_ptr->candidate_slist_len > 0) { + herr_t result; - /* mark the indicated entries as clean */ - if ( H5C_mark_entries_as_clean(f, primary_dxpl_id, secondary_dxpl_id, - (int32_t)num_entries, &(haddr_buf_ptr[0])) < 0 ) { + /* convert the candidate list into the format we + * are used to receiving from process 0. + */ + if(H5AC_copy_candidate_list_to_buffer(cache_ptr, &num_entries, &haddr_buf_ptr, NULL, NULL) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't construct candidate buffer.") - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ - "Can't mark entries clean.") + /* initial sync point barrier */ + if(MPI_SUCCESS != (mpi_code = MPI_Barrier(aux_ptr->mpi_comm))) + HMPI_GOTO_ERROR(FAIL, "MPI_Barrier failed 1", mpi_code) - } - } + /* apply the candidate list */ + aux_ptr->write_permitted = TRUE; -done: + result = H5C_apply_candidate_list(f, + dxpl_id, + dxpl_id, + cache_ptr, + num_entries, + haddr_buf_ptr, + aux_ptr->mpi_rank, + aux_ptr->mpi_size); - if ( MPI_Offset_buf_ptr != NULL ) { + aux_ptr->write_permitted = FALSE; - MPI_Offset_buf_ptr = - (MPI_Offset *)H5MM_xfree((void *)MPI_Offset_buf_ptr); - } + if(result < 0) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't apply candidate list.") - if ( haddr_buf_ptr != NULL ) { + /* this code exists primarily for the test bed -- it allows us to + * enforce posix semantics on the server that pretends to be a + * file system in our parallel tests. + */ + if(aux_ptr->write_done != NULL) + (aux_ptr->write_done)(); + /* final sync point barrier */ + if(MPI_SUCCESS != (mpi_code = MPI_Barrier(aux_ptr->mpi_comm))) + HMPI_GOTO_ERROR(FAIL, "MPI_Barrier failed 1", mpi_code) + + /* if this is process zero, tidy up the dirtied, + * and flushed and still clean lists. + */ + if(aux_ptr->mpi_rank == 0) { + if(H5AC_tidy_cache_0_lists(cache_ptr, num_entries, haddr_buf_ptr) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't tidy up process 0 lists.") + } /* end if */ + } /* end if */ + + /* if it is defined, call the sync point done callback. Note + * that this callback is defined purely for testing purposes, + * and should be undefined under normal operating circumstances. + */ + if(aux_ptr->sync_point_done != NULL) + (aux_ptr->sync_point_done)(num_entries, haddr_buf_ptr); + +done: + if(haddr_buf_ptr != NULL) haddr_buf_ptr = (haddr_t *)H5MM_xfree((void *)haddr_buf_ptr); - } FUNC_LEAVE_NOAPI(ret_value) +} /* H5AC_rsp__dist_md_write__flush() */ +#endif /* H5_HAVE_PARALLEL */ -} /* H5AC_receive_and_apply_clean_list() */ + +/*------------------------------------------------------------------------- + * Function: H5AC_rsp__dist_md_write__flush_to_min_clean + * + * Purpose: Routine for handling the details of running a sync point + * triggered by the accumulation of dirty metadata (as + * opposed to a flush call to the API) when the distributed + * metadata write strategy is selected. + * + * After invocation and initial sanity checking this function + * first checks to see if evictions are enabled -- if they + * are not, the function does nothing and returns. + * + * Otherwise, process zero constructs a list of entries to + * be flushed in order to bring the process zero cache back + * within its min clean requirement. Note that this list + * (the candidate list) may be empty. + * + * Then, all processes participate in a barrier. + * + * After the barrier, process 0 broadcasts the number of + * entries in the candidate list prepared above, and all + * other processes receive this number. + * + * If this number is zero, we are done, and the function + * returns without further action. + * + * Otherwise, process 0 broadcasts the sorted list of + * candidate entries, and all other processes receive it. + * + * Then, each process uses the same algorithm to assign + * each entry on the candidate list to exactly one process + * for flushing. + * + * Each process then flushes the entries assigned to it, and + * marks all other entries on the candidate list as clean. + * + * Finally, all processes participate in a second barrier to + * avoid messages from the past/future bugs. + * + * At the end of this process, process 0 and only process 0 + * must tidy up its lists of dirtied and cleaned entries. + * These lists are not used in the distributed metadata write + * strategy, but they must be maintained should we shift + * to a strategy that uses them. + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: John Mainzer + * April 28, 2010 + * + *------------------------------------------------------------------------- + */ +#ifdef H5_HAVE_PARALLEL +herr_t +H5AC_rsp__dist_md_write__flush_to_min_clean(H5F_t *f, + hid_t dxpl_id, + H5AC_t * cache_ptr) +{ + hbool_t evictions_enabled; + H5AC_aux_t * aux_ptr; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5AC_rsp__dist_md_write__flush_to_min_clean, FAIL) + + HDassert( f != NULL ); + HDassert( f->shared->cache == cache_ptr ); + + HDassert( cache_ptr != NULL ); + HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); + + aux_ptr = (H5AC_aux_t *)(cache_ptr->aux_ptr); + + HDassert( aux_ptr != NULL ); + HDassert( aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC ); + HDassert( aux_ptr->metadata_write_strategy == + H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED ); + + /* Query if evictions are allowed */ + if(H5C_get_evictions_enabled((const H5C_t *)cache_ptr, &evictions_enabled) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, FAIL, "H5C_get_evictions_enabled() failed.") + + if(evictions_enabled) { + /* construct candidate list -- process 0 only */ + if(aux_ptr->mpi_rank == 0) { + if(H5AC_construct_candidate_list(cache_ptr, aux_ptr, H5AC_SYNC_POINT_OP__FLUSH_TO_MIN_CLEAN) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't construct candidate list.") + } /* mpi rank == 0 */ + + /* propagate and apply candidate list -- all processes */ + if(H5AC_propagate_and_apply_candidate_list(f, dxpl_id, cache_ptr) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't propagate and apply candidate list.") + } /* evictions enabled */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5AC_rsp__dist_md_write__flush_to_min_clean() */ +#endif /* H5_HAVE_PARALLEL */ /*------------------------------------------------------------------------- - * Function: H5AC_flush_entries + * Function: H5AC_rsp__p0_only__flush * - * Purpose: Flush the metadata cache associated with the specified file, - * only writing from rank 0, but propagating the cleaned entries - * to all ranks. + * Purpose: Routine for handling the details of running a sync point + * that is triggered a flush -- which in turn must have been + * triggered by either a flush API call or a file close -- + * when the process 0 only metadata write strategy is selected. * - * Return: Non-negative on success/Negative on failure if there was a - * request to flush all items and something was protected. + * First, all processes participate in a barrier. * - * Programmer: Quincey Koziol - * koziol@hdfgroup.org - * Aug 22 2009 + * Then process zero flushes all dirty entries, and broadcasts + * they number of clean entries (if any) to all the other + * caches. + * + * If this number is zero, we are done. + * + * Otherwise, process 0 broadcasts the list of cleaned + * entries, and all other processes which are part of this + * file group receive it, and mark the listed entries as + * clean in their caches. + * + * Since all processes have the same set of dirty + * entries at the beginning of the sync point, and all + * entries that will be written are written before + * process zero broadcasts the number of cleaned entries, + * there is no need for a closing barrier. + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: John Mainzer + * April 28, 2010 * *------------------------------------------------------------------------- */ +#ifdef H5_HAVE_PARALLEL herr_t -H5AC_flush_entries(H5F_t *f) +H5AC_rsp__p0_only__flush(H5F_t *f, + hid_t dxpl_id, + H5AC_t * cache_ptr) { - herr_t ret_value = SUCCEED; /* Return value */ + int mpi_code; + H5AC_aux_t * aux_ptr; + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5AC_flush_entries) + FUNC_ENTER_NOAPI(H5AC_rsp__p0_only__flush, FAIL) - HDassert(f); - HDassert(f->shared->cache); + HDassert( f != NULL ); + HDassert( f->shared->cache == cache_ptr ); - /* Check if we have >1 ranks */ - if(f->shared->cache->aux_ptr) { - H5AC_aux_t * aux_ptr = f->shared->cache->aux_ptr; - int mpi_code; + HDassert( cache_ptr != NULL ); + HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); -#if H5AC_DEBUG_DIRTY_BYTES_CREATION - HDfprintf(stdout, - "%d::H5AC_flush: (u/uu/i/iu/r/ru) = %d/%d/%d/%d/%d/%d\n", - (int)(aux_ptr->mpi_rank), - (int)(aux_ptr->unprotect_dirty_bytes), - (int)(aux_ptr->unprotect_dirty_bytes_updates), - (int)(aux_ptr->insert_dirty_bytes), - (int)(aux_ptr->insert_dirty_bytes_updates), - (int)(aux_ptr->move_dirty_bytes), - (int)(aux_ptr->move_dirty_bytes_updates)); -#endif /* H5AC_DEBUG_DIRTY_BYTES_CREATION */ + aux_ptr = (H5AC_aux_t *)(cache_ptr->aux_ptr); + + HDassert( aux_ptr != NULL ); + HDassert( aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC ); + HDassert( aux_ptr->metadata_write_strategy == + H5AC_METADATA_WRITE_STRATEGY__PROCESS_0_ONLY ); + + + /* to prevent "messages from the future" we must + * synchronize all processes before we start the flush. + * Hence the following barrier. + */ + if(MPI_SUCCESS != (mpi_code = MPI_Barrier(aux_ptr->mpi_comm))) + HMPI_GOTO_ERROR(FAIL, "MPI_Barrier failed 1", mpi_code) + + /* Flush data to disk, from rank 0 process */ + if(aux_ptr->mpi_rank == 0) { + herr_t result; + + aux_ptr->write_permitted = TRUE; + + result = H5C_flush_cache(f, dxpl_id, dxpl_id, H5AC__NO_FLAGS_SET); + + aux_ptr->write_permitted = FALSE; + + if(result < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't flush.") + + if(aux_ptr->write_done != NULL) + (aux_ptr->write_done)(); + } /* end if */ + + /* Propagate cleaned entries to other ranks. */ + if(H5AC_propagate_flushed_and_still_clean_entries_list(f, H5AC_noblock_dxpl_id, cache_ptr) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't propagate clean entries list.") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5AC_rsp__p0_only__flush() */ +#endif /* H5_HAVE_PARALLEL */ + + +/*------------------------------------------------------------------------- + * Function: H5AC_rsp__p0_only__flush_to_min_clean + * + * Purpose: Routine for handling the details of running a sync point + * triggered by the accumulation of dirty metadata (as + * opposed to a flush call to the API) when the process 0 + * only metadata write strategy is selected. + * + * After invocation and initial sanity checking this function + * first checks to see if evictions are enabled -- if they + * are not, the function does nothing and returns. + * + * Otherwise, all processes participate in a barrier. + * + * After the barrier, if this is process 0, the function + * causes the cache to flush sufficient entries to get the + * cache back within its minimum clean fraction, and broadcast + * the number of entries which have been flushed since + * the last sync point, and are still clean. + * + * If this number is zero, we are done. + * + * Otherwise, process 0 broadcasts the list of cleaned + * entries, and all other processes which are part of this + * file group receive it, and mark the listed entries as + * clean in their caches. + * + * Since all processes have the same set of dirty + * entries at the beginning of the sync point, and all + * entries that will be written are written before + * process zero broadcasts the number of cleaned entries, + * there is no need for a closing barrier. + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: John Mainzer + * April 28, 2010 + * + *------------------------------------------------------------------------- + */ +#ifdef H5_HAVE_PARALLEL +herr_t +H5AC_rsp__p0_only__flush_to_min_clean(H5F_t *f, + hid_t dxpl_id, + H5AC_t * cache_ptr) +{ + hbool_t evictions_enabled; + H5AC_aux_t * aux_ptr; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5AC_rsp__p0_only__flush_to_min_clean, FAIL) + + HDassert( f != NULL ); + HDassert( f->shared->cache == cache_ptr ); + + HDassert( cache_ptr != NULL ); + HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); + + aux_ptr = (H5AC_aux_t *)(cache_ptr->aux_ptr); + + HDassert( aux_ptr != NULL ); + HDassert( aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC ); + HDassert( aux_ptr->metadata_write_strategy == + H5AC_METADATA_WRITE_STRATEGY__PROCESS_0_ONLY ); + + /* Query if evictions are allowed */ + if(H5C_get_evictions_enabled((const H5C_t *)cache_ptr, &evictions_enabled) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, FAIL, "H5C_get_evictions_enabled() failed.") + + /* Flush if evictions are allowed -- following call + * will cause process 0 to flush to min clean size, + * and then propagate the newly clean entries to the + * other processes. + * + * Otherwise, do nothing. + */ + if(evictions_enabled) { + int mpi_code; /* to prevent "messages from the future" we must synchronize all - * processes before we start the flush. Hence the following - * barrier. + * processes before we start the flush. This synchronization may + * already be done -- hence the do_barrier parameter. */ if(MPI_SUCCESS != (mpi_code = MPI_Barrier(aux_ptr->mpi_comm))) HMPI_GOTO_ERROR(FAIL, "MPI_Barrier failed", mpi_code) - /* Flush data to disk, from rank 0 process */ - if(aux_ptr->mpi_rank == 0 ) { - herr_t status; + if(0 == aux_ptr->mpi_rank) { + herr_t result; - aux_ptr->write_permitted = TRUE; + /* here, process 0 flushes as many entries as necessary to + * comply with the currently specified min clean size. + * Note that it is quite possible that no entries will be + * flushed. + */ + aux_ptr->write_permitted = TRUE; - status = H5C_flush_cache(f, - H5AC_noblock_dxpl_id, - H5AC_noblock_dxpl_id, - H5AC__NO_FLAGS_SET); + result = H5C_flush_to_min_clean(f, dxpl_id, H5AC_noblock_dxpl_id); - aux_ptr->write_permitted = FALSE; + aux_ptr->write_permitted = FALSE; - if(status < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't flush.") + if(result < 0) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5C_flush_to_min_clean() failed.") + /* this call exists primarily for the test code -- it is used + * to enforce POSIX semantics on the process used to simulate + * reads and writes in t_cache.c. + */ if(aux_ptr->write_done != NULL) (aux_ptr->write_done)(); - } /* end if ( aux_ptr->mpi_rank == 0 ) */ + } /* end if */ - /* Propagate cleaned entries to other ranks */ - if(H5AC_propagate_flushed_and_still_clean_entries_list(f, - H5AC_noblock_dxpl_id, - f->shared->cache, - FALSE) < 0 ) + if(H5AC_propagate_flushed_and_still_clean_entries_list(f, dxpl_id, cache_ptr) < 0) HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't propagate clean entries list.") - } /* end if ( aux_ptr != NULL ) */ + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5AC_rsp__p0_only__flush_to_min_clean() */ +#endif /* H5_HAVE_PARALLEL */ + + +/*------------------------------------------------------------------------- + * Function: H5AC_run_sync_point + * + * Purpose: Top level routine for managing a sync point between all + * meta data caches in the parallel case. Since all caches + * see the same sequence of dirty metadata, we simply count + * bytes of dirty metadata, and run a sync point whenever the + * number of dirty bytes of metadata seen since the last + * sync point exceeds a threshold that is common across all + * processes. We also run sync points in response to + * HDF5 API calls triggering either a flush or a file close. + * + * In earlier versions of PHDF5, only the metadata cache with + * mpi rank 0 was allowed to write to file. All other + * metadata caches on processes with rank greater than 0 were + * required to retain dirty entries until they were notified + * that the entry is was clean. + * + * This function was created to make it easier for us to + * experiment with other options, as it is a single point + * for the execution of sync points. + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: John Mainzer + * March 11, 2010 + * + *------------------------------------------------------------------------- + */ +#ifdef H5_HAVE_PARALLEL +herr_t +H5AC_run_sync_point(H5F_t *f, + hid_t dxpl_id, + int sync_point_op) +{ + H5AC_t * cache_ptr; + H5AC_aux_t * aux_ptr; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5AC_run_sync_point, FAIL) + + HDassert( f != NULL ); + + cache_ptr = f->shared->cache; + + HDassert( cache_ptr != NULL ); + HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); + + aux_ptr = (H5AC_aux_t *)(cache_ptr->aux_ptr); + + HDassert( aux_ptr != NULL ); + HDassert( aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC ); + + HDassert( ( sync_point_op == H5AC_SYNC_POINT_OP__FLUSH_TO_MIN_CLEAN ) || + ( sync_point_op == H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED ) ); + +#if H5AC_DEBUG_DIRTY_BYTES_CREATION + HDfprintf(stdout, + "%d:H5AC_propagate...:%d: (u/uu/i/iu/r/ru) = %d/%d/%d/%d/%d/%d\n", + (int)(aux_ptr->mpi_rank), + (int)(aux_ptr->dirty_bytes_propagations), + (int)(aux_ptr->unprotect_dirty_bytes), + (int)(aux_ptr->unprotect_dirty_bytes_updates), + (int)(aux_ptr->insert_dirty_bytes), + (int)(aux_ptr->insert_dirty_bytes_updates), + (int)(aux_ptr->rename_dirty_bytes), + (int)(aux_ptr->rename_dirty_bytes_updates)); +#endif /* H5AC_DEBUG_DIRTY_BYTES_CREATION */ + + switch(aux_ptr->metadata_write_strategy) { + case H5AC_METADATA_WRITE_STRATEGY__PROCESS_0_ONLY: + switch(sync_point_op) { + case H5AC_SYNC_POINT_OP__FLUSH_TO_MIN_CLEAN: + if(H5AC_rsp__p0_only__flush_to_min_clean(f, dxpl_id, cache_ptr) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, FAIL, "H5AC_rsp__p0_only__flush_to_min_clean() failed.") + break; + + case H5AC_SYNC_POINT_OP__FLUSH_CACHE: + if(H5AC_rsp__p0_only__flush(f, dxpl_id, cache_ptr) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, FAIL, "H5AC_rsp__p0_only__flush() failed.") + break; + + default: + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unknown flush op"); + break; + } /* end switch */ + break; + + case H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED: + switch(sync_point_op) { + case H5AC_SYNC_POINT_OP__FLUSH_TO_MIN_CLEAN: + if(H5AC_rsp__dist_md_write__flush_to_min_clean(f, dxpl_id, cache_ptr) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, FAIL, "H5AC_rsp__dist_md_write__flush() failed.") + break; + + case H5AC_SYNC_POINT_OP__FLUSH_CACHE: + if(H5AC_rsp__dist_md_write__flush(f, dxpl_id, cache_ptr) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, FAIL, "H5AC_rsp__dist_md_write__flush() failed.") + break; + + default: + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unknown flush op"); + break; + } /* end switch */ + break; + + default: + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Unknown metadata write strategy.") + break; + } /* end switch */ + + /* reset the dirty bytes count */ + aux_ptr->dirty_bytes = 0; + +#if H5AC_DEBUG_DIRTY_BYTES_CREATION + aux_ptr->dirty_bytes_propagations += 1; + aux_ptr->unprotect_dirty_bytes = 0; + aux_ptr->unprotect_dirty_bytes_updates = 0; + aux_ptr->insert_dirty_bytes = 0; + aux_ptr->insert_dirty_bytes_updates = 0; + aux_ptr->rename_dirty_bytes = 0; + aux_ptr->rename_dirty_bytes_updates = 0; +#endif /* H5AC_DEBUG_DIRTY_BYTES_CREATION */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5AC_run_sync_point() */ +#endif /* H5_HAVE_PARALLEL */ + + +/*------------------------------------------------------------------------- + * Function: H5AC_tidy_cache_0_lists() + * + * Purpose: In the distributed metadata write strategy, not all dirty + * entries are written by process 0 -- thus we must tidy + * up the dirtied, and flushed and still clean lists + * maintained by process zero after each sync point. + * + * This procedure exists to tend to this issue. + * + * At this point, all entries that process 0 cleared should + * have been removed from both the dirty and flushed and + * still clean lists, and entries that process 0 has flushed + * should have been removed from the dirtied list and added + * to the flushed and still clean list. + * + * However, since the distributed metadata write strategy + * doesn't make use of these lists, the objective is simply + * to maintain these lists in consistent state that allows + * them to be used should the metadata write strategy change + * to one that uses these lists. + * + * Thus for our purposes, all we need to do is remove from + * the dirtied and flushed and still clean lists all + * references to entries that appear in the candidate list. + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: John Mainzer + * 4/20/10 + * + *------------------------------------------------------------------------- + */ +#ifdef H5_HAVE_PARALLEL +static herr_t +H5AC_tidy_cache_0_lists(H5AC_t * cache_ptr, + int num_candidates, + haddr_t * candidates_list_ptr) + +{ + int i; + H5AC_aux_t * aux_ptr; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5AC_tidy_cache_0_lists, FAIL) + + HDassert( cache_ptr != NULL ); + HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); + + aux_ptr = (H5AC_aux_t *)(cache_ptr->aux_ptr); + + HDassert( aux_ptr != NULL ); + HDassert( aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC ); + HDassert( aux_ptr->metadata_write_strategy == + H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED ); + HDassert( aux_ptr->mpi_rank == 0 ); + HDassert( num_candidates > 0 ); + HDassert( candidates_list_ptr != NULL ); + + /* clean up dirtied and flushed and still clean lists by removing + * all entries on the candidate list. Cleared entries should + * have been removed from both the dirty and cleaned lists at + * this point, flushed entries should have been added to the + * cleaned list. However, for this metadata write strategy, + * we just want to remove all references to the candidate entries. + */ + for(i = 0; i < num_candidates; i++) { + H5AC_slist_entry_t * d_slist_entry_ptr; + H5AC_slist_entry_t * c_slist_entry_ptr; + haddr_t addr; + + addr = candidates_list_ptr[i]; + + /* addr must be either on the dirtied list, or on the flushed + * and still clean list. Remove it. + */ + d_slist_entry_ptr = (H5AC_slist_entry_t *)H5SL_search(aux_ptr->d_slist_ptr, (void *)&addr); + if(d_slist_entry_ptr != NULL) { + HDassert(d_slist_entry_ptr->magic == H5AC__H5AC_SLIST_ENTRY_T_MAGIC); + HDassert(d_slist_entry_ptr->addr == addr); + + if(H5SL_remove(aux_ptr->d_slist_ptr, (void *)(&addr)) != d_slist_entry_ptr) + HGOTO_ERROR(H5E_CACHE, H5E_CANTDELETE, FAIL, "Can't delete entry from dirty entry slist.") + + d_slist_entry_ptr->magic = 0; + H5FL_FREE(H5AC_slist_entry_t, d_slist_entry_ptr); + + aux_ptr->d_slist_len -= 1; + + HDassert(aux_ptr->d_slist_len >= 0); + } /* end if */ + + c_slist_entry_ptr = (H5AC_slist_entry_t *)H5SL_search(aux_ptr->c_slist_ptr, (void *)&addr); + if(c_slist_entry_ptr != NULL) { + HDassert(c_slist_entry_ptr->magic == H5AC__H5AC_SLIST_ENTRY_T_MAGIC); + HDassert(c_slist_entry_ptr->addr == addr); + + if(H5SL_remove(aux_ptr->c_slist_ptr, (void *)(&addr)) != c_slist_entry_ptr) + HGOTO_ERROR(H5E_CACHE, H5E_CANTDELETE, FAIL, "Can't delete entry from clean entry slist.") + + c_slist_entry_ptr->magic = 0; + H5FL_FREE(H5AC_slist_entry_t, c_slist_entry_ptr); + + aux_ptr->c_slist_len -= 1; + + HDassert( aux_ptr->c_slist_len >= 0 ); + } /* end if */ + } /* end for */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5AC_tidy_cache_0_lists() */ +#endif /* H5_HAVE_PARALLEL */ + + +/*------------------------------------------------------------------------- + * Function: H5AC_flush_entries + * + * Purpose: Flush the metadata cache associated with the specified file, + * only writing from rank 0, but propagating the cleaned entries + * to all ranks. + * + * Return: Non-negative on success/Negative on failure if there was a + * request to flush all items and something was protected. + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Aug 22 2009 + * + *------------------------------------------------------------------------- + */ +#ifdef H5_HAVE_PARALLEL +herr_t +H5AC_flush_entries(H5F_t *f) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5AC_flush_entries) + + HDassert(f); + HDassert(f->shared->cache); + + /* Check if we have >1 ranks */ + if(f->shared->cache->aux_ptr) { + if(H5AC_run_sync_point(f, H5AC_noblock_dxpl_id, H5AC_SYNC_POINT_OP__FLUSH_CACHE) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't run sync point.") + } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) @@ -4057,7 +5155,6 @@ herr_t H5AC_ignore_tags(H5F_t * f) { /* Variable Declarations */ - H5AC_t * cache_ptr = NULL; herr_t ret_value = SUCCEED; /* Function Enter Macro */ @@ -4068,18 +5165,12 @@ H5AC_ignore_tags(H5F_t * f) HDassert(f->shared); HDassert(f->shared->cache); - /* Get cache pointer */ - cache_ptr = f->shared->cache; - /* Set up a new metadata tag */ - if (H5C_ignore_tags(cache_ptr) < 0) + if(H5C_ignore_tags(f->shared->cache) < 0) HGOTO_ERROR(H5E_CACHE, H5E_CANTSET, FAIL, "H5C_ignore_tags() failed.") done: - - /* Function Leave Macro */ FUNC_LEAVE_NOAPI(ret_value) - } /* H5AC_ignore_tags() */ @@ -4103,27 +5194,24 @@ H5AC_tag(hid_t dxpl_id, haddr_t metadata_tag, haddr_t * prev_tag) herr_t ret_value = SUCCEED; /* Function Enter Macro */ - FUNC_ENTER_NOAPI_NOINIT(H5AC_tag) + FUNC_ENTER_NOAPI(H5AC_tag, FAIL) /* Check Arguments */ if(NULL == (dxpl = (H5P_genplist_t *)H5I_object_verify(dxpl_id, H5I_GENPROP_LST))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list"); + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list") /* Get the current tag value and return that (if prev_tag is NOT null)*/ - if (prev_tag) { - if( (H5P_get(dxpl, "H5AC_metadata_tag", prev_tag)) < 0 ) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to query dxpl"); - } + if(prev_tag) { + if((H5P_get(dxpl, "H5AC_metadata_tag", prev_tag)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to query dxpl") + } /* end if */ /* Set the provided tag value in the dxpl_id. */ if(H5P_set(dxpl, "H5AC_metadata_tag", &metadata_tag) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set property in dxpl") done: - - /* Function Leave Macro */ - FUNC_LEAVE_NOAPI(ret_value); - + FUNC_LEAVE_NOAPI(ret_value) } /* H5AC_tag */ @@ -4144,22 +5232,19 @@ done: herr_t H5AC_retag_copied_metadata(H5F_t * f, haddr_t metadata_tag) { - /* Variable Declarations */ herr_t ret_value = SUCCEED; /* Function Enter Macro */ - FUNC_ENTER_NOAPI_NOINIT(H5AC_retag_copied_metadata) + FUNC_ENTER_NOAPI(H5AC_retag_copied_metadata, FAIL) /* Assertions */ HDassert(f); HDassert(f->shared); /* Call cache-level function to retag entries */ - H5C_retag_copied_metadata(f->shared->cache, metadata_tag); + H5C_retag_copied_metadata(f->shared->cache, metadata_tag); done: - - /* Function Leave Macro */ - FUNC_LEAVE_NOAPI(ret_value); - + FUNC_LEAVE_NOAPI(ret_value) } /* H5AC_retag_copied_metadata */ + diff --git a/src/H5ACpkg.h b/src/H5ACpkg.h index d5346f5..3060a70 100644 --- a/src/H5ACpkg.h +++ b/src/H5ACpkg.h @@ -46,6 +46,17 @@ #define H5AC_DEBUG_DIRTY_BYTES_CREATION 0 +#ifdef H5_HAVE_PARALLEL + +/* the following #defined are used to specify the operation required + * at a sync point. + */ + +#define H5AC_SYNC_POINT_OP__FLUSH_TO_MIN_CLEAN 0 +#define H5AC_SYNC_POINT_OP__FLUSH_CACHE 1 + +#endif /* H5_HAVE_PARALLEL */ + /*------------------------------------------------------------------------- * It is a bit difficult to set ranges of allowable values on the * dirty_bytes_threshold field of H5AC_aux_t. The following are @@ -59,6 +70,9 @@ #define H5AC__MAX_DIRTY_BYTES_THRESHOLD (int32_t) \ (H5C__MAX_MAX_CACHE_SIZE / 4) +#define H5AC__DEFAULT_METADATA_WRITE_STRATEGY \ + H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED + /**************************************************************************** * * structure H5AC_aux_t @@ -162,6 +176,12 @@ * broadcast. This field is reset to zero after each such * broadcast. * + * metadata_write_strategy: Integer code indicating how we will be + * writing the metadata. In the first incarnation of + * this code, all writes were done from process 0. This + * field exists to facilitate experiments with other + * strategies. + * * dirty_bytes_propagations: This field only exists when the * H5AC_DEBUG_DIRTY_BYTES_CREATION #define is TRUE. * @@ -211,6 +231,19 @@ * been created via move operations since the last time * the cleaned list was propagated. * + * Things have changed a bit since the following four fields were defined. + * If metadata_write_strategy is H5AC_METADATA_WRITE_STRATEGY__PROCESS_0_ONLY, + * all comments hold as before -- with the caviate that pending further + * coding, the process 0 metadata cache is forbidden to flush entries outside + * of a sync point. + * + * However, for different metadata write strategies, these fields are used + * only to maintain the correct dirty byte count on process zero -- and in + * most if not all cases, this is redundant, as process zero will be barred + * from flushing entries outside of a sync point. + * + * JRM -- 3/16/10 + * * d_slist_ptr: Pointer to an instance of H5SL_t used to maintain a list * of entries that have been dirtied since the last time they * were listed in a clean entries broadcast. This list is @@ -259,6 +292,17 @@ * contain the value 0 on all processes other than process 0. * It exists primarily for sanity checking. * + * The following two fields are used only when metadata_write_strategy + * is H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED. + * + * candidate_slist_ptr: Pointer to an instance of H5SL_t used by process 0 + * to construct a list of entries to be flushed at this sync + * point. This list is then broadcast to the other processes, + * which then either flush or mark clean all entries on it. + * + * candidate_slist_len: Integer field containing the number of entries on the + * candidate list. It exists primarily for sanity checking. + * * write_done: In the parallel test bed, it is necessary to ensure that * all writes to the server process from cache 0 complete * before it enters the barrier call with the other caches. @@ -271,6 +315,19 @@ * This field must be set to NULL when the callback is not * needed. * + * Note: This field has been extended for use by all processes + * with the addition of support for the distributed + * metadata write strategy. + * JRM -- 5/9/10 + * + * sync_point_done: In the parallel test bed, it is necessary to verify + * that the expected writes, and only the expected writes, + * have taken place at the end of each sync point. + * + * The sync_point_done callback allows t_cache to perform + * this verification. The field is set to NULL when the + * callback is not needed. + * ****************************************************************************/ #ifdef H5_HAVE_PARALLEL @@ -293,6 +350,8 @@ typedef struct H5AC_aux_t int32_t dirty_bytes; + int32_t metadata_write_strategy; + #if H5AC_DEBUG_DIRTY_BYTES_CREATION int32_t dirty_bytes_propagations; @@ -316,8 +375,15 @@ typedef struct H5AC_aux_t int32_t c_slist_len; + H5SL_t * candidate_slist_ptr; + + int32_t candidate_slist_len; + void (* write_done)(void); + void (* sync_point_done)(int num_writes, + haddr_t * written_entries_tbl); + } H5AC_aux_t; /* struct H5AC_aux_t */ #endif /* H5_HAVE_PARALLEL */ diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h index 221dd41..b55572d 100644 --- a/src/H5ACprivate.h +++ b/src/H5ACprivate.h @@ -223,6 +223,9 @@ H5_DLLVAR hid_t H5AC_ind_dxpl_id; /* Default cache configuration. */ +#define H5AC__DEFAULT_METADATA_WRITE_STRATEGY \ + H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED + #ifdef H5_HAVE_PARALLEL #define H5AC__DEFAULT_CACHE_CONFIG \ { \ @@ -255,7 +258,9 @@ H5_DLLVAR hid_t H5AC_ind_dxpl_id; /* int epochs_before_eviction = */ 3, \ /* hbool_t apply_empty_reserve = */ TRUE, \ /* double empty_reserve = */ 0.1, \ - /* int dirty_bytes_threshold = */ (256 * 1024) \ + /* int dirty_bytes_threshold = */ (256 * 1024), \ + /* int metadata_write_strategy = */ \ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY \ } #else /* H5_HAVE_PARALLEL */ #define H5AC__DEFAULT_CACHE_CONFIG \ @@ -289,7 +294,9 @@ H5_DLLVAR hid_t H5AC_ind_dxpl_id; /* int epochs_before_eviction = */ 3, \ /* hbool_t apply_empty_reserve = */ TRUE, \ /* double empty_reserve = */ 0.1, \ - /* int dirty_bytes_threshold = */ (256 * 1024) \ + /* int dirty_bytes_threshold = */ (256 * 1024), \ + /* int metadata_write_strategy = */ \ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY \ } #endif /* H5_HAVE_PARALLEL */ @@ -359,6 +366,9 @@ H5_DLL herr_t H5AC_expunge_entry(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr, unsigned flags); +H5_DLL herr_t H5AC_set_sync_point_done_callback(H5C_t *cache_ptr, + void (*sync_point_done)(int num_writes, haddr_t *written_entries_tbl)); + H5_DLL herr_t H5AC_set_write_done_callback(H5C_t * cache_ptr, void (* write_done)(void)); H5_DLL herr_t H5AC_stats(const H5F_t *f); @@ -393,5 +403,9 @@ H5_DLL herr_t H5AC_retag_copied_metadata(H5F_t * f, haddr_t metadata_tag); H5_DLL herr_t H5AC_ignore_tags(H5F_t * f); +#ifdef H5_HAVE_PARALLEL +H5_DLL herr_t H5AC_add_candidate(H5AC_t * cache_ptr, haddr_t addr); +#endif /* H5_HAVE_PARALLEL */ + #endif /* !_H5ACprivate_H */ diff --git a/src/H5ACpublic.h b/src/H5ACpublic.h index 02941b6..639179c 100644 --- a/src/H5ACpublic.h +++ b/src/H5ACpublic.h @@ -354,21 +354,22 @@ extern "C" { * Parallel Configuration Fields: * * In PHDF5, all operations that modify metadata must be executed collectively. + * * We used to think that this was enough to ensure consistency across the * metadata caches, but since we allow processes to read metadata individually, * the order of dirty entries in the LRU list can vary across processes, * which can result in inconsistencies between the caches. * - * To prevent this, only the metadata cache on process 0 is allowed to write - * to file, and then only after synchronizing with the other caches. After - * it writes entries to file, it sends the base addresses of the now clean - * entries to the other caches, so they can mark these entries clean as well. + * PHDF5 uses several strategies to prevent such inconsistencies in metadata, + * all of which use the fact that the same stream of dirty metadata is seen + * by all processes for purposes of synchronization. This is done by + * having each process count the number of bytes of dirty metadata generated, + * and then running a "sync point" whenever this count exceeds a user + * specified threshold (see dirty_bytes_threshold below). * - * The different caches know when to synchronize caches by counting the - * number of bytes of dirty metadata created by the collective operations - * modifying metadata. Whenever this count exceeds a user specified - * threshold (see below), process 0 flushes down to its minimum clean size, - * and then sends the list of newly cleaned entries to the other caches. + * The current metadata write strategy is indicated by the + * metadata_write_strategy field. The possible values of this field, along + * with the associated metadata write strategies are discussed below. * * dirty_bytes_threshold: Threshold of dirty byte creation used to * synchronize updates between caches. (See above for outline and @@ -378,11 +379,67 @@ extern "C" { * file. This field is ignored unless HDF5 has been compiled for * parallel. * + * metadata_write_strategy: Integer field containing a code indicating the + * desired metadata write strategy. The valid values of this field + * are enumerated and discussed below: + * + * + * H5AC_METADATA_WRITE_STRATEGY__PROCESS_0_ONLY: + * + * When metadata_write_strategy is set to this value, only process + * zero is allowed to write dirty metadata to disk. All other + * processes must retain dirty metadata until they are informed at + * a sync point that the dirty metadata in question has been written + * to disk. + * + * When the sync point is reached (or when there is a user generated + * flush), process zero flushes sufficient entries to bring it into + * complience with its min clean size (or flushes all dirty entries in + * the case of a user generated flush), broad casts the list of + * entries just cleaned to all the other processes, and then exits + * the sync point. + * + * Upon receipt of the broadcast, the other processes mark the indicated + * entries as clean, and leave the sync point as well. + * + * + * H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED: + * + * In the distributed metadata write strategy, process zero still makes + * the decisions as to what entries should be flushed, but the actual + * flushes are distributed across the processes in the computation to + * the extent possible. + * + * In this strategy, when a sync point is triggered (either by dirty + * metadata creation or manual flush), all processes enter a barrier. + * + * On the other side of the barrier, process 0 constructs an ordered + * list of the entries to be flushed, and then broadcasts this list + * to the caches in all the processes. + * + * All processes then scan the list of entries to be flushed, flushing + * some, and marking the rest as clean. The algorithm for this purpose + * ensures that each entry in the list is flushed exactly once, and + * all are marked clean in each cache. + * + * Note that in the case of a flush of the cache, no message passing + * is necessary, as all processes have the same list of dirty entries, + * and all of these entries must be flushed. Thus in this case it is + * sufficient for each process to sort its list of dirty entries after + * leaving the initial barrier, and use this list as if it had been + * received from process zero. + * + * To avoid possible messages from the past/future, all caches must + * wait until all caches are done before leaving the sync point. + * ****************************************************************************/ #define H5AC__CURR_CACHE_CONFIG_VERSION 1 #define H5AC__MAX_TRACE_FILE_NAME_LEN 1024 +#define H5AC_METADATA_WRITE_STRATEGY__PROCESS_0_ONLY 0 +#define H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED 1 + typedef struct H5AC_cache_config_t { /* general configuration fields: */ @@ -440,6 +497,7 @@ typedef struct H5AC_cache_config_t /* parallel configuration fields: */ int dirty_bytes_threshold; + int metadata_write_strategy; } H5AC_cache_config_t; @@ -335,6 +335,624 @@ done: /*------------------------------------------------------------------------- + * Function: H5C_apply_candidate_list + * + * Purpose: Apply the supplied candidate list. + * + * We used to do this by simply having each process write + * every mpi_size-th entry in the candidate list, starting + * at index mpi_rank, and mark all the others clean. + * + * However, this can cause unnecessary contention in a file + * system by increasing the number of processes writing to + * adjacent locations in the HDF5 file. + * + * To attempt to minimize this, we now arange matters such + * that each process writes n adjacent entries in the + * candidate list, and marks all others clean. We must do + * this in such a fashion as to guarantee that each entry + * on the candidate list is written by exactly one process, + * and marked clean by all others. + * + * To do this, first construct a table mapping mpi_rank + * to the index of the first entry in the candidate list to + * be written by the process of that mpi_rank, and then use + * the table to control which entries are written and which + * are marked as clean as a function of the mpi_rank. + * + * Note that the table must be identical on all processes, as + * all see the same candidate list, mpi_size, and mpi_rank -- + * the inputs used to construct the table. + * + * We construct the table as follows. Let: + * + * n = num_candidates / mpi_size; + * + * m = num_candidates % mpi_size; + * + * Now allocate an array of integers of length mpi_size + 1, + * and call this array candidate_assignment_table. + * + * Conceptually, if the number of candidates is a multiple + * of the mpi_size, we simply pass through the candidate list + * and assign n entries to each process to flush, with the + * index of the first entry to flush in the location in + * the candidate_assignment_table indicated by the mpi_rank + * of the process. + * + * In the more common case in which the candidate list isn't + * isn't a multiple of the mpi_size, we pretend it is, and + * give num_candidates % mpi_size processes one extra entry + * each to make things work out. + * + * Once the table is constructed, we determine the first and + * last entry this process is to flush as follows: + * + * first_entry_to_flush = candidate_assignment_table[mpi_rank] + * + * last_entry_to_flush = + * candidate_assignment_table[mpi_rank + 1] - 1; + * + * With these values determined, we simply scan through the + * candidate list, marking all entries in the range + * [first_entry_to_flush, last_entry_to_flush] for flush, + * and all others to be cleaned. + * + * Finally, we scan the LRU from tail to head, flushing + * or marking clean the candidate entries as indicated. + * If necessary, we scan the pinned list as well. + * + * Note that this function will fail if any protected or + * clean entries appear on the candidate list. + * + * This function is used in managing sync points, and + * shouldn't be used elsewhere. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: John Mainzer + * 3/17/10 + * + * Modifications: + * + * Heavily reworked to have each process flush a group of + * adjacent entries. + * JRM -- 4/15/10 + * + *------------------------------------------------------------------------- + */ +#ifdef H5_HAVE_PARALLEL +#define H5C_APPLY_CANDIDATE_LIST__DEBUG 0 +herr_t +H5C_apply_candidate_list(H5F_t * f, + hid_t primary_dxpl_id, + hid_t secondary_dxpl_id, + H5C_t * cache_ptr, + int num_candidates, + haddr_t * candidates_list_ptr, + int mpi_rank, + int mpi_size) +{ + hbool_t first_flush = FALSE; + int i; + int m; + int n; + int first_entry_to_flush; + int last_entry_to_flush; + int entries_to_clear = 0; + int entries_to_flush = 0; + int entries_cleared = 0; + int entries_flushed = 0; + int entries_examined = 0; + int initial_list_len; + int * candidate_assignment_table = NULL; + haddr_t addr; + H5C_cache_entry_t * clear_ptr = NULL; + H5C_cache_entry_t * entry_ptr = NULL; + H5C_cache_entry_t * flush_ptr = NULL; +#if H5C_DO_SANITY_CHECKS + haddr_t last_addr; +#endif /* H5C_DO_SANITY_CHECKS */ +#if H5C_APPLY_CANDIDATE_LIST__DEBUG + char tbl_buf[1024]; +#endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5C_apply_candidate_list, FAIL) + + HDassert( cache_ptr != NULL ); + HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); + HDassert( num_candidates > 0 ); + HDassert( num_candidates <= cache_ptr->slist_len ); + HDassert( candidates_list_ptr != NULL ); + HDassert( 0 <= mpi_rank ); + HDassert( mpi_rank < mpi_size ); + +#if H5C_APPLY_CANDIDATE_LIST__DEBUG + HDfprintf(stdout, "%s:%d: setting up candidate assignment table.\n", + FUNC, mpi_rank); + for ( i = 0; i < 1024; i++ ) tbl_buf[i] = '\0'; + sprintf(&(tbl_buf[0]), "candidate list = "); + for ( i = 0; i < num_candidates; i++ ) + { + sprintf(&(tbl_buf[strlen(tbl_buf)]), " 0x%llx", + (long long)(*(candidates_list_ptr + i))); + } + sprintf(&(tbl_buf[strlen(tbl_buf)]), "\n"); + HDfprintf(stdout, "%s", tbl_buf); +#endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */ + + n = num_candidates / mpi_size; + m = num_candidates % mpi_size; + HDassert(n >= 0); + + if(NULL == (candidate_assignment_table = (int *)H5MM_malloc(sizeof(int) * (size_t)(mpi_size + 1)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for candidate assignment table") + + candidate_assignment_table[0] = 0; + candidate_assignment_table[mpi_size] = num_candidates; + + if(m == 0) { /* mpi_size is an even divisor of num_candidates */ + HDassert(n > 0); + for(i = 1; i < mpi_size; i++) + candidate_assignment_table[i] = candidate_assignment_table[i - 1] + n; + } /* end if */ + else { + for(i = 1; i <= m; i++) + candidate_assignment_table[i] = candidate_assignment_table[i - 1] + n + 1; + + if(num_candidates < mpi_size) { + for(i = m + 1; i < mpi_size; i++) + candidate_assignment_table[i] = num_candidates; + } /* end if */ + else { + for(i = m + 1; i < mpi_size; i++) + candidate_assignment_table[i] = candidate_assignment_table[i - 1] + n; + } /* end else */ + } /* end else */ + HDassert((candidate_assignment_table[mpi_size - 1] + n) == num_candidates); + +#if H5C_DO_SANITY_CHECKS + /* verify that the candidate assignment table has the expected form */ + for ( i = 1; i < mpi_size - 1; i++ ) + { + int a, b; + + a = candidate_assignment_table[i] - candidate_assignment_table[i - 1]; + b = candidate_assignment_table[i + 1] - candidate_assignment_table[i]; + + HDassert( n + 1 >= a ); + HDassert( a >= b ); + HDassert( b >= n ); + } +#endif /* H5C_DO_SANITY_CHECKS */ + + first_entry_to_flush = candidate_assignment_table[mpi_rank]; + last_entry_to_flush = candidate_assignment_table[mpi_rank + 1] - 1; + +#if H5C_APPLY_CANDIDATE_LIST__DEBUG + for ( i = 0; i < 1024; i++ ) + tbl_buf[i] = '\0'; + sprintf(&(tbl_buf[0]), "candidate assignment table = "); + for(i = 0; i <= mpi_size; i++) + sprintf(&(tbl_buf[strlen(tbl_buf)]), " %d", candidate_assignment_table[i]); + sprintf(&(tbl_buf[strlen(tbl_buf)]), "\n"); + HDfprintf(stdout, "%s", tbl_buf); + + HDfprintf(stdout, "%s:%d: flush entries [%d, %d].\n", + FUNC, mpi_rank, first_entry_to_flush, last_entry_to_flush); + + HDfprintf(stdout, "%s:%d: marking entries.\n", FUNC, mpi_rank); +#endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */ + + for(i = 0; i < num_candidates; i++) { + addr = candidates_list_ptr[i]; + HDassert( H5F_addr_defined(addr) ); + +#if H5C_DO_SANITY_CHECKS + if ( i > 0 ) { + if ( last_addr == addr ) { + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Duplicate entry in cleaned list.\n") + } else if ( last_addr > addr ) { + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "candidate list not sorted.\n") + } + } + + last_addr = addr; +#endif /* H5C_DO_SANITY_CHECKS */ + + H5C__SEARCH_INDEX(cache_ptr, addr, entry_ptr, FAIL) + if(entry_ptr == NULL) { + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Listed candidate entry not in cache?!?!?.") + } else if(!entry_ptr->is_dirty) { + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Listed entry not dirty?!?!?.") + } else if ( entry_ptr->is_protected ) { + /* For now at least, we can't deal with protected entries. + * If we encounter one, scream and die. If it becomes an + * issue, we should be able to work around this. + */ + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Listed entry is protected?!?!?.") + } else { + /* determine whether the entry is to be cleared or flushed, + * and mark it accordingly. We will scan the protected and + * pinned list shortly, and clear or flush according to these + * markings. + */ + if((i >= first_entry_to_flush) && (i <= last_entry_to_flush)) { + entries_to_flush++; + entry_ptr->flush_immediately = TRUE; + } /* end if */ + else { + entries_to_clear++; + entry_ptr->clear_on_unprotect = TRUE; + } /* end else */ + } /* end else */ + } /* end for */ + +#if H5C_APPLY_CANDIDATE_LIST__DEBUG + HDfprintf(stdout, "%s:%d: num candidates/to clear/to flush = %d/%d/%d.\n", + FUNC, mpi_rank, (int)num_candidates, (int)entries_to_clear, + (int)entries_to_flush); +#endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */ + + + /* We have now marked all the entries on the candidate list for + * either flush or clear -- now scan the LRU and the pinned list + * for these entries and do the deed. + * + * Note that we are doing things in this round about manner so as + * to preserve the order of the LRU list to the best of our ability. + * If we don't do this, my experiments indicate that we will have a + * noticably poorer hit ratio as a result. + */ + +#if H5C_APPLY_CANDIDATE_LIST__DEBUG + HDfprintf(stdout, "%s:%d: scanning LRU list. len = %d.\n", FUNC, mpi_rank, + (int)(cache_ptr->LRU_list_len)); +#endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */ + + entries_examined = 0; + initial_list_len = cache_ptr->LRU_list_len; + entry_ptr = cache_ptr->LRU_tail_ptr; + + while((entry_ptr != NULL) && (entries_examined <= initial_list_len) && + ((entries_cleared + entries_flushed) < num_candidates)) { + if(entry_ptr->clear_on_unprotect) { + entry_ptr->clear_on_unprotect = FALSE; + clear_ptr = entry_ptr; + entry_ptr = entry_ptr->prev; + entries_cleared++; + +#if ( H5C_APPLY_CANDIDATE_LIST__DEBUG > 1 ) + HDfprintf(stdout, "%s:%d: clearing 0x%llx.\n", FUNC, mpi_rank, + (long long)clear_ptr->addr); +#endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */ + + if(H5C_flush_single_entry(f, + primary_dxpl_id, + secondary_dxpl_id, + clear_ptr->type, + clear_ptr->addr, + H5C__FLUSH_CLEAR_ONLY_FLAG, + &first_flush, + TRUE) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't clear entry.") + } else if(entry_ptr->flush_immediately) { + entry_ptr->flush_immediately = FALSE; + flush_ptr = entry_ptr; + entry_ptr = entry_ptr->prev; + entries_flushed++; + +#if ( H5C_APPLY_CANDIDATE_LIST__DEBUG > 1 ) + HDfprintf(stdout, "%s:%d: flushing 0x%llx.\n", FUNC, mpi_rank, + (long long)flush_ptr->addr); +#endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */ + + if(H5C_flush_single_entry(f, + primary_dxpl_id, + secondary_dxpl_id, + flush_ptr->type, + flush_ptr->addr, + H5C__NO_FLAGS_SET, + &first_flush, + TRUE) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't clear entry.") + } else { + entry_ptr = entry_ptr->prev; + } + + entries_examined++; + } /* end while */ + +#if H5C_APPLY_CANDIDATE_LIST__DEBUG + HDfprintf(stdout, "%s:%d: entries examined/cleared/flushed = %d/%d/%d.\n", + FUNC, mpi_rank, entries_examined, + entries_cleared, entries_flushed); +#endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */ + + /* It is also possible that some of the cleared entries are on the + * pinned list. Must scan that also. + */ + +#if H5C_APPLY_CANDIDATE_LIST__DEBUG + HDfprintf(stdout, "%s:%d: scanning pinned entry list. len = %d\n", + FUNC, mpi_rank, (int)(cache_ptr->pel_len)); +#endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */ + + entry_ptr = cache_ptr->pel_head_ptr; + while((entry_ptr != NULL) && + ((entries_cleared + entries_flushed) < num_candidates)) { + if(entry_ptr->clear_on_unprotect) { + entry_ptr->clear_on_unprotect = FALSE; + clear_ptr = entry_ptr; + entry_ptr = entry_ptr->next; + entries_cleared++; + +#if ( H5C_APPLY_CANDIDATE_LIST__DEBUG > 1 ) + HDfprintf(stdout, "%s:%d: clearing 0x%llx.\n", FUNC, mpi_rank, + (long long)clear_ptr->addr); +#endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */ + + if(H5C_flush_single_entry(f, + primary_dxpl_id, + secondary_dxpl_id, + clear_ptr->type, + clear_ptr->addr, + H5C__FLUSH_CLEAR_ONLY_FLAG, + &first_flush, + TRUE) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't clear entry.") + } else if(entry_ptr->flush_immediately) { + entry_ptr->flush_immediately = FALSE; + flush_ptr = entry_ptr; + entry_ptr = entry_ptr->next; + entries_flushed++; + +#if ( H5C_APPLY_CANDIDATE_LIST__DEBUG > 1 ) + HDfprintf(stdout, "%s:%d: flushing 0x%llx.\n", FUNC, mpi_rank, + (long long)flush_ptr->addr); +#endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */ + + if(H5C_flush_single_entry(f, + primary_dxpl_id, + secondary_dxpl_id, + flush_ptr->type, + flush_ptr->addr, + H5C__NO_FLAGS_SET, + &first_flush, + TRUE) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't clear entry.") + } else { + entry_ptr = entry_ptr->next; + } + } /* end while */ + +#if H5C_APPLY_CANDIDATE_LIST__DEBUG + HDfprintf(stdout, + "%s:%d: pel entries examined/cleared/flushed = %d/%d/%d.\n", + FUNC, mpi_rank, entries_examined, + entries_cleared, entries_flushed); + HDfprintf(stdout, "%s:%d: done.\n", FUNC, mpi_rank); + + fsync(stdout); +#endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */ + + if((entries_flushed != entries_to_flush) || (entries_cleared != entries_to_clear)) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "entry count mismatch.") + +done: + if(candidate_assignment_table != NULL) + candidate_assignment_table = (int *)H5MM_xfree((void *)candidate_assignment_table); + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5C_apply_candidate_list() */ +#endif /* H5_HAVE_PARALLEL */ + + +/*------------------------------------------------------------------------- + * Function: H5C_construct_candidate_list__clean_cache + * + * Purpose: Construct the list of entries that should be flushed to + * clean all entries in the cache. + * + * This function is used in managing sync points, and + * shouldn't be used elsewhere. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: John Mainzer + * 3/17/10 + * + *------------------------------------------------------------------------- + */ +#ifdef H5_HAVE_PARALLEL +herr_t +H5C_construct_candidate_list__clean_cache(H5C_t * cache_ptr) +{ + size_t space_needed; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5C_construct_candidate_list__clean_cache, FAIL) + + HDassert( cache_ptr != NULL ); + HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); + + /* As a sanity check, set space needed to the size of the skip list. + * This should be the sum total of the sizes of all the dirty entries + * in the metadata cache. + */ + space_needed = cache_ptr->slist_size; + + /* Recall that while we shouldn't have any protected entries at this + * point, it is possible that some dirty entries may reside on the + * pinned list at this point. + */ + HDassert( cache_ptr->slist_size <= + (cache_ptr->dLRU_list_size + cache_ptr->pel_size) ); + HDassert( cache_ptr->slist_len <= + (cache_ptr->dLRU_list_len + cache_ptr->pel_len) ); + + if(space_needed > 0) { /* we have work to do */ + H5C_cache_entry_t *entry_ptr; + int nominated_entries_count = 0; + size_t nominated_entries_size = 0; + haddr_t nominated_addr; + + HDassert( cache_ptr->slist_len > 0 ); + + /* Scan the dirty LRU list from tail forward and nominate sufficient + * entries to free up the necessary space. + */ + entry_ptr = cache_ptr->dLRU_tail_ptr; + while((nominated_entries_size < space_needed) && + (nominated_entries_count < cache_ptr->slist_len) && + (entry_ptr != NULL)) { + HDassert( ! (entry_ptr->is_protected) ); + HDassert( ! (entry_ptr->is_read_only) ); + HDassert( entry_ptr->ro_ref_count == 0 ); + HDassert( entry_ptr->is_dirty ); + HDassert( entry_ptr->in_slist ); + + nominated_addr = entry_ptr->addr; + if(H5AC_add_candidate((H5AC_t *)cache_ptr, nominated_addr) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5AC_add_candidate() failed(1).") + + nominated_entries_size += entry_ptr->size; + nominated_entries_count++; + entry_ptr = entry_ptr->aux_prev; + } /* end while */ + HDassert( entry_ptr == NULL ); + + /* it is possible that there are some dirty entries on the + * protected entry list as well -- scan it too if necessary + */ + entry_ptr = cache_ptr->pel_head_ptr; + while((nominated_entries_size < space_needed) && + (nominated_entries_count < cache_ptr->slist_len) && + (entry_ptr != NULL)) { + if(entry_ptr->is_dirty) { + HDassert( ! (entry_ptr->is_protected) ); + HDassert( ! (entry_ptr->is_read_only) ); + HDassert( entry_ptr->ro_ref_count == 0 ); + HDassert( entry_ptr->is_dirty ); + HDassert( entry_ptr->in_slist ); + + nominated_addr = entry_ptr->addr; + if(H5AC_add_candidate((H5AC_t *)cache_ptr, nominated_addr) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5AC_add_candidate() failed(2).") + + nominated_entries_size += entry_ptr->size; + nominated_entries_count++; + } /* end if */ + + entry_ptr = entry_ptr->next; + } /* end while */ + + HDassert( nominated_entries_count == cache_ptr->slist_len ); + HDassert( nominated_entries_size == space_needed ); + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5C_construct_candidate_list__clean_cache() */ +#endif /* H5_HAVE_PARALLEL */ + + +/*------------------------------------------------------------------------- + * Function: H5C_construct_candidate_list__min_clean + * + * Purpose: Construct the list of entries that should be flushed to + * get the cache back within its min clean constraints. + * + * This function is used in managing sync points, and + * shouldn't be used elsewhere. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: John Mainzer + * 3/17/10 + * + *------------------------------------------------------------------------- + */ +#ifdef H5_HAVE_PARALLEL +herr_t +H5C_construct_candidate_list__min_clean(H5C_t * cache_ptr) +{ + size_t space_needed = 0; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5C_construct_candidate_list__min_clean, FAIL) + + HDassert( cache_ptr != NULL ); + HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); + + /* compute the number of bytes (if any) that must be flushed to get the + * cache back within its min clean constraints. + */ + if(cache_ptr->max_cache_size > cache_ptr->index_size) { + if(((cache_ptr->max_cache_size - cache_ptr->index_size) + + cache_ptr->cLRU_list_size) >= cache_ptr->min_clean_size) + space_needed = 0; + else + space_needed = cache_ptr->min_clean_size - + ((cache_ptr->max_cache_size - cache_ptr->index_size) + + cache_ptr->cLRU_list_size); + } /* end if */ + else { + if(cache_ptr->min_clean_size <= cache_ptr->cLRU_list_size) + space_needed = 0; + else + space_needed = cache_ptr->min_clean_size - + cache_ptr->cLRU_list_size; + } /* end else */ + + if(space_needed > 0) { /* we have work to do */ + H5C_cache_entry_t *entry_ptr; + int nominated_entries_count = 0; + size_t nominated_entries_size = 0; + + HDassert( cache_ptr->slist_len > 0 ); + + /* Scan the dirty LRU list from tail forward and nominate sufficient + * entries to free up the necessary space. + */ + entry_ptr = cache_ptr->dLRU_tail_ptr; + while((nominated_entries_size < space_needed) && + (nominated_entries_count < cache_ptr->slist_len) && + (entry_ptr != NULL)) { + haddr_t nominated_addr; + + HDassert( ! (entry_ptr->is_protected) ); + HDassert( ! (entry_ptr->is_read_only) ); + HDassert( entry_ptr->ro_ref_count == 0 ); + HDassert( entry_ptr->is_dirty ); + HDassert( entry_ptr->in_slist ); + + nominated_addr = entry_ptr->addr; + if(H5AC_add_candidate((H5AC_t *)cache_ptr, nominated_addr) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5AC_add_candidate() failed.") + + nominated_entries_size += entry_ptr->size; + nominated_entries_count++; + entry_ptr = entry_ptr->aux_prev; + } /* end while */ + HDassert( nominated_entries_count <= cache_ptr->slist_len ); + HDassert( nominated_entries_size >= space_needed ); + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5C_construct_candidate_list__min_clean() */ +#endif /* H5_HAVE_PARALLEL */ + + +/*------------------------------------------------------------------------- * Function: H5C_create * * Purpose: Allocate, initialize, and return the address of a new @@ -356,10 +974,6 @@ done: * Programmer: John Mainzer * 6/2/04 * - * JRM -- 11/5/08 - * Added initialization for the new clean_index_size and - * dirty_index_size fields of H5C_t. - * *------------------------------------------------------------------------- */ H5C_t * @@ -1502,9 +2116,7 @@ H5C_flush_to_min_clean(H5F_t * f, #endif /* end modified code -- commented out for now */ done: - FUNC_LEAVE_NOAPI(ret_value) - } /* H5C_flush_to_min_clean() */ @@ -1903,33 +2515,6 @@ H5C_get_trace_file_ptr_from_entry(const H5C_cache_entry_t *entry_ptr, * Programmer: John Mainzer * 6/2/04 * - * QAK -- 1/31/08 - * Added initialization for the new free_file_space_on_destroy - * field. - * - * JRM -- 11/13/08 - * Moved test to see if we already have an entry with the - * specified address in the cache. This was necessary as - * we used to modify some fields in the entry to be inserted - * priort to this test, which got the cache confused if the - * insertion failed because the entry was already present. - * - * Also revised the function to call H5C_make_space_in_cache() - * if the min_clean_size is not met at present, not just if - * there is insufficient space in the cache for the new - * entry. - * - * The purpose of this modification is to avoid "metadata - * blizzards" in the write only case. In such instances, - * the cache was allowed to fill with dirty metadata. When - * we finally needed to evict an entry to make space, we had - * to flush out a whole cache full of metadata -- which has - * interesting performance effects. We hope to avoid (or - * perhaps more accurately hide) this effect by maintaining - * the min_clean_size, which should force us to start flushing - * entries long before we actually have to evict something - * to make space. - * *------------------------------------------------------------------------- */ herr_t @@ -2042,6 +2627,7 @@ H5C_insert_entry(H5F_t * f, #ifdef H5_HAVE_PARALLEL entry_ptr->clear_on_unprotect = FALSE; + entry_ptr->flush_immediately = FALSE; #endif /* H5_HAVE_PARALLEL */ entry_ptr->flush_in_progress = FALSE; @@ -3813,29 +4399,17 @@ done: *------------------------------------------------------------------------- */ herr_t -H5C_set_prefix(H5C_t * cache_ptr, - char * prefix) +H5C_set_prefix(H5C_t * cache_ptr, char * prefix) { - herr_t ret_value = SUCCEED; /* Return value */ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5C_set_prefix) - FUNC_ENTER_NOAPI(H5C_set_prefix, FAIL) - - /* This would normally be an assert, but we need to use an HGOTO_ERROR - * call to shut up the compiler. - */ - if ( ( ! cache_ptr ) || ( cache_ptr->magic != H5C__H5C_T_MAGIC ) ) { - - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Bad cache_ptr") - } - - HDassert( prefix ); - HDassert( HDstrlen(prefix) < H5C__PREFIX_LEN ) ; + HDassert((cache_ptr) && (cache_ptr->magic == H5C__H5C_T_MAGIC)); + HDassert(prefix); + HDassert(HDstrlen(prefix) < H5C__PREFIX_LEN); HDstrcpy(&(cache_ptr->prefix[0]), prefix); -done: - FUNC_LEAVE_NOAPI(ret_value) - + FUNC_LEAVE_NOAPI(SUCCEED) } /* H5C_set_prefix() */ @@ -7441,17 +8015,6 @@ H5C_flush_single_entry(H5F_t * f, } } } -#if 0 - /* this should be useful for debugging from time to time. - * lets leave it in for now. -- JRM 12/15/04 - */ - else { - HDfprintf(stdout, - "H5C_flush_single_entry(): non-existant entry. addr = %a\n", - addr); - HDfflush(stdout); - } -#endif #endif /* H5C_DO_SANITY_CHECKS */ if ( ( entry_ptr != NULL ) && ( entry_ptr->is_protected ) ) @@ -7572,133 +8135,6 @@ H5C_flush_single_entry(H5F_t * f, */ if ( destroy ) { /* AKA eviction */ -#if 0 /* JRM */ - /* This test code may come in handy -- lets keep it for a while. - * - * Note that it will cause spurious errors in the serial case - * unless we are maintaining the clean and dirty LRU lists. - */ - { - if ( entry_ptr->is_dirty ) - { - if ( cache_ptr->dLRU_head_ptr == NULL ) - HDfprintf(stdout, - "%s: cache_ptr->dLRU_head_ptr == NULL.\n", - FUNC); - - if ( cache_ptr->dLRU_tail_ptr == NULL ) - HDfprintf(stdout, - "%s: cache_ptr->dLRU_tail_ptr == NULL.\n", - FUNC); - - if ( cache_ptr->dLRU_list_len <= 0 ) - HDfprintf(stdout, - "%s: cache_ptr->dLRU_list_len <= 0.\n", - FUNC); - - if ( cache_ptr->dLRU_list_size <= 0 ) - HDfprintf(stdout, - "%s: cache_ptr->dLRU_list_size <= 0.\n", - FUNC); - - if ( cache_ptr->dLRU_list_size < entry_ptr->size ) - HDfprintf(stdout, - "%s: cache_ptr->dLRU_list_size < entry_ptr->size.\n", - FUNC); - - if ( ( (cache_ptr->dLRU_list_size) == entry_ptr->size ) && - ( ! ( (cache_ptr->dLRU_list_len) == 1 ) ) ) - HDfprintf(stdout, - "%s: dLRU_list_size == size && dLRU_list_len != 1\n", - FUNC); - - if ( ( entry_ptr->aux_prev == NULL ) && - ( cache_ptr->dLRU_head_ptr != entry_ptr ) ) - HDfprintf(stdout, - "%s: entry_ptr->aux_prev == NULL && dLRU_head_ptr != entry_ptr\n", - FUNC); - - if ( ( entry_ptr->aux_next == NULL ) && - ( cache_ptr->dLRU_tail_ptr != entry_ptr ) ) - HDfprintf(stdout, - "%s: entry_ptr->aux_next == NULL && dLRU_tail_ptr != entry_ptr\n", - FUNC); - - if ( ( cache_ptr->dLRU_list_len == 1 ) && - ( ! ( ( cache_ptr->dLRU_head_ptr == entry_ptr ) && - ( cache_ptr->dLRU_tail_ptr == entry_ptr ) && - ( entry_ptr->aux_next == NULL ) && - ( entry_ptr->aux_prev == NULL ) && - ( cache_ptr->dLRU_list_size == entry_ptr->size ) - ) - ) - ) - { - HDfprintf(stdout, - "%s: single entry dlru sanity check fails\n", - FUNC); - } - - } - else - { - if ( cache_ptr->cLRU_head_ptr == NULL ) - HDfprintf(stdout, - "%s: cache_ptr->cLRU_head_ptr == NULL.\n", - FUNC); - - if ( cache_ptr->cLRU_tail_ptr == NULL ) - HDfprintf(stdout, - "%s: cache_ptr->cLRU_tail_ptr == NULL.\n", - FUNC); - - if ( cache_ptr->cLRU_list_len <= 0 ) - HDfprintf(stdout, - "%s: cache_ptr->cLRU_list_len <= 0.\n", - FUNC); - - if ( cache_ptr->cLRU_list_size <= 0 ) - HDfprintf(stdout, - "%s: cache_ptr->cLRU_list_size <= 0.\n", - FUNC); - - if ( cache_ptr->cLRU_list_size < entry_ptr->size ) - HDfprintf(stdout, - "%s: cache_ptr->cLRU_list_size < entry_ptr->size.\n", - FUNC); - - if ( ( (cache_ptr->cLRU_list_size) == entry_ptr->size ) && - ( ! ( (cache_ptr->cLRU_list_len) == 1 ) ) ) - HDfprintf(stdout, - "%s: cLRU_list_size == size && cLRU_list_len != 1\n", - FUNC); - - if ( ( entry_ptr->aux_prev == NULL ) && - ( cache_ptr->cLRU_head_ptr != entry_ptr ) ) - HDfprintf(stdout, "%s: entry_ptr->aux_prev == NULL && cLRU_head_ptr != entry_ptr\n", FUNC); - - if ( ( entry_ptr->aux_next == NULL ) && - ( cache_ptr->cLRU_tail_ptr != entry_ptr ) ) - HDfprintf(stdout, "%s: entry_ptr->aux_next == NULL && cLRU_tail_ptr != entry_ptr\n", FUNC); - - if ( ( cache_ptr->cLRU_list_len == 1 ) && - ( ! ( ( cache_ptr->cLRU_head_ptr == entry_ptr ) && - ( cache_ptr->cLRU_tail_ptr == entry_ptr ) && - ( entry_ptr->aux_next == NULL ) && - ( entry_ptr->aux_prev == NULL ) && - ( cache_ptr->cLRU_list_size == entry_ptr->size ) - ) - ) - ) - { - HDfprintf(stdout, - "%s: single entry clru sanity check fails\n", - FUNC); - } - } - } -#endif /* JRM */ - H5C__UPDATE_RP_FOR_EVICTION(cache_ptr, entry_ptr, FAIL) } else { @@ -7864,10 +8300,10 @@ H5C_flush_single_entry(H5F_t * f, * H5C__UPDATE_INDEX_FOR_ENTRY_CLEAN()). */ H5C__UPDATE_INDEX_FOR_SIZE_CHANGE((cache_ptr), \ - (entry_ptr->size),\ + (entry_ptr->size), \ (new_size), \ (entry_ptr), \ - (TRUE)); + (TRUE)) /* The entry can't be protected since we just flushed it. * Thus we must update the replacement policy data @@ -7923,9 +8359,7 @@ H5C_flush_single_entry(H5F_t * f, } done: - FUNC_LEAVE_NOAPI(ret_value) - } /* H5C_flush_single_entry() */ @@ -8023,6 +8457,7 @@ H5C_load_entry(H5F_t * f, entry->flush_marker = FALSE; #ifdef H5_HAVE_PARALLEL entry->clear_on_unprotect = FALSE; + entry->flush_immediately = FALSE; #endif /* H5_HAVE_PARALLEL */ entry->flush_in_progress = FALSE; entry->destroy_in_progress = FALSE; @@ -8862,20 +9297,17 @@ H5C_flush_marked_entries(H5F_t * f, hid_t primary_dxpl_id, hid_t secondary_dxpl_ HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); /* Flush all marked entries */ - if (H5C_flush_cache(f, + if(H5C_flush_cache(f, primary_dxpl_id, secondary_dxpl_id, H5C__FLUSH_MARKED_ENTRIES_FLAG | H5C__FLUSH_IGNORE_PROTECTED_FLAG) < 0) { HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't flush cache") - } /* end if */ done: - - FUNC_LEAVE_NOAPI(ret_value); - + FUNC_LEAVE_NOAPI(ret_value) } /* H5C_flush_marked_entries */ #if H5C_DO_TAGGING_SANITY_CHECKS @@ -8891,8 +9323,6 @@ done: * Programmer: Mike McGreevy * January 14, 2010 * - * Modifications: - * *------------------------------------------------------------------------- */ static herr_t @@ -8959,10 +9389,7 @@ H5C_verify_tag(int id, haddr_t tag) } done: - - /* Function Leave Macro */ - FUNC_LEAVE_NOAPI(ret_value); - + FUNC_LEAVE_NOAPI(ret_value) } /* H5C_verify_tag */ #endif @@ -8980,43 +9407,35 @@ done: * Programmer: Mike McGreevy * March 17, 2010 * - * Modifications: - * *------------------------------------------------------------------------- */ -herr_t +void H5C_retag_copied_metadata(H5C_t * cache_ptr, haddr_t metadata_tag) { /* Variable Declarations */ - herr_t ret_value = SUCCEED; /* Return Value */ int i = 0; /* Iterator */ - H5C_cache_entry_t *next_entry_ptr = NULL; /* entry pointer */ /* Assertions */ HDassert(cache_ptr); /* Function Enter Macro */ - FUNC_ENTER_NOAPI(H5C_retag_copied_metadata, FAIL) + FUNC_ENTER_NOAPI_NOFUNC(H5C_retag_copied_metadata) /* Iterate through entries, retagging those with the H5AC__COPIED_TAG tag */ - for (i = 0; i < H5C__HASH_TABLE_LEN; i++) { + for(i = 0; i < H5C__HASH_TABLE_LEN; i++) { + H5C_cache_entry_t *next_entry_ptr; /* entry pointer */ next_entry_ptr = cache_ptr->index[i]; - - while ( next_entry_ptr != NULL ) { - if (cache_ptr->index[i] != NULL) { - if ((cache_ptr->index[i])->tag == H5AC__COPIED_TAG) { + while(next_entry_ptr != NULL) { + if(cache_ptr->index[i] != NULL) { + if((cache_ptr->index[i])->tag == H5AC__COPIED_TAG) (cache_ptr->index[i])->tag = metadata_tag; - } /* end if */ } /* end if */ + next_entry_ptr = next_entry_ptr->ht_next; } /* end while */ - } /* end for */ -done: - - /* Function Leave Macro */ - FUNC_LEAVE_NOAPI(ret_value); - + FUNC_LEAVE_NOAPI_VOID } /* H5C_retag_copied_metadata */ + diff --git a/src/H5Cpkg.h b/src/H5Cpkg.h index e1dffa4..b4a8944 100644 --- a/src/H5Cpkg.h +++ b/src/H5Cpkg.h @@ -1875,7 +1875,7 @@ if ( ( (cache_ptr) == NULL ) || \ ( ( !( was_clean ) || \ ( (cache_ptr)->clean_index_size < (old_size) ) ) && \ ( ( (was_clean) ) || \ - ( (cache_ptr)->dirty_index_size < (old_size) ) ) ) \ + ( (cache_ptr)->dirty_index_size < (old_size) ) ) ) || \ ( (entry_ptr) == NULL ) ) { \ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ "Pre HT entry size change SC failed") \ @@ -1893,7 +1893,7 @@ if ( ( (cache_ptr) == NULL ) || \ ( ( !((entry_ptr)->is_dirty ) || \ ( (cache_ptr)->dirty_index_size < (new_size) ) ) && \ ( ( ((entry_ptr)->is_dirty) ) || \ - ( (cache_ptr)->clean_index_size < (new_size) ) ) ) \ + ( (cache_ptr)->clean_index_size < (new_size) ) ) ) || \ ( ( (cache_ptr)->index_len == 1 ) && \ ( (cache_ptr)->index_size != (new_size) ) ) ) { \ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ @@ -2098,24 +2098,25 @@ if ( (cache_ptr)->index_size != \ H5C__POST_HT_UPDATE_FOR_ENTRY_DIRTY_SC(cache_ptr, entry_ptr); \ } -#define H5C__UPDATE_INDEX_FOR_SIZE_CHANGE(cache_ptr, old_size, new_size, \ - entry_ptr, was_clean) \ -{ \ - H5C__PRE_HT_ENTRY_SIZE_CHANGE_SC(cache_ptr, old_size, new_size, \ - entry_ptr, was_clean) \ - (cache_ptr)->index_size -= (old_size); \ - (cache_ptr)->index_size += (new_size); \ - if ( was_clean ) { \ - (cache_ptr)->clean_index_size -= (old_size); \ - } else { \ - (cache_ptr)->dirty_index_size -= (old_size); \ - } \ - if ( (entry_ptr)->is_dirty ) { \ - (cache_ptr)->dirty_index_size += (new_size); \ - } else { \ - (cache_ptr)->clean_index_size += (new_size); \ - } \ - H5C__POST_HT_ENTRY_SIZE_CHANGE_SC(cache_ptr, old_size, new_size, entry_ptr) \ +#define H5C__UPDATE_INDEX_FOR_SIZE_CHANGE(cache_ptr, old_size, new_size, \ + entry_ptr, was_clean) \ +{ \ + H5C__PRE_HT_ENTRY_SIZE_CHANGE_SC(cache_ptr, old_size, new_size, \ + entry_ptr, was_clean) \ + (cache_ptr)->index_size -= (old_size); \ + (cache_ptr)->index_size += (new_size); \ + if ( was_clean ) { \ + (cache_ptr)->clean_index_size -= (old_size); \ + } else { \ + (cache_ptr)->dirty_index_size -= (old_size); \ + } \ + if ( (entry_ptr)->is_dirty ) { \ + (cache_ptr)->dirty_index_size += (new_size); \ + } else { \ + (cache_ptr)->clean_index_size += (new_size); \ + } \ + H5C__POST_HT_ENTRY_SIZE_CHANGE_SC(cache_ptr, old_size, new_size, \ + entry_ptr) \ } diff --git a/src/H5Cprivate.h b/src/H5Cprivate.h index 3f38500..7e14872 100644 --- a/src/H5Cprivate.h +++ b/src/H5Cprivate.h @@ -383,6 +383,14 @@ typedef herr_t (*H5C_log_flush_func_t)(H5C_t * cache_ptr, * the unprotect, the entry's is_dirty flag is reset by flushing * it with the H5C__FLUSH_CLEAR_ONLY_FLAG. * + * flush_immediately: Boolean flag used only in Phdf5 -- and then only + * for H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED. + * + * When a destributed metadata write is triggered at a + * sync point, this field is used to mark entries that + * must be flushed before leaving the sync point. At all + * other times, this field should be set to FALSE. + * * flush_in_progress: Boolean flag that is set to true iff the entry * is in the process of being flushed. This allows the cache * to detect when a call is the result of a flush callback. @@ -581,6 +589,7 @@ typedef struct H5C_cache_entry_t hbool_t flush_marker; #ifdef H5_HAVE_PARALLEL hbool_t clear_on_unprotect; + hbool_t flush_immediately; #endif /* H5_HAVE_PARALLEL */ hbool_t flush_in_progress; hbool_t destroy_in_progress; @@ -1034,6 +1043,21 @@ typedef struct H5C_auto_size_ctl_t #define H5C__FREE_FILE_SPACE_FLAG 0x0800 #define H5C__TAKE_OWNERSHIP_FLAG 0x1000 +#ifdef H5_HAVE_PARALLEL +H5_DLL herr_t H5C_apply_candidate_list(H5F_t * f, + hid_t primary_dxpl_id, + hid_t secondary_dxpl_id, + H5C_t * cache_ptr, + int num_candidates, + haddr_t * candidates_list_ptr, + int mpi_rank, + int mpi_size); + +H5_DLL herr_t H5C_construct_candidate_list__clean_cache(H5C_t * cache_ptr); + +H5_DLL herr_t H5C_construct_candidate_list__min_clean(H5C_t * cache_ptr); +#endif /* H5_HAVE_PARALLEL */ + H5_DLL H5C_t * H5C_create(size_t max_cache_size, size_t min_clean_size, int max_type_id, @@ -1177,7 +1201,7 @@ H5_DLL herr_t H5C_validate_resize_config(H5C_auto_size_ctl_t * config_ptr, H5_DLL herr_t H5C_ignore_tags(H5C_t * cache_ptr); -H5_DLL herr_t H5C_retag_copied_metadata(H5C_t * cache_ptr, haddr_t metadata_tag); +H5_DLL void H5C_retag_copied_metadata(H5C_t * cache_ptr, haddr_t metadata_tag); #endif /* !_H5Cprivate_H */ diff --git a/src/H5Dchunk.c b/src/H5Dchunk.c index bd2bd7e..168c011 100644 --- a/src/H5Dchunk.c +++ b/src/H5Dchunk.c @@ -2713,7 +2713,6 @@ H5D_chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata, hbool_t fb_info_init = FALSE; /* Whether the fill value buffer has been initialized */ H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk); /*raw data chunk cache*/ H5D_rdcc_ent_t *ent = NULL; /*cache entry */ - hbool_t found = FALSE; /*already in cache? */ haddr_t chunk_addr = HADDR_UNDEF; /* Address of chunk on disk */ size_t chunk_size; /*size of a chunk */ void *chunk = NULL; /*the file chunk */ @@ -2845,7 +2844,7 @@ H5D_chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata, rdcc->stats.ninits++; } /* end else */ } /* end else */ - HDassert(found || chunk_size > 0); + HDassert(chunk_size > 0); if(ent) { /* diff --git a/src/H5Dio.c b/src/H5Dio.c index 285451e..b7c2ecb 100644 --- a/src/H5Dio.c +++ b/src/H5Dio.c @@ -291,6 +291,19 @@ H5D_read(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, H5D_io_info_t io_info; /* Dataset I/O info */ H5D_type_info_t type_info; /* Datatype info for operation */ hbool_t type_info_init = FALSE; /* Whether the datatype info has been initialized */ + H5S_t * projected_mem_space = NULL; /* If not NULL, ptr to dataspace containing a */ + /* projection of the supplied mem_space to a new */ + /* data space with rank equal to that of */ + /* file_space. */ + /* */ + /* This field is only used if */ + /* H5S_select_shape_same() returns TRUE when */ + /* comparing the mem_space and the data_space, */ + /* and the mem_space have different rank. */ + /* */ + /* Note that if this variable is used, the */ + /* projected mem space must be discarded at the */ + /* end of the function to avoid a memory leak. */ H5D_storage_t store; /*union of EFL and chunk pointer in file space */ hssize_t snelmts; /*total number of elmts (signed) */ hsize_t nelmts; /*total number of elmts */ @@ -340,6 +353,37 @@ H5D_read(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, if(!(H5S_has_extent(mem_space))) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "memory dataspace does not have extent set") + /* H5S_select_shape_same() has been modified to accept topologically identical + * selections with different rank as having the same shape (if the most + * rapidly changing coordinates match up), but the I/O code still has + * difficulties with the notion. + * + * To solve this, we check to see if H5S_select_shape_same() returns true, + * and if the ranks of the mem and file spaces are different. If the are, + * construct a new mem space that is equivalent to the old mem space, and + * use that instead. + * + * Note that in general, this requires us to touch up the memory buffer as + * well. + */ + if(TRUE == H5S_select_shape_same(mem_space, file_space) && + H5S_GET_EXTENT_NDIMS(mem_space) != H5S_GET_EXTENT_NDIMS(file_space)) { + void *adj_buf = NULL; /* Pointer to the location in buf corresponding */ + /* to the beginning of the projected mem space. */ + + /* Attempt to construct projected dataspace for memory dataspace */ + if(H5S_select_construct_projection(mem_space, &projected_mem_space, + (unsigned)H5S_GET_EXTENT_NDIMS(file_space), buf, &adj_buf, type_info.dst_type_size) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to construct projected memory dataspace") + HDassert(projected_mem_space); + HDassert(adj_buf); + + /* Switch to using projected memory dataspace & adjusted buffer */ + mem_space = projected_mem_space; + buf = adj_buf; + } /* end if */ + + /* Retrieve dataset properties */ /* <none needed in the general case> */ @@ -417,6 +461,11 @@ done: if(type_info_init && H5D_typeinfo_term(&type_info) < 0) HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to shut down type info") + /* discard projected mem space if it was created */ + if(NULL != projected_mem_space) + if(H5S_close(projected_mem_space) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to shut down projected memory dataspace") + FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL) } /* end H5D_read() */ @@ -442,6 +491,19 @@ H5D_write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, H5D_io_info_t io_info; /* Dataset I/O info */ H5D_type_info_t type_info; /* Datatype info for operation */ hbool_t type_info_init = FALSE; /* Whether the datatype info has been initialized */ + H5S_t * projected_mem_space = NULL; /* If not NULL, ptr to dataspace containing a */ + /* projection of the supplied mem_space to a new */ + /* data space with rank equal to that of */ + /* file_space. */ + /* */ + /* This field is only used if */ + /* H5S_select_shape_same() returns TRUE when */ + /* comparing the mem_space and the data_space, */ + /* and the mem_space have different rank. */ + /* */ + /* Note that if this variable is used, the */ + /* projected mem space must be discarded at the */ + /* end of the function to avoid a memory leak. */ H5D_storage_t store; /*union of EFL and chunk pointer in file space */ hssize_t snelmts; /*total number of elmts (signed) */ hsize_t nelmts; /*total number of elmts */ @@ -515,6 +577,37 @@ H5D_write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, file_space = dataset->shared->space; if(!mem_space) mem_space = file_space; + + /* H5S_select_shape_same() has been modified to accept topologically + * identical selections with different rank as having the same shape + * (if the most rapidly changing coordinates match up), but the I/O + * code still has difficulties with the notion. + * + * To solve this, we check to see if H5S_select_shape_same() returns + * true, and if the ranks of the mem and file spaces are different. + * If the are, construct a new mem space that is equivalent to the + * old mem space, and use that instead. + * + * Note that in general, this requires us to touch up the memory buffer + * as well. + */ + if(TRUE == H5S_select_shape_same(mem_space, file_space) && + H5S_GET_EXTENT_NDIMS(mem_space) != H5S_GET_EXTENT_NDIMS(file_space)) { + void *adj_buf = NULL; /* Pointer to the location in buf corresponding */ + /* to the beginning of the projected mem space. */ + + /* Attempt to construct projected dataspace for memory dataspace */ + if(H5S_select_construct_projection(mem_space, &projected_mem_space, + (unsigned)H5S_GET_EXTENT_NDIMS(file_space), buf, &adj_buf, type_info.src_type_size) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to construct projected memory dataspace") + HDassert(projected_mem_space); + HDassert(adj_buf); + + /* Switch to using projected memory dataspace & adjusted buffer */ + mem_space = projected_mem_space; + buf = adj_buf; + } /* end if */ + if((snelmts = H5S_GET_SELECT_NPOINTS(mem_space)) < 0) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "src dataspace has invalid selection") H5_ASSIGN_OVERFLOW(nelmts, snelmts, hssize_t, hsize_t); @@ -608,6 +701,11 @@ done: if(type_info_init && H5D_typeinfo_term(&type_info) < 0) HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to shut down type info") + /* discard projected mem space if it was created */ + if(NULL != projected_mem_space) + if(H5S_close(projected_mem_space) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to shut down projected memory dataspace") + FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL) } /* end H5D_write() */ diff --git a/src/H5Dmpio.c b/src/H5Dmpio.c index ad9b737..e646a7b 100644 --- a/src/H5Dmpio.c +++ b/src/H5Dmpio.c @@ -115,7 +115,7 @@ static herr_t H5D_inter_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, const H5S_t *file_space, const H5S_t *mem_space); static herr_t H5D_final_collective_io(H5D_io_info_t *io_info, - const H5D_type_info_t *type_info, size_t nelmts, MPI_Datatype *mpi_file_type, + const H5D_type_info_t *type_info, hsize_t nelmts, MPI_Datatype *mpi_file_type, MPI_Datatype *mpi_buf_type); #ifdef H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS static herr_t H5D_sort_chunk(H5D_io_info_t *io_info, const H5D_chunk_map_t *fm, @@ -819,10 +819,10 @@ H5D_link_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type H5D_chunk_map_t *fm, int sum_chunk) { H5D_chunk_addr_info_t *chunk_addr_info_array = NULL; - hbool_t mbt_is_derived = FALSE; - hbool_t mft_is_derived = FALSE; MPI_Datatype chunk_final_mtype; /* Final memory MPI datatype for all chunks with seletion */ + hbool_t chunk_final_mtype_is_derived = FALSE; MPI_Datatype chunk_final_ftype; /* Final file MPI datatype for all chunks with seletion */ + hbool_t chunk_final_ftype_is_derived = FALSE; H5D_storage_t ctg_store; /* Storage info for "fake" contiguous dataset */ size_t total_chunks; haddr_t *total_chunk_addr_array = NULL; @@ -830,7 +830,10 @@ H5D_link_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type MPI_Datatype *chunk_ftype = NULL; MPI_Aint *chunk_disp_array = NULL; MPI_Aint *chunk_mem_disp_array = NULL; - int *blocklen = NULL; + hbool_t *chunk_mft_is_derived_array = NULL; /* Flags to indicate each chunk's MPI file datatype is derived */ + hbool_t *chunk_mbt_is_derived_array = NULL; /* Flags to indicate each chunk's MPI memory datatype is derived */ + int *chunk_mpi_file_counts = NULL; /* Count of MPI file datatype for each chunk */ + int *chunk_mpi_mem_counts = NULL; /* Count of MPI memory datatype for each chunk */ int mpi_code; /* MPI return code */ herr_t ret_value = SUCCEED; @@ -897,7 +900,7 @@ if(H5DEBUG(D)) HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL, "couldn't finish shared collective MPI-IO") } /* end if */ else { - size_t mpi_buf_count; /* Number of MPI types */ + hsize_t mpi_buf_count; /* Number of MPI types */ size_t num_chunk; /* Number of chunks for this process */ size_t u; /* Local index variable */ @@ -912,21 +915,25 @@ if(H5DEBUG(D)) /* Set up MPI datatype for chunks selected */ if(num_chunk) { - hsize_t mpi_mem_extra_offset; /* Extra offset for memory MPI datatype */ - hsize_t mpi_file_extra_offset; /* Extra offset for file MPI datatype */ - size_t mpi_mem_count; /* Memory MPI datatype count */ - size_t mpi_file_count; /* File MPI datatype count */ - hbool_t locl_mbt_is_derived = FALSE, /* Whether the buffer (memory) type is derived and needs to be free'd */ - local_mft_is_derived = FALSE; /* Whether the file type is derived and needs to be free'd */ - int blocklen_value; /* Placeholder for array fill */ - /* Allocate chunking information */ - chunk_addr_info_array= H5MM_malloc(num_chunk * sizeof(H5D_chunk_addr_info_t)); - chunk_mtype = H5MM_malloc(num_chunk * sizeof(MPI_Datatype)); - chunk_ftype = H5MM_malloc(num_chunk * sizeof(MPI_Datatype)); - chunk_disp_array = H5MM_malloc(num_chunk * sizeof(MPI_Aint)); - chunk_mem_disp_array = H5MM_calloc(num_chunk * sizeof(MPI_Aint)); - blocklen = H5MM_malloc(num_chunk * sizeof(int)); + if(NULL == (chunk_addr_info_array = (H5D_chunk_addr_info_t *)H5MM_malloc(num_chunk * sizeof(H5D_chunk_addr_info_t)))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate chunk array buffer") + if(NULL == (chunk_mtype = (MPI_Datatype *)H5MM_malloc(num_chunk * sizeof(MPI_Datatype)))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate chunk memory datatype buffer") + if(NULL == (chunk_ftype = (MPI_Datatype *)H5MM_malloc(num_chunk * sizeof(MPI_Datatype)))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate chunk file datatype buffer") + if(NULL == (chunk_disp_array = (MPI_Aint *)H5MM_malloc(num_chunk * sizeof(MPI_Aint)))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate chunk file displacement buffer") + if(NULL == (chunk_mem_disp_array = (MPI_Aint *)H5MM_calloc(num_chunk * sizeof(MPI_Aint)))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate chunk memory displacement buffer") + if(NULL == (chunk_mpi_mem_counts = (int *)H5MM_calloc(num_chunk * sizeof(int)))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate chunk memory counts buffer") + if(NULL == (chunk_mpi_file_counts = (int *)H5MM_calloc(num_chunk * sizeof(int)))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate chunk file counts buffer") + if(NULL == (chunk_mbt_is_derived_array = (hbool_t *)H5MM_calloc(num_chunk * sizeof(hbool_t)))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate chunk memory is derived datatype flags buffer") + if(NULL == (chunk_mft_is_derived_array = (hbool_t *)H5MM_calloc(num_chunk * sizeof(hbool_t)))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate chunk file is derived datatype flags buffer") #ifdef H5D_DEBUG if(H5DEBUG(D)) @@ -945,14 +952,12 @@ if(H5DEBUG(D)) for(u = 0; u < num_chunk; u++) { /* Disk MPI derived datatype */ if(H5S_mpio_space_type(chunk_addr_info_array[u].chunk_info.fspace, - type_info->src_type_size, &chunk_ftype[u], &mpi_file_count, - &mpi_file_extra_offset, &local_mft_is_derived) < 0) + type_info->src_type_size, &chunk_ftype[u], &chunk_mpi_file_counts[u], &(chunk_mft_is_derived_array[u])) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't create MPI file type") /* Buffer MPI derived datatype */ if(H5S_mpio_space_type(chunk_addr_info_array[u].chunk_info.mspace, - type_info->dst_type_size, &chunk_mtype[u], &mpi_mem_count, - &mpi_mem_extra_offset, &locl_mbt_is_derived) < 0) + type_info->dst_type_size, &chunk_mtype[u], &chunk_mpi_mem_counts[u], &(chunk_mbt_is_derived_array[u])) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't create MPI buf type") /* Chunk address relative to the first chunk */ @@ -963,39 +968,38 @@ if(H5DEBUG(D)) chunk_disp_array[u] = (MPI_Aint)chunk_addr_info_array[u].chunk_addr; } /* end for */ - /* Initialize the buffer with the constant value 1 */ - blocklen_value = 1; - H5V_array_fill(blocklen, &blocklen_value, sizeof(int), num_chunk); - /* Create final MPI derived datatype for the file */ - if(MPI_SUCCESS != (mpi_code = MPI_Type_struct((int)num_chunk, blocklen, chunk_disp_array, chunk_ftype, &chunk_final_ftype))) + if(MPI_SUCCESS != (mpi_code = MPI_Type_struct((int)num_chunk, chunk_mpi_file_counts, chunk_disp_array, chunk_ftype, &chunk_final_ftype))) HMPI_GOTO_ERROR(FAIL, "MPI_Type_struct failed", mpi_code) if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&chunk_final_ftype))) HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code) + chunk_final_ftype_is_derived = TRUE; /* Create final MPI derived datatype for memory */ - if(MPI_SUCCESS != (mpi_code = MPI_Type_struct(num_chunk, blocklen, chunk_mem_disp_array, chunk_mtype, &chunk_final_mtype))) + if(MPI_SUCCESS != (mpi_code = MPI_Type_struct((int)num_chunk, chunk_mpi_mem_counts, chunk_mem_disp_array, chunk_mtype, &chunk_final_mtype))) HMPI_GOTO_ERROR(FAIL, "MPI_Type_struct failed", mpi_code) if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&chunk_final_mtype))) HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code) + chunk_final_mtype_is_derived = TRUE; /* Free the file & memory MPI datatypes for each chunk */ for(u = 0; u < num_chunk; u++) { - if(MPI_SUCCESS != (mpi_code = MPI_Type_free(chunk_mtype + u))) - HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + if(chunk_mbt_is_derived_array[u]) + if(MPI_SUCCESS != (mpi_code = MPI_Type_free(chunk_mtype + u))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) - if(MPI_SUCCESS != (mpi_code = MPI_Type_free(chunk_ftype + u))) - HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + if(chunk_mft_is_derived_array[u]) + if(MPI_SUCCESS != (mpi_code = MPI_Type_free(chunk_ftype + u))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) } /* end for */ - /* buffer, file derived datatypes should be true */ - mbt_is_derived = TRUE; - mft_is_derived = TRUE; - mpi_buf_count = (size_t)1; + /* We have a single, complicated MPI datatype for both memory & file */ + mpi_buf_count = (hsize_t)1; } /* end if */ else { /* no selection at all for this process */ /* Allocate chunking information */ - total_chunk_addr_array = H5MM_malloc(sizeof(haddr_t) * total_chunks); + if(NULL == (total_chunk_addr_array = (haddr_t *)H5MM_malloc(sizeof(haddr_t) * total_chunks))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate total chunk address arraybuffer") /* Retrieve chunk address map */ if(H5D_chunk_addrmap(io_info, total_chunk_addr_array) < 0) @@ -1012,8 +1016,8 @@ if(H5DEBUG(D)) chunk_final_ftype = MPI_BYTE; chunk_final_mtype = MPI_BYTE; - /* buffer, file derived datatypes should be true */ - mpi_buf_count = (size_t)0; + /* No chunks selected for this process */ + mpi_buf_count = (hsize_t)0; } /* end else */ #ifdef H5D_DEBUG if(H5DEBUG(D)) @@ -1033,6 +1037,7 @@ done: if(H5DEBUG(D)) HDfprintf(H5DEBUG(D),"before freeing memory inside H5D_link_collective_io ret_value = %d\n", ret_value); #endif + /* Release resources */ if(total_chunk_addr_array) H5MM_xfree(total_chunk_addr_array); if(chunk_addr_info_array) @@ -1045,13 +1050,19 @@ if(H5DEBUG(D)) H5MM_xfree(chunk_disp_array); if(chunk_mem_disp_array) H5MM_xfree(chunk_mem_disp_array); - if(blocklen) - H5MM_xfree(blocklen); + if(chunk_mpi_mem_counts) + H5MM_xfree(chunk_mpi_mem_counts); + if(chunk_mpi_file_counts) + H5MM_xfree(chunk_mpi_file_counts); + if(chunk_mbt_is_derived_array) + H5MM_xfree(chunk_mbt_is_derived_array); + if(chunk_mft_is_derived_array) + H5MM_xfree(chunk_mft_is_derived_array); /* Free the MPI buf and file types, if they were derived */ - if(mbt_is_derived && MPI_SUCCESS != (mpi_code = MPI_Type_free(&chunk_final_mtype))) + if(chunk_final_mtype_is_derived && MPI_SUCCESS != (mpi_code = MPI_Type_free(&chunk_final_mtype))) HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) - if(mft_is_derived && MPI_SUCCESS != (mpi_code = MPI_Type_free(&chunk_final_ftype))) + if(chunk_final_ftype_is_derived && MPI_SUCCESS != (mpi_code = MPI_Type_free(&chunk_final_ftype))) HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) FUNC_LEAVE_NOAPI(ret_value) @@ -1547,32 +1558,29 @@ static herr_t H5D_inter_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, const H5S_t *file_space, const H5S_t *mem_space) { - size_t mpi_buf_count; /* # of MPI types */ + int mpi_buf_count; /* # of MPI types */ hbool_t mbt_is_derived = FALSE; hbool_t mft_is_derived = FALSE; MPI_Datatype mpi_file_type, mpi_buf_type; - int mpi_code; /* MPI return code */ - herr_t ret_value = SUCCEED; /* return value */ + int mpi_code; /* MPI return code */ + herr_t ret_value = SUCCEED; /* return value */ FUNC_ENTER_NOAPI_NOINIT(H5D_inter_collective_io) if((file_space != NULL) && (mem_space != NULL)) { - hsize_t mpi_buf_offset, mpi_file_offset; /* Offset within dataset where selection (ie. MPI type) begins */ - size_t mpi_file_count; /* Number of file "objects" to transfer */ + int mpi_file_count; /* Number of file "objects" to transfer */ /* Obtain disk and memory MPI derived datatype */ - if(H5S_mpio_space_type(file_space, type_info->src_type_size, - &mpi_file_type, &mpi_file_count, &mpi_file_offset, &mft_is_derived) < 0) + if(H5S_mpio_space_type(file_space, type_info->src_type_size, &mpi_file_type, &mpi_file_count, &mft_is_derived) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't create MPI file type") - if(H5S_mpio_space_type(mem_space, type_info->src_type_size, - &mpi_buf_type, &mpi_buf_count, &mpi_buf_offset, &mbt_is_derived) < 0) + if(H5S_mpio_space_type(mem_space, type_info->src_type_size, &mpi_buf_type, &mpi_buf_count, &mbt_is_derived) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't create MPI buffer type") } /* end if */ else { /* For non-selection, participate with a none MPI derived datatype, the count is 0. */ mpi_buf_type = MPI_BYTE; mpi_file_type = MPI_BYTE; - mpi_buf_count = (size_t)0; + mpi_buf_count = 0; mbt_is_derived = FALSE; mft_is_derived = FALSE; } /* end else */ @@ -1583,7 +1591,7 @@ if(H5DEBUG(D)) #endif /* Perform final collective I/O operation */ - if(H5D_final_collective_io(io_info, type_info, mpi_buf_count, &mpi_file_type, &mpi_buf_type) < 0) + if(H5D_final_collective_io(io_info, type_info, (hsize_t)mpi_buf_count, &mpi_file_type, &mpi_buf_type) < 0) HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish collective MPI-IO") done: @@ -1616,7 +1624,7 @@ if(H5DEBUG(D)) */ static herr_t H5D_final_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, - size_t mpi_buf_count, MPI_Datatype *mpi_file_type, MPI_Datatype *mpi_buf_type) + hsize_t mpi_buf_count, MPI_Datatype *mpi_file_type, MPI_Datatype *mpi_buf_type) { hbool_t plist_is_setup = FALSE; /* Whether the dxpl has been customized */ herr_t ret_value = SUCCEED; @@ -1629,11 +1637,11 @@ H5D_final_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info plist_is_setup = TRUE; if(io_info->op_type == H5D_IO_OP_WRITE) { - if((io_info->io_ops.single_write)(io_info, type_info, (hsize_t)mpi_buf_count, NULL, NULL) < 0) + if((io_info->io_ops.single_write)(io_info, type_info, mpi_buf_count, NULL, NULL) < 0) HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "optimized write failed") } /* end if */ else { - if((io_info->io_ops.single_read)(io_info, type_info, (hsize_t)mpi_buf_count, NULL, NULL) < 0) + if((io_info->io_ops.single_read)(io_info, type_info, mpi_buf_count, NULL, NULL) < 0) HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "optimized read failed") } /* end else */ diff --git a/src/H5FDmpio.c b/src/H5FDmpio.c index 117dfc7..b382fb4 100644 --- a/src/H5FDmpio.c +++ b/src/H5FDmpio.c @@ -1771,6 +1771,7 @@ H5FD_mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, } /* end if */ } /* end if */ else { +#if 0 /* JRM -- 3/23/10 */ /* this is no longer always the case */ /* Only one process can do the actual metadata write */ if(file->mpi_rank != H5_PAR_META_WRITE) #ifdef LATER @@ -1778,6 +1779,7 @@ H5FD_mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, #else /* LATER */ HGOTO_DONE(SUCCEED) /* skip the actual write */ #endif /* LATER */ +#endif /* JRM */ } /* end if */ /* Write the data. */ diff --git a/src/H5FDmpiposix.c b/src/H5FDmpiposix.c index 14947a8..86f4d95 100644 --- a/src/H5FDmpiposix.c +++ b/src/H5FDmpiposix.c @@ -1287,9 +1287,11 @@ H5FD_mpiposix_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, HMPI_GOTO_ERROR(FAIL, "MPI_Barrier failed", mpi_code) #endif /* JRM */ +#if 0 /* JRM -- 3/23/10 */ /* this is no longer always the case */ /* Only one process will do the actual write if all procs in comm write same metadata */ if (file->mpi_rank != H5_PAR_META_WRITE) HGOTO_DONE(SUCCEED) /* skip the actual write */ +#endif /* JRM */ } /* end if */ #ifdef REPORT_IO diff --git a/src/H5HLcache.c b/src/H5HLcache.c index 238dce6..51d60f9 100644 --- a/src/H5HLcache.c +++ b/src/H5HLcache.c @@ -330,6 +330,11 @@ H5HL_prefix_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata) /* Check if the current buffer from the speculative read already has the heap data */ if(spec_read_size >= (heap->prfx_size + heap->dblk_size)) { + /* Set p to the start of the data block. This is necessary + * because there may be a gap between the used portion of the + * prefix and the data block due to alignment constraints. */ + p = buf + heap->prfx_size; + /* Copy the heap data from the speculative read buffer */ HDmemcpy(heap->dblk_image, p, heap->dblk_size); } /* end if */ @@ -435,6 +440,11 @@ H5HL_prefix_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, /* Check if the local heap is a single object in cache */ if(heap->single_cache_obj) { + /* Set p to the start of the data block. This is necessary because + * there may be a gap between the used portion of the prefix and the + * data block due to alignment constraints. */ + p = buf + heap->prfx_size; + /* Serialize the free list into the heap data's image */ H5HL_fl_serialize(heap); diff --git a/src/H5Sall.c b/src/H5Sall.c index 115d5d35..c98781a 100644 --- a/src/H5Sall.c +++ b/src/H5Sall.c @@ -47,6 +47,8 @@ static htri_t H5S_all_is_contiguous(const H5S_t *space); static htri_t H5S_all_is_single(const H5S_t *space); static htri_t H5S_all_is_regular(const H5S_t *space); static herr_t H5S_all_adjust_u(H5S_t *space, const hsize_t *offset); +static herr_t H5S_all_project_scalar(const H5S_t *space, hsize_t *offset); +static herr_t H5S_all_project_simple(const H5S_t *space, H5S_t *new_space, hsize_t *offset); static herr_t H5S_all_iter_init(H5S_sel_iter_t *iter, const H5S_t *space); /* Selection iteration callbacks */ @@ -76,6 +78,8 @@ const H5S_select_class_t H5S_sel_all[1] = {{ H5S_all_is_single, H5S_all_is_regular, H5S_all_adjust_u, + H5S_all_project_scalar, + H5S_all_project_simple, H5S_all_iter_init, }}; @@ -372,18 +376,18 @@ H5S_all_iter_release (H5S_sel_iter_t UNUSED * iter) EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -herr_t -H5S_all_release (H5S_t UNUSED * space) +static herr_t +H5S_all_release(H5S_t *space) { - FUNC_ENTER_NOAPI_NOFUNC(H5S_all_release); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_all_release) /* Check args */ - assert (space); + HDassert(space); /* Reset the number of elements in the selection */ - space->select.num_elem=0; + space->select.num_elem = 0; - FUNC_LEAVE_NOAPI(SUCCEED); + FUNC_LEAVE_NOAPI(SUCCEED) } /* H5S_all_release() */ @@ -406,18 +410,18 @@ H5S_all_release (H5S_t UNUSED * space) EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -herr_t +static herr_t H5S_all_copy(H5S_t *dst, const H5S_t UNUSED *src, hbool_t UNUSED share_selection) { - FUNC_ENTER_NOAPI_NOFUNC(H5S_all_copy); + FUNC_ENTER_NOAPI_NOFUNC(H5S_all_copy) - assert(src); - assert(dst); + HDassert(src); + HDassert(dst); /* Set number of elements in selection */ - dst->select.num_elem=(hsize_t)H5S_GET_EXTENT_NPOINTS(dst); + dst->select.num_elem = (hsize_t)H5S_GET_EXTENT_NPOINTS(dst); - FUNC_LEAVE_NOAPI(SUCCEED); + FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5S_all_copy() */ @@ -542,20 +546,20 @@ H5S_all_serialize (const H5S_t *space, uint8_t *buf) REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5S_all_deserialize (H5S_t *space, const uint8_t UNUSED *buf) +H5S_all_deserialize(H5S_t *space, const uint8_t UNUSED *buf) { herr_t ret_value; /* return value */ - FUNC_ENTER_NOAPI(H5S_all_deserialize, FAIL); + FUNC_ENTER_NOAPI(H5S_all_deserialize, FAIL) - assert(space); + HDassert(space); /* Change to "all" selection */ if((ret_value = H5S_select_all(space, TRUE)) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection") done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_all_deserialize() */ @@ -764,6 +768,69 @@ H5S_all_adjust_u(H5S_t UNUSED *space, const hsize_t UNUSED *offset) } /* H5S_all_adjust_u() */ +/*------------------------------------------------------------------------- + * Function: H5S_all_project_scalar + * + * Purpose: Projects a single element 'all' selection into a scalar + * dataspace + * + * Return: non-negative on success, negative on failure. + * + * Programmer: Quincey Koziol + * Sunday, July 18, 2010 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5S_all_project_scalar(const H5S_t UNUSED *space, hsize_t *offset) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_all_project_scalar) + + /* Check args */ + HDassert(space && H5S_SEL_ALL == H5S_GET_SELECT_TYPE(space)); + HDassert(offset); + + /* Set offset of selection in projected buffer */ + *offset = 0; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5S_all_project_scalar() */ + + +/*------------------------------------------------------------------------- + * Function: H5S_all_project_simple + * + * Purpose: Projects an 'all' selection onto/into a simple dataspace + * of a different rank + * + * Return: non-negative on success, negative on failure. + * + * Programmer: Quincey Koziol + * Sunday, July 18, 2010 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5S_all_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *offset) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5S_all_project_simple) + + /* Check args */ + HDassert(base_space && H5S_SEL_ALL == H5S_GET_SELECT_TYPE(base_space)); + HDassert(new_space); + HDassert(offset); + + /* Select the entire new space */ + if(H5S_select_all(new_space, TRUE) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "unable to set all selection") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5S_all_project_simple() */ + + /*-------------------------------------------------------------------------- NAME H5S_select_all diff --git a/src/H5Shyper.c b/src/H5Shyper.c index 74402b1..df81275 100644 --- a/src/H5Shyper.c +++ b/src/H5Shyper.c @@ -33,12 +33,12 @@ /* Local datatypes */ /* Static function prototypes */ -static herr_t H5S_hyper_free_span_info (H5S_hyper_span_info_t *span_info); -static herr_t H5S_hyper_free_span (H5S_hyper_span_t *span); -static H5S_hyper_span_info_t *H5S_hyper_copy_span (H5S_hyper_span_info_t *spans); -static herr_t H5S_hyper_span_scratch (H5S_hyper_span_info_t *spans, void *scr_value); -static herr_t H5S_hyper_span_precompute (H5S_hyper_span_info_t *spans, size_t elmt_size); -static herr_t H5S_generate_hyperslab (H5S_t *space, H5S_seloper_t op, +static herr_t H5S_hyper_free_span_info(H5S_hyper_span_info_t *span_info); +static herr_t H5S_hyper_free_span(H5S_hyper_span_t *span); +static H5S_hyper_span_info_t *H5S_hyper_copy_span(H5S_hyper_span_info_t *spans); +static void H5S_hyper_span_scratch(H5S_hyper_span_info_t *spans, void *scr_value); +static herr_t H5S_hyper_span_precompute(H5S_hyper_span_info_t *spans, size_t elmt_size); +static herr_t H5S_generate_hyperslab(H5S_t *space, H5S_seloper_t op, const hsize_t start[], const hsize_t stride[], const hsize_t count[], const hsize_t block[]); static herr_t H5S_hyper_generate_spans(H5S_t *space); /* Needed for use in hyperslab code (H5Shyper.c) */ @@ -62,6 +62,8 @@ static htri_t H5S_hyper_is_contiguous(const H5S_t *space); static htri_t H5S_hyper_is_single(const H5S_t *space); static htri_t H5S_hyper_is_regular(const H5S_t *space); static herr_t H5S_hyper_adjust_u(H5S_t *space, const hsize_t *offset); +static herr_t H5S_hyper_project_scalar(const H5S_t *space, hsize_t *offset); +static herr_t H5S_hyper_project_simple(const H5S_t *space, H5S_t *new_space, hsize_t *offset); static herr_t H5S_hyper_iter_init(H5S_sel_iter_t *iter, const H5S_t *space); /* Selection iteration callbacks */ @@ -96,6 +98,8 @@ const H5S_select_class_t H5S_sel_hyper[1] = {{ H5S_hyper_is_single, H5S_hyper_is_regular, H5S_hyper_adjust_u, + H5S_hyper_project_scalar, + H5S_hyper_project_simple, H5S_hyper_iter_init, }}; @@ -292,15 +296,15 @@ H5S_hyper_iter_init(H5S_sel_iter_t *iter, const H5S_t *space) /* Check if the regular selection can be "flattened" */ if(cont_dim>0) { - unsigned last_dim_flattened=1; /* Flag to indicate that the last dimension was flattened */ - unsigned flat_rank=rank-cont_dim; /* Number of dimensions after flattening */ + unsigned last_dim_flattened = 1; /* Flag to indicate that the last dimension was flattened */ + unsigned flat_rank = rank-cont_dim; /* Number of dimensions after flattening */ unsigned curr_dim; /* Current dimension */ /* Set the iterator's rank to the contiguous dimensions */ - iter->u.hyp.iter_rank=flat_rank; + iter->u.hyp.iter_rank = flat_rank; /* "Flatten" dataspace extent and selection information */ - curr_dim=flat_rank-1; + curr_dim = flat_rank - 1; for(i = (int)rank - 1, acc = 1; i >= 0; i--) { if(tdiminfo[i].block == mem_size[i] && i > 0) { /* "Flatten" this dimension */ @@ -308,24 +312,25 @@ H5S_hyper_iter_init(H5S_sel_iter_t *iter, const H5S_t *space) acc *= mem_size[i]; /* Indicate that the dimension was flattened */ - last_dim_flattened=1; + last_dim_flattened = 1; } /* end if */ else { if(last_dim_flattened) { /* First dimension after flattened dimensions */ - iter->u.hyp.diminfo[curr_dim].start = tdiminfo[i].start*acc; + iter->u.hyp.diminfo[curr_dim].start = tdiminfo[i].start * acc; + /* Special case for single block regular selections */ if(tdiminfo[i].count==1) iter->u.hyp.diminfo[curr_dim].stride = 1; else - iter->u.hyp.diminfo[curr_dim].stride = tdiminfo[i].stride*acc; + iter->u.hyp.diminfo[curr_dim].stride = tdiminfo[i].stride * acc; iter->u.hyp.diminfo[curr_dim].count = tdiminfo[i].count; - iter->u.hyp.diminfo[curr_dim].block = tdiminfo[i].block*acc; - iter->u.hyp.size[curr_dim] = mem_size[i]*acc; + iter->u.hyp.diminfo[curr_dim].block = tdiminfo[i].block * acc; + iter->u.hyp.size[curr_dim] = mem_size[i] * acc; iter->u.hyp.sel_off[curr_dim] = space->select.offset[i] * acc; /* Reset the "last dim flattened" flag to avoid flattened any further dimensions */ - last_dim_flattened=0; + last_dim_flattened = 0; /* Reset the "accumulator" for possible further dimension flattening */ acc=1; @@ -596,12 +601,12 @@ static htri_t H5S_hyper_iter_has_next_block(const H5S_sel_iter_t *iter) { unsigned u; /* Local index variable */ - herr_t ret_value=FALSE; /* Return value */ + htri_t ret_value = FALSE; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_hyper_iter_has_next_block); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_hyper_iter_has_next_block) /* Check args */ - assert (iter); + HDassert(iter); /* Check for a single "regular" hyperslab */ if(iter->u.hyp.diminfo_valid) { @@ -609,25 +614,25 @@ H5S_hyper_iter_has_next_block(const H5S_sel_iter_t *iter) const hsize_t *toff; /* Temporary offset in selection */ /* Check if the offset of the iterator is at the last location in all dimensions */ - tdiminfo=iter->u.hyp.diminfo; - toff=iter->u.hyp.off; - for(u=0; u<iter->rank; u++) { + tdiminfo = iter->u.hyp.diminfo; + toff = iter->u.hyp.off; + for(u = 0; u < iter->rank; u++) { /* If there is only one block, continue */ - if(tdiminfo[u].count==1) + if(tdiminfo[u].count == 1) continue; - if(toff[u]!=(tdiminfo[u].start+((tdiminfo[u].count-1)*tdiminfo[u].stride))) + if(toff[u] != (tdiminfo[u].start + ((tdiminfo[u].count - 1) * tdiminfo[u].stride))) HGOTO_DONE(TRUE); } /* end for */ } /* end if */ else { /* Check for any levels of the tree with more sequences in them */ - for(u=0; u<iter->rank; u++) - if(iter->u.hyp.span[u]->next!=NULL) + for(u = 0; u < iter->rank; u++) + if(iter->u.hyp.span[u]->next != NULL) HGOTO_DONE(TRUE); } /* end else */ done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_hyper_iter_has_next_block() */ @@ -1089,30 +1094,30 @@ H5S_hyper_iter_release (H5S_sel_iter_t *iter) REVISION LOG --------------------------------------------------------------------------*/ static H5S_hyper_span_t * -H5S_hyper_new_span (hsize_t low, hsize_t high, H5S_hyper_span_info_t *down, H5S_hyper_span_t *next) +H5S_hyper_new_span(hsize_t low, hsize_t high, H5S_hyper_span_info_t *down, H5S_hyper_span_t *next) { H5S_hyper_span_t *ret_value; - FUNC_ENTER_NOAPI_NOINIT(H5S_hyper_new_span); + FUNC_ENTER_NOAPI_NOINIT(H5S_hyper_new_span) /* Allocate a new span node */ - if((ret_value = H5FL_MALLOC(H5S_hyper_span_t))==NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate hyperslab span"); + if(NULL == (ret_value = H5FL_MALLOC(H5S_hyper_span_t))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate hyperslab span") /* Copy the span's basic information */ - ret_value->low=low; - ret_value->high=high; - ret_value->nelem=(high-low)+1; - ret_value->pstride=0; - ret_value->down=down; - ret_value->next=next; + ret_value->low = low; + ret_value->high = high; + ret_value->nelem = (high - low) + 1; + ret_value->pstride = 0; + ret_value->down = down; + ret_value->next = next; /* Increment the reference count of the 'down span' if there is one */ - if(ret_value->down!=NULL) + if(ret_value->down) ret_value->down->count++; done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_hyper_new_span() */ @@ -1195,24 +1200,23 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_hyper_span_precompute (H5S_hyper_span_info_t *spans, size_t elmt_size) +H5S_hyper_span_precompute(H5S_hyper_span_info_t *spans, size_t elmt_size) { - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5S_hyper_span_precompute); + FUNC_ENTER_NOAPI_NOINIT(H5S_hyper_span_precompute) - assert(spans); + HDassert(spans); /* Call the helper routine to actually do the work */ - if(H5S_hyper_span_precompute_helper(spans,elmt_size)==FAIL) - HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "can't precompute span info"); + if(H5S_hyper_span_precompute_helper(spans, elmt_size) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "can't precompute span info") /* Reset the scratch pointers for the next routine which needs them */ - if(H5S_hyper_span_scratch(spans,NULL)==FAIL) - HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "can't reset hyperslab scratch pointer"); + H5S_hyper_span_scratch(spans, NULL); done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_hyper_span_precompute() */ @@ -1222,10 +1226,10 @@ done: PURPOSE Set the scratch pointers on hyperslab span trees USAGE - herr_t H5S_hyper_span_scratch(span_info) + void H5S_hyper_span_scratch(span_info) H5S_hyper_span_info_t *span_info; IN: Span tree to reset RETURNS - Non-negative on success, negative on failure + <none> DESCRIPTION Set the scratch pointers on a hyperslab span tree. GLOBAL VARIABLES @@ -1233,37 +1237,33 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -static herr_t -H5S_hyper_span_scratch (H5S_hyper_span_info_t *spans, void *scr_value) +static void +H5S_hyper_span_scratch(H5S_hyper_span_info_t *spans, void *scr_value) { - H5S_hyper_span_t *span; /* Hyperslab span */ - herr_t ret_value=SUCCEED; /* Return value */ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_hyper_span_scratch) - FUNC_ENTER_NOAPI_NOINIT(H5S_hyper_span_scratch); - - assert(spans); + HDassert(spans); /* Check if we've already set this down span tree */ - if(spans->scratch!=scr_value) { + if(spans->scratch != scr_value) { + H5S_hyper_span_t *span; /* Hyperslab span */ + /* Set the tree's scratch pointer */ spans->scratch = (H5S_hyper_span_info_t *)scr_value; /* Set the scratch pointers in all the nodes */ - span=spans->head; - while(span!=NULL) { + span = spans->head; + while(span != NULL) { /* If there are down spans, set their scratch value also */ - if(span->down!=NULL) { - if(H5S_hyper_span_scratch(span->down,scr_value)==FAIL) - HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "can't reset hyperslab scratch pointer"); - } /* end if */ + if(span->down != NULL) + H5S_hyper_span_scratch(span->down, scr_value); /* Advance to next span */ - span=span->next; + span = span->next; } /* end while */ } /* end if */ -done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI_VOID } /* H5S_hyper_span_scratch() */ @@ -1293,65 +1293,65 @@ H5S_hyper_copy_span_helper (H5S_hyper_span_info_t *spans) H5S_hyper_span_info_t *new_down; /* New down span tree */ H5S_hyper_span_info_t *ret_value; - FUNC_ENTER_NOAPI_NOINIT(H5S_hyper_copy_span_helper); + FUNC_ENTER_NOAPI_NOINIT(H5S_hyper_copy_span_helper) - assert(spans); + HDassert(spans); /* Check if the span tree was already copied */ - if(spans->scratch!=NULL && spans->scratch!=(H5S_hyper_span_info_t *)~((size_t)NULL)) { + if(spans->scratch != NULL && spans->scratch != (H5S_hyper_span_info_t *)~((size_t)NULL)) { /* Just return the value of the already copied span tree */ - ret_value=spans->scratch; + ret_value = spans->scratch; /* Increment the reference count of the span tree */ ret_value->count++; } /* end if */ else { /* Allocate a new span_info node */ - if((ret_value = H5FL_MALLOC(H5S_hyper_span_info_t))==NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate hyperslab span"); + if(NULL == (ret_value = H5FL_MALLOC(H5S_hyper_span_info_t))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate hyperslab span info") /* Copy the span_info information */ - ret_value->count=1; - ret_value->scratch=NULL; - ret_value->head=NULL; + ret_value->count = 1; + ret_value->scratch = NULL; + ret_value->head = NULL; /* Set the scratch pointer in the node being copied to the newly allocated node */ - spans->scratch=ret_value; + spans->scratch = ret_value; /* Copy over the nodes in the span list */ - span=spans->head; - prev_span=NULL; - while(span!=NULL) { + span = spans->head; + prev_span = NULL; + while(span != NULL) { /* Allocate a new node */ - if((new_span = H5S_hyper_new_span(span->low,span->high,NULL,NULL))==NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate hyperslab span"); + if(NULL == (new_span = H5S_hyper_new_span(span->low, span->high, NULL, NULL))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate hyperslab span") /* Append to list of spans */ - if(prev_span==NULL) - ret_value->head=new_span; + if(NULL == prev_span) + ret_value->head = new_span; else - prev_span->next=new_span; + prev_span->next = new_span; /* Copy the pstride */ - new_span->pstride=span->pstride; + new_span->pstride = span->pstride; /* Recurse to copy the 'down' spans, if there are any */ - if(span->down!=NULL) { - if((new_down = H5S_hyper_copy_span_helper(span->down))==NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate hyperslab span"); - new_span->down=new_down; + if(span->down != NULL) { + if(NULL == (new_down = H5S_hyper_copy_span_helper(span->down))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, NULL, "can't copy hyperslab spans") + new_span->down = new_down; } /* end if */ /* Update the previous (new) span */ - prev_span=new_span; + prev_span = new_span; /* Advance to next span */ - span=span->next; + span = span->next; } /* end while */ } /* end else */ done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_hyper_copy_span_helper() */ @@ -1375,23 +1375,23 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static H5S_hyper_span_info_t * -H5S_hyper_copy_span (H5S_hyper_span_info_t *spans) +H5S_hyper_copy_span(H5S_hyper_span_info_t *spans) { H5S_hyper_span_info_t *ret_value; - FUNC_ENTER_NOAPI_NOINIT(H5S_hyper_copy_span); + FUNC_ENTER_NOAPI_NOINIT(H5S_hyper_copy_span) - assert(spans); + HDassert(spans); /* Copy the hyperslab span tree */ - ret_value=H5S_hyper_copy_span_helper(spans); + if(NULL == (ret_value = H5S_hyper_copy_span_helper(spans))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy hyperslab span tree") /* Reset the scratch pointers for the next routine which needs them */ - if(H5S_hyper_span_scratch(spans,NULL)==FAIL) - HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, NULL, "can't reset span tree scratch pointers"); + H5S_hyper_span_scratch(spans, NULL); done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_hyper_copy_span() */ @@ -1630,7 +1630,7 @@ H5S_hyper_copy (H5S_t *dst, const H5S_t *src, hbool_t share_selection) assert(dst); /* Allocate space for the hyperslab selection information */ - if((dst->select.sel_info.hslab=H5FL_MALLOC(H5S_hyper_sel_t))==NULL) + if(NULL == (dst->select.sel_info.hslab = H5FL_MALLOC(H5S_hyper_sel_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab info"); /* Set temporary pointers */ @@ -1658,7 +1658,7 @@ H5S_hyper_copy (H5S_t *dst, const H5S_t *src, hbool_t share_selection) } /* end if */ else /* Copy the hyperslab span information */ - dst->select.sel_info.hslab->span_lst=H5S_hyper_copy_span(src->select.sel_info.hslab->span_lst); + dst->select.sel_info.hslab->span_lst = H5S_hyper_copy_span(src->select.sel_info.hslab->span_lst); } /* end if */ done: @@ -2331,44 +2331,44 @@ H5S_hyper_span_blocklist(H5S_hyper_span_info_t *spans, hsize_t start[], hsize_t { H5S_hyper_span_t *curr; /* Pointer to current hyperslab span */ hsize_t u; /* Index variable */ - herr_t ret_value=SUCCEED; /* return value */ + herr_t ret_value = SUCCEED; /* return value */ - FUNC_ENTER_NOAPI_NOINIT(H5S_hyper_span_blocklist); + FUNC_ENTER_NOAPI_NOINIT(H5S_hyper_span_blocklist) /* Sanity checks */ - assert(spans); - assert(rank<H5O_LAYOUT_NDIMS); - assert(start); - assert(end); - assert(startblock); - assert(numblocks && *numblocks>0); - assert(buf && *buf); + HDassert(spans); + HDassert(rank < H5O_LAYOUT_NDIMS); + HDassert(start); + HDassert(end); + HDassert(startblock); + HDassert(numblocks && *numblocks > 0); + HDassert(buf && *buf); /* Walk through the list of spans, recursing or outputing them */ - curr=spans->head; - while(curr!=NULL && *numblocks>0) { + curr = spans->head; + while(curr != NULL && *numblocks > 0) { /* Recurse if this node has down spans */ - if(curr->down!=NULL) { + if(curr->down != NULL) { /* Add the starting and ending points for this span to the list */ - start[rank]=curr->low; - end[rank]=curr->high; + start[rank] = curr->low; + end[rank] = curr->high; /* Recurse down to the next dimension */ - if(H5S_hyper_span_blocklist(curr->down,start,end,rank+1,startblock,numblocks,buf)<0) + if(H5S_hyper_span_blocklist(curr->down, start, end, (rank + 1), startblock, numblocks, buf) < 0) HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release hyperslab spans"); } /* end if */ else { /* Skip this block if we haven't skipped all the startblocks yet */ - if(*startblock>0) { + if(*startblock > 0) { /* Decrement the starting block */ (*startblock)--; - } + } /* end if */ /* Process this block */ else { /* Encode all the previous dimensions starting & ending points */ /* Copy previous starting points */ - for(u=0; u<rank; u++, (*buf)++) + for(u = 0; u < rank; u++, (*buf)++) HDmemcpy(*buf, &start[u], sizeof(hsize_t)); /* Copy starting point for this span */ @@ -2376,7 +2376,7 @@ H5S_hyper_span_blocklist(H5S_hyper_span_info_t *spans, hsize_t start[], hsize_t (*buf)++; /* Copy previous ending points */ - for(u=0; u<rank; u++, (*buf)++) + for(u = 0; u < rank; u++, (*buf)++) HDmemcpy(*buf, &end[u], sizeof(hsize_t)); /* Copy starting point for this span */ @@ -2389,11 +2389,11 @@ H5S_hyper_span_blocklist(H5S_hyper_span_info_t *spans, hsize_t start[], hsize_t } /* end else */ /* Advance to next node */ - curr=curr->next; + curr = curr->next; } /* end while */ done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_hyper_span_blocklist() */ @@ -2430,29 +2430,26 @@ done: static herr_t H5S_get_select_hyper_blocklist(H5S_t *space, hbool_t internal, hsize_t startblock, hsize_t numblocks, hsize_t *buf) { - H5S_hyper_dim_t *diminfo; /* Alias for dataspace's diminfo information */ - hsize_t tmp_count[H5O_LAYOUT_NDIMS]; /* Temporary hyperslab counts */ - hsize_t offset[H5O_LAYOUT_NDIMS]; /* Offset of element in dataspace */ - hsize_t start[H5O_LAYOUT_NDIMS]; /* Location of start of hyperslab */ - hsize_t end[H5O_LAYOUT_NDIMS]; /* Location of end of hyperslab */ - hsize_t temp_off; /* Offset in a given dimension */ - int i; /* Counter */ - int fast_dim; /* Rank of the fastest changing dimension for the dataspace */ - int temp_dim; /* Temporary rank holder */ - int ndims; /* Rank of the dataspace */ - int done; /* Whether we are done with the iteration */ - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_get_select_hyper_blocklist); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_get_select_hyper_blocklist) - assert(space); - assert(buf); + HDassert(space); + HDassert(buf); /* Check for a "regular" hyperslab selection */ if(space->select.sel_info.hslab->diminfo_valid) { + const H5S_hyper_dim_t *diminfo; /* Alias for dataspace's diminfo information */ + hsize_t tmp_count[H5O_LAYOUT_NDIMS]; /* Temporary hyperslab counts */ + hsize_t offset[H5O_LAYOUT_NDIMS]; /* Offset of element in dataspace */ + unsigned fast_dim; /* Rank of the fastest changing dimension for the dataspace */ + unsigned ndims; /* Rank of the dataspace */ + hbool_t done; /* Whether we are done with the iteration */ + unsigned u; /* Counter */ + /* Set some convienence values */ - ndims=space->extent.rank; - fast_dim=ndims-1; + ndims = space->extent.rank; + fast_dim = ndims - 1; /* Check which set of dimension information to use */ if(internal) @@ -2460,39 +2457,41 @@ H5S_get_select_hyper_blocklist(H5S_t *space, hbool_t internal, hsize_t startbloc * Use the "optimized dimension information" to pass back information * on the blocks set, not the "application information". */ - diminfo=space->select.sel_info.hslab->opt_diminfo; + diminfo = space->select.sel_info.hslab->opt_diminfo; else /* * Use the "application dimension information" to pass back to the user * the blocks they set, not the optimized, internal information. */ - diminfo=space->select.sel_info.hslab->app_diminfo; + diminfo = space->select.sel_info.hslab->app_diminfo; /* Build the tables of count sizes as well as the initial offset */ - for(i=0; i<ndims; i++) { - tmp_count[i]=diminfo[i].count; - offset[i]=diminfo[i].start; + for(u = 0; u < ndims; u++) { + tmp_count[u] = diminfo[u].count; + offset[u] = diminfo[u].start; } /* end for */ /* We're not done with the iteration */ - done=0; + done = FALSE; /* Go iterate over the hyperslabs */ - while(done==0 && numblocks>0) { + while(!done && numblocks > 0) { + hsize_t temp_off; /* Offset in a given dimension */ + /* Iterate over the blocks in the fastest dimension */ - while(tmp_count[fast_dim]>0 && numblocks>0) { + while(tmp_count[fast_dim] > 0 && numblocks > 0) { /* Check if we should copy this block information */ - if(startblock==0) { + if(startblock == 0) { /* Copy the starting location */ - HDmemcpy(buf,offset,sizeof(hsize_t)*ndims); - buf+=ndims; + HDmemcpy(buf, offset, sizeof(hsize_t) * ndims); + buf += ndims; /* Compute the ending location */ - HDmemcpy(buf,offset,sizeof(hsize_t)*ndims); - for(i=0; i<ndims; i++) - buf[i]+=(diminfo[i].block-1); - buf+=ndims; + HDmemcpy(buf, offset, sizeof(hsize_t) * ndims); + for(u = 0; u < ndims; u++) + buf[u] += (diminfo[u].block - 1); + buf += ndims; /* Decrement the number of blocks to retrieve */ numblocks--; @@ -2501,33 +2500,35 @@ H5S_get_select_hyper_blocklist(H5S_t *space, hbool_t internal, hsize_t startbloc startblock--; /* Move the offset to the next sequence to start */ - offset[fast_dim]+=diminfo[fast_dim].stride; + offset[fast_dim] += diminfo[fast_dim].stride; /* Decrement the block count */ tmp_count[fast_dim]--; } /* end while */ /* Work on other dimensions if necessary */ - if(fast_dim>0 && numblocks>0) { + if(fast_dim > 0 && numblocks > 0) { + int temp_dim; /* Temporary rank holder */ + /* Reset the block counts */ - tmp_count[fast_dim]=diminfo[fast_dim].count; + tmp_count[fast_dim] = diminfo[fast_dim].count; /* Bubble up the decrement to the slower changing dimensions */ - temp_dim=fast_dim-1; - while(temp_dim>=0 && done==0) { + temp_dim = (int)(fast_dim - 1); + while(temp_dim >= 0 && !done) { /* Decrement the block count */ tmp_count[temp_dim]--; /* Check if we have more blocks left */ - if(tmp_count[temp_dim]>0) + if(tmp_count[temp_dim] > 0) break; /* Check for getting out of iterator */ - if(temp_dim==0) - done=1; + if(temp_dim == 0) + done = TRUE; /* Reset the block count in this dimension */ - tmp_count[temp_dim]=diminfo[temp_dim].count; + tmp_count[temp_dim] = diminfo[temp_dim].count; /* Wrapped a dimension, go up to next dimension */ temp_dim--; @@ -2535,16 +2536,20 @@ H5S_get_select_hyper_blocklist(H5S_t *space, hbool_t internal, hsize_t startbloc } /* end if */ /* Re-compute offset array */ - for(i=0; i<ndims; i++) { - temp_off=diminfo[i].start+diminfo[i].stride*(diminfo[i].count-tmp_count[i]); - offset[i]=temp_off; + for(u = 0; u < ndims; u++) { + temp_off = diminfo[u].start + diminfo[u].stride * (diminfo[u].count - tmp_count[u]); + offset[u] = temp_off; } /* end for */ } /* end while */ } /* end if */ - else - ret_value=H5S_hyper_span_blocklist(space->select.sel_info.hslab->span_lst,start,end,(hsize_t)0,&startblock,&numblocks,&buf); + else { + hsize_t start[H5O_LAYOUT_NDIMS]; /* Location of start of hyperslab */ + hsize_t end[H5O_LAYOUT_NDIMS]; /* Location of end of hyperslab */ - FUNC_LEAVE_NOAPI(ret_value); + ret_value = H5S_hyper_span_blocklist(space->select.sel_info.hslab->span_lst, start, end, (hsize_t)0, &startblock, &numblocks, &buf); + } /* end else */ + + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_get_select_hyper_blocklist() */ @@ -2636,40 +2641,40 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_hyper_bounds_helper (const H5S_hyper_span_info_t *spans, const hssize_t *offset, hsize_t rank, hsize_t *start, hsize_t *end) +H5S_hyper_bounds_helper(const H5S_hyper_span_info_t *spans, const hssize_t *offset, hsize_t rank, hsize_t *start, hsize_t *end) { - H5S_hyper_span_t *curr; /* Hyperslab information nodes */ - herr_t ret_value=SUCCEED; /* Return value */ + H5S_hyper_span_t *curr; /* Hyperslab information nodes */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5S_hyper_bounds_helper) - assert(spans); - assert(offset); - assert(rank<H5O_LAYOUT_NDIMS); - assert(start); - assert(end); + HDassert(spans); + HDassert(offset); + HDassert(rank < H5O_LAYOUT_NDIMS); + HDassert(start); + HDassert(end); /* Check each point to determine whether selection+offset is within extent */ curr=spans->head; while(curr!=NULL) { /* Check for offset moving selection negative */ - if(((hssize_t)curr->low+offset[rank])<0) + if(((hssize_t)curr->low + offset[rank]) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "offset moves selection out of bounds") /* Check if the current span extends the bounding box */ - if((curr->low+offset[rank])<start[rank]) - start[rank]=curr->low+offset[rank]; - if((curr->high+offset[rank])>end[rank]) - end[rank]=curr->high+offset[rank]; + if((curr->low + offset[rank]) < start[rank]) + start[rank] = curr->low + offset[rank]; + if((curr->high + offset[rank]) > end[rank]) + end[rank] = curr->high + offset[rank]; /* Recurse if this node has down spans */ - if(curr->down!=NULL) { - if(H5S_hyper_bounds_helper(curr->down,offset,rank+1,start,end)<0) + if(curr->down != NULL) { + if(H5S_hyper_bounds_helper(curr->down, offset, (rank + 1), start, end) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "failure in lower dimension") } /* end if */ /* Advance to next node */ - curr=curr->next; + curr = curr->next; } /* end while */ done: @@ -3609,20 +3614,16 @@ done: herr_t H5S_hyper_reset_scratch(H5S_t *space) { - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5S_hyper_reset_scratch); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_hyper_reset_scratch) - assert(space); + HDassert(space); /* Check if there are spans in the span tree */ - if(space->select.sel_info.hslab->span_lst!=NULL) + if(space->select.sel_info.hslab->span_lst != NULL) /* Reset the scratch pointers for the next routine which needs them */ - if(H5S_hyper_span_scratch(space->select.sel_info.hslab->span_lst,NULL)==FAIL) - HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "can't reset span tree scratch pointers"); + H5S_hyper_span_scratch(space->select.sel_info.hslab->span_lst, NULL); -done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(SUCCEED) } /* H5S_hyper_reset_scratch() */ @@ -3685,6 +3686,8 @@ H5S_hyper_convert(H5S_t *space) case H5S_SEL_NONE: /* No elements selected in dataspace */ case H5S_SEL_POINTS: /* Point selection */ + case H5S_SEL_ERROR: /* Selection error */ + case H5S_SEL_N: /* Selection count */ default: HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "can't convert to span tree selection"); } /* end switch */ @@ -4033,8 +4036,7 @@ H5S_hyper_adjust_u(H5S_t *space, const hsize_t *offset) HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab offset adjustment"); /* Reset the scratch pointers for the next routine which needs them */ - if(H5S_hyper_span_scratch(space->select.sel_info.hslab->span_lst,NULL)==FAIL) - HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "can't reset hyperslab scratch pointer"); + H5S_hyper_span_scratch(space->select.sel_info.hslab->span_lst, NULL); } /* end if */ done: @@ -4042,6 +4044,357 @@ done: } /* H5S_hyper_adjust_u() */ +/*------------------------------------------------------------------------- + * Function: H5S_hyper_project_scalar + * + * Purpose: Projects a single element hyperslab selection into a scalar + * dataspace + * + * Return: non-negative on success, negative on failure. + * + * Programmer: Quincey Koziol + * Sunday, July 18, 2010 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5S_hyper_project_scalar(const H5S_t *space, hsize_t *offset) +{ + hsize_t block[H5S_MAX_RANK]; /* Block selected in base dataspace */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5S_hyper_project_scalar) + + /* Check args */ + HDassert(space && H5S_SEL_HYPERSLABS == H5S_GET_SELECT_TYPE(space)); + HDassert(offset); + + /* Check for a "regular" hyperslab selection */ + if(space->select.sel_info.hslab->diminfo_valid) { + const H5S_hyper_dim_t *diminfo = space->select.sel_info.hslab->opt_diminfo; /* Alias for dataspace's diminfo information */ + unsigned u; /* Counter */ + + /* Build the table of the initial offset */ + for(u = 0; u < space->extent.rank; u++) { + block[u] = diminfo[u].start; + + /* Check for more than one hyperslab */ + if(diminfo[u].count > 1 || diminfo[u].block > 1) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "hyperslab selection of one element has more than one node!") + } /* end for */ + } /* end if */ + else { + const H5S_hyper_span_t *curr; /* Pointer to current hyperslab span */ + unsigned curr_dim; /* Current dimension being operated on */ + + /* Advance down selected spans */ + curr = space->select.sel_info.hslab->span_lst->head; + curr_dim = 0; + while(curr) { + /* Check for more than one span */ + if(curr->next || curr->low != curr->high) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "hyperslab selection of one element has more than one node!") + + /* Save the location of the selection in current dimension */ + block[curr_dim] = curr->low; + + /* Advance down to next dimension */ + curr = curr->down->head; + curr_dim++; + } /* end while */ + } /* end else */ + + /* Calculate offset of selection in projected buffer */ + *offset = H5V_array_offset(space->extent.rank, space->extent.size, block); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5S_hyper_project_scalar() */ + + +/*------------------------------------------------------------------------- + * Function: H5S_hyper_project_simple_lower + * + * Purpose: Projects a hyperslab selection onto/into a simple dataspace + * of a lower rank + * + * Return: non-negative on success, negative on failure. + * + * Programmer: Quincey Koziol + * Sunday, July 18, 2010 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5S_hyper_project_simple_lower(const H5S_t *base_space, H5S_t *new_space) +{ + H5S_hyper_span_info_t *down; /* Pointer to list of spans */ + unsigned curr_dim; /* Current dimension being operated on */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_hyper_project_simple_lower) + + /* Check args */ + HDassert(base_space && H5S_SEL_HYPERSLABS == H5S_GET_SELECT_TYPE(base_space)); + HDassert(new_space); + HDassert(new_space->extent.rank < base_space->extent.rank); + + /* Walk down the span tree until we reach the selection to project */ + down = base_space->select.sel_info.hslab->span_lst; + curr_dim = 0; + while(down && curr_dim < (base_space->extent.rank - new_space->extent.rank)) { + /* Sanity check */ + HDassert(NULL == down->head->next); + + /* Advance down to next dimension */ + down = down->head->down; + curr_dim++; + } /* end while */ + HDassert(down); + + /* Share the underlying hyperslab span information */ + new_space->select.sel_info.hslab->span_lst = down; + new_space->select.sel_info.hslab->span_lst->count++; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5S_hyper_project_simple_lower() */ + + +/*------------------------------------------------------------------------- + * Function: H5S_hyper_project_simple_higher + * + * Purpose: Projects a hyperslab selection onto/into a simple dataspace + * of a higher rank + * + * Return: non-negative on success, negative on failure. + * + * Programmer: Quincey Koziol + * Sunday, July 18, 2010 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5S_hyper_project_simple_higher(const H5S_t *base_space, H5S_t *new_space) +{ + H5S_hyper_span_t *prev_span = NULL; /* Pointer to previous list of spans */ + unsigned curr_dim; /* Current dimension being operated on */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5S_hyper_project_simple_higher) + + /* Check args */ + HDassert(base_space && H5S_SEL_HYPERSLABS == H5S_GET_SELECT_TYPE(base_space)); + HDassert(new_space); + HDassert(new_space->extent.rank > base_space->extent.rank); + + /* Create nodes until reaching the correct # of dimensions */ + new_space->select.sel_info.hslab->span_lst = NULL; + curr_dim = 0; + while(curr_dim < (new_space->extent.rank - base_space->extent.rank)) { + H5S_hyper_span_info_t *new_span_info; /* Pointer to list of spans */ + H5S_hyper_span_t *new_span; /* Temporary hyperslab span */ + + /* Allocate a new span_info node */ + if(NULL == (new_span_info = H5FL_MALLOC(H5S_hyper_span_info_t))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab span info") + + /* Check for linking into higher span */ + if(prev_span) + prev_span->down = new_span_info; + + /* Allocate a new node */ + if(NULL == (new_span = H5S_hyper_new_span(0, 0, NULL, NULL))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab span") + + /* Set the span_info information */ + new_span_info->count = 1; + new_span_info->scratch = NULL; + new_span_info->head = new_span; + + /* Attach to new space, if top span info */ + if(NULL == new_space->select.sel_info.hslab->span_lst) + new_space->select.sel_info.hslab->span_lst = new_span_info; + + /* Remember previous span info */ + prev_span = new_span; + + /* Advance to next dimension */ + curr_dim++; + } /* end while */ + HDassert(new_space->select.sel_info.hslab->span_lst); + HDassert(prev_span); + + /* Share the underlying hyperslab span information */ + prev_span->down = base_space->select.sel_info.hslab->span_lst; + prev_span->down->count++; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5S_hyper_project_simple_higher() */ + + +/*------------------------------------------------------------------------- + * Function: H5S_hyper_project_simple + * + * Purpose: Projects a hyperslab selection onto/into a simple dataspace + * of a different rank + * + * Return: non-negative on success, negative on failure. + * + * Programmer: Quincey Koziol + * Sunday, July 18, 2010 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5S_hyper_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *offset) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5S_hyper_project_simple) + + /* Check args */ + HDassert(base_space && H5S_SEL_HYPERSLABS == H5S_GET_SELECT_TYPE(base_space)); + HDassert(new_space); + HDassert(offset); + + /* We are setting a new selection, remove any current selection in new dataspace */ + if(H5S_SELECT_RELEASE(new_space) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release selection") + + /* Allocate space for the hyperslab selection information */ + if(NULL == (new_space->select.sel_info.hslab = H5FL_MALLOC(H5S_hyper_sel_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab info") + + /* Check for a "regular" hyperslab selection */ + if(base_space->select.sel_info.hslab->diminfo_valid) { + unsigned base_space_dim; /* Current dimension in the base dataspace */ + unsigned new_space_dim; /* Current dimension in the new dataspace */ + + /* Check if the new space's rank is < or > base space's rank */ + if(new_space->extent.rank < base_space->extent.rank) { + const H5S_hyper_dim_t *opt_diminfo = base_space->select.sel_info.hslab->opt_diminfo; /* Alias for dataspace's diminfo information */ + hsize_t block[H5S_MAX_RANK]; /* Block selected in base dataspace */ + unsigned u; /* Local index variable */ + + /* Compute the offset for the down-projection */ + HDmemset(block, 0, sizeof(block)); + for(u = 0; u < (base_space->extent.rank - new_space->extent.rank); u++) + block[u] = opt_diminfo[u].start; + *offset = H5V_array_offset(base_space->extent.rank, base_space->extent.size, block); + + /* Set the correct dimensions for the base & new spaces */ + base_space_dim = base_space->extent.rank - new_space->extent.rank; + new_space_dim = 0; + } /* end if */ + else { + HDassert(new_space->extent.rank > base_space->extent.rank); + + /* The offset is zero when projected into higher dimensions */ + *offset = 0; + + /* Set the diminfo information for the higher dimensions */ + for(new_space_dim = 0; new_space_dim < (new_space->extent.rank - base_space->extent.rank); new_space_dim++) { + new_space->select.sel_info.hslab->app_diminfo[new_space_dim].start = 0; + new_space->select.sel_info.hslab->app_diminfo[new_space_dim].stride = 1; + new_space->select.sel_info.hslab->app_diminfo[new_space_dim].count = 1; + new_space->select.sel_info.hslab->app_diminfo[new_space_dim].block = 1; + + new_space->select.sel_info.hslab->opt_diminfo[new_space_dim].start = 0; + new_space->select.sel_info.hslab->opt_diminfo[new_space_dim].stride = 1; + new_space->select.sel_info.hslab->opt_diminfo[new_space_dim].count = 1; + new_space->select.sel_info.hslab->opt_diminfo[new_space_dim].block = 1; + } /* end for */ + + /* Start at beginning of base space's dimension info */ + base_space_dim = 0; + } /* end else */ + + /* Copy the diminfo */ + while(base_space_dim < base_space->extent.rank) { + new_space->select.sel_info.hslab->app_diminfo[new_space_dim].start = + base_space->select.sel_info.hslab->app_diminfo[base_space_dim].start; + new_space->select.sel_info.hslab->app_diminfo[new_space_dim].stride = + base_space->select.sel_info.hslab->app_diminfo[base_space_dim].stride; + new_space->select.sel_info.hslab->app_diminfo[new_space_dim].count = + base_space->select.sel_info.hslab->app_diminfo[base_space_dim].count; + new_space->select.sel_info.hslab->app_diminfo[new_space_dim].block = + base_space->select.sel_info.hslab->app_diminfo[base_space_dim].block; + + new_space->select.sel_info.hslab->opt_diminfo[new_space_dim].start = + base_space->select.sel_info.hslab->opt_diminfo[base_space_dim].start; + new_space->select.sel_info.hslab->opt_diminfo[new_space_dim].stride = + base_space->select.sel_info.hslab->opt_diminfo[base_space_dim].stride; + new_space->select.sel_info.hslab->opt_diminfo[new_space_dim].count = + base_space->select.sel_info.hslab->opt_diminfo[base_space_dim].count; + new_space->select.sel_info.hslab->opt_diminfo[new_space_dim].block = + base_space->select.sel_info.hslab->opt_diminfo[base_space_dim].block; + + /* Advance to next dimensions */ + base_space_dim++; + new_space_dim++; + } /* end for */ + + /* Indicate that the dimension information is valid */ + new_space->select.sel_info.hslab->diminfo_valid = TRUE; + + /* Indicate that there's no slab information */ + new_space->select.sel_info.hslab->span_lst = NULL; + } /* end if */ + else { + /* Check if the new space's rank is < or > base space's rank */ + if(new_space->extent.rank < base_space->extent.rank) { + const H5S_hyper_span_t *curr; /* Pointer to current hyperslab span */ + hsize_t block[H5S_MAX_RANK]; /* Block selected in base dataspace */ + unsigned curr_dim; /* Current dimension being operated on */ + + /* Clear the block buffer */ + HDmemset(block, 0, sizeof(block)); + + /* Advance down selected spans */ + curr = base_space->select.sel_info.hslab->span_lst->head; + curr_dim = 0; + while(curr && curr_dim < (base_space->extent.rank - new_space->extent.rank)) { + /* Save the location of the selection in current dimension */ + block[curr_dim] = curr->low; + + /* Advance down to next dimension */ + curr = curr->down->head; + curr_dim++; + } /* end while */ + + /* Compute the offset for the down-projection */ + *offset = H5V_array_offset(base_space->extent.rank, base_space->extent.size, block); + + /* Project the base space's selection down in less dimensions */ + if(H5S_hyper_project_simple_lower(base_space, new_space) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't project hyperslab selection into less dimensions") + } /* end if */ + else { + HDassert(new_space->extent.rank > base_space->extent.rank); + + /* The offset is zero when projected into higher dimensions */ + *offset = 0; + + /* Project the base space's selection down in less dimensions */ + if(H5S_hyper_project_simple_higher(base_space, new_space) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't project hyperslab selection into less dimensions") + } /* end else */ + + /* Indicate that the dimension information is not valid */ + new_space->select.sel_info.hslab->diminfo_valid = FALSE; + } /* end else */ + + /* Number of elements selected will be the same */ + new_space->select.num_elem = base_space->select.num_elem; + + /* Set selection type */ + new_space->select.type = H5S_sel_hyper; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5S_hyper_project_simple() */ + + /*-------------------------------------------------------------------------- NAME H5S_hyper_adjust_helper_s @@ -4061,41 +4414,41 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_hyper_adjust_helper_s (H5S_hyper_span_info_t *spans, const hssize_t *offset) +H5S_hyper_adjust_helper_s(H5S_hyper_span_info_t *spans, const hssize_t *offset) { H5S_hyper_span_t *span; /* Pointer to current span in span tree */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_hyper_adjust_helper_s); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_hyper_adjust_helper_s) /* Sanity check */ - assert(spans); - assert(offset); + HDassert(spans); + HDassert(offset); /* Check if we've already set this down span tree */ - if(spans->scratch!=(H5S_hyper_span_info_t *)~((size_t)NULL)) { + if(spans->scratch != (H5S_hyper_span_info_t *)~((size_t)NULL)) { /* Set the tree's scratch pointer */ - spans->scratch=(H5S_hyper_span_info_t *)~((size_t)NULL); + spans->scratch = (H5S_hyper_span_info_t *)~((size_t)NULL); /* Get the span lists for each span in this tree */ - span=spans->head; + span = spans->head; /* Iterate over the spans in tree */ - while(span!=NULL) { + while(span != NULL) { /* Adjust span offset */ - assert((hssize_t)span->low>=*offset); - span->low-=*offset; - span->high-=*offset; + HDassert((hssize_t)span->low >= *offset); + span->low -= *offset; + span->high -= *offset; /* Recursively adjust spans in next dimension down */ - if(span->down!=NULL) - H5S_hyper_adjust_helper_s(span->down,offset+1); + if(span->down != NULL) + H5S_hyper_adjust_helper_s(span->down, offset + 1); /* Advance to next span in this dimension */ - span=span->next; + span = span->next; } /* end while */ } /* end if */ - FUNC_LEAVE_NOAPI(SUCCEED); + FUNC_LEAVE_NOAPI(SUCCEED) } /* H5S_hyper_adjust_helper_s() */ @@ -4142,8 +4495,7 @@ H5S_hyper_adjust_s(H5S_t *space, const hssize_t *offset) HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab offset adjustment"); /* Reset the scratch pointers for the next routine which needs them */ - if(H5S_hyper_span_scratch(space->select.sel_info.hslab->span_lst,NULL)==FAIL) - HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "can't reset hyperslab scratch pointer"); + H5S_hyper_span_scratch(space->select.sel_info.hslab->span_lst, NULL); } /* end if */ done: @@ -4252,8 +4604,7 @@ H5S_hyper_move(H5S_t *space, const hssize_t *offset) HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab offset movement"); /* Reset the scratch pointers for the next routine which needs them */ - if(H5S_hyper_span_scratch(space->select.sel_info.hslab->span_lst,NULL)==FAIL) - HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "can't reset hyperslab scratch pointer"); + H5S_hyper_span_scratch(space->select.sel_info.hslab->span_lst, NULL); } /* end if */ done: @@ -6035,8 +6386,6 @@ done: * Programmer: Quincey Koziol * Wednesday, January 10, 2001 * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t @@ -6220,18 +6569,18 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation"); } /* end switch */ - if(op==H5S_SELECT_SET) { + if(op == H5S_SELECT_SET) { /* If we are setting a new selection, remove current selection first */ - if(H5S_SELECT_RELEASE(space)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release hyperslab"); + if(H5S_SELECT_RELEASE(space) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release selection") /* Allocate space for the hyperslab selection information */ - if((space->select.sel_info.hslab=H5FL_MALLOC(H5S_hyper_sel_t))==NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab info"); + if(NULL == (space->select.sel_info.hslab = H5FL_MALLOC(H5S_hyper_sel_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab info") /* Save the diminfo */ - space->select.num_elem=1; - for(u=0; u<space->extent.rank; u++) { + space->select.num_elem = 1; + for(u = 0; u < space->extent.rank; u++) { space->select.sel_info.hslab->app_diminfo[u].start = start[u]; space->select.sel_info.hslab->app_diminfo[u].stride = stride[u]; space->select.sel_info.hslab->app_diminfo[u].count = count[u]; @@ -6241,39 +6590,40 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, space->select.sel_info.hslab->opt_diminfo[u].stride = opt_stride[u]; space->select.sel_info.hslab->opt_diminfo[u].count = opt_count[u]; space->select.sel_info.hslab->opt_diminfo[u].block = opt_block[u]; - space->select.num_elem*=(opt_count[u]*opt_block[u]); + + space->select.num_elem *= (opt_count[u] * opt_block[u]); } /* end for */ /* Indicate that the dimension information is valid */ - space->select.sel_info.hslab->diminfo_valid=TRUE; + space->select.sel_info.hslab->diminfo_valid = TRUE; /* Indicate that there's no slab information */ - space->select.sel_info.hslab->span_lst=NULL; + space->select.sel_info.hslab->span_lst = NULL; } /* end if */ - else if(op>=H5S_SELECT_OR && op<=H5S_SELECT_NOTA) { + else if(op >= H5S_SELECT_OR && op <= H5S_SELECT_NOTA) { /* Sanity check */ - assert(H5S_GET_SELECT_TYPE(space)==H5S_SEL_HYPERSLABS); + HDassert(H5S_GET_SELECT_TYPE(space) == H5S_SEL_HYPERSLABS); /* Check if there's no hyperslab span information currently */ - if(space->select.sel_info.hslab->span_lst==NULL) - if(H5S_hyper_generate_spans(space)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "dataspace does not have span tree"); + if(NULL == space->select.sel_info.hslab->span_lst) + if(H5S_hyper_generate_spans(space) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "dataspace does not have span tree") /* Indicate that the regular dimensions are no longer valid */ - space->select.sel_info.hslab->diminfo_valid=FALSE; + space->select.sel_info.hslab->diminfo_valid = FALSE; /* Add in the new hyperslab information */ - if(H5S_generate_hyperslab (space, op, start, opt_stride, opt_count, opt_block)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't generate hyperslabs"); + if(H5S_generate_hyperslab(space, op, start, opt_stride, opt_count, opt_block) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't generate hyperslabs") } /* end if */ else - HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation"); + HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation") /* Set selection type */ - space->select.type=H5S_sel_hyper; + space->select.type = H5S_sel_hyper; done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5S_select_hyperslab() */ diff --git a/src/H5Smpio.c b/src/H5Smpio.c index f535122..e9d0541 100644 --- a/src/H5Smpio.c +++ b/src/H5Smpio.c @@ -31,45 +31,25 @@ #include "H5Fprivate.h" /* File access */ #include "H5FDprivate.h" /* File drivers */ #include "H5Iprivate.h" /* IDs */ +#include "H5MMprivate.h" /* Memory management */ #include "H5Oprivate.h" /* Object headers */ #include "H5Pprivate.h" /* Property lists */ #include "H5Spkg.h" /* Dataspaces */ #ifdef H5_HAVE_PARALLEL -static herr_t -H5S_mpio_all_type( const H5S_t *space, size_t elmt_size, - /* out: */ - MPI_Datatype *new_type, - size_t *count, - hsize_t *extra_offset, - hbool_t *is_derived_type ); -static herr_t -H5S_mpio_none_type( const H5S_t *space, size_t elmt_size, - /* out: */ - MPI_Datatype *new_type, - size_t *count, - hsize_t *extra_offset, - hbool_t *is_derived_type ); -static herr_t -H5S_mpio_hyper_type( const H5S_t *space, size_t elmt_size, - /* out: */ - MPI_Datatype *new_type, - size_t *count, - hsize_t *extra_offset, - hbool_t *is_derived_type ); - -static herr_t -H5S_mpio_span_hyper_type( const H5S_t *space, size_t elmt_size, - /* out: */ - MPI_Datatype *new_type, - size_t *count, - hsize_t *extra_offset, - hbool_t *is_derived_type ); +static herr_t H5S_mpio_all_type(const H5S_t *space, size_t elmt_size, + MPI_Datatype *new_type, int *count, hbool_t *is_derived_type); +static herr_t H5S_mpio_none_type(MPI_Datatype *new_type, int *count, + hbool_t *is_derived_type); +static herr_t H5S_mpio_hyper_type(const H5S_t *space, size_t elmt_size, + MPI_Datatype *new_type, int *count, hbool_t *is_derived_type); +static herr_t H5S_mpio_span_hyper_type(const H5S_t *space, size_t elmt_size, + MPI_Datatype *new_type, int *count, hbool_t *is_derived_type); +static herr_t H5S_obtain_datatype(const hsize_t down[], H5S_hyper_span_t* span, + const MPI_Datatype *elmt_type, MPI_Datatype *span_type, size_t elmt_size); -static herr_t H5S_obtain_datatype(const hsize_t size[], - H5S_hyper_span_t* span,MPI_Datatype *span_type, - size_t elmt_size,int dimindex); +#define H5S_MPIO_INITIAL_ALLOC_COUNT 256 /*------------------------------------------------------------------------- @@ -82,30 +62,20 @@ static herr_t H5S_obtain_datatype(const hsize_t size[], * Outputs: *new_type the MPI type corresponding to the selection * *count how many objects of the new_type in selection * (useful if this is the buffer type for xfer) - * *extra_offset Number of bytes of offset within dataset * *is_derived_type 0 if MPI primitive type, 1 if derived * * Programmer: rky 980813 * - * Modifications: - * - * Quincey Koziol, June 18, 2002 - * Added 'extra_offset' parameter - * *------------------------------------------------------------------------- */ static herr_t -H5S_mpio_all_type( const H5S_t *space, size_t elmt_size, - /* out: */ - MPI_Datatype *new_type, - size_t *count, - hsize_t *extra_offset, - hbool_t *is_derived_type ) +H5S_mpio_all_type(const H5S_t *space, size_t elmt_size, + MPI_Datatype *new_type, int *count, hbool_t *is_derived_type) { hsize_t total_bytes; - hssize_t snelmts; /*total number of elmts (signed) */ - hsize_t nelmts; /*total number of elmts */ - herr_t ret_value = SUCCEED; + hssize_t snelmts; /* Total number of elmts (signed) */ + hsize_t nelmts; /* Total number of elmts */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5S_mpio_all_type) @@ -121,8 +91,7 @@ H5S_mpio_all_type( const H5S_t *space, size_t elmt_size, /* fill in the return values */ *new_type = MPI_BYTE; - H5_ASSIGN_OVERFLOW(*count, total_bytes, hsize_t, size_t); - *extra_offset = 0; + H5_ASSIGN_OVERFLOW(*count, total_bytes, hsize_t, int); *is_derived_type = FALSE; done: @@ -140,32 +109,23 @@ done: * Outputs: *new_type the MPI type corresponding to the selection * *count how many objects of the new_type in selection * (useful if this is the buffer type for xfer) - * *extra_offset Number of bytes of offset within dataset * *is_derived_type 0 if MPI primitive type, 1 if derived * * Programmer: Quincey Koziol, October 29, 2002 * - * Modifications: - * *------------------------------------------------------------------------- */ static herr_t -H5S_mpio_none_type( const H5S_t UNUSED *space, size_t UNUSED elmt_size, - /* out: */ - MPI_Datatype *new_type, - size_t *count, - hsize_t *extra_offset, - hbool_t *is_derived_type ) +H5S_mpio_none_type(MPI_Datatype *new_type, int *count, hbool_t *is_derived_type) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_mpio_none_type); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_mpio_none_type) /* fill in the return values */ *new_type = MPI_BYTE; *count = 0; - *extra_offset = 0; *is_derived_type = FALSE; - FUNC_LEAVE_NOAPI(SUCCEED); + FUNC_LEAVE_NOAPI(SUCCEED) } /* H5S_mpio_none_type() */ @@ -179,35 +139,15 @@ H5S_mpio_none_type( const H5S_t UNUSED *space, size_t UNUSED elmt_size, * Outputs: *new_type the MPI type corresponding to the selection * *count how many objects of the new_type in selection * (useful if this is the buffer type for xfer) - * *extra_offset Number of bytes of offset within dataset * *is_derived_type 0 if MPI primitive type, 1 if derived * * Programmer: rky 980813 * - * Modifications: ppw 990401 - * rky, ppw 2000-09-26 Freed old type after creating struct type. - * rky 2000-10-05 Changed displacements to be MPI_Aint. - * rky 2000-10-06 Added code for cases of empty hyperslab. - * akc, rky 2000-11-16 Replaced hard coded dimension size with - * H5S_MAX_RANK. - * - * Quincey Koziol, June 18, 2002 - * Added 'extra_offset' parameter. Also accomodate selection - * offset in MPI type built. - * - * Albert Cheng, August 4, 2004 - * Reimplemented the algorithm of forming the outer_type by - * defining it as (start, vector, extent) in one call. - * *------------------------------------------------------------------------- */ static herr_t -H5S_mpio_hyper_type( const H5S_t *space, size_t elmt_size, - /* out: */ - MPI_Datatype *new_type, - size_t *count, - hsize_t *extra_offset, - hbool_t *is_derived_type ) +H5S_mpio_hyper_type(const H5S_t *space, size_t elmt_size, + MPI_Datatype *new_type, int *count, hbool_t *is_derived_type) { H5S_sel_iter_t sel_iter; /* Selection iteration info */ hbool_t sel_iter_init = FALSE; /* Selection iteration info has been initialized */ @@ -231,18 +171,16 @@ H5S_mpio_hyper_type( const H5S_t *space, size_t elmt_size, int mpi_code; /* MPI return code */ herr_t ret_value = SUCCEED; - FUNC_ENTER_NOAPI_NOINIT(H5S_mpio_hyper_type); + FUNC_ENTER_NOAPI_NOINIT(H5S_mpio_hyper_type) /* Check args */ HDassert(space); HDassert(sizeof(MPI_Aint) >= sizeof(elmt_size)); - if(0 == elmt_size) - goto empty; /* Initialize selection iterator */ if(H5S_select_iter_init(&sel_iter, space, elmt_size) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator") - sel_iter_init = 1; /* Selection iteration info has been initialized */ + sel_iter_init = TRUE; /* Selection iteration info has been initialized */ /* Abbreviate args */ diminfo = sel_iter.u.hyp.diminfo; @@ -251,18 +189,16 @@ H5S_mpio_hyper_type( const H5S_t *space, size_t elmt_size, /* make a local copy of the dimension info so we can operate with them */ /* Check if this is a "flattened" regular hyperslab selection */ - if(sel_iter.u.hyp.iter_rank!=0 && sel_iter.u.hyp.iter_rank<space->extent.rank) { + if(sel_iter.u.hyp.iter_rank != 0 && sel_iter.u.hyp.iter_rank < space->extent.rank) { /* Flattened selection */ rank = sel_iter.u.hyp.iter_rank; HDassert(rank >= 0 && rank <= H5S_MAX_RANK); /* within array bounds */ - if (0==rank) - goto empty; #ifdef H5S_DEBUG if(H5DEBUG(S)) HDfprintf(H5DEBUG(S), "%s: Flattened selection\n",FUNC); #endif - for ( i=0; i<rank; ++i) { - d[i].start = diminfo[i].start+sel_iter.u.hyp.sel_off[i]; + for(i = 0; i < rank; ++i) { + d[i].start = diminfo[i].start + sel_iter.u.hyp.sel_off[i]; d[i].strid = diminfo[i].stride; d[i].block = diminfo[i].block; d[i].count = diminfo[i].count; @@ -277,26 +213,26 @@ H5S_mpio_hyper_type( const H5S_t *space, size_t elmt_size, HDfprintf(H5DEBUG(S), "\n" ); } #endif - if (0==d[i].block) + if(0 == d[i].block) goto empty; - if (0==d[i].count) + if(0 == d[i].count) goto empty; - if (0==d[i].xtent) + if(0 == d[i].xtent) goto empty; - } + } /* end for */ } /* end if */ else { /* Non-flattened selection */ rank = space->extent.rank; - HDassert(rank >= 0 && rank<=H5S_MAX_RANK); /* within array bounds */ - if (0==rank) + HDassert(rank >= 0 && rank <= H5S_MAX_RANK); /* within array bounds */ + if(0 == rank) goto empty; #ifdef H5S_DEBUG if(H5DEBUG(S)) HDfprintf(H5DEBUG(S),"%s: Non-flattened selection\n",FUNC); #endif - for ( i=0; i<rank; ++i) { - d[i].start = diminfo[i].start+space->select.offset[i]; + for(i = 0; i < rank; ++i) { + d[i].start = diminfo[i].start + space->select.offset[i]; d[i].strid = diminfo[i].stride; d[i].block = diminfo[i].block; d[i].count = diminfo[i].count; @@ -311,40 +247,37 @@ H5S_mpio_hyper_type( const H5S_t *space, size_t elmt_size, HDfprintf(H5DEBUG(S), "\n" ); } #endif - if (0==d[i].block) + if(0 == d[i].block) goto empty; - if (0==d[i].count) + if(0 == d[i].count) goto empty; - if (0==d[i].xtent) + if(0 == d[i].xtent) goto empty; - } + } /* end for */ } /* end else */ /********************************************************************** Compute array "offset[rank]" which gives the offsets for a multi- dimensional array with dimensions "d[i].xtent" (i=0,1,...,rank-1). **********************************************************************/ - offset[rank-1] = 1; - max_xtent[rank-1] = d[rank-1].xtent; -/*#ifdef H5Smpi_DEBUG */ /* leave the old way */ + offset[rank - 1] = 1; + max_xtent[rank - 1] = d[rank - 1].xtent; #ifdef H5S_DEBUG - if(H5DEBUG(S)){ + if(H5DEBUG(S)) { i=rank-1; - HDfprintf(H5DEBUG(S), " offset[%2d]=%d; max_xtent[%2d]=%d\n", + HDfprintf(H5DEBUG(S), " offset[%2d]=%d; max_xtent[%2d]=%d\n", i, offset[i], i, max_xtent[i]); } #endif - for (i=rank-2; i>=0; --i) { - offset[i] = offset[i+1]*d[i+1].xtent; - max_xtent[i] = max_xtent[i+1]*d[i].xtent; + for(i = rank - 2; i >= 0; --i) { + offset[i] = offset[i + 1] * d[i + 1].xtent; + max_xtent[i] = max_xtent[i + 1] * d[i].xtent; #ifdef H5S_DEBUG - if(H5DEBUG(S)){ + if(H5DEBUG(S)) HDfprintf(H5DEBUG(S), " offset[%2d]=%d; max_xtent[%2d]=%d\n", i, offset[i], i, max_xtent[i]); - } #endif - - } + } /* end for */ /* Create a type covering the selected hyperslab. * Multidimensional dataspaces are stored in row-major order. @@ -356,59 +289,58 @@ H5S_mpio_hyper_type( const H5S_t *space, size_t elmt_size, *******************************************************/ #ifdef H5S_DEBUG if(H5DEBUG(S)) { - HDfprintf(H5DEBUG(S), "%s: Making contig type %d MPI_BYTEs\n", FUNC,elmt_size ); + HDfprintf(H5DEBUG(S), "%s: Making contig type %Zu MPI_BYTEs\n", FUNC, elmt_size); for (i=rank-1; i>=0; --i) HDfprintf(H5DEBUG(S), "d[%d].xtent=%Hu \n", i, d[i].xtent); } #endif - if (MPI_SUCCESS != (mpi_code= MPI_Type_contiguous( (int)elmt_size, MPI_BYTE, &inner_type ))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code); + if(MPI_SUCCESS != (mpi_code = MPI_Type_contiguous((int)elmt_size, MPI_BYTE, &inner_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code) /******************************************************* * Construct the type by walking the hyperslab dims * from the inside out: *******************************************************/ - for ( i=rank-1; i>=0; --i) { + for(i = rank - 1; i >= 0; --i) { #ifdef H5S_DEBUG - if(H5DEBUG(S)) { - HDfprintf(H5DEBUG(S), "%s: Dimension i=%d \n" + if(H5DEBUG(S)) + HDfprintf(H5DEBUG(S), "%s: Dimension i=%d \n" "start=%Hd count=%Hu block=%Hu stride=%Hu, xtent=%Hu max_xtent=%d\n", FUNC, i, d[i].start, d[i].count, d[i].block, d[i].strid, d[i].xtent, max_xtent[i]); - } #endif #ifdef H5S_DEBUG if(H5DEBUG(S)) - HDfprintf(H5DEBUG(S), "%s: i=%d Making vector-type \n", FUNC,i); + HDfprintf(H5DEBUG(S), "%s: i=%d Making vector-type \n", FUNC,i); #endif /**************************************** * Build vector type of the selection. ****************************************/ - mpi_code =MPI_Type_vector((int)(d[i].count), /* count */ - (int)(d[i].block), /* blocklength */ - (int)(d[i].strid), /* stride */ - inner_type, /* old type */ - &outer_type); /* new type */ - - MPI_Type_free( &inner_type ); - if (mpi_code!=MPI_SUCCESS) - HMPI_GOTO_ERROR(FAIL, "couldn't create MPI vector type", mpi_code); - - /**************************************** - * Then build the dimension type as (start, vector type, xtent). - ****************************************/ - /* calculate start and extent values of this dimension */ + mpi_code = MPI_Type_vector((int)(d[i].count), /* count */ + (int)(d[i].block), /* blocklength */ + (int)(d[i].strid), /* stride */ + inner_type, /* old type */ + &outer_type); /* new type */ + + MPI_Type_free(&inner_type); + if(mpi_code != MPI_SUCCESS) + HMPI_GOTO_ERROR(FAIL, "couldn't create MPI vector type", mpi_code) + + /**************************************** + * Then build the dimension type as (start, vector type, xtent). + ****************************************/ + /* calculate start and extent values of this dimension */ displacement[1] = d[i].start * offset[i] * elmt_size; displacement[2] = (MPI_Aint)elmt_size * max_xtent[i]; if(MPI_SUCCESS != (mpi_code = MPI_Type_extent(outer_type, &extent_len))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_extent failed", mpi_code); + HMPI_GOTO_ERROR(FAIL, "MPI_Type_extent failed", mpi_code) - /************************************************* - * Restructure this datatype ("outer_type") - * so that it still starts at 0, but its extent - * is the full extent in this dimension. - *************************************************/ - if (displacement[1] > 0 || (int)extent_len < displacement[2]) { + /************************************************* + * Restructure this datatype ("outer_type") + * so that it still starts at 0, but its extent + * is the full extent in this dimension. + *************************************************/ + if(displacement[1] > 0 || (int)extent_len < displacement[2]) { block_length[0] = 1; block_length[1] = 1; @@ -420,42 +352,37 @@ H5S_mpio_hyper_type( const H5S_t *space, size_t elmt_size, old_types[1] = outer_type; old_types[2] = MPI_UB; #ifdef H5S_DEBUG - if(H5DEBUG(S)){ - HDfprintf(H5DEBUG(S), "%s: i=%d Extending struct type\n" - "***displacements: %d, %d, %d\n", - FUNC, i, displacement[0], displacement[1], displacement[2]); - } + if(H5DEBUG(S)) + HDfprintf(H5DEBUG(S), "%s: i=%d Extending struct type\n" + "***displacements: %ld, %ld, %ld\n", + FUNC, i, (long)displacement[0], (long)displacement[1], (long)displacement[2]); #endif - mpi_code = MPI_Type_struct ( 3, /* count */ - block_length, /* blocklengths */ - displacement, /* displacements */ - old_types, /* old types */ - &inner_type); /* new type */ - - MPI_Type_free (&outer_type); - if (mpi_code!=MPI_SUCCESS) - HMPI_GOTO_ERROR(FAIL, "couldn't resize MPI vector type", mpi_code); - } - else { + mpi_code = MPI_Type_struct(3, /* count */ + block_length, /* blocklengths */ + displacement, /* displacements */ + old_types, /* old types */ + &inner_type); /* new type */ + + MPI_Type_free(&outer_type); + if(mpi_code != MPI_SUCCESS) + HMPI_GOTO_ERROR(FAIL, "couldn't resize MPI vector type", mpi_code) + } /* end if */ + else inner_type = outer_type; - } } /* end for */ /*************************** * End of loop, walking * thru dimensions. ***************************/ - /* At this point inner_type is actually the outermost type, even for 0-trip loop */ - *new_type = inner_type; - if (MPI_SUCCESS != (mpi_code= MPI_Type_commit( new_type ))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code); + if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(new_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code) /* fill in the remaining return values */ *count = 1; /* only have to move one of these suckers! */ - *extra_offset = 0; *is_derived_type = TRUE; HGOTO_DONE(SUCCEED); @@ -463,24 +390,21 @@ empty: /* special case: empty hyperslab */ *new_type = MPI_BYTE; *count = 0; - *extra_offset = 0; *is_derived_type = FALSE; done: /* Release selection iterator */ - if(sel_iter_init) { - if (H5S_SELECT_ITER_RELEASE(&sel_iter)<0) - HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator"); - } /* end if */ + if(sel_iter_init) + if(H5S_SELECT_ITER_RELEASE(&sel_iter) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator") #ifdef H5S_DEBUG - if(H5DEBUG(S)){ + if(H5DEBUG(S)) HDfprintf(H5DEBUG(S), "Leave %s, count=%ld is_derived_type=%t\n", FUNC, *count, *is_derived_type ); - } #endif - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S_mpio_hyper_type() */ /*------------------------------------------------------------------------- @@ -494,68 +418,57 @@ done: * Outputs: *new_type the MPI type corresponding to the selection * *count how many objects of the new_type in selection * (useful if this is the buffer type for xfer) - * *extra_offset Number of bytes of offset within dataset * *is_derived_type 0 if MPI primitive type, 1 if derived * * Programmer: kyang * + *------------------------------------------------------------------------- */ static herr_t -H5S_mpio_span_hyper_type( const H5S_t *space, - size_t elmt_size, - MPI_Datatype *new_type,/* out: */ - size_t *count, - hsize_t *extra_offset, - hbool_t *is_derived_type ) +H5S_mpio_span_hyper_type(const H5S_t *space, size_t elmt_size, + MPI_Datatype *new_type, int *count, hbool_t *is_derived_type) { - MPI_Datatype span_type; - H5S_hyper_span_t *ospan; - H5S_hyper_span_info_t *odown; - hsize_t *size; - int mpi_code; - herr_t ret_value = SUCCEED; + MPI_Datatype elmt_type; /* MPI datatype for an element */ + hbool_t elmt_type_is_derived = FALSE; /* Whether the element type has been created */ + MPI_Datatype span_type; /* MPI datatype for overall span tree */ + hsize_t down[H5S_MAX_RANK]; /* 'down' sizes for each dimension */ + int mpi_code; /* MPI return code */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5S_mpio_span_hyper_type) /* Check args */ HDassert(space); - - if(0 == elmt_size) - goto empty; - size = space->extent.size; - if(0 == size) - goto empty; - - odown = space->select.sel_info.hslab->span_lst; - if(NULL == odown) - goto empty; - ospan = odown->head; - if(NULL == ospan) - goto empty; - - /* obtain derived data type */ - if(FAIL == H5S_obtain_datatype(space->extent.size, ospan, &span_type, elmt_size, space->extent.rank)) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't obtain MPI derived data type") - + HDassert(space->extent.size); + HDassert(space->select.sel_info.hslab->span_lst); + HDassert(space->select.sel_info.hslab->span_lst->head); + + /* Create the base type for an element */ + if(MPI_SUCCESS != (mpi_code = MPI_Type_contiguous((int)elmt_size, MPI_BYTE, &elmt_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code) + elmt_type_is_derived = TRUE; + + /* Compute 'down' sizes for each dimension */ + if(H5V_array_down(space->extent.rank, space->extent.size, down) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGETSIZE, FAIL, "couldn't compute 'down' dimension sizes") + + /* Obtain derived data type */ + if(H5S_obtain_datatype(down, space->select.sel_info.hslab->span_lst->head, &elmt_type, &span_type, elmt_size) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't obtain MPI derived data type") if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&span_type))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code); - + HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code) *new_type = span_type; + /* fill in the remaining return values */ *count = 1; - *extra_offset = 0; *is_derived_type = TRUE; - HGOTO_DONE(SUCCEED) - -empty: - /* special case: empty hyperslab */ - *new_type = MPI_BYTE; - *count = 0; - *extra_offset = 0; - *is_derived_type = FALSE; - done: + /* Release resources */ + if(elmt_type_is_derived) + if(MPI_SUCCESS != (mpi_code = MPI_Type_free(&elmt_type))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + FUNC_LEAVE_NOAPI(ret_value) } /* end H5S_mpio_span_hyper_type() */ @@ -564,7 +477,7 @@ done: * Function: H5S_obtain datatype * * Purpose: Obtain an MPI derived datatype based on span-tree - implementation + * implementation * * Return: non-negative on success, negative on failure. * @@ -572,165 +485,169 @@ done: * * Programmer: kyang * + *------------------------------------------------------------------------- */ static herr_t -H5S_obtain_datatype(const hsize_t size[], - H5S_hyper_span_t* span, - MPI_Datatype *span_type, - size_t elmt_size, - int dimindex) +H5S_obtain_datatype(const hsize_t *down, H5S_hyper_span_t *span, + const MPI_Datatype *elmt_type, MPI_Datatype *span_type, size_t elmt_size) { - int innercount, outercount; - MPI_Datatype bas_type; - MPI_Datatype temp_type; - MPI_Datatype tempinner_type; + size_t alloc_count; /* Number of span tree nodes allocated at this level */ + size_t outercount; /* Number of span tree nodes at this level */ MPI_Datatype *inner_type = NULL; + hbool_t inner_types_freed = FALSE; /* Whether the inner_type MPI datatypes have been freed */ + hbool_t span_type_valid = FALSE; /* Whether the span_type MPI datatypes is valid */ int *blocklen = NULL; MPI_Aint *disp = NULL; - MPI_Aint stride; - H5S_hyper_span_info_t *down; - H5S_hyper_span_t *tspan; -#ifdef H5_HAVE_MPI2 - MPI_Aint sizeaint, sizedtype; -#endif /* H5_HAVE_MPI2 */ - hsize_t total_lowd, total_lowd1; - int i; - int mpi_code; - herr_t ret_value = SUCCEED; + H5S_hyper_span_t *tspan; /* Temporary pointer to span tree node */ + int mpi_code; /* MPI return status code */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5S_obtain_datatype) + /* Sanity check */ HDassert(span); - inner_type = NULL; - down = NULL; - tspan = NULL; - down = span->down; - tspan = span; - - /* Obtain the number of span tree nodes for this dimension */ - outercount = 0; - while(tspan) { - tspan = tspan->next; - outercount++; - } /* end while */ - if(outercount == 0) - HGOTO_DONE(SUCCEED) - -/* MPI2 hasn't been widely acccepted, adding H5_HAVE_MPI2 for the future use */ -#ifdef H5_HAVE_MPI2 - MPI_Type_extent(MPI_Aint, &sizeaint); - MPI_Type_extent(MPI_Datatype, &sizedtype); - - blocklen = (int *)HDcalloc((size_t)outercount, sizeof(int)); - disp = (MPI_Aint *)HDcalloc((size_t)outercount, sizeaint); - inner_type = (MPI_Datatype *)HDcalloc((size_t)outercount, sizedtype); -#else - blocklen = (int *)HDcalloc((size_t)outercount, sizeof(int)); - disp = (MPI_Aint *)HDcalloc((size_t)outercount, sizeof(MPI_Aint)); - inner_type = (MPI_Datatype *)HDcalloc((size_t)outercount, sizeof(MPI_Datatype)); -#endif - - tspan = span; - outercount = 0; + /* Allocate the initial displacement & block length buffers */ + alloc_count = H5S_MPIO_INITIAL_ALLOC_COUNT; + if(NULL == (disp = (MPI_Aint *)H5MM_malloc(alloc_count * sizeof(MPI_Aint)))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of displacements") + if(NULL == (blocklen = (int *)H5MM_malloc(alloc_count * sizeof(int)))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of block lengths") /* if this is the fastest changing dimension, it is the base case for derived datatype. */ - if(down == NULL) { - - HDassert(dimindex <= 1); - - if(MPI_SUCCESS != (mpi_code = MPI_Type_contiguous((int)elmt_size, MPI_BYTE, &bas_type))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code); - - if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&bas_type))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code); - + if(NULL == span->down) { + tspan = span; + outercount = 0; while(tspan) { + /* Check if we need to increase the size of the buffers */ + if(outercount >= alloc_count) { + MPI_Aint *tmp_disp; /* Temporary pointer to new displacement buffer */ + int *tmp_blocklen; /* Temporary pointer to new block length buffer */ + + /* Double the allocation count */ + alloc_count *= 2; + + /* Re-allocate the buffers */ + if(NULL == (tmp_disp = (MPI_Aint *)H5MM_realloc(disp, alloc_count * sizeof(MPI_Aint)))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of displacements") + disp = tmp_disp; + if(NULL == (tmp_blocklen = (int *)H5MM_realloc(blocklen, alloc_count * sizeof(int)))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of block lengths") + blocklen = tmp_blocklen; + } /* end if */ + + /* Store displacement & block length */ disp[outercount] = (MPI_Aint)elmt_size * tspan->low; blocklen[outercount] = tspan->nelem; + tspan = tspan->next; outercount++; } /* end while */ - if(MPI_SUCCESS != (mpi_code = MPI_Type_hindexed(outercount, blocklen, disp, bas_type, span_type))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_hindexed failed", mpi_code); + if(MPI_SUCCESS != (mpi_code = MPI_Type_hindexed((int)outercount, blocklen, disp, *elmt_type, span_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_hindexed failed", mpi_code) + span_type_valid = TRUE; } /* end if */ - else { /* dimindex is the rank of the dimension */ - - HDassert(dimindex > 1); - - /* Calculate the total bytes of the lower dimensions */ - total_lowd = 1; /* one dimension down */ - total_lowd1 = 1; /* two dimensions down */ - - for(i = dimindex - 1; i > 0; i--) - total_lowd = total_lowd * size[i]; + else { + size_t u; /* Local index variable */ - for(i = dimindex - 1; i > 1; i--) - total_lowd1 = total_lowd1 * size[i]; + if(NULL == (inner_type = (MPI_Datatype *)H5MM_malloc(alloc_count * sizeof(MPI_Datatype)))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of inner MPI datatypes") + tspan = span; + outercount = 0; while(tspan) { + MPI_Datatype down_type; /* Temporary MPI datatype for a span tree node's children */ + MPI_Aint stride; /* Distance between inner MPI datatypes */ + + /* Check if we need to increase the size of the buffers */ + if(outercount >= alloc_count) { + MPI_Aint *tmp_disp; /* Temporary pointer to new displacement buffer */ + int *tmp_blocklen; /* Temporary pointer to new block length buffer */ + MPI_Datatype *tmp_inner_type; /* Temporary pointer to inner MPI datatype buffer */ + + /* Double the allocation count */ + alloc_count *= 2; + + /* Re-allocate the buffers */ + if(NULL == (tmp_disp = (MPI_Aint *)H5MM_realloc(disp, alloc_count * sizeof(MPI_Aint)))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of displacements") + disp = tmp_disp; + if(NULL == (tmp_blocklen = (int *)H5MM_realloc(blocklen, alloc_count * sizeof(int)))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of block lengths") + blocklen = tmp_blocklen; + if(NULL == (tmp_inner_type = (MPI_Datatype *)H5MM_realloc(inner_type, alloc_count * sizeof(MPI_Datatype)))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of inner MPI datatypes") + } /* end if */ /* Displacement should be in byte and should have dimension information */ /* First using MPI Type vector to build derived data type for this span only */ /* Need to calculate the disp in byte for this dimension. */ /* Calculate the total bytes of the lower dimension */ - - disp[outercount] = tspan->low * total_lowd * elmt_size; + disp[outercount] = tspan->low * (*down) * elmt_size; blocklen[outercount] = 1; - /* generating inner derived datatype by using MPI_Type_hvector */ - if(FAIL == H5S_obtain_datatype(size, tspan->down->head, &temp_type, elmt_size, dimindex - 1)) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't obtain MPI derived data type") - - if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&temp_type))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code); - - /* building the inner vector datatype */ - stride = total_lowd * elmt_size; - innercount = tspan->nelem; + /* Generate MPI datatype for next dimension down */ + if(H5S_obtain_datatype(down + 1, tspan->down->head, elmt_type, &down_type, elmt_size) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't obtain MPI derived data type") - if(MPI_SUCCESS != (mpi_code = MPI_Type_hvector(innercount, 1, stride, temp_type, &tempinner_type))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_hvector failed", mpi_code); + /* Build the MPI datatype for this node */ + stride = (*down) * elmt_size; + H5_CHECK_OVERFLOW(tspan->nelem, hsize_t, int) + if(MPI_SUCCESS != (mpi_code = MPI_Type_hvector((int)tspan->nelem, 1, stride, down_type, &inner_type[outercount]))) { + MPI_Type_free(&down_type); + HMPI_GOTO_ERROR(FAIL, "MPI_Type_hvector failed", mpi_code) + } /* end if */ - if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&tempinner_type))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code); + /* Release MPI datatype for next dimension down */ + if(MPI_SUCCESS != (mpi_code = MPI_Type_free(&down_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_free failed", mpi_code) - if(MPI_SUCCESS != (mpi_code = MPI_Type_free(&temp_type))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_free failed", mpi_code); - - inner_type[outercount] = tempinner_type; - outercount ++; tspan = tspan->next; + outercount++; } /* end while */ /* building the whole vector datatype */ - if(MPI_SUCCESS != (mpi_code = MPI_Type_struct(outercount, blocklen, disp, inner_type, span_type))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_struct failed", mpi_code); + H5_CHECK_OVERFLOW(outercount, size_t, int) + if(MPI_SUCCESS != (mpi_code = MPI_Type_struct((int)outercount, blocklen, disp, inner_type, span_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_struct failed", mpi_code) + span_type_valid = TRUE; + + /* Release inner node types */ + for(u = 0; u < outercount; u++) + if(MPI_SUCCESS != (mpi_code = MPI_Type_free(&inner_type[u]))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + inner_types_freed = TRUE; } /* end else */ - if(inner_type != NULL && down != NULL) { - } /* end if */ - done: + /* General cleanup */ if(inner_type != NULL) { - if(down != NULL) { - for(i = 0; i < outercount; i++) - if(MPI_SUCCESS != (mpi_code = MPI_Type_free(&inner_type[i]))) - HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code); + if(!inner_types_freed) { + size_t u; /* Local index variable */ + + for(u = 0; u < outercount; u++) + if(MPI_SUCCESS != (mpi_code = MPI_Type_free(&inner_type[u]))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) } /* end if */ - HDfree(inner_type); + H5MM_free(inner_type); } /* end if */ if(blocklen != NULL) - HDfree(blocklen); + H5MM_free(blocklen); if(disp != NULL) - HDfree(disp); + H5MM_free(disp); + + /* Error cleanup */ + if(ret_value < 0) { + if(span_type_valid) + if(MPI_SUCCESS != (mpi_code = MPI_Type_free(span_type))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + } /* end if */ FUNC_LEAVE_NOAPI(ret_value) } /* end H5S_obtain_datatype() */ - /*------------------------------------------------------------------------- * Function: H5S_mpio_space_type @@ -743,49 +660,38 @@ done: * Outputs: *new_type the MPI type corresponding to the selection * *count how many objects of the new_type in selection * (useful if this is the buffer type for xfer) - * *extra_offset Number of bytes of offset within dataset * *is_derived_type 0 if MPI primitive type, 1 if derived * * Programmer: rky 980813 * - * Modifications: - * - * Quincey Koziol, June 18, 2002 - * Added 'extra_offset' parameter - * *------------------------------------------------------------------------- */ herr_t -H5S_mpio_space_type( const H5S_t *space, size_t elmt_size, - /* out: */ - MPI_Datatype *new_type, - size_t *count, - hsize_t *extra_offset, - hbool_t *is_derived_type ) +H5S_mpio_space_type(const H5S_t *space, size_t elmt_size, + MPI_Datatype *new_type, int *count, hbool_t *is_derived_type) { - herr_t ret_value = SUCCEED; + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5S_mpio_space_type); + FUNC_ENTER_NOAPI_NOINIT(H5S_mpio_space_type) /* Check args */ HDassert(space); + HDassert(elmt_size); /* Creat MPI type based on the kind of selection */ - switch (H5S_GET_EXTENT_TYPE(space)) { + switch(H5S_GET_EXTENT_TYPE(space)) { case H5S_NULL: case H5S_SCALAR: case H5S_SIMPLE: switch(H5S_GET_SELECT_TYPE(space)) { case H5S_SEL_NONE: - if ( H5S_mpio_none_type( space, elmt_size, - /* out: */ new_type, count, extra_offset, is_derived_type ) <0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't convert \"all\" selection to MPI type"); + if(H5S_mpio_none_type(new_type, count, is_derived_type) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't convert 'none' selection to MPI type") break; case H5S_SEL_ALL: - if ( H5S_mpio_all_type( space, elmt_size, - /* out: */ new_type, count, extra_offset, is_derived_type ) <0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't convert \"all\" selection to MPI type"); + if(H5S_mpio_all_type(space, elmt_size, new_type, count, is_derived_type) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't convert 'all' selection to MPI type") break; case H5S_SEL_POINTS: @@ -794,16 +700,14 @@ H5S_mpio_space_type( const H5S_t *space, size_t elmt_size, break; case H5S_SEL_HYPERSLABS: - if((H5S_SELECT_IS_REGULAR(space) == TRUE)) { - if(H5S_mpio_hyper_type( space, elmt_size, - /* out: */ new_type, count, extra_offset, is_derived_type )<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't convert \"all\" selection to MPI type"); - } - else { - if(H5S_mpio_span_hyper_type( space, elmt_size, - /* out: */ new_type, count, extra_offset, is_derived_type )<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't convert \"all\" selection to MPI type"); - } + if((H5S_SELECT_IS_REGULAR(space) == TRUE)) { + if(H5S_mpio_hyper_type(space, elmt_size, new_type, count, is_derived_type) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't convert regular 'hyperslab' selection to MPI type") + } /* end if */ + else { + if(H5S_mpio_span_hyper_type(space, elmt_size, new_type, count, is_derived_type) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't convert irregular 'hyperslab' selection to MPI type") + } /* end else */ break; default: @@ -815,11 +719,10 @@ H5S_mpio_space_type( const H5S_t *space, size_t elmt_size, default: HDassert("unknown data space type" && 0); break; - } + } /* end switch */ done: FUNC_LEAVE_NOAPI(ret_value); -} - +} /* end H5S_mpio_space_type() */ #endif /* H5_HAVE_PARALLEL */ diff --git a/src/H5Snone.c b/src/H5Snone.c index c6e8a6a..1948f13 100644 --- a/src/H5Snone.c +++ b/src/H5Snone.c @@ -48,6 +48,8 @@ static htri_t H5S_none_is_contiguous(const H5S_t *space); static htri_t H5S_none_is_single(const H5S_t *space); static htri_t H5S_none_is_regular(const H5S_t *space); static herr_t H5S_none_adjust_u(H5S_t *space, const hsize_t *offset); +static herr_t H5S_none_project_scalar(const H5S_t *space, hsize_t *offset); +static herr_t H5S_none_project_simple(const H5S_t *space, H5S_t *new_space, hsize_t *offset); static herr_t H5S_none_iter_init(H5S_sel_iter_t *iter, const H5S_t *space); /* Selection iteration callbacks */ @@ -77,6 +79,8 @@ const H5S_select_class_t H5S_sel_none[1] = {{ H5S_none_is_single, H5S_none_is_regular, H5S_none_adjust_u, + H5S_none_project_scalar, + H5S_none_project_simple, H5S_none_iter_init, }}; @@ -110,18 +114,18 @@ static const H5S_sel_iter_class_t H5S_sel_iter_none[1] = {{ *------------------------------------------------------------------------- */ herr_t -H5S_none_iter_init (H5S_sel_iter_t *iter, const H5S_t UNUSED *space) +H5S_none_iter_init(H5S_sel_iter_t *iter, const H5S_t UNUSED *space) { - FUNC_ENTER_NOAPI_NOFUNC(H5S_none_iter_init); + FUNC_ENTER_NOAPI_NOFUNC(H5S_none_iter_init) /* Check args */ - assert (space && H5S_SEL_NONE==H5S_GET_SELECT_TYPE(space)); - assert (iter); + HDassert(space && H5S_SEL_NONE==H5S_GET_SELECT_TYPE(space)); + HDassert(iter); /* Initialize type of selection iterator */ - iter->type=H5S_sel_iter_none; + iter->type = H5S_sel_iter_none; - FUNC_LEAVE_NOAPI(SUCCEED); + FUNC_LEAVE_NOAPI(SUCCEED) } /* H5S_none_iter_init() */ @@ -141,15 +145,15 @@ H5S_none_iter_init (H5S_sel_iter_t *iter, const H5S_t UNUSED *space) *------------------------------------------------------------------------- */ static herr_t -H5S_none_iter_coords (const H5S_sel_iter_t UNUSED *iter, hsize_t UNUSED *coords) +H5S_none_iter_coords(const H5S_sel_iter_t UNUSED *iter, hsize_t UNUSED *coords) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_iter_coords); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_iter_coords) /* Check args */ - assert (iter); - assert (coords); + HDassert(iter); + HDassert(coords); - FUNC_LEAVE_NOAPI(FAIL); + FUNC_LEAVE_NOAPI(FAIL) } /* H5S_none_iter_coords() */ @@ -169,16 +173,16 @@ H5S_none_iter_coords (const H5S_sel_iter_t UNUSED *iter, hsize_t UNUSED *coords) *------------------------------------------------------------------------- */ static herr_t -H5S_none_iter_block (const H5S_sel_iter_t UNUSED *iter, hsize_t UNUSED *start, hsize_t UNUSED *end) +H5S_none_iter_block(const H5S_sel_iter_t UNUSED *iter, hsize_t UNUSED *start, hsize_t UNUSED *end) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_iter_block); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_iter_block) /* Check args */ - assert (iter); - assert (start); - assert (end); + HDassert(iter); + HDassert(start); + HDassert(end); - FUNC_LEAVE_NOAPI(FAIL); + FUNC_LEAVE_NOAPI(FAIL) } /* H5S_none_iter_block() */ @@ -197,14 +201,14 @@ H5S_none_iter_block (const H5S_sel_iter_t UNUSED *iter, hsize_t UNUSED *start, h *------------------------------------------------------------------------- */ static hsize_t -H5S_none_iter_nelmts (const H5S_sel_iter_t UNUSED *iter) +H5S_none_iter_nelmts(const H5S_sel_iter_t UNUSED *iter) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_iter_nelmts); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_iter_nelmts) /* Check args */ - assert (iter); + HDassert(iter); - FUNC_LEAVE_NOAPI(0); + FUNC_LEAVE_NOAPI(0) } /* H5S_none_iter_nelmts() */ @@ -228,12 +232,12 @@ H5S_none_iter_nelmts (const H5S_sel_iter_t UNUSED *iter) static htri_t H5S_none_iter_has_next_block(const H5S_sel_iter_t UNUSED *iter) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_iter_has_next_block); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_iter_has_next_block) /* Check args */ - assert (iter); + HDassert(iter); - FUNC_LEAVE_NOAPI(FAIL); + FUNC_LEAVE_NOAPI(FAIL) } /* H5S_none_iter_has_next_block() */ @@ -258,13 +262,13 @@ H5S_none_iter_has_next_block(const H5S_sel_iter_t UNUSED *iter) static herr_t H5S_none_iter_next(H5S_sel_iter_t UNUSED *iter, size_t UNUSED nelem) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_iter_next); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_iter_next) /* Check args */ - assert (iter); - assert (nelem>0); + HDassert(iter); + HDassert(nelem>0); - FUNC_LEAVE_NOAPI(SUCCEED); + FUNC_LEAVE_NOAPI(SUCCEED) } /* H5S_none_iter_next() */ @@ -315,14 +319,14 @@ H5S_none_iter_next_block(H5S_sel_iter_t UNUSED *iter) REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_none_iter_release (H5S_sel_iter_t UNUSED * iter) +H5S_none_iter_release(H5S_sel_iter_t UNUSED * iter) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_iter_release); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_iter_release) /* Check args */ - assert (iter); + HDassert(iter); - FUNC_LEAVE_NOAPI(SUCCEED); + FUNC_LEAVE_NOAPI(SUCCEED) } /* H5S_none_iter_release() */ @@ -344,14 +348,14 @@ H5S_none_iter_release (H5S_sel_iter_t UNUSED * iter) REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_none_release (H5S_t UNUSED * space) +H5S_none_release(H5S_t UNUSED * space) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_release); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_release) /* Check args */ - assert (space); + HDassert(space); - FUNC_LEAVE_NOAPI(SUCCEED); + FUNC_LEAVE_NOAPI(SUCCEED) } /* H5S_none_release() */ @@ -377,15 +381,15 @@ H5S_none_release (H5S_t UNUSED * space) static herr_t H5S_none_copy(H5S_t *dst, const H5S_t UNUSED *src, hbool_t UNUSED share_selection) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_copy); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_copy) - assert(src); - assert(dst); + HDassert(src); + HDassert(dst); /* Set number of elements in selection */ - dst->select.num_elem=0; + dst->select.num_elem = 0; - FUNC_LEAVE_NOAPI(SUCCEED); + FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5S_none_copy() */ @@ -410,13 +414,13 @@ H5S_none_copy(H5S_t *dst, const H5S_t UNUSED *src, hbool_t UNUSED share_selectio REVISION LOG --------------------------------------------------------------------------*/ static htri_t -H5S_none_is_valid (const H5S_t UNUSED *space) +H5S_none_is_valid(const H5S_t UNUSED *space) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_is_valid); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_is_valid) - assert(space); + HDassert(space); - FUNC_LEAVE_NOAPI(TRUE); + FUNC_LEAVE_NOAPI(TRUE) } /* end H5S_none_is_valid() */ @@ -440,17 +444,17 @@ H5S_none_is_valid (const H5S_t UNUSED *space) REVISION LOG --------------------------------------------------------------------------*/ static hssize_t -H5S_none_serial_size (const H5S_t UNUSED *space) +H5S_none_serial_size(const H5S_t UNUSED *space) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_serial_size); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_serial_size) - assert(space); + HDassert(space); /* Basic number of bytes required to serialize point selection: * <type (4 bytes)> + <version (4 bytes)> + <padding (4 bytes)> + * <length (4 bytes)> = 16 bytes */ - FUNC_LEAVE_NOAPI(16); + FUNC_LEAVE_NOAPI(16) } /* end H5S_none_serial_size() */ @@ -474,11 +478,11 @@ H5S_none_serial_size (const H5S_t UNUSED *space) REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_none_serialize (const H5S_t *space, uint8_t *buf) +H5S_none_serialize(const H5S_t *space, uint8_t *buf) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_serialize); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_serialize) - assert(space); + HDassert(space); /* Store the preamble information */ UINT32ENCODE(buf, (uint32_t)H5S_GET_SELECT_TYPE(space)); /* Store the type of selection */ @@ -486,7 +490,7 @@ H5S_none_serialize (const H5S_t *space, uint8_t *buf) UINT32ENCODE(buf, (uint32_t)0); /* Store the un-used padding */ UINT32ENCODE(buf, (uint32_t)0); /* Store the additional information length */ - FUNC_LEAVE_NOAPI(SUCCEED); + FUNC_LEAVE_NOAPI(SUCCEED) } /* H5S_none_serialize() */ @@ -510,20 +514,20 @@ H5S_none_serialize (const H5S_t *space, uint8_t *buf) REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_none_deserialize (H5S_t *space, const uint8_t UNUSED *buf) +H5S_none_deserialize(H5S_t *space, const uint8_t UNUSED *buf) { - herr_t ret_value; /* return value */ + herr_t ret_value = SUCCEED; /* return value */ - FUNC_ENTER_NOAPI_NOINIT(H5S_none_deserialize); + FUNC_ENTER_NOAPI_NOINIT(H5S_none_deserialize) - assert(space); + HDassert(space); /* Change to "none" selection */ - if((ret_value=H5S_select_none(space))<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection"); + if(H5S_select_none(space) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection") done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_none_deserialize() */ @@ -555,13 +559,13 @@ done: static herr_t H5S_none_bounds(const H5S_t UNUSED *space, hsize_t UNUSED *start, hsize_t UNUSED *end) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_bounds); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_bounds) - assert(space); - assert(start); - assert(end); + HDassert(space); + HDassert(start); + HDassert(end); - FUNC_LEAVE_NOAPI(FAIL); + FUNC_LEAVE_NOAPI(FAIL) } /* H5Sget_none_bounds() */ @@ -618,11 +622,11 @@ H5S_none_offset(const H5S_t UNUSED *space, hsize_t UNUSED *offset) static htri_t H5S_none_is_contiguous(const H5S_t UNUSED *space) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_is_contiguous); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_is_contiguous) - assert(space); + HDassert(space); - FUNC_LEAVE_NOAPI(FALSE); + FUNC_LEAVE_NOAPI(FALSE) } /* H5S_none_is_contiguous() */ @@ -647,11 +651,11 @@ H5S_none_is_contiguous(const H5S_t UNUSED *space) static htri_t H5S_none_is_single(const H5S_t UNUSED *space) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_is_single); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_is_single) - assert(space); + HDassert(space); - FUNC_LEAVE_NOAPI(FALSE); + FUNC_LEAVE_NOAPI(FALSE) } /* H5S_none_is_single() */ @@ -677,12 +681,12 @@ H5S_none_is_single(const H5S_t UNUSED *space) static htri_t H5S_none_is_regular(const H5S_t UNUSED *space) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_is_regular); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_is_regular) /* Check args */ - assert(space); + HDassert(space); - FUNC_LEAVE_NOAPI(TRUE); + FUNC_LEAVE_NOAPI(TRUE) } /* H5S_none_is_regular() */ @@ -717,6 +721,65 @@ H5S_none_adjust_u(H5S_t UNUSED *space, const hsize_t UNUSED *offset) } /* H5S_none_adjust_u() */ +/*------------------------------------------------------------------------- + * Function: H5S_none_project_scalar + * + * Purpose: Projects a 'none' selection into a scalar dataspace + * + * Return: non-negative on success, negative on failure. + * + * Programmer: Quincey Koziol + * Sunday, July 18, 2010 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5S_none_project_scalar(const H5S_t UNUSED *space, hsize_t UNUSED *offset) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_project_scalar) + + /* Check args */ + HDassert(space && H5S_SEL_NONE == H5S_GET_SELECT_TYPE(space)); + HDassert(offset); + + FUNC_LEAVE_NOAPI(FAIL) +} /* H5S_none_project_scalar() */ + + +/*------------------------------------------------------------------------- + * Function: H5S_none_project_simple + * + * Purpose: Projects an 'none' selection onto/into a simple dataspace + * of a different rank + * + * Return: non-negative on success, negative on failure. + * + * Programmer: Quincey Koziol + * Sunday, July 18, 2010 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5S_none_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *offset) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5S_none_project_simple) + + /* Check args */ + HDassert(base_space && H5S_SEL_NONE == H5S_GET_SELECT_TYPE(base_space)); + HDassert(new_space); + HDassert(offset); + + /* Select the entire new space */ + if(H5S_select_none(new_space) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "unable to set none selection") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5S_none_project_simple() */ + + /*-------------------------------------------------------------------------- NAME H5S_select_none @@ -734,27 +797,28 @@ H5S_none_adjust_u(H5S_t UNUSED *space, const hsize_t UNUSED *offset) EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -herr_t H5S_select_none (H5S_t *space) +herr_t +H5S_select_none(H5S_t *space) { - herr_t ret_value=SUCCEED; /* return value */ + herr_t ret_value = SUCCEED; /* return value */ - FUNC_ENTER_NOAPI(H5S_select_none, FAIL); + FUNC_ENTER_NOAPI(H5S_select_none, FAIL) /* Check args */ - assert(space); + HDassert(space); /* Remove current selection first */ - if(H5S_SELECT_RELEASE(space)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release hyperslab"); + if(H5S_SELECT_RELEASE(space) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release hyperslab") /* Set number of elements in selection */ - space->select.num_elem=0; + space->select.num_elem = 0; /* Set selection type */ - space->select.type=H5S_sel_none; + space->select.type = H5S_sel_none; done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_select_none() */ @@ -833,24 +897,24 @@ H5S_none_get_seq_list(const H5S_t UNUSED *space, unsigned UNUSED flags, H5S_sel_ size_t UNUSED maxseq, size_t UNUSED maxelem, size_t *nseq, size_t *nelem, hsize_t UNUSED *off, size_t UNUSED *len) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_get_seq_list); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_get_seq_list) /* Check args */ - assert(space); - assert(iter); - assert(maxseq>0); - assert(maxelem>0); - assert(nseq); - assert(nelem); - assert(off); - assert(len); + HDassert(space); + HDassert(iter); + HDassert(maxseq > 0); + HDassert(maxelem > 0); + HDassert(nseq); + HDassert(nelem); + HDassert(off); + HDassert(len); /* "none" selections don't generate sequences of bytes */ - *nseq=0; + *nseq = 0; /* They don't use any elements, either */ - *nelem=0; + *nelem = 0; - FUNC_LEAVE_NOAPI(SUCCEED); + FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5S_none_get_seq_list() */ diff --git a/src/H5Spkg.h b/src/H5Spkg.h index b7818a2..0a9df69 100644 --- a/src/H5Spkg.h +++ b/src/H5Spkg.h @@ -145,6 +145,10 @@ typedef htri_t (*H5S_sel_is_single_func_t)(const H5S_t *space); typedef htri_t (*H5S_sel_is_regular_func_t)(const H5S_t *space); /* Method to adjust a selection by an offset */ typedef herr_t (*H5S_sel_adjust_u_func_t)(H5S_t *space, const hsize_t *offset); +/* Method to construct single element projection onto scalar dataspace */ +typedef herr_t (*H5S_sel_project_scalar)(const H5S_t *space, hsize_t *offset); +/* Method to construct selection projection onto/into simple dataspace */ +typedef herr_t (*H5S_sel_project_simple)(const H5S_t *space, H5S_t *new_space, hsize_t *offset); /* Method to initialize iterator for current selection */ typedef herr_t (*H5S_sel_iter_init_func_t)(H5S_sel_iter_t *sel_iter, const H5S_t *space); @@ -166,6 +170,8 @@ typedef struct { H5S_sel_is_single_func_t is_single; /* Method to determine if current selection is a single block */ H5S_sel_is_regular_func_t is_regular; /* Method to determine if current selection is "regular" */ H5S_sel_adjust_u_func_t adjust_u; /* Method to adjust a selection by an offset */ + H5S_sel_project_scalar project_scalar; /* Method to construct scalar dataspace projection */ + H5S_sel_project_simple project_simple; /* Method to construct simple dataspace projection */ H5S_sel_iter_init_func_t iter_init; /* Method to initialize iterator for current selection */ } H5S_select_class_t; diff --git a/src/H5Spoint.c b/src/H5Spoint.c index 24dfe2a..cb7e98f 100644 --- a/src/H5Spoint.c +++ b/src/H5Spoint.c @@ -49,6 +49,8 @@ static htri_t H5S_point_is_contiguous(const H5S_t *space); static htri_t H5S_point_is_single(const H5S_t *space); static htri_t H5S_point_is_regular(const H5S_t *space); static herr_t H5S_point_adjust_u(H5S_t *space, const hsize_t *offset); +static herr_t H5S_point_project_scalar(const H5S_t *space, hsize_t *offset); +static herr_t H5S_point_project_simple(const H5S_t *space, H5S_t *new_space, hsize_t *offset); static herr_t H5S_point_iter_init(H5S_sel_iter_t *iter, const H5S_t *space); /* Selection iteration callbacks */ @@ -78,6 +80,8 @@ const H5S_select_class_t H5S_sel_point[1] = {{ H5S_point_is_single, H5S_point_is_regular, H5S_point_adjust_u, + H5S_point_project_scalar, + H5S_point_project_simple, H5S_point_iter_init, }}; @@ -610,18 +614,18 @@ H5S_point_copy(H5S_t *dst, const H5S_t *src, hbool_t UNUSED share_selection) /* Allocate room for the head of the point list */ if(NULL == (dst->select.sel_info.pnt_lst = H5FL_MALLOC(H5S_pnt_list_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate point node") + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate point list node") curr = src->select.sel_info.pnt_lst->head; new_tail = NULL; while(curr) { /* Create new point */ if(NULL == (new_node = H5FL_MALLOC(H5S_pnt_node_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate point node") + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate point node") new_node->next = NULL; - if(NULL == (new_node->pnt = (hsize_t *)H5MM_malloc(src->extent.rank*sizeof(hsize_t)))) { + if(NULL == (new_node->pnt = (hsize_t *)H5MM_malloc(src->extent.rank * sizeof(hsize_t)))) { new_node = H5FL_FREE(H5S_pnt_node_t, new_node); - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate coordinate information") + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate coordinate information") } /* end if */ /* Copy over the point's coordinates */ @@ -976,7 +980,7 @@ H5S_get_select_elem_pointlist(H5S_t *space, hsize_t startpoint, hsize_t numpoint node = node->next; } /* end while */ - /* Iterate through the node, copying each hyperslab's information */ + /* Iterate through the node, copying each point's information */ while(node != NULL && numpoints > 0) { HDmemcpy(buf, node->pnt, sizeof(hsize_t) * rank); buf += rank; @@ -1346,6 +1350,173 @@ H5S_point_adjust_u(H5S_t *space, const hsize_t *offset) } /* H5S_point_adjust_u() */ +/*------------------------------------------------------------------------- + * Function: H5S_point_project_scalar + * + * Purpose: Projects a single element point selection into a scalar + * dataspace + * + * Return: non-negative on success, negative on failure. + * + * Programmer: Quincey Koziol + * Sunday, July 18, 2010 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5S_point_project_scalar(const H5S_t *space, hsize_t *offset) +{ + const H5S_pnt_node_t *node; /* Point node */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5S_point_project_scalar) + + /* Check args */ + HDassert(space && H5S_SEL_POINTS == H5S_GET_SELECT_TYPE(space)); + HDassert(offset); + + /* Get the head of the point list */ + node = space->select.sel_info.pnt_lst->head; + + /* Check for more than one point selected */ + if(node->next) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "point selection of one element has more than one node!") + + /* Calculate offset of selection in projected buffer */ + *offset = H5V_array_offset(space->extent.rank, space->extent.size, node->pnt); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5S_point_project_scalar() */ + + +/*------------------------------------------------------------------------- + * Function: H5S_point_project_simple + * + * Purpose: Projects a point selection onto/into a simple dataspace + * of a different rank + * + * Return: non-negative on success, negative on failure. + * + * Programmer: Quincey Koziol + * Sunday, July 18, 2010 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5S_point_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *offset) +{ + const H5S_pnt_node_t *base_node; /* Point node in base space */ + H5S_pnt_node_t *new_node; /* Point node in new space */ + H5S_pnt_node_t *prev_node; /* Previous point node in new space */ + unsigned rank_diff; /* Difference in ranks between spaces */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5S_point_project_simple) + + /* Check args */ + HDassert(base_space && H5S_SEL_POINTS == H5S_GET_SELECT_TYPE(base_space)); + HDassert(new_space); + HDassert(offset); + + /* We are setting a new selection, remove any current selection in new dataspace */ + if(H5S_SELECT_RELEASE(new_space) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release selection") + + /* Allocate room for the head of the point list */ + if(NULL == (new_space->select.sel_info.pnt_lst = H5FL_MALLOC(H5S_pnt_list_t))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate point list node") + + /* Check if the new space's rank is < or > base space's rank */ + if(new_space->extent.rank < base_space->extent.rank) { + hsize_t block[H5S_MAX_RANK]; /* Block selected in base dataspace */ + + /* Compute the difference in ranks */ + rank_diff = base_space->extent.rank - new_space->extent.rank; + + /* Calculate offset of selection in projected buffer */ + HDmemset(block, 0, sizeof(block)); + HDmemcpy(block, base_space->select.sel_info.pnt_lst->head->pnt, sizeof(hsize_t) * rank_diff); + *offset = H5V_array_offset(base_space->extent.rank, base_space->extent.size, block); + + /* Iterate through base space's point nodes, copying the point information */ + base_node = base_space->select.sel_info.pnt_lst->head; + prev_node = NULL; + while(base_node) { + /* Create new point */ + if(NULL == (new_node = H5FL_MALLOC(H5S_pnt_node_t))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate point node") + new_node->next = NULL; + if(NULL == (new_node->pnt = (hsize_t *)H5MM_malloc(new_space->extent.rank * sizeof(hsize_t)))) { + new_node = H5FL_FREE(H5S_pnt_node_t, new_node); + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate coordinate information") + } /* end if */ + + /* Copy over the point's coordinates */ + HDmemcpy(new_node->pnt, &base_node->pnt[rank_diff], (new_space->extent.rank * sizeof(hsize_t))); + + /* Keep the order the same when copying */ + if(NULL == prev_node) + prev_node = new_space->select.sel_info.pnt_lst->head = new_node; + else { + prev_node->next = new_node; + prev_node = new_node; + } /* end else */ + + /* Advance to next node */ + base_node = base_node->next; + } /* end while */ + } /* end if */ + else { + HDassert(new_space->extent.rank > base_space->extent.rank); + + /* Compute the difference in ranks */ + rank_diff = new_space->extent.rank - base_space->extent.rank; + + /* The offset is zero when projected into higher dimensions */ + *offset = 0; + + /* Iterate through base space's point nodes, copying the point information */ + base_node = base_space->select.sel_info.pnt_lst->head; + prev_node = NULL; + while(base_node) { + /* Create new point */ + if(NULL == (new_node = H5FL_MALLOC(H5S_pnt_node_t))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate point node") + new_node->next = NULL; + if(NULL == (new_node->pnt = (hsize_t *)H5MM_malloc(new_space->extent.rank * sizeof(hsize_t)))) { + new_node = H5FL_FREE(H5S_pnt_node_t, new_node); + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate coordinate information") + } /* end if */ + + /* Copy over the point's coordinates */ + HDmemset(new_node->pnt, 0, sizeof(hsize_t) * rank_diff); + HDmemcpy(&new_node->pnt[rank_diff], base_node->pnt, (new_space->extent.rank * sizeof(hsize_t))); + + /* Keep the order the same when copying */ + if(NULL == prev_node) + prev_node = new_space->select.sel_info.pnt_lst->head = new_node; + else { + prev_node->next = new_node; + prev_node = new_node; + } /* end else */ + + /* Advance to next node */ + base_node = base_node->next; + } /* end while */ + } /* end else */ + + /* Number of elements selected will be the same */ + new_space->select.num_elem = base_space->select.num_elem; + + /* Set selection type */ + new_space->select.type = H5S_sel_point; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5S_point_project_simple() */ + + /*-------------------------------------------------------------------------- NAME H5Sselect_elements diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h index 2858ddb..d7faa89 100644 --- a/src/H5Sprivate.h +++ b/src/H5Sprivate.h @@ -133,6 +133,8 @@ typedef struct H5S_sel_iter_t { #define H5S_SELECT_IS_SINGLE(S) ((*(S)->select.type->is_single)(S)) #define H5S_SELECT_IS_REGULAR(S) ((*(S)->select.type->is_regular)(S)) #define H5S_SELECT_ADJUST_U(S,O) ((*(S)->select.type->adjust_u)(S, O)) +#define H5S_SELECT_PROJECT_SCALAR(S,O) ((*(S)->select.type->project_scalar)(S, O)) +#define H5S_SELECT_PROJECT_SIMPLE(S,NS, O) ((*(S)->select.type->project_simple)(S, NS, O)) #define H5S_SELECT_ITER_COORDS(ITER,COORDS) ((*(ITER)->type->iter_coords)(ITER,COORDS)) #define H5S_SELECT_ITER_BLOCK(ITER,START,END) ((*(ITER)->type->iter_block)(ITER,START,END)) #define H5S_SELECT_ITER_NELMTS(ITER) ((*(ITER)->type->iter_nelmts)(ITER)) @@ -157,6 +159,8 @@ typedef struct H5S_sel_iter_t { #define H5S_SELECT_IS_SINGLE(S) (H5S_select_is_single(S)) #define H5S_SELECT_IS_REGULAR(S) (H5S_select_is_regular(S)) #define H5S_SELECT_ADJUST_U(S,O) (H5S_select_adjust_u(S, O)) +#define H5S_SELECT_PROJECT_SCALAR(S,O) (H5S_select_project_scalar)(S, O)) +#define H5S_SELECT_PROJECT_SIMPLE(S,NS,O) (H5S_select_project_simple)(S, NS, O)) #define H5S_SELECT_ITER_COORDS(ITER,COORDS) (H5S_select_iter_coords(ITER,COORDS)) #define H5S_SELECT_ITER_BLOCK(ITER,START,END) (H5S_select_iter_block(ITER,START,END)) #define H5S_SELECT_ITER_NELMTS(ITER) (H5S_select_iter_nelmts(ITER)) @@ -215,6 +219,9 @@ H5_DLL herr_t H5S_get_select_offset(const H5S_t *space, hsize_t *offset); H5_DLL herr_t H5S_select_offset(H5S_t *space, const hssize_t *offset); H5_DLL herr_t H5S_select_copy(H5S_t *dst, const H5S_t *src, hbool_t share_selection); H5_DLL htri_t H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2); +H5_DLL herr_t H5S_select_construct_projection(const H5S_t *base_space, + H5S_t **new_space_ptr, unsigned new_space_rank, const void *buf, + void const **adj_buf_ptr, hsize_t element_size); H5_DLL herr_t H5S_select_release(H5S_t *ds); H5_DLL herr_t H5S_select_get_seq_list(const H5S_t *space, unsigned flags, H5S_sel_iter_t *iter, size_t maxseq, size_t maxbytes, @@ -225,6 +232,8 @@ H5_DLL htri_t H5S_select_is_contiguous(const H5S_t *space); H5_DLL htri_t H5S_select_is_single(const H5S_t *space); H5_DLL htri_t H5S_select_is_regular(const H5S_t *space); H5_DLL herr_t H5S_select_adjust_u(H5S_t *space, const hsize_t *offset); +H5_DLL herr_t H5S_select_project_scalar(const H5S_t *space, hsize_t *offset); +H5_DLL herr_t H5S_select_project_simple(const H5S_t *space, H5S_t *new_space, hsize_t *offset); /* Operations on all selections */ H5_DLL herr_t H5S_select_all(H5S_t *space, hbool_t rel_prev); @@ -268,18 +277,8 @@ H5_DLL herr_t H5S_mpio_space_type( const H5S_t *space, size_t elmt_size, /* out: */ MPI_Datatype *new_type, - size_t *count, - hsize_t *extra_offset, + int *count, hbool_t *is_derived_type ); - -H5_DLL herr_t -H5S_mpio_space_span_type( const H5S_t *space, size_t elmt_size, - /* out: */ - MPI_Datatype *new_type, - size_t *count, - hsize_t *extra_offset, - hbool_t *is_derived_type ); - #endif /* H5_HAVE_PARALLEL */ #endif /* _H5Sprivate_H */ diff --git a/src/H5Sselect.c b/src/H5Sselect.c index a419131..17b7fab 100644 --- a/src/H5Sselect.c +++ b/src/H5Sselect.c @@ -27,6 +27,7 @@ #include "H5Eprivate.h" /* Error handling */ #include "H5FLprivate.h" /* Free Lists */ #include "H5Iprivate.h" /* IDs */ +#include "H5MMprivate.h" /* Memory management */ #include "H5Spkg.h" /* Dataspaces */ #include "H5Vprivate.h" /* Vector and array functions */ #include "H5WBprivate.h" /* Wrapped Buffers */ @@ -108,7 +109,7 @@ H5S_select_copy (H5S_t *dst, const H5S_t *src, hbool_t share_selection) { herr_t ret_value; /* return value */ - FUNC_ENTER_NOAPI(H5S_select_copy, FAIL); + FUNC_ENTER_NOAPI(H5S_select_copy, FAIL) /* Check args */ assert(dst); @@ -119,10 +120,10 @@ H5S_select_copy (H5S_t *dst, const H5S_t *src, hbool_t share_selection) /* Perform correct type of copy based on the type of selection */ if((ret_value=(*src->select.type->copy)(dst,src,share_selection))<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy selection specific information"); + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy selection specific information") done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_select_copy() */ @@ -149,14 +150,14 @@ H5S_select_release(H5S_t *ds) { herr_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI_NOFUNC(H5S_select_release); + FUNC_ENTER_NOAPI_NOFUNC(H5S_select_release) assert(ds); /* Call the selection type's release function */ ret_value=(*ds->select.type->release)(ds); - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5S_select_release() */ @@ -186,14 +187,14 @@ H5S_select_get_seq_list(const H5S_t *space, unsigned flags, { herr_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI_NOFUNC(H5S_select_get_seq_list); + FUNC_ENTER_NOAPI_NOFUNC(H5S_select_get_seq_list) assert(space); /* Call the selection type's get_seq_list function */ ret_value=(*space->select.type->get_seq_list)(space,flags,iter,maxseq,maxbytes,nseq,nbytes,off,len); - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5S_select_get_seq_list() */ @@ -221,14 +222,14 @@ H5S_select_serial_size(const H5S_t *space) { hssize_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI_NOFUNC(H5S_select_serial_size); + FUNC_ENTER_NOAPI_NOFUNC(H5S_select_serial_size) assert(space); /* Call the selection type's serial_size function */ ret_value=(*space->select.type->serial_size)(space); - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5S_select_serial_size() */ @@ -259,7 +260,7 @@ H5S_select_serialize(const H5S_t *space, uint8_t *buf) { herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOFUNC(H5S_select_serialize); + FUNC_ENTER_NOAPI_NOFUNC(H5S_select_serialize) assert(space); assert(buf); @@ -267,7 +268,7 @@ H5S_select_serialize(const H5S_t *space, uint8_t *buf) /* Call the selection type's serialize function */ ret_value=(*space->select.type->serialize)(space,buf); - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5S_select_serialize() */ @@ -410,13 +411,13 @@ H5S_select_valid(const H5S_t *space) { htri_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI_NOFUNC(H5S_select_valid); + FUNC_ENTER_NOAPI_NOFUNC(H5S_select_valid) assert(space); ret_value = (*space->select.type->is_valid)(space); - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_select_valid() */ @@ -449,7 +450,7 @@ H5S_select_deserialize (H5S_t *space, const uint8_t *buf) uint32_t sel_type; /* Pointer to the selection type */ herr_t ret_value=FAIL; /* return value */ - FUNC_ENTER_NOAPI(H5S_select_deserialize, FAIL); + FUNC_ENTER_NOAPI(H5S_select_deserialize, FAIL) assert(space); @@ -476,10 +477,10 @@ H5S_select_deserialize (H5S_t *space, const uint8_t *buf) break; } if(ret_value<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTLOAD, FAIL, "can't deserialize selection"); + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTLOAD, FAIL, "can't deserialize selection") done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_select_deserialize() */ @@ -567,7 +568,7 @@ H5S_get_select_bounds(const H5S_t *space, hsize_t *start, hsize_t *end) { herr_t ret_value; /* return value */ - FUNC_ENTER_NOAPI_NOFUNC(H5S_get_select_bounds); + FUNC_ENTER_NOAPI_NOFUNC(H5S_get_select_bounds) /* Check args */ assert(space); @@ -576,7 +577,7 @@ H5S_get_select_bounds(const H5S_t *space, hsize_t *start, hsize_t *end) ret_value = (*space->select.type->bounds)(space,start,end); - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_get_select_bounds() */ @@ -646,14 +647,14 @@ H5S_select_is_contiguous(const H5S_t *space) { herr_t ret_value; /* return value */ - FUNC_ENTER_NOAPI_NOFUNC(H5S_select_is_contiguous); + FUNC_ENTER_NOAPI_NOFUNC(H5S_select_is_contiguous) /* Check args */ assert(space); ret_value = (*space->select.type->is_contiguous)(space); - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_select_is_contiguous() */ @@ -683,14 +684,14 @@ H5S_select_is_single(const H5S_t *space) { herr_t ret_value; /* return value */ - FUNC_ENTER_NOAPI_NOFUNC(H5S_select_is_single); + FUNC_ENTER_NOAPI_NOFUNC(H5S_select_is_single) /* Check args */ assert(space); ret_value = (*space->select.type->is_single)(space); - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_select_is_single() */ @@ -720,14 +721,14 @@ H5S_select_is_regular(const H5S_t *space) { herr_t ret_value; /* return value */ - FUNC_ENTER_NOAPI_NOFUNC(H5S_select_is_regular); + FUNC_ENTER_NOAPI_NOFUNC(H5S_select_is_regular) /* Check args */ assert(space); ret_value = (*space->select.type->is_regular)(space); - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_select_is_regular() */ @@ -770,6 +771,86 @@ H5S_select_adjust_u(H5S_t *space, const hsize_t *offset) /*-------------------------------------------------------------------------- NAME + H5S_select_project_scalar + PURPOSE + Project a single element selection for a scalar dataspace + USAGE + herr_t H5S_select_project_scalar(space, offset) + const H5S_t *space; IN: Pointer to dataspace to project + hsize_t *offset; IN/OUT: Offset of projected point + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Projects a selection of a single element into a scalar dataspace, computing + the offset of the element in the original selection. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + This routine participates in the "Inlining C function pointers" + pattern, don't call it directly, use the appropriate macro + defined in H5Sprivate.h. + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_select_project_scalar(const H5S_t *space, hsize_t *offset) +{ + herr_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOFUNC(H5S_select_project_scalar) + + /* Check args */ + HDassert(space); + HDassert(offset); + + ret_value = (*space->select.type->project_scalar)(space, offset); + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5S_select_project_scalar() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S_select_project_simple + PURPOSE + Project a selection onto/into a dataspace of different rank + USAGE + herr_t H5S_select_project_simple(space, new_space, offset) + const H5S_t *space; IN: Pointer to dataspace to project + H5S_t *new_space; IN/OUT: Pointer to dataspace projected onto + hsize_t *offset; IN/OUT: Offset of projected point + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Projects a selection onto/into a simple dataspace, computing + the offset of the first element in the original selection. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + This routine participates in the "Inlining C function pointers" + pattern, don't call it directly, use the appropriate macro + defined in H5Sprivate.h. + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_select_project_simple(const H5S_t *space, H5S_t *new_space, hsize_t *offset) +{ + herr_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOFUNC(H5S_select_project_simple) + + /* Check args */ + HDassert(space); + HDassert(new_space); + HDassert(offset); + + ret_value = (*space->select.type->project_simple)(space, new_space, offset); + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5S_select_project_simple() */ + + +/*-------------------------------------------------------------------------- + NAME H5S_select_iter_init PURPOSE Initializes iteration information for a selection. @@ -790,7 +871,7 @@ H5S_select_iter_init(H5S_sel_iter_t *sel_iter, const H5S_t *space, size_t elmt_s { herr_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI_NOFUNC(H5S_select_iter_init); + FUNC_ENTER_NOAPI_NOFUNC(H5S_select_iter_init) /* Check args */ assert(sel_iter); @@ -813,7 +894,7 @@ H5S_select_iter_init(H5S_sel_iter_t *sel_iter, const H5S_t *space, size_t elmt_s /* Call initialization routine for selection type */ ret_value= (*space->select.type->iter_init)(sel_iter, space); - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_select_iter_init() */ @@ -844,7 +925,7 @@ H5S_select_iter_coords (const H5S_sel_iter_t *sel_iter, hsize_t *coords) { herr_t ret_value; /* return value */ - FUNC_ENTER_NOAPI_NOFUNC(H5S_select_iter_coords); + FUNC_ENTER_NOAPI_NOFUNC(H5S_select_iter_coords) /* Check args */ assert(sel_iter); @@ -853,7 +934,7 @@ H5S_select_iter_coords (const H5S_sel_iter_t *sel_iter, hsize_t *coords) /* Call iter_coords routine for selection type */ ret_value = (*sel_iter->type->iter_coords)(sel_iter,coords); - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_select_iter_coords() */ #ifdef LATER @@ -886,7 +967,7 @@ H5S_select_iter_block (const H5S_sel_iter_t *iter, hsize_t *start, hsize_t *end) { herr_t ret_value; /* return value */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_select_iter_block); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_select_iter_block) /* Check args */ assert(iter); @@ -896,7 +977,7 @@ H5S_select_iter_block (const H5S_sel_iter_t *iter, hsize_t *start, hsize_t *end) /* Call iter_block routine for selection type */ ret_value = (*iter->type->iter_block)(iter,start,end); - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_select_iter_block() */ #endif /* LATER */ @@ -926,7 +1007,7 @@ H5S_select_iter_nelmts (const H5S_sel_iter_t *sel_iter) { hsize_t ret_value; /* return value */ - FUNC_ENTER_NOAPI_NOFUNC(H5S_select_iter_nelmts); + FUNC_ENTER_NOAPI_NOFUNC(H5S_select_iter_nelmts) /* Check args */ assert(sel_iter); @@ -934,7 +1015,7 @@ H5S_select_iter_nelmts (const H5S_sel_iter_t *sel_iter) /* Call iter_nelmts routine for selection type */ ret_value = (*sel_iter->type->iter_nelmts)(sel_iter); - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_select_iter_nelmts() */ #ifdef LATER @@ -965,7 +1046,7 @@ H5S_select_iter_has_next_block (const H5S_sel_iter_t *iter) { herr_t ret_value; /* return value */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_select_iter_has_next_block); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_select_iter_has_next_block) /* Check args */ assert(iter); @@ -973,7 +1054,7 @@ H5S_select_iter_has_next_block (const H5S_sel_iter_t *iter) /* Call iter_has_next_block routine for selection type */ ret_value = (*iter->type->iter_has_next_block)(iter); - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_select_iter_has_next_block() */ #endif /* LATER */ @@ -1005,7 +1086,7 @@ H5S_select_iter_next(H5S_sel_iter_t *iter, size_t nelem) { herr_t ret_value; /* return value */ - FUNC_ENTER_NOAPI_NOFUNC(H5S_select_iter_next); + FUNC_ENTER_NOAPI_NOFUNC(H5S_select_iter_next) /* Check args */ assert(iter); @@ -1017,7 +1098,7 @@ H5S_select_iter_next(H5S_sel_iter_t *iter, size_t nelem) /* Decrement the number of elements left in selection */ iter->elmt_left-=nelem; - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_select_iter_next() */ #ifdef LATER @@ -1050,7 +1131,7 @@ H5S_select_iter_next_block(H5S_sel_iter_t *iter) { herr_t ret_value; /* return value */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_select_iter_next_block); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_select_iter_next_block) /* Check args */ assert(iter); @@ -1058,7 +1139,7 @@ H5S_select_iter_next_block(H5S_sel_iter_t *iter) /* Call iter_next_block routine for selection type */ ret_value = (*iter->type->iter_next_block)(iter); - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_select_iter_next_block() */ #endif /* LATER */ @@ -1088,7 +1169,7 @@ H5S_select_iter_release(H5S_sel_iter_t *sel_iter) { herr_t ret_value; /* return value */ - FUNC_ENTER_NOAPI_NOFUNC(H5S_select_iter_release); + FUNC_ENTER_NOAPI_NOFUNC(H5S_select_iter_release) /* Check args */ assert(sel_iter); @@ -1096,7 +1177,7 @@ H5S_select_iter_release(H5S_sel_iter_t *sel_iter) /* Call selection type-specific release routine */ ret_value = (*sel_iter->type->iter_release)(sel_iter); - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_select_iter_release() */ @@ -1154,7 +1235,7 @@ H5S_select_iterate(void *buf, hid_t type_id, const H5S_t *space, H5D_operator_t herr_t user_ret=0; /* User's return value */ herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5S_select_iterate, FAIL); + FUNC_ENTER_NOAPI(H5S_select_iterate, FAIL) /* Check args */ HDassert(buf); @@ -1302,7 +1383,7 @@ H5S_get_select_type(const H5S_t *space) { H5S_sel_type ret_value; /* Return value */ - FUNC_ENTER_NOAPI_NOFUNC(H5S_get_select_type); + FUNC_ENTER_NOAPI_NOFUNC(H5S_get_select_type) /* Check args */ assert(space); @@ -1310,7 +1391,7 @@ H5S_get_select_type(const H5S_t *space) /* Set return value */ ret_value=H5S_GET_SELECT_TYPE(space); - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5S_get_select_type() */ @@ -1334,16 +1415,17 @@ H5S_get_select_type(const H5S_t *space) Assumes that there is only a single "block" for hyperslab selections. EXAMPLES REVISION LOG + Modified function to view identical shapes with different dimensions + as being the same under some circumstances. --------------------------------------------------------------------------*/ htri_t H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2) { - H5S_sel_iter_t iter1; /* Selection #1 iteration info */ - H5S_sel_iter_t iter2; /* Selection #2 iteration info */ - hbool_t iter1_init = 0; /* Selection #1 iteration info has been initialized */ - hbool_t iter2_init = 0; /* Selection #2 iteration info has been initialized */ - unsigned u; /* Index variable */ - htri_t ret_value = TRUE; /* Return value */ + H5S_sel_iter_t iter_a; /* Selection a iteration info */ + H5S_sel_iter_t iter_b; /* Selection b iteration info */ + hbool_t iter_a_init = 0; /* Selection a iteration info has been initialized */ + hbool_t iter_b_init = 0; /* Selection b iteration info has been initialized */ + htri_t ret_value = TRUE; /* Return value */ FUNC_ENTER_NOAPI(H5S_select_shape_same, FAIL) @@ -1358,139 +1440,527 @@ H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2) HGOTO_DONE(FALSE) } /* end if */ else { - /* Check for different dimensionality */ - if(space1->extent.rank != space2->extent.rank) - HGOTO_DONE(FALSE) + const H5S_t *space_a; /* Dataspace with larger rank */ + const H5S_t *space_b; /* Dataspace with smaller rank */ + unsigned space_a_rank; /* Number of dimensions of dataspace A */ + unsigned space_b_rank; /* Number of dimensions of dataspace B */ + + /* need to be able to handle spaces of different rank: + * + * To simplify logic, let space_a point to the element of the set + * {space1, space2} with the largest rank or space1 if the ranks + * are identical. + * + * Similarly, let space_b point to the element of {space1, space2} + * with the smallest rank, or space2 if they are identical. + * + * Let: space_a_rank be the rank of space_a, + * space_b_rank be the rank of space_b, + * delta_rank = space_a_rank - space_b_rank. + * + * Set all this up below. + */ + if(space1->extent.rank >= space2->extent.rank) { + space_a = space1; + space_a_rank = space_a->extent.rank; + + space_b = space2; + space_b_rank = space_b->extent.rank; + } /* end if */ + else { + space_a = space2; + space_a_rank = space_a->extent.rank; + + space_b = space1; + space_b_rank = space_b->extent.rank; + } /* end else */ + HDassert(space_a_rank >= space_b_rank); + HDassert(space_b_rank > 0); /* Check for different number of elements selected */ - if(H5S_GET_SELECT_NPOINTS(space1) != H5S_GET_SELECT_NPOINTS(space2)) + if(H5S_GET_SELECT_NPOINTS(space_a) != H5S_GET_SELECT_NPOINTS(space_b)) HGOTO_DONE(FALSE) /* Check for "easy" cases before getting into generalized block iteration code */ - if(H5S_GET_SELECT_TYPE(space1)==H5S_SEL_ALL && H5S_GET_SELECT_TYPE(space2)==H5S_SEL_ALL) { - hsize_t dims1[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace #1 */ - hsize_t dims2[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace #2 */ - - if(H5S_get_simple_extent_dims(space1, dims1, NULL)<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality"); - if(H5S_get_simple_extent_dims(space2, dims2, NULL)<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality"); - - /* Check that the sizes are the same */ - for (u=0; u<space1->extent.rank; u++) - if(dims1[u]!=dims2[u]) - HGOTO_DONE(FALSE); + if((H5S_GET_SELECT_TYPE(space_a) == H5S_SEL_ALL) && (H5S_GET_SELECT_TYPE(space_b) == H5S_SEL_ALL)) { + hsize_t dims1[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace #1 */ + hsize_t dims2[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace #2 */ + int space_a_dim; /* Current dimension in dataspace A */ + int space_b_dim; /* Current dimension in dataspace B */ + + if(H5S_get_simple_extent_dims(space_a, dims1, NULL) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality") + if(H5S_get_simple_extent_dims(space_b, dims2, NULL) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality") + + space_a_dim = (int)space_a_rank - 1; + space_b_dim = (int)space_b_rank - 1; + + /* recall that space_a_rank >= space_b_rank. + * + * In the following while loop, we test to see if space_a and space_b + * have identical size in all dimensions they have in common. + */ + while(space_b_dim >= 0) { + if(dims1[space_a_dim] != dims2[space_b_dim]) + HGOTO_DONE(FALSE) + + space_a_dim--; + space_b_dim--; + } /* end while */ + + /* Since we are selecting the entire spaces, we must also verify that space_a + * has size 1 in all dimensions that it does not share with space_b. + */ + while(space_a_dim >= 0) { + if(dims1[space_a_dim] != 1) + HGOTO_DONE(FALSE) + + space_a_dim--; + } /* end while */ } /* end if */ - else if(H5S_GET_SELECT_TYPE(space1)==H5S_SEL_NONE || H5S_GET_SELECT_TYPE(space2)==H5S_SEL_NONE) { - HGOTO_DONE(TRUE); + else if((H5S_GET_SELECT_TYPE(space1) == H5S_SEL_NONE) || (H5S_GET_SELECT_TYPE(space2) == H5S_SEL_NONE)) { + HGOTO_DONE(TRUE) } /* end if */ - else if((H5S_GET_SELECT_TYPE(space1)==H5S_SEL_HYPERSLABS && space1->select.sel_info.hslab->diminfo_valid) - && (H5S_GET_SELECT_TYPE(space2)==H5S_SEL_HYPERSLABS && space2->select.sel_info.hslab->diminfo_valid)) { - - /* Check that the shapes are the same */ - for (u=0; u<space1->extent.rank; u++) { - if(space1->select.sel_info.hslab->opt_diminfo[u].stride!=space2->select.sel_info.hslab->opt_diminfo[u].stride) - HGOTO_DONE(FALSE); - if(space1->select.sel_info.hslab->opt_diminfo[u].count!=space2->select.sel_info.hslab->opt_diminfo[u].count) - HGOTO_DONE(FALSE); - if(space1->select.sel_info.hslab->opt_diminfo[u].block!=space2->select.sel_info.hslab->opt_diminfo[u].block) - HGOTO_DONE(FALSE); - } /* end for */ + else if((H5S_GET_SELECT_TYPE(space_a) == H5S_SEL_HYPERSLABS && space_a->select.sel_info.hslab->diminfo_valid) + && (H5S_GET_SELECT_TYPE(space_b) == H5S_SEL_HYPERSLABS && space_b->select.sel_info.hslab->diminfo_valid)) { + int space_a_dim; /* Current dimension in dataspace A */ + int space_b_dim; /* Current dimension in dataspace B */ + + space_a_dim = (int)space_a_rank - 1; + space_b_dim = (int)space_b_rank - 1; + + /* check that the shapes are the same in the common dimensions, and that + * block == 1 in all dimensions that appear only in space_a. + */ + while(space_b_dim >= 0) { + if(space_a->select.sel_info.hslab->opt_diminfo[space_a_dim].stride != + space_b->select.sel_info.hslab->opt_diminfo[space_b_dim].stride) + HGOTO_DONE(FALSE) + + if(space_a->select.sel_info.hslab->opt_diminfo[space_a_dim].count != + space_b->select.sel_info.hslab->opt_diminfo[space_b_dim].count) + HGOTO_DONE(FALSE) + + if(space_a->select.sel_info.hslab->opt_diminfo[space_a_dim].block != + space_b->select.sel_info.hslab->opt_diminfo[space_b_dim].block) + HGOTO_DONE(FALSE) + + space_a_dim--; + space_b_dim--; + } /* end while */ + + while(space_a_dim >= 0) { + if(space_a->select.sel_info.hslab->opt_diminfo[space_a_dim].block != 1) + HGOTO_DONE(FALSE) + + space_a_dim--; + } /* end while */ } /* end if */ /* Iterate through all the blocks in the selection */ else { - hsize_t start1[H5O_LAYOUT_NDIMS]; /* Start point of selection block in dataspace #1 */ - hsize_t start2[H5O_LAYOUT_NDIMS]; /* Start point of selection block in dataspace #2 */ - hsize_t end1[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace #1 */ - hsize_t end2[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace #2 */ - hsize_t off1[H5O_LAYOUT_NDIMS]; /* Offset of selection #1 blocks */ - hsize_t off2[H5O_LAYOUT_NDIMS]; /* Offset of selection #2 blocks */ - htri_t status1,status2; /* Status from next block checks */ - unsigned first_block=1; /* Flag to indicate the first block */ + hsize_t start_a[H5O_LAYOUT_NDIMS]; /* Start point of selection block in dataspace a */ + hsize_t start_b[H5O_LAYOUT_NDIMS]; /* Start point of selection block in dataspace b */ + hsize_t end_a[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace a */ + hsize_t end_b[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace b */ + hsize_t off_a[H5O_LAYOUT_NDIMS]; /* Offset of selection a blocks */ + hsize_t off_b[H5O_LAYOUT_NDIMS]; /* Offset of selection b blocks */ + hbool_t first_block = TRUE; /* Flag to indicate the first block */ /* Initialize iterator for each dataspace selection * Use '0' for element size instead of actual element size to indicate * that the selection iterator shouldn't be "flattened", since we * aren't actually going to be doing I/O with the iterators. */ - if(H5S_select_iter_init(&iter1, space1, (size_t)0) < 0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator"); - iter1_init = 1; - if(H5S_select_iter_init(&iter2, space2, (size_t)0) < 0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator"); - iter2_init = 1; + if(H5S_select_iter_init(&iter_a, space_a, (size_t)0) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator a") + iter_a_init = 1; + if(H5S_select_iter_init(&iter_b, space_b, (size_t)0) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator b") + iter_b_init = 1; /* Iterate over all the blocks in each selection */ while(1) { + int space_a_dim; /* Current dimension in dataspace A */ + int space_b_dim; /* Current dimension in dataspace B */ + htri_t status_a, status_b; /* Status from next block checks */ + /* Get the current block for each selection iterator */ - if(H5S_SELECT_ITER_BLOCK(&iter1,start1,end1)<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get iterator block"); - if(H5S_SELECT_ITER_BLOCK(&iter2,start2,end2)<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get iterator block"); + if(H5S_SELECT_ITER_BLOCK(&iter_a, start_a, end_a) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get iterator block a") + if(H5S_SELECT_ITER_BLOCK(&iter_b, start_b, end_b) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get iterator block b") - /* The first block only compares the sizes and sets the relative offsets for later blocks */ + space_a_dim = (int)space_a_rank - 1; + space_b_dim = (int)space_b_rank - 1; + + /* The first block only compares the sizes and sets the + * relative offsets for later blocks + */ if(first_block) { - /* If the block sizes from each selection doesn't match, get out */ - for (u=0; u<space1->extent.rank; u++) { - if((end1[u]-start1[u])!=(end2[u]-start2[u])) - HGOTO_DONE(FALSE); + /* If the block sizes in the common dimensions from + * each selection don't match, get out + */ + while(space_b_dim >= 0) { + if((end_a[space_a_dim] - start_a[space_a_dim]) != + (end_b[space_b_dim] - start_b[space_b_dim])) + HGOTO_DONE(FALSE) + + /* Set the relative locations of the selections */ + off_a[space_a_dim] = start_a[space_a_dim]; + off_b[space_b_dim] = start_b[space_b_dim]; + + space_a_dim--; + space_b_dim--; + } /* end while */ + + /* similarly, if the block size in any dimension that appears only + * in space_a is not equal to 1, get out. + */ + while(space_a_dim >= 0) { + if((end_a[space_a_dim] - start_a[space_a_dim]) != 0) + HGOTO_DONE(FALSE) /* Set the relative locations of the selections */ - off1[u]=start1[u]; - off2[u]=start2[u]; - } /* end for */ + off_a[space_a_dim] = start_a[space_a_dim]; + + space_a_dim--; + } /* end while */ /* Reset "first block" flag */ - first_block=0; + first_block = FALSE; } /* end if */ + /* Check over the blocks for each selection */ else { - /* Check over the blocks for each selection */ - for (u=0; u<space1->extent.rank; u++) { + /* for dimensions that space_a and space_b have in common: */ + while(space_b_dim >= 0) { /* Check if the blocks are in the same relative location */ - if((start1[u]-off1[u])!=(start2[u]-off2[u])) - HGOTO_DONE(FALSE); + if((start_a[space_a_dim] - off_a[space_a_dim]) != + (start_b[space_b_dim] - off_b[space_b_dim])) + HGOTO_DONE(FALSE) /* If the block sizes from each selection doesn't match, get out */ - if((end1[u]-start1[u])!=(end2[u]-start2[u])) - HGOTO_DONE(FALSE); - } /* end for */ + if((end_a[space_a_dim] - start_a[space_a_dim]) != + (end_b[space_b_dim] - start_b[space_b_dim])) + HGOTO_DONE(FALSE) + + space_a_dim--; + space_b_dim--; + } /* end while */ + + /* For dimensions that appear only in space_a: */ + while(space_a_dim >= 0) { + /* If the block size isn't 1, get out */ + if((end_a[space_a_dim] - start_a[space_a_dim]) != 0) + HGOTO_DONE(FALSE) + + space_a_dim--; + } /* end while */ } /* end else */ /* Check if we are able to advance to the next selection block */ - if((status1=H5S_SELECT_ITER_HAS_NEXT_BLOCK(&iter1))<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to check iterator block"); - if((status2=H5S_SELECT_ITER_HAS_NEXT_BLOCK(&iter2))<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to check iterator block"); + if((status_a = H5S_SELECT_ITER_HAS_NEXT_BLOCK(&iter_a)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to check iterator block a") + + if((status_b = H5S_SELECT_ITER_HAS_NEXT_BLOCK(&iter_b)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to check iterator block b") /* Did we run out of blocks at the same time? */ - if(status1==FALSE && status2==FALSE) + if((status_a == FALSE) && (status_b == FALSE)) break; - else if(status1!=status2) { - HGOTO_DONE(FALSE); - } /* end if */ + else if(status_a != status_b) + HGOTO_DONE(FALSE) else { /* Advance to next block in selection iterators */ - if(H5S_SELECT_ITER_NEXT_BLOCK(&iter1)<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to advance to next iterator block"); - if(H5S_SELECT_ITER_NEXT_BLOCK(&iter2)<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to advance to next iterator block"); + if(H5S_SELECT_ITER_NEXT_BLOCK(&iter_a) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to advance to next iterator block a") + + if(H5S_SELECT_ITER_NEXT_BLOCK(&iter_b) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to advance to next iterator block b") } /* end else */ } /* end while */ } /* end else */ } /* end else */ done: - if(iter1_init) { - if (H5S_SELECT_ITER_RELEASE(&iter1)<0) - HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator"); + if(iter_a_init) + if(H5S_SELECT_ITER_RELEASE(&iter_a) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator a") + if(iter_b_init) + if(H5S_SELECT_ITER_RELEASE(&iter_b) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator b") + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5S_select_shape_same() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S_select_construct_projection + + PURPOSE + Given a dataspace a of rank n with some selection, construct a new + dataspace b of rank m (m != n), with the selection in a being + topologically identical to that in b (as verified by + H5S_select_shape_same(). + + This function exists, as some I/O code chokes of topologically + identical selections with different ranks. At least to begin + with, we will deal with the issue by constructing projections + of the memory dataspace with ranks equaling those of the file + dataspace. + + Note that if m > n, it is possible that the starting point in the + buffer associated with the memory dataspace will have to be + adjusted to match the projected dataspace. If the buf parameter + is not NULL, the function must return an adjusted buffer base + address in *adj_buf_ptr. + + USAGE + htri_t H5S_select_construct_projection(base_space, + new_space_ptr, + new_space_rank, + buf, + adj_buf_ptr) + const H5S_t *base_space; IN: Ptr to Dataspace to project + H5S_t ** new_space_ptr; OUT: Ptr to location in which to return + the address of the projected space + int new_space_rank; IN: Rank of the projected space. + const void * buf; IN: Base address of the buffer + associated with the base space. + May be NULL. + void ** adj_buf_ptr; OUT: If buf != NULL, store the base + address of the section of buf + that is described by *new_space_ptr + in *adj_buf_ptr. + + RETURNS + Non-negative on success/Negative on failure. + + DESCRIPTION + Construct a new dataspace and associated selection which is a + projection of the supplied dataspace and associated selection into + the specified rank. Return it in *new_space_ptr. + + If buf is supplied, computes the base address of the projected + selection in buf, and stores the base address in *adj_buf_ptr. + + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + The selection in the supplied base_space has thickness 1 in all + dimensions greater than new_space_rank. Note that here we count + dimensions from the fastest changing coordinate to the slowest + changing changing coordinate. + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_select_construct_projection(const H5S_t *base_space, H5S_t **new_space_ptr, + unsigned new_space_rank, const void *buf, void const **adj_buf_ptr, hsize_t element_size) +{ + H5S_t * new_space = NULL; /* New dataspace constructed */ + hsize_t base_space_dims[H5S_MAX_RANK]; /* Current dimensions of base dataspace */ + hsize_t base_space_maxdims[H5S_MAX_RANK]; /* Maximum dimensions of base dataspace */ + int sbase_space_rank; /* Signed # of dimensions of base dataspace */ + unsigned base_space_rank; /* # of dimensions of base dataspace */ + hsize_t projected_space_element_offset = 0; /* Offset of selected element in projected buffer */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5S_select_construct_projection, FAIL) + + /* Sanity checks */ + HDassert(base_space != NULL); + HDassert((H5S_GET_EXTENT_TYPE(base_space) == H5S_SCALAR) || (H5S_GET_EXTENT_TYPE(base_space) == H5S_SIMPLE)); + HDassert(new_space_ptr != NULL); + HDassert((new_space_rank != 0) || (H5S_GET_SELECT_NPOINTS(base_space) <= 1)); + HDassert(new_space_rank <= H5S_MAX_RANK); + HDassert((buf == NULL) || (adj_buf_ptr != NULL)); + HDassert(element_size > 0 ); + + /* Get the extent info for the base dataspace */ + if((sbase_space_rank = H5S_get_simple_extent_dims(base_space, base_space_dims, base_space_maxdims)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality of base space") + base_space_rank = (unsigned)sbase_space_rank; + HDassert(base_space_rank != new_space_rank); + + /* Check if projected space is scalar */ + if(new_space_rank == 0) { + hssize_t npoints; /* Number of points selected */ + + /* Retreve the number of elements selected */ + if((npoints = (hssize_t)H5S_GET_SELECT_NPOINTS(base_space)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get number of points selected") + HDassert(npoints <= 1); + + /* Create new scalar dataspace */ + if(NULL == (new_space = H5S_create(H5S_SCALAR))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "unable to create scalar dataspace") + + /* No need to register the dataspace(i.e. get an ID) as + * we will just be discarding it shortly. + */ + + /* Selection for the new space will be either all or + * none, depending on whether the base space has 0 or + * 1 elements selected. + * + * Observe that the base space can't have more than + * one selected element, since its selection has the + * same shape as the file dataspace, and that data + * space is scalar. + */ + if(1 == npoints) { + /* Assuming that the selection in the base dataspace is not + * empty, we must compute the offset of the selected item in + * the buffer associated with the base dataspace. + * + * Since the new space rank is zero, we know that the + * the base space must have rank at least 1 -- and + * hence it is a simple dataspace. However, the + * selection, may be either point, hyperspace, or all. + * + */ + if(H5S_SELECT_PROJECT_SCALAR(base_space, &projected_space_element_offset) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "unable to project scalar selection") + } /* end if */ + else { + HDassert(0 == npoints); + + if(H5S_select_none(new_space) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't delete default selection") + } /* end else */ + } /* end if */ + else { /* projected space must be simple */ + hsize_t new_space_dims[H5S_MAX_RANK]; /* Current dimensions for new dataspace */ + hsize_t new_space_maxdims[H5S_MAX_RANK];/* Maximum dimensions for new dataspace */ + unsigned rank_diff; /* Difference in ranks */ + + /* Set up the dimensions of the new, projected dataspace. + * + * How we do this depends on whether we are projecting up into + * increased dimensions, or down into a reduced number of + * dimensions. + * + * If we are projecting up (the first half of the following + * if statement), we copy the dimensions of the base data + * space into the fastest changing dimensions of the new + * projected dataspace, and set the remaining dimensions to + * one. + * + * If we are projecting down (the second half of the following + * if statement), we just copy the dimensions with the most + * quickly changing dimensions into the dims for the projected + * data set. + * + * This works, because H5S_select_shape_same() will return + * true on selections of different rank iff: + * + * 1) the selection in the lower rank dataspace matches that + * in the dimensions with the fastest changing indicies in + * the larger rank dataspace, and + * + * 2) the selection has thickness 1 in all ranks that appear + * only in the higher rank dataspace (i.e. those with + * more slowly changing indicies). + */ + if(new_space_rank > base_space_rank) { + hsize_t tmp_dim_size = 1; /* Temporary dimension value, for filling arrays */ + + /* we must copy the dimensions of the base space into + * the fastest changing dimensions of the new space, + * and set the remaining dimensions to 1 + */ + rank_diff = new_space_rank - base_space_rank; + H5V_array_fill(new_space_dims, &tmp_dim_size, sizeof(tmp_dim_size), rank_diff); + H5V_array_fill(new_space_maxdims, &tmp_dim_size, sizeof(tmp_dim_size), rank_diff); + HDmemcpy(&new_space_dims[rank_diff], base_space_dims, sizeof(new_space_dims[0]) * base_space_rank); + HDmemcpy(&new_space_maxdims[rank_diff], base_space_maxdims, sizeof(new_space_maxdims[0]) * base_space_rank); + } /* end if */ + else { /* new_space_rank < base_space_rank */ + /* we must copy the fastest changing dimension of the + * base space into the dimensions of the new space. + */ + rank_diff = base_space_rank - new_space_rank; + HDmemcpy(new_space_dims, &base_space_dims[rank_diff], sizeof(new_space_dims[0]) * new_space_rank); + HDmemcpy(new_space_maxdims, &base_space_maxdims[rank_diff], sizeof(new_space_maxdims[0]) * new_space_rank); + } /* end else */ + + /* now have the new space rank and dimensions set up -- + * so we can create the new simple dataspace. + */ + if(NULL == (new_space = H5S_create_simple(new_space_rank, new_space_dims, new_space_maxdims))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create simple dataspace") + + /* No need to register the dataspace(i.e. get an ID) as + * we will just be discarding it shortly. + */ + + /* If we get this far, we have successfully created the projected + * dataspace. We must now project the selection in the base + * dataspace into the projected dataspace. + */ + if(H5S_SELECT_PROJECT_SIMPLE(base_space, new_space, &projected_space_element_offset) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "unable to project simple selection") + + /* If we get this far, we have created the new dataspace, and projected + * the selection in the base dataspace into the new dataspace. + * + * If the base dataspace is simple, check to see if the + * offset_changed flag on the base selection has been set -- if so, + * project the offset into the new dataspace and set the + * offset_changed flag. + */ + if(H5S_GET_EXTENT_TYPE(base_space) == H5S_SIMPLE && base_space->select.offset_changed) { + if(new_space_rank > base_space_rank) { + HDmemset(new_space->select.offset, 0, sizeof(new_space->select.offset[0]) * rank_diff); + HDmemcpy(&new_space->select.offset[rank_diff], base_space->select.offset, sizeof(new_space->select.offset[0]) * base_space_rank); + } /* end if */ + else + HDmemcpy(new_space->select.offset, &base_space->select.offset[rank_diff], sizeof(new_space->select.offset[0]) * new_space_rank); + + /* Propagate the offset changed flag into the new dataspace. */ + new_space->select.offset_changed = TRUE; + } /* end if */ + } /* end else */ + + /* If we have done the projection correctly, the following assertion + * should hold. + */ + HDassert(TRUE == H5S_select_shape_same(base_space, new_space)); + + /* load the address of the new space into *new_space_ptr */ + *new_space_ptr = new_space; + + /* now adjust the buffer if required */ + if(buf != NULL) { + if(new_space_rank < base_space_rank) { + /* a bit of pointer magic here: + * + * Since we can't do pointer arithmetic on void pointers, we first + * cast buf to a pointer to byte -- i.e. uint8_t. + * + * We then multiply the projected space element offset we + * calculated earlier by the supplied element size, add this + * value to the type cast buf pointer, cast the result back + * to a pointer to void, and assign the result to *adj_buf_ptr. + */ + *adj_buf_ptr = (const void *)(((const uint8_t *)buf) + + ((size_t)(projected_space_element_offset * element_size))); + } /* end if */ + else + /* No adjustment necessary */ + *adj_buf_ptr = buf; } /* end if */ - if(iter2_init) { - if (H5S_SELECT_ITER_RELEASE(&iter2)<0) - HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator"); + +done: + /* Cleanup on error */ + if(ret_value < 0) { + if(new_space && H5S_close(new_space) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace") } /* end if */ FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_select_shape_same() */ +} /* H5S_select_construct_projection() */ /*-------------------------------------------------------------------------- @@ -1536,7 +2006,7 @@ H5S_select_fill(const void *fill, size_t fill_size, const H5S_t *space, void *_b /* Initialize iterator */ if(H5S_select_iter_init(&iter, space, fill_size) < 0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator") + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator") iter_init = 1; /* Selection iteration info has been initialized */ /* Get the number of elements in selection */ @@ -1556,7 +2026,7 @@ H5S_select_fill(const void *fill, size_t fill_size, const H5S_t *space, void *_b /* Get the sequences of bytes */ if(H5S_SELECT_GET_SEQ_LIST(space, 0, &iter, (size_t)H5D_IO_VECTOR_SIZE, max_elem, &nseq, &nelem, off, len) < 0) - HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed") + HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed") /* Loop over sequences */ for(curr_seq = 0; curr_seq < nseq; curr_seq++) { diff --git a/src/H5public.h b/src/H5public.h index e07c4e3..0ff480f 100644 --- a/src/H5public.h +++ b/src/H5public.h @@ -71,10 +71,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 73 /* For tweaks, bug-fixes, or development */ +#define H5_VERS_RELEASE 75 /* For tweaks, bug-fixes, or development */ #define H5_VERS_SUBRELEASE "FA_a4" /* For pre-releases like snap0 */ /* Empty string for real releases. */ -#define H5_VERS_INFO "HDF5 library version: 1.9.73-FA_a4" /* Full version string */ +#define H5_VERS_INFO "HDF5 library version: 1.9.75-FA_a4" /* Full version string */ #define H5check() H5check_version(H5_VERS_MAJOR,H5_VERS_MINOR, \ H5_VERS_RELEASE) diff --git a/src/Makefile.in b/src/Makefile.in index 0e3d148..14a17bf 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -222,6 +222,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -247,6 +248,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ @@ -445,7 +447,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 = 63 +LT_VERS_REVISION = 65 LT_VERS_AGE = 0 H5detect_CFLAGS = -g $(AM_CFLAGS) diff --git a/src/libhdf5.settings.in b/src/libhdf5.settings.in index ba233e8..2e8bc52 100644 --- a/src/libhdf5.settings.in +++ b/src/libhdf5.settings.in @@ -37,12 +37,12 @@ Compiling Options: Languages: ---------- Fortran: @HDF_FORTRAN@ -@BUILD_FORTRAN_CONDITIONAL_TRUE@ Fortran Compiler: @FC@ +@BUILD_FORTRAN_CONDITIONAL_TRUE@ Fortran Compiler: @FC_VERSION@ @BUILD_FORTRAN_CONDITIONAL_TRUE@ Fortran Flags: @FCFLAGS@ @BUILD_FORTRAN_CONDITIONAL_TRUE@ H5 Fortran Flags: @H5_FCFLAGS@ @BUILD_FORTRAN_CONDITIONAL_TRUE@ AM Fortran Flags: @AM_FCFLAGS@ C++: @HDF_CXX@ -@BUILD_CXX_CONDITIONAL_TRUE@ C++ Compiler: @CXX@ +@BUILD_CXX_CONDITIONAL_TRUE@ C++ Compiler: @CXX_VERSION@ @BUILD_CXX_CONDITIONAL_TRUE@ C++ Flags: @CXXFLAGS@ @BUILD_CXX_CONDITIONAL_TRUE@ H5 C++ Flags: @H5_CXXFLAGS@ @BUILD_CXX_CONDITIONAL_TRUE@ AM C++ Flags: @AM_CXXFLAGS@ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ae5786a..772466a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -301,6 +301,7 @@ IF (CREATE_GENERATORS) space_overflow gen_filespace gen_specmetaread + gen_sizes_lheap ) FOREACH (gen ${H5_GENERATORS}) diff --git a/test/Makefile.am b/test/Makefile.am index e556c91..6ca7227 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -64,7 +64,8 @@ check_PROGRAMS=$(TEST_PROG) error_test err_compat tcheck_version testmeta # so do not appear in this list. 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_nullspace gen_udlinks space_overflow gen_filespace gen_specmetaread \ + gen_sizes_lheap if BUILD_ALL_CONDITIONAL noinst_PROGRAMS=$(BUILD_ALL_PROGS) diff --git a/test/Makefile.in b/test/Makefile.in index 2a0b13d..65bdaec 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -100,7 +100,7 @@ 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_specmetaread$(EXEEXT) gen_sizes_lheap$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) app_ref_SOURCES = app_ref.c app_ref_OBJECTS = app_ref.$(OBJEXT) @@ -262,6 +262,10 @@ gen_nullspace_SOURCES = gen_nullspace.c gen_nullspace_OBJECTS = gen_nullspace.$(OBJEXT) gen_nullspace_LDADD = $(LDADD) gen_nullspace_DEPENDENCIES = libh5test.la $(LIBHDF5) +gen_sizes_lheap_SOURCES = gen_sizes_lheap.c +gen_sizes_lheap_OBJECTS = gen_sizes_lheap.$(OBJEXT) +gen_sizes_lheap_LDADD = $(LDADD) +gen_sizes_lheap_DEPENDENCIES = libh5test.la $(LIBHDF5) gen_specmetaread_SOURCES = gen_specmetaread.c gen_specmetaread_OBJECTS = gen_specmetaread.$(OBJEXT) gen_specmetaread_LDADD = $(LDADD) @@ -405,13 +409,13 @@ SOURCES = $(libh5test_la_SOURCES) app_ref.c big.c bittests.c btree2.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_specmetaread.c \ - gen_udlinks.c getname.c gheap.c hyperslab.c istore.c lheap.c \ - links.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_generator.c swmr_reader.c swmr_writer.c tcheck_version.c \ - $(testhdf5_SOURCES) testmeta.c $(ttsafe_SOURCES) unlink.c \ - vfd.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 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_generator.c swmr_reader.c \ + swmr_writer.c tcheck_version.c $(testhdf5_SOURCES) testmeta.c \ + $(ttsafe_SOURCES) unlink.c vfd.c DIST_SOURCES = $(libh5test_la_SOURCES) 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 \ @@ -420,13 +424,13 @@ DIST_SOURCES = $(libh5test_la_SOURCES) app_ref.c big.c bittests.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_specmetaread.c \ - gen_udlinks.c getname.c gheap.c hyperslab.c istore.c lheap.c \ - links.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_generator.c swmr_reader.c swmr_writer.c tcheck_version.c \ - $(testhdf5_SOURCES) testmeta.c $(ttsafe_SOURCES) unlink.c \ - vfd.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 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_generator.c swmr_reader.c \ + swmr_writer.c tcheck_version.c $(testhdf5_SOURCES) testmeta.c \ + $(ttsafe_SOURCES) unlink.c vfd.c ETAGS = etags CTAGS = ctags am__tty_colors = \ @@ -470,6 +474,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -495,6 +500,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ @@ -749,7 +755,8 @@ TEST_PROG = testhdf5 lheap ohdr stab gheap cache cache_api cache_tagging \ # so do not appear in this list. 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_nullspace gen_udlinks space_overflow gen_filespace gen_specmetaread \ + gen_sizes_lheap # The libh5test library provides common support code for the tests. @@ -1025,6 +1032,9 @@ gen_noencoder$(EXEEXT): $(gen_noencoder_OBJECTS) $(gen_noencoder_DEPENDENCIES) gen_nullspace$(EXEEXT): $(gen_nullspace_OBJECTS) $(gen_nullspace_DEPENDENCIES) @rm -f gen_nullspace$(EXEEXT) $(LINK) $(gen_nullspace_OBJECTS) $(gen_nullspace_LDADD) $(LIBS) +gen_sizes_lheap$(EXEEXT): $(gen_sizes_lheap_OBJECTS) $(gen_sizes_lheap_DEPENDENCIES) + @rm -f gen_sizes_lheap$(EXEEXT) + $(LINK) $(gen_sizes_lheap_OBJECTS) $(gen_sizes_lheap_LDADD) $(LIBS) gen_specmetaread$(EXEEXT): $(gen_specmetaread_OBJECTS) $(gen_specmetaread_DEPENDENCIES) @rm -f gen_specmetaread$(EXEEXT) $(LINK) $(gen_specmetaread_OBJECTS) $(gen_specmetaread_LDADD) $(LIBS) @@ -1157,6 +1167,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen_new_super.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen_noencoder.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen_nullspace.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen_sizes_lheap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen_specmetaread.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen_udlinks.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getname.Po@am__quote@ diff --git a/test/cache_api.c b/test/cache_api.c index 8fd2912..c6e27c6 100644 --- a/test/cache_api.c +++ b/test/cache_api.c @@ -65,11 +65,8 @@ static void check_file_mdc_api_errs(void); * Programmer: John Mainzer * 4/12/04 * - * Modifications: - * *------------------------------------------------------------------------- */ - static void check_fapl_mdc_api_calls(void) { @@ -113,7 +110,9 @@ check_fapl_mdc_api_calls(void) /* int epochs_before_eviction = */ 4, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.05, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }; H5AC_cache_config_t scratch; H5C_auto_size_ctl_t default_auto_size_ctl; @@ -560,7 +559,9 @@ check_file_mdc_api_calls(void) /* int epochs_before_eviction = */ 4, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.05, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }; H5AC_cache_config_t mod_config_2 = { @@ -593,7 +594,9 @@ check_file_mdc_api_calls(void) /* int epochs_before_eviction = */ 4, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.05, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }; H5AC_cache_config_t mod_config_3 = { @@ -626,7 +629,9 @@ check_file_mdc_api_calls(void) /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ FALSE, /* double empty_reserve = */ 0.05, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }; H5AC_cache_config_t mod_config_4 = { @@ -660,7 +665,9 @@ check_file_mdc_api_calls(void) /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }; TESTING("MDC/FILE related API calls"); @@ -915,7 +922,9 @@ mdc_api_call_smoke_check(int express_test) /* int epochs_before_eviction = */ 2, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.05, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }; H5AC_cache_config_t mod_config_2 = { @@ -948,7 +957,9 @@ mdc_api_call_smoke_check(int express_test) /* int epochs_before_eviction = */ 2, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.05, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }; H5AC_cache_config_t mod_config_3 = { @@ -981,7 +992,9 @@ mdc_api_call_smoke_check(int express_test) /* int epochs_before_eviction = */ 2, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.05, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }; TESTING("MDC API smoke check"); @@ -1514,7 +1527,7 @@ mdc_api_call_smoke_check(int express_test) * used to test error rejection in the MDC related API calls. */ -#define NUM_INVALID_CONFIGS 41 +#define NUM_INVALID_CONFIGS 42 H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = { @@ -1549,7 +1562,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 1 -- bad rpt_fcn_enabled */ @@ -1582,7 +1597,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 2 -- bad open_trace_file */ @@ -1615,7 +1632,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 3 -- bad close_trace_file */ @@ -1648,7 +1667,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 4 -- open_trace_file == TRUE and empty trace_file_name */ @@ -1681,7 +1702,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 5 -- bad set_initial_size */ @@ -1714,7 +1737,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 6 -- max_size too big */ @@ -1747,7 +1772,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 7 -- min_size too small */ @@ -1780,7 +1807,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 8 -- min_size > max_size */ @@ -1813,7 +1842,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 9 -- initial size out of range (too big) */ @@ -1846,7 +1877,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 10 -- initial_size out of range (too small) */ @@ -1879,7 +1912,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 11 -- min_clean_fraction too big */ @@ -1912,7 +1947,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 12 -- min_clean_fraction too small */ @@ -1945,7 +1982,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 13 -- epoch_length too small */ @@ -1978,7 +2017,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 14 -- epoch_length too big */ @@ -2011,7 +2052,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 15 -- invalid incr_mode */ @@ -2044,7 +2087,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 16 -- lower_hr_threshold too small */ @@ -2077,7 +2122,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 17 -- lower_hr_threshold too big */ @@ -2110,7 +2157,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 18 -- increment too small */ @@ -2143,7 +2192,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 19 -- bad apply_max_increment */ @@ -2176,7 +2227,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 20 -- invalid flash_incr_mode */ @@ -2209,7 +2262,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 21 -- flash_multiple too small */ @@ -2242,7 +2297,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 22 -- flash_multiple too big */ @@ -2275,7 +2332,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 23 -- flash_threshold too small */ @@ -2308,7 +2367,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 24 -- flash_threshold too big */ @@ -2341,7 +2402,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 25 -- bad decr_mode */ @@ -2374,7 +2437,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 26 -- upper_hr_threshold too big */ @@ -2407,7 +2472,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 27 -- decrement too small */ @@ -2440,7 +2507,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 28 -- decrement too big */ @@ -2473,7 +2542,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 29 -- epochs_before_eviction too small */ @@ -2506,7 +2577,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 0, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 30 -- epochs_before_eviction too big */ @@ -2539,7 +2612,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ H5C__MAX_EPOCH_MARKERS + 1, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 31 -- invalid apply_empty_reserve */ @@ -2572,7 +2647,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ 2, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 32 -- empty_reserve too small */ @@ -2605,7 +2682,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ -0.0000000001, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 33 -- empty_reserve too big */ @@ -2638,7 +2717,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 1.00000000001, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 34 -- upper_hr_threshold too small */ @@ -2671,7 +2752,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 35 -- upper_hr_threshold too big */ @@ -2704,7 +2787,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 36 -- upper_hr_threshold <= lower_hr_threshold */ @@ -2737,7 +2822,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 37 -- dirty_bytes_threshold too small */ @@ -2770,7 +2857,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (H5C__MIN_MAX_CACHE_SIZE / 2) - 1 + /* int dirty_bytes_threshold = */ (H5C__MIN_MAX_CACHE_SIZE / 2) - 1, + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 38 -- dirty_bytes_threshold too big */ @@ -2803,7 +2892,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (H5C__MAX_MAX_CACHE_SIZE / 4) + 1 + /* int dirty_bytes_threshold = */ (H5C__MAX_MAX_CACHE_SIZE / 4) + 1, + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 39 -- attempt to disable evictions when auto incr enabled */ @@ -2836,7 +2927,9 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY }, { /* 40 -- attempt to disable evictions when auto decr enabled */ @@ -2869,7 +2962,43 @@ H5AC_cache_config_t invalid_configs[NUM_INVALID_CONFIGS] = /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, - /* int dirty_bytes_threshold = */ (256 * 1024) + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ + H5AC__DEFAULT_METADATA_WRITE_STRATEGY + }, + { + /* 41 -- unknown metadata write strategy */ + /* int version = */ H5C__CURR_AUTO_SIZE_CTL_VER, + /* hbool_t rpt_fcn_enabled = */ FALSE, + /* hbool_t open_trace_file = */ FALSE, + /* hbool_t close_trace_file = */ FALSE, + /* char trace_file_name[] = */ "", + /* hbool_t evictions_enabled = */ TRUE, + /* hbool_t set_initial_size = */ TRUE, + /* size_t initial_size = */ (1 * 1024 * 1024), + /* double min_clean_fraction = */ 0.25, + /* size_t max_size = */ (16 * 1024 * 1024), + /* size_t min_size = */ ( 1 * 1024 * 1024), + /* long int epoch_length = */ 50000, + /* enum H5C_cache_incr_mode incr_mode = */ H5C_incr__threshold, + /* double lower_hr_threshold = */ 0.9, + /* double increment = */ 2.0, + /* hbool_t apply_max_increment = */ TRUE, + /* size_t max_increment = */ (4 * 1024 * 1024), + /* enum H5C_cache_flash_incr_mode */ + /* flash_incr_mode = */ H5C_flash_incr__off, + /* double flash_multiple = */ 2.0, + /* double flash_threshold = */ 0.5, + /* enum H5C_cache_decr_mode decr_mode = */ H5C_decr__age_out_with_threshold, + /* double upper_hr_threshold = */ 0.999, + /* double decrement = */ 0.9, + /* hbool_t apply_max_decrement = */ TRUE, + /* size_t max_decrement = */ (1 * 1024 * 1024), + /* int epochs_before_eviction = */ 3, + /* hbool_t apply_empty_reserve = */ TRUE, + /* double empty_reserve = */ 0.1, + /* int dirty_bytes_threshold = */ (256 * 1024), + /* int metadata_write_strategy = */ -1 } }; diff --git a/test/cache_common.h b/test/cache_common.h index f493239..d7e7f1a 100644 --- a/test/cache_common.h +++ b/test/cache_common.h @@ -412,38 +412,40 @@ if ( ( (cache_ptr) == NULL ) || \ /* Macros used in H5AC level tests */ -#define CACHE_CONFIGS_EQUAL(a, b, cmp_set_init, cmp_init_size) \ - ( ( (a).version == (b).version ) && \ - ( (a).rpt_fcn_enabled == (b).rpt_fcn_enabled ) && \ - ( (a).open_trace_file == (b).open_trace_file ) && \ - ( (a).close_trace_file == (b).close_trace_file ) && \ - ( ( (a).open_trace_file == FALSE ) || \ - ( strcmp((a).trace_file_name, (b).trace_file_name) == 0 ) ) && \ - ( (a).evictions_enabled == (b).evictions_enabled ) && \ - ( ( ! cmp_set_init ) || \ - ( (a).set_initial_size == (b).set_initial_size ) ) && \ - ( ( ! cmp_init_size ) || \ - ( (a).initial_size == (b).initial_size ) ) && \ - ( (a).min_clean_fraction == (b).min_clean_fraction ) && \ - ( (a).max_size == (b).max_size ) && \ - ( (a).min_size == (b).min_size ) && \ - ( (a).epoch_length == (b).epoch_length ) && \ - ( (a).incr_mode == (b).incr_mode ) && \ - ( (a).lower_hr_threshold == (b).lower_hr_threshold ) && \ - ( (a).increment == (b).increment ) && \ - ( (a).apply_max_increment == (b).apply_max_increment ) && \ - ( (a).max_increment == (b).max_increment ) && \ - ( (a).flash_incr_mode == (b).flash_incr_mode ) && \ - ( (a).flash_multiple == (b).flash_multiple ) && \ - ( (a).flash_threshold == (b).flash_threshold ) && \ - ( (a).decr_mode == (b).decr_mode ) && \ - ( (a).upper_hr_threshold == (b).upper_hr_threshold ) && \ - ( (a).decrement == (b).decrement ) && \ - ( (a).apply_max_decrement == (b).apply_max_decrement ) && \ - ( (a).max_decrement == (b).max_decrement ) && \ - ( (a).epochs_before_eviction == (b).epochs_before_eviction ) && \ - ( (a).apply_empty_reserve == (b).apply_empty_reserve ) && \ - ( (a).empty_reserve == (b).empty_reserve ) ) +#define CACHE_CONFIGS_EQUAL(a, b, cmp_set_init, cmp_init_size) \ + ( ( (a).version == (b).version ) && \ + ( (a).rpt_fcn_enabled == (b).rpt_fcn_enabled ) && \ + ( (a).open_trace_file == (b).open_trace_file ) && \ + ( (a).close_trace_file == (b).close_trace_file ) && \ + ( ( (a).open_trace_file == FALSE ) || \ + ( strcmp((a).trace_file_name, (b).trace_file_name) == 0 ) ) && \ + ( (a).evictions_enabled == (b).evictions_enabled ) && \ + ( ( ! cmp_set_init ) || \ + ( (a).set_initial_size == (b).set_initial_size ) ) && \ + ( ( ! cmp_init_size ) || \ + ( (a).initial_size == (b).initial_size ) ) && \ + ( (a).min_clean_fraction == (b).min_clean_fraction ) && \ + ( (a).max_size == (b).max_size ) && \ + ( (a).min_size == (b).min_size ) && \ + ( (a).epoch_length == (b).epoch_length ) && \ + ( (a).incr_mode == (b).incr_mode ) && \ + ( (a).lower_hr_threshold == (b).lower_hr_threshold ) && \ + ( (a).increment == (b).increment ) && \ + ( (a).apply_max_increment == (b).apply_max_increment ) && \ + ( (a).max_increment == (b).max_increment ) && \ + ( (a).flash_incr_mode == (b).flash_incr_mode ) && \ + ( (a).flash_multiple == (b).flash_multiple ) && \ + ( (a).flash_threshold == (b).flash_threshold ) && \ + ( (a).decr_mode == (b).decr_mode ) && \ + ( (a).upper_hr_threshold == (b).upper_hr_threshold ) && \ + ( (a).decrement == (b).decrement ) && \ + ( (a).apply_max_decrement == (b).apply_max_decrement ) && \ + ( (a).max_decrement == (b).max_decrement ) && \ + ( (a).epochs_before_eviction == (b).epochs_before_eviction ) && \ + ( (a).apply_empty_reserve == (b).apply_empty_reserve ) && \ + ( (a).empty_reserve == (b).empty_reserve ) && \ + ( (a).dirty_bytes_threshold == (b).dirty_bytes_threshold ) && \ + ( (a).metadata_write_strategy == (b).metadata_write_strategy ) ) #define XLATE_EXT_TO_INT_MDC_CONFIG(i, e) \ { \ diff --git a/test/gen_sizes_lheap.c b/test/gen_sizes_lheap.c new file mode 100644 index 0000000..de7e261 --- /dev/null +++ b/test/gen_sizes_lheap.c @@ -0,0 +1,82 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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: Neil Fortner <nfortne2@hdfgroup.org> + * Thursday, July 15, 2010 + * + * Purpose: Creates a file with non-default sizes of lengths and addresses. + * This is used to make sure that the local heap code is able to + * handle this case correctly, even when the heap prefix and data + * are contiguous. + */ + +#include "hdf5.h" + +#define TESTFILE "tsizeslheap.h5" + + +/*------------------------------------------------------------------------- + * Function: main + * + * Purpose: + * + * Return: Success: + * + * Failure: + * + * Programmer: Neil Fortner + * Thursday, July 15, 2010 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +int +main(void) +{ + hid_t file, space, dset, fcpl; + + /* Create the FCPL */ + fcpl = H5Pcreate(H5P_FILE_CREATE); + if(fcpl < 0) + printf("fcpl < 0!\n"); + + /* Set sizeof_addr and sizeof_size to be 4 */ + if(H5Pset_sizes(fcpl, 4, 4) < 0) + printf("H5Pset_sizes < 0!\n"); + + /* Create the file */ + file = H5Fcreate(TESTFILE, H5F_ACC_TRUNC, fcpl, H5P_DEFAULT); + if(file < 0) + printf("file < 0!\n"); + + /* Create the dataspace (for dataset) */ + space = H5Screate(H5S_SCALAR); + if(space < 0) + printf("space < 0!\n"); + + /* Create the dataset with compound array fields */ + dset = H5Dcreate2(file, "Dataset1", H5T_NATIVE_INT, space, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + if(dset < 0) + printf("dset < 0!\n"); + + H5Dclose(dset); + H5Sclose(space); + H5Fclose(file); + H5Pclose(fcpl); + + return 0; +} diff --git a/test/h5test.h b/test/h5test.h index f984751..722d850 100644 --- a/test/h5test.h +++ b/test/h5test.h @@ -118,7 +118,7 @@ extern MPI_Info h5_io_info_g; /* MPI INFO object for IO */ /* * Alarm definitions to wait up (terminate) a test that runs too long. */ -#define alarm_seconds 1200 /* default is 20 minutes */ +#define alarm_seconds 1800 /* default is 30 minutes */ #define ALARM_ON HDalarm(alarm_seconds) #define ALARM_OFF HDalarm(0) /* set alarms to N seconds if N > 0, else use default alarm_seconds. */ diff --git a/test/lheap.c b/test/lheap.c index 1d98fc4..9f78a15 100644 --- a/test/lheap.c +++ b/test/lheap.c @@ -20,6 +20,7 @@ * Purpose: Test local heaps used by symbol tables (groups). */ #include "h5test.h" +#include "H5srcdir.h" #include "H5ACprivate.h" #include "H5HLprivate.h" #include "H5Iprivate.h" @@ -29,6 +30,8 @@ const char *FILENAME[] = { NULL }; +#define TESTFILE "tsizeslheap.h5" + #define NOBJS 40 @@ -170,6 +173,29 @@ main(void) if (H5Fclose(file)<0) goto error; PASSED(); + + /* Check opening existing file non-default sizes of lengths and addresses */ + TESTING("opening pre-created file with non-default sizes"); + { + const char *testfile = H5_get_srcdir_filename(TESTFILE); /* Corrected test file name */ + hid_t dset = -1; + + file = H5Fopen(testfile, H5F_ACC_RDONLY, H5P_DEFAULT); + if(file >= 0){ + if((dset = H5Dopen2(file, "/Dataset1", H5P_DEFAULT)) < 0) + TEST_ERROR + if(H5Dclose(dset) < 0) TEST_ERROR + if(H5Fclose(file) < 0) TEST_ERROR + } + else { + H5_FAILED(); + printf("***cannot open the pre-created non-default sizes test file (%s)\n", + testfile); + goto error; + } /* end else */ + } + PASSED(); + puts("All local heap tests passed."); h5_cleanup(FILENAME, fapl); diff --git a/test/testframe.c b/test/testframe.c index f0d94d8..201f569 100644 --- a/test/testframe.c +++ b/test/testframe.c @@ -26,7 +26,7 @@ /* * Definitions for the testing structure. */ -#define MAXNUMOFTESTS 45 +#define MAXNUMOFTESTS 50 #define MAXTESTNAME 16 #define MAXTESTDESC 64 diff --git a/test/tselect.c b/test/tselect.c index b8c59d8..89cd9e5 100644 --- a/test/tselect.c +++ b/test/tselect.c @@ -159,6 +159,9 @@ #define SPACERE5_DIM3 12 #define SPACERE5_DIM4 8 +/* #defines for shape same / different rank tests */ +#define SS_DR_MAX_RANK 5 + /* Location comparison function */ @@ -1585,6 +1588,2031 @@ test_select_hyper_contig3(hid_t dset_type, hid_t xfer_plist) HDfree(rbuf); } /* test_select_hyper_contig3() */ + +/**************************************************************** +** +** verify_select_hyper_contig_dr__run_test(): Verify data from +** test_select_hyper_contig_dr__run_test() +** +****************************************************************/ +static void +verify_select_hyper_contig_dr__run_test(const uint16_t *cube_buf, + size_t cube_size, unsigned edge_size, unsigned cube_rank) +{ + const uint16_t *cube_ptr; /* Pointer into the cube buffer */ + uint16_t expected_value; /* Expected value in dataset */ + unsigned i, j, k, l, m; /* Local index variables */ + size_t s; /* Local index variable */ + hbool_t mis_match; /* Flag to indicate mis-match in expected value */ + + HDassert(cube_buf); + HDassert(cube_size > 0); + + expected_value = 0; + mis_match = FALSE; + cube_ptr = cube_buf; + s = 0; + i = 0; + do { + j = 0; + do { + k = 0; + do { + l = 0; + do { + m = 0; + do { + /* Sanity check */ + HDassert(s < cube_size); + + /* Check for correct value */ + if(*cube_ptr != expected_value) + mis_match = TRUE; + + /* Advance to next element */ + cube_ptr++; + expected_value++; + s++; + m++; + } while((cube_rank > 0) && (m < edge_size)); + l++; + } while((cube_rank > 1) && (l < edge_size)); + k++; + } while((cube_rank > 2) && (k < edge_size)); + j++; + } while((cube_rank > 3) && (j < edge_size)); + i++; + } while((cube_rank > 4) && (i < edge_size)); + if(mis_match) + TestErrPrintf("Initial cube data don't match! Line = %d\n", __LINE__); +} /* verify_select_hyper_contig_dr__run_test() */ + + +/**************************************************************** +** +** test_select_hyper_contig_dr__run_test(): Test H5S (dataspace) +** selection code with contiguous source and target having +** different ranks but the same shape. We have already +** tested H5S_shape_same in isolation, so now we try to do +** I/O. +** +****************************************************************/ +static void +test_select_hyper_contig_dr__run_test(int test_num, const uint16_t *cube_buf, + const uint16_t *zero_buf, unsigned edge_size, unsigned chunk_edge_size, + unsigned small_rank, unsigned large_rank, hid_t dset_type, hid_t xfer_plist) +{ + hbool_t mis_match; /* Flag indicating a value read in wasn't what was expected */ + hid_t fapl; /* File access property list */ + hid_t fid1; /* File ID */ + hid_t small_cube_sid; /* Dataspace ID for small cube in memory & file */ + hid_t mem_large_cube_sid; /* Dataspace ID for large cube in memory */ + hid_t file_large_cube_sid; /* Dataspace ID for large cube in file */ + hid_t small_cube_dcpl_id = H5P_DEFAULT; /* DCPL for small cube dataset */ + hid_t large_cube_dcpl_id = H5P_DEFAULT; /* DCPL for large cube dataset */ + hid_t small_cube_dataset; /* Dataset ID */ + hid_t large_cube_dataset; /* Dataset ID */ + size_t start_index; /* Offset within buffer to begin inspecting */ + size_t stop_index; /* Offset within buffer to end inspecting */ + uint16_t expected_value; /* Expected value in dataset */ + uint16_t * small_cube_buf_1; /* Buffer for small cube data */ + uint16_t * large_cube_buf_1; /* Buffer for large cube data */ + uint16_t * ptr_1; /* Temporary pointer into cube data */ + hsize_t dims[SS_DR_MAX_RANK]; /* Dataspace dimensions */ + hsize_t start[SS_DR_MAX_RANK]; /* Shared hyperslab start offset */ + hsize_t stride[SS_DR_MAX_RANK]; /* Shared hyperslab stride */ + hsize_t count[SS_DR_MAX_RANK]; /* Shared hyperslab count */ + hsize_t block[SS_DR_MAX_RANK]; /* Shared hyperslab block size */ + hsize_t * start_ptr; /* Actual hyperslab start offset */ + hsize_t * stride_ptr; /* Actual hyperslab stride */ + hsize_t * count_ptr; /* Actual hyperslab count */ + hsize_t * block_ptr; /* Actual hyperslab block size */ + size_t small_cube_size; /* Number of elements in small cube */ + size_t large_cube_size; /* Number of elements in large cube */ + unsigned u, v, w, x; /* Local index variables */ + size_t s; /* Local index variable */ + htri_t check; /* Shape comparison return value */ + herr_t ret; /* Generic return value */ + + MESSAGE(7, ("\tn-cube slice through m-cube I/O test %d.\n", test_num)); + MESSAGE(7, ("\tranks = %u/%u, edge_size = %u, chunk_edge_size = %u.\n", small_rank, large_rank, edge_size, chunk_edge_size)); + + HDassert(edge_size >= 6); + HDassert(edge_size >= chunk_edge_size); + HDassert((chunk_edge_size == 0) || (chunk_edge_size >= 3)); + HDassert(small_rank > 0); + HDassert(small_rank < large_rank); + HDassert(large_rank <= SS_DR_MAX_RANK); + + /* Compute cube sizes */ + small_cube_size = large_cube_size = (size_t)1; + for(u = 0; u < large_rank; u++) { + if(u < small_rank) + small_cube_size *= (size_t)edge_size; + + large_cube_size *= (size_t)edge_size; + } /* end for */ + + HDassert(large_cube_size < (size_t)UINT_MAX); + + /* set up the start, stride, count, and block pointers */ + start_ptr = &(start[SS_DR_MAX_RANK - large_rank]); + stride_ptr = &(stride[SS_DR_MAX_RANK - large_rank]); + count_ptr = &(count[SS_DR_MAX_RANK - large_rank]); + block_ptr = &(block[SS_DR_MAX_RANK - large_rank]); + + /* Allocate buffers */ + small_cube_buf_1 = (uint16_t *)HDcalloc(sizeof(uint16_t), small_cube_size); + CHECK(small_cube_buf_1, NULL, "HDcalloc"); + large_cube_buf_1 = (uint16_t *)HDcalloc(sizeof(uint16_t), large_cube_size); + CHECK(large_cube_buf_1, NULL, "HDcalloc"); + + /* Create a dataset transfer property list */ + fapl = H5Pcreate(H5P_FILE_ACCESS); + CHECK(fapl, FAIL, "H5Pcreate"); + + /* Use the 'core' VFD for this test */ + ret = H5Pset_fapl_core(fapl, (size_t)(1024 * 1024), FALSE); + CHECK(ret, FAIL, "H5Pset_fapl_core"); + + /* Create file */ + fid1 = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, fapl); + CHECK(fid1, FAIL, "H5Fcreate"); + + /* Close file access property list */ + ret = H5Pclose(fapl); + CHECK(ret, FAIL, "H5Pclose"); + + /* setup dims: */ + dims[0] = dims[1] = dims[2] = dims[3] = dims[4] = (hsize_t)edge_size; + + /* Create small cube dataspaces */ + small_cube_sid = H5Screate_simple((int)small_rank, dims, NULL); + CHECK(small_cube_sid, FAIL, "H5Screate_simple"); + + /* Create large cube dataspace */ + mem_large_cube_sid = H5Screate_simple((int)large_rank, dims, NULL); + CHECK(mem_large_cube_sid, FAIL, "H5Screate_simple"); + file_large_cube_sid = H5Screate_simple((int)large_rank, dims, NULL); + CHECK(file_large_cube_sid, FAIL, "H5Screate_simple"); + + /* if chunk edge size is greater than zero, set up the small and + * large data set creation property lists to specify chunked + * datasets. + */ + if(chunk_edge_size > 0) { + hsize_t chunk_dims[SS_DR_MAX_RANK]; /* Chunk dimensions */ + + chunk_dims[0] = chunk_dims[1] = + chunk_dims[2] = chunk_dims[3] = chunk_dims[4] = (hsize_t)chunk_edge_size; + + small_cube_dcpl_id = H5Pcreate(H5P_DATASET_CREATE); + CHECK(small_cube_dcpl_id, FAIL, "H5Pcreate"); + + ret = H5Pset_layout(small_cube_dcpl_id, H5D_CHUNKED); + CHECK(ret, FAIL, "H5Pset_layout"); + + ret = H5Pset_chunk(small_cube_dcpl_id, (int)small_rank, chunk_dims); + CHECK(ret, FAIL, "H5Pset_chunk"); + + + large_cube_dcpl_id = H5Pcreate(H5P_DATASET_CREATE); + CHECK(large_cube_dcpl_id, FAIL, "H5Pcreate"); + + ret = H5Pset_layout(large_cube_dcpl_id, H5D_CHUNKED); + CHECK(ret, FAIL, "H5Pset_layout"); + + ret = H5Pset_chunk(large_cube_dcpl_id, (int)large_rank, chunk_dims); + CHECK(ret, FAIL, "H5Pset_chunk"); + } /* end if */ + + /* create the small cube dataset */ + small_cube_dataset = H5Dcreate2(fid1, "small_cube_dataset", dset_type, + small_cube_sid, H5P_DEFAULT, small_cube_dcpl_id, H5P_DEFAULT); + CHECK(small_cube_dataset, FAIL, "H5Dcreate2"); + + /* Close non-default small dataset DCPL */ + if(small_cube_dcpl_id != H5P_DEFAULT) { + ret = H5Pclose(small_cube_dcpl_id); + CHECK(ret, FAIL, "H5Pclose"); + } /* end if */ + + /* create the large cube dataset */ + large_cube_dataset = H5Dcreate2(fid1, "large_cube_dataset", dset_type, + file_large_cube_sid, H5P_DEFAULT, large_cube_dcpl_id, H5P_DEFAULT); + CHECK(large_cube_dataset, FAIL, "H5Dcreate2"); + + /* Close non-default large dataset DCPL */ + if(large_cube_dcpl_id != H5P_DEFAULT) { + ret = H5Pclose(large_cube_dcpl_id); + CHECK(ret, FAIL, "H5Pclose"); + } /* end if */ + + + /* write initial data to the on disk datasets */ + ret = H5Dwrite(small_cube_dataset, H5T_NATIVE_UINT16, small_cube_sid, + small_cube_sid, xfer_plist, cube_buf); + CHECK(ret, FAIL, "H5Dwrite"); + + ret = H5Dwrite(large_cube_dataset, H5T_NATIVE_UINT16, mem_large_cube_sid, + file_large_cube_sid, xfer_plist, cube_buf); + CHECK(ret, FAIL, "H5Dwrite"); + + /* read initial data from disk and verify that it is as expected. */ + ret = H5Dread(small_cube_dataset, H5T_NATIVE_UINT16, small_cube_sid, + small_cube_sid, xfer_plist, small_cube_buf_1); + CHECK(ret, FAIL, "H5Dread"); + + /* Check that the data is valid */ + verify_select_hyper_contig_dr__run_test(small_cube_buf_1, small_cube_size, + edge_size, small_rank); + + ret = H5Dread(large_cube_dataset, H5T_NATIVE_UINT16, mem_large_cube_sid, + file_large_cube_sid, xfer_plist, large_cube_buf_1); + CHECK(ret, FAIL, "H5Dread"); + + /* Check that the data is valid */ + verify_select_hyper_contig_dr__run_test(large_cube_buf_1, large_cube_size, + edge_size, large_rank); + + + /* first, verify that we can read from disk correctly using selections + * of different rank that H5S_select_shape_same() views as being of the + * same shape. + * + * Start by reading small_rank-D slice from the on disk large cube, and + * verifying that the data read is correct. Verify that H5S_select_shape_same() + * returns true on the memory and file selections. + */ + + + /* set up start, stride, count, and block -- note that we will + * change start[] so as to read slices of the large cube. + */ + for(u = 0; u < SS_DR_MAX_RANK; u++) { + start[u] = 0; + stride[u] = 1; + count[u] = 1; + if((SS_DR_MAX_RANK - u) > small_rank) + block[u] = 1; + else + block[u] = (hsize_t)edge_size; + } /* end for */ + + u = 0; + do { + v = 0; + do { + w = 0; + do { + x = 0; + do { + /* we know that small_rank >= 1 and that large_rank > small_rank + * by the assertions at the head of this function. Thus no + * need for another inner loop. + */ + start[0] = (hsize_t)u; + start[1] = (hsize_t)v; + start[2] = (hsize_t)w; + start[3] = (hsize_t)x; + start[4] = (hsize_t)0; + + ret = H5Sselect_hyperslab(file_large_cube_sid, + H5S_SELECT_SET, + start_ptr, + stride_ptr, + count_ptr, + block_ptr); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* verify that H5S_select_shape_same() reports the two + * selections as having the same shape. + */ + check = H5S_select_shape_same_test(small_cube_sid, + file_large_cube_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + /* Read selection from disk */ + ret = H5Dread(large_cube_dataset, + H5T_NATIVE_UINT16, + small_cube_sid, + file_large_cube_sid, + xfer_plist, + small_cube_buf_1); + CHECK(ret, FAIL, "H5Dread"); + + /* verify that expected data is retrieved */ + mis_match = FALSE; + ptr_1 = small_cube_buf_1; + expected_value = (uint16_t)((u * edge_size * edge_size * edge_size * edge_size) + + (v * edge_size * edge_size * edge_size) + + (w * edge_size * edge_size) + + (x * edge_size)); + for(s = 0; s < small_cube_size; s++ ) { + if(*ptr_1 != expected_value ) + mis_match = TRUE; + ptr_1++; + expected_value++; + } /* end for */ + if(mis_match) + TestErrPrintf("small cube read from largecube has bad data! Line=%d\n",__LINE__); + + x++; + } while((large_rank >= 2) && (small_rank <= 1) && (x < edge_size)); + w++; + } while((large_rank >= 3) && (small_rank <= 2) && (w < edge_size)); + v++; + } while((large_rank >= 4) && (small_rank <= 3) && (v < edge_size)); + u++; + } while((large_rank >= 5) && (small_rank <= 4) && (u < edge_size)); + + + /* similarly, read the on disk small cube into slices through the in memory + * large cube, and verify that the correct data (and only the correct data) + * is read. + */ + + /* zero out the in-memory large cube */ + HDmemset(large_cube_buf_1, 0, large_cube_size * sizeof(uint16_t)); + + u = 0; + do { + v = 0; + do { + w = 0; + do { + x = 0; + do { + /* we know that small_rank >= 1 and that large_rank > small_rank + * by the assertions at the head of this function. Thus no + * need for another inner loop. + */ + start[0] = (hsize_t)u; + start[1] = (hsize_t)v; + start[2] = (hsize_t)w; + start[3] = (hsize_t)x; + start[4] = (hsize_t)0; + + ret = H5Sselect_hyperslab(mem_large_cube_sid, + H5S_SELECT_SET, + start_ptr, + stride_ptr, + count_ptr, + block_ptr); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + + /* verify that H5S_select_shape_same() reports the two + * selections as having the same shape. + */ + check = H5S_select_shape_same_test(small_cube_sid, + mem_large_cube_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + + /* Read selection from disk */ + ret = H5Dread(small_cube_dataset, + H5T_NATIVE_UINT16, + mem_large_cube_sid, + small_cube_sid, + xfer_plist, + large_cube_buf_1); + CHECK(ret, FAIL, "H5Dread"); + + + /* verify that the expected data and only the + * expected data was read. + */ + start_index = (u * edge_size * edge_size * edge_size * edge_size) + + (v * edge_size * edge_size * edge_size) + + (w * edge_size * edge_size) + + (x * edge_size); + stop_index = start_index + small_cube_size - 1; + + HDassert(start_index < stop_index); + HDassert(stop_index <= large_cube_size); + + mis_match = FALSE; + ptr_1 = large_cube_buf_1; + expected_value = 0; + for(s = 0; s < start_index; s++) { + if(*ptr_1 != 0) + mis_match = TRUE; + ptr_1++; + } /* end for */ + for(; s <= stop_index; s++) { + if(*ptr_1 != expected_value) + mis_match = TRUE; + expected_value++; + ptr_1++; + } /* end for */ + for(; s < large_cube_size; s++) { + if(*ptr_1 != 0) + mis_match = TRUE; + ptr_1++; + } /* end for */ + if(mis_match) + TestErrPrintf("large cube read from small cube has bad data! Line=%u\n", __LINE__); + + /* Zero out the buffer for the next pass */ + HDmemset(large_cube_buf_1 + start_index, 0, small_cube_size * sizeof(uint16_t)); + + x++; + } while((large_rank >= 2) && (small_rank <= 1) && (x < edge_size)); + w++; + } while((large_rank >= 3) && (small_rank <= 2) && (w < edge_size)); + v++; + } while((large_rank >= 4) && (small_rank <= 3) && (v < edge_size)); + u++; + } while((large_rank >= 5) && (small_rank <= 4) && (u < edge_size)); + + + /* now we go in the opposite direction, verifying that we can write + * from memory to file using selections of different rank that + * H5S_select_shape_same() views as being of the same shape. + * + * Start by writing small_rank D slices from the in memory large cube, to + * the the on disk small cube dataset. After each write, read the small + * cube dataset back from disk, and verify that it contains the expected + * data. Verify that H5S_select_shape_same() returns true on the + * memory and file selections. + */ + + u = 0; + do { + v = 0; + do { + w = 0; + do { + x = 0; + do { + /* we know that small_rank >= 1 and that large_rank > small_rank + * by the assertions at the head of this function. Thus no + * need for another inner loop. + */ + + /* zero out the on disk small cube */ + ret = H5Dwrite(small_cube_dataset, + H5T_NATIVE_UINT16, + small_cube_sid, + small_cube_sid, + xfer_plist, + zero_buf); + CHECK(ret, FAIL, "H5Dwrite"); + + /* select the portion of the in memory large cube from which we + * are going to write data. + */ + start[0] = (hsize_t)u; + start[1] = (hsize_t)v; + start[2] = (hsize_t)w; + start[3] = (hsize_t)x; + start[4] = (hsize_t)0; + + ret = H5Sselect_hyperslab(mem_large_cube_sid, + H5S_SELECT_SET, + start_ptr, + stride_ptr, + count_ptr, + block_ptr); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + + /* verify that H5S_select_shape_same() reports the in + * memory slice through the cube selection and the + * on disk full small cube selections as having the same shape. + */ + check = H5S_select_shape_same_test(small_cube_sid, + mem_large_cube_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + + /* write the slice from the in memory large cube to the on disk small cube */ + ret = H5Dwrite(small_cube_dataset, + H5T_NATIVE_UINT16, + mem_large_cube_sid, + small_cube_sid, + xfer_plist, + cube_buf); + CHECK(ret, FAIL, "H5Dwrite"); + + + /* read the on disk small cube into memory */ + ret = H5Dread(small_cube_dataset, + H5T_NATIVE_UINT16, + small_cube_sid, + small_cube_sid, + xfer_plist, + small_cube_buf_1); + CHECK(ret, FAIL, "H5Dread"); + + + /* verify that expected data is retrieved */ + mis_match = FALSE; + ptr_1 = small_cube_buf_1; + expected_value = (uint16_t)((u * edge_size * edge_size * edge_size * edge_size) + + (v * edge_size * edge_size * edge_size) + + (w * edge_size * edge_size) + + (x * edge_size)); + for(s = 0; s < small_cube_size; s++) { + if(*ptr_1 != expected_value) + mis_match = TRUE; + expected_value++; + ptr_1++; + } /* end for */ + if(mis_match ) + TestErrPrintf("small cube data don't match! Line=%d\n",__LINE__); + + x++; + } while((large_rank >= 2) && (small_rank <= 1) && (x < edge_size)); + w++; + } while((large_rank >= 3) && (small_rank <= 2) && (w < edge_size)); + v++; + } while((large_rank >= 4) && (small_rank <= 3) && (v < edge_size)); + u++; + } while((large_rank >= 5) && (small_rank <= 4) && (u < edge_size)); + + + /* Now write the contents of the in memory small cube to slices of + * the on disk cube. After each write, read the on disk cube + * into memeory, and verify that it contains the expected + * data. Verify that H5S_select_shape_same() returns true on + * the memory and file selections. + */ + + /* select the entire memory and file cube dataspaces */ + ret = H5Sselect_all(mem_large_cube_sid); + CHECK(ret, FAIL, "H5Sselect_all"); + + ret = H5Sselect_all(file_large_cube_sid); + CHECK(ret, FAIL, "H5Sselect_all"); + + u = 0; + do { + v = 0; + do { + w = 0; + do { + x = 0; + do { + /* we know that small_rank >= 1 and that large_rank > small_rank + * by the assertions at the head of this function. Thus no + * need for another inner loop. + */ + + /* zero out the on disk cube */ + ret = H5Dwrite(large_cube_dataset, + H5T_NATIVE_USHORT, + mem_large_cube_sid, + file_large_cube_sid, + xfer_plist, + zero_buf); + CHECK(ret, FAIL, "H5Dwrite"); + + + /* select the portion of the in memory large cube to which we + * are going to write data. + */ + start[0] = (hsize_t)u; + start[1] = (hsize_t)v; + start[2] = (hsize_t)w; + start[3] = (hsize_t)x; + start[4] = (hsize_t)0; + + ret = H5Sselect_hyperslab(file_large_cube_sid, + H5S_SELECT_SET, + start_ptr, + stride_ptr, + count_ptr, + block_ptr); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + + /* verify that H5S_select_shape_same() reports the in + * memory full selection of the small cube and the + * on disk slice through the large cube selection + * as having the same shape. + */ + check = H5S_select_shape_same_test(small_cube_sid, + file_large_cube_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + + /* write the cube from memory to the target slice of the disk cube */ + ret = H5Dwrite(large_cube_dataset, + H5T_NATIVE_UINT16, + small_cube_sid, + file_large_cube_sid, + xfer_plist, + cube_buf); + CHECK(ret, FAIL, "H5Dwrite"); + + + /* read the on disk cube into memory */ + ret = H5Sselect_all(file_large_cube_sid); + CHECK(ret, FAIL, "H5Sselect_all"); + + ret = H5Dread(large_cube_dataset, + H5T_NATIVE_UINT16, + mem_large_cube_sid, + file_large_cube_sid, + xfer_plist, + large_cube_buf_1); + CHECK(ret, FAIL, "H5Dread"); + + + /* verify that the expected data and only the + * expected data was read. + */ + start_index = (u * edge_size * edge_size * edge_size * edge_size) + + (v * edge_size * edge_size * edge_size) + + (w * edge_size * edge_size) + + (x * edge_size); + stop_index = start_index + small_cube_size - 1; + + HDassert(start_index < stop_index); + HDassert(stop_index <= large_cube_size); + + mis_match = FALSE; + ptr_1 = large_cube_buf_1; + expected_value = 0; + for(s = 0; s < start_index; s++) { + if(*ptr_1 != 0) + mis_match = TRUE; + ptr_1++; + } /* end for */ + for(; s <= stop_index; s++) { + if(*ptr_1 != expected_value) + mis_match = TRUE; + expected_value++; + ptr_1++; + } /* end for */ + for(; s < large_cube_size; s++) { + if(*ptr_1 != 0) + mis_match = TRUE; + ptr_1++; + } /* end for */ + if(mis_match) + TestErrPrintf("large cube written from small cube has bad data! Line=%d\n", __LINE__); + + x++; + } while((large_rank >= 2) && (small_rank <= 1) && (x < edge_size)); + w++; + } while((large_rank >= 3) && (small_rank <= 2) && (w < edge_size)); + v++; + } while((large_rank >= 4) && (small_rank <= 3) && (v < edge_size)); + u++; + } while((large_rank >= 5) && (small_rank <= 4) && (u < edge_size)); + + /* Close memory dataspaces */ + ret = H5Sclose(small_cube_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(mem_large_cube_sid); + CHECK(ret, FAIL, "H5Sclose"); + + + /* Close disk dataspace */ + ret = H5Sclose(file_large_cube_sid); + CHECK(ret, FAIL, "H5Sclose"); + + + /* Close Datasets */ + ret = H5Dclose(small_cube_dataset); + CHECK(ret, FAIL, "H5Dclose"); + + ret = H5Dclose(large_cube_dataset); + CHECK(ret, FAIL, "H5Dclose"); + + /* Close file */ + ret = H5Fclose(fid1); + CHECK(ret, FAIL, "H5Fclose"); + + /* Free memory buffers */ + HDfree(small_cube_buf_1); + HDfree(large_cube_buf_1); + +} /* test_select_hyper_contig_dr__run_test() */ + + +/**************************************************************** +** +** test_select_hyper_contig_dr(): Test H5S (dataspace) +** selection code with contiguous source and target having +** different ranks but the same shape. We have already +** tested H5S_shape_same in isolation, so now we try to do +** I/O. +** +****************************************************************/ +static void +test_select_hyper_contig_dr(hid_t dset_type, hid_t xfer_plist) +{ + int test_num = 0; + unsigned chunk_edge_size; /* Size of chunk's dataspace dimensions */ + unsigned edge_size = 6; /* Size of dataset's dataspace dimensions */ + unsigned small_rank; /* Current rank of small dataset */ + unsigned large_rank; /* Current rank of large dataset */ + uint16_t *cube_buf; /* Buffer for writing cube data */ + uint16_t *zero_buf; /* Buffer for writing zeroed cube data */ + uint16_t *cube_ptr; /* Temporary pointer into cube data */ + unsigned max_rank = 5; /* Max. rank to use */ + size_t max_cube_size; /* Max. number of elements in largest cube */ + size_t s; /* Local index variable */ + unsigned u; /* Local index variable */ + + /* Output message about test being performed */ + MESSAGE(5, ("Testing Contiguous Hyperslabs With Different Rank I/O Functionality\n")); + + /* Compute max. cube size */ + max_cube_size = (size_t)1; + for(u = 0; u < max_rank; u++) + max_cube_size *= (size_t)edge_size; + + /* Allocate cube buffer for writing values */ + cube_buf = (uint16_t *)HDmalloc(sizeof(uint16_t) * max_cube_size); + CHECK(cube_buf, NULL, "HDmalloc"); + + /* Initialize the cube buffer */ + cube_ptr = cube_buf; + for(s = 0; s < max_cube_size; s++) + *cube_ptr++ = (uint16_t)s; + + /* Allocate cube buffer for zeroing values on disk */ + zero_buf = (uint16_t *)HDcalloc(sizeof(uint16_t), max_cube_size); + CHECK(zero_buf, NULL, "HDcalloc"); + + for(large_rank = 1; large_rank <= max_rank; large_rank++) { + for(small_rank = 1; small_rank < large_rank; small_rank++) { + chunk_edge_size = 0; + test_select_hyper_contig_dr__run_test(test_num, cube_buf, zero_buf, + edge_size, chunk_edge_size, small_rank, large_rank, + dset_type, xfer_plist); + test_num++; + + chunk_edge_size = 3; + test_select_hyper_contig_dr__run_test(test_num, cube_buf, zero_buf, + edge_size, chunk_edge_size, small_rank, large_rank, + dset_type, xfer_plist); + test_num++; + } /* for loop on small rank */ + } /* for loop on large rank */ + + HDfree(cube_buf); + HDfree(zero_buf); + +} /* test_select_hyper_contig_dr() */ + + +/**************************************************************** +** +** test_select_hyper_checker_board_dr__select_checker_board(): +** Given an n-cube data space with each edge of length +** edge_size, and a checker_edge_size either select a checker +** board selection of the entire cube(if sel_rank == n), +** or select a checker board selection of a +** sel_rank dimensional slice through n-cube parallel to the +** sel_rank fastest changing indices, with origin (in the +** higher indices) as indicated by the start array. +** +** Note that this function, like all its relatives, is +** hard coded to presume a maximum n-cube rank of 5. +** While this maximum is declared as a constant, increasing +** it will require extensive coding in addition to changing +** the value of the constant. +** +** JRM -- 9/9/09 +** +****************************************************************/ +static void +test_select_hyper_checker_board_dr__select_checker_board(hid_t tgt_n_cube_sid, + unsigned tgt_n_cube_rank, unsigned edge_size, unsigned checker_edge_size, + unsigned sel_rank, hsize_t sel_start[]) +{ + hbool_t first_selection = TRUE; + unsigned n_cube_offset; + unsigned sel_offset; + hsize_t base_count; + hsize_t offset_count; + hsize_t start[SS_DR_MAX_RANK]; /* Offset of hyperslab selection */ + hsize_t stride[SS_DR_MAX_RANK]; /* Stride of hyperslab selection */ + hsize_t count[SS_DR_MAX_RANK]; /* Count of hyperslab selection */ + hsize_t block[SS_DR_MAX_RANK]; /* Block size of hyperslab selection */ + unsigned i, j, k, l, m; /* Local index variable */ + unsigned u; /* Local index variables */ + herr_t ret; /* Generic return value */ + + HDassert(edge_size >= 6); + HDassert(0 < checker_edge_size); + HDassert(checker_edge_size <= edge_size); + HDassert(0 < sel_rank); + HDassert(sel_rank <= tgt_n_cube_rank); + HDassert(tgt_n_cube_rank <= SS_DR_MAX_RANK); + + sel_offset = SS_DR_MAX_RANK - sel_rank; + n_cube_offset = SS_DR_MAX_RANK - tgt_n_cube_rank; + HDassert(n_cube_offset <= sel_offset); + + /* First, compute the base count (which assumes start == 0 + * for the associated offset) and offset_count (which + * assumes start == checker_edge_size for the associated + * offset). + */ + base_count = edge_size / (checker_edge_size * 2); + if((edge_size % (checker_edge_size * 2)) > 0) + base_count++; + + offset_count = (edge_size - checker_edge_size) / (checker_edge_size * 2); + if(((edge_size - checker_edge_size) % (checker_edge_size * 2)) > 0) + offset_count++; + + /* Now set up the stride and block arrays, and portions of the start + * and count arrays that will not be altered during the selection of + * the checker board. + */ + u = 0; + while(u < n_cube_offset) { + /* these values should never be used */ + start[u] = 0; + stride[u] = 0; + count[u] = 0; + block[u] = 0; + + u++; + } /* end while */ + + while(u < sel_offset) { + start[u] = sel_start[u]; + stride[u] = 2 * edge_size; + count[u] = 1; + block[u] = 1; + + u++; + } /* end while */ + + while(u < SS_DR_MAX_RANK) { + stride[u] = 2 * checker_edge_size; + block[u] = checker_edge_size; + + u++; + } /* end while */ + + i = 0; + do { + if(0 >= sel_offset) { + if(i == 0) { + start[0] = 0; + count[0] = base_count; + } /* end if */ + else { + start[0] = checker_edge_size; + count[0] = offset_count; + } /* end else */ + } /* end if */ + + j = 0; + do { + if(1 >= sel_offset) { + if(j == 0 ) { + start[1] = 0; + count[1] = base_count; + } /* end if */ + else { + start[1] = checker_edge_size; + count[1] = offset_count; + } /* end else */ + } /* end if */ + + k = 0; + do { + if(2 >= sel_offset) { + if(k == 0) { + start[2] = 0; + count[2] = base_count; + } /* end if */ + else { + start[2] = checker_edge_size; + count[2] = offset_count; + } /* end else */ + } /* end if */ + + l = 0; + do { + if(3 >= sel_offset) { + if(l == 0) { + start[3] = 0; + count[3] = base_count; + } /* end if */ + else { + start[3] = checker_edge_size; + count[3] = offset_count; + } /* end else */ + } /* end if */ + + m = 0; + do { + if(4 >= sel_offset) { + if(m == 0) { + start[4] = 0; + count[4] = base_count; + } /* end if */ + else { + start[4] = checker_edge_size; + count[4] = offset_count; + } /* end else */ + } /* end if */ + + if(((i + j + k + l + m) % 2) == 0) { + if(first_selection) { + first_selection = FALSE; + + ret = H5Sselect_hyperslab(tgt_n_cube_sid, + H5S_SELECT_SET, + &(start[n_cube_offset]), + &(stride[n_cube_offset]), + &(count[n_cube_offset]), + &(block[n_cube_offset])); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + } /* end if */ + else { + ret = H5Sselect_hyperslab(tgt_n_cube_sid, + H5S_SELECT_OR, + &(start[n_cube_offset]), + &(stride[n_cube_offset]), + &(count[n_cube_offset]), + &(block[n_cube_offset])); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + } /* end else */ + } /* end if */ + + m++; + } while((m <= 1) && (4 >= sel_offset)); + l++; + } while((l <= 1) && (3 >= sel_offset)); + k++; + } while((k <= 1) && (2 >= sel_offset)); + j++; + } while((j <= 1) && (1 >= sel_offset)); + i++; + } while((i <= 1) && (0 >= sel_offset)); + + /* Wierdness alert: + * + * Some how, it seems that selections can extend beyond the + * boundaries of the target data space -- hence the following + * code to manually clip the selection back to the data space + * proper. + */ + for(u = 0; u < SS_DR_MAX_RANK; u++) { + start[u] = 0; + stride[u] = edge_size; + count[u] = 1; + block[u] = edge_size; + } /* end for */ + + ret = H5Sselect_hyperslab(tgt_n_cube_sid, H5S_SELECT_AND, start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); +} /* test_select_hyper_checker_board_dr__select_checker_board() */ + + +/**************************************************************** +** +** test_select_hyper_checker_board_dr__verify_data(): +** +** Examine the supplied buffer to see if it contains the +** expected data. Return TRUE if it does, and FALSE +** otherwise. +** +** The supplied buffer is presumed to contain the results +** of read or writing a checkerboard selection of an +** n-cube, or a checkerboard selection of an m (1 <= m < n) +** dimensional slice through an n-cube parallel to the +** fastest changing indices. +** +** It is further presumed that the buffer was zeroed before +** the read, and that the n-cube was initialize with the +** natural numbers listed in order from the origin along +** the fastest changing axis. +** +** Thus for a 10x10x10 3-cube, the value stored in location +** (x, y, z) (assuming that z is the fastest changing index +** and x the slowest) is assumed to be: +** +** (10 * 10 * x) + (10 * y) + z +** +** Thus, if the buffer contains the result of reading a +** checker board selection of a 10x10x10 3-cube, location +** (x, y, z) will contain zero if it is not in a checker, +** and 100x + 10y + z if (x, y, z) is in a checker. +** +** If the buffer contains the result of reading a 3 +** dimensional slice (parallel to the three fastest changing +** indices) through an n cube (n > 3), then the expected +** values in the buffer will be the same, save that we will +** add a constant determined by the origin of the 3-cube +** in the n-cube. +** +** Finally, the function presumes that the first element +** of the buffer resides either at the origin of either +** a selected or an unselected checker. +** +****************************************************************/ +static hbool_t +test_select_hyper_checker_board_dr__verify_data(uint16_t * buf_ptr, + unsigned rank, unsigned edge_size, unsigned checker_edge_size, + uint16_t first_expected_val, hbool_t buf_starts_in_checker) +{ + hbool_t good_data = TRUE; + hbool_t in_checker; + hbool_t start_in_checker[5]; + uint16_t expected_value; + uint16_t * val_ptr; + unsigned i, j, k, l, m; /* to track position in n-cube */ + unsigned v, w, x, y, z; /* to track position in checker */ + const unsigned test_max_rank = 5; /* code changes needed if this is increased */ + + HDassert(buf_ptr != NULL); + HDassert(0 < rank); + HDassert(rank <= test_max_rank); + HDassert(edge_size >= 6); + HDassert(0 < checker_edge_size); + HDassert(checker_edge_size <= edge_size); + HDassert(test_max_rank <= SS_DR_MAX_RANK); + + val_ptr = buf_ptr; + expected_value = first_expected_val; + + i = 0; + v = 0; + start_in_checker[0] = buf_starts_in_checker; + do { + if(v >= checker_edge_size) { + start_in_checker[0] = !start_in_checker[0]; + v = 0; + } /* end if */ + + j = 0; + w = 0; + start_in_checker[1] = start_in_checker[0]; + do { + if(w >= checker_edge_size) { + start_in_checker[1] = !start_in_checker[1]; + w = 0; + } /* end if */ + + k = 0; + x = 0; + start_in_checker[2] = start_in_checker[1]; + do { + if(x >= checker_edge_size) { + start_in_checker[2] = !start_in_checker[2]; + x = 0; + } /* end if */ + + l = 0; + y = 0; + start_in_checker[3] = start_in_checker[2]; + do { + if(y >= checker_edge_size) { + start_in_checker[3] = ! start_in_checker[3]; + y = 0; + } /* end if */ + + m = 0; + z = 0; + in_checker = start_in_checker[3]; + do { + if(z >= checker_edge_size) { + in_checker = ! in_checker; + z = 0; + } /* end if */ + + if(in_checker) { + if(*val_ptr != expected_value) + good_data = FALSE; + } /* end if */ + else { + if(*val_ptr != 0) + good_data = FALSE; + } /* end else */ + + val_ptr++; + expected_value++; + + m++; + z++; + } while((rank >= (test_max_rank - 4)) && (m < edge_size)); + l++; + y++; + } while((rank >= (test_max_rank - 3)) && (l < edge_size)); + k++; + x++; + } while((rank >= (test_max_rank - 2)) && (k < edge_size)); + j++; + w++; + } while((rank >= (test_max_rank - 1)) && (j < edge_size)); + i++; + v++; + } while((rank >= test_max_rank) && (i < edge_size)); + + return(good_data); +} /* test_select_hyper_checker_board_dr__verify_data() */ + + +/**************************************************************** +** +** test_select_hyper_checker_board_dr__run_test(): Test H5S +** (dataspace) selection code with checker board source and +** target selections having different ranks but the same +** shape. We have already tested H5S_shape_same in +** isolation, so now we try to do I/O. +** +****************************************************************/ +static void +test_select_hyper_checker_board_dr__run_test(int test_num, const uint16_t *cube_buf, + const uint16_t *zero_buf, unsigned edge_size, unsigned checker_edge_size, + unsigned chunk_edge_size, unsigned small_rank, unsigned large_rank, + hid_t dset_type, hid_t xfer_plist) +{ + hbool_t data_ok; + hbool_t start_in_checker[5]; + hid_t fapl; /* File access property list */ + hid_t fid; /* HDF5 File IDs */ + hid_t full_small_cube_sid; /* Dataspace for small cube w/all selection */ + hid_t mem_small_cube_sid; + hid_t file_small_cube_sid; + hid_t full_large_cube_sid; /* Dataspace for large cube w/all selection */ + hid_t mem_large_cube_sid; + hid_t file_large_cube_sid; + hid_t small_cube_dcpl_id = H5P_DEFAULT; /* DCPL for small cube dataset */ + hid_t large_cube_dcpl_id = H5P_DEFAULT; /* DCPL for large cube dataset */ + hid_t small_cube_dataset; /* Dataset ID */ + hid_t large_cube_dataset; /* Dataset ID */ + unsigned small_rank_offset; /* Rank offset of slice */ + const unsigned test_max_rank = 5; /* must update code if this changes */ + size_t start_index; /* Offset within buffer to begin inspecting */ + size_t stop_index; /* Offset within buffer to end inspecting */ + uint16_t expected_value; + uint16_t * small_cube_buf_1; + uint16_t * large_cube_buf_1; + uint16_t * ptr_1; + size_t small_cube_size; /* Number of elements in small cube */ + size_t large_cube_size; /* Number of elements in large cube */ + hsize_t dims[SS_DR_MAX_RANK]; + hsize_t chunk_dims[SS_DR_MAX_RANK]; + hsize_t sel_start[SS_DR_MAX_RANK]; + unsigned u, v, w, x; /* Local index variables */ + size_t s; /* Local index variable */ + htri_t check; /* Shape comparison return value */ + herr_t ret; /* Generic return value */ + + MESSAGE(7, ("\tn-cube slice through m-cube I/O test %d.\n", test_num)); + MESSAGE(7, ("\tranks = %d/%d, edge_size = %d, checker_edge_size = %d, chunk_edge_size = %d.\n", small_rank, large_rank, edge_size, checker_edge_size, chunk_edge_size)); + + HDassert(edge_size >= 6); + HDassert(checker_edge_size > 0); + HDassert(checker_edge_size <= edge_size); + HDassert(edge_size >= chunk_edge_size); + HDassert((chunk_edge_size == 0) || (chunk_edge_size >= 3)); + HDassert(small_rank > 0); + HDassert(small_rank < large_rank); + HDassert(large_rank <= test_max_rank); + HDassert(test_max_rank <= SS_DR_MAX_RANK); + + /* Compute cube sizes */ + small_cube_size = large_cube_size = (size_t)1; + for(u = 0; u < large_rank; u++) { + if(u < small_rank) + small_cube_size *= (size_t)edge_size; + + large_cube_size *= (size_t)edge_size; + } /* end for */ + HDassert(large_cube_size < (size_t)(UINT_MAX)); + + small_rank_offset = test_max_rank - small_rank; + HDassert(small_rank_offset >= 1); + + /* also, at present, we use 16 bit values in this test -- + * hence the following assertion. Delete it if we convert + * to 32 bit values. + */ + HDassert(large_cube_size < (size_t)(UINT16_MAX)); + + + /* Allocate & initialize buffers */ + small_cube_buf_1 = (uint16_t *)HDcalloc(sizeof(uint16_t), small_cube_size); + CHECK(small_cube_buf_1, NULL, "HDcalloc"); + large_cube_buf_1 = (uint16_t *)HDcalloc(sizeof(uint16_t), large_cube_size); + CHECK(large_cube_buf_1, NULL, "HDcalloc"); + + + /* Create a dataset transfer property list */ + fapl = H5Pcreate(H5P_FILE_ACCESS); + CHECK(fapl, FAIL, "H5Pcreate"); + + /* Use the 'core' VFD for this test */ + ret = H5Pset_fapl_core(fapl, (size_t)(1024 * 1024), FALSE); + CHECK(ret, FAIL, "H5Pset_fapl_core"); + + /* Create file */ + fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, fapl); + CHECK(fid, FAIL, "H5Fcreate"); + + /* Close file access property list */ + ret = H5Pclose(fapl); + CHECK(ret, FAIL, "H5Pclose"); + + + /* setup dims: */ + dims[0] = dims[1] = dims[2] = dims[3] = dims[4] = edge_size; + + + /* Create small cube dataspaces */ + full_small_cube_sid = H5Screate_simple((int)small_rank, dims, NULL); + CHECK(full_small_cube_sid, FAIL, "H5Screate_simple"); + + mem_small_cube_sid = H5Screate_simple((int)small_rank, dims, NULL); + CHECK(mem_small_cube_sid, FAIL, "H5Screate_simple"); + + file_small_cube_sid = H5Screate_simple((int)small_rank, dims, NULL); + CHECK(file_small_cube_sid, FAIL, "H5Screate_simple"); + + + /* Create large cube dataspace */ + full_large_cube_sid = H5Screate_simple((int)large_rank, dims, NULL); + CHECK(full_large_cube_sid, FAIL, "H5Screate_simple"); + + mem_large_cube_sid = H5Screate_simple((int)large_rank, dims, NULL); + CHECK(mem_large_cube_sid, FAIL, "H5Screate_simple"); + + file_large_cube_sid = H5Screate_simple((int)large_rank, dims, NULL); + CHECK(file_large_cube_sid, FAIL, "H5Screate_simple"); + + + /* if chunk edge size is greater than zero, set up the small and + * large data set creation property lists to specify chunked + * datasets. + */ + if(chunk_edge_size > 0) { + chunk_dims[0] = chunk_dims[1] = + chunk_dims[2] = chunk_dims[3] = chunk_dims[4] = chunk_edge_size; + + small_cube_dcpl_id = H5Pcreate(H5P_DATASET_CREATE); + CHECK(small_cube_dcpl_id, FAIL, "H5Pcreate"); + + ret = H5Pset_layout(small_cube_dcpl_id, H5D_CHUNKED); + CHECK(ret, FAIL, "H5Pset_layout"); + + ret = H5Pset_chunk(small_cube_dcpl_id, (int)small_rank, chunk_dims); + CHECK(ret, FAIL, "H5Pset_chunk"); + + + large_cube_dcpl_id = H5Pcreate(H5P_DATASET_CREATE); + CHECK(large_cube_dcpl_id, FAIL, "H5Pcreate"); + + ret = H5Pset_layout(large_cube_dcpl_id, H5D_CHUNKED); + CHECK(ret, FAIL, "H5Pset_layout"); + + ret = H5Pset_chunk(large_cube_dcpl_id, (int)large_rank, chunk_dims); + CHECK(ret, FAIL, "H5Pset_chunk"); + } /* end if */ + + + /* create the small cube dataset */ + small_cube_dataset = H5Dcreate2(fid, "small_cube_dataset", dset_type, + file_small_cube_sid, H5P_DEFAULT, small_cube_dcpl_id, H5P_DEFAULT); + CHECK(small_cube_dataset, FAIL, "H5Dcreate2"); + + /* Close non-default small dataset DCPL */ + if(small_cube_dcpl_id != H5P_DEFAULT) { + ret = H5Pclose(small_cube_dcpl_id); + CHECK(ret, FAIL, "H5Pclose"); + } /* end if */ + + /* create the large cube dataset */ + large_cube_dataset = H5Dcreate2(fid, "large_cube_dataset", dset_type, + file_large_cube_sid, H5P_DEFAULT, large_cube_dcpl_id, H5P_DEFAULT); + CHECK(large_cube_dataset, FAIL, "H5Dcreate2"); + + /* Close non-default large dataset DCPL */ + if(large_cube_dcpl_id != H5P_DEFAULT) { + ret = H5Pclose(large_cube_dcpl_id); + CHECK(ret, FAIL, "H5Pclose"); + } /* end if */ + + + /* write initial data to the on disk datasets */ + ret = H5Dwrite(small_cube_dataset, H5T_NATIVE_UINT16, full_small_cube_sid, + full_small_cube_sid, xfer_plist, cube_buf); + CHECK(ret, FAIL, "H5Dwrite"); + + ret = H5Dwrite(large_cube_dataset, H5T_NATIVE_UINT16, full_large_cube_sid, + full_large_cube_sid, xfer_plist, cube_buf); + CHECK(ret, FAIL, "H5Dwrite"); + + + /* read initial small cube data from disk and verify that it is as expected. */ + ret = H5Dread(small_cube_dataset, H5T_NATIVE_UINT16, full_small_cube_sid, + full_small_cube_sid, xfer_plist, small_cube_buf_1); + CHECK(ret, FAIL, "H5Dread"); + + /* Check that the data is valid */ + verify_select_hyper_contig_dr__run_test(small_cube_buf_1, small_cube_size, + edge_size, small_rank); + + /* read initial large cube data from disk and verify that it is as expected. */ + ret = H5Dread(large_cube_dataset, H5T_NATIVE_UINT16, full_large_cube_sid, + full_large_cube_sid, xfer_plist, large_cube_buf_1); + CHECK(ret, FAIL, "H5Dread"); + + /* Check that the data is valid */ + verify_select_hyper_contig_dr__run_test(large_cube_buf_1, large_cube_size, + edge_size, large_rank); + + + /* first, verify that we can read from disk correctly using selections + * of different rank that H5S_select_shape_same() views as being of the + * same shape. + * + * Start by reading small_rank-D slice from the on disk large cube, and + * verifying that the data read is correct. Verify that H5S_select_shape_same() + * returns true on the memory and file selections. + * + * The first step is to set up the needed checker board selection in the + * in memory small small cube + */ + + sel_start[0] = sel_start[1] = sel_start[2] = sel_start[3] = sel_start[4] = 0; + + test_select_hyper_checker_board_dr__select_checker_board(mem_small_cube_sid, + small_rank, + edge_size, + checker_edge_size, + small_rank, + sel_start); + + /* now read slices from the large, on-disk cube into the small cube. + * Note how we adjust sel_start only in the dimensions peculiar to the + * large cube. + */ + + start_in_checker[0] = TRUE; + u = 0; + do { + if(small_rank_offset > 0) + sel_start[0] = u; + + v = 0; + do { + if(small_rank_offset > 1) + sel_start[1] = v; + + w = 0; + do { + if(small_rank_offset > 2) + sel_start[2] = w; + + x = 0; + do { + if(small_rank_offset > 3) + sel_start[3] = x; + + /* we know that small_rank >= 1 and that large_rank > small_rank + * by the assertions at the head of this function. Thus no + * need for another inner loop. + */ + + HDassert((sel_start[0] == 0) || (0 < small_rank_offset)); + HDassert((sel_start[1] == 0) || (1 < small_rank_offset)); + HDassert((sel_start[2] == 0) || (2 < small_rank_offset)); + HDassert((sel_start[3] == 0) || (3 < small_rank_offset)); + HDassert((sel_start[4] == 0) || (4 < small_rank_offset)); + + test_select_hyper_checker_board_dr__select_checker_board + ( + file_large_cube_sid, + large_rank, + edge_size, + checker_edge_size, + small_rank, + sel_start + ); + + /* verify that H5S_select_shape_same() reports the two + * selections as having the same shape. + */ + check = H5S_select_shape_same_test(mem_small_cube_sid, + file_large_cube_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + /* zero the buffer that we will be using for reading */ + HDmemset(small_cube_buf_1, 0, sizeof(*small_cube_buf_1) * small_cube_size); + + /* Read selection from disk */ + ret = H5Dread(large_cube_dataset, + H5T_NATIVE_UINT16, + mem_small_cube_sid, + file_large_cube_sid, + xfer_plist, + small_cube_buf_1); + CHECK(ret, FAIL, "H5Dread"); + + expected_value = (uint16_t) + ((u * edge_size * edge_size * edge_size * edge_size) + + (v * edge_size * edge_size * edge_size) + + (w * edge_size * edge_size) + + (x * edge_size)); + + data_ok = test_select_hyper_checker_board_dr__verify_data + ( + small_cube_buf_1, + small_rank, + edge_size, + checker_edge_size, + expected_value, + (hbool_t)TRUE + ); + if(!data_ok) + TestErrPrintf("small cube read from largecube has bad data! Line=%d\n",__LINE__); + + x++; + } while((large_rank >= (test_max_rank - 3)) && + (small_rank <= (test_max_rank - 4)) && (x < edge_size)); + w++; + } while((large_rank >= (test_max_rank - 2)) && + (small_rank <= (test_max_rank - 3)) && (w < edge_size)); + v++; + } while((large_rank >= (test_max_rank - 1)) && + (small_rank <= (test_max_rank - 2)) && (v < edge_size)); + u++; + } while((large_rank >= test_max_rank) && + (small_rank <= (test_max_rank - 1)) && (u < edge_size)); + + + /* similarly, read the on disk small cube into slices through the in memory + * large cube, and verify that the correct data (and only the correct data) + * is read. + */ + + /* select a checker board in the file small cube dataspace */ + sel_start[0] = sel_start[1] = sel_start[2] = sel_start[3] = sel_start[4] = 0; + test_select_hyper_checker_board_dr__select_checker_board(file_small_cube_sid, + small_rank, + edge_size, + checker_edge_size, + small_rank, + sel_start); + + + start_in_checker[0] = TRUE; + u = 0; + do { + if(0 < small_rank_offset) + sel_start[0] = u; + + v = 0; + do { + if(1 < small_rank_offset) + sel_start[1] = v; + + w = 0; + do { + if(2 < small_rank_offset) + sel_start[2] = w; + + x = 0; + do { + if(3 < small_rank_offset) + sel_start[3] = x; + + /* we know that small_rank >= 1 and that large_rank > small_rank + * by the assertions at the head of this function. Thus no + * need for another inner loop. + */ + + HDassert((sel_start[0] == 0) || (0 < small_rank_offset)); + HDassert((sel_start[1] == 0) || (1 < small_rank_offset)); + HDassert((sel_start[2] == 0) || (2 < small_rank_offset)); + HDassert((sel_start[3] == 0) || (3 < small_rank_offset)); + HDassert((sel_start[4] == 0) || (4 < small_rank_offset)); + + test_select_hyper_checker_board_dr__select_checker_board + ( + mem_large_cube_sid, + large_rank, + edge_size, + checker_edge_size, + small_rank, + sel_start + ); + + /* verify that H5S_select_shape_same() reports the two + * selections as having the same shape. + */ + check = H5S_select_shape_same_test(file_small_cube_sid, + mem_large_cube_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + + /* zero out the in memory large cube */ + HDmemset(large_cube_buf_1, 0, sizeof(*large_cube_buf_1) * large_cube_size); + + /* Read selection from disk */ + ret = H5Dread(small_cube_dataset, + H5T_NATIVE_UINT16, + mem_large_cube_sid, + file_small_cube_sid, + xfer_plist, + large_cube_buf_1); + CHECK(ret, FAIL, "H5Dread"); + + + /* verify that the expected data and only the + * expected data was read. + */ + data_ok = TRUE; + ptr_1 = large_cube_buf_1; + expected_value = 0; + start_index = (u * edge_size * edge_size * edge_size * edge_size) + + (v * edge_size * edge_size * edge_size) + + (w * edge_size * edge_size) + + (x * edge_size); + stop_index = start_index + small_cube_size - 1; + + HDassert( start_index < stop_index ); + HDassert( stop_index <= large_cube_size ); + + /* verify that the large cube contains only zeros before the slice */ + for(s = 0; s < start_index; s++) { + if(*ptr_1 != 0) + data_ok = FALSE; + ptr_1++; + } /* end for */ + HDassert(s == start_index); + + data_ok &= test_select_hyper_checker_board_dr__verify_data + ( + ptr_1, + small_rank, + edge_size, + checker_edge_size, + (uint16_t)0, + (hbool_t)TRUE + ); + + ptr_1 += small_cube_size; + s += small_cube_size; + + HDassert(s == stop_index + 1); + + /* verify that the large cube contains only zeros after the slice */ + for(s = stop_index + 1; s < large_cube_size; s++) { + if(*ptr_1 != 0) + data_ok = FALSE; + ptr_1++; + } /* end for */ + if(!data_ok) + TestErrPrintf("large cube read from small cube has bad data! Line=%d\n",__LINE__); + + x++; + } while((large_rank >= (test_max_rank - 3)) && + (small_rank <= (test_max_rank - 4)) && (x < edge_size)); + w++; + } while((large_rank >= (test_max_rank - 2)) && + (small_rank <= (test_max_rank - 3)) && (w < edge_size)); + v++; + } while((large_rank >= (test_max_rank - 1)) && + (small_rank <= (test_max_rank - 2)) && (v < edge_size)); + u++; + } while((large_rank >= test_max_rank) && + (small_rank <= (test_max_rank - 1)) && (u < edge_size)); + + + /* now we go in the opposite direction, verifying that we can write + * from memory to file using selections of different rank that + * H5S_select_shape_same() views as being of the same shape. + * + * Start by writing small_rank D slices from the in memory large cube, to + * the the on disk small cube dataset. After each write, read the small + * cube dataset back from disk, and verify that it contains the expected + * data. Verify that H5S_select_shape_same() returns true on the + * memory and file selections. + */ + + /* select a checker board in the file small cube dataspace */ + sel_start[0] = sel_start[1] = sel_start[2] = sel_start[3] = sel_start[4] = 0; + test_select_hyper_checker_board_dr__select_checker_board(file_small_cube_sid, + small_rank, + edge_size, + checker_edge_size, + small_rank, + sel_start); + + start_in_checker[0] = TRUE; + u = 0; + do { + if(small_rank_offset > 0) + sel_start[0] = u; + + v = 0; + do { + if(small_rank_offset > 1) + sel_start[1] = v; + + w = 0; + do { + if(small_rank_offset > 2) + sel_start[2] = w; + + x = 0; + do { + if(small_rank_offset > 3) + sel_start[3] = x; + + /* zero out the on disk small cube */ + ret = H5Dwrite(small_cube_dataset, + H5T_NATIVE_UINT16, + full_small_cube_sid, + full_small_cube_sid, + xfer_plist, + zero_buf); + CHECK(ret, FAIL, "H5Dwrite"); + + + /* we know that small_rank >= 1 and that large_rank > small_rank + * by the assertions at the head of this function. Thus no + * need for another inner loop. + */ + + HDassert((sel_start[0] == 0) || (0 < small_rank_offset)); + HDassert((sel_start[1] == 0) || (1 < small_rank_offset)); + HDassert((sel_start[2] == 0) || (2 < small_rank_offset)); + HDassert((sel_start[3] == 0) || (3 < small_rank_offset)); + HDassert((sel_start[4] == 0) || (4 < small_rank_offset)); + + test_select_hyper_checker_board_dr__select_checker_board + ( + mem_large_cube_sid, + large_rank, + edge_size, + checker_edge_size, + small_rank, + sel_start + ); + + /* verify that H5S_select_shape_same() reports the two + * selections as having the same shape. + */ + check = H5S_select_shape_same_test(file_small_cube_sid, + mem_large_cube_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + + /* write the slice from the in memory large cube to the + * on disk small cube + */ + ret = H5Dwrite(small_cube_dataset, + H5T_NATIVE_UINT16, + mem_large_cube_sid, + file_small_cube_sid, + xfer_plist, + cube_buf); + CHECK(ret, FAIL, "H5Dwrite"); + + + /* zero the buffer that we will be using for reading */ + HDmemset(small_cube_buf_1, 0, sizeof(*small_cube_buf_1) * small_cube_size); + + /* read the on disk small cube into memory */ + ret = H5Dread(small_cube_dataset, + H5T_NATIVE_UINT16, + full_small_cube_sid, + full_small_cube_sid, + xfer_plist, + small_cube_buf_1); + CHECK(ret, FAIL, "H5Dread"); + + expected_value = (uint16_t) + ((u * edge_size * edge_size * edge_size * edge_size) + + (v * edge_size * edge_size * edge_size) + + (w * edge_size * edge_size) + + (x * edge_size)); + + data_ok = test_select_hyper_checker_board_dr__verify_data + ( + small_cube_buf_1, + small_rank, + edge_size, + checker_edge_size, + expected_value, + (hbool_t)TRUE + ); + if(!data_ok) + TestErrPrintf("small cube read from largecube has bad data! Line=%d\n",__LINE__); + + x++; + } while((large_rank >= (test_max_rank - 3)) && + (small_rank <= (test_max_rank - 4)) && (x < edge_size)); + w++; + } while((large_rank >= (test_max_rank - 2)) && + (small_rank <= (test_max_rank - 3)) && (w < edge_size)); + v++; + } while((large_rank >= (test_max_rank - 1)) && + (small_rank <= (test_max_rank - 2)) && (v < edge_size)); + u++; + } while((large_rank >= test_max_rank) && + (small_rank <= (test_max_rank - 1)) && (u < edge_size)); + + + /* Now write checker board selections of the entries in memory + * small cube to slices of the on disk cube. After each write, + * read the on disk large cube * into memeory, and verify that + * it contains the expected * data. Verify that + * H5S_select_shape_same() returns true on the memory and file + * selections. + */ + + /* select a checker board in the in memory small cube dataspace */ + sel_start[0] = sel_start[1] = sel_start[2] = sel_start[3] = sel_start[4] = 0; + test_select_hyper_checker_board_dr__select_checker_board(mem_small_cube_sid, + small_rank, + edge_size, + checker_edge_size, + small_rank, + sel_start); + + start_in_checker[0] = TRUE; + u = 0; + do { + if(small_rank_offset > 0) + sel_start[0] = u; + + v = 0; + do { + if(small_rank_offset > 1) + sel_start[1] = v; + + w = 0; + do { + if(small_rank_offset > 2) + sel_start[2] = w; + + x = 0; + do { + if(small_rank_offset > 3) + sel_start[3] = x; + + /* zero out the on disk cube */ + ret = H5Dwrite(large_cube_dataset, + H5T_NATIVE_USHORT, + full_large_cube_sid, + full_large_cube_sid, + xfer_plist, + zero_buf); + CHECK(ret, FAIL, "H5Dwrite"); + + /* we know that small_rank >= 1 and that large_rank > small_rank + * by the assertions at the head of this function. Thus no + * need for another inner loop. + */ + + HDassert((sel_start[0] == 0) || (0 < small_rank_offset)); + HDassert((sel_start[1] == 0) || (1 < small_rank_offset)); + HDassert((sel_start[2] == 0) || (2 < small_rank_offset)); + HDassert((sel_start[3] == 0) || (3 < small_rank_offset)); + HDassert((sel_start[4] == 0) || (4 < small_rank_offset)); + + + test_select_hyper_checker_board_dr__select_checker_board + ( + file_large_cube_sid, + large_rank, + edge_size, + checker_edge_size, + small_rank, + sel_start + ); + + /* verify that H5S_select_shape_same() reports the two + * selections as having the same shape. + */ + check = H5S_select_shape_same_test(file_large_cube_sid, + mem_small_cube_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + + /* write the checker board selection of the in memory + * small cube to a slice through the on disk large + * cube. + */ + ret = H5Dwrite(large_cube_dataset, + H5T_NATIVE_UINT16, + mem_small_cube_sid, + file_large_cube_sid, + xfer_plist, + cube_buf); + CHECK(ret, FAIL, "H5Dwrite"); + + + /* zero out the in memory large cube */ + HDmemset(large_cube_buf_1, 0, sizeof(*large_cube_buf_1) * large_cube_size); + + /* read the on disk large cube into memory */ + ret = H5Dread(large_cube_dataset, + H5T_NATIVE_UINT16, + full_large_cube_sid, + full_large_cube_sid, + xfer_plist, + large_cube_buf_1); + CHECK(ret, FAIL, "H5Dread"); + + + /* verify that the expected data and only the + * expected data was written to the on disk large + * cube. + */ + data_ok = TRUE; + ptr_1 = large_cube_buf_1; + expected_value = 0; + start_index = (u * edge_size * edge_size * edge_size * edge_size) + + (v * edge_size * edge_size * edge_size) + + (w * edge_size * edge_size) + + (x * edge_size); + stop_index = start_index + small_cube_size - 1; + + HDassert( start_index < stop_index ); + HDassert( stop_index <= large_cube_size ); + + /* verify that the large cube contains only zeros before the slice */ + for(s = 0; s < start_index; s++) { + if(*ptr_1 != 0) + data_ok = FALSE; + ptr_1++; + } /* end for */ + HDassert(s == start_index); + + /* verify that the slice contains the expected data */ + data_ok &= test_select_hyper_checker_board_dr__verify_data + ( + ptr_1, + small_rank, + edge_size, + checker_edge_size, + (uint16_t)0, + (hbool_t)TRUE + ); + + ptr_1 += small_cube_size; + s += small_cube_size; + + HDassert(s == stop_index + 1); + + /* verify that the large cube contains only zeros after the slice */ + for(s = stop_index + 1; s < large_cube_size; s++) { + if(*ptr_1 != 0) + data_ok = FALSE; + ptr_1++; + } /* end for */ + if(!data_ok) + TestErrPrintf("large cube written from small cube has bad data! Line=%d\n",__LINE__); + + x++; + } while((large_rank >= (test_max_rank - 3)) && + (small_rank <= (test_max_rank - 4)) && (x < edge_size)); + w++; + } while((large_rank >= (test_max_rank - 2)) && + (small_rank <= (test_max_rank - 3)) && (w < edge_size)); + v++; + } while((large_rank >= (test_max_rank - 1)) && + (small_rank <= (test_max_rank - 2)) && (v < edge_size)); + u++; + } while((large_rank >= test_max_rank) && + (small_rank <= (test_max_rank - 1)) && (u < edge_size)); + + + /* Close memory dataspaces */ + ret = H5Sclose(full_small_cube_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(full_large_cube_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(mem_small_cube_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(mem_large_cube_sid); + CHECK(ret, FAIL, "H5Sclose"); + + + /* Close disk dataspace */ + ret = H5Sclose(file_small_cube_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(file_large_cube_sid); + CHECK(ret, FAIL, "H5Sclose"); + + /* Close Datasets */ + ret = H5Dclose(small_cube_dataset); + CHECK(ret, FAIL, "H5Dclose"); + + ret = H5Dclose(large_cube_dataset); + CHECK(ret, FAIL, "H5Dclose"); + + /* Close file */ + ret = H5Fclose(fid); + CHECK(ret, FAIL, "H5Fclose"); + + /* Free memory buffers */ + HDfree(small_cube_buf_1); + HDfree(large_cube_buf_1); + +} /* test_select_hyper_checker_board_dr__run_test() */ + + +/**************************************************************** +** +** test_select_hyper_checker_board_dr(): Test H5S (dataspace) +** selection code with checkerboard source and target having +** different ranks but the same shape. We have already +** tested H5S_shape_same in isolation, so now we try to do +** I/O. +** +** This is just an initial smoke check, so we will work +** with a slice through a cube only. +** +****************************************************************/ +static void +test_select_hyper_checker_board_dr(hid_t dset_type, hid_t xfer_plist) +{ + uint16_t *cube_buf; /* Buffer for writing cube data */ + uint16_t *cube_ptr; /* Temporary pointer into cube data */ + uint16_t *zero_buf; /* Buffer for writing zeroed cube data */ + int test_num = 0; + unsigned checker_edge_size = 2; /* Size of checkerboard dimension */ + unsigned chunk_edge_size; /* Size of chunk's dataspace dimensions */ + unsigned edge_size = 6; /* Size of dataset's dataspace dimensions */ + unsigned small_rank; /* Current rank of small dataset */ + unsigned large_rank; /* Current rank of large dataset */ + unsigned max_rank = 5; /* Max. rank to use */ + size_t max_cube_size; /* Max. number of elements in largest cube */ + size_t s; /* Local index variable */ + unsigned u; /* Local index variable */ + + /* Output message about test being performed */ + MESSAGE(5, ("Testing Checker Board Hyperslabs With Different Rank I/O Functionality\n")); + + /* Compute max. cube size */ + max_cube_size = (size_t)1; + for(u = 0; u < max_rank; u++) + max_cube_size *= (size_t)(edge_size + 1); + + /* Allocate cube buffer for writing values */ + cube_buf = (uint16_t *)HDmalloc(sizeof(uint16_t) * max_cube_size); + CHECK(cube_buf, NULL, "HDmalloc"); + + /* Initialize the cube buffer */ + cube_ptr = cube_buf; + for(s = 0; s < max_cube_size; s++) + *cube_ptr++ = (uint16_t)s; + + /* Allocate cube buffer for zeroing values on disk */ + zero_buf = (uint16_t *)HDcalloc(sizeof(uint16_t), max_cube_size); + CHECK(zero_buf, NULL, "HDcalloc"); + + for(large_rank = 1; large_rank <= max_rank; large_rank++) { + for(small_rank = 1; small_rank < large_rank; small_rank++) { + chunk_edge_size = 0; + test_select_hyper_checker_board_dr__run_test(test_num, cube_buf, + zero_buf, edge_size, checker_edge_size, chunk_edge_size, small_rank, + large_rank, dset_type, xfer_plist); + test_num++; + + test_select_hyper_checker_board_dr__run_test(test_num, cube_buf, + zero_buf, + edge_size + 1, checker_edge_size, chunk_edge_size, small_rank, + large_rank, dset_type, xfer_plist); + test_num++; + + chunk_edge_size = 3; + test_select_hyper_checker_board_dr__run_test(test_num, cube_buf, + zero_buf, + edge_size, checker_edge_size, chunk_edge_size, small_rank, + large_rank, dset_type, xfer_plist); + test_num++; + + test_select_hyper_checker_board_dr__run_test(test_num, cube_buf, + zero_buf, + edge_size + 1, checker_edge_size, chunk_edge_size, small_rank, + large_rank, dset_type, xfer_plist); + test_num++; + } /* for loop on small rank */ + } /* for loop on large rank */ + + HDfree(cube_buf); + HDfree(zero_buf); + +} /* test_select_hyper_checker_board_dr() */ + + /**************************************************************** ** ** test_select_hyper_copy(): Test H5S (dataspace) selection code. @@ -2345,15 +4373,15 @@ test_select_point_offset(void) CHECK(ret, FAIL, "H5Sselect_elements"); /* Read selection from disk */ - ret=H5Dread(dataset,H5T_NATIVE_UCHAR,sid2,sid1,H5P_DEFAULT,rbuf); + ret = H5Dread(dataset, H5T_NATIVE_UCHAR, sid2, sid1, H5P_DEFAULT, rbuf); CHECK(ret, FAIL, "H5Dread"); /* Compare data read with data written out */ - for(i=0; i<POINT1_NPOINTS; i++) { - tbuf=wbuf+((coord2[i][0]+offset[0])*SPACE2_DIM2)+coord2[i][1]+offset[1]; - tbuf2=rbuf+(coord3[i][0]*SPACE3_DIM2)+coord3[i][1]; - if(*tbuf!=*tbuf2) - TestErrPrintf("element values don't match!, i=%d\n",i); + for(i = 0; i < POINT1_NPOINTS; i++) { + tbuf = wbuf + ((coord2[i][0] + (hsize_t)offset[0]) * SPACE2_DIM2) + coord2[i][1] + (hsize_t)offset[1]; + tbuf2 = rbuf + (coord3[i][0] * SPACE3_DIM2) + coord3[i][1]; + if(*tbuf != *tbuf2) + TestErrPrintf("element values don't match!, i=%d\n", i); } /* end for */ /* Close memory dataspace */ @@ -2410,7 +4438,7 @@ test_select_hyper_union(void) *tbuf2; /* temporary buffer pointer */ int i,j; /* Counters */ herr_t ret; /* Generic return value */ - hsize_t npoints; /* Number of elements in selection */ + hssize_t npoints; /* Number of elements in selection */ /* Output message about test being performed */ MESSAGE(5, ("Testing Hyperslab Selection Functions with unions of hyperslabs\n")); @@ -2448,7 +4476,7 @@ test_select_hyper_union(void) CHECK(ret, FAIL, "H5Sselect_hyperslab"); npoints = H5Sget_select_npoints(sid1); - VERIFY(npoints, 2*15*13, "H5Sget_select_npoints"); + VERIFY(npoints, 2 * 15 * 13, "H5Sget_select_npoints"); /* Select 8x26 hyperslab for memory dataset */ start[0]=15; start[1]=0; @@ -2561,7 +4589,7 @@ test_select_hyper_union(void) CHECK(ret, FAIL, "H5Sselect_hyperslab"); npoints = H5Sget_select_npoints(sid2); - VERIFY(npoints, 15*26, "H5Sget_select_npoints"); + VERIFY(npoints, 15 * 26, "H5Sget_select_npoints"); /* Create a dataset */ dataset = H5Dcreate2(fid1, SPACE2_NAME, H5T_NATIVE_UCHAR, sid1, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); @@ -2647,7 +4675,7 @@ test_select_hyper_union(void) CHECK(ret, FAIL, "H5Sselect_hyperslab"); npoints = H5Sget_select_npoints(sid2); - VERIFY(npoints, 15*26, "H5Sget_select_npoints"); + VERIFY(npoints, 15 * 26, "H5Sget_select_npoints"); /* Create a dataset */ dataset = H5Dcreate2(fid1, SPACE3_NAME, H5T_NATIVE_UCHAR, sid1, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); @@ -2737,7 +4765,7 @@ test_select_hyper_union(void) CHECK(ret, FAIL, "H5Sselect_hyperslab"); npoints = H5Sget_select_npoints(sid2); - VERIFY(npoints, 15*26, "H5Sget_select_npoints"); + VERIFY(npoints, 15 * 26, "H5Sget_select_npoints"); /* Create a dataset */ dataset = H5Dcreate2(fid1, SPACE4_NAME, H5T_NATIVE_UCHAR, sid1, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); @@ -2834,7 +4862,7 @@ test_select_hyper_union(void) CHECK(ret, FAIL, "H5Sselect_hyperslab"); npoints = H5Sget_select_npoints(sid2); - VERIFY(npoints, 15*26, "H5Sget_select_npoints"); + VERIFY(npoints, 15 * 26, "H5Sget_select_npoints"); /* Create a dataset */ dataset = H5Dcreate2(fid1,SPACE5_NAME, H5T_NATIVE_UCHAR, sid1, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); @@ -3277,7 +5305,7 @@ test_select_hyper_and_2d(void) *tbuf2; /* temporary buffer pointer */ int i,j; /* Counters */ herr_t ret; /* Generic return value */ - hsize_t npoints; /* Number of elements in selection */ + hssize_t npoints; /* Number of elements in selection */ /* Output message about test being performed */ MESSAGE(5, ("Testing Hyperslab Selection Functions with intersection of 2-D hyperslabs\n")); @@ -3322,7 +5350,7 @@ test_select_hyper_and_2d(void) CHECK(ret, FAIL, "H5Sselect_hyperslab"); npoints = H5Sget_select_npoints(sid1); - VERIFY(npoints, 5*5, "H5Sget_select_npoints"); + VERIFY(npoints, 5 * 5, "H5Sget_select_npoints"); /* Select 25 hyperslab for memory dataset */ start[0]=0; @@ -3333,7 +5361,7 @@ test_select_hyper_and_2d(void) CHECK(ret, FAIL, "H5Sselect_hyperslab"); npoints = H5Sget_select_npoints(sid2); - VERIFY(npoints, 5*5, "H5Sget_select_npoints"); + VERIFY(npoints, 5 * 5, "H5Sget_select_npoints"); /* Create a dataset */ dataset = H5Dcreate2(fid1, SPACE2_NAME, H5T_NATIVE_UCHAR, sid1, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); @@ -3406,7 +5434,7 @@ test_select_hyper_xor_2d(void) *tbuf2; /* temporary buffer pointer */ int i,j; /* Counters */ herr_t ret; /* Generic return value */ - hsize_t npoints; /* Number of elements in selection */ + hssize_t npoints; /* Number of elements in selection */ /* Output message about test being performed */ MESSAGE(5, ("Testing Hyperslab Selection Functions with XOR of 2-D hyperslabs\n")); @@ -3537,7 +5565,7 @@ test_select_hyper_notb_2d(void) *tbuf2; /* temporary buffer pointer */ int i,j; /* Counters */ herr_t ret; /* Generic return value */ - hsize_t npoints; /* Number of elements in selection */ + hssize_t npoints; /* Number of elements in selection */ /* Output message about test being performed */ MESSAGE(5, ("Testing Hyperslab Selection Functions with NOTB of 2-D hyperslabs\n")); @@ -3667,7 +5695,7 @@ test_select_hyper_nota_2d(void) *tbuf2; /* temporary buffer pointer */ int i,j; /* Counters */ herr_t ret; /* Generic return value */ - hsize_t npoints; /* Number of elements in selection */ + hssize_t npoints; /* Number of elements in selection */ /* Output message about test being performed */ MESSAGE(5, ("Testing Hyperslab Selection Functions with NOTA of 2-D hyperslabs\n")); @@ -3878,7 +5906,7 @@ test_select_hyper_union_random_5d(hid_t read_plist) #else /* QAK */ seed=987909620; #endif /* QAK */ - HDsrand(seed); + HDsrandom(seed); #ifdef QAK printf("test_num=%d, seed=%u\n",test_num,seed); @@ -3893,26 +5921,26 @@ printf("hyperslab=%d\n",i); #endif /* QAK */ /* Select random hyperslab location & size for selection */ for(j=0; j<SPACE5_RANK; j++) { - start[j]=rand()%dims1[j]; - count[j]=(rand()%(dims1[j]-start[j]))+1; + start[j] = ((hsize_t)HDrandom() % dims1[j]); + count[j] = (((hsize_t)HDrandom() % (dims1[j] - start[j])) + 1); #ifdef QAK printf("start[%d]=%d, count[%d]=%d (end[%d]=%d)\n",j,(int)start[j],j,(int)count[j],j,(int)(start[j]+count[j]-1)); #endif /* QAK */ } /* end for */ /* Select hyperslab */ - ret = H5Sselect_hyperslab(sid1,(i==0 ? H5S_SELECT_SET : H5S_SELECT_OR),start,NULL,count,NULL); + ret = H5Sselect_hyperslab(sid1, (i == 0 ? H5S_SELECT_SET : H5S_SELECT_OR), start, NULL, count, NULL); CHECK(ret, FAIL, "H5Sselect_hyperslab"); } /* end for */ /* Get the number of elements selected */ - npoints=H5Sget_select_npoints(sid1); + npoints = H5Sget_select_npoints(sid1); CHECK(npoints, 0, "H5Sget_select_npoints"); /* Select linear 1-D hyperslab for memory dataset */ - start[0]=0; - count[0]=npoints; - ret = H5Sselect_hyperslab(sid2,H5S_SELECT_SET,start,NULL,count,NULL); + start[0] = 0; + count[0] = (hsize_t)npoints; + ret = H5Sselect_hyperslab(sid2, H5S_SELECT_SET, start, NULL, count, NULL); CHECK(ret, FAIL, "H5Sselect_hyperslab"); npoints2 = H5Sget_select_npoints(sid2); @@ -4973,24 +7001,24 @@ typedef struct { static herr_t test_select_hyper_iter3(void *_elem, hid_t UNUSED type_id, unsigned ndim, const hsize_t *point, void *_operator_data) { - unsigned short *tbuf=(unsigned short *)_elem; /* temporary buffer pointer */ - fill_iter_info *iter_info=(fill_iter_info *)_operator_data; /* Get the pointer to the iterator information */ + unsigned *tbuf = (unsigned *)_elem; /* temporary buffer pointer */ + fill_iter_info *iter_info = (fill_iter_info *)_operator_data; /* Get the pointer to the iterator information */ hsize_t *coord_ptr; /* Pointer to the coordinate information for a point*/ /* Check value in current buffer location */ - if(*tbuf!=iter_info->fill_value) + if(*tbuf != iter_info->fill_value) return(-1); else { /* Check number of dimensions */ - if(ndim!=SPACE7_RANK) + if(ndim != SPACE7_RANK) return(-1); else { /* Check Coordinates */ - coord_ptr=iter_info->coords+(2*iter_info->curr_coord); + coord_ptr = iter_info->coords + (2 * iter_info->curr_coord); iter_info->curr_coord++; - if(coord_ptr[0]!=point[0]) + if(coord_ptr[0] != point[0]) return(-1); - else if(coord_ptr[1]!=point[1]) + else if(coord_ptr[1] != point[1]) return(-1); else return(0); @@ -5009,25 +7037,25 @@ test_select_fill_all(void) { hid_t sid1; /* Dataspace ID */ hsize_t dims1[] = {SPACE7_DIM1, SPACE7_DIM2}; - int fill_value; /* Fill value */ + unsigned fill_value; /* Fill value */ fill_iter_info iter_info; /* Iterator information structure */ hsize_t points[SPACE7_DIM1*SPACE7_DIM2][SPACE7_RANK]; /* Coordinates of selection */ - unsigned short *wbuf, /* buffer to write to disk */ + unsigned *wbuf, /* buffer to write to disk */ *tbuf; /* temporary buffer pointer */ - int i,j; /* Counters */ + unsigned u, v; /* Counters */ herr_t ret; /* Generic return value */ /* Output message about test being performed */ MESSAGE(5, ("Testing Filling 'all' Selections\n")); /* Allocate memory buffer */ - wbuf = (unsigned short *)HDmalloc(sizeof(unsigned short)*SPACE7_DIM1*SPACE7_DIM2); + wbuf = (unsigned *)HDmalloc(sizeof(unsigned) * SPACE7_DIM1 * SPACE7_DIM2); CHECK(wbuf, NULL, "HDmalloc"); /* Initialize memory buffer */ - for(i=0, tbuf=wbuf; i<SPACE7_DIM1; i++) - for(j=0; j<SPACE7_DIM2; j++) - *tbuf++=(unsigned short)(i*SPACE7_DIM2)+j; + for(u = 0, tbuf = wbuf; u < SPACE7_DIM1; u++) + for(v = 0; v < SPACE7_DIM2; v++) + *tbuf++ = (u * SPACE7_DIM2) + v; /* Create dataspace for dataset on disk */ sid1 = H5Screate_simple(SPACE7_RANK, dims1, NULL); @@ -5036,32 +7064,32 @@ test_select_fill_all(void) /* Space defaults to "all" selection */ /* Set fill value */ - fill_value=SPACE7_FILL; + fill_value = SPACE7_FILL; /* Fill selection in memory */ - ret=H5Dfill(&fill_value,H5T_NATIVE_INT,wbuf,H5T_NATIVE_USHORT,sid1); + ret = H5Dfill(&fill_value, H5T_NATIVE_UINT, wbuf, H5T_NATIVE_UINT, sid1); CHECK(ret, FAIL, "H5Dfill"); /* Verify memory buffer the hard way... */ - for(i=0, tbuf=wbuf; i<SPACE7_DIM1; i++) - for(j=0; j<SPACE7_DIM2; j++) - if(*tbuf!=(unsigned short)fill_value) - TestErrPrintf("Error! j=%d, i=%d, *tbuf=%x, fill_value=%x\n",j,i,(unsigned)*tbuf,(unsigned)fill_value); + for(u = 0, tbuf = wbuf; u < SPACE7_DIM1; u++) + for(v = 0; v < SPACE7_DIM2; v++) + if(*tbuf != fill_value) + TestErrPrintf("Error! v=%d, u=%u, *tbuf=%u, fill_value=%u\n", v, u, *tbuf, fill_value); /* Set the coordinates of the selection */ - for(i=0; i<SPACE7_DIM1; i++) - for(j=0; j<SPACE7_DIM2; j++) { - points[(i*SPACE7_DIM2)+j][0]=i; - points[(i*SPACE7_DIM2)+j][1]=j; + for(u = 0; u < SPACE7_DIM1; u++) + for(v = 0; v < SPACE7_DIM2; v++) { + points[(u * SPACE7_DIM2) + v][0] = u; + points[(u * SPACE7_DIM2) + v][1] = v; } /* end for */ /* Initialize the iterator structure */ - iter_info.fill_value=SPACE7_FILL; - iter_info.curr_coord=0; - iter_info.coords=(hsize_t *)points; + iter_info.fill_value = SPACE7_FILL; + iter_info.curr_coord = 0; + iter_info.coords = (hsize_t *)points; /* Iterate through selection, verifying correct data */ - ret = H5Diterate(wbuf,H5T_NATIVE_USHORT,sid1,test_select_hyper_iter3,&iter_info); + ret = H5Diterate(wbuf, H5T_NATIVE_UINT, sid1, test_select_hyper_iter3, &iter_info); CHECK(ret, FAIL, "H5Diterate"); /* Close dataspace */ @@ -5085,78 +7113,78 @@ test_select_fill_point(hssize_t *offset) hsize_t dims1[] = {SPACE7_DIM1, SPACE7_DIM2}; hssize_t real_offset[SPACE7_RANK]; /* Actual offset to use */ hsize_t points[5][SPACE7_RANK] = {{2,4}, {3,8}, {8,4}, {7,5}, {7,7}}; - size_t num_points=5; /* Number of points selected */ + size_t num_points = 5; /* Number of points selected */ int fill_value; /* Fill value */ fill_iter_info iter_info; /* Iterator information structure */ - unsigned short *wbuf, /* buffer to write to disk */ + unsigned *wbuf, /* buffer to write to disk */ *tbuf; /* temporary buffer pointer */ - int i,j,k; /* Counters */ + unsigned u, v, w; /* Counters */ herr_t ret; /* Generic return value */ /* Output message about test being performed */ MESSAGE(5, ("Testing Filling 'point' Selections\n")); /* Allocate memory buffer */ - wbuf = (unsigned short *)HDmalloc(sizeof(unsigned short)*SPACE7_DIM1*SPACE7_DIM2); + wbuf = (unsigned *)HDmalloc(sizeof(unsigned) * SPACE7_DIM1 * SPACE7_DIM2); CHECK(wbuf, NULL, "HDmalloc"); /* Initialize memory buffer */ - for(i=0, tbuf=wbuf; i<SPACE7_DIM1; i++) - for(j=0; j<SPACE7_DIM2; j++) - *tbuf++=(unsigned short)(i*SPACE7_DIM2)+j; + for(u = 0, tbuf = wbuf; u < SPACE7_DIM1; u++) + for(v = 0; v < SPACE7_DIM2; v++) + *tbuf++ = (unsigned short)(u * SPACE7_DIM2) + v; /* Create dataspace for dataset on disk */ sid1 = H5Screate_simple(SPACE7_RANK, dims1, NULL); CHECK(sid1, FAIL, "H5Screate_simple"); /* Select "point" selection */ - ret = H5Sselect_elements(sid1, H5S_SELECT_SET,num_points,(const hsize_t *)points); + ret = H5Sselect_elements(sid1, H5S_SELECT_SET, num_points, (const hsize_t *)points); CHECK(ret, FAIL, "H5Sselect_elements"); - if(offset!=NULL) { - HDmemcpy(real_offset,offset,SPACE7_RANK*sizeof(hssize_t)); + if(offset != NULL) { + HDmemcpy(real_offset, offset, SPACE7_RANK * sizeof(hssize_t)); /* Set offset, if provided */ - ret = H5Soffset_simple(sid1,real_offset); + ret = H5Soffset_simple(sid1, real_offset); CHECK(ret, FAIL, "H5Soffset_simple"); } /* end if */ else - HDmemset(real_offset,0,SPACE7_RANK*sizeof(hssize_t)); + HDmemset(real_offset, 0, SPACE7_RANK * sizeof(hssize_t)); /* Set fill value */ - fill_value=SPACE7_FILL; + fill_value = SPACE7_FILL; /* Fill selection in memory */ - ret=H5Dfill(&fill_value,H5T_NATIVE_INT,wbuf,H5T_NATIVE_USHORT,sid1); + ret = H5Dfill(&fill_value, H5T_NATIVE_INT, wbuf, H5T_NATIVE_UINT, sid1); CHECK(ret, FAIL, "H5Dfill"); /* Verify memory buffer the hard way... */ - for(i=0, tbuf=wbuf; i<SPACE7_DIM1; i++) - for(j=0; j<SPACE7_DIM2; j++, tbuf++) { - for(k=0; k<(int)num_points; k++) { - if(i==(int)(points[k][0]+real_offset[0]) && j==(int)(points[k][1]+real_offset[1])) { - if(*tbuf!=(unsigned short)fill_value) - TestErrPrintf("Error! j=%d, i=%d, *tbuf=%u, fill_value=%u\n",j,i,(unsigned)*tbuf,(unsigned)fill_value); + for(u = 0, tbuf = wbuf; u < SPACE7_DIM1; u++) + for(v = 0; v < SPACE7_DIM2; v++, tbuf++) { + for(w = 0; w < (unsigned)num_points; w++) { + if(u == (unsigned)(points[w][0] + (hsize_t)real_offset[0]) && v == (unsigned)(points[w][1] + (hsize_t)real_offset[1])) { + if(*tbuf != (unsigned)fill_value) + TestErrPrintf("Error! v=%u, u=%u, *tbuf=%u, fill_value=%u\n", v, u, *tbuf, (unsigned)fill_value); break; } /* end if */ } /* end for */ - if(k==(int)num_points && *tbuf!=((unsigned short)(i*SPACE7_DIM2)+j)) - TestErrPrintf("Error! j=%d, i=%d, *tbuf=%u, should be: %u\n",j,i,(unsigned)*tbuf,(unsigned)((i*SPACE7_DIM2)+j)); + if(w == (unsigned)num_points && *tbuf != ((u * SPACE7_DIM2) + v)) + TestErrPrintf("Error! v=%d, u=%d, *tbuf=%u, should be: %u\n", v, u, *tbuf, ((u * SPACE7_DIM2) + v)); } /* end for */ /* Initialize the iterator structure */ - iter_info.fill_value=SPACE7_FILL; - iter_info.curr_coord=0; - iter_info.coords=(hsize_t *)points; + iter_info.fill_value = SPACE7_FILL; + iter_info.curr_coord = 0; + iter_info.coords = (hsize_t *)points; /* Add in the offset */ - for(i=0; i<(int)num_points; i++) { - points[i][0]+=real_offset[0]; - points[i][1]+=real_offset[1]; + for(u = 0; u < (unsigned)num_points; u++) { + points[u][0] = (hsize_t)(points[u][0] + real_offset[0]); + points[u][1] = (hsize_t)(points[u][1] + real_offset[1]); } /* end for */ /* Iterate through selection, verifying correct data */ - ret = H5Diterate(wbuf,H5T_NATIVE_USHORT,sid1,test_select_hyper_iter3,&iter_info); + ret = H5Diterate(wbuf, H5T_NATIVE_UINT, sid1, test_select_hyper_iter3, &iter_info); CHECK(ret, FAIL, "H5Diterate"); /* Close dataspace */ @@ -5185,78 +7213,78 @@ test_select_fill_hyper_simple(hssize_t *offset) hsize_t points[16][SPACE7_RANK]; /* Coordinates selected */ int fill_value; /* Fill value */ fill_iter_info iter_info; /* Iterator information structure */ - unsigned short *wbuf, /* buffer to write to disk */ + unsigned *wbuf, /* buffer to write to disk */ *tbuf; /* temporary buffer pointer */ - int i,j; /* Counters */ + unsigned u, v; /* Counters */ herr_t ret; /* Generic return value */ /* Output message about test being performed */ MESSAGE(5, ("Testing Filling Simple 'hyperslab' Selections\n")); /* Allocate memory buffer */ - wbuf = (unsigned short *)HDmalloc(sizeof(unsigned short)*SPACE7_DIM1*SPACE7_DIM2); + wbuf = (unsigned *)HDmalloc(sizeof(unsigned) * SPACE7_DIM1 * SPACE7_DIM2); CHECK(wbuf, NULL, "HDmalloc"); /* Initialize memory buffer */ - for(i=0, tbuf=wbuf; i<SPACE7_DIM1; i++) - for(j=0; j<SPACE7_DIM2; j++) - *tbuf++=(unsigned short)(i*SPACE7_DIM2)+j; + for(u = 0, tbuf = wbuf; u < SPACE7_DIM1; u++) + for(v = 0; v < SPACE7_DIM2; v++) + *tbuf++ = (unsigned short)(u * SPACE7_DIM2) + v; /* Create dataspace for dataset on disk */ sid1 = H5Screate_simple(SPACE7_RANK, dims1, NULL); CHECK(sid1, FAIL, "H5Screate_simple"); /* Select "hyperslab" selection */ - start[0]=3; start[1]=3; - count[0]=4; count[1]=4; - ret = H5Sselect_hyperslab(sid1, H5S_SELECT_SET,start,NULL,count,NULL); + start[0] = 3; start[1] = 3; + count[0] = 4; count[1] = 4; + ret = H5Sselect_hyperslab(sid1, H5S_SELECT_SET, start, NULL, count, NULL); CHECK(ret, FAIL, "H5Sselect_hyperslab"); - if(offset!=NULL) { - HDmemcpy(real_offset,offset,SPACE7_RANK*sizeof(hssize_t)); + if(offset != NULL) { + HDmemcpy(real_offset, offset, SPACE7_RANK * sizeof(hssize_t)); /* Set offset, if provided */ - ret = H5Soffset_simple(sid1,real_offset); + ret = H5Soffset_simple(sid1, real_offset); CHECK(ret, FAIL, "H5Soffset_simple"); } /* end if */ else - HDmemset(real_offset,0,SPACE7_RANK*sizeof(hssize_t)); + HDmemset(real_offset, 0, SPACE7_RANK * sizeof(hssize_t)); /* Set fill value */ - fill_value=SPACE7_FILL; + fill_value = SPACE7_FILL; /* Fill selection in memory */ - ret=H5Dfill(&fill_value,H5T_NATIVE_INT,wbuf,H5T_NATIVE_USHORT,sid1); + ret = H5Dfill(&fill_value, H5T_NATIVE_INT, wbuf, H5T_NATIVE_UINT, sid1); CHECK(ret, FAIL, "H5Dfill"); /* Verify memory buffer the hard way... */ - for(i=0, tbuf=wbuf; i<SPACE7_DIM1; i++) - for(j=0; j<SPACE7_DIM2; j++, tbuf++) { - if((i>=(int)(start[0]+real_offset[0]) && i<(int)(start[0]+count[0]+real_offset[0])) - && (j>=(int)(start[1]+real_offset[1]) && j<(int)(start[1]+count[1]+real_offset[1]))) { - if(*tbuf!=(unsigned short)fill_value) - TestErrPrintf("Error! j=%d, i=%d, *tbuf=%u, fill_value=%u\n",j,i,(unsigned)*tbuf,(unsigned)fill_value); + for(u = 0, tbuf = wbuf; u < SPACE7_DIM1; u++) + for(v = 0; v < SPACE7_DIM2; v++, tbuf++) { + if((u >= (unsigned)(start[0] + real_offset[0]) && u < (unsigned)(start[0] + count[0] + real_offset[0])) + && (v >= (unsigned)(start[1] + real_offset[1]) && v < (unsigned)(start[1] + count[1] + real_offset[1]))) { + if(*tbuf != (unsigned)fill_value) + TestErrPrintf("Error! v=%u, u=%u, *tbuf=%u, fill_value=%u\n", v, u, *tbuf, (unsigned)fill_value); } /* end if */ else { - if(*tbuf!=((unsigned short)(i*SPACE7_DIM2)+j)) - TestErrPrintf("Error! j=%d, i=%d, *tbuf=%u, should be: %u\n",j,i,(unsigned)*tbuf,(unsigned)((i*SPACE7_DIM2)+j)); + if(*tbuf != ((unsigned)(u * SPACE7_DIM2) + v)) + TestErrPrintf("Error! v=%u, u=%u, *tbuf=%u, should be: %u\n", v, u, *tbuf, ((u * SPACE7_DIM2) + v)); } /* end else */ } /* end for */ /* Initialize the iterator structure */ - iter_info.fill_value=SPACE7_FILL; - iter_info.curr_coord=0; - iter_info.coords=(hsize_t *)points; + iter_info.fill_value = SPACE7_FILL; + iter_info.curr_coord = 0; + iter_info.coords = (hsize_t *)points; /* Set the coordinates of the selection (with the offset) */ - for(i=0, num_points=0; i<(int)count[0]; i++) - for(j=0; j<(int)count[1]; j++, num_points++) { - points[num_points][0]=i+start[0]+real_offset[0]; - points[num_points][1]=j+start[1]+real_offset[1]; + for(u = 0, num_points = 0; u < (unsigned)count[0]; u++) + for(v = 0; v < (unsigned)count[1]; v++, num_points++) { + points[num_points][0] = (hsize_t)(u + start[0] + real_offset[0]); + points[num_points][1] = (hsize_t)(v + start[1] + real_offset[1]); } /* end for */ /* Iterate through selection, verifying correct data */ - ret = H5Diterate(wbuf,H5T_NATIVE_USHORT,sid1,test_select_hyper_iter3,&iter_info); + ret = H5Diterate(wbuf, H5T_NATIVE_UINT, sid1, test_select_hyper_iter3, &iter_info); CHECK(ret, FAIL, "H5Diterate"); /* Close dataspace */ @@ -5292,79 +7320,79 @@ test_select_fill_hyper_regular(hssize_t *offset) size_t num_points=16; /* Number of points selected */ int fill_value; /* Fill value */ fill_iter_info iter_info; /* Iterator information structure */ - unsigned short *wbuf, /* buffer to write to disk */ + unsigned *wbuf, /* buffer to write to disk */ *tbuf; /* temporary buffer pointer */ - int i,j,k; /* Counters */ + unsigned u, v, w; /* Counters */ herr_t ret; /* Generic return value */ /* Output message about test being performed */ MESSAGE(5, ("Testing Filling Regular 'hyperslab' Selections\n")); /* Allocate memory buffer */ - wbuf = (unsigned short *)HDmalloc(sizeof(unsigned short)*SPACE7_DIM1*SPACE7_DIM2); + wbuf = (unsigned *)HDmalloc(sizeof(unsigned) * SPACE7_DIM1 * SPACE7_DIM2); CHECK(wbuf, NULL, "HDmalloc"); /* Initialize memory buffer */ - for(i=0, tbuf=wbuf; i<SPACE7_DIM1; i++) - for(j=0; j<SPACE7_DIM2; j++) - *tbuf++=(unsigned short)(i*SPACE7_DIM2)+j; + for(u = 0, tbuf = wbuf; u < SPACE7_DIM1; u++) + for(v = 0; v < SPACE7_DIM2; v++) + *tbuf++ =(u * SPACE7_DIM2) + v; /* Create dataspace for dataset on disk */ sid1 = H5Screate_simple(SPACE7_RANK, dims1, NULL); CHECK(sid1, FAIL, "H5Screate_simple"); /* Select "hyperslab" selection */ - start[0]=2; start[1]=2; - stride[0]=4; stride[1]=4; - count[0]=2; count[1]=2; - block[0]=2; block[1]=2; - ret = H5Sselect_hyperslab(sid1,H5S_SELECT_SET,start,stride,count,block); + start[0] = 2; start[1] = 2; + stride[0] = 4; stride[1] = 4; + count[0] = 2; count[1] = 2; + block[0] = 2; block[1] = 2; + ret = H5Sselect_hyperslab(sid1, H5S_SELECT_SET, start, stride, count, block); CHECK(ret, FAIL, "H5Sselect_hyperslab"); - if(offset!=NULL) { - HDmemcpy(real_offset,offset,SPACE7_RANK*sizeof(hssize_t)); + if(offset != NULL) { + HDmemcpy(real_offset, offset, SPACE7_RANK * sizeof(hssize_t)); /* Set offset, if provided */ - ret = H5Soffset_simple(sid1,real_offset); + ret = H5Soffset_simple(sid1, real_offset); CHECK(ret, FAIL, "H5Soffset_simple"); } /* end if */ else - HDmemset(real_offset,0,SPACE7_RANK*sizeof(hssize_t)); + HDmemset(real_offset, 0, SPACE7_RANK * sizeof(hssize_t)); /* Set fill value */ - fill_value=SPACE7_FILL; + fill_value = SPACE7_FILL; /* Fill selection in memory */ - ret=H5Dfill(&fill_value,H5T_NATIVE_INT,wbuf,H5T_NATIVE_USHORT,sid1); + ret = H5Dfill(&fill_value, H5T_NATIVE_INT, wbuf, H5T_NATIVE_UINT, sid1); CHECK(ret, FAIL, "H5Dfill"); /* Verify memory buffer the hard way... */ - for(i=0, tbuf=wbuf; i<SPACE7_DIM1; i++) - for(j=0; j<SPACE7_DIM2; j++, tbuf++) { - for(k=0; k<(int)num_points; k++) { - if(i==(int)(points[k][0]+real_offset[0]) && j==(int)(points[k][1]+real_offset[1])) { - if(*tbuf!=(unsigned short)fill_value) - TestErrPrintf("Error! j=%d, i=%d, *tbuf=%u, fill_value=%u\n",j,i,(unsigned)*tbuf,(unsigned)fill_value); + for(u = 0, tbuf = wbuf; u < SPACE7_DIM1; u++) + for(v = 0; v < SPACE7_DIM2; v++, tbuf++) { + for(w = 0; w < (unsigned)num_points; w++) { + if(u == (unsigned)(points[w][0] + real_offset[0]) && v == (unsigned)(points[w][1] + real_offset[1])) { + if(*tbuf != (unsigned)fill_value) + TestErrPrintf("Error! v=%u, u=%u, *tbuf=%u, fill_value=%u\n", v, u, *tbuf, (unsigned)fill_value); break; } /* end if */ } /* end for */ - if(k==(int)num_points && *tbuf!=((unsigned short)(i*SPACE7_DIM2)+j)) - TestErrPrintf("Error! j=%d, i=%d, *tbuf=%u, should be: %u\n",j,i,(unsigned)*tbuf,(unsigned)((i*SPACE7_DIM2)+j)); + if(w == (unsigned)num_points && *tbuf != ((u * SPACE7_DIM2) + v)) + TestErrPrintf("Error! v=%d, u=%d, *tbuf=%u, should be: %u\n", v, u, *tbuf, ((u * SPACE7_DIM2) + v)); } /* end for */ /* Initialize the iterator structure */ - iter_info.fill_value=SPACE7_FILL; - iter_info.curr_coord=0; - iter_info.coords=(hsize_t *)points; + iter_info.fill_value = SPACE7_FILL; + iter_info.curr_coord = 0; + iter_info.coords = (hsize_t *)points; /* Add in the offset */ - for(i=0; i<(int)num_points; i++) { - points[i][0] += real_offset[0]; - points[i][1] += real_offset[1]; + for(u = 0; u < (unsigned)num_points; u++) { + points[u][0] = (hsize_t)(points[u][0] + real_offset[0]); + points[u][1] = (hsize_t)(points[u][1] + real_offset[1]); } /* end for */ /* Iterate through selection, verifying correct data */ - ret = H5Diterate(wbuf,H5T_NATIVE_USHORT,sid1,test_select_hyper_iter3,&iter_info); + ret = H5Diterate(wbuf, H5T_NATIVE_UINT, sid1, test_select_hyper_iter3, &iter_info); CHECK(ret, FAIL, "H5Diterate"); /* Close dataspace */ @@ -5407,72 +7435,72 @@ test_select_fill_hyper_irregular(hssize_t *offset) {6,4}, {6,5}, {6,6}, {6,7}, {7,4}, {7,5}, {7,6}, {7,7}, }; - size_t num_points=32; /* Number of points selected */ - size_t num_iter_points=28; /* Number of resulting points */ + size_t num_points = 32; /* Number of points selected */ + size_t num_iter_points = 28; /* Number of resulting points */ int fill_value; /* Fill value */ fill_iter_info iter_info; /* Iterator information structure */ - unsigned short *wbuf, /* buffer to write to disk */ + unsigned *wbuf, /* buffer to write to disk */ *tbuf; /* temporary buffer pointer */ - int i,j,k; /* Counters */ + unsigned u, v, w; /* Counters */ herr_t ret; /* Generic return value */ /* Output message about test being performed */ MESSAGE(5, ("Testing Filling Irregular 'hyperslab' Selections\n")); /* Allocate memory buffer */ - wbuf = (unsigned short *)HDmalloc(sizeof(unsigned short)*SPACE7_DIM1*SPACE7_DIM2); + wbuf = (unsigned *)HDmalloc(sizeof(unsigned) * SPACE7_DIM1 * SPACE7_DIM2); CHECK(wbuf, NULL, "HDmalloc"); /* Initialize memory buffer */ - for(i=0, tbuf=wbuf; i<SPACE7_DIM1; i++) - for(j=0; j<SPACE7_DIM2; j++) - *tbuf++=(unsigned short)(i*SPACE7_DIM2)+j; + for(u = 0, tbuf = wbuf; u < SPACE7_DIM1; u++) + for(v = 0; v < SPACE7_DIM2; v++) + *tbuf++ = (u * SPACE7_DIM2) + v; /* Create dataspace for dataset on disk */ sid1 = H5Screate_simple(SPACE7_RANK, dims1, NULL); CHECK(sid1, FAIL, "H5Screate_simple"); /* Select first "hyperslab" selection */ - start[0]=2; start[1]=2; - count[0]=4; count[1]=4; - ret = H5Sselect_hyperslab(sid1,H5S_SELECT_SET,start,NULL,count,NULL); + start[0] = 2; start[1] = 2; + count[0] = 4; count[1] = 4; + ret = H5Sselect_hyperslab(sid1, H5S_SELECT_SET, start, NULL, count, NULL); CHECK(ret, FAIL, "H5Sselect_hyperslab"); /* Combine with second "hyperslab" selection */ - start[0]=4; start[1]=4; - count[0]=4; count[1]=4; - ret = H5Sselect_hyperslab(sid1,H5S_SELECT_OR,start,NULL,count,NULL); + start[0] = 4; start[1] = 4; + count[0] = 4; count[1] = 4; + ret = H5Sselect_hyperslab(sid1, H5S_SELECT_OR, start, NULL, count, NULL); CHECK(ret, FAIL, "H5Sselect_hyperslab"); - if(offset!=NULL) { - HDmemcpy(real_offset,offset,SPACE7_RANK*sizeof(hssize_t)); + if(offset != NULL) { + HDmemcpy(real_offset, offset, SPACE7_RANK * sizeof(hssize_t)); /* Set offset, if provided */ - ret = H5Soffset_simple(sid1,real_offset); + ret = H5Soffset_simple(sid1, real_offset); CHECK(ret, FAIL, "H5Soffset_simple"); } /* end if */ else - HDmemset(real_offset,0,SPACE7_RANK*sizeof(hssize_t)); + HDmemset(real_offset, 0, SPACE7_RANK * sizeof(hssize_t)); /* Set fill value */ - fill_value=SPACE7_FILL; + fill_value = SPACE7_FILL; /* Fill selection in memory */ - ret=H5Dfill(&fill_value,H5T_NATIVE_INT,wbuf,H5T_NATIVE_USHORT,sid1); + ret = H5Dfill(&fill_value, H5T_NATIVE_INT, wbuf, H5T_NATIVE_UINT, sid1); CHECK(ret, FAIL, "H5Dfill"); /* Verify memory buffer the hard way... */ - for(i=0, tbuf=wbuf; i<SPACE7_DIM1; i++) - for(j=0; j<SPACE7_DIM2; j++, tbuf++) { - for(k=0; k<(int)num_points; k++) { - if(i==(int)(points[k][0]+real_offset[0]) && j==(int)(points[k][1]+real_offset[1])) { - if(*tbuf!=(unsigned short)fill_value) - TestErrPrintf("Error! j=%d, i=%d, *tbuf=%u, fill_value=%u\n",j,i,(unsigned)*tbuf,(unsigned)fill_value); + for(u = 0, tbuf = wbuf; u < SPACE7_DIM1; u++) + for(v = 0; v < SPACE7_DIM2; v++, tbuf++) { + for(w = 0; w < (unsigned)num_points; w++) { + if(u == (unsigned)(points[w][0] + real_offset[0]) && v == (unsigned)(points[w][1] + real_offset[1])) { + if(*tbuf != (unsigned)fill_value) + TestErrPrintf("Error! v=%u, u=%u, *tbuf=%u, fill_value=%u\n", v, u, *tbuf, (unsigned)fill_value); break; } /* end if */ } /* end for */ - if(k==(int)num_points && *tbuf!=((unsigned short)(i*SPACE7_DIM2)+j)) - TestErrPrintf("Error! j=%d, i=%d, *tbuf=%u, should be: %u\n",j,i,(unsigned)*tbuf,(unsigned)((i*SPACE7_DIM2)+j)); + if(w == (unsigned)num_points && *tbuf != ((u * SPACE7_DIM2) + v)) + TestErrPrintf("Error! v=%u, u=%u, *tbuf=%u, should be: %u\n", v, u, *tbuf, ((u * SPACE7_DIM2) + v)); } /* end for */ /* Initialize the iterator structure */ @@ -5481,13 +7509,13 @@ test_select_fill_hyper_irregular(hssize_t *offset) iter_info.coords = (hsize_t *)iter_points; /* Add in the offset */ - for(i=0; i<(int)num_iter_points; i++) { - iter_points[i][0] += real_offset[0]; - iter_points[i][1] += real_offset[1]; + for(u = 0; u < (unsigned)num_iter_points; u++) { + iter_points[u][0] = (hsize_t)(iter_points[u][0] + real_offset[0]); + iter_points[u][1] = (hsize_t)(iter_points[u][1] + real_offset[1]); } /* end for */ /* Iterate through selection, verifying correct data */ - ret = H5Diterate(wbuf, H5T_NATIVE_USHORT, sid1, test_select_hyper_iter3, &iter_info); + ret = H5Diterate(wbuf, H5T_NATIVE_UINT, sid1, test_select_hyper_iter3, &iter_info); CHECK(ret, FAIL, "H5Diterate"); /* Close dataspace */ @@ -7005,6 +9033,2855 @@ test_shape_same(void) CHECK(ret, FAIL, "H5Sclose"); } /* test_shape_same() */ +/**************************************************************** +** +** test_shape_same_dr__smoke_check_1(): +** +** Create a square, 2 D data space (10 X 10), and select +** all of it. +** +** Similarly, create nine, 3 D data spaces (10 X 10 X 10), +** and select (10 X 10 X 1) hyper slabs in each, three with +** the slab parallel to the xy plane, three parallel to the +** xz plane, and three parallel to the yz plane. +** +** Assuming that z is the fastest changing dimension, +** H5S_select_shape_same() should return TRUE when comparing +** the full 2 D space against any hyperslab parallel to the +** yz plane in the 3 D space, and FALSE when comparing the +** full 2 D space against the other two hyper slabs. +** +** Also create two additional 3 D data spaces (10 X 10 X 10), +** and select a (10 X 10 X 2) hyper slab parallel to the yz +** axis in one of them, and two parallel (10 X 10 X 1) hyper +** slabs parallel to the yz axis in the other. +** H5S_select_shape_same() should return FALSE when comparing +** each to the 2 D selection. +** +****************************************************************/ +static void +test_shape_same_dr__smoke_check_1(void) +{ + hid_t small_square_sid; + hid_t small_cube_xy_slice_0_sid; + hid_t small_cube_xy_slice_1_sid; + hid_t small_cube_xy_slice_2_sid; + hid_t small_cube_xz_slice_0_sid; + hid_t small_cube_xz_slice_1_sid; + hid_t small_cube_xz_slice_2_sid; + hid_t small_cube_yz_slice_0_sid; + hid_t small_cube_yz_slice_1_sid; + hid_t small_cube_yz_slice_2_sid; + hid_t small_cube_yz_slice_3_sid; + hid_t small_cube_yz_slice_4_sid; + hsize_t small_cube_dims[] = {10, 10, 10}; + hsize_t start[3]; + hsize_t stride[3]; + hsize_t count[3]; + hsize_t block[3]; + htri_t check; /* Shape comparison return value */ + herr_t ret; /* Generic return value */ + + MESSAGE(7, (" Smoke check 1: Slices through a cube.\n")); + + /* Create the 10 x 10 dataspace */ + small_square_sid = H5Screate_simple(2, small_cube_dims, NULL); + CHECK(small_square_sid, FAIL, "H5Screate_simple"); + + /* Create the 10 X 10 X 10 dataspaces for the hyperslab parallel to the xy axis */ + small_cube_xy_slice_0_sid = H5Screate_simple(3, small_cube_dims, NULL); + CHECK(small_cube_xy_slice_0_sid, FAIL, "H5Screate_simple"); + + small_cube_xy_slice_1_sid = H5Screate_simple(3, small_cube_dims, NULL); + CHECK(small_cube_xy_slice_1_sid, FAIL, "H5Screate_simple"); + + small_cube_xy_slice_2_sid = H5Screate_simple(3, small_cube_dims, NULL); + CHECK(small_cube_xy_slice_2_sid, FAIL, "H5Screate_simple"); + + start[0] = 0; /* x */ + start[1] = 0; /* y */ + start[2] = 0; /* z */ + + /* stride is a bit silly here, since we are only selecting a single */ + /* contiguous plane, but include it anyway, with values large enough */ + /* to ensure that we will only get the single block selected. */ + stride[0] = 20; /* x */ + stride[1] = 20; /* y */ + stride[2] = 20; /* z */ + + count[0] = 1; /* x */ + count[1] = 1; /* y */ + count[2] = 1; /* z */ + + block[0] = 10; /* x */ + block[1] = 10; /* y */ + block[2] = 1; /* z */ + ret = H5Sselect_hyperslab(small_cube_xy_slice_0_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[2] = 5; + ret = H5Sselect_hyperslab(small_cube_xy_slice_1_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[2] = 9; + ret = H5Sselect_hyperslab(small_cube_xy_slice_2_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + + /* Create the 10 X 10 X 10 dataspaces for the hyperslab parallel to the xz axis */ + small_cube_xz_slice_0_sid = H5Screate_simple(3, small_cube_dims, NULL); + CHECK(small_cube_xz_slice_0_sid, FAIL, "H5Screate_simple"); + + small_cube_xz_slice_1_sid = H5Screate_simple(3, small_cube_dims, NULL); + CHECK(small_cube_xz_slice_1_sid, FAIL, "H5Screate_simple"); + + small_cube_xz_slice_2_sid = H5Screate_simple(3, small_cube_dims, NULL); + CHECK(small_cube_xz_slice_2_sid, FAIL, "H5Screate_simple"); + + start[0] = 0; /* x */ + start[1] = 0; /* y */ + start[2] = 0; /* z */ + + /* stride is a bit silly here, since we are only selecting a single */ + /* contiguous chunk, but include it anyway, with values large enough */ + /* to ensure that we will only get the single chunk. */ + stride[0] = 20; /* x */ + stride[1] = 20; /* y */ + stride[2] = 20; /* z */ + + count[0] = 1; /* x */ + count[1] = 1; /* y */ + count[2] = 1; /* z */ + + block[0] = 10; /* x */ + block[1] = 1; /* y */ + block[2] = 10; /* z */ + ret = H5Sselect_hyperslab(small_cube_xz_slice_0_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[1] = 4; + ret = H5Sselect_hyperslab(small_cube_xz_slice_1_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[1] = 9; + ret = H5Sselect_hyperslab(small_cube_xz_slice_2_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + + /* Create the 10 X 10 X 10 dataspaces for the hyperslabs parallel to the yz axis */ + small_cube_yz_slice_0_sid = H5Screate_simple(3, small_cube_dims, NULL); + CHECK(small_cube_yz_slice_0_sid, FAIL, "H5Screate_simple"); + + small_cube_yz_slice_1_sid = H5Screate_simple(3, small_cube_dims, NULL); + CHECK(small_cube_yz_slice_1_sid, FAIL, "H5Screate_simple"); + + small_cube_yz_slice_2_sid = H5Screate_simple(3, small_cube_dims, NULL); + CHECK(small_cube_yz_slice_2_sid, FAIL, "H5Screate_simple"); + + small_cube_yz_slice_3_sid = H5Screate_simple(3, small_cube_dims, NULL); + CHECK(small_cube_yz_slice_3_sid, FAIL, "H5Screate_simple"); + + small_cube_yz_slice_4_sid = H5Screate_simple(3, small_cube_dims, NULL); + CHECK(small_cube_yz_slice_4_sid, FAIL, "H5Screate_simple"); + + start[0] = 0; /* x */ + start[1] = 0; /* y */ + start[2] = 0; /* z */ + + /* stride is a bit silly here, since we are only selecting a single */ + /* contiguous chunk, but include it anyway, with values large enough */ + /* to ensure that we will only get the single chunk. */ + stride[0] = 20; /* x */ + stride[1] = 20; /* y */ + stride[2] = 20; /* z */ + + count[0] = 1; /* x */ + count[1] = 1; /* y */ + count[2] = 1; /* z */ + + block[0] = 1; /* x */ + block[1] = 10; /* y */ + block[2] = 10; /* z */ + + ret = H5Sselect_hyperslab(small_cube_yz_slice_0_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[0] = 4; + ret = H5Sselect_hyperslab(small_cube_yz_slice_1_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[0] = 9; + ret = H5Sselect_hyperslab(small_cube_yz_slice_2_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[0] = 4; + block[0] = 2; + ret = H5Sselect_hyperslab(small_cube_yz_slice_3_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[0] = 3; + block[0] = 1; + ret = H5Sselect_hyperslab(small_cube_yz_slice_4_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[0] = 6; + ret = H5Sselect_hyperslab(small_cube_yz_slice_4_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + + /* setup is done -- run the tests: */ + + /* Compare against "xy" selection */ + check = H5S_select_shape_same_test(small_cube_xy_slice_0_sid, small_square_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + check = H5S_select_shape_same_test(small_cube_xy_slice_1_sid, small_square_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + check = H5S_select_shape_same_test(small_cube_xy_slice_2_sid, small_square_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + + /* Compare against "xz" selection */ + check = H5S_select_shape_same_test(small_cube_xz_slice_0_sid, small_square_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + check = H5S_select_shape_same_test(small_cube_xz_slice_1_sid, small_square_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + check = H5S_select_shape_same_test(small_cube_xz_slice_2_sid, small_square_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + + /* Compare against "yz" selection */ + check = H5S_select_shape_same_test(small_cube_yz_slice_0_sid, small_square_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + check = H5S_select_shape_same_test(small_cube_yz_slice_1_sid, small_square_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + check = H5S_select_shape_same_test(small_cube_yz_slice_2_sid, small_square_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + check = H5S_select_shape_same_test(small_cube_yz_slice_3_sid, small_square_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + check = H5S_select_shape_same_test(small_cube_yz_slice_4_sid, small_square_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + + /* Close dataspaces */ + ret = H5Sclose(small_square_sid); + CHECK(ret, FAIL, "H5Sclose"); + + + ret = H5Sclose(small_cube_xy_slice_0_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(small_cube_xy_slice_1_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(small_cube_xy_slice_2_sid); + CHECK(ret, FAIL, "H5Sclose"); + + + ret = H5Sclose(small_cube_xz_slice_0_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(small_cube_xz_slice_1_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(small_cube_xz_slice_2_sid); + CHECK(ret, FAIL, "H5Sclose"); + + + ret = H5Sclose(small_cube_yz_slice_0_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(small_cube_yz_slice_1_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(small_cube_yz_slice_2_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(small_cube_yz_slice_3_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(small_cube_yz_slice_4_sid); + CHECK(ret, FAIL, "H5Sclose"); + +} /* test_shape_same_dr__smoke_check_1() */ + +/**************************************************************** +** +** test_shape_same_dr__smoke_check_2(): +** +** Create a square, 2 D data space (10 X 10), and select +** a "checker board" hyper slab as follows: +** +** * * - - * * - - * * +** * * - - * * - - * * +** - - * * - - * * - - +** - - * * - - * * - - +** * * - - * * - - * * +** * * - - * * - - * * +** - - * * - - * * - - +** - - * * - - * * - - +** * * - - * * - - * * +** * * - - * * - - * * +** +** where asterisks indicate selected elements, and dashes +** indicate unselected elements. +** +** Similarly, create nine, 3 D data spaces (10 X 10 X 10), +** and select similar (10 X 10 X 1) checker board hyper +** slabs in each, three with the slab parallel to the xy +** plane, three parallel to the xz plane, and three parallel +** to the yz plane. +** +** Assuming that z is the fastest changing dimension, +** H5S_select_shape_same() should return TRUE when comparing +** the 2 D space checker board selection against a checker +** board hyperslab parallel to the yz plane in the 3 D +** space, and FALSE when comparing the 2 D checkerboard +** selection against two hyper slabs parallel to the xy +** or xz planes. +** +** Also create an additional 3 D data spaces (10 X 10 X 10), +** and select a checker board parallel with the yz axis, +** save with some squares being on different planes. +** H5S_select_shape_same() should return FALSE when +** comparing this selection to the 2 D selection. +** +****************************************************************/ +static void +test_shape_same_dr__smoke_check_2(void) +{ + hid_t small_square_sid; + hid_t small_cube_xy_slice_0_sid; + hid_t small_cube_xy_slice_1_sid; + hid_t small_cube_xy_slice_2_sid; + hid_t small_cube_xz_slice_0_sid; + hid_t small_cube_xz_slice_1_sid; + hid_t small_cube_xz_slice_2_sid; + hid_t small_cube_yz_slice_0_sid; + hid_t small_cube_yz_slice_1_sid; + hid_t small_cube_yz_slice_2_sid; + hid_t small_cube_yz_slice_3_sid; + hsize_t small_cube_dims[] = {10, 10, 10}; + hsize_t start[3]; + hsize_t stride[3]; + hsize_t count[3]; + hsize_t block[3]; + htri_t check; /* Shape comparison return value */ + herr_t ret; /* Generic return value */ + + MESSAGE(7, (" Smoke check 2: Checker board slices through a cube.\n")); + + /* Create the 10 x 10 dataspace */ + small_square_sid = H5Screate_simple(2, small_cube_dims, NULL); + CHECK(small_square_sid, FAIL, "H5Screate_simple"); + + start[0] = 0; /* x */ + start[1] = 0; /* y */ + + stride[0] = 4; /* x */ + stride[1] = 4; /* y */ + + count[0] = 3; /* x */ + count[1] = 3; /* y */ + + block[0] = 2; /* x */ + block[1] = 2; /* y */ + ret = H5Sselect_hyperslab(small_square_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[0] = 2; /* x */ + start[1] = 2; /* y */ + + stride[0] = 4; /* x */ + stride[1] = 4; /* y */ + + count[0] = 2; /* x */ + count[1] = 2; /* y */ + + block[0] = 2; /* x */ + block[1] = 2; /* y */ + ret = H5Sselect_hyperslab(small_square_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + + /* Create the 10 X 10 X 10 dataspaces for the hyperslab parallel to the xy axis */ + small_cube_xy_slice_0_sid = H5Screate_simple(3, small_cube_dims, NULL); + CHECK(small_cube_xy_slice_0_sid, FAIL, "H5Screate_simple"); + + small_cube_xy_slice_1_sid = H5Screate_simple(3, small_cube_dims, NULL); + CHECK(small_cube_xy_slice_1_sid, FAIL, "H5Screate_simple"); + + small_cube_xy_slice_2_sid = H5Screate_simple(3, small_cube_dims, NULL); + CHECK(small_cube_xy_slice_2_sid, FAIL, "H5Screate_simple"); + + + start[0] = 0; /* x */ + start[1] = 0; /* y */ + start[2] = 0; /* z */ + + stride[0] = 4; /* x */ + stride[1] = 4; /* y */ + stride[2] = 20; /* z -- large enough that there will only be one slice */ + + count[0] = 3; /* x */ + count[1] = 3; /* y */ + count[2] = 1; /* z */ + + block[0] = 2; /* x */ + block[1] = 2; /* y */ + block[2] = 1; /* z */ + ret = H5Sselect_hyperslab(small_cube_xy_slice_0_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[2] = 3; + ret = H5Sselect_hyperslab(small_cube_xy_slice_1_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[2] = 9; + ret = H5Sselect_hyperslab(small_cube_xy_slice_2_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + + start[0] = 2; /* x */ + start[1] = 2; /* y */ + start[2] = 0; /* z */ + + stride[0] = 4; /* x */ + stride[1] = 4; /* y */ + stride[2] = 20; /* z -- large enough that there will only be one slice */ + + count[0] = 2; /* x */ + count[1] = 2; /* y */ + count[2] = 1; /* z */ + + block[0] = 2; /* x */ + block[1] = 2; /* y */ + block[2] = 1; /* z */ + ret = H5Sselect_hyperslab(small_cube_xy_slice_0_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[2] = 3; + ret = H5Sselect_hyperslab(small_cube_xy_slice_1_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[2] = 9; + ret = H5Sselect_hyperslab(small_cube_xy_slice_2_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + + /* Create the 10 X 10 X 10 dataspaces for the hyperslab parallel to the xz axis */ + small_cube_xz_slice_0_sid = H5Screate_simple(3, small_cube_dims, NULL); + CHECK(small_cube_xz_slice_0_sid, FAIL, "H5Screate_simple"); + + small_cube_xz_slice_1_sid = H5Screate_simple(3, small_cube_dims, NULL); + CHECK(small_cube_xz_slice_1_sid, FAIL, "H5Screate_simple"); + + small_cube_xz_slice_2_sid = H5Screate_simple(3, small_cube_dims, NULL); + CHECK(small_cube_xz_slice_2_sid, FAIL, "H5Screate_simple"); + + + start[0] = 0; /* x */ + start[1] = 0; /* y */ + start[2] = 0; /* z */ + + stride[0] = 4; /* x */ + stride[1] = 20; /* y -- large enough that there will only be one slice */ + stride[2] = 4; /* z */ + + count[0] = 3; /* x */ + count[1] = 1; /* y */ + count[2] = 3; /* z */ + + block[0] = 2; /* x */ + block[1] = 1; /* y */ + block[2] = 2; /* z */ + ret = H5Sselect_hyperslab(small_cube_xz_slice_0_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[1] = 5; + ret = H5Sselect_hyperslab(small_cube_xz_slice_1_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[1] = 9; + ret = H5Sselect_hyperslab(small_cube_xz_slice_2_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[0] = 2; /* x */ + start[1] = 0; /* y */ + start[2] = 2; /* z */ + + stride[0] = 4; /* x */ + stride[1] = 20; /* y -- large enough that there will only be one slice */ + stride[2] = 4; /* z */ + + count[0] = 2; /* x */ + count[1] = 1; /* y */ + count[2] = 2; /* z */ + + block[0] = 2; /* x */ + block[1] = 1; /* y */ + block[2] = 2; /* z */ + ret = H5Sselect_hyperslab(small_cube_xz_slice_0_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[1] = 5; + ret = H5Sselect_hyperslab(small_cube_xz_slice_1_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[1] = 9; + ret = H5Sselect_hyperslab(small_cube_xz_slice_2_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + + /* Create the 10 X 10 X 10 dataspaces for the hyperslabs parallel to the yz axis */ + small_cube_yz_slice_0_sid = H5Screate_simple(3, small_cube_dims, NULL); + CHECK(small_cube_yz_slice_0_sid, FAIL, "H5Screate_simple"); + + small_cube_yz_slice_1_sid = H5Screate_simple(3, small_cube_dims, NULL); + CHECK(small_cube_yz_slice_1_sid, FAIL, "H5Screate_simple"); + + small_cube_yz_slice_2_sid = H5Screate_simple(3, small_cube_dims, NULL); + CHECK(small_cube_yz_slice_2_sid, FAIL, "H5Screate_simple"); + + small_cube_yz_slice_3_sid = H5Screate_simple(3, small_cube_dims, NULL); + CHECK(small_cube_yz_slice_3_sid, FAIL, "H5Screate_simple"); + + start[0] = 0; /* x */ + start[1] = 0; /* y */ + start[2] = 0; /* z */ + + stride[0] = 20; /* x -- large enough that there will only be one slice */ + stride[1] = 4; /* y */ + stride[2] = 4; /* z */ + + count[0] = 1; /* x */ + count[1] = 3; /* y */ + count[2] = 3; /* z */ + + block[0] = 1; /* x */ + block[1] = 2; /* y */ + block[2] = 2; /* z */ + ret = H5Sselect_hyperslab(small_cube_yz_slice_0_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[0] = 8; + ret = H5Sselect_hyperslab(small_cube_yz_slice_1_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[0] = 9; + ret = H5Sselect_hyperslab(small_cube_yz_slice_2_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[0] = 3; + ret = H5Sselect_hyperslab(small_cube_yz_slice_3_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + + start[0] = 0; /* x */ + start[1] = 2; /* y */ + start[2] = 2; /* z */ + + stride[0] = 20; /* x -- large enough that there will only be one slice */ + stride[1] = 4; /* y */ + stride[2] = 4; /* z */ + + count[0] = 1; /* x */ + count[1] = 2; /* y */ + count[2] = 2; /* z */ + + block[0] = 1; /* x */ + block[1] = 2; /* y */ + block[2] = 2; /* z */ + ret = H5Sselect_hyperslab(small_cube_yz_slice_0_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[0] = 8; + ret = H5Sselect_hyperslab(small_cube_yz_slice_1_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[0] = 9; + ret = H5Sselect_hyperslab(small_cube_yz_slice_2_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[0] = 4; + /* This test gets the right answer, but it fails the shape same + * test in an unexpected point. Bring this up with Quincey, as + * the oddness looks like it is not related to my code. + * -- JRM + */ + ret = H5Sselect_hyperslab(small_cube_yz_slice_3_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + + /* setup is done -- run the tests: */ + + /* Compare against "xy" selection */ + check = H5S_select_shape_same_test(small_cube_xy_slice_0_sid, small_square_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + check = H5S_select_shape_same_test(small_cube_xy_slice_1_sid, small_square_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + check = H5S_select_shape_same_test(small_cube_xy_slice_2_sid, small_square_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + + /* Compare against "xz" selection */ + check = H5S_select_shape_same_test(small_cube_xz_slice_0_sid, small_square_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + check = H5S_select_shape_same_test(small_cube_xz_slice_1_sid, small_square_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + check = H5S_select_shape_same_test(small_cube_xz_slice_2_sid, small_square_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + + /* Compare against "yz" selection */ + check = H5S_select_shape_same_test(small_cube_yz_slice_0_sid, small_square_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + check = H5S_select_shape_same_test(small_cube_yz_slice_1_sid, small_square_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + check = H5S_select_shape_same_test(small_cube_yz_slice_2_sid, small_square_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + check = H5S_select_shape_same_test(small_cube_yz_slice_3_sid, small_square_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + + /* Close dataspaces */ + ret = H5Sclose(small_square_sid); + CHECK(ret, FAIL, "H5Sclose"); + + + ret = H5Sclose(small_cube_xy_slice_0_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(small_cube_xy_slice_1_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(small_cube_xy_slice_2_sid); + CHECK(ret, FAIL, "H5Sclose"); + + + ret = H5Sclose(small_cube_xz_slice_0_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(small_cube_xz_slice_1_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(small_cube_xz_slice_2_sid); + CHECK(ret, FAIL, "H5Sclose"); + + + ret = H5Sclose(small_cube_yz_slice_0_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(small_cube_yz_slice_1_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(small_cube_yz_slice_2_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(small_cube_yz_slice_3_sid); + CHECK(ret, FAIL, "H5Sclose"); + +} /* test_shape_same_dr__smoke_check_2() */ + + +/**************************************************************** +** +** test_shape_same_dr__smoke_check_3(): +** +** Create a square, 2 D data space (10 X 10), and select an +** irregular hyper slab as follows: +** +** y +** 9 - - - - - - - - - - +** 8 - - - - - - - - - - +** 7 - - - * * * * - - - +** 6 - - * * * * * - - - +** 5 - - * * - - - - - - +** 4 - - * * - * * - - - +** 3 - - * * - * * - - - +** 2 - - - - - - - - - - +** 1 - - - - - - - - - - +** 0 - - - - - - - - - - +** 0 1 2 3 4 5 6 7 8 9 x +** +** where asterisks indicate selected elements, and dashes +** indicate unselected elements. +** +** Similarly, create nine, 3 D data spaces (10 X 10 X 10), +** and select similar irregular hyper slabs in each, three +** with the slab parallel to the xy plane, three parallel +** to the xz plane, and three parallel to the yz plane. +** Further, translate the irregular slab in 2/3rds of the +** cases. +** +** Assuming that z is the fastest changing dimension, +** H5S_select_shape_same() should return TRUE when +** comparing the 2 D irregular hyperslab selection +** against the irregular hyperslab selections parallel +** to the yz plane in the 3 D space, and FALSE when +** comparing it against the irregular hyper slabs +** selections parallel to the xy or xz planes. +** +****************************************************************/ +static void +test_shape_same_dr__smoke_check_3(void) +{ + hid_t small_square_sid; + hid_t small_cube_xy_slice_0_sid; + hid_t small_cube_xy_slice_1_sid; + hid_t small_cube_xy_slice_2_sid; + hid_t small_cube_xz_slice_0_sid; + hid_t small_cube_xz_slice_1_sid; + hid_t small_cube_xz_slice_2_sid; + hid_t small_cube_yz_slice_0_sid; + hid_t small_cube_yz_slice_1_sid; + hid_t small_cube_yz_slice_2_sid; + hsize_t small_cube_dims[] = {10, 10, 10}; + hsize_t start[3]; + hsize_t stride[3]; + hsize_t count[3]; + hsize_t block[3]; + htri_t check; /* Shape comparison return value */ + herr_t ret; /* Generic return value */ + + MESSAGE(7, (" Smoke check 3: Offset subsets of slices through a cube.\n")); + + /* Create the 10 x 10 dataspace */ + small_square_sid = H5Screate_simple(2, small_cube_dims, NULL); + CHECK(small_square_sid, FAIL, "H5Screate_simple"); + + start[0] = 2; /* x */ + start[1] = 3; /* y */ + + stride[0] = 20; /* x */ + stride[1] = 20; /* y */ + + count[0] = 1; /* x */ + count[1] = 1; /* y */ + + block[0] = 2; /* x */ + block[1] = 4; /* y */ + ret = H5Sselect_hyperslab(small_square_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[0] = 3; /* x */ + start[1] = 6; /* y */ + + stride[0] = 20; /* x */ + stride[1] = 20; /* y */ + + count[0] = 1; /* x */ + count[1] = 1; /* y */ + + block[0] = 4; /* x */ + block[1] = 2; /* y */ + ret = H5Sselect_hyperslab(small_square_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[0] = 5; /* x */ + start[1] = 3; /* y */ + + stride[0] = 20; /* x */ + stride[1] = 20; /* y */ + + count[0] = 1; /* x */ + count[1] = 1; /* y */ + + block[0] = 2; /* x */ + block[1] = 2; /* y */ + ret = H5Sselect_hyperslab(small_square_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + + /* Create the 10 X 10 X 10 dataspaces for the hyperslab parallel to the xy axis */ + small_cube_xy_slice_0_sid = H5Screate_simple(3, small_cube_dims, NULL); + CHECK(small_cube_xy_slice_0_sid, FAIL, "H5Screate_simple"); + + small_cube_xy_slice_1_sid = H5Screate_simple(3, small_cube_dims, NULL); + CHECK(small_cube_xy_slice_1_sid, FAIL, "H5Screate_simple"); + + small_cube_xy_slice_2_sid = H5Screate_simple(3, small_cube_dims, NULL); + CHECK(small_cube_xy_slice_2_sid, FAIL, "H5Screate_simple"); + + + start[0] = 2; /* x */ + start[1] = 3; /* y */ + start[2] = 5; /* z */ + + stride[0] = 20; /* x */ + stride[1] = 20; /* y */ + stride[2] = 20; /* z */ + + count[0] = 1; /* x */ + count[1] = 1; /* y */ + count[2] = 1; /* z */ + + block[0] = 2; /* x */ + block[1] = 4; /* y */ + block[2] = 1; /* z */ + ret = H5Sselect_hyperslab(small_cube_xy_slice_0_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* move the starting point to the origin */ + start[0] -= 1; /* x */ + start[1] -= 2; /* y */ + ret = H5Sselect_hyperslab(small_cube_xy_slice_1_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* move the irregular selection to the upper right hand corner */ + start[0] += 5; /* x */ + start[1] += 5; /* y */ + ret = H5Sselect_hyperslab(small_cube_xy_slice_2_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[0] = 3; /* x */ + start[1] = 6; /* y */ + start[2] = 5; /* z */ + + stride[0] = 20; /* x */ + stride[1] = 20; /* y */ + stride[2] = 20; /* z */ + + count[0] = 1; /* x */ + count[1] = 1; /* y */ + count[2] = 1; /* z */ + + block[0] = 4; /* x */ + block[1] = 2; /* y */ + block[2] = 1; /* z */ + ret = H5Sselect_hyperslab(small_cube_xy_slice_0_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* move the starting point to the origin */ + start[0] -= 1; /* x */ + start[1] -= 2; /* y */ + ret = H5Sselect_hyperslab(small_cube_xy_slice_1_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* move the irregular selection to the upper right hand corner */ + start[0] += 5; /* x */ + start[1] += 5; /* y */ + ret = H5Sselect_hyperslab(small_cube_xy_slice_2_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[0] = 5; /* x */ + start[1] = 3; /* y */ + start[2] = 5; /* z */ + + stride[0] = 20; /* x */ + stride[1] = 20; /* y */ + stride[2] = 20; /* z */ + + count[0] = 1; /* x */ + count[1] = 1; /* y */ + count[2] = 1; /* z */ + + block[0] = 2; /* x */ + block[1] = 2; /* y */ + block[2] = 1; /* z */ + ret = H5Sselect_hyperslab(small_cube_xy_slice_0_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* move the starting point to the origin */ + start[0] -= 1; /* x */ + start[1] -= 2; /* y */ + ret = H5Sselect_hyperslab(small_cube_xy_slice_1_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* move the irregular selection to the upper right hand corner */ + start[0] += 5; /* x */ + start[1] += 5; /* y */ + ret = H5Sselect_hyperslab(small_cube_xy_slice_2_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + + /* Create the 10 X 10 X 10 dataspaces for the hyperslab parallel to the xz axis */ + small_cube_xz_slice_0_sid = H5Screate_simple(3, small_cube_dims, NULL); + CHECK(small_cube_xz_slice_0_sid, FAIL, "H5Screate_simple"); + + small_cube_xz_slice_1_sid = H5Screate_simple(3, small_cube_dims, NULL); + CHECK(small_cube_xz_slice_1_sid, FAIL, "H5Screate_simple"); + + small_cube_xz_slice_2_sid = H5Screate_simple(3, small_cube_dims, NULL); + CHECK(small_cube_xz_slice_2_sid, FAIL, "H5Screate_simple"); + + start[0] = 2; /* x */ + start[1] = 5; /* y */ + start[2] = 3; /* z */ + + stride[0] = 20; /* x */ + stride[1] = 20; /* y */ + stride[2] = 20; /* z */ + + count[0] = 1; /* x */ + count[1] = 1; /* y */ + count[2] = 1; /* z */ + + block[0] = 2; /* x */ + block[1] = 1; /* y */ + block[2] = 4; /* z */ + ret = H5Sselect_hyperslab(small_cube_xz_slice_0_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* move the starting point to the origin */ + start[0] -= 1; /* x */ + start[2] -= 2; /* y */ + ret = H5Sselect_hyperslab(small_cube_xz_slice_1_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* move the irregular selection to the upper right hand corner */ + start[0] += 5; /* x */ + start[2] += 5; /* y */ + ret = H5Sselect_hyperslab(small_cube_xz_slice_2_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[0] = 3; /* x */ + start[1] = 5; /* y */ + start[2] = 6; /* z */ + + stride[0] = 20; /* x */ + stride[1] = 20; /* y */ + stride[2] = 20; /* z */ + + count[0] = 1; /* x */ + count[1] = 1; /* y */ + count[2] = 1; /* z */ + + block[0] = 4; /* x */ + block[1] = 1; /* y */ + block[2] = 2; /* z */ + ret = H5Sselect_hyperslab(small_cube_xz_slice_0_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* move the starting point to the origin */ + start[0] -= 1; /* x */ + start[2] -= 2; /* y */ + ret = H5Sselect_hyperslab(small_cube_xz_slice_1_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* move the irregular selection to the upper right hand corner */ + start[0] += 5; /* x */ + start[2] += 5; /* y */ + ret = H5Sselect_hyperslab(small_cube_xz_slice_2_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[0] = 5; /* x */ + start[1] = 5; /* y */ + start[2] = 3; /* z */ + + stride[0] = 20; /* x */ + stride[1] = 20; /* y */ + stride[2] = 20; /* z */ + + count[0] = 1; /* x */ + count[1] = 1; /* y */ + count[2] = 1; /* z */ + + block[0] = 2; /* x */ + block[1] = 1; /* y */ + block[2] = 2; /* z */ + ret = H5Sselect_hyperslab(small_cube_xz_slice_0_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* move the starting point to the origin */ + start[0] -= 1; /* x */ + start[2] -= 2; /* y */ + ret = H5Sselect_hyperslab(small_cube_xz_slice_1_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* move the irregular selection to the upper right hand corner */ + start[0] += 5; /* x */ + start[2] += 5; /* y */ + ret = H5Sselect_hyperslab(small_cube_xz_slice_2_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + +/* QAK: Start here. + */ + /* Create the 10 X 10 X 10 dataspaces for the hyperslabs parallel to the yz axis */ + small_cube_yz_slice_0_sid = H5Screate_simple(3, small_cube_dims, NULL); + CHECK(small_cube_yz_slice_0_sid, FAIL, "H5Screate_simple"); + + small_cube_yz_slice_1_sid = H5Screate_simple(3, small_cube_dims, NULL); + CHECK(small_cube_yz_slice_1_sid, FAIL, "H5Screate_simple"); + + small_cube_yz_slice_2_sid = H5Screate_simple(3, small_cube_dims, NULL); + CHECK(small_cube_yz_slice_2_sid, FAIL, "H5Screate_simple"); + + start[0] = 8; /* x */ + start[1] = 2; /* y */ + start[2] = 3; /* z */ + + stride[0] = 20; /* x -- large enough that there will only be one slice */ + stride[1] = 20; /* y */ + stride[2] = 20; /* z */ + + count[0] = 1; /* x */ + count[1] = 1; /* y */ + count[2] = 1; /* z */ + + block[0] = 1; /* x */ + block[1] = 2; /* y */ + block[2] = 4; /* z */ + ret = H5Sselect_hyperslab(small_cube_yz_slice_0_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* move the starting point to the origin */ + start[1] -= 1; /* x */ + start[2] -= 2; /* y */ + ret = H5Sselect_hyperslab(small_cube_yz_slice_1_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* move the irregular selection to the upper right hand corner */ + start[0] += 5; /* x */ + start[2] += 5; /* y */ + ret = H5Sselect_hyperslab(small_cube_yz_slice_2_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[0] = 8; /* x */ + start[1] = 3; /* y */ + start[2] = 6; /* z */ + + stride[0] = 20; /* x */ + stride[1] = 20; /* y */ + stride[2] = 20; /* z */ + + count[0] = 1; /* x */ + count[1] = 1; /* y */ + count[2] = 1; /* z */ + + block[0] = 1; /* x */ + block[1] = 4; /* y */ + block[2] = 2; /* z */ + ret = H5Sselect_hyperslab(small_cube_yz_slice_0_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* move the starting point to the origin */ + start[1] -= 1; /* x */ + start[2] -= 2; /* y */ + ret = H5Sselect_hyperslab(small_cube_yz_slice_1_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* move the irregular selection to the upper right hand corner */ + start[0] += 5; /* x */ + start[2] += 5; /* y */ + ret = H5Sselect_hyperslab(small_cube_yz_slice_2_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[0] = 8; /* x */ + start[1] = 5; /* y */ + start[2] = 3; /* z */ + + stride[0] = 20; /* x */ + stride[1] = 20; /* y */ + stride[2] = 20; /* z */ + + count[0] = 1; /* x */ + count[1] = 1; /* y */ + count[2] = 1; /* z */ + + block[0] = 1; /* x */ + block[1] = 2; /* y */ + block[2] = 2; /* z */ + ret = H5Sselect_hyperslab(small_cube_yz_slice_0_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* move the starting point to the origin */ + start[1] -= 1; /* x */ + start[2] -= 2; /* y */ + ret = H5Sselect_hyperslab(small_cube_yz_slice_1_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* move the irregular selection to the upper right hand corner */ + start[0] += 5; /* x */ + start[2] += 5; /* y */ + ret = H5Sselect_hyperslab(small_cube_yz_slice_2_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + + /* setup is done -- run the tests: */ + + /* Compare against "xy" selection */ + check = H5S_select_shape_same_test(small_cube_xy_slice_0_sid, small_square_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + check = H5S_select_shape_same_test(small_cube_xy_slice_1_sid, small_square_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + check = H5S_select_shape_same_test(small_cube_xy_slice_2_sid, small_square_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + + /* Compare against "xz" selection */ + check = H5S_select_shape_same_test(small_cube_xz_slice_0_sid, small_square_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + check = H5S_select_shape_same_test(small_cube_xz_slice_1_sid, small_square_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + check = H5S_select_shape_same_test(small_cube_xz_slice_2_sid, small_square_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + + /* Compare against "yz" selection */ + check = H5S_select_shape_same_test(small_cube_yz_slice_0_sid, small_square_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + check = H5S_select_shape_same_test(small_cube_yz_slice_1_sid, small_square_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + check = H5S_select_shape_same_test(small_cube_yz_slice_2_sid, small_square_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + + /* Close dataspaces */ + ret = H5Sclose(small_square_sid); + CHECK(ret, FAIL, "H5Sclose"); + + + ret = H5Sclose(small_cube_xy_slice_0_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(small_cube_xy_slice_1_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(small_cube_xy_slice_2_sid); + CHECK(ret, FAIL, "H5Sclose"); + + + ret = H5Sclose(small_cube_xz_slice_0_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(small_cube_xz_slice_1_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(small_cube_xz_slice_2_sid); + CHECK(ret, FAIL, "H5Sclose"); + + + ret = H5Sclose(small_cube_yz_slice_0_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(small_cube_yz_slice_1_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(small_cube_yz_slice_2_sid); + CHECK(ret, FAIL, "H5Sclose"); + +} /* test_shape_same_dr__smoke_check_3() */ + + +/**************************************************************** +** +** test_shape_same_dr__smoke_check_4(): +** +** Create a square, 2 D data space (10 X 10), and select +** the entire space. +** +** Similarly, create 3 D and 4 D data spaces: +** +** (1 X 10 X 10) +** (10 X 1 X 10) +** (10 X 10 X 1) +** (10 X 10 X 10) +** +** (1 X 1 X 10 X 10) +** (1 X 10 X 1 X 10) +** (1 X 10 X 10 X 1) +** (10 X 1 X 1 X 10) +** (10 X 1 X 10 X 1) +** (10 X 10 X 1 X 1) +** (10 X 1 X 10 X 10) +** +** And select these entire spaces as well. +** +** Compare the 2 D space against all the other spaces +** with H5S_select_shape_same(). The (1 X 10 X 10) & +** (1 X 1 X 10 X 10) should return TRUE. All others +** should return FALSE. +** +****************************************************************/ +static void +test_shape_same_dr__smoke_check_4(void) +{ + hid_t square_sid; + hid_t three_d_space_0_sid; + hid_t three_d_space_1_sid; + hid_t three_d_space_2_sid; + hid_t three_d_space_3_sid; + hid_t four_d_space_0_sid; + hid_t four_d_space_1_sid; + hid_t four_d_space_2_sid; + hid_t four_d_space_3_sid; + hid_t four_d_space_4_sid; + hid_t four_d_space_5_sid; + hid_t four_d_space_6_sid; + hsize_t dims[] = {10, 10, 10, 10}; + htri_t check; /* Shape comparison return value */ + herr_t ret; /* Generic return value */ + + MESSAGE(7, (" Smoke check 4: Spaces of different dimension but same size.\n")); + + /* Create the 10 x 10 dataspace */ + square_sid = H5Screate_simple(2, dims, NULL); + CHECK(square_sid, FAIL, "H5Screate_simple"); + + /* create (1 X 10 X 10) data space */ + dims[0] = 1; + dims[1] = 10; + dims[2] = 10; + three_d_space_0_sid = H5Screate_simple(3, dims, NULL); + CHECK(three_d_space_0_sid, FAIL, "H5Screate_simple"); + + /* create (10 X 1 X 10) data space */ + dims[0] = 10; + dims[1] = 1; + dims[2] = 10; + three_d_space_1_sid = H5Screate_simple(3, dims, NULL); + CHECK(three_d_space_1_sid, FAIL, "H5Screate_simple"); + + /* create (10 X 10 X 1) data space */ + dims[0] = 10; + dims[1] = 10; + dims[2] = 1; + three_d_space_2_sid = H5Screate_simple(3, dims, NULL); + CHECK(three_d_space_2_sid, FAIL, "H5Screate_simple"); + + /* create (10 X 10 X 10) data space */ + dims[0] = 10; + dims[1] = 10; + dims[2] = 10; + three_d_space_3_sid = H5Screate_simple(3, dims, NULL); + CHECK(three_d_space_3_sid, FAIL, "H5Screate_simple"); + + + /* create (1 X 1 X 10 X 10) data space */ + dims[0] = 1; + dims[1] = 1; + dims[2] = 10; + dims[3] = 10; + four_d_space_0_sid = H5Screate_simple(4, dims, NULL); + CHECK(four_d_space_0_sid, FAIL, "H5Screate_simple"); + + /* create (1 X 10 X 1 X 10) data space */ + dims[0] = 1; + dims[1] = 10; + dims[2] = 1; + dims[3] = 10; + four_d_space_1_sid = H5Screate_simple(4, dims, NULL); + CHECK(four_d_space_1_sid, FAIL, "H5Screate_simple"); + + /* create (1 X 10 X 10 X 1) data space */ + dims[0] = 1; + dims[1] = 10; + dims[2] = 10; + dims[3] = 1; + four_d_space_2_sid = H5Screate_simple(4, dims, NULL); + CHECK(four_d_space_2_sid, FAIL, "H5Screate_simple"); + + /* create (10 X 1 X 1 X 10) data space */ + dims[0] = 10; + dims[1] = 1; + dims[2] = 1; + dims[3] = 10; + four_d_space_3_sid = H5Screate_simple(4, dims, NULL); + CHECK(four_d_space_3_sid, FAIL, "H5Screate_simple"); + + /* create (10 X 1 X 10 X 1) data space */ + dims[0] = 10; + dims[1] = 1; + dims[2] = 10; + dims[3] = 1; + four_d_space_4_sid = H5Screate_simple(4, dims, NULL); + CHECK(four_d_space_4_sid, FAIL, "H5Screate_simple"); + + /* create (10 X 10 X 1 X 1) data space */ + dims[0] = 10; + dims[1] = 10; + dims[2] = 1; + dims[3] = 1; + four_d_space_5_sid = H5Screate_simple(4, dims, NULL); + CHECK(four_d_space_5_sid, FAIL, "H5Screate_simple"); + + /* create (10 X 1 X 10 X 10) data space */ + dims[0] = 10; + dims[1] = 1; + dims[2] = 10; + dims[3] = 10; + four_d_space_6_sid = H5Screate_simple(4, dims, NULL); + CHECK(four_d_space_6_sid, FAIL, "H5Screate_simple"); + + + /* setup is done -- run the tests: */ + + check = H5S_select_shape_same_test(three_d_space_0_sid, square_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + check = H5S_select_shape_same_test(three_d_space_1_sid, square_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + check = H5S_select_shape_same_test(three_d_space_2_sid, square_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + check = H5S_select_shape_same_test(three_d_space_3_sid, square_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + + check = H5S_select_shape_same_test(four_d_space_0_sid, square_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + check = H5S_select_shape_same_test(four_d_space_1_sid, square_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + check = H5S_select_shape_same_test(four_d_space_2_sid, square_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + check = H5S_select_shape_same_test(four_d_space_3_sid, square_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + check = H5S_select_shape_same_test(four_d_space_4_sid, square_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + check = H5S_select_shape_same_test(four_d_space_5_sid, square_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + check = H5S_select_shape_same_test(four_d_space_6_sid, square_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + + /* Close dataspaces */ + ret = H5Sclose(square_sid); + CHECK(ret, FAIL, "H5Sclose"); + + + ret = H5Sclose(three_d_space_0_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(three_d_space_1_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(three_d_space_2_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(three_d_space_3_sid); + CHECK(ret, FAIL, "H5Sclose"); + + + ret = H5Sclose(four_d_space_0_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(four_d_space_1_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(four_d_space_2_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(four_d_space_3_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(four_d_space_4_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(four_d_space_5_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(four_d_space_6_sid); + CHECK(ret, FAIL, "H5Sclose"); + +} /* test_shape_same_dr__smoke_check_4() */ + +/**************************************************************** +** +** test_shape_same_dr__full_space_vs_slice(): Tests selection +** of a full n-cube data space vs an n-dimensional slice of +** of an m-cube (m > n) in a call to H5S_select_shape_same(). +** Note that this test does not require the n-cube and the +** n-dimensional slice to have the same rank (although +** H5S_select_shape_same() should always return FALSE if +** they don't). +** +** Per Quincey's suggestion, only test up to 5 dimensional +** spaces. +** +****************************************************************/ +static void +test_shape_same_dr__full_space_vs_slice(int test_num, + int small_rank, + int large_rank, + int offset, + hsize_t edge_size, + hbool_t dim_selected[], + hbool_t expected_result) +{ + char test_desc_0[128]; + char test_desc_1[128]; + int i; + hid_t n_cube_0_sid; /* the fully selected hyper cube */ + hid_t n_cube_1_sid; /* the hyper cube in which a slice is selected */ + hsize_t dims[SS_DR_MAX_RANK]; + hsize_t start[SS_DR_MAX_RANK]; + hsize_t * start_ptr; + hsize_t stride[SS_DR_MAX_RANK]; + hsize_t * stride_ptr; + hsize_t count[SS_DR_MAX_RANK]; + hsize_t * count_ptr; + hsize_t block[SS_DR_MAX_RANK]; + hsize_t * block_ptr; + htri_t check; /* Shape comparison return value */ + herr_t ret; /* Generic return value */ + + HDassert( 0 < small_rank ); + HDassert( small_rank <= large_rank ); + HDassert( large_rank <= SS_DR_MAX_RANK ); + HDassert( 0 <= offset ); + HDassert( offset < large_rank ); + HDassert( edge_size > 0 ); + HDassert( edge_size <= 1000 ); + + sprintf(test_desc_0, + "\tn-cube slice through m-cube (n <= m) test %d.\n", + test_num); + MESSAGE(7, (test_desc_0)); + + /* This statement must be updated if SS_DR_MAX_RANK is changed */ + sprintf(test_desc_1, + "\t\tranks: %d/%d offset: %d dim_selected: %d/%d/%d/%d/%d.\n", + small_rank, large_rank, offset, + (int)dim_selected[0], + (int)dim_selected[1], + (int)dim_selected[2], + (int)dim_selected[3], + (int)dim_selected[4]); + MESSAGE(7, (test_desc_1)); + + /* copy the edge size into the dims array */ + for(i = 0; i < SS_DR_MAX_RANK; i++) + dims[i] = edge_size; + + /* Create the small n-cube */ + n_cube_0_sid = H5Screate_simple(small_rank, dims, NULL); + CHECK(n_cube_0_sid, FAIL, "H5Screate_simple"); + + + /* Create the large n-cube */ + n_cube_1_sid = H5Screate_simple(large_rank, dims, NULL); + CHECK(n_cube_1_sid, FAIL, "H5Screate_simple"); + + /* set up start, stride, count, and block for the hyperslab selection */ + for(i = 0; i < SS_DR_MAX_RANK; i++) { + stride[i] = 2 * edge_size; /* a bit silly in this case */ + count[i] = 1; + if(dim_selected[i]) { + start[i] = 0; + block[i] = edge_size; + } /* end if */ + else { + start[i] = (hsize_t)offset; + block[i] = 1; + } /* end else */ + } /* end for */ + + /* since large rank may be less than SS_DR_MAX_RANK, we may not + * use the entire start, stride, count, and block arrays. This + * is a problem, since it is inconvenient to set up the dim_selected + * array to reflect the large rank, and thus if large_rank < + * SS_DR_MAX_RANK, we need to hide the lower index entries + * from H5Sselect_hyperslab(). + * + * Do this by setting up pointers to the first valid entry in start, + * stride, count, and block below, and pass these pointers in + * to H5Sselect_hyperslab() instead of the array base addresses. + */ + + i = SS_DR_MAX_RANK - large_rank; + HDassert(i >= 0); + + start_ptr = &(start[i]); + stride_ptr = &(stride[i]); + count_ptr = &(count[i]); + block_ptr = &(block[i]); + + + /* select the hyper slab */ + ret = H5Sselect_hyperslab(n_cube_1_sid, H5S_SELECT_SET, + start_ptr, stride_ptr, count_ptr, block_ptr); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + + /* setup is done -- run the test: */ + check = H5S_select_shape_same_test(n_cube_0_sid, n_cube_1_sid); + VERIFY(check, expected_result, "test_shape_same_dr__full_space_vs_slice"); + + + /* Close dataspaces */ + ret = H5Sclose(n_cube_0_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(n_cube_1_sid); + CHECK(ret, FAIL, "H5Sclose"); + +} /* test_shape_same_dr__full_space_vs_slice() */ + + +/**************************************************************** +** +** test_shape_same_dr__run_full_space_vs_slice_tests(): +** +** Run the est_shape_same_dr__full_space_vs_slice() test +** over a variety of ranks and offsets. +** +** At present, we test H5S_select_shape_same() with +** fully selected 1, 2, 3, and 4 cubes as one parameter, and +** 1, 2, 3, and 4 dimensional slices through a n-cube of rank +** no more than 5 (and at least the rank of the slice). +** We stop at rank 5, as Quincey suggested that it would be +** sufficient. +** +** All the n-cubes will have lengths of the same size, so +** H5S_select_shape_same() should return true iff: +** +** 1) the rank for the fully selected n cube equals the +** number of dimensions selected in the slice through the +** m-cube (m >= n). +** +** 2) The dimensions selected in the slice through the m-cube +** are the dimesnions with the most quickly changing +** indices. +** +****************************************************************/ +static void +test_shape_same_dr__run_full_space_vs_slice_tests(void) +{ + hbool_t dim_selected[5]; + hbool_t expected_result; + int i, j; + int v, w, x, y, z; + int test_num = 0; + int small_rank; + int large_rank; + hsize_t edge_size = 10; + + for(large_rank = 1; large_rank <= 5; large_rank++) { + for(small_rank = 1; small_rank <= large_rank; small_rank++) { + v = 0; + do { + if(v == 0) + dim_selected[0] = FALSE; + else + dim_selected[0] = TRUE; + + w = 0; + do { + if(w == 0) + dim_selected[1] = FALSE; + else + dim_selected[1] = TRUE; + + x = 0; + do { + if(x == 0) + dim_selected[2] = FALSE; + else + dim_selected[2] = TRUE; + + y = 0; + do { + if(y == 0) + dim_selected[3] = FALSE; + else + dim_selected[3] = TRUE; + + z = 0; + do { + if(z == 0) + dim_selected[4] = FALSE; + else + dim_selected[4] = TRUE; + + /* compute the expected result: */ + i = 0; + j = 4; + expected_result = TRUE; + while((i < small_rank) && expected_result) { + if(!dim_selected[j]) + expected_result = FALSE; + i++; + j--; + } /* end while */ + + while((i < large_rank) && expected_result) { + if(dim_selected[j]) + expected_result = FALSE; + i++; + j--; + } /* end while */ + + + /* everything is set up -- run the tests */ + + test_shape_same_dr__full_space_vs_slice + ( + test_num++, + small_rank, + large_rank, + 0, + edge_size, + dim_selected, + expected_result + ); + + test_shape_same_dr__full_space_vs_slice + ( + test_num++, + small_rank, + large_rank, + large_rank / 2, + edge_size, + dim_selected, + expected_result + ); + + test_shape_same_dr__full_space_vs_slice + ( + test_num++, + small_rank, + large_rank, + large_rank - 1, + edge_size, + dim_selected, + expected_result + ); + + z++; + } while((z < 2) && (large_rank >= 1)); + + y++; + } while((y < 2) && (large_rank >= 2)); + + x++; + } while((x < 2) && (large_rank >= 3)); + + w++; + } while((w < 2) && (large_rank >= 4)); + + v++; + } while((v < 2) && (large_rank >= 5)); + } /* end for */ + } /* end for */ + +} /* test_shape_same_dr__run_full_space_vs_slice_tests() */ + + +/**************************************************************** +** +** test_shape_same_dr__checkerboard(): Tests selection of a +** "checker board" subset of a full n-cube data space vs +** a "checker board" n-dimensional slice of an m-cube (m > n). +** in a call to H5S_select_shape_same(). +** +** Note that this test does not require the n-cube and the +** n-dimensional slice to have the same rank (although +** H5S_select_shape_same() should always return FALSE if +** they don't). +** +** Per Quincey's suggestion, only test up to 5 dimensional +** spaces. +** +****************************************************************/ +static void +test_shape_same_dr__checkerboard(int test_num, + int small_rank, + int large_rank, + int offset, + hsize_t edge_size, + hsize_t checker_size, + hbool_t dim_selected[], + hbool_t expected_result) +{ + char test_desc_0[128]; + char test_desc_1[128]; + int i; + int dims_selected = 0; + hid_t n_cube_0_sid; /* the checker board selected + * hyper cube + */ + hid_t n_cube_1_sid; /* the hyper cube in which a + * checkerboard slice is selected + */ + hsize_t dims[SS_DR_MAX_RANK]; + hsize_t base_start[2]; + hsize_t start[SS_DR_MAX_RANK]; + hsize_t * start_ptr; + hsize_t base_stride[2]; + hsize_t stride[SS_DR_MAX_RANK]; + hsize_t * stride_ptr; + hsize_t base_count[2]; + hsize_t count[SS_DR_MAX_RANK]; + hsize_t * count_ptr; + hsize_t base_block[2]; + hsize_t block[SS_DR_MAX_RANK]; + hsize_t * block_ptr; + htri_t check; /* Shape comparison return value */ + herr_t ret; /* Generic return value */ + + HDassert( 0 < small_rank ); + HDassert( small_rank <= large_rank ); + HDassert( large_rank <= SS_DR_MAX_RANK ); + HDassert( 0 < checker_size ); + HDassert( checker_size <= edge_size ); + HDassert( edge_size <= 1000 ); + HDassert( 0 <= offset ); + HDassert( offset < (int)edge_size ); + + for(i = SS_DR_MAX_RANK - large_rank; i < SS_DR_MAX_RANK; i++) + if(dim_selected[i] == TRUE) + dims_selected++; + + HDassert( dims_selected >= 0 ); + HDassert( dims_selected <= large_rank ); + + sprintf(test_desc_0, + "\tcheckerboard n-cube slice through m-cube (n <= m) test %d.\n", + test_num); + MESSAGE(7, (test_desc_0)); + + /* This statement must be updated if SS_DR_MAX_RANK is changed */ + sprintf(test_desc_1, + "\tranks: %d/%d edge/chkr size: %d/%d offset: %d dim_selected: %d/%d/%d/%d/%d:%d.\n", + small_rank, large_rank, + (int)edge_size, (int)checker_size, + offset, + (int)dim_selected[0], + (int)dim_selected[1], + (int)dim_selected[2], + (int)dim_selected[3], + (int)dim_selected[4], + dims_selected); + MESSAGE(7, (test_desc_1)); + + /* copy the edge size into the dims array */ + for(i = 0; i < SS_DR_MAX_RANK; i++) + dims[i] = edge_size; + + /* Create the small n-cube */ + n_cube_0_sid = H5Screate_simple(small_rank, dims, NULL); + CHECK(n_cube_0_sid, FAIL, "H5Screate_simple"); + + /* Select a "checkerboard" pattern in the small n-cube. + * + * In the 1-D case, the "checkerboard" would look like this: + * + * * * - - * * - - * * + * + * and in the 2-D case, it would look like this: + * + * * * - - * * - - * * + * * * - - * * - - * * + * - - * * - - * * - - + * - - * * - - * * - - + * * * - - * * - - * * + * * * - - * * - - * * + * - - * * - - * * - - + * - - * * - - * * - - + * * * - - * * - - * * + * * * - - * * - - * * + * + * In both cases, asterisks indicate selected elements, + * and dashes indicate unselected elements. + * + * 3-D and 4-D ascii art is somewhat painful, so I'll + * leave those selections to your imagination. :-) + * + * Note, that since the edge_size and checker_size are + * parameters that are passed in, the selection need + * not look exactly like the selection shown above. + * At present, the function allows checker sizes that + * are not even divisors of the edge size -- thus + * something like the following is also possible: + * + * * * * - - - * * * - + * * * * - - - * * * - + * * * * - - - * * * - + * - - - * * * - - - * + * - - - * * * - - - * + * - - - * * * - - - * + * * * * - - - * * * - + * * * * - - - * * * - + * * * * - - - * * * - + * - - - * * * - - - * + * + * As the above pattern can't be selected in one + * call to H5Sselect_hyperslab(), and since the + * values in the start, stride, count, and block + * arrays will be repeated over all entries in + * the selected space case, and over all selected + * dimensions in the selected hyperslab case, we + * compute these values first and store them in + * in the base_start, base_stride, base_count, + * and base_block arrays. + */ + + base_start[0] = 0; + base_start[1] = checker_size; + + base_stride[0] = 2 * checker_size; + base_stride[1] = 2 * checker_size; + + /* Note that the following computation depends on the C99 + * requirement that integer division discard any fraction + * (truncation towards zero) to function correctly. As we + * now require C99, this shouldn't be a problem, but noting + * it may save us some pain if we are ever obliged to support + * pre-C99 compilers again. + */ + + base_count[0] = edge_size / (checker_size * 2); + if((edge_size % (checker_size * 2)) > 0) + base_count[0]++; + + base_count[1] = (edge_size - checker_size) / (checker_size * 2); + if(((edge_size - checker_size) % (checker_size * 2)) > 0) + base_count[1]++; + + base_block[0] = checker_size; + base_block[1] = checker_size; + + /* now setup start, stride, count, and block arrays for + * the first call to H5Sselect_hyperslab(). + */ + for(i = 0; i < SS_DR_MAX_RANK; i++) { + start[i] = base_start[0]; + stride[i] = base_stride[0]; + count[i] = base_count[0]; + block[i] = base_block[0]; + } /* end for */ + + ret = H5Sselect_hyperslab(n_cube_0_sid, H5S_SELECT_SET, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* if small_rank == 1, or if edge_size == checker_size, we + * are done, as either there is no added dimension in which + * to place offset selected "checkers". + * + * Otherwise, set up start, stride, count and block, and + * make the additional selection. + */ + + if((small_rank > 1) && (checker_size < edge_size)) { + for(i = 0; i < SS_DR_MAX_RANK; i++) { + start[i] = base_start[1]; + stride[i] = base_stride[1]; + count[i] = base_count[1]; + block[i] = base_block[1]; + } /* end for */ + + ret = H5Sselect_hyperslab(n_cube_0_sid, H5S_SELECT_OR, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + } /* end if */ + + /* Wierdness alert: + * + * Some how, it seems that selections can extend beyond the + * boundaries of the target data space -- hence the following + * code to manually clip the selection back to the data space + * proper. + */ + for(i = 0; i < SS_DR_MAX_RANK; i++) { + start[i] = 0; + stride[i] = edge_size; + count[i] = 1; + block[i] = edge_size; + } /* end for */ + + ret = H5Sselect_hyperslab(n_cube_0_sid, H5S_SELECT_AND, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + + /* Create the large n-cube */ + n_cube_1_sid = H5Screate_simple(large_rank, dims, NULL); + CHECK(n_cube_1_sid, FAIL, "H5Screate_simple"); + + + /* Now select the checkerboard selection in the (possibly larger) n-cube. + * + * Since we have already calculated the base start, stride, count, + * and block, re-use the values in setting up start, stride, count, + * and block. + */ + for(i = 0; i < SS_DR_MAX_RANK; i++) { + if(dim_selected[i]) { + start[i] = base_start[0]; + stride[i] = base_stride[0]; + count[i] = base_count[0]; + block[i] = base_block[0]; + } /* end if */ + else { + start[i] = (hsize_t)offset; + stride[i] = (hsize_t)(2 * edge_size); + count[i] = 1; + block[i] = 1; + } /* end else */ + } /* end for */ + + /* Since large rank may be less than SS_DR_MAX_RANK, we may not + * use the entire start, stride, count, and block arrays. This + * is a problem, since it is inconvenient to set up the dim_selected + * array to reflect the large rank, and thus if large_rank < + * SS_DR_MAX_RANK, we need to hide the lower index entries + * from H5Sselect_hyperslab(). + * + * Do this by setting up pointers to the first valid entry in start, + * stride, count, and block below, and pass these pointers in + * to H5Sselect_hyperslab() instead of the array base addresses. + */ + + i = SS_DR_MAX_RANK - large_rank; + HDassert( i >= 0 ); + + start_ptr = &(start[i]); + stride_ptr = &(stride[i]); + count_ptr = &(count[i]); + block_ptr = &(block[i]); + + /* select the hyper slab */ + ret = H5Sselect_hyperslab(n_cube_1_sid, H5S_SELECT_SET, + start_ptr, stride_ptr, count_ptr, block_ptr); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* As before, if the number of dimensions selected is less than or + * equal to 1, or if edge_size == checker_size, we are done, as + * either there is no added dimension in which to place offset selected + * "checkers", or the hyperslab is completely occupied by one + * "checker". + * + * Otherwise, set up start, stride, count and block, and + * make the additional selection. + */ + if((dims_selected > 1) && (checker_size < edge_size)) { + for(i = 0; i < SS_DR_MAX_RANK; i++) { + if(dim_selected[i]) { + start[i] = base_start[1]; + stride[i] = base_stride[1]; + count[i] = base_count[1]; + block[i] = base_block[1]; + } /* end if */ + else { + start[i] = (hsize_t)offset; + stride[i] = (hsize_t)(2 * edge_size); + count[i] = 1; + block[i] = 1; + } /* end else */ + } /* end for */ + + ret = H5Sselect_hyperslab(n_cube_1_sid, H5S_SELECT_OR, + start_ptr, stride_ptr, count_ptr, block_ptr); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + } /* end if */ + + + /* Wierdness alert: + * + * Again, it seems that selections can extend beyond the + * boundaries of the target data space -- hence the following + * code to manually clip the selection back to the data space + * proper. + */ + for(i = 0; i < SS_DR_MAX_RANK; i++) { + start[i] = 0; + stride[i] = edge_size; + count[i] = 1; + block[i] = edge_size; + } /* end for */ + + ret = H5Sselect_hyperslab(n_cube_1_sid, H5S_SELECT_AND, + start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* setup is done -- run the test: */ + check = H5S_select_shape_same_test(n_cube_0_sid, n_cube_1_sid); + VERIFY(check, expected_result, "test_shape_same_dr__checkerboard"); + + + /* Close dataspaces */ + ret = H5Sclose(n_cube_0_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(n_cube_1_sid); + CHECK(ret, FAIL, "H5Sclose"); + +} /* test_shape_same_dr__checkerboard() */ + + +/**************************************************************** +** +** test_shape_same_dr__run_checkerboard_tests(): +** +** In this set of tests, we test H5S_select_shape_same() +** with a "checkerboard" selection of 1, 2, 3, and 4 cubes as +** one parameter, and 1, 2, 3, and 4 dimensional checkerboard +** slices through a n-cube of rank no more than 5 (and at +** least the rank of the slice). +** +** All the n-cubes will have lengths of the same size, so +** H5S_select_shape_same() should return true iff: +** +** 1) the rank of the n cube equals the number of dimensions +** selected in the checker board slice through the m-cube +** (m >= n). +** +** 2) The dimensions selected in the checkerboard slice +** through the m-cube are the dimensions with the most +** quickly changing indices. +** +****************************************************************/ +static void +test_shape_same_dr__run_checkerboard_tests(void) +{ + hbool_t dim_selected[5]; + hbool_t expected_result; + int i, j; + int v, w, x, y, z; + int test_num = 0; + int small_rank; + int large_rank; + + for(large_rank = 1; large_rank <= 5; large_rank++) { + for(small_rank = 1; small_rank <= large_rank; small_rank++) { + v = 0; + do { + if(v == 0) + dim_selected[0] = FALSE; + else + dim_selected[0] = TRUE; + + w = 0; + do { + if(w == 0) + dim_selected[1] = FALSE; + else + dim_selected[1] = TRUE; + + x = 0; + do { + if(x == 0) + dim_selected[2] = FALSE; + else + dim_selected[2] = TRUE; + + y = 0; + do { + if(y == 0) + dim_selected[3] = FALSE; + else + dim_selected[3] = TRUE; + + z = 0; + do { + if(z == 0) + dim_selected[4] = FALSE; + else + dim_selected[4] = TRUE; + + + /* compute the expected result: */ + i = 0; + j = 4; + expected_result = TRUE; + while((i < small_rank) && expected_result) { + if(!dim_selected[j]) + expected_result = FALSE; + i++; + j--; + } /* end while */ + + while((i < large_rank) && expected_result) { + if(dim_selected[j]) + expected_result = FALSE; + i++; + j--; + } /* end while */ + + + /* everything is set up -- run the tests */ + + /* run test with edge size 16, checker + * size 1, and a variety of offsets + */ + test_shape_same_dr__checkerboard + ( + test_num++, + small_rank, + large_rank, + /* offset */ 0, + /* edge_size */ 16, + /* checker_size */ 1, + dim_selected, + expected_result + ); + + test_shape_same_dr__checkerboard + ( + test_num++, + small_rank, + large_rank, + /* offset */ 5, + /* edge_size */ 16, + /* checker_size */ 1, + dim_selected, + expected_result + ); + + test_shape_same_dr__checkerboard + ( + test_num++, + small_rank, + large_rank, + /* offset */ 15, + /* edge_size */ 16, + /* checker_size */ 1, + dim_selected, + expected_result + ); + + + /* run test with edge size 10, checker + * size 2, and a variety of offsets + */ + test_shape_same_dr__checkerboard + ( + test_num++, + small_rank, + large_rank, + /* offset */ 0, + /* edge_size */ 10, + /* checker_size */ 2, + dim_selected, + expected_result + ); + + test_shape_same_dr__checkerboard + ( + test_num++, + small_rank, + large_rank, + /* offset */ 5, + /* edge_size */ 10, + /* checker_size */ 2, + dim_selected, + expected_result + ); + + test_shape_same_dr__checkerboard + ( + test_num++, + small_rank, + large_rank, + /* offset */ 9, + /* edge_size */ 10, + /* checker_size */ 2, + dim_selected, + expected_result + ); + + + /* run test with edge size 10, checker + * size 3, and a variety of offsets + */ + test_shape_same_dr__checkerboard + ( + test_num++, + small_rank, + large_rank, + /* offset */ 0, + /* edge_size */ 10, + /* checker_size */ 3, + dim_selected, + expected_result + ); + + test_shape_same_dr__checkerboard + ( + test_num++, + small_rank, + large_rank, + /* offset */ 5, + /* edge_size */ 10, + /* checker_size */ 3, + dim_selected, + expected_result + ); + + test_shape_same_dr__checkerboard + ( + test_num++, + small_rank, + large_rank, + /* offset */ 9, + /* edge_size */ 10, + /* checker_size */ 3, + dim_selected, + expected_result + ); + + + /* run test with edge size 8, checker + * size 8, and a variety of offsets + */ + test_shape_same_dr__checkerboard + ( + test_num++, + small_rank, + large_rank, + /* offset */ 0, + /* edge_size */ 8, + /* checker_size */ 8, + dim_selected, + expected_result + ); + + test_shape_same_dr__checkerboard + ( + test_num++, + small_rank, + large_rank, + /* offset */ 4, + /* edge_size */ 8, + /* checker_size */ 8, + dim_selected, + expected_result + ); + + test_shape_same_dr__checkerboard + ( + test_num++, + small_rank, + large_rank, + /* offset */ 7, + /* edge_size */ 8, + /* checker_size */ 8, + dim_selected, + expected_result + ); + + z++; + } while((z < 2) && (large_rank >= 1)); + + y++; + } while((y < 2) && (large_rank >= 2)); + + x++; + } while((x < 2) && (large_rank >= 3)); + + w++; + } while((w < 2) && (large_rank >= 4)); + + v++; + } while((v < 2) && (large_rank >= 5)); + } /* end for */ + } /* end for */ + +} /* test_shape_same_dr__run_checkerboard_tests() */ + + +/**************************************************************** +** +** test_shape_same_dr__irregular(): +** +** Tests selection of an "irregular" subset of a full +** n-cube data space vs an identical "irregular" subset +** of an n-dimensional slice of an m-cube (m > n). +** in a call to H5S_select_shape_same(). +** +** Note that this test does not require the n-cube and the +** n-dimensional slice to have the same rank (although +** H5S_select_shape_same() should always return FALSE if +** they don't). +** +****************************************************************/ +static void +test_shape_same_dr__irregular(int test_num, + int small_rank, + int large_rank, + int pattern_offset, + int slice_offset, + hbool_t dim_selected[], + hbool_t expected_result) +{ + char test_desc_0[128]; + char test_desc_1[128]; + int edge_size = 10; + int i; + int j; + int k; + int dims_selected = 0; + hid_t n_cube_0_sid; /* the hyper cube containing + * an irregular selection + */ + hid_t n_cube_1_sid; /* the hyper cube in which a + * slice contains an irregular + * selection. + */ + hsize_t dims[SS_DR_MAX_RANK]; + hsize_t start_0[SS_DR_MAX_RANK] = { 2, 2, 2, 2, 5}; + hsize_t stride_0[SS_DR_MAX_RANK] = {10, 10, 10, 10, 10}; + hsize_t count_0[SS_DR_MAX_RANK] = { 1, 1, 1, 1, 1}; + hsize_t block_0[SS_DR_MAX_RANK] = { 2, 2, 2, 2, 3}; + + hsize_t start_1[SS_DR_MAX_RANK] = { 2, 2, 2, 5, 2}; + hsize_t stride_1[SS_DR_MAX_RANK] = {10, 10, 10, 10, 10}; + hsize_t count_1[SS_DR_MAX_RANK] = { 1, 1, 1, 1, 1}; + hsize_t block_1[SS_DR_MAX_RANK] = { 2, 2, 2, 3, 2}; + + hsize_t start_2[SS_DR_MAX_RANK] = { 2, 2, 5, 2, 2}; + hsize_t stride_2[SS_DR_MAX_RANK] = {10, 10, 10, 10, 10}; + hsize_t count_2[SS_DR_MAX_RANK] = { 1, 1, 1, 1, 1}; + hsize_t block_2[SS_DR_MAX_RANK] = { 2, 2, 3, 2, 2}; + + hsize_t start_3[SS_DR_MAX_RANK] = { 2, 5, 2, 2, 2}; + hsize_t stride_3[SS_DR_MAX_RANK] = {10, 10, 10, 10, 10}; + hsize_t count_3[SS_DR_MAX_RANK] = { 1, 1, 1, 1, 1}; + hsize_t block_3[SS_DR_MAX_RANK] = { 2, 3, 2, 2, 2}; + + hsize_t start_4[SS_DR_MAX_RANK] = { 5, 2, 2, 2, 2}; + hsize_t stride_4[SS_DR_MAX_RANK] = {10, 10, 10, 10, 10}; + hsize_t count_4[SS_DR_MAX_RANK] = { 1, 1, 1, 1, 1}; + hsize_t block_4[SS_DR_MAX_RANK] = { 3, 2, 2, 2, 2}; + + hsize_t clip_start[SS_DR_MAX_RANK] = { 0, 0, 0, 0, 0}; + hsize_t clip_stride[SS_DR_MAX_RANK] = {10, 10, 10, 10, 10}; + hsize_t clip_count[SS_DR_MAX_RANK] = { 1, 1, 1, 1, 1}; + hsize_t clip_block[SS_DR_MAX_RANK] = {10, 10, 10, 10, 10}; + + + hsize_t *(starts[SS_DR_MAX_RANK]) = + {start_0, start_1, start_2, start_3, start_4}; + hsize_t *(strides[SS_DR_MAX_RANK]) = + {stride_0, stride_1, stride_2, stride_3, stride_4}; + hsize_t *(counts[SS_DR_MAX_RANK]) = + {count_0, count_1, count_2, count_3, count_4}; + hsize_t *(blocks[SS_DR_MAX_RANK]) = + {block_0, block_1, block_2, block_3, block_4}; + + hsize_t start[SS_DR_MAX_RANK]; + hsize_t * start_ptr; + hsize_t stride[SS_DR_MAX_RANK]; + hsize_t * stride_ptr; + hsize_t count[SS_DR_MAX_RANK]; + hsize_t * count_ptr; + hsize_t block[SS_DR_MAX_RANK]; + hsize_t * block_ptr; + htri_t check; /* Shape comparison return value */ + herr_t ret; /* Generic return value */ + + HDassert( 0 < small_rank ); + HDassert( small_rank <= large_rank ); + HDassert( large_rank <= SS_DR_MAX_RANK ); + HDassert( 9 <= edge_size ); + HDassert( edge_size <= 1000 ); + HDassert( 0 <= slice_offset ); + HDassert( slice_offset < edge_size ); + HDassert( -2 <= pattern_offset ); + HDassert( pattern_offset <= 2 ); + + for(i = SS_DR_MAX_RANK - large_rank; i < SS_DR_MAX_RANK; i++) + if(dim_selected[i] == TRUE) + dims_selected++; + + HDassert( dims_selected >= 0 ); + HDassert( dims_selected <= large_rank ); + + sprintf(test_desc_0, + "\tirregular sub set of n-cube slice through m-cube (n <= m) test %d.\n", + test_num); + MESSAGE(7, (test_desc_0)); + + /* This statement must be updated if SS_DR_MAX_RANK is changed */ + sprintf(test_desc_1, + "\tranks: %d/%d edge: %d s/p offset: %d/%d dim_selected: %d/%d/%d/%d/%d:%d.\n", + small_rank, large_rank, + edge_size, + slice_offset, pattern_offset, + (int)dim_selected[0], + (int)dim_selected[1], + (int)dim_selected[2], + (int)dim_selected[3], + (int)dim_selected[4], + dims_selected); + MESSAGE(7, (test_desc_1)); + + /* copy the edge size into the dims array */ + for(i = 0; i < SS_DR_MAX_RANK; i++) + dims[i] = (hsize_t)edge_size; + + /* Create the small n-cube */ + n_cube_0_sid = H5Screate_simple(small_rank, dims, NULL); + CHECK(n_cube_0_sid, FAIL, "H5Screate_simple"); + + /* Select an "irregular" pattern in the small n-cube. This + * pattern can be though of a set of four 3 x 2 x 2 X 2 + * four dimensional prisims, each parallel to one of the + * axies and none of them intersecting with the other. + * + * In the lesser dimensional cases, this 4D pattern is + * projected onto the lower dimensional space. + * + * In the 1-D case, the projection of the pattern looks + * like this: + * + * - - * * - * * * - - + * 0 1 2 3 4 5 6 7 8 9 x + * + * and in the 2-D case, it would look like this: + * + * + * y + * 9 - - - - - - - - - - + * 8 - - - - - - - - - - + * 7 - - * * - - - - - - + * 6 - - * * - - - - - - + * 5 - - * * - - - - - - + * 4 - - - - - - - - - - + * 3 - - * * - * * * - - + * 2 - - * * - * * * - - + * 1 - - - - - - - - - - + * 0 - - - - - - - - - - + * 0 1 2 3 4 5 6 7 8 9 x + * + * In both cases, asterisks indicate selected elements, + * and dashes indicate unselected elements. + * + * Note that is this case, since the edge size is fixed, + * the pattern does not change. However, we do use the + * displacement parameter to allow it to be moved around + * within the n-cube or hyper slab. + */ + + /* first, ensure that the small n-cube has no selection */ + ret = H5Sselect_none(n_cube_0_sid); + CHECK(ret, FAIL, "H5Sselect_none"); + + /* now, select the irregular pattern */ + for(i = 0; i < SS_DR_MAX_RANK; i++) { + ret = H5Sselect_hyperslab(n_cube_0_sid, H5S_SELECT_OR, + starts[i], strides[i], counts[i], blocks[i]); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + } /* end for */ + + /* finally, clip the selection to ensure that it lies fully + * within the n-cube. + */ + ret = H5Sselect_hyperslab(n_cube_0_sid, H5S_SELECT_AND, + clip_start, clip_stride, clip_count, clip_block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + + /* Create the large n-cube */ + n_cube_1_sid = H5Screate_simple(large_rank, dims, NULL); + CHECK(n_cube_1_sid, FAIL, "H5Screate_simple"); + + /* Ensure that the large n-cube has no selection */ + H5Sselect_none(n_cube_1_sid); + CHECK(ret, FAIL, "H5Sselect_none"); + + + /* Since large rank may be less than SS_DR_MAX_RANK, we may not + * use the entire start, stride, count, and block arrays. This + * is a problem, since it is inconvenient to set up the dim_selected + * array to reflect the large rank, and thus if large_rank < + * SS_DR_MAX_RANK, we need to hide the lower index entries + * from H5Sselect_hyperslab(). + * + * Do this by setting up pointers to the first valid entry in start, + * stride, count, and block below, and pass these pointers in + * to H5Sselect_hyperslab() instead of the array base addresses. + */ + + i = SS_DR_MAX_RANK - large_rank; + HDassert( i >= 0 ); + + start_ptr = &(start[i]); + stride_ptr = &(stride[i]); + count_ptr = &(count[i]); + block_ptr = &(block[i]); + + + /* Now select the irregular selection in the (possibly larger) n-cube. + * + * Basic idea is to project the pattern used in the smaller n-cube + * onto the dimensions selected in the larger n-cube, with the displacement + * specified. + */ + for(i = 0; i < SS_DR_MAX_RANK; i++) { + j = 0; + for(k = 0; k < SS_DR_MAX_RANK; k++) { + if(dim_selected[k]) { + start[k] = (starts[i])[j] + (hsize_t)pattern_offset; + stride[k] = (strides[i])[j]; + count[k] = (counts[i])[j]; + block[k] = (blocks[i])[j]; + j++; + } /* end if */ + else { + start[k] = (hsize_t)slice_offset; + stride[k] = (hsize_t)(2 * edge_size); + count[k] = 1; + block[k] = 1; + } /* end else */ + } /* end for */ + + /* select the hyper slab */ + ret = H5Sselect_hyperslab(n_cube_1_sid, H5S_SELECT_OR, + start_ptr, stride_ptr, count_ptr, block_ptr); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + } /* end for */ + + /* it is possible that the selection extends beyond the data space. + * clip the selection to ensure that it doesn't. + */ + ret = H5Sselect_hyperslab(n_cube_1_sid, H5S_SELECT_AND, + clip_start, clip_stride, clip_count, clip_block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + + /* setup is done -- run the test: */ + check = H5S_select_shape_same_test(n_cube_0_sid, n_cube_1_sid); + VERIFY(check, expected_result, "test_shape_same_dr__checkerboard"); + + + /* Close dataspaces */ + ret = H5Sclose(n_cube_0_sid); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Sclose(n_cube_1_sid); + CHECK(ret, FAIL, "H5Sclose"); + +} /* test_shape_same_dr__irregular() */ + + +/**************************************************************** +** +** test_shape_same_dr__run_irregular_tests(): +** +** In this set of tests, we test H5S_select_shape_same() +** with an "irregular" subselection of 1, 2, 3, and 4 cubes as +** one parameter, and irregular subselections of 1, 2, 3, +** and 4 dimensional slices through a n-cube of rank no more +** than 5 (and at least the rank of the slice) as the other. +** Note that the "irregular" selection may be offset between +** the n-cube and the slice. +** +** All the irregular selections will be identical (modulo rank) +** so H5S_select_shape_same() should return true iff: +** +** 1) the rank of the n cube equals the number of dimensions +** selected in the irregular slice through the m-cube +** (m >= n). +** +** 2) The dimensions selected in the irregular slice +** through the m-cube are the dimensions with the most +** quickly changing indices. +** +****************************************************************/ +static void +test_shape_same_dr__run_irregular_tests(void) +{ + hbool_t dim_selected[5]; + hbool_t expected_result; + int i, j; + int v, w, x, y, z; + int test_num = 0; + int small_rank; + int large_rank; + + for(large_rank = 1; large_rank <= 5; large_rank++) { + for(small_rank = 1; small_rank <= large_rank; small_rank++) { + v = 0; + do { + if(v == 0) + dim_selected[0] = FALSE; + else + dim_selected[0] = TRUE; + + w = 0; + do { + if(w == 0) + dim_selected[1] = FALSE; + else + dim_selected[1] = TRUE; + + x = 0; + do { + if(x == 0) + dim_selected[2] = FALSE; + else + dim_selected[2] = TRUE; + + y = 0; + do { + if(y == 0) + dim_selected[3] = FALSE; + else + dim_selected[3] = TRUE; + + z = 0; + do { + if(z == 0) + dim_selected[4] = FALSE; + else + dim_selected[4] = TRUE; + + + /* compute the expected result: */ + i = 0; + j = 4; + expected_result = TRUE; + while((i < small_rank) && expected_result) { + if(!dim_selected[j]) + expected_result = FALSE; + i++; + j--; + } /* end while */ + + while((i < large_rank) && expected_result) { + if(dim_selected[j]) + expected_result = FALSE; + i++; + j--; + } /* end while */ + + + /* everything is set up -- run the tests */ + + test_shape_same_dr__irregular + ( + test_num++, + small_rank, + large_rank, + /* pattern_offset */ -2, + /* slice_offset */ 0, + dim_selected, + expected_result + ); + + test_shape_same_dr__irregular + ( + test_num++, + small_rank, + large_rank, + /* pattern_offset */ -2, + /* slice_offset */ 4, + dim_selected, + expected_result + ); + + test_shape_same_dr__irregular + ( + test_num++, + small_rank, + large_rank, + /* pattern_offset */ -2, + /* slice_offset */ 9, + dim_selected, + expected_result + ); + + + test_shape_same_dr__irregular + ( + test_num++, + small_rank, + large_rank, + /* pattern_offset */ 0, + /* slice_offset */ 0, + dim_selected, + expected_result + ); + + test_shape_same_dr__irregular + ( + test_num++, + small_rank, + large_rank, + /* pattern_offset */ 0, + /* slice_offset */ 6, + dim_selected, + expected_result + ); + + test_shape_same_dr__irregular + ( + test_num++, + small_rank, + large_rank, + /* pattern_offset */ 0, + /* slice_offset */ 9, + dim_selected, + expected_result + ); + + + test_shape_same_dr__irregular + ( + test_num++, + small_rank, + large_rank, + /* pattern_offset */ 2, + /* slice_offset */ 0, + dim_selected, + expected_result + ); + + test_shape_same_dr__irregular + ( + test_num++, + small_rank, + large_rank, + /* pattern_offset */ 2, + /* slice_offset */ 5, + dim_selected, + expected_result + ); + + test_shape_same_dr__irregular + ( + test_num++, + small_rank, + large_rank, + /* pattern_offset */ 2, + /* slice_offset */ 9, + dim_selected, + expected_result + ); + + z++; + } while((z < 2) && (large_rank >= 1)); + + y++; + } while((y < 2) && (large_rank >= 2)); + + x++; + } while((x < 2) && (large_rank >= 3)); + + w++; + } while((w < 2) && (large_rank >= 4)); + + v++; + } while((v < 2 ) && (large_rank >= 5)); + } /* end for */ + } /* end for */ + +} /* test_shape_same_dr__run_irregular_tests() */ + + +/**************************************************************** +** +** test_shape_same_dr(): Tests selections on dataspace with +** different ranks, to verify that "shape same" routine +** is now handling this case correctly. +** +****************************************************************/ +static void +test_shape_same_dr(void) +{ + /* Output message about test being performed */ + MESSAGE(6, ("Testing Same Shape/Different Rank Comparisons\n")); + + + /* first run some smoke checks */ + test_shape_same_dr__smoke_check_1(); + test_shape_same_dr__smoke_check_2(); + test_shape_same_dr__smoke_check_3(); + test_shape_same_dr__smoke_check_4(); + + + /* now run more intensive tests. */ + test_shape_same_dr__run_full_space_vs_slice_tests(); + test_shape_same_dr__run_checkerboard_tests(); + test_shape_same_dr__run_irregular_tests(); + +} /* test_shape_same_dr() */ + /**************************************************************** ** @@ -8241,6 +13118,14 @@ test_select(void) test_select_hyper_contig3(H5T_STD_U16LE,plist_id); /* Test yet more contiguous hyperslab selection cases */ test_select_hyper_contig3(H5T_STD_U16BE,H5P_DEFAULT); /* Test yet more contiguous hyperslab selection cases */ test_select_hyper_contig3(H5T_STD_U16BE,plist_id); /* Test yet more contiguous hyperslab selection cases */ + test_select_hyper_contig_dr(H5T_STD_U16LE, H5P_DEFAULT); + test_select_hyper_contig_dr(H5T_STD_U16LE, plist_id); + test_select_hyper_contig_dr(H5T_STD_U16BE, H5P_DEFAULT); + test_select_hyper_contig_dr(H5T_STD_U16BE, plist_id); + test_select_hyper_checker_board_dr(H5T_STD_U16LE, H5P_DEFAULT); + test_select_hyper_checker_board_dr(H5T_STD_U16LE, plist_id); + test_select_hyper_checker_board_dr(H5T_STD_U16BE, H5P_DEFAULT); + test_select_hyper_checker_board_dr(H5T_STD_U16BE, plist_id); test_select_hyper_copy(); /* Test hyperslab selection copying code */ test_select_point_copy(); /* Test point selection copying code */ test_select_hyper_offset(); /* Test selection offset code with hyperslabs */ @@ -8320,6 +13205,9 @@ test_select(void) /* Test "same shape" routine */ test_shape_same(); + /* Test "same shape" routine for selections of different rank */ + test_shape_same_dr(); + /* Test "re-build" routine */ test_space_rebuild(); diff --git a/test/tsizeslheap.h5 b/test/tsizeslheap.h5 Binary files differnew file mode 100644 index 0000000..c7f2adb --- /dev/null +++ b/test/tsizeslheap.h5 diff --git a/testpar/Makefile.am b/testpar/Makefile.am index 3c39989..6e76e88 100644 --- a/testpar/Makefile.am +++ b/testpar/Makefile.am @@ -32,7 +32,8 @@ check_PROGRAMS = $(TEST_PROG_PARA) check_SCRIPTS= $(TEST_SCRIPT) testphdf5_SOURCES=testphdf5.c t_dset.c t_file.c t_mdset.c t_ph5basic.c \ - t_coll_chunk.c t_span_tree.c t_chunk_alloc.c t_filter_read.c + t_coll_chunk.c t_span_tree.c t_chunk_alloc.c t_filter_read.c \ + t_rank_projection.c # The tests all depend on the hdf5 library and the test library LDADD = $(LIBH5TEST) $(LIBHDF5) diff --git a/testpar/Makefile.in b/testpar/Makefile.in index 2b4b00b..4f92776 100644 --- a/testpar/Makefile.in +++ b/testpar/Makefile.in @@ -90,7 +90,8 @@ t_posix_compliant_DEPENDENCIES = $(LIBH5TEST) $(LIBHDF5) am_testphdf5_OBJECTS = testphdf5.$(OBJEXT) t_dset.$(OBJEXT) \ t_file.$(OBJEXT) t_mdset.$(OBJEXT) t_ph5basic.$(OBJEXT) \ t_coll_chunk.$(OBJEXT) t_span_tree.$(OBJEXT) \ - t_chunk_alloc.$(OBJEXT) t_filter_read.$(OBJEXT) + t_chunk_alloc.$(OBJEXT) t_filter_read.$(OBJEXT) \ + t_rank_projection.$(OBJEXT) testphdf5_OBJECTS = $(am_testphdf5_OBJECTS) testphdf5_LDADD = $(LDADD) testphdf5_DEPENDENCIES = $(LIBH5TEST) $(LIBHDF5) @@ -155,6 +156,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -180,6 +182,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ @@ -388,7 +391,8 @@ TEST_PROG_PARA = t_mpi t_posix_compliant testphdf5 t_cache t_pflush1 t_pflush2 TEST_SCRIPT_PARA = testph5.sh check_SCRIPTS = $(TEST_SCRIPT) testphdf5_SOURCES = testphdf5.c t_dset.c t_file.c t_mdset.c t_ph5basic.c \ - t_coll_chunk.c t_span_tree.c t_chunk_alloc.c t_filter_read.c + t_coll_chunk.c t_span_tree.c t_chunk_alloc.c t_filter_read.c \ + t_rank_projection.c # The tests all depend on the hdf5 library and the test library @@ -492,6 +496,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_pflush2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_ph5basic.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_posix_compliant.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_rank_projection.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_span_tree.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testphdf5.Po@am__quote@ diff --git a/testpar/t_cache.c b/testpar/t_cache.c index 9bcf09f..a417bb4 100644 --- a/testpar/t_cache.c +++ b/testpar/t_cache.c @@ -77,6 +77,11 @@ long global_dirty_pins = 0; long local_pins = 0; +/* the following fields are used by the server process only */ +int total_reads = 0; +int total_writes = 0; + + /***************************************************************************** * struct datum * @@ -135,6 +140,14 @@ long local_pins = 0; * flushed: Boolean flag that is set to true whenever the entry is * dirty, and is flushed via a call to flush_datum(). * + * reads: Integer field used to maintain a count of the number of + * times this entry has been read from the server since + * the last time the read and write counts were reset. + * + * writes: Integer field used to maintain a count of the number of + * times this entry has been written to the server since + * the last time the read and write counts were reset. + * * index: Index of this instance of datum in the data_index[] array * discussed below. * @@ -154,6 +167,8 @@ struct datum hbool_t local_pinned; hbool_t cleared; hbool_t flushed; + int reads; + int writes; int index; }; @@ -217,6 +232,38 @@ int data_index[NUM_DATA_ENTRIES]; /***************************************************************************** + * The following two #defines are used to control code that is in turn used + * to force "POSIX" semantics on the server process used to simulate metadata + * reads and writes. Without some such mechanism, the test code contains + * race conditions that will frequently cause spurious failures. + * + * When set to TRUE, DO_WRITE_REQ_ACK forces the server to send an ack after + * each write request, and the client to wait until the ack is received + * before proceeding. This was my first solution to the problem, and at + * first glance, it would seem to have a lot of unnecessary overhead. + * + * In an attempt to reduce the overhead, I implemented a second solution + * in which no acks are sent after writes. Instead, the metadata cache is + * provided with a callback function to call after each sequence of writes. + * This callback simply causes the client to send the server process a + * "sync" message and and await an ack in reply. + * + * Strangely, at least on Phoenix, the first solution runs faster by a + * rather large margin. However, I can imagine this changing with + * different OS's and MPI implementatins. + * + * Thus I have left code supporting the second solution in place. + * + * Note that while one of these two #defines must be set to TRUE, there + * should never be any need to set both of them to TRUE (although the + * tests will still function with this setting). + *****************************************************************************/ + +#define DO_WRITE_REQ_ACK TRUE +#define DO_SYNC_AFTER_WRITE FALSE + + +/***************************************************************************** * struct mssg * * The mssg structure is used as a generic container for messages to @@ -236,22 +283,32 @@ int data_index[NUM_DATA_ENTRIES]; * * ver: Version number of a datum. Not used in all mssgs. * + * count: Reported number of total/entry reads/writes. Not used + * in all mssgs. + * * magic: Magic number for error detection. Must be set to * MSSG_MAGIC. * *****************************************************************************/ -#define DO_WRITE_REQ_ACK FALSE -#define DO_SYNC_AFTER_WRITE TRUE - -#define WRITE_REQ_CODE 0 -#define WRITE_REQ_ACK_CODE 1 -#define READ_REQ_CODE 2 -#define READ_REQ_REPLY_CODE 3 -#define SYNC_REQ_CODE 4 -#define SYNC_ACK_CODE 5 -#define DONE_REQ_CODE 6 -#define MAX_REQ_CODE 6 +#define WRITE_REQ_CODE 0 +#define WRITE_REQ_ACK_CODE 1 +#define READ_REQ_CODE 2 +#define READ_REQ_REPLY_CODE 3 +#define SYNC_REQ_CODE 4 +#define SYNC_ACK_CODE 5 +#define REQ_TTL_WRITES_CODE 6 +#define REQ_TTL_WRITES_RPLY_CODE 7 +#define REQ_TTL_READS_CODE 8 +#define REQ_TTL_READS_RPLY_CODE 9 +#define REQ_ENTRY_WRITES_CODE 10 +#define REQ_ENTRY_WRITES_RPLY_CODE 11 +#define REQ_ENTRY_READS_CODE 12 +#define REQ_ENTRY_READS_RPLY_CODE 13 +#define REQ_RW_COUNT_RESET_CODE 14 +#define REQ_RW_COUNT_RESET_RPLY_CODE 15 +#define DONE_REQ_CODE 16 +#define MAX_REQ_CODE 16 #define MSSG_MAGIC 0x1248 @@ -262,8 +319,9 @@ struct mssg_t int dest; long int mssg_num; haddr_t base_addr; - int len; + unsigned len; int ver; + int count; unsigned magic; }; @@ -306,10 +364,16 @@ static hbool_t takedown_derived_types(void); /* server functions */ +static hbool_t reset_server_counters(void); static hbool_t server_main(void); static hbool_t serve_read_request(struct mssg_t * mssg_ptr); static hbool_t serve_sync_request(struct mssg_t * mssg_ptr); static hbool_t serve_write_request(struct mssg_t * mssg_ptr); +static hbool_t serve_total_writes_request(struct mssg_t * mssg_ptr); +static hbool_t serve_total_reads_request(struct mssg_t * mssg_ptr); +static hbool_t serve_entry_writes_request(struct mssg_t * mssg_ptr); +static hbool_t serve_entry_reads_request(struct mssg_t * mssg_ptr); +static hbool_t serve_rw_count_reset_request(struct mssg_t * mssg_ptr); /* call back functions & related data structures */ @@ -361,11 +425,19 @@ void mark_entry_dirty(int32_t idx); void pin_entry(H5F_t * file_ptr, int32_t idx, hbool_t global, hbool_t dirty); void pin_protected_entry(int32_t idx, hbool_t global); void move_entry(H5F_t * file_ptr, int32_t old_idx, int32_t new_idx); +static hbool_t reset_server_counts(void); void resize_entry(int32_t idx, size_t new_size); -hbool_t setup_cache_for_test(hid_t * fid_ptr, H5F_t ** file_ptr_ptr, - H5C_t ** cache_ptr_ptr); +hbool_t setup_cache_for_test(hid_t * fid_ptr, + H5F_t ** file_ptr_ptr, + H5C_t ** cache_ptr_ptr, + int metadata_write_strategy); void setup_rand(void); hbool_t take_down_cache(hid_t fid); +static hbool_t verify_entry_reads(haddr_t addr, int expected_entry_reads); +static hbool_t verify_entry_writes(haddr_t addr, int expected_entry_writes); +static hbool_t verify_total_reads(int expected_total_reads); +static hbool_t verify_total_writes(int expected_total_writes); +void verify_writes(int num_writes, haddr_t * written_entries_tbl); void unlock_entry(H5F_t * file_ptr, int32_t type, unsigned int flags); void unpin_entry(H5F_t * file_ptr, int32_t idx, hbool_t global, hbool_t dirty, hbool_t via_unprotect); @@ -374,12 +446,12 @@ void unpin_entry(H5F_t * file_ptr, int32_t idx, hbool_t global, /* test functions */ hbool_t server_smoke_check(void); -hbool_t smoke_check_1(void); -hbool_t smoke_check_2(void); -hbool_t smoke_check_3(void); -hbool_t smoke_check_4(void); -hbool_t smoke_check_5(void); -hbool_t trace_file_check(void); +hbool_t smoke_check_1(int metadata_write_strategy); +hbool_t smoke_check_2(int metadata_write_strategy); +hbool_t smoke_check_3(int metadata_write_strategy); +hbool_t smoke_check_4(int metadata_write_strategy); +hbool_t smoke_check_5(int metadata_write_strategy); +hbool_t trace_file_check(int metadata_write_strategy); /*****************************************************************************/ @@ -631,12 +703,7 @@ set_up_file_communicator(void) * * Programmer: JRM -- 12/20/05 * - * Modifications: - * - * None. - * *****************************************************************************/ - static int addr_to_datum_index(haddr_t base_addr) { @@ -684,20 +751,7 @@ addr_to_datum_index(haddr_t base_addr) * * Programmer: JRM -- 12/20/05 * - * Modifications: - * - * JRM -- 7/11/06 - * Added support for the local_len field. - * - * JRM -- 2/4/09 - * Added initialization for the cleared and flushed fields. - * - * Mike McGreevy, July 2, 2009 - * Changed base address from 0 to 512 since the superblock will - * always be at address 0. - * *****************************************************************************/ - static void init_data(void) { @@ -735,6 +789,8 @@ init_data(void) data[i].local_pinned = FALSE; data[i].cleared = FALSE; data[i].flushed = FALSE; + data[i].reads = 0; + data[i].writes = 0; data[i].index = i; data_index[i] = i; @@ -773,12 +829,7 @@ init_data(void) * * Programmer: JRM -- 4/25/06 * - * Modifications: - * - * None. - * *****************************************************************************/ - static int do_express_test(void) { @@ -850,6 +901,7 @@ do_sync(void) mssg.base_addr = 0; mssg.len = 0; mssg.ver = 0; + mssg.count = 0; mssg.magic = MSSG_MAGIC; if ( ! send_mssg(&mssg, FALSE) ) { @@ -1103,7 +1155,7 @@ send_mssg(struct mssg_t *mssg_ptr, } /* send_mssg() */ - + /***************************************************************************** * * Function: setup_derived_types() @@ -1117,12 +1169,7 @@ send_mssg(struct mssg_t *mssg_ptr, * * Programmer: JRM -- 12/22/05 * - * Modifications: - * - * None. - * *****************************************************************************/ - static hbool_t setup_derived_types(void) { @@ -1130,11 +1177,11 @@ setup_derived_types(void) hbool_t success = TRUE; int i; int result; - MPI_Datatype mpi_types[8] = {MPI_INT, MPI_INT, MPI_INT, MPI_LONG, + MPI_Datatype mpi_types[9] = {MPI_INT, MPI_INT, MPI_INT, MPI_LONG, HADDR_AS_MPI_TYPE, MPI_INT, MPI_INT, - MPI_UNSIGNED}; - int block_len[8] = {1, 1, 1, 1, 1, 1, 1, 1}; - MPI_Aint displs[8]; + MPI_INT, MPI_UNSIGNED}; + int block_len[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1}; + MPI_Aint displs[9]; struct mssg_t sample; /* used to compute displacements */ /* setup the displacements array */ @@ -1145,7 +1192,8 @@ setup_derived_types(void) ( MPI_SUCCESS != MPI_Address(&sample.base_addr, &displs[4]) ) || ( MPI_SUCCESS != MPI_Address(&sample.len, &displs[5]) ) || ( MPI_SUCCESS != MPI_Address(&sample.ver, &displs[6]) ) || - ( MPI_SUCCESS != MPI_Address(&sample.magic, &displs[7]) ) ) { + ( MPI_SUCCESS != MPI_Address(&sample.count, &displs[7]) ) || + ( MPI_SUCCESS != MPI_Address(&sample.magic, &displs[8]) ) ) { nerrors++; success = FALSE; @@ -1157,7 +1205,7 @@ setup_derived_types(void) } else { /* Now calculate the actual displacements */ - for ( i = 7; i >= 0; --i) + for ( i = 8; i >= 0; --i) { displs[i] -= displs[0]; } @@ -1165,7 +1213,7 @@ setup_derived_types(void) if ( success ) { - result = MPI_Type_struct(8, block_len, displs, mpi_types, &mpi_mssg_t); + result = MPI_Type_struct(9, block_len, displs, mpi_types, &mpi_mssg_t); if ( result != MPI_SUCCESS ) { @@ -1247,6 +1295,79 @@ takedown_derived_types(void) /***************************************************************************** * + * Function: reset_server_counters() + * + * Purpose: Reset the counters maintained by the server, doing a + * sanity check in passing. + * + * Return: Success: TRUE + * + * Failure: FALSE + * + * Programmer: JRM -- 5/5/10 + * + * Modifications: + * + * None. + * + *****************************************************************************/ + +static hbool_t +reset_server_counters(void) +{ + const char * fcn_name = "reset_server_counters()"; + hbool_t success = TRUE; + int i; + long actual_total_reads = 0; + long actual_total_writes = 0; + + for ( i = 0; i < NUM_DATA_ENTRIES; i++ ) + { + if ( data[i].reads > 0 ) { + + actual_total_reads += data[i].reads; + data[i].reads = 0; + } + + if ( data[i].writes > 0 ) { + + actual_total_writes += data[i].writes; + data[i].writes = 0; + } + } + + if ( actual_total_reads != total_reads ) { + + success = FALSE; + nerrors++; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: actual/total reads mismatch (%ld/%ld).\n", + world_mpi_rank, fcn_name, + actual_total_reads, total_reads); + } + } + + if ( actual_total_writes != total_writes ) { + + success = FALSE; + nerrors++; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: actual/total writes mismatch (%ld/%ld).\n", + world_mpi_rank, fcn_name, + actual_total_writes, total_writes); + } + } + + total_reads = 0; + total_writes = 0; + + return(success); + +} /* reset_server_counters() */ + + +/***************************************************************************** + * * Function: server_main() * * Purpose: Main function for the server process. This process exists @@ -1303,7 +1424,8 @@ server_main(void) case WRITE_REQ_ACK_CODE: success = FALSE; - HDfprintf(stdout, "%s: Received write ack?!?.\n", fcn_name); + if(verbose) + HDfprintf(stdout, "%s: Received write ack?!?.\n", fcn_name); break; case READ_REQ_CODE: @@ -1312,8 +1434,8 @@ server_main(void) case READ_REQ_REPLY_CODE: success = FALSE; - HDfprintf(stdout, "%s: Received read req reply?!?.\n", - fcn_name); + if(verbose) + HDfprintf(stdout, "%s: Received read req reply?!?.\n", fcn_name); break; case SYNC_REQ_CODE: @@ -1322,27 +1444,71 @@ server_main(void) case SYNC_ACK_CODE: success = FALSE; - HDfprintf(stdout, "%s: Received sync ack?!?.\n", - fcn_name); + if(verbose) + HDfprintf(stdout, "%s: Received sync ack?!?.\n", fcn_name); + break; + + case REQ_TTL_WRITES_CODE: + success = serve_total_writes_request(&mssg); + break; + + case REQ_TTL_WRITES_RPLY_CODE: + success = FALSE; + if(verbose) + HDfprintf(stdout, "%s: Received total writes reply?!?.\n", fcn_name); + break; + + case REQ_TTL_READS_CODE: + success = serve_total_reads_request(&mssg); + break; + + case REQ_TTL_READS_RPLY_CODE: + success = FALSE; + if(verbose) + HDfprintf(stdout, "%s: Received total reads reply?!?.\n", fcn_name); + break; + + case REQ_ENTRY_WRITES_CODE: + success = serve_entry_writes_request(&mssg); + break; + + case REQ_ENTRY_WRITES_RPLY_CODE: + success = FALSE; + if(verbose) + HDfprintf(stdout, "%s: Received entry writes reply?!?.\n", fcn_name); + break; + + case REQ_ENTRY_READS_CODE: + success = serve_entry_reads_request(&mssg); + break; + + case REQ_ENTRY_READS_RPLY_CODE: + success = FALSE; + if(verbose) + HDfprintf(stdout, "%s: Received entry reads reply?!?.\n", fcn_name); + break; + + case REQ_RW_COUNT_RESET_CODE: + success = serve_rw_count_reset_request(&mssg); + break; + + case REQ_RW_COUNT_RESET_RPLY_CODE: + success = FALSE; + if(verbose) + HDfprintf(stdout, "%s: Received RW count reset reply?!?.\n", fcn_name); break; case DONE_REQ_CODE: done_count++; - /* HDfprintf(stdout, "%d:%s: done_count = %d.\n", - world_mpi_rank, fcn_name, done_count); */ - if ( done_count >= file_mpi_size ) { - + if(done_count >= file_mpi_size) done = TRUE; - } break; default: nerrors++; success = FALSE; - if ( verbose ) { - HDfprintf(stdout, "%d:%s: Unknown request code.\n", - world_mpi_rank, fcn_name); - } + if(verbose) + HDfprintf(stdout, "%d:%s: Unknown request code.\n", world_mpi_rank, fcn_name); break; } } @@ -1352,7 +1518,7 @@ server_main(void) } /* server_main() */ - + /***************************************************************************** * * Function: serve_read_request() @@ -1370,16 +1536,12 @@ server_main(void) * * Programmer: JRM -- 12/22/05 * - * Modifications: - * - * None. - * *****************************************************************************/ - static hbool_t serve_read_request(struct mssg_t * mssg_ptr) { const char * fcn_name = "serve_read_request()"; + hbool_t report_mssg = FALSE; hbool_t success = TRUE; int target_index; haddr_t target_addr; @@ -1426,11 +1588,11 @@ serve_read_request(struct mssg_t * mssg_ptr) success = FALSE; if ( verbose ) { HDfprintf(stdout, - "%d:%s: proc %d read invalid entry. idx/base_addr = %d/%a.\n", - world_mpi_rank, fcn_name, - mssg_ptr->src, + "%d:%s: proc %d read invalid entry. idx/base_addr = %d/0x%llx.\n", + world_mpi_rank, fcn_name, + mssg_ptr->src, target_index, - data[target_index].base_addr); + (long long)(data[target_index].base_addr)); } } else { @@ -1442,7 +1604,12 @@ serve_read_request(struct mssg_t * mssg_ptr) reply.base_addr = data[target_index].base_addr; reply.len = data[target_index].len; reply.ver = data[target_index].ver; + reply.count = 0; reply.magic = MSSG_MAGIC; + + /* and update the counters */ + total_reads++; + (data[target_index].reads)++; } } @@ -1451,6 +1618,27 @@ serve_read_request(struct mssg_t * mssg_ptr) success = send_mssg(&reply, TRUE); } + if ( report_mssg ) { + + if ( success ) { + + HDfprintf(stdout, "%d read 0x%llx. len = %d. ver = %d.\n", + (int)(mssg_ptr->src), + (long long)(data[target_index].base_addr), + (int)(data[target_index].len), + (int)(data[target_index].ver)); + + } else { + + HDfprintf(stdout, "%d read 0x%llx FAILED. len = %d. ver = %d.\n", + (int)(mssg_ptr->src), + (long long)(data[target_index].base_addr), + (int)(data[target_index].len), + (int)(data[target_index].ver)); + + } + } + return(success); } /* serve_read_request() */ @@ -1486,6 +1674,7 @@ static hbool_t serve_sync_request(struct mssg_t * mssg_ptr) { const char * fcn_name = "serve_sync_request()"; + hbool_t report_mssg = FALSE; hbool_t success = TRUE; struct mssg_t reply; @@ -1511,6 +1700,7 @@ serve_sync_request(struct mssg_t * mssg_ptr) reply.base_addr = 0; reply.len = 0; reply.ver = 0; + reply.count = 0; reply.magic = MSSG_MAGIC; } @@ -1519,11 +1709,24 @@ serve_sync_request(struct mssg_t * mssg_ptr) success = send_mssg(&reply, TRUE); } + if ( report_mssg ) { + + if ( success ) { + + HDfprintf(stdout, "%d sync.\n", (int)(mssg_ptr->src)); + + } else { + + HDfprintf(stdout, "%d sync FAILED.\n", (int)(mssg_ptr->src)); + + } + } + return(success); } /* serve_sync_request() */ - + /***************************************************************************** * * Function: serve_write_request() @@ -1541,19 +1744,12 @@ serve_sync_request(struct mssg_t * mssg_ptr) * * Programmer: JRM -- 12/21/05 * - * Modifications: - * - * JRM -- 5/9/06 - * Added code supporting a write ack message. This is a - * speculative fix to a bug observed on Cobalt. If it - * doesn't work, it will help narrow down the possibilities. - * *****************************************************************************/ - static hbool_t serve_write_request(struct mssg_t * mssg_ptr) { const char * fcn_name = "serve_write_request()"; + hbool_t report_mssg = FALSE; hbool_t success = TRUE; int target_index; int new_ver_num; @@ -1604,6 +1800,7 @@ serve_write_request(struct mssg_t * mssg_ptr) new_ver_num = mssg_ptr->ver; + /* this check should catch duplicate writes */ if ( new_ver_num <= data[target_index].ver ) { nerrors++; @@ -1622,6 +1819,10 @@ serve_write_request(struct mssg_t * mssg_ptr) data[target_index].ver = new_ver_num; data[target_index].valid = TRUE; + /* and update the counters */ + total_writes++; + (data[target_index].writes)++; + #if DO_WRITE_REQ_ACK /* compose the reply message */ @@ -1632,6 +1833,7 @@ serve_write_request(struct mssg_t * mssg_ptr) reply.base_addr = data[target_index].base_addr; reply.len = data[target_index].len; reply.ver = data[target_index].ver; + reply.count = 0; reply.magic = MSSG_MAGIC; /* and send it */ @@ -1641,10 +1843,469 @@ serve_write_request(struct mssg_t * mssg_ptr) } + if ( report_mssg ) { + + if ( success ) { + + HDfprintf(stdout, "%d write 0x%llx. len = %d. ver = %d.\n", + (int)(mssg_ptr->src), + (long long)(data[target_index].base_addr), + (int)(data[target_index].len), + (int)(data[target_index].ver)); + + } else { + + HDfprintf(stdout, "%d write 0x%llx FAILED. len = %d. ver = %d.\n", + (int)(mssg_ptr->src), + (long long)(data[target_index].base_addr), + (int)(data[target_index].len), + (int)(data[target_index].ver)); + + } + } + return(success); } /* serve_write_request() */ + +/***************************************************************************** + * + * Function: serve_total_writes_request() + * + * Purpose: Serve a request for the total number of writes recorded since + * the last reset. + * + * The function accepts a pointer to an instance of struct + * mssg_t as input. If all sanity checks pass, it sends + * the current value of the total_writes global variable to + * the requesting process. + * + * Return: Success: TRUE + * + * Failure: FALSE + * + * Programmer: JRM -- 5/5/10 + * + *****************************************************************************/ +static hbool_t +serve_total_writes_request(struct mssg_t * mssg_ptr) +{ + const char * fcn_name = "serve_total_writes_request()"; + hbool_t report_mssg = FALSE; + hbool_t success = TRUE; + struct mssg_t reply; + + if ( ( mssg_ptr == NULL ) || + ( mssg_ptr->req != REQ_TTL_WRITES_CODE ) || + ( mssg_ptr->magic != MSSG_MAGIC ) ) { + + nerrors++; + success = FALSE; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: Bad mssg on entry.\n", + world_mpi_rank, fcn_name); + } + } + + if ( success ) { + + /* compose the reply message */ + reply.req = REQ_TTL_WRITES_RPLY_CODE; + reply.src = world_mpi_rank; + reply.dest = mssg_ptr->src; + reply.mssg_num = -1; /* set by send function */ + reply.base_addr = 0; + reply.len = 0; + reply.ver = 0; + reply.count = total_writes; + reply.magic = MSSG_MAGIC; + } + + if ( success ) { + + success = send_mssg(&reply, TRUE); + } + + if ( report_mssg ) { + + if ( success ) { + + HDfprintf(stdout, "%d request total writes %ld.\n", + (int)(mssg_ptr->src), + total_writes); + + } else { + + HDfprintf(stdout, "%d request total writes %ld -- FAILED.\n", + (int)(mssg_ptr->src), + total_writes); + + } + } + + return(success); + +} /* serve_total_writes_request() */ + + +/***************************************************************************** + * + * Function: serve_total_reads_request() + * + * Purpose: Serve a request for the total number of reads recorded since + * the last reset. + * + * The function accepts a pointer to an instance of struct + * mssg_t as input. If all sanity checks pass, it sends + * the current value of the total_reads global variable to + * the requesting process. + * + * Return: Success: TRUE + * + * Failure: FALSE + * + * Programmer: JRM -- 5/5/10 + * + *****************************************************************************/ +static hbool_t +serve_total_reads_request(struct mssg_t * mssg_ptr) +{ + const char * fcn_name = "serve_total_reads_request()"; + hbool_t report_mssg = FALSE; + hbool_t success = TRUE; + struct mssg_t reply; + + if ( ( mssg_ptr == NULL ) || + ( mssg_ptr->req != REQ_TTL_READS_CODE ) || + ( mssg_ptr->magic != MSSG_MAGIC ) ) { + + nerrors++; + success = FALSE; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: Bad mssg on entry.\n", + world_mpi_rank, fcn_name); + } + } + + if ( success ) { + + /* compose the reply message */ + reply.req = REQ_TTL_READS_RPLY_CODE; + reply.src = world_mpi_rank; + reply.dest = mssg_ptr->src; + reply.mssg_num = -1; /* set by send function */ + reply.base_addr = 0; + reply.len = 0; + reply.ver = 0; + reply.count = total_reads; + reply.magic = MSSG_MAGIC; + } + + if ( success ) { + + success = send_mssg(&reply, TRUE); + } + + if ( report_mssg ) { + + if ( success ) { + + HDfprintf(stdout, "%d request total reads %ld.\n", + (int)(mssg_ptr->src), + total_reads); + + } else { + + HDfprintf(stdout, "%d request total reads %ld -- FAILED.\n", + (int)(mssg_ptr->src), + total_reads); + + } + } + + return(success); + +} /* serve_total_reads_request() */ + + +/***************************************************************************** + * + * Function: serve_entry_writes_request() + * + * Purpose: Serve an entry writes request. + * + * The function accepts a pointer to an instance of struct + * mssg_t as input. If all sanity checks pass, it sends + * the number of times that the indicated datum has been + * written since the last counter reset to the requesting + * process. + * + * Return: Success: TRUE + * + * Failure: FALSE + * + * Programmer: JRM -- 5/5/10 + * + *****************************************************************************/ +static hbool_t +serve_entry_writes_request(struct mssg_t * mssg_ptr) +{ + const char * fcn_name = "serve_entry_writes_request()"; + hbool_t report_mssg = FALSE; + hbool_t success = TRUE; + int target_index; + haddr_t target_addr; + struct mssg_t reply; + + if ( ( mssg_ptr == NULL ) || + ( mssg_ptr->req != REQ_ENTRY_WRITES_CODE ) || + ( mssg_ptr->magic != MSSG_MAGIC ) ) { + + nerrors++; + success = FALSE; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: Bad mssg on entry.\n", + world_mpi_rank, fcn_name); + } + } + + if ( success ) { + + target_addr = mssg_ptr->base_addr; + target_index = addr_to_datum_index(target_addr); + + if ( target_index < 0 ) { + + nerrors++; + success = FALSE; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: addr lookup failed for %a.\n", + world_mpi_rank, fcn_name, target_addr); + } + } else { + + /* compose the reply message */ + reply.req = REQ_ENTRY_WRITES_RPLY_CODE; + reply.src = world_mpi_rank; + reply.dest = mssg_ptr->src; + reply.mssg_num = -1; /* set by send function */ + reply.base_addr = target_addr; + reply.len = 0; + reply.ver = 0; + reply.count = data[target_index].writes; + reply.magic = MSSG_MAGIC; + } + } + + if ( success ) { + + success = send_mssg(&reply, TRUE); + } + + if ( report_mssg ) { + + if ( success ) { + + HDfprintf(stdout, "%d request entry 0x%llx writes = %ld.\n", + (int)(mssg_ptr->src), + (long long)(data[target_index].base_addr), + (long)(data[target_index].writes)); + + } else { + + HDfprintf(stdout, "%d request entry 0x%llx writes = %ld FAILED.\n", + (int)(mssg_ptr->src), + (long long)(data[target_index].base_addr), + (long)(data[target_index].writes)); + + } + } + + return(success); + +} /* serve_entry_writes_request() */ + + +/***************************************************************************** + * + * Function: serve_entry_reads_request() + * + * Purpose: Serve an entry reads request. + * + * The function accepts a pointer to an instance of struct + * mssg_t as input. If all sanity checks pass, it sends + * the number of times that the indicated datum has been + * read since the last counter reset to the requesting + * process. + * + * Return: Success: TRUE + * + * Failure: FALSE + * + * Programmer: JRM -- 5/5/10 + * + *****************************************************************************/ +static hbool_t +serve_entry_reads_request(struct mssg_t * mssg_ptr) +{ + const char * fcn_name = "serve_entry_reads_request()"; + hbool_t report_mssg = FALSE; + hbool_t success = TRUE; + int target_index; + haddr_t target_addr; + struct mssg_t reply; + + if ( ( mssg_ptr == NULL ) || + ( mssg_ptr->req != REQ_ENTRY_READS_CODE ) || + ( mssg_ptr->magic != MSSG_MAGIC ) ) { + + nerrors++; + success = FALSE; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: Bad mssg on entry.\n", + world_mpi_rank, fcn_name); + } + } + + if ( success ) { + + target_addr = mssg_ptr->base_addr; + target_index = addr_to_datum_index(target_addr); + + if ( target_index < 0 ) { + + nerrors++; + success = FALSE; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: addr lookup failed for %a.\n", + world_mpi_rank, fcn_name, target_addr); + } + } else { + + /* compose the reply message */ + reply.req = REQ_ENTRY_READS_RPLY_CODE; + reply.src = world_mpi_rank; + reply.dest = mssg_ptr->src; + reply.mssg_num = -1; /* set by send function */ + reply.base_addr = target_addr; + reply.len = 0; + reply.ver = 0; + reply.count = (long)(data[target_index].reads); + reply.magic = MSSG_MAGIC; + } + } + + if ( success ) { + + success = send_mssg(&reply, TRUE); + } + + if ( report_mssg ) { + + if ( success ) { + + HDfprintf(stdout, "%d request entry 0x%llx reads = %ld.\n", + (int)(mssg_ptr->src), + (long long)(data[target_index].base_addr), + (long)(data[target_index].reads)); + + } else { + + HDfprintf(stdout, "%d request entry 0x%llx reads = %ld FAILED.\n", + (int)(mssg_ptr->src), + (long long)(data[target_index].base_addr), + (long)(data[target_index].reads)); + + } + } + + return(success); + +} /* serve_entry_reads_request() */ + + +/***************************************************************************** + * + * Function: serve_rw_count_reset_request() + * + * Purpose: Serve read/write count reset request. + * + * The function accepts a pointer to an instance of struct + * mssg_t as input. If all sanity checks pass, it resets the + * read/write counters, and sends a confirmation message to + * the calling process. + * + * Return: Success: TRUE + * + * Failure: FALSE + * + * Programmer: JRM -- 5/5/10 + * + *****************************************************************************/ +static hbool_t +serve_rw_count_reset_request(struct mssg_t * mssg_ptr) +{ + const char * fcn_name = "serve_rw_count_reset_request()"; + hbool_t report_mssg = FALSE; + hbool_t success = TRUE; + struct mssg_t reply; + + if ( ( mssg_ptr == NULL ) || + ( mssg_ptr->req != REQ_RW_COUNT_RESET_CODE ) || + ( mssg_ptr->magic != MSSG_MAGIC ) ) { + + nerrors++; + success = FALSE; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: Bad mssg on entry.\n", + world_mpi_rank, fcn_name); + } + } + + if ( success ) { + + success = reset_server_counters(); + } + + if ( success ) { + + /* compose the reply message */ + reply.req = REQ_RW_COUNT_RESET_RPLY_CODE; + reply.src = world_mpi_rank; + reply.dest = mssg_ptr->src; + reply.mssg_num = -1; /* set by send function */ + reply.base_addr = 0; + reply.len = 0; + reply.ver = 0; + reply.count = 0; + reply.magic = MSSG_MAGIC; + } + + if ( success ) { + + success = send_mssg(&reply, TRUE); + } + + if ( report_mssg ) { + + if ( success ) { + + HDfprintf(stdout, "%d request R/W counter reset.\n", + (int)(mssg_ptr->src)); + + } else { + + HDfprintf(stdout, "%d request R/w counter reset FAILED.\n", + (int)(mssg_ptr->src)); + + } + } + + return(success); + +} /* serve_rw_count_reset_request() */ + /*****************************************************************************/ /**************************** Call back functions ****************************/ @@ -1662,21 +2323,8 @@ serve_write_request(struct mssg_t * mssg_ptr) * Programmer: John Mainzer * 12/29/05 * - * Modifications: - * - * JRM -- 7/11/06 - * Modified code to support the local_len field of datum. - * This field allow us to track the cache's value for the - * length of the entry, while retaining the original - * value for communications with the server. - * - * JRM -- 2/4/09 - * Added code to set the cleared flag when a dirty entry is - * cleared. - * *------------------------------------------------------------------------- */ - static herr_t clear_datum(H5F_t * f, void * thing, @@ -1728,6 +2376,7 @@ clear_datum(H5F_t * f, } /* clear_datum() */ + /*------------------------------------------------------------------------- * Function: destroy_datum() * @@ -1740,17 +2389,8 @@ clear_datum(H5F_t * f, * Programmer: John Mainzer * 12/29/05 * - * Modifications: - * - * JRM -- 7/11/06 - * Modified code to support the local_len field of datum. - * This field allow us to track the cache's value for the - * length of the entry, while retaining the original - * value for communications with the server. - * *------------------------------------------------------------------------- */ - static herr_t destroy_datum(H5F_t UNUSED * f, void * thing) @@ -1785,6 +2425,7 @@ destroy_datum(H5F_t UNUSED * f, } /* destroy_datum() */ + /*------------------------------------------------------------------------- * Function: flush_datum * @@ -1796,27 +2437,8 @@ destroy_datum(H5F_t UNUSED * f, * Programmer: John Mainzer * 12/29/05 * - * Modifications: - * - * JRM -- 5/9/06 - * Added code to receive the write request ack messages - * from the server. This is part of a speculative fix to - * a bug spotted on Cobalt. If it doesn't fix the problem, - * it will narrow down the possibilities. - * - * JRM -- 7/11/06 - * Modified code to support the local_len field of datum. - * This field allow us to track the cache's value for the - * length of the entry, while retaining the original - * value for communications with the server. - * - * JRM -- 2/4/09 - * Added code to set the flushed flag when a dirty entry - * is flushed. - * *------------------------------------------------------------------------- */ - static herr_t flush_datum(H5F_t *f, hid_t UNUSED dxpl_id, @@ -1825,15 +2447,31 @@ flush_datum(H5F_t *f, void *thing) { const char * fcn_name = "flush_datum()"; + hbool_t was_dirty = FALSE; herr_t ret_value = SUCCEED; int idx; struct datum * entry_ptr; struct mssg_t mssg; + H5C_t * cache_ptr; + struct H5AC_aux_t * aux_ptr; HDassert( thing ); entry_ptr = (struct datum *)thing; + HDassert( f ); + HDassert( f->shared ); + HDassert( f->shared->cache ); + + cache_ptr = f->shared->cache; + + HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); + HDassert( cache_ptr->aux_ptr ); + + aux_ptr = (H5AC_aux_t *)(f->shared->cache->aux_ptr); + + HDassert( aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC ); + idx = addr_to_datum_index(entry_ptr->base_addr); HDassert( idx >= 0 ); @@ -1847,7 +2485,10 @@ flush_datum(H5F_t *f, HDassert( entry_ptr->header.is_dirty == entry_ptr->dirty ); - if ( ( file_mpi_rank != 0 ) && ( entry_ptr->dirty ) ) { + if ( ( file_mpi_rank != 0 ) && + ( entry_ptr->dirty ) && + ( aux_ptr->metadata_write_strategy == + H5AC_METADATA_WRITE_STRATEGY__PROCESS_0_ONLY ) ) { ret_value = FAIL; HDfprintf(stdout, @@ -1859,6 +2500,8 @@ flush_datum(H5F_t *f, if ( entry_ptr->header.is_dirty ) { + was_dirty = TRUE; /* so we will receive the ack if requested */ + /* compose the message */ mssg.req = WRITE_REQ_CODE; mssg.src = world_mpi_rank; @@ -1867,6 +2510,7 @@ flush_datum(H5F_t *f, mssg.base_addr = entry_ptr->base_addr; mssg.len = entry_ptr->len; mssg.ver = entry_ptr->ver; + mssg.count = 0; mssg.magic = MSSG_MAGIC; if ( ! send_mssg(&mssg, FALSE) ) { @@ -1889,7 +2533,7 @@ flush_datum(H5F_t *f, #if DO_WRITE_REQ_ACK - if ( ( ret_value == SUCCEED ) && ( entry_ptr->header.is_dirty ) ) { + if ( ( ret_value == SUCCEED ) && ( was_dirty ) ) { if ( ! recv_mssg(&mssg, WRITE_REQ_ACK_CODE) ) { @@ -1986,6 +2630,7 @@ load_datum(H5F_t UNUSED *f, mssg.base_addr = entry_ptr->base_addr; mssg.len = entry_ptr->len; mssg.ver = 0; /* bogus -- should be corrected by server */ + mssg.count = 0; /* not used */ mssg.magic = MSSG_MAGIC; if ( ! send_mssg(&mssg, FALSE) ) { @@ -2420,7 +3065,7 @@ local_pin_and_unpin_random_entries(H5F_t * file_ptr, } /* local_pin_and_unpin_random_entries() */ - + /***************************************************************************** * Function: local_pin_random_entry() * @@ -2436,10 +3081,7 @@ local_pin_and_unpin_random_entries(H5F_t * file_ptr, * Programmer: John Mainzer * 4/12/06 * - * Modifications: - * *****************************************************************************/ - void local_pin_random_entry(H5F_t * file_ptr, int min_idx, @@ -2940,7 +3582,7 @@ pin_protected_entry(int32_t idx, } /* pin_protected_entry() */ - + /***************************************************************************** * Function: move_entry() * @@ -2956,13 +3598,7 @@ pin_protected_entry(int32_t idx, * Programmer: John Mainzer * 1/10/06 * - * Modifications: - * - * 7/11/06 -- JRM - * Added support for the phony_len field in datum. - * *****************************************************************************/ - void move_entry(H5F_t * file_ptr, int32_t old_idx, @@ -2996,7 +3632,35 @@ move_entry(H5F_t * file_ptr, old_addr = old_entry_ptr->base_addr; new_addr = new_entry_ptr->base_addr; - result = H5AC_move_entry(file_ptr, &(types[0]), old_addr, new_addr); + /* Moving will mark the entry dirty if it is not already */ + old_entry_ptr->dirty = TRUE; + + /* touch up versions, base_addrs, and data_index. Do this + * now as it is possible that the rename will trigger a + * sync point. + */ + if(old_entry_ptr->ver < new_entry_ptr->ver) + old_entry_ptr->ver = new_entry_ptr->ver; + else + (old_entry_ptr->ver)++; + + old_entry_ptr->base_addr = new_addr; + new_entry_ptr->base_addr = old_addr; + + data_index[old_entry_ptr->index] = new_idx; + data_index[new_entry_ptr->index] = old_idx; + + tmp = old_entry_ptr->index; + old_entry_ptr->index = new_entry_ptr->index; + new_entry_ptr->index = tmp; + + if(old_entry_ptr->local_len != new_entry_ptr->local_len) { + tmp_len = old_entry_ptr->local_len; + old_entry_ptr->local_len = new_entry_ptr->local_len; + new_entry_ptr->local_len = tmp_len; + } /* end if */ + + result = H5AC_move_entry(file_ptr, &(types[0]), old_addr, new_addr); if ( ( result < 0 ) || ( old_entry_ptr->header.addr != new_addr ) ) { @@ -3009,43 +3673,118 @@ move_entry(H5F_t * file_ptr, } else { HDassert( ((old_entry_ptr->header).type)->id == DATUM_ENTRY_TYPE ); - HDassert( old_entry_ptr->header.is_dirty ); - old_entry_ptr->dirty = TRUE; - /* touch up versions, base_addrs, and data_index */ + if ( ! (old_entry_ptr->header.is_dirty) ) { - if ( old_entry_ptr->ver < new_entry_ptr->ver ) { + /* it is possible that we just exceeded the dirty bytes + * threshold, triggering a write of the newly inserted + * entry. Test for this, and only flag an error if this + * is not the case. + */ - old_entry_ptr->ver = new_entry_ptr->ver; + struct H5AC_aux_t * aux_ptr; - } else { + aux_ptr = ((H5AC_aux_t *)(file_ptr->shared->cache->aux_ptr)); - (old_entry_ptr->ver)++; + if ( ! ( ( aux_ptr != NULL ) && + ( aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC ) && + ( aux_ptr->dirty_bytes == 0 ) ) ) { + nerrors++; + if ( verbose ) { + HDfprintf(stdout, + "%d:%s: data[%d].header.is_dirty = %d.\n", + world_mpi_rank, fcn_name, new_idx, + (int)(data[new_idx].header.is_dirty)); + } + } + } else { + + HDassert( old_entry_ptr->header.is_dirty ); } + } + } - old_entry_ptr->base_addr = new_addr; - new_entry_ptr->base_addr = old_addr; +} /* move_entry() */ - data_index[old_entry_ptr->index] = new_idx; - data_index[new_entry_ptr->index] = old_idx; + +/***************************************************************************** + * + * Function: reset_server_counts() + * + * Purpose: Send a message to the server process requesting it to reset + * its counters. Await confirmation message. + * + * Return: Success: TRUE + * + * Failure: FALSE + * + * Programmer: JRM -- 5/6/10 + * + *****************************************************************************/ +static hbool_t +reset_server_counts(void) +{ + const char * fcn_name = "reset_server_counts()"; + hbool_t success = TRUE; /* will set to FALSE if appropriate. */ + struct mssg_t mssg; + + if ( success ) { - tmp = old_entry_ptr->index; - old_entry_ptr->index = new_entry_ptr->index; - new_entry_ptr->index = tmp; + /* compose the message */ + mssg.req = REQ_RW_COUNT_RESET_CODE; + mssg.src = world_mpi_rank; + mssg.dest = world_server_mpi_rank; + mssg.mssg_num = -1; /* set by send function */ + mssg.base_addr = 0; + mssg.len = 0; + mssg.ver = 0; + mssg.count = 0; + mssg.magic = MSSG_MAGIC; - if ( old_entry_ptr->local_len != new_entry_ptr->local_len ) { + if ( ! send_mssg(&mssg, FALSE) ) { - tmp_len = old_entry_ptr->local_len; - old_entry_ptr->local_len = new_entry_ptr->local_len; - new_entry_ptr->local_len = tmp_len; - } + nerrors++; + success = FALSE; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: send_mssg() failed.\n", + world_mpi_rank, fcn_name); + } } } - return; + if ( success ) { -} /* move_entry() */ + if ( ! recv_mssg(&mssg, REQ_RW_COUNT_RESET_RPLY_CODE) ) { + + nerrors++; + success = FALSE; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: recv_mssg() failed.\n", + world_mpi_rank, fcn_name); + } + } else if ( ( mssg.req != REQ_RW_COUNT_RESET_RPLY_CODE ) || + ( mssg.src != world_server_mpi_rank ) || + ( mssg.dest != world_mpi_rank ) || + ( mssg.base_addr != 0 ) || + ( mssg.len != 0 ) || + ( mssg.ver != 0 ) || + ( mssg.count != 0 ) || + ( mssg.magic != MSSG_MAGIC ) ) { + + nerrors++; + success = FALSE; + if ( verbose ) { + HDfprintf(stdout, + "%d:%s: Bad data in req r/w counter reset reply.\n", + world_mpi_rank, fcn_name); + } + } + } + + return(success); + +} /* reset_server_counts() */ /***************************************************************************** @@ -3121,7 +3860,7 @@ resize_entry(int32_t idx, } /* resize_entry() */ - + /***************************************************************************** * * Function: setup_cache_for_test() @@ -3140,22 +3879,19 @@ resize_entry(int32_t idx, * * Programmer: JRM -- 1/4/06 * - * Modifications: - * - * None. - * *****************************************************************************/ - hbool_t setup_cache_for_test(hid_t * fid_ptr, H5F_t ** file_ptr_ptr, - H5C_t ** cache_ptr_ptr) + H5C_t ** cache_ptr_ptr, + int metadata_write_strategy) { const char * fcn_name = "setup_cache_for_test()"; hbool_t success = FALSE; /* will set to TRUE if appropriate. */ hbool_t enable_rpt_fcn = FALSE; hid_t fid = -1; H5AC_cache_config_t config; + H5AC_cache_config_t test_config; H5F_t * file_ptr = NULL; H5C_t * cache_ptr = NULL; @@ -3213,7 +3949,7 @@ setup_cache_for_test(hid_t * fid_ptr, success = TRUE; } - if ( ( success ) && ( enable_rpt_fcn ) ) { + if ( success ) { config.version = H5AC__CURR_CACHE_CONFIG_VERSION; @@ -3221,12 +3957,13 @@ setup_cache_for_test(hid_t * fid_ptr, != SUCCEED ) { HDfprintf(stdout, - "%d:%s: H5AC_get_cache_auto_resize_config() failed.\n", + "%d:%s: H5AC_get_cache_auto_resize_config(1) failed.\n", world_mpi_rank, fcn_name); } else { - config.rpt_fcn_enabled = TRUE; + config.rpt_fcn_enabled = enable_rpt_fcn; + config.metadata_write_strategy = metadata_write_strategy; if ( H5AC_set_cache_auto_resize_config(cache_ptr, &config) != SUCCEED ) { @@ -3234,7 +3971,8 @@ setup_cache_for_test(hid_t * fid_ptr, HDfprintf(stdout, "%d:%s: H5AC_set_cache_auto_resize_config() failed.\n", world_mpi_rank, fcn_name); - } else { + + } else if ( enable_rpt_fcn ) { HDfprintf(stdout, "%d:%s: rpt_fcn enabled.\n", world_mpi_rank, fcn_name); @@ -3242,6 +3980,71 @@ setup_cache_for_test(hid_t * fid_ptr, } } + /* verify that the metadata write strategy is set as expected. Must + * do this here, as this field is only set in the parallel case. Hence + * we can't do our usual checks in the serial case. + */ + + if ( success ) /* verify that the metadata write strategy is as expected */ + { + if ( cache_ptr->aux_ptr == NULL ) { + + nerrors++; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: cache_ptr->aux_ptr == NULL.\n", + world_mpi_rank, fcn_name); + } + } else if ( ((H5AC_aux_t *)(cache_ptr->aux_ptr))->magic != + H5AC__H5AC_AUX_T_MAGIC ) { + + nerrors++; + if ( verbose ) { + HDfprintf(stdout, + "%d:%s: cache_ptr->aux_ptr->magic != H5AC__H5AC_AUX_T_MAGIC.\n", + world_mpi_rank, fcn_name); + } + } else if( ((H5AC_aux_t *)(cache_ptr->aux_ptr))->metadata_write_strategy + != metadata_write_strategy ) { + + nerrors++; + if ( verbose ) { + HDfprintf(stdout, + "%d:%s: bad cache_ptr->aux_ptr->metadata_write_strategy\n", + world_mpi_rank, fcn_name); + } + } + } + + /* also verify that the expected metadata write strategy is reported + * when we get the current configuration. + */ + + if ( success ) { + + test_config.version = H5AC__CURR_CACHE_CONFIG_VERSION; + + if ( H5AC_get_cache_auto_resize_config(cache_ptr, &test_config) + != SUCCEED ) { + + HDfprintf(stdout, + "%d:%s: H5AC_get_cache_auto_resize_config(2) failed.\n", + world_mpi_rank, fcn_name); + + } else if ( test_config.metadata_write_strategy != + metadata_write_strategy ) { + + nerrors++; + + if ( verbose ) { + + HDfprintf(stdout, + "%d:%s: unexpected metadata_write_strategy.\n", + world_mpi_rank, fcn_name); + } + } + } + + #if DO_SYNC_AFTER_WRITE if ( success ) { @@ -3259,10 +4062,153 @@ setup_cache_for_test(hid_t * fid_ptr, #endif /* DO_SYNC_AFTER_WRITE */ + if ( success ) { + + if ( H5AC_set_sync_point_done_callback(cache_ptr, verify_writes) != + SUCCEED ) { + + nerrors++; + if ( verbose ) { + HDfprintf(stdout, + "%d:%s: H5AC_set_sync_point_done_callback failed.\n", + world_mpi_rank, fcn_name); + } + } + } + return(success); } /* setup_cache_for_test() */ + +/***************************************************************************** + * + * Function: verify_writes() + * + * Purpose: Verify that the indicated entries have been written exactly + * once each, and that the indicated total number of writes + * has been processed by the server process. Flag an error if + * discrepency is noted. Finally reset the counters maintained + * by the server process. + * + * This function should only be called by the metadata cache + * as the "sync point done" function, as it must do some + * synchronization to avoid false positives. + * + * Note that at present, this function does not allow for the + * case in which one or more of the indicated entries should + * have been written more than once since the last time the + * server process's counters were reset. That is fine for now, + * as with the current metadata write strategies, no entry + * should be written more than once per sync point. If this + * changes this limitation will have to be revisited. + * + * Return: void. + * + * Programmer: JRM -- 5/9/10 + * + *****************************************************************************/ +void +verify_writes(int num_writes, + haddr_t * written_entries_tbl) +{ + const char * fcn_name = "verify_writes()"; + const hbool_t report = FALSE; + hbool_t proceed = TRUE; + int i; + + HDassert( world_mpi_rank != world_server_mpi_rank ); + HDassert( num_writes >= 0 ); + HDassert( ( num_writes == 0 ) || + ( written_entries_tbl != NULL ) ); + + /* barrier to ensure that all other processes are ready to leave + * the sync point as well. + */ + if ( proceed ) { + + if ( MPI_SUCCESS != MPI_Barrier(file_mpi_comm) ) { + + proceed = FALSE; + nerrors++; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: barrier 1 failed.\n", + world_mpi_rank, fcn_name); + } + } + } + + if ( proceed ) { + + proceed = verify_total_writes(num_writes); + } + + while ( ( proceed ) && ( i < num_writes ) ) + { + proceed = verify_entry_writes(written_entries_tbl[i], 1); + i++; + } + + /* barrier to ensure that all other processes have finished verifying + * the number of writes before we reset the counters. + */ + if ( proceed ) { + + if ( MPI_SUCCESS != MPI_Barrier(file_mpi_comm) ) { + + proceed = FALSE; + nerrors++; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: barrier 2 failed.\n", + world_mpi_rank, fcn_name); + } + } + } + + if ( proceed ) { + + proceed = reset_server_counts(); + } + + /* if requested, display status of check to stdout */ + if ( ( report ) && ( file_mpi_rank == 0 ) ) { + + if ( proceed ) { + + HDfprintf(stdout, "%d:%s: verified %d writes.\n", + world_mpi_rank, fcn_name, num_writes); + + } else { + + HDfprintf(stdout, "%d:%s: FAILED to verify %d writes.\n", + world_mpi_rank, fcn_name, num_writes); + + } + } + + /* final barrier to ensure that all processes think that the server + * counters have been reset before we leave the sync point. This + * barrier is probaby not necessary at this point in time (5/9/10), + * but I can think of at least one likely change to the metadata write + * strategies that will require it -- hence its insertion now. + */ + if ( proceed ) { + + if ( MPI_SUCCESS != MPI_Barrier(file_mpi_comm) ) { + + proceed = FALSE; + nerrors++; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: barrier 3 failed.\n", + world_mpi_rank, fcn_name); + } + } + } + + return; + +} /* verify_writes() */ + /***************************************************************************** * @@ -3509,6 +4455,425 @@ take_down_cache(hid_t fid) } /* take_down_cache() */ + +/***************************************************************************** + * Function: verify_entry_reads + * + * Purpose: Query the server to determine the number of times the + * indicated entry has been read since the last time the + * server counters were reset. + * + * Return TRUE if successful, and if the supplied expected + * number of reads matches the number of reads reported by + * the server process. + * + * Return FALSE and flag an error otherwise. + * + * Return: TRUE if successful, FALSE otherwise. + * + * Programmer: John Mainzer + * 5/6/10 + * + *------------------------------------------------------------------------- + */ +static hbool_t +verify_entry_reads(haddr_t addr, + int expected_entry_reads) +{ + const char * fcn_name = "verify_entry_reads()"; + hbool_t success = TRUE; + int reported_entry_reads; + struct mssg_t mssg; + + if ( success ) { + + /* compose the message */ + mssg.req = REQ_ENTRY_READS_CODE; + mssg.src = world_mpi_rank; + mssg.dest = world_server_mpi_rank; + mssg.mssg_num = -1; /* set by send function */ + mssg.base_addr = addr; + mssg.len = 0; /* not used */ + mssg.ver = 0; /* not used */ + mssg.count = 0; /* not used */ + mssg.magic = MSSG_MAGIC; + + if ( ! send_mssg(&mssg, FALSE) ) { + + nerrors++; + success = FALSE; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: send_mssg() failed.\n", + world_mpi_rank, fcn_name); + } + } + } + + if ( success ) { + + if ( ! recv_mssg(&mssg, REQ_ENTRY_READS_RPLY_CODE) ) { + + nerrors++; + success = FALSE; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: recv_mssg() failed.\n", + world_mpi_rank, fcn_name); + } + } + } + + if ( success ) { + + if ( ( mssg.req != REQ_ENTRY_READS_RPLY_CODE ) || + ( mssg.src != world_server_mpi_rank ) || + ( mssg.dest != world_mpi_rank ) || + ( mssg.base_addr != addr ) || + ( mssg.len != 0 ) || + ( mssg.ver != 0 ) || + ( mssg.magic != MSSG_MAGIC ) ) { + + nerrors++; + success = FALSE; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: Bad data in req entry reads reply.\n", + world_mpi_rank, fcn_name); + } + } else { + + reported_entry_reads = mssg.count; + } + } + + if ( ! success ) { + + if ( reported_entry_reads != expected_entry_reads ) { + + nerrors++; + success = FALSE; + if ( verbose ) { + HDfprintf(stdout, + "%d:%s: rep/exp entry 0x%llx reads mismatch (%ld/%ld).\n", + world_mpi_rank, fcn_name, (long long)addr, + reported_entry_reads, expected_entry_reads); + } + } + } + + return(success); + +} /* verify_entry_reads() */ + + +/***************************************************************************** + * Function: verify_entry_writes + * + * Purpose: Query the server to determine the number of times the + * indicated entry has been written since the last time the + * server counters were reset. + * + * Return TRUE if successful, and if the supplied expected + * number of reads matches the number of reads reported by + * the server process. + * + * Return FALSE and flag an error otherwise. + * + * Return: TRUE if successful, FALSE otherwise. + * + * Programmer: John Mainzer + * 5/6/10 + * + *------------------------------------------------------------------------- + */ +static hbool_t +verify_entry_writes(haddr_t addr, + int expected_entry_writes) +{ + const char * fcn_name = "verify_entry_writes()"; + hbool_t success = TRUE; + int reported_entry_writes; + struct mssg_t mssg; + + if ( success ) { + + /* compose the message */ + mssg.req = REQ_ENTRY_WRITES_CODE; + mssg.src = world_mpi_rank; + mssg.dest = world_server_mpi_rank; + mssg.mssg_num = -1; /* set by send function */ + mssg.base_addr = addr; + mssg.len = 0; /* not used */ + mssg.ver = 0; /* not used */ + mssg.count = 0; /* not used */ + mssg.magic = MSSG_MAGIC; + + if ( ! send_mssg(&mssg, FALSE) ) { + + nerrors++; + success = FALSE; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: send_mssg() failed.\n", + world_mpi_rank, fcn_name); + } + } + } + + if ( success ) { + + if ( ! recv_mssg(&mssg, REQ_ENTRY_WRITES_RPLY_CODE) ) { + + nerrors++; + success = FALSE; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: recv_mssg() failed.\n", + world_mpi_rank, fcn_name); + } + } + } + + if ( success ) { + + if ( ( mssg.req != REQ_ENTRY_WRITES_RPLY_CODE ) || + ( mssg.src != world_server_mpi_rank ) || + ( mssg.dest != world_mpi_rank ) || + ( mssg.base_addr != addr ) || + ( mssg.len != 0 ) || + ( mssg.ver != 0 ) || + ( mssg.magic != MSSG_MAGIC ) ) { + + nerrors++; + success = FALSE; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: Bad data in req entry writes reply.\n", + world_mpi_rank, fcn_name); + } + } else { + + reported_entry_writes = mssg.count; + } + } + + if ( ! success ) { + + if ( reported_entry_writes != expected_entry_writes ) { + + nerrors++; + success = FALSE; + if ( verbose ) { + HDfprintf(stdout, + "%d:%s: rep/exp entry 0x%llx writes mismatch (%ld/%ld).\n", + world_mpi_rank, fcn_name, (long long)addr, + reported_entry_writes, expected_entry_writes); + } + } + } + + return(success); + +} /* verify_entry_writes() */ + + +/***************************************************************************** + * + * Function: verify_total_reads() + * + * Purpose: Query the server to obtain the total reads since the last + * server counter reset, and compare this value with the supplied + * expected value. + * + * If the values match, return TRUE. + * + * If the values don't match, flag an error and return FALSE. + * + * Return: Success: TRUE + * + * Failure: FALSE + * + * Programmer: JRM -- 5/6/10 + * + *****************************************************************************/ +static hbool_t +verify_total_reads(int expected_total_reads) +{ + const char * fcn_name = "verify_total_reads()"; + hbool_t success = TRUE; /* will set to FALSE if appropriate. */ + long reported_total_reads; + struct mssg_t mssg; + + if ( success ) { + + /* compose the message */ + mssg.req = REQ_TTL_READS_CODE; + mssg.src = world_mpi_rank; + mssg.dest = world_server_mpi_rank; + mssg.mssg_num = -1; /* set by send function */ + mssg.base_addr = 0; + mssg.len = 0; + mssg.ver = 0; + mssg.count = 0; + mssg.magic = MSSG_MAGIC; + + if ( ! send_mssg(&mssg, FALSE) ) { + + nerrors++; + success = FALSE; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: send_mssg() failed.\n", + world_mpi_rank, fcn_name); + } + } + } + + if ( success ) { + + if ( ! recv_mssg(&mssg, REQ_TTL_READS_RPLY_CODE) ) { + + nerrors++; + success = FALSE; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: recv_mssg() failed.\n", + world_mpi_rank, fcn_name); + } + } else if ( ( mssg.req != REQ_TTL_READS_RPLY_CODE ) || + ( mssg.src != world_server_mpi_rank ) || + ( mssg.dest != world_mpi_rank ) || + ( mssg.base_addr != 0 ) || + ( mssg.len != 0 ) || + ( mssg.ver != 0 ) || + ( mssg.magic != MSSG_MAGIC ) ) { + + nerrors++; + success = FALSE; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: Bad data in req total reads reply.\n", + world_mpi_rank, fcn_name); + } + } else { + + reported_total_reads = mssg.count; + } + } + + if ( success ) { + + if ( reported_total_reads != expected_total_reads ) { + + nerrors++; + success = FALSE; + if ( verbose ) { + HDfprintf(stdout, + "%d:%s: reported/expected total reads mismatch (%ld/%ld).\n", + world_mpi_rank, fcn_name, + reported_total_reads, expected_total_reads); + + } + } + } + + return(success); + +} /* verify_total_reads() */ + + +/***************************************************************************** + * + * Function: verify_total_writes() + * + * Purpose: Query the server to obtain the total writes since the last + * server counter reset, and compare this value with the supplied + * expected value. + * + * If the values match, return TRUE. + * + * If the values don't match, flag an error and return FALSE. + * + * Return: Success: TRUE + * + * Failure: FALSE + * + * Programmer: JRM -- 5/6/10 + * + *****************************************************************************/ +static hbool_t +verify_total_writes(int expected_total_writes) +{ + const char * fcn_name = "verify_total_writes()"; + hbool_t success = TRUE; /* will set to FALSE if appropriate. */ + long reported_total_writes; + struct mssg_t mssg; + + if ( success ) { + + /* compose the message */ + mssg.req = REQ_TTL_WRITES_CODE; + mssg.src = world_mpi_rank; + mssg.dest = world_server_mpi_rank; + mssg.mssg_num = -1; /* set by send function */ + mssg.base_addr = 0; + mssg.len = 0; + mssg.ver = 0; + mssg.count = 0; + mssg.magic = MSSG_MAGIC; + + if ( ! send_mssg(&mssg, FALSE) ) { + + nerrors++; + success = FALSE; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: send_mssg() failed.\n", + world_mpi_rank, fcn_name); + } + } + } + + if ( success ) { + + if ( ! recv_mssg(&mssg, REQ_TTL_WRITES_RPLY_CODE) ) { + + nerrors++; + success = FALSE; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: recv_mssg() failed.\n", + world_mpi_rank, fcn_name); + } + } else if ( ( mssg.req != REQ_TTL_WRITES_RPLY_CODE ) || + ( mssg.src != world_server_mpi_rank ) || + ( mssg.dest != world_mpi_rank ) || + ( mssg.base_addr != 0 ) || + ( mssg.len != 0 ) || + ( mssg.ver != 0 ) || + ( mssg.magic != MSSG_MAGIC ) ) { + + nerrors++; + success = FALSE; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: Bad data in req total reads reply.\n", + world_mpi_rank, fcn_name); + } + } else { + + reported_total_writes = mssg.count; + } + } + + if ( success ) { + + if ( reported_total_writes != expected_total_writes ) { + + nerrors++; + success = FALSE; + if ( verbose ) { + HDfprintf(stdout, + "%d:%s: reported/expected total writes mismatch (%ld/%ld).\n", + world_mpi_rank, fcn_name, + reported_total_writes, expected_total_writes); + } + } + } + + return(success); + +} /* verify_total_writes() */ + /***************************************************************************** * Function: unlock_entry() @@ -3695,6 +5060,7 @@ unpin_entry(H5F_t * file_ptr, /****************************** test functions *******************************/ /*****************************************************************************/ + /***************************************************************************** * * Function: server_smoke_check() @@ -3707,21 +5073,7 @@ unpin_entry(H5F_t * file_ptr, * * Programmer: JRM -- 12/21/05 * - * Modifications: - * - * JRM -- 5/9/06 - * Added code supporting the write request ack message. This - * message was added to eliminate one possible cause of a - * bug spotted on cobalt. If this doesn't fix the problem, - * it will narrow things down a bit. - * - * JRM -- 5/10/06 - * Added call to do_sync(). This is part of an attempt to - * optimize out the slowdown caused by the addition of the - * write request ack message. - * *****************************************************************************/ - hbool_t server_smoke_check(void) { @@ -3761,6 +5113,7 @@ server_smoke_check(void) mssg.base_addr = data[world_mpi_rank].base_addr; mssg.len = data[world_mpi_rank].len; mssg.ver = ++(data[world_mpi_rank].ver); + mssg.count = 0; mssg.magic = MSSG_MAGIC; if ( ! ( success = send_mssg(&mssg, FALSE) ) ) { @@ -3813,6 +5166,50 @@ server_smoke_check(void) do_sync(); + /* barrier to allow all writes to complete */ + if ( MPI_SUCCESS != MPI_Barrier(file_mpi_comm) ) { + + success = FALSE; + nerrors++; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: barrier 1 failed.\n", + world_mpi_rank, fcn_name); + } + } + + /* verify that the expected entries have been written, the total */ + if ( success ) { + + success = verify_entry_writes(data[world_mpi_rank].base_addr, 1); + } + + if ( success ) { + + success = verify_entry_reads(data[world_mpi_rank].base_addr, 0); + } + + if ( success ) { + + success = verify_total_writes(world_mpi_size - 1); + } + + if ( success ) { + + success = verify_total_reads(0); + } + + /* barrier to allow all writes to complete */ + if ( MPI_SUCCESS != MPI_Barrier(file_mpi_comm) ) { + + success = FALSE; + nerrors++; + if ( verbose ) { + + HDfprintf(stdout, "%d:%s: barrier 2 failed.\n", + world_mpi_rank, fcn_name); + } + } + /* compose the read message */ mssg.req = READ_REQ_CODE; mssg.src = world_mpi_rank; @@ -3821,6 +5218,7 @@ server_smoke_check(void) mssg.base_addr = data[world_mpi_rank].base_addr; mssg.len = data[world_mpi_rank].len; mssg.ver = 0; /* bogus -- should be corrected by server */ + mssg.count = 0; mssg.magic = MSSG_MAGIC; if ( success ) { @@ -3872,6 +5270,98 @@ server_smoke_check(void) } } + /* barrier to allow all writes to complete */ + if ( MPI_SUCCESS != MPI_Barrier(file_mpi_comm) ) { + + success = FALSE; + nerrors++; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: barrier 3 failed.\n", + world_mpi_rank, fcn_name); + } + } + + /* verify that the expected entries have been read, and the total */ + if ( success ) { + + success = verify_entry_writes(data[world_mpi_rank].base_addr, 1); + } + + if ( success ) { + + success = verify_entry_reads(data[world_mpi_rank].base_addr, 1); + } + + if ( success ) { + + success = verify_total_writes(world_mpi_size - 1); + } + + if ( success ) { + + success = verify_total_reads(world_mpi_size - 1); + } + + if ( MPI_SUCCESS != MPI_Barrier(file_mpi_comm) ) { + + success = FALSE; + nerrors++; + if ( verbose ) { + + HDfprintf(stdout, "%d:%s: barrier 4 failed.\n", + world_mpi_rank, fcn_name); + } + } + + /* reset the counters */ + if ( success ) { + + success = reset_server_counts(); + } + + if ( MPI_SUCCESS != MPI_Barrier(file_mpi_comm) ) { + + success = FALSE; + nerrors++; + if ( verbose ) { + + HDfprintf(stdout, "%d:%s: barrier 5 failed.\n", + world_mpi_rank, fcn_name); + } + } + + /* verify that the counters have been reset */ + if ( success ) { + + success = verify_entry_writes(data[world_mpi_rank].base_addr, 0); + } + + if ( success ) { + + success = verify_entry_reads(data[world_mpi_rank].base_addr, 0); + } + + if ( success ) { + + success = verify_total_writes(0); + } + + if ( success ) { + + success = verify_total_reads(0); + } + + if ( MPI_SUCCESS != MPI_Barrier(file_mpi_comm) ) { + + success = FALSE; + nerrors++; + if ( verbose ) { + + HDfprintf(stdout, "%d:%s: barrier 6 failed.\n", + world_mpi_rank, fcn_name); + } + } + /* compose the done message */ mssg.req = DONE_REQ_CODE; mssg.src = world_mpi_rank; @@ -3880,6 +5370,7 @@ server_smoke_check(void) mssg.base_addr = 0; /* not used */ mssg.len = 0; /* not used */ mssg.ver = 0; /* not used */ + mssg.count = 0; mssg.magic = MSSG_MAGIC; if ( success ) { @@ -3918,6 +5409,7 @@ server_smoke_check(void) } /* server_smoke_check() */ + /***************************************************************************** * * Function: smoke_check_1() @@ -3930,14 +5422,9 @@ server_smoke_check(void) * * Programmer: JRM -- 1/4/06 * - * Modifications: - * - * None. - * *****************************************************************************/ - hbool_t -smoke_check_1(void) +smoke_check_1(int metadata_write_strategy) { const char * fcn_name = "smoke_check_1()"; hbool_t success = TRUE; @@ -3948,9 +5435,25 @@ smoke_check_1(void) H5C_t * cache_ptr = NULL; struct mssg_t mssg; - if ( world_mpi_rank == 0 ) { + switch ( metadata_write_strategy ) { + + case H5AC_METADATA_WRITE_STRATEGY__PROCESS_0_ONLY: + if ( world_mpi_rank == 0 ) { + TESTING("smoke check #1 -- process 0 only md write strategy"); + } + break; - TESTING("smoke check #1"); + case H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED: + if ( world_mpi_rank == 0 ) { + TESTING("smoke check #1 -- distributed md write strategy"); + } + break; + + default: + if ( world_mpi_rank == 0 ) { + TESTING("smoke check #1 -- unknown md write strategy"); + } + break; } nerrors = 0; @@ -3971,7 +5474,8 @@ smoke_check_1(void) } else /* run the clients */ { - if ( ! setup_cache_for_test(&fid, &file_ptr, &cache_ptr) ) { + if ( ! setup_cache_for_test(&fid, &file_ptr, &cache_ptr, + metadata_write_strategy) ) { nerrors++; fid = -1; @@ -4039,6 +5543,7 @@ smoke_check_1(void) mssg.base_addr = 0; /* not used */ mssg.len = 0; /* not used */ mssg.ver = 0; /* not used */ + mssg.count = 0; /* not used */ mssg.magic = MSSG_MAGIC; if ( success ) { @@ -4077,7 +5582,7 @@ smoke_check_1(void) } /* smoke_check_1() */ - + /***************************************************************************** * * Function: smoke_check_2() @@ -4093,18 +5598,9 @@ smoke_check_1(void) * * Programmer: JRM -- 1/12/06 * - * Modifications: - * - * JRM -- 4/13/06 - * Added pinned entry tests. - * - * JRM -- 4/28/06 - * Modified test to move pinned entries. - * *****************************************************************************/ - hbool_t -smoke_check_2(void) +smoke_check_2(int metadata_write_strategy) { const char * fcn_name = "smoke_check_2()"; hbool_t success = TRUE; @@ -4115,9 +5611,25 @@ smoke_check_2(void) H5C_t * cache_ptr = NULL; struct mssg_t mssg; - if ( world_mpi_rank == 0 ) { + switch ( metadata_write_strategy ) { - TESTING("smoke check #2"); + case H5AC_METADATA_WRITE_STRATEGY__PROCESS_0_ONLY: + if ( world_mpi_rank == 0 ) { + TESTING("smoke check #2 -- process 0 only md write strategy"); + } + break; + + case H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED: + if ( world_mpi_rank == 0 ) { + TESTING("smoke check #2 -- distributed md write strategy"); + } + break; + + default: + if ( world_mpi_rank == 0 ) { + TESTING("smoke check #2 -- unknown md write strategy"); + } + break; } nerrors = 0; @@ -4138,7 +5650,8 @@ smoke_check_2(void) } else /* run the clients */ { - if ( ! setup_cache_for_test(&fid, &file_ptr, &cache_ptr) ) { + if ( ! setup_cache_for_test(&fid, &file_ptr, &cache_ptr, + metadata_write_strategy) ) { nerrors++; fid = -1; @@ -4253,6 +5766,7 @@ smoke_check_2(void) mssg.base_addr = 0; /* not used */ mssg.len = 0; /* not used */ mssg.ver = 0; /* not used */ + mssg.count = 0; /* not used */ mssg.magic = MSSG_MAGIC; if ( success ) { @@ -4291,7 +5805,7 @@ smoke_check_2(void) } /* smoke_check_2() */ - + /***************************************************************************** * * Function: smoke_check_3() @@ -4310,18 +5824,9 @@ smoke_check_2(void) * * Programmer: JRM -- 1/13/06 * - * Modifications: - * - * Added code intended to ensure correct operation with large - * numbers of processors. - * JRM - 1/31/06 - * - * Added pinned entry tests. JRM - 4/14/06 - * *****************************************************************************/ - hbool_t -smoke_check_3(void) +smoke_check_3(int metadata_write_strategy) { const char * fcn_name = "smoke_check_3()"; hbool_t success = TRUE; @@ -4338,9 +5843,25 @@ smoke_check_3(void) H5C_t * cache_ptr = NULL; struct mssg_t mssg; - if ( world_mpi_rank == 0 ) { + switch ( metadata_write_strategy ) { + + case H5AC_METADATA_WRITE_STRATEGY__PROCESS_0_ONLY: + if ( world_mpi_rank == 0 ) { + TESTING("smoke check #3 -- process 0 only md write strategy"); + } + break; + + case H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED: + if ( world_mpi_rank == 0 ) { + TESTING("smoke check #3 -- distributed md write strategy"); + } + break; - TESTING("smoke check #3"); + default: + if ( world_mpi_rank == 0 ) { + TESTING("smoke check #3 -- unknown md write strategy"); + } + break; } /* 0 */ @@ -4373,7 +5894,8 @@ smoke_check_3(void) /* 1 */ if ( verbose ) {HDfprintf(stderr, "%d: cp = %d\n", world_mpi_rank, cp++);} - if ( ! setup_cache_for_test(&fid, &file_ptr, &cache_ptr) ) { + if ( ! setup_cache_for_test(&fid, &file_ptr, &cache_ptr, + metadata_write_strategy) ) { nerrors++; fid = -1; @@ -4612,6 +6134,7 @@ smoke_check_3(void) mssg.base_addr = 0; /* not used */ mssg.len = 0; /* not used */ mssg.ver = 0; /* not used */ + mssg.count = 0; /* not used */ mssg.magic = MSSG_MAGIC; if ( success ) { @@ -4654,7 +6177,7 @@ smoke_check_3(void) } /* smoke_check_3() */ - + /***************************************************************************** * * Function: smoke_check_4() @@ -4673,20 +6196,9 @@ smoke_check_3(void) * * Programmer: JRM -- 1/13/06 * - * Modifications: - * - * Added code intended to insure correct operation with large - * numbers of processors. - * JRM - 1/31/06 - * - * Added code testing pinned insertion of entries. - * - * JRM - 8/15/06 - * *****************************************************************************/ - hbool_t -smoke_check_4(void) +smoke_check_4(int metadata_write_strategy) { const char * fcn_name = "smoke_check_4()"; hbool_t success = TRUE; @@ -4701,9 +6213,25 @@ smoke_check_4(void) H5C_t * cache_ptr = NULL; struct mssg_t mssg; - if ( world_mpi_rank == 0 ) { + switch ( metadata_write_strategy ) { + + case H5AC_METADATA_WRITE_STRATEGY__PROCESS_0_ONLY: + if ( world_mpi_rank == 0 ) { + TESTING("smoke check #4 -- process 0 only md write strategy"); + } + break; + + case H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED: + if ( world_mpi_rank == 0 ) { + TESTING("smoke check #4 -- distributed md write strategy"); + } + break; - TESTING("smoke check #4"); + default: + if ( world_mpi_rank == 0 ) { + TESTING("smoke check #4 -- unknown md write strategy"); + } + break; } nerrors = 0; @@ -4724,7 +6252,8 @@ smoke_check_4(void) } else /* run the clients */ { - if ( ! setup_cache_for_test(&fid, &file_ptr, &cache_ptr) ) { + if ( ! setup_cache_for_test(&fid, &file_ptr, &cache_ptr, + metadata_write_strategy) ) { nerrors++; fid = -1; @@ -4926,6 +6455,7 @@ smoke_check_4(void) mssg.base_addr = 0; /* not used */ mssg.len = 0; /* not used */ mssg.ver = 0; /* not used */ + mssg.count = 0; /* not used */ mssg.magic = MSSG_MAGIC; if ( success ) { @@ -4965,7 +6495,7 @@ smoke_check_4(void) } /* smoke_check_4() */ - + /***************************************************************************** * * Function: smoke_check_5() @@ -4979,16 +6509,9 @@ smoke_check_4(void) * * Programmer: JRM -- 5/18/06 * - * Modifications: - * - * JRM -- 7/12/06 - * Added test code for H5AC_expunge_entry() and - * H5AC_resize_entry(). - * *****************************************************************************/ - hbool_t -smoke_check_5(void) +smoke_check_5(int metadata_write_strategy) { const char * fcn_name = "smoke_check_5()"; hbool_t success = TRUE; @@ -5001,11 +6524,28 @@ smoke_check_5(void) H5C_t * cache_ptr = NULL; struct mssg_t mssg; - if ( world_mpi_rank == 0 ) { + switch ( metadata_write_strategy ) { + + case H5AC_METADATA_WRITE_STRATEGY__PROCESS_0_ONLY: + if ( world_mpi_rank == 0 ) { + TESTING("smoke check #5 -- process 0 only md write strategy"); + } + break; - TESTING("smoke check #5"); + case H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED: + if ( world_mpi_rank == 0 ) { + TESTING("smoke check #5 -- distributed md write strategy"); + } + break; + + default: + if ( world_mpi_rank == 0 ) { + TESTING("smoke check #5 -- unknown md write strategy"); + } + break; } + /* 0 */ if ( verbose ) { HDfprintf(stderr, "%d: cp = %d\n", world_mpi_rank, cp++); } @@ -5043,7 +6583,8 @@ smoke_check_5(void) HDfprintf(stderr, "%d: cp = %d\n", world_mpi_rank, cp++); } - if ( ! setup_cache_for_test(&fid, &file_ptr, &cache_ptr) ) { + if ( ! setup_cache_for_test(&fid, &file_ptr, &cache_ptr, + metadata_write_strategy) ) { nerrors++; fid = -1; @@ -5180,6 +6721,7 @@ smoke_check_5(void) mssg.base_addr = 0; /* not used */ mssg.len = 0; /* not used */ mssg.ver = 0; /* not used */ + mssg.count = 0; /* not used */ mssg.magic = MSSG_MAGIC; if ( success ) { @@ -5223,7 +6765,7 @@ smoke_check_5(void) } /* smoke_check_5() */ - + /***************************************************************************** * * Function: trace_file_check() @@ -5245,7 +6787,7 @@ smoke_check_5(void) * - H5AC_flush() * - H5AC_set() * - H5AC_mark_entry_dirty() - * H5AC_move_entry() + * - H5AC_move_entry() * - H5AC_pin_protected_entry() * - H5AC_protect() * - H5AC_unpin_entry() @@ -5262,47 +6804,69 @@ smoke_check_5(void) * * Programmer: JRM -- 6/13/06 * - * Modifications: - * - * JRM -- 7/11/06 - * Updated for H5AC_expunge_entry() and - * H5AC_resize_entry(). - * *****************************************************************************/ - hbool_t -trace_file_check(void) +trace_file_check(int metadata_write_strategy) { hbool_t success = TRUE; #ifdef H5_METADATA_TRACE_FILE const char * fcn_name = "trace_file_check()"; - const char * expected_output[] = + const char *((* expected_output)[]) = NULL; + const char * expected_output_0[] = { "### HDF5 metadata cache trace file version 1 ###\n", - "H5AC_set_cache_auto_resize_config 1 0 1 0 \"t_cache_trace.txt\" 1 0 1048576 0.500000 16777216 1048576 50000 1 0.900000 2.000000 1 1.000000 0.250000 1 4194304 3 0.999000 0.900000 1 1048576 3 1 0.100000 262144 0\n", - "H5AC_set 0x0 15 0x0 2 0\n", - "H5AC_set 0x2 15 0x0 2 0\n", - "H5AC_set 0x4 15 0x0 4 0\n", - "H5AC_set 0x8 15 0x0 6 0\n", - "H5AC_protect 0 15 H5AC_WRITE 2 1\n", - "H5AC_mark_entry_dirty 0 0\n", - "H5AC_unprotect 0 15 0 0 0\n", - "H5AC_protect 2 15 H5AC_WRITE 2 1\n", - "H5AC_pin_protected_entry 2 0\n", - "H5AC_unprotect 2 15 0 0 0\n", - "H5AC_unpin_entry 2 0\n", - "H5AC_expunge_entry 2 15 0\n", - "H5AC_protect 4 15 H5AC_WRITE 4 1\n", - "H5AC_pin_protected_entry 4 0\n", - "H5AC_unprotect 4 15 0 0 0\n", - "H5AC_mark_entry_dirty 0x4 0 0 0\n", - "H5AC_resize_entry 0x4 2 0\n", - "H5AC_resize_entry 0x4 4 0\n", - "H5AC_unpin_entry 4 0\n", - "H5AC_move_entry 0 8a65 15 0\n", - "H5AC_move_entry 8a65 0 15 0\n", + "H5AC_set_cache_auto_resize_config 1 0 1 0 \"t_cache_trace.txt\" 1 0 2097152 0.300000 33554432 1048576 50000 1 0.900000 2.000000 1 1.000000 0.250000 1 4194304 3 0.999000 0.900000 1 1048576 3 1 0.100000 262144 0 0\n", + "H5AC_set 0x200 25 0x0 2 0\n", + "H5AC_set 0x202 25 0x0 2 0\n", + "H5AC_set 0x204 25 0x0 4 0\n", + "H5AC_set 0x208 25 0x0 6 0\n", + "H5AC_protect 0x200 25 H5AC_WRITE 2 1\n", + "H5AC_mark_entry_dirty 0x200 0\n", + "H5AC_unprotect 0x200 25 0 0 0\n", + "H5AC_protect 0x202 25 H5AC_WRITE 2 1\n", + "H5AC_pin_protected_entry 0x202 0\n", + "H5AC_unprotect 0x202 25 0 0 0\n", + "H5AC_unpin_entry 0x202 0\n", + "H5AC_expunge_entry 0x202 25 0\n", + "H5AC_protect 0x204 25 H5AC_WRITE 4 1\n", + "H5AC_pin_protected_entry 0x204 0\n", + "H5AC_unprotect 0x204 25 0 0 0\n", + "H5AC_mark_entry_dirty 0x204 0 0 0\n", + "H5AC_resize_entry 0x204 2 0\n", + "H5AC_resize_entry 0x204 4 0\n", + "H5AC_unpin_entry 0x204 0\n", + "H5AC_move_entry 0x200 0x8c65 25 0\n", + "H5AC_move_entry 0x8c65 0x200 25 0\n", + "H5AC_flush 0\n", + NULL + }; + const char * expected_output_1[] = + { + "### HDF5 metadata cache trace file version 1 ###\n", + "H5AC_set_cache_auto_resize_config 1 0 1 0 \"t_cache_trace.txt\" 1 0 2097152 0.300000 33554432 1048576 50000 1 0.900000 2.000000 1 1.000000 0.250000 1 4194304 3 0.999000 0.900000 1 1048576 3 1 0.100000 262144 1 0\n", + "H5AC_set 0x200 25 0x0 2 0\n", + "H5AC_set 0x202 25 0x0 2 0\n", + "H5AC_set 0x204 25 0x0 4 0\n", + "H5AC_set 0x208 25 0x0 6 0\n", + "H5AC_protect 0x200 25 H5AC_WRITE 2 1\n", + "H5AC_mark_entry_dirty 0x200 0\n", + "H5AC_unprotect 0x200 25 0 0 0\n", + "H5AC_protect 0x202 25 H5AC_WRITE 2 1\n", + "H5AC_pin_protected_entry 0x202 0\n", + "H5AC_unprotect 0x202 25 0 0 0\n", + "H5AC_unpin_entry 0x202 0\n", + "H5AC_expunge_entry 0x202 25 0\n", + "H5AC_protect 0x204 25 H5AC_WRITE 4 1\n", + "H5AC_pin_protected_entry 0x204 0\n", + "H5AC_unprotect 0x204 25 0 0 0\n", + "H5AC_mark_entry_dirty 0x204 0 0 0\n", + "H5AC_resize_pinned_entry 0x204 2 0\n", + "H5AC_resize_pinned_entry 0x204 4 0\n", + "H5AC_unpin_entry 0x204 0\n", + "H5AC_move_entry 0x200 0x8c65 25 0\n", + "H5AC_move_entry 0x8c65 0x200 25 0\n", "H5AC_flush 0\n", NULL }; @@ -5322,9 +6886,39 @@ trace_file_check(void) #endif /* H5_METADATA_TRACE_FILE */ - if ( world_mpi_rank == 0 ) { + switch ( metadata_write_strategy ) { + + case H5AC_METADATA_WRITE_STRATEGY__PROCESS_0_ONLY: +#ifdef H5_METADATA_TRACE_FILE + expected_output = &expected_output_0; +#endif /* H5_METADATA_TRACE_FILE */ + if ( world_mpi_rank == 0 ) { + TESTING( + "trace file collection -- process 0 only md write strategy"); + } + break; - TESTING("trace file collection"); + case H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED: +#ifdef H5_METADATA_TRACE_FILE + expected_output = &expected_output_1; +#endif /* H5_METADATA_TRACE_FILE */ + if ( world_mpi_rank == 0 ) { + TESTING( + "trace file collection -- distributed md write strategy"); + } + break; + + default: +#ifdef H5_METADATA_TRACE_FILE + /* this will almost certainly cause a failure, but it keeps us + * from de-referenceing a NULL pointer. + */ + expected_output = &expected_output_0; +#endif /* H5_METADATA_TRACE_FILE */ + if ( world_mpi_rank == 0 ) { + TESTING("trace file collection -- unknown md write strategy"); + } + break; } #ifdef H5_METADATA_TRACE_FILE @@ -5348,7 +6942,8 @@ trace_file_check(void) else /* run the clients */ { - if ( ! setup_cache_for_test(&fid, &file_ptr, &cache_ptr) ) { + if ( ! setup_cache_for_test(&fid, &file_ptr, &cache_ptr, + metadata_write_strategy) ) { nerrors++; fid = -1; @@ -5481,6 +7076,7 @@ trace_file_check(void) mssg.base_addr = 0; /* not used */ mssg.len = 0; /* not used */ mssg.ver = 0; /* not used */ + mssg.count = 0; /* not used */ mssg.magic = MSSG_MAGIC; if ( success ) { @@ -5515,13 +7111,13 @@ trace_file_check(void) i = 0; while ( ( nerrors == 0 ) && ( ! done ) ) { - if ( expected_output[i] == NULL ) { + if ( (*expected_output)[i] == NULL ) { expected_line_len = 0; } else { - expected_line_len = HDstrlen(expected_output[i]); + expected_line_len = HDstrlen((*expected_output)[i]); } if ( HDfgets(buffer, 255, trace_file_ptr) != NULL ) { @@ -5538,7 +7134,7 @@ trace_file_check(void) done = TRUE; } else if ( ( actual_line_len != expected_line_len ) || - ( HDstrcmp(buffer, expected_output[i]) != 0 ) ) { + ( HDstrcmp(buffer, (*expected_output)[i]) != 0 ) ) { nerrors++; if ( verbose ) { @@ -5546,7 +7142,7 @@ trace_file_check(void) "%d:%s: Unexpected data in trace file line %d.\n", world_mpi_rank, fcn_name, i); HDfprintf(stdout, "%d:%s: expected = \"%s\" %d\n", - world_mpi_rank, fcn_name, expected_output[i], + world_mpi_rank, fcn_name, (*expected_output)[i], expected_line_len); HDfprintf(stdout, "%d:%s: actual = \"%s\" %d\n", world_mpi_rank, fcn_name, buffer, @@ -5770,22 +7366,28 @@ main(int argc, char **argv) server_smoke_check(); #endif #if 1 - smoke_check_1(); + smoke_check_1(H5AC_METADATA_WRITE_STRATEGY__PROCESS_0_ONLY); + smoke_check_1(H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED); #endif #if 1 - smoke_check_2(); + smoke_check_2(H5AC_METADATA_WRITE_STRATEGY__PROCESS_0_ONLY); + smoke_check_2(H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED); #endif #if 1 - smoke_check_3(); + smoke_check_3(H5AC_METADATA_WRITE_STRATEGY__PROCESS_0_ONLY); + smoke_check_3(H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED); #endif #if 1 - smoke_check_4(); + smoke_check_4(H5AC_METADATA_WRITE_STRATEGY__PROCESS_0_ONLY); + smoke_check_4(H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED); #endif #if 1 - smoke_check_5(); + smoke_check_5(H5AC_METADATA_WRITE_STRATEGY__PROCESS_0_ONLY); + smoke_check_5(H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED); #endif #if 1 - trace_file_check(); + trace_file_check(H5AC_METADATA_WRITE_STRATEGY__PROCESS_0_ONLY); + trace_file_check(H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED); #endif finish: diff --git a/testpar/t_posix_compliant.c b/testpar/t_posix_compliant.c index af0e6bc..960f4c8 100644 --- a/testpar/t_posix_compliant.c +++ b/testpar/t_posix_compliant.c @@ -37,7 +37,7 @@ * macro STANDALONE. E.g., * mpicc -DSTANDALONE t_posix_compliant.c -o t_posix_compliant * then run it as an MPI application. E.g., - * mpirun -np 3 ./t_posix_compliant + * mpiexec -np 3 ./t_posix_compliant */ #include <unistd.h> diff --git a/testpar/t_rank_projection.c b/testpar/t_rank_projection.c new file mode 100644 index 0000000..bbc0a1f --- /dev/null +++ b/testpar/t_rank_projection.c @@ -0,0 +1,4041 @@ + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + This program will test independant and collective reads and writes between + selections of different rank that non-the-less are deemed as having the + same shape by H5Sselect_shape_same(). + */ + +#define H5S_PACKAGE /*suppress error about including H5Spkg */ + + +#include "hdf5.h" +#include "H5private.h" +#include "testphdf5.h" +#include "H5Spkg.h" /* Dataspaces */ + + +/*------------------------------------------------------------------------- + * Function: contig_hyperslab_dr_pio_test__run_test() + * + * Purpose: Test I/O to/from hyperslab selections of different rank in + * the parallel. + * + * Return: void + * + * Programmer: JRM -- 9/18/09 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +#define PAR_SS_DR_MAX_RANK 5 +#define CONTIG_HYPERSLAB_DR_PIO_TEST__RUN_TEST__DEBUG 0 + +void +contig_hyperslab_dr_pio_test__run_test(const int test_num, + const int edge_size, + const int chunk_edge_size, + const int small_rank, + const int large_rank, + const hbool_t use_collective_io, + const hid_t dset_type) +{ + const char *fcnName = "contig_hyperslab_dr_pio_test()"; + const char *filename; + hbool_t use_gpfs = FALSE; /* Use GPFS hints */ + hbool_t mis_match = FALSE; + int i, j, k, l, m, n; + int mrc; + int mpi_size = -1; + int mpi_rank = -1; + int start_index; + int stop_index; + const int test_max_rank = 5; /* must update code if this changes */ + uint32_t expected_value; + uint32_t * small_ds_buf_0 = NULL; + uint32_t * small_ds_buf_1 = NULL; + uint32_t * small_ds_buf_2 = NULL; + uint32_t * small_ds_slice_buf = NULL; + uint32_t * large_ds_buf_0 = NULL; + uint32_t * large_ds_buf_1 = NULL; + uint32_t * large_ds_buf_2 = NULL; + uint32_t * large_ds_slice_buf = NULL; + uint32_t * ptr_0; + uint32_t * ptr_1; + uint32_t * ptr_2; + MPI_Comm mpi_comm = MPI_COMM_NULL; + MPI_Info mpi_info = MPI_INFO_NULL; + hid_t fid; /* HDF5 file ID */ + hid_t acc_tpl; /* File access templates */ + hid_t xfer_plist = H5P_DEFAULT; + hid_t full_mem_small_ds_sid; + hid_t full_file_small_ds_sid; + hid_t mem_small_ds_sid; + hid_t file_small_ds_sid; + hid_t small_ds_slice_sid; + hid_t full_mem_large_ds_sid; + hid_t full_file_large_ds_sid; + hid_t mem_large_ds_sid; + hid_t file_large_ds_sid; + hid_t file_large_ds_process_slice_sid; + hid_t mem_large_ds_process_slice_sid; + hid_t large_ds_slice_sid; + hid_t small_ds_dcpl_id = H5P_DEFAULT; + hid_t large_ds_dcpl_id = H5P_DEFAULT; + hid_t small_dataset; /* Dataset ID */ + hid_t large_dataset; /* Dataset ID */ + size_t small_ds_size = 1; + size_t small_ds_slice_size = 1; + size_t large_ds_size = 1; + size_t large_ds_slice_size = 1; + hsize_t dims[PAR_SS_DR_MAX_RANK]; + hsize_t chunk_dims[PAR_SS_DR_MAX_RANK]; + hsize_t start[PAR_SS_DR_MAX_RANK]; + hsize_t stride[PAR_SS_DR_MAX_RANK]; + hsize_t count[PAR_SS_DR_MAX_RANK]; + hsize_t block[PAR_SS_DR_MAX_RANK]; + hsize_t * start_ptr = NULL; + hsize_t * stride_ptr = NULL; + hsize_t * count_ptr = NULL; + hsize_t * block_ptr = NULL; + htri_t check; /* Shape comparison return value */ + herr_t ret; /* Generic return value */ + + HDassert( edge_size >= 6 ); + HDassert( edge_size >= chunk_edge_size ); + HDassert( ( chunk_edge_size == 0 ) || ( chunk_edge_size >= 3 ) ); + HDassert( 1 < small_rank ); + HDassert( small_rank < large_rank ); + HDassert( large_rank <= test_max_rank ); + HDassert( test_max_rank <= PAR_SS_DR_MAX_RANK ); + + MPI_Comm_size(MPI_COMM_WORLD, &mpi_size); + MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank); + + HDassert( mpi_size >= 1 ); + + mpi_comm = MPI_COMM_WORLD; + mpi_info = MPI_INFO_NULL; + + for ( i = 0; i < small_rank - 1; i++ ) + { + small_ds_size *= (size_t)edge_size; + small_ds_slice_size *= (size_t)edge_size; + } + small_ds_size *= (size_t)(mpi_size + 1); + + + for ( i = 0; i < large_rank - 1; i++ ) { + + large_ds_size *= (size_t)edge_size; + large_ds_slice_size *= (size_t)edge_size; + } + large_ds_size *= (size_t)(mpi_size + 1); + + + /* set up the start, stride, count, and block pointers */ + start_ptr = &(start[PAR_SS_DR_MAX_RANK - large_rank]); + stride_ptr = &(stride[PAR_SS_DR_MAX_RANK - large_rank]); + count_ptr = &(count[PAR_SS_DR_MAX_RANK - large_rank]); + block_ptr = &(block[PAR_SS_DR_MAX_RANK - large_rank]); + + + /* Allocate buffers */ + small_ds_buf_0 = (uint32_t *)HDmalloc(sizeof(uint32_t) * small_ds_size); + VRFY((small_ds_buf_0 != NULL), "malloc of small_ds_buf_0 succeeded"); + + small_ds_buf_1 = (uint32_t *)HDmalloc(sizeof(uint32_t) * small_ds_size); + VRFY((small_ds_buf_1 != NULL), "malloc of small_ds_buf_1 succeeded"); + + small_ds_buf_2 = (uint32_t *)HDmalloc(sizeof(uint32_t) * small_ds_size); + VRFY((small_ds_buf_2 != NULL), "malloc of small_ds_buf_2 succeeded"); + + small_ds_slice_buf = + (uint32_t *)HDmalloc(sizeof(uint32_t) * small_ds_slice_size); + VRFY((small_ds_slice_buf != NULL), "malloc of small_ds_slice_buf succeeded"); + + large_ds_buf_0 = (uint32_t *)HDmalloc(sizeof(uint32_t) * large_ds_size); + VRFY((large_ds_buf_0 != NULL), "malloc of large_ds_buf_0 succeeded"); + + large_ds_buf_1 = (uint32_t *)HDmalloc(sizeof(uint32_t) * large_ds_size); + VRFY((large_ds_buf_1 != NULL), "malloc of large_ds_buf_1 succeeded"); + + large_ds_buf_2 = (uint32_t *)HDmalloc(sizeof(uint32_t) * large_ds_size); + VRFY((large_ds_buf_2 != NULL), "malloc of large_ds_buf_2 succeeded"); + + large_ds_slice_buf = + (uint32_t *)HDmalloc(sizeof(uint32_t) * large_ds_slice_size); + VRFY((large_ds_slice_buf != NULL), "malloc of large_ds_slice_buf succeeded"); + + /* initialize the buffers */ + + ptr_0 = small_ds_buf_0; + ptr_1 = small_ds_buf_1; + ptr_2 = small_ds_buf_2; + + for ( i = 0; i < (int)small_ds_size; i++ ) { + + *ptr_0 = (uint32_t)i; + *ptr_1 = 0; + *ptr_2 = 0; + + ptr_0++; + ptr_1++; + ptr_2++; + } + + ptr_0 = small_ds_slice_buf; + + for ( i = 0; i < (int)small_ds_slice_size; i++ ) { + + *ptr_0 = (uint32_t)0; + ptr_0++; + } + + ptr_0 = large_ds_buf_0; + ptr_1 = large_ds_buf_1; + ptr_2 = large_ds_buf_2; + + for ( i = 0; i < (int)large_ds_size; i++ ) { + + *ptr_0 = (uint32_t)i; + *ptr_1 = 0; + *ptr_2 = 0; + + ptr_0++; + ptr_1++; + ptr_2++; + } + + ptr_0 = large_ds_slice_buf; + + for ( i = 0; i < (int)large_ds_slice_size; i++ ) { + + *ptr_0 = (uint32_t)0; + ptr_0++; + } + + filename = (const char *)GetTestParameters(); + HDassert( filename != NULL ); +#if CONTIG_HYPERSLAB_DR_PIO_TEST__RUN_TEST__DEBUG + if ( MAINPROCESS ) { + + HDfprintf(stdout, "%d: test num = %d.\n", mpi_rank, test_num); + HDfprintf(stdout, "%d: mpi_size = %d.\n", mpi_rank, mpi_size); + HDfprintf(stdout, + "%d: small/large rank = %d/%d, use_collective_io = %d.\n", + mpi_rank, small_rank, large_rank, (int)use_collective_io); + HDfprintf(stdout, "%d: edge_size = %d, chunk_edge_size = %d.\n", + mpi_rank, edge_size, chunk_edge_size); + HDfprintf(stdout, "%d: small_ds_size = %d, large_ds_size = %d.\n", + mpi_rank, (int)small_ds_size, (int)large_ds_size); + HDfprintf(stdout, "%d: filename = %s.\n", mpi_rank, filename); + } +#endif + /* ---------------------------------------- + * CREATE AN HDF5 FILE WITH PARALLEL ACCESS + * ---------------------------------------*/ + /* setup file access template */ + acc_tpl = create_faccess_plist(mpi_comm, mpi_info, facc_type, use_gpfs); + VRFY((acc_tpl >= 0), "create_faccess_plist() succeeded"); + + /* create the file collectively */ + fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, acc_tpl); + VRFY((fid >= 0), "H5Fcreate succeeded"); + + MESG("File opened."); + + /* Release file-access template */ + ret = H5Pclose(acc_tpl); + VRFY((ret >= 0), "H5Pclose(acc_tpl) succeeded"); + + + /* setup dims: */ + dims[0] = (int)(mpi_size + 1); + dims[1] = dims[2] = dims[3] = dims[4] = edge_size; + + + /* Create small ds dataspaces */ + full_mem_small_ds_sid = H5Screate_simple(small_rank, dims, NULL); + VRFY((full_mem_small_ds_sid != 0), + "H5Screate_simple() full_mem_small_ds_sid succeeded"); + + full_file_small_ds_sid = H5Screate_simple(small_rank, dims, NULL); + VRFY((full_file_small_ds_sid != 0), + "H5Screate_simple() full_file_small_ds_sid succeeded"); + + mem_small_ds_sid = H5Screate_simple(small_rank, dims, NULL); + VRFY((mem_small_ds_sid != 0), + "H5Screate_simple() mem_small_ds_sid succeeded"); + + file_small_ds_sid = H5Screate_simple(small_rank, dims, NULL); + VRFY((file_small_ds_sid != 0), + "H5Screate_simple() file_small_ds_sid succeeded"); + + small_ds_slice_sid = H5Screate_simple(small_rank - 1, &(dims[1]), NULL); + VRFY((small_ds_slice_sid != 0), + "H5Screate_simple() small_ds_slice_sid succeeded"); + + + /* Create large ds dataspaces */ + full_mem_large_ds_sid = H5Screate_simple(large_rank, dims, NULL); + VRFY((full_mem_large_ds_sid != 0), + "H5Screate_simple() full_mem_large_ds_sid succeeded"); + + full_file_large_ds_sid = H5Screate_simple(large_rank, dims, NULL); + VRFY((full_file_large_ds_sid != FAIL), + "H5Screate_simple() full_file_large_ds_sid succeeded"); + + mem_large_ds_sid = H5Screate_simple(large_rank, dims, NULL); + VRFY((mem_large_ds_sid != FAIL), + "H5Screate_simple() mem_large_ds_sid succeeded"); + + file_large_ds_sid = H5Screate_simple(large_rank, dims, NULL); + VRFY((file_large_ds_sid != FAIL), + "H5Screate_simple() file_large_ds_sid succeeded"); + + mem_large_ds_process_slice_sid = H5Screate_simple(large_rank, dims, NULL); + VRFY((mem_large_ds_process_slice_sid != FAIL), + "H5Screate_simple() mem_large_ds_process_slice_sid succeeded"); + + file_large_ds_process_slice_sid = H5Screate_simple(large_rank, dims, NULL); + VRFY((file_large_ds_process_slice_sid != FAIL), + "H5Screate_simple() file_large_ds_process_slice_sid succeeded"); + + + large_ds_slice_sid = H5Screate_simple(large_rank - 1, &(dims[1]), NULL); + VRFY((large_ds_slice_sid != 0), + "H5Screate_simple() large_ds_slice_sid succeeded"); + + + /* Select the entire extent of the full small ds, and ds slice dataspaces */ + ret = H5Sselect_all(full_mem_small_ds_sid); + VRFY((ret != FAIL), "H5Sselect_all(full_mem_small_ds_sid) succeeded"); + + ret = H5Sselect_all(full_file_small_ds_sid); + VRFY((ret != FAIL), "H5Sselect_all(full_file_small_ds_sid) succeeded"); + + ret = H5Sselect_all(small_ds_slice_sid); + VRFY((ret != FAIL), "H5Sselect_all(small_ds_slice_sid) succeeded"); + + + /* Select the entire extent of the full large ds, and ds slice dataspaces */ + ret = H5Sselect_all(full_mem_large_ds_sid); + VRFY((ret != FAIL), "H5Sselect_all(full_mem_large_ds_sid) succeeded"); + + ret = H5Sselect_all(full_file_large_ds_sid); + VRFY((ret != FAIL), "H5Sselect_all(full_file_large_ds_sid) succeeded"); + + ret = H5Sselect_all(large_ds_slice_sid); + VRFY((ret != FAIL), "H5Sselect_all(large_ds_slice_sid) succeeded"); + + + /* if chunk edge size is greater than zero, set up the small and + * large data set creation property lists to specify chunked + * datasets. + */ + if ( chunk_edge_size > 0 ) { + + chunk_dims[0] = mpi_size + 1; + chunk_dims[1] = chunk_dims[2] = + chunk_dims[3] = chunk_dims[4] = chunk_edge_size; + + small_ds_dcpl_id = H5Pcreate(H5P_DATASET_CREATE); + VRFY((ret != FAIL), "H5Pcreate() small_ds_dcpl_id succeeded"); + + ret = H5Pset_layout(small_ds_dcpl_id, H5D_CHUNKED); + VRFY((ret != FAIL), "H5Pset_layout() small_ds_dcpl_id succeeded"); + + ret = H5Pset_chunk(small_ds_dcpl_id, small_rank, chunk_dims); + VRFY((ret != FAIL), "H5Pset_chunk() small_ds_dcpl_id succeeded"); + + + large_ds_dcpl_id = H5Pcreate(H5P_DATASET_CREATE); + VRFY((ret != FAIL), "H5Pcreate() large_ds_dcpl_id succeeded"); + + ret = H5Pset_layout(large_ds_dcpl_id, H5D_CHUNKED); + VRFY((ret != FAIL), "H5Pset_layout() large_ds_dcpl_id succeeded"); + + ret = H5Pset_chunk(large_ds_dcpl_id, large_rank, chunk_dims); + VRFY((ret != FAIL), "H5Pset_chunk() large_ds_dcpl_id succeeded"); + } + + /* create the small dataset */ + small_dataset = H5Dcreate2(fid, "small_dataset", dset_type, + file_small_ds_sid, H5P_DEFAULT, + small_ds_dcpl_id, H5P_DEFAULT); + VRFY((ret != FAIL), "H5Dcreate2() small_dataset succeeded"); + + /* create the large dataset */ + large_dataset = H5Dcreate2(fid, "large_dataset", dset_type, + file_large_ds_sid, H5P_DEFAULT, + large_ds_dcpl_id, H5P_DEFAULT); + VRFY((ret != FAIL), "H5Dcreate2() large_dataset succeeded"); + + + + /* setup xfer property list */ + xfer_plist = H5Pcreate(H5P_DATASET_XFER); + VRFY((xfer_plist >= 0), "H5Pcreate(H5P_DATASET_XFER) succeeded"); + + ret = H5Pset_dxpl_mpio(xfer_plist, H5FD_MPIO_COLLECTIVE); + VRFY((ret >= 0), "H5Pset_dxpl_mpio succeeded"); + + if ( ! use_collective_io ) { + + ret = H5Pset_dxpl_mpio_collective_opt(xfer_plist, + H5FD_MPIO_INDIVIDUAL_IO); + VRFY((ret>= 0), "H5Pset_dxpl_mpio_collective_opt() suceeded"); + } + + /* setup selection to write initial data to the small and large data sets */ + start[0] = mpi_rank; + stride[0] = 2 * (mpi_size + 1); + count[0] = 1; + block[0] = 1; + + for ( i = 1; i < large_rank; i++ ) { + + start[i] = 0; + stride[i] = 2 * edge_size; + count[i] = 1; + block[i] = edge_size; + } + + /* setup selections for writing initial data to the small data set */ + ret = H5Sselect_hyperslab(mem_small_ds_sid, + H5S_SELECT_SET, + start, + stride, + count, + block); + VRFY((ret >= 0), "H5Sselect_hyperslab(mem_small_ds_sid, set) suceeded"); + + ret = H5Sselect_hyperslab(file_small_ds_sid, + H5S_SELECT_SET, + start, + stride, + count, + block); + VRFY((ret >= 0), "H5Sselect_hyperslab(file_small_ds_sid, set) suceeded"); + + if ( MAINPROCESS ) { /* add an additional slice to the selections */ + + start[0] = mpi_size; + + ret = H5Sselect_hyperslab(mem_small_ds_sid, + H5S_SELECT_OR, + start, + stride, + count, + block); + VRFY((ret>= 0), "H5Sselect_hyperslab(mem_small_ds_sid, or) suceeded"); + + ret = H5Sselect_hyperslab(file_small_ds_sid, + H5S_SELECT_OR, + start, + stride, + count, + block); + VRFY((ret>= 0), "H5Sselect_hyperslab(file_small_ds_sid, or) suceeded"); + } + + + /* write the initial value of the small data set to file */ + ret = H5Dwrite(small_dataset, dset_type, mem_small_ds_sid, file_small_ds_sid, + xfer_plist, small_ds_buf_0); + + VRFY((ret >= 0), "H5Dwrite() small_dataset initial write succeeded"); + + + /* sync with the other processes before checking data */ + mrc = MPI_Barrier(MPI_COMM_WORLD); + VRFY((mrc==MPI_SUCCESS), "Sync after small dataset writes"); + + + /* read the small data set back to verify that it contains the + * expected data. Note that each process reads in the entire + * data set. + */ + ret = H5Dread(small_dataset, + H5T_NATIVE_UINT32, + full_mem_small_ds_sid, + full_file_small_ds_sid, + xfer_plist, + small_ds_buf_1); + VRFY((ret >= 0), "H5Dread() small_dataset initial read succeeded"); + + + /* verify that the correct data was written to the small data set */ + expected_value = 0; + mis_match = FALSE; + ptr_1 = small_ds_buf_1; + + i = 0; + for ( i = 0; i < (int)small_ds_size; i++ ) { + + if ( *ptr_1 != expected_value ) { + + mis_match = TRUE; + } + ptr_1++; + expected_value++; + } + VRFY( (mis_match == FALSE), "small ds init data good."); + + + + /* setup selections for writing initial data to the large data set */ + + start[0] = mpi_rank; + + ret = H5Sselect_hyperslab(mem_large_ds_sid, + H5S_SELECT_SET, + start, + stride, + count, + block); + VRFY((ret >= 0), "H5Sselect_hyperslab(mem_large_ds_sid, set) suceeded"); + + ret = H5Sselect_hyperslab(file_large_ds_sid, + H5S_SELECT_SET, + start, + stride, + count, + block); + VRFY((ret >= 0), "H5Sselect_hyperslab(file_large_ds_sid, set) suceeded"); + + /* In passing, setup the process slice data spaces as well */ + + ret = H5Sselect_hyperslab(mem_large_ds_process_slice_sid, + H5S_SELECT_SET, + start, + stride, + count, + block); + VRFY((ret >= 0), + "H5Sselect_hyperslab(mem_large_ds_process_slice_sid, set) suceeded"); + + ret = H5Sselect_hyperslab(file_large_ds_process_slice_sid, + H5S_SELECT_SET, + start, + stride, + count, + block); + VRFY((ret >= 0), + "H5Sselect_hyperslab(file_large_ds_process_slice_sid, set) suceeded"); + + if ( MAINPROCESS ) { /* add an additional slice to the selections */ + + start[0] = mpi_size; + + ret = H5Sselect_hyperslab(mem_large_ds_sid, + H5S_SELECT_OR, + start, + stride, + count, + block); + VRFY((ret>= 0), "H5Sselect_hyperslab(mem_large_ds_sid, or) suceeded"); + + ret = H5Sselect_hyperslab(file_large_ds_sid, + H5S_SELECT_OR, + start, + stride, + count, + block); + VRFY((ret>= 0), "H5Sselect_hyperslab(file_large_ds_sid, or) suceeded"); + } + + + /* write the initial value of the large data set to file */ + ret = H5Dwrite(large_dataset, dset_type, mem_large_ds_sid, file_large_ds_sid, + xfer_plist, large_ds_buf_0); + if ( ret < 0 ) H5Eprint(H5E_DEFAULT, stderr); + VRFY((ret >= 0), "H5Dwrite() large_dataset initial write succeeded"); + + + /* sync with the other processes before checking data */ + mrc = MPI_Barrier(MPI_COMM_WORLD); + VRFY((mrc==MPI_SUCCESS), "Sync after large dataset writes"); + + + /* read the small data set back to verify that it contains the + * expected data. Note that each process reads in the entire + * data set. + */ + ret = H5Dread(large_dataset, + H5T_NATIVE_UINT32, + full_mem_large_ds_sid, + full_file_large_ds_sid, + xfer_plist, + large_ds_buf_1); + VRFY((ret >= 0), "H5Dread() large_dataset initial read succeeded"); + + + /* verify that the correct data was written to the small data set */ + expected_value = 0; + mis_match = FALSE; + ptr_1 = large_ds_buf_1; + + i = 0; + for ( i = 0; i < (int)large_ds_size; i++ ) { + + if ( *ptr_1 != expected_value ) { + + mis_match = TRUE; + } + ptr_1++; + expected_value++; + } + VRFY( (mis_match == FALSE), "large ds init data good."); + + + /* first, verify that we can read from disk correctly using selections + * of different rank that H5S_select_shape_same() views as being of the + * same shape. + * + * Start by reading small_rank-D - 1 slice from the on disk large cube, + * and verifying that the data read is correct. Verify that + * H5S_select_shape_same() returns true on the memory and file selections. + */ + + /* We have already done a H5Sselect_all() on the data space + * small_ds_slice_sid, so no need to call H5Sselect_all() again. + */ + + /* set up start, stride, count, and block -- note that we will + * change start[] so as to read slices of the large cube. + */ + for ( i = 0; i < PAR_SS_DR_MAX_RANK; i++ ) { + + start[i] = 0; + stride[i] = 2 * edge_size; + count[i] = 1; + if ( (PAR_SS_DR_MAX_RANK - i) > (small_rank - 1) ) { + + block[i] = 1; + + } else { + + block[i] = edge_size; + } + } + + /* zero out the buffer we will be reading into */ + ptr_0 = small_ds_slice_buf; + + for ( i = 0; i < (int)small_ds_slice_size; i++ ) { + + *ptr_0 = (uint32_t)0; + ptr_0++; + } + +#if CONTIG_HYPERSLAB_DR_PIO_TEST__RUN_TEST__DEBUG + HDfprintf(stdout, + "%s reading slices from big cube on disk into small cube slice.\n", + fcnName); +#endif + /* in serial versions of this test, we loop through all the dimensions + * of the large data set. However, in the parallel version, each + * process only works with that slice of the large cube indicated + * by its rank -- hence we set the most slowly changing index to + * mpi_rank, and don't itterate over it. + */ + + if ( PAR_SS_DR_MAX_RANK - large_rank == 0 ) { + + i = mpi_rank; + + } else { + + i = 0; + } + + /* since large_rank is at most PAR_SS_DR_MAX_RANK, no need to + * loop over it -- either we are setting i to mpi_rank, or + * we are setting it to zero. It will not change during the + * test. + */ + + if ( PAR_SS_DR_MAX_RANK - large_rank == 1 ) { + + j = mpi_rank; + + } else { + + j = 0; + } + + do { + if ( PAR_SS_DR_MAX_RANK - large_rank == 2 ) { + + k = mpi_rank; + + } else { + + k = 0; + } + + do { + /* since small rank >= 2 and large_rank > small_rank, we + * have large_rank >= 3. Since PAR_SS_DR_MAX_RANK == 5 + * (baring major re-orgaization), this gives us: + * + * (PAR_SS_DR_MAX_RANK - large_rank) <= 2 + * + * so no need to repeat the test in the outer loops -- + * just set l = 0. + */ + + l = 0; + do { + /* we know that small_rank - 1 >= 1 and that + * large_rank > small_rank by the assertions at the head + * of this function. Thus no need for another inner loop. + */ + start[0] = i; + start[1] = j; + start[2] = k; + start[3] = l; + start[4] = 0; + + ret = H5Sselect_hyperslab(file_large_ds_sid, + H5S_SELECT_SET, + start_ptr, + stride_ptr, + count_ptr, + block_ptr); + VRFY((ret != FAIL), + "H5Sselect_hyperslab(file_large_cube_sid) succeeded"); + + + /* verify that H5S_select_shape_same() reports the two + * selections as having the same shape. + */ + check = H5S_select_shape_same_test(small_ds_slice_sid, + file_large_ds_sid); + VRFY((check == TRUE), "H5S_select_shape_same_test passed"); + + + /* Read selection from disk */ +#if CONTIG_HYPERSLAB_DR_PIO_TEST__RUN_TEST__DEBUG + HDfprintf(stdout, "%s:%d: start = %d %d %d %d %d.\n", + fcnName, (int)mpi_rank, + (int)start[0], (int)start[1], (int)start[2], + (int)start[3], (int)start[4]); + HDfprintf(stdout, "%s slice/file extent dims = %d/%d.\n", + fcnName, + H5Sget_simple_extent_ndims(small_ds_slice_sid), + H5Sget_simple_extent_ndims(file_large_ds_sid)); +#endif + ret = H5Dread(large_dataset, + H5T_NATIVE_UINT32, + small_ds_slice_sid, + file_large_ds_sid, + xfer_plist, + small_ds_slice_buf); + VRFY((ret >= 0), "H5Sread() slice from large ds succeeded."); + + + /* verify that expected data is retrieved */ + + mis_match = FALSE; + ptr_1 = small_ds_slice_buf; + expected_value = + (i * edge_size * edge_size * edge_size * edge_size) + + (j * edge_size * edge_size * edge_size) + + (k * edge_size * edge_size) + + (l * edge_size); + + for ( n = 0; n < (int)small_ds_slice_size; n++ ) { + + if ( *ptr_1 != expected_value ) { + + mis_match = TRUE; + } + + *ptr_1 = 0; /* zero data for next use */ + + ptr_1++; + expected_value++; + } + + VRFY((mis_match == FALSE), + "small slice read from large ds data good."); + l++; + + } while ( ( large_rank > 2 ) && + ( (small_rank - 1) <= 1 ) && + ( l < edge_size ) ); + k++; + } while ( ( large_rank > 3 ) && + ( (small_rank - 1) <= 2 ) && + ( k < edge_size ) ); + j++; + } while ( ( large_rank > 4 ) && + ( (small_rank - 1) <= 3 ) && + ( j < edge_size ) ); + + + /* similarly, read slices of the on disk small data set into slices + * through the in memory large data set, and verify that the correct + * data (and only the correct data) is read. + */ + + start[0] = mpi_rank; + stride[0] = 2 * (mpi_size + 1); + count[0] = 1; + block[0] = 1; + + for ( i = 1; i < large_rank; i++ ) { + + start[i] = 0; + stride[i] = 2 * edge_size; + count[i] = 1; + block[i] = edge_size; + } + + ret = H5Sselect_hyperslab(file_small_ds_sid, + H5S_SELECT_SET, + start, + stride, + count, + block); + VRFY((ret >= 0), "H5Sselect_hyperslab(file_small_ds_sid, set) suceeded"); + + +#if CONTIG_HYPERSLAB_DR_PIO_TEST__RUN_TEST__DEBUG + HDfprintf(stdout, + "%s reading slices of on disk small data set into slices of big data set.\n", + fcnName); +#endif + + /* zero out the in memory large ds */ + ptr_1 = large_ds_buf_1; + for ( n = 0; n < (int)large_ds_size; n++ ) { + + *ptr_1 = 0; + ptr_1++; + } + + /* set up start, stride, count, and block -- note that we will + * change start[] so as to read slices of the large cube. + */ + for ( i = 0; i < PAR_SS_DR_MAX_RANK; i++ ) { + + start[i] = 0; + stride[i] = 2 * edge_size; + count[i] = 1; + if ( (PAR_SS_DR_MAX_RANK - i) > (small_rank - 1) ) { + + block[i] = 1; + + } else { + + block[i] = edge_size; + } + } + + + /* in serial versions of this test, we loop through all the dimensions + * of the large data set that don't appear in the small data set. + * + * However, in the parallel version, each process only works with that + * slice of the large (and small) data set indicated by its rank -- hence + * we set the most slowly changing index to mpi_rank, and don't itterate + * over it. + */ + + + if ( PAR_SS_DR_MAX_RANK - large_rank == 0 ) { + + i = mpi_rank; + + } else { + + i = 0; + } + + /* since large_rank is at most PAR_SS_DR_MAX_RANK, no need to + * loop over it -- either we are setting i to mpi_rank, or + * we are setting it to zero. It will not change during the + * test. + */ + + if ( PAR_SS_DR_MAX_RANK - large_rank == 1 ) { + + j = mpi_rank; + + } else { + + j = 0; + } + + do { + if ( PAR_SS_DR_MAX_RANK - large_rank == 2 ) { + + k = mpi_rank; + + } else { + + k = 0; + } + + do { + /* since small rank >= 2 and large_rank > small_rank, we + * have large_rank >= 3. Since PAR_SS_DR_MAX_RANK == 5 + * (baring major re-orgaization), this gives us: + * + * (PAR_SS_DR_MAX_RANK - large_rank) <= 2 + * + * so no need to repeat the test in the outer loops -- + * just set l = 0. + */ + + l = 0; + do { + /* we know that small_rank >= 1 and that large_rank > small_rank + * by the assertions at the head of this function. Thus no + * need for another inner loop. + */ + start[0] = i; + start[1] = j; + start[2] = k; + start[3] = l; + start[4] = 0; + + ret = H5Sselect_hyperslab(mem_large_ds_sid, + H5S_SELECT_SET, + start_ptr, + stride_ptr, + count_ptr, + block_ptr); + VRFY((ret != FAIL), + "H5Sselect_hyperslab(mem_large_ds_sid) succeeded"); + + + /* verify that H5S_select_shape_same() reports the two + * selections as having the same shape. + */ + check = H5S_select_shape_same_test(file_small_ds_sid, + mem_large_ds_sid); + VRFY((check == TRUE), "H5S_select_shape_same_test passed"); + + + /* Read selection from disk */ +#if CONTIG_HYPERSLAB_DR_PIO_TEST__RUN_TEST__DEBUG + HDfprintf(stdout, "%s:%d: start = %d %d %d %d %d.\n", + fcnName, (int)mpi_rank, + (int)start[0], (int)start[1], (int)start[2], + (int)start[3], (int)start[4]); + HDfprintf(stdout, "%s:%d: mem/file extent dims = %d/%d.\n", + fcnName, mpi_rank, + H5Sget_simple_extent_ndims(mem_large_ds_sid), + H5Sget_simple_extent_ndims(file_small_ds_sid)); +#endif + ret = H5Dread(small_dataset, + H5T_NATIVE_UINT32, + mem_large_ds_sid, + file_small_ds_sid, + xfer_plist, + large_ds_buf_1); + VRFY((ret >= 0), "H5Sread() slice from small ds succeeded."); + + /* verify that the expected data and only the + * expected data was read. + */ + ptr_1 = large_ds_buf_1; + expected_value = mpi_rank * small_ds_slice_size; + start_index = + (i * edge_size * edge_size * edge_size * edge_size) + + (j * edge_size * edge_size * edge_size) + + (k * edge_size * edge_size) + + (l * edge_size); + stop_index = start_index + (int)small_ds_slice_size - 1; + + HDassert( 0 <= start_index ); + HDassert( start_index < stop_index ); + HDassert( stop_index <= (int)large_ds_size ); + + for ( n = 0; n < (int)large_ds_size; n++ ) { + + if ( ( n >= start_index ) && ( n <= stop_index ) ) { + + if ( *ptr_1 != expected_value ) { + + mis_match = TRUE; + } + expected_value++; + + } else { + + if ( *ptr_1 != 0 ) { + + mis_match = TRUE; + } + } + /* zero out the value for the next pass */ + *ptr_1 = 0; + + ptr_1++; + } + + VRFY((mis_match == FALSE), + "small slice read from large ds data good."); + + l++; + + } while ( ( large_rank > 2 ) && + ( (small_rank - 1) <= 1 ) && + ( l < edge_size ) ); + k++; + } while ( ( large_rank > 3 ) && + ( (small_rank - 1) <= 2 ) && + ( k < edge_size ) ); + j++; + } while ( ( large_rank > 4 ) && + ( (small_rank - 1) <= 3 ) && + ( j < edge_size ) ); + + + /* now we go in the opposite direction, verifying that we can write + * from memory to file using selections of different rank that + * H5S_select_shape_same() views as being of the same shape. + * + * Start by writing small_rank - 1 D slices from the in memory large data + * set to the on disk small cube dataset. After each write, read the + * slice of the small dataset back from disk, and verify that it contains + * the expected data. Verify that H5S_select_shape_same() returns true on + * the memory and file selections. + */ + + start[0] = mpi_rank; + stride[0] = 2 * (mpi_size + 1); + count[0] = 1; + block[0] = 1; + + for ( i = 1; i < large_rank; i++ ) { + + start[i] = 0; + stride[i] = 2 * edge_size; + count[i] = 1; + block[i] = edge_size; + } + + ret = H5Sselect_hyperslab(file_small_ds_sid, + H5S_SELECT_SET, + start, + stride, + count, + block); + VRFY((ret >= 0), "H5Sselect_hyperslab(file_small_ds_sid, set) suceeded"); + + ret = H5Sselect_hyperslab(mem_small_ds_sid, + H5S_SELECT_SET, + start, + stride, + count, + block); + VRFY((ret >= 0), "H5Sselect_hyperslab(mem_small_ds_sid, set) suceeded"); + + + /* set up start, stride, count, and block -- note that we will + * change start[] so as to read slices of the large cube. + */ + for ( i = 0; i < PAR_SS_DR_MAX_RANK; i++ ) { + + start[i] = 0; + stride[i] = 2 * edge_size; + count[i] = 1; + if ( (PAR_SS_DR_MAX_RANK - i) > (small_rank - 1) ) { + + block[i] = 1; + + } else { + + block[i] = edge_size; + } + } + + /* zero out the in memory small ds */ + ptr_1 = small_ds_buf_1; + for ( n = 0; n < (int)small_ds_size; n++ ) { + + *ptr_1 = 0; + ptr_1++; + } + + +#if CONTIG_HYPERSLAB_DR_PIO_TEST__RUN_TEST__DEBUG + HDfprintf(stdout, + "%s writing slices from big ds to slices of small ds on disk.\n", + fcnName); +#endif + + /* in serial versions of this test, we loop through all the dimensions + * of the large data set that don't appear in the small data set. + * + * However, in the parallel version, each process only works with that + * slice of the large (and small) data set indicated by its rank -- hence + * we set the most slowly changing index to mpi_rank, and don't itterate + * over it. + */ + + + if ( PAR_SS_DR_MAX_RANK - large_rank == 0 ) { + + i = mpi_rank; + + } else { + + i = 0; + } + + /* since large_rank is at most PAR_SS_DR_MAX_RANK, no need to + * loop over it -- either we are setting i to mpi_rank, or + * we are setting it to zero. It will not change during the + * test. + */ + + if ( PAR_SS_DR_MAX_RANK - large_rank == 1 ) { + + j = mpi_rank; + + } else { + + j = 0; + } + + j = 0; + do { + if ( PAR_SS_DR_MAX_RANK - large_rank == 2 ) { + + k = mpi_rank; + + } else { + + k = 0; + } + + do { + /* since small rank >= 2 and large_rank > small_rank, we + * have large_rank >= 3. Since PAR_SS_DR_MAX_RANK == 5 + * (baring major re-orgaization), this gives us: + * + * (PAR_SS_DR_MAX_RANK - large_rank) <= 2 + * + * so no need to repeat the test in the outer loops -- + * just set l = 0. + */ + + l = 0; + do { + /* we know that small_rank >= 1 and that large_rank > small_rank + * by the assertions at the head of this function. Thus no + * need for another inner loop. + */ + + /* zero out this rank's slice of the on disk small data set */ + ret = H5Dwrite(small_dataset, + H5T_NATIVE_UINT32, + mem_small_ds_sid, + file_small_ds_sid, + xfer_plist, + small_ds_buf_2); + VRFY((ret >= 0), "H5Dwrite() zero slice to small ds succeeded."); + + /* select the portion of the in memory large cube from which we + * are going to write data. + */ + start[0] = i; + start[1] = j; + start[2] = k; + start[3] = l; + start[4] = 0; + + ret = H5Sselect_hyperslab(mem_large_ds_sid, + H5S_SELECT_SET, + start_ptr, + stride_ptr, + count_ptr, + block_ptr); + VRFY((ret >= 0), + "H5Sselect_hyperslab() mem_large_ds_sid succeeded."); + + + /* verify that H5S_select_shape_same() reports the in + * memory slice through the cube selection and the + * on disk full square selections as having the same shape. + */ + check = H5S_select_shape_same_test(file_small_ds_sid, + mem_large_ds_sid); + VRFY((check == TRUE), "H5S_select_shape_same_test passed."); + + + /* write the slice from the in memory large data set to the + * slice of the on disk small dataset. */ +#if CONTIG_HYPERSLAB_DR_PIO_TEST__RUN_TEST__DEBUG + HDfprintf(stdout, "%s:%d: start = %d %d %d %d %d.\n", + fcnName, (int)mpi_rank, + (int)start[0], (int)start[1], (int)start[2], + (int)start[3], (int)start[4]); + HDfprintf(stdout, "%s:%d: mem/file extent dims = %d/%d.\n", + fcnName, mpi_rank, + H5Sget_simple_extent_ndims(mem_large_ds_sid), + H5Sget_simple_extent_ndims(file_small_ds_sid)); +#endif + ret = H5Dwrite(small_dataset, + H5T_NATIVE_UINT32, + mem_large_ds_sid, + file_small_ds_sid, + xfer_plist, + large_ds_buf_0); + VRFY((ret >= 0), "H5Dwrite() slice to large ds succeeded."); + + + /* read the on disk square into memory */ + ret = H5Dread(small_dataset, + H5T_NATIVE_UINT32, + mem_small_ds_sid, + file_small_ds_sid, + xfer_plist, + small_ds_buf_1); + VRFY((ret >= 0), "H5Dread() slice from small ds succeeded."); + + + /* verify that expected data is retrieved */ + + mis_match = FALSE; + ptr_1 = small_ds_buf_1; + + expected_value = + (i * edge_size * edge_size * edge_size * edge_size) + + (j * edge_size * edge_size * edge_size) + + (k * edge_size * edge_size) + + (l * edge_size); + + start_index = mpi_rank * small_ds_slice_size; + stop_index = start_index + small_ds_slice_size - 1; + + HDassert( 0 <= start_index ); + HDassert( start_index < stop_index ); + HDassert( stop_index <= (int)small_ds_size ); + + for ( n = 0; n < (int)small_ds_size; n++ ) { + + if ( ( n >= start_index ) && ( n <= stop_index ) ) { + + if ( *ptr_1 != expected_value ) { + + mis_match = TRUE; + } + expected_value++; + + } else { + + if ( *ptr_1 != 0 ) { + + mis_match = TRUE; + } + } + /* zero out the value for the next pass */ + *ptr_1 = 0; + + ptr_1++; + } + + VRFY((mis_match == FALSE), + "small slice write from large ds data good."); + + l++; + + } while ( ( large_rank > 2 ) && + ( (small_rank - 1) <= 1 ) && + ( l < edge_size ) ); + k++; + } while ( ( large_rank > 3 ) && + ( (small_rank - 1) <= 2 ) && + ( k < edge_size ) ); + j++; + } while ( ( large_rank > 4 ) && + ( (small_rank - 1) <= 3 ) && + ( j < edge_size ) ); + + + /* Now write the contents of the process's slice of the in memory + * small data set to slices of the on disk large data set. After + * each write, read the process's slice of the large data set back + * into memory, and verify that it contains the expected data. + * Verify that H5S_select_shape_same() returns true on the memory + * and file selections. + */ + + /* select the slice of the in memory small data set associated with + * the process's mpi rank. + */ + start[0] = mpi_rank; + stride[0] = 2 * (mpi_size + 1); + count[0] = 1; + block[0] = 1; + + for ( i = 1; i < large_rank; i++ ) { + + start[i] = 0; + stride[i] = 2 * edge_size; + count[i] = 1; + block[i] = edge_size; + } + + ret = H5Sselect_hyperslab(mem_small_ds_sid, + H5S_SELECT_SET, + start, + stride, + count, + block); + VRFY((ret >= 0), "H5Sselect_hyperslab(mem_small_ds_sid, set) suceeded"); + + + /* set up start, stride, count, and block -- note that we will + * change start[] so as to write slices of the small data set to + * slices of the large data set. + */ + for ( i = 0; i < PAR_SS_DR_MAX_RANK; i++ ) { + + start[i] = 0; + stride[i] = 2 * edge_size; + count[i] = 1; + if ( (PAR_SS_DR_MAX_RANK - i) > (small_rank - 1) ) { + + block[i] = 1; + + } else { + + block[i] = edge_size; + } + } + + /* zero out the in memory large ds */ + ptr_1 = large_ds_buf_1; + for ( n = 0; n < (int)large_ds_size; n++ ) { + + *ptr_1 = 0; + ptr_1++; + } + +#if CONTIG_HYPERSLAB_DR_PIO_TEST__RUN_TEST__DEBUG + HDfprintf(stdout, + "%s writing process slices of small ds to slices of large ds on disk.\n", + fcnName); +#endif + + if ( PAR_SS_DR_MAX_RANK - large_rank == 0 ) { + + i = mpi_rank; + + } else { + + i = 0; + } + + /* since large_rank is at most PAR_SS_DR_MAX_RANK, no need to + * loop over it -- either we are setting i to mpi_rank, or + * we are setting it to zero. It will not change during the + * test. + */ + + if ( PAR_SS_DR_MAX_RANK - large_rank == 1 ) { + + j = mpi_rank; + + } else { + + j = 0; + } + + do { + if ( PAR_SS_DR_MAX_RANK - large_rank == 2 ) { + + k = mpi_rank; + + } else { + + k = 0; + } + + do { + /* since small rank >= 2 and large_rank > small_rank, we + * have large_rank >= 3. Since PAR_SS_DR_MAX_RANK == 5 + * (baring major re-orgaization), this gives us: + * + * (PAR_SS_DR_MAX_RANK - large_rank) <= 2 + * + * so no need to repeat the test in the outer loops -- + * just set l = 0. + */ + + l = 0; + do { + /* we know that small_rank >= 1 and that large_rank > small_rank + * by the assertions at the head of this function. Thus no + * need for another inner loop. + */ + + /* Zero out this processes slice of the on disk large data set. + * Note that this will leave one slice with its original data + * as there is one more slice than processes. + */ + ret = H5Dwrite(large_dataset, + H5T_NATIVE_UINT32, + large_ds_slice_sid, + file_large_ds_process_slice_sid, + xfer_plist, + large_ds_buf_2); + VRFY((ret != FAIL), "H5Dwrite() to zero large ds suceeded"); + + + /* select the portion of the in memory large cube to which we + * are going to write data. + */ + start[0] = i; + start[1] = j; + start[2] = k; + start[3] = l; + start[4] = 0; + + ret = H5Sselect_hyperslab(file_large_ds_sid, + H5S_SELECT_SET, + start_ptr, + stride_ptr, + count_ptr, + block_ptr); + VRFY((ret != FAIL), + "H5Sselect_hyperslab() target large ds slice succeeded"); + + + /* verify that H5S_select_shape_same() reports the in + * memory small data set slice selection and the + * on disk slice through the large data set selection + * as having the same shape. + */ + check = H5S_select_shape_same_test(mem_small_ds_sid, + file_large_ds_sid); + VRFY((check == TRUE), "H5S_select_shape_same_test passed"); + + + /* write the small data set slice from memory to the + * target slice of the disk data set + */ +#if CONTIG_HYPERSLAB_DR_PIO_TEST__RUN_TEST__DEBUG + HDfprintf(stdout, "%s:%d: start = %d %d %d %d %d.\n", + fcnName, (int)mpi_rank, + (int)start[0], (int)start[1], (int)start[2], + (int)start[3], (int)start[4]); + HDfprintf(stdout, "%s:%d: mem/file extent dims = %d/%d.\n", + fcnName, mpi_rank, + H5Sget_simple_extent_ndims(mem_small_ds_sid), + H5Sget_simple_extent_ndims(file_large_ds_sid)); +#endif + ret = H5Dwrite(large_dataset, + H5T_NATIVE_UINT32, + mem_small_ds_sid, + file_large_ds_sid, + xfer_plist, + small_ds_buf_0); + VRFY((ret != FAIL), + "H5Dwrite of small ds slice to large ds succeeded"); + + + /* read this processes slice on the on disk large + * data set into memory. + */ + + ret = H5Dread(large_dataset, + H5T_NATIVE_UINT32, + mem_large_ds_process_slice_sid, + file_large_ds_process_slice_sid, + xfer_plist, + large_ds_buf_1); + VRFY((ret != FAIL), + "H5Dread() of process slice of large ds succeeded"); + + + /* verify that the expected data and only the + * expected data was read. + */ + ptr_1 = large_ds_buf_1; + expected_value = (uint32_t)(mpi_rank) * small_ds_slice_size; + + + start_index = (i * edge_size * edge_size * edge_size * edge_size) + + (j * edge_size * edge_size * edge_size) + + (k * edge_size * edge_size) + + (l * edge_size); + stop_index = start_index + (int)small_ds_slice_size - 1; + + HDassert( 0 <= start_index ); + HDassert( start_index < stop_index ); + HDassert( stop_index < (int)large_ds_size ); + + for ( n = 0; n < (int)large_ds_size; n++ ) { + + if ( ( n >= start_index ) && ( n <= stop_index ) ) { + + if ( *ptr_1 != expected_value ) { + + mis_match = TRUE; + } + + expected_value++; + + } else { + + if ( *ptr_1 != 0 ) { + + mis_match = TRUE; + } + } + /* zero out buffer for next test */ + *ptr_1 = 0; + ptr_1++; + } + + VRFY((mis_match == FALSE), + "small ds slice write to large ds slice data good."); + + l++; + + } while ( ( large_rank > 2 ) && + ( (small_rank - 1) <= 1 ) && + ( l < edge_size ) ); + k++; + } while ( ( large_rank > 3 ) && + ( (small_rank - 1) <= 2 ) && + ( k < edge_size ) ); + j++; + } while ( ( large_rank > 4 ) && + ( (small_rank - 1) <= 3 ) && + ( j < edge_size ) ); + + + /* Close dataspaces */ + ret = H5Sclose(full_mem_small_ds_sid); + VRFY((ret != FAIL), "H5Sclose(full_mem_small_ds_sid) succeeded"); + + ret = H5Sclose(full_file_small_ds_sid); + VRFY((ret != FAIL), "H5Sclose(full_file_small_ds_sid) succeeded"); + + ret = H5Sclose(mem_small_ds_sid); + VRFY((ret != FAIL), "H5Sclose(mem_small_ds_sid) succeeded"); + + ret = H5Sclose(file_small_ds_sid); + VRFY((ret != FAIL), "H5Sclose(file_small_ds_sid) succeeded"); + + ret = H5Sclose(small_ds_slice_sid); + VRFY((ret != FAIL), "H5Sclose(small_ds_slice_sid) succeeded"); + + ret = H5Sclose(full_mem_large_ds_sid); + VRFY((ret != FAIL), "H5Sclose(full_mem_large_ds_sid) succeeded"); + + ret = H5Sclose(full_file_large_ds_sid); + VRFY((ret != FAIL), "H5Sclose(full_file_large_ds_sid) succeeded"); + + ret = H5Sclose(mem_large_ds_sid); + VRFY((ret != FAIL), "H5Sclose(mem_large_ds_sid) succeeded"); + + ret = H5Sclose(file_large_ds_sid); + VRFY((ret != FAIL), "H5Sclose(mem_large_ds_sid) succeeded"); + + ret = H5Sclose(mem_large_ds_process_slice_sid); + VRFY((ret != FAIL), "H5Sclose(mem_large_ds_process_slice_sid) succeeded"); + + ret = H5Sclose(file_large_ds_process_slice_sid); + VRFY((ret != FAIL), "H5Sclose(file_large_ds_process_slice_sid) succeeded"); + + ret = H5Sclose(large_ds_slice_sid); + VRFY((ret != FAIL), "H5Sclose(large_ds_slice_sid) succeeded"); + + + /* Close Datasets */ + ret = H5Dclose(small_dataset); + VRFY((ret != FAIL), "H5Dclose(small_dataset) succeeded"); + + ret = H5Dclose(large_dataset); + VRFY((ret != FAIL), "H5Dclose(large_dataset) succeeded"); + + + /* close the file collectively */ + MESG("about to close file."); + ret = H5Fclose(fid); + VRFY((ret != FAIL), "file close succeeded"); + + /* Free memory buffers */ + + if ( small_ds_buf_0 != NULL ) HDfree(small_ds_buf_0); + if ( small_ds_buf_1 != NULL ) HDfree(small_ds_buf_1); + if ( small_ds_buf_2 != NULL ) HDfree(small_ds_buf_2); + if ( small_ds_slice_buf != NULL ) HDfree(small_ds_slice_buf); + + if ( large_ds_buf_0 != NULL ) HDfree(large_ds_buf_0); + if ( large_ds_buf_1 != NULL ) HDfree(large_ds_buf_1); + if ( large_ds_buf_2 != NULL ) HDfree(large_ds_buf_2); + if ( large_ds_slice_buf != NULL ) HDfree(large_ds_slice_buf); + + return; + +} /* contig_hyperslab_dr_pio_test__run_test() */ + + +/*------------------------------------------------------------------------- + * Function: contig_hyperslab_dr_pio_test() + * + * Purpose: Test I/O to/from hyperslab selections of different rank in + * the parallel case. + * + * Return: void + * + * Programmer: JRM -- 9/18/09 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +void +contig_hyperslab_dr_pio_test(void) +{ + const char *fcnName = "contig_hyperslab_dr_pio_test()"; + int test_num = 0; + int edge_size = 10; + int chunk_edge_size = 0; + int small_rank; + int large_rank; + int use_collective_io; + hid_t dset_type = H5T_STD_U32LE; + + for ( large_rank = 3; large_rank <= PAR_SS_DR_MAX_RANK; large_rank++ ) { + + for ( small_rank = 2; small_rank < large_rank; small_rank++ ) { + + for ( use_collective_io = 0; + use_collective_io <= 1; + use_collective_io++ ) { + + chunk_edge_size = 0; + contig_hyperslab_dr_pio_test__run_test(test_num, + edge_size, + chunk_edge_size, + small_rank, + large_rank, + (hbool_t)use_collective_io, + dset_type); + test_num++; +#if 1 + chunk_edge_size = 5; + contig_hyperslab_dr_pio_test__run_test(test_num, + edge_size, + chunk_edge_size, + small_rank, + large_rank, + (hbool_t)use_collective_io, + dset_type); + test_num++; +#endif + } + } + } + + return; + +} /* contig_hyperslab_dr_pio_test() */ + + +/**************************************************************** +** +** checker_board_hyperslab_dr_pio_test__select_checker_board(): +** Given a data space of tgt_rank, and dimensions: +** +** (mpi_size + 1), edge_size, ... , edge_size +** +** edge_size, and a checker_edge_size, select a checker +** board selection of a sel_rank (sel_rank < tgt_rank) +** dimensional slice through the data space parallel to the +** sel_rank fastest changing indicies, with origin (in the +** higher indicies) as indicated by the start array. +** +** Note that this function, like all its relatives, is +** hard coded to presume a maximum data space rank of 5. +** While this maximum is declared as a constant, increasing +** it will require extensive coding in addition to changing +** the value of the constant. +** +** JRM -- 10/8/09 +** +****************************************************************/ + +#define CHECKER_BOARD_HYPERSLAB_DR_PIO_TEST__SELECT_CHECKER_BOARD__DEBUG 0 + +static void +checker_board_hyperslab_dr_pio_test__select_checker_board( + const int mpi_rank, + const hid_t tgt_sid, + const int tgt_rank, + const int edge_size, + const int checker_edge_size, + const int sel_rank, + hsize_t sel_start[]) +{ +#if CHECKER_BOARD_HYPERSLAB_DR_PIO_TEST__SELECT_CHECKER_BOARD__DEBUG + const char * fcnName = + "checker_board_hyperslab_dr_pio_test__select_checker_board():"; +#endif + hbool_t first_selection = TRUE; + int i, j, k, l, m; + int n_cube_offset; + int sel_offset; + const int test_max_rank = PAR_SS_DR_MAX_RANK; /* must update code if */ + /* this changes */ + hsize_t base_count; + hsize_t offset_count; + hsize_t start[PAR_SS_DR_MAX_RANK]; + hsize_t stride[PAR_SS_DR_MAX_RANK]; + hsize_t count[PAR_SS_DR_MAX_RANK]; + hsize_t block[PAR_SS_DR_MAX_RANK]; + herr_t ret; /* Generic return value */ + + HDassert( edge_size >= 6 ); + HDassert( 0 < checker_edge_size ); + HDassert( checker_edge_size <= edge_size ); + HDassert( 0 < sel_rank ); + HDassert( sel_rank <= tgt_rank ); + HDassert( tgt_rank <= test_max_rank ); + HDassert( test_max_rank <= PAR_SS_DR_MAX_RANK ); + + sel_offset = test_max_rank - sel_rank; + HDassert( sel_offset >= 0 ); + + n_cube_offset = test_max_rank - tgt_rank; + HDassert( n_cube_offset >= 0 ); + HDassert( n_cube_offset <= sel_offset ); + +#if CHECKER_BOARD_HYPERSLAB_DR_PIO_TEST__SELECT_CHECKER_BOARD__DEBUG + HDfprintf(stdout, "%s:%d: edge_size/checker_edge_size = %d/%d\n", + fcnName, mpi_rank, edge_size, checker_edge_size); + HDfprintf(stdout, "%s:%d: sel_rank/sel_offset = %d/%d.\n", + fcnName, mpi_rank, sel_rank, sel_offset); + HDfprintf(stdout, "%s:%d: tgt_rank/n_cube_offset = %d/%d.\n", + fcnName, mpi_rank, tgt_rank, n_cube_offset); +#endif /* CHECKER_BOARD_HYPERSLAB_DR_PIO_TEST__SELECT_CHECKER_BOARD__DEBUG */ + + /* First, compute the base count (which assumes start == 0 + * for the associated offset) and offset_count (which + * assumes start == checker_edge_size for the associated + * offset). + * + * Note that the following computation depends on the C99 + * requirement that integer division discard any fraction + * (truncation towards zero) to function correctly. As we + * now require C99, this shouldn't be a problem, but noting + * it may save us some pain if we are ever obliged to support + * pre-C99 compilers again. + */ + + base_count = edge_size / (checker_edge_size * 2); + + if ( (edge_size % (checker_edge_size * 2)) > 0 ) { + + base_count++; + } + + offset_count = (edge_size - checker_edge_size) / (checker_edge_size * 2); + + if ( ((edge_size - checker_edge_size) % (checker_edge_size * 2)) > 0 ) { + + offset_count++; + } + + /* Now set up the stride and block arrays, and portions of the start + * and count arrays that will not be altered during the selection of + * the checker board. + */ + i = 0; + while ( i < n_cube_offset ) { + + /* these values should never be used */ + start[i] = 0; + stride[i] = 0; + count[i] = 0; + block[i] = 0; + + i++; + } + + while ( i < sel_offset ) { + + start[i] = sel_start[i]; + stride[i] = 2 * edge_size; + count[i] = 1; + block[i] = 1; + + i++; + } + + while ( i < test_max_rank ) { + + stride[i] = 2 * checker_edge_size; + block[i] = checker_edge_size; + + i++; + } + + i = 0; + do { + if ( 0 >= sel_offset ) { + + if ( i == 0 ) { + + start[0] = 0; + count[0] = base_count; + + } else { + + start[0] = checker_edge_size; + count[0] = offset_count; + + } + } + + j = 0; + do { + if ( 1 >= sel_offset ) { + + if ( j == 0 ) { + + start[1] = 0; + count[1] = base_count; + + } else { + + start[1] = checker_edge_size; + count[1] = offset_count; + + } + } + + k = 0; + do { + if ( 2 >= sel_offset ) { + + if ( k == 0 ) { + + start[2] = 0; + count[2] = base_count; + + } else { + + start[2] = checker_edge_size; + count[2] = offset_count; + + } + } + + l = 0; + do { + if ( 3 >= sel_offset ) { + + if ( l == 0 ) { + + start[3] = 0; + count[3] = base_count; + + } else { + + start[3] = checker_edge_size; + count[3] = offset_count; + + } + } + + m = 0; + do { + if ( 4 >= sel_offset ) { + + if ( m == 0 ) { + + start[4] = 0; + count[4] = base_count; + + } else { + + start[4] = checker_edge_size; + count[4] = offset_count; + + } + } + + if ( ((i + j + k + l + m) % 2) == 0 ) { + +#if CHECKER_BOARD_HYPERSLAB_DR_PIO_TEST__SELECT_CHECKER_BOARD__DEBUG + HDfprintf(stdout, "%s%d: *** first_selection = %d ***\n", + fcnName, mpi_rank, (int)first_selection); + HDfprintf(stdout, "%s:%d: i/j/k/l/m = %d/%d/%d/%d/%d\n", + fcnName, mpi_rank, i, j, k, l, m); + HDfprintf(stdout, + "%s:%d: start = %d %d %d %d %d.\n", + fcnName, mpi_rank, (int)start[0], (int)start[1], + (int)start[2], (int)start[3], (int)start[4]); + HDfprintf(stdout, + "%s:%d: stride = %d %d %d %d %d.\n", + fcnName, mpi_rank, (int)stride[0], (int)stride[1], + (int)stride[2], (int)stride[3], (int)stride[4]); + HDfprintf(stdout, + "%s:%d: count = %d %d %d %d %d.\n", + fcnName, mpi_rank, (int)count[0], (int)count[1], + (int)count[2], (int)count[3], (int)count[4]); + HDfprintf(stdout, + "%s:%d: block = %d %d %d %d %d.\n", + fcnName, mpi_rank, (int)block[0], (int)block[1], + (int)block[2], (int)block[3], (int)block[4]); + HDfprintf(stdout, "%s:%d: n-cube extent dims = %d.\n", + fcnName, mpi_rank, + H5Sget_simple_extent_ndims(tgt_sid)); + HDfprintf(stdout, "%s:%d: selection rank = %d.\n", + fcnName, mpi_rank, sel_rank); +#endif + + if ( first_selection ) { + + first_selection = FALSE; + + ret = H5Sselect_hyperslab + ( + tgt_sid, + H5S_SELECT_SET, + &(start[n_cube_offset]), + &(stride[n_cube_offset]), + &(count[n_cube_offset]), + &(block[n_cube_offset]) + ); + + VRFY((ret != FAIL), "H5Sselect_hyperslab(SET) succeeded"); + + } else { + + ret = H5Sselect_hyperslab + ( + tgt_sid, + H5S_SELECT_OR, + &(start[n_cube_offset]), + &(stride[n_cube_offset]), + &(count[n_cube_offset]), + &(block[n_cube_offset]) + ); + + VRFY((ret != FAIL), "H5Sselect_hyperslab(OR) succeeded"); + + } + } + + m++; + + } while ( ( m <= 1 ) && + ( 4 >= sel_offset ) ); + + l++; + + } while ( ( l <= 1 ) && + ( 3 >= sel_offset ) ); + + k++; + + } while ( ( k <= 1 ) && + ( 2 >= sel_offset ) ); + + j++; + + } while ( ( j <= 1 ) && + ( 1 >= sel_offset ) ); + + + i++; + + } while ( ( i <= 1 ) && + ( 0 >= sel_offset ) ); + +#if CHECKER_BOARD_HYPERSLAB_DR_PIO_TEST__SELECT_CHECKER_BOARD__DEBUG + HDfprintf(stdout, "%s%d: H5Sget_select_npoints(tgt_sid) = %d.\n", + fcnName, mpi_rank, (int)H5Sget_select_npoints(tgt_sid)); +#endif /* CHECKER_BOARD_HYPERSLAB_DR_PIO_TEST__SELECT_CHECKER_BOARD__DEBUG */ + + /* Clip the selection back to the data space proper. */ + + for ( i = 0; i < test_max_rank; i++ ) { + + start[i] = 0; + stride[i] = edge_size; + count[i] = 1; + block[i] = edge_size; + } + + ret = H5Sselect_hyperslab(tgt_sid, H5S_SELECT_AND, + start, stride, count, block); + + VRFY((ret != FAIL), "H5Sselect_hyperslab(AND) succeeded"); + +#if CHECKER_BOARD_HYPERSLAB_DR_PIO_TEST__SELECT_CHECKER_BOARD__DEBUG + HDfprintf(stdout, "%s%d: H5Sget_select_npoints(tgt_sid) = %d.\n", + fcnName, mpi_rank, (int)H5Sget_select_npoints(tgt_sid)); + HDfprintf(stdout, "%s%d: done.\n", fcnName, mpi_rank); +#endif /* CHECKER_BOARD_HYPERSLAB_DR_PIO_TEST__SELECT_CHECKER_BOARD__DEBUG */ + + return; + +} /* checker_board_hyperslab_dr_pio_test__select_checker_board() */ + + +/**************************************************************** +** +** checker_board_hyperslab_dr_pio_test__verify_data(): +** +** Examine the supplied buffer to see if it contains the +** expected data. Return TRUE if it does, and FALSE +** otherwise. +** +** The supplied buffer is presumed to this process's slice +** of the target data set. Each such slice will be an +** n-cube of rank (rank -1) and the supplied edge_size with +** origin (mpi_rank, 0, ... , 0) in the target data set. +** +** Further, the buffer is presumed to be the result of reading +** or writing a checker board selection of an m (1 <= m < +** rank) dimensional slice through this processes slice +** of the target data set. Also, this slice must be parallel +** to the fastest changing indicies. +** +** It is further presumed that the buffer was zeroed before +** the read/write, and that the full target data set (i.e. +** the buffer/data set for all processes) was initialized +** with the natural numbers listed in order from the origin +** along the fastest changing axis. +** +** Thus for a 20x10x10 dataset, the value stored in location +** (x, y, z) (assuming that z is the fastest changing index +** and x the slowest) is assumed to be: +** +** (10 * 10 * x) + (10 * y) + z +** +** Further, supposing that this is process 10, this process's +** slice of the dataset would be a 10 x 10 2-cube with origin +** (10, 0, 0) in the data set, and would be initialize (prior +** to the checkerboard selection) as follows: +** +** 1000, 1001, 1002, ... 1008, 1009 +** 1010, 1011, 1012, ... 1018, 1019 +** . . . . . +** . . . . . +** . . . . . +** 1090, 1091, 1092, ... 1098, 1099 +** +** In the case of a read from the processors slice of another +** data set of different rank, the values expected will have +** to be adjusted accordingly. This is done via the +** first_expected_val parameter. +** +** Finally, the function presumes that the first element +** of the buffer resides either at the origin of either +** a selected or an unselected checker. (Translation: +** if partial checkers appear in the buffer, they will +** intersect the edges of the n-cube oposite the origin.) +** +****************************************************************/ + +#define CHECKER_BOARD_HYPERSLAB_DR_PIO_TEST__VERIFY_DATA__DEBUG 0 + +static hbool_t +checker_board_hyperslab_dr_pio_test__verify_data(uint32_t * buf_ptr, + const int mpi_rank, + const int rank, + const int edge_size, + const int checker_edge_size, + uint32_t first_expected_val, + hbool_t buf_starts_in_checker) +{ +#if CHECKER_BOARD_HYPERSLAB_DR_PIO_TEST__VERIFY_DATA__DEBUG + const char * fcnName = + "checker_board_hyperslab_dr_pio_test__verify_data():"; +#endif + hbool_t good_data = TRUE; + hbool_t in_checker; + hbool_t start_in_checker[5]; + uint32_t expected_value; + uint32_t * val_ptr; + int i, j, k, l, m; /* to track position in n-cube */ + int v, w, x, y, z; /* to track position in checker */ + const int test_max_rank = 5; /* code changes needed if this is increased */ + + HDassert( buf_ptr != NULL ); + HDassert( 0 < rank ); + HDassert( rank <= test_max_rank ); + HDassert( edge_size >= 6 ); + HDassert( 0 < checker_edge_size ); + HDassert( checker_edge_size <= edge_size ); + HDassert( test_max_rank <= PAR_SS_DR_MAX_RANK ); + +#if CHECKER_BOARD_HYPERSLAB_DR_PIO_TEST__VERIFY_DATA__DEBUG + HDfprintf(stdout, "%s mpi_rank = %d.\n", fcnName, mpi_rank); + HDfprintf(stdout, "%s rank = %d.\n", fcnName, rank); + HDfprintf(stdout, "%s edge_size = %d.\n", fcnName, edge_size); + HDfprintf(stdout, "%s checker_edge_size = %d.\n", fcnName, checker_edge_size); + HDfprintf(stdout, "%s first_expected_val = %d.\n", fcnName, (int)first_expected_val); + HDfprintf(stdout, "%s starts_in_checker = %d.\n", fcnName, (int)buf_starts_in_checker); +#endif + + val_ptr = buf_ptr; + expected_value = first_expected_val; + + i = 0; + v = 0; + start_in_checker[0] = buf_starts_in_checker; + do + { + if ( v >= checker_edge_size ) { + + start_in_checker[0] = ! start_in_checker[0]; + v = 0; + } + + j = 0; + w = 0; + start_in_checker[1] = start_in_checker[0]; + do + { + if ( w >= checker_edge_size ) { + + start_in_checker[1] = ! start_in_checker[1]; + w = 0; + } + + k = 0; + x = 0; + start_in_checker[2] = start_in_checker[1]; + do + { + if ( x >= checker_edge_size ) { + + start_in_checker[2] = ! start_in_checker[2]; + x = 0; + } + + l = 0; + y = 0; + start_in_checker[3] = start_in_checker[2]; + do + { + if ( y >= checker_edge_size ) { + + start_in_checker[3] = ! start_in_checker[3]; + y = 0; + } + + m = 0; + z = 0; +#if CHECKER_BOARD_HYPERSLAB_DR_PIO_TEST__VERIFY_DATA__DEBUG + HDfprintf(stdout, "%d, %d, %d, %d, %d:", i, j, k, l, m); +#endif + in_checker = start_in_checker[3]; + do + { +#if CHECKER_BOARD_HYPERSLAB_DR_PIO_TEST__VERIFY_DATA__DEBUG + HDfprintf(stdout, " %d", (int)(*val_ptr)); +#endif + if ( z >= checker_edge_size ) { + + in_checker = ! in_checker; + z = 0; + } + + if ( in_checker ) { + + if ( *val_ptr != expected_value ) { + + good_data = FALSE; + } + + /* zero out buffer for re-use */ + *val_ptr = 0; + + } else if ( *val_ptr != 0 ) { + + good_data = FALSE; + + /* zero out buffer for re-use */ + *val_ptr = 0; + + } + + val_ptr++; + expected_value++; + m++; + z++; + + } while ( ( rank >= (test_max_rank - 4) ) && + ( m < edge_size ) ); +#if CHECKER_BOARD_HYPERSLAB_DR_PIO_TEST__VERIFY_DATA__DEBUG + HDfprintf(stdout, "\n"); +#endif + l++; + y++; + } while ( ( rank >= (test_max_rank - 3) ) && + ( l < edge_size ) ); + k++; + x++; + } while ( ( rank >= (test_max_rank - 2) ) && + ( k < edge_size ) ); + j++; + w++; + } while ( ( rank >= (test_max_rank - 1) ) && + ( j < edge_size ) ); + i++; + v++; + } while ( ( rank >= test_max_rank ) && + ( i < edge_size ) ); + + return(good_data); + +} /* checker_board_hyperslab_dr_pio_test__verify_data() */ + + +/*------------------------------------------------------------------------- + * Function: checker_board_hyperslab_dr_pio_test__run_test() + * + * Purpose: Test I/O to/from checkerboard selections of hyperslabs of + * different rank in the parallel. + * + * Return: void + * + * Programmer: JRM -- 10/10/09 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +#define PAR_SS_DR_MAX_RANK 5 +#define CHECKER_BOARD_HYPERSLAB_DR_PIO_TEST__RUN_TEST__DEBUG 0 + +void +checker_board_hyperslab_dr_pio_test__run_test(const int test_num, + const int edge_size, + const int checker_edge_size, + const int chunk_edge_size, + const int small_rank, + const int large_rank, + const hbool_t use_collective_io, + const hid_t dset_type) +{ + const char *fcnName = "checker_board_hyperslab_dr_pio_test__run_test()"; + const char *filename; + hbool_t use_gpfs = FALSE; /* Use GPFS hints */ + hbool_t data_ok = FALSE; + hbool_t mis_match = FALSE; + int i, j, k, l, m, n; + int mrc; + int start_index; + int stop_index; + int small_ds_offset; + int large_ds_offset; + const int test_max_rank = 5; /* must update code if this changes */ + uint32_t expected_value; + uint32_t * small_ds_buf_0 = NULL; + uint32_t * small_ds_buf_1 = NULL; + uint32_t * small_ds_buf_2 = NULL; + uint32_t * small_ds_slice_buf = NULL; + uint32_t * large_ds_buf_0 = NULL; + uint32_t * large_ds_buf_1 = NULL; + uint32_t * large_ds_buf_2 = NULL; + uint32_t * large_ds_slice_buf = NULL; + uint32_t * ptr_0; + uint32_t * ptr_1; + uint32_t * ptr_2; + int mpi_rank; + int mpi_size; + MPI_Comm mpi_comm = MPI_COMM_NULL; + MPI_Info mpi_info = MPI_INFO_NULL; + hid_t fid; /* HDF5 file ID */ + hid_t acc_tpl; /* File access templates */ + hid_t xfer_plist = H5P_DEFAULT; + hid_t full_mem_small_ds_sid; + hid_t full_file_small_ds_sid; + hid_t mem_small_ds_sid; + hid_t file_small_ds_sid_0; + hid_t file_small_ds_sid_1; + hid_t small_ds_slice_sid; + hid_t full_mem_large_ds_sid; + hid_t full_file_large_ds_sid; + hid_t mem_large_ds_sid; + hid_t file_large_ds_sid_0; + hid_t file_large_ds_sid_1; + hid_t file_large_ds_process_slice_sid; + hid_t mem_large_ds_process_slice_sid; + hid_t large_ds_slice_sid; + hid_t small_ds_dcpl_id = H5P_DEFAULT; + hid_t large_ds_dcpl_id = H5P_DEFAULT; + hid_t small_dataset; /* Dataset ID */ + hid_t large_dataset; /* Dataset ID */ + size_t small_ds_size = 1; + size_t small_ds_slice_size = 1; + size_t large_ds_size = 1; + size_t large_ds_slice_size = 1; + hsize_t dims[PAR_SS_DR_MAX_RANK]; + hsize_t chunk_dims[PAR_SS_DR_MAX_RANK]; + hsize_t start[PAR_SS_DR_MAX_RANK]; + hsize_t stride[PAR_SS_DR_MAX_RANK]; + hsize_t count[PAR_SS_DR_MAX_RANK]; + hsize_t block[PAR_SS_DR_MAX_RANK]; + hsize_t sel_start[PAR_SS_DR_MAX_RANK]; + hsize_t * start_ptr = NULL; + hsize_t * stride_ptr = NULL; + hsize_t * count_ptr = NULL; + hsize_t * block_ptr = NULL; + htri_t check; /* Shape comparison return value */ + herr_t ret; /* Generic return value */ + + HDassert( edge_size >= 6 ); + HDassert( edge_size >= chunk_edge_size ); + HDassert( ( chunk_edge_size == 0 ) || ( chunk_edge_size >= 3 ) ); + HDassert( 1 < small_rank ); + HDassert( small_rank < large_rank ); + HDassert( large_rank <= test_max_rank ); + HDassert( test_max_rank <= PAR_SS_DR_MAX_RANK ); + + MPI_Comm_size(MPI_COMM_WORLD, &mpi_size); + MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank); + + HDassert( mpi_size >= 1 ); + + mpi_comm = MPI_COMM_WORLD; + mpi_info = MPI_INFO_NULL; + + for ( i = 0; i < small_rank - 1; i++ ) + { + small_ds_size *= (size_t)edge_size; + small_ds_slice_size *= (size_t)edge_size; + } + small_ds_size *= (size_t)(mpi_size + 1); + + small_ds_offset = PAR_SS_DR_MAX_RANK - small_rank; + + HDassert( 0 < small_ds_offset ); + HDassert( small_ds_offset < PAR_SS_DR_MAX_RANK ); + + + for ( i = 0; i < large_rank - 1; i++ ) { + + large_ds_size *= (size_t)edge_size; + large_ds_slice_size *= (size_t)edge_size; + } + large_ds_size *= (size_t)(mpi_size + 1); + + large_ds_offset = PAR_SS_DR_MAX_RANK - large_rank; + + HDassert( 0 <= large_ds_offset ); + HDassert( large_ds_offset < PAR_SS_DR_MAX_RANK ); + + + /* set up the start, stride, count, and block pointers */ + start_ptr = &(start[PAR_SS_DR_MAX_RANK - large_rank]); + stride_ptr = &(stride[PAR_SS_DR_MAX_RANK - large_rank]); + count_ptr = &(count[PAR_SS_DR_MAX_RANK - large_rank]); + block_ptr = &(block[PAR_SS_DR_MAX_RANK - large_rank]); + + + /* Allocate buffers */ + small_ds_buf_0 = (uint32_t *)HDmalloc(sizeof(uint32_t) * small_ds_size); + VRFY((small_ds_buf_0 != NULL), "malloc of small_ds_buf_0 succeeded"); + + small_ds_buf_1 = (uint32_t *)HDmalloc(sizeof(uint32_t) * small_ds_size); + VRFY((small_ds_buf_1 != NULL), "malloc of small_ds_buf_1 succeeded"); + + small_ds_buf_2 = (uint32_t *)HDmalloc(sizeof(uint32_t) * small_ds_size); + VRFY((small_ds_buf_2 != NULL), "malloc of small_ds_buf_2 succeeded"); + + small_ds_slice_buf = + (uint32_t *)HDmalloc(sizeof(uint32_t) * small_ds_slice_size); + VRFY((small_ds_slice_buf != NULL), "malloc of small_ds_slice_buf succeeded"); + + large_ds_buf_0 = (uint32_t *)HDmalloc(sizeof(uint32_t) * large_ds_size); + VRFY((large_ds_buf_0 != NULL), "malloc of large_ds_buf_0 succeeded"); + + large_ds_buf_1 = (uint32_t *)HDmalloc(sizeof(uint32_t) * large_ds_size); + VRFY((large_ds_buf_1 != NULL), "malloc of large_ds_buf_1 succeeded"); + + large_ds_buf_2 = (uint32_t *)HDmalloc(sizeof(uint32_t) * large_ds_size); + VRFY((large_ds_buf_2 != NULL), "malloc of large_ds_buf_2 succeeded"); + + large_ds_slice_buf = + (uint32_t *)HDmalloc(sizeof(uint32_t) * large_ds_slice_size); + VRFY((large_ds_slice_buf != NULL), "malloc of large_ds_slice_buf succeeded"); + + /* initialize the buffers */ + + ptr_0 = small_ds_buf_0; + ptr_1 = small_ds_buf_1; + ptr_2 = small_ds_buf_2; + + for ( i = 0; i < (int)small_ds_size; i++ ) { + + *ptr_0 = (uint32_t)i; + *ptr_1 = 0; + *ptr_2 = 0; + + ptr_0++; + ptr_1++; + ptr_2++; + } + + ptr_0 = small_ds_slice_buf; + + for ( i = 0; i < (int)small_ds_slice_size; i++ ) { + + *ptr_0 = (uint32_t)i; + ptr_0++; + } + + ptr_0 = large_ds_buf_0; + ptr_1 = large_ds_buf_1; + ptr_2 = large_ds_buf_2; + + for ( i = 0; i < (int)large_ds_size; i++ ) { + + *ptr_0 = (uint32_t)i; + *ptr_1 = 0; + *ptr_2 = 0; + + ptr_0++; + ptr_1++; + ptr_2++; + } + + ptr_0 = large_ds_slice_buf; + + for ( i = 0; i < (int)large_ds_slice_size; i++ ) { + + *ptr_0 = (uint32_t)0; + ptr_0++; + } + + filename = (const char *)GetTestParameters(); + HDassert( filename != NULL ); + +#if CHECKER_BOARD_HYPERSLAB_DR_PIO_TEST__RUN_TEST__DEBUG + if ( MAINPROCESS ) { + + HDfprintf(stdout, "%s:%d: test num = %d.\n", fcnName, mpi_rank, test_num); + HDfprintf(stdout, "%s:%d: mpi_size = %d.\n", fcnName, mpi_rank, mpi_size); + HDfprintf(stdout, + "%s:%d: small/large rank = %d/%d, use_collective_io = %d.\n", + fcnName, mpi_rank, small_rank, large_rank, (int)use_collective_io); + HDfprintf(stdout, "%s:%d: edge_size = %d, chunk_edge_size = %d.\n", + fcnName, mpi_rank, edge_size, chunk_edge_size); + HDfprintf(stdout, "%s:%d: checker_edge_size = %d.\n", + fcnName, mpi_rank, checker_edge_size); + HDfprintf(stdout, "%s:%d: small_ds_size = %d, large_ds_size = %d.\n", + fcnName, mpi_rank, (int)small_ds_size, (int)large_ds_size); + HDfprintf(stdout, "%s:%d: filename = %s.\n", fcnName, mpi_rank, filename); + } +#endif /* CHECKER_BOARD_HYPERSLAB_DR_PIO_TEST__RUN_TEST__DEBUG */ + + /* ---------------------------------------- + * CREATE AN HDF5 FILE WITH PARALLEL ACCESS + * ---------------------------------------*/ + /* setup file access template */ + acc_tpl = create_faccess_plist(mpi_comm, mpi_info, facc_type, use_gpfs); + VRFY((acc_tpl >= 0), "create_faccess_plist() succeeded"); + + /* create the file collectively */ + fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, acc_tpl); + VRFY((fid >= 0), "H5Fcreate succeeded"); + + MESG("File opened."); + + /* Release file-access template */ + ret = H5Pclose(acc_tpl); + VRFY((ret >= 0), "H5Pclose(acc_tpl) succeeded"); + + + /* setup dims: */ + dims[0] = (int)(mpi_size + 1); + dims[1] = dims[2] = dims[3] = dims[4] = edge_size; + + + /* Create small ds dataspaces */ + full_mem_small_ds_sid = H5Screate_simple(small_rank, dims, NULL); + VRFY((full_mem_small_ds_sid != 0), + "H5Screate_simple() full_mem_small_ds_sid succeeded"); + + full_file_small_ds_sid = H5Screate_simple(small_rank, dims, NULL); + VRFY((full_file_small_ds_sid != 0), + "H5Screate_simple() full_file_small_ds_sid succeeded"); + + mem_small_ds_sid = H5Screate_simple(small_rank, dims, NULL); + VRFY((mem_small_ds_sid != 0), + "H5Screate_simple() mem_small_ds_sid succeeded"); + + file_small_ds_sid_0 = H5Screate_simple(small_rank, dims, NULL); + VRFY((file_small_ds_sid_0 != 0), + "H5Screate_simple() file_small_ds_sid_0 succeeded"); + + file_small_ds_sid_1 = H5Screate_simple(small_rank, dims, NULL); + VRFY((file_small_ds_sid_1 != 0), + "H5Screate_simple() file_small_ds_sid_1 succeeded"); + + small_ds_slice_sid = H5Screate_simple(small_rank - 1, &(dims[1]), NULL); + VRFY((small_ds_slice_sid != 0), + "H5Screate_simple() small_ds_slice_sid succeeded"); + + + /* Create large ds dataspaces */ + full_mem_large_ds_sid = H5Screate_simple(large_rank, dims, NULL); + VRFY((full_mem_large_ds_sid != 0), + "H5Screate_simple() full_mem_large_ds_sid succeeded"); + + full_file_large_ds_sid = H5Screate_simple(large_rank, dims, NULL); + VRFY((full_file_large_ds_sid != FAIL), + "H5Screate_simple() full_file_large_ds_sid succeeded"); + + mem_large_ds_sid = H5Screate_simple(large_rank, dims, NULL); + VRFY((mem_large_ds_sid != FAIL), + "H5Screate_simple() mem_large_ds_sid succeeded"); + + file_large_ds_sid_0 = H5Screate_simple(large_rank, dims, NULL); + VRFY((file_large_ds_sid_0 != FAIL), + "H5Screate_simple() file_large_ds_sid_0 succeeded"); + + file_large_ds_sid_1 = H5Screate_simple(large_rank, dims, NULL); + VRFY((file_large_ds_sid_1 != FAIL), + "H5Screate_simple() file_large_ds_sid_1 succeeded"); + + mem_large_ds_process_slice_sid = H5Screate_simple(large_rank, dims, NULL); + VRFY((mem_large_ds_process_slice_sid != FAIL), + "H5Screate_simple() mem_large_ds_process_slice_sid succeeded"); + + file_large_ds_process_slice_sid = H5Screate_simple(large_rank, dims, NULL); + VRFY((file_large_ds_process_slice_sid != FAIL), + "H5Screate_simple() file_large_ds_process_slice_sid succeeded"); + + + large_ds_slice_sid = H5Screate_simple(large_rank - 1, &(dims[1]), NULL); + VRFY((large_ds_slice_sid != 0), + "H5Screate_simple() large_ds_slice_sid succeeded"); + + + /* Select the entire extent of the full small ds, and ds slice dataspaces */ + ret = H5Sselect_all(full_mem_small_ds_sid); + VRFY((ret != FAIL), "H5Sselect_all(full_mem_small_ds_sid) succeeded"); + + ret = H5Sselect_all(full_file_small_ds_sid); + VRFY((ret != FAIL), "H5Sselect_all(full_file_small_ds_sid) succeeded"); + + ret = H5Sselect_all(small_ds_slice_sid); + VRFY((ret != FAIL), "H5Sselect_all(small_ds_slice_sid) succeeded"); + + + /* Select the entire extent of the full large ds, and ds slice dataspaces */ + ret = H5Sselect_all(full_mem_large_ds_sid); + VRFY((ret != FAIL), "H5Sselect_all(full_mem_large_ds_sid) succeeded"); + + ret = H5Sselect_all(full_file_large_ds_sid); + VRFY((ret != FAIL), "H5Sselect_all(full_file_large_ds_sid) succeeded"); + + ret = H5Sselect_all(large_ds_slice_sid); + VRFY((ret != FAIL), "H5Sselect_all(large_ds_slice_sid) succeeded"); + + + /* if chunk edge size is greater than zero, set up the small and + * large data set creation property lists to specify chunked + * datasets. + */ + if ( chunk_edge_size > 0 ) { + + chunk_dims[0] = mpi_size + 1; + chunk_dims[1] = chunk_dims[2] = + chunk_dims[3] = chunk_dims[4] = chunk_edge_size; + + small_ds_dcpl_id = H5Pcreate(H5P_DATASET_CREATE); + VRFY((ret != FAIL), "H5Pcreate() small_ds_dcpl_id succeeded"); + + ret = H5Pset_layout(small_ds_dcpl_id, H5D_CHUNKED); + VRFY((ret != FAIL), "H5Pset_layout() small_ds_dcpl_id succeeded"); + + ret = H5Pset_chunk(small_ds_dcpl_id, small_rank, chunk_dims); + VRFY((ret != FAIL), "H5Pset_chunk() small_ds_dcpl_id succeeded"); + + + large_ds_dcpl_id = H5Pcreate(H5P_DATASET_CREATE); + VRFY((ret != FAIL), "H5Pcreate() large_ds_dcpl_id succeeded"); + + ret = H5Pset_layout(large_ds_dcpl_id, H5D_CHUNKED); + VRFY((ret != FAIL), "H5Pset_layout() large_ds_dcpl_id succeeded"); + + ret = H5Pset_chunk(large_ds_dcpl_id, large_rank, chunk_dims); + VRFY((ret != FAIL), "H5Pset_chunk() large_ds_dcpl_id succeeded"); + } + + /* create the small dataset */ + small_dataset = H5Dcreate2(fid, "small_dataset", dset_type, + file_small_ds_sid_0, H5P_DEFAULT, + small_ds_dcpl_id, H5P_DEFAULT); + VRFY((ret != FAIL), "H5Dcreate2() small_dataset succeeded"); + + /* create the large dataset */ + large_dataset = H5Dcreate2(fid, "large_dataset", dset_type, + file_large_ds_sid_0, H5P_DEFAULT, + large_ds_dcpl_id, H5P_DEFAULT); + VRFY((ret != FAIL), "H5Dcreate2() large_dataset succeeded"); + + + + /* setup xfer property list */ + xfer_plist = H5Pcreate(H5P_DATASET_XFER); + VRFY((xfer_plist >= 0), "H5Pcreate(H5P_DATASET_XFER) succeeded"); + + ret = H5Pset_dxpl_mpio(xfer_plist, H5FD_MPIO_COLLECTIVE); + VRFY((ret >= 0), "H5Pset_dxpl_mpio succeeded"); + + if ( ! use_collective_io ) { + + ret = H5Pset_dxpl_mpio_collective_opt(xfer_plist, + H5FD_MPIO_INDIVIDUAL_IO); + VRFY((ret>= 0), "H5Pset_dxpl_mpio_collective_opt() suceeded"); + } + + /* setup selection to write initial data to the small and large data sets */ + start[0] = mpi_rank; + stride[0] = 2 * (mpi_size + 1); + count[0] = 1; + block[0] = 1; + + for ( i = 1; i < large_rank; i++ ) { + + start[i] = 0; + stride[i] = 2 * edge_size; + count[i] = 1; + block[i] = edge_size; + } + + /* setup selections for writing initial data to the small data set */ + ret = H5Sselect_hyperslab(mem_small_ds_sid, + H5S_SELECT_SET, + start, + stride, + count, + block); + VRFY((ret >= 0), "H5Sselect_hyperslab(mem_small_ds_sid, set) suceeded"); + + ret = H5Sselect_hyperslab(file_small_ds_sid_0, + H5S_SELECT_SET, + start, + stride, + count, + block); + VRFY((ret >= 0), "H5Sselect_hyperslab(file_small_ds_sid_0, set) suceeded"); + + if ( MAINPROCESS ) { /* add an additional slice to the selections */ + + start[0] = mpi_size; + + ret = H5Sselect_hyperslab(mem_small_ds_sid, + H5S_SELECT_OR, + start, + stride, + count, + block); + VRFY((ret>= 0), "H5Sselect_hyperslab(mem_small_ds_sid, or) suceeded"); + + ret = H5Sselect_hyperslab(file_small_ds_sid_0, + H5S_SELECT_OR, + start, + stride, + count, + block); + VRFY((ret>= 0), "H5Sselect_hyperslab(file_small_ds_sid_0, or) suceeded"); + } + + + /* write the initial value of the small data set to file */ + ret = H5Dwrite(small_dataset, dset_type, mem_small_ds_sid, file_small_ds_sid_0, + xfer_plist, small_ds_buf_0); + VRFY((ret >= 0), "H5Dwrite() small_dataset initial write succeeded"); + + + /* sync with the other processes before checking data */ + mrc = MPI_Barrier(MPI_COMM_WORLD); + VRFY((mrc==MPI_SUCCESS), "Sync after small dataset writes"); + + + /* read the small data set back to verify that it contains the + * expected data. Note that each process reads in the entire + * data set and verifies it. + */ + ret = H5Dread(small_dataset, + H5T_NATIVE_UINT32, + full_mem_small_ds_sid, + full_file_small_ds_sid, + xfer_plist, + small_ds_buf_1); + VRFY((ret >= 0), "H5Dread() small_dataset initial read succeeded"); + + + /* verify that the correct data was written to the small data set */ + expected_value = 0; + mis_match = FALSE; + ptr_1 = small_ds_buf_1; + + i = 0; + for ( i = 0; i < (int)small_ds_size; i++ ) { + + if ( *ptr_1 != expected_value ) { + + mis_match = TRUE; + } + ptr_1++; + expected_value++; + } + VRFY( (mis_match == FALSE), "small ds init data good."); + + + + /* setup selections for writing initial data to the large data set */ + + start[0] = mpi_rank; + + ret = H5Sselect_hyperslab(mem_large_ds_sid, + H5S_SELECT_SET, + start, + stride, + count, + block); + VRFY((ret >= 0), "H5Sselect_hyperslab(mem_large_ds_sid, set) suceeded"); + + ret = H5Sselect_hyperslab(file_large_ds_sid_0, + H5S_SELECT_SET, + start, + stride, + count, + block); + VRFY((ret >= 0), "H5Sselect_hyperslab(file_large_ds_sid_0, set) suceeded"); + + /* In passing, setup the process slice data spaces as well */ + + ret = H5Sselect_hyperslab(mem_large_ds_process_slice_sid, + H5S_SELECT_SET, + start, + stride, + count, + block); + VRFY((ret >= 0), + "H5Sselect_hyperslab(mem_large_ds_process_slice_sid, set) suceeded"); + + ret = H5Sselect_hyperslab(file_large_ds_process_slice_sid, + H5S_SELECT_SET, + start, + stride, + count, + block); + VRFY((ret >= 0), + "H5Sselect_hyperslab(file_large_ds_process_slice_sid, set) suceeded"); + + if ( MAINPROCESS ) { /* add an additional slice to the selections */ + + start[0] = mpi_size; + + ret = H5Sselect_hyperslab(mem_large_ds_sid, + H5S_SELECT_OR, + start, + stride, + count, + block); + VRFY((ret>= 0), "H5Sselect_hyperslab(mem_large_ds_sid, or) suceeded"); + + ret = H5Sselect_hyperslab(file_large_ds_sid_0, + H5S_SELECT_OR, + start, + stride, + count, + block); + VRFY((ret>= 0), "H5Sselect_hyperslab(file_large_ds_sid_0, or) suceeded"); + } + + + /* write the initial value of the large data set to file */ + ret = H5Dwrite(large_dataset, dset_type, mem_large_ds_sid, file_large_ds_sid_0, + xfer_plist, large_ds_buf_0); + if ( ret < 0 ) H5Eprint(H5E_DEFAULT, stderr); + VRFY((ret >= 0), "H5Dwrite() large_dataset initial write succeeded"); + + + /* sync with the other processes before checking data */ + mrc = MPI_Barrier(MPI_COMM_WORLD); + VRFY((mrc==MPI_SUCCESS), "Sync after large dataset writes"); + + + /* read the small data set back to verify that it contains the + * expected data. Note that each process reads in the entire + * data set. + */ + ret = H5Dread(large_dataset, + H5T_NATIVE_UINT32, + full_mem_large_ds_sid, + full_file_large_ds_sid, + xfer_plist, + large_ds_buf_1); + VRFY((ret >= 0), "H5Dread() large_dataset initial read succeeded"); + + + /* verify that the correct data was written to the small data set */ + expected_value = 0; + mis_match = FALSE; + ptr_1 = large_ds_buf_1; + + i = 0; + for ( i = 0; i < (int)large_ds_size; i++ ) { + + if ( *ptr_1 != expected_value ) { + + mis_match = TRUE; + } + ptr_1++; + expected_value++; + } + VRFY( (mis_match == FALSE), "large ds init data good."); + + /***********************************/ + /***** INITIALIZATION COMPLETE *****/ + /***********************************/ + + /* first, verify that we can read from disk correctly using selections + * of different rank that H5S_select_shape_same() views as being of the + * same shape. + * + * Start by reading a (small_rank - 1)-D slice from this processes slice + * of the on disk large data set, and verifying that the data read is + * correct. Verify that H5S_select_shape_same() returns true on the + * memory and file selections. + * + * The first step is to set up the needed checker board selection in the + * in memory small small cube + */ + + sel_start[0] = sel_start[1] = sel_start[2] = sel_start[3] = sel_start[4] = 0; + sel_start[small_ds_offset] = mpi_rank; + + checker_board_hyperslab_dr_pio_test__select_checker_board(mpi_rank, + small_ds_slice_sid, + small_rank - 1, + edge_size, + checker_edge_size, + small_rank - 1, + sel_start); + + /* zero out the buffer we will be reading into */ + + ptr_0 = small_ds_slice_buf; + + for ( i = 0; i < (int)small_ds_slice_size; i++ ) { + + *ptr_0 = (uint32_t)0; + ptr_0++; + } + +#if CHECKER_BOARD_HYPERSLAB_DR_PIO_TEST__RUN_TEST__DEBUG + HDfprintf(stdout, "%s:%d: initial small_ds_slice_buf = ", + fcnName, mpi_rank); + ptr_0 = small_ds_slice_buf; + for ( i = 0; i < (int)small_ds_slice_size; i++ ) { + HDfprintf(stdout, "%d ", (int)(*ptr_0)); + ptr_0++; + } + HDfprintf(stdout, "\n"); +#endif /* CHECKER_BOARD_HYPERSLAB_DR_PIO_TEST__RUN_TEST__DEBUG */ + + /* set up start, stride, count, and block -- note that we will + * change start[] so as to read slices of the large cube. + */ + for ( i = 0; i < PAR_SS_DR_MAX_RANK; i++ ) { + + start[i] = 0; + stride[i] = 2 * edge_size; + count[i] = 1; + if ( (PAR_SS_DR_MAX_RANK - i) > (small_rank - 1) ) { + + block[i] = 1; + + } else { + + block[i] = edge_size; + } + } + +#if CHECKER_BOARD_HYPERSLAB_DR_PIO_TEST__RUN_TEST__DEBUG + HDfprintf(stdout, + "%s:%d: reading slice from big ds on disk into small ds slice.\n", + fcnName, mpi_rank); +#endif /* CHECKER_BOARD_HYPERSLAB_DR_PIO_TEST__RUN_TEST__DEBUG */ + /* in serial versions of this test, we loop through all the dimensions + * of the large data set. However, in the parallel version, each + * process only works with that slice of the large cube indicated + * by its rank -- hence we set the most slowly changing index to + * mpi_rank, and don't itterate over it. + */ + + if ( PAR_SS_DR_MAX_RANK - large_rank == 0 ) { + + i = mpi_rank; + + } else { + + i = 0; + } + + /* since large_rank is at most PAR_SS_DR_MAX_RANK, no need to + * loop over it -- either we are setting i to mpi_rank, or + * we are setting it to zero. It will not change during the + * test. + */ + + if ( PAR_SS_DR_MAX_RANK - large_rank == 1 ) { + + j = mpi_rank; + + } else { + + j = 0; + } + + do { + if ( PAR_SS_DR_MAX_RANK - large_rank == 2 ) { + + k = mpi_rank; + + } else { + + k = 0; + } + + do { + /* since small rank >= 2 and large_rank > small_rank, we + * have large_rank >= 3. Since PAR_SS_DR_MAX_RANK == 5 + * (baring major re-orgaization), this gives us: + * + * (PAR_SS_DR_MAX_RANK - large_rank) <= 2 + * + * so no need to repeat the test in the outer loops -- + * just set l = 0. + */ + + l = 0; + do { + /* we know that small_rank - 1 >= 1 and that + * large_rank > small_rank by the assertions at the head + * of this function. Thus no need for another inner loop. + */ + start[0] = i; + start[1] = j; + start[2] = k; + start[3] = l; + start[4] = 0; + + HDassert( ( start[0] == 0 ) || ( 0 < small_ds_offset + 1 ) ); + HDassert( ( start[1] == 0 ) || ( 1 < small_ds_offset + 1 ) ); + HDassert( ( start[2] == 0 ) || ( 2 < small_ds_offset + 1 ) ); + HDassert( ( start[3] == 0 ) || ( 3 < small_ds_offset + 1 ) ); + HDassert( ( start[4] == 0 ) || ( 4 < small_ds_offset + 1 ) ); + + checker_board_hyperslab_dr_pio_test__select_checker_board + ( + mpi_rank, + file_large_ds_sid_0, + large_rank, + edge_size, + checker_edge_size, + small_rank - 1, + start + ); + + /* verify that H5S_select_shape_same() reports the two + * selections as having the same shape. + */ + check = H5S_select_shape_same_test(small_ds_slice_sid, + file_large_ds_sid_0); + VRFY((check == TRUE), "H5S_select_shape_same_test passed"); + + + /* Read selection from disk */ +#if CHECKER_BOARD_HYPERSLAB_DR_PIO_TEST__RUN_TEST__DEBUG + HDfprintf(stdout, "%s:%d: start = %d %d %d %d %d.\n", fcnName, + mpi_rank, start[0], start[1], start[2], start[3], + start[4]); + HDfprintf(stdout, "%s slice/file extent dims = %d/%d.\n", + fcnName, + H5Sget_simple_extent_ndims(small_ds_slice_sid), + H5Sget_simple_extent_ndims(file_large_ds_sid_0)); +#endif /* CHECKER_BOARD_HYPERSLAB_DR_PIO_TEST__RUN_TEST__DEBUG */ + + ret = H5Dread(large_dataset, + H5T_NATIVE_UINT32, + small_ds_slice_sid, + file_large_ds_sid_0, + xfer_plist, + small_ds_slice_buf); + VRFY((ret >= 0), "H5Sread() slice from large ds succeeded."); + +#if CHECKER_BOARD_HYPERSLAB_DR_PIO_TEST__RUN_TEST__DEBUG + HDfprintf(stdout, "%s:%d: H5Dread() returns.\n", + fcnName, mpi_rank); +#endif + + /* verify that expected data is retrieved */ + + expected_value = (uint32_t) + ((i * edge_size * edge_size * edge_size * edge_size) + + (j * edge_size * edge_size * edge_size) + + (k * edge_size * edge_size) + + (l * edge_size)); + + data_ok = checker_board_hyperslab_dr_pio_test__verify_data + ( + small_ds_slice_buf, + mpi_rank, + small_rank - 1, + edge_size, + checker_edge_size, + expected_value, + (hbool_t)TRUE + ); + + VRFY((data_ok == TRUE), + "small slice read from large ds data good."); + l++; + + } while ( ( large_rank > 2 ) && + ( (small_rank - 1) <= 1 ) && + ( l < edge_size ) ); + k++; + } while ( ( large_rank > 3 ) && + ( (small_rank - 1) <= 2 ) && + ( k < edge_size ) ); + j++; + } while ( ( large_rank > 4 ) && + ( (small_rank - 1) <= 3 ) && + ( j < edge_size ) ); + + + /* similarly, read slices of the on disk small data set into slices + * through the in memory large data set, and verify that the correct + * data (and only the correct data) is read. + */ + + sel_start[0] = sel_start[1] = sel_start[2] = sel_start[3] = sel_start[4] = 0; + sel_start[small_ds_offset] = mpi_rank; + + checker_board_hyperslab_dr_pio_test__select_checker_board(mpi_rank, + file_small_ds_sid_0, + small_rank, + edge_size, + checker_edge_size, + small_rank - 1, + sel_start); + +#if CHECKER_BOARD_HYPERSLAB_DR_PIO_TEST__RUN_TEST__DEBUG + HDfprintf(stdout, + "%s reading slices of on disk small data set into slices of big data set.\n", + fcnName); +#endif + + /* zero out the buffer we will be reading into */ + ptr_0 = large_ds_buf_1; + for ( i = 0; i < (int)large_ds_size; i++ ) { + + *ptr_0 = (uint32_t)0; + ptr_0++; + } + + /* set up start, stride, count, and block -- note that we will + * change start[] so as to read the slice of the small data set + * into different slices of the process slice of the large data + * set. + */ + for ( i = 0; i < PAR_SS_DR_MAX_RANK; i++ ) { + + start[i] = 0; + stride[i] = 2 * edge_size; + count[i] = 1; + if ( (PAR_SS_DR_MAX_RANK - i) > (small_rank - 1) ) { + + block[i] = 1; + + } else { + + block[i] = edge_size; + } + } + + + /* in serial versions of this test, we loop through all the dimensions + * of the large data set that don't appear in the small data set. + * + * However, in the parallel version, each process only works with that + * slice of the large (and small) data set indicated by its rank -- hence + * we set the most slowly changing index to mpi_rank, and don't itterate + * over it. + */ + + + if ( PAR_SS_DR_MAX_RANK - large_rank == 0 ) { + + i = mpi_rank; + + } else { + + i = 0; + } + + /* since large_rank is at most PAR_SS_DR_MAX_RANK, no need to + * loop over it -- either we are setting i to mpi_rank, or + * we are setting it to zero. It will not change during the + * test. + */ + + if ( PAR_SS_DR_MAX_RANK - large_rank == 1 ) { + + j = mpi_rank; + + } else { + + j = 0; + } + + do { + if ( PAR_SS_DR_MAX_RANK - large_rank == 2 ) { + + k = mpi_rank; + + } else { + + k = 0; + } + + do { + /* since small rank >= 2 and large_rank > small_rank, we + * have large_rank >= 3. Since PAR_SS_DR_MAX_RANK == 5 + * (baring major re-orgaization), this gives us: + * + * (PAR_SS_DR_MAX_RANK - large_rank) <= 2 + * + * so no need to repeat the test in the outer loops -- + * just set l = 0. + */ + + l = 0; + do { + /* we know that small_rank >= 1 and that large_rank > small_rank + * by the assertions at the head of this function. Thus no + * need for another inner loop. + */ + start[0] = i; + start[1] = j; + start[2] = k; + start[3] = l; + start[4] = 0; + + HDassert( ( start[0] == 0 ) || ( 0 < small_ds_offset + 1 ) ); + HDassert( ( start[1] == 0 ) || ( 1 < small_ds_offset + 1 ) ); + HDassert( ( start[2] == 0 ) || ( 2 < small_ds_offset + 1 ) ); + HDassert( ( start[3] == 0 ) || ( 3 < small_ds_offset + 1 ) ); + HDassert( ( start[4] == 0 ) || ( 4 < small_ds_offset + 1 ) ); + + checker_board_hyperslab_dr_pio_test__select_checker_board + ( + mpi_rank, + mem_large_ds_sid, + large_rank, + edge_size, + checker_edge_size, + small_rank - 1, + start + ); + + + /* verify that H5S_select_shape_same() reports the two + * selections as having the same shape. + */ + check = H5S_select_shape_same_test(file_small_ds_sid_0, + mem_large_ds_sid); + VRFY((check == TRUE), "H5S_select_shape_same_test passed"); + + + /* Read selection from disk */ +#if CHECKER_BOARD_HYPERSLAB_DR_PIO_TEST__RUN_TEST__DEBUG + HDfprintf(stdout, "%s:%d: start = %d %d %d %d %d.\n", + fcnName, mpi_rank, + start[0], start[1], start[2], start[3], start[4]); + HDfprintf(stdout, "%s:%d: mem/file extent dims = %d/%d.\n", + fcnName, mpi_rank, + H5Sget_simple_extent_ndims(large_ds_slice_sid), + H5Sget_simple_extent_ndims(file_small_ds_sid_0)); +#endif + ret = H5Dread(small_dataset, + H5T_NATIVE_UINT32, + mem_large_ds_sid, + file_small_ds_sid_0, + xfer_plist, + large_ds_buf_1); + VRFY((ret >= 0), "H5Sread() slice from small ds succeeded."); + + /* verify that the expected data and only the + * expected data was read. + */ + data_ok = TRUE; + ptr_1 = large_ds_buf_1; + expected_value = mpi_rank * small_ds_slice_size; + start_index = + (i * edge_size * edge_size * edge_size * edge_size) + + (j * edge_size * edge_size * edge_size) + + (k * edge_size * edge_size) + + (l * edge_size); + stop_index = start_index + (int)small_ds_slice_size - 1; + +#if CHECKER_BOARD_HYPERSLAB_DR_PIO_TEST__RUN_TEST__DEBUG + HDfprintf(stdout, "%s:%d: expected_value = %d.\n", + fcnName, mpi_rank, expected_value); + HDfprintf(stdout, "%s:%d: start/stop index = %d/%d.\n", + fcnName, mpi_rank, start_index, stop_index); + n = 0; + for ( m = 0; m < large_ds_size; m ++ ) { + HDfprintf(stdout, "%d ", (int)(*ptr_1)); + ptr_1++; + n++; + if ( n >= edge_size ) { + HDfprintf(stdout, "\n"); + n = 0; + } + } + HDfprintf(stdout, "\n"); + fsync(stdout); + ptr_1 = large_ds_buf_1; +#endif + + HDassert( 0 <= start_index ); + HDassert( start_index < stop_index ); + HDassert( stop_index <= (int)large_ds_size ); + + for ( n = 0; n < (int)start_index; n++ ) { + + if ( *ptr_1 != 0 ) { + + data_ok = FALSE; + } + + /* zero out the value for the next pass */ + *ptr_1 = 0; + + *ptr_1++; + } + + VRFY((data_ok == TRUE), + "slice read from small to large ds data good(1)."); + + data_ok = checker_board_hyperslab_dr_pio_test__verify_data + ( + ptr_1, + mpi_rank, + small_rank - 1, + edge_size, + checker_edge_size, + expected_value, + (hbool_t)TRUE + ); + + VRFY((data_ok == TRUE), + "slice read from small to large ds data good(2)."); + + + ptr_1 = large_ds_buf_1 + stop_index + 1; + for ( n = stop_index + 1; n < large_ds_size; n++ ) { + + if ( *ptr_1 != 0 ) { + + data_ok = FALSE; + } + + /* zero out the value for the next pass */ + *ptr_1 = 0; + + *ptr_1++; + } + + VRFY((data_ok == TRUE), + "slice read from small to large ds data good(3)."); + + l++; + + } while ( ( large_rank > 2 ) && + ( (small_rank - 1) <= 1 ) && + ( l < edge_size ) ); + k++; + } while ( ( large_rank > 3 ) && + ( (small_rank - 1) <= 2 ) && + ( k < edge_size ) ); + j++; + } while ( ( large_rank > 4 ) && + ( (small_rank - 1) <= 3 ) && + ( j < edge_size ) ); + + + /* now we go in the opposite direction, verifying that we can write + * from memory to file using selections of different rank that + * H5S_select_shape_same() views as being of the same shape. + * + * Start by writing small_rank - 1 D slices from the in memory large data + * set to the on disk small dataset. After each write, read the slice of + * the small dataset back from disk, and verify that it contains the + * expected data. Verify that H5S_select_shape_same() returns true on + * the memory and file selections. + */ + + start[0] = mpi_rank; + stride[0] = 2 * (mpi_size + 1); + count[0] = 1; + block[0] = 1; + + for ( i = 1; i < large_rank; i++ ) { + + start[i] = 0; + stride[i] = 2 * edge_size; + count[i] = 1; + block[i] = edge_size; + } + + ret = H5Sselect_hyperslab(file_small_ds_sid_0, + H5S_SELECT_SET, + start, + stride, + count, + block); + VRFY((ret >= 0), "H5Sselect_hyperslab(file_small_ds_sid_0, set) suceeded"); + + ret = H5Sselect_hyperslab(mem_small_ds_sid, + H5S_SELECT_SET, + start, + stride, + count, + block); + VRFY((ret >= 0), "H5Sselect_hyperslab(mem_small_ds_sid, set) suceeded"); + + + sel_start[0] = sel_start[1] = sel_start[2] = sel_start[3] = sel_start[4] = 0; + sel_start[small_ds_offset] = mpi_rank; + + checker_board_hyperslab_dr_pio_test__select_checker_board(mpi_rank, + file_small_ds_sid_1, + small_rank, + edge_size, + checker_edge_size, + small_rank - 1, + sel_start); + + + /* set up start, stride, count, and block -- note that we will + * change start[] so as to read slices of the large cube. + */ + for ( i = 0; i < PAR_SS_DR_MAX_RANK; i++ ) { + + start[i] = 0; + stride[i] = 2 * edge_size; + count[i] = 1; + if ( (PAR_SS_DR_MAX_RANK - i) > (small_rank - 1) ) { + + block[i] = 1; + + } else { + + block[i] = edge_size; + } + } + + /* zero out the in memory small ds */ + ptr_1 = small_ds_buf_1; + for ( n = 0; n < (int)small_ds_size; n++ ) { + + *ptr_1 = 0; + ptr_1++; + } + + +#if CHECKER_BOARD_HYPERSLAB_DR_PIO_TEST__RUN_TEST__DEBUG + HDfprintf(stdout, + "%s writing checker boards selections of slices from big ds to slices of small ds on disk.\n", + fcnName); +#endif + + /* in serial versions of this test, we loop through all the dimensions + * of the large data set that don't appear in the small data set. + * + * However, in the parallel version, each process only works with that + * slice of the large (and small) data set indicated by its rank -- hence + * we set the most slowly changing index to mpi_rank, and don't itterate + * over it. + */ + + + if ( PAR_SS_DR_MAX_RANK - large_rank == 0 ) { + + i = mpi_rank; + + } else { + + i = 0; + } + + /* since large_rank is at most PAR_SS_DR_MAX_RANK, no need to + * loop over it -- either we are setting i to mpi_rank, or + * we are setting it to zero. It will not change during the + * test. + */ + + if ( PAR_SS_DR_MAX_RANK - large_rank == 1 ) { + + j = mpi_rank; + + } else { + + j = 0; + } + + j = 0; + do { + if ( PAR_SS_DR_MAX_RANK - large_rank == 2 ) { + + k = mpi_rank; + + } else { + + k = 0; + } + + do { + /* since small rank >= 2 and large_rank > small_rank, we + * have large_rank >= 3. Since PAR_SS_DR_MAX_RANK == 5 + * (baring major re-orgaization), this gives us: + * + * (PAR_SS_DR_MAX_RANK - large_rank) <= 2 + * + * so no need to repeat the test in the outer loops -- + * just set l = 0. + */ + + l = 0; + do { + /* we know that small_rank >= 1 and that large_rank > small_rank + * by the assertions at the head of this function. Thus no + * need for another inner loop. + */ + + /* zero out this rank's slice of the on disk small data set */ + ret = H5Dwrite(small_dataset, + H5T_NATIVE_UINT32, + mem_small_ds_sid, + file_small_ds_sid_0, + xfer_plist, + small_ds_buf_2); + VRFY((ret >= 0), "H5Dwrite() zero slice to small ds succeeded."); + + /* select the portion of the in memory large cube from which we + * are going to write data. + */ + start[0] = i; + start[1] = j; + start[2] = k; + start[3] = l; + start[4] = 0; + + HDassert( ( start[0] == 0 ) || ( 0 < small_ds_offset + 1 ) ); + HDassert( ( start[1] == 0 ) || ( 1 < small_ds_offset + 1 ) ); + HDassert( ( start[2] == 0 ) || ( 2 < small_ds_offset + 1 ) ); + HDassert( ( start[3] == 0 ) || ( 3 < small_ds_offset + 1 ) ); + HDassert( ( start[4] == 0 ) || ( 4 < small_ds_offset + 1 ) ); + + checker_board_hyperslab_dr_pio_test__select_checker_board + ( + mpi_rank, + mem_large_ds_sid, + large_rank, + edge_size, + checker_edge_size, + small_rank - 1, + start + ); + + + /* verify that H5S_select_shape_same() reports the in + * memory checkerboard selection of the slice through the + * large dataset and the checkerboard selection of the process + * slice of the small data set as having the same shape. + */ + check = H5S_select_shape_same_test(file_small_ds_sid_1, + mem_large_ds_sid); + VRFY((check == TRUE), "H5S_select_shape_same_test passed."); + + + /* write the checker board selection of the slice from the in + * memory large data set to the slice of the on disk small + * dataset. + */ +#if CHECKER_BOARD_HYPERSLAB_DR_PIO_TEST__RUN_TEST__DEBUG + HDfprintf(stdout, "%s:%d: start = %d %d %d %d %d.\n", + fcnName, mpi_rank, + start[0], start[1], start[2], start[3], start[4]); + HDfprintf(stdout, "%s:%d: mem/file extent dims = %d/%d.\n", + fcnName, mpi_rank, + H5Sget_simple_extent_ndims(mem_large_ds_sid), + H5Sget_simple_extent_ndims(file_small_ds_sid_1)); +#endif + ret = H5Dwrite(small_dataset, + H5T_NATIVE_UINT32, + mem_large_ds_sid, + file_small_ds_sid_1, + xfer_plist, + large_ds_buf_0); + VRFY((ret >= 0), "H5Dwrite() slice to large ds succeeded."); + + + /* read the on disk process slice of the small dataset into memory */ + ret = H5Dread(small_dataset, + H5T_NATIVE_UINT32, + mem_small_ds_sid, + file_small_ds_sid_0, + xfer_plist, + small_ds_buf_1); + VRFY((ret >= 0), "H5Dread() slice from small ds succeeded."); + + + /* verify that expected data is retrieved */ + + mis_match = FALSE; + ptr_1 = small_ds_buf_1; + + expected_value = + (i * edge_size * edge_size * edge_size * edge_size) + + (j * edge_size * edge_size * edge_size) + + (k * edge_size * edge_size) + + (l * edge_size); + + start_index = mpi_rank * small_ds_slice_size; + stop_index = start_index + small_ds_slice_size - 1; + + HDassert( 0 <= start_index ); + HDassert( start_index < stop_index ); + HDassert( stop_index <= (int)small_ds_size ); + + data_ok = TRUE; + + for ( n = 0; n < start_index; n++ ) { + + if ( *(ptr_1 + n) != 0 ) { + + data_ok = FALSE; + *(ptr_1 + n) = 0; + } + } + + data_ok &= checker_board_hyperslab_dr_pio_test__verify_data + ( + ptr_1 + start_index, + mpi_rank, + small_rank - 1, + edge_size, + checker_edge_size, + expected_value, + (hbool_t)TRUE + ); + + + for ( n = stop_index; n < small_ds_size; n++ ) { + + if ( *(ptr_1 + n) != 0 ) { + + data_ok = FALSE; + *(ptr_1 + n) = 0; + } + } + + VRFY((data_ok == TRUE), + "large slice write slice to small slice data good."); + + l++; + + } while ( ( large_rank > 2 ) && + ( (small_rank - 1) <= 1 ) && + ( l < edge_size ) ); + k++; + } while ( ( large_rank > 3 ) && + ( (small_rank - 1) <= 2 ) && + ( k < edge_size ) ); + j++; + } while ( ( large_rank > 4 ) && + ( (small_rank - 1) <= 3 ) && + ( j < edge_size ) ); + + + /* Now write the contents of the process's slice of the in memory + * small data set to slices of the on disk large data set. After + * each write, read the process's slice of the large data set back + * into memory, and verify that it contains the expected data. + * Verify that H5S_select_shape_same() returns true on the memory + * and file selections. + */ + + start[0] = mpi_rank; + stride[0] = 2 * (mpi_size + 1); + count[0] = 1; + block[0] = 1; + + for ( i = 1; i < large_rank; i++ ) { + + start[i] = 0; + stride[i] = 2 * edge_size; + count[i] = 1; + block[i] = edge_size; + } + + ret = H5Sselect_hyperslab(file_large_ds_sid_0, + H5S_SELECT_SET, + start, + stride, + count, + block); + VRFY((ret >= 0), "H5Sselect_hyperslab(file_large_ds_sid_0, set) suceeded"); + + ret = H5Sselect_hyperslab(mem_large_ds_sid, + H5S_SELECT_SET, + start, + stride, + count, + block); + VRFY((ret >= 0), "H5Sselect_hyperslab(mem_small_ds_sid, set) suceeded"); + + /* setup a checkerboard selection of the slice of the in memory small + * data set associated with the process's mpi rank. + */ + + sel_start[0] = sel_start[1] = sel_start[2] = sel_start[3] = sel_start[4] = 0; + sel_start[small_ds_offset] = mpi_rank; + + checker_board_hyperslab_dr_pio_test__select_checker_board(mpi_rank, + mem_small_ds_sid, + small_rank, + edge_size, + checker_edge_size, + small_rank - 1, + sel_start); + + /* set up start, stride, count, and block -- note that we will + * change start[] so as to write checkerboard selections of slices + * of the small data set to slices of the large data set. + */ + for ( i = 0; i < PAR_SS_DR_MAX_RANK; i++ ) { + + start[i] = 0; + stride[i] = 2 * edge_size; + count[i] = 1; + if ( (PAR_SS_DR_MAX_RANK - i) > (small_rank - 1) ) { + + block[i] = 1; + + } else { + + block[i] = edge_size; + } + } + + /* zero out the in memory large ds */ + ptr_1 = large_ds_buf_1; + for ( n = 0; n < (int)large_ds_size; n++ ) { + + *ptr_1 = 0; + ptr_1++; + } + +#if CONTIG_HYPERSLAB_DR_PIO_TEST__RUN_TEST__DEBUG + HDfprintf(stdout, + "%s writing process checkerboard selections of slices of small ds to process slices of large ds on disk.\n", + fcnName); +#endif + + if ( PAR_SS_DR_MAX_RANK - large_rank == 0 ) { + + i = mpi_rank; + + } else { + + i = 0; + } + + /* since large_rank is at most PAR_SS_DR_MAX_RANK, no need to + * loop over it -- either we are setting i to mpi_rank, or + * we are setting it to zero. It will not change during the + * test. + */ + + if ( PAR_SS_DR_MAX_RANK - large_rank == 1 ) { + + j = mpi_rank; + + } else { + + j = 0; + } + + do { + if ( PAR_SS_DR_MAX_RANK - large_rank == 2 ) { + + k = mpi_rank; + + } else { + + k = 0; + } + + do { + /* since small rank >= 2 and large_rank > small_rank, we + * have large_rank >= 3. Since PAR_SS_DR_MAX_RANK == 5 + * (baring major re-orgaization), this gives us: + * + * (PAR_SS_DR_MAX_RANK - large_rank) <= 2 + * + * so no need to repeat the test in the outer loops -- + * just set l = 0. + */ + + l = 0; + do { + /* we know that small_rank >= 1 and that large_rank > small_rank + * by the assertions at the head of this function. Thus no + * need for another inner loop. + */ + + /* Zero out this processes slice of the on disk large data set. + * Note that this will leave one slice with its original data + * as there is one more slice than processes. + */ + ret = H5Dwrite(large_dataset, + H5T_NATIVE_UINT32, + mem_large_ds_sid, + file_large_ds_sid_0, + xfer_plist, + large_ds_buf_2); + VRFY((ret != FAIL), "H5Dwrite() to zero large ds suceeded"); + + + /* select the portion of the in memory large cube to which we + * are going to write data. + */ + start[0] = i; + start[1] = j; + start[2] = k; + start[3] = l; + start[4] = 0; + + HDassert( ( start[0] == 0 ) || ( 0 < small_ds_offset + 1 ) ); + HDassert( ( start[1] == 0 ) || ( 1 < small_ds_offset + 1 ) ); + HDassert( ( start[2] == 0 ) || ( 2 < small_ds_offset + 1 ) ); + HDassert( ( start[3] == 0 ) || ( 3 < small_ds_offset + 1 ) ); + HDassert( ( start[4] == 0 ) || ( 4 < small_ds_offset + 1 ) ); + + checker_board_hyperslab_dr_pio_test__select_checker_board + ( + mpi_rank, + file_large_ds_sid_1, + large_rank, + edge_size, + checker_edge_size, + small_rank - 1, + start + ); + + + /* verify that H5S_select_shape_same() reports the in + * memory small data set slice selection and the + * on disk slice through the large data set selection + * as having the same shape. + */ + check = H5S_select_shape_same_test(mem_small_ds_sid, + file_large_ds_sid_1); + VRFY((check == TRUE), "H5S_select_shape_same_test passed"); + + + /* write the small data set slice from memory to the + * target slice of the disk data set + */ +#if CHECKER_BOARD_HYPERSLAB_DR_PIO_TEST__RUN_TEST__DEBUG + HDfprintf(stdout, "%s:%d: start = %d %d %d %d %d.\n", + fcnName, mpi_rank, + start[0], start[1], start[2], start[3], start[4]); + HDfprintf(stdout, "%s:%d: mem/file extent dims = %d/%d.\n", + fcnName, mpi_rank, + H5Sget_simple_extent_ndims(mem_small_ds_sid), + H5Sget_simple_extent_ndims(file_large_ds_sid_1)); +#endif + ret = H5Dwrite(large_dataset, + H5T_NATIVE_UINT32, + mem_small_ds_sid, + file_large_ds_sid_1, + xfer_plist, + small_ds_buf_0); + VRFY((ret != FAIL), + "H5Dwrite of small ds slice to large ds succeeded"); + + + /* read this processes slice on the on disk large + * data set into memory. + */ + + ret = H5Dread(large_dataset, + H5T_NATIVE_UINT32, + mem_large_ds_sid, + file_large_ds_sid_0, + xfer_plist, + large_ds_buf_1); + VRFY((ret != FAIL), + "H5Dread() of process slice of large ds succeeded"); + + + /* verify that the expected data and only the + * expected data was read. + */ + ptr_1 = large_ds_buf_1; + expected_value = (uint32_t)(mpi_rank) * small_ds_slice_size; + + + start_index = (i * edge_size * edge_size * edge_size * edge_size) + + (j * edge_size * edge_size * edge_size) + + (k * edge_size * edge_size) + + (l * edge_size); + stop_index = start_index + (int)small_ds_slice_size - 1; + + HDassert( 0 <= start_index ); + HDassert( start_index < stop_index ); + HDassert( stop_index < (int)large_ds_size ); + + + mis_match = FALSE; + + data_ok = TRUE; + + for ( n = 0; n < start_index; n++ ) { + + if ( *(ptr_1 + n) != 0 ) { + + data_ok = FALSE; + *(ptr_1 + n) = 0; + } + } + + data_ok &= checker_board_hyperslab_dr_pio_test__verify_data + ( + ptr_1 + start_index, + mpi_rank, + small_rank - 1, + edge_size, + checker_edge_size, + expected_value, + (hbool_t)TRUE + ); + + + for ( n = stop_index; n < small_ds_size; n++ ) { + + if ( *(ptr_1 + n) != 0 ) { + + data_ok = FALSE; + *(ptr_1 + n) = 0; + } + } + + VRFY((data_ok == TRUE), + "small ds cb slice write to large ds slice data good."); + + l++; + + } while ( ( large_rank > 2 ) && + ( (small_rank - 1) <= 1 ) && + ( l < edge_size ) ); + k++; + } while ( ( large_rank > 3 ) && + ( (small_rank - 1) <= 2 ) && + ( k < edge_size ) ); + j++; + } while ( ( large_rank > 4 ) && + ( (small_rank - 1) <= 3 ) && + ( j < edge_size ) ); + + + /* Close dataspaces */ + ret = H5Sclose(full_mem_small_ds_sid); + VRFY((ret != FAIL), "H5Sclose(full_mem_small_ds_sid) succeeded"); + + ret = H5Sclose(full_file_small_ds_sid); + VRFY((ret != FAIL), "H5Sclose(full_file_small_ds_sid) succeeded"); + + ret = H5Sclose(mem_small_ds_sid); + VRFY((ret != FAIL), "H5Sclose(mem_small_ds_sid) succeeded"); + + ret = H5Sclose(file_small_ds_sid_0); + VRFY((ret != FAIL), "H5Sclose(file_small_ds_sid_0) succeeded"); + + ret = H5Sclose(file_small_ds_sid_1); + VRFY((ret != FAIL), "H5Sclose(file_small_ds_sid_1) succeeded"); + + ret = H5Sclose(small_ds_slice_sid); + VRFY((ret != FAIL), "H5Sclose(small_ds_slice_sid) succeeded"); + + ret = H5Sclose(full_mem_large_ds_sid); + VRFY((ret != FAIL), "H5Sclose(full_mem_large_ds_sid) succeeded"); + + ret = H5Sclose(full_file_large_ds_sid); + VRFY((ret != FAIL), "H5Sclose(full_file_large_ds_sid) succeeded"); + + ret = H5Sclose(mem_large_ds_sid); + VRFY((ret != FAIL), "H5Sclose(mem_large_ds_sid) succeeded"); + + ret = H5Sclose(file_large_ds_sid_0); + VRFY((ret != FAIL), "H5Sclose(mem_large_ds_sid) succeeded"); + + ret = H5Sclose(file_large_ds_sid_1); + VRFY((ret != FAIL), "H5Sclose(mem_large_ds_sid) succeeded"); + + ret = H5Sclose(mem_large_ds_process_slice_sid); + VRFY((ret != FAIL), "H5Sclose(mem_large_ds_process_slice_sid) succeeded"); + + ret = H5Sclose(file_large_ds_process_slice_sid); + VRFY((ret != FAIL), "H5Sclose(file_large_ds_process_slice_sid) succeeded"); + + ret = H5Sclose(large_ds_slice_sid); + VRFY((ret != FAIL), "H5Sclose(large_ds_slice_sid) succeeded"); + + + /* Close Datasets */ + ret = H5Dclose(small_dataset); + VRFY((ret != FAIL), "H5Dclose(small_dataset) succeeded"); + + ret = H5Dclose(large_dataset); + VRFY((ret != FAIL), "H5Dclose(large_dataset) succeeded"); + + + /* close the file collectively */ + MESG("about to close file."); + ret = H5Fclose(fid); + VRFY((ret != FAIL), "file close succeeded"); + + /* Free memory buffers */ + if ( small_ds_buf_0 != NULL ) HDfree(small_ds_buf_0); + if ( small_ds_buf_1 != NULL ) HDfree(small_ds_buf_1); + if ( small_ds_buf_2 != NULL ) HDfree(small_ds_buf_2); + if ( small_ds_slice_buf != NULL ) HDfree(small_ds_slice_buf); + + if ( large_ds_buf_0 != NULL ) HDfree(large_ds_buf_0); + if ( large_ds_buf_1 != NULL ) HDfree(large_ds_buf_1); + if ( large_ds_buf_2 != NULL ) HDfree(large_ds_buf_2); + if ( large_ds_slice_buf != NULL ) HDfree(large_ds_slice_buf); + + return; + +} /* contig_hyperslab_dr_pio_test__run_test() */ + + +/*------------------------------------------------------------------------- + * Function: checker_board_hyperslab_dr_pio_test() + * + * Purpose: Test I/O to/from hyperslab selections of different rank in + * the parallel case. + * + * Return: void + * + * Programmer: JRM -- 9/18/09 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +void +checker_board_hyperslab_dr_pio_test(void) +{ + const char *fcnName = "checker_board_hyperslab_dr_pio_test()"; + int test_num = 0; + int edge_size = 10; + int checker_edge_size = 3; + int chunk_edge_size = 0; + int small_rank = 3; + int large_rank = 4; + int use_collective_io = 1; + hid_t dset_type = H5T_STD_U32LE; +#if 0 + int DebugWait = 1; + + while (DebugWait) ; +#endif + + for ( large_rank = 3; large_rank <= PAR_SS_DR_MAX_RANK; large_rank++ ) { + + for ( small_rank = 2; small_rank < large_rank; small_rank++ ) { + + for ( use_collective_io = 0; + use_collective_io <= 1; + use_collective_io++ ) { + + chunk_edge_size = 0; + checker_board_hyperslab_dr_pio_test__run_test(test_num, + edge_size, + checker_edge_size, + chunk_edge_size, + small_rank, + large_rank, + (hbool_t)use_collective_io, + dset_type); + test_num++; + + chunk_edge_size = 5; + checker_board_hyperslab_dr_pio_test__run_test(test_num, + edge_size, + checker_edge_size, + chunk_edge_size, + small_rank, + large_rank, + (hbool_t)use_collective_io, + dset_type); + test_num++; + + } + } + } + + return; + +} /* checker_board_hyperslab_dr_pio_test() */ + diff --git a/testpar/t_span_tree.c b/testpar/t_span_tree.c index 667872c..5425377 100644 --- a/testpar/t_span_tree.c +++ b/testpar/t_span_tree.c @@ -934,3 +934,1930 @@ coll_read_test(int chunk_factor) return ; } + +/**************************************************************** +** +** lower_dim_size_comp_test__select_checker_board(): +** +** Given a data space of tgt_rank, and dimensions: +** +** (mpi_size + 1), edge_size, ... , edge_size +** +** edge_size, and a checker_edge_size, select a checker +** board selection of a sel_rank (sel_rank < tgt_rank) +** dimensional slice through the data space parallel to the +** sel_rank fastest changing indicies, with origin (in the +** higher indicies) as indicated by the start array. +** +** Note that this function, is hard coded to presume a +** maximum data space rank of 5. +** +** While this maximum is declared as a constant, increasing +** it will require extensive coding in addition to changing +** the value of the constant. +** +** JRM -- 11/11/09 +** +****************************************************************/ + +#define LDSCT_DS_RANK 5 +#define LOWER_DIM_SIZE_COMP_TEST_DEBUG_TARGET_RANK 0 + +#define LOWER_DIM_SIZE_COMP_TEST__SELECT_CHECKER_BOARD__DEBUG 0 + +static void +lower_dim_size_comp_test__select_checker_board( + const int mpi_rank, + const hid_t tgt_sid, + const int tgt_rank, + const hsize_t dims[LDSCT_DS_RANK], + const int checker_edge_size, + const int sel_rank, + hsize_t sel_start[]) +{ +#if LOWER_DIM_SIZE_COMP_TEST__SELECT_CHECKER_BOARD__DEBUG + const char * fcnName = + "lower_dim_size_comp_test__select_checker_board():"; +#endif + hbool_t first_selection = TRUE; + int i, j, k, l, m; + int ds_offset; + int sel_offset; + const int test_max_rank = LDSCT_DS_RANK; /* must update code if */ + /* this changes */ + hsize_t base_count; + hsize_t offset_count; + hsize_t start[LDSCT_DS_RANK]; + hsize_t stride[LDSCT_DS_RANK]; + hsize_t count[LDSCT_DS_RANK]; + hsize_t block[LDSCT_DS_RANK]; + herr_t ret; /* Generic return value */ + +#if LOWER_DIM_SIZE_COMP_TEST__SELECT_CHECKER_BOARD__DEBUG + if ( mpi_rank == LOWER_DIM_SIZE_COMP_TEST_DEBUG_TARGET_RANK ) { + HDfprintf(stdout, + "%s:%d: dims/checker_edge_size = %d %d %d %d %d / %d\n", + fcnName, mpi_rank, (int)dims[0], (int)dims[1], (int)dims[2], + (int)dims[3], (int)dims[4], checker_edge_size); + } +#endif /* LOWER_DIM_SIZE_COMP_TEST__SELECT_CHECKER_BOARD__DEBUG */ + + HDassert( 0 < checker_edge_size ); + HDassert( 0 < sel_rank ); + HDassert( sel_rank <= tgt_rank ); + HDassert( tgt_rank <= test_max_rank ); + HDassert( test_max_rank <= LDSCT_DS_RANK ); + + sel_offset = test_max_rank - sel_rank; + HDassert( sel_offset >= 0 ); + + ds_offset = test_max_rank - tgt_rank; + HDassert( ds_offset >= 0 ); + HDassert( ds_offset <= sel_offset ); + + HDassert( (hsize_t)checker_edge_size <= dims[sel_offset] ); + HDassert( dims[sel_offset] == 10 ); + +#if LOWER_DIM_SIZE_COMP_TEST__SELECT_CHECKER_BOARD__DEBUG + if ( mpi_rank == LOWER_DIM_SIZE_COMP_TEST_DEBUG_TARGET_RANK ) { + HDfprintf(stdout, "%s:%d: sel_rank/sel_offset = %d/%d.\n", + fcnName, mpi_rank, sel_rank, sel_offset); + HDfprintf(stdout, "%s:%d: tgt_rank/ds_offset = %d/%d.\n", + fcnName, mpi_rank, tgt_rank, ds_offset); + } +#endif /* LOWER_DIM_SIZE_COMP_TEST__SELECT_CHECKER_BOARD__DEBUG */ + + /* First, compute the base count (which assumes start == 0 + * for the associated offset) and offset_count (which + * assumes start == checker_edge_size for the associated + * offset). + * + * Note that the following computation depends on the C99 + * requirement that integer division discard any fraction + * (truncation towards zero) to function correctly. As we + * now require C99, this shouldn't be a problem, but noting + * it may save us some pain if we are ever obliged to support + * pre-C99 compilers again. + */ + + base_count = dims[sel_offset] / (checker_edge_size * 2); + + if ( (dims[sel_rank] % (checker_edge_size * 2)) > 0 ) { + + base_count++; + } + + offset_count = + (hsize_t)((dims[sel_offset] - (hsize_t)checker_edge_size) / + ((hsize_t)(checker_edge_size * 2))); + + if ( ((dims[sel_rank] - (hsize_t)checker_edge_size) % + ((hsize_t)(checker_edge_size * 2))) > 0 ) { + + offset_count++; + } + +#if LOWER_DIM_SIZE_COMP_TEST__SELECT_CHECKER_BOARD__DEBUG + if ( mpi_rank == LOWER_DIM_SIZE_COMP_TEST_DEBUG_TARGET_RANK ) { + HDfprintf(stdout, "%s:%d: base_count/offset_count = %d/%d.\n", + fcnName, mpi_rank, base_count, offset_count); + } +#endif /* LOWER_DIM_SIZE_COMP_TEST__SELECT_CHECKER_BOARD__DEBUG */ + + /* Now set up the stride and block arrays, and portions of the start + * and count arrays that will not be altered during the selection of + * the checker board. + */ + i = 0; + while ( i < ds_offset ) { + + /* these values should never be used */ + start[i] = 0; + stride[i] = 0; + count[i] = 0; + block[i] = 0; + + i++; + } + + while ( i < sel_offset ) { + + start[i] = sel_start[i]; + stride[i] = 2 * dims[i]; + count[i] = 1; + block[i] = 1; + + i++; + } + + while ( i < test_max_rank ) { + + stride[i] = (hsize_t)(2 * checker_edge_size); + block[i] = (hsize_t)checker_edge_size; + + i++; + } + + i = 0; + do { + if ( 0 >= sel_offset ) { + + if ( i == 0 ) { + + start[0] = 0; + count[0] = base_count; + + } else { + + start[0] = (hsize_t)checker_edge_size; + count[0] = offset_count; + + } + } + + j = 0; + do { + if ( 1 >= sel_offset ) { + + if ( j == 0 ) { + + start[1] = 0; + count[1] = base_count; + + } else { + + start[1] = (hsize_t)checker_edge_size; + count[1] = offset_count; + + } + } + + k = 0; + do { + if ( 2 >= sel_offset ) { + + if ( k == 0 ) { + + start[2] = 0; + count[2] = base_count; + + } else { + + start[2] = (hsize_t)checker_edge_size; + count[2] = offset_count; + + } + } + + l = 0; + do { + if ( 3 >= sel_offset ) { + + if ( l == 0 ) { + + start[3] = 0; + count[3] = base_count; + + } else { + + start[3] = (hsize_t)checker_edge_size; + count[3] = offset_count; + + } + } + + m = 0; + do { + if ( 4 >= sel_offset ) { + + if ( m == 0 ) { + + start[4] = 0; + count[4] = base_count; + + } else { + + start[4] = (hsize_t)checker_edge_size; + count[4] = offset_count; + + } + } + + if ( ((i + j + k + l + m) % 2) == 0 ) { + +#if LOWER_DIM_SIZE_COMP_TEST__SELECT_CHECKER_BOARD__DEBUG + if ( mpi_rank == + LOWER_DIM_SIZE_COMP_TEST_DEBUG_TARGET_RANK ) { + + HDfprintf(stdout, + "%s%d: *** first_selection = %d ***\n", + fcnName, mpi_rank, (int)first_selection); + HDfprintf(stdout, + "%s:%d: i/j/k/l/m = %d/%d/%d/%d/%d\n", + fcnName, mpi_rank, i, j, k, l, m); + HDfprintf(stdout, + "%s:%d: start = %d %d %d %d %d.\n", + fcnName, mpi_rank, + (int)start[0], (int)start[1], + (int)start[2], (int)start[3], + (int)start[4]); + HDfprintf(stdout, + "%s:%d: stride = %d %d %d %d %d.\n", + fcnName, mpi_rank, + (int)stride[0], (int)stride[1], + (int)stride[2], (int)stride[3], + (int)stride[4]); + HDfprintf(stdout, + "%s:%d: count = %d %d %d %d %d.\n", + fcnName, mpi_rank, + (int)count[0], (int)count[1], + (int)count[2], (int)count[3], + (int)count[4]); + HDfprintf(stdout, + "%s:%d: block = %d %d %d %d %d.\n", + fcnName, mpi_rank, + (int)block[0], (int)block[1], + (int)block[2], (int)block[3], + (int)block[4]); + HDfprintf(stdout, + "%s:%d: n-cube extent dims = %d.\n", + fcnName, mpi_rank, + H5Sget_simple_extent_ndims(tgt_sid)); + HDfprintf(stdout, + "%s:%d: selection rank = %d.\n", + fcnName, mpi_rank, sel_rank); + } +#endif + + if ( first_selection ) { + + first_selection = FALSE; + + ret = H5Sselect_hyperslab + ( + tgt_sid, + H5S_SELECT_SET, + &(start[ds_offset]), + &(stride[ds_offset]), + &(count[ds_offset]), + &(block[ds_offset]) + ); + + VRFY((ret != FAIL), "H5Sselect_hyperslab(SET) succeeded"); + + } else { + + ret = H5Sselect_hyperslab + ( + tgt_sid, + H5S_SELECT_OR, + &(start[ds_offset]), + &(stride[ds_offset]), + &(count[ds_offset]), + &(block[ds_offset]) + ); + + VRFY((ret != FAIL), "H5Sselect_hyperslab(OR) succeeded"); + + } + } + + m++; + + } while ( ( m <= 1 ) && + ( 4 >= sel_offset ) ); + + l++; + + } while ( ( l <= 1 ) && + ( 3 >= sel_offset ) ); + + k++; + + } while ( ( k <= 1 ) && + ( 2 >= sel_offset ) ); + + j++; + + } while ( ( j <= 1 ) && + ( 1 >= sel_offset ) ); + + + i++; + + } while ( ( i <= 1 ) && + ( 0 >= sel_offset ) ); + +#if LOWER_DIM_SIZE_COMP_TEST__SELECT_CHECKER_BOARD__DEBUG + if ( mpi_rank == LOWER_DIM_SIZE_COMP_TEST_DEBUG_TARGET_RANK ) { + HDfprintf(stdout, "%s%d: H5Sget_select_npoints(tgt_sid) = %d.\n", + fcnName, mpi_rank, (int)H5Sget_select_npoints(tgt_sid)); + } +#endif /* LOWER_DIM_SIZE_COMP_TEST__SELECT_CHECKER_BOARD__DEBUG */ + + /* Clip the selection back to the data space proper. */ + + for ( i = 0; i < test_max_rank; i++ ) { + + start[i] = 0; + stride[i] = dims[i]; + count[i] = 1; + block[i] = dims[i]; + } + + ret = H5Sselect_hyperslab(tgt_sid, H5S_SELECT_AND, + start, stride, count, block); + + VRFY((ret != FAIL), "H5Sselect_hyperslab(AND) succeeded"); + +#if LOWER_DIM_SIZE_COMP_TEST__SELECT_CHECKER_BOARD__DEBUG + if ( mpi_rank == LOWER_DIM_SIZE_COMP_TEST_DEBUG_TARGET_RANK ) { + HDfprintf(stdout, "%s%d: H5Sget_select_npoints(tgt_sid) = %d.\n", + fcnName, mpi_rank, (int)H5Sget_select_npoints(tgt_sid)); + HDfprintf(stdout, "%s%d: done.\n", fcnName, mpi_rank); + } +#endif /* LOWER_DIM_SIZE_COMP_TEST__SELECT_CHECKER_BOARD__DEBUG */ + + return; + +} /* lower_dim_size_comp_test__select_checker_board() */ + + +/**************************************************************** +** +** lower_dim_size_comp_test__verify_data(): +** +** Examine the supplied buffer to see if it contains the +** expected data. Return TRUE if it does, and FALSE +** otherwise. +** +** The supplied buffer is presumed to this process's slice +** of the target data set. Each such slice will be an +** n-cube of rank (rank -1) and the supplied edge_size with +** origin (mpi_rank, 0, ... , 0) in the target data set. +** +** Further, the buffer is presumed to be the result of reading +** or writing a checker board selection of an m (1 <= m < +** rank) dimensional slice through this processes slice +** of the target data set. Also, this slice must be parallel +** to the fastest changing indicies. +** +** It is further presumed that the buffer was zeroed before +** the read/write, and that the full target data set (i.e. +** the buffer/data set for all processes) was initialized +** with the natural numbers listed in order from the origin +** along the fastest changing axis. +** +** Thus for a 20x10x10 dataset, the value stored in location +** (x, y, z) (assuming that z is the fastest changing index +** and x the slowest) is assumed to be: +** +** (10 * 10 * x) + (10 * y) + z +** +** Further, supposing that this is process 10, this process's +** slice of the dataset would be a 10 x 10 2-cube with origin +** (10, 0, 0) in the data set, and would be initialize (prior +** to the checkerboard selection) as follows: +** +** 1000, 1001, 1002, ... 1008, 1009 +** 1010, 1011, 1012, ... 1018, 1019 +** . . . . . +** . . . . . +** . . . . . +** 1090, 1091, 1092, ... 1098, 1099 +** +** In the case of a read from the processors slice of another +** data set of different rank, the values expected will have +** to be adjusted accordingly. This is done via the +** first_expected_val parameter. +** +** Finally, the function presumes that the first element +** of the buffer resides either at the origin of either +** a selected or an unselected checker. (Translation: +** if partial checkers appear in the buffer, they will +** intersect the edges of the n-cube oposite the origin.) +** +****************************************************************/ + +#define LOWER_DIM_SIZE_COMP_TEST__VERIFY_DATA__DEBUG 0 + +static hbool_t +lower_dim_size_comp_test__verify_data(uint32_t * buf_ptr, +#if LOWER_DIM_SIZE_COMP_TEST__VERIFY_DATA__DEBUG + const int mpi_rank, +#endif /* LOWER_DIM_SIZE_COMP_TEST__VERIFY_DATA__DEBUG */ + const int rank, + const int edge_size, + const int checker_edge_size, + uint32_t first_expected_val, + hbool_t buf_starts_in_checker) +{ +#if LOWER_DIM_SIZE_COMP_TEST__VERIFY_DATA__DEBUG + const char * fcnName = + "lower_dim_size_comp_test__verify_data():"; +#endif + hbool_t good_data = TRUE; + hbool_t in_checker; + hbool_t start_in_checker[5]; + uint32_t expected_value; + uint32_t * val_ptr; + int i, j, k, l, m; /* to track position in n-cube */ + int v, w, x, y, z; /* to track position in checker */ + const int test_max_rank = 5; /* code changes needed if this is increased */ + + HDassert( buf_ptr != NULL ); + HDassert( 0 < rank ); + HDassert( rank <= test_max_rank ); + HDassert( edge_size >= 6 ); + HDassert( 0 < checker_edge_size ); + HDassert( checker_edge_size <= edge_size ); + HDassert( test_max_rank <= LDSCT_DS_RANK ); + +#if LOWER_DIM_SIZE_COMP_TEST__VERIFY_DATA__DEBUG + if ( mpi_rank == LOWER_DIM_SIZE_COMP_TEST_DEBUG_TARGET_RANK ) { + HDfprintf(stdout, "%s mpi_rank = %d.\n", fcnName, mpi_rank); + HDfprintf(stdout, "%s rank = %d.\n", fcnName, rank); + HDfprintf(stdout, "%s edge_size = %d.\n", fcnName, edge_size); + HDfprintf(stdout, "%s checker_edge_size = %d.\n", + fcnName, checker_edge_size); + HDfprintf(stdout, "%s first_expected_val = %d.\n", + fcnName, (int)first_expected_val); + HDfprintf(stdout, "%s starts_in_checker = %d.\n", + fcnName, (int)buf_starts_in_checker); + } +#endif + + val_ptr = buf_ptr; + expected_value = first_expected_val; + + i = 0; + v = 0; + start_in_checker[0] = buf_starts_in_checker; + do + { + if ( v >= checker_edge_size ) { + + start_in_checker[0] = ! start_in_checker[0]; + v = 0; + } + + j = 0; + w = 0; + start_in_checker[1] = start_in_checker[0]; + do + { + if ( w >= checker_edge_size ) { + + start_in_checker[1] = ! start_in_checker[1]; + w = 0; + } + + k = 0; + x = 0; + start_in_checker[2] = start_in_checker[1]; + do + { + if ( x >= checker_edge_size ) { + + start_in_checker[2] = ! start_in_checker[2]; + x = 0; + } + + l = 0; + y = 0; + start_in_checker[3] = start_in_checker[2]; + do + { + if ( y >= checker_edge_size ) { + + start_in_checker[3] = ! start_in_checker[3]; + y = 0; + } + + m = 0; + z = 0; +#if LOWER_DIM_SIZE_COMP_TEST__VERIFY_DATA__DEBUG + if ( mpi_rank == + LOWER_DIM_SIZE_COMP_TEST_DEBUG_TARGET_RANK ) { + HDfprintf(stdout, "%d, %d, %d, %d, %d:", i, j, k, l, m); + } +#endif + in_checker = start_in_checker[3]; + do + { +#if LOWER_DIM_SIZE_COMP_TEST__VERIFY_DATA__DEBUG + if ( mpi_rank == + LOWER_DIM_SIZE_COMP_TEST_DEBUG_TARGET_RANK ) { + HDfprintf(stdout, " %d", (int)(*val_ptr)); + } +#endif + if ( z >= checker_edge_size ) { + + in_checker = ! in_checker; + z = 0; + } + + if ( in_checker ) { + + if ( *val_ptr != expected_value ) { + + good_data = FALSE; + } + + /* zero out buffer for re-use */ + *val_ptr = 0; + + } else if ( *val_ptr != 0 ) { + + good_data = FALSE; + + /* zero out buffer for re-use */ + *val_ptr = 0; + + } + + val_ptr++; + expected_value++; + m++; + z++; + + } while ( ( rank >= (test_max_rank - 4) ) && + ( m < edge_size ) ); +#if LOWER_DIM_SIZE_COMP_TEST__VERIFY_DATA__DEBUG + if ( mpi_rank == + LOWER_DIM_SIZE_COMP_TEST_DEBUG_TARGET_RANK ) { + HDfprintf(stdout, "\n"); + } +#endif + l++; + y++; + } while ( ( rank >= (test_max_rank - 3) ) && + ( l < edge_size ) ); + k++; + x++; + } while ( ( rank >= (test_max_rank - 2) ) && + ( k < edge_size ) ); + j++; + w++; + } while ( ( rank >= (test_max_rank - 1) ) && + ( j < edge_size ) ); + i++; + v++; + } while ( ( rank >= test_max_rank ) && + ( i < edge_size ) ); + + return(good_data); + +} /* lower_dim_size_comp_test__verify_data() */ + + +/*------------------------------------------------------------------------- + * Function: lower_dim_size_comp_test__run_test() + * + * Purpose: Verify that a bug in the computation of the size of the + * lower dimensions of a data space in H5S_obtain_datatype() + * has been corrected. + * + * Return: void + * + * Programmer: JRM -- 11/11/09 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +#define LDSCT_DS_RANK 5 +#define LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG 0 + +void +lower_dim_size_comp_test__run_test(const int chunk_edge_size, + const hbool_t use_collective_io, + const hid_t dset_type) +{ +#if LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG + const char *fcnName = "lower_dim_size_comp_test__run_test()"; + int rank; + hsize_t dims[32]; + hsize_t max_dims[32]; +#endif /* LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG */ + const char *filename; + hbool_t use_gpfs = FALSE; /* Use GPFS hints */ + hbool_t data_ok = FALSE; + hbool_t mis_match = FALSE; + int i; + int start_index; + int stop_index; + int mrc; + int mpi_rank; + int mpi_size; + MPI_Comm mpi_comm = MPI_COMM_NULL; + MPI_Info mpi_info = MPI_INFO_NULL; + hid_t fid; /* HDF5 file ID */ + hid_t acc_tpl; /* File access templates */ + hid_t xfer_plist = H5P_DEFAULT; + size_t small_ds_size; + size_t small_ds_slice_size; + size_t large_ds_size; + size_t large_ds_slice_size; + uint32_t expected_value; + uint32_t * small_ds_buf_0 = NULL; + uint32_t * small_ds_buf_1 = NULL; + uint32_t * large_ds_buf_0 = NULL; + uint32_t * large_ds_buf_1 = NULL; + uint32_t * ptr_0; + uint32_t * ptr_1; + hsize_t small_chunk_dims[LDSCT_DS_RANK]; + hsize_t large_chunk_dims[LDSCT_DS_RANK]; + hsize_t small_dims[LDSCT_DS_RANK]; + hsize_t large_dims[LDSCT_DS_RANK]; + hsize_t start[LDSCT_DS_RANK]; + hsize_t stride[LDSCT_DS_RANK]; + hsize_t count[LDSCT_DS_RANK]; + hsize_t block[LDSCT_DS_RANK]; + hsize_t small_sel_start[LDSCT_DS_RANK]; + hsize_t large_sel_start[LDSCT_DS_RANK]; + hid_t full_mem_small_ds_sid; + hid_t full_file_small_ds_sid; + hid_t mem_small_ds_sid; + hid_t file_small_ds_sid; + hid_t full_mem_large_ds_sid; + hid_t full_file_large_ds_sid; + hid_t mem_large_ds_sid; + hid_t file_large_ds_sid; + hid_t small_ds_dcpl_id = H5P_DEFAULT; + hid_t large_ds_dcpl_id = H5P_DEFAULT; + hid_t small_dataset; /* Dataset ID */ + hid_t large_dataset; /* Dataset ID */ + htri_t check; /* Shape comparison return value */ + herr_t ret; /* Generic return value */ + + MPI_Comm_size(MPI_COMM_WORLD, &mpi_size); + MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank); + + HDassert( mpi_size >= 1 ); + + mpi_comm = MPI_COMM_WORLD; + mpi_info = MPI_INFO_NULL; + +#if LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG + if ( mpi_rank == LOWER_DIM_SIZE_COMP_TEST_DEBUG_TARGET_RANK ) { + HDfprintf(stdout, "%s:%d: chunk_edge_size = %d.\n", + fcnName, mpi_rank, (int)chunk_edge_size); + HDfprintf(stdout, "%s:%d: use_collective_io = %d.\n", + fcnName, mpi_rank, (int)use_collective_io); + } +#endif /* LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG */ + + + small_ds_size = (size_t)((mpi_size + 1) * 1 * 1 * 10 * 10); + small_ds_slice_size = (size_t) ( 1 * 1 * 10 * 10); + large_ds_size = (size_t)((mpi_size + 1) * 10 * 10 * 10 * 10); + large_ds_slice_size = (size_t) (10 * 10 * 10 * 10); + +#if LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG + if ( mpi_rank == LOWER_DIM_SIZE_COMP_TEST_DEBUG_TARGET_RANK ) { + HDfprintf(stdout, "%s:%d: small ds size / slice size = %d / %d.\n", + fcnName, mpi_rank, + (int)small_ds_size, (int)small_ds_slice_size); + HDfprintf(stdout, "%s:%d: large ds size / slice size = %d / %d.\n", + fcnName, mpi_rank, + (int)large_ds_size, (int)large_ds_slice_size); + } +#endif /* LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG */ + + /* Allocate buffers */ + small_ds_buf_0 = (uint32_t *)HDmalloc(sizeof(uint32_t) * small_ds_size); + VRFY((small_ds_buf_0 != NULL), "malloc of small_ds_buf_0 succeeded"); + + small_ds_buf_1 = (uint32_t *)HDmalloc(sizeof(uint32_t) * small_ds_size); + VRFY((small_ds_buf_1 != NULL), "malloc of small_ds_buf_1 succeeded"); + + large_ds_buf_0 = (uint32_t *)HDmalloc(sizeof(uint32_t) * large_ds_size); + VRFY((large_ds_buf_0 != NULL), "malloc of large_ds_buf_0 succeeded"); + + large_ds_buf_1 = (uint32_t *)HDmalloc(sizeof(uint32_t) * large_ds_size); + VRFY((large_ds_buf_1 != NULL), "malloc of large_ds_buf_1 succeeded"); + + + /* initialize the buffers */ + + ptr_0 = small_ds_buf_0; + ptr_1 = small_ds_buf_1; + + for ( i = 0; i < (int)small_ds_size; i++ ) { + + *ptr_0 = (uint32_t)i; + *ptr_1 = 0; + + ptr_0++; + ptr_1++; + } + + ptr_0 = large_ds_buf_0; + ptr_1 = large_ds_buf_1; + + for ( i = 0; i < (int)large_ds_size; i++ ) { + + *ptr_0 = (uint32_t)i; + *ptr_1 = 0; + + ptr_0++; + ptr_1++; + } + + + /* get the file name */ + + filename = (const char *)GetTestParameters(); + HDassert( filename != NULL ); + + + /* ---------------------------------------- + * CREATE AN HDF5 FILE WITH PARALLEL ACCESS + * ---------------------------------------*/ + /* setup file access template */ + acc_tpl = create_faccess_plist(mpi_comm, mpi_info, facc_type, use_gpfs); + VRFY((acc_tpl >= 0), "create_faccess_plist() succeeded"); + + /* create the file collectively */ + fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, acc_tpl); + VRFY((fid >= 0), "H5Fcreate succeeded"); + + MESG("File opened."); + + /* Release file-access template */ + ret = H5Pclose(acc_tpl); + VRFY((ret >= 0), "H5Pclose(acc_tpl) succeeded"); + + + /* setup dims: */ + small_dims[0] = (hsize_t)(mpi_size + 1); + small_dims[1] = 1; + small_dims[2] = 1; + small_dims[3] = 10; + small_dims[4] = 10; + + large_dims[0] = (hsize_t)(mpi_size + 1); + large_dims[1] = 10; + large_dims[2] = 10; + large_dims[3] = 10; + large_dims[4] = 10; + +#if LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG + if ( mpi_rank == LOWER_DIM_SIZE_COMP_TEST_DEBUG_TARGET_RANK ) { + HDfprintf(stdout, "%s:%d: small_dims[] = %d %d %d %d %d\n", + fcnName, mpi_rank, (int)small_dims[0], (int)small_dims[1], + (int)small_dims[2], (int)small_dims[3], (int)small_dims[4]); + HDfprintf(stdout, "%s:%d: large_dims[] = %d %d %d %d %d\n", + fcnName, mpi_rank, (int)large_dims[0], (int)large_dims[1], + (int)large_dims[2], (int)large_dims[3], (int)large_dims[4]); + } +#endif + + /* create data spaces */ + + full_mem_small_ds_sid = H5Screate_simple(5, small_dims, NULL); + VRFY((full_mem_small_ds_sid != 0), + "H5Screate_simple() full_mem_small_ds_sid succeeded"); + + full_file_small_ds_sid = H5Screate_simple(5, small_dims, NULL); + VRFY((full_file_small_ds_sid != 0), + "H5Screate_simple() full_file_small_ds_sid succeeded"); + + mem_small_ds_sid = H5Screate_simple(5, small_dims, NULL); + VRFY((mem_small_ds_sid != 0), + "H5Screate_simple() mem_small_ds_sid succeeded"); + + file_small_ds_sid = H5Screate_simple(5, small_dims, NULL); + VRFY((file_small_ds_sid != 0), + "H5Screate_simple() file_small_ds_sid succeeded"); + + + full_mem_large_ds_sid = H5Screate_simple(5, large_dims, NULL); + VRFY((full_mem_large_ds_sid != 0), + "H5Screate_simple() full_mem_large_ds_sid succeeded"); + + full_file_large_ds_sid = H5Screate_simple(5, large_dims, NULL); + VRFY((full_file_large_ds_sid != 0), + "H5Screate_simple() full_file_large_ds_sid succeeded"); + + mem_large_ds_sid = H5Screate_simple(5, large_dims, NULL); + VRFY((mem_large_ds_sid != 0), + "H5Screate_simple() mem_large_ds_sid succeeded"); + + file_large_ds_sid = H5Screate_simple(5, large_dims, NULL); + VRFY((file_large_ds_sid != 0), + "H5Screate_simple() file_large_ds_sid succeeded"); + + + /* Select the entire extent of the full small ds dataspaces */ + ret = H5Sselect_all(full_mem_small_ds_sid); + VRFY((ret != FAIL), "H5Sselect_all(full_mem_small_ds_sid) succeeded"); + + ret = H5Sselect_all(full_file_small_ds_sid); + VRFY((ret != FAIL), "H5Sselect_all(full_file_small_ds_sid) succeeded"); + + + /* Select the entire extent of the full large ds dataspaces */ + ret = H5Sselect_all(full_mem_large_ds_sid); + VRFY((ret != FAIL), "H5Sselect_all(full_mem_large_ds_sid) succeeded"); + + ret = H5Sselect_all(full_file_large_ds_sid); + VRFY((ret != FAIL), "H5Sselect_all(full_file_large_ds_sid) succeeded"); + + + /* if chunk edge size is greater than zero, set up the small and + * large data set creation property lists to specify chunked + * datasets. + */ + if ( chunk_edge_size > 0 ) { + + small_chunk_dims[0] = (hsize_t)(1); + small_chunk_dims[1] = small_chunk_dims[2] = (hsize_t)1; + small_chunk_dims[3] = small_chunk_dims[4] = (hsize_t)chunk_edge_size; + +#if LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG + if ( mpi_rank == LOWER_DIM_SIZE_COMP_TEST_DEBUG_TARGET_RANK ) { + HDfprintf(stdout, "%s:%d: small chunk dims[] = %d %d %d %d %d\n", + fcnName, mpi_rank, (int)small_chunk_dims[0], + (int)small_chunk_dims[1], (int)small_chunk_dims[2], + (int)small_chunk_dims[3], (int)small_chunk_dims[4]); + } +#endif + + small_ds_dcpl_id = H5Pcreate(H5P_DATASET_CREATE); + VRFY((ret != FAIL), "H5Pcreate() small_ds_dcpl_id succeeded"); + + ret = H5Pset_layout(small_ds_dcpl_id, H5D_CHUNKED); + VRFY((ret != FAIL), "H5Pset_layout() small_ds_dcpl_id succeeded"); + + ret = H5Pset_chunk(small_ds_dcpl_id, 5, small_chunk_dims); + VRFY((ret != FAIL), "H5Pset_chunk() small_ds_dcpl_id succeeded"); + + large_chunk_dims[0] = (hsize_t)(1); + large_chunk_dims[1] = large_chunk_dims[2] = + large_chunk_dims[3] = large_chunk_dims[4] = (hsize_t)chunk_edge_size; + + +#if LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG + if ( mpi_rank == LOWER_DIM_SIZE_COMP_TEST_DEBUG_TARGET_RANK ) { + HDfprintf(stdout, "%s:%d: large chunk dims[] = %d %d %d %d %d\n", + fcnName, mpi_rank, (int)large_chunk_dims[0], + (int)large_chunk_dims[1], (int)large_chunk_dims[2], + (int)large_chunk_dims[3], (int)large_chunk_dims[4]); + } +#endif + + large_ds_dcpl_id = H5Pcreate(H5P_DATASET_CREATE); + VRFY((ret != FAIL), "H5Pcreate() large_ds_dcpl_id succeeded"); + + ret = H5Pset_layout(large_ds_dcpl_id, H5D_CHUNKED); + VRFY((ret != FAIL), "H5Pset_layout() large_ds_dcpl_id succeeded"); + + ret = H5Pset_chunk(large_ds_dcpl_id, 5, large_chunk_dims); + VRFY((ret != FAIL), "H5Pset_chunk() large_ds_dcpl_id succeeded"); + } + + + /* create the small dataset */ + small_dataset = H5Dcreate2(fid, "small_dataset", dset_type, + file_small_ds_sid, H5P_DEFAULT, + small_ds_dcpl_id, H5P_DEFAULT); + VRFY((ret >= 0), "H5Dcreate2() small_dataset succeeded"); + + + /* create the large dataset */ + large_dataset = H5Dcreate2(fid, "large_dataset", dset_type, + file_large_ds_sid, H5P_DEFAULT, + large_ds_dcpl_id, H5P_DEFAULT); + VRFY((ret >= 0), "H5Dcreate2() large_dataset succeeded"); + +#if LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG + if ( mpi_rank == LOWER_DIM_SIZE_COMP_TEST_DEBUG_TARGET_RANK ) { + HDfprintf(stdout, + "%s:%d: small/large ds id = %d / %d.\n", + fcnName, mpi_rank, (int)small_dataset, + (int)large_dataset); + } +#endif /* LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG */ + + + /* setup xfer property list */ + xfer_plist = H5Pcreate(H5P_DATASET_XFER); + VRFY((xfer_plist >= 0), "H5Pcreate(H5P_DATASET_XFER) succeeded"); + + ret = H5Pset_dxpl_mpio(xfer_plist, H5FD_MPIO_COLLECTIVE); + VRFY((ret >= 0), "H5Pset_dxpl_mpio succeeded"); + + if ( ! use_collective_io ) { + + ret = H5Pset_dxpl_mpio_collective_opt(xfer_plist, + H5FD_MPIO_INDIVIDUAL_IO); + VRFY((ret>= 0), "H5Pset_dxpl_mpio_collective_opt() suceeded"); + } + + + /* setup selection to write initial data to the small data sets */ + start[0] = (hsize_t)(mpi_rank + 1); + start[1] = start[2] = start[3] = start[4] = 0; + + stride[0] = (hsize_t)(2 * (mpi_size + 1)); + stride[1] = stride[2] = 2; + stride[3] = stride[4] = 2 * 10; + + count[0] = count[1] = count[2] = count[3] = count[4] = 1; + + block[0] = block[1] = block[2] = 1; + block[3] = block[4] = 10; + +#if LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG + if ( mpi_rank == LOWER_DIM_SIZE_COMP_TEST_DEBUG_TARGET_RANK ) { + HDfprintf(stdout, + "%s:%d: settings for small data set initialization.\n", + fcnName, mpi_rank); + HDfprintf(stdout, "%s:%d: start[] = %d %d %d %d %d\n", + fcnName, mpi_rank, (int)start[0], (int)start[1], + (int)start[2], (int)start[3], (int)start[4]); + HDfprintf(stdout, "%s:%d: stride[] = %d %d %d %d %d\n", + fcnName, mpi_rank, (int)stride[0], (int)stride[1], + (int)stride[2], (int)stride[3], (int)stride[4]); + HDfprintf(stdout, "%s:%d: count[] = %d %d %d %d %d\n", + fcnName, mpi_rank, (int)count[0], (int)count[1], + (int)count[2], (int)count[3], (int)count[4]); + HDfprintf(stdout, "%s:%d: block[] = %d %d %d %d %d\n", + fcnName, mpi_rank, (int)block[0], (int)block[1], + (int)block[2], (int)block[3], (int)block[4]); + } +#endif /* LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG */ + + /* setup selections for writing initial data to the small data set */ + ret = H5Sselect_hyperslab(mem_small_ds_sid, + H5S_SELECT_SET, + start, + stride, + count, + block); + VRFY((ret >= 0), "H5Sselect_hyperslab(mem_small_ds_sid, set) suceeded"); + + ret = H5Sselect_hyperslab(file_small_ds_sid, + H5S_SELECT_SET, + start, + stride, + count, + block); + VRFY((ret >= 0), "H5Sselect_hyperslab(file_small_ds_sid, set) suceeded"); + + if ( MAINPROCESS ) { /* add an additional slice to the selections */ + + start[0] = 0; + +#if LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG + if ( mpi_rank == LOWER_DIM_SIZE_COMP_TEST_DEBUG_TARGET_RANK ) { + HDfprintf(stdout, + "%s:%d: added settings for main process.\n", + fcnName, mpi_rank); + HDfprintf(stdout, "%s:%d: start[] = %d %d %d %d %d\n", + fcnName, mpi_rank, (int)start[0], (int)start[1], + (int)start[2], (int)start[3], (int)start[4]); + HDfprintf(stdout, "%s:%d: stride[] = %d %d %d %d %d\n", + fcnName, mpi_rank, (int)stride[0], (int)stride[1], + (int)stride[2], (int)stride[3], (int)stride[4]); + HDfprintf(stdout, "%s:%d: count[] = %d %d %d %d %d\n", + fcnName, mpi_rank, (int)count[0], (int)count[1], + (int)count[2], (int)count[3], (int)count[4]); + HDfprintf(stdout, "%s:%d: block[] = %d %d %d %d %d\n", + fcnName, mpi_rank, (int)block[0], (int)block[1], + (int)block[2], (int)block[3], (int)block[4]); + } +#endif /* LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG */ + + ret = H5Sselect_hyperslab(mem_small_ds_sid, + H5S_SELECT_OR, + start, + stride, + count, + block); + VRFY((ret>= 0), "H5Sselect_hyperslab(mem_small_ds_sid, or) suceeded"); + + ret = H5Sselect_hyperslab(file_small_ds_sid, + H5S_SELECT_OR, + start, + stride, + count, + block); + VRFY((ret>= 0), "H5Sselect_hyperslab(file_small_ds_sid, or) suceeded"); + } + + check = H5Sselect_valid(mem_small_ds_sid); + VRFY((check == TRUE),"H5Sselect_valid(mem_small_ds_sid) returns TRUE"); + + check = H5Sselect_valid(file_small_ds_sid); + VRFY((check == TRUE),"H5Sselect_valid(file_small_ds_sid) returns TRUE"); + + + /* write the initial value of the small data set to file */ +#if LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG + if ( mpi_rank == LOWER_DIM_SIZE_COMP_TEST_DEBUG_TARGET_RANK ) { + HDfprintf(stdout, "%s:%d: writing init value of small ds to file.\n", + fcnName, mpi_rank); + } +#endif /* LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG */ + ret = H5Dwrite(small_dataset, + dset_type, + mem_small_ds_sid, + file_small_ds_sid, + xfer_plist, + small_ds_buf_0); + VRFY((ret >= 0), "H5Dwrite() small_dataset initial write succeeded"); + + + /* read the small data set back to verify that it contains the + * expected data. Note that each process reads in the entire + * data set and verifies it. + */ + ret = H5Dread(small_dataset, + H5T_NATIVE_UINT32, + full_mem_small_ds_sid, + full_file_small_ds_sid, + xfer_plist, + small_ds_buf_1); + VRFY((ret >= 0), "H5Dread() small_dataset initial read succeeded"); + + + /* sync with the other processes before checking data */ + mrc = MPI_Barrier(MPI_COMM_WORLD); + VRFY((mrc==MPI_SUCCESS), "Sync after small dataset writes"); + + + /* verify that the correct data was written to the small data set, + * and reset the buffer to zero in passing. + */ + expected_value = 0; + mis_match = FALSE; + ptr_1 = small_ds_buf_1; + + i = 0; + for ( i = 0; i < (int)small_ds_size; i++ ) { + + if ( *ptr_1 != expected_value ) { + + mis_match = TRUE; + } + + *ptr_1 = (uint32_t)0; + + ptr_1++; + expected_value++; + } + VRFY( (mis_match == FALSE), "small ds init data good."); + + + + /* setup selections for writing initial data to the large data set */ + start[0] = (hsize_t)(mpi_rank + 1); + start[1] = start[2] = start[3] = start[4] = (hsize_t)0; + + stride[0] = (hsize_t)(2 * (mpi_size + 1)); + stride[1] = stride[2] = stride[3] = stride[4] = (hsize_t)(2 * 10); + + count[0] = count[1] = count[2] = count[3] = count[4] = (hsize_t)1; + + block[0] = (hsize_t)1; + block[1] = block[2] = block[3] = block[4] = (hsize_t)10; + +#if LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG + if ( mpi_rank == LOWER_DIM_SIZE_COMP_TEST_DEBUG_TARGET_RANK ) { + HDfprintf(stdout, + "%s:%d: settings for large data set initialization.\n", + fcnName, mpi_rank); + HDfprintf(stdout, "%s:%d: start[] = %d %d %d %d %d\n", + fcnName, mpi_rank, (int)start[0], (int)start[1], + (int)start[2], (int)start[3], (int)start[4]); + HDfprintf(stdout, "%s:%d: stride[] = %d %d %d %d %d\n", + fcnName, mpi_rank, (int)stride[0], (int)stride[1], + (int)stride[2], (int)stride[3], (int)stride[4]); + HDfprintf(stdout, "%s:%d: count[] = %d %d %d %d %d\n", + fcnName, mpi_rank, (int)count[0], (int)count[1], + (int)count[2], (int)count[3], (int)count[4]); + HDfprintf(stdout, "%s:%d: block[] = %d %d %d %d %d\n", + fcnName, mpi_rank, (int)block[0], (int)block[1], + (int)block[2], (int)block[3], (int)block[4]); + } +#endif /* LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG */ + + ret = H5Sselect_hyperslab(mem_large_ds_sid, + H5S_SELECT_SET, + start, + stride, + count, + block); + VRFY((ret >= 0), "H5Sselect_hyperslab(mem_large_ds_sid, set) suceeded"); + + ret = H5Sselect_hyperslab(file_large_ds_sid, + H5S_SELECT_SET, + start, + stride, + count, + block); + VRFY((ret >= 0), "H5Sselect_hyperslab(file_large_ds_sid, set) suceeded"); + +#if LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG + if ( mpi_rank == LOWER_DIM_SIZE_COMP_TEST_DEBUG_TARGET_RANK ) { + HDfprintf(stdout, + "%s%d: H5Sget_select_npoints(mem_large_ds_sid) = %d.\n", + fcnName, mpi_rank, + (int)H5Sget_select_npoints(mem_large_ds_sid)); + HDfprintf(stdout, + "%s%d: H5Sget_select_npoints(file_large_ds_sid) = %d.\n", + fcnName, mpi_rank, + (int)H5Sget_select_npoints(file_large_ds_sid)); + } +#endif /* LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG */ + + if ( MAINPROCESS ) { /* add an additional slice to the selections */ + + start[0] = (hsize_t)0; + +#if LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG + if ( mpi_rank == LOWER_DIM_SIZE_COMP_TEST_DEBUG_TARGET_RANK ) { + HDfprintf(stdout, + "%s:%d: added settings for main process.\n", + fcnName, mpi_rank); + HDfprintf(stdout, "%s:%d: start[] = %d %d %d %d %d\n", + fcnName, mpi_rank, (int)start[0], (int)start[1], + (int)start[2], (int)start[3], (int)start[4]); + HDfprintf(stdout, "%s:%d: stride[] = %d %d %d %d %d\n", + fcnName, mpi_rank, (int)stride[0], (int)stride[1], + (int)stride[2], (int)stride[3], (int)stride[4]); + HDfprintf(stdout, "%s:%d: count[] = %d %d %d %d %d\n", + fcnName, mpi_rank, (int)count[0], (int)count[1], + (int)count[2], (int)count[3], (int)count[4]); + HDfprintf(stdout, "%s:%d: block[] = %d %d %d %d %d\n", + fcnName, mpi_rank, (int)block[0], (int)block[1], + (int)block[2], (int)block[3], (int)block[4]); + } +#endif /* LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG */ + + ret = H5Sselect_hyperslab(mem_large_ds_sid, + H5S_SELECT_OR, + start, + stride, + count, + block); + VRFY((ret>= 0), "H5Sselect_hyperslab(mem_large_ds_sid, or) suceeded"); + + ret = H5Sselect_hyperslab(file_large_ds_sid, + H5S_SELECT_OR, + start, + stride, + count, + block); + VRFY((ret>= 0), "H5Sselect_hyperslab(file_large_ds_sid, or) suceeded"); + +#if LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG + if ( mpi_rank == LOWER_DIM_SIZE_COMP_TEST_DEBUG_TARGET_RANK ) { + HDfprintf(stdout, + "%s%d: H5Sget_select_npoints(mem_large_ds_sid) = %d.\n", + fcnName, mpi_rank, + (int)H5Sget_select_npoints(mem_large_ds_sid)); + HDfprintf(stdout, + "%s%d: H5Sget_select_npoints(file_large_ds_sid) = %d.\n", + fcnName, mpi_rank, + (int)H5Sget_select_npoints(file_large_ds_sid)); + } +#endif /* LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG */ + } + + /* try clipping the selection back to the large data space proper */ + start[0] = start[1] = start[2] = start[3] = start[4] = (hsize_t)0; + + stride[0] = (hsize_t)(2 * (mpi_size + 1)); + stride[1] = stride[2] = stride[3] = stride[4] = (hsize_t)(2 * 10); + + count[0] = count[1] = count[2] = count[3] = count[4] = (hsize_t)1; + + block[0] = (hsize_t)(mpi_size + 1); + block[1] = block[2] = block[3] = block[4] = (hsize_t)10; + + ret = H5Sselect_hyperslab(mem_large_ds_sid, H5S_SELECT_AND, + start, stride, count, block); + VRFY((ret != FAIL),"H5Sselect_hyperslab(mem_large_ds_sid, and) succeeded"); + + ret = H5Sselect_hyperslab(file_large_ds_sid, H5S_SELECT_AND, + start, stride, count, block); + VRFY((ret != FAIL),"H5Sselect_hyperslab(file_large_ds_sid, and) succeeded"); + +#if LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG + if ( mpi_rank == LOWER_DIM_SIZE_COMP_TEST_DEBUG_TARGET_RANK ) { + + rank = H5Sget_simple_extent_dims(mem_large_ds_sid, dims, max_dims); + HDfprintf(stdout, + "%s:%d: mem_large_ds_sid dims[%d] = %d %d %d %d %d\n", + fcnName, mpi_rank, rank, (int)dims[0], (int)dims[1], + (int)dims[2], (int)dims[3], (int)dims[4]); + + rank = H5Sget_simple_extent_dims(file_large_ds_sid, dims, max_dims); + HDfprintf(stdout, + "%s:%d: file_large_ds_sid dims[%d] = %d %d %d %d %d\n", + fcnName, mpi_rank, rank, (int)dims[0], (int)dims[1], + (int)dims[2], (int)dims[3], (int)dims[4]); + } +#endif /* LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG */ + + check = H5Sselect_valid(mem_large_ds_sid); + VRFY((check == TRUE),"H5Sselect_valid(mem_large_ds_sid) returns TRUE"); + + check = H5Sselect_valid(file_large_ds_sid); + VRFY((check == TRUE),"H5Sselect_valid(file_large_ds_sid) returns TRUE"); + + + /* write the initial value of the large data set to file */ +#if LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG + if ( mpi_rank == LOWER_DIM_SIZE_COMP_TEST_DEBUG_TARGET_RANK ) { + HDfprintf(stdout, "%s:%d: writing init value of large ds to file.\n", + fcnName, mpi_rank); + HDfprintf(stdout, + "%s:%d: large_dataset = %d.\n", + fcnName, mpi_rank, + (int)large_dataset); + HDfprintf(stdout, + "%s:%d: mem_large_ds_sid = %d, file_large_ds_sid = %d.\n", + fcnName, mpi_rank, + (int)mem_large_ds_sid, (int)file_large_ds_sid); + } +#endif /* LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG */ + + ret = H5Dwrite(large_dataset, + dset_type, + mem_large_ds_sid, + file_large_ds_sid, + xfer_plist, + large_ds_buf_0); + + if ( ret < 0 ) H5Eprint(H5E_DEFAULT, stderr); + VRFY((ret >= 0), "H5Dwrite() large_dataset initial write succeeded"); + + + /* sync with the other processes before checking data */ + mrc = MPI_Barrier(MPI_COMM_WORLD); + VRFY((mrc==MPI_SUCCESS), "Sync after large dataset writes"); + + /* read the large data set back to verify that it contains the + * expected data. Note that each process reads in the entire + * data set. + */ + ret = H5Dread(large_dataset, + H5T_NATIVE_UINT32, + full_mem_large_ds_sid, + full_file_large_ds_sid, + xfer_plist, + large_ds_buf_1); + VRFY((ret >= 0), "H5Dread() large_dataset initial read succeeded"); + + + /* verify that the correct data was written to the large data set. + * in passing, reset the buffer to zeros + */ + expected_value = 0; + mis_match = FALSE; + ptr_1 = large_ds_buf_1; + + i = 0; + for ( i = 0; i < (int)large_ds_size; i++ ) { + + if ( *ptr_1 != expected_value ) { + + mis_match = TRUE; + } + + *ptr_1 = (uint32_t)0; + + ptr_1++; + expected_value++; + } + VRFY( (mis_match == FALSE), "large ds init data good."); + + /***********************************/ + /***** INITIALIZATION COMPLETE *****/ + /***********************************/ + + + /* read a checkerboard selection of the process slice of the + * small on disk data set into the process slice of the large + * in memory data set, and verify the data read. + */ + + small_sel_start[0] = (hsize_t)(mpi_rank + 1); + small_sel_start[1] = small_sel_start[2] = + small_sel_start[3] = small_sel_start[4] = 0; + + lower_dim_size_comp_test__select_checker_board(mpi_rank, + file_small_ds_sid, + /* tgt_rank = */ 5, + small_dims, + /* checker_edge_size = */ 3, + /* sel_rank */ 2, + small_sel_start); + + expected_value = (uint32_t) + ((small_sel_start[0] * small_dims[1] * small_dims[2] * + small_dims[3] * small_dims[4]) + + (small_sel_start[1] * small_dims[2] * small_dims[3] * + small_dims[4]) + + (small_sel_start[2] * small_dims[3] * small_dims[4]) + + (small_sel_start[3] * small_dims[4]) + + (small_sel_start[4])); + + + large_sel_start[0] = (hsize_t)(mpi_rank + 1); + large_sel_start[1] = 5; + large_sel_start[2] = large_sel_start[3] = large_sel_start[4] = 0; + + lower_dim_size_comp_test__select_checker_board(mpi_rank, + mem_large_ds_sid, + /* tgt_rank = */ 5, + large_dims, + /* checker_edge_size = */ 3, + /* sel_rank = */ 2, + large_sel_start); + + + /* verify that H5S_select_shape_same() reports the two + * selections as having the same shape. + */ + check = H5S_select_shape_same_test(mem_large_ds_sid, + file_small_ds_sid); + VRFY((check == TRUE), "H5S_select_shape_same_test passed (1)"); + + + ret = H5Dread(small_dataset, + H5T_NATIVE_UINT32, + mem_large_ds_sid, + file_small_ds_sid, + xfer_plist, + large_ds_buf_1); + + VRFY((ret >= 0), "H5Sread() slice from small ds succeeded."); + +#if LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG + if ( mpi_rank == LOWER_DIM_SIZE_COMP_TEST_DEBUG_TARGET_RANK ) { + HDfprintf(stdout, "%s:%d: H5Dread() returns.\n", fcnName, mpi_rank); + } +#endif /* LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG */ + + /* verify that expected data is retrieved */ + + data_ok = TRUE; + + start_index = (int)((large_sel_start[0] * large_dims[1] * large_dims[2] * + large_dims[3] * large_dims[4]) + + (large_sel_start[1] * large_dims[2] * large_dims[3] * + large_dims[4]) + + (large_sel_start[2] * large_dims[3] * large_dims[4]) + + (large_sel_start[3] * large_dims[4]) + + (large_sel_start[4])); + + stop_index = start_index + (int)small_ds_slice_size; + + HDassert( 0 <= start_index ); + HDassert( start_index < stop_index ); + HDassert( stop_index <= (int)large_ds_size ); + + ptr_1 = large_ds_buf_1; + + for ( i = 0; i < start_index; i++ ) { + + if ( *ptr_1 != (uint32_t)0 ) { + + data_ok = FALSE; + *ptr_1 = (uint32_t)0; + } + + ptr_1++; + } + + VRFY((data_ok == TRUE), "slice read from small ds data good(1)."); + + + data_ok = lower_dim_size_comp_test__verify_data(ptr_1, +#if LOWER_DIM_SIZE_COMP_TEST__VERIFY_DATA__DEBUG + mpi_rank, +#endif /* LOWER_DIM_SIZE_COMP_TEST__VERIFY_DATA__DEBUG */ + /* rank */ 2, + /* edge_size */ 10, + /* checker_edge_size */ 3, + expected_value, + /* buf_starts_in_checker */ TRUE); + + VRFY((data_ok == TRUE), "slice read from small ds data good(2)."); + + data_ok = TRUE; + + ptr_1 += small_ds_slice_size; + + + for ( i = stop_index; i < (int)large_ds_size; i++ ) { + + if ( *ptr_1 != (uint32_t)0 ) { + + data_ok = FALSE; + *ptr_1 = (uint32_t)0; + } + + ptr_1++; + } + + VRFY((data_ok == TRUE), "slice read from small ds data good(3)."); + + + + + + /* read a checkerboard selection of a slice of the process slice of + * the large on disk data set into the process slice of the small + * in memory data set, and verify the data read. + */ + + small_sel_start[0] = (hsize_t)(mpi_rank + 1); + small_sel_start[1] = small_sel_start[2] = + small_sel_start[3] = small_sel_start[4] = 0; + + lower_dim_size_comp_test__select_checker_board(mpi_rank, + mem_small_ds_sid, + /* tgt_rank = */ 5, + small_dims, + /* checker_edge_size = */ 3, + /* sel_rank */ 2, + small_sel_start); + + large_sel_start[0] = (hsize_t)(mpi_rank + 1); + large_sel_start[1] = 5; + large_sel_start[2] = large_sel_start[3] = large_sel_start[4] = 0; + + lower_dim_size_comp_test__select_checker_board(mpi_rank, + file_large_ds_sid, + /* tgt_rank = */ 5, + large_dims, + /* checker_edge_size = */ 3, + /* sel_rank = */ 2, + large_sel_start); + + + /* verify that H5S_select_shape_same() reports the two + * selections as having the same shape. + */ + check = H5S_select_shape_same_test(mem_small_ds_sid, + file_large_ds_sid); + VRFY((check == TRUE), "H5S_select_shape_same_test passed (2)"); + + + ret = H5Dread(large_dataset, + H5T_NATIVE_UINT32, + mem_small_ds_sid, + file_large_ds_sid, + xfer_plist, + small_ds_buf_1); + + VRFY((ret >= 0), "H5Sread() slice from large ds succeeded."); + +#if LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG + if ( mpi_rank == LOWER_DIM_SIZE_COMP_TEST_DEBUG_TARGET_RANK ) { + HDfprintf(stdout, "%s:%d: H5Dread() returns.\n", fcnName, mpi_rank); + } +#endif /* LOWER_DIM_SIZE_COMP_TEST__RUN_TEST__DEBUG */ + + /* verify that expected data is retrieved */ + + data_ok = TRUE; + + expected_value = (uint32_t) + ((large_sel_start[0] * large_dims[1] * large_dims[2] * + large_dims[3] * large_dims[4]) + + (large_sel_start[1] * large_dims[2] * large_dims[3] * + large_dims[4]) + + (large_sel_start[2] * large_dims[3] * large_dims[4]) + + (large_sel_start[3] * large_dims[4]) + + (large_sel_start[4])); + + start_index = (int)(mpi_rank + 1) * (int)small_ds_slice_size; + + stop_index = start_index + (int)small_ds_slice_size; + + HDassert( 0 <= start_index ); + HDassert( start_index < stop_index ); + HDassert( stop_index <= (int)small_ds_size ); + + ptr_1 = small_ds_buf_1; + + for ( i = 0; i < start_index; i++ ) { + + if ( *ptr_1 != (uint32_t)0 ) { + + data_ok = FALSE; + *ptr_1 = (uint32_t)0; + } + + ptr_1++; + } + + VRFY((data_ok == TRUE), "slice read from large ds data good(1)."); + + + data_ok = lower_dim_size_comp_test__verify_data(ptr_1, +#if LOWER_DIM_SIZE_COMP_TEST__VERIFY_DATA__DEBUG + mpi_rank, +#endif /* LOWER_DIM_SIZE_COMP_TEST__VERIFY_DATA__DEBUG */ + /* rank */ 2, + /* edge_size */ 10, + /* checker_edge_size */ 3, + expected_value, + /* buf_starts_in_checker */ TRUE); + + VRFY((data_ok == TRUE), "slice read from large ds data good(2)."); + + data_ok = TRUE; + + ptr_1 += small_ds_slice_size; + + + for ( i = stop_index; i < (int)small_ds_size; i++ ) { + + if ( *ptr_1 != (uint32_t)0 ) { + +#if LOWER_DIM_SIZE_COMP_TEST__VERIFY_DATA__DEBUG + if ( mpi_rank == LOWER_DIM_SIZE_COMP_TEST_DEBUG_TARGET_RANK ) { + HDfprintf(stdout, "%s:%d: unexpected value at index %d: %d.\n", + fcnName, mpi_rank, (int)i, (int)(*ptr_1)); + } +#endif /* LOWER_DIM_SIZE_COMP_TEST__VERIFY_DATA__DEBUG */ + + data_ok = FALSE; + *ptr_1 = (uint32_t)0; + } + + ptr_1++; + } + + VRFY((data_ok == TRUE), "slice read from large ds data good(3)."); + + + /* Close dataspaces */ + ret = H5Sclose(full_mem_small_ds_sid); + VRFY((ret != FAIL), "H5Sclose(full_mem_small_ds_sid) succeeded"); + + ret = H5Sclose(full_file_small_ds_sid); + VRFY((ret != FAIL), "H5Sclose(full_file_small_ds_sid) succeeded"); + + ret = H5Sclose(mem_small_ds_sid); + VRFY((ret != FAIL), "H5Sclose(mem_small_ds_sid) succeeded"); + + ret = H5Sclose(file_small_ds_sid); + VRFY((ret != FAIL), "H5Sclose(file_small_ds_sid) succeeded"); + + + ret = H5Sclose(full_mem_large_ds_sid); + VRFY((ret != FAIL), "H5Sclose(full_mem_large_ds_sid) succeeded"); + + ret = H5Sclose(full_file_large_ds_sid); + VRFY((ret != FAIL), "H5Sclose(full_file_large_ds_sid) succeeded"); + + ret = H5Sclose(mem_large_ds_sid); + VRFY((ret != FAIL), "H5Sclose(mem_large_ds_sid) succeeded"); + + ret = H5Sclose(file_large_ds_sid); + VRFY((ret != FAIL), "H5Sclose(file_large_ds_sid) succeeded"); + + + /* Close Datasets */ + ret = H5Dclose(small_dataset); + VRFY((ret != FAIL), "H5Dclose(small_dataset) succeeded"); + + ret = H5Dclose(large_dataset); + VRFY((ret != FAIL), "H5Dclose(large_dataset) succeeded"); + + + /* close the file collectively */ + MESG("about to close file."); + ret = H5Fclose(fid); + VRFY((ret != FAIL), "file close succeeded"); + + /* Free memory buffers */ + if ( small_ds_buf_0 != NULL ) HDfree(small_ds_buf_0); + if ( small_ds_buf_1 != NULL ) HDfree(small_ds_buf_1); + + if ( large_ds_buf_0 != NULL ) HDfree(large_ds_buf_0); + if ( large_ds_buf_1 != NULL ) HDfree(large_ds_buf_1); + + return; + +} /* lower_dim_size_comp_test__run_test() */ + + +/*------------------------------------------------------------------------- + * Function: lower_dim_size_comp_test() + * + * Purpose: Test to see if an error in the computation of the size + * of the lower dimensions in H5S_obtain_datatype() has + * been corrected. + * + * Return: void + * + * Programmer: JRM -- 11/11/09 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +void +lower_dim_size_comp_test(void) +{ + /* const char *fcnName = "lower_dim_size_comp_test()"; */ + int chunk_edge_size = 0; + int use_collective_io = 1; + hid_t dset_type = H5T_STD_U32LE; +#if 0 + sleep(60); +#endif + for ( use_collective_io = (hbool_t)0; + (int)use_collective_io <= 1; + (hbool_t)(use_collective_io++) ) { + + chunk_edge_size = 0; + lower_dim_size_comp_test__run_test(chunk_edge_size, + (hbool_t)use_collective_io, + dset_type); + + + chunk_edge_size = 5; + lower_dim_size_comp_test__run_test(chunk_edge_size, + (hbool_t)use_collective_io, + dset_type); + } + + return; + +} /* lower_dim_size_comp_test() */ + + +/*------------------------------------------------------------------------- + * Function: link_chunk_collective_io_test() + * + * Purpose: Test to verify that an error in MPI type management in + * H5D_link_chunk_collective_io() has been corrected. + * In this bug, we used to free MPI types regardless of + * whether they were basic or derived. + * + * This test is based on a bug report kindly provided by + * Rob Latham of the MPICH team and ANL. + * + * The basic thrust of the test is to cause a process + * to participate in a collective I/O in which it: + * + * 1) Reads or writes exactly one chunk, + * + * 2) Has no in memory buffer for any other chunk. + * + * The test differers from Rob Latham's bug report in + * that is runs with an arbitrary number of proceeses, + * and uses a 1 dimensional dataset. + * + * Return: void + * + * Programmer: JRM -- 12/16/09 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +#define LINK_CHUNK_COLLECTIVE_IO_TEST_CHUNK_SIZE 16 + +void +link_chunk_collective_io_test(void) +{ + /* const char *fcnName = "link_chunk_collective_io_test()"; */ + const char *filename; + hbool_t mis_match = FALSE; + hbool_t use_gpfs = FALSE; /* Use GPFS hints */ + int i; + int mrc; + int mpi_rank; + int mpi_size; + MPI_Comm mpi_comm = MPI_COMM_WORLD; + MPI_Info mpi_info = MPI_INFO_NULL; + hsize_t count[1] = {1}; + hsize_t stride[1] = {2 * LINK_CHUNK_COLLECTIVE_IO_TEST_CHUNK_SIZE}; + hsize_t block[1] = {LINK_CHUNK_COLLECTIVE_IO_TEST_CHUNK_SIZE}; + hsize_t start[1]; + hsize_t dims[1]; + hsize_t chunk_dims[1] = {LINK_CHUNK_COLLECTIVE_IO_TEST_CHUNK_SIZE}; + herr_t ret; /* Generic return value */ + hid_t file_id; + hid_t acc_tpl; + hid_t dset_id; + hid_t file_ds_sid; + hid_t write_mem_ds_sid; + hid_t read_mem_ds_sid; + hid_t ds_dcpl_id; + hid_t xfer_plist; + double diff; + double expected_value; + double local_data_written[LINK_CHUNK_COLLECTIVE_IO_TEST_CHUNK_SIZE]; + double local_data_read[LINK_CHUNK_COLLECTIVE_IO_TEST_CHUNK_SIZE]; + + MPI_Comm_size(MPI_COMM_WORLD, &mpi_size); + MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank); + + HDassert( mpi_size > 0 ); + + /* get the file name */ + filename = (const char *)GetTestParameters(); + HDassert( filename != NULL ); + + /* setup file access template */ + acc_tpl = create_faccess_plist(mpi_comm, mpi_info, facc_type, use_gpfs); + VRFY((acc_tpl >= 0), "create_faccess_plist() succeeded"); + + /* create the file collectively */ + file_id = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, acc_tpl); + VRFY((file_id >= 0), "H5Fcreate succeeded"); + + MESG("File opened."); + + /* Release file-access template */ + ret = H5Pclose(acc_tpl); + VRFY((ret >= 0), "H5Pclose(acc_tpl) succeeded"); + + /* setup dims */ + dims[0] = ((hsize_t)mpi_size) * ((hsize_t)(LINK_CHUNK_COLLECTIVE_IO_TEST_CHUNK_SIZE)); + + /* setup mem and file data spaces */ + write_mem_ds_sid = H5Screate_simple(1, chunk_dims, NULL); + VRFY((write_mem_ds_sid != 0), + "H5Screate_simple() write_mem_ds_sid succeeded"); + + read_mem_ds_sid = H5Screate_simple(1, chunk_dims, NULL); + VRFY((read_mem_ds_sid != 0), + "H5Screate_simple() read_mem_ds_sid succeeded"); + + file_ds_sid = H5Screate_simple(1, dims, NULL); + VRFY((file_ds_sid != 0), + "H5Screate_simple() file_ds_sid succeeded"); + + /* setup data set creation property list */ + ds_dcpl_id = H5Pcreate(H5P_DATASET_CREATE); + VRFY((ds_dcpl_id != FAIL), "H5Pcreate() ds_dcpl_id succeeded"); + + ret = H5Pset_layout(ds_dcpl_id, H5D_CHUNKED); + VRFY((ret != FAIL), "H5Pset_layout() ds_dcpl_id succeeded"); + + ret = H5Pset_chunk(ds_dcpl_id, 1, chunk_dims); + VRFY((ret != FAIL), "H5Pset_chunk() small_ds_dcpl_id succeeded"); + + /* create the data set */ + dset_id = H5Dcreate2(file_id, "dataset", H5T_NATIVE_DOUBLE, + file_ds_sid, H5P_DEFAULT, + ds_dcpl_id, H5P_DEFAULT); + VRFY((dset_id >= 0), "H5Dcreate2() dataset succeeded"); + + /* close the dataset creation property list */ + ret = H5Pclose(ds_dcpl_id); + VRFY((ret >= 0), "H5Pclose(ds_dcpl_id) succeeded"); + + /* setup local data */ + expected_value = (double)(LINK_CHUNK_COLLECTIVE_IO_TEST_CHUNK_SIZE) * + (double)(mpi_rank); + for ( i = 0; i < LINK_CHUNK_COLLECTIVE_IO_TEST_CHUNK_SIZE; i++ ) { + + local_data_written[i] = expected_value; + local_data_read[i] = 0.0; + expected_value += 1.0; + } + + /* select the file and mem spaces */ + start[0] = (hsize_t)(mpi_rank * LINK_CHUNK_COLLECTIVE_IO_TEST_CHUNK_SIZE); + ret = H5Sselect_hyperslab(file_ds_sid, + H5S_SELECT_SET, + start, + stride, + count, + block); + VRFY((ret >= 0), "H5Sselect_hyperslab(file_ds_sid, set) suceeded"); + + ret = H5Sselect_all(write_mem_ds_sid); + VRFY((ret != FAIL), "H5Sselect_all(mem_ds_sid) succeeded"); + + /* Note that we use NO SELECTION on the read memory dataspace */ + + /* setup xfer property list */ + xfer_plist = H5Pcreate(H5P_DATASET_XFER); + VRFY((xfer_plist >= 0), "H5Pcreate(H5P_DATASET_XFER) succeeded"); + + ret = H5Pset_dxpl_mpio(xfer_plist, H5FD_MPIO_COLLECTIVE); + VRFY((ret >= 0), "H5Pset_dxpl_mpio succeeded"); + + /* write the data set */ + ret = H5Dwrite(dset_id, + H5T_NATIVE_DOUBLE, + write_mem_ds_sid, + file_ds_sid, + xfer_plist, + local_data_written); + + VRFY((ret >= 0), "H5Dwrite() dataset initial write succeeded"); + + /* sync with the other processes before checking data */ + mrc = MPI_Barrier(MPI_COMM_WORLD); + VRFY((mrc==MPI_SUCCESS), "Sync after dataset write"); + + /* read this processes slice of the dataset back in */ + ret = H5Dread(dset_id, + H5T_NATIVE_DOUBLE, + read_mem_ds_sid, + file_ds_sid, + xfer_plist, + local_data_read); + VRFY((ret >= 0), "H5Dread() dataset read succeeded"); + + /* close the xfer property list */ + ret = H5Pclose(xfer_plist); + VRFY((ret >= 0), "H5Pclose(xfer_plist) succeeded"); + + /* verify the data */ + mis_match = FALSE; + for ( i = 0; i < LINK_CHUNK_COLLECTIVE_IO_TEST_CHUNK_SIZE; i++ ) { + + diff = local_data_written[i] - local_data_read[i]; + diff = fabs(diff); + + if ( diff >= 0.001 ) { + + mis_match = TRUE; + } + } + VRFY( (mis_match == FALSE), "dataset data good."); + + /* Close dataspaces */ + ret = H5Sclose(write_mem_ds_sid); + VRFY((ret != FAIL), "H5Sclose(write_mem_ds_sid) succeeded"); + + ret = H5Sclose(read_mem_ds_sid); + VRFY((ret != FAIL), "H5Sclose(read_mem_ds_sid) succeeded"); + + ret = H5Sclose(file_ds_sid); + VRFY((ret != FAIL), "H5Sclose(file_ds_sid) succeeded"); + + /* Close Dataset */ + ret = H5Dclose(dset_id); + VRFY((ret != FAIL), "H5Dclose(dset_id) succeeded"); + + /* close the file collectively */ + ret = H5Fclose(file_id); + VRFY((ret != FAIL), "file close succeeded"); + + return; + +} /* link_chunk_collective_io_test() */ + diff --git a/testpar/testphdf5.c b/testpar/testphdf5.c index 4dabada..0864b11 100644 --- a/testpar/testphdf5.c +++ b/testpar/testphdf5.c @@ -462,7 +462,6 @@ int main(int argc, char **argv) coll_irregular_complex_chunk_read,NULL, "collective irregular complex chunk read",PARATESTFILE); - AddTest("null", null_dataset, NULL, "null dataset test", PARATESTFILE); @@ -473,6 +472,26 @@ int main(int argc, char **argv) "I/O mode confusion test -- hangs quickly on failure", &io_mode_confusion_params); + AddTest("tldsc", + lower_dim_size_comp_test, NULL, + "test lower dim size comp in span tree to mpi derived type", + PARATESTFILE); + + AddTest("lccio", + link_chunk_collective_io_test, NULL, + "test mpi derived type management", + PARATESTFILE); + + /* rank projections / shape same tests */ + + AddTest("chsssdrpio", + contig_hyperslab_dr_pio_test, NULL, + "contiguous hyperslab shape same different rank PIO",PARATESTFILE); + + AddTest("cbhsssdrpio", + checker_board_hyperslab_dr_pio_test, NULL, + "checker board hyperslab shape same different rank PIO",PARATESTFILE); + /* Display testing information */ TestInfo(argv[0]); diff --git a/testpar/testphdf5.h b/testpar/testphdf5.h index 24c4432..ba46e4d 100644 --- a/testpar/testphdf5.h +++ b/testpar/testphdf5.h @@ -237,6 +237,10 @@ void coll_irregular_simple_chunk_write(void); void coll_irregular_complex_chunk_read(void); void coll_irregular_complex_chunk_write(void); void io_mode_confusion(void); +void lower_dim_size_comp_test(void); +void link_chunk_collective_io_test(void); +void contig_hyperslab_dr_pio_test(void); +void checker_board_hyperslab_dr_pio_test(void); #ifdef H5_HAVE_FILTER_DEFLATE void compress_readAll(void); #endif /* H5_HAVE_FILTER_DEFLATE */ diff --git a/tools/Makefile.in b/tools/Makefile.in index e29c0ac..fc80fd0 100644 --- a/tools/Makefile.in +++ b/tools/Makefile.in @@ -146,6 +146,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -171,6 +172,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ diff --git a/tools/h5copy/Makefile.in b/tools/h5copy/Makefile.in index 0ac4799..74a01ac 100644 --- a/tools/h5copy/Makefile.in +++ b/tools/h5copy/Makefile.in @@ -138,6 +138,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -163,6 +164,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ diff --git a/tools/h5diff/Makefile.in b/tools/h5diff/Makefile.in index 32f1a87..872e70e 100644 --- a/tools/h5diff/Makefile.in +++ b/tools/h5diff/Makefile.in @@ -145,6 +145,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -170,6 +171,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ diff --git a/tools/h5dump/Makefile.in b/tools/h5dump/Makefile.in index 517608b..e3323a0 100644 --- a/tools/h5dump/Makefile.in +++ b/tools/h5dump/Makefile.in @@ -143,6 +143,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -168,6 +169,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ diff --git a/tools/h5import/Makefile.in b/tools/h5import/Makefile.in index cd93184..3df03c4 100755 --- a/tools/h5import/Makefile.in +++ b/tools/h5import/Makefile.in @@ -138,6 +138,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -163,6 +164,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ diff --git a/tools/h5jam/Makefile.in b/tools/h5jam/Makefile.in index bf5219a..d6b4702 100644 --- a/tools/h5jam/Makefile.in +++ b/tools/h5jam/Makefile.in @@ -152,6 +152,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -177,6 +178,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ diff --git a/tools/h5ls/CMakeLists.txt b/tools/h5ls/CMakeLists.txt index c2d9100..b57423b 100644 --- a/tools/h5ls/CMakeLists.txt +++ b/tools/h5ls/CMakeLists.txt @@ -63,6 +63,10 @@ IF (BUILD_TESTING) tsoftlinks-3.ls tsoftlinks-4.ls tsoftlinks-5.ls + textlinksrc-nodangle-1.ls + textlinksrc-nodangle-2.ls + tsoftlinks-nodangle-1.ls + thlinks-nodangle-1.ls tgroup.ls tgroup-1.ls tgroup-2.ls @@ -186,6 +190,17 @@ IF (BUILD_TESTING) ADD_H5_TEST (textlinksrc-6-old 0 -w80 -E textlinksrc.h5) ADD_H5_TEST (textlinksrc-7-old 0 -w80 -E textlinksrc.h5/ext_link1) + # tests for no-dangling-links + # if this option is given on dangling link, h5ls should return exit code 1 + # when used alone , expect to print out help and return exit code 1 + ADD_H5_TEST (textlinksrc-nodangle-1 1 -w80 --no-dangling-links textlinksrc.h5) + # external dangling link - expected exit code 1 + ADD_H5_TEST (textlinksrc-nodangle-2 1 -w80 --follow-symlinks --no-dangling-links textlinksrc.h5) + # soft dangling link - expected exit code 1 + ADD_H5_TEST (tsoftlinks-nodangle-1 1 -w80 --follow-symlinks --no-dangling-links tsoftlinks.h5) + # when used file with no dangling links - expected exit code 0 + ADD_H5_TEST (thlinks-nodangle-1 0 -w80 --follow-symlinks --no-dangling-links thlink.h5) + # tests for hard links ADD_H5_TEST (thlink-1 0 -w80 thlink.h5) diff --git a/tools/h5ls/Makefile.in b/tools/h5ls/Makefile.in index 4949f8b..7281297 100644 --- a/tools/h5ls/Makefile.in +++ b/tools/h5ls/Makefile.in @@ -132,6 +132,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -157,6 +158,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ diff --git a/tools/h5ls/h5ls.c b/tools/h5ls/h5ls.c index 789e02a..fb08ddb 100644 --- a/tools/h5ls/h5ls.c +++ b/tools/h5ls/h5ls.c @@ -43,6 +43,7 @@ typedef struct symlink_trav_t { char *file; char *path; } *objs; + hbool_t dangle_link; } symlink_trav_t; /* Struct to pass through to visitors */ @@ -66,6 +67,7 @@ static hbool_t string_g = FALSE; /* print 1-byte numbers as ASCII? */ static hbool_t fullname_g = FALSE; /* print full path names */ static hbool_t recursive_g = FALSE; /* recursive descent listing */ static hbool_t follow_symlink_g = FALSE; /* follow symbolic links */ +static hbool_t no_dangling_link_g = FALSE; /* treat dangling link is error */ static hbool_t follow_elink_g = FALSE; /* follow external links */ static hbool_t grp_literal_g = FALSE; /* list group, not contents */ static hbool_t hexdump_g = FALSE; /* show data as raw hexadecimal */ @@ -114,28 +116,38 @@ usage (void) fprintf(stderr, "\ usage: %s [OPTIONS] [OBJECTS...]\n\ OPTIONS\n\ - -h, -?, --help Print a usage message and exit\n\ - -a, --address Print addresses for raw data\n\ - -d, --data Print the values of datasets\n\ - -e, --errors Show all HDF5 error reporting\n\ - --follow-symlinks Follow symbolic links (soft links and external links)\n\ - to display target object information.\n\ - Without this option, h5ls identifies a symbolic link\n\ - as a soft link or external link and prints the value\n\ - assigned to the symbolic link; it does not provide any\n\ - information regarding the target object or determine\n\ - whether the link is a dangling link.\n\ - -f, --full Print full path names instead of base names\n\ - -g, --group Show information about a group, not its contents\n\ - -l, --label Label members of compound datasets\n\ - -r, --recursive List all groups recursively, avoiding cycles\n\ - -s, --string Print 1-byte integer datasets as ASCII\n\ - -S, --simple Use a machine-readable output format\n\ - -wN, --width=N Set the number of columns of output\n\ - -v, --verbose Generate more verbose output\n\ - -V, --version Print version number and exit\n\ - --vfd=DRIVER Use the specified virtual file driver\n\ - -x, --hexdump Show raw data in hexadecimal format\n\ + -h, -?, --help Print a usage message and exit\n\ + -a, --address Print addresses for raw data\n\ + -d, --data Print the values of datasets\n\ + -e, --errors Show all HDF5 error reporting\n\ + --follow-symlinks\n\ + Follow symbolic links (soft links and external links)\n\ + to display target object information.\n\ + Without this option, h5ls identifies a symbolic link\n\ + as a soft link or external link and prints the value\n\ + assigned to the symbolic link; it does not provide any\n\ + information regarding the target object or determine\n\ + whether the link is a dangling link.\n\ + --no-dangling-links\n\ + Must be used with --follow-symlinks option;\n\ + otherwise, h5ls shows error message and returns an exit\n\ + code of 1. \n\ + Check for any symbolic links (soft links or external links)\n\ + that do not resolve to an existing object (dataset, group,\n\ + or named datatype).\n\ + If any dangling link is found, this situation is treated\n\ + as an error and h5ls returns an exit code of 1.\n\ + -f, --full Print full path names instead of base names\n\ + -g, --group Show information about a group, not its contents\n\ + -l, --label Label members of compound datasets\n\ + -r, --recursive List all groups recursively, avoiding cycles\n\ + -s, --string Print 1-byte integer datasets as ASCII\n\ + -S, --simple Use a machine-readable output format\n\ + -wN, --width=N Set the number of columns of output\n\ + -v, --verbose Generate more verbose output\n\ + -V, --version Print version number and exit\n\ + --vfd=DRIVER Use the specified virtual file driver\n\ + -x, --hexdump Show raw data in hexadecimal format\n\ \n\ OBJECTS\n\ Each object consists of an HDF5 file name optionally followed by a\n\ @@ -170,8 +182,6 @@ usage: %s [OPTIONS] [OBJECTS...]\n\ * Thursday, November 5, 1998 * * Modifications: - * Add _H5LS_CONVERT_SPECIAL_CHAR_ #ifdef section and make it not to - * convert special chars to visible chars. (Jonathan Kim 06/24/2010) * *------------------------------------------------------------------------- */ @@ -180,27 +190,6 @@ display_string(FILE *stream, const char *s, hbool_t escape_spaces) { int nprint=0; -#ifdef _H5LS_CONVERT_SPECIAL_CHAR_ - /*------------------------------------------------------------------- - * _H5LS_CONVERT_SPECIAL_CHAR_ is not defined, so this code section - * will not be compiled. - * This code section is due to be removed after verifying no problem - * at customer sites. (However we may keep it just for the future - * reference as it survived over ten years) - * - * Reason for Obsolete: - * This portion of code converts special characters or '\' to string, - * so when those characters are in object or attribute name, h5ls display - * as visible characters. - * However if a user come up with object or attribute name with special - * character in programming, this code takes away control over '\' - * (escape character) from the user and causes confusion for the output, - * also it’s not possible to handle all the cases in this way. - * This also causes discrepancy from how the string data saved in - * HDF5 file. - * Also other HDF tools don’t convert characters like this, so this - * causes inconsistent output among tools. - *-------------------------------------------------------------/ for (/*void*/; s && *s; s++) { switch (*s) { case '"': @@ -253,17 +242,6 @@ display_string(FILE *stream, const char *s, hbool_t escape_spaces) break; } } -#else - if (stream) - { - nprint = fprintf(stream,s); - } - else - { - nprint = strlen(s); - } -#endif /* _H5LS_CONVERT_SPECIAL_CHAR_ */ - return nprint; } @@ -1999,18 +1977,31 @@ list_lnk(const char *name, const H5L_info_t *linfo, void *_iter) { char *buf=NULL; iter_t *iter = (iter_t*)_iter; + int ret; + h5tool_link_info_t lnk_info; + + /* init linkinfo struct */ + memset(&lnk_info, 0, sizeof(h5tool_link_info_t)); + + /* if verbose, make H5tools_get_link_info() display more */ + if (verbose_g) + lnk_info.opt.msg_mode=1; /* Print the link's name, either full name or base name */ display_obj_name(stdout, iter, name, ""); switch(linfo->type) { case H5L_TYPE_SOFT: - if((buf = (char*)HDmalloc(linfo->u.val_size)) == NULL) + ret = H5tools_get_link_info(iter->fid, name, &lnk_info); + /* lnk_info.trg_path is malloced in H5tools_get_link_info() + * so it will be freed via buf later */ + buf = lnk_info.trg_path; + /* error */ + if (ret < 0) goto done; - - if(H5Lget_val(iter->fid, name, buf, linfo->u.val_size, H5P_DEFAULT) < 0) { - goto done; - } /* end if */ + /* no dangling link option given and detect dangling link */ + else if (no_dangling_link_g && ret == 0) + iter->symlink_list->dangle_link = TRUE; HDfputs("Soft Link {", stdout); HDfputs(buf, stdout); @@ -2058,10 +2049,16 @@ list_lnk(const char *name, const H5L_info_t *linfo, void *_iter) const char *filename; const char *path; - if((buf = (char*)HDmalloc(linfo->u.val_size)) == NULL) - goto done; - if(H5Lget_val(iter->fid, name, buf, linfo->u.val_size, H5P_DEFAULT) < 0) + ret = H5tools_get_link_info(iter->fid, name, &lnk_info); + /* lnk_info.trg_path is malloced in H5tools_get_link_info() + * so it will be freed via buf later */ + buf = lnk_info.trg_path; + /* error */ + if (ret < 0) goto done; + /* no dangling link option given and detect dangling link */ + else if (no_dangling_link_g && ret == 0) + iter->symlink_list->dangle_link = TRUE; if(H5Lunpack_elink_val(buf, linfo->u.val_size, NULL, &filename, &path) < 0) goto done; @@ -2134,9 +2131,9 @@ done: * * Purpose: Begins iteration on an object * - * Return: Success: EXIT_SUCCESS(0) - * - * Failure: EXIT_FAILURE(1) + * Return: + * Success: 0 + * Failure: -1 * * Programmer: Neil Fortner * Wednesday, August 21, 2008 @@ -2272,6 +2269,42 @@ get_width(void) return width; } +/*------------------------------------------------------------------------- + * Function: is_valid_args + * + * Purpose: check if command line arguments are valid + * + * Return: + * Success: TRUE (1) + * Failure: FALSE (0) + * + * Programmer: + * Jonathan Kim (06/15/2010) + * + *-------------------------------------------------------------------------*/ +static hbool_t +is_valid_args(void) +{ + herr_t ret = TRUE; + + if(recursive_g && grp_literal_g) + { + fprintf(stderr, "Error: 'recursive' option not compatible with 'group info' option!\n\n"); + ret = FALSE; + goto out; + } + + if(no_dangling_link_g && !follow_symlink_g) + { + fprintf(stderr, "Error: --no-dangling-links must be used along with --follow-symlinks option!\n\n"); + ret = FALSE; + goto out; + } + +out: + return ret; +} + /*------------------------------------------------------------------------- * Function: leave @@ -2323,7 +2356,7 @@ main(int argc, const char *argv[]) static char root_name[] = "/"; char drivername[50]; const char *preferred_driver = NULL; - int err_openfile = 0; + int err_exit = 0; h5tools_setprogname(PROGRAMNAME); h5tools_setstatus(EXIT_SUCCESS); @@ -2356,6 +2389,8 @@ main(int argc, const char *argv[]) show_errors_g = TRUE; } else if(!HDstrcmp(argv[argno], "--follow-symlinks")) { follow_symlink_g = TRUE; + } else if(!HDstrcmp(argv[argno], "--no-dangling-links")) { + no_dangling_link_g = TRUE; } else if(!HDstrcmp(argv[argno], "--external")) { follow_elink_g = TRUE; } else if(!HDstrcmp(argv[argno], "--full")) { @@ -2499,11 +2534,11 @@ main(int argc, const char *argv[]) } /* end if */ /* Check for conflicting arguments */ - if(recursive_g && grp_literal_g) { - fprintf(stderr, "Error: 'recursive' option not compatible with 'group info' option!\n\n"); + if (!is_valid_args()) + { usage(); leave(EXIT_FAILURE); - } /* end if */ + } /* Turn off HDF5's automatic error printing unless you're debugging h5ls */ if(!show_errors_g) @@ -2555,7 +2590,7 @@ main(int argc, const char *argv[]) if(file < 0) { fprintf(stderr, "%s: unable to open file\n", argv[argno-1]); HDfree(fname); - err_openfile = 1; + err_exit = 1; continue; } /* end if */ if(oname) { @@ -2590,6 +2625,7 @@ main(int argc, const char *argv[]) iter.gid = -1; iter.symlink_target = FALSE; iter.symlink_list = &symlink_list; + iter.symlink_list->dangle_link = FALSE; /* Initialize list of visited symbolic links */ symlink_list.nused = symlink_list.nalloc = 0; @@ -2630,9 +2666,13 @@ main(int argc, const char *argv[]) HDfree(symlink_list.objs[u].path); } HDfree(symlink_list.objs); + + /* if no-dangling-links option specified and dangling link found */ + if (no_dangling_link_g && iter.symlink_list->dangle_link) + err_exit = 1; } /* end while */ - if (err_openfile) + if (err_exit) leave(EXIT_FAILURE); else leave(EXIT_SUCCESS); diff --git a/tools/h5ls/testh5ls.sh.in b/tools/h5ls/testh5ls.sh.in index 2f681ac..34659e0 100644 --- a/tools/h5ls/testh5ls.sh.in +++ b/tools/h5ls/testh5ls.sh.in @@ -167,6 +167,18 @@ TOOLTEST textlinksrc-3-old.ls 0 -w80 -Er textlinksrc.h5/ext_link1 TOOLTEST textlinksrc-6-old.ls 0 -w80 -E textlinksrc.h5 TOOLTEST textlinksrc-7-old.ls 0 -w80 -E textlinksrc.h5/ext_link1 +# tests for no-dangling-links +# if this option is given on dangling link, h5ls should return exit code 1 +# when used alone , expect to print out help and return exit code 1 +TOOLTEST textlinksrc-nodangle-1.ls 1 -w80 --no-dangling-links textlinksrc.h5 +# external dangling link - expected exit code 1 +TOOLTEST textlinksrc-nodangle-2.ls 1 -w80 --follow-symlinks --no-dangling-links textlinksrc.h5 +# soft dangling link - expected exit code 1 +TOOLTEST tsoftlinks-nodangle-1.ls 1 -w80 --follow-symlinks --no-dangling-links tsoftlinks.h5 +# when used file with no dangling links - expected exit code 0 +TOOLTEST thlinks-nodangle-1.ls 0 -w80 --follow-symlinks --no-dangling-links thlink.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 cbf40a5..adec48a 100644 --- a/tools/h5repack/CMakeLists.txt +++ b/tools/h5repack/CMakeLists.txt @@ -53,8 +53,13 @@ IF (BUILD_TESTING) ADD_TEST (NAME testh5repack_detect_szip COMMAND $<TARGET_FILE:testh5repack_detect_szip>) IF (HDF5_ENABLE_SZIP_SUPPORT) - SET (passRegex "yes") - SET_TESTS_PROPERTIES (testh5repack_detect_szip PROPERTIES PASS_REGULAR_EXPRESSION "yes") + IF (HDF5_ENABLE_SZIP_ENCODING) + SET (passRegex "yes") + SET_TESTS_PROPERTIES (testh5repack_detect_szip PROPERTIES PASS_REGULAR_EXPRESSION "yes") + ELSE (HDF5_ENABLE_SZIP_ENCODING) + SET (passRegex "no") + SET_TESTS_PROPERTIES (testh5repack_detect_szip PROPERTIES PASS_REGULAR_EXPRESSION "no") + ENDIF (HDF5_ENABLE_SZIP_ENCODING) ELSE (HDF5_ENABLE_SZIP_SUPPORT) SET (passRegex "no") SET_TESTS_PROPERTIES (testh5repack_detect_szip PROPERTIES PASS_REGULAR_EXPRESSION "no") diff --git a/tools/h5repack/Makefile.in b/tools/h5repack/Makefile.in index ce18bb9..9fef88b 100644 --- a/tools/h5repack/Makefile.in +++ b/tools/h5repack/Makefile.in @@ -152,6 +152,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -177,6 +178,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ diff --git a/tools/h5stat/Makefile.in b/tools/h5stat/Makefile.in index 3d69400..35be805 100644 --- a/tools/h5stat/Makefile.in +++ b/tools/h5stat/Makefile.in @@ -161,6 +161,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -186,6 +187,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ diff --git a/tools/lib/Makefile.in b/tools/lib/Makefile.in index 7568a89..fe7fc52 100644 --- a/tools/lib/Makefile.in +++ b/tools/lib/Makefile.in @@ -131,6 +131,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -156,6 +157,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ diff --git a/tools/lib/h5tools_utils.c b/tools/lib/h5tools_utils.c index ca1caa1..04d375d 100644 --- a/tools/lib/h5tools_utils.c +++ b/tools/lib/h5tools_utils.c @@ -638,7 +638,6 @@ tmpfile(void) * Patameters: * - [IN] fileid : link file id * - [IN] linkpath : link path - * - [OUT] h5li : link's info (H5L_info_t) * - [OUT] link_info: returning target object info (h5tool_link_info_t) * * Return: @@ -656,7 +655,7 @@ tmpfile(void) *-------------------------------------------------------------------------*/ int H5tools_get_link_info(hid_t file_id, const char * linkpath, h5tool_link_info_t *link_info) { - int Ret = -1; /* init to fail */ + int ret = -1; /* init to fail */ htri_t l_ret; H5O_info_t trg_oinfo; hid_t fapl; @@ -684,7 +683,7 @@ int H5tools_get_link_info(hid_t file_id, const char * linkpath, h5tool_link_info /* given path is hard link (object) */ if (link_info->linfo.type == H5L_TYPE_HARD) { - Ret = 2; + ret = 2; goto out; } @@ -721,7 +720,7 @@ int H5tools_get_link_info(hid_t file_id, const char * linkpath, h5tool_link_info /* detect dangling link */ if(l_ret == FALSE) { - Ret = 0; + ret = 0; goto out; } /* function failed */ @@ -750,7 +749,7 @@ int H5tools_get_link_info(hid_t file_id, const char * linkpath, h5tool_link_info link_info->trg_type = trg_oinfo.type; /* succeed */ - Ret = 1; + ret = 1; out: if (link_info->linfo.type == H5L_TYPE_EXTERNAL) { @@ -758,7 +757,7 @@ out: H5Pclose(lapl); } - return Ret; + return ret; } /*------------------------------------------------------------------------- diff --git a/tools/misc/Makefile.in b/tools/misc/Makefile.in index 4a2c7a8..eb60cd2 100644 --- a/tools/misc/Makefile.in +++ b/tools/misc/Makefile.in @@ -186,6 +186,7 @@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ +CXX_VERSION = @CXX_VERSION@ CYGPATH_W = @CYGPATH_W@ DEBUG_PKG = @DEBUG_PKG@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@ @@ -211,6 +212,7 @@ FC = @FC@ FCFLAGS = @FCFLAGS@ FCFLAGS_f90 = @FCFLAGS_f90@ FCLIBS = @FCLIBS@ +FC_VERSION = @FC_VERSION@ FGREP = @FGREP@ FILTERS = @FILTERS@ FSEARCH_DIRS = @FSEARCH_DIRS@ diff --git a/tools/testfiles/help-1.ls b/tools/testfiles/help-1.ls index 1b5de0c..6a2904e 100644 --- a/tools/testfiles/help-1.ls +++ b/tools/testfiles/help-1.ls @@ -3,28 +3,38 @@ ############################# usage: h5ls [OPTIONS] [OBJECTS...] OPTIONS - -h, -?, --help Print a usage message and exit - -a, --address Print addresses for raw data - -d, --data Print the values of datasets - -e, --errors Show all HDF5 error reporting - --follow-symlinks Follow symbolic links (soft links and external links) - to display target object information. - Without this option, h5ls identifies a symbolic link - as a soft link or external link and prints the value - assigned to the symbolic link; it does not provide any - information regarding the target object or determine - whether the link is a dangling link. - -f, --full Print full path names instead of base names - -g, --group Show information about a group, not its contents - -l, --label Label members of compound datasets - -r, --recursive List all groups recursively, avoiding cycles - -s, --string Print 1-byte integer datasets as ASCII - -S, --simple Use a machine-readable output format - -wN, --width=N Set the number of columns of output - -v, --verbose Generate more verbose output - -V, --version Print version number and exit - --vfd=DRIVER Use the specified virtual file driver - -x, --hexdump Show raw data in hexadecimal format + -h, -?, --help Print a usage message and exit + -a, --address Print addresses for raw data + -d, --data Print the values of datasets + -e, --errors Show all HDF5 error reporting + --follow-symlinks + Follow symbolic links (soft links and external links) + to display target object information. + Without this option, h5ls identifies a symbolic link + as a soft link or external link and prints the value + assigned to the symbolic link; it does not provide any + information regarding the target object or determine + whether the link is a dangling link. + --no-dangling-links + Must be used with --follow-symlinks option; + otherwise, h5ls shows error message and returns an exit + code of 1. + Check for any symbolic links (soft links or external links) + that do not resolve to an existing object (dataset, group, + or named datatype). + If any dangling link is found, this situation is treated + as an error and h5ls returns an exit code of 1. + -f, --full Print full path names instead of base names + -g, --group Show information about a group, not its contents + -l, --label Label members of compound datasets + -r, --recursive List all groups recursively, avoiding cycles + -s, --string Print 1-byte integer datasets as ASCII + -S, --simple Use a machine-readable output format + -wN, --width=N Set the number of columns of output + -v, --verbose Generate more verbose output + -V, --version Print version number and exit + --vfd=DRIVER Use the specified virtual file driver + -x, --hexdump Show raw data in hexadecimal format OBJECTS Each object consists of an HDF5 file name optionally followed by a diff --git a/tools/testfiles/help-2.ls b/tools/testfiles/help-2.ls index 6f7e75d..92163d1 100644 --- a/tools/testfiles/help-2.ls +++ b/tools/testfiles/help-2.ls @@ -3,28 +3,38 @@ ############################# usage: h5ls [OPTIONS] [OBJECTS...] OPTIONS - -h, -?, --help Print a usage message and exit - -a, --address Print addresses for raw data - -d, --data Print the values of datasets - -e, --errors Show all HDF5 error reporting - --follow-symlinks Follow symbolic links (soft links and external links) - to display target object information. - Without this option, h5ls identifies a symbolic link - as a soft link or external link and prints the value - assigned to the symbolic link; it does not provide any - information regarding the target object or determine - whether the link is a dangling link. - -f, --full Print full path names instead of base names - -g, --group Show information about a group, not its contents - -l, --label Label members of compound datasets - -r, --recursive List all groups recursively, avoiding cycles - -s, --string Print 1-byte integer datasets as ASCII - -S, --simple Use a machine-readable output format - -wN, --width=N Set the number of columns of output - -v, --verbose Generate more verbose output - -V, --version Print version number and exit - --vfd=DRIVER Use the specified virtual file driver - -x, --hexdump Show raw data in hexadecimal format + -h, -?, --help Print a usage message and exit + -a, --address Print addresses for raw data + -d, --data Print the values of datasets + -e, --errors Show all HDF5 error reporting + --follow-symlinks + Follow symbolic links (soft links and external links) + to display target object information. + Without this option, h5ls identifies a symbolic link + as a soft link or external link and prints the value + assigned to the symbolic link; it does not provide any + information regarding the target object or determine + whether the link is a dangling link. + --no-dangling-links + Must be used with --follow-symlinks option; + otherwise, h5ls shows error message and returns an exit + code of 1. + Check for any symbolic links (soft links or external links) + that do not resolve to an existing object (dataset, group, + or named datatype). + If any dangling link is found, this situation is treated + as an error and h5ls returns an exit code of 1. + -f, --full Print full path names instead of base names + -g, --group Show information about a group, not its contents + -l, --label Label members of compound datasets + -r, --recursive List all groups recursively, avoiding cycles + -s, --string Print 1-byte integer datasets as ASCII + -S, --simple Use a machine-readable output format + -wN, --width=N Set the number of columns of output + -v, --verbose Generate more verbose output + -V, --version Print version number and exit + --vfd=DRIVER Use the specified virtual file driver + -x, --hexdump Show raw data in hexadecimal format OBJECTS Each object consists of an HDF5 file name optionally followed by a diff --git a/tools/testfiles/help-3.ls b/tools/testfiles/help-3.ls index 939c8eb..7199815 100644 --- a/tools/testfiles/help-3.ls +++ b/tools/testfiles/help-3.ls @@ -3,28 +3,38 @@ ############################# usage: h5ls [OPTIONS] [OBJECTS...] OPTIONS - -h, -?, --help Print a usage message and exit - -a, --address Print addresses for raw data - -d, --data Print the values of datasets - -e, --errors Show all HDF5 error reporting - --follow-symlinks Follow symbolic links (soft links and external links) - to display target object information. - Without this option, h5ls identifies a symbolic link - as a soft link or external link and prints the value - assigned to the symbolic link; it does not provide any - information regarding the target object or determine - whether the link is a dangling link. - -f, --full Print full path names instead of base names - -g, --group Show information about a group, not its contents - -l, --label Label members of compound datasets - -r, --recursive List all groups recursively, avoiding cycles - -s, --string Print 1-byte integer datasets as ASCII - -S, --simple Use a machine-readable output format - -wN, --width=N Set the number of columns of output - -v, --verbose Generate more verbose output - -V, --version Print version number and exit - --vfd=DRIVER Use the specified virtual file driver - -x, --hexdump Show raw data in hexadecimal format + -h, -?, --help Print a usage message and exit + -a, --address Print addresses for raw data + -d, --data Print the values of datasets + -e, --errors Show all HDF5 error reporting + --follow-symlinks + Follow symbolic links (soft links and external links) + to display target object information. + Without this option, h5ls identifies a symbolic link + as a soft link or external link and prints the value + assigned to the symbolic link; it does not provide any + information regarding the target object or determine + whether the link is a dangling link. + --no-dangling-links + Must be used with --follow-symlinks option; + otherwise, h5ls shows error message and returns an exit + code of 1. + Check for any symbolic links (soft links or external links) + that do not resolve to an existing object (dataset, group, + or named datatype). + If any dangling link is found, this situation is treated + as an error and h5ls returns an exit code of 1. + -f, --full Print full path names instead of base names + -g, --group Show information about a group, not its contents + -l, --label Label members of compound datasets + -r, --recursive List all groups recursively, avoiding cycles + -s, --string Print 1-byte integer datasets as ASCII + -S, --simple Use a machine-readable output format + -wN, --width=N Set the number of columns of output + -v, --verbose Generate more verbose output + -V, --version Print version number and exit + --vfd=DRIVER Use the specified virtual file driver + -x, --hexdump Show raw data in hexadecimal format OBJECTS Each object consists of an HDF5 file name optionally followed by a diff --git a/tools/testfiles/textlinksrc-2-old.ls b/tools/testfiles/textlinksrc-2-old.ls index acdc3d2..403a1d2 100644 --- a/tools/testfiles/textlinksrc-2-old.ls +++ b/tools/testfiles/textlinksrc-2-old.ls @@ -3,6 +3,6 @@ ############################# Opened "textlinksrc.h5" with sec2 driver. ext_link5 External Link {textlinktar.h5//empty_group} {Group - Location: 3:1832 + Location: 5:1832 Links: 1 } diff --git a/tools/testfiles/textlinksrc-2.ls b/tools/testfiles/textlinksrc-2.ls index ea99be8..1e92f59 100644 --- a/tools/testfiles/textlinksrc-2.ls +++ b/tools/testfiles/textlinksrc-2.ls @@ -3,6 +3,6 @@ ############################# Opened "textlinksrc.h5" with sec2 driver. ext_link5 External Link {textlinktar.h5//empty_group} {Group - Location: 3:1832 + Location: 5:1832 Links: 1 } diff --git a/tools/testfiles/textlinksrc-nodangle-1.ls b/tools/testfiles/textlinksrc-nodangle-1.ls new file mode 100644 index 0000000..8a6144b --- /dev/null +++ b/tools/testfiles/textlinksrc-nodangle-1.ls @@ -0,0 +1,56 @@ +############################# + output for 'h5ls -w80 --no-dangling-links textlinksrc.h5' +############################# +Error: --no-dangling-links must be used along with --follow-symlinks option! + +usage: h5ls [OPTIONS] [OBJECTS...] + OPTIONS + -h, -?, --help Print a usage message and exit + -a, --address Print addresses for raw data + -d, --data Print the values of datasets + -e, --errors Show all HDF5 error reporting + --follow-symlinks + Follow symbolic links (soft links and external links) + to display target object information. + Without this option, h5ls identifies a symbolic link + as a soft link or external link and prints the value + assigned to the symbolic link; it does not provide any + information regarding the target object or determine + whether the link is a dangling link. + --no-dangling-links + Must be used with --follow-symlinks option; + otherwise, h5ls shows error message and returns an exit + code of 1. + Check for any symbolic links (soft links or external links) + that do not resolve to an existing object (dataset, group, + or named datatype). + If any dangling link is found, this situation is treated + as an error and h5ls returns an exit code of 1. + -f, --full Print full path names instead of base names + -g, --group Show information about a group, not its contents + -l, --label Label members of compound datasets + -r, --recursive List all groups recursively, avoiding cycles + -s, --string Print 1-byte integer datasets as ASCII + -S, --simple Use a machine-readable output format + -wN, --width=N Set the number of columns of output + -v, --verbose Generate more verbose output + -V, --version Print version number and exit + --vfd=DRIVER Use the specified virtual file driver + -x, --hexdump Show raw data in hexadecimal format + + OBJECTS + Each object consists of an HDF5 file name optionally followed by a + slash and an object name within the file (if no object is specified + within the file then the contents of the root group are displayed). + The file name may include a printf(3C) integer format such as + "%05d" to open a file family. + + Deprecated Options + The following options have been deprecated in HDF5. While they remain + available, they have been superseded as indicated and may be removed + from HDF5 in the future. Use the indicated replacement option in all + new work; where possible, existing scripts, et cetera, should also be + updated to use the replacement option. + + -E or --external Follow external links. + Replaced by --follow-symlinks. diff --git a/tools/testfiles/textlinksrc-nodangle-2.ls b/tools/testfiles/textlinksrc-nodangle-2.ls new file mode 100644 index 0000000..4713849 --- /dev/null +++ b/tools/testfiles/textlinksrc-nodangle-2.ls @@ -0,0 +1,8 @@ +############################# + output for 'h5ls -w80 --follow-symlinks --no-dangling-links textlinksrc.h5' +############################# +ext_link1 External Link {textlinktar.h5//group} {Group} +ext_link2 External Link {textlinktar.h5//dset} {Dataset {6}} +ext_link3 External Link {textlinktar.h5//type} {Type} +ext_link4 External Link {textlinktar.h5//group/elink_t2} {**NOT FOUND**} +ext_link5 External Link {textlinktar.h5//empty_group} {Group} diff --git a/tools/testfiles/tgroup-1.ls b/tools/testfiles/tgroup-1.ls index 8d38e0f..03a70fd 100644 --- a/tools/testfiles/tgroup-1.ls +++ b/tools/testfiles/tgroup-1.ls @@ -5,28 +5,38 @@ Error: 'recursive' option not compatible with 'group info' option! usage: h5ls [OPTIONS] [OBJECTS...] OPTIONS - -h, -?, --help Print a usage message and exit - -a, --address Print addresses for raw data - -d, --data Print the values of datasets - -e, --errors Show all HDF5 error reporting - --follow-symlinks Follow symbolic links (soft links and external links) - to display target object information. - Without this option, h5ls identifies a symbolic link - as a soft link or external link and prints the value - assigned to the symbolic link; it does not provide any - information regarding the target object or determine - whether the link is a dangling link. - -f, --full Print full path names instead of base names - -g, --group Show information about a group, not its contents - -l, --label Label members of compound datasets - -r, --recursive List all groups recursively, avoiding cycles - -s, --string Print 1-byte integer datasets as ASCII - -S, --simple Use a machine-readable output format - -wN, --width=N Set the number of columns of output - -v, --verbose Generate more verbose output - -V, --version Print version number and exit - --vfd=DRIVER Use the specified virtual file driver - -x, --hexdump Show raw data in hexadecimal format + -h, -?, --help Print a usage message and exit + -a, --address Print addresses for raw data + -d, --data Print the values of datasets + -e, --errors Show all HDF5 error reporting + --follow-symlinks + Follow symbolic links (soft links and external links) + to display target object information. + Without this option, h5ls identifies a symbolic link + as a soft link or external link and prints the value + assigned to the symbolic link; it does not provide any + information regarding the target object or determine + whether the link is a dangling link. + --no-dangling-links + Must be used with --follow-symlinks option; + otherwise, h5ls shows error message and returns an exit + code of 1. + Check for any symbolic links (soft links or external links) + that do not resolve to an existing object (dataset, group, + or named datatype). + If any dangling link is found, this situation is treated + as an error and h5ls returns an exit code of 1. + -f, --full Print full path names instead of base names + -g, --group Show information about a group, not its contents + -l, --label Label members of compound datasets + -r, --recursive List all groups recursively, avoiding cycles + -s, --string Print 1-byte integer datasets as ASCII + -S, --simple Use a machine-readable output format + -wN, --width=N Set the number of columns of output + -v, --verbose Generate more verbose output + -V, --version Print version number and exit + --vfd=DRIVER Use the specified virtual file driver + -x, --hexdump Show raw data in hexadecimal format OBJECTS Each object consists of an HDF5 file name optionally followed by a diff --git a/tools/testfiles/thlinks-nodangle-1.ls b/tools/testfiles/thlinks-nodangle-1.ls new file mode 100644 index 0000000..37ba6b0 --- /dev/null +++ b/tools/testfiles/thlinks-nodangle-1.ls @@ -0,0 +1,7 @@ +############################# + output for 'h5ls -w80 --follow-symlinks --no-dangling-links thlink.h5' +############################# +dset1 Dataset {5} +g1 Group +g2 Group +g3 Group, same as / diff --git a/tools/testfiles/tsoftlinks-nodangle-1.ls b/tools/testfiles/tsoftlinks-nodangle-1.ls new file mode 100644 index 0000000..6d639b7 --- /dev/null +++ b/tools/testfiles/tsoftlinks-nodangle-1.ls @@ -0,0 +1,13 @@ +############################# + output for 'h5ls -w80 --follow-symlinks --no-dangling-links tsoftlinks.h5' +############################# +dset1 Dataset {4, 2} +dset2 Dataset {4, 2} +dtype Type +group1 Group +group_empty Group +soft_dangle Soft Link {not_yet} {**NOT FOUND**} +soft_dset1 Soft Link {/dset1} {Dataset {4, 2}} +soft_dtype Soft Link {/dtype} {Type} +soft_empty_grp Soft Link {/group_empty} {Group} +soft_group1 Soft Link {/group1} {Group} diff --git a/vms/src/h5pubconf.h b/vms/src/h5pubconf.h index c8665f1..57264ac 100644 --- a/vms/src/h5pubconf.h +++ b/vms/src/h5pubconf.h @@ -489,13 +489,13 @@ #define H5_PACKAGE_NAME "HDF5" /* Define to the full name and version of this package. */ -#define H5_PACKAGE_STRING "HDF5 1.9.73-FA_a4" +#define H5_PACKAGE_STRING "HDF5 1.9.75-FA_a4" /* Define to the one symbol short name of this package. */ #define H5_PACKAGE_TARNAME "hdf5" /* Define to the version of this package. */ -#define H5_PACKAGE_VERSION "1.9.73-FA_a4" +#define H5_PACKAGE_VERSION "1.9.75-FA_a4" /* Width for printf() for type `long long' or `__int64', use `ll' */ #define H5_PRINTF_LL_WIDTH "ll" @@ -651,7 +651,7 @@ /* #undef H5_USING_MEMCHECKER */ /* Version number of package */ -#define H5_VERSION "1.9.73-FA_a4" +#define H5_VERSION "1.9.75-FA_a4" /* Define if vsnprintf() returns the correct value for formatted strings that don't fit into size allowed */ diff --git a/windows/src/H5pubconf.h b/windows/src/H5pubconf.h index 926c63a..b7d2ad2 100755 --- a/windows/src/H5pubconf.h +++ b/windows/src/H5pubconf.h @@ -478,13 +478,13 @@ #define H5_PACKAGE_NAME "HDF5" /* Define to the full name and version of this package. */ -#define H5_PACKAGE_STRING "HDF5 1.9.73-FA_a4" +#define H5_PACKAGE_STRING "HDF5 1.9.75-FA_a4" /* Define to the one symbol short name of this package. */ #define H5_PACKAGE_TARNAME "hdf5" /* Define to the version of this package. */ -#define H5_PACKAGE_VERSION "1.9.73-FA_a4" +#define H5_PACKAGE_VERSION "1.9.75-FA_a4" /* Width for printf() for type `long long' or `__int64', use `ll' */ #define H5_PRINTF_LL_WIDTH "I64" @@ -641,7 +641,7 @@ /* #undef H5_USING_MEMCHECKER */ /* Version number of package */ -#define H5_VERSION "1.9.73-FA_a4" +#define H5_VERSION "1.9.75-FA_a4" /* Define if vsnprintf() returns the correct value for formatted strings that don't fit into size allowed */ diff --git a/windows/tools/h5ls/testh5ls.bat b/windows/tools/h5ls/testh5ls.bat index 7fa931b..953216d 100644 --- a/windows/tools/h5ls/testh5ls.bat +++ b/windows/tools/h5ls/testh5ls.bat @@ -199,6 +199,17 @@ rem ############################################################################ call :tooltest textlinksrc-6-old.ls 0 -w80 -E textlinksrc.h5
call :tooltest textlinksrc-7-old.ls 0 -w80 -E textlinksrc.h5/ext_link1
+ rem tests for no-dangling-links
+ rem if this option is given on dangling link, h5ls should return exit code 1
+ rem when used alone , expect to print out help and return exit code 1
+ call :tooltest textlinksrc-nodangle-1.ls 1 -w80 --no-dangling-links textlinksrc.h5
+ rem external dangling link - expected exit code 1
+ call :tooltest textlinksrc-nodangle-2.ls 1 -w80 --follow-symlinks --no-dangling-links textlinksrc.h5
+ rem soft dangling link - expected exit code 1
+ call :tooltest tsoftlinks-nodangle-1.ls 1 -w80 --follow-symlinks --no-dangling-links tsoftlinks.h5
+ rem when used file with no dangling links - expected exit code 0
+ call :tooltest thlinks-nodangle-1.ls 0 -w80 --follow-symlinks --no-dangling-links thlink.h5
+
rem tests for hard links
call :tooltest thlink-1.ls 0 -w80 thlink.h5
|