summaryrefslogtreecommitdiffstats
path: root/src/H5.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5.c')
-rw-r--r--src/H5.c305
1 files changed, 172 insertions, 133 deletions
diff --git a/src/H5.c b/src/H5.c
index 731f15a..27df917 100644
--- a/src/H5.c
+++ b/src/H5.c
@@ -32,6 +32,8 @@
#include "H5SLprivate.h" /* Skip lists */
#include "H5Tprivate.h" /* Datatypes */
+#include "H5FDsec2.h" /* for H5FD_sec2_init() */
+
/****************/
/* Local Macros */
/****************/
@@ -63,9 +65,6 @@ 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 */
/*****************************/
@@ -101,32 +100,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,8 +142,13 @@ done:
herr_t
H5_init_library(void)
{
+ size_t i;
herr_t ret_value = SUCCEED;
+ /* 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.
*/
@@ -257,26 +259,32 @@ 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_phase1() < 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"}
/* Finish initializing interfaces that depend on the interfaces above */
- if (H5P_init_phase2() < 0)
- HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize property list interface")
- 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");
@@ -300,9 +308,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
@@ -346,108 +356,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) {