diff options
Diffstat (limited to 'src')
244 files changed, 11443 insertions, 5765 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 33d31fb..dcb74a9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -241,6 +241,7 @@ set (H5FD_SOURCES ${HDF5_SRC_DIR}/H5FDmpi.c ${HDF5_SRC_DIR}/H5FDmpio.c ${HDF5_SRC_DIR}/H5FDmulti.c + ${HDF5_SRC_DIR}/H5FDperform.c ${HDF5_SRC_DIR}/H5FDros3.c ${HDF5_SRC_DIR}/H5FDs3comms.c ${HDF5_SRC_DIR}/H5FDsec2.c @@ -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 */ @@ -101,32 +101,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 +143,20 @@ done: herr_t H5_init_library(void) { + size_t i; 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,28 +260,33 @@ 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 (H5T_init() < 0) - HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize datatype interface") - if (H5D_init() < 0) - HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize dataset 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 */ /* Debugging? */ H5__debug_mask("-all"); @@ -302,9 +310,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 @@ -348,108 +358,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) { @@ -915,6 +954,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 @@ -935,10 +975,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, @@ -973,9 +1010,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 */ @@ -983,7 +1021,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"); @@ -1002,7 +1040,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() */ @@ -339,7 +310,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))) @@ -1248,7 +1219,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 @@ -1300,7 +1271,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 @@ -1489,21 +1460,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) @@ -1685,9 +1717,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 d310a2b..25e7e9a 100644 --- a/src/H5ACproxy_entry.c +++ b/src/H5ACproxy_entry.c @@ -422,7 +422,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); @@ -434,7 +434,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..c853794 100644 --- a/src/H5ACpublic.h +++ b/src/H5ACpublic.h @@ -76,7 +76,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 +123,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 +396,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 +576,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 +708,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 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 @@ -153,19 +153,10 @@ static herr_t H5C__mark_flush_dep_clean(H5C_cache_entry_t *entry); static herr_t H5C__serialize_ring(H5F_t *f, H5C_ring_t ring); static herr_t H5C__serialize_single_entry(H5F_t *f, H5C_t *cache_ptr, H5C_cache_entry_t *entry_ptr); +static herr_t H5C__generate_image(H5F_t *f, H5C_t *cache_ptr, H5C_cache_entry_t *entry_ptr); 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); @@ -175,9 +166,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); @@ -397,7 +385,7 @@ H5C_create(size_t max_cache_size, size_t min_clean_size, int max_type_id, cache_ptr->slist_size = (size_t)0; /* slist_ring_len, slist_ring_size, and - * slist_ptr initialized above. + * slist_ptr initializaed above. */ #if H5C_DO_SANITY_CHECKS @@ -811,7 +799,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) @@ -890,6 +878,9 @@ H5C_dest(H5F_t *f) HGOTO_ERROR(H5E_CACHE, H5E_CANTCREATE, FAIL, "Can't generate metadata cache image") } + /* Question: Is it possible for cache_ptr->slist be non-null at this + * point? If no, shouldn't this if statement be an assert? + */ if (cache_ptr->slist_ptr != NULL) { HDassert(cache_ptr->slist_len == 0); @@ -1178,10 +1169,10 @@ H5C_evict_or_refresh_all_entries_in_page(H5F_t *f, uint64_t page, uint32_t lengt * Note that this will be satisfied from the metadata * file via the VFD SWMR reade VFD. * - * For this reason, we don't nead to check for reads + * For this reason, we don't need to check for reads * past the EOA. Torn reads and checksums are also * not an issue, since pages in the metadata file - * are checksumed and re-tried if necessary in the + * are checksummed and re-tried if necessary in the * VFD SWMR reader VFD. */ if (NULL == (image_ptr = (uint8_t *)H5MM_malloc(image_len + H5C_IMAGE_EXTRA_SPACE))) @@ -1402,7 +1393,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 */ @@ -1437,7 +1428,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 */ @@ -1544,8 +1535,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 */ @@ -1724,8 +1715,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 */ @@ -1908,7 +1899,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. @@ -1927,8 +1918,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 */ @@ -1942,23 +1933,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 */ @@ -2290,8 +2290,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 */ @@ -2404,8 +2404,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 */ @@ -2451,8 +2451,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 */ @@ -2548,8 +2547,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 */ @@ -2589,8 +2587,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 */ @@ -2604,8 +2602,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 */ @@ -2668,8 +2666,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 */ @@ -2688,7 +2686,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 */ @@ -2747,9 +2745,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); @@ -2897,7 +2900,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. @@ -3012,7 +3015,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) @@ -3048,16 +3051,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 */ @@ -3565,8 +3576,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 */ @@ -3576,8 +3587,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 */ @@ -3744,8 +3755,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 */ @@ -4011,8 +4022,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 */ @@ -5336,7 +5347,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 @@ -6348,7 +6359,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 @@ -6546,8 +6557,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 */ @@ -6806,11 +6817,11 @@ done: * be cleared and not flushed, and the call can't be part of a * sequence of flushes. * - * If the caller knows the address of the skip list node at - * which the target entry resides, it can avoid a lookup - * by supplying that address in the tgt_node_ptr parameter. - * If this parameter is NULL, the function will do a skip list - * search for the entry instead. + * If the caller knows the address of the skip list node at + * which the target entry resides, it can avoid a lookup + * by supplying that address in the tgt_node_ptr parameter. + * If this parameter is NULL, the function will do a skip list + * search for the entry instead. * * The function does nothing silently if there is no entry * at the supplied address, or if the entry found has the @@ -7611,22 +7622,17 @@ H5C__load_entry(H5F_t *f, #endif /* H5_HAVE_PARALLEL */ const H5C_class_t *type, haddr_t addr, void *udata) { - hbool_t dirty = FALSE; /* Flag indicating whether thing */ - /* was dirtied during deserialize */ - uint8_t * image = NULL; /* Buffer for disk image */ - void * thing = NULL; /* Pointer to thing loaded */ - H5C_cache_entry_t *entry = NULL; /* Alias for thing loaded, as */ - /* cache entry */ -#if 0 -size_t init_len; -#endif - size_t len; /* Size of image in file */ + hbool_t dirty = FALSE; /* Flag indicating whether thing was dirtied during deserialize */ + uint8_t * image = NULL; /* Buffer for disk image */ + void * thing = NULL; /* Pointer to thing loaded */ + H5C_cache_entry_t *entry = NULL; /* Alias for thing loaded, as cache entry */ + size_t len; /* Size of image in file */ #ifdef H5_HAVE_PARALLEL - int mpi_rank = 0; /* MPI process rank */ - MPI_Comm comm = MPI_COMM_NULL; /* File MPI Communicator */ - int mpi_code; /* MPI error code */ -#endif /* H5_HAVE_PARALLEL */ - void *ret_value = NULL; /* Return value */ + int mpi_rank = 0; /* MPI process rank */ + MPI_Comm comm = MPI_COMM_NULL; /* File MPI Communicator */ + int mpi_code; /* MPI error code */ +#endif /* H5_HAVE_PARALLEL */ + void *ret_value = NULL; /* Return value */ FUNC_ENTER_STATIC @@ -7746,15 +7752,11 @@ init_len = len; /* If the entry could be read speculatively and the length is still * changing, check for updating the actual size */ - if ((type->flags & H5C__CLASS_SPECULATIVE_LOAD_FLAG) && (len_changed)) { - + if ((type->flags & H5C__CLASS_SPECULATIVE_LOAD_FLAG) && len_changed) { /* Retrieve the actual length */ actual_len = len; - if (type->get_final_load_size(image, len, udata, &actual_len) < 0) { - - /* Transfer control to while() and count towards retries */ - continue; - } + if (type->get_final_load_size(image, len, udata, &actual_len) < 0) + continue; /* Transfer control to while() and count towards retries */ /* Check for the length changing */ if (actual_len != len) { @@ -7792,11 +7794,11 @@ init_len = len; * initial portion of the buffer. * * In addition to being of questionable utility, - * this optimization changed the invarient that + * this optimization changed the invariant that * that metadata is read and written atomically. * While this didn't cause immediate problems, * the page buffer in VFD SWMR depends on this - * invarient in its management of multi-page + * invariant in its management of multi-page * metadata entries. * * To repair this issue, I have reverted to @@ -7812,7 +7814,7 @@ init_len = len; * disable it in the VFD SWMR case. * * While this issue was detected in the global - * heap case, note that the super bloc, the + * heap case, note that the super block, the * local heap, and the fractal heap also use * speculative loads. * @@ -8338,7 +8340,7 @@ done: /*------------------------------------------------------------------------- * - * Function: H5C__validate_lru_list + * Function: H5C_validate_lru_list * * Purpose: Debugging function that scans the LRU list for errors. * @@ -8358,15 +8360,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); @@ -8406,7 +8408,7 @@ H5C__validate_lru_list(H5C_t *cache_ptr) entry_ptr = entry_ptr->next; } - if ((cache_ptr->LRU_list_len != len) || (cache_ptr->LRU_list_size != size)) + if ((cache_ptr->LRU_list_len != (uint32_t)len) || (cache_ptr->LRU_list_size != size)) HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 8 failed") done: @@ -8414,12 +8416,12 @@ done: 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. @@ -8439,15 +8441,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); @@ -8490,7 +8492,7 @@ H5C__validate_pinned_entry_list(H5C_t *cache_ptr) entry_ptr = entry_ptr->next; } - if ((cache_ptr->pel_len != len) || (cache_ptr->pel_size != size)) + if ((cache_ptr->pel_len != (uint32_t)len) || (cache_ptr->pel_size != size)) HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 9 failed") done: @@ -8498,12 +8500,12 @@ done: 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. @@ -8523,15 +8525,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); @@ -8574,7 +8576,7 @@ H5C__validate_protected_entry_list(H5C_t *cache_ptr) entry_ptr = entry_ptr->next; } - if ((cache_ptr->pl_len != len) || (cache_ptr->pl_size != size)) + if ((cache_ptr->pl_len != (uint32_t)len) || (cache_ptr->pl_size != size)) HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 9 failed") done: @@ -8582,12 +8584,12 @@ done: 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 @@ -8605,8 +8607,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; @@ -8634,7 +8636,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 */ /*------------------------------------------------------------------------- @@ -8703,7 +8705,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 @@ -9124,8 +9126,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 */ @@ -9134,7 +9136,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). */ { @@ -9291,8 +9293,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 @@ -9342,7 +9344,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) { @@ -9569,7 +9571,7 @@ done: * *------------------------------------------------------------------------- */ -herr_t +static herr_t H5C__generate_image(H5F_t *f, H5C_t *cache_ptr, H5C_cache_entry_t *entry_ptr) { haddr_t new_addr = HADDR_UNDEF; @@ -9578,7 +9580,7 @@ H5C__generate_image(H5F_t *f, H5C_t *cache_ptr, H5C_cache_entry_t *entry_ptr) unsigned serialize_flags = H5C__SERIALIZE_NO_FLAGS_SET; herr_t ret_value = SUCCEED; - FUNC_ENTER_PACKAGE + FUNC_ENTER_STATIC /* Sanity check */ HDassert(f); @@ -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... :-) */ @@ -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..8ec1c59 100644 --- a/src/H5CXprivate.h +++ b/src/H5CXprivate.h @@ -160,6 +160,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 7784c3b..58b6bbe 100644 --- a/src/H5Cdbg.c +++ b/src/H5Cdbg.c @@ -1012,9 +1012,9 @@ H5C__dump_entry(H5C_t *cache_ptr, const H5C_cache_entry_t *entry_ptr, hbool_t du * 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/H5Cimage.c b/src/H5Cimage.c index 659382b..bdfba08 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. @@ -1192,7 +1192,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 @@ -1884,7 +1884,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 @@ -2401,7 +2401,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 @@ -2563,7 +2563,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. */ @@ -3444,7 +3444,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 5fc255f..dd286a9 100644 --- a/src/H5Cpkg.h +++ b/src/H5Cpkg.h @@ -999,7 +999,7 @@ if ( ( ( ( (head_ptr) == NULL ) || ( (tail_ptr) == NULL ) ) && \ * ***********************************************************************/ -/* H5C__HASH_TABLE_LEN is defined in H5Cpkg.h. It must be a power of two. */ +/* H5C__HASH_TABLE_LEN is defined in H5Cpkg.h. It mut be a power of two. */ #define H5C__HASH_MASK ((size_t)(H5C__HASH_TABLE_LEN - 1) << 3) @@ -1642,7 +1642,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. */ @@ -4664,7 +4664,7 @@ typedef struct H5C_tag_info_t { * This field exists because the fixed and variable length * array cache clients allocate numerous entries in a single * block, and sub-allocate metadata cache entries out of this - * block. The effect of this is to break the invarient, + * block. The effect of this is to break the invariant, * normally maintained by the free space managers in paged * allocation mode, that no entry of less than a page in * size crosses page boundaries, and that entries of page @@ -4674,7 +4674,7 @@ typedef struct H5C_tag_info_t { * * The correct solution is to modify the fixed and variable * length array cache client to repair this. However, in - * the interrim, this field exists to detect similar + * the interim, this field exists to detect similar * behaviour elsewhere. * * To complicate matters, speculative reads for metadata @@ -5029,7 +5029,7 @@ typedef struct H5C_tag_info_t { * This field exists because the fixed and variable length * array cache clients allocate numerous entries in a single * block, and sub-allocate metadata cache entries out of this - * block. The effect of this is to break the invarient, + * block. The effect of this is to break the invariant, * normally maintained by the free space managers in paged * allocation mode, that no entry of less than a page in * size crosses page boundaries, and that entries of page @@ -5039,7 +5039,7 @@ typedef struct H5C_tag_info_t { * * The correct solution is to modify the fixed and variable * length array cache client to repair this. However, in - * the interrim, this field exists to detect similar + * the interim, this field exists to detect similar * behaviour elsewhere. * ****************************************************************************/ @@ -5317,7 +5317,6 @@ 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, hbool_t write_permitted); H5_DLL herr_t H5C__flush_marked_entries(H5F_t * f); -H5_DLL herr_t H5C__generate_image(H5F_t *f, H5C_t *cache_ptr, H5C_cache_entry_t *entry_ptr); H5_DLL herr_t H5C__serialize_cache(H5F_t *f); H5_DLL herr_t H5C__iter_tagged_entries(H5C_t *cache, haddr_t tag, hbool_t match_global, H5C_tag_iter_cb_t cb, void *cb_ctx); diff --git a/src/H5Cprefetched.c b/src/H5Cprefetched.c index 74573d0..fd5153d 100644 --- a/src/H5Cprefetched.c +++ b/src/H5Cprefetched.c @@ -303,7 +303,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 cbc34b2..524a276 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 @@ -879,7 +879,7 @@ typedef struct H5C_t H5C_t; * managers. * * The refresh entry callback exists to address this issue. As - * indicated above, it is essential for the superblock, and desireable + * indicated above, it is essential for the superblock, and desirable * whenever it is not possible to simply evict an entry that resides * in a modified page cache page. * @@ -1528,7 +1528,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. @@ -1643,7 +1643,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 @@ -1680,7 +1680,7 @@ typedef int H5C_ring_t; * * refreshed_in_tick: When an entry is refreshed as part of the VFD SWMR * reader end of tick processing, this field is used to - * record the tick in which this occured. The field is + * record the tick in which this occurred. The field is * used primarily for sanity checking. * * pi_next: Next pointer used by the page index hash table that maps @@ -1869,7 +1869,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. @@ -2312,7 +2312,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 @@ -2434,6 +2434,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/H5Cquery.c b/src/H5Cquery.c index d95dd87..d62c61a 100644 --- a/src/H5Cquery.c +++ b/src/H5Cquery.c @@ -201,7 +201,7 @@ H5C_get_cache_hit_rate(const H5C_t *cache_ptr, double *hit_rate_ptr) if (cache_ptr->cache_accesses > 0) *hit_rate_ptr = ((double)(cache_ptr->cache_hits)) / ((double)(cache_ptr->cache_accesses)); else - *hit_rate_ptr = 0.0f; + *hit_rate_ptr = 0.0; done: FUNC_LEAVE_NOAPI(ret_value) @@ -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 cd54c3a..9078877 100644 --- a/src/H5Dchunk.c +++ b/src/H5Dchunk.c @@ -239,10 +239,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 { @@ -258,14 +262,13 @@ typedef struct H5D_chunk_iter_ud_t { 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); + 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); @@ -290,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); @@ -309,8 +309,6 @@ static herr_t H5D__chunk_mem_cb(void *elem, const H5T_t *type, unsigned ndims, 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, @@ -318,9 +316,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 */ @@ -331,13 +329,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 */ @@ -966,7 +975,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 */ @@ -1059,7 +1068,7 @@ 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) + 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 */ @@ -1090,7 +1099,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 */ @@ -1354,7 +1363,7 @@ done: * *------------------------------------------------------------------------- */ -static void * +void * H5D__chunk_mem_alloc(size_t size, const H5O_pline_t *pline) { void *ret_value = NULL; /* Return value */ @@ -1385,7 +1394,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; @@ -1409,7 +1418,7 @@ H5D__chunk_mem_xfree(void *chk, const void *_pline) * calls H5D__chunk_mem_xfree and discards the return value. *------------------------------------------------------------------------- */ -static void +void H5D__chunk_mem_free(void *chk, const void *_pline) { (void)H5D__chunk_mem_xfree(chk, _pline); @@ -1429,7 +1438,7 @@ H5D__chunk_mem_free(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 */ @@ -2251,7 +2260,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) { @@ -2466,8 +2474,7 @@ 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 */ @@ -2543,7 +2550,7 @@ H5D__chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_ 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-existant chunk & skip it if appropriate */ + /* 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 */ @@ -2629,8 +2636,7 @@ 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 */ @@ -3211,7 +3217,9 @@ H5D__chunk_lookup(const H5D_t *dset, const hsize_t *scaled, H5D_chunk_ud_t *udat unsigned idx = 0; /* Index of chunk in cache, if present */ hbool_t found = FALSE; /* In cache? */ #ifdef H5_HAVE_PARALLEL - hbool_t reenable_coll_md_reads = FALSE; + 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 */ @@ -3285,11 +3293,10 @@ H5D__chunk_lookup(const H5D_t *dset, const hsize_t *scaled, H5D_chunk_ud_t *udat * processes. */ if (H5F_HAS_FEATURE(idx_info.f, H5FD_FEAT_HAS_MPI)) { - hbool_t do_coll_md_reads = H5CX_get_coll_metadata_read(); - if (do_coll_md_reads) { - H5CX_set_coll_metadata_read(FALSE); - reenable_coll_md_reads = TRUE; - } + 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 */ @@ -3335,8 +3342,8 @@ H5D__chunk_lookup(const H5D_t *dset, const hsize_t *scaled, H5D_chunk_ud_t *udat done: #ifdef H5_HAVE_PARALLEL /* Re-enable collective metadata reads if we disabled them */ - if (reenable_coll_md_reads) - H5CX_set_coll_metadata_read(TRUE); + 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) @@ -3648,7 +3655,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. */ @@ -4352,8 +4359,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 */ @@ -4400,8 +4407,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 */ @@ -4673,19 +4680,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; @@ -4758,7 +4772,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 */ @@ -4774,8 +4788,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) @@ -4969,27 +4983,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") @@ -5005,39 +5027,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; + + /* 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) - /* MSC - should not need this if MPI_type_create_hindexed_block is working */ - block_lens[i] = block_len; +#if MPI_VERSION >= 3 && MPI_SUBVERSION >= 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 @@ -5045,32 +5117,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 */ @@ -5113,39 +5224,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 */ /*------------------------------------------------------------------------- @@ -5253,7 +5350,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 */ @@ -5998,7 +6095,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 */ @@ -6729,10 +6826,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, @@ -6859,7 +6956,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) { @@ -7154,6 +7251,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 @@ -7558,7 +7738,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..356a54e 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 */ /********************/ @@ -55,8 +64,8 @@ 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); + 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 */ @@ -228,8 +248,8 @@ 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) + 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..3828e8e 100644 --- a/src/H5Dcontig.c +++ b/src/H5Dcontig.c @@ -91,8 +91,7 @@ typedef struct H5D_contig_writevv_ud_t { 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); + 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[]); @@ -109,13 +108,24 @@ static herr_t H5D__contig_write_one(H5D_io_info_t *io_info, hsize_t offset, size /*********************/ /* 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 +278,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; @@ -550,8 +567,8 @@ 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) + 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 @@ -574,8 +591,8 @@ 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 */ @@ -609,8 +626,8 @@ 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 */ diff --git a/src/H5Dearray.c b/src/H5Dearray.c index bef453d..0174a76 100644 --- a/src/H5Dearray.c +++ b/src/H5Dearray.c @@ -418,7 +418,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) @@ -574,7 +574,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..a30955b 100644 --- a/src/H5Defl.c +++ b/src/H5Defl.c @@ -62,7 +62,7 @@ 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); + 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 */ @@ -198,8 +210,8 @@ 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) + 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 8293ec4..8c031e4 100644 --- a/src/H5Dfarray.c +++ b/src/H5Dfarray.c @@ -416,7 +416,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) 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 a287ae8..15092f3 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 d1861c4..e226a0a 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 */ @@ -810,86 +821,35 @@ H5D__ioinfo_adjust(H5D_io_info_t *io_info, const H5D_t *dset, const H5S_t *file_ io_info->io_ops.single_write = H5D__mpio_select_write; } /* 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++) { - size_t cause_strlen = HDstrlen(cause_strings[idx]); - - if (cause & local_no_collective_cause) { - /* Check if there were any previous error messages included. If so, prepend a - * semicolon to separate the messages. - */ - if (local_error_message_previously_written) - HDstrncat(local_no_collective_cause_string, "; ", 2); - - HDstrncat(local_no_collective_cause_string, cause_strings[idx], cause_strlen); - - local_error_message_previously_written = TRUE; - } /* end if */ - - if (cause & global_no_collective_cause) { - /* Check if there were any previous error messages included. If so, prepend a - * semicolon to separate the messages. - */ - if (global_error_message_previously_written) - HDstrncat(global_no_collective_cause_string, "; ", 2); - - HDstrncat(global_no_collective_cause_string, cause_strings[idx], cause_strlen); - - 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..527fc7b 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(). + * filtered I/O in the function H5D__mpio_collective_filtered_chunk_io_setup(). This + * struct's fields are as follows: * - * This struct's fields are as follows: + * 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: * - * 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. + * chunk_idx - The index of the chunk in the dataset's chunk index. * - * 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. + * 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. * - * 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. + * need_insert - A flag which determines whether or not a chunk needs to be re-inserted into + * the chunk index after the write operation. * - * 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. + * 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. * - * 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. + * 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. * - * 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_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_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. + * 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. * - * Its fields are as follows: + * 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. * - * 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. + * 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. * - * 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. + * chunk_buf_size - The size in bytes of the data buffer allocated for the chunk * - * 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. + * 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. * - * Its fields are as follows: + * new_owner - The MPI rank which has been selected to perform the modifications to this 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. + * 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. * - * new_owner - The processor which has been selected to perform the write to this chunk. + * 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. * - * 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. + * hh - A handle for hash tables provided by the uthash.h header * - * Its fields are as follows: - * - * 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. - * - * 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); \ + fflush(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__); \ + fflush(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)strlen(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)strlen(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 = time(NULL); + HDfprintf(debug_log_file, "##### %s", asctime(localtime(&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); + /* 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); - 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") - - /* 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__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 (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 (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") + mpi_buf_count = (file_type_is_derived || mem_type_is_derived) ? 1 : 0; - 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) - - /* 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 MPI_VERSION >= 3 + /* + * 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; + + 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; - /* The new owner of the chunk is determined by the process + /* Set index for the beginning of this section of duplicate chunk entries */ + set_begin_index = i; + + /* + * 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]; + + 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]++; + } - /* 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 + /* + * 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; + + 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) + } - /* 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. +#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 MPI_VERSION >= 3 + 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 MPI_VERSION >= 3 + 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 - /* 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") + /* Initialize temporary I/O info */ + coll_io_info = *io_info; + coll_io_info.u.rbuf = NULL; - 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; + 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 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. + /* 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); + } + + /* + * 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 - iter_nelmts = H5S_GET_SELECT_NPOINTS(chunk_info->fspace); + 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 (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") + /* Set size of full chunks in dataset */ + file_chunk_size = io_info->dset->shared->layout.u.chunk.size; - 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") + /* 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); + } - iter_nelmts = H5S_GET_SELECT_NPOINTS(chunk_info->mspace); + /* + * 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); - 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") + chunk_list[i].chunk_buf_size = MAX(chunk_list[i].chunk_current.length, file_chunk_size); + /* + * 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 (!index_empty) { + /* + * Setup for I/O operation + */ - 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") + /* Initialize temporary I/O info */ + coll_io_info = *io_info; + coll_io_info.op_type = H5D_IO_OP_READ; - /* 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") + /* 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; - if (H5S_SELECT_ITER_RELEASE(mem_iter) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "couldn't release selection iterator") - mem_iter_init = FALSE; + /* 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") + } - /* 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; + /* + * Now that all owned chunks have been read, update the chunks + * with modification data from the owning rank and other ranks. + */ - iter_nelmts = H5S_GET_SELECT_NPOINTS(chunk_info->fspace); + /* 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); - /* 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") + chunk_info = chunk_list[i].chunk_info; - if (H5S_SELECT_ITER_RELEASE(mem_iter) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "couldn't release selection iterator") - mem_iter_init = FALSE; + /* + * 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") + } - 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) + /* 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") - /* For each asynchronous receive call previously posted, receive the chunk modification - * buffer from another rank and update the chunk data + /* 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. */ - for (i = 0; i < (size_t)chunk_entry->async_info.num_receive_requests; i++) { - const unsigned char *mod_data_p; - - /* 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))) + 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 (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_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 MPI_VERSION >= 3 + 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 MPI_VERSION >= 3 + 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 MPI_VERSION >= 3 && MPI_SUBVERSION >= 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 (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 (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__filtered_collective_chunk_entry_io() */ +} /* 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 92ea120..5114d6a 100644 --- a/src/H5Dpkg.h +++ b/src/H5Dpkg.h @@ -123,13 +123,12 @@ 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, - struct H5D_chunk_map_t *cm); + 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 { @@ -347,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 */ @@ -435,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. */ @@ -561,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); @@ -582,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); @@ -618,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); @@ -637,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 @@ -687,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); @@ -696,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 eba569e..a843d88 100644 --- a/src/H5Dsingle.c +++ b/src/H5Dsingle.c @@ -126,8 +126,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 d5375c1..7158e05 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 */ @@ -1310,7 +1321,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) { @@ -1320,7 +1331,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() */ @@ -1488,7 +1498,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") @@ -1966,7 +1976,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") @@ -2243,10 +2253,38 @@ H5D__virtual_init(H5F_t *f, const H5D_t *dset, hid_t dapl_id) storage->printf_gap = (hsize_t)0; /* Retrieve VDS file FAPL to layout */ - if (storage->source_fapl <= 0) + if (storage->source_fapl <= 0) { + H5P_genplist_t * source_fapl = NULL; /* Source file FAPL */ + H5F_close_degree_t close_degree = H5F_CLOSE_WEAK; /* Close degree for source files */ + if ((storage->source_fapl = H5F_get_access_plist(f, FALSE)) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get fapl") + /* Get property list pointer */ + if (NULL == (source_fapl = (H5P_genplist_t *)H5I_object(storage->source_fapl))) + HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, H5I_INVALID_HID, "not a property list") + + /* Source files must always be opened with H5F_CLOSE_WEAK close degree */ + if (H5P_set(source_fapl, H5F_ACS_CLOSE_DEGREE_NAME, &close_degree) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file close degree") + } /* end if */ +#ifndef NDEBUG + else { + H5P_genplist_t * source_fapl = NULL; /* Source file FAPL */ + H5F_close_degree_t close_degree; /* Close degree for source files */ + + /* Get property list pointer */ + if (NULL == (source_fapl = (H5P_genplist_t *)H5I_object(storage->source_fapl))) + HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, H5I_INVALID_HID, "not a property list") + + /* Verify H5F_CLOSE_WEAK close degree is set */ + if (H5P_get(source_fapl, H5F_ACS_CLOSE_DEGREE_NAME, &close_degree) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get file close degree") + + HDassert(close_degree == H5F_CLOSE_WEAK); + } /* end else */ +#endif /* NDEBUG */ + /* Copy DAPL to layout */ if (storage->source_dapl <= 0) if ((storage->source_dapl = H5P_copy_plist(dapl, FALSE)) < 0) @@ -2322,7 +2360,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( @@ -2355,8 +2393,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 */ @@ -2656,7 +2694,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 * @@ -2666,7 +2704,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 */ @@ -2726,8 +2764,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 */ @@ -2846,7 +2884,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 * @@ -2856,7 +2894,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 */ @@ -2919,7 +2957,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/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 c8696b3..c8d1c7b 100644 --- a/src/H5ESpublic.h +++ b/src/H5ESpublic.h @@ -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 6975d3d..05a8762 100644 --- a/src/H5FAcache.c +++ b/src/H5FAcache.c @@ -946,7 +946,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..59d3652 100644 --- a/src/H5FAprivate.h +++ b/src/H5FAprivate.h @@ -134,7 +134,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); @@ -67,9 +67,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 */ /*****************************/ @@ -103,20 +100,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") @@ -126,7 +123,7 @@ H5FD__init_package(void) done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD__init_package() */ +} /*------------------------------------------------------------------------- * Function: H5FD_term_package @@ -150,20 +147,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() */ @@ -173,7 +164,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 * @@ -309,6 +300,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 @@ -406,7 +453,7 @@ H5FD_sb_size(H5FD_t *file) { hsize_t ret_value = 0; - FUNC_ENTER_NOAPI(0) + FUNC_ENTER_NOAPI_NOERR /* Sanity checks */ HDassert(file); @@ -416,7 +463,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) } @@ -544,7 +590,7 @@ H5FD_fapl_get(H5FD_t *file) { void *ret_value = NULL; - FUNC_ENTER_NOAPI(NULL) + FUNC_ENTER_NOAPI_NOERR /* Sanity checks */ HDassert(file); @@ -554,7 +600,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() */ @@ -826,9 +871,6 @@ H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr) /* Dispatch to file driver */ if (HADDR_UNDEF == maxaddr) maxaddr = driver->maxaddr; -#if 0 /* JRM */ - HDfprintf(stderr, "H5FD_open(): calling %s.open().\n", driver->name); -#endif /* JRM */ if (NULL == (file = (driver->open)(name, flags, fapl_id, maxaddr))) HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, NULL, "open failed") @@ -875,7 +917,6 @@ H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr) ret_value = file; done: - /* XXX We leak H5FD_t's on many error conditions. */ /* Can't cleanup 'file' information, since we don't know what type it is */ FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD_open() */ @@ -1015,10 +1056,9 @@ 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) + if ((!f1 || !f1->cls) && (!f2 || !f2->cls)) HGOTO_DONE(0) if (!f1 || !f1->cls) HGOTO_DONE(-1) if (!f2 || !f2->cls) @@ -1376,7 +1416,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); @@ -1384,7 +1424,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() */ @@ -1456,7 +1495,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) @@ -1820,6 +1859,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 callback 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..a1750ee 100644 --- a/src/H5FDcore.c +++ b/src/H5FDcore.c @@ -149,8 +149,10 @@ 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_CORE_VALUE, /* value */ "core", /* name */ MAXADDR, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -183,9 +185,15 @@ static const H5FD_class_t H5FD_core_g = { 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 +398,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 +416,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 +458,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 +478,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 +538,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 +548,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 +632,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 +757,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 +928,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 +1522,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 +1744,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 a723a1d..fd62ad7 100644 --- a/src/H5FDdevelop.h +++ b/src/H5FDdevelop.h @@ -160,6 +160,7 @@ typedef struct H5FD_t H5FD_t; /* Class information for each file driver */ typedef struct H5FD_class_t { + H5FD_class_value_t value; const char * name; haddr_t maxaddr; H5F_close_degree_t fc_degree; @@ -192,6 +193,7 @@ typedef struct H5FD_class_t { 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; @@ -237,7 +239,10 @@ struct H5FD_t { extern "C" { #endif +H5_DLL hid_t H5FDperform_init(hid_t (*)(void)); 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); @@ -258,6 +263,7 @@ 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..7a43117 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,7 @@ 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_DIRECT_VALUE, /* value */ "direct", /* name */ MAXADDR, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -172,48 +175,13 @@ static const H5FD_class_t H5FD_direct_g = { 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 +199,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 +276,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 +329,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 +459,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 +508,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..4e54197 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,7 @@ 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_FAMILY_VALUE, /* value */ "family", /* name */ HADDR_MAX, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -137,34 +145,125 @@ static const H5FD_class_t H5FD_family_g = { 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 = strstr(old_filename, ".h5"))) { + /* Insert the printf format between the filename and ".h5" extension. */ + HDstrcpy(tmp_buffer, old_filename); + file_extension = strstr(tmp_buffer, ".h5"); + HDsprintf(file_extension, "%s%s", suffix, ".h5"); + } + else if ((file_extension = strrchr(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 = strrchr(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 +282,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 +292,6 @@ H5FD_family_init(void) /* Set return value */ ret_value = H5FD_FAMILY_g; -done: FUNC_LEAVE_NOAPI(ret_value) } /* H5FD_family_init() */ @@ -242,7 +340,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 +349,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 +690,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 +707,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 +756,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 +772,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 +1485,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 +1501,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 +1528,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 +1574,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..4927a40 100644 --- a/src/H5FDhdfs.c +++ b/src/H5FDhdfs.c @@ -278,6 +278,7 @@ 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_HDFS_VALUE, /* value */ "hdfs", /* name */ MAXADDR, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -310,6 +311,7 @@ static const H5FD_class_t H5FD_hdfs_g = { NULL, /* lock */ NULL, /* unlock */ NULL, /* del */ + NULL, /* ctl */ H5FD_FLMAP_DICHOTOMY /* fl_map */ }; @@ -317,29 +319,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 +530,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 +602,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 23dfa4d..d09801f 100644 --- a/src/H5FDint.c +++ b/src/H5FDint.c @@ -35,6 +35,7 @@ #include "H5Fprivate.h" /* File access */ #include "H5FDpkg.h" /* File Drivers */ #include "H5Iprivate.h" /* IDs */ +#include "H5PLprivate.h" /* Plugins */ /****************/ /* Local Macros */ @@ -44,6 +45,20 @@ /* Local Typedefs */ /******************/ +/* 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 +66,7 @@ /********************/ /* Local Prototypes */ /********************/ +static int H5FD__get_driver_cb(void *obj, hid_t id, void *_op_data); /*********************/ /* Package Variables */ @@ -166,21 +182,23 @@ H5FD_read(H5FD_t *file, H5FD_mem_t type, haddr_t addr, size_t size, void *buf /* HGOTO_DONE(SUCCEED) #endif /* H5_HAVE_PARALLEL */ - /* 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 0 /* JRM */ - if(!(file->access_flags & H5F_ACC_SWMR_READ)) { - haddr_t eoa; + /* 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)) { + haddr_t eoa; - if(HADDR_UNDEF == (eoa = (file->cls->get_eoa)(file, type))) + if (HADDR_UNDEF == (eoa = (file->cls->get_eoa)(file, type))) HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver get_eoa request failed") - if((addr + file->base_addr + size) > eoa) - HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "addr overflow, addr = %llu, size = %llu, eoa = %llu", (unsigned long long)(addr + file->base_addr), (unsigned long long)size, (unsigned long long)eoa) + if ((addr + file->base_addr + size) > eoa) + HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "addr overflow, addr = %llu, size = %llu, eoa = %llu", + (unsigned long long)(addr + file->base_addr), (unsigned long long)size, + (unsigned long long)eoa) } #endif /* JRM */ @@ -425,3 +443,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..af34682 100644 --- a/src/H5FDlog.c +++ b/src/H5FDlog.c @@ -180,78 +180,50 @@ 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 = { - "log", /* name */ - MAXADDR, /* maxaddr */ - H5F_CLOSE_WEAK, /* fc_degree */ - H5FD__log_term, /* terminate */ - NULL, /* sb_size */ - NULL, /* sb_encode */ - NULL, /* sb_decode */ - sizeof(H5FD_log_fapl_t), /* fapl_size */ - H5FD__log_fapl_get, /* fapl_get */ - H5FD__log_fapl_copy, /* fapl_copy */ - H5FD__log_fapl_free, /* fapl_free */ - 0, /* dxpl_size */ - NULL, /* dxpl_copy */ - NULL, /* dxpl_free */ - H5FD__log_open, /* open */ - H5FD__log_close, /* close */ - H5FD__log_cmp, /* cmp */ - H5FD__log_query, /* query */ - NULL, /* get_type_map */ - H5FD__log_alloc, /* alloc */ - H5FD__log_free, /* free */ - H5FD__log_get_eoa, /* get_eoa */ - H5FD__log_set_eoa, /* set_eoa */ - H5FD__log_get_eof, /* get_eof */ - H5FD__log_get_handle, /* get_handle */ - H5FD__log_read, /* read */ - H5FD__log_write, /* write */ - NULL, /* flush */ - H5FD__log_truncate, /* truncate */ - H5FD__log_lock, /* lock */ - H5FD__log_unlock, /* unlock */ - H5FD__log_delete, /* del */ - H5FD_FLMAP_DICHOTOMY /* fl_map */ + H5FD_LOG_VALUE, /* value */ + "log", /* name */ + MAXADDR, /* maxaddr */ + H5F_CLOSE_WEAK, /* fc_degree */ + H5FD__log_term, /* terminate */ + NULL, /* sb_size */ + NULL, /* sb_encode */ + NULL, /* sb_decode */ + sizeof(H5FD_log_fapl_t), /* fapl_size */ + H5FD__log_fapl_get, /* fapl_get */ + H5FD__log_fapl_copy, /* fapl_copy */ + H5FD__log_fapl_free, /* fapl_free */ + 0, /* dxpl_size */ + NULL, /* dxpl_copy */ + NULL, /* dxpl_free */ + H5FD__log_open, /* open */ + H5FD__log_close, /* close */ + H5FD__log_cmp, /* cmp */ + H5FD__log_query, /* query */ + NULL, /* get_type_map */ + H5FD__log_alloc, /* alloc */ + H5FD__log_free, /* free */ + H5FD__log_get_eoa, /* get_eoa */ + H5FD__log_set_eoa, /* set_eoa */ + H5FD__log_get_eof, /* get_eof */ + H5FD__log_get_handle, /* get_handle */ + H5FD__log_read, /* read */ + H5FD__log_write, /* write */ + 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 +240,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 +260,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 +328,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 +463,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 +505,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 +1543,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..e74901a 100644 --- a/src/H5FDmirror.c +++ b/src/H5FDmirror.c @@ -160,6 +160,7 @@ 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_MIRROR_VALUE, /* value */ "mirror", /* name */ MAXADDR, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -192,6 +193,7 @@ static const H5FD_class_t H5FD_mirror_g = { H5FD__mirror_lock, /* lock */ H5FD__mirror_unlock, /* unlock */ NULL, /* del */ + NULL, /* ctl */ H5FD_FLMAP_DICHOTOMY /* fl_map */ }; @@ -204,30 +206,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 +225,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 +1147,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 +1315,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..4aa8a96 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,61 @@ 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_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); /* 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 = { + 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_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 +155,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 +188,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 +243,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 +313,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 +385,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 +840,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 +899,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 +1029,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 */ @@ -1165,6 +1206,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 +1234,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 +1300,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 +1337,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); @@ -1307,11 +1366,21 @@ H5FD__mpio_read(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type, hid_t H5_ATTR_UNU 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 (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 @@ -1345,8 +1414,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, bytes_read, H5FD__mem_t_to_str(type)); #endif /* @@ -1356,6 +1425,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); @@ -1468,20 +1540,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 +1585,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); @@ -1562,8 +1635,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, bytes_written, H5FD__mem_t_to_str(type)); #endif /* Each process will keep track of its perceived EOF value locally, and @@ -1701,17 +1774,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 +1849,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 +1869,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..d9a6ce9 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,12 @@ 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 = { + H5_VFD_MULTI, /* value */ "multi", /* name */ HADDR_MAX, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -201,6 +209,7 @@ static const H5FD_class_t H5FD_multi_g = { H5FD_multi_lock, /* lock */ H5FD_multi_unlock, /* unlock */ H5FD_multi_delete, /* del */ + H5FD_multi_ctl, /* ctl */ H5FD_FLMAP_DEFAULT /* fl_map */ }; @@ -271,74 +280,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 +376,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 +386,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 +413,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 +426,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 +465,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 +1134,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 +2176,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 +2184,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 +2225,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/H5FDperform.c b/src/H5FDperform.c new file mode 100644 index 0000000..096fdd6 --- /dev/null +++ b/src/H5FDperform.c @@ -0,0 +1,58 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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(hid_t (*init)(void)) +{ + 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`, et + * cetera) 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 = init(); +done: + FUNC_LEAVE_API_NOINIT(ret_value) +} diff --git a/src/H5FDprivate.h b/src/H5FDprivate.h index 7c0dd77..4ba7060 100644 --- a/src/H5FDprivate.h +++ b/src/H5FDprivate.h @@ -88,7 +88,7 @@ * * struct H5FD_vfd_swmr_idx_entry_t * - * Indicies into the VFD SWMR metadata file are maintained in arrays of + * Indices into the VFD SWMR metadata file are maintained in arrays of * instances of H5FD_vfd_swmr_index_t. * * The fields of H5FD_vfd_swmr_idx_entry_t are discussed below. @@ -182,7 +182,7 @@ typedef struct H5FD_vfd_swmr_idx_entry_t { * tick_num: Sequence number of the current tick. * Initialized to zero on file creation/open, and incremented * by the VFD SWMR writer at the end of each tick. - * num_entries: The number of entires in the index. + * num_entries: The number of entries in the index. * entries: The array of index entries */ typedef struct H5FD_vfd_swmr_md_index { @@ -259,13 +259,6 @@ vfd_swmr_pageno_to_mdf_idx_entry(H5FD_vfd_swmr_idx_entry_t *idx, uint32_t nentri /* 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 /****************************/ @@ -302,12 +295,19 @@ 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; + /*****************************/ /* Library Private Variables */ /*****************************/ @@ -318,6 +318,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); @@ -328,11 +329,18 @@ 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); H5FD_t * H5FD_deduplicate(H5FD_t *, hid_t); 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); @@ -352,13 +360,14 @@ 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_get_driver_name(const H5FD_t *file, char **driver_name); +H5_DLL herr_t H5FD_init(void); /* Function prototypes for VFD SWMR */ H5_DLL int shadow_image_defer_free(struct H5F_shared_t *, const H5FD_vfd_swmr_idx_entry_t *); H5_DLL herr_t H5FD_vfd_swmr_get_tick_and_idx(H5FD_t *_file, hbool_t read_index, uint64_t *tick_ptr, @@ -382,9 +391,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..a8d85c6 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_SWMR ((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..922dac5 100644 --- a/src/H5FDros3.c +++ b/src/H5FDros3.c @@ -237,6 +237,7 @@ 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_ROS3_VALUE, /* value */ "ros3", /* name */ MAXADDR, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -269,6 +270,7 @@ static const H5FD_class_t H5FD_ros3_g = { NULL, /* lock */ NULL, /* unlock */ NULL, /* del */ + NULL, /* ctl */ H5FD_FLMAP_DICHOTOMY /* fl_map */ }; @@ -276,31 +278,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 +304,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 +358,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 +391,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 +401,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..46f5fd4 100644 --- a/src/H5FDsec2.c +++ b/src/H5FDsec2.c @@ -139,8 +139,11 @@ 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_SEC2_VALUE, /* value */ "sec2", /* name */ MAXADDR, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -173,6 +176,7 @@ static const H5FD_class_t H5FD_sec2_g = { H5FD__sec2_lock, /* lock */ H5FD__sec2_unlock, /* unlock */ H5FD__sec2_delete, /* del */ + H5FD__sec2_ctl, /* ctl */ H5FD_FLMAP_DICHOTOMY /* fl_map */ }; @@ -180,39 +184,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 +200,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 +220,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 +272,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 +1048,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..31438cd 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,12 @@ 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_SPLITTER_VALUE, /* value */ "splitter", /* name */ MAXADDR, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -138,7 +146,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 +157,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 */ @@ -162,7 +170,8 @@ static const H5FD_class_t H5FD_splitter_g = { 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 +182,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 +196,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 +205,6 @@ H5FD_splitter_init(void) ret_value = H5FD_SPLITTER_g; -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD_splitter_init() */ @@ -309,57 +293,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 +324,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 +353,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 +373,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 = strstr(base_filename, ".h5"))) { + /* Insert the suffix between the filename and ".h5" extension. */ + HDstrcpy(new_path, base_filename); + file_extension = strstr(new_path, ".h5"); + HDsprintf(file_extension, "%s%s", suffix, ".h5"); + } + else if ((file_extension = strrchr(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 = strrchr(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 +781,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 +798,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 +812,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 +861,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 +1286,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 +1476,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..122379a 100644 --- a/src/H5FDstdio.c +++ b/src/H5FDstdio.c @@ -183,6 +183,7 @@ 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 = { + H5_VFD_STDIO, /* value */ "stdio", /* name */ MAXADDR, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -215,6 +216,7 @@ static const H5FD_class_t H5FD_stdio_g = { H5FD_stdio_lock, /* lock */ H5FD_stdio_unlock, /* unlock */ H5FD_stdio_delete, /* del */ + NULL, /* ctl */ H5FD_FLMAP_DICHOTOMY /* fl_map */ }; @@ -242,7 +244,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/H5FDvfd_swmr.c b/src/H5FDvfd_swmr.c index 60812bd..11c177b 100644 --- a/src/H5FDvfd_swmr.c +++ b/src/H5FDvfd_swmr.c @@ -90,6 +90,7 @@ static htri_t H5FD__vfd_swmr_index_deserialize(const H5FD_vfd_swmr_t *file, H5FD static herr_t H5FD__vfd_swmr_load_hdr_and_idx(H5FD_vfd_swmr_t *, hbool_t); static const H5FD_class_t H5FD_vfd_swmr_g = { + H5FD_VFD_SWMR_VALUE, /* value */ "vfd_swmr", /* name */ MAXADDR, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -122,6 +123,7 @@ static const H5FD_class_t H5FD_vfd_swmr_g = { H5FD__vfd_swmr_lock, /* lock */ H5FD__vfd_swmr_unlock, /* unlock */ NULL, /* del */ + NULL, /* ctl */ H5FD_FLMAP_DICHOTOMY /* fl_map */ }; @@ -132,30 +134,6 @@ H5FL_DEFINE_STATIC(H5FD_vfd_swmr_t); H5FL_SEQ_DEFINE(H5FD_vfd_swmr_idx_entry_t); /*------------------------------------------------------------------------- - * Function: H5FD__init_package - * - * Purpose: Initializes any interface-specific data or routines. - * -b - * 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_vfd_swmr_init() < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "unable to initialize swmr VFD") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5FD__init_package() */ - -/*------------------------------------------------------------------------- * Function: H5FD_vfd_swmr_init * * Purpose: Initialize this driver by registering the driver with the @@ -174,7 +152,7 @@ H5FD_vfd_swmr_init(void) { hid_t ret_value = H5I_INVALID_HID; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR if (H5I_VFL != H5I_get_type(H5FD_VFD_SWMR_g)) H5FD_VFD_SWMR_g = H5FD_register(&H5FD_vfd_swmr_g, sizeof(H5FD_class_t), FALSE); @@ -182,7 +160,6 @@ H5FD_vfd_swmr_init(void) /* Set return value */ ret_value = H5FD_VFD_SWMR_g; -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD_vfd_swmr_init() */ @@ -231,7 +208,7 @@ H5Pset_fapl_vfd_swmr(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_VFD_SWMR, NULL); + ret_value = H5P_set_driver(plist, H5FD_VFD_SWMR, NULL, NULL); done: FUNC_LEAVE_API(ret_value) diff --git a/src/H5FDvfd_swmr.h b/src/H5FDvfd_swmr.h index 20a6b96..dfd8d19 100644 --- a/src/H5FDvfd_swmr.h +++ b/src/H5FDvfd_swmr.h @@ -16,7 +16,8 @@ #ifndef H5FDvfd_swmr_H #define H5FDvfd_swmr_H -#define H5FD_VFD_SWMR (H5FD_vfd_swmr_init()) +#define H5FD_VFD_SWMR (H5FDperform_init(H5FD_vfd_swmr_init)) +#define H5FD_VFD_SWMR_VALUE H5_VFD_SWMR #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..6519551 100644 --- a/src/H5FLprivate.h +++ b/src/H5FLprivate.h @@ -148,8 +148,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 +223,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 */ @@ -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 67983d3..679cb26 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 */ @@ -187,9 +187,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 d28358c..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 */ @@ -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 b80fd15..729aeea 100644 --- a/src/H5Fint.c +++ b/src/H5Fint.c @@ -92,9 +92,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. @@ -139,29 +136,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) @@ -173,7 +147,7 @@ H5F__init_package(void) done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5F__init_package() */ +} /* end H5F_init() */ /*------------------------------------------------------------------------- * Function: H5F_term_package @@ -197,23 +171,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() */ @@ -278,7 +246,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") || @@ -430,7 +398,7 @@ H5F_get_access_plist(H5F_t *f, hbool_t app_ref) } /* end if */ if (H5P_set(new_plist, H5F_ACS_VFD_SWMR_CONFIG_NAME, &(f->shared->vfd_swmr_config)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set initial metadata cache resize config.") + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set VFD SWMR config") #ifdef H5_HAVE_PARALLEL if (H5P_set(new_plist, H5_COLL_MD_READ_FLAG_NAME, &(f->shared->coll_md_read)) < 0) @@ -459,9 +427,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) @@ -1064,7 +1033,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 @@ -1161,7 +1130,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 @@ -1298,7 +1267,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") @@ -1874,7 +1843,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id) /* When configured with VFD SWMR */ if (vfd_swmr_config_ptr->version) { - /* Verify that file access flags are consistent with VFD SWMR configuartion */ + /* Verify that file access flags are consistent with VFD SWMR configuration */ if ((flags & H5F_ACC_RDWR) && !vfd_swmr_config_ptr->writer) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "file access is writer but VFD SWMR config is reader") if ((flags & H5F_ACC_RDWR) == 0 && vfd_swmr_config_ptr->writer) @@ -1910,7 +1879,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). @@ -2020,8 +1989,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id) /* Short cuts */ shared = file->shared; - - lf = shared->lf; + lf = shared->lf; /* Set the file locking flag. If the file is already open, the file * requested file locking flag must match that of the open file. @@ -3304,7 +3272,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. * @@ -3324,7 +3292,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 @@ -3755,7 +3723,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 @@ -3774,7 +3742,7 @@ herr_t H5F__start_swmr_write(H5F_t *f) { hbool_t ci_load = FALSE; /* whether MDC ci load requested */ - hbool_t ci_write = FALSE; /* whether MDC ci write requested */ + hbool_t ci_write = FALSE; /* whether MDC CI write requested */ size_t grp_dset_count = 0; /* # of open objects: groups & datasets */ size_t nt_attr_count = 0; /* # of opened named datatypes + opened attributes */ hid_t * obj_ids = NULL; /* List of ids */ 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 ca26941..2edcc60 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 @@ -218,10 +218,10 @@ typedef struct H5F_mtab_t { * the shadow file to release after max_lag ticks. */ typedef struct shadow_defree { - uint64_t offset; // offset of the region in *bytes* - uint32_t length; // length of the region in *bytes* - uint64_t tick_num; // tick number when the free was deferred - TAILQ_ENTRY(shadow_defree) link; // deferred-free queue linkage + uint64_t offset; /* offset of the region in *bytes* */ + uint32_t length; /* length of the region in *bytes* */ + uint64_t tick_num; /* tick number when the free was deferred */ + TAILQ_ENTRY(shadow_defree) link; /* deferred-free queue linkage */ } shadow_defree_t; /* Structure specifically to store superblock. This was originally @@ -247,10 +247,10 @@ typedef struct H5F_super_t { * the file below the SWMR VFD to release after a delay. */ typedef struct lower_defree { - SIMPLEQ_ENTRY(lower_defree) link; // deferred-free queue linkage - H5FD_mem_t alloc_type; // type with which the region was allocated - haddr_t addr; // start of the region *in bytes* - hsize_t size; // length of the region *in bytes* + SIMPLEQ_ENTRY(lower_defree) link; /* deferred-free queue linkage */ + H5FD_mem_t alloc_type; /* type with which the region was allocated */ + haddr_t addr; /* start of the region *in bytes* */ + hsize_t size; /* length of the region *in bytes* */ uint64_t free_after_tick; /* the region may be reused on tick * free_after_tick + 1 at the earliest */ @@ -385,7 +385,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 */ @@ -441,7 +441,7 @@ struct H5F_shared_t { */ uint32_t mdf_idx_entries_used; /* Number of entries in *mdf_idx * that are in use -- these will - * be contiguous at indicies 0 + * be contiguous at indices 0 * through mdf_idx_entries_used - 1. */ @@ -482,7 +482,7 @@ struct H5F_shared_t { * file */ uint64_t updater_seq_num; /* Sequence number of the next updater file to be - * genereated. This field must be initialized to zero, + * generated. This field must be initialized to zero, * and incremented after each updater file is generated. */ @@ -659,14 +659,14 @@ H5_DLL herr_t H5F__reparse_file_lock_variable_test(void); * in the testhdf5 program, which involves the test of a non-existing HDF5 file. */ -H5_DLL void H5F_post_vfd_swmr_log_entry(H5F_t *f, int entry_type_code, char *log_info); +H5_DLL void H5F__post_vfd_swmr_log_entry(H5F_t *f, int entry_type_code, const char *log_info); #define H5F_POST_VFD_SWMR_LOG_ENTRY_INTERNAL(fp, entry_type_code, log_info) \ do { \ if (fp != NULL) { \ if (fp->shared != NULL) { \ if (fp->shared->vfd_swmr_log_on == TRUE) { \ - H5F_post_vfd_swmr_log_entry(fp, entry_type_code, log_info); \ + H5F__post_vfd_swmr_log_entry(fp, entry_type_code, log_info); \ } \ } \ } \ diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index 9a4f363..e94ee64 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 */ @@ -938,7 +936,7 @@ typedef enum H5F_prefix_open_t { * the past tick is used to assemble the associated data in preparation for * writing an updater file. * - * Each entry in this array pertains to a given modified metdata page or + * Each entry in this array pertains to a given modified metadata page or * multi-page metadata entry, and contains the following fields: * * entry_image_ptr: void pointer to a buffer containing the image of the @@ -1187,6 +1185,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); /* VFD SWMR functions */ @@ -1247,6 +1246,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 7120085..6d292bf 100644 --- a/src/H5Fpublic.h +++ b/src/H5Fpublic.h @@ -322,7 +322,7 @@ typedef herr_t (*H5F_flush_cb_t)(hid_t object_id, void *udata); * An integer field indicating the threshold for the page buffer size. * During a tick, the page buffer must expand as necessary to retain copies * of all modified metadata pages and multi-page metadata entries. - * If the page buffer size exceeds this thresold, an early end of tick + * If the page buffer size exceeds this threshold, an early end of tick * will be triggered. * Note that this is not a limit on the maximum page buffer size, as the * metadata cache is flushed as part of end of tick processing. @@ -1727,7 +1727,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 * @@ -1806,7 +1806,6 @@ H5_DLL herr_t H5Fget_dset_no_attrs_hint(hid_t file_id, hbool_t *minimize); * */ H5_DLL herr_t H5Fset_dset_no_attrs_hint(hid_t file_id, hbool_t minimize); -H5_DLL herr_t H5Fwait(hid_t file_id); /* VFD SWMR */ /** @@ -2022,6 +2021,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? * */ @@ -2040,6 +2040,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 24b25ff..2665505 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 e7a3b53..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. */ @@ -1043,7 +1043,7 @@ done: HDONE_ERROR(H5E_FILE, H5E_CANTUNPIN, FAIL, "unable to unpin driver info") /* Evict the driver info block from the cache */ - if (H5AC_expunge_entry(f, H5AC_DRVRINFO, sblock->driver_addr, H5AC__NO_FLAGS_SET) < 0) + if (sblock && H5AC_expunge_entry(f, H5AC_DRVRINFO, sblock->driver_addr, H5AC__NO_FLAGS_SET) < 0) HDONE_ERROR(H5E_FILE, H5E_CANTEXPUNGE, FAIL, "unable to expunge driver info block") } /* end if */ diff --git a/src/H5Fsuper_cache.c b/src/H5Fsuper_cache.c index 7d1ff86..258570e 100644 --- a/src/H5Fsuper_cache.c +++ b/src/H5Fsuper_cache.c @@ -701,7 +701,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 */ @@ -800,7 +800,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/H5Fvfd_swmr.c b/src/H5Fvfd_swmr.c index e5189b7..06d0c0d 100644 --- a/src/H5Fvfd_swmr.c +++ b/src/H5Fvfd_swmr.c @@ -828,7 +828,7 @@ clean_shadow_index(H5F_t *f, uint32_t nentries, H5FD_vfd_swmr_idx_entry_t *idx, * dirty the first page in the HDF5 file. However, the * metadata cache will no longer exist at this point. * - * Thus, we must check for the existance of the metadata + * Thus, we must check for the existence of the metadata * cache, and only attempt to flush it if it exists. * * 3) If this is the first tick (i.e. tick == 1), create the @@ -1021,7 +1021,7 @@ update_eot: HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to insert entry into the EOT queue") done: - /* Kent: Calcuate the processing time and write the time info to the log file */ + /* Kent: Calculate the processing time and write the time info to the log file */ if (shared->vfd_swmr_log_on == true) { if (H5_timer_get_times(shared->vfd_swmr_log_start_time, ¤t_time) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get time from H5_timer_get_times") @@ -1060,7 +1060,7 @@ H5F_vfd_swmr_writer__dump_index(H5F_shared_t *shared) H5FD_vfd_swmr_idx_entry_t *index = NULL; herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR HDassert(shared); HDassert(shared->vfd_swmr); @@ -1080,8 +1080,6 @@ H5F_vfd_swmr_writer__dump_index(H5F_shared_t *shared) index[i].md_file_page_offset, index[i].length); } -done: - FUNC_LEAVE_NOAPI(ret_value) } /* end H5F_vfd_swmr_writer__dump_index() */ @@ -1105,11 +1103,11 @@ done: * * If any such pages or multi-page metadata entries are found: * - * a) direct the page buffer to evict any such superceeded + * a) direct the page buffer to evict any such superseded * pages, and * * b) direct the metadata cache to either evict or refresh - * any entries residing in the superceeded pages. + * any entries residing in the superseded pages. * * Note that this operation MUST be performed in this order, * as the metadata cache will refer to the page buffer @@ -2091,7 +2089,7 @@ done: */ void -H5F_post_vfd_swmr_log_entry(H5F_t *f, int entry_type_code, char *log_info) +H5F__post_vfd_swmr_log_entry(H5F_t *f, int entry_type_code, const char *log_info) { double temp_time; H5_timevals_t current_time; @@ -2276,7 +2274,7 @@ H5F__vfd_swmr_construct_ud_cl(H5F_vfd_swmr_updater_t *updater) * --determine num_change_list entries * --allocate buffers * --construct on disk image (serialize) of the updater header and change list - * --create updater file using a temporay file name: + * --create updater file using a temporary file name: * --<shared->vfd_swmr_config.updater_file_path>.ud_tmp * --allocate space and write the following to the updater file * --updater file header diff --git a/src/H5Gcache.c b/src/H5Gcache.c index df9943f..0ad3de0 100644 --- a/src/H5Gcache.c +++ b/src/H5Gcache.c @@ -135,7 +135,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 @@ -241,7 +241,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/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 */ /*****************************/ @@ -358,7 +355,7 @@ H5HF_insert(H5HF_t *fh, size_t size, const void *obj, void *id /*out*/) if (size > hdr->max_man_size) { /* Store 'huge' object in heap * - * Although not ideal, we can quiet the const warning here becuase no + * 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") diff --git a/src/H5HFcache.c b/src/H5HFcache.c index 654fa36..3a48018 100644 --- a/src/H5HFcache.c +++ b/src/H5HFcache.c @@ -799,7 +799,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 */ @@ -898,7 +898,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 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/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); @@ -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); @@ -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); + /* Sanity checks */ + HDassert(0 == H5I_nmembers(H5I_MAP)); - /* Destroy the dataset object id group */ - n += (H5I_dec_type_ref(H5I_MAP) > 0); - - /* 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() */ @@ -119,9 +119,6 @@ static herr_t H5MF__defer_free(H5F_shared_t *shared, H5FD_mem_t alloc_type, hadd /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /*****************************/ /* Library Private Variables */ /*****************************/ @@ -713,8 +710,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) @@ -766,7 +765,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 */ @@ -794,7 +793,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 */ @@ -838,7 +837,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 */ @@ -916,7 +915,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); @@ -956,7 +956,7 @@ H5MF__alloc_pagefs(H5F_t *f, H5FD_mem_t alloc_type, hsize_t size) FUNC_ENTER_STATIC_TAG(H5AC__FREESPACE_TAG) #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); @@ -1053,7 +1053,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); @@ -1099,7 +1100,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 */ @@ -1146,8 +1147,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 */ @@ -1224,7 +1225,7 @@ H5MF__xfree_inner_impl(H5F_t *f, H5FD_mem_t alloc_type, haddr_t addr, hsize_t si * 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 */ @@ -1240,8 +1241,9 @@ H5MF__xfree_inner_impl(H5F_t *f, H5FD_mem_t alloc_type, haddr_t addr, hsize_t si 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 */ @@ -1258,7 +1260,8 @@ H5MF__xfree_inner_impl(H5F_t *f, H5FD_mem_t alloc_type, haddr_t addr, hsize_t si */ 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 */ @@ -1352,7 +1355,7 @@ H5MF__xfree_impl(H5F_t *f, H5FD_mem_t alloc_type, haddr_t addr, hsize_t size) * Further, in the VFD SWMR case, the large metadata entry will typically * be buffered in the page buffer. If an intersecting entry is left * in the page buffer, in addition to causing potential corruption in - * the HDF5 file, it may also result in overlaping entries in the page + * the HDF5 file, it may also result in overlapping entries in the page * buffer and metadata file index. * * It's ok to remove the page from the PB without flushing to @@ -1416,7 +1419,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 */ @@ -1469,7 +1474,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: */ @@ -1507,7 +1512,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 */ @@ -1533,7 +1538,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 */ @@ -1544,7 +1549,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 */ @@ -1557,7 +1562,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); @@ -1592,8 +1597,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 */ @@ -1729,8 +1734,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 */ @@ -1739,8 +1745,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 4684ee2..e7b966c 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 e686842d..2f5103f 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) @@ -798,30 +801,20 @@ H5MF__sect_large_can_merge(const H5FS_section_info_t *_sect1, const H5FS_section const H5MF_free_section_t *sect2 = (const H5MF_free_section_t *)_sect2; /* File free section */ htri_t ret_value = FALSE; /* Return value */ - FUNC_ENTER_STATIC + FUNC_ENTER_STATIC_NOERR /* Check arguments. */ HDassert(sect1); HDassert(sect2); HDassert(sect1->sect_info.type == sect2->sect_info.type); /* Checks "MERGE_SYM" flag */ - if (!H5F_addr_lt(sect1->sect_info.addr, sect2->sect_info.addr)) { - HDfprintf(stderr, - "%s.%d: sect1->sect_info.addr %" PRIuHADDR ", sect2->sect_info.addr %" PRIuHADDR "\n", - __func__, __LINE__, sect1->sect_info.addr, sect2->sect_info.addr); - HDfprintf(stderr, - "%s.%d: sect1->sect_info.size %" PRIuHSIZE ", sect2->sect_info.size %" PRIuHSIZE "\n", - __func__, __LINE__, sect1->sect_info.size, sect2->sect_info.size); - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't merge") - } HDassert(H5F_addr_lt(sect1->sect_info.addr, sect2->sect_info.addr)); 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 */ -done: FUNC_LEAVE_NOAPI(ret_value) } /* H5MF__sect_large_can_merge() */ @@ -907,8 +900,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 */ @@ -58,9 +58,6 @@ /* Package Variable Definitions */ /********************************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /********************/ /* Static Variables */ /********************/ @@ -77,9 +77,6 @@ H5_DLL htri_t H5MV__try_extend_md(H5F_shared_t *, haddr_t, hsize_t); /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /*****************************/ /* Library Private Variables */ /*****************************/ diff --git a/src/H5MVprivate.h b/src/H5MVprivate.h index c02c6ae..b2a5458 100644 --- a/src/H5MVprivate.h +++ b/src/H5MVprivate.h @@ -14,7 +14,7 @@ * * Created: H5MVprivate.h * - * Purpose: Private header file for VFD SWMR free space mangement + * Purpose: Private header file for VFD SWMR free space management * *------------------------------------------------------------------------- */ 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 56f7145..c4f8b27 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 8eed092..84e68a1 100644 --- a/src/H5Ocache.c +++ b/src/H5Ocache.c @@ -277,7 +277,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 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 6716769..8367b93 100644 --- a/src/H5Ocopy.c +++ b/src/H5Ocopy.c @@ -962,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 e06e699..1cda3ea 100644 --- a/src/H5Ocopy_ref.c +++ b/src/H5Ocopy_ref.c @@ -170,31 +170,32 @@ H5O__copy_expand_ref_object1(H5O_loc_t *src_oloc, const void *buf_src, H5O_loc_t H5O_token_t tmp_token = {0}; /* If data is not initialized, copy zeros and skip */ - if (0 == HDmemcmp(src_buf, zeros, buf_size)) { + if (0 == HDmemcmp(src_buf, zeros, buf_size)) HDmemset(dst_buf, 0, buf_size); - continue; - } - - /* Set up for the object copy for the reference */ - if (H5R__decode_token_obj_compat(src_buf, &buf_size, &tmp_token, token_size) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "unable to decode src object address") - 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") - - if (!H5F_addr_defined(src_oloc->addr) || src_oloc->addr == 0) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "undefined reference pointer") - dst_oloc->addr = HADDR_UNDEF; - - /* 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 the object reference info for the destination file */ - 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__encode_token_obj_compat((const H5O_token_t *)&tmp_token, token_size, dst_buf, &buf_size) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "unable to encode dst object address") - } /* end for */ + else { + /* Set up for the object copy for the reference */ + if (H5R__decode_token_obj_compat(src_buf, &buf_size, &tmp_token, token_size) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "unable to decode src object address") + 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") + + if (!H5F_addr_defined(src_oloc->addr) || src_oloc->addr == 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "undefined reference pointer") + dst_oloc->addr = HADDR_UNDEF; + + /* 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 the object reference info for the destination file */ + 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__encode_token_obj_compat((const H5O_token_t *)&tmp_token, token_size, dst_buf, + &buf_size) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "unable to encode dst object address") + } /* end else */ + } /* end for */ done: FUNC_LEAVE_NOAPI(ret_value) @@ -232,43 +233,42 @@ H5O__copy_expand_ref_region1(H5O_loc_t *src_oloc, const void *buf_src, H5O_loc_t uint8_t * q; /* If data is not initialized, copy zeros and skip */ - if (0 == HDmemcmp(src_buf, zeros, buf_size)) { + if (0 == HDmemcmp(src_buf, zeros, buf_size)) HDmemset(dst_buf, 0, buf_size); - continue; - } - - /* Read from heap */ - if (H5R__decode_heap(src_oloc->file, src_buf, &buf_size, &data, &data_size) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "unable to decode dataset region information") - - /* Get object address */ - p = (const uint8_t *)data; - H5F_addr_decode(src_oloc->file, &p, &src_oloc->addr); - if (!H5F_addr_defined(src_oloc->addr) || src_oloc->addr == 0) { - H5MM_free(data); - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "undefined reference pointer") - } - dst_oloc->addr = HADDR_UNDEF; - - /* 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) { - H5MM_free(data); - HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object") - } /* end if */ - - /* Serialize object addr */ - q = (uint8_t *)data; - H5F_addr_encode(dst_oloc->file, &q, dst_oloc->addr); - - /* Write to heap */ - if (H5R__encode_heap(dst_oloc->file, dst_buf, &buf_size, data, (size_t)data_size) < 0) { + else { + /* Read from heap */ + if (H5R__decode_heap(src_oloc->file, src_buf, &buf_size, &data, &data_size) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "unable to decode dataset region information") + + /* Get object address */ + p = (const uint8_t *)data; + H5F_addr_decode(src_oloc->file, &p, &src_oloc->addr); + if (!H5F_addr_defined(src_oloc->addr) || src_oloc->addr == 0) { + H5MM_free(data); + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "undefined reference pointer") + } + dst_oloc->addr = HADDR_UNDEF; + + /* 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) { + H5MM_free(data); + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object") + } /* end if */ + + /* Serialize object addr */ + q = (uint8_t *)data; + H5F_addr_encode(dst_oloc->file, &q, dst_oloc->addr); + + /* Write to heap */ + if (H5R__encode_heap(dst_oloc->file, dst_buf, &buf_size, data, (size_t)data_size) < 0) { + H5MM_free(data); + HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "unable to encode dataset region information") + } + + /* Free the buffer allocated in H5R__decode_heap() */ H5MM_free(data); - HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "unable to encode dataset region information") - } - - /* Free the buffer allocated in H5R__decode_heap() */ - H5MM_free(data); - } /* end for */ + } /* end else */ + } /* end for */ done: FUNC_LEAVE_NOAPI(ret_value) @@ -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..ee79b0c 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 @@ -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() */ 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..ebfe636 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 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 72306df..d5d1972 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 @@ -109,9 +109,6 @@ static herr_t H5PB__write_raw(H5F_shared_t *, H5FD_mem_t, haddr_t, size_t, const /* Package Variables */ /*********************/ -/* Package initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - /*****************************/ /* Library Private Variables */ /*****************************/ @@ -119,7 +116,6 @@ hbool_t H5_PKG_INIT_VAR = FALSE; /*******************/ /* Local Variables */ /*******************/ - /* Declare a free list to manage the H5PB_t struct */ H5FL_DEFINE_STATIC(H5PB_t); @@ -297,7 +293,7 @@ H5PB_print_stats(const H5PB_t *page_buf) (page_buf->bypasses[0] + page_buf->bypasses[1] + page_buf->bypasses[2]), page_buf->bypasses[0], page_buf->bypasses[1], page_buf->bypasses[2]); - HDfprintf(stdout, "acesses = %" PRIi64 " (%" PRIi64 "/%" PRIi64 "/%" PRIi64 ")\n", + HDfprintf(stdout, "accesses = %" PRIi64 " (%" PRIi64 "/%" PRIi64 "/%" PRIi64 ")\n", (page_buf->accesses[0] + page_buf->accesses[1] + page_buf->accesses[2]), page_buf->accesses[0], page_buf->accesses[1], page_buf->accesses[2]); @@ -924,7 +920,7 @@ H5PB_count_meta_access_by_size(H5PB_t *pb, size_t size) * max_pages), simply read from the HDF5 file and return. * * The free space manager guarantees that allocations larger - * than one page will be page alligned, and that allocations + * than one page will be page aligned, and that allocations * of size less than or equal to page size will not cross page * boundaries. Further, unlike raw data, metadata is always * written and read atomically. @@ -1052,7 +1048,7 @@ H5PB_count_meta_access_by_size(H5PB_t *pb, size_t size) * Changes: Updated for discovery of the fact that the fixed and * extensible array data structures allocate multiple * metadata cache entries in a single block, and thus - * violate that invarient that metadata entries either + * violate that invariant that metadata entries either * do not cross page boundaries, or are page aligned. * * JRM -- 3/28/20 @@ -1205,7 +1201,7 @@ H5PB_read(H5F_shared_t *shared, H5FD_mem_t type, haddr_t addr, size_t size, void * empty. * * Since we know that the read crosses at least one - * page boundary, and we have aleady filtered out the + * page boundary, and we have already filtered out the * body only case, at least two of the above must be * non-empty. */ @@ -1542,7 +1538,7 @@ done: * In all contexts, there is no guarantee that the page buffer * will contain any of the possible entries. * - * Space allocations larger than one page must be page alligned. + * Space allocations larger than one page must be page aligned. * Further, any space between the end of a multi-page allocation * and the next page boundary will remain un-allocated until after * the original allocation is freed. This implies that: @@ -1900,7 +1896,7 @@ H5PB_vfd_swmr__release_tick_list(H5F_shared_t *shared) } } /* if the entry is not a multi-page metadata entry, it must already - * be on either the replacment policy or the delayed write list. + * be on either the replacement policy or the delayed write list. * In either case, it will be flush when possible and necessary. */ } @@ -2236,7 +2232,7 @@ done: * max_pages), simply write to the HDF5 file and return. * * The free space manager guarantees that allocations larger - * than one page will be page alligned, and that allocations + * than one page will be page aligned, and that allocations * of size less than or equal to page size will not cross page * boundaries. Further, unlike raw data, metadata is always * written and read atomically. @@ -2256,7 +2252,7 @@ done: * structures, it complicates the metadata cache and the page * buffer. * - * From the page buffer perspective, it breaks the invarient + * From the page buffer perspective, it breaks the invariant * that metadata entries of less than page size don't cross * page boundaries, and those of size greater than or equal * to page size start on page boundaries -- which is important @@ -2511,7 +2507,7 @@ H5PB_write(H5F_shared_t *shared, H5FD_mem_t type, haddr_t addr, size_t size, con * empty. * * Since we know that the write crosses at least one - * page boundary, and we have aleady filtered out the + * page boundary, and we have already filtered out the * body only case, at least two of the above must be * non-empty. */ @@ -3139,7 +3135,7 @@ H5PB__flush_entry(H5F_shared_t *shared, H5PB_t *page_buf, H5PB_entry_t *const en * true in all cases. */ - /* Verify that the base addresss of the page is within the EOA. If it + /* Verify that the base address of the page is within the EOA. If it * isn't, the associated page has been discarded and should have been * removed from the page buffer. This is a bug in the HDF5 library, so * an assertion is adequate here. @@ -3354,7 +3350,7 @@ done: * * evict the entry and test to see if page_buf->curr_pages < * page_buf->max_pages. If it is, return. Otherwise, continue - * the scan until either the above condidtion is fulfilled, + * the scan until either the above condition is fulfilled, * or the head of the LRU is reach. * * Under normal circumstances, it should always be possible @@ -3725,7 +3721,7 @@ done: * Y | Y | MPMDE | N | X | Error (case 9) * ------+------+--------+------+---------+------------------------------------- * Y | Y | MPMDE | Y | X | Clip read to MPE size if required. - * | | | | | Satify read from MPE (case 9) + * | | | | | Satisfy read from MPE (case 9) * ------+------+--------+------+---------+------------------------------------- * | | | | | * ------+------+--------+------+---------+------------------------------------- @@ -4195,7 +4191,7 @@ H5PB__read_raw(H5F_shared_t *shared, H5FD_mem_t type, haddr_t addr, size_t size, else { /* this is an internal page -- copy it in its - * entireity. + * entirety. */ offset = @@ -4375,7 +4371,7 @@ H5PB__write_meta(H5F_shared_t *shared, H5FD_mem_t type, haddr_t addr, size_t siz H5PB_t * page_buf; /* Page buffer for this file */ H5PB_entry_t *entry_ptr; /* Pointer to page buffer entry */ uint64_t page; /* page offset of addr */ - haddr_t page_addr; /* page containg addr */ + haddr_t page_addr; /* page containing addr */ size_t offset; /* offset of write in page */ herr_t ret_value = SUCCEED; /* Return value */ diff --git a/src/H5PBpkg.h b/src/H5PBpkg.h index f06206b..03c75bd 100644 --- a/src/H5PBpkg.h +++ b/src/H5PBpkg.h @@ -153,7 +153,7 @@ /* successor at head of list -- prepend */ \ H5PB__DLL_PREPEND(entry_ptr, head_ptr, tail_ptr, len, Size, fail_val) \ \ - else /* sucessor in body of list -- insert before it */ \ + else /* successor in body of list -- insert before it */ \ { \ H5PB__DLL_PRE_INSERT_SC(entry_ptr, head_ptr, tail_ptr, len, Size, fail_val) \ HDassert(suc_ptr->prev->magic == H5PB__H5PB_ENTRY_T_MAGIC); \ @@ -278,7 +278,7 @@ /* successor at head of list -- prepend */ \ H5PB__IL_DLL_PREPEND(entry_ptr, head_ptr, tail_ptr, len, Size, fail_val) \ \ - else /* sucessor in body of list -- insert before it */ \ + else /* successor in body of list -- insert before it */ \ { \ H5PB__IL_DLL_PRE_INSERT_SC(entry_ptr, head_ptr, tail_ptr, len, Size, fail_val) \ HDassert(suc_ptr->il_prev->magic == H5PB__H5PB_ENTRY_T_MAGIC); \ @@ -1458,7 +1458,7 @@ * Macro: H5PB__INSERT_IN_DWL * * Insert the supplied page buffer entry in the delayed write list - * maintaining the invarient: + * maintaining the invariant: * * entry_ptr->next == NULL || * entry_ptr->delay_write_until >= entry_ptr->next->delay_write_until @@ -1599,7 +1599,7 @@ * Fields supporting the hash table: * * Entries in the page buffer are indexed by a more or less conventional - * hash table with chaining (see header comment on H5PB_t for futher details). + * hash table with chaining (see header comment on H5PB_t for further details). * If there are multiple entries in any hash bin, they are stored in a doubly * linked list. * @@ -1647,7 +1647,7 @@ * Fields supporting VFD SWMR: * * is_mpmde: Boolean flag that is set to TRUE iff the entry - * is a multi-page metadata entry. In the absense of VFD + * is a multi-page metadata entry. In the absence of VFD * SWMR, the field should always be set to FALSE. * * Observe that: @@ -1668,15 +1668,15 @@ * * delay_write_until: Unsigned 64 bit integer containing the first tick * in which the entry may be written to file, or 0 if there - * is no such constraint. It should be set ot 0 when VFD + * is no such constraint. It should be set to 0 when VFD * is not enabled. * * tl_next: Next pointer on the list of entries modified in the current - * tick, If the enty is not on the tick list, or if there is + * tick, If the entry is not on the tick list, or if there is * no next entry on the list, this field should be set to NULL. * * tl_prev: Prev pointer on the list of entries modified in the current - * tick, If the enty is not on the tick list, or if there is + * tick, If the entry is not on the tick list, or if there is * no previous entry on the list, this field should be set to * NULL. * diff --git a/src/H5PBprivate.h b/src/H5PBprivate.h index 15ee749..c23336e 100644 --- a/src/H5PBprivate.h +++ b/src/H5PBprivate.h @@ -308,7 +308,7 @@ typedef struct H5PB_entry_t H5PB_entry_t; * * To facilitate identification of entries that must be removed from the * DWL during the end of tick scan, the list always observes the following - * invarient for any entry on the list: + * invariant for any entry on the list: * * entry_ptr->next == NULL || * entry_ptr->delay_write_until >= entry_ptr->next->delay_write_until @@ -528,7 +528,7 @@ typedef struct H5PB_entry_t H5PB_entry_t; * max_dwl_size: int64_t containing the maximum value of dwl_size. * * total_dwl_ins_depth: int64_t containing the total insertion depth - * required to maintain the odering invarient on the + * required to maintain the odering invariant on the * delayed write list. * * md_read_splits: int64_t containing the number of metadata reads that @@ -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 ff9ff8a..65d426b 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 @@ -114,7 +134,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 @@ -416,6 +436,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 */ /*********************/ @@ -518,7 +541,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 = @@ -851,6 +874,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 @@ -941,42 +1166,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 */ @@ -1022,7 +1257,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: @@ -1030,6 +1265,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) + + assert(plist); + assert(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) + + assert(plist); + assert(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 @@ -1056,7 +1465,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") @@ -1140,7 +1549,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") @@ -1193,13 +1602,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 @@ -1250,6 +1750,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 */ @@ -1280,7 +1789,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 */ @@ -1288,6 +1796,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") @@ -1507,6 +2018,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() */ @@ -2390,7 +2911,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 @@ -2406,7 +2927,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 @@ -2852,7 +3373,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 */ @@ -4916,15 +5437,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 * @@ -4944,7 +5464,7 @@ 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)) @@ -4974,10 +5494,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 * @@ -4995,7 +5514,7 @@ 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)) @@ -5764,7 +6283,7 @@ H5Pset_vfd_swmr_config(hid_t plist_id, H5F_vfd_swmr_config_t *config_ptr) if (H5P_set(plist, H5F_ACS_VFD_SWMR_CONFIG_NAME, config_ptr) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set metadata cache initial config") - if (H5P_set_driver(plist, H5FD_VFD_SWMR, NULL) < 0) + if (H5P_set_driver(plist, H5FD_VFD_SWMR, NULL, NULL) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set VFD SWMR driver info"); done: diff --git a/src/H5Pint.c b/src/H5Pint.c index 90fd1c2..c0f5ee1 100644 --- a/src/H5Pint.c +++ b/src/H5Pint.c @@ -123,77 +123,78 @@ 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_FILE_ACCESS_ANY_VFD_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_ANY_VFD_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] = {{ @@ -413,48 +414,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)); @@ -473,8 +455,6 @@ H5P__init_package(void) */ tot_init = 0; do { - size_t u; /* Local index variable */ - /* Reset pass initialization counter */ pass_init = 0; @@ -524,8 +504,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) -} /* end H5P__init_package() */ +} + +/*------------------------------------------------------------------------- + * 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_phase2() */ /*-------------------------------------------------------------------------- NAME @@ -551,77 +582,109 @@ 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_ANY_VFD_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_LST_FILE_ACCESS_ANY_VFD_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() */ @@ -3243,7 +3306,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 @@ -3302,7 +3365,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 @@ -3502,7 +3565,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); @@ -3517,7 +3580,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() */ @@ -3818,7 +3880,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 */ @@ -3948,7 +4010,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); @@ -4769,7 +4831,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 @@ -4850,7 +4912,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) @@ -5250,14 +5312,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 e442030..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. * 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 ed61646..ed9db10 100644 --- a/src/H5Ppublic.h +++ b/src/H5Ppublic.h @@ -117,21 +117,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] --> @@ -146,8 +195,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] --> @@ -162,8 +211,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] --> @@ -173,13 +222,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] --> @@ -188,7 +252,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] --> @@ -198,7 +271,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] --> @@ -265,15 +350,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; @@ -579,77 +664,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: + * 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. * - * \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 - * - * 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 * @@ -1378,35 +1398,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 @@ -1879,9 +1876,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 @@ -3450,6 +3444,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} @@ -3886,13 +3908,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 * @@ -4183,17 +4205,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(). @@ -4293,6 +4312,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 * @@ -4301,7 +4371,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. * @@ -5410,12 +5480,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 */ @@ -7031,9 +7127,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 * @@ -7387,11 +7480,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 * @@ -7559,8 +7648,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); @@ -7588,6 +7680,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); /** @@ -7611,6 +7705,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); @@ -7854,8 +7950,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); @@ -7883,7 +7980,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); @@ -7933,7 +8030,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 */ /*****************************/ @@ -353,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 7ee4ecc..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 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() */ @@ -239,7 +239,7 @@ } /* 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; \ @@ -255,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; \ @@ -311,7 +311,7 @@ { \ 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 *_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 */ \ @@ -510,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); @@ -524,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 *)); @@ -555,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 @@ -584,32 +576,26 @@ 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; - - 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; + /* Terminate all the factories */ + if (H5SL_fac_nused_g > 0) { + size_t i; + herr_t H5_ATTR_NDEBUG_UNUSED ret; - n++; + 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; - /* 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++; - } + /* 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; + n++; } FUNC_LEAVE_NOAPI(n) @@ -1943,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 diff --git a/src/H5SLprivate.h b/src/H5SLprivate.h index be6f7b6..f4f7506 100644 --- a/src/H5SLprivate.h +++ b/src/H5SLprivate.h @@ -85,6 +85,7 @@ 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_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..aec5560 100644 --- a/src/H5Smpio.c +++ b/src/H5Smpio.c @@ -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..240b722 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 */ @@ -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/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(). @@ -600,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 * @@ -740,19 +709,17 @@ 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 */ @@ -793,7 +760,7 @@ H5T__init_package(void) 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) @@ -1433,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 */ @@ -1446,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) @@ -1476,7 +1440,7 @@ done: } /* end if */ FUNC_LEAVE_NOAPI(ret_value) -} /* end H5T__init_package() */ +} /* end H5T_init() */ /*------------------------------------------------------------------------- * Function: H5T__unlock_cb @@ -1532,183 +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; - 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 */ + 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) @@ -1739,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() */ @@ -2170,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); @@ -2185,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() */ @@ -2243,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); @@ -4276,7 +4226,7 @@ done: * * Return: Success: non-negative * - * Failure: nagative + * Failure: negative * * Programmer: Robb Matzke * Tuesday, December 22, 1998 @@ -5626,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) } @@ -5651,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); @@ -5660,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) } @@ -5738,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() */ @@ -5768,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); @@ -5806,7 +5753,6 @@ H5T_is_sensible(const H5T_t *dt) break; } /* end switch */ -done: FUNC_LEAVE_NOAPI(ret_value) } @@ -5999,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); @@ -6008,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() */ @@ -6099,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); @@ -6112,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() */ @@ -6266,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); @@ -6277,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; @@ -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 @@ -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. 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 c06c895..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)))) @@ -3205,14 +3205,14 @@ H5T__conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, si HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "unable to copy src type for conversion") /* References need to know about the src file */ if (tsrc_cpy->shared->type == H5T_REFERENCE) - if (H5T_set_loc(tsrc_cpy, src->shared->u.vlen.file, H5T_LOC_MEMORY) < 0) + if (H5T_set_loc(tsrc_cpy, src->shared->u.vlen.file, src->shared->u.vlen.loc) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't set datatype location"); if (NULL == (tdst_cpy = H5T_copy(dst->shared->parent, H5T_COPY_ALL))) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "unable to copy dst type for conversion") /* References need to know about the dst file */ if (tdst_cpy->shared->type == H5T_REFERENCE) - if (H5T_set_loc(tdst_cpy, dst->shared->u.vlen.file, H5T_LOC_MEMORY) < 0) + if (H5T_set_loc(tdst_cpy, dst->shared->u.vlen.file, dst->shared->u.vlen.loc) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't set datatype location"); if (((tsrc_id = H5I_register(H5I_DATATYPE, tsrc_cpy, FALSE)) < 0) || @@ -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 @@ -7145,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 * *------------------------------------------------------------------------- */ @@ -7205,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 * *------------------------------------------------------------------------- */ @@ -7265,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 * *------------------------------------------------------------------------- */ @@ -7325,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 * *------------------------------------------------------------------------- */ @@ -7385,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 * *------------------------------------------------------------------------- */ @@ -7445,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 * *------------------------------------------------------------------------- */ @@ -7505,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 * *------------------------------------------------------------------------- */ @@ -7565,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 * *------------------------------------------------------------------------- */ @@ -7625,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 * *------------------------------------------------------------------------- */ @@ -7687,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 * *------------------------------------------------------------------------- */ @@ -7797,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 * *------------------------------------------------------------------------- */ @@ -7819,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 * *------------------------------------------------------------------------- */ @@ -7929,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 * *------------------------------------------------------------------------- */ @@ -7951,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 * *------------------------------------------------------------------------- */ @@ -8061,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 * *------------------------------------------------------------------------- */ @@ -8083,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 * *------------------------------------------------------------------------- */ @@ -8193,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 * *------------------------------------------------------------------------- */ @@ -8215,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 * *------------------------------------------------------------------------- */ @@ -8325,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 * *------------------------------------------------------------------------- */ @@ -8349,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 c9a2907..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. * 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 19593dd..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. */ diff --git a/src/H5Tpublic.h b/src/H5Tpublic.h index 911efdf..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] --> @@ -1161,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 @@ -1171,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 @@ -1266,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/H5VLcallback.c b/src/H5VLcallback.c index fcab19f..0c5c73d 100644 --- a/src/H5VLcallback.c +++ b/src/H5VLcallback.c @@ -4967,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 @@ -4998,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 @@ -6408,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 @@ -6442,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 @@ -6452,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() */ @@ -6546,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() */ @@ -6639,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() */ @@ -6732,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() */ @@ -6827,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() */ @@ -6958,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 70c8112..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) @@ -1757,7 +1737,7 @@ H5VL__get_connector_name(hid_t id, char *name /*out*/, size_t size) len = HDstrlen(cls->name); if (name) { - HDstrncpy(name, cls->name, MIN(len + 1, size)); + HDstrncpy(name, cls->name, size); if (len >= size) name[size - 1] = '\0'; } /* end if */ @@ -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_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() */ @@ -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. * @@ -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 48a29cd..46c1a10 100644 --- a/src/H5Zscaleoffset.c +++ b/src/H5Zscaleoffset.c @@ -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)) \ @@ -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 ea532cf..092b289 100644 --- a/src/H5Ztrans.c +++ b/src/H5Ztrans.c @@ -1352,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. * @@ -1692,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; @@ -1723,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 022cb55..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" @@ -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/H5mpi.c b/src/H5mpi.c index 4a8aa44..15fb785 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 MPI_VERSION >= 3 + 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 MPI_VERSION >= 3 + 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 58a4100..da20a1b 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 @@ -106,8 +108,14 @@ */ #include "H5queue.h" -/* 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 @@ -171,7 +179,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(); \ @@ -386,6 +394,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. @@ -507,6 +534,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 @@ -575,7 +605,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. */ @@ -2006,7 +2036,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 @@ -2036,33 +2066,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); @@ -2116,13 +2119,9 @@ H5_DLL herr_t H5CX_pop(hbool_t update_dxpl_props); #define FUNC_ENTER_API_INIT(err) \ /* Initialize the library */ \ if (!H5_INIT_GLOBAL && !H5_TERM_GLOBAL) { \ - H5_INIT_GLOBAL = TRUE; \ 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 */ \ @@ -2131,6 +2130,8 @@ H5_DLL herr_t H5CX_pop(hbool_t update_dxpl_props); /* Push the API context */ \ if (H5CX_push() < 0) \ HGOTO_ERROR(H5E_FUNC, H5E_CANTSET, err, "can't set API context") \ + else \ + api_ctx_pushed = TRUE; \ \ BEGIN_MPE_LOG @@ -2170,6 +2171,8 @@ H5_DLL herr_t H5CX_pop(hbool_t update_dxpl_props); #define FUNC_ENTER_API(err) \ { \ { \ + hbool_t api_ctx_pushed = FALSE; \ + \ FUNC_ENTER_API_COMMON \ FUNC_ENTER_API_INIT(err); \ FUNC_ENTER_API_PUSH(err); \ @@ -2182,6 +2185,8 @@ H5_DLL herr_t H5CX_pop(hbool_t update_dxpl_props); #define FUNC_ENTER_API_NO_EOT(err) \ { \ { \ + hbool_t api_ctx_pushed = FALSE; \ + \ FUNC_ENTER_API_COMMON \ FUNC_ENTER_API_INIT(err); \ FUNC_ENTER_API_PUSH(err); \ @@ -2196,6 +2201,8 @@ H5_DLL herr_t H5CX_pop(hbool_t update_dxpl_props); #define FUNC_ENTER_API_NOCLEAR(err) \ { \ { \ + hbool_t api_ctx_pushed = FALSE; \ + \ FUNC_ENTER_API_COMMON \ FUNC_ENTER_API_INIT(err); \ FUNC_ENTER_API_PUSH(err); \ @@ -2270,27 +2277,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: @@ -2304,7 +2303,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: @@ -2319,7 +2318,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: @@ -2331,9 +2330,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: @@ -2347,7 +2344,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 @@ -2369,8 +2366,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) \ { \ @@ -2379,21 +2376,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. */ @@ -2404,28 +2401,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 @@ -2447,7 +2444,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 @@ -2463,15 +2460,18 @@ H5_DLL herr_t H5CX_pop(hbool_t update_dxpl_props); H5_API_SET_CANCEL #define FUNC_LEAVE_API_COMMON(ret_value) \ - ; \ - } /*end scope from end of FUNC_ENTER*/ \ FINISH_MPE_LOG \ H5TRACE_RETURN(ret_value); #define FUNC_LEAVE_API(ret_value) \ + ; \ + } /*end scope from end of FUNC_ENTER*/ \ VFD_SWMR_LEAVE(ret_value); \ FUNC_LEAVE_API_COMMON(ret_value); \ - (void)H5CX_pop(TRUE); \ + if (api_ctx_pushed) { \ + (void)H5CX_pop(TRUE); \ + api_ctx_pushed = FALSE; \ + } \ H5_POP_FUNC \ if (err_occurred) \ (void)H5E_dump_api_stack(TRUE); \ @@ -2482,8 +2482,13 @@ H5_DLL herr_t H5CX_pop(hbool_t update_dxpl_props); /* Use this macro when VFD SWMR EOT is not used on leaving an API function */ #define FUNC_LEAVE_API_NO_EOT(ret_value) \ + ; \ + } /*end scope from end of FUNC_ENTER*/ \ FUNC_LEAVE_API_COMMON(ret_value); \ - (void)H5CX_pop(TRUE); \ + if (api_ctx_pushed) { \ + (void)H5CX_pop(TRUE); \ + api_ctx_pushed = FALSE; \ + } \ H5_POP_FUNC \ if (err_occurred) \ (void)H5E_dump_api_stack(TRUE); \ @@ -2494,6 +2499,8 @@ H5_DLL herr_t H5CX_pop(hbool_t update_dxpl_props); /* Use this macro to match the FUNC_ENTER_API_NOINIT macro */ #define FUNC_LEAVE_API_NOINIT(ret_value) \ + ; \ + } /*end scope from end of FUNC_ENTER*/ \ FUNC_LEAVE_API_COMMON(ret_value); \ H5_POP_FUNC \ if (err_occurred) \ @@ -2506,6 +2513,8 @@ H5_DLL herr_t H5CX_pop(hbool_t update_dxpl_props); /* Use this macro to match the FUNC_ENTER_API_NOINIT_NOERR_NOFS macro */ #define FUNC_LEAVE_API_NOFS(ret_value) \ + ; \ + } /*end scope from end of FUNC_ENTER*/ \ FUNC_LEAVE_API_COMMON(ret_value); \ FUNC_LEAVE_API_THREADSAFE \ return (ret_value); \ @@ -2582,27 +2591,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) \ @@ -2723,7 +2711,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 */ @@ -2737,6 +2726,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 163deed..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,7 +83,7 @@ /** * For tweaks, bug-fixes, or development */ -#define H5_VERS_RELEASE 1 +#define H5_VERS_RELEASE 2 /** * For pre-releases like \c snap0. Empty string for official releases. */ @@ -91,7 +91,7 @@ /** * Full version string */ -#define H5_VERS_INFO "HDF5 library version: 1.13.1-1" +#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/H5retry_private.h b/src/H5retry_private.h index 5ff63d3..057c402 100644 --- a/src/H5retry_private.h +++ b/src/H5retry_private.h @@ -81,7 +81,7 @@ h5_retry_init(struct h5_retry_t *r, unsigned int maxtries, uint64_t minival, uin return h5_retry_decrement(r); } -/* If any tries remain, sleep for the mininum interval, or twice the +/* If any tries remain, sleep for the minimum interval, or twice the * previous sleep time, and return true. If no tries remain, return false. */ static inline bool diff --git a/src/H5system.c b/src/H5system.c index e671ea9..b280c84 100644 --- a/src/H5system.c +++ b/src/H5system.c @@ -1096,7 +1096,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 */ 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 8daa17d..8defbc1 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_SWMR: + H5RS_acat(rs, "H5_VFD_SWMR"); + 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 */ @@ -3964,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 ae058f4..3baf833 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -63,7 +63,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 H5FDsec2.c H5FDspace.c \ + H5FDmulti.c H5FDperform.c H5FDsec2.c H5FDspace.c \ H5FDsplitter.c H5FDstdio.c H5FDtest.c \ H5FDvfd_swmr.c H5FDvfd_swmr_instr.c \ H5FL.c H5FO.c H5FS.c H5FScache.c H5FSdbg.c H5FSint.c H5FSsection.c \ |