summaryrefslogtreecommitdiffstats
path: root/src/H5.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5.c')
-rw-r--r--src/H5.c341
1 files changed, 197 insertions, 144 deletions
diff --git a/src/H5.c b/src/H5.c
index 3ceaecd..7142234 100644
--- a/src/H5.c
+++ b/src/H5.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 */
@@ -83,6 +83,8 @@ hbool_t H5_libinit_g = FALSE; /* Library hasn't been initialized */
hbool_t H5_libterm_g = FALSE; /* Library isn't being shutdown */
#endif
+hbool_t H5_use_selection_io_g = FALSE;
+
#ifdef H5_HAVE_MPE
hbool_t H5_MPEinit_g = FALSE; /* MPE Library hasn't been initialized */
#endif
@@ -101,32 +103,30 @@ static H5_atclose_node_t *H5_atclose_head = NULL;
/* Declare a free list to manage the H5_atclose_node_t struct */
H5FL_DEFINE_STATIC(H5_atclose_node_t);
-/*--------------------------------------------------------------------------
-NAME
- H5__init_package -- Initialize interface-specific information
-USAGE
- herr_t H5__init_package()
-RETURNS
- Non-negative on success/Negative on failure
-DESCRIPTION
- Initializes any interface-specific data or routines.
---------------------------------------------------------------------------*/
-herr_t
-H5__init_package(void)
+/*-------------------------------------------------------------------------
+ * Function: H5_default_vfd_init
+ *
+ * Purpose: Initialize the default VFD.
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5_default_vfd_init(void)
{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
-
- /* Run the library initialization routine, if it hasn't already ran */
- if (!H5_INIT_GLOBAL && !H5_TERM_GLOBAL) {
- if (H5_init_library() < 0)
- HGOTO_ERROR(H5E_LIB, H5E_CANTINIT, FAIL, "unable to initialize library")
- } /* end if */
+ herr_t ret_value = SUCCEED;
+ FUNC_ENTER_NOAPI(FAIL)
+ /* Load the hid_t for the default VFD for the side effect
+ * it has of initializing the default VFD.
+ */
+ if (H5FD_sec2_init() == H5I_INVALID_HID) {
+ HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to load default VFD ID")
+ }
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5__init_package() */
+}
/*--------------------------------------------------------------------------
* NAME
@@ -145,15 +145,21 @@ done:
herr_t
H5_init_library(void)
{
- herr_t ret_value = SUCCEED;
+ size_t i;
+ char * env_use_select_io = NULL;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Run the library initialization routine, if it hasn't already run */
+ if (H5_INIT_GLOBAL || H5_TERM_GLOBAL)
+ HGOTO_DONE(SUCCEED)
/* Set the 'library initialized' flag as early as possible, to avoid
* possible re-entrancy.
*/
H5_INIT_GLOBAL = TRUE;
- FUNC_ENTER_NOAPI(FAIL)
-
#ifdef H5_HAVE_PARALLEL
{
int mpi_initialized;
@@ -257,24 +263,41 @@ H5_init_library(void)
* The dataspace interface needs to be initialized so that future IDs for
* dataspaces work.
*/
- if (H5E_init() < 0)
- HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize error interface")
- if (H5VL_init_phase1() < 0)
- HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize vol interface")
- if (H5P_init() < 0)
- HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize property list interface")
- if (H5AC_init() < 0)
- HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize metadata caching interface")
- if (H5L_init() < 0)
- HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize link interface")
- if (H5FS_init() < 0)
- HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize FS interface")
- if (H5S_init() < 0)
- HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize dataspace interface")
-
+ /* clang-format off */
+ struct {
+ herr_t (*func)(void);
+ const char *descr;
+ } initializer[] = {
+ {H5E_init, "error"}
+ , {H5VL_init_phase1, "VOL"}
+ , {H5SL_init, "skip lists"}
+ , {H5FD_init, "VFD"}
+ , {H5_default_vfd_init, "default VFD"}
+ , {H5P_init_phase1, "property list"}
+ , {H5AC_init, "metadata caching"}
+ , {H5L_init, "link"}
+ , {H5S_init, "dataspace"}
+ , {H5PL_init, "plugins"}
/* Finish initializing interfaces that depend on the interfaces above */
- if (H5VL_init_phase2() < 0)
- HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize vol interface")
+ , {H5P_init_phase2, "property list"}
+ , {H5VL_init_phase2, "VOL"}
+ };
+
+ for (i = 0; i < NELMTS(initializer); i++) {
+ if (initializer[i].func() < 0) {
+ HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL,
+ "unable to initialize %s interface", initializer[i].descr)
+ }
+ }
+ /* clang-format on */
+
+ /* Check for HDF5_USE_SELECTION_IO env variable */
+ env_use_select_io = HDgetenv("HDF5_USE_SELECTION_IO");
+ if (NULL != env_use_select_io && HDstrcmp(env_use_select_io, "") && HDstrcmp(env_use_select_io, "0") &&
+ HDstrcmp(env_use_select_io, "no") && HDstrcmp(env_use_select_io, "No") &&
+ HDstrcmp(env_use_select_io, "NO") && HDstrcmp(env_use_select_io, "false") &&
+ HDstrcmp(env_use_select_io, "False") && HDstrcmp(env_use_select_io, "FALSE"))
+ H5_use_selection_io_g = TRUE;
/* Debugging? */
H5__debug_mask("-all");
@@ -298,9 +321,11 @@ done:
void
H5_term_library(void)
{
- int pending, ntries = 0, n;
- size_t at = 0;
- char loop[1024];
+ int pending, ntries = 0;
+ char loop[1024], *next = loop;
+ size_t i;
+ size_t nleft = sizeof(loop);
+ int nprinted;
H5E_auto2_t func;
#ifdef H5_HAVE_THREADSAFE
@@ -344,108 +369,137 @@ H5_term_library(void)
H5_atclose_head = NULL;
} /* end if */
+ /* clang-format off */
+
/*
* Terminate each interface. The termination functions return a positive
* value if they do something that might affect some other interface in a
* way that would necessitate some cleanup work in the other interface.
*/
-#define DOWN(F) \
- (((n = H5##F##_term_package()) && (at + 8) < sizeof loop) \
- ? (HDsprintf(loop + at, "%s%s", (at ? "," : ""), #F), at += HDstrlen(loop + at), n) \
- : ((n > 0 && (at + 5) < sizeof loop) ? (HDsprintf(loop + at, "..."), at += HDstrlen(loop + at), n) \
- : n))
-
- do {
- pending = 0;
- /* Try to organize these so the "higher" level components get shut
- * down before "lower" level components that they might rely on. -QAK
- */
+#define TERMINATOR(module, wait) { \
+ .func = H5##module##_term_package \
+ , .name = #module \
+ , .completed = false \
+ , .await_prior = wait \
+ }
+ /*
+ * Termination is ordered by the `terminator` table so the "higher" level
+ * packages are shut down before "lower" level packages that they
+ * rely on:
+ */
+ struct {
+ int (*func)(void); /* function to terminate the module; returns 0
+ * on success, >0 if termination was not
+ * completed and we should try to terminate
+ * some dependent modules, first.
+ */
+ const char *name; /* name of the module */
+ hbool_t completed; /* true iff this terminator was already
+ * completed
+ */
+ const hbool_t await_prior; /* true iff all prior terminators in the
+ * list must complete before this
+ * terminator is attempted
+ */
+ } terminator[] = {
/* Close the event sets first, so that all asynchronous operations
- * complete before anything else attempts to shut down.
+ * complete before anything else attempts to shut down.
*/
- pending += DOWN(ES);
-
- /* Close down the user-facing interfaces, after the event sets */
- if (pending == 0) {
- /* Close the interfaces dependent on others */
- pending += DOWN(L);
-
- /* Close the "top" of various interfaces (IDs, etc) but don't shut
- * down the whole interface yet, so that the object header messages
- * get serialized correctly for entries in the metadata cache and the
- * symbol table entry in the superblock gets serialized correctly, etc.
- * all of which is performed in the 'F' shutdown.
- */
- pending += DOWN(A_top);
- pending += DOWN(D_top);
- pending += DOWN(G_top);
- pending += DOWN(M_top);
- pending += DOWN(R_top);
- pending += DOWN(S_top);
- pending += DOWN(T_top);
- } /* end if */
-
+ TERMINATOR(ES, false)
+ /* Do not attempt to close down package L until after event sets
+ * have finished closing down.
+ */
+ , TERMINATOR(L, true)
+ /* Close the "top" of various interfaces (IDs, etc) but don't shut
+ * down the whole interface yet, so that the object header messages
+ * get serialized correctly for entries in the metadata cache and the
+ * symbol table entry in the superblock gets serialized correctly, etc.
+ * all of which is performed in the 'F' shutdown.
+ *
+ * The tops of packages A, D, G, M, S, T do not need to wait for L
+ * or previous packages to finish closing down.
+ */
+ , TERMINATOR(A_top, false)
+ , TERMINATOR(D_top, false)
+ , TERMINATOR(G_top, false)
+ , TERMINATOR(M_top, false)
+ , TERMINATOR(S_top, false)
+ , TERMINATOR(T_top, false)
/* Don't shut down the file code until objects in files are shut down */
- if (pending == 0)
- pending += DOWN(F);
-
+ , TERMINATOR(F, true)
/* Don't shut down the property list code until all objects that might
- * use property lists are shut down */
- if (pending == 0)
- pending += DOWN(P);
-
+ * use property lists are shut down
+ */
+ , TERMINATOR(P, true)
/* Wait to shut down the "bottom" of various interfaces until the
- * files are closed, so pieces of the file can be serialized
- * correctly.
+ * files are closed, so pieces of the file can be serialized
+ * correctly.
+ *
+ * Shut down the "bottom" of the attribute, dataset, group,
+ * reference, dataspace, and datatype interfaces, fully closing
+ * out the interfaces now.
*/
- if (pending == 0) {
- /* Shut down the "bottom" of the attribute, dataset, group,
- * reference, dataspace, and datatype interfaces, fully closing
- * out the interfaces now.
- */
- pending += DOWN(A);
- pending += DOWN(D);
- pending += DOWN(G);
- pending += DOWN(M);
- pending += DOWN(R);
- pending += DOWN(S);
- pending += DOWN(T);
- } /* end if */
-
- /* Don't shut down "low-level" components until "high-level" components
- * have successfully shut down. This prevents property lists and IDs
- * from being closed "out from underneath" of the high-level objects
- * that depend on them. -QAK
+ , TERMINATOR(A, true)
+ , TERMINATOR(D, false)
+ , TERMINATOR(G, false)
+ , TERMINATOR(M, false)
+ , TERMINATOR(S, false)
+ , TERMINATOR(T, false)
+ /* Wait to shut down low-level packages like AC until after
+ * the preceding high-level packages have shut down. This prevents
+ * low-level objects from closing "out from underneath" their
+ * reliant high-level objects.
*/
- if (pending == 0) {
- pending += DOWN(AC);
- /* Shut down the "pluggable" interfaces, before the plugin framework */
- pending += DOWN(Z);
- pending += DOWN(FD);
- pending += DOWN(VL);
- /* Don't shut down the plugin code until all "pluggable" interfaces (Z, FD, PL) are shut down */
- if (pending == 0)
- pending += DOWN(PL);
- /* Don't shut down the error code until other APIs which use it are shut down */
- if (pending == 0)
- pending += DOWN(E);
- /* Don't shut down the ID code until other APIs which use them are shut down */
- if (pending == 0)
- pending += DOWN(I);
- /* Don't shut down the skip list code until everything that uses it is down */
- if (pending == 0)
- pending += DOWN(SL);
- /* Don't shut down the free list code until everything that uses it is down */
- if (pending == 0)
- pending += DOWN(FL);
- /* Don't shut down the API context code until _everything_ else is down */
- if (pending == 0)
- pending += DOWN(CX);
- } /* end if */
+ , TERMINATOR(AC, true)
+ /* Shut down the "pluggable" interfaces, before the plugin framework */
+ , TERMINATOR(Z, false)
+ , TERMINATOR(FD, false)
+ , TERMINATOR(VL, false)
+ /* Don't shut down the plugin code until all "pluggable" interfaces
+ * (Z, FD, PL) are shut down
+ */
+ , TERMINATOR(PL, true)
+ /* Shut down the following packages in strictly the order given
+ * by the table.
+ */
+ , TERMINATOR(E, true)
+ , TERMINATOR(I, true)
+ , TERMINATOR(SL, true)
+ , TERMINATOR(FL, true)
+ , TERMINATOR(CX, true)
+ };
+
+ do {
+ pending = 0;
+ for (i = 0; i < NELMTS(terminator); i++) {
+ if (terminator[i].completed)
+ continue;
+ if (pending != 0 && terminator[i].await_prior)
+ break;
+ if (terminator[i].func() == 0) {
+ terminator[i].completed = true;
+ continue;
+ }
+
+ /* log a package when its terminator needs to be retried */
+ pending++;
+ nprinted = HDsnprintf(next, nleft, "%s%s",
+ (next != loop) ? "," : "", terminator[i].name);
+ if (nprinted < 0)
+ continue;
+ if ((size_t)nprinted >= nleft)
+ nprinted = HDsnprintf(next, nleft, "...");
+ if (nprinted < 0 || (size_t)nprinted >= nleft)
+ continue;
+ nleft -= (size_t)nprinted;
+ next += nprinted;
+ }
} while (pending && ntries++ < 100);
+ /* clang-format on */
+
if (pending) {
/* Only display the error message if the user is interested in them. */
if (func) {
@@ -911,6 +965,7 @@ H5check_version(unsigned majnum, unsigned minnum, unsigned relnum)
static int checked = 0; /* If we've already checked the version info */
static unsigned int disable_version_check = 0; /* Set if the version check should be disabled */
static const char * version_mismatch_warning = VERSION_MISMATCH_WARNING;
+ static const char * release_mismatch_warning = RELEASE_MISMATCH_WARNING;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API_NOINIT_NOERR_NOFS
@@ -931,10 +986,7 @@ H5check_version(unsigned majnum, unsigned minnum, unsigned relnum)
}
/* H5_VERS_MAJOR and H5_VERS_MINOR must match */
- /* Cast relnum to int to avoid warning for unsigned < 0 comparison
- * in first release versions */
- if (H5_VERS_MAJOR != majnum || H5_VERS_MINOR != minnum || H5_VERS_RELEASE > (int)relnum) {
-
+ if (H5_VERS_MAJOR != majnum || H5_VERS_MINOR != minnum) {
switch (disable_version_check) {
case 0:
HDfprintf(stderr, "%s%s", version_mismatch_warning,
@@ -969,9 +1021,10 @@ H5check_version(unsigned majnum, unsigned minnum, unsigned relnum)
break;
} /* end switch */
- } /* end if (H5_VERS_MAJOR != majnum || H5_VERS_MINOR != minnum || H5_VERS_RELEASE > relnum) */
+ } /* end if (H5_VERS_MAJOR != majnum || H5_VERS_MINOR != minnum) */
/* H5_VERS_RELEASE should be compatible, we will only add checks for exceptions */
+ /* Library develop release versions are incompatible by design */
if (H5_VERS_RELEASE != relnum) {
for (unsigned i = 0; i < VERS_RELEASE_EXCEPTIONS_SIZE; i++) {
/* Check for incompatible headers or incompatible library */
@@ -979,7 +1032,7 @@ H5check_version(unsigned majnum, unsigned minnum, unsigned relnum)
switch (disable_version_check) {
case 0:
HDfprintf(
- stderr, "%s%s", version_mismatch_warning,
+ stderr, "%s%s", release_mismatch_warning,
"You can, at your own risk, disable this warning by setting the environment\n"
"variable 'HDF5_DISABLE_VERSION_CHECK' to a value of '1'.\n"
"Setting it to 2 or higher will suppress the warning messages totally.\n");
@@ -998,7 +1051,7 @@ H5check_version(unsigned majnum, unsigned minnum, unsigned relnum)
"%s'HDF5_DISABLE_VERSION_CHECK' "
"environment variable is set to %d, application will\n"
"continue at your own risk.\n",
- version_mismatch_warning, disable_version_check);
+ release_mismatch_warning, disable_version_check);
/* Mention the versions we are referring to */
HDfprintf(stderr, "Headers are %u.%u.%u, library is %u.%u.%u\n", majnum, minnum,
relnum, (unsigned)H5_VERS_MAJOR, (unsigned)H5_VERS_MINOR,