diff options
author | Dana Robinson <derobins@hdfgroup.org> | 2022-04-06 00:50:57 (GMT) |
---|---|---|
committer | Dana Robinson <derobins@hdfgroup.org> | 2022-04-06 00:50:57 (GMT) |
commit | 7e2d23d2a15509c3753d7c8d2571f1360a834087 (patch) | |
tree | e4fd90365661429a6042690633dfdbd779ec25bb /src | |
parent | 715cf1a29b14abd81b4a03421fc742d6f4542fd0 (diff) | |
parent | da562164ce4defaf84ff98869d317e7751bcc6f3 (diff) | |
download | hdf5-7e2d23d2a15509c3753d7c8d2571f1360a834087.zip hdf5-7e2d23d2a15509c3753d7c8d2571f1360a834087.tar.gz hdf5-7e2d23d2a15509c3753d7c8d2571f1360a834087.tar.bz2 |
Merge remote-tracking branch 'canonical/develop' into feature/onion_vfd
Diffstat (limited to 'src')
268 files changed, 16539 insertions, 8844 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9a313a0..b1bd4a2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -241,6 +241,7 @@ set (H5FD_SOURCES ${HDF5_SRC_DIR}/H5FDmpio.c ${HDF5_SRC_DIR}/H5FDmulti.c ${HDF5_SRC_DIR}/H5FDonion.c + ${HDF5_SRC_DIR}/H5FDperform.c ${HDF5_SRC_DIR}/H5FDros3.c ${HDF5_SRC_DIR}/H5FDs3comms.c ${HDF5_SRC_DIR}/H5FDsec2.c @@ -378,14 +379,6 @@ set (H5HL_HDRS IDE_GENERATED_PROPERTIES ("H5HL" "${H5HL_HDRS}" "${H5HL_SOURCES}" ) -set (H5HP_SOURCES - ${HDF5_SRC_DIR}/H5HP.c -) -set (H5HP_HDRS -) -IDE_GENERATED_PROPERTIES ("H5HP" "${H5HP_HDRS}" "${H5HP_SOURCES}" ) - - set (H5I_SOURCES ${HDF5_SRC_DIR}/H5I.c ${HDF5_SRC_DIR}/H5Idbg.c @@ -442,16 +435,6 @@ set (H5MM_HDRS IDE_GENERATED_PROPERTIES ("H5MM" "${H5MM_HDRS}" "${H5MM_SOURCES}" ) -set (H5MP_SOURCES - ${HDF5_SRC_DIR}/H5MP.c - ${HDF5_SRC_DIR}/H5MPtest.c -) - -set (H5MP_HDRS -) -IDE_GENERATED_PROPERTIES ("H5MP" "${H5MP_HDRS}" "${H5MP_SOURCES}" ) - - set (H5O_SOURCES ${HDF5_SRC_DIR}/H5O.c ${HDF5_SRC_DIR}/H5Oainfo.c @@ -750,7 +733,6 @@ set (H5_MODULE_HEADERS ${HDF5_SRC_DIR}/H5Lmodule.h ${HDF5_SRC_DIR}/H5Mmodule.h ${HDF5_SRC_DIR}/H5MFmodule.h - ${HDF5_SRC_DIR}/H5MPmodule.h ${HDF5_SRC_DIR}/H5Omodule.h ${HDF5_SRC_DIR}/H5Pmodule.h ${HDF5_SRC_DIR}/H5PBmodule.h @@ -788,13 +770,11 @@ set (common_SRCS ${H5HF_SOURCES} ${H5HG_SOURCES} ${H5HL_SOURCES} - ${H5HP_SOURCES} ${H5I_SOURCES} ${H5L_SOURCES} ${H5M_SOURCES} ${H5MF_SOURCES} ${H5MM_SOURCES} - ${H5MP_SOURCES} ${H5O_SOURCES} ${H5P_SOURCES} ${H5PB_SOURCES} @@ -837,7 +817,6 @@ set (H5_PUBLIC_HEADERS ${H5M_HDRS} ${H5MF_HDRS} ${H5MM_HDRS} - ${H5MP_HDRS} ${H5O_HDRS} ${H5P_HDRS} ${H5PB_HDRS} @@ -896,6 +875,7 @@ set (H5_PRIVATE_HEADERS ${HDF5_SRC_DIR}/H5FAprivate.h ${HDF5_SRC_DIR}/H5FDmirror_priv.h + ${HDF5_SRC_DIR}/H5FDonion_priv.h ${HDF5_SRC_DIR}/H5FDpkg.h ${HDF5_SRC_DIR}/H5FDprivate.h @@ -918,8 +898,6 @@ set (H5_PRIVATE_HEADERS ${HDF5_SRC_DIR}/H5HLpkg.h ${HDF5_SRC_DIR}/H5HLprivate.h - ${HDF5_SRC_DIR}/H5HPprivate.h - ${HDF5_SRC_DIR}/H5Ipkg.h ${HDF5_SRC_DIR}/H5Iprivate.h @@ -934,9 +912,6 @@ set (H5_PRIVATE_HEADERS ${HDF5_SRC_DIR}/H5MMprivate.h - ${HDF5_SRC_DIR}/H5MPpkg.h - ${HDF5_SRC_DIR}/H5MPprivate.h - ${HDF5_SRC_DIR}/H5Opkg.h ${HDF5_SRC_DIR}/H5Oprivate.h ${HDF5_SRC_DIR}/H5Oshared.h @@ -1057,20 +1032,23 @@ if (LOCAL_BATCH_TEST) endif () endif () +#### make the H5detect program set (lib_prog_deps) -if (NOT EXISTS "${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c") - add_executable (H5detect ${HDF5_SRC_DIR}/H5detect.c) - target_include_directories (H5detect PRIVATE "${HDF5_SRC_DIR};${HDF5_SRC_BINARY_DIR};$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_INCLUDE_DIRS}>") - target_compile_definitions(H5detect PUBLIC ${HDF_EXTRA_C_FLAGS} ${HDF_EXTRA_FLAGS}) - TARGET_C_PROPERTIES (H5detect STATIC) - target_link_libraries (H5detect - PRIVATE "$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_LIBRARIES}>" $<$<OR:$<PLATFORM_ID:Windows>,$<PLATFORM_ID:MinGW>>:ws2_32.lib> - ) - target_compile_options(H5detect - PRIVATE "$<$<PLATFORM_ID:Emscripten>:-O0>" - ) - set (lib_prog_deps ${lib_prog_deps} H5detect) +add_executable (H5detect ${HDF5_SRC_DIR}/H5detect.c) +target_include_directories (H5detect PRIVATE "${HDF5_SRC_DIR};${HDF5_SRC_BINARY_DIR};$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_INCLUDE_DIRS}>") +target_compile_definitions(H5detect PUBLIC ${HDF_EXTRA_C_FLAGS} ${HDF_EXTRA_FLAGS}) +TARGET_C_PROPERTIES (H5detect STATIC) +target_link_libraries (H5detect + PRIVATE "$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_LIBRARIES}>" $<$<OR:$<PLATFORM_ID:Windows>,$<PLATFORM_ID:MinGW>>:ws2_32.lib> +) +target_compile_options(H5detect + PRIVATE "$<$<PLATFORM_ID:Emscripten>:-O0>" +) +set (lib_prog_deps ${lib_prog_deps} H5detect) +# check if a pregenerated H5Tinit.c file is present +if (NOT EXISTS "${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c") + # execute the H5detect program if (HDF5_BATCH_H5DETECT) configure_file ( ${HDF5_SOURCE_DIR}/bin/batch/${HDF5_BATCH_H5DETECT_SCRIPT}.in.cmake @@ -1078,9 +1056,9 @@ if (NOT EXISTS "${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c") ) add_custom_command ( OUTPUT gen_SRCS.stamp1 + BYPRODUCTS H5Tinit.c COMMAND ${HDF5_BATCH_CMD} ARGS ${HDF5_BINARY_DIR}/${HDF5_BATCH_H5DETECT_SCRIPT} - BYPRODUCTS H5Tinit.c gen_SRCS.stamp1 COMMAND ${CMAKE_COMMAND} ARGS -E echo "Executed batch command to create H5Tinit.c" COMMAND ${CMAKE_COMMAND} @@ -1091,31 +1069,30 @@ if (NOT EXISTS "${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c") add_custom_target (gen_H5Tinit COMMAND ${CMAKE_COMMAND} -P ${HDF5_SOURCE_DIR}/config/cmake/wait_H5Tinit.cmake ) - set_source_files_properties (${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c PROPERTIES GENERATED TRUE) else () - add_custom_command (TARGET H5detect POST_BUILD + add_custom_command ( + OUTPUT gen_SRCS.stamp1 + BYPRODUCTS H5Tinit.c COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:H5detect> ARGS H5Tinit.c - BYPRODUCTS H5Tinit.c gen_SRCS.stamp1 COMMAND ${CMAKE_COMMAND} ARGS -E touch gen_SRCS.stamp1 DEPENDS H5detect WORKING_DIRECTORY ${HDF5_GENERATED_SOURCE_DIR} COMMENT "Create H5Tinit.c" ) - set_source_files_properties (${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c PROPERTIES GENERATED TRUE) if (BUILD_SHARED_LIBS) - add_custom_command (TARGET H5detect POST_BUILD + add_custom_command ( + OUTPUT shared/shared_gen_SRCS.stamp1 + BYPRODUCTS shared/H5Tinit.c COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different H5Tinit.c shared/H5Tinit.c - BYPRODUCTS shared/H5Tinit.c shared/shared_gen_SRCS.stamp1 COMMAND ${CMAKE_COMMAND} ARGS -E touch shared/shared_gen_SRCS.stamp1 - DEPENDS H5detect H5Tinit.c + DEPENDS H5detect gen_SRCS.stamp1 WORKING_DIRECTORY ${HDF5_GENERATED_SOURCE_DIR} COMMENT "Copy H5Tinit.c to shared folder" ) - set_source_files_properties (${HDF5_GENERATED_SOURCE_DIR}/shared/H5Tinit.c PROPERTIES GENERATED TRUE) endif () endif () else () @@ -1131,16 +1108,15 @@ else () if (BUILD_SHARED_LIBS) add_custom_command ( OUTPUT shared/shared_gen_SRCS.stamp1 + BYPRODUCTS shared/H5Tinit.c COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different H5Tinit.c shared/H5Tinit.c - BYPRODUCTS shared/H5Tinit.c shared/shared_gen_SRCS.stamp1 COMMAND ${CMAKE_COMMAND} ARGS -E touch shared/shared_gen_SRCS.stamp1 - DEPENDS H5Tinit.c + DEPENDS H5Tinit.c gen_SRCS.stamp1 WORKING_DIRECTORY ${HDF5_GENERATED_SOURCE_DIR} COMMENT "Copy existing H5Tinit.c to shared folder" ) - set_source_files_properties (${HDF5_GENERATED_SOURCE_DIR}/shared/H5Tinit.c PROPERTIES GENERATED TRUE) endif () endif () @@ -1151,6 +1127,7 @@ if (HDF5_ENABLE_FORMATTERS) clang_format (HDF5_SRC_DETECT_FORMAT ${HDF5_SRC_DIR}/H5detect.c) endif () +# make the H5make_libsettings program add_executable (H5make_libsettings ${HDF5_SRC_DIR}/H5make_libsettings.c) target_include_directories (H5make_libsettings PRIVATE "${HDF5_SRC_DIR};${HDF5_SRC_BINARY_DIR};$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_INCLUDE_DIRS}>") target_compile_definitions(H5make_libsettings PUBLIC ${HDF_EXTRA_C_FLAGS} ${HDF_EXTRA_FLAGS}) @@ -1170,10 +1147,12 @@ if (HDF5_ENABLE_FORMATTERS) clang_format (HDF5_SRC_LIBSETTINGS_FORMAT H5make_libsettings) endif () -add_custom_command (TARGET H5make_libsettings POST_BUILD +# execute the H5make_libsettings program +add_custom_command ( + OUTPUT gen_SRCS.stamp2 + BYPRODUCTS H5lib_settings.c COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:H5make_libsettings> ARGS H5lib_settings.c - BYPRODUCTS H5lib_settings.c gen_SRCS.stamp2 COMMAND ${CMAKE_COMMAND} ARGS -E touch gen_SRCS.stamp2 DEPENDS H5make_libsettings @@ -1182,17 +1161,17 @@ add_custom_command (TARGET H5make_libsettings POST_BUILD ) set_source_files_properties (${HDF5_SRC_BINARY_DIR}/H5lib_settings.c PROPERTIES GENERATED TRUE) if (BUILD_SHARED_LIBS) - add_custom_command (TARGET H5make_libsettings POST_BUILD + add_custom_command ( + OUTPUT shared/shared_gen_SRCS.stamp2 + BYPRODUCTS shared/H5lib_settings.c COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different H5lib_settings.c shared/H5lib_settings.c - BYPRODUCTS shared/H5lib_settings.c shared/shared_gen_SRCS.stamp2 COMMAND ${CMAKE_COMMAND} ARGS -E touch shared/shared_gen_SRCS.stamp2 - DEPENDS H5make_libsettings H5lib_settings.c + DEPENDS H5make_libsettings gen_SRCS.stamp2 WORKING_DIRECTORY ${HDF5_SRC_BINARY_DIR} COMMENT "Copy H5lib_settings.c to shared folder" ) - set_source_files_properties (${HDF5_SRC_BINARY_DIR}/shared/H5lib_settings.c PROPERTIES GENERATED TRUE) endif () ## all_packages="AC,B,B2,D,F,FA,FL,FS,HL,I,O,S,ST,T,Z" @@ -1205,7 +1184,7 @@ option (HDF5_ENABLE_DEBUG_APIS "Turn on extra debug output in all packages" OFF) if (NOT ONLY_SHARED_LIBS) set (gen_SRCS ${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c ${HDF5_SRC_BINARY_DIR}/H5lib_settings.c) add_custom_target (gen_${HDF5_LIB_TARGET} ALL - DEPENDS ${lib_prog_deps} ${gen_SRCS} ${HDF5_GENERATED_SOURCE_DIR}/gen_SRCS.stamp1 ${HDF5_SRC_BINARY_DIR}/gen_SRCS.stamp2 + DEPENDS ${lib_prog_deps} ${HDF5_GENERATED_SOURCE_DIR}/gen_SRCS.stamp1 ${HDF5_SRC_BINARY_DIR}/gen_SRCS.stamp2 COMMENT "Generation target files" ) @@ -1244,7 +1223,7 @@ endif () if (BUILD_SHARED_LIBS) set (shared_gen_SRCS ${HDF5_GENERATED_SOURCE_DIR}/shared/H5Tinit.c ${HDF5_SRC_BINARY_DIR}/shared/H5lib_settings.c) add_custom_target (gen_${HDF5_LIBSH_TARGET} ALL - DEPENDS ${lib_prog_deps} ${shared_gen_SRCS} ${HDF5_GENERATED_SOURCE_DIR}/shared/shared_gen_SRCS.stamp1 ${HDF5_SRC_BINARY_DIR}/shared/shared_gen_SRCS.stamp2 + DEPENDS ${lib_prog_deps} ${HDF5_GENERATED_SOURCE_DIR}/shared/shared_gen_SRCS.stamp1 ${HDF5_SRC_BINARY_DIR}/shared/shared_gen_SRCS.stamp2 COMMENT "Shared generation target files" ) @@ -29,9 +29,12 @@ #include "H5Lprivate.h" /* Links */ #include "H5MMprivate.h" /* Memory management */ #include "H5Pprivate.h" /* Property lists */ +#include "H5PLprivate.h" /* Plugins */ #include "H5SLprivate.h" /* Skip lists */ #include "H5Tprivate.h" /* Datatypes */ +#include "H5FDsec2.h" /* for H5FD_sec2_init() */ + /****************/ /* Local Macros */ /****************/ @@ -63,16 +66,13 @@ static int H5__mpi_delete_cb(MPI_Comm comm, int keyval, void *attr_val, int *fla /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /*****************************/ /* Library Private Variables */ /*****************************/ -/* Library incompatible release versions */ -const unsigned VERS_RELEASE_EXCEPTIONS[] = {0}; -const unsigned VERS_RELEASE_EXCEPTIONS_SIZE = 0; +/* Library incompatible release versions, develop releases are incompatible by design */ +const unsigned VERS_RELEASE_EXCEPTIONS[] = {0, 1, 2}; +const unsigned VERS_RELEASE_EXCEPTIONS_SIZE = 3; /* statically initialize block for pthread_once call used in initializing */ /* the first global mutex */ @@ -83,6 +83,8 @@ hbool_t H5_libinit_g = FALSE; /* Library hasn't been initialized */ hbool_t H5_libterm_g = FALSE; /* Library isn't being shutdown */ #endif +hbool_t H5_use_selection_io_g = FALSE; + #ifdef H5_HAVE_MPE hbool_t H5_MPEinit_g = FALSE; /* MPE Library hasn't been initialized */ #endif @@ -101,32 +103,30 @@ static H5_atclose_node_t *H5_atclose_head = NULL; /* Declare a free list to manage the H5_atclose_node_t struct */ H5FL_DEFINE_STATIC(H5_atclose_node_t); -/*-------------------------------------------------------------------------- -NAME - H5__init_package -- Initialize interface-specific information -USAGE - herr_t H5__init_package() -RETURNS - Non-negative on success/Negative on failure -DESCRIPTION - Initializes any interface-specific data or routines. ---------------------------------------------------------------------------*/ -herr_t -H5__init_package(void) +/*------------------------------------------------------------------------- + * Function: H5_default_vfd_init + * + * Purpose: Initialize the default VFD. + * + * Return: Success: non-negative + * Failure: negative + *------------------------------------------------------------------------- + */ +static herr_t +H5_default_vfd_init(void) { - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT - - /* Run the library initialization routine, if it hasn't already ran */ - if (!H5_INIT_GLOBAL && !H5_TERM_GLOBAL) { - if (H5_init_library() < 0) - HGOTO_ERROR(H5E_LIB, H5E_CANTINIT, FAIL, "unable to initialize library") - } /* end if */ + herr_t ret_value = SUCCEED; + FUNC_ENTER_NOAPI(FAIL) + /* Load the hid_t for the default VFD for the side effect + * it has of initializing the default VFD. + */ + if (H5FD_sec2_init() == H5I_INVALID_HID) { + HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to load default VFD ID") + } done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5__init_package() */ +} /*-------------------------------------------------------------------------- * NAME @@ -145,15 +145,21 @@ done: herr_t H5_init_library(void) { - herr_t ret_value = SUCCEED; + size_t i; + char * env_use_select_io = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(FAIL) + + /* Run the library initialization routine, if it hasn't already run */ + if (H5_INIT_GLOBAL || H5_TERM_GLOBAL) + HGOTO_DONE(SUCCEED) /* Set the 'library initialized' flag as early as possible, to avoid * possible re-entrancy. */ H5_INIT_GLOBAL = TRUE; - FUNC_ENTER_NOAPI(FAIL) - #ifdef H5_HAVE_PARALLEL { int mpi_initialized; @@ -257,24 +263,41 @@ H5_init_library(void) * The dataspace interface needs to be initialized so that future IDs for * dataspaces work. */ - if (H5E_init() < 0) - HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize error interface") - if (H5VL_init_phase1() < 0) - HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize vol interface") - if (H5P_init() < 0) - HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize property list interface") - if (H5AC_init() < 0) - HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize metadata caching interface") - if (H5L_init() < 0) - HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize link interface") - if (H5FS_init() < 0) - HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize FS interface") - if (H5S_init() < 0) - HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize dataspace interface") - + /* clang-format off */ + struct { + herr_t (*func)(void); + const char *descr; + } initializer[] = { + {H5E_init, "error"} + , {H5VL_init_phase1, "VOL"} + , {H5SL_init, "skip lists"} + , {H5FD_init, "VFD"} + , {H5_default_vfd_init, "default VFD"} + , {H5P_init_phase1, "property list"} + , {H5AC_init, "metadata caching"} + , {H5L_init, "link"} + , {H5S_init, "dataspace"} + , {H5PL_init, "plugins"} /* Finish initializing interfaces that depend on the interfaces above */ - if (H5VL_init_phase2() < 0) - HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize vol interface") + , {H5P_init_phase2, "property list"} + , {H5VL_init_phase2, "VOL"} + }; + + for (i = 0; i < NELMTS(initializer); i++) { + if (initializer[i].func() < 0) { + HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, + "unable to initialize %s interface", initializer[i].descr) + } + } + /* clang-format on */ + + /* Check for HDF5_USE_SELECTION_IO env variable */ + env_use_select_io = HDgetenv("HDF5_USE_SELECTION_IO"); + if (NULL != env_use_select_io && HDstrcmp(env_use_select_io, "") && HDstrcmp(env_use_select_io, "0") && + HDstrcmp(env_use_select_io, "no") && HDstrcmp(env_use_select_io, "No") && + HDstrcmp(env_use_select_io, "NO") && HDstrcmp(env_use_select_io, "false") && + HDstrcmp(env_use_select_io, "False") && HDstrcmp(env_use_select_io, "FALSE")) + H5_use_selection_io_g = TRUE; /* Debugging? */ H5__debug_mask("-all"); @@ -298,9 +321,11 @@ done: void H5_term_library(void) { - int pending, ntries = 0, n; - size_t at = 0; - char loop[1024]; + int pending, ntries = 0; + char loop[1024], *next = loop; + size_t i; + size_t nleft = sizeof(loop); + int nprinted; H5E_auto2_t func; #ifdef H5_HAVE_THREADSAFE @@ -344,108 +369,137 @@ H5_term_library(void) H5_atclose_head = NULL; } /* end if */ + /* clang-format off */ + /* * Terminate each interface. The termination functions return a positive * value if they do something that might affect some other interface in a * way that would necessitate some cleanup work in the other interface. */ -#define DOWN(F) \ - (((n = H5##F##_term_package()) && (at + 8) < sizeof loop) \ - ? (HDsprintf(loop + at, "%s%s", (at ? "," : ""), #F), at += HDstrlen(loop + at), n) \ - : ((n > 0 && (at + 5) < sizeof loop) ? (HDsprintf(loop + at, "..."), at += HDstrlen(loop + at), n) \ - : n)) - - do { - pending = 0; - /* Try to organize these so the "higher" level components get shut - * down before "lower" level components that they might rely on. -QAK - */ +#define TERMINATOR(module, wait) { \ + .func = H5##module##_term_package \ + , .name = #module \ + , .completed = false \ + , .await_prior = wait \ + } + /* + * Termination is ordered by the `terminator` table so the "higher" level + * packages are shut down before "lower" level packages that they + * rely on: + */ + struct { + int (*func)(void); /* function to terminate the module; returns 0 + * on success, >0 if termination was not + * completed and we should try to terminate + * some dependent modules, first. + */ + const char *name; /* name of the module */ + hbool_t completed; /* true iff this terminator was already + * completed + */ + const hbool_t await_prior; /* true iff all prior terminators in the + * list must complete before this + * terminator is attempted + */ + } terminator[] = { /* Close the event sets first, so that all asynchronous operations - * complete before anything else attempts to shut down. + * complete before anything else attempts to shut down. */ - pending += DOWN(ES); - - /* Close down the user-facing interfaces, after the event sets */ - if (pending == 0) { - /* Close the interfaces dependent on others */ - pending += DOWN(L); - - /* Close the "top" of various interfaces (IDs, etc) but don't shut - * down the whole interface yet, so that the object header messages - * get serialized correctly for entries in the metadata cache and the - * symbol table entry in the superblock gets serialized correctly, etc. - * all of which is performed in the 'F' shutdown. - */ - pending += DOWN(A_top); - pending += DOWN(D_top); - pending += DOWN(G_top); - pending += DOWN(M_top); - pending += DOWN(R_top); - pending += DOWN(S_top); - pending += DOWN(T_top); - } /* end if */ - + TERMINATOR(ES, false) + /* Do not attempt to close down package L until after event sets + * have finished closing down. + */ + , TERMINATOR(L, true) + /* Close the "top" of various interfaces (IDs, etc) but don't shut + * down the whole interface yet, so that the object header messages + * get serialized correctly for entries in the metadata cache and the + * symbol table entry in the superblock gets serialized correctly, etc. + * all of which is performed in the 'F' shutdown. + * + * The tops of packages A, D, G, M, S, T do not need to wait for L + * or previous packages to finish closing down. + */ + , TERMINATOR(A_top, false) + , TERMINATOR(D_top, false) + , TERMINATOR(G_top, false) + , TERMINATOR(M_top, false) + , TERMINATOR(S_top, false) + , TERMINATOR(T_top, false) /* Don't shut down the file code until objects in files are shut down */ - if (pending == 0) - pending += DOWN(F); - + , TERMINATOR(F, true) /* Don't shut down the property list code until all objects that might - * use property lists are shut down */ - if (pending == 0) - pending += DOWN(P); - + * use property lists are shut down + */ + , TERMINATOR(P, true) /* Wait to shut down the "bottom" of various interfaces until the - * files are closed, so pieces of the file can be serialized - * correctly. + * files are closed, so pieces of the file can be serialized + * correctly. + * + * Shut down the "bottom" of the attribute, dataset, group, + * reference, dataspace, and datatype interfaces, fully closing + * out the interfaces now. */ - if (pending == 0) { - /* Shut down the "bottom" of the attribute, dataset, group, - * reference, dataspace, and datatype interfaces, fully closing - * out the interfaces now. - */ - pending += DOWN(A); - pending += DOWN(D); - pending += DOWN(G); - pending += DOWN(M); - pending += DOWN(R); - pending += DOWN(S); - pending += DOWN(T); - } /* end if */ - - /* Don't shut down "low-level" components until "high-level" components - * have successfully shut down. This prevents property lists and IDs - * from being closed "out from underneath" of the high-level objects - * that depend on them. -QAK + , TERMINATOR(A, true) + , TERMINATOR(D, false) + , TERMINATOR(G, false) + , TERMINATOR(M, false) + , TERMINATOR(S, false) + , TERMINATOR(T, false) + /* Wait to shut down low-level packages like AC until after + * the preceding high-level packages have shut down. This prevents + * low-level objects from closing "out from underneath" their + * reliant high-level objects. */ - if (pending == 0) { - pending += DOWN(AC); - /* Shut down the "pluggable" interfaces, before the plugin framework */ - pending += DOWN(Z); - pending += DOWN(FD); - pending += DOWN(VL); - /* Don't shut down the plugin code until all "pluggable" interfaces (Z, FD, PL) are shut down */ - if (pending == 0) - pending += DOWN(PL); - /* Don't shut down the error code until other APIs which use it are shut down */ - if (pending == 0) - pending += DOWN(E); - /* Don't shut down the ID code until other APIs which use them are shut down */ - if (pending == 0) - pending += DOWN(I); - /* Don't shut down the skip list code until everything that uses it is down */ - if (pending == 0) - pending += DOWN(SL); - /* Don't shut down the free list code until everything that uses it is down */ - if (pending == 0) - pending += DOWN(FL); - /* Don't shut down the API context code until _everything_ else is down */ - if (pending == 0) - pending += DOWN(CX); - } /* end if */ + , TERMINATOR(AC, true) + /* Shut down the "pluggable" interfaces, before the plugin framework */ + , TERMINATOR(Z, false) + , TERMINATOR(FD, false) + , TERMINATOR(VL, false) + /* Don't shut down the plugin code until all "pluggable" interfaces + * (Z, FD, PL) are shut down + */ + , TERMINATOR(PL, true) + /* Shut down the following packages in strictly the order given + * by the table. + */ + , TERMINATOR(E, true) + , TERMINATOR(I, true) + , TERMINATOR(SL, true) + , TERMINATOR(FL, true) + , TERMINATOR(CX, true) + }; + + do { + pending = 0; + for (i = 0; i < NELMTS(terminator); i++) { + if (terminator[i].completed) + continue; + if (pending != 0 && terminator[i].await_prior) + break; + if (terminator[i].func() == 0) { + terminator[i].completed = true; + continue; + } + + /* log a package when its terminator needs to be retried */ + pending++; + nprinted = HDsnprintf(next, nleft, "%s%s", + (next != loop) ? "," : "", terminator[i].name); + if (nprinted < 0) + continue; + if ((size_t)nprinted >= nleft) + nprinted = HDsnprintf(next, nleft, "..."); + if (nprinted < 0 || (size_t)nprinted >= nleft) + continue; + nleft -= (size_t)nprinted; + next += nprinted; + } } while (pending && ntries++ < 100); + /* clang-format on */ + if (pending) { /* Only display the error message if the user is interested in them. */ if (func) { @@ -911,6 +965,7 @@ H5check_version(unsigned majnum, unsigned minnum, unsigned relnum) static int checked = 0; /* If we've already checked the version info */ static unsigned int disable_version_check = 0; /* Set if the version check should be disabled */ static const char * version_mismatch_warning = VERSION_MISMATCH_WARNING; + static const char * release_mismatch_warning = RELEASE_MISMATCH_WARNING; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API_NOINIT_NOERR_NOFS @@ -931,10 +986,7 @@ H5check_version(unsigned majnum, unsigned minnum, unsigned relnum) } /* H5_VERS_MAJOR and H5_VERS_MINOR must match */ - /* Cast relnum to int to avoid warning for unsigned < 0 comparison - * in first release versions */ - if (H5_VERS_MAJOR != majnum || H5_VERS_MINOR != minnum || H5_VERS_RELEASE > (int)relnum) { - + if (H5_VERS_MAJOR != majnum || H5_VERS_MINOR != minnum) { switch (disable_version_check) { case 0: HDfprintf(stderr, "%s%s", version_mismatch_warning, @@ -969,9 +1021,10 @@ H5check_version(unsigned majnum, unsigned minnum, unsigned relnum) break; } /* end switch */ - } /* end if (H5_VERS_MAJOR != majnum || H5_VERS_MINOR != minnum || H5_VERS_RELEASE > relnum) */ + } /* end if (H5_VERS_MAJOR != majnum || H5_VERS_MINOR != minnum) */ /* H5_VERS_RELEASE should be compatible, we will only add checks for exceptions */ + /* Library develop release versions are incompatible by design */ if (H5_VERS_RELEASE != relnum) { for (unsigned i = 0; i < VERS_RELEASE_EXCEPTIONS_SIZE; i++) { /* Check for incompatible headers or incompatible library */ @@ -979,7 +1032,7 @@ H5check_version(unsigned majnum, unsigned minnum, unsigned relnum) switch (disable_version_check) { case 0: HDfprintf( - stderr, "%s%s", version_mismatch_warning, + stderr, "%s%s", release_mismatch_warning, "You can, at your own risk, disable this warning by setting the environment\n" "variable 'HDF5_DISABLE_VERSION_CHECK' to a value of '1'.\n" "Setting it to 2 or higher will suppress the warning messages totally.\n"); @@ -998,7 +1051,7 @@ H5check_version(unsigned majnum, unsigned minnum, unsigned relnum) "%s'HDF5_DISABLE_VERSION_CHECK' " "environment variable is set to %d, application will\n" "continue at your own risk.\n", - version_mismatch_warning, disable_version_check); + release_mismatch_warning, disable_version_check); /* Mention the versions we are referring to */ HDfprintf(stderr, "Headers are %u.%u.%u, library is %u.%u.%u\n", majnum, minnum, relnum, (unsigned)H5_VERS_MAJOR, (unsigned)H5_VERS_MINOR, @@ -1868,7 +1868,7 @@ done: if all attributes were processed. DESCRIPTION - This function interates over the attributes of dataset or group + This function iterates over the attributes of dataset or group specified with 'loc_id' & 'obj_name'. For each attribute of the object, the 'op_data' and some additional information (specified below) are passed to the 'op' function. The iteration begins with the '*idx' @@ -1956,7 +1956,7 @@ done: if all attributes were processed. DESCRIPTION - This function interates over the attributes of dataset or group + This function iterates over the attributes of dataset or group specified with 'loc_id' & 'obj_name'. For each attribute of the object, the 'op_data' and some additional information (specified below) are passed to the 'op' function. The iteration begins with the '*idx' @@ -2410,7 +2410,7 @@ done: htri_t H5Aexists(hid_t obj_id, const char *attr_name) { - hbool_t exists; /* Flag for attribute existance */ + hbool_t exists; /* Flag for attribute existence */ htri_t ret_value = FAIL; /* Return value */ FUNC_ENTER_API(FAIL) @@ -2526,7 +2526,7 @@ done: htri_t H5Aexists_by_name(hid_t loc_id, const char *obj_name, const char *attr_name, hid_t lapl_id) { - hbool_t exists; /* Flag for attribute existance */ + hbool_t exists; /* Flag for attribute existence */ htri_t ret_value = FAIL; /* Return value */ FUNC_ENTER_API(FAIL) @@ -70,9 +70,6 @@ static herr_t H5AC__verify_tag(const H5AC_class_t *type); /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /*****************************/ /* Library Private Variables */ /*****************************/ @@ -143,29 +140,7 @@ H5AC_init(void) { herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) - /* FUNC_ENTER() does all the work */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5AC_init() */ - -/*------------------------------------------------------------------------- - * Function: H5AC__init_package - * - * Purpose: Initialize interface-specific information - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * Thursday, July 18, 2002 - * - *------------------------------------------------------------------------- - */ -herr_t -H5AC__init_package(void) -{ - FUNC_ENTER_PACKAGE_NOERR + FUNC_ENTER_NOAPI_NOERR #ifdef H5_HAVE_PARALLEL /* check whether to enable strict collective function calling @@ -182,8 +157,8 @@ H5AC__init_package(void) } #endif /* H5_HAVE_PARALLEL */ - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5AC__init_package() */ + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5AC_init() */ /*------------------------------------------------------------------------- * Function: H5AC_term_package @@ -204,10 +179,6 @@ H5AC_term_package(void) { FUNC_ENTER_NOAPI_NOINIT_NOERR - if (H5_PKG_INIT_VAR) - /* Reset interface initialization flag */ - H5_PKG_INIT_VAR = FALSE; - FUNC_LEAVE_NOAPI(0) } /* end H5AC_term_package() */ @@ -332,7 +303,7 @@ H5AC_create(const H5F_t *f, H5AC_cache_config_t *config_ptr, H5AC_cache_image_co aux_ptr->sync_point_done = NULL; aux_ptr->p0_image_len = 0; - HDsprintf(prefix, "%d:", mpi_rank); + HDsnprintf(prefix, sizeof(prefix), "%d:", mpi_rank); if (mpi_rank == 0) { if (NULL == (aux_ptr->d_slist_ptr = H5SL_create(H5SL_TYPE_HADDR, NULL))) @@ -1228,7 +1199,7 @@ done: * metadata cache flush. * * Initially, this means setting up the slist prior to the - * flush. We do this in a seperate call because + * flush. We do this in a separate call because * H5F__flush_phase2() make repeated calls to H5AC_flush(). * Handling this detail in separate calls allows us to avoid * the overhead of setting up and taking down the skip list @@ -1280,7 +1251,7 @@ done: * flush. * * Initially, this means taking down the slist after the - * flush. We do this in a seperate call because + * flush. We do this in a separate call because * H5F__flush_phase2() make repeated calls to H5AC_flush(). * Handling this detail in separate calls allows us to avoid * the overhead of setting up and taking down the skip list @@ -1469,21 +1440,82 @@ H5AC_resize_entry(void *thing, size_t new_size) cache_ptr = entry_ptr->cache_ptr; HDassert(cache_ptr); - /* Resize the entry */ - if (H5C_resize_entry(thing, new_size) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTRESIZE, FAIL, "can't resize entry") - #ifdef H5_HAVE_PARALLEL - { + /* Log the generation of dirty bytes of metadata iff: + * + * 1) The entry is clean on entry, and this resize will dirty it + * (i.e. the current and new sizes are different), and + * + * 2) This is a parallel computation -- which it is if the aux_ptr + * is non-null. + * + * A few points to note about this section of the code: + * + * 1) This call must occur before the call to H5C_resize_entry() since + * H5AC__log_dirtied_entry() expects the target entry to be clean + * on entry. + * + * 2) This code has some basic issues in terms of the number of bytes + * added to the dirty bytes count. + * + * First, it adds the initial entry size to aux_ptr->dirty_bytes, + * not the final size. Note that this code used to use the final + * size, but code to support this has been removed from + * H5AC__log_dirtied_entry() for reasons unknown since I wrote this + * code. + * + * As long as all ranks do the same thing here, this probably doesn't + * matter much, although it will delay initiation of sync points. + * + * A more interesting point is that this code will not increment + * aux_ptr->dirty_bytes if a dirty entry is resized. At first glance + * this seems major, as particularly with the older file formats, + * resizes can be quite large. However, this is probably not an + * issue either, since such resizes will be accompanied by large + * amounts of dirty metadata creation in other areas -- which will + * cause aux_ptr->dirty_bytes to be incremented. + * + * The bottom line is that this code is probably OK, but the above + * points should be kept in mind. + * + * One final observation: This comment is occasioned by a bug caused + * by moving the call to H5AC__log_dirtied_entry() after the call to + * H5C_resize_entry(), and then only calling H5AC__log_dirtied_entry() + * if entry_ptr->is_dirty was false. + * + * Since H5C_resize_entry() marks the target entry dirty unless there + * is not change in size, this had the effect of not calling + * H5AC__log_dirtied_entry() when it should be, and corrupting + * the cleaned and dirtied lists used by rank 0 in the parallel + * version of the metadata cache. + * + * The point here is that you should be very careful when working with + * this code, and not modify it unless you fully understand it. + * + * JRM -- 2/28/22 + */ + + if ((!entry_ptr->is_dirty) && (entry_ptr->size != new_size)) { + + /* the entry is clean, and will be marked dirty in the resize + * operation. + */ H5AC_aux_t *aux_ptr; aux_ptr = (H5AC_aux_t *)H5C_get_aux_ptr(cache_ptr); - if ((!entry_ptr->is_dirty) && (NULL != aux_ptr)) + + if (NULL != aux_ptr) { + if (H5AC__log_dirtied_entry(entry_ptr) < 0) HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKDIRTY, FAIL, "can't log dirtied entry") + } } #endif /* H5_HAVE_PARALLEL */ + /* Resize the entry */ + if (H5C_resize_entry(thing, new_size) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTRESIZE, FAIL, "can't resize entry") + done: /* If currently logging, generate a message */ if (cache_ptr != NULL && cache_ptr->log_info != NULL) @@ -1665,9 +1697,14 @@ H5AC_unprotect(H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing, un if (H5AC__log_dirtied_entry((H5AC_info_t *)thing) < 0) HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "can't log dirtied entry") - if (deleted && aux_ptr->mpi_rank == 0) - if (H5AC__log_deleted_entry((H5AC_info_t *)thing) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "H5AC__log_deleted_entry() failed") + if (deleted && aux_ptr->mpi_rank == 0) { + if (H5AC__log_deleted_entry((H5AC_info_t *)thing) < 0) { + /* If we fail to log the deleted entry, push an error but still + * participate in a possible sync point ahead + */ + HDONE_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "H5AC__log_deleted_entry() failed") + } + } } /* end if */ #endif /* H5_HAVE_PARALLEL */ diff --git a/src/H5ACdbg.c b/src/H5ACdbg.c index 2d24adb..5e24517 100644 --- a/src/H5ACdbg.c +++ b/src/H5ACdbg.c @@ -197,9 +197,9 @@ done: * If either the parent or the child is not in the metadata * cache, the function sets *fd_exists_ptr to FALSE. * - * If both are in the cache, the childs list of parents is + * If both are in the cache, the child's list of parents is * searched for the proposed parent. If the proposed parent - * is found in the childs parent list, the function sets + * is found in the child's parent list, the function sets * *fd_exists_ptr to TRUE. In all other non-error cases, * the function sets *fd_exists_ptr FALSE. * diff --git a/src/H5ACmpio.c b/src/H5ACmpio.c index 7d2ba25..7eaf751 100644 --- a/src/H5ACmpio.c +++ b/src/H5ACmpio.c @@ -304,8 +304,10 @@ H5AC__broadcast_candidate_list(H5AC_t *cache_ptr, unsigned *num_entries_ptr, had * 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) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't construct candidate buffer.") + if (H5AC__copy_candidate_list_to_buffer(cache_ptr, &chk_num_entries, &haddr_buf_ptr) < 0) { + /* Push an error, but still participate in following MPI_Bcast */ + HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't construct candidate buffer.") + } HDassert(chk_num_entries == num_entries); HDassert(haddr_buf_ptr != NULL); @@ -428,18 +430,23 @@ H5AC__broadcast_clean_list(H5AC_t *cache_ptr) /* allocate a buffer to store the list of entry base addresses in */ buf_size = sizeof(haddr_t) * num_entries; - if (NULL == (addr_buf_ptr = (haddr_t *)H5MM_malloc(buf_size))) - HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for addr buffer") - - /* Set up user data for callback */ - udata.aux_ptr = aux_ptr; - udata.addr_buf_ptr = addr_buf_ptr; - udata.u = 0; - - /* Free all the clean list entries, building the address list in the callback */ - /* (Callback also removes the matching entries from the dirtied list) */ - if (H5SL_free(aux_ptr->c_slist_ptr, H5AC__broadcast_clean_list_cb, &udata) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFREE, FAIL, "Can't build address list for clean entries") + if (NULL == (addr_buf_ptr = (haddr_t *)H5MM_malloc(buf_size))) { + /* Push an error, but still participate in following MPI_Bcast */ + HDONE_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for addr buffer") + } + else { + /* Set up user data for callback */ + udata.aux_ptr = aux_ptr; + udata.addr_buf_ptr = addr_buf_ptr; + udata.u = 0; + + /* Free all the clean list entries, building the address list in the callback */ + /* (Callback also removes the matching entries from the dirtied list) */ + if (H5SL_free(aux_ptr->c_slist_ptr, H5AC__broadcast_clean_list_cb, &udata) < 0) { + /* Push an error, but still participate in following MPI_Bcast */ + HDONE_ERROR(H5E_CACHE, H5E_CANTFREE, FAIL, "Can't build address list for clean entries") + } + } /* Now broadcast the list of cleaned entries */ if (MPI_SUCCESS != @@ -1132,7 +1139,7 @@ done: * * 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 + * and applying the list. It must be run simultaneously on * all processes that have the relevant file open. To ensure * proper synchronization, there is a barrier at the beginning * of this function. @@ -1311,7 +1318,7 @@ done: * * This function is the main routine for handling this * notification procedure. It must be called - * simultaniously on all processes that have the relevant + * simultaneously 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. * @@ -1448,8 +1455,10 @@ H5AC__receive_haddr_list(MPI_Comm mpi_comm, unsigned *num_entries_ptr, haddr_t * /* allocate buffers to store the list of entry base addresses in */ buf_size = sizeof(haddr_t) * num_entries; - if (NULL == (haddr_buf_ptr = (haddr_t *)H5MM_malloc(buf_size))) - HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for haddr buffer") + if (NULL == (haddr_buf_ptr = (haddr_t *)H5MM_malloc(buf_size))) { + /* Push an error, but still participate in following MPI_Bcast */ + HDONE_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for haddr buffer") + } /* Now receive the list of candidate entries */ if (MPI_SUCCESS != @@ -1800,10 +1809,14 @@ H5AC__rsp__dist_md_write__flush_to_min_clean(H5F_t *f) if (evictions_enabled) { /* construct candidate list -- process 0 only */ - if (aux_ptr->mpi_rank == 0) + if (aux_ptr->mpi_rank == 0) { + /* If constructing candidate list fails, push an error but still participate + * in collective operations during following candidate list propagation + */ 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.") + HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't construct candidate list.") + } /* propagate and apply candidate list -- all processes */ if (H5AC__propagate_and_apply_candidate_list(f) < 0) @@ -1899,15 +1912,21 @@ H5AC__rsp__p0_only__flush(H5F_t *f) aux_ptr->write_permitted = FALSE; /* Check for error on the write operation */ - if (result < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't flush.") - - /* 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) - (aux_ptr->write_done)(); + if (result < 0) { + /* If write operation fails, push an error but still participate + * in collective operations during following cache entry + * propagation + */ + HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't flush.") + } + else { + /* 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) + (aux_ptr->write_done)(); + } } /* end if */ /* Propagate cleaned entries to other ranks. */ @@ -2019,15 +2038,21 @@ H5AC__rsp__p0_only__flush_to_min_clean(H5F_t *f) aux_ptr->write_permitted = FALSE; /* Check for error on the write operation */ - 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) - (aux_ptr->write_done)(); + if (result < 0) { + /* If write operation fails, push an error but still participate + * in collective operations during following cache entry + * propagation + */ + HDONE_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5C_flush_to_min_clean() failed.") + } + else { + /* 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) + (aux_ptr->write_done)(); + } } /* end if */ if (H5AC__propagate_flushed_and_still_clean_entries_list(f) < 0) @@ -2093,11 +2118,11 @@ H5AC__run_sync_point(H5F_t *f, int sync_point_op) (sync_point_op == H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED)); #if H5AC_DEBUG_DIRTY_BYTES_CREATION - HDfprintf(stdout, "%d:H5AC_propagate...:%u: (u/uu/i/iu/r/ru) = %zu/%u/%zu/%u/%zu/%u\n", aux_ptr->mpi_rank, + HDfprintf(stdout, "%d:H5AC_propagate...:%u: (u/uu/i/iu/m/mu) = %zu/%u/%zu/%u/%zu/%u\n", aux_ptr->mpi_rank, aux_ptr->dirty_bytes_propagations, aux_ptr->unprotect_dirty_bytes, aux_ptr->unprotect_dirty_bytes_updates, aux_ptr->insert_dirty_bytes, - aux_ptr->insert_dirty_bytes_updates, aux_ptr->rename_dirty_bytes, - aux_ptr->rename_dirty_bytes_updates); + aux_ptr->insert_dirty_bytes_updates, aux_ptr->move_dirty_bytes, + aux_ptr->move_dirty_bytes_updates); #endif /* H5AC_DEBUG_DIRTY_BYTES_CREATION */ /* clear collective access flag on half of the entries in the @@ -2161,8 +2186,8 @@ H5AC__run_sync_point(H5F_t *f, int sync_point_op) 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; + aux_ptr->move_dirty_bytes = 0; + aux_ptr->move_dirty_bytes_updates = 0; #endif /* H5AC_DEBUG_DIRTY_BYTES_CREATION */ done: diff --git a/src/H5ACpkg.h b/src/H5ACpkg.h index 521f85a..9b75034 100644 --- a/src/H5ACpkg.h +++ b/src/H5ACpkg.h @@ -346,7 +346,7 @@ H5FL_EXTERN(H5AC_aux_t); * * The following field supports the metadata cache image feature. * - * p0_image_len: unsiged integer containing the length of the metadata cache + * p0_image_len: unsigned integer containing the length of the metadata cache * image constructed by MPI process 0. This field should be 0 * if the value is unknown, or if cache image is not enabled. * diff --git a/src/H5ACproxy_entry.c b/src/H5ACproxy_entry.c index b3d31b2..31d3224 100644 --- a/src/H5ACproxy_entry.c +++ b/src/H5ACproxy_entry.c @@ -421,7 +421,7 @@ H5AC_proxy_entry_dest(H5AC_proxy_entry_t *pentry) { herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR /* Sanity checks */ HDassert(pentry); @@ -433,7 +433,6 @@ H5AC_proxy_entry_dest(H5AC_proxy_entry_t *pentry) /* Free the proxy entry object */ pentry = H5FL_FREE(H5AC_proxy_entry_t, pentry); -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5AC_proxy_entry_dest() */ diff --git a/src/H5ACpublic.h b/src/H5ACpublic.h index f8f4f28..42bc090 100644 --- a/src/H5ACpublic.h +++ b/src/H5ACpublic.h @@ -28,10 +28,6 @@ #include "H5public.h" #include "H5Cpublic.h" -#ifdef __cplusplus -extern "C" { -#endif - /**************************************************************************** * * structure H5AC_cache_config_t @@ -76,7 +72,7 @@ extern "C" { * * *** DEPRECATED *** Use H5Fstart/stop logging functions instead * - * The trace file is a debuging feature that allow the capture of + * The trace file is a debugging feature that allow the capture of * top level metadata cache requests for purposes of debugging and/or * optimization. This field should normally be set to FALSE, as * trace file collection imposes considerable overhead. @@ -123,7 +119,7 @@ extern "C" { * H5C_incr__off ) && ( decr_mode == H5C_decr__off )). There * is no logical reason why this should be so, but it simplifies * implementation and testing, and I can't think of any reason - * why it would be desireable. If you can think of one, I'll + * why it would be desirable. If you can think of one, I'll * revisit the issue. * * set_initial_size: Boolean flag indicating whether the size of the @@ -396,7 +392,7 @@ extern "C" { * * 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 + * compliance 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. @@ -576,7 +572,7 @@ typedef struct H5AC_cache_config_t { size_t min_size; /**< Lower bound (in bytes) on the range of values that the - * adaptive cache resize code can select as the mininum cache * size. */ + * adaptive cache resize code can select as the minimum cache * size. */ long int epoch_length; /**< Number of cache accesses between runs of the adaptive cache resize @@ -708,13 +704,13 @@ typedef struct H5AC_cache_config_t { * of bytes of dirty metadata created since the last synchronization exceeds * this limit.\n This field only applies to the parallel case. While it is * ignored elsewhere, it can still draw a value out of bounds error.\n It - * must be consistant across all caches on any given file.\n By default, + * must be consistent across all caches on any given file.\n By default, * this field is set to 256 KB. It shouldn't be more than half the current * max cache size times the min clean fraction. */ int metadata_write_strategy; /**< Desired metadata write strategy. The valid values for this field - * are:\n #H5AC_METADATA_WRITE_STRATEGY__PROCESS_0_ONLY: Specifies tha only + * are:\n #H5AC_METADATA_WRITE_STRATEGY__PROCESS_0_ONLY: Specifies the only * process zero is allowed to write dirty metadata to disk.\n * #H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED: Specifies that process zero * still makes the decisions as to what entries should be flushed, but the @@ -783,7 +779,4 @@ typedef struct H5AC_cache_image_config_t { //! <!-- [H5AC_cache_image_config_t_snip] --> -#ifdef __cplusplus -} -#endif #endif diff --git a/src/H5Adense.c b/src/H5Adense.c index b0d793c..fa51f9d 100644 --- a/src/H5Adense.c +++ b/src/H5Adense.c @@ -337,7 +337,7 @@ H5A__dense_open(H5F_t *f, const H5O_ainfo_t *ainfo, const char *name) H5HF_t * fheap = NULL; /* Fractal heap handle */ H5HF_t * shared_fheap = NULL; /* Fractal heap handle for shared header messages */ H5B2_t * bt2_name = NULL; /* v2 B-tree handle for name index */ - htri_t attr_sharable; /* Flag indicating attributes are sharable */ + htri_t attr_sharable; /* Flag indicating attributes are shareable */ hbool_t attr_exists; /* Attribute exists in v2 B-tree */ H5A_t * ret_value = NULL; /* Return value */ @@ -356,7 +356,7 @@ H5A__dense_open(H5F_t *f, const H5O_ainfo_t *ainfo, const char *name) if ((attr_sharable = H5SM_type_shared(f, H5O_ATTR_ID)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, NULL, "can't determine if attributes are shared") - /* Get handle for shared message heap, if attributes are sharable */ + /* Get handle for shared message heap, if attributes are shareable */ if (attr_sharable) { haddr_t shared_fheap_addr; /* Address of fractal heap to use */ @@ -429,7 +429,7 @@ H5A__dense_insert(H5F_t *f, const H5O_ainfo_t *ainfo, H5A_t *attr) H5WB_t * wb = NULL; /* Wrapped buffer for attribute data */ uint8_t attr_buf[H5A_ATTR_BUF_SIZE]; /* Buffer for serializing message */ unsigned mesg_flags = 0; /* Flags for storing message */ - htri_t attr_sharable; /* Flag indicating attributes are sharable */ + htri_t attr_sharable; /* Flag indicating attributes are shareable */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE @@ -443,7 +443,7 @@ H5A__dense_insert(H5F_t *f, const H5O_ainfo_t *ainfo, H5A_t *attr) if ((attr_sharable = H5SM_type_shared(f, H5O_ATTR_ID)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't determine if attributes are shared") - /* Get handle for shared message heap, if attributes are sharable */ + /* Get handle for shared message heap, if attributes are shareable */ if (attr_sharable) { haddr_t shared_fheap_addr; /* Address of fractal heap to use */ htri_t shared_mesg; /* Should this message be stored in the Shared Message table? */ @@ -727,7 +727,7 @@ H5A__dense_write(H5F_t *f, const H5O_ainfo_t *ainfo, H5A_t *attr) H5HF_t * fheap = NULL; /* Fractal heap handle */ H5HF_t * shared_fheap = NULL; /* Fractal heap handle for shared header messages */ H5B2_t * bt2_name = NULL; /* v2 B-tree handle for name index */ - htri_t attr_sharable; /* Flag indicating attributes are sharable */ + htri_t attr_sharable; /* Flag indicating attributes are shareable */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE @@ -743,7 +743,7 @@ H5A__dense_write(H5F_t *f, const H5O_ainfo_t *ainfo, H5A_t *attr) if ((attr_sharable = H5SM_type_shared(f, H5O_ATTR_ID)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't determine if attributes are shared") - /* Get handle for shared message heap, if attributes are sharable */ + /* Get handle for shared message heap, if attributes are shareable */ if (attr_sharable) { haddr_t shared_fheap_addr; /* Address of fractal heap to use */ @@ -865,7 +865,7 @@ H5A__dense_rename(H5F_t *f, const H5O_ainfo_t *ainfo, const char *old_name, cons H5B2_t * bt2_name = NULL; /* v2 B-tree handle for name index */ H5B2_t * bt2_corder = NULL; /* v2 B-tree handle for creation order ndex */ H5A_t * attr_copy = NULL; /* Copy of attribute to rename */ - htri_t attr_sharable; /* Flag indicating attributes are sharable */ + htri_t attr_sharable; /* Flag indicating attributes are shareable */ htri_t shared_mesg; /* Should this message be stored in the Shared Message table? */ hbool_t attr_exists; /* Attribute exists in v2 B-tree */ herr_t ret_value = SUCCEED; /* Return value */ @@ -882,7 +882,7 @@ H5A__dense_rename(H5F_t *f, const H5O_ainfo_t *ainfo, const char *old_name, cons if ((attr_sharable = H5SM_type_shared(f, H5O_ATTR_ID)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't determine if attributes are shared") - /* Get handle for shared message heap, if attributes are sharable */ + /* Get handle for shared message heap, if attributes are shareable */ if (attr_sharable) { haddr_t shared_fheap_addr; /* Address of fractal heap to use */ @@ -1181,7 +1181,7 @@ H5A__dense_iterate(H5F_t *f, hid_t loc_id, const H5O_ainfo_t *ainfo, H5_index_t /* Check on iteration order */ if (order == H5_ITER_NATIVE && H5F_addr_defined(bt2_addr)) { H5A_bt2_ud_it_t udata; /* User data for iterator callback */ - htri_t attr_sharable; /* Flag indicating attributes are sharable */ + htri_t attr_sharable; /* Flag indicating attributes are shareable */ /* Open the fractal heap */ if (NULL == (fheap = H5HF_open(f, ainfo->fheap_addr))) @@ -1191,7 +1191,7 @@ H5A__dense_iterate(H5F_t *f, hid_t loc_id, const H5O_ainfo_t *ainfo, H5_index_t if ((attr_sharable = H5SM_type_shared(f, H5O_ATTR_ID)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't determine if attributes are shared") - /* Get handle for shared message heap, if attributes are sharable */ + /* Get handle for shared message heap, if attributes are shareable */ if (attr_sharable) { haddr_t shared_fheap_addr; /* Address of fractal heap to use */ @@ -1338,7 +1338,7 @@ H5A__dense_remove(H5F_t *f, const H5O_ainfo_t *ainfo, const char *name) H5HF_t * shared_fheap = NULL; /* Fractal heap handle for shared header messages */ H5B2_t * bt2_name = NULL; /* v2 B-tree handle for name index */ H5A_t * attr_copy = NULL; /* Copy of attribute to remove */ - htri_t attr_sharable; /* Flag indicating attributes are sharable */ + htri_t attr_sharable; /* Flag indicating attributes are shareable */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE @@ -1356,7 +1356,7 @@ H5A__dense_remove(H5F_t *f, const H5O_ainfo_t *ainfo, const char *name) if ((attr_sharable = H5SM_type_shared(f, H5O_ATTR_ID)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't determine if attributes are shared") - /* Get handle for shared message heap, if attributes are sharable */ + /* Get handle for shared message heap, if attributes are shareable */ if (attr_sharable) { haddr_t shared_fheap_addr; /* Address of fractal heap to use */ @@ -1585,7 +1585,7 @@ H5A__dense_remove_by_idx(H5F_t *f, const H5O_ainfo_t *ainfo, H5_index_t idx_type /* If there is an index defined for the field, use it */ if (H5F_addr_defined(bt2_addr)) { H5A_bt2_ud_rmbi_t udata; /* User data for v2 B-tree record removal */ - htri_t attr_sharable; /* Flag indicating attributes are sharable */ + htri_t attr_sharable; /* Flag indicating attributes are shareable */ /* Open the fractal heap */ if (NULL == (fheap = H5HF_open(f, ainfo->fheap_addr))) @@ -1595,7 +1595,7 @@ H5A__dense_remove_by_idx(H5F_t *f, const H5O_ainfo_t *ainfo, H5_index_t idx_type if ((attr_sharable = H5SM_type_shared(f, H5O_ATTR_ID)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't determine if attributes are shared") - /* Get handle for shared message heap, if attributes are sharable */ + /* Get handle for shared message heap, if attributes are shareable */ if (attr_sharable) { haddr_t shared_fheap_addr; /* Address of fractal heap to use */ @@ -1675,7 +1675,7 @@ H5A__dense_exists(H5F_t *f, const H5O_ainfo_t *ainfo, const char *name, hbool_t H5HF_t * fheap = NULL; /* Fractal heap handle */ H5HF_t * shared_fheap = NULL; /* Fractal heap handle for shared header messages */ H5B2_t * bt2_name = NULL; /* v2 B-tree handle for name index */ - htri_t attr_sharable; /* Flag indicating attributes are sharable */ + htri_t attr_sharable; /* Flag indicating attributes are shareable */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE @@ -1694,7 +1694,7 @@ H5A__dense_exists(H5F_t *f, const H5O_ainfo_t *ainfo, const char *name, hbool_t if ((attr_sharable = H5SM_type_shared(f, H5O_ATTR_ID)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't determine if attributes are shared") - /* Get handle for shared message heap, if attributes are sharable */ + /* Get handle for shared message heap, if attributes are shareable */ if (attr_sharable) { haddr_t shared_fheap_addr; /* Address of fractal heap to use */ diff --git a/src/H5Adeprec.c b/src/H5Adeprec.c index 8ae4e41..05e4eed 100644 --- a/src/H5Adeprec.c +++ b/src/H5Adeprec.c @@ -356,7 +356,7 @@ done: last operator if it was non-zero, or zero if all attributes were processed. DESCRIPTION - This function interates over the attributes of dataset or group + This function iterates over the attributes of dataset or group specified with 'loc_id'. For each attribute of the object, the 'op_data' and some additional information (specified below) are passed to the 'op' function. The iteration begins with the '*attr_number' diff --git a/src/H5Aint.c b/src/H5Aint.c index 300d686..b0b91d0 100644 --- a/src/H5Aint.c +++ b/src/H5Aint.c @@ -99,9 +99,6 @@ static herr_t H5A__iterate_common(hid_t loc_id, H5_index_t idx_type, H5_iter_ord /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /* Format version bounds for attribute */ const unsigned H5O_attr_ver_bounds[] = { H5O_ATTR_VERSION_1, /* H5F_LIBVER_EARLIEST */ @@ -139,9 +136,6 @@ static const H5I_class_t H5I_ATTR_CLS[1] = {{ (H5I_free_t)H5A__close_cb /* Callback routine for closing objects of this class */ }}; -/* Flag indicating "top" of interface has been initialized */ -static hbool_t H5A_top_package_initialize_s = FALSE; - /*------------------------------------------------------------------------- * Function: H5A_init * @@ -158,30 +152,6 @@ H5A_init(void) herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) - /* FUNC_ENTER() does all the work */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5A_init() */ - -/*-------------------------------------------------------------------------- -NAME - H5A__init_package -- Initialize interface-specific information -USAGE - herr_t H5A__init_package() - -RETURNS - Non-negative on success/Negative on failure -DESCRIPTION - Initializes any interface-specific data or routines. - ---------------------------------------------------------------------------*/ -herr_t -H5A__init_package(void) -{ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_PACKAGE /* * Create attribute ID type. @@ -189,12 +159,9 @@ H5A__init_package(void) if (H5I_register_type(H5I_ATTR_CLS) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to initialize interface") - /* Mark "top" of interface as initialized, too */ - H5A_top_package_initialize_s = TRUE; - done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5A__init_package() */ +} /* end H5A_init() */ /*-------------------------------------------------------------------------- NAME @@ -220,16 +187,10 @@ H5A_top_term_package(void) FUNC_ENTER_NOAPI_NOINIT_NOERR - if (H5A_top_package_initialize_s) { - if (H5I_nmembers(H5I_ATTR) > 0) { - (void)H5I_clear_type(H5I_ATTR, FALSE, FALSE); - n++; /*H5I*/ - } /* end if */ - - /* Mark closed */ - if (0 == n) - H5A_top_package_initialize_s = FALSE; - } /* end if */ + if (H5I_nmembers(H5I_ATTR) > 0) { + (void)H5I_clear_type(H5I_ATTR, FALSE, FALSE); + n++; /*H5I*/ + } /* end if */ FUNC_LEAVE_NOAPI(n) } /* H5A_top_term_package() */ @@ -260,18 +221,11 @@ H5A_term_package(void) FUNC_ENTER_NOAPI_NOINIT_NOERR - if (H5_PKG_INIT_VAR) { - /* Sanity checks */ - HDassert(0 == H5I_nmembers(H5I_ATTR)); - HDassert(FALSE == H5A_top_package_initialize_s); - - /* Destroy the attribute object id group */ - n += (H5I_dec_type_ref(H5I_ATTR) > 0); + /* Sanity checks */ + HDassert(0 == H5I_nmembers(H5I_ATTR)); - /* Mark closed */ - if (0 == n) - H5_PKG_INIT_VAR = FALSE; - } /* end if */ + /* Destroy the attribute object id group */ + n += (H5I_dec_type_ref(H5I_ATTR) > 0); FUNC_LEAVE_NOAPI(n) } /* H5A_term_package() */ @@ -1148,7 +1102,7 @@ H5A__get_info(const H5A_t *attr, H5A_info_t *ainfo) { herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR /* Check args */ HDassert(attr); @@ -1166,7 +1120,6 @@ H5A__get_info(const H5A_t *attr, H5A_info_t *ainfo) ainfo->corder = attr->shared->crt_idx; } /* end else */ -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5A__get_info() */ @@ -1383,14 +1336,13 @@ H5A_oloc(H5A_t *attr) { H5O_loc_t *ret_value = NULL; /* Return value */ - FUNC_ENTER_NOAPI(NULL) + FUNC_ENTER_NOAPI_NOERR HDassert(attr); /* Set return value */ ret_value = &(attr->oloc); -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5A_oloc() */ @@ -1414,14 +1366,13 @@ H5A_nameof(H5A_t *attr) { H5G_name_t *ret_value = NULL; /* Return value */ - FUNC_ENTER_NOAPI(NULL) + FUNC_ENTER_NOAPI_NOERR HDassert(attr); /* Set return value */ ret_value = &(attr->path); -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5A_nameof() */ @@ -1443,14 +1394,13 @@ H5A_type(const H5A_t *attr) { H5T_t *ret_value = NULL; /* Return value */ - FUNC_ENTER_NOAPI(NULL) + FUNC_ENTER_NOAPI_NOERR HDassert(attr); /* Set return value */ ret_value = attr->shared->dt; -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5A_type() */ diff --git a/src/H5Apublic.h b/src/H5Apublic.h index b78ae05..4ac6a53 100644 --- a/src/H5Apublic.h +++ b/src/H5Apublic.h @@ -622,7 +622,7 @@ H5_DLL hid_t H5Aget_type(hid_t attr_id); * For example, if \p idx_type, \p order, and \p idx are set to * #H5_INDEX_NAME, #H5_ITER_INC, and 5, respectively, the attribute * in question is the fifth attribute from the beginning of the - * alpha-numeric index of attribute names. If \p order were set to + * alphanumeric index of attribute names. If \p order were set to * #H5_ITER_DEC, it would be the fifth attribute from the end of * the index. * @@ -677,7 +677,7 @@ H5_DLL herr_t H5Aiterate2(hid_t loc_id, H5_index_t idx_type, H5_iter_order_t ord * For example, if \p idx_type, \p order, and \p idx are set to * #H5_INDEX_NAME, #H5_ITER_INC, and 5, respectively, the attribute * in question is the fifth attribute from the beginning of the - * alpha-numeric index of attribute names. If \p order were set to + * alphanumeric index of attribute names. If \p order were set to * #H5_ITER_DEC, it would be the fifth attribute from the end of * the index. * @@ -157,9 +157,6 @@ static H5B_t *H5B__copy(const H5B_t *old_bt); /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /* Declare a free list to manage the haddr_t sequence information */ H5FL_SEQ_DEFINE(haddr_t); @@ -61,9 +61,6 @@ /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /* v2 B-tree client ID to class mapping */ /* Remember to add client ID to H5B2_subid_t in H5B2private.h when adding a new diff --git a/src/H5B2int.c b/src/H5B2int.c index 610da6c..ab43a5a 100644 --- a/src/H5B2int.c +++ b/src/H5B2int.c @@ -52,9 +52,9 @@ /********************/ /* Local Prototypes */ /********************/ -static herr_t H5B2__update_child_flush_depends(H5B2_hdr_t *hdr, unsigned depth, - const H5B2_node_ptr_t *node_ptrs, unsigned start_idx, - unsigned end_idx, void *old_parent, void *new_parent); +static herr_t H5B2__update_child_flush_depends(H5B2_hdr_t *hdr, unsigned depth, H5B2_node_ptr_t *node_ptrs, + unsigned start_idx, unsigned end_idx, void *old_parent, + void *new_parent); /*********************/ /* Package Variables */ @@ -1617,7 +1617,7 @@ done: *------------------------------------------------------------------------- */ herr_t -H5B2__iterate_node(H5B2_hdr_t *hdr, uint16_t depth, const H5B2_node_ptr_t *curr_node, void *parent, +H5B2__iterate_node(H5B2_hdr_t *hdr, uint16_t depth, H5B2_node_ptr_t *curr_node, void *parent, H5B2_operator_t op, void *op_data) { const H5AC_class_t *curr_node_class = NULL; /* Pointer to current node's class info */ @@ -1642,8 +1642,7 @@ H5B2__iterate_node(H5B2_hdr_t *hdr, uint16_t depth, const H5B2_node_ptr_t *curr_ /* Lock the current B-tree node */ if (NULL == - (internal = H5B2__protect_internal(hdr, parent, (H5B2_node_ptr_t *)curr_node, depth, FALSE, - H5AC__READ_ONLY_FLAG))) /* Casting away const OK -QAK */ + (internal = H5B2__protect_internal(hdr, parent, curr_node, depth, FALSE, H5AC__READ_ONLY_FLAG))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node") /* Set up information about current node */ @@ -1739,8 +1738,8 @@ done: *------------------------------------------------------------------------- */ herr_t -H5B2__delete_node(H5B2_hdr_t *hdr, uint16_t depth, const H5B2_node_ptr_t *curr_node, void *parent, - H5B2_remove_t op, void *op_data) +H5B2__delete_node(H5B2_hdr_t *hdr, uint16_t depth, H5B2_node_ptr_t *curr_node, void *parent, H5B2_remove_t op, + void *op_data) { const H5AC_class_t *curr_node_class = NULL; /* Pointer to current node's class info */ void * node = NULL; /* Pointers to current node */ @@ -1759,8 +1758,7 @@ H5B2__delete_node(H5B2_hdr_t *hdr, uint16_t depth, const H5B2_node_ptr_t *curr_n /* Lock the current B-tree node */ if (NULL == - (internal = H5B2__protect_internal(hdr, parent, (H5B2_node_ptr_t *)curr_node, depth, FALSE, - H5AC__NO_FLAGS_SET))) /* Casting away const OK -QAK */ + (internal = H5B2__protect_internal(hdr, parent, curr_node, depth, FALSE, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node") /* Set up information about current node */ @@ -1824,7 +1822,7 @@ done: *------------------------------------------------------------------------- */ herr_t -H5B2__node_size(H5B2_hdr_t *hdr, uint16_t depth, const H5B2_node_ptr_t *curr_node, void *parent, +H5B2__node_size(H5B2_hdr_t *hdr, uint16_t depth, H5B2_node_ptr_t *curr_node, void *parent, hsize_t *btree_size) { H5B2_internal_t *internal = NULL; /* Pointer to internal node */ @@ -1839,8 +1837,8 @@ H5B2__node_size(H5B2_hdr_t *hdr, uint16_t depth, const H5B2_node_ptr_t *curr_nod HDassert(depth > 0); /* Lock the current B-tree node */ - if (NULL == (internal = H5B2__protect_internal(hdr, parent, (H5B2_node_ptr_t *)curr_node, depth, FALSE, - H5AC__READ_ONLY_FLAG))) /* Casting away const OK -QAK */ + if (NULL == + (internal = H5B2__protect_internal(hdr, parent, curr_node, depth, FALSE, H5AC__READ_ONLY_FLAG))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node") /* Recursively descend into child nodes, if we are above the "twig" level in the B-tree */ @@ -1910,7 +1908,7 @@ done: *------------------------------------------------------------------------- */ herr_t -H5B2__update_flush_depend(H5B2_hdr_t *hdr, unsigned depth, const H5B2_node_ptr_t *node_ptr, void *old_parent, +H5B2__update_flush_depend(H5B2_hdr_t *hdr, unsigned depth, H5B2_node_ptr_t *node_ptr, void *old_parent, void *new_parent) { const H5AC_class_t *child_class; /* Pointer to child node's class info */ @@ -1941,9 +1939,8 @@ H5B2__update_flush_depend(H5B2_hdr_t *hdr, unsigned depth, const H5B2_node_ptr_t H5B2_internal_t *child_int; /* Protect child */ - if (NULL == (child_int = H5B2__protect_internal( - hdr, new_parent, (H5B2_node_ptr_t *)node_ptr, (uint16_t)(depth - 1), FALSE, - H5AC__NO_FLAGS_SET))) /* Casting away const OK -QAK */ + if (NULL == (child_int = H5B2__protect_internal(hdr, new_parent, node_ptr, (uint16_t)(depth - 1), + FALSE, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node") child_class = H5AC_BT2_INT; child = child_int; @@ -2010,7 +2007,7 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5B2__update_child_flush_depends(H5B2_hdr_t *hdr, unsigned depth, const H5B2_node_ptr_t *node_ptrs, +H5B2__update_child_flush_depends(H5B2_hdr_t *hdr, unsigned depth, H5B2_node_ptr_t *node_ptrs, unsigned start_idx, unsigned end_idx, void *old_parent, void *new_parent) { unsigned u; /* Local index variable */ diff --git a/src/H5B2internal.c b/src/H5B2internal.c index c00f555..a8192df 100644 --- a/src/H5B2internal.c +++ b/src/H5B2internal.c @@ -17,7 +17,7 @@ * Dec 01 2016 * Quincey Koziol * - * Purpose: Routines for managing v2 B-tree internal ndoes. + * Purpose: Routines for managing v2 B-tree internal nodes. * *------------------------------------------------------------------------- */ diff --git a/src/H5B2leaf.c b/src/H5B2leaf.c index 20ace84..f48cf5b 100644 --- a/src/H5B2leaf.c +++ b/src/H5B2leaf.c @@ -17,7 +17,7 @@ * Dec 01 2016 * Quincey Koziol * - * Purpose: Routines for managing v2 B-tree leaf ndoes. + * Purpose: Routines for managing v2 B-tree leaf nodes. * *------------------------------------------------------------------------- */ diff --git a/src/H5B2pkg.h b/src/H5B2pkg.h index 8d620cc..66d04fa 100644 --- a/src/H5B2pkg.h +++ b/src/H5B2pkg.h @@ -321,7 +321,7 @@ extern const H5B2_class_t *const H5B2_client_class_g[H5B2_NUM_BTREE_ID]; /* Generic routines */ H5_DLL herr_t H5B2__create_flush_depend(H5AC_info_t *parent_entry, H5AC_info_t *child_entry); -H5_DLL herr_t H5B2__update_flush_depend(H5B2_hdr_t *hdr, unsigned depth, const H5B2_node_ptr_t *node_ptr, +H5_DLL herr_t H5B2__update_flush_depend(H5B2_hdr_t *hdr, unsigned depth, H5B2_node_ptr_t *node_ptr, void *old_parent, void *new_parent); H5_DLL herr_t H5B2__destroy_flush_depend(H5AC_info_t *parent_entry, H5AC_info_t *child_entry); @@ -390,9 +390,9 @@ H5_DLL herr_t H5B2__update_leaf(H5B2_hdr_t *hdr, H5B2_node_ptr_t *curr_node_ptr, void *op_data); /* Routines for iterating over nodes/records */ -H5_DLL herr_t H5B2__iterate_node(H5B2_hdr_t *hdr, uint16_t depth, const H5B2_node_ptr_t *curr_node, - void *parent, H5B2_operator_t op, void *op_data); -H5_DLL herr_t H5B2__node_size(H5B2_hdr_t *hdr, uint16_t depth, const H5B2_node_ptr_t *curr_node, void *parent, +H5_DLL herr_t H5B2__iterate_node(H5B2_hdr_t *hdr, uint16_t depth, H5B2_node_ptr_t *curr_node, void *parent, + H5B2_operator_t op, void *op_data); +H5_DLL herr_t H5B2__node_size(H5B2_hdr_t *hdr, uint16_t depth, H5B2_node_ptr_t *curr_node, void *parent, hsize_t *op_data); /* Routines for locating records */ @@ -423,8 +423,8 @@ H5_DLL herr_t H5B2__remove_leaf_by_idx(H5B2_hdr_t *hdr, H5B2_node_ptr_t *curr_no void *op_data); /* Routines for deleting nodes */ -H5_DLL herr_t H5B2__delete_node(H5B2_hdr_t *hdr, uint16_t depth, const H5B2_node_ptr_t *curr_node, - void *parent, H5B2_remove_t op, void *op_data); +H5_DLL herr_t H5B2__delete_node(H5B2_hdr_t *hdr, uint16_t depth, H5B2_node_ptr_t *curr_node, void *parent, + H5B2_remove_t op, void *op_data); /* Debugging routines for dumping file structures */ H5_DLL herr_t H5B2__hdr_debug(H5F_t *f, haddr_t addr, FILE *stream, int indent, int fwidth, @@ -138,16 +138,6 @@ static herr_t H5C__generate_image(H5F_t *f, H5C_t *cache_ptr, H5C_cache_entry_t static herr_t H5C__verify_len_eoa(H5F_t *f, const H5C_class_t *type, haddr_t addr, size_t *len, hbool_t actual); -#if H5C_DO_SLIST_SANITY_CHECKS -static hbool_t H5C__entry_in_skip_list(H5C_t *cache_ptr, H5C_cache_entry_t *target_ptr); -#endif /* H5C_DO_SLIST_SANITY_CHECKS */ - -#if H5C_DO_EXTREME_SANITY_CHECKS -static herr_t H5C__validate_lru_list(H5C_t *cache_ptr); -static herr_t H5C__validate_pinned_entry_list(H5C_t *cache_ptr); -static herr_t H5C__validate_protected_entry_list(H5C_t *cache_ptr); -#endif /* H5C_DO_EXTREME_SANITY_CHECKS */ - #ifndef NDEBUG static void H5C__assert_flush_dep_nocycle(const H5C_cache_entry_t *entry, const H5C_cache_entry_t *base_entry); @@ -157,9 +147,6 @@ static void H5C__assert_flush_dep_nocycle(const H5C_cache_entry_t *entry, /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /* Declare a free list to manage the tag info struct */ H5FL_DEFINE(H5C_tag_info_t); @@ -781,7 +768,7 @@ H5C_prep_for_file_close(H5F_t *f) * * 2) Since the FSM settle routines are only invoked once during * file close, invoking them now will prevent their invocation - * during a flush, and thus avoid any resulting entrie dirties, + * during a flush, and thus avoid any resulting entry dirties, * deletions, insertion, or moves during the flush. */ if (H5C__serialize_cache(f) < 0) @@ -999,7 +986,7 @@ H5C_expunge_entry(H5F_t *f, const H5C_class_t *type, haddr_t addr, unsigned flag HDassert(H5F_addr_defined(addr)); #if H5C_DO_EXTREME_SANITY_CHECKS - if (H5C__validate_lru_list(cache_ptr) < 0) + if (H5C_validate_lru_list(cache_ptr) < 0) HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "LRU extreme sanity check failed on entry") #endif /* H5C_DO_EXTREME_SANITY_CHECKS */ @@ -1034,7 +1021,7 @@ H5C_expunge_entry(H5F_t *f, const H5C_class_t *type, haddr_t addr, unsigned flag done: #if H5C_DO_EXTREME_SANITY_CHECKS - if (H5C__validate_lru_list(cache_ptr) < 0) + if (H5C_validate_lru_list(cache_ptr) < 0) HDONE_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "LRU extreme sanity check failed on exit") #endif /* H5C_DO_EXTREME_SANITY_CHECKS */ @@ -1141,8 +1128,8 @@ H5C_flush_cache(H5F_t *f, unsigned flags) #endif /* H5C_DO_SANITY_CHECKS */ #if H5C_DO_EXTREME_SANITY_CHECKS - if ((H5C__validate_protected_entry_list(cache_ptr) < 0) || - (H5C__validate_pinned_entry_list(cache_ptr) < 0) || (H5C__validate_lru_list(cache_ptr) < 0)) + if ((H5C_validate_protected_entry_list(cache_ptr) < 0) || + (H5C_validate_pinned_entry_list(cache_ptr) < 0) || (H5C_validate_lru_list(cache_ptr) < 0)) HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on entry") #endif /* H5C_DO_EXTREME_SANITY_CHECKS */ @@ -1317,8 +1304,8 @@ H5C_insert_entry(H5F_t *f, const H5C_class_t *type, haddr_t addr, void *thing, u #if H5C_DO_EXTREME_SANITY_CHECKS /* no need to verify that entry is not already in the index as */ /* we already make that check below. */ - if ((H5C__validate_protected_entry_list(cache_ptr) < 0) || - (H5C__validate_pinned_entry_list(cache_ptr) < 0) || (H5C__validate_lru_list(cache_ptr) < 0)) + if ((H5C_validate_protected_entry_list(cache_ptr) < 0) || + (H5C_validate_pinned_entry_list(cache_ptr) < 0) || (H5C_validate_lru_list(cache_ptr) < 0)) HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on entry") #endif /* H5C_DO_EXTREME_SANITY_CHECKS */ @@ -1427,6 +1414,7 @@ H5C_insert_entry(H5F_t *f, const H5C_class_t *type, haddr_t addr, void *thing, u entry_ptr->serialization_count = 0; #endif /* NDEBUG */ + /* initialize tag list fields */ entry_ptr->tl_next = NULL; entry_ptr->tl_prev = NULL; entry_ptr->tag_info = NULL; @@ -1487,7 +1475,7 @@ H5C_insert_entry(H5F_t *f, const H5C_class_t *type, haddr_t addr, void *thing, u * Finally, we usually don't check to see if the cache is * oversized at the end of an unprotect. As a result, it is * possible to have a vastly oversized cache with no protected - * entries as long as all the protects preceed the unprotects. + * entries as long as all the protects precede the unprotects. * * Since items 1 and 2 are not changing any time soon, I see * no point in worrying about the third. @@ -1506,8 +1494,8 @@ H5C_insert_entry(H5F_t *f, const H5C_class_t *type, haddr_t addr, void *thing, u H5C__UPDATE_RP_FOR_INSERTION(cache_ptr, entry_ptr, FAIL) #if H5C_DO_EXTREME_SANITY_CHECKS - if ((H5C__validate_protected_entry_list(cache_ptr) < 0) || - (H5C__validate_pinned_entry_list(cache_ptr) < 0) || (H5C__validate_lru_list(cache_ptr) < 0)) + if ((H5C_validate_protected_entry_list(cache_ptr) < 0) || + (H5C_validate_pinned_entry_list(cache_ptr) < 0) || (H5C_validate_lru_list(cache_ptr) < 0)) HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed just before done") #endif /* H5C_DO_EXTREME_SANITY_CHECKS */ @@ -1521,23 +1509,32 @@ H5C_insert_entry(H5F_t *f, const H5C_class_t *type, haddr_t addr, void *thing, u #ifdef H5_HAVE_PARALLEL if (H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI)) - coll_access = H5CX_get_coll_metadata_read(); + coll_access = H5F_get_coll_metadata_reads(f); entry_ptr->coll_access = coll_access; if (coll_access) { H5C__INSERT_IN_COLL_LIST(cache_ptr, entry_ptr, FAIL) /* Make sure the size of the collective entries in the cache remain in check */ - if (cache_ptr->max_cache_size * 80 < cache_ptr->coll_list_size * 100) - if (H5C_clear_coll_entries(cache_ptr, TRUE) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "can't clear collective metadata entries") - } /* end if */ + if (H5P_USER_TRUE == H5F_COLL_MD_READ(f)) { + if (cache_ptr->max_cache_size * 80 < cache_ptr->coll_list_size * 100) { + if (H5C_clear_coll_entries(cache_ptr, TRUE) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "can't clear collective metadata entries") + } /* end if */ + } /* end if */ + else { + if (cache_ptr->max_cache_size * 40 < cache_ptr->coll_list_size * 100) { + if (H5C_clear_coll_entries(cache_ptr, TRUE) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "can't clear collective metadata entries") + } /* end if */ + } /* end else */ + } /* end if */ #endif done: #if H5C_DO_EXTREME_SANITY_CHECKS - if ((H5C__validate_protected_entry_list(cache_ptr) < 0) || - (H5C__validate_pinned_entry_list(cache_ptr) < 0) || (H5C__validate_lru_list(cache_ptr) < 0)) + if ((H5C_validate_protected_entry_list(cache_ptr) < 0) || + (H5C_validate_pinned_entry_list(cache_ptr) < 0) || (H5C_validate_lru_list(cache_ptr) < 0)) HDONE_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on exit") #endif /* H5C_DO_EXTREME_SANITY_CHECKS */ @@ -1861,8 +1858,8 @@ H5C_move_entry(H5C_t *cache_ptr, const H5C_class_t *type, haddr_t old_addr, hadd HDassert(H5F_addr_ne(old_addr, new_addr)); #if H5C_DO_EXTREME_SANITY_CHECKS - if ((H5C__validate_protected_entry_list(cache_ptr) < 0) || - (H5C__validate_pinned_entry_list(cache_ptr) < 0) || (H5C__validate_lru_list(cache_ptr) < 0)) + if ((H5C_validate_protected_entry_list(cache_ptr) < 0) || + (H5C_validate_pinned_entry_list(cache_ptr) < 0) || (H5C_validate_lru_list(cache_ptr) < 0)) HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on entry") #endif /* H5C_DO_EXTREME_SANITY_CHECKS */ @@ -1967,8 +1964,8 @@ H5C_move_entry(H5C_t *cache_ptr, const H5C_class_t *type, haddr_t old_addr, hadd done: #if H5C_DO_EXTREME_SANITY_CHECKS - if ((H5C__validate_protected_entry_list(cache_ptr) < 0) || - (H5C__validate_pinned_entry_list(cache_ptr) < 0) || (H5C__validate_lru_list(cache_ptr) < 0)) + if ((H5C_validate_protected_entry_list(cache_ptr) < 0) || + (H5C_validate_pinned_entry_list(cache_ptr) < 0) || (H5C_validate_lru_list(cache_ptr) < 0)) HDONE_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on exit") #endif /* H5C_DO_EXTREME_SANITY_CHECKS */ @@ -2014,8 +2011,7 @@ H5C_resize_entry(void *thing, size_t new_size) HGOTO_ERROR(H5E_CACHE, H5E_BADTYPE, FAIL, "Entry isn't pinned or protected??") #if H5C_DO_EXTREME_SANITY_CHECKS - if ((H5C__validate_protected_entry_list(cache_ptr) < 0) || - (H5C__validate_pinned_entry_list(cache_ptr) < 0)) + if ((H5C_validate_protected_entry_list(cache_ptr) < 0) || (H5C_validate_pinned_entry_list(cache_ptr) < 0)) HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on entry") #endif /* H5C_DO_EXTREME_SANITY_CHECKS */ @@ -2111,8 +2107,7 @@ H5C_resize_entry(void *thing, size_t new_size) done: #if H5C_DO_EXTREME_SANITY_CHECKS - if ((H5C__validate_protected_entry_list(cache_ptr) < 0) || - (H5C__validate_pinned_entry_list(cache_ptr) < 0)) + if ((H5C_validate_protected_entry_list(cache_ptr) < 0) || (H5C_validate_pinned_entry_list(cache_ptr) < 0)) HDONE_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on exit") #endif /* H5C_DO_EXTREME_SANITY_CHECKS */ @@ -2152,8 +2147,8 @@ H5C_pin_protected_entry(void *thing) HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC); #if H5C_DO_EXTREME_SANITY_CHECKS - if ((H5C__validate_protected_entry_list(cache_ptr) < 0) || - (H5C__validate_pinned_entry_list(cache_ptr) < 0) || (H5C__validate_lru_list(cache_ptr) < 0)) + if ((H5C_validate_protected_entry_list(cache_ptr) < 0) || + (H5C_validate_pinned_entry_list(cache_ptr) < 0) || (H5C_validate_lru_list(cache_ptr) < 0)) HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on entry") #endif /* H5C_DO_EXTREME_SANITY_CHECKS */ @@ -2167,8 +2162,8 @@ H5C_pin_protected_entry(void *thing) done: #if H5C_DO_EXTREME_SANITY_CHECKS - if ((H5C__validate_protected_entry_list(cache_ptr) < 0) || - (H5C__validate_pinned_entry_list(cache_ptr) < 0) || (H5C__validate_lru_list(cache_ptr) < 0)) + if ((H5C_validate_protected_entry_list(cache_ptr) < 0) || + (H5C_validate_pinned_entry_list(cache_ptr) < 0) || (H5C_validate_lru_list(cache_ptr) < 0)) HDONE_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on exit") #endif /* H5C_DO_EXTREME_SANITY_CHECKS */ @@ -2231,8 +2226,8 @@ H5C_protect(H5F_t *f, const H5C_class_t *type, haddr_t addr, void *udata, unsign HDassert(H5F_addr_defined(addr)); #if H5C_DO_EXTREME_SANITY_CHECKS - if ((H5C__validate_protected_entry_list(cache_ptr) < 0) || - (H5C__validate_pinned_entry_list(cache_ptr) < 0) || (H5C__validate_lru_list(cache_ptr) < 0)) + if ((H5C_validate_protected_entry_list(cache_ptr) < 0) || + (H5C_validate_pinned_entry_list(cache_ptr) < 0) || (H5C_validate_lru_list(cache_ptr) < 0)) HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, NULL, "an extreme sanity check failed on entry") #endif /* H5C_DO_EXTREME_SANITY_CHECKS */ @@ -2251,7 +2246,7 @@ H5C_protect(H5F_t *f, const H5C_class_t *type, haddr_t addr, void *udata, unsign #ifdef H5_HAVE_PARALLEL if (H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI)) - coll_access = H5CX_get_coll_metadata_read(); + coll_access = H5F_get_coll_metadata_reads(f); #endif /* H5_HAVE_PARALLEL */ /* first check to see if the target is in cache */ @@ -2310,9 +2305,14 @@ H5C_protect(H5F_t *f, const H5C_class_t *type, haddr_t addr, void *udata, unsign H5MM_memcpy(((uint8_t *)entry_ptr->image_ptr) + entry_ptr->size, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE); #endif /* H5C_DO_MEMORY_SANITY_CHECKS */ - if (0 == mpi_rank) - if (H5C__generate_image(f, cache_ptr, entry_ptr) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, NULL, "can't generate entry's image") + if (0 == mpi_rank) { + if (H5C__generate_image(f, cache_ptr, entry_ptr) < 0) { + /* If image generation fails, push an error but + * still participate in the following MPI_Bcast + */ + HDONE_ERROR(H5E_CACHE, H5E_CANTGET, NULL, "can't generate entry's image") + } + } } /* end if */ HDassert(entry_ptr->image_ptr); @@ -2447,7 +2447,7 @@ H5C_protect(H5F_t *f, const H5C_class_t *type, haddr_t addr, void *udata, unsign * Finally, we usually don't check to see if the cache is * oversized at the end of an unprotect. As a result, it is * possible to have a vastly oversized cache with no protected - * entries as long as all the protects preceed the unprotects. + * entries as long as all the protects precede the unprotects. * * Since items 1, 2, and 3 are not changing any time soon, I * see no point in worrying about the fourth. @@ -2562,7 +2562,7 @@ H5C_protect(H5F_t *f, const H5C_class_t *type, haddr_t addr, void *udata, unsign * * Also, if the min_clean_size requirement is not met, we * should also call H5C__make_space_in_cache() to bring us - * into complience. + * into compliance. */ if (cache_ptr->index_size >= cache_ptr->max_cache_size) @@ -2598,16 +2598,24 @@ H5C_protect(H5F_t *f, const H5C_class_t *type, haddr_t addr, void *udata, unsign #ifdef H5_HAVE_PARALLEL /* Make sure the size of the collective entries in the cache remain in check */ - if (coll_access) - if (cache_ptr->max_cache_size * 80 < cache_ptr->coll_list_size * 100) - if (H5C_clear_coll_entries(cache_ptr, TRUE) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, NULL, "can't clear collective metadata entries") -#endif /* H5_HAVE_PARALLEL */ + if (coll_access) { + if (H5P_USER_TRUE == H5F_COLL_MD_READ(f)) { + if (cache_ptr->max_cache_size * 80 < cache_ptr->coll_list_size * 100) + if (H5C_clear_coll_entries(cache_ptr, TRUE) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, NULL, "can't clear collective metadata entries") + } /* end if */ + else { + if (cache_ptr->max_cache_size * 40 < cache_ptr->coll_list_size * 100) + if (H5C_clear_coll_entries(cache_ptr, TRUE) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, NULL, "can't clear collective metadata entries") + } /* end else */ + } /* end if */ +#endif /* H5_HAVE_PARALLEL */ done: #if H5C_DO_EXTREME_SANITY_CHECKS - if ((H5C__validate_protected_entry_list(cache_ptr) < 0) || - (H5C__validate_pinned_entry_list(cache_ptr) < 0) || (H5C__validate_lru_list(cache_ptr) < 0)) + if ((H5C_validate_protected_entry_list(cache_ptr) < 0) || + (H5C_validate_pinned_entry_list(cache_ptr) < 0) || (H5C_validate_lru_list(cache_ptr) < 0)) HDONE_ERROR(H5E_CACHE, H5E_SYSTEM, NULL, "an extreme sanity check failed on exit") #endif /* H5C_DO_EXTREME_SANITY_CHECKS */ @@ -3080,8 +3088,8 @@ H5C_unpin_entry(void *_entry_ptr) HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC); #if H5C_DO_EXTREME_SANITY_CHECKS - if ((H5C__validate_protected_entry_list(cache_ptr) < 0) || - (H5C__validate_pinned_entry_list(cache_ptr) < 0) || (H5C__validate_lru_list(cache_ptr) < 0)) + if ((H5C_validate_protected_entry_list(cache_ptr) < 0) || + (H5C_validate_pinned_entry_list(cache_ptr) < 0) || (H5C_validate_lru_list(cache_ptr) < 0)) HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on entry") #endif /* H5C_DO_EXTREME_SANITY_CHECKS */ @@ -3091,8 +3099,8 @@ H5C_unpin_entry(void *_entry_ptr) done: #if H5C_DO_EXTREME_SANITY_CHECKS - if ((H5C__validate_protected_entry_list(cache_ptr) < 0) || - (H5C__validate_pinned_entry_list(cache_ptr) < 0) || (H5C__validate_lru_list(cache_ptr) < 0)) + if ((H5C_validate_protected_entry_list(cache_ptr) < 0) || + (H5C_validate_pinned_entry_list(cache_ptr) < 0) || (H5C_validate_lru_list(cache_ptr) < 0)) HDONE_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on exit") #endif /* H5C_DO_EXTREME_SANITY_CHECKS */ @@ -3259,8 +3267,8 @@ H5C_unprotect(H5F_t *f, haddr_t addr, void *thing, unsigned flags) was_clean = !(entry_ptr->is_dirty); #if H5C_DO_EXTREME_SANITY_CHECKS - if ((H5C__validate_protected_entry_list(cache_ptr) < 0) || - (H5C__validate_pinned_entry_list(cache_ptr) < 0) || (H5C__validate_lru_list(cache_ptr) < 0)) + if ((H5C_validate_protected_entry_list(cache_ptr) < 0) || + (H5C_validate_pinned_entry_list(cache_ptr) < 0) || (H5C_validate_lru_list(cache_ptr) < 0)) HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on entry") #endif /* H5C_DO_EXTREME_SANITY_CHECKS */ @@ -3526,8 +3534,8 @@ H5C_unprotect(H5F_t *f, haddr_t addr, void *thing, unsigned flags) done: #if H5C_DO_EXTREME_SANITY_CHECKS - if ((H5C__validate_protected_entry_list(cache_ptr) < 0) || - (H5C__validate_pinned_entry_list(cache_ptr) < 0) || (H5C__validate_lru_list(cache_ptr) < 0)) + if ((H5C_validate_protected_entry_list(cache_ptr) < 0) || + (H5C_validate_pinned_entry_list(cache_ptr) < 0) || (H5C_validate_lru_list(cache_ptr) < 0)) HDONE_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on exit") #endif /* H5C_DO_EXTREME_SANITY_CHECKS */ @@ -4851,7 +4859,7 @@ H5C__autoadjust__ageout__evict_aged_out_entries(H5F_t *f, hbool_t write_permitte /* for now at least, don't bother to maintain the minimum clean size, * as the cache should now be less than its maximum size. Due to - * the vaguries of the cache size reduction algorthim, we may not + * the vaguries of the cache size reduction algorithm, we may not * reduce the size of the cache. * * If we do, we will calculate a new minimum clean size, which will @@ -5863,7 +5871,7 @@ H5C__flush_invalidate_ring(H5F_t *f, H5C_ring_t ring, unsigned flags) * If either of these happen, and one of the target * or proxy entries happens to be the next entry in * the hash bucket, we could either find ourselves - * either scanning a non-existant entry, scanning + * either scanning a non-existent entry, scanning * through a different bucket, or skipping an entry. * * Neither of these are good, so restart the @@ -6061,8 +6069,8 @@ H5C__flush_ring(H5F_t *f, H5C_ring_t ring, unsigned flags) HDassert(ring < H5C_RING_NTYPES); #if H5C_DO_EXTREME_SANITY_CHECKS - if ((H5C__validate_protected_entry_list(cache_ptr) < 0) || - (H5C__validate_pinned_entry_list(cache_ptr) < 0) || (H5C__validate_lru_list(cache_ptr) < 0)) + if ((H5C_validate_protected_entry_list(cache_ptr) < 0) || + (H5C_validate_pinned_entry_list(cache_ptr) < 0) || (H5C_validate_lru_list(cache_ptr) < 0)) HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on entry") #endif /* H5C_DO_EXTREME_SANITY_CHECKS */ @@ -7185,8 +7193,20 @@ H5C__load_entry(H5F_t *f, #ifdef H5_HAVE_PARALLEL if (!coll_access || 0 == mpi_rank) { #endif /* H5_HAVE_PARALLEL */ - if (H5F_block_read(f, type->mem_type, addr, len, image) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_READERROR, NULL, "Can't read image*") + + if (H5F_block_read(f, type->mem_type, addr, len, image) < 0) { + +#ifdef H5_HAVE_PARALLEL + if (coll_access) { + /* Push an error, but still participate in following MPI_Bcast */ + HDmemset(image, 0, len); + HDONE_ERROR(H5E_CACHE, H5E_READERROR, NULL, "Can't read image*") + } + else +#endif + HGOTO_ERROR(H5E_CACHE, H5E_READERROR, NULL, "Can't read image*") + } + #ifdef H5_HAVE_PARALLEL } /* end if */ /* if the collective metadata read optimization is turned on, @@ -7233,8 +7253,19 @@ H5C__load_entry(H5F_t *f, * loaded thing, go get the on-disk image again (the extra portion). */ if (H5F_block_read(f, type->mem_type, addr + len, actual_len - len, image + len) < - 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, "can't read image") + 0) { + +#ifdef H5_HAVE_PARALLEL + if (coll_access) { + /* Push an error, but still participate in following MPI_Bcast */ + HDmemset(image + len, 0, actual_len - len); + HDONE_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, "can't read image") + } + else +#endif + HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, "can't read image") + } + #ifdef H5_HAVE_PARALLEL } /* If the collective metadata read optimization is turned on, @@ -7386,6 +7417,7 @@ H5C__load_entry(H5F_t *f, entry->serialization_count = 0; #endif /* NDEBUG */ + /* initialize tag list fields */ entry->tl_next = NULL; entry->tl_prev = NULL; entry->tag_info = NULL; @@ -7714,7 +7746,7 @@ done: /*------------------------------------------------------------------------- * - * Function: H5C__validate_lru_list + * Function: H5C_validate_lru_list * * Purpose: Debugging function that scans the LRU list for errors. * @@ -7729,15 +7761,15 @@ done: *------------------------------------------------------------------------- */ #if H5C_DO_EXTREME_SANITY_CHECKS -static herr_t -H5C__validate_lru_list(H5C_t *cache_ptr) +herr_t +H5C_validate_lru_list(H5C_t *cache_ptr) { int32_t len = 0; size_t size = 0; H5C_cache_entry_t *entry_ptr = NULL; herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_STATIC + FUNC_ENTER_NOAPI(FAIL) HDassert(cache_ptr); HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC); @@ -7746,51 +7778,48 @@ H5C__validate_lru_list(H5C_t *cache_ptr) (cache_ptr->LRU_head_ptr != cache_ptr->LRU_tail_ptr)) HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 1 failed") - if (cache_ptr->LRU_list_len < 0) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 2 failed") - if ((cache_ptr->LRU_list_len == 1) && ((cache_ptr->LRU_head_ptr != cache_ptr->LRU_tail_ptr) || (cache_ptr->LRU_head_ptr == NULL) || (cache_ptr->LRU_head_ptr->size != cache_ptr->LRU_list_size))) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 3 failed") + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 2 failed") if ((cache_ptr->LRU_list_len >= 1) && ((cache_ptr->LRU_head_ptr == NULL) || (cache_ptr->LRU_head_ptr->prev != NULL) || (cache_ptr->LRU_tail_ptr == NULL) || (cache_ptr->LRU_tail_ptr->next != NULL))) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 4 failed") + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 3 failed") entry_ptr = cache_ptr->LRU_head_ptr; while (entry_ptr != NULL) { if ((entry_ptr != cache_ptr->LRU_head_ptr) && ((entry_ptr->prev == NULL) || (entry_ptr->prev->next != entry_ptr))) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 5 failed") + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 4 failed") if ((entry_ptr != cache_ptr->LRU_tail_ptr) && ((entry_ptr->next == NULL) || (entry_ptr->next->prev != entry_ptr))) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 6 failed") + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 5 failed") if ((entry_ptr->is_pinned) || (entry_ptr->pinned_from_client) || (entry_ptr->pinned_from_cache)) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 7 failed") + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 6 failed") len++; size += entry_ptr->size; entry_ptr = entry_ptr->next; } - if ((cache_ptr->LRU_list_len != len) || (cache_ptr->LRU_list_size != size)) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 8 failed") + if ((cache_ptr->LRU_list_len != (uint32_t)len) || (cache_ptr->LRU_list_size != size)) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 7 failed") done: if (ret_value != SUCCEED) HDassert(0); FUNC_LEAVE_NOAPI(ret_value) -} /* H5C__validate_lru_list() */ +} /* H5C_validate_lru_list() */ #endif /* H5C_DO_EXTREME_SANITY_CHECKS */ /*------------------------------------------------------------------------- * - * Function: H5C__validate_pinned_entry_list + * Function: H5C_validate_pinned_entry_list * * Purpose: Debugging function that scans the pinned entry list for * errors. @@ -7806,15 +7835,15 @@ done: *------------------------------------------------------------------------- */ #if H5C_DO_EXTREME_SANITY_CHECKS -static herr_t -H5C__validate_pinned_entry_list(H5C_t *cache_ptr) +herr_t +H5C_validate_pinned_entry_list(H5C_t *cache_ptr) { int32_t len = 0; size_t size = 0; H5C_cache_entry_t *entry_ptr = NULL; herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_STATIC + FUNC_ENTER_NOAPI(FAIL) HDassert(cache_ptr); HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC); @@ -7823,54 +7852,51 @@ H5C__validate_pinned_entry_list(H5C_t *cache_ptr) (cache_ptr->pel_head_ptr != cache_ptr->pel_tail_ptr)) HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 1 failed") - if (cache_ptr->pel_len < 0) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 2 failed") - if ((cache_ptr->pel_len == 1) && ((cache_ptr->pel_head_ptr != cache_ptr->pel_tail_ptr) || (cache_ptr->pel_head_ptr == NULL) || (cache_ptr->pel_head_ptr->size != cache_ptr->pel_size))) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 3 failed") + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 2 failed") if ((cache_ptr->pel_len >= 1) && ((cache_ptr->pel_head_ptr == NULL) || (cache_ptr->pel_head_ptr->prev != NULL) || (cache_ptr->pel_tail_ptr == NULL) || (cache_ptr->pel_tail_ptr->next != NULL))) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 4 failed") + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 3 failed") entry_ptr = cache_ptr->pel_head_ptr; while (entry_ptr != NULL) { if ((entry_ptr != cache_ptr->pel_head_ptr) && ((entry_ptr->prev == NULL) || (entry_ptr->prev->next != entry_ptr))) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 5 failed") + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 4 failed") if ((entry_ptr != cache_ptr->pel_tail_ptr) && ((entry_ptr->next == NULL) || (entry_ptr->next->prev != entry_ptr))) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 6 failed") + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 5 failed") if (!entry_ptr->is_pinned) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 7 failed") + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 6 failed") if (!(entry_ptr->pinned_from_client || entry_ptr->pinned_from_cache)) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 8 failed") + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 7 failed") len++; size += entry_ptr->size; entry_ptr = entry_ptr->next; } - if ((cache_ptr->pel_len != len) || (cache_ptr->pel_size != size)) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 9 failed") + if ((cache_ptr->pel_len != (uint32_t)len) || (cache_ptr->pel_size != size)) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 8 failed") done: if (ret_value != SUCCEED) HDassert(0); FUNC_LEAVE_NOAPI(ret_value) -} /* H5C__validate_pinned_entry_list() */ +} /* H5C_validate_pinned_entry_list() */ #endif /* H5C_DO_EXTREME_SANITY_CHECKS */ /*------------------------------------------------------------------------- * - * Function: H5C__validate_protected_entry_list + * Function: H5C_validate_protected_entry_list * * Purpose: Debugging function that scans the protected entry list for * errors. @@ -7886,15 +7912,15 @@ done: *------------------------------------------------------------------------- */ #if H5C_DO_EXTREME_SANITY_CHECKS -static herr_t -H5C__validate_protected_entry_list(H5C_t *cache_ptr) +herr_t +H5C_validate_protected_entry_list(H5C_t *cache_ptr) { int32_t len = 0; size_t size = 0; H5C_cache_entry_t *entry_ptr = NULL; herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_STATIC + FUNC_ENTER_NOAPI(FAIL) HDassert(cache_ptr); HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC); @@ -7903,54 +7929,51 @@ H5C__validate_protected_entry_list(H5C_t *cache_ptr) (cache_ptr->pl_head_ptr != cache_ptr->pl_tail_ptr)) HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 1 failed") - if (cache_ptr->pl_len < 0) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 2 failed") - if ((cache_ptr->pl_len == 1) && ((cache_ptr->pl_head_ptr != cache_ptr->pl_tail_ptr) || (cache_ptr->pl_head_ptr == NULL) || (cache_ptr->pl_head_ptr->size != cache_ptr->pl_size))) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 3 failed") + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 2 failed") if ((cache_ptr->pl_len >= 1) && ((cache_ptr->pl_head_ptr == NULL) || (cache_ptr->pl_head_ptr->prev != NULL) || (cache_ptr->pl_tail_ptr == NULL) || (cache_ptr->pl_tail_ptr->next != NULL))) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 4 failed") + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 3 failed") entry_ptr = cache_ptr->pl_head_ptr; while (entry_ptr != NULL) { if ((entry_ptr != cache_ptr->pl_head_ptr) && ((entry_ptr->prev == NULL) || (entry_ptr->prev->next != entry_ptr))) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 5 failed") + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 4 failed") if ((entry_ptr != cache_ptr->pl_tail_ptr) && ((entry_ptr->next == NULL) || (entry_ptr->next->prev != entry_ptr))) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 6 failed") + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 5 failed") if (!entry_ptr->is_protected) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 7 failed") + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 6 failed") if (entry_ptr->is_read_only && (entry_ptr->ro_ref_count <= 0)) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 8 failed") + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 7 failed") len++; size += entry_ptr->size; entry_ptr = entry_ptr->next; } - if ((cache_ptr->pl_len != len) || (cache_ptr->pl_size != size)) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 9 failed") + if ((cache_ptr->pl_len != (uint32_t)len) || (cache_ptr->pl_size != size)) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 8 failed") done: if (ret_value != SUCCEED) HDassert(0); FUNC_LEAVE_NOAPI(ret_value) -} /* H5C__validate_protected_entry_list() */ +} /* H5C_validate_protected_entry_list() */ #endif /* H5C_DO_EXTREME_SANITY_CHECKS */ /*------------------------------------------------------------------------- * - * Function: H5C__entry_in_skip_list + * Function: H5C_entry_in_skip_list * * Purpose: Debugging function that scans skip list to see if it * is in present. We need this, as it is possible for @@ -7964,8 +7987,8 @@ done: *------------------------------------------------------------------------- */ #if H5C_DO_SLIST_SANITY_CHECKS -static hbool_t -H5C__entry_in_skip_list(H5C_t *cache_ptr, H5C_cache_entry_t *target_ptr) +hbool_t +H5C_entry_in_skip_list(H5C_t *cache_ptr, H5C_cache_entry_t *target_ptr) { H5SL_node_t *node_ptr; hbool_t in_slist; @@ -7993,7 +8016,7 @@ H5C__entry_in_skip_list(H5C_t *cache_ptr, H5C_cache_entry_t *target_ptr) } return (in_slist); -} /* H5C__entry_in_skip_list() */ +} /* H5C_entry_in_skip_list() */ #endif /* H5C_DO_SLIST_SANITY_CHECKS */ /*------------------------------------------------------------------------- @@ -8062,7 +8085,7 @@ done: * To cork the object * Return error if the object is already corked * H5C__UNCORK: - * To uncork the obejct + * To uncork the object * Return error if the object is not corked * H5C__GET_CORKED: * To retrieve the cork status of an object in @@ -8483,8 +8506,8 @@ H5C__serialize_cache(H5F_t *f) #endif /* H5C_DO_SANITY_CHECKS */ #if H5C_DO_EXTREME_SANITY_CHECKS - if ((H5C__validate_protected_entry_list(cache_ptr) < 0) || - (H5C__validate_pinned_entry_list(cache_ptr) < 0) || (H5C__validate_lru_list(cache_ptr) < 0)) + if ((H5C_validate_protected_entry_list(cache_ptr) < 0) || + (H5C_validate_pinned_entry_list(cache_ptr) < 0) || (H5C_validate_lru_list(cache_ptr) < 0)) HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on entry") #endif /* H5C_DO_EXTREME_SANITY_CHECKS */ @@ -8493,7 +8516,7 @@ H5C__serialize_cache(H5F_t *f) * each entry in the cache to zero before we start the serialization. * This allows us to detect the case in which any entry is serialized * more than once (a performance issues), and more importantly, the - * case is which any flush depencency parent is serializes more than + * case is which any flush dependency parent is serializes more than * once (a correctness issue). */ { @@ -8650,8 +8673,8 @@ H5C__serialize_ring(H5F_t *f, H5C_ring_t ring) * are serialized correctly, it doesn't matter if we have to go back * and serialize an entry a second time. * - * These possible actions result in the following modfications to - * tha basic algorithm: + * These possible actions result in the following modifications to + * the basic algorithm: * * 1) In the event of an entry expunge, eviction or removal, we must * restart the scan as it is possible that the next entry in our @@ -8701,7 +8724,7 @@ H5C__serialize_ring(H5F_t *f, H5C_ring_t ring) * condition appears. * * Observe that either eviction or removal of entries as a result of - * a serialization is not a problem as long as the flush depencency + * a serialization is not a problem as long as the flush dependency * tree does not change beyond the removal of a leaf. */ while (!done) { @@ -47,7 +47,7 @@ typedef struct H5CS_t { * each thread individually. The association of stacks to threads will * be handled by the pthread library. * - * In order for this macro to work, H5CS_get_my_stack() must be preceeded + * In order for this macro to work, H5CS_get_my_stack() must be preceded * by "H5CS_t *fstack =". */ static H5CS_t *H5CS__get_stack(void); @@ -127,7 +127,7 @@ H5CS__get_stack(void) herr_t H5CS_print_stack(const H5CS_t *fstack, FILE *stream) { - const int indent = 2; /* Indention level */ + const int indent = 2; /* Indentation level */ int i; /* Local index ariable */ /* Don't push this function on the function stack... :-) */ diff --git a/src/H5CSprivate.h b/src/H5CSprivate.h index a238ec7..2dc28f5 100644 --- a/src/H5CSprivate.h +++ b/src/H5CSprivate.h @@ -17,10 +17,6 @@ #ifndef H5CSprivate_H #define H5CSprivate_H -#ifdef NOT_YET -#include "H5CSpublic.h" -#endif /* NOT_YET */ - /* Private headers needed by this file */ #include "H5private.h" @@ -50,7 +50,7 @@ * each thread individually. The association of contexts to threads will * be handled by the pthread library. * - * In order for this macro to work, H5CX_get_my_context() must be preceeded + * In order for this macro to work, H5CX_get_my_context() must be preceded * by "H5CX_node_t *ctx =". */ #define H5CX_get_my_context() H5CX__get_context() @@ -428,9 +428,6 @@ static H5CX_node_t *H5CX__pop_common(hbool_t update_dxpl_props); /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /*******************/ /* Local Variables */ /*******************/ @@ -463,18 +460,17 @@ H5FL_DEFINE_STATIC(H5CX_node_t); /* Declare a static free list to manage H5CX_state_t structs */ H5FL_DEFINE_STATIC(H5CX_state_t); -/*-------------------------------------------------------------------------- -NAME - H5CX__init_package -- Initialize interface-specific information -USAGE - herr_t H5CX__init_package() -RETURNS - Non-negative on success/Negative on failure -DESCRIPTION - Initializes any interface-specific data or routines. ---------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------- + * Function: H5CX_init + * + * Purpose: Initialize the interface from some other layer. + * + * Return: Success: non-negative + * Failure: negative + *------------------------------------------------------------------------- + */ herr_t -H5CX__init_package(void) +H5CX_init(void) { H5P_genplist_t *dx_plist; /* Data transfer property list */ H5P_genplist_t *lc_plist; /* Link creation property list */ @@ -484,7 +480,7 @@ H5CX__init_package(void) H5P_genplist_t *fa_plist; /* File access property list */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_STATIC + FUNC_ENTER_NOAPI(FAIL) /* Reset the "default DXPL cache" information */ HDmemset(&H5CX_def_dxpl_cache, 0, sizeof(H5CX_dxpl_cache_t)); @@ -649,10 +645,9 @@ H5CX__init_package(void) if (H5P_get(fa_plist, H5F_ACS_LIBVER_HIGH_BOUND_NAME, &H5CX_def_fapl_cache.high_bound) < 0) HGOTO_ERROR(H5E_CONTEXT, H5E_CANTGET, FAIL, "Can't retrieve dataset minimize flag") - done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5CX__init_package() */ +} /*------------------------------------------------------------------------- * Function: H5CX_term_package @@ -673,24 +668,20 @@ H5CX_term_package(void) { FUNC_ENTER_NOAPI_NOINIT_NOERR - if (H5_PKG_INIT_VAR) { - H5CX_node_t *cnode; /* Context node */ + H5CX_node_t *cnode; /* Context node */ - /* Pop the top context node from the stack */ - /* (Can't check for errors, as rest of library is shut down) */ - cnode = H5CX__pop_common(FALSE); + /* Pop the top context node from the stack */ + /* (Can't check for errors, as rest of library is shut down) */ + cnode = H5CX__pop_common(FALSE); - /* Free the context node */ - /* (Allocated with HDmalloc() in H5CX_push_special() ) */ - HDfree(cnode); + /* Free the context node */ + /* (Allocated with HDmalloc() in H5CX_push_special() ) */ + HDfree(cnode); #ifndef H5_HAVE_THREADSAFE - H5CX_head_g = NULL; + H5CX_head_g = NULL; #endif /* H5_HAVE_THREADSAFE */ - H5_PKG_INIT_VAR = FALSE; - } /* end if */ - FUNC_LEAVE_NOAPI(0) } /* end H5CX_term_package() */ @@ -1227,7 +1218,7 @@ H5CX_set_libver_bounds(H5F_t *f) H5CX_node_t **head = NULL; /* Pointer to head of API context list */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR /* Sanity check */ head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */ @@ -1241,7 +1232,6 @@ H5CX_set_libver_bounds(H5F_t *f) (*head)->ctx.low_bound_valid = TRUE; (*head)->ctx.high_bound_valid = TRUE; -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5CX_set_libver_bounds() */ @@ -1407,9 +1397,7 @@ H5CX_set_apl(hid_t *acspl_id, const H5P_libclass_t *libclass, /* If parallel is enabled and the file driver used is the MPI-IO * VFD, issue an MPI barrier for easier debugging if the API function - * calling this is supposed to be called collectively. Note that this - * happens only when the environment variable H5_COLL_BARRIER is set - * to non 0. + * calling this is supposed to be called collectively. */ if (H5_coll_api_sanity_check_g) { MPI_Comm mpi_comm; /* File communicator */ @@ -1435,7 +1423,7 @@ done: * Purpose: Sanity checks and sets up collective operations. * * Note: Should be called for all API routines that modify file - * file metadata but don't pass in an access property list. + * metadata but don't pass in an access property list. * * Return: Non-negative on success / Negative on failure * @@ -1466,9 +1454,7 @@ H5CX_set_loc(hid_t /* If parallel is enabled and the file driver used is the MPI-IO * VFD, issue an MPI barrier for easier debugging if the API function - * calling this is supposed to be called collectively. Note that this - * happens only when the environment variable H5_COLL_BARRIER is set - * to non 0. + * calling this is supposed to be called collectively. */ if (H5_coll_api_sanity_check_g) { MPI_Comm mpi_comm; /* File communicator */ @@ -1509,7 +1495,7 @@ H5CX_set_vol_wrap_ctx(void *vol_wrap_ctx) H5CX_node_t **head = NULL; /* Pointer to head of API context list */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR /* Sanity check */ head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */ @@ -1521,7 +1507,6 @@ H5CX_set_vol_wrap_ctx(void *vol_wrap_ctx) /* Mark the value as valid */ (*head)->ctx.vol_wrap_ctx_valid = TRUE; -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5CX_set_vol_wrap_ctx() */ @@ -1543,7 +1528,7 @@ H5CX_set_vol_connector_prop(const H5VL_connector_prop_t *vol_connector_prop) H5CX_node_t **head = NULL; /* Pointer to head of API context list */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR /* Sanity check */ head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */ @@ -1555,7 +1540,6 @@ H5CX_set_vol_connector_prop(const H5VL_connector_prop_t *vol_connector_prop) /* Mark the value as valid */ (*head)->ctx.vol_connector_prop_valid = TRUE; -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5CX_set_vol_connector_prop() */ @@ -1637,7 +1621,7 @@ H5CX_get_vol_wrap_ctx(void **vol_wrap_ctx) H5CX_node_t **head = NULL; /* Pointer to head of API context list */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR /* Sanity check */ HDassert(vol_wrap_ctx); @@ -1651,7 +1635,6 @@ H5CX_get_vol_wrap_ctx(void **vol_wrap_ctx) else *vol_wrap_ctx = NULL; -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5CX_get_vol_wrap_ctx() */ @@ -1673,7 +1656,7 @@ H5CX_get_vol_connector_prop(H5VL_connector_prop_t *vol_connector_prop) H5CX_node_t **head = NULL; /* Pointer to head of API context list */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR /* Sanity check */ HDassert(vol_connector_prop); @@ -1687,7 +1670,6 @@ H5CX_get_vol_connector_prop(H5VL_connector_prop_t *vol_connector_prop) else HDmemset(vol_connector_prop, 0, sizeof(H5VL_connector_prop_t)); -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5CX_get_vol_connector_prop() */ @@ -1803,7 +1785,7 @@ H5CX_get_mpi_coll_datatypes(MPI_Datatype *btype, MPI_Datatype *ftype) H5CX_node_t **head = NULL; /* Pointer to head of API context list */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR /* Sanity check */ HDassert(btype); @@ -1815,7 +1797,6 @@ H5CX_get_mpi_coll_datatypes(MPI_Datatype *btype, MPI_Datatype *ftype) *btype = (*head)->ctx.btype; *ftype = (*head)->ctx.ftype; -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5CX_get_mpi_coll_datatypes() */ @@ -2977,7 +2958,7 @@ H5CX_set_mpi_coll_datatypes(MPI_Datatype btype, MPI_Datatype ftype) herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR /* Sanity check */ head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */ @@ -2987,7 +2968,6 @@ H5CX_set_mpi_coll_datatypes(MPI_Datatype btype, MPI_Datatype ftype) (*head)->ctx.btype = btype; (*head)->ctx.ftype = ftype; -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5CX_set_mpi_coll_datatypes() */ @@ -3009,7 +2989,7 @@ H5CX_set_io_xfer_mode(H5FD_mpio_xfer_t io_xfer_mode) H5CX_node_t **head = NULL; /* Pointer to head of API context list */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR /* Sanity check */ head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */ @@ -3021,7 +3001,6 @@ H5CX_set_io_xfer_mode(H5FD_mpio_xfer_t io_xfer_mode) /* Mark the value as valid */ (*head)->ctx.io_xfer_mode_valid = TRUE; -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5CX_set_io_xfer_mode() */ @@ -3043,7 +3022,7 @@ H5CX_set_mpio_coll_opt(H5FD_mpio_collective_opt_t mpio_coll_opt) H5CX_node_t **head = NULL; /* Pointer to head of API context list */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR /* Sanity check */ head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */ @@ -3055,7 +3034,6 @@ H5CX_set_mpio_coll_opt(H5FD_mpio_collective_opt_t mpio_coll_opt) /* Mark the value as valid */ (*head)->ctx.mpio_coll_opt_valid = TRUE; -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5CX_set_mpio_coll_opt() */ @@ -3135,7 +3113,7 @@ H5CX_set_vlen_alloc_info(H5MM_allocate_t alloc_func, void *alloc_info, H5MM_free H5CX_node_t **head = NULL; /* Pointer to head of API context list */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR /* Sanity check */ head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */ @@ -3150,7 +3128,6 @@ H5CX_set_vlen_alloc_info(H5MM_allocate_t alloc_func, void *alloc_info, H5MM_free /* Mark the value as valid */ (*head)->ctx.vl_alloc_info_valid = TRUE; -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5CX_set_vlen_alloc_info() */ @@ -3172,7 +3149,7 @@ H5CX_set_nlinks(size_t nlinks) H5CX_node_t **head = NULL; /* Pointer to head of API context list */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR /* Sanity check */ head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */ @@ -3184,7 +3161,6 @@ H5CX_set_nlinks(size_t nlinks) /* Mark the value as valid */ (*head)->ctx.nlinks_valid = TRUE; -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5CX_set_nlinks() */ diff --git a/src/H5CXprivate.h b/src/H5CXprivate.h index c500356..878bcf6 100644 --- a/src/H5CXprivate.h +++ b/src/H5CXprivate.h @@ -16,11 +16,6 @@ #ifndef H5CXprivate_H #define H5CXprivate_H -/* Include package's public header */ -#ifdef NOT_YET -#include "H5CXpublic.h" -#endif /* NOT_YET */ - /* Private headers needed by this file */ #include "H5private.h" /* Generic Functions */ #include "H5ACprivate.h" /* Metadata cache */ @@ -160,6 +155,8 @@ H5_DLL herr_t H5CX_set_vlen_alloc_info(H5MM_allocate_t alloc_func, void *alloc_i /* "Setter" routines for LAPL properties cached in API context */ H5_DLL herr_t H5CX_set_nlinks(size_t nlinks); +H5_DLL herr_t H5CX_init(void); + /* "Setter" routines for cached DXPL properties that must be returned to application */ #ifdef H5_HAVE_PARALLEL H5_DLL void H5CX_set_mpio_actual_chunk_opt(H5D_mpio_actual_chunk_opt_mode_t chunk_opt); diff --git a/src/H5Cdbg.c b/src/H5Cdbg.c index 104f1af..de9019c 100644 --- a/src/H5Cdbg.c +++ b/src/H5Cdbg.c @@ -844,9 +844,9 @@ H5C_stats__reset(H5C_t H5_ATTR_UNUSED *cache_ptr) * If either the parent or the child is not in the metadata * cache, the function sets *fd_exists_ptr to FALSE. * - * If both are in the cache, the childs list of parents is + * If both are in the cache, the child's list of parents is * searched for the proposed parent. If the proposed parent - * is found in the childs parent list, the function sets + * is found in the child's parent list, the function sets * *fd_exists_ptr to TRUE. In all other non-error cases, * the function sets *fd_exists_ptr FALSE. * diff --git a/src/H5Cepoch.c b/src/H5Cepoch.c index 3434fed..8655881 100644 --- a/src/H5Cepoch.c +++ b/src/H5Cepoch.c @@ -78,22 +78,21 @@ static herr_t H5C__epoch_marker_fsf_size(const void H5_ATTR_UNUSED *thing, /* Local Variables */ /*******************/ -const H5AC_class_t H5AC_EPOCH_MARKER[1] = {{ - /* id = */ H5AC_EPOCH_MARKER_ID, - /* name = */ "epoch marker", - /* mem_type = */ H5FD_MEM_DEFAULT, /* value doesn't matter */ - /* flags = */ H5AC__CLASS_NO_FLAGS_SET, - /* get_initial_load_size = */ H5C__epoch_marker_get_initial_load_size, - /* get_final_load_size = */ H5C__epoch_marker_get_final_load_size, - /* verify_chksum = */ H5C__epoch_marker_verify_chksum, - /* deserialize = */ H5C__epoch_marker_deserialize, - /* image_len = */ H5C__epoch_marker_image_len, - /* pre_serialize = */ H5C__epoch_marker_pre_serialize, - /* serialize = */ H5C__epoch_marker_serialize, - /* notify = */ H5C__epoch_marker_notify, - /* free_icr = */ H5C__epoch_marker_free_icr, - /* fsf_size = */ H5C__epoch_marker_fsf_size, -}}; +const H5AC_class_t H5AC_EPOCH_MARKER[1] = { + {/* id = */ H5AC_EPOCH_MARKER_ID, + /* name = */ "epoch marker", + /* mem_type = */ H5FD_MEM_DEFAULT, /* value doesn't matter */ + /* flags = */ H5AC__CLASS_NO_FLAGS_SET, + /* get_initial_load_size = */ H5C__epoch_marker_get_initial_load_size, + /* get_final_load_size = */ H5C__epoch_marker_get_final_load_size, + /* verify_chksum = */ H5C__epoch_marker_verify_chksum, + /* deserialize = */ H5C__epoch_marker_deserialize, + /* image_len = */ H5C__epoch_marker_image_len, + /* pre_serialize = */ H5C__epoch_marker_pre_serialize, + /* serialize = */ H5C__epoch_marker_serialize, + /* notify = */ H5C__epoch_marker_notify, + /* free_icr = */ H5C__epoch_marker_free_icr, + /* fsf_size = */ H5C__epoch_marker_fsf_size}}; /*************************************************************************** * Class functions for H5C__EPOCH_MAKER_TYPE: diff --git a/src/H5Cimage.c b/src/H5Cimage.c index f17ff48..98c1291 100644 --- a/src/H5Cimage.c +++ b/src/H5Cimage.c @@ -591,7 +591,7 @@ H5C__deserialize_prefetched_entry(H5F_t *f, H5C_t *cache_ptr, H5C_cache_entry_t * * Note that at present, dirty can't be set to true with prefetched * entries. However this may change, so include this functionality - * against that posibility. + * against that possibility. * * Also, note that it is possible for a prefetched entry to be dirty -- * hence the value assigned to ds_entry_ptr->is_dirty below. @@ -997,6 +997,9 @@ H5C__read_cache_image(H5F_t *f, H5C_t *cache_ptr) #endif /* H5_HAVE_PARALLEL */ /* Read the buffer (if serial access, or rank 0 of parallel access) */ + /* NOTE: if this block read is being performed on rank 0 only, throwing + * an error here will cause other ranks to hang in the following MPI_Bcast. + */ if (H5F_block_read(f, H5FD_MEM_SUPER, cache_ptr->image_addr, cache_ptr->image_len, cache_ptr->image_buffer) < 0) HGOTO_ERROR(H5E_CACHE, H5E_READERROR, FAIL, "Can't read metadata cache image block") @@ -1129,7 +1132,7 @@ done: * image superblock extension message must be deleted from * the superblock extension and the image block freed * - * Contrawise, if the file is openened R/O, the metadata + * Contrawise, if the file is opened R/O, the metadata * cache image superblock extension message and image block * must be left as is. Further, any dirty entries in the * cache image block must be marked as clean to avoid @@ -1821,7 +1824,7 @@ done: * Purpose: Decode the metadata cache image entry from the supplied * buffer into the supplied instance of H5C_image_entry_t. * This includes allocating a buffer for the entry image, - * loading it, and seting ie_ptr->image_ptr to point to + * loading it, and setting ie_ptr->image_ptr to point to * the buffer. * * Advances the buffer pointer to the first byte @@ -2338,7 +2341,7 @@ done: * also be a flush dependency child. * * Finally, note that for purposes of the cache image, flush - * dependency height ends when a flush dependecy relation + * dependency height ends when a flush dependency relation * passes off the cache image. * * On exit, the flush dependency height of each entry in the @@ -2500,7 +2503,7 @@ H5C__prep_for_file_close__compute_fd_heights(const H5C_t *cache_ptr) entry_ptr = entry_ptr->il_next; } /* while (entry_ptr != NULL) */ - /* At present, no extenal parent or child flush dependency links + /* At present, no external parent or child flush dependency links * should exist -- hence the following assertions. This will change * if we support ageout of entries in the cache image. */ @@ -3381,7 +3384,7 @@ done: * creating if specified. * * In general, the size and location of the cache image block - * will be unknow at the time that the cache image superblock + * will be unknown at the time that the cache image superblock * message is created. A subsequent call to this routine will * be used to write the correct data. * diff --git a/src/H5Cmpio.c b/src/H5Cmpio.c index 35d8dd0..d127961 100644 --- a/src/H5Cmpio.c +++ b/src/H5Cmpio.c @@ -1097,7 +1097,7 @@ done: * * Note that this function is a modified version of * H5C_flush_cache() -- any changes there may need to be - * reflected here and vise versa. + * reflected here and vice versa. * * Return: Non-negative on success/Negative on failure. * diff --git a/src/H5Cpkg.h b/src/H5Cpkg.h index 99ed4f8..61c3afc 100644 --- a/src/H5Cpkg.h +++ b/src/H5Cpkg.h @@ -1011,7 +1011,7 @@ if ( ( (cache_ptr) == NULL ) || \ ( H5C__HASH_FCN((entry_ptr)->addr) >= H5C__HASH_TABLE_LEN ) || \ ( (cache_ptr)->index_size != \ ((cache_ptr)->clean_index_size + \ - (cache_ptr)->dirty_index_size) ) || \ + (cache_ptr)->dirty_index_size) ) || \ ( (cache_ptr)->index_size < ((cache_ptr)->clean_index_size) ) || \ ( (cache_ptr)->index_size < ((cache_ptr)->dirty_index_size) ) || \ ( (entry_ptr)->ring <= H5C_RING_UNDEFINED ) || \ @@ -1034,7 +1034,7 @@ if ( ( (cache_ptr) == NULL ) || \ ( (cache_ptr)->magic != H5C__H5C_T_MAGIC ) || \ ( (cache_ptr)->index_size != \ ((cache_ptr)->clean_index_size + \ - (cache_ptr)->dirty_index_size) ) || \ + (cache_ptr)->dirty_index_size) ) || \ ( (cache_ptr)->index_size < ((cache_ptr)->clean_index_size) ) || \ ( (cache_ptr)->index_size < ((cache_ptr)->dirty_index_size) ) || \ ( (cache_ptr)->index_ring_len[(entry_ptr)->ring] == 0 ) || \ @@ -1071,7 +1071,7 @@ if ( ( (cache_ptr) == NULL ) || \ ( (entry_ptr)->ht_prev != NULL ) ) || \ ( (cache_ptr)->index_size != \ ((cache_ptr)->clean_index_size + \ - (cache_ptr)->dirty_index_size) ) || \ + (cache_ptr)->dirty_index_size) ) || \ ( (cache_ptr)->index_size < ((cache_ptr)->clean_index_size) ) || \ ( (cache_ptr)->index_size < ((cache_ptr)->dirty_index_size) ) || \ ( (entry_ptr)->ring <= H5C_RING_UNDEFINED ) || \ @@ -1102,7 +1102,7 @@ if ( ( (cache_ptr) == NULL ) || \ ( (entry_ptr)->ht_prev != NULL ) || \ ( (cache_ptr)->index_size != \ ((cache_ptr)->clean_index_size + \ - (cache_ptr)->dirty_index_size) ) || \ + (cache_ptr)->dirty_index_size) ) || \ ( (cache_ptr)->index_size < ((cache_ptr)->clean_index_size) ) || \ ( (cache_ptr)->index_size < ((cache_ptr)->dirty_index_size) ) || \ ( (cache_ptr)->index_ring_len[(entry_ptr)->ring] > \ @@ -1161,7 +1161,7 @@ if ( ( (cache_ptr) == NULL ) || \ } #define H5C__PRE_HT_ENTRY_SIZE_CHANGE_SC(cache_ptr, old_size, new_size, \ - entry_ptr, was_clean) \ + entry_ptr, was_clean) \ if ( ( (cache_ptr) == NULL ) || \ ( (cache_ptr)->index_len <= 0 ) || \ ( (cache_ptr)->index_size <= 0 ) || \ @@ -1175,9 +1175,9 @@ if ( ( (cache_ptr) == NULL ) || \ ( (cache_ptr)->index_size < ((cache_ptr)->clean_index_size) ) || \ ( (cache_ptr)->index_size < ((cache_ptr)->dirty_index_size) ) || \ ( ( !( was_clean ) || \ - ( (cache_ptr)->clean_index_size < (old_size) ) ) && \ - ( ( (was_clean) ) || \ - ( (cache_ptr)->dirty_index_size < (old_size) ) ) ) || \ + ( (cache_ptr)->clean_index_size < (old_size) ) ) && \ + ( ( (was_clean) ) || \ + ( (cache_ptr)->dirty_index_size < (old_size) ) ) ) || \ ( (entry_ptr) == NULL ) || \ ( (entry_ptr)->ring <= H5C_RING_UNDEFINED ) || \ ( (entry_ptr)->ring >= H5C_RING_NTYPES ) || \ @@ -1196,20 +1196,20 @@ if ( ( (cache_ptr) == NULL ) || \ } #define H5C__POST_HT_ENTRY_SIZE_CHANGE_SC(cache_ptr, old_size, new_size, \ - entry_ptr) \ + entry_ptr) \ if ( ( (cache_ptr) == NULL ) || \ ( (cache_ptr)->index_len <= 0 ) || \ ( (cache_ptr)->index_size <= 0 ) || \ ( (new_size) > (cache_ptr)->index_size ) || \ ( (cache_ptr)->index_size != \ - ((cache_ptr)->clean_index_size + \ + ((cache_ptr)->clean_index_size + \ (cache_ptr)->dirty_index_size) ) || \ ( (cache_ptr)->index_size < ((cache_ptr)->clean_index_size) ) || \ ( (cache_ptr)->index_size < ((cache_ptr)->dirty_index_size) ) || \ ( ( !((entry_ptr)->is_dirty ) || \ - ( (cache_ptr)->dirty_index_size < (new_size) ) ) && \ - ( ( ((entry_ptr)->is_dirty) ) || \ - ( (cache_ptr)->clean_index_size < (new_size) ) ) ) || \ + ( (cache_ptr)->dirty_index_size < (new_size) ) ) && \ + ( ( ((entry_ptr)->is_dirty) ) || \ + ( (cache_ptr)->clean_index_size < (new_size) ) ) ) || \ ( ( (cache_ptr)->index_len == 1 ) && \ ( (cache_ptr)->index_size != (new_size) ) ) || \ ( (cache_ptr)->index_ring_len[(entry_ptr)->ring] > \ @@ -1465,10 +1465,10 @@ if ( ( (cache_ptr)->index_size != \ H5C__PRE_HT_UPDATE_FOR_ENTRY_CLEAN_SC(cache_ptr, entry_ptr); \ (cache_ptr)->dirty_index_size -= (entry_ptr)->size; \ ((cache_ptr)->dirty_index_ring_size[entry_ptr->ring]) \ - -= (entry_ptr)->size; \ + -= (entry_ptr)->size; \ (cache_ptr)->clean_index_size += (entry_ptr)->size; \ ((cache_ptr)->clean_index_ring_size[entry_ptr->ring]) \ - += (entry_ptr)->size; \ + += (entry_ptr)->size; \ H5C__POST_HT_UPDATE_FOR_ENTRY_CLEAN_SC(cache_ptr, entry_ptr); \ } @@ -1477,18 +1477,18 @@ if ( ( (cache_ptr)->index_size != \ H5C__PRE_HT_UPDATE_FOR_ENTRY_DIRTY_SC(cache_ptr, entry_ptr); \ (cache_ptr)->clean_index_size -= (entry_ptr)->size; \ ((cache_ptr)->clean_index_ring_size[entry_ptr->ring]) \ - -= (entry_ptr)->size; \ + -= (entry_ptr)->size; \ (cache_ptr)->dirty_index_size += (entry_ptr)->size; \ ((cache_ptr)->dirty_index_ring_size[entry_ptr->ring]) \ - += (entry_ptr)->size; \ + += (entry_ptr)->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) \ + entry_ptr, was_clean) \ { \ H5C__PRE_HT_ENTRY_SIZE_CHANGE_SC(cache_ptr, old_size, new_size, \ - entry_ptr, was_clean) \ + entry_ptr, was_clean) \ (cache_ptr)->index_size -= (old_size); \ (cache_ptr)->index_size += (new_size); \ ((cache_ptr)->index_ring_size[entry_ptr->ring]) -= (old_size); \ @@ -1497,14 +1497,14 @@ if ( ( (cache_ptr)->index_size != \ (cache_ptr)->clean_index_size -= (old_size); \ ((cache_ptr)->clean_index_ring_size[entry_ptr->ring])-= (old_size); \ } else { \ - (cache_ptr)->dirty_index_size -= (old_size); \ + (cache_ptr)->dirty_index_size -= (old_size); \ ((cache_ptr)->dirty_index_ring_size[entry_ptr->ring])-= (old_size); \ } \ if((entry_ptr)->is_dirty) { \ (cache_ptr)->dirty_index_size += (new_size); \ ((cache_ptr)->dirty_index_ring_size[entry_ptr->ring])+= (new_size); \ } else { \ - (cache_ptr)->clean_index_size += (new_size); \ + (cache_ptr)->clean_index_size += (new_size); \ ((cache_ptr)->clean_index_ring_size[entry_ptr->ring])+= (new_size); \ } \ H5C__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->il_len, \ @@ -1597,7 +1597,7 @@ if ( ( (cache_ptr)->index_size != \ * * H5C_DO_SLIST_SANITY_CHECKS * - * can be selected independantly. This is easy to miss as the + * can be selected independently. This is easy to miss as the * two #defines are easy to confuse. */ @@ -1791,7 +1791,7 @@ if ( ( (cache_ptr)->index_size != \ } else { /* slist disabled */ \ \ HDassert( (cache_ptr)->slist_len == 0 ); \ - HDassert( (cache_ptr)->slist_size == 0 ); \ + HDassert( (cache_ptr)->slist_size == 0 ); \ } \ } /* H5C__REMOVE_ENTRY_FROM_SLIST */ @@ -2033,16 +2033,16 @@ if ( ( (cache_ptr)->index_size != \ /* modified LRU specific code */ \ \ /* remove the entry from the LRU list, and re-insert it at the head.\ - */ \ + */ \ \ H5C__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_len, \ (cache_ptr)->LRU_list_size, (fail_val)) \ \ H5C__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_len, \ (cache_ptr)->LRU_list_size, (fail_val)) \ \ /* Use the dirty flag to infer whether the entry is on the clean or \ @@ -2096,16 +2096,16 @@ if ( ( (cache_ptr)->index_size != \ /* modified LRU specific code */ \ \ /* remove the entry from the LRU list, and re-insert it at the head \ - */ \ + */ \ \ H5C__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_len, \ (cache_ptr)->LRU_list_size, (fail_val)) \ \ H5C__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_len, \ (cache_ptr)->LRU_list_size, (fail_val)) \ \ /* End modified LRU specific code. */ \ @@ -2288,28 +2288,28 @@ if ( ( (cache_ptr)->index_size != \ /* modified LRU specific code */ \ \ /* remove the entry from the LRU list, and re-insert it at the \ - * head. \ - */ \ + * head. \ + */ \ \ H5C__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_len, \ (cache_ptr)->LRU_list_size, (fail_val)) \ \ H5C__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_len, \ (cache_ptr)->LRU_list_size, (fail_val)) \ \ /* since the entry is being flushed or cleared, one would think \ - * that it must be dirty -- but that need not be the case. Use the \ - * dirty flag to infer whether the entry is on the clean or dirty \ - * LRU list, and remove it. Then insert it at the head of the \ - * clean LRU list. \ + * that it must be dirty -- but that need not be the case. Use the \ + * dirty flag to infer whether the entry is on the clean or dirty \ + * LRU list, and remove it. Then insert it at the head of the \ + * clean LRU list. \ * \ * The function presumes that a dirty entry will be either cleared \ - * or flushed shortly, so it is OK if we put a dirty entry on the \ - * clean LRU list. \ + * or flushed shortly, so it is OK if we put a dirty entry on the \ + * clean LRU list. \ */ \ \ if ( (entry_ptr)->is_dirty ) { \ @@ -2350,17 +2350,17 @@ if ( ( (cache_ptr)->index_size != \ /* modified LRU specific code */ \ \ /* remove the entry from the LRU list, and re-insert it at the \ - * head. \ - */ \ + * head. \ + */ \ \ H5C__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_len, \ (cache_ptr)->LRU_list_size, (fail_val)) \ \ H5C__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_len, \ (cache_ptr)->LRU_list_size, (fail_val)) \ \ /* End modified LRU specific code. */ \ @@ -2424,7 +2424,7 @@ if ( ( (cache_ptr)->index_size != \ \ H5C__DLL_APPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_len, \ (cache_ptr)->LRU_list_size, (fail_val)) \ \ /* insert the entry at the tail of the clean or dirty LRU list as \ @@ -2465,7 +2465,7 @@ if ( ( (cache_ptr)->index_size != \ (cache_ptr)->pel_tail_ptr, \ (cache_ptr)->pel_len, \ (cache_ptr)->pel_size, (fail_val)) \ - \ + \ } else { \ \ /* modified LRU specific code */ \ @@ -2474,7 +2474,7 @@ if ( ( (cache_ptr)->index_size != \ \ H5C__DLL_APPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_len, \ (cache_ptr)->LRU_list_size, (fail_val)) \ \ /* End modified LRU specific code. */ \ @@ -2558,7 +2558,7 @@ if ( ( (cache_ptr)->index_size != \ \ H5C__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_len, \ (cache_ptr)->LRU_list_size, (fail_val)) \ \ /* insert the entry at the head of the clean or dirty LRU list as \ @@ -2599,7 +2599,7 @@ if ( ( (cache_ptr)->index_size != \ (cache_ptr)->pel_tail_ptr, \ (cache_ptr)->pel_len, \ (cache_ptr)->pel_size, (fail_val)) \ - \ + \ } else { \ \ /* modified LRU specific code */ \ @@ -2608,7 +2608,7 @@ if ( ( (cache_ptr)->index_size != \ \ H5C__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_len, \ (cache_ptr)->LRU_list_size, (fail_val)) \ \ /* End modified LRU specific code. */ \ @@ -2677,12 +2677,12 @@ if ( ( (cache_ptr)->index_size != \ HDassert( !((entry_ptr)->is_read_only) ); \ HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ HDassert( (entry_ptr)->size > 0 ); \ - \ + \ if ( (entry_ptr)->is_pinned ) { \ \ H5C__DLL_REMOVE((entry_ptr), (cache_ptr)->pel_head_ptr, \ - (cache_ptr)->pel_tail_ptr, \ - (cache_ptr)->pel_len, \ + (cache_ptr)->pel_tail_ptr, \ + (cache_ptr)->pel_len, \ (cache_ptr)->pel_size, (fail_val)) \ \ } else { \ @@ -2693,7 +2693,7 @@ if ( ( (cache_ptr)->index_size != \ \ H5C__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_len, \ (cache_ptr)->LRU_list_size, (fail_val)) \ \ /* Similarly, remove the entry from the clean or dirty LRU list \ @@ -2739,12 +2739,12 @@ if ( ( (cache_ptr)->index_size != \ HDassert( !((entry_ptr)->is_read_only) ); \ HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ HDassert( (entry_ptr)->size > 0 ); \ - \ + \ if ( (entry_ptr)->is_pinned ) { \ \ H5C__DLL_REMOVE((entry_ptr), (cache_ptr)->pel_head_ptr, \ - (cache_ptr)->pel_tail_ptr, \ - (cache_ptr)->pel_len, \ + (cache_ptr)->pel_tail_ptr, \ + (cache_ptr)->pel_len, \ (cache_ptr)->pel_size, (fail_val)) \ \ } else { \ @@ -2755,7 +2755,7 @@ if ( ( (cache_ptr)->index_size != \ \ H5C__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_len, \ (cache_ptr)->LRU_list_size, (fail_val)) \ \ /* End modified LRU specific code. */ \ @@ -2804,21 +2804,21 @@ if ( ( (cache_ptr)->index_size != \ HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ HDassert( (entry_ptr)->size > 0 ); \ \ - if ( ! ( (entry_ptr)->is_pinned ) && ! ( (entry_ptr->is_protected ) ) ) { \ - \ + if ( ! ( (entry_ptr)->is_pinned ) && ! ( (entry_ptr->is_protected ) ) ) {\ + \ /* modified LRU specific code */ \ \ /* remove the entry from the LRU list, and re-insert it at the head. \ - */ \ + */ \ \ H5C__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_len, \ (cache_ptr)->LRU_list_size, (fail_val)) \ \ H5C__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_len, \ (cache_ptr)->LRU_list_size, (fail_val)) \ \ /* remove the entry from either the clean or dirty LUR list as \ @@ -2827,7 +2827,7 @@ if ( ( (cache_ptr)->index_size != \ if ( was_dirty ) { \ \ H5C__AUX_DLL_REMOVE((entry_ptr), \ - (cache_ptr)->dLRU_head_ptr, \ + (cache_ptr)->dLRU_head_ptr, \ (cache_ptr)->dLRU_tail_ptr, \ (cache_ptr)->dLRU_list_len, \ (cache_ptr)->dLRU_list_size, \ @@ -2836,34 +2836,34 @@ if ( ( (cache_ptr)->index_size != \ } else { \ \ H5C__AUX_DLL_REMOVE((entry_ptr), \ - (cache_ptr)->cLRU_head_ptr, \ + (cache_ptr)->cLRU_head_ptr, \ (cache_ptr)->cLRU_tail_ptr, \ (cache_ptr)->cLRU_list_len, \ (cache_ptr)->cLRU_list_size, \ - (fail_val)) \ + (fail_val)) \ } \ \ /* insert the entry at the head of either the clean or dirty \ - * LRU list as appropriate. \ + * LRU list as appropriate. \ */ \ \ if ( (entry_ptr)->is_dirty ) { \ \ H5C__AUX_DLL_PREPEND((entry_ptr), \ - (cache_ptr)->dLRU_head_ptr, \ + (cache_ptr)->dLRU_head_ptr, \ (cache_ptr)->dLRU_tail_ptr, \ (cache_ptr)->dLRU_list_len, \ (cache_ptr)->dLRU_list_size, \ - (fail_val)) \ + (fail_val)) \ \ } else { \ \ H5C__AUX_DLL_PREPEND((entry_ptr), \ - (cache_ptr)->cLRU_head_ptr, \ + (cache_ptr)->cLRU_head_ptr, \ (cache_ptr)->cLRU_tail_ptr, \ (cache_ptr)->cLRU_list_len, \ (cache_ptr)->cLRU_list_size, \ - (fail_val)) \ + (fail_val)) \ } \ \ /* End modified LRU specific code. */ \ @@ -2872,7 +2872,7 @@ if ( ( (cache_ptr)->index_size != \ #else /* H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ -#define H5C__UPDATE_RP_FOR_MOVE(cache_ptr, entry_ptr, was_dirty, fail_val) \ +#define H5C__UPDATE_RP_FOR_MOVE(cache_ptr, entry_ptr, was_dirty, fail_val) \ { \ HDassert( (cache_ptr) ); \ HDassert( (cache_ptr)->magic == H5C__H5C_T_MAGIC ); \ @@ -2881,21 +2881,21 @@ if ( ( (cache_ptr)->index_size != \ HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ HDassert( (entry_ptr)->size > 0 ); \ \ - if ( ! ( (entry_ptr)->is_pinned ) && ! ( (entry_ptr->is_protected ) ) ) { \ - \ + if ( ! ( (entry_ptr)->is_pinned ) && ! ( (entry_ptr->is_protected ) ) ) {\ + \ /* modified LRU specific code */ \ \ /* remove the entry from the LRU list, and re-insert it at the head. \ - */ \ + */ \ \ H5C__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_len, \ (cache_ptr)->LRU_list_size, (fail_val)) \ \ H5C__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_len, \ (cache_ptr)->LRU_list_size, (fail_val)) \ \ /* End modified LRU specific code. */ \ @@ -2952,49 +2952,49 @@ if ( ( (cache_ptr)->index_size != \ \ if ( (entry_ptr)->coll_access ) { \ \ - H5C__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->coll_list_len, \ - (cache_ptr)->coll_list_size, \ - (entry_ptr)->size, \ - (new_size)); \ - \ + H5C__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->coll_list_len, \ + (cache_ptr)->coll_list_size, \ + (entry_ptr)->size, \ + (new_size)); \ + \ } \ \ if ( (entry_ptr)->is_pinned ) { \ \ - H5C__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->pel_len, \ - (cache_ptr)->pel_size, \ - (entry_ptr)->size, \ - (new_size)); \ - \ + H5C__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->pel_len, \ + (cache_ptr)->pel_size, \ + (entry_ptr)->size, \ + (new_size)); \ + \ } else { \ \ /* modified LRU specific code */ \ \ - /* Update the size of the LRU list */ \ + /* Update the size of the LRU list */ \ \ - H5C__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->LRU_list_len, \ - (cache_ptr)->LRU_list_size, \ - (entry_ptr)->size, \ - (new_size)); \ + H5C__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, \ + (entry_ptr)->size, \ + (new_size)); \ \ /* Similarly, update the size of the clean or dirty LRU list as \ - * appropriate. At present, the entry must be clean, but that \ - * could change. \ + * appropriate. At present, the entry must be clean, but that \ + * could change. \ */ \ \ if ( (entry_ptr)->is_dirty ) { \ \ - H5C__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->dLRU_list_len, \ - (cache_ptr)->dLRU_list_size, \ - (entry_ptr)->size, \ - (new_size)); \ + H5C__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->dLRU_list_len, \ + (cache_ptr)->dLRU_list_size, \ + (entry_ptr)->size, \ + (new_size)); \ \ } else { \ \ - H5C__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->cLRU_list_len, \ - (cache_ptr)->cLRU_list_size, \ - (entry_ptr)->size, \ - (new_size)); \ + H5C__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->cLRU_list_len, \ + (cache_ptr)->cLRU_list_size, \ + (entry_ptr)->size, \ + (new_size)); \ } \ \ /* End modified LRU specific code. */ \ @@ -3017,21 +3017,21 @@ if ( ( (cache_ptr)->index_size != \ \ if ( (entry_ptr)->is_pinned ) { \ \ - H5C__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->pel_len, \ - (cache_ptr)->pel_size, \ - (entry_ptr)->size, \ - (new_size)); \ + H5C__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->pel_len, \ + (cache_ptr)->pel_size, \ + (entry_ptr)->size, \ + (new_size)); \ \ } else { \ \ /* modified LRU specific code */ \ \ - /* Update the size of the LRU list */ \ + /* Update the size of the LRU list */ \ \ - H5C__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->LRU_list_len, \ - (cache_ptr)->LRU_list_size, \ - (entry_ptr)->size, \ - (new_size)); \ + H5C__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, \ + (entry_ptr)->size, \ + (new_size)); \ \ /* End modified LRU specific code. */ \ } \ @@ -3318,7 +3318,7 @@ if ( ( (hd_ptr) == NULL ) || \ ( (Size) < (entry_ptr)->size ) || \ ( ( (Size) == (entry_ptr)->size ) && ( ! ( (len) == 1 ) ) ) || \ ( ( (entry_ptr)->coll_prev == NULL ) && ( (hd_ptr) != (entry_ptr) ) ) || \ - ( ( (entry_ptr)->coll_next == NULL ) && ( (tail_ptr) != (entry_ptr) ) ) || \ + ( ( (entry_ptr)->coll_next == NULL ) && ( (tail_ptr) != (entry_ptr) ) ) ||\ ( ( (len) == 1 ) && \ ( ! ( ( (hd_ptr) == (entry_ptr) ) && ( (tail_ptr) == (entry_ptr) ) && \ ( (entry_ptr)->coll_next == NULL ) && \ @@ -3350,10 +3350,10 @@ if ( ( ( ( (head_ptr) == NULL ) || ( (tail_ptr) == NULL ) ) && \ ) \ ) { \ HDassert(0 && "COLL DLL sanity check failed"); \ - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, (fv), "COLL DLL sanity check failed") \ + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, (fv), "COLL DLL sanity check failed")\ } -#define H5C__COLL_DLL_PRE_INSERT_SC(entry_ptr, hd_ptr, tail_ptr, len, Size, fv) \ +#define H5C__COLL_DLL_PRE_INSERT_SC(entry_ptr, hd_ptr, tail_ptr, len, Size, fv)\ if ( ( (entry_ptr) == NULL ) || \ ( (entry_ptr)->coll_next != NULL ) || \ ( (entry_ptr)->coll_prev != NULL ) || \ @@ -5074,7 +5074,7 @@ H5_DLL herr_t H5C__generate_cache_image(H5F_t *f, H5C_t *cache_ptr); H5_DLL herr_t H5C__load_cache_image(H5F_t *f); H5_DLL herr_t H5C__mark_flush_dep_serialized(H5C_cache_entry_t * entry_ptr); H5_DLL herr_t H5C__mark_flush_dep_unserialized(H5C_cache_entry_t * entry_ptr); -H5_DLL herr_t H5C__make_space_in_cache(H5F_t * f, size_t space_needed, +H5_DLL herr_t H5C__make_space_in_cache(H5F_t * f, size_t space_needed, hbool_t write_permitted); H5_DLL herr_t H5C__flush_marked_entries(H5F_t * f); H5_DLL herr_t H5C__serialize_cache(H5F_t *f); diff --git a/src/H5Cprefetched.c b/src/H5Cprefetched.c index 07fca2b..f89c233 100644 --- a/src/H5Cprefetched.c +++ b/src/H5Cprefetched.c @@ -302,7 +302,7 @@ H5C__prefetched_entry_free_icr(void *_thing) HDassert(entry_ptr->fd_parent_count == 0); if (entry_ptr->image_ptr != NULL) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "prefetched entry image buffer still attatched?") + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "prefetched entry image buffer still attached?") entry_ptr = H5FL_FREE(H5C_cache_entry_t, entry_ptr); diff --git a/src/H5Cprivate.h b/src/H5Cprivate.h index 78d6f35..9514443 100644 --- a/src/H5Cprivate.h +++ b/src/H5Cprivate.h @@ -213,7 +213,7 @@ #define H5C_DO_TAGGING_SANITY_CHECKS 1 #define H5C_DO_EXTREME_SANITY_CHECKS 0 #else /* NDEBUG */ -/* With rare execptions, the following defines should be set +/* With rare exceptions, the following defines should be set * to 0 if NDEBUG is defined */ #define H5C_DO_SANITY_CHECKS 0 @@ -1428,7 +1428,7 @@ typedef int H5C_ring_t; * with no flush dependency children. * * Since the image_fd_height is used to order entries in the - * cache image so that fd parents preceed fd children, for + * cache image so that fd parents precede fd children, for * purposes of this field, and entry is at flush dependency * level 0 if it either has no children, or if all of its * children are not in the cache image. @@ -1543,7 +1543,7 @@ typedef int H5C_ring_t; * number of times each entry is serialized during cache * serialization. While no entry should be serialized more than * once in any serialization call, throw an assertion if any - * flush depencency parent is serialized more than once during + * flush dependency parent is serialized more than once during * a single cache serialization. * * This is a debugging field, and thus is maintained only if @@ -1734,7 +1734,7 @@ typedef struct H5C_cache_entry_t { * with no flush dependency children. * * Since the image_fd_height is used to order entries in the - * cache image so that fd parents preceed fd children, for + * cache image so that fd parents precede fd children, for * purposes of this field, an entry is at flush dependency * level 0 if it either has no children, or if all of its * children are not in the cache image. @@ -2177,7 +2177,7 @@ typedef struct H5C_auto_size_ctl_t { * equivalent of H5AC__CACHE_IMAGE__ENTRY_AGEOUT__NONE. * * flags: Unsigned integer containing flags controlling which aspects of the - * cache image functinality is actually executed. The primary impetus + * cache image functionality is actually executed. The primary impetus * behind this field is to allow development of tests for partial * implementations that will require little if any modification to run * with the full implementation. In normal operation, all flags should @@ -2292,6 +2292,16 @@ H5_DLL herr_t H5C_cache_image_status(H5F_t *f, hbool_t *load_ci_ptr, hbool_t * H5_DLL hbool_t H5C_cache_image_pending(const H5C_t *cache_ptr); H5_DLL herr_t H5C_get_mdc_image_info(const H5C_t *cache_ptr, haddr_t *image_addr, hsize_t *image_len); +#if H5C_DO_SLIST_SANITY_CHECKS +H5_DLL hbool_t H5C_entry_in_skip_list(H5C_t *cache_ptr, H5C_cache_entry_t *target_ptr); +#endif + +#if H5C_DO_EXTREME_SANITY_CHECKS +H5_DLL herr_t H5C_validate_lru_list(H5C_t *cache_ptr); +H5_DLL herr_t H5C_validate_pinned_entry_list(H5C_t *cache_ptr); +H5_DLL herr_t H5C_validate_protected_entry_list(H5C_t *cache_ptr); +#endif /* H5C_DO_EXTREME_SANITY_CHECKS */ + /* Logging functions */ H5_DLL herr_t H5C_start_logging(H5C_t *cache); H5_DLL herr_t H5C_stop_logging(H5C_t *cache); diff --git a/src/H5Cpublic.h b/src/H5Cpublic.h index 79ece10..c65dc7c 100644 --- a/src/H5Cpublic.h +++ b/src/H5Cpublic.h @@ -27,10 +27,6 @@ /* Public headers needed by this file */ #include "H5public.h" -#ifdef __cplusplus -extern "C" { -#endif - enum H5C_cache_incr_mode { H5C_incr__off, /**<Automatic cache size increase is disabled, and the remaining increment fields are ignored.*/ @@ -61,7 +57,4 @@ enum H5C_cache_decr_mode { /**<Automatic cache size decrease is enabled using the ageout with hit rate threshold algorithm.*/ }; -#ifdef __cplusplus -} -#endif #endif @@ -62,9 +62,6 @@ static herr_t H5D__set_extent_api_common(hid_t dset_id, const hsize_t size[], vo /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /*****************************/ /* Library Private Variables */ /*****************************/ @@ -1805,7 +1802,7 @@ H5Dset_extent(hid_t dset_id, const hsize_t size[]) FUNC_ENTER_API(FAIL) H5TRACE2("e", "i*h", dset_id, size); - /* Change a datset's dimenions synchronously */ + /* Change a datset's dimensions synchronously */ if ((ret_value = H5D__set_extent_api_common(dset_id, size, NULL, NULL)) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to synchronously change a dataset's dimensions") @@ -1838,7 +1835,7 @@ H5Dset_extent_async(const char *app_file, const char *app_func, unsigned app_lin if (H5ES_NONE != es_id) token_ptr = &token; /* Point at token for VOL connector to set up */ - /* Change a datset's dimenions asynchronously */ + /* Change a datset's dimensions asynchronously */ if (H5D__set_extent_api_common(dset_id, size, token_ptr, &vol_obj) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to asynchronously change a dataset's dimensions") diff --git a/src/H5Dchunk.c b/src/H5Dchunk.c index 6600417..4445911 100644 --- a/src/H5Dchunk.c +++ b/src/H5Dchunk.c @@ -59,6 +59,7 @@ #include "H5Iprivate.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ #include "H5MFprivate.h" /* File memory management */ +#include "H5PBprivate.h" /* Page Buffer */ #include "H5VMprivate.h" /* Vector and array functions */ /****************/ @@ -70,6 +71,7 @@ #define H5D_CHUNK_GET_NODE_INFO(map, node) \ (map->use_single ? map->single_chunk_info : (H5D_chunk_info_t *)H5SL_item(node)) #define H5D_CHUNK_GET_NEXT_NODE(map, node) (map->use_single ? (H5SL_node_t *)NULL : H5SL_next(node)) +#define H5D_CHUNK_GET_NODE_COUNT(map) (map->use_single ? (size_t)1 : H5SL_count(map->sel_chunks)) /* Sanity check on chunk index types: commonly used by a lot of routines in this file */ #define H5D_CHUNK_STORAGE_INDEX_CHK(storage) \ @@ -239,10 +241,14 @@ typedef struct H5D_chunk_file_iter_ud_t { #ifdef H5_HAVE_PARALLEL /* information to construct a collective I/O operation for filling chunks */ -typedef struct H5D_chunk_coll_info_t { - size_t num_io; /* Number of write operations */ - haddr_t *addr; /* array of the file addresses of the write operation */ -} H5D_chunk_coll_info_t; +typedef struct H5D_chunk_coll_fill_info_t { + size_t num_chunks; /* Number of chunks in the write operation */ + struct chunk_coll_fill_info { + haddr_t addr; /* File address of the chunk */ + size_t chunk_size; /* Size of the chunk in the file */ + hbool_t unfiltered_partial_chunk; + } * chunk_info; +} H5D_chunk_coll_fill_info_t; #endif /* H5_HAVE_PARALLEL */ typedef struct H5D_chunk_iter_ud_t { @@ -257,15 +263,14 @@ typedef struct H5D_chunk_iter_ud_t { /* Chunked layout operation callbacks */ static herr_t H5D__chunk_construct(H5F_t *f, H5D_t *dset); static herr_t H5D__chunk_init(H5F_t *f, const H5D_t *dset, hid_t dapl_id); -static herr_t H5D__chunk_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info, - hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space, - H5D_chunk_map_t *fm); +static herr_t H5D__chunk_io_init(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, + H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t *fm); static herr_t H5D__chunk_io_init_selections(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info, H5D_chunk_map_t *fm); static herr_t H5D__chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, - const H5S_t *file_space, const H5S_t *mem_space, H5D_chunk_map_t *fm); + H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t *fm); static herr_t H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, - const H5S_t *file_space, const H5S_t *mem_space, H5D_chunk_map_t *fm); + H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t *fm); static herr_t H5D__chunk_flush(H5D_t *dset); static herr_t H5D__chunk_io_term(const H5D_chunk_map_t *fm); static herr_t H5D__chunk_dest(H5D_t *dset); @@ -288,9 +293,6 @@ static int H5D__chunk_format_convert_cb(const H5D_chunk_rec_t *chunk_rec, void * /* Helper routines */ static herr_t H5D__chunk_set_info_real(H5O_layout_chunk_t *layout, unsigned ndims, const hsize_t *curr_dims, const hsize_t *max_dims); -static void * H5D__chunk_mem_alloc(size_t size, const H5O_pline_t *pline); -static void * H5D__chunk_mem_xfree(void *chk, const void *pline); -static void * H5D__chunk_mem_realloc(void *chk, size_t size, const H5O_pline_t *pline); static herr_t H5D__chunk_cinfo_cache_reset(H5D_chunk_cached_t *last); static herr_t H5D__chunk_cinfo_cache_update(H5D_chunk_cached_t *last, const H5D_chunk_ud_t *udata); static hbool_t H5D__chunk_cinfo_cache_found(const H5D_chunk_cached_t *last, H5D_chunk_ud_t *udata); @@ -304,11 +306,10 @@ static herr_t H5D__chunk_file_cb(void *elem, const H5T_t *type, unsigned ndims void *fm); static herr_t H5D__chunk_mem_cb(void *elem, const H5T_t *type, unsigned ndims, const hsize_t *coords, void *fm); +static htri_t H5D__chunk_may_use_select_io(const H5D_io_info_t *io_info); static unsigned H5D__chunk_hash_val(const H5D_shared_t *shared, const hsize_t *scaled); static herr_t H5D__chunk_flush_entry(const H5D_t *dset, H5D_rdcc_ent_t *ent, hbool_t reset); static herr_t H5D__chunk_cache_evict(const H5D_t *dset, H5D_rdcc_ent_t *ent, hbool_t flush); -static hbool_t H5D__chunk_is_partial_edge_chunk(unsigned dset_ndims, const uint32_t *chunk_dims, - const hsize_t *chunk_scaled, const hsize_t *dset_dims); static void * H5D__chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata, hbool_t relax, hbool_t prev_unfilt_chunk); static herr_t H5D__chunk_unlock(const H5D_io_info_t *io_info, const H5D_chunk_ud_t *udata, hbool_t dirty, @@ -316,9 +317,9 @@ static herr_t H5D__chunk_unlock(const H5D_io_info_t *io_info, const H5D_chunk_ static herr_t H5D__chunk_cache_prune(const H5D_t *dset, size_t size); static herr_t H5D__chunk_prune_fill(H5D_chunk_it_ud1_t *udata, hbool_t new_unfilt_chunk); #ifdef H5_HAVE_PARALLEL -static herr_t H5D__chunk_collective_fill(const H5D_t *dset, H5D_chunk_coll_info_t *chunk_info, - size_t chunk_size, const void *fill_buf); -static int H5D__chunk_cmp_addr(const void *addr1, const void *addr2); +static herr_t H5D__chunk_collective_fill(const H5D_t *dset, H5D_chunk_coll_fill_info_t *chunk_fill_info, + const void *fill_buf, const void *partial_chunk_fill_buf); +static int H5D__chunk_cmp_coll_fill_info(const void *_entry1, const void *_entry2); #endif /* H5_HAVE_PARALLEL */ /* Debugging helper routine callback */ @@ -329,13 +330,24 @@ static int H5D__chunk_dump_index_cb(const H5D_chunk_rec_t *chunk_rec, void *_uda /*********************/ /* Chunked storage layout I/O ops */ -const H5D_layout_ops_t H5D_LOPS_CHUNK[1] = { - {H5D__chunk_construct, H5D__chunk_init, H5D__chunk_is_space_alloc, H5D__chunk_is_data_cached, - H5D__chunk_io_init, H5D__chunk_read, H5D__chunk_write, +const H5D_layout_ops_t H5D_LOPS_CHUNK[1] = {{ + H5D__chunk_construct, /* construct */ + H5D__chunk_init, /* init */ + H5D__chunk_is_space_alloc, /* is_space_alloc */ + H5D__chunk_is_data_cached, /* is_data_cached */ + H5D__chunk_io_init, /* io_init */ + H5D__chunk_read, /* ser_read */ + H5D__chunk_write, /* ser_write */ #ifdef H5_HAVE_PARALLEL - H5D__chunk_collective_read, H5D__chunk_collective_write, -#endif /* H5_HAVE_PARALLEL */ - NULL, NULL, H5D__chunk_flush, H5D__chunk_io_term, H5D__chunk_dest}}; + H5D__chunk_collective_read, /* par_read */ + H5D__chunk_collective_write, /* par_write */ +#endif + NULL, /* readvv */ + NULL, /* writevv */ + H5D__chunk_flush, /* flush */ + H5D__chunk_io_term, /* io_term */ + H5D__chunk_dest /* dest */ +}}; /*******************/ /* Local Variables */ @@ -964,7 +976,7 @@ H5D__chunk_init(H5F_t *f, const H5D_t *const dset, hid_t dapl_id) if (!(scaled_power2up = H5VM_power2up(rdcc->scaled_dims[u]))) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to get the next power of 2") - /* Inital 'power2up' values for scaled dimensions */ + /* Initial 'power2up' values for scaled dimensions */ rdcc->scaled_power2up[u] = scaled_power2up; /* Number of bits required to encode scaled dimension size */ @@ -1056,16 +1068,17 @@ H5D__chunk_is_data_cached(const H5D_shared_t *shared_dset) *------------------------------------------------------------------------- */ static herr_t -H5D__chunk_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, - const H5S_t *file_space, const H5S_t *mem_space, H5D_chunk_map_t *fm) +H5D__chunk_io_init(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, + H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t *fm) { const H5D_t *dataset = io_info->dset; /* Local pointer to dataset info */ hssize_t old_offset[H5O_LAYOUT_NDIMS]; /* Old selection offset */ htri_t file_space_normalized = FALSE; /* File dataspace was normalized */ unsigned f_ndims; /* The number of dimensions of the file's dataspace */ - int sm_ndims; /* The number of dimensions of the memory buffer's dataspace (signed) */ - unsigned u; /* Local index variable */ - herr_t ret_value = SUCCEED; /* Return value */ + int sm_ndims; /* The number of dimensions of the memory buffer's dataspace (signed) */ + htri_t use_selection_io = FALSE; /* Whether to use selection I/O */ + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC @@ -1088,7 +1101,7 @@ H5D__chunk_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_inf * speed up hyperslab calculations by removing the extra checks and/or * additions involving the offset and the hyperslab selection -QAK) */ - if ((file_space_normalized = H5S_hyper_normalize_offset((H5S_t *)file_space, old_offset)) < 0) + if ((file_space_normalized = H5S_hyper_normalize_offset(file_space, old_offset)) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to normalize selection") /* Decide the number of chunks in each dimension */ @@ -1119,6 +1132,11 @@ H5D__chunk_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_inf if (H5D__chunk_io_init_selections(io_info, type_info, fm) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file and memory chunk selections") + /* Check if we're performing selection I/O and save the result */ + if ((use_selection_io = H5D__chunk_may_use_select_io(io_info)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't check if selection I/O is possible") + io_info->use_select_io = (hbool_t)use_selection_io; + done: /* Reset the global dataspace info */ fm->file_space = NULL; @@ -1352,7 +1370,7 @@ done: * *------------------------------------------------------------------------- */ -static void * +void * H5D__chunk_mem_alloc(size_t size, const H5O_pline_t *pline) { void *ret_value = NULL; /* Return value */ @@ -1383,7 +1401,7 @@ H5D__chunk_mem_alloc(size_t size, const H5O_pline_t *pline) * *------------------------------------------------------------------------- */ -static void * +void * H5D__chunk_mem_xfree(void *chk, const void *_pline) { const H5O_pline_t *pline = (const H5O_pline_t *)_pline; @@ -1401,6 +1419,19 @@ H5D__chunk_mem_xfree(void *chk, const void *_pline) } /* H5D__chunk_mem_xfree() */ /*------------------------------------------------------------------------- + * Function: H5D__chunk_mem_free + * + * Purpose: Wrapper with H5MM_free_t-compatible signature that just + * calls H5D__chunk_mem_xfree and discards the return value. + *------------------------------------------------------------------------- + */ +void +H5D__chunk_mem_free(void *chk, const void *_pline) +{ + (void)H5D__chunk_mem_xfree(chk, _pline); +} + +/*------------------------------------------------------------------------- * Function: H5D__chunk_mem_realloc * * Purpose: Reallocate space for a chunk in memory. This routine allocates @@ -1414,7 +1445,7 @@ H5D__chunk_mem_xfree(void *chk, const void *_pline) * *------------------------------------------------------------------------- */ -static void * +void * H5D__chunk_mem_realloc(void *chk, size_t size, const H5O_pline_t *pline) { void *ret_value = NULL; /* Return value */ @@ -2236,7 +2267,6 @@ H5D__chunk_file_cb(void H5_ATTR_UNUSED *elem, const H5T_t H5_ATTR_UNUSED *type, /* Set the chunk's scaled coordinates */ H5MM_memcpy(chunk_info->scaled, scaled, sizeof(hsize_t) * fm->f_ndims); chunk_info->scaled[fm->f_ndims] = 0; - H5MM_memcpy(chunk_info->scaled, scaled, sizeof(hsize_t) * fm->f_ndims); /* Insert the new chunk into the skip list */ if (H5SL_insert(fm->sel_chunks, chunk_info, &chunk_info->index) < 0) { @@ -2438,6 +2468,78 @@ done: } /* end H5D__chunk_cacheable() */ /*------------------------------------------------------------------------- + * Function: H5D__chunk_may_use_select_io + * + * Purpose: A small internal function to if it may be possible to use + * selection I/O. + * + * Return: TRUE or FALSE + * + * Programmer: Neil Fortner + * 4 May 2021 + * + *------------------------------------------------------------------------- + */ +static htri_t +H5D__chunk_may_use_select_io(const H5D_io_info_t *io_info) +{ + const H5D_t *dataset = NULL; /* Local pointer to dataset info */ + htri_t ret_value = FAIL; /* Return value */ + + FUNC_ENTER_STATIC + + /* Sanity check */ + HDassert(io_info); + + dataset = io_info->dset; + HDassert(dataset); + + /* Don't use selection I/O if it's globally disabled, there is a type + * conversion, or if there are filters on the dataset (for now) */ + if (!H5_use_selection_io_g || io_info->io_ops.single_read != H5D__select_read || + dataset->shared->dcpl_cache.pline.nused > 0) + ret_value = FALSE; + else { + hbool_t page_buf_enabled; + + HDassert(io_info->io_ops.single_write == H5D__select_write); + + /* Check if the page buffer is enabled */ + if (H5PB_enabled(io_info->f_sh, H5FD_MEM_DRAW, &page_buf_enabled) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't check if page buffer is enabled") + if (page_buf_enabled) + ret_value = FALSE; + else { + /* Check if chunks in this dataset may be cached, if so don't use + * selection I/O (for now). Note that chunks temporarily cached for + * the purpose of writing the fill value don't count, since they are + * immediately evicted. */ +#ifdef H5_HAVE_PARALLEL + /* If MPI based VFD is used and the file is opened for write access, + * must bypass the chunk-cache scheme because other MPI processes + * could be writing to other elements in the same chunk. + */ + if (io_info->using_mpi_vfd && (H5F_ACC_RDWR & H5F_INTENT(dataset->oloc.file))) + ret_value = TRUE; + else { +#endif /* H5_HAVE_PARALLEL */ + /* Check if the chunk is too large to keep in the cache */ + H5_CHECK_OVERFLOW(dataset->shared->layout.u.chunk.size, uint32_t, size_t); + if ((size_t)dataset->shared->layout.u.chunk.size > dataset->shared->cache.chunk.nbytes_max) + ret_value = TRUE; + else + ret_value = FALSE; +#ifdef H5_HAVE_PARALLEL + } /* end else */ +#endif /* H5_HAVE_PARALLEL */ + } /* end else */ + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D__chunk_may_use_select_io() */ + +/*------------------------------------------------------------------------- * Function: H5D__chunk_read * * Purpose: Read from a chunked dataset. @@ -2451,19 +2553,19 @@ done: */ static herr_t H5D__chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t H5_ATTR_UNUSED nelmts, - const H5S_t H5_ATTR_UNUSED *file_space, const H5S_t H5_ATTR_UNUSED *mem_space, - H5D_chunk_map_t *fm) + H5S_t H5_ATTR_UNUSED *file_space, H5S_t H5_ATTR_UNUSED *mem_space, H5D_chunk_map_t *fm) { - H5SL_node_t * chunk_node; /* Current node in chunk skip list */ - H5D_io_info_t nonexistent_io_info; /* "nonexistent" I/O info object */ - H5D_io_info_t ctg_io_info; /* Contiguous I/O info object */ - H5D_storage_t ctg_store; /* Chunk storage information as contiguous dataset */ - H5D_io_info_t cpt_io_info; /* Compact I/O info object */ - H5D_storage_t cpt_store; /* Chunk storage information as compact dataset */ - hbool_t cpt_dirty; /* Temporary placeholder for compact storage "dirty" flag */ - uint32_t src_accessed_bytes = 0; /* Total accessed size in a chunk */ - hbool_t skip_missing_chunks = FALSE; /* Whether to skip missing chunks */ - herr_t ret_value = SUCCEED; /*return value */ + H5SL_node_t * chunk_node; /* Current node in chunk skip list */ + H5D_io_info_t nonexistent_io_info; /* "nonexistent" I/O info object */ + uint32_t src_accessed_bytes = 0; /* Total accessed size in a chunk */ + hbool_t skip_missing_chunks = FALSE; /* Whether to skip missing chunks */ + H5S_t ** chunk_mem_spaces = NULL; /* Array of chunk memory spaces */ + H5S_t * chunk_mem_spaces_static[8]; /* Static buffer for chunk_mem_spaces */ + H5S_t ** chunk_file_spaces = NULL; /* Array of chunk file spaces */ + H5S_t * chunk_file_spaces_static[8]; /* Static buffer for chunk_file_spaces */ + haddr_t * chunk_addrs = NULL; /* Array of chunk addresses */ + haddr_t chunk_addrs_static[8]; /* Static buffer for chunk_addrs */ + herr_t ret_value = SUCCEED; /*return value */ FUNC_ENTER_STATIC @@ -2477,23 +2579,6 @@ H5D__chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_ H5MM_memcpy(&nonexistent_io_info, io_info, sizeof(nonexistent_io_info)); nonexistent_io_info.layout_ops = *H5D_LOPS_NONEXISTENT; - /* Set up contiguous I/O info object */ - H5MM_memcpy(&ctg_io_info, io_info, sizeof(ctg_io_info)); - ctg_io_info.store = &ctg_store; - ctg_io_info.layout_ops = *H5D_LOPS_CONTIG; - - /* Initialize temporary contiguous storage info */ - H5_CHECKED_ASSIGN(ctg_store.contig.dset_size, hsize_t, io_info->dset->shared->layout.u.chunk.size, - uint32_t); - - /* Set up compact I/O info object */ - H5MM_memcpy(&cpt_io_info, io_info, sizeof(cpt_io_info)); - cpt_io_info.store = &cpt_store; - cpt_io_info.layout_ops = *H5D_LOPS_COMPACT; - - /* Initialize temporary compact storage info */ - cpt_store.compact.dirty = &cpt_dirty; - { const H5O_fill_t *fill = &(io_info->dset->shared->dcpl_cache.fill); /* Fill value info */ H5D_fill_value_t fill_status; /* Fill value status */ @@ -2511,80 +2596,215 @@ H5D__chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_ skip_missing_chunks = TRUE; } - /* Iterate through nodes in chunk skip list */ - chunk_node = H5D_CHUNK_GET_FIRST_NODE(fm); - while (chunk_node) { - H5D_chunk_info_t *chunk_info; /* Chunk information */ - H5D_chunk_ud_t udata; /* Chunk index pass-through */ + /* Different blocks depending on whether we're using selection I/O */ + if (io_info->use_select_io) { + size_t num_chunks; + size_t element_sizes[2] = {type_info->dst_type_size, 0}; + void * bufs[2] = {io_info->u.rbuf, NULL}; + + /* Cache number of chunks */ + num_chunks = H5D_CHUNK_GET_NODE_COUNT(fm); + + /* Allocate arrays of dataspaces and offsets for use with selection I/O, + * or point to static buffers */ + HDassert(sizeof(chunk_mem_spaces_static) / sizeof(chunk_mem_spaces_static[0]) == + sizeof(chunk_file_spaces_static) / sizeof(chunk_file_spaces_static[0])); + HDassert(sizeof(chunk_mem_spaces_static) / sizeof(chunk_mem_spaces_static[0]) == + sizeof(chunk_addrs_static) / sizeof(chunk_addrs_static[0])); + if (num_chunks > (sizeof(chunk_mem_spaces_static) / sizeof(chunk_mem_spaces_static[0]))) { + if (NULL == (chunk_mem_spaces = H5MM_malloc(num_chunks * sizeof(H5S_t *)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "memory allocation failed for memory space list") + if (NULL == (chunk_file_spaces = H5MM_malloc(num_chunks * sizeof(H5S_t *)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "memory allocation failed for file space list") + if (NULL == (chunk_addrs = H5MM_malloc(num_chunks * sizeof(haddr_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "memory allocation failed for chunk address list") + } /* end if */ + else { + chunk_mem_spaces = chunk_mem_spaces_static; + chunk_file_spaces = chunk_file_spaces_static; + chunk_addrs = chunk_addrs_static; + } /* end else */ - /* Get the actual chunk information from the skip list node */ - chunk_info = H5D_CHUNK_GET_NODE_INFO(fm, chunk_node); + /* Reset num_chunks */ + num_chunks = 0; - /* Get the info for the chunk in the file */ - if (H5D__chunk_lookup(io_info->dset, chunk_info->scaled, &udata) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address") + /* Iterate through nodes in chunk skip list */ + chunk_node = H5D_CHUNK_GET_FIRST_NODE(fm); + while (chunk_node) { + H5D_chunk_info_t *chunk_info; /* Chunk information */ + H5D_chunk_ud_t udata; /* Chunk index pass-through */ - /* Sanity check */ - HDassert((H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length > 0) || - (!H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length == 0)); + /* Get the actual chunk information from the skip list node */ + chunk_info = H5D_CHUNK_GET_NODE_INFO(fm, chunk_node); - /* Check for non-existant chunk & skip it if appropriate */ - if (H5F_addr_defined(udata.chunk_block.offset) || UINT_MAX != udata.idx_hint || - !skip_missing_chunks) { - H5D_io_info_t *chk_io_info; /* Pointer to I/O info object for this chunk */ - void * chunk = NULL; /* Pointer to locked chunk buffer */ - htri_t cacheable; /* Whether the chunk is cacheable */ + /* Get the info for the chunk in the file */ + if (H5D__chunk_lookup(io_info->dset, chunk_info->scaled, &udata) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address") - /* Set chunk's [scaled] coordinates */ - io_info->store->chunk.scaled = chunk_info->scaled; + /* There should be no chunks cached */ + HDassert(UINT_MAX == udata.idx_hint); - /* Determine if we should use the chunk cache */ - if ((cacheable = H5D__chunk_cacheable(io_info, udata.chunk_block.offset, FALSE)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't tell if chunk is cacheable") - if (cacheable) { - /* Load the chunk into cache and lock it. */ + /* Sanity check */ + HDassert((H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length > 0) || + (!H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length == 0)); + + /* Check for non-existent chunk & skip it if appropriate */ + if (H5F_addr_defined(udata.chunk_block.offset)) { + /* Add chunk to list for selection I/O */ + chunk_mem_spaces[num_chunks] = chunk_info->mspace; + chunk_file_spaces[num_chunks] = chunk_info->fspace; + chunk_addrs[num_chunks] = udata.chunk_block.offset; + num_chunks++; + } /* end if */ + else if (!skip_missing_chunks) { + /* Perform the actual read operation from the nonexistent chunk + */ + if ((io_info->io_ops.single_read)(&nonexistent_io_info, type_info, + (hsize_t)chunk_info->chunk_points, chunk_info->fspace, + chunk_info->mspace) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "chunked read failed") + } /* end if */ - /* Compute # of bytes accessed in chunk */ - H5_CHECK_OVERFLOW(type_info->src_type_size, /*From:*/ size_t, /*To:*/ uint32_t); - src_accessed_bytes = chunk_info->chunk_points * (uint32_t)type_info->src_type_size; + /* Advance to next chunk in list */ + chunk_node = H5D_CHUNK_GET_NEXT_NODE(fm, chunk_node); + } /* end while */ - /* Lock the chunk into the cache */ - if (NULL == (chunk = H5D__chunk_lock(io_info, &udata, FALSE, FALSE))) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk") + /* Issue selection I/O call (we can skip the page buffer because we've + * already verified it won't be used, and the metadata accumulator + * because this is raw data) */ + if (H5F_shared_select_read(H5F_SHARED(io_info->dset->oloc.file), H5FD_MEM_DRAW, (uint32_t)num_chunks, + chunk_mem_spaces, chunk_file_spaces, chunk_addrs, element_sizes, bufs) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "chunk selection read failed") + + /* Clean up memory */ + if (chunk_mem_spaces != chunk_mem_spaces_static) { + HDassert(chunk_mem_spaces); + HDassert(chunk_file_spaces != chunk_file_spaces_static); + HDassert(chunk_addrs != chunk_addrs_static); + H5MM_free(chunk_mem_spaces); + chunk_mem_spaces = NULL; + H5MM_free(chunk_file_spaces); + chunk_file_spaces = NULL; + H5MM_free(chunk_addrs); + chunk_addrs = NULL; + } /* end if */ + } /* end if */ + else { + H5D_io_info_t ctg_io_info; /* Contiguous I/O info object */ + H5D_storage_t ctg_store; /* Chunk storage information as contiguous dataset */ + H5D_io_info_t cpt_io_info; /* Compact I/O info object */ + H5D_storage_t cpt_store; /* Chunk storage information as compact dataset */ + hbool_t cpt_dirty; /* Temporary placeholder for compact storage "dirty" flag */ + + /* Set up contiguous I/O info object */ + H5MM_memcpy(&ctg_io_info, io_info, sizeof(ctg_io_info)); + ctg_io_info.store = &ctg_store; + ctg_io_info.layout_ops = *H5D_LOPS_CONTIG; + + /* Initialize temporary contiguous storage info */ + H5_CHECKED_ASSIGN(ctg_store.contig.dset_size, hsize_t, io_info->dset->shared->layout.u.chunk.size, + uint32_t); + + /* Set up compact I/O info object */ + H5MM_memcpy(&cpt_io_info, io_info, sizeof(cpt_io_info)); + cpt_io_info.store = &cpt_store; + cpt_io_info.layout_ops = *H5D_LOPS_COMPACT; + + /* Initialize temporary compact storage info */ + cpt_store.compact.dirty = &cpt_dirty; + + /* Iterate through nodes in chunk skip list */ + chunk_node = H5D_CHUNK_GET_FIRST_NODE(fm); + while (chunk_node) { + H5D_chunk_info_t *chunk_info; /* Chunk information */ + H5D_chunk_ud_t udata; /* Chunk index pass-through */ + htri_t cacheable; /* Whether the chunk is cacheable */ + + /* Get the actual chunk information from the skip list node */ + chunk_info = H5D_CHUNK_GET_NODE_INFO(fm, chunk_node); + + /* Get the info for the chunk in the file */ + if (H5D__chunk_lookup(io_info->dset, chunk_info->scaled, &udata) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address") - /* Set up the storage buffer information for this chunk */ - cpt_store.compact.buf = chunk; + /* Sanity check */ + HDassert((H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length > 0) || + (!H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length == 0)); - /* Point I/O info at contiguous I/O info for this chunk */ - chk_io_info = &cpt_io_info; - } /* end if */ - else if (H5F_addr_defined(udata.chunk_block.offset)) { - /* Set up the storage address information for this chunk */ - ctg_store.contig.dset_addr = udata.chunk_block.offset; + /* Check for non-existent chunk & skip it if appropriate */ + if (H5F_addr_defined(udata.chunk_block.offset) || UINT_MAX != udata.idx_hint || + !skip_missing_chunks) { + H5D_io_info_t *chk_io_info; /* Pointer to I/O info object for this chunk */ + void * chunk = NULL; /* Pointer to locked chunk buffer */ - /* Point I/O info at temporary I/O info for this chunk */ - chk_io_info = &ctg_io_info; - } /* end else if */ - else { - /* Point I/O info at "nonexistent" I/O info for this chunk */ - chk_io_info = &nonexistent_io_info; - } /* end else */ + /* Set chunk's [scaled] coordinates */ + io_info->store->chunk.scaled = chunk_info->scaled; - /* Perform the actual read operation */ - if ((io_info->io_ops.single_read)(chk_io_info, type_info, (hsize_t)chunk_info->chunk_points, - chunk_info->fspace, chunk_info->mspace) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "chunked read failed") + /* Determine if we should use the chunk cache */ + if ((cacheable = H5D__chunk_cacheable(io_info, udata.chunk_block.offset, FALSE)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't tell if chunk is cacheable") + if (cacheable) { + /* Load the chunk into cache and lock it. */ - /* Release the cache lock on the chunk. */ - if (chunk && H5D__chunk_unlock(io_info, &udata, FALSE, chunk, src_accessed_bytes) < 0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk") - } /* end if */ + /* Compute # of bytes accessed in chunk */ + H5_CHECK_OVERFLOW(type_info->src_type_size, /*From:*/ size_t, /*To:*/ uint32_t); + src_accessed_bytes = chunk_info->chunk_points * (uint32_t)type_info->src_type_size; - /* Advance to next chunk in list */ - chunk_node = H5D_CHUNK_GET_NEXT_NODE(fm, chunk_node); - } /* end while */ + /* Lock the chunk into the cache */ + if (NULL == (chunk = H5D__chunk_lock(io_info, &udata, FALSE, FALSE))) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk") + + /* Set up the storage buffer information for this chunk */ + cpt_store.compact.buf = chunk; + + /* Point I/O info at contiguous I/O info for this chunk */ + chk_io_info = &cpt_io_info; + } /* end if */ + else if (H5F_addr_defined(udata.chunk_block.offset)) { + /* Set up the storage address information for this chunk */ + ctg_store.contig.dset_addr = udata.chunk_block.offset; + + /* Point I/O info at temporary I/O info for this chunk */ + chk_io_info = &ctg_io_info; + } /* end else if */ + else { + /* Point I/O info at "nonexistent" I/O info for this chunk */ + chk_io_info = &nonexistent_io_info; + } /* end else */ + + /* Perform the actual read operation */ + if ((io_info->io_ops.single_read)(chk_io_info, type_info, (hsize_t)chunk_info->chunk_points, + chunk_info->fspace, chunk_info->mspace) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "chunked read failed") + + /* Release the cache lock on the chunk. */ + if (chunk && H5D__chunk_unlock(io_info, &udata, FALSE, chunk, src_accessed_bytes) < 0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk") + } /* end if */ + + /* Advance to next chunk in list */ + chunk_node = H5D_CHUNK_GET_NEXT_NODE(fm, chunk_node); + } /* end while */ + } /* end else */ done: + /* Cleanup on failure */ + if (ret_value < 0) { + if (chunk_mem_spaces != chunk_mem_spaces_static) + chunk_mem_spaces = H5MM_xfree(chunk_mem_spaces); + if (chunk_file_spaces != chunk_file_spaces_static) + chunk_file_spaces = H5MM_xfree(chunk_file_spaces); + if (chunk_addrs != chunk_addrs_static) + chunk_addrs = H5MM_xfree(chunk_addrs); + } /* end if */ + + /* Make sure we cleaned up */ + HDassert(!chunk_mem_spaces || chunk_mem_spaces == chunk_mem_spaces_static); + HDassert(!chunk_file_spaces || chunk_file_spaces == chunk_file_spaces_static); + HDassert(!chunk_addrs || chunk_addrs == chunk_addrs_static); + FUNC_LEAVE_NOAPI(ret_value) } /* H5D__chunk_read() */ @@ -2602,17 +2822,22 @@ done: */ static herr_t H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t H5_ATTR_UNUSED nelmts, - const H5S_t H5_ATTR_UNUSED *file_space, const H5S_t H5_ATTR_UNUSED *mem_space, - H5D_chunk_map_t *fm) + H5S_t H5_ATTR_UNUSED *file_space, H5S_t H5_ATTR_UNUSED *mem_space, H5D_chunk_map_t *fm) { - H5SL_node_t * chunk_node; /* Current node in chunk skip list */ - H5D_io_info_t ctg_io_info; /* Contiguous I/O info object */ - H5D_storage_t ctg_store; /* Chunk storage information as contiguous dataset */ - H5D_io_info_t cpt_io_info; /* Compact I/O info object */ - H5D_storage_t cpt_store; /* Chunk storage information as compact dataset */ - hbool_t cpt_dirty; /* Temporary placeholder for compact storage "dirty" flag */ - uint32_t dst_accessed_bytes = 0; /* Total accessed size in a chunk */ - herr_t ret_value = SUCCEED; /* Return value */ + H5SL_node_t * chunk_node; /* Current node in chunk skip list */ + H5D_io_info_t ctg_io_info; /* Contiguous I/O info object */ + H5D_storage_t ctg_store; /* Chunk storage information as contiguous dataset */ + H5D_io_info_t cpt_io_info; /* Compact I/O info object */ + H5D_storage_t cpt_store; /* Chunk storage information as compact dataset */ + hbool_t cpt_dirty; /* Temporary placeholder for compact storage "dirty" flag */ + uint32_t dst_accessed_bytes = 0; /* Total accessed size in a chunk */ + H5S_t ** chunk_mem_spaces = NULL; /* Array of chunk memory spaces */ + H5S_t * chunk_mem_spaces_static[8]; /* Static buffer for chunk_mem_spaces */ + H5S_t ** chunk_file_spaces = NULL; /* Array of chunk file spaces */ + H5S_t * chunk_file_spaces_static[8]; /* Static buffer for chunk_file_spaces */ + haddr_t * chunk_addrs = NULL; /* Array of chunk addresses */ + haddr_t chunk_addrs_static[8]; /* Static buffer for chunk_addrs */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC @@ -2639,116 +2864,295 @@ H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize /* Initialize temporary compact storage info */ cpt_store.compact.dirty = &cpt_dirty; - /* Iterate through nodes in chunk skip list */ - chunk_node = H5D_CHUNK_GET_FIRST_NODE(fm); - while (chunk_node) { - H5D_chunk_info_t * chunk_info; /* Chunk information */ - H5D_chk_idx_info_t idx_info; /* Chunked index info */ - H5D_io_info_t * chk_io_info; /* Pointer to I/O info object for this chunk */ - void * chunk; /* Pointer to locked chunk buffer */ - H5D_chunk_ud_t udata; /* Index pass-through */ - htri_t cacheable; /* Whether the chunk is cacheable */ - hbool_t need_insert = FALSE; /* Whether the chunk needs to be inserted into the index */ + /* Different blocks depending on whether we're using selection I/O */ + if (io_info->use_select_io) { + size_t num_chunks; + size_t element_sizes[2] = {type_info->dst_type_size, 0}; + const void *bufs[2] = {io_info->u.wbuf, NULL}; + + /* Cache number of chunks */ + num_chunks = H5D_CHUNK_GET_NODE_COUNT(fm); + + /* Allocate arrays of dataspaces and offsets for use with selection I/O, + * or point to static buffers */ + HDassert(sizeof(chunk_mem_spaces_static) / sizeof(chunk_mem_spaces_static[0]) == + sizeof(chunk_file_spaces_static) / sizeof(chunk_file_spaces_static[0])); + HDassert(sizeof(chunk_mem_spaces_static) / sizeof(chunk_mem_spaces_static[0]) == + sizeof(chunk_addrs_static) / sizeof(chunk_addrs_static[0])); + if (num_chunks > (sizeof(chunk_mem_spaces_static) / sizeof(chunk_mem_spaces_static[0]))) { + if (NULL == (chunk_mem_spaces = H5MM_malloc(num_chunks * sizeof(H5S_t *)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "memory allocation failed for memory space list") + if (NULL == (chunk_file_spaces = H5MM_malloc(num_chunks * sizeof(H5S_t *)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "memory allocation failed for file space list") + if (NULL == (chunk_addrs = H5MM_malloc(num_chunks * sizeof(haddr_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "memory allocation failed for chunk address list") + } /* end if */ + else { + chunk_mem_spaces = chunk_mem_spaces_static; + chunk_file_spaces = chunk_file_spaces_static; + chunk_addrs = chunk_addrs_static; + } /* end else */ - /* Get the actual chunk information from the skip list node */ - chunk_info = H5D_CHUNK_GET_NODE_INFO(fm, chunk_node); + /* Reset num_chunks */ + num_chunks = 0; - /* Look up the chunk */ - if (H5D__chunk_lookup(io_info->dset, chunk_info->scaled, &udata) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address") + /* Iterate through nodes in chunk skip list */ + chunk_node = H5D_CHUNK_GET_FIRST_NODE(fm); + while (chunk_node) { + H5D_chunk_info_t * chunk_info; /* Chunk information */ + H5D_chk_idx_info_t idx_info; /* Chunked index info */ + H5D_chunk_ud_t udata; /* Index pass-through */ + htri_t cacheable; /* Whether the chunk is cacheable */ + hbool_t need_insert = FALSE; /* Whether the chunk needs to be inserted into the index */ - /* Sanity check */ - HDassert((H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length > 0) || - (!H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length == 0)); - - /* Set chunk's [scaled] coordinates */ - io_info->store->chunk.scaled = chunk_info->scaled; - - /* Determine if we should use the chunk cache */ - if ((cacheable = H5D__chunk_cacheable(io_info, udata.chunk_block.offset, TRUE)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't tell if chunk is cacheable") - if (cacheable) { - /* Load the chunk into cache. But if the whole chunk is written, - * simply allocate space instead of load the chunk. */ - hbool_t entire_chunk = TRUE; /* Whether whole chunk is selected */ - - /* Compute # of bytes accessed in chunk */ - H5_CHECK_OVERFLOW(type_info->dst_type_size, /*From:*/ size_t, /*To:*/ uint32_t); - dst_accessed_bytes = chunk_info->chunk_points * (uint32_t)type_info->dst_type_size; - - /* Determine if we will access all the data in the chunk */ - if (dst_accessed_bytes != ctg_store.contig.dset_size || - (chunk_info->chunk_points * type_info->src_type_size) != ctg_store.contig.dset_size || - fm->fsel_type == H5S_SEL_POINTS) - entire_chunk = FALSE; - - /* Lock the chunk into the cache */ - if (NULL == (chunk = H5D__chunk_lock(io_info, &udata, entire_chunk, FALSE))) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk") - - /* Set up the storage buffer information for this chunk */ - cpt_store.compact.buf = chunk; - - /* Point I/O info at main I/O info for this chunk */ - chk_io_info = &cpt_io_info; + /* Get the actual chunk information from the skip list node */ + chunk_info = H5D_CHUNK_GET_NODE_INFO(fm, chunk_node); + + /* Get the info for the chunk in the file */ + if (H5D__chunk_lookup(io_info->dset, chunk_info->scaled, &udata) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address") + + /* There should be no chunks cached */ + HDassert(UINT_MAX == udata.idx_hint); + + /* Sanity check */ + HDassert((H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length > 0) || + (!H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length == 0)); + + /* Set chunk's [scaled] coordinates */ + io_info->store->chunk.scaled = chunk_info->scaled; + + /* Determine if we should use the chunk cache */ + if ((cacheable = H5D__chunk_cacheable(io_info, udata.chunk_block.offset, TRUE)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't tell if chunk is cacheable") + if (cacheable) { + /* Load the chunk into cache. But if the whole chunk is written, + * simply allocate space instead of load the chunk. */ + void * chunk; /* Pointer to locked chunk buffer */ + hbool_t entire_chunk = TRUE; /* Whether whole chunk is selected */ + + /* Compute # of bytes accessed in chunk */ + H5_CHECK_OVERFLOW(type_info->dst_type_size, /*From:*/ size_t, /*To:*/ uint32_t); + dst_accessed_bytes = chunk_info->chunk_points * (uint32_t)type_info->dst_type_size; + + /* Determine if we will access all the data in the chunk */ + if (dst_accessed_bytes != ctg_store.contig.dset_size || + (chunk_info->chunk_points * type_info->src_type_size) != ctg_store.contig.dset_size || + fm->fsel_type == H5S_SEL_POINTS) + entire_chunk = FALSE; + + /* Lock the chunk into the cache */ + if (NULL == (chunk = H5D__chunk_lock(io_info, &udata, entire_chunk, FALSE))) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk") + + /* Set up the storage buffer information for this chunk */ + cpt_store.compact.buf = chunk; + + /* Perform the actual write operation */ + if ((io_info->io_ops.single_write)(&cpt_io_info, type_info, (hsize_t)chunk_info->chunk_points, + chunk_info->fspace, chunk_info->mspace) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "chunked write failed") + + /* Release the cache lock on the chunk */ + if (H5D__chunk_unlock(io_info, &udata, TRUE, chunk, dst_accessed_bytes) < 0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk") + } /* end if */ + else { + /* If the chunk hasn't been allocated on disk, do so now. */ + if (!H5F_addr_defined(udata.chunk_block.offset)) { + /* Compose chunked index info struct */ + idx_info.f = io_info->dset->oloc.file; + idx_info.pline = &(io_info->dset->shared->dcpl_cache.pline); + idx_info.layout = &(io_info->dset->shared->layout.u.chunk); + idx_info.storage = &(io_info->dset->shared->layout.storage.u.chunk); + + /* Set up the size of chunk for user data */ + udata.chunk_block.length = io_info->dset->shared->layout.u.chunk.size; + + /* Allocate the chunk */ + if (H5D__chunk_file_alloc(&idx_info, NULL, &udata.chunk_block, &need_insert, + chunk_info->scaled) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, + "unable to insert/resize chunk on chunk level") + + /* Make sure the address of the chunk is returned. */ + if (!H5F_addr_defined(udata.chunk_block.offset)) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "chunk address isn't defined") + + /* Cache the new chunk information */ + H5D__chunk_cinfo_cache_update(&io_info->dset->shared->cache.chunk.last, &udata); + + /* Insert chunk into index */ + if (need_insert && io_info->dset->shared->layout.storage.u.chunk.ops->insert) + if ((io_info->dset->shared->layout.storage.u.chunk.ops->insert)(&idx_info, &udata, + NULL) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, + "unable to insert chunk addr into index") + } /* end if */ + + /* Add chunk to list for selection I/O */ + chunk_mem_spaces[num_chunks] = chunk_info->mspace; + chunk_file_spaces[num_chunks] = chunk_info->fspace; + chunk_addrs[num_chunks] = udata.chunk_block.offset; + num_chunks++; + } /* end else */ + + /* Advance to next chunk in list */ + chunk_node = H5D_CHUNK_GET_NEXT_NODE(fm, chunk_node); + } /* end while */ + + /* Issue selection I/O call (we can skip the page buffer because we've + * already verified it won't be used, and the metadata accumulator + * because this is raw data) */ + if (H5F_shared_select_write(H5F_SHARED(io_info->dset->oloc.file), H5FD_MEM_DRAW, (uint32_t)num_chunks, + chunk_mem_spaces, chunk_file_spaces, chunk_addrs, element_sizes, + bufs) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "chunk selection read failed") + + /* Clean up memory */ + if (chunk_mem_spaces != chunk_mem_spaces_static) { + HDassert(chunk_mem_spaces); + HDassert(chunk_file_spaces != chunk_file_spaces_static); + HDassert(chunk_addrs != chunk_addrs_static); + H5MM_free(chunk_mem_spaces); + chunk_mem_spaces = NULL; + H5MM_free(chunk_file_spaces); + chunk_file_spaces = NULL; + H5MM_free(chunk_addrs); + chunk_addrs = NULL; } /* end if */ - else { - /* If the chunk hasn't been allocated on disk, do so now. */ - if (!H5F_addr_defined(udata.chunk_block.offset)) { - /* Compose chunked index info struct */ - idx_info.f = io_info->dset->oloc.file; - idx_info.pline = &(io_info->dset->shared->dcpl_cache.pline); - idx_info.layout = &(io_info->dset->shared->layout.u.chunk); - idx_info.storage = &(io_info->dset->shared->layout.storage.u.chunk); - - /* Set up the size of chunk for user data */ - udata.chunk_block.length = io_info->dset->shared->layout.u.chunk.size; - - /* Allocate the chunk */ - if (H5D__chunk_file_alloc(&idx_info, NULL, &udata.chunk_block, &need_insert, - chunk_info->scaled) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, - "unable to insert/resize chunk on chunk level") - - /* Make sure the address of the chunk is returned. */ - if (!H5F_addr_defined(udata.chunk_block.offset)) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "chunk address isn't defined") - - /* Cache the new chunk information */ - H5D__chunk_cinfo_cache_update(&io_info->dset->shared->cache.chunk.last, &udata); + } /* end if */ + else { + /* Iterate through nodes in chunk skip list */ + chunk_node = H5D_CHUNK_GET_FIRST_NODE(fm); + while (chunk_node) { + H5D_chunk_info_t * chunk_info; /* Chunk information */ + H5D_chk_idx_info_t idx_info; /* Chunked index info */ + H5D_io_info_t * chk_io_info; /* Pointer to I/O info object for this chunk */ + void * chunk; /* Pointer to locked chunk buffer */ + H5D_chunk_ud_t udata; /* Index pass-through */ + htri_t cacheable; /* Whether the chunk is cacheable */ + hbool_t need_insert = FALSE; /* Whether the chunk needs to be inserted into the index */ + + /* Get the actual chunk information from the skip list node */ + chunk_info = H5D_CHUNK_GET_NODE_INFO(fm, chunk_node); + + /* Look up the chunk */ + if (H5D__chunk_lookup(io_info->dset, chunk_info->scaled, &udata) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address") + + /* Sanity check */ + HDassert((H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length > 0) || + (!H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length == 0)); + + /* Set chunk's [scaled] coordinates */ + io_info->store->chunk.scaled = chunk_info->scaled; + + /* Determine if we should use the chunk cache */ + if ((cacheable = H5D__chunk_cacheable(io_info, udata.chunk_block.offset, TRUE)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't tell if chunk is cacheable") + if (cacheable) { + /* Load the chunk into cache. But if the whole chunk is written, + * simply allocate space instead of load the chunk. */ + hbool_t entire_chunk = TRUE; /* Whether whole chunk is selected */ + + /* Compute # of bytes accessed in chunk */ + H5_CHECK_OVERFLOW(type_info->dst_type_size, /*From:*/ size_t, /*To:*/ uint32_t); + dst_accessed_bytes = chunk_info->chunk_points * (uint32_t)type_info->dst_type_size; + + /* Determine if we will access all the data in the chunk */ + if (dst_accessed_bytes != ctg_store.contig.dset_size || + (chunk_info->chunk_points * type_info->src_type_size) != ctg_store.contig.dset_size || + fm->fsel_type == H5S_SEL_POINTS) + entire_chunk = FALSE; + + /* Lock the chunk into the cache */ + if (NULL == (chunk = H5D__chunk_lock(io_info, &udata, entire_chunk, FALSE))) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk") + + /* Set up the storage buffer information for this chunk */ + cpt_store.compact.buf = chunk; + + /* Point I/O info at main I/O info for this chunk */ + chk_io_info = &cpt_io_info; } /* end if */ + else { + /* If the chunk hasn't been allocated on disk, do so now. */ + if (!H5F_addr_defined(udata.chunk_block.offset)) { + /* Compose chunked index info struct */ + idx_info.f = io_info->dset->oloc.file; + idx_info.pline = &(io_info->dset->shared->dcpl_cache.pline); + idx_info.layout = &(io_info->dset->shared->layout.u.chunk); + idx_info.storage = &(io_info->dset->shared->layout.storage.u.chunk); + + /* Set up the size of chunk for user data */ + udata.chunk_block.length = io_info->dset->shared->layout.u.chunk.size; + + /* Allocate the chunk */ + if (H5D__chunk_file_alloc(&idx_info, NULL, &udata.chunk_block, &need_insert, + chunk_info->scaled) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, + "unable to insert/resize chunk on chunk level") + + /* Make sure the address of the chunk is returned. */ + if (!H5F_addr_defined(udata.chunk_block.offset)) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "chunk address isn't defined") + + /* Cache the new chunk information */ + H5D__chunk_cinfo_cache_update(&io_info->dset->shared->cache.chunk.last, &udata); + } /* end if */ - /* Set up the storage address information for this chunk */ - ctg_store.contig.dset_addr = udata.chunk_block.offset; + /* Set up the storage address information for this chunk */ + ctg_store.contig.dset_addr = udata.chunk_block.offset; - /* No chunk cached */ - chunk = NULL; + /* No chunk cached */ + chunk = NULL; - /* Point I/O info at temporary I/O info for this chunk */ - chk_io_info = &ctg_io_info; - } /* end else */ + /* Point I/O info at temporary I/O info for this chunk */ + chk_io_info = &ctg_io_info; + } /* end else */ - /* Perform the actual write operation */ - if ((io_info->io_ops.single_write)(chk_io_info, type_info, (hsize_t)chunk_info->chunk_points, - chunk_info->fspace, chunk_info->mspace) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "chunked write failed") + /* Perform the actual write operation */ + if ((io_info->io_ops.single_write)(chk_io_info, type_info, (hsize_t)chunk_info->chunk_points, + chunk_info->fspace, chunk_info->mspace) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "chunked write failed") - /* Release the cache lock on the chunk, or insert chunk into index. */ - if (chunk) { - if (H5D__chunk_unlock(io_info, &udata, TRUE, chunk, dst_accessed_bytes) < 0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk") - } /* end if */ - else { - if (need_insert && io_info->dset->shared->layout.storage.u.chunk.ops->insert) - if ((io_info->dset->shared->layout.storage.u.chunk.ops->insert)(&idx_info, &udata, NULL) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert chunk addr into index") - } /* end else */ + /* Release the cache lock on the chunk, or insert chunk into index. */ + if (chunk) { + if (H5D__chunk_unlock(io_info, &udata, TRUE, chunk, dst_accessed_bytes) < 0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk") + } /* end if */ + else { + if (need_insert && io_info->dset->shared->layout.storage.u.chunk.ops->insert) + if ((io_info->dset->shared->layout.storage.u.chunk.ops->insert)(&idx_info, &udata, NULL) < + 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, + "unable to insert chunk addr into index") + } /* end else */ - /* Advance to next chunk in list */ - chunk_node = H5D_CHUNK_GET_NEXT_NODE(fm, chunk_node); - } /* end while */ + /* Advance to next chunk in list */ + chunk_node = H5D_CHUNK_GET_NEXT_NODE(fm, chunk_node); + } /* end while */ + } /* end else */ done: + /* Cleanup on failure */ + if (ret_value < 0) { + if (chunk_mem_spaces != chunk_mem_spaces_static) + chunk_mem_spaces = H5MM_xfree(chunk_mem_spaces); + if (chunk_file_spaces != chunk_file_spaces_static) + chunk_file_spaces = H5MM_xfree(chunk_file_spaces); + if (chunk_addrs != chunk_addrs_static) + chunk_addrs = H5MM_xfree(chunk_addrs); + } /* end if */ + + /* Make sure we cleaned up */ + HDassert(!chunk_mem_spaces || chunk_mem_spaces == chunk_mem_spaces_static); + HDassert(!chunk_file_spaces || chunk_file_spaces == chunk_file_spaces_static); + HDassert(!chunk_addrs || chunk_addrs == chunk_addrs_static); + FUNC_LEAVE_NOAPI(ret_value) } /* H5D__chunk_write() */ @@ -3153,11 +3557,16 @@ H5D__chunk_hash_val(const H5D_shared_t *shared, const hsize_t *scaled) herr_t H5D__chunk_lookup(const H5D_t *dset, const hsize_t *scaled, H5D_chunk_ud_t *udata) { - H5D_rdcc_ent_t * ent = NULL; /* Cache entry */ - H5O_storage_chunk_t *sc = &(dset->shared->layout.storage.u.chunk); - unsigned idx = 0; /* Index of chunk in cache, if present */ - hbool_t found = FALSE; /* In cache? */ - herr_t ret_value = SUCCEED; /* Return value */ + H5D_rdcc_ent_t * ent = NULL; /* Cache entry */ + H5O_storage_chunk_t *sc = &(dset->shared->layout.storage.u.chunk); + unsigned idx = 0; /* Index of chunk in cache, if present */ + hbool_t found = FALSE; /* In cache? */ +#ifdef H5_HAVE_PARALLEL + H5P_coll_md_read_flag_t md_reads_file_flag; + hbool_t md_reads_context_flag; + hbool_t restore_md_reads_state = FALSE; +#endif + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE @@ -3228,8 +3637,12 @@ H5D__chunk_lookup(const H5D_t *dset, const hsize_t *scaled, H5D_chunk_ud_t *udat * highly unlikely that users would read the same chunks from all * processes. */ - if (H5F_HAS_FEATURE(idx_info.f, H5FD_FEAT_HAS_MPI)) - H5CX_set_coll_metadata_read(FALSE); + if (H5F_HAS_FEATURE(idx_info.f, H5FD_FEAT_HAS_MPI)) { + md_reads_file_flag = H5P_FORCE_FALSE; + md_reads_context_flag = FALSE; + H5F_set_coll_metadata_reads(idx_info.f, &md_reads_file_flag, &md_reads_context_flag); + restore_md_reads_state = TRUE; + } #endif /* H5_HAVE_PARALLEL */ /* Go get the chunk information */ @@ -3272,6 +3685,12 @@ H5D__chunk_lookup(const H5D_t *dset, const hsize_t *scaled, H5D_chunk_ud_t *udat } /* end else */ done: +#ifdef H5_HAVE_PARALLEL + /* Re-enable collective metadata reads if we disabled them */ + if (restore_md_reads_state) + H5F_set_coll_metadata_reads(dset->oloc.file, &md_reads_file_flag, &md_reads_context_flag); +#endif /* H5_HAVE_PARALLEL */ + FUNC_LEAVE_NOAPI(ret_value) } /* H5D__chunk_lookup() */ @@ -3581,7 +4000,7 @@ H5D__chunk_cache_prune(const H5D_t *dset, size_t size) * traversing the list when pointer pN reaches wN percent of the original * list. In other words, preemption method N gets to consider entries in * approximate least recently used order w0 percent before method N+1 - * where 100% means tha method N will run to completion before method N+1 + * where 100% means the method N will run to completion before method N+1 * begins. The pointers participating in the list traversal are each * given a chance at preemption before any of the pointers are advanced. */ @@ -4285,8 +4704,8 @@ H5D__chunk_allocate(const H5D_io_info_t *io_info, hbool_t full_overwrite, const hbool_t blocks_written = FALSE; /* Flag to indicate that chunk was actually written */ hbool_t using_mpi = FALSE; /* Flag to indicate that the file is being accessed with an MPI-capable file driver */ - H5D_chunk_coll_info_t chunk_info; /* chunk address information for doing I/O */ -#endif /* H5_HAVE_PARALLEL */ + H5D_chunk_coll_fill_info_t chunk_fill_info; /* chunk address information for doing I/O */ +#endif /* H5_HAVE_PARALLEL */ hbool_t carry; /* Flag to indicate that chunk increment carrys to higher dimension (sorta) */ unsigned space_ndims; /* Dataset's space rank */ const hsize_t * space_dim; /* Dataset's dataspace dimensions */ @@ -4333,8 +4752,8 @@ H5D__chunk_allocate(const H5D_io_info_t *io_info, hbool_t full_overwrite, const using_mpi = TRUE; /* init chunk info stuff for collective I/O */ - chunk_info.num_io = 0; - chunk_info.addr = NULL; + chunk_fill_info.num_chunks = 0; + chunk_fill_info.chunk_info = NULL; } /* end if */ #endif /* H5_HAVE_PARALLEL */ @@ -4387,7 +4806,7 @@ H5D__chunk_allocate(const H5D_io_info_t *io_info, hbool_t full_overwrite, const /* (delay allocating fill buffer for VL datatypes until refilling) */ /* (casting away const OK - QAK) */ if (H5D__fill_init(&fb_info, NULL, (H5MM_allocate_t)H5D__chunk_mem_alloc, (void *)pline, - (H5MM_free_t)H5D__chunk_mem_xfree, (void *)pline, &dset->shared->dcpl_cache.fill, + (H5MM_free_t)H5D__chunk_mem_free, (void *)pline, &dset->shared->dcpl_cache.fill, dset->shared->type, dset->shared->type_id, (size_t)0, orig_chunk_size) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize fill buffer info") fb_info_init = TRUE; @@ -4606,19 +5025,26 @@ H5D__chunk_allocate(const H5D_io_info_t *io_info, hbool_t full_overwrite, const if (using_mpi) { /* collect all chunk addresses to be written to write collectively at the end */ - /* allocate/resize address array if no more space left */ - /* Note that if we add support for parallel filters we must - * also store an array of chunk sizes and pass it to the - * apporpriate collective write function */ - if (0 == chunk_info.num_io % 1024) - if (NULL == (chunk_info.addr = (haddr_t *)H5MM_realloc( - chunk_info.addr, (chunk_info.num_io + 1024) * sizeof(haddr_t)))) + + /* allocate/resize chunk info array if no more space left */ + if (0 == chunk_fill_info.num_chunks % 1024) { + void *tmp_realloc; + + if (NULL == (tmp_realloc = H5MM_realloc(chunk_fill_info.chunk_info, + (chunk_fill_info.num_chunks + 1024) * + sizeof(struct chunk_coll_fill_info)))) HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, - "memory allocation failed for chunk addresses") + "memory allocation failed for chunk fill info") + + chunk_fill_info.chunk_info = tmp_realloc; + } - /* Store the chunk's address for later */ - chunk_info.addr[chunk_info.num_io] = udata.chunk_block.offset; - chunk_info.num_io++; + /* Store info about the chunk for later */ + chunk_fill_info.chunk_info[chunk_fill_info.num_chunks].addr = udata.chunk_block.offset; + chunk_fill_info.chunk_info[chunk_fill_info.num_chunks].chunk_size = chunk_size; + chunk_fill_info.chunk_info[chunk_fill_info.num_chunks].unfiltered_partial_chunk = + (*fill_buf == unfilt_fill_buf); + chunk_fill_info.num_chunks++; /* Indicate that blocks will be written */ blocks_written = TRUE; @@ -4691,7 +5117,7 @@ H5D__chunk_allocate(const H5D_io_info_t *io_info, hbool_t full_overwrite, const #ifdef H5_HAVE_PARALLEL /* do final collective I/O */ if (using_mpi && blocks_written) - if (H5D__chunk_collective_fill(dset, &chunk_info, chunk_size, fb_info.fill_buf) < 0) + if (H5D__chunk_collective_fill(dset, &chunk_fill_info, fb_info.fill_buf, unfilt_fill_buf) < 0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write raw data to file") #endif /* H5_HAVE_PARALLEL */ @@ -4707,8 +5133,8 @@ done: unfilt_fill_buf = H5D__chunk_mem_xfree(unfilt_fill_buf, &def_pline); #ifdef H5_HAVE_PARALLEL - if (using_mpi && chunk_info.addr) - H5MM_free(chunk_info.addr); + if (using_mpi && chunk_fill_info.chunk_info) + H5MM_free(chunk_fill_info.chunk_info); #endif FUNC_LEAVE_NOAPI(ret_value) @@ -4902,27 +5328,35 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5D__chunk_collective_fill(const H5D_t *dset, H5D_chunk_coll_info_t *chunk_info, size_t chunk_size, - const void *fill_buf) +H5D__chunk_collective_fill(const H5D_t *dset, H5D_chunk_coll_fill_info_t *chunk_fill_info, + const void *fill_buf, const void *partial_chunk_fill_buf) { - MPI_Comm mpi_comm = MPI_COMM_NULL; /* MPI communicator for file */ - int mpi_rank = (-1); /* This process's rank */ - int mpi_size = (-1); /* MPI Comm size */ - int mpi_code; /* MPI return code */ - size_t num_blocks; /* Number of blocks between processes. */ - size_t leftover_blocks; /* Number of leftover blocks to handle */ - int blocks, leftover, block_len; /* converted to int for MPI */ + MPI_Comm mpi_comm = MPI_COMM_NULL; /* MPI communicator for file */ + int mpi_rank = (-1); /* This process's rank */ + int mpi_size = (-1); /* MPI Comm size */ + int mpi_code; /* MPI return code */ + size_t num_blocks; /* Number of blocks between processes. */ + size_t leftover_blocks; /* Number of leftover blocks to handle */ + int blocks, leftover; /* converted to int for MPI */ MPI_Aint * chunk_disp_array = NULL; + MPI_Aint * block_disps = NULL; int * block_lens = NULL; MPI_Datatype mem_type = MPI_BYTE, file_type = MPI_BYTE; H5FD_mpio_xfer_t prev_xfer_mode; /* Previous data xfer mode */ hbool_t have_xfer_mode = FALSE; /* Whether the previous xffer mode has been retrieved */ - hbool_t need_addr_sort = FALSE; - int i; /* Local index variable */ + hbool_t need_sort = FALSE; + size_t i; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC + /* + * If a separate fill buffer is provided for partial chunks, ensure + * that the "don't filter partial edge chunks" flag is set. + */ + if (partial_chunk_fill_buf) + HDassert(dset->shared->layout.u.chunk.flags & H5O_LAYOUT_CHUNK_DONT_FILTER_PARTIAL_BOUND_CHUNKS); + /* Get the MPI communicator */ if (MPI_COMM_NULL == (mpi_comm = H5F_mpi_get_comm(dset->oloc.file))) HGOTO_ERROR(H5E_INTERNAL, H5E_MPI, FAIL, "Can't retrieve MPI communicator") @@ -4938,39 +5372,89 @@ H5D__chunk_collective_fill(const H5D_t *dset, H5D_chunk_coll_info_t *chunk_info, /* Distribute evenly the number of blocks between processes. */ if (mpi_size == 0) HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "Resulted in division by zero") - num_blocks = (size_t)(chunk_info->num_io / (size_t)mpi_size); /* value should be the same on all procs */ + num_blocks = + (size_t)(chunk_fill_info->num_chunks / (size_t)mpi_size); /* value should be the same on all procs */ /* After evenly distributing the blocks between processes, are there any * leftover blocks for each individual process (round-robin)? */ - leftover_blocks = (size_t)(chunk_info->num_io % (size_t)mpi_size); + leftover_blocks = (size_t)(chunk_fill_info->num_chunks % (size_t)mpi_size); /* Cast values to types needed by MPI */ H5_CHECKED_ASSIGN(blocks, int, num_blocks, size_t); H5_CHECKED_ASSIGN(leftover, int, leftover_blocks, size_t); - H5_CHECKED_ASSIGN(block_len, int, chunk_size, size_t); /* Check if we have any chunks to write on this rank */ if (num_blocks > 0 || (leftover && leftover > mpi_rank)) { + MPI_Aint partial_fill_buf_disp = 0; + hbool_t all_same_block_len = TRUE; + /* Allocate buffers */ - /* (MSC - should not need block_lens if MPI_type_create_hindexed_block is working) */ - if (NULL == (block_lens = (int *)H5MM_malloc((size_t)(blocks + 1) * sizeof(int)))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate chunk lengths buffer") if (NULL == (chunk_disp_array = (MPI_Aint *)H5MM_malloc((size_t)(blocks + 1) * sizeof(MPI_Aint)))) HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate chunk file displacement buffer") - for (i = 0; i < blocks; i++) { - /* store the chunk address as an MPI_Aint */ - chunk_disp_array[i] = (MPI_Aint)(chunk_info->addr[i + (mpi_rank * blocks)]); + if (partial_chunk_fill_buf) { + MPI_Aint fill_buf_addr; + MPI_Aint partial_fill_buf_addr; - /* MSC - should not need this if MPI_type_create_hindexed_block is working */ - block_lens[i] = block_len; + /* Calculate the displacement between the fill buffer and partial chunk fill buffer */ + if (MPI_SUCCESS != (mpi_code = MPI_Get_address(fill_buf, &fill_buf_addr))) + HMPI_GOTO_ERROR(FAIL, "MPI_Get_address failed", mpi_code) + if (MPI_SUCCESS != (mpi_code = MPI_Get_address(partial_chunk_fill_buf, &partial_fill_buf_addr))) + HMPI_GOTO_ERROR(FAIL, "MPI_Get_address failed", mpi_code) + +#if H5_CHECK_MPI_VERSION(3, 1) + partial_fill_buf_disp = MPI_Aint_diff(partial_fill_buf_addr, fill_buf_addr); +#else + partial_fill_buf_disp = partial_fill_buf_addr - fill_buf_addr; +#endif - /* Make sure that the addresses in the datatype are - * monotonically non-decreasing + /* + * Allocate all-zero block displacements array. If a block's displacement + * is left as zero, that block will be written to from the regular fill + * buffer. If a block represents an unfiltered partial edge chunk, its + * displacement will be set so that the block is written to from the + * unfiltered fill buffer. */ - if (i && (chunk_disp_array[i] < chunk_disp_array[i - 1])) - need_addr_sort = TRUE; + if (NULL == (block_disps = (MPI_Aint *)H5MM_calloc((size_t)(blocks + 1) * sizeof(MPI_Aint)))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate block displacements buffer") + } + + /* + * Perform initial scan of chunk info list to: + * - make sure that chunk addresses are monotonically non-decreasing + * - check if all blocks have the same length + */ + for (i = 1; i < chunk_fill_info->num_chunks; i++) { + if (chunk_fill_info->chunk_info[i].addr < chunk_fill_info->chunk_info[i - 1].addr) + need_sort = TRUE; + + if (chunk_fill_info->chunk_info[i].chunk_size != chunk_fill_info->chunk_info[i - 1].chunk_size) + all_same_block_len = FALSE; + } + + if (need_sort) + HDqsort(chunk_fill_info->chunk_info, chunk_fill_info->num_chunks, + sizeof(struct chunk_coll_fill_info), H5D__chunk_cmp_coll_fill_info); + + /* Allocate buffer for block lengths if necessary */ + if (!all_same_block_len) + if (NULL == (block_lens = (int *)H5MM_malloc((size_t)(blocks + 1) * sizeof(int)))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate chunk lengths buffer") + + for (i = 0; i < (size_t)blocks; i++) { + size_t idx = i + (size_t)(mpi_rank * blocks); + + /* store the chunk address as an MPI_Aint */ + chunk_disp_array[i] = (MPI_Aint)(chunk_fill_info->chunk_info[idx].addr); + + if (!all_same_block_len) + H5_CHECKED_ASSIGN(block_lens[i], int, chunk_fill_info->chunk_info[idx].chunk_size, size_t); + + if (chunk_fill_info->chunk_info[idx].unfiltered_partial_chunk) { + HDassert(partial_chunk_fill_buf); + block_disps[i] = partial_fill_buf_disp; + } } /* end for */ /* Calculate if there are any leftover blocks after evenly @@ -4978,32 +5462,71 @@ H5D__chunk_collective_fill(const H5D_t *dset, H5D_chunk_coll_info_t *chunk_info, * to processes 0 -> leftover. */ if (leftover && leftover > mpi_rank) { - chunk_disp_array[blocks] = (MPI_Aint)chunk_info->addr[(blocks * mpi_size) + mpi_rank]; - if (blocks && (chunk_disp_array[blocks] < chunk_disp_array[blocks - 1])) - need_addr_sort = TRUE; - block_lens[blocks] = block_len; + chunk_disp_array[blocks] = + (MPI_Aint)chunk_fill_info->chunk_info[(blocks * mpi_size) + mpi_rank].addr; + + if (!all_same_block_len) + H5_CHECKED_ASSIGN(block_lens[blocks], int, + chunk_fill_info->chunk_info[(blocks * mpi_size) + mpi_rank].chunk_size, + size_t); + + if (chunk_fill_info->chunk_info[(blocks * mpi_size) + mpi_rank].unfiltered_partial_chunk) { + HDassert(partial_chunk_fill_buf); + block_disps[blocks] = partial_fill_buf_disp; + } + blocks++; } - /* Ensure that the blocks are sorted in monotonically non-decreasing - * order of offset in the file. - */ - if (need_addr_sort) - HDqsort(chunk_disp_array, (size_t)blocks, sizeof(MPI_Aint), H5D__chunk_cmp_addr); + /* Create file and memory types for the write operation */ + if (all_same_block_len) { + int block_len; + + H5_CHECKED_ASSIGN(block_len, int, chunk_fill_info->chunk_info[0].chunk_size, size_t); + + mpi_code = + MPI_Type_create_hindexed_block(blocks, block_len, chunk_disp_array, MPI_BYTE, &file_type); + if (mpi_code != MPI_SUCCESS) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hindexed_block failed", mpi_code) + + if (partial_chunk_fill_buf) { + /* + * If filters are disabled for partial edge chunks, those chunks could + * potentially have the same block length as the other chunks, but still + * need to be written to using the unfiltered fill buffer. Use an hindexed + * block type rather than an hvector. + */ + mpi_code = + MPI_Type_create_hindexed_block(blocks, block_len, block_disps, MPI_BYTE, &mem_type); + if (mpi_code != MPI_SUCCESS) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hindexed_block failed", mpi_code) + } + else { + mpi_code = MPI_Type_create_hvector(blocks, block_len, 0, MPI_BYTE, &mem_type); + if (mpi_code != MPI_SUCCESS) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hvector failed", mpi_code) + } + } + else { + /* + * Currently, different block lengths implies that there are partial + * edge chunks and the "don't filter partial edge chunks" flag is set. + */ + HDassert(partial_chunk_fill_buf); + HDassert(block_lens); + HDassert(block_disps); + + mpi_code = MPI_Type_create_hindexed(blocks, block_lens, chunk_disp_array, MPI_BYTE, &file_type); + if (mpi_code != MPI_SUCCESS) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hindexed failed", mpi_code) + + mpi_code = MPI_Type_create_hindexed(blocks, block_lens, block_disps, MPI_BYTE, &mem_type); + if (mpi_code != MPI_SUCCESS) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hindexed failed", mpi_code) + } - /* MSC - should use this if MPI_type_create_hindexed block is working: - * mpi_code = MPI_Type_create_hindexed_block(blocks, block_len, chunk_disp_array, MPI_BYTE, - * &file_type); - */ - mpi_code = MPI_Type_create_hindexed(blocks, block_lens, chunk_disp_array, MPI_BYTE, &file_type); - if (mpi_code != MPI_SUCCESS) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hindexed failed", mpi_code) if (MPI_SUCCESS != (mpi_code = MPI_Type_commit(&file_type))) HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code) - - mpi_code = MPI_Type_create_hvector(blocks, block_len, 0, MPI_BYTE, &mem_type); - if (mpi_code != MPI_SUCCESS) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hvector failed", mpi_code) if (MPI_SUCCESS != (mpi_code = MPI_Type_commit(&mem_type))) HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code) } /* end if */ @@ -5046,39 +5569,25 @@ done: if (MPI_SUCCESS != (mpi_code = MPI_Type_free(&mem_type))) HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) H5MM_xfree(chunk_disp_array); + H5MM_xfree(block_disps); H5MM_xfree(block_lens); FUNC_LEAVE_NOAPI(ret_value) } /* end H5D__chunk_collective_fill() */ static int -H5D__chunk_cmp_addr(const void *addr1, const void *addr2) +H5D__chunk_cmp_coll_fill_info(const void *_entry1, const void *_entry2) { - MPI_Aint _addr1 = (MPI_Aint)0, _addr2 = (MPI_Aint)0; - int ret_value = 0; + const struct chunk_coll_fill_info *entry1; + const struct chunk_coll_fill_info *entry2; FUNC_ENTER_STATIC_NOERR - _addr1 = *((const MPI_Aint *)addr1); - _addr2 = *((const MPI_Aint *)addr2); - -#if MPI_VERSION >= 3 && MPI_SUBVERSION >= 1 - { - MPI_Aint diff = MPI_Aint_diff(_addr1, _addr2); - - if (diff < (MPI_Aint)0) - ret_value = -1; - else if (diff > (MPI_Aint)0) - ret_value = 1; - else - ret_value = 0; - } -#else - ret_value = (_addr1 > _addr2) - (_addr1 < _addr2); -#endif + entry1 = (const struct chunk_coll_fill_info *)_entry1; + entry2 = (const struct chunk_coll_fill_info *)_entry2; - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5D__chunk_cmp_addr() */ + FUNC_LEAVE_NOAPI(H5F_addr_cmp(entry1->addr, entry2->addr)) +} /* end H5D__chunk_cmp_coll_fill_info() */ #endif /* H5_HAVE_PARALLEL */ /*------------------------------------------------------------------------- @@ -5186,7 +5695,7 @@ H5D__chunk_prune_fill(H5D_chunk_it_ud1_t *udata, hbool_t new_unfilt_chunk) /* The number of bytes accessed in the chunk */ /* (i.e. the bytes replaced with fill values) */ - H5_CHECK_OVERFLOW(sel_nelmts, hssize_t, uint32_t); + H5_CHECK_OVERFLOW(sel_nelmts, hsize_t, uint32_t); bytes_accessed = (uint32_t)sel_nelmts * layout->u.chunk.dim[rank]; /* Release lock on chunk */ @@ -5931,7 +6440,7 @@ H5D__chunk_copy_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata) size_t buf_size = udata->buf_size; /* Size of chunk buffer */ const H5O_pline_t *pline = udata->pline; /* I/O pipeline for applying filters */ - /* needed for commpressed variable length data */ + /* needed for compressed variable length data */ hbool_t must_filter = FALSE; /* Whether chunk must be filtered during copy */ size_t nbytes; /* Size of chunk in file (in bytes) */ H5Z_cb_t filter_cb; /* Filter failure callback struct */ @@ -6662,10 +7171,10 @@ H5D__chunk_stats(const H5D_t *dset, hbool_t headers) miss_rate = 0.0; } if (miss_rate > 100) { - HDsprintf(ascii, "%7d%%", (int)(miss_rate + 0.5)); + HDsnprintf(ascii, sizeof(ascii), "%7d%%", (int)(miss_rate + 0.5)); } else { - HDsprintf(ascii, "%7.2f%%", miss_rate); + HDsnprintf(ascii, sizeof(ascii), "%7.2f%%", miss_rate); } HDfprintf(H5DEBUG(AC), " %-18s %8u %8u %7s %8d+%-9ld\n", "raw data chunks", rdcc->stats.nhits, @@ -6792,7 +7301,7 @@ done: * *------------------------------------------------------------------------- */ -static hbool_t +hbool_t H5D__chunk_is_partial_edge_chunk(unsigned dset_ndims, const uint32_t *chunk_dims, const hsize_t scaled[], const hsize_t *dset_dims) { @@ -7087,6 +7596,89 @@ done: } /* end H5D__chunk_format_convert() */ /*------------------------------------------------------------------------- + * Function: H5D__chunk_index_empty_cb + * + * Purpose: Callback function that simply stops iteration and sets the + * `empty` parameter to FALSE if called. If this callback is + * entered, it means that the chunk index contains at least + * one chunk, so is not empty. + * + * Return: H5_ITER_STOP + * + *------------------------------------------------------------------------- + */ +static int +H5D__chunk_index_empty_cb(const H5D_chunk_rec_t H5_ATTR_UNUSED *chunk_rec, void *_udata) +{ + hbool_t *empty = (hbool_t *)_udata; + int ret_value = H5_ITER_STOP; + + FUNC_ENTER_STATIC_NOERR + + *empty = FALSE; + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D__chunk_index_empty_cb() */ + +/*------------------------------------------------------------------------- + * Function: H5D__chunk_index_empty + * + * Purpose: Determines whether a chunk index is empty (has no chunks + * inserted into it yet). + * + * Note: This routine is meant to be a little more performant than + * just counting the number of chunks in the index. In the + * future, this is probably a callback that the chunk index + * ops structure should provide. + * + * Return: Non-negative on Success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5D__chunk_index_empty(const H5D_t *dset, hbool_t *empty) +{ + H5D_chk_idx_info_t idx_info; /* Chunked index info */ + H5D_rdcc_ent_t * ent; /* Cache entry */ + const H5D_rdcc_t * rdcc = NULL; /* Raw data chunk cache */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE_TAG(dset->oloc.addr) + + HDassert(dset); + HDassert(dset->shared); + HDassert(empty); + + rdcc = &(dset->shared->cache.chunk); /* raw data chunk cache */ + HDassert(rdcc); + + /* Search for cached chunks that haven't been written out */ + for (ent = rdcc->head; ent; ent = ent->next) + /* Flush the chunk out to disk, to make certain the size is correct later */ + if (H5D__chunk_flush_entry(dset, ent, FALSE) < 0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "cannot flush indexed storage buffer") + + /* Compose chunked index info struct */ + idx_info.f = dset->oloc.file; + idx_info.pline = &dset->shared->dcpl_cache.pline; + idx_info.layout = &dset->shared->layout.u.chunk; + idx_info.storage = &dset->shared->layout.storage.u.chunk; + + *empty = TRUE; + + if (H5F_addr_defined(idx_info.storage->idx_addr)) { + /* Iterate over the allocated chunks */ + if ((dset->shared->layout.storage.u.chunk.ops->iterate)(&idx_info, H5D__chunk_index_empty_cb, empty) < + 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, + "unable to retrieve allocated chunk information from index") + } + +done: + FUNC_LEAVE_NOAPI_TAG(ret_value) +} /* end H5D__chunk_index_empty() */ + +/*------------------------------------------------------------------------- * Function: H5D__get_num_chunks_cb * * Purpose: Callback function that increments the number of written @@ -7491,7 +8083,7 @@ H5D__chunk_iter_cb(const H5D_chunk_rec_t *chunk_rec, void *udata) /*------------------------------------------------------------------------- * Function: H5D__chunk_iter * - * Purpose: Iterate over all the chunks in the dataset with given callbak. + * Purpose: Iterate over all the chunks in the dataset with given callback. * * Return: Success: Non-negative * Failure: Negative diff --git a/src/H5Dcompact.c b/src/H5Dcompact.c index fe41298..1ac1267 100644 --- a/src/H5Dcompact.c +++ b/src/H5Dcompact.c @@ -47,6 +47,15 @@ /* Local Typedefs */ /******************/ +/* Callback info for I/O operation when file driver + * wishes to do its own memory management + */ +typedef struct H5D_compact_iovv_memmanage_ud_t { + H5F_shared_t *f_sh; /* Shared file for dataset */ + void * dstbuf; /* Pointer to buffer to be read into/written into */ + const void * srcbuf; /* Pointer to buffer to be read from/written from */ +} H5D_compact_iovv_memmanage_ud_t; + /********************/ /* Local Prototypes */ /********************/ @@ -54,9 +63,9 @@ /* Layout operation callbacks */ static herr_t H5D__compact_construct(H5F_t *f, H5D_t *dset); static hbool_t H5D__compact_is_space_alloc(const H5O_storage_t *storage); -static herr_t H5D__compact_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info, - hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space, - H5D_chunk_map_t *cm); +static herr_t H5D__compact_io_init(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, + H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t *cm); +static herr_t H5D__compact_iovv_memmanage_cb(hsize_t dst_off, hsize_t src_off, size_t len, void *_udata); static ssize_t H5D__compact_readvv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_size_arr[], hsize_t dset_offset_arr[], size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_size_arr[], hsize_t mem_offset_arr[]); @@ -71,13 +80,24 @@ static herr_t H5D__compact_dest(H5D_t *dset); /*********************/ /* Compact storage layout I/O ops */ -const H5D_layout_ops_t H5D_LOPS_COMPACT[1] = { - {H5D__compact_construct, NULL, H5D__compact_is_space_alloc, NULL, H5D__compact_io_init, H5D__contig_read, - H5D__contig_write, +const H5D_layout_ops_t H5D_LOPS_COMPACT[1] = {{ + H5D__compact_construct, /* construct */ + NULL, /* init */ + H5D__compact_is_space_alloc, /* is_space_alloc */ + NULL, /* is_data_cached */ + H5D__compact_io_init, /* io_init */ + H5D__contig_read, /* ser_read */ + H5D__contig_write, /* ser_write */ #ifdef H5_HAVE_PARALLEL - NULL, NULL, -#endif /* H5_HAVE_PARALLEL */ - H5D__compact_readvv, H5D__compact_writevv, H5D__compact_flush, NULL, H5D__compact_dest}}; + NULL, /* par_read */ + NULL, /* par_write */ +#endif + H5D__compact_readvv, /* readvv */ + H5D__compact_writevv, /* writevv */ + H5D__compact_flush, /* flush */ + NULL, /* io_term */ + H5D__compact_dest /* dest */ +}}; /*******************/ /* Local Variables */ @@ -227,9 +247,9 @@ H5D__compact_is_space_alloc(const H5O_storage_t H5_ATTR_UNUSED *storage) *------------------------------------------------------------------------- */ static herr_t -H5D__compact_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t H5_ATTR_UNUSED *type_info, - hsize_t H5_ATTR_UNUSED nelmts, const H5S_t H5_ATTR_UNUSED *file_space, - const H5S_t H5_ATTR_UNUSED *mem_space, H5D_chunk_map_t H5_ATTR_UNUSED *cm) +H5D__compact_io_init(H5D_io_info_t *io_info, const H5D_type_info_t H5_ATTR_UNUSED *type_info, + hsize_t H5_ATTR_UNUSED nelmts, H5S_t H5_ATTR_UNUSED *file_space, + H5S_t H5_ATTR_UNUSED *mem_space, H5D_chunk_map_t H5_ATTR_UNUSED *cm) { FUNC_ENTER_STATIC_NOERR @@ -240,6 +260,48 @@ H5D__compact_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t H5_ATTR } /* end H5D__compact_io_init() */ /*------------------------------------------------------------------------- + * Function: H5D__compact_iovv_memmanage_cb + * + * Purpose: Callback operator for H5D__compact_readvv()/_writevv() to + * send a memory copy request to the underlying file driver. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D__compact_iovv_memmanage_cb(hsize_t dst_off, hsize_t src_off, size_t len, void *_udata) +{ + H5D_compact_iovv_memmanage_ud_t *udata = (H5D_compact_iovv_memmanage_ud_t *)_udata; + H5FD_ctl_memcpy_args_t op_args; + uint64_t op_flags; + H5FD_t * file_handle = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC + + /* Retrieve pointer to file driver structure for ctl call */ + if (H5F_shared_get_file_driver(udata->f_sh, &file_handle) < 0) + HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "can't get file handle") + + /* Setup operation flags and arguments */ + op_flags = H5FD_CTL__ROUTE_TO_TERMINAL_VFD_FLAG | H5FD_CTL__FAIL_IF_UNKNOWN_FLAG; + + op_args.dstbuf = udata->dstbuf; + op_args.dst_off = dst_off; + op_args.srcbuf = udata->srcbuf; + op_args.src_off = src_off; + op_args.len = len; + + /* Make request to file driver */ + if (H5FD_ctl(file_handle, H5FD_CTL__MEM_COPY, op_flags, &op_args, NULL) < 0) + HGOTO_ERROR(H5E_IO, H5E_FCNTL, FAIL, "VFD memcpy request failed") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D__compact_iovv_memmanage_cb() */ + +/*------------------------------------------------------------------------- * Function: H5D__compact_readvv * * Purpose: Reads some data vectors from a dataset into a buffer. @@ -268,11 +330,28 @@ H5D__compact_readvv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t * HDassert(io_info); - /* Use the vectorized memory copy routine to do actual work */ - if ((ret_value = H5VM_memcpyvv(io_info->u.rbuf, mem_max_nseq, mem_curr_seq, mem_size_arr, mem_offset_arr, - io_info->store->compact.buf, dset_max_nseq, dset_curr_seq, dset_size_arr, - dset_offset_arr)) < 0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed") + /* Check if file driver wishes to do its own memory management */ + if (H5F_SHARED_HAS_FEATURE(io_info->f_sh, H5FD_FEAT_MEMMANAGE)) { + H5D_compact_iovv_memmanage_ud_t udata; + + /* Set up udata for memory copy operation */ + udata.f_sh = io_info->f_sh; + udata.dstbuf = io_info->u.rbuf; + udata.srcbuf = io_info->store->compact.buf; + + /* Request that file driver does the memory copy */ + if ((ret_value = H5VM_opvv(mem_max_nseq, mem_curr_seq, mem_size_arr, mem_offset_arr, dset_max_nseq, + dset_curr_seq, dset_size_arr, dset_offset_arr, + H5D__compact_iovv_memmanage_cb, &udata)) < 0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed") + } + else { + /* Use the vectorized memory copy routine to do actual work */ + if ((ret_value = H5VM_memcpyvv(io_info->u.rbuf, mem_max_nseq, mem_curr_seq, mem_size_arr, + mem_offset_arr, io_info->store->compact.buf, dset_max_nseq, + dset_curr_seq, dset_size_arr, dset_offset_arr)) < 0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed") + } done: FUNC_LEAVE_NOAPI(ret_value) @@ -310,11 +389,28 @@ H5D__compact_writevv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t HDassert(io_info); - /* Use the vectorized memory copy routine to do actual work */ - if ((ret_value = H5VM_memcpyvv(io_info->store->compact.buf, dset_max_nseq, dset_curr_seq, dset_size_arr, - dset_offset_arr, io_info->u.wbuf, mem_max_nseq, mem_curr_seq, mem_size_arr, - mem_offset_arr)) < 0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed") + /* Check if file driver wishes to do its own memory management */ + if (H5F_SHARED_HAS_FEATURE(io_info->f_sh, H5FD_FEAT_MEMMANAGE)) { + H5D_compact_iovv_memmanage_ud_t udata; + + /* Set up udata for memory copy operation */ + udata.f_sh = io_info->f_sh; + udata.dstbuf = io_info->store->compact.buf; + udata.srcbuf = io_info->u.wbuf; + + /* Request that file driver does the memory copy */ + if ((ret_value = H5VM_opvv(dset_max_nseq, dset_curr_seq, dset_size_arr, dset_offset_arr, mem_max_nseq, + mem_curr_seq, mem_size_arr, mem_offset_arr, H5D__compact_iovv_memmanage_cb, + &udata)) < 0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed") + } + else { + /* Use the vectorized memory copy routine to do actual work */ + if ((ret_value = H5VM_memcpyvv(io_info->store->compact.buf, dset_max_nseq, dset_curr_seq, + dset_size_arr, dset_offset_arr, io_info->u.wbuf, mem_max_nseq, + mem_curr_seq, mem_size_arr, mem_offset_arr)) < 0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed") + } /* Mark the compact dataset's buffer as dirty */ *io_info->store->compact.dirty = TRUE; diff --git a/src/H5Dcontig.c b/src/H5Dcontig.c index 4dc6f72..840c7ec 100644 --- a/src/H5Dcontig.c +++ b/src/H5Dcontig.c @@ -43,6 +43,7 @@ #include "H5FOprivate.h" /* File objects */ #include "H5Oprivate.h" /* Object headers */ #include "H5Pprivate.h" /* Property lists */ +#include "H5PBprivate.h" /* Page Buffer */ #include "H5VMprivate.h" /* Vector and array functions */ /****************/ @@ -90,9 +91,8 @@ typedef struct H5D_contig_writevv_ud_t { /* Layout operation callbacks */ static herr_t H5D__contig_construct(H5F_t *f, H5D_t *dset); static herr_t H5D__contig_init(H5F_t *f, const H5D_t *dset, hid_t dapl_id); -static herr_t H5D__contig_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info, - hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space, - H5D_chunk_map_t *cm); +static herr_t H5D__contig_io_init(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, + H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t *cm); static ssize_t H5D__contig_readvv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[], size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[]); @@ -103,19 +103,31 @@ static herr_t H5D__contig_flush(H5D_t *dset); /* Helper routines */ static herr_t H5D__contig_write_one(H5D_io_info_t *io_info, hsize_t offset, size_t size); +static htri_t H5D__contig_may_use_select_io(const H5D_io_info_t *io_info, H5D_io_op_type_t op_type); /*********************/ /* Package Variables */ /*********************/ /* Contiguous storage layout I/O ops */ -const H5D_layout_ops_t H5D_LOPS_CONTIG[1] = { - {H5D__contig_construct, H5D__contig_init, H5D__contig_is_space_alloc, H5D__contig_is_data_cached, - H5D__contig_io_init, H5D__contig_read, H5D__contig_write, +const H5D_layout_ops_t H5D_LOPS_CONTIG[1] = {{ + H5D__contig_construct, /* construct */ + H5D__contig_init, /* init */ + H5D__contig_is_space_alloc, /* is_space_alloc */ + H5D__contig_is_data_cached, /* is_data_cached */ + H5D__contig_io_init, /* io_init */ + H5D__contig_read, /* ser_read */ + H5D__contig_write, /* ser_write */ #ifdef H5_HAVE_PARALLEL - H5D__contig_collective_read, H5D__contig_collective_write, -#endif /* H5_HAVE_PARALLEL */ - H5D__contig_readvv, H5D__contig_writevv, H5D__contig_flush, NULL, NULL}}; + H5D__contig_collective_read, /* par_read */ + H5D__contig_collective_write, /* par_write */ +#endif + H5D__contig_readvv, /* readvv */ + H5D__contig_writevv, /* writevv */ + H5D__contig_flush, /* flush */ + NULL, /* io_term */ + NULL /* dest */ +}}; /*******************/ /* Local Variables */ @@ -268,9 +280,16 @@ H5D__contig_fill(const H5D_io_info_t *io_info) if (using_mpi) { /* Write the chunks out from only one process */ /* !! Use the internal "independent" DXPL!! -QAK */ - if (H5_PAR_META_WRITE == mpi_rank) - if (H5D__contig_write_one(&ioinfo, offset, size) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to write fill value to dataset") + if (H5_PAR_META_WRITE == mpi_rank) { + if (H5D__contig_write_one(&ioinfo, offset, size) < 0) { + /* If writing fails, push an error and stop writing, but + * still participate in following MPI_Barrier. + */ + blocks_written = TRUE; + HDONE_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to write fill value to dataset") + break; + } + } /* Indicate that blocks are being written */ blocks_written = TRUE; @@ -549,19 +568,81 @@ H5D__contig_is_data_cached(const H5D_shared_t *shared_dset) *------------------------------------------------------------------------- */ static herr_t -H5D__contig_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t H5_ATTR_UNUSED *type_info, - hsize_t H5_ATTR_UNUSED nelmts, const H5S_t H5_ATTR_UNUSED *file_space, - const H5S_t H5_ATTR_UNUSED *mem_space, H5D_chunk_map_t H5_ATTR_UNUSED *cm) +H5D__contig_io_init(H5D_io_info_t *io_info, const H5D_type_info_t H5_ATTR_UNUSED *type_info, + hsize_t H5_ATTR_UNUSED nelmts, H5S_t H5_ATTR_UNUSED *file_space, + H5S_t H5_ATTR_UNUSED *mem_space, H5D_chunk_map_t H5_ATTR_UNUSED *cm) { - FUNC_ENTER_STATIC_NOERR + htri_t use_selection_io = FALSE; /* Whether to use selection I/O */ + htri_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC io_info->store->contig.dset_addr = io_info->dset->shared->layout.storage.u.contig.addr; io_info->store->contig.dset_size = io_info->dset->shared->layout.storage.u.contig.size; - FUNC_LEAVE_NOAPI(SUCCEED) + /* Check if we're performing selection I/O */ + if ((use_selection_io = H5D__contig_may_use_select_io(io_info, H5D_IO_OP_READ)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't check if selection I/O is possible") + io_info->use_select_io = (hbool_t)use_selection_io; + +done: + FUNC_LEAVE_NOAPI(ret_value) } /* end H5D__contig_io_init() */ /*------------------------------------------------------------------------- + * Function: H5D__contig_may_use_select_io + * + * Purpose: A small internal function to if it may be possible to use + * selection I/O. + * + * Return: TRUE/FALSE/FAIL + * + * Programmer: Neil Fortner + * 3 August 2021 + * + *------------------------------------------------------------------------- + */ +static htri_t +H5D__contig_may_use_select_io(const H5D_io_info_t *io_info, H5D_io_op_type_t op_type) +{ + const H5D_t *dataset = io_info->dset; /* Local pointer to dataset info */ + htri_t ret_value = FAIL; /* Return value */ + + FUNC_ENTER_STATIC + + /* Sanity check */ + HDassert(io_info); + HDassert(dataset); + HDassert(op_type == H5D_IO_OP_READ || op_type == H5D_IO_OP_WRITE); + + /* Don't use selection I/O if it's globally disabled, if there is a type + * conversion, or if it's not a contiguous dataset, or if the sieve buffer + * exists (write) or is dirty (read) */ + if (!H5_use_selection_io_g || io_info->io_ops.single_read != H5D__select_read || + io_info->layout_ops.readvv != H5D__contig_readvv || + (op_type == H5D_IO_OP_READ && io_info->dset->shared->cache.contig.sieve_dirty) || + (op_type == H5D_IO_OP_WRITE && io_info->dset->shared->cache.contig.sieve_buf)) + ret_value = FALSE; + else { + hbool_t page_buf_enabled; + + HDassert(io_info->io_ops.single_write == H5D__select_write); + HDassert(io_info->layout_ops.writevv == H5D__contig_writevv); + + /* Check if the page buffer is enabled */ + if (H5PB_enabled(io_info->f_sh, H5FD_MEM_DRAW, &page_buf_enabled) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't check if page buffer is enabled") + if (page_buf_enabled) + ret_value = FALSE; + else + ret_value = TRUE; + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D__contig_may_use_select_io() */ + +/*------------------------------------------------------------------------- * Function: H5D__contig_read * * Purpose: Read from a contiguous dataset. @@ -574,10 +655,10 @@ H5D__contig_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t H5_ATTR_ *------------------------------------------------------------------------- */ herr_t -H5D__contig_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, - const H5S_t *file_space, const H5S_t *mem_space, H5D_chunk_map_t H5_ATTR_UNUSED *fm) +H5D__contig_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, H5S_t *file_space, + H5S_t *mem_space, H5D_chunk_map_t H5_ATTR_UNUSED *fm) { - herr_t ret_value = SUCCEED; /*return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE @@ -588,8 +669,20 @@ H5D__contig_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize HDassert(mem_space); HDassert(file_space); - /* Read data */ - if ((io_info->io_ops.single_read)(io_info, type_info, nelmts, file_space, mem_space) < 0) + if (io_info->use_select_io) { + size_t dst_type_size = type_info->dst_type_size; + + /* Issue selection I/O call (we can skip the page buffer because we've + * already verified it won't be used, and the metadata accumulator + * because this is raw data) */ + if (H5F_shared_select_read(H5F_SHARED(io_info->dset->oloc.file), H5FD_MEM_DRAW, nelmts > 0 ? 1 : 0, + &mem_space, &file_space, &(io_info->store->contig.dset_addr), + &dst_type_size, &(io_info->u.rbuf)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "contiguous selection read failed") + } /* end if */ + else + /* Read data through legacy (non-selection I/O) pathway */ + if ((io_info->io_ops.single_read)(io_info, type_info, nelmts, file_space, mem_space) < 0) HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "contiguous read failed") done: @@ -609,10 +702,10 @@ done: *------------------------------------------------------------------------- */ herr_t -H5D__contig_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, - const H5S_t *file_space, const H5S_t *mem_space, H5D_chunk_map_t H5_ATTR_UNUSED *fm) +H5D__contig_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, H5S_t *file_space, + H5S_t *mem_space, H5D_chunk_map_t H5_ATTR_UNUSED *fm) { - herr_t ret_value = SUCCEED; /*return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE @@ -623,8 +716,20 @@ H5D__contig_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsiz HDassert(mem_space); HDassert(file_space); - /* Write data */ - if ((io_info->io_ops.single_write)(io_info, type_info, nelmts, file_space, mem_space) < 0) + if (io_info->use_select_io) { + size_t dst_type_size = type_info->dst_type_size; + + /* Issue selection I/O call (we can skip the page buffer because we've + * already verified it won't be used, and the metadata accumulator + * because this is raw data) */ + if (H5F_shared_select_write(H5F_SHARED(io_info->dset->oloc.file), H5FD_MEM_DRAW, nelmts > 0 ? 1 : 0, + &mem_space, &file_space, &(io_info->store->contig.dset_addr), + &dst_type_size, &(io_info->u.wbuf)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "contiguous selection write failed") + } /* end if */ + else + /* Write data through legacy (non-selection I/O) pathway */ + if ((io_info->io_ops.single_write)(io_info, type_info, nelmts, file_space, mem_space) < 0) HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "contiguous write failed") done: diff --git a/src/H5Dearray.c b/src/H5Dearray.c index abce233..cd52b66 100644 --- a/src/H5Dearray.c +++ b/src/H5Dearray.c @@ -417,7 +417,7 @@ H5D__earray_debug(FILE *stream, int indent, int fwidth, hsize_t idx, const void HDassert(elmt); /* Print element */ - HDsprintf(temp_str, "Element #%" PRIuHSIZE ":", idx); + HDsnprintf(temp_str, sizeof(temp_str), "Element #%" PRIuHSIZE ":", idx); HDfprintf(stream, "%*s%-*s %" PRIuHADDR "\n", indent, "", fwidth, temp_str, *(const haddr_t *)elmt); FUNC_LEAVE_NOAPI(SUCCEED) @@ -573,7 +573,7 @@ H5D__earray_filt_debug(FILE *stream, int indent, int fwidth, hsize_t idx, const HDassert(elmt); /* Print element */ - HDsprintf(temp_str, "Element #%" PRIuHSIZE ":", idx); + HDsnprintf(temp_str, sizeof(temp_str), "Element #%" PRIuHSIZE ":", idx); HDfprintf(stream, "%*s%-*s {%" PRIuHADDR ", %u, %0x}\n", indent, "", fwidth, temp_str, elmt->addr, elmt->nbytes, elmt->filter_mask); diff --git a/src/H5Defl.c b/src/H5Defl.c index 85c9dba..b22c6de 100644 --- a/src/H5Defl.c +++ b/src/H5Defl.c @@ -60,9 +60,9 @@ typedef struct H5D_efl_writevv_ud_t { /********************/ /* Layout operation callbacks */ -static herr_t H5D__efl_construct(H5F_t *f, H5D_t *dset); -static herr_t H5D__efl_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, - const H5S_t *file_space, const H5S_t *mem_space, H5D_chunk_map_t *cm); +static herr_t H5D__efl_construct(H5F_t *f, H5D_t *dset); +static herr_t H5D__efl_io_init(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, + H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t *cm); static ssize_t H5D__efl_readvv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[], size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[]); @@ -80,12 +80,24 @@ static herr_t H5D__efl_write(const H5O_efl_t *efl, const H5D_t *dset, haddr_t ad /*********************/ /* External File List (EFL) storage layout I/O ops */ -const H5D_layout_ops_t H5D_LOPS_EFL[1] = {{H5D__efl_construct, NULL, H5D__efl_is_space_alloc, NULL, - H5D__efl_io_init, H5D__contig_read, H5D__contig_write, +const H5D_layout_ops_t H5D_LOPS_EFL[1] = {{ + H5D__efl_construct, /* construct */ + NULL, /* init */ + H5D__efl_is_space_alloc, /* is_space_alloc */ + NULL, /* is_data_cached */ + H5D__efl_io_init, /* io_init */ + H5D__contig_read, /* ser_read */ + H5D__contig_write, /* ser_write */ #ifdef H5_HAVE_PARALLEL - NULL, NULL, -#endif /* H5_HAVE_PARALLEL */ - H5D__efl_readvv, H5D__efl_writevv, NULL, NULL, NULL}}; + NULL, /* par_read */ + NULL, /* par_write */ +#endif + H5D__efl_readvv, /* readvv */ + H5D__efl_writevv, /* writevv */ + NULL, /* flush */ + NULL, /* io_term */ + NULL /* dest */ +}}; /*******************/ /* Local Variables */ @@ -197,9 +209,9 @@ H5D__efl_is_space_alloc(const H5O_storage_t H5_ATTR_UNUSED *storage) *------------------------------------------------------------------------- */ static herr_t -H5D__efl_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t H5_ATTR_UNUSED *type_info, - hsize_t H5_ATTR_UNUSED nelmts, const H5S_t H5_ATTR_UNUSED *file_space, - const H5S_t H5_ATTR_UNUSED *mem_space, H5D_chunk_map_t H5_ATTR_UNUSED *cm) +H5D__efl_io_init(H5D_io_info_t *io_info, const H5D_type_info_t H5_ATTR_UNUSED *type_info, + hsize_t H5_ATTR_UNUSED nelmts, H5S_t H5_ATTR_UNUSED *file_space, + H5S_t H5_ATTR_UNUSED *mem_space, H5D_chunk_map_t H5_ATTR_UNUSED *cm) { FUNC_ENTER_STATIC_NOERR diff --git a/src/H5Dfarray.c b/src/H5Dfarray.c index 0741e8f..ab0f0f8 100644 --- a/src/H5Dfarray.c +++ b/src/H5Dfarray.c @@ -415,7 +415,7 @@ H5D__farray_debug(FILE *stream, int indent, int fwidth, hsize_t idx, const void HDassert(elmt); /* Print element */ - HDsprintf(temp_str, "Element #%" PRIuHSIZE ":", idx); + HDsnprintf(temp_str, sizeof(temp_str), "Element #%" PRIuHSIZE ":", idx); HDfprintf(stream, "%*s%-*s %" PRIuHADDR "\n", indent, "", fwidth, temp_str, *(const haddr_t *)elmt); FUNC_LEAVE_NOAPI(SUCCEED) @@ -675,7 +675,7 @@ H5D__farray_filt_debug(FILE *stream, int indent, int fwidth, hsize_t idx, const HDassert(elmt); /* Print element */ - HDsprintf(temp_str, "Element #%" PRIuHSIZE ":", idx); + HDsnprintf(temp_str, sizeof(temp_str), "Element #%" PRIuHSIZE ":", idx); HDfprintf(stream, "%*s%-*s {%" PRIuHADDR ", %u, %0x}\n", indent, "", fwidth, temp_str, elmt->addr, elmt->nbytes, elmt->filter_mask); diff --git a/src/H5Dfill.c b/src/H5Dfill.c index fe98487..cec7e8b 100644 --- a/src/H5Dfill.c +++ b/src/H5Dfill.c @@ -112,7 +112,7 @@ H5FL_EXTERN(H5S_sel_iter_t); on each element so that each of them has a copy of the VL data. --------------------------------------------------------------------------*/ herr_t -H5D__fill(const void *fill, const H5T_t *fill_type, void *buf, const H5T_t *buf_type, const H5S_t *space) +H5D__fill(const void *fill, const H5T_t *fill_type, void *buf, const H5T_t *buf_type, H5S_t *space) { H5S_sel_iter_t *mem_iter = NULL; /* Memory selection iteration info */ hbool_t mem_iter_init = FALSE; /* Whether the memory selection iterator has been initialized */ diff --git a/src/H5Dint.c b/src/H5Dint.c index 6d3f4a3..cc17265 100644 --- a/src/H5Dint.c +++ b/src/H5Dint.c @@ -139,9 +139,6 @@ static const H5I_class_t H5I_DATASET_CLS[1] = {{ (H5I_free_t)H5D__close_cb /* Callback routine for closing objects of this class */ }}; -/* Flag indicating "top" of interface has been initialized */ -static hbool_t H5D_top_package_initialize_s = FALSE; - /* Prefixes of VDS and external file from the environment variables * HDF5_EXTFILE_PREFIX and HDF5_VDS_PREFIX */ static const char *H5D_prefix_ext_env = NULL; @@ -160,37 +157,10 @@ static const char *H5D_prefix_vds_env = NULL; herr_t H5D_init(void) { - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(FAIL) - /* FUNC_ENTER() does all the work */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5D_init() */ - -/*-------------------------------------------------------------------------- -NAME - H5D__init_package -- Initialize interface-specific information -USAGE - herr_t H5D__init_package() - -RETURNS - Non-negative on success/Negative on failure -DESCRIPTION - Initializes any interface-specific data or routines. -NOTES - Care must be taken when using the H5P functions, since they can cause - a deadlock in the library when the library is attempting to terminate -QAK - ---------------------------------------------------------------------------*/ -herr_t -H5D__init_package(void) -{ H5P_genplist_t *def_dcpl; /* Default Dataset Creation Property list */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_PACKAGE + FUNC_ENTER_NOAPI(FAIL) /* Initialize the ID group for the dataset IDs */ if (H5I_register_type(H5I_DATASET_CLS) < 0) @@ -220,16 +190,13 @@ H5D__init_package(void) if (H5P_get(def_dcpl, H5O_CRT_PIPELINE_NAME, &H5D_def_dset.dcpl_cache.pline) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't retrieve pipeline filter") - /* Mark "top" of interface as initialized, too */ - H5D_top_package_initialize_s = TRUE; - /* Retrieve the prefixes of VDS and external file from the environment variable */ H5D_prefix_vds_env = HDgetenv("HDF5_VDS_PREFIX"); H5D_prefix_ext_env = HDgetenv("HDF5_EXTFILE_PREFIX"); done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5D__init_package() */ +} /* end H5D_init() */ /*------------------------------------------------------------------------- * Function: H5D_top_term_package @@ -248,38 +215,32 @@ H5D_top_term_package(void) FUNC_ENTER_NOAPI_NOINIT_NOERR - if (H5D_top_package_initialize_s) { - if (H5I_nmembers(H5I_DATASET) > 0) { - /* The dataset API uses the "force" flag set to true because it - * is using the "file objects" (H5FO) API functions to track open - * objects in the file. Using the H5FO code means that dataset - * IDs can have reference counts >1, when an existing dataset is - * opened more than once. However, the H5I code does not attempt - * to close objects with reference counts>1 unless the "force" flag - * is set to true. - * - * At some point (probably after the group and datatypes use the - * the H5FO code), the H5FO code might need to be switched around - * to storing pointers to the objects being tracked (H5D_t, H5G_t, - * etc) and reference count those itself instead of relying on the - * reference counting in the H5I layer. Then, the "force" flag can - * be put back to false. - * - * Setting the "force" flag to true for all the interfaces won't - * work because the "file driver" (H5FD) APIs use the H5I reference - * counting to avoid closing a file driver out from underneath an - * open file... - * - * QAK - 5/13/03 - */ - (void)H5I_clear_type(H5I_DATASET, TRUE, FALSE); - n++; /*H5I*/ - } /* end if */ - - /* Mark closed */ - if (0 == n) - H5D_top_package_initialize_s = FALSE; - } /* end if */ + if (H5I_nmembers(H5I_DATASET) > 0) { + /* The dataset API uses the "force" flag set to true because it + * is using the "file objects" (H5FO) API functions to track open + * objects in the file. Using the H5FO code means that dataset + * IDs can have reference counts >1, when an existing dataset is + * opened more than once. However, the H5I code does not attempt + * to close objects with reference counts>1 unless the "force" flag + * is set to true. + * + * At some point (probably after the group and datatypes use the + * the H5FO code), the H5FO code might need to be switched around + * to storing pointers to the objects being tracked (H5D_t, H5G_t, + * etc) and reference count those itself instead of relying on the + * reference counting in the H5I layer. Then, the "force" flag can + * be put back to false. + * + * Setting the "force" flag to true for all the interfaces won't + * work because the "file driver" (H5FD) APIs use the H5I reference + * counting to avoid closing a file driver out from underneath an + * open file... + * + * QAK - 5/13/03 + */ + (void)H5I_clear_type(H5I_DATASET, TRUE, FALSE); + n++; /*H5I*/ + } FUNC_LEAVE_NOAPI(n) } /* end H5D_top_term_package() */ @@ -304,18 +265,11 @@ H5D_term_package(void) FUNC_ENTER_NOAPI_NOINIT_NOERR - if (H5_PKG_INIT_VAR) { - /* Sanity checks */ - HDassert(0 == H5I_nmembers(H5I_DATASET)); - HDassert(FALSE == H5D_top_package_initialize_s); - - /* Destroy the dataset object id group */ - n += (H5I_dec_type_ref(H5I_DATASET) > 0); + /* Sanity checks */ + HDassert(0 == H5I_nmembers(H5I_DATASET)); - /* Mark closed */ - if (0 == n) - H5_PKG_INIT_VAR = FALSE; - } /* end if */ + /* Destroy the dataset object id group */ + n += (H5I_dec_type_ref(H5I_DATASET) > 0); FUNC_LEAVE_NOAPI(n) } /* end H5D_term_package() */ @@ -410,7 +364,7 @@ done: * * Return: * Success: Non-negative - * Failture: Negative + * Failure: Negative *------------------------------------------------------------------------- */ herr_t @@ -424,40 +378,18 @@ H5D__get_space_status(const H5D_t *dset, H5D_space_status_t *allocation) /* Check for chunked layout */ if (dset->shared->layout.type == H5D_CHUNKED) { - hsize_t space_allocated; /* The number of bytes allocated for chunks */ - hssize_t snelmts; /* Temporary holder for number of elements in dataspace */ - hsize_t nelmts; /* Number of elements in dataspace */ - size_t dt_size; /* Size of datatype */ - hsize_t full_size; /* The number of bytes in the dataset when fully populated */ - - /* For chunked layout set the space status by the storage size */ - /* Get the dataset's dataspace */ - HDassert(dset->shared->space); - - /* Get the total number of elements in dataset's dataspace */ - if ((snelmts = H5S_GET_EXTENT_NPOINTS(dset->shared->space)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to retrieve number of elements in dataspace") - nelmts = (hsize_t)snelmts; - - /* Get the size of the dataset's datatype */ - if (0 == (dt_size = H5T_GET_SIZE(dset->shared->type))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to retrieve size of datatype") - - /* Compute the maximum size of the dataset in bytes */ - full_size = nelmts * dt_size; - - /* Check for overflow during multiplication */ - if (nelmts != (full_size / dt_size)) - HGOTO_ERROR(H5E_DATASET, H5E_OVERFLOW, FAIL, "size of dataset's storage overflowed") - - /* Difficult to error check, since the error value is 0 and 0 is a valid value... :-/ */ - if (H5D__get_storage_size(dset, &space_allocated) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get size of dataset's storage") - - /* Decide on how much of the space is allocated */ - if (space_allocated == 0) + hsize_t n_chunks_total = dset->shared->layout.u.chunk.nchunks; + hsize_t n_chunks_alloc = 0; + + if (H5D__get_num_chunks(dset, dset->shared->space, &n_chunks_alloc) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, + "unable to retrieve number of allocated chunks in dataset") + + HDassert(n_chunks_alloc <= n_chunks_total); + + if (n_chunks_alloc == 0) *allocation = H5D_SPACE_STATUS_NOT_ALLOCATED; - else if (space_allocated == full_size) + else if (n_chunks_alloc == n_chunks_total) *allocation = H5D_SPACE_STATUS_ALLOCATED; else *allocation = H5D_SPACE_STATUS_PART_ALLOCATED; @@ -757,7 +689,7 @@ H5D__calculate_minimum_header_size(H5F_t *file, H5D_t *dset, H5O_t *ohdr) H5T_t * type = NULL; H5O_fill_t *fill_prop = NULL; hbool_t use_at_least_v18 = FALSE; - const char continuation[1] = ""; /* requred for work-around */ + const char continuation[1] = ""; /* required for work-around */ size_t get_value = 0; size_t ret_value = 0; @@ -804,7 +736,7 @@ H5D__calculate_minimum_header_size(H5F_t *file, H5D_t *dset, H5O_t *ohdr) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, 0, "can't get size of continuation message") ret_value += get_value; - /* Fill Value (backwards compatability) message size */ + /* Fill Value (backwards compatibility) message size */ if (fill_prop->buf && !use_at_least_v18) { H5O_fill_t old_fill_prop; /* Copy for writing "old" fill value */ @@ -893,7 +825,7 @@ H5D__prepare_minimized_oh(H5F_t *file, H5D_t *dset, H5O_loc_t *oloc) if (ohdr_size == 0) HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "computed header size is invalid") - /* Special allocation of space for compact datsets is handled by the call here. */ + /* Special allocation of space for compact datasets is handled by the call here. */ if (H5O_apply_ohdr(file, oh, dset->shared->dcpl_id, ohdr_size, (size_t)1, oloc) == FAIL) HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "can't apply object header to file") @@ -1347,10 +1279,19 @@ H5D__create(H5F_t *file, hid_t type_id, const H5S_t *space, hid_t dcpl_id, hid_t HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set latest indexing") } /* end if */ - /* Check if this dataset is going into a parallel file and set space allocation time */ + /* Check if the file driver would like to force early space allocation */ if (H5F_HAS_FEATURE(file, H5FD_FEAT_ALLOCATE_EARLY)) new_dset->shared->dcpl_cache.fill.alloc_time = H5D_ALLOC_TIME_EARLY; + /* + * Check if this dataset is going into a parallel file and set space allocation time. + * If the dataset has filters applied to it, writes to the dataset must be collective, + * so we don't need to force early space allocation. Otherwise, we force early space + * allocation to facilitate independent raw data operations. + */ + if (H5F_HAS_FEATURE(file, H5FD_FEAT_HAS_MPI) && (new_dset->shared->dcpl_cache.pline.nused == 0)) + new_dset->shared->dcpl_cache.fill.alloc_time = H5D_ALLOC_TIME_EARLY; + /* Set the dataset's I/O operations */ if (H5D__layout_set_io_ops(new_dset) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to initialize I/O operations") diff --git a/src/H5Dio.c b/src/H5Dio.c index 6bd4666..cb61b71 100644 --- a/src/H5Dio.c +++ b/src/H5Dio.c @@ -82,8 +82,7 @@ H5FL_DEFINE(H5D_chunk_map_t); *------------------------------------------------------------------------- */ herr_t -H5D__read(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, const H5S_t *file_space, - void *buf /*out*/) +H5D__read(H5D_t *dataset, hid_t mem_type_id, H5S_t *mem_space, H5S_t *file_space, void *buf /*out*/) { H5D_chunk_map_t *fm = NULL; /* Chunk file<->memory mapping */ H5D_io_info_t io_info; /* Dataset I/O info */ @@ -166,7 +165,7 @@ H5D__read(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, const H5S_t * 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, + * and if the ranks of the mem and file spaces are different. If they are, * construct a new mem space that is equivalent to the old mem space, and * use that instead. * @@ -295,13 +294,13 @@ done: *------------------------------------------------------------------------- */ herr_t -H5D__write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, const H5S_t *file_space, - const void *buf) +H5D__write(H5D_t *dataset, hid_t mem_type_id, H5S_t *mem_space, H5S_t *file_space, const void *buf) { H5D_chunk_map_t *fm = NULL; /* Chunk file<->memory mapping */ 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 */ + hbool_t should_alloc_space = FALSE; /* Whether or not to initialize dataset's storage */ H5S_t * projected_mem_space = NULL; /* If not NULL, ptr to dataspace containing a */ /* projection of the supplied mem_space to a new */ /* dataspace with rank equal to that of */ @@ -434,8 +433,20 @@ H5D__write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, const H5S_ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set up I/O operation") /* Allocate dataspace and initialize it if it hasn't been. */ - if (nelmts > 0 && dataset->shared->dcpl_cache.efl.nused == 0 && - !(*dataset->shared->layout.ops->is_space_alloc)(&dataset->shared->layout.storage)) { + should_alloc_space = dataset->shared->dcpl_cache.efl.nused == 0 && + !(*dataset->shared->layout.ops->is_space_alloc)(&dataset->shared->layout.storage); + + /* + * If not using an MPI-based VFD, we only need to allocate + * and initialize storage if there's a selection in the + * dataset's dataspace. Otherwise, we always need to participate + * in the storage allocation since this may use collective + * operations and we will hang if we don't participate. + */ + if (!H5F_HAS_FEATURE(dataset->oloc.file, H5FD_FEAT_HAS_MPI)) + should_alloc_space = should_alloc_space && (nelmts > 0); + + if (should_alloc_space) { hssize_t file_nelmts; /* Number of elements in file dataset's dataspace */ hbool_t full_overwrite; /* Whether we are over-writing all the elements */ @@ -565,6 +576,10 @@ H5D__ioinfo_init(H5D_t *dset, const H5D_type_info_t *type_info, H5D_storage_t *s io_info->io_ops.single_write = H5D__scatgath_write; } /* end else */ + /* Start with selection I/O off, layout callback will turn it on if + * appropriate */ + io_info->use_select_io = FALSE; + #ifdef H5_HAVE_PARALLEL /* Determine if the file was opened with an MPI VFD */ io_info->using_mpi_vfd = H5F_HAS_FEATURE(dset->oloc.file, H5FD_FEAT_HAS_MPI); @@ -803,105 +818,47 @@ H5D__ioinfo_adjust(H5D_io_info_t *io_info, const H5D_t *dset, const H5S_t *file_ /* Check if we can use the optimized parallel I/O routines */ if (opt == TRUE) { - /* Override the I/O op pointers to the MPI-specific routines */ - io_info->io_ops.multi_read = dset->shared->layout.ops->par_read; - io_info->io_ops.multi_write = dset->shared->layout.ops->par_write; - io_info->io_ops.single_read = H5D__mpio_select_read; - io_info->io_ops.single_write = H5D__mpio_select_write; - } /* end if */ + /* Override the I/O op pointers to the MPI-specific routines, unless + * selection I/O is to be used - in this case the file driver will + * handle collective I/O */ + /* Check for selection/vector support in file driver? -NAF */ + if (!io_info->use_select_io) { + io_info->io_ops.multi_read = dset->shared->layout.ops->par_read; + io_info->io_ops.multi_write = dset->shared->layout.ops->par_write; + io_info->io_ops.single_read = H5D__mpio_select_read; + io_info->io_ops.single_write = H5D__mpio_select_write; + } /* end if */ + } /* end if */ else { - int comm_size = 0; - - /* Retrieve size of MPI communicator used for file */ - if ((comm_size = H5F_shared_mpi_get_size(io_info->f_sh)) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get MPI communicator size") - /* Check if there are any filters in the pipeline. If there are, * we cannot break to independent I/O if this is a write operation * with multiple ranks involved; otherwise, there will be metadata * inconsistencies in the file. */ - if (comm_size > 1 && io_info->op_type == H5D_IO_OP_WRITE && - io_info->dset->shared->dcpl_cache.pline.nused > 0) { - H5D_mpio_no_collective_cause_t cause; - uint32_t local_no_collective_cause; - uint32_t global_no_collective_cause; - hbool_t local_error_message_previously_written = FALSE; - hbool_t global_error_message_previously_written = FALSE; - size_t idx; - size_t cause_strings_len; - char local_no_collective_cause_string[512] = ""; - char global_no_collective_cause_string[512] = ""; - const char * cause_strings[] = { - "independent I/O was requested", - "datatype conversions were required", - "data transforms needed to be applied", - "optimized MPI types flag wasn't set", - "one of the dataspaces was neither simple nor scalar", - "dataset was not contiguous or chunked", - "parallel writes to filtered datasets are disabled", - "an error occurred while checking if collective I/O was possible"}; - - cause_strings_len = sizeof(cause_strings) / sizeof(cause_strings[0]); - - if (H5CX_get_mpio_local_no_coll_cause(&local_no_collective_cause) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, - "unable to get local no collective cause value") - if (H5CX_get_mpio_global_no_coll_cause(&global_no_collective_cause) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, - "unable to get global no collective cause value") - - /* Append each of the "reason for breaking collective I/O" error messages to the - * local and global no collective cause strings */ - for (cause = 1, idx = 0; - (cause < H5D_MPIO_NO_COLLECTIVE_MAX_CAUSE) && (idx < cause_strings_len); - cause <<= 1, idx++) { - if (cause & local_no_collective_cause) { - size_t local_buffer_space = sizeof(local_no_collective_cause_string) - - HDstrlen(local_no_collective_cause_string) - 1; - - /* Check if there were any previous error messages included. If so, prepend a - * semicolon to separate the messages. - */ - if (local_buffer_space && local_error_message_previously_written) { - HDstrncat(local_no_collective_cause_string, "; ", local_buffer_space); - local_buffer_space -= MIN(local_buffer_space, 2); - } - - if (local_buffer_space) - HDstrncat(local_no_collective_cause_string, cause_strings[idx], - local_buffer_space); - - local_error_message_previously_written = TRUE; - } /* end if */ - - if (cause & global_no_collective_cause) { - size_t global_buffer_space = sizeof(global_no_collective_cause_string) - - HDstrlen(global_no_collective_cause_string) - 1; - - /* Check if there were any previous error messages included. If so, prepend a - * semicolon to separate the messages. - */ - if (global_buffer_space && global_error_message_previously_written) { - HDstrncat(global_no_collective_cause_string, "; ", global_buffer_space); - global_buffer_space -= MIN(global_buffer_space, 2); - } - - if (global_buffer_space) - HDstrncat(global_no_collective_cause_string, cause_strings[idx], - global_buffer_space); - - global_error_message_previously_written = TRUE; - } /* end if */ - } /* end for */ - - HGOTO_ERROR(H5E_IO, H5E_NO_INDEPENDENT, FAIL, - "Can't perform independent write with filters in pipeline.\n" - " The following caused a break from collective I/O:\n" - " Local causes: %s\n" - " Global causes: %s", - local_no_collective_cause_string, global_no_collective_cause_string); - } /* end if */ + if (io_info->op_type == H5D_IO_OP_WRITE && io_info->dset->shared->dcpl_cache.pline.nused > 0) { + int comm_size = 0; + + /* Retrieve size of MPI communicator used for file */ + if ((comm_size = H5F_shared_mpi_get_size(io_info->f_sh)) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get MPI communicator size") + + if (comm_size > 1) { + char local_no_coll_cause_string[512]; + char global_no_coll_cause_string[512]; + + if (H5D__mpio_get_no_coll_cause_strings(local_no_coll_cause_string, 512, + global_no_coll_cause_string, 512) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, + "can't get reasons for breaking collective I/O") + + HGOTO_ERROR(H5E_IO, H5E_NO_INDEPENDENT, FAIL, + "Can't perform independent write with filters in pipeline.\n" + " The following caused a break from collective I/O:\n" + " Local causes: %s\n" + " Global causes: %s", + local_no_coll_cause_string, global_no_coll_cause_string); + } + } /* If we won't be doing collective I/O, but the user asked for * collective I/O, change the request to use independent I/O diff --git a/src/H5Dlayout.c b/src/H5Dlayout.c index 6c4fc12..6fdec05 100644 --- a/src/H5Dlayout.c +++ b/src/H5Dlayout.c @@ -213,7 +213,7 @@ H5D__layout_meta_size(const H5F_t *f, const H5O_layout_t *layout, hbool_t includ ret_value++; /* Dimension sizes */ - ret_value += layout->u.chunk.ndims * layout->u.chunk.enc_bytes_per_dim; + ret_value += layout->u.chunk.ndims * (size_t)layout->u.chunk.enc_bytes_per_dim; /* Type of chunk index */ ret_value++; diff --git a/src/H5Dmpio.c b/src/H5Dmpio.c index 448e92d..2cde4d3 100644 --- a/src/H5Dmpio.c +++ b/src/H5Dmpio.c @@ -36,6 +36,7 @@ #include "H5Eprivate.h" /* Error handling */ #include "H5Fprivate.h" /* File access */ #include "H5FDprivate.h" /* File drivers */ +#include "H5FLprivate.h" /* Free Lists */ #include "H5Iprivate.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ #include "H5Oprivate.h" /* Object headers */ @@ -43,6 +44,15 @@ #include "H5Sprivate.h" /* Dataspaces */ #include "H5VMprivate.h" /* Vector */ +/* uthash is an external, header-only hash table implementation. + * + * We include the file directly in src/ and #define a few functions + * to use our internal memory calls. + */ +#define uthash_malloc(sz) H5MM_malloc(sz) +#define uthash_free(ptr, sz) H5MM_free(ptr) /* Ignoring sz is intentional */ +#include "uthash.h" + #ifdef H5_HAVE_PARALLEL /****************/ @@ -81,9 +91,54 @@ /* Macros to represent the regularity of the selection for multiple chunk IO case. */ #define H5D_CHUNK_SELECT_REG 1 +/* + * Threshold value for redistributing shared filtered chunks + * on all MPI ranks, or just MPI rank 0 + */ +#define H5D_CHUNK_REDISTRIBUTE_THRES ((size_t)((25 * H5_MB) / sizeof(H5D_chunk_redistribute_info_t))) + +/* + * Initial allocation size for the arrays that hold + * buffers for chunk modification data that is sent + * to other ranks and the MPI_Request objects for + * those send operations + */ +#define H5D_CHUNK_NUM_SEND_MSGS_INIT 64 + +/* + * Define a tag value for the MPI messages sent/received for + * chunk modification data + */ +#define H5D_CHUNK_MOD_DATA_TAG 64 + +/* + * Macro to initialize a H5D_chk_idx_info_t + * structure, given a pointer to a H5D_io_info_t + * structure + */ +#define H5D_MPIO_INIT_CHUNK_IDX_INFO(index_info, io_info_ptr) \ + do { \ + index_info.f = (io_info_ptr)->dset->oloc.file; \ + index_info.pline = &((io_info_ptr)->dset->shared->dcpl_cache.pline); \ + index_info.layout = &((io_info_ptr)->dset->shared->layout.u.chunk); \ + index_info.storage = &((io_info_ptr)->dset->shared->layout.storage.u.chunk); \ + } while (0) + +/* + * Macro to initialize a H5D_chunk_ud_t structure + * given a pointer to a H5D_chk_idx_info_t structure + */ +#define H5D_MPIO_INIT_CHUNK_UD_INFO(chunk_ud, index_info_ptr) \ + do { \ + HDmemset(&chunk_ud, 0, sizeof(H5D_chunk_ud_t)); \ + chunk_ud.common.layout = (index_info_ptr)->layout; \ + chunk_ud.common.storage = (index_info_ptr)->storage; \ + } while (0) + /******************/ /* Local Typedefs */ /******************/ + /* Combine chunk address and chunk info into a struct for better performance. */ typedef struct H5D_chunk_addr_info_t { haddr_t chunk_addr; @@ -100,115 +155,137 @@ typedef enum H5D_mpio_no_rank0_bcast_cause_t { } H5D_mpio_no_rank0_bcast_cause_t; /* + * Information necessary for re-allocating file space for a chunk + * during a parallel write of a chunked dataset with filters + * applied. + */ +typedef struct H5D_chunk_alloc_info_t { + H5F_block_t chunk_current; + H5F_block_t chunk_new; + hsize_t chunk_idx; +} H5D_chunk_alloc_info_t; + +/* + * Information for a chunk pertaining to the dataset's chunk + * index entry for the chunk + */ +typedef struct H5D_chunk_index_info_t { + hsize_t chunk_idx; + unsigned filter_mask; + hbool_t need_insert; +} H5D_chunk_index_info_t; + +/* * Information about a single chunk when performing collective filtered I/O. All * of the fields of one of these structs are initialized at the start of collective - * filtered I/O in the function H5D__construct_filtered_io_info_list(). - * - * This struct's fields are as follows: - * - * index - The "Index" of the chunk in the dataset. The index of a chunk is used during - * the collective re-insertion of chunks into the chunk index after the collective - * I/O has been performed. + * filtered I/O in the function H5D__mpio_collective_filtered_chunk_io_setup(). This + * struct's fields are as follows: * - * scaled - The scaled coordinates of the chunk in the dataset's file dataspace. The - * coordinates are used in both the collective re-allocation of space in the file - * and the collective re-insertion of chunks into the chunk index after the collective - * I/O has been performed. + * index_info - A structure containing the information needed when collectively + * re-inserting the chunk into the dataset's chunk index. The structure + * is distributed to all ranks during the re-insertion operation. Its fields + * are as follows: * - * full_overwrite - A flag which determines whether or not a chunk needs to be read from the - * file when being updated. If a chunk is being fully overwritten (the entire - * extent is selected in its file dataspace), then it is not necessary to - * read the chunk from the file. However, if the chunk is not being fully - * overwritten, it has to be read from the file in order to update the chunk - * without trashing the parts of the chunk that are not selected. + * chunk_idx - The index of the chunk in the dataset's chunk index. * - * num_writers - The total number of processors writing to this chunk. This field is used - * when the new owner of a chunk is receiving messages, which contain selections in - * the chunk and data to update the chunk with, from other processors which have this - * chunk selected in the I/O operation. The new owner must know how many processors it - * should expect messages from so that it can post an equal number of receive calls. + * filter_mask - A bit-mask that indicates which filters are to be applied to the + * chunk. Each filter in a chunk's filter pipeline has a bit position + * that can be masked to disable that particular filter for the chunk. + * This filter mask is saved alongside the chunk in the file. * - * io_size - The total size of I/O to this chunk. This field is an accumulation of the size of - * I/O to the chunk from each processor which has the chunk selected and is used to - * determine the value for the previous full_overwrite flag. + * need_insert - A flag which determines whether or not a chunk needs to be re-inserted into + * the chunk index after the write operation. * - * buf - A pointer which serves the dual purpose of holding either the chunk data which is to be - * written to the file or the chunk data which has been read from the file. + * chunk_info - A pointer to the chunk's H5D_chunk_info_t structure, which contains useful + * information like the dataspaces containing the selection in the chunk. * - * chunk_states - In the case of dataset writes only, this struct is used to track a chunk's size and - * address in the file before and after the filtering operation has occurred. + * chunk_current - The address in the file and size of this chunk before the filtering + * operation. When reading a chunk from the file, this field is used to + * read the correct amount of bytes. It is also used when redistributing + * shared chunks among MPI ranks and as a parameter to the chunk file + * space reallocation function. * - * Its fields are as follows: + * chunk_new - The address in the file and size of this chunk after the filtering + * operation. This field is relevant when collectively re-allocating space + * in the file for all of the chunks written to in the I/O operation, as + * their sizes may have changed after their data has been filtered. * - * chunk_current - The address in the file and size of this chunk before the filtering - * operation. When reading a chunk from the file, this field is used to - * read the correct amount of bytes. It is also used when redistributing - * shared chunks among processors and as a parameter to the chunk file - * space reallocation function. + * need_read - A flag which determines whether or not a chunk needs to be read from the + * file. During writes, if a chunk is being fully overwritten (the entire extent + * is selected in its file dataspace), then it is not necessary to read the chunk + * from the file. However, if the chunk is not being fully overwritten, it has to + * be read from the file in order to update the chunk without trashing the parts + * of the chunk that are not selected. During reads, this field should generally + * be true, but may be false if the chunk isn't allocated, for example. * - * new_chunk - The address in the file and size of this chunk after the filtering - * operation. This field is relevant when collectively re-allocating space - * in the file for all of the chunks written to in the I/O operation, as - * their sizes may have changed after their data has been filtered. + * skip_filter_pline - A flag which determines whether to skip calls to the filter pipeline + * for this chunk. This flag is mostly useful for correct handling of + * partial edge chunks when the "don't filter partial edge chunks" flag + * is set on the dataset's DCPL. * - * owners - In the case of dataset writes only, this struct is used to manage which single processor - * will ultimately write data out to the chunk. It allows the other processors to act according - * to the decision and send their selection in the chunk, as well as the data they wish - * to update the chunk with, to the processor which is writing to the chunk. + * io_size - The total size of I/O to this chunk. This field is an accumulation of the size of + * I/O to the chunk from each MPI rank which has the chunk selected and is used to + * determine the value for the previous `full_overwrite` flag. * - * Its fields are as follows: + * chunk_buf_size - The size in bytes of the data buffer allocated for the chunk * - * original_owner - The processor which originally had this chunk selected at the beginning of - * the collective filtered I/O operation. This field is currently used when - * redistributing shared chunks among processors. + * orig_owner - The MPI rank which originally had this chunk selected at the beginning of + * the collective filtered I/O operation. This field is currently used when + * redistributing shared chunks among MPI ranks. * - * new_owner - The processor which has been selected to perform the write to this chunk. + * new_owner - The MPI rank which has been selected to perform the modifications to this chunk. * - * async_info - In the case of dataset writes only, this struct is used by the owning processor of the - * chunk in order to manage the MPI send and receive calls made between it and all of - * the other processors which have this chunk selected in the I/O operation. + * num_writers - The total number of MPI ranks writing to this chunk. This field is used when + * the new owner of a chunk is receiving messages from other MPI ranks that + * contain their selections in the chunk and the data to update the chunk with. + * The new owner must know how many MPI ranks it should expect messages from so + * that it can post an equal number of receive calls. * - * Its fields are as follows: + * buf - A pointer which serves the dual purpose of holding either the chunk data which is to be + * written to the file or the chunk data which has been read from the file. * - * receive_requests_array - An array containing one MPI_Request for each of the - * asynchronous MPI receive calls the owning processor of this - * chunk makes to another processor in order to receive that - * processor's chunk modification data and selection in the chunk. + * hh - A handle for hash tables provided by the uthash.h header * - * receive_buffer_array - An array of buffers into which the owning processor of this chunk - * will store chunk modification data and the selection in the chunk - * received from another processor. - * - * num_receive_requests - The number of entries in the receive_request_array and - * receive_buffer_array fields. */ typedef struct H5D_filtered_collective_io_info_t { - hsize_t index; - hsize_t scaled[H5O_LAYOUT_NDIMS]; - hbool_t full_overwrite; - size_t num_writers; - size_t io_size; - void * buf; - - struct { - H5F_block_t chunk_current; - H5F_block_t new_chunk; - } chunk_states; - - struct { - int original_owner; - int new_owner; - } owners; - - struct { - MPI_Request * receive_requests_array; - unsigned char **receive_buffer_array; - int num_receive_requests; - } async_info; + H5D_chunk_index_info_t index_info; + + H5D_chunk_info_t *chunk_info; + H5F_block_t chunk_current; + H5F_block_t chunk_new; + hbool_t need_read; + hbool_t skip_filter_pline; + size_t io_size; + size_t chunk_buf_size; + int orig_owner; + int new_owner; + int num_writers; + void * buf; + + UT_hash_handle hh; } H5D_filtered_collective_io_info_t; -/* Function pointer typedef for sort function */ -typedef int (*H5D_mpio_sort_func_cb_t)(const void *, const void *); +/* + * Information necessary for redistributing shared chunks during + * a parallel write of a chunked dataset with filters applied. + */ +typedef struct H5D_chunk_redistribute_info_t { + H5F_block_t chunk_block; + hsize_t chunk_idx; + int orig_owner; + int new_owner; + int num_writers; +} H5D_chunk_redistribute_info_t; + +/* + * Information used when re-inserting a chunk into a dataset's + * chunk index during a parallel write of a chunked dataset with + * filters applied. + */ +typedef struct H5D_chunk_insert_info_t { + H5F_block_t chunk_block; + H5D_chunk_index_info_t index_info; +} H5D_chunk_insert_info_t; /********************/ /* Local Prototypes */ @@ -216,53 +293,98 @@ typedef int (*H5D_mpio_sort_func_cb_t)(const void *, const void *); static herr_t H5D__chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, H5D_chunk_map_t *fm); static herr_t H5D__multi_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, - H5D_chunk_map_t *fm); + H5D_chunk_map_t *fm, int mpi_rank, int mpi_size); static herr_t H5D__multi_chunk_filtered_collective_io(H5D_io_info_t * io_info, - const H5D_type_info_t *type_info, H5D_chunk_map_t *fm); + const H5D_type_info_t *type_info, H5D_chunk_map_t *fm, + int mpi_rank, int mpi_size); static herr_t H5D__link_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, - H5D_chunk_map_t *fm, int sum_chunk); + H5D_chunk_map_t *fm, int sum_chunk, int mpi_rank, int mpi_size); static herr_t H5D__link_chunk_filtered_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, - H5D_chunk_map_t *fm); + H5D_chunk_map_t *fm, int mpi_rank, int mpi_size); 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, hsize_t nelmts, MPI_Datatype mpi_file_type, MPI_Datatype mpi_buf_type); static herr_t H5D__sort_chunk(H5D_io_info_t *io_info, const H5D_chunk_map_t *fm, - H5D_chunk_addr_info_t chunk_addr_info_array[], int many_chunk_opt); + H5D_chunk_addr_info_t chunk_addr_info_array[], int many_chunk_opt, int mpi_rank, + int mpi_size); static herr_t H5D__obtain_mpio_mode(H5D_io_info_t *io_info, H5D_chunk_map_t *fm, uint8_t assign_io_mode[], - haddr_t chunk_addr[]); + haddr_t chunk_addr[], int mpi_rank, int mpi_size); static herr_t H5D__mpio_get_sum_chunk(const H5D_io_info_t *io_info, const H5D_chunk_map_t *fm, int *sum_chunkf); -static herr_t H5D__construct_filtered_io_info_list(const H5D_io_info_t * io_info, - const H5D_type_info_t * type_info, - const H5D_chunk_map_t * fm, - H5D_filtered_collective_io_info_t **chunk_list, - size_t * num_entries); -#if MPI_VERSION >= 3 -static herr_t H5D__chunk_redistribute_shared_chunks(const H5D_io_info_t * io_info, - const H5D_type_info_t * type_info, - const H5D_chunk_map_t * fm, - H5D_filtered_collective_io_info_t *local_chunk_array, - size_t *local_chunk_array_num_entries); -#endif -static herr_t H5D__mpio_array_gatherv(void *local_array, size_t local_array_num_entries, - size_t array_entry_size, void **gathered_array, - size_t *gathered_array_num_entries, hbool_t allgather, int root, - MPI_Comm comm, int (*sort_func)(const void *, const void *)); -static herr_t H5D__mpio_filtered_collective_write_type(H5D_filtered_collective_io_info_t *chunk_list, - size_t num_entries, MPI_Datatype *new_mem_type, - hbool_t *mem_type_derived, MPI_Datatype *new_file_type, - hbool_t *file_type_derived); -static herr_t H5D__filtered_collective_chunk_entry_io(H5D_filtered_collective_io_info_t *chunk_entry, - const H5D_io_info_t * io_info, - const H5D_type_info_t * type_info, - const H5D_chunk_map_t * fm); +static herr_t H5D__mpio_collective_filtered_chunk_io_setup(const H5D_io_info_t * io_info, + const H5D_type_info_t * type_info, + const H5D_chunk_map_t * fm, + H5D_filtered_collective_io_info_t **chunk_list, + size_t *num_entries, int mpi_rank); +static herr_t H5D__mpio_redistribute_shared_chunks(H5D_filtered_collective_io_info_t *chunk_list, + size_t chunk_list_num_entries, + const H5D_io_info_t *io_info, const H5D_chunk_map_t *fm, + int mpi_rank, int mpi_size, + size_t **rank_chunks_assigned_map); +static herr_t H5D__mpio_redistribute_shared_chunks_int(H5D_filtered_collective_io_info_t *chunk_list, + size_t * num_chunks_assigned_map, + hbool_t all_ranks_involved, + const H5D_io_info_t * io_info, + const H5D_chunk_map_t *fm, int mpi_rank, int mpi_size); +static herr_t H5D__mpio_share_chunk_modification_data(H5D_filtered_collective_io_info_t *chunk_list, + size_t *chunk_list_num_entries, H5D_io_info_t *io_info, + const H5D_type_info_t *type_info, int mpi_rank, + int mpi_size, + H5D_filtered_collective_io_info_t **chunk_hash_table, + unsigned char *** chunk_msg_bufs, + int * chunk_msg_bufs_len); +static herr_t H5D__mpio_collective_filtered_chunk_common_io(H5D_filtered_collective_io_info_t *chunk_list, + size_t chunk_list_num_entries, + const H5D_io_info_t * io_info, + const H5D_type_info_t *type_info, int mpi_size); +static herr_t H5D__mpio_collective_filtered_chunk_read(H5D_filtered_collective_io_info_t *chunk_list, + size_t chunk_list_num_entries, + const H5D_io_info_t * io_info, + const H5D_type_info_t *type_info, int mpi_rank, + int mpi_size); +static herr_t H5D__mpio_collective_filtered_chunk_update(H5D_filtered_collective_io_info_t *chunk_list, + size_t chunk_list_num_entries, + H5D_filtered_collective_io_info_t *chunk_hash_table, + unsigned char ** chunk_msg_bufs, + int chunk_msg_bufs_len, const H5D_io_info_t *io_info, + const H5D_type_info_t *type_info, int mpi_rank, + int mpi_size); +static herr_t H5D__mpio_collective_filtered_chunk_reallocate(H5D_filtered_collective_io_info_t *chunk_list, + size_t chunk_list_num_entries, + size_t * num_chunks_assigned_map, + H5D_io_info_t * io_info, + H5D_chk_idx_info_t *idx_info, int mpi_rank, + int mpi_size); +static herr_t H5D__mpio_collective_filtered_chunk_reinsert(H5D_filtered_collective_io_info_t *chunk_list, + size_t chunk_list_num_entries, + size_t * num_chunks_assigned_map, + H5D_io_info_t * io_info, + H5D_chk_idx_info_t *idx_info, int mpi_rank, + int mpi_size); +static herr_t H5D__mpio_get_chunk_redistribute_info_types(MPI_Datatype *contig_type, + hbool_t * contig_type_derived, + MPI_Datatype *resized_type, + hbool_t * resized_type_derived); +static herr_t H5D__mpio_get_chunk_alloc_info_types(MPI_Datatype *contig_type, hbool_t *contig_type_derived, + MPI_Datatype *resized_type, hbool_t *resized_type_derived); +static herr_t H5D__mpio_get_chunk_insert_info_types(MPI_Datatype *contig_type, hbool_t *contig_type_derived, + MPI_Datatype *resized_type, + hbool_t * resized_type_derived); +static herr_t H5D__mpio_collective_filtered_io_type(H5D_filtered_collective_io_info_t *chunk_list, + size_t num_entries, H5D_io_op_type_t op_type, + MPI_Datatype *new_mem_type, hbool_t *mem_type_derived, + MPI_Datatype *new_file_type, hbool_t *file_type_derived); static int H5D__cmp_chunk_addr(const void *chunk_addr_info1, const void *chunk_addr_info2); static int H5D__cmp_filtered_collective_io_info_entry(const void *filtered_collective_io_info_entry1, const void *filtered_collective_io_info_entry2); -#if MPI_VERSION >= 3 -static int H5D__cmp_filtered_collective_io_info_entry_owner(const void *filtered_collective_io_info_entry1, - const void *filtered_collective_io_info_entry2); +static int H5D__cmp_chunk_redistribute_info(const void *entry1, const void *entry2); +static int H5D__cmp_chunk_redistribute_info_orig_owner(const void *entry1, const void *entry2); + +#ifdef H5Dmpio_DEBUG +static herr_t H5D__mpio_debug_init(void); +static herr_t H5D__mpio_dump_collective_filtered_chunk_list(H5D_filtered_collective_io_info_t *chunk_list, + size_t chunk_list_num_entries, int mpi_rank); #endif /*********************/ @@ -273,6 +395,188 @@ static int H5D__cmp_filtered_collective_io_info_entry_owner(const void *filtered /* Local Variables */ /*******************/ +/* Declare extern free list to manage the H5S_sel_iter_t struct */ +H5FL_EXTERN(H5S_sel_iter_t); + +#ifdef H5Dmpio_DEBUG + +/* Flags to control debug actions in this file. + * (Meant to be indexed by characters) + * + * These flags can be set with either (or both) the environment variable + * "H5D_mpio_Debug" set to a string containing one or more characters + * (flags) or by setting them as a string value for the + * "H5D_mpio_debug_key" MPI Info key. + * + * Supported characters in 'H5D_mpio_Debug' string: + * 't' trace function entry and exit + * 'f' log to file rather than debugging stream + * 'm' show (rough) memory usage statistics + * 'c' show critical timing information + * + * To only show output from a particular MPI rank, specify its rank + * number as a character, e.g.: + * + * '0' only show output from rank 0 + * + * To only show output from a particular range (up to 8 ranks supported + * between 0-9) of MPI ranks, specify the start and end ranks separated + * by a hyphen, e.g.: + * + * '0-7' only show output from ranks 0 through 7 + * + */ +static int H5D_mpio_debug_flags_s[256]; +static int H5D_mpio_debug_rank_s[8] = {-1, -1, -1, -1, -1, -1, -1, -1}; +static hbool_t H5D_mpio_debug_inited = FALSE; +static const char *const trace_in_pre = "-> "; +static const char *const trace_out_pre = "<- "; +static int debug_indent = 0; +static FILE * debug_stream = NULL; + +/* Determine if this rank should output debugging info */ +#define H5D_MPIO_DEBUG_THIS_RANK(rank) \ + (H5D_mpio_debug_rank_s[0] < 0 || rank == H5D_mpio_debug_rank_s[0] || rank == H5D_mpio_debug_rank_s[1] || \ + rank == H5D_mpio_debug_rank_s[2] || rank == H5D_mpio_debug_rank_s[3] || \ + rank == H5D_mpio_debug_rank_s[4] || rank == H5D_mpio_debug_rank_s[5] || \ + rank == H5D_mpio_debug_rank_s[6] || rank == H5D_mpio_debug_rank_s[7]) + +/* Print some debugging string */ +#define H5D_MPIO_DEBUG(rank, string) \ + do { \ + if (debug_stream && H5D_MPIO_DEBUG_THIS_RANK(rank)) { \ + HDfprintf(debug_stream, "%*s(Rank %d) " string "\n", debug_indent, "", rank); \ + HDfflush(debug_stream); \ + } \ + } while (0) + +/* Print some debugging string with printf-style arguments */ +#define H5D_MPIO_DEBUG_VA(rank, string, ...) \ + do { \ + if (debug_stream && H5D_MPIO_DEBUG_THIS_RANK(rank)) { \ + HDfprintf(debug_stream, "%*s(Rank %d) " string "\n", debug_indent, "", rank, __VA_ARGS__); \ + HDfflush(debug_stream); \ + } \ + } while (0) + +#define H5D_MPIO_TRACE_ENTER(rank) \ + do { \ + hbool_t trace_flag = H5D_mpio_debug_flags_s[(int)'t']; \ + \ + if (trace_flag) { \ + H5D_MPIO_DEBUG_VA(rank, "%s%s", trace_in_pre, __func__); \ + debug_indent += (int)HDstrlen(trace_in_pre); \ + } \ + } while (0) + +#define H5D_MPIO_TRACE_EXIT(rank) \ + do { \ + hbool_t trace_flag = H5D_mpio_debug_flags_s[(int)'t']; \ + \ + if (trace_flag) { \ + debug_indent -= (int)HDstrlen(trace_out_pre); \ + H5D_MPIO_DEBUG_VA(rank, "%s%s", trace_out_pre, __func__); \ + } \ + } while (0) + +#define H5D_MPIO_TIME_START(rank, op_name) \ + { \ + hbool_t time_flag = H5D_mpio_debug_flags_s[(int)'c']; \ + double start_time = 0.0, end_time = 0.0; \ + const char *const op = op_name; \ + \ + if (time_flag) { \ + start_time = MPI_Wtime(); \ + } + +#define H5D_MPIO_TIME_STOP(rank) \ + if (time_flag) { \ + end_time = MPI_Wtime(); \ + H5D_MPIO_DEBUG_VA(rank, "'%s' took %f seconds", op, (end_time - start_time)); \ + } \ + } + +/*--------------------------------------------------------------------------- + * Function: H5D__mpio_parse_debug_str + * + * Purpose: Parse a string for H5Dmpio-related debugging flags + * + * Returns: N/A + * + *--------------------------------------------------------------------------- + */ +static void +H5D__mpio_parse_debug_str(const char *s) +{ + FUNC_ENTER_STATIC_NOERR + + HDassert(s); + + while (*s) { + int c = (int)(*s); + + if (c >= (int)'0' && c <= (int)'9') { + hbool_t range = FALSE; + + if (*(s + 1) && *(s + 2)) + range = (int)*(s + 1) == '-' && (int)*(s + 2) >= (int)'0' && (int)*(s + 2) <= (int)'9'; + + if (range) { + int start_rank = c - (int)'0'; + int end_rank = (int)*(s + 2) - '0'; + int num_ranks = end_rank - start_rank + 1; + int i; + + if (num_ranks > 8) { + end_rank = start_rank + 7; + num_ranks = 8; + } + + for (i = 0; i < num_ranks; i++) + H5D_mpio_debug_rank_s[i] = start_rank++; + + s += 3; + } + else + H5D_mpio_debug_rank_s[0] = c - (int)'0'; + } + else + H5D_mpio_debug_flags_s[c]++; + + s++; + } + + FUNC_LEAVE_NOAPI_VOID +} + +static herr_t +H5D__mpio_debug_init(void) +{ + const char *debug_str; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC_NOERR + + HDassert(!H5D_mpio_debug_inited); + + /* Clear the debug flag buffer */ + HDmemset(H5D_mpio_debug_flags_s, 0, sizeof(H5D_mpio_debug_flags_s)); + + /* Retrieve and parse the H5Dmpio debug string */ + debug_str = HDgetenv("H5D_mpio_Debug"); + if (debug_str) + H5D__mpio_parse_debug_str(debug_str); + + if (H5DEBUG(D)) + debug_stream = H5DEBUG(D); + + H5D_mpio_debug_inited = TRUE; + + FUNC_LEAVE_NOAPI(ret_value) +} + +#endif + /*------------------------------------------------------------------------- * Function: H5D__mpio_opt_possible * @@ -347,14 +651,9 @@ H5D__mpio_opt_possible(const H5D_io_info_t *io_info, const H5S_t *file_space, co * use collective IO will defer until each chunk IO is reached. */ -#if MPI_VERSION < 3 - /* - * Don't allow parallel writes to filtered datasets if the MPI version - * is less than 3. The functions needed (MPI_Mprobe and MPI_Imrecv) will - * not be available. - */ - if (io_info->op_type == H5D_IO_OP_WRITE && io_info->dset->shared->layout.type == H5D_CHUNKED && - io_info->dset->shared->dcpl_cache.pline.nused > 0) +#ifndef H5_HAVE_PARALLEL_FILTERED_WRITES + /* Don't allow writes to filtered datasets if the functionality is disabled */ + if (io_info->op_type == H5D_IO_OP_WRITE && io_info->dset->shared->dcpl_cache.pline.nused > 0) local_cause[0] |= H5D_MPIO_PARALLEL_FILTERED_WRITES_DISABLED; #endif @@ -365,7 +664,7 @@ H5D__mpio_opt_possible(const H5D_io_info_t *io_info, const H5S_t *file_space, co /* Check to see if the process is reading the entire dataset */ if (H5S_GET_SELECT_TYPE(file_space) != H5S_SEL_ALL) local_cause[1] |= H5D_MPIO_RANK0_NOT_H5S_ALL; - /* Only perform this optimization for contigous datasets, currently */ + /* Only perform this optimization for contiguous datasets, currently */ else if (H5D_CONTIGUOUS != io_info->dset->shared->layout.type) /* Flag to do a MPI_Bcast of the data from one proc instead of * having all the processes involved in the collective I/O. @@ -437,6 +736,150 @@ done: } /* H5D__mpio_opt_possible() */ /*------------------------------------------------------------------------- + * Function: H5D__mpio_get_no_coll_cause_strings + * + * Purpose: When collective I/O is broken internally, it can be useful + * for users to see a representative string for the reason(s) + * why it was broken. This routine inspects the current + * "cause" flags from the API context and prints strings into + * the caller's buffers for the local and global reasons that + * collective I/O was broken. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5D__mpio_get_no_coll_cause_strings(char *local_cause, size_t local_cause_len, char *global_cause, + size_t global_cause_len) +{ + uint32_t local_no_coll_cause; + uint32_t global_no_coll_cause; + size_t local_cause_bytes_written = 0; + size_t global_cause_bytes_written = 0; + int nbits; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_PACKAGE + + HDassert((local_cause && local_cause_len > 0) || (global_cause && global_cause_len > 0)); + + /* + * Use compile-time assertion so this routine is updated + * when any new "no collective cause" values are added + */ + HDcompile_assert(H5D_MPIO_NO_COLLECTIVE_MAX_CAUSE == (H5D_mpio_no_collective_cause_t)256); + + /* Initialize output buffers */ + if (local_cause) + *local_cause = '\0'; + if (global_cause) + *global_cause = '\0'; + + /* Retrieve the local and global cause flags from the API context */ + if (H5CX_get_mpio_local_no_coll_cause(&local_no_coll_cause) < 0) + HGOTO_ERROR(H5E_CONTEXT, H5E_CANTGET, FAIL, "unable to get local no collective cause value") + if (H5CX_get_mpio_global_no_coll_cause(&global_no_coll_cause) < 0) + HGOTO_ERROR(H5E_CONTEXT, H5E_CANTGET, FAIL, "unable to get global no collective cause value") + + /* + * Append each of the "reason for breaking collective I/O" + * error messages to the local and global cause string buffers + */ + nbits = 8 * sizeof(local_no_coll_cause); + for (int bit_pos = 0; bit_pos < nbits; bit_pos++) { + H5D_mpio_no_collective_cause_t cur_cause; + const char * cause_str; + size_t buf_space_left; + + cur_cause = (H5D_mpio_no_collective_cause_t)(1 << bit_pos); + if (cur_cause == H5D_MPIO_NO_COLLECTIVE_MAX_CAUSE) + break; + + switch (cur_cause) { + case H5D_MPIO_SET_INDEPENDENT: + cause_str = "independent I/O was requested"; + break; + case H5D_MPIO_DATATYPE_CONVERSION: + cause_str = "datatype conversions were required"; + break; + case H5D_MPIO_DATA_TRANSFORMS: + cause_str = "data transforms needed to be applied"; + break; + case H5D_MPIO_MPI_OPT_TYPES_ENV_VAR_DISABLED: + cause_str = "optimized MPI types flag wasn't set"; + break; + case H5D_MPIO_NOT_SIMPLE_OR_SCALAR_DATASPACES: + cause_str = "one of the dataspaces was neither simple nor scalar"; + break; + case H5D_MPIO_NOT_CONTIGUOUS_OR_CHUNKED_DATASET: + cause_str = "dataset was not contiguous or chunked"; + break; + case H5D_MPIO_PARALLEL_FILTERED_WRITES_DISABLED: + cause_str = "parallel writes to filtered datasets are disabled"; + break; + case H5D_MPIO_ERROR_WHILE_CHECKING_COLLECTIVE_POSSIBLE: + cause_str = "an error occurred while checking if collective I/O was possible"; + break; + case H5D_MPIO_COLLECTIVE: + case H5D_MPIO_NO_COLLECTIVE_MAX_CAUSE: + default: + HDassert(0 && "invalid no collective cause reason"); + break; + } + + /* + * Determine if the local reasons for breaking collective I/O + * included the current cause + */ + if (local_cause && (cur_cause & local_no_coll_cause)) { + buf_space_left = local_cause_len - local_cause_bytes_written; + + /* + * Check if there were any previous error messages included. If + * so, prepend a semicolon to separate the messages. + */ + if (buf_space_left && local_cause_bytes_written) { + HDstrncat(local_cause, "; ", buf_space_left); + local_cause_bytes_written += MIN(buf_space_left, 2); + buf_space_left -= MIN(buf_space_left, 2); + } + + if (buf_space_left) { + HDstrncat(local_cause, cause_str, buf_space_left); + local_cause_bytes_written += MIN(buf_space_left, HDstrlen(cause_str)); + } + } + + /* + * Determine if the global reasons for breaking collective I/O + * included the current cause + */ + if (global_cause && (cur_cause & global_no_coll_cause)) { + buf_space_left = global_cause_len - global_cause_bytes_written; + + /* + * Check if there were any previous error messages included. If + * so, prepend a semicolon to separate the messages. + */ + if (buf_space_left && global_cause_bytes_written) { + HDstrncat(global_cause, "; ", buf_space_left); + global_cause_bytes_written += MIN(buf_space_left, 2); + buf_space_left -= MIN(buf_space_left, 2); + } + + if (buf_space_left) { + HDstrncat(global_cause, cause_str, buf_space_left); + global_cause_bytes_written += MIN(buf_space_left, HDstrlen(cause_str)); + } + } + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D__mpio_get_no_coll_cause_strings() */ + +/*------------------------------------------------------------------------- * Function: H5D__mpio_select_read * * Purpose: MPI-IO function to read directly from app buffer to file. @@ -449,8 +892,8 @@ done: */ herr_t H5D__mpio_select_read(const H5D_io_info_t *io_info, const H5D_type_info_t H5_ATTR_UNUSED *type_info, - hsize_t mpi_buf_count, const H5S_t H5_ATTR_UNUSED *file_space, - const H5S_t H5_ATTR_UNUSED *mem_space) + hsize_t mpi_buf_count, H5S_t H5_ATTR_UNUSED *file_space, + H5S_t H5_ATTR_UNUSED *mem_space) { const H5D_contig_storage_t *store_contig = &(io_info->store->contig); /* Contiguous storage info for this I/O operation */ @@ -480,8 +923,8 @@ done: */ herr_t H5D__mpio_select_write(const H5D_io_info_t *io_info, const H5D_type_info_t H5_ATTR_UNUSED *type_info, - hsize_t mpi_buf_count, const H5S_t H5_ATTR_UNUSED *file_space, - const H5S_t H5_ATTR_UNUSED *mem_space) + hsize_t mpi_buf_count, H5S_t H5_ATTR_UNUSED *file_space, + H5S_t H5_ATTR_UNUSED *mem_space) { const H5D_contig_storage_t *store_contig = &(io_info->store->contig); /* Contiguous storage info for this I/O operation */ @@ -500,145 +943,6 @@ done: } /* end H5D__mpio_select_write() */ /*------------------------------------------------------------------------- - * Function: H5D__mpio_array_gatherv - * - * Purpose: Given an array, specified in local_array, by each processor - * calling this function, collects each array into a single - * array which is then either gathered to the processor - * specified by root, when allgather is false, or is - * distributed back to all processors when allgather is true. - * - * The number of entries in the array contributed by an - * individual processor and the size of each entry should be - * specified in local_array_num_entries and array_entry_size, - * respectively. - * - * The MPI communicator to use should be specified for comm. - * - * If the sort_func argument is supplied, the array is sorted - * before the function returns. - * - * Note: if allgather is specified as true, root is ignored. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Jordan Henderson - * Sunday, April 9th, 2017 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5D__mpio_array_gatherv(void *local_array, size_t local_array_num_entries, size_t array_entry_size, - void **_gathered_array, size_t *_gathered_array_num_entries, hbool_t allgather, - int root, MPI_Comm comm, H5D_mpio_sort_func_cb_t sort_func) -{ - size_t gathered_array_num_entries = 0; /* The size of the newly-constructed array */ - void * gathered_array = NULL; /* The newly-constructed array returned to the caller */ - int *receive_counts_array = NULL; /* Array containing number of entries each processor is contributing */ - int *displacements_array = - NULL; /* Array of displacements where each processor places its data in the final array */ - int mpi_code, mpi_rank, mpi_size; - int sendcount; - herr_t ret_value = SUCCEED; - - FUNC_ENTER_STATIC - - HDassert(_gathered_array); - HDassert(_gathered_array_num_entries); - - MPI_Comm_size(comm, &mpi_size); - MPI_Comm_rank(comm, &mpi_rank); - - /* Determine the size of the end result array by collecting the number - * of entries contributed by each processor into a single total. - */ - if (MPI_SUCCESS != (mpi_code = MPI_Allreduce(&local_array_num_entries, &gathered_array_num_entries, 1, - MPI_INT, MPI_SUM, comm))) - HMPI_GOTO_ERROR(FAIL, "MPI_Allreduce failed", mpi_code) - - /* If 0 entries resulted from the collective operation, no processor is contributing anything and there is - * nothing to do */ - if (gathered_array_num_entries > 0) { - /* - * If gathering to all processors, all processors need to allocate space for the resulting array, as - * well as the receive counts and displacements arrays for the collective MPI_Allgatherv call. - * Otherwise, only the root processor needs to allocate the space for an MPI_Gatherv call. - */ - if (allgather || (mpi_rank == root)) { - if (NULL == (gathered_array = H5MM_malloc(gathered_array_num_entries * array_entry_size))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate gathered array") - - if (NULL == (receive_counts_array = (int *)H5MM_malloc((size_t)mpi_size * sizeof(int)))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate receive counts array") - - if (NULL == (displacements_array = (int *)H5MM_malloc((size_t)mpi_size * sizeof(int)))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate receive displacements array") - } /* end if */ - - /* - * If gathering to all processors, inform each processor of how many entries each other processor is - * contributing to the resulting array by collecting the counts into each processor's "receive counts" - * array. Otherwise, inform only the root processor of how many entries each other processor is - * contributing. - */ - if (allgather) { - if (MPI_SUCCESS != (mpi_code = MPI_Allgather(&local_array_num_entries, 1, MPI_INT, - receive_counts_array, 1, MPI_INT, comm))) - HMPI_GOTO_ERROR(FAIL, "MPI_Allgather failed", mpi_code) - } /* end if */ - else { - if (MPI_SUCCESS != (mpi_code = MPI_Gather(&local_array_num_entries, 1, MPI_INT, - receive_counts_array, 1, MPI_INT, root, comm))) - HMPI_GOTO_ERROR(FAIL, "MPI_Gather failed", mpi_code) - } /* end else */ - - if (allgather || (mpi_rank == root)) { - size_t i; - - /* Multiply each receive count by the size of the array entry, since the data is sent as bytes. */ - for (i = 0; i < (size_t)mpi_size; i++) - H5_CHECKED_ASSIGN(receive_counts_array[i], int, - (size_t)receive_counts_array[i] * array_entry_size, size_t); - - /* Set receive buffer offsets for the collective MPI_Allgatherv/MPI_Gatherv call. */ - displacements_array[0] = 0; - for (i = 1; i < (size_t)mpi_size; i++) - displacements_array[i] = displacements_array[i - 1] + receive_counts_array[i - 1]; - } /* end if */ - - /* As the data is sent as bytes, calculate the true sendcount for the data. */ - H5_CHECKED_ASSIGN(sendcount, int, local_array_num_entries *array_entry_size, size_t); - - if (allgather) { - if (MPI_SUCCESS != - (mpi_code = MPI_Allgatherv(local_array, sendcount, MPI_BYTE, gathered_array, - receive_counts_array, displacements_array, MPI_BYTE, comm))) - HMPI_GOTO_ERROR(FAIL, "MPI_Allgatherv failed", mpi_code) - } /* end if */ - else { - if (MPI_SUCCESS != - (mpi_code = MPI_Gatherv(local_array, sendcount, MPI_BYTE, gathered_array, - receive_counts_array, displacements_array, MPI_BYTE, root, comm))) - HMPI_GOTO_ERROR(FAIL, "MPI_Gatherv failed", mpi_code) - } /* end else */ - - if (sort_func && (allgather || (mpi_rank == root))) - HDqsort(gathered_array, gathered_array_num_entries, array_entry_size, sort_func); - } /* end if */ - - *_gathered_array = gathered_array; - *_gathered_array_num_entries = gathered_array_num_entries; - -done: - if (receive_counts_array) - H5MM_free(receive_counts_array); - if (displacements_array) - H5MM_free(displacements_array); - - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5D__mpio_array_gatherv() */ - -/*------------------------------------------------------------------------- * Function: H5D__mpio_get_sum_chunk * * Purpose: Routine for obtaining total number of chunks to cover @@ -690,7 +994,7 @@ done: */ herr_t H5D__contig_collective_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, - hsize_t H5_ATTR_UNUSED nelmts, const H5S_t *file_space, const H5S_t *mem_space, + hsize_t H5_ATTR_UNUSED nelmts, H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t H5_ATTR_UNUSED *fm) { H5D_mpio_actual_io_mode_t actual_io_mode = H5D_MPIO_CONTIGUOUS_COLLECTIVE; @@ -729,7 +1033,7 @@ done: */ herr_t H5D__contig_collective_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, - hsize_t H5_ATTR_UNUSED nelmts, const H5S_t *file_space, const H5S_t *mem_space, + hsize_t H5_ATTR_UNUSED nelmts, H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t H5_ATTR_UNUSED *fm) { H5D_mpio_actual_io_mode_t actual_io_mode = H5D_MPIO_CONTIGUOUS_COLLECTIVE; @@ -793,11 +1097,17 @@ static herr_t H5D__chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, H5D_chunk_map_t *fm) { H5FD_mpio_chunk_opt_t chunk_opt_mode; - int io_option = H5D_MULTI_CHUNK_IO_MORE_OPT; - int sum_chunk = -1; +#ifdef H5Dmpio_DEBUG + hbool_t log_file_flag = FALSE; + FILE * debug_log_file = NULL; +#endif #ifdef H5_HAVE_INSTRUMENTED_LIBRARY htri_t temp_not_link_io = FALSE; #endif + int io_option = H5D_MULTI_CHUNK_IO_MORE_OPT; + int sum_chunk = -1; + int mpi_rank; + int mpi_size; herr_t ret_value = SUCCEED; FUNC_ENTER_STATIC @@ -808,9 +1118,35 @@ H5D__chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_inf HDassert(type_info); HDassert(fm); - /* Disable collective metadata reads for chunked dataset I/O operations - * in order to prevent potential hangs */ - H5CX_set_coll_metadata_read(FALSE); + /* Obtain the current rank of the process and the number of ranks */ + if ((mpi_rank = H5F_mpi_get_rank(io_info->dset->oloc.file)) < 0) + HGOTO_ERROR(H5E_IO, H5E_MPI, FAIL, "unable to obtain MPI rank") + if ((mpi_size = H5F_mpi_get_size(io_info->dset->oloc.file)) < 0) + HGOTO_ERROR(H5E_IO, H5E_MPI, FAIL, "unable to obtain MPI size") + +#ifdef H5Dmpio_DEBUG + /* Initialize file-level debugging if not initialized */ + if (!H5D_mpio_debug_inited && H5D__mpio_debug_init() < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize H5Dmpio debugging") + + /* Open file for debugging if necessary */ + log_file_flag = H5D_mpio_debug_flags_s[(int)'f']; + if (log_file_flag) { + char debug_log_filename[1024]; + time_t time_now; + + HDsnprintf(debug_log_filename, 1024, "H5Dmpio_debug.rank%d", mpi_rank); + + if (NULL == (debug_log_file = HDfopen(debug_log_filename, "a"))) + HGOTO_ERROR(H5E_IO, H5E_OPENERROR, FAIL, "couldn't open debugging log file") + + /* Print a short header for this I/O operation */ + time_now = HDtime(NULL); + HDfprintf(debug_log_file, "##### %s", HDasctime(HDlocaltime(&time_now))); + + debug_stream = debug_log_file; + } +#endif /* Check the optional property list for the collective chunk IO optimization option */ if (H5CX_get_mpio_chunk_opt_mode(&chunk_opt_mode) < 0) @@ -824,13 +1160,10 @@ H5D__chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_inf /* via default path. branch by num threshold */ else { unsigned one_link_chunk_io_threshold; /* Threshold to use single collective I/O for all chunks */ - int mpi_size; /* Number of processes in MPI job */ if (H5D__mpio_get_sum_chunk(io_info, fm, &sum_chunk) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSWAP, FAIL, "unable to obtain the total chunk number of all processes"); - if ((mpi_size = H5F_mpi_get_size(io_info->dset->oloc.file)) < 0) - HGOTO_ERROR(H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi size") /* Get the chunk optimization option threshold */ if (H5CX_get_mpio_chunk_opt_num(&one_link_chunk_io_threshold) < 0) @@ -876,22 +1209,12 @@ H5D__chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_inf case H5D_ONE_LINK_CHUNK_IO_MORE_OPT: /* Check if there are any filters in the pipeline */ if (io_info->dset->shared->dcpl_cache.pline.nused > 0) { - /* For now, Multi-chunk IO must be forced for parallel filtered read, - * so that data can be unfiltered as it is received. There is significant - * complexity in unfiltering the data when it is read all at once into a - * single buffer. - */ - if (io_info->op_type == H5D_IO_OP_READ) { - if (H5D__multi_chunk_filtered_collective_io(io_info, type_info, fm) < 0) - HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, - "couldn't finish optimized multiple filtered chunk MPI-IO") - } /* end if */ - else if (H5D__link_chunk_filtered_collective_io(io_info, type_info, fm) < 0) + if (H5D__link_chunk_filtered_collective_io(io_info, type_info, fm, mpi_rank, mpi_size) < 0) HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish filtered linked chunk MPI-IO") } /* end if */ else /* Perform unfiltered link chunk collective IO */ - if (H5D__link_chunk_collective_io(io_info, type_info, fm, sum_chunk) < 0) + if (H5D__link_chunk_collective_io(io_info, type_info, fm, sum_chunk, mpi_rank, mpi_size) < 0) HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish linked chunk MPI-IO") break; @@ -899,18 +1222,28 @@ H5D__chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_inf default: /* multiple chunk IO via threshold */ /* Check if there are any filters in the pipeline */ if (io_info->dset->shared->dcpl_cache.pline.nused > 0) { - if (H5D__multi_chunk_filtered_collective_io(io_info, type_info, fm) < 0) + if (H5D__multi_chunk_filtered_collective_io(io_info, type_info, fm, mpi_rank, mpi_size) < 0) HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish optimized multiple filtered chunk MPI-IO") } /* end if */ else /* Perform unfiltered multi chunk collective IO */ - if (H5D__multi_chunk_collective_io(io_info, type_info, fm) < 0) + if (H5D__multi_chunk_collective_io(io_info, type_info, fm, mpi_rank, mpi_size) < 0) HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish optimized multiple chunk MPI-IO") break; } /* end switch */ done: +#ifdef H5Dmpio_DEBUG + /* Close debugging log file */ + if (debug_log_file) { + HDfprintf(debug_log_file, "##############\n\n"); + if (EOF == HDfclose(debug_log_file)) + HDONE_ERROR(H5E_IO, H5E_CLOSEERROR, FAIL, "couldn't close debugging log file") + debug_stream = H5DEBUG(D); + } +#endif + FUNC_LEAVE_NOAPI(ret_value) } /* end H5D__chunk_collective_io */ @@ -929,8 +1262,8 @@ done: */ herr_t H5D__chunk_collective_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, - hsize_t H5_ATTR_UNUSED nelmts, const H5S_t H5_ATTR_UNUSED *file_space, - const H5S_t H5_ATTR_UNUSED *mem_space, H5D_chunk_map_t *fm) + hsize_t H5_ATTR_UNUSED nelmts, H5S_t H5_ATTR_UNUSED *file_space, + H5S_t H5_ATTR_UNUSED *mem_space, H5D_chunk_map_t *fm) { herr_t ret_value = SUCCEED; /* Return value */ @@ -959,8 +1292,8 @@ done: */ herr_t H5D__chunk_collective_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, - hsize_t H5_ATTR_UNUSED nelmts, const H5S_t H5_ATTR_UNUSED *file_space, - const H5S_t H5_ATTR_UNUSED *mem_space, H5D_chunk_map_t *fm) + hsize_t H5_ATTR_UNUSED nelmts, H5S_t H5_ATTR_UNUSED *file_space, + H5S_t H5_ATTR_UNUSED *mem_space, H5D_chunk_map_t *fm) { herr_t ret_value = SUCCEED; /* Return value */ @@ -993,12 +1326,12 @@ done: */ static herr_t H5D__link_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, H5D_chunk_map_t *fm, - int sum_chunk) + int sum_chunk, int mpi_rank, int mpi_size) { H5D_chunk_addr_info_t *chunk_addr_info_array = NULL; - MPI_Datatype chunk_final_mtype; /* Final memory MPI datatype for all chunks with seletion */ + MPI_Datatype chunk_final_mtype; /* Final memory MPI datatype for all chunks with selection */ hbool_t chunk_final_mtype_is_derived = FALSE; - MPI_Datatype chunk_final_ftype; /* Final file MPI datatype for all chunks with seletion */ + MPI_Datatype chunk_final_ftype; /* Final file MPI datatype for all chunks with selection */ hbool_t chunk_final_ftype_is_derived = FALSE; H5D_storage_t ctg_store; /* Storage info for "fake" contiguous dataset */ size_t total_chunks; @@ -1074,9 +1407,8 @@ H5D__link_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *typ /* Set up the base storage address for this chunk */ io_info->store = &ctg_store; -#ifdef H5D_DEBUG - if (H5DEBUG(D)) - HDfprintf(H5DEBUG(D), "before inter_collective_io for total chunk = 1 \n"); +#ifdef H5Dmpio_DEBUG + H5D_MPIO_DEBUG(mpi_rank, "before inter_collective_io for total chunk = 1"); #endif /* Perform I/O */ @@ -1092,9 +1424,8 @@ H5D__link_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *typ num_chunk = H5SL_count(fm->sel_chunks); H5_CHECK_OVERFLOW(num_chunk, size_t, int); -#ifdef H5D_DEBUG - if (H5DEBUG(D)) - HDfprintf(H5DEBUG(D), "total_chunks = %zu, num_chunk = %zu\n", total_chunks, num_chunk); +#ifdef H5Dmpio_DEBUG + H5D_MPIO_DEBUG_VA(mpi_rank, "total_chunks = %zu, num_chunk = %zu", total_chunks, num_chunk); #endif /* Set up MPI datatype for chunks selected */ @@ -1125,18 +1456,17 @@ H5D__link_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *typ HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate chunk file is derived datatype flags buffer") -#ifdef H5D_DEBUG - if (H5DEBUG(D)) - HDfprintf(H5DEBUG(D), "before sorting the chunk address \n"); +#ifdef H5Dmpio_DEBUG + H5D_MPIO_DEBUG(mpi_rank, "before sorting chunk addresses"); #endif + /* Sort the chunk address */ - if (H5D__sort_chunk(io_info, fm, chunk_addr_info_array, sum_chunk) < 0) + if (H5D__sort_chunk(io_info, fm, chunk_addr_info_array, sum_chunk, mpi_rank, mpi_size) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSWAP, FAIL, "unable to sort chunk address") ctg_store.contig.dset_addr = chunk_addr_info_array[0].chunk_addr; -#ifdef H5D_DEBUG - if (H5DEBUG(D)) - HDfprintf(H5DEBUG(D), "after sorting the chunk address \n"); +#ifdef H5Dmpio_DEBUG + H5D_MPIO_DEBUG(mpi_rank, "after sorting chunk addresses"); #endif /* Obtain MPI derived datatype from all individual chunks */ @@ -1241,9 +1571,9 @@ H5D__link_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *typ /* No chunks selected for this process */ mpi_buf_count = (hsize_t)0; } /* end else */ -#ifdef H5D_DEBUG - if (H5DEBUG(D)) - HDfprintf(H5DEBUG(D), "before coming to final collective IO\n"); + +#ifdef H5Dmpio_DEBUG + H5D_MPIO_DEBUG(mpi_rank, "before coming to final collective I/O"); #endif /* Set up the base storage address for this chunk */ @@ -1256,11 +1586,11 @@ H5D__link_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *typ } /* end else */ done: -#ifdef H5D_DEBUG - if (H5DEBUG(D)) - HDfprintf(H5DEBUG(D), "before freeing memory inside H5D_link_collective_io ret_value = %d\n", - ret_value); +#ifdef H5Dmpio_DEBUG + H5D_MPIO_DEBUG_VA(mpi_rank, "before freeing memory inside H5D_link_collective_io ret_value = %d", + ret_value); #endif + /* Release resources */ if (chunk_addr_info_array) H5MM_xfree(chunk_addr_info_array); @@ -1293,68 +1623,89 @@ done: /*------------------------------------------------------------------------- * Function: H5D__link_chunk_filtered_collective_io * - * Purpose: Routine for one collective IO with one MPI derived datatype - * to link with all filtered chunks - * - * 1. Construct a list of selected chunks in the collective IO - * operation - * A. If any chunk is being written to by more than 1 - * process, the process writing to the chunk which - * currently has the least amount of chunks assigned - * to it becomes the new owner (in the case of ties, - * the lowest MPI rank becomes the new owner) - * 2. If the operation is a write operation - * A. Loop through each chunk in the operation - * I. If this is not a full overwrite of the chunk - * a) Read the chunk from file and pass the chunk - * through the filter pipeline in reverse order - * (Unfilter the chunk) + * Purpose: Performs collective I/O on filtered chunks by creating a + * single MPI derived datatype to link with all filtered + * chunks. The general algorithm is as follows: + * + * 1. Construct a list of selected chunks in the collective + * I/O operation + * 2. If the operation is a read operation + * A. Ensure that the list of chunks is sorted in + * monotonically non-decreasing order of chunk offset + * in the file + * B. Participate in a collective read of chunks from + * the file + * C. Loop through each selected chunk, unfiltering it and + * scattering the data to the application's read buffer + * 3. If the operation is a write operation + * A. Redistribute any chunks being written by more than 1 + * MPI rank, such that the chunk is only owned by 1 MPI + * rank. The rank writing to the chunk which currently + * has the least amount of chunks assigned to it becomes + * the new owner (in the case of ties, the lowest MPI + * rank becomes the new owner) + * B. Participate in a collective read of chunks from the + * file + * C. Loop through each chunk selected in the operation + * and for each chunk: + * I. If we actually read the chunk from the file (if + * a chunk is being fully overwritten, we skip + * reading it), pass the chunk through the filter + * pipeline in reverse order (unfilter the chunk) * II. Update the chunk data with the modifications from - * the owning process + * the owning MPI rank * III. Receive any modification data from other - * processes and update the chunk data with these + * ranks and update the chunk data with those * modifications * IV. Filter the chunk - * B. Contribute the modified chunks to an array gathered - * by all processes which contains the new sizes of - * every chunk modified in the collective IO operation - * C. All processes collectively re-allocate each chunk - * from the gathered array with their new sizes after - * the filter operation - * D. If this process has any chunks selected in the IO - * operation, create an MPI derived type for memory and - * file to write out the process' selected chunks to the - * file - * E. Perform the collective write - * F. All processes collectively re-insert each modified + * D. Contribute the modified chunks to an array gathered + * by all ranks which contains information for + * re-allocating space in the file for every chunk + * modified. Then, each rank collectively re-allocates + * each chunk from the gathered array with their new + * sizes after the filter operation + * E. Proceed with the collective write operation for all + * the modified chunks + * F. Contribute the modified chunks to an array gathered + * by all ranks which contains information for + * re-inserting every chunk modified into the chunk + * index. Then, each rank collectively re-inserts each * chunk from the gathered array into the chunk index * + * TODO: Note that steps D. and F. here are both collective + * operations that partially share data from the + * H5D_filtered_collective_io_info_t structure. To + * try to conserve on memory a bit, the distributed + * arrays these operations create are discarded after + * each operation is performed. If memory consumption + * here proves to not be an issue, the necessary data + * for both operations could be combined into a single + * structure so that only one collective MPI operation + * is needed to carry out both operations, rather than + * two. * * Return: Non-negative on success/Negative on failure * - * Programmer: Jordan Henderson - * Friday, Nov. 4th, 2016 - * *------------------------------------------------------------------------- */ static herr_t H5D__link_chunk_filtered_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, - H5D_chunk_map_t *fm) + H5D_chunk_map_t *fm, int mpi_rank, int mpi_size) { - H5D_filtered_collective_io_info_t *chunk_list = NULL; /* The list of chunks being read/written */ - H5D_filtered_collective_io_info_t *collective_chunk_list = - NULL; /* The list of chunks used during collective operations */ - H5D_storage_t ctg_store; /* Chunk storage information as contiguous dataset */ - MPI_Datatype mem_type = MPI_BYTE; - MPI_Datatype file_type = MPI_BYTE; - hbool_t mem_type_is_derived = FALSE; - hbool_t file_type_is_derived = FALSE; - size_t chunk_list_num_entries; - size_t collective_chunk_list_num_entries; - size_t * num_chunks_selected_array = NULL; /* Array of number of chunks selected on each process */ - size_t i; /* Local index variable */ - int mpi_rank, mpi_size, mpi_code; - herr_t ret_value = SUCCEED; + H5D_filtered_collective_io_info_t *chunk_list = NULL; /* The list of chunks being read/written */ + H5D_filtered_collective_io_info_t *chunk_hash_table = NULL; + unsigned char ** chunk_msg_bufs = NULL; + H5D_storage_t ctg_store; /* Chunk storage information as contiguous dataset */ + MPI_Datatype mem_type = MPI_BYTE; + MPI_Datatype file_type = MPI_BYTE; + hbool_t mem_type_is_derived = FALSE; + hbool_t file_type_is_derived = FALSE; + size_t * rank_chunks_assigned_map = NULL; + size_t chunk_list_num_entries; + size_t i; + int chunk_msg_bufs_len = 0; + int mpi_code; + herr_t ret_value = SUCCEED; FUNC_ENTER_STATIC @@ -1362,11 +1713,12 @@ H5D__link_chunk_filtered_collective_io(H5D_io_info_t *io_info, const H5D_type_in HDassert(type_info); HDassert(fm); - /* Obtain the current rank of the process and the number of processes */ - if ((mpi_rank = H5F_mpi_get_rank(io_info->dset->oloc.file)) < 0) - HGOTO_ERROR(H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi rank") - if ((mpi_size = H5F_mpi_get_size(io_info->dset->oloc.file)) < 0) - HGOTO_ERROR(H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi size") +#ifdef H5Dmpio_DEBUG + H5D_MPIO_TRACE_ENTER(mpi_rank); + H5D_MPIO_DEBUG_VA(mpi_rank, "Performing Linked-chunk I/O (%s) with MPI Comm size of %d", + io_info->op_type == H5D_IO_OP_WRITE ? "write" : "read", mpi_size); + H5D_MPIO_TIME_START(mpi_rank, "Linked-chunk I/O"); +#endif /* Set the actual-chunk-opt-mode property. */ H5CX_set_mpio_actual_chunk_opt(H5D_MPIO_LINK_CHUNK); @@ -1377,123 +1729,127 @@ H5D__link_chunk_filtered_collective_io(H5D_io_info_t *io_info, const H5D_type_in H5CX_set_mpio_actual_io_mode(H5D_MPIO_CHUNK_COLLECTIVE); /* Build a list of selected chunks in the collective io operation */ - if (H5D__construct_filtered_io_info_list(io_info, type_info, fm, &chunk_list, &chunk_list_num_entries) < - 0) + if (H5D__mpio_collective_filtered_chunk_io_setup(io_info, type_info, fm, &chunk_list, + &chunk_list_num_entries, mpi_rank) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "couldn't construct filtered I/O info list") - if (io_info->op_type == H5D_IO_OP_WRITE) { /* Filtered collective write */ + if (io_info->op_type == H5D_IO_OP_READ) { /* Filtered collective read */ + if (H5D__mpio_collective_filtered_chunk_read(chunk_list, chunk_list_num_entries, io_info, type_info, + mpi_rank, mpi_size) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "couldn't read filtered chunks") + } + else { /* Filtered collective write */ H5D_chk_idx_info_t index_info; - H5D_chunk_ud_t udata; hsize_t mpi_buf_count; - /* Construct chunked index info */ - index_info.f = io_info->dset->oloc.file; - index_info.pline = &(io_info->dset->shared->dcpl_cache.pline); - index_info.layout = &(io_info->dset->shared->layout.u.chunk); - index_info.storage = &(io_info->dset->shared->layout.storage.u.chunk); - - /* Set up chunk information for insertion to chunk index */ - udata.common.layout = index_info.layout; - udata.common.storage = index_info.storage; - udata.filter_mask = 0; - - /* Iterate through all the chunks in the collective write operation, - * updating each chunk with the data modifications from other processes, - * then re-filtering the chunk. + H5D_MPIO_INIT_CHUNK_IDX_INFO(index_info, io_info); + + if (mpi_size > 1) { + /* Redistribute shared chunks being written to */ + if (H5D__mpio_redistribute_shared_chunks(chunk_list, chunk_list_num_entries, io_info, fm, + mpi_rank, mpi_size, &rank_chunks_assigned_map) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to redistribute shared chunks") + + /* Send any chunk modification messages for chunks this rank no longer owns */ + if (H5D__mpio_share_chunk_modification_data(chunk_list, &chunk_list_num_entries, io_info, + type_info, mpi_rank, mpi_size, &chunk_hash_table, + &chunk_msg_bufs, &chunk_msg_bufs_len) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, + "unable to send chunk modification data between MPI ranks") + + /* Make sure the local chunk list was updated correctly */ + HDassert(chunk_list_num_entries == rank_chunks_assigned_map[mpi_rank]); + } + + /* Proceed to update all the chunks this rank owns with its own + * modification data and data from other ranks, before re-filtering + * the chunks. As chunk reads are done collectively here, all ranks + * must participate. */ - for (i = 0; i < chunk_list_num_entries; i++) - if (mpi_rank == chunk_list[i].owners.new_owner) - if (H5D__filtered_collective_chunk_entry_io(&chunk_list[i], io_info, type_info, fm) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "couldn't process chunk entry") - - /* Gather the new chunk sizes to all processes for a collective reallocation - * of the chunks in the file. - */ - if (H5D__mpio_array_gatherv(chunk_list, chunk_list_num_entries, - sizeof(H5D_filtered_collective_io_info_t), - (void **)&collective_chunk_list, &collective_chunk_list_num_entries, true, - 0, io_info->comm, NULL) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGATHER, FAIL, "couldn't gather new chunk sizes") - - /* Collectively re-allocate the modified chunks (from each process) in the file */ - for (i = 0; i < collective_chunk_list_num_entries; i++) { - hbool_t insert; - - if (H5D__chunk_file_alloc(&index_info, &collective_chunk_list[i].chunk_states.chunk_current, - &collective_chunk_list[i].chunk_states.new_chunk, &insert, - collective_chunk_list[i].scaled) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "unable to allocate chunk") - } /* end for */ - - if (NULL == (num_chunks_selected_array = (size_t *)H5MM_malloc((size_t)mpi_size * sizeof(size_t)))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate num chunks selected array") - - if (MPI_SUCCESS != - (mpi_code = MPI_Allgather(&chunk_list_num_entries, 1, MPI_UNSIGNED_LONG_LONG, - num_chunks_selected_array, 1, MPI_UNSIGNED_LONG_LONG, io_info->comm))) - HMPI_GOTO_ERROR(FAIL, "MPI_Allgather failed", mpi_code) - - /* If this process has any chunks selected, create a MPI type for collectively - * writing out the chunks to file. Otherwise, the process contributes to the + if (H5D__mpio_collective_filtered_chunk_update(chunk_list, chunk_list_num_entries, chunk_hash_table, + chunk_msg_bufs, chunk_msg_bufs_len, io_info, type_info, + mpi_rank, mpi_size) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "couldn't update modified chunks") + + /* Free up resources used by chunk hash table now that we're done updating chunks */ + HASH_CLEAR(hh, chunk_hash_table); + + /* All ranks now collectively re-allocate file space for all chunks */ + if (H5D__mpio_collective_filtered_chunk_reallocate(chunk_list, chunk_list_num_entries, + rank_chunks_assigned_map, io_info, &index_info, + mpi_rank, mpi_size) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, + "couldn't collectively re-allocate file space for chunks") + + /* If this rank has any chunks selected, create a MPI type for collectively + * writing out the chunks to file. Otherwise, the rank contributes to the * collective write with a none type. */ - if (chunk_list_num_entries) { - size_t offset; - - /* During the collective re-allocation of chunks in the file, the record for each - * chunk is only updated in the collective array, not in the local copy of chunks on each - * process. However, each process needs the updated chunk records so that they can create - * a MPI type for the collective write that will write to the chunk's possible new locations - * in the file instead of the old ones. This ugly hack seems to be the best solution to - * copy the information back to the local array and avoid having to modify the collective - * write type function in an ugly way so that it will accept the collective array instead - * of the local array. This works correctly because the array gather function guarantees - * that the chunk data in the collective array is ordered in blocks by rank. - */ - for (i = 0, offset = 0; i < (size_t)mpi_rank; i++) - offset += num_chunks_selected_array[i]; - - H5MM_memcpy(chunk_list, &collective_chunk_list[offset], - num_chunks_selected_array[mpi_rank] * sizeof(H5D_filtered_collective_io_info_t)); + if (H5D__mpio_collective_filtered_io_type(chunk_list, chunk_list_num_entries, io_info->op_type, + &mem_type, &mem_type_is_derived, &file_type, + &file_type_is_derived) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, + "couldn't create MPI type for writing filtered chunks") - /* Create single MPI type encompassing each selection in the dataspace */ - if (H5D__mpio_filtered_collective_write_type(chunk_list, chunk_list_num_entries, &mem_type, - &mem_type_is_derived, &file_type, - &file_type_is_derived) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, FAIL, "couldn't create MPI link chunk I/O type") + mpi_buf_count = (file_type_is_derived || mem_type_is_derived) ? 1 : 0; - /* Override the write buffer to point to the address of the first - * chunk data buffer + /* Setup contig storage info for I/O operation */ + if (chunk_list_num_entries) { + /* + * Override the write buffer to point to the first + * chunk's data buffer */ io_info->u.wbuf = chunk_list[0].buf; - } /* end if */ - /* We have a single, complicated MPI datatype for both memory & file */ - mpi_buf_count = (mem_type_is_derived && file_type_is_derived) ? (hsize_t)1 : (hsize_t)0; - - /* Set up the base storage address for this operation */ - ctg_store.contig.dset_addr = 0; /* Write address must be set to address 0 */ - io_info->store = &ctg_store; + /* + * Setup the base storage address for this operation + * to be the first chunk's file address + */ + ctg_store.contig.dset_addr = chunk_list[0].chunk_new.offset; + } + else + ctg_store.contig.dset_addr = 0; /* Perform I/O */ + io_info->store = &ctg_store; if (H5D__final_collective_io(io_info, type_info, mpi_buf_count, file_type, mem_type) < 0) HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish MPI-IO") + /* Free up resources in anticipation of following collective operation */ + for (i = 0; i < chunk_list_num_entries; i++) { + if (chunk_list[i].buf) { + H5MM_free(chunk_list[i].buf); + chunk_list[i].buf = NULL; + } + } + /* Participate in the collective re-insertion of all chunks modified - * in this iteration into the chunk index + * into the chunk index */ - for (i = 0; i < collective_chunk_list_num_entries; i++) { - udata.chunk_block = collective_chunk_list[i].chunk_states.new_chunk; - udata.common.scaled = collective_chunk_list[i].scaled; - udata.chunk_idx = collective_chunk_list[i].index; - - if ((index_info.storage->ops->insert)(&index_info, &udata, io_info->dset) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert chunk address into index") - } /* end for */ - } /* end if */ + if (H5D__mpio_collective_filtered_chunk_reinsert(chunk_list, chunk_list_num_entries, + rank_chunks_assigned_map, io_info, &index_info, + mpi_rank, mpi_size) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, + "couldn't collectively re-insert modified chunks into chunk index") + } done: - /* Free resources used by a process which had some selection */ + /* Free the MPI buf and file types, if they were derived */ + if (mem_type_is_derived && MPI_SUCCESS != (mpi_code = MPI_Type_free(&mem_type))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + if (file_type_is_derived && MPI_SUCCESS != (mpi_code = MPI_Type_free(&file_type))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + + if (chunk_msg_bufs) { + for (i = 0; i < (size_t)chunk_msg_bufs_len; i++) + H5MM_free(chunk_msg_bufs[i]); + + H5MM_free(chunk_msg_bufs); + } + + HASH_CLEAR(hh, chunk_hash_table); + + /* Free resources used by a rank which had some selection */ if (chunk_list) { for (i = 0; i < chunk_list_num_entries; i++) if (chunk_list[i].buf) @@ -1502,16 +1858,13 @@ done: H5MM_free(chunk_list); } /* end if */ - if (num_chunks_selected_array) - H5MM_free(num_chunks_selected_array); - if (collective_chunk_list) - H5MM_free(collective_chunk_list); + if (rank_chunks_assigned_map) + H5MM_free(rank_chunks_assigned_map); - /* Free the MPI buf and file types, if they were derived */ - if (mem_type_is_derived && MPI_SUCCESS != (mpi_code = MPI_Type_free(&mem_type))) - HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) - if (file_type_is_derived && MPI_SUCCESS != (mpi_code = MPI_Type_free(&file_type))) - HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) +#ifdef H5Dmpio_DEBUG + H5D_MPIO_TIME_STOP(mpi_rank); + H5D_MPIO_TRACE_EXIT(mpi_rank); +#endif FUNC_LEAVE_NOAPI(ret_value) } /* end H5D__link_chunk_filtered_collective_io() */ @@ -1534,7 +1887,8 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5D__multi_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, H5D_chunk_map_t *fm) +H5D__multi_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, H5D_chunk_map_t *fm, + int mpi_rank, int mpi_size) { H5D_io_info_t ctg_io_info; /* Contiguous I/O info object */ H5D_storage_t ctg_store; /* Chunk storage information as contiguous dataset */ @@ -1547,11 +1901,8 @@ H5D__multi_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *ty H5FD_mpio_collective_opt_t last_coll_opt_mode = H5FD_MPIO_COLLECTIVE_IO; /* Last parallel transfer with independent IO or collective IO with this mode */ - size_t total_chunk; /* Total # of chunks in dataset */ -#ifdef H5Dmpio_DEBUG - int mpi_rank; -#endif - size_t u; /* Local index variable */ + size_t total_chunk; /* Total # of chunks in dataset */ + size_t u; /* Local index variable */ H5D_mpio_actual_io_mode_t actual_io_mode = H5D_MPIO_NO_COLLECTIVE; /* Local variable for tracking the I/O mode used. */ herr_t ret_value = SUCCEED; @@ -1561,10 +1912,6 @@ H5D__multi_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *ty /* Set the actual chunk opt mode property */ H5CX_set_mpio_actual_chunk_opt(H5D_MPIO_MULTI_CHUNK); -#ifdef H5Dmpio_DEBUG - mpi_rank = H5F_mpi_get_rank(io_info->dset->oloc.file); -#endif - /* Retrieve total # of chunks in dataset */ H5_CHECKED_ASSIGN(total_chunk, size_t, fm->layout->u.chunk.nchunks, hsize_t); HDassert(total_chunk != 0); @@ -1572,13 +1919,13 @@ H5D__multi_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *ty /* Allocate memories */ chunk_io_option = (uint8_t *)H5MM_calloc(total_chunk); chunk_addr = (haddr_t *)H5MM_calloc(total_chunk * sizeof(haddr_t)); -#ifdef H5D_DEBUG - if (H5DEBUG(D)) - HDfprintf(H5DEBUG(D), "total_chunk %zu\n", total_chunk); + +#ifdef H5Dmpio_DEBUG + H5D_MPIO_DEBUG_VA(mpi_rank, "total_chunk %zu", total_chunk); #endif /* Obtain IO option for each chunk */ - if (H5D__obtain_mpio_mode(io_info, fm, chunk_io_option, chunk_addr) < 0) + if (H5D__obtain_mpio_mode(io_info, fm, chunk_io_option, chunk_addr, mpi_rank, mpi_size) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTRECV, FAIL, "unable to obtain MPIO mode") /* Set up contiguous I/O info object */ @@ -1606,9 +1953,8 @@ H5D__multi_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *ty H5S_t * fspace; /* Dataspace describing chunk & selection in it */ H5S_t * mspace; /* Dataspace describing selection in memory corresponding to this chunk */ -#ifdef H5D_DEBUG - if (H5DEBUG(D)) - HDfprintf(H5DEBUG(D), "mpi_rank = %d, chunk index = %zu\n", mpi_rank, u); +#ifdef H5Dmpio_DEBUG + H5D_MPIO_DEBUG_VA(mpi_rank, "mpi_rank = %d, chunk index = %zu", mpi_rank, u); #endif /* Get the chunk info for this chunk, if there are elements selected */ chunk_info = fm->select_chunk[u]; @@ -1626,10 +1972,9 @@ H5D__multi_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *ty * needs to contribute MPI NONE TYPE. */ if (chunk_io_option[u] == H5D_CHUNK_IO_MODE_COL) { -#ifdef H5D_DEBUG - if (H5DEBUG(D)) - HDfprintf(H5DEBUG(D), "inside collective chunk IO mpi_rank = %d, chunk index = %zu\n", - mpi_rank, u); +#ifdef H5Dmpio_DEBUG + H5D_MPIO_DEBUG_VA(mpi_rank, "inside collective chunk IO mpi_rank = %d, chunk index = %zu", + mpi_rank, u); #endif /* Set the file & memory dataspaces */ @@ -1665,10 +2010,9 @@ H5D__multi_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *ty HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish shared collective MPI-IO") } /* end if */ else { /* possible independent IO for this chunk */ -#ifdef H5D_DEBUG - if (H5DEBUG(D)) - HDfprintf(H5DEBUG(D), "inside independent IO mpi_rank = %d, chunk index = %zu\n", mpi_rank, - u); +#ifdef H5Dmpio_DEBUG + H5D_MPIO_DEBUG_VA(mpi_rank, "inside independent IO mpi_rank = %d, chunk index = %zu", mpi_rank, + u); #endif HDassert(chunk_io_option[u] == 0); @@ -1698,9 +2042,8 @@ H5D__multi_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *ty /* Perform the I/O */ if (H5D__inter_collective_io(&ctg_io_info, type_info, fspace, mspace) < 0) HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish shared collective MPI-IO") -#ifdef H5D_DEBUG - if (H5DEBUG(D)) - HDfprintf(H5DEBUG(D), "after inter collective IO\n"); +#ifdef H5Dmpio_DEBUG + H5D_MPIO_DEBUG(mpi_rank, "after inter collective IO"); #endif } /* end else */ } /* end for */ @@ -1720,80 +2063,101 @@ done: /*------------------------------------------------------------------------- * Function: H5D__multi_chunk_filtered_collective_io * - * Purpose: To do filtered collective IO iteratively to save on memory. - * While link_chunk_filtered_collective_io will construct and - * work on a list of all of the chunks selected in the IO - * operation at once, this function works iteratively on a set - * of chunks at a time; at most one chunk per rank per - * iteration. - * - * 1. Construct a list of selected chunks in the collective IO - * operation - * A. If any chunk is being written to by more than 1 - * process, the process writing to the chunk which - * currently has the least amount of chunks assigned - * to it becomes the new owner (in the case of ties, - * the lowest MPI rank becomes the new owner) - * 2. If the operation is a read operation - * A. Loop through each chunk in the operation - * I. Read the chunk from the file - * II. Unfilter the chunk - * III. Scatter the read chunk data to the user's buffer - * 3. If the operation is a write operation - * A. Loop through each chunk in the operation - * I. If this is not a full overwrite of the chunk - * a) Read the chunk from file and pass the chunk - * through the filter pipeline in reverse order - * (Unfilter the chunk) - * II. Update the chunk data with the modifications from - * the owning process - * III. Receive any modification data from other - * processes and update the chunk data with these - * modifications - * IV. Filter the chunk - * V. Contribute the chunk to an array gathered by - * all processes which contains every chunk - * modified in this iteration (up to one chunk - * per process, some processes may not have a - * selection/may have less chunks to work on than - * other processes) - * VI. All processes collectively re-allocate each - * chunk from the gathered array with their new - * sizes after the filter operation - * VII. Proceed with the collective write operation - * for the chunks modified on this iteration - * VIII. All processes collectively re-insert each - * chunk from the gathered array into the chunk - * index + * Purpose: Performs collective I/O on filtered chunks iteratively to + * save on memory and potentially get better performance + * depending on the average number of chunks per rank. While + * linked-chunk I/O will construct and work on a list of all + * of the chunks selected in the I/O operation at once, this + * function works iteratively on a set of chunks at a time; at + * most one chunk per rank per iteration. The general + * algorithm is as follows: + * + * 1. Construct a list of selected chunks in the collective + * I/O operation + * 2. If the operation is a read operation, loop an amount of + * times equal to the maximum number of chunks selected on + * any particular rank and on each iteration: + * A. Participate in a collective read of chunks from + * the file (ranks that run out of chunks still need + * to participate) + * B. Unfilter the chunk that was read (if any) + * C. Scatter the read chunk's data to the application's + * read buffer + * 3. If the operation is a write operation, redistribute any + * chunks being written to by more than 1 MPI rank, such + * that the chunk is only owned by 1 MPI rank. The rank + * writing to the chunk which currently has the least + * amount of chunks assigned to it becomes the new owner + * (in the case of ties, the lowest MPI rank becomes the + * new owner). Then, loop an amount of times equal to the + * maximum number of chunks selected on any particular + * rank and on each iteration: + * A. Participate in a collective read of chunks from + * the file (ranks that run out of chunks still need + * to participate) + * I. If we actually read a chunk from the file (if + * a chunk is being fully overwritten, we skip + * reading it), pass the chunk through the filter + * pipeline in reverse order (unfilter the chunk) + * B. Update the chunk data with the modifications from + * the owning rank + * C. Receive any modification data from other ranks and + * update the chunk data with those modifications + * D. Filter the chunk + * E. Contribute the chunk to an array gathered by + * all ranks which contains information for + * re-allocating space in the file for every chunk + * modified in this iteration (up to one chunk per + * rank; some ranks may not have a selection/may have + * less chunks to work on than other ranks). Then, + * each rank collectively re-allocates each chunk + * from the gathered array with their new sizes + * after the filter operation + * F. Proceed with the collective write operation + * for the chunks modified on this iteration + * G. Contribute the chunk to an array gathered by + * all ranks which contains information for + * re-inserting every chunk modified on this + * iteration into the chunk index. Then, each rank + * collectively re-inserts each chunk from the + * gathered array into the chunk index + * + * TODO: Note that steps E. and G. here are both collective + * operations that partially share data from the + * H5D_filtered_collective_io_info_t structure. To + * try to conserve on memory a bit, the distributed + * arrays these operations create are discarded after + * each operation is performed. If memory consumption + * here proves to not be an issue, the necessary data + * for both operations could be combined into a single + * structure so that only one collective MPI operation + * is needed to carry out both operations, rather than + * two. * * Return: Non-negative on success/Negative on failure * - * Programmer: Jordan Henderson - * Friday, Dec. 2nd, 2016 - * *------------------------------------------------------------------------- */ static herr_t H5D__multi_chunk_filtered_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, - H5D_chunk_map_t *fm) + H5D_chunk_map_t *fm, int mpi_rank, int mpi_size) { - H5D_filtered_collective_io_info_t *chunk_list = NULL; /* The list of chunks being read/written */ - H5D_filtered_collective_io_info_t *collective_chunk_list = - NULL; /* The list of chunks used during collective operations */ - H5D_storage_t store; /* union of EFL and chunk pointer in file space */ - H5D_io_info_t ctg_io_info; /* Contiguous I/O info object */ - H5D_storage_t ctg_store; /* Chunk storage information as contiguous dataset */ - MPI_Datatype *file_type_array = NULL; - MPI_Datatype *mem_type_array = NULL; - hbool_t * file_type_is_derived_array = NULL; - hbool_t * mem_type_is_derived_array = NULL; - hbool_t * has_chunk_selected_array = - NULL; /* Array of whether or not each process is contributing a chunk to each iteration */ - size_t chunk_list_num_entries; - size_t collective_chunk_list_num_entries; - size_t i, j; /* Local index variable */ - int mpi_rank, mpi_size, mpi_code; - herr_t ret_value = SUCCEED; + H5D_filtered_collective_io_info_t *chunk_list = NULL; /* The list of chunks being read/written */ + H5D_filtered_collective_io_info_t *chunk_hash_table = NULL; + unsigned char ** chunk_msg_bufs = NULL; + H5D_io_info_t ctg_io_info; /* Contiguous I/O info object */ + H5D_storage_t ctg_store; /* Chunk storage information as contiguous dataset */ + MPI_Datatype mem_type = MPI_BYTE; + MPI_Datatype file_type = MPI_BYTE; + hbool_t mem_type_is_derived = FALSE; + hbool_t file_type_is_derived = FALSE; + hbool_t have_chunk_to_process; + size_t chunk_list_num_entries; + size_t i; + size_t max_num_chunks; + int chunk_msg_bufs_len = 0; + int mpi_code; + herr_t ret_value = SUCCEED; FUNC_ENTER_STATIC @@ -1801,11 +2165,12 @@ H5D__multi_chunk_filtered_collective_io(H5D_io_info_t *io_info, const H5D_type_i HDassert(type_info); HDassert(fm); - /* Obtain the current rank of the process and the number of processes */ - if ((mpi_rank = H5F_mpi_get_rank(io_info->dset->oloc.file)) < 0) - HGOTO_ERROR(H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi rank") - if ((mpi_size = H5F_mpi_get_size(io_info->dset->oloc.file)) < 0) - HGOTO_ERROR(H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi size") +#ifdef H5Dmpio_DEBUG + H5D_MPIO_TRACE_ENTER(mpi_rank); + H5D_MPIO_DEBUG_VA(mpi_rank, "Performing Multi-chunk I/O (%s) with MPI Comm size of %d", + io_info->op_type == H5D_IO_OP_WRITE ? "write" : "read", mpi_size); + H5D_MPIO_TIME_START(mpi_rank, "Multi-chunk I/O"); +#endif /* Set the actual chunk opt mode property */ H5CX_set_mpio_actual_chunk_opt(H5D_MPIO_MULTI_CHUNK); @@ -1816,10 +2181,19 @@ H5D__multi_chunk_filtered_collective_io(H5D_io_info_t *io_info, const H5D_type_i H5CX_set_mpio_actual_io_mode(H5D_MPIO_CHUNK_COLLECTIVE); /* Build a list of selected chunks in the collective IO operation */ - if (H5D__construct_filtered_io_info_list(io_info, type_info, fm, &chunk_list, &chunk_list_num_entries) < - 0) + if (H5D__mpio_collective_filtered_chunk_io_setup(io_info, type_info, fm, &chunk_list, + &chunk_list_num_entries, mpi_rank) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "couldn't construct filtered I/O info list") + /* Retrieve the maximum number of chunks selected for any rank */ + if (MPI_SUCCESS != (mpi_code = MPI_Allreduce(&chunk_list_num_entries, &max_num_chunks, 1, + MPI_UNSIGNED_LONG_LONG, MPI_MAX, io_info->comm))) + HMPI_GOTO_ERROR(FAIL, "MPI_Allreduce failed", mpi_code) + + /* If no one has anything selected at all, end the operation */ + if (0 == max_num_chunks) + HGOTO_DONE(SUCCEED); + /* Set up contiguous I/O info object */ H5MM_memcpy(&ctg_io_info, io_info, sizeof(ctg_io_info)); ctg_io_info.store = &ctg_store; @@ -1827,190 +2201,147 @@ H5D__multi_chunk_filtered_collective_io(H5D_io_info_t *io_info, const H5D_type_i /* Initialize temporary contiguous storage info */ ctg_store.contig.dset_size = (hsize_t)io_info->dset->shared->layout.u.chunk.size; - ctg_store.contig.dset_addr = 0; - - /* Set dataset storage for I/O info */ - io_info->store = &store; if (io_info->op_type == H5D_IO_OP_READ) { /* Filtered collective read */ - for (i = 0; i < chunk_list_num_entries; i++) - if (H5D__filtered_collective_chunk_entry_io(&chunk_list[i], io_info, type_info, fm) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "couldn't process chunk entry") - } /* end if */ + for (i = 0; i < max_num_chunks; i++) { + /* Check if this rank has a chunk to work on for this iteration */ + have_chunk_to_process = (i < chunk_list_num_entries); + + if (H5D__mpio_collective_filtered_chunk_read(have_chunk_to_process ? &chunk_list[i] : NULL, + have_chunk_to_process ? 1 : 0, io_info, type_info, + mpi_rank, mpi_size) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "couldn't read filtered chunks") + + if (have_chunk_to_process && chunk_list[i].buf) { + H5MM_free(chunk_list[i].buf); + chunk_list[i].buf = NULL; + } + } + } else { /* Filtered collective write */ H5D_chk_idx_info_t index_info; - H5D_chunk_ud_t udata; - size_t max_num_chunks; hsize_t mpi_buf_count; /* Construct chunked index info */ - index_info.f = io_info->dset->oloc.file; - index_info.pline = &(io_info->dset->shared->dcpl_cache.pline); - index_info.layout = &(io_info->dset->shared->layout.u.chunk); - index_info.storage = &(io_info->dset->shared->layout.storage.u.chunk); - - /* Set up chunk information for insertion to chunk index */ - udata.common.layout = index_info.layout; - udata.common.storage = index_info.storage; - udata.filter_mask = 0; - - /* Retrieve the maximum number of chunks being written among all processes */ - if (MPI_SUCCESS != (mpi_code = MPI_Allreduce(&chunk_list_num_entries, &max_num_chunks, 1, - MPI_UNSIGNED_LONG_LONG, MPI_MAX, io_info->comm))) - HMPI_GOTO_ERROR(FAIL, "MPI_Allreduce failed", mpi_code) - - /* If no one is writing anything at all, end the operation */ - if (!(max_num_chunks > 0)) - HGOTO_DONE(SUCCEED); - - /* Allocate arrays for storing MPI file and mem types and whether or not the - * types were derived. - */ - if (NULL == (file_type_array = (MPI_Datatype *)H5MM_malloc(max_num_chunks * sizeof(MPI_Datatype)))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate file type array") - - if (NULL == (file_type_is_derived_array = (hbool_t *)H5MM_calloc(max_num_chunks * sizeof(hbool_t)))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate file type is derived array") - - if (NULL == (mem_type_array = (MPI_Datatype *)H5MM_malloc(max_num_chunks * sizeof(MPI_Datatype)))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate mem type array") - - if (NULL == (mem_type_is_derived_array = (hbool_t *)H5MM_calloc(max_num_chunks * sizeof(hbool_t)))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate mem type is derived array") - - /* Iterate over the max number of chunks among all processes, as this process could - * have no chunks left to work on, but it still needs to participate in the collective - * re-allocation and re-insertion of chunks modified by other processes. + H5D_MPIO_INIT_CHUNK_IDX_INFO(index_info, io_info); + + if (mpi_size > 1) { + /* Redistribute shared chunks being written to */ + if (H5D__mpio_redistribute_shared_chunks(chunk_list, chunk_list_num_entries, io_info, fm, + mpi_rank, mpi_size, NULL) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to redistribute shared chunks") + + /* Send any chunk modification messages for chunks this rank no longer owns */ + if (H5D__mpio_share_chunk_modification_data(chunk_list, &chunk_list_num_entries, io_info, + type_info, mpi_rank, mpi_size, &chunk_hash_table, + &chunk_msg_bufs, &chunk_msg_bufs_len) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, + "unable to send chunk modification data between MPI ranks") + } + + /* Iterate over the max number of chunks among all ranks, as this rank could + * have no chunks left to work on, but it still needs to participate in the + * collective re-allocation and re-insertion of chunks modified by other ranks. */ for (i = 0; i < max_num_chunks; i++) { - /* Check if this process has a chunk to work on for this iteration */ - hbool_t have_chunk_to_process = - (i < chunk_list_num_entries) && (mpi_rank == chunk_list[i].owners.new_owner); - - if (have_chunk_to_process) - if (H5D__filtered_collective_chunk_entry_io(&chunk_list[i], io_info, type_info, fm) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "couldn't process chunk entry") + /* Check if this rank has a chunk to work on for this iteration */ + have_chunk_to_process = (i < chunk_list_num_entries) && (mpi_rank == chunk_list[i].new_owner); - /* Gather the new chunk sizes to all processes for a collective re-allocation - * of the chunks in the file + /* Proceed to update the chunk this rank owns (if any left) with its + * own modification data and data from other ranks, before re-filtering + * the chunks. As chunk reads are done collectively here, all ranks + * must participate. */ - if (H5D__mpio_array_gatherv(&chunk_list[i], have_chunk_to_process ? 1 : 0, - sizeof(H5D_filtered_collective_io_info_t), - (void **)&collective_chunk_list, &collective_chunk_list_num_entries, - true, 0, io_info->comm, NULL) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGATHER, FAIL, "couldn't gather new chunk sizes") - - /* Participate in the collective re-allocation of all chunks modified - * in this iteration. + if (H5D__mpio_collective_filtered_chunk_update(have_chunk_to_process ? &chunk_list[i] : NULL, + have_chunk_to_process ? 1 : 0, chunk_hash_table, + chunk_msg_bufs, chunk_msg_bufs_len, io_info, + type_info, mpi_rank, mpi_size) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "couldn't update modified chunks") + + /* All ranks now collectively re-allocate file space for all chunks */ + if (H5D__mpio_collective_filtered_chunk_reallocate(have_chunk_to_process ? &chunk_list[i] : NULL, + have_chunk_to_process ? 1 : 0, NULL, io_info, + &index_info, mpi_rank, mpi_size) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, + "couldn't collectively re-allocate file space for chunks") + + /* + * If this rank has a chunk to work on, create a MPI type + * for writing out the chunk. Otherwise, the rank will + * use MPI_BYTE for the file and memory type and specify + * a count of 0. */ - for (j = 0; j < collective_chunk_list_num_entries; j++) { - hbool_t insert = FALSE; + if (H5D__mpio_collective_filtered_io_type( + have_chunk_to_process ? &chunk_list[i] : NULL, have_chunk_to_process ? 1 : 0, + io_info->op_type, &mem_type, &mem_type_is_derived, &file_type, &file_type_is_derived) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, + "couldn't create MPI type for writing filtered chunks") - if (H5D__chunk_file_alloc(&index_info, &collective_chunk_list[j].chunk_states.chunk_current, - &collective_chunk_list[j].chunk_states.new_chunk, &insert, - chunk_list[j].scaled) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "unable to allocate chunk") - } /* end for */ - - if (NULL == - (has_chunk_selected_array = (hbool_t *)H5MM_malloc((size_t)mpi_size * sizeof(hbool_t)))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate num chunks selected array") - - if (MPI_SUCCESS != - (mpi_code = MPI_Allgather(&have_chunk_to_process, 1, MPI_C_BOOL, has_chunk_selected_array, 1, - MPI_C_BOOL, io_info->comm))) - HMPI_GOTO_ERROR(FAIL, "MPI_Allgather failed", mpi_code) + mpi_buf_count = (file_type_is_derived || mem_type_is_derived) ? 1 : 0; - /* If this process has a chunk to work on, create a MPI type for the - * memory and file for writing out the chunk - */ + /* Override the write buffer to point to the chunk data buffer */ if (have_chunk_to_process) { - size_t offset; - int mpi_type_count; - - for (j = 0, offset = 0; j < (size_t)mpi_rank; j++) - offset += has_chunk_selected_array[j]; - - /* Collect the new chunk info back to the local copy, since only the record in the - * collective array gets updated by the chunk re-allocation */ - H5MM_memcpy(&chunk_list[i].chunk_states.new_chunk, - &collective_chunk_list[offset].chunk_states.new_chunk, - sizeof(chunk_list[i].chunk_states.new_chunk)); - - H5_CHECKED_ASSIGN(mpi_type_count, int, chunk_list[i].chunk_states.new_chunk.length, hsize_t); - - /* Create MPI memory type for writing to chunk */ - if (MPI_SUCCESS != - (mpi_code = MPI_Type_contiguous(mpi_type_count, MPI_BYTE, &mem_type_array[i]))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code) - if (MPI_SUCCESS != (mpi_code = MPI_Type_commit(&mem_type_array[i]))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code) - mem_type_is_derived_array[i] = TRUE; - - /* Create MPI file type for writing to chunk */ - if (MPI_SUCCESS != - (mpi_code = MPI_Type_contiguous(mpi_type_count, MPI_BYTE, &file_type_array[i]))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code) - if (MPI_SUCCESS != (mpi_code = MPI_Type_commit(&file_type_array[i]))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code) - file_type_is_derived_array[i] = TRUE; - - mpi_buf_count = 1; - - /* Set up the base storage address for this operation */ - ctg_store.contig.dset_addr = chunk_list[i].chunk_states.new_chunk.offset; - - /* Override the write buffer to point to the address of the - * chunk data buffer + /* + * Override the write buffer to point to the + * chunk's data buffer */ ctg_io_info.u.wbuf = chunk_list[i].buf; - } /* end if */ - else { - mem_type_array[i] = file_type_array[i] = MPI_BYTE; - mpi_buf_count = 0; - } /* end else */ + + /* + * Setup the base storage address for this + * operation to be the chunk's file address + */ + ctg_store.contig.dset_addr = chunk_list[i].chunk_new.offset; + } + else + ctg_store.contig.dset_addr = 0; /* Perform the I/O */ - if (H5D__final_collective_io(&ctg_io_info, type_info, mpi_buf_count, file_type_array[i], - mem_type_array[i]) < 0) + if (H5D__final_collective_io(&ctg_io_info, type_info, mpi_buf_count, file_type, mem_type) < 0) HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish MPI-IO") + /* Free up resources in anticipation of following collective operation */ + if (have_chunk_to_process && chunk_list[i].buf) { + H5MM_free(chunk_list[i].buf); + chunk_list[i].buf = NULL; + } + /* Participate in the collective re-insertion of all chunks modified * in this iteration into the chunk index */ - for (j = 0; j < collective_chunk_list_num_entries; j++) { - udata.chunk_block = collective_chunk_list[j].chunk_states.new_chunk; - udata.common.scaled = collective_chunk_list[j].scaled; - udata.chunk_idx = collective_chunk_list[j].index; - - if ((index_info.storage->ops->insert)(&index_info, &udata, io_info->dset) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, - "unable to insert chunk address into index") - } /* end for */ + if (H5D__mpio_collective_filtered_chunk_reinsert(have_chunk_to_process ? &chunk_list[i] : NULL, + have_chunk_to_process ? 1 : 0, NULL, io_info, + &index_info, mpi_rank, mpi_size) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, + "couldn't collectively re-insert modified chunks into chunk index") + + /* Free the MPI types, if they were derived */ + if (mem_type_is_derived && MPI_SUCCESS != (mpi_code = MPI_Type_free(&mem_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + mem_type_is_derived = FALSE; + if (file_type_is_derived && MPI_SUCCESS != (mpi_code = MPI_Type_free(&file_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + file_type_is_derived = FALSE; + } /* end for */ + } - if (collective_chunk_list) { - H5MM_free(collective_chunk_list); - collective_chunk_list = NULL; - } /* end if */ - if (has_chunk_selected_array) { - H5MM_free(has_chunk_selected_array); - has_chunk_selected_array = NULL; - } /* end if */ - } /* end for */ +done: + /* Free the MPI buf and file types, if they were derived */ + if (mem_type_is_derived && MPI_SUCCESS != (mpi_code = MPI_Type_free(&mem_type))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + if (file_type_is_derived && MPI_SUCCESS != (mpi_code = MPI_Type_free(&file_type))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) - /* Free the MPI file and memory types, if they were derived */ - for (i = 0; i < max_num_chunks; i++) { - if (file_type_is_derived_array[i]) - if (MPI_SUCCESS != (mpi_code = MPI_Type_free(&file_type_array[i]))) - HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + if (chunk_msg_bufs) { + for (i = 0; i < (size_t)chunk_msg_bufs_len; i++) + H5MM_free(chunk_msg_bufs[i]); - if (mem_type_is_derived_array[i]) - if (MPI_SUCCESS != (mpi_code = MPI_Type_free(&mem_type_array[i]))) - HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) - } /* end for */ - } /* end else */ + H5MM_free(chunk_msg_bufs); + } -done: + HASH_CLEAR(hh, chunk_hash_table); + + /* Free resources used by a rank which had some selection */ if (chunk_list) { for (i = 0; i < chunk_list_num_entries; i++) if (chunk_list[i].buf) @@ -2019,16 +2350,10 @@ done: H5MM_free(chunk_list); } /* end if */ - if (collective_chunk_list) - H5MM_free(collective_chunk_list); - if (file_type_array) - H5MM_free(file_type_array); - if (mem_type_array) - H5MM_free(mem_type_array); - if (file_type_is_derived_array) - H5MM_free(file_type_is_derived_array); - if (mem_type_is_derived_array) - H5MM_free(mem_type_is_derived_array); +#ifdef H5Dmpio_DEBUG + H5D_MPIO_TIME_STOP(mpi_rank); + H5D_MPIO_TRACE_EXIT(mpi_rank); +#endif FUNC_LEAVE_NOAPI(ret_value) } /* end H5D__multi_chunk_filtered_collective_io() */ @@ -2054,11 +2379,22 @@ H5D__inter_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_inf 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 */ +#ifdef H5Dmpio_DEBUG + int mpi_rank; +#endif + herr_t ret_value = SUCCEED; /* return value */ FUNC_ENTER_STATIC +#ifdef H5Dmpio_DEBUG + mpi_rank = H5F_mpi_get_rank(io_info->dset->oloc.file); + H5D_MPIO_TRACE_ENTER(mpi_rank); + H5D_MPIO_TIME_START(mpi_rank, "Inter collective I/O"); + if (mpi_rank < 0) + HGOTO_ERROR(H5E_IO, H5E_MPI, FAIL, "unable to obtain MPI rank") +#endif + if ((file_space != NULL) && (mem_space != NULL)) { int mpi_file_count; /* Number of file "objects" to transfer */ hsize_t *permute_map = NULL; /* array that holds the mapping from the old, @@ -2117,9 +2453,8 @@ H5D__inter_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_inf mft_is_derived = FALSE; } /* end else */ -#ifdef H5D_DEBUG - if (H5DEBUG(D)) - HDfprintf(H5DEBUG(D), "before final collective IO \n"); +#ifdef H5Dmpio_DEBUG + H5D_MPIO_DEBUG(mpi_rank, "before final collective I/O"); #endif /* Perform final collective I/O operation */ @@ -2133,9 +2468,10 @@ done: if (mft_is_derived && MPI_SUCCESS != (mpi_code = MPI_Type_free(&mpi_file_type))) HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) -#ifdef H5D_DEBUG - if (H5DEBUG(D)) - HDfprintf(H5DEBUG(D), "before leaving inter_collective_io ret_value = %d\n", ret_value); +#ifdef H5Dmpio_DEBUG + H5D_MPIO_TIME_STOP(mpi_rank); + H5D_MPIO_DEBUG_VA(mpi_rank, "before leaving inter_collective_io ret_value = %d", ret_value); + H5D_MPIO_TRACE_EXIT(mpi_rank); #endif FUNC_LEAVE_NOAPI(ret_value) @@ -2157,10 +2493,21 @@ static herr_t H5D__final_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t mpi_buf_count, MPI_Datatype mpi_file_type, MPI_Datatype mpi_buf_type) { +#ifdef H5Dmpio_DEBUG + int mpi_rank; +#endif herr_t ret_value = SUCCEED; FUNC_ENTER_STATIC +#ifdef H5Dmpio_DEBUG + mpi_rank = H5F_mpi_get_rank(io_info->dset->oloc.file); + H5D_MPIO_TRACE_ENTER(mpi_rank); + H5D_MPIO_TIME_START(mpi_rank, "Final collective I/O"); + if (mpi_rank < 0) + HGOTO_ERROR(H5E_IO, H5E_MPI, FAIL, "unable to obtain MPI rank") +#endif + /* Pass buf type, file type to the file driver. */ if (H5CX_set_mpi_coll_datatypes(mpi_buf_type, mpi_file_type) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set MPI-I/O collective I/O datatypes") @@ -2175,10 +2522,12 @@ H5D__final_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_inf } /* end else */ done: -#ifdef H5D_DEBUG - if (H5DEBUG(D)) - HDfprintf(H5DEBUG(D), "ret_value before leaving final_collective_io=%d\n", ret_value); +#ifdef H5Dmpio_DEBUG + H5D_MPIO_TIME_STOP(mpi_rank); + H5D_MPIO_DEBUG_VA(mpi_rank, "ret_value before leaving final_collective_io=%d", ret_value); + H5D_MPIO_TRACE_EXIT(mpi_rank); #endif + FUNC_LEAVE_NOAPI(ret_value) } /* end H5D__final_collective_io */ @@ -2220,62 +2569,149 @@ H5D__cmp_chunk_addr(const void *chunk_addr_info1, const void *chunk_addr_info2) * * Return: -1, 0, 1 * - * Programmer: Jordan Henderson - * Wednesday, Nov. 30th, 2016 - * *------------------------------------------------------------------------- */ static int H5D__cmp_filtered_collective_io_info_entry(const void *filtered_collective_io_info_entry1, const void *filtered_collective_io_info_entry2) { - haddr_t addr1 = HADDR_UNDEF, addr2 = HADDR_UNDEF; + const H5D_filtered_collective_io_info_t *entry1; + const H5D_filtered_collective_io_info_t *entry2; + haddr_t addr1 = HADDR_UNDEF; + haddr_t addr2 = HADDR_UNDEF; + int ret_value; FUNC_ENTER_STATIC_NOERR - addr1 = ((const H5D_filtered_collective_io_info_t *)filtered_collective_io_info_entry1) - ->chunk_states.new_chunk.offset; - addr2 = ((const H5D_filtered_collective_io_info_t *)filtered_collective_io_info_entry2) - ->chunk_states.new_chunk.offset; + entry1 = (const H5D_filtered_collective_io_info_t *)filtered_collective_io_info_entry1; + entry2 = (const H5D_filtered_collective_io_info_t *)filtered_collective_io_info_entry2; - FUNC_LEAVE_NOAPI(H5F_addr_cmp(addr1, addr2)) -} /* end H5D__cmp_filtered_collective_io_info_entry() */ + addr1 = entry1->chunk_new.offset; + addr2 = entry2->chunk_new.offset; + + /* + * If both chunk addresses are defined, H5F_addr_cmp is safe to use. + * Otherwise, if both addresses aren't defined, compared chunk + * entries based on their chunk index. Finally, if only one chunk + * address is defined, return the appropriate value based on which + * is defined. + */ + if (H5F_addr_defined(addr1) && H5F_addr_defined(addr2)) { + ret_value = H5F_addr_cmp(addr1, addr2); + } + else if (!H5F_addr_defined(addr1) && !H5F_addr_defined(addr2)) { + hsize_t chunk_idx1 = entry1->index_info.chunk_idx; + hsize_t chunk_idx2 = entry2->index_info.chunk_idx; -#if MPI_VERSION >= 3 + ret_value = (chunk_idx1 > chunk_idx2) - (chunk_idx1 < chunk_idx2); + } + else + ret_value = H5F_addr_defined(addr1) ? 1 : -1; + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D__cmp_filtered_collective_io_info_entry() */ /*------------------------------------------------------------------------- - * Function: H5D__cmp_filtered_collective_io_info_entry_owner + * Function: H5D__cmp_chunk_redistribute_info * - * Purpose: Routine to compare filtered collective chunk io info - * entries's original owner fields + * Purpose: Routine to compare two H5D_chunk_redistribute_info_t + * structures * - * Description: Callback for qsort() to compare filtered collective chunk - * io info entries's original owner fields + * Description: Callback for qsort() to compare two + * H5D_chunk_redistribute_info_t structures + * + * Return: -1, 0, 1 + * + *------------------------------------------------------------------------- + */ +static int +H5D__cmp_chunk_redistribute_info(const void *_entry1, const void *_entry2) +{ + const H5D_chunk_redistribute_info_t *entry1; + const H5D_chunk_redistribute_info_t *entry2; + hsize_t chunk_index1; + hsize_t chunk_index2; + int ret_value; + + FUNC_ENTER_STATIC_NOERR + + entry1 = (const H5D_chunk_redistribute_info_t *)_entry1; + entry2 = (const H5D_chunk_redistribute_info_t *)_entry2; + + chunk_index1 = entry1->chunk_idx; + chunk_index2 = entry2->chunk_idx; + + if (chunk_index1 == chunk_index2) { + int orig_owner1 = entry1->orig_owner; + int orig_owner2 = entry2->orig_owner; + + ret_value = (orig_owner1 > orig_owner2) - (orig_owner1 < orig_owner2); + } + else + ret_value = (chunk_index1 > chunk_index2) - (chunk_index1 < chunk_index2); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D__cmp_chunk_redistribute_info() */ + +/*------------------------------------------------------------------------- + * Function: H5D__cmp_chunk_redistribute_info_orig_owner * - * Return: The difference between the two - * H5D_filtered_collective_io_info_t's original owner fields + * Purpose: Routine to compare the original owning MPI rank for two + * H5D_chunk_redistribute_info_t structures * - * Programmer: Jordan Henderson - * Monday, Apr. 10th, 2017 + * Description: Callback for qsort() to compare the original owning MPI + * rank for two H5D_chunk_redistribute_info_t + * structures + * + * Return: -1, 0, 1 * *------------------------------------------------------------------------- */ static int -H5D__cmp_filtered_collective_io_info_entry_owner(const void *filtered_collective_io_info_entry1, - const void *filtered_collective_io_info_entry2) +H5D__cmp_chunk_redistribute_info_orig_owner(const void *_entry1, const void *_entry2) { - int owner1 = -1, owner2 = -1; + const H5D_chunk_redistribute_info_t *entry1; + const H5D_chunk_redistribute_info_t *entry2; + int owner1 = -1; + int owner2 = -1; + int ret_value; FUNC_ENTER_STATIC_NOERR - owner1 = ((const H5D_filtered_collective_io_info_t *)filtered_collective_io_info_entry1) - ->owners.original_owner; - owner2 = ((const H5D_filtered_collective_io_info_t *)filtered_collective_io_info_entry2) - ->owners.original_owner; + entry1 = (const H5D_chunk_redistribute_info_t *)_entry1; + entry2 = (const H5D_chunk_redistribute_info_t *)_entry2; - FUNC_LEAVE_NOAPI(owner1 - owner2) -} /* end H5D__cmp_filtered_collective_io_info_entry_owner() */ -#endif + owner1 = entry1->orig_owner; + owner2 = entry2->orig_owner; + + if (owner1 == owner2) { + haddr_t addr1 = entry1->chunk_block.offset; + haddr_t addr2 = entry2->chunk_block.offset; + + /* + * If both chunk addresses are defined, H5F_addr_cmp is safe to use. + * Otherwise, if both addresses aren't defined, compared chunk + * entries based on their chunk index. Finally, if only one chunk + * address is defined, return the appropriate value based on which + * is defined. + */ + if (H5F_addr_defined(addr1) && H5F_addr_defined(addr2)) { + ret_value = H5F_addr_cmp(addr1, addr2); + } + else if (!H5F_addr_defined(addr1) && !H5F_addr_defined(addr2)) { + hsize_t chunk_idx1 = entry1->chunk_idx; + hsize_t chunk_idx2 = entry2->chunk_idx; + + ret_value = (chunk_idx1 > chunk_idx2) - (chunk_idx1 < chunk_idx2); + } + else + ret_value = H5F_addr_defined(addr1) ? 1 : -1; + } + else + ret_value = (owner1 > owner2) - (owner1 < owner2); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D__cmp_chunk_redistribute_info_orig_owner() */ /*------------------------------------------------------------------------- * Function: H5D__sort_chunk @@ -2304,26 +2740,24 @@ H5D__cmp_filtered_collective_io_info_entry_owner(const void *filtered_collective */ static herr_t H5D__sort_chunk(H5D_io_info_t *io_info, const H5D_chunk_map_t *fm, - H5D_chunk_addr_info_t chunk_addr_info_array[], int sum_chunk) + H5D_chunk_addr_info_t chunk_addr_info_array[], int sum_chunk, int mpi_rank, int mpi_size) { - H5SL_node_t * chunk_node; /* Current node in chunk skip list */ - H5D_chunk_info_t *chunk_info; /* Current chunking info. of this node. */ - haddr_t chunk_addr; /* Current chunking address of this node */ - haddr_t *total_chunk_addr_array = NULL; /* The array of chunk address for the total number of chunk */ - hbool_t do_sort = FALSE; /* Whether the addresses need to be sorted */ - int bsearch_coll_chunk_threshold; - int many_chunk_opt = H5D_OBTAIN_ONE_CHUNK_ADDR_IND; - int mpi_size; /* Number of MPI processes */ - int mpi_code; /* MPI return code */ - int i; /* Local index variable */ - herr_t ret_value = SUCCEED; /* Return value */ + H5SL_node_t * chunk_node; /* Current node in chunk skip list */ + H5D_chunk_info_t *chunk_info; /* Current chunking info. of this node. */ + haddr_t chunk_addr; /* Current chunking address of this node */ + haddr_t *total_chunk_addr_array = NULL; /* The array of chunk address for the total number of chunk */ + H5P_coll_md_read_flag_t md_reads_file_flag; + hbool_t md_reads_context_flag; + hbool_t restore_md_reads_state = FALSE; + hbool_t do_sort = FALSE; /* Whether the addresses need to be sorted */ + int bsearch_coll_chunk_threshold; + int many_chunk_opt = H5D_OBTAIN_ONE_CHUNK_ADDR_IND; + int mpi_code; /* MPI return code */ + int i; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC - /* Retrieve # of MPI processes */ - if ((mpi_size = H5F_mpi_get_size(io_info->dset->oloc.file)) < 0) - HGOTO_ERROR(H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi size") - /* Calculate the actual threshold to obtain all chunk addresses collectively * The bigger this number is, the more possible the use of obtaining chunk * address collectively. @@ -2337,31 +2771,56 @@ H5D__sort_chunk(H5D_io_info_t *io_info, const H5D_chunk_map_t *fm, ((sum_chunk / mpi_size) >= H5D_ALL_CHUNK_ADDR_THRES_COL_NUM)) many_chunk_opt = H5D_OBTAIN_ALL_CHUNK_ADDR_COL; -#ifdef H5D_DEBUG - if (H5DEBUG(D)) - HDfprintf(H5DEBUG(D), "many_chunk_opt= %d\n", many_chunk_opt); +#ifdef H5Dmpio_DEBUG + H5D_MPIO_DEBUG_VA(mpi_rank, "many_chunk_opt = %d", many_chunk_opt); #endif /* If we need to optimize the way to obtain the chunk address */ if (many_chunk_opt != H5D_OBTAIN_ONE_CHUNK_ADDR_IND) { - int mpi_rank; - -#ifdef H5D_DEBUG - if (H5DEBUG(D)) - HDfprintf(H5DEBUG(D), "Coming inside H5D_OBTAIN_ALL_CHUNK_ADDR_COL\n"); +#ifdef H5Dmpio_DEBUG + H5D_MPIO_DEBUG(mpi_rank, "Coming inside H5D_OBTAIN_ALL_CHUNK_ADDR_COL"); #endif /* Allocate array for chunk addresses */ if (NULL == (total_chunk_addr_array = (haddr_t *)H5MM_malloc(sizeof(haddr_t) * (size_t)fm->layout->u.chunk.nchunks))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory chunk address array") - /* Retrieve all the chunk addresses with process 0 */ - if ((mpi_rank = H5F_mpi_get_rank(io_info->dset->oloc.file)) < 0) - HGOTO_ERROR(H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi rank") - if (mpi_rank == 0) { - if (H5D__chunk_addrmap(io_info, total_chunk_addr_array) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk address") + herr_t result; + + /* + * If enabled, disable collective metadata reads here. + * Since the chunk address mapping is done on rank 0 + * only here, it will cause problems if collective + * metadata reads are enabled. + */ + if (H5F_get_coll_metadata_reads(io_info->dset->oloc.file)) { + md_reads_file_flag = H5P_FORCE_FALSE; + md_reads_context_flag = FALSE; + H5F_set_coll_metadata_reads(io_info->dset->oloc.file, &md_reads_file_flag, + &md_reads_context_flag); + restore_md_reads_state = TRUE; + } + + result = H5D__chunk_addrmap(io_info, total_chunk_addr_array); + + /* Ensure that we restore the old collective metadata reads state */ + if (restore_md_reads_state) { + H5F_set_coll_metadata_reads(io_info->dset->oloc.file, &md_reads_file_flag, + &md_reads_context_flag); + restore_md_reads_state = FALSE; + } + + if (result < 0) { + size_t u; + + /* Clear total chunk address array */ + for (u = 0; u < (size_t)fm->layout->u.chunk.nchunks; u++) + total_chunk_addr_array[u] = HADDR_UNDEF; + + /* Push error, but still participate in following MPI_Bcast */ + HDONE_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk address") + } } /* end if */ /* Broadcasting the MPI_IO option info. and chunk address info. */ @@ -2405,10 +2864,10 @@ H5D__sort_chunk(H5D_io_info_t *io_info, const H5D_chunk_map_t *fm, chunk_node = H5SL_next(chunk_node); } /* end while */ -#ifdef H5D_DEBUG - if (H5DEBUG(D)) - HDfprintf(H5DEBUG(D), "before Qsort\n"); +#ifdef H5Dmpio_DEBUG + H5D_MPIO_DEBUG(mpi_rank, "before Qsort"); #endif + if (do_sort) { size_t num_chunks = H5SL_count(fm->sel_chunks); @@ -2416,6 +2875,10 @@ H5D__sort_chunk(H5D_io_info_t *io_info, const H5D_chunk_map_t *fm, } /* end if */ done: + /* Re-enable collective metadata reads if we disabled them */ + if (restore_md_reads_state) + H5F_set_coll_metadata_reads(io_info->dset->oloc.file, &md_reads_file_flag, &md_reads_context_flag); + if (total_chunk_addr_array) H5MM_xfree(total_chunk_addr_array); @@ -2432,7 +2895,7 @@ done: * * 1) Each process provides two piece of information for all chunks having selection * a) chunk index - * b) wheather this chunk is regular(for MPI derived datatype not working case) + * b) whether this chunk is regular(for MPI derived datatype not working case) * * 2) Gather all the information to the root process * @@ -2461,22 +2924,24 @@ done: */ static herr_t H5D__obtain_mpio_mode(H5D_io_info_t *io_info, H5D_chunk_map_t *fm, uint8_t assign_io_mode[], - haddr_t chunk_addr[]) + haddr_t chunk_addr[], int mpi_rank, int mpi_size) { - size_t total_chunks; - unsigned percent_nproc_per_chunk, threshold_nproc_per_chunk; - uint8_t * io_mode_info = NULL; - uint8_t * recv_io_mode_info = NULL; - uint8_t * mergebuf = NULL; - uint8_t * tempbuf; - H5SL_node_t * chunk_node; - H5D_chunk_info_t *chunk_info; - int mpi_size, mpi_rank; - MPI_Comm comm; - int root; - size_t ic; - int mpi_code; - herr_t ret_value = SUCCEED; + size_t total_chunks; + unsigned percent_nproc_per_chunk, threshold_nproc_per_chunk; + uint8_t * io_mode_info = NULL; + uint8_t * recv_io_mode_info = NULL; + uint8_t * mergebuf = NULL; + uint8_t * tempbuf; + H5SL_node_t * chunk_node; + H5D_chunk_info_t * chunk_info; + H5P_coll_md_read_flag_t md_reads_file_flag; + hbool_t md_reads_context_flag; + hbool_t restore_md_reads_state = FALSE; + MPI_Comm comm; + int root; + size_t ic; + int mpi_code; + herr_t ret_value = SUCCEED; FUNC_ENTER_STATIC @@ -2484,12 +2949,6 @@ H5D__obtain_mpio_mode(H5D_io_info_t *io_info, H5D_chunk_map_t *fm, uint8_t assig root = 0; comm = io_info->comm; - /* Obtain the number of process and the current rank of the process */ - if ((mpi_rank = H5F_mpi_get_rank(io_info->dset->oloc.file)) < 0) - HGOTO_ERROR(H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi rank") - if ((mpi_size = H5F_mpi_get_size(io_info->dset->oloc.file)) < 0) - HGOTO_ERROR(H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi size") - /* Setup parameters */ H5_CHECKED_ASSIGN(total_chunks, size_t, fm->layout->u.chunk.nchunks, hsize_t); if (H5CX_get_mpio_chunk_opt_ratio(&percent_nproc_per_chunk) < 0) @@ -2536,6 +2995,20 @@ H5D__obtain_mpio_mode(H5D_io_info_t *io_info, H5D_chunk_map_t *fm, uint8_t assig size_t nproc; unsigned *nproc_per_chunk; + /* + * If enabled, disable collective metadata reads here. + * Since the chunk address mapping is done on rank 0 + * only here, it will cause problems if collective + * metadata reads are enabled. + */ + if (H5F_get_coll_metadata_reads(io_info->dset->oloc.file)) { + md_reads_file_flag = H5P_FORCE_FALSE; + md_reads_context_flag = FALSE; + H5F_set_coll_metadata_reads(io_info->dset->oloc.file, &md_reads_file_flag, + &md_reads_context_flag); + restore_md_reads_state = TRUE; + } + /* pre-computing: calculate number of processes and regularity of the selection occupied in each chunk */ if (NULL == (nproc_per_chunk = (unsigned *)H5MM_calloc(total_chunks * sizeof(unsigned)))) @@ -2602,6 +3075,10 @@ H5D__obtain_mpio_mode(H5D_io_info_t *io_info, H5D_chunk_map_t *fm, uint8_t assig #endif done: + /* Re-enable collective metadata reads if we disabled them */ + if (restore_md_reads_state) + H5F_set_coll_metadata_reads(io_info->dset->oloc.file, &md_reads_file_flag, &md_reads_context_flag); + if (io_mode_info) H5MM_free(io_mode_info); if (mergebuf) @@ -2615,34 +3092,32 @@ done: } /* end H5D__obtain_mpio_mode() */ /*------------------------------------------------------------------------- - * Function: H5D__construct_filtered_io_info_list + * Function: H5D__mpio_collective_filtered_chunk_io_setup * * Purpose: Constructs a list of entries which contain the necessary * information for inter-process communication when performing * collective io on filtered chunks. This list is used by - * each process when performing I/O on locally selected chunks - * and also in operations that must be collectively done - * on every chunk, such as chunk re-allocation, insertion of - * chunks into the chunk index, etc. + * each MPI rank when performing I/O on locally selected + * chunks and also in operations that must be collectively + * done on every chunk, such as chunk re-allocation, insertion + * of chunks into the chunk index, etc. * * Return: Non-negative on success/Negative on failure * - * Programmer: Jordan Henderson - * Tuesday, January 10th, 2017 - * *------------------------------------------------------------------------- */ static herr_t -H5D__construct_filtered_io_info_list(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info, - const H5D_chunk_map_t * fm, - H5D_filtered_collective_io_info_t **chunk_list, size_t *num_entries) +H5D__mpio_collective_filtered_chunk_io_setup(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info, + const H5D_chunk_map_t * fm, + H5D_filtered_collective_io_info_t **chunk_list, + size_t *num_entries, int mpi_rank) { - H5D_filtered_collective_io_info_t *local_info_array = - NULL; /* The list of initially selected chunks for this process */ - size_t num_chunks_selected; - size_t i; - int mpi_rank; - herr_t ret_value = SUCCEED; + H5D_filtered_collective_io_info_t *local_info_array = NULL; + H5D_chunk_ud_t udata; + hbool_t filter_partial_edge_chunks; + size_t num_chunks_selected; + size_t i; + herr_t ret_value = SUCCEED; FUNC_ENTER_STATIC @@ -2652,19 +3127,23 @@ H5D__construct_filtered_io_info_list(const H5D_io_info_t *io_info, const H5D_typ HDassert(chunk_list); HDassert(num_entries); - if ((mpi_rank = H5F_mpi_get_rank(io_info->dset->oloc.file)) < 0) - HGOTO_ERROR(H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi rank") +#ifdef H5Dmpio_DEBUG + H5D_MPIO_TRACE_ENTER(mpi_rank); + H5D_MPIO_TIME_START(mpi_rank, "Filtered Collective I/O Setup"); +#endif - /* Each process builds a local list of the chunks they have selected */ + /* Each rank builds a local list of the chunks they have selected */ if ((num_chunks_selected = H5SL_count(fm->sel_chunks))) { H5D_chunk_info_t *chunk_info; - H5D_chunk_ud_t udata; H5SL_node_t * chunk_node; hsize_t select_npoints; - hssize_t chunk_npoints; + hbool_t need_sort = FALSE; - if (NULL == (local_info_array = (H5D_filtered_collective_io_info_t *)H5MM_malloc( - num_chunks_selected * sizeof(H5D_filtered_collective_io_info_t)))) + /* Determine whether partial edge chunks should be filtered */ + filter_partial_edge_chunks = !(io_info->dset->shared->layout.u.chunk.flags & + H5O_LAYOUT_CHUNK_DONT_FILTER_PARTIAL_BOUND_CHUNKS); + + if (NULL == (local_info_array = H5MM_malloc(num_chunks_selected * sizeof(*local_info_array)))) HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate local io info array buffer") chunk_node = H5SL_first(fm->sel_chunks); @@ -2675,275 +3154,787 @@ H5D__construct_filtered_io_info_list(const H5D_io_info_t *io_info, const H5D_typ if (H5D__chunk_lookup(io_info->dset, chunk_info->scaled, &udata) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address") - local_info_array[i].index = chunk_info->index; - local_info_array[i].chunk_states.chunk_current = local_info_array[i].chunk_states.new_chunk = - udata.chunk_block; - local_info_array[i].num_writers = 0; - local_info_array[i].owners.original_owner = local_info_array[i].owners.new_owner = mpi_rank; - local_info_array[i].buf = NULL; - - local_info_array[i].async_info.num_receive_requests = 0; - local_info_array[i].async_info.receive_buffer_array = NULL; - local_info_array[i].async_info.receive_requests_array = NULL; - - H5MM_memcpy(local_info_array[i].scaled, chunk_info->scaled, sizeof(chunk_info->scaled)); - - select_npoints = H5S_GET_SELECT_NPOINTS(chunk_info->mspace); - local_info_array[i].io_size = (size_t)select_npoints * type_info->src_type_size; - - /* Currently the full overwrite status of a chunk is only obtained on a per-process - * basis. This means that if the total selection in the chunk, as determined by the combination - * of selections of all of the processes interested in the chunk, covers the entire chunk, - * the performance optimization of not reading the chunk from the file is still valid, but - * is not applied in the current implementation. Something like an appropriately placed - * MPI_Allreduce or a running total of the number of chunk points selected during chunk - * redistribution should suffice for implementing this case - JTH. + /* Initialize rank-local chunk info */ + local_info_array[i].chunk_info = chunk_info; + local_info_array[i].chunk_buf_size = 0; + local_info_array[i].num_writers = 0; + local_info_array[i].orig_owner = mpi_rank; + local_info_array[i].new_owner = mpi_rank; + local_info_array[i].buf = NULL; + + select_npoints = H5S_GET_SELECT_NPOINTS(chunk_info->fspace); + local_info_array[i].io_size = (size_t)select_npoints * type_info->dst_type_size; + + /* + * Determine whether this chunk will need to be read from the file. If this is + * a read operation, the chunk will be read. If this is a write operation, we + * generally need to read a filtered chunk from the file before modifying it, + * unless the chunk is being fully overwritten. + * + * TODO: Currently the full overwrite status of a chunk is only obtained on a + * per-rank basis. This means that if the total selection in the chunk, as + * determined by the combination of selections of all of the ranks interested in + * the chunk, covers the entire chunk, the performance optimization of not reading + * the chunk from the file is still valid, but is not applied in the current + * implementation. + * + * To implement this case, a few approaches were considered: + * + * - Keep a running total (distributed to each rank) of the number of chunk + * elements selected during chunk redistribution and compare that to the total + * number of elements in the chunk once redistribution is finished + * + * - Process all incoming chunk messages before doing I/O (these are currently + * processed AFTER doing I/O), combine the owning rank's selection in a chunk + * with the selections received from other ranks and check to see whether that + * combined selection covers the entire chunk + * + * The first approach will be dangerous if the application performs an overlapping + * write to a chunk, as the number of selected elements can equal or exceed the + * number of elements in the chunk without the whole chunk selection being covered. + * While it might be considered erroneous for an application to do an overlapping + * write, we don't explicitly disallow it. + * + * The second approach contains a bit of complexity in that part of the chunk + * messages will be needed before doing I/O and part will be needed after doing I/O. + * Since modification data from chunk messages can't be applied until after any I/O + * is performed (otherwise, we'll overwrite any applied modification data), chunk + * messages are currently entirely processed after I/O. However, in order to determine + * if a chunk is being fully overwritten, we need the dataspace portion of the chunk + * messages before doing I/O. The naive way to do this is to process chunk messages + * twice, using just the relevant information from the message before and after I/O. + * The better way would be to avoid processing chunk messages twice by extracting (and + * keeping around) the dataspace portion of the message before I/O and processing the + * rest of the chunk message after I/O. Note that the dataspace portion of each chunk + * message is used to correctly apply chunk modification data from the message, so + * must be kept around both before and after I/O in this case. + */ + if (io_info->op_type == H5D_IO_OP_READ) + local_info_array[i].need_read = TRUE; + else { + local_info_array[i].need_read = + local_info_array[i].io_size < (size_t)io_info->dset->shared->layout.u.chunk.size; + } + + local_info_array[i].skip_filter_pline = FALSE; + if (!filter_partial_edge_chunks) { + /* + * If this is a partial edge chunk and the "don't filter partial edge + * chunks" flag is set, make sure not to apply filters to the chunk. + */ + if (H5D__chunk_is_partial_edge_chunk(io_info->dset->shared->ndims, + io_info->dset->shared->layout.u.chunk.dim, + chunk_info->scaled, io_info->dset->shared->curr_dims)) + local_info_array[i].skip_filter_pline = TRUE; + } + + /* Initialize the chunk's shared info */ + local_info_array[i].chunk_current = udata.chunk_block; + local_info_array[i].chunk_new = udata.chunk_block; + + /* + * Check if the list is not in ascending order of offset in the file + * or has unallocated chunks. In either case, the list should get + * sorted. + */ + if (i) { + haddr_t curr_chunk_offset = local_info_array[i].chunk_current.offset; + haddr_t prev_chunk_offset = local_info_array[i - 1].chunk_current.offset; + + if (!H5F_addr_defined(prev_chunk_offset) || !H5F_addr_defined(curr_chunk_offset) || + (curr_chunk_offset < prev_chunk_offset)) + need_sort = TRUE; + } + + /* + * Extensible arrays may calculate a chunk's index a little differently + * than normal when the dataset's unlimited dimension is not the + * slowest-changing dimension, so set the index here based on what the + * extensible array code calculated instead of what was calculated + * in the chunk file mapping. */ - if ((chunk_npoints = H5S_GET_EXTENT_NPOINTS(chunk_info->fspace)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTCOUNT, FAIL, "dataspace is invalid") - local_info_array[i].full_overwrite = - (local_info_array[i].io_size >= (hsize_t)chunk_npoints * type_info->dst_type_size) ? TRUE - : FALSE; + if (io_info->dset->shared->layout.u.chunk.idx_type == H5D_CHUNK_IDX_EARRAY) + local_info_array[i].index_info.chunk_idx = udata.chunk_idx; + else + local_info_array[i].index_info.chunk_idx = chunk_info->index; + + local_info_array[i].index_info.filter_mask = udata.filter_mask; + local_info_array[i].index_info.need_insert = FALSE; chunk_node = H5SL_next(chunk_node); - } /* end for */ - } /* end if */ - - /* Redistribute shared chunks to new owners as necessary */ - if (io_info->op_type == H5D_IO_OP_WRITE) -#if MPI_VERSION >= 3 - if (H5D__chunk_redistribute_shared_chunks(io_info, type_info, fm, local_info_array, - &num_chunks_selected) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to redistribute shared chunks") -#else - HGOTO_ERROR( - H5E_DATASET, H5E_WRITEERROR, FAIL, - "unable to redistribute shared chunks - MPI version < 3 (MPI_Mprobe and MPI_Imrecv missing)") + } + + /* Ensure the chunk list is sorted in ascending order of offset in the file */ + if (need_sort) + HDqsort(local_info_array, num_chunks_selected, sizeof(H5D_filtered_collective_io_info_t), + H5D__cmp_filtered_collective_io_info_entry); + +#ifdef H5Dmpio_DEBUG + H5D__mpio_dump_collective_filtered_chunk_list(local_info_array, num_chunks_selected, mpi_rank); #endif + } + else if (H5F_get_coll_metadata_reads(io_info->dset->oloc.file)) { + hsize_t scaled[H5O_LAYOUT_NDIMS] = {0}; + + /* + * If this rank has no selection in the dataset and collective + * metadata reads are enabled, do a fake lookup of a chunk to + * ensure that this rank has the chunk index opened. Otherwise, + * only the ranks that had a selection will have opened the + * chunk index and they will have done so independently. Therefore, + * when ranks with no selection participate in later collective + * metadata reads, they will try to open the chunk index collectively + * and issues will occur since other ranks won't participate. + * + * In the future, we should consider having a chunk index "open" + * callback that can be used to ensure collectivity between ranks + * in a more natural way, but this hack should suffice for now. + */ + if (H5D__chunk_lookup(io_info->dset, scaled, &udata) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address") + } *chunk_list = local_info_array; *num_entries = num_chunks_selected; done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5D__construct_filtered_io_info_list() */ +#ifdef H5Dmpio_DEBUG + H5D_MPIO_TIME_STOP(mpi_rank); + H5D_MPIO_TRACE_EXIT(mpi_rank); +#endif -#if MPI_VERSION >= 3 + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D__mpio_collective_filtered_chunk_io_setup() */ /*------------------------------------------------------------------------- - * Function: H5D__chunk_redistribute_shared_chunks - * - * Purpose: When performing a collective write on a Dataset with - * filters applied, this function is used to redistribute any - * chunks which are selected by more than one process, so as - * to preserve file integrity after the write by ensuring - * that any shared chunks are only modified by one process. - * - * The current implementation follows this 3-phase process: - * - * - Collect everyone's list of chunks into one large list, - * sort the list in increasing order of chunk offset in the - * file and hand the list off to rank 0 - * - * - Rank 0 scans the list looking for matching runs of chunk - * offset in the file (corresponding to a shared chunk which - * has been selected by more than one rank in the I/O - * operation) and for each shared chunk, it redistributes - * the chunk to the process writing to the chunk which - * currently has the least amount of chunks assigned to it - * by modifying the "new_owner" field in each of the list - * entries corresponding to that chunk - * - * - After the chunks have been redistributed, rank 0 re-sorts - * the list in order of previous owner so that each rank - * will get back exactly the array that they contributed to - * the redistribution operation, with the "new_owner" field - * of each chunk they are modifying having possibly been - * modified. Rank 0 then scatters each segment of the list - * back to its corresponding rank + * Function: H5D__mpio_redistribute_shared_chunks + * + * Purpose: When performing a parallel write on a chunked Dataset with + * filters applied, we must ensure that any particular chunk + * is only written to by a single MPI rank in order to avoid + * potential data races on the chunk. This function is used to + * redistribute (by assigning ownership to a single rank) any + * chunks which are selected by more than one MPI rank. + * + * An initial Allgather is performed to determine how many + * chunks each rank has selected in the write operation and + * then that number is compared against a threshold value to + * determine whether chunk redistribution should be done on + * MPI rank 0 only, or on all MPI ranks. * * Return: Non-negative on success/Negative on failure * - * Programmer: Jordan Henderson - * Monday, May 1, 2017 + *------------------------------------------------------------------------- + */ +static herr_t +H5D__mpio_redistribute_shared_chunks(H5D_filtered_collective_io_info_t *chunk_list, + size_t chunk_list_num_entries, const H5D_io_info_t *io_info, + const H5D_chunk_map_t *fm, int mpi_rank, int mpi_size, + size_t **rank_chunks_assigned_map) +{ + hbool_t redistribute_on_all_ranks; + size_t *num_chunks_map = NULL; + size_t coll_chunk_list_size = 0; + size_t i; + int mpi_code; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC + + HDassert(chunk_list || 0 == chunk_list_num_entries); + HDassert(io_info); + HDassert(fm); + HDassert(mpi_size > 1); /* No chunk sharing is possible for MPI Comm size of 1 */ + +#ifdef H5Dmpio_DEBUG + H5D_MPIO_TRACE_ENTER(mpi_rank); + H5D_MPIO_TIME_START(mpi_rank, "Redistribute shared chunks"); +#endif + + /* + * Allocate an array for each rank to keep track of the number of + * chunks assigned to any other rank in order to cut down on future + * MPI communication. + */ + if (NULL == (num_chunks_map = H5MM_malloc((size_t)mpi_size * sizeof(*num_chunks_map)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "couldn't allocate assigned chunks array") + + /* Perform initial Allgather to determine the collective chunk list size */ + if (MPI_SUCCESS != (mpi_code = MPI_Allgather(&chunk_list_num_entries, 1, H5_SIZE_T_AS_MPI_TYPE, + num_chunks_map, 1, H5_SIZE_T_AS_MPI_TYPE, io_info->comm))) + HMPI_GOTO_ERROR(FAIL, "MPI_Allgather failed", mpi_code) + + for (i = 0; i < (size_t)mpi_size; i++) + coll_chunk_list_size += num_chunks_map[i]; + + /* + * Determine whether we should perform chunk redistribution on all + * ranks or just rank 0. For a relatively small number of chunks, + * we redistribute on all ranks to cut down on MPI communication + * overhead. For a larger number of chunks, we redistribute on + * rank 0 only to cut down on memory usage. + */ + redistribute_on_all_ranks = coll_chunk_list_size < H5D_CHUNK_REDISTRIBUTE_THRES; + + if (H5D__mpio_redistribute_shared_chunks_int(chunk_list, num_chunks_map, redistribute_on_all_ranks, + io_info, fm, mpi_rank, mpi_size) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTREDISTRIBUTE, FAIL, "can't redistribute shared chunks") + + /* + * If the caller provided a pointer for the mapping from + * rank value -> number of chunks assigned, return that + * mapping here. + */ + if (rank_chunks_assigned_map) { + /* + * If we performed chunk redistribution on rank 0 only, distribute + * the rank value -> number of chunks assigned mapping back to all + * ranks. + */ + if (!redistribute_on_all_ranks) { + if (MPI_SUCCESS != + (mpi_code = MPI_Bcast(num_chunks_map, mpi_size, H5_SIZE_T_AS_MPI_TYPE, 0, io_info->comm))) + HMPI_GOTO_ERROR(FAIL, "couldn't broadcast chunk mapping to other ranks", mpi_code) + } + + *rank_chunks_assigned_map = num_chunks_map; + } + +done: + if (!rank_chunks_assigned_map || (ret_value < 0)) { + num_chunks_map = H5MM_xfree(num_chunks_map); + } + +#ifdef H5Dmpio_DEBUG + H5D_MPIO_TIME_STOP(mpi_rank); + H5D_MPIO_TRACE_EXIT(mpi_rank); +#endif + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D__mpio_redistribute_shared_chunks() */ + +/*------------------------------------------------------------------------- + * Function: H5D__mpio_redistribute_shared_chunks_int + * + * Purpose: Routine to perform redistribution of shared chunks during + * parallel writes to datasets with filters applied. + * + * If `all_ranks_involved` is TRUE, chunk redistribution + * occurs on all MPI ranks. This is usually done when there + * is a relatively small number of chunks involved in order to + * cut down on MPI communication overhead while increasing + * total memory usage a bit. + * + * If `all_ranks_involved` is FALSE, only rank 0 will perform + * chunk redistribution. This is usually done when there is + * a relatively large number of chunks involved in order to + * cut down on total memory usage at the cost of increased + * overhead from MPI communication. + * + * This implementation is as follows: + * + * - All MPI ranks send their list of selected chunks to the + * ranks involved in chunk redistribution. Then, the + * involved ranks sort this new list in order of chunk + * index. + * + * - The involved ranks scan the list looking for matching + * runs of chunk index values (corresponding to a shared + * chunk which has been selected by more than one rank in + * the I/O operation) and for each shared chunk, + * redistribute the chunk to the MPI rank writing to the + * chunk which currently has the least amount of chunks + * assigned to it. This is done by modifying the "new_owner" + * field in each of the list entries corresponding to that + * chunk. The involved ranks then re-sort the list in order + * of original chunk owner so that each rank's section of + * contributed chunks is contiguous in the collective chunk + * list. + * + * - If chunk redistribution occurred on all ranks, each rank + * scans through the collective chunk list to find their + * contributed section of chunks and uses that to update + * their local chunk list with the newly-updated "new_owner" + * and "num_writers" fields. If chunk redistribution + * occurred only on rank 0, an MPI_Scatterv operation will + * be used to scatter the segments of the collective chunk + * list from rank 0 back to the corresponding ranks. + * + * Return: Non-negative on success/Negative on failure * *------------------------------------------------------------------------- */ static herr_t -H5D__chunk_redistribute_shared_chunks(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info, - const H5D_chunk_map_t * fm, - H5D_filtered_collective_io_info_t *local_chunk_array, - size_t * local_chunk_array_num_entries) +H5D__mpio_redistribute_shared_chunks_int(H5D_filtered_collective_io_info_t *chunk_list, + size_t *num_chunks_assigned_map, hbool_t all_ranks_involved, + const H5D_io_info_t *io_info, const H5D_chunk_map_t *fm, + int mpi_rank, int mpi_size) { - H5D_filtered_collective_io_info_t *shared_chunks_info_array = - NULL; /* The list of all chunks selected in the operation by all processes */ - H5S_sel_iter_t *mem_iter = NULL; /* Memory iterator for H5D__gather_mem */ - unsigned char **mod_data = - NULL; /* Array of chunk modification data buffers sent by a process to new chunk owners */ - MPI_Request *send_requests = NULL; /* Array of MPI_Isend chunk modification data send requests */ - MPI_Status * send_statuses = NULL; /* Array of MPI_Isend chunk modification send statuses */ - hbool_t mem_iter_init = FALSE; - size_t shared_chunks_info_array_num_entries = 0; - size_t num_send_requests = 0; - size_t * num_assigned_chunks_array = NULL; - size_t i, last_assigned_idx; - int * send_counts = NULL; - int * send_displacements = NULL; - int scatter_recvcount_int; - int mpi_rank, mpi_size, mpi_code; + MPI_Datatype struct_type; + MPI_Datatype packed_type; + hbool_t struct_type_derived = FALSE; + hbool_t packed_type_derived = FALSE; + size_t i; + size_t coll_chunk_list_num_entries = 0; + void * coll_chunk_list = NULL; + int * counts_disps_array = NULL; + int * counts_ptr = NULL; + int * displacements_ptr = NULL; + int num_chunks_int; + int mpi_code; herr_t ret_value = SUCCEED; FUNC_ENTER_STATIC + HDassert(num_chunks_assigned_map); + HDassert(chunk_list || 0 == num_chunks_assigned_map[mpi_rank]); HDassert(io_info); - HDassert(type_info); HDassert(fm); - HDassert(local_chunk_array_num_entries); + HDassert(mpi_size > 1); - if ((mpi_rank = H5F_mpi_get_rank(io_info->dset->oloc.file)) < 0) - HGOTO_ERROR(H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi rank") - if ((mpi_size = H5F_mpi_get_size(io_info->dset->oloc.file)) < 0) - HGOTO_ERROR(H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi size") +#ifdef H5Dmpio_DEBUG + H5D_MPIO_TRACE_ENTER(mpi_rank); + H5D_MPIO_TIME_START(mpi_rank, "Redistribute shared chunks (internal)"); +#endif - /* Set to latest format for encoding dataspace */ - H5CX_set_libver_bounds(NULL); + /* + * Make sure it's safe to cast this rank's number + * of chunks to be sent into an int for MPI + */ + H5_CHECKED_ASSIGN(num_chunks_int, int, num_chunks_assigned_map[mpi_rank], size_t); - if (*local_chunk_array_num_entries) - if (NULL == (send_requests = - (MPI_Request *)H5MM_malloc(*local_chunk_array_num_entries * sizeof(MPI_Request)))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate send requests buffer") + /* + * Phase 1 - Participate in collective gathering of every rank's + * list of chunks to the ranks which are performing the redistribution + * operation. + */ - if (NULL == (mem_iter = (H5S_sel_iter_t *)H5MM_malloc(sizeof(H5S_sel_iter_t)))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate memory iterator") + if (all_ranks_involved || (mpi_rank == 0)) { + /* + * Allocate array to store the receive counts of each rank, as well as + * the displacements into the final array where each rank will place + * their data. The first half of the array contains the receive counts + * (in rank order), while the latter half contains the displacements + * (also in rank order). + */ + if (NULL == (counts_disps_array = H5MM_malloc(2 * (size_t)mpi_size * sizeof(*counts_disps_array)))) { + /* Push an error, but still participate in collective gather operation */ + HDONE_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "couldn't allocate receive counts and displacements array") + } + else { + /* Set the receive counts from the assigned chunks map */ + counts_ptr = counts_disps_array; + + for (i = 0; i < (size_t)mpi_size; i++) + H5_CHECKED_ASSIGN(counts_ptr[i], int, num_chunks_assigned_map[i], size_t); + + /* Set the displacements into the receive buffer for the gather operation */ + displacements_ptr = &counts_disps_array[mpi_size]; + + *displacements_ptr = 0; + for (i = 1; i < (size_t)mpi_size; i++) + displacements_ptr[i] = displacements_ptr[i - 1] + counts_ptr[i - 1]; + } + } - /* Gather every rank's list of chunks to rank 0 to allow it to perform the redistribution operation. After - * this call, the gathered list will initially be sorted in increasing order of chunk offset in the file. + /* + * Construct MPI derived types for extracting information + * necessary for MPI communication */ - if (H5D__mpio_array_gatherv(local_chunk_array, *local_chunk_array_num_entries, - sizeof(H5D_filtered_collective_io_info_t), (void **)&shared_chunks_info_array, - &shared_chunks_info_array_num_entries, false, 0, io_info->comm, - H5D__cmp_filtered_collective_io_info_entry) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGATHER, FAIL, "couldn't gather array") + if (H5D__mpio_get_chunk_redistribute_info_types(&packed_type, &packed_type_derived, &struct_type, + &struct_type_derived) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, + "can't create derived datatypes for chunk redistribution info") + + /* Perform gather operation */ + if (H5_mpio_gatherv_alloc(chunk_list, num_chunks_int, struct_type, counts_ptr, displacements_ptr, + packed_type, all_ranks_involved, 0, io_info->comm, mpi_rank, mpi_size, + &coll_chunk_list, &coll_chunk_list_num_entries) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGATHER, FAIL, + "can't gather chunk redistribution info to involved ranks") - /* Rank 0 redistributes any shared chunks to new owners as necessary */ - if (mpi_rank == 0) { - if (NULL == (send_counts = (int *)H5MM_calloc((size_t)mpi_size * sizeof(int)))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "unable to allocate send counts buffer") + /* + * If all ranks are redistributing shared chunks, we no + * longer need the receive counts and displacements array + */ + if (all_ranks_involved) { + counts_disps_array = H5MM_xfree(counts_disps_array); + } - if (NULL == (send_displacements = (int *)H5MM_malloc((size_t)mpi_size * sizeof(int)))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "unable to allocate send displacements buffer") + /* + * Phase 2 - Involved ranks now redistribute any shared chunks to new + * owners as necessary. + */ - if (NULL == (num_assigned_chunks_array = (size_t *)H5MM_calloc((size_t)mpi_size * sizeof(size_t)))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, - "unable to allocate number of assigned chunks array") + if (all_ranks_involved || (mpi_rank == 0)) { + H5D_chunk_redistribute_info_t *chunk_entry; + hsize_t curr_chunk_idx; + size_t set_begin_index; + int num_writers; + int new_chunk_owner; - for (i = 0; i < shared_chunks_info_array_num_entries;) { - H5D_filtered_collective_io_info_t *chunk_entry; - haddr_t last_seen_addr = shared_chunks_info_array[i].chunk_states.chunk_current.offset; - size_t set_begin_index = i; - size_t num_writers = 0; - int new_chunk_owner = shared_chunks_info_array[i].owners.original_owner; + /* Clear the mapping from rank value -> number of assigned chunks */ + HDmemset(num_chunks_assigned_map, 0, (size_t)mpi_size * sizeof(*num_chunks_assigned_map)); - /* Process each set of duplicate entries caused by another process writing to the same chunk */ - do { - chunk_entry = &shared_chunks_info_array[i]; + /* Sort collective chunk list according to chunk index */ + HDqsort(coll_chunk_list, coll_chunk_list_num_entries, sizeof(H5D_chunk_redistribute_info_t), + H5D__cmp_chunk_redistribute_info); - send_counts[chunk_entry->owners.original_owner] += (int)sizeof(*chunk_entry); + /* + * Process all chunks in the collective chunk list. + * Note that the loop counter is incremented by both + * the outer loop (while processing each entry in + * the collective chunk list) and the inner loop + * (while processing duplicate entries for shared + * chunks). + */ + chunk_entry = &((H5D_chunk_redistribute_info_t *)coll_chunk_list)[0]; + for (i = 0; i < coll_chunk_list_num_entries;) { + /* Set chunk's initial new owner to its original owner */ + new_chunk_owner = chunk_entry->orig_owner; + + /* + * Set the current chunk index so we know when we've processed + * all duplicate entries for a particular shared chunk + */ + curr_chunk_idx = chunk_entry->chunk_idx; + + /* Reset the initial number of writers to this chunk */ + num_writers = 0; + + /* Set index for the beginning of this section of duplicate chunk entries */ + set_begin_index = i; - /* The new owner of the chunk is determined by the process + /* + * Process each chunk entry in the set for the current + * (possibly shared) chunk and increment the loop counter + * while doing so. + */ + do { + /* + * The new owner of the chunk is determined by the rank * writing to the chunk which currently has the least amount * of chunks assigned to it */ - if (num_assigned_chunks_array[chunk_entry->owners.original_owner] < - num_assigned_chunks_array[new_chunk_owner]) - new_chunk_owner = chunk_entry->owners.original_owner; + if (num_chunks_assigned_map[chunk_entry->orig_owner] < + num_chunks_assigned_map[new_chunk_owner]) + new_chunk_owner = chunk_entry->orig_owner; + /* Update the number of writers to this particular chunk */ num_writers++; - } while (++i < shared_chunks_info_array_num_entries && - shared_chunks_info_array[i].chunk_states.chunk_current.offset == last_seen_addr); - /* Set all of the chunk entries' "new_owner" fields */ + chunk_entry++; + } while (++i < coll_chunk_list_num_entries && chunk_entry->chunk_idx == curr_chunk_idx); + + /* We should never have more writers to a chunk than the number of MPI ranks */ + HDassert(num_writers <= mpi_size); + + /* Set all processed chunk entries' "new_owner" and "num_writers" fields */ for (; set_begin_index < i; set_begin_index++) { - shared_chunks_info_array[set_begin_index].owners.new_owner = new_chunk_owner; - shared_chunks_info_array[set_begin_index].num_writers = num_writers; - } /* end for */ + H5D_chunk_redistribute_info_t *entry; - num_assigned_chunks_array[new_chunk_owner]++; - } /* end for */ + entry = &((H5D_chunk_redistribute_info_t *)coll_chunk_list)[set_begin_index]; - /* Sort the new list in order of previous owner so that each original owner of a chunk - * entry gets that entry back, with the possibly newly-modified "new_owner" field + entry->new_owner = new_chunk_owner; + entry->num_writers = num_writers; + } + + /* Update the number of chunks assigned to the MPI rank that now owns this chunk */ + num_chunks_assigned_map[new_chunk_owner]++; + } + + /* + * Re-sort the collective chunk list in order of original chunk owner + * so that each rank's section of contributed chunks is contiguous in + * the collective chunk list. + * + * NOTE: this re-sort is frail in that it needs to sort the collective + * chunk list so that each rank's section of contributed chunks + * is in the exact order it was contributed in, or things will + * be scrambled when each rank's local chunk list is updated. + * Therefore, the sorting algorithm here is tied to the one + * used during the I/O setup operation. Specifically, chunks + * are first sorted by ascending order of offset in the file and + * then by chunk index. In the future, a better redistribution + * algorithm may be devised that doesn't rely on frail sorting, + * but the current implementation is a quick and naive approach. */ - if (shared_chunks_info_array_num_entries > 1) - HDqsort(shared_chunks_info_array, shared_chunks_info_array_num_entries, - sizeof(H5D_filtered_collective_io_info_t), - H5D__cmp_filtered_collective_io_info_entry_owner); - - send_displacements[0] = 0; - for (i = 1; i < (size_t)mpi_size; i++) - send_displacements[i] = send_displacements[i - 1] + send_counts[i - 1]; - } /* end if */ + HDqsort(coll_chunk_list, coll_chunk_list_num_entries, sizeof(H5D_chunk_redistribute_info_t), + H5D__cmp_chunk_redistribute_info_orig_owner); + } - /* Scatter the segments of the list back to each process */ - H5_CHECKED_ASSIGN(scatter_recvcount_int, int, - *local_chunk_array_num_entries * sizeof(H5D_filtered_collective_io_info_t), size_t); - if (MPI_SUCCESS != - (mpi_code = MPI_Scatterv(shared_chunks_info_array, send_counts, send_displacements, MPI_BYTE, - local_chunk_array, scatter_recvcount_int, MPI_BYTE, 0, io_info->comm))) - HMPI_GOTO_ERROR(FAIL, "unable to scatter shared chunks info buffer", mpi_code) + if (all_ranks_involved) { + /* + * If redistribution occurred on all ranks, search for the section + * in the collective chunk list corresponding to this rank's locally + * selected chunks and update the local list after redistribution. + */ + for (i = 0; i < coll_chunk_list_num_entries; i++) + if (mpi_rank == ((H5D_chunk_redistribute_info_t *)coll_chunk_list)[i].orig_owner) + break; - if (shared_chunks_info_array) { - H5MM_free(shared_chunks_info_array); - shared_chunks_info_array = NULL; - } /* end if */ + for (size_t j = 0; j < (size_t)num_chunks_int; j++) { + H5D_chunk_redistribute_info_t *coll_entry; - /* Now that the chunks have been redistributed, each process must send its modification data - * to the new owners of any of the chunks it previously possessed. Accordingly, each process - * must also issue asynchronous receives for any messages it may receive for each of the - * chunks it is assigned, in order to avoid potential deadlocking issues. + coll_entry = &((H5D_chunk_redistribute_info_t *)coll_chunk_list)[i++]; + + chunk_list[j].new_owner = coll_entry->new_owner; + chunk_list[j].num_writers = coll_entry->num_writers; + } + } + else { + /* + * If redistribution occurred only on rank 0, scatter the segments + * of the collective chunk list back to each rank so that their + * local chunk lists get updated + */ + if (MPI_SUCCESS != + (mpi_code = MPI_Scatterv(coll_chunk_list, counts_ptr, displacements_ptr, packed_type, chunk_list, + num_chunks_int, struct_type, 0, io_info->comm))) + HMPI_GOTO_ERROR(FAIL, "unable to scatter shared chunks info buffer", mpi_code) + } + +#ifdef H5Dmpio_DEBUG + H5D__mpio_dump_collective_filtered_chunk_list(chunk_list, num_chunks_assigned_map[mpi_rank], mpi_rank); +#endif + +done: + H5MM_free(coll_chunk_list); + + if (struct_type_derived) { + if (MPI_SUCCESS != (mpi_code = MPI_Type_free(&struct_type))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + } + if (packed_type_derived) { + if (MPI_SUCCESS != (mpi_code = MPI_Type_free(&packed_type))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + } + + H5MM_free(counts_disps_array); + +#ifdef H5Dmpio_DEBUG + H5D_MPIO_TIME_STOP(mpi_rank); + H5D_MPIO_TRACE_EXIT(mpi_rank); +#endif + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D__mpio_redistribute_shared_chunks_int() */ + +/*------------------------------------------------------------------------- + * Function: H5D__mpio_share_chunk_modification_data + * + * Purpose: When performing a parallel write on a chunked dataset with + * filters applied, we must first ensure that any particular + * chunk is only written to by a single MPI rank in order to + * avoid potential data races on the chunk. Once dataset + * chunks have been redistributed in a suitable manner, each + * MPI rank must send its chunk data to other ranks for each + * chunk it no longer owns. + * + * The current implementation here follows the Nonblocking + * Consensus algorithm described in: + * http://unixer.de/publications/img/hoefler-dsde-protocols.pdf + * + * First, each MPI rank scans through its list of selected + * chunks and does the following for each chunk: + * + * * If a chunk in the MPI rank's chunk list is still owned + * by that rank, the rank checks how many messages are + * incoming for that chunk and adds that to its running + * total. Then, the rank updates its local chunk list so + * that any previous chunk entries for chunks that are no + * longer owned by the rank get overwritten by chunk + * entries for chunks the rank still owns. Since the data + * for the chunks no longer owned will have already been + * sent, those chunks can effectively be discarded. + * * If a chunk in the MPI rank's chunk list is no longer + * owned by that rank, the rank sends the data it wishes to + * update the chunk with to the MPI rank that now has + * ownership of that chunk. To do this, it encodes the + * chunk's index, its selection in the chunk and its + * modification data into a buffer and then posts a + * non-blocking MPI_Issend to the owning rank. + * + * Once this step is complete, all MPI ranks allocate arrays + * to hold chunk message receive buffers and MPI request + * objects for each non-blocking receive they will post for + * incoming chunk modification messages. Then, all MPI ranks + * enter a loop that alternates between non-blocking + * MPI_Iprobe calls to probe for incoming messages and + * MPI_Testall calls to see if all send requests have + * completed. As chunk modification messages arrive, + * non-blocking MPI_Irecv calls will be posted for each + * message. + * + * Once all send requests have completed, an MPI_Ibarrier is + * posted and the loop then alternates between MPI_Iprobe + * calls and MPI_Test calls to check if all ranks have reached + * the non-blocking barrier. Once all ranks have reached the + * barrier, processing can move on to updating the selected + * chunks that are owned in the operation. + * + * Any chunk messages that were received from other ranks + * will be returned through the `chunk_msg_bufs` array and + * `chunk_msg_bufs_len` will be set appropriately. + * + * NOTE: The use of non-blocking sends and receives of chunk + * data here may contribute to large amounts of memory + * usage/MPI request overhead if the number of shared + * chunks is high. If this becomes a problem, it may be + * useful to split the message receiving loop away so + * that chunk modification messages can be received and + * processed immediately (MPI_Recv) using a single chunk + * message buffer. However, it's possible this may + * degrade performance since the chunk message sends + * are synchronous (MPI_Issend) in the Nonblocking + * Consensus algorithm. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D__mpio_share_chunk_modification_data(H5D_filtered_collective_io_info_t *chunk_list, + size_t *chunk_list_num_entries, H5D_io_info_t *io_info, + const H5D_type_info_t *type_info, int mpi_rank, int mpi_size, + H5D_filtered_collective_io_info_t **chunk_hash_table, + unsigned char ***chunk_msg_bufs, int *chunk_msg_bufs_len) +{ +#if H5_CHECK_MPI_VERSION(3, 0) + H5D_filtered_collective_io_info_t *chunk_table = NULL; + H5S_sel_iter_t * mem_iter = NULL; + unsigned char ** msg_send_bufs = NULL; + unsigned char ** msg_recv_bufs = NULL; + MPI_Request * send_requests = NULL; + MPI_Request * recv_requests = NULL; + MPI_Request ibarrier = MPI_REQUEST_NULL; + hbool_t mem_iter_init = FALSE; + hbool_t ibarrier_posted = FALSE; + size_t send_bufs_nalloc = 0; + size_t num_send_requests = 0; + size_t num_recv_requests = 0; + size_t num_msgs_incoming = 0; + size_t last_assigned_idx; + size_t i; + int mpi_code; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC + + HDassert(chunk_list_num_entries); + HDassert(chunk_list || 0 == *chunk_list_num_entries); + HDassert(io_info); + HDassert(type_info); + HDassert(mpi_size > 1); + HDassert(chunk_msg_bufs); + HDassert(chunk_msg_bufs_len); + +#ifdef H5Dmpio_DEBUG + H5D_MPIO_TRACE_ENTER(mpi_rank); + H5D_MPIO_TIME_START(mpi_rank, "Share chunk modification data"); +#endif + + /* Set to latest format for encoding dataspace */ + H5CX_set_libver_bounds(NULL); + + if (*chunk_list_num_entries) { + /* Allocate a selection iterator for iterating over chunk dataspaces */ + if (NULL == (mem_iter = H5FL_MALLOC(H5S_sel_iter_t))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate dataspace selection iterator") + + /* + * Allocate send buffer and MPI_Request arrays for non-blocking + * sends of outgoing chunk messages + */ + send_bufs_nalloc = H5D_CHUNK_NUM_SEND_MSGS_INIT; + if (NULL == (msg_send_bufs = H5MM_malloc(send_bufs_nalloc * sizeof(*msg_send_bufs)))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, + "couldn't allocate chunk modification message buffer array") + + if (NULL == (send_requests = H5MM_malloc(send_bufs_nalloc * sizeof(*send_requests)))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate send requests array") + } + + /* + * For each chunk this rank owns, add to the total number of + * incoming MPI messages, then update the local chunk list to + * overwrite any previous chunks no longer owned by this rank. + * Since the data for those chunks will have already been sent, + * this rank should no longer be interested in them and they + * can effectively be discarded. This bookkeeping also makes + * the code for the collective file space re-allocation and + * chunk re-insertion operations a bit simpler. + * + * For each chunk this rank doesn't own, use non-blocking + * synchronous sends to send the data this rank is writing to + * the rank that does own the chunk. */ - if (*local_chunk_array_num_entries) - if (NULL == (mod_data = (unsigned char **)H5MM_malloc(*local_chunk_array_num_entries * - sizeof(unsigned char *)))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "unable to allocate modification data buffer array") - - /* Perform all the sends on the chunks that this rank doesn't own */ - /* (Sends and recvs must be two separate loops, to avoid deadlock) */ - for (i = 0, last_assigned_idx = 0; i < *local_chunk_array_num_entries; i++) { - H5D_filtered_collective_io_info_t *chunk_entry = &local_chunk_array[i]; - - if (mpi_rank != chunk_entry->owners.new_owner) { - H5D_chunk_info_t *chunk_info = NULL; + for (i = 0, last_assigned_idx = 0; i < *chunk_list_num_entries; i++) { + H5D_filtered_collective_io_info_t *chunk_entry = &chunk_list[i]; + + if (mpi_rank == chunk_entry->new_owner) { + num_msgs_incoming += (size_t)(chunk_entry->num_writers - 1); + + /* + * Overwrite chunk entries this rank doesn't own with entries that it + * does own, since it has sent the necessary data and is no longer + * interested in the chunks it doesn't own. + */ + chunk_list[last_assigned_idx] = chunk_list[i]; + + /* + * Since, at large scale, a chunk's index value may be larger than + * the maximum value that can be stored in an int, we cannot rely + * on using a chunk's index value as the tag for the MPI messages + * sent/received for a chunk. Therefore, add this chunk to a hash + * table with the chunk's index as a key so that we can quickly find + * the chunk when processing chunk messages that were received. The + * message itself will contain the chunk's index so we can update + * the correct chunk with the received data. + */ + HASH_ADD(hh, chunk_table, index_info.chunk_idx, sizeof(hsize_t), &chunk_list[last_assigned_idx]); + + last_assigned_idx++; + } + else { + H5D_chunk_info_t *chunk_info = chunk_entry->chunk_info; unsigned char * mod_data_p = NULL; hsize_t iter_nelmts; - size_t mod_data_size; + size_t mod_data_size = 0; + size_t space_size = 0; - /* Look up the chunk and get its file and memory dataspaces */ - if (NULL == (chunk_info = (H5D_chunk_info_t *)H5SL_search(fm->sel_chunks, &chunk_entry->index))) - HGOTO_ERROR(H5E_DATASPACE, H5E_NOTFOUND, FAIL, "can't locate chunk in skip list") + /* Add the size of the chunk index to the encoded size */ + mod_data_size += sizeof(hsize_t); - /* Determine size of serialized chunk file dataspace, plus the size of - * the data being written - */ - if (H5S_encode(chunk_info->fspace, &mod_data_p, &mod_data_size) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTENCODE, FAIL, "unable to get encoded dataspace size") + /* Determine size of serialized chunk file dataspace */ + if (H5S_encode(chunk_info->fspace, &mod_data_p, &space_size) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to get encoded dataspace size") + mod_data_size += space_size; + /* Determine size of data being written */ iter_nelmts = H5S_GET_SELECT_NPOINTS(chunk_info->mspace); - H5_CHECK_OVERFLOW(iter_nelmts, hsize_t, size_t); + mod_data_size += (size_t)iter_nelmts * type_info->src_type_size; - if (NULL == (mod_data[num_send_requests] = (unsigned char *)H5MM_malloc(mod_data_size))) + if (NULL == (msg_send_bufs[num_send_requests] = H5MM_malloc(mod_data_size))) HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, - "couldn't allocate chunk modification send buffer") + "couldn't allocate chunk modification message buffer") + + mod_data_p = msg_send_bufs[num_send_requests]; + + /* Store the chunk's index into the buffer */ + HDmemcpy(mod_data_p, &chunk_entry->index_info.chunk_idx, sizeof(hsize_t)); + mod_data_p += sizeof(hsize_t); /* Serialize the chunk's file dataspace into the buffer */ - mod_data_p = mod_data[num_send_requests]; if (H5S_encode(chunk_info->fspace, &mod_data_p, &mod_data_size) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTENCODE, FAIL, "unable to encode dataspace") /* Initialize iterator for memory selection */ - if (H5S_select_iter_init(mem_iter, chunk_info->mspace, type_info->src_type_size, 0) < 0) + if (H5S_select_iter_init(mem_iter, chunk_info->mspace, type_info->src_type_size, + H5S_SEL_ITER_SHARE_WITH_DATASPACE) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize memory selection information") mem_iter_init = TRUE; @@ -2952,466 +3943,2057 @@ H5D__chunk_redistribute_shared_chunks(const H5D_io_info_t *io_info, const H5D_ty if (0 == H5D__gather_mem(io_info->u.wbuf, mem_iter, (size_t)iter_nelmts, mod_data_p)) HGOTO_ERROR(H5E_IO, H5E_CANTGATHER, FAIL, "couldn't gather from write buffer") - /* Send modification data to new owner */ + /* + * Ensure that the size of the chunk data being sent can be + * safely cast to an int for MPI. Note that this should + * generally be OK for now (unless a rank is sending a + * whole 32-bit-sized chunk of data + its encoded selection), + * but if we allow larger than 32-bit-sized chunks in the + * future, this may become a problem and derived datatypes + * will need to be used. + */ H5_CHECK_OVERFLOW(mod_data_size, size_t, int) - H5_CHECK_OVERFLOW(chunk_entry->index, hsize_t, int) + + /* Send modification data to new owner */ if (MPI_SUCCESS != - (mpi_code = MPI_Isend(mod_data[num_send_requests], (int)mod_data_size, MPI_BYTE, - chunk_entry->owners.new_owner, (int)chunk_entry->index, io_info->comm, - &send_requests[num_send_requests]))) - HMPI_GOTO_ERROR(FAIL, "MPI_Isend failed", mpi_code) + (mpi_code = MPI_Issend(msg_send_bufs[num_send_requests], (int)mod_data_size, MPI_BYTE, + chunk_entry->new_owner, H5D_CHUNK_MOD_DATA_TAG, io_info->comm, + &send_requests[num_send_requests]))) + HMPI_GOTO_ERROR(FAIL, "MPI_Issend failed", mpi_code) + + num_send_requests++; + + /* Resize send buffer and send request arrays if necessary */ + if (num_send_requests == send_bufs_nalloc) { + void *tmp_alloc; + + send_bufs_nalloc = (size_t)((double)send_bufs_nalloc * 1.5); + + if (NULL == + (tmp_alloc = H5MM_realloc(msg_send_bufs, send_bufs_nalloc * sizeof(*msg_send_bufs)))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, + "couldn't resize chunk modification message buffer array") + msg_send_bufs = tmp_alloc; + + if (NULL == + (tmp_alloc = H5MM_realloc(send_requests, send_bufs_nalloc * sizeof(*send_requests)))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't resize send requests array") + send_requests = tmp_alloc; + } - if (mem_iter_init && H5S_SELECT_ITER_RELEASE(mem_iter) < 0) + if (H5S_SELECT_ITER_RELEASE(mem_iter) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "couldn't release memory selection iterator") mem_iter_init = FALSE; + } + } - num_send_requests++; - } /* end if */ - } /* end for */ + /* Check if the number of send or receive requests will overflow an int (MPI requirement) */ + if (num_send_requests > INT_MAX || num_msgs_incoming > INT_MAX) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, + "too many shared chunks in parallel filtered write operation") + + H5_CHECK_OVERFLOW(num_send_requests, size_t, int) + H5_CHECK_OVERFLOW(num_msgs_incoming, size_t, int) + + /* + * Allocate receive buffer and MPI_Request arrays for non-blocking + * receives of incoming chunk messages + */ + if (num_msgs_incoming) { + if (NULL == (msg_recv_bufs = H5MM_malloc(num_msgs_incoming * sizeof(*msg_recv_bufs)))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, + "couldn't allocate chunk modification message buffer array") - /* Perform all the recvs on the chunks this rank owns */ - for (i = 0, last_assigned_idx = 0; i < *local_chunk_array_num_entries; i++) { - H5D_filtered_collective_io_info_t *chunk_entry = &local_chunk_array[i]; + if (NULL == (recv_requests = H5MM_malloc(num_msgs_incoming * sizeof(*recv_requests)))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate receive requests array") + } - if (mpi_rank == chunk_entry->owners.new_owner) { - /* Allocate all necessary buffers for an asynchronous receive operation */ - if (chunk_entry->num_writers > 1) { - MPI_Message message; - MPI_Status status; - size_t j; + /* Process any incoming messages until everyone is done */ + do { + MPI_Status status; + int msg_flag; - chunk_entry->async_info.num_receive_requests = (int)chunk_entry->num_writers - 1; - if (NULL == (chunk_entry->async_info.receive_requests_array = (MPI_Request *)H5MM_malloc( - (size_t)chunk_entry->async_info.num_receive_requests * sizeof(MPI_Request)))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "unable to allocate async requests array") + /* Probe for an incoming message from any rank */ + if (MPI_SUCCESS != (mpi_code = MPI_Iprobe(MPI_ANY_SOURCE, H5D_CHUNK_MOD_DATA_TAG, io_info->comm, + &msg_flag, &status))) + HMPI_GOTO_ERROR(FAIL, "MPI_Iprobe failed", mpi_code) - if (NULL == - (chunk_entry->async_info.receive_buffer_array = (unsigned char **)H5MM_malloc( - (size_t)chunk_entry->async_info.num_receive_requests * sizeof(unsigned char *)))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "unable to allocate async receive buffers") + /* + * If a message was found, allocate a buffer for the message and + * post a non-blocking receive to receive it + */ + if (msg_flag) { +#if H5_CHECK_MPI_VERSION(3, 0) + MPI_Count msg_size = 0; - for (j = 0; j < chunk_entry->num_writers - 1; j++) { - int count = 0; + if (MPI_SUCCESS != (mpi_code = MPI_Get_elements_x(&status, MPI_BYTE, &msg_size))) + HMPI_GOTO_ERROR(FAIL, "MPI_Get_elements_x failed", mpi_code) - /* Probe for a particular message from any process, removing that message - * from the receive queue in the process and allocating that much memory - * for the asynchronous receive - */ - if (MPI_SUCCESS != (mpi_code = MPI_Mprobe(MPI_ANY_SOURCE, (int)chunk_entry->index, - io_info->comm, &message, &status))) - HMPI_GOTO_ERROR(FAIL, "MPI_Mprobe failed", mpi_code) - - if (MPI_SUCCESS != (mpi_code = MPI_Get_count(&status, MPI_BYTE, &count))) - HMPI_GOTO_ERROR(FAIL, "MPI_Get_count failed", mpi_code) - - HDassert(count >= 0); - if (NULL == (chunk_entry->async_info.receive_buffer_array[j] = - (unsigned char *)H5MM_malloc((size_t)count * sizeof(char *)))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, - "unable to allocate modification data receive buffer") - - if (MPI_SUCCESS != (mpi_code = MPI_Imrecv( - chunk_entry->async_info.receive_buffer_array[j], count, MPI_BYTE, - &message, &chunk_entry->async_info.receive_requests_array[j]))) - HMPI_GOTO_ERROR(FAIL, "MPI_Imrecv failed", mpi_code) - } /* end for */ - } /* end if */ - - local_chunk_array[last_assigned_idx++] = local_chunk_array[i]; - } /* end else */ - } /* end for */ + H5_CHECK_OVERFLOW(msg_size, MPI_Count, int) +#else + int msg_size = 0; - *local_chunk_array_num_entries = last_assigned_idx; + if (MPI_SUCCESS != (mpi_code = MPI_Get_elements(&status, MPI_BYTE, &msg_size))) + HMPI_GOTO_ERROR(FAIL, "MPI_Get_elements failed", mpi_code) +#endif - /* Wait for all async send requests to complete before returning */ - if (num_send_requests) { - if (NULL == (send_statuses = (MPI_Status *)H5MM_malloc(num_send_requests * sizeof(MPI_Status)))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate send statuses buffer") + if (msg_size <= 0) + HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "invalid chunk modification message size") - H5_CHECK_OVERFLOW(num_send_requests, size_t, int); - if (MPI_SUCCESS != (mpi_code = MPI_Waitall((int)num_send_requests, send_requests, send_statuses))) - HMPI_GOTO_ERROR(FAIL, "MPI_Waitall failed", mpi_code) - } /* end if */ + HDassert((num_recv_requests + 1) <= num_msgs_incoming); + if (NULL == + (msg_recv_bufs[num_recv_requests] = H5MM_malloc((size_t)msg_size * sizeof(unsigned char)))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, + "couldn't allocate chunk modification message receive buffer") -done: - /* Now that all async send requests have completed, free up the send - * buffers used in the async operations + if (MPI_SUCCESS != (mpi_code = MPI_Irecv(msg_recv_bufs[num_recv_requests], (int)msg_size, + MPI_BYTE, status.MPI_SOURCE, H5D_CHUNK_MOD_DATA_TAG, + io_info->comm, &recv_requests[num_recv_requests]))) + HMPI_GOTO_ERROR(FAIL, "MPI_Irecv failed", mpi_code) + + num_recv_requests++; + } + + if (ibarrier_posted) { + int ibarrier_completed; + + if (MPI_SUCCESS != (mpi_code = MPI_Test(&ibarrier, &ibarrier_completed, MPI_STATUS_IGNORE))) + HMPI_GOTO_ERROR(FAIL, "MPI_Test failed", mpi_code) + + if (ibarrier_completed) + break; + } + else { + int all_sends_completed; + + /* Determine if all send requests have completed */ + if (MPI_SUCCESS != (mpi_code = MPI_Testall((int)num_send_requests, send_requests, + &all_sends_completed, MPI_STATUSES_IGNORE))) + HMPI_GOTO_ERROR(FAIL, "MPI_Testall failed", mpi_code) + + if (all_sends_completed) { + /* Post non-blocking barrier */ + if (MPI_SUCCESS != (mpi_code = MPI_Ibarrier(io_info->comm, &ibarrier))) + HMPI_GOTO_ERROR(FAIL, "MPI_Ibarrier failed", mpi_code) + ibarrier_posted = TRUE; + + /* + * Now that all send requests have completed, free up the + * send buffers used in the non-blocking operations + */ + if (msg_send_bufs) { + for (i = 0; i < num_send_requests; i++) { + if (msg_send_bufs[i]) + H5MM_free(msg_send_bufs[i]); + } + + msg_send_bufs = H5MM_xfree(msg_send_bufs); + } + } + } + } while (1); + + /* + * Ensure all receive requests have completed before moving on. + * For linked-chunk I/O, more overlap with computation could + * theoretically be achieved by returning the receive requests + * array and postponing this wait until during chunk updating + * when the data is really needed. However, multi-chunk I/O + * only updates a chunk at a time and the messages may not come + * in the order that chunks are processed. So, the safest way to + * support both I/O modes is to simply make sure all messages + * are available. */ - for (i = 0; i < num_send_requests; i++) { - if (mod_data[i]) - H5MM_free(mod_data[i]); - } /* end for */ + if (MPI_SUCCESS != (mpi_code = MPI_Waitall((int)num_recv_requests, recv_requests, MPI_STATUSES_IGNORE))) + HMPI_GOTO_ERROR(FAIL, "MPI_Waitall failed", mpi_code) + + /* Set the new number of locally-selected chunks */ + *chunk_list_num_entries = last_assigned_idx; + + /* Return chunk message buffers if any were received */ + *chunk_hash_table = chunk_table; + *chunk_msg_bufs = msg_recv_bufs; + *chunk_msg_bufs_len = (int)num_recv_requests; +done: + if (ret_value < 0) { + /* If this rank failed, make sure to participate in collective barrier */ + if (!ibarrier_posted) { + if (MPI_SUCCESS != (mpi_code = MPI_Ibarrier(io_info->comm, &ibarrier))) + HMPI_GOTO_ERROR(FAIL, "MPI_Ibarrier failed", mpi_code) + } + + if (num_send_requests) { + for (i = 0; i < num_send_requests; i++) { + MPI_Cancel(&send_requests[i]); + } + } + + if (recv_requests) { + for (i = 0; i < num_recv_requests; i++) { + MPI_Cancel(&recv_requests[i]); + } + } + + if (msg_recv_bufs) { + for (i = 0; i < num_recv_requests; i++) { + H5MM_free(msg_recv_bufs[i]); + } + + H5MM_free(msg_recv_bufs); + } + + HASH_CLEAR(hh, chunk_table); + } + + if (recv_requests) + H5MM_free(recv_requests); if (send_requests) H5MM_free(send_requests); - if (send_statuses) - H5MM_free(send_statuses); - if (send_counts) - H5MM_free(send_counts); - if (send_displacements) - H5MM_free(send_displacements); - if (mod_data) - H5MM_free(mod_data); - if (mem_iter_init && H5S_SELECT_ITER_RELEASE(mem_iter) < 0) - HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "couldn't release selection iterator") - if (mem_iter) - H5MM_free(mem_iter); - if (num_assigned_chunks_array) - H5MM_free(num_assigned_chunks_array); - if (shared_chunks_info_array) - H5MM_free(shared_chunks_info_array); + + if (msg_send_bufs) { + for (i = 0; i < num_send_requests; i++) { + if (msg_send_bufs[i]) + H5MM_free(msg_send_bufs[i]); + } + + H5MM_free(msg_send_bufs); + } + + if (mem_iter) { + if (mem_iter_init && H5S_SELECT_ITER_RELEASE(mem_iter) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "couldn't release dataspace selection iterator") + mem_iter = H5FL_FREE(H5S_sel_iter_t, mem_iter); + } + +#ifdef H5Dmpio_DEBUG + H5D_MPIO_TIME_STOP(mpi_rank); + H5D_MPIO_TRACE_EXIT(mpi_rank); +#endif FUNC_LEAVE_NOAPI(ret_value) -} /* end H5D__chunk_redistribute_shared_chunks() */ +#else + FUNC_ENTER_STATIC + HERROR( + H5E_DATASET, H5E_WRITEERROR, + "unable to send chunk modification data between MPI ranks - MPI version < 3 (MPI_Ibarrier missing)") + FUNC_LEAVE_NOAPI(FAIL) #endif +} /* end H5D__mpio_share_chunk_modification_data() */ /*------------------------------------------------------------------------- - * Function: H5D__mpio_filtered_collective_write_type + * Function: H5D__mpio_collective_filtered_chunk_common_io * - * Purpose: Constructs a MPI derived datatype for both the memory and - * the file for a collective write of filtered chunks. The - * datatype contains the offsets in the file and the locations - * of the filtered chunk data buffers. + * Purpose: This routine performs the common part of collective I/O + * when reading or writing filtered chunks collectively. * * Return: Non-negative on success/Negative on failure * - * Programmer: Jordan Henderson - * Tuesday, November 22, 2016 - * *------------------------------------------------------------------------- */ static herr_t -H5D__mpio_filtered_collective_write_type(H5D_filtered_collective_io_info_t *chunk_list, size_t num_entries, - MPI_Datatype *new_mem_type, hbool_t *mem_type_derived, - MPI_Datatype *new_file_type, hbool_t *file_type_derived) +H5D__mpio_collective_filtered_chunk_common_io(H5D_filtered_collective_io_info_t *chunk_list, + size_t chunk_list_num_entries, const H5D_io_info_t *io_info, + const H5D_type_info_t *type_info, int mpi_size) { - MPI_Aint *write_buf_array = NULL; /* Relative displacements of filtered chunk data buffers */ - MPI_Aint *file_offset_array = NULL; /* Chunk offsets in the file */ - int * length_array = NULL; /* Filtered Chunk lengths */ - herr_t ret_value = SUCCEED; + H5D_io_info_t coll_io_info; + H5D_storage_t ctg_store; + MPI_Datatype file_type = MPI_DATATYPE_NULL; + MPI_Datatype mem_type = MPI_DATATYPE_NULL; + hbool_t mem_type_is_derived = FALSE; + hbool_t file_type_is_derived = FALSE; + hsize_t mpi_buf_count; + haddr_t base_read_offset = HADDR_UNDEF; + size_t num_chunks; + size_t i; + char fake_buf; /* Used as a fake buffer for ranks with no chunks, thus a NULL buf pointer */ + int mpi_code; + herr_t ret_value = SUCCEED; FUNC_ENTER_STATIC - HDassert(chunk_list); - HDassert(new_mem_type); - HDassert(mem_type_derived); - HDassert(new_file_type); - HDassert(file_type_derived); + HDassert(chunk_list || 0 == chunk_list_num_entries); + HDassert(io_info); + HDassert(type_info); - if (num_entries > 0) { - size_t i; - int mpi_code; - void * base_buf; - - H5_CHECK_OVERFLOW(num_entries, size_t, int); - - /* Allocate arrays */ - if (NULL == (length_array = (int *)H5MM_malloc((size_t)num_entries * sizeof(int)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, - "memory allocation failed for filtered collective write length array") - if (NULL == (write_buf_array = (MPI_Aint *)H5MM_malloc((size_t)num_entries * sizeof(MPI_Aint)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, - "memory allocation failed for filtered collective write buf length array") - if (NULL == (file_offset_array = (MPI_Aint *)H5MM_malloc((size_t)num_entries * sizeof(MPI_Aint)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, - "memory allocation failed for collective write offset array") - - /* Ensure the list is sorted in ascending order of offset in the file */ - HDqsort(chunk_list, num_entries, sizeof(H5D_filtered_collective_io_info_t), - H5D__cmp_filtered_collective_io_info_entry); + /* Initialize temporary I/O info */ + coll_io_info = *io_info; - base_buf = chunk_list[0].buf; - for (i = 0; i < num_entries; i++) { - /* Set up the offset in the file, the length of the chunk data, and the relative - * displacement of the chunk data write buffer - */ - file_offset_array[i] = (MPI_Aint)chunk_list[i].chunk_states.new_chunk.offset; - length_array[i] = (int)chunk_list[i].chunk_states.new_chunk.length; - write_buf_array[i] = (MPI_Aint)chunk_list[i].buf - (MPI_Aint)base_buf; - } /* end for */ + /* + * Construct MPI derived datatype for collective I/O on chunks + */ + if (H5D__mpio_collective_filtered_io_type(chunk_list, chunk_list_num_entries, io_info->op_type, &mem_type, + &mem_type_is_derived, &file_type, &file_type_is_derived) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, FAIL, "couldn't create MPI I/O type for chunk I/O") - /* Create memory MPI type */ - if (MPI_SUCCESS != (mpi_code = MPI_Type_create_hindexed((int)num_entries, length_array, - write_buf_array, MPI_BYTE, new_mem_type))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hindexed failed", mpi_code) - *mem_type_derived = TRUE; - if (MPI_SUCCESS != (mpi_code = MPI_Type_commit(new_mem_type))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code) - - /* Create file MPI type */ - if (MPI_SUCCESS != (mpi_code = MPI_Type_create_hindexed((int)num_entries, length_array, - file_offset_array, MPI_BYTE, new_file_type))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hindexed failed", mpi_code) - *file_type_derived = TRUE; - if (MPI_SUCCESS != (mpi_code = MPI_Type_commit(new_file_type))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code) - } /* end if */ + /* + * For reads, determine how many chunks are actually being read. + * Note that if this is a read during a write operation + * (read chunk -> unfilter -> modify -> write back), some + * chunks may not need to be read if they're being fully + * overwritten during a write operation. + */ + if (io_info->op_type == H5D_IO_OP_READ) { + for (i = 0, num_chunks = 0; i < chunk_list_num_entries; i++) { + HDassert(chunk_list[i].buf); + + if (chunk_list[i].need_read) { + if (!H5F_addr_defined(base_read_offset)) + base_read_offset = chunk_list[i].chunk_current.offset; + + num_chunks++; + } + } + } + else + num_chunks = chunk_list_num_entries; + + /* + * If this rank doesn't have a selection, it can + * skip I/O if independent I/O was requested at + * the low level, or if the MPI communicator size + * is 1. + * + * Otherwise, this rank has to participate in + * collective I/O, but probably has a NULL buf + * pointer, so override to a fake buffer since our + * write/read function expects one. + */ + if (num_chunks == 0) { + H5FD_mpio_collective_opt_t coll_opt_mode; + + /* Get the collective_opt property to check whether the application wants to do IO individually. */ + if (H5CX_get_mpio_coll_opt(&coll_opt_mode) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get MPI-I/O collective_opt property") + + if ((mpi_size == 1) || (H5FD_MPIO_INDIVIDUAL_IO == coll_opt_mode)) { + HGOTO_DONE(SUCCEED) + } + else { + if (io_info->op_type == H5D_IO_OP_WRITE) + coll_io_info.u.wbuf = &fake_buf; + else + coll_io_info.u.rbuf = &fake_buf; + } + } + + /* + * Setup for I/O operation + */ + + mpi_buf_count = (num_chunks) ? 1 : 0; + + if (num_chunks) { + /* + * Setup the base storage address for this operation + * to be the first chunk's file address + */ + if (io_info->op_type == H5D_IO_OP_WRITE) + ctg_store.contig.dset_addr = chunk_list[0].chunk_new.offset; + else + ctg_store.contig.dset_addr = base_read_offset; + } + else + ctg_store.contig.dset_addr = 0; + + ctg_store.contig.dset_size = (hsize_t)io_info->dset->shared->layout.u.chunk.size; + coll_io_info.store = &ctg_store; + + /* Perform I/O */ + if (H5D__final_collective_io(&coll_io_info, type_info, mpi_buf_count, file_type, mem_type) < 0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "couldn't finish MPI I/O") done: - if (write_buf_array) - H5MM_free(write_buf_array); - if (file_offset_array) - H5MM_free(file_offset_array); - if (length_array) - H5MM_free(length_array); + /* Free the MPI buf and file types, if they were derived */ + if (mem_type_is_derived && MPI_SUCCESS != (mpi_code = MPI_Type_free(&mem_type))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + if (file_type_is_derived && MPI_SUCCESS != (mpi_code = MPI_Type_free(&file_type))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) FUNC_LEAVE_NOAPI(ret_value) -} /* end H5D__mpio_filtered_collective_write_type() */ +} /* end H5D__mpio_collective_filtered_chunk_common_io() */ /*------------------------------------------------------------------------- - * Function: H5D__filtered_collective_chunk_entry_io + * Function: H5D__mpio_collective_filtered_chunk_read * - * Purpose: Given an entry for a filtered chunk, performs the necessary - * steps for updating the chunk data during a collective - * write, or for reading the chunk from file during a - * collective read. + * Purpose: This routine coordinates a collective read across all ranks + * of the chunks they have selected. Each rank will then go + * and * * Return: Non-negative on success/Negative on failure * - * Programmer: Jordan Henderson - * Wednesday, January 18, 2017 - * *------------------------------------------------------------------------- */ static herr_t -H5D__filtered_collective_chunk_entry_io(H5D_filtered_collective_io_info_t *chunk_entry, - const H5D_io_info_t *io_info, const H5D_type_info_t *type_info, - const H5D_chunk_map_t *fm) +H5D__mpio_collective_filtered_chunk_read(H5D_filtered_collective_io_info_t *chunk_list, + size_t chunk_list_num_entries, const H5D_io_info_t *io_info, + const H5D_type_info_t *type_info, int mpi_rank, int mpi_size) { - H5D_chunk_info_t *chunk_info = NULL; - H5S_sel_iter_t * mem_iter = NULL; /* Memory iterator for H5D__scatter_mem/H5D__gather_mem */ - H5S_sel_iter_t * file_iter = NULL; - H5Z_EDC_t err_detect; /* Error detection info */ - H5Z_cb_t filter_cb; /* I/O filter callback function */ - unsigned filter_mask = 0; - hsize_t iter_nelmts; /* Number of points to iterate over for the chunk IO operation */ - hssize_t extent_npoints; - hsize_t true_chunk_size; - hbool_t mem_iter_init = FALSE; - hbool_t file_iter_init = FALSE; - size_t buf_size; - size_t i; - H5S_t * dataspace = NULL; /* Other process' dataspace for the chunk */ - void * tmp_gath_buf = NULL; /* Temporary gather buffer to gather into from application buffer - before scattering out to the chunk data buffer (when writing data), - or vice versa (when reading data) */ - int mpi_code; - herr_t ret_value = SUCCEED; + H5D_fill_buf_info_t fb_info; + H5D_chunk_info_t * chunk_info = NULL; + H5D_io_info_t coll_io_info; + H5Z_EDC_t err_detect; /* Error detection info */ + H5Z_cb_t filter_cb; /* I/O filter callback function */ + hsize_t file_chunk_size = 0; + hsize_t iter_nelmts; /* Number of points to iterate over for the chunk IO operation */ + hbool_t should_fill = FALSE; + hbool_t fb_info_init = FALSE; + hbool_t index_empty = FALSE; + size_t i; + H5S_t * fill_space = NULL; + void * base_read_buf = NULL; + herr_t ret_value = SUCCEED; FUNC_ENTER_STATIC - HDassert(chunk_entry); + HDassert(chunk_list || 0 == chunk_list_num_entries); HDassert(io_info); HDassert(type_info); - HDassert(fm); - /* Retrieve filter settings from API context */ - if (H5CX_get_err_detect(&err_detect) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get error detection info") - if (H5CX_get_filter_cb(&filter_cb) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get I/O filter callback function") +#ifdef H5Dmpio_DEBUG + H5D_MPIO_TRACE_ENTER(mpi_rank); + H5D_MPIO_TIME_START(mpi_rank, "Filtered collective chunk read"); +#else + (void)mpi_rank; +#endif + + /* Initialize temporary I/O info */ + coll_io_info = *io_info; + coll_io_info.u.rbuf = NULL; - /* Look up the chunk and get its file and memory dataspaces */ - if (NULL == (chunk_info = (H5D_chunk_info_t *)H5SL_search(fm->sel_chunks, &chunk_entry->index))) - HGOTO_ERROR(H5E_DATASPACE, H5E_NOTFOUND, FAIL, "can't locate chunk in skip list") + if (chunk_list_num_entries) { + /* Retrieve filter settings from API context */ + if (H5CX_get_err_detect(&err_detect) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get error detection info") + if (H5CX_get_filter_cb(&filter_cb) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get I/O filter callback function") - if ((extent_npoints = H5S_GET_EXTENT_NPOINTS(chunk_info->fspace)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTCOUNT, FAIL, "dataspace is invalid") - true_chunk_size = (hsize_t)extent_npoints * type_info->src_type_size; + /* Set size of full chunks in dataset */ + file_chunk_size = io_info->dset->shared->layout.u.chunk.size; + + /* Determine if fill values should be "read" for unallocated chunks */ + should_fill = (io_info->dset->shared->dcpl_cache.fill.fill_time == H5D_FILL_TIME_ALLOC) || + ((io_info->dset->shared->dcpl_cache.fill.fill_time == H5D_FILL_TIME_IFSET) && + io_info->dset->shared->dcpl_cache.fill.fill_defined); + } - /* If the size of the filtered chunk is larger than the number of points in the - * chunk file space extent times the datatype size, allocate enough space to hold the - * whole filtered chunk. Otherwise, allocate a buffer equal to the size of the - * chunk so that the unfiltering operation doesn't have to grow the buffer. + /* + * Allocate memory buffers for all chunks being read. Chunk data buffers are of + * the largest size between the chunk's current filtered size and the chunk's true + * size, as calculated by the number of elements in the chunk's file space extent + * multiplied by the datatype size. This tries to ensure that: + * + * * If we're reading the chunk and the filter normally reduces the chunk size, + * the unfiltering operation won't need to grow the buffer. + * * If we're reading the chunk and the filter normally grows the chunk size, + * we make sure to read into a buffer of size equal to the filtered chunk's + * size; reading into a (smaller) buffer of size equal to the unfiltered + * chunk size would of course be bad. */ - buf_size = MAX(chunk_entry->chunk_states.chunk_current.length, true_chunk_size); + for (i = 0; i < chunk_list_num_entries; i++) { + HDassert(chunk_list[i].need_read); + + chunk_list[i].chunk_buf_size = MAX(chunk_list[i].chunk_current.length, file_chunk_size); + + if (NULL == (chunk_list[i].buf = H5MM_malloc(chunk_list[i].chunk_buf_size))) { + /* Push an error, but participate in collective read */ + HDONE_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate chunk data buffer") + break; + } + + /* + * Check if chunk is currently allocated. If not, don't try to + * read it from the file. Instead, just fill the chunk buffer + * with the fill value if necessary. + */ + if (H5F_addr_defined(chunk_list[i].chunk_current.offset)) { + /* Set first read buffer */ + if (!base_read_buf) + base_read_buf = chunk_list[i].buf; + + /* Set chunk's new length for eventual filter pipeline calls */ + if (chunk_list[i].skip_filter_pline) + chunk_list[i].chunk_new.length = file_chunk_size; + else + chunk_list[i].chunk_new.length = chunk_list[i].chunk_current.length; + } + else { + chunk_list[i].need_read = FALSE; + + /* Set chunk's new length for eventual filter pipeline calls */ + chunk_list[i].chunk_new.length = file_chunk_size; + + if (should_fill) { + /* Initialize fill value buffer if not already initialized */ + if (!fb_info_init) { + hsize_t chunk_dims[H5S_MAX_RANK]; + + HDassert(io_info->dset->shared->ndims == io_info->dset->shared->layout.u.chunk.ndims - 1); + for (size_t j = 0; j < io_info->dset->shared->layout.u.chunk.ndims - 1; j++) + chunk_dims[j] = (hsize_t)io_info->dset->shared->layout.u.chunk.dim[j]; + + /* Get a dataspace for filling chunk memory buffers */ + if (NULL == (fill_space = H5S_create_simple( + io_info->dset->shared->layout.u.chunk.ndims - 1, chunk_dims, NULL))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create chunk fill dataspace") + + /* Initialize fill value buffer */ + if (H5D__fill_init(&fb_info, NULL, (H5MM_allocate_t)H5D__chunk_mem_alloc, + (void *)&io_info->dset->shared->dcpl_cache.pline, + (H5MM_free_t)H5D__chunk_mem_free, + (void *)&io_info->dset->shared->dcpl_cache.pline, + &io_info->dset->shared->dcpl_cache.fill, io_info->dset->shared->type, + io_info->dset->shared->type_id, 0, file_chunk_size) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize fill value buffer") + + fb_info_init = TRUE; + } - if (NULL == (chunk_entry->buf = H5MM_malloc(buf_size))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate chunk data buffer") + /* Write fill value to memory buffer */ + HDassert(fb_info.fill_buf); + if (H5D__fill(fb_info.fill_buf, io_info->dset->shared->type, chunk_list[i].buf, + type_info->mem_type, fill_space) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "couldn't fill chunk buffer with fill value") + } + } + } - /* If this is not a full chunk overwrite or this is a read operation, the chunk must be - * read from the file and unfiltered. + /* + * If dataset is incrementally allocated and hasn't been written to + * yet, the chunk index should be empty. In this case, a collective + * read of chunks is essentially a no-op, so avoid it here. */ - if (!chunk_entry->full_overwrite || io_info->op_type == H5D_IO_OP_READ) { - H5FD_mpio_xfer_t xfer_mode; /* Parallel transfer for this request */ + index_empty = FALSE; + if (io_info->dset->shared->dcpl_cache.fill.alloc_time == H5D_ALLOC_TIME_INCR) + if (H5D__chunk_index_empty(io_info->dset, &index_empty) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "couldn't determine if chunk index is empty") - chunk_entry->chunk_states.new_chunk.length = chunk_entry->chunk_states.chunk_current.length; + if (!index_empty) { + /* + * Override the read buffer to point to the address of + * the first chunk data buffer being read into + */ + if (base_read_buf) + coll_io_info.u.rbuf = base_read_buf; - /* Currently, these chunk reads are done independently and will likely - * cause issues with collective metadata reads enabled. In the future, - * this should be refactored to use collective chunk reads - JTH */ + /* Perform collective chunk read */ + if (H5D__mpio_collective_filtered_chunk_common_io(chunk_list, chunk_list_num_entries, &coll_io_info, + type_info, mpi_size) < 0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "couldn't finish collective filtered chunk read") + } - /* Get the original state of parallel I/O transfer mode */ - if (H5CX_get_io_xfer_mode(&xfer_mode) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get MPI-I/O transfer mode") + /* + * Iterate through all the read chunks, unfiltering them and scattering their + * data out to the application's read buffer. + */ + for (i = 0; i < chunk_list_num_entries; i++) { + chunk_info = chunk_list[i].chunk_info; + + /* Unfilter the chunk, unless we didn't read it from the file */ + if (chunk_list[i].need_read && !chunk_list[i].skip_filter_pline) { + if (H5Z_pipeline(&io_info->dset->shared->dcpl_cache.pline, H5Z_FLAG_REVERSE, + &(chunk_list[i].index_info.filter_mask), err_detect, filter_cb, + (size_t *)&chunk_list[i].chunk_new.length, &chunk_list[i].chunk_buf_size, + &chunk_list[i].buf) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTFILTER, FAIL, "couldn't unfilter chunk for modifying") + } + + /* Scatter the chunk data to the read buffer */ + iter_nelmts = H5S_GET_SELECT_NPOINTS(chunk_info->fspace); + + if (H5D_select_io_mem(io_info->u.rbuf, chunk_info->mspace, chunk_list[i].buf, chunk_info->fspace, + type_info->src_type_size, (size_t)iter_nelmts) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "couldn't copy chunk data to read buffer") + } - /* Change the xfer_mode to independent for handling the I/O */ - if (H5CX_set_io_xfer_mode(H5FD_MPIO_INDEPENDENT) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set MPI-I/O transfer mode") +done: + /* Free all resources used by entries in the chunk list */ + for (i = 0; i < chunk_list_num_entries; i++) { + if (chunk_list[i].buf) { + H5MM_free(chunk_list[i].buf); + chunk_list[i].buf = NULL; + } + } - if (H5F_shared_block_read(io_info->f_sh, H5FD_MEM_DRAW, - chunk_entry->chunk_states.chunk_current.offset, - chunk_entry->chunk_states.new_chunk.length, chunk_entry->buf) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "unable to read raw data chunk") + /* Release the fill buffer info, if it's been initialized */ + if (fb_info_init && H5D__fill_term(&fb_info) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release fill buffer info") + if (fill_space && (H5S_close(fill_space) < 0)) + HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "can't close fill space") - /* Return to the original I/O transfer mode setting */ - if (H5CX_set_io_xfer_mode(xfer_mode) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set MPI-I/O transfer mode") +#ifdef H5Dmpio_DEBUG + H5D_MPIO_TIME_STOP(mpi_rank); + H5D_MPIO_TRACE_EXIT(mpi_rank); +#endif - if (H5Z_pipeline(&io_info->dset->shared->dcpl_cache.pline, H5Z_FLAG_REVERSE, &filter_mask, err_detect, - filter_cb, (size_t *)&chunk_entry->chunk_states.new_chunk.length, &buf_size, - &chunk_entry->buf) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTFILTER, FAIL, "couldn't unfilter chunk for modifying") - } /* end if */ - else { - chunk_entry->chunk_states.new_chunk.length = true_chunk_size; - } /* end else */ + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D__mpio_collective_filtered_chunk_read() */ - /* Initialize iterator for memory selection */ - if (NULL == (mem_iter = (H5S_sel_iter_t *)H5MM_malloc(sizeof(H5S_sel_iter_t)))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate memory iterator") +/*------------------------------------------------------------------------- + * Function: H5D__mpio_collective_filtered_chunk_update + * + * Purpose: When performing a parallel write on a chunked dataset with + * filters applied, all ranks must update their owned chunks + * with their own modification data and data from other ranks. + * This routine is responsible for coordinating that process. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D__mpio_collective_filtered_chunk_update(H5D_filtered_collective_io_info_t *chunk_list, + size_t chunk_list_num_entries, + H5D_filtered_collective_io_info_t *chunk_hash_table, + unsigned char **chunk_msg_bufs, int chunk_msg_bufs_len, + const H5D_io_info_t *io_info, const H5D_type_info_t *type_info, + int mpi_rank, int mpi_size) +{ + H5D_fill_buf_info_t fb_info; + H5D_chunk_info_t * chunk_info = NULL; + H5S_sel_iter_t * sel_iter = NULL; /* Dataspace selection iterator for H5D__scatter_mem */ + H5D_io_info_t coll_io_info; + H5Z_EDC_t err_detect; /* Error detection info */ + H5Z_cb_t filter_cb; /* I/O filter callback function */ + hsize_t file_chunk_size = 0; + hsize_t iter_nelmts; /* Number of points to iterate over for the chunk IO operation */ + hbool_t should_fill = FALSE; + hbool_t fb_info_init = FALSE; + hbool_t sel_iter_init = FALSE; + hbool_t index_empty = FALSE; + size_t i; + H5S_t * dataspace = NULL; + H5S_t * fill_space = NULL; + void * base_read_buf = NULL; + herr_t ret_value = SUCCEED; - if (H5S_select_iter_init(mem_iter, chunk_info->mspace, type_info->src_type_size, 0) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize memory selection information") - mem_iter_init = TRUE; + FUNC_ENTER_STATIC - /* If this is a read operation, scatter the read chunk data to the user's buffer. - * - * If this is a write operation, update the chunk data buffer with the modifications - * from the current process, then apply any modifications from other processes. Finally, - * filter the newly-updated chunk. - */ - switch (io_info->op_type) { - case H5D_IO_OP_READ: - if (NULL == (file_iter = (H5S_sel_iter_t *)H5MM_malloc(sizeof(H5S_sel_iter_t)))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate file iterator") + HDassert(chunk_list || 0 == chunk_list_num_entries); + HDassert((chunk_msg_bufs && chunk_hash_table) || 0 == chunk_msg_bufs_len); + HDassert(io_info); + HDassert(type_info); - if (H5S_select_iter_init(file_iter, chunk_info->fspace, type_info->src_type_size, 0) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, - "unable to initialize memory selection information") - file_iter_init = TRUE; +#ifdef H5Dmpio_DEBUG + H5D_MPIO_TRACE_ENTER(mpi_rank); + H5D_MPIO_TIME_START(mpi_rank, "Filtered collective chunk update"); +#endif + + if (chunk_list_num_entries) { + /* Retrieve filter settings from API context */ + if (H5CX_get_err_detect(&err_detect) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get error detection info") + if (H5CX_get_filter_cb(&filter_cb) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get I/O filter callback function") - iter_nelmts = H5S_GET_SELECT_NPOINTS(chunk_info->fspace); + /* Set size of full chunks in dataset */ + file_chunk_size = io_info->dset->shared->layout.u.chunk.size; - if (NULL == (tmp_gath_buf = H5MM_malloc(iter_nelmts * type_info->src_type_size))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate temporary gather buffer") + /* Determine if fill values should be written to chunks */ + should_fill = (io_info->dset->shared->dcpl_cache.fill.fill_time == H5D_FILL_TIME_ALLOC) || + ((io_info->dset->shared->dcpl_cache.fill.fill_time == H5D_FILL_TIME_IFSET) && + io_info->dset->shared->dcpl_cache.fill.fill_defined); + } - if (!H5D__gather_mem(chunk_entry->buf, file_iter, (size_t)iter_nelmts, tmp_gath_buf)) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "couldn't gather from chunk buffer") + /* + * Allocate memory buffers for all owned chunks. Chunk data buffers are of the + * largest size between the chunk's current filtered size and the chunk's true + * size, as calculated by the number of elements in the chunk's file space extent + * multiplied by the datatype size. This tries to ensure that: + * + * * If we're fully overwriting the chunk and the filter normally reduces the + * chunk size, we simply have the exact buffer size required to hold the + * unfiltered chunk data. + * * If we're fully overwriting the chunk and the filter normally grows the + * chunk size (e.g., fletcher32 filter), the final filtering operation + * (hopefully) won't need to grow the buffer. + * * If we're reading the chunk and the filter normally reduces the chunk size, + * the unfiltering operation won't need to grow the buffer. + * * If we're reading the chunk and the filter normally grows the chunk size, + * we make sure to read into a buffer of size equal to the filtered chunk's + * size; reading into a (smaller) buffer of size equal to the unfiltered + * chunk size would of course be bad. + */ + for (i = 0; i < chunk_list_num_entries; i++) { + HDassert(mpi_rank == chunk_list[i].new_owner); - iter_nelmts = H5S_GET_SELECT_NPOINTS(chunk_info->mspace); + chunk_list[i].chunk_buf_size = MAX(chunk_list[i].chunk_current.length, file_chunk_size); - if (H5D__scatter_mem(tmp_gath_buf, mem_iter, (size_t)iter_nelmts, io_info->u.rbuf) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "couldn't scatter to read buffer") + /* + * If this chunk hasn't been allocated yet and we aren't writing + * out fill values to it, make sure to 0-fill its memory buffer + * so we don't use uninitialized memory. + */ + if (!H5F_addr_defined(chunk_list[i].chunk_current.offset) && !should_fill) + chunk_list[i].buf = H5MM_calloc(chunk_list[i].chunk_buf_size); + else + chunk_list[i].buf = H5MM_malloc(chunk_list[i].chunk_buf_size); + if (NULL == chunk_list[i].buf) { + /* Push an error, but participate in collective read */ + HDONE_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate chunk data buffer") break; + } + + /* Set chunk's new length for eventual filter pipeline calls */ + if (chunk_list[i].need_read) { + /* + * Check if chunk is currently allocated. If not, don't try to + * read it from the file. Instead, just fill the chunk buffer + * with the fill value if fill values are to be written. + */ + if (H5F_addr_defined(chunk_list[i].chunk_current.offset)) { + /* Set first read buffer */ + if (!base_read_buf) + base_read_buf = chunk_list[i].buf; + + /* Set chunk's new length for eventual filter pipeline calls */ + if (chunk_list[i].skip_filter_pline) + chunk_list[i].chunk_new.length = file_chunk_size; + else + chunk_list[i].chunk_new.length = chunk_list[i].chunk_current.length; + } + else { + chunk_list[i].need_read = FALSE; + + /* Set chunk's new length for eventual filter pipeline calls */ + chunk_list[i].chunk_new.length = file_chunk_size; + + if (should_fill) { + /* Initialize fill value buffer if not already initialized */ + if (!fb_info_init) { + hsize_t chunk_dims[H5S_MAX_RANK]; + + HDassert(io_info->dset->shared->ndims == + io_info->dset->shared->layout.u.chunk.ndims - 1); + for (size_t j = 0; j < io_info->dset->shared->layout.u.chunk.ndims - 1; j++) + chunk_dims[j] = (hsize_t)io_info->dset->shared->layout.u.chunk.dim[j]; + + /* Get a dataspace for filling chunk memory buffers */ + if (NULL == (fill_space = H5S_create_simple( + io_info->dset->shared->layout.u.chunk.ndims - 1, chunk_dims, NULL))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, + "unable to create chunk fill dataspace") + + /* Initialize fill value buffer */ + if (H5D__fill_init(&fb_info, NULL, (H5MM_allocate_t)H5D__chunk_mem_alloc, + (void *)&io_info->dset->shared->dcpl_cache.pline, + (H5MM_free_t)H5D__chunk_mem_free, + (void *)&io_info->dset->shared->dcpl_cache.pline, + &io_info->dset->shared->dcpl_cache.fill, + io_info->dset->shared->type, io_info->dset->shared->type_id, 0, + file_chunk_size) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize fill value buffer") + + fb_info_init = TRUE; + } + + /* Write fill value to memory buffer */ + HDassert(fb_info.fill_buf); + if (H5D__fill(fb_info.fill_buf, io_info->dset->shared->type, chunk_list[i].buf, + type_info->mem_type, fill_space) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, + "couldn't fill chunk buffer with fill value") + } + } + } + else + chunk_list[i].chunk_new.length = file_chunk_size; + } - case H5D_IO_OP_WRITE: - iter_nelmts = H5S_GET_SELECT_NPOINTS(chunk_info->mspace); + /* + * If dataset is incrementally allocated and hasn't been written to + * yet, the chunk index should be empty. In this case, a collective + * read of chunks is essentially a no-op, so avoid it here. + */ + index_empty = FALSE; + if (io_info->dset->shared->dcpl_cache.fill.alloc_time == H5D_ALLOC_TIME_INCR) + if (H5D__chunk_index_empty(io_info->dset, &index_empty) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "couldn't determine if chunk index is empty") - if (NULL == (tmp_gath_buf = H5MM_malloc(iter_nelmts * type_info->src_type_size))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate temporary gather buffer") + if (!index_empty) { + /* + * Setup for I/O operation + */ - /* Gather modification data from the application write buffer into a temporary buffer */ - if (0 == H5D__gather_mem(io_info->u.wbuf, mem_iter, (size_t)iter_nelmts, tmp_gath_buf)) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "couldn't gather from write buffer") + /* Initialize temporary I/O info */ + coll_io_info = *io_info; + coll_io_info.op_type = H5D_IO_OP_READ; - if (H5S_SELECT_ITER_RELEASE(mem_iter) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "couldn't release selection iterator") - mem_iter_init = FALSE; + /* Override the read buffer to point to the address of the first + * chunk data buffer being read into + */ + if (base_read_buf) + coll_io_info.u.rbuf = base_read_buf; - /* Initialize iterator for file selection */ - if (H5S_select_iter_init(mem_iter, chunk_info->fspace, type_info->dst_type_size, 0) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, - "unable to initialize file selection information") - mem_iter_init = TRUE; + /* Read all chunks that need to be read from the file */ + if (H5D__mpio_collective_filtered_chunk_common_io(chunk_list, chunk_list_num_entries, &coll_io_info, + type_info, mpi_size) < 0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "couldn't finish collective filtered chunk read") + } - iter_nelmts = H5S_GET_SELECT_NPOINTS(chunk_info->fspace); + /* + * Now that all owned chunks have been read, update the chunks + * with modification data from the owning rank and other ranks. + */ - /* Scatter the owner's modification data into the chunk data buffer according to - * the file space. - */ - if (H5D__scatter_mem(tmp_gath_buf, mem_iter, (size_t)iter_nelmts, chunk_entry->buf) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "couldn't scatter to chunk data buffer") + /* Process all chunks with data from the owning rank first */ + for (i = 0; i < chunk_list_num_entries; i++) { + HDassert(mpi_rank == chunk_list[i].new_owner); - if (H5S_SELECT_ITER_RELEASE(mem_iter) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "couldn't release selection iterator") - mem_iter_init = FALSE; + chunk_info = chunk_list[i].chunk_info; - if (MPI_SUCCESS != - (mpi_code = MPI_Waitall(chunk_entry->async_info.num_receive_requests, - chunk_entry->async_info.receive_requests_array, MPI_STATUSES_IGNORE))) - HMPI_GOTO_ERROR(FAIL, "MPI_Waitall failed", mpi_code) + /* + * If this chunk wasn't being fully overwritten, we read it from + * the file, so we need to unfilter it + */ + if (chunk_list[i].need_read && !chunk_list[i].skip_filter_pline) { + if (H5Z_pipeline(&io_info->dset->shared->dcpl_cache.pline, H5Z_FLAG_REVERSE, + &(chunk_list[i].index_info.filter_mask), err_detect, filter_cb, + (size_t *)&chunk_list[i].chunk_new.length, &chunk_list[i].chunk_buf_size, + &chunk_list[i].buf) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTFILTER, FAIL, "couldn't unfilter chunk for modifying") + } + + iter_nelmts = H5S_GET_SELECT_NPOINTS(chunk_info->mspace); + + if (H5D_select_io_mem(chunk_list[i].buf, chunk_info->fspace, io_info->u.wbuf, chunk_info->mspace, + type_info->dst_type_size, (size_t)iter_nelmts) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "couldn't copy chunk data to write buffer") + } - /* For each asynchronous receive call previously posted, receive the chunk modification - * buffer from another rank and update the chunk data - */ - for (i = 0; i < (size_t)chunk_entry->async_info.num_receive_requests; i++) { - const unsigned char *mod_data_p; + /* Allocate iterator for memory selection */ + if (NULL == (sel_iter = H5FL_MALLOC(H5S_sel_iter_t))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate memory iterator") - /* Decode the process' chunk file dataspace */ - mod_data_p = chunk_entry->async_info.receive_buffer_array[i]; - if (NULL == (dataspace = H5S_decode(&mod_data_p))) + /* Now process all received chunk message buffers */ + for (i = 0; i < (size_t)chunk_msg_bufs_len; i++) { + H5D_filtered_collective_io_info_t *chunk_entry = NULL; + const unsigned char * msg_ptr = chunk_msg_bufs[i]; + hsize_t chunk_idx; + + if (msg_ptr) { + /* Retrieve the chunk's index value */ + HDmemcpy(&chunk_idx, msg_ptr, sizeof(hsize_t)); + msg_ptr += sizeof(hsize_t); + + /* Find the chunk entry according to its chunk index */ + HASH_FIND(hh, chunk_hash_table, &chunk_idx, sizeof(hsize_t), chunk_entry); + HDassert(chunk_entry); + HDassert(mpi_rank == chunk_entry->new_owner); + + /* + * Only process the chunk if its data buffer is allocated. + * In the case of multi-chunk I/O, we're only working on + * a chunk at a time, so we need to skip over messages + * that aren't for the chunk we're currently working on. + */ + if (!chunk_entry->buf) + continue; + else { + /* Decode the chunk file dataspace from the message */ + if (NULL == (dataspace = H5S_decode(&msg_ptr))) HGOTO_ERROR(H5E_DATASET, H5E_CANTDECODE, FAIL, "unable to decode dataspace") - if (H5S_select_iter_init(mem_iter, dataspace, type_info->dst_type_size, 0) < 0) + if (H5S_select_iter_init(sel_iter, dataspace, type_info->dst_type_size, + H5S_SEL_ITER_SHARE_WITH_DATASPACE) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize memory selection information") - mem_iter_init = TRUE; + sel_iter_init = TRUE; iter_nelmts = H5S_GET_SELECT_NPOINTS(dataspace); /* Update the chunk data with the received modification data */ - if (H5D__scatter_mem(mod_data_p, mem_iter, (size_t)iter_nelmts, chunk_entry->buf) < 0) + if (H5D__scatter_mem(msg_ptr, sel_iter, (size_t)iter_nelmts, chunk_entry->buf) < 0) HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "couldn't scatter to write buffer") - if (H5S_SELECT_ITER_RELEASE(mem_iter) < 0) + if (H5S_SELECT_ITER_RELEASE(sel_iter) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "couldn't release selection iterator") - mem_iter_init = FALSE; + sel_iter_init = FALSE; + if (dataspace) { if (H5S_close(dataspace) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTFREE, FAIL, "can't close dataspace") dataspace = NULL; } - H5MM_free(chunk_entry->async_info.receive_buffer_array[i]); - } /* end for */ - /* Filter the chunk */ - if (H5Z_pipeline(&io_info->dset->shared->dcpl_cache.pline, 0, &filter_mask, err_detect, filter_cb, - (size_t *)&chunk_entry->chunk_states.new_chunk.length, &buf_size, - &chunk_entry->buf) < 0) + H5MM_free(chunk_msg_bufs[i]); + chunk_msg_bufs[i] = NULL; + } + } + } + + /* Finally, filter all the chunks */ + for (i = 0; i < chunk_list_num_entries; i++) { + if (!chunk_list[i].skip_filter_pline) { + if (H5Z_pipeline(&io_info->dset->shared->dcpl_cache.pline, 0, + &(chunk_list[i].index_info.filter_mask), err_detect, filter_cb, + (size_t *)&chunk_list[i].chunk_new.length, &chunk_list[i].chunk_buf_size, + &chunk_list[i].buf) < 0) HGOTO_ERROR(H5E_PLINE, H5E_CANTFILTER, FAIL, "output pipeline failed") + } #if H5_SIZEOF_SIZE_T > 4 - /* Check for the chunk expanding too much to encode in a 32-bit value */ - if (chunk_entry->chunk_states.new_chunk.length > ((size_t)0xffffffff)) - HGOTO_ERROR(H5E_DATASET, H5E_BADRANGE, FAIL, "chunk too large for 32-bit length") + /* Check for the chunk expanding too much to encode in a 32-bit value */ + if (chunk_list[i].chunk_new.length > ((size_t)0xffffffff)) + HGOTO_ERROR(H5E_DATASET, H5E_BADRANGE, FAIL, "chunk too large for 32-bit length") #endif - break; + } - default: - HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "invalid I/O operation") - } /* end switch */ +done: + if (sel_iter) { + if (sel_iter_init && H5S_SELECT_ITER_RELEASE(sel_iter) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "couldn't release selection iterator") + sel_iter = H5FL_FREE(H5S_sel_iter_t, sel_iter); + } + if (dataspace && (H5S_close(dataspace) < 0)) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTFREE, FAIL, "can't close dataspace") + if (fill_space && (H5S_close(fill_space) < 0)) + HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "can't close fill space") + + /* Release the fill buffer info, if it's been initialized */ + if (fb_info_init && H5D__fill_term(&fb_info) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release fill buffer info") + + /* On failure, try to free all resources used by entries in the chunk list */ + if (ret_value < 0) { + for (i = 0; i < chunk_list_num_entries; i++) { + if (chunk_list[i].buf) { + H5MM_free(chunk_list[i].buf); + chunk_list[i].buf = NULL; + } + } + } + +#ifdef H5Dmpio_DEBUG + H5D_MPIO_TIME_STOP(mpi_rank); + H5D_MPIO_TRACE_EXIT(mpi_rank); +#endif + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D__mpio_collective_filtered_chunk_update() */ + +/*------------------------------------------------------------------------- + * Function: H5D__mpio_collective_filtered_chunk_reallocate + * + * Purpose: When performing a parallel write on a chunked dataset with + * filters applied, all ranks must eventually get together and + * perform a collective reallocation of space in the file for + * all chunks that were modified on all ranks. This routine is + * responsible for coordinating that process. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D__mpio_collective_filtered_chunk_reallocate(H5D_filtered_collective_io_info_t *chunk_list, + size_t chunk_list_num_entries, size_t *num_chunks_assigned_map, + H5D_io_info_t *io_info, H5D_chk_idx_info_t *idx_info, + int mpi_rank, int mpi_size) +{ + H5D_chunk_alloc_info_t *collective_list = NULL; + MPI_Datatype send_type; + MPI_Datatype recv_type; + hbool_t send_type_derived = FALSE; + hbool_t recv_type_derived = FALSE; + hbool_t need_sort = FALSE; + size_t collective_num_entries = 0; + size_t num_local_chunks_processed = 0; + size_t i; + void * gathered_array = NULL; + int * counts_disps_array = NULL; + int * counts_ptr = NULL; + int * displacements_ptr = NULL; + int mpi_code; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC + + HDassert(chunk_list || 0 == chunk_list_num_entries); + HDassert(io_info); + HDassert(idx_info); + HDassert(idx_info->storage->idx_type != H5D_CHUNK_IDX_NONE); + +#ifdef H5Dmpio_DEBUG + H5D_MPIO_TRACE_ENTER(mpi_rank); + H5D_MPIO_TIME_START(mpi_rank, "Reallocation of chunk file space"); +#endif + + /* + * Make sure it's safe to cast this rank's number + * of chunks to be sent into an int for MPI + */ + H5_CHECK_OVERFLOW(chunk_list_num_entries, size_t, int); + + /* Create derived datatypes for the chunk file space info needed */ + if (H5D__mpio_get_chunk_alloc_info_types(&recv_type, &recv_type_derived, &send_type, &send_type_derived) < + 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, + "can't create derived datatypes for chunk file space info") + + /* + * Gather the new chunk sizes to all ranks for a collective reallocation + * of the chunks in the file. + */ + if (num_chunks_assigned_map) { + /* + * If a mapping between rank value -> number of assigned chunks has + * been provided (usually during linked-chunk I/O), we can use this + * to optimize MPI overhead a bit since MPI ranks won't need to + * first inform each other about how many chunks they're contributing. + */ + if (NULL == (counts_disps_array = H5MM_malloc(2 * (size_t)mpi_size * sizeof(*counts_disps_array)))) { + /* Push an error, but still participate in collective gather operation */ + HDONE_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "couldn't allocate receive counts and displacements array") + } + else { + /* Set the receive counts from the assigned chunks map */ + counts_ptr = counts_disps_array; + + for (i = 0; i < (size_t)mpi_size; i++) + H5_CHECKED_ASSIGN(counts_ptr[i], int, num_chunks_assigned_map[i], size_t); + + /* Set the displacements into the receive buffer for the gather operation */ + displacements_ptr = &counts_disps_array[mpi_size]; + + *displacements_ptr = 0; + for (i = 1; i < (size_t)mpi_size; i++) + displacements_ptr[i] = displacements_ptr[i - 1] + counts_ptr[i - 1]; + } + + /* Perform gather operation */ + if (H5_mpio_gatherv_alloc(chunk_list, (int)chunk_list_num_entries, send_type, counts_ptr, + displacements_ptr, recv_type, TRUE, 0, io_info->comm, mpi_rank, mpi_size, + &gathered_array, &collective_num_entries) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGATHER, FAIL, "can't gather chunk file space info to/from ranks") + } + else { + /* + * If no mapping between rank value -> number of assigned chunks has + * been provided (usually during multi-chunk I/O), all MPI ranks will + * need to first inform other ranks about how many chunks they're + * contributing before performing the actual gather operation. Use + * the 'simple' MPI_Allgatherv wrapper for this. + */ + if (H5_mpio_gatherv_alloc_simple(chunk_list, (int)chunk_list_num_entries, send_type, recv_type, TRUE, + 0, io_info->comm, mpi_rank, mpi_size, &gathered_array, + &collective_num_entries) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGATHER, FAIL, "can't gather chunk file space info to/from ranks") + } + + /* Collectively re-allocate the modified chunks (from each rank) in the file */ + collective_list = (H5D_chunk_alloc_info_t *)gathered_array; + for (i = 0, num_local_chunks_processed = 0; i < collective_num_entries; i++) { + H5D_chunk_alloc_info_t *coll_entry = &collective_list[i]; + hbool_t need_insert; + hbool_t update_local_chunk; + + if (H5D__chunk_file_alloc(idx_info, &coll_entry->chunk_current, &coll_entry->chunk_new, &need_insert, + NULL) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "unable to allocate chunk") + + /* + * If we just re-allocated a chunk that is local to this + * rank, make sure to update the chunk entry in the local + * chunk list + */ + update_local_chunk = + (num_local_chunks_processed < chunk_list_num_entries) && + (coll_entry->chunk_idx == chunk_list[num_local_chunks_processed].index_info.chunk_idx); + + if (update_local_chunk) { + H5D_filtered_collective_io_info_t *local_chunk; + + local_chunk = &chunk_list[num_local_chunks_processed]; + + /* Sanity check that this chunk is actually local */ + HDassert(mpi_rank == local_chunk->orig_owner); + HDassert(mpi_rank == local_chunk->new_owner); + + local_chunk->chunk_new = coll_entry->chunk_new; + local_chunk->index_info.need_insert = need_insert; + + /* + * Since chunk reallocation can move chunks around, check if + * the local chunk list is still in ascending offset of order + * in the file + */ + if (num_local_chunks_processed) { + haddr_t curr_chunk_offset = local_chunk->chunk_new.offset; + haddr_t prev_chunk_offset = chunk_list[num_local_chunks_processed - 1].chunk_new.offset; + + HDassert(H5F_addr_defined(prev_chunk_offset) && H5F_addr_defined(curr_chunk_offset)); + if (curr_chunk_offset < prev_chunk_offset) + need_sort = TRUE; + } + + num_local_chunks_processed++; + } + } + + HDassert(chunk_list_num_entries == num_local_chunks_processed); + + /* + * Ensure this rank's local chunk list is sorted in + * ascending order of offset in the file + */ + if (need_sort) + HDqsort(chunk_list, chunk_list_num_entries, sizeof(H5D_filtered_collective_io_info_t), + H5D__cmp_filtered_collective_io_info_entry); + +done: + H5MM_free(gathered_array); + H5MM_free(counts_disps_array); + + if (send_type_derived) { + if (MPI_SUCCESS != (mpi_code = MPI_Type_free(&send_type))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + } + if (recv_type_derived) { + if (MPI_SUCCESS != (mpi_code = MPI_Type_free(&recv_type))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + } + +#ifdef H5Dmpio_DEBUG + H5D_MPIO_TIME_STOP(mpi_rank); + H5D_MPIO_TRACE_EXIT(mpi_rank); +#endif + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5D__mpio_collective_filtered_chunk_reallocate() */ + +/*------------------------------------------------------------------------- + * Function: H5D__mpio_collective_filtered_chunk_reinsert + * + * Purpose: When performing a parallel write on a chunked dataset with + * filters applied, all ranks must eventually get together and + * perform a collective reinsertion into the dataset's chunk + * index of chunks that were modified. This routine is + * responsible for coordinating that process. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D__mpio_collective_filtered_chunk_reinsert(H5D_filtered_collective_io_info_t *chunk_list, + size_t chunk_list_num_entries, size_t *num_chunks_assigned_map, + H5D_io_info_t *io_info, H5D_chk_idx_info_t *idx_info, + int mpi_rank, int mpi_size) +{ + H5D_chunk_ud_t chunk_ud; + MPI_Datatype send_type; + MPI_Datatype recv_type; + hbool_t send_type_derived = FALSE; + hbool_t recv_type_derived = FALSE; + hsize_t scaled_coords[H5O_LAYOUT_NDIMS]; + size_t collective_num_entries = 0; + size_t i; + void * gathered_array = NULL; + int * counts_disps_array = NULL; + int * counts_ptr = NULL; + int * displacements_ptr = NULL; + int mpi_code; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC + + HDassert(chunk_list || 0 == chunk_list_num_entries); + HDassert(io_info); + HDassert(idx_info); + +#ifdef H5Dmpio_DEBUG + H5D_MPIO_TRACE_ENTER(mpi_rank); + H5D_MPIO_TIME_START(mpi_rank, "Reinsertion of modified chunks into chunk index"); +#endif + + /* Only re-insert chunks if index has an insert method */ + if (!idx_info->storage->ops->insert) + HGOTO_DONE(SUCCEED); + + /* + * Make sure it's safe to cast this rank's number + * of chunks to be sent into an int for MPI + */ + H5_CHECK_OVERFLOW(chunk_list_num_entries, size_t, int); + + /* Create derived datatypes for the chunk re-insertion info needed */ + if (H5D__mpio_get_chunk_insert_info_types(&recv_type, &recv_type_derived, &send_type, + &send_type_derived) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, + "can't create derived datatypes for chunk re-insertion info") + + /* + * Gather information to all ranks for a collective re-insertion + * of the modified chunks into the chunk index + */ + if (num_chunks_assigned_map) { + /* + * If a mapping between rank value -> number of assigned chunks has + * been provided (usually during linked-chunk I/O), we can use this + * to optimize MPI overhead a bit since MPI ranks won't need to + * first inform each other about how many chunks they're contributing. + */ + if (NULL == (counts_disps_array = H5MM_malloc(2 * (size_t)mpi_size * sizeof(*counts_disps_array)))) { + /* Push an error, but still participate in collective gather operation */ + HDONE_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "couldn't allocate receive counts and displacements array") + } + else { + /* Set the receive counts from the assigned chunks map */ + counts_ptr = counts_disps_array; + + for (i = 0; i < (size_t)mpi_size; i++) + H5_CHECKED_ASSIGN(counts_ptr[i], int, num_chunks_assigned_map[i], size_t); + + /* Set the displacements into the receive buffer for the gather operation */ + displacements_ptr = &counts_disps_array[mpi_size]; + + *displacements_ptr = 0; + for (i = 1; i < (size_t)mpi_size; i++) + displacements_ptr[i] = displacements_ptr[i - 1] + counts_ptr[i - 1]; + } + + /* Perform gather operation */ + if (H5_mpio_gatherv_alloc(chunk_list, (int)chunk_list_num_entries, send_type, counts_ptr, + displacements_ptr, recv_type, TRUE, 0, io_info->comm, mpi_rank, mpi_size, + &gathered_array, &collective_num_entries) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGATHER, FAIL, + "can't gather chunk index re-insertion info to/from ranks") + } + else { + /* + * If no mapping between rank value -> number of assigned chunks has + * been provided (usually during multi-chunk I/O), all MPI ranks will + * need to first inform other ranks about how many chunks they're + * contributing before performing the actual gather operation. Use + * the 'simple' MPI_Allgatherv wrapper for this. + */ + if (H5_mpio_gatherv_alloc_simple(chunk_list, (int)chunk_list_num_entries, send_type, recv_type, TRUE, + 0, io_info->comm, mpi_rank, mpi_size, &gathered_array, + &collective_num_entries) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGATHER, FAIL, + "can't gather chunk index re-insertion info to/from ranks") + } + + /* Initialize static chunk udata fields from chunk index info */ + H5D_MPIO_INIT_CHUNK_UD_INFO(chunk_ud, idx_info); + + for (i = 0; i < collective_num_entries; i++) { + H5D_chunk_insert_info_t *coll_entry = &((H5D_chunk_insert_info_t *)gathered_array)[i]; + + /* + * We only need to reinsert this chunk if we had to actually + * allocate or reallocate space in the file for it + */ + if (!coll_entry->index_info.need_insert) + continue; + + chunk_ud.chunk_block = coll_entry->chunk_block; + chunk_ud.chunk_idx = coll_entry->index_info.chunk_idx; + chunk_ud.filter_mask = coll_entry->index_info.filter_mask; + chunk_ud.common.scaled = scaled_coords; + + /* Calculate scaled coordinates for the chunk */ + if (idx_info->layout->idx_type == H5D_CHUNK_IDX_EARRAY && idx_info->layout->u.earray.unlim_dim > 0) { + /* + * Extensible arrays where the unlimited dimension is not + * the slowest-changing dimension "swizzle" the coordinates + * to move the unlimited dimension value to offset 0. Therefore, + * we use the "swizzled" down chunks to calculate the "swizzled" + * scaled coordinates and then we undo the "swizzle" operation. + * + * TODO: In the future, this is something that should be handled + * by the particular chunk index rather than manually + * here. Likely, the chunk index ops should get a new + * callback that accepts a chunk index and provides the + * caller with the scaled coordinates for that chunk. + */ + H5VM_array_calc_pre(chunk_ud.chunk_idx, io_info->dset->shared->ndims, + idx_info->layout->u.earray.swizzled_down_chunks, scaled_coords); + + H5VM_unswizzle_coords(hsize_t, scaled_coords, idx_info->layout->u.earray.unlim_dim); + } + else { + H5VM_array_calc_pre(chunk_ud.chunk_idx, io_info->dset->shared->ndims, + io_info->dset->shared->layout.u.chunk.down_chunks, scaled_coords); + } + + scaled_coords[io_info->dset->shared->ndims] = 0; + +#ifndef NDEBUG + /* + * If a matching local chunk entry is found, the + * `chunk_info` structure (which contains the chunk's + * pre-computed scaled coordinates) will be valid + * for this rank. Compare those coordinates against + * the calculated coordinates above to make sure + * they match. + */ + for (size_t dbg_idx = 0; dbg_idx < chunk_list_num_entries; dbg_idx++) { + if (coll_entry->index_info.chunk_idx == chunk_list[dbg_idx].index_info.chunk_idx) { + hbool_t coords_match = !HDmemcmp(scaled_coords, chunk_list[dbg_idx].chunk_info->scaled, + io_info->dset->shared->ndims * sizeof(hsize_t)); + + HDassert(coords_match && "Calculated scaled coordinates for chunk didn't match " + "chunk's actual scaled coordinates!"); + break; + } + } +#endif + + if ((idx_info->storage->ops->insert)(idx_info, &chunk_ud, io_info->dset) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert chunk address into index") + } + +done: + H5MM_free(gathered_array); + H5MM_free(counts_disps_array); + + if (send_type_derived) { + if (MPI_SUCCESS != (mpi_code = MPI_Type_free(&send_type))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + } + if (recv_type_derived) { + if (MPI_SUCCESS != (mpi_code = MPI_Type_free(&recv_type))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + } + +#ifdef H5Dmpio_DEBUG + H5D_MPIO_TIME_STOP(mpi_rank); + H5D_MPIO_TRACE_EXIT(mpi_rank); +#endif + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D__mpio_collective_filtered_chunk_reinsert() */ + +/*------------------------------------------------------------------------- + * Function: H5D__mpio_get_chunk_redistribute_info_types + * + * Purpose: Constructs MPI derived datatypes for communicating the + * info from a H5D_filtered_collective_io_info_t structure + * that is necessary for redistributing shared chunks during a + * collective write of filtered chunks. + * + * The datatype returned through `contig_type` has an extent + * equal to the size of an H5D_chunk_redistribute_info_t + * structure and is suitable for communicating that structure + * type. + * + * The datatype returned through `resized_type` has an extent + * equal to the size of an H5D_filtered_collective_io_info_t + * structure. This makes it suitable for sending an array of + * those structures, while extracting out just the info + * necessary for the chunk redistribution operation during + * communication. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D__mpio_get_chunk_redistribute_info_types(MPI_Datatype *contig_type, hbool_t *contig_type_derived, + MPI_Datatype *resized_type, hbool_t *resized_type_derived) +{ + MPI_Datatype struct_type = MPI_DATATYPE_NULL; + hbool_t struct_type_derived = FALSE; + MPI_Datatype chunk_block_type = MPI_DATATYPE_NULL; + hbool_t chunk_block_type_derived = FALSE; + MPI_Datatype types[5]; + MPI_Aint displacements[5]; + int block_lengths[5]; + int field_count; + int mpi_code; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC + + HDassert(contig_type); + HDassert(contig_type_derived); + HDassert(resized_type); + HDassert(resized_type_derived); + + *contig_type_derived = FALSE; + *resized_type_derived = FALSE; + + /* Create struct type for the inner H5F_block_t structure */ + if (H5F_mpi_get_file_block_type(FALSE, &chunk_block_type, &chunk_block_type_derived) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't create derived type for chunk file description") + + field_count = 5; + HDassert(field_count == (sizeof(types) / sizeof(MPI_Datatype))); + + /* + * Create structure type to pack chunk H5F_block_t structure + * next to chunk_idx, orig_owner, new_owner and num_writers + * fields + */ + block_lengths[0] = 1; + block_lengths[1] = 1; + block_lengths[2] = 1; + block_lengths[3] = 1; + block_lengths[4] = 1; + displacements[0] = offsetof(H5D_chunk_redistribute_info_t, chunk_block); + displacements[1] = offsetof(H5D_chunk_redistribute_info_t, chunk_idx); + displacements[2] = offsetof(H5D_chunk_redistribute_info_t, orig_owner); + displacements[3] = offsetof(H5D_chunk_redistribute_info_t, new_owner); + displacements[4] = offsetof(H5D_chunk_redistribute_info_t, num_writers); + types[0] = chunk_block_type; + types[1] = HSIZE_AS_MPI_TYPE; + types[2] = MPI_INT; + types[3] = MPI_INT; + types[4] = MPI_INT; + if (MPI_SUCCESS != + (mpi_code = MPI_Type_create_struct(field_count, block_lengths, displacements, types, contig_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_struct failed", mpi_code) + *contig_type_derived = TRUE; + + if (MPI_SUCCESS != (mpi_code = MPI_Type_commit(contig_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code) + + /* Create struct type to extract the chunk_current, chunk_idx, orig_owner, + * new_owner and num_writers fields from a H5D_filtered_collective_io_info_t + * structure + */ + block_lengths[0] = 1; + block_lengths[1] = 1; + block_lengths[2] = 1; + block_lengths[3] = 1; + block_lengths[4] = 1; + displacements[0] = offsetof(H5D_filtered_collective_io_info_t, chunk_current); + displacements[1] = offsetof(H5D_filtered_collective_io_info_t, index_info.chunk_idx); + displacements[2] = offsetof(H5D_filtered_collective_io_info_t, orig_owner); + displacements[3] = offsetof(H5D_filtered_collective_io_info_t, new_owner); + displacements[4] = offsetof(H5D_filtered_collective_io_info_t, num_writers); + types[0] = chunk_block_type; + types[1] = HSIZE_AS_MPI_TYPE; + types[2] = MPI_INT; + types[3] = MPI_INT; + types[4] = MPI_INT; + if (MPI_SUCCESS != + (mpi_code = MPI_Type_create_struct(field_count, block_lengths, displacements, types, &struct_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_struct failed", mpi_code) + struct_type_derived = TRUE; + + if (MPI_SUCCESS != (mpi_code = MPI_Type_create_resized( + struct_type, 0, sizeof(H5D_filtered_collective_io_info_t), resized_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_resized failed", mpi_code) + *resized_type_derived = TRUE; + + if (MPI_SUCCESS != (mpi_code = MPI_Type_commit(resized_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code) + +done: + if (struct_type_derived) { + if (MPI_SUCCESS != (mpi_code = MPI_Type_free(&struct_type))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + } + if (chunk_block_type_derived) { + if (MPI_SUCCESS != (mpi_code = MPI_Type_free(&chunk_block_type))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + } + + if (ret_value < 0) { + if (*resized_type_derived) { + if (MPI_SUCCESS != (mpi_code = MPI_Type_free(resized_type))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + *resized_type_derived = FALSE; + } + if (*contig_type_derived) { + if (MPI_SUCCESS != (mpi_code = MPI_Type_free(contig_type))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + *contig_type_derived = FALSE; + } + } + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D__mpio_get_chunk_redistribute_info_types() */ + +/*------------------------------------------------------------------------- + * Function: H5D__mpio_get_chunk_alloc_info_types + * + * Purpose: Constructs MPI derived datatypes for communicating the info + * from a H5D_filtered_collective_io_info_t structure that is + * necessary for re-allocating file space during a collective + * write of filtered chunks. + * + * The datatype returned through `contig_type` has an extent + * equal to the size of an H5D_chunk_alloc_info_t structure + * and is suitable for communicating that structure type. + * + * The datatype returned through `resized_type` has an extent + * equal to the size of an H5D_filtered_collective_io_info_t + * structure. This makes it suitable for sending an array of + * those structures, while extracting out just the info + * necessary for the chunk file space reallocation operation + * during communication. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D__mpio_get_chunk_alloc_info_types(MPI_Datatype *contig_type, hbool_t *contig_type_derived, + MPI_Datatype *resized_type, hbool_t *resized_type_derived) +{ + MPI_Datatype struct_type = MPI_DATATYPE_NULL; + hbool_t struct_type_derived = FALSE; + MPI_Datatype chunk_block_type = MPI_DATATYPE_NULL; + hbool_t chunk_block_type_derived = FALSE; + MPI_Datatype types[3]; + MPI_Aint displacements[3]; + int block_lengths[3]; + int field_count; + int mpi_code; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC + + HDassert(contig_type); + HDassert(contig_type_derived); + HDassert(resized_type); + HDassert(resized_type_derived); + + *contig_type_derived = FALSE; + *resized_type_derived = FALSE; + + /* Create struct type for the inner H5F_block_t structure */ + if (H5F_mpi_get_file_block_type(FALSE, &chunk_block_type, &chunk_block_type_derived) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't create derived type for chunk file description") + + field_count = 3; + HDassert(field_count == (sizeof(types) / sizeof(MPI_Datatype))); + + /* + * Create structure type to pack both chunk H5F_block_t structures + * next to chunk_idx field + */ + block_lengths[0] = 1; + block_lengths[1] = 1; + block_lengths[2] = 1; + displacements[0] = offsetof(H5D_chunk_alloc_info_t, chunk_current); + displacements[1] = offsetof(H5D_chunk_alloc_info_t, chunk_new); + displacements[2] = offsetof(H5D_chunk_alloc_info_t, chunk_idx); + types[0] = chunk_block_type; + types[1] = chunk_block_type; + types[2] = HSIZE_AS_MPI_TYPE; + if (MPI_SUCCESS != + (mpi_code = MPI_Type_create_struct(field_count, block_lengths, displacements, types, contig_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_struct failed", mpi_code) + *contig_type_derived = TRUE; + + if (MPI_SUCCESS != (mpi_code = MPI_Type_commit(contig_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code) + + /* + * Create struct type to extract the chunk_current, chunk_new and chunk_idx + * fields from a H5D_filtered_collective_io_info_t structure + */ + block_lengths[0] = 1; + block_lengths[1] = 1; + block_lengths[2] = 1; + displacements[0] = offsetof(H5D_filtered_collective_io_info_t, chunk_current); + displacements[1] = offsetof(H5D_filtered_collective_io_info_t, chunk_new); + displacements[2] = offsetof(H5D_filtered_collective_io_info_t, index_info.chunk_idx); + types[0] = chunk_block_type; + types[1] = chunk_block_type; + types[2] = HSIZE_AS_MPI_TYPE; + if (MPI_SUCCESS != + (mpi_code = MPI_Type_create_struct(field_count, block_lengths, displacements, types, &struct_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_struct failed", mpi_code) + struct_type_derived = TRUE; + + if (MPI_SUCCESS != (mpi_code = MPI_Type_create_resized( + struct_type, 0, sizeof(H5D_filtered_collective_io_info_t), resized_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_resized failed", mpi_code) + *resized_type_derived = TRUE; + + if (MPI_SUCCESS != (mpi_code = MPI_Type_commit(resized_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code) + +done: + if (struct_type_derived) { + if (MPI_SUCCESS != (mpi_code = MPI_Type_free(&struct_type))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + } + if (chunk_block_type_derived) { + if (MPI_SUCCESS != (mpi_code = MPI_Type_free(&chunk_block_type))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + } + + if (ret_value < 0) { + if (*resized_type_derived) { + if (MPI_SUCCESS != (mpi_code = MPI_Type_free(resized_type))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + *resized_type_derived = FALSE; + } + if (*contig_type_derived) { + if (MPI_SUCCESS != (mpi_code = MPI_Type_free(contig_type))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + *contig_type_derived = FALSE; + } + } + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D__mpio_get_chunk_alloc_info_types() */ + +/*------------------------------------------------------------------------- + * Function: H5D__mpio_get_chunk_insert_info_types + * + * Purpose: Constructs MPI derived datatypes for communicating the + * information necessary when reinserting chunks into a + * dataset's chunk index. This includes the chunk's new offset + * and size (H5F_block_t) and the inner `index_info` structure + * of a H5D_filtered_collective_io_info_t structure. + * + * The datatype returned through `contig_type` has an extent + * equal to the size of an H5D_chunk_insert_info_t structure + * and is suitable for communicating that structure type. + * + * The datatype returned through `resized_type` has an extent + * equal to the size of the encompassing + * H5D_filtered_collective_io_info_t structure. This makes it + * suitable for sending an array of + * H5D_filtered_collective_io_info_t structures, while + * extracting out just the information needed during + * communication. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D__mpio_get_chunk_insert_info_types(MPI_Datatype *contig_type, hbool_t *contig_type_derived, + MPI_Datatype *resized_type, hbool_t *resized_type_derived) +{ + MPI_Datatype struct_type = MPI_DATATYPE_NULL; + hbool_t struct_type_derived = FALSE; + MPI_Datatype chunk_block_type = MPI_DATATYPE_NULL; + hbool_t chunk_block_type_derived = FALSE; + MPI_Aint contig_type_extent; + MPI_Datatype types[4]; + MPI_Aint displacements[4]; + int block_lengths[4]; + int field_count; + int mpi_code; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC + + HDassert(contig_type); + HDassert(contig_type_derived); + HDassert(resized_type); + HDassert(resized_type_derived); + + *contig_type_derived = FALSE; + *resized_type_derived = FALSE; + + /* Create struct type for an H5F_block_t structure */ + if (H5F_mpi_get_file_block_type(FALSE, &chunk_block_type, &chunk_block_type_derived) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't create derived type for chunk file description") + + field_count = 4; + HDassert(field_count == (sizeof(types) / sizeof(MPI_Datatype))); + + /* + * Create struct type to pack information into memory as follows: + * + * Chunk's new Offset/Size (H5F_block_t) -> + * Chunk Index Info (H5D_chunk_index_info_t) + */ + block_lengths[0] = 1; + block_lengths[1] = 1; + block_lengths[2] = 1; + block_lengths[3] = 1; + displacements[0] = offsetof(H5D_chunk_insert_info_t, chunk_block); + displacements[1] = offsetof(H5D_chunk_insert_info_t, index_info.chunk_idx); + displacements[2] = offsetof(H5D_chunk_insert_info_t, index_info.filter_mask); + displacements[3] = offsetof(H5D_chunk_insert_info_t, index_info.need_insert); + types[0] = chunk_block_type; + types[1] = HSIZE_AS_MPI_TYPE; + types[2] = MPI_UNSIGNED; + types[3] = MPI_C_BOOL; + if (MPI_SUCCESS != + (mpi_code = MPI_Type_create_struct(field_count, block_lengths, displacements, types, &struct_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_struct failed", mpi_code) + struct_type_derived = TRUE; + + contig_type_extent = (MPI_Aint)(sizeof(H5F_block_t) + sizeof(H5D_chunk_index_info_t)); + + if (MPI_SUCCESS != (mpi_code = MPI_Type_create_resized(struct_type, 0, contig_type_extent, contig_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_resized failed", mpi_code) + *contig_type_derived = TRUE; + + if (MPI_SUCCESS != (mpi_code = MPI_Type_commit(contig_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code) + + struct_type_derived = FALSE; + if (MPI_SUCCESS != (mpi_code = MPI_Type_free(&struct_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + + /* + * Create struct type to correctly extract all needed + * information from a H5D_filtered_collective_io_info_t + * structure. + */ + displacements[0] = offsetof(H5D_filtered_collective_io_info_t, chunk_new); + displacements[1] = offsetof(H5D_filtered_collective_io_info_t, index_info.chunk_idx); + displacements[2] = offsetof(H5D_filtered_collective_io_info_t, index_info.filter_mask); + displacements[3] = offsetof(H5D_filtered_collective_io_info_t, index_info.need_insert); + if (MPI_SUCCESS != + (mpi_code = MPI_Type_create_struct(field_count, block_lengths, displacements, types, &struct_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_struct failed", mpi_code) + struct_type_derived = TRUE; + + if (MPI_SUCCESS != (mpi_code = MPI_Type_create_resized( + struct_type, 0, sizeof(H5D_filtered_collective_io_info_t), resized_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_resized failed", mpi_code) + *resized_type_derived = TRUE; + + if (MPI_SUCCESS != (mpi_code = MPI_Type_commit(resized_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code) done: - if (chunk_entry->async_info.receive_buffer_array) - H5MM_free(chunk_entry->async_info.receive_buffer_array); - if (chunk_entry->async_info.receive_requests_array) - H5MM_free(chunk_entry->async_info.receive_requests_array); - if (tmp_gath_buf) - H5MM_free(tmp_gath_buf); - if (file_iter_init && H5S_SELECT_ITER_RELEASE(file_iter) < 0) - HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "couldn't release selection iterator") - if (file_iter) - H5MM_free(file_iter); - if (mem_iter_init && H5S_SELECT_ITER_RELEASE(mem_iter) < 0) - HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "couldn't release selection iterator") - if (mem_iter) - H5MM_free(mem_iter); - if (dataspace) - if (H5S_close(dataspace) < 0) - HDONE_ERROR(H5E_DATASPACE, H5E_CANTFREE, FAIL, "can't close dataspace") + if (struct_type_derived) { + if (MPI_SUCCESS != (mpi_code = MPI_Type_free(&struct_type))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + } + if (chunk_block_type_derived) { + if (MPI_SUCCESS != (mpi_code = MPI_Type_free(&chunk_block_type))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + } + + if (ret_value < 0) { + if (*resized_type_derived) { + if (MPI_SUCCESS != (mpi_code = MPI_Type_free(resized_type))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + *resized_type_derived = FALSE; + } + if (*contig_type_derived) { + if (MPI_SUCCESS != (mpi_code = MPI_Type_free(contig_type))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + *contig_type_derived = FALSE; + } + } FUNC_LEAVE_NOAPI(ret_value) -} /* end H5D__filtered_collective_chunk_entry_io() */ +} /* end H5D__mpio_get_chunk_insert_info_types() */ + +/*------------------------------------------------------------------------- + * Function: H5D__mpio_collective_filtered_io_type + * + * Purpose: Constructs a MPI derived datatype for both the memory and + * the file for a collective I/O operation on filtered chunks. + * The datatype contains the chunk offsets and lengths in the + * file and the locations of the chunk data buffers to read + * into/write from. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D__mpio_collective_filtered_io_type(H5D_filtered_collective_io_info_t *chunk_list, size_t num_entries, + H5D_io_op_type_t op_type, MPI_Datatype *new_mem_type, + hbool_t *mem_type_derived, MPI_Datatype *new_file_type, + hbool_t *file_type_derived) +{ + MPI_Aint *io_buf_array = NULL; /* Relative displacements of filtered chunk data buffers */ + MPI_Aint *file_offset_array = NULL; /* Chunk offsets in the file */ + int * length_array = NULL; /* Filtered Chunk lengths */ + int mpi_code; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC + + HDassert(chunk_list || 0 == num_entries); + HDassert(new_mem_type); + HDassert(mem_type_derived); + HDassert(new_file_type); + HDassert(file_type_derived); + + *mem_type_derived = FALSE; + *file_type_derived = FALSE; + *new_mem_type = MPI_BYTE; + *new_file_type = MPI_BYTE; + + if (num_entries > 0) { + H5F_block_t *chunk_block; + size_t last_valid_idx = 0; + size_t i; + int chunk_count; + + /* + * Determine number of chunks for I/O operation and + * setup for derived datatype creation if I/O operation + * includes multiple chunks + */ + if (num_entries == 1) { + /* Set last valid index to 0 for contiguous datatype creation */ + last_valid_idx = 0; + + if (op_type == H5D_IO_OP_WRITE) + chunk_count = 1; + else + chunk_count = chunk_list[0].need_read ? 1 : 0; + } + else { + MPI_Aint chunk_buf; + MPI_Aint base_buf; + haddr_t base_offset = HADDR_UNDEF; + + H5_CHECK_OVERFLOW(num_entries, size_t, int); + + /* Allocate arrays */ + if (NULL == (length_array = H5MM_malloc((size_t)num_entries * sizeof(int)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "memory allocation failed for filtered collective I/O length array") + if (NULL == (io_buf_array = H5MM_malloc((size_t)num_entries * sizeof(MPI_Aint)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "memory allocation failed for filtered collective I/O buf length array") + if (NULL == (file_offset_array = H5MM_malloc((size_t)num_entries * sizeof(MPI_Aint)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "memory allocation failed for filtered collective I/O offset array") + + /* + * If doing a write, we can set the base chunk offset + * and base chunk data buffer right away. + * + * If doing a read, some chunks may be skipped over + * for reading if they aren't yet allocated in the + * file. Therefore, we have to find the first chunk + * actually being read in order to set the base chunk + * offset and base chunk data buffer. + */ + if (op_type == H5D_IO_OP_WRITE) { +#if H5_CHECK_MPI_VERSION(3, 0) + if (MPI_SUCCESS != (mpi_code = MPI_Get_address(chunk_list[0].buf, &base_buf))) + HMPI_GOTO_ERROR(FAIL, "MPI_Get_address failed", mpi_code) +#else + base_buf = (MPI_Aint)chunk_list[0].buf; +#endif + + base_offset = chunk_list[0].chunk_new.offset; + } + + for (i = 0, chunk_count = 0; i < num_entries; i++) { + if (op_type == H5D_IO_OP_READ) { + /* + * If this chunk isn't being read, don't add it + * to the MPI type we're building up for I/O + */ + if (!chunk_list[i].need_read) + continue; + + /* + * If this chunk is being read, go ahead and + * set the base chunk offset and base chunk + * data buffer if we haven't already + */ + if (!H5F_addr_defined(base_offset)) { +#if H5_CHECK_MPI_VERSION(3, 0) + if (MPI_SUCCESS != (mpi_code = MPI_Get_address(chunk_list[i].buf, &base_buf))) + HMPI_GOTO_ERROR(FAIL, "MPI_Get_address failed", mpi_code) +#else + base_buf = (MPI_Aint)chunk_list[i].buf; +#endif + + base_offset = chunk_list[i].chunk_current.offset; + } + } + + /* Set convenience pointer for current chunk block */ + chunk_block = + (op_type == H5D_IO_OP_READ) ? &chunk_list[i].chunk_current : &chunk_list[i].chunk_new; + + /* + * Set the current chunk entry's offset in the file, relative to + * the first chunk entry + */ + HDassert(H5F_addr_defined(chunk_block->offset)); + file_offset_array[chunk_count] = (MPI_Aint)(chunk_block->offset - base_offset); + + /* + * Ensure the chunk list is sorted in ascending ordering of + * offset in the file + */ + if (chunk_count) + HDassert(file_offset_array[chunk_count] > file_offset_array[chunk_count - 1]); + + /* Set the current chunk entry's size for the I/O operation */ + H5_CHECK_OVERFLOW(chunk_block->length, hsize_t, int); + length_array[chunk_count] = (int)chunk_block->length; + + /* + * Set the displacement of the chunk entry's chunk data buffer, + * relative to the first entry's data buffer + */ +#if H5_CHECK_MPI_VERSION(3, 1) + if (MPI_SUCCESS != (mpi_code = MPI_Get_address(chunk_list[i].buf, &chunk_buf))) + HMPI_GOTO_ERROR(FAIL, "MPI_Get_address failed", mpi_code) + + io_buf_array[chunk_count] = MPI_Aint_diff(chunk_buf, base_buf); +#else + chunk_buf = (MPI_Aint)chunk_list[i].buf; + io_buf_array[chunk_count] = chunk_buf - base_buf; +#endif + + /* + * Set last valid index in case only a single chunk will + * be involved in the I/O operation + */ + last_valid_idx = i; + + chunk_count++; + } /* end for */ + } + + /* + * Create derived datatypes for the chunk list if this + * rank has any chunks to work on + */ + if (chunk_count > 0) { + if (chunk_count == 1) { + int chunk_len; + + /* Single chunk - use a contiguous type for both memory and file */ + + /* Ensure that we can cast chunk size to an int for MPI */ + chunk_block = (op_type == H5D_IO_OP_READ) ? &chunk_list[last_valid_idx].chunk_current + : &chunk_list[last_valid_idx].chunk_new; + H5_CHECKED_ASSIGN(chunk_len, int, chunk_block->length, hsize_t); + + if (MPI_SUCCESS != (mpi_code = MPI_Type_contiguous(chunk_len, MPI_BYTE, new_file_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code) + *new_mem_type = *new_file_type; + + /* + * Since we use the same datatype for both memory and file, only + * mark the file type as derived so the caller doesn't try to + * free the same type twice + */ + *mem_type_derived = FALSE; + *file_type_derived = TRUE; + + if (MPI_SUCCESS != (mpi_code = MPI_Type_commit(new_file_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code) + } + else { + HDassert(file_offset_array); + HDassert(length_array); + HDassert(io_buf_array); + + /* Multiple chunks - use an hindexed type for both memory and file */ + + /* Create memory MPI type */ + if (MPI_SUCCESS != (mpi_code = MPI_Type_create_hindexed( + chunk_count, length_array, io_buf_array, MPI_BYTE, new_mem_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hindexed failed", mpi_code) + *mem_type_derived = TRUE; + + if (MPI_SUCCESS != (mpi_code = MPI_Type_commit(new_mem_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code) + + /* Create file MPI type */ + if (MPI_SUCCESS != + (mpi_code = MPI_Type_create_hindexed(chunk_count, length_array, file_offset_array, + MPI_BYTE, new_file_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hindexed failed", mpi_code) + *file_type_derived = TRUE; + + if (MPI_SUCCESS != (mpi_code = MPI_Type_commit(new_file_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code) + } + } + } /* end if */ + +done: + if (file_offset_array) + H5MM_free(file_offset_array); + if (io_buf_array) + H5MM_free(io_buf_array); + if (length_array) + H5MM_free(length_array); + + if (ret_value < 0) { + if (*file_type_derived) { + if (MPI_SUCCESS != (mpi_code = MPI_Type_free(new_file_type))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + *file_type_derived = FALSE; + } + if (*mem_type_derived) { + if (MPI_SUCCESS != (mpi_code = MPI_Type_free(new_mem_type))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + *mem_type_derived = FALSE; + } + } + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D__mpio_collective_filtered_io_type() */ + +#ifdef H5Dmpio_DEBUG + +static herr_t +H5D__mpio_dump_collective_filtered_chunk_list(H5D_filtered_collective_io_info_t *chunk_list, + size_t chunk_list_num_entries, int mpi_rank) +{ + H5D_filtered_collective_io_info_t *chunk_entry; + size_t i; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC_NOERR + + H5D_MPIO_DEBUG(mpi_rank, "CHUNK LIST: ["); + for (i = 0; i < chunk_list_num_entries; i++) { + unsigned chunk_rank; + + chunk_entry = &chunk_list[i]; + + HDassert(chunk_entry->chunk_info); + chunk_rank = (unsigned)H5S_GET_EXTENT_NDIMS(chunk_entry->chunk_info->fspace); + + H5D_MPIO_DEBUG(mpi_rank, " {"); + H5D_MPIO_DEBUG_VA(mpi_rank, " - Entry %zu -", i); + + H5D_MPIO_DEBUG(mpi_rank, " - Chunk Fspace Info -"); + H5D_MPIO_DEBUG_VA(mpi_rank, + " Chunk Current Info: { Offset: %" PRIuHADDR ", Length: %" PRIuHADDR " }", + chunk_entry->chunk_current.offset, chunk_entry->chunk_current.length); + H5D_MPIO_DEBUG_VA(mpi_rank, " Chunk New Info: { Offset: %" PRIuHADDR ", Length: %" PRIuHADDR " }", + chunk_entry->chunk_new.offset, chunk_entry->chunk_new.length); + + H5D_MPIO_DEBUG(mpi_rank, " - Chunk Insert Info -"); + H5D_MPIO_DEBUG_VA(mpi_rank, + " Chunk Scaled Coords (4-d): { %" PRIuHSIZE ", %" PRIuHSIZE ", %" PRIuHSIZE + ", %" PRIuHSIZE " }", + chunk_rank < 1 ? 0 : chunk_entry->chunk_info->scaled[0], + chunk_rank < 2 ? 0 : chunk_entry->chunk_info->scaled[1], + chunk_rank < 3 ? 0 : chunk_entry->chunk_info->scaled[2], + chunk_rank < 4 ? 0 : chunk_entry->chunk_info->scaled[3]); + H5D_MPIO_DEBUG_VA(mpi_rank, " Chunk Index: %" PRIuHSIZE, chunk_entry->index_info.chunk_idx); + H5D_MPIO_DEBUG_VA(mpi_rank, " Filter Mask: %u", chunk_entry->index_info.filter_mask); + H5D_MPIO_DEBUG_VA(mpi_rank, " Need Insert: %s", + chunk_entry->index_info.need_insert ? "YES" : "NO"); + + H5D_MPIO_DEBUG(mpi_rank, " - Other Info -"); + H5D_MPIO_DEBUG_VA(mpi_rank, " Chunk Info Ptr: %p", (void *)chunk_entry->chunk_info); + H5D_MPIO_DEBUG_VA(mpi_rank, " Need Read: %s", chunk_entry->need_read ? "YES" : "NO"); + H5D_MPIO_DEBUG_VA(mpi_rank, " Chunk I/O Size: %zu", chunk_entry->io_size); + H5D_MPIO_DEBUG_VA(mpi_rank, " Chunk Buffer Size: %zu", chunk_entry->chunk_buf_size); + H5D_MPIO_DEBUG_VA(mpi_rank, " Original Owner: %d", chunk_entry->orig_owner); + H5D_MPIO_DEBUG_VA(mpi_rank, " New Owner: %d", chunk_entry->new_owner); + H5D_MPIO_DEBUG_VA(mpi_rank, " # of Writers: %d", chunk_entry->num_writers); + H5D_MPIO_DEBUG_VA(mpi_rank, " Chunk Data Buffer Ptr: %p", (void *)chunk_entry->buf); + + H5D_MPIO_DEBUG(mpi_rank, " }"); + } + H5D_MPIO_DEBUG(mpi_rank, "]"); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D__mpio_dump_collective_filtered_chunk_list() */ + +#endif + #endif /* H5_HAVE_PARALLEL */ diff --git a/src/H5Dpkg.h b/src/H5Dpkg.h index e07ba30..0e0eb08 100644 --- a/src/H5Dpkg.h +++ b/src/H5Dpkg.h @@ -121,15 +121,14 @@ typedef herr_t (*H5D_layout_construct_func_t)(H5F_t *f, H5D_t *dset); typedef herr_t (*H5D_layout_init_func_t)(H5F_t *f, const H5D_t *dset, hid_t dapl_id); typedef hbool_t (*H5D_layout_is_space_alloc_func_t)(const H5O_storage_t *storage); typedef hbool_t (*H5D_layout_is_data_cached_func_t)(const H5D_shared_t *shared_dset); -typedef herr_t (*H5D_layout_io_init_func_t)(const struct H5D_io_info_t *io_info, - const H5D_type_info_t *type_info, hsize_t nelmts, - const H5S_t *file_space, const H5S_t *mem_space, +typedef herr_t (*H5D_layout_io_init_func_t)(struct H5D_io_info_t *io_info, const H5D_type_info_t *type_info, + hsize_t nelmts, H5S_t *file_space, H5S_t *mem_space, struct H5D_chunk_map_t *cm); typedef herr_t (*H5D_layout_read_func_t)(struct H5D_io_info_t *io_info, const H5D_type_info_t *type_info, - hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space, + hsize_t nelmts, H5S_t *file_space, H5S_t *mem_space, struct H5D_chunk_map_t *fm); typedef herr_t (*H5D_layout_write_func_t)(struct H5D_io_info_t *io_info, const H5D_type_info_t *type_info, - hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space, + hsize_t nelmts, H5S_t *file_space, H5S_t *mem_space, struct H5D_chunk_map_t *fm); typedef ssize_t (*H5D_layout_readvv_func_t)(const struct H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], @@ -170,10 +169,10 @@ typedef struct H5D_layout_ops_t { /* Function pointers for either multiple or single block I/O access */ typedef herr_t (*H5D_io_single_read_func_t)(const struct H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, - const H5S_t *file_space, const H5S_t *mem_space); + H5S_t *file_space, H5S_t *mem_space); typedef herr_t (*H5D_io_single_write_func_t)(const struct H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, - const H5S_t *file_space, const H5S_t *mem_space); + H5S_t *file_space, H5S_t *mem_space); /* Typedef for raw data I/O framework info */ typedef struct H5D_io_ops_t { @@ -223,6 +222,7 @@ typedef struct H5D_io_info_t { H5D_layout_ops_t layout_ops; /* Dataset layout I/O operation function pointers */ H5D_io_ops_t io_ops; /* I/O operation function pointers */ H5D_io_op_type_t op_type; + hbool_t use_select_io; /* Whether to use selection I/O */ union { void * rbuf; /* Pointer to buffer for read */ const void *wbuf; /* Pointer to buffer to write */ @@ -346,10 +346,10 @@ typedef struct H5D_chunk_map_t { H5O_layout_t *layout; /* Dataset layout information*/ hsize_t nelmts; /* Number of elements selected in file & memory dataspaces */ - const H5S_t *file_space; /* Pointer to the file dataspace */ - unsigned f_ndims; /* Number of dimensions for file dataspace */ + H5S_t * file_space; /* Pointer to the file dataspace */ + unsigned f_ndims; /* Number of dimensions for file dataspace */ - const H5S_t * mem_space; /* Pointer to the memory dataspace */ + H5S_t * mem_space; /* Pointer to the memory dataspace */ H5S_t * mchunk_tmpl; /* Dataspace template for new memory chunks */ H5S_sel_iter_t mem_iter; /* Iterator for elements in memory selection */ unsigned m_ndims; /* Number of dimensions for memory dataspace */ @@ -434,7 +434,7 @@ typedef struct H5D_rdcdc_t { /* * A dataset is made of two layers, an H5D_t struct that is unique to - * each instance of an opened datset, and a shared struct that is only + * each instance of an opened dataset, and a shared struct that is only * created once for a given dataset. Thus, if a dataset is opened twice, * there will be two IDs and two H5D_t structs, both sharing one H5D_shared_t. */ @@ -560,6 +560,7 @@ H5_DLL herr_t H5D__alloc_storage(const H5D_io_info_t *io_info, H5D_time_alloc_t hbool_t full_overwrite, hsize_t old_dim[]); H5_DLL herr_t H5D__get_storage_size(const H5D_t *dset, hsize_t *storage_size); H5_DLL herr_t H5D__get_chunk_storage_size(H5D_t *dset, const hsize_t *offset, hsize_t *storage_size); +H5_DLL herr_t H5D__chunk_index_empty(const H5D_t *dset, hbool_t *empty); H5_DLL herr_t H5D__get_num_chunks(const H5D_t *dset, const H5S_t *space, hsize_t *nchunks); H5_DLL herr_t H5D__get_chunk_info(const H5D_t *dset, const H5S_t *space, hsize_t chk_idx, hsize_t *coord, unsigned *filter_mask, haddr_t *offset, hsize_t *size); @@ -581,25 +582,29 @@ H5_DLL herr_t H5D__refresh(H5D_t *dataset, hid_t dset_id); H5_DLL herr_t H5D__format_convert(H5D_t *dataset); /* Internal I/O routines */ -H5_DLL herr_t H5D__read(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, const H5S_t *file_space, +H5_DLL herr_t H5D__read(H5D_t *dataset, hid_t mem_type_id, H5S_t *mem_space, H5S_t *file_space, void *buf /*out*/); -H5_DLL herr_t H5D__write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, const H5S_t *file_space, +H5_DLL herr_t H5D__write(H5D_t *dataset, hid_t mem_type_id, H5S_t *mem_space, H5S_t *file_space, const void *buf); /* Functions that perform direct serial I/O operations */ H5_DLL herr_t H5D__select_read(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, - const H5S_t *file_space, const H5S_t *mem_space); + H5S_t *file_space, H5S_t *mem_space); H5_DLL herr_t H5D__select_write(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info, - hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space); + hsize_t nelmts, H5S_t *file_space, H5S_t *mem_space); + +/* Functions that perform direct copying between memory buffers */ +H5_DLL herr_t H5D_select_io_mem(void *dst_buf, const H5S_t *dst_space, const void *src_buf, + const H5S_t *src_space, size_t elmt_size, size_t nelmts); /* Functions that perform scatter-gather serial I/O operations */ H5_DLL herr_t H5D__scatter_mem(const void *_tscat_buf, H5S_sel_iter_t *iter, size_t nelmts, void *_buf); H5_DLL size_t H5D__gather_mem(const void *_buf, H5S_sel_iter_t *iter, size_t nelmts, void *_tgath_buf /*out*/); H5_DLL herr_t H5D__scatgath_read(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info, - hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space); + hsize_t nelmts, H5S_t *file_space, H5S_t *mem_space); H5_DLL herr_t H5D__scatgath_write(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info, - hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space); + hsize_t nelmts, H5S_t *file_space, H5S_t *mem_space); /* Functions that operate on dataset's layout information */ H5_DLL herr_t H5D__layout_set_io_ops(const H5D_t *dataset); @@ -617,9 +622,9 @@ H5_DLL hbool_t H5D__contig_is_space_alloc(const H5O_storage_t *storage); H5_DLL hbool_t H5D__contig_is_data_cached(const H5D_shared_t *shared_dset); H5_DLL herr_t H5D__contig_fill(const H5D_io_info_t *io_info); H5_DLL herr_t H5D__contig_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, - const H5S_t *file_space, const H5S_t *mem_space, H5D_chunk_map_t *fm); + H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t *fm); H5_DLL herr_t H5D__contig_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, - const H5S_t *file_space, const H5S_t *mem_space, H5D_chunk_map_t *fm); + H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t *fm); H5_DLL herr_t H5D__contig_copy(H5F_t *f_src, const H5O_storage_contig_t *storage_src, H5F_t *f_dst, H5O_storage_contig_t *storage_dst, H5T_t *src_dtype, H5O_copy_t *cpy_info); H5_DLL herr_t H5D__contig_delete(H5F_t *f, const H5O_storage_t *store); @@ -636,7 +641,13 @@ H5_DLL herr_t H5D__chunk_allocate(const H5D_io_info_t *io_info, hbool_t full_ov const hsize_t old_dim[]); H5_DLL herr_t H5D__chunk_file_alloc(const H5D_chk_idx_info_t *idx_info, const H5F_block_t *old_chunk, H5F_block_t *new_chunk, hbool_t *need_insert, const hsize_t *scaled); +H5_DLL void * H5D__chunk_mem_alloc(size_t size, const H5O_pline_t *pline); +H5_DLL void H5D__chunk_mem_free(void *chk, const void *_pline); +H5_DLL void * H5D__chunk_mem_xfree(void *chk, const void *pline); +H5_DLL void * H5D__chunk_mem_realloc(void *chk, size_t size, const H5O_pline_t *pline); H5_DLL herr_t H5D__chunk_update_old_edge_chunks(H5D_t *dset, hsize_t old_dim[]); +H5_DLL hbool_t H5D__chunk_is_partial_edge_chunk(unsigned dset_ndims, const uint32_t *chunk_dims, + const hsize_t *chunk_scaled, const hsize_t *dset_dims); H5_DLL herr_t H5D__chunk_prune_by_extent(H5D_t *dset, const hsize_t *old_dim); H5_DLL herr_t H5D__chunk_set_sizes(H5D_t *dset); #ifdef H5_HAVE_PARALLEL @@ -686,7 +697,7 @@ H5_DLL herr_t H5D__efl_bh_info(H5F_t *f, H5O_efl_t *efl, hsize_t *heap_size); /* Functions that perform fill value operations on datasets */ H5_DLL herr_t H5D__fill(const void *fill, const H5T_t *fill_type, void *buf, const H5T_t *buf_type, - const H5S_t *space); + H5S_t *space); H5_DLL herr_t H5D__fill_init(H5D_fill_buf_info_t *fb_info, void *caller_fill_buf, H5MM_allocate_t alloc_func, void *alloc_info, H5MM_free_t free_func, void *free_info, const H5O_fill_t *fill, const H5T_t *dset_type, hid_t dset_type_id, size_t nelmts, size_t min_buf_size); @@ -695,39 +706,41 @@ H5_DLL herr_t H5D__fill_term(H5D_fill_buf_info_t *fb_info); #ifdef H5_HAVE_PARALLEL -#ifdef H5S_DEBUG +#ifdef H5D_DEBUG #ifndef H5Dmpio_DEBUG #define H5Dmpio_DEBUG #endif /*H5Dmpio_DEBUG*/ -#endif /*H5S_DEBUG*/ +#endif /*H5D_DEBUG*/ /* MPI-IO function to read, it will select either regular or irregular read */ H5_DLL herr_t H5D__mpio_select_read(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info, - hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space); + hsize_t nelmts, H5S_t *file_space, H5S_t *mem_space); /* MPI-IO function to write, it will select either regular or irregular read */ H5_DLL herr_t H5D__mpio_select_write(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info, - hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space); + hsize_t nelmts, H5S_t *file_space, H5S_t *mem_space); /* MPI-IO functions to handle contiguous collective IO */ H5_DLL herr_t H5D__contig_collective_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, - hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space, + hsize_t nelmts, H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t *fm); H5_DLL herr_t H5D__contig_collective_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, - hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space, + hsize_t nelmts, H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t *fm); /* MPI-IO functions to handle chunked collective IO */ H5_DLL herr_t H5D__chunk_collective_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, - hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space, + hsize_t nelmts, H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t *fm); H5_DLL herr_t H5D__chunk_collective_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, - hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space, + hsize_t nelmts, H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t *fm); /* MPI-IO function to check if a direct I/O transfer is possible between * memory and the file */ H5_DLL htri_t H5D__mpio_opt_possible(const H5D_io_info_t *io_info, const H5S_t *file_space, const H5S_t *mem_space, const H5D_type_info_t *type_info); +H5_DLL herr_t H5D__mpio_get_no_coll_cause_strings(char *local_cause, size_t local_cause_len, + char *global_cause, size_t global_cause_len); #endif /* H5_HAVE_PARALLEL */ diff --git a/src/H5Dpublic.h b/src/H5Dpublic.h index c496414..02644ed 100644 --- a/src/H5Dpublic.h +++ b/src/H5Dpublic.h @@ -77,7 +77,7 @@ typedef enum H5D_chunk_index_t { */ typedef enum H5D_alloc_time_t { H5D_ALLOC_TIME_ERROR = -1, /**< Error */ - H5D_ALLOC_TIME_DEFAULT = 0, /**< \todo Define this! */ + H5D_ALLOC_TIME_DEFAULT = 0, /**< Default (layout dependent) */ H5D_ALLOC_TIME_EARLY = 1, /**< Allocate on creation */ H5D_ALLOC_TIME_LATE = 2, /**< Allocate on first write */ H5D_ALLOC_TIME_INCR = 3 /**< Allocate incrementally (by chunk) */ @@ -91,9 +91,9 @@ typedef enum H5D_alloc_time_t { typedef enum H5D_space_status_t { H5D_SPACE_STATUS_ERROR = -1, /**< Error */ H5D_SPACE_STATUS_NOT_ALLOCATED = 0, /**< Space has not been allocated for this dataset. */ - H5D_SPACE_STATUS_PART_ALLOCATED = 1, /**< Space has been allocated for this dataset. */ - H5D_SPACE_STATUS_ALLOCATED = 2 /**< Space has been partially allocated for this dataset. (Used only for - datasets with chunked storage.) */ + H5D_SPACE_STATUS_PART_ALLOCATED = 1, /**< Space has been partially allocated for this dataset. + (Used only for datasets with chunked storage.) */ + H5D_SPACE_STATUS_ALLOCATED = 2 /**< Space has been allocated for this dataset. */ } H5D_space_status_t; //! <!-- [H5D_space_status_t_snip] --> @@ -127,8 +127,8 @@ typedef enum H5D_fill_value_t { */ typedef enum H5D_vds_view_t { H5D_VDS_ERROR = -1, /**< Error */ - H5D_VDS_FIRST_MISSING = 0, /**< \todo Define this! */ - H5D_VDS_LAST_AVAILABLE = 1 /**< \todo Define this! */ + H5D_VDS_FIRST_MISSING = 0, /**< Include all data before the first missing mapped data */ + H5D_VDS_LAST_AVAILABLE = 1 /**< Include all available mapped data */ } H5D_vds_view_t; //! <!-- [H5D_vds_view_t_snip] --> @@ -300,7 +300,7 @@ extern "C" { * caller may derive new datatypes, dataspaces, and creation and * access properties from the old ones and reuse them in calls to * create additional datasets. Once created, the dataset can be - * read from or written to. Reading data from a datatset that was + * read from or written to. Reading data from a dataset that was * not previously written, the HDF5 library will return default * or user-defined fill values. * @@ -682,8 +682,7 @@ H5_DLL herr_t H5Dget_chunk_info_by_coord(hid_t dset_id, const hsize_t *offset, u * Iterate over all chunked datasets and chunks in a file. * \snippet H5D_examples.c H5Ovisit_cb * - * \version 1.?.? - * \todo When was this function introduced? + * \since 1.13.0 * */ H5_DLL herr_t H5Dchunk_iter(hid_t dset_id, hid_t dxpl_id, H5D_chunk_iter_op_t cb, void *op_data); diff --git a/src/H5Dscatgath.c b/src/H5Dscatgath.c index 971ddfb..500ea9e 100644 --- a/src/H5Dscatgath.c +++ b/src/H5Dscatgath.c @@ -437,7 +437,7 @@ done: */ herr_t H5D__scatgath_read(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, - const H5S_t *file_space, const H5S_t *mem_space) + H5S_t *file_space, H5S_t *mem_space) { void * buf = io_info->u.rbuf; /* Local pointer to application buffer */ H5S_sel_iter_t *mem_iter = NULL; /* Memory selection iteration info*/ @@ -577,7 +577,7 @@ done: */ herr_t H5D__scatgath_write(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, - const H5S_t *file_space, const H5S_t *mem_space) + H5S_t *file_space, H5S_t *mem_space) { const void * buf = io_info->u.wbuf; /* Local pointer to application buffer */ H5S_sel_iter_t *mem_iter = NULL; /* Memory selection iteration info*/ diff --git a/src/H5Dselect.c b/src/H5Dselect.c index 7d2ead1..f464ca5 100644 --- a/src/H5Dselect.c +++ b/src/H5Dselect.c @@ -44,8 +44,8 @@ /* Local Prototypes */ /********************/ -static herr_t H5D__select_io(const H5D_io_info_t *io_info, size_t elmt_size, size_t nelmts, - const H5S_t *file_space, const H5S_t *mem_space); +static herr_t H5D__select_io(const H5D_io_info_t *io_info, size_t elmt_size, size_t nelmts, H5S_t *file_space, + H5S_t *mem_space); /*********************/ /* Package Variables */ @@ -77,8 +77,8 @@ H5FL_EXTERN(H5S_sel_iter_t); *------------------------------------------------------------------------- */ static herr_t -H5D__select_io(const H5D_io_info_t *io_info, size_t elmt_size, size_t nelmts, const H5S_t *file_space, - const H5S_t *mem_space) +H5D__select_io(const H5D_io_info_t *io_info, size_t elmt_size, size_t nelmts, H5S_t *file_space, + H5S_t *mem_space) { H5S_sel_iter_t *mem_iter = NULL; /* Memory selection iteration info */ hbool_t mem_iter_init = FALSE; /* Memory selection iteration info has been initialized */ @@ -105,6 +105,9 @@ H5D__select_io(const H5D_io_info_t *io_info, size_t elmt_size, size_t nelmts, co HDassert(io_info->store); HDassert(io_info->u.rbuf); + if (elmt_size == 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "invalid elmt_size of 0") + /* Check for only one element in selection */ if (nelmts == 1) { hsize_t single_mem_off; /* Offset in memory */ @@ -226,8 +229,6 @@ H5D__select_io(const H5D_io_info_t *io_info, size_t elmt_size, size_t nelmts, co /* Decrement number of elements left to process */ HDassert(((size_t)tmp_file_len % elmt_size) == 0); - if (elmt_size == 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "Resulted in division by zero") nelmts -= ((size_t)tmp_file_len / elmt_size); } /* end while */ } /* end else */ @@ -257,6 +258,188 @@ done: } /* end H5D__select_io() */ /*------------------------------------------------------------------------- + * Function: H5D_select_io_mem + * + * Purpose: Perform memory copies directly between two memory buffers + * according to the selections in the `dst_space` and + * `src_space` dataspaces. + * + * Note: This routine is [basically] the same as H5D__select_io, + * with the only difference being that the readvv/writevv + * calls are exchanged for H5VM_memcpyvv calls. Changes should + * be made to both routines. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5D_select_io_mem(void *dst_buf, const H5S_t *dst_space, const void *src_buf, const H5S_t *src_space, + size_t elmt_size, size_t nelmts) +{ + H5S_sel_iter_t *dst_sel_iter = NULL; /* Destination dataspace iteration info */ + H5S_sel_iter_t *src_sel_iter = NULL; /* Source dataspace iteration info */ + hbool_t dst_sel_iter_init = FALSE; /* Destination dataspace selection iterator initialized? */ + hbool_t src_sel_iter_init = FALSE; /* Source dataspace selection iterator initialized? */ + hsize_t * dst_off = NULL; /* Pointer to sequence offsets in destination buffer */ + hsize_t * src_off = NULL; /* Pointer to sequence offsets in source buffer */ + size_t * dst_len = NULL; /* Pointer to sequence lengths in destination buffer */ + size_t * src_len = NULL; /* Pointer to sequence lengths in source buffer */ + size_t curr_dst_seq; /* Current destination buffer sequence to operate on */ + size_t curr_src_seq; /* Current source buffer sequence to operate on */ + size_t dst_nseq; /* Number of sequences generated for destination buffer */ + size_t src_nseq; /* Number of sequences generated for source buffer */ + size_t dxpl_vec_size; /* Vector length from API context's DXPL */ + size_t vec_size; /* Vector length */ + ssize_t bytes_copied; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(FAIL) + + HDassert(dst_buf); + HDassert(dst_space); + HDassert(src_buf); + HDassert(src_space); + + if (elmt_size == 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "invalid elmt_size of 0") + + /* Check for only one element in selection */ + if (nelmts == 1) { + hsize_t single_dst_off; /* Offset in dst_space */ + hsize_t single_src_off; /* Offset in src_space */ + size_t single_dst_len; /* Length in dst_space */ + size_t single_src_len; /* Length in src_space */ + + /* Get offset of first element in selections */ + if (H5S_SELECT_OFFSET(dst_space, &single_dst_off) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't retrieve destination selection offset") + if (H5S_SELECT_OFFSET(src_space, &single_src_off) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't retrieve source selection offset") + + /* Set up necessary information for I/O operation */ + dst_nseq = src_nseq = 1; + curr_dst_seq = curr_src_seq = 0; + single_dst_off *= elmt_size; + single_src_off *= elmt_size; + single_dst_len = single_src_len = elmt_size; + + /* Perform vectorized memcpy from src_buf to dst_buf */ + if ((bytes_copied = + H5VM_memcpyvv(dst_buf, dst_nseq, &curr_dst_seq, &single_dst_len, &single_dst_off, src_buf, + src_nseq, &curr_src_seq, &single_src_len, &single_src_off)) < 0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed") + + HDassert(((size_t)bytes_copied % elmt_size) == 0); + } + else { + unsigned sel_iter_flags = H5S_SEL_ITER_GET_SEQ_LIST_SORTED | H5S_SEL_ITER_SHARE_WITH_DATASPACE; + size_t dst_nelem; /* Number of elements used in destination buffer sequences */ + size_t src_nelem; /* Number of elements used in source buffer sequences */ + + /* Get info from API context */ + if (H5CX_get_vec_size(&dxpl_vec_size) < 0) + HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "can't retrieve I/O vector size") + + /* Allocate the vector I/O arrays */ + if (dxpl_vec_size > H5D_IO_VECTOR_SIZE) + vec_size = dxpl_vec_size; + else + vec_size = H5D_IO_VECTOR_SIZE; + + if (NULL == (dst_len = H5FL_SEQ_MALLOC(size_t, vec_size))) + HGOTO_ERROR(H5E_IO, H5E_CANTALLOC, FAIL, "can't allocate I/O length vector array") + if (NULL == (dst_off = H5FL_SEQ_MALLOC(hsize_t, vec_size))) + HGOTO_ERROR(H5E_IO, H5E_CANTALLOC, FAIL, "can't allocate I/O offset vector array") + if (NULL == (src_len = H5FL_SEQ_MALLOC(size_t, vec_size))) + HGOTO_ERROR(H5E_IO, H5E_CANTALLOC, FAIL, "can't allocate I/O length vector array") + if (NULL == (src_off = H5FL_SEQ_MALLOC(hsize_t, vec_size))) + HGOTO_ERROR(H5E_IO, H5E_CANTALLOC, FAIL, "can't allocate I/O offset vector array") + + /* Allocate the dataspace selection iterators */ + if (NULL == (dst_sel_iter = H5FL_MALLOC(H5S_sel_iter_t))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate destination selection iterator") + if (NULL == (src_sel_iter = H5FL_MALLOC(H5S_sel_iter_t))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate source selection iterator") + + /* Initialize destination selection iterator */ + if (H5S_select_iter_init(dst_sel_iter, dst_space, elmt_size, sel_iter_flags) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator") + dst_sel_iter_init = TRUE; /* Destination selection iteration info has been initialized */ + + /* Initialize source selection iterator */ + if (H5S_select_iter_init(src_sel_iter, src_space, elmt_size, H5S_SEL_ITER_SHARE_WITH_DATASPACE) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator") + src_sel_iter_init = TRUE; /* Source selection iteration info has been initialized */ + + /* Initialize sequence counts */ + curr_dst_seq = curr_src_seq = 0; + dst_nseq = src_nseq = 0; + + /* Loop, until all bytes are processed */ + while (nelmts > 0) { + /* Check if more destination buffer sequences are needed */ + if (curr_dst_seq >= dst_nseq) { + /* Get sequences for destination selection */ + if (H5S_SELECT_ITER_GET_SEQ_LIST(dst_sel_iter, vec_size, nelmts, &dst_nseq, &dst_nelem, + dst_off, dst_len) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "sequence length generation failed") + + /* Start at the beginning of the sequences again */ + curr_dst_seq = 0; + } + + /* Check if more source buffer sequences are needed */ + if (curr_src_seq >= src_nseq) { + /* Get sequences for source selection */ + if (H5S_SELECT_ITER_GET_SEQ_LIST(src_sel_iter, vec_size, nelmts, &src_nseq, &src_nelem, + src_off, src_len) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "sequence length generation failed") + + /* Start at the beginning of the sequences again */ + curr_src_seq = 0; + } /* end if */ + + /* Perform vectorized memcpy from src_buf to dst_buf */ + if ((bytes_copied = H5VM_memcpyvv(dst_buf, dst_nseq, &curr_dst_seq, dst_len, dst_off, src_buf, + src_nseq, &curr_src_seq, src_len, src_off)) < 0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed") + + /* Decrement number of elements left to process */ + HDassert(((size_t)bytes_copied % elmt_size) == 0); + nelmts -= ((size_t)bytes_copied / elmt_size); + } + } + +done: + /* Release selection iterators */ + if (src_sel_iter) { + if (src_sel_iter_init && H5S_SELECT_ITER_RELEASE(src_sel_iter) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator") + + src_sel_iter = H5FL_FREE(H5S_sel_iter_t, src_sel_iter); + } + if (dst_sel_iter) { + if (dst_sel_iter_init && H5S_SELECT_ITER_RELEASE(dst_sel_iter) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator") + + dst_sel_iter = H5FL_FREE(H5S_sel_iter_t, dst_sel_iter); + } + + /* Release vector arrays, if allocated */ + if (src_off) + src_off = H5FL_SEQ_FREE(hsize_t, src_off); + if (src_len) + src_len = H5FL_SEQ_FREE(size_t, src_len); + if (dst_off) + dst_off = H5FL_SEQ_FREE(hsize_t, dst_off); + if (dst_len) + dst_len = H5FL_SEQ_FREE(size_t, dst_len); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D_select_io_mem() */ + +/*------------------------------------------------------------------------- * Function: H5D__select_read * * Purpose: Reads directly from file into application memory. @@ -270,7 +453,7 @@ done: */ herr_t H5D__select_read(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, - const H5S_t *file_space, const H5S_t *mem_space) + H5S_t *file_space, H5S_t *mem_space) { herr_t ret_value = SUCCEED; /* Return value */ @@ -299,7 +482,7 @@ done: */ herr_t H5D__select_write(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, - const H5S_t *file_space, const H5S_t *mem_space) + H5S_t *file_space, H5S_t *mem_space) { herr_t ret_value = SUCCEED; /* Return value */ diff --git a/src/H5Dsingle.c b/src/H5Dsingle.c index 50cf6a1..b93523a 100644 --- a/src/H5Dsingle.c +++ b/src/H5Dsingle.c @@ -125,8 +125,14 @@ H5D__single_idx_init(const H5D_chk_idx_info_t *idx_info, const H5S_t H5_ATTR_UNU HDassert(idx_info->layout); HDassert(idx_info->storage); - if (idx_info->pline->nused) + if (idx_info->pline->nused) { idx_info->layout->flags |= H5O_LAYOUT_CHUNK_SINGLE_INDEX_WITH_FILTER; + + if (!H5F_addr_defined(idx_info->storage->idx_addr)) { + idx_info->storage->u.single.nbytes = 0; + idx_info->storage->u.single.filter_mask = 0; + } + } else idx_info->layout->flags = 0; diff --git a/src/H5Dvirtual.c b/src/H5Dvirtual.c index 4012188..b28bbbc 100644 --- a/src/H5Dvirtual.c +++ b/src/H5Dvirtual.c @@ -84,9 +84,9 @@ /* Layout operation callbacks */ static hbool_t H5D__virtual_is_data_cached(const H5D_shared_t *shared_dset); static herr_t H5D__virtual_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, - const H5S_t *file_space, const H5S_t *mem_space, H5D_chunk_map_t *fm); + H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t *fm); static herr_t H5D__virtual_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, - const H5S_t *file_space, const H5S_t *mem_space, H5D_chunk_map_t *fm); + H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t *fm); static herr_t H5D__virtual_flush(H5D_t *dset); /* Other functions */ @@ -103,26 +103,37 @@ static herr_t H5D__virtual_build_source_name(char * size_t static_strlen, size_t nsubs, hsize_t blockno, char **built_name); static herr_t H5D__virtual_init_all(const H5D_t *dset); -static herr_t H5D__virtual_pre_io(H5D_io_info_t *io_info, H5O_storage_virtual_t *storage, - const H5S_t *file_space, const H5S_t *mem_space, hsize_t *tot_nelmts); +static herr_t H5D__virtual_pre_io(H5D_io_info_t *io_info, H5O_storage_virtual_t *storage, H5S_t *file_space, + H5S_t *mem_space, hsize_t *tot_nelmts); static herr_t H5D__virtual_post_io(H5O_storage_virtual_t *storage); static herr_t H5D__virtual_read_one(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, - const H5S_t *file_space, H5O_storage_virtual_srcdset_t *source_dset); + H5S_t *file_space, H5O_storage_virtual_srcdset_t *source_dset); static herr_t H5D__virtual_write_one(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, - const H5S_t *file_space, H5O_storage_virtual_srcdset_t *source_dset); + H5S_t *file_space, H5O_storage_virtual_srcdset_t *source_dset); /*********************/ /* Package Variables */ /*********************/ /* Contiguous storage layout I/O ops */ -const H5D_layout_ops_t H5D_LOPS_VIRTUAL[1] = {{NULL, H5D__virtual_init, H5D__virtual_is_space_alloc, - H5D__virtual_is_data_cached, NULL, H5D__virtual_read, - H5D__virtual_write, +const H5D_layout_ops_t H5D_LOPS_VIRTUAL[1] = {{ + NULL, /* construct */ + H5D__virtual_init, /* init */ + H5D__virtual_is_space_alloc, /* is_space_alloc */ + H5D__virtual_is_data_cached, /* is_data_cached */ + NULL, /* io_init */ + H5D__virtual_read, /* ser_read */ + H5D__virtual_write, /* ser_write */ #ifdef H5_HAVE_PARALLEL - NULL, NULL, -#endif /* H5_HAVE_PARALLEL */ - NULL, NULL, H5D__virtual_flush, NULL, NULL}}; + NULL, /* par_read */ + NULL, /* par_write */ +#endif + NULL, /* readvv */ + NULL, /* writevv */ + H5D__virtual_flush, /* flush */ + NULL, /* io_term */ + NULL /* dest */ +}}; /*******************/ /* Local Variables */ @@ -195,7 +206,7 @@ H5D_virtual_check_mapping_pre(const H5S_t *vspace, const H5S_t *src_space, "can't get number of elements in non-unlimited dimension") if (nenu_vs != nenu_ss) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, - "numbers of elemnts in the non-unlimited dimensions is different for source and " + "numbers of elements in the non-unlimited dimensions is different for source and " "virtual spaces") } /* end if */ /* We will handle the printf case after parsing the source names */ @@ -1304,7 +1315,7 @@ H5D_virtual_free_parsed_name(H5O_storage_virtual_name_seg_t *name_seg) H5O_storage_virtual_name_seg_t *next_seg; herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR /* Walk name segments, freeing them */ while (name_seg) { @@ -1314,7 +1325,6 @@ H5D_virtual_free_parsed_name(H5O_storage_virtual_name_seg_t *name_seg) name_seg = next_seg; } /* end while */ -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5D_virtual_free_parsed_name() */ @@ -1482,7 +1492,7 @@ H5D__virtual_set_extent_unlim(const H5D_t *dset) storage->list[i].source_dset.dset->shared->space) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "can't copy source dataspace extent") - /* Get source space dimenstions */ + /* Get source space dimensions */ if (H5S_get_simple_extent_dims(storage->list[i].source_select, curr_dims, NULL) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get source space dimensions") @@ -1960,7 +1970,7 @@ H5D__virtual_init_all(const H5D_t *dset) storage->list[i].source_dset.dset->shared->space) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "can't copy source dataspace extent") - /* Get source space dimenstions */ + /* Get source space dimensions */ if (H5S_get_simple_extent_dims(storage->list[i].source_select, source_dims, NULL) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get source space dimensions") @@ -2344,7 +2354,7 @@ H5D__virtual_is_data_cached(const H5D_shared_t *shared_dset) if (storage->list[i].psfn_nsubs || storage->list[i].psdn_nsubs) { /* Iterate over sub-source dsets */ for (j = storage->list[i].sub_dset_io_start; j < storage->list[i].sub_dset_io_end; j++) - /* Check for cahced data in source dset */ + /* Check for cached data in source dset */ if (storage->list[i].sub_dset[j].dset && storage->list[i].sub_dset[j].dset->shared->layout.ops->is_data_cached && storage->list[i].sub_dset[j].dset->shared->layout.ops->is_data_cached( @@ -2377,8 +2387,8 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5D__virtual_pre_io(H5D_io_info_t *io_info, H5O_storage_virtual_t *storage, const H5S_t *file_space, - const H5S_t *mem_space, hsize_t *tot_nelmts) +H5D__virtual_pre_io(H5D_io_info_t *io_info, H5O_storage_virtual_t *storage, H5S_t *file_space, + H5S_t *mem_space, hsize_t *tot_nelmts) { hssize_t select_nelmts; /* Number of elements in selection */ hsize_t bounds_start[H5S_MAX_RANK]; /* Selection bounds start */ @@ -2678,7 +2688,7 @@ H5D__virtual_post_io(H5O_storage_virtual_t *storage) /*------------------------------------------------------------------------- * Function: H5D__virtual_read_one * - * Purpose: Read from a singe source dataset in a virtual dataset. + * Purpose: Read from a single source dataset in a virtual dataset. * * Return: Non-negative on success/Negative on failure * @@ -2688,7 +2698,7 @@ H5D__virtual_post_io(H5O_storage_virtual_t *storage) *------------------------------------------------------------------------- */ static herr_t -H5D__virtual_read_one(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, const H5S_t *file_space, +H5D__virtual_read_one(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, H5S_t *file_space, H5O_storage_virtual_srcdset_t *source_dset) { H5S_t *projected_src_space = NULL; /* File space for selection in a single source dataset */ @@ -2748,8 +2758,8 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5D__virtual_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, - const H5S_t *file_space, const H5S_t *mem_space, H5D_chunk_map_t H5_ATTR_UNUSED *fm) +H5D__virtual_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, H5S_t *file_space, + H5S_t *mem_space, H5D_chunk_map_t H5_ATTR_UNUSED *fm) { H5O_storage_virtual_t *storage; /* Convenient pointer into layout struct */ hsize_t tot_nelmts; /* Total number of elements mapped to mem_space */ @@ -2868,7 +2878,7 @@ done: /*------------------------------------------------------------------------- * Function: H5D__virtual_write_one * - * Purpose: Write to a singe source dataset in a virtual dataset. + * Purpose: Write to a single source dataset in a virtual dataset. * * Return: Non-negative on success/Negative on failure * @@ -2878,7 +2888,7 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5D__virtual_write_one(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, const H5S_t *file_space, +H5D__virtual_write_one(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, H5S_t *file_space, H5O_storage_virtual_srcdset_t *source_dset) { H5S_t *projected_src_space = NULL; /* File space for selection in a single source dataset */ @@ -2941,7 +2951,7 @@ done: */ static herr_t H5D__virtual_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, - const H5S_t *file_space, const H5S_t *mem_space, H5D_chunk_map_t H5_ATTR_UNUSED *fm) + H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t H5_ATTR_UNUSED *fm) { H5O_storage_virtual_t *storage; /* Convenient pointer into layout struct */ hsize_t tot_nelmts; /* Total number of elements mapped to mem_space */ @@ -92,9 +92,6 @@ static herr_t H5E__append_stack(H5E_t *dst_estack, const H5E_t *src_stack); /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /*****************************/ /* Library Private Variables */ /*****************************/ @@ -141,46 +138,19 @@ static const H5I_class_t H5I_ERRSTK_CLS[1] = {{ * * Purpose: Initialize the interface from some other layer. * - * Return: SUCCEED/FAIL - * - * Programmer: Quincey Koziol - * Tuesday, June 29, 2004 - * + * Return: Success: non-negative + * Failure: negative *------------------------------------------------------------------------- */ herr_t H5E_init(void) { - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(FAIL) - /* FUNC_ENTER() does all the work */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5E_init() */ - -/*-------------------------------------------------------------------------- - * Function: H5E__init_package - * - * Purpose: Initialize interface-specific information - * - * Return: SUCCEED/FAIL - * - * Programmer: Raymond Lu - * Friday, July 11, 2003 - * - *-------------------------------------------------------------------------- - */ -herr_t -H5E__init_package(void) -{ H5E_cls_t *cls; /* Pointer to error class */ H5E_msg_t *msg; /* Pointer to new error message */ char lib_vers[128]; /* Buffer to constructu library version within */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_PACKAGE + FUNC_ENTER_NOAPI(FAIL) /* Initialize the ID group for the error class IDs */ if (H5I_register_type(H5I_ERRCLS_CLS) < 0) @@ -213,7 +183,7 @@ H5E__init_package(void) done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5E__init_package() */ +} /*------------------------------------------------------------------------- * Function: H5E_term_package @@ -237,66 +207,61 @@ H5E_term_package(void) FUNC_ENTER_NOAPI_NOINIT_NOERR - if (H5_PKG_INIT_VAR) { - int64_t ncls, nmsg, nstk; - - /* Check if there are any open error stacks, classes or messages */ - ncls = H5I_nmembers(H5I_ERROR_CLASS); - nmsg = H5I_nmembers(H5I_ERROR_MSG); - nstk = H5I_nmembers(H5I_ERROR_STACK); - - if ((ncls + nmsg + nstk) > 0) { - /* Clear the default error stack. Note that - * the following H5I_clear_type calls do not - * force the clears and will not be able to - * clear any error message IDs that are still - * in use by the default error stack unless we - * clear that stack manually. - * - * Error message IDs will typically still be - * in use by the default error stack when the - * application does H5E_BEGIN/END_TRY cleanup - * at the very end. - */ - H5E_clear_stack(NULL); - - /* Clear any outstanding error stacks */ - if (nstk > 0) - (void)H5I_clear_type(H5I_ERROR_STACK, FALSE, FALSE); - - /* Clear all the error classes */ - if (ncls > 0) { - (void)H5I_clear_type(H5I_ERROR_CLASS, FALSE, FALSE); - - /* Reset the HDF5 error class, if its been closed */ - if (H5I_nmembers(H5I_ERROR_CLASS) == 0) - H5E_ERR_CLS_g = -1; - } /* end if */ + int64_t ncls, nmsg, nstk; + + /* Check if there are any open error stacks, classes or messages */ + ncls = H5I_nmembers(H5I_ERROR_CLASS); + nmsg = H5I_nmembers(H5I_ERROR_MSG); + nstk = H5I_nmembers(H5I_ERROR_STACK); + + if ((ncls + nmsg + nstk) > 0) { + /* Clear the default error stack. Note that + * the following H5I_clear_type calls do not + * force the clears and will not be able to + * clear any error message IDs that are still + * in use by the default error stack unless we + * clear that stack manually. + * + * Error message IDs will typically still be + * in use by the default error stack when the + * application does H5E_BEGIN/END_TRY cleanup + * at the very end. + */ + H5E_clear_stack(NULL); + + /* Clear any outstanding error stacks */ + if (nstk > 0) + (void)H5I_clear_type(H5I_ERROR_STACK, FALSE, FALSE); + + /* Clear all the error classes */ + if (ncls > 0) { + (void)H5I_clear_type(H5I_ERROR_CLASS, FALSE, FALSE); - /* Clear all the error messages */ - if (nmsg > 0) { - (void)H5I_clear_type(H5I_ERROR_MSG, FALSE, FALSE); + /* Reset the HDF5 error class, if its been closed */ + if (H5I_nmembers(H5I_ERROR_CLASS) == 0) + H5E_ERR_CLS_g = -1; + } /* end if */ - /* Reset the HDF5 error messages, if they've been closed */ - if (H5I_nmembers(H5I_ERROR_MSG) == 0) { + /* Clear all the error messages */ + if (nmsg > 0) { + (void)H5I_clear_type(H5I_ERROR_MSG, FALSE, FALSE); + + /* Reset the HDF5 error messages, if they've been closed */ + if (H5I_nmembers(H5I_ERROR_MSG) == 0) { /* Include the automatically generated error code termination */ #include "H5Eterm.h" - } /* end if */ - } /* end if */ - - n++; /*H5I*/ - } /* end if */ - else { - /* Destroy the error class, message, and stack id groups */ - n += (H5I_dec_type_ref(H5I_ERROR_STACK) > 0); - n += (H5I_dec_type_ref(H5I_ERROR_CLASS) > 0); - n += (H5I_dec_type_ref(H5I_ERROR_MSG) > 0); - - /* Mark closed */ - if (0 == n) - H5_PKG_INIT_VAR = FALSE; - } /* end else */ - } /* end if */ + } /* end if */ + } /* end if */ + + n++; /*H5I*/ + } /* end if */ + else { + /* Destroy the error class, message, and stack id groups */ + n += (H5I_dec_type_ref(H5I_ERROR_STACK) > 0); + n += (H5I_dec_type_ref(H5I_ERROR_CLASS) > 0); + n += (H5I_dec_type_ref(H5I_ERROR_MSG) > 0); + + } /* end else */ FUNC_LEAVE_NOAPI(n) } /* end H5E_term_package() */ @@ -721,7 +686,7 @@ done: /*------------------------------------------------------------------------- * Function: H5E__close_msg * - * Purpose: Private function to close an error messge. + * Purpose: Private function to close an error message. * * Return: SUCCEED/FAIL * @@ -75,9 +75,6 @@ static H5EA_t *H5EA__new(H5F_t *f, haddr_t ea_addr, hbool_t from_open, void *ctx /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /* Extensible array client ID to class mapping */ /* Remember to add client ID to H5EA_cls_id_t in H5EAprivate.h when adding a new diff --git a/src/H5EAdbg.c b/src/H5EAdbg.c index b0e564c..b377422 100644 --- a/src/H5EAdbg.c +++ b/src/H5EAdbg.c @@ -237,7 +237,7 @@ H5EA__iblock_debug(H5F_t *f, haddr_t H5_ATTR_UNUSED addr, FILE *stream, int inde HDfprintf(stream, "%*sData Block Addresses in Index Block:\n", indent, ""); for (u = 0; u < iblock->ndblk_addrs; u++) { /* Print address */ - HDsprintf(temp_str, "Address #%u:", u); + HDsnprintf(temp_str, sizeof(temp_str), "Address #%u:", u); HDfprintf(stream, "%*s%-*s %" PRIuHADDR "\n", (indent + 3), "", MAX(0, (fwidth - 3)), temp_str, iblock->dblk_addrs[u]); } /* end for */ @@ -252,7 +252,7 @@ H5EA__iblock_debug(H5F_t *f, haddr_t H5_ATTR_UNUSED addr, FILE *stream, int inde HDfprintf(stream, "%*sSuper Block Addresses in Index Block:\n", indent, ""); for (u = 0; u < iblock->nsblk_addrs; u++) { /* Print address */ - HDsprintf(temp_str, "Address #%u:", u); + HDsnprintf(temp_str, sizeof(temp_str), "Address #%u:", u); HDfprintf(stream, "%*s%-*s %" PRIuHADDR "\n", (indent + 3), "", MAX(0, (fwidth - 3)), temp_str, iblock->sblk_addrs[u]); } /* end for */ @@ -341,7 +341,7 @@ H5EA__sblock_debug(H5F_t *f, haddr_t addr, FILE *stream, int indent, int fwidth, HDfprintf(stream, "%*sData Block Addresses in Super Block:\n", indent, ""); for (u = 0; u < sblock->ndblks; u++) { /* Print address */ - HDsprintf(temp_str, "Address #%u:", u); + HDsnprintf(temp_str, sizeof(temp_str), "Address #%u:", u); HDfprintf(stream, "%*s%-*s %" PRIuHADDR "\n", (indent + 3), "", MAX(0, (fwidth - 3)), temp_str, sblock->dblk_addrs[u]); } /* end for */ diff --git a/src/H5EApkg.h b/src/H5EApkg.h index bfa8588..2212ccb 100644 --- a/src/H5EApkg.h +++ b/src/H5EApkg.h @@ -301,7 +301,7 @@ typedef struct H5EA_dblock_t { /* Computed/cached values (not stored) */ size_t nelmts; /* Number of elements in block */ - size_t npages; /* Nummber of pages in a block (zero if not paged) */ + size_t npages; /* Number of pages in a block (zero if not paged) */ } H5EA_dblock_t; /* The extensible array data block page information */ diff --git a/src/H5EAprivate.h b/src/H5EAprivate.h index 19dabd9..9481559f 100644 --- a/src/H5EAprivate.h +++ b/src/H5EAprivate.h @@ -26,11 +26,6 @@ #ifndef H5EAprivate_H #define H5EAprivate_H -/* Include package's public header */ -#ifdef NOT_YET -#include "H5EApublic.h" -#endif /* NOT_YET */ - /* Private headers needed by this file */ #include "H5ACprivate.h" /* Metadata cache */ #include "H5Fprivate.h" /* File access */ diff --git a/src/H5EAtest.c b/src/H5EAtest.c index 7924eaa..24efbc2 100644 --- a/src/H5EAtest.c +++ b/src/H5EAtest.c @@ -322,7 +322,7 @@ H5EA__test_debug(FILE *stream, int indent, int fwidth, hsize_t idx, const void * HDassert(elmt); /* Print element */ - HDsprintf(temp_str, "Element #%llu:", (unsigned long long)idx); + HDsnprintf(temp_str, sizeof(temp_str), "Element #%llu:", (unsigned long long)idx); HDfprintf(stream, "%*s%-*s %llu\n", indent, "", fwidth, temp_str, (unsigned long long)*(const uint64_t *)elmt); @@ -236,6 +236,61 @@ done: } /* end H5ESget_op_counter() */ /*------------------------------------------------------------------------- + * Function: H5ESget_requests + * + * Purpose: Retrieve the requests in an event set. Up to *count + * requests are stored in the provided requests array, and + * the connector ids corresponding to these requests are + * stored in the provided connector_ids array. Either or + * both of these arrays may be NULL, in which case this + * information is not returned. If these arrays are + * non-NULL, they must be large enough to contain *count + * entries. On exit, *count is set to the total number of + * events in the event set. + * + * Events are returned in the order they were added to the + * event set. If order is H5_ITER_INC or H5_ITER_NATIVE, + * events will be returned starting from the oldest. If order + * is H5_ITER_DEC, events will be returned starting with the + * newest/most recent. + * + * Return: SUCCEED / FAIL + * + * Programmer: Neil Fortner + * Tuesday, November 23, 2021 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ESget_requests(hid_t es_id, H5_iter_order_t order, hid_t *connector_ids, void **requests, size_t array_len, + size_t *count /*out*/) +{ + H5ES_t *es; /* Event set */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE6("e", "iIo*i**xzx", es_id, order, connector_ids, requests, array_len, count); + + /* Check arguments */ + if (NULL == (es = H5I_object_verify(es_id, H5I_EVENTSET))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid event set identifier") + if (order <= H5_ITER_UNKNOWN || order >= H5_ITER_N) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified") + + /* Call internal routine */ + if (array_len > 0 && (requests || connector_ids)) + if (H5ES__get_requests(es, order, connector_ids, requests, array_len) < 0) + HGOTO_ERROR(H5E_EVENTSET, H5E_CANTGET, FAIL, "can't get requests") + + /* Retrieve the count, if non-NULL */ + if (count) + *count = H5ES__list_count(&es->active); + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5ESget_requests() */ + +/*------------------------------------------------------------------------- * Function: H5ESwait * * Purpose: Wait (with timeout) for operations in event set to complete diff --git a/src/H5ESdevelop.h b/src/H5ESdevelop.h index 5a0f2b4..2fb9aeb 100644 --- a/src/H5ESdevelop.h +++ b/src/H5ESdevelop.h @@ -42,6 +42,8 @@ extern "C" { #endif H5_DLL herr_t H5ESinsert_request(hid_t es_id, hid_t connector_id, void *request); +H5_DLL herr_t H5ESget_requests(hid_t es_id, H5_iter_order_t order, hid_t *connector_ids, void **requests, + size_t array_len, size_t *count); #ifdef __cplusplus } diff --git a/src/H5ESint.c b/src/H5ESint.c index 6f9efe9..7eb5909 100644 --- a/src/H5ESint.c +++ b/src/H5ESint.c @@ -50,6 +50,14 @@ /* Local Typedefs */ /******************/ +/* Callback context for get events operations */ +typedef struct H5ES_get_requests_ctx_t { + hid_t *connector_ids; /* Output buffer for list of connector IDs that match the above requests */ + void **requests; /* Output buffer for list of requests in event set */ + size_t array_len; /* Length of the above output buffers */ + size_t i; /* Number of elements filled in output buffers */ +} H5ES_get_requests_ctx_t; + /* Callback context for wait operations */ typedef struct H5ES_wait_ctx_t { H5ES_t * es; /* Event set being operated on */ @@ -84,6 +92,7 @@ static herr_t H5ES__close(H5ES_t *es); static herr_t H5ES__close_cb(void *es, void **request_token); static herr_t H5ES__insert(H5ES_t *es, H5VL_t *connector, void *request_token, const char *app_file, const char *app_func, unsigned app_line, const char *caller, const char *api_args); +static int H5ES__get_requests_cb(H5ES_event_t *ev, void *_ctx); static herr_t H5ES__handle_fail(H5ES_t *es, H5ES_event_t *ev); static herr_t H5ES__op_complete(H5ES_t *es, H5ES_event_t *ev, H5VL_request_status_t ev_status); static int H5ES__wait_cb(H5ES_event_t *ev, void *_ctx); @@ -95,9 +104,6 @@ static int H5ES__close_failed_cb(H5ES_event_t *ev, void *_ctx); /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /*****************************/ /* Library Private Variables */ /*****************************/ @@ -118,23 +124,20 @@ static const H5I_class_t H5I_EVENTSET_CLS[1] = {{ H5FL_DEFINE_STATIC(H5ES_t); /*------------------------------------------------------------------------- - * Function: H5ES__init_package + * Function: H5ES_init * - * Purpose: Initializes any interface-specific data or routines. - * - * Return: Non-negative on success / Negative on failure - * - * Programmer: Quincey Koziol - * Monday, April 6, 2020 + * Purpose: Initialize the interface from some other layer. * + * Return: Success: non-negative + * Failure: negative *------------------------------------------------------------------------- */ herr_t -H5ES__init_package(void) +H5ES_init(void) { herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_PACKAGE + FUNC_ENTER_NOAPI(FAIL) /* Initialize the ID group for the event set IDs */ if (H5I_register_type(H5I_EVENTSET_CLS) < 0) @@ -142,7 +145,7 @@ H5ES__init_package(void) done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5ES__init_package() */ +} /*------------------------------------------------------------------------- * Function: H5ES_term_package @@ -165,14 +168,8 @@ H5ES_term_package(void) FUNC_ENTER_NOAPI_NOINIT_NOERR - if (H5_PKG_INIT_VAR) { - /* Destroy the event set ID group */ - n += (H5I_dec_type_ref(H5I_EVENTSET) > 0); - - /* Mark closed */ - if (0 == n) - H5_PKG_INIT_VAR = FALSE; - } /* end if */ + /* Destroy the event set ID group */ + n += (H5I_dec_type_ref(H5I_EVENTSET) > 0); FUNC_LEAVE_NOAPI(n) } /* end H5ES_term_package() */ @@ -294,7 +291,8 @@ H5ES__insert(H5ES_t *es, H5VL_t *connector, void *request_token, const char *app * there's no need to duplicate it. */ ev->op_info.api_name = caller; - if (NULL == (ev->op_info.api_args = H5MM_xstrdup(api_args))) + HDassert(ev->op_info.api_args == NULL); + if (api_args && NULL == (ev->op_info.api_args = H5MM_xstrdup(api_args))) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTALLOC, FAIL, "can't copy API routine arguments") /* Append fully initialized event onto the event set's 'active' list */ @@ -431,6 +429,86 @@ done: } /* end H5ES__insert_request() */ /*------------------------------------------------------------------------- + * Function: H5ES__get_requests_cb + * + * Purpose: Iterator callback for H5ES__get_events - adds the event to + * the list. + * + * Return: SUCCEED / FAIL + * + * Programmer: Neil Fortner + * Tuesday, November 23, 2021 + * + *------------------------------------------------------------------------- + */ +static int +H5ES__get_requests_cb(H5ES_event_t *ev, void *_ctx) +{ + H5ES_get_requests_ctx_t *ctx = (H5ES_get_requests_ctx_t *)_ctx; /* Callback context */ + int ret_value = H5_ITER_CONT; /* Return value */ + + FUNC_ENTER_STATIC_NOERR + + /* Sanity check */ + HDassert(ev); + HDassert(ctx); + HDassert(ctx->i < ctx->array_len); + + /* Get the connector ID for the event */ + if (ctx->connector_ids) + ctx->connector_ids[ctx->i] = ev->request->connector->id; + + /* Get the request for the event */ + if (ctx->requests) + ctx->requests[ctx->i] = ev->request->data; + + /* Check if we've run out of room in the arrays */ + if (++ctx->i == ctx->array_len) + ret_value = H5_ITER_STOP; + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5ES__get_requests_cb() */ + +/*------------------------------------------------------------------------- + * Function: H5ES__get_requests + * + * Purpose: Get all requests in an event set. + * + * Return: SUCCEED / FAIL + * + * Programmer: Neil Fortner + * Tuesday, November 23, 2021 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ES__get_requests(H5ES_t *es, H5_iter_order_t order, hid_t *connector_ids, void **requests, size_t array_len) +{ + H5ES_get_requests_ctx_t ctx; /* Callback context */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* Sanity check */ + HDassert(es); + HDassert(array_len > 0); + HDassert(requests || connector_ids); + + /* Set up context for iterator callbacks */ + ctx.connector_ids = connector_ids; + ctx.requests = requests; + ctx.array_len = array_len; + ctx.i = 0; + + /* Iterate over the events in the set */ + if (H5ES__list_iterate(&es->active, order, H5ES__get_requests_cb, &ctx) < 0) + HGOTO_ERROR(H5E_EVENTSET, H5E_BADITER, FAIL, "iteration failed") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5ES__get_requests() */ + +/*------------------------------------------------------------------------- * Function: H5ES__handle_fail * * Purpose: Handle a failed event @@ -673,7 +751,7 @@ H5ES__wait(H5ES_t *es, uint64_t timeout, size_t *num_in_progress, hbool_t *op_fa ctx.op_failed = op_failed; /* Iterate over the events in the set, waiting for them to complete */ - if (H5ES__list_iterate(&es->active, H5ES__wait_cb, &ctx) < 0) + if (H5ES__list_iterate(&es->active, H5_ITER_NATIVE, H5ES__wait_cb, &ctx) < 0) HGOTO_ERROR(H5E_EVENTSET, H5E_BADITER, FAIL, "iteration failed") done: @@ -781,7 +859,7 @@ H5ES__cancel(H5ES_t *es, size_t *num_not_canceled, hbool_t *op_failed) ctx.op_failed = op_failed; /* Iterate over the events in the set, attempting to cancel them */ - if (H5ES__list_iterate(&es->active, H5ES__cancel_cb, &ctx) < 0) + if (H5ES__list_iterate(&es->active, H5_ITER_NATIVE, H5ES__cancel_cb, &ctx) < 0) HGOTO_ERROR(H5E_EVENTSET, H5E_BADITER, FAIL, "iteration failed") done: @@ -818,13 +896,13 @@ H5ES__get_err_info_cb(H5ES_event_t *ev, void *_ctx) * so there's no need to duplicate them internally, but they are duplicated * here, when they are given back to the user. */ - if (NULL == (ctx->curr_err_info->api_name = H5MM_strdup(ev->op_info.api_name))) + if (NULL == (ctx->curr_err_info->api_name = H5MM_xstrdup(ev->op_info.api_name))) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTALLOC, H5_ITER_ERROR, "can't copy HDF5 API routine name") - if (NULL == (ctx->curr_err_info->api_args = H5MM_strdup(ev->op_info.api_args))) + if (NULL == (ctx->curr_err_info->api_args = H5MM_xstrdup(ev->op_info.api_args))) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTALLOC, H5_ITER_ERROR, "can't copy HDF5 API routine arguments") - if (NULL == (ctx->curr_err_info->app_file_name = H5MM_strdup(ev->op_info.app_file_name))) + if (NULL == (ctx->curr_err_info->app_file_name = H5MM_xstrdup(ev->op_info.app_file_name))) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTALLOC, H5_ITER_ERROR, "can't copy HDF5 application file name") - if (NULL == (ctx->curr_err_info->app_func_name = H5MM_strdup(ev->op_info.app_func_name))) + if (NULL == (ctx->curr_err_info->app_func_name = H5MM_xstrdup(ev->op_info.app_func_name))) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTALLOC, H5_ITER_ERROR, "can't copy HDF5 application function name") ctx->curr_err_info->app_line_num = ev->op_info.app_line_num; ctx->curr_err_info->op_ins_count = ev->op_info.op_ins_count; @@ -895,7 +973,7 @@ H5ES__get_err_info(H5ES_t *es, size_t num_err_info, H5ES_err_info_t err_info[], ctx.curr_err_info = &err_info[0]; /* Iterate over the failed events in the set, copying their error info */ - if (H5ES__list_iterate(&es->failed, H5ES__get_err_info_cb, &ctx) < 0) + if (H5ES__list_iterate(&es->failed, H5_ITER_NATIVE, H5ES__get_err_info_cb, &ctx) < 0) HGOTO_ERROR(H5E_EVENTSET, H5E_BADITER, FAIL, "iteration failed") /* Set # of failed events cleared from event set's failed list */ @@ -969,7 +1047,7 @@ H5ES__close(H5ES_t *es) "can't close event set while unfinished operations are present (i.e. wait on event set first)") /* Iterate over the failed events in the set, releasing them */ - if (H5ES__list_iterate(&es->failed, H5ES__close_failed_cb, (void *)es) < 0) + if (H5ES__list_iterate(&es->failed, H5_ITER_NATIVE, H5ES__close_failed_cb, (void *)es) < 0) HGOTO_ERROR(H5E_EVENTSET, H5E_BADITER, FAIL, "iteration failed") /* Release the event set */ diff --git a/src/H5ESlist.c b/src/H5ESlist.c index c0e24cc..61a9dd1 100644 --- a/src/H5ESlist.c +++ b/src/H5ESlist.c @@ -88,6 +88,8 @@ H5ES__list_append(H5ES_event_list_t *el, H5ES_event_t *ev) HDassert(el); HDassert(ev); + ev->next = NULL; + /* Append event onto the event list */ if (NULL == el->tail) el->head = el->tail = ev; @@ -133,7 +135,10 @@ H5ES__list_count(const H5ES_event_list_t *el) * each event. * * Note: Iteration is safe for deleting the current event. Modifying - * the list in other ways is likely unsafe. + * the list in other ways is likely unsafe. If order is + * H5_ITER_INC or H5_ITER_NATIVE events are visited starting + * with the oldest, otherwise they are visited starting with + * the newest. * * Return: SUCCEED / FAIL * @@ -143,7 +148,7 @@ H5ES__list_count(const H5ES_event_list_t *el) *------------------------------------------------------------------------- */ int -H5ES__list_iterate(H5ES_event_list_t *el, H5ES_list_iter_func_t cb, void *ctx) +H5ES__list_iterate(H5ES_event_list_t *el, H5_iter_order_t order, H5ES_list_iter_func_t cb, void *ctx) { H5ES_event_t *ev; /* Event in list */ int ret_value = H5_ITER_CONT; /* Return value */ @@ -155,12 +160,12 @@ H5ES__list_iterate(H5ES_event_list_t *el, H5ES_list_iter_func_t cb, void *ctx) HDassert(cb); /* Iterate over events in list */ - ev = el->head; + ev = (order == H5_ITER_DEC) ? el->tail : el->head; while (ev) { H5ES_event_t *tmp; /* Temporary event */ /* Get pointer to next node, so it's safe if this one is removed */ - tmp = ev->next; + tmp = (order == H5_ITER_DEC) ? ev->prev : ev->next; /* Perform iterator callback */ if ((ret_value = (*cb)(ev, ctx)) != H5_ITER_CONT) { diff --git a/src/H5ESpkg.h b/src/H5ESpkg.h index a7a8e20..6ee50fa 100644 --- a/src/H5ESpkg.h +++ b/src/H5ESpkg.h @@ -81,6 +81,8 @@ typedef int (*H5ES_list_iter_func_t)(H5ES_event_t *ev, void *ctx); H5_DLL H5ES_t *H5ES__create(void); H5_DLL herr_t H5ES__insert_request(H5ES_t *es, H5VL_t *connector, void *token); H5_DLL herr_t H5ES__wait(H5ES_t *es, uint64_t timeout, size_t *num_in_progress, hbool_t *op_failed); +H5_DLL herr_t H5ES__get_requests(H5ES_t *es, H5_iter_order_t order, hid_t *connector_ids, void **requests, + size_t array_len); H5_DLL herr_t H5ES__cancel(H5ES_t *es, size_t *num_not_canceled, hbool_t *op_failed); H5_DLL herr_t H5ES__get_err_info(H5ES_t *es, size_t num_err_info, H5ES_err_info_t err_info[], size_t *num_cleared); @@ -88,7 +90,8 @@ H5_DLL herr_t H5ES__get_err_info(H5ES_t *es, size_t num_err_info, H5ES_err_info /* Event list operations */ H5_DLL void H5ES__list_append(H5ES_event_list_t *el, H5ES_event_t *ev); H5_DLL size_t H5ES__list_count(const H5ES_event_list_t *el); -H5_DLL int H5ES__list_iterate(H5ES_event_list_t *el, H5ES_list_iter_func_t cb, void *ctx); +H5_DLL int H5ES__list_iterate(H5ES_event_list_t *el, H5_iter_order_t order, H5ES_list_iter_func_t cb, + void *ctx); H5_DLL void H5ES__list_remove(H5ES_event_list_t *el, const H5ES_event_t *ev); /* Event operations */ diff --git a/src/H5ESprivate.h b/src/H5ESprivate.h index 3d9ce9f..153e3e3 100644 --- a/src/H5ESprivate.h +++ b/src/H5ESprivate.h @@ -51,5 +51,6 @@ typedef struct H5ES_t H5ES_t; /***************************************/ herr_t H5ES_insert(hid_t es_id, H5VL_t *connector, void *token, const char *caller, const char *caller_args, ...); +H5_DLL herr_t H5ES_init(void); #endif /* H5ESprivate_H */ diff --git a/src/H5ESpublic.h b/src/H5ESpublic.h index 4cf71c5..c8d1c7b 100644 --- a/src/H5ESpublic.h +++ b/src/H5ESpublic.h @@ -51,13 +51,13 @@ typedef enum H5ES_status_t { /* Information about operations in an event set */ typedef struct H5ES_op_info_t { /* API call info */ - char *api_name; /* Name of HDF5 API routine called */ - char *api_args; /* "Argument string" for arguments to HDF5 API routine called */ + const char *api_name; /* Name of HDF5 API routine called */ + char * api_args; /* "Argument string" for arguments to HDF5 API routine called */ /* Application info */ - char * app_file_name; /* Name of source file where the HDF5 API routine was called */ - char * app_func_name; /* Name of function where the HDF5 API routine was called */ - unsigned app_line_num; /* Line # of source file where the HDF5 API routine was called */ + const char *app_file_name; /* Name of source file where the HDF5 API routine was called */ + const char *app_func_name; /* Name of function where the HDF5 API routine was called */ + unsigned app_line_num; /* Line # of source file where the HDF5 API routine was called */ /* Operation info */ uint64_t op_ins_count; /* Counter of operation's insertion into event set */ @@ -200,7 +200,18 @@ H5_DLL herr_t H5ESget_count(hid_t es_id, size_t *count); /** * \ingroup H5ES * - * \todo Fill in the blanks! + * \brief Retrieves the next operation counter to be assigned in an event set + * + * \es_id + * \param[out] counter The next counter value to be assigned to an event + * \returns \herr_t + * + * \details H5ESget_op_counter() retrieves the \p counter that will be assigned + * to the next operation inserted into the event set \p es_id. + * + * \note This is designed for wrapper libraries mainly, to use as a mechanism + * for matching operations inserted into the event set with possible + * errors that occur. * * \since 1.13.0 * diff --git a/src/H5Eint.c b/src/H5Eint.c index 6438cd9..d744db3 100644 --- a/src/H5Eint.c +++ b/src/H5Eint.c @@ -930,7 +930,7 @@ H5E_dump_api_stack(hbool_t is_api) { herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR /* Only dump the error stack during an API call */ if (is_api) { @@ -953,6 +953,5 @@ H5E_dump_api_stack(hbool_t is_api) #endif /* H5_NO_DEPRECATED_SYMBOLS */ } /* end if */ -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5E_dump_api_stack() */ diff --git a/src/H5Epkg.h b/src/H5Epkg.h index 30ff084..b11ee9e 100644 --- a/src/H5Epkg.h +++ b/src/H5Epkg.h @@ -48,7 +48,7 @@ * each thread individually. The association of stacks to threads will * be handled by the pthread library. * - * In order for this macro to work, H5E__get_my_stack() must be preceeded + * In order for this macro to work, H5E__get_my_stack() must be preceded * by "H5E_t *estack =". */ #define H5E__get_my_stack() H5E__get_stack() @@ -1306,7 +1306,7 @@ done: /*------------------------------------------------------------------------- * Function: H5Funmount * - * Purpose: Given a mount point, dissassociate the mount point's file + * Purpose: Given a mount point, disassociate the mount point's file * from the file mounted there. Do not close either file. * * The mount point can either be the group in the parent or the @@ -2262,7 +2262,7 @@ done: * 1) The file being opened has v3 superblock * 2) The file is opened with H5F_ACC_RDWR * 3) The file is not already marked for SWMR writing - * 4) Current implementaion for opened objects: + * 4) Current implementation for opened objects: * --only allow datasets and groups without attributes * --disallow named datatype with/without attributes * --disallow opened attributes attached to objects @@ -64,9 +64,6 @@ static H5FA_t *H5FA__new(H5F_t *f, haddr_t fa_addr, hbool_t from_open, void *ctx /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /* Fixed array client ID to class mapping */ /* Remember to add client ID to H5FA_cls_id_t in H5FAprivate.h when adding a new @@ -95,7 +92,7 @@ H5FL_BLK_DEFINE(fa_native_elmt); /*------------------------------------------------------------------------- * Function: H5FA__new * - * Purpose: Allocate and initialize a new fixe array wrapper in memory + * Purpose: Allocate and initialize a new fixed array wrapper in memory * * Return: Pointer to farray wrapper success * NULL on failure diff --git a/src/H5FAcache.c b/src/H5FAcache.c index 367b4b0..e6e32da 100644 --- a/src/H5FAcache.c +++ b/src/H5FAcache.c @@ -943,7 +943,7 @@ done: * file space block set. * * This function is needed when the data block is paged, as - * the datablock header and all its pages are allocted as a + * the datablock header and all its pages are allocated as a * single contiguous chunk of file space, and must be * deallocated the same way. * diff --git a/src/H5FAdblkpage.c b/src/H5FAdblkpage.c index 713bd67..f6a5aef 100644 --- a/src/H5FAdblkpage.c +++ b/src/H5FAdblkpage.c @@ -147,7 +147,7 @@ H5FA__dblk_page_create(H5FA_hdr_t *hdr, haddr_t addr, size_t nelmts) FUNC_ENTER_PACKAGE #ifdef H5FA_DEBUG - HDfprintf(stderr, "%s: Called, addr = %a\n", __func__, addr); + HDfprintf(stderr, "%s: Called, addr = %" PRIuHADDR "\n", __func__, addr); #endif /* H5FA_DEBUG */ /* Sanity check */ diff --git a/src/H5FApkg.h b/src/H5FApkg.h index c4bf934..15f6445 100644 --- a/src/H5FApkg.h +++ b/src/H5FApkg.h @@ -179,8 +179,8 @@ typedef struct H5FA_dblock_t { /* Computed/cached values (not stored) */ haddr_t addr; /* Address of this data block on disk */ hsize_t size; /* Size of data block on disk */ - size_t npages; /* Nummber of pages in data block (zero if not paged) */ - size_t last_page_nelmts; /* Nummber of elements in last page, if paged */ + size_t npages; /* Number of pages in data block (zero if not paged) */ + size_t last_page_nelmts; /* Number of elements in last page, if paged */ /* Fixed Array data block information (not stored) */ size_t dblk_page_nelmts; /* # of elements per data block page */ diff --git a/src/H5FAprivate.h b/src/H5FAprivate.h index 26057bf..745c129 100644 --- a/src/H5FAprivate.h +++ b/src/H5FAprivate.h @@ -24,11 +24,6 @@ #ifndef H5FAprivate_H #define H5FAprivate_H -/* Include package's public header */ -#ifdef NOT_YET -#include "H5FApublic.h" -#endif /* NOT_YET */ - /* Private headers needed by this file */ #include "H5ACprivate.h" /* Metadata cache */ #include "H5Fprivate.h" /* File access */ @@ -134,7 +129,7 @@ H5_DLL herr_t H5FA_patch_file(H5FA_t *fa, H5F_t *f); H5_DLL herr_t H5FA_get_stats(const H5FA_t *ea, H5FA_stat_t *stats); /* Debugging routines */ -#ifdef H5FA_DEBUGGING -#endif /* H5FA_DEBUGGING */ +#ifdef H5FA_DEBUG +#endif /* H5FA_DEBUG */ #endif /* H5FAprivate_H */ diff --git a/src/H5FAtest.c b/src/H5FAtest.c index 384a657..b57f562 100644 --- a/src/H5FAtest.c +++ b/src/H5FAtest.c @@ -303,7 +303,7 @@ H5FA__test_debug(FILE *stream, int indent, int fwidth, hsize_t idx, const void * HDassert(elmt); /* Print element */ - HDsprintf(temp_str, "Element #%llu:", (unsigned long long)idx); + HDsnprintf(temp_str, sizeof(temp_str), "Element #%llu:", (unsigned long long)idx); HDfprintf(stream, "%*s%-*s %llu\n", indent, "", fwidth, temp_str, (unsigned long long)*(const uint64_t *)elmt); @@ -61,9 +61,6 @@ static herr_t H5FD__query(const H5FD_t *f, unsigned long *flags /*out*/); /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /*****************************/ /* Library Private Variables */ /*****************************/ @@ -95,20 +92,20 @@ static const H5I_class_t H5I_VFL_CLS[1] = {{ }}; /*------------------------------------------------------------------------- - * Function: H5FD__init_package - * - * Purpose: Initialize the virtual file layer. + * Function: H5FD_init * - * Return: SUCCEED/FAIL + * Purpose: Initialize the interface from some other layer. * + * Return: Success: non-negative + * Failure: negative *------------------------------------------------------------------------- */ herr_t -H5FD__init_package(void) +H5FD_init(void) { herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_PACKAGE + FUNC_ENTER_NOAPI(FAIL) if (H5I_register_type(H5I_VFL_CLS) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "unable to initialize interface") @@ -118,7 +115,7 @@ H5FD__init_package(void) done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD__init_package() */ +} /*------------------------------------------------------------------------- * Function: H5FD_term_package @@ -142,20 +139,14 @@ H5FD_term_package(void) FUNC_ENTER_NOAPI_NOINIT_NOERR - if (H5_PKG_INIT_VAR) { - if (H5I_nmembers(H5I_VFL) > 0) { - (void)H5I_clear_type(H5I_VFL, FALSE, FALSE); - n++; /*H5I*/ - } /* end if */ - else { - /* Destroy the VFL driver ID group */ - n += (H5I_dec_type_ref(H5I_VFL) > 0); - - /* Mark closed */ - if (0 == n) - H5_PKG_INIT_VAR = FALSE; - } /* end else */ - } /* end if */ + if (H5I_nmembers(H5I_VFL) > 0) { + (void)H5I_clear_type(H5I_VFL, FALSE, FALSE); + n++; /*H5I*/ + } /* end if */ + else { + /* Destroy the VFL driver ID group */ + n += (H5I_dec_type_ref(H5I_VFL) > 0); + } /* end else */ FUNC_LEAVE_NOAPI(n) } /* end H5FD_term_package() */ @@ -165,7 +156,7 @@ H5FD_term_package(void) * * Purpose: Frees a file driver class struct and returns an indication of * success. This function is used as the free callback for the - * virtual file layer object identifiers (cf H5FD__init_package). + * virtual file layer object identifiers (cf H5FD_init). * * Return: SUCCEED/FAIL * @@ -223,6 +214,8 @@ H5FDregister(const H5FD_class_t *cls) /* Check arguments */ if (!cls) HGOTO_ERROR(H5E_ARGS, H5E_UNINITIALIZED, H5I_INVALID_HID, "null class pointer is disallowed") + if (cls->version != H5FD_CLASS_VERSION) + HGOTO_ERROR(H5E_ARGS, H5E_VERSION, H5I_INVALID_HID, "wrong file driver version #") if (!cls->open || !cls->close) HGOTO_ERROR(H5E_ARGS, H5E_UNINITIALIZED, H5I_INVALID_HID, "'open' and/or 'close' methods are not defined") @@ -301,6 +294,62 @@ done: } /* end H5FD_register() */ /*------------------------------------------------------------------------- + * Function: H5FDis_driver_registered_by_name + * + * Purpose: Tests whether a VFD class has been registered or not + * according to a supplied driver name. + * + * Return: >0 if a VFD with that name has been registered + * 0 if a VFD with that name has NOT been registered + * <0 on errors + * + *------------------------------------------------------------------------- + */ +htri_t +H5FDis_driver_registered_by_name(const char *driver_name) +{ + htri_t ret_value = FALSE; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE1("t", "*s", driver_name); + + /* Check if driver with this name is registered */ + if ((ret_value = H5FD_is_driver_registered_by_name(driver_name, NULL)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't check if VFD is registered") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5FDis_driver_registered_by_name() */ + +/*------------------------------------------------------------------------- + * Function: H5FDis_driver_registered_by_value + * + * Purpose: Tests whether a VFD class has been registered or not + * according to a supplied driver value (ID). + * + * Return: >0 if a VFD with that value has been registered + * 0 if a VFD with that value hasn't been registered + * <0 on errors + * + *------------------------------------------------------------------------- + */ +htri_t +H5FDis_driver_registered_by_value(H5FD_class_value_t driver_value) +{ + htri_t ret_value = FALSE; + + FUNC_ENTER_API(FAIL) + H5TRACE1("t", "DV", driver_value); + + /* Check if driver with this value is registered */ + if ((ret_value = H5FD_is_driver_registered_by_value(driver_value, NULL)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't check if VFD is registered") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5FDis_driver_registered_by_value() */ + +/*------------------------------------------------------------------------- * Function: H5FDunregister * * Purpose: Removes a driver ID from the library. This in no way affects @@ -398,7 +447,7 @@ H5FD_sb_size(H5FD_t *file) { hsize_t ret_value = 0; - FUNC_ENTER_NOAPI(0) + FUNC_ENTER_NOAPI_NOERR /* Sanity checks */ HDassert(file); @@ -408,7 +457,6 @@ H5FD_sb_size(H5FD_t *file) if (file->cls->sb_size) ret_value = (file->cls->sb_size)(file); -done: FUNC_LEAVE_NOAPI(ret_value) } @@ -536,7 +584,7 @@ H5FD_fapl_get(H5FD_t *file) { void *ret_value = NULL; - FUNC_ENTER_NOAPI(NULL) + FUNC_ENTER_NOAPI_NOERR /* Sanity checks */ HDassert(file); @@ -546,7 +594,6 @@ H5FD_fapl_get(H5FD_t *file) if (file->cls->fapl_get) ret_value = (file->cls->fapl_get)(file); -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD_fapl_get() */ @@ -883,7 +930,7 @@ H5FD_cmp(const H5FD_t *f1, const H5FD_t *f2) { int ret_value = -1; /* Return value */ - FUNC_ENTER_NOAPI(-1) /* return value is arbitrary */ + FUNC_ENTER_NOAPI_NOERR; /* return value is arbitrary */ if ((!f1 || !f1->cls) && (!f2 || !f2->cls)) HGOTO_DONE(0) @@ -1244,7 +1291,7 @@ H5FD_get_maxaddr(const H5FD_t *file) { haddr_t ret_value = HADDR_UNDEF; /* Return value */ - FUNC_ENTER_NOAPI(HADDR_UNDEF) + FUNC_ENTER_NOAPI_NOERR /* Sanity checks */ HDassert(file); @@ -1252,7 +1299,6 @@ H5FD_get_maxaddr(const H5FD_t *file) /* Set return value */ ret_value = file->maxaddr; -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD_get_maxaddr() */ @@ -1324,7 +1370,7 @@ H5FD_get_fs_type_map(const H5FD_t *file, H5FD_mem_t *type_map) HDassert(file->cls); HDassert(type_map); - /* Check for VFD class providing a type map retrieval rouine */ + /* Check for VFD class providing a type map retrieval routine */ if (file->cls->get_type_map) { /* Retrieve type mapping for this file */ if ((file->cls->get_type_map)(file, type_map) < 0) @@ -1436,6 +1482,370 @@ done: } /* end H5FDwrite() */ /*------------------------------------------------------------------------- + * Function: H5FDread_vector + * + * Purpose: Perform count reads from the specified file at the offsets + * provided in the addrs array, with the lengths and memory + * types provided in the sizes and types arrays. Data read + * is returned in the buffers provided in the bufs array. + * + * All reads are done according to the data transfer property + * list dxpl_id (which may be the constant H5P_DEFAULT). + * + * Return: Success: SUCCEED + * All reads have completed successfully, and + * the results havce been into the supplied + * buffers. + * + * Failure: FAIL + * The contents of supplied buffers are undefined. + * + * Programmer: JRM -- 6/10/20 + * + * Changes: None. + * + *------------------------------------------------------------------------- + */ +herr_t +H5FDread_vector(H5FD_t *file, hid_t dxpl_id, uint32_t count, H5FD_mem_t types[], haddr_t addrs[], + size_t sizes[], void *bufs[] /* out */) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE7("e", "*#iIu*Mt*a*zx", file, dxpl_id, count, types, addrs, sizes, bufs); + + /* Check arguments */ + if (!file) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file pointer cannot be NULL") + + if (!file->cls) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file class pointer cannot be NULL") + + if ((!types) && (count > 0)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "types parameter can't be NULL if count is positive") + + if ((!addrs) && (count > 0)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "addrs parameter can't be NULL if count is positive") + + if ((!sizes) && (count > 0)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "sizes parameter can't be NULL if count is positive") + + if ((!bufs) && (count > 0)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bufs parameter can't be NULL if count is positive") + + if ((count > 0) && (sizes[0] == 0)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "sizes[0] can't be 0") + + if ((count > 0) && (types[0] == H5FD_MEM_NOLIST)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "count[0] can't be H5FD_MEM_NOLIST") + + /* Get the default dataset transfer property list if the user + * didn't provide one + */ + if (H5P_DEFAULT == dxpl_id) { + dxpl_id = H5P_DATASET_XFER_DEFAULT; + } + else { + if (TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list") + } + + /* Set DXPL for operation */ + H5CX_set_dxpl(dxpl_id); + + /* Call private function */ + /* (Note compensating for base addresses addition in internal routine) */ + if (H5FD_read_vector(file, count, types, addrs, sizes, bufs) < 0) + HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "file vector read request failed") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5FDread_vector() */ + +/*------------------------------------------------------------------------- + * Function: H5FDwrite_vector + * + * Purpose: Perform count writes to the specified file at the offsets + * provided in the addrs array, with the lengths and memory + * types provided in the sizes and types arrays. Data to be + * written is in the buffers provided in the bufs array. + * + * All writes are done according to the data transfer property + * list dxpl_id (which may be the constant H5P_DEFAULT). + * + * Return: Success: SUCCEED + * All writes have completed successfully + * + * Failure: FAIL + * One or more of the writes failed. + * + * Programmer: JRM -- 6/10/20 + * + * Changes: None. + * + *------------------------------------------------------------------------- + */ +herr_t +H5FDwrite_vector(H5FD_t *file, hid_t dxpl_id, uint32_t count, H5FD_mem_t types[], haddr_t addrs[], + size_t sizes[], const void *bufs[] /* in */) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE7("e", "*#iIu*Mt*a*z**x", file, dxpl_id, count, types, addrs, sizes, bufs); + + /* Check arguments */ + if (!file) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file pointer cannot be NULL") + + if (!file->cls) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file class pointer cannot be NULL") + + if ((!types) && (count > 0)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "types parameter can't be NULL if count is positive") + + if ((!addrs) && (count > 0)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "addrs parameter can't be NULL if count is positive") + + if ((!sizes) && (count > 0)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "sizes parameter can't be NULL if count is positive") + + if ((!bufs) && (count > 0)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bufs parameter can't be NULL if count is positive") + + if ((count > 0) && (sizes[0] == 0)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "sizes[0] can't be 0") + + if ((count > 0) && (types[0] == H5FD_MEM_NOLIST)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "count[0] can't be H5FD_MEM_NOLIST") + + /* Get the default dataset transfer property list if the user didn't provide one */ + if (H5P_DEFAULT == dxpl_id) { + dxpl_id = H5P_DATASET_XFER_DEFAULT; + } + else { + if (TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list") + } + + /* Set DXPL for operation */ + H5CX_set_dxpl(dxpl_id); + + /* Call private function */ + /* (Note compensating for base address addition in internal routine) */ + if (H5FD_write_vector(file, count, types, addrs, sizes, bufs) < 0) + HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "file vector write request failed") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5FDwrite_vector() */ + +/*------------------------------------------------------------------------- + * Function: H5FDread_selection + * + * Purpose: Perform count reads from the specified file at the + * locations selected in the dataspaces in the file_spaces + * array, with each of those dataspaces starting at the file + * address specified by the corresponding element of the + * offsets array, and with the size of each element in the + * dataspace specified by the corresponding element of the + * element_sizes array. The memory type provided by type is + * the same for all selections. Data read is returned in + * the locations selected in the dataspaces in the + * mem_spaces array, within the buffers provided in the + * corresponding elements of the bufs array. + * + * If i > 0 and element_sizes[i] == 0, presume + * element_sizes[n] = element_sizes[i-1] for all n >= i and + * < count. + * + * If the underlying VFD supports selection reads, pass the + * call through directly. + * + * If it doesn't, convert the selection read into a sequence + * of individual reads. + * + * All reads are done according to the data transfer property + * list dxpl_id (which may be the constant H5P_DEFAULT). + * + * Return: Success: SUCCEED + * All reads have completed successfully, and + * the results havce been into the supplied + * buffers. + * + * Failure: FAIL + * The contents of supplied buffers are undefined. + * + * Programmer: NAF -- 5/19/21 + * + * Changes: None. + * + *------------------------------------------------------------------------- + */ +herr_t +H5FDread_selection(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, uint32_t count, hid_t mem_space_ids[], + hid_t file_space_ids[], haddr_t offsets[], size_t element_sizes[], void *bufs[] /* out */) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE9("e", "*#MtiIu*i*i*a*zx", file, type, dxpl_id, count, mem_space_ids, file_space_ids, offsets, + element_sizes, bufs); + + /* Check arguments */ + if (!file) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file pointer cannot be NULL") + + if (!file->cls) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file class pointer cannot be NULL") + + if ((!mem_space_ids) && (count > 0)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "mem_spaces parameter can't be NULL if count is positive") + + if ((!file_space_ids) && (count > 0)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file_spaces parameter can't be NULL if count is positive") + + if ((!offsets) && (count > 0)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "offsets parameter can't be NULL if count is positive") + + if ((!element_sizes) && (count > 0)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, + "element_sizes parameter can't be NULL if count is positive") + + if ((!bufs) && (count > 0)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bufs parameter can't be NULL if count is positive") + + if ((count > 0) && (element_sizes[0] == 0)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "sizes[0] can't be 0") + + if ((count > 0) && (bufs[0] == NULL)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bufs[0] can't be NULL") + + /* Get the default dataset transfer property list if the user didn't provide one */ + if (H5P_DEFAULT == dxpl_id) { + dxpl_id = H5P_DATASET_XFER_DEFAULT; + } + else { + if (TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list") + } + + /* Set DXPL for operation */ + H5CX_set_dxpl(dxpl_id); + + /* Call private function */ + /* (Note compensating for base address addition in internal routine) */ + if (H5FD_read_selection_id(file, type, count, mem_space_ids, file_space_ids, offsets, element_sizes, + bufs) < 0) + HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "file selection read request failed") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5FDread_selection() */ + +/*------------------------------------------------------------------------- + * Function: H5FDwrite_selection + * + * Purpose: Perform count writes to the specified file at the + * locations selected in the dataspaces in the file_spaces + * array, with each of those dataspaces starting at the file + * address specified by the corresponding element of the + * offsets array, and with the size of each element in the + * dataspace specified by the corresponding element of the + * element_sizes array. The memory type provided by type is + * the same for all selections. Data write is from + * the locations selected in the dataspaces in the + * mem_spaces array, within the buffers provided in the + * corresponding elements of the bufs array. + * + * If i > 0 and element_sizes[i] == 0, presume + * element_sizes[n] = element_sizes[i-1] for all n >= i and + * < count. + * + * If the underlying VFD supports selection writes, pass the + * call through directly. + * + * If it doesn't, convert the selection write into a sequence + * of individual writes. + * + * All writes are done according to the data transfer property + * list dxpl_id (which may be the constant H5P_DEFAULT). + * + * Return: Success: SUCCEED + * All writes have completed successfully + * + * Failure: FAIL + * One or more of the writes failed. + * + * Programmer: NAF -- 5/14/21 + * + * Changes: None. + * + *------------------------------------------------------------------------- + */ +herr_t +H5FDwrite_selection(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, uint32_t count, hid_t mem_space_ids[], + hid_t file_space_ids[], haddr_t offsets[], size_t element_sizes[], const void *bufs[]) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE9("e", "*#MtiIu*i*i*a*z**x", file, type, dxpl_id, count, mem_space_ids, file_space_ids, offsets, + element_sizes, bufs); + + /* Check arguments */ + if (!file) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file pointer cannot be NULL") + + if (!file->cls) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file class pointer cannot be NULL") + + if ((!mem_space_ids) && (count > 0)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "mem_spaces parameter can't be NULL if count is positive") + + if ((!file_space_ids) && (count > 0)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file_spaces parameter can't be NULL if count is positive") + + if ((!offsets) && (count > 0)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "offsets parameter can't be NULL if count is positive") + + if ((!element_sizes) && (count > 0)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, + "element_sizes parameter can't be NULL if count is positive") + + if ((!bufs) && (count > 0)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bufs parameter can't be NULL if count is positive") + + if ((count > 0) && (element_sizes[0] == 0)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "sizes[0] can't be 0") + + if ((count > 0) && (bufs[0] == NULL)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bufs[0] can't be NULL") + + /* Get the default dataset transfer property list if the user didn't provide one */ + if (H5P_DEFAULT == dxpl_id) { + dxpl_id = H5P_DATASET_XFER_DEFAULT; + } + else { + if (TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list") + } + + /* Set DXPL for operation */ + H5CX_set_dxpl(dxpl_id); + + /* Call private function */ + /* (Note compensating for base address addition in internal routine) */ + if (H5FD_write_selection_id(file, type, count, mem_space_ids, file_space_ids, offsets, element_sizes, + bufs) < 0) + HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "file selection write request failed") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5FDwrite_selection() */ + +/*------------------------------------------------------------------------- * Function: H5FDflush * * Purpose: Notify driver to flush all cached data. If the driver has no @@ -1688,6 +2098,111 @@ done: } /* end H5FD_unlock() */ /*------------------------------------------------------------------------- + * Function: H5FDctl + * + * Purpose: Perform a CTL operation. + * + * The desired operation is specified by the op_code + * parameter. + * + * The flags parameter controls management of op_codes that + * are unknown to the callback + * + * The input and output parameters allow op_code specific + * input and output + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: JRM -- 8/3/21 + * + *------------------------------------------------------------------------- + */ +herr_t +H5FDctl(H5FD_t *file, uint64_t op_code, uint64_t flags, const void *input, void **output) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE5("e", "*#ULUL*x**x", file, op_code, flags, input, output); + + /* Check arguments */ + if (!file) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file pointer cannot be NULL") + + if (!file->cls) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file class pointer cannot be NULL") + + /* Don't attempt to validate the op code. If appropriate, that will + * be done by the underlying VFD callback, along with the input and + * output parameters. + */ + + /* Call private function */ + if (H5FD_ctl(file, op_code, flags, input, output) < 0) + HGOTO_ERROR(H5E_VFL, H5E_FCNTL, FAIL, "VFD ctl request failed") + +done: + + FUNC_LEAVE_API(ret_value) + +} /* end H5FDctl() */ + +/*------------------------------------------------------------------------- + * Function: H5FD_ctl + * + * Purpose: Private version of H5FDctl() + * + * The desired operation is specified by the op_code + * parameter. + * + * The flags parameter controls management of op_codes that + * are unknown to the callback + * + * The input and output parameters allow op_code specific + * input and output + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: JRM -- 8/3/21 + * + *------------------------------------------------------------------------- + */ +herr_t +H5FD_ctl(H5FD_t *file, uint64_t op_code, uint64_t flags, const void *input, void **output) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity checks */ + HDassert(file); + HDassert(file->cls); + + /* Dispatch to driver if the ctl function exists. + * + * If it doesn't, fail if the H5FD_CTL__FAIL_IF_UNKNOWN_FLAG is set. + * + * Otherwise, report success. + */ + if (file->cls->ctl) { + + if ((file->cls->ctl)(file, op_code, flags, input, output) < 0) + + HGOTO_ERROR(H5E_VFL, H5E_FCNTL, FAIL, "VFD ctl request failed") + } + else if (flags & H5FD_CTL__FAIL_IF_UNKNOWN_FLAG) { + + HGOTO_ERROR(H5E_VFL, H5E_FCNTL, FAIL, + "VFD ctl request failed (no ctl and fail if unknown flag is set)") + } + +done: + + FUNC_LEAVE_NOAPI(ret_value) + +} /* end H5FD_ctl() */ + +/*------------------------------------------------------------------------- * Function: H5FD_get_fileno * * Purpose: Quick and dirty routine to retrieve the file's 'fileno' value diff --git a/src/H5FDcore.c b/src/H5FDcore.c index 50288c4..0604316 100644 --- a/src/H5FDcore.c +++ b/src/H5FDcore.c @@ -149,8 +149,11 @@ static herr_t H5FD__core_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing static herr_t H5FD__core_lock(H5FD_t *_file, hbool_t rw); static herr_t H5FD__core_unlock(H5FD_t *_file); static herr_t H5FD__core_delete(const char *filename, hid_t fapl_id); +static inline const H5FD_core_fapl_t *H5FD__core_get_default_config(void); static const H5FD_class_t H5FD_core_g = { + H5FD_CLASS_VERSION, /* struct version */ + H5FD_CORE_VALUE, /* value */ "core", /* name */ MAXADDR, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -178,14 +181,24 @@ static const H5FD_class_t H5FD_core_g = { H5FD__core_get_handle, /* get_handle */ H5FD__core_read, /* read */ H5FD__core_write, /* write */ + NULL, /* read_vector */ + NULL, /* write_vector */ + NULL, /* read_selection */ + NULL, /* write_selection */ H5FD__core_flush, /* flush */ H5FD__core_truncate, /* truncate */ H5FD__core_lock, /* lock */ H5FD__core_unlock, /* unlock */ H5FD__core_delete, /* del */ + NULL, /* ctl */ H5FD_FLMAP_DICHOTOMY /* fl_map */ }; +/* Default configurations, if none provided */ +static const H5FD_core_fapl_t H5FD_core_default_config_g = { + (size_t)H5_MB, TRUE, H5FD_CORE_WRITE_TRACKING_FLAG, H5FD_CORE_WRITE_TRACKING_PAGE_SIZE}; +static const H5FD_core_fapl_t H5FD_core_default_paged_config_g = {(size_t)H5_MB, TRUE, TRUE, (size_t)4096}; + /* Define a free list to manage the region type */ H5FL_DEFINE(H5FD_core_region_t); @@ -390,7 +403,7 @@ H5FD__core_write_to_bstore(H5FD_core_t *file, haddr_t addr, size_t size) "write to backing store failed: time = %s, filename = '%s', file descriptor = %d, " "errno = %d, error message = '%s', ptr = %p, total write size = %llu, bytes this " "sub-write = %llu, bytes actually written = %llu, offset = %llu", - HDctime(&mytime), file->name, file->fd, myerrno, HDstrerror(myerrno), ptr, + HDctime(&mytime), file->name, file->fd, myerrno, HDstrerror(myerrno), (void *)ptr, (unsigned long long)size, (unsigned long long)bytes_in, (unsigned long long)bytes_wrote, (unsigned long long)offset); } /* end if */ @@ -408,37 +421,30 @@ done: } /* end H5FD__core_write_to_bstore() */ /*------------------------------------------------------------------------- - * Function: H5FD__init_package + * Function: H5FD__core_get_default_config * - * Purpose: Initializes any interface-specific data or routines. + * Purpose: Retrieves a default configuration for this VFD when no + * configuration information has been provided. * - * Return: Non-negative on success/Negative on failure + * Return: Valid Core VFD configuration information pointer (can't + * fail) * *------------------------------------------------------------------------- */ -static herr_t -H5FD__init_package(void) +static inline const H5FD_core_fapl_t * +H5FD__core_get_default_config(void) { - char * lock_env_var = NULL; /* Environment variable pointer */ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_STATIC + char *driver = HDgetenv(HDF5_DRIVER); - /* Check the use disabled file locks environment variable */ - lock_env_var = HDgetenv("HDF5_USE_FILE_LOCKING"); - if (lock_env_var && !HDstrcmp(lock_env_var, "BEST_EFFORT")) - ignore_disabled_file_locks_s = TRUE; /* Override: Ignore disabled locks */ - else if (lock_env_var && (!HDstrcmp(lock_env_var, "TRUE") || !HDstrcmp(lock_env_var, "1"))) - ignore_disabled_file_locks_s = FALSE; /* Override: Don't ignore disabled locks */ - else - ignore_disabled_file_locks_s = FAIL; /* Environment variable not set, or not set correctly */ - - if (H5FD_core_init() < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "unable to initialize core VFD") + if (driver) { + if (!HDstrcmp(driver, "core")) + return &H5FD_core_default_config_g; + else if (!HDstrcmp(driver, "core_paged")) + return &H5FD_core_default_paged_config_g; + } -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5FD__init_package() */ + return &H5FD_core_default_config_g; +} /* end H5FD__core_get_default_config() */ /*------------------------------------------------------------------------- * Function: H5FD_core_init @@ -457,9 +463,19 @@ done: hid_t H5FD_core_init(void) { - hid_t ret_value = H5I_INVALID_HID; /* Return value */ + char *lock_env_var = NULL; /* Environment variable pointer */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ - FUNC_ENTER_NOAPI(H5I_INVALID_HID) + FUNC_ENTER_NOAPI_NOERR + + /* Check the use disabled file locks environment variable */ + lock_env_var = HDgetenv(HDF5_USE_FILE_LOCKING); + if (lock_env_var && !HDstrcmp(lock_env_var, "BEST_EFFORT")) + ignore_disabled_file_locks_s = TRUE; /* Override: Ignore disabled locks */ + else if (lock_env_var && (!HDstrcmp(lock_env_var, "TRUE") || !HDstrcmp(lock_env_var, "1"))) + ignore_disabled_file_locks_s = FALSE; /* Override: Don't ignore disabled locks */ + else + ignore_disabled_file_locks_s = FAIL; /* Environment variable not set, or not set correctly */ if (H5I_VFL != H5I_get_type(H5FD_CORE_g)) H5FD_CORE_g = H5FD_register(&H5FD_core_g, sizeof(H5FD_class_t), FALSE); @@ -467,7 +483,6 @@ H5FD_core_init(void) /* Set return value */ ret_value = H5FD_CORE_g; -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD_core_init() */ @@ -528,7 +543,7 @@ H5Pset_core_write_tracking(hid_t plist_id, hbool_t is_enabled, size_t page_size) if (H5FD_CORE != H5P_peek_driver(plist)) HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "incorrect VFL driver") if (NULL == (old_fa = (const H5FD_core_fapl_t *)H5P_peek_driver_info(plist))) - HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "bad VFL driver info") + old_fa = H5FD__core_get_default_config(); /* Set VFD info values */ HDmemset(&fa, 0, sizeof(H5FD_core_fapl_t)); @@ -538,7 +553,7 @@ H5Pset_core_write_tracking(hid_t plist_id, hbool_t is_enabled, size_t page_size) fa.page_size = page_size; /* Set the property values & the driver for the FAPL */ - if (H5P_set_driver(plist, H5FD_CORE, &fa) < 0) + if (H5P_set_driver(plist, H5FD_CORE, &fa, NULL) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set core VFD as driver") done: @@ -622,7 +637,7 @@ H5Pset_fapl_core(hid_t fapl_id, size_t increment, hbool_t backing_store) fa.page_size = H5FD_CORE_WRITE_TRACKING_PAGE_SIZE; /* Set the property values & the driver for the FAPL */ - if (H5P_set_driver(plist, H5FD_CORE, &fa) < 0) + if (H5P_set_driver(plist, H5FD_CORE, &fa, NULL) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set core VFD as driver") done: @@ -747,7 +762,7 @@ H5FD__core_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr if (NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list") if (NULL == (fa = (const H5FD_core_fapl_t *)H5P_peek_driver_info(plist))) - HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, NULL, "bad VFL driver info") + fa = H5FD__core_get_default_config(); /* Build the open flags */ o_flags = (H5F_ACC_RDWR & flags) ? O_RDWR : O_RDONLY; @@ -918,8 +933,8 @@ H5FD__core_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr "file read failed: time = %s, filename = '%s', file descriptor = %d, errno = %d, " "error message = '%s', file->mem = %p, total read size = %llu, bytes this " "sub-read = %llu, bytes actually read = %llu, offset = %llu", - HDctime(&mytime), file->name, file->fd, myerrno, HDstrerror(myerrno), file->mem, - (unsigned long long)size, (unsigned long long)bytes_in, + HDctime(&mytime), file->name, file->fd, myerrno, HDstrerror(myerrno), + (void *)file->mem, (unsigned long long)size, (unsigned long long)bytes_in, (unsigned long long)bytes_read, (unsigned long long)offset); } /* end if */ @@ -1512,7 +1527,7 @@ done: * Addendum -- 12/2/11 * For file images opened with the core file driver, it is * necessary that we avoid reallocating the core file driver's - * buffer uneccessarily. + * buffer unnecessarily. * * To this end, I have made the following functional changes * to this function. @@ -1734,7 +1749,7 @@ H5FD__core_delete(const char *filename, hid_t fapl_id) if (NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") if (NULL == (fa = (const H5FD_core_fapl_t *)H5P_peek_driver_info(plist))) - HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "bad VFL driver info") + fa = H5FD__core_get_default_config(); if (fa->backing_store) if (HDremove(filename) < 0) diff --git a/src/H5FDcore.h b/src/H5FDcore.h index d456c3e..4067980 100644 --- a/src/H5FDcore.h +++ b/src/H5FDcore.h @@ -20,7 +20,8 @@ #ifndef H5FDcore_H #define H5FDcore_H -#define H5FD_CORE (H5FD_core_init()) +#define H5FD_CORE (H5FDperform_init(H5FD_core_init)) +#define H5FD_CORE_VALUE H5_VFD_CORE #ifdef __cplusplus extern "C" { diff --git a/src/H5FDdevelop.h b/src/H5FDdevelop.h index 57f0a42..f5b32ed 100644 --- a/src/H5FDdevelop.h +++ b/src/H5FDdevelop.h @@ -25,6 +25,9 @@ /* Public Macros */ /*****************/ +/* H5FD_class_t struct version */ +#define H5FD_CLASS_VERSION 0x01 /* File driver struct version */ + /* Map "fractal heap" header blocks to 'ohdr' type file memory, since its * a fair amount of work to add a new kind of file memory and they are similar * enough to object headers and probably too minor to deserve their own type. @@ -160,6 +163,8 @@ typedef struct H5FD_t H5FD_t; /* Class information for each file driver */ typedef struct H5FD_class_t { + unsigned version; /**< File driver class struct version # */ + H5FD_class_value_t value; const char * name; haddr_t maxaddr; H5F_close_degree_t fc_degree; @@ -187,11 +192,22 @@ typedef struct H5FD_class_t { herr_t (*get_handle)(H5FD_t *file, hid_t fapl, void **file_handle); herr_t (*read)(H5FD_t *file, H5FD_mem_t type, hid_t dxpl, haddr_t addr, size_t size, void *buffer); herr_t (*write)(H5FD_t *file, H5FD_mem_t type, hid_t dxpl, haddr_t addr, size_t size, const void *buffer); + herr_t (*read_vector)(H5FD_t *file, hid_t dxpl, uint32_t count, H5FD_mem_t types[], haddr_t addrs[], + size_t sizes[], void *bufs[]); + herr_t (*write_vector)(H5FD_t *file, hid_t dxpl, uint32_t count, H5FD_mem_t types[], haddr_t addrs[], + size_t sizes[], const void *bufs[]); + herr_t (*read_selection)(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, size_t count, hid_t mem_spaces[], + hid_t file_spaces[], haddr_t offsets[], size_t element_sizes[], + void *bufs[] /*out*/); + herr_t (*write_selection)(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, size_t count, hid_t mem_spaces[], + hid_t file_spaces[], haddr_t offsets[], size_t element_sizes[], + const void *bufs[] /*in*/); herr_t (*flush)(H5FD_t *file, hid_t dxpl_id, hbool_t closing); herr_t (*truncate)(H5FD_t *file, hid_t dxpl_id, hbool_t closing); herr_t (*lock)(H5FD_t *file, hbool_t rw); herr_t (*unlock)(H5FD_t *file); herr_t (*del)(const char *name, hid_t fapl); + herr_t (*ctl)(H5FD_t *file, uint64_t op_code, uint64_t flags, const void *input, void **output); H5FD_mem_t fl_map[H5FD_MEM_NTYPES]; } H5FD_class_t; @@ -221,6 +237,9 @@ struct H5FD_t { hbool_t paged_aggr; /* Paged aggregation for file space is enabled or not */ }; +/* VFD initialization function */ +typedef hid_t (*H5FD_init_t)(void); + /********************/ /* Public Variables */ /********************/ @@ -233,7 +252,10 @@ struct H5FD_t { extern "C" { #endif +H5_DLL hid_t H5FDperform_init(H5FD_init_t op); H5_DLL hid_t H5FDregister(const H5FD_class_t *cls); +H5_DLL htri_t H5FDis_driver_registered_by_name(const char *driver_name); +H5_DLL htri_t H5FDis_driver_registered_by_value(H5FD_class_value_t driver_value); H5_DLL herr_t H5FDunregister(hid_t driver_id); H5_DLL H5FD_t *H5FDopen(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr); H5_DLL herr_t H5FDclose(H5FD_t *file); @@ -249,11 +271,22 @@ H5_DLL herr_t H5FDread(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t ad void *buf /*out*/); H5_DLL herr_t H5FDwrite(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size, const void *buf); +H5_DLL herr_t H5FDread_vector(H5FD_t *file, hid_t dxpl_id, uint32_t count, H5FD_mem_t types[], + haddr_t addrs[], size_t sizes[], void *bufs[] /* out */); +H5_DLL herr_t H5FDwrite_vector(H5FD_t *file, hid_t dxpl_id, uint32_t count, H5FD_mem_t types[], + haddr_t addrs[], size_t sizes[], const void *bufs[] /* in */); +H5_DLL herr_t H5FDread_selection(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, uint32_t count, + hid_t mem_spaces[], hid_t file_spaces[], haddr_t offsets[], + size_t element_sizes[], void *bufs[] /* out */); +H5_DLL herr_t H5FDwrite_selection(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, uint32_t count, + hid_t mem_spaces[], hid_t file_spaces[], haddr_t offsets[], + size_t element_sizes[], const void *bufs[]); H5_DLL herr_t H5FDflush(H5FD_t *file, hid_t dxpl_id, hbool_t closing); H5_DLL herr_t H5FDtruncate(H5FD_t *file, hid_t dxpl_id, hbool_t closing); H5_DLL herr_t H5FDlock(H5FD_t *file, hbool_t rw); H5_DLL herr_t H5FDunlock(H5FD_t *file); H5_DLL herr_t H5FDdelete(const char *name, hid_t fapl_id); +H5_DLL herr_t H5FDctl(H5FD_t *file, uint64_t op_code, uint64_t flags, const void *input, void **output); #ifdef __cplusplus } diff --git a/src/H5FDdirect.c b/src/H5FDdirect.c index a1b7b7e..25ee970 100644 --- a/src/H5FDdirect.c +++ b/src/H5FDdirect.c @@ -120,6 +120,8 @@ typedef struct H5FD_direct_t { /* Prototypes */ static herr_t H5FD__direct_term(void); +static herr_t H5FD__direct_populate_config(size_t boundary, size_t block_size, size_t cbuf_size, + H5FD_direct_fapl_t *fa_out); static void * H5FD__direct_fapl_get(H5FD_t *file); static void * H5FD__direct_fapl_copy(const void *_old_fa); static H5FD_t *H5FD__direct_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr); @@ -140,6 +142,8 @@ static herr_t H5FD__direct_unlock(H5FD_t *_file); static herr_t H5FD__direct_delete(const char *filename, hid_t fapl_id); static const H5FD_class_t H5FD_direct_g = { + H5FD_CLASS_VERSION, /* struct version */ + H5FD_DIRECT_VALUE, /* value */ "direct", /* name */ MAXADDR, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -167,53 +171,22 @@ static const H5FD_class_t H5FD_direct_g = { H5FD__direct_get_handle, /* get_handle */ H5FD__direct_read, /* read */ H5FD__direct_write, /* write */ + NULL, /* read_vector */ + NULL, /* write_vector */ + NULL, /* read_selection */ + NULL, /* write_selection */ NULL, /* flush */ H5FD__direct_truncate, /* truncate */ H5FD__direct_lock, /* lock */ H5FD__direct_unlock, /* unlock */ H5FD__direct_delete, /* del */ + NULL, /* ctl */ H5FD_FLMAP_DICHOTOMY /* fl_map */ }; /* Declare a free list to manage the H5FD_direct_t struct */ H5FL_DEFINE_STATIC(H5FD_direct_t); -/*-------------------------------------------------------------------------- -NAME - H5FD__init_package -- Initialize interface-specific information -USAGE - herr_t H5FD__init_package() -RETURNS - Non-negative on success/Negative on failure -DESCRIPTION - Initializes any interface-specific data or routines. (Just calls - H5FD_direct_init currently). - ---------------------------------------------------------------------------*/ -static herr_t -H5FD__init_package(void) -{ - char * lock_env_var = NULL; /* Environment variable pointer */ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_STATIC - - /* Check the use disabled file locks environment variable */ - lock_env_var = HDgetenv("HDF5_USE_FILE_LOCKING"); - if (lock_env_var && !HDstrcmp(lock_env_var, "BEST_EFFORT")) - ignore_disabled_file_locks_s = TRUE; /* Override: Ignore disabled locks */ - else if (lock_env_var && (!HDstrcmp(lock_env_var, "TRUE") || !HDstrcmp(lock_env_var, "1"))) - ignore_disabled_file_locks_s = FALSE; /* Override: Don't ignore disabled locks */ - else - ignore_disabled_file_locks_s = FAIL; /* Environment variable not set, or not set correctly */ - - if (H5FD_direct_init() < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "unable to initialize direct VFD") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5FD__init_package() */ - /*------------------------------------------------------------------------- * Function: H5FD_direct_init * @@ -231,12 +204,25 @@ done: hid_t H5FD_direct_init(void) { - hid_t ret_value = H5I_INVALID_HID; /* Return value */ + char *lock_env_var = NULL; /* Environment variable pointer */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ FUNC_ENTER_NOAPI(H5I_INVALID_HID) - if (H5I_VFL != H5I_get_type(H5FD_DIRECT_g)) + /* Check the use disabled file locks environment variable */ + lock_env_var = HDgetenv(HDF5_USE_FILE_LOCKING); + if (lock_env_var && !HDstrcmp(lock_env_var, "BEST_EFFORT")) + ignore_disabled_file_locks_s = TRUE; /* Override: Ignore disabled locks */ + else if (lock_env_var && (!HDstrcmp(lock_env_var, "TRUE") || !HDstrcmp(lock_env_var, "1"))) + ignore_disabled_file_locks_s = FALSE; /* Override: Don't ignore disabled locks */ + else + ignore_disabled_file_locks_s = FAIL; /* Environment variable not set, or not set correctly */ + + if (H5I_VFL != H5I_get_type(H5FD_DIRECT_g)) { H5FD_DIRECT_g = H5FD_register(&H5FD_direct_g, sizeof(H5FD_class_t), FALSE); + if (H5I_INVALID_HID == H5FD_DIRECT_g) + HGOTO_ERROR(H5E_ID, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register direct"); + } /* Set return value */ ret_value = H5FD_DIRECT_g; @@ -295,28 +281,10 @@ H5Pset_fapl_direct(hid_t fapl_id, size_t boundary, size_t block_size, size_t cbu if (NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") - HDmemset(&fa, 0, sizeof(H5FD_direct_fapl_t)); - if (boundary != 0) - fa.mboundary = boundary; - else - fa.mboundary = MBOUNDARY_DEF; - if (block_size != 0) - fa.fbsize = block_size; - else - fa.fbsize = FBSIZE_DEF; - if (cbuf_size != 0) - fa.cbsize = cbuf_size; - else - fa.cbsize = CBSIZE_DEF; - - /* Set the default to be true for data alignment */ - fa.must_align = TRUE; - - /* Copy buffer size must be a multiple of file block size */ - if (fa.cbsize % fa.fbsize != 0) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "copy buffer size must be a multiple of block size") + if (H5FD__direct_populate_config(boundary, block_size, cbuf_size, &fa) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't initialize driver configuration info") - ret_value = H5P_set_driver(plist, H5FD_DIRECT, &fa); + ret_value = H5P_set_driver(plist, H5FD_DIRECT, &fa, NULL); done: FUNC_LEAVE_API(ret_value) @@ -366,6 +334,53 @@ done: } /* end H5Pget_fapl_direct() */ /*------------------------------------------------------------------------- + * Function: H5FD__direct_populate_config + * + * Purpose: Populates a H5FD_direct_fapl_t structure with the provided + * values, supplying defaults where values are not provided. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD__direct_populate_config(size_t boundary, size_t block_size, size_t cbuf_size, H5FD_direct_fapl_t *fa_out) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC + + HDassert(fa_out); + + HDmemset(fa_out, 0, sizeof(H5FD_direct_fapl_t)); + + if (boundary != 0) + fa_out->mboundary = boundary; + else + fa_out->mboundary = MBOUNDARY_DEF; + + if (block_size != 0) + fa_out->fbsize = block_size; + else + fa_out->fbsize = FBSIZE_DEF; + + if (cbuf_size != 0) + fa_out->cbsize = cbuf_size; + else + fa_out->cbsize = CBSIZE_DEF; + + /* Set the default to be true for data alignment */ + fa_out->must_align = TRUE; + + /* Copy buffer size must be a multiple of file block size */ + if (fa_out->cbsize % fa_out->fbsize != 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "copy buffer size must be a multiple of block size") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD__direct_populate_config() */ + +/*------------------------------------------------------------------------- * Function: H5FD__direct_fapl_get * * Purpose: Returns a file access property list which indicates how the @@ -449,6 +464,7 @@ H5FD__direct_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxad int fd = (-1); H5FD_direct_t * file = NULL; const H5FD_direct_fapl_t *fa; + H5FD_direct_fapl_t default_fa; #ifdef H5_HAVE_WIN32_API HFILE filehandle; struct _BY_HANDLE_FILE_INFORMATION fileinfo; @@ -497,8 +513,11 @@ H5FD__direct_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxad /* Get the driver specific information */ if (NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list") - if (NULL == (fa = (const H5FD_direct_fapl_t *)H5P_peek_driver_info(plist))) - HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, NULL, "bad VFL driver info") + if (NULL == (fa = (const H5FD_direct_fapl_t *)H5P_peek_driver_info(plist))) { + if (H5FD__direct_populate_config(0, 0, 0, &default_fa) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, NULL, "can't initialize driver configuration info") + fa = &default_fa; + } file->fd = fd; H5_CHECKED_ASSIGN(file->eof, haddr_t, sb.st_size, h5_stat_size_t); diff --git a/src/H5FDdirect.h b/src/H5FDdirect.h index f06de7f..bfad16a 100644 --- a/src/H5FDdirect.h +++ b/src/H5FDdirect.h @@ -21,9 +21,11 @@ #define H5FDdirect_H #ifdef H5_HAVE_DIRECT -#define H5FD_DIRECT (H5FD_direct_init()) +#define H5FD_DIRECT (H5FDperform_init(H5FD_direct_init)) +#define H5FD_DIRECT_VALUE H5_VFD_DIRECT #else -#define H5FD_DIRECT (H5I_INVALID_HID) +#define H5FD_DIRECT (H5I_INVALID_HID) +#define H5FD_DIRECT_VALUE H5_VFD_INVALID #endif /* H5_HAVE_DIRECT */ #ifdef H5_HAVE_DIRECT diff --git a/src/H5FDfamily.c b/src/H5FDfamily.c index 8cf9f9e..66a1a68 100644 --- a/src/H5FDfamily.c +++ b/src/H5FDfamily.c @@ -47,6 +47,9 @@ /* The size of the member name buffers */ #define H5FD_FAM_MEMB_NAME_BUF_SIZE 4096 +/* Default member size - 100 MiB */ +#define H5FD_FAM_DEF_MEM_SIZE ((hsize_t)(100 * H5_MB)) + /* The driver identification number, initialized at runtime */ static hid_t H5FD_FAMILY_g = 0; @@ -77,6 +80,10 @@ typedef struct H5FD_family_fapl_t { hid_t memb_fapl_id; /*file access property list of each memb*/ } H5FD_family_fapl_t; +/* Private routines */ +static herr_t H5FD__family_get_default_config(H5FD_family_fapl_t *fa_out); +static char * H5FD__family_get_default_printf_filename(const char *old_filename); + /* Callback prototypes */ static herr_t H5FD__family_term(void); static void * H5FD__family_fapl_get(H5FD_t *_file); @@ -105,6 +112,8 @@ static herr_t H5FD__family_delete(const char *filename, hid_t fapl_id); /* The class struct */ static const H5FD_class_t H5FD_family_g = { + H5FD_CLASS_VERSION, /* struct version */ + H5FD_FAMILY_VALUE, /* value */ "family", /* name */ HADDR_MAX, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -132,39 +141,134 @@ static const H5FD_class_t H5FD_family_g = { H5FD__family_get_handle, /* get_handle */ H5FD__family_read, /* read */ H5FD__family_write, /* write */ + NULL, /* read_vector */ + NULL, /* write_vector */ + NULL, /* read_selection */ + NULL, /* write_selection */ H5FD__family_flush, /* flush */ H5FD__family_truncate, /* truncate */ H5FD__family_lock, /* lock */ H5FD__family_unlock, /* unlock */ H5FD__family_delete, /* del */ + NULL, /* ctl */ H5FD_FLMAP_DICHOTOMY /* fl_map */ }; -/*-------------------------------------------------------------------------- -NAME - H5FD__init_package -- Initialize interface-specific information -USAGE - herr_t H5FD__init_package() -RETURNS - Non-negative on success/Negative on failure -DESCRIPTION - Initializes any interface-specific data or routines. (Just calls - H5FD_family_init currently). - ---------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------- + * Function: H5FD__family_get_default_config + * + * Purpose: Populates a H5FD_family_fapl_t structure with default + * values. + * + * Return: Non-negative on Success/Negative on Failure + * + *------------------------------------------------------------------------- + */ static herr_t -H5FD__init_package(void) +H5FD__family_get_default_config(H5FD_family_fapl_t *fa_out) +{ + H5P_genplist_t *def_plist; + H5P_genplist_t *plist; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC + + HDassert(fa_out); + + fa_out->memb_size = H5FD_FAM_DEF_MEM_SIZE; + + /* Use copy of default file access property list for member FAPL ID. + * The Sec2 driver is explicitly set on the member FAPL ID, as the + * default driver might have been replaced with the Family VFD, which + * would cause recursion badness in the child members. + */ + if (NULL == (def_plist = (H5P_genplist_t *)H5I_object(H5P_FILE_ACCESS_DEFAULT))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") + if ((fa_out->memb_fapl_id = H5P_copy_plist(def_plist, FALSE)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTCOPY, FAIL, "can't copy property list") + if (NULL == (plist = (H5P_genplist_t *)H5I_object(fa_out->memb_fapl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") + if (H5P_set_driver_by_value(plist, H5_VFD_SEC2, NULL, TRUE) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't set default driver on member FAPL") + +done: + if (ret_value < 0 && fa_out->memb_fapl_id >= 0) { + if (H5I_dec_ref(fa_out->memb_fapl_id) < 0) + HDONE_ERROR(H5E_VFL, H5E_CANTDEC, FAIL, "can't decrement ref. count on member FAPL ID") + } + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD__family_get_default_config() */ + +/*------------------------------------------------------------------------- + * Function: H5FD__family_get_default_printf_filename + * + * Purpose: Given a filename, allocates and returns a new filename + * buffer that contains the given filename modified into this + * VFD's printf-style format. For example, the filename + * "file1.h5" would be modified to "file1-%06d.h5". This would + * allow for member filenames such as "file1-000000.h5", + * "file1-000001.h5", etc. The caller is responsible for + * freeing the returned buffer. + * + * Return: Non-negative on Success/Negative on Failure + * + *------------------------------------------------------------------------- + */ +static char * +H5FD__family_get_default_printf_filename(const char *old_filename) { - herr_t ret_value = SUCCEED; + const char *suffix = "-%06d"; + size_t old_filename_len = 0; + size_t new_filename_len = 0; + char * file_extension = NULL; + char * tmp_buffer = NULL; + char * ret_value = NULL; FUNC_ENTER_STATIC - if (H5FD_family_init() < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "unable to initialize family VFD") + HDassert(old_filename); + + old_filename_len = HDstrlen(old_filename); + if (0 == old_filename_len) + HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, NULL, "invalid filename") + + new_filename_len = old_filename_len + HDstrlen(suffix) + 1; + if (NULL == (tmp_buffer = H5MM_malloc(new_filename_len))) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, NULL, "can't allocate new filename buffer") + + /* Determine if filename contains a ".h5" extension. */ + if ((file_extension = HDstrstr(old_filename, ".h5"))) { + /* Insert the printf format between the filename and ".h5" extension. */ + HDstrcpy(tmp_buffer, old_filename); + file_extension = HDstrstr(tmp_buffer, ".h5"); + HDsprintf(file_extension, "%s%s", suffix, ".h5"); + } + else if ((file_extension = HDstrrchr(old_filename, '.'))) { + char *new_extension_loc = NULL; + + /* If the filename doesn't contain a ".h5" extension, but contains + * AN extension, just insert the printf format before that extension. + */ + HDstrcpy(tmp_buffer, old_filename); + new_extension_loc = HDstrrchr(tmp_buffer, '.'); + HDsprintf(new_extension_loc, "%s%s", suffix, file_extension); + } + else { + /* If the filename doesn't contain an extension at all, just insert + * the printf format at the end of the filename. + */ + HDsnprintf(tmp_buffer, new_filename_len, "%s%s", old_filename, suffix); + } + + ret_value = tmp_buffer; done: + if (!ret_value) + H5MM_xfree(tmp_buffer); + FUNC_LEAVE_NOAPI(ret_value) -} /* H5FD__init_package() */ +} /* end H5FD__family_get_default_printf_filename() */ /*------------------------------------------------------------------------- * Function: H5FD_family_init @@ -183,9 +287,9 @@ done: hid_t H5FD_family_init(void) { - hid_t ret_value = H5I_INVALID_HID; /* Return value */ + hid_t ret_value = H5I_INVALID_HID; - FUNC_ENTER_NOAPI(H5I_INVALID_HID) + FUNC_ENTER_NOAPI_NOERR if (H5I_VFL != H5I_get_type(H5FD_FAMILY_g)) H5FD_FAMILY_g = H5FD_register(&H5FD_family_g, sizeof(H5FD_class_t), FALSE); @@ -193,7 +297,6 @@ H5FD_family_init(void) /* Set return value */ ret_value = H5FD_FAMILY_g; -done: FUNC_LEAVE_NOAPI(ret_value) } /* H5FD_family_init() */ @@ -242,7 +345,7 @@ herr_t H5Pset_fapl_family(hid_t fapl_id, hsize_t msize, hid_t memb_fapl_id) { herr_t ret_value; - H5FD_family_fapl_t fa = {0, -1}; + H5FD_family_fapl_t fa = {0, H5I_INVALID_HID}; H5P_genplist_t * plist; /* Property list pointer */ FUNC_ENTER_API(FAIL) @@ -251,18 +354,22 @@ H5Pset_fapl_family(hid_t fapl_id, hsize_t msize, hid_t memb_fapl_id) /* Check arguments */ if (TRUE != H5P_isa_class(fapl_id, H5P_FILE_ACCESS)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") - if (H5P_DEFAULT == memb_fapl_id) - memb_fapl_id = H5P_FILE_ACCESS_DEFAULT; + if (H5P_DEFAULT == memb_fapl_id) { + /* Get default configuration for member FAPL */ + if (H5FD__family_get_default_config(&fa) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't get default driver configuration info") + } else if (TRUE != H5P_isa_class(memb_fapl_id, H5P_FILE_ACCESS)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access list") /* Initialize driver specific information. */ - fa.memb_size = msize; - fa.memb_fapl_id = memb_fapl_id; + fa.memb_size = msize; + if (H5P_DEFAULT != memb_fapl_id) + fa.memb_fapl_id = memb_fapl_id; if (NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") - ret_value = H5P_set_driver(plist, H5FD_FAMILY, &fa); + ret_value = H5P_set_driver(plist, H5FD_FAMILY, &fa, NULL); done: FUNC_LEAVE_API(ret_value) @@ -588,9 +695,10 @@ H5FD__family_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxad { H5FD_family_t *file = NULL; char * memb_name = NULL, *temp = NULL; - hsize_t eof = HADDR_UNDEF; - unsigned t_flags = flags & ~H5F_ACC_CREAT; - H5FD_t * ret_value = NULL; + hsize_t eof = HADDR_UNDEF; + hbool_t default_config = FALSE; + unsigned t_flags = flags & ~H5F_ACC_CREAT; + H5FD_t * ret_value = NULL; FUNC_ENTER_STATIC @@ -604,21 +712,32 @@ H5FD__family_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxad if (NULL == (file = (H5FD_family_t *)H5MM_calloc(sizeof(H5FD_family_t)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate file struct") if (H5P_FILE_ACCESS_DEFAULT == fapl_id) { - file->memb_fapl_id = H5P_FILE_ACCESS_DEFAULT; - if (H5I_inc_ref(file->memb_fapl_id, FALSE) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTINC, NULL, "unable to increment ref count on VFL driver") - file->memb_size = 1024 * 1024 * 1024; /*1GB. Actual member size to be updated later */ - file->pmem_size = 1024 * 1024 * 1024; /*1GB. Member size passed in through property */ - file->mem_newsize = 0; /*New member size used by h5repart only */ - } /* end if */ + H5FD_family_fapl_t default_fa; + + /* Get default configuration */ + if (H5FD__family_get_default_config(&default_fa) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "can't get default driver configuration info") + + file->memb_fapl_id = default_fa.memb_fapl_id; + file->memb_size = H5FD_FAM_DEF_MEM_SIZE; /* Actual member size to be updated later */ + file->pmem_size = H5FD_FAM_DEF_MEM_SIZE; /* Member size passed in through property */ + file->mem_newsize = 0; /*New member size used by h5repart only */ + + default_config = TRUE; + } /* end if */ else { H5P_genplist_t * plist; /* Property list pointer */ const H5FD_family_fapl_t *fa; + H5FD_family_fapl_t default_fa; if (NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list") - if (NULL == (fa = (const H5FD_family_fapl_t *)H5P_peek_driver_info(plist))) - HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, NULL, "bad VFL driver info") + if (NULL == (fa = (const H5FD_family_fapl_t *)H5P_peek_driver_info(plist))) { + if (H5FD__family_get_default_config(&default_fa) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "can't get default family VFD configuration") + fa = &default_fa; + default_config = TRUE; + } /* Check for new family file size. It's used by h5repart only. */ if (H5P_exist_plist(plist, H5F_ACS_FAMILY_NEWSIZE_NAME) > 0) { @@ -642,7 +761,10 @@ H5FD__family_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxad } /* end else */ file->memb_size = fa->memb_size; /* Actual member size to be updated later */ file->pmem_size = fa->memb_size; /* Member size passed in through property */ - } /* end else */ + + if (default_config && H5I_dec_ref(fa->memb_fapl_id) < 0) + HGOTO_ERROR(H5E_ID, H5E_CANTDEC, NULL, "can't decrement ref. count on member FAPL") + } /* end else */ file->name = H5MM_strdup(name); file->flags = flags; @@ -655,8 +777,16 @@ H5FD__family_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxad /* Check that names are unique */ HDsnprintf(memb_name, H5FD_FAM_MEMB_NAME_BUF_SIZE, name, 0); HDsnprintf(temp, H5FD_FAM_MEMB_NAME_BUF_SIZE, name, 1); - if (!HDstrcmp(memb_name, temp)) - HGOTO_ERROR(H5E_FILE, H5E_FILEEXISTS, NULL, "file names not unique") + if (!HDstrcmp(memb_name, temp)) { + if (default_config) { + temp = H5MM_xfree(temp); + if (NULL == (temp = H5FD__family_get_default_printf_filename(name))) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "can't get default printf-style filename") + name = temp; + } + else + HGOTO_ERROR(H5E_FILE, H5E_FILEEXISTS, NULL, "file names not unique") + } /* Open all the family members */ while (1) { @@ -1360,7 +1490,9 @@ H5FD__family_delete(const char *filename, hid_t fapl_id) { H5P_genplist_t * plist; const H5FD_family_fapl_t *fa; - hid_t memb_fapl_id = H5I_INVALID_HID; + H5FD_family_fapl_t default_fa = {0, H5I_INVALID_HID}; + hbool_t default_config = FALSE; + hid_t memb_fapl_id = H5I_INVALID_HID; unsigned current_member; char * member_name = NULL; char * temp = NULL; @@ -1374,13 +1506,21 @@ H5FD__family_delete(const char *filename, hid_t fapl_id) /* Get the driver info (for the member fapl) * The family_open call accepts H5P_DEFAULT, so we'll accept that here, too. */ - if (H5P_FILE_ACCESS_DEFAULT == fapl_id) - memb_fapl_id = H5P_FILE_ACCESS_DEFAULT; + if (H5P_FILE_ACCESS_DEFAULT == fapl_id) { + if (H5FD__family_get_default_config(&default_fa) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't get default family VFD configuration") + memb_fapl_id = default_fa.memb_fapl_id; + default_config = TRUE; + } else { if (NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") - if (NULL == (fa = (const H5FD_family_fapl_t *)H5P_peek_driver_info(plist))) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bad family VFD driver info") + if (NULL == (fa = (const H5FD_family_fapl_t *)H5P_peek_driver_info(plist))) { + if (H5FD__family_get_default_config(&default_fa) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't get default family VFD configuration") + fa = &default_fa; + default_config = TRUE; + } memb_fapl_id = fa->memb_fapl_id; } @@ -1393,8 +1533,17 @@ H5FD__family_delete(const char *filename, hid_t fapl_id) /* Sanity check to make sure that generated names are unique */ HDsnprintf(member_name, H5FD_FAM_MEMB_NAME_BUF_SIZE, filename, 0); HDsnprintf(temp, H5FD_FAM_MEMB_NAME_BUF_SIZE, filename, 1); - if (!HDstrcmp(member_name, temp)) - HGOTO_ERROR(H5E_VFL, H5E_CANTDELETEFILE, FAIL, "provided file name cannot generate unique sub-files") + if (!HDstrcmp(member_name, temp)) { + if (default_config) { + temp = H5MM_xfree(temp); + if (NULL == (temp = H5FD__family_get_default_printf_filename(filename))) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't get default printf-style filename") + filename = temp; + } + else + HGOTO_ERROR(H5E_VFL, H5E_CANTDELETEFILE, FAIL, + "provided file name cannot generate unique sub-files") + } /* Delete all the family members */ current_member = 0; @@ -1430,9 +1579,9 @@ done: if (temp) H5MM_xfree(temp); - /* Don't close memb_fapl_id - We didn't bump its reference count since we're - * only using it in this call. - */ + /* Only close memb_fapl_id if we created one from the default configuration */ + if (default_fa.memb_fapl_id >= 0 && H5I_dec_ref(default_fa.memb_fapl_id) < 0) + HDONE_ERROR(H5E_VFL, H5E_CANTDEC, FAIL, "can't decrement ref. count on member FAPL ID") FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD__family_delete() */ diff --git a/src/H5FDfamily.h b/src/H5FDfamily.h index 20ef532..bd51f36 100644 --- a/src/H5FDfamily.h +++ b/src/H5FDfamily.h @@ -20,7 +20,8 @@ #ifndef H5FDfamily_H #define H5FDfamily_H -#define H5FD_FAMILY (H5FD_family_init()) +#define H5FD_FAMILY (H5FDperform_init(H5FD_family_init)) +#define H5FD_FAMILY_VALUE H5_VFD_FAMILY #ifdef __cplusplus extern "C" { diff --git a/src/H5FDhdfs.c b/src/H5FDhdfs.c index 2c4bff6..f0ffb62 100644 --- a/src/H5FDhdfs.c +++ b/src/H5FDhdfs.c @@ -278,6 +278,8 @@ static herr_t H5FD__hdfs_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing static herr_t H5FD__hdfs_validate_config(const H5FD_hdfs_fapl_t *fa); static const H5FD_class_t H5FD_hdfs_g = { + H5FD_CLASS_VERSION, /* struct version */ + H5FD_HDFS_VALUE, /* value */ "hdfs", /* name */ MAXADDR, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -305,11 +307,16 @@ static const H5FD_class_t H5FD_hdfs_g = { H5FD__hdfs_get_handle, /* get_handle */ H5FD__hdfs_read, /* read */ H5FD__hdfs_write, /* write */ + NULL, /* read_vector */ + NULL, /* write_vector */ + NULL, /* read_selection */ + NULL, /* write_selection */ NULL, /* flush */ H5FD__hdfs_truncate, /* truncate */ NULL, /* lock */ NULL, /* unlock */ NULL, /* del */ + NULL, /* ctl */ H5FD_FLMAP_DICHOTOMY /* fl_map */ }; @@ -317,29 +324,6 @@ static const H5FD_class_t H5FD_hdfs_g = { H5FL_DEFINE_STATIC(H5FD_hdfs_t); /*------------------------------------------------------------------------- - * Function: H5FD__init_package - * - * Purpose: Initializes any interface-specific data or routines. - * - * Return: Non-negative on success/Negative on failure - * - *------------------------------------------------------------------------- - */ -static herr_t -H5FD__init_package(void) -{ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_STATIC - - if (H5FD_hdfs_init() < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "unable to initialize hdfs VFD") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5FD__init_package() */ - -/*------------------------------------------------------------------------- * Function: H5FD_hdfs_init * * Purpose: Initialize this driver by registering the driver with the @@ -551,16 +535,16 @@ done: * Function: H5FD__hdfs_validate_config() * * Purpose: Test to see if the supplied instance of H5FD_hdfs_fapl_t - * contains internally consistant data. Return SUCCEED if so, + * contains internally consistent data. Return SUCCEED if so, * and FAIL otherwise. * - * Note the difference between internally consistant and + * Note the difference between internally consistent and * correct. As we will have to try to access the target * object to determine whether the supplied data is correct, - * we will settle for internal consistancy at this point + * we will settle for internal consistency at this point * * Return: SUCCEED if instance of H5FD_hdfs_fapl_t contains internally - * consistant data, FAIL otherwise. + * consistent data, FAIL otherwise. * * Programmer: Jacob Smith * 9/10/17 @@ -623,7 +607,7 @@ H5Pset_fapl_hdfs(hid_t fapl_id, H5FD_hdfs_fapl_t *fa) if (FAIL == H5FD__hdfs_validate_config(fa)) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid hdfs config") - ret_value = H5P_set_driver(plist, H5FD_HDFS, (void *)fa); + ret_value = H5P_set_driver(plist, H5FD_HDFS, (void *)fa, NULL); done: FUNC_LEAVE_API(ret_value) diff --git a/src/H5FDhdfs.h b/src/H5FDhdfs.h index 7c871a4..e401e81 100644 --- a/src/H5FDhdfs.h +++ b/src/H5FDhdfs.h @@ -22,9 +22,11 @@ #define H5FDhdfs_H #ifdef H5_HAVE_LIBHDFS -#define H5FD_HDFS (H5FD_hdfs_init()) +#define H5FD_HDFS (H5FDperform_init(H5FD_hdfs_init)) +#define H5FD_HDFS_VALUE H5_VFD_HDFS #else /* H5_HAVE_LIBHDFS */ -#define H5FD_HDFS (H5I_INVALID_HID) +#define H5FD_HDFS (H5I_INVALID_HID) +#define H5FD_HDFS_VALUE H5_VFD_INVALID #endif /* H5_HAVE_LIBHDFS */ #ifdef H5_HAVE_LIBHDFS diff --git a/src/H5FDint.c b/src/H5FDint.c index f13f222..0c3fe9e 100644 --- a/src/H5FDint.c +++ b/src/H5FDint.c @@ -34,16 +34,73 @@ #include "H5Eprivate.h" /* Error handling */ #include "H5Fprivate.h" /* File access */ #include "H5FDpkg.h" /* File Drivers */ +#include "H5FLprivate.h" /* Free Lists */ #include "H5Iprivate.h" /* IDs */ +#include "H5PLprivate.h" /* Plugins */ /****************/ /* Local Macros */ /****************/ +/* Length of sequence lists requested from dataspace selections */ +#define H5FD_SEQ_LIST_LEN 128 + +/* Length of stack allocated arrays for building vector I/O operations. + * Corresponds to the number of contiguous blocks in a selection I/O operation. + * If more space is needed dynamic allocation will be used instead. */ +#define H5FD_LOCAL_VECTOR_LEN 8 + +/* Length of stack allocated arrays for dataspace IDs/structs for selection I/O + * operations. Corresponds to the number of file selection/memory selection + * pairs (along with addresses, etc.) in a selection I/O operation. If more + * space is needed dynamic allocation will be used instead */ +#define H5FD_LOCAL_SEL_ARR_LEN 8 + /******************/ /* Local Typedefs */ /******************/ +/************************************************************************* + * + * H5FD_vsrt_tmp_t + * + * Structure used to store vector I/O request addresses and the associated + * indexes in the addrs[] array for the purpose of determine the sorted + * order. + * + * This is done by allocating an array of H5FD_vsrt_tmp_t of length + * count, loading it with the contents of the addrs[] array and the + * associated indices, and then sorting it. + * + * This sorted array of H5FD_vsrt_tmp_t is then used to populate sorted + * versions of the types[], addrs[], sizes[] and bufs[] vectors. + * + * addr: haddr_t containing the value of addrs[i], + * + * index: integer containing the value of i used to obtain the + * value of the addr field from the addrs[] vector. + * + *************************************************************************/ + +typedef struct H5FD_vsrt_tmp_t { + haddr_t addr; + int index; +} H5FD_vsrt_tmp_t; + +/* Information needed for iterating over the registered VFD hid_t IDs. + * The name or value of the new VFD that is being registered is stored + * in the name (or value) field and the found_id field is initialized to + * H5I_INVALID_HID (-1). If we find a VFD with the same name / value, + * we set the found_id field to the existing ID for return to the function. + */ +typedef struct H5FD_get_driver_ud_t { + /* IN */ + H5PL_vfd_key_t key; + + /* OUT */ + hid_t found_id; /* The driver ID, if we found a match */ +} H5FD_get_driver_ud_t; + /********************/ /* Package Typedefs */ /********************/ @@ -51,6 +108,13 @@ /********************/ /* Local Prototypes */ /********************/ +static int H5FD__get_driver_cb(void *obj, hid_t id, void *_op_data); +static herr_t H5FD__read_selection_translate(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, uint32_t count, + H5S_t **mem_spaces, H5S_t **file_spaces, haddr_t offsets[], + size_t element_sizes[], void *bufs[] /* out */); +static herr_t H5FD__write_selection_translate(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, uint32_t count, + H5S_t **mem_spaces, H5S_t **file_spaces, haddr_t offsets[], + size_t element_sizes[], const void *bufs[]); /*********************/ /* Package Variables */ @@ -64,6 +128,9 @@ /* Local Variables */ /*******************/ +/* Declare extern free list to manage the H5S_sel_iter_t struct */ +H5FL_EXTERN(H5S_sel_iter_t); + /*------------------------------------------------------------------------- * Function: H5FD_locate_signature * @@ -244,6 +311,1689 @@ done: } /* end H5FD_write() */ /*------------------------------------------------------------------------- + * Function: H5FD_read_vector + * + * Purpose: Private version of H5FDread_vector() + * + * Perform count reads from the specified file at the offsets + * provided in the addrs array, with the lengths and memory + * types provided in the sizes and types arrays. Data read + * is returned in the buffers provided in the bufs array. + * + * If i > 0 and sizes[i] == 0, presume sizes[n] = sizes[i-1] + * for all n >= i and < count. + * + * Similarly, if i > 0 and types[i] == H5FD_MEM_NOLIST, + * presume types[n] = types[i-1] for all n >= i and < count. + * + * If the underlying VFD supports vector reads, pass the + * call through directly. + * + * If it doesn't, convert the vector read into a sequence + * of individual reads. + * + * Note that it is not in general possible to convert a + * vector read into a selection read, because each element + * in the vector read may have a different memory type. + * In contrast, selection reads are of a single type. + * + * Return: Success: SUCCEED + * All reads have completed successfully, and + * the results havce been into the supplied + * buffers. + * + * Failure: FAIL + * The contents of supplied buffers are undefined. + * + * Programmer: JRM -- 6/10/20 + * + * Changes: None + * + *------------------------------------------------------------------------- + */ +herr_t +H5FD_read_vector(H5FD_t *file, uint32_t count, H5FD_mem_t types[], haddr_t addrs[], size_t sizes[], + void *bufs[] /* out */) +{ + hbool_t addrs_cooked = FALSE; + hbool_t extend_sizes = FALSE; + hbool_t extend_types = FALSE; + uint32_t i; + size_t size; + H5FD_mem_t type; + hid_t dxpl_id = H5I_INVALID_HID; /* DXPL for operation */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity checks */ + HDassert(file); + HDassert(file->cls); + HDassert((types) || (count == 0)); + HDassert((addrs) || (count == 0)); + HDassert((sizes) || (count == 0)); + HDassert((bufs) || (count == 0)); + + /* verify that the first elements of the sizes and types arrays are + * valid. + */ + HDassert((count == 0) || (sizes[0] != 0)); + HDassert((count == 0) || (types[0] != H5FD_MEM_NOLIST)); + + /* Get proper DXPL for I/O */ + dxpl_id = H5CX_get_dxpl(); + +#ifndef H5_HAVE_PARALLEL + /* The no-op case + * + * Do not return early for Parallel mode since the I/O could be a + * collective transfer. + */ + if (0 == count) { + HGOTO_DONE(SUCCEED) + } +#endif /* H5_HAVE_PARALLEL */ + + if (file->base_addr > 0) { + + /* apply the base_addr offset to the addrs array. Must undo before + * we return. + */ + for (i = 0; i < count; i++) { + + addrs[i] += file->base_addr; + } + addrs_cooked = TRUE; + } + + /* If the file is open for SWMR read access, allow access to data past + * the end of the allocated space (the 'eoa'). This is done because the + * eoa stored in the file's superblock might be out of sync with the + * objects being written within the file by the application performing + * SWMR write operations. + */ + if ((!(file->access_flags & H5F_ACC_SWMR_READ)) && (count > 0)) { + haddr_t eoa; + + extend_sizes = FALSE; + extend_types = FALSE; + + for (i = 0; i < count; i++) { + + if (!extend_sizes) { + + if (sizes[i] == 0) { + + extend_sizes = TRUE; + size = sizes[i - 1]; + } + else { + + size = sizes[i]; + } + } + + if (!extend_types) { + + if (types[i] == H5FD_MEM_NOLIST) { + + extend_types = TRUE; + type = types[i - 1]; + } + else { + + type = types[i]; + } + } + + if (HADDR_UNDEF == (eoa = (file->cls->get_eoa)(file, type))) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver get_eoa request failed") + + if ((addrs[i] + size) > eoa) + + HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, + "addr overflow, addrs[%d] = %llu, sizes[%d] = %llu, eoa = %llu", (int)i, + (unsigned long long)(addrs[i]), (int)i, (unsigned long long)size, + (unsigned long long)eoa) + } + } + + /* if the underlying VFD supports vector read, make the call */ + if (file->cls->read_vector) { + + if ((file->cls->read_vector)(file, dxpl_id, count, types, addrs, sizes, bufs) < 0) + + HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read vector request failed") + } + else { + + /* otherwise, implement the vector read as a sequence of regular + * read calls. + */ + extend_sizes = FALSE; + extend_types = FALSE; + + for (i = 0; i < count; i++) { + + /* we have already verified that sizes[0] != 0 and + * types[0] != H5FD_MEM_NOLIST + */ + + if (!extend_sizes) { + + if (sizes[i] == 0) { + + extend_sizes = TRUE; + size = sizes[i - 1]; + } + else { + + size = sizes[i]; + } + } + + if (!extend_types) { + + if (types[i] == H5FD_MEM_NOLIST) { + + extend_types = TRUE; + type = types[i - 1]; + } + else { + + type = types[i]; + } + } + + if ((file->cls->read)(file, type, dxpl_id, addrs[i], size, bufs[i]) < 0) + HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read request failed") + } + } + +done: + /* undo the base addr offset to the addrs array if necessary */ + if (addrs_cooked) { + + HDassert(file->base_addr > 0); + + for (i = 0; i < count; i++) { + + addrs[i] -= file->base_addr; + } + } + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_read_vector() */ + +/*------------------------------------------------------------------------- + * Function: H5FD_write_vector + * + * Purpose: Private version of H5FDwrite_vector() + * + * Perform count writes to the specified file at the offsets + * provided in the addrs array, with the lengths and memory + * types provided in the sizes and types arrays. Data written + * is taken from the buffers provided in the bufs array. + * + * If i > 0 and sizes[i] == 0, presume sizes[n] = sizes[i-1] + * for all n >= i and < count. + * + * Similarly, if i > 0 and types[i] == H5FD_MEM_NOLIST, + * presume types[n] = types[i-1] for all n >= i and < count. + * + * If the underlying VFD supports vector writes, pass the + * call through directly. + * + * If it doesn't, convert the vector write into a sequence + * of individual writes. + * + * Note that it is not in general possible to convert a + * vector write into a selection write, because each element + * in the vector write may have a different memory type. + * In contrast, selection writes are of a single type. + * + * Return: Success: SUCCEED + * All writes have completed successfully. + * + * Failure: FAIL + * One or more writes failed. + * + * Programmer: JRM -- 6/10/20 + * + * Changes: None + * + *------------------------------------------------------------------------- + */ +herr_t +H5FD_write_vector(H5FD_t *file, uint32_t count, H5FD_mem_t types[], haddr_t addrs[], size_t sizes[], + const void *bufs[]) +{ + hbool_t addrs_cooked = FALSE; + hbool_t extend_sizes = FALSE; + hbool_t extend_types = FALSE; + uint32_t i; + size_t size; + H5FD_mem_t type; + hid_t dxpl_id; /* DXPL for operation */ + haddr_t eoa = HADDR_UNDEF; /* EOA for file */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity checks */ + HDassert(file); + HDassert(file->cls); + HDassert((types) || (count == 0)); + HDassert((addrs) || (count == 0)); + HDassert((sizes) || (count == 0)); + HDassert((bufs) || (count == 0)); + + /* verify that the first elements of the sizes and types arrays are + * valid. + */ + HDassert((count == 0) || (sizes[0] != 0)); + HDassert((count == 0) || (types[0] != H5FD_MEM_NOLIST)); + + /* Get proper DXPL for I/O */ + dxpl_id = H5CX_get_dxpl(); + +#ifndef H5_HAVE_PARALLEL + /* The no-op case + * + * Do not return early for Parallel mode since the I/O could be a + * collective transfer. + */ + if (0 == count) + HGOTO_DONE(SUCCEED) +#endif /* H5_HAVE_PARALLEL */ + + if (file->base_addr > 0) { + + /* apply the base_addr offset to the addrs array. Must undo before + * we return. + */ + for (i = 0; i < count; i++) { + + addrs[i] += file->base_addr; + } + addrs_cooked = TRUE; + } + + extend_sizes = FALSE; + extend_types = FALSE; + + for (i = 0; i < count; i++) { + + if (!extend_sizes) { + + if (sizes[i] == 0) { + + extend_sizes = TRUE; + size = sizes[i - 1]; + } + else { + + size = sizes[i]; + } + } + + if (!extend_types) { + + if (types[i] == H5FD_MEM_NOLIST) { + + extend_types = TRUE; + type = types[i - 1]; + } + else { + + type = types[i]; + } + } + + if (HADDR_UNDEF == (eoa = (file->cls->get_eoa)(file, type))) + + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver get_eoa request failed") + + if ((addrs[i] + size) > eoa) + + HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "addr overflow, addrs[%d] = %llu, sizes[%d] = %llu, \ + eoa = %llu", + (int)i, (unsigned long long)(addrs[i]), (int)i, (unsigned long long)size, + (unsigned long long)eoa) + } + + /* if the underlying VFD supports vector write, make the call */ + if (file->cls->write_vector) { + + if ((file->cls->write_vector)(file, dxpl_id, count, types, addrs, sizes, bufs) < 0) + + HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "driver write vector request failed") + } + else { + /* otherwise, implement the vector write as a sequence of regular + * write calls. + */ + extend_sizes = FALSE; + extend_types = FALSE; + + for (i = 0; i < count; i++) { + + /* we have already verified that sizes[0] != 0 and + * types[0] != H5FD_MEM_NOLIST + */ + + if (!extend_sizes) { + + if (sizes[i] == 0) { + + extend_sizes = TRUE; + size = sizes[i - 1]; + } + else { + + size = sizes[i]; + } + } + + if (!extend_types) { + + if (types[i] == H5FD_MEM_NOLIST) { + + extend_types = TRUE; + type = types[i - 1]; + } + else { + + type = types[i]; + } + } + + if ((file->cls->write)(file, type, dxpl_id, addrs[i], size, bufs[i]) < 0) + HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver write request failed") + } + } + +done: + /* undo the base addr offset to the addrs array if necessary */ + if (addrs_cooked) { + + HDassert(file->base_addr > 0); + + for (i = 0; i < count; i++) { + + addrs[i] -= file->base_addr; + } + } + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_write_vector() */ + +/*------------------------------------------------------------------------- + * Function: H5FD__read_selection_translate + * + * Purpose: Translates a selection read call to a vector read call if + * vector reads are supported, or a series of scalar read + * calls otherwise. + * + * Return: Success: SUCCEED + * All reads have completed successfully, and + * the results havce been into the supplied + * buffers. + * + * Failure: FAIL + * The contents of supplied buffers are undefined. + * + * Programmer: NAF -- 5/13/21 + * + * Changes: None + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD__read_selection_translate(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, uint32_t count, + H5S_t **mem_spaces, H5S_t **file_spaces, haddr_t offsets[], + size_t element_sizes[], void *bufs[] /* out */) +{ + hbool_t extend_sizes = FALSE; + hbool_t extend_bufs = FALSE; + uint32_t i; + size_t element_size; + void * buf; + hbool_t use_vector = FALSE; + haddr_t addrs_local[H5FD_LOCAL_VECTOR_LEN]; + haddr_t * addrs = addrs_local; + size_t sizes_local[H5FD_LOCAL_VECTOR_LEN]; + size_t * sizes = sizes_local; + void * vec_bufs_local[H5FD_LOCAL_VECTOR_LEN]; + void ** vec_bufs = vec_bufs_local; + hsize_t file_off[H5FD_SEQ_LIST_LEN]; + size_t file_len[H5FD_SEQ_LIST_LEN]; + hsize_t mem_off[H5FD_SEQ_LIST_LEN]; + size_t mem_len[H5FD_SEQ_LIST_LEN]; + size_t file_seq_i; + size_t mem_seq_i; + size_t file_nseq; + size_t mem_nseq; + size_t io_len; + size_t nelmts; + hssize_t hss_nelmts; + size_t seq_nelem; + H5S_sel_iter_t *file_iter = NULL; + H5S_sel_iter_t *mem_iter = NULL; + hbool_t file_iter_init = FALSE; + hbool_t mem_iter_init = FALSE; + H5FD_mem_t types[2] = {type, H5FD_MEM_NOLIST}; + size_t vec_arr_nalloc = H5FD_LOCAL_VECTOR_LEN; + size_t vec_arr_nused = 0; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity checks */ + HDassert(file); + HDassert(file->cls); + HDassert(mem_spaces); + HDassert(file_spaces); + HDassert(offsets); + HDassert(element_sizes); + HDassert(bufs); + + /* Verify that the first elements of the element_sizes and bufs arrays are + * valid. */ + HDassert(element_sizes[0] != 0); + HDassert(bufs[0] != NULL); + + /* Check if we're using vector I/O */ + use_vector = file->cls->read_vector != NULL; + + /* Allocate sequence lists for memory and file spaces */ + if (NULL == (file_iter = H5FL_MALLOC(H5S_sel_iter_t))) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "couldn't allocate file selection iterator") + if (NULL == (mem_iter = H5FL_MALLOC(H5S_sel_iter_t))) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "couldn't allocate memory selection iterator") + + /* Loop over dataspaces */ + for (i = 0; i < count; i++) { + + /* we have already verified that element_sizes[0] != 0 and bufs[0] + * != NULL */ + + if (!extend_sizes) { + + if (element_sizes[i] == 0) { + + extend_sizes = TRUE; + element_size = element_sizes[i - 1]; + } + else { + + element_size = element_sizes[i]; + } + } + + if (!extend_bufs) { + + if (bufs[i] == NULL) { + + extend_bufs = TRUE; + buf = bufs[i - 1]; + } + else { + + buf = bufs[i]; + } + } + + /* Initialize sequence lists for memory and file spaces */ + if (H5S_select_iter_init(file_iter, file_spaces[i], element_size, 0) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "can't initialize sequence list for file space") + file_iter_init = TRUE; + if (H5S_select_iter_init(mem_iter, mem_spaces[i], element_size, 0) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "can't initialize sequence list for memory space") + mem_iter_init = TRUE; + + /* Get the number of elements in selection */ + if ((hss_nelmts = (hssize_t)H5S_GET_SELECT_NPOINTS(file_spaces[i])) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTCOUNT, FAIL, "can't get number of elements selected") + H5_CHECKED_ASSIGN(nelmts, size_t, hss_nelmts, hssize_t); + +#ifndef NDEBUG + /* Verify mem space has the same number of elements */ + { + if ((hss_nelmts = (hssize_t)H5S_GET_SELECT_NPOINTS(mem_spaces[i])) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTCOUNT, FAIL, "can't get number of elements selected") + HDassert((hssize_t)nelmts == hss_nelmts); + } +#endif /* NDEBUG */ + + /* Initialize values so sequence lists are retrieved on the first + * iteration */ + file_seq_i = H5FD_SEQ_LIST_LEN; + mem_seq_i = H5FD_SEQ_LIST_LEN; + file_nseq = 0; + mem_nseq = 0; + + /* Loop until all elements are processed */ + while (file_seq_i < file_nseq || nelmts > 0) { + /* Fill/refill file sequence list if necessary */ + if (file_seq_i == H5FD_SEQ_LIST_LEN) { + if (H5S_SELECT_ITER_GET_SEQ_LIST(file_iter, H5FD_SEQ_LIST_LEN, SIZE_MAX, &file_nseq, + &seq_nelem, file_off, file_len) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed") + HDassert(file_nseq > 0); + + nelmts -= seq_nelem; + file_seq_i = 0; + } + HDassert(file_seq_i < file_nseq); + + /* Fill/refill memory sequence list if necessary */ + if (mem_seq_i == H5FD_SEQ_LIST_LEN) { + if (H5S_SELECT_ITER_GET_SEQ_LIST(mem_iter, H5FD_SEQ_LIST_LEN, SIZE_MAX, &mem_nseq, &seq_nelem, + mem_off, mem_len) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed") + HDassert(mem_nseq > 0); + + mem_seq_i = 0; + } + HDassert(mem_seq_i < mem_nseq); + + /* Calculate length of this IO */ + io_len = MIN(file_len[file_seq_i], mem_len[mem_seq_i]); + + /* Check if we're using vector I/O */ + if (use_vector) { + /* Check if we need to extend the arrays */ + if (vec_arr_nused == vec_arr_nalloc) { + /* Check if we're using the static arrays */ + if (addrs == addrs_local) { + HDassert(sizes == sizes_local); + HDassert(vec_bufs == vec_bufs_local); + + /* Allocate dynamic arrays */ + if (NULL == (addrs = H5MM_malloc(sizeof(addrs_local) * 2))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "memory allocation failed for address list") + if (NULL == (sizes = H5MM_malloc(sizeof(sizes_local) * 2))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "memory allocation failed for size list") + if (NULL == (vec_bufs = H5MM_malloc(sizeof(vec_bufs_local) * 2))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "memory allocation failed for buffer list") + + /* Copy the existing data */ + (void)H5MM_memcpy(addrs, addrs_local, sizeof(addrs_local)); + (void)H5MM_memcpy(sizes, sizes_local, sizeof(sizes_local)); + (void)H5MM_memcpy(vec_bufs, vec_bufs_local, sizeof(vec_bufs_local)); + } + else { + void *tmp_ptr; + + /* Reallocate arrays */ + if (NULL == (tmp_ptr = H5MM_realloc(addrs, vec_arr_nalloc * sizeof(*addrs) * 2))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "memory reallocation failed for address list") + addrs = tmp_ptr; + if (NULL == (tmp_ptr = H5MM_realloc(sizes, vec_arr_nalloc * sizeof(*sizes) * 2))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "memory reallocation failed for size list") + sizes = tmp_ptr; + if (NULL == + (tmp_ptr = H5MM_realloc(vec_bufs, vec_arr_nalloc * sizeof(*vec_bufs) * 2))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "memory reallocation failed for buffer list") + vec_bufs = tmp_ptr; + } + + /* Record that we've doubled the array sizes */ + vec_arr_nalloc *= 2; + } + + /* Add this segment to vector read list */ + addrs[vec_arr_nused] = offsets[i] + file_off[file_seq_i]; + sizes[vec_arr_nused] = io_len; + vec_bufs[vec_arr_nused] = (void *)((uint8_t *)buf + mem_off[mem_seq_i]); + vec_arr_nused++; + } + else + /* Issue scalar read call */ + if ((file->cls->read)(file, type, dxpl_id, offsets[i] + file_off[file_seq_i], io_len, + (void *)((uint8_t *)buf + mem_off[mem_seq_i])) < 0) + HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read request failed") + + /* Update file sequence */ + if (io_len == file_len[file_seq_i]) + file_seq_i++; + else { + file_off[file_seq_i] += io_len; + file_len[file_seq_i] -= io_len; + } + + /* Update memory sequence */ + if (io_len == mem_len[mem_seq_i]) + mem_seq_i++; + else { + mem_off[mem_seq_i] += io_len; + mem_len[mem_seq_i] -= io_len; + } + } + + /* Make sure both memory and file sequences terminated at the same time */ + if (mem_seq_i < mem_nseq) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "file selection terminated before memory selection") + + /* Terminate iterators */ + if (H5S_SELECT_ITER_RELEASE(file_iter) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "can't release file selection iterator") + file_iter_init = FALSE; + if (H5S_SELECT_ITER_RELEASE(mem_iter) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "can't release memory selection iterator") + mem_iter_init = FALSE; + } + + /* Issue vector read call if appropriate */ + if (use_vector) { + H5_CHECK_OVERFLOW(vec_arr_nused, size_t, uint32_t) + if ((file->cls->read_vector)(file, dxpl_id, (uint32_t)vec_arr_nused, types, addrs, sizes, vec_bufs) < + 0) + HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read vector request failed") + } + +done: + /* Terminate and free iterators */ + if (file_iter) { + if (file_iter_init && H5S_SELECT_ITER_RELEASE(file_iter) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "can't release file selection iterator") + file_iter = H5FL_FREE(H5S_sel_iter_t, file_iter); + } + if (mem_iter) { + if (mem_iter_init && H5S_SELECT_ITER_RELEASE(mem_iter) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "can't release memory selection iterator") + mem_iter = H5FL_FREE(H5S_sel_iter_t, mem_iter); + } + + /* Cleanup vector arrays */ + if (use_vector) { + if (addrs != addrs_local) + addrs = H5MM_xfree(addrs); + if (sizes != sizes_local) + sizes = H5MM_xfree(sizes); + if (vec_bufs != vec_bufs_local) + vec_bufs = H5MM_xfree(vec_bufs); + } + + /* Make sure we cleaned up */ + HDassert(!addrs || addrs == addrs_local); + HDassert(!sizes || sizes == sizes_local); + HDassert(!vec_bufs || vec_bufs == vec_bufs_local); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD__read_selection_translate() */ + +/*------------------------------------------------------------------------- + * Function: H5FD_read_selection + * + * Purpose: Private version of H5FDread_selection() + * + * Perform count reads from the specified file at the + * locations selected in the dataspaces in the file_spaces + * array, with each of those dataspaces starting at the file + * address specified by the corresponding element of the + * offsets array, and with the size of each element in the + * dataspace specified by the corresponding element of the + * element_sizes array. The memory type provided by type is + * the same for all selections. Data read is returned in + * the locations selected in the dataspaces in the + * mem_spaces array, within the buffers provided in the + * corresponding elements of the bufs array. + * + * If i > 0 and element_sizes[i] == 0, presume + * element_sizes[n] = element_sizes[i-1] for all n >= i and + * < count. + * + * If the underlying VFD supports selection reads, pass the + * call through directly. + * + * If it doesn't, convert the vector read into a sequence + * of individual reads. + * + * Return: Success: SUCCEED + * All reads have completed successfully, and + * the results havce been into the supplied + * buffers. + * + * Failure: FAIL + * The contents of supplied buffers are undefined. + * + * Programmer: NAF -- 3/29/21 + * + * Changes: None + * + *------------------------------------------------------------------------- + */ +herr_t +H5FD_read_selection(H5FD_t *file, H5FD_mem_t type, uint32_t count, H5S_t **mem_spaces, H5S_t **file_spaces, + haddr_t offsets[], size_t element_sizes[], void *bufs[] /* out */) +{ + hbool_t offsets_cooked = FALSE; + hid_t mem_space_ids_local[H5FD_LOCAL_SEL_ARR_LEN]; + hid_t * mem_space_ids = mem_space_ids_local; + hid_t file_space_ids_local[H5FD_LOCAL_SEL_ARR_LEN]; + hid_t * file_space_ids = file_space_ids_local; + uint32_t num_spaces = 0; + hid_t dxpl_id = H5I_INVALID_HID; /* DXPL for operation */ + uint32_t i; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity checks */ + HDassert(file); + HDassert(file->cls); + HDassert((mem_spaces) || (count == 0)); + HDassert((file_spaces) || (count == 0)); + HDassert((offsets) || (count == 0)); + HDassert((element_sizes) || (count == 0)); + HDassert((bufs) || (count == 0)); + + /* Verify that the first elements of the element_sizes and bufs arrays are + * valid. */ + HDassert((count == 0) || (element_sizes[0] != 0)); + HDassert((count == 0) || (bufs[0] != NULL)); + + /* Get proper DXPL for I/O */ + dxpl_id = H5CX_get_dxpl(); + +#ifndef H5_HAVE_PARALLEL + /* The no-op case + * + * Do not return early for Parallel mode since the I/O could be a + * collective transfer. + */ + if (0 == count) { + HGOTO_DONE(SUCCEED) + } +#endif /* H5_HAVE_PARALLEL */ + + if (file->base_addr > 0) { + + /* apply the base_addr offset to the offsets array. Must undo before + * we return. + */ + for (i = 0; i < count; i++) { + + offsets[i] += file->base_addr; + } + offsets_cooked = TRUE; + } + + /* If the file is open for SWMR read access, allow access to data past + * the end of the allocated space (the 'eoa'). This is done because the + * eoa stored in the file's superblock might be out of sync with the + * objects being written within the file by the application performing + * SWMR write operations. + */ + /* For now at least, only check that the offset is not past the eoa, since + * looking into the highest offset in the selection (different from the + * bounds) is potentially expensive. + */ + if (!(file->access_flags & H5F_ACC_SWMR_READ)) { + haddr_t eoa; + + if (HADDR_UNDEF == (eoa = (file->cls->get_eoa)(file, type))) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver get_eoa request failed") + + for (i = 0; i < count; i++) { + + if ((offsets[i]) > eoa) + + HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "addr overflow, offsets[%d] = %llu, eoa = %llu", + (int)i, (unsigned long long)(offsets[i]), (unsigned long long)eoa) + } + } + + /* if the underlying VFD supports selection read, make the call */ + if (file->cls->read_selection) { + /* Allocate array of space IDs if necessary, otherwise use local + * buffers */ + if (count > sizeof(mem_space_ids_local) / sizeof(mem_space_ids_local[0])) { + if (NULL == (mem_space_ids = H5MM_malloc(count * sizeof(hid_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "memory allocation failed for dataspace list") + if (NULL == (file_space_ids = H5MM_malloc(count * sizeof(hid_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "memory allocation failed for dataspace list") + } + + /* Create IDs for all dataspaces */ + for (; num_spaces < count; num_spaces++) { + if ((mem_space_ids[num_spaces] = H5I_register(H5I_DATASPACE, mem_spaces[num_spaces], TRUE)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTREGISTER, FAIL, "unable to register dataspace ID") + + if ((file_space_ids[num_spaces] = H5I_register(H5I_DATASPACE, file_spaces[num_spaces], TRUE)) < + 0) { + if (H5I_dec_app_ref(mem_space_ids[num_spaces]) < 0) + HDONE_ERROR(H5E_VFL, H5E_CANTDEC, FAIL, "problem freeing id") + HGOTO_ERROR(H5E_VFL, H5E_CANTREGISTER, FAIL, "unable to register dataspace ID") + } + } + + if ((file->cls->read_selection)(file, type, dxpl_id, count, mem_space_ids, file_space_ids, offsets, + element_sizes, bufs) < 0) + HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read selection request failed") + } + else + /* Otherwise, implement the selection read as a sequence of regular + * or vector read calls. + */ + if (H5FD__read_selection_translate(file, type, dxpl_id, count, mem_spaces, file_spaces, offsets, + element_sizes, bufs) < 0) + HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "translation to vector or scalar read failed") + +done: + /* undo the base addr offset to the offsets array if necessary */ + if (offsets_cooked) { + + HDassert(file->base_addr > 0); + + for (i = 0; i < count; i++) { + + offsets[i] -= file->base_addr; + } + } + + /* Cleanup dataspace arrays */ + for (i = 0; i < num_spaces; i++) { + if (H5I_dec_app_ref(mem_space_ids[i]) < 0) + HDONE_ERROR(H5E_VFL, H5E_CANTDEC, FAIL, "problem freeing id") + if (H5I_dec_app_ref(file_space_ids[i]) < 0) + HDONE_ERROR(H5E_VFL, H5E_CANTDEC, FAIL, "problem freeing id") + } + if (mem_space_ids != mem_space_ids_local) + mem_space_ids = H5MM_xfree(mem_space_ids); + if (file_space_ids != file_space_ids_local) + file_space_ids = H5MM_xfree(file_space_ids); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_read_selection() */ + +/*------------------------------------------------------------------------- + * Function: H5FD_read_selection_id + * + * Purpose: Like H5FD_read_selection(), but takes hid_t arrays instead + * of H5S_t * arrays for the dataspaces. + * + * Return: Success: SUCCEED + * All reads have completed successfully, and + * the results havce been into the supplied + * buffers. + * + * Failure: FAIL + * The contents of supplied buffers are undefined. + * + * Programmer: NAF -- 5/19/21 + * + * Changes: None + * + *------------------------------------------------------------------------- + */ +herr_t +H5FD_read_selection_id(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem_space_ids[], + hid_t file_space_ids[], haddr_t offsets[], size_t element_sizes[], + void *bufs[] /* out */) +{ + hbool_t offsets_cooked = FALSE; + H5S_t * mem_spaces_local[H5FD_LOCAL_SEL_ARR_LEN]; + H5S_t ** mem_spaces = mem_spaces_local; + H5S_t * file_spaces_local[H5FD_LOCAL_SEL_ARR_LEN]; + H5S_t ** file_spaces = file_spaces_local; + hid_t dxpl_id = H5I_INVALID_HID; /* DXPL for operation */ + uint32_t i; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity checks */ + HDassert(file); + HDassert(file->cls); + HDassert((mem_space_ids) || (count == 0)); + HDassert((file_space_ids) || (count == 0)); + HDassert((offsets) || (count == 0)); + HDassert((element_sizes) || (count == 0)); + HDassert((bufs) || (count == 0)); + + /* Verify that the first elements of the element_sizes and bufs arrays are + * valid. */ + HDassert((count == 0) || (element_sizes[0] != 0)); + HDassert((count == 0) || (bufs[0] != NULL)); + + /* Get proper DXPL for I/O */ + dxpl_id = H5CX_get_dxpl(); + +#ifndef H5_HAVE_PARALLEL + /* The no-op case + * + * Do not return early for Parallel mode since the I/O could be a + * collective transfer. + */ + if (0 == count) { + HGOTO_DONE(SUCCEED) + } +#endif /* H5_HAVE_PARALLEL */ + + if (file->base_addr > 0) { + + /* apply the base_addr offset to the offsets array. Must undo before + * we return. + */ + for (i = 0; i < count; i++) { + + offsets[i] += file->base_addr; + } + offsets_cooked = TRUE; + } + + /* If the file is open for SWMR read access, allow access to data past + * the end of the allocated space (the 'eoa'). This is done because the + * eoa stored in the file's superblock might be out of sync with the + * objects being written within the file by the application performing + * SWMR write operations. + */ + /* For now at least, only check that the offset is not past the eoa, since + * looking into the highest offset in the selection (different from the + * bounds) is potentially expensive. + */ + if (!(file->access_flags & H5F_ACC_SWMR_READ)) { + haddr_t eoa; + + if (HADDR_UNDEF == (eoa = (file->cls->get_eoa)(file, type))) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver get_eoa request failed") + + for (i = 0; i < count; i++) { + + if ((offsets[i]) > eoa) + + HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "addr overflow, offsets[%d] = %llu, eoa = %llu", + (int)i, (unsigned long long)(offsets[i]), (unsigned long long)eoa) + } + } + + /* if the underlying VFD supports selection read, make the call */ + if (file->cls->read_selection) { + if ((file->cls->read_selection)(file, type, dxpl_id, count, mem_space_ids, file_space_ids, offsets, + element_sizes, bufs) < 0) + HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read selection request failed") + } + else { + /* Otherwise, implement the selection read as a sequence of regular + * or vector read calls. + */ + + /* Allocate arrays of space objects if necessary, otherwise use local + * buffers */ + if (count > sizeof(mem_spaces_local) / sizeof(mem_spaces_local[0])) { + if (NULL == (mem_spaces = H5MM_malloc(count * sizeof(H5S_t *)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "memory allocation failed for dataspace list") + if (NULL == (file_spaces = H5MM_malloc(count * sizeof(H5S_t *)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "memory allocation failed for dataspace list") + } + + /* Get object pointers for all dataspaces */ + for (i = 0; i < count; i++) { + if (NULL == (mem_spaces[i] = (H5S_t *)H5I_object_verify(mem_space_ids[i], H5I_DATASPACE))) + HGOTO_ERROR(H5E_VFL, H5E_BADTYPE, H5I_INVALID_HID, "can't retrieve memory dataspace from ID") + if (NULL == (file_spaces[i] = (H5S_t *)H5I_object_verify(file_space_ids[i], H5I_DATASPACE))) + HGOTO_ERROR(H5E_VFL, H5E_BADTYPE, H5I_INVALID_HID, "can't retrieve file dataspace from ID") + } + + /* Translate to vector or scalar I/O */ + if (H5FD__read_selection_translate(file, type, dxpl_id, count, mem_spaces, file_spaces, offsets, + element_sizes, bufs) < 0) + HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "translation to vector or scalar read failed") + } + +done: + /* undo the base addr offset to the offsets array if necessary */ + if (offsets_cooked) { + + HDassert(file->base_addr > 0); + + for (i = 0; i < count; i++) { + + offsets[i] -= file->base_addr; + } + } + + /* Cleanup dataspace arrays */ + if (mem_spaces != mem_spaces_local) + mem_spaces = H5MM_xfree(mem_spaces); + if (file_spaces != file_spaces_local) + file_spaces = H5MM_xfree(file_spaces); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_read_selection_id() */ + +/*------------------------------------------------------------------------- + * Function: H5FD__write_selection_translate + * + * Purpose: Translates a selection write call to a vector write call + * if vector writes are supported, or a series of scalar + * write calls otherwise. + * + * Return: Success: SUCCEED + * All writes have completed successfully. + * + * Failure: FAIL + * One or more writes failed. + * + * Programmer: NAF -- 5/13/21 + * + * Changes: None + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD__write_selection_translate(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, uint32_t count, + H5S_t **mem_spaces, H5S_t **file_spaces, haddr_t offsets[], + size_t element_sizes[], const void *bufs[]) +{ + hbool_t extend_sizes = FALSE; + hbool_t extend_bufs = FALSE; + uint32_t i; + size_t element_size; + const void * buf; + hbool_t use_vector = FALSE; + haddr_t addrs_local[H5FD_LOCAL_VECTOR_LEN]; + haddr_t * addrs = addrs_local; + size_t sizes_local[H5FD_LOCAL_VECTOR_LEN]; + size_t * sizes = sizes_local; + const void * vec_bufs_local[H5FD_LOCAL_VECTOR_LEN]; + const void ** vec_bufs = vec_bufs_local; + hsize_t file_off[H5FD_SEQ_LIST_LEN]; + size_t file_len[H5FD_SEQ_LIST_LEN]; + hsize_t mem_off[H5FD_SEQ_LIST_LEN]; + size_t mem_len[H5FD_SEQ_LIST_LEN]; + size_t file_seq_i; + size_t mem_seq_i; + size_t file_nseq; + size_t mem_nseq; + size_t io_len; + size_t nelmts; + hssize_t hss_nelmts; + size_t seq_nelem; + H5S_sel_iter_t *file_iter = NULL; + H5S_sel_iter_t *mem_iter = NULL; + hbool_t file_iter_init = FALSE; + hbool_t mem_iter_init = FALSE; + H5FD_mem_t types[2] = {type, H5FD_MEM_NOLIST}; + size_t vec_arr_nalloc = H5FD_LOCAL_VECTOR_LEN; + size_t vec_arr_nused = 0; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity checks */ + HDassert(file); + HDassert(file->cls); + HDassert(mem_spaces); + HDassert(file_spaces); + HDassert(offsets); + HDassert(element_sizes); + HDassert(bufs); + + /* Verify that the first elements of the element_sizes and bufs arrays are + * valid. */ + HDassert(element_sizes[0] != 0); + HDassert(bufs[0] != NULL); + + /* Check if we're using vector I/O */ + use_vector = file->cls->write_vector != NULL; + + /* Allocate sequence lists for memory and file spaces */ + if (NULL == (file_iter = H5FL_MALLOC(H5S_sel_iter_t))) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "couldn't allocate file selection iterator") + if (NULL == (mem_iter = H5FL_MALLOC(H5S_sel_iter_t))) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "couldn't allocate memory selection iterator") + + /* Loop over dataspaces */ + for (i = 0; i < count; i++) { + + /* we have already verified that element_sizes[0] != 0 and bufs[0] + * != NULL */ + + if (!extend_sizes) { + + if (element_sizes[i] == 0) { + + extend_sizes = TRUE; + element_size = element_sizes[i - 1]; + } + else { + + element_size = element_sizes[i]; + } + } + + if (!extend_bufs) { + + if (bufs[i] == NULL) { + + extend_bufs = TRUE; + buf = bufs[i - 1]; + } + else { + + buf = bufs[i]; + } + } + + /* Initialize sequence lists for memory and file spaces */ + if (H5S_select_iter_init(file_iter, file_spaces[i], element_size, 0) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "can't initialize sequence list for file space") + file_iter_init = TRUE; + if (H5S_select_iter_init(mem_iter, mem_spaces[i], element_size, 0) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "can't initialize sequence list for memory space") + mem_iter_init = TRUE; + + /* Get the number of elements in selection */ + if ((hss_nelmts = (hssize_t)H5S_GET_SELECT_NPOINTS(file_spaces[i])) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTCOUNT, FAIL, "can't get number of elements selected") + H5_CHECKED_ASSIGN(nelmts, size_t, hss_nelmts, hssize_t); + +#ifndef NDEBUG + /* Verify mem space has the same number of elements */ + { + if ((hss_nelmts = (hssize_t)H5S_GET_SELECT_NPOINTS(mem_spaces[i])) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTCOUNT, FAIL, "can't get number of elements selected") + HDassert((hssize_t)nelmts == hss_nelmts); + } +#endif /* NDEBUG */ + + /* Initialize values so sequence lists are retrieved on the first + * iteration */ + file_seq_i = H5FD_SEQ_LIST_LEN; + mem_seq_i = H5FD_SEQ_LIST_LEN; + file_nseq = 0; + mem_nseq = 0; + + /* Loop until all elements are processed */ + while (file_seq_i < file_nseq || nelmts > 0) { + /* Fill/refill file sequence list if necessary */ + if (file_seq_i == H5FD_SEQ_LIST_LEN) { + if (H5S_SELECT_ITER_GET_SEQ_LIST(file_iter, H5FD_SEQ_LIST_LEN, SIZE_MAX, &file_nseq, + &seq_nelem, file_off, file_len) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed") + HDassert(file_nseq > 0); + + nelmts -= seq_nelem; + file_seq_i = 0; + } + HDassert(file_seq_i < file_nseq); + + /* Fill/refill memory sequence list if necessary */ + if (mem_seq_i == H5FD_SEQ_LIST_LEN) { + if (H5S_SELECT_ITER_GET_SEQ_LIST(mem_iter, H5FD_SEQ_LIST_LEN, SIZE_MAX, &mem_nseq, &seq_nelem, + mem_off, mem_len) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed") + HDassert(mem_nseq > 0); + + mem_seq_i = 0; + } + HDassert(mem_seq_i < mem_nseq); + + /* Calculate length of this IO */ + io_len = MIN(file_len[file_seq_i], mem_len[mem_seq_i]); + + /* Check if we're using vector I/O */ + if (use_vector) { + /* Check if we need to extend the arrays */ + if (vec_arr_nused == vec_arr_nalloc) { + /* Check if we're using the static arrays */ + if (addrs == addrs_local) { + HDassert(sizes == sizes_local); + HDassert(vec_bufs == vec_bufs_local); + + /* Allocate dynamic arrays */ + if (NULL == (addrs = H5MM_malloc(sizeof(addrs_local) * 2))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "memory allocation failed for address list") + if (NULL == (sizes = H5MM_malloc(sizeof(sizes_local) * 2))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "memory allocation failed for size list") + if (NULL == (vec_bufs = H5MM_malloc(sizeof(vec_bufs_local) * 2))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "memory allocation failed for buffer list") + + /* Copy the existing data */ + (void)H5MM_memcpy(addrs, addrs_local, sizeof(addrs_local)); + (void)H5MM_memcpy(sizes, sizes_local, sizeof(sizes_local)); + (void)H5MM_memcpy(vec_bufs, vec_bufs_local, sizeof(vec_bufs_local)); + } + else { + void *tmp_ptr; + + /* Reallocate arrays */ + if (NULL == (tmp_ptr = H5MM_realloc(addrs, vec_arr_nalloc * sizeof(*addrs) * 2))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "memory reallocation failed for address list") + addrs = tmp_ptr; + if (NULL == (tmp_ptr = H5MM_realloc(sizes, vec_arr_nalloc * sizeof(*sizes) * 2))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "memory reallocation failed for size list") + sizes = tmp_ptr; + if (NULL == + (tmp_ptr = H5MM_realloc(vec_bufs, vec_arr_nalloc * sizeof(*vec_bufs) * 2))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "memory reallocation failed for buffer list") + vec_bufs = tmp_ptr; + } + + /* Record that we've doubled the array sizes */ + vec_arr_nalloc *= 2; + } + + /* Add this segment to vector write list */ + addrs[vec_arr_nused] = offsets[i] + file_off[file_seq_i]; + sizes[vec_arr_nused] = io_len; + vec_bufs[vec_arr_nused] = (const void *)((const uint8_t *)buf + mem_off[mem_seq_i]); + vec_arr_nused++; + } + else + /* Issue scalar write call */ + if ((file->cls->write)(file, type, dxpl_id, offsets[i] + file_off[file_seq_i], io_len, + (const void *)((const uint8_t *)buf + mem_off[mem_seq_i])) < 0) + HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "driver write request failed") + + /* Update file sequence */ + if (io_len == file_len[file_seq_i]) + file_seq_i++; + else { + file_off[file_seq_i] += io_len; + file_len[file_seq_i] -= io_len; + } + + /* Update memory sequence */ + if (io_len == mem_len[mem_seq_i]) + mem_seq_i++; + else { + mem_off[mem_seq_i] += io_len; + mem_len[mem_seq_i] -= io_len; + } + } + + /* Make sure both memory and file sequences terminated at the same time */ + if (mem_seq_i < mem_nseq) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "file selection terminated before memory selection") + + /* Terminate iterators */ + if (H5S_SELECT_ITER_RELEASE(file_iter) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "can't release file selection iterator") + file_iter_init = FALSE; + if (H5S_SELECT_ITER_RELEASE(mem_iter) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "can't release memory selection iterator") + mem_iter_init = FALSE; + } + + /* Issue vector write call if appropriate */ + if (use_vector) { + H5_CHECK_OVERFLOW(vec_arr_nused, size_t, uint32_t) + if ((file->cls->write_vector)(file, dxpl_id, (uint32_t)vec_arr_nused, types, addrs, sizes, vec_bufs) < + 0) + HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "driver write vector request failed") + } + +done: + /* Terminate and free iterators */ + if (file_iter) { + if (file_iter_init && H5S_SELECT_ITER_RELEASE(file_iter) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "can't release file selection iterator") + file_iter = H5FL_FREE(H5S_sel_iter_t, file_iter); + } + if (mem_iter) { + if (mem_iter_init && H5S_SELECT_ITER_RELEASE(mem_iter) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "can't release memory selection iterator") + mem_iter = H5FL_FREE(H5S_sel_iter_t, mem_iter); + } + + /* Cleanup vector arrays */ + if (use_vector) { + if (addrs != addrs_local) + addrs = H5MM_xfree(addrs); + if (sizes != sizes_local) + sizes = H5MM_xfree(sizes); + if (vec_bufs != vec_bufs_local) + vec_bufs = H5MM_xfree(vec_bufs); + } + + /* Make sure we cleaned up */ + HDassert(!addrs || addrs == addrs_local); + HDassert(!sizes || sizes == sizes_local); + HDassert(!vec_bufs || vec_bufs == vec_bufs_local); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD__write_selection_translate() */ + +/*------------------------------------------------------------------------- + * Function: H5FD_write_selection + * + * Purpose: Private version of H5FDwrite_selection() + * + * Perform count writes to the specified file at the + * locations selected in the dataspaces in the file_spaces + * array, with each of those dataspaces starting at the file + * address specified by the corresponding element of the + * offsets array, and with the size of each element in the + * dataspace specified by the corresponding element of the + * element_sizes array. The memory type provided by type is + * the same for all selections. Data write is from + * the locations selected in the dataspaces in the + * mem_spaces array, within the buffers provided in the + * corresponding elements of the bufs array. + * + * If i > 0 and element_sizes[i] == 0, presume + * element_sizes[n] = element_sizes[i-1] for all n >= i and + * < count. + * + * If the underlying VFD supports selection writes, pass the + * call through directly. + * + * If it doesn't, convert the vector write into a sequence + * of individual writes. + * + * Return: Success: SUCCEED + * All writes have completed successfully. + * + * Failure: FAIL + * One or more writes failed. + * + * Programmer: NAF -- 3/29/21 + * + * Changes: None + * + *------------------------------------------------------------------------- + */ +herr_t +H5FD_write_selection(H5FD_t *file, H5FD_mem_t type, uint32_t count, H5S_t **mem_spaces, H5S_t **file_spaces, + haddr_t offsets[], size_t element_sizes[], const void *bufs[]) +{ + hbool_t offsets_cooked = FALSE; + hid_t mem_space_ids_local[H5FD_LOCAL_SEL_ARR_LEN]; + hid_t * mem_space_ids = mem_space_ids_local; + hid_t file_space_ids_local[H5FD_LOCAL_SEL_ARR_LEN]; + hid_t * file_space_ids = file_space_ids_local; + uint32_t num_spaces = 0; + hid_t dxpl_id = H5I_INVALID_HID; /* DXPL for operation */ + uint32_t i; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity checks */ + HDassert(file); + HDassert(file->cls); + HDassert((mem_spaces) || (count == 0)); + HDassert((file_spaces) || (count == 0)); + HDassert((offsets) || (count == 0)); + HDassert((element_sizes) || (count == 0)); + HDassert((bufs) || (count == 0)); + + /* Verify that the first elements of the element_sizes and bufs arrays are + * valid. */ + HDassert((count == 0) || (element_sizes[0] != 0)); + HDassert((count == 0) || (bufs[0] != NULL)); + + /* Get proper DXPL for I/O */ + dxpl_id = H5CX_get_dxpl(); + +#ifndef H5_HAVE_PARALLEL + /* The no-op case + * + * Do not return early for Parallel mode since the I/O could be a + * collective transfer. + */ + if (0 == count) { + HGOTO_DONE(SUCCEED) + } +#endif /* H5_HAVE_PARALLEL */ + + if (file->base_addr > 0) { + + /* apply the base_addr offset to the offsets array. Must undo before + * we return. + */ + for (i = 0; i < count; i++) { + + offsets[i] += file->base_addr; + } + offsets_cooked = TRUE; + } + + /* For now at least, only check that the offset is not past the eoa, since + * looking into the highest offset in the selection (different from the + * bounds) is potentially expensive. + */ + { + haddr_t eoa; + + if (HADDR_UNDEF == (eoa = (file->cls->get_eoa)(file, type))) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver get_eoa request failed") + + for (i = 0; i < count; i++) { + + if ((offsets[i]) > eoa) + + HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "addr overflow, offsets[%d] = %llu, eoa = %llu", + (int)i, (unsigned long long)(offsets[i]), (unsigned long long)eoa) + } + } + + /* if the underlying VFD supports selection write, make the call */ + if (file->cls->write_selection) { + /* Allocate array of space IDs if necessary, otherwise use local + * buffers */ + if (count > sizeof(mem_space_ids_local) / sizeof(mem_space_ids_local[0])) { + if (NULL == (mem_space_ids = H5MM_malloc(count * sizeof(hid_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "memory allocation failed for dataspace list") + if (NULL == (file_space_ids = H5MM_malloc(count * sizeof(hid_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "memory allocation failed for dataspace list") + } + + /* Create IDs for all dataspaces */ + for (; num_spaces < count; num_spaces++) { + if ((mem_space_ids[num_spaces] = H5I_register(H5I_DATASPACE, mem_spaces[num_spaces], TRUE)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTREGISTER, FAIL, "unable to register dataspace ID") + + if ((file_space_ids[num_spaces] = H5I_register(H5I_DATASPACE, file_spaces[num_spaces], TRUE)) < + 0) { + if (H5I_dec_app_ref(mem_space_ids[num_spaces]) < 0) + HDONE_ERROR(H5E_VFL, H5E_CANTDEC, FAIL, "problem freeing id") + HGOTO_ERROR(H5E_VFL, H5E_CANTREGISTER, FAIL, "unable to register dataspace ID") + } + } + + if ((file->cls->write_selection)(file, type, dxpl_id, count, mem_space_ids, file_space_ids, offsets, + element_sizes, bufs) < 0) + HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "driver write selection request failed") + } + else + /* Otherwise, implement the selection write as a sequence of regular + * or vector write calls. + */ + if (H5FD__write_selection_translate(file, type, dxpl_id, count, mem_spaces, file_spaces, offsets, + element_sizes, bufs) < 0) + HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "translation to vector or scalar write failed") + +done: + /* undo the base addr offset to the offsets array if necessary */ + if (offsets_cooked) { + + HDassert(file->base_addr > 0); + + for (i = 0; i < count; i++) { + + offsets[i] -= file->base_addr; + } + } + + /* Cleanup dataspace arrays */ + for (i = 0; i < num_spaces; i++) { + if (H5I_dec_app_ref(mem_space_ids[i]) < 0) + HDONE_ERROR(H5E_VFL, H5E_CANTDEC, FAIL, "problem freeing id") + if (H5I_dec_app_ref(file_space_ids[i]) < 0) + HDONE_ERROR(H5E_VFL, H5E_CANTDEC, FAIL, "problem freeing id") + } + if (mem_space_ids != mem_space_ids_local) + mem_space_ids = H5MM_xfree(mem_space_ids); + if (file_space_ids != file_space_ids_local) + file_space_ids = H5MM_xfree(file_space_ids); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_write_selection() */ + +/*------------------------------------------------------------------------- + * Function: H5FD_write_selection_id + * + * Purpose: Like H5FD_write_selection(), but takes hid_t arrays + * instead of H5S_t * arrays for the dataspaces. + * + * Return: Success: SUCCEED + * All writes have completed successfully. + * + * Failure: FAIL + * One or more writes failed. + * + * Programmer: NAF -- 5/19/21 + * + * Changes: None + * + *------------------------------------------------------------------------- + */ +herr_t +H5FD_write_selection_id(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem_space_ids[], + hid_t file_space_ids[], haddr_t offsets[], size_t element_sizes[], const void *bufs[]) +{ + hbool_t offsets_cooked = FALSE; + H5S_t * mem_spaces_local[H5FD_LOCAL_SEL_ARR_LEN]; + H5S_t ** mem_spaces = mem_spaces_local; + H5S_t * file_spaces_local[H5FD_LOCAL_SEL_ARR_LEN]; + H5S_t ** file_spaces = file_spaces_local; + hid_t dxpl_id = H5I_INVALID_HID; /* DXPL for operation */ + uint32_t i; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity checks */ + HDassert(file); + HDassert(file->cls); + HDassert((mem_space_ids) || (count == 0)); + HDassert((file_space_ids) || (count == 0)); + HDassert((offsets) || (count == 0)); + HDassert((element_sizes) || (count == 0)); + HDassert((bufs) || (count == 0)); + + /* Verify that the first elements of the element_sizes and bufs arrays are + * valid. */ + HDassert((count == 0) || (element_sizes[0] != 0)); + HDassert((count == 0) || (bufs[0] != NULL)); + + /* Get proper DXPL for I/O */ + dxpl_id = H5CX_get_dxpl(); + +#ifndef H5_HAVE_PARALLEL + /* The no-op case + * + * Do not return early for Parallel mode since the I/O could be a + * collective transfer. + */ + if (0 == count) { + HGOTO_DONE(SUCCEED) + } +#endif /* H5_HAVE_PARALLEL */ + + if (file->base_addr > 0) { + + /* apply the base_addr offset to the offsets array. Must undo before + * we return. + */ + for (i = 0; i < count; i++) { + + offsets[i] += file->base_addr; + } + offsets_cooked = TRUE; + } + + /* For now at least, only check that the offset is not past the eoa, since + * looking into the highest offset in the selection (different from the + * bounds) is potentially expensive. + */ + { + haddr_t eoa; + + if (HADDR_UNDEF == (eoa = (file->cls->get_eoa)(file, type))) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver get_eoa request failed") + + for (i = 0; i < count; i++) { + + if ((offsets[i]) > eoa) + + HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "addr overflow, offsets[%d] = %llu, eoa = %llu", + (int)i, (unsigned long long)(offsets[i]), (unsigned long long)eoa) + } + } + + /* if the underlying VFD supports selection write, make the call */ + if (file->cls->write_selection) { + if ((file->cls->write_selection)(file, type, dxpl_id, count, mem_space_ids, file_space_ids, offsets, + element_sizes, bufs) < 0) + HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "driver write selection request failed") + } + else { + /* Otherwise, implement the selection write as a sequence of regular + * or vector write calls. + */ + + /* Allocate arrays of space objects if necessary, otherwise use local + * buffers */ + if (count > sizeof(mem_spaces_local) / sizeof(mem_spaces_local[0])) { + if (NULL == (mem_spaces = H5MM_malloc(count * sizeof(H5S_t *)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "memory allocation failed for dataspace list") + if (NULL == (file_spaces = H5MM_malloc(count * sizeof(H5S_t *)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "memory allocation failed for dataspace list") + } + + /* Get object pointers for all dataspaces */ + for (i = 0; i < count; i++) { + if (NULL == (mem_spaces[i] = (H5S_t *)H5I_object_verify(mem_space_ids[i], H5I_DATASPACE))) + HGOTO_ERROR(H5E_VFL, H5E_BADTYPE, H5I_INVALID_HID, "can't retrieve memory dataspace from ID") + if (NULL == (file_spaces[i] = (H5S_t *)H5I_object_verify(file_space_ids[i], H5I_DATASPACE))) + HGOTO_ERROR(H5E_VFL, H5E_BADTYPE, H5I_INVALID_HID, "can't retrieve file dataspace from ID") + } + + /* Translate to vector or scalar I/O */ + if (H5FD__write_selection_translate(file, type, dxpl_id, count, mem_spaces, file_spaces, offsets, + element_sizes, bufs) < 0) + HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "translation to vector or scalar write failed") + } + +done: + /* undo the base addr offset to the offsets array if necessary */ + if (offsets_cooked) { + + HDassert(file->base_addr > 0); + + for (i = 0; i < count; i++) { + + offsets[i] -= file->base_addr; + } + } + + /* Cleanup dataspace arrays */ + if (mem_spaces != mem_spaces_local) + mem_spaces = H5MM_xfree(mem_spaces); + if (file_spaces != file_spaces_local) + file_spaces = H5MM_xfree(file_spaces); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_write_selection_id() */ + +/*------------------------------------------------------------------------- * Function: H5FD_set_eoa * * Purpose: Private version of H5FDset_eoa() @@ -383,6 +2133,246 @@ H5FD_driver_query(const H5FD_class_t *driver, unsigned long *flags /*out*/) } /* end H5FD_driver_query() */ /*------------------------------------------------------------------------- + * Function: H5FD_sort_vector_io_req + * + * Purpose: Determine whether the supplied vector I/O request is + * sorted. + * + * if is is, set *vector_was_sorted to TRUE, set: + * + * *s_types_ptr = types + * *s_addrs_ptr = addrs + * *s_sizes_ptr = sizes + * *s_bufs_ptr = bufs + * + * and return. + * + * If it is not sorted, duplicate the type, addrs, sizes, + * and bufs vectors, storing the base addresses of the new + * vectors in *s_types_ptr, *s_addrs_ptr, *s_sizes_ptr, and + * *s_bufs_ptr respectively. Determine the sorted order + * of the vector I/O request, and load it into the new + * vectors in sorted order. + * + * Note that in this case, it is the callers responsibility + * to free the sorted vectors. + * + * JRM -- 3/15/21 + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ + +static int +H5FD__vsrt_tmp_cmp(const void *element_1, const void *element_2) +{ + haddr_t addr_1 = ((const H5FD_vsrt_tmp_t *)element_1)->addr; + haddr_t addr_2 = ((const H5FD_vsrt_tmp_t *)element_2)->addr; + int ret_value = 0; /* Return value */ + + FUNC_ENTER_STATIC_NOERR + + /* Sanity checks */ + HDassert(H5F_addr_defined(addr_1)); + HDassert(H5F_addr_defined(addr_2)); + + /* Compare the addresses */ + if (H5F_addr_gt(addr_1, addr_2)) + ret_value = 1; + else if (H5F_addr_lt(addr_1, addr_2)) + ret_value = -1; + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5FD__vsrt_tmp_cmp() */ + +herr_t +H5FD_sort_vector_io_req(hbool_t *vector_was_sorted, uint32_t _count, H5FD_mem_t types[], haddr_t addrs[], + size_t sizes[], H5_flexible_const_ptr_t bufs[], H5FD_mem_t **s_types_ptr, + haddr_t **s_addrs_ptr, size_t **s_sizes_ptr, H5_flexible_const_ptr_t **s_bufs_ptr) +{ + herr_t ret_value = SUCCEED; /* Return value */ + size_t count = (size_t)_count; + size_t i; + struct H5FD_vsrt_tmp_t *srt_tmp = NULL; + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity checks */ + + HDassert(vector_was_sorted); + + HDassert((types) || (count == 0)); + HDassert((addrs) || (count == 0)); + HDassert((sizes) || (count == 0)); + HDassert((bufs) || (count == 0)); + + /* verify that the first elements of the sizes and types arrays are + * valid. + */ + HDassert((count == 0) || (sizes[0] != 0)); + HDassert((count == 0) || (types[0] != H5FD_MEM_NOLIST)); + + HDassert((count == 0) || ((s_types_ptr) && (NULL == *s_types_ptr))); + HDassert((count == 0) || ((s_addrs_ptr) && (NULL == *s_addrs_ptr))); + HDassert((count == 0) || ((s_sizes_ptr) && (NULL == *s_sizes_ptr))); + HDassert((count == 0) || ((s_bufs_ptr) && (NULL == *s_bufs_ptr))); + + /* scan the addrs array to see if it is sorted */ + for (i = 1; i < count; i++) { + HDassert(H5F_addr_defined(addrs[i - 1])); + + if (H5F_addr_gt(addrs[i - 1], addrs[i])) + break; + else if (H5F_addr_eq(addrs[i - 1], addrs[i])) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "duplicate addr in vector") + } + + /* if we traversed the entire array without breaking out, then + * the array was already sorted */ + if (i >= count) + *vector_was_sorted = TRUE; + else + *vector_was_sorted = FALSE; + + if (*vector_was_sorted) { + + *s_types_ptr = types; + *s_addrs_ptr = addrs; + *s_sizes_ptr = sizes; + *s_bufs_ptr = bufs; + } + else { + + /* must sort the addrs array in increasing addr order, while + * maintaining the association between each addr, and the + * sizes[], types[], and bufs[] values at the same index. + * + * Do this by allocating an array of struct H5FD_vsrt_tmp_t, where + * each instance of H5FD_vsrt_tmp_t has two fields, addr and index. + * Load the array with the contents of the addrs array and + * the index of the associated entry. Sort the array, allocate + * the s_types_ptr, s_addrs_ptr, s_sizes_ptr, and s_bufs_ptr + * arrays and populate them using the mapping provided by + * the sorted array of H5FD_vsrt_tmp_t. + */ + int j; + size_t fixed_size_index = count; + size_t fixed_type_index = count; + size_t srt_tmp_size; + + srt_tmp_size = (count * sizeof(struct H5FD_vsrt_tmp_t)); + + if (NULL == (srt_tmp = (H5FD_vsrt_tmp_t *)HDmalloc(srt_tmp_size))) + + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't alloc srt_tmp") + + for (i = 0; i < count; i++) { + HDassert(i == (size_t)((int)i)); + + srt_tmp[i].addr = addrs[i]; + srt_tmp[i].index = (int)i; + } + + /* sort the srt_tmp array */ + HDqsort(srt_tmp, count, sizeof(struct H5FD_vsrt_tmp_t), H5FD__vsrt_tmp_cmp); + + /* verify no duplicate entries */ + i = 1; + + for (i = 1; i < count; i++) { + HDassert(H5F_addr_lt(srt_tmp[i - 1].addr, srt_tmp[i].addr)); + + if (H5F_addr_eq(addrs[i - 1], addrs[i])) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "duplicate addr in vector") + } + + if ((NULL == (*s_types_ptr = (H5FD_mem_t *)HDmalloc(count * sizeof(H5FD_mem_t)))) || + (NULL == (*s_addrs_ptr = (haddr_t *)HDmalloc(count * sizeof(haddr_t)))) || + (NULL == (*s_sizes_ptr = (size_t *)HDmalloc(count * sizeof(size_t)))) || + (NULL == + (*s_bufs_ptr = (H5_flexible_const_ptr_t *)HDmalloc(count * sizeof(H5_flexible_const_ptr_t))))) { + + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't alloc sorted vector(s)") + } + + HDassert(sizes[0] != 0); + HDassert(types[0] != H5FD_MEM_NOLIST); + + /* Scan the sizes and types vectors to determine if the fixed size / type + * optimization is in use, and if so, to determine the index of the last + * valid value on each vector. We have already verified that the first + * elements of these arrays are valid so we can start at the second + * element (if it exists). + */ + for (i = 1; i < count && ((fixed_size_index == count) || (fixed_type_index == count)); i++) { + if ((fixed_size_index == count) && (sizes[i] == 0)) + fixed_size_index = i - 1; + if ((fixed_type_index == count) && (types[i] == H5FD_MEM_NOLIST)) + fixed_type_index = i - 1; + } + + HDassert(fixed_size_index <= count); + HDassert(fixed_type_index <= count); + + /* populate the sorted vectors */ + for (i = 0; i < count; i++) { + + j = srt_tmp[i].index; + + (*s_types_ptr)[j] = types[MIN(i, fixed_type_index)]; + (*s_addrs_ptr)[j] = addrs[i]; + (*s_sizes_ptr)[j] = sizes[MIN(i, fixed_size_index)]; + (*s_bufs_ptr)[j] = bufs[i]; + } + } + +done: + if (srt_tmp) { + + HDfree(srt_tmp); + srt_tmp = NULL; + } + + /* On failure, free the sorted vectors if they were allocated. + * Note that we only allocate these vectors if the original array + * was not sorted -- thus we check both for failure, and for + * the flag indicating that the original vector was not sorted + * in increasing address order. + */ + if ((ret_value != SUCCEED) && (!(*vector_was_sorted))) { + + /* free space allocated for sorted vectors */ + if (*s_types_ptr) { + + HDfree(*s_types_ptr); + *s_types_ptr = NULL; + } + + if (*s_addrs_ptr) { + + HDfree(*s_addrs_ptr); + *s_addrs_ptr = NULL; + } + + if (*s_sizes_ptr) { + + HDfree(*s_sizes_ptr); + *s_sizes_ptr = NULL; + } + + if (*s_bufs_ptr) { + + HDfree(*s_bufs_ptr); + *s_bufs_ptr = NULL; + } + } + + FUNC_LEAVE_NOAPI(ret_value) + +} /* end H5FD_sort_vector_io_req() */ + +/*------------------------------------------------------------------------- * Function: H5FD_delete * * Purpose: Private version of H5FDdelete() @@ -402,6 +2392,7 @@ H5FD_delete(const char *filename, hid_t fapl_id) FUNC_ENTER_NOAPI(FAIL) /* Sanity checks */ + HDassert(filename); /* Get file access property list */ @@ -425,3 +2416,357 @@ H5FD_delete(const char *filename, hid_t fapl_id) done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD_delete() */ + +/*------------------------------------------------------------------------- + * Function: H5FD_check_plugin_load + * + * Purpose: Check if a VFD plugin matches the search criteria, and can + * be loaded. + * + * Note: Matching the driver's name / value, but the driver having + * an incompatible version is not an error, but means that the + * driver isn't a "match". Setting the SUCCEED value to FALSE + * and not failing for that case allows the plugin framework + * to keep looking for other DLLs that match and have a + * compatible version. + * + * Return: SUCCEED / FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5FD_check_plugin_load(const H5FD_class_t *cls, const H5PL_key_t *key, hbool_t *success) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOERR + + /* Sanity checks */ + HDassert(cls); + HDassert(key); + HDassert(success); + + /* Which kind of key are we looking for? */ + if (key->vfd.kind == H5FD_GET_DRIVER_BY_NAME) { + /* Check if plugin name matches VFD class name */ + if (cls->name && !HDstrcmp(cls->name, key->vfd.u.name)) + *success = TRUE; + } + else { + /* Sanity check */ + HDassert(key->vfd.kind == H5FD_GET_DRIVER_BY_VALUE); + + /* Check if plugin value matches VFD class value */ + if (cls->value == key->vfd.u.value) + *success = TRUE; + } + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_check_plugin_load() */ + +/*------------------------------------------------------------------------- + * Function: H5FD__get_driver_cb + * + * Purpose: Callback routine to search through registered VFDs + * + * Return: Success: H5_ITER_STOP if the class and op_data name + * members match. H5_ITER_CONT otherwise. + * Failure: Can't fail + * + *------------------------------------------------------------------------- + */ +static int +H5FD__get_driver_cb(void *obj, hid_t id, void *_op_data) +{ + H5FD_get_driver_ud_t *op_data = (H5FD_get_driver_ud_t *)_op_data; /* User data for callback */ + H5FD_class_t * cls = (H5FD_class_t *)obj; + int ret_value = H5_ITER_CONT; /* Callback return value */ + + FUNC_ENTER_STATIC_NOERR + + if (H5FD_GET_DRIVER_BY_NAME == op_data->key.kind) { + if (0 == HDstrcmp(cls->name, op_data->key.u.name)) { + op_data->found_id = id; + ret_value = H5_ITER_STOP; + } /* end if */ + } /* end if */ + else { + HDassert(H5FD_GET_DRIVER_BY_VALUE == op_data->key.kind); + if (cls->value == op_data->key.u.value) { + op_data->found_id = id; + ret_value = H5_ITER_STOP; + } /* end if */ + } /* end else */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD__get_driver_cb() */ + +/*------------------------------------------------------------------------- + * Function: H5FD_register_driver_by_name + * + * Purpose: Registers a new VFD as a member of the virtual file driver + * class. + * + * Return: Success: A VFD ID which is good until the library is + * closed. + * + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +hid_t +H5FD_register_driver_by_name(const char *name, hbool_t app_ref) +{ + htri_t driver_is_registered = FALSE; + hid_t driver_id = H5I_INVALID_HID; + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_NOAPI(H5I_INVALID_HID) + + /* Check if driver is already registered */ + if ((driver_is_registered = H5FD_is_driver_registered_by_name(name, &driver_id)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_BADITER, H5I_INVALID_HID, "can't check if driver is already registered") + + /* If driver is already registered, increment ref count on ID and return ID */ + if (driver_is_registered) { + HDassert(driver_id >= 0); + + if (H5I_inc_ref(driver_id, app_ref) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTINC, H5I_INVALID_HID, "unable to increment ref count on VFD") + } /* end if */ + else { + H5PL_key_t key; + const H5FD_class_t *cls; + + /* Try loading the driver */ + key.vfd.kind = H5FD_GET_DRIVER_BY_NAME; + key.vfd.u.name = name; + if (NULL == (cls = (const H5FD_class_t *)H5PL_load(H5PL_TYPE_VFD, &key))) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, H5I_INVALID_HID, "unable to load VFD") + + /* Register the driver we loaded */ + if ((driver_id = H5FD_register(cls, sizeof(*cls), app_ref)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VFD ID") + } /* end else */ + + ret_value = driver_id; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_register_driver_by_name() */ + +/*------------------------------------------------------------------------- + * Function: H5FD_register_driver_by_value + * + * Purpose: Registers a new VFD as a member of the virtual file driver + * class. + * + * Return: Success: A VFD ID which is good until the library is + * closed. + * + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +hid_t +H5FD_register_driver_by_value(H5FD_class_value_t value, hbool_t app_ref) +{ + htri_t driver_is_registered = FALSE; + hid_t driver_id = H5I_INVALID_HID; + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_NOAPI(H5I_INVALID_HID) + + /* Check if driver is already registered */ + if ((driver_is_registered = H5FD_is_driver_registered_by_value(value, &driver_id)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_BADITER, H5I_INVALID_HID, "can't check if driver is already registered") + + /* If driver is already registered, increment ref count on ID and return ID */ + if (driver_is_registered) { + HDassert(driver_id >= 0); + + if (H5I_inc_ref(driver_id, app_ref) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTINC, H5I_INVALID_HID, "unable to increment ref count on VFD") + } /* end if */ + else { + H5PL_key_t key; + const H5FD_class_t *cls; + + /* Try loading the driver */ + key.vfd.kind = H5FD_GET_DRIVER_BY_VALUE; + key.vfd.u.value = value; + if (NULL == (cls = (const H5FD_class_t *)H5PL_load(H5PL_TYPE_VFD, &key))) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, H5I_INVALID_HID, "unable to load VFD") + + /* Register the driver we loaded */ + if ((driver_id = H5FD_register(cls, sizeof(*cls), app_ref)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VFD ID") + } /* end else */ + + ret_value = driver_id; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_register_driver_by_value() */ + +/*------------------------------------------------------------------------- + * Function: H5FD_is_driver_registered_by_name + * + * Purpose: Checks if a driver with a particular name is registered. + * If `registered_id` is non-NULL and a driver with the + * specified name has been registered, the driver's ID will be + * returned in `registered_id`. + * + * Return: >0 if a VFD with that name has been registered + * 0 if a VFD with that name has NOT been registered + * <0 on errors + * + *------------------------------------------------------------------------- + */ +htri_t +H5FD_is_driver_registered_by_name(const char *driver_name, hid_t *registered_id) +{ + H5FD_get_driver_ud_t op_data; /* Callback info for driver search */ + htri_t ret_value = FALSE; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Set up op data for iteration */ + op_data.key.kind = H5FD_GET_DRIVER_BY_NAME; + op_data.key.u.name = driver_name; + op_data.found_id = H5I_INVALID_HID; + + /* Find driver with name */ + if (H5I_iterate(H5I_VFL, H5FD__get_driver_cb, &op_data, FALSE) < 0) + HGOTO_ERROR(H5E_VFL, H5E_BADITER, FAIL, "can't iterate over VFDs") + + /* Found a driver with that name */ + if (op_data.found_id != H5I_INVALID_HID) { + if (registered_id) + *registered_id = op_data.found_id; + ret_value = TRUE; + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_is_driver_registered_by_name() */ + +/*------------------------------------------------------------------------- + * Function: H5FD_is_driver_registered_by_value + * + * Purpose: Checks if a driver with a particular value (ID) is + * registered. If `registered_id` is non-NULL and a driver + * with the specified value has been registered, the driver's + * ID will be returned in `registered_id`. + * + * Return: >0 if a VFD with that value has been registered + * 0 if a VFD with that value has NOT been registered + * <0 on errors + * + *------------------------------------------------------------------------- + */ +htri_t +H5FD_is_driver_registered_by_value(H5FD_class_value_t driver_value, hid_t *registered_id) +{ + H5FD_get_driver_ud_t op_data; /* Callback info for driver search */ + htri_t ret_value = FALSE; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Set up op data for iteration */ + op_data.key.kind = H5FD_GET_DRIVER_BY_VALUE; + op_data.key.u.value = driver_value; + op_data.found_id = H5I_INVALID_HID; + + /* Find driver with value */ + if (H5I_iterate(H5I_VFL, H5FD__get_driver_cb, &op_data, FALSE) < 0) + HGOTO_ERROR(H5E_VFL, H5E_BADITER, FAIL, "can't iterate over VFDs") + + /* Found a driver with that value */ + if (op_data.found_id != H5I_INVALID_HID) { + if (registered_id) + *registered_id = op_data.found_id; + ret_value = TRUE; + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_is_driver_registered_by_value() */ + +/*------------------------------------------------------------------------- + * Function: H5FD_get_driver_id_by_name + * + * Purpose: Retrieves the ID for a registered VFL driver. + * + * Return: Positive if the VFL driver has been registered + * Negative on error (if the driver is not a valid driver or + * is not registered) + * + *------------------------------------------------------------------------- + */ +hid_t +H5FD_get_driver_id_by_name(const char *name, hbool_t is_api) +{ + H5FD_get_driver_ud_t op_data; + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_NOAPI(H5I_INVALID_HID) + + /* Set up op data for iteration */ + op_data.key.kind = H5FD_GET_DRIVER_BY_NAME; + op_data.key.u.name = name; + op_data.found_id = H5I_INVALID_HID; + + /* Find driver with specified name */ + if (H5I_iterate(H5I_VFL, H5FD__get_driver_cb, &op_data, FALSE) < 0) + HGOTO_ERROR(H5E_VFL, H5E_BADITER, H5I_INVALID_HID, "can't iterate over VFL drivers") + + /* Found a driver with that name */ + if (op_data.found_id != H5I_INVALID_HID) { + ret_value = op_data.found_id; + if (H5I_inc_ref(ret_value, is_api) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTINC, H5I_INVALID_HID, "unable to increment ref count on VFL driver") + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_get_driver_id_by_name() */ + +/*------------------------------------------------------------------------- + * Function: H5FD_get_driver_id_by_value + * + * Purpose: Retrieves the ID for a registered VFL driver. + * + * Return: Positive if the VFL driver has been registered + * Negative on error (if the driver is not a valid driver or + * is not registered) + * + *------------------------------------------------------------------------- + */ +hid_t +H5FD_get_driver_id_by_value(H5FD_class_value_t value, hbool_t is_api) +{ + H5FD_get_driver_ud_t op_data; + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_NOAPI(H5I_INVALID_HID) + + /* Set up op data for iteration */ + op_data.key.kind = H5FD_GET_DRIVER_BY_VALUE; + op_data.key.u.value = value; + op_data.found_id = H5I_INVALID_HID; + + /* Find driver with specified value */ + if (H5I_iterate(H5I_VFL, H5FD__get_driver_cb, &op_data, FALSE) < 0) + HGOTO_ERROR(H5E_VFL, H5E_BADITER, H5I_INVALID_HID, "can't iterate over VFL drivers") + + /* Found a driver with that value */ + if (op_data.found_id != H5I_INVALID_HID) { + ret_value = op_data.found_id; + if (H5I_inc_ref(ret_value, is_api) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTINC, H5I_INVALID_HID, "unable to increment ref count on VFL driver") + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_get_driver_id_by_value() */ diff --git a/src/H5FDlog.c b/src/H5FDlog.c index f996b9e..4d2e705 100644 --- a/src/H5FDlog.c +++ b/src/H5FDlog.c @@ -180,6 +180,8 @@ static herr_t H5FD__log_unlock(H5FD_t *_file); static herr_t H5FD__log_delete(const char *filename, hid_t fapl_id); static const H5FD_class_t H5FD_log_g = { + H5FD_CLASS_VERSION, /* struct version */ + H5FD_LOG_VALUE, /* value */ "log", /* name */ MAXADDR, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -207,51 +209,26 @@ static const H5FD_class_t H5FD_log_g = { H5FD__log_get_handle, /* get_handle */ H5FD__log_read, /* read */ H5FD__log_write, /* write */ + NULL, /* read vector */ + NULL, /* write vector */ + NULL, /* read_selection */ + NULL, /* write_selection */ NULL, /* flush */ H5FD__log_truncate, /* truncate */ H5FD__log_lock, /* lock */ H5FD__log_unlock, /* unlock */ H5FD__log_delete, /* del */ + NULL, /* ctl */ H5FD_FLMAP_DICHOTOMY /* fl_map */ }; +/* Default configuration, if none provided */ +static const H5FD_log_fapl_t H5FD_log_default_config_g = {NULL, H5FD_LOG_LOC_IO | H5FD_LOG_ALLOC, 4096}; + /* Declare a free list to manage the H5FD_log_t struct */ H5FL_DEFINE_STATIC(H5FD_log_t); /*------------------------------------------------------------------------- - * Function: H5FD__init_package - * - * Purpose: Initializes any interface-specific data or routines. - * - * Return: Non-negative on success/Negative on failure - * - *------------------------------------------------------------------------- - */ -static herr_t -H5FD__init_package(void) -{ - char * lock_env_var = NULL; /* Environment variable pointer */ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_STATIC - - /* Check the use disabled file locks environment variable */ - lock_env_var = HDgetenv("HDF5_USE_FILE_LOCKING"); - if (lock_env_var && !HDstrcmp(lock_env_var, "BEST_EFFORT")) - ignore_disabled_file_locks_s = TRUE; /* Override: Ignore disabled locks */ - else if (lock_env_var && (!HDstrcmp(lock_env_var, "TRUE") || !HDstrcmp(lock_env_var, "1"))) - ignore_disabled_file_locks_s = FALSE; /* Override: Don't ignore disabled locks */ - else - ignore_disabled_file_locks_s = FAIL; /* Environment variable not set, or not set correctly */ - - if (H5FD_log_init() < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "unable to initialize log VFD") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5FD__init_package() */ - -/*------------------------------------------------------------------------- * Function: H5FD_log_init * * Purpose: Initialize this driver by registering the driver with the @@ -268,9 +245,19 @@ done: hid_t H5FD_log_init(void) { - hid_t ret_value = H5I_INVALID_HID; /* Return value */ + char *lock_env_var = NULL; /* Environment variable pointer */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ - FUNC_ENTER_NOAPI(H5I_INVALID_HID) + FUNC_ENTER_NOAPI_NOERR + + /* Check the use disabled file locks environment variable */ + lock_env_var = HDgetenv(HDF5_USE_FILE_LOCKING); + if (lock_env_var && !HDstrcmp(lock_env_var, "BEST_EFFORT")) + ignore_disabled_file_locks_s = TRUE; /* Override: Ignore disabled locks */ + else if (lock_env_var && (!HDstrcmp(lock_env_var, "TRUE") || !HDstrcmp(lock_env_var, "1"))) + ignore_disabled_file_locks_s = FALSE; /* Override: Don't ignore disabled locks */ + else + ignore_disabled_file_locks_s = FAIL; /* Environment variable not set, or not set correctly */ if (H5I_VFL != H5I_get_type(H5FD_LOG_g)) H5FD_LOG_g = H5FD_register(&H5FD_log_g, sizeof(H5FD_class_t), FALSE); @@ -278,7 +265,6 @@ H5FD_log_init(void) /* Set return value */ ret_value = H5FD_LOG_g; -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD_log_init() */ @@ -347,7 +333,7 @@ H5Pset_fapl_log(hid_t fapl_id, const char *logfile, unsigned long long flags, si fa.flags = flags; fa.buf_size = buf_size; - ret_value = H5P_set_driver(plist, H5FD_LOG, &fa); + ret_value = H5P_set_driver(plist, H5FD_LOG, &fa, NULL); done: if (fa.logfile) @@ -482,10 +468,11 @@ static H5FD_t * H5FD__log_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr) { H5FD_log_t * file = NULL; - H5P_genplist_t * plist; /* Property list */ - const H5FD_log_fapl_t *fa; /* File access property list information */ - int fd = -1; /* File descriptor */ - int o_flags; /* Flags for open() call */ + H5P_genplist_t * plist; /* Property list */ + const H5FD_log_fapl_t *fa; /* File access property list information */ + H5FD_log_fapl_t default_fa = H5FD_log_default_config_g; + int fd = -1; /* File descriptor */ + int o_flags; /* Flags for open() call */ #ifdef H5_HAVE_WIN32_API struct _BY_HANDLE_FILE_INFORMATION fileinfo; #endif @@ -523,8 +510,10 @@ H5FD__log_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr) /* Get the driver specific information */ if (NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list") - if (NULL == (fa = (const H5FD_log_fapl_t *)H5P_peek_driver_info(plist))) - HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, NULL, "bad VFL driver info") + if (NULL == (fa = (const H5FD_log_fapl_t *)H5P_peek_driver_info(plist))) { + /* Use default driver configuration*/ + fa = &default_fa; + } /* Start timer for open() call */ if (fa->flags & H5FD_LOG_TIME_OPEN) @@ -1559,7 +1548,7 @@ H5FD__log_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id, ha HDfprintf(file->logfp, "%10" PRIuHADDR "-%10" PRIuHADDR " (%10zu bytes) (%s) Written", orig_addr, (orig_addr + orig_size) - 1, orig_size, flavors[type]); - /* Check if this is the first write into a "default" section, grabbed by the metadata agregation + /* Check if this is the first write into a "default" section, grabbed by the metadata aggregation * algorithm */ if (file->fa.flags & H5FD_LOG_FLAVOR) { if ((H5FD_mem_t)file->flavor[orig_addr] == H5FD_MEM_DEFAULT) { diff --git a/src/H5FDlog.h b/src/H5FDlog.h index 969c091..a916fec 100644 --- a/src/H5FDlog.h +++ b/src/H5FDlog.h @@ -20,7 +20,8 @@ #ifndef H5FDlog_H #define H5FDlog_H -#define H5FD_LOG (H5FD_log_init()) +#define H5FD_LOG (H5FDperform_init(H5FD_log_init)) +#define H5FD_LOG_VALUE H5_VFD_LOG /* Flags for H5Pset_fapl_log() */ /* Flags for tracking 'meta' operations (truncate) */ diff --git a/src/H5FDmirror.c b/src/H5FDmirror.c index 8cbeff6..0ab5345 100644 --- a/src/H5FDmirror.c +++ b/src/H5FDmirror.c @@ -160,6 +160,8 @@ static herr_t H5FD__mirror_unlock(H5FD_t *_file); static herr_t H5FD__mirror_verify_reply(H5FD_mirror_t *file); static const H5FD_class_t H5FD_mirror_g = { + H5FD_CLASS_VERSION, /* struct version */ + H5FD_MIRROR_VALUE, /* value */ "mirror", /* name */ MAXADDR, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -187,11 +189,16 @@ static const H5FD_class_t H5FD_mirror_g = { NULL, /* get_handle */ H5FD__mirror_read, /* read */ H5FD__mirror_write, /* write */ + NULL, /* read_vector */ + NULL, /* write_vector */ + NULL, /* read_selection */ + NULL, /* write_selection */ NULL, /* flush */ H5FD__mirror_truncate, /* truncate */ H5FD__mirror_lock, /* lock */ H5FD__mirror_unlock, /* unlock */ NULL, /* del */ + NULL, /* ctl */ H5FD_FLMAP_DICHOTOMY /* fl_map */ }; @@ -204,30 +211,6 @@ H5FL_DEFINE_STATIC(H5FD_mirror_t); /* Declare a free list to manage the H5FD_mirror_xmit_open_t struct */ H5FL_DEFINE_STATIC(H5FD_mirror_xmit_open_t); -/*------------------------------------------------------------------------- - * Function: H5FD__init_package - * - * Purpose: Initializes any interface-specific data or routines. - * - * Return: Non-negative on success/Negative on failure - *------------------------------------------------------------------------- - */ -static herr_t -H5FD__init_package(void) -{ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_STATIC - - LOG_OP_CALL(__func__); - - if (H5FD_mirror_init() < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "unable to initialize mirror VFD"); - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5FD__init_package() */ - /* ------------------------------------------------------------------------- * Function: H5FD_mirror_init * @@ -247,9 +230,11 @@ H5FD_mirror_init(void) LOG_OP_CALL(__func__); - if (H5I_VFL != H5I_get_type(H5FD_MIRROR_g)) + if (H5I_VFL != H5I_get_type(H5FD_MIRROR_g)) { H5FD_MIRROR_g = H5FD_register(&H5FD_mirror_g, sizeof(H5FD_class_t), FALSE); - + if (H5I_INVALID_HID == H5FD_MIRROR_g) + HGOTO_ERROR(H5E_ID, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register mirror"); + } ret_value = H5FD_MIRROR_g; done: @@ -1167,7 +1152,7 @@ done: /* ------------------------------------------------------------------------- * Function: H5FD__mirror_fapl_get * - * Purpose: Get the file access propety list which could be used to create + * Purpose: Get the file access property list which could be used to create * an identical file. * * Return: Success: pointer to the new file access property list value. @@ -1335,7 +1320,7 @@ H5Pset_fapl_mirror(hid_t fapl_id, H5FD_mirror_fapl_t *fa) if (H5FD_MIRROR_CURR_FAPL_T_VERSION != fa->version) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unknown fapl_t version"); - ret_value = H5P_set_driver(plist, H5FD_MIRROR, (const void *)fa); + ret_value = H5P_set_driver(plist, H5FD_MIRROR, (const void *)fa, NULL); done: FUNC_LEAVE_API(ret_value) diff --git a/src/H5FDmirror.h b/src/H5FDmirror.h index 49e24c1..b196b2b 100644 --- a/src/H5FDmirror.h +++ b/src/H5FDmirror.h @@ -19,7 +19,8 @@ #ifdef H5_HAVE_MIRROR_VFD -#define H5FD_MIRROR (H5FD_mirror_init()) +#define H5FD_MIRROR (H5FDperform_init(H5FD_mirror_init)) +#define H5FD_MIRROR_VALUE H5_VFD_MIRROR #ifdef __cplusplus extern "C" { @@ -33,7 +34,7 @@ extern "C" { /* --------------------------------------------------------------------------- * Structure: H5FD_mirror_fapl_t * - * Used to pass configuraiton information to the Mirror VFD. + * Used to pass configuration information to the Mirror VFD. * Populate components as appropriate and pass structure pointer to * `H5Pset_fapl_mirror()`. * diff --git a/src/H5FDmirror_priv.h b/src/H5FDmirror_priv.h index 21de97b..f647c21 100644 --- a/src/H5FDmirror_priv.h +++ b/src/H5FDmirror_priv.h @@ -28,10 +28,10 @@ extern "C" { * = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ -/* The maximum allowed size for a receiving buffer when accepting bytes to +/* Define the maximum allowed size for a receiving buffer when accepting bytes to * write. Writes larger than this size are performed by multiple accept-write * steps by the Writer. */ -#define H5FD_MIRROR_DATA_BUFFER_MAX H5_GB /* 1 Gigabyte */ +#define H5FD_MIRROR_DATA_BUFFER_MAX (1024 * 1024 * 1024) /* 1 Gigabyte */ #define H5FD_MIRROR_XMIT_CURR_VERSION 1 #define H5FD_MIRROR_XMIT_MAGIC 0x87F8005B @@ -80,7 +80,7 @@ extern "C" { * * `magic` (uint32_t) * A "unique" number identifying the structure and endianness of - * transmitting maching. + * transmitting machine. * Must be set to H5FD_MIRROR_XMIT_MAGIC native to the VFD "sender". * * `version` (uint8_t) @@ -214,13 +214,13 @@ typedef struct H5FD_mirror_xmit_open_t { * * `status` (uint32_t) * Number indicating whether the command was successful or if an - * occured. + * occurred. * Allowed values are H5FD_MIRROR_STATUS_OK and * H5FD_MIRROR_STATUS_ERROR. * * `message` (char[]) * Error message. Populated if and only if there was a problem. - * It is possible that a message may reach the end of the alloted + * It is possible that a message may reach the end of the allotted * space without a NULL terminator -- the onus is on the programmer to * handle this situation. * diff --git a/src/H5FDmpi.c b/src/H5FDmpi.c index 048b8f3..7eb1463 100644 --- a/src/H5FDmpi.c +++ b/src/H5FDmpi.c @@ -41,26 +41,42 @@ * Programmer: Quincey Koziol * Friday, January 30, 2004 * + * Changes: Reworked function to use the ctl callback so we can get + * rid of H5FD_class_mpi_t. Since there are no real limits + * on what the ctl callback can do, its file parameter can't + * be constant. Thus, I had to remove the const qualifier + * on this functions file parameter as well. Note also the + * circumlocution required to use the ctl callbacks output + * parameter to pass back the rank without introducing + * compiler warnings. + * JRM -- 8/13/21 + * *------------------------------------------------------------------------- */ int -H5FD_mpi_get_rank(const H5FD_t *file) +H5FD_mpi_get_rank(H5FD_t *file) { - const H5FD_class_mpi_t *cls; - - int ret_value; + const H5FD_class_t *cls; + uint64_t flags = H5FD_CTL__FAIL_IF_UNKNOWN_FLAG | H5FD_CTL__ROUTE_TO_TERMINAL_VFD_FLAG; + int rank = -1; + void * rank_ptr = (void *)(&rank); + int ret_value; FUNC_ENTER_NOAPI(FAIL) HDassert(file); - cls = (const H5FD_class_mpi_t *)(file->cls); + cls = (const H5FD_class_t *)(file->cls); HDassert(cls); - HDassert(cls->get_rank); /* All MPI drivers must implement this */ + HDassert(cls->ctl); /* All MPI drivers must implement this */ /* Dispatch to driver */ - if ((ret_value = (cls->get_rank)(file)) < 0) + if ((cls->ctl)(file, H5FD_CTL__GET_MPI_RANK_OPCODE, flags, NULL, &rank_ptr) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "driver get_rank request failed") + HDassert(rank >= 0); + + ret_value = rank; + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD_mpi_get_rank() */ @@ -77,25 +93,43 @@ done: * Programmer: Quincey Koziol * Friday, January 30, 2004 * + * Changes: Reworked function to use the ctl callback so we can get + * rid of H5FD_class_mpi_t. Since there are no real limits + * on what the ctl callback can do, its file parameter can't + * be constant. Thus, I had to remove the const qualifier + * on this functions file parameter as well. Note also the + * circumlocution required to use the ctl callbacks output + * parameter to pass back the rank without introducing + * compiler warnings. + * JRM -- 8/13/21 + * *------------------------------------------------------------------------- */ int -H5FD_mpi_get_size(const H5FD_t *file) +H5FD_mpi_get_size(H5FD_t *file) { - const H5FD_class_mpi_t *cls; - int ret_value; + const H5FD_class_t *cls; + uint64_t flags = H5FD_CTL__FAIL_IF_UNKNOWN_FLAG | H5FD_CTL__ROUTE_TO_TERMINAL_VFD_FLAG; + int size = 0; + void * size_ptr = (void *)(&size); + int ret_value; FUNC_ENTER_NOAPI(FAIL) HDassert(file); - cls = (const H5FD_class_mpi_t *)(file->cls); + cls = (const H5FD_class_t *)(file->cls); HDassert(cls); - HDassert(cls->get_size); /* All MPI drivers must implement this */ + HDassert(cls->ctl); /* All MPI drivers must implement this */ /* Dispatch to driver */ - if ((ret_value = (cls->get_size)(file)) < 0) + if ((cls->ctl)(file, H5FD_CTL__GET_MPI_SIZE_OPCODE, flags, NULL, &size_ptr) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "driver get_size request failed") + if (0 >= size) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "driver get_size request returned bad value") + + ret_value = size; + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD_mpi_get_size() */ @@ -112,25 +146,43 @@ done: * Programmer: Quincey Koziol * Friday, January 30, 2004 * + * Changes: Reworked function to use the ctl callback so we can get + * rid of H5FD_class_mpi_t. Since there are no real limits + * on what the ctl callback can do, its file parameter can't + * be constant. Thus, I had to remove the const qualifier + * on this functions file parameter as well. Note also the + * circumlocution required to use the ctl callbacks output + * parameter to pass back the rank without introducing + * compiler warnings. + * JRM -- 8/13/21 + * *------------------------------------------------------------------------- */ MPI_Comm -H5FD_mpi_get_comm(const H5FD_t *file) +H5FD_mpi_get_comm(H5FD_t *file) { - const H5FD_class_mpi_t *cls; - MPI_Comm ret_value; + const H5FD_class_t *cls; + uint64_t flags = H5FD_CTL__FAIL_IF_UNKNOWN_FLAG | H5FD_CTL__ROUTE_TO_TERMINAL_VFD_FLAG; + MPI_Comm comm = MPI_COMM_NULL; + void * comm_ptr = (void *)(&comm); + MPI_Comm ret_value; FUNC_ENTER_NOAPI(MPI_COMM_NULL) HDassert(file); - cls = (const H5FD_class_mpi_t *)(file->cls); + cls = (const H5FD_class_t *)(file->cls); HDassert(cls); - HDassert(cls->get_comm); /* All MPI drivers must implement this */ + HDassert(cls->ctl); /* All MPI drivers must implement this */ /* Dispatch to driver */ - if ((ret_value = (cls->get_comm)(file)) == MPI_COMM_NULL) + if ((cls->ctl)(file, H5FD_CTL__GET_MPI_COMMUNICATOR_OPCODE, flags, NULL, &comm_ptr) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTGET, MPI_COMM_NULL, "driver get_comm request failed") + if (comm == MPI_COMM_NULL) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, MPI_COMM_NULL, "driver get_comm request failed -- bad comm") + + ret_value = comm; + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD_mpi_get_comm() */ diff --git a/src/H5FDmpio.c b/src/H5FDmpio.c index dd40399..2a5e462 100644 --- a/src/H5FDmpio.c +++ b/src/H5FDmpio.c @@ -45,6 +45,9 @@ static hid_t H5FD_MPIO_g = 0; /* (Can be changed by setting "HDF5_MPI_OPT_TYPES" environment variable to '0' or '1') */ hbool_t H5FD_mpi_opt_types_g = TRUE; +/* Whether the driver initialized MPI on its own */ +hbool_t H5FD_mpi_self_initialized = FALSE; + /* * The view is set to this value */ @@ -72,66 +75,78 @@ typedef struct H5FD_mpio_t { /* Private Prototypes */ /* Callbacks */ -static herr_t H5FD__mpio_term(void); -static H5FD_t * H5FD__mpio_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr); -static herr_t H5FD__mpio_close(H5FD_t *_file); -static herr_t H5FD__mpio_query(const H5FD_t *_f1, unsigned long *flags); -static haddr_t H5FD__mpio_get_eoa(const H5FD_t *_file, H5FD_mem_t type); -static herr_t H5FD__mpio_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t addr); -static haddr_t H5FD__mpio_get_eof(const H5FD_t *_file, H5FD_mem_t type); -static herr_t H5FD__mpio_get_handle(H5FD_t *_file, hid_t fapl, void **file_handle); -static herr_t H5FD__mpio_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size, - void *buf); -static herr_t H5FD__mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size, - const void *buf); -static herr_t H5FD__mpio_flush(H5FD_t *_file, hid_t dxpl_id, hbool_t closing); -static herr_t H5FD__mpio_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing); -static herr_t H5FD__mpio_delete(const char *filename, hid_t fapl_id); -static int H5FD__mpio_mpi_rank(const H5FD_t *_file); -static int H5FD__mpio_mpi_size(const H5FD_t *_file); -static MPI_Comm H5FD__mpio_communicator(const H5FD_t *_file); +static herr_t H5FD__mpio_term(void); +static H5FD_t *H5FD__mpio_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr); +static herr_t H5FD__mpio_close(H5FD_t *_file); +static herr_t H5FD__mpio_query(const H5FD_t *_f1, unsigned long *flags); +static haddr_t H5FD__mpio_get_eoa(const H5FD_t *_file, H5FD_mem_t type); +static herr_t H5FD__mpio_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t addr); +static haddr_t H5FD__mpio_get_eof(const H5FD_t *_file, H5FD_mem_t type); +static herr_t H5FD__mpio_get_handle(H5FD_t *_file, hid_t fapl, void **file_handle); +static herr_t H5FD__mpio_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size, + void *buf); +static herr_t H5FD__mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size, + const void *buf); +static herr_t H5FD__mpio_read_vector(H5FD_t *_file, hid_t H5_ATTR_UNUSED dxpl_id, uint32_t count, + H5FD_mem_t types[], haddr_t addrs[], size_t sizes[], void *bufs[]); +static herr_t H5FD__mpio_write_vector(H5FD_t *_file, hid_t H5_ATTR_UNUSED dxpl_id, uint32_t count, + H5FD_mem_t types[], haddr_t addrs[], size_t sizes[], + const void *bufs[]); +static herr_t H5FD__mpio_flush(H5FD_t *_file, hid_t dxpl_id, hbool_t closing); +static herr_t H5FD__mpio_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing); +static herr_t H5FD__mpio_delete(const char *filename, hid_t fapl_id); +static herr_t H5FD__mpio_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void *input, + void **output); + +/* Other functions */ +static herr_t H5FD__mpio_vector_build_types( + uint32_t count, H5FD_mem_t types[], haddr_t addrs[], size_t sizes[], H5_flexible_const_ptr_t bufs[], + haddr_t *s_addrs[], size_t *s_sizes[], H5_flexible_const_ptr_t *s_bufs[], hbool_t *vector_was_sorted, + MPI_Offset *mpi_off, H5_flexible_const_ptr_t *mpi_bufs_base, int *size_i, MPI_Datatype *buf_type, + hbool_t *buf_type_created, MPI_Datatype *file_type, hbool_t *file_type_created, char *unused); /* The MPIO file driver information */ -static const H5FD_class_mpi_t H5FD_mpio_g = { - { - /* Start of superclass information */ - "mpio", /* name */ - HADDR_MAX, /* maxaddr */ - H5F_CLOSE_SEMI, /* fc_degree */ - H5FD__mpio_term, /* terminate */ - NULL, /* sb_size */ - NULL, /* sb_encode */ - NULL, /* sb_decode */ - 0, /* fapl_size */ - NULL, /* fapl_get */ - NULL, /* fapl_copy */ - NULL, /* fapl_free */ - 0, /* dxpl_size */ - NULL, /* dxpl_copy */ - NULL, /* dxpl_free */ - H5FD__mpio_open, /* open */ - H5FD__mpio_close, /* close */ - NULL, /* cmp */ - H5FD__mpio_query, /* query */ - NULL, /* get_type_map */ - NULL, /* alloc */ - NULL, /* free */ - H5FD__mpio_get_eoa, /* get_eoa */ - H5FD__mpio_set_eoa, /* set_eoa */ - H5FD__mpio_get_eof, /* get_eof */ - H5FD__mpio_get_handle, /* get_handle */ - H5FD__mpio_read, /* read */ - H5FD__mpio_write, /* write */ - H5FD__mpio_flush, /* flush */ - H5FD__mpio_truncate, /* truncate */ - NULL, /* lock */ - NULL, /* unlock */ - H5FD__mpio_delete, /* del */ - H5FD_FLMAP_DICHOTOMY /* fl_map */ - }, /* End of superclass information */ - H5FD__mpio_mpi_rank, /* get_rank */ - H5FD__mpio_mpi_size, /* get_size */ - H5FD__mpio_communicator /* get_comm */ +static const H5FD_class_t H5FD_mpio_g = { + H5FD_CLASS_VERSION, /* struct version */ + H5_VFD_MPIO, /* value */ + "mpio", /* name */ + HADDR_MAX, /* maxaddr */ + H5F_CLOSE_SEMI, /* fc_degree */ + H5FD__mpio_term, /* terminate */ + NULL, /* sb_size */ + NULL, /* sb_encode */ + NULL, /* sb_decode */ + 0, /* fapl_size */ + NULL, /* fapl_get */ + NULL, /* fapl_copy */ + NULL, /* fapl_free */ + 0, /* dxpl_size */ + NULL, /* dxpl_copy */ + NULL, /* dxpl_free */ + H5FD__mpio_open, /* open */ + H5FD__mpio_close, /* close */ + NULL, /* cmp */ + H5FD__mpio_query, /* query */ + NULL, /* get_type_map */ + NULL, /* alloc */ + NULL, /* free */ + H5FD__mpio_get_eoa, /* get_eoa */ + H5FD__mpio_set_eoa, /* set_eoa */ + H5FD__mpio_get_eof, /* get_eof */ + H5FD__mpio_get_handle, /* get_handle */ + H5FD__mpio_read, /* read */ + H5FD__mpio_write, /* write */ + H5FD__mpio_read_vector, /* read_vector */ + H5FD__mpio_write_vector, /* write_vector */ + NULL, /* read_selection */ + NULL, /* write_selection */ + H5FD__mpio_flush, /* flush */ + H5FD__mpio_truncate, /* truncate */ + NULL, /* lock */ + NULL, /* unlock */ + H5FD__mpio_delete, /* del */ + H5FD__mpio_ctl, /* ctl */ + H5FD_FLMAP_DICHOTOMY /* fl_map */ }; #ifdef H5FDmpio_DEBUG @@ -157,35 +172,6 @@ static int H5FD_mpio_debug_rank_s = -1; (H5FD_mpio_debug_rank_s < 0 || H5FD_mpio_debug_rank_s == (file)->mpi_rank) #endif -/*-------------------------------------------------------------------------- -NAME - H5FD__init_package -- Initialize interface-specific information - -USAGE - herr_t H5FD__init_package() - -RETURNS - SUCCEED/FAIL - -DESCRIPTION - Initializes any interface-specific data or routines. (Just calls - H5FD_mpio_init currently). - ---------------------------------------------------------------------------*/ -static herr_t -H5FD__init_package(void) -{ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_STATIC - - if (H5FD_mpio_init() < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "unable to initialize mpio VFD") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5FD__init_package() */ - #ifdef H5FDmpio_DEBUG /*--------------------------------------------------------------------------- @@ -219,6 +205,41 @@ H5FD__mpio_parse_debug_str(const char *s) FUNC_LEAVE_NOAPI_VOID } /* end H5FD__mpio_parse_debug_str() */ + +/*--------------------------------------------------------------------------- + * Function: H5FD__mem_t_to_str + * + * Purpose: Returns a string representing the enum value in an H5FD_mem_t + * enum + * + * Returns: H5FD_mem_t enum value string + * + *--------------------------------------------------------------------------- + */ +static const char * +H5FD__mem_t_to_str(H5FD_mem_t mem_type) +{ + switch (mem_type) { + case H5FD_MEM_NOLIST: + return "H5FD_MEM_NOLIST"; + case H5FD_MEM_DEFAULT: + return "H5FD_MEM_DEFAULT"; + case H5FD_MEM_SUPER: + return "H5FD_MEM_SUPER"; + case H5FD_MEM_BTREE: + return "H5FD_MEM_BTREE"; + case H5FD_MEM_DRAW: + return "H5FD_MEM_DRAW"; + case H5FD_MEM_GHEAP: + return "H5FD_MEM_GHEAP"; + case H5FD_MEM_LHEAP: + return "H5FD_MEM_LHEAP"; + case H5FD_MEM_OHDR: + return "H5FD_MEM_OHDR"; + default: + return "(Unknown)"; + } +} #endif /* H5FDmpio_DEBUG */ /*------------------------------------------------------------------------- @@ -239,13 +260,30 @@ hid_t H5FD_mpio_init(void) { static int H5FD_mpio_Debug_inited = 0; + char * env = NULL; hid_t ret_value = H5I_INVALID_HID; /* Return value */ FUNC_ENTER_NOAPI(H5I_INVALID_HID) /* Register the MPI-IO VFD, if it isn't already */ - if (H5I_VFL != H5I_get_type(H5FD_MPIO_g)) - H5FD_MPIO_g = H5FD_register((const H5FD_class_t *)&H5FD_mpio_g, sizeof(H5FD_class_mpi_t), FALSE); + if (H5I_VFL != H5I_get_type(H5FD_MPIO_g)) { + H5FD_MPIO_g = H5FD_register((const H5FD_class_t *)&H5FD_mpio_g, sizeof(H5FD_class_t), FALSE); + + /* Check if MPI driver has been loaded dynamically */ + env = HDgetenv(HDF5_DRIVER); + if (env && !HDstrcmp(env, "mpio")) { + int mpi_initialized = 0; + + /* Initialize MPI if not already initialized */ + if (MPI_SUCCESS != MPI_Initialized(&mpi_initialized)) + HGOTO_ERROR(H5E_VFL, H5E_UNINITIALIZED, H5I_INVALID_HID, "can't check if MPI is initialized") + if (!mpi_initialized) { + if (MPI_SUCCESS != MPI_Init(NULL, NULL)) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, H5I_INVALID_HID, "can't initialize MPI") + H5FD_mpi_self_initialized = TRUE; + } + } + } if (!H5FD_mpio_Debug_inited) { const char *s; /* String for environment variables */ @@ -292,6 +330,17 @@ H5FD__mpio_term(void) { FUNC_ENTER_STATIC_NOERR + /* Terminate MPI if the driver initialized it */ + if (H5FD_mpi_self_initialized) { + int mpi_finalized = 0; + + MPI_Finalized(&mpi_finalized); + if (!mpi_finalized) + MPI_Finalize(); + + H5FD_mpi_self_initialized = FALSE; + } + /* Reset VFL ID */ H5FD_MPIO_g = 0; @@ -353,7 +402,7 @@ H5Pset_fapl_mpio(hid_t fapl_id, MPI_Comm comm, MPI_Info info) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set MPI info object") /* duplication is done during driver setting. */ - ret_value = H5P_set_driver(plist, H5FD_MPIO, NULL); + ret_value = H5P_set_driver(plist, H5FD_MPIO, NULL, NULL); done: FUNC_LEAVE_API(ret_value) @@ -808,11 +857,16 @@ H5FD__mpio_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t H5_ATTR if (NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list") - /* Get the MPI communicator and info object from the property list */ - if (H5P_get(plist, H5F_ACS_MPI_PARAMS_COMM_NAME, &comm) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "can't get MPI communicator") - if (H5P_get(plist, H5F_ACS_MPI_PARAMS_INFO_NAME, &info) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "can't get MPI info object") + if (H5FD_mpi_self_initialized) { + comm = MPI_COMM_WORLD; + } + else { + /* Get the MPI communicator and info object from the property list */ + if (H5P_get(plist, H5F_ACS_MPI_PARAMS_COMM_NAME, &comm) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "can't get MPI communicator") + if (H5P_get(plist, H5F_ACS_MPI_PARAMS_INFO_NAME, &info) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "can't get MPI info object") + } /* Get the MPI rank of this process and the total number of processes */ if (MPI_SUCCESS != (mpi_code = MPI_Comm_rank(comm, &mpi_rank))) @@ -862,14 +916,19 @@ H5FD__mpio_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t H5_ATTR file->mpi_size = mpi_size; /* Only processor p0 will get the filesize and broadcast it. */ - if (mpi_rank == 0) + if (mpi_rank == 0) { + /* If MPI_File_get_size fails, broadcast file size as -1 to signal error */ if (MPI_SUCCESS != (mpi_code = MPI_File_get_size(fh, &file_size))) - HMPI_GOTO_ERROR(NULL, "MPI_File_get_size failed", mpi_code) + file_size = (MPI_Offset)-1; + } /* Broadcast file size */ if (MPI_SUCCESS != (mpi_code = MPI_Bcast(&file_size, (int)sizeof(MPI_Offset), MPI_BYTE, 0, comm))) HMPI_GOTO_ERROR(NULL, "MPI_Bcast failed", mpi_code) + if (file_size < 0) + HMPI_GOTO_ERROR(NULL, "MPI_File_get_size failed", mpi_code) + /* Determine if the file should be truncated */ if (file_size && (flags & H5F_ACC_TRUNC)) { /* Truncate the file */ @@ -987,7 +1046,6 @@ H5FD__mpio_query(const H5FD_t H5_ATTR_UNUSED *_file, unsigned long *flags /* out *flags |= H5FD_FEAT_AGGREGATE_METADATA; /* OK to aggregate metadata allocations */ *flags |= H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */ *flags |= H5FD_FEAT_HAS_MPI; /* This driver uses MPI */ - *flags |= H5FD_FEAT_ALLOCATE_EARLY; /* Allocate space early instead of late */ *flags |= H5FD_FEAT_DEFAULT_VFD_COMPATIBLE; /* VFD creates a file which can be opened with the default VFD */ } /* end if */ @@ -1153,7 +1211,7 @@ H5FD__mpio_read(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type, hid_t H5_ATTR_UNU MPI_Status mpi_stat; /* Status from I/O operation */ MPI_Datatype buf_type = MPI_BYTE; /* MPI description of the selection in memory */ int size_i; /* Integer copy of 'size' to read */ -#if MPI_VERSION >= 3 +#if H5_CHECK_MPI_VERSION(3, 0) MPI_Count bytes_read = 0; /* Number of bytes read in */ MPI_Count type_size; /* MPI datatype used for I/O's size */ MPI_Count io_size; /* Actual number of bytes requested */ @@ -1165,6 +1223,7 @@ H5FD__mpio_read(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type, hid_t H5_ATTR_UNU int n; #endif hbool_t use_view_this_time = FALSE; + hbool_t derived_type = FALSE; hbool_t rank0_bcast = FALSE; /* If read-with-rank0-and-bcast flag was used */ #ifdef H5FDmpio_DEBUG hbool_t H5FD_mpio_debug_t_flag = (H5FD_mpio_debug_flags_s[(int)'t'] && H5FD_MPIO_TRACE_THIS_RANK(file)); @@ -1192,8 +1251,6 @@ H5FD__mpio_read(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type, hid_t H5_ATTR_UNU if (H5FD_mpi_haddr_to_MPIOff(addr, &mpi_off /*out*/) < 0) HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "can't convert from haddr to MPI off") size_i = (int)size; - if ((hsize_t)size_i != size) - HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "can't convert from size to size_i") /* Only look for MPI views for raw data transfers */ if (type == H5FD_MEM_DRAW) { @@ -1260,10 +1317,14 @@ H5FD__mpio_read(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type, hid_t H5_ATTR_UNU rank0_bcast = TRUE; /* Read on rank 0 Bcast to other ranks */ - if (file->mpi_rank == 0) + if (file->mpi_rank == 0) { + /* If MPI_File_read_at fails, push an error, but continue + * to participate in following MPI_Bcast */ if (MPI_SUCCESS != (mpi_code = MPI_File_read_at(file->f, mpi_off, buf, size_i, buf_type, &mpi_stat))) - HMPI_GOTO_ERROR(FAIL, "MPI_File_read_at failed", mpi_code) + HMPI_DONE_ERROR(FAIL, "MPI_File_read_at failed", mpi_code) + } + if (MPI_SUCCESS != (mpi_code = MPI_Bcast(buf, size_i, buf_type, 0, file->comm))) HMPI_GOTO_ERROR(FAIL, "MPI_Bcast failed", mpi_code) } /* end if */ @@ -1293,6 +1354,21 @@ H5FD__mpio_read(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type, hid_t H5_ATTR_UNU HMPI_GOTO_ERROR(FAIL, "MPI_File_set_view failed", mpi_code) } /* end if */ else { + if (size != (hsize_t)size_i) { + /* If HERE, then we need to work around the integer size limit + * of 2GB. The input size_t size variable cannot fit into an integer, + * but we can get around that limitation by creating a different datatype + * and then setting the integer size (or element count) to 1 when using + * the derived_type. + */ + + if (H5_mpio_create_large_type(size, 0, MPI_BYTE, &buf_type) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "can't create MPI-I/O datatype") + + derived_type = TRUE; + size_i = 1; + } + #ifdef H5FDmpio_DEBUG if (H5FD_mpio_debug_r_flag) HDfprintf(stderr, "%s: (%d) doing MPI independent IO\n", __func__, file->mpi_rank); @@ -1306,12 +1382,22 @@ H5FD__mpio_read(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type, hid_t H5_ATTR_UNU /* Only retrieve bytes read if this rank _actually_ participated in I/O */ if (!rank0_bcast || (rank0_bcast && file->mpi_rank == 0)) { /* How many bytes were actually read? */ -#if MPI_VERSION >= 3 - if (MPI_SUCCESS != (mpi_code = MPI_Get_elements_x(&mpi_stat, buf_type, &bytes_read))) +#if H5_CHECK_MPI_VERSION(3, 0) + if (MPI_SUCCESS != (mpi_code = MPI_Get_elements_x(&mpi_stat, buf_type, &bytes_read))) { #else - if (MPI_SUCCESS != (mpi_code = MPI_Get_elements(&mpi_stat, MPI_BYTE, &bytes_read))) + if (MPI_SUCCESS != (mpi_code = MPI_Get_elements(&mpi_stat, MPI_BYTE, &bytes_read))) { #endif - HMPI_GOTO_ERROR(FAIL, "MPI_Get_elements failed", mpi_code) + if (rank0_bcast && file->mpi_rank == 0) { + /* If MPI_Get_elements(_x) fails for a rank 0 bcast strategy, + * push an error, but continue to participate in the following + * MPI_Bcast. + */ + bytes_read = -1; + HMPI_DONE_ERROR(FAIL, "MPI_Get_elements failed", mpi_code) + } + else + HMPI_GOTO_ERROR(FAIL, "MPI_Get_elements failed", mpi_code) + } } /* end if */ /* If the rank0-bcast feature was used, broadcast the # of bytes read to @@ -1321,7 +1407,7 @@ H5FD__mpio_read(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type, hid_t H5_ATTR_UNU * of the data. (QAK - 2019/1/2) */ if (rank0_bcast) -#if MPI_VERSION >= 3 +#if H5_CHECK_MPI_VERSION(3, 0) if (MPI_SUCCESS != MPI_Bcast(&bytes_read, 1, MPI_COUNT, 0, file->comm)) #else if (MPI_SUCCESS != MPI_Bcast(&bytes_read, 1, MPI_INT, 0, file->comm)) @@ -1329,7 +1415,7 @@ H5FD__mpio_read(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type, hid_t H5_ATTR_UNU HMPI_GOTO_ERROR(FAIL, "MPI_Bcast failed", 0) /* Get the type's size */ -#if MPI_VERSION >= 3 +#if H5_CHECK_MPI_VERSION(3, 0) if (MPI_SUCCESS != (mpi_code = MPI_Type_size_x(buf_type, &type_size))) #else if (MPI_SUCCESS != (mpi_code = MPI_Type_size(buf_type, &type_size))) @@ -1345,8 +1431,8 @@ H5FD__mpio_read(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type, hid_t H5_ATTR_UNU #ifdef H5FDmpio_DEBUG if (H5FD_mpio_debug_r_flag) - HDfprintf(stderr, "%s: (%d) mpi_off = %ld bytes_read = %lld\n", __func__, file->mpi_rank, - (long)mpi_off, bytes_read); + HDfprintf(stderr, "%s: (%d) mpi_off = %ld bytes_read = %lld type = %s\n", __func__, file->mpi_rank, + (long)mpi_off, (long long)bytes_read, H5FD__mem_t_to_str(type)); #endif /* @@ -1356,6 +1442,9 @@ H5FD__mpio_read(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type, hid_t H5_ATTR_UNU HDmemset((char *)buf + bytes_read, 0, (size_t)n); done: + if (derived_type) + MPI_Type_free(&buf_type); + #ifdef H5FDmpio_DEBUG if (H5FD_mpio_debug_t_flag) HDfprintf(stderr, "%s: (%d) Leaving\n", __func__, file->mpi_rank); @@ -1393,7 +1482,7 @@ H5FD__mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id, h MPI_Offset mpi_off; MPI_Status mpi_stat; /* Status from I/O operation */ MPI_Datatype buf_type = MPI_BYTE; /* MPI description of the selection in memory */ -#if MPI_VERSION >= 3 +#if H5_CHECK_MPI_VERSION(3, 0) MPI_Count bytes_written; MPI_Count type_size; /* MPI datatype used for I/O's size */ MPI_Count io_size; /* Actual number of bytes requested */ @@ -1468,20 +1557,6 @@ H5FD__mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id, h */ mpi_off = 0; } /* end if */ - else if (size != (hsize_t)size_i) { - /* If HERE, then we need to work around the integer size limit - * of 2GB. The input size_t size variable cannot fit into an integer, - * but we can get around that limitation by creating a different datatype - * and then setting the integer size (or element count) to 1 when using - * the derived_type. - */ - - if (H5_mpio_create_large_type(size, 0, MPI_BYTE, &buf_type) < 0) - HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "can't create MPI-I/O datatype") - - derived_type = TRUE; - size_i = 1; - } /* Write the data. */ if (use_view_this_time) { @@ -1527,6 +1602,21 @@ H5FD__mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id, h HMPI_GOTO_ERROR(FAIL, "MPI_File_set_view failed", mpi_code) } /* end if */ else { + if (size != (hsize_t)size_i) { + /* If HERE, then we need to work around the integer size limit + * of 2GB. The input size_t size variable cannot fit into an integer, + * but we can get around that limitation by creating a different datatype + * and then setting the integer size (or element count) to 1 when using + * the derived_type. + */ + + if (H5_mpio_create_large_type(size, 0, MPI_BYTE, &buf_type) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "can't create MPI-I/O datatype") + + derived_type = TRUE; + size_i = 1; + } + #ifdef H5FDmpio_DEBUG if (H5FD_mpio_debug_w_flag) HDfprintf(stderr, "%s: (%d) doing MPI independent IO\n", __func__, file->mpi_rank); @@ -1538,7 +1628,7 @@ H5FD__mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id, h } /* end else */ /* How many bytes were actually written? */ -#if MPI_VERSION >= 3 +#if H5_CHECK_MPI_VERSION(3, 0) if (MPI_SUCCESS != (mpi_code = MPI_Get_elements_x(&mpi_stat, buf_type, &bytes_written))) #else if (MPI_SUCCESS != (mpi_code = MPI_Get_elements(&mpi_stat, MPI_BYTE, &bytes_written))) @@ -1546,7 +1636,7 @@ H5FD__mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id, h HMPI_GOTO_ERROR(FAIL, "MPI_Get_elements failed", mpi_code) /* Get the type's size */ -#if MPI_VERSION >= 3 +#if H5_CHECK_MPI_VERSION(3, 0) if (MPI_SUCCESS != (mpi_code = MPI_Type_size_x(buf_type, &type_size))) #else if (MPI_SUCCESS != (mpi_code = MPI_Type_size(buf_type, &type_size))) @@ -1562,8 +1652,8 @@ H5FD__mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id, h #ifdef H5FDmpio_DEBUG if (H5FD_mpio_debug_w_flag) - HDfprintf(stderr, "%s: (%d) mpi_off = %ld bytes_written = %lld\n", __func__, file->mpi_rank, - (long)mpi_off, bytes_written); + HDfprintf(stderr, "%s: (%d) mpi_off = %ld bytes_written = %lld type = %s\n", __func__, + file->mpi_rank, (long)mpi_off, (long long)bytes_written, H5FD__mem_t_to_str(type)); #endif /* Each process will keep track of its perceived EOF value locally, and @@ -1590,6 +1680,1050 @@ done: } /* end H5FD__mpio_write() */ /*------------------------------------------------------------------------- + * Function: H5FD__mpio_vector_build_types + * + * Purpose: Build MPI datatypes and calculate offset, base buffer, and + * size for MPIO vector I/O. Spun off from common code in + * H5FD__mpio_vector_read() and H5FD__mpio_vector_write(). + * + * Return: Success: SUCCEED. + * Failure: FAIL. + * + * Programmer: Neil Fortner + * March 14, 2022 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD__mpio_vector_build_types(uint32_t count, H5FD_mem_t types[], haddr_t addrs[], size_t sizes[], + H5_flexible_const_ptr_t bufs[], haddr_t *s_addrs[], size_t *s_sizes[], + H5_flexible_const_ptr_t *s_bufs[], hbool_t *vector_was_sorted, + MPI_Offset *mpi_off, H5_flexible_const_ptr_t *mpi_bufs_base, int *size_i, + MPI_Datatype *buf_type, hbool_t *buf_type_created, MPI_Datatype *file_type, + hbool_t *file_type_created, char *unused) +{ + hsize_t bigio_count; /* Transition point to create derived type */ + hbool_t fixed_size = FALSE; + size_t size; + H5FD_mem_t * s_types = NULL; + int * mpi_block_lengths = NULL; + MPI_Aint mpi_bufs_base_Aint; + MPI_Aint * mpi_bufs = NULL; + MPI_Aint * mpi_displacements = NULL; + MPI_Datatype *sub_types = NULL; + uint8_t * sub_types_created = NULL; + int i; + int j; + int mpi_code; /* MPI return code */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC + + /* Sanity checks */ + HDassert(s_sizes); + HDassert(s_bufs); + HDassert(vector_was_sorted); + HDassert(*vector_was_sorted); + HDassert(mpi_off); + HDassert(mpi_bufs_base); + HDassert(size_i); + HDassert(buf_type); + HDassert(buf_type_created); + HDassert(!*buf_type_created); + HDassert(file_type); + HDassert(file_type_created); + HDassert(!*file_type_created); + HDassert(unused); + + /* Get bio I/O transition point (may be lower than 2G for testing) */ + bigio_count = H5_mpi_get_bigio_count(); + + if (count == 1) { + /* Single block. Just use a series of MPI_BYTEs for the file view. + */ + *size_i = (int)sizes[0]; + *buf_type = MPI_BYTE; + *file_type = MPI_BYTE; + *mpi_bufs_base = bufs[0]; + + /* Setup s_addrs, s_sizes and s_bufs (needed for incomplete read filling code and eof + * calculation code) */ + *s_addrs = addrs; + *s_sizes = sizes; + *s_bufs = bufs; + + /* some numeric conversions */ + if (H5FD_mpi_haddr_to_MPIOff(addrs[0], mpi_off) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "can't set MPI offset") + + /* Check for size overflow */ + if (sizes[0] > bigio_count) { + /* We need to work around the integer size limit of 2GB. The input size_t size + * variable cannot fit into an integer, but we can get around that limitation by + * creating a different datatype and then setting the integer size (or element + * count) to 1 when using the derived_type. */ + + if (H5_mpio_create_large_type(sizes[0], 0, MPI_BYTE, buf_type) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "can't create MPI-I/O datatype") + *buf_type_created = TRUE; + + if (H5_mpio_create_large_type(sizes[0], 0, MPI_BYTE, file_type) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "can't create MPI-I/O datatype") + *file_type_created = TRUE; + + *size_i = 1; + } + } + else if (count > 0) { /* create MPI derived types describing the vector write */ + + /* sort the vector I/O request into increasing address order if required + * + * If the vector is already sorted, the base addresses of types, addrs, sizes, + * and bufs will be returned in s_types, s_addrs, s_sizes, and s_bufs respectively. + * + * If the vector was not already sorted, new, sorted versions of types, addrs, sizes, and bufs + * are allocated, populated, and returned in s_types, s_addrs, s_sizes, and s_bufs respectively. + * In this case, this function must free the memory allocated for the sorted vectors. + */ + if (H5FD_sort_vector_io_req(vector_was_sorted, count, types, addrs, sizes, bufs, &s_types, s_addrs, + s_sizes, s_bufs) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "can't sort vector I/O request") + + if ((NULL == (mpi_block_lengths = (int *)HDmalloc((size_t)count * sizeof(int)))) || + (NULL == (mpi_displacements = (MPI_Aint *)HDmalloc((size_t)count * sizeof(MPI_Aint)))) || + (NULL == (mpi_bufs = (MPI_Aint *)HDmalloc((size_t)count * sizeof(MPI_Aint))))) { + + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't alloc mpi block lengths / displacement") + } + + /* when we setup mpi_bufs[] below, all addresses are offsets from + * mpi_bufs_base. + * + * Since these offsets must all be positive, we must scan through + * s_bufs[] to find the smallest value, and choose that for + * mpi_bufs_base. + */ + + j = 0; /* guess at the index of the smallest value of s_bufs[] */ + + for (i = 1; i < (int)count; i++) { + + if ((*s_bufs)[i].cvp < (*s_bufs)[j].cvp) { + + j = i; + } + } + + *mpi_bufs_base = (*s_bufs)[j]; + + if (MPI_SUCCESS != (mpi_code = MPI_Get_address(mpi_bufs_base->cvp, &mpi_bufs_base_Aint))) + + HMPI_GOTO_ERROR(FAIL, "MPI_Get_address for s_bufs[] to mpi_bufs_base failed", mpi_code) + + *size_i = 1; + + fixed_size = FALSE; + + /* load the mpi_block_lengths and mpi_displacements arrays */ + for (i = 0; i < (int)count; i++) { + /* Determine size of this vector element */ + if (!fixed_size) { + if ((*s_sizes)[i] == 0) { + HDassert(vector_was_sorted); + fixed_size = TRUE; + size = sizes[i - 1]; + } + else { + size = (*s_sizes)[i]; + } + } + + /* Add to block lengths and displacements arrays */ + mpi_block_lengths[i] = (int)size; + mpi_displacements[i] = (MPI_Aint)(*s_addrs)[i]; + + /* convert s_bufs[i] to MPI_Aint... */ + if (MPI_SUCCESS != (mpi_code = MPI_Get_address((*s_bufs)[i].cvp, &(mpi_bufs[i])))) + HMPI_GOTO_ERROR(FAIL, "MPI_Get_address for s_bufs[] - mpi_bufs_base failed", mpi_code) + + /*... and then subtract mpi_bufs_base_Aint from it. */ +#if ((MPI_VERSION > 3) || ((MPI_VERSION == 3) && (MPI_SUBVERSION >= 1))) + mpi_bufs[i] = MPI_Aint_diff(mpi_bufs[i], mpi_bufs_base_Aint); +#else + mpi_bufs[i] = mpi_bufs[i] - mpi_bufs_base_Aint; +#endif + + /* Check for size overflow */ + if (size > bigio_count) { + /* We need to work around the integer size limit of 2GB. The input size_t size + * variable cannot fit into an integer, but we can get around that limitation by + * creating a different datatype and then setting the integer size (or element + * count) to 1 when using the derived_type. */ + + /* Allocate arrays to keep track of types and whether they were created, if + * necessary */ + if (!sub_types) { + HDassert(!sub_types_created); + + if (NULL == (sub_types = (int *)HDmalloc((size_t)count * sizeof(MPI_Datatype)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't alloc sub types array") + if (NULL == (sub_types_created = (uint8_t *)HDcalloc((size_t)count, 1))) { + H5MM_free(sub_types); + sub_types = NULL; + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't alloc sub types created array") + } + + /* Initialize sub_types to all MPI_BYTE */ + for (j = 0; j < (int)count; j++) + sub_types[j] = MPI_BYTE; + } + HDassert(sub_types_created); + + /* Create type for large block */ + if (H5_mpio_create_large_type(size, 0, MPI_BYTE, &sub_types[i]) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "can't create MPI-I/O datatype") + sub_types_created[i] = TRUE; + + /* Only one of these large types for this vector element */ + mpi_block_lengths[i] = 1; + } + else + HDassert(size == (size_t)mpi_block_lengths[i]); + } + + /* create the memory MPI derived types */ + if (sub_types) { + if (MPI_SUCCESS != (mpi_code = MPI_Type_create_struct((int)count, mpi_block_lengths, mpi_bufs, + sub_types, buf_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_struct for buf_type failed", mpi_code) + } + else if (MPI_SUCCESS != (mpi_code = MPI_Type_create_hindexed((int)count, mpi_block_lengths, mpi_bufs, + MPI_BYTE, buf_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hindexed for buf_type failed", mpi_code) + + *buf_type_created = TRUE; + + if (MPI_SUCCESS != (mpi_code = MPI_Type_commit(buf_type))) + + HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit for buf_type failed", mpi_code) + + /* create the file MPI derived type */ + if (sub_types) { + if (MPI_SUCCESS != (mpi_code = MPI_Type_create_struct((int)count, mpi_block_lengths, + mpi_displacements, sub_types, file_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_struct for file_type failed", mpi_code) + } + else if (MPI_SUCCESS != (mpi_code = MPI_Type_create_hindexed((int)count, mpi_block_lengths, + mpi_displacements, MPI_BYTE, file_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hindexed for file_type failed", mpi_code) + + *file_type_created = TRUE; + + if (MPI_SUCCESS != (mpi_code = MPI_Type_commit(file_type))) + + HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit for file_type failed", mpi_code) + + /* Free up memory used to build types */ + HDassert(mpi_block_lengths); + HDfree(mpi_block_lengths); + mpi_block_lengths = NULL; + + HDassert(mpi_displacements); + HDfree(mpi_displacements); + mpi_displacements = NULL; + + HDassert(mpi_bufs); + HDfree(mpi_bufs); + mpi_bufs = NULL; + + if (sub_types) { + HDassert(sub_types); + + for (i = 0; i < (int)count; i++) + if (sub_types_created[i]) + MPI_Type_free(&sub_types[i]); + + HDfree(sub_types); + sub_types = NULL; + HDfree(sub_types_created); + sub_types_created = NULL; + } + + /* some numeric conversions */ + if (H5FD_mpi_haddr_to_MPIOff((haddr_t)0, mpi_off) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "can't set MPI off to 0") + } + else { + /* setup for null participation in the collective operation. */ + *buf_type = MPI_BYTE; + *file_type = MPI_BYTE; + + /* Set non-NULL pointer for I/O operation */ + mpi_bufs_base->vp = unused; + + /* MPI count to read */ + *size_i = 0; + + /* some numeric conversions */ + if (H5FD_mpi_haddr_to_MPIOff((haddr_t)0, mpi_off) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "can't set MPI off to 0") + } + +done: + /* free sorted vectors if they exist */ + if (!vector_was_sorted) + if (s_types) { + HDfree(s_types); + s_types = NULL; + } + + /* Clean up on error */ + if (ret_value < 0) { + if (mpi_block_lengths) { + HDfree(mpi_block_lengths); + mpi_block_lengths = NULL; + } + + if (mpi_displacements) { + HDfree(mpi_displacements); + mpi_displacements = NULL; + } + + if (mpi_bufs) { + HDfree(mpi_bufs); + mpi_bufs = NULL; + } + + if (sub_types) { + HDassert(sub_types_created); + + for (i = 0; i < (int)count; i++) + if (sub_types_created[i]) + MPI_Type_free(&sub_types[i]); + + HDfree(sub_types); + sub_types = NULL; + HDfree(sub_types_created); + sub_types_created = NULL; + } + } + + /* Make sure we cleaned up */ + HDassert(!mpi_block_lengths); + HDassert(!mpi_displacements); + HDassert(!mpi_bufs); + HDassert(!sub_types); + HDassert(!sub_types_created); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD__mpio_vector_build_types() */ + +/*------------------------------------------------------------------------- + * Function: H5FD__mpio_read_vector() + * + * Purpose: The behaviour of this function dependes on the value of + * the io_xfer_mode obtained from the context. + * + * If it is H5FD_MPIO_COLLECTIVE, this is a collective + * operation, which allows us to use MPI_File_set_view, and + * then perform the entire vector read in a single MPI call. + * + * Do this (if count is positive), by constructing memory + * and file derived types from the supplied vector, using + * file type to set the file view, and then reading the + * the memory type from file. Note that this read is + * either independent or collective depending on the + * value of mpio_coll_opt -- again obtained from the context. + * + * If count is zero, participate in the collective read + * (if so configured) with an empty read. + * + * Finally, set the file view back to its default state. + * + * In contrast, if io_xfer_mode is H5FD_MPIO_INDEPENDENT, + * this call is independent, and thus we cannot use + * MPI_File_set_view(). + * + * In this case, simply walk the vector, and issue an + * independent read for each entry. + * + * Return: Success: SUCCEED. + * Failure: FAIL. + * + * Programmer: John Mainzer + * March 15, 2021 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD__mpio_read_vector(H5FD_t *_file, hid_t H5_ATTR_UNUSED dxpl_id, uint32_t count, H5FD_mem_t types[], + haddr_t addrs[], size_t sizes[], void *bufs[]) +{ + H5FD_mpio_t * file = (H5FD_mpio_t *)_file; + hbool_t vector_was_sorted = TRUE; + haddr_t * s_addrs = NULL; + size_t * s_sizes = NULL; + void ** s_bufs = NULL; + char unused = 0; /* Unused, except for non-NULL pointer value */ + void * mpi_bufs_base = NULL; + MPI_Datatype buf_type = MPI_BYTE; /* MPI description of the selection in memory */ + hbool_t buf_type_created = FALSE; + MPI_Datatype file_type = MPI_BYTE; /* MPI description of the selection in file */ + hbool_t file_type_created = FALSE; + int i; + int mpi_code; /* MPI return code */ + MPI_Offset mpi_off = 0; + MPI_Status mpi_stat; /* Status from I/O operation */ + H5FD_mpio_xfer_t xfer_mode; /* I/O transfer mode */ + H5FD_mpio_collective_opt_t coll_opt_mode; /* whether we are doing collective or independent I/O */ + int size_i; +#if MPI_VERSION >= 3 + MPI_Count bytes_read = 0; /* Number of bytes read in */ + MPI_Count type_size; /* MPI datatype used for I/O's size */ + MPI_Count io_size; /* Actual number of bytes requested */ + MPI_Count n; +#else + int bytes_read = 0; /* Number of bytes read in */ + int type_size; /* MPI datatype used for I/O's size */ + int io_size; /* Actual number of bytes requested */ + int n; +#endif + hbool_t rank0_bcast = FALSE; /* If read-with-rank0-and-bcast flag was used */ +#ifdef H5FDmpio_DEBUG + hbool_t H5FD_mpio_debug_t_flag = (H5FD_mpio_debug_flags_s[(int)'t'] && H5FD_MPIO_TRACE_THIS_RANK(file)); + hbool_t H5FD_mpio_debug_r_flag = (H5FD_mpio_debug_flags_s[(int)'r'] && H5FD_MPIO_TRACE_THIS_RANK(file)); +#endif + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC + +#ifdef H5FDmpio_DEBUG + if (H5FD_mpio_debug_t_flag) + HDfprintf(stderr, "%s: (%d) Entering\n", __func__, file->mpi_rank); +#endif + + /* Sanity checks */ + HDassert(file); + HDassert(H5FD_MPIO == file->pub.driver_id); + HDassert((types) || (count == 0)); + HDassert((addrs) || (count == 0)); + HDassert((sizes) || (count == 0)); + HDassert((bufs) || (count == 0)); + + /* verify that the first elements of the sizes and types arrays are + * valid. + */ + HDassert((count == 0) || (sizes[0] != 0)); + HDassert((count == 0) || (types[0] != H5FD_MEM_NOLIST)); + + /* Get the transfer mode from the API context + * + * This flag is set to H5FD_MPIO_COLLECTIVE if the API call is + * collective, and to H5FD_MPIO_INDEPENDENT if it is not. + * + * While this doesn't mean that we are actually about to do a collective + * read, it does mean that all ranks are here, so we can use MPI_File_set_view(). + */ + if (H5CX_get_io_xfer_mode(&xfer_mode) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't get MPI-I/O transfer mode") + + if (xfer_mode == H5FD_MPIO_COLLECTIVE) { + /* Build MPI types, etc. */ + if (H5FD__mpio_vector_build_types(count, types, addrs, sizes, (H5_flexible_const_ptr_t *)bufs, + &s_addrs, &s_sizes, (H5_flexible_const_ptr_t **)&s_bufs, + &vector_was_sorted, &mpi_off, + (H5_flexible_const_ptr_t *)&mpi_bufs_base, &size_i, &buf_type, + &buf_type_created, &file_type, &file_type_created, &unused) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't build MPI datatypes for I/O") + + /* free sorted addrs vector if it exists */ + if (!vector_was_sorted) + if (s_addrs) { + HDfree(s_addrs); + s_addrs = NULL; + } + + /* Portably initialize MPI status variable */ + HDmemset(&mpi_stat, 0, sizeof(mpi_stat)); + +#ifdef H5FDmpio_DEBUG + if (H5FD_mpio_debug_r_flag) + HDfprintf(stdout, "%s: mpi_off = %ld size_i = %d\n", __func__, (long)mpi_off, size_i); +#endif + + /* Setup the file view. */ + if (MPI_SUCCESS != (mpi_code = MPI_File_set_view(file->f, mpi_off, MPI_BYTE, file_type, + H5FD_mpi_native_g, file->info))) + HMPI_GOTO_ERROR(FAIL, "MPI_File_set_view failed", mpi_code) + + /* Reset mpi_off to 0 since the view now starts at the data offset */ + if (H5FD_mpi_haddr_to_MPIOff((haddr_t)0, &mpi_off) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "can't set MPI off to 0") + + /* Get the collective_opt property to check whether the application wants to do IO individually. + */ + if (H5CX_get_mpio_coll_opt(&coll_opt_mode) < 0) + + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't get MPI-I/O collective_op property") + + /* Read the data. */ +#ifdef H5FDmpio_DEBUG + if (H5FD_mpio_debug_r_flag) + HDfprintf(stdout, "%s: using MPIO collective mode\n", __func__); +#endif + if (coll_opt_mode == H5FD_MPIO_COLLECTIVE_IO) { +#ifdef H5FDmpio_DEBUG + if (H5FD_mpio_debug_r_flag) + HDfprintf(stdout, "%s: doing MPI collective IO\n", __func__); +#endif + /* Check whether we should read from rank 0 and broadcast to other ranks */ + if (H5CX_get_mpio_rank0_bcast()) { +#ifdef H5FDmpio_DEBUG + if (H5FD_mpio_debug_r_flag) + HDfprintf(stdout, "%s: doing read-rank0-and-MPI_Bcast\n", __func__); +#endif + /* Indicate path we've taken */ + rank0_bcast = TRUE; + + /* Read on rank 0 Bcast to other ranks */ + if (file->mpi_rank == 0) + if (MPI_SUCCESS != (mpi_code = MPI_File_read_at(file->f, mpi_off, mpi_bufs_base, size_i, + buf_type, &mpi_stat))) + HMPI_GOTO_ERROR(FAIL, "MPI_File_read_at_all failed", mpi_code) + if (MPI_SUCCESS != (mpi_code = MPI_Bcast(mpi_bufs_base, size_i, buf_type, 0, file->comm))) + HMPI_GOTO_ERROR(FAIL, "MPI_Bcast failed", mpi_code) + } /* end if */ + else if (MPI_SUCCESS != (mpi_code = MPI_File_read_at_all(file->f, mpi_off, mpi_bufs_base, size_i, + buf_type, &mpi_stat))) + HMPI_GOTO_ERROR(FAIL, "MPI_File_read_at_all failed", mpi_code) + } /* end if */ + else if (size_i > 0) { +#ifdef H5FDmpio_DEBUG + if (H5FD_mpio_debug_r_flag) + HDfprintf(stdout, "%s: doing MPI independent IO\n", __func__); +#endif + + if (MPI_SUCCESS != + (mpi_code = MPI_File_read_at(file->f, mpi_off, mpi_bufs_base, size_i, buf_type, &mpi_stat))) + + HMPI_GOTO_ERROR(FAIL, "MPI_File_read_at failed", mpi_code) + + } /* end else */ + + /* Reset the file view */ + if (MPI_SUCCESS != (mpi_code = MPI_File_set_view(file->f, (MPI_Offset)0, MPI_BYTE, MPI_BYTE, + H5FD_mpi_native_g, file->info))) + HMPI_GOTO_ERROR(FAIL, "MPI_File_set_view failed", mpi_code) + + /* Only retrieve bytes read if this rank _actually_ participated in I/O */ + if (!rank0_bcast || (rank0_bcast && file->mpi_rank == 0)) { + /* How many bytes were actually read? */ +#if MPI_VERSION >= 3 + if (MPI_SUCCESS != (mpi_code = MPI_Get_elements_x(&mpi_stat, buf_type, &bytes_read))) +#else + if (MPI_SUCCESS != (mpi_code = MPI_Get_elements(&mpi_stat, MPI_BYTE, &bytes_read))) +#endif + HMPI_GOTO_ERROR(FAIL, "MPI_Get_elements failed", mpi_code) + } /* end if */ + + /* If the rank0-bcast feature was used, broadcast the # of bytes read to + * other ranks, which didn't perform any I/O. + */ + /* NOTE: This could be optimized further to be combined with the broadcast + * of the data. (QAK - 2019/1/2) + * Or have rank 0 clear the unread parts of the buffer prior to + * the bcast. (NAF - 2021/9/15) + */ + if (rank0_bcast) +#if MPI_VERSION >= 3 + if (MPI_SUCCESS != MPI_Bcast(&bytes_read, 1, MPI_COUNT, 0, file->comm)) +#else + if (MPI_SUCCESS != MPI_Bcast(&bytes_read, 1, MPI_INT, 0, file->comm)) +#endif + HMPI_GOTO_ERROR(FAIL, "MPI_Bcast failed", 0) + + /* Get the type's size */ +#if MPI_VERSION >= 3 + if (MPI_SUCCESS != (mpi_code = MPI_Type_size_x(buf_type, &type_size))) +#else + if (MPI_SUCCESS != (mpi_code = MPI_Type_size(buf_type, &type_size))) +#endif + HMPI_GOTO_ERROR(FAIL, "MPI_Type_size failed", mpi_code) + + /* Compute the actual number of bytes requested */ + io_size = type_size * size_i; + + /* Check for read failure */ + if (bytes_read < 0 || bytes_read > io_size) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file read failed") + + /* Check for incomplete read */ + n = io_size - bytes_read; + if (n > 0) { + i = (int)count - 1; + + /* Iterate over sorted array in reverse, filling in zeroes to + * sections of the buffers that were not read to */ + do { + HDassert(i >= 0); + +#if MPI_VERSION >= 3 + io_size = MIN(n, (MPI_Count)s_sizes[i]); + bytes_read = (MPI_Count)s_sizes[i] - io_size; +#else + io_size = MIN(n, (int)s_sizes[i]); + bytes_read = (int)s_sizes[i] - io_size; +#endif + HDassert(bytes_read >= 0); + + HDmemset((char *)s_bufs[i] + bytes_read, 0, (size_t)io_size); + + n -= io_size; + i--; + } while (n > 0); + } + } + else if (count > 0) { + haddr_t max_addr = HADDR_MAX; + hbool_t fixed_size = FALSE; + size_t size; + + /* The read is part of an independent operation. As a result, + * we can't use MPI_File_set_view() (since it it a collective operation), + * and thus we can't use the above code to construct the MPI datatypes. + * In the future, we could write code to detect when a contiguous slab + * in the file selection spans multiple vector elements and construct a + * memory datatype to match this larger block in the file, but for now + * just read in each element of the vector in a separate + * MPI_File_read_at() call. + * + * We could also just detect the case when the entire file selection is + * contiguous, which would allow us to use + * H5FD__mpio_vector_build_types() to construct the memory datatype. + */ + +#ifdef H5FDmpio_DEBUG + if (H5FD_mpio_debug_r_flag) + HDfprintf(stdout, "%s: doing MPI independent IO\n", __func__); +#endif + + /* Loop over vector elements */ + for (i = 0; i < (int)count; i++) { + /* Convert address to mpi offset */ + if (H5FD_mpi_haddr_to_MPIOff(addrs[i], &mpi_off) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "can't convert from haddr to MPI off") + + /* Calculate I/O size */ + if (!fixed_size) { + if (sizes[i] == 0) { + fixed_size = TRUE; + size = sizes[i - 1]; + } + else { + size = sizes[i]; + } + } + size_i = (int)size; + + if (size != (size_t)size_i) { + /* If HERE, then we need to work around the integer size limit + * of 2GB. The input size_t size variable cannot fit into an integer, + * but we can get around that limitation by creating a different datatype + * and then setting the integer size (or element count) to 1 when using + * the derived_type. + */ + + if (H5_mpio_create_large_type(size, 0, MPI_BYTE, &buf_type) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "can't create MPI-I/O datatype") + + buf_type_created = TRUE; + size_i = 1; + } + + /* Check if we actually need to do I/O */ + if (addrs[i] < max_addr) { + /* Portably initialize MPI status variable */ + HDmemset(&mpi_stat, 0, sizeof(mpi_stat)); + + /* Issue read */ + if (MPI_SUCCESS != + (mpi_code = MPI_File_read_at(file->f, mpi_off, bufs[i], size_i, buf_type, &mpi_stat))) + + HMPI_GOTO_ERROR(FAIL, "MPI_File_read_at failed", mpi_code) + + /* How many bytes were actually read? */ +#if MPI_VERSION >= 3 + if (MPI_SUCCESS != (mpi_code = MPI_Get_elements_x(&mpi_stat, MPI_BYTE, &bytes_read))) +#else + if (MPI_SUCCESS != (mpi_code = MPI_Get_elements(&mpi_stat, MPI_BYTE, &bytes_read))) +#endif + HMPI_GOTO_ERROR(FAIL, "MPI_Get_elements failed", mpi_code) + + /* Compute the actual number of bytes requested */ +#if MPI_VERSION >= 3 + io_size = (MPI_Count)size; +#else + io_size = (int)size; +#endif + + /* Check for read failure */ + if (bytes_read < 0 || bytes_read > io_size) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file read failed") + + /* + * If we didn't read the entire I/O, fill in zeroes beyond end of + * the physical MPI file and don't issue any more reads at higher + * addresses. + */ + if ((n = (io_size - bytes_read)) > 0) { + HDmemset((char *)bufs[i] + bytes_read, 0, (size_t)n); + max_addr = addrs[i] + (haddr_t)bytes_read; + } + } + else { + /* Read is past the max address, fill in zeroes */ + HDmemset((char *)bufs[i], 0, size); + } + } + } + +done: + if (buf_type_created) { + MPI_Type_free(&buf_type); + } + + if (file_type_created) { + MPI_Type_free(&file_type); + } + + /* free sorted vectors if they exist */ + if (!vector_was_sorted) { + if (s_addrs) { + HDfree(s_addrs); + s_addrs = NULL; + } + if (s_sizes) { + HDfree(s_sizes); + s_sizes = NULL; + } + if (s_bufs) { + HDfree(s_bufs); + s_bufs = NULL; + } + } + +#ifdef H5FDmpio_DEBUG + if (H5FD_mpio_debug_t_flag) + HDfprintf(stdout, "%s: Leaving, proc %d: ret_value = %d\n", __func__, file->mpi_rank, ret_value); +#endif + + FUNC_LEAVE_NOAPI(ret_value) + +} /* end H5FD__mpio_read_vector() */ + +/*------------------------------------------------------------------------- + * Function: H5FD__mpio_write_vector + * + * Purpose: The behaviour of this function dependes on the value of + * the io_xfer_mode obtained from the context. + * + * If it is H5FD_MPIO_COLLECTIVE, this is a collective + * operation, which allows us to use MPI_File_set_view, and + * then perform the entire vector write in a single MPI call. + * + * Do this (if count is positive), by constructing memory + * and file derived types from the supplied vector, using + * file type to set the file view, and then writing the + * the memory type to file. Note that this write is + * either independent or collective depending on the + * value of mpio_coll_opt -- again obtained from the context. + * + * If count is zero, participate in the collective write + * (if so configured) with an empty write. + * + * Finally, set the file view back to its default state. + * + * In contrast, if io_xfer_mode is H5FD_MPIO_INDEPENDENT, + * this call is independent, and thus we cannot use + * MPI_File_set_view(). + * + * In this case, simply walk the vector, and issue an + * independent write for each entry. + * + * Return: Success: SUCCEED. + * Failure: FAIL. + * + * Programmer: John Mainzer + * March 15, 2021 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD__mpio_write_vector(H5FD_t *_file, hid_t H5_ATTR_UNUSED dxpl_id, uint32_t count, H5FD_mem_t types[], + haddr_t addrs[], size_t sizes[], const void *bufs[]) +{ + H5FD_mpio_t * file = (H5FD_mpio_t *)_file; + hbool_t vector_was_sorted = TRUE; + haddr_t * s_addrs = NULL; + size_t * s_sizes = NULL; + const void ** s_bufs = NULL; + char unused = 0; /* Unused, except for non-NULL pointer value */ + const void * mpi_bufs_base = NULL; + MPI_Datatype buf_type = MPI_BYTE; /* MPI description of the selection in memory */ + hbool_t buf_type_created = FALSE; + MPI_Datatype file_type = MPI_BYTE; /* MPI description of the selection in file */ + hbool_t file_type_created = FALSE; + int i; + int mpi_code; /* MPI return code */ + MPI_Offset mpi_off = 0; + MPI_Status mpi_stat; /* Status from I/O operation */ + H5FD_mpio_xfer_t xfer_mode; /* I/O transfer mode */ + H5FD_mpio_collective_opt_t coll_opt_mode; /* whether we are doing collective or independent I/O */ + int size_i; +#ifdef H5FDmpio_DEBUG + hbool_t H5FD_mpio_debug_t_flag = (H5FD_mpio_debug_flags_s[(int)'t'] && H5FD_MPIO_TRACE_THIS_RANK(file)); + hbool_t H5FD_mpio_debug_w_flag = (H5FD_mpio_debug_flags_s[(int)'w'] && H5FD_MPIO_TRACE_THIS_RANK(file)); +#endif + haddr_t max_addr = 0; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC + +#ifdef H5FDmpio_DEBUG + if (H5FD_mpio_debug_t_flag) + HDfprintf(stderr, "%s: (%d) Entering\n", __func__, file->mpi_rank); +#endif + + /* Sanity checks */ + HDassert(file); + HDassert(H5FD_MPIO == file->pub.driver_id); + HDassert((types) || (count == 0)); + HDassert((addrs) || (count == 0)); + HDassert((sizes) || (count == 0)); + HDassert((bufs) || (count == 0)); + + /* verify that the first elements of the sizes and types arrays are + * valid. + */ + HDassert((count == 0) || (sizes[0] != 0)); + HDassert((count == 0) || (types[0] != H5FD_MEM_NOLIST)); + + /* Verify that no data is written when between MPI_Barrier()s during file flush */ + + HDassert(!H5CX_get_mpi_file_flushing()); + + /* Get the transfer mode from the API context + * + * This flag is set to H5FD_MPIO_COLLECTIVE if the API call is + * collective, and to H5FD_MPIO_INDEPENDENT if it is not. + * + * While this doesn't mean that we are actually about to do a collective + * write, it does mean that all ranks are here, so we can use MPI_File_set_view(). + */ + if (H5CX_get_io_xfer_mode(&xfer_mode) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't get MPI-I/O transfer mode") + + if (xfer_mode == H5FD_MPIO_COLLECTIVE) { + /* Build MPI types, etc. */ + if (H5FD__mpio_vector_build_types(count, types, addrs, sizes, (H5_flexible_const_ptr_t *)bufs, + &s_addrs, &s_sizes, (H5_flexible_const_ptr_t **)&s_bufs, + &vector_was_sorted, &mpi_off, + (H5_flexible_const_ptr_t *)&mpi_bufs_base, &size_i, &buf_type, + &buf_type_created, &file_type, &file_type_created, &unused) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't build MPI datatypes for I/O") + + /* Compute max addr writted to */ + if (count > 0) + max_addr = s_addrs[count - 1] + (haddr_t)(s_sizes[count - 1]); + + /* free sorted vectors if they exist */ + if (!vector_was_sorted) { + if (s_addrs) { + HDfree(s_addrs); + s_addrs = NULL; + } + if (s_sizes) { + HDfree(s_sizes); + s_sizes = NULL; + } + if (s_bufs) { + HDfree(s_bufs); + s_bufs = NULL; + } + } + + /* Portably initialize MPI status variable */ + HDmemset(&mpi_stat, 0, sizeof(MPI_Status)); + +#ifdef H5FDmpio_DEBUG + if (H5FD_mpio_debug_w_flag) + HDfprintf(stdout, "%s: mpi_off = %ld size_i = %d\n", __func__, (long)mpi_off, size_i); +#endif + + /* Setup the file view. */ + if (MPI_SUCCESS != (mpi_code = MPI_File_set_view(file->f, mpi_off, MPI_BYTE, file_type, + H5FD_mpi_native_g, file->info))) + HMPI_GOTO_ERROR(FAIL, "MPI_File_set_view failed", mpi_code) + + /* Reset mpi_off to 0 since the view now starts at the data offset */ + if (H5FD_mpi_haddr_to_MPIOff((haddr_t)0, &mpi_off) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "can't set MPI off to 0") + + /* Get the collective_opt property to check whether the application wants to do IO individually. + */ + if (H5CX_get_mpio_coll_opt(&coll_opt_mode) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't get MPI-I/O collective_op property") + + /* Write the data. */ +#ifdef H5FDmpio_DEBUG + if (H5FD_mpio_debug_w_flag) + HDfprintf(stdout, "%s: using MPIO collective mode\n", __func__); +#endif + + if (coll_opt_mode == H5FD_MPIO_COLLECTIVE_IO) { +#ifdef H5FDmpio_DEBUG + if (H5FD_mpio_debug_w_flag) + HDfprintf(stdout, "%s: doing MPI collective IO\n", __func__); +#endif + + if (MPI_SUCCESS != (mpi_code = MPI_File_write_at_all(file->f, mpi_off, mpi_bufs_base, size_i, + buf_type, &mpi_stat))) + HMPI_GOTO_ERROR(FAIL, "MPI_File_write_at_all failed", mpi_code) + } /* end if */ + else if (size_i > 0) { +#ifdef H5FDmpio_DEBUG + if (H5FD_mpio_debug_w_flag) + HDfprintf(stdout, "%s: doing MPI independent IO\n", __func__); +#endif + + if (MPI_SUCCESS != + (mpi_code = MPI_File_write_at(file->f, mpi_off, mpi_bufs_base, size_i, buf_type, &mpi_stat))) + HMPI_GOTO_ERROR(FAIL, "MPI_File_write_at failed", mpi_code) + } /* end else */ + + /* Reset the file view */ + if (MPI_SUCCESS != (mpi_code = MPI_File_set_view(file->f, (MPI_Offset)0, MPI_BYTE, MPI_BYTE, + H5FD_mpi_native_g, file->info))) + HMPI_GOTO_ERROR(FAIL, "MPI_File_set_view failed", mpi_code) + } + else if (count > 0) { + hbool_t fixed_size = FALSE; + size_t size; + + /* The read is part of an independent operation. As a result, + * we can't use MPI_File_set_view() (since it it a collective operation), + * and thus we can't use the above code to construct the MPI datatypes. + * In the future, we could write code to detect when a contiguous slab + * in the file selection spans multiple vector elements and construct a + * memory datatype to match this larger block in the file, but for now + * just read in each element of the vector in a separate + * MPI_File_read_at() call. + * + * We could also just detect the case when the entire file selection is + * contiguous, which would allow us to use + * H5FD__mpio_vector_build_types() to construct the memory datatype. + */ + +#ifdef H5FDmpio_DEBUG + if (H5FD_mpio_debug_w_flag) + HDfprintf(stdout, "%s: doing MPI independent IO\n", __func__); +#endif + + /* Loop over vector elements */ + for (i = 0; i < (int)count; i++) { + /* Convert address to mpi offset */ + if (H5FD_mpi_haddr_to_MPIOff(addrs[i], &mpi_off) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "can't convert from haddr to MPI off") + + /* Calculate I/O size */ + if (!fixed_size) { + if (sizes[i] == 0) { + fixed_size = TRUE; + size = sizes[i - 1]; + } + else { + size = sizes[i]; + } + } + size_i = (int)size; + + if (size != (size_t)size_i) { + /* If HERE, then we need to work around the integer size limit + * of 2GB. The input size_t size variable cannot fit into an integer, + * but we can get around that limitation by creating a different datatype + * and then setting the integer size (or element count) to 1 when using + * the derived_type. + */ + + if (H5_mpio_create_large_type(size, 0, MPI_BYTE, &buf_type) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "can't create MPI-I/O datatype") + + buf_type_created = TRUE; + size_i = 1; + } + + /* Perform write */ + if (MPI_SUCCESS != + (mpi_code = MPI_File_write_at(file->f, mpi_off, bufs[i], size_i, buf_type, &mpi_stat))) + + HMPI_GOTO_ERROR(FAIL, "MPI_File_write_at failed", mpi_code) + + /* Check if this is the highest address written to so far */ + if (addrs[i] + size > max_addr) + max_addr = addrs[i] + size; + } + } + + /* Each process will keep track of its perceived EOF value locally, and + * ultimately we will reduce this value to the maximum amongst all + * processes, but until then keep the actual eof at HADDR_UNDEF just in + * case something bad happens before that point. (rather have a value + * we know is wrong sitting around rather than one that could only + * potentially be wrong.) + */ + file->eof = HADDR_UNDEF; + + /* check to see if the local eof has changed been extended, and update if so */ + if (max_addr > file->local_eof) + file->local_eof = max_addr; + +done: + if (buf_type_created) + MPI_Type_free(&buf_type); + + if (file_type_created) + MPI_Type_free(&file_type); + + /* Cleanup on error */ + if (ret_value < 0 && !vector_was_sorted) { + if (s_addrs) { + HDfree(s_addrs); + s_addrs = NULL; + } + if (s_sizes) { + HDfree(s_sizes); + s_sizes = NULL; + } + if (s_bufs) { + HDfree(s_bufs); + s_bufs = NULL; + } + } + + /* Make sure we cleaned up */ + HDassert(vector_was_sorted || !s_addrs); + HDassert(vector_was_sorted || !s_sizes); + HDassert(vector_was_sorted || !s_bufs); + +#ifdef H5FDmpio_DEBUG + if (H5FD_mpio_debug_t_flag) + HDfprintf(stdout, "%s: Leaving, proc %d: ret_value = %d\n", __func__, file->mpi_rank, ret_value); +#endif + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD__mpio_write_vector() */ + +/*------------------------------------------------------------------------- * Function: H5FD__mpio_flush * * Purpose: Makes sure that all data is on disk. This is collective. @@ -1701,17 +2835,19 @@ H5FD__mpio_truncate(H5FD_t *_file, hid_t H5_ATTR_UNUSED dxpl_id, hbool_t H5_ATTR HMPI_GOTO_ERROR(FAIL, "MPI_Barrier failed", mpi_code) /* Only processor p0 will get the filesize and broadcast it. */ - /* (Note that throwing an error here will cause non-rank 0 processes - * to hang in following Bcast. -QAK, 3/17/2018) - */ - if (0 == file->mpi_rank) + if (0 == file->mpi_rank) { + /* If MPI_File_get_size fails, broadcast file size as -1 to signal error */ if (MPI_SUCCESS != (mpi_code = MPI_File_get_size(file->f, &size))) - HMPI_GOTO_ERROR(FAIL, "MPI_File_get_size failed", mpi_code) + size = (MPI_Offset)-1; + } /* Broadcast file size */ if (MPI_SUCCESS != (mpi_code = MPI_Bcast(&size, (int)sizeof(MPI_Offset), MPI_BYTE, 0, file->comm))) HMPI_GOTO_ERROR(FAIL, "MPI_Bcast failed", mpi_code) + if (size < 0) + HMPI_GOTO_ERROR(FAIL, "MPI_File_get_size failed", mpi_code) + if (H5FD_mpi_haddr_to_MPIOff(file->eoa, &needed_eof) < 0) HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "cannot convert from haddr_t to MPI_Offset") @@ -1774,11 +2910,16 @@ H5FD__mpio_delete(const char *filename, hid_t fapl_id) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") HDassert(H5FD_MPIO == H5P_peek_driver(plist)); - /* Get the MPI communicator and info from the fapl */ - if (H5P_get(plist, H5F_ACS_MPI_PARAMS_INFO_NAME, &info) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't get MPI info object") - if (H5P_get(plist, H5F_ACS_MPI_PARAMS_COMM_NAME, &comm) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't get MPI communicator") + if (H5FD_mpi_self_initialized) { + comm = MPI_COMM_WORLD; + } + else { + /* Get the MPI communicator and info from the fapl */ + if (H5P_get(plist, H5F_ACS_MPI_PARAMS_INFO_NAME, &info) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't get MPI info object") + if (H5P_get(plist, H5F_ACS_MPI_PARAMS_COMM_NAME, &comm) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't get MPI communicator") + } /* Get the MPI rank of this process */ if (MPI_SUCCESS != (mpi_code = MPI_Comm_rank(comm, &mpi_rank))) @@ -1789,96 +2930,101 @@ H5FD__mpio_delete(const char *filename, hid_t fapl_id) HMPI_GOTO_ERROR(FAIL, "MPI_Barrier failed", mpi_code) /* Delete the file */ - if (mpi_rank == 0) + if (mpi_rank == 0) { + /* If MPI_File_delete fails, push an error but + * still participate in the following MPI_Barrier + */ if (MPI_SUCCESS != (mpi_code = MPI_File_delete(filename, info))) - HMPI_GOTO_ERROR(FAIL, "MPI_File_delete failed", mpi_code) + HMPI_DONE_ERROR(FAIL, "MPI_File_delete failed", mpi_code) + } /* Set up a barrier (don't want processes to run ahead of the delete) */ if (MPI_SUCCESS != (mpi_code = MPI_Barrier(comm))) HMPI_GOTO_ERROR(FAIL, "MPI_Barrier failed", mpi_code) done: + /* Free duplicated MPI Communicator and Info objects */ + if (H5_mpi_comm_free(&comm) < 0) + HDONE_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "unable to free MPI communicator") + if (H5_mpi_info_free(&info) < 0) + HDONE_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "unable to free MPI info object") + FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD__mpio_delete() */ /*------------------------------------------------------------------------- - * Function: H5FD__mpio_mpi_rank + * Function: H5FD__mpio_ctl * - * Purpose: Returns the MPI rank for a process + * Purpose: MPIO version of the ctl callback. * - * Return: Success: non-negative - * Failure: negative + * The desired operation is specified by the op_code + * parameter. * - * Programmer: Quincey Koziol - * Thursday, May 16, 2002 + * The flags parameter controls management of op_codes that + * are unknown to the callback * - *------------------------------------------------------------------------- - */ -static int -H5FD__mpio_mpi_rank(const H5FD_t *_file) -{ - const H5FD_mpio_t *file = (const H5FD_mpio_t *)_file; - - FUNC_ENTER_STATIC_NOERR - - /* Sanity checks */ - HDassert(file); - HDassert(H5FD_MPIO == file->pub.driver_id); - - FUNC_LEAVE_NOAPI(file->mpi_rank) -} /* end H5FD__mpio_mpi_rank() */ - -/*------------------------------------------------------------------------- - * Function: H5FD__mpio_mpi_size + * The input and output parameters allow op_code specific + * input and output * - * Purpose: Returns the number of MPI processes + * At present, the supported op codes are: * - * Return: Success: non-negative - * Failure: negative + * H5FD_CTL__GET_MPI_COMMUNICATOR_OPCODE + * H5FD_CTL__GET_MPI_RANK_OPCODE + * H5FD_CTL__GET_MPI_SIZE_OPCODE * - * Programmer: Quincey Koziol - * Thursday, May 16, 2002 + * Note that these opcodes must be supported by all VFDs that + * support MPI. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: JRM -- 8/3/21 * *------------------------------------------------------------------------- */ -static int -H5FD__mpio_mpi_size(const H5FD_t *_file) +static herr_t +H5FD__mpio_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void H5_ATTR_UNUSED *input, + void **output) { - const H5FD_mpio_t *file = (const H5FD_mpio_t *)_file; + H5FD_mpio_t *file = (H5FD_mpio_t *)_file; + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_STATIC_NOERR + FUNC_ENTER_NOAPI(FAIL) /* Sanity checks */ HDassert(file); HDassert(H5FD_MPIO == file->pub.driver_id); - FUNC_LEAVE_NOAPI(file->mpi_size) -} /* end H5FD__mpio_mpi_size() */ + switch (op_code) { -/*------------------------------------------------------------------------- - * Function: H5FD__mpio_communicator - * - * Purpose: Returns the MPI communicator for the file. - * - * Return: Success: The communicator - * Failure: Can't fail - * - * Programmer: Robb Matzke - * Monday, August 9, 1999 - * - *------------------------------------------------------------------------- - */ -static MPI_Comm -H5FD__mpio_communicator(const H5FD_t *_file) -{ - const H5FD_mpio_t *file = (const H5FD_mpio_t *)_file; + case H5FD_CTL__GET_MPI_COMMUNICATOR_OPCODE: + HDassert(output); + HDassert(*output); + **((MPI_Comm **)output) = file->comm; + break; - FUNC_ENTER_STATIC_NOERR + case H5FD_CTL__GET_MPI_RANK_OPCODE: + HDassert(output); + HDassert(*output); + **((int **)output) = file->mpi_rank; + break; - /* Sanity checks */ - HDassert(file); - HDassert(H5FD_MPIO == file->pub.driver_id); + case H5FD_CTL__GET_MPI_SIZE_OPCODE: + HDassert(output); + HDassert(*output); + **((int **)output) = file->mpi_size; + break; + + default: /* unknown op code */ + if (flags & H5FD_CTL__FAIL_IF_UNKNOWN_FLAG) { + + HGOTO_ERROR(H5E_VFL, H5E_FCNTL, FAIL, "unknown op_code and fail if unknown") + } + break; + } + +done: + + FUNC_LEAVE_NOAPI(ret_value) - FUNC_LEAVE_NOAPI(file->comm) -} /* end H5FD__mpio_communicator() */ +} /* end H5FD__mpio_ctl() */ #endif /* H5_HAVE_PARALLEL */ diff --git a/src/H5FDmpio.h b/src/H5FDmpio.h index 8caf11c..5ce98ca 100644 --- a/src/H5FDmpio.h +++ b/src/H5FDmpio.h @@ -23,7 +23,7 @@ /* Macros */ #ifdef H5_HAVE_PARALLEL -#define H5FD_MPIO (H5FD_mpio_init()) +#define H5FD_MPIO (H5FDperform_init(H5FD_mpio_init)) #else #define H5FD_MPIO (H5I_INVALID_HID) #endif /* H5_HAVE_PARALLEL */ @@ -223,7 +223,7 @@ H5_DLL herr_t H5Pset_dxpl_mpio_collective_opt(hid_t dxpl_id, H5FD_mpio_collectiv * * Use of this function is optional. * - * \todo Add missing version information + * \since 1.8.0 * */ H5_DLL herr_t H5Pset_dxpl_mpio_chunk_opt(hid_t dxpl_id, H5FD_mpio_chunk_opt_t opt_mode); @@ -247,7 +247,7 @@ H5_DLL herr_t H5Pset_dxpl_mpio_chunk_opt(hid_t dxpl_id, H5FD_mpio_chunk_opt_t op * otherwise, a separate I/O process will be invoked for each chunk * (multi-chunk I/O). * - * \todo Add missing version information + * \since 1.8.0 * */ H5_DLL herr_t H5Pset_dxpl_mpio_chunk_opt_num(hid_t dxpl_id, unsigned num_chunk_per_proc); @@ -272,7 +272,7 @@ H5_DLL herr_t H5Pset_dxpl_mpio_chunk_opt_num(hid_t dxpl_id, unsigned num_chunk_p * percent_proc_per_chunk, the library will do collective I/O for this * chunk; otherwise, independent I/O will be done for the chunk. * - * \todo Add missing version information + * \since 1.8.0 * */ H5_DLL herr_t H5Pset_dxpl_mpio_chunk_opt_ratio(hid_t dxpl_id, unsigned percent_num_proc_per_chunk); diff --git a/src/H5FDmulti.c b/src/H5FDmulti.c index cae4174..20c538f 100644 --- a/src/H5FDmulti.c +++ b/src/H5FDmulti.c @@ -135,8 +135,13 @@ typedef struct H5FD_multi_dxpl_t { } H5FD_multi_dxpl_t; /* Private functions */ -static int compute_next(H5FD_multi_t *file); -static int open_members(H5FD_multi_t *file); +static herr_t H5FD_split_populate_config(const char *meta_ext, hid_t meta_plist_id, const char *raw_ext, + hid_t raw_plist_id, hbool_t relax, H5FD_multi_fapl_t *fa_out); +static herr_t H5FD_multi_populate_config(const H5FD_mem_t *memb_map, const hid_t *memb_fapl, + const char *const *memb_name, const haddr_t *memb_addr, + hbool_t relax, H5FD_multi_fapl_t *fa_out); +static int compute_next(H5FD_multi_t *file); +static int open_members(H5FD_multi_t *file); /* Callback prototypes */ static herr_t H5FD_multi_term(void); @@ -166,9 +171,13 @@ static herr_t H5FD_multi_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing static herr_t H5FD_multi_lock(H5FD_t *_file, hbool_t rw); static herr_t H5FD_multi_unlock(H5FD_t *_file); static herr_t H5FD_multi_delete(const char *filename, hid_t fapl_id); +static herr_t H5FD_multi_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void *input, + void **output); /* The class struct */ static const H5FD_class_t H5FD_multi_g = { + H5FD_CLASS_VERSION, /* struct version */ + H5_VFD_MULTI, /* value */ "multi", /* name */ HADDR_MAX, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -196,11 +205,16 @@ static const H5FD_class_t H5FD_multi_g = { H5FD_multi_get_handle, /* get_handle */ H5FD_multi_read, /* read */ H5FD_multi_write, /* write */ + NULL, /*read_vector */ + NULL, /*write_vector */ + NULL, /* read_selection */ + NULL, /* write_selection */ H5FD_multi_flush, /* flush */ H5FD_multi_truncate, /* truncate */ H5FD_multi_lock, /* lock */ H5FD_multi_unlock, /* unlock */ H5FD_multi_delete, /* del */ + H5FD_multi_ctl, /* ctl */ H5FD_FLMAP_DEFAULT /* fl_map */ }; @@ -271,74 +285,19 @@ herr_t H5Pset_fapl_split(hid_t fapl, const char *meta_ext, hid_t meta_plist_id, const char *raw_ext, hid_t raw_plist_id) { - H5FD_mem_t memb_map[H5FD_MEM_NTYPES]; - hid_t memb_fapl[H5FD_MEM_NTYPES]; - const char *memb_name[H5FD_MEM_NTYPES]; - char meta_name[H5FD_MULT_MAX_FILE_NAME_LEN]; - char raw_name[H5FD_MULT_MAX_FILE_NAME_LEN]; - haddr_t memb_addr[H5FD_MEM_NTYPES]; + H5FD_multi_fapl_t fa; + static const char *func = "H5Pset_fapl_split"; /* Function Name for error reporting */ /*NO TRACE*/ /* Clear the error stack */ H5Eclear2(H5E_DEFAULT); - /* Initialize */ - ALL_MEMBERS (mt) { - /* Treat global heap as raw data, not metadata */ - memb_map[mt] = ((mt == H5FD_MEM_DRAW || mt == H5FD_MEM_GHEAP) ? H5FD_MEM_DRAW : H5FD_MEM_SUPER); - memb_fapl[mt] = -1; - memb_name[mt] = NULL; - memb_addr[mt] = HADDR_UNDEF; - } - END_MEMBERS; - - /* The file access properties */ - memb_fapl[H5FD_MEM_SUPER] = meta_plist_id; - memb_fapl[H5FD_MEM_DRAW] = raw_plist_id; - - /* The names */ - /* process meta filename */ - if (meta_ext) { - if (strstr(meta_ext, "%s")) { - /* Note: this doesn't accommodate for when the '%s' in the user's - * string is at a position >sizeof(meta_name) - QK & JK - 2013/01/17 - */ - strncpy(meta_name, meta_ext, sizeof(meta_name)); - meta_name[sizeof(meta_name) - 1] = '\0'; - } - else - sprintf(meta_name, "%%s%s", meta_ext); - } - else { - strncpy(meta_name, "%s.meta", sizeof(meta_name)); - meta_name[sizeof(meta_name) - 1] = '\0'; - } - memb_name[H5FD_MEM_SUPER] = meta_name; - - /* process raw filename */ - if (raw_ext) { - if (strstr(raw_ext, "%s")) { - /* Note: this doesn't accommodate for when the '%s' in the user's - * string is at a position >sizeof(raw_name) - QK & JK - 2013/01/17 - */ - strncpy(raw_name, raw_ext, sizeof(raw_name)); - raw_name[sizeof(raw_name) - 1] = '\0'; - } - else - sprintf(raw_name, "%%s%s", raw_ext); - } - else { - strncpy(raw_name, "%s.raw", sizeof(raw_name)); - raw_name[sizeof(raw_name) - 1] = '\0'; - } - memb_name[H5FD_MEM_DRAW] = raw_name; - - /* The sizes */ - memb_addr[H5FD_MEM_SUPER] = 0; - memb_addr[H5FD_MEM_DRAW] = HADDR_MAX / 2; + if (H5FD_split_populate_config(meta_ext, meta_plist_id, raw_ext, raw_plist_id, TRUE, &fa) < 0) + H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_CANTSET, "can't setup split driver configuration", + -1); - return H5Pset_fapl_multi(fapl, memb_map, memb_fapl, memb_name, memb_addr, TRUE); + return H5Pset_driver(fapl, H5FD_MULTI, &fa); } /*------------------------------------------------------------------------- @@ -422,14 +381,7 @@ H5Pset_fapl_multi(hid_t fapl_id, const H5FD_mem_t *memb_map, const hid_t *memb_f const char *const *memb_name, const haddr_t *memb_addr, hbool_t relax) { H5FD_multi_fapl_t fa; - H5FD_mem_t mt, mmt; - H5FD_mem_t _memb_map[H5FD_MEM_NTYPES]; - hid_t _memb_fapl[H5FD_MEM_NTYPES]; - char _memb_name[H5FD_MEM_NTYPES][16]; - const char * _memb_name_ptrs[H5FD_MEM_NTYPES]; - haddr_t _memb_addr[H5FD_MEM_NTYPES]; - static const char *letters = "Xsbrglo"; - static const char *func = "H5FDset_fapl_multi"; /* Function Name for error reporting */ + static const char *func = "H5FDset_fapl_multi"; /* Function Name for error reporting */ /*NO TRACE*/ @@ -439,66 +391,9 @@ H5Pset_fapl_multi(hid_t fapl_id, const H5FD_mem_t *memb_map, const hid_t *memb_f /* Check arguments and supply default values */ if (H5I_GENPROP_LST != H5Iget_type(fapl_id) || TRUE != H5Pisa_class(fapl_id, H5P_FILE_ACCESS)) H5Epush_ret(func, H5E_ERR_CLS, H5E_PLIST, H5E_BADVALUE, "not an access list", -1); - if (!memb_map) { - for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) - _memb_map[mt] = H5FD_MEM_DEFAULT; - memb_map = _memb_map; - } - if (!memb_fapl) { - for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) - _memb_fapl[mt] = H5Pcreate(H5P_FILE_ACCESS); - memb_fapl = _memb_fapl; - } - if (!memb_name) { - assert(strlen(letters) == H5FD_MEM_NTYPES); - for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) { - sprintf(_memb_name[mt], "%%s-%c.h5", letters[mt]); - _memb_name_ptrs[mt] = _memb_name[mt]; - } - memb_name = _memb_name_ptrs; - } - if (!memb_addr) { - for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) - _memb_addr[mt] = (hsize_t)(mt ? (mt - 1) : 0) * (HADDR_MAX / (H5FD_MEM_NTYPES - 1)); - memb_addr = _memb_addr; - } - - for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) { - /* Map usage type */ - mmt = memb_map[mt]; - if (mmt < 0 || mmt >= H5FD_MEM_NTYPES) - H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADRANGE, "file resource type out of range", -1); - if (H5FD_MEM_DEFAULT == mmt) - mmt = mt; - - /* - * All members of MEMB_FAPL must be either defaults or actual file - * access property lists. - */ - if (H5P_DEFAULT != memb_fapl[mmt] && TRUE != H5Pisa_class(memb_fapl[mmt], H5P_FILE_ACCESS)) - H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "file resource type incorrect", -1); - - /* All names must be defined */ - if (!memb_name[mmt] || !memb_name[mmt][0]) - H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "file resource type not set", -1); - } - - /* - * Initialize driver specific information. No need to copy it into the FA - * struct since all members will be copied by H5Pset_driver(). - */ - memset(&fa, 0, sizeof(H5FD_multi_fapl_t)); - memcpy(fa.memb_map, memb_map, H5FD_MEM_NTYPES * sizeof(H5FD_mem_t)); - memcpy(fa.memb_fapl, memb_fapl, H5FD_MEM_NTYPES * sizeof(hid_t)); - memcpy(fa.memb_name, memb_name, H5FD_MEM_NTYPES * sizeof(char *)); - memcpy(fa.memb_addr, memb_addr, H5FD_MEM_NTYPES * sizeof(haddr_t)); - fa.relax = relax; + if (H5FD_multi_populate_config(memb_map, memb_fapl, memb_name, memb_addr, relax, &fa) < 0) + H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_CANTSET, "can't setup driver configuration", -1); - /* Patch up H5P_DEFAULT property lists for members */ - for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) { - if (fa.memb_fapl[mt] == H5P_DEFAULT) - fa.memb_fapl[mt] = H5Pcreate(H5P_FILE_ACCESS); - } return H5Pset_driver(fapl_id, H5FD_MULTI, &fa); } @@ -523,6 +418,7 @@ H5Pget_fapl_multi(hid_t fapl_id, H5FD_mem_t *memb_map /*out*/, hid_t *memb_fapl char **memb_name /*out*/, haddr_t *memb_addr /*out*/, hbool_t *relax) { const H5FD_multi_fapl_t *fa; + H5FD_multi_fapl_t default_fa; H5FD_mem_t mt; static const char * func = "H5FDget_fapl_multi"; /* Function Name for error reporting */ @@ -535,8 +431,17 @@ H5Pget_fapl_multi(hid_t fapl_id, H5FD_mem_t *memb_map /*out*/, hid_t *memb_fapl H5Epush_ret(func, H5E_ERR_CLS, H5E_PLIST, H5E_BADTYPE, "not an access list", -1); if (H5FD_MULTI != H5Pget_driver(fapl_id)) H5Epush_ret(func, H5E_ERR_CLS, H5E_PLIST, H5E_BADVALUE, "incorrect VFL driver", -1); - if (NULL == (fa = (const H5FD_multi_fapl_t *)H5Pget_driver_info(fapl_id))) - H5Epush_ret(func, H5E_ERR_CLS, H5E_PLIST, H5E_BADVALUE, "bad VFL driver info", -1); + H5E_BEGIN_TRY + { + fa = (const H5FD_multi_fapl_t *)H5Pget_driver_info(fapl_id); + } + H5E_END_TRY; + if (!fa || (H5P_FILE_ACCESS_DEFAULT == fapl_id)) { + if (H5FD_multi_populate_config(NULL, NULL, NULL, NULL, TRUE, &default_fa) < 0) + H5Epush_ret(func, H5E_ERR_CLS, H5E_VFL, H5E_CANTSET, "can't setup default driver configuration", + -1); + fa = &default_fa; + } if (memb_map) memcpy(memb_map, fa->memb_map, H5FD_MEM_NTYPES * sizeof(H5FD_mem_t)); @@ -565,6 +470,231 @@ H5Pget_fapl_multi(hid_t fapl_id, H5FD_mem_t *memb_map /*out*/, hid_t *memb_fapl } /*------------------------------------------------------------------------- + * Function: H5FD_split_populate_config + * + * Purpose: Populates a H5FD_multi_fapl_t structure with the provided + * split driver values, supplying defaults where values are not + * provided. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD_split_populate_config(const char *meta_ext, hid_t meta_plist_id, const char *raw_ext, hid_t raw_plist_id, + hbool_t relax, H5FD_multi_fapl_t *fa_out) +{ + static const char *func = "H5FD_split_populate_config"; /* Function Name for error reporting */ + static char + meta_name_g[H5FD_MULT_MAX_FILE_NAME_LEN]; /* Static scratch buffer to store metadata member name */ + static char + raw_name_g[H5FD_MULT_MAX_FILE_NAME_LEN]; /* Static scratch buffer to store raw data member name */ + const char *_memb_name[H5FD_MEM_NTYPES]; + H5FD_mem_t _memb_map[H5FD_MEM_NTYPES]; + hid_t _memb_fapl[H5FD_MEM_NTYPES]; + haddr_t _memb_addr[H5FD_MEM_NTYPES]; + herr_t ret_value = 0; + + assert(fa_out); + + /* Initialize */ + ALL_MEMBERS (mt) { + /* Treat global heap as raw data, not metadata */ + _memb_map[mt] = ((mt == H5FD_MEM_DRAW || mt == H5FD_MEM_GHEAP) ? H5FD_MEM_DRAW : H5FD_MEM_SUPER); + _memb_fapl[mt] = H5P_DEFAULT; + _memb_name[mt] = NULL; + _memb_addr[mt] = HADDR_UNDEF; + } + END_MEMBERS; + + /* The file access properties */ + _memb_fapl[H5FD_MEM_SUPER] = meta_plist_id; + _memb_fapl[H5FD_MEM_DRAW] = raw_plist_id; + + /* The names */ + /* process meta filename */ + if (meta_ext) { + if (strstr(meta_ext, "%s")) { + /* Note: this doesn't accommodate for when the '%s' in the user's + * string is at a position >sizeof(meta_name) - QK & JK - 2013/01/17 + */ + strncpy(meta_name_g, meta_ext, sizeof(meta_name_g)); + meta_name_g[sizeof(meta_name_g) - 1] = '\0'; + } + else + snprintf(meta_name_g, sizeof(meta_name_g), "%%s%s", meta_ext); + } + else { + strncpy(meta_name_g, "%s.meta", sizeof(meta_name_g)); + meta_name_g[sizeof(meta_name_g) - 1] = '\0'; + } + _memb_name[H5FD_MEM_SUPER] = meta_name_g; + + /* process raw filename */ + if (raw_ext) { + if (strstr(raw_ext, "%s")) { + /* Note: this doesn't accommodate for when the '%s' in the user's + * string is at a position >sizeof(raw_name) - QK & JK - 2013/01/17 + */ + strncpy(raw_name_g, raw_ext, sizeof(raw_name_g)); + raw_name_g[sizeof(raw_name_g) - 1] = '\0'; + } + else + snprintf(raw_name_g, sizeof(raw_name_g), "%%s%s", raw_ext); + } + else { + strncpy(raw_name_g, "%s.raw", sizeof(raw_name_g)); + raw_name_g[sizeof(raw_name_g) - 1] = '\0'; + } + _memb_name[H5FD_MEM_DRAW] = raw_name_g; + + /* The sizes */ + _memb_addr[H5FD_MEM_SUPER] = 0; + _memb_addr[H5FD_MEM_DRAW] = HADDR_MAX / 2; + + ALL_MEMBERS (mt) { + /* Map usage type */ + H5FD_mem_t mmt = _memb_map[mt]; + if (mmt < 0 || mmt >= H5FD_MEM_NTYPES) + H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADRANGE, "file resource type out of range", -1); + + /* + * All members of MEMB_FAPL must be either defaults or actual file + * access property lists. + */ + if (H5P_DEFAULT != _memb_fapl[mmt] && TRUE != H5Pisa_class(_memb_fapl[mmt], H5P_FILE_ACCESS)) + H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "file resource type incorrect", -1); + + /* All names must be defined */ + if (!_memb_name[mmt] || !_memb_name[mmt][0]) + H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "file resource type not set", -1); + } + END_MEMBERS; + + /* + * Initialize driver specific information. No need to copy it into the FA + * struct since all members will be copied by H5Pset_driver(). + */ + memset(fa_out, 0, sizeof(H5FD_multi_fapl_t)); + memcpy(fa_out->memb_map, _memb_map, H5FD_MEM_NTYPES * sizeof(H5FD_mem_t)); + memcpy(fa_out->memb_fapl, _memb_fapl, H5FD_MEM_NTYPES * sizeof(hid_t)); + memcpy(fa_out->memb_name, _memb_name, H5FD_MEM_NTYPES * sizeof(char *)); + memcpy(fa_out->memb_addr, _memb_addr, H5FD_MEM_NTYPES * sizeof(haddr_t)); + fa_out->relax = relax; + + /* Patch up H5P_DEFAULT property lists for members */ + ALL_MEMBERS (mt) { + if (fa_out->memb_fapl[mt] == H5P_DEFAULT) { + fa_out->memb_fapl[mt] = H5Pcreate(H5P_FILE_ACCESS); + if (H5Pset_fapl_sec2(fa_out->memb_fapl[mt]) < 0) + H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_CANTSET, + "can't set sec2 driver on member FAPL", -1); + } + } + END_MEMBERS; + + return ret_value; +} + +/*------------------------------------------------------------------------- + * Function: H5FD_multi_populate_config + * + * Purpose: Populates a H5FD_multi_fapl_t structure with the provided + * values, supplying defaults where values are not provided. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD_multi_populate_config(const H5FD_mem_t *memb_map, const hid_t *memb_fapl, const char *const *memb_name, + const haddr_t *memb_addr, hbool_t relax, H5FD_multi_fapl_t *fa_out) +{ + static const char *func = "H5FD_multi_populate_config"; /* Function Name for error reporting */ + static const char *letters = "Xsbrglo"; + static char _memb_name_g[H5FD_MEM_NTYPES][16]; /* Static scratch buffer to store member names */ + H5FD_mem_t mt, mmt; + H5FD_mem_t _memb_map[H5FD_MEM_NTYPES]; + hid_t _memb_fapl[H5FD_MEM_NTYPES]; + const char * _memb_name_ptrs[H5FD_MEM_NTYPES]; + haddr_t _memb_addr[H5FD_MEM_NTYPES]; + herr_t ret_value = 0; + + assert(fa_out); + + if (!memb_map) { + for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) + _memb_map[mt] = H5FD_MEM_DEFAULT; + memb_map = _memb_map; + } + if (!memb_fapl) { + for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) { + _memb_fapl[mt] = H5Pcreate(H5P_FILE_ACCESS); + if (H5Pset_fapl_sec2(_memb_fapl[mt]) < 0) + H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_CANTSET, + "can't set sec2 driver on member FAPL", -1); + } + memb_fapl = _memb_fapl; + } + if (!memb_name) { + assert(strlen(letters) == H5FD_MEM_NTYPES); + for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) { + snprintf(_memb_name_g[mt], 16, "%%s-%c.h5", letters[mt]); + _memb_name_ptrs[mt] = _memb_name_g[mt]; + } + memb_name = _memb_name_ptrs; + } + if (!memb_addr) { + for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) + _memb_addr[mt] = (hsize_t)(mt ? (mt - 1) : 0) * (HADDR_MAX / (H5FD_MEM_NTYPES - 1)); + memb_addr = _memb_addr; + } + + for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) { + /* Map usage type */ + mmt = memb_map[mt]; + if (mmt < 0 || mmt >= H5FD_MEM_NTYPES) + H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADRANGE, "file resource type out of range", -1); + if (H5FD_MEM_DEFAULT == mmt) + mmt = mt; + + /* + * All members of MEMB_FAPL must be either defaults or actual file + * access property lists. + */ + if (H5P_DEFAULT != memb_fapl[mmt] && TRUE != H5Pisa_class(memb_fapl[mmt], H5P_FILE_ACCESS)) + H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "file resource type incorrect", -1); + + /* All names must be defined */ + if (!memb_name[mmt] || !memb_name[mmt][0]) + H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "file resource type not set", -1); + } + + /* + * Initialize driver specific information. No need to copy it into the FA + * struct since all members will be copied by H5Pset_driver(). + */ + memset(fa_out, 0, sizeof(H5FD_multi_fapl_t)); + memcpy(fa_out->memb_map, memb_map, H5FD_MEM_NTYPES * sizeof(H5FD_mem_t)); + memcpy(fa_out->memb_fapl, memb_fapl, H5FD_MEM_NTYPES * sizeof(hid_t)); + memcpy(fa_out->memb_name, memb_name, H5FD_MEM_NTYPES * sizeof(char *)); + memcpy(fa_out->memb_addr, memb_addr, H5FD_MEM_NTYPES * sizeof(haddr_t)); + fa_out->relax = relax; + + /* Patch up H5P_DEFAULT property lists for members */ + for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) { + if (fa_out->memb_fapl[mt] == H5P_DEFAULT) { + fa_out->memb_fapl[mt] = H5Pcreate(H5P_FILE_ACCESS); + if (H5Pset_fapl_sec2(fa_out->memb_fapl[mt]) < 0) + H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_CANTSET, + "can't set sec2 driver on member FAPL", -1); + } + } + + return ret_value; +} /* end H5FD_multi_populate_config() */ + +/*------------------------------------------------------------------------- * Function: H5FD_multi_sb_size * * Purpose: Returns the size of the private information to be stored in @@ -1009,12 +1139,26 @@ H5FD_multi_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr */ if (NULL == (file = (H5FD_multi_t *)calloc((size_t)1, sizeof(H5FD_multi_t)))) H5Epush_ret(func, H5E_ERR_CLS, H5E_RESOURCE, H5E_NOSPACE, "memory allocation failed", NULL); - if (H5P_FILE_ACCESS_DEFAULT == fapl_id || H5FD_MULTI != H5Pget_driver(fapl_id)) { + H5E_BEGIN_TRY + { + fa = (const H5FD_multi_fapl_t *)H5Pget_driver_info(fapl_id); + } + H5E_END_TRY; + if (!fa || (H5P_FILE_ACCESS_DEFAULT == fapl_id) || (H5FD_MULTI != H5Pget_driver(fapl_id))) { + char *env = getenv(HDF5_DRIVER); + close_fapl = fapl_id = H5Pcreate(H5P_FILE_ACCESS); - if (H5Pset_fapl_multi(fapl_id, NULL, NULL, NULL, NULL, TRUE) < 0) - H5Epush_goto(func, H5E_ERR_CLS, H5E_FILE, H5E_CANTSET, "can't set property value", error) + if (env && !strcmp(env, "split")) { + if (H5Pset_fapl_split(fapl_id, NULL, H5P_DEFAULT, NULL, H5P_DEFAULT) < 0) + H5Epush_goto(func, H5E_ERR_CLS, H5E_FILE, H5E_CANTSET, "can't set property value", error) + } + else { + if (H5Pset_fapl_multi(fapl_id, NULL, NULL, NULL, NULL, TRUE) < 0) + H5Epush_goto(func, H5E_ERR_CLS, H5E_FILE, H5E_CANTSET, "can't set property value", error) + } + + fa = (const H5FD_multi_fapl_t *)H5Pget_driver_info(fapl_id); } - fa = (const H5FD_multi_fapl_t *)H5Pget_driver_info(fapl_id); assert(fa); ALL_MEMBERS (mt) { file->fa.memb_map[mt] = fa->memb_map[mt]; @@ -2037,6 +2181,7 @@ H5FD_multi_delete(const char *filename, hid_t fapl_id) char full_filename[H5FD_MULT_MAX_FILE_NAME_LEN]; int nchars; const H5FD_multi_fapl_t *fa; + H5FD_multi_fapl_t default_fa; static const char * func = "H5FD_multi_delete"; /* Function Name for error reporting */ /* Clear the error stack */ @@ -2044,11 +2189,26 @@ H5FD_multi_delete(const char *filename, hid_t fapl_id) assert(filename); - /* Quiet compiler */ - (void)fapl_id; - /* Get the driver info */ - fa = (const H5FD_multi_fapl_t *)H5Pget_driver_info(fapl_id); + H5E_BEGIN_TRY + { + fa = (const H5FD_multi_fapl_t *)H5Pget_driver_info(fapl_id); + } + H5E_END_TRY; + if (!fa) { + char *env = getenv(HDF5_DRIVER); + + if (env && !strcmp(env, "split")) { + if (H5FD_split_populate_config(NULL, H5P_DEFAULT, NULL, H5P_DEFAULT, TRUE, &default_fa) < 0) + H5Epush_ret(func, H5E_ERR_CLS, H5E_VFL, H5E_CANTSET, "can't setup driver configuration", -1); + } + else { + if (H5FD_multi_populate_config(NULL, NULL, NULL, NULL, TRUE, &default_fa) < 0) + H5Epush_ret(func, H5E_ERR_CLS, H5E_VFL, H5E_CANTSET, "can't setup driver configuration", -1); + } + + fa = &default_fa; + } assert(fa); /* Delete each member file using the underlying fapl */ @@ -2070,6 +2230,54 @@ H5FD_multi_delete(const char *filename, hid_t fapl_id) } /* end H5FD_multi_delete() */ H5_MULTI_GCC_DIAG_ON("format-nonliteral") +/*------------------------------------------------------------------------- + * Function: H5FD_multi_ctl + * + * Purpose: Multi VFD version of the ctl callback. + * + * The desired operation is specified by the op_code + * parameter. + * + * The flags parameter controls management of op_codes that + * are unknown to the callback + * + * The input and output parameters allow op_code specific + * input and output + * + * At present, this VFD supports no op codes of its own. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD_multi_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void *input, void **output) +{ + H5FD_multi_t * file = (H5FD_multi_t *)_file; + static const char *func = "H5FD_multi_ctl"; /* Function Name for error reporting */ + herr_t ret_value = 0; + + /* Silence compiler */ + (void)file; + (void)input; + (void)output; + + /* Clear the error stack */ + H5Eclear2(H5E_DEFAULT); + + switch (op_code) { + /* Unknown op code */ + default: + if (flags & H5FD_CTL__FAIL_IF_UNKNOWN_FLAG) + H5Epush_ret(func, H5E_ERR_CLS, H5E_VFL, H5E_FCNTL, + "VFD ctl request failed (unknown op code and fail if unknown flag is set)", -1); + + break; + } + + return ret_value; +} /* end H5FD_multi_ctl() */ + #ifdef H5private_H /* * This is not related to the functionality of the driver code. diff --git a/src/H5FDmulti.h b/src/H5FDmulti.h index 62cc9c8..7a01f4c 100644 --- a/src/H5FDmulti.h +++ b/src/H5FDmulti.h @@ -20,7 +20,7 @@ #ifndef H5FDmulti_H #define H5FDmulti_H -#define H5FD_MULTI (H5FD_multi_init()) +#define H5FD_MULTI (H5FDperform_init(H5FD_multi_init)) #ifdef __cplusplus extern "C" { diff --git a/src/H5FDonion.c b/src/H5FDonion.c index 6232a04..2fa81a6 100644 --- a/src/H5FDonion.c +++ b/src/H5FDonion.c @@ -29,8 +29,7 @@ #include "H5Iprivate.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ -/* The driver identification number, initialized at runtime - */ +/* The driver identification number, initialized at runtime */ static hid_t H5FD_ONION_g = 0; /****************************************************************************** @@ -171,6 +170,8 @@ static herr_t H5FD__onion_sb_decode(H5FD_t *_file, const char *name, const unsi static hsize_t H5FD__onion_sb_size(H5FD_t *_file); static const H5FD_class_t H5FD_onion_g = { + H5FD_CLASS_VERSION, /* struct version */ + H5FD_ONION_VALUE, /* value */ "onion", /* name */ MAXADDR, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -198,39 +199,20 @@ static const H5FD_class_t H5FD_onion_g = { NULL, /* get_handle */ H5FD__onion_read, /* read */ H5FD__onion_write, /* write */ + NULL, /* read_vector */ + NULL, /* write_vector */ + NULL, /* read_selection */ + NULL, /* write_selection */ NULL, /* flush */ NULL, /* truncate */ NULL, /* lock */ NULL, /* unlock */ - NULL, /* del */ + NULL, /* del */ + NULL, /* ctl */ H5FD_FLMAP_DICHOTOMY /* fl_map */ }; /*----------------------------------------------------------------------------- - * Function: H5FD__init_package - * - * Purpose: Initializes any interface-specific data or routines. - * - * Return: Non-negative on success/Negative on failure - * - *----------------------------------------------------------------------------- - */ -static herr_t -H5FD__init_package(void) -{ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_STATIC - - if (H5FD_onion_init() < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "unable to initialize Onion VFD") - -done: - FUNC_LEAVE_NOAPI(ret_value) - -} /* end H5FD__init_package() */ - -/*----------------------------------------------------------------------------- * Function: H5FD_onion_init * * Purpose: Initialize this driver by registering the driver with the @@ -246,7 +228,7 @@ H5FD_onion_init(void) { hid_t ret_value = H5I_INVALID_HID; - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR if (H5I_VFL != H5I_get_type(H5FD_ONION_g)) H5FD_ONION_g = H5FD_register(&H5FD_onion_g, sizeof(H5FD_class_t), FALSE); @@ -254,9 +236,7 @@ H5FD_onion_init(void) /* Set return value */ ret_value = H5FD_ONION_g; -done: FUNC_LEAVE_NOAPI(ret_value) - } /* end H5FD_onion_init() */ /*----------------------------------------------------------------------------- @@ -271,7 +251,7 @@ done: static herr_t H5FD__onion_term(void) { - FUNC_ENTER_STATIC_NOERR; + FUNC_ENTER_STATIC_NOERR /* Reset VFL ID */ H5FD_ONION_g = 0; @@ -368,7 +348,7 @@ H5Pset_fapl_onion(hid_t fapl_id, const H5FD_onion_fapl_info_t *fa) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid backing fapl id") } - ret_value = H5P_set_driver(plist, H5FD_ONION, (const void *)fa); + ret_value = H5P_set_driver(plist, H5FD_ONION, (const void *)fa, NULL); done: FUNC_LEAVE_API(ret_value) diff --git a/src/H5FDonion.h b/src/H5FDonion.h index d583a75..535f4d7 100644 --- a/src/H5FDonion.h +++ b/src/H5FDonion.h @@ -18,7 +18,9 @@ #ifndef H5FDonion_H #define H5FDonion_H -#define H5FD_ONION (H5FD_onion_init()) +#define H5FD_ONION (H5FDperform_init(H5FD_onion_init)) +#define H5FD_ONION_VALUE H5_VFD_ONION + #define H5FD_ONION_ENABLE_INDEX_STATS 0 @@ -127,10 +129,6 @@ typedef struct H5FD_onion_fapl_info_t { extern "C" { #endif -/* - * PUBLIC PROTOTYPES - */ - H5_DLL hid_t H5FD_onion_init(void); H5_DLL herr_t H5Pget_fapl_onion(hid_t fapl_id, H5FD_onion_fapl_info_t *fa_out); H5_DLL herr_t H5Pset_fapl_onion(hid_t fapl_id, const H5FD_onion_fapl_info_t *fa); diff --git a/src/H5FDperform.c b/src/H5FDperform.c new file mode 100644 index 0000000..4a68c6e --- /dev/null +++ b/src/H5FDperform.c @@ -0,0 +1,59 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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 COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://www.hdfgroup.org/licenses. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/****************/ +/* Module Setup */ +/****************/ + +#include "H5FDmodule.h" /* This source code file is part of the H5FD module */ + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5CXprivate.h" /* API Contexts */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5FDpkg.h" /* File Drivers */ +#include "H5Iprivate.h" /* IDs */ + +/*------------------------------------------------------------------------- + * Function: H5FDperform_init + * + * Purpose: Ensure that the library is initialized and then call + * the provided VFD initializer + * + * Return: Success: Identifier for the VFD just initialized + * Failure: H5I_INVALID_HID + *------------------------------------------------------------------------- + */ +hid_t +H5FDperform_init(H5FD_init_t op) +{ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_API_NOINIT + /*NO TRACE*/ + + /* It is possible that an application will evaluate an + * `H5FD_*` symbol (`H5FD_FAMILY`, `H5FD_MULTI`, `H5FD_SEC2`, etc. + * before the library has had an opportunity to initialize. Call + * H5_init_library() to make sure that the library has been initialized + * before `init` is run. + */ + if (H5_init_library() < 0) + HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, H5I_INVALID_HID, "library initialization failed") + + ret_value = op(); + +done: + FUNC_LEAVE_API_NOINIT(ret_value) +} diff --git a/src/H5FDprivate.h b/src/H5FDprivate.h index c00c123..bcbc693 100644 --- a/src/H5FDprivate.h +++ b/src/H5FDprivate.h @@ -24,6 +24,7 @@ /* Private headers needed by this file */ #include "H5Pprivate.h" /* Property lists */ +#include "H5Sprivate.h" /* Dataspaces */ /* * The MPI drivers are needed because there are @@ -45,13 +46,6 @@ /* Definitions for file MPI type property */ #define H5FD_MPI_XFER_FILE_MPI_TYPE_NAME "H5FD_mpi_file_mpi_type" -/* Sub-class the H5FD_class_t to add more specific functions for MPI-based VFDs */ -typedef struct H5FD_class_mpi_t { - H5FD_class_t super; /* Superclass information & methods */ - int (*get_rank)(const H5FD_t *file); /* Get the MPI rank of a process */ - int (*get_size)(const H5FD_t *file); /* Get the MPI size of a communicator */ - MPI_Comm (*get_comm)(const H5FD_t *file); /* Get the communicator for a file */ -} H5FD_class_mpi_t; #endif /****************************/ @@ -88,12 +82,22 @@ typedef struct { } \ } -/* Define structure to hold driver ID & info for FAPLs */ +/* Define structure to hold driver ID, info & configuration string for FAPLs */ typedef struct { - hid_t driver_id; /* Driver's ID */ - const void *driver_info; /* Driver info, for open callbacks */ + hid_t driver_id; /* Driver's ID */ + const void *driver_info; /* Driver info, for open callbacks */ + const char *driver_config_str; /* Driver configuration string */ } H5FD_driver_prop_t; +/* Which kind of VFD field to use for searching */ +typedef enum H5FD_get_driver_kind_t { + H5FD_GET_DRIVER_BY_NAME, /* Name field is set */ + H5FD_GET_DRIVER_BY_VALUE /* Value field is set */ +} H5FD_get_driver_kind_t; + +/* Forward declarations for prototype arguments */ +struct H5S_t; + /*****************************/ /* Library Private Variables */ /*****************************/ @@ -104,6 +108,7 @@ typedef struct { /* Forward declarations for prototype arguments */ struct H5F_t; +union H5PL_key_t; H5_DLL int H5FD_term_interface(void); H5_DLL herr_t H5FD_locate_signature(H5FD_t *file, haddr_t *sig_addr); @@ -114,10 +119,17 @@ H5_DLL herr_t H5FD_sb_load(H5FD_t *file, const char *name, const uint8_t H5_DLL void * H5FD_fapl_get(H5FD_t *file); H5_DLL herr_t H5FD_free_driver_info(hid_t driver_id, const void *driver_info); H5_DLL hid_t H5FD_register(const void *cls, size_t size, hbool_t app_ref); +H5_DLL hid_t H5FD_register_driver_by_name(const char *name, hbool_t app_ref); +H5_DLL hid_t H5FD_register_driver_by_value(H5FD_class_value_t value, hbool_t app_ref); +H5_DLL htri_t H5FD_is_driver_registered_by_name(const char *driver_name, hid_t *registered_id); +H5_DLL htri_t H5FD_is_driver_registered_by_value(H5FD_class_value_t driver_value, hid_t *registered_id); +H5_DLL hid_t H5FD_get_driver_id_by_name(const char *name, hbool_t is_api); +H5_DLL hid_t H5FD_get_driver_id_by_value(H5FD_class_value_t value, hbool_t is_api); H5_DLL H5FD_t *H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr); H5_DLL herr_t H5FD_close(H5FD_t *file); H5_DLL int H5FD_cmp(const H5FD_t *f1, const H5FD_t *f2); H5_DLL herr_t H5FD_driver_query(const H5FD_class_t *driver, unsigned long *flags /*out*/); +H5_DLL herr_t H5FD_check_plugin_load(const H5FD_class_t *cls, const union H5PL_key_t *key, hbool_t *success); H5_DLL haddr_t H5FD_alloc(H5FD_t *file, H5FD_mem_t type, struct H5F_t *f, hsize_t size, haddr_t *frag_addr, hsize_t *frag_size); H5_DLL herr_t H5FD_free(H5FD_t *file, H5FD_mem_t type, struct H5F_t *f, haddr_t addr, hsize_t size); @@ -132,17 +144,40 @@ H5_DLL herr_t H5FD_set_feature_flags(H5FD_t *file, unsigned long feature_flags) H5_DLL herr_t H5FD_get_fs_type_map(const H5FD_t *file, H5FD_mem_t *type_map); H5_DLL herr_t H5FD_read(H5FD_t *file, H5FD_mem_t type, haddr_t addr, size_t size, void *buf /*out*/); H5_DLL herr_t H5FD_write(H5FD_t *file, H5FD_mem_t type, haddr_t addr, size_t size, const void *buf); +H5_DLL herr_t H5FD_read_vector(H5FD_t *file, uint32_t count, H5FD_mem_t types[], haddr_t addrs[], + size_t sizes[], void *bufs[] /* out */); +H5_DLL herr_t H5FD_write_vector(H5FD_t *file, uint32_t count, H5FD_mem_t types[], haddr_t addrs[], + size_t sizes[], const void *bufs[] /* out */); +H5_DLL herr_t H5FD_read_selection(H5FD_t *file, H5FD_mem_t type, uint32_t count, struct H5S_t **mem_spaces, + struct H5S_t **file_spaces, haddr_t offsets[], size_t element_sizes[], + void *bufs[] /* out */); +H5_DLL herr_t H5FD_write_selection(H5FD_t *file, H5FD_mem_t type, uint32_t count, struct H5S_t **mem_spaces, + struct H5S_t **file_spaces, haddr_t offsets[], size_t element_sizes[], + const void *bufs[]); +H5_DLL herr_t H5FD_read_selection_id(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem_space_ids[], + hid_t file_space_ids[], haddr_t offsets[], size_t element_sizes[], + void *bufs[] /* out */); +H5_DLL herr_t H5FD_write_selection_id(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem_space_ids[], + hid_t file_space_ids[], haddr_t offsets[], size_t element_sizes[], + const void *bufs[]); H5_DLL herr_t H5FD_flush(H5FD_t *file, hbool_t closing); H5_DLL herr_t H5FD_truncate(H5FD_t *file, hbool_t closing); H5_DLL herr_t H5FD_lock(H5FD_t *file, hbool_t rw); H5_DLL herr_t H5FD_unlock(H5FD_t *file); H5_DLL herr_t H5FD_delete(const char *name, hid_t fapl_id); +H5_DLL herr_t H5FD_ctl(H5FD_t *file, uint64_t op_code, uint64_t flags, const void *input, void **output); H5_DLL herr_t H5FD_get_fileno(const H5FD_t *file, unsigned long *filenum); H5_DLL herr_t H5FD_get_vfd_handle(H5FD_t *file, hid_t fapl, void **file_handle); H5_DLL herr_t H5FD_set_base_addr(H5FD_t *file, haddr_t base_addr); H5_DLL haddr_t H5FD_get_base_addr(const H5FD_t *file); H5_DLL herr_t H5FD_set_paged_aggr(H5FD_t *file, hbool_t paged); +H5_DLL herr_t H5FD_sort_vector_io_req(hbool_t *vector_was_sorted, uint32_t count, H5FD_mem_t types[], + haddr_t addrs[], size_t sizes[], H5_flexible_const_ptr_t bufs[], + H5FD_mem_t **s_types_ptr, haddr_t **s_addrs_ptr, size_t **s_sizes_ptr, + H5_flexible_const_ptr_t **s_bufs_ptr); +H5_DLL herr_t H5FD_init(void); + /* Function prototypes for MPI based VFDs*/ #ifdef H5_HAVE_PARALLEL /* General routines */ @@ -156,9 +191,9 @@ H5_DLL herr_t H5FD_set_mpio_atomicity(H5FD_t *file, hbool_t flag); H5_DLL herr_t H5FD_get_mpio_atomicity(H5FD_t *file, hbool_t *flag); /* Driver specific methods */ -H5_DLL int H5FD_mpi_get_rank(const H5FD_t *file); -H5_DLL int H5FD_mpi_get_size(const H5FD_t *file); -H5_DLL MPI_Comm H5FD_mpi_get_comm(const H5FD_t *_file); +H5_DLL int H5FD_mpi_get_rank(H5FD_t *file); +H5_DLL int H5FD_mpi_get_size(H5FD_t *file); +H5_DLL MPI_Comm H5FD_mpi_get_comm(H5FD_t *file); #endif /* H5_HAVE_PARALLEL */ #endif /* H5FDprivate_H */ diff --git a/src/H5FDpublic.h b/src/H5FDpublic.h index 0cfb072..f8f88f3 100644 --- a/src/H5FDpublic.h +++ b/src/H5FDpublic.h @@ -28,6 +28,40 @@ #define H5FD_VFD_DEFAULT 0 /* Default VFL driver value */ +/* VFD identifier values + * These are H5FD_class_value_t values, NOT hid_t values! + */ +#define H5_VFD_INVALID ((H5FD_class_value_t)(-1)) +#define H5_VFD_SEC2 ((H5FD_class_value_t)(0)) +#define H5_VFD_CORE ((H5FD_class_value_t)(1)) +#define H5_VFD_LOG ((H5FD_class_value_t)(2)) +#define H5_VFD_FAMILY ((H5FD_class_value_t)(3)) +#define H5_VFD_MULTI ((H5FD_class_value_t)(4)) +#define H5_VFD_STDIO ((H5FD_class_value_t)(5)) +#define H5_VFD_SPLITTER ((H5FD_class_value_t)(6)) +#ifdef H5_HAVE_PARALLEL +#define H5_VFD_MPIO ((H5FD_class_value_t)(7)) +#endif +#ifdef H5_HAVE_DIRECT +#define H5_VFD_DIRECT ((H5FD_class_value_t)(8)) +#endif +#ifdef H5_HAVE_MIRROR_VFD +#define H5_VFD_MIRROR ((H5FD_class_value_t)(9)) +#endif +#ifdef H5_HAVE_LIBHDFS +#define H5_VFD_HDFS ((H5FD_class_value_t)(10)) +#endif +#ifdef H5_HAVE_ROS3_VFD +#define H5_VFD_ROS3 ((H5FD_class_value_t)(11)) +#endif +#define H5_VFD_ONION ((H5FD_class_value_t)(12)) + +/* VFD IDs below this value are reserved for library use. */ +#define H5_VFD_RESERVED 256 + +/* Maximum VFD ID */ +#define H5_VFD_MAX 65535 + /* Define VFL driver features that can be enabled on a per-driver basis */ /* These are returned with the 'query' function pointer in H5FD_class_t */ /* @@ -137,11 +171,103 @@ * enabled may be used as the Write-Only (W/O) channel driver. */ #define H5FD_FEAT_DEFAULT_VFD_COMPATIBLE 0x00008000 +/* + * Defining H5FD_FEAT_MEMMANAGE for a VFL driver means that + * the driver uses special memory management routines or wishes + * to do memory management in a specific manner. Therefore, HDF5 + * should request that the driver handle any memory management + * operations when appropriate. + */ +#define H5FD_FEAT_MEMMANAGE 0x00010000 + +/* ctl function definitions: */ +#define H5FD_CTL_OPC_RESERVED 512 /* Opcodes below this value are reserved for library use */ +#define H5FD_CTL_OPC_EXPER_MIN \ + H5FD_CTL_OPC_RESERVED /* Minimum opcode value available for experimental use \ + */ +#define H5FD_CTL_OPC_EXPER_MAX \ + (H5FD_CTL_OPC_RESERVED + 511) /* Maximum opcode value available for experimental use */ + +/* ctl function op codes: */ +#define H5FD_CTL__INVALID_OPCODE 0 +#define H5FD_CTL__TEST_OPCODE 1 +#define H5FD_CTL__GET_MPI_COMMUNICATOR_OPCODE 2 +#define H5FD_CTL__GET_MPI_RANK_OPCODE 3 +#define H5FD_CTL__GET_MPI_SIZE_OPCODE 4 +#define H5FD_CTL__MEM_ALLOC 5 +#define H5FD_CTL__MEM_FREE 6 +#define H5FD_CTL__MEM_COPY 7 + +/* ctl function flags: */ + +/* Definitions: + * + * WARNING: While the following definitions of Terminal + * and Passthrough VFDs should be workable for now, they + * have to be adjusted as our use cases for VFDs expand. + * + * JRM -- 8/4/21 + * + * + * Terminal VFD: Lowest VFD in the VFD stack through + * which all VFD calls pass. Note that this definition + * is situational. For example, the sec2 VFD is typically + * terminal. However, in the context of the family file + * driver, it is not -- the family file driver is the + * bottom VFD through which all VFD calls pass, and thus + * it is terminal. + * + * Similarly, on the splitter VFD, a sec2 VFD on the + * R/W channel is terminal, but a sec2 VFD on the W/O + * channel is not. + * + * + * Pass through VFD: Any VFD that relays all VFD calls + * (with the possible exception of some non-I/O related + * calls) to underlying VFD(s). + */ + +/* Unknown op codes should be ignored silently unless the + * H5FD_CTL__FAIL_IF_UNKNOWN_FLAG is set. + * + * On terminal VFDs, unknown op codes should generate an + * error unconditionally if this flag is set. + * + * On pass through VFDs, unknown op codes should be routed + * to the underlying VFD(s) as indicated by any routing + * flags. In the absence of such flags, the VFD should + * generate an error. + */ +#define H5FD_CTL__FAIL_IF_UNKNOWN_FLAG 0x0001 + +/* The H5FD_CTL__ROUTE_TO_TERMINAL_VFD_FLAG is used only + * by non-ternminal VFDs, and only applies to unknown + * opcodes. (known op codes should be handled as + * appropriate.) + * + * If this flag is set for an unknown op code, that + * op code should be passed to the next VFD down + * the VFD stack en-route to the terminal VFD. + * If that VFD does not support the ctl call, the + * pass through VFD should fail or succeed as directed + * by the H5FD_CTL__FAIL_IF_UNKNOWN_FLAG. + */ +#define H5FD_CTL__ROUTE_TO_TERMINAL_VFD_FLAG 0x0002 /*******************/ /* Public Typedefs */ /*******************/ +/* + * File driver identifiers. + * + * Values 0 through 255 are for drivers defined by the HDF5 library. + * Values 256 through 511 are available for testing new drivers. + * Subsequent values should be obtained from the HDF5 development + * team at mailto:help@hdfgroup.org. + */ +typedef int H5FD_class_value_t; + /* Types of allocation requests: see H5Fpublic.h */ typedef enum H5F_mem_t H5FD_mem_t; @@ -253,6 +379,19 @@ typedef struct { } H5FD_file_image_callbacks_t; //! <!-- [H5FD_file_image_callbacks_t_snip] --> +/** + * Define structure to hold "ctl memory copy" parameters + */ +//! <!-- [H5FD_ctl_memcpy_args_t_snip] --> +typedef struct H5FD_ctl_memcpy_args_t { + void * dstbuf; /**< Destination buffer */ + hsize_t dst_off; /**< Offset within destination buffer */ + const void *srcbuf; /**< Source buffer */ + hsize_t src_off; /**< Offset within source buffer */ + size_t len; /**< Length of data to copy from source buffer */ +} H5FD_ctl_memcpy_args_t; +//! <!-- [H5FD_ctl_memcpy_args_t_snip] --> + /********************/ /* Public Variables */ /********************/ diff --git a/src/H5FDros3.c b/src/H5FDros3.c index c0361f9..fcce76d 100644 --- a/src/H5FDros3.c +++ b/src/H5FDros3.c @@ -237,6 +237,8 @@ static herr_t H5FD__ros3_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing static herr_t H5FD__ros3_validate_config(const H5FD_ros3_fapl_t *fa); static const H5FD_class_t H5FD_ros3_g = { + H5FD_CLASS_VERSION, /* struct version */ + H5FD_ROS3_VALUE, /* value */ "ros3", /* name */ MAXADDR, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -264,11 +266,16 @@ static const H5FD_class_t H5FD_ros3_g = { H5FD__ros3_get_handle, /* get_handle */ H5FD__ros3_read, /* read */ H5FD__ros3_write, /* write */ + NULL, /* read_vector */ + NULL, /* write_vector */ + NULL, /* read_selection */ + NULL, /* write_selection */ NULL, /* flush */ H5FD__ros3_truncate, /* truncate */ NULL, /* lock */ NULL, /* unlock */ NULL, /* del */ + NULL, /* ctl */ H5FD_FLMAP_DICHOTOMY /* fl_map */ }; @@ -276,31 +283,6 @@ static const H5FD_class_t H5FD_ros3_g = { H5FL_DEFINE_STATIC(H5FD_ros3_t); /*------------------------------------------------------------------------- - * Function: H5FD__init_package - * - * Purpose: Initializes any interface-specific data or routines. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Jacob Smith 2017 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5FD__init_package(void) -{ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_STATIC - - if (H5FD_ros3_init() < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "unable to initialize ros3 VFD") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD__init_package() */ - -/*------------------------------------------------------------------------- * Function: H5FD_ros3_init * * Purpose: Initialize this driver by registering the driver with the @@ -327,8 +309,12 @@ H5FD_ros3_init(void) HDfprintf(stdout, "H5FD_ros3_init() called.\n"); #endif - if (H5I_VFL != H5I_get_type(H5FD_ROS3_g)) + if (H5I_VFL != H5I_get_type(H5FD_ROS3_g)) { H5FD_ROS3_g = H5FD_register(&H5FD_ros3_g, sizeof(H5FD_class_t), FALSE); + if (H5I_INVALID_HID == H5FD_ROS3_g) { + HGOTO_ERROR(H5E_ID, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register ros3"); + } + } #if ROS3_STATS /* pre-compute statsbin boundaries @@ -377,7 +363,7 @@ H5FD__ros3_term(void) * Function: H5Pset_fapl_ros3 * * Purpose: Modify the file access property list to use the H5FD_ROS3 - * driver defined in this source file. All driver specfic + * driver defined in this source file. All driver specific * properties are passed in as a pointer to a suitably * initialized instance of H5FD_ros3_fapl_t * @@ -410,7 +396,7 @@ H5Pset_fapl_ros3(hid_t fapl_id, H5FD_ros3_fapl_t *fa) if (FAIL == H5FD__ros3_validate_config(fa)) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid ros3 config") - ret_value = H5P_set_driver(plist, H5FD_ROS3, (void *)fa); + ret_value = H5P_set_driver(plist, H5FD_ROS3, (void *)fa, NULL); done: FUNC_LEAVE_API(ret_value) @@ -420,16 +406,16 @@ done: * Function: H5FD__ros3_validate_config() * * Purpose: Test to see if the supplied instance of H5FD_ros3_fapl_t - * contains internally consistant data. Return SUCCEED if so, + * contains internally consistent data. Return SUCCEED if so, * and FAIL otherwise. * - * Note the difference between internally consistant and + * Note the difference between internally consistent and * correct. As we will have to try to access the target * object to determine whether the supplied data is correct, - * we will settle for internal consistancy at this point + * we will settle for internal consistency at this point * * Return: SUCCEED if instance of H5FD_ros3_fapl_t contains internally - * consistant data, FAIL otherwise. + * consistent data, FAIL otherwise. * * Programmer: Jacob Smith * 9/10/17 diff --git a/src/H5FDros3.h b/src/H5FDros3.h index 8e42ca2..4a623c4 100644 --- a/src/H5FDros3.h +++ b/src/H5FDros3.h @@ -22,9 +22,11 @@ #define H5FDros3_H #ifdef H5_HAVE_ROS3_VFD -#define H5FD_ROS3 (H5FD_ros3_init()) +#define H5FD_ROS3 (H5FDperform_init(H5FD_ros3_init)) +#define H5FD_ROS3_VALUE H5_VFD_ROS3 #else -#define H5FD_ROS3 (H5I_INVALID_HID) +#define H5FD_ROS3 (H5I_INVALID_HID) +#define H5FD_ROS3_VALUE H5_VFD_INVALID #endif /* H5_HAVE_ROS3_VFD */ #ifdef H5_HAVE_ROS3_VFD diff --git a/src/H5FDs3comms.h b/src/H5FDs3comms.h index da6a62d..b81bfae 100644 --- a/src/H5FDs3comms.h +++ b/src/H5FDs3comms.h @@ -179,7 +179,7 @@ * HTTP header fields, of particular use when composing an * "S3 Canonical Request" for authentication. * - * - The creation of a Canoncial Request involves: + * - The creation of a Canonical Request involves: * - convert field names to lower case * - sort by this lower-case name * - convert ": " name-value separator in HTTP string to ":" @@ -459,7 +459,7 @@ typedef struct { * * Pointer to NULL-terminated string for "secret" access id to S3 resource. * - * Requred to authenticate. + * Required to authenticate. * * `signing_key` (unsigned char *) * @@ -470,7 +470,7 @@ typedef struct { * which may be re-used for several (up to seven (7)) days from creation? * Computed once upon file open. * - * Requred to authenticate. + * Required to authenticate. * *---------------------------------------------------------------------------- */ diff --git a/src/H5FDsec2.c b/src/H5FDsec2.c index d823e3c..cc417070 100644 --- a/src/H5FDsec2.c +++ b/src/H5FDsec2.c @@ -139,8 +139,12 @@ static herr_t H5FD__sec2_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing static herr_t H5FD__sec2_lock(H5FD_t *_file, hbool_t rw); static herr_t H5FD__sec2_unlock(H5FD_t *_file); static herr_t H5FD__sec2_delete(const char *filename, hid_t fapl_id); +static herr_t H5FD__sec2_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void *input, + void **output); static const H5FD_class_t H5FD_sec2_g = { + H5FD_CLASS_VERSION, /* struct version */ + H5FD_SEC2_VALUE, /* value */ "sec2", /* name */ MAXADDR, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -168,11 +172,16 @@ static const H5FD_class_t H5FD_sec2_g = { H5FD__sec2_get_handle, /* get_handle */ H5FD__sec2_read, /* read */ H5FD__sec2_write, /* write */ + NULL, /* read_vector */ + NULL, /* write_vector */ + NULL, /* read_selection */ + NULL, /* write_selection */ NULL, /* flush */ H5FD__sec2_truncate, /* truncate */ H5FD__sec2_lock, /* lock */ H5FD__sec2_unlock, /* unlock */ H5FD__sec2_delete, /* del */ + H5FD__sec2_ctl, /* ctl */ H5FD_FLMAP_DICHOTOMY /* fl_map */ }; @@ -180,39 +189,6 @@ static const H5FD_class_t H5FD_sec2_g = { H5FL_DEFINE_STATIC(H5FD_sec2_t); /*------------------------------------------------------------------------- - * Function: H5FD__init_package - * - * Purpose: Initializes any interface-specific data or routines. - * - * Return: Non-negative on success/Negative on failure - * - *------------------------------------------------------------------------- - */ -static herr_t -H5FD__init_package(void) -{ - char * lock_env_var = NULL; /* Environment variable pointer */ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_STATIC - - /* Check the use disabled file locks environment variable */ - lock_env_var = HDgetenv("HDF5_USE_FILE_LOCKING"); - if (lock_env_var && !HDstrcmp(lock_env_var, "BEST_EFFORT")) - ignore_disabled_file_locks_s = TRUE; /* Override: Ignore disabled locks */ - else if (lock_env_var && (!HDstrcmp(lock_env_var, "TRUE") || !HDstrcmp(lock_env_var, "1"))) - ignore_disabled_file_locks_s = FALSE; /* Override: Don't ignore disabled locks */ - else - ignore_disabled_file_locks_s = FAIL; /* Environment variable not set, or not set correctly */ - - if (H5FD_sec2_init() < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "unable to initialize sec2 VFD") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5FD__init_package() */ - -/*------------------------------------------------------------------------- * Function: H5FD_sec2_init * * Purpose: Initialize this driver by registering the driver with the @@ -229,9 +205,19 @@ done: hid_t H5FD_sec2_init(void) { - hid_t ret_value = H5I_INVALID_HID; /* Return value */ + char *lock_env_var = NULL; /* Environment variable pointer */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ - FUNC_ENTER_NOAPI(H5I_INVALID_HID) + FUNC_ENTER_NOAPI_NOERR + + /* Check the use disabled file locks environment variable */ + lock_env_var = HDgetenv(HDF5_USE_FILE_LOCKING); + if (lock_env_var && !HDstrcmp(lock_env_var, "BEST_EFFORT")) + ignore_disabled_file_locks_s = TRUE; /* Override: Ignore disabled locks */ + else if (lock_env_var && (!HDstrcmp(lock_env_var, "TRUE") || !HDstrcmp(lock_env_var, "1"))) + ignore_disabled_file_locks_s = FALSE; /* Override: Don't ignore disabled locks */ + else + ignore_disabled_file_locks_s = FAIL; /* Environment variable not set, or not set correctly */ if (H5I_VFL != H5I_get_type(H5FD_SEC2_g)) H5FD_SEC2_g = H5FD_register(&H5FD_sec2_g, sizeof(H5FD_class_t), FALSE); @@ -239,7 +225,6 @@ H5FD_sec2_init(void) /* Set return value */ ret_value = H5FD_SEC2_g; -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD_sec2_init() */ @@ -292,7 +277,7 @@ H5Pset_fapl_sec2(hid_t fapl_id) if (NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") - ret_value = H5P_set_driver(plist, H5FD_SEC2, NULL); + ret_value = H5P_set_driver(plist, H5FD_SEC2, NULL, NULL); done: FUNC_LEAVE_API(ret_value) @@ -1068,3 +1053,47 @@ H5FD__sec2_delete(const char *filename, hid_t H5_ATTR_UNUSED fapl_id) done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD__sec2_delete() */ + +/*------------------------------------------------------------------------- + * Function: H5FD__sec2_ctl + * + * Purpose: Sec2 VFD version of the ctl callback. + * + * The desired operation is specified by the op_code + * parameter. + * + * The flags parameter controls management of op_codes that + * are unknown to the callback + * + * The input and output parameters allow op_code specific + * input and output + * + * At present, no op codes are supported by this VFD. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD__sec2_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void H5_ATTR_UNUSED *input, + void H5_ATTR_UNUSED **output) +{ + H5FD_sec2_t *file = (H5FD_sec2_t *)_file; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC + + /* Sanity checks */ + HDassert(file); + + switch (op_code) { + /* Unknown op code */ + default: + if (flags & H5FD_CTL__FAIL_IF_UNKNOWN_FLAG) + HGOTO_ERROR(H5E_VFL, H5E_FCNTL, FAIL, "unknown op_code and fail if unknown flag is set") + break; + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD__sec2_ctl() */ diff --git a/src/H5FDsec2.h b/src/H5FDsec2.h index 541ac71..df4d4d4 100644 --- a/src/H5FDsec2.h +++ b/src/H5FDsec2.h @@ -20,7 +20,8 @@ #ifndef H5FDsec2_H #define H5FDsec2_H -#define H5FD_SEC2 (H5FD_sec2_init()) +#define H5FD_SEC2 (H5FDperform_init(H5FD_sec2_init)) +#define H5FD_SEC2_VALUE H5_VFD_SEC2 #ifdef __cplusplus extern "C" { diff --git a/src/H5FDspace.c b/src/H5FDspace.c index de52dc3..48b06ba 100644 --- a/src/H5FDspace.c +++ b/src/H5FDspace.c @@ -148,7 +148,7 @@ H5FD__alloc_real(H5FD_t *file, H5FD_mem_t type, hsize_t size, haddr_t *frag_addr FUNC_ENTER_PACKAGE #ifdef H5FD_ALLOC_DEBUG - HDfprintf(stderr, "%s: type = %u, size = %Hu\n", __func__, (unsigned)type, size); + HDfprintf(stderr, "%s: type = %u, size = %" PRIuHSIZE "\n", __func__, (unsigned)type, size); #endif /* H5FD_ALLOC_DEBUG */ /* check args */ @@ -211,7 +211,7 @@ H5FD__alloc_real(H5FD_t *file, H5FD_mem_t type, hsize_t size, haddr_t *frag_addr done: #ifdef H5FD_ALLOC_DEBUG - HDfprintf(stderr, "%s: ret_value = %a\n", __func__, ret_value); + HDfprintf(stderr, "%s: ret_value = %" PRIuHADDR "\n", __func__, ret_value); #endif /* H5FD_ALLOC_DEBUG */ FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD__alloc_real() */ @@ -287,7 +287,8 @@ H5FD__free_real(H5FD_t *file, H5FD_mem_t type, haddr_t addr, hsize_t size) HDassert(size > 0); #ifdef H5FD_ALLOC_DEBUG - HDfprintf(stderr, "%s: type = %u, addr = %a, size = %Hu\n", __func__, (unsigned)type, addr, size); + HDfprintf(stderr, "%s: type = %u, addr = %" PRIuHADDR ", size = %" PRIuHSIZE "\n", __func__, + (unsigned)type, addr, size); #endif /* H5FD_ALLOC_DEBUG */ /* Sanity checking */ @@ -317,11 +318,11 @@ H5FD__free_real(H5FD_t *file, H5FD_mem_t type, haddr_t addr, hsize_t size) eoa = file->cls->get_eoa(file, type); #ifdef H5FD_ALLOC_DEBUG - HDfprintf(stderr, "%s: eoa = %a\n", __func__, eoa); + HDfprintf(stderr, "%s: eoa = %" PRIuHADDR "\n", __func__, eoa); #endif /* H5FD_ALLOC_DEBUG */ if (eoa == (addr + size)) { #ifdef H5FD_ALLOC_DEBUG - HDfprintf(stderr, "%s: Reducing file size to = %a\n", __func__, addr); + HDfprintf(stderr, "%s: Reducing file size to = %" PRIuHADDR "\n", __func__, addr); #endif /* H5FD_ALLOC_DEBUG */ if (file->cls->set_eoa(file, type, addr) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "set end of space allocation request failed") @@ -330,8 +331,8 @@ H5FD__free_real(H5FD_t *file, H5FD_mem_t type, haddr_t addr, hsize_t size) else { /* leak memory */ #ifdef H5FD_ALLOC_DEBUG - HDfprintf(stderr, "%s: LEAKED MEMORY!!! type = %u, addr = %a, size = %Hu\n", __func__, (unsigned)type, - addr, size); + HDfprintf(stderr, "%s: LEAKED MEMORY!!! type = %u, addr = %" PRIuHADDR ", size = %" PRIuHSIZE "\n", + __func__, (unsigned)type, addr, size); #endif /* H5FD_ALLOC_DEBUG */ } /* end else */ diff --git a/src/H5FDsplitter.c b/src/H5FDsplitter.c index 73c898a..124c54f 100644 --- a/src/H5FDsplitter.c +++ b/src/H5FDsplitter.c @@ -104,6 +104,10 @@ static int H5FD__copy_plist(hid_t fapl_id, hid_t *id_out_ptr); /* Prototypes */ static herr_t H5FD__splitter_term(void); +static herr_t H5FD__splitter_populate_config(H5FD_splitter_vfd_config_t *vfd_config, + H5FD_splitter_fapl_t * fapl_out); +static herr_t H5FD__splitter_get_default_wo_path(char *new_path, size_t new_path_len, + const char *base_filename); static hsize_t H5FD__splitter_sb_size(H5FD_t *_file); static herr_t H5FD__splitter_sb_encode(H5FD_t *_file, char *name /*out*/, unsigned char *buf /*out*/); static herr_t H5FD__splitter_sb_decode(H5FD_t *_file, const char *name, const unsigned char *buf); @@ -129,8 +133,13 @@ static herr_t H5FD__splitter_flush(H5FD_t *_file, hid_t dxpl_id, hbool_t closin static herr_t H5FD__splitter_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing); static herr_t H5FD__splitter_lock(H5FD_t *_file, hbool_t rw); static herr_t H5FD__splitter_unlock(H5FD_t *_file); +static herr_t H5FD__splitter_delete(const char *filename, hid_t fapl_id); +static herr_t H5FD__splitter_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void *input, + void **output); static const H5FD_class_t H5FD_splitter_g = { + H5FD_CLASS_VERSION, /* struct version */ + H5FD_SPLITTER_VALUE, /* value */ "splitter", /* name */ MAXADDR, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -138,7 +147,7 @@ static const H5FD_class_t H5FD_splitter_g = { H5FD__splitter_sb_size, /* sb_size */ H5FD__splitter_sb_encode, /* sb_encode */ H5FD__splitter_sb_decode, /* sb_decode */ - sizeof(H5FD_splitter_fapl_t), /* fapl_size */ + sizeof(H5FD_splitter_fapl_t), /* fapl_size */ H5FD__splitter_fapl_get, /* fapl_get */ H5FD__splitter_fapl_copy, /* fapl_copy */ H5FD__splitter_fapl_free, /* fapl_free */ @@ -149,7 +158,7 @@ static const H5FD_class_t H5FD_splitter_g = { H5FD__splitter_close, /* close */ H5FD__splitter_cmp, /* cmp */ H5FD__splitter_query, /* query */ - H5FD__splitter_get_type_map, /* get_type_map */ + H5FD__splitter_get_type_map, /* get_type_map */ H5FD__splitter_alloc, /* alloc */ H5FD__splitter_free, /* free */ H5FD__splitter_get_eoa, /* get_eoa */ @@ -158,11 +167,16 @@ static const H5FD_class_t H5FD_splitter_g = { H5FD__splitter_get_handle, /* get_handle */ H5FD__splitter_read, /* read */ H5FD__splitter_write, /* write */ + NULL, /* read_vector */ + NULL, /* write_vector */ + NULL, /* read_selection */ + NULL, /* write_selection */ H5FD__splitter_flush, /* flush */ H5FD__splitter_truncate, /* truncate */ H5FD__splitter_lock, /* lock */ H5FD__splitter_unlock, /* unlock */ - NULL, /* del */ + H5FD__splitter_delete, /* del */ + H5FD__splitter_ctl, /* ctl */ H5FD_FLMAP_DICHOTOMY /* fl_map */ }; @@ -173,30 +187,6 @@ H5FL_DEFINE_STATIC(H5FD_splitter_t); H5FL_DEFINE_STATIC(H5FD_splitter_fapl_t); /*------------------------------------------------------------------------- - * Function: H5FD__init_package - * - * Purpose: Initializes any interface-specific data or routines. - * - * Return: SUCCEED/FAIL - *------------------------------------------------------------------------- - */ -static herr_t -H5FD__init_package(void) -{ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_STATIC - - H5FD_SPLITTER_LOG_CALL(__func__); - - if (H5FD_splitter_init() < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "unable to initialize splitter VFD") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5FD__init_package() */ - -/*------------------------------------------------------------------------- * Function: H5FD_splitter_init * * Purpose: Initialize the splitter driver by registering it with the @@ -211,7 +201,7 @@ H5FD_splitter_init(void) { hid_t ret_value = H5I_INVALID_HID; - FUNC_ENTER_NOAPI(H5I_INVALID_HID) + FUNC_ENTER_NOAPI_NOERR H5FD_SPLITTER_LOG_CALL(__func__); @@ -220,7 +210,6 @@ H5FD_splitter_init(void) ret_value = H5FD_SPLITTER_g; -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD_splitter_init() */ @@ -309,57 +298,14 @@ H5Pset_fapl_splitter(hid_t fapl_id, H5FD_splitter_vfd_config_t *vfd_config) if (NULL == (plist_ptr = (H5P_genplist_t *)H5I_object(fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a valid property list") - /* Make sure that the W/O channel supports write-only capability. - * Some drivers (e.g. family or multi) do revision of the superblock - * in-memory, causing problems in that channel. - * Uses the feature flag H5FD_FEAT_DEFAULT_VFD_COMPATIBLE as the - * determining attribute. - */ - if (H5P_DEFAULT != vfd_config->wo_fapl_id) { - H5FD_class_t * wo_driver = NULL; - H5FD_driver_prop_t wo_driver_prop; - H5P_genplist_t * wo_plist_ptr = NULL; - unsigned long wo_driver_flags = 0; - - wo_plist_ptr = (H5P_genplist_t *)H5I_object(vfd_config->wo_fapl_id); - if (NULL == wo_plist_ptr) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") - if (H5P_peek(wo_plist_ptr, H5F_ACS_FILE_DRV_NAME, &wo_driver_prop) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get driver ID & info") - wo_driver = (H5FD_class_t *)H5I_object(wo_driver_prop.driver_id); - if (NULL == wo_driver) - HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "invalid driver ID in file access property list") - if (H5FD_driver_query(wo_driver, &wo_driver_flags) < 0) - HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "can't query VFD flags") - if (0 == (H5FD_FEAT_DEFAULT_VFD_COMPATIBLE & wo_driver_flags)) - HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "unsuitable W/O driver") - } /* end if W/O VFD is non-default */ - info = H5FL_CALLOC(H5FD_splitter_fapl_t); if (NULL == info) HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "unable to allocate file access property list struct") - info->ignore_wo_errs = vfd_config->ignore_wo_errs; - HDstrncpy(info->wo_path, vfd_config->wo_path, H5FD_SPLITTER_PATH_MAX + 1); - info->wo_path[H5FD_SPLITTER_PATH_MAX] = '\0'; - HDstrncpy(info->log_file_path, vfd_config->log_file_path, H5FD_SPLITTER_PATH_MAX + 1); - info->log_file_path[H5FD_SPLITTER_PATH_MAX] = '\0'; - info->rw_fapl_id = H5P_FILE_ACCESS_DEFAULT; /* pre-set value */ - info->wo_fapl_id = H5P_FILE_ACCESS_DEFAULT; /* pre-set value */ - - /* Set non-default channel FAPL IDs in splitter configuration info */ - if (H5P_DEFAULT != vfd_config->rw_fapl_id) { - if (FALSE == H5P_isa_class(vfd_config->rw_fapl_id, H5P_FILE_ACCESS)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access list") - info->rw_fapl_id = vfd_config->rw_fapl_id; - } - if (H5P_DEFAULT != vfd_config->wo_fapl_id) { - if (FALSE == H5P_isa_class(vfd_config->wo_fapl_id, H5P_FILE_ACCESS)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access list") - info->wo_fapl_id = vfd_config->wo_fapl_id; - } + if (H5FD__splitter_populate_config(vfd_config, info) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't setup driver configuration") - ret_value = H5P_set_driver(plist_ptr, H5FD_SPLITTER, info); + ret_value = H5P_set_driver(plist_ptr, H5FD_SPLITTER, info, NULL); done: if (info) @@ -383,9 +329,10 @@ done: herr_t H5Pget_fapl_splitter(hid_t fapl_id, H5FD_splitter_vfd_config_t *config /*out*/) { - const H5FD_splitter_fapl_t *fapl_ptr = NULL; - H5P_genplist_t * plist_ptr = NULL; - herr_t ret_value = SUCCEED; + const H5FD_splitter_fapl_t *fapl_ptr = NULL; + H5FD_splitter_fapl_t * default_fapl = NULL; + H5P_genplist_t * plist_ptr = NULL; + herr_t ret_value = SUCCEED; FUNC_ENTER_API(FAIL) H5TRACE2("e", "ix", fapl_id, config); @@ -411,8 +358,14 @@ H5Pget_fapl_splitter(hid_t fapl_id, H5FD_splitter_vfd_config_t *config /*out*/) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") if (H5FD_SPLITTER != H5P_peek_driver(plist_ptr)) HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "incorrect VFL driver") - if (NULL == (fapl_ptr = (const H5FD_splitter_fapl_t *)H5P_peek_driver_info(plist_ptr))) - HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "unable to get specific-driver info") + fapl_ptr = (const H5FD_splitter_fapl_t *)H5P_peek_driver_info(plist_ptr); + if (NULL == fapl_ptr) { + if (NULL == (default_fapl = H5FL_CALLOC(H5FD_splitter_fapl_t))) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "unable to allocate file access property list struct") + if (H5FD__splitter_populate_config(NULL, default_fapl) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't initialize driver configuration info") + fapl_ptr = default_fapl; + } HDstrncpy(config->wo_path, fapl_ptr->wo_path, H5FD_SPLITTER_PATH_MAX + 1); HDstrncpy(config->log_file_path, fapl_ptr->log_file_path, H5FD_SPLITTER_PATH_MAX + 1); @@ -425,10 +378,188 @@ H5Pget_fapl_splitter(hid_t fapl_id, H5FD_splitter_vfd_config_t *config /*out*/) HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "can't copy W/O FAPL"); done: + if (default_fapl) + H5FL_FREE(H5FD_splitter_fapl_t, default_fapl); + FUNC_LEAVE_API(ret_value) } /* end H5Pget_fapl_splitter() */ /*------------------------------------------------------------------------- + * Function: H5FD__splitter_populate_config + * + * Purpose: Populates a H5FD_splitter_fapl_t structure with the provided + * values, supplying defaults where values are not provided. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD__splitter_populate_config(H5FD_splitter_vfd_config_t *vfd_config, H5FD_splitter_fapl_t *fapl_out) +{ + H5P_genplist_t *def_plist; + H5P_genplist_t *plist; + hbool_t free_config = FALSE; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC + + HDassert(fapl_out); + + HDmemset(fapl_out, 0, sizeof(H5FD_splitter_fapl_t)); + + if (!vfd_config) { + vfd_config = H5MM_calloc(sizeof(H5FD_splitter_vfd_config_t)); + if (NULL == vfd_config) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "unable to allocate file access property list struct") + + vfd_config->magic = H5FD_SPLITTER_MAGIC; + vfd_config->version = H5FD_CURR_SPLITTER_VFD_CONFIG_VERSION; + vfd_config->rw_fapl_id = H5P_DEFAULT; + vfd_config->wo_fapl_id = H5P_DEFAULT; + + free_config = TRUE; + } + + /* Make sure that the W/O channel supports write-only capability. + * Some drivers (e.g. family or multi) do revision of the superblock + * in-memory, causing problems in that channel. + * Uses the feature flag H5FD_FEAT_DEFAULT_VFD_COMPATIBLE as the + * determining attribute. + */ + if (H5P_DEFAULT != vfd_config->wo_fapl_id) { + H5FD_class_t * wo_driver = NULL; + H5FD_driver_prop_t wo_driver_prop; + H5P_genplist_t * wo_plist_ptr = NULL; + unsigned long wo_driver_flags = 0; + + wo_plist_ptr = (H5P_genplist_t *)H5I_object(vfd_config->wo_fapl_id); + if (NULL == wo_plist_ptr) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") + if (H5P_peek(wo_plist_ptr, H5F_ACS_FILE_DRV_NAME, &wo_driver_prop) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get driver ID & info") + wo_driver = (H5FD_class_t *)H5I_object(wo_driver_prop.driver_id); + if (NULL == wo_driver) + HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "invalid driver ID in file access property list") + if (H5FD_driver_query(wo_driver, &wo_driver_flags) < 0) + HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "can't query VFD flags") + if (0 == (H5FD_FEAT_DEFAULT_VFD_COMPATIBLE & wo_driver_flags)) + HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "unsuitable W/O driver") + } /* end if W/O VFD is non-default */ + + fapl_out->ignore_wo_errs = vfd_config->ignore_wo_errs; + HDstrncpy(fapl_out->wo_path, vfd_config->wo_path, H5FD_SPLITTER_PATH_MAX + 1); + fapl_out->wo_path[H5FD_SPLITTER_PATH_MAX] = '\0'; + HDstrncpy(fapl_out->log_file_path, vfd_config->log_file_path, H5FD_SPLITTER_PATH_MAX + 1); + fapl_out->log_file_path[H5FD_SPLITTER_PATH_MAX] = '\0'; + fapl_out->rw_fapl_id = H5P_FILE_ACCESS_DEFAULT; /* pre-set value */ + fapl_out->wo_fapl_id = H5P_FILE_ACCESS_DEFAULT; /* pre-set value */ + + if (NULL == (def_plist = (H5P_genplist_t *)H5I_object(H5P_FILE_ACCESS_DEFAULT))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") + + /* Set non-default channel FAPL IDs in splitter configuration info */ + if (H5P_DEFAULT != vfd_config->rw_fapl_id) { + if (FALSE == H5P_isa_class(vfd_config->rw_fapl_id, H5P_FILE_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access list") + fapl_out->rw_fapl_id = vfd_config->rw_fapl_id; + } + else { + /* Use copy of default file access property list for R/W channel FAPL ID. + * The Sec2 driver is explicitly set on the FAPL ID, as the default + * driver might have been replaced with the Splitter VFD, which + * would cause recursion badness. + */ + if ((fapl_out->rw_fapl_id = H5P_copy_plist(def_plist, FALSE)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTCOPY, FAIL, "can't copy property list") + if (NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_out->rw_fapl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") + if (H5P_set_driver_by_value(plist, H5_VFD_SEC2, NULL, TRUE) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't set default driver on R/W channel FAPL") + } + if (H5P_DEFAULT != vfd_config->wo_fapl_id) { + if (FALSE == H5P_isa_class(vfd_config->wo_fapl_id, H5P_FILE_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access list") + fapl_out->wo_fapl_id = vfd_config->wo_fapl_id; + } + else { + /* Use copy of default file access property list for W/O channel FAPL ID. + * The Sec2 driver is explicitly set on the FAPL ID, as the default + * driver might have been replaced with the Splitter VFD, which + * would cause recursion badness. + */ + if ((fapl_out->wo_fapl_id = H5P_copy_plist(def_plist, FALSE)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTCOPY, FAIL, "can't copy property list") + if (NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_out->wo_fapl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") + if (H5P_set_driver_by_value(plist, H5_VFD_SEC2, NULL, TRUE) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't set default driver on R/W channel FAPL") + } + +done: + if (free_config && vfd_config) + H5MM_free(vfd_config); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD__splitter_populate_config() */ + +/*------------------------------------------------------------------------- + * Function: H5FD__splitter_get_default_wo_path + * + * Purpose: Given a base filename, returns a default filename for the + * W/O channel file by appending '_wo' to the base file name. + * + * Return: Non-negative on Success/Negative on Failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD__splitter_get_default_wo_path(char *new_path, size_t new_path_len, const char *base_filename) +{ + const char *suffix = "_wo"; + size_t old_filename_len = 0; + char * file_extension = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC + + HDassert(new_path); + HDassert(base_filename); + + /* Check that output buffer can hold base filename + `_wo` suffix */ + old_filename_len = HDstrlen(base_filename); + if (old_filename_len > H5FD_SPLITTER_PATH_MAX - HDstrlen(suffix) - 1) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "filename exceeds max length") + + /* Determine if filename contains a ".h5" extension. */ + if ((file_extension = HDstrstr(base_filename, ".h5"))) { + /* Insert the suffix between the filename and ".h5" extension. */ + HDstrcpy(new_path, base_filename); + file_extension = HDstrstr(new_path, ".h5"); + HDsprintf(file_extension, "%s%s", suffix, ".h5"); + } + else if ((file_extension = HDstrrchr(base_filename, '.'))) { + char *new_extension_loc = NULL; + + /* If the filename doesn't contain a ".h5" extension, but contains + * AN extension, just insert the suffix before that extension. + */ + HDstrcpy(new_path, base_filename); + new_extension_loc = HDstrrchr(new_path, '.'); + HDsprintf(new_extension_loc, "%s%s", suffix, file_extension); + } + else { + /* If the filename doesn't contain an extension at all, just insert + * the suffix at the end of the filename. + */ + HDsnprintf(new_path, new_path_len, "%s%s", base_filename, suffix); + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD__splitter_get_default_wo_path() */ + +/*------------------------------------------------------------------------- * Function: H5FD__splitter_flush * * Purpose: Flushes all data to disk for both channels. @@ -655,10 +786,11 @@ done: static H5FD_t * H5FD__splitter_open(const char *name, unsigned flags, hid_t splitter_fapl_id, haddr_t maxaddr) { - H5FD_splitter_t * file_ptr = NULL; /* Splitter VFD info */ - const H5FD_splitter_fapl_t *fapl_ptr = NULL; /* Driver-specific property list */ - H5P_genplist_t * plist_ptr = NULL; - H5FD_t * ret_value = NULL; + H5FD_splitter_t * file_ptr = NULL; /* Splitter VFD info */ + const H5FD_splitter_fapl_t *fapl_ptr = NULL; /* Driver-specific property list */ + H5FD_splitter_fapl_t * default_fapl = NULL; + H5P_genplist_t * plist_ptr = NULL; + H5FD_t * ret_value = NULL; FUNC_ENTER_STATIC @@ -671,8 +803,7 @@ H5FD__splitter_open(const char *name, unsigned flags, hid_t splitter_fapl_id, ha HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "bogus maxaddr") if (ADDR_OVERFLOW(maxaddr)) HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, NULL, "bogus maxaddr") - if ((H5P_FILE_ACCESS_DEFAULT == splitter_fapl_id) || (H5FD_SPLITTER != H5Pget_driver(splitter_fapl_id))) - /* presupposes that H5P_FILE_ACCESS_DEFAULT is not a splitter */ + if (H5FD_SPLITTER != H5Pget_driver(splitter_fapl_id)) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "driver is not splitter") file_ptr = (H5FD_splitter_t *)H5FL_CALLOC(H5FD_splitter_t); @@ -686,8 +817,20 @@ H5FD__splitter_open(const char *name, unsigned flags, hid_t splitter_fapl_id, ha if (NULL == plist_ptr) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list") fapl_ptr = (const H5FD_splitter_fapl_t *)H5P_peek_driver_info(plist_ptr); - if (NULL == fapl_ptr) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "unable to get VFL driver info") + if (NULL == fapl_ptr) { + if (NULL == (default_fapl = H5FL_CALLOC(H5FD_splitter_fapl_t))) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, NULL, "unable to allocate file access property list struct") + if (H5FD__splitter_populate_config(NULL, default_fapl) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, NULL, "can't initialize driver configuration info") + + /* If W/O path is not set, use base filename with '_wo' suffix */ + if (*default_fapl->wo_path == '\0') + if (H5FD__splitter_get_default_wo_path(default_fapl->wo_path, H5FD_SPLITTER_PATH_MAX + 1, name) < + 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, NULL, "can't generate default filename for W/O channel") + + fapl_ptr = default_fapl; + } /* Copy simpler info */ HDstrncpy(file_ptr->fa.wo_path, fapl_ptr->wo_path, H5FD_SPLITTER_PATH_MAX + 1); @@ -723,6 +866,9 @@ H5FD__splitter_open(const char *name, unsigned flags, hid_t splitter_fapl_id, ha ret_value = (H5FD_t *)file_ptr; done: + if (default_fapl) + H5FL_FREE(H5FD_splitter_fapl_t, default_fapl); + if (NULL == ret_value) { if (file_ptr) { if (H5I_INVALID_HID != file_ptr->fa.rw_fapl_id) @@ -1145,6 +1291,62 @@ done: } /* end H5FD__splitter_unlock */ /*------------------------------------------------------------------------- + * Function: H5FD__splitter_ctl + * + * Purpose: Splitter VFD version of the ctl callback. + * + * The desired operation is specified by the op_code + * parameter. + * + * The flags parameter controls management of op_codes that + * are unknown to the callback + * + * The input and output parameters allow op_code specific + * input and output + * + * At present, this VFD supports no op codes of its own and + * simply passes ctl calls on to the R/W channel VFD. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD__splitter_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void *input, void **output) +{ + H5FD_splitter_t *file = (H5FD_splitter_t *)_file; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC + + /* Sanity checks */ + HDassert(file); + + switch (op_code) { + /* Unknown op code */ + default: + if (flags & H5FD_CTL__ROUTE_TO_TERMINAL_VFD_FLAG) { + /* Pass ctl call down to R/W channel VFD */ + if (H5FDctl(file->rw_file, op_code, flags, input, output) < 0) + HGOTO_ERROR(H5E_VFL, H5E_FCNTL, FAIL, "VFD ctl request failed") + } + else { + /* If no valid VFD routing flag is specified, fail for unknown op code + * if H5FD_CTL__FAIL_IF_UNKNOWN_FLAG flag is set. + */ + if (flags & H5FD_CTL__FAIL_IF_UNKNOWN_FLAG) + HGOTO_ERROR(H5E_VFL, H5E_FCNTL, FAIL, + "VFD ctl request failed (unknown op code and fail if unknown flag is set)") + } + + break; + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD__splitter_ctl() */ + +/*------------------------------------------------------------------------- * Function: H5FD__splitter_query * * Purpose: Set the flags that this VFL driver is capable of supporting. @@ -1279,6 +1481,74 @@ done: } /* end H5FD__splitter_free() */ /*------------------------------------------------------------------------- + * Function: H5FD__splitter_delete + * + * Purpose: Delete a file + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD__splitter_delete(const char *filename, hid_t fapl_id) +{ + const H5FD_splitter_fapl_t *fapl_ptr = NULL; + H5FD_splitter_fapl_t * default_fapl = NULL; + H5P_genplist_t * plist; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC + + HDassert(filename); + + /* Get the driver info */ + if (H5P_FILE_ACCESS_DEFAULT == fapl_id) { + if (NULL == (default_fapl = H5FL_CALLOC(H5FD_splitter_fapl_t))) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "unable to allocate file access property list struct") + if (H5FD__splitter_populate_config(NULL, default_fapl) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't initialize driver configuration info") + + /* If W/O path is not set, use base filename with '_wo' suffix */ + if (*default_fapl->wo_path == '\0') + if (H5FD__splitter_get_default_wo_path(default_fapl->wo_path, H5FD_SPLITTER_PATH_MAX + 1, + filename) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't generate default filename for W/O channel") + + fapl_ptr = default_fapl; + } + else { + if (NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") + if (NULL == (fapl_ptr = (const H5FD_splitter_fapl_t *)H5P_peek_driver_info(plist))) { + if (NULL == (default_fapl = H5FL_CALLOC(H5FD_splitter_fapl_t))) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, + "unable to allocate file access property list struct") + if (H5FD__splitter_populate_config(NULL, default_fapl) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't initialize driver configuration info") + + /* If W/O path is not set, use base filename with '_wo' suffix */ + if (*default_fapl->wo_path == '\0') + if (H5FD__splitter_get_default_wo_path(default_fapl->wo_path, H5FD_SPLITTER_PATH_MAX + 1, + filename) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't generate default filename for W/O channel") + + fapl_ptr = default_fapl; + } + } + + if (H5FDdelete(filename, fapl_ptr->rw_fapl_id) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTDELETEFILE, FAIL, "unable to delete file") + if (H5FDdelete(fapl_ptr->wo_path, fapl_ptr->wo_fapl_id) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTDELETEFILE, FAIL, "unable to delete W/O channel file") + +done: + if (default_fapl) + H5FL_FREE(H5FD_splitter_fapl_t, default_fapl); + + FUNC_LEAVE_NOAPI(ret_value) +} + +/*------------------------------------------------------------------------- * Function: H5FD__splitter_log_error * * Purpose: Log an error from the W/O channel appropriately. diff --git a/src/H5FDsplitter.h b/src/H5FDsplitter.h index ee6e7c5..c8751c8 100644 --- a/src/H5FDsplitter.h +++ b/src/H5FDsplitter.h @@ -17,7 +17,8 @@ #ifndef H5FDsplitter_H #define H5FDsplitter_H -#define H5FD_SPLITTER (H5FD_splitter_init()) +#define H5FD_SPLITTER (H5FDperform_init(H5FD_splitter_init)) +#define H5FD_SPLITTER_VALUE H5_VFD_SPLITTER /* The version of the H5FD_splitter_vfd_config_t structure used */ #define H5FD_CURR_SPLITTER_VFD_CONFIG_VERSION 1 @@ -34,7 +35,7 @@ * Structure: H5FD_spliiter_vfd_config_t * * One-stop shopping for configuring a Splitter VFD (rather than many - * paramaters passed into H5Pset/get functions). + * parameters passed into H5Pset/get functions). * * magic (int32_t) * Semi-unique number, used to sanity-check that a given pointer is diff --git a/src/H5FDstdio.c b/src/H5FDstdio.c index 6631325..6624685 100644 --- a/src/H5FDstdio.c +++ b/src/H5FDstdio.c @@ -183,39 +183,46 @@ static herr_t H5FD_stdio_unlock(H5FD_t *_file); static herr_t H5FD_stdio_delete(const char *filename, hid_t fapl_id); static const H5FD_class_t H5FD_stdio_g = { - "stdio", /* name */ - MAXADDR, /* maxaddr */ - H5F_CLOSE_WEAK, /* fc_degree */ - H5FD_stdio_term, /* terminate */ - NULL, /* sb_size */ - NULL, /* sb_encode */ - NULL, /* sb_decode */ - 0, /* fapl_size */ - NULL, /* fapl_get */ - NULL, /* fapl_copy */ - NULL, /* fapl_free */ - 0, /* dxpl_size */ - NULL, /* dxpl_copy */ - NULL, /* dxpl_free */ - H5FD_stdio_open, /* open */ - H5FD_stdio_close, /* close */ - H5FD_stdio_cmp, /* cmp */ - H5FD_stdio_query, /* query */ - NULL, /* get_type_map */ - H5FD_stdio_alloc, /* alloc */ - NULL, /* free */ - H5FD_stdio_get_eoa, /* get_eoa */ - H5FD_stdio_set_eoa, /* set_eoa */ - H5FD_stdio_get_eof, /* get_eof */ - H5FD_stdio_get_handle, /* get_handle */ - H5FD_stdio_read, /* read */ - H5FD_stdio_write, /* write */ - H5FD_stdio_flush, /* flush */ - H5FD_stdio_truncate, /* truncate */ - H5FD_stdio_lock, /* lock */ - H5FD_stdio_unlock, /* unlock */ - H5FD_stdio_delete, /* del */ - H5FD_FLMAP_DICHOTOMY /* fl_map */ + H5FD_CLASS_VERSION, /* struct version */ + H5_VFD_STDIO, /* value */ + "stdio", /* name */ + MAXADDR, /* maxaddr */ + H5F_CLOSE_WEAK, /* fc_degree */ + H5FD_stdio_term, /* terminate */ + NULL, /* sb_size */ + NULL, /* sb_encode */ + NULL, /* sb_decode */ + 0, /* fapl_size */ + NULL, /* fapl_get */ + NULL, /* fapl_copy */ + NULL, /* fapl_free */ + 0, /* dxpl_size */ + NULL, /* dxpl_copy */ + NULL, /* dxpl_free */ + H5FD_stdio_open, /* open */ + H5FD_stdio_close, /* close */ + H5FD_stdio_cmp, /* cmp */ + H5FD_stdio_query, /* query */ + NULL, /* get_type_map */ + H5FD_stdio_alloc, /* alloc */ + NULL, /* free */ + H5FD_stdio_get_eoa, /* get_eoa */ + H5FD_stdio_set_eoa, /* set_eoa */ + H5FD_stdio_get_eof, /* get_eof */ + H5FD_stdio_get_handle, /* get_handle */ + H5FD_stdio_read, /* read */ + H5FD_stdio_write, /* write */ + NULL, /* read_vector */ + NULL, /* write_vector */ + NULL, /* read_selection */ + NULL, /* write_selection */ + H5FD_stdio_flush, /* flush */ + H5FD_stdio_truncate, /* truncate */ + H5FD_stdio_lock, /* lock */ + H5FD_stdio_unlock, /* unlock */ + H5FD_stdio_delete, /* del */ + NULL, /* ctl */ + H5FD_FLMAP_DICHOTOMY /* fl_map */ }; /*------------------------------------------------------------------------- @@ -242,7 +249,7 @@ H5FD_stdio_init(void) H5Eclear2(H5E_DEFAULT); /* Check the use disabled file locks environment variable */ - lock_env_var = getenv("HDF5_USE_FILE_LOCKING"); + lock_env_var = getenv(HDF5_USE_FILE_LOCKING); if (lock_env_var && !strcmp(lock_env_var, "BEST_EFFORT")) ignore_disabled_file_locks_s = 1; /* Override: Ignore disabled locks */ else if (lock_env_var && (!strcmp(lock_env_var, "TRUE") || !strcmp(lock_env_var, "1"))) diff --git a/src/H5FDstdio.h b/src/H5FDstdio.h index 9db92ed..484c6ea 100644 --- a/src/H5FDstdio.h +++ b/src/H5FDstdio.h @@ -22,7 +22,7 @@ #include "H5Ipublic.h" -#define H5FD_STDIO (H5FD_stdio_init()) +#define H5FD_STDIO (H5FDperform_init(H5FD_stdio_init)) #ifdef __cplusplus extern "C" { diff --git a/src/H5FDwindows.c b/src/H5FDwindows.c index 6ce33a7..fa3c05f 100644 --- a/src/H5FDwindows.c +++ b/src/H5FDwindows.c @@ -56,7 +56,7 @@ H5Pset_fapl_windows(hid_t fapl_id) if (NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") - ret_value = H5P_set_driver(plist, H5FD_WINDOWS, NULL); + ret_value = H5P_set_driver(plist, H5FD_WINDOWS, NULL, NULL); done: FUNC_LEAVE_API(ret_value) @@ -114,9 +114,6 @@ struct H5FL_fac_node_t { struct H5FL_fac_node_t *next; /* Pointer to next block in free list */ }; -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /* The head of the list of factory things to garbage collect */ static H5FL_fac_gc_list_t H5FL_fac_gc_head = {0, NULL}; @@ -184,20 +181,15 @@ H5FL_term_package(void) FUNC_ENTER_NOAPI_NOINIT_NOERR - if (H5_PKG_INIT_VAR) { /* Garbage collect any nodes on the free lists */ - (void)H5FL_garbage_coll(); - - /* Shut down the various kinds of free lists */ - n += H5FL__reg_term(); - n += H5FL__fac_term_all(); - n += H5FL__arr_term(); - n += H5FL__blk_term(); + (void) + H5FL_garbage_coll(); - /* Mark interface closed */ - if (0 == n) - H5_PKG_INIT_VAR = FALSE; - } /* end if */ + /* Shut down the various kinds of free lists */ + n += H5FL__reg_term(); + n += H5FL__fac_term_all(); + n += H5FL__arr_term(); + n += H5FL__blk_term(); #ifdef H5FL_TRACK /* If we haven't freed all the allocated memory, dump out the list now */ @@ -1009,27 +1001,32 @@ H5FL_blk_free(H5FL_blk_head_t *head, void *block) #ifdef H5FL_TRACK { - H5FL_track_t *trk = block = ((unsigned char *)block) - sizeof(H5FL_track_t); + unsigned char *block_ptr = ((unsigned char *)block) - sizeof(H5FL_track_t); + H5FL_track_t trk; + + HDmemcpy(&trk, block_ptr, sizeof(H5FL_track_t)); /* Free tracking information about the allocation location */ - H5CS_close_stack(trk->stack); + H5CS_close_stack(trk.stack); /* The 'func' & 'file' strings are statically allocated (by the compiler) * and are not allocated, so there's no need to free them. */ - trk->file = NULL; - trk->func = NULL; + trk.file = NULL; + trk.func = NULL; /* Remove from "outstanding allocations" list */ - if (trk == H5FL_out_head_g) { + if ((void *)block_ptr == (void *)H5FL_out_head_g) { H5FL_out_head_g = H5FL_out_head_g->next; if (H5FL_out_head_g) H5FL_out_head_g->prev = NULL; } /* end if */ else { - trk->prev->next = trk->next; - if (trk->next) - trk->next->prev = trk->prev; + trk.prev->next = trk.next; + if (trk.next) + trk.next->prev = trk.prev; } /* end else */ + + HDmemcpy(block_ptr, &trk, sizeof(H5FL_track_t)); } #endif /* H5FL_TRACK */ @@ -1128,25 +1125,30 @@ H5FL_blk_realloc(H5FL_blk_head_t *head, void *block, size_t new_size H5FL_TRACK_ else { #ifdef H5FL_TRACK { - H5FL_track_t *trk = (H5FL_track_t *)(((unsigned char *)block) - sizeof(H5FL_track_t)); + unsigned char *block_ptr = ((unsigned char *)block) - sizeof(H5FL_track_t); + H5FL_track_t trk; + + HDmemcpy(&trk, block_ptr, sizeof(H5FL_track_t)); /* Release previous tracking information */ - H5CS_close_stack(trk->stack); + H5CS_close_stack(trk.stack); /* The 'func' & 'file' strings are statically allocated (by the compiler) * and are not allocated, so there's no need to free them. */ - trk->file = NULL; - trk->func = NULL; + trk.file = NULL; + trk.func = NULL; /* Store new tracking information */ - trk->stack = H5CS_copy_stack(); - HDassert(trk->stack); + trk.stack = H5CS_copy_stack(); + HDassert(trk.stack); /* The 'call_func' & 'call_file' strings are statically allocated (by the compiler) * there's no need to duplicate them. */ - trk->file = call_file; - trk->func = call_func; - trk->line = call_line; + trk.file = call_file; + trk.func = call_func; + trk.line = call_line; + + HDmemcpy(block_ptr, &trk, sizeof(H5FL_track_t)); } #endif /* H5FL_TRACK */ ret_value = block; @@ -1434,10 +1436,42 @@ H5FL_arr_free(H5FL_arr_head_t *head, void *obj) /* Make certain that the free list is initialized */ HDassert(head->init); +#ifdef H5FL_TRACK + { + unsigned char *block_ptr = ((unsigned char *)obj) - sizeof(H5FL_track_t); + H5FL_track_t trk; + + HDmemcpy(&trk, block_ptr, sizeof(H5FL_track_t)); + + /* Free tracking information about the allocation location */ + H5CS_close_stack(trk.stack); + /* The 'func' & 'file' strings are statically allocated (by the compiler) + * and are not allocated, so there's no need to free them. + */ + trk.file = NULL; + trk.func = NULL; + + /* Remove from "outstanding allocations" list */ + if ((void *)block_ptr == H5FL_out_head_g) { + H5FL_out_head_g = H5FL_out_head_g->next; + if (H5FL_out_head_g) + H5FL_out_head_g->prev = NULL; + } /* end if */ + else { + trk.prev->next = trk.next; + if (trk.next) + trk.next->prev = trk.prev; + } /* end else */ + + HDmemcpy(block_ptr, &trk, sizeof(H5FL_track_t)); + } +#endif + /* Get the pointer to the info header in front of the block to free */ temp = (H5FL_arr_list_t *)(( void *)((unsigned char *)obj - - sizeof(H5FL_arr_list_t))); /*lint !e826 Pointer-to-pointer cast is appropriate here */ + (sizeof(H5FL_arr_list_t) + + H5FL_TRACK_SIZE))); /*lint !e826 Pointer-to-pointer cast is appropriate here */ /* Get the number of elements */ free_nelem = temp->nelem; @@ -1490,7 +1524,7 @@ done: *------------------------------------------------------------------------- */ void * -H5FL_arr_malloc(H5FL_arr_head_t *head, size_t elem) +H5FL_arr_malloc(H5FL_arr_head_t *head, size_t elem H5FL_TRACK_PARAMS) { H5FL_arr_list_t *new_obj; /* Pointer to the new free list node allocated */ size_t mem_size; /* Size of memory block being recycled */ @@ -1531,7 +1565,8 @@ H5FL_arr_malloc(H5FL_arr_head_t *head, size_t elem) } /* end if */ /* Otherwise allocate a node */ else { - if (NULL == (new_obj = (H5FL_arr_list_t *)H5FL__malloc(sizeof(H5FL_arr_list_t) + mem_size))) + if (NULL == + (new_obj = (H5FL_arr_list_t *)H5FL__malloc(sizeof(H5FL_arr_list_t) + H5FL_TRACK_SIZE + mem_size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Increment the number of blocks of this size */ @@ -1547,6 +1582,28 @@ H5FL_arr_malloc(H5FL_arr_head_t *head, size_t elem) /* Get a pointer to the new block */ ret_value = ((char *)new_obj) + sizeof(H5FL_arr_list_t); +#ifdef H5FL_TRACK + /* Copy allocation location information */ + ((H5FL_track_t *)ret_value)->stack = H5CS_copy_stack(); + HDassert(((H5FL_track_t *)ret_value)->stack); + /* The 'call_func' & 'call_file' strings are statically allocated (by the compiler) + * there's no need to duplicate them. + */ + ((H5FL_track_t *)ret_value)->file = call_file; + ((H5FL_track_t *)ret_value)->func = call_func; + ((H5FL_track_t *)ret_value)->line = call_line; + + /* Add to "outstanding allocations" list */ + ((H5FL_track_t *)ret_value)->prev = NULL; + ((H5FL_track_t *)ret_value)->next = H5FL_out_head_g; + if (H5FL_out_head_g) + H5FL_out_head_g->prev = (H5FL_track_t *)ret_value; + H5FL_out_head_g = (H5FL_track_t *)ret_value; + + /* Adjust for allocation tracking information */ + ret_value = ((unsigned char *)ret_value) + sizeof(H5FL_track_t); +#endif + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5FL_arr_malloc() */ @@ -1565,7 +1622,7 @@ done: *------------------------------------------------------------------------- */ void * -H5FL_arr_calloc(H5FL_arr_head_t *head, size_t elem) +H5FL_arr_calloc(H5FL_arr_head_t *head, size_t elem H5FL_TRACK_PARAMS) { void *ret_value = NULL; /* Pointer to the block to return */ @@ -1576,7 +1633,7 @@ H5FL_arr_calloc(H5FL_arr_head_t *head, size_t elem) HDassert(elem); /* Allocate the array */ - if (NULL == (ret_value = H5FL_arr_malloc(head, elem))) + if (NULL == (ret_value = H5FL_arr_malloc(head, elem H5FL_TRACK_INFO_INT))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Clear to zeros */ @@ -1600,7 +1657,7 @@ done: *------------------------------------------------------------------------- */ void * -H5FL_arr_realloc(H5FL_arr_head_t *head, void *obj, size_t new_elem) +H5FL_arr_realloc(H5FL_arr_head_t *head, void *obj, size_t new_elem H5FL_TRACK_PARAMS) { void *ret_value = NULL; /* Pointer to the block to return */ @@ -1612,7 +1669,7 @@ H5FL_arr_realloc(H5FL_arr_head_t *head, void *obj, size_t new_elem) /* Check if we are really allocating the object */ if (obj == NULL) - ret_value = H5FL_arr_malloc(head, new_elem); + ret_value = H5FL_arr_malloc(head, new_elem H5FL_TRACK_INFO_INT); else { H5FL_arr_list_t *temp; /* Temp. ptr to the new free list node allocated */ @@ -1622,14 +1679,15 @@ H5FL_arr_realloc(H5FL_arr_head_t *head, void *obj, size_t new_elem) /* Get the pointer to the info header in front of the block to free */ temp = (H5FL_arr_list_t *)(( void *)((unsigned char *)obj - - sizeof(H5FL_arr_list_t))); /*lint !e826 Pointer-to-pointer cast is appropriate here */ + (sizeof(H5FL_arr_list_t) + + H5FL_TRACK_SIZE))); /*lint !e826 Pointer-to-pointer cast is appropriate here */ /* Check if the size is really changing */ if (temp->nelem != new_elem) { size_t blk_size; /* Size of block */ /* Get the new array of objects */ - ret_value = H5FL_arr_malloc(head, new_elem); + ret_value = H5FL_arr_malloc(head, new_elem H5FL_TRACK_INFO_INT); /* Copy the appropriate amount of elements */ blk_size = head->list_arr[MIN(temp->nelem, new_elem)].size; @@ -1638,8 +1696,35 @@ H5FL_arr_realloc(H5FL_arr_head_t *head, void *obj, size_t new_elem) /* Free the old block */ H5FL_arr_free(head, obj); } /* end if */ - else + else { +#ifdef H5FL_TRACK + unsigned char *block_ptr = ((unsigned char *)obj) - sizeof(H5FL_track_t); + H5FL_track_t trk; + + HDmemcpy(&trk, block_ptr, sizeof(H5FL_track_t)); + + /* Release previous tracking information */ + H5CS_close_stack(trk.stack); + /* The 'func' & 'file' strings are statically allocated (by the compiler) + * and are not allocated, so there's no need to free them. + */ + trk.file = NULL; + trk.func = NULL; + + /* Store new tracking information */ + trk.stack = H5CS_copy_stack(); + HDassert(trk.stack); + /* The 'call_func' & 'call_file' strings are statically allocated (by the compiler) + * there's no need to duplicate them. + */ + trk.file = call_file; + trk.func = call_func; + trk.line = call_line; + + HDmemcpy(block_ptr, &trk, sizeof(H5FL_track_t)); +#endif ret_value = obj; + } } /* end else */ FUNC_LEAVE_NOAPI(ret_value) diff --git a/src/H5FLprivate.h b/src/H5FLprivate.h index 381f977..8e9d0d4 100644 --- a/src/H5FLprivate.h +++ b/src/H5FLprivate.h @@ -50,6 +50,11 @@ */ /* #define H5FL_TRACK */ #ifdef H5FL_TRACK + +#ifndef H5_HAVE_CODESTACK +#error "Free list tracking requires code stack to be enabled" +#endif + /* Macro for inclusion in the free list allocation calls */ #define H5FL_TRACK_INFO , __FILE__, __func__, __LINE__ @@ -148,8 +153,8 @@ typedef struct H5FL_reg_head_t { typedef union H5FL_blk_list_t { size_t size; /* Size of the page */ union H5FL_blk_list_t *next; /* Pointer to next block in free list */ - double unused1; /* Unused normally, just here for aligment */ - haddr_t unused2; /* Unused normally, just here for aligment */ + double unused1; /* Unused normally, just here for alignment */ + haddr_t unused2; /* Unused normally, just here for alignment */ } H5FL_blk_list_t; /* Data structure for priority queue node of block free lists */ @@ -223,8 +228,8 @@ typedef struct H5FL_blk_head_t { typedef union H5FL_arr_list_t { union H5FL_arr_list_t *next; /* Pointer to next block in free list */ size_t nelem; /* Number of elements in this array */ - double unused1; /* Unused normally, just here for aligment */ - haddr_t unused2; /* Unused normally, just here for aligment */ + double unused1; /* Unused normally, just here for alignment */ + haddr_t unused2; /* Unused normally, just here for alignment */ } H5FL_arr_list_t; /* Data structure for each size of array element */ @@ -273,16 +278,17 @@ typedef struct H5FL_arr_head_t { #define H5FL_BARR_DEFINE_STATIC(b, t, m) static H5FL_ARR_DEFINE_COMMON(sizeof(b), t, m) /* Allocate an array of type 't' */ -#define H5FL_ARR_MALLOC(t, elem) H5FL_arr_malloc(&(H5FL_ARR_NAME(t)), elem) +#define H5FL_ARR_MALLOC(t, elem) H5FL_arr_malloc(&(H5FL_ARR_NAME(t)), elem H5FL_TRACK_INFO) /* Allocate an array of type 't' and clear it to all zeros */ -#define H5FL_ARR_CALLOC(t, elem) H5FL_arr_calloc(&(H5FL_ARR_NAME(t)), elem) +#define H5FL_ARR_CALLOC(t, elem) H5FL_arr_calloc(&(H5FL_ARR_NAME(t)), elem H5FL_TRACK_INFO) /* Free an array of type 't' */ #define H5FL_ARR_FREE(t, obj) (t *)H5FL_arr_free(&(H5FL_ARR_NAME(t)), obj) /* Re-allocate an array of type 't' */ -#define H5FL_ARR_REALLOC(t, obj, new_elem) H5FL_arr_realloc(&(H5FL_ARR_NAME(t)), obj, new_elem) +#define H5FL_ARR_REALLOC(t, obj, new_elem) \ + H5FL_arr_realloc(&(H5FL_ARR_NAME(t)), obj, new_elem H5FL_TRACK_INFO) #else /* H5_NO_ARR_FREE_LISTS */ /* Common macro for H5FL_ARR_DEFINE & H5FL_ARR_DEFINE_STATIC (and H5FL_BARR variants) */ @@ -405,10 +411,10 @@ H5_DLL void *H5FL_reg_calloc(H5FL_reg_head_t *head H5FL_TRACK_PARAMS); H5_DLL void *H5FL_reg_free(H5FL_reg_head_t *head, void *obj); /* Array free lists */ -H5_DLL void *H5FL_arr_malloc(H5FL_arr_head_t *head, size_t elem); -H5_DLL void *H5FL_arr_calloc(H5FL_arr_head_t *head, size_t elem); +H5_DLL void *H5FL_arr_malloc(H5FL_arr_head_t *head, size_t elem H5FL_TRACK_PARAMS); +H5_DLL void *H5FL_arr_calloc(H5FL_arr_head_t *head, size_t elem H5FL_TRACK_PARAMS); H5_DLL void *H5FL_arr_free(H5FL_arr_head_t *head, void *obj); -H5_DLL void *H5FL_arr_realloc(H5FL_arr_head_t *head, void *obj, size_t new_elem); +H5_DLL void *H5FL_arr_realloc(H5FL_arr_head_t *head, void *obj, size_t new_elem H5FL_TRACK_PARAMS); /* Sequence free lists */ H5_DLL void *H5FL_seq_malloc(H5FL_seq_head_t *head, size_t elem H5FL_TRACK_PARAMS); @@ -61,9 +61,6 @@ static herr_t H5FS__sinfo_free_node_cb(void *item, void *key, void *op_data); /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /* Declare a free list to manage the H5FS_section_class_t sequence information */ H5FL_SEQ_DEFINE(H5FS_section_class_t); @@ -146,7 +143,8 @@ H5FS_create(H5F_t *f, haddr_t *fs_addr, const H5FS_create_t *fs_create, uint16_t /* Set the return value */ ret_value = fspace; #ifdef H5FS_DEBUG - HDfprintf(stderr, "%s: fspace = %p, fspace->addr = %a\n", __func__, fspace, fspace->addr); + HDfprintf(stderr, "%s: fspace = %p, fspace->addr = %" PRIuHADDR "\n", __func__, (void *)fspace, + fspace->addr); #endif /* H5FS_DEBUG */ done: @@ -155,7 +153,7 @@ done: HDONE_ERROR(H5E_FSPACE, H5E_CANTFREE, NULL, "unable to destroy free space header") #ifdef H5FS_DEBUG - HDfprintf(stderr, "%s: Leaving, ret_value = %d\n", __func__, ret_value); + HDfprintf(stderr, "%s: Leaving, ret_value = %p\n", __func__, (void *)ret_value); #endif /* H5FS_DEBUG */ FUNC_LEAVE_NOAPI(ret_value) } /* H5FS_create() */ @@ -183,8 +181,8 @@ H5FS_open(H5F_t *f, haddr_t fs_addr, uint16_t nclasses, const H5FS_section_class FUNC_ENTER_NOAPI(NULL) #ifdef H5FS_DEBUG - HDfprintf(stderr, "%s: Opening free space manager, fs_addr = %a, nclasses = %Zu\n", __func__, fs_addr, - nclasses); + HDfprintf(stderr, "%s: Opening free space manager, fs_addr = %" PRIuHADDR ", nclasses = %Zu\n", __func__, + fs_addr, nclasses); #endif /* H5FS_DEBUG */ /* Check arguments. */ @@ -204,10 +202,10 @@ H5FS_open(H5F_t *f, haddr_t fs_addr, uint16_t nclasses, const H5FS_section_class (fspace = (H5FS_t *)H5AC_protect(f, H5AC_FSPACE_HDR, fs_addr, &cache_udata, H5AC__READ_ONLY_FLAG))) HGOTO_ERROR(H5E_FSPACE, H5E_CANTPROTECT, NULL, "unable to load free space header") #ifdef H5FS_DEBUG - HDfprintf(stderr, "%s: fspace->sect_addr = %a\n", __func__, fspace->sect_addr); - HDfprintf(stderr, "%s: fspace->sect_size = %Hu\n", __func__, fspace->sect_size); - HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu\n", __func__, fspace->alloc_sect_size); - HDfprintf(stderr, "%s: fspace->sinfo = %p\n", __func__, fspace->sinfo); + HDfprintf(stderr, "%s: fspace->sect_addr = %" PRIuHADDR "\n", __func__, fspace->sect_addr); + HDfprintf(stderr, "%s: fspace->sect_size = %" PRIuHSIZE "\n", __func__, fspace->sect_size); + HDfprintf(stderr, "%s: fspace->alloc_sect_size = %" PRIuHSIZE "\n", __func__, fspace->alloc_sect_size); + HDfprintf(stderr, "%s: fspace->sinfo = %p\n", __func__, (void *)fspace->sinfo); HDfprintf(stderr, "%s: fspace->rc = %u\n", __func__, fspace->rc); #endif /* H5FS_DEBUG */ @@ -251,7 +249,7 @@ H5FS_delete(H5F_t *f, haddr_t fs_addr) FUNC_ENTER_NOAPI(FAIL) #ifdef H5FS_DEBUG - HDfprintf(stderr, "%s: Deleting free space manager, fs_addr = %a\n", __func__, fs_addr); + HDfprintf(stderr, "%s: Deleting free space manager, fs_addr = %" PRIuHADDR "\n", __func__, fs_addr); #endif /* H5FS_DEBUG */ /* Check arguments. */ @@ -321,7 +319,7 @@ H5FS_delete(H5F_t *f, haddr_t fs_addr) /* Delete serialized section storage, if there are any */ #ifdef H5FS_DEBUG - HDfprintf(stderr, "%s: fspace->sect_addr = %a\n", __func__, fspace->sect_addr); + HDfprintf(stderr, "%s: fspace->sect_addr = %" PRIuHADDR "\n", __func__, fspace->sect_addr); #endif /* H5FS_DEBUG */ if (fspace->serial_sect_count > 0) { unsigned sinfo_status = 0; /* Free space section info's status in the metadata cache */ @@ -407,8 +405,8 @@ H5FS_close(H5F_t *f, H5FS_t *fspace) HDassert(f); HDassert(fspace); #ifdef H5FS_DEBUG - HDfprintf(stderr, "%s: Entering, fspace = %p, fspace->addr = %a, fspace->sinfo = %p\n", __func__, fspace, - fspace->addr, fspace->sinfo); + HDfprintf(stderr, "%s: Entering, fspace = %p, fspace->addr = %" PRIuHADDR ", fspace->sinfo = %p\n", + __func__, (void *)fspace, fspace->addr, (void *)fspace->sinfo); #endif /* H5FS_DEBUG */ /* Check if section info is valid */ @@ -416,11 +414,12 @@ H5FS_close(H5F_t *f, H5FS_t *fspace) if (fspace->sinfo) { #ifdef H5FS_DEBUG HDfprintf(stderr, - "%s: fspace->tot_sect_count = %Hu, fspace->serial_sect_count = %Hu, fspace->sect_addr = " - "%a, fspace->rc = %u\n", + "%s: fspace->tot_sect_count = %" PRIuHSIZE ", fspace->serial_sect_count = %" PRIuHSIZE + ", fspace->sect_addr = %" PRIuHADDR ", fspace->rc = %u\n", __func__, fspace->tot_sect_count, fspace->serial_sect_count, fspace->sect_addr, fspace->rc); - HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n", __func__, - fspace->alloc_sect_size, fspace->sect_size); + HDfprintf(stderr, + "%s: fspace->alloc_sect_size = %" PRIuHSIZE ", fspace->sect_size = %" PRIuHSIZE "\n", + __func__, fspace->alloc_sect_size, fspace->sect_size); #endif /* H5FS_DEBUG */ /* If there are sections to serialize, update them */ /* (if the free space manager is persistent) */ @@ -711,7 +710,7 @@ H5FS__incr(H5FS_t *fspace) FUNC_ENTER_PACKAGE #ifdef H5FS_DEBUG - HDfprintf(stderr, "%s: Entering, fpace->addr = %a, fspace->rc = %u\n", __func__, fspace->addr, + HDfprintf(stderr, "%s: Entering, fpace->addr = %" PRIuHADDR ", fspace->rc = %u\n", __func__, fspace->addr, fspace->rc); #endif /* H5FS_DEBUG */ @@ -751,7 +750,7 @@ H5FS__decr(H5FS_t *fspace) FUNC_ENTER_PACKAGE #ifdef H5FS_DEBUG - HDfprintf(stderr, "%s: Entering, fpace->addr = %a, fspace->rc = %u\n", __func__, fspace->addr, + HDfprintf(stderr, "%s: Entering, fpace->addr = %" PRIuHADDR ", fspace->rc = %u\n", __func__, fspace->addr, fspace->rc); #endif /* H5FS_DEBUG */ diff --git a/src/H5FSint.c b/src/H5FSint.c index 0ab975b..d7950ab 100644 --- a/src/H5FSint.c +++ b/src/H5FSint.c @@ -68,31 +68,6 @@ /*******************/ /*------------------------------------------------------------------------- - * Function: H5FS_init - * - * Purpose: Initialize the interface in case it is unable to initialize - * itself soon enough. - * - * Return: Success: non-negative - * Failure: negative - * - * Programmer: Quincey Koziol - * Saturday, March 4, 2000 - * - *------------------------------------------------------------------------- - */ -herr_t -H5FS_init(void) -{ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOERR - /* FUNC_ENTER() does all the work */ - - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FS_init() */ - -/*------------------------------------------------------------------------- * Function: H5FS__create_flush_depend * * Purpose: Create a flush dependency between two data structure components diff --git a/src/H5FSprivate.h b/src/H5FSprivate.h index fdc5c91..bb4f56a 100644 --- a/src/H5FSprivate.h +++ b/src/H5FSprivate.h @@ -116,7 +116,7 @@ typedef struct H5FS_section_class_t { const struct H5FS_section_class_t *, const uint8_t *, haddr_t, hsize_t, unsigned *); /* Routine to deserialize a buffer into a "live" section */ htri_t (*can_merge)(const H5FS_section_info_t *, const H5FS_section_info_t *, - void *); /* Routine to determine if two nodes are mergable */ + void *); /* Routine to determine if two nodes are mergeable */ herr_t (*merge)(H5FS_section_info_t **, H5FS_section_info_t *, void *); /* Routine to merge two nodes */ htri_t (*can_shrink)(const H5FS_section_info_t *, void *); /* Routine to determine if node can shrink container */ @@ -186,9 +186,6 @@ H5FL_SEQ_EXTERN(H5FS_section_class_t); /* Library-private Function Prototypes */ /***************************************/ -/* Package initialization routine */ -H5_DLL herr_t H5FS_init(void); - /* Free space manager routines */ H5_DLL H5FS_t *H5FS_create(H5F_t *f, haddr_t *fs_addr, const H5FS_create_t *fs_create, uint16_t nclasses, const H5FS_section_class_t *classes[], void *cls_init_udata, hsize_t alignment, diff --git a/src/H5FSsection.c b/src/H5FSsection.c index c764932..55f8a94 100644 --- a/src/H5FSsection.c +++ b/src/H5FSsection.c @@ -123,7 +123,7 @@ H5FS__sinfo_new(H5F_t *f, H5FS_t *fspace) HDassert(f); HDassert(fspace); #ifdef H5FS_SINFO_DEBUG - HDfprintf(stderr, "%s: fspace->addr = %a\n", __func__, fspace->addr); + HDfprintf(stderr, "%s: fspace->addr = %" PRIuHADDR "\n", __func__, fspace->addr); #endif /* H5FS_SINFO_DEBUG */ /* Allocate the free space header */ @@ -136,7 +136,7 @@ H5FS__sinfo_new(H5F_t *f, H5FS_t *fspace) sinfo->sect_off_size = (fspace->max_sect_addr + 7) / 8; sinfo->sect_len_size = H5VM_limit_enc_size((uint64_t)fspace->max_sect_size); #ifdef H5FS_SINFO_DEBUG - HDfprintf(stderr, "%s: fspace->max_sect_size = %Hu\n", __func__, fspace->max_sect_size); + HDfprintf(stderr, "%s: fspace->max_sect_size = %" PRIuHSIZE "\n", __func__, fspace->max_sect_size); HDfprintf(stderr, "%s: fspace->max_sect_addr = %u\n", __func__, fspace->max_sect_addr); HDfprintf(stderr, "%s: sinfo->nbins = %u\n", __func__, sinfo->nbins); HDfprintf(stderr, "%s: sinfo->sect_off_size = %u, sinfo->sect_len_size = %u\n", __func__, @@ -200,10 +200,12 @@ H5FS__sinfo_lock(H5F_t *f, H5FS_t *fspace, unsigned accmode) FUNC_ENTER_STATIC #ifdef H5FS_SINFO_DEBUG - HDfprintf(stderr, "%s: Called, fspace->addr = %a, fspace->sinfo = %p, fspace->sect_addr = %a\n", __func__, - fspace->addr, fspace->sinfo, fspace->sect_addr); - HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n", __func__, - fspace->alloc_sect_size, fspace->sect_size); + HDfprintf(stderr, + "%s: Called, fspace->addr = %" PRIuHADDR ", fspace->sinfo = %p, fspace->sect_addr = %" PRIuHADDR + "\n", + __func__, fspace->addr, (void *)fspace->sinfo, fspace->sect_addr); + HDfprintf(stderr, "%s: fspace->alloc_sect_size = %" PRIuHSIZE ", fspace->sect_size = %" PRIuHSIZE "\n", + __func__, fspace->alloc_sect_size, fspace->sect_size); #endif /* H5FS_SINFO_DEBUG */ /* Check arguments. */ @@ -251,8 +253,8 @@ H5FS__sinfo_lock(H5F_t *f, H5FS_t *fspace, unsigned accmode) HDassert(H5F_addr_defined(fspace->addr)); #ifdef H5FS_SINFO_DEBUG - HDfprintf(stderr, "%s: Reading in existing sections, fspace->sect_addr = %a\n", __func__, - fspace->sect_addr); + HDfprintf(stderr, "%s: Reading in existing sections, fspace->sect_addr = %" PRIuHADDR "\n", + __func__, fspace->sect_addr); #endif /* H5FS_SINFO_DEBUG */ /* Protect the free space sections */ cache_udata.f = f; @@ -289,10 +291,12 @@ H5FS__sinfo_lock(H5F_t *f, H5FS_t *fspace, unsigned accmode) done: #ifdef H5FS_SINFO_DEBUG - HDfprintf(stderr, "%s: Leaving, fspace->addr = %a, fspace->sinfo = %p, fspace->sect_addr = %a\n", - __func__, fspace->addr, fspace->sinfo, fspace->sect_addr); - HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n", __func__, - fspace->alloc_sect_size, fspace->sect_size); + HDfprintf(stderr, + "%s: Leaving, fspace->addr = %" PRIuHADDR + ", fspace->sinfo = %p, fspace->sect_addr = %" PRIuHADDR "\n", + __func__, fspace->addr, (void *)fspace->sinfo, fspace->sect_addr); + HDfprintf(stderr, "%s: fspace->alloc_sect_size = %" PRIuHSIZE ", fspace->sect_size = %" PRIuHSIZE "\n", + __func__, fspace->alloc_sect_size, fspace->sect_size); #endif /* H5FS_SINFO_DEBUG */ FUNC_LEAVE_NOAPI(ret_value) } /* H5FS__sinfo_lock() */ @@ -331,14 +335,16 @@ H5FS__sinfo_unlock(H5F_t *f, H5FS_t *fspace, hbool_t modified) FUNC_ENTER_STATIC #ifdef H5FS_SINFO_DEBUG - HDfprintf(stderr, "%s: Called, modified = %t, fspace->addr = %a, fspace->sect_addr = %a\n", __func__, - modified, fspace->addr, fspace->sect_addr); + HDfprintf(stderr, + "%s: Called, modified = %d, fspace->addr = %" PRIuHADDR ", fspace->sect_addr = %" PRIuHADDR + "\n", + __func__, modified, fspace->addr, fspace->sect_addr); HDfprintf( stderr, - "%s: fspace->sinfo_lock_count = %u, fspace->sinfo_modified = %t, fspace->sinfo_protected = %t\n", + "%s: fspace->sinfo_lock_count = %u, fspace->sinfo_modified = %d, fspace->sinfo_protected = %d\n", __func__, fspace->sinfo_lock_count, fspace->sinfo_modified, fspace->sinfo_protected); - HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n", __func__, - fspace->alloc_sect_size, fspace->sect_size); + HDfprintf(stderr, "%s: fspace->alloc_sect_size = %" PRIuHSIZE ", fspace->sect_size = %" PRIuHSIZE "\n", + __func__, fspace->alloc_sect_size, fspace->sect_size); #endif /* H5FS_SINFO_DEBUG */ /* Check arguments. */ @@ -490,7 +496,8 @@ H5FS__sinfo_unlock(H5F_t *f, H5FS_t *fspace, hbool_t modified) #ifdef H5FS_SINFO_DEBUG HDfprintf(stderr, - "%s: Freeing section info on disk, old_sect_addr = %a, old_alloc_sect_size = %Hu\n", + "%s: Freeing section info on disk, old_sect_addr = %" PRIuHADDR + ", old_alloc_sect_size = %" PRIuHSIZE "\n", __func__, old_sect_addr, old_alloc_sect_size); #endif /* H5FS_SINFO_DEBUG */ /* Release space for section info in file */ @@ -1343,7 +1350,8 @@ H5FS_sect_add(H5F_t *f, H5FS_t *fspace, H5FS_section_info_t *sect, unsigned flag FUNC_ENTER_NOAPI(FAIL) #ifdef H5FS_SINFO_DEBUG - HDfprintf(stderr, "%s: *sect = {%a, %Hu, %u, %s}\n", __func__, sect->addr, sect->size, sect->type, + HDfprintf(stderr, "%s: *sect = {%" PRIuHADDR ", %" PRIuHSIZE ", %u, %s}\n", __func__, sect->addr, + sect->size, sect->type, (sect->state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED")); #endif /* H5FS_SINFO_DEBUG */ @@ -1384,7 +1392,7 @@ H5FS_sect_add(H5F_t *f, H5FS_t *fspace, H5FS_section_info_t *sect, unsigned flag HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't insert free space section into skip list") #ifdef H5FS_SINFO_DEBUG - HDfprintf(stderr, "%s: fspace->tot_space = %Hu\n", __func__, fspace->tot_space); + HDfprintf(stderr, "%s: fspace->tot_space = %" PRIuHSIZE "\n", __func__, fspace->tot_space); #endif /* H5FS_SINFO_DEBUG */ /* Mark free space sections as changed */ /* (if adding sections while deserializing sections, don't set the flag) */ @@ -1429,8 +1437,8 @@ H5FS_sect_try_extend(H5F_t *f, H5FS_t *fspace, haddr_t addr, hsize_t size, hsize FUNC_ENTER_NOAPI(FAIL) #ifdef H5FS_SINFO_DEBUG - HDfprintf(stderr, "%s: addr = %a, size = %Hu, extra_requested = %hu\n", __func__, addr, size, - extra_requested); + HDfprintf(stderr, "%s: addr = %" PRIuHADDR ", size = %" PRIuHSIZE ", extra_requested = %" PRIuHSIZE "\n", + __func__, addr, size, extra_requested); #endif /* H5FS_SINFO_DEBUG */ /* Check arguments. */ @@ -1442,9 +1450,10 @@ H5FS_sect_try_extend(H5F_t *f, H5FS_t *fspace, haddr_t addr, hsize_t size, hsize /* Check for any sections on free space list */ #ifdef H5FS_SINFO_DEBUG - HDfprintf(stderr, "%s: fspace->tot_sect_count = %Hu\n", __func__, fspace->tot_sect_count); - HDfprintf(stderr, "%s: fspace->serial_sect_count = %Hu\n", __func__, fspace->serial_sect_count); - HDfprintf(stderr, "%s: fspace->ghost_sect_count = %Hu\n", __func__, fspace->ghost_sect_count); + HDfprintf(stderr, "%s: fspace->tot_sect_count = %" PRIuHSIZE "\n", __func__, fspace->tot_sect_count); + HDfprintf(stderr, "%s: fspace->serial_sect_count = %" PRIuHSIZE "\n", __func__, + fspace->serial_sect_count); + HDfprintf(stderr, "%s: fspace->ghost_sect_count = %" PRIuHSIZE "\n", __func__, fspace->ghost_sect_count); #endif /* H5FS_SINFO_DEBUG */ if (fspace->tot_sect_count > 0) { H5FS_section_info_t *sect; /* Temporary free space section */ @@ -1592,7 +1601,7 @@ H5FS_sect_try_merge(H5F_t *f, H5FS_t *fspace, H5FS_section_info_t *sect, unsigne } /* end if */ else { /* Check if section is merged */ - if (sect->size > saved_fs_size) { + if (sect->size != saved_fs_size) { if (H5FS__sect_link(fspace, sect, flags) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't insert free space section into skip list") @@ -2082,11 +2091,11 @@ H5FS_sect_change_class(H5F_t *f, H5FS_t *fspace, H5FS_section_info_t *sect, uint } /* end else */ } /* end if */ - /* Check if the section's class change will affect the mergable list */ + /* Check if the section's class change will affect the mergeable list */ if ((old_cls->flags & H5FS_CLS_SEPAR_OBJ) != (new_cls->flags & H5FS_CLS_SEPAR_OBJ)) { - hbool_t to_mergable; /* Flag if the section is changing to a mergable section */ + hbool_t to_mergable; /* Flag if the section is changing to a mergeable section */ - /* Determine if this section is becoming mergable or is becoming separate */ + /* Determine if this section is becoming mergeable or is becoming separate */ if (old_cls->flags & H5FS_CLS_SEPAR_OBJ) to_mergable = TRUE; else diff --git a/src/H5Fcwfs.c b/src/H5Fcwfs.c index d689737..43c8cf7 100644 --- a/src/H5Fcwfs.c +++ b/src/H5Fcwfs.c @@ -252,7 +252,7 @@ H5F_cwfs_advance_heap(H5F_t *f, H5HG_heap_t *heap, hbool_t add_heap) unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR /* Check args */ HDassert(f); @@ -272,7 +272,6 @@ H5F_cwfs_advance_heap(H5F_t *f, H5HG_heap_t *heap, hbool_t add_heap) f->shared->cwfs[f->shared->ncwfs - 1] = heap; } /* end if */ -done: FUNC_LEAVE_NOAPI(ret_value) } /* H5F_cwfs_advance_heap() */ @@ -295,7 +294,7 @@ H5F_cwfs_remove_heap(H5F_shared_t *shared, H5HG_heap_t *heap) unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR /* Check args */ HDassert(shared); @@ -310,6 +309,5 @@ H5F_cwfs_remove_heap(H5F_shared_t *shared, H5HG_heap_t *heap) } /* end if */ } /* end for */ -done: FUNC_LEAVE_NOAPI(ret_value) } /* H5F_cwfs_remove_heap() */ diff --git a/src/H5Fefc.c b/src/H5Fefc.c index 2d4eff2..2c7dd92 100644 --- a/src/H5Fefc.c +++ b/src/H5Fefc.c @@ -450,7 +450,7 @@ H5F__efc_release_real(H5F_efc_t *efc) /* Sanity checks */ HDassert(efc); - /* Lock the EFC to prevent manipulation of the EFC wile we are releasing it. + /* Lock the EFC to prevent manipulation of the EFC while we are releasing it. * The EFC should never be locked when we enter this function because that * would require a cycle, a cycle would necessarily invoke * H5F__efc_try_close(), and that function checks the status of the lock diff --git a/src/H5Fint.c b/src/H5Fint.c index c2d3e77..05bba16 100644 --- a/src/H5Fint.c +++ b/src/H5Fint.c @@ -91,9 +91,6 @@ static herr_t H5F__flush_phase2(H5F_t *f, hbool_t closing); /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /* Based on the value of the HDF5_USE_FILE_LOCKING environment variable. * TRUE/FALSE have obvious meanings. FAIL means the environment variable was * not set, so the code should ignore it and use the fapl value instead. @@ -138,29 +135,6 @@ H5F_init(void) herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) - /* FUNC_ENTER() does all the work */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5F_init() */ - -/*-------------------------------------------------------------------------- -NAME - H5F__init_package -- Initialize interface-specific information -USAGE - herr_t H5F__init_package() -RETURNS - Non-negative on success/Negative on failure -DESCRIPTION - Initializes any interface-specific data or routines. - ---------------------------------------------------------------------------*/ -herr_t -H5F__init_package(void) -{ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_PACKAGE /* Initialize the ID group for the file IDs */ if (H5I_register_type(H5I_FILE_CLS) < 0) @@ -172,7 +146,7 @@ H5F__init_package(void) done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5F__init_package() */ +} /* end H5F_init() */ /*------------------------------------------------------------------------- * Function: H5F_term_package @@ -196,23 +170,17 @@ H5F_term_package(void) FUNC_ENTER_NOAPI_NOINIT_NOERR - if (H5_PKG_INIT_VAR) { - if (H5I_nmembers(H5I_FILE) > 0) { - (void)H5I_clear_type(H5I_FILE, FALSE, FALSE); - n++; /*H5I*/ - } /* end if */ - else { - /* Make certain we've cleaned up all the shared file objects */ - H5F_sfile_assert_num(0); - - /* Destroy the file object id group */ - n += (H5I_dec_type_ref(H5I_FILE) > 0); + if (H5I_nmembers(H5I_FILE) > 0) { + (void)H5I_clear_type(H5I_FILE, FALSE, FALSE); + n++; /*H5I*/ + } /* end if */ + else { + /* Make certain we've cleaned up all the shared file objects */ + H5F_sfile_assert_num(0); - /* Mark closed */ - if (0 == n) - H5_PKG_INIT_VAR = FALSE; - } /* end else */ - } /* end if */ + /* Destroy the file object id group */ + n += (H5I_dec_type_ref(H5I_FILE) > 0); + } /* end else */ FUNC_LEAVE_NOAPI(n) } /* end H5F_term_package() */ @@ -277,7 +245,7 @@ H5F__parse_file_lock_env_var(htri_t *use_locks) FUNC_ENTER_PACKAGE_NOERR /* Check the file locking environment variable */ - lock_env_var = HDgetenv("HDF5_USE_FILE_LOCKING"); + lock_env_var = HDgetenv(HDF5_USE_FILE_LOCKING); if (lock_env_var && (!HDstrcmp(lock_env_var, "FALSE") || !HDstrcmp(lock_env_var, "0"))) *use_locks = FALSE; /* Override: Never use locks */ else if (lock_env_var && (!HDstrcmp(lock_env_var, "TRUE") || !HDstrcmp(lock_env_var, "BEST_EFFORT") || @@ -454,9 +422,10 @@ H5F_get_access_plist(H5F_t *f, hbool_t app_ref) HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set initial metadata cache resize config.") /* Prepare the driver property */ - driver_prop.driver_id = f->shared->lf->driver_id; - driver_prop.driver_info = H5FD_fapl_get(f->shared->lf); - driver_prop_copied = TRUE; + driver_prop.driver_id = f->shared->lf->driver_id; + driver_prop.driver_info = H5FD_fapl_get(f->shared->lf); + driver_prop.driver_config_str = H5P_peek_driver_config_str(old_plist); + driver_prop_copied = TRUE; /* Set the driver property */ if (H5P_set(new_plist, H5F_ACS_FILE_DRV_NAME, &driver_prop) < 0) @@ -1059,7 +1028,7 @@ H5F__is_hdf5(const char *name, hid_t fapl_id) { H5FD_t * file = NULL; /* Low-level file struct */ H5F_shared_t *shared = NULL; /* Shared part of file */ - haddr_t sig_addr = HADDR_UNDEF; /* Addess of hdf5 file signature */ + haddr_t sig_addr = HADDR_UNDEF; /* Address of hdf5 file signature */ htri_t ret_value = FAIL; /* Return value */ FUNC_ENTER_PACKAGE @@ -1156,7 +1125,7 @@ H5F__new(H5F_shared_t *shared, unsigned flags, hid_t fcpl_id, hid_t fapl_id, H5F /* Initialization for handling file space (for paged aggregation) */ f->shared->pgend_meta_thres = H5F_FILE_SPACE_PGEND_META_THRES; - /* intialize point of no return */ + /* initialize point of no return */ f->shared->point_of_no_return = FALSE; /* Copy the file creation and file access property lists into the @@ -1293,7 +1262,7 @@ H5F__new(H5F_shared_t *shared, unsigned flags, hid_t fcpl_id, hid_t fapl_id, H5F f->shared->read_attempts = H5F_METADATA_READ_ATTEMPTS; } - /* Determine the # of bins for metdata read retries */ + /* Determine the # of bins for metadata read retries */ if (H5F_set_retries(f) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "can't set retries and retries_nbins") @@ -1818,7 +1787,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id) * or creating it) so we can compare it with files that are already * open. If that fails then we try again with the full set of flags * (only if they're different than the original failed attempt). - * However, if the file driver can't distinquish between files then + * However, if the file driver can't distinguish between files then * there's no reason to open the file tentatively because it's the * application's responsibility to prevent this situation (there's no * way for us to detect it here anyway). @@ -1828,7 +1797,13 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id) else tent_flags = flags; - if (NULL == (lf = H5FD_open(name, tent_flags, fapl_id, HADDR_UNDEF))) { + H5E_BEGIN_TRY + { + lf = H5FD_open(name, tent_flags, fapl_id, HADDR_UNDEF); + } + H5E_END_TRY; + + if (NULL == lf) { if (tent_flags == flags) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file: name = '%s', tent_flags = %x", name, tent_flags) @@ -3141,7 +3116,7 @@ H5F__get_file_image(H5F_t *file, void *buf_ptr, size_t buf_len, size_t *image_le * file driver. However, this test will not work if there is some * other file driver sitting on top of the multi file driver. * - * I'm not sure if this is possible at present, but in all likelyhood, + * I'm not sure if this is possible at present, but in all likelihood, * it will become possible in the future. On the other hand, we may * remove the split/multi file drivers before then. * @@ -3161,7 +3136,7 @@ H5F__get_file_image(H5F_t *file, void *buf_ptr, size_t buf_len, size_t *image_le * * While this problem is quite solvable, the required time and * resources are lacking at present. Hence, for now, we don't - * allow the get file image operation to be perfomed on files + * allow the get file image operation to be performed on files * opened with the family file driver. * * Observe that the following test only looks at the top level @@ -3592,7 +3567,7 @@ done: * 1) The file being opened has v3 superblock * 2) The file is opened with H5F_ACC_RDWR * 3) The file is not already marked for SWMR writing - * 4) Current implementaion for opened objects: + * 4) Current implementation for opened objects: * --only allow datasets and groups without attributes * --disallow named datatype with/without attributes * --disallow opened attributes attached to objects diff --git a/src/H5Fio.c b/src/H5Fio.c index 5a9d2c1..53fec97 100644 --- a/src/H5Fio.c +++ b/src/H5Fio.c @@ -233,12 +233,101 @@ H5F_block_write(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size, const void /* Pass through page buffer layer */ if (H5PB_write(f->shared, map_type, addr, size, buf) < 0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "write through page buffer failed") - done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5F_block_write() */ /*------------------------------------------------------------------------- + * Function: H5F_shared_select_read + * + * Purpose: Reads some data from a file/server/etc into a buffer. + * The location of the data is defined by the mem_spaces and + * file_spaces dataspace arrays, along with the offsets + * array. The addresses is relative to the base address for + * the file. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Neil Fortner + * May 3 2021 + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_shared_select_read(H5F_shared_t *f_sh, H5FD_mem_t type, uint32_t count, H5S_t **mem_spaces, + H5S_t **file_spaces, haddr_t offsets[], size_t element_sizes[], void *bufs[] /* out */) +{ + H5FD_mem_t map_type; /* Mapped memory type */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity checks */ + HDassert(f_sh); + HDassert((mem_spaces) || (count == 0)); + HDassert((file_spaces) || (count == 0)); + HDassert((offsets) || (count == 0)); + HDassert((element_sizes) || (count == 0)); + HDassert((bufs) || (count == 0)); + + /* Treat global heap as raw data */ + map_type = (type == H5FD_MEM_GHEAP) ? H5FD_MEM_DRAW : type; + + /* Pass down to file driver layer (bypass page buffer for now) */ + if (H5FD_read_selection(f_sh->lf, map_type, count, mem_spaces, file_spaces, offsets, element_sizes, + bufs) < 0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "selection read through file driver failed") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_shared_select_read() */ + +/*------------------------------------------------------------------------- + * Function: H5F_shared_select_write + * + * Purpose: Writes some data from a buffer to a file/server/etc. + * The location of the data is defined by the mem_spaces and + * file_spaces dataspace arrays, along with the offsets + * array. The addresses is relative to the base address for + * the file. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Neil Fortner + * May 4 2021 + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_shared_select_write(H5F_shared_t *f_sh, H5FD_mem_t type, uint32_t count, H5S_t **mem_spaces, + H5S_t **file_spaces, haddr_t offsets[], size_t element_sizes[], const void *bufs[]) +{ + H5FD_mem_t map_type; /* Mapped memory type */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity checks */ + HDassert(f_sh); + HDassert((mem_spaces) || (count == 0)); + HDassert((file_spaces) || (count == 0)); + HDassert((offsets) || (count == 0)); + HDassert((element_sizes) || (count == 0)); + HDassert((bufs) || (count == 0)); + + /* Treat global heap as raw data */ + map_type = (type == H5FD_MEM_GHEAP) ? H5FD_MEM_DRAW : type; + + /* Pass down to file driver layer (bypass page buffer for now) */ + if (H5FD_write_selection(f_sh->lf, map_type, count, mem_spaces, file_spaces, offsets, element_sizes, + bufs) < 0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "selection write through file driver failed") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_shared_select_write() */ + +/*------------------------------------------------------------------------- * Function: H5F_flush_tagged_metadata * * Purpose: Flushes metadata with specified tag in the metadata cache diff --git a/src/H5Fmount.c b/src/H5Fmount.c index 4b90ea3..7d27234 100644 --- a/src/H5Fmount.c +++ b/src/H5Fmount.c @@ -104,7 +104,7 @@ H5F_mount(const H5G_loc_t *loc, const char *name, H5F_t *child, hid_t H5_ATTR_UN H5F_t * parent = NULL; /*file containing mount point */ unsigned lt, rt, md; /*binary search indices */ int cmp; /*binary search comparison value*/ - H5G_loc_t mp_loc; /* entry of moint point to be opened */ + H5G_loc_t mp_loc; /* entry of mount point to be opened */ H5G_name_t mp_path; /* Mount point group hier. path */ H5O_loc_t mp_oloc; /* Mount point object location */ H5G_loc_t root_loc; /* Group location of root of file to mount */ diff --git a/src/H5Fmpi.c b/src/H5Fmpi.c index 53d2d78..02d8d52 100644 --- a/src/H5Fmpi.c +++ b/src/H5Fmpi.c @@ -31,11 +31,12 @@ /***********/ /* Headers */ /***********/ -#include "H5private.h" /* Generic Functions */ -#include "H5Eprivate.h" /* Error handling */ -#include "H5Fpkg.h" /* File access */ -#include "H5FDprivate.h" /* File drivers */ -#include "H5Iprivate.h" /* IDs */ +#include "H5private.h" /* Generic Functions */ +#include "H5CXprivate.h" /* API Contexts */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Fpkg.h" /* File access */ +#include "H5FDprivate.h" /* File drivers */ +#include "H5Iprivate.h" /* IDs */ #include "H5VLnative_private.h" /* Native VOL connector */ @@ -402,4 +403,189 @@ H5F_mpi_retrieve_comm(hid_t loc_id, hid_t acspl_id, MPI_Comm *mpi_comm) done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5F_mpi_retrieve_comm */ + +/*------------------------------------------------------------------------- + * Function: H5F_get_coll_metadata_reads + * + * Purpose: Determines whether collective metadata reads should be + * performed. This routine is meant to be the single source of + * truth for the collective metadata reads status, as it + * coordinates between the file-global flag and the flag set + * for the current operation in the current API context. + * + * Return: TRUE/FALSE (can't fail) + * + *------------------------------------------------------------------------- + */ +hbool_t +H5F_get_coll_metadata_reads(const H5F_t *file) +{ + H5P_coll_md_read_flag_t file_flag = H5P_USER_FALSE; + hbool_t ret_value = FALSE; + + FUNC_ENTER_NOAPI_NOERR + + HDassert(file && file->shared); + + /* Retrieve the file-global flag */ + file_flag = H5F_COLL_MD_READ(file); + + /* If file flag is set to H5P_FORCE_FALSE, exit early + * with FALSE, since collective metadata reads have + * been explicitly disabled somewhere in the library. + */ + if (H5P_FORCE_FALSE == file_flag) + ret_value = FALSE; + else { + /* If file flag is set to H5P_USER_TRUE, ignore + * any settings in the API context. A file-global + * setting of H5P_USER_TRUE for collective metadata + * reads should ignore any settings on an Access + * Property List for an individual operation. + */ + if (H5P_USER_TRUE == file_flag) + ret_value = TRUE; + else { + /* Get the collective metadata reads flag from + * the current API context. + */ + ret_value = H5CX_get_coll_metadata_read(); + } + } + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_get_coll_metadata_reads() */ + +/*------------------------------------------------------------------------- + * Function: H5F_set_coll_metadata_reads + * + * Purpose: Used to temporarily modify the collective metadata reads + * status. This is useful for cases where either: + * + * * Collective metadata reads are enabled, but need to be + * disabled for an operation about to occur that may trigger + * an independent metadata read (such as only rank 0 doing + * something) + * + * * Metadata reads are currently independent, but it is + * guaranteed that the application has maintained + * collectivity at the interface level (e.g., an operation + * that modifies metadata is being performed). In this case, + * it should be safe to enable collective metadata reads, + * barring any internal library issues that may occur + * + * After completion, the `file_flag` parameter will be set to + * the previous value of the file-global collective metadata + * reads flag. The `context_flag` parameter will be set to the + * previous value of the API context's collective metadata + * reads flag. Another call to this routine should be made to + * restore these values (see below warning). + * + * !! WARNING !! + * It is dangerous to modify the collective metadata reads + * status, as this can cause crashes, hangs and corruption in + * the HDF5 file when improperly done. Therefore, the + * `file_flag` and `context_flag` parameters are both + * mandatory, and it is assumed that the caller will guarantee + * these settings are restored with another call to this + * routine once the bracketed operation is complete. + * !! WARNING !! + * + * Return: Nothing + * + *------------------------------------------------------------------------- + */ +void +H5F_set_coll_metadata_reads(H5F_t *file, H5P_coll_md_read_flag_t *file_flag, hbool_t *context_flag) +{ + H5P_coll_md_read_flag_t prev_file_flag = H5P_USER_FALSE; + hbool_t prev_context_flag = FALSE; + + FUNC_ENTER_NOAPI_NOERR + + HDassert(file && file->shared); + HDassert(file_flag); + HDassert(context_flag); + + /* Save old state */ + prev_file_flag = H5F_COLL_MD_READ(file); + prev_context_flag = H5CX_get_coll_metadata_read(); + + /* Set new desired state */ + if (prev_file_flag != *file_flag) { + file->shared->coll_md_read = *file_flag; + *file_flag = prev_file_flag; + } + if (prev_context_flag != *context_flag) { + H5CX_set_coll_metadata_read(*context_flag); + *context_flag = prev_context_flag; + } + + FUNC_LEAVE_NOAPI_VOID +} /* end H5F_set_coll_metadata_reads() */ + +/*------------------------------------------------------------------------- + * Function: H5F_mpi_get_file_block_type + * + * Purpose: Creates an MPI derived datatype for communicating an + * H5F_block_t structure. If `commit` is specified as TRUE, + * the resulting datatype will be committed and ready for + * use in communication. Otherwise, the type is only suitable + * for building other derived types. + * + * If TRUE is returned through `new_type_derived`, this lets + * the caller know that the datatype has been derived and + * should be freed with MPI_Type_free once it is no longer + * needed. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_mpi_get_file_block_type(hbool_t commit, MPI_Datatype *new_type, hbool_t *new_type_derived) +{ + MPI_Datatype types[2]; + MPI_Aint displacements[2]; + int block_lengths[2]; + int field_count; + int mpi_code; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(FAIL) + + HDassert(new_type); + HDassert(new_type_derived); + + *new_type_derived = FALSE; + + field_count = 2; + HDassert(field_count == sizeof(types) / sizeof(MPI_Datatype)); + + block_lengths[0] = 1; + block_lengths[1] = 1; + displacements[0] = offsetof(H5F_block_t, offset); + displacements[1] = offsetof(H5F_block_t, length); + types[0] = HADDR_AS_MPI_TYPE; + types[1] = HSIZE_AS_MPI_TYPE; + if (MPI_SUCCESS != + (mpi_code = MPI_Type_create_struct(field_count, block_lengths, displacements, types, new_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_struct failed", mpi_code) + *new_type_derived = TRUE; + + if (commit && MPI_SUCCESS != (mpi_code = MPI_Type_commit(new_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code) + +done: + if (ret_value < 0) { + if (*new_type_derived) { + if (MPI_SUCCESS != (mpi_code = MPI_Type_free(new_type))) + HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code) + *new_type_derived = FALSE; + } + } + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_mpi_get_file_block_type() */ + #endif /* H5_HAVE_PARALLEL */ diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h index b016696..9208815 100644 --- a/src/H5Fpkg.h +++ b/src/H5Fpkg.h @@ -79,7 +79,7 @@ #define H5F_SUPERBLOCK_FIXED_SIZE (H5F_SIGNATURE_LEN + 1) /* superblock version */ /* The H5F_SUPERBLOCK_MINIMAL_VARLEN_SIZE is the minimal amount of super block - * variable length data guarnateed to load the sizeof offsets and the sizeof + * variable length data guaranteed to load the sizeof offsets and the sizeof * lengths fields in all versions of the superblock. * * This is necessary in the V3 cache, as on the initial load, we need to @@ -352,7 +352,7 @@ struct H5F_shared_t { /* Metadata retry info */ unsigned read_attempts; /* The # of reads to try when reading metadata with checksum */ unsigned retries_nbins; /* # of bins for each retries[] */ - uint32_t *retries[H5AC_NTYPES]; /* Track # of read retries for metdata items with checksum */ + uint32_t *retries[H5AC_NTYPES]; /* Track # of read retries for metadata items with checksum */ /* Object flush info */ H5F_object_flush_t object_flush; /* Information for object flush callback */ diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index 051abd9..629aee1 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -24,11 +24,9 @@ typedef struct H5F_t H5F_t; /* Include package's public header */ #include "H5Fpublic.h" -/* Public headers needed by this file */ -#include "H5FDpublic.h" /* File drivers */ - /* Private headers needed by this file */ #include "H5MMprivate.h" /* Memory management */ +#include "H5FDprivate.h" /* File drivers */ #ifdef H5_HAVE_PARALLEL #include "H5Pprivate.h" /* Property lists */ #endif /* H5_HAVE_PARALLEL */ @@ -760,6 +758,7 @@ struct H5O_loc_t; struct H5HG_heap_t; struct H5VL_class_t; struct H5P_genplist_t; +struct H5S_t; /* Forward declarations for anonymous H5F objects */ @@ -906,6 +905,7 @@ H5_DLL hbool_t H5F_shared_has_feature(const H5F_shared_t *f, unsigned feature); H5_DLL hbool_t H5F_has_feature(const H5F_t *f, unsigned feature); H5_DLL haddr_t H5F_shared_get_eoa(const H5F_shared_t *f_sh, H5FD_mem_t type); H5_DLL haddr_t H5F_get_eoa(const H5F_t *f, H5FD_mem_t type); +H5_DLL herr_t H5F_shared_get_file_driver(const H5F_shared_t *f_sh, H5FD_t **file_handle); H5_DLL herr_t H5F_get_vfd_handle(const H5F_t *file, hid_t fapl, void **file_handle); /* File mounting routines */ @@ -924,6 +924,14 @@ H5_DLL herr_t H5F_shared_block_write(H5F_shared_t *f_sh, H5FD_mem_t type, haddr_ const void *buf); H5_DLL herr_t H5F_block_write(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size, const void *buf); +/* Functions that operate on selections of elements in the file */ +H5_DLL herr_t H5F_shared_select_read(H5F_shared_t *f_sh, H5FD_mem_t type, uint32_t count, + struct H5S_t **mem_spaces, struct H5S_t **file_spaces, haddr_t offsets[], + size_t element_sizes[], void *bufs[] /* out */); +H5_DLL herr_t H5F_shared_select_write(H5F_shared_t *f_sh, H5FD_mem_t type, uint32_t count, + struct H5S_t **mem_spaces, struct H5S_t **file_spaces, + haddr_t offsets[], size_t element_sizes[], const void *bufs[]); + /* Functions that flush or evict */ H5_DLL herr_t H5F_flush_tagged_metadata(H5F_t *f, haddr_t tag); H5_DLL herr_t H5F_evict_tagged_metadata(H5F_t *f, haddr_t tag); @@ -963,6 +971,9 @@ H5_DLL MPI_Comm H5F_mpi_get_comm(const H5F_t *f); H5_DLL int H5F_shared_mpi_get_size(const H5F_shared_t *f_sh); H5_DLL int H5F_mpi_get_size(const H5F_t *f); H5_DLL herr_t H5F_mpi_retrieve_comm(hid_t loc_id, hid_t acspl_id, MPI_Comm *mpi_comm); +H5_DLL herr_t H5F_mpi_get_file_block_type(hbool_t commit, MPI_Datatype *new_type, hbool_t *new_type_derived); +H5_DLL hbool_t H5F_get_coll_metadata_reads(const H5F_t *f); +H5_DLL void H5F_set_coll_metadata_reads(H5F_t *f, H5P_coll_md_read_flag_t *file_flag, hbool_t *context_flag); #endif /* H5_HAVE_PARALLEL */ /* External file cache routines */ diff --git a/src/H5Fpublic.h b/src/H5Fpublic.h index c3230e1..671eec3 100644 --- a/src/H5Fpublic.h +++ b/src/H5Fpublic.h @@ -1606,7 +1606,7 @@ H5_DLL herr_t H5Fget_page_buffering_stats(hid_t file_id, unsigned accesses[2], u * \brief Obtains information about a cache image if it exists * * \file_id - * \param[out] image_addr Offset of the cache image if it exists, or \c HADDR_UNDEF if it does not + * \param[out] image_addr Offset of the cache image if it exists, or #HADDR_UNDEF if it does not * \param[out] image_size Length of the cache image if it exists, or 0 if it does not * \returns \herr_t * @@ -1878,6 +1878,7 @@ H5_DLL herr_t H5Fget_info1(hid_t obj_id, H5F_info1_t *file_info); * * \deprecated When? * + * \todo In which version was this function introduced? * \todo In which version was this function deprecated? * */ @@ -1896,6 +1897,7 @@ H5_DLL herr_t H5Fset_latest_format(hid_t file_id, hbool_t latest_format); * \details H5Fis_hdf5() determines whether a file is in the HDF5 format. * * \todo In which version was this function deprecated? + * \todo In which version was this function introduced? * */ H5_DLL htri_t H5Fis_hdf5(const char *file_name); diff --git a/src/H5Fquery.c b/src/H5Fquery.c index 04792b4..a625897 100644 --- a/src/H5Fquery.c +++ b/src/H5Fquery.c @@ -950,6 +950,29 @@ done: } /* end H5F_get_eoa() */ /*------------------------------------------------------------------------- + * Function: H5F_shared_get_file_driver + * + * Purpose: Returns a pointer to the file driver structure of the + * file's 'shared' structure. + * + * Return: file handle on success/abort on failure (shouldn't fail) + *------------------------------------------------------------------------- + */ +herr_t +H5F_shared_get_file_driver(const H5F_shared_t *f_sh, H5FD_t **file_handle) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOERR + + HDassert(f_sh); + HDassert(file_handle); + + *file_handle = f_sh->lf; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5F_shared_get_file_driver() */ + +/*------------------------------------------------------------------------- * Function: H5F_get_vfd_handle * * Purpose: Returns a pointer to the file handle of the low-level file diff --git a/src/H5Fsuper.c b/src/H5Fsuper.c index 4df0064..bf02b06 100644 --- a/src/H5Fsuper.c +++ b/src/H5Fsuper.c @@ -375,7 +375,7 @@ H5F__super_read(H5F_t *f, H5P_genplist_t *fa_plist, hbool_t initial_read) if (0 == mpi_rank) { herr_t status; - /* Try detecting file's siganture */ + /* Try detecting file's signature */ /* (Don't leave before Bcast, to avoid hang on error) */ H5E_BEGIN_TRY { @@ -467,7 +467,7 @@ H5F__super_read(H5F_t *f, H5P_genplist_t *fa_plist, hbool_t initial_read) * * After upgrading low_bound, the library will check to ensure that the * superblock version does not exceed the version allowed by high_bound. - * Otherise fail file open. + * Otherwise fail file open. * * For details, please see RFC:Setting Bounds for Object Creation in HDF5 1.10.0. */ diff --git a/src/H5Fsuper_cache.c b/src/H5Fsuper_cache.c index 28ff82f..b9dc74a 100644 --- a/src/H5Fsuper_cache.c +++ b/src/H5Fsuper_cache.c @@ -698,7 +698,7 @@ H5F__cache_superblock_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNU HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "driver get_eoa request failed") H5F_addr_encode(f, &image, (rel_eof + sblock->base_addr)); - /* Encode the driver informaton block address */ + /* Encode the driver information block address */ H5F_addr_encode(f, &image, sblock->driver_addr); /* Encode the root group object entry, including the cached stab info */ @@ -797,7 +797,7 @@ done: /*------------------------------------------------------------------------- * Function: H5F__cache_drvrinfo_get_initial_load_size * - * Purpose: Compute the intiial size of the data structure on disk. + * Purpose: Compute the initial size of the data structure on disk. * * Return: Non-negative on success/Negative on failure * diff --git a/src/H5Gcache.c b/src/H5Gcache.c index 4713193..65ed1e6 100644 --- a/src/H5Gcache.c +++ b/src/H5Gcache.c @@ -134,7 +134,7 @@ H5G__cache_node_get_initial_load_size(void *_udata, size_t *image_len) * Function: H5G__cache_node_deserialize * * Purpose: Given a buffer containing the on disk image of a symbol table - * node, allocate an instance of H5G_node_t, load the contence of the + * node, allocate an instance of H5G_node_t, load the contents of the * image into it, and return a pointer to the instance. * * Note that deserializing the image requires access to the file @@ -240,7 +240,7 @@ H5G__cache_node_image_len(const void *_thing, size_t *image_len) /*------------------------------------------------------------------------- * Function: H5G__cache_node_serialize * - * Purpose: Given a correctly sized buffer and an instace of H5G_node_t, + * Purpose: Given a correctly sized buffer and an instance of H5G_node_t, * serialize the contents of the instance of H5G_node_t, and write * this data into the supplied buffer. This buffer will be written * to disk. diff --git a/src/H5Gcompact.c b/src/H5Gcompact.c index 0c0b5db..4988738 100644 --- a/src/H5Gcompact.c +++ b/src/H5Gcompact.c @@ -419,7 +419,7 @@ done: * Function: H5G__compact_lookup_cb * * Purpose: Callback routine for searching 'link' messages for a particular - * name & gettting object location for it + * name & getting object location for it * * Return: SUCCEED/FAIL * diff --git a/src/H5Gint.c b/src/H5Gint.c index 90a2c6b..ba0cb6d 100644 --- a/src/H5Gint.c +++ b/src/H5Gint.c @@ -91,9 +91,6 @@ static herr_t H5G__close_cb(H5VL_object_t *grp_vol_obj, void **request); /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /* Declare a free list to manage the H5G_t struct */ H5FL_DEFINE(H5G_t); H5FL_DEFINE(H5G_shared_t); @@ -117,9 +114,6 @@ static const H5I_class_t H5I_GROUP_CLS[1] = {{ (H5I_free_t)H5G__close_cb /* Callback routine for closing objects of this class */ }}; -/* Flag indicating "top" of interface has been initialized */ -static hbool_t H5G_top_package_initialize_s = FALSE; - /*------------------------------------------------------------------------- * Function: H5G_init * @@ -136,48 +130,13 @@ H5G_init(void) herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) - /* FUNC_ENTER() does all the work */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5G_init() */ - -/*------------------------------------------------------------------------- - * Function: H5G__init_package - * - * Purpose: Initializes the H5G interface. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Monday, January 5, 1998 - * - * Notes: The group creation properties are registered in the property - * list interface initialization routine (H5P_init_package) - * so that the file creation property class can inherit from it - * correctly. (Which allows the file creation property list to - * control the group creation properties of the root group of - * a file) QAK - 24/10/2005 - * - *------------------------------------------------------------------------- - */ -herr_t -H5G__init_package(void) -{ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_PACKAGE - /* Initialize the ID group for the group IDs */ if (H5I_register_type(H5I_GROUP_CLS) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to initialize interface") - /* Mark "top" of interface as initialized, too */ - H5G_top_package_initialize_s = TRUE; - done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5G__init_package() */ +} /* end H5G_init() */ /*------------------------------------------------------------------------- * Function: H5G_top_term_package @@ -200,16 +159,10 @@ H5G_top_term_package(void) FUNC_ENTER_NOAPI_NOINIT_NOERR - if (H5G_top_package_initialize_s) { - if (H5I_nmembers(H5I_GROUP) > 0) { - (void)H5I_clear_type(H5I_GROUP, FALSE, FALSE); - n++; /*H5I*/ - } /* end if */ - - /* Mark closed */ - if (0 == n) - H5G_top_package_initialize_s = FALSE; - } /* end if */ + if (H5I_nmembers(H5I_GROUP) > 0) { + (void)H5I_clear_type(H5I_GROUP, FALSE, FALSE); + n++; + } FUNC_LEAVE_NOAPI(n) } /* end H5G_top_term_package() */ @@ -238,18 +191,11 @@ H5G_term_package(void) FUNC_ENTER_NOAPI_NOINIT_NOERR - if (H5_PKG_INIT_VAR) { - /* Sanity checks */ - HDassert(0 == H5I_nmembers(H5I_GROUP)); - HDassert(FALSE == H5G_top_package_initialize_s); - - /* Destroy the group object id group */ - n += (H5I_dec_type_ref(H5I_GROUP) > 0); + /* Sanity checks */ + HDassert(0 == H5I_nmembers(H5I_GROUP)); - /* Mark closed */ - if (0 == n) - H5_PKG_INIT_VAR = FALSE; - } /* end if */ + /* Destroy the group object id group */ + n += (H5I_dec_type_ref(H5I_GROUP) > 0); FUNC_LEAVE_NOAPI(n) } /* end H5G_term_package() */ diff --git a/src/H5Gnode.c b/src/H5Gnode.c index ba29b78..d73888e 100644 --- a/src/H5Gnode.c +++ b/src/H5Gnode.c @@ -1210,7 +1210,7 @@ H5G__node_copy(H5F_t *f, const void H5_ATTR_UNUSED *_lt_key, haddr_t addr, const &(sn->entry[i]); /* Convenience variable to refer to current source group entry */ H5O_link_t lnk; /* Link to insert */ const char * name; /* Name of source object */ - H5G_entry_t tmp_src_ent; /* Temperary copy. Change will not affect the cache */ + H5G_entry_t tmp_src_ent; /* Temporary copy. Change will not affect the cache */ H5O_type_t obj_type = H5O_TYPE_UNKNOWN; /* Target object type */ H5G_copy_file_ud_t *cpy_udata; /* Copy file udata */ H5G_obj_create_t gcrt_info; /* Group creation info */ diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h index 4cf4623..d1725f6 100644 --- a/src/H5Gprivate.h +++ b/src/H5Gprivate.h @@ -130,7 +130,7 @@ typedef enum { typedef int H5G_own_loc_t; /* Structure to store information about the name an object was opened with */ -typedef struct { +typedef struct H5G_name_t { H5RS_str_t *full_path_r; /* Path to object, as seen from root of current file mounting hierarchy */ H5RS_str_t *user_path_r; /* Path to object, as opened by user */ unsigned obj_hidden; /* Whether the object is visible in group hier. */ diff --git a/src/H5Gpublic.h b/src/H5Gpublic.h index d9c29f6..ce36b84 100644 --- a/src/H5Gpublic.h +++ b/src/H5Gpublic.h @@ -1113,7 +1113,7 @@ H5_DLL herr_t H5Gget_objinfo(hid_t loc_id, const char *name, hbool_t follow_link * actual object name length, the object name is truncated to * \Code{max_size - 1} characters. * - * Note that if the size of the object's name is unkown, a preliminary + * Note that if the size of the object's name is unknown, a preliminary * call to H5Gget_objname_by_idx() with \p name set to \c NULL will * return the length of the object's name. A second call to * H5Gget_objname_by_idx() can then be used to retrieve the actual @@ -63,9 +63,6 @@ /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /*****************************/ /* Library Private Variables */ /*****************************/ @@ -117,8 +114,14 @@ H5HF__op_write(const void *obj, size_t obj_len, void *op_data) { FUNC_ENTER_PACKAGE_NOERR - /* Perform "write", using memcpy() */ - H5MM_memcpy((void *)obj, op_data, obj_len); /* Casting away const OK -QAK */ + /* Perform "write", using memcpy() + * + * We cast away const here because no obj pointer that was originally + * const should ever arrive here. + */ + H5_GCC_CLANG_DIAG_OFF("cast-qual") + H5MM_memcpy((void *)obj, op_data, obj_len); + H5_GCC_CLANG_DIAG_ON("cast-qual") FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5HF__op_write() */ @@ -350,10 +353,15 @@ H5HF_insert(H5HF_t *fh, size_t size, const void *obj, void *id /*out*/) /* Check for 'huge' object */ if (size > hdr->max_man_size) { - /* Store 'huge' object in heap */ - /* (Casting away const OK - QAK) */ + /* Store 'huge' object in heap + * + * Although not ideal, we can quiet the const warning here because no + * obj pointer that was originally const should ever arrive here. + */ + H5_GCC_CLANG_DIAG_OFF("cast-qual") if (H5HF__huge_insert(hdr, size, (void *)obj, id) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "can't store 'huge' object in fractal heap") + H5_GCC_CLANG_DIAG_ON("cast-qual") } /* end if */ /* Check for 'tiny' object */ else if (size <= hdr->tiny_max_len) { diff --git a/src/H5HFcache.c b/src/H5HFcache.c index fde5a4f..22ad09b 100644 --- a/src/H5HFcache.c +++ b/src/H5HFcache.c @@ -796,7 +796,7 @@ H5HF__cache_hdr_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_NDEBUG_UN /* Encode I/O filter information */ if (H5O_msg_encode(hdr->f, H5O_PLINE_ID, FALSE, image, &(hdr->pline)) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTENCODE, FAIL, "can't encode I/O pipeline fiters") + HGOTO_ERROR(H5E_HEAP, H5E_CANTENCODE, FAIL, "can't encode I/O pipeline filters") image += hdr->filter_len; } /* end if */ @@ -895,7 +895,7 @@ H5HF__cache_iblock_get_initial_load_size(void *_udata, size_t *image_len) * Function: H5HF__cache_iblock_verify_chksum * * Purpose: Verify the computed checksum of the data structure is the - * same as the stored chksum. + * same as the stored checksum. * * Return: Success: TRUE/FALSE * Failure: Negative @@ -1655,9 +1655,15 @@ H5HF__cache_dblock_verify_chksum(const void *_image, size_t len, void *_udata) /* Update info about direct block */ udata->decompressed = TRUE; len = nbytes; - } /* end if */ - else - read_buf = (void *)image; /* Casting away const OK - QAK */ + } + else { + /* If the data are unfiltered, we just point to the image, which we + * never modify. Casting away const is okay here. + */ + H5_GCC_CLANG_DIAG_OFF("cast-qual") + read_buf = (void *)image; + H5_GCC_CLANG_DIAG_OFF("cast-qual") + } /* Decode checksum */ chk_size = (size_t)(H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr) - H5HF_SIZEOF_CHKSUM); diff --git a/src/H5HFdbg.c b/src/H5HFdbg.c index 8dbb3f4..d38ae20 100644 --- a/src/H5HFdbg.c +++ b/src/H5HFdbg.c @@ -50,7 +50,7 @@ /* User data for direct block debugging iterator callback */ typedef struct { FILE * stream; /* Stream for output */ - int indent; /* Indention amount */ + int indent; /* Indentation amount */ int fwidth; /* Field width mount */ haddr_t dblock_addr; /* Direct block's address */ hsize_t dblock_size; /* Direct block's size */ @@ -63,7 +63,7 @@ typedef struct { typedef struct { H5FS_t *fspace; /* Free space manager */ FILE * stream; /* Stream for output */ - int indent; /* Indention amount */ + int indent; /* Indentation amount */ int fwidth; /* Field width mount */ } H5HF_debug_iter_ud2_t; diff --git a/src/H5HFdblock.c b/src/H5HFdblock.c index 4adb47a..749b973 100644 --- a/src/H5HFdblock.c +++ b/src/H5HFdblock.c @@ -432,7 +432,7 @@ H5HF__man_dblock_protect(H5HF_hdr_t *hdr, haddr_t dblock_addr, size_t dblock_siz H5HF_indirect_t *par_iblock, unsigned par_entry, unsigned flags) { H5HF_direct_t * dblock; /* Direct block from cache */ - H5HF_dblock_cache_ud_t udata; /* parent and other infor for deserializing direct block */ + H5HF_dblock_cache_ud_t udata; /* parent and other info for deserializing direct block */ H5HF_direct_t * ret_value = NULL; /* Return value */ FUNC_ENTER_PACKAGE diff --git a/src/H5HFman.c b/src/H5HFman.c index 427be00..a362d99 100644 --- a/src/H5HFman.c +++ b/src/H5HFman.c @@ -487,10 +487,16 @@ H5HF__man_write(H5HF_hdr_t *hdr, const uint8_t *id, const void *obj) HDassert(id); HDassert(obj); - /* Call the internal 'op' routine routine */ - /* (Casting away const OK - QAK) */ + /* Call the internal 'op' routine routine + * + * In this case, the callback operation needs to modify the obj buffer that + * was passed in as const. We quiet the warning here because an obj pointer + * that was originally const should *never* arrive here. + */ + H5_GCC_CLANG_DIAG_OFF("cast-qual") if (H5HF__man_op_real(hdr, id, H5HF__op_write, (void *)obj, H5HF_OP_MODIFY) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "unable to operate on heap object") + H5_GCC_CLANG_DIAG_ON("cast-qual") done: FUNC_LEAVE_NOAPI(ret_value) diff --git a/src/H5HFspace.c b/src/H5HFspace.c index d62267c..67f9b6f 100644 --- a/src/H5HFspace.c +++ b/src/H5HFspace.c @@ -383,7 +383,7 @@ H5HF__space_create_root(const H5HF_hdr_t *hdr, H5HF_indirect_t *root_iblock) /* Only need to scan the sections if the free space has been initialized */ if (hdr->fspace) - /* Iterate over all sections, seting the parent pointers in 'single' sections to the new indirect + /* Iterate over all sections, setting the parent pointers in 'single' sections to the new indirect * block */ if (H5FS_sect_iterate(hdr->f, hdr->fspace, H5HF__space_create_root_cb, root_iblock) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_BADITER, FAIL, "can't iterate over sections to set parent pointers") @@ -84,9 +84,6 @@ static size_t H5HG__alloc(H5F_t *f, H5HG_heap_t *heap, size_t size, unsigned *h /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /* Declare a free list to manage the H5HG_heap_t struct */ H5FL_DEFINE(H5HG_heap_t); diff --git a/src/H5HGprivate.h b/src/H5HGprivate.h index d8e6b46..5deae88 100644 --- a/src/H5HGprivate.h +++ b/src/H5HGprivate.h @@ -50,7 +50,7 @@ typedef struct H5HG_heap_t H5HG_heap_t; /* Size of encoded global heap ID */ /* (size of file address + 32-bit integer) */ -#define H5HG_HEAP_ID_SIZE(F) ((size_t)H5F_SIZEOF_ADDR(F) + H5_SIZEOF_UINT32_T) +#define H5HG_HEAP_ID_SIZE(F) ((size_t)H5F_SIZEOF_ADDR(F) + sizeof(uint32_t)) /* Main global heap routines */ H5_DLL herr_t H5HG_insert(H5F_t *f, size_t size, const void *obj, H5HG_t *hobj /*out*/); @@ -64,9 +64,6 @@ static herr_t H5HL__dirty(H5HL_t *heap); /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /* Declare a free list to manage the H5HL_free_t struct */ H5FL_DEFINE(H5HL_free_t); diff --git a/src/H5HP.c b/src/H5HP.c deleted file mode 100644 index d164223..0000000 --- a/src/H5HP.c +++ /dev/null @@ -1,904 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * 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 COPYING file, which can be found at the root of the source code * - * distribution tree, or in https://www.hdfgroup.org/licenses. * - * If you do not have access to either file, you may request a copy from * - * help@hdfgroup.org. * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/* - * Purpose: Provides a heap abstract data type. - * - * (See chapter 11 - "Priority Queues" of _Algorithms_, by - * Sedgewick for additional information) - * - */ - -/* Private headers needed */ -#include "H5private.h" /* Generic Functions */ -#include "H5Eprivate.h" /* Error handling */ -#include "H5HPprivate.h" /* Heap routines */ -#include "H5FLprivate.h" /* Memory management functions */ - -/* Local Macros */ -#define H5HP_START_SIZE 16 /* Initial number of entries for heaps */ - -/* Private typedefs & structs */ - -/* Data structure for entries in the internal heap array */ -typedef struct { - int val; /* Value to be used for heap condition */ - H5HP_info_t *obj; /* Pointer to object stored in heap */ -} H5HP_ent_t; - -/* Main heap data structure */ -struct H5HP_t { - H5HP_type_t type; /* Type of heap (minimum or maximum value at "top") */ - size_t nobjs; /* Number of active objects in heap array */ - size_t nalloc; /* Number of allocated locations in heap array */ - H5HP_ent_t *heap; /* Pointer to array containing heap entries */ -}; - -/* Static functions */ -static herr_t H5HP__swim_max(H5HP_t *heap, size_t loc); -static herr_t H5HP__swim_min(H5HP_t *heap, size_t loc); -static herr_t H5HP__sink_max(H5HP_t *heap, size_t loc); -static herr_t H5HP__sink_min(H5HP_t *heap, size_t loc); - -/* Declare a free list to manage the H5HP_t struct */ -H5FL_DEFINE_STATIC(H5HP_t); - -/* Declare a free list to manage sequences of H5HP_ent_t */ -H5FL_SEQ_DEFINE_STATIC(H5HP_ent_t); - -/*-------------------------------------------------------------------------- - NAME - H5HP__swim_max - PURPOSE - Restore heap condition by moving an object upward - USAGE - herr_t H5HP__swim_max(heap, loc) - H5HP_t *heap; IN/OUT: Pointer to heap to modify - size_t loc; IN: Location to start from - - RETURNS - Returns non-negative on success, negative on failure. - DESCRIPTION - Restore the heap condition for the heap's array by "swimming" the object - at a location upward. - GLOBAL VARIABLES - COMMENTS, BUGS, ASSUMPTIONS - This routine is for "maximum" value heaps. - EXAMPLES - REVISION LOG ---------------------------------------------------------------------------*/ -static herr_t -H5HP__swim_max(H5HP_t *heap, size_t loc) -{ - int val; /* Temporary copy value of object to move in heap */ - H5HP_info_t *obj; /* Temporary pointer to object to move in heap */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_STATIC_NOERR - - /* Get copies of the information about the object to move in the heap */ - val = heap->heap[loc].val; - obj = heap->heap[loc].obj; - - /* Move object up in heap until it's reached the maximum location possible */ - while (heap->heap[loc / 2].val < val) { - /* Move object "above" current location in heap down */ - heap->heap[loc].val = heap->heap[loc / 2].val; - heap->heap[loc].obj = heap->heap[loc / 2].obj; - - /* Update heap location for object which moved */ - heap->heap[loc].obj->heap_loc = loc; - - /* Move to location "above" current location */ - loc = loc / 2; - } /* end while */ - - /* Put object into heap at correct location */ - heap->heap[loc].val = val; - heap->heap[loc].obj = obj; - - /* Update heap location for object */ - heap->heap[loc].obj->heap_loc = loc; - - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5HP__swim_max() */ - -/*-------------------------------------------------------------------------- - NAME - H5HP__swim_min - PURPOSE - Restore heap condition by moving an object upward - USAGE - herr_t H5HP__swim_min(heap, loc) - H5HP_t *heap; IN/OUT: Pointer to heap to modify - size_t loc; IN: Location to start from - - RETURNS - Returns non-negative on success, negative on failure. - DESCRIPTION - Restore the heap condition for the heap's array by "swimming" the object - at a location upward. - GLOBAL VARIABLES - COMMENTS, BUGS, ASSUMPTIONS - This routine is for "minimum" value heaps. - EXAMPLES - REVISION LOG ---------------------------------------------------------------------------*/ -static herr_t -H5HP__swim_min(H5HP_t *heap, size_t loc) -{ - int val; /* Temporary copy value of object to move in heap */ - H5HP_info_t *obj; /* Temporary pointer to object to move in heap */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_STATIC_NOERR - - /* Get copies of the information about the object to move in the heap */ - val = heap->heap[loc].val; - obj = heap->heap[loc].obj; - - /* Move object up in heap until it's reached the minimum location possible */ - while (heap->heap[loc / 2].val > val) { - /* Move object "above" current location in heap down */ - heap->heap[loc].val = heap->heap[loc / 2].val; - heap->heap[loc].obj = heap->heap[loc / 2].obj; - - /* Update heap location for object which moved */ - heap->heap[loc].obj->heap_loc = loc; - - /* Move to location "above" current location */ - loc = loc / 2; - } /* end while */ - - /* Put object into heap at correct location */ - heap->heap[loc].val = val; - heap->heap[loc].obj = obj; - - /* Update heap location for object */ - heap->heap[loc].obj->heap_loc = loc; - - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5HP__swim_min() */ - -/*-------------------------------------------------------------------------- - NAME - H5HP__sink_max - PURPOSE - Restore heap condition by moving an object downward - USAGE - herr_t H5HP__sink_max(heap, loc) - H5HP_t *heap; IN/OUT: Pointer to heap to modify - size_t loc; IN: Location to start from - - RETURNS - Returns non-negative on success, negative on failure. - DESCRIPTION - Restore the heap condition for the heap's array by "sinking" the object - at a location downward. - GLOBAL VARIABLES - COMMENTS, BUGS, ASSUMPTIONS - This routine is for "maximum" value heaps. - EXAMPLES - REVISION LOG ---------------------------------------------------------------------------*/ -static herr_t -H5HP__sink_max(H5HP_t *heap, size_t loc) -{ - int val; /* Temporary copy value of object to move in heap */ - void * obj; /* Temporary pointer to object to move in heap */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_STATIC_NOERR - - /* Get copies of the information about the object to move in the heap */ - val = heap->heap[loc].val; - obj = heap->heap[loc].obj; - - /* Move object up in heap until it's reached the maximum location possible */ - while ((2 * loc) <= heap->nobjs) { - size_t new_loc = loc * 2; /* New object's potential location area */ - - /* Get the greater of the two objects below the location in heap */ - if (new_loc < heap->nobjs && (heap->heap[new_loc].val < heap->heap[new_loc + 1].val)) - new_loc++; - - /* Check if the object is smaller than the larger of the objects below it */ - /* If so, its in the correct location now, and we can get out */ - if (val >= heap->heap[new_loc].val) - break; - - /* Move the greater of the two objects below the current location up */ - heap->heap[loc].val = heap->heap[new_loc].val; - heap->heap[loc].obj = heap->heap[new_loc].obj; - - /* Update heap location for object which moved */ - heap->heap[loc].obj->heap_loc = loc; - - /* Move to location "below" current location */ - loc = new_loc; - } /* end while */ - - /* Put object into heap at correct location */ - heap->heap[loc].val = val; - heap->heap[loc].obj = (H5HP_info_t *)obj; - - /* Update heap location for object */ - heap->heap[loc].obj->heap_loc = loc; - - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5HP__sink_max() */ - -/*-------------------------------------------------------------------------- - NAME - H5HP__sink_min - PURPOSE - Restore heap condition by moving an object downward - USAGE - herr_t H5HP__sink_min(heap, loc) - H5HP_t *heap; IN/OUT: Pointer to heap to modify - size_t loc; IN: Location to start from - - RETURNS - Returns non-negative on success, negative on failure. - DESCRIPTION - Restore the heap condition for the heap's array by "sinking" the object - at a location downward. - GLOBAL VARIABLES - COMMENTS, BUGS, ASSUMPTIONS - This routine is for "minimum" value heaps. - EXAMPLES - REVISION LOG ---------------------------------------------------------------------------*/ -static herr_t -H5HP__sink_min(H5HP_t *heap, size_t loc) -{ - int val; /* Temporary copy value of object to move in heap */ - void * obj; /* Temporary pointer to object to move in heap */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_STATIC_NOERR - - /* Get copies of the information about the object to move in the heap */ - val = heap->heap[loc].val; - obj = heap->heap[loc].obj; - - /* Move object up in heap until it's reached the maximum location possible */ - while ((2 * loc) <= heap->nobjs) { - size_t new_loc = loc * 2; /* New object's potential location area */ - - /* Get the lesser of the two objects below the location in heap */ - if (new_loc < heap->nobjs && (heap->heap[new_loc].val > heap->heap[new_loc + 1].val)) - new_loc++; - - /* Check if the object is greater than the larger of the objects below it */ - /* If so, its in the correct location now, and we can get out */ - if (val <= heap->heap[new_loc].val) - break; - - /* Move the greater of the two objects below the current location up */ - heap->heap[loc].val = heap->heap[new_loc].val; - heap->heap[loc].obj = heap->heap[new_loc].obj; - - /* Update heap location for object which moved */ - heap->heap[loc].obj->heap_loc = loc; - - /* Move to location "below" current location */ - loc = new_loc; - } /* end while */ - - /* Put object into heap at correct location */ - heap->heap[loc].val = val; - heap->heap[loc].obj = (H5HP_info_t *)obj; - - /* Update heap location for object */ - heap->heap[loc].obj->heap_loc = loc; - - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5HP__sink_min() */ - -/*-------------------------------------------------------------------------- - NAME - H5HP_create - PURPOSE - Create a heap - USAGE - H5HP_t *H5HP_create(heap_type) - H5HP_type_t heap_type; IN: Type of heap to create - - RETURNS - Returns a pointer to a heap on success, NULL on failure. - DESCRIPTION - Create a priority queue. The SIZE is used to set the initial number of - entries allocated. - GLOBAL VARIABLES - COMMENTS, BUGS, ASSUMPTIONS - EXAMPLES - REVISION LOG ---------------------------------------------------------------------------*/ -H5HP_t * -H5HP_create(H5HP_type_t heap_type) -{ - H5HP_t *new_heap = NULL; /* Pointer to new heap object created */ - H5HP_t *ret_value; /* Return value */ - - FUNC_ENTER_NOAPI(NULL) - - /* Check args */ - HDassert(heap_type == H5HP_MIN_HEAP || heap_type == H5HP_MAX_HEAP); - - /* Allocate ref-counted string structure */ - if ((new_heap = H5FL_MALLOC(H5HP_t)) == NULL) - HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, NULL, "memory allocation failed"); - - /* Allocate the array to store the heap entries */ - if ((new_heap->heap = H5FL_SEQ_MALLOC(H5HP_ent_t, (size_t)(H5HP_START_SIZE + 1))) == NULL) - HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, NULL, "memory allocation failed"); - - /* Set the internal fields */ - new_heap->type = heap_type; - new_heap->nobjs = 0; - new_heap->nalloc = H5HP_START_SIZE + 1; - - /* Set the information in the 0'th location based on the type of heap */ - if (heap_type == H5HP_MIN_HEAP) { - /* Set the value in the '0' location to be the minimum value, to - * simplify the algorithms - */ - new_heap->heap[0].val = INT_MIN; - new_heap->heap[0].obj = NULL; - } /* end if */ - else { - /* Set the value in the '0' location to be the maximum value, to - * simplify the algorithms - */ - new_heap->heap[0].val = INT_MAX; - new_heap->heap[0].obj = NULL; - } /* end else */ - - /* Set the return value */ - ret_value = new_heap; - -done: - /* Error cleanup */ - if (NULL == ret_value) { - if (NULL != new_heap) { - if (NULL != new_heap->heap) - new_heap->heap = H5FL_SEQ_FREE(H5HP_ent_t, new_heap->heap); - new_heap = H5FL_FREE(H5HP_t, new_heap); - } /* end if */ - } /* end if */ - - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5HP_create() */ - -/*-------------------------------------------------------------------------- - NAME - H5HP_count - PURPOSE - Check the number of elements in a heap - USAGE - ssize_t H5HP_count(heap) - const H5HP_t *heap; IN: Pointer to heap to query - - RETURNS - Returns non-negative on success, negative on failure. - DESCRIPTION - Checks the number of elements in heap - GLOBAL VARIABLES - COMMENTS, BUGS, ASSUMPTIONS - EXAMPLES - REVISION LOG ---------------------------------------------------------------------------*/ -ssize_t -H5HP_count(const H5HP_t *heap) -{ - ssize_t ret_value; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT_NOERR - - /* Check args */ - HDassert(heap); - - /* Check internal consistency */ - /* (Pre-condition) */ - HDassert(heap->nobjs < heap->nalloc); - HDassert(heap->heap); - HDassert((heap->type == H5HP_MAX_HEAP && heap->heap[0].val == INT_MAX) || - (heap->type == H5HP_MIN_HEAP && heap->heap[0].val == INT_MIN)); - HDassert(heap->heap[0].obj == NULL); - - /* Return the number of objects in the heap */ - H5_CHECK_OVERFLOW(heap->nobjs, size_t, ssize_t); - ret_value = (ssize_t)heap->nobjs; - - /* No post-condition check necessary, since heap is constant */ - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5HP_count() */ - -/*-------------------------------------------------------------------------- - NAME - H5HP_insert - PURPOSE - Insert an object into a heap, with an initial value - USAGE - herr_t H5HP_insert(heap, val, obj) - H5HP_t *heap; IN/OUT: Pointer to heap to modify - int val; IN: Initial value for object in heap - void *obj; IN: Pointer to object to insert into heap - - RETURNS - Returns non-negative on success, negative on failure. - DESCRIPTION - Inserts a OBJ into a HEAP, with an initial VALue. - GLOBAL VARIABLES - COMMENTS, BUGS, ASSUMPTIONS - EXAMPLES - REVISION LOG ---------------------------------------------------------------------------*/ -herr_t -H5HP_insert(H5HP_t *heap, int val, void *obj) -{ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(FAIL) - - /* Check args */ - HDassert(heap); - HDassert(obj); - - /* Check internal consistency */ - /* (Pre-condition) */ - HDassert(heap->nobjs < heap->nalloc); - HDassert(heap->heap); - HDassert((heap->type == H5HP_MAX_HEAP && heap->heap[0].val == INT_MAX) || - (heap->type == H5HP_MIN_HEAP && heap->heap[0].val == INT_MIN)); - HDassert(heap->heap[0].obj == NULL); - - /* Increment number of objects in heap */ - heap->nobjs++; - - /* Check if we need to allocate more room for heap array */ - if (heap->nobjs >= heap->nalloc) { - size_t n = MAX(H5HP_START_SIZE, 2 * (heap->nalloc - 1)) + 1; - H5HP_ent_t *new_heap = H5FL_SEQ_REALLOC(H5HP_ent_t, heap->heap, n); - - if (!new_heap) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to extend heap array"); - heap->heap = new_heap; - heap->nalloc = n; - } /* end if */ - - /* Insert new object at end of heap */ - heap->heap[heap->nobjs].val = val; - heap->heap[heap->nobjs].obj = (H5HP_info_t *)obj; - heap->heap[heap->nobjs].obj->heap_loc = heap->nobjs; - - /* Restore heap condition */ - if (heap->type == H5HP_MAX_HEAP) { - if (H5HP__swim_max(heap, heap->nobjs) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "unable to restore heap condition"); - } /* end if */ - else { - if (H5HP__swim_min(heap, heap->nobjs) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "unable to restore heap condition"); - } /* end else */ - -done: - - /* Check internal consistency */ - /* (Post-condition) */ - HDassert(heap->nobjs < heap->nalloc); - HDassert(heap->heap); - HDassert((heap->type == H5HP_MAX_HEAP && heap->heap[0].val == INT_MAX) || - (heap->type == H5HP_MIN_HEAP && heap->heap[0].val == INT_MIN)); - HDassert(heap->heap[0].obj == NULL); - - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5HP_insert() */ - -/*-------------------------------------------------------------------------- - NAME - H5HP_top - PURPOSE - Check the value of the top object in the heap - USAGE - herr_t H5HP_top(heap, val) - const H5HP_t *heap; IN: Pointer to heap to modify - int val; IN/OUT: Initial value for object in heap - - RETURNS - Returns non-negative on success, negative on failure. - DESCRIPTION - Checks the value of the top object in a heap - GLOBAL VARIABLES - COMMENTS, BUGS, ASSUMPTIONS - EXAMPLES - REVISION LOG ---------------------------------------------------------------------------*/ -herr_t -H5HP_top(const H5HP_t *heap, int *val) -{ - FUNC_ENTER_NOAPI_NOINIT_NOERR - - /* Check args */ - HDassert(heap); - HDassert(val); - - /* Check internal consistency */ - /* (Pre-condition) */ - HDassert(heap->nobjs < heap->nalloc); - HDassert(heap->heap); - HDassert((heap->type == H5HP_MAX_HEAP && heap->heap[0].val == INT_MAX) || - (heap->type == H5HP_MIN_HEAP && heap->heap[0].val == INT_MIN)); - HDassert(heap->heap[0].obj == NULL); - - /* Get value of the top object in the heap */ - *val = heap->heap[1].val; - - /* No post-condition check necessary, since heap is constant */ - FUNC_LEAVE_NOAPI(SUCCEED); -} /* end H5HP_top() */ - -/*-------------------------------------------------------------------------- - NAME - H5HP_remove - PURPOSE - Remove an object into a heap - USAGE - herr_t H5HP_remove(heap, val, obj) - H5HP_t *heap; IN/OUT: Pointer to heap to modify - int *val; OUT: Pointer to value of object removed from heap - void **obj; OUT: Pointer to object removed from heap - - RETURNS - Returns non-negative on success, negative on failure. - DESCRIPTION - Removes the top object on a heap, returning its value and object pointer - GLOBAL VARIABLES - COMMENTS, BUGS, ASSUMPTIONS - EXAMPLES - REVISION LOG ---------------------------------------------------------------------------*/ -herr_t -H5HP_remove(H5HP_t *heap, int *val, void **obj) -{ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(FAIL) - - /* Check args */ - HDassert(heap); - HDassert(val); - HDassert(obj); - - /* Check internal consistency */ - /* (Pre-condition) */ - HDassert(heap->nobjs < heap->nalloc); - HDassert(heap->heap); - HDassert((heap->type == H5HP_MAX_HEAP && heap->heap[0].val == INT_MAX) || - (heap->type == H5HP_MIN_HEAP && heap->heap[0].val == INT_MIN)); - HDassert(heap->heap[0].obj == NULL); - - /* Check if there are any objects on the heap to remove */ - if (heap->nobjs == 0) - HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "heap is empty"); - - /* Get the information for the top object on the heap */ - HDassert(heap->heap[1].obj->heap_loc == 1); - *val = heap->heap[1].val; - *obj = heap->heap[1].obj; - - /* Move the last element in the heap to the top */ - heap->heap[1].val = heap->heap[heap->nobjs].val; - heap->heap[1].obj = heap->heap[heap->nobjs].obj; - heap->heap[1].obj->heap_loc = 1; - - /* Decrement number of objects in heap */ - heap->nobjs--; - - /* Restore heap condition, if there are objects on the heap */ - if (heap->nobjs > 0) { - if (heap->type == H5HP_MAX_HEAP) { - if (H5HP__sink_max(heap, (size_t)1) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDELETE, FAIL, "unable to restore heap condition"); - } /* end if */ - else { - if (H5HP__sink_min(heap, (size_t)1) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDELETE, FAIL, "unable to restore heap condition"); - } /* end else */ - } /* end if */ - -done: - - /* Check internal consistency */ - /* (Post-condition) */ - HDassert(heap->nobjs < heap->nalloc); - HDassert(heap->heap); - HDassert((heap->type == H5HP_MAX_HEAP && heap->heap[0].val == INT_MAX) || - (heap->type == H5HP_MIN_HEAP && heap->heap[0].val == INT_MIN)); - HDassert(heap->heap[0].obj == NULL); - - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5HP_remove() */ - -/*-------------------------------------------------------------------------- - NAME - H5HP_change - PURPOSE - Change the priority of an object on a heap - USAGE - herr_t H5HP_change(heap, val, obj) - H5HP_t *heap; IN/OUT: Pointer to heap to modify - int val; IN: New priority value for object - void *obj; IN: Pointer to object to modify - - RETURNS - Returns non-negative on success, negative on failure. - DESCRIPTION - Changes the priority of an object on a heap. - GLOBAL VARIABLES - COMMENTS, BUGS, ASSUMPTIONS - EXAMPLES - REVISION LOG ---------------------------------------------------------------------------*/ -herr_t -H5HP_change(H5HP_t *heap, int val, void *_obj) -{ - H5HP_info_t *obj = (H5HP_info_t *)_obj; /* Alias for object */ - size_t obj_loc; /* Location of object in heap */ - int old_val; /* Object's old priority value */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(FAIL) - - /* Check args */ - HDassert(heap); - HDassert(obj); - - /* Check internal consistency */ - /* (Pre-condition) */ - HDassert(heap->nobjs < heap->nalloc); - HDassert(heap->heap); - HDassert((heap->type == H5HP_MAX_HEAP && heap->heap[0].val == INT_MAX) || - (heap->type == H5HP_MIN_HEAP && heap->heap[0].val == INT_MIN)); - HDassert(heap->heap[0].obj == NULL); - - /* Get the location of the object in the heap */ - obj_loc = obj->heap_loc; - HDassert(obj_loc > 0 && obj_loc <= heap->nobjs); - - /* Change the heap object's priority */ - old_val = heap->heap[obj_loc].val; - heap->heap[obj_loc].val = val; - - /* Restore heap condition */ - if (val < old_val) { - if (heap->type == H5HP_MAX_HEAP) { - if (H5HP__sink_max(heap, obj_loc) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTRESTORE, FAIL, "unable to restore heap condition"); - } /* end if */ - else { - if (H5HP__swim_min(heap, obj_loc) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTRESTORE, FAIL, "unable to restore heap condition"); - } /* end else */ - } /* end if */ - else { - if (heap->type == H5HP_MAX_HEAP) { - if (H5HP__swim_max(heap, obj_loc) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTRESTORE, FAIL, "unable to restore heap condition"); - } /* end if */ - else { - if (H5HP__sink_min(heap, obj_loc) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTRESTORE, FAIL, "unable to restore heap condition"); - } /* end else */ - } /* end else */ - -done: - - /* Check internal consistency */ - /* (Post-condition) */ - HDassert(heap->nobjs < heap->nalloc); - HDassert(heap->heap); - HDassert((heap->type == H5HP_MAX_HEAP && heap->heap[0].val == INT_MAX) || - (heap->type == H5HP_MIN_HEAP && heap->heap[0].val == INT_MIN)); - HDassert(heap->heap[0].obj == NULL); - - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5HP_change() */ - -/*-------------------------------------------------------------------------- - NAME - H5HP_incr - PURPOSE - Increment the priority of an object on a heap - USAGE - herr_t H5HP_incr(heap, amt, obj) - H5HP_t *heap; IN/OUT: Pointer to heap to modify - unsigned amt; IN: Amount to increase priority by - void *obj; IN: Pointer to object to modify - - RETURNS - Returns non-negative on success, negative on failure. - DESCRIPTION - Increments the priority of an object on a heap by one. - GLOBAL VARIABLES - COMMENTS, BUGS, ASSUMPTIONS - EXAMPLES - REVISION LOG ---------------------------------------------------------------------------*/ -herr_t -H5HP_incr(H5HP_t *heap, unsigned amt, void *_obj) -{ - H5HP_info_t *obj = (H5HP_info_t *)_obj; /* Alias for object */ - size_t obj_loc; /* Location of object in heap */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(FAIL) - - /* Check args */ - HDassert(heap); - HDassert(obj); - - /* Check internal consistency */ - /* (Pre-condition) */ - HDassert(heap->nobjs < heap->nalloc); - HDassert(heap->heap); - HDassert((heap->type == H5HP_MAX_HEAP && heap->heap[0].val == INT_MAX) || - (heap->type == H5HP_MIN_HEAP && heap->heap[0].val == INT_MIN)); - HDassert(heap->heap[0].obj == NULL); - - /* Get the location of the object in the heap */ - obj_loc = obj->heap_loc; - HDassert(obj_loc > 0 && obj_loc <= heap->nobjs); - - /* Change the heap object's priority */ - heap->heap[obj_loc].val += (int)amt; - - /* Restore heap condition */ - if (H5HP_MAX_HEAP == heap->type) { - if (H5HP__swim_max(heap, obj_loc) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTRESTORE, FAIL, "unable to restore heap condition") - } /* end if */ - else { - if (H5HP__sink_min(heap, obj_loc) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTRESTORE, FAIL, "unable to restore heap condition") - } /* end else */ - -done: - - /* Check internal consistency */ - /* (Post-condition) */ - HDassert(heap->nobjs < heap->nalloc); - HDassert(heap->heap); - HDassert((heap->type == H5HP_MAX_HEAP && heap->heap[0].val == INT_MAX) || - (heap->type == H5HP_MIN_HEAP && heap->heap[0].val == INT_MIN)); - HDassert(heap->heap[0].obj == NULL); - - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5HP_incr() */ - -/*-------------------------------------------------------------------------- - NAME - H5HP_decr - PURPOSE - Decrement the priority of an object on a heap - USAGE - herr_t H5HP_dec(heap, amt, obj) - H5HP_t *heap; IN/OUT: Pointer to heap to modify - unsigned amt; IN: Amount to decrease priority by - void *obj; IN: Pointer to object to modify - - RETURNS - Returns non-negative on success, negative on failure. - DESCRIPTION - Decrements the priority of an object on a heap by one. - GLOBAL VARIABLES - COMMENTS, BUGS, ASSUMPTIONS - EXAMPLES - REVISION LOG ---------------------------------------------------------------------------*/ -herr_t -H5HP_decr(H5HP_t *heap, unsigned amt, void *_obj) -{ - H5HP_info_t *obj = (H5HP_info_t *)_obj; /* Alias for object */ - size_t obj_loc; /* Location of object in heap */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(FAIL) - - /* Check args */ - HDassert(heap); - HDassert(obj); - - /* Check internal consistency */ - /* (Pre-condition) */ - HDassert(heap->nobjs < heap->nalloc); - HDassert(heap->heap); - HDassert((heap->type == H5HP_MAX_HEAP && heap->heap[0].val == INT_MAX) || - (heap->type == H5HP_MIN_HEAP && heap->heap[0].val == INT_MIN)); - HDassert(heap->heap[0].obj == NULL); - - /* Get the location of the object in the heap */ - obj_loc = obj->heap_loc; - HDassert(obj_loc > 0 && obj_loc <= heap->nobjs); - - /* Change the heap object's priority */ - H5_CHECK_OVERFLOW(amt, unsigned, int); - heap->heap[obj_loc].val -= (int)amt; - - /* Restore heap condition */ - if (heap->type == H5HP_MAX_HEAP) { - if (H5HP__sink_max(heap, obj_loc) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTRESTORE, FAIL, "unable to restore heap condition"); - } /* end if */ - else { - if (H5HP__swim_min(heap, obj_loc) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTRESTORE, FAIL, "unable to restore heap condition"); - } /* end else */ - -done: - - /* Check internal consistency */ - /* (Post-condition) */ - HDassert(heap->nobjs < heap->nalloc); - HDassert(heap->heap); - HDassert((heap->type == H5HP_MAX_HEAP && heap->heap[0].val == INT_MAX) || - (heap->type == H5HP_MIN_HEAP && heap->heap[0].val == INT_MIN)); - HDassert(heap->heap[0].obj == NULL); - - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5HP_decr() */ - -/*-------------------------------------------------------------------------- - NAME - H5HP_close - PURPOSE - Close a heap, deallocating it. - USAGE - herr_t H5HP_close(heap) - H5HP_t *heap; IN/OUT: Pointer to heap to close - - RETURNS - Returns non-negative on success, negative on failure. - DESCRIPTION - Close a heap, freeing all internal information. Any objects left in - the heap are not deallocated. - GLOBAL VARIABLES - COMMENTS, BUGS, ASSUMPTIONS - EXAMPLES - REVISION LOG ---------------------------------------------------------------------------*/ -herr_t -H5HP_close(H5HP_t *heap) -{ - FUNC_ENTER_NOAPI_NOINIT_NOERR - - /* Check args */ - HDassert(heap); - - /* Check internal consistency */ - /* (Pre-condition) */ - HDassert(heap->nobjs < heap->nalloc); - HDassert(heap->heap); - HDassert((heap->type == H5HP_MAX_HEAP && heap->heap[0].val == INT_MAX) || - (heap->type == H5HP_MIN_HEAP && heap->heap[0].val == INT_MIN)); - HDassert(NULL == heap->heap[0].obj); - - /* Free internal structures for heap */ - heap->heap = H5FL_SEQ_FREE(H5HP_ent_t, heap->heap); - - /* Free actual heap object */ - heap = H5FL_FREE(H5HP_t, heap); - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5HP_close() */ diff --git a/src/H5HPprivate.h b/src/H5HPprivate.h deleted file mode 100644 index 50020bc..0000000 --- a/src/H5HPprivate.h +++ /dev/null @@ -1,68 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * 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 COPYING file, which can be found at the root of the source code * - * distribution tree, or in https://www.hdfgroup.org/licenses. * - * If you do not have access to either file, you may request a copy from * - * help@hdfgroup.org. * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/* - * This file contains private information about the H5HP module - */ -#ifndef H5HPprivate_H -#define H5HPprivate_H - -/**************************************/ -/* Public headers needed by this file */ -/**************************************/ -#ifdef LATER -#include "H5HPpublic.h" -#endif /* LATER */ - -/***************************************/ -/* Private headers needed by this file */ -/***************************************/ -#include "H5private.h" - -/************/ -/* Typedefs */ -/************/ - -/* Typedef for heap struct (defined in H5HP.c) */ -typedef struct H5HP_t H5HP_t; - -/* Typedef for objects which can be inserted into heaps */ -/* This _must_ be the first field in objects which can be inserted into heaps */ -typedef struct H5HP_info_t { - size_t heap_loc; /* Location of object in heap */ -} H5HP_info_t; - -/* Typedef for type of heap to create */ -typedef enum { - H5HP_MIN_HEAP, /* Minimum values in heap are at the "top" */ - H5HP_MAX_HEAP /* Maximum values in heap are at the "top" */ -} H5HP_type_t; - -/**********/ -/* Macros */ -/**********/ - -/********************/ -/* Private routines */ -/********************/ -H5_DLL H5HP_t *H5HP_create(H5HP_type_t heap_type); -H5_DLL herr_t H5HP_insert(H5HP_t *heap, int val, void *obj); -H5_DLL ssize_t H5HP_count(const H5HP_t *heap); -H5_DLL herr_t H5HP_top(const H5HP_t *heap, int *val); -H5_DLL herr_t H5HP_remove(H5HP_t *heap, int *val, void **ptr); -H5_DLL herr_t H5HP_change(H5HP_t *heap, int val, void *obj); -H5_DLL herr_t H5HP_incr(H5HP_t *heap, unsigned amt, void *obj); -H5_DLL herr_t H5HP_decr(H5HP_t *heap, unsigned amt, void *obj); -H5_DLL herr_t H5HP_close(H5HP_t *heap); - -#endif /* H5HPprivate_H */ @@ -814,7 +814,7 @@ H5I__iterate_pub_cb(void H5_ATTR_UNUSED *obj, hid_t id, void *_udata) /*------------------------------------------------------------------------- * Function: H5Iiterate * - * Purpose: Call the callback funciton op for each member of the id + * Purpose: Call the callback function op for each member of the id * type type. op takes as parameters the id and a * passthrough of op_data, and returns an herr_t. A positive * return from op will cause the iteration to stop and diff --git a/src/H5Iint.c b/src/H5Iint.c index 86a2810..1ea2ad7 100644 --- a/src/H5Iint.c +++ b/src/H5Iint.c @@ -85,9 +85,6 @@ static int H5I__find_id_cb(void *_item, void *_key, void *_udata); /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /* Declared extern in H5Ipkg.h and documented there */ H5I_type_info_t *H5I_type_info_array_g[H5I_MAX_NUM_TYPES]; int H5I_next_type_g = (int)H5I_NTYPES; @@ -127,30 +124,24 @@ H5I_term_package(void) FUNC_ENTER_NOAPI_NOINIT_NOERR - if (H5_PKG_INIT_VAR) { - H5I_type_info_t *type_info = NULL; /* Pointer to ID type */ - int i; - - /* Count the number of types still in use */ - for (i = 0; i < H5I_next_type_g; i++) - if ((type_info = H5I_type_info_array_g[i]) && type_info->hash_table) + H5I_type_info_t *type_info = NULL; /* Pointer to ID type */ + int i; + + /* Count the number of types still in use */ + for (i = 0; i < H5I_next_type_g; i++) + if ((type_info = H5I_type_info_array_g[i]) && type_info->hash_table) + in_use++; + + /* If no types are still being used then clean up */ + if (0 == in_use) { + for (i = 0; i < H5I_next_type_g; i++) { + type_info = H5I_type_info_array_g[i]; + if (type_info) { + HDassert(NULL == type_info->hash_table); + type_info = H5MM_xfree(type_info); + H5I_type_info_array_g[i] = NULL; in_use++; - - /* If no types are still being used then clean up */ - if (0 == in_use) { - for (i = 0; i < H5I_next_type_g; i++) { - type_info = H5I_type_info_array_g[i]; - if (type_info) { - HDassert(NULL == type_info->hash_table); - type_info = H5MM_xfree(type_info); - H5I_type_info_array_g[i] = NULL; - in_use++; - } } - - /* Mark interface closed */ - if (0 == in_use) - H5_PKG_INIT_VAR = FALSE; } } diff --git a/src/H5Ipublic.h b/src/H5Ipublic.h index 8d4dbf8..d6892bb 100644 --- a/src/H5Ipublic.h +++ b/src/H5Ipublic.h @@ -508,7 +508,7 @@ H5_DLL int H5Idec_type_ref(H5I_type_t type); * * \brief Retrieves the reference count on an ID type * - * \param[in] type The identifier of the type whose reference count is to be retieved + * \param[in] type The identifier of the type whose reference count is to be retrieved * * \return Returns the current reference count on success, negative on failure. * diff --git a/src/H5Lint.c b/src/H5Lint.c index 346c37d..9e45124 100644 --- a/src/H5Lint.c +++ b/src/H5Lint.c @@ -175,9 +175,6 @@ static herr_t H5L__get_name_by_idx_cb(H5G_loc_t *grp_loc /*in*/, const char *nam /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /*****************************/ /* Library Private Variables */ /*****************************/ @@ -211,30 +208,6 @@ H5L_init(void) herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) - /* FUNC_ENTER() does all the work */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5L_init() */ - -/*------------------------------------------------------------------------- - * Function: H5L__init_package - * - * Purpose: Initialize information specific to H5L interface. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: James Laird - * Tuesday, January 24, 2006 - * - *------------------------------------------------------------------------- - */ -herr_t -H5L__init_package(void) -{ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_PACKAGE /* Initialize user-defined link classes */ if (H5L_register_external() < 0) @@ -242,12 +215,12 @@ H5L__init_package(void) done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5L_init_package() */ +} /* end H5L_init() */ /*------------------------------------------------------------------------- * Function: H5L_term_package * - * Purpose: Terminate any resources allocated in H5L__init_package. + * Purpose: Terminate any resources allocated in H5L_init. * * Return: Non-negative on success/Negative on failure * @@ -263,17 +236,11 @@ H5L_term_package(void) FUNC_ENTER_NOAPI_NOINIT_NOERR - if (H5_PKG_INIT_VAR) { - /* Free the table of link types */ - if (H5L_table_g) { - H5L_table_g = (H5L_class_t *)H5MM_xfree(H5L_table_g); - H5L_table_used_g = H5L_table_alloc_g = 0; - n++; - } /* end if */ - - /* Mark the interface as uninitialized */ - if (0 == n) - H5_PKG_INIT_VAR = FALSE; + /* Free the table of link types */ + if (H5L_table_g) { + H5L_table_g = (H5L_class_t *)H5MM_xfree(H5L_table_g); + H5L_table_used_g = H5L_table_alloc_g = 0; + n++; } /* end if */ FUNC_LEAVE_NOAPI(n) diff --git a/src/H5Lpublic.h b/src/H5Lpublic.h index 72b0182..ca5f6e6 100644 --- a/src/H5Lpublic.h +++ b/src/H5Lpublic.h @@ -462,7 +462,7 @@ H5_DLL herr_t H5Ldelete_by_idx_async(const char *app_file, const char *app_func, * * \return \herr_t * - * \details H5Lget_val() returns tha value of link \p name. For smbolic links, + * \details H5Lget_val() returns the value of link \p name. For smbolic links, * this is the path to which the link points, including the null * terminator. For external and user-defined links, it is the link * buffer. @@ -492,7 +492,7 @@ H5_DLL herr_t H5Ldelete_by_idx_async(const char *app_file, const char *app_func, * * This function should be used only after H5Lget_info() has been * called to verify that \p name is a symbolic link. This can be - * deteremined from the \c link_type field of the \ref H5L_info_t + * determined from the \c link_type field of the \ref H5L_info_t * \c struct. * * \note This function will fail if called on a hard link. @@ -580,7 +580,7 @@ H5_DLL herr_t H5Lget_val_by_idx(hid_t loc_id, const char *group_name, H5_index_t * name includes either a relative path or an absolute path to the * target link, intermediate steps along the path must be verified * before the existence of the target link can be safely checked. If - * the path is not verified and an intermediate element of the path + * the path is not verified, and an intermediate element of the path * does not exist, H5Lexists() will fail. The example in the next * paragraph illustrates one step-by-step method for verifying the * existence of a link with a relative or absolute path. @@ -620,13 +620,13 @@ H5_DLL herr_t H5Lget_val_by_idx(hid_t loc_id, const char *group_name, H5_index_t * H5Lexists() with arguments \c file, \c "/", and \c lapl * returns a positive value; in other words, * \Code{H5Lexists(file, "/", lapl)} returns a positive value. - * In HDF5 version 1.8.16, this function returns 0.</li> + * In the HDF5 1.8 release, this function returns 0.</li> * <li>Let \c root denote a valid HDF5 group identifier that refers to the * root group of an HDF5 file, and let \c lapl denote a valid link * access property list identifier. A call to H5Lexists() with * arguments c root, \c "/", and \c lapl returns a positive value; - * in other words, \Code{H5Lexists(root, "/", lapl)} returns a postive - * value. In HDF5 version 1.8.16, this function returns 0.</li> + * in other words, \Code{H5Lexists(root, "/", lapl)} returns a positive + * value. In the HDF5 1.8 release, this function returns 0.</li> * </ol> * Note that the function accepts link names and path names. This is * potentially misleading to callers, and we plan to separate the @@ -1094,7 +1094,7 @@ H5_DLL herr_t H5Lvisit2(hid_t grp_id, H5_index_t idx_type, H5_iter_order_t order * \p idx_type specifies the index to be used. If the links have not * been indexed by the index type, they will first be sorted by that * index then the iteration will begin; if the links have been so - * indexed, the sorting step will be unnecesary, so the iteration may + * indexed, the sorting step will be unnecessary, so the iteration may * begin more quickly. Valid values include the following: * \indexes * @@ -1853,7 +1853,7 @@ H5_DLL herr_t H5Lvisit1(hid_t grp_id, H5_index_t idx_type, H5_iter_order_t order * \p idx_type specifies the index to be used. If the links have not * been indexed by the index type, they will first be sorted by that * index then the iteration will begin; if the links have been so - * indexed, the sorting step will be unnecesary, so the iteration may + * indexed, the sorting step will be unnecessary, so the iteration may * begin more quickly. Valid values include the following: * \indexes * @@ -58,9 +58,6 @@ static herr_t H5M__get_api_common(hid_t map_id, hid_t key_mem_type_id, const voi /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /*****************************/ /* Library Private Variables */ /*****************************/ @@ -77,9 +74,6 @@ static const H5I_class_t H5I_MAP_CLS[1] = {{ (H5I_free_t)H5M__close_cb /* Callback routine for closing objects of this class */ }}; -/* Flag indicating "top" of interface has been initialized */ -static hbool_t H5M_top_package_initialize_s = FALSE; - /*------------------------------------------------------------------------- * Function: H5M_init * @@ -96,41 +90,14 @@ H5M_init(void) herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) - /* FUNC_ENTER() does all the work */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5M_init() */ - -/*------------------------------------------------------------------------- -NAME - H5M__init_package -- Initialize interface-specific information -USAGE - herr_t H5M__init_package() - -RETURNS - Non-negative on success/Negative on failure -DESCRIPTION - Initializes any interface-specific data or routines. ---------------------------------------------------------------------------- -*/ -herr_t -H5M__init_package(void) -{ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_PACKAGE /* Initialize the ID group for the map IDs */ if (H5I_register_type(H5I_MAP_CLS) < 0) HGOTO_ERROR(H5E_MAP, H5E_CANTINIT, FAIL, "unable to initialize interface") - /* Mark "top" of interface as initialized, too */ - H5M_top_package_initialize_s = TRUE; - done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5M__init_package() */ +} /* end H5M_init() */ /*------------------------------------------------------------------------- * Function: H5M_top_term_package @@ -149,16 +116,10 @@ H5M_top_term_package(void) FUNC_ENTER_NOAPI_NOINIT_NOERR - if (H5M_top_package_initialize_s) { - if (H5I_nmembers(H5I_MAP) > 0) { - (void)H5I_clear_type(H5I_MAP, FALSE, FALSE); - n++; /*H5I*/ - } /* end if */ - - /* Mark closed */ - if (0 == n) - H5M_top_package_initialize_s = FALSE; - } /* end if */ + if (H5I_nmembers(H5I_MAP) > 0) { + (void)H5I_clear_type(H5I_MAP, FALSE, FALSE); + n++; + } FUNC_LEAVE_NOAPI(n) } /* end H5M_top_term_package() */ @@ -183,18 +144,11 @@ H5M_term_package(void) FUNC_ENTER_NOAPI_NOINIT_NOERR - if (H5_PKG_INIT_VAR) { - /* Sanity checks */ - HDassert(0 == H5I_nmembers(H5I_MAP)); - HDassert(FALSE == H5M_top_package_initialize_s); - - /* Destroy the dataset object id group */ - n += (H5I_dec_type_ref(H5I_MAP) > 0); + /* Sanity checks */ + HDassert(0 == H5I_nmembers(H5I_MAP)); - /* Mark closed */ - if (0 == n) - H5_PKG_INIT_VAR = FALSE; - } /* end if */ + /* Destroy the dataset object id group */ + n += (H5I_dec_type_ref(H5I_MAP) > 0); FUNC_LEAVE_NOAPI(n) } /* end H5M_term_package() */ @@ -533,7 +487,7 @@ H5M__open_api_common(hid_t loc_id, const char *name, hid_t mapl_id, void **token /* Open the map */ if (H5VL_optional(*vol_obj_ptr, &vol_cb_args, H5P_DATASET_XFER_DEFAULT, token_ptr) < 0) HGOTO_ERROR(H5E_MAP, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open map") - map = map_args.create.map; + map = map_args.open.map; /* Register an ID for the map */ if ((ret_value = H5VL_register(H5I_MAP, map, (*vol_obj_ptr)->connector, TRUE)) < 0) @@ -1360,6 +1314,7 @@ H5Miterate(hid_t map_id, hsize_t *idx, hid_t key_mem_type_id, H5M_iterate_t op, map_args.specific.args.iterate.loc_params.type = H5VL_OBJECT_BY_SELF; map_args.specific.args.iterate.loc_params.obj_type = H5I_get_type(map_id); map_args.specific.args.iterate.idx = (idx ? *idx : 0); + map_args.specific.args.iterate.key_mem_type_id = key_mem_type_id; map_args.specific.args.iterate.op = op; map_args.specific.args.iterate.op_data = op_data; vol_cb_args.op_type = H5VL_MAP_SPECIFIC; @@ -1450,6 +1405,7 @@ H5Miterate_by_name(hid_t loc_id, const char *map_name, hsize_t *idx, hid_t key_m map_args.specific.args.iterate.loc_params.loc_data.loc_by_name.name = map_name; map_args.specific.args.iterate.loc_params.loc_data.loc_by_name.lapl_id = lapl_id; map_args.specific.args.iterate.idx = (idx ? *idx : 0); + map_args.specific.args.iterate.key_mem_type_id = key_mem_type_id; map_args.specific.args.iterate.op = op; map_args.specific.args.iterate.op_data = op_data; vol_cb_args.op_type = H5VL_MAP_SPECIFIC; @@ -115,9 +115,6 @@ static herr_t H5MF__sects_cb(H5FS_section_info_t *_sect, void *_udata); /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /*****************************/ /* Library Private Variables */ /*****************************/ @@ -653,8 +650,10 @@ H5MF__add_sect(H5F_t *f, H5FD_mem_t alloc_type, H5FS_t *fspace, H5MF_free_sectio H5AC_set_ring(fsm_ring, &orig_ring); #ifdef H5MF_ALLOC_DEBUG_MORE - HDfprintf(stderr, "%s: adding node, node->sect_info.addr = %a, node->sect_info.size = %Hu\n", __func__, - node->sect_info.addr, node->sect_info.size); + HDfprintf(stderr, + "%s: adding node, node->sect_info.addr = %" PRIuHADDR ", node->sect_info.size = %" PRIuHSIZE + "\n", + __func__, node->sect_info.addr, node->sect_info.size); #endif /* H5MF_ALLOC_DEBUG_MORE */ /* Add the section */ if (H5FS_sect_add(f, fspace, (H5FS_section_info_t *)node, H5FS_ADD_RETURNED_SPACE, &udata) < 0) @@ -706,7 +705,7 @@ H5MF__find_sect(H5F_t *f, H5FD_mem_t alloc_type, hsize_t size, H5FS_t *fspace, h HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "error locating free space in file") #ifdef H5MF_ALLOC_DEBUG_MORE - HDfprintf(stderr, "%s: section found = %t\n", __func__, ret_value); + HDfprintf(stderr, "%s: section found = %d\n", __func__, ret_value); #endif /* H5MF_ALLOC_DEBUG_MORE */ /* Check for actually finding section */ @@ -734,7 +733,7 @@ H5MF__find_sect(H5F_t *f, H5FD_mem_t alloc_type, hsize_t size, H5FS_t *fspace, h node->sect_info.size -= size; #ifdef H5MF_ALLOC_DEBUG_MORE - HDfprintf(stderr, "%s: re-adding node, node->sect_info.size = %Hu\n", __func__, + HDfprintf(stderr, "%s: re-adding node, node->sect_info.size = %" PRIuHSIZE "\n", __func__, node->sect_info.size); #endif /* H5MF_ALLOC_DEBUG_MORE */ @@ -778,7 +777,7 @@ H5MF_alloc(H5F_t *f, H5FD_mem_t alloc_type, hsize_t size) FUNC_ENTER_NOAPI_TAG(H5AC__FREESPACE_TAG, HADDR_UNDEF) #ifdef H5MF_ALLOC_DEBUG - HDfprintf(stderr, "%s: alloc_type = %u, size = %Hu\n", __func__, (unsigned)alloc_type, size); + HDfprintf(stderr, "%s: alloc_type = %u, size = %" PRIuHSIZE "\n", __func__, (unsigned)alloc_type, size); #endif /* H5MF_ALLOC_DEBUG */ /* check arguments */ @@ -851,7 +850,8 @@ done: H5AC_set_ring(orig_ring, NULL); #ifdef H5MF_ALLOC_DEBUG - HDfprintf(stderr, "%s: Leaving: ret_value = %a, size = %Hu\n", __func__, ret_value, size); + HDfprintf(stderr, "%s: Leaving: ret_value = %" PRIuHADDR ", size = %" PRIuHSIZE "\n", __func__, ret_value, + size); #endif /* H5MF_ALLOC_DEBUG */ #ifdef H5MF_ALLOC_DEBUG_DUMP H5MF__sects_dump(f, stderr); @@ -891,7 +891,7 @@ H5MF__alloc_pagefs(H5F_t *f, H5FD_mem_t alloc_type, hsize_t size) FUNC_ENTER_STATIC #ifdef H5MF_ALLOC_DEBUG - HDfprintf(stderr, "%s: alloc_type = %u, size = %Hu\n", __func__, (unsigned)alloc_type, size); + HDfprintf(stderr, "%s: alloc_type = %u, size = %" PRIuHSIZE "\n", __func__, (unsigned)alloc_type, size); #endif /* H5MF_ALLOC_DEBUG */ H5MF__alloc_to_fs_type(f->shared, alloc_type, size, &ptype); @@ -988,7 +988,8 @@ H5MF__alloc_pagefs(H5F_t *f, H5FD_mem_t alloc_type, hsize_t size) done: #ifdef H5MF_ALLOC_DEBUG - HDfprintf(stderr, "%s: Leaving: ret_value = %a, size = %Hu\n", __func__, ret_value, size); + HDfprintf(stderr, "%s: Leaving: ret_value = %" PRIuHADDR ", size = %" PRIuHSIZE "\n", __func__, ret_value, + size); #endif /* H5MF_ALLOC_DEBUG */ #ifdef H5MF_ALLOC_DEBUG_DUMP H5MF__sects_dump(f, stderr); @@ -1034,7 +1035,7 @@ H5MF_alloc_tmp(H5F_t *f, hsize_t size) FUNC_ENTER_NOAPI(HADDR_UNDEF) #ifdef H5MF_ALLOC_DEBUG - HDfprintf(stderr, "%s: size = %Hu\n", __func__, size); + HDfprintf(stderr, "%s: size = %" PRIuHSIZE "\n", __func__, size); #endif /* H5MF_ALLOC_DEBUG */ /* check args */ @@ -1086,8 +1087,8 @@ H5MF_xfree(H5F_t *f, H5FD_mem_t alloc_type, haddr_t addr, hsize_t size) FUNC_ENTER_NOAPI_TAG(H5AC__FREESPACE_TAG, FAIL) #ifdef H5MF_ALLOC_DEBUG - HDfprintf(stderr, "%s: Entering - alloc_type = %u, addr = %a, size = %Hu\n", __func__, - (unsigned)alloc_type, addr, size); + HDfprintf(stderr, "%s: Entering - alloc_type = %u, addr = %" PRIuHADDR ", size = %" PRIuHSIZE "\n", + __func__, (unsigned)alloc_type, addr, size); #endif /* H5MF_ALLOC_DEBUG */ /* check arguments */ @@ -1136,7 +1137,7 @@ H5MF_xfree(H5F_t *f, H5FD_mem_t alloc_type, haddr_t addr, hsize_t size) * space is at the end of the file */ #ifdef H5MF_ALLOC_DEBUG_MORE - HDfprintf(stderr, "%s: fs_addr = %a\n", __func__, f->shared->fs_addr[fs_type]); + HDfprintf(stderr, "%s: fs_addr = %" PRIuHADDR "\n", __func__, f->shared->fs_addr[fs_type]); #endif /* H5MF_ALLOC_DEBUG_MORE */ if (!H5F_addr_defined(f->shared->fs_addr[fs_type])) { htri_t status; /* "can absorb" status for section into */ @@ -1152,8 +1153,9 @@ H5MF_xfree(H5F_t *f, H5FD_mem_t alloc_type, haddr_t addr, hsize_t size) HGOTO_DONE(SUCCEED) else if (size < f->shared->fs_threshold) { #ifdef H5MF_ALLOC_DEBUG_MORE - HDfprintf(stderr, "%s: dropping addr = %a, size = %Hu, on the floor!\n", __func__, addr, - size); + HDfprintf(stderr, + "%s: dropping addr = %" PRIuHADDR ", size = %" PRIuHSIZE ", on the floor!\n", + __func__, addr, size); #endif /* H5MF_ALLOC_DEBUG_MORE */ HGOTO_DONE(SUCCEED) } /* end else-if */ @@ -1170,7 +1172,8 @@ H5MF_xfree(H5F_t *f, H5FD_mem_t alloc_type, haddr_t addr, hsize_t size) */ if (f->shared->fs_state[fs_type] == H5F_FS_STATE_DELETING || !H5F_HAVE_FREE_SPACE_MANAGER(f)) { #ifdef H5MF_ALLOC_DEBUG_MORE - HDfprintf(stderr, "%s: dropping addr = %a, size = %Hu, on the floor!\n", __func__, addr, size); + HDfprintf(stderr, "%s: dropping addr = %" PRIuHADDR ", size = %" PRIuHSIZE ", on the floor!\n", + __func__, addr, size); #endif /* H5MF_ALLOC_DEBUG_MORE */ HGOTO_DONE(SUCCEED) } /* end if */ @@ -1279,7 +1282,9 @@ H5MF_try_extend(H5F_t *f, H5FD_mem_t alloc_type, haddr_t addr, hsize_t size, hsi FUNC_ENTER_NOAPI_TAG(H5AC__FREESPACE_TAG, FAIL) #ifdef H5MF_ALLOC_DEBUG - HDfprintf(stderr, "%s: Entering: alloc_type = %u, addr = %a, size = %Hu, extra_requested = %Hu\n", + HDfprintf(stderr, + "%s: Entering: alloc_type = %u, addr = %" PRIuHADDR ", size = %" PRIuHSIZE + ", extra_requested = %" PRIuHSIZE "\n", __func__, (unsigned)alloc_type, addr, size, extra_requested); #endif /* H5MF_ALLOC_DEBUG */ @@ -1332,7 +1337,7 @@ H5MF_try_extend(H5F_t *f, H5FD_mem_t alloc_type, haddr_t addr, hsize_t size, hsi if ((ret_value = H5F__try_extend(f, map_type, end, extra_requested + frag_size)) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_CANTEXTEND, FAIL, "error extending file") #ifdef H5MF_ALLOC_DEBUG_MORE - HDfprintf(stderr, "%s: extended = %t\n", __func__, ret_value); + HDfprintf(stderr, "%s: extended = %d\n", __func__, ret_value); #endif /* H5MF_ALLOC_DEBUG_MORE */ /* If extending at EOA succeeds: */ @@ -1370,7 +1375,7 @@ H5MF_try_extend(H5F_t *f, H5FD_mem_t alloc_type, haddr_t addr, hsize_t size, hsi HGOTO_ERROR(H5E_RESOURCE, H5E_CANTEXTEND, FAIL, "error extending aggregation block") #ifdef H5MF_ALLOC_DEBUG_MORE - HDfprintf(stderr, "%s: H5MF__aggr_try_extend = %t\n", __func__, ret_value); + HDfprintf(stderr, "%s: H5MF__aggr_try_extend = %d\n", __func__, ret_value); #endif /* H5MF_ALLOC_DEBUG_MORE */ } /* end if */ @@ -1396,7 +1401,7 @@ H5MF_try_extend(H5F_t *f, H5FD_mem_t alloc_type, haddr_t addr, hsize_t size, hsi HGOTO_ERROR(H5E_RESOURCE, H5E_CANTEXTEND, FAIL, "error extending block in free space manager") #ifdef H5MF_ALLOC_DEBUG_MORE - HDfprintf(stderr, "%s: Try to H5FS_sect_try_extend = %t\n", __func__, ret_value); + HDfprintf(stderr, "%s: Try to H5FS_sect_try_extend = %d\n", __func__, ret_value); #endif /* H5MF_ALLOC_DEBUG_MORE */ } /* end if */ @@ -1407,7 +1412,7 @@ H5MF_try_extend(H5F_t *f, H5FD_mem_t alloc_type, haddr_t addr, hsize_t size, hsi if (frag_size <= H5F_PGEND_META_THRES(f) && extra_requested <= frag_size) ret_value = TRUE; #ifdef H5MF_ALLOC_DEBUG_MORE - HDfprintf(stderr, "%s: Try to extend into the page end threshold = %t\n", __func__, + HDfprintf(stderr, "%s: Try to extend into the page end threshold = %d\n", __func__, ret_value); #endif /* H5MF_ALLOC_DEBUG_MORE */ } /* end if */ @@ -1420,7 +1425,7 @@ done: H5AC_set_ring(orig_ring, NULL); #ifdef H5MF_ALLOC_DEBUG - HDfprintf(stderr, "%s: Leaving: ret_value = %t\n", __func__, ret_value); + HDfprintf(stderr, "%s: Leaving: ret_value = %d\n", __func__, ret_value); #endif /* H5MF_ALLOC_DEBUG */ #ifdef H5MF_ALLOC_DEBUG_DUMP H5MF__sects_dump(f, stderr); @@ -1455,8 +1460,8 @@ H5MF_try_shrink(H5F_t *f, H5FD_mem_t alloc_type, haddr_t addr, hsize_t size) FUNC_ENTER_NOAPI_TAG(H5AC__FREESPACE_TAG, FAIL) #ifdef H5MF_ALLOC_DEBUG - HDfprintf(stderr, "%s: Entering - alloc_type = %u, addr = %a, size = %Hu\n", __func__, - (unsigned)alloc_type, addr, size); + HDfprintf(stderr, "%s: Entering - alloc_type = %u, addr = %" PRIuHADDR ", size = %" PRIuHSIZE "\n", + __func__, (unsigned)alloc_type, addr, size); #endif /* H5MF_ALLOC_DEBUG */ /* check arguments */ @@ -1592,8 +1597,9 @@ H5MF__close_delete_fstype(H5F_t *f, H5F_mem_page_t type) HDassert((H5FD_mem_t)type < H5FD_MEM_NTYPES); #ifdef H5MF_ALLOC_DEBUG_MORE - HDfprintf(stderr, "%s: Check 1.0 - f->shared->fs_man[%u] = %p, f->shared->fs_addr[%u] = %a\n", __func__, - (unsigned)type, f->shared->fs_man[type], (unsigned)type, f->shared->fs_addr[type]); + HDfprintf(stderr, "%s: Check 1.0 - f->shared->fs_man[%u] = %p, f->shared->fs_addr[%u] = %" PRIuHADDR "\n", + __func__, (unsigned)type, (void *)f->shared->fs_man[type], (unsigned)type, + f->shared->fs_addr[type]); #endif /* H5MF_ALLOC_DEBUG_MORE */ /* If the free space manager for this type is open, close it */ @@ -1602,8 +1608,9 @@ H5MF__close_delete_fstype(H5F_t *f, H5F_mem_page_t type) HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't close the free space manager") #ifdef H5MF_ALLOC_DEBUG_MORE - HDfprintf(stderr, "%s: Check 2.0 - f->shared->fs_man[%u] = %p, f->shared->fs_addr[%u] = %a\n", __func__, - (unsigned)type, f->shared->fs_man[type], (unsigned)type, f->shared->fs_addr[type]); + HDfprintf(stderr, "%s: Check 2.0 - f->shared->fs_man[%u] = %p, f->shared->fs_addr[%u] = %" PRIuHADDR "\n", + __func__, (unsigned)type, (void *)f->shared->fs_man[type], (unsigned)type, + f->shared->fs_addr[type]); #endif /* H5MF_ALLOC_DEBUG_MORE */ /* If there is free space manager info for this type, delete it */ diff --git a/src/H5MFaggr.c b/src/H5MFaggr.c index 77345c9..78bf620 100644 --- a/src/H5MFaggr.c +++ b/src/H5MFaggr.c @@ -92,7 +92,7 @@ H5MF_aggr_vfd_alloc(H5F_t *f, H5FD_mem_t alloc_type, hsize_t size) FUNC_ENTER_NOAPI(HADDR_UNDEF) #ifdef H5MF_AGGR_DEBUG - HDfprintf(stderr, "%s: alloc_type = %u, size = %Hu\n", __func__, (unsigned)alloc_type, size); + HDfprintf(stderr, "%s: alloc_type = %u, size = %" PRIuHSIZE "\n", __func__, (unsigned)alloc_type, size); #endif /* H5MF_AGGR_DEBUG */ /* check arguments */ @@ -120,7 +120,8 @@ H5MF_aggr_vfd_alloc(H5F_t *f, H5FD_mem_t alloc_type, hsize_t size) done: #ifdef H5MF_AGGR_DEBUG - HDfprintf(stderr, "%s: Leaving: ret_value = %a, size = %Hu\n", __func__, ret_value, size); + HDfprintf(stderr, "%s: Leaving: ret_value = %" PRIuHADDR ", size = %" PRIuHSIZE "\n", __func__, ret_value, + size); #endif /* H5MF_AGGR_DEBUG */ FUNC_LEAVE_NOAPI(ret_value) @@ -150,7 +151,7 @@ H5MF__aggr_alloc(H5F_t *f, H5F_blk_aggr_t *aggr, H5F_blk_aggr_t *other_aggr, H5F FUNC_ENTER_STATIC #ifdef H5MF_AGGR_DEBUG - HDfprintf(stderr, "%s: type = %u, size = %Hu\n", __func__, (unsigned)type, size); + HDfprintf(stderr, "%s: type = %u, size = %" PRIuHSIZE "\n", __func__, (unsigned)type, size); #endif /* H5MF_AGGR_DEBUG */ /* check args */ @@ -195,12 +196,12 @@ H5MF__aggr_alloc(H5F_t *f, H5F_blk_aggr_t *aggr, H5F_blk_aggr_t *other_aggr, H5F haddr_t aggr_frag_addr = HADDR_UNDEF; /* Address of aggregrator fragment */ hsize_t aggr_frag_size = 0; /* Size of aggregator fragment */ hsize_t alignment; /* Alignment of this section */ - hsize_t aggr_mis_align = 0; /* Mis-alignment of aggregator */ + hsize_t aggr_mis_align = 0; /* Misalignment of aggregator */ H5FD_mem_t alloc_type, other_alloc_type; /* Current aggregator & 'other' aggregator types */ #ifdef H5MF_AGGR_DEBUG - HDfprintf(stderr, "%s: aggr = {%a, %Hu, %Hu}\n", __func__, aggr->addr, aggr->tot_size, - aggr->size); + HDfprintf(stderr, "%s: aggr = {%" PRIuHADDR ", %" PRIuHSIZE ", %" PRIuHSIZE "}\n", __func__, + aggr->addr, aggr->tot_size, aggr->size); #endif /* H5MF_AGGR_DEBUG */ /* Turn off alignment if allocation < threshold */ @@ -388,7 +389,7 @@ H5MF__aggr_alloc(H5F_t *f, H5F_blk_aggr_t *aggr, H5F_blk_aggr_t *other_aggr, H5F done: #ifdef H5MF_AGGR_DEBUG - HDfprintf(stderr, "%s: ret_value = %a\n", __func__, ret_value); + HDfprintf(stderr, "%s: ret_value = %" PRIuHADDR "\n", __func__, ret_value); #endif /* H5MF_AGGR_DEBUG */ FUNC_LEAVE_NOAPI(ret_value) } /* end H5MF__aggr_alloc() */ @@ -537,8 +538,11 @@ done: if (H5F_addr_eq((sect->sect_info.addr + sect->sect_info.size), aggr->addr) || H5F_addr_eq((aggr->addr + aggr->size), sect->sect_info.addr)) { #ifdef H5MF_AGGR_DEBUG - HDfprintf(stderr, "%s: section {%a, %Hu} adjoins aggr = {%a, %Hu}\n", "H5MF__aggr_can_absorb", - sect->sect_info.addr, sect->sect_info.size, aggr->addr, aggr->size); + HDfprintf(stderr, + "%s: section {%" PRIuHADDR ", %" PRIuHSIZE "} adjoins aggr = {%" PRIuHADDR + ", %" PRIuHSIZE "}\n", + "H5MF__aggr_can_absorb", sect->sect_info.addr, sect->sect_info.size, aggr->addr, + aggr->size); #endif /* H5MF_AGGR_DEBUG */ /* Check if aggregator would get too large and should be absorbed into section */ if ((aggr->size + sect->sect_info.size) >= aggr->alloc_size) @@ -587,7 +591,9 @@ done: /* Check if the section adjoins the beginning or end of the aggregator */ if (H5F_addr_eq((sect->sect_info.addr + sect->sect_info.size), aggr->addr)) { #ifdef H5MF_AGGR_DEBUG - HDfprintf(stderr, "%s: aggr {%a, %Hu} adjoins front of section = {%a, %Hu}\n", + HDfprintf(stderr, + "%s: aggr {%" PRIuHADDR ", %" PRIuHSIZE "} adjoins front of section = {%" PRIuHADDR + ", %" PRIuHSIZE "}\n", "H5MF__aggr_absorb", aggr->addr, aggr->size, sect->sect_info.addr, sect->sect_info.size); #endif /* H5MF_AGGR_DEBUG */ @@ -599,7 +605,9 @@ done: HDassert(H5F_addr_eq((aggr->addr + aggr->size), sect->sect_info.addr)); #ifdef H5MF_AGGR_DEBUG - HDfprintf(stderr, "%s: aggr {%a, %Hu} adjoins end of section = {%a, %Hu}\n", + HDfprintf(stderr, + "%s: aggr {%" PRIuHADDR ", %" PRIuHSIZE "} adjoins end of section = {%" PRIuHADDR + ", %" PRIuHSIZE "}\n", "H5MF__aggr_absorb", aggr->addr, aggr->size, sect->sect_info.addr, sect->sect_info.size); #endif /* H5MF_AGGR_DEBUG */ @@ -617,7 +625,9 @@ done: /* Check if the section adjoins the beginning or end of the aggregator */ if (H5F_addr_eq((sect->sect_info.addr + sect->sect_info.size), aggr->addr)) { #ifdef H5MF_AGGR_DEBUG - HDfprintf(stderr, "%s: section {%a, %Hu} adjoins front of aggr = {%a, %Hu}\n", + HDfprintf(stderr, + "%s: section {%" PRIuHADDR ", %" PRIuHSIZE "} adjoins front of aggr = {%" PRIuHADDR + ", %" PRIuHSIZE "}\n", "H5MF__aggr_absorb", sect->sect_info.addr, sect->sect_info.size, aggr->addr, aggr->size); #endif /* H5MF_AGGR_DEBUG */ @@ -635,7 +645,9 @@ done: HDassert(H5F_addr_eq((aggr->addr + aggr->size), sect->sect_info.addr)); #ifdef H5MF_AGGR_DEBUG - HDfprintf(stderr, "%s: section {%a, %Hu} adjoins end of aggr = {%a, %Hu}\n", + HDfprintf(stderr, + "%s: section {%" PRIuHADDR ", %" PRIuHSIZE "} adjoins end of aggr = {%" PRIuHADDR + ", %" PRIuHSIZE "}\n", "H5MF__aggr_absorb", sect->sect_info.addr, sect->sect_info.size, aggr->addr, aggr->size); #endif /* H5MF_AGGR_DEBUG */ @@ -723,7 +735,8 @@ done: tmp_addr = aggr->addr; tmp_size = aggr->size; #ifdef H5MF_AGGR_DEBUG - HDfprintf(stderr, "%s: tmp_addr = %a, tmp_size = %Hu\n", __func__, tmp_addr, tmp_size); + HDfprintf(stderr, "%s: tmp_addr = %" PRIuHADDR ", tmp_size = %" PRIuHSIZE "\n", __func__, + tmp_addr, tmp_size); #endif /* H5MF_AGGR_DEBUG */ /* Reset aggregator block information */ diff --git a/src/H5MFdbg.c b/src/H5MFdbg.c index 6ccbe78..60d7779 100644 --- a/src/H5MFdbg.c +++ b/src/H5MFdbg.c @@ -50,7 +50,7 @@ typedef struct { H5FS_t *fspace; /* Free space manager */ FILE * stream; /* Stream for output */ - int indent; /* Indention amount */ + int indent; /* Indentation amount */ int fwidth; /* Field width amount */ } H5MF_debug_iter_ud_t; diff --git a/src/H5MFsection.c b/src/H5MFsection.c index 69b2ca0..13675f5 100644 --- a/src/H5MFsection.c +++ b/src/H5MFsection.c @@ -472,8 +472,9 @@ H5MF__sect_simple_can_shrink(const H5FS_section_info_t *_sect, void *_udata) /* Set the shrinking type */ udata->shrink = H5MF_SHRINK_EOA; #ifdef H5MF_ALLOC_DEBUG_MORE - HDfprintf(stderr, "%s: section {%a, %Hu}, shrinks file, eoa = %a\n", __func__, sect->sect_info.addr, - sect->sect_info.size, eoa); + HDfprintf(stderr, + "%s: section {%" PRIuHADDR ", %" PRIuHSIZE "}, shrinks file, eoa = %" PRIuHADDR "\n", + __func__, sect->sect_info.addr, sect->sect_info.size, eoa); #endif /* H5MF_ALLOC_DEBUG_MORE */ /* Indicate shrinking can occur */ @@ -496,8 +497,9 @@ H5MF__sect_simple_can_shrink(const H5FS_section_info_t *_sect, void *_udata) /* Set the aggregator to operate on */ udata->aggr = &(udata->f->shared->meta_aggr); #ifdef H5MF_ALLOC_DEBUG_MORE - HDfprintf(stderr, "%s: section {%a, %Hu}, adjoins metadata aggregator\n", __func__, - sect->sect_info.addr, sect->sect_info.size); + HDfprintf(stderr, + "%s: section {%" PRIuHADDR ", %" PRIuHSIZE "}, adjoins metadata aggregator\n", + __func__, sect->sect_info.addr, sect->sect_info.size); #endif /* H5MF_ALLOC_DEBUG_MORE */ /* Indicate shrinking can occur */ @@ -517,8 +519,9 @@ H5MF__sect_simple_can_shrink(const H5FS_section_info_t *_sect, void *_udata) /* Set the aggregator to operate on */ udata->aggr = &(udata->f->shared->sdata_aggr); #ifdef H5MF_ALLOC_DEBUG_MORE - HDfprintf(stderr, "%s: section {%a, %Hu}, adjoins small data aggregator\n", __func__, - sect->sect_info.addr, sect->sect_info.size); + HDfprintf(stderr, + "%s: section {%" PRIuHADDR ", %" PRIuHSIZE "}, adjoins small data aggregator\n", + __func__, sect->sect_info.addr, sect->sect_info.size); #endif /* H5MF_ALLOC_DEBUG_MORE */ /* Indicate shrinking can occur */ @@ -625,8 +628,8 @@ H5MF__sect_small_add(H5FS_section_info_t **_sect, unsigned *flags, void *_udata) FUNC_ENTER_STATIC #ifdef H5MF_ALLOC_DEBUG_MORE - HDfprintf(stderr, "%s: Entering, section {%a, %Hu}\n", __func__, (*sect)->sect_info.addr, - (*sect)->sect_info.size); + HDfprintf(stderr, "%s: Entering, section {%" PRIuHADDR ", %" PRIuHSIZE "}\n", __func__, + (*sect)->sect_info.addr, (*sect)->sect_info.size); #endif /* H5MF_ALLOC_DEBUG_MORE */ /* Do not adjust the section raw data or global heap data */ @@ -653,8 +656,8 @@ H5MF__sect_small_add(H5FS_section_info_t **_sect, unsigned *flags, void *_udata) else if (prem <= H5F_PGEND_META_THRES(udata->f)) { (*sect)->sect_info.size += prem; #ifdef H5MF_ALLOC_DEBUG_MORE - HDfprintf(stderr, "%s: section is adjusted {%a, %Hu}\n", __func__, (*sect)->sect_info.addr, - (*sect)->sect_info.size); + HDfprintf(stderr, "%s: section is adjusted {%" PRIuHADDR ", %" PRIuHSIZE "}\n", __func__, + (*sect)->sect_info.addr, (*sect)->sect_info.size); #endif /* H5MF_ALLOC_DEBUG_MORE */ } /* end if */ @@ -702,7 +705,7 @@ H5MF__sect_small_can_merge(const H5FS_section_info_t *_sect1, const H5FS_section ret_value = FALSE; #ifdef H5MF_ALLOC_DEBUG_MORE - HDfprintf(stderr, "%s: Leaving: ret_value = %t\n", __func__, ret_value); + HDfprintf(stderr, "%s: Leaving: ret_value = %d\n", __func__, ret_value); #endif /* H5MF_ALLOC_DEBUG_MORE */ FUNC_LEAVE_NOAPI(ret_value) @@ -806,7 +809,7 @@ H5MF__sect_large_can_merge(const H5FS_section_info_t *_sect1, const H5FS_section ret_value = H5F_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr); #ifdef H5MF_ALLOC_DEBUG_MORE - HDfprintf(stderr, "%s: Leaving: ret_value = %t\n", __func__, ret_value); + HDfprintf(stderr, "%s: Leaving: ret_value = %d\n", __func__, ret_value); #endif /* H5MF_ALLOC_DEBUG_MORE */ FUNC_LEAVE_NOAPI(ret_value) @@ -894,8 +897,9 @@ H5MF__sect_large_can_shrink(const H5FS_section_info_t *_sect, void *_udata) /* Set the shrinking type */ udata->shrink = H5MF_SHRINK_EOA; #ifdef H5MF_ALLOC_DEBUG_MORE - HDfprintf(stderr, "%s: section {%a, %Hu}, shrinks file, eoa = %a\n", __func__, sect->sect_info.addr, - sect->sect_info.size, eoa); + HDfprintf(stderr, + "%s: section {%" PRIuHADDR ", %" PRIuHSIZE "}, shrinks file, eoa = %" PRIuHADDR "\n", + __func__, sect->sect_info.addr, sect->sect_info.size, eoa); #endif /* H5MF_ALLOC_DEBUG_MORE */ /* Indicate shrinking can occur */ diff --git a/src/H5MP.c b/src/H5MP.c deleted file mode 100644 index 474a995..0000000 --- a/src/H5MP.c +++ /dev/null @@ -1,446 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * 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 COPYING file, which can be found at the root of the source code * - * distribution tree, or in https://www.hdfgroup.org/licenses. * - * If you do not have access to either file, you may request a copy from * - * help@hdfgroup.org. * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/*------------------------------------------------------------------------- - * - * Created: H5MP.c - * May 2 2005 - * Quincey Koziol - * - * Purpose: Implements memory pools. (Similar to Apache's APR - * memory pools) - * - * Please see the documentation in: - * doc/html/TechNotes/MemoryPools.html for a full description - * of how they work, etc. - * - *------------------------------------------------------------------------- - */ - -#include "H5MPmodule.h" /* This source code file is part of the H5MP module */ - -/* Private headers */ -#include "H5private.h" /* Generic Functions */ -#include "H5Eprivate.h" /* Error handling */ -#include "H5MMprivate.h" /* Memory management */ -#include "H5MPpkg.h" /* Memory Pools */ - -/****************/ -/* Local Macros */ -/****************/ - -/* Minimum sized block */ -#define H5MP_MIN_BLOCK (H5MP_BLOCK_ALIGN(sizeof(H5MP_page_blk_t)) + H5MP_BLOCK_ALIGNMENT) - -/* First block in page */ -#define H5MP_PAGE_FIRST_BLOCK(p) \ - (H5MP_page_blk_t *)((void *)((unsigned char *)(p) + H5MP_BLOCK_ALIGN(sizeof(H5MP_page_t)))) - -/******************/ -/* Local Typedefs */ -/******************/ - -/********************/ -/* Local Prototypes */ -/********************/ - -/********************************/ -/* Package Variable Definitions */ -/********************************/ - -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - -/********************/ -/* Static Variables */ -/********************/ - -/* Declare a free list to manage the H5MP_pool_t struct */ -H5FL_DEFINE(H5MP_pool_t); - -/*------------------------------------------------------------------------- - * Function: H5MP_create - * - * Purpose: Create a new memory pool - * - * Return: Pointer to the memory pool "header" on success/NULL on failure - * - * Programmer: Quincey Koziol - * May 2 2005 - * - *------------------------------------------------------------------------- - */ -H5MP_pool_t * -H5MP_create(size_t page_size, unsigned flags) -{ - H5MP_pool_t *mp = NULL; /* New memory pool header */ - H5MP_pool_t *ret_value = NULL; /* Return value */ - - FUNC_ENTER_NOAPI(NULL) - - /* Allocate space for the pool header */ - if (NULL == (mp = H5FL_MALLOC(H5MP_pool_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for memory pool header") - - /* Assign information */ - mp->page_size = H5MP_BLOCK_ALIGN(page_size); - mp->flags = flags; - - /* Initialize information */ - mp->free_size = 0; - mp->first = NULL; - mp->max_size = mp->page_size - H5MP_BLOCK_ALIGN(sizeof(H5MP_page_t)); - - /* Create factory for pool pages */ - if (NULL == (mp->page_fac = H5FL_fac_init(page_size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, NULL, "can't create page factory") - - /* Set return value */ - ret_value = mp; - -done: - if (NULL == ret_value && mp) - if (H5MP_close(mp) < 0) - HDONE_ERROR(H5E_RESOURCE, H5E_CANTFREE, NULL, "unable to free memory pool header") - - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5MP_create() */ - -/*------------------------------------------------------------------------- - * Function: H5MP__new_page - * - * Purpose: Allocate new page for a memory pool - * - * Return: Pointer to the page allocated on success/NULL on failure - * - * Programmer: Quincey Koziol - * May 4 2005 - * - *------------------------------------------------------------------------- - */ -static H5MP_page_t * -H5MP__new_page(H5MP_pool_t *mp, size_t page_size) -{ - H5MP_page_t * new_page; /* New page created */ - H5MP_page_blk_t *first_blk; /* Pointer to first block in page */ - H5MP_page_t * ret_value = NULL; /* Return value */ - - FUNC_ENTER_STATIC - - /* Sanity check */ - HDassert(mp); - HDassert(page_size >= mp->page_size); - - /* Allocate page */ - if (page_size > mp->page_size) { - if (NULL == (new_page = (H5MP_page_t *)H5MM_malloc(page_size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for page") - new_page->free_size = page_size - H5MP_BLOCK_ALIGN(sizeof(H5MP_page_t)); - new_page->fac_alloc = FALSE; - } /* end if */ - else { - if (NULL == (new_page = (H5MP_page_t *)H5FL_FAC_MALLOC(mp->page_fac))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for page") - new_page->free_size = mp->max_size; - new_page->fac_alloc = TRUE; - } /* end else */ - - /* Initialize page information */ - first_blk = H5MP_PAGE_FIRST_BLOCK(new_page); - first_blk->size = new_page->free_size; - first_blk->page = new_page; - first_blk->is_free = TRUE; - first_blk->prev = NULL; - first_blk->next = NULL; - - /* Insert into page list */ - new_page->prev = NULL; - new_page->next = mp->first; - if (mp->first) - mp->first->prev = new_page; - mp->first = new_page; - - /* Account for new free space */ - new_page->free_blk = first_blk; - mp->free_size += new_page->free_size; - - /* Assign return value */ - ret_value = new_page; - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5MP__new_page() */ - -/*------------------------------------------------------------------------- - * Function: H5MP_malloc - * - * Purpose: Allocate space in a memory pool - * - * Return: Pointer to the space allocated on success/NULL on failure - * - * Programmer: Quincey Koziol - * May 2 2005 - * - *------------------------------------------------------------------------- - */ -void * -H5MP_malloc(H5MP_pool_t *mp, size_t request) -{ - H5MP_page_t * alloc_page = NULL; /* Page to allocate space from */ - H5MP_page_blk_t *alloc_free; /* Pointer to free space in page */ - size_t needed; /* Size requested, plus block header and alignment */ - void * ret_value = NULL; /* Return value */ - - FUNC_ENTER_NOAPI(NULL) - - /* Sanity check */ - HDassert(mp); - HDassert(request > 0); - - /* Compute actual size needed */ - needed = H5MP_BLOCK_ALIGN(request) + H5MP_BLOCK_ALIGN(sizeof(H5MP_page_blk_t)); - - /* See if the request can be handled by existing free space */ - if (needed <= mp->free_size) { - size_t pool_free_avail; /* Amount of free space possibly available in pool */ - - /* Locate page with enough free space */ - alloc_page = mp->first; - pool_free_avail = mp->free_size; - while (alloc_page && pool_free_avail >= needed) { - /* If we found a page with enough free space, search for large - * enough free block on that page */ - if (alloc_page->free_size >= needed) { - size_t page_free_avail; /* Amount of free space possibly available */ - - /* Locate large enough block */ - alloc_free = alloc_page->free_blk; - page_free_avail = alloc_page->free_size; - while (alloc_free && page_free_avail >= needed) { - if (alloc_free->is_free) { - /* If we found a large enough block, leave now */ - if (alloc_free->size >= needed) - goto found; /* Needed to escape double "while" loop */ - - /* Decrement amount of potential space left */ - page_free_avail -= alloc_free->size; - } /* end if */ - - /* Go to next block */ - alloc_free = alloc_free->next; - } /* end while */ - } /* end if */ - - /* Decrement amount of potential space left */ - pool_free_avail -= alloc_page->free_size; - - /* Go to next page */ - alloc_page = alloc_page->next; - } /* end while */ - } /* end if */ - - { - size_t page_size; /* Size of page needed */ - - /* Check if the request is too large for a standard page */ - page_size = - (needed > mp->max_size) ? (needed + H5MP_BLOCK_ALIGN(sizeof(H5MP_page_t))) : mp->page_size; - - /* Allocate new page */ - if (NULL == (alloc_page = H5MP__new_page(mp, page_size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for page") - - /* Set the block to allocate from */ - alloc_free = alloc_page->free_blk; - } /* end block */ - - /* Allocate space in page */ -found: - - /* Sanity check */ - HDassert(alloc_page); - HDassert(alloc_free); - - /* Check if we can subdivide the free space */ - if (alloc_free->size > (needed + H5MP_MIN_BLOCK)) { - H5MP_page_blk_t *new_free; /* New free block created */ - - /* Carve out new free block after block to allocate */ - new_free = (H5MP_page_blk_t *)((void *)(((unsigned char *)alloc_free) + needed)); - - /* Link into existing lists */ - new_free->next = alloc_free->next; - if (alloc_free->next) - alloc_free->next->prev = new_free; - new_free->prev = alloc_free; - alloc_free->next = new_free; - - /* Set blocks' information */ - new_free->size = alloc_free->size - needed; - new_free->is_free = TRUE; - new_free->page = alloc_free->page; - alloc_free->size = needed; - alloc_free->is_free = FALSE; - } /* end if */ - else { - /* Use whole free space block for new block */ - alloc_free->is_free = FALSE; - } /* end else */ - - /* Update page & pool's free size information */ - alloc_page->free_size -= alloc_free->size; - if (alloc_page->free_blk == alloc_free) - alloc_page->free_blk = alloc_free->next; - mp->free_size -= alloc_free->size; - - /* Set new space pointer for the return value */ - ret_value = ((unsigned char *)alloc_free) + H5MP_BLOCK_ALIGN(sizeof(H5MP_page_blk_t)); - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5MP_malloc() */ - -/*------------------------------------------------------------------------- - * Function: H5MP_free - * - * Purpose: Release space in a memory pool - * - * Return: NULL on success/NULL on failure - * - * Programmer: Quincey Koziol - * May 3 2005 - * - * Note: Should we release pages that have no used blocks? - * - *------------------------------------------------------------------------- - */ -void * -H5MP_free(H5MP_pool_t *mp, void *spc) -{ - H5MP_page_blk_t *spc_blk; /* Block for space to free */ - H5MP_page_t * spc_page; /* Page containing block to free */ - void * ret_value = NULL; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT_NOERR - - /* Sanity check */ - HDassert(mp); - HDassert(spc); - - /* Get block header for space to free */ - spc_blk = - (H5MP_page_blk_t *)((void *)(((unsigned char *)spc) - H5MP_BLOCK_ALIGN(sizeof(H5MP_page_blk_t)))); - - /* Mark block as free */ - HDassert(spc_blk->is_free == FALSE); - spc_blk->is_free = TRUE; - - /* Add it's space to the amount of free space in the page & pool */ - spc_page = spc_blk->page; - spc_page->free_size += spc_blk->size; - mp->free_size += spc_blk->size; - - /* Move page with newly freed space to front of list of pages in pool */ - if (spc_page != mp->first) { - /* Remove page from list */ - spc_page->prev->next = spc_page->next; - if (spc_page->next) - spc_page->next->prev = spc_page->prev; - - /* Insert page at beginning of list */ - spc_page->prev = NULL; - spc_page->next = mp->first; - mp->first->prev = spc_page; - mp->first = spc_page; - } /* end if */ - - /* Check if block can be merged with free space after it on page */ - if (spc_blk->next != NULL) { - H5MP_page_blk_t *next_blk; /* Block following space to free */ - - next_blk = spc_blk->next; - HDassert(next_blk->prev == spc_blk); - if (next_blk->is_free) { - spc_blk->size += next_blk->size; - spc_blk->next = next_blk->next; - } /* end if */ - } /* end if */ - - /* Check if block can be merged with free space before it on page */ - if (spc_blk->prev != NULL) { - H5MP_page_blk_t *prev_blk; /* Block before space to free */ - - prev_blk = spc_blk->prev; - HDassert(prev_blk->next == spc_blk); - if (prev_blk->is_free) { - prev_blk->size += spc_blk->size; - prev_blk->next = spc_blk->next; - } /* end if */ - } /* end if */ - - /* Check if the block freed becomes the first free block on the page */ - if (spc_page->free_blk == NULL || spc_blk < spc_page->free_blk) - spc_page->free_blk = spc_blk; - - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5MP_free() */ - -/*------------------------------------------------------------------------- - * Function: H5MP_close - * - * Purpose: Release all memory for a pool and destroy pool - * - * Return: Non-negative on success/negative on failure - * - * Programmer: Quincey Koziol - * May 3 2005 - * - *------------------------------------------------------------------------- - */ -herr_t -H5MP_close(H5MP_pool_t *mp) -{ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(FAIL) - - /* Release memory for pool pages */ - if (mp->first != NULL) { - H5MP_page_t *page, *next_page; /* Pointer to pages in pool */ - - /* Iterate through pages, releasing them */ - page = mp->first; - while (page) { - next_page = page->next; - - /* Free the page appropriately */ - if (page->fac_alloc) - page = (H5MP_page_t *)H5FL_FAC_FREE(mp->page_fac, page); - else - page = (H5MP_page_t *)H5MM_xfree(page); - - page = next_page; - } /* end while */ - } /* end if */ - - /* Release page factory */ - if (mp->page_fac) - if (H5FL_fac_term(mp->page_fac) < 0) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't destroy page factory") - -done: - /* Free the memory pool itself */ - mp = H5FL_FREE(H5MP_pool_t, mp); - - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5MP_close() */ diff --git a/src/H5MPmodule.h b/src/H5MPmodule.h deleted file mode 100644 index 8e34598..0000000 --- a/src/H5MPmodule.h +++ /dev/null @@ -1,32 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * 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 COPYING file, which can be found at the root of the source code * - * distribution tree, or in https://www.hdfgroup.org/licenses. * - * If you do not have access to either file, you may request a copy from * - * help@hdfgroup.org. * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/* - * Programmer: Quincey Koziol - * Saturday, September 12, 2015 - * - * Purpose: This file contains declarations which define macros for the - * H5MP package. Including this header means that the source file - * is part of the H5MP package. - */ -#ifndef H5MPmodule_H -#define H5MPmodule_H - -/* Define the proper control macros for the generic FUNC_ENTER/LEAVE and error - * reporting macros. - */ -#define H5MP_MODULE -#define H5_MY_PKG H5MP -#define H5_MY_PKG_ERR H5E_RESOURCE -#define H5_MY_PKG_INIT NO - -#endif /* H5MPmodule_H */ diff --git a/src/H5MPpkg.h b/src/H5MPpkg.h deleted file mode 100644 index 64c5293..0000000 --- a/src/H5MPpkg.h +++ /dev/null @@ -1,99 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * 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 COPYING file, which can be found at the root of the source code * - * distribution tree, or in https://www.hdfgroup.org/licenses. * - * If you do not have access to either file, you may request a copy from * - * help@hdfgroup.org. * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/* - * Programmer: Quincey Koziol - * Monday, May 2, 2005 - * - * Purpose: This file contains declarations which are visible only within - * the H5MP package. Source files outside the H5MP package should - * include H5MPprivate.h instead. - */ -#if !(defined H5MP_FRIEND || defined H5MP_MODULE) -#error "Do not include this file outside the H5MP package!" -#endif - -#ifndef H5MPpkg_H -#define H5MPpkg_H - -/* Get package's private header */ -#include "H5MPprivate.h" /* Memory Pools */ - -/* Other private headers needed by this file */ -#include "H5FLprivate.h" /* Free Lists */ - -/**************************/ -/* Package Private Macros */ -/**************************/ - -/* Alignment macros */ -/* (Ideas from Apache APR :-) */ - -/* Default alignment necessary */ -#define H5MP_BLOCK_ALIGNMENT 8 - -/* General alignment macro */ -/* (this only works for aligning to power of 2 boundary) */ -#define H5MP_ALIGN(x, a) (((x) + ((size_t)(a)) - 1) & ~(((size_t)(a)) - 1)) - -/* Default alignment */ -#define H5MP_BLOCK_ALIGN(x) H5MP_ALIGN(x, H5MP_BLOCK_ALIGNMENT) - -/****************************/ -/* Package Private Typedefs */ -/****************************/ - -/* Free block in pool */ -typedef struct H5MP_page_blk_t { - size_t size; /* Size of block (includes this H5MP_page_blk_t info) */ - unsigned is_free : 1; /* Flag to indicate the block is free */ - struct H5MP_page_t * page; /* Pointer to page block is located in */ - struct H5MP_page_blk_t *prev; /* Pointer to previous block in page */ - struct H5MP_page_blk_t *next; /* Pointer to next block in page */ -} H5MP_page_blk_t; - -/* Memory pool page */ -typedef struct H5MP_page_t { - size_t free_size; /* Total amount of free space in page */ - unsigned fac_alloc : 1; /* Flag to indicate the page was allocated by the pool's factory */ - H5MP_page_blk_t * free_blk; /* Pointer to first free block in page */ - struct H5MP_page_t *next; /* Pointer to next page in pool */ - struct H5MP_page_t *prev; /* Pointer to previous page in pool */ -} H5MP_page_t; - -/* Memory pool header */ -struct H5MP_pool_t { - H5FL_fac_head_t *page_fac; /* Free-list factory for pages */ - size_t page_size; /* Page size for pool */ - size_t free_size; /* Total amount of free space in pool */ - size_t max_size; /* Maximum block that will fit in a standard page */ - H5MP_page_t * first; /* Pointer to first page in pool */ - unsigned flags; /* Bit flags for pool settings */ -}; - -/*****************************************/ -/* Package Private Variable Declarations */ -/*****************************************/ - -/******************************/ -/* Package Private Prototypes */ -/******************************/ -#ifdef H5MP_TESTING -H5_DLL herr_t H5MP_get_pool_free_size(const H5MP_pool_t *mp, size_t *free_size); -H5_DLL htri_t H5MP_pool_is_free_size_correct(const H5MP_pool_t *mp); -H5_DLL herr_t H5MP_get_pool_first_page(const H5MP_pool_t *mp, H5MP_page_t **page); -H5_DLL herr_t H5MP_get_page_free_size(const H5MP_page_t *mp, size_t *page); -H5_DLL herr_t H5MP_get_page_next_page(const H5MP_page_t *page, H5MP_page_t **next_page); -#endif /* H5MP_TESTING */ - -#endif /* H5MPpkg_H */ diff --git a/src/H5MPprivate.h b/src/H5MPprivate.h deleted file mode 100644 index 2b06650..0000000 --- a/src/H5MPprivate.h +++ /dev/null @@ -1,57 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * 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 COPYING file, which can be found at the root of the source code * - * distribution tree, or in https://www.hdfgroup.org/licenses. * - * If you do not have access to either file, you may request a copy from * - * help@hdfgroup.org. * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/*------------------------------------------------------------------------- - * - * Created: H5MPprivate.h - * May 2 2005 - * Quincey Koziol - * - * Purpose: Private header for memory pool routines. - * - *------------------------------------------------------------------------- - */ - -#ifndef H5MPprivate_H -#define H5MPprivate_H - -/* Include package's public header (not yet) */ -/* #include "H5MPpublic.h" */ - -/* Private headers needed by this file */ - -/**************************/ -/* Library Private Macros */ -/**************************/ - -/* Pool creation flags */ -/* Default settings */ -#define H5MP_FLG_DEFAULT 0 -#define H5MP_PAGE_SIZE_DEFAULT 4096 /* (bytes) */ - -/****************************/ -/* Library Private Typedefs */ -/****************************/ - -/* Memory pool header (defined in H5MPpkg.c) */ -typedef struct H5MP_pool_t H5MP_pool_t; - -/***************************************/ -/* Library-private Function Prototypes */ -/***************************************/ -H5_DLL H5MP_pool_t *H5MP_create(size_t page_size, unsigned flags); -H5_DLL void * H5MP_malloc(H5MP_pool_t *mp, size_t request); -H5_DLL void * H5MP_free(H5MP_pool_t *mp, void *spc); -H5_DLL herr_t H5MP_close(H5MP_pool_t *mp); - -#endif /* H5MPprivate_H */ diff --git a/src/H5MPtest.c b/src/H5MPtest.c deleted file mode 100644 index 27e7bbe..0000000 --- a/src/H5MPtest.c +++ /dev/null @@ -1,213 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * 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 COPYING file, which can be found at the root of the source code * - * distribution tree, or in https://www.hdfgroup.org/licenses. * - * If you do not have access to either file, you may request a copy from * - * help@hdfgroup.org. * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/* Programmer: Quincey Koziol - * Tuesday, May 3, 2005 - * - * Purpose: Memory pool testing functions. - */ - -#include "H5MPmodule.h" /* This source code file is part of the H5MP module */ -#define H5MP_TESTING /*include H5MP testing funcs*/ - -/* Private headers */ -#include "H5private.h" /* Generic Functions */ -#include "H5MPpkg.h" /* Memory Pools */ -#include "H5Eprivate.h" /* Error handling */ - -/* Static Prototypes */ - -/* Package variables */ - -/*------------------------------------------------------------------------- - * Function: H5MP_get_pool_free_size - * - * Purpose: Retrieve the total amount of free space in entire pool - * - * Return: Success: non-negative - * - * Failure: negative - * - * Programmer: Quincey Koziol - * Tuesday, May 3, 2005 - * - *------------------------------------------------------------------------- - */ -herr_t -H5MP_get_pool_free_size(const H5MP_pool_t *mp, size_t *free_size) -{ - FUNC_ENTER_NOAPI_NOINIT_NOERR - - /* Check arguments. */ - HDassert(mp); - HDassert(free_size); - - /* Get memory pool's free space */ - *free_size = mp->free_size; - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5MP_get_pool_free_size() */ - -/*------------------------------------------------------------------------- - * Function: H5MP_get_pool_first_page - * - * Purpose: Retrieve the first page in a memory pool - * - * Return: Success: non-negative - * - * Failure: negative - * - * Programmer: Quincey Koziol - * Tuesday, May 3, 2005 - * - *------------------------------------------------------------------------- - */ -herr_t -H5MP_get_pool_first_page(const H5MP_pool_t *mp, H5MP_page_t **page) -{ - FUNC_ENTER_NOAPI_NOINIT_NOERR - - /* Check arguments. */ - HDassert(mp); - HDassert(page); - - /* Get memory pool's first page */ - *page = mp->first; - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5MP_get_pool_first_page() */ - -/*------------------------------------------------------------------------- - * Function: H5MP_pool_is_free_size_correct - * - * Purpose: Check that the free space reported in each page corresponds - * to the free size in each page and that the free space in the - * free blocks for a page corresponds with the free space for - * the page. - * - * Return: Success: non-negative - * - * Failure: negative - * - * Programmer: Quincey Koziol - * Wednesday, May 3, 2005 - * - *------------------------------------------------------------------------- - */ -htri_t -H5MP_pool_is_free_size_correct(const H5MP_pool_t *mp) -{ - H5MP_page_t *page; /* Pointer to current page */ - size_t pool_free; /* Size of pages' free space */ - htri_t ret_value = TRUE; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT_NOERR - - /* Check arguments. */ - HDassert(mp); - - /* Iterate through pages, checking the free size & accumulating the - * free space for all the pages */ - page = mp->first; - pool_free = 0; - while (page != NULL) { - H5MP_page_blk_t *blk; /* Pointer to current free block */ - size_t page_free; /* Size of blocks on free list */ - - /* Iterate through the blocks in page, accumulating free space */ - blk = (H5MP_page_blk_t *)((void *)((unsigned char *)page + H5MP_BLOCK_ALIGN(sizeof(H5MP_page_t)))); - page_free = 0; - while (blk != NULL) { - if (blk->is_free) - page_free += blk->size; - blk = blk->next; - } /* end while */ - - /* Check that the free space from the blocks on the free list - * corresponds to space in page */ - if (page_free != page->free_size) - HGOTO_DONE(FALSE) - - /* Increment the amount of free space in pool */ - pool_free += page->free_size; - - /* Advance to next page */ - page = page->next; - } /* end while */ - - /* Check that the free space from the pages - * corresponds to free space in pool */ - if (pool_free != mp->free_size) - HGOTO_DONE(FALSE) - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5MP_pool_is_free_size_correct() */ - -/*------------------------------------------------------------------------- - * Function: H5MP_get_page_free_size - * - * Purpose: Retrieve the amount of free space in given page - * - * Return: Success: non-negative - * - * Failure: negative - * - * Programmer: Quincey Koziol - * Tuesday, May 3, 2005 - * - *------------------------------------------------------------------------- - */ -herr_t -H5MP_get_page_free_size(const H5MP_page_t *page, size_t *free_size) -{ - FUNC_ENTER_NOAPI_NOINIT_NOERR - - /* Check arguments. */ - HDassert(page); - HDassert(free_size); - - /* Get memory page's free space */ - *free_size = page->free_size; - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5MP_get_page_free_size() */ - -/*------------------------------------------------------------------------- - * Function: H5MP_get_page_next_page - * - * Purpose: Retrieve the next page in the pool - * - * Return: Success: non-negative - * - * Failure: negative - * - * Programmer: Quincey Koziol - * Tuesday, May 3, 2005 - * - *------------------------------------------------------------------------- - */ -herr_t -H5MP_get_page_next_page(const H5MP_page_t *page, H5MP_page_t **next_page) -{ - FUNC_ENTER_NOAPI_NOINIT_NOERR - - /* Check arguments. */ - HDassert(page); - HDassert(next_page); - - /* Get next memory page */ - *next_page = page->next; - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5MP_get_page_next_page() */ diff --git a/src/H5Oainfo.c b/src/H5Oainfo.c index 10c9ede..03ea3df 100644 --- a/src/H5Oainfo.c +++ b/src/H5Oainfo.c @@ -52,7 +52,7 @@ const H5O_msg_class_t H5O_MSG_AINFO[1] = {{ H5O_AINFO_ID, /*message id number */ "ainfo", /*message name for debugging */ sizeof(H5O_ainfo_t), /*native message size */ - 0, /* messages are sharable? */ + 0, /* messages are shareable? */ H5O__ainfo_decode, /*decode message */ H5O__ainfo_encode, /*encode message */ H5O__ainfo_copy, /*copy the native value */ diff --git a/src/H5Oattr.c b/src/H5Oattr.c index db53eaf..83c0370 100644 --- a/src/H5Oattr.c +++ b/src/H5Oattr.c @@ -65,7 +65,7 @@ const H5O_msg_class_t H5O_MSG_ATTR[1] = {{ H5O_ATTR_ID, /* message id number */ "attribute", /* message name for debugging */ sizeof(H5A_t), /* native message size */ - H5O_SHARE_IS_SHARABLE, /* messages are sharable? */ + H5O_SHARE_IS_SHARABLE, /* messages are shareable? */ H5O__attr_shared_decode, /* decode message */ H5O__attr_shared_encode, /* encode message */ H5O__attr_copy, /* copy the native value */ diff --git a/src/H5Oattribute.c b/src/H5Oattribute.c index 6ca4204..b83b57e 100644 --- a/src/H5Oattribute.c +++ b/src/H5Oattribute.c @@ -248,19 +248,19 @@ H5O__attr_create(const H5O_loc_t *loc, H5A_t *attr) /* Check if switching to "dense" attribute storage is possible */ if (!H5F_addr_defined(ainfo.fheap_addr)) { - htri_t sharable; /* Whether the attribute will be shared */ + htri_t shareable; /* Whether the attribute will be shared */ size_t raw_size = 0; /* Raw size of message */ - /* Check for attribute being sharable */ - if ((sharable = H5SM_can_share(loc->file, NULL, NULL, H5O_ATTR_ID, attr)) < 0) + /* Check for attribute being shareable */ + if ((shareable = H5SM_can_share(loc->file, NULL, NULL, H5O_ATTR_ID, attr)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_BADMESG, FAIL, "can't determine attribute sharing status") - else if (sharable == FALSE) { + else if (shareable == FALSE) { /* Compute the size needed to encode the attribute */ raw_size = (H5O_MSG_ATTR->raw_size)(loc->file, FALSE, attr); } /* end if */ /* Check for condititions for switching to "dense" attribute storage are met */ - if (ainfo.nattrs == oh->max_compact || (!sharable && raw_size >= H5O_MESG_MAX_SIZE)) { + if (ainfo.nattrs == oh->max_compact || (!shareable && raw_size >= H5O_MESG_MAX_SIZE)) { H5O_iter_cvt_t udata; /* User data for callback */ H5O_mesg_operator_t op; /* Wrapper for operator */ diff --git a/src/H5Obogus.c b/src/H5Obogus.c index c7fcdb9..ea231d6 100644 --- a/src/H5Obogus.c +++ b/src/H5Obogus.c @@ -47,7 +47,7 @@ const H5O_msg_class_t H5O_MSG_BOGUS_VALID[1] = {{ H5O_BOGUS_VALID_ID, /*message id number */ "bogus valid", /*message name for debugging */ 0, /*native message size */ - H5O_SHARE_IS_SHARABLE, /* messages are sharable? */ + H5O_SHARE_IS_SHARABLE, /* messages are shareable? */ H5O__bogus_decode, /*decode message */ H5O__bogus_encode, /*encode message */ NULL, /*copy the native value */ @@ -71,7 +71,7 @@ const H5O_msg_class_t H5O_MSG_BOGUS_INVALID[1] = {{ H5O_BOGUS_INVALID_ID, /*message id number */ "bogus invalid", /*message name for debugging */ 0, /*native message size */ - H5O_SHARE_IS_SHARABLE, /* messages are sharable? */ + H5O_SHARE_IS_SHARABLE, /* messages are shareable? */ H5O__bogus_decode, /*decode message */ H5O__bogus_encode, /*encode message */ NULL, /*copy the native value */ diff --git a/src/H5Obtreek.c b/src/H5Obtreek.c index a783366..1eaf3e5 100644 --- a/src/H5Obtreek.c +++ b/src/H5Obtreek.c @@ -37,7 +37,7 @@ const H5O_msg_class_t H5O_MSG_BTREEK[1] = {{ H5O_BTREEK_ID, /*message id number */ "v1 B-tree 'K' values", /*message name for debugging */ sizeof(H5O_btreek_t), /*native message size */ - 0, /* messages are sharable? */ + 0, /* messages are shareable? */ H5O__btreek_decode, /*decode message */ H5O__btreek_encode, /*encode message */ H5O__btreek_copy, /*copy the native value */ diff --git a/src/H5Ocache.c b/src/H5Ocache.c index 3aae0cb..c7586cc 100644 --- a/src/H5Ocache.c +++ b/src/H5Ocache.c @@ -275,7 +275,7 @@ H5O__cache_verify_chksum(const void *_image, size_t len, void *_udata) * * Note that the object header is read with with a speculative read. * If the initial read is too small, make note of this fact and return - * without error. H5C__load_entry() will note the size discrepency + * without error. H5C__load_entry() will note the size discrepancy * and retry the deserialize operation with the correct size read. * * Return: Success: Pointer to in core representation @@ -346,7 +346,7 @@ H5O__cache_deserialize(const void *image, size_t len, void *_udata, hbool_t *dir done: /* Release the [possibly partially initialized] object header on errors */ if (!ret_value && oh) - if (H5O__free(oh) < 0) + if (H5O__free(oh, FALSE) < 0) HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, NULL, "unable to destroy object header data") FUNC_LEAVE_NOAPI(ret_value) @@ -639,7 +639,7 @@ H5O__cache_free_icr(void *_thing) HDassert(oh->cache_info.type == H5AC_OHDR); /* Destroy object header */ - if (H5O__free(oh) < 0) + if (H5O__free(oh, FALSE) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "can't destroy object header") done: @@ -1242,7 +1242,7 @@ H5O__prefix_deserialize(const uint8_t *_image, H5O_cache_ud_t *udata) /* Save the object header for later use in 'deserialize' callback */ udata->oh = oh; - if (H5O__free(saved_oh) < 0) + if (H5O__free(saved_oh, FALSE) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "can't destroy object header") udata->free_oh = FALSE; } @@ -1255,7 +1255,7 @@ H5O__prefix_deserialize(const uint8_t *_image, H5O_cache_ud_t *udata) done: /* Release the [possibly partially initialized] object header on errors */ if (ret_value < 0 && oh) - if (H5O__free(oh) < 0) + if (H5O__free(oh, FALSE) < 0) HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to destroy object header data") FUNC_LEAVE_NOAPI(ret_value) diff --git a/src/H5Ocache_image.c b/src/H5Ocache_image.c index 2603f71..8f60a0e 100644 --- a/src/H5Ocache_image.c +++ b/src/H5Ocache_image.c @@ -51,7 +51,7 @@ const H5O_msg_class_t H5O_MSG_MDCI[1] = {{ H5O_MDCI_MSG_ID, /* message id number */ "mdci", /* message name for debugging */ sizeof(H5O_mdci_t), /* native message size */ - 0, /* messages are sharable? */ + 0, /* messages are shareable? */ H5O__mdci_decode, /* decode message */ H5O__mdci_encode, /* encode message */ H5O__mdci_copy, /* copy method */ diff --git a/src/H5Ocont.c b/src/H5Ocont.c index 080225a..9dd04fe 100644 --- a/src/H5Ocont.c +++ b/src/H5Ocont.c @@ -47,7 +47,7 @@ const H5O_msg_class_t H5O_MSG_CONT[1] = {{ H5O_CONT_ID, /*message id number */ "hdr continuation", /*message name for debugging */ sizeof(H5O_cont_t), /*native message size */ - 0, /* messages are sharable? */ + 0, /* messages are shareable? */ H5O__cont_decode, /*decode message */ H5O__cont_encode, /*encode message */ NULL, /*no copy method */ diff --git a/src/H5Ocopy.c b/src/H5Ocopy.c index e31db41..0b0bb55 100644 --- a/src/H5Ocopy.c +++ b/src/H5Ocopy.c @@ -33,7 +33,6 @@ #include "H5Aprivate.h" /* Attributes */ #include "H5CXprivate.h" /* API Contexts */ #include "H5Eprivate.h" /* Error handling */ -#include "H5ESprivate.h" /* Event Sets */ #include "H5FLprivate.h" /* Free lists */ #include "H5Iprivate.h" /* IDs */ #include "H5HGprivate.h" /* Global Heaps */ @@ -772,7 +771,7 @@ done: /* Free destination object header on failure */ if (ret_value < 0) { if (oh_dst && !inserted) { - if (H5O__free(oh_dst) < 0) + if (H5O__free(oh_dst, TRUE) < 0) HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy object header data") if (H5O_loc_reset(oloc_dst) < 0) HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy object header data") @@ -963,7 +962,7 @@ H5O__copy_header(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, hid_t if (H5P_get(ocpy_plist, H5O_CPY_OPTION_NAME, &cpy_option) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get object copy flag") - /* Retrieve the marge committed datatype list */ + /* Retrieve the merge committed datatype list */ if (H5P_peek(ocpy_plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &dt_list) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get merge committed datatype list") diff --git a/src/H5Ocopy_ref.c b/src/H5Ocopy_ref.c index f1f8aaf..1cda3ea 100644 --- a/src/H5Ocopy_ref.c +++ b/src/H5Ocopy_ref.c @@ -288,21 +288,22 @@ H5O__copy_expand_ref_object2(H5O_loc_t *src_oloc, hid_t tid_src, const H5T_t *dt size_t nbytes_src, H5O_loc_t *dst_oloc, H5G_loc_t *dst_root_loc, void *buf_dst, size_t ref_count, H5O_copy_t *cpy_info) { - H5T_t * dt_mem = NULL; /* Memory datatype */ - H5T_t * dt_dst = NULL; /* Destination datatype */ - hid_t tid_mem = H5I_INVALID_HID; /* Datatype ID for memory datatype */ - hid_t tid_dst = H5I_INVALID_HID; /* Datatype ID for memory datatype */ - H5T_path_t *tpath_src_mem = NULL, *tpath_mem_dst = NULL; /* Datatype conversion paths */ - size_t i; /* Local index variable */ - hbool_t reg_tid_src = (tid_src == H5I_INVALID_HID); - hid_t dst_loc_id = H5I_INVALID_HID; - void * conv_buf = NULL; /* Buffer for converting data */ - size_t conv_buf_size = 0; /* Buffer size */ - void * reclaim_buf = NULL; /* Buffer for reclaiming data */ - H5S_t * buf_space = NULL; /* Dataspace describing buffer */ - hsize_t buf_dim[1] = {ref_count}; /* Dimension for buffer */ - size_t token_size = H5F_SIZEOF_ADDR(src_oloc->file); - herr_t ret_value = SUCCEED; + H5T_t * dt_mem = NULL; /* Memory datatype */ + H5T_t * dt_dst = NULL; /* Destination datatype */ + hid_t tid_mem = H5I_INVALID_HID; /* Datatype ID for memory datatype */ + hid_t tid_dst = H5I_INVALID_HID; /* Datatype ID for memory datatype */ + H5T_path_t * tpath_src_mem = NULL, *tpath_mem_dst = NULL; /* Datatype conversion paths */ + size_t i; /* Local index variable */ + hbool_t reg_tid_src = (tid_src == H5I_INVALID_HID); + hid_t dst_loc_id = H5I_INVALID_HID; + void * conv_buf = NULL; /* Buffer for converting data */ + size_t conv_buf_size = 0; /* Buffer size */ + void * reclaim_buf = NULL; /* Buffer for reclaiming data */ + H5S_t * buf_space = NULL; /* Dataspace describing buffer */ + hsize_t buf_dim[1] = {ref_count}; /* Dimension for buffer */ + size_t token_size = H5F_SIZEOF_ADDR(src_oloc->file); + const unsigned char zeros[H5R_REF_BUF_SIZE] = {0}; + herr_t ret_value = SUCCEED; FUNC_ENTER_STATIC @@ -353,29 +354,34 @@ H5O__copy_expand_ref_object2(H5O_loc_t *src_oloc, hid_t tid_src, const H5T_t *dt /* Making equivalent references in the destination file */ for (i = 0; i < ref_count; i++) { - H5R_ref_t * ref_ptr = (H5R_ref_t *)conv_buf; - H5R_ref_priv_t *ref = (H5R_ref_priv_t *)&ref_ptr[i]; - H5O_token_t tmp_token = {0}; - - /* Get src object address */ - if (H5R__get_obj_token(ref, &tmp_token, &token_size) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to get object token") - if (H5VL_native_token_to_addr(src_oloc->file, H5I_FILE, tmp_token, &src_oloc->addr) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTUNSERIALIZE, FAIL, "can't deserialize object token into address") - - /* Attempt to copy object from source to destination file */ - if (H5O__copy_obj_by_ref(src_oloc, dst_oloc, dst_root_loc, cpy_info) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object") - - /* Set dst object address */ - if (H5VL_native_addr_to_token(dst_oloc->file, H5I_FILE, dst_oloc->addr, &tmp_token) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTSERIALIZE, FAIL, "can't serialize address into object token") - if (H5R__set_obj_token(ref, (const H5O_token_t *)&tmp_token, token_size) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "unable to set object token") - /* Do not set app_ref since references are released once the copy is done */ - if (H5R__set_loc_id(ref, dst_loc_id, TRUE, FALSE) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "unable to set destination loc id") - } /* end for */ + H5R_ref_t * ref_ptr = (H5R_ref_t *)conv_buf; + H5R_ref_priv_t *ref = (H5R_ref_priv_t *)&ref_ptr[i]; + + /* Check for null reference - only expand reference if it is not null */ + if (HDmemcmp(ref, zeros, H5R_REF_BUF_SIZE)) { + H5O_token_t tmp_token = {0}; + + /* Get src object address */ + if (H5R__get_obj_token(ref, &tmp_token, &token_size) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to get object token") + if (H5VL_native_token_to_addr(src_oloc->file, H5I_FILE, tmp_token, &src_oloc->addr) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTUNSERIALIZE, FAIL, + "can't deserialize object token into address") + + /* Attempt to copy object from source to destination file */ + if (H5O__copy_obj_by_ref(src_oloc, dst_oloc, dst_root_loc, cpy_info) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object") + + /* Set dst object address */ + if (H5VL_native_addr_to_token(dst_oloc->file, H5I_FILE, dst_oloc->addr, &tmp_token) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTSERIALIZE, FAIL, "can't serialize address into object token") + if (H5R__set_obj_token(ref, (const H5O_token_t *)&tmp_token, token_size) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "unable to set object token") + /* Do not set app_ref since references are released once the copy is done */ + if (H5R__set_loc_id(ref, dst_loc_id, TRUE, FALSE) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "unable to set destination loc id") + } /* end if */ + } /* end for */ /* Copy into another buffer, to reclaim memory later */ if (NULL == (reclaim_buf = H5FL_BLK_MALLOC(type_conv, conv_buf_size))) diff --git a/src/H5Odrvinfo.c b/src/H5Odrvinfo.c index 8bebc6d..69ab5b2 100644 --- a/src/H5Odrvinfo.c +++ b/src/H5Odrvinfo.c @@ -38,7 +38,7 @@ const H5O_msg_class_t H5O_MSG_DRVINFO[1] = {{ H5O_DRVINFO_ID, /*message id number */ "driver info", /*message name for debugging */ sizeof(H5O_drvinfo_t), /*native message size */ - 0, /* messages are sharable? */ + 0, /* messages are shareable? */ H5O__drvinfo_decode, /*decode message */ H5O__drvinfo_encode, /*encode message */ H5O__drvinfo_copy, /*copy the native value */ diff --git a/src/H5Odtype.c b/src/H5Odtype.c index 1be9522..9af79f4 100644 --- a/src/H5Odtype.c +++ b/src/H5Odtype.c @@ -89,7 +89,7 @@ const H5O_msg_class_t H5O_MSG_DTYPE[1] = {{ H5O_DTYPE_ID, /* message id number */ "datatype", /* message name for debugging */ sizeof(H5T_t), /* native message size */ - H5O_SHARE_IS_SHARABLE | H5O_SHARE_IN_OHDR, /* messages are sharable? */ + H5O_SHARE_IS_SHARABLE | H5O_SHARE_IN_OHDR, /* messages are shareable? */ H5O__dtype_shared_decode, /* decode message */ H5O__dtype_shared_encode, /* encode message */ H5O__dtype_copy, /* copy the native value */ @@ -1731,7 +1731,7 @@ H5O__dtype_debug(H5F_t *f, const void *mesg, FILE *stream, int indent, int fwidt case H5T_NO_CLASS: case H5T_NCLASSES: default: - HDsprintf(buf, "H5T_CLASS_%d", (int)(dt->shared->type)); + HDsnprintf(buf, sizeof(buf), "H5T_CLASS_%d", (int)(dt->shared->type)); s = buf; break; } /* end switch */ @@ -1746,7 +1746,7 @@ H5O__dtype_debug(H5F_t *f, const void *mesg, FILE *stream, int indent, int fwidt HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, "Number of members:", dt->shared->u.compnd.nmembs); for (i = 0; i < dt->shared->u.compnd.nmembs; i++) { - HDsprintf(buf, "Member %u:", i); + HDsnprintf(buf, sizeof(buf), "Member %u:", i); HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, buf, dt->shared->u.compnd.memb[i].name); HDfprintf(stream, "%*s%-*s %lu\n", indent + 3, "", MAX(0, fwidth - 3), "Byte offset:", (unsigned long)(dt->shared->u.compnd.memb[i].offset)); @@ -1759,7 +1759,7 @@ H5O__dtype_debug(H5F_t *f, const void *mesg, FILE *stream, int indent, int fwidt HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, "Number of members:", dt->shared->u.enumer.nmembs); for (i = 0; i < dt->shared->u.enumer.nmembs; i++) { - HDsprintf(buf, "Member %u:", i); + HDsnprintf(buf, sizeof(buf), "Member %u:", i); HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, buf, dt->shared->u.enumer.name[i]); HDfprintf(stream, "%*s%-*s 0x", indent, "", fwidth, "Raw bytes of value:"); for (k = 0; k < dt->shared->parent->shared->size; k++) @@ -1799,13 +1799,14 @@ H5O__dtype_debug(H5F_t *f, const void *mesg, FILE *stream, int indent, int fwidt case H5T_CSET_RESERVED_13: case H5T_CSET_RESERVED_14: case H5T_CSET_RESERVED_15: - HDsprintf(buf, "H5T_CSET_RESERVED_%d", (int)(dt->shared->u.atomic.u.s.cset)); + HDsnprintf(buf, sizeof(buf), "H5T_CSET_RESERVED_%d", (int)(dt->shared->u.atomic.u.s.cset)); s = buf; break; case H5T_CSET_ERROR: default: - HDsprintf(buf, "Unknown character set: %d", (int)(dt->shared->u.atomic.u.s.cset)); + HDsnprintf(buf, sizeof(buf), "Unknown character set: %d", + (int)(dt->shared->u.atomic.u.s.cset)); s = buf; break; } /* end switch */ @@ -1837,13 +1838,14 @@ H5O__dtype_debug(H5F_t *f, const void *mesg, FILE *stream, int indent, int fwidt case H5T_STR_RESERVED_13: case H5T_STR_RESERVED_14: case H5T_STR_RESERVED_15: - HDsprintf(buf, "H5T_STR_RESERVED_%d", (int)(dt->shared->u.atomic.u.s.pad)); + HDsnprintf(buf, sizeof(buf), "H5T_STR_RESERVED_%d", (int)(dt->shared->u.atomic.u.s.pad)); s = buf; break; case H5T_STR_ERROR: default: - HDsprintf(buf, "Unknown string padding: %d", (int)(dt->shared->u.atomic.u.s.pad)); + HDsnprintf(buf, sizeof(buf), "Unknown string padding: %d", + (int)(dt->shared->u.atomic.u.s.pad)); s = buf; break; } /* end switch */ @@ -1862,7 +1864,7 @@ H5O__dtype_debug(H5F_t *f, const void *mesg, FILE *stream, int indent, int fwidt case H5T_VLEN_BADTYPE: case H5T_VLEN_MAXTYPE: default: - HDsprintf(buf, "H5T_VLEN_%d", dt->shared->u.vlen.type); + HDsnprintf(buf, sizeof(buf), "H5T_VLEN_%d", dt->shared->u.vlen.type); s = buf; break; } /* end switch */ @@ -1880,7 +1882,7 @@ H5O__dtype_debug(H5F_t *f, const void *mesg, FILE *stream, int indent, int fwidt case H5T_LOC_BADLOC: case H5T_LOC_MAXLOC: default: - HDsprintf(buf, "H5T_LOC_%d", (int)dt->shared->u.vlen.loc); + HDsnprintf(buf, sizeof(buf), "H5T_LOC_%d", (int)dt->shared->u.vlen.loc); s = buf; break; } /* end switch */ @@ -1911,13 +1913,13 @@ H5O__dtype_debug(H5F_t *f, const void *mesg, FILE *stream, int indent, int fwidt case H5T_CSET_RESERVED_13: case H5T_CSET_RESERVED_14: case H5T_CSET_RESERVED_15: - HDsprintf(buf, "H5T_CSET_RESERVED_%d", (int)(dt->shared->u.vlen.cset)); + HDsnprintf(buf, sizeof(buf), "H5T_CSET_RESERVED_%d", (int)(dt->shared->u.vlen.cset)); s = buf; break; case H5T_CSET_ERROR: default: - HDsprintf(buf, "Unknown character set: %d", (int)(dt->shared->u.vlen.cset)); + HDsnprintf(buf, sizeof(buf), "Unknown character set: %d", (int)(dt->shared->u.vlen.cset)); s = buf; break; } /* end switch */ @@ -1949,13 +1951,13 @@ H5O__dtype_debug(H5F_t *f, const void *mesg, FILE *stream, int indent, int fwidt case H5T_STR_RESERVED_13: case H5T_STR_RESERVED_14: case H5T_STR_RESERVED_15: - HDsprintf(buf, "H5T_STR_RESERVED_%d", (int)(dt->shared->u.vlen.pad)); + HDsnprintf(buf, sizeof(buf), "H5T_STR_RESERVED_%d", (int)(dt->shared->u.vlen.pad)); s = buf; break; case H5T_STR_ERROR: default: - HDsprintf(buf, "Unknown string padding: %d", (int)(dt->shared->u.vlen.pad)); + HDsnprintf(buf, sizeof(buf), "Unknown string padding: %d", (int)(dt->shared->u.vlen.pad)); s = buf; break; } /* end switch */ @@ -1995,7 +1997,7 @@ H5O__dtype_debug(H5F_t *f, const void *mesg, FILE *stream, int indent, int fwidt case H5T_ORDER_ERROR: default: - HDsprintf(buf, "H5T_ORDER_%d", dt->shared->u.atomic.order); + HDsnprintf(buf, sizeof(buf), "H5T_ORDER_%d", dt->shared->u.atomic.order); s = buf; break; } /* end switch */ @@ -2069,9 +2071,9 @@ H5O__dtype_debug(H5F_t *f, const void *mesg, FILE *stream, int indent, int fwidt case H5T_NPAD: default: if (dt->shared->u.atomic.u.f.pad < 0) - HDsprintf(buf, "H5T_PAD_%d", -(dt->shared->u.atomic.u.f.pad)); + HDsnprintf(buf, sizeof(buf), "H5T_PAD_%d", -(dt->shared->u.atomic.u.f.pad)); else - HDsprintf(buf, "bit-%d", dt->shared->u.atomic.u.f.pad); + HDsnprintf(buf, sizeof(buf), "bit-%d", dt->shared->u.atomic.u.f.pad); s = buf; break; } /* end switch */ @@ -2092,7 +2094,7 @@ H5O__dtype_debug(H5F_t *f, const void *mesg, FILE *stream, int indent, int fwidt case H5T_NORM_ERROR: default: - HDsprintf(buf, "H5T_NORM_%d", (int)(dt->shared->u.atomic.u.f.norm)); + HDsnprintf(buf, sizeof(buf), "H5T_NORM_%d", (int)(dt->shared->u.atomic.u.f.norm)); s = buf; } /* end switch */ HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Normalization:", s); @@ -2129,7 +2131,7 @@ H5O__dtype_debug(H5F_t *f, const void *mesg, FILE *stream, int indent, int fwidt case H5T_SGN_ERROR: case H5T_NSGN: default: - HDsprintf(buf, "H5T_SGN_%d", (int)(dt->shared->u.atomic.u.i.sign)); + HDsnprintf(buf, sizeof(buf), "H5T_SGN_%d", (int)(dt->shared->u.atomic.u.i.sign)); s = buf; break; } /* end switch */ diff --git a/src/H5Oefl.c b/src/H5Oefl.c index d950249..931fe0b 100644 --- a/src/H5Oefl.c +++ b/src/H5Oefl.c @@ -41,7 +41,7 @@ const H5O_msg_class_t H5O_MSG_EFL[1] = {{ H5O_EFL_ID, /*message id number */ "external file list", /*message name for debugging */ sizeof(H5O_efl_t), /*native message size */ - 0, /* messages are sharable? */ + 0, /* messages are shareable? */ H5O__efl_decode, /*decode message */ H5O__efl_encode, /*encode message */ H5O__efl_copy, /*copy native value */ diff --git a/src/H5Ofill.c b/src/H5Ofill.c index 5068039..d905352 100644 --- a/src/H5Ofill.c +++ b/src/H5Ofill.c @@ -107,7 +107,7 @@ const H5O_msg_class_t H5O_MSG_FILL[1] = {{ H5O_FILL_ID, /*message id number */ "fill", /*message name for debugging */ sizeof(H5O_fill_t), /*native message size */ - H5O_SHARE_IS_SHARABLE | H5O_SHARE_IN_OHDR, /* messages are sharable? */ + H5O_SHARE_IS_SHARABLE | H5O_SHARE_IN_OHDR, /* messages are shareable? */ H5O__fill_shared_decode, /*decode message */ H5O__fill_shared_encode, /*encode message */ H5O__fill_copy, /*copy the native value */ @@ -131,7 +131,7 @@ const H5O_msg_class_t H5O_MSG_FILL_NEW[1] = {{ H5O_FILL_NEW_ID, /*message id number */ "fill_new", /*message name for debugging */ sizeof(H5O_fill_t), /*native message size */ - H5O_SHARE_IS_SHARABLE | H5O_SHARE_IN_OHDR, /* messages are sharable? */ + H5O_SHARE_IS_SHARABLE | H5O_SHARE_IN_OHDR, /* messages are shareable? */ H5O__fill_new_shared_decode, /*decode message */ H5O__fill_new_shared_encode, /*encode message */ H5O__fill_copy, /*copy the native value */ diff --git a/src/H5Ofsinfo.c b/src/H5Ofsinfo.c index b60f589..7253f3e 100644 --- a/src/H5Ofsinfo.c +++ b/src/H5Ofsinfo.c @@ -44,7 +44,7 @@ const H5O_msg_class_t H5O_MSG_FSINFO[1] = {{ H5O_FSINFO_ID, /* message id number */ "fsinfo", /* message name for debugging */ sizeof(H5O_fsinfo_t), /* native message size */ - 0, /* messages are sharable? */ + 0, /* messages are shareable? */ H5O__fsinfo_decode, /* decode message */ H5O__fsinfo_encode, /* encode message */ H5O__fsinfo_copy, /* copy the native value */ @@ -176,7 +176,7 @@ H5O__fsinfo_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh, unsigned H5_ATTR_UNU H5F_DECODE_LENGTH(f, p, fsinfo->threshold); /* Free-space section threshold */ H5F_DECODE_LENGTH(f, p, fsinfo->page_size); /* File space page size */ - UINT16DECODE(p, fsinfo->pgend_meta_thres); /* Page end metdata threshold */ + UINT16DECODE(p, fsinfo->pgend_meta_thres); /* Page end metadata threshold */ H5F_addr_decode(f, &p, &(fsinfo->eoa_pre_fsm_fsalloc)); /* EOA before free-space header and section info */ diff --git a/src/H5Oginfo.c b/src/H5Oginfo.c index 8540cc4..304890c 100644 --- a/src/H5Oginfo.c +++ b/src/H5Oginfo.c @@ -43,7 +43,7 @@ const H5O_msg_class_t H5O_MSG_GINFO[1] = {{ H5O_GINFO_ID, /*message id number */ "ginfo", /*message name for debugging */ sizeof(H5O_ginfo_t), /*native message size */ - 0, /* messages are sharable? */ + 0, /* messages are shareable? */ H5O__ginfo_decode, /*decode message */ H5O__ginfo_encode, /*encode message */ H5O__ginfo_copy, /*copy the native value */ diff --git a/src/H5Oint.c b/src/H5Oint.c index f24d0bb..2348790 100644 --- a/src/H5Oint.c +++ b/src/H5Oint.c @@ -82,9 +82,6 @@ static herr_t H5O__reset_info2(H5O_info2_t *oinfo); /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /* Header message ID to class mapping * * Remember to increment H5O_MSG_TYPES in H5Opkg.h when adding a new @@ -178,21 +175,20 @@ static const H5O_obj_class_t *const H5O_obj_class_g[] = { }; /*------------------------------------------------------------------------- - * Function: H5O__init_package - * - * Purpose: Initialize information specific to H5O interface. - * - * Return: Non-negative on success/Negative on failure + * Function: H5O_init * - * Programmer: Quincey Koziol - * Thursday, January 18, 2007 + * Purpose: Initialize the interface from some other layer. * + * Return: Success: non-negative + * Failure: negative *------------------------------------------------------------------------- */ herr_t -H5O__init_package(void) +H5O_init(void) { - FUNC_ENTER_PACKAGE_NOERR + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOERR /* H5O interface sanity checks */ HDcompile_assert(H5O_MSG_TYPES == NELMTS(H5O_msg_class_g)); @@ -200,8 +196,8 @@ H5O__init_package(void) HDcompile_assert(H5O_UNKNOWN_ID < H5O_MSG_TYPES); - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5O__init_package() */ + FUNC_LEAVE_NOAPI(ret_value) +} /*------------------------------------------------------------------------- * Function: H5O__set_version @@ -293,7 +289,7 @@ H5O_create(H5F_t *f, size_t size_hint, size_t initial_rc, hid_t ocpl_id, H5O_loc HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "Can't apply object header to file") done: - if ((FAIL == ret_value) && (NULL != oh) && (H5O__free(oh) < 0)) + if ((FAIL == ret_value) && (NULL != oh) && (H5O__free(oh, TRUE) < 0)) HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "can't delete object header") FUNC_LEAVE_NOAPI(ret_value) @@ -357,7 +353,7 @@ H5O_create_ohdr(H5F_t *f, hid_t ocpl_id) ret_value = oh; done: - if ((NULL == ret_value) && (NULL != oh) && (H5O__free(oh) < 0)) + if ((NULL == ret_value) && (NULL != oh) && (H5O__free(oh, TRUE) < 0)) HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, NULL, "can't delete object header") FUNC_LEAVE_NOAPI(ret_value) @@ -567,7 +563,7 @@ H5O_open(H5O_loc_t *loc) { herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR /* Check args */ HDassert(loc); @@ -584,7 +580,6 @@ H5O_open(H5O_loc_t *loc) else H5F_INCR_NOPEN_OBJS(loc->file); -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_open() */ @@ -3019,7 +3014,7 @@ H5O_get_proxy(const H5O_t *oh) *------------------------------------------------------------------------- */ herr_t -H5O__free(H5O_t *oh) +H5O__free(H5O_t *oh, hbool_t force) { unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ @@ -3043,10 +3038,12 @@ H5O__free(H5O_t *oh) for (u = 0; u < oh->nmesgs; u++) { #ifndef NDEBUG /* Verify that message is clean, unless it could have been marked - * dirty by decoding */ + * dirty by decoding, or if this is a forced free (in case of + * failure during creation of the object some messages may be dirty) + */ if (oh->ndecode_dirtied && oh->mesg[u].dirty) oh->ndecode_dirtied--; - else + else if (!force) HDassert(oh->mesg[u].dirty == 0); #endif /* NDEBUG */ diff --git a/src/H5Olayout.c b/src/H5Olayout.c index 651e317..c939e72 100644 --- a/src/H5Olayout.c +++ b/src/H5Olayout.c @@ -51,7 +51,7 @@ const H5O_msg_class_t H5O_MSG_LAYOUT[1] = {{ H5O_LAYOUT_ID, /* message id number */ "layout", /* message name for debugging */ sizeof(H5O_layout_t), /* native message size */ - 0, /* messages are sharable? */ + 0, /* messages are shareable? */ H5O__layout_decode, /* decode message */ H5O__layout_encode, /* encode message */ H5O__layout_copy, /* copy the native value */ diff --git a/src/H5Olinfo.c b/src/H5Olinfo.c index 711f199..eacc916 100644 --- a/src/H5Olinfo.c +++ b/src/H5Olinfo.c @@ -53,7 +53,7 @@ const H5O_msg_class_t H5O_MSG_LINFO[1] = {{ H5O_LINFO_ID, /*message id number */ "linfo", /*message name for debugging */ sizeof(H5O_linfo_t), /*native message size */ - 0, /* messages are sharable? */ + 0, /* messages are shareable? */ H5O__linfo_decode, /*decode message */ H5O__linfo_encode, /*encode message */ H5O__linfo_copy, /*copy the native value */ diff --git a/src/H5Olink.c b/src/H5Olink.c index 75456f4..51c44a3 100644 --- a/src/H5Olink.c +++ b/src/H5Olink.c @@ -56,7 +56,7 @@ const H5O_msg_class_t H5O_MSG_LINK[1] = {{ H5O_LINK_ID, /*message id number */ "link", /*message name for debugging */ sizeof(H5O_link_t), /*native message size */ - 0, /* messages are sharable? */ + 0, /* messages are shareable? */ H5O__link_decode, /*decode message */ H5O__link_encode, /*encode message */ H5O__link_copy, /*copy the native value */ diff --git a/src/H5Omessage.c b/src/H5Omessage.c index 15edf1e..fa20aa1 100644 --- a/src/H5Omessage.c +++ b/src/H5Omessage.c @@ -371,7 +371,7 @@ H5O__msg_write_real(H5F_t *f, H5O_t *oh, const H5O_msg_class_t *type, unsigned m HDassert(((H5O_shared_t *)idx_msg->native)->type != H5O_SHARE_TYPE_COMMITTED); /* Also, sanity check that a message doesn't switch status from being - * shared (or sharable) to being unsharable. (Which could cause + * shared (or shareable) to being unshareable. (Which could cause * a message to increase in size in the object header) */ HDassert(!(mesg_flags & H5O_MSG_FLAG_DONTSHARE)); @@ -1131,7 +1131,7 @@ done: * Nov 19 2004 * * Description: - * This function interates over the object headers of an object + * This function iterates over the object headers of an object * specified with 'loc' of type 'type_id'. For each object header of the * object, the 'op_data' and some additional information (specified below) are * passed to the 'op' function. @@ -1194,7 +1194,7 @@ done: * Sep 6 2005 * * Description: - * This function interates over the object headers of an object + * This function iterates over the object headers of an object * specified with 'ent' of type 'type_id'. For each object header of the * object, the 'op_data' and some additional information (specified below) are * passed to the 'op' function. @@ -1544,7 +1544,7 @@ H5O_msg_is_shared(unsigned type_id, const void *mesg) HDassert(type); HDassert(mesg); - /* If messages in a class aren't sharable, then obviously this message isn't shared! :-) */ + /* If messages in a class aren't shareable, then obviously this message isn't shared! :-) */ if (type->share_flags & H5O_SHARE_IS_SHARABLE) ret_value = H5O_IS_STORED_SHARED(((const H5O_shared_t *)mesg)->type); else diff --git a/src/H5Omtime.c b/src/H5Omtime.c index 163ea32..7d3c56a 100644 --- a/src/H5Omtime.c +++ b/src/H5Omtime.c @@ -43,7 +43,7 @@ const H5O_msg_class_t H5O_MSG_MTIME[1] = {{ H5O_MTIME_ID, /*message id number */ "mtime", /*message name for debugging */ sizeof(time_t), /*native message size */ - 0, /* messages are sharable? */ + 0, /* messages are shareable? */ H5O__mtime_decode, /*decode message */ H5O__mtime_encode, /*encode message */ H5O__mtime_copy, /*copy the native value */ @@ -68,7 +68,7 @@ const H5O_msg_class_t H5O_MSG_MTIME_NEW[1] = {{ H5O_MTIME_NEW_ID, /*message id number */ "mtime_new", /*message name for debugging */ sizeof(time_t), /*native message size */ - 0, /* messages are sharable? */ + 0, /* messages are shareable? */ H5O__mtime_new_decode, /*decode message */ H5O__mtime_new_encode, /*encode message */ H5O__mtime_copy, /*copy the native value */ diff --git a/src/H5Oname.c b/src/H5Oname.c index 1636a0e..35578a9 100644 --- a/src/H5Oname.c +++ b/src/H5Oname.c @@ -43,7 +43,7 @@ const H5O_msg_class_t H5O_MSG_NAME[1] = {{ H5O_NAME_ID, /*message id number */ "name", /*message name for debugging */ sizeof(H5O_name_t), /*native message size */ - 0, /* messages are sharable? */ + 0, /* messages are shareable? */ H5O__name_decode, /*decode message */ H5O__name_encode, /*encode message */ H5O__name_copy, /*copy the native value */ diff --git a/src/H5Onull.c b/src/H5Onull.c index 9b377fb..0f3143c 100644 --- a/src/H5Onull.c +++ b/src/H5Onull.c @@ -31,7 +31,7 @@ const H5O_msg_class_t H5O_MSG_NULL[1] = {{ H5O_NULL_ID, /*message id number */ "null", /*message name for debugging */ 0, /*native message size */ - 0, /* messages are sharable? */ + 0, /* messages are shareable? */ NULL, /*no decode method */ NULL, /*no encode method */ NULL, /*no copy method */ diff --git a/src/H5Opkg.h b/src/H5Opkg.h index 331fcf6..1fe918d 100644 --- a/src/H5Opkg.h +++ b/src/H5Opkg.h @@ -378,7 +378,7 @@ typedef struct H5O_chunk_proxy_t { H5O_t * oh; /* Object header for this chunk */ unsigned chunkno; /* Chunk number for this chunk */ - /* Flush depencency parent information (not stored) + /* Flush dependency parent information (not stored) * * The following field is used to store a pointer * to the in-core representation of a new chunk proxy's flush dependency @@ -551,7 +551,7 @@ H5_DLL herr_t H5O__visit(H5G_loc_t *loc, const char *obj_name, H5_index_t idx_ty H5O_iterate2_t op, void *op_data, unsigned fields); H5_DLL herr_t H5O__inc_rc(H5O_t *oh); H5_DLL herr_t H5O__dec_rc(H5O_t *oh); -H5_DLL herr_t H5O__free(H5O_t *oh); +H5_DLL herr_t H5O__free(H5O_t *oh, hbool_t force); /* Object header message routines */ H5_DLL herr_t H5O__msg_alloc(H5F_t *f, H5O_t *oh, const H5O_msg_class_t *type, unsigned *mesg_flags, diff --git a/src/H5Opline.c b/src/H5Opline.c index 221e323..243f454 100644 --- a/src/H5Opline.c +++ b/src/H5Opline.c @@ -67,7 +67,7 @@ const H5O_msg_class_t H5O_MSG_PLINE[1] = {{ H5O_PLINE_ID, /* message id number */ "filter pipeline", /* message name for debugging */ sizeof(H5O_pline_t), /* native message size */ - H5O_SHARE_IS_SHARABLE | H5O_SHARE_IN_OHDR, /* messages are sharable? */ + H5O_SHARE_IS_SHARABLE | H5O_SHARE_IN_OHDR, /* messages are shareable? */ H5O__pline_shared_decode, /* decode message */ H5O__pline_shared_encode, /* encode message */ H5O__pline_copy, /* copy the native value */ @@ -86,7 +86,7 @@ const H5O_msg_class_t H5O_MSG_PLINE[1] = {{ H5O__pline_shared_debug /* debug the message */ }}; -/* Format version bounds for filter pipleline */ +/* Format version bounds for filter pipeline */ const unsigned H5O_pline_ver_bounds[] = { H5O_PLINE_VERSION_1, /* H5F_LIBVER_EARLIEST */ H5O_PLINE_VERSION_2, /* H5F_LIBVER_V18 */ diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h index 050bd49..58b863d 100644 --- a/src/H5Oprivate.h +++ b/src/H5Oprivate.h @@ -251,7 +251,7 @@ typedef struct H5O_copy_t { #define H5O_SHARE_TYPE_UNSHARED 0 /* Message is not shared */ #define H5O_SHARE_TYPE_SOHM 1 /* Message is stored in SOHM heap */ #define H5O_SHARE_TYPE_COMMITTED 2 /* Message is stored in another object header */ -#define H5O_SHARE_TYPE_HERE 3 /* Message is stored in this object header, but is sharable */ +#define H5O_SHARE_TYPE_HERE 3 /* Message is stored in this object header, but is shareable */ /* Detect messages that aren't stored in message's object header */ #define H5O_IS_STORED_SHARED(T) \ diff --git a/src/H5Opublic.h b/src/H5Opublic.h index d9d0500..70f451e 100644 --- a/src/H5Opublic.h +++ b/src/H5Opublic.h @@ -80,7 +80,7 @@ #define H5O_SHMESG_MAX_LIST_SIZE 5000 /* Flags for H5Oget_info. - * Theses flags determine which fields will be filled in in the H5O_info_t + * These flags determine which fields will be filled in the H5O_info_t * struct. */ #define H5O_INFO_BASIC 0x0001u /**< Fill in the fileno, addr, type, and rc fields */ @@ -90,8 +90,8 @@ //! <!-- [H5O_native_info_fields_snip] --> /** - * Flags for H5Oget_native_info(). Theses flags determine which fields will be - * filled in in the \ref H5O_native_info_t struct. + * Flags for H5Oget_native_info(). These flags determine which fields will be + * filled in the \ref H5O_native_info_t struct. */ #define H5O_NATIVE_INFO_HDR 0x0008u /**< Fill in the hdr field */ #define H5O_NATIVE_INFO_META_SIZE 0x0010u /**< Fill in the meta_size field */ @@ -510,7 +510,7 @@ H5_DLL herr_t H5Oget_info3(hid_t loc_id, H5O_info2_t *oinfo, unsigned fields); * location and relative name * * \fgdta_loc_obj_id{loc_id} - * \param[in] name Name of group, relative to \p loc_id + * \param[in] name Name of object, relative to \p loc_id * \param[out] oinfo Buffer in which to return object information * \param[in] fields Flags specifying the fields to include in \p oinfo * \lapl_id @@ -1166,7 +1166,7 @@ H5_DLL ssize_t H5Oget_comment_by_name(hid_t loc_id, const char *name, char *comm * <em>best effort</em> setting. If the application passes in * a value indicating iteration in creation order and a group is * encountered that was not tracked in creation order, that group - * will be iterated over in alpha-numeric order by name, or + * will be iterated over in alphanumeric order by name, or * <em>name order</em>. (<em>Name order</em> is the native order * used by the HDF5 library and is always available.) * @@ -1265,7 +1265,7 @@ H5_DLL herr_t H5Ovisit3(hid_t obj_id, H5_index_t idx_type, H5_iter_order_t order * <em>best effort</em> setting. If the application passes in a * value indicating iteration in creation order and a group is * encountered that was not tracked in creation order, that group - * will be iterated over in alpha-numeric order by name, or + * will be iterated over in alphanumeric order by name, or * <em>name order</em>. (<em>Name order</em> is the native order * used by the HDF5 library and is always available.) * @@ -1834,7 +1834,7 @@ H5_DLL herr_t H5Oget_info1(hid_t loc_id, H5O_info1_t *oinfo); * by location and relative name * * \fgdta_loc_obj_id{loc_id} - * \param[in] name Name of group, relative to \p loc_id + * \param[in] name Name of object, relative to \p loc_id * \param[out] oinfo Buffer in which to return object information * \lapl_id * @@ -1960,7 +1960,7 @@ H5_DLL herr_t H5Oget_info2(hid_t loc_id, H5O_info1_t *oinfo, unsigned fields); * by location and relative name * * \fgdta_loc_obj_id{loc_id} - * \param[in] name Name of group, relative to \p loc_id + * \param[in] name Name of object, relative to \p loc_id * \param[out] oinfo Buffer in which to return object information * \param[in] fields Flags specifying the fields to include in \p oinfo * \lapl_id @@ -1978,7 +1978,7 @@ H5_DLL herr_t H5Oget_info2(hid_t loc_id, H5O_info1_t *oinfo, unsigned fields); * in the H5Oget_info1() function entry. * * The \p fields parameter contains flags to determine which fields - * will be filled in in the H5O_info1_t \c struct returned in + * will be filled in the H5O_info1_t \c struct returned in * \p oinfo. These flags are defined in the H5Opublic.h file: * * \obj_info_fields @@ -2096,7 +2096,7 @@ H5_DLL herr_t H5Oget_info_by_idx2(hid_t loc_id, const char *group_name, H5_index * <em>best effort</em> setting. If the application passes in * a value indicating iteration in creation order and a group is * encountered that was not tracked in creation order, that group - * will be iterated over in alpha-numeric order by name, or + * will be iterated over in alphanumeric order by name, or * <em>name order</em>. (<em>Name order</em> is the native order * used by the HDF5 library and is always available.) * @@ -2188,7 +2188,7 @@ H5_DLL herr_t H5Ovisit1(hid_t obj_id, H5_index_t idx_type, H5_iter_order_t order * <em>best effort</em> setting. If the application passes in a * value indicating iteration in creation order and a group is * encountered that was not tracked in creation order, that group - * will be iterated over in alpha-numeric order by name, or + * will be iterated over in alphanumeric order by name, or * <em>name order</em>. (<em>Name order</em> is the native order * used by the HDF5 library and is always available.) * @@ -2291,7 +2291,7 @@ H5_DLL herr_t H5Ovisit_by_name1(hid_t loc_id, const char *obj_name, H5_index_t i * <em>best effort</em> setting. If the application passes in * a value indicating iteration in creation order and a group is * encountered that was not tracked in creation order, that group - * will be iterated over in alpha-numeric order by name, or + * will be iterated over in alphanumeric order by name, or * <em>name order</em>. (<em>Name order</em> is the native order * used by the HDF5 library and is always available.) * @@ -2385,7 +2385,7 @@ H5_DLL herr_t H5Ovisit2(hid_t obj_id, H5_index_t idx_type, H5_iter_order_t order * <em>best effort</em> setting. If the application passes in a * value indicating iteration in creation order and a group is * encountered that was not tracked in creation order, that group - * will be iterated over in alpha-numeric order by name, or + * will be iterated over in alphanumeric order by name, or * <em>name order</em>. (<em>Name order</em> is the native order * used by the HDF5 library and is always available.) * diff --git a/src/H5Orefcount.c b/src/H5Orefcount.c index 52eee14..500ab0f 100644 --- a/src/H5Orefcount.c +++ b/src/H5Orefcount.c @@ -45,7 +45,7 @@ const H5O_msg_class_t H5O_MSG_REFCOUNT[1] = {{ H5O_REFCOUNT_ID, /*message id number */ "refcount", /*message name for debugging */ sizeof(H5O_refcount_t), /*native message size */ - 0, /* messages are sharable? */ + 0, /* messages are shareable? */ H5O__refcount_decode, /*decode message */ H5O__refcount_encode, /*encode message */ H5O__refcount_copy, /*copy the native value */ diff --git a/src/H5Osdspace.c b/src/H5Osdspace.c index dab989f..574103d 100644 --- a/src/H5Osdspace.c +++ b/src/H5Osdspace.c @@ -61,7 +61,7 @@ const H5O_msg_class_t H5O_MSG_SDSPACE[1] = {{ H5O_SDSPACE_ID, /* message id number */ "dataspace", /* message name for debugging */ sizeof(H5S_extent_t), /* native message size */ - H5O_SHARE_IS_SHARABLE | H5O_SHARE_IN_OHDR, /* messages are sharable? */ + H5O_SHARE_IS_SHARABLE | H5O_SHARE_IN_OHDR, /* messages are shareable? */ H5O__sdspace_shared_decode, /* decode message */ H5O__sdspace_shared_encode, /* encode message */ H5O__sdspace_copy, /* copy the native value */ diff --git a/src/H5Oshmesg.c b/src/H5Oshmesg.c index 1c894a5..a4e8b8f 100644 --- a/src/H5Oshmesg.c +++ b/src/H5Oshmesg.c @@ -37,7 +37,7 @@ const H5O_msg_class_t H5O_MSG_SHMESG[1] = {{ H5O_SHMESG_ID, /*message id number */ "shared message table", /*message name for debugging */ sizeof(H5O_shmesg_table_t), /*native message size */ - 0, /* messages are sharable? */ + 0, /* messages are shareable? */ H5O__shmesg_decode, /*decode message */ H5O__shmesg_encode, /*encode message */ H5O__shmesg_copy, /*copy the native value */ diff --git a/src/H5Ostab.c b/src/H5Ostab.c index fa030bd..213b8a0 100644 --- a/src/H5Ostab.c +++ b/src/H5Ostab.c @@ -51,7 +51,7 @@ const H5O_msg_class_t H5O_MSG_STAB[1] = {{ H5O_STAB_ID, /*message id number */ "stab", /*message name for debugging */ sizeof(H5O_stab_t), /*native message size */ - 0, /* messages are sharable? */ + 0, /* messages are shareable? */ H5O__stab_decode, /*decode message */ H5O__stab_encode, /*encode message */ H5O__stab_copy, /*copy the native value */ diff --git a/src/H5Ounknown.c b/src/H5Ounknown.c index 2b8a7bb..dc43a6c 100644 --- a/src/H5Ounknown.c +++ b/src/H5Ounknown.c @@ -37,7 +37,7 @@ const H5O_msg_class_t H5O_MSG_UNKNOWN[1] = {{ H5O_UNKNOWN_ID, /*message id number */ "unknown", /*message name for debugging */ 0, /*native message size */ - 0, /* messages are sharable? */ + 0, /* messages are shareable? */ NULL, /*decode message */ NULL, /*encode message */ NULL, /*copy the native value */ @@ -54,9 +54,6 @@ typedef struct { /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /*****************************/ /* Library Private Variables */ /*****************************/ @@ -678,7 +675,7 @@ done: NAME H5Pexist PURPOSE - Routine to query the existance of a property in a property object. + Routine to query the existence of a property in a property object. USAGE htri_t H5P_exist(id, name) hid_t id; IN: Property object ID to check @@ -712,7 +709,7 @@ H5Pexist(hid_t id, const char *name) if (!name || !*name) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid property name"); - /* Check for the existance of the property in the list or class */ + /* Check for the existence of the property in the list or class */ if (H5I_GENPROP_LST == H5I_get_type(id)) { if (NULL == (plist = (H5P_genplist_t *)H5I_object(id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list"); @@ -858,7 +855,7 @@ done: Failure: H5I_INVALID_HID (negative) DESCRIPTION Decodes a property list from a binary buffer. The contents of the buffer - contain the values for the correponding properties of the plist. The decode + contain the values for the corresponding properties of the plist. The decode callback of a certain property decodes its value from the buffer and sets it in the property list. GLOBAL VARIABLES @@ -1299,7 +1296,7 @@ done: Returns non-negative on success, negative on failure. DESCRIPTION Removes a property from a property list. Both properties which were - in existance when the property list was created (i.e. properties registered + in existence when the property list was created (i.e. properties registered with H5Pregister2) and properties added to the list after it was created (i.e. added with H5Pinsert2) may be removed from a property list. Properties do not need to be removed a property list before the list itself @@ -131,9 +131,6 @@ static herr_t H5PB__write_entry(H5F_shared_t *f_sh, H5PB_entry_t *page_entry); /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /*****************************/ /* Library Private Variables */ /*****************************/ @@ -1306,6 +1303,75 @@ done: } /* end H5PB_write() */ /*------------------------------------------------------------------------- + * Function: H5PB_enabled + * + * Purpose: Check if the page buffer may be enabled for the specified + * file and data access type. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Neil Fortner + * + *------------------------------------------------------------------------- + */ +herr_t +H5PB_enabled(H5F_shared_t *f_sh, H5FD_mem_t type, hbool_t *enabled) +{ + H5PB_t *page_buf; /* Page buffering info for this file */ + hbool_t bypass_pb = FALSE; /* Whether to bypass page buffering */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOERR + + /* Sanity checks */ + HDassert(f_sh); + + /* Get pointer to page buffer info for this file */ + page_buf = f_sh->page_buf; + +#ifdef H5_HAVE_PARALLEL + if (H5F_SHARED_HAS_FEATURE(f_sh, H5FD_FEAT_HAS_MPI)) { +#if 1 + bypass_pb = TRUE; +#else + /* MSC - why this stopped working ? */ + int mpi_size; + + if ((mpi_size = H5F_shared_mpi_get_size(f_sh)) < 0) + HGOTO_ERROR(H5E_PAGEBUF, H5E_CANTGET, FAIL, "can't retrieve MPI communicator size") + if (1 != mpi_size) + bypass_pb = TRUE; +#endif + } /* end if */ +#endif + + /* If page buffering is disabled, or if this is a parallel raw data access, + * bypass page buffering. Note that page buffering may still be disabled for + * large metadata access or large non-parallel raw data access, but this + * function doesn't take I/O size into account so if it returns TRUE the + * page buffer may still be disabled for some I/O. If it returns FALSE it is + * always disabled for this access type. + */ + if (NULL == page_buf || (bypass_pb && H5FD_MEM_DRAW == type)) { + /* Update statistics, since wherever this function is called, if it + * returns FALSE, the calling function performs I/O avoiding the page + * buffer layer */ + if (page_buf) { + HDassert(type == H5FD_MEM_DRAW); + page_buf->bypasses[1]++; + } /* end if */ + + /* Page buffer is disabled, at least for this data access type */ + *enabled = FALSE; + } /* end if */ + else + /* Page buffer may be enabled */ + *enabled = TRUE; + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5PB_enabled() */ + +/*------------------------------------------------------------------------- * Function: H5PB__insert_entry() * * Purpose: This function was created without documentation. diff --git a/src/H5PBprivate.h b/src/H5PBprivate.h index e0197bf..0a255fc 100644 --- a/src/H5PBprivate.h +++ b/src/H5PBprivate.h @@ -23,11 +23,6 @@ #ifndef H5PBprivate_H #define H5PBprivate_H -/* Include package's public header */ -#ifdef NOT_YET -#include "H5PBpublic.h" -#endif /* NOT_YET */ - /* Private headers needed by this header */ #include "H5private.h" /* Generic Functions */ #include "H5Fprivate.h" /* File access */ @@ -91,6 +86,7 @@ H5_DLL herr_t H5PB_update_entry(H5PB_t *page_buf, haddr_t addr, size_t size, con H5_DLL herr_t H5PB_remove_entry(const H5F_shared_t *f_sh, haddr_t addr); H5_DLL herr_t H5PB_read(H5F_shared_t *f_sh, H5FD_mem_t type, haddr_t addr, size_t size, void *buf /*out*/); H5_DLL herr_t H5PB_write(H5F_shared_t *f_sh, H5FD_mem_t type, haddr_t addr, size_t size, const void *buf); +H5_DLL herr_t H5PB_enabled(H5F_shared_t *f_sh, H5FD_mem_t type, hbool_t *enabled); /* Statistics routines */ H5_DLL herr_t H5PB_reset_stats(H5PB_t *page_buf); @@ -67,7 +67,7 @@ * the special "::" string. * * Return: Success: Non-negative - * Failture: Negative + * Failure: Negative * *------------------------------------------------------------------------- */ @@ -99,7 +99,7 @@ done: * Positive if one or more of the plugin types are enabled * * Return: Success: Non-negative - * Failture: Negative + * Failure: Negative * *------------------------------------------------------------------------- */ @@ -128,7 +128,7 @@ done: * Purpose: Insert a plugin search path at the end of the list. * * Return: Success: Non-negative - * Failture: Negative + * Failure: Negative * *------------------------------------------------------------------------- */ @@ -160,7 +160,7 @@ done: * Purpose: Insert a plugin search path at the beginning of the list. * * Return: Success: Non-negative - * Failture: Negative + * Failure: Negative * *------------------------------------------------------------------------- */ @@ -234,7 +234,7 @@ done: * other paths after the index. * * Return: Success: Non-negative - * Failture: Negative + * Failure: Negative * *------------------------------------------------------------------------- */ @@ -270,11 +270,11 @@ done: /*------------------------------------------------------------------------- * Function: H5PLremove * - * Purpose: Remove the plugin path at the specifed index and compact + * Purpose: Remove the plugin path at the specified index and compact * the list. * * Return: Success: Non-negative - * Failture: Negative + * Failure: Negative * * Return: Non-negative or success. * diff --git a/src/H5PLint.c b/src/H5PLint.c index d20401e..fe9d3c1 100644 --- a/src/H5PLint.c +++ b/src/H5PLint.c @@ -46,9 +46,6 @@ /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /*****************************/ /* Library Private Variables */ /*****************************/ @@ -123,28 +120,27 @@ H5PL__set_plugin_control_mask(unsigned int mask) } /* end H5PL__set_plugin_control_mask() */ /*------------------------------------------------------------------------- - * Function: H5PL__init_package - * - * Purpose: Initialize any package-specific data and call any init - * routines for the package. + * Function: H5PL_init * - * Return: SUCCEED/FAIL + * Purpose: Initialize the interface from some other layer. * + * Return: Success: non-negative + * Failure: negative *------------------------------------------------------------------------- */ herr_t -H5PL__init_package(void) +H5PL_init(void) { char * env_var = NULL; herr_t ret_value = SUCCEED; - FUNC_ENTER_PACKAGE + FUNC_ENTER_NOAPI(FAIL) /* Check the environment variable to determine if the user wants * to ignore plugins. The special symbol H5PL_NO_PLUGIN (defined in * H5PLpublic.h) means we don't want to load plugins. */ - if (NULL != (env_var = HDgetenv("HDF5_PLUGIN_PRELOAD"))) + if (NULL != (env_var = HDgetenv(HDF5_PLUGIN_PRELOAD))) if (!HDstrcmp(env_var, H5PL_NO_PLUGIN)) { H5PL_plugin_control_mask_g = 0; H5PL_allow_plugins_g = FALSE; @@ -160,7 +156,7 @@ H5PL__init_package(void) done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5PL__init_package() */ +} /*------------------------------------------------------------------------- * Function: H5PL_term_package @@ -183,24 +179,17 @@ H5PL_term_package(void) FUNC_ENTER_NOAPI_NOINIT - if (H5_PKG_INIT_VAR) { - - /* Close the plugin cache. - * We need to bump the return value if we did any real work here. - */ - if (H5PL__close_plugin_cache(&already_closed) < 0) - HGOTO_ERROR(H5E_PLUGIN, H5E_CANTFREE, (-1), "problem closing plugin cache") - if (!already_closed) - ret_value++; - - /* Close the search path table and free the paths */ - if (H5PL__close_path_table() < 0) - HGOTO_ERROR(H5E_PLUGIN, H5E_CANTFREE, (-1), "problem closing search path table") + /* Close the plugin cache. + * We need to bump the return value if we did any real work here. + */ + if (H5PL__close_plugin_cache(&already_closed) < 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTFREE, (-1), "problem closing plugin cache") + if (!already_closed) + ret_value++; - /* Mark the interface as uninitialized */ - if (0 == ret_value) - H5_PKG_INIT_VAR = FALSE; - } /* end if */ + /* Close the search path table and free the paths */ + if (H5PL__close_path_table() < 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTFREE, (-1), "problem closing search path table") done: FUNC_LEAVE_NOAPI(ret_value) @@ -243,6 +232,11 @@ H5PL_load(H5PL_type_t type, const H5PL_key_t *key) "Virtual Object Layer (VOL) driver plugins disabled") break; + case H5PL_TYPE_VFD: + if ((H5PL_plugin_control_mask_g & H5PL_VFD_PLUGIN) == 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTLOAD, NULL, "Virtual File Driver (VFD) plugins disabled") + break; + case H5PL_TYPE_ERROR: case H5PL_TYPE_NONE: default: @@ -275,9 +269,31 @@ done: * * Purpose: Opens a plugin. * - * The success parameter will be set to TRUE and the plugin_info - * parameter will be filled in on success. Otherwise, they - * will be FALSE and NULL, respectively. + * `path` specifies the path to the plugin library file. + * + * `type` specifies the type of plugin being searched for and + * will be used to verify that a loaded plugin matches the + * type requested. H5PL_TYPE_NONE may be passed, in which case + * no plugin type verification is performed. This is most + * useful when iterating over available plugins without regard + * to their types. + * + * `key` specifies the information that will be used to find a + * specific plugin. For filter plugins, this is typically an + * integer identifier. For VOL connector and VFD plugins, this + * is typically either an integer identifier or a name string. + * After a plugin has been opened, this information will be + * compared against the relevant information provided by the + * plugin to ensure that the plugin is a match. If + * H5PL_TYPE_NONE is provided for `type`, then `key` should be + * NULL. + * + * On successful open of a plugin, the `success` parameter + * will be set to TRUE and the `plugin_type` and `plugin_info` + * parameters will be filled appropriately. On failure, the + * `success` parameter will be set to FALSE, the `plugin_type` + * parameter will be set to H5PL_TYPE_ERROR and the + * `plugin_info` parameter will be set to NULL. * * Return: SUCCEED/FAIL * @@ -308,6 +324,8 @@ H5PL__open(const char *path, H5PL_type_t type, const H5PL_key_t *key, hbool_t *s /* Check args - Just assert on package functions */ HDassert(path); + if (type == H5PL_TYPE_NONE) + HDassert(!key); HDassert(success); HDassert(plugin_info); @@ -396,6 +414,34 @@ H5PL__open(const char *path, H5PL_type_t type, const H5PL_key_t *key, hbool_t *s break; } + case H5PL_TYPE_VFD: { + const void *cls; + + /* Get the plugin info */ + if (NULL == (cls = (const void *)(*get_plugin_info)())) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "can't get VFD info from plugin") + + /* Setup temporary plugin key if one wasn't supplied */ + if (!key) { + tmp_key.vfd.kind = H5FD_GET_DRIVER_BY_NAME; + tmp_key.vfd.u.name = ((const H5FD_class_t *)cls)->name; + key = &tmp_key; + } + + /* Ask VFD interface if this class is the one we are looking for and is compatible, etc */ + if (H5FD_check_plugin_load(cls, key, success) < 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTLOAD, FAIL, "VFD compatibility check failed") + + /* Check for finding the correct plugin */ + if (*success) { + if (plugin_type) + *plugin_type = H5PL_TYPE_VFD; + *plugin_info = cls; + } + + break; + } + case H5PL_TYPE_ERROR: case H5PL_TYPE_NONE: default: @@ -453,10 +499,9 @@ H5PL_iterate(H5PL_iterate_type_t iter_type, H5PL_iterate_t iter_op, void *op_dat { herr_t ret_value = H5_ITER_CONT; - FUNC_ENTER_NOAPI(H5_ITER_ERROR) + FUNC_ENTER_NOAPI_NOERR ret_value = H5PL__path_table_iterate(iter_type, iter_op, op_data); -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5PL_iterate() */ diff --git a/src/H5PLpath.c b/src/H5PLpath.c index 39a7d0d..b86fd6e 100644 --- a/src/H5PLpath.c +++ b/src/H5PLpath.c @@ -248,7 +248,7 @@ H5PL__create_path_table(void) /* Retrieve paths from HDF5_PLUGIN_PATH if the user sets it * or from the default paths if it isn't set. */ - env_var = HDgetenv("HDF5_PLUGIN_PATH"); + env_var = HDgetenv(HDF5_PLUGIN_PATH); if (NULL == env_var) paths = H5MM_strdup(H5PL_DEFAULT_PATH); else @@ -322,7 +322,7 @@ H5PL__close_path_table(void) * Purpose: Gets the number of plugin paths that have been stored. * * Return: Success: The number of paths - * Failture: Can't fail + * Failure: Can't fail *------------------------------------------------------------------------- */ unsigned @@ -571,12 +571,12 @@ H5PL__path_table_iterate(H5PL_iterate_type_t iter_type, H5PL_iterate_t iter_op, FUNC_ENTER_PACKAGE - for (u = 0; (u < H5PL_num_paths_g) && (ret_value == H5_ITER_CONT); u++) - ret_value = H5PL__path_table_iterate_process_path(H5PL_paths_g[u], iter_type, iter_op, op_data); - - if (ret_value < 0) - HGOTO_ERROR(H5E_PLUGIN, H5E_BADITER, H5_ITER_ERROR, "can't iterate over plugins in plugin path '%s'", - H5PL_paths_g[u]); + for (u = 0; (u < H5PL_num_paths_g) && (ret_value == H5_ITER_CONT); u++) { + if ((ret_value = + H5PL__path_table_iterate_process_path(H5PL_paths_g[u], iter_type, iter_op, op_data)) < 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_BADITER, H5_ITER_ERROR, + "can't iterate over plugins in plugin path '%s'", H5PL_paths_g[u]); + } done: FUNC_LEAVE_NOAPI(ret_value); @@ -615,9 +615,9 @@ H5PL__path_table_iterate_process_path(const char *plugin_path, H5PL_iterate_type HDassert(plugin_path); HDassert(iter_op); - /* Open the directory */ + /* Open the directory - skip the path if the directory can't be opened */ if (!(dirp = HDopendir(plugin_path))) - HGOTO_ERROR(H5E_PLUGIN, H5E_OPENERROR, H5_ITER_ERROR, "can't open directory: %s", plugin_path) + HGOTO_DONE(H5_ITER_CONT) /* Iterate through all entries in the directory */ while (NULL != (dp = HDreaddir(dirp))) { @@ -663,7 +663,8 @@ H5PL__path_table_iterate_process_path(const char *plugin_path, H5PL_iterate_type /* Determine if we should process this plugin */ plugin_matches = (iter_type == H5PL_ITER_TYPE_ALL) || ((iter_type == H5PL_ITER_TYPE_FILTER) && (plugin_type == H5PL_TYPE_FILTER)) || - ((iter_type == H5PL_ITER_TYPE_VOL) && (plugin_type == H5PL_TYPE_VOL)); + ((iter_type == H5PL_ITER_TYPE_VOL) && (plugin_type == H5PL_TYPE_VOL)) || + ((iter_type == H5PL_ITER_TYPE_VFD) && (plugin_type == H5PL_TYPE_VFD)); /* If the plugin was successfully loaded, call supplied callback function on plugin */ if (plugin_loaded && plugin_matches && (ret_value = iter_op(plugin_type, plugin_info, op_data))) @@ -706,10 +707,11 @@ H5PL__path_table_iterate_process_path(const char *plugin_path, H5PL_iterate_type HDassert(plugin_path); HDassert(iter_op); - /* Specify a file mask. *.* = We want everything! */ - HDsprintf(service, "%s\\*.dll", plugin_path); + /* Specify a file mask. *.* = We want everything! - + * skip the path if the directory can't be opened */ + HDsnprintf(service, sizeof(service), "%s\\*.dll", plugin_path); if ((hFind = FindFirstFileA(service, &fdFile)) == INVALID_HANDLE_VALUE) - HGOTO_ERROR(H5E_PLUGIN, H5E_OPENERROR, H5_ITER_ERROR, "can't open directory") + HGOTO_DONE(H5_ITER_CONT) /* Loop over all the files */ do { @@ -740,7 +742,8 @@ H5PL__path_table_iterate_process_path(const char *plugin_path, H5PL_iterate_type /* Determine if we should process this plugin */ plugin_matches = (iter_type == H5PL_ITER_TYPE_ALL) || ((iter_type == H5PL_ITER_TYPE_FILTER) && (plugin_type == H5PL_TYPE_FILTER)) || - ((iter_type == H5PL_ITER_TYPE_VOL) && (plugin_type == H5PL_TYPE_VOL)); + ((iter_type == H5PL_ITER_TYPE_VOL) && (plugin_type == H5PL_TYPE_VOL)) || + ((iter_type == H5PL_ITER_TYPE_VFD) && (plugin_type == H5PL_TYPE_VFD)); /* If the plugin was successfully loaded, call supplied callback function on plugin */ if (plugin_loaded && plugin_matches && (ret_value = iter_op(plugin_type, plugin_info, op_data))) @@ -931,7 +934,7 @@ H5PL__find_plugin_in_path(const H5PL_search_params_t *search_params, hbool_t *fo *found = FALSE; /* Specify a file mask. *.* = We want everything! */ - HDsprintf(service, "%s\\*.dll", dir); + HDsnprintf(service, sizeof(service), "%s\\*.dll", dir); if ((hFind = FindFirstFileA(service, &fdFile)) == INVALID_HANDLE_VALUE) HGOTO_ERROR(H5E_PLUGIN, H5E_OPENERROR, FAIL, "can't open directory") diff --git a/src/H5PLplugin_cache.c b/src/H5PLplugin_cache.c index b7cdac0..25e373f 100644 --- a/src/H5PLplugin_cache.c +++ b/src/H5PLplugin_cache.c @@ -263,59 +263,99 @@ H5PL__find_plugin_in_cache(const H5PL_search_params_t *search_params, hbool_t *f /* Loop over all the plugins, looking for one that matches */ for (u = 0; u < H5PL_num_plugins_g; u++) { - /* If the plugin type (filter, VOL connector, etc.) match, proceed */ - if (search_params->type == H5PL_cache_g[u].type) { - hbool_t matched = FALSE; /* Whether cached plugin info matches */ + hbool_t matched = FALSE; /* Whether cached plugin info matches */ - switch (search_params->type) { - case H5PL_TYPE_FILTER: - if (search_params->key->id == H5PL_cache_g[u].key.id) + /* Determine if the plugin types match */ + if (search_params->type != H5PL_cache_g[u].type) + continue; + + /* Determine if cache entry matches based on type-specific information */ + switch (search_params->type) { + case H5PL_TYPE_FILTER: + /* Check if specified filter plugin ID matches cache entry's ID */ + if (search_params->key->id == H5PL_cache_g[u].key.id) + matched = TRUE; + + break; + + case H5PL_TYPE_VOL: + if (search_params->key->vol.kind == H5VL_GET_CONNECTOR_BY_NAME) { + /* Make sure the plugin cache entry key type matches our search key type */ + if (H5PL_cache_g[u].key.vol.kind != H5VL_GET_CONNECTOR_BY_NAME) + continue; + + /* Check if specified VOL connector name matches cache entry's name */ + if (!HDstrcmp(search_params->key->vol.u.name, H5PL_cache_g[u].key.vol.u.name)) + matched = TRUE; + } + else { + HDassert(search_params->key->vol.kind == H5VL_GET_CONNECTOR_BY_VALUE); + + /* Make sure the plugin cache entry key type matches our search key type */ + if (H5PL_cache_g[u].key.vol.kind != H5VL_GET_CONNECTOR_BY_VALUE) + continue; + + /* Check if specified VOL connector ID matches cache entry's ID */ + if (search_params->key->vol.u.value == H5PL_cache_g[u].key.vol.u.value) + matched = TRUE; + } + + break; + + case H5PL_TYPE_VFD: + if (search_params->key->vfd.kind == H5FD_GET_DRIVER_BY_NAME) { + /* Make sure the plugin cache entry key type matches our search key type */ + if (H5PL_cache_g[u].key.vfd.kind != H5FD_GET_DRIVER_BY_NAME) + continue; + + /* Check if specified VFD name matches cache entry's name */ + if (!HDstrcmp(search_params->key->vfd.u.name, H5PL_cache_g[u].key.vfd.u.name)) matched = TRUE; - break; - - case H5PL_TYPE_VOL: - if (search_params->key->vol.kind == H5VL_GET_CONNECTOR_BY_VALUE) { - if (search_params->key->vol.u.value == H5PL_cache_g[u].key.vol.u.value) - matched = TRUE; - } /* end if */ - else if (search_params->key->vol.kind == H5VL_GET_CONNECTOR_BY_NAME) { - if (0 == HDstrcmp(search_params->key->vol.u.name, H5PL_cache_g[u].key.vol.u.name)) - matched = TRUE; - } /* end else-if */ - else - HGOTO_ERROR(H5E_PLUGIN, H5E_BADVALUE, FAIL, "bad VOL plugin search key type") - break; - - case H5PL_TYPE_ERROR: - case H5PL_TYPE_NONE: - default: - HGOTO_ERROR(H5E_PLUGIN, H5E_BADVALUE, FAIL, "bad plugin type") - } /* end switch */ - - /* If the plugin type (filter, VOL connector, etc.) and key match, query the plugin for its info - */ - if (matched) { - H5PL_get_plugin_info_t get_plugin_info_function; - const void * info; - - /* Get the "get plugin info" function from the plugin. */ - if (NULL == (get_plugin_info_function = (H5PL_get_plugin_info_t)H5PL_GET_LIB_FUNC( - (H5PL_cache_g[u]).handle, "H5PLget_plugin_info"))) - HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "can't get function for H5PLget_plugin_info") - - /* Call the "get plugin info" function */ - if (NULL == (info = (*get_plugin_info_function)())) - HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "can't get plugin info") - - /* Set output parameters */ - *found = TRUE; - *plugin_info = info; - - /* No need to continue processing */ + } + else { + HDassert(search_params->key->vfd.kind == H5FD_GET_DRIVER_BY_VALUE); + + /* Make sure the plugin cache entry key type matches our search key type */ + if (H5PL_cache_g[u].key.vfd.kind != H5FD_GET_DRIVER_BY_VALUE) + continue; + + /* Check if specified VFD ID matches cache entry's ID */ + if (search_params->key->vfd.u.value == H5PL_cache_g[u].key.vfd.u.value) + matched = TRUE; + } + break; - } /* end if */ - } /* end if */ - } /* end for */ + + case H5PL_TYPE_ERROR: + case H5PL_TYPE_NONE: + default: + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "Invalid plugin type specified") + } + + /* If the plugin type (filter, VOL connector, VFD plugin, etc.) and key match, + * query the plugin for its info. + */ + if (matched) { + H5PL_get_plugin_info_t get_plugin_info_function; + const void * info; + + /* Get the "get plugin info" function from the plugin. */ + if (NULL == (get_plugin_info_function = (H5PL_get_plugin_info_t)H5PL_GET_LIB_FUNC( + H5PL_cache_g[u].handle, "H5PLget_plugin_info"))) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "can't get function for H5PLget_plugin_info") + + /* Call the "get plugin info" function */ + if (NULL == (info = (*get_plugin_info_function)())) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "can't get plugin info") + + /* Set output parameters */ + *found = TRUE; + *plugin_info = info; + + /* No need to continue processing */ + break; + } + } /* end for */ done: FUNC_LEAVE_NOAPI(ret_value) diff --git a/src/H5PLprivate.h b/src/H5PLprivate.h index 7eae513..83cc8a5 100644 --- a/src/H5PLprivate.h +++ b/src/H5PLprivate.h @@ -22,6 +22,7 @@ /* Private headers needed by this file */ #include "H5private.h" /* Generic Functions */ +#include "H5FDprivate.h" /* File Drivers */ #include "H5VLprivate.h" /* Virtual Object Layer */ /**************************/ @@ -32,16 +33,29 @@ /* Library Private Typedefs */ /****************************/ +/* Key used to find VOL connector plugins */ +typedef struct H5PL_vol_key_t { + H5VL_get_connector_kind_t kind; /* Kind of VOL lookup to do */ + union { + H5VL_class_value_t value; /* VOL connector value */ + const char * name; /* VOL connector name */ + } u; +} H5PL_vol_key_t; + +/* Key used to find VFD plugins */ +typedef struct H5PL_vfd_key_t { + H5FD_get_driver_kind_t kind; /* Kind of VFD lookup to do */ + union { + H5FD_class_value_t value; /* VFD value */ + const char * name; /* VFD name */ + } u; +} H5PL_vfd_key_t; + /* The key that will be used to find the plugin */ typedef union H5PL_key_t { - int id; /* I/O filters */ - struct { - H5VL_get_connector_kind_t kind; /* Kind of VOL lookup to do */ - union { - H5VL_class_value_t value; /* VOL connector value */ - const char * name; /* VOL connector name */ - } u; - } vol; + int id; /* I/O filters */ + H5PL_vol_key_t vol; + H5PL_vfd_key_t vfd; } H5PL_key_t; /* Enum dictating the type of plugins to process @@ -50,6 +64,7 @@ typedef union H5PL_key_t { typedef enum { H5PL_ITER_TYPE_FILTER, H5PL_ITER_TYPE_VOL, + H5PL_ITER_TYPE_VFD, H5PL_ITER_TYPE_ALL, } H5PL_iterate_type_t; @@ -67,5 +82,6 @@ typedef herr_t (*H5PL_iterate_t)(H5PL_type_t plugin_type, const void *plugin_inf /* Internal API routines */ H5_DLL const void *H5PL_load(H5PL_type_t plugin_type, const H5PL_key_t *key); H5_DLL herr_t H5PL_iterate(H5PL_iterate_type_t iter_type, H5PL_iterate_t iter_op, void *op_data); +H5_DLL herr_t H5PL_init(void); #endif /* H5PLprivate_H */ diff --git a/src/H5PLpublic.h b/src/H5PLpublic.h index 55ff594..ab24bd5 100644 --- a/src/H5PLpublic.h +++ b/src/H5PLpublic.h @@ -35,14 +35,16 @@ typedef enum H5PL_type_t { H5PL_TYPE_ERROR = -1, /**< Error */ H5PL_TYPE_FILTER = 0, /**< Filter */ - H5PL_TYPE_VOL = 1, /**< VOL driver */ - H5PL_TYPE_NONE = 2 /**< Sentinel: This must be last! */ + H5PL_TYPE_VOL = 1, /**< VOL connector */ + H5PL_TYPE_VFD = 2, /**< VFD */ + H5PL_TYPE_NONE = 3 /**< Sentinel: This must be last! */ } H5PL_type_t; //! <!-- [H5PL_type_t_snip] --> /* Common dynamic plugin type flags used by the set/get_loading_state functions */ #define H5PL_FILTER_PLUGIN 0x0001 #define H5PL_VOL_PLUGIN 0x0002 +#define H5PL_VFD_PLUGIN 0x0004 #define H5PL_ALL_PLUGIN 0xFFFF #ifdef __cplusplus diff --git a/src/H5Pdxpl.c b/src/H5Pdxpl.c index 46dc94c..c901931 100644 --- a/src/H5Pdxpl.c +++ b/src/H5Pdxpl.c @@ -1991,7 +1991,7 @@ done: /*------------------------------------------------------------------------- * Function: H5Pget_mpio_actual_io_mode * - * Purpose: Retrieves the type of I/O actually preformed when collective I/O + * Purpose: Retrieves the type of I/O actually performed when collective I/O * is requested. * * Return: Non-negative on success/Negative on failure @@ -2213,10 +2213,18 @@ H5P__dxfr_dset_io_hyp_sel_cmp(const void *_space1, const void *_space2, size_t H if (TRUE != H5S_extent_equal(*space1, *space2)) HGOTO_DONE(-1); - /* Compare the selection "shape" of the dataspaces */ - /* (Error & not-equal count the same) */ - if (TRUE != H5S_select_shape_same(*space1, *space2)) + /* Compare the selection "shape" of the dataspaces + * (Error & not-equal count the same) + * + * Since H5S_select_shape_same() can result in the dataspaces being + * rebuilt, the parameters are not const which makes it impossible + * to match the cmp prototype. Since we need to compare them, + * we quiet the const warning. + */ + H5_GCC_CLANG_DIAG_OFF("cast-qual") + if (TRUE != H5S_select_shape_same((H5S_t *)*space1, (H5S_t *)*space2)) HGOTO_DONE(-1); + H5_GCC_CLANG_DIAG_ON("cast-qual") } /* end if */ done: diff --git a/src/H5Pencdec.c b/src/H5Pencdec.c index e2a97f8..01573d1 100644 --- a/src/H5Pencdec.c +++ b/src/H5Pencdec.c @@ -663,7 +663,7 @@ done: on failure. DESCRIPTION Decodes a property list from a binary buffer. The contents of the buffer - contain the values for the correponding properties of the plist. The decode + contain the values for the corresponding properties of the plist. The decode callback of a certain property decodes its value from the buffer and sets it in the property list. GLOBAL VARIABLES diff --git a/src/H5Pfapl.c b/src/H5Pfapl.c index a8e0d8e..bfac42b 100644 --- a/src/H5Pfapl.c +++ b/src/H5Pfapl.c @@ -41,8 +41,28 @@ #include "H5VMprivate.h" /* Vector Functions */ /* Includes needed to set default file driver */ -#include "H5FDsec2.h" /* POSIX unbuffered I/O */ +#include "H5FDsec2.h" /* POSIX unbuffered I/O */ +#include "H5FDcore.h" +#include "H5FDlog.h" +#include "H5FDfamily.h" +#include "H5FDmulti.h" #include "H5FDstdio.h" /* Standard C buffered I/O */ +#include "H5FDsplitter.h" +#ifdef H5_HAVE_PARALLEL +#include "H5FDmpio.h" +#endif +#ifdef H5_HAVE_DIRECT +#include "H5FDdirect.h" +#endif +#ifdef H5_HAVE_MIRROR_VFD +#include "H5FDmirror.h" +#endif +#ifdef H5_HAVE_LIBHDFS +#include "H5FDhdfs.h" +#endif +#ifdef H5_HAVE_ROS3_VFD +#include "H5FDros3.h" +#endif #ifdef H5_HAVE_WINDOWS #include "H5FDwindows.h" /* Win32 I/O */ #endif @@ -73,7 +93,7 @@ #define H5F_ACS_DATA_CACHE_BYTE_SIZE_DEC H5P__decode_size_t /* Definition for preemption read chunks first */ #define H5F_ACS_PREEMPT_READ_CHUNKS_SIZE sizeof(double) -#define H5F_ACS_PREEMPT_READ_CHUNKS_DEF 0.75f +#define H5F_ACS_PREEMPT_READ_CHUNKS_DEF 0.75 #define H5F_ACS_PREEMPT_READ_CHUNKS_ENC H5P__encode_double #define H5F_ACS_PREEMPT_READ_CHUNKS_DEC H5P__decode_double /* Definition for threshold for alignment */ @@ -113,7 +133,7 @@ #define H5F_ACS_FILE_DRV_SIZE sizeof(H5FD_driver_prop_t) #define H5F_ACS_FILE_DRV_DEF \ { \ - H5_DEFAULT_VFD, NULL \ + H5_DEFAULT_VFD, NULL, NULL \ } #define H5F_ACS_FILE_DRV_CRT H5P__facc_file_driver_create #define H5F_ACS_FILE_DRV_SET H5P__facc_file_driver_set @@ -398,6 +418,9 @@ static int H5P__facc_mpi_info_cmp(const void *value1, const void *value2, siz static herr_t H5P__facc_mpi_info_close(const char *name, size_t size, void *value); #endif /* H5_HAVE_PARALLEL */ +/* Internal routines */ +static herr_t H5P__facc_set_def_driver_check_predefined(const char *driver_name, hid_t *driver_id); + /*********************/ /* Package Variables */ /*********************/ @@ -500,7 +523,7 @@ static const size_t H5F_def_page_buf_size_g = H5F_ACS_PAGE_BUFFER_SIZE_DEF; /* static const unsigned H5F_def_page_buf_min_meta_perc_g = H5F_ACS_PAGE_BUFFER_MIN_META_PERC_DEF; /* Default page buffer minimum metadata size */ static const unsigned H5F_def_page_buf_min_raw_perc_g = - H5F_ACS_PAGE_BUFFER_MIN_RAW_PERC_DEF; /* Default page buffer mininum raw data size */ + H5F_ACS_PAGE_BUFFER_MIN_RAW_PERC_DEF; /* Default page buffer minimum raw data size */ static const hbool_t H5F_def_use_file_locking_g = H5F_ACS_USE_FILE_LOCKING_DEF; /* Default use file locking flag */ static const hbool_t H5F_def_ignore_disabled_file_locks_g = @@ -809,6 +832,208 @@ done: } /* end H5P__facc_reg_prop() */ /*------------------------------------------------------------------------- + * Function: H5P__facc_set_def_driver + * + * Purpose: Parses a string that contains the name of the default VFL + * driver for the default FAPL. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5P__facc_set_def_driver(void) +{ + const char *driver_env_var; + hbool_t driver_ref_inc = FALSE; + hid_t driver_id = H5I_INVALID_HID; /* VFL driver ID */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC + + /* Check if VFL driver environment variable is set */ + driver_env_var = HDgetenv(HDF5_DRIVER); + + /* Only parse VFL driver string if it's set */ + if (driver_env_var && *driver_env_var) { + H5FD_driver_prop_t driver_prop; + H5P_genplist_t * def_fapl; /* Default file access property list */ + H5P_genclass_t * def_fapclass; /* Default file access property class */ + const char * driver_config_env_var; + htri_t driver_is_registered; + + /* Check to see if the driver is already registered */ + if ((driver_is_registered = H5FD_is_driver_registered_by_name(driver_env_var, &driver_id)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't check if VFL driver is already registered") + if (driver_is_registered) { + HDassert(driver_id >= 0); + + if (H5I_inc_ref(driver_id, TRUE) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTINC, FAIL, "unable to increment ref count on VFD") + driver_ref_inc = TRUE; + } /* end else-if */ + else { + /* Check for VFL drivers that ship with the library */ + if (H5P__facc_set_def_driver_check_predefined(driver_env_var, &driver_id) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't check for predefined VFL driver name") + else if (driver_id > 0) { + if (H5I_inc_ref(driver_id, TRUE) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTINC, FAIL, "can't increment VFL driver refcount") + driver_ref_inc = TRUE; + } + else { + /* Register the VFL driver */ + if ((driver_id = H5FD_register_driver_by_name(driver_env_var, TRUE)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTREGISTER, FAIL, "can't register VFL driver") + driver_ref_inc = TRUE; + } /* end else */ + } /* end else */ + + /* Retrieve driver configuration string from environment variable, if set. */ + driver_config_env_var = HDgetenv(HDF5_DRIVER_CONFIG); + + driver_prop.driver_id = driver_id; + driver_prop.driver_info = NULL; + driver_prop.driver_config_str = driver_config_env_var; + + /* Get default file access pclass */ + if (NULL == (def_fapclass = (H5P_genclass_t *)H5I_object(H5P_FILE_ACCESS))) + HGOTO_ERROR(H5E_VFL, H5E_BADID, FAIL, + "can't find object for default file access property class ID") + + /* Set new default VFL driver for default file access pclass */ + if (H5P__class_set(def_fapclass, H5F_ACS_FILE_DRV_NAME, &driver_prop) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, + "can't set default VFL driver for default file access property list class") + + /* Get default file access plist */ + if (NULL == (def_fapl = (H5P_genplist_t *)H5I_object(H5P_FILE_ACCESS_DEFAULT))) + HGOTO_ERROR(H5E_VFL, H5E_BADID, FAIL, "can't find object for default fapl ID") + + /* Set new default VFL driver for default FAPL */ + if (H5P_set_driver(def_fapl, driver_prop.driver_id, driver_prop.driver_info, + driver_prop.driver_config_str) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't set default VFL driver for default FAPL") + } + +done: + /* Clean up on error */ + if (ret_value < 0) { + if (driver_id >= 0 && driver_ref_inc && H5I_dec_app_ref(driver_id) < 0) + HDONE_ERROR(H5E_PLIST, H5E_CANTDEC, FAIL, "unable to unregister VFL driver") + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P__facc_set_def_driver() */ + +/*------------------------------------------------------------------------- + * Function: H5P__facc_set_def_driver_check_predefined + * + * Purpose: Checks a given driver name against a list of predefined + * names for VFL drivers that are internal to HDF5. If a name + * is matched, the ID for that driver is returned through + * `driver_id`. Otherwise, `driver_id` is set to + * H5I_INVALID_HID. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5P__facc_set_def_driver_check_predefined(const char *driver_name, hid_t *driver_id) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC + + HDassert(driver_name); + HDassert(driver_id); + + if (!HDstrcmp(driver_name, "sec2")) { + if ((*driver_id = H5FD_SEC2) < 0) + HGOTO_ERROR(H5E_VFL, H5E_UNINITIALIZED, FAIL, "couldn't initialize sec2 VFD") + } + else if (!HDstrcmp(driver_name, "core") || !HDstrcmp(driver_name, "core_paged")) { + if ((*driver_id = H5FD_CORE) < 0) + HGOTO_ERROR(H5E_VFL, H5E_UNINITIALIZED, FAIL, "couldn't initialize core VFD") + } + else if (!HDstrcmp(driver_name, "log")) { + if ((*driver_id = H5FD_LOG) < 0) + HGOTO_ERROR(H5E_VFL, H5E_UNINITIALIZED, FAIL, "couldn't initialize log VFD") + } + else if (!HDstrcmp(driver_name, "family")) { + if ((*driver_id = H5FD_FAMILY) < 0) + HGOTO_ERROR(H5E_VFL, H5E_UNINITIALIZED, FAIL, "couldn't initialize family VFD") + } + else if (!HDstrcmp(driver_name, "multi") || !HDstrcmp(driver_name, "split")) { + if ((*driver_id = H5FD_MULTI) < 0) + HGOTO_ERROR(H5E_VFL, H5E_UNINITIALIZED, FAIL, "couldn't initialize multi VFD") + } + else if (!HDstrcmp(driver_name, "stdio")) { + if ((*driver_id = H5FD_STDIO) < 0) + HGOTO_ERROR(H5E_VFL, H5E_UNINITIALIZED, FAIL, "couldn't initialize stdio VFD") + } + else if (!HDstrcmp(driver_name, "splitter")) { + if ((*driver_id = H5FD_SPLITTER) < 0) + HGOTO_ERROR(H5E_VFL, H5E_UNINITIALIZED, FAIL, "couldn't initialize splitter VFD") + } + else if (!HDstrcmp(driver_name, "mpio")) { +#ifdef H5_HAVE_PARALLEL + if ((*driver_id = H5FD_MPIO) < 0) + HGOTO_ERROR(H5E_VFL, H5E_UNINITIALIZED, FAIL, "couldn't initialize MPI I/O VFD") +#else + HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "MPI-I/O VFD is not enabled") +#endif + } + else if (!HDstrcmp(driver_name, "direct")) { +#ifdef H5_HAVE_DIRECT + if ((*driver_id = H5FD_DIRECT) < 0) + HGOTO_ERROR(H5E_VFL, H5E_UNINITIALIZED, FAIL, "couldn't initialize Direct I/O VFD") +#else + HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "Direct I/O VFD is not enabled") +#endif + } + else if (!HDstrcmp(driver_name, "mirror")) { +#ifdef H5_HAVE_MIRROR_VFD + if ((*driver_id = H5FD_MIRROR) < 0) + HGOTO_ERROR(H5E_VFL, H5E_UNINITIALIZED, FAIL, "couldn't initialize mirror VFD") +#else + HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "Mirror VFD is not enabled") +#endif + } + else if (!HDstrcmp(driver_name, "hdfs")) { +#ifdef H5_HAVE_LIBHDFS + if ((*driver_id = H5FD_HDFS) < 0) + HGOTO_ERROR(H5E_VFL, H5E_UNINITIALIZED, FAIL, "couldn't initialize HDFS VFD") +#else + HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "HDFS VFD is not enabled") +#endif + } + else if (!HDstrcmp(driver_name, "ros3")) { +#ifdef H5_HAVE_ROS3_VFD + if ((*driver_id = H5FD_ROS3) < 0) + HGOTO_ERROR(H5E_VFL, H5E_UNINITIALIZED, FAIL, "couldn't initialize ROS3 VFD") +#else + HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "ROS3 VFD is not enabled") +#endif + } + else if (!HDstrcmp(driver_name, "windows")) { +#ifdef H5_HAVE_WINDOWS + if ((*driver_id = H5FD_WINDOWS) < 0) + HGOTO_ERROR(H5E_VFL, H5E_UNINITIALIZED, FAIL, "couldn't initialize Windows VFD") +#else + HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "Windows VFD is not enabled") +#endif + } + else { + *driver_id = H5I_INVALID_HID; + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P__facc_set_def_driver_check_predefined() */ + +/*------------------------------------------------------------------------- * Function: H5Pset_alignment * * Purpose: Sets the alignment properties of a file access property list @@ -899,42 +1124,52 @@ done: } /* end H5Pget_alignment() */ /*------------------------------------------------------------------------- - * Function: H5P_set_driver + * Function: H5P_set_driver * - * Purpose: Set the file driver (DRIVER_ID) for a file access - * property list (PLIST_ID) and supply an optional - * struct containing the driver-specific properites - * (DRIVER_INFO). The driver properties will be copied into the - * property list and the reference count on the driver will be - * incremented, allowing the caller to close the driver ID but - * still use the property list. + * Purpose: Set the file driver (NEW_DRIVER_ID) for a file access + * property list (PLIST). A struct (NEW_DRIVER_INFO) or string + * (NEW_DRIVER_CONFIG_STR) containing the driver-specific + * properties can optionally be supplied. The driver properties + * (struct or string) will be copied into the property list and + * the reference count on the driver will be incremented, + * allowing the caller to close the driver ID but still use the + * property list. * - * Return: Success: Non-negative - * Failure: Negative + * Note: Only one of either NEW_DRIVER_INFO or NEW_DRIVER_CONFIG_STR + * should be specified, but not both. + * + * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke - * Tuesday, August 3, 1999 + * Tuesday, August 3, 1999 * *------------------------------------------------------------------------- */ herr_t -H5P_set_driver(H5P_genplist_t *plist, hid_t new_driver_id, const void *new_driver_info) +H5P_set_driver(H5P_genplist_t *plist, hid_t new_driver_id, const void *new_driver_info, + const char *new_driver_config_str) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) + /* If VFD configuration information is supplied, ensure that either binary + * configuration data or a configuration string is supplied, but not both. + */ + HDassert(!new_driver_info || !new_driver_config_str); + if (NULL == H5I_object_verify(new_driver_id, H5I_VFL)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file driver ID") if (TRUE == H5P_isa_class(plist->plist_id, H5P_FILE_ACCESS)) { - H5FD_driver_prop_t driver_prop; /* Property for driver ID & info */ + H5FD_driver_prop_t driver_prop; /* Property for driver ID, info & config. string */ /* Prepare the driver property */ - driver_prop.driver_id = new_driver_id; - driver_prop.driver_info = new_driver_info; + driver_prop.driver_id = new_driver_id; + driver_prop.driver_info = new_driver_info; + driver_prop.driver_config_str = new_driver_config_str; - /* Set the driver ID & info property */ + /* Set the driver ID, info & config. string property */ if (H5P_set(plist, H5F_ACS_FILE_DRV_NAME, &driver_prop) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set driver ID & info") } /* end if */ @@ -950,7 +1185,7 @@ done: * * Purpose: Set the file driver (DRIVER_ID) for a file access * property list (PLIST_ID) and supply an optional - * struct containing the driver-specific properites + * struct containing the driver-specific properties * (DRIVER_INFO). The driver properties will be copied into the * property list and the reference count on the driver will be * incremented, allowing the caller to close the driver ID but @@ -980,7 +1215,7 @@ H5Pset_driver(hid_t plist_id, hid_t new_driver_id, const void *new_driver_info) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file driver ID") /* Set the driver */ - if (H5P_set_driver(plist, new_driver_id, new_driver_info) < 0) + if (H5P_set_driver(plist, new_driver_id, new_driver_info, NULL) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set driver info") done: @@ -988,6 +1223,180 @@ done: } /* end H5Pset_driver() */ /*------------------------------------------------------------------------- + * Function: H5P_set_driver_by_name + * + * Purpose: Set the file driver name (DRIVER_NAME) for a file access + * property list (PLIST) and supply an optional string + * containing the driver-specific properties (DRIVER_CONFIG). + * The driver properties string will be copied into the + * property list. + * + * If the file driver specified by DRIVER_NAME is not + * currently registered, an attempt will be made to load the + * driver as a plugin. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5P_set_driver_by_name(H5P_genplist_t *plist, const char *driver_name, const char *driver_config, + hbool_t app_ref) +{ + hid_t new_driver_id = H5I_INVALID_HID; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(FAIL) + + HDassert(plist); + HDassert(driver_name); + + /* Register the driver */ + if ((new_driver_id = H5FD_register_driver_by_name(driver_name, app_ref)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTREGISTER, FAIL, "unable to register VFD") + + /* Set the driver */ + if (H5P_set_driver(plist, new_driver_id, NULL, driver_config) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set driver info") + +done: + if (ret_value < 0) { + if (new_driver_id >= 0 && H5I_dec_app_ref(new_driver_id) < 0) + HDONE_ERROR(H5E_PLIST, H5E_CANTDEC, FAIL, "can't decrement count on VFD ID") + } + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P_set_driver_by_name() */ + +/*------------------------------------------------------------------------- + * Function: H5Pset_driver_by_name + * + * Purpose: Set the file driver name (DRIVER_NAME) for a file access + * property list (PLIST_ID) and supply an optional string + * containing the driver-specific properties (DRIVER_CONFIG). + * The driver properties string will be copied into the + * property list. + * + * If the file driver specified by DRIVER_NAME is not + * currently registered, an attempt will be made to load the + * driver as a plugin. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pset_driver_by_name(hid_t plist_id, const char *driver_name, const char *driver_config) +{ + H5P_genplist_t *plist; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE3("e", "i*s*s", plist_id, driver_name, driver_config); + + /* Check arguments */ + if (NULL == (plist = (H5P_genplist_t *)H5I_object_verify(plist_id, H5I_GENPROP_LST))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list") + if (!driver_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "driver_name parameter cannot be NULL") + if (!*driver_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "driver_name parameter cannot be an empty string") + + /* Set the driver */ + if (H5P_set_driver_by_name(plist, driver_name, driver_config, TRUE) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set driver info") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pset_driver_by_name() */ + +/*------------------------------------------------------------------------- + * Function: H5P_set_driver_by_value + * + * Purpose: Set the file driver value (DRIVER_VALUE) for a file access + * property list (PLIST) and supply an optional string + * containing the driver-specific properties (DRIVER_CONFIG). + * The driver properties string will be copied into the + * property list. + * + * If the file driver specified by DRIVER_VALUE is not + * currently registered, an attempt will be made to load the + * driver as a plugin. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5P_set_driver_by_value(H5P_genplist_t *plist, H5FD_class_value_t driver_value, const char *driver_config, + hbool_t app_ref) +{ + hid_t new_driver_id = H5I_INVALID_HID; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(FAIL) + + HDassert(plist); + HDassert(driver_value >= 0); + + /* Register the driver */ + if ((new_driver_id = H5FD_register_driver_by_value(driver_value, app_ref)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTREGISTER, FAIL, "unable to register VFD") + + /* Set the driver */ + if (H5P_set_driver(plist, new_driver_id, NULL, driver_config) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set driver info") + +done: + if (ret_value < 0) { + if (new_driver_id >= 0 && H5I_dec_app_ref(new_driver_id) < 0) + HDONE_ERROR(H5E_PLIST, H5E_CANTDEC, FAIL, "can't decrement count on VFD ID") + } + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P_set_driver_by_value() */ + +/*------------------------------------------------------------------------- + * Function: H5Pset_driver_by_value + * + * Purpose: Set the file driver value (DRIVER_VALUE) for a file access + * property list (PLIST_ID) and supply an optional string + * containing the driver-specific properties (DRIVER_CONFIG). + * The driver properties string will be copied into the + * property list. + * + * If the file driver specified by DRIVER_VALUE is not + * currently registered, an attempt will be made to load the + * driver as a plugin. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pset_driver_by_value(hid_t plist_id, H5FD_class_value_t driver_value, const char *driver_config) +{ + H5P_genplist_t *plist; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE3("e", "iDV*s", plist_id, driver_value, driver_config); + + /* Check arguments */ + if (NULL == (plist = (H5P_genplist_t *)H5I_object_verify(plist_id, H5I_GENPROP_LST))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list") + if (driver_value < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "negative VFD value is disallowed") + + /* Set the driver */ + if (H5P_set_driver_by_value(plist, driver_value, driver_config, TRUE) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set driver info") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pset_driver_by_value() */ + +/*------------------------------------------------------------------------- * Function: H5P_peek_driver * * Purpose: Return the ID of the low-level file driver. PLIST_ID should @@ -1014,7 +1423,7 @@ H5P_peek_driver(H5P_genplist_t *plist) /* Get the current driver ID */ if (TRUE == H5P_isa_class(plist->plist_id, H5P_FILE_ACCESS)) { - H5FD_driver_prop_t driver_prop; /* Property for driver ID & info */ + H5FD_driver_prop_t driver_prop; /* Property for driver ID, info & configuration string */ if (H5P_peek(plist, H5F_ACS_FILE_DRV_NAME, &driver_prop) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get driver ID") @@ -1098,7 +1507,7 @@ H5P_peek_driver_info(H5P_genplist_t *plist) /* Get the current driver info */ if (TRUE == H5P_isa_class(plist->plist_id, H5P_FILE_ACCESS)) { - H5FD_driver_prop_t driver_prop; /* Property for driver ID & info */ + H5FD_driver_prop_t driver_prop; /* Property for driver ID, info & configuration string */ if (H5P_peek(plist, H5F_ACS_FILE_DRV_NAME, &driver_prop) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get driver info") @@ -1151,13 +1560,104 @@ done: } /* end H5Pget_driver_info() */ /*------------------------------------------------------------------------- + * Function: H5P_peek_driver_config_str + * + * Purpose: Returns a pointer directly to the file driver configuration + * string of a file access property list. + * + * Return: Success: Ptr to *uncopied* driver configuration string, if + * any. + * + * Failure: NULL. NULL is also returned if the driver has not + * been configured with a driver configuration string. + * + *------------------------------------------------------------------------- + */ +const char * +H5P_peek_driver_config_str(H5P_genplist_t *plist) +{ + const char *ret_value = NULL; /* Return value */ + + FUNC_ENTER_NOAPI(NULL) + + /* Get the current driver configuration string */ + if (TRUE == H5P_isa_class(plist->plist_id, H5P_FILE_ACCESS)) { + H5FD_driver_prop_t driver_prop; /* Property for driver ID, info & configuration string */ + + if (H5P_peek(plist, H5F_ACS_FILE_DRV_NAME, &driver_prop) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get driver configuration string") + ret_value = driver_prop.driver_config_str; + } /* end if */ + else + HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, NULL, "not a file access property list") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P_peek_driver_config_str() */ + +/*------------------------------------------------------------------------- + * Function: H5Pget_driver_config_str + * + * Purpose: Retrieves a string representation of the configuration for + * the driver set on the given FAPL. The returned string can + * be used to configure the same driver in an identical way. + * + * `config_buf` may be NULL, in which case the length of the + * driver configuration string is simply returned. The caller + * can then allocate a buffer of the appropriate size and call + * this routine again. + * + * Return: Length of the driver configuration string on success (not + * including the NUL terminator) + * Negative on failure + * + *------------------------------------------------------------------------- + */ +ssize_t +H5Pget_driver_config_str(hid_t fapl_id, char *config_buf, size_t buf_size) +{ + H5P_genplist_t *plist; /* Property list pointer */ + const char * config_str = NULL; + ssize_t ret_value = -1; + + FUNC_ENTER_API((-1)) + H5TRACE3("Zs", "i*sz", fapl_id, config_buf, buf_size); + + /* Check arguments */ + if (!config_buf && buf_size) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, (-1), "config_buf cannot be NULL if buf_size is non-zero") + + /* Get the plist structure */ + if (NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) + HGOTO_ERROR(H5E_ID, H5E_BADID, (-1), "can't find object for ID") + + /* Retrieve configuration string property */ + if ((config_str = H5P_peek_driver_config_str(plist))) { + size_t config_str_len = HDstrlen(config_str); + + if (config_buf) { + HDstrncpy(config_buf, config_str, MIN(config_str_len + 1, buf_size)); + if (config_str_len >= buf_size) + config_buf[buf_size - 1] = '\0'; + } + + ret_value = (ssize_t)config_str_len; + } + else + ret_value = 0; + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Pget_driver_config_str() */ + +/*------------------------------------------------------------------------- * Function: H5P__file_driver_copy * * Purpose: Copy file driver ID & info. * * Note: This is an "in-place" copy, since this routine gets called * after the top-level copy has been performed and this routine - * finishes the "deep" part of the copy. + * finishes the "deep" part of the copy. * * Return: Success: Non-negative * Failure: Negative @@ -1208,6 +1708,15 @@ H5P__file_driver_copy(void *value) /* Set the driver info for the copy */ info->driver_info = new_pl; } /* end if */ + + /* Copy driver configuration string, if it exists */ + if (info->driver_config_str) { + char *new_config_str = NULL; + + if (NULL == (new_config_str = H5MM_strdup(info->driver_config_str))) + HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "driver configuration string copy failed") + info->driver_config_str = new_config_str; + } /* end if */ } /* end if */ } /* end if */ @@ -1238,7 +1747,6 @@ H5P__file_driver_free(void *value) if (value) { H5FD_driver_prop_t *info = (H5FD_driver_prop_t *)value; /* Driver ID & info struct */ - /* Copy the driver & info, if there is one */ if (info->driver_id > 0) { /* Free the driver info, if it exists */ @@ -1246,6 +1754,9 @@ H5P__file_driver_free(void *value) if (H5FD_free_driver_info(info->driver_id, info->driver_info) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTFREE, FAIL, "driver info free request failed") + /* Free the driver configuration string, if it exists */ + H5MM_xfree_const(info->driver_config_str); + /* Decrement reference count for driver */ if (H5I_dec_ref(info->driver_id) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTDEC, FAIL, "can't decrement reference count for driver ID") @@ -1465,6 +1976,16 @@ H5P__facc_file_driver_cmp(const void *_info1, const void *_info2, size_t H5_ATTR HGOTO_DONE(cmp_value); } /* end if */ + /* Compare driver configuration strings */ + if (info1->driver_config_str == NULL && info2->driver_config_str != NULL) + HGOTO_DONE(-1); + if (info1->driver_config_str != NULL && info2->driver_config_str == NULL) + HGOTO_DONE(1); + if (info1->driver_config_str) { + if (0 != (cmp_value = HDstrcmp(info1->driver_config_str, info2->driver_config_str))) + HGOTO_DONE(cmp_value); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5P__facc_file_driver_cmp() */ @@ -2348,7 +2869,7 @@ done: * * Currently, the only two valid combinations for this routine are: * LOW = H5F_FORMAT_EARLIEST and HIGH = H5F_FORMAT_LATEST (the default - * setting, which creates objects with the ealiest version possible for + * setting, which creates objects with the earliest version possible for * each object, but no upper limit on the version allowed to be created if * a newer version of an object's format is required to support a feature * requested with an HDF5 library API routine), and LOW = H5F_FORMAT_LATEST @@ -2364,7 +2885,7 @@ done: * Note: Eventually we want to add more values to the H5F_libver_t * enumerated type that indicate library release values where the file * format was changed (like "H5F_FORMAT_1_2_0" for the file format changes - * in the 1.2.x release branch and possily even "H5F_FORMAT_1_4_2" for + * in the 1.2.x release branch and possibly even "H5F_FORMAT_1_4_2" for * a change mid-way through the 1.4.x release branch, etc). * * Adding more values will allow applications to make settings like the @@ -2810,7 +3331,7 @@ H5Pset_file_image_callbacks(hid_t fapl_id, H5FD_file_image_callbacks_t *callback HDassert(callbacks_ptr->udata_copy); HDassert(callbacks_ptr->udata_free); if ((info.callbacks.udata = callbacks_ptr->udata_copy(callbacks_ptr->udata)) == NULL) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't copy the suppplied udata") + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't copy the supplied udata") } /* end if */ /* Set values */ @@ -4763,15 +5284,14 @@ H5P__decode_coll_md_read_flag_t(const void **_pp, void *_value) * Function: H5Pset_all_coll_metadata_ops * * Purpose: Tell the library whether the metadata read operations will - * be done collectively (1) or not (0). Default is independent. - * With collective mode, the library will optimize access to - * metadata operations on the file. + * be done collectively (1) or not (0). Default is independent. + * With collective mode, the library will optimize access to + * metadata operations on the file. * * Note: This routine accepts file access property lists, link - * access property lists, attribute access property lists, - * dataset access property lists, group access property lists, - * named datatype access property lists, - * and dataset transfer property lists. + * access property lists, attribute access property lists, + * dataset access property lists, group access property lists + * and named datatype access property lists. * * Return: Non-negative on success/Negative on failure * @@ -4791,11 +5311,10 @@ H5Pset_all_coll_metadata_ops(hid_t plist_id, hbool_t is_collective) H5TRACE2("e", "ib", plist_id, is_collective); /* Compare the property list's class against the other class */ - /* (Dataset, group, attribute, and named datype access property lists + /* (Dataset, group, attribute, and named datatype access property lists * are sub-classes of link access property lists -QAK) */ - if (TRUE != H5P_isa_class(plist_id, H5P_LINK_ACCESS) && - TRUE != H5P_isa_class(plist_id, H5P_FILE_ACCESS) && TRUE != H5P_isa_class(plist_id, H5P_DATASET_XFER)) + if (TRUE != H5P_isa_class(plist_id, H5P_LINK_ACCESS) && TRUE != H5P_isa_class(plist_id, H5P_FILE_ACCESS)) HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "property list is not an access plist") /* set property to either TRUE if > 0, or FALSE otherwise */ @@ -4822,10 +5341,9 @@ done: * Purpose: Gets information about collective metadata read mode. * * Note: This routine accepts file access property lists, link - * access property lists, attribute access property lists, - * dataset access property lists, group access property lists, - * named datatype access property lists, - * and dataset transfer property lists. + * access property lists, attribute access property lists, + * dataset access property lists, group access property lists, + * and named datatype access property lists. * * Return: Non-negative on success/Negative on failure * @@ -4843,11 +5361,10 @@ H5Pget_all_coll_metadata_ops(hid_t plist_id, hbool_t *is_collective /*out*/) H5TRACE2("e", "ix", plist_id, is_collective); /* Compare the property list's class against the other class */ - /* (Dataset, group, attribute, and named datype access property lists + /* (Dataset, group, attribute, and named datatype access property lists * are sub-classes of link access property lists -QAK) */ - if (TRUE != H5P_isa_class(plist_id, H5P_LINK_ACCESS) && - TRUE != H5P_isa_class(plist_id, H5P_FILE_ACCESS) && TRUE != H5P_isa_class(plist_id, H5P_DATASET_XFER)) + if (TRUE != H5P_isa_class(plist_id, H5P_LINK_ACCESS) && TRUE != H5P_isa_class(plist_id, H5P_FILE_ACCESS)) HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "property list is not an access plist") /* Get value */ diff --git a/src/H5Pint.c b/src/H5Pint.c index 9530d87..cc3f10b 100644 --- a/src/H5Pint.c +++ b/src/H5Pint.c @@ -123,76 +123,77 @@ static herr_t H5P__free_del_name_cb(void *item, void H5_ATTR_UNUSED *key, void H /* * Predefined property list classes. These are initialized at runtime by - * H5P__init_package() in this source file. + * H5P_init() in this source file. */ -hid_t H5P_CLS_ROOT_ID_g = H5I_INVALID_HID; -H5P_genclass_t *H5P_CLS_ROOT_g = NULL; -hid_t H5P_CLS_OBJECT_CREATE_ID_g = H5I_INVALID_HID; -H5P_genclass_t *H5P_CLS_OBJECT_CREATE_g = NULL; -hid_t H5P_CLS_FILE_CREATE_ID_g = H5I_INVALID_HID; -H5P_genclass_t *H5P_CLS_FILE_CREATE_g = NULL; -hid_t H5P_CLS_FILE_ACCESS_ID_g = H5I_INVALID_HID; -H5P_genclass_t *H5P_CLS_FILE_ACCESS_g = NULL; -hid_t H5P_CLS_DATASET_CREATE_ID_g = H5I_INVALID_HID; -H5P_genclass_t *H5P_CLS_DATASET_CREATE_g = NULL; +hid_t H5P_CLS_ROOT_ID_g = H5I_INVALID_HID; +H5P_genclass_t *H5P_CLS_ROOT_g = NULL; + +hid_t H5P_CLS_ATTRIBUTE_ACCESS_ID_g = H5I_INVALID_HID; +H5P_genclass_t *H5P_CLS_ATTRIBUTE_ACCESS_g = NULL; +hid_t H5P_CLS_ATTRIBUTE_CREATE_ID_g = H5I_INVALID_HID; +H5P_genclass_t *H5P_CLS_ATTRIBUTE_CREATE_g = NULL; hid_t H5P_CLS_DATASET_ACCESS_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_DATASET_ACCESS_g = NULL; +hid_t H5P_CLS_DATASET_CREATE_ID_g = H5I_INVALID_HID; +H5P_genclass_t *H5P_CLS_DATASET_CREATE_g = NULL; hid_t H5P_CLS_DATASET_XFER_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_DATASET_XFER_g = NULL; +hid_t H5P_CLS_DATATYPE_ACCESS_ID_g = H5I_INVALID_HID; +H5P_genclass_t *H5P_CLS_DATATYPE_ACCESS_g = NULL; +hid_t H5P_CLS_DATATYPE_CREATE_ID_g = H5I_INVALID_HID; +H5P_genclass_t *H5P_CLS_DATATYPE_CREATE_g = NULL; +hid_t H5P_CLS_FILE_ACCESS_ID_g = H5I_INVALID_HID; +H5P_genclass_t *H5P_CLS_FILE_ACCESS_g = NULL; +hid_t H5P_CLS_FILE_CREATE_ID_g = H5I_INVALID_HID; +H5P_genclass_t *H5P_CLS_FILE_CREATE_g = NULL; hid_t H5P_CLS_FILE_MOUNT_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_FILE_MOUNT_g = NULL; -hid_t H5P_CLS_GROUP_CREATE_ID_g = H5I_INVALID_HID; -H5P_genclass_t *H5P_CLS_GROUP_CREATE_g = NULL; hid_t H5P_CLS_GROUP_ACCESS_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_GROUP_ACCESS_g = NULL; -hid_t H5P_CLS_DATATYPE_CREATE_ID_g = H5I_INVALID_HID; -H5P_genclass_t *H5P_CLS_DATATYPE_CREATE_g = NULL; -hid_t H5P_CLS_DATATYPE_ACCESS_ID_g = H5I_INVALID_HID; -H5P_genclass_t *H5P_CLS_DATATYPE_ACCESS_g = NULL; -hid_t H5P_CLS_MAP_CREATE_ID_g = H5I_INVALID_HID; -H5P_genclass_t *H5P_CLS_MAP_CREATE_g = NULL; +hid_t H5P_CLS_GROUP_CREATE_ID_g = H5I_INVALID_HID; +H5P_genclass_t *H5P_CLS_GROUP_CREATE_g = NULL; +hid_t H5P_CLS_LINK_ACCESS_ID_g = H5I_INVALID_HID; +H5P_genclass_t *H5P_CLS_LINK_ACCESS_g = NULL; +hid_t H5P_CLS_LINK_CREATE_ID_g = H5I_INVALID_HID; +H5P_genclass_t *H5P_CLS_LINK_CREATE_g = NULL; hid_t H5P_CLS_MAP_ACCESS_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_MAP_ACCESS_g = NULL; -hid_t H5P_CLS_ATTRIBUTE_CREATE_ID_g = H5I_INVALID_HID; -H5P_genclass_t *H5P_CLS_ATTRIBUTE_CREATE_g = NULL; -hid_t H5P_CLS_ATTRIBUTE_ACCESS_ID_g = H5I_INVALID_HID; -H5P_genclass_t *H5P_CLS_ATTRIBUTE_ACCESS_g = NULL; +hid_t H5P_CLS_MAP_CREATE_ID_g = H5I_INVALID_HID; +H5P_genclass_t *H5P_CLS_MAP_CREATE_g = NULL; hid_t H5P_CLS_OBJECT_COPY_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_OBJECT_COPY_g = NULL; -hid_t H5P_CLS_LINK_CREATE_ID_g = H5I_INVALID_HID; -H5P_genclass_t *H5P_CLS_LINK_CREATE_g = NULL; -hid_t H5P_CLS_LINK_ACCESS_ID_g = H5I_INVALID_HID; -H5P_genclass_t *H5P_CLS_LINK_ACCESS_g = NULL; +hid_t H5P_CLS_OBJECT_CREATE_ID_g = H5I_INVALID_HID; +H5P_genclass_t *H5P_CLS_OBJECT_CREATE_g = NULL; +hid_t H5P_CLS_REFERENCE_ACCESS_ID_g = H5I_INVALID_HID; +H5P_genclass_t *H5P_CLS_REFERENCE_ACCESS_g = NULL; hid_t H5P_CLS_STRING_CREATE_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_STRING_CREATE_g = NULL; hid_t H5P_CLS_VOL_INITIALIZE_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_VOL_INITIALIZE_g = NULL; -hid_t H5P_CLS_REFERENCE_ACCESS_ID_g = H5I_INVALID_HID; -H5P_genclass_t *H5P_CLS_REFERENCE_ACCESS_g = NULL; /* * Predefined property lists for each predefined class. These are initialized - * at runtime by H5P__init_package() in this source file. + * at runtime by H5P_init() in this source file. */ -hid_t H5P_LST_FILE_CREATE_ID_g = H5I_INVALID_HID; -hid_t H5P_LST_FILE_ACCESS_ID_g = H5I_INVALID_HID; -hid_t H5P_LST_DATASET_CREATE_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_ATTRIBUTE_ACCESS_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_ATTRIBUTE_CREATE_ID_g = H5I_INVALID_HID; hid_t H5P_LST_DATASET_ACCESS_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_DATASET_CREATE_ID_g = H5I_INVALID_HID; hid_t H5P_LST_DATASET_XFER_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_DATATYPE_ACCESS_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_DATATYPE_CREATE_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_FILE_ACCESS_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_FILE_CREATE_ID_g = H5I_INVALID_HID; hid_t H5P_LST_FILE_MOUNT_ID_g = H5I_INVALID_HID; -hid_t H5P_LST_GROUP_CREATE_ID_g = H5I_INVALID_HID; hid_t H5P_LST_GROUP_ACCESS_ID_g = H5I_INVALID_HID; -hid_t H5P_LST_DATATYPE_CREATE_ID_g = H5I_INVALID_HID; -hid_t H5P_LST_DATATYPE_ACCESS_ID_g = H5I_INVALID_HID; -hid_t H5P_LST_MAP_CREATE_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_GROUP_CREATE_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_LINK_ACCESS_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_LINK_CREATE_ID_g = H5I_INVALID_HID; hid_t H5P_LST_MAP_ACCESS_ID_g = H5I_INVALID_HID; -hid_t H5P_LST_ATTRIBUTE_CREATE_ID_g = H5I_INVALID_HID; -hid_t H5P_LST_ATTRIBUTE_ACCESS_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_MAP_CREATE_ID_g = H5I_INVALID_HID; hid_t H5P_LST_OBJECT_COPY_ID_g = H5I_INVALID_HID; -hid_t H5P_LST_LINK_CREATE_ID_g = H5I_INVALID_HID; -hid_t H5P_LST_LINK_ACCESS_ID_g = H5I_INVALID_HID; -hid_t H5P_LST_VOL_INITIALIZE_ID_g = H5I_INVALID_HID; hid_t H5P_LST_REFERENCE_ACCESS_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_VOL_INITIALIZE_ID_g = H5I_INVALID_HID; /* Root property list class library initialization object */ const H5P_libclass_t H5P_CLS_ROOT[1] = {{ @@ -412,48 +413,29 @@ static const H5I_class_t H5I_GENPROPLST_CLS[1] = {{ }}; /*------------------------------------------------------------------------- - * Function: H5P_init + * Function: H5P_init_phase1 * - * Purpose: Initialize the interface from some other layer. + * Purpose: Initialize the interface from some other layer. This should + * be followed with a call to H5P_init_phase2 after the H5P + * interface is completely setup. * - * Return: Success: non-negative - * Failure: negative + * Return: Success: non-negative + * Failure: negative * - * Programmer: Quincey Koziol + * Programmer: Quincey Koziol * Saturday, March 4, 2000 * *------------------------------------------------------------------------- */ herr_t -H5P_init(void) +H5P_init_phase1(void) { + size_t tot_init = 0; /* Total # of classes initialized */ + size_t pass_init; /* # of classes initialized in each pass */ + size_t u; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) - /* FUNC_ENTER() does all the work */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5P_init() */ - -/*-------------------------------------------------------------------------- -NAME - H5P__init_package -- Initialize interface-specific information -USAGE - herr_t H5P__init_package() -RETURNS - Non-negative on success/Negative on failure -DESCRIPTION - Initializes any interface-specific data or routines. ---------------------------------------------------------------------------*/ -herr_t -H5P__init_package(void) -{ - size_t tot_init; /* Total # of classes initialized */ - size_t pass_init; /* # of classes initialized in each pass */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_PACKAGE /* Sanity check */ HDcompile_assert(H5P_TYPE_REFERENCE_ACCESS == (H5P_TYPE_MAX_TYPE - 1)); @@ -472,8 +454,6 @@ H5P__init_package(void) */ tot_init = 0; do { - size_t u; /* Local index variable */ - /* Reset pass initialization counter */ pass_init = 0; @@ -523,8 +503,59 @@ H5P__init_package(void) HDassert(tot_init == NELMTS(init_class)); done: + if (ret_value < 0 && tot_init > 0) { + /* First uninitialize all default property lists */ + H5I_clear_type(H5I_GENPROP_LST, FALSE, FALSE); + + /* Then uninitialize any initialized libclass */ + for (u = 0; u < NELMTS(init_class); u++) { + H5P_libclass_t const *lib_class = init_class[u]; /* Current class to operate on */ + + HDassert(lib_class->class_id); + if (*lib_class->class_id >= 0) { + /* Close the class ID */ + if (H5I_dec_ref(*lib_class->class_id) < 0) + HDONE_ERROR(H5E_PLIST, H5E_CLOSEERROR, FAIL, "unable to close property list class ID") + } + else if (lib_class->pclass && *lib_class->pclass) { + /* Close a half-initialized pclass */ + if (H5P__close_class(*lib_class->pclass) < 0) + HDONE_ERROR(H5E_PLIST, H5E_CLOSEERROR, FAIL, "unable to close property list class") + } + } + } + + FUNC_LEAVE_NOAPI(ret_value) +} + +/*------------------------------------------------------------------------- + * Function: H5P_init_phase2 + * + * Purpose: Finish initializing the interface from some other package. + * + * Note: This is broken out as a separate routine so that the + * library's default VFL driver can be chosen and initialized + * after the entire H5P interface has been initialized. + * + * Return: Success: Non-negative + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +herr_t +H5P_init_phase2(void) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(FAIL) + + /* Set up the default VFL driver */ + if (H5P__facc_set_def_driver() < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "unable to set default VFL driver") + +done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5P__init_package() */ +} /* end H5P_init_phase2() */ /*-------------------------------------------------------------------------- NAME @@ -550,77 +581,107 @@ H5P_term_package(void) FUNC_ENTER_NOAPI_NOINIT_NOERR - if (H5_PKG_INIT_VAR) { - int64_t nlist, nclass; - - /* Destroy HDF5 library property classes & lists */ - - /* Check if there are any open property list classes or lists */ - nclass = H5I_nmembers(H5I_GENPROP_CLS); - nlist = H5I_nmembers(H5I_GENPROP_LST); - - /* If there are any open classes or groups, attempt to get rid of them. */ - if ((nclass + nlist) > 0) { - /* Clear the lists */ - if (nlist > 0) { - (void)H5I_clear_type(H5I_GENPROP_LST, FALSE, FALSE); - - /* Reset the default property lists, if they've been closed */ - if (H5I_nmembers(H5I_GENPROP_LST) == 0) { - H5P_LST_FILE_CREATE_ID_g = H5P_LST_FILE_ACCESS_ID_g = H5P_LST_DATASET_CREATE_ID_g = - H5P_LST_DATASET_ACCESS_ID_g = H5P_LST_DATASET_XFER_ID_g = H5P_LST_GROUP_CREATE_ID_g = - H5P_LST_GROUP_ACCESS_ID_g = H5P_LST_DATATYPE_CREATE_ID_g = - H5P_LST_DATATYPE_ACCESS_ID_g = H5P_LST_MAP_CREATE_ID_g = - H5P_LST_MAP_ACCESS_ID_g = H5P_LST_ATTRIBUTE_CREATE_ID_g = - H5P_LST_ATTRIBUTE_ACCESS_ID_g = H5P_LST_OBJECT_COPY_ID_g = - H5P_LST_LINK_CREATE_ID_g = H5P_LST_LINK_ACCESS_ID_g = - H5P_LST_VOL_INITIALIZE_ID_g = H5P_LST_REFERENCE_ACCESS_ID_g = - H5P_LST_FILE_MOUNT_ID_g = H5I_INVALID_HID; - } /* end if */ - } /* end if */ - - /* Only attempt to close the classes after all the lists are closed */ - if (nlist == 0 && nclass > 0) { - (void)H5I_clear_type(H5I_GENPROP_CLS, FALSE, FALSE); - - /* Reset the default property classes, if they've been closed */ - if (H5I_nmembers(H5I_GENPROP_CLS) == 0) { - H5P_CLS_ROOT_g = H5P_CLS_OBJECT_CREATE_g = H5P_CLS_FILE_CREATE_g = H5P_CLS_FILE_ACCESS_g = - H5P_CLS_DATASET_CREATE_g = H5P_CLS_DATASET_ACCESS_g = H5P_CLS_DATASET_XFER_g = - H5P_CLS_GROUP_CREATE_g = H5P_CLS_GROUP_ACCESS_g = H5P_CLS_DATATYPE_CREATE_g = - H5P_CLS_DATATYPE_ACCESS_g = H5P_CLS_MAP_CREATE_g = H5P_CLS_MAP_ACCESS_g = - H5P_CLS_STRING_CREATE_g = H5P_CLS_ATTRIBUTE_CREATE_g = - H5P_CLS_ATTRIBUTE_ACCESS_g = H5P_CLS_OBJECT_COPY_g = - H5P_CLS_LINK_CREATE_g = H5P_CLS_LINK_ACCESS_g = - H5P_CLS_VOL_INITIALIZE_g = H5P_CLS_REFERENCE_ACCESS_g = - H5P_CLS_FILE_MOUNT_g = NULL; - - H5P_CLS_ROOT_ID_g = H5P_CLS_OBJECT_CREATE_ID_g = H5P_CLS_FILE_CREATE_ID_g = - H5P_CLS_FILE_ACCESS_ID_g = H5P_CLS_DATASET_CREATE_ID_g = H5P_CLS_DATASET_ACCESS_ID_g = - H5P_CLS_DATASET_XFER_ID_g = H5P_CLS_GROUP_CREATE_ID_g = - H5P_CLS_GROUP_ACCESS_ID_g = H5P_CLS_DATATYPE_CREATE_ID_g = - H5P_CLS_DATATYPE_ACCESS_ID_g = H5P_CLS_MAP_CREATE_ID_g = - H5P_CLS_MAP_ACCESS_ID_g = H5P_CLS_STRING_CREATE_ID_g = - H5P_CLS_ATTRIBUTE_CREATE_ID_g = H5P_CLS_ATTRIBUTE_ACCESS_ID_g = - H5P_CLS_OBJECT_COPY_ID_g = H5P_CLS_LINK_CREATE_ID_g = - H5P_CLS_LINK_ACCESS_ID_g = H5P_CLS_VOL_INITIALIZE_ID_g = - H5P_CLS_REFERENCE_ACCESS_ID_g = - H5P_CLS_FILE_MOUNT_ID_g = H5I_INVALID_HID; - } /* end if */ - } /* end if */ + int64_t nlist, nclass; + + /* Destroy HDF5 library property classes & lists */ + + /* Check if there are any open property list classes or lists */ + nclass = H5I_nmembers(H5I_GENPROP_CLS); + nlist = H5I_nmembers(H5I_GENPROP_LST); + + /* If there are any open classes or groups, attempt to get rid of them. */ + if ((nclass + nlist) > 0) { + /* Clear the lists */ + if (nlist > 0) { + (void)H5I_clear_type(H5I_GENPROP_LST, FALSE, FALSE); + + /* Reset the default property lists, if they've been closed */ + if (H5I_nmembers(H5I_GENPROP_LST) == 0) { + H5P_LST_ATTRIBUTE_ACCESS_ID_g = H5I_INVALID_HID; + H5P_LST_ATTRIBUTE_CREATE_ID_g = H5I_INVALID_HID; + H5P_LST_DATASET_ACCESS_ID_g = H5I_INVALID_HID; + H5P_LST_DATASET_CREATE_ID_g = H5I_INVALID_HID; + H5P_LST_DATASET_XFER_ID_g = H5I_INVALID_HID; + H5P_LST_DATATYPE_ACCESS_ID_g = H5I_INVALID_HID; + H5P_LST_DATATYPE_CREATE_ID_g = H5I_INVALID_HID; + H5P_LST_FILE_ACCESS_ID_g = H5I_INVALID_HID; + H5P_LST_FILE_CREATE_ID_g = H5I_INVALID_HID; + H5P_LST_FILE_MOUNT_ID_g = H5I_INVALID_HID; + H5P_LST_GROUP_ACCESS_ID_g = H5I_INVALID_HID; + H5P_LST_GROUP_CREATE_ID_g = H5I_INVALID_HID; + H5P_LST_LINK_ACCESS_ID_g = H5I_INVALID_HID; + H5P_LST_LINK_CREATE_ID_g = H5I_INVALID_HID; + H5P_LST_MAP_ACCESS_ID_g = H5I_INVALID_HID; + H5P_LST_MAP_CREATE_ID_g = H5I_INVALID_HID; + H5P_LST_OBJECT_COPY_ID_g = H5I_INVALID_HID; + H5P_LST_REFERENCE_ACCESS_ID_g = H5I_INVALID_HID; + H5P_LST_VOL_INITIALIZE_ID_g = H5I_INVALID_HID; + } + } - n++; /*H5I*/ + /* Only attempt to close the classes after all the lists are closed */ + if (nlist == 0 && nclass > 0) { + (void)H5I_clear_type(H5I_GENPROP_CLS, FALSE, FALSE); + + /* Reset the default property classes and IDs if they've been closed */ + if (H5I_nmembers(H5I_GENPROP_CLS) == 0) { + H5P_CLS_ROOT_g = NULL; + + H5P_CLS_ATTRIBUTE_ACCESS_g = NULL; + H5P_CLS_ATTRIBUTE_CREATE_g = NULL; + H5P_CLS_DATASET_ACCESS_g = NULL; + H5P_CLS_DATASET_CREATE_g = NULL; + H5P_CLS_DATASET_XFER_g = NULL; + H5P_CLS_DATATYPE_ACCESS_g = NULL; + H5P_CLS_DATATYPE_CREATE_g = NULL; + H5P_CLS_FILE_ACCESS_g = NULL; + H5P_CLS_FILE_CREATE_g = NULL; + H5P_CLS_FILE_MOUNT_g = NULL; + H5P_CLS_GROUP_ACCESS_g = NULL; + H5P_CLS_GROUP_CREATE_g = NULL; + H5P_CLS_LINK_ACCESS_g = NULL; + H5P_CLS_LINK_CREATE_g = NULL; + H5P_CLS_MAP_ACCESS_g = NULL; + H5P_CLS_MAP_CREATE_g = NULL; + H5P_CLS_OBJECT_COPY_g = NULL; + H5P_CLS_OBJECT_CREATE_g = NULL; + H5P_CLS_REFERENCE_ACCESS_g = NULL; + H5P_CLS_STRING_CREATE_g = NULL; + H5P_CLS_VOL_INITIALIZE_g = NULL; + + H5P_CLS_ROOT_ID_g = H5I_INVALID_HID; + + H5P_CLS_ATTRIBUTE_ACCESS_ID_g = H5I_INVALID_HID; + H5P_CLS_ATTRIBUTE_CREATE_ID_g = H5I_INVALID_HID; + H5P_CLS_DATASET_ACCESS_ID_g = H5I_INVALID_HID; + H5P_CLS_DATASET_CREATE_ID_g = H5I_INVALID_HID; + H5P_CLS_DATASET_XFER_ID_g = H5I_INVALID_HID; + H5P_CLS_DATATYPE_ACCESS_ID_g = H5I_INVALID_HID; + H5P_CLS_DATATYPE_CREATE_ID_g = H5I_INVALID_HID; + H5P_CLS_FILE_ACCESS_ID_g = H5I_INVALID_HID; + H5P_CLS_FILE_CREATE_ID_g = H5I_INVALID_HID; + H5P_CLS_FILE_MOUNT_ID_g = H5I_INVALID_HID; + H5P_CLS_GROUP_ACCESS_ID_g = H5I_INVALID_HID; + H5P_CLS_GROUP_CREATE_ID_g = H5I_INVALID_HID; + H5P_CLS_LINK_ACCESS_ID_g = H5I_INVALID_HID; + H5P_CLS_LINK_CREATE_ID_g = H5I_INVALID_HID; + H5P_CLS_MAP_ACCESS_ID_g = H5I_INVALID_HID; + H5P_CLS_MAP_CREATE_ID_g = H5I_INVALID_HID; + H5P_CLS_OBJECT_COPY_ID_g = H5I_INVALID_HID; + H5P_CLS_OBJECT_CREATE_ID_g = H5I_INVALID_HID; + H5P_CLS_REFERENCE_ACCESS_ID_g = H5I_INVALID_HID; + H5P_CLS_STRING_CREATE_ID_g = H5I_INVALID_HID; + H5P_CLS_VOL_INITIALIZE_ID_g = H5I_INVALID_HID; + } } - else { - /* Destroy the property list and class id groups */ - n += (H5I_dec_type_ref(H5I_GENPROP_LST) > 0); - n += (H5I_dec_type_ref(H5I_GENPROP_CLS) > 0); - /* Mark closed */ - if (0 == n) - H5_PKG_INIT_VAR = FALSE; - } /* end else */ - } /* end if */ + n++; /*H5I*/ + } + else { + /* Destroy the property list and class id groups */ + n += (H5I_dec_type_ref(H5I_GENPROP_LST) > 0); + n += (H5I_dec_type_ref(H5I_GENPROP_CLS) > 0); + } /* end else */ FUNC_LEAVE_NOAPI(n) } /* end H5P_term_package() */ @@ -3242,7 +3303,7 @@ done: NAME H5P_exist_plist PURPOSE - Internal routine to query the existance of a property in a property list. + Internal routine to query the existence of a property in a property list. USAGE htri_t H5P_exist_plist(plist, name) const H5P_genplist_t *plist; IN: Property list to check @@ -3301,7 +3362,7 @@ done: NAME H5P__exist_pclass PURPOSE - Internal routine to query the existance of a property in a property class. + Internal routine to query the existence of a property in a property class. USAGE herr_t H5P__exist_pclass(pclass, name) H5P_genclass_t *pclass; IN: Property class to check @@ -3501,7 +3562,7 @@ H5P_get_nprops_pclass(const H5P_genclass_t *pclass, size_t *nprops, hbool_t recu { herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR HDassert(pclass); HDassert(nprops); @@ -3516,7 +3577,6 @@ H5P_get_nprops_pclass(const H5P_genclass_t *pclass, size_t *nprops, hbool_t recu *nprops += pclass->nprops; } /* end while */ -done: FUNC_LEAVE_NOAPI(ret_value) } /* H5P_get_nprops_pclass() */ @@ -3817,7 +3877,7 @@ H5P__cmp_plist_cb(H5P_genprop_t *prop, void *_udata) /* Check if the property exists in the second property list */ if ((prop2_exist = H5P_exist_plist(udata->plist2, prop->name)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, H5_ITER_ERROR, "can't lookup existance of property?") + HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, H5_ITER_ERROR, "can't lookup existence of property?") if (prop2_exist) { const H5P_genprop_t *prop2; /* Pointer to property in second plist */ @@ -3947,7 +4007,7 @@ H5P_class_isa(const H5P_genclass_t *pclass1, const H5P_genclass_t *pclass2) { htri_t ret_value = FAIL; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR HDassert(pclass1); HDassert(pclass2); @@ -4768,7 +4828,7 @@ done: Returns non-negative on success, negative on failure. DESCRIPTION Removes a property from a property list. Both properties which were - in existance when the property list was created (i.e. properties registered + in existence when the property list was created (i.e. properties registered with H5Pregister2) and properties added to the list after it was created (i.e. added with H5Pinsert2) may be removed from a property list. Properties do not need to be removed a property list before the list itself @@ -4849,7 +4909,7 @@ H5P__copy_prop_plist(hid_t dst_id, hid_t src_id, const char *name) NULL == (dst_plist = (H5P_genplist_t *)H5I_object(dst_id))) HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "property object doesn't exist") - /* If the property exists in the destination alread */ + /* If the property exists in the destination already */ if (NULL != H5P__find_prop_plist(dst_plist, name)) { /* Delete the property from the destination list, calling the 'close' callback if necessary */ if (H5P_remove(dst_plist, name) < 0) @@ -5249,14 +5309,13 @@ H5P_get_class_name(H5P_genclass_t *pclass) { char *ret_value = NULL; /* Return value */ - FUNC_ENTER_NOAPI(NULL) + FUNC_ENTER_NOAPI_NOERR HDassert(pclass); /* Get class name */ ret_value = H5MM_xstrdup(pclass->name); -done: FUNC_LEAVE_NOAPI(ret_value) } /* H5P_get_class_name() */ diff --git a/src/H5Pmodule.h b/src/H5Pmodule.h index 6e92e66..66a9574 100644 --- a/src/H5Pmodule.h +++ b/src/H5Pmodule.h @@ -111,7 +111,8 @@ * * \defgroup GAPL General Access Properties * \ingroup H5P - * \todo Should this be as standalone page? + * The functions in this section can be applied to different kinds of property + * lists. * * \defgroup GCPL Group Creation Properties * \ingroup H5P diff --git a/src/H5Pocpl.c b/src/H5Pocpl.c index edb0cca..06d9f85 100644 --- a/src/H5Pocpl.c +++ b/src/H5Pocpl.c @@ -482,7 +482,7 @@ done: * transfer property list. The FLAGS argument specifies certain * general properties of the filter and is documented below. * The CD_VALUES is an array of CD_NELMTS integers which are - * auxiliary data for the filter. The integer vlues will be + * auxiliary data for the filter. The integer values will be * stored in the dataset object header as part of the filter * information. * @@ -543,7 +543,7 @@ done: * transfer property list. The FLAGS argument specifies certain * general properties of the filter and is documented below. * The CD_VALUES is an array of CD_NELMTS integers which are - * auxiliary data for the filter. The integer vlues will be + * auxiliary data for the filter. The integer values will be * stored in the dataset object header as part of the filter * information. * @@ -609,7 +609,7 @@ done: * creation property list. The FLAGS argument specifies certain * general properties of the filter and is documented below. * The CD_VALUES is an array of CD_NELMTS integers which are - * auxiliary data for the filter. The integer vlues will be + * auxiliary data for the filter. The integer values will be * stored in the dataset object header as part of the filter * information. * @@ -671,7 +671,7 @@ done: * creation property list. The FLAGS argument specifies certain * general properties of the filter and is documented below. * The CD_VALUES is an array of CD_NELMTS integers which are - * auxiliary data for the filter. The integer vlues will be + * auxiliary data for the filter. The integer values will be * stored in the dataset object header as part of the filter * information. * @@ -782,7 +782,7 @@ done: * CD_NELMTS indicates the number of entries in the CD_VALUES * array allocated by the caller while on exit it contains the * number of values defined by the filter. FILTER_CONFIG is a bit - * field contaning encode/decode flags from H5Zpublic.h. The IDX + * field containing encode/decode flags from H5Zpublic.h. The IDX * should be a value between zero and N-1 as described for * H5Pget_nfilters() and the function will return failure if the * filter number is out of range. @@ -867,7 +867,7 @@ done: * CD_NELMTS indicates the number of entries in the CD_VALUES * array allocated by the caller while on exit it contains the * number of values defined by the filter. FILTER_CONFIG is a bit - * field contaning encode/decode flags from H5Zpublic.h. The ID + * field containing encode/decode flags from H5Zpublic.h. The ID * should be the filter ID to retrieve the parameters for. If the * filter is not set for the property list, an error will be returned. * @@ -916,7 +916,7 @@ done: * CD_NELMTS indicates the number of entries in the CD_VALUES * array allocated by the caller while on exit it contains the * number of values defined by the filter. FILTER_CONFIG is a bit - * field contaning encode/decode flags from H5Zpublic.h. The ID + * field containing encode/decode flags from H5Zpublic.h. The ID * should be the filter ID to retrieve the parameters for. If the * filter is not set for the property list, an error will be returned. * @@ -940,6 +940,8 @@ H5Pget_filter_by_id2(hid_t plist_id, H5Z_filter_t id, unsigned int *flags /*out* H5TRACE8("e", "iZfx*zxzxx", plist_id, id, flags, cd_nelmts, cd_values, namelen, name, filter_config); /* Check args */ + if (id < 0 || id > H5Z_FILTER_MAX) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "filter ID value out of range") if (cd_nelmts || cd_values) { /* * It's likely that users forget to initialize this on input, so @@ -1838,6 +1840,8 @@ H5Pget_filter_by_id1(hid_t plist_id, H5Z_filter_t id, unsigned int *flags /*out* H5TRACE7("e", "iZfx*zxzx", plist_id, id, flags, cd_nelmts, cd_values, namelen, name); /* Check args */ + if (id < 0 || id > H5Z_FILTER_MAX) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "filter ID value out of range") if (cd_nelmts || cd_values) { /* * It's likely that users forget to initialize this on input, so diff --git a/src/H5Ppkg.h b/src/H5Ppkg.h index dd43f76..2946931 100644 --- a/src/H5Ppkg.h +++ b/src/H5Ppkg.h @@ -188,6 +188,9 @@ H5_DLL herr_t H5P__decode_double(const void **_pp, void *value); H5_DLL herr_t H5P__encode_coll_md_read_flag_t(const void *value, void **_pp, size_t *size); H5_DLL herr_t H5P__decode_coll_md_read_flag_t(const void **_pp, void *value); +/* Private FAPL routines */ +H5_DLL herr_t H5P__facc_set_def_driver(void); + /* Private OCPL routines */ H5_DLL herr_t H5P__get_filter(const struct H5Z_filter_info_t *filter, unsigned int *flags, size_t *cd_nelmts, unsigned cd_values[], size_t namelen, char name[], unsigned *filter_config); diff --git a/src/H5Pprivate.h b/src/H5Pprivate.h index 6ebe5d3..7cbb397 100644 --- a/src/H5Pprivate.h +++ b/src/H5Pprivate.h @@ -156,8 +156,9 @@ struct H5O_fill_t; struct H5T_t; struct H5VL_connector_prop_t; -/* Package initialization routine */ -H5_DLL herr_t H5P_init(void); +/* Package initialization routines */ +H5_DLL herr_t H5P_init_phase1(void); +H5_DLL herr_t H5P_init_phase2(void); /* Internal versions of API routines */ H5_DLL herr_t H5P_close(H5P_genplist_t *plist); @@ -181,7 +182,13 @@ H5_DLL char * H5P_get_class_name(H5P_genclass_t *pclass); H5_DLL herr_t H5P_get_nprops_pclass(const H5P_genclass_t *pclass, size_t *nprops, hbool_t recurse); H5_DLL hid_t H5P_peek_driver(H5P_genplist_t *plist); H5_DLL const void *H5P_peek_driver_info(H5P_genplist_t *plist); -H5_DLL herr_t H5P_set_driver(H5P_genplist_t *plist, hid_t new_driver_id, const void *new_driver_info); +H5_DLL const char *H5P_peek_driver_config_str(H5P_genplist_t *plist); +H5_DLL herr_t H5P_set_driver(H5P_genplist_t *plist, hid_t new_driver_id, const void *new_driver_info, + const char *new_driver_config_str); +H5_DLL herr_t H5P_set_driver_by_name(H5P_genplist_t *plist, const char *driver_name, + const char *driver_config, hbool_t app_ref); +H5_DLL herr_t H5P_set_driver_by_value(H5P_genplist_t *plist, H5FD_class_value_t driver_value, + const char *driver_config, hbool_t app_ref); H5_DLL herr_t H5P_set_vol(H5P_genplist_t *plist, hid_t vol_id, const void *vol_info); H5_DLL herr_t H5P_reset_vol_class(const H5P_genclass_t *pclass, const struct H5VL_connector_prop_t *vol_prop); H5_DLL herr_t H5P_set_vlen_mem_manager(H5P_genplist_t *plist, H5MM_allocate_t alloc_func, void *alloc_info, diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h index a5c5c37..d0bc2b8 100644 --- a/src/H5Ppublic.h +++ b/src/H5Ppublic.h @@ -116,21 +116,70 @@ extern "C" { /* Define property list class callback function pointer types */ //! <!-- [H5P_cls_create_func_t_snip] --> /** - * \todo Document me! + * \brief Callback function for H5Pcreate_class() + * + * \param[in] prop_id The identifier of the property list class being created + * \param[in] create_data User pointer to any class creation data required + * \return \herr_t + * + * \details This function is called when a new property list of the class + * with which this function was registered is being created. The + * function is called after any registered parent create function is + * called for each property value. + * + * If the create function returns a negative value, the new list is not + * returned to the user and the property list creation routine returns + * an error value. + * + * \since 1.4.0 + * */ typedef herr_t (*H5P_cls_create_func_t)(hid_t prop_id, void *create_data); //! <!-- [H5P_cls_create_func_t_snip] --> //! <!-- [H5P_cls_copy_func_t_snip] --> /** - * \todo Document me! + * \brief Callback function for H5Pcreate_class() + * + * \param[in] new_prop_id The identifier of the property list copy + * \param[in] old_prop_id The identifier of the property list being copied + * \param[in] copy_data User pointer to any copy data required + * \return \herr_t + * + * \details This function is called when an existing property list of this + * class is copied. The copy callback function is called after any + * registered parent copy callback function is called for each property + * value. + * + * If the copy routine returns a negative value, the new list is not + * returned to the user and the property list copy function returns an + * error value. + * + * \since 1.4.0 + * */ typedef herr_t (*H5P_cls_copy_func_t)(hid_t new_prop_id, hid_t old_prop_id, void *copy_data); //! <!-- [H5P_cls_copy_func_t_snip] --> //! <!-- [H5P_cls_close_func_t_snip] --> /** - * \todo Document me! + * \brief Callback function for H5Pcreate_class() + * + * \param[in] prop_id The identifier of the property list class being created + * \param[in] close_data User pointer to any close data required + * \return \herr_t + * + * \details This function is called when a property list of the class + * with which this function was registered is being closed. The + * function is called after any registered parent close function is + * called for each property value. + * + * If the close function returns a negative value, the new list is not + * returned to the user and the property list close routine returns + * an error value. + * + * \since 1.4.0 + * */ typedef herr_t (*H5P_cls_close_func_t)(hid_t prop_id, void *close_data); //! <!-- [H5P_cls_close_func_t_snip] --> @@ -145,8 +194,8 @@ typedef herr_t (*H5P_cls_close_func_t)(hid_t prop_id, void *close_data); * \param[in,out] value The value for the property * \return \herr_t * - * \details The H5P_prp_cb1_t() describes the parameters used by the - * property create,copy and close callback functions. + * \details The H5P_prp_cb1_t() function describes the parameters used by the + * property create, copy and close callback functions. */ typedef herr_t (*H5P_prp_cb1_t)(const char *name, size_t size, void *value); //! <!-- [H5P_prp_cb1_t_snip] --> @@ -161,8 +210,8 @@ typedef herr_t (*H5P_prp_cb1_t)(const char *name, size_t size, void *value); * \param[in] value The value for the property * \return \herr_t * - * \details The H5P_prp_cb2_t() describes the parameters used by the - * property set ,copy and delete callback functions. + * \details The H5P_prp_cb2_t() function describes the parameters used by the + * property set, copy and delete callback functions. */ typedef herr_t (*H5P_prp_cb2_t)(hid_t prop_id, const char *name, size_t size, void *value); //! <!-- [H5P_prp_cb2_t_snip] --> @@ -172,13 +221,28 @@ typedef H5P_prp_cb2_t H5P_prp_set_func_t; typedef H5P_prp_cb2_t H5P_prp_get_func_t; //! <!-- [H5P_prp_encode_func_t_snip] --> /** - * \todo Document me! + * \brief Callback function for encoding property values + * + * \param[in] value The property value to be encoded + * \param[out] buf The encoded property value + * \param[out] size The size of \p buf + * \return \herr_t + * + * \note There is currently no public API which exposes a callback of this type. + * */ typedef herr_t (*H5P_prp_encode_func_t)(const void *value, void **buf, size_t *size); //! <!-- [H5P_prp_encode_func_t_snip] --> //! <!-- [H5P_prp_decode_func_t_snip] --> /** - * \todo Document me! + * \brief Callback function for decoding property values + * + * \param[in] buf A buffer containing an encoded property value + * \param[out] value The decoded property value + * \return \herr_t + * + * \note There is currently no public API which exposes a callback of this type. + * */ typedef herr_t (*H5P_prp_decode_func_t)(const void **buf, void *value); //! <!-- [H5P_prp_decode_func_t_snip] --> @@ -187,7 +251,16 @@ typedef H5P_prp_cb1_t H5P_prp_copy_func_t; //! <!-- [H5P_prp_compare_func_t_snip] --> /** - * \todo Document me! + * \brief Callback function for comparing property values + * + * \param[in] value1 A property value + * \param[in] value2 A property value + * \param[in] size The size of the \p value1 and \p value2 buffers + * \return Returns a positive value if \c value1 is greater than \c value2, a + * negative value if \c value2 is greater than \c value1 and zero if + * \c value1 and \c value2 are equal. + * + * \see H5Pregister(), H5Pinsert() */ typedef int (*H5P_prp_compare_func_t)(const void *value1, const void *value2, size_t size); //! <!-- [H5P_prp_compare_func_t_snip] --> @@ -197,7 +270,19 @@ typedef H5P_prp_cb1_t H5P_prp_close_func_t; /* Define property list iteration function type */ //! <!-- [H5P_iterate_t_snip] --> /** - * \todo Document me! + * \brief Callback function for H5Piterate() + * + * \param[in] id The identifier of a property list or property list class + * \param[in] name The name of the current property + * \param[in,out] iter_data The user context passed to H5Piterate() + * \return \herr_t_iter + * + * \details This function is called for each property encountered when + * iterating over a property list or property list class + * via H5Piterate(). + * + * \since 1.4.0 + * */ typedef herr_t (*H5P_iterate_t)(hid_t id, const char *name, void *iter_data); //! <!-- [H5P_iterate_t_snip] --> @@ -264,15 +349,15 @@ typedef enum H5D_mpio_no_collective_cause_t { H5D_MPIO_DATA_TRANSFORMS = 0x04, /**< Collective I/O was not performed because data transforms needed to be applied */ H5D_MPIO_MPI_OPT_TYPES_ENV_VAR_DISABLED = 0x08, - /**< \todo FIXME! */ + /**< Collective I/O was disabled by environment variable (\Code{HDF5_MPI_OPT_TYPES}) */ H5D_MPIO_NOT_SIMPLE_OR_SCALAR_DATASPACES = 0x10, /**< Collective I/O was not performed because one of the dataspaces was neither simple nor scalar */ H5D_MPIO_NOT_CONTIGUOUS_OR_CHUNKED_DATASET = 0x20, /**< Collective I/O was not performed because the dataset was neither contiguous nor chunked */ H5D_MPIO_PARALLEL_FILTERED_WRITES_DISABLED = 0x40, - /**< \todo FIXME! */ + /**< Collective I/O was not performed because parallel filtered writes are disabled */ H5D_MPIO_ERROR_WHILE_CHECKING_COLLECTIVE_POSSIBLE = 0x80, - /**< \todo FIXME! */ + /**< Error */ H5D_MPIO_NO_COLLECTIVE_MAX_CAUSE = 0x100 /**< Sentinel */ } H5D_mpio_no_collective_cause_t; @@ -577,77 +662,12 @@ H5_DLL hid_t H5Pcreate(hid_t cls_id); * those existing properties, only add or remove their own class * properties. Property list classes defined and supported in the * HDF5 library distribution are listed and briefly described in - * H5Pcreate(). The \p create routine is called when a new property - * list of this class is being created. The #H5P_cls_create_func_t - * callback function is defined as follows: - * - * \snippet this H5P_cls_create_func_t_snip - * - * The parameters to this callback function are defined as follows: - * <table> - * <tr> - * <td>\ref hid_t \c prop_id</td> - * <td>IN: The identifier of the property list being created</td> - * </tr> - * <tr> - * <td>\Code{void * create_data}</td> - * <td>IN: User pointer to any class creation data required</td> - * </tr> - * </table> - * - * The \p create routine is called after any registered - * \p create function is called for each property value. If the - * \p create routine returns a negative value, the new list is not - * returned to the user and the property list creation routine returns - * an error value. - * - * The \p copy routine is called when an existing property - * list of this class is copied. The #H5P_cls_copy_func_t callback - * function is defined as follows: - * \snippet this H5P_cls_copy_func_t_snip + * H5Pcreate(). The \p create, \p copy, \p close functions are called + * when a property list of the new class is created, copied, or closed, + * respectively. * - * The parameters to this callback function are defined as follows: - * <table> - * <tr> - * <td>\ref hid_t \c prop_id</td> - * <td>IN: The identifier of the property list created by copying</td> - * </tr> - * <tr> - * <td>\Code{void * copy_data}</td> - * <td>IN: User pointer to any class copy data required</td> - * </tr> - * </table> - * - * The \p copy routine is called after any registered \p copy function - * is called for each property value. If the \p copy routine returns a - * negative value, the new list is not returned to the user and the - * property list \p copy routine returns an error value. - * - * The \p close routine is called when a property list of this class - * is being closed. The #H5P_cls_close_func_t callback function is - * defined as follows: - * \snippet this H5P_cls_close_func_t_snip - * - * The parameters to this callback function are defined as follows: - * <table> - * <tr> - * <td>\ref hid_t \c prop_id</td> - * <td>IN: The identifier of the property list being closed</td> - * </tr> - * <tr> - * <td>\Code{void * close_data}</td> - * <td>IN: User pointer to any class close data required</td> - * </tr> - * </table> - * - * The \p close routine is called before any registered \p close - * function is called for each property value. If the \p close routine - * returns a negative value, the property list close routine returns - * an error value but the property list is still closed. - * - * H5Pclose_class() can be used to release the property list class - * identifier returned by this function so that resources leaks will - * not develop. + * H5Pclose_class() must be used to release the property list class + * identifier returned by this function. * * \since 1.4.0 * @@ -1376,35 +1396,12 @@ H5_DLL htri_t H5Pisa_class(hid_t plist_id, hid_t pclass_id); * returned in this case, the iterator cannot be restarted if * one of the calls to its operator returns non-zero. * - * The prototype for the #H5P_iterate_t operator is as follows: - * \snippet this H5P_iterate_t_snip - * - * The operation receives the property list or class + * The operation \p iter_func receives the property list or class * identifier for the object being iterated over, \p id, the * name of the current property within the object, \p name, * and the pointer to the operator data passed in to H5Piterate(), - * \p iter_data. The valid return values from an operator are - * as follows: + * \p iter_data. * - * <table> - * <tr> - * <td>Zero</td> - * <td>Causes the iterator to continue, returning zero when all - * properties have been processed</td> - * </tr> - * <tr> - * <td>Positive</td> - * <td>Causes the iterator to immediately return that positive - * value, indicating short-circuit success. The iterator - * can be restarted at the index of the next property</td> - * </tr> - * <tr> - * <td>Negative</td> - * <td>Causes the iterator to immediately return that value, - * indicating failure. The iterator can be restarted at the - * index of the next property</td> - * </tr> - * </table> * H5Piterate() assumes that the properties in the object * identified by \p id remain unchanged through the iteration. * If the membership changes during the iteration, the function's @@ -1877,9 +1874,6 @@ H5_DLL herr_t H5Pget_attr_phase_change(hid_t plist_id, unsigned *max_compact, un * * \brief Returns information about a filter in a pipeline * - * \todo Signature for H5Pget_filter2 is different in H5Pocpl.c than in - * H5Ppublic.h - * * \ocpl_id{plist_id} * \param[in] idx Sequence number within the filter pipeline of the filter * for which information is sought @@ -3448,6 +3442,34 @@ H5_DLL const void *H5Pget_driver_info(hid_t plist_id); /** * \ingroup FAPL * + * \brief Retrieves a string representation of the configuration for + * the driver set on the given FAPL. The returned string can + * be used to configure the same driver in an identical way. + * + * \fapl_id + * \param[out] config_buf Driver configuration string output buffer + * \param[in] buf_size Size of driver configuration string output buffer + * + * \return Returns the length of the driver configuration string on + * success (not including the NUL terminator). Returns negative + * on failure. + * + * \details H5Pget_driver_config_str() retrieves a string representation + * of the configuration for the driver set on the given FAPL. The + * returned string can be used to configure the same driver in + * an identical way. + * + * If \p config_buf is NULL, the length of the driver configuration + * string is simply returned. The caller can then allocate a buffer + * of the appropriate size and call this routine again. + * + * \version 1.12.1 Function publicized in this release. + * + */ +H5_DLL ssize_t H5Pget_driver_config_str(hid_t fapl_id, char *config_buf, size_t buf_size); +/** + * \ingroup FAPL + * * \brief Retrieves the size of the external link open file cache * * \fapl_id{plist_id} @@ -3884,13 +3906,13 @@ H5_DLL herr_t H5Pget_meta_block_size(hid_t fapl_id, hsize_t *size); * * The second example illustrates the two cases for retrieving the * number of read attempts from the file access property list of a file - * opened with SWMR acccess. + * opened with SWMR access. * * \include H5Pget_metadata_read_attempts.2.c * * The third example illustrates the two cases for retrieving the number * of read attempts from the file access property list of a file opened - * with non-SWMR acccess. + * with non-SWMR access. * * \include H5Pget_metadata_read_attempts.3.c * @@ -4177,17 +4199,14 @@ H5_DLL herr_t H5Pset_alignment(hid_t fapl_id, hsize_t threshold, hsize_t alignme * * \note Note: Raw dataset chunk caching is not currently * supported when using the MPI I/O and MPI POSIX file drivers - * in read/write mode; see H5Pset_fapl_mpio() and - * H5Pset_fapl_mpiposix(), respectively. When using one of these - * file drivers, all calls to H5Dread() and H5Dwrite() will access + * in read/write mode; see H5Pset_fapl_mpio(). When using this + * file driver, all calls to H5Dread() and H5Dwrite() will access * the disk directly, and H5Pset_cache() will have no effect on * performance. * * \note Raw dataset chunk caching is supported when these drivers are * used in read-only mode. * - * \todo Check on H5Pset_fapl_mpio() and H5Pset_fapl_mpiposix(). - * * \version 1.8.0 The use of the \p mdc_nelmts parameter was discontinued. * Metadata cache configuration is managed with * H5Pset_mdc_config() and H5Pget_mdc_config(). @@ -4287,6 +4306,57 @@ H5_DLL herr_t H5Pset_driver(hid_t plist_id, hid_t driver_id, const void *driver_ /** * \ingroup FAPL * + * \brief Sets a file driver according to a given driver name + * + * \plist_id + * \param[in] driver_name The new driver name + * \param[in] driver_config Optional string containing driver properties + * + * \return \herr_t + * + * \details H5Pset_driver_by_name() sets the file driver, by the name + * driver_name, for a file access or data transfer property list, + * \p plist_id, and supplies an optional string containing the + * driver-specific properties, \p driver_config. The driver + * properties string will be copied into the property list. + * + * If the driver specified by \p driver_name is not currently + * registered, an attempt will be made to load the driver as a + * plugin. + * + * \version 1.12.1 Function publicized in this release. + * + */ +H5_DLL herr_t H5Pset_driver_by_name(hid_t plist_id, const char *driver_name, const char *driver_config); +/** + * \ingroup FAPL + * + * \brief Sets a file driver according to a given driver value (ID). + * + * \plist_id + * \param[in] driver_value The new driver value (ID) + * \param[in] driver_config Optional string containing driver properties + * + * \return \herr_t + * + * \details H5Pset_driver_by_value() sets the file driver, by the value + * driver_value, for a file access or data transfer property list, + * \p plist_id, and supplies an optional string containing the + * driver-specific properties, \p driver_config. The driver + * properties string will be copied into the property list. + * + * If the driver specified by \p driver_value is not currently + * registered, an attempt will be made to load the driver as a + * plugin. + * + * \version 1.12.1 Function publicized in this release. + * + */ +H5_DLL herr_t H5Pset_driver_by_value(hid_t plist_id, H5FD_class_value_t driver_value, + const char *driver_config); +/** + * \ingroup FAPL + * * \brief Sets the number of files that can be held open in an external * link open file cache * @@ -4295,7 +4365,7 @@ H5_DLL herr_t H5Pset_driver(hid_t plist_id, hid_t driver_id, const void *driver_ * The <em>external link open file cache</em> holds files open after * they have been accessed via an external link. This cache reduces * the number of times such files are opened when external links are - * accessed repeatedly and can siginificantly improves performance in + * accessed repeatedly and can significantly improves performance in * certain heavy-use situations and when low-level file opens or closes * are expensive. * @@ -5404,12 +5474,38 @@ H5_DLL herr_t H5Pset_coll_metadata_write(hid_t plist_id, hbool_t is_collective); H5_DLL herr_t H5Pget_coll_metadata_write(hid_t plist_id, hbool_t *is_collective); /** - * \todo Add missing documentation + * \ingroup FAPL + * + * \brief Get the MPI communicator and info + * + * \fapl_id + * \param[out] comm MPI communicator + * \param[out] info MPI info object + * \return \herr_t + * + * \details H5Pget_mpi_params() gets the MPI communicator and info stored in + * the file access property list \p fapl_id. + * + * \todo When was this introduced? + * */ H5_DLL herr_t H5Pget_mpi_params(hid_t fapl_id, MPI_Comm *comm, MPI_Info *info); /** - * \todo Add missing documentation + * \ingroup FAPL + * + * \brief Set the MPI communicator and info + * + * \fapl_id + * \param[in] comm MPI communicator + * \param[in] info MPI info object + * \return \herr_t + * + * \details H5Pset_mpi_params() sets the MPI communicator and info stored in + * the file access property list \p fapl_id. + * + * \todo When was this introduced? + * */ H5_DLL herr_t H5Pset_mpi_params(hid_t fapl_id, MPI_Comm comm, MPI_Info info); #endif /* H5_HAVE_PARALLEL */ @@ -6392,10 +6488,10 @@ H5_DLL herr_t H5Pset_layout(hid_t plist_id, H5D_layout_t layout); * <td>byte 0</td> * </tr> * <tr> - * <td>????????</td> - * <td>????SPPP</td> - * <td>PPPPPPPP</td> - * <td>PPPP????</td> + * <td> ???????? </td> + * <td> ????SPPP </td> + * <td> PPPPPPPP </td> + * <td> PPPP???? </td> * </tr> * </table> * Note: S - sign bit, P - significant bit, ? - padding bit; For @@ -7021,9 +7117,6 @@ H5_DLL herr_t H5Pget_virtual_printf_gap(hid_t dapl_id, hsize_t *gap_size); * * \dapl_id * \param[out] view The flag specifying the view of the virtual dataset. - * Valid values are: - * \li #H5D_VDS_FIRST_MISSING - * \li #H5D_VDS_LAST_AVAILABLE * * \return \herr_t * @@ -7377,11 +7470,7 @@ H5_DLL herr_t H5Pset_virtual_printf_gap(hid_t dapl_id, hsize_t gap_size); * * \dapl_id * \param[in] view Flag specifying the extent of the data to be included - * in the view. Valid values are: - * \li #H5D_VDS_FIRST_MISSING: View includes all data - * before the first missing mapped data - * \li #H5D_VDS_LAST_AVAILABLE View includes all - * available mapped data + * in the view. * * \return \herr_t * @@ -7549,8 +7638,11 @@ H5_DLL herr_t H5Pget_hyper_vector_size(hid_t fapl_id, size_t *size /*out*/); * \details H5Pget_preserve() checks the status of the dataset transfer * property list. * + * \since 1.0.0 + * * \version 1.6.0 The flag parameter was changed from INTEGER to LOGICAL to * better match the C API. (Fortran 90) + * \version 1.8.2 Deprecated. * */ H5_DLL int H5Pget_preserve(hid_t plist_id); @@ -7578,6 +7670,8 @@ H5_DLL int H5Pget_preserve(hid_t plist_id); * * Please refer to the function H5Pset_type_conv_cb() for more details. * + * \since 1.8.0 + * */ H5_DLL herr_t H5Pget_type_conv_cb(hid_t dxpl_id, H5T_conv_except_func_t *op, void **operate_data); /** @@ -7601,6 +7695,8 @@ H5_DLL herr_t H5Pget_type_conv_cb(hid_t dxpl_id, H5T_conv_except_func_t *op, voi * H5Pset_vlen_mem_manager(), returning the parameters set by * that function. * + * \since 1.0.0 + * */ H5_DLL herr_t H5Pget_vlen_mem_manager(hid_t plist_id, H5MM_allocate_t *alloc_func, void **alloc_info, H5MM_free_t *free_func, void **free_info); @@ -7844,8 +7940,9 @@ H5_DLL herr_t H5Pset_hyper_vector_size(hid_t plist_id, size_t size); * I/O pipeline treats the destination datapoints as completely * uninitialized. * - * \todo Add missing version information: introduction, deprecation, etc. - * Why is the declaration not in the deprecated section? + * \since 1.0.0 + * + * \version 1.8.2 Deprecated. * */ H5_DLL herr_t H5Pset_preserve(hid_t plist_id, hbool_t status); @@ -7873,7 +7970,7 @@ H5_DLL herr_t H5Pset_preserve(hid_t plist_id, hbool_t status); * function prototype is as follows: * \snippet H5Tpublic.h H5T_conv_except_func_t_snip * - * \todo Add version information. + * \since 1.8.0 * */ H5_DLL herr_t H5Pset_type_conv_cb(hid_t dxpl_id, H5T_conv_except_func_t op, void *operate_data); @@ -7923,7 +8020,8 @@ H5_DLL herr_t H5Pset_type_conv_cb(hid_t dxpl_id, H5T_conv_except_func_t op, void * set to \c NULL and the \p alloc_info and \p free_info parameters are * ignored. * - * \todo Add version information. + * \since 1.0.0 + * */ H5_DLL herr_t H5Pset_vlen_mem_manager(hid_t plist_id, H5MM_allocate_t alloc_func, void *alloc_info, H5MM_free_t free_func, void *free_info); @@ -69,9 +69,6 @@ static herr_t H5RS__resize_for_append(H5RS_str_t *rs, size_t len); /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /*****************************/ /* Library Private Variables */ /*****************************/ @@ -316,8 +313,16 @@ H5RS_wrap(const char *s) if (NULL == (ret_value = H5FL_MALLOC(H5RS_str_t))) HGOTO_ERROR(H5E_RS, H5E_CANTALLOC, NULL, "memory allocation failed") - /* Set the internal fields */ - ret_value->s = (char *)s; + /* Set the internal fields + * + * We ignore warnings about storing a const char pointer in the struct + * since we never modify or free the string when the wrapped struct + * field is set to TRUE. + */ + H5_GCC_CLANG_DIAG_OFF("cast-qual") + ret_value->s = (char *)s; + H5_GCC_CLANG_DIAG_ON("cast-qual") + ret_value->len = HDstrlen(s); ret_value->end = ret_value->s + ret_value->len; @@ -345,7 +350,7 @@ done: */ /* Disable warning for "format not a string literal" here -QAK */ /* - * This pragma only needs to surround the sprintf() calls with + * This pragma only needs to surround the snprintf() calls with * format_templ in the code below, but early (4.4.7, at least) gcc only * allows diagnostic pragmas to be toggled outside of functions. */ diff --git a/src/H5Rint.c b/src/H5Rint.c index e1a5dcd..65bd485 100644 --- a/src/H5Rint.c +++ b/src/H5Rint.c @@ -141,9 +141,6 @@ static herr_t H5R__decode_string(const unsigned char *buf, size_t *nbytes, char /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /*****************************/ /* Library Private Variables */ /*****************************/ @@ -152,106 +149,27 @@ hbool_t H5_PKG_INIT_VAR = FALSE; /* Local Variables */ /*******************/ -/* Flag indicating "top" of interface has been initialized */ -static hbool_t H5R_top_package_initialize_s = FALSE; - -/*-------------------------------------------------------------------------- -NAME - H5R__init_package -- Initialize interface-specific information -USAGE - herr_t H5R__init_package() - -RETURNS - Non-negative on success/Negative on failure -DESCRIPTION - Initializes any interface-specific data or routines. - ---------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------- + * Function: H5R_init + * + * Purpose: Initialize the interface from some other layer. + * + * Return: Success: non-negative + * Failure: negative + *------------------------------------------------------------------------- + */ herr_t -H5R__init_package(void) +H5R_init(void) { - FUNC_ENTER_NOAPI_NOINIT_NOERR + herr_t ret_value = SUCCEED; - /* Mark "top" of interface as initialized */ - H5R_top_package_initialize_s = TRUE; + FUNC_ENTER_NOAPI_NOINIT_NOERR /* Sanity check, if assert fails, H5R_REF_BUF_SIZE must be increased */ HDcompile_assert(sizeof(H5R_ref_priv_t) <= H5R_REF_BUF_SIZE); - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5R__init_package() */ - -/*-------------------------------------------------------------------------- - NAME - H5R_top_term_package - PURPOSE - Terminate various H5R objects - USAGE - void H5R_top_term_package() - RETURNS - void - DESCRIPTION - Release IDs for the ID group, deferring full interface shutdown - until later (in H5R_term_package). - GLOBAL VARIABLES - COMMENTS, BUGS, ASSUMPTIONS - Can't report errors... - EXAMPLES - REVISION LOG ---------------------------------------------------------------------------*/ -int -H5R_top_term_package(void) -{ - int n = 0; - - FUNC_ENTER_NOAPI_NOINIT_NOERR - - /* Mark closed if initialized */ - if (H5R_top_package_initialize_s) - if (0 == n) - H5R_top_package_initialize_s = FALSE; - - FUNC_LEAVE_NOAPI(n) -} /* end H5R_top_term_package() */ - -/*-------------------------------------------------------------------------- - NAME - H5R_term_package - PURPOSE - Terminate various H5R objects - USAGE - void H5R_term_package() - RETURNS - void - DESCRIPTION - Release the ID group and any other resources allocated. - GLOBAL VARIABLES - COMMENTS, BUGS, ASSUMPTIONS - Can't report errors... - - Finishes shutting down the interface, after H5R_top_term_package() - is called - EXAMPLES - REVISION LOG ---------------------------------------------------------------------------*/ -int -H5R_term_package(void) -{ - int n = 0; - - FUNC_ENTER_NOAPI_NOINIT_NOERR - - if (H5_PKG_INIT_VAR) { - /* Sanity checks */ - HDassert(FALSE == H5R_top_package_initialize_s); - - /* Mark closed */ - if (0 == n) - H5_PKG_INIT_VAR = FALSE; - } - - FUNC_LEAVE_NOAPI(n) -} /* end H5R_term_package() */ + FUNC_LEAVE_NOAPI(ret_value) +} /*------------------------------------------------------------------------- * Function: H5R__create_object @@ -1150,7 +1068,7 @@ H5R__encode_obj_token(const H5O_token_t *obj_token, size_t token_size, unsigned /* Encode token */ H5MM_memcpy(p, obj_token, token_size); } - *nalloc = token_size + H5_SIZEOF_UINT8_T; + *nalloc = token_size + sizeof(uint8_t); FUNC_LEAVE_NOAPI(ret_value) } /* end H5R__encode_obj_token() */ @@ -1178,7 +1096,7 @@ H5R__decode_obj_token(const unsigned char *buf, size_t *nbytes, H5O_token_t *obj HDassert(token_size); /* Don't decode if buffer size isn't big enough */ - if (*nbytes < H5_SIZEOF_UINT8_T) + if (*nbytes < sizeof(uint8_t)) HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "Buffer size is too small") /* Get token size */ @@ -1192,7 +1110,7 @@ H5R__decode_obj_token(const unsigned char *buf, size_t *nbytes, H5O_token_t *obj /* Decode token */ H5MM_memcpy(obj_token, p, *token_size); - *nbytes = (size_t)(*token_size + H5_SIZEOF_UINT8_T); + *nbytes = (size_t)(*token_size + sizeof(uint8_t)); done: FUNC_LEAVE_NOAPI(ret_value) @@ -1225,7 +1143,7 @@ H5R__encode_region(H5S_t *space, unsigned char *buf, size_t *nalloc) "Cannot determine amount of space needed for serializing selection") /* Don't encode if buffer size isn't big enough or buffer is empty */ - if (buf && *nalloc >= ((size_t)buf_size + 2 * H5_SIZEOF_UINT32_T)) { + if (buf && *nalloc >= ((size_t)buf_size + 2 * sizeof(uint32_t))) { int rank; p = (uint8_t *)buf; @@ -1241,7 +1159,7 @@ H5R__encode_region(H5S_t *space, unsigned char *buf, size_t *nalloc) if (H5S_SELECT_SERIALIZE(space, (unsigned char **)&p) < 0) HGOTO_ERROR(H5E_REFERENCE, H5E_CANTENCODE, FAIL, "can't serialize selection") } /* end if */ - *nalloc = (size_t)buf_size + 2 * H5_SIZEOF_UINT32_T; + *nalloc = (size_t)buf_size + 2 * sizeof(uint32_t); done: FUNC_LEAVE_NOAPI(ret_value) @@ -1272,16 +1190,16 @@ H5R__decode_region(const unsigned char *buf, size_t *nbytes, H5S_t **space_ptr) HDassert(space_ptr); /* Don't decode if buffer size isn't big enough */ - if (*nbytes < (2 * H5_SIZEOF_UINT32_T)) + if (*nbytes < (2 * sizeof(uint32_t))) HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "Buffer size is too small") /* Decode the selection size */ UINT32DECODE(p, buf_size); - buf_size += H5_SIZEOF_UINT32_T; + buf_size += sizeof(uint32_t); /* Decode the extent rank */ UINT32DECODE(p, rank); - buf_size += H5_SIZEOF_UINT32_T; + buf_size += sizeof(uint32_t); /* Don't decode if buffer size isn't big enough */ if (*nbytes < buf_size) diff --git a/src/H5Rpkg.h b/src/H5Rpkg.h index ee5fb71..09144f9 100644 --- a/src/H5Rpkg.h +++ b/src/H5Rpkg.h @@ -43,7 +43,7 @@ #define H5R_REF_ATTRNAME(x) ((x)->info.attr.name) /* Header size */ -#define H5R_ENCODE_HEADER_SIZE (2 * H5_SIZEOF_UINT8_T) +#define H5R_ENCODE_HEADER_SIZE (2 * sizeof(uint8_t)) /****************************/ /* Package Private Typedefs */ diff --git a/src/H5Rprivate.h b/src/H5Rprivate.h index 6d6fcd5..59d2ed2 100644 --- a/src/H5Rprivate.h +++ b/src/H5Rprivate.h @@ -39,4 +39,6 @@ /* Library Private Prototypes */ /******************************/ +H5_DLL herr_t H5R_init(void); + #endif /* H5Rprivate_H */ @@ -55,9 +55,6 @@ static htri_t H5S__is_simple(const H5S_t *sdim); /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /* Format version bounds for dataspace */ const unsigned H5O_sdspace_ver_bounds[] = { H5O_SDSPACE_VERSION_1, /* H5F_LIBVER_EARLIEST */ @@ -96,9 +93,6 @@ static const H5I_class_t H5I_SPACE_SEL_ITER_CLS[1] = {{ (H5I_free_t)H5S__sel_iter_close_cb /* Callback routine for closing objects of this class */ }}; -/* Flag indicating "top" of interface has been initialized */ -static hbool_t H5S_top_package_initialize_s = FALSE; - /*------------------------------------------------------------------------- * Function: H5S_init * @@ -114,44 +108,19 @@ H5S_init(void) herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) - /* FUNC_ENTER() does all the work */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5S_init() */ - -/*-------------------------------------------------------------------------- -NAME - H5S__init_package -- Initialize interface-specific information -USAGE - herr_t H5S__init_package() -RETURNS - Non-negative on success/Negative on failure -DESCRIPTION - Initializes any interface-specific data or routines. ---------------------------------------------------------------------------*/ -herr_t -H5S__init_package(void) -{ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_PACKAGE /* Initialize the ID group for the dataspace IDs */ if (H5I_register_type(H5I_DATASPACE_CLS) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize dataspace ID class") - /* Initialize the ID group for the dataspace selction iterator IDs */ + /* Initialize the ID group for the dataspace selection iterator IDs */ if (H5I_register_type(H5I_SPACE_SEL_ITER_CLS) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize dataspace selection iterator ID class") - /* Mark "top" of interface as initialized, too */ - H5S_top_package_initialize_s = TRUE; - done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5S__init_package() */ +} /* end H5S_init() */ /*-------------------------------------------------------------------------- NAME @@ -178,21 +147,14 @@ H5S_top_term_package(void) FUNC_ENTER_NOAPI_NOINIT_NOERR - if (H5S_top_package_initialize_s) { - if (H5I_nmembers(H5I_DATASPACE) > 0) { - (void)H5I_clear_type(H5I_DATASPACE, FALSE, FALSE); - n++; /*H5I*/ - } /* end if */ - - if (H5I_nmembers(H5I_SPACE_SEL_ITER) > 0) { - (void)H5I_clear_type(H5I_SPACE_SEL_ITER, FALSE, FALSE); - n++; /*H5I*/ - } /* end if */ - - /* Mark "top" of interface as closed */ - if (0 == n) - H5S_top_package_initialize_s = FALSE; - } /* end if */ + if (H5I_nmembers(H5I_DATASPACE) > 0) { + (void)H5I_clear_type(H5I_DATASPACE, FALSE, FALSE); + n++; + } + if (H5I_nmembers(H5I_SPACE_SEL_ITER) > 0) { + (void)H5I_clear_type(H5I_SPACE_SEL_ITER, FALSE, FALSE); + n++; + } FUNC_LEAVE_NOAPI(n) } /* end H5S_top_term_package() */ @@ -224,22 +186,15 @@ H5S_term_package(void) FUNC_ENTER_NOAPI_NOINIT_NOERR - if (H5_PKG_INIT_VAR) { - /* Sanity checks */ - HDassert(0 == H5I_nmembers(H5I_DATASPACE)); - HDassert(0 == H5I_nmembers(H5I_SPACE_SEL_ITER)); - HDassert(FALSE == H5S_top_package_initialize_s); - - /* Destroy the dataspace object id group */ - n += (H5I_dec_type_ref(H5I_DATASPACE) > 0); + /* Sanity checks */ + HDassert(0 == H5I_nmembers(H5I_DATASPACE)); + HDassert(0 == H5I_nmembers(H5I_SPACE_SEL_ITER)); - /* Destroy the dataspace selection iterator object id group */ - n += (H5I_dec_type_ref(H5I_SPACE_SEL_ITER) > 0); + /* Destroy the dataspace object id group */ + n += (H5I_dec_type_ref(H5I_DATASPACE) > 0); - /* Mark interface as closed */ - if (0 == n) - H5_PKG_INIT_VAR = FALSE; - } /* end if */ + /* Destroy the dataspace selection iterator object id group */ + n += (H5I_dec_type_ref(H5I_SPACE_SEL_ITER) > 0); FUNC_LEAVE_NOAPI(n) } /* end H5S_term_package() */ @@ -759,7 +714,7 @@ H5S_get_simple_extent_npoints(const H5S_t *ds) { hssize_t ret_value = -1; /* Return value */ - FUNC_ENTER_NOAPI(-1) + FUNC_ENTER_NOAPI_NOERR /* check args */ HDassert(ds); @@ -767,7 +722,6 @@ H5S_get_simple_extent_npoints(const H5S_t *ds) /* Get the number of elements in extent */ ret_value = (hssize_t)ds->extent.nelem; -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5S_get_simple_extent_npoints() */ @@ -1740,13 +1694,12 @@ H5S_get_simple_extent_type(const H5S_t *space) { H5S_class_t ret_value = H5S_NO_CLASS; /* Return value */ - FUNC_ENTER_NOAPI(H5S_NO_CLASS) + FUNC_ENTER_NOAPI_NOERR HDassert(space); ret_value = H5S_GET_EXTENT_TYPE(space); -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5S_get_simple_extent_type() */ @@ -36,13 +36,6 @@ * skip list. The implementation in that document hurts * performance, at least for integer keys. -NAF) * - * (Also, this implementation has a couple of home-grown - * optimizations, including setting the "update" vector to the - * actual 'forward' pointer to update, instead of the node - * containing the forward pointer -QAK - * -No longer uses update vector, as insertions/deletions are now - * always at level 0. -NAF) - * * (Note: This implementation does not have the information for * implementing the "Linear List Operations" (like insert/delete/ * search by position) in section 3.4 of "A Skip List Cookbook", @@ -71,25 +64,14 @@ /* Define the code template for searches for the "OP" in the H5SL_LOCATE macro */ #define H5SL_LOCATE_SEARCH_FOUND(SLIST, X, I) \ { \ - HDassert(!X->removed); \ - HGOTO_DONE(X->item); \ - } /* end block */ - -/* Define the code template for deferred removals for the "OP" in the - * H5SL_LOCATE macro */ -#define H5SL_LOCATE_SEARCH_DEFER_REMOVE_FOUND(SLIST, X, I) \ - { \ - HDassert(!X->removed); \ - X->removed = TRUE; \ HGOTO_DONE(X->item); \ - } /* end block */ + } /* Define the code template for finds for the "OP" in the H5SL_LOCATE macro */ #define H5SL_LOCATE_FIND_FOUND(SLIST, X, I) \ { \ - HDassert(!X->removed); \ HGOTO_DONE(X); \ - } /* end block */ + } /* Define a code template for comparing scalar keys for the "CMP" in the H5SL_LOCATE macro */ #define H5SL_LOCATE_SCALAR_CMP(SLIST, TYPE, PNODE, PKEY, HASHVAL) (*(TYPE *)((PNODE)->key) < *(TYPE *)PKEY) @@ -155,51 +137,19 @@ H5_GLUE3(H5SL_LOCATE_, CMP, _CMP)(SLIST, TYPE, X->forward[_i], KEY, HASHVAL)) { \ X = X->forward[_i]; \ _count++; \ - } /* end while */ \ - } /* end for */ \ + } \ + } \ X = X->forward[0]; \ if (X != NULL && H5_GLUE3(H5SL_LOCATE_, CMP, _EQ)(SLIST, TYPE, X, KEY, HASHVAL)) { \ /* What to do when a node is found */ \ H5_GLUE3(H5SL_LOCATE_, OP, _FOUND)(SLIST, X, _i) \ - } /* end if */ \ - } - -/* Macro used to find node for operation, if there may be "removed" nodes in the - * list (whose keys cannot be read) */ -#define H5SL_LOCATE_SAFE(OP, CMP, SLIST, X, TYPE, KEY, HASHVAL) \ - { \ - int _i; /* Local index variable */ \ - H5SL_node_t *_low = X; \ - H5SL_node_t *_high = NULL; \ - \ - H5_GLUE3(H5SL_LOCATE_, CMP, _HASHINIT) \ - (KEY, HASHVAL) for (_i = (int)SLIST->curr_level; _i >= 0; _i--) \ - { \ - X = _low->forward[_i]; \ - while (X != _high) { \ - if (!X->removed) { \ - if (H5_GLUE3(H5SL_LOCATE_, CMP, _CMP)(SLIST, TYPE, X, KEY, HASHVAL)) \ - _low = X; \ - else \ - break; \ - } /* end if */ \ - X = X->forward[_i]; \ - } /* end while */ \ - _high = X; \ - if (X != NULL && H5_GLUE3(H5SL_LOCATE_, CMP, _EQ)(SLIST, TYPE, X, KEY, HASHVAL)) { \ - /* What to do when a node is found */ \ - H5_GLUE3(H5SL_LOCATE_, OP, _FOUND)(SLIST, X, _i) break; \ - } /* end if */ \ - } /* end for */ \ + } \ } /* Macro used to find node for operation */ #define H5SL_LOCATE(OP, CMP, SLIST, X, TYPE, KEY, HASHVAL) \ { \ - if ((SLIST)->safe_iterating) \ - H5SL_LOCATE_SAFE(OP, CMP, SLIST, X, TYPE, KEY, HASHVAL) \ - else \ - H5SL_LOCATE_OPT(OP, CMP, SLIST, X, TYPE, KEY, HASHVAL) \ + H5SL_LOCATE_OPT(OP, CMP, SLIST, X, TYPE, KEY, HASHVAL) \ } /* Macro used to grow a node by 1. Does not update pointers. LVL is the current @@ -225,13 +175,13 @@ if (NULL == (H5SL_fac_g = (H5FL_fac_head_t **)H5MM_realloc( \ (void *)H5SL_fac_g, H5SL_fac_nalloc_g * sizeof(H5FL_fac_head_t *)))) \ HGOTO_ERROR(H5E_SLIST, H5E_CANTALLOC, ERR, "memory allocation failed") \ - } /* end if */ \ + } \ \ /* Create the new factory */ \ H5SL_fac_g[H5SL_fac_nused_g] = \ H5FL_fac_init((1u << H5SL_fac_nused_g) * sizeof(H5SL_node_t *)); \ H5SL_fac_nused_g++; \ - } /* end if */ \ + } \ \ /* Allocate space for new forward pointers */ \ if (NULL == (_tmp = (H5SL_node_t **)H5FL_FAC_MALLOC(H5SL_fac_g[X->log_nalloc]))) \ @@ -239,7 +189,7 @@ H5MM_memcpy((void *)_tmp, (const void *)X->forward, (LVL + 1) * sizeof(H5SL_node_t *)); \ X->forward = (H5SL_node_t **)H5FL_FAC_FREE(H5SL_fac_g[X->log_nalloc - 1], (void *)X->forward); \ X->forward = _tmp; \ - } /* end if */ \ + } \ \ X->level++; \ } @@ -260,7 +210,7 @@ H5MM_memcpy((void *)_tmp, (const void *)X->forward, (LVL) * sizeof(H5SL_node_t *)); \ X->forward = (H5SL_node_t **)H5FL_FAC_FREE(H5SL_fac_g[X->log_nalloc + 1], (void *)X->forward); \ X->forward = _tmp; \ - } /* end if */ \ + } \ \ X->level--; \ } @@ -284,12 +234,12 @@ else { \ HDassert(_lvl < (size_t)SLIST->curr_level); \ X->forward[_lvl + 1] = PREV->forward[_lvl + 1]; \ - } /* end else */ \ + } \ PREV->forward[_lvl + 1] = X; \ } /* Macro used to reduce the level of a node by 1. Does not update the head node - * "current level". PREV is the previous node of the currrent height of X. */ + * "current level". PREV is the previous node of the current height of X. */ #define H5SL_DEMOTE(X, PREV) \ { \ size_t _lvl = X->level; \ @@ -305,7 +255,7 @@ #define H5SL_INSERT(CMP, SLIST, X, TYPE, KEY, HASHVAL) \ { \ H5SL_node_t *_last = X; /* Lowest node in the current gap */ \ - H5SL_node_t *_next = NULL; /* Highest node in the currect gap */ \ + H5SL_node_t *_next = NULL; /* Highest node in the current gap */ \ H5SL_node_t *_drop; /* Low node of the gap to drop into */ \ int _count; /* Number of nodes in the current gap */ \ int _i; \ @@ -322,7 +272,7 @@ if (!_drop) \ _drop = X; \ break; \ - } /* end if */ \ + } \ \ /* Check if this node is the start of the next gap */ \ if (!_drop && !H5_GLUE3(H5SL_LOCATE_, CMP, _CMP)(SLIST, TYPE, X->forward[_i], KEY, HASHVAL)) \ @@ -337,7 +287,7 @@ break; \ } \ X = X->forward[_i]; \ - } /* end for */ \ + } \ HDassert(!_drop->forward[_i] || \ !H5_GLUE3(H5SL_LOCATE_, CMP, _CMP)(SLIST, TYPE, _drop->forward[_i], KEY, HASHVAL)); \ \ @@ -350,7 +300,7 @@ /* Prepare to drop down */ \ X = _last = _drop; \ _next = _drop->forward[_i]; \ - } /* end for */ \ + } \ \ if (_next && H5_GLUE3(H5SL_LOCATE_, CMP, _EQ)(SLIST, TYPE, _next, KEY, HASHVAL)) \ HGOTO_ERROR(H5E_SLIST, H5E_CANTINSERT, NULL, "can't insert duplicate key") \ @@ -359,172 +309,167 @@ /* Macro used to remove node */ #define H5SL_REMOVE(CMP, SLIST, X, TYPE, KEY, HASHVAL) \ { \ - /* Check for deferred removal */ \ - if (SLIST->safe_iterating) \ - H5SL_LOCATE(SEARCH_DEFER_REMOVE, CMP, SLIST, X, TYPE, KEY, HASHVAL) \ - else { \ - H5SL_node_t *_last = X; /* Lowest node in the current gap */ \ - H5SL_node_t *_llast = X; /* Lowest node in the previous gap */ \ - H5SL_node_t *_next = NULL; /* Highest node in the currect gap */ \ - H5SL_node_t *_drop = NULL; /* Low node of the gap to drop into */ \ - H5SL_node_t *_ldrop = NULL; /* Low node of gap before the one to drop into */ \ - H5SL_node_t *_head = SLIST->header; /* Head of the skip list */ \ - int _count; /* Number of nodes in the current gap */ \ - int _i = (int)SLIST->curr_level; \ + H5SL_node_t *_last = X; /* Lowest node in the current gap */ \ + H5SL_node_t *_llast = X; /* Lowest node in the previous gap */ \ + H5SL_node_t *_next = NULL; /* Highest node in the current gap */ \ + H5SL_node_t *_drop = NULL; /* Low node of the gap to drop into */ \ + H5SL_node_t *_ldrop = NULL; /* Low node of gap before the one to drop into */ \ + H5SL_node_t *_head = SLIST->header; /* Head of the skip list */ \ + int _count; /* Number of nodes in the current gap */ \ + int _i = (int)SLIST->curr_level; \ \ - if (_i < 0) \ - HGOTO_DONE(NULL); \ + if (_i < 0) \ + HGOTO_DONE(NULL); \ \ - H5_GLUE3(H5SL_LOCATE_, CMP, _HASHINIT) \ - (KEY, HASHVAL) \ + H5_GLUE3(H5SL_LOCATE_, CMP, _HASHINIT) \ + (KEY, HASHVAL) \ \ - /* Find the gap to drop in to at the highest level */ \ - while (X && (!X->key || H5_GLUE3(H5SL_LOCATE_, CMP, _CMP)(SLIST, TYPE, X, KEY, HASHVAL))) \ - { \ - _llast = _last; \ - _last = X; \ - X = X->forward[_i]; \ - } \ - _next = X; \ + /* Find the gap to drop in to at the highest level */ \ + while (X && (!X->key || H5_GLUE3(H5SL_LOCATE_, CMP, _CMP)(SLIST, TYPE, X, KEY, HASHVAL))) \ + { \ + _llast = _last; \ + _last = X; \ + X = X->forward[_i]; \ + } \ + _next = X; \ \ - /* Main loop */ \ - for (_i--; _i >= 0; _i--) { \ - /* Search for the node to drop into, also count the number of */ \ - /* nodes of height _i in this gap and keep track of of the node */ \ - /* before the one to drop into (_ldrop will become _llast, */ \ - /* _drop will become _last). */ \ - X = _ldrop = _last; \ - _drop = NULL; \ - for (_count = 0;; _count++) { \ - /* Terminate if this is the last node in the gap */ \ - if (X->forward[_i] == _next) { \ - if (!_drop) \ - _drop = X; \ - break; \ - } /* end if */ \ + /* Main loop */ \ + for (_i--; _i >= 0; _i--) { \ + /* Search for the node to drop into, also count the number of */ \ + /* nodes of height _i in this gap and keep track of of the node */ \ + /* before the one to drop into (_ldrop will become _llast, */ \ + /* _drop will become _last). */ \ + X = _ldrop = _last; \ + _drop = NULL; \ + for (_count = 0;; _count++) { \ + /* Terminate if this is the last node in the gap */ \ + if (X->forward[_i] == _next) { \ + if (!_drop) \ + _drop = X; \ + break; \ + } \ \ - /* If we have already found the node to drop into and there */ \ - /* is more than one node in this gap, we can stop searching */ \ - if (_drop) { \ - HDassert(_count >= 1); \ - _count = 2; \ - break; \ + /* If we have already found the node to drop into and there */ \ + /* is more than one node in this gap, we can stop searching */ \ + if (_drop) { \ + HDassert(_count >= 1); \ + _count = 2; \ + break; \ + } \ + else { /* !_drop */ \ + /* Check if this node is the start of the next gap */ \ + if (!H5_GLUE3(H5SL_LOCATE_, CMP, _CMP)(SLIST, TYPE, X->forward[_i], KEY, HASHVAL)) { \ + _drop = X; \ + /* Again check if we can stop searching */ \ + if (_count) { \ + _count = 2; \ + break; \ + } \ } \ - else { /* !_drop */ \ - /* Check if this node is the start of the next gap */ \ - if (!H5_GLUE3(H5SL_LOCATE_, CMP, _CMP)(SLIST, TYPE, X->forward[_i], KEY, HASHVAL)) { \ - _drop = X; \ - /* Again check if we can stop searching */ \ - if (_count) { \ - _count = 2; \ - break; \ - } /* end if */ \ - } /* end if */ \ - else \ - _ldrop = X; \ - } /* end else */ \ + else \ + _ldrop = X; \ + } \ \ - /* No need to check the last node in the gap if there are */ \ - /* 3, as there cannot be a fourth */ \ - if (_count == 2) { \ - if (!_drop) \ - _drop = X->forward[_i]; \ - break; \ - } /* end if */ \ - X = X->forward[_i]; \ - } /* end for */ \ - HDassert(_count >= 1 && _count <= 3); \ - HDassert(!_drop->forward[_i] || \ - !H5_GLUE3(H5SL_LOCATE_, CMP, _CMP)(SLIST, TYPE, _drop->forward[_i], KEY, HASHVAL)); \ + /* No need to check the last node in the gap if there are */ \ + /* 3, as there cannot be a fourth */ \ + if (_count == 2) { \ + if (!_drop) \ + _drop = X->forward[_i]; \ + break; \ + } \ + X = X->forward[_i]; \ + } \ + HDassert(_count >= 1 && _count <= 3); \ + HDassert(!_drop->forward[_i] || \ + !H5_GLUE3(H5SL_LOCATE_, CMP, _CMP)(SLIST, TYPE, _drop->forward[_i], KEY, HASHVAL)); \ \ - /* Check if we need to adjust node heights */ \ - if (_count == 1) { \ - /* Check if we are in the first gap */ \ - if (_llast == _last) { \ - /* We are in the first gap, count the number of nodes */ \ - /* of height _i in the next gap. We need only check */ \ - /* onenode to see if we should promote the first node */ \ - /* in the next gap */ \ - _llast = _next->forward[_i + 1]; \ + /* Check if we need to adjust node heights */ \ + if (_count == 1) { \ + /* Check if we are in the first gap */ \ + if (_llast == _last) { \ + /* We are in the first gap, count the number of nodes */ \ + /* of height _i in the next gap. We need only check */ \ + /* onenode to see if we should promote the first node */ \ + /* in the next gap */ \ + _llast = _next->forward[_i + 1]; \ \ - /* Demote the separator node */ \ - H5SL_DEMOTE(_next, _last) \ + /* Demote the separator node */ \ + H5SL_DEMOTE(_next, _last) \ \ - /* If there are 2 or more nodes, promote the first */ \ - if (_next->forward[_i]->forward[_i] != _llast) { \ - X = _next->forward[_i]; \ - H5SL_PROMOTE(SLIST, X, _last, NULL) \ - } \ - else if (!_head->forward[_i + 1]) { \ - /* shrink the header */ \ - HDassert(_i == SLIST->curr_level - 1); \ - HDassert((size_t)SLIST->curr_level == _head->level); \ + /* If there are 2 or more nodes, promote the first */ \ + if (_next->forward[_i]->forward[_i] != _llast) { \ + X = _next->forward[_i]; \ + H5SL_PROMOTE(SLIST, X, _last, NULL) \ + } \ + else if (!_head->forward[_i + 1]) { \ + /* shrink the header */ \ + HDassert(_i == SLIST->curr_level - 1); \ + HDassert((size_t)SLIST->curr_level == _head->level); \ \ - H5SL_SHRINK(_head, (size_t)(_i + 1)) \ - SLIST->curr_level--; \ - } /* end else */ \ + H5SL_SHRINK(_head, (size_t)(_i + 1)) \ + SLIST->curr_level--; \ } \ - else { \ - /* We are not in the first gap, count the number of */ \ - /* nodes of height _i in the previous gap. Note we */ \ - /* "look ahead" in this loop so X has the value of the */ \ - /* last node in the previous gap. */ \ - X = _llast->forward[_i]; \ - for (_count = 1; _count < 3 && X->forward[_i] != _last; _count++) \ - X = X->forward[_i]; \ - HDassert(X->forward[_i] == _last); \ + } \ + else { \ + /* We are not in the first gap, count the number of */ \ + /* nodes of height _i in the previous gap. Note we */ \ + /* "look ahead" in this loop so X has the value of the */ \ + /* last node in the previous gap. */ \ + X = _llast->forward[_i]; \ + for (_count = 1; _count < 3 && X->forward[_i] != _last; _count++) \ + X = X->forward[_i]; \ + HDassert(X->forward[_i] == _last); \ \ - /* Demote the separator node */ \ - H5SL_DEMOTE(_last, _llast) \ + /* Demote the separator node */ \ + H5SL_DEMOTE(_last, _llast) \ \ - /* If there are 2 or more nodes, promote the last */ \ - if (_count >= 2) \ - H5SL_PROMOTE(SLIST, X, _llast, NULL) \ - else if (!_head->forward[_i + 1]) { \ - /* shrink the header */ \ - HDassert(_i == SLIST->curr_level - 1); \ - HDassert((size_t)SLIST->curr_level == _head->level); \ + /* If there are 2 or more nodes, promote the last */ \ + if (_count >= 2) \ + H5SL_PROMOTE(SLIST, X, _llast, NULL) \ + else if (!_head->forward[_i + 1]) { \ + /* shrink the header */ \ + HDassert(_i == SLIST->curr_level - 1); \ + HDassert((size_t)SLIST->curr_level == _head->level); \ \ - H5SL_SHRINK(_head, (size_t)(_i + 1)) \ - SLIST->curr_level--; \ - } /* end else */ \ - } /* end else */ \ - } /* end if */ \ + H5SL_SHRINK(_head, (size_t)(_i + 1)) \ + SLIST->curr_level--; \ + } \ + } \ + } \ \ - /* Prepare to drop down */ \ - _llast = _ldrop; \ - _last = _drop; \ - _next = _drop->forward[_i]; \ - } /* end for */ \ + /* Prepare to drop down */ \ + _llast = _ldrop; \ + _last = _drop; \ + _next = _drop->forward[_i]; \ + } \ \ - /* Check if we've found the node */ \ - if (_next && H5_GLUE3(H5SL_LOCATE_, CMP, _EQ)(SLIST, TYPE, _next, KEY, HASHVAL)) { \ - void *tmp = _next->item; \ - X = _next; \ + /* Check if we've found the node */ \ + if (_next && H5_GLUE3(H5SL_LOCATE_, CMP, _EQ)(SLIST, TYPE, _next, KEY, HASHVAL)) { \ + void *tmp = _next->item; \ + X = _next; \ \ - /* If the node has a height > 0, swap it with its (lower) */ \ - /* neighbor */ \ - if (X->level) { \ - X = X->backward; \ - _next->key = X->key; \ - _next->item = X->item; \ - _next->hashval = X->hashval; \ - } /* end if */ \ - HDassert(!X->level); \ + /* If the node has a height > 0, swap it with its (lower) */ \ + /* neighbor */ \ + if (X->level) { \ + X = X->backward; \ + _next->key = X->key; \ + _next->item = X->item; \ + _next->hashval = X->hashval; \ + } \ + HDassert(!X->level); \ \ - /* Remove the node */ \ - X->backward->forward[0] = X->forward[0]; \ - if (SLIST->last == X) \ - SLIST->last = X->backward; \ - else \ - X->forward[0]->backward = X->backward; \ - SLIST->nobjs--; \ - X->forward = (H5SL_node_t **)H5FL_FAC_FREE(H5SL_fac_g[0], X->forward); \ - X = H5FL_FREE(H5SL_node_t, X); \ + /* Remove the node */ \ + X->backward->forward[0] = X->forward[0]; \ + if (SLIST->last == X) \ + SLIST->last = X->backward; \ + else \ + X->forward[0]->backward = X->backward; \ + SLIST->nobjs--; \ + X->forward = (H5SL_node_t **)H5FL_FAC_FREE(H5SL_fac_g[0], X->forward); \ + X = H5FL_FREE(H5SL_node_t, X); \ \ - HGOTO_DONE(tmp); \ - } /* end if */ \ - } /* end else */ \ + HGOTO_DONE(tmp); \ + } \ } /* Macro used to search for node */ @@ -542,7 +487,6 @@ struct H5SL_node_t { size_t level; /* The level of this node */ size_t log_nalloc; /* log2(Number of slots allocated in forward) */ uint32_t hashval; /* Hash value for key (only for strings, currently) */ - hbool_t removed; /* Whether the node is "removed" (actual removal deferred) */ struct H5SL_node_t **forward; /* Array of forward pointers from this node */ struct H5SL_node_t * backward; /* Backward pointer from this node */ }; @@ -558,8 +502,6 @@ struct H5SL_t { size_t nobjs; /* Number of active objects in skip list */ H5SL_node_t *header; /* Header for nodes in skip list */ H5SL_node_t *last; /* Pointer to last node in skip list */ - hbool_t safe_iterating; /* Whether a routine is "safely" iterating over the list and removals should be - deferred */ }; /* Static functions */ @@ -568,9 +510,6 @@ static H5SL_node_t *H5SL__insert_common(H5SL_t *slist, void *item, const void *k static herr_t H5SL__release_common(H5SL_t *slist, H5SL_operator_t op, void *op_data); static herr_t H5SL__close_common(H5SL_t *slist, H5SL_operator_t op, void *op_data); -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /* Declare a free list to manage the H5SL_t struct */ H5FL_DEFINE_STATIC(H5SL_t); @@ -582,26 +521,21 @@ static H5FL_fac_head_t **H5SL_fac_g; static size_t H5SL_fac_nused_g; static size_t H5SL_fac_nalloc_g; -/*-------------------------------------------------------------------------- - NAME - H5SL__init_package - PURPOSE - Initialize interface-specific information - USAGE - herr_t H5SL__init_package() - RETURNS - Non-negative on success/Negative on failure - DESCRIPTION - Initializes any interface-specific data or routines. - GLOBAL VARIABLES - COMMENTS, BUGS, ASSUMPTIONS - EXAMPLES - REVISION LOG ---------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------- + * Function: H5SL_init + * + * Purpose: Initialize the interface from some other layer. + * + * Return: Success: non-negative + * Failure: negative + *------------------------------------------------------------------------- + */ herr_t -H5SL__init_package(void) +H5SL_init(void) { - FUNC_ENTER_PACKAGE_NOERR + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOERR /* Allocate space for array of factories */ H5SL_fac_g = (H5FL_fac_head_t **)H5MM_malloc(sizeof(H5FL_fac_head_t *)); @@ -613,8 +547,8 @@ H5SL__init_package(void) HDassert(H5SL_fac_g[0]); H5SL_fac_nused_g = 1; - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5SL__init_package() */ + FUNC_LEAVE_NOAPI(ret_value) +} /*-------------------------------------------------------------------------- NAME @@ -642,33 +576,27 @@ H5SL_term_package(void) FUNC_ENTER_NOAPI_NOINIT_NOERR - if (H5_PKG_INIT_VAR) { - /* Terminate all the factories */ - if (H5SL_fac_nused_g > 0) { - size_t i; - herr_t H5_ATTR_NDEBUG_UNUSED ret; + /* Terminate all the factories */ + if (H5SL_fac_nused_g > 0) { + size_t i; + herr_t H5_ATTR_NDEBUG_UNUSED ret; - for (i = 0; i < H5SL_fac_nused_g; i++) { - ret = H5FL_fac_term(H5SL_fac_g[i]); - HDassert(ret >= 0); - } /* end if */ - H5SL_fac_nused_g = 0; + for (i = 0; i < H5SL_fac_nused_g; i++) { + ret = H5FL_fac_term(H5SL_fac_g[i]); + HDassert(ret >= 0); + } + H5SL_fac_nused_g = 0; - n++; - } /* end if */ - - /* Free the list of factories */ - if (H5SL_fac_g) { - H5SL_fac_g = (H5FL_fac_head_t **)H5MM_xfree((void *)H5SL_fac_g); - H5SL_fac_nalloc_g = 0; + n++; + } - n++; - } /* end if */ + /* Free the list of factories */ + if (H5SL_fac_g) { + H5SL_fac_g = (H5FL_fac_head_t **)H5MM_xfree((void *)H5SL_fac_g); + H5SL_fac_nalloc_g = 0; - /* Mark the interface as uninitialized */ - if (0 == n) - H5_PKG_INIT_VAR = FALSE; - } /* end if */ + n++; + } FUNC_LEAVE_NOAPI(n) } /* H5SL_term_package() */ @@ -711,11 +639,10 @@ H5SL__new_node(void *item, const void *key, uint32_t hashval) ret_value->item = item; ret_value->level = 0; ret_value->hashval = hashval; - ret_value->removed = FALSE; if (NULL == (ret_value->forward = (H5SL_node_t **)H5FL_FAC_MALLOC(H5SL_fac_g[0]))) { ret_value = H5FL_FREE(H5SL_node_t, ret_value); HGOTO_ERROR(H5E_SLIST, H5E_NOSPACE, NULL, "memory allocation failed") - } /* end if */ + } ret_value->log_nalloc = 0; done: @@ -805,7 +732,7 @@ H5SL__insert_common(H5SL_t *slist, void *item, const void *key) default: HDassert(0 && "Unknown skiplist type!"); - } /* end switch */ + } /* 'key' must not have been found in existing list, if we get here */ @@ -880,15 +807,22 @@ H5SL__release_common(H5SL_t *slist, H5SL_operator_t op, void *op_data) while (node) { next_node = node->forward[0]; - /* Call callback, if one is given */ + /* Call callback, if one is given. + * + * Ignoring const here is fine as we only need the value to be const + * with respect to the list code, which should never modify the + * elements. The library code that is making use of the skip list + * container can do what it likes with the elements. + */ + H5_GCC_CLANG_DIAG_OFF("cast-qual") if (op) - /* Casting away const OK -QAK */ (void)(op)(node->item, (void *)node->key, op_data); + H5_GCC_CLANG_DIAG_ON("cast-qual") node->forward = (H5SL_node_t **)H5FL_FAC_FREE(H5SL_fac_g[node->log_nalloc], node->forward); node = H5FL_FREE(H5SL_node_t, node); node = next_node; - } /* end while */ + } /* Reset the header pointers */ slist->header->forward = @@ -1001,9 +935,8 @@ H5SL_create(H5SL_type_t type, H5SL_cmp_t cmp) new_slist->cmp = cmp; /* Set the dynamic internal fields */ - new_slist->curr_level = -1; - new_slist->nobjs = 0; - new_slist->safe_iterating = FALSE; + new_slist->curr_level = -1; + new_slist->nobjs = 0; /* Allocate the header node */ if (NULL == (header = H5SL__new_node(NULL, NULL, (uint32_t)ULONG_MAX))) @@ -1027,7 +960,7 @@ done: if (ret_value == NULL) { if (new_slist != NULL) new_slist = H5FL_FREE(H5SL_t, new_slist); - } /* end if */ + } FUNC_LEAVE_NOAPI(ret_value) } /* end H5SL_create() */ @@ -1058,9 +991,6 @@ H5SL_count(H5SL_t *slist) /* Check args */ HDassert(slist); - /* Not currently supported */ - HDassert(!slist->safe_iterating); - /* Check internal consistency */ /* (Pre-condition) */ @@ -1099,9 +1029,6 @@ H5SL_insert(H5SL_t *slist, void *item, const void *key) HDassert(slist); HDassert(key); - /* Not currently supported */ - HDassert(!slist->safe_iterating); - /* Check internal consistency */ /* (Pre-condition) */ @@ -1148,9 +1075,6 @@ H5SL_add(H5SL_t *slist, void *item, const void *key) HDassert(slist); HDassert(key); - /* Not currently supported */ - HDassert(!slist->safe_iterating); - /* Check internal consistency */ /* (Pre-condition) */ @@ -1242,7 +1166,7 @@ H5SL_remove(H5SL_t *slist, const void *key) default: HDassert(0 && "Unknown skiplist type!"); - } /* end switch */ + } done: FUNC_LEAVE_NOAPI(ret_value) @@ -1281,9 +1205,6 @@ H5SL_remove_first(H5SL_t *slist) /* Check args */ HDassert(slist); - /* Not currently supported */ - HDassert(!slist->safe_iterating); - /* Assign level */ H5_CHECK_OVERFLOW(slist->curr_level, int, size_t); level = (size_t)slist->curr_level; @@ -1345,12 +1266,12 @@ H5SL_remove_first(H5SL_t *slist) H5SL_SHRINK(head, level) slist->curr_level--; - } /* end else */ + } } else break; - } /* end for */ - } /* end if */ + } + } done: FUNC_LEAVE_NOAPI(ret_value) @@ -1436,7 +1357,7 @@ H5SL_search(H5SL_t *slist, const void *key) default: HDassert(0 && "Unknown skiplist type!"); - } /* end switch */ + } /* 'key' must not have been found in list, if we get here */ ret_value = NULL; @@ -1480,9 +1401,6 @@ H5SL_less(H5SL_t *slist, const void *key) HDassert(slist); HDassert(key); - /* Not currently supported */ - HDassert(!slist->safe_iterating); - /* Check internal consistency */ /* (Pre-condition) */ @@ -1531,7 +1449,7 @@ H5SL_less(H5SL_t *slist, const void *key) default: HDassert(0 && "Unknown skiplist type!"); - } /* end switch */ + } /* An exact match for 'key' must not have been found in list, if we get here */ /* Check for a node with a key that is less than the given 'key' */ @@ -1541,13 +1459,13 @@ H5SL_less(H5SL_t *slist, const void *key) ret_value = slist->last->item; else ret_value = NULL; - } /* end if */ + } else { if (x->backward != slist->header) ret_value = x->backward->item; else ret_value = NULL; - } /* end else */ + } done: FUNC_LEAVE_NOAPI(ret_value) @@ -1588,9 +1506,6 @@ H5SL_greater(H5SL_t *slist, const void *key) HDassert(slist); HDassert(key); - /* Not currently supported */ - HDassert(!slist->safe_iterating); - /* Check internal consistency */ /* (Pre-condition) */ @@ -1639,7 +1554,7 @@ H5SL_greater(H5SL_t *slist, const void *key) default: HDassert(0 && "Unknown skiplist type!"); - } /* end switch */ + } /* An exact match for 'key' must not have been found in list, if we get here */ /* ('x' must be the next node with a key greater than the 'key', or NULL) */ @@ -1734,7 +1649,7 @@ H5SL_find(H5SL_t *slist, const void *key) default: HDassert(0 && "Unknown skiplist type!"); - } /* end switch */ + } /* 'key' must not have been found in list, if we get here */ ret_value = NULL; @@ -1826,7 +1741,7 @@ H5SL_below(H5SL_t *slist, const void *key) default: HDassert(0 && "Unknown skiplist type!"); - } /* end switch */ + } /* An exact match for 'key' must not have been found in list, if we get here */ /* Check for a node with a key that is less than the given 'key' */ @@ -1836,13 +1751,13 @@ H5SL_below(H5SL_t *slist, const void *key) ret_value = slist->last; else ret_value = NULL; - } /* end if */ + } else { if (x->backward != slist->header) ret_value = x->backward; else ret_value = NULL; - } /* end else */ + } done: FUNC_LEAVE_NOAPI(ret_value) @@ -1931,7 +1846,7 @@ H5SL_above(H5SL_t *slist, const void *key) default: HDassert(0 && "Unknown skiplist type!"); - } /* end switch */ + } /* An exact match for 'key' must not have been found in list, if we get here */ /* ('x' must be the next node with a key greater than the 'key', or NULL) */ @@ -1971,9 +1886,6 @@ H5SL_first(H5SL_t *slist) /* Check args */ HDassert(slist); - /* Not currently supported */ - HDassert(!slist->safe_iterating); - /* Check internal consistency */ /* (Pre-condition) */ @@ -2007,9 +1919,6 @@ H5SL_next(H5SL_node_t *slist_node) /* Check args */ HDassert(slist_node); - /* Not currently supported */ - HDassert(!slist_node->removed); - /* Check internal consistency */ /* (Pre-condition) */ @@ -2020,7 +1929,7 @@ H5SL_next(H5SL_node_t *slist_node) NAME H5SL_prev PURPOSE - Gets a pointer to the previos node in a skip list + Gets a pointer to the previous node in a skip list USAGE H5SL_node_t *H5SL_prev(slist_node) H5SL_node_t *slist_node; IN: Pointer to skip list node @@ -2043,9 +1952,6 @@ H5SL_prev(H5SL_node_t *slist_node) /* Check args */ HDassert(slist_node); - /* Not currently supported */ - HDassert(!slist_node->removed); - /* Check internal consistency */ /* (Pre-condition) */ @@ -2080,9 +1986,6 @@ H5SL_last(H5SL_t *slist) /* Check args */ HDassert(slist); - /* Not currently supported */ - HDassert(!slist->safe_iterating); - /* Check internal consistency */ /* (Pre-condition) */ @@ -2116,9 +2019,6 @@ H5SL_item(H5SL_node_t *slist_node) /* Check args */ HDassert(slist_node); - /* Not currently supported */ - HDassert(!slist_node->removed); - /* Check internal consistency */ /* (Pre-condition) */ @@ -2179,15 +2079,21 @@ H5SL_iterate(H5SL_t *slist, H5SL_operator_t op, void *op_data) /* Protect against the node being deleted by the callback */ next = node->forward[0]; - /* Call the iterator callback */ - /* Casting away const OK -QAK */ - if (!node->removed) - if ((ret_value = (op)(node->item, (void *)node->key, op_data)) != 0) - break; + /* Call the iterator callback + * + * Ignoring const here is fine as we only need the value to be const + * with respect to the list code, which should never modify the + * elements. The library code that is making use of the skip list + * container can do what it likes with the elements. + */ + H5_GCC_CLANG_DIAG_OFF("cast-qual") + if ((ret_value = (op)(node->item, (void *)node->key, op_data)) != 0) + break; + H5_GCC_CLANG_DIAG_ON("cast-qual") /* Advance to next node */ node = next; - } /* end while */ + } FUNC_LEAVE_NOAPI(ret_value) } /* end H5SL_iterate() */ @@ -2222,9 +2128,6 @@ H5SL_release(H5SL_t *slist) /* Check args */ HDassert(slist); - /* Not currently supported */ - HDassert(!slist->safe_iterating); - /* Check internal consistency */ /* (Pre-condition) */ @@ -2274,9 +2177,6 @@ H5SL_free(H5SL_t *slist, H5SL_operator_t op, void *op_data) /* Check args */ HDassert(slist); - /* Not currently supported */ - HDassert(!slist->safe_iterating); - /* Check internal consistency */ /* (Pre-condition) */ @@ -2290,186 +2190,6 @@ done: /*-------------------------------------------------------------------------- NAME - H5SL_try_free_safe - PURPOSE - Makes the supplied callback on all nodes in the skip list, freeing each - node that the callback returns TRUE for. - USAGE - herr_t PURPOSE(slist,op,opdata) - H5SL_t *slist; IN/OUT: Pointer to skip list to release nodes - H5SL_try_free_op_t op; IN: Callback function to try to free item & key - void *op_data; IN/OUT: Pointer to application data for callback - - RETURNS - Returns non-negative on success, negative on failure. - DESCRIPTION - Makes the supplied callback on all nodes in the skip list, freeing each - node that the callback returns TRUE for. The iteration is performed in - a safe manner, such that the callback can call H5SL_remove(), - H5SL_search(), H5SL_find(), and H5SL_iterate() on nodes in this - skiplist, except H5SL_remove() may not be call on *this* node. - GLOBAL VARIABLES - COMMENTS, BUGS, ASSUMPTIONS - This function is written to be most efficient when most nodes are - removed from the skiplist, as it rebuilds the nodes afterwards. - EXAMPLES - REVISION LOG ---------------------------------------------------------------------------*/ -herr_t -H5SL_try_free_safe(H5SL_t *slist, H5SL_try_free_op_t op, void *op_data) -{ - H5SL_node_t *node, *next_node, *last_node; /* Pointers to skip list nodes */ - htri_t op_ret; - herr_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI_NOINIT - - /* Check args */ - HDassert(slist); - HDassert(op); - - /* Not currently supported */ - HDassert(!slist->safe_iterating); - - /* Check internal consistency */ - /* (Pre-condition) */ - - /* Mark skip list as safe iterating, so nodes aren't freed out from under - * us */ - slist->safe_iterating = TRUE; - - /* Iterate over skip list nodes, making the callback for each and marking - * them as removed if requested by the callback */ - node = slist->header->forward[0]; - while (node) { - /* Check if the node was already removed */ - if (!node->removed) { - /* Call callback */ - /* Casting away const OK -NAF */ - if ((op_ret = (op)(node->item, (void *)node->key, op_data)) < 0) - HGOTO_ERROR(H5E_SLIST, H5E_CALLBACK, FAIL, "callback operation failed") - - /* Check if op indicated that the node should be removed */ - if (op_ret) - /* Mark the node as removed */ - node->removed = TRUE; - } /* end if */ - - /* Advance node */ - node = node->forward[0]; - } /* end while */ - - /* Reset safe_iterating */ - slist->safe_iterating = FALSE; - - /* Iterate over nodes, freeing ones marked as removed */ - node = slist->header->forward[0]; - last_node = slist->header; - while (node) { - /* Save next node */ - next_node = node->forward[0]; - - /* Check if the node was marked as removed */ - if (node->removed) { - /* Remove the node */ - node->forward = (H5SL_node_t **)H5FL_FAC_FREE(H5SL_fac_g[node->log_nalloc], node->forward); - node = H5FL_FREE(H5SL_node_t, node); - slist->nobjs--; - } /* end if */ - else { - /* Update backwards and forwards[0] pointers, and set the level to - * 0. Since the list is flattened we must rebuild the skiplist - * afterwards. */ - /* Set level to 0. Note there is no need to preserve - * node->forward[0] since it was cached above and will always be - * updated later. */ - if (node->level > 0) { - node->forward = - (H5SL_node_t **)H5FL_FAC_FREE(H5SL_fac_g[node->log_nalloc], (void *)node->forward); - if (NULL == (node->forward = (H5SL_node_t **)H5FL_FAC_MALLOC(H5SL_fac_g[0]))) - HGOTO_ERROR(H5E_SLIST, H5E_CANTALLOC, FAIL, "memory allocation failed") - node->log_nalloc = 0; - node->level = 0; - } /* end if */ - - /* Update pointers */ - last_node->forward[0] = node; - node->backward = last_node; - last_node = node; - } /* end else */ - - /* Advance node */ - node = next_node; - } /* end while */ - - /* Final pointer update */ - last_node->forward[0] = NULL; - slist->last = last_node; - - /* Demote skip list to level 0 */ - if (slist->curr_level > 0) { - HDassert(slist->header->level == (size_t)slist->curr_level); - - node = slist->header->forward[0]; - slist->header->forward = (H5SL_node_t **)H5FL_FAC_FREE(H5SL_fac_g[slist->header->log_nalloc], - (void *)slist->header->forward); - if (NULL == (slist->header->forward = (H5SL_node_t **)H5FL_FAC_MALLOC(H5SL_fac_g[0]))) - HGOTO_ERROR(H5E_SLIST, H5E_CANTALLOC, FAIL, "memory allocation failed") - slist->header->forward[0] = node; - slist->header->log_nalloc = 0; - slist->header->level = 0; - } /* end if */ - - /* Check if there are any nodes left */ - if (slist->nobjs > 0) { - int i; - - HDassert(slist->header->forward[0]); - - /* Set skiplist level to 0 */ - slist->curr_level = 0; - - /* Rebuild the forward arrays */ - for (i = 0; slist->curr_level >= i; i++) { - HDassert(slist->curr_level == i); - - /* Promote every third node this level until we run out of nodes */ - node = last_node = slist->header; - while (1) { - /* Check second node in gap, if not present, no need to promote - * further this level. */ - HDassert(node->forward[i]); - node = node->forward[i]->forward[i]; - if (!node) - break; - - /* Check third and fourth node in gap, if either is not present, - * no need to promote further this level. */ - node = node->forward[i]; - if (!node || !node->forward[i]) - break; - - /* Promote the third node in the gap */ - H5SL_PROMOTE(slist, node, last_node, FAIL) - last_node = node; - } /* end while */ - } /* end for */ - } /* end if */ - else { - HDassert(!slist->header->forward[0]); - HDassert(slist->last == slist->header); - HDassert(slist->nobjs == 0); - - /* Reset the skiplist level */ - slist->curr_level = -1; - } /* end else */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5SL_try_free_safe() */ - -/*-------------------------------------------------------------------------- - NAME H5SL_destroy PURPOSE Close a skip list, deallocating it and freeing all its nodes. diff --git a/src/H5SLprivate.h b/src/H5SLprivate.h index c9e1147..f4f7506 100644 --- a/src/H5SLprivate.h +++ b/src/H5SLprivate.h @@ -60,9 +60,6 @@ typedef int (*H5SL_cmp_t)(const void *key1, const void *key2); /* Typedef for iteration operations */ typedef herr_t (*H5SL_operator_t)(void *item, void *key, void *operator_data /*in,out*/); -/* Typedef for H5SL_try_free_safe operation callback */ -typedef htri_t (*H5SL_try_free_op_t)(void *item, void *key, void *operator_data /*in,out*/); - /********************/ /* Private routines */ /********************/ @@ -86,9 +83,9 @@ H5_DLL void * H5SL_item(H5SL_node_t *slist_node); H5_DLL herr_t H5SL_iterate(H5SL_t *slist, H5SL_operator_t op, void *op_data); H5_DLL herr_t H5SL_release(H5SL_t *slist); H5_DLL herr_t H5SL_free(H5SL_t *slist, H5SL_operator_t op, void *op_data); -H5_DLL herr_t H5SL_try_free_safe(H5SL_t *slist, H5SL_try_free_op_t op, void *op_data); H5_DLL herr_t H5SL_close(H5SL_t *slist); H5_DLL herr_t H5SL_destroy(H5SL_t *slist, H5SL_operator_t op, void *op_data); +H5_DLL herr_t H5SL_init(void); H5_DLL int H5SL_term_interface(void); #endif /* H5SLprivate_H */ @@ -76,9 +76,6 @@ static herr_t H5SM__read_mesg(H5F_t *f, const H5SM_sohm_t *mesg, H5HF_t *fheap, /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - H5FL_DEFINE(H5SM_master_table_t); H5FL_ARR_DEFINE(H5SM_index_header_t, H5O_SHMESG_MAX_NINDEXES); H5FL_DEFINE(H5SM_list_t); @@ -117,7 +114,7 @@ H5SM_init(H5F_t *f, H5P_genplist_t *fc_plist, const H5O_loc_t *ext_loc) haddr_t table_addr = HADDR_UNDEF; /* Address of SOHM master table in file */ unsigned list_max, btree_min; /* Phase change limits for SOHM indices */ unsigned index_type_flags[H5O_SHMESG_MAX_NINDEXES]; /* Messages types stored in each index */ - unsigned minsizes[H5O_SHMESG_MAX_NINDEXES]; /* Message size sharing threshhold for each index */ + unsigned minsizes[H5O_SHMESG_MAX_NINDEXES]; /* Message size sharing threshold for each index */ unsigned type_flags_used; /* Message type flags used, for sanity checking */ unsigned x; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ @@ -1599,7 +1596,7 @@ H5SM_delete(H5F_t *f, H5O_t *open_oh, H5O_shared_t *sh_mesg) */ if (H5SM__delete_from_index(f, open_oh, &(table->indexes[index_num]), sh_mesg, &cache_flags, &mesg_size, &mesg_buf) < 0) - HGOTO_ERROR(H5E_SOHM, H5E_CANTDELETE, FAIL, "unable to delete mesage from SOHM index") + HGOTO_ERROR(H5E_SOHM, H5E_CANTDELETE, FAIL, "unable to delete message from SOHM index") /* Release the master SOHM table */ if (H5AC_unprotect(f, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), table, cache_flags) < 0) diff --git a/src/H5Sall.c b/src/H5Sall.c index 35ddf3d..4dcc83a 100644 --- a/src/H5Sall.c +++ b/src/H5Sall.c @@ -49,22 +49,22 @@ static herr_t H5S__all_copy(H5S_t *dst, const H5S_t *src, hbool_t share_selection); static herr_t H5S__all_release(H5S_t *space); static htri_t H5S__all_is_valid(const H5S_t *space); -static hssize_t H5S__all_serial_size(const H5S_t *space); -static herr_t H5S__all_serialize(const H5S_t *space, uint8_t **p); +static hssize_t H5S__all_serial_size(H5S_t *space); +static herr_t H5S__all_serialize(H5S_t *space, uint8_t **p); static herr_t H5S__all_deserialize(H5S_t **space, const uint8_t **p); static herr_t H5S__all_bounds(const H5S_t *space, hsize_t *start, hsize_t *end); static herr_t H5S__all_offset(const H5S_t *space, hsize_t *off); static int H5S__all_unlim_dim(const H5S_t *space); 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 htri_t H5S__all_shape_same(const H5S_t *space1, const H5S_t *space2); -static htri_t H5S__all_intersect_block(const H5S_t *space, const hsize_t *start, const hsize_t *end); +static htri_t H5S__all_is_regular(H5S_t *space); +static htri_t H5S__all_shape_same(H5S_t *space1, H5S_t *space2); +static htri_t H5S__all_intersect_block(H5S_t *space, const hsize_t *start, const hsize_t *end); static herr_t H5S__all_adjust_u(H5S_t *space, const hsize_t *offset); static herr_t H5S__all_adjust_s(H5S_t *space, const hssize_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(const H5S_t *space, H5S_sel_iter_t *iter); +static herr_t H5S__all_iter_init(H5S_t *space, H5S_sel_iter_t *iter); /* Selection iteration callbacks */ static herr_t H5S__all_iter_coords(const H5S_sel_iter_t *iter, hsize_t *coords); @@ -144,7 +144,7 @@ static const H5S_sel_iter_class_t H5S_sel_iter_all[1] = {{ *------------------------------------------------------------------------- */ static herr_t -H5S__all_iter_init(const H5S_t H5_ATTR_UNUSED *space, H5S_sel_iter_t *iter) +H5S__all_iter_init(H5S_t H5_ATTR_UNUSED *space, H5S_sel_iter_t *iter) { FUNC_ENTER_STATIC_NOERR @@ -557,7 +557,7 @@ H5S__all_is_valid(const H5S_t H5_ATTR_UNUSED *space) REVISION LOG --------------------------------------------------------------------------*/ static hssize_t -H5S__all_serial_size(const H5S_t H5_ATTR_UNUSED *space) +H5S__all_serial_size(H5S_t H5_ATTR_UNUSED *space) { FUNC_ENTER_STATIC_NOERR @@ -577,7 +577,7 @@ H5S__all_serial_size(const H5S_t H5_ATTR_UNUSED *space) Serialize the current selection into a user-provided buffer. USAGE herr_t H5S__all_serialize(space, p) - const H5S_t *space; IN: Dataspace with selection to serialize + H5S_t *space; IN: Dataspace with selection to serialize uint8_t **p; OUT: Pointer to buffer to put serialized selection. Will be advanced to end of serialized selection. @@ -592,7 +592,7 @@ H5S__all_serial_size(const H5S_t H5_ATTR_UNUSED *space) REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S__all_serialize(const H5S_t *space, uint8_t **p) +H5S__all_serialize(H5S_t *space, uint8_t **p) { uint8_t *pp = (*p); /* Local pointer for decoding */ @@ -864,7 +864,7 @@ H5S__all_is_single(const H5S_t H5_ATTR_UNUSED *space) Check if a "all" selection is "regular" USAGE htri_t H5S__all_is_regular(space) - const H5S_t *space; IN: Dataspace pointer to check + H5S_t *space; IN: Dataspace pointer to check RETURNS TRUE/FALSE/FAIL DESCRIPTION @@ -877,7 +877,7 @@ H5S__all_is_single(const H5S_t H5_ATTR_UNUSED *space) REVISION LOG --------------------------------------------------------------------------*/ static htri_t -H5S__all_is_regular(const H5S_t H5_ATTR_UNUSED *space) +H5S__all_is_regular(H5S_t H5_ATTR_UNUSED *space) { FUNC_ENTER_STATIC_NOERR @@ -894,8 +894,8 @@ H5S__all_is_regular(const H5S_t H5_ATTR_UNUSED *space) Check if a two "all" selections are the same shape USAGE htri_t H5S__all_shape_same(space1, space2) - const H5S_t *space1; IN: First dataspace to check - const H5S_t *space2; IN: Second dataspace to check + H5S_t *space1; IN: First dataspace to check + H5S_t *space2; IN: Second dataspace to check RETURNS TRUE / FALSE / FAIL DESCRIPTION @@ -907,7 +907,7 @@ H5S__all_is_regular(const H5S_t H5_ATTR_UNUSED *space) REVISION LOG --------------------------------------------------------------------------*/ static htri_t -H5S__all_shape_same(const H5S_t *space1, const H5S_t *space2) +H5S__all_shape_same(H5S_t *space1, H5S_t *space2) { int space1_dim; /* Current dimension in first dataspace */ int space2_dim; /* Current dimension in second dataspace */ @@ -957,7 +957,7 @@ done: Detect intersections of selection with block USAGE htri_t H5S__all_intersect_block(space, start, end) - const H5S_t *space; IN: Dataspace with selection to use + H5S_t *space; IN: Dataspace with selection to use const hsize_t *start; IN: Starting coordinate for block const hsize_t *end; IN: Ending coordinate for block RETURNS @@ -970,7 +970,7 @@ done: REVISION LOG --------------------------------------------------------------------------*/ htri_t -H5S__all_intersect_block(const H5S_t H5_ATTR_UNUSED *space, const hsize_t H5_ATTR_UNUSED *start, +H5S__all_intersect_block(H5S_t H5_ATTR_UNUSED *space, const hsize_t H5_ATTR_UNUSED *start, const hsize_t H5_ATTR_UNUSED *end) { FUNC_ENTER_STATIC_NOERR diff --git a/src/H5Shyper.c b/src/H5Shyper.c index a5b9b6c..7284846 100644 --- a/src/H5Shyper.c +++ b/src/H5Shyper.c @@ -173,8 +173,8 @@ static herr_t H5S__hyper_copy(H5S_t *dst, const H5S_t *src, hbool_t share_sele static herr_t H5S__hyper_release(H5S_t *space); static htri_t H5S__hyper_is_valid(const H5S_t *space); static hsize_t H5S__hyper_span_nblocks(H5S_hyper_span_info_t *spans); -static hssize_t H5S__hyper_serial_size(const H5S_t *space); -static herr_t H5S__hyper_serialize(const H5S_t *space, uint8_t **p); +static hssize_t H5S__hyper_serial_size(H5S_t *space); +static herr_t H5S__hyper_serialize(H5S_t *space, uint8_t **p); static herr_t H5S__hyper_deserialize(H5S_t **space, const uint8_t **p); static herr_t H5S__hyper_bounds(const H5S_t *space, hsize_t *start, hsize_t *end); static herr_t H5S__hyper_offset(const H5S_t *space, hsize_t *offset); @@ -182,14 +182,14 @@ static int H5S__hyper_unlim_dim(const H5S_t *space); static herr_t H5S__hyper_num_elem_non_unlim(const H5S_t *space, hsize_t *num_elem_non_unlim); 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 htri_t H5S__hyper_shape_same(const H5S_t *space1, const H5S_t *space2); -static htri_t H5S__hyper_intersect_block(const H5S_t *space, const hsize_t *start, const hsize_t *end); +static htri_t H5S__hyper_is_regular(H5S_t *space); +static htri_t H5S__hyper_shape_same(H5S_t *space1, H5S_t *space2); +static htri_t H5S__hyper_intersect_block(H5S_t *space, const hsize_t *start, const hsize_t *end); static herr_t H5S__hyper_adjust_u(H5S_t *space, const hsize_t *offset); static herr_t H5S__hyper_adjust_s(H5S_t *space, const hssize_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(const H5S_t *space, H5S_sel_iter_t *iter); +static herr_t H5S__hyper_iter_init(H5S_t *space, H5S_sel_iter_t *iter); /* Selection iteration callbacks */ static herr_t H5S__hyper_iter_coords(const H5S_sel_iter_t *iter, hsize_t *coords); @@ -296,12 +296,12 @@ H5S__hyper_print_spans_helper(FILE *f, const H5S_hyper_span_t *span, unsigned de FUNC_ENTER_STATIC_NOERR while (span) { - HDfprintf(f, "%s: %*sdepth=%u, span=%p, (%Hu, %Hu), next=%p\n", __func__, depth * 2, "", depth, span, - span->low, span->high, span->next); + HDfprintf(f, "%s: %*sdepth=%u, span=%p, (%" PRIuHSIZE ", %" PRIuHSIZE "), next=%p\n", __func__, + depth * 2, "", depth, (void *)span, span->low, span->high, (void *)span->next); if (span->down) { - HDfprintf(f, "%s: %*sspans=%p, count=%u, bounds[0]={%Hu, %Hu}, head=%p\n", __func__, - (depth + 1) * 2, "", span->down, span->down->count, span->down->low_bounds[0], - span->down->high_bounds[0], span->down->head); + HDfprintf(f, "%s: %*sspans=%p, count=%u, bounds[0]={%" PRIuHSIZE ", %" PRIuHSIZE "}, head=%p\n", + __func__, (depth + 1) * 2, "", (void *)span->down, span->down->count, + span->down->low_bounds[0], span->down->high_bounds[0], (void *)span->down->head); H5S__hyper_print_spans_helper(f, span->down->head, depth + 1); } /* end if */ span = span->next; @@ -316,8 +316,9 @@ H5S__hyper_print_spans(FILE *f, const H5S_hyper_span_info_t *span_lst) FUNC_ENTER_STATIC_NOERR if (span_lst != NULL) { - HDfprintf(f, "%s: spans=%p, count=%u, bounds[0]={%Hu, %Hu}, head=%p\n", __func__, span_lst, - span_lst->count, span_lst->low_bounds[0], span_lst->high_bounds[0], span_lst->head); + HDfprintf(f, "%s: spans=%p, count=%u, bounds[0]={%" PRIuHSIZE ", %" PRIuHSIZE "}, head=%p\n", + __func__, (void *)span_lst, span_lst->count, span_lst->low_bounds[0], + span_lst->high_bounds[0], (void *)span_lst->head); H5S__hyper_print_spans_helper(f, span_lst->head, 0); } /* end if */ @@ -344,16 +345,16 @@ H5S__hyper_print_diminfo_helper(FILE *f, const char *field, unsigned ndims, cons if (dinfo != NULL) { HDfprintf(f, "%s: %s: start=[", __func__, field); for (u = 0; u < ndims; u++) - HDfprintf(f, "%Hd%s", dinfo[u].start, (u < (ndims - 1) ? ", " : "]\n")); + HDfprintf(f, "%" PRIuHSIZE "%s", dinfo[u].start, (u < (ndims - 1) ? ", " : "]\n")); HDfprintf(f, "%s: %s: stride=[", __func__, field); for (u = 0; u < ndims; u++) - HDfprintf(f, "%Hu%s", dinfo[u].stride, (u < (ndims - 1) ? ", " : "]\n")); + HDfprintf(f, "%" PRIuHSIZE "%s", dinfo[u].stride, (u < (ndims - 1) ? ", " : "]\n")); HDfprintf(f, "%s: %s: count=[", __func__, field); for (u = 0; u < ndims; u++) - HDfprintf(f, "%Hu%s", dinfo[u].count, (u < (ndims - 1) ? ", " : "]\n")); + HDfprintf(f, "%" PRIuHSIZE "%s", dinfo[u].count, (u < (ndims - 1) ? ", " : "]\n")); HDfprintf(f, "%s: %s: block=[", __func__, field); for (u = 0; u < ndims; u++) - HDfprintf(f, "%Hu%s", dinfo[u].block, (u < (ndims - 1) ? ", " : "]\n")); + HDfprintf(f, "%" PRIuHSIZE "%s", dinfo[u].block, (u < (ndims - 1) ? ", " : "]\n")); } /* end if */ else HDfprintf(f, "%s: %s==NULL\n", __func__, field); @@ -412,31 +413,31 @@ H5S__hyper_print_spans_dfs(FILE *f, const H5S_hyper_span_info_t *span_lst, unsig for (u = 0; u < depth; u++) HDfprintf(f, "\t"); - HDfprintf(f, "DIM[%u]: ref_count=%u, #elems=%u, head=%p, tail=%p, actual_tail=%p, matched=%t\n", depth, - span_lst->count, num_elems, span_lst->head, span_lst->tail, actual_tail, + HDfprintf(f, "DIM[%u]: ref_count=%u, #elems=%u, head=%p, tail=%p, actual_tail=%p, matched=%d\n", depth, + span_lst->count, num_elems, (void *)span_lst->head, (void *)span_lst->tail, (void *)actual_tail, (span_lst->tail == actual_tail)); for (u = 0; u < depth; u++) HDfprintf(f, "\t"); HDfprintf(f, "low_bounds=["); for (u = 0; u < dims - 1; u++) - HDfprintf(f, "%llu,", span_lst->low_bounds[u]); - HDfprintf(f, "%llu]\n", span_lst->low_bounds[dims - 1]); + HDfprintf(f, "%" PRIuHSIZE ",", span_lst->low_bounds[u]); + HDfprintf(f, "%" PRIuHSIZE "]\n", span_lst->low_bounds[dims - 1]); for (u = 0; u < depth; u++) HDfprintf(f, "\t"); HDfprintf(f, "high_bounds=["); for (u = 0; u < dims - 1; u++) - HDfprintf(f, "%llu,", span_lst->high_bounds[u]); - HDfprintf(f, "%llu]\n", span_lst->high_bounds[dims - 1]); + HDfprintf(f, "%" PRIuHSIZE ",", span_lst->high_bounds[u]); + HDfprintf(f, "%" PRIuHSIZE "]\n", span_lst->high_bounds[dims - 1]); cur_elem = span_lst->head; elem_idx = 0; while (cur_elem) { for (u = 0; u < depth; u++) HDfprintf(f, "\t"); - HDfprintf(f, "ELEM[%u]: ptr=%p, low=%Hu, high=%Hu, down=%p\n", elem_idx++, cur_elem, cur_elem->low, - cur_elem->high, cur_elem->down); + HDfprintf(f, "ELEM[%u]: ptr=%p, low=%" PRIuHSIZE ", high=%" PRIuHSIZE ", down=%p\n", elem_idx++, + (void *)cur_elem, cur_elem->low, cur_elem->high, (void *)cur_elem->down); if (cur_elem->down) H5S__hyper_print_spans_dfs(f, cur_elem->down, depth + 1, dims); cur_elem = cur_elem->next; @@ -473,7 +474,7 @@ H5S__hyper_print_space_dfs(FILE *f, const H5S_t *space) HDassert(hslab); HDfprintf(f, "=======================\n"); - HDfprintf(f, "SPACE: span_lst=%p, #dims=%u, offset_changed=%d\n", hslab->span_lst, dims, + HDfprintf(f, "SPACE: span_lst=%p, #dims=%u, offset_changed=%d\n", (void *)hslab->span_lst, dims, space->select.offset_changed); HDfprintf(f, " offset=["); @@ -484,25 +485,25 @@ H5S__hyper_print_space_dfs(FILE *f, const H5S_t *space) HDfprintf(f, " low_bounds=["); if (space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) { for (u = 0; u < dims - 1; u++) - HDfprintf(f, "%llu,", space->select.sel_info.hslab->diminfo.low_bounds[u]); - HDfprintf(f, "%llu]\n", space->select.sel_info.hslab->diminfo.low_bounds[dims - 1]); + HDfprintf(f, "%" PRIuHSIZE ",", space->select.sel_info.hslab->diminfo.low_bounds[u]); + HDfprintf(f, "%" PRIuHSIZE "]\n", space->select.sel_info.hslab->diminfo.low_bounds[dims - 1]); } /* end if */ else { for (u = 0; u < dims - 1; u++) - HDfprintf(f, "%llu,", space->select.sel_info.hslab->span_lst->low_bounds[u]); - HDfprintf(f, "%llu]\n", space->select.sel_info.hslab->span_lst->low_bounds[dims - 1]); + HDfprintf(f, "%" PRIuHSIZE ",", space->select.sel_info.hslab->span_lst->low_bounds[u]); + HDfprintf(f, "%" PRIuHSIZE "]\n", space->select.sel_info.hslab->span_lst->low_bounds[dims - 1]); } /* end else */ HDfprintf(f, " high_bounds=["); if (space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) { for (u = 0; u < dims - 1; u++) - HDfprintf(f, "%llu,", space->select.sel_info.hslab->diminfo.high_bounds[u]); - HDfprintf(f, "%llu]\n", space->select.sel_info.hslab->diminfo.high_bounds[dims - 1]); + HDfprintf(f, "%" PRIuHSIZE ",", space->select.sel_info.hslab->diminfo.high_bounds[u]); + HDfprintf(f, "%" PRIuHSIZE "]\n", space->select.sel_info.hslab->diminfo.high_bounds[dims - 1]); } /* end if */ else { for (u = 0; u < dims - 1; u++) - HDfprintf(f, "%llu,", space->select.sel_info.hslab->span_lst->high_bounds[u]); - HDfprintf(f, "%llu]\n", space->select.sel_info.hslab->span_lst->high_bounds[dims - 1]); + HDfprintf(f, "%" PRIuHSIZE ",", space->select.sel_info.hslab->span_lst->high_bounds[u]); + HDfprintf(f, "%" PRIuHSIZE "]\n", space->select.sel_info.hslab->span_lst->high_bounds[dims - 1]); } /* end else */ /* Print out diminfo, if it's valid */ @@ -559,7 +560,7 @@ H5S__hyper_get_op_gen(void) *------------------------------------------------------------------------- */ static herr_t -H5S__hyper_iter_init(const H5S_t *space, H5S_sel_iter_t *iter) +H5S__hyper_iter_init(H5S_t *space, H5S_sel_iter_t *iter) { hsize_t *slab_size; /* Pointer to the dataspace dimensions to use for calc. slab */ hsize_t acc; /* Accumulator for computing cumulative sizes */ @@ -586,7 +587,7 @@ H5S__hyper_iter_init(const H5S_t *space, H5S_sel_iter_t *iter) * to be impossible. */ if (space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_NO) - H5S__hyper_rebuild((H5S_t *)space); /* Casting away const OK -NAF */ + H5S__hyper_rebuild(space); /* Check for the special case of just one H5Sselect_hyperslab call made */ if (space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) { @@ -2060,7 +2061,7 @@ H5S__hyper_iter_get_seq_list_opt(H5S_sel_iter_t *iter, size_t maxseq, size_t max /* Increment the offset and count for the other dimensions */ temp_dim = (int)fast_dim - 1; while (temp_dim >= 0) { - /* Move to the next row in the curent dimension */ + /* Move to the next row in the current dimension */ offset[temp_dim]++; tmp_block[temp_dim]++; @@ -2178,7 +2179,7 @@ H5S__hyper_iter_get_seq_list_opt(H5S_sel_iter_t *iter, size_t maxseq, size_t max /* Increment the offset and count for the other dimensions */ temp_dim = (int)fast_dim - 1; while (temp_dim >= 0) { - /* Move to the next row in the curent dimension */ + /* Move to the next row in the current dimension */ offset[temp_dim]++; tmp_block[temp_dim]++; @@ -2492,7 +2493,7 @@ H5S__hyper_iter_get_seq_list_single(H5S_sel_iter_t *iter, size_t maxseq, size_t /* Increment the offset and count for the other dimensions */ while (temp_dim >= 0) { - /* Move to the next row in the curent dimension */ + /* Move to the next row in the current dimension */ offset[temp_dim]++; tmp_block[temp_dim]++; @@ -3575,7 +3576,7 @@ H5S__hyper_get_enc_size_real(hsize_t max_size) REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S__hyper_get_version_enc_size(const H5S_t *space, hsize_t block_count, uint32_t *version, uint8_t *enc_size) +H5S__hyper_get_version_enc_size(H5S_t *space, hsize_t block_count, uint32_t *version, uint8_t *enc_size) { hsize_t bounds_start[H5S_MAX_RANK]; /* Starting coordinate of bounding box */ hsize_t bounds_end[H5S_MAX_RANK]; /* Opposite coordinate of bounding box */ @@ -3584,7 +3585,7 @@ H5S__hyper_get_version_enc_size(const H5S_t *space, hsize_t block_count, uint32_ H5F_libver_t low_bound; /* The 'low' bound of library format versions */ H5F_libver_t high_bound; /* The 'high' bound of library format versions */ htri_t is_regular; /* A regular hyperslab or not */ - uint32_t tmp_version; /* Local temporay version */ + uint32_t tmp_version; /* Local temporary version */ unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ @@ -3728,7 +3729,7 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static hssize_t -H5S__hyper_serial_size(const H5S_t *space) +H5S__hyper_serial_size(H5S_t *space) { hsize_t block_count = 0; /* block counter for regular hyperslabs */ uint32_t version; /* Version number */ @@ -3928,7 +3929,7 @@ H5S__hyper_serialize_helper(const H5S_hyper_span_info_t *spans, hsize_t *start, Serialize the current selection into a user-provided buffer. USAGE herr_t H5S__hyper_serialize(space, p) - const H5S_t *space; IN: Dataspace with selection to serialize + H5S_t *space; IN: Dataspace with selection to serialize uint8_t **p; OUT: Pointer to buffer to put serialized selection. Will be advanced to end of serialized selection. @@ -3943,7 +3944,7 @@ H5S__hyper_serialize_helper(const H5S_hyper_span_info_t *spans, hsize_t *start, REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S__hyper_serialize(const H5S_t *space, uint8_t **p) +H5S__hyper_serialize(H5S_t *space, uint8_t **p) { const H5S_hyper_dim_t *diminfo; /* Alias for dataspace's diminfo information */ hsize_t tmp_count[H5S_MAX_RANK]; /* Temporary hyperslab counts */ @@ -3972,7 +3973,7 @@ H5S__hyper_serialize(const H5S_t *space, uint8_t **p) pp = (*p); HDassert(pp); - /* Set some convienence values */ + /* Set some convenience values */ ndims = space->extent.rank; diminfo = space->select.sel_info.hslab->diminfo.opt; @@ -4075,7 +4076,7 @@ H5S__hyper_serialize(const H5S_t *space, uint8_t **p) else { HDassert(version == H5S_HYPER_VERSION_1); - /* Set some convienence values */ + /* Set some convenience values */ fast_dim = ndims - 1; /* Encode number of hyperslabs */ @@ -4225,7 +4226,7 @@ H5S__hyper_deserialize(H5S_t **space, const uint8_t **p) { H5S_t *tmp_space = NULL; /* Pointer to actual dataspace to use, either *space or a newly allocated one */ - hsize_t dims[H5S_MAX_RANK]; /* Dimenion sizes */ + hsize_t dims[H5S_MAX_RANK]; /* Dimension sizes */ hsize_t start[H5S_MAX_RANK]; /* hyperslab start information */ hsize_t block[H5S_MAX_RANK]; /* hyperslab block information */ uint32_t version; /* Version number */ @@ -4618,7 +4619,7 @@ H5S__get_select_hyper_blocklist(H5S_t *space, hsize_t startblock, hsize_t numblo hbool_t done; /* Whether we are done with the iteration */ unsigned u; /* Counter */ - /* Set some convienence values */ + /* Set some convenience values */ ndims = space->extent.rank; fast_dim = ndims - 1; @@ -5112,7 +5113,7 @@ H5S__hyper_is_contiguous(const H5S_t *space) large_contiguous = TRUE; /* assume true and reset if the dimensions don't match */ small_contiguous = FALSE; /* assume false initially */ - /* Check for a "large contigous" block */ + /* Check for a "large contiguous" block */ for (u = 0; u < space->extent.rank; u++) { if (diminfo[u].count > 1) { large_contiguous = FALSE; @@ -5326,7 +5327,7 @@ done: Check if a hyperslab selection is "regular" USAGE htri_t H5S__hyper_is_regular(space) - const H5S_t *space; IN: Dataspace pointer to check + H5S_t *space; IN: Dataspace pointer to check RETURNS TRUE/FALSE/FAIL DESCRIPTION @@ -5339,7 +5340,7 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static htri_t -H5S__hyper_is_regular(const H5S_t *space) +H5S__hyper_is_regular(H5S_t *space) { htri_t ret_value = FAIL; /* return value */ @@ -5352,7 +5353,7 @@ H5S__hyper_is_regular(const H5S_t *space) * to be impossible. */ if (space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_NO) - H5S__hyper_rebuild((H5S_t *)space); /* Casting away const OK -NAF */ + H5S__hyper_rebuild(space); /* Only simple check for regular hyperslabs for now... */ if (space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) @@ -5576,8 +5577,8 @@ H5S__hyper_spans_shape_same(const H5S_hyper_span_info_t *span_info1, const H5S_h Check if a two hyperslab selections are the same shape USAGE htri_t H5S__hyper_shape_same(space1, space2) - const H5S_t *space1; IN: First dataspace to check - const H5S_t *space2; IN: Second dataspace to check + H5S_t *space1; IN: First dataspace to check + H5S_t *space2; IN: Second dataspace to check RETURNS TRUE / FALSE / FAIL DESCRIPTION @@ -5594,7 +5595,7 @@ H5S__hyper_spans_shape_same(const H5S_hyper_span_info_t *span_info1, const H5S_h REVISION LOG --------------------------------------------------------------------------*/ static htri_t -H5S__hyper_shape_same(const H5S_t *space1, const H5S_t *space2) +H5S__hyper_shape_same(H5S_t *space1, H5S_t *space2) { unsigned space1_rank; /* Number of dimensions of first dataspace */ unsigned space2_rank; /* Number of dimensions of second dataspace */ @@ -5617,9 +5618,9 @@ H5S__hyper_shape_same(const H5S_t *space1, const H5S_t *space2) /* Rebuild diminfo if it is invalid and has not been confirmed to be * impossible */ if (space1->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_NO) - H5S__hyper_rebuild((H5S_t *)space1); /* Casting away const OK -QAK */ + H5S__hyper_rebuild(space1); if (space2->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_NO) - H5S__hyper_rebuild((H5S_t *)space2); /* Casting away const OK -QAK */ + H5S__hyper_rebuild(space2); /* If both are regular hyperslabs, compare their diminfo values */ if (space1->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES && @@ -5664,11 +5665,11 @@ H5S__hyper_shape_same(const H5S_t *space1, const H5S_t *space2) /* Make certain that both selections have span trees */ if (NULL == space1->select.sel_info.hslab->span_lst) - if (H5S__hyper_generate_spans((H5S_t *)space1) < 0) /* Casting away const OK -QAK */ + if (H5S__hyper_generate_spans(space1) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "can't construct span tree for hyperslab selection") if (NULL == space2->select.sel_info.hslab->span_lst) - if (H5S__hyper_generate_spans((H5S_t *)space2) < 0) /* Casting away const OK -QAK */ + if (H5S__hyper_generate_spans(space2) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "can't construct span tree for hyperslab selection") @@ -6255,7 +6256,7 @@ done: Detect intersections of selection with block USAGE htri_t H5S__hyper_intersect_block(space, start, end) - const H5S_t *space; IN: Dataspace with selection to use + H5S_t *space; IN: Dataspace with selection to use const hsize_t *start; IN: Starting coordinate for block const hsize_t *end; IN: Ending coordinate for block RETURNS @@ -6270,7 +6271,7 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static htri_t -H5S__hyper_intersect_block(const H5S_t *space, const hsize_t *start, const hsize_t *end) +H5S__hyper_intersect_block(H5S_t *space, const hsize_t *start, const hsize_t *end) { htri_t ret_value = FAIL; /* Return value */ @@ -6286,7 +6287,7 @@ H5S__hyper_intersect_block(const H5S_t *space, const hsize_t *start, const hsize * to be impossible. */ if (space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_NO) - H5S__hyper_rebuild((H5S_t *)space); /* Casting away const OK -QAK */ + H5S__hyper_rebuild(space); /* Check for regular hyperslab intersection */ if (space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) { @@ -11516,7 +11517,7 @@ H5S__hyper_proj_int_iterate(const H5S_hyper_span_info_t *ss_span_info, udata->skip += (count - 1) * (udata->skip - old_skip); } /* end if */ else { - /* Third case: agorithm added skip and nelem (in that + /* Third case: algorithm added skip and nelem (in that * order). Add the same skip and nelem once for each item * remaining in count. */ hsize_t skip_add; @@ -11592,8 +11593,8 @@ also that proj_space can share some span trees with dst_space, so proj_space mus if dst_space must be preserved. GLOBAL VARIABLES COMMENTS, BUGS, ASSUMPTIONS EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5S__hyper_project_intersection(const H5S_t *src_space, const H5S_t *dst_space, - const H5S_t *src_intersect_space, H5S_t *proj_space, hbool_t share_selection) +H5S__hyper_project_intersection(H5S_t *src_space, H5S_t *dst_space, H5S_t *src_intersect_space, + H5S_t *proj_space, hbool_t share_selection) { H5S_hyper_project_intersect_ud_t udata; /* User data for subroutines */ const H5S_hyper_span_info_t * ss_span_info; @@ -11622,7 +11623,7 @@ H5S__hyper_project_intersection(const H5S_t *src_space, const H5S_t *dst_space, if (H5S_GET_SELECT_TYPE(src_space) == H5S_SEL_HYPERSLABS) { /* Make certain the selection has a span tree */ if (NULL == src_space->select.sel_info.hslab->span_lst) - if (H5S__hyper_generate_spans((H5S_t *)src_space) < 0) /* Casting away const OK -NAF */ + if (H5S__hyper_generate_spans(src_space) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "can't construct span tree for source hyperslab selection") @@ -11644,7 +11645,7 @@ H5S__hyper_project_intersection(const H5S_t *src_space, const H5S_t *dst_space, if (H5S_GET_SELECT_TYPE(dst_space) == H5S_SEL_HYPERSLABS) { /* Make certain the selection has a span tree */ if (NULL == dst_space->select.sel_info.hslab->span_lst) - if (H5S__hyper_generate_spans((H5S_t *)dst_space) < 0) /* Casting away const OK -NAF */ + if (H5S__hyper_generate_spans(dst_space) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "can't construct span tree for dsetination hyperslab selection") @@ -11664,7 +11665,7 @@ H5S__hyper_project_intersection(const H5S_t *src_space, const H5S_t *dst_space, /* Make certain the source intersect selection has a span tree */ if (NULL == src_intersect_space->select.sel_info.hslab->span_lst) - if (H5S__hyper_generate_spans((H5S_t *)src_intersect_space) < 0) /* Casting away const OK -NAF */ + if (H5S__hyper_generate_spans(src_intersect_space) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "can't construct span tree for source intersect hyperslab selection") @@ -12036,7 +12037,7 @@ H5S_hyper_get_clip_extent(const H5S_t *clip_space, const H5S_t *match_space, hbo hsize_t num_slices; /* Number of slices in unlimited dimension */ hsize_t ret_value = 0; /* Return value */ - FUNC_ENTER_NOAPI(0) + FUNC_ENTER_NOAPI_NOERR /* Check parameters */ HDassert(clip_space); @@ -12058,7 +12059,6 @@ H5S_hyper_get_clip_extent(const H5S_t *clip_space, const H5S_t *match_space, hbo /* Call "real" get_clip_extent function */ ret_value = H5S__hyper_get_clip_extent_real(clip_space, num_slices, incl_trail); -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5S_hyper_get_clip_extent() */ @@ -12094,7 +12094,7 @@ H5S_hyper_get_clip_extent_match(const H5S_t *clip_space, const H5S_t *match_spac hsize_t num_slices; /* Number of slices in unlimited dimension */ hsize_t ret_value = 0; /* Return value */ - FUNC_ENTER_NOAPI(0) + FUNC_ENTER_NOAPI_NOERR /* Check parameters */ HDassert(clip_space); @@ -12140,7 +12140,6 @@ H5S_hyper_get_clip_extent_match(const H5S_t *clip_space, const H5S_t *match_spac /* Call "real" get_clip_extent function */ ret_value = H5S__hyper_get_clip_extent_real(clip_space, num_slices, incl_trail); -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5S_hyper_get_clip_extent_match() */ @@ -12256,7 +12255,7 @@ H5S_hyper_get_first_inc_block(const H5S_t *space, hsize_t clip_size, hbool_t *pa H5S_hyper_dim_t *diminfo; /* Convenience pointer to diminfo in unlimited dimension */ hsize_t ret_value = 0; - FUNC_ENTER_NOAPI(0) + FUNC_ENTER_NOAPI_NOERR /* Check parameters */ HDassert(space); @@ -12286,7 +12285,6 @@ H5S_hyper_get_first_inc_block(const H5S_t *space, hsize_t clip_size, hbool_t *pa } /* end if */ } /* end else */ -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5S_hyper_get_first_inc_block */ diff --git a/src/H5Smpio.c b/src/H5Smpio.c index b626b77..da9b41d 100644 --- a/src/H5Smpio.c +++ b/src/H5Smpio.c @@ -223,7 +223,7 @@ H5S__mpio_create_point_datatype(size_t elmt_size, hsize_t num_points, MPI_Aint * /* Check whether standard or BIGIO processing will be employeed */ if (bigio_count >= num_points) { -#if MPI_VERSION >= 3 +#if H5_CHECK_MPI_VERSION(3, 0) /* Create an MPI datatype for the whole point selection */ if (MPI_SUCCESS != (mpi_code = MPI_Type_create_hindexed_block((int)num_points, 1, disp, elmt_type, new_type))) @@ -284,7 +284,7 @@ H5S__mpio_create_point_datatype(size_t elmt_size, hsize_t num_points, MPI_Aint * #endif for (i = 0; i < num_big_types; i++) { -#if MPI_VERSION >= 3 +#if H5_CHECK_MPI_VERSION(3, 0) if (MPI_SUCCESS != (mpi_code = MPI_Type_create_hindexed_block((int)bigio_count, 1, &disp[(hsize_t)i * bigio_count], elmt_type, &inner_types[i]))) @@ -300,7 +300,7 @@ H5S__mpio_create_point_datatype(size_t elmt_size, hsize_t num_points, MPI_Aint * } /* end for*/ if (remaining_points) { -#if MPI_VERSION >= 3 +#if H5_CHECK_MPI_VERSION(3, 0) if (MPI_SUCCESS != (mpi_code = MPI_Type_create_hindexed_block( remaining_points, 1, &disp[(hsize_t)num_big_types * bigio_count], elmt_type, &inner_types[num_big_types]))) @@ -1145,7 +1145,7 @@ H5S__obtain_datatype(H5S_hyper_span_info_t *spans, const hsize_t *down, size_t e /* If this is the fastest changing dimension, it is the base case for derived datatype. */ span = spans->head; if (NULL == span->down) { - hbool_t large_block = FALSE; /* Wether the block length is larger than 32 bit integer */ + hbool_t large_block = FALSE; /* Whether the block length is larger than 32 bit integer */ outercount = 0; while (span) { diff --git a/src/H5Snone.c b/src/H5Snone.c index 82e513e..9292cd4 100644 --- a/src/H5Snone.c +++ b/src/H5Snone.c @@ -49,22 +49,22 @@ static herr_t H5S__none_copy(H5S_t *dst, const H5S_t *src, hbool_t share_selection); static herr_t H5S__none_release(H5S_t *space); static htri_t H5S__none_is_valid(const H5S_t *space); -static hssize_t H5S__none_serial_size(const H5S_t *space); -static herr_t H5S__none_serialize(const H5S_t *space, uint8_t **p); +static hssize_t H5S__none_serial_size(H5S_t *space); +static herr_t H5S__none_serialize(H5S_t *space, uint8_t **p); static herr_t H5S__none_deserialize(H5S_t **space, const uint8_t **p); static herr_t H5S__none_bounds(const H5S_t *space, hsize_t *start, hsize_t *end); static herr_t H5S__none_offset(const H5S_t *space, hsize_t *off); static int H5S__none_unlim_dim(const H5S_t *space); 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 htri_t H5S__none_shape_same(const H5S_t *space1, const H5S_t *space2); -static htri_t H5S__none_intersect_block(const H5S_t *space, const hsize_t *start, const hsize_t *end); +static htri_t H5S__none_is_regular(H5S_t *space); +static htri_t H5S__none_shape_same(H5S_t *space1, H5S_t *space2); +static htri_t H5S__none_intersect_block(H5S_t *space, const hsize_t *start, const hsize_t *end); static herr_t H5S__none_adjust_u(H5S_t *space, const hsize_t *offset); static herr_t H5S__none_adjust_s(H5S_t *space, const hssize_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(const H5S_t *space, H5S_sel_iter_t *iter); +static herr_t H5S__none_iter_init(H5S_t *space, H5S_sel_iter_t *iter); /* Selection iteration callbacks */ static herr_t H5S__none_iter_coords(const H5S_sel_iter_t *iter, hsize_t *coords); @@ -144,7 +144,7 @@ static const H5S_sel_iter_class_t H5S_sel_iter_none[1] = {{ *------------------------------------------------------------------------- */ static herr_t -H5S__none_iter_init(const H5S_t H5_ATTR_UNUSED *space, H5S_sel_iter_t *iter) +H5S__none_iter_init(H5S_t H5_ATTR_UNUSED *space, H5S_sel_iter_t *iter) { FUNC_ENTER_STATIC_NOERR @@ -513,7 +513,7 @@ H5S__none_is_valid(const H5S_t H5_ATTR_UNUSED *space) REVISION LOG --------------------------------------------------------------------------*/ static hssize_t -H5S__none_serial_size(const H5S_t H5_ATTR_UNUSED *space) +H5S__none_serial_size(H5S_t H5_ATTR_UNUSED *space) { FUNC_ENTER_STATIC_NOERR @@ -533,7 +533,7 @@ H5S__none_serial_size(const H5S_t H5_ATTR_UNUSED *space) Serialize the current selection into a user-provided buffer. USAGE herr_t H5S__none_serialize(space, p) - const H5S_t *space; IN: Dataspace with selection to serialize + H5S_t *space; IN: Dataspace with selection to serialize uint8_t **p; OUT: Pointer to buffer to put serialized selection. Will be advanced to end of serialized selection. @@ -548,7 +548,7 @@ H5S__none_serial_size(const H5S_t H5_ATTR_UNUSED *space) REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S__none_serialize(const H5S_t *space, uint8_t **p) +H5S__none_serialize(H5S_t *space, uint8_t **p) { uint8_t *pp = (*p); /* Local pointer for decoding */ @@ -803,7 +803,7 @@ H5S__none_is_single(const H5S_t H5_ATTR_UNUSED *space) Check if a "none" selection is "regular" USAGE htri_t H5S__none_is_regular(space) - const H5S_t *space; IN: Dataspace pointer to check + H5S_t *space; IN: Dataspace pointer to check RETURNS TRUE/FALSE/FAIL DESCRIPTION @@ -816,7 +816,7 @@ H5S__none_is_single(const H5S_t H5_ATTR_UNUSED *space) REVISION LOG --------------------------------------------------------------------------*/ static htri_t -H5S__none_is_regular(const H5S_t H5_ATTR_UNUSED *space) +H5S__none_is_regular(H5S_t H5_ATTR_UNUSED *space) { FUNC_ENTER_STATIC_NOERR @@ -833,8 +833,8 @@ H5S__none_is_regular(const H5S_t H5_ATTR_UNUSED *space) Check if a two "none" selections are the same shape USAGE htri_t H5S__none_shape_same(space1, space2) - const H5S_t *space1; IN: First dataspace to check - const H5S_t *space2; IN: Second dataspace to check + H5S_t *space1; IN: First dataspace to check + H5S_t *space2; IN: Second dataspace to check RETURNS TRUE / FALSE / FAIL DESCRIPTION @@ -846,7 +846,7 @@ H5S__none_is_regular(const H5S_t H5_ATTR_UNUSED *space) REVISION LOG --------------------------------------------------------------------------*/ static htri_t -H5S__none_shape_same(const H5S_t H5_ATTR_UNUSED *space1, const H5S_t H5_ATTR_UNUSED *space2) +H5S__none_shape_same(H5S_t H5_ATTR_UNUSED *space1, H5S_t H5_ATTR_UNUSED *space2) { FUNC_ENTER_STATIC_NOERR @@ -864,7 +864,7 @@ H5S__none_shape_same(const H5S_t H5_ATTR_UNUSED *space1, const H5S_t H5_ATTR_UNU Detect intersections of selection with block USAGE htri_t H5S__none_intersect_block(space, start, end) - const H5S_t *space; IN: Dataspace with selection to use + H5S_t *space; IN: Dataspace with selection to use const hsize_t *start; IN: Starting coordinate for block const hsize_t *end; IN: Ending coordinate for block RETURNS @@ -877,7 +877,7 @@ H5S__none_shape_same(const H5S_t H5_ATTR_UNUSED *space1, const H5S_t H5_ATTR_UNU REVISION LOG --------------------------------------------------------------------------*/ htri_t -H5S__none_intersect_block(const H5S_t H5_ATTR_UNUSED *space, const hsize_t H5_ATTR_UNUSED *start, +H5S__none_intersect_block(H5S_t H5_ATTR_UNUSED *space, const hsize_t H5_ATTR_UNUSED *start, const hsize_t H5_ATTR_UNUSED *end) { FUNC_ENTER_STATIC_NOERR diff --git a/src/H5Spkg.h b/src/H5Spkg.h index c89b616..afabf25 100644 --- a/src/H5Spkg.h +++ b/src/H5Spkg.h @@ -201,7 +201,7 @@ struct H5S_hyper_span_info_t { typedef enum { H5S_DIMINFO_VALID_IMPOSSIBLE, /* 0: diminfo is not valid and can never be valid with the current selection */ - H5S_DIMINFO_VALID_NO, /* 1: diminfo is not valid but may or may not be possible to constuct */ + H5S_DIMINFO_VALID_NO, /* 1: diminfo is not valid but may or may not be possible to construct */ H5S_DIMINFO_VALID_YES /* 2: diminfo is valid */ } H5S_diminfo_valid_t; @@ -242,9 +242,9 @@ typedef herr_t (*H5S_sel_release_func_t)(H5S_t *space); /* Method to determine if current selection is valid for dataspace */ typedef htri_t (*H5S_sel_is_valid_func_t)(const H5S_t *space); /* Method to determine number of bytes required to store current selection */ -typedef hssize_t (*H5S_sel_serial_size_func_t)(const H5S_t *space); +typedef hssize_t (*H5S_sel_serial_size_func_t)(H5S_t *space); /* Method to store current selection in "serialized" form (a byte sequence suitable for storing on disk) */ -typedef herr_t (*H5S_sel_serialize_func_t)(const H5S_t *space, uint8_t **p); +typedef herr_t (*H5S_sel_serialize_func_t)(H5S_t *space, uint8_t **p); /* Method to create selection from "serialized" form (a byte sequence suitable for storing on disk) */ typedef herr_t (*H5S_sel_deserialize_func_t)(H5S_t **space, const uint8_t **p); /* Method to determine smallest n-D bounding box containing the current selection */ @@ -260,12 +260,11 @@ typedef htri_t (*H5S_sel_is_contiguous_func_t)(const H5S_t *space); /* Method to determine if current selection is a single block */ typedef htri_t (*H5S_sel_is_single_func_t)(const H5S_t *space); /* Method to determine if current selection is "regular" */ -typedef htri_t (*H5S_sel_is_regular_func_t)(const H5S_t *space); +typedef htri_t (*H5S_sel_is_regular_func_t)(H5S_t *space); /* Method to determine if two dataspaces' selections are the same shape */ -typedef htri_t (*H5S_sel_shape_same_func_t)(const H5S_t *space1, const H5S_t *space2); +typedef htri_t (*H5S_sel_shape_same_func_t)(H5S_t *space1, H5S_t *space2); /* Method to determine if selection intersects a block */ -typedef htri_t (*H5S_sel_intersect_block_func_t)(const H5S_t *space, const hsize_t *start, - const hsize_t *end); +typedef htri_t (*H5S_sel_intersect_block_func_t)(H5S_t *space, const hsize_t *start, const hsize_t *end); /* 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 adjust a selection by an offset (signed) */ @@ -275,7 +274,7 @@ 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)(const H5S_t *space, H5S_sel_iter_t *sel_iter); +typedef herr_t (*H5S_sel_iter_init_func_t)(H5S_t *space, H5S_sel_iter_t *sel_iter); /* Selection class information */ typedef struct { @@ -405,9 +404,8 @@ H5_DLL herr_t H5S__extent_copy_real(H5S_extent_t *dst, const H5S_extent_t *src, H5_DLL uint64_t H5S__hyper_get_op_gen(void); H5_DLL void H5S__hyper_rebuild(H5S_t *space); H5_DLL herr_t H5S__modify_select(H5S_t *space1, H5S_seloper_t op, H5S_t *space2); -H5_DLL herr_t H5S__hyper_project_intersection(const H5S_t *src_space, const H5S_t *dst_space, - const H5S_t *src_intersect_space, H5S_t *proj_space, - hbool_t share_space); +H5_DLL herr_t H5S__hyper_project_intersection(H5S_t *src_space, H5S_t *dst_space, H5S_t *src_intersect_space, + H5S_t *proj_space, hbool_t share_space); /* Operations on selection iterators */ H5_DLL herr_t H5S__sel_iter_close_cb(H5S_sel_iter_t *_sel_iter, void **request); diff --git a/src/H5Spoint.c b/src/H5Spoint.c index 5991116..bc667b1 100644 --- a/src/H5Spoint.c +++ b/src/H5Spoint.c @@ -59,22 +59,22 @@ static void H5S__free_pnt_list(H5S_pnt_list_t *pnt_lst); static herr_t H5S__point_copy(H5S_t *dst, const H5S_t *src, hbool_t share_selection); static herr_t H5S__point_release(H5S_t *space); static htri_t H5S__point_is_valid(const H5S_t *space); -static hssize_t H5S__point_serial_size(const H5S_t *space); -static herr_t H5S__point_serialize(const H5S_t *space, uint8_t **p); +static hssize_t H5S__point_serial_size(H5S_t *space); +static herr_t H5S__point_serialize(H5S_t *space, uint8_t **p); static herr_t H5S__point_deserialize(H5S_t **space, const uint8_t **p); static herr_t H5S__point_bounds(const H5S_t *space, hsize_t *start, hsize_t *end); static herr_t H5S__point_offset(const H5S_t *space, hsize_t *off); static int H5S__point_unlim_dim(const H5S_t *space); 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 htri_t H5S__point_shape_same(const H5S_t *space1, const H5S_t *space2); -static htri_t H5S__point_intersect_block(const H5S_t *space, const hsize_t *start, const hsize_t *end); +static htri_t H5S__point_is_regular(H5S_t *space); +static htri_t H5S__point_shape_same(H5S_t *space1, H5S_t *space2); +static htri_t H5S__point_intersect_block(H5S_t *space, const hsize_t *start, const hsize_t *end); static herr_t H5S__point_adjust_u(H5S_t *space, const hsize_t *offset); static herr_t H5S__point_adjust_s(H5S_t *space, const hssize_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(const H5S_t *space, H5S_sel_iter_t *iter); +static herr_t H5S__point_iter_init(H5S_t *space, H5S_sel_iter_t *iter); static herr_t H5S__point_get_version_enc_size(const H5S_t *space, uint32_t *version, uint8_t *enc_size); /* Selection iteration callbacks */ @@ -170,7 +170,7 @@ H5FL_DEFINE_STATIC(H5S_pnt_list_t); *------------------------------------------------------------------------- */ static herr_t -H5S__point_iter_init(const H5S_t *space, H5S_sel_iter_t *iter) +H5S__point_iter_init(H5S_t *space, H5S_sel_iter_t *iter) { herr_t ret_value = SUCCEED; /* Return value */ @@ -1060,7 +1060,7 @@ H5S__point_get_version_enc_size(const H5S_t *space, uint32_t *version, uint8_t * hsize_t bounds_start[H5S_MAX_RANK]; /* Starting coordinate of bounding box */ hsize_t bounds_end[H5S_MAX_RANK]; /* Opposite coordinate of bounding box */ hsize_t max_size = 0; /* Maximum selection size */ - unsigned u; /* Local index veriable */ + unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC @@ -1159,7 +1159,7 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static hssize_t -H5S__point_serial_size(const H5S_t *space) +H5S__point_serial_size(H5S_t *space) { uint32_t version; /* Version number */ uint8_t enc_size; /* Encoded size of point selection info */ @@ -1204,7 +1204,7 @@ done: Serialize the current selection into a user-provided buffer. USAGE herr_t H5S__point_serialize(space, p) - const H5S_t *space; IN: Dataspace with selection to serialize + H5S_t *space; IN: Dataspace with selection to serialize uint8_t **p; OUT: Pointer to buffer to put serialized selection. Will be advanced to end of serialized selection. @@ -1219,7 +1219,7 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S__point_serialize(const H5S_t *space, uint8_t **p) +H5S__point_serialize(H5S_t *space, uint8_t **p) { H5S_pnt_node_t *curr; /* Point information nodes */ uint8_t * pp; /* Local pointer for encoding */ @@ -1505,7 +1505,7 @@ done: dataspace they are located within. The list of points is formatted as follows: <coordinate> followed by the next coordinate, etc. until all the point information in the selection have been put into the user's buffer. - The points are returned in the order they will be interated through + The points are returned in the order they will be iterated through when a selection is read/written from/to disk. GLOBAL VARIABLES COMMENTS, BUGS, ASSUMPTIONS @@ -1579,7 +1579,7 @@ H5S__get_select_elem_pointlist(const H5S_t *space, hsize_t startpoint, hsize_t n dataspace they are located within. The list of points is formatted as follows: <coordinate> followed by the next coordinate, etc. until all the point information in the selection have been put into the user's buffer. - The points are returned in the order they will be interated through + The points are returned in the order they will be iterated through when a selection is read/written from/to disk. GLOBAL VARIABLES COMMENTS, BUGS, ASSUMPTIONS @@ -1844,7 +1844,7 @@ H5S__point_is_single(const H5S_t *space) Check if a point selection is "regular" USAGE htri_t H5S__point_is_regular(space) - const H5S_t *space; IN: Dataspace pointer to check + H5S_t *space; IN: Dataspace pointer to check RETURNS TRUE/FALSE/FAIL DESCRIPTION @@ -1859,7 +1859,7 @@ H5S__point_is_single(const H5S_t *space) REVISION LOG --------------------------------------------------------------------------*/ static htri_t -H5S__point_is_regular(const H5S_t *space) +H5S__point_is_regular(H5S_t *space) { htri_t ret_value = FAIL; /* Return value */ @@ -1884,8 +1884,8 @@ H5S__point_is_regular(const H5S_t *space) Check if a two "point" selections are the same shape USAGE htri_t H5S__point_shape_same(space1, space2) - const H5S_t *space1; IN: First dataspace to check - const H5S_t *space2; IN: Second dataspace to check + H5S_t *space1; IN: First dataspace to check + H5S_t *space2; IN: Second dataspace to check RETURNS TRUE / FALSE / FAIL DESCRIPTION @@ -1897,7 +1897,7 @@ H5S__point_is_regular(const H5S_t *space) REVISION LOG --------------------------------------------------------------------------*/ static htri_t -H5S__point_shape_same(const H5S_t *space1, const H5S_t *space2) +H5S__point_shape_same(H5S_t *space1, H5S_t *space2) { H5S_pnt_node_t *pnt1, *pnt2; /* Point information nodes */ hssize_t offset[H5S_MAX_RANK]; /* Offset between the selections */ @@ -1990,7 +1990,7 @@ done: Detect intersections of selection with block USAGE htri_t H5S__point_intersect_block(space, start, end) - const H5S_t *space; IN: Dataspace with selection to use + H5S_t *space; IN: Dataspace with selection to use const hsize_t *start; IN: Starting coordinate for block const hsize_t *end; IN: Ending coordinate for block RETURNS @@ -2003,7 +2003,7 @@ done: REVISION LOG --------------------------------------------------------------------------*/ htri_t -H5S__point_intersect_block(const H5S_t *space, const hsize_t *start, const hsize_t *end) +H5S__point_intersect_block(H5S_t *space, const hsize_t *start, const hsize_t *end) { H5S_pnt_node_t *pnt; /* Point information node */ htri_t ret_value = FALSE; /* Return value */ diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h index 51a98a6..8a14563 100644 --- a/src/H5Sprivate.h +++ b/src/H5Sprivate.h @@ -232,36 +232,35 @@ H5_DLL herr_t H5S_extent_copy(H5S_t *dst, const H5S_t *src); /* Operations on selections */ H5_DLL herr_t H5S_select_deserialize(H5S_t **space, const uint8_t **p); H5_DLL H5S_sel_type H5S_get_select_type(const H5S_t *space); -H5_DLL herr_t H5S_select_iterate(void *buf, const H5T_t *type, const H5S_t *space, - const H5S_sel_iter_op_t *op, void *op_data); -H5_DLL herr_t H5S_select_fill(const void *fill, size_t fill_size, const H5S_t *space, void *buf); -H5_DLL htri_t H5S_select_valid(const H5S_t *space); -H5_DLL hsize_t H5S_get_select_npoints(const H5S_t *space); -H5_DLL herr_t H5S_get_select_bounds(const H5S_t *space, hsize_t *start, hsize_t *end); -H5_DLL herr_t H5S_get_select_offset(const H5S_t *space, hsize_t *offset); -H5_DLL int H5S_get_select_unlim_dim(const H5S_t *space); -H5_DLL herr_t H5S_get_select_num_elem_non_unlim(const H5S_t *space, hsize_t *num_elem_non_unlim); -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 htri_t H5S_select_intersect_block(const H5S_t *space, const hsize_t *start, const hsize_t *end); -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 hssize_t H5S_select_serial_size(const H5S_t *space); -H5_DLL herr_t H5S_select_serialize(const H5S_t *space, uint8_t **p); -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_adjust_s(H5S_t *space, const hssize_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); -H5_DLL herr_t H5S_select_project_intersection(const H5S_t *src_space, const H5S_t *dst_space, - const H5S_t *src_intersect_space, H5S_t **new_space_ptr, - hbool_t share_space); -H5_DLL herr_t H5S_select_subtract(H5S_t *space, H5S_t *subtract_space); +H5_DLL herr_t H5S_select_iterate(void *buf, const H5T_t *type, H5S_t *space, const H5S_sel_iter_op_t *op, + void *op_data); +H5_DLL herr_t H5S_select_fill(const void *fill, size_t fill_size, H5S_t *space, void *buf); +H5_DLL htri_t H5S_select_valid(const H5S_t *space); +H5_DLL hsize_t H5S_get_select_npoints(const H5S_t *space); +H5_DLL herr_t H5S_get_select_bounds(const H5S_t *space, hsize_t *start, hsize_t *end); +H5_DLL herr_t H5S_get_select_offset(const H5S_t *space, hsize_t *offset); +H5_DLL int H5S_get_select_unlim_dim(const H5S_t *space); +H5_DLL herr_t H5S_get_select_num_elem_non_unlim(const H5S_t *space, hsize_t *num_elem_non_unlim); +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(H5S_t *space1, H5S_t *space2); +H5_DLL htri_t H5S_select_intersect_block(H5S_t *space, const hsize_t *start, const hsize_t *end); +H5_DLL herr_t H5S_select_construct_projection(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 hssize_t H5S_select_serial_size(H5S_t *space); +H5_DLL herr_t H5S_select_serialize(H5S_t *space, uint8_t **p); +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(H5S_t *space); +H5_DLL herr_t H5S_select_adjust_u(H5S_t *space, const hsize_t *offset); +H5_DLL herr_t H5S_select_adjust_s(H5S_t *space, const hssize_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); +H5_DLL herr_t H5S_select_project_intersection(H5S_t *src_space, H5S_t *dst_space, H5S_t *src_intersect_space, + H5S_t **new_space_ptr, hbool_t share_space); +H5_DLL herr_t H5S_select_subtract(H5S_t *space, H5S_t *subtract_space); /* Operations on all selections */ H5_DLL herr_t H5S_select_all(H5S_t *space, hbool_t rel_prev); @@ -290,8 +289,7 @@ H5_DLL H5S_t * H5S_hyper_get_unlim_block(const H5S_t *space, hsize_t block_index H5_DLL hsize_t H5S_hyper_get_first_inc_block(const H5S_t *space, hsize_t clip_size, hbool_t *partial); /* Operations on selection iterators */ -H5_DLL herr_t H5S_select_iter_init(H5S_sel_iter_t *iter, const H5S_t *space, size_t elmt_size, - unsigned flags); +H5_DLL herr_t H5S_select_iter_init(H5S_sel_iter_t *iter, H5S_t *space, size_t elmt_size, unsigned flags); H5_DLL herr_t H5S_select_iter_coords(const H5S_sel_iter_t *sel_iter, hsize_t *coords); H5_DLL hsize_t H5S_select_iter_nelmts(const H5S_sel_iter_t *sel_iter); H5_DLL herr_t H5S_select_iter_next(H5S_sel_iter_t *sel_iter, size_t nelem); diff --git a/src/H5Spublic.h b/src/H5Spublic.h index 30ca813..536f290 100644 --- a/src/H5Spublic.h +++ b/src/H5Spublic.h @@ -171,7 +171,7 @@ H5_DLL herr_t H5Sclose(hid_t space_id); * composing the entire current extent). If either \p stride or * \p block is NULL, then it will be set to \p 1. * - * \since 1.12.0 + * \since 1.10.6 * */ H5_DLL hid_t H5Scombine_hyperslab(hid_t space_id, H5S_seloper_t op, const hsize_t start[], @@ -194,7 +194,7 @@ H5_DLL hid_t H5Scombine_hyperslab(hid_t space_id, H5S_seloper_t op, const hsize_ * from \p space1_id is copied for the dataspace extent of the * newly created dataspace. * - * \since 1.12.0 + * \since 1.10.6 * */ H5_DLL hid_t H5Scombine_select(hid_t space1_id, H5S_seloper_t op, hid_t space2_id); @@ -795,7 +795,7 @@ H5_DLL htri_t H5Sis_simple(hid_t space_id); * \p space2_id. The first selection is modified to contain the * result of \p space1_id operated on by \p space2_id. * - * \since 1.12.0 + * \since 1.10.6 * */ H5_DLL herr_t H5Smodify_select(hid_t space1_id, H5S_seloper_t op, hid_t space2_id); @@ -940,7 +940,7 @@ H5_DLL herr_t H5Ssel_iter_reset(hid_t sel_iter_id, hid_t space_id); * * \note This can be useful for VOL developers to implement chunked datasets. * - * \since 1.12.0 + * \since 1.10.6 */ H5_DLL herr_t H5Sselect_adjust(hid_t spaceid, const hssize_t *offset); /** @@ -977,7 +977,7 @@ H5_DLL herr_t H5Sselect_all(hid_t spaceid); * offset) from the source dataspace \p src_id to the destination * dataspace \p dst_id. * - * \since 1.12.0 + * \since 1.10.6 * */ H5_DLL herr_t H5Sselect_copy(hid_t dst_id, hid_t src_id); @@ -1205,7 +1205,7 @@ H5_DLL herr_t H5Sselect_hyperslab(hid_t space_id, H5S_seloper_t op, const hsize_ * \note Assumes that \p start & \p end block bounds are inclusive, so * \p start == \p end value is OK. * - * \since 1.12.0 + * \since 1.10.6 * */ H5_DLL htri_t H5Sselect_intersect_block(hid_t space_id, const hsize_t *start, const hsize_t *end); @@ -1244,7 +1244,7 @@ H5_DLL herr_t H5Sselect_none(hid_t spaceid); * into a third selection.This can be useful for VOL developers to * implement chunked or virtual datasets. * - * \since 1.12.0 + * \since 1.10.6 * */ H5_DLL hid_t H5Sselect_project_intersection(hid_t src_space_id, hid_t dst_space_id, @@ -1265,7 +1265,7 @@ H5_DLL hid_t H5Sselect_project_intersection(hid_t src_space_id, hid_t dst_space_ * This is primarily used for reading the entire selection in * one swoop. * - * \since 1.12.0 + * \since 1.10.6 * */ H5_DLL htri_t H5Sselect_shape_same(hid_t space1_id, hid_t space2_id); diff --git a/src/H5Sselect.c b/src/H5Sselect.c index 7a0ea3c..bcf12a0 100644 --- a/src/H5Sselect.c +++ b/src/H5Sselect.c @@ -304,7 +304,7 @@ done: *------------------------------------------------------------------------- */ hssize_t -H5S_select_serial_size(const H5S_t *space) +H5S_select_serial_size(H5S_t *space) { hssize_t ret_value = -1; /* Return value */ @@ -343,7 +343,7 @@ H5S_select_serial_size(const H5S_t *space) REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5S_select_serialize(const H5S_t *space, uint8_t **p) +H5S_select_serialize(H5S_t *space, uint8_t **p) { herr_t ret_value = SUCCEED; /* Return value */ @@ -880,7 +880,7 @@ H5S_select_is_single(const H5S_t *space) REVISION LOG --------------------------------------------------------------------------*/ htri_t -H5S_select_is_regular(const H5S_t *space) +H5S_select_is_regular(H5S_t *space) { herr_t ret_value = FAIL; /* Return value */ @@ -1116,7 +1116,7 @@ H5S_select_project_simple(const H5S_t *space, H5S_t *new_space, hsize_t *offset) in the dataspace's selection. --------------------------------------------------------------------------*/ herr_t -H5S_select_iter_init(H5S_sel_iter_t *sel_iter, const H5S_t *space, size_t elmt_size, unsigned flags) +H5S_select_iter_init(H5S_sel_iter_t *sel_iter, H5S_t *space, size_t elmt_size, unsigned flags) { herr_t ret_value = FAIL; /* Return value */ @@ -1497,8 +1497,7 @@ H5S_select_iter_release(H5S_sel_iter_t *sel_iter) the selection is not modified. --------------------------------------------------------------------------*/ herr_t -H5S_select_iterate(void *buf, const H5T_t *type, const H5S_t *space, const H5S_sel_iter_op_t *op, - void *op_data) +H5S_select_iterate(void *buf, const H5T_t *type, H5S_t *space, const H5S_sel_iter_op_t *op, void *op_data) { H5S_sel_iter_t *iter = NULL; /* Selection iteration info */ hbool_t iter_init = FALSE; /* Selection iteration info has been initialized */ @@ -1739,7 +1738,7 @@ H5S_get_select_type(const H5S_t *space) REVISION LOG --------------------------------------------------------------------------*/ htri_t -H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2) +H5S_select_shape_same(H5S_t *space1, H5S_t *space2) { H5S_sel_iter_t *iter_a = NULL; /* Selection a iteration info */ H5S_sel_iter_t *iter_b = NULL; /* Selection b iteration info */ @@ -1760,8 +1759,8 @@ H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2) /* Check special cases if both dataspaces aren't scalar */ /* (If only one is, the number of selected points check is sufficient) */ if (space1->extent.rank > 0 && space2->extent.rank > 0) { - const H5S_t *space_a; /* Dataspace with larger rank */ - const H5S_t *space_b; /* Dataspace with smaller rank */ + H5S_t * space_a; /* Dataspace with larger rank */ + 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 */ int space_a_dim; /* Current dimension in dataspace A */ @@ -2063,7 +2062,7 @@ done: don't call it directly, use the appropriate macro defined in H5Sprivate.h. --------------------------------------------------------------------------*/ htri_t -H5S_select_intersect_block(const H5S_t *space, const hsize_t *start, const hsize_t *end) +H5S_select_intersect_block(H5S_t *space, const hsize_t *start, const hsize_t *end) { htri_t ret_value = TRUE; /* Return value */ @@ -2214,7 +2213,7 @@ done: REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5S_select_construct_projection(const H5S_t *base_space, H5S_t **new_space_ptr, unsigned new_space_rank, +H5S_select_construct_projection(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 */ @@ -2247,7 +2246,7 @@ H5S_select_construct_projection(const H5S_t *base_space, H5S_t **new_space_ptr, if (new_space_rank == 0) { hssize_t npoints; /* Number of points selected */ - /* Retreve the number of elements selected */ + /* Retrieve 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); @@ -2316,12 +2315,12 @@ H5S_select_construct_projection(const H5S_t *base_space, H5S_t **new_space_ptr, * 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 + * in the dimensions with the fastest changing indices 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). + * more slowly changing indices). */ if (new_space_rank > base_space_rank) { hsize_t tmp_dim_size = 1; /* Temporary dimension value, for filling arrays */ @@ -2452,7 +2451,7 @@ done: REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5S_select_fill(const void *fill, size_t fill_size, const H5S_t *space, void *_buf) +H5S_select_fill(const void *fill, size_t fill_size, H5S_t *space, void *_buf) { H5S_sel_iter_t *iter = NULL; /* Selection iteration info */ hbool_t iter_init = FALSE; /* Selection iteration info has been initialized */ @@ -2568,9 +2567,8 @@ to share structures inside dst_space with proj_space REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5S_select_project_intersection(const H5S_t *src_space, const H5S_t *dst_space, - const H5S_t *src_intersect_space, H5S_t **new_space_ptr, - hbool_t share_selection) +H5S_select_project_intersection(H5S_t *src_space, H5S_t *dst_space, H5S_t *src_intersect_space, + H5S_t **new_space_ptr, hbool_t share_selection) { H5S_t * new_space = NULL; /* New dataspace constructed */ H5S_t * tmp_src_intersect_space = NULL; /* Temporary SIS converted from points->hyperslabs */ diff --git a/src/H5Stest.c b/src/H5Stest.c index a851549..6a31f3c 100644 --- a/src/H5Stest.c +++ b/src/H5Stest.c @@ -185,12 +185,13 @@ H5S__check_spans_tail_ptr(const H5S_hyper_span_info_t *span_lst) if (NULL != cur_elem->down) if ((ret_value = H5S__check_spans_tail_ptr(cur_elem->down)) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_INCONSISTENTSTATE, FAIL, - "the seletion has inconsistent tail pointers") + "the selection has inconsistent tail pointers") cur_elem = cur_elem->next; } /* end while */ if (actual_tail != span_lst->tail) - HGOTO_ERROR(H5E_DATASPACE, H5E_INCONSISTENTSTATE, FAIL, "the seletion has inconsistent tail pointers") + HGOTO_ERROR(H5E_DATASPACE, H5E_INCONSISTENTSTATE, FAIL, + "the selection has inconsistent tail pointers") done: FUNC_LEAVE_NOAPI(ret_value) @@ -231,7 +232,8 @@ H5S__check_points_tail_ptr(const H5S_pnt_list_t *pnt_lst) cur_elem = cur_elem->next; } /* end while */ if (actual_tail != pnt_lst->tail) - HGOTO_ERROR(H5E_DATASPACE, H5E_INCONSISTENTSTATE, FAIL, "the seletion has inconsistent tail pointers") + HGOTO_ERROR(H5E_DATASPACE, H5E_INCONSISTENTSTATE, FAIL, + "the selection has inconsistent tail pointers") done: FUNC_LEAVE_NOAPI(ret_value) @@ -314,7 +316,7 @@ H5S__check_internal_consistency(const H5S_t *space) if ((NULL != hslab) && (NULL != hslab->span_lst)) if (H5S__check_spans_tail_ptr(hslab->span_lst) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_INCONSISTENTSTATE, FAIL, - "the seletion has inconsistent tail pointers") + "the selection has inconsistent tail pointers") } /* end if */ else if (space->select.type->type == H5S_SEL_POINTS) { H5S_pnt_list_t *pnt_lst = space->select.sel_info.pnt_lst; @@ -322,7 +324,7 @@ H5S__check_internal_consistency(const H5S_t *space) if (NULL != pnt_lst) if (H5S__check_points_tail_ptr(pnt_lst) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_INCONSISTENTSTATE, FAIL, - "the seletion has inconsistent tail pointers") + "the selection has inconsistent tail pointers") } /* end else-if */ done: @@ -368,12 +368,9 @@ H5T_order_t H5T_native_order_g = H5T_ORDER_ERROR; /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /* * Predefined data types. These are initialized at runtime in H5Tinit.c and - * by H5T__init_package() in this source file. + * by H5T_init() in this source file. * * If more of these are added, the new ones must be added to the list of * types to reset in H5T_term_package(). @@ -423,31 +420,29 @@ hid_t H5T_C_S1_g = FAIL; hid_t H5T_FORTRAN_S1_g = FAIL; -hid_t H5T_NATIVE_SCHAR_g = FAIL; -hid_t H5T_NATIVE_UCHAR_g = FAIL; -hid_t H5T_NATIVE_SHORT_g = FAIL; -hid_t H5T_NATIVE_USHORT_g = FAIL; -hid_t H5T_NATIVE_INT_g = FAIL; -hid_t H5T_NATIVE_UINT_g = FAIL; -hid_t H5T_NATIVE_LONG_g = FAIL; -hid_t H5T_NATIVE_ULONG_g = FAIL; -hid_t H5T_NATIVE_LLONG_g = FAIL; -hid_t H5T_NATIVE_ULLONG_g = FAIL; -hid_t H5T_NATIVE_FLOAT_g = FAIL; -hid_t H5T_NATIVE_DOUBLE_g = FAIL; -#if H5_SIZEOF_LONG_DOUBLE != 0 +hid_t H5T_NATIVE_SCHAR_g = FAIL; +hid_t H5T_NATIVE_UCHAR_g = FAIL; +hid_t H5T_NATIVE_SHORT_g = FAIL; +hid_t H5T_NATIVE_USHORT_g = FAIL; +hid_t H5T_NATIVE_INT_g = FAIL; +hid_t H5T_NATIVE_UINT_g = FAIL; +hid_t H5T_NATIVE_LONG_g = FAIL; +hid_t H5T_NATIVE_ULONG_g = FAIL; +hid_t H5T_NATIVE_LLONG_g = FAIL; +hid_t H5T_NATIVE_ULLONG_g = FAIL; +hid_t H5T_NATIVE_FLOAT_g = FAIL; +hid_t H5T_NATIVE_DOUBLE_g = FAIL; hid_t H5T_NATIVE_LDOUBLE_g = FAIL; -#endif -hid_t H5T_NATIVE_B8_g = FAIL; -hid_t H5T_NATIVE_B16_g = FAIL; -hid_t H5T_NATIVE_B32_g = FAIL; -hid_t H5T_NATIVE_B64_g = FAIL; -hid_t H5T_NATIVE_OPAQUE_g = FAIL; -hid_t H5T_NATIVE_HADDR_g = FAIL; -hid_t H5T_NATIVE_HSIZE_g = FAIL; -hid_t H5T_NATIVE_HSSIZE_g = FAIL; -hid_t H5T_NATIVE_HERR_g = FAIL; -hid_t H5T_NATIVE_HBOOL_g = FAIL; +hid_t H5T_NATIVE_B8_g = FAIL; +hid_t H5T_NATIVE_B16_g = FAIL; +hid_t H5T_NATIVE_B32_g = FAIL; +hid_t H5T_NATIVE_B64_g = FAIL; +hid_t H5T_NATIVE_OPAQUE_g = FAIL; +hid_t H5T_NATIVE_HADDR_g = FAIL; +hid_t H5T_NATIVE_HSIZE_g = FAIL; +hid_t H5T_NATIVE_HSSIZE_g = FAIL; +hid_t H5T_NATIVE_HERR_g = FAIL; +hid_t H5T_NATIVE_HBOOL_g = FAIL; hid_t H5T_NATIVE_INT8_g = FAIL; hid_t H5T_NATIVE_UINT8_g = FAIL; @@ -483,21 +478,19 @@ hid_t H5T_NATIVE_UINT_FAST64_g = FAIL; * datatype or C structures, which are different from the alignments for memory * address below this group of variables. */ -size_t H5T_NATIVE_SCHAR_COMP_ALIGN_g = 0; -size_t H5T_NATIVE_UCHAR_COMP_ALIGN_g = 0; -size_t H5T_NATIVE_SHORT_COMP_ALIGN_g = 0; -size_t H5T_NATIVE_USHORT_COMP_ALIGN_g = 0; -size_t H5T_NATIVE_INT_COMP_ALIGN_g = 0; -size_t H5T_NATIVE_UINT_COMP_ALIGN_g = 0; -size_t H5T_NATIVE_LONG_COMP_ALIGN_g = 0; -size_t H5T_NATIVE_ULONG_COMP_ALIGN_g = 0; -size_t H5T_NATIVE_LLONG_COMP_ALIGN_g = 0; -size_t H5T_NATIVE_ULLONG_COMP_ALIGN_g = 0; -size_t H5T_NATIVE_FLOAT_COMP_ALIGN_g = 0; -size_t H5T_NATIVE_DOUBLE_COMP_ALIGN_g = 0; -#if H5_SIZEOF_LONG_DOUBLE != 0 +size_t H5T_NATIVE_SCHAR_COMP_ALIGN_g = 0; +size_t H5T_NATIVE_UCHAR_COMP_ALIGN_g = 0; +size_t H5T_NATIVE_SHORT_COMP_ALIGN_g = 0; +size_t H5T_NATIVE_USHORT_COMP_ALIGN_g = 0; +size_t H5T_NATIVE_INT_COMP_ALIGN_g = 0; +size_t H5T_NATIVE_UINT_COMP_ALIGN_g = 0; +size_t H5T_NATIVE_LONG_COMP_ALIGN_g = 0; +size_t H5T_NATIVE_ULONG_COMP_ALIGN_g = 0; +size_t H5T_NATIVE_LLONG_COMP_ALIGN_g = 0; +size_t H5T_NATIVE_ULLONG_COMP_ALIGN_g = 0; +size_t H5T_NATIVE_FLOAT_COMP_ALIGN_g = 0; +size_t H5T_NATIVE_DOUBLE_COMP_ALIGN_g = 0; size_t H5T_NATIVE_LDOUBLE_COMP_ALIGN_g = 0; -#endif size_t H5T_POINTER_COMP_ALIGN_g = 0; size_t H5T_HVL_COMP_ALIGN_g = 0; @@ -509,21 +502,19 @@ size_t H5T_REF_COMP_ALIGN_g = 0; * Alignment constraints for native types. These are initialized at run time * in H5Tinit.c */ -size_t H5T_NATIVE_SCHAR_ALIGN_g = 0; -size_t H5T_NATIVE_UCHAR_ALIGN_g = 0; -size_t H5T_NATIVE_SHORT_ALIGN_g = 0; -size_t H5T_NATIVE_USHORT_ALIGN_g = 0; -size_t H5T_NATIVE_INT_ALIGN_g = 0; -size_t H5T_NATIVE_UINT_ALIGN_g = 0; -size_t H5T_NATIVE_LONG_ALIGN_g = 0; -size_t H5T_NATIVE_ULONG_ALIGN_g = 0; -size_t H5T_NATIVE_LLONG_ALIGN_g = 0; -size_t H5T_NATIVE_ULLONG_ALIGN_g = 0; -size_t H5T_NATIVE_FLOAT_ALIGN_g = 0; -size_t H5T_NATIVE_DOUBLE_ALIGN_g = 0; -#if H5_SIZEOF_LONG_DOUBLE != 0 +size_t H5T_NATIVE_SCHAR_ALIGN_g = 0; +size_t H5T_NATIVE_UCHAR_ALIGN_g = 0; +size_t H5T_NATIVE_SHORT_ALIGN_g = 0; +size_t H5T_NATIVE_USHORT_ALIGN_g = 0; +size_t H5T_NATIVE_INT_ALIGN_g = 0; +size_t H5T_NATIVE_UINT_ALIGN_g = 0; +size_t H5T_NATIVE_LONG_ALIGN_g = 0; +size_t H5T_NATIVE_ULONG_ALIGN_g = 0; +size_t H5T_NATIVE_LLONG_ALIGN_g = 0; +size_t H5T_NATIVE_ULLONG_ALIGN_g = 0; +size_t H5T_NATIVE_FLOAT_ALIGN_g = 0; +size_t H5T_NATIVE_DOUBLE_ALIGN_g = 0; size_t H5T_NATIVE_LDOUBLE_ALIGN_g = 0; -#endif /* * Alignment constraints for C9x types. These are initialized at run time in @@ -606,34 +597,6 @@ static const H5I_class_t H5I_DATATYPE_CLS[1] = {{ (H5I_free_t)H5T__close_cb /* Callback routine for closing objects of this class */ }}; -/* Flag indicating "top" of interface has been initialized */ -static hbool_t H5T_top_package_initialize_s = FALSE; - -/*------------------------------------------------------------------------- - * Function: H5T_init - * - * Purpose: Initialize the interface from some other package. - * - * Return: Success: non-negative - * Failure: negative - * - * Programmer: Robb Matzke - * Wednesday, December 16, 1998 - * - *------------------------------------------------------------------------- - */ -herr_t -H5T_init(void) -{ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(FAIL) - /* FUNC_ENTER() does all the work */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5T_init() */ - /*------------------------------------------------------------------------- * Function: H5T__init_inf * @@ -746,62 +709,58 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5T__init_inf() */ -/*-------------------------------------------------------------------------- -NAME - H5T__init_package -- Initialize interface-specific information -USAGE - herr__t H5T_init_package() -RETURNS - Non-negative on success/Negative on failure -DESCRIPTION - Initializes any interface-specific data or routines. - ---------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------- + * Function: H5T_init + * + * Purpose: Initialize the interface from some other layer. + * + * Return: Success: non-negative + * Failure: negative + *------------------------------------------------------------------------- + */ herr_t -H5T__init_package(void) +H5T_init(void) { - H5T_t *native_schar = NULL; /* Datatype structure for native signed char */ - H5T_t *native_uchar = NULL; /* Datatype structure for native unsigned char */ - H5T_t *native_short = NULL; /* Datatype structure for native short */ - H5T_t *native_ushort = NULL; /* Datatype structure for native unsigned short */ - H5T_t *native_int = NULL; /* Datatype structure for native int */ - H5T_t *native_uint = NULL; /* Datatype structure for native unsigned int */ - H5T_t *native_long = NULL; /* Datatype structure for native long */ - H5T_t *native_ulong = NULL; /* Datatype structure for native unsigned long */ - H5T_t *native_llong = NULL; /* Datatype structure for native long long */ - H5T_t *native_ullong = NULL; /* Datatype structure for native unsigned long long */ - H5T_t *native_float = NULL; /* Datatype structure for native float */ - H5T_t *native_double = NULL; /* Datatype structure for native double */ -#if H5_SIZEOF_LONG_DOUBLE != 0 - H5T_t *native_ldouble = NULL; /* Datatype structure for native long double */ -#endif - H5T_t * std_u8le = NULL; /* Datatype structure for unsigned 8-bit little-endian integer */ - H5T_t * std_u8be = NULL; /* Datatype structure for unsigned 8-bit big-endian integer */ - H5T_t * std_u16le = NULL; /* Datatype structure for unsigned 16-bit little-endian integer */ - H5T_t * std_u16be = NULL; /* Datatype structure for unsigned 16-bit big-endian integer */ - H5T_t * std_u32le = NULL; /* Datatype structure for unsigned 32-bit little-endian integer */ - H5T_t * std_u32be = NULL; /* Datatype structure for unsigned 32-bit big-endian integer */ - H5T_t * std_u64le = NULL; /* Datatype structure for unsigned 64-bit little-endian integer */ - H5T_t * std_u64be = NULL; /* Datatype structure for unsigned 64-bit big-endian integer */ - H5T_t * dt = NULL; - H5T_t * fixedpt = NULL; /* Datatype structure for native int */ - H5T_t * floatpt = NULL; /* Datatype structure for native float */ - H5T_t * string = NULL; /* Datatype structure for C string */ - H5T_t * bitfield = NULL; /* Datatype structure for bitfield */ - H5T_t * compound = NULL; /* Datatype structure for compound objects */ - H5T_t * enum_type = NULL; /* Datatype structure for enum objects */ - H5T_t * vlen = NULL; /* Datatype structure for vlen objects */ - H5T_t * array = NULL; /* Datatype structure for array objects */ - H5T_t * objref = NULL; /* Datatype structure for deprecated reference objects */ - H5T_t * regref = NULL; /* Datatype structure for deprecated region references */ - H5T_t * ref = NULL; /* Datatype structure for opaque references */ - hsize_t dim[1] = {1}; /* Dimension info for array datatype */ + H5T_t * native_schar = NULL; /* Datatype structure for native signed char */ + H5T_t * native_uchar = NULL; /* Datatype structure for native unsigned char */ + H5T_t * native_short = NULL; /* Datatype structure for native short */ + H5T_t * native_ushort = NULL; /* Datatype structure for native unsigned short */ + H5T_t * native_int = NULL; /* Datatype structure for native int */ + H5T_t * native_uint = NULL; /* Datatype structure for native unsigned int */ + H5T_t * native_long = NULL; /* Datatype structure for native long */ + H5T_t * native_ulong = NULL; /* Datatype structure for native unsigned long */ + H5T_t * native_llong = NULL; /* Datatype structure for native long long */ + H5T_t * native_ullong = NULL; /* Datatype structure for native unsigned long long */ + H5T_t * native_float = NULL; /* Datatype structure for native float */ + H5T_t * native_double = NULL; /* Datatype structure for native double */ + H5T_t * native_ldouble = NULL; /* Datatype structure for native long double */ + H5T_t * std_u8le = NULL; /* Datatype structure for unsigned 8-bit little-endian integer */ + H5T_t * std_u8be = NULL; /* Datatype structure for unsigned 8-bit big-endian integer */ + H5T_t * std_u16le = NULL; /* Datatype structure for unsigned 16-bit little-endian integer */ + H5T_t * std_u16be = NULL; /* Datatype structure for unsigned 16-bit big-endian integer */ + H5T_t * std_u32le = NULL; /* Datatype structure for unsigned 32-bit little-endian integer */ + H5T_t * std_u32be = NULL; /* Datatype structure for unsigned 32-bit big-endian integer */ + H5T_t * std_u64le = NULL; /* Datatype structure for unsigned 64-bit little-endian integer */ + H5T_t * std_u64be = NULL; /* Datatype structure for unsigned 64-bit big-endian integer */ + H5T_t * dt = NULL; + H5T_t * fixedpt = NULL; /* Datatype structure for native int */ + H5T_t * floatpt = NULL; /* Datatype structure for native float */ + H5T_t * string = NULL; /* Datatype structure for C string */ + H5T_t * bitfield = NULL; /* Datatype structure for bitfield */ + H5T_t * compound = NULL; /* Datatype structure for compound objects */ + H5T_t * enum_type = NULL; /* Datatype structure for enum objects */ + H5T_t * vlen = NULL; /* Datatype structure for vlen objects */ + H5T_t * array = NULL; /* Datatype structure for array objects */ + H5T_t * objref = NULL; /* Datatype structure for deprecated reference objects */ + H5T_t * regref = NULL; /* Datatype structure for deprecated region references */ + H5T_t * ref = NULL; /* Datatype structure for opaque references */ + hsize_t dim[1] = {1}; /* Dimension info for array datatype */ herr_t status; hbool_t copied_dtype = TRUE; /* Flag to indicate whether datatype was copied or allocated (for error cleanup) */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_NOAPI(FAIL) /* Initialize the ID group for the file IDs */ if (H5I_register_type(H5I_DATATYPE_CLS) < 0) @@ -843,10 +802,8 @@ H5T__init_package(void) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object") if (NULL == (native_double = (H5T_t *)H5I_object(H5T_NATIVE_DOUBLE_g))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object") -#if H5_SIZEOF_LONG_DOUBLE != 0 if (NULL == (native_ldouble = (H5T_t *)H5I_object(H5T_NATIVE_LDOUBLE_g))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object") -#endif /*------------------------------------------------------------ * Derived native types @@ -1116,7 +1073,6 @@ H5T__init_package(void) H5T__register_int(H5T_PERS_HARD, "flt_dbl", native_float, native_double, H5T__conv_float_double); status |= H5T__register_int(H5T_PERS_HARD, "dbl_flt", native_double, native_float, H5T__conv_double_float); -#if H5_SIZEOF_LONG_DOUBLE != 0 status |= H5T__register_int(H5T_PERS_HARD, "flt_ldbl", native_float, native_ldouble, H5T__conv_float_ldouble); status |= @@ -1125,7 +1081,6 @@ H5T__init_package(void) H5T__register_int(H5T_PERS_HARD, "ldbl_flt", native_ldouble, native_float, H5T__conv_ldouble_float); status |= H5T__register_int(H5T_PERS_HARD, "ldbl_dbl", native_ldouble, native_double, H5T__conv_ldouble_double); -#endif /* H5_SIZEOF_LONG_DOUBLE != 0 */ /* from long long */ status |= @@ -1445,7 +1400,7 @@ H5T__init_package(void) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to register conversion function(s)") /* Register datatype creation property class properties here. See similar - * code in H5D__init_package(), etc. for example. + * code in H5D_init(), etc. for example. */ /* Only register the default property list if it hasn't been created yet */ @@ -1458,9 +1413,6 @@ H5T__init_package(void) HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "can't insert property into class") } /* end if */ - /* Mark "top" of interface as initialized, too */ - H5T_top_package_initialize_s = TRUE; - done: /* General cleanup */ if (compound != NULL) @@ -1488,7 +1440,7 @@ done: } /* end if */ FUNC_LEAVE_NOAPI(ret_value) -} /* end H5T__init_package() */ +} /* end H5T_init() */ /*------------------------------------------------------------------------- * Function: H5T__unlock_cb @@ -1544,185 +1496,177 @@ H5T_top_term_package(void) FUNC_ENTER_NOAPI_NOINIT_NOERR - if (H5T_top_package_initialize_s) { - /* Unregister all conversion functions */ - if (H5T_g.path) { - int i, nprint = 0; - - for (i = 0; i < H5T_g.npaths; i++) { - H5T_path_t *path; - - path = H5T_g.path[i]; - HDassert(path); - if (path->conv.u.app_func) { - H5T__print_stats(path, &nprint /*in,out*/); - path->cdata.command = H5T_CONV_FREE; - if (path->conv.is_app) { - if ((path->conv.u.app_func)((hid_t)FAIL, (hid_t)FAIL, &(path->cdata), (size_t)0, - (size_t)0, (size_t)0, NULL, NULL, H5CX_get_dxpl()) < 0) { + /* Unregister all conversion functions */ + if (H5T_g.path) { + int i, nprint = 0; + + for (i = 0; i < H5T_g.npaths; i++) { + H5T_path_t *path; + + path = H5T_g.path[i]; + HDassert(path); + if (path->conv.u.app_func) { + H5T__print_stats(path, &nprint /*in,out*/); + path->cdata.command = H5T_CONV_FREE; + if (path->conv.is_app) { + if ((path->conv.u.app_func)((hid_t)FAIL, (hid_t)FAIL, &(path->cdata), (size_t)0, + (size_t)0, (size_t)0, NULL, NULL, H5CX_get_dxpl()) < 0) { #ifdef H5T_DEBUG - if (H5DEBUG(T)) { - HDfprintf(H5DEBUG(T), - "H5T: conversion function " - "0x%08lx failed to free private data for " - "%s (ignored)\n", - (unsigned long)(path->conv.u.app_func), path->name); - } /* end if */ + if (H5DEBUG(T)) { + HDfprintf(H5DEBUG(T), + "H5T: conversion function " + "0x%08lx failed to free private data for " + "%s (ignored)\n", + (unsigned long)(path->conv.u.app_func), path->name); + } /* end if */ #endif - H5E_clear_stack(NULL); /*ignore the error*/ - } /* end if */ - } /* end if */ - else { - if ((path->conv.u.lib_func)((hid_t)FAIL, (hid_t)FAIL, &(path->cdata), (size_t)0, - (size_t)0, (size_t)0, NULL, NULL) < 0) { + H5E_clear_stack(NULL); /*ignore the error*/ + } /* end if */ + } /* end if */ + else { + if ((path->conv.u.lib_func)((hid_t)FAIL, (hid_t)FAIL, &(path->cdata), (size_t)0, + (size_t)0, (size_t)0, NULL, NULL) < 0) { #ifdef H5T_DEBUG - if (H5DEBUG(T)) { - HDfprintf(H5DEBUG(T), - "H5T: conversion function " - "0x%08lx failed to free private data for " - "%s (ignored)\n", - (unsigned long)(path->conv.u.lib_func), path->name); - } /* end if */ + if (H5DEBUG(T)) { + HDfprintf(H5DEBUG(T), + "H5T: conversion function " + "0x%08lx failed to free private data for " + "%s (ignored)\n", + (unsigned long)(path->conv.u.lib_func), path->name); + } /* end if */ #endif - H5E_clear_stack(NULL); /*ignore the error*/ - } /* end if */ - } /* end else */ - } /* end if */ - - if (path->src) - (void)H5T_close_real(path->src); - if (path->dst) - (void)H5T_close_real(path->dst); - path = H5FL_FREE(H5T_path_t, path); - H5T_g.path[i] = NULL; - } /* end for */ - - /* Clear conversion tables */ - H5T_g.path = (H5T_path_t **)H5MM_xfree(H5T_g.path); - H5T_g.npaths = 0; - H5T_g.apaths = 0; - H5T_g.soft = (H5T_soft_t *)H5MM_xfree(H5T_g.soft); - H5T_g.nsoft = 0; - H5T_g.asoft = 0; + H5E_clear_stack(NULL); /*ignore the error*/ + } /* end if */ + } /* end else */ + } /* end if */ + + if (path->src) + (void)H5T_close_real(path->src); + if (path->dst) + (void)H5T_close_real(path->dst); + path = H5FL_FREE(H5T_path_t, path); + H5T_g.path[i] = NULL; + } /* end for */ - n++; - } /* end if */ + /* Clear conversion tables */ + H5T_g.path = (H5T_path_t **)H5MM_xfree(H5T_g.path); + H5T_g.npaths = 0; + H5T_g.apaths = 0; + H5T_g.soft = (H5T_soft_t *)H5MM_xfree(H5T_g.soft); + H5T_g.nsoft = 0; + H5T_g.asoft = 0; - /* Unlock all datatypes, then free them */ - /* note that we are ignoring the return value from H5I_iterate() */ - /* Also note that we are incrementing 'n' in the callback */ - H5I_iterate(H5I_DATATYPE, H5T__unlock_cb, &n, FALSE); - - /* Release all datatype IDs */ - if (H5I_nmembers(H5I_DATATYPE) > 0) { - (void)H5I_clear_type(H5I_DATATYPE, FALSE, FALSE); - n++; /*H5I*/ - } /* end if */ - - /* Reset all the datatype IDs */ - if (H5T_IEEE_F32BE_g > 0) { - H5T_IEEE_F32BE_g = FAIL; - H5T_IEEE_F32LE_g = FAIL; - H5T_IEEE_F64BE_g = FAIL; - H5T_IEEE_F64LE_g = FAIL; - - H5T_STD_I8BE_g = FAIL; - H5T_STD_I8LE_g = FAIL; - H5T_STD_I16BE_g = FAIL; - H5T_STD_I16LE_g = FAIL; - H5T_STD_I32BE_g = FAIL; - H5T_STD_I32LE_g = FAIL; - H5T_STD_I64BE_g = FAIL; - H5T_STD_I64LE_g = FAIL; - H5T_STD_U8BE_g = FAIL; - H5T_STD_U8LE_g = FAIL; - H5T_STD_U16BE_g = FAIL; - H5T_STD_U16LE_g = FAIL; - H5T_STD_U32BE_g = FAIL; - H5T_STD_U32LE_g = FAIL; - H5T_STD_U64BE_g = FAIL; - H5T_STD_U64LE_g = FAIL; - H5T_STD_B8BE_g = FAIL; - H5T_STD_B8LE_g = FAIL; - H5T_STD_B16BE_g = FAIL; - H5T_STD_B16LE_g = FAIL; - H5T_STD_B32BE_g = FAIL; - H5T_STD_B32LE_g = FAIL; - H5T_STD_B64BE_g = FAIL; - H5T_STD_B64LE_g = FAIL; - H5T_STD_REF_OBJ_g = FAIL; - H5T_STD_REF_DSETREG_g = FAIL; - H5T_STD_REF_g = FAIL; - - H5T_UNIX_D32BE_g = FAIL; - H5T_UNIX_D32LE_g = FAIL; - H5T_UNIX_D64BE_g = FAIL; - H5T_UNIX_D64LE_g = FAIL; - - H5T_C_S1_g = FAIL; - - H5T_FORTRAN_S1_g = FAIL; - - H5T_NATIVE_SCHAR_g = FAIL; - H5T_NATIVE_UCHAR_g = FAIL; - H5T_NATIVE_SHORT_g = FAIL; - H5T_NATIVE_USHORT_g = FAIL; - H5T_NATIVE_INT_g = FAIL; - H5T_NATIVE_UINT_g = FAIL; - H5T_NATIVE_LONG_g = FAIL; - H5T_NATIVE_ULONG_g = FAIL; - H5T_NATIVE_LLONG_g = FAIL; - H5T_NATIVE_ULLONG_g = FAIL; - H5T_NATIVE_FLOAT_g = FAIL; - H5T_NATIVE_DOUBLE_g = FAIL; -#if H5_SIZEOF_LONG_DOUBLE != 0 - H5T_NATIVE_LDOUBLE_g = FAIL; -#endif - H5T_NATIVE_B8_g = FAIL; - H5T_NATIVE_B16_g = FAIL; - H5T_NATIVE_B32_g = FAIL; - H5T_NATIVE_B64_g = FAIL; - H5T_NATIVE_OPAQUE_g = FAIL; - H5T_NATIVE_HADDR_g = FAIL; - H5T_NATIVE_HSIZE_g = FAIL; - H5T_NATIVE_HSSIZE_g = FAIL; - H5T_NATIVE_HERR_g = FAIL; - H5T_NATIVE_HBOOL_g = FAIL; - - H5T_NATIVE_INT8_g = FAIL; - H5T_NATIVE_UINT8_g = FAIL; - H5T_NATIVE_INT_LEAST8_g = FAIL; - H5T_NATIVE_UINT_LEAST8_g = FAIL; - H5T_NATIVE_INT_FAST8_g = FAIL; - H5T_NATIVE_UINT_FAST8_g = FAIL; - - H5T_NATIVE_INT16_g = FAIL; - H5T_NATIVE_UINT16_g = FAIL; - H5T_NATIVE_INT_LEAST16_g = FAIL; - H5T_NATIVE_UINT_LEAST16_g = FAIL; - H5T_NATIVE_INT_FAST16_g = FAIL; - H5T_NATIVE_UINT_FAST16_g = FAIL; - - H5T_NATIVE_INT32_g = FAIL; - H5T_NATIVE_UINT32_g = FAIL; - H5T_NATIVE_INT_LEAST32_g = FAIL; - H5T_NATIVE_UINT_LEAST32_g = FAIL; - H5T_NATIVE_INT_FAST32_g = FAIL; - H5T_NATIVE_UINT_FAST32_g = FAIL; - - H5T_NATIVE_INT64_g = FAIL; - H5T_NATIVE_UINT64_g = FAIL; - H5T_NATIVE_INT_LEAST64_g = FAIL; - H5T_NATIVE_UINT_LEAST64_g = FAIL; - H5T_NATIVE_INT_FAST64_g = FAIL; - H5T_NATIVE_UINT_FAST64_g = FAIL; - - n++; - } /* end if */ + n++; + } /* end if */ - /* Mark "top" of interface as closed */ - if (0 == n) - H5T_top_package_initialize_s = FALSE; + /* Unlock all datatypes, then free them */ + /* note that we are ignoring the return value from H5I_iterate() */ + /* Also note that we are incrementing 'n' in the callback */ + H5I_iterate(H5I_DATATYPE, H5T__unlock_cb, &n, FALSE); + + /* Release all datatype IDs */ + if (H5I_nmembers(H5I_DATATYPE) > 0) { + (void)H5I_clear_type(H5I_DATATYPE, FALSE, FALSE); + n++; /*H5I*/ + } /* end if */ + + /* Reset all the datatype IDs */ + if (H5T_IEEE_F32BE_g > 0) { + H5T_IEEE_F32BE_g = FAIL; + H5T_IEEE_F32LE_g = FAIL; + H5T_IEEE_F64BE_g = FAIL; + H5T_IEEE_F64LE_g = FAIL; + + H5T_STD_I8BE_g = FAIL; + H5T_STD_I8LE_g = FAIL; + H5T_STD_I16BE_g = FAIL; + H5T_STD_I16LE_g = FAIL; + H5T_STD_I32BE_g = FAIL; + H5T_STD_I32LE_g = FAIL; + H5T_STD_I64BE_g = FAIL; + H5T_STD_I64LE_g = FAIL; + H5T_STD_U8BE_g = FAIL; + H5T_STD_U8LE_g = FAIL; + H5T_STD_U16BE_g = FAIL; + H5T_STD_U16LE_g = FAIL; + H5T_STD_U32BE_g = FAIL; + H5T_STD_U32LE_g = FAIL; + H5T_STD_U64BE_g = FAIL; + H5T_STD_U64LE_g = FAIL; + H5T_STD_B8BE_g = FAIL; + H5T_STD_B8LE_g = FAIL; + H5T_STD_B16BE_g = FAIL; + H5T_STD_B16LE_g = FAIL; + H5T_STD_B32BE_g = FAIL; + H5T_STD_B32LE_g = FAIL; + H5T_STD_B64BE_g = FAIL; + H5T_STD_B64LE_g = FAIL; + H5T_STD_REF_OBJ_g = FAIL; + H5T_STD_REF_DSETREG_g = FAIL; + H5T_STD_REF_g = FAIL; + + H5T_UNIX_D32BE_g = FAIL; + H5T_UNIX_D32LE_g = FAIL; + H5T_UNIX_D64BE_g = FAIL; + H5T_UNIX_D64LE_g = FAIL; + + H5T_C_S1_g = FAIL; + + H5T_FORTRAN_S1_g = FAIL; + + H5T_NATIVE_SCHAR_g = FAIL; + H5T_NATIVE_UCHAR_g = FAIL; + H5T_NATIVE_SHORT_g = FAIL; + H5T_NATIVE_USHORT_g = FAIL; + H5T_NATIVE_INT_g = FAIL; + H5T_NATIVE_UINT_g = FAIL; + H5T_NATIVE_LONG_g = FAIL; + H5T_NATIVE_ULONG_g = FAIL; + H5T_NATIVE_LLONG_g = FAIL; + H5T_NATIVE_ULLONG_g = FAIL; + H5T_NATIVE_FLOAT_g = FAIL; + H5T_NATIVE_DOUBLE_g = FAIL; + H5T_NATIVE_LDOUBLE_g = FAIL; + H5T_NATIVE_B8_g = FAIL; + H5T_NATIVE_B16_g = FAIL; + H5T_NATIVE_B32_g = FAIL; + H5T_NATIVE_B64_g = FAIL; + H5T_NATIVE_OPAQUE_g = FAIL; + H5T_NATIVE_HADDR_g = FAIL; + H5T_NATIVE_HSIZE_g = FAIL; + H5T_NATIVE_HSSIZE_g = FAIL; + H5T_NATIVE_HERR_g = FAIL; + H5T_NATIVE_HBOOL_g = FAIL; + + H5T_NATIVE_INT8_g = FAIL; + H5T_NATIVE_UINT8_g = FAIL; + H5T_NATIVE_INT_LEAST8_g = FAIL; + H5T_NATIVE_UINT_LEAST8_g = FAIL; + H5T_NATIVE_INT_FAST8_g = FAIL; + H5T_NATIVE_UINT_FAST8_g = FAIL; + + H5T_NATIVE_INT16_g = FAIL; + H5T_NATIVE_UINT16_g = FAIL; + H5T_NATIVE_INT_LEAST16_g = FAIL; + H5T_NATIVE_UINT_LEAST16_g = FAIL; + H5T_NATIVE_INT_FAST16_g = FAIL; + H5T_NATIVE_UINT_FAST16_g = FAIL; + + H5T_NATIVE_INT32_g = FAIL; + H5T_NATIVE_UINT32_g = FAIL; + H5T_NATIVE_INT_LEAST32_g = FAIL; + H5T_NATIVE_UINT_LEAST32_g = FAIL; + H5T_NATIVE_INT_FAST32_g = FAIL; + H5T_NATIVE_UINT_FAST32_g = FAIL; + + H5T_NATIVE_INT64_g = FAIL; + H5T_NATIVE_UINT64_g = FAIL; + H5T_NATIVE_INT_LEAST64_g = FAIL; + H5T_NATIVE_UINT_LEAST64_g = FAIL; + H5T_NATIVE_INT_FAST64_g = FAIL; + H5T_NATIVE_UINT_FAST64_g = FAIL; + + n++; } /* end if */ FUNC_LEAVE_NOAPI(n) @@ -1753,18 +1697,11 @@ H5T_term_package(void) FUNC_ENTER_NOAPI_NOINIT_NOERR - if (H5_PKG_INIT_VAR) { - /* Sanity check */ - HDassert(0 == H5I_nmembers(H5I_DATATYPE)); - HDassert(FALSE == H5T_top_package_initialize_s); - - /* Destroy the datatype object id group */ - n += (H5I_dec_type_ref(H5I_DATATYPE) > 0); + /* Sanity check */ + HDassert(0 == H5I_nmembers(H5I_DATATYPE)); - /* Mark interface as closed */ - if (0 == n) - H5_PKG_INIT_VAR = FALSE; - } /* end if */ + /* Destroy the datatype object id group */ + n += (H5I_dec_type_ref(H5I_DATATYPE) > 0); FUNC_LEAVE_NOAPI(n) } /* end H5T_term_package() */ @@ -2184,7 +2121,7 @@ H5T_get_class(const H5T_t *dt, htri_t internal) { H5T_class_t ret_value = H5T_NO_CLASS; /* Return value */ - FUNC_ENTER_NOAPI(H5T_NO_CLASS) + FUNC_ENTER_NOAPI_NOERR HDassert(dt); @@ -2199,7 +2136,6 @@ H5T_get_class(const H5T_t *dt, htri_t internal) ret_value = dt->shared->type; } -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5T_get_class() */ @@ -2257,7 +2193,7 @@ H5T_detect_class(const H5T_t *dt, H5T_class_t cls, hbool_t from_api) unsigned i; htri_t ret_value = FALSE; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR HDassert(dt); HDassert(cls > H5T_NO_CLASS && cls < H5T_NCLASSES); @@ -4290,7 +4226,7 @@ done: * * Return: Success: non-negative * - * Failure: nagative + * Failure: negative * * Programmer: Robb Matzke * Tuesday, December 22, 1998 @@ -5640,14 +5576,13 @@ H5T_is_immutable(const H5T_t *dt) { htri_t ret_value = FALSE; - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR HDassert(dt); if (dt->shared->state == H5T_STATE_IMMUTABLE) ret_value = TRUE; -done: FUNC_LEAVE_NOAPI(ret_value) } @@ -5665,7 +5600,7 @@ H5T_is_named(const H5T_t *dt) { htri_t ret_value = FALSE; - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR HDassert(dt); @@ -5674,7 +5609,6 @@ H5T_is_named(const H5T_t *dt) else ret_value = (H5T_STATE_OPEN == dt->shared->state || H5T_STATE_NAMED == dt->shared->state); -done: FUNC_LEAVE_NOAPI(ret_value) } @@ -5752,14 +5686,13 @@ H5T_get_ref_type(const H5T_t *dt) { H5R_type_t ret_value = H5R_BADTYPE; - FUNC_ENTER_NOAPI(H5R_BADTYPE) + FUNC_ENTER_NOAPI_NOERR HDassert(dt); if (dt->shared->type == H5T_REFERENCE) ret_value = dt->shared->u.atomic.u.r.rtype; -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5T_get_ref_type() */ @@ -5782,7 +5715,7 @@ H5T_is_sensible(const H5T_t *dt) { htri_t ret_value = FAIL; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR HDassert(dt); @@ -5820,7 +5753,6 @@ H5T_is_sensible(const H5T_t *dt) break; } /* end switch */ -done: FUNC_LEAVE_NOAPI(ret_value) } @@ -6013,7 +5945,7 @@ H5T_is_relocatable(const H5T_t *dt) { htri_t ret_value = FALSE; - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR /* Sanity check */ HDassert(dt); @@ -6022,7 +5954,6 @@ H5T_is_relocatable(const H5T_t *dt) if (H5T_detect_class(dt, H5T_VLEN, FALSE) || H5T_detect_class(dt, H5T_REFERENCE, FALSE)) ret_value = TRUE; -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5T_is_relocatable() */ @@ -6113,7 +6044,7 @@ H5T_is_vl_storage(const H5T_t *dt) { htri_t ret_value = FALSE; - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR /* Sanity check */ HDassert(dt); @@ -6126,7 +6057,6 @@ H5T_is_vl_storage(const H5T_t *dt) else ret_value = FALSE; -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5T_is_vl_storage() */ @@ -6280,7 +6210,7 @@ H5T_patch_file(H5T_t *dt, H5F_t *f) { herr_t ret_value = SUCCEED; - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR /* Sanity check */ HDassert(dt); @@ -6291,7 +6221,6 @@ H5T_patch_file(H5T_t *dt, H5F_t *f) dt->sh_loc.file = f; } /* end if */ -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5T_patch_file() */ @@ -43,7 +43,7 @@ /* Local Typedefs */ /******************/ -/* Cancelability structure */ +/* Cancellability structure */ typedef struct H5TS_cancel_struct { int previous_state; unsigned int cancel_count; @@ -192,10 +192,10 @@ H5TS_tid_destructor(void *_v) return; /* TBD use an atomic CAS */ - HDpthread_mutex_lock(&H5TS_tid_mtx); + pthread_mutex_lock(&H5TS_tid_mtx); tid->next = H5TS_tid_next_free; H5TS_tid_next_free = tid; - HDpthread_mutex_unlock(&H5TS_tid_mtx); + pthread_mutex_unlock(&H5TS_tid_mtx); } /*-------------------------------------------------------------------------- @@ -215,8 +215,8 @@ H5TS_tid_destructor(void *_v) static void H5TS_tid_init(void) { - HDpthread_mutex_init(&H5TS_tid_mtx, NULL); - HDpthread_key_create(&H5TS_tid_key, H5TS_tid_destructor); + pthread_mutex_init(&H5TS_tid_mtx, NULL); + pthread_key_create(&H5TS_tid_key, H5TS_tid_destructor); } /*-------------------------------------------------------------------------- @@ -246,7 +246,7 @@ H5TS_tid_init(void) uint64_t H5TS_thread_id(void) { - H5TS_tid_t *tid = HDpthread_getspecific(H5TS_tid_key); + H5TS_tid_t *tid = pthread_getspecific(H5TS_tid_key); H5TS_tid_t proto_tid; /* An ID is already assigned. */ @@ -260,14 +260,14 @@ H5TS_thread_id(void) * point `tid` at `proto_tid` if we need to allocate some * memory. */ - HDpthread_mutex_lock(&H5TS_tid_mtx); + pthread_mutex_lock(&H5TS_tid_mtx); if ((tid = H5TS_tid_next_free) != NULL) H5TS_tid_next_free = tid->next; else if (H5TS_tid_next_id != UINT64_MAX) { tid = &proto_tid; tid->id = ++H5TS_tid_next_id; } - HDpthread_mutex_unlock(&H5TS_tid_mtx); + pthread_mutex_unlock(&H5TS_tid_mtx); /* If a prototype ID record was established, copy it to the heap. */ if (tid == &proto_tid) @@ -281,7 +281,7 @@ H5TS_thread_id(void) * to it. */ tid->next = NULL; - if (HDpthread_setspecific(H5TS_tid_key, tid) != 0) { + if (pthread_setspecific(H5TS_tid_key, tid) != 0) { H5TS_tid_destructor(tid); return 0; } @@ -323,29 +323,29 @@ H5TS_pthread_first_thread_init(void) #endif /* initialize global API mutex lock */ - HDpthread_mutex_init(&H5_g.init_lock.atomic_lock, NULL); - HDpthread_cond_init(&H5_g.init_lock.cond_var, NULL); + pthread_mutex_init(&H5_g.init_lock.atomic_lock, NULL); + pthread_cond_init(&H5_g.init_lock.cond_var, NULL); H5_g.init_lock.lock_count = 0; - HDpthread_mutex_init(&H5_g.init_lock.atomic_lock2, NULL); + pthread_mutex_init(&H5_g.init_lock.atomic_lock2, NULL); H5_g.init_lock.attempt_lock_count = 0; /* Initialize integer thread identifiers. */ H5TS_tid_init(); /* initialize key for thread-specific error stacks */ - HDpthread_key_create(&H5TS_errstk_key_g, H5TS__key_destructor); + pthread_key_create(&H5TS_errstk_key_g, H5TS__key_destructor); #ifdef H5_HAVE_CODESTACK /* initialize key for thread-specific function stacks */ - HDpthread_key_create(&H5TS_funcstk_key_g, H5TS__key_destructor); + pthread_key_create(&H5TS_funcstk_key_g, H5TS__key_destructor); #endif /* H5_HAVE_CODESTACK */ /* initialize key for thread-specific API contexts */ - HDpthread_key_create(&H5TS_apictx_key_g, H5TS__key_destructor); + pthread_key_create(&H5TS_apictx_key_g, H5TS__key_destructor); /* initialize key for thread cancellability mechanism */ - HDpthread_key_create(&H5TS_cancel_key_s, H5TS__key_destructor); + pthread_key_create(&H5TS_cancel_key_s, H5TS__key_destructor); FUNC_LEAVE_NOAPI_VOID_NAMECHECK_ONLY } /* end H5TS_pthread_first_thread_init() */ @@ -380,13 +380,13 @@ H5TS__mutex_acquire(H5TS_mutex_t *mutex, unsigned int lock_count, hbool_t *acqui *acquired = TRUE; #else /* H5_HAVE_WIN_THREADS */ /* Attempt to acquire the mutex lock */ - if (0 == HDpthread_mutex_lock(&mutex->atomic_lock)) { - pthread_t my_thread_id = HDpthread_self(); + if (0 == pthread_mutex_lock(&mutex->atomic_lock)) { + pthread_t my_thread_id = pthread_self(); /* Check if locked already */ if (mutex->lock_count) { /* Check for this thread already owning the lock */ - if (HDpthread_equal(my_thread_id, mutex->owner_thread)) { + if (pthread_equal(my_thread_id, mutex->owner_thread)) { /* Already owned by self - increment count */ mutex->lock_count += lock_count; *acquired = TRUE; @@ -401,7 +401,7 @@ H5TS__mutex_acquire(H5TS_mutex_t *mutex, unsigned int lock_count, hbool_t *acqui *acquired = TRUE; } /* end else */ - if (0 != HDpthread_mutex_unlock(&mutex->atomic_lock)) + if (0 != pthread_mutex_unlock(&mutex->atomic_lock)) ret_value = -1; } /* end if */ else @@ -463,35 +463,35 @@ herr_t H5TS_mutex_lock(H5TS_mutex_t *mutex) EnterCriticalSection(&mutex->CriticalSection); #else /* H5_HAVE_WIN_THREADS */ /* Acquire the "attempt" lock, increment the attempt lock count, release the lock */ - ret_value = HDpthread_mutex_lock(&mutex->atomic_lock2); + ret_value = pthread_mutex_lock(&mutex->atomic_lock2); if (ret_value) HGOTO_DONE(ret_value); mutex->attempt_lock_count++; - ret_value = HDpthread_mutex_unlock(&mutex->atomic_lock2); + ret_value = pthread_mutex_unlock(&mutex->atomic_lock2); if (ret_value) HGOTO_DONE(ret_value); /* Acquire the library lock */ - ret_value = HDpthread_mutex_lock(&mutex->atomic_lock); + ret_value = pthread_mutex_lock(&mutex->atomic_lock); if (ret_value) HGOTO_DONE(ret_value); /* Check if this thread already owns the lock */ - if (mutex->lock_count && HDpthread_equal(HDpthread_self(), mutex->owner_thread)) + if (mutex->lock_count && pthread_equal(pthread_self(), mutex->owner_thread)) /* already owned by self - increment count */ mutex->lock_count++; else { /* Wait until the lock is released by current owner thread */ while (mutex->lock_count) - HDpthread_cond_wait(&mutex->cond_var, &mutex->atomic_lock); + pthread_cond_wait(&mutex->cond_var, &mutex->atomic_lock); /* After we've received the signal, take ownership of the mutex */ - mutex->owner_thread = HDpthread_self(); + mutex->owner_thread = pthread_self(); mutex->lock_count = 1; } /* end else */ /* Release the library lock */ - ret_value = HDpthread_mutex_unlock(&mutex->atomic_lock); + ret_value = pthread_mutex_unlock(&mutex->atomic_lock); done: #endif /* H5_HAVE_WIN_THREADS */ @@ -530,12 +530,12 @@ H5TS__mutex_unlock(H5TS_mutex_t *mutex, unsigned int *lock_count) #else /* H5_HAVE_WIN_THREADS */ /* Reset the lock count for this thread */ - ret_value = HDpthread_mutex_lock(&mutex->atomic_lock); + ret_value = pthread_mutex_lock(&mutex->atomic_lock); if (ret_value) HGOTO_DONE(ret_value); *lock_count = mutex->lock_count; mutex->lock_count = 0; - ret_value = HDpthread_mutex_unlock(&mutex->atomic_lock); + ret_value = pthread_mutex_unlock(&mutex->atomic_lock); /* If the lock count drops to zero, signal the condition variable, to * wake another thread. @@ -543,7 +543,7 @@ H5TS__mutex_unlock(H5TS_mutex_t *mutex, unsigned int *lock_count) if (mutex->lock_count == 0) { int err; - err = HDpthread_cond_signal(&mutex->cond_var); + err = pthread_cond_signal(&mutex->cond_var); if (err != 0) ret_value = err; } /* end if */ @@ -586,11 +586,11 @@ H5TS_mutex_unlock(H5TS_mutex_t *mutex) #else /* H5_HAVE_WIN_THREADS */ /* Decrement the lock count for this thread */ - ret_value = HDpthread_mutex_lock(&mutex->atomic_lock); + ret_value = pthread_mutex_lock(&mutex->atomic_lock); if (ret_value) HGOTO_DONE(ret_value); mutex->lock_count--; - ret_value = HDpthread_mutex_unlock(&mutex->atomic_lock); + ret_value = pthread_mutex_unlock(&mutex->atomic_lock); /* If the lock count drops to zero, signal the condition variable, to * wake another thread. @@ -598,7 +598,7 @@ H5TS_mutex_unlock(H5TS_mutex_t *mutex) if (mutex->lock_count == 0) { int err; - err = HDpthread_cond_signal(&mutex->cond_var); + err = pthread_cond_signal(&mutex->cond_var); if (err != 0) ret_value = err; } /* end if */ @@ -630,13 +630,13 @@ H5TSmutex_get_attempt_count(unsigned int *count) #ifdef H5_HAVE_WIN_THREADS /* Add Win32 equivalent here when async is supported */ #else /* H5_HAVE_WIN_THREADS */ - ret_value = HDpthread_mutex_lock(&H5_g.init_lock.atomic_lock2); + ret_value = pthread_mutex_lock(&H5_g.init_lock.atomic_lock2); if (ret_value) HGOTO_DONE(ret_value); *count = H5_g.init_lock.attempt_lock_count; - ret_value = HDpthread_mutex_unlock(&H5_g.init_lock.atomic_lock2); + ret_value = pthread_mutex_unlock(&H5_g.init_lock.atomic_lock2); if (ret_value) HGOTO_DONE(ret_value); @@ -685,9 +685,9 @@ H5TSmutex_release(unsigned int *lock_count) * Creates a cancellation counter for a thread if it is the first time * the thread is entering the library. * - * if counter value is zero, then set cancelability type of the thread + * if counter value is zero, then set cancellability type of the thread * to PTHREAD_CANCEL_DISABLE as thread is entering the library and store - * the previous cancelability type into cancellation counter. + * the previous cancellability type into cancellation counter. * Increase the counter value by 1. * * PROGRAMMER: Chee Wai LEE @@ -725,7 +725,7 @@ H5TS_cancel_count_inc(void) HGOTO_DONE(FAIL); /* Set the thread's cancellation counter with the new object */ - ret_value = HDpthread_setspecific(H5TS_cancel_key_s, (void *)cancel_counter); + ret_value = pthread_setspecific(H5TS_cancel_key_s, (void *)cancel_counter); if (ret_value) { HDfree(cancel_counter); HGOTO_DONE(FAIL); @@ -735,7 +735,7 @@ H5TS_cancel_count_inc(void) /* Check if thread entering library */ if (cancel_counter->cancel_count == 0) /* Set cancellation state to 'disable', and remember previous state */ - ret_value = HDpthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancel_counter->previous_state); + ret_value = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancel_counter->previous_state); /* Increment # of times the library API was re-entered, to avoid resetting * previous cancellation state until the final API routine is returning. @@ -758,8 +758,8 @@ done: * 0 on success and a non-zero error code on error. * * DESCRIPTION - * If counter value is one, then set cancelability type of the thread - * to the previous cancelability type stored in the cancellation counter. + * If counter value is one, then set cancellability type of the thread + * to the previous cancellability type stored in the cancellation counter. * (the thread is leaving the library). * * Decrement the counter value by 1. @@ -788,7 +788,7 @@ H5TS_cancel_count_dec(void) /* Check for leaving last API routine */ if (cancel_counter->cancel_count == 1) /* Reset to previous thread cancellation state, if last API */ - ret_value = HDpthread_setcancelstate(cancel_counter->previous_state, NULL); + ret_value = pthread_setcancelstate(cancel_counter->previous_state, NULL); /* Decrement cancellation counter */ --cancel_counter->cancel_count; @@ -995,7 +995,7 @@ H5TS_create_thread(H5TS_thread_cb_t func, H5TS_attr_t *attr, void *udata) #else /* H5_HAVE_WIN_THREADS */ - HDpthread_create(&ret_value, attr, (void *(*)(void *))func, udata); + pthread_create(&ret_value, attr, (void *(*)(void *))func, udata); #endif /* H5_HAVE_WIN_THREADS */ diff --git a/src/H5TSprivate.h b/src/H5TSprivate.h index 3150f59..5d69854 100644 --- a/src/H5TSprivate.h +++ b/src/H5TSprivate.h @@ -13,11 +13,9 @@ /*------------------------------------------------------------------------- * - * Created: H5TSprivate.h - * May 2 2000 - * Chee Wai LEE + * Created: H5TSprivate.h * - * Purpose: Private non-prototype header. + * Purpose: Thread-safety abstractions used by the library * *------------------------------------------------------------------------- */ diff --git a/src/H5Tbit.c b/src/H5Tbit.c index 04e2a97..20f3855 100644 --- a/src/H5Tbit.c +++ b/src/H5Tbit.c @@ -228,7 +228,7 @@ done: * Purpose: Return a small bit sequence as a number. Bit vector starts * at OFFSET and is SIZE bits long. * - * Return: The bit sequence interpretted as an unsigned integer + * Return: The bit sequence interpreted as an unsigned integer * *------------------------------------------------------------------------- */ @@ -538,7 +538,7 @@ H5T__bit_inc(uint8_t *buf, size_t start, size_t size) /*------------------------------------------------------------------------- * Function: H5T__bit_dec * - * Purpose: Decrement part of a bit field by substracting 1. The bit + * Purpose: Decrement part of a bit field by subtracting 1. The bit * field starts with bit position START and is SIZE bits long. * * Return: The "borrow-in" value. It's TRUE if underflows, FALSE @@ -564,9 +564,9 @@ H5T__bit_dec(uint8_t *buf, size_t start, size_t size) if ((size + start - 1) / 8 > idx) { /* The bit sequence doesn't end in the same byte as starts */ - /* Example: a sequence like 11000100 and start = 3. We substract 00001000 from + /* Example: a sequence like 11000100 and start = 3. We subtract 00001000 from * it and get 10111100. If a sequence is 00000111, we do right shift for START - * bits and get 00000000. So we need to borrow from higher byte when we substract + * bits and get 00000000. So we need to borrow from higher byte when we subtract * 00001000. */ if (!(buf[idx] >> pos)) @@ -597,7 +597,7 @@ H5T__bit_dec(uint8_t *buf, size_t start, size_t size) else { /* The bit sequence ends in the same byte as starts */ - /* Example: a sequence like 11000100 and pos=3, size=3. We substract 00001000 + /* Example: a sequence like 11000100 and pos=3, size=3. We subtract 00001000 * and get 10111100. A bit is borrowed from 6th bit(buf[idx]>>6=00000010, tmp>>6=00000011, * not equal). We need to put this bit back by increment 1000000. */ diff --git a/src/H5Tcommit.c b/src/H5Tcommit.c index d079e71..a3a1aa0 100644 --- a/src/H5Tcommit.c +++ b/src/H5Tcommit.c @@ -1127,7 +1127,7 @@ H5T_open(const H5G_loc_t *loc) done: if (ret_value == NULL) { if (dt) { - if (shared_fo == NULL) { /* Need to free shared fo */ + if (shared_fo == NULL) { /* Need to free shared file object */ if (dt->shared->owned_vol_obj && H5VL_free_object(dt->shared->owned_vol_obj) < 0) HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, NULL, "unable to close owned VOL object") dt->shared = H5FL_FREE(H5T_shared_t, dt->shared); diff --git a/src/H5Tconv.c b/src/H5Tconv.c index 273bb23..5efff10 100644 --- a/src/H5Tconv.c +++ b/src/H5Tconv.c @@ -2753,7 +2753,7 @@ H5T__conv_enum_init(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata) HDassert(domain[1] >= domain[0]); length = (unsigned)(domain[1] - domain[0]) + 1; if (src->shared->u.enumer.nmembs < 2 || - (double)length / src->shared->u.enumer.nmembs < (double)(1.2f)) { + (double)length / src->shared->u.enumer.nmembs < (double)(1.2F)) { priv->base = domain[0]; priv->length = length; if (NULL == (map = (int *)H5MM_malloc(length * sizeof(int)))) @@ -4867,7 +4867,7 @@ H5T__conv_s_s(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, siz size_t olap; /*num overlapping elements */ size_t nchars = 0; /*number of characters copied */ uint8_t *s, *sp, *d, *dp; /*src and dst traversal pointers*/ - uint8_t *dbuf = NULL; /*temp buf for overlap convers. */ + uint8_t *dbuf = NULL; /*temp buf for overlap converts. */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE @@ -7009,14 +7009,12 @@ H5T__conv_float_double(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t ne * *------------------------------------------------------------------------- */ -#if H5_SIZEOF_LONG_DOUBLE != 0 herr_t H5T__conv_float_ldouble(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg) { H5T_CONV_fF(FLOAT, LDOUBLE, float, long double, -, -); } -#endif /* H5_SIZEOF_LONG_DOUBLE != 0 */ /*------------------------------------------------------------------------- * Function: H5T__conv_double_float @@ -7051,14 +7049,12 @@ H5T__conv_double_float(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t ne * *------------------------------------------------------------------------- */ -#if H5_SIZEOF_LONG_DOUBLE != 0 herr_t H5T__conv_double_ldouble(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg) { H5T_CONV_fF(DOUBLE, LDOUBLE, double, long double, -, -); } -#endif /* H5_SIZEOF_LONG_DOUBLE != 0 */ /*------------------------------------------------------------------------- * Function: H5T__conv_ldouble_float @@ -7073,14 +7069,12 @@ H5T__conv_double_ldouble(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t * *------------------------------------------------------------------------- */ -#if H5_SIZEOF_LONG_DOUBLE != 0 herr_t H5T__conv_ldouble_float(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg) { H5T_CONV_Ff(LDOUBLE, FLOAT, long double, float, -FLT_MAX, FLT_MAX); } -#endif /* H5_SIZEOF_LONG_DOUBLE != 0 */ /*------------------------------------------------------------------------- * Function: H5T__conv_ldouble_double @@ -7095,14 +7089,12 @@ H5T__conv_ldouble_float(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t n * *------------------------------------------------------------------------- */ -#if H5_SIZEOF_LONG_DOUBLE != 0 herr_t H5T__conv_ldouble_double(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg) { H5T_CONV_Ff(LDOUBLE, DOUBLE, long double, double, -DBL_MAX, DBL_MAX); } -#endif /* H5_SIZEOF_LONG_DOUBLE != 0 */ /*------------------------------------------------------------------------- * Function: H5T__conv_schar_float @@ -7153,7 +7145,7 @@ H5T__conv_schar_double(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t ne * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu - * Tuesday, Febuary 1, 2005 + * Tuesday, February 1, 2005 * *------------------------------------------------------------------------- */ @@ -7213,7 +7205,7 @@ H5T__conv_uchar_double(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t ne * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu - * Tuesday, Febuary 1, 2005 + * Tuesday, February 1, 2005 * *------------------------------------------------------------------------- */ @@ -7273,7 +7265,7 @@ H5T__conv_short_double(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t ne * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu - * Tuesday, Febuary 1, 2005 + * Tuesday, February 1, 2005 * *------------------------------------------------------------------------- */ @@ -7333,7 +7325,7 @@ H5T__conv_ushort_double(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t n * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu - * Tuesday, Febuary 1, 2005 + * Tuesday, February 1, 2005 * *------------------------------------------------------------------------- */ @@ -7393,7 +7385,7 @@ H5T__conv_int_double(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelm * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu - * Tuesday, Febuary 1, 2005 + * Tuesday, February 1, 2005 * *------------------------------------------------------------------------- */ @@ -7453,7 +7445,7 @@ H5T__conv_uint_double(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nel * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu - * Tuesday, Febuary 1, 2005 + * Tuesday, February 1, 2005 * *------------------------------------------------------------------------- */ @@ -7513,7 +7505,7 @@ H5T__conv_long_double(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nel * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu - * Tuesday, Febuary 1, 2005 + * Tuesday, February 1, 2005 * *------------------------------------------------------------------------- */ @@ -7573,7 +7565,7 @@ H5T__conv_ulong_double(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t ne * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu - * Tuesday, Febuary 1, 2005 + * Tuesday, February 1, 2005 * *------------------------------------------------------------------------- */ @@ -7633,7 +7625,7 @@ H5T__conv_llong_double(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t ne * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu - * Tuesday, Febuary 1, 2005 + * Tuesday, February 1, 2005 * *------------------------------------------------------------------------- */ @@ -7695,7 +7687,7 @@ H5T__conv_ullong_double(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t n * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu - * Tuesday, Febuary 1, 2005 + * Tuesday, February 1, 2005 * *------------------------------------------------------------------------- */ @@ -7805,7 +7797,7 @@ H5T__conv_double_uchar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t ne * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu - * Tuesday, Febuary 1, 2005 + * Tuesday, February 1, 2005 * *------------------------------------------------------------------------- */ @@ -7827,7 +7819,7 @@ H5T__conv_ldouble_schar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t n * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu - * Tuesday, Febuary 1, 2005 + * Tuesday, February 1, 2005 * *------------------------------------------------------------------------- */ @@ -7937,7 +7929,7 @@ H5T__conv_double_ushort(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t n * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu - * Tuesday, Febuary 1, 2005 + * Tuesday, February 1, 2005 * *------------------------------------------------------------------------- */ @@ -7959,7 +7951,7 @@ H5T__conv_ldouble_short(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t n * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu - * Tuesday, Febuary 1, 2005 + * Tuesday, February 1, 2005 * *------------------------------------------------------------------------- */ @@ -8069,7 +8061,7 @@ H5T__conv_double_uint(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nel * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu - * Tuesday, Febuary 1, 2005 + * Tuesday, February 1, 2005 * *------------------------------------------------------------------------- */ @@ -8091,7 +8083,7 @@ H5T__conv_ldouble_int(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nel * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu - * Tuesday, Febuary 1, 2005 + * Tuesday, February 1, 2005 * *------------------------------------------------------------------------- */ @@ -8201,7 +8193,7 @@ H5T__conv_double_ulong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t ne * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu - * Tuesday, Febuary 1, 2005 + * Tuesday, February 1, 2005 * *------------------------------------------------------------------------- */ @@ -8223,7 +8215,7 @@ H5T__conv_ldouble_long(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t ne * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu - * Tuesday, Febuary 1, 2005 + * Tuesday, February 1, 2005 * *------------------------------------------------------------------------- */ @@ -8333,7 +8325,7 @@ H5T__conv_double_ullong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t n * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu - * Tuesday, Febuary 1, 2005 + * Tuesday, February 1, 2005 * *------------------------------------------------------------------------- */ @@ -8357,7 +8349,7 @@ H5T__conv_ldouble_llong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t n * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu - * Tuesday, Febuary 1, 2005 + * Tuesday, February 1, 2005 * *------------------------------------------------------------------------- */ diff --git a/src/H5Tfields.c b/src/H5Tfields.c index baeae6d..68bc0a3 100644 --- a/src/H5Tfields.c +++ b/src/H5Tfields.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Module Info: This module contains commond functionality for fields in + * Module Info: This module contains command functionality for fields in * enumerated & compound datatypes in the H5T interface. */ diff --git a/src/H5Tnative.c b/src/H5Tnative.c index 2688b23..e6fab51 100644 --- a/src/H5Tnative.c +++ b/src/H5Tnative.c @@ -43,7 +43,7 @@ static herr_t H5T__cmp_offset(size_t *comp_size, size_t *offset, size_t elem_siz * * Purpose: High-level API to return the native type of a datatype. * The native type is chosen by matching the size and class of - * querried datatype from the following native premitive + * queried datatype from the following native primitive * datatypes: * H5T_NATIVE_CHAR H5T_NATIVE_UCHAR * H5T_NATIVE_SHORT H5T_NATIVE_USHORT @@ -56,7 +56,7 @@ static herr_t H5T__cmp_offset(size_t *comp_size, size_t *offset, size_t elem_siz * H5T_NATIVE_LDOUBLE * * Compound, array, enum, and VL types all choose among these - * types for theire members. Time, Bifield, Opaque, Reference + * types for their members. Time, Bitfield, Opaque, Reference * types are only copy out. * * Return: Success: Returns the native data type if successful. @@ -696,7 +696,7 @@ H5_GCC_DIAG_OFF("duplicated-branches") /*------------------------------------------------------------------------- * Function: H5T__get_native_float * - * Purpose: Returns the native floatt type of a datatype. + * Purpose: Returns the native float type of a datatype. * * Return: Success: Returns the native data type if successful. * @@ -718,9 +718,7 @@ H5T__get_native_float(size_t size, H5T_direction_t direction, size_t *struct_ali enum match_type { /* The different kinds of floating point types we can match */ H5T_NATIVE_FLOAT_MATCH_FLOAT, H5T_NATIVE_FLOAT_MATCH_DOUBLE, -#if H5_SIZEOF_LONG_DOUBLE != 0 H5T_NATIVE_FLOAT_MATCH_LDOUBLE, -#endif H5T_NATIVE_FLOAT_MATCH_UNKNOWN } match = H5T_NATIVE_FLOAT_MATCH_UNKNOWN; H5T_t *ret_value = NULL; /* Return value */ @@ -738,24 +736,16 @@ H5T__get_native_float(size_t size, H5T_direction_t direction, size_t *struct_ali match = H5T_NATIVE_FLOAT_MATCH_DOUBLE; native_size = sizeof(double); } -#if H5_SIZEOF_LONG_DOUBLE != 0 else if (size <= sizeof(long double)) { match = H5T_NATIVE_FLOAT_MATCH_LDOUBLE; native_size = sizeof(long double); } -#endif else { /* If not match, return the biggest datatype */ -#if H5_SIZEOF_LONG_DOUBLE != 0 match = H5T_NATIVE_FLOAT_MATCH_LDOUBLE; native_size = sizeof(long double); -#else - match = H5T_NATIVE_FLOAT_MATCH_DOUBLE; - native_size = sizeof(double); -#endif } } else { -#if H5_SIZEOF_LONG_DOUBLE != 0 if (size > sizeof(double)) { match = H5T_NATIVE_FLOAT_MATCH_LDOUBLE; native_size = sizeof(long double); @@ -768,16 +758,6 @@ H5T__get_native_float(size_t size, H5T_direction_t direction, size_t *struct_ali match = H5T_NATIVE_FLOAT_MATCH_FLOAT; native_size = sizeof(float); } -#else - if (size > sizeof(float)) { - match = H5T_NATIVE_FLOAT_MATCH_DOUBLE; - native_size = sizeof(double); - } - else { - match = H5T_NATIVE_FLOAT_MATCH_FLOAT; - native_size = sizeof(float); - } -#endif } /* Set the appropriate native floating point information */ @@ -792,12 +772,11 @@ H5T__get_native_float(size_t size, H5T_direction_t direction, size_t *struct_ali align = H5T_NATIVE_DOUBLE_COMP_ALIGN_g; break; -#if H5_SIZEOF_LONG_DOUBLE != 0 case H5T_NATIVE_FLOAT_MATCH_LDOUBLE: tid = H5T_NATIVE_LDOUBLE; align = H5T_NATIVE_LDOUBLE_COMP_ALIGN_g; break; -#endif + case H5T_NATIVE_FLOAT_MATCH_UNKNOWN: default: HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "Unknown native floating-point match") diff --git a/src/H5Topaque.c b/src/H5Topaque.c index f097fca..c5c2788 100644 --- a/src/H5Topaque.c +++ b/src/H5Topaque.c @@ -70,7 +70,7 @@ done: /*------------------------------------------------------------------------- * Function: H5Tget_tag * - * Purpose: Get tha tag associated with an opaque datatype. + * Purpose: Get the tag associated with an opaque datatype. * * Return: A pointer to an allocated string. The caller should free * the string. NULL is returned for errors. diff --git a/src/H5Tpkg.h b/src/H5Tpkg.h index 51ecaca..4062cbe 100644 --- a/src/H5Tpkg.h +++ b/src/H5Tpkg.h @@ -123,7 +123,7 @@ #endif /* Define an internal macro for converting unsigned long long to long double. SGI compilers give - * some incorect conversion. 64-bit Solaris does different rounding. Windows Visual Studio 6 does + * some incorrect conversion. 64-bit Solaris does different rounding. Windows Visual Studio 6 does * not support unsigned long long. For FreeBSD(sleipnir), the last 2 bytes of mantissa are lost when * compiler tries to do the conversion. For Cygwin, compiler doesn't do rounding correctly. * Mac OS 10.4 gives some incorrect result. */ @@ -401,9 +401,7 @@ H5_DLLVAR size_t H5T_NATIVE_LONG_COMP_ALIGN_g; H5_DLLVAR size_t H5T_NATIVE_LLONG_COMP_ALIGN_g; H5_DLLVAR size_t H5T_NATIVE_FLOAT_COMP_ALIGN_g; H5_DLLVAR size_t H5T_NATIVE_DOUBLE_COMP_ALIGN_g; -#if H5_SIZEOF_LONG_DOUBLE != 0 H5_DLLVAR size_t H5T_NATIVE_LDOUBLE_COMP_ALIGN_g; -#endif H5_DLLVAR size_t H5T_POINTER_COMP_ALIGN_g; H5_DLLVAR size_t H5T_HVL_COMP_ALIGN_g; @@ -429,9 +427,7 @@ H5_DLLVAR size_t H5T_NATIVE_LLONG_ALIGN_g; H5_DLLVAR size_t H5T_NATIVE_ULLONG_ALIGN_g; H5_DLLVAR size_t H5T_NATIVE_FLOAT_ALIGN_g; H5_DLLVAR size_t H5T_NATIVE_DOUBLE_ALIGN_g; -#if H5_SIZEOF_LONG_DOUBLE != 0 H5_DLLVAR size_t H5T_NATIVE_LDOUBLE_ALIGN_g; -#endif /* C9x alignment constraints */ H5_DLLVAR size_t H5T_NATIVE_INT8_ALIGN_g; @@ -468,10 +464,8 @@ H5_DLLVAR float H5T_NATIVE_FLOAT_POS_INF_g; H5_DLLVAR float H5T_NATIVE_FLOAT_NEG_INF_g; H5_DLLVAR double H5T_NATIVE_DOUBLE_POS_INF_g; H5_DLLVAR double H5T_NATIVE_DOUBLE_NEG_INF_g; -#if H5_SIZEOF_LONG_DOUBLE != 0 H5_DLLVAR double H5T_NATIVE_LDOUBLE_POS_INF_g; H5_DLLVAR double H5T_NATIVE_LDOUBLE_NEG_INF_g; -#endif /* Declare extern the free lists for H5T_t's and H5T_shared_t's */ H5FL_EXTERN(H5T_t); diff --git a/src/H5Tprivate.h b/src/H5Tprivate.h index 6624096..9731379 100644 --- a/src/H5Tprivate.h +++ b/src/H5Tprivate.h @@ -101,6 +101,8 @@ typedef struct H5T_subset_info_t { } H5T_subset_info_t; /* Forward declarations for prototype arguments */ +struct H5G_loc_t; +struct H5G_name_t; struct H5O_shared_t; /* The native endianness of the platform */ @@ -120,14 +122,14 @@ H5_DLL size_t H5T_get_size(const H5T_t *dt); H5_DLL hbool_t H5T_get_force_conv(const H5T_t *dt); H5_DLL int H5T_cmp(const H5T_t *dt1, const H5T_t *dt2, hbool_t superset); H5_DLL herr_t H5T_encode(H5T_t *obj, unsigned char *buf, size_t *nalloc); -H5_DLL H5T_t * H5T_decode(size_t buf_size, const unsigned char *buf); -H5_DLL herr_t H5T_debug(const H5T_t *dt, FILE *stream); -H5_DLL struct H5O_loc_t *H5T_oloc(H5T_t *dt); -H5_DLL H5G_name_t *H5T_nameof(const H5T_t *dt); -H5_DLL htri_t H5T_is_immutable(const H5T_t *dt); -H5_DLL htri_t H5T_is_named(const H5T_t *dt); -H5_DLL herr_t H5T_convert_committed_datatype(H5T_t *dt, H5F_t *f); -H5_DLL htri_t H5T_is_relocatable(const H5T_t *dt); +H5_DLL H5T_t * H5T_decode(size_t buf_size, const unsigned char *buf); +H5_DLL herr_t H5T_debug(const H5T_t *dt, FILE *stream); +H5_DLL struct H5O_loc_t * H5T_oloc(H5T_t *dt); +H5_DLL struct H5G_name_t *H5T_nameof(const H5T_t *dt); +H5_DLL htri_t H5T_is_immutable(const H5T_t *dt); +H5_DLL htri_t H5T_is_named(const H5T_t *dt); +H5_DLL herr_t H5T_convert_committed_datatype(H5T_t *dt, H5F_t *f); +H5_DLL htri_t H5T_is_relocatable(const H5T_t *dt); H5_DLL H5T_path_t *H5T_path_find(const H5T_t *src, const H5T_t *dst); H5_DLL hbool_t H5T_path_noop(const H5T_path_t *p); H5_DLL H5T_bkg_t H5T_path_bkg(const H5T_path_t *p); @@ -159,7 +161,7 @@ H5_DLL herr_t H5T_invoke_vol_optional(H5T_t *dt, H5VL_optional_args_t *args, hi H5_DLL H5R_type_t H5T_get_ref_type(const H5T_t *dt); /* Operations on named datatypes */ -H5_DLL H5T_t *H5T_open(const H5G_loc_t *loc); +H5_DLL H5T_t *H5T_open(const struct H5G_loc_t *loc); H5_DLL int H5T_link(const H5T_t *type, int adjust); H5_DLL herr_t H5T_update_shared(H5T_t *type); diff --git a/src/H5Tpublic.h b/src/H5Tpublic.h index bb5b0ef..3df7ca2 100644 --- a/src/H5Tpublic.h +++ b/src/H5Tpublic.h @@ -148,7 +148,7 @@ typedef enum H5T_pad_t { H5T_PAD_ONE = 1, /**< always set to one */ H5T_PAD_BACKGROUND = 2, /**< set to background value */ - H5T_NPAD = 3 /**< sentinal: THIS MUST BE LAST */ + H5T_NPAD = 3 /**< sentinel: THIS MUST BE LAST */ } H5T_pad_t; //! <!-- [H5T_pad_t_snip] --> @@ -803,13 +803,11 @@ H5_DLLVAR hid_t H5T_VAX_F64_g; * C-style \Code{double} */ #define H5T_NATIVE_DOUBLE (H5OPEN H5T_NATIVE_DOUBLE_g) -#if H5_SIZEOF_LONG_DOUBLE != 0 /** * \ingroup PDTNAT * C-style \Code{long double} */ #define H5T_NATIVE_LDOUBLE (H5OPEN H5T_NATIVE_LDOUBLE_g) -#endif /** * \ingroup PDTNAT * HDF5 8-bit bitfield based on native types @@ -872,9 +870,7 @@ H5_DLLVAR hid_t H5T_NATIVE_LLONG_g; H5_DLLVAR hid_t H5T_NATIVE_ULLONG_g; H5_DLLVAR hid_t H5T_NATIVE_FLOAT_g; H5_DLLVAR hid_t H5T_NATIVE_DOUBLE_g; -#if H5_SIZEOF_LONG_DOUBLE != 0 H5_DLLVAR hid_t H5T_NATIVE_LDOUBLE_g; -#endif H5_DLLVAR hid_t H5T_NATIVE_B8_g; H5_DLLVAR hid_t H5T_NATIVE_B16_g; H5_DLLVAR hid_t H5T_NATIVE_B32_g; @@ -1165,7 +1161,7 @@ H5_DLL herr_t H5Tlock(hid_t type_id); * the link(s) by which the new committed datatype is accessed and * the creation of any intermediate groups that may be missing. * - * Once commited, this datatype may be used to define the datatype + * Once committed, this datatype may be used to define the datatype * of any other dataset or attribute in the file. * * This function will not accept a datatype that cannot actually hold @@ -1175,7 +1171,7 @@ H5_DLL herr_t H5Tlock(hid_t type_id); * Committed datatypes are sometimes referred to as named datatypes. * * \version 1.8.7 Function modified in this release to reject datatypes that - * will not accomodate actual data, such as a compound datatype + * will not accommodate actual data, such as a compound datatype * with no fields or an enumerated datatype with no members. * * \since 1.8.0 @@ -1270,7 +1266,7 @@ H5_DLL hid_t H5Topen_async(const char *app_file, const char *app_func, unsigned * fields and enumerated datatypes with no members. * * \version 1.8.7 Function modified in this release to reject datatypes that - * will not accomodate actual data, such as a compound datatype + * will not accommodate actual data, such as a compound datatype * with no fields or an enumerated datatype with no members. * * \since 1.2.0 diff --git a/src/H5Tref.c b/src/H5Tref.c index cac8cf6..511c531 100644 --- a/src/H5Tref.c +++ b/src/H5Tref.c @@ -309,8 +309,8 @@ H5T__ref_set_loc(H5T_t *dt, H5VL_object_t *file, H5T_loc_t loc) HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "can't get encode size") /* Size on disk, memory size is different */ - dt->shared->size = MAX(H5_SIZEOF_UINT32_T + H5R_ENCODE_HEADER_SIZE + cont_info.blob_id_size, - ref_encode_size); + dt->shared->size = + MAX(sizeof(uint32_t) + H5R_ENCODE_HEADER_SIZE + cont_info.blob_id_size, ref_encode_size); dt->shared->u.atomic.prec = 8 * dt->shared->size; /* Set up the function pointers to access the information on @@ -778,7 +778,7 @@ H5T__ref_disk_isnull(const H5VL_object_t *src_file, const void *src_buf, hbool_t H5VL_blob_specific_args_t vol_cb_args; /* Arguments to VOL callback */ /* Skip the size / header */ - p = (const uint8_t *)src_buf + H5R_ENCODE_HEADER_SIZE + H5_SIZEOF_UINT32_T; + p = (const uint8_t *)src_buf + H5R_ENCODE_HEADER_SIZE + sizeof(uint32_t); /* Set up VOL callback arguments */ vol_cb_args.op_type = H5VL_BLOB_ISNULL; @@ -819,7 +819,7 @@ H5T__ref_disk_setnull(H5VL_object_t *dst_file, void *dst_buf, void *bg_buf) /* TODO Should get rid of bg stuff */ if (p_bg) { /* Skip the size / header */ - p_bg += (H5_SIZEOF_UINT32_T + H5R_ENCODE_HEADER_SIZE); + p_bg += (sizeof(uint32_t) + H5R_ENCODE_HEADER_SIZE); /* Set up VOL callback arguments */ vol_cb_args.op_type = H5VL_BLOB_DELETE; @@ -929,8 +929,8 @@ H5T__ref_disk_read(H5VL_object_t *src_file, const void *src_buf, size_t H5_ATTR_ blob_size -= H5R_ENCODE_HEADER_SIZE; /* Skip the size */ - p += H5_SIZEOF_UINT32_T; - HDassert(src_size > (H5R_ENCODE_HEADER_SIZE + H5_SIZEOF_UINT32_T)); + p += sizeof(uint32_t); + HDassert(src_size > (H5R_ENCODE_HEADER_SIZE + sizeof(uint32_t))); /* Retrieve blob */ if (H5VL_blob_get(src_file, p, q, blob_size, NULL) < 0) @@ -974,9 +974,9 @@ H5T__ref_disk_write(H5VL_object_t H5_ATTR_UNUSED *src_file, const void *src_buf, size_t p_buf_size_left = dst_size; /* Skip the size / header */ - p_bg += (H5_SIZEOF_UINT32_T + H5R_ENCODE_HEADER_SIZE); - HDassert(p_buf_size_left > (H5_SIZEOF_UINT32_T + H5R_ENCODE_HEADER_SIZE)); - p_buf_size_left -= (H5_SIZEOF_UINT32_T + H5R_ENCODE_HEADER_SIZE); + p_bg += (sizeof(uint32_t) + H5R_ENCODE_HEADER_SIZE); + HDassert(p_buf_size_left > (sizeof(uint32_t) + H5R_ENCODE_HEADER_SIZE)); + p_buf_size_left -= (sizeof(uint32_t) + H5R_ENCODE_HEADER_SIZE); /* Set up VOL callback arguments */ vol_cb_args.op_type = H5VL_BLOB_DELETE; @@ -991,12 +991,12 @@ H5T__ref_disk_write(H5VL_object_t H5_ATTR_UNUSED *src_file, const void *src_buf, p += H5R_ENCODE_HEADER_SIZE; q += H5R_ENCODE_HEADER_SIZE; src_size -= H5R_ENCODE_HEADER_SIZE; - buf_size_left -= H5_SIZEOF_UINT32_T; + buf_size_left -= sizeof(uint32_t); /* Set the size */ UINT32ENCODE(q, src_size); - HDassert(buf_size_left > H5_SIZEOF_UINT32_T); - buf_size_left -= H5_SIZEOF_UINT32_T; + HDassert(buf_size_left > sizeof(uint32_t)); + buf_size_left -= sizeof(uint32_t); /* Store blob */ if (H5VL_blob_put(dst_file, p, src_size, q, NULL) < 0) @@ -655,6 +655,39 @@ done: FUNC_LEAVE_API(ret_value) } /* H5VLobject() */ +/*--------------------------------------------------------------------------- + * Function: H5VLobject_is_native + * + * Purpose: Determines whether an object ID represents a native VOL + * connector object. + * + * Return: Non-negative on success/Negative on failure + * + *--------------------------------------------------------------------------- + */ +herr_t +H5VLobject_is_native(hid_t obj_id, hbool_t *is_native) +{ + H5VL_object_t *vol_obj = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "i*b", obj_id, is_native); + + if (!is_native) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "`is_native` argument is NULL") + + /* Get the location object for the ID */ + if (NULL == (vol_obj = H5VL_vol_object(obj_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier") + + if (H5VL_object_is_native(vol_obj, is_native) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't determine if object is a native connector object") + +done: + FUNC_LEAVE_API(ret_value) +} /* H5VLobject_is_native() */ + /*------------------------------------------------------------------------- * Function: H5VLget_file_type * diff --git a/src/H5VLcallback.c b/src/H5VLcallback.c index a61b003..0c5c73d 100644 --- a/src/H5VLcallback.c +++ b/src/H5VLcallback.c @@ -30,7 +30,7 @@ #include "H5private.h" /* Generic Functions */ #include "H5Eprivate.h" /* Error handling */ #include "H5ESprivate.h" /* Event Sets */ -#include "H5Fprivate.h" /* File access */ +#include "H5Fprivate.h" /* File access */ #include "H5Iprivate.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ #include "H5Pprivate.h" /* Property lists */ @@ -3527,6 +3527,7 @@ H5VL__file_open_find_connector_cb(H5PL_type_t plugin_type, const void *plugin_in H5P_genplist_t * fapl_plist; H5P_genplist_t * fapl_plist_copy; hbool_t is_accessible = FALSE; /* Whether file is accessible */ + ssize_t num_errors = 0; herr_t status; hid_t connector_id = H5I_INVALID_HID; hid_t fapl_id = H5I_INVALID_HID; @@ -3565,6 +3566,10 @@ H5VL__file_open_find_connector_cb(H5PL_type_t plugin_type, const void *plugin_in vol_cb_args.args.is_accessible.fapl_id = fapl_id; vol_cb_args.args.is_accessible.accessible = &is_accessible; + /* Store current error stack size */ + if ((num_errors = H5Eget_num(H5E_DEFAULT)) < 0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, H5_ITER_ERROR, "can't get current error stack size") + /* Check if file is accessible with given VOL connector */ H5E_BEGIN_TRY { @@ -3572,11 +3577,23 @@ H5VL__file_open_find_connector_cb(H5PL_type_t plugin_type, const void *plugin_in } H5E_END_TRY; - /* If the file was accessible with the current VOL connector, return - * the FAPL with that VOL connector set on it. Errors are ignored here - * as some VOL connectors may not support H5Fis_accessible. - */ - if (status == SUCCEED && is_accessible) { + if (status < 0) { + ssize_t new_num_errors = 0; + + /* Pop any errors generated by the above call */ + if ((new_num_errors = H5Eget_num(H5E_DEFAULT)) < 0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, H5_ITER_ERROR, "can't get current error stack size") + if (new_num_errors > num_errors) { + new_num_errors -= num_errors; + if (H5Epop(H5E_DEFAULT, (size_t)new_num_errors) < 0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTRELEASE, H5_ITER_ERROR, "can't sanitize error stack") + } + } + else if (status == SUCCEED && is_accessible) { + /* If the file was accessible with the current VOL connector, return + * the FAPL with that VOL connector set on it. + */ + /* Modify 'connector_prop' to point to the VOL connector that * was actually used to open the file, rather than the original * VOL connector that was requested. @@ -3586,7 +3603,7 @@ H5VL__file_open_find_connector_cb(H5PL_type_t plugin_type, const void *plugin_in udata->fapl_id = fapl_id; ret_value = H5_ITER_STOP; - } /* end if */ + } done: if (ret_value != H5_ITER_STOP) { @@ -4950,7 +4967,7 @@ done: /*------------------------------------------------------------------------- * Function: H5VL__link_copy * - * Purpose: Copys a link from src to dst. + * Purpose: Copies a link from src to dst. * * Return: Success: Non-negative * Failure: Negative @@ -4981,7 +4998,7 @@ done: /*------------------------------------------------------------------------- * Function: H5VL_link_copy * - * Purpose: Copys a link from src to dst. + * Purpose: Copies a link from src to dst. * * Return: Success: Non-negative * Failure: Negative @@ -6391,7 +6408,7 @@ done: /*------------------------------------------------------------------------- * Function: H5VL__request_wait * - * Purpose: Waits on an asychronous request through the VOL + * Purpose: Waits on an asynchronous request through the VOL * * Return: Success: Non-negative * Failure: Negative @@ -6425,7 +6442,7 @@ done: /*------------------------------------------------------------------------- * Function: H5VL_request_wait * - * Purpose: Waits on an asychronous request through the VOL + * Purpose: Waits on an asynchronous request through the VOL * * Return: Success: Non-negative * Failure: Negative @@ -6435,18 +6452,28 @@ done: herr_t H5VL_request_wait(const H5VL_object_t *vol_obj, uint64_t timeout, H5VL_request_status_t *status) { - herr_t ret_value = SUCCEED; /* Return value */ + hbool_t vol_wrapper_set = FALSE; + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) /* Sanity checks */ HDassert(vol_obj); + /* Set wrapper info in API context */ + if (H5VL_set_vol_wrapper(vol_obj) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info") + vol_wrapper_set = TRUE; + /* Call the corresponding internal VOL routine */ if (H5VL__request_wait(vol_obj->data, vol_obj->connector->cls, timeout, status) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "request wait failed") done: + /* Reset object wrapping info in API context */ + if (vol_wrapper_set && H5VL_reset_vol_wrapper() < 0) + HDONE_ERROR(H5E_VOL, H5E_CANTRESET, FAIL, "can't reset VOL wrapper info") + FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_request_wait() */ @@ -6529,18 +6556,28 @@ done: herr_t H5VL_request_notify(const H5VL_object_t *vol_obj, H5VL_request_notify_t cb, void *ctx) { - herr_t ret_value = SUCCEED; /* Return value */ + hbool_t vol_wrapper_set = FALSE; + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) /* Sanity check */ HDassert(vol_obj); + /* Set wrapper info in API context */ + if (H5VL_set_vol_wrapper(vol_obj) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info") + vol_wrapper_set = TRUE; + /* Call the corresponding internal VOL routine */ if (H5VL__request_notify(vol_obj->data, vol_obj->connector->cls, cb, ctx) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "request notify failed") done: + /* Reset object wrapping info in API context */ + if (vol_wrapper_set && H5VL_reset_vol_wrapper() < 0) + HDONE_ERROR(H5E_VOL, H5E_CANTRESET, FAIL, "can't reset VOL wrapper info") + FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_request_notify() */ @@ -6622,18 +6659,28 @@ done: herr_t H5VL_request_cancel(const H5VL_object_t *vol_obj, H5VL_request_status_t *status) { - herr_t ret_value = SUCCEED; /* Return value */ + hbool_t vol_wrapper_set = FALSE; + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) /* Sanity check */ HDassert(vol_obj); + /* Set wrapper info in API context */ + if (H5VL_set_vol_wrapper(vol_obj) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info") + vol_wrapper_set = TRUE; + /* Call the corresponding internal VOL routine */ if (H5VL__request_cancel(vol_obj->data, vol_obj->connector->cls, status) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "request cancel failed") done: + /* Reset object wrapping info in API context */ + if (vol_wrapper_set && H5VL_reset_vol_wrapper() < 0) + HDONE_ERROR(H5E_VOL, H5E_CANTRESET, FAIL, "can't reset VOL wrapper info") + FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_request_cancel() */ @@ -6715,19 +6762,29 @@ done: herr_t H5VL_request_specific(const H5VL_object_t *vol_obj, H5VL_request_specific_args_t *args) { - herr_t ret_value = SUCCEED; /* Return value */ + hbool_t vol_wrapper_set = FALSE; + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) /* Sanity check */ HDassert(vol_obj); + /* Set wrapper info in API context */ + if (H5VL_set_vol_wrapper(vol_obj) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info") + vol_wrapper_set = TRUE; + /* Call the corresponding internal VOL routine */ if (H5VL__request_specific(vol_obj->data, vol_obj->connector->cls, args) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute asynchronous request specific callback") done: + /* Reset object wrapping info in API context */ + if (vol_wrapper_set && H5VL_reset_vol_wrapper() < 0) + HDONE_ERROR(H5E_VOL, H5E_CANTRESET, FAIL, "can't reset VOL wrapper info") + FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_request_specific() */ @@ -6810,19 +6867,29 @@ done: herr_t H5VL_request_optional(const H5VL_object_t *vol_obj, H5VL_optional_args_t *args) { - herr_t ret_value = SUCCEED; /* Return value */ + hbool_t vol_wrapper_set = FALSE; + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) /* Sanity check */ HDassert(vol_obj); + /* Set wrapper info in API context */ + if (H5VL_set_vol_wrapper(vol_obj) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info") + vol_wrapper_set = TRUE; + /* Call the corresponding internal VOL routine */ if (H5VL__request_optional(vol_obj->data, vol_obj->connector->cls, args) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute asynchronous request optional callback") done: + /* Reset object wrapping info in API context */ + if (vol_wrapper_set && H5VL_reset_vol_wrapper() < 0) + HDONE_ERROR(H5E_VOL, H5E_CANTRESET, FAIL, "can't reset VOL wrapper info") + FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_request_optional() */ @@ -6941,18 +7008,28 @@ done: herr_t H5VL_request_free(const H5VL_object_t *vol_obj) { - herr_t ret_value = SUCCEED; /* Return value */ + hbool_t vol_wrapper_set = FALSE; + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) /* Sanity check */ HDassert(vol_obj); + /* Set wrapper info in API context */ + if (H5VL_set_vol_wrapper(vol_obj) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info") + vol_wrapper_set = TRUE; + /* Call the corresponding VOL callback */ if (H5VL__request_free(vol_obj->data, vol_obj->connector->cls) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "request free failed") done: + /* Reset object wrapping info in API context */ + if (vol_wrapper_set && H5VL_reset_vol_wrapper() < 0) + HDONE_ERROR(H5E_VOL, H5E_CANTRESET, FAIL, "can't reset VOL wrapper info") + FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_request_free() */ diff --git a/src/H5VLint.c b/src/H5VLint.c index b4432d0..391bd91 100644 --- a/src/H5VLint.c +++ b/src/H5VLint.c @@ -32,6 +32,7 @@ #include "H5CXprivate.h" /* API Contexts */ #include "H5Dprivate.h" /* Datasets */ #include "H5Eprivate.h" /* Error handling */ +#include "H5ESprivate.h" /* Event sets */ #include "H5Fprivate.h" /* Files */ #include "H5FLprivate.h" /* Free lists */ #include "H5Gprivate.h" /* Groups */ @@ -69,11 +70,7 @@ typedef struct H5VL_wrap_ctx_t { */ typedef struct { /* IN */ - H5VL_get_connector_kind_t kind; /* Which kind of connector search to make */ - union { - const char * name; /* The name of the VOL connector to check */ - H5VL_class_value_t value; /* The value of the VOL connector to check */ - } u; + H5PL_vol_key_t key; /* OUT */ hid_t found_id; /* The connector ID, if we found a match */ @@ -98,9 +95,6 @@ static herr_t H5VL__free_vol_wrapper(H5VL_wrap_ctx_t *vol_wrap_ctx); /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /*****************************/ /* Library Private Variables */ /*****************************/ @@ -153,7 +147,9 @@ H5VL_init_phase1(void) FUNC_ENTER_NOAPI(FAIL) - /* FUNC_ENTER() does all the work */ + /* Initialize the ID group for the VL IDs */ + if (H5I_register_type(H5I_VOL_CLS) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "unable to initialize H5VL interface") done: FUNC_LEAVE_NOAPI(ret_value) @@ -175,23 +171,38 @@ done: herr_t H5VL_init_phase2(void) { + size_t i; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) + /* clang-format off */ + struct { + herr_t (*func)(void); + const char *descr; + } initializer[] = { + {H5T_init, "datatype"} + , {H5O_init, "object header"} + , {H5D_init, "dataset"} + , {H5F_init, "file"} + , {H5G_init, "group"} + , {H5A_init, "attribute"} + , {H5M_init, "map"} + , {H5CX_init, "context"} + , {H5ES_init, "event set"} + , {H5Z_init, "transform"} + , {H5R_init, "reference"} + }; + /* Initialize all packages for VOL-managed objects */ - if (H5T_init() < 0) - HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "unable to initialize datatype interface") - if (H5D_init() < 0) - HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "unable to initialize dataset interface") - if (H5F_init() < 0) - HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "unable to initialize file interface") - if (H5G_init() < 0) - HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "unable to initialize group interface") - if (H5A_init() < 0) - HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "unable to initialize attribute interface") - if (H5M_init() < 0) - HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "unable to initialize map interface") + for (i = 0; i < NELMTS(initializer); i++) { + if (initializer[i].func() < 0) { + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, + "unable to initialize %s interface", initializer[i].descr) + } + } + + /* clang-format on */ /* Sanity check default VOL connector */ HDassert(H5VL_def_conn_s.connector_id == (-1)); @@ -206,32 +217,6 @@ done: } /* end H5VL_init_phase2() */ /*------------------------------------------------------------------------- - * Function: H5VL__init_package - * - * Purpose: Initialize interface-specific information - * - * Return: Success: Non-negative - * - * Failure: Negative - * - *------------------------------------------------------------------------- - */ -herr_t -H5VL__init_package(void) -{ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_PACKAGE - - /* Initialize the ID group for the VL IDs */ - if (H5I_register_type(H5I_VOL_CLS) < 0) - HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "unable to initialize H5VL interface") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5VL__init_package() */ - -/*------------------------------------------------------------------------- * Function: H5VL_term_package * * Purpose: Terminate various H5VL objects @@ -249,37 +234,31 @@ H5VL_term_package(void) FUNC_ENTER_NOAPI_NOINIT_NOERR - if (H5_PKG_INIT_VAR) { - if (H5VL_def_conn_s.connector_id > 0) { - /* Release the default VOL connector */ - (void)H5VL_conn_free(&H5VL_def_conn_s); - H5VL_def_conn_s.connector_id = -1; - H5VL_def_conn_s.connector_info = NULL; + if (H5VL_def_conn_s.connector_id > 0) { + /* Release the default VOL connector */ + (void)H5VL_conn_free(&H5VL_def_conn_s); + H5VL_def_conn_s.connector_id = -1; + H5VL_def_conn_s.connector_info = NULL; + n++; + } /* end if */ + else { + if (H5I_nmembers(H5I_VOL) > 0) { + /* Unregister all VOL connectors */ + (void)H5I_clear_type(H5I_VOL, TRUE, FALSE); n++; } /* end if */ else { - if (H5I_nmembers(H5I_VOL) > 0) { - /* Unregister all VOL connectors */ - (void)H5I_clear_type(H5I_VOL, TRUE, FALSE); + if (H5VL__num_opt_operation() > 0) { + /* Unregister all dynamically registered optional operations */ + (void)H5VL__term_opt_operation(); n++; } /* end if */ else { - if (H5VL__num_opt_operation() > 0) { - /* Unregister all dynamically registered optional operations */ - (void)H5VL__term_opt_operation(); - n++; - } /* end if */ - else { - /* Destroy the VOL connector ID group */ - n += (H5I_dec_type_ref(H5I_VOL) > 0); - - /* Mark interface as closed */ - if (0 == n) - H5_PKG_INIT_VAR = FALSE; - } /* end else */ - } /* end else */ - } /* end else */ - } /* end if */ + /* Destroy the VOL connector ID group */ + n += (H5I_dec_type_ref(H5I_VOL) > 0); + } /* end else */ + } /* end else */ + } /* end else */ FUNC_LEAVE_NOAPI(n) } /* end H5VL_term_package() */ @@ -341,15 +320,15 @@ H5VL__get_connector_cb(void *obj, hid_t id, void *_op_data) FUNC_ENTER_STATIC_NOERR - if (H5VL_GET_CONNECTOR_BY_NAME == op_data->kind) { - if (0 == HDstrcmp(cls->name, op_data->u.name)) { + if (H5VL_GET_CONNECTOR_BY_NAME == op_data->key.kind) { + if (0 == HDstrcmp(cls->name, op_data->key.u.name)) { op_data->found_id = id; ret_value = H5_ITER_STOP; } /* end if */ } /* end if */ else { - HDassert(H5VL_GET_CONNECTOR_BY_VALUE == op_data->kind); - if (cls->value == op_data->u.value) { + HDassert(H5VL_GET_CONNECTOR_BY_VALUE == op_data->key.kind); + if (cls->value == op_data->key.u.value) { op_data->found_id = id; ret_value = H5_ITER_STOP; } /* end if */ @@ -398,7 +377,7 @@ H5VL__set_def_conn(void) } /* end if */ /* Check for environment variable set */ - env_var = HDgetenv("HDF5_VOL_CONNECTOR"); + env_var = HDgetenv(HDF5_VOL_CONNECTOR); /* Only parse the string if it's set */ if (env_var && *env_var) { @@ -976,7 +955,7 @@ H5VL_conn_inc_rc(H5VL_t *connector) { int64_t ret_value = -1; - FUNC_ENTER_NOAPI(-1) + FUNC_ENTER_NOAPI_NOERR /* Check arguments */ HDassert(connector); @@ -986,7 +965,6 @@ H5VL_conn_inc_rc(H5VL_t *connector) ret_value = connector->nrefs; -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_conn_inc_rc() */ @@ -1299,9 +1277,9 @@ H5VL__register_connector_by_class(const H5VL_class_t *cls, hbool_t app_ref, hid_ "callback is provided") /* Set up op data for iteration */ - op_data.kind = H5VL_GET_CONNECTOR_BY_NAME; - op_data.u.name = cls->name; - op_data.found_id = H5I_INVALID_HID; + op_data.key.kind = H5VL_GET_CONNECTOR_BY_NAME; + op_data.key.u.name = cls->name; + op_data.found_id = H5I_INVALID_HID; /* Check if connector is already registered */ if (H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, TRUE) < 0) @@ -1350,15 +1328,15 @@ H5VL__register_connector_by_name(const char *name, hbool_t app_ref, hid_t vipl_i FUNC_ENTER_PACKAGE /* Set up op data for iteration */ - op_data.kind = H5VL_GET_CONNECTOR_BY_NAME; - op_data.u.name = name; - op_data.found_id = H5I_INVALID_HID; + op_data.key.kind = H5VL_GET_CONNECTOR_BY_NAME; + op_data.key.u.name = name; + op_data.found_id = H5I_INVALID_HID; /* Check if connector is already registered */ if (H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, app_ref) < 0) HGOTO_ERROR(H5E_VOL, H5E_BADITER, H5I_INVALID_HID, "can't iterate over VOL ids") - /* If connector alread registered, increment ref count on ID and return ID */ + /* If connector already registered, increment ref count on ID and return ID */ if (op_data.found_id != H5I_INVALID_HID) { if (H5I_inc_ref(op_data.found_id, app_ref) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTINC, H5I_INVALID_HID, @@ -1410,15 +1388,15 @@ H5VL__register_connector_by_value(H5VL_class_value_t value, hbool_t app_ref, hid FUNC_ENTER_PACKAGE /* Set up op data for iteration */ - op_data.kind = H5VL_GET_CONNECTOR_BY_VALUE; - op_data.u.value = value; - op_data.found_id = H5I_INVALID_HID; + op_data.key.kind = H5VL_GET_CONNECTOR_BY_VALUE; + op_data.key.u.value = value; + op_data.found_id = H5I_INVALID_HID; /* Check if connector is already registered */ - if (H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, TRUE) < 0) + if (H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, app_ref) < 0) HGOTO_ERROR(H5E_VOL, H5E_BADITER, H5I_INVALID_HID, "can't iterate over VOL ids") - /* If connector alread registered, increment ref count on ID and return ID */ + /* If connector already registered, increment ref count on ID and return ID */ if (op_data.found_id != H5I_INVALID_HID) { if (H5I_inc_ref(op_data.found_id, app_ref) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTINC, H5I_INVALID_HID, @@ -1449,8 +1427,9 @@ done: * * Purpose: Checks if a connector with a particular name is registered. * - * Return: Success: 0 - * Failure: -1 + * Return: >0 if a VOL connector with that name has been registered + * 0 if a VOL connector with that name has NOT been registered + * <0 on errors * * Programmer: Dana Robinson * June 17, 2017 @@ -1466,9 +1445,9 @@ H5VL__is_connector_registered_by_name(const char *name) FUNC_ENTER_PACKAGE /* Set up op data for iteration */ - op_data.kind = H5VL_GET_CONNECTOR_BY_NAME; - op_data.u.name = name; - op_data.found_id = H5I_INVALID_HID; + op_data.key.kind = H5VL_GET_CONNECTOR_BY_NAME; + op_data.key.u.name = name; + op_data.found_id = H5I_INVALID_HID; /* Find connector with name */ if (H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, TRUE) < 0) @@ -1488,8 +1467,9 @@ done: * Purpose: Checks if a connector with a particular value (ID) is * registered. * - * Return: Success: 0 - * Failure: -1 + * Return: >0 if a VOL connector with that value has been registered + * 0 if a VOL connector with that value hasn't been registered + * <0 on errors * *------------------------------------------------------------------------- */ @@ -1502,9 +1482,9 @@ H5VL__is_connector_registered_by_value(H5VL_class_value_t value) FUNC_ENTER_PACKAGE /* Set up op data for iteration */ - op_data.kind = H5VL_GET_CONNECTOR_BY_VALUE; - op_data.u.value = value; - op_data.found_id = H5I_INVALID_HID; + op_data.key.kind = H5VL_GET_CONNECTOR_BY_VALUE; + op_data.key.u.value = value; + op_data.found_id = H5I_INVALID_HID; /* Find connector with value */ if (H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, TRUE) < 0) @@ -1635,9 +1615,9 @@ H5VL__peek_connector_id_by_name(const char *name) FUNC_ENTER_PACKAGE /* Set up op data for iteration */ - op_data.kind = H5VL_GET_CONNECTOR_BY_NAME; - op_data.u.name = name; - op_data.found_id = H5I_INVALID_HID; + op_data.key.kind = H5VL_GET_CONNECTOR_BY_NAME; + op_data.key.u.name = name; + op_data.found_id = H5I_INVALID_HID; /* Find connector with name */ if (H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, TRUE) < 0) @@ -1671,9 +1651,9 @@ H5VL__peek_connector_id_by_value(H5VL_class_value_t value) FUNC_ENTER_PACKAGE /* Set up op data for iteration */ - op_data.kind = H5VL_GET_CONNECTOR_BY_VALUE; - op_data.u.value = value; - op_data.found_id = H5I_INVALID_HID; + op_data.key.kind = H5VL_GET_CONNECTOR_BY_VALUE; + op_data.key.u.value = value; + op_data.found_id = H5I_INVALID_HID; /* Find connector with value */ if (H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, TRUE) < 0) @@ -2006,7 +1986,7 @@ H5VL_cmp_connector_cls(int *cmp_value, const H5VL_class_t *cls1, const H5VL_clas { herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR /* Sanity checks */ HDassert(cls1); @@ -2534,7 +2514,7 @@ H5VL_check_plugin_load(const H5VL_class_t *cls, const H5PL_key_t *key, hbool_t * { herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR /* Sanity checks */ HDassert(cls); @@ -2560,7 +2540,6 @@ H5VL_check_plugin_load(const H5VL_class_t *cls, const H5PL_key_t *key, hbool_t * if (*success && cls->version != H5VL_VERSION) *success = FALSE; -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_check_plugin_load() */ diff --git a/src/H5VLnative.c b/src/H5VLnative.c index 18b5b9c..2a86c26 100644 --- a/src/H5VLnative.c +++ b/src/H5VLnative.c @@ -224,7 +224,7 @@ H5VL__native_term(void) * Purpose: Query the connector class. * * Note: This routine is in this file so that it can return the address - * of the staticly declared class struct. + * of the statically declared class struct. * * Returns: SUCCEED (Can't fail) * @@ -251,7 +251,7 @@ H5VL__native_introspect_get_conn_cls(void H5_ATTR_UNUSED *obj, H5VL_get_conn_lvl * Purpose: Query the capability flags for this connector. * * Note: This routine is in this file so that it can return the field - * from the staticly declared class struct. + * from the statically declared class struct. * * Returns: SUCCEED (Can't fail) * @@ -324,7 +324,7 @@ done: herr_t H5VL__native_get_file_addr_len(void *obj, H5I_type_t obj_type, size_t *addr_len) { - H5F_t *file = NULL; /* File stuct pointer */ + H5F_t *file = NULL; /* File struct pointer */ herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(FAIL) diff --git a/src/H5VLnative.h b/src/H5VLnative.h index fe8ede2..5e43c4e 100644 --- a/src/H5VLnative.h +++ b/src/H5VLnative.h @@ -74,7 +74,7 @@ typedef union H5VL_native_attr_optional_args_t { #define H5VL_NATIVE_DATASET_CHUNK_WRITE 7 /* H5Dchunk_write */ #define H5VL_NATIVE_DATASET_GET_VLEN_BUF_SIZE 8 /* H5Dvlen_get_buf_size */ #define H5VL_NATIVE_DATASET_GET_OFFSET 9 /* H5Dget_offset */ -#define H5VL_NATIVE_DATASET_CHUNK_ITER 10 /* H5Dget_offset */ +#define H5VL_NATIVE_DATASET_CHUNK_ITER 10 /* H5Dchunk_iter */ /* NOTE: If values over 1023 are added, the H5VL_RESERVED_NATIVE_OPTIONAL macro * must be updated. */ @@ -208,8 +208,8 @@ typedef union H5VL_native_dataset_optional_args_t { #ifdef H5_HAVE_PARALLEL #define H5VL_NATIVE_FILE_GET_MPI_ATOMICITY 26 /* H5Fget_mpi_atomicity */ #define H5VL_NATIVE_FILE_SET_MPI_ATOMICITY 27 /* H5Fset_mpi_atomicity */ -#endif /* H5_HAVE_PARALLEL */ -#define H5VL_NATIVE_FILE_POST_OPEN 28 /* Adjust file after open, with wrapping context */ +#endif +#define H5VL_NATIVE_FILE_POST_OPEN 28 /* Adjust file after open, with wrapping context */ /* NOTE: If values over 1023 are added, the H5VL_RESERVED_NATIVE_OPTIONAL macro * must be updated. */ diff --git a/src/H5VLnative_introspect.c b/src/H5VLnative_introspect.c index fa11bea..0cc6ee4 100644 --- a/src/H5VLnative_introspect.c +++ b/src/H5VLnative_introspect.c @@ -53,7 +53,7 @@ /*******************/ /* Note: H5VL__native_introspect_get_conn_cls and H5VL__native_introspect_get_cap_flags - * are in src/H5VLnative.c so that they can work with the staticly declared + * are in src/H5VLnative.c so that they can work with the statically declared * class struct. */ diff --git a/src/H5VLnative_token.c b/src/H5VLnative_token.c index bed0164..b5bd7b8 100644 --- a/src/H5VLnative_token.c +++ b/src/H5VLnative_token.c @@ -112,7 +112,7 @@ H5VL__native_token_to_str(void *obj, H5I_type_t obj_type, const H5O_token_t *tok if (NULL == (*token_str = H5MM_malloc(addr_ndigits + 1))) HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate buffer for token string") - HDsnprintf(*token_str, addr_ndigits + 1, H5_PRINTF_HADDR_FMT, addr); + HDsnprintf(*token_str, addr_ndigits + 1, "%" PRIuHADDR, addr); done: FUNC_LEAVE_NOAPI(ret_value) @@ -139,7 +139,7 @@ H5VL__native_str_to_token(void *obj, H5I_type_t obj_type, const char *token_str, /* Check parameters */ HDassert(token_str); - HDsscanf(token_str, H5_PRINTF_HADDR_FMT, &addr); + HDsscanf(token_str, "%" PRIuHADDR, &addr); if (H5VL_native_addr_to_token(obj, obj_type, addr, token) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTDECODE, FAIL, "can't convert address to object token") diff --git a/src/H5VLpassthru.c b/src/H5VLpassthru.c index 681531e..6eda875 100644 --- a/src/H5VLpassthru.c +++ b/src/H5VLpassthru.c @@ -45,7 +45,7 @@ /* Macros */ /**********/ -/* Whether to display log messge when callback is invoked */ +/* Whether to display log message when callback is invoked */ /* (Uncomment to enable) */ /* #define ENABLE_PASSTHRU_LOGGING */ @@ -641,16 +641,13 @@ H5VL_pass_through_info_to_str(const void *_info, char **str) under_vol_str_len = strlen(under_vol_string); /* Allocate space for our info */ - *str = (char *)H5allocate_memory(32 + under_vol_str_len, (hbool_t)0); + size_t strSize = 32 + under_vol_str_len; + *str = (char *)H5allocate_memory(strSize, (hbool_t)0); assert(*str); - /* Encode our info - * Normally we'd use snprintf() here for a little extra safety, but that - * call had problems on Windows until recently. So, to be as platform-independent - * as we can, we're using sprintf() instead. - */ - sprintf(*str, "under_vol=%u;under_info={%s}", (unsigned)under_value, - (under_vol_string ? under_vol_string : "")); + /* Encode our info */ + snprintf(*str, strSize, "under_vol=%u;under_info={%s}", (unsigned)under_value, + (under_vol_string ? under_vol_string : "")); return 0; } /* end H5VL_pass_through_info_to_str() */ diff --git a/src/H5VLpublic.h b/src/H5VLpublic.h index 78e39e3..543c3c8 100644 --- a/src/H5VLpublic.h +++ b/src/H5VLpublic.h @@ -356,6 +356,19 @@ H5_DLL herr_t H5VLunregister_connector(hid_t connector_id); * \since 1.12.0 */ H5_DLL herr_t H5VLquery_optional(hid_t obj_id, H5VL_subclass_t subcls, int opt_type, uint64_t *flags); +/** + * \ingroup H5VL + * \brief Determines whether an object ID represents a native + * VOL connector object. + * + * \param[in] obj_id Object identifier + * \param[in] is_native Boolean determining whether object is a native + * VOL connector object + * \return \herr_t + * + * \since 1.13.0 + */ +H5_DLL herr_t H5VLobject_is_native(hid_t obj_id, hbool_t *is_native); #ifdef __cplusplus } @@ -1244,7 +1244,7 @@ H5VM_chunk_index_scaled(unsigned ndims, const hsize_t *coord, const uint32_t *ch * Function: H5VM_opvv * * Purpose: Perform an operation on a source & destination sequences - * of offset/length pairs. Each set of sequnces has an array + * of offset/length pairs. Each set of sequences has an array * of lengths, an array of offsets, the maximum number of * sequences and the current sequence to start at in the sequence. * diff --git a/src/H5VMprivate.h b/src/H5VMprivate.h index 0d3bd0f..e773bae 100644 --- a/src/H5VMprivate.h +++ b/src/H5VMprivate.h @@ -393,8 +393,8 @@ static const unsigned char LogTable256[] = { static inline unsigned H5_ATTR_UNUSED H5VM_log2_gen(uint64_t n) { - unsigned r; /* r will be log2(n) */ - register unsigned int t, tt, ttt; /* temporaries */ + unsigned r; /* r will be log2(n) */ + unsigned int t, tt, ttt; /* temporaries */ if ((ttt = (unsigned)(n >> 32))) if ((tt = (unsigned)(n >> 48))) @@ -18,7 +18,7 @@ * Quincey Koziol * * Purpose: Implements the "wrapped buffer" code for wrapping - * an existing [staticly sized] buffer, in order to + * an existing [statically sized] buffer, in order to * avoid lots of memory allocation calls. * *------------------------------------------------------------------------- @@ -56,9 +56,6 @@ typedef enum { H5Z_PRELUDE_SET_LOCAL /* Call "set local" callback */ } H5Z_prelude_type_t; -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /* Local variables */ static size_t H5Z_table_alloc_g = 0; static size_t H5Z_table_used_g = 0; @@ -74,19 +71,23 @@ static int H5Z__check_unregister_group_cb(void *obj_ptr, hid_t obj_id, void *key static int H5Z__flush_file_cb(void *obj_ptr, hid_t obj_id, void *key); /*------------------------------------------------------------------------- - * Function: H5Z__init_package + * Function: H5Z_init * - * Purpose: Initializes the data filter layer. + * Purpose: Initialize the interface from some other layer. * - * Return: Non-negative on success/Negative on failure + * Return: Success: non-negative + * Failure: negative *------------------------------------------------------------------------- */ herr_t -H5Z__init_package(void) +H5Z_init(void) { herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_PACKAGE + FUNC_ENTER_NOAPI(FAIL) + + if (H5_TERM_GLOBAL) + HGOTO_DONE(SUCCEED) /* Internal filters */ if (H5Z_register(H5Z_SHUFFLE) < 0) @@ -111,7 +112,7 @@ H5Z__init_package(void) done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5Z__init_package() */ +} /*------------------------------------------------------------------------- * Function: H5Z_term_package @@ -128,76 +129,70 @@ H5Z_term_package(void) FUNC_ENTER_NOAPI_NOINIT_NOERR - if (H5_PKG_INIT_VAR) { #ifdef H5Z_DEBUG - char comment[16], bandwidth[32]; - int dir, nprint = 0; - size_t i; - - if (H5DEBUG(Z)) { - for (i = 0; i < H5Z_table_used_g; i++) { - for (dir = 0; dir < 2; dir++) { - struct { - char *user; - char *system; - char *elapsed; - } timestrs = {H5_timer_get_time_string(H5Z_stat_table_g[i].stats[dir].times.user), - H5_timer_get_time_string(H5Z_stat_table_g[i].stats[dir].times.system), - H5_timer_get_time_string(H5Z_stat_table_g[i].stats[dir].times.elapsed)}; - if (0 == H5Z_stat_table_g[i].stats[dir].total) - goto next; - - if (0 == nprint++) { - /* Print column headers */ - HDfprintf(H5DEBUG(Z), "H5Z: filter statistics " - "accumulated over life of library:\n"); - HDfprintf(H5DEBUG(Z), " %-16s %10s %10s %8s %8s %8s %10s\n", "Filter", "Total", - "Errors", "User", "System", "Elapsed", "Bandwidth"); - HDfprintf(H5DEBUG(Z), " %-16s %10s %10s %8s %8s %8s %10s\n", "------", "-----", - "------", "----", "------", "-------", "---------"); - } /* end if */ + char comment[16], bandwidth[32]; + int dir, nprint = 0; + size_t i; - /* Truncate the comment to fit in the field */ - HDstrncpy(comment, H5Z_table_g[i].name, sizeof comment); - comment[sizeof(comment) - 1] = '\0'; - - /* - * Format bandwidth to have four significant digits and - * units of `B/s', `kB/s', `MB/s', `GB/s', or `TB/s' or - * the word `Inf' if the elapsed time is zero. - */ - H5_bandwidth(bandwidth, (double)(H5Z_stat_table_g[i].stats[dir].total), - H5Z_stat_table_g[i].stats[dir].times.elapsed); - - /* Print the statistics */ - HDfprintf(H5DEBUG(Z), " %s%-15s %10" PRIdHSIZE " %10" PRIdHSIZE " %8s %8s %8s %10s\n", - (dir ? "<" : ">"), comment, H5Z_stat_table_g[i].stats[dir].total, - H5Z_stat_table_g[i].stats[dir].errors, timestrs.user, timestrs.system, - timestrs.elapsed, bandwidth); + if (H5DEBUG(Z)) { + for (i = 0; i < H5Z_table_used_g; i++) { + for (dir = 0; dir < 2; dir++) { + struct { + char *user; + char *system; + char *elapsed; + } timestrs = {H5_timer_get_time_string(H5Z_stat_table_g[i].stats[dir].times.user), + H5_timer_get_time_string(H5Z_stat_table_g[i].stats[dir].times.system), + H5_timer_get_time_string(H5Z_stat_table_g[i].stats[dir].times.elapsed)}; + if (0 == H5Z_stat_table_g[i].stats[dir].total) + goto next; + + if (0 == nprint++) { + /* Print column headers */ + HDfprintf(H5DEBUG(Z), "H5Z: filter statistics " + "accumulated over life of library:\n"); + HDfprintf(H5DEBUG(Z), " %-16s %10s %10s %8s %8s %8s %10s\n", "Filter", "Total", + "Errors", "User", "System", "Elapsed", "Bandwidth"); + HDfprintf(H5DEBUG(Z), " %-16s %10s %10s %8s %8s %8s %10s\n", "------", "-----", + "------", "----", "------", "-------", "---------"); + } /* end if */ + + /* Truncate the comment to fit in the field */ + HDstrncpy(comment, H5Z_table_g[i].name, sizeof comment); + comment[sizeof(comment) - 1] = '\0'; + + /* + * Format bandwidth to have four significant digits and + * units of `B/s', `kB/s', `MB/s', `GB/s', or `TB/s' or + * the word `Inf' if the elapsed time is zero. + */ + H5_bandwidth(bandwidth, (double)(H5Z_stat_table_g[i].stats[dir].total), + H5Z_stat_table_g[i].stats[dir].times.elapsed); + + /* Print the statistics */ + HDfprintf(H5DEBUG(Z), " %s%-15s %10" PRIdHSIZE " %10" PRIdHSIZE " %8s %8s %8s %10s\n", + (dir ? "<" : ">"), comment, H5Z_stat_table_g[i].stats[dir].total, + H5Z_stat_table_g[i].stats[dir].errors, timestrs.user, timestrs.system, + timestrs.elapsed, bandwidth); next: - HDfree(timestrs.user); - HDfree(timestrs.system); - HDfree(timestrs.elapsed); - } /* end for */ - } /* end for */ - } /* end if */ -#endif /* H5Z_DEBUG */ - - /* Free the table of filters */ - if (H5Z_table_g) { - H5Z_table_g = (H5Z_class2_t *)H5MM_xfree(H5Z_table_g); + HDfree(timestrs.user); + HDfree(timestrs.system); + HDfree(timestrs.elapsed); + } /* end for */ + } /* end for */ + } /* end if */ +#endif /* H5Z_DEBUG */ + + /* Free the table of filters */ + if (H5Z_table_g) { + H5Z_table_g = (H5Z_class2_t *)H5MM_xfree(H5Z_table_g); #ifdef H5Z_DEBUG - H5Z_stat_table_g = (H5Z_stats_t *)H5MM_xfree(H5Z_stat_table_g); + H5Z_stat_table_g = (H5Z_stats_t *)H5MM_xfree(H5Z_stat_table_g); #endif /* H5Z_DEBUG */ - H5Z_table_used_g = H5Z_table_alloc_g = 0; + H5Z_table_used_g = H5Z_table_alloc_g = 0; - n++; - } /* end if */ - - /* Mark interface as closed */ - if (0 == n) - H5_PKG_INIT_VAR = FALSE; + n++; } /* end if */ FUNC_LEAVE_NOAPI(n) @@ -599,14 +594,9 @@ H5Z__flush_file_cb(void *obj_ptr, hid_t H5_ATTR_UNUSED obj_id, void H5_ATTR_PARA /* Do a global flush if the file is opened for write */ if (H5F_ACC_RDWR & H5F_INTENT(f)) { -/* When parallel HDF5 is defined, check for collective metadata reads on this - * file and set the flag for metadata I/O in the API context. -QAK, 2018/02/14 - */ #ifdef H5_HAVE_PARALLEL /* Check if MPIO driver is used */ if (H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI)) { - H5P_coll_md_read_flag_t coll_md_read; /* Do all metadata reads collectively */ - /* Sanity check for collectively calling H5Zunregister, if requested */ /* (Sanity check assumes that a barrier on one file's comm * is sufficient (i.e. that there aren't different comms for @@ -626,13 +616,8 @@ H5Z__flush_file_cb(void *obj_ptr, hid_t H5_ATTR_UNUSED obj_id, void H5_ATTR_PARA /* Set the "sanity checked" flag */ object->sanity_checked = TRUE; } /* end if */ - - /* Check whether to use the collective metadata read DXPL */ - coll_md_read = H5F_COLL_MD_READ(f); - if (H5P_USER_TRUE == coll_md_read) - H5CX_set_coll_metadata_read(TRUE); - } /* end if */ -#endif /* H5_HAVE_PARALLEL */ + } /* end if */ +#endif /* H5_HAVE_PARALLEL */ /* Call the flush routine for mounted file hierarchies */ if (H5F_flush_mounts((H5F_t *)obj_ptr) < 0) @@ -1506,7 +1491,7 @@ done: /*------------------------------------------------------------------------- * Function: H5Z_filter_in_pline * - * Purpose: Check wheter a filter is in the filter pipeline using the + * Purpose: Check whether a filter is in the filter pipeline using the * filter ID. This function is very similar to H5Z_filter_info * * Return: TRUE - found filter @@ -1520,7 +1505,7 @@ H5Z_filter_in_pline(const H5O_pline_t *pline, H5Z_filter_t filter) size_t idx; /* Index of filter in pipeline */ htri_t ret_value = TRUE; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR HDassert(pline); HDassert(filter >= 0 && filter <= H5Z_FILTER_MAX); @@ -1534,7 +1519,6 @@ H5Z_filter_in_pline(const H5O_pline_t *pline, H5Z_filter_t filter) if (idx >= pline->nused) ret_value = FALSE; -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5Z_filter_in_pline() */ @@ -1554,7 +1538,7 @@ H5Z_all_filters_avail(const H5O_pline_t *pline) size_t i, j; /* Local index variable */ htri_t ret_value = TRUE; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR /* Check args */ HDassert(pline); diff --git a/src/H5Znbit.c b/src/H5Znbit.c index b696085..905d417 100644 --- a/src/H5Znbit.c +++ b/src/H5Znbit.c @@ -975,7 +975,7 @@ H5Z__filter_nbit(unsigned flags, size_t cd_nelmts, const unsigned cd_values[], s /* input; decompress */ if (flags & H5Z_FLAG_REVERSE) { - size_out = d_nelmts * cd_values[4]; /* cd_values[4] stores datatype size */ + size_out = d_nelmts * (size_t)cd_values[4]; /* cd_values[4] stores datatype size */ /* allocate memory space for decompressed buffer */ if (NULL == (outbuf = (unsigned char *)H5MM_malloc(size_out))) @@ -1015,7 +1015,7 @@ done: * assume one byte has 8 bit * assume padding bit is 0 * assume size of unsigned char is one byte - * assume one data item of certain datatype is stored continously in bytes + * assume one data item of certain datatype is stored continuously in bytes * atomic datatype is treated on byte basis */ @@ -1170,7 +1170,8 @@ H5Z__nbit_decompress_one_array(unsigned char *data, size_t data_offset, unsigned n = total_size / p.size; for (i = 0; i < n; i++) - H5Z__nbit_decompress_one_atomic(data, data_offset + i * p.size, buffer, j, buf_len, &p); + H5Z__nbit_decompress_one_atomic(data, data_offset + i * (size_t)p.size, buffer, j, buf_len, + &p); break; case H5Z_NBIT_ARRAY: @@ -1178,8 +1179,8 @@ H5Z__nbit_decompress_one_array(unsigned char *data, size_t data_offset, unsigned n = total_size / base_size; /* number of base_type elements inside the array datatype */ begin_index = *parms_index; for (i = 0; i < n; i++) { - if (H5Z__nbit_decompress_one_array(data, data_offset + i * base_size, buffer, j, buf_len, - parms, parms_index) < 0) + if (H5Z__nbit_decompress_one_array(data, data_offset + i * (size_t)base_size, buffer, j, + buf_len, parms, parms_index) < 0) HGOTO_ERROR(H5E_PLINE, H5E_CANTFILTER, FAIL, "can't decompress array") *parms_index = begin_index; } @@ -1190,8 +1191,8 @@ H5Z__nbit_decompress_one_array(unsigned char *data, size_t data_offset, unsigned n = total_size / base_size; /* number of base_type elements inside the array datatype */ begin_index = *parms_index; for (i = 0; i < n; i++) { - if (H5Z__nbit_decompress_one_compound(data, data_offset + i * base_size, buffer, j, buf_len, - parms, parms_index) < 0) + if (H5Z__nbit_decompress_one_compound(data, data_offset + i * (size_t)base_size, buffer, j, + buf_len, parms, parms_index) < 0) HGOTO_ERROR(H5E_PLINE, H5E_CANTFILTER, FAIL, "can't decompress compound") *parms_index = begin_index; } @@ -1291,7 +1292,7 @@ H5Z__nbit_decompress(unsigned char *data, unsigned d_nelmts, unsigned char *buff FUNC_ENTER_STATIC /* may not have to initialize to zeros */ - HDmemset(data, 0, d_nelmts * parms[4]); + HDmemset(data, 0, d_nelmts * (size_t)parms[4]); /* initialization before the loop */ j = 0; @@ -1309,7 +1310,7 @@ H5Z__nbit_decompress(unsigned char *data, unsigned d_nelmts, unsigned char *buff HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "invalid datatype precision/offset") for (i = 0; i < d_nelmts; i++) - H5Z__nbit_decompress_one_atomic(data, i * p.size, buffer, &j, &buf_len, &p); + H5Z__nbit_decompress_one_atomic(data, i * (size_t)p.size, buffer, &j, &buf_len, &p); break; case H5Z_NBIT_ARRAY: @@ -1468,7 +1469,7 @@ H5Z__nbit_compress_one_array(unsigned char *data, size_t data_offset, unsigned c p.offset = parms[(*parms_index)++]; n = total_size / p.size; for (i = 0; i < n; i++) - H5Z__nbit_compress_one_atomic(data, data_offset + i * p.size, buffer, j, buf_len, &p); + H5Z__nbit_compress_one_atomic(data, data_offset + i * (size_t)p.size, buffer, j, buf_len, &p); break; case H5Z_NBIT_ARRAY: @@ -1476,8 +1477,8 @@ H5Z__nbit_compress_one_array(unsigned char *data, size_t data_offset, unsigned c n = total_size / base_size; /* number of base_type elements inside the array datatype */ begin_index = *parms_index; for (i = 0; i < n; i++) { - H5Z__nbit_compress_one_array(data, data_offset + i * base_size, buffer, j, buf_len, parms, - parms_index); + H5Z__nbit_compress_one_array(data, data_offset + i * (size_t)base_size, buffer, j, buf_len, + parms, parms_index); *parms_index = begin_index; } break; @@ -1487,8 +1488,8 @@ H5Z__nbit_compress_one_array(unsigned char *data, size_t data_offset, unsigned c n = total_size / base_size; /* number of base_type elements inside the array datatype */ begin_index = *parms_index; for (i = 0; i < n; i++) { - H5Z__nbit_compress_one_compound(data, data_offset + i * base_size, buffer, j, buf_len, parms, - parms_index); + H5Z__nbit_compress_one_compound(data, data_offset + i * (size_t)base_size, buffer, j, buf_len, + parms, parms_index); *parms_index = begin_index; } break; @@ -1574,7 +1575,7 @@ H5Z__nbit_compress(unsigned char *data, unsigned d_nelmts, unsigned char *buffer p.offset = parms[7]; for (i = 0; i < d_nelmts; i++) - H5Z__nbit_compress_one_atomic(data, i * p.size, buffer, &new_size, &buf_len, &p); + H5Z__nbit_compress_one_atomic(data, i * (size_t)p.size, buffer, &new_size, &buf_len, &p); break; case H5Z_NBIT_ARRAY: diff --git a/src/H5Zscaleoffset.c b/src/H5Zscaleoffset.c index a8a63bf..46c1a10 100644 --- a/src/H5Zscaleoffset.c +++ b/src/H5Zscaleoffset.c @@ -364,12 +364,12 @@ H5Z_class2_t H5Z_SCALEOFFSET[1] = {{ #define H5Z_scaleoffset_max_min_3(i, d_nelmts, buf, filval, max, min, D_val) \ { \ i = 0; \ - while (i < d_nelmts && HDfabs(buf[i] - filval) < HDpow(10.0, -D_val)) \ + while (i < d_nelmts && HDfabs((double)(buf[i] - filval)) < HDpow(10.0, -D_val)) \ i++; \ if (i < d_nelmts) \ min = max = buf[i]; \ for (; i < d_nelmts; i++) { \ - if (HDfabs(buf[i] - filval) < HDpow(10.0, -D_val)) \ + if (HDfabs((double)(buf[i] - filval)) < HDpow(10.0, -D_val)) \ continue; /* ignore fill value */ \ if (buf[i] > max) \ max = buf[i]; \ @@ -425,22 +425,22 @@ H5Z_class2_t H5Z_SCALEOFFSET[1] = {{ #define H5Z_scaleoffset_check_3(i, type, pow_fun, round_fun, max, min, minbits, D_val) \ { \ if (sizeof(type) == sizeof(int)) { \ - if (round_fun(max * pow_fun(10.0F, (type)D_val) - min * pow_fun(10.0F, (type)D_val)) > \ - pow_fun(2.0F, (type)(sizeof(int) * 8 - 1))) { \ + if (round_fun(max * pow_fun((type)10, (type)D_val) - min * pow_fun((type)10, (type)D_val)) > \ + pow_fun((type)2, (type)(sizeof(int) * 8 - 1))) { \ *minbits = sizeof(int) * 8; \ goto done; \ } \ } \ else if (sizeof(type) == sizeof(long)) { \ - if (round_fun(max * pow_fun(10.0F, (type)D_val) - min * pow_fun(10.0F, (type)D_val)) > \ - pow_fun(2.0F, (type)(sizeof(long) * 8 - 1))) { \ + if (round_fun(max * pow_fun((type)10, (type)D_val) - min * pow_fun((type)10, (type)D_val)) > \ + pow_fun((type)2, (type)(sizeof(long) * 8 - 1))) { \ *minbits = sizeof(long) * 8; \ goto done; \ } \ } \ else if (sizeof(type) == sizeof(long long)) { \ - if (round_fun(max * pow_fun(10.0F, (type)D_val) - min * pow_fun(10.0F, (type)D_val)) > \ - pow_fun(2.0F, (type)(sizeof(long long) * 8 - 1))) { \ + if (round_fun(max * pow_fun((type)10, (type)D_val) - min * pow_fun((type)10, (type)D_val)) > \ + pow_fun((type)2, (type)(sizeof(long long) * 8 - 1))) { \ *minbits = sizeof(long long) * 8; \ goto done; \ } \ @@ -530,27 +530,27 @@ H5Z_class2_t H5Z_SCALEOFFSET[1] = {{ { \ if (sizeof(type) == sizeof(int)) \ for (i = 0; i < d_nelmts; i++) { \ - if (abs_fun(buf[i] - filval) < pow_fun(10.0F, (type)-D_val)) \ + if (abs_fun(buf[i] - filval) < pow_fun((type)10, (type)-D_val)) \ *(int *)((void *)&buf[i]) = (int)(((unsigned int)1 << *minbits) - 1); \ else \ - *(int *)((void *)&buf[i]) = (int)lround_fun(buf[i] * pow_fun(10.0F, (type)D_val) - \ - min * pow_fun(10.0F, (type)D_val)); \ + *(int *)((void *)&buf[i]) = (int)lround_fun(buf[i] * pow_fun((type)10, (type)D_val) - \ + min * pow_fun((type)10, (type)D_val)); \ } \ else if (sizeof(type) == sizeof(long)) \ for (i = 0; i < d_nelmts; i++) { \ - if (abs_fun(buf[i] - filval) < pow_fun(10.0F, (type)-D_val)) \ + if (abs_fun(buf[i] - filval) < pow_fun((type)10, (type)-D_val)) \ *(long *)((void *)&buf[i]) = (long)(((unsigned long)1 << *minbits) - 1); \ else \ - *(long *)((void *)&buf[i]) = lround_fun(buf[i] * pow_fun(10.0F, (type)D_val) - \ - min * pow_fun(10.0F, (type)D_val)); \ + *(long *)((void *)&buf[i]) = lround_fun(buf[i] * pow_fun((type)10, (type)D_val) - \ + min * pow_fun((type)10, (type)D_val)); \ } \ else if (sizeof(type) == sizeof(long long)) \ for (i = 0; i < d_nelmts; i++) { \ - if (abs_fun(buf[i] - filval) < pow_fun(10.0F, (type)-D_val)) \ + if (abs_fun(buf[i] - filval) < pow_fun((type)10, (type)-D_val)) \ *(long long *)((void *)&buf[i]) = (long long)(((unsigned long long)1 << *minbits) - 1); \ else \ - *(long long *)((void *)&buf[i]) = llround_fun(buf[i] * pow_fun(10.0F, (type)D_val) - \ - min * pow_fun(10.0F, (type)D_val)); \ + *(long long *)((void *)&buf[i]) = llround_fun(buf[i] * pow_fun((type)10, (type)D_val) - \ + min * pow_fun((type)10, (type)D_val)); \ } \ else \ HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "cannot find matched integer dataype") \ @@ -561,16 +561,16 @@ H5Z_class2_t H5Z_SCALEOFFSET[1] = {{ { \ if (sizeof(type) == sizeof(int)) \ for (i = 0; i < d_nelmts; i++) \ - *(int *)((void *)&buf[i]) = (int)lround_fun(buf[i] * pow_fun(10.0F, (type)D_val) - \ - min * pow_fun(10.0F, (type)D_val)); \ + *(int *)((void *)&buf[i]) = (int)lround_fun(buf[i] * pow_fun((type)10, (type)D_val) - \ + min * pow_fun((type)10, (type)D_val)); \ else if (sizeof(type) == sizeof(long)) \ for (i = 0; i < d_nelmts; i++) \ - *(long *)((void *)&buf[i]) = \ - lround_fun(buf[i] * pow_fun(10.0F, (type)D_val) - min * pow_fun(10.0F, (type)D_val)); \ + *(long *)((void *)&buf[i]) = lround_fun(buf[i] * pow_fun((type)10, (type)D_val) - \ + min * pow_fun((type)10, (type)D_val)); \ else if (sizeof(type) == sizeof(long long)) \ for (i = 0; i < d_nelmts; i++) \ - *(long long *)((void *)&buf[i]) = \ - llround_fun(buf[i] * pow_fun(10.0F, (type)D_val) - min * pow_fun(10.0F, (type)D_val)); \ + *(long long *)((void *)&buf[i]) = llround_fun(buf[i] * pow_fun((type)10, (type)D_val) - \ + min * pow_fun((type)10, (type)D_val)); \ else \ HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "cannot find matched integer dataype") \ } @@ -606,8 +606,8 @@ H5Z_class2_t H5Z_SCALEOFFSET[1] = {{ H5Z_scaleoffset_get_filval_2(type, cd_values, filval) \ H5Z_scaleoffset_max_min_3(i, d_nelmts, buf, filval, max, min, D_val) \ H5Z_scaleoffset_check_3(i, type, pow_fun, round_fun, max, min, minbits, D_val) span = \ - (unsigned long long)(llround_fun(max * pow_fun(10.0F, (type)D_val) - \ - min * pow_fun(10.0F, (type)D_val)) + \ + (unsigned long long)(llround_fun(max * pow_fun((type)10, (type)D_val) - \ + min * pow_fun((type)10, (type)D_val)) + \ 1); \ *minbits = H5Z__scaleoffset_log2(span + 1); \ if (*minbits != sizeof(type) * 8) /* change values if minbits != full precision */ \ @@ -617,8 +617,8 @@ H5Z_class2_t H5Z_SCALEOFFSET[1] = {{ else { /* fill value undefined */ \ H5Z_scaleoffset_max_min_2(i, d_nelmts, buf, max, min) \ H5Z_scaleoffset_check_3(i, type, pow_fun, round_fun, max, min, minbits, D_val) span = \ - (unsigned long long)(llround_fun(max * pow_fun(10.0F, (type)D_val) - \ - min * pow_fun(10.0F, (type)D_val)) + \ + (unsigned long long)(llround_fun(max * pow_fun((type)10, (type)D_val) - \ + min * pow_fun((type)10, (type)D_val)) + \ 1); \ *minbits = H5Z__scaleoffset_log2(span); \ if (*minbits != sizeof(type) * 8) /* change values if minbits != full precision */ \ @@ -659,7 +659,7 @@ H5Z_class2_t H5Z_SCALEOFFSET[1] = {{ buf[i] = (type)(buf[i] + (type)(minval)); \ } while (0) -/* Retrive minimum value of floating-point type */ +/* Retrieve minimum value of floating-point type */ #define H5Z_scaleoffset_get_min(type, minval, min) \ { \ if (sizeof(type) <= sizeof(long long)) \ @@ -685,19 +685,19 @@ H5Z_class2_t H5Z_SCALEOFFSET[1] = {{ buf[i] = \ (type)((*(int *)((void *)&buf[i]) == (int)(((unsigned int)1 << minbits) - 1)) \ ? filval \ - : (type)(*(int *)((void *)&buf[i])) / pow_fun(10.0F, (type)D_val) + min); \ + : (type)(*(int *)((void *)&buf[i])) / pow_fun((type)10, (type)D_val) + min); \ else if (sizeof(type) == sizeof(long)) \ for (i = 0; i < d_nelmts; i++) \ buf[i] = \ (type)((*(long *)((void *)&buf[i]) == (long)(((unsigned long)1 << minbits) - 1)) \ ? filval \ - : (type)(*(long *)((void *)&buf[i])) / pow_fun(10.0F, (type)D_val) + min); \ + : (type)(*(long *)((void *)&buf[i])) / pow_fun((type)10, (type)D_val) + min); \ else if (sizeof(type) == sizeof(long long)) \ for (i = 0; i < d_nelmts; i++) \ buf[i] = (type)( \ (*(long long *)((void *)&buf[i]) == (long long)(((unsigned long long)1 << minbits) - 1)) \ ? filval \ - : (type)(*(long long *)((void *)&buf[i])) / pow_fun(10.0F, (type)D_val) + min); \ + : (type)(*(long long *)((void *)&buf[i])) / pow_fun((type)10, (type)D_val) + min); \ else \ HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "cannot find matched integer dataype") \ } @@ -707,13 +707,13 @@ H5Z_class2_t H5Z_SCALEOFFSET[1] = {{ { \ if (sizeof(type) == sizeof(int)) \ for (i = 0; i < d_nelmts; i++) \ - buf[i] = ((type)(*(int *)((void *)&buf[i])) / pow_fun(10.0F, (type)D_val) + min); \ + buf[i] = ((type)(*(int *)((void *)&buf[i])) / pow_fun((type)10, (type)D_val) + min); \ else if (sizeof(type) == sizeof(long)) \ for (i = 0; i < d_nelmts; i++) \ - buf[i] = ((type)(*(long *)((void *)&buf[i])) / pow_fun(10.0F, (type)D_val) + min); \ + buf[i] = ((type)(*(long *)((void *)&buf[i])) / pow_fun((type)10, (type)D_val) + min); \ else if (sizeof(type) == sizeof(long long)) \ for (i = 0; i < d_nelmts; i++) \ - buf[i] = ((type)(*(long long *)((void *)&buf[i])) / pow_fun(10.0F, (type)D_val) + min); \ + buf[i] = ((type)(*(long long *)((void *)&buf[i])) / pow_fun((type)10, (type)D_val) + min); \ else \ HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "cannot find matched integer dataype") \ } @@ -1205,7 +1205,7 @@ H5Z__filter_scaleoffset(unsigned flags, size_t cd_nelmts, const unsigned cd_valu /* prepare parameters to pass to compress/decompress functions */ p.size = cd_values[H5Z_SCALEOFFSET_PARM_SIZE]; - p.mem_order = H5T_native_order_g; + p.mem_order = (unsigned)H5T_native_order_g; /* input; decompress */ if (flags & H5Z_FLAG_REVERSE) { @@ -1240,7 +1240,7 @@ H5Z__filter_scaleoffset(unsigned flags, size_t cd_nelmts, const unsigned cd_valu p.minbits = minbits; /* calculate size of output buffer after decompression */ - size_out = d_nelmts * p.size; + size_out = d_nelmts * (size_t)p.size; /* allocate memory space for decompressed buffer */ if (NULL == (outbuf = (unsigned char *)H5MM_malloc(size_out))) @@ -1388,7 +1388,7 @@ done: * assume one byte has 8 bit * assume padding bit is 0 * assume size of unsigned char is one byte - * assume one data item of certain datatype is stored continously in bytes + * assume one data item of certain datatype is stored continuously in bytes * atomic datatype is treated on byte basis */ @@ -1403,7 +1403,7 @@ H5Z__scaleoffset_convert(void *buf, unsigned d_nelmts, unsigned dtype_size) unsigned char *buffer, temp; buffer = (unsigned char *)buf; - for (i = 0; i < d_nelmts * dtype_size; i += dtype_size) + for (i = 0; i < d_nelmts * (size_t)dtype_size; i += dtype_size) for (j = 0; j < dtype_size / 2; j++) { /* swap pair of bytes */ temp = buffer[i + j]; @@ -1681,7 +1681,7 @@ H5Z__scaleoffset_decompress(unsigned char *data, unsigned d_nelmts, unsigned cha unsigned buf_len; /* must initialize to zeros */ - for (i = 0; i < d_nelmts * p.size; i++) + for (i = 0; i < d_nelmts * (size_t)p.size; i++) data[i] = 0; /* initialization before the loop */ diff --git a/src/H5Ztrans.c b/src/H5Ztrans.c index ab7e9be..092b289 100644 --- a/src/H5Ztrans.c +++ b/src/H5Ztrans.c @@ -150,7 +150,6 @@ static void H5Z__xform_reduce_tree(H5Z_node *tree); HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Unexpected type conversion operation") \ } -#if H5_SIZEOF_LONG_DOUBLE != 0 #if CHAR_MIN >= 0 #define H5Z_XFORM_TYPE_OP(RESL, RESR, TYPE, OP, SIZE) \ { \ @@ -212,65 +211,6 @@ static void H5Z__xform_reduce_tree(H5Z_node *tree); H5Z_XFORM_DO_OP1((RESL), (RESR), long double, OP, (SIZE)) \ } #endif /* CHAR_MIN >= 0 */ -#else -#if CHAR_MIN >= 0 -#define H5Z_XFORM_TYPE_OP(RESL, RESR, TYPE, OP, SIZE) \ - { \ - if ((TYPE) == H5T_NATIVE_CHAR) \ - H5Z_XFORM_DO_OP1((RESL), (RESR), char, OP, (SIZE)) \ - else if ((TYPE) == H5T_NATIVE_SCHAR) \ - H5Z_XFORM_DO_OP1((RESL), (RESR), signed char, OP, (SIZE)) \ - else if ((TYPE) == H5T_NATIVE_SHORT) \ - H5Z_XFORM_DO_OP1((RESL), (RESR), short, OP, (SIZE)) \ - else if ((TYPE) == H5T_NATIVE_USHORT) \ - H5Z_XFORM_DO_OP1((RESL), (RESR), unsigned short, OP, (SIZE)) \ - else if ((TYPE) == H5T_NATIVE_INT) \ - H5Z_XFORM_DO_OP1((RESL), (RESR), int, OP, (SIZE)) \ - else if ((TYPE) == H5T_NATIVE_UINT) \ - H5Z_XFORM_DO_OP1((RESL), (RESR), unsigned int, OP, (SIZE)) \ - else if ((TYPE) == H5T_NATIVE_LONG) \ - H5Z_XFORM_DO_OP1((RESL), (RESR), long, OP, (SIZE)) \ - else if ((TYPE) == H5T_NATIVE_ULONG) \ - H5Z_XFORM_DO_OP1((RESL), (RESR), unsigned long, OP, (SIZE)) \ - else if ((TYPE) == H5T_NATIVE_LLONG) \ - H5Z_XFORM_DO_OP1((RESL), (RESR), long long, OP, (SIZE)) \ - else if ((TYPE) == H5T_NATIVE_ULLONG) \ - H5Z_XFORM_DO_OP1((RESL), (RESR), unsigned long long, OP, (SIZE)) \ - else if ((TYPE) == H5T_NATIVE_FLOAT) \ - H5Z_XFORM_DO_OP1((RESL), (RESR), float, OP, (SIZE)) \ - else if ((TYPE) == H5T_NATIVE_DOUBLE) \ - H5Z_XFORM_DO_OP1((RESL), (RESR), double, OP, (SIZE)) \ - } -#else /* CHAR_MIN >= 0 */ -#define H5Z_XFORM_TYPE_OP(RESL, RESR, TYPE, OP, SIZE) \ - { \ - if ((TYPE) == H5T_NATIVE_CHAR) \ - H5Z_XFORM_DO_OP1((RESL), (RESR), char, OP, (SIZE)) \ - else if ((TYPE) == H5T_NATIVE_UCHAR) \ - H5Z_XFORM_DO_OP1((RESL), (RESR), unsigned char, OP, (SIZE)) \ - else if ((TYPE) == H5T_NATIVE_SHORT) \ - H5Z_XFORM_DO_OP1((RESL), (RESR), short, OP, (SIZE)) \ - else if ((TYPE) == H5T_NATIVE_USHORT) \ - H5Z_XFORM_DO_OP1((RESL), (RESR), unsigned short, OP, (SIZE)) \ - else if ((TYPE) == H5T_NATIVE_INT) \ - H5Z_XFORM_DO_OP1((RESL), (RESR), int, OP, (SIZE)) \ - else if ((TYPE) == H5T_NATIVE_UINT) \ - H5Z_XFORM_DO_OP1((RESL), (RESR), unsigned int, OP, (SIZE)) \ - else if ((TYPE) == H5T_NATIVE_LONG) \ - H5Z_XFORM_DO_OP1((RESL), (RESR), long, OP, (SIZE)) \ - else if ((TYPE) == H5T_NATIVE_ULONG) \ - H5Z_XFORM_DO_OP1((RESL), (RESR), unsigned long, OP, (SIZE)) \ - else if ((TYPE) == H5T_NATIVE_LLONG) \ - H5Z_XFORM_DO_OP1((RESL), (RESR), long long, OP, (SIZE)) \ - else if ((TYPE) == H5T_NATIVE_ULLONG) \ - H5Z_XFORM_DO_OP1((RESL), (RESR), unsigned long long, OP, (SIZE)) \ - else if ((TYPE) == H5T_NATIVE_FLOAT) \ - H5Z_XFORM_DO_OP1((RESL), (RESR), float, OP, (SIZE)) \ - else if ((TYPE) == H5T_NATIVE_DOUBLE) \ - H5Z_XFORM_DO_OP1((RESL), (RESR), double, OP, (SIZE)) \ - } -#endif /* CHAR_MIN >= 0 */ -#endif /*H5_SIZEOF_LONG_DOUBLE */ #define H5Z_XFORM_DO_OP3(OP) \ { \ @@ -1056,10 +996,8 @@ H5Z_xform_eval(H5Z_data_xform_t *data_xform_prop, void *array, size_t array_size H5Z_XFORM_DO_OP5(float, array_size) else if (array_type == H5T_NATIVE_DOUBLE) H5Z_XFORM_DO_OP5(double, array_size) -#if H5_SIZEOF_LONG_DOUBLE != 0 else if (array_type == H5T_NATIVE_LDOUBLE) H5Z_XFORM_DO_OP5(long double, array_size) -#endif } /* end if */ /* Otherwise, do the full data transform */ @@ -1267,11 +1205,9 @@ H5Z__xform_find_type(const H5T_t *type) /* Check for DOUBLE type */ else if ((tmp = (H5T_t *)H5I_object(H5T_NATIVE_DOUBLE)) && 0 == H5T_cmp(type, tmp, FALSE)) HGOTO_DONE(H5T_NATIVE_DOUBLE) -#if H5_SIZEOF_LONG_DOUBLE != 0 /* Check for LONGDOUBLE type */ else if ((tmp = (H5T_t *)H5I_object(H5T_NATIVE_LDOUBLE)) && 0 == H5T_cmp(type, tmp, FALSE)) HGOTO_DONE(H5T_NATIVE_LDOUBLE) -#endif else HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "could not find matching type") @@ -1416,7 +1352,7 @@ H5Z__op_is_numbs2(H5Z_node *_tree) * Function: H5Z__xform_reduce_tree * * Purpose: Simplifies parse tree passed in by performing any obvious - * and trivial arithemtic calculations. + * and trivial arithmetic calculations. * * Return: None. * @@ -1756,7 +1692,7 @@ H5Z_xform_noop(const H5Z_data_xform_t *data_xform_prop) if (data_xform_prop) { ret_value = FALSE; - /* Check for trivial data tranformation: expression = "x" */ + /* Check for trivial data transformation: expression = "x" */ if ((HDstrlen(data_xform_prop->xform_exp) == 1) && data_xform_prop->dat_val_pointers && (data_xform_prop->dat_val_pointers->num_ptrs == 1)) { ret_value = TRUE; @@ -1787,7 +1723,7 @@ H5Z_xform_extract_xform_str(const H5Z_data_xform_t *data_xform_prop) /* There should be no way that this can be NULL since the function * that calls this one checks to make sure it isn't before - * pasing them */ + * passing them */ HDassert(data_xform_prop); FUNC_LEAVE_NOAPI(data_xform_prop->xform_exp) diff --git a/src/H5detect.c b/src/H5detect.c index e8cded7..e72d7a0 100644 --- a/src/H5detect.c +++ b/src/H5detect.c @@ -772,7 +772,7 @@ done:\n\ fprintf(rawoutstream, "/* sigprocmask() support: no */\n"); #endif - /* Print the statics of signal handlers called for debugging */ + /* Print the statistics of signal handlers called for debugging */ fprintf(rawoutstream, "\n" "/******************************/\n" "/* signal handlers statistics */\n" @@ -1412,7 +1412,7 @@ detect_C99_floats(void) */ DETECT_F(double, LDOUBLE, d_g[nd_g]); nd_g++; -#elif H5_SIZEOF_LONG_DOUBLE != 0 +#else DETECT_F(long double, LDOUBLE, d_g[nd_g]); nd_g++; #endif @@ -1475,7 +1475,7 @@ verify_signal_handlers(int signum, void (*handler)(int)) } else { if (val == signum) { - /* return from signum handler. Record a sucess. */ + /* return from signum handler. Record a success. */ nsuccesses++; } else { diff --git a/src/H5module.h b/src/H5module.h index 6d3cba8..f7d3cd6 100644 --- a/src/H5module.h +++ b/src/H5module.h @@ -11,9 +11,9 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Purpose: This file contains declarations which define macros for the - * H5 package. Including this header means that the source file - * is part of the H5 package. + * Purpose: This file contains declarations which define macros for the + * H5 package. Including this header means that the source file + * is part of the H5 package. */ #ifndef H5module_H #define H5module_H diff --git a/src/H5mpi.c b/src/H5mpi.c index 4a8aa44..f5d709a 100644 --- a/src/H5mpi.c +++ b/src/H5mpi.c @@ -38,7 +38,7 @@ static hsize_t bigio_count_g = H5_MAX_MPI_COUNT; /*------------------------------------------------------------------------- * Function: H5_mpi_set_bigio_count * - * Purpose: Allow us to programatically change the switch point + * Purpose: Allow us to programmatically change the switch point * when we utilize derived datatypes. This is of * particular interest for allowing nightly testing * @@ -549,4 +549,237 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5_mpio_create_large_type() */ +/*------------------------------------------------------------------------- + * Function: H5_mpio_gatherv_alloc + * + * Purpose: A wrapper around MPI_(All)gatherv that performs allocation + * of the receive buffer on the caller's behalf. This + * routine's parameters are as follows: + * + * `send_buf` - The buffer that data will be sent from for + * the calling MPI rank. Analogous to + * MPI_(All)gatherv's `sendbuf` parameter. + * + * `send_count` - The number of `send_type` elements in the + * send buffer. Analogous to MPI_(All)gatherv's + * `sendcount` parameter. + * + * `send_type` - The MPI Datatype of the elements in the send + * buffer. Analogous to MPI_(All)gatherv's + * `sendtype` parameter. + * + * `recv_counts` - An array containing the number of elements + * to be received from each MPI rank. + * Analogous to MPI_(All)gatherv's `recvcount` + * parameter. + * + * `displacements` - An array containing the displacements + * in the receive buffer where data from + * each MPI rank should be placed. Analogous + * to MPI_(All)gatherv's `displs` parameter. + * + * `recv_type` - The MPI Datatype of the elements in the + * receive buffer. Analogous to + * MPI_(All)gatherv's `recvtype` parameter. + * + * `allgather` - Specifies whether the gather operation to be + * performed should be MPI_Allgatherv (TRUE) or + * MPI_Gatherv (FALSE). + * + * `root` - For MPI_Gatherv operations, specifies the rank + * that will receive the data sent by other ranks. + * Analogous to MPI_Gatherv's `root` parameter. For + * MPI_Allgatherv operations, this parameter is + * ignored. + * + * `comm` - Specifies the MPI Communicator for the operation. + * Analogous to MPI_(All)gatherv's `comm` parameter. + * + * `mpi_rank` - Specifies the calling rank's rank value, as + * obtained by calling MPI_Comm_rank on the + * MPI Communicator `comm`. + * + * `mpi_size` - Specifies the MPI Communicator size, as + * obtained by calling MPI_Comm_size on the + * MPI Communicator `comm`. + * + * `out_buf` - Resulting buffer that is allocated and + * returned to the caller after data has been + * gathered into it. Returned only to the rank + * specified by `root` for MPI_Gatherv + * operations, or to all ranks for + * MPI_Allgatherv operations. + * + * `out_buf_num_entries` - The number of elements in the + * resulting buffer, in terms of + * the MPI Datatype provided for + * `recv_type`. + * + * Notes: This routine is collective across `comm`. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5_mpio_gatherv_alloc(void *send_buf, int send_count, MPI_Datatype send_type, const int recv_counts[], + const int displacements[], MPI_Datatype recv_type, hbool_t allgather, int root, + MPI_Comm comm, int mpi_rank, int mpi_size, void **out_buf, size_t *out_buf_num_entries) +{ + size_t recv_buf_num_entries = 0; + void * recv_buf = NULL; +#if H5_CHECK_MPI_VERSION(3, 0) + MPI_Count type_lb; + MPI_Count type_extent; +#else + MPI_Aint type_lb; + MPI_Aint type_extent; +#endif + int mpi_code; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(FAIL) + + HDassert(send_buf || send_count == 0); + if (allgather || (mpi_rank == root)) + HDassert(out_buf && out_buf_num_entries); + + /* Retrieve the extent of the MPI Datatype being used */ +#if H5_CHECK_MPI_VERSION(3, 0) + if (MPI_SUCCESS != (mpi_code = MPI_Type_get_extent_x(recv_type, &type_lb, &type_extent))) +#else + if (MPI_SUCCESS != (mpi_code = MPI_Type_get_extent(recv_type, &type_lb, &type_extent))) +#endif + HMPI_GOTO_ERROR(FAIL, "MPI_Type_get_extent(_x) failed", mpi_code) + + if (type_extent < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "MPI recv_type had a negative extent") + + /* + * Calculate the total size of the buffer being + * returned and allocate it + */ + if (allgather || (mpi_rank == root)) { + size_t i; + size_t buf_size; + + for (i = 0, recv_buf_num_entries = 0; i < (size_t)mpi_size; i++) + recv_buf_num_entries += (size_t)recv_counts[i]; + buf_size = recv_buf_num_entries * (size_t)type_extent; + + /* If our buffer size is 0, there's nothing to do */ + if (buf_size == 0) + HGOTO_DONE(SUCCEED) + + if (NULL == (recv_buf = H5MM_malloc(buf_size))) + /* Push an error, but still participate in collective gather operation */ + HDONE_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "couldn't allocate receive buffer") + } + + /* Perform gather operation */ + if (allgather) { + if (MPI_SUCCESS != (mpi_code = MPI_Allgatherv(send_buf, send_count, send_type, recv_buf, recv_counts, + displacements, recv_type, comm))) + HMPI_GOTO_ERROR(FAIL, "MPI_Allgatherv failed", mpi_code) + } + else { + if (MPI_SUCCESS != (mpi_code = MPI_Gatherv(send_buf, send_count, send_type, recv_buf, recv_counts, + displacements, recv_type, root, comm))) + HMPI_GOTO_ERROR(FAIL, "MPI_Gatherv failed", mpi_code) + } + + if (allgather || (mpi_rank == root)) { + *out_buf = recv_buf; + *out_buf_num_entries = recv_buf_num_entries; + } + +done: + if (ret_value < 0) { + if (recv_buf) + H5MM_free(recv_buf); + } + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5_mpio_gatherv_alloc() */ + +/*------------------------------------------------------------------------- + * Function: H5_mpio_gatherv_alloc_simple + * + * Purpose: A slightly simplified interface to H5_mpio_gatherv_alloc + * which calculates the receive counts and receive buffer + * displacements for the caller. + * + * Notes: This routine is collective across `comm`. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5_mpio_gatherv_alloc_simple(void *send_buf, int send_count, MPI_Datatype send_type, MPI_Datatype recv_type, + hbool_t allgather, int root, MPI_Comm comm, int mpi_rank, int mpi_size, + void **out_buf, size_t *out_buf_num_entries) +{ + int * recv_counts_disps_array = NULL; + int mpi_code; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(FAIL) + + HDassert(send_buf || send_count == 0); + if (allgather || (mpi_rank == root)) + HDassert(out_buf && out_buf_num_entries); + + /* + * Allocate array to store the receive counts of each rank, as well as + * the displacements into the final array where each rank will place + * their data. The first half of the array contains the receive counts + * (in rank order), while the latter half contains the displacements + * (also in rank order). + */ + if (allgather || (mpi_rank == root)) { + if (NULL == + (recv_counts_disps_array = H5MM_malloc(2 * (size_t)mpi_size * sizeof(*recv_counts_disps_array)))) + /* Push an error, but still participate in collective gather operation */ + HDONE_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "couldn't allocate receive counts and displacements array") + } + + /* Collect each rank's send count to interested ranks */ + if (allgather) { + if (MPI_SUCCESS != + (mpi_code = MPI_Allgather(&send_count, 1, MPI_INT, recv_counts_disps_array, 1, MPI_INT, comm))) + HMPI_GOTO_ERROR(FAIL, "MPI_Allgather failed", mpi_code) + } + else { + if (MPI_SUCCESS != + (mpi_code = MPI_Gather(&send_count, 1, MPI_INT, recv_counts_disps_array, 1, MPI_INT, root, comm))) + HMPI_GOTO_ERROR(FAIL, "MPI_Gather failed", mpi_code) + } + + /* Set the displacements into the receive buffer for the gather operation */ + if (allgather || (mpi_rank == root)) { + size_t i; + int * displacements_ptr; + + displacements_ptr = &recv_counts_disps_array[mpi_size]; + + *displacements_ptr = 0; + for (i = 1; i < (size_t)mpi_size; i++) + displacements_ptr[i] = displacements_ptr[i - 1] + recv_counts_disps_array[i - 1]; + } + + /* Perform gather operation */ + if (H5_mpio_gatherv_alloc(send_buf, send_count, send_type, recv_counts_disps_array, + &recv_counts_disps_array[mpi_size], recv_type, allgather, root, comm, mpi_rank, + mpi_size, out_buf, out_buf_num_entries) < 0) + HGOTO_ERROR(H5E_LIB, H5E_CANTGATHER, FAIL, "can't gather data") + +done: + if (recv_counts_disps_array) + H5MM_free(recv_counts_disps_array); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5_mpio_gatherv_alloc_simple() */ + #endif /* H5_HAVE_PARALLEL */ diff --git a/src/H5private.h b/src/H5private.h index b1db201..518cea4 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -44,10 +44,12 @@ #include <sys/time.h> #endif #ifdef H5_HAVE_UNISTD_H +#include <unistd.h> +#endif #ifdef H5_HAVE_PWD_H #include <pwd.h> #endif -#include <unistd.h> +#ifdef H5_HAVE_WAITPID #include <sys/wait.h> #endif @@ -99,8 +101,14 @@ #include <dirent.h> #endif -/* Define the default VFD for this platform. - * Since the removal of the Windows VFD, this is sec2 for all platforms. +/* Define the default VFD for this platform. Since the removal of the + * Windows VFD, this is sec2 for all platforms. + * + * Note well: if you change the default, then be sure to change + * H5_default_vfd_init() to call that default's initializer. Also, + * make sure that the initializer for each *non*-default VFD calls + * H5_init_library(); also, make sure that the initializer for default + * VFD does *not* call H5_init_library(). */ #define H5_DEFAULT_VFD H5FD_SEC2 @@ -164,7 +172,7 @@ */ #define BEGIN_MPE_LOG \ if (H5_MPEinit_g) { \ - sprintf(p_event_start, "start %s", __func__); \ + snprintf(p_event_start, sizeof(p_event_start), "start %s", __func__); \ if (eventa(__func__) == -1 && eventb(__func__) == -1) { \ const char *p_color = "red"; \ eventa(__func__) = MPE_Log_get_event_number(); \ @@ -252,10 +260,10 @@ #define H5_ATTR_NORETURN __attribute__((noreturn)) #define H5_ATTR_CONST __attribute__((const)) #define H5_ATTR_PURE __attribute__((pure)) -#if defined(__GNUC__) && __GNUC__ >= 7 && !defined(__INTEL_COMPILER) +#if defined(__clang__) || defined(__GNUC__) && __GNUC__ >= 7 && !defined(__INTEL_COMPILER) #define H5_ATTR_FALLTHROUGH __attribute__((fallthrough)); #else -#define H5_ATTR_FALLTHROUGH /*void*/ +#define H5_ATTR_FALLTHROUGH /* FALLTHROUGH */ #endif #else #define H5_ATTR_FORMAT(X, Y, Z) /*void*/ @@ -379,6 +387,25 @@ #define HSSIZET_MAX ((hssize_t)LLONG_MAX) #define HSSIZET_MIN (~(HSSIZET_MAX)) +#ifdef H5_HAVE_PARALLEL + +/* Define a type for safely sending size_t values with MPI */ +#if SIZE_MAX == UCHAR_MAX +#define H5_SIZE_T_AS_MPI_TYPE MPI_UNSIGNED_CHAR +#elif SIZE_MAX == USHRT_MAX +#define H5_SIZE_T_AS_MPI_TYPE MPI_UNSIGNED_SHORT +#elif SIZE_MAX == UINT_MAX +#define H5_SIZE_T_AS_MPI_TYPE MPI_UNSIGNED +#elif SIZE_MAX == ULONG_MAX +#define H5_SIZE_T_AS_MPI_TYPE MPI_UNSIGNED_LONG +#elif SIZE_MAX == ULLONG_MAX +#define H5_SIZE_T_AS_MPI_TYPE MPI_UNSIGNED_LONG_LONG +#else +#error "no suitable MPI type for size_t" +#endif + +#endif /* H5_HAVE_PARALLEL */ + /* * Types and max sizes for POSIX I/O. * OS X (Darwin) is odd since the max I/O size does not match the types. @@ -500,6 +527,9 @@ #define H5_GCC_CLANG_DIAG_ON(x) #endif +/* Function pointer typedef for qsort */ +typedef int (*H5_sort_func_cb_t)(const void *, const void *); + /* Typedefs and functions for timing certain parts of the library. */ /* A set of elapsed/user/system times emitted as a time point by the @@ -568,7 +598,7 @@ typedef off_t h5_stat_size_t; #define HDoff_t off_t #endif -#/* Redefine all the POSIX and C functions. We should never see an +/* Redefine all the POSIX and C functions. We should never see an * undecorated POSIX or C function (or any other non-HDF5 function) * in the source. */ @@ -1127,57 +1157,6 @@ H5_DLL H5_ATTR_CONST int Nflock(int fd, int operation); #ifndef HDprintf #define HDprintf printf /*varargs*/ #endif -#ifndef HDpthread_attr_destroy -#define HDpthread_attr_destroy(A) pthread_attr_destroy(A) -#endif -#ifndef HDpthread_attr_init -#define HDpthread_attr_init(A) pthread_attr_init(A) -#endif -#ifndef HDpthread_attr_setscope -#define HDpthread_attr_setscope(A, S) pthread_attr_setscope(A, S) -#endif -#ifndef HDpthread_cond_init -#define HDpthread_cond_init(C, A) pthread_cond_init(C, A) -#endif -#ifndef HDpthread_cond_signal -#define HDpthread_cond_signal(C) pthread_cond_signal(C) -#endif -#ifndef HDpthread_cond_wait -#define HDpthread_cond_wait(C, M) pthread_cond_wait(C, M) -#endif -#ifndef HDpthread_create -#define HDpthread_create(R, A, F, U) pthread_create(R, A, F, U) -#endif -#ifndef HDpthread_equal -#define HDpthread_equal(T1, T2) pthread_equal(T1, T2) -#endif -#ifndef HDpthread_getspecific -#define HDpthread_getspecific(K) pthread_getspecific(K) -#endif -#ifndef HDpthread_join -#define HDpthread_join(T, V) pthread_join(T, V) -#endif -#ifndef HDpthread_key_create -#define HDpthread_key_create(K, D) pthread_key_create(K, D) -#endif -#ifndef HDpthread_mutex_init -#define HDpthread_mutex_init(M, A) pthread_mutex_init(M, A) -#endif -#ifndef HDpthread_mutex_lock -#define HDpthread_mutex_lock(M) pthread_mutex_lock(M) -#endif -#ifndef HDpthread_mutex_unlock -#define HDpthread_mutex_unlock(M) pthread_mutex_unlock(M) -#endif -#ifndef HDpthread_self -#define HDpthread_self() pthread_self() -#endif -#ifndef HDpthread_setcancelstate -#define HDpthread_setcancelstate(N, O) pthread_setcancelstate(N, O) -#endif -#ifndef HDpthread_setspecific -#define HDpthread_setspecific(K, V) pthread_setspecific(K, V) -#endif #ifndef HDputc #define HDputc(C, F) putc(C, F) #endif @@ -1763,6 +1742,15 @@ typedef struct H5_debug_t { } H5_debug_t; #ifdef H5_HAVE_PARALLEL + +/* + * Check that the MPI library version is at least version + * `mpi_version` and subversion `mpi_subversion` + */ +#define H5_CHECK_MPI_VERSION(mpi_version, mpi_subversion) \ + ((MPI_VERSION > (mpi_version)) || \ + ((MPI_VERSION == (mpi_version)) && (MPI_SUBVERSION >= (mpi_subversion)))) + extern hbool_t H5_coll_api_sanity_check_g; #endif /* H5_HAVE_PARALLEL */ @@ -1989,7 +1977,7 @@ extern H5_api_t H5_g; #define H5_API_LOCK #define H5_API_UNLOCK -/* disable cancelability (sequential version) */ +/* disable cancellability (sequential version) */ #define H5_API_UNSET_CANCEL #define H5_API_SET_CANCEL @@ -2003,6 +1991,14 @@ extern hbool_t H5_libterm_g; /* Is the library being shutdown? */ #endif /* H5_HAVE_THREADSAFE */ +/* Extern global to determine if we should use selection I/O if available (this + * variable should be removed once selection I/O performs as well as the + * previous scalar I/O implementation + * + * NOTE: Must be exposed via H5_DLLVAR so parallel tests pass on Windows. + */ +H5_DLLVAR hbool_t H5_use_selection_io_g; + #ifdef H5_HAVE_CODESTACK /* Include required function stack header */ @@ -2019,33 +2015,6 @@ extern hbool_t H5_libterm_g; /* Is the library being shutdown? */ extern hbool_t H5_MPEinit_g; /* Has the MPE Library been initialized? */ #endif -/* Macros for referencing package initialization symbols */ -#define H5_PACKAGE_INIT_VAR(x) H5_GLUE(x, _init_g) -#define H5_PACKAGE_INIT_FUNC(x) H5_GLUE(x, __init_package) - -/* Macros for defining package initialization routines */ -#ifdef H5_MY_PKG -#define H5_PKG_INIT_VAR H5_PACKAGE_INIT_VAR(H5_MY_PKG) -#define H5_PKG_INIT_FUNC H5_PACKAGE_INIT_FUNC(H5_MY_PKG) -#define H5_PACKAGE_YES_INIT(err) \ - /* Initialize this interface or bust */ \ - if (!H5_PKG_INIT_VAR && !H5_TERM_GLOBAL) { \ - H5_PKG_INIT_VAR = TRUE; \ - if (H5_PKG_INIT_FUNC() < 0) { \ - H5_PKG_INIT_VAR = FALSE; \ - HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, err, "interface initialization failed") \ - } \ - } -#define H5_PACKAGE_NO_INIT(err) \ - /* Initialize this interface or bust */ \ - if (!H5_PKG_INIT_VAR && !H5_TERM_GLOBAL) \ - H5_PKG_INIT_VAR = TRUE; -#define H5_PACKAGE_INIT(pkg_init, err) H5_GLUE3(H5_PACKAGE_, pkg_init, _INIT)(err) -#else /* H5_MY_PKG */ -#define H5_PKG_INIT_VAR (TRUE) -#define H5_PACKAGE_INIT(pkg_init, err) -#endif /* H5_MY_PKG */ - /* Forward declaration of H5CXpush() / H5CXpop() */ /* (Including H5CXprivate.h creates bad circular dependencies - QAK, 3/18/2018) */ H5_DLL herr_t H5CX_push(void); @@ -2101,10 +2070,7 @@ H5_DLL herr_t H5CX_pop(hbool_t update_dxpl_props); if (!H5_INIT_GLOBAL && !H5_TERM_GLOBAL) { \ if (H5_init_library() < 0) \ HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, err, "library initialization failed") \ - } /* end if */ \ - \ - /* Initialize the package, if appropriate */ \ - H5_PACKAGE_INIT(H5_MY_PKG_INIT, err) + } #define FUNC_ENTER_API_PUSH(err) \ /* Push the name of this function on the function stack */ \ @@ -2213,27 +2179,19 @@ H5_DLL herr_t H5CX_pop(hbool_t update_dxpl_props); FUNC_ENTER_COMMON_NOERR(H5_IS_API(__func__)); \ { -/* Note: this macro only works when there's _no_ interface initialization routine for the module */ -#define FUNC_ENTER_NOAPI_INIT(err) \ - /* Initialize the package, if appropriate */ \ - H5_PACKAGE_INIT(H5_MY_PKG_INIT, err) \ - \ - /* Push the name of this function on the function stack */ \ - H5_PUSH_FUNC - /* Use this macro for all "normal" non-API functions */ #define FUNC_ENTER_NOAPI(err) \ { \ FUNC_ENTER_COMMON(!H5_IS_API(__func__)); \ - FUNC_ENTER_NOAPI_INIT(err) \ - if (H5_PKG_INIT_VAR || !H5_TERM_GLOBAL) { + H5_PUSH_FUNC \ + { /* Use this macro for all non-API functions, which propagate errors, but don't issue them */ #define FUNC_ENTER_NOAPI_NOERR \ { \ FUNC_ENTER_COMMON_NOERR(!H5_IS_API(__func__)); \ - FUNC_ENTER_NOAPI_INIT(-) \ - if (H5_PKG_INIT_VAR || !H5_TERM_GLOBAL) { + H5_PUSH_FUNC \ + { /* * Use this macro for non-API functions which fall into these categories: @@ -2247,7 +2205,7 @@ H5_DLL herr_t H5CX_pop(hbool_t update_dxpl_props); { \ FUNC_ENTER_COMMON(!H5_IS_API(__func__)); \ H5_PUSH_FUNC \ - if (H5_PKG_INIT_VAR || !H5_TERM_GLOBAL) { + { /* * Use this macro for non-API functions which fall into these categories: @@ -2262,7 +2220,7 @@ H5_DLL herr_t H5CX_pop(hbool_t update_dxpl_props); { \ FUNC_ENTER_COMMON_NOERR(!H5_IS_API(__func__)); \ H5_PUSH_FUNC \ - if (H5_PKG_INIT_VAR || !H5_TERM_GLOBAL) { + { /* * Use this macro for non-API functions which fall into these categories: @@ -2274,9 +2232,7 @@ H5_DLL herr_t H5CX_pop(hbool_t update_dxpl_props); { \ FUNC_ENTER_COMMON(!H5_IS_API(__func__)); \ \ - /* Initialize the package, if appropriate */ \ - H5_PACKAGE_INIT(H5_MY_PKG_INIT, err) \ - if (H5_PKG_INIT_VAR || !H5_TERM_GLOBAL) { + { /* * Use this macro for non-API functions which fall into these categories: @@ -2290,7 +2246,7 @@ H5_DLL herr_t H5CX_pop(hbool_t update_dxpl_props); #define FUNC_ENTER_NOAPI_NOERR_NOFS \ { \ FUNC_ENTER_COMMON_NOERR(!H5_IS_API(__func__)); \ - if (H5_PKG_INIT_VAR || !H5_TERM_GLOBAL) { + { /* * Use this macro for non-API functions that shouldn't perform _any_ initialization @@ -2312,8 +2268,8 @@ H5_DLL herr_t H5CX_pop(hbool_t update_dxpl_props); \ FUNC_ENTER_COMMON(!H5_IS_API(__func__)); \ H5AC_tag(tag, &prev_tag); \ - FUNC_ENTER_NOAPI_INIT(err) \ - if (H5_PKG_INIT_VAR || !H5_TERM_GLOBAL) { + H5_PUSH_FUNC \ + { #define FUNC_ENTER_NOAPI_NOINIT_TAG(tag) \ { \ @@ -2322,21 +2278,21 @@ H5_DLL herr_t H5CX_pop(hbool_t update_dxpl_props); FUNC_ENTER_COMMON(!H5_IS_API(__func__)); \ H5AC_tag(tag, &prev_tag); \ H5_PUSH_FUNC \ - if (H5_PKG_INIT_VAR || !H5_TERM_GLOBAL) { + { /* Use this macro for all "normal" package-level functions */ #define FUNC_ENTER_PACKAGE \ { \ FUNC_ENTER_COMMON(H5_IS_PKG(__func__)); \ H5_PUSH_FUNC \ - if (H5_PKG_INIT_VAR || !H5_TERM_GLOBAL) { + { /* Use this macro for package-level functions which propgate errors, but don't issue them */ #define FUNC_ENTER_PACKAGE_NOERR \ { \ FUNC_ENTER_COMMON_NOERR(H5_IS_PKG(__func__)); \ H5_PUSH_FUNC \ - if (H5_PKG_INIT_VAR || !H5_TERM_GLOBAL) { + { /* Use the following macro as replacement for the FUNC_ENTER_PACKAGE * macro when the function needs to set up a metadata tag. */ @@ -2347,28 +2303,28 @@ H5_DLL herr_t H5CX_pop(hbool_t update_dxpl_props); FUNC_ENTER_COMMON(H5_IS_PKG(__func__)); \ H5AC_tag(tag, &prev_tag); \ H5_PUSH_FUNC \ - if (H5_PKG_INIT_VAR || !H5_TERM_GLOBAL) { + { /* Use this macro for all "normal" staticly-scoped functions */ #define FUNC_ENTER_STATIC \ { \ FUNC_ENTER_COMMON(H5_IS_PKG(__func__)); \ H5_PUSH_FUNC \ - if (H5_PKG_INIT_VAR || !H5_TERM_GLOBAL) { + { /* Use this macro for staticly-scoped functions which propgate errors, but don't issue them */ #define FUNC_ENTER_STATIC_NOERR \ { \ FUNC_ENTER_COMMON_NOERR(H5_IS_PKG(__func__)); \ H5_PUSH_FUNC \ - if (H5_PKG_INIT_VAR || !H5_TERM_GLOBAL) { + { /* Use this macro for staticly-scoped functions which propgate errors, but don't issue them */ /* And that shouldn't push their name on the function stack */ #define FUNC_ENTER_STATIC_NOERR_NOFS \ { \ FUNC_ENTER_COMMON_NOERR(H5_IS_PKG(__func__)); \ - if (H5_PKG_INIT_VAR || !H5_TERM_GLOBAL) { + { /* * Use this macro for non-API functions that shouldn't perform _any_ initialization @@ -2390,7 +2346,7 @@ H5_DLL herr_t H5CX_pop(hbool_t update_dxpl_props); FUNC_ENTER_COMMON(H5_IS_PKG(__func__)); \ H5AC_tag(tag, &prev_tag); \ H5_PUSH_FUNC \ - if (H5_PKG_INIT_VAR || !H5_TERM_GLOBAL) { + { /*------------------------------------------------------------------------- * Purpose: Register function exit for code profiling. This should be @@ -2519,27 +2475,6 @@ H5_DLL herr_t H5CX_pop(hbool_t update_dxpl_props); return (ret_value); \ } /*end scope from beginning of FUNC_ENTER*/ -/* Macros to declare package initialization function, if a package initialization routine is defined */ -#ifdef H5_PKG_SINGLE_SOURCE -#define H5_PKG_DECLARE_YES_FUNC(pkg) static herr_t H5_PACKAGE_INIT_FUNC(pkg)(void); -#else -#define H5_PKG_DECLARE_YES_FUNC(pkg) extern herr_t H5_PACKAGE_INIT_FUNC(pkg)(void); -#endif -#define H5_PKG_DECLARE_NO_FUNC(pkg) - -/* Declare package initialization symbols (if in a package) */ -#ifdef H5_PKG_SINGLE_SOURCE -#define H5_PKG_DECLARE_VAR(pkg) static hbool_t H5_PACKAGE_INIT_VAR(pkg); -#else -#define H5_PKG_DECLARE_VAR(pkg) extern hbool_t H5_PACKAGE_INIT_VAR(pkg); -#endif -#define H5_PKG_DECLARE_FUNC(pkg_init, pkg) H5_GLUE3(H5_PKG_DECLARE_, pkg_init, _FUNC)(pkg) - -#ifdef H5_MY_PKG -H5_PKG_DECLARE_VAR(H5_MY_PKG) -H5_PKG_DECLARE_FUNC(H5_MY_PKG_INIT, H5_MY_PKG) -#endif - /* Macro to begin/end tagging (when FUNC_ENTER_*TAG macros are insufficient). * Make sure to use HGOTO_ERROR_TAG and HGOTO_DONE_TAG between these macros! */ #define H5_BEGIN_TAG(tag) \ @@ -2558,6 +2493,16 @@ H5_PKG_DECLARE_FUNC(H5_MY_PKG_INIT, H5_MY_PKG) #define HDcompile_assert(e) do { typedef struct { unsigned int b: (e); } x; } while(0) */ +/* Private typedefs */ + +/* Union for const/non-const pointer for use by functions that manipulate + * pointers but do not write to their targets or return pointers to const + * specified locations. This helps us avoid compiler warnings. */ +typedef union { + void * vp; + const void *cvp; +} H5_flexible_const_ptr_t; + /* Private functions, not part of the publicly documented API */ H5_DLL herr_t H5_init_library(void); H5_DLL void H5_term_library(void); @@ -2658,7 +2603,8 @@ struct h5_long_options { */ }; -H5_DLL int H5_get_option(int argc, const char **argv, const char *opt, const struct h5_long_options *l_opt); +H5_DLL int H5_get_option(int argc, const char *const *argv, const char *opt, + const struct h5_long_options *l_opt); #ifdef H5_HAVE_PARALLEL /* Generic MPI functions */ @@ -2672,6 +2618,14 @@ H5_DLL herr_t H5_mpi_comm_cmp(MPI_Comm comm1, MPI_Comm comm2, int *result); H5_DLL herr_t H5_mpi_info_cmp(MPI_Info info1, MPI_Info info2, int *result); H5_DLL herr_t H5_mpio_create_large_type(hsize_t num_elements, MPI_Aint stride_bytes, MPI_Datatype old_type, MPI_Datatype *new_type); +H5_DLL herr_t H5_mpio_gatherv_alloc(void *send_buf, int send_count, MPI_Datatype send_type, + const int recv_counts[], const int displacements[], + MPI_Datatype recv_type, hbool_t allgather, int root, MPI_Comm comm, + int mpi_rank, int mpi_size, void **out_buf, size_t *out_buf_num_entries); +H5_DLL herr_t H5_mpio_gatherv_alloc_simple(void *send_buf, int send_count, MPI_Datatype send_type, + MPI_Datatype recv_type, hbool_t allgather, int root, MPI_Comm comm, + int mpi_rank, int mpi_size, void **out_buf, + size_t *out_buf_num_entries); #endif /* H5_HAVE_PARALLEL */ /* Functions for debugging */ diff --git a/src/H5public.h b/src/H5public.h index c9430dc..3f9848a 100644 --- a/src/H5public.h +++ b/src/H5public.h @@ -46,7 +46,7 @@ #include <stddef.h> #include <stdint.h> -/* Unlike most sys/ headers, which are POSIX-only, sys/types.h is avaible +/* Unlike most sys/ headers, which are POSIX-only, sys/types.h is available * on Windows, though it doesn't necessarily contain all the POSIX types * we need for HDF5 (e.g. ssize_t). */ @@ -83,15 +83,15 @@ /** * For tweaks, bug-fixes, or development */ -#define H5_VERS_RELEASE 0 +#define H5_VERS_RELEASE 2 /** * For pre-releases like \c snap0. Empty string for official releases. */ -#define H5_VERS_SUBRELEASE "7" +#define H5_VERS_SUBRELEASE "1" /** * Full version string */ -#define H5_VERS_INFO "HDF5 library version: 1.13.0-7" +#define H5_VERS_INFO "HDF5 library version: 1.13.2-1" #define H5check() H5check_version(H5_VERS_MAJOR, H5_VERS_MINOR, H5_VERS_RELEASE) @@ -168,6 +168,58 @@ (((H5_VERS_MAJOR == Maj) && (H5_VERS_MINOR == Min) && (H5_VERS_RELEASE <= Rel)) || \ ((H5_VERS_MAJOR == Maj) && (H5_VERS_MINOR < Min)) || (H5_VERS_MAJOR < Maj)) +/* Macros for various environment variables that HDF5 interprets */ +/** + * Used to specify the name of an HDF5 Virtual File Driver to use as + * the default file driver for file access. Setting this environment + * variable overrides the default file driver for File Access Property + * Lists. + */ +#define HDF5_DRIVER "HDF5_DRIVER" +/** + * Used to specify a configuration string for the HDF5 Virtual File + * Driver being used for file access. + */ +#define HDF5_DRIVER_CONFIG "HDF5_DRIVER_CONFIG" +/** + * Used to specify the name of an HDF5 Virtual Object Layer Connector + * to use as the default VOL connector for file access. Setting this + * environment variable overrides the default VOL connector for File + * Access Property Lists. + */ +#define HDF5_VOL_CONNECTOR "HDF5_VOL_CONNECTOR" +/** + * Used to specify a delimiter-separated (currently, ';' for Windows + * and ':' for other systems) list of paths that HDF5 should search + * when loading plugins. + */ +#define HDF5_PLUGIN_PATH "HDF5_PLUGIN_PATH" +/** + * Used to control the loading of HDF5 plugins at runtime. If this + * environment variable is set to the special string "::" (defined + * in H5PLpublic.h as H5PL_NO_PLUGIN), then dynamic loading of any + * HDF5 plugins will be disabled. No other values are valid for this + * environment variable. + */ +#define HDF5_PLUGIN_PRELOAD "HDF5_PLUGIN_PRELOAD" +/** + * Used to control whether HDF5 uses file locking when creating or + * opening a file. Valid values for this environment variable are + * as follows: + * + * "TRUE" or "1" - Request that file locks should be used + * "FALSE" or "0" - Request that file locks should NOT be used + * "BEST_EFFORT" - Request that file locks should be used and + * that any locking errors caused by file + * locking being disabled on the system + * should be ignored + */ +#define HDF5_USE_FILE_LOCKING "HDF5_USE_FILE_LOCKING" +/** + * Used to instruct HDF5 not to cleanup files created during testing. + */ +#define HDF5_NOCLEANUP "HDF5_NOCLEANUP" + /** * Status return values. Failed integer functions in HDF5 result almost * always in a negative value (unsigned failing functions sometimes return @@ -237,6 +289,11 @@ typedef long long ssize_t; * \internal Defined as a (minimum) 64-bit integer type. */ typedef uint64_t hsize_t; + +#ifdef H5_HAVE_PARALLEL +#define HSIZE_AS_MPI_TYPE MPI_UINT64_T +#endif + /** * The size of file objects. Used when negative values are needed to indicate errors. * @@ -271,7 +328,7 @@ typedef uint64_t haddr_t; #define HADDR_MAX (HADDR_UNDEF - 1) #ifdef H5_HAVE_PARALLEL -#define HADDR_AS_MPI_TYPE MPI_LONG_LONG_INT +#define HADDR_AS_MPI_TYPE MPI_UINT64_T #endif //! <!-- [H5_iter_order_t_snip] --> diff --git a/src/H5system.c b/src/H5system.c index 9a966b0..a369e3d 100644 --- a/src/H5system.c +++ b/src/H5system.c @@ -862,7 +862,7 @@ H5_nanosleep(uint64_t nanosec) #else - const uint64_t nanosec_per_sec = 1000 * 1000 * 1000; + const uint64_t nanosec_per_sec = 1000 * 1000L * 1000; struct timespec sleeptime; /* Struct to hold time to sleep */ /* Set up time to sleep @@ -956,7 +956,7 @@ const char *H5_optarg; /* Flag argument (or value) */ *------------------------------------------------------------------------- */ int -H5_get_option(int argc, const char **argv, const char *opts, const struct h5_long_options *l_opts) +H5_get_option(int argc, const char *const *argv, const char *opts, const struct h5_long_options *l_opts) { static int sp = 1; /* character index in current token */ int optchar = '?'; /* option character passed back to user */ @@ -1033,7 +1033,7 @@ H5_get_option(int argc, const char **argv, const char *opts, const struct h5_lon HDfree(arg); } else { - register char *cp; /* pointer into current token */ + char *cp; /* pointer into current token */ /* short command line option */ optchar = argv[H5_optind][sp]; diff --git a/src/H5timer.c b/src/H5timer.c index b2cc5f0..b5dba97 100644 --- a/src/H5timer.c +++ b/src/H5timer.c @@ -193,17 +193,26 @@ H5_now_usec(void) struct timespec ts; HDclock_gettime(CLOCK_MONOTONIC, &ts); - now = (uint64_t)(ts.tv_sec * (1000 * 1000)) + (uint64_t)(ts.tv_nsec / 1000); + + /* Cast all values in this expression to uint64_t to ensure that all intermediate + * calculations are done in 64 bit, to prevent overflow */ + now = ((uint64_t)ts.tv_sec * ((uint64_t)1000 * (uint64_t)1000)) + + ((uint64_t)ts.tv_nsec / (uint64_t)1000); } #elif defined(H5_HAVE_GETTIMEOFDAY) { struct timeval now_tv; HDgettimeofday(&now_tv, NULL); - now = (uint64_t)(now_tv.tv_sec * (1000 * 1000)) + (uint64_t)now_tv.tv_usec; + + /* Cast all values in this expression to uint64_t to ensure that all intermediate + * calculations are done in 64 bit, to prevent overflow */ + now = ((uint64_t)now_tv.tv_sec * ((uint64_t)1000 * (uint64_t)1000)) + (uint64_t)now_tv.tv_usec; } #else /* H5_HAVE_GETTIMEOFDAY */ - now = (uint64_t)(HDtime(NULL) * (1000 * 1000)); + /* Cast all values in this expression to uint64_t to ensure that all intermediate calculations + * are done in 64 bit, to prevent overflow */ + now = ((uint64_t)HDtime(NULL) * ((uint64_t)1000 * (uint64_t)1000)); #endif /* H5_HAVE_GETTIMEOFDAY */ return (now); diff --git a/src/H5trace.c b/src/H5trace.c index 3a5d420..946dc27 100644 --- a/src/H5trace.c +++ b/src/H5trace.c @@ -1046,6 +1046,68 @@ H5_trace_args(H5RS_str_t *rs, const char *type, va_list ap) } /* end block */ break; + case 'V': /* H5FD_class_value_t */ + { + H5FD_class_value_t class_val = + (H5FD_class_value_t)HDva_arg(ap, H5FD_class_value_t); + + switch (class_val) { + case H5_VFD_INVALID: + H5RS_acat(rs, "H5_VFD_INVALID"); + break; + case H5_VFD_SEC2: + H5RS_acat(rs, "H5_VFD_SEC2"); + break; + case H5_VFD_CORE: + H5RS_acat(rs, "H5_VFD_CORE"); + break; + case H5_VFD_LOG: + H5RS_acat(rs, "H5_VFD_LOG"); + break; + case H5_VFD_FAMILY: + H5RS_acat(rs, "H5_VFD_FAMILY"); + break; + case H5_VFD_MULTI: + H5RS_acat(rs, "H5_VFD_MULTI"); + break; + case H5_VFD_STDIO: + H5RS_acat(rs, "H5_VFD_STDIO"); + break; +#ifdef H5_HAVE_PARALLEL + case H5_VFD_MPIO: + H5RS_acat(rs, "H5_VFD_MPIO"); + break; +#endif +#ifdef H5_HAVE_DIRECT + case H5_VFD_DIRECT: + H5RS_acat(rs, "H5_VFD_DIRECT"); + break; +#endif +#ifdef H5_HAVE_MIRROR_VFD + case H5_VFD_MIRROR: + H5RS_acat(rs, "H5_VFD_MIRROR"); + break; +#endif +#ifdef H5_HAVE_LIBHDFS + case H5_VFD_HDFS: + H5RS_acat(rs, "H5_VFD_HDFS"); + break; +#endif +#ifdef H5_HAVE_ROS3_VFD + case H5_VFD_ROS3: + H5RS_acat(rs, "H5_VFD_ROS3"); + break; +#endif + case H5_VFD_ONION: + H5RS_acat(rs, "H5_VFD_ONION"); + break; + default: + H5RS_asprintf_cat(rs, "%ld", (long)class_val); + break; + } + } /* end block */ + break; + default: H5RS_asprintf_cat(rs, "BADTYPE(D%c)", type[1]); goto error; @@ -1189,7 +1251,7 @@ H5_trace_args(H5RS_str_t *rs, const char *type, va_list ap) { H5FD_class_t cls = HDva_arg(ap, H5FD_class_t); - H5RS_asprintf_cat(rs, "{'%s', " H5_PRINTF_HADDR_FMT ", ", cls.name, cls.maxaddr); + H5RS_asprintf_cat(rs, "{'%s', %" PRIuHADDR ", ", cls.name, cls.maxaddr); H5_trace_args_close_degree(rs, cls.fc_degree); H5RS_acat(rs, ", ...}"); } /* end block */ @@ -1563,10 +1625,8 @@ H5_trace_args(H5RS_str_t *rs, const char *type, va_list ap) H5RS_acat(rs, "H5T_NATIVE_FLOAT"); else if (obj == H5T_NATIVE_DOUBLE_g) H5RS_acat(rs, "H5T_NATIVE_DOUBLE"); -#if H5_SIZEOF_LONG_DOUBLE != 0 else if (obj == H5T_NATIVE_LDOUBLE_g) H5RS_acat(rs, "H5T_NATIVE_LDOUBLE"); -#endif else if (obj == H5T_IEEE_F32BE_g) H5RS_acat(rs, "H5T_IEEE_F32BE"); else if (obj == H5T_IEEE_F32LE_g) @@ -3966,7 +4026,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...) H5_timer_get_times(function_timer, &function_times); H5_timer_get_times(running_timer, &running_times); - HDsprintf(tmp, "%.6f", (function_times.elapsed - running_times.elapsed)); + HDsnprintf(tmp, sizeof(tmp), "%.6f", (function_times.elapsed - running_times.elapsed)); H5RS_asprintf_cat(rs, " %*s ", (int)HDstrlen(tmp), ""); } for (i = 0; i < current_depth; i++) diff --git a/src/Makefile.am b/src/Makefile.am index afbe0c2..d289278 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -62,7 +62,7 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5lib_settings.c H5system.c \ H5FA.c H5FAcache.c H5FAdbg.c H5FAdblock.c H5FAdblkpage.c H5FAhdr.c \ H5FAint.c H5FAstat.c H5FAtest.c \ H5FD.c H5FDcore.c H5FDfamily.c H5FDint.c H5FDlog.c \ - H5FDmulti.c H5FDonion.c H5FDsec2.c H5FDspace.c \ + H5FDmulti.c H5FDonion.c H5FDperform.c H5FDsec2.c H5FDspace.c \ H5FDsplitter.c H5FDstdio.c H5FDtest.c \ H5FL.c H5FO.c H5FS.c H5FScache.c H5FSdbg.c H5FSint.c H5FSsection.c \ H5FSstat.c H5FStest.c \ @@ -74,12 +74,11 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5lib_settings.c H5system.c \ H5HFspace.c H5HFstat.c H5HFtest.c H5HFtiny.c \ H5HG.c H5HGcache.c H5HGdbg.c H5HGquery.c \ H5HL.c H5HLcache.c H5HLdbg.c H5HLint.c H5HLprfx.c H5HLdblk.c \ - H5HP.c \ H5I.c H5Idbg.c H5Iint.c H5Itest.c \ H5L.c H5Ldeprec.c H5Lexternal.c H5Lint.c \ H5M.c \ H5MF.c H5MFaggr.c H5MFdbg.c H5MFsection.c \ - H5MM.c H5MP.c H5MPtest.c \ + H5MM.c \ H5O.c H5Odeprec.c H5Oainfo.c H5Oalloc.c H5Oattr.c H5Oattribute.c \ H5Obogus.c H5Obtreek.c H5Ocache.c H5Ocache_image.c H5Ochunk.c \ H5Ocont.c H5Ocopy.c H5Ocopy_ref.c H5Odbg.c H5Odrvinfo.c H5Odtype.c \ diff --git a/src/libhdf5.settings.in b/src/libhdf5.settings.in index 44c1540..7fe1a36 100644 --- a/src/libhdf5.settings.in +++ b/src/libhdf5.settings.in @@ -67,28 +67,29 @@ Languages: Features: --------- - Parallel HDF5: @PARALLEL@ -Parallel Filtered Dataset Writes: @PARALLEL_FILTERED_WRITES@ - Large Parallel I/O: @LARGE_PARALLEL_IO@ - High-level library: @HDF5_HL@ - Build HDF5 Tests: @HDF5_TESTS@ - Build HDF5 Tools: @HDF5_TOOLS@ - Threadsafety: @THREADSAFE@ - Default API mapping: @DEFAULT_API_VERSION@ - With deprecated public symbols: @DEPRECATED_SYMBOLS@ - I/O filters (external): @EXTERNAL_FILTERS@ - MPE: @MPE@ - Map (H5M) API: @MAP_API@ - Direct VFD: @DIRECT_VFD@ - Mirror VFD: @MIRROR_VFD@ - (Read-Only) S3 VFD: @ROS3_VFD@ - (Read-Only) HDFS VFD: @HAVE_LIBHDFS@ - dmalloc: @HAVE_DMALLOC@ - Packages w/ extra debug output: @INTERNAL_DEBUG_OUTPUT@ - API tracing: @TRACE_API@ - Using memory checker: @USINGMEMCHECKER@ - Memory allocation sanity checks: @MEMORYALLOCSANITYCHECK@ - Function stack tracing: @CODESTACK@ - Use file locking: @DESIRED_FILE_LOCKING@ - Strict file format checks: @STRICT_FORMAT_CHECKS@ - Optimization instrumentation: @INSTRUMENT_LIBRARY@ + Parallel HDF5: @PARALLEL@ + Parallel Filtered Dataset Writes: @PARALLEL_FILTERED_WRITES@ + Large Parallel I/O: @LARGE_PARALLEL_IO@ + High-level library: @HDF5_HL@ +Dimension scales w/ new references: @DIMENSION_SCALES_WITH_NEW_REF@ + Build HDF5 Tests: @HDF5_TESTS@ + Build HDF5 Tools: @HDF5_TOOLS@ + Threadsafety: @THREADSAFE@ + Default API mapping: @DEFAULT_API_VERSION@ + With deprecated public symbols: @DEPRECATED_SYMBOLS@ + I/O filters (external): @EXTERNAL_FILTERS@ + MPE: @MPE@ + Map (H5M) API: @MAP_API@ + Direct VFD: @DIRECT_VFD@ + Mirror VFD: @MIRROR_VFD@ + (Read-Only) S3 VFD: @ROS3_VFD@ + (Read-Only) HDFS VFD: @HAVE_LIBHDFS@ + dmalloc: @HAVE_DMALLOC@ + Packages w/ extra debug output: @INTERNAL_DEBUG_OUTPUT@ + API tracing: @TRACE_API@ + Using memory checker: @USINGMEMCHECKER@ + Memory allocation sanity checks: @MEMORYALLOCSANITYCHECK@ + Function stack tracing: @CODESTACK@ + Use file locking: @DESIRED_FILE_LOCKING@ + Strict file format checks: @STRICT_FORMAT_CHECKS@ + Optimization instrumentation: @INSTRUMENT_LIBRARY@ diff --git a/src/uthash.h b/src/uthash.h index 8bdca55..ea99839 100644 --- a/src/uthash.h +++ b/src/uthash.h @@ -714,25 +714,35 @@ typedef unsigned char uint8_t; hashv += (unsigned)(keylen); \ switch (_hj_k) { \ case 11: \ - hashv += ((unsigned)_hj_key[10] << 24); /* FALLTHROUGH */ \ + hashv += ((unsigned)_hj_key[10] << 24); \ + H5_ATTR_FALLTHROUGH \ case 10: \ - hashv += ((unsigned)_hj_key[9] << 16); /* FALLTHROUGH */ \ + hashv += ((unsigned)_hj_key[9] << 16); \ + H5_ATTR_FALLTHROUGH \ case 9: \ - hashv += ((unsigned)_hj_key[8] << 8); /* FALLTHROUGH */ \ + hashv += ((unsigned)_hj_key[8] << 8); \ + H5_ATTR_FALLTHROUGH \ case 8: \ - _hj_j += ((unsigned)_hj_key[7] << 24); /* FALLTHROUGH */ \ + _hj_j += ((unsigned)_hj_key[7] << 24); \ + H5_ATTR_FALLTHROUGH \ case 7: \ - _hj_j += ((unsigned)_hj_key[6] << 16); /* FALLTHROUGH */ \ + _hj_j += ((unsigned)_hj_key[6] << 16); \ + H5_ATTR_FALLTHROUGH \ case 6: \ - _hj_j += ((unsigned)_hj_key[5] << 8); /* FALLTHROUGH */ \ + _hj_j += ((unsigned)_hj_key[5] << 8); \ + H5_ATTR_FALLTHROUGH \ case 5: \ - _hj_j += _hj_key[4]; /* FALLTHROUGH */ \ + _hj_j += _hj_key[4]; \ + H5_ATTR_FALLTHROUGH \ case 4: \ - _hj_i += ((unsigned)_hj_key[3] << 24); /* FALLTHROUGH */ \ + _hj_i += ((unsigned)_hj_key[3] << 24); \ + H5_ATTR_FALLTHROUGH \ case 3: \ - _hj_i += ((unsigned)_hj_key[2] << 16); /* FALLTHROUGH */ \ + _hj_i += ((unsigned)_hj_key[2] << 16); \ + H5_ATTR_FALLTHROUGH \ case 2: \ - _hj_i += ((unsigned)_hj_key[1] << 8); /* FALLTHROUGH */ \ + _hj_i += ((unsigned)_hj_key[1] << 8); \ + H5_ATTR_FALLTHROUGH \ case 1: \ _hj_i += _hj_key[0]; \ } \ |