summaryrefslogtreecommitdiffstats
path: root/src/H5.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5.c')
-rw-r--r--src/H5.c1318
1 files changed, 813 insertions, 505 deletions
diff --git a/src/H5.c b/src/H5.c
index 68b339a..259e240 100644
--- a/src/H5.c
+++ b/src/H5.c
@@ -1,95 +1,127 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
- * Copyright by the Board of Trustees of the University of Illinois. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
- * the files COPYING and Copyright.html. COPYING can be found at the root *
- * of the source code distribution tree; Copyright.html can be found at the *
- * root level of an installed copy of the electronic HDF5 document set and *
- * is linked from the top-level documents page. It can also be found at *
- * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
- * access to either file, you may request a copy from help@hdfgroup.org. *
+ * 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 "H5module.h" /* This source code file is part of the H5 module */
/***********/
/* Headers */
/***********/
-#include "H5private.h" /* Generic Functions */
-#include "H5ACprivate.h" /* Metadata cache */
-#include "H5Dprivate.h" /* Datasets */
-#include "H5Eprivate.h" /* Error handling */
-#include "H5FLprivate.h" /* Free lists */
-#include "H5Lprivate.h" /* Links */
-#include "H5MMprivate.h" /* Memory management */
-#include "H5Pprivate.h" /* Property lists */
-#include "H5Tprivate.h" /* Datatypes */
-#include "H5SLprivate.h" /* Skip lists */
-
+#include "H5private.h" /* Generic Functions */
+#include "H5ACprivate.h" /* Metadata cache */
+#include "H5CXprivate.h" /* API Contexts */
+#include "H5Dprivate.h" /* Datasets */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5FLprivate.h" /* Free lists */
+#include "H5FSprivate.h" /* File free space */
+#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 */
/****************/
-
/******************/
/* Local Typedefs */
/******************/
-
/********************/
/* Package Typedefs */
/********************/
+/* Node for list of 'atclose' routines to invoke at library shutdown */
+typedef struct H5_atclose_node_t {
+ H5_atclose_func_t func; /* Function to invoke */
+ void *ctx; /* Context to pass to function */
+ struct H5_atclose_node_t *next; /* Pointer to next node in list */
+} H5_atclose_node_t;
/********************/
/* Local Prototypes */
/********************/
-static void H5_debug_mask(const char*);
+static void H5__debug_mask(const char *);
#ifdef H5_HAVE_PARALLEL
-static int H5_mpi_delete_cb(MPI_Comm comm, int keyval, void *attr_val, int *flag);
+static int H5__mpi_delete_cb(MPI_Comm comm, int keyval, void *attr_val, int *flag);
#endif /*H5_HAVE_PARALLEL*/
/*********************/
/* Package Variables */
/*********************/
-
/*****************************/
/* Library Private Variables */
/*****************************/
-/* HDF5 API Entered variable */
-/* (move to H5.c when new FUNC_ENTER macros in actual use -QAK) */
-hbool_t H5_api_entered_g = FALSE;
+/* Library incompatible release versions, develop releases are incompatible by design */
+const unsigned VERS_RELEASE_EXCEPTIONS[] = {0};
+const unsigned VERS_RELEASE_EXCEPTIONS_SIZE = 1;
/* statically initialize block for pthread_once call used in initializing */
/* the first global mutex */
#ifdef H5_HAVE_THREADSAFE
H5_api_t H5_g;
#else
-hbool_t H5_libinit_g = FALSE; /* Library hasn't been initialized */
-#endif
-
-#ifdef H5_HAVE_MPE
-hbool_t H5_MPEinit_g = FALSE; /* MPE Library hasn't been initialized */
+hbool_t H5_libinit_g = FALSE; /* Library hasn't been initialized */
+hbool_t H5_libterm_g = FALSE; /* Library isn't being shutdown */
#endif
-char H5_lib_vers_info_g[] = H5_VERS_INFO;
-static hbool_t H5_dont_atexit_g = FALSE;
-H5_debug_t H5_debug_g; /*debugging info */
+hbool_t H5_use_selection_io_g = FALSE;
+char H5_lib_vers_info_g[] = H5_VERS_INFO;
+static hbool_t H5_dont_atexit_g = FALSE;
+H5_debug_t H5_debug_g; /* debugging info */
/*******************/
/* Local Variables */
/*******************/
+/* Linked list of registered 'atclose' functions to invoke at library shutdown */
+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);
+
+/*-------------------------------------------------------------------------
+ * 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;
+
+ 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)
+}
/*--------------------------------------------------------------------------
* NAME
@@ -108,42 +140,45 @@ H5_debug_t H5_debug_g; /*debugging info */
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;
+
#ifdef H5_HAVE_PARALLEL
{
- int mpi_initialized;
+ int mpi_initialized;
+ int mpi_finalized;
int mpi_code;
- MPI_Initialized(&mpi_initialized);
-
-#ifdef H5_HAVE_MPE
- /* Initialize MPE instrumentation library. */
- if (!H5_MPEinit_g)
- {
- int mpe_code;
- if (mpi_initialized){
- mpe_code = MPE_Init_log();
- HDassert(mpe_code >=0);
- H5_MPEinit_g = TRUE;
- }
- }
-#endif /*H5_HAVE_MPE*/
+ MPI_Initialized(&mpi_initialized);
+ MPI_Finalized(&mpi_finalized);
/* add an attribute on MPI_COMM_SELF to call H5_term_library
when it is destroyed, i.e. on MPI_Finalize */
- if (mpi_initialized) {
+ if (mpi_initialized && !mpi_finalized) {
int key_val;
- if(MPI_SUCCESS != (mpi_code = MPI_Comm_create_keyval(MPI_NULL_COPY_FN,
- (MPI_Comm_delete_attr_function *)H5_mpi_delete_cb,
- &key_val, NULL)))
+ if (MPI_SUCCESS != (mpi_code = MPI_Comm_create_keyval(
+ MPI_COMM_NULL_COPY_FN, (MPI_Comm_delete_attr_function *)H5__mpi_delete_cb,
+ &key_val, NULL)))
HMPI_GOTO_ERROR(FAIL, "MPI_Comm_create_keyval failed", mpi_code)
- if(MPI_SUCCESS != (mpi_code = MPI_Comm_set_attr(MPI_COMM_SELF, key_val, NULL)))
+ if (MPI_SUCCESS != (mpi_code = MPI_Comm_set_attr(MPI_COMM_SELF, key_val, NULL)))
HMPI_GOTO_ERROR(FAIL, "MPI_Comm_set_attr failed", mpi_code)
+
+ if (MPI_SUCCESS != (mpi_code = MPI_Comm_free_keyval(&key_val)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Comm_free_keyval failed", mpi_code)
}
}
#endif /*H5_HAVE_PARALLEL*/
@@ -152,30 +187,32 @@ H5_init_library(void)
* Make sure the package information is updated.
*/
HDmemset(&H5_debug_g, 0, sizeof H5_debug_g);
- H5_debug_g.pkg[H5_PKG_A].name = "a";
+ H5_debug_g.pkg[H5_PKG_A].name = "a";
H5_debug_g.pkg[H5_PKG_AC].name = "ac";
- H5_debug_g.pkg[H5_PKG_B].name = "b";
- H5_debug_g.pkg[H5_PKG_D].name = "d";
- H5_debug_g.pkg[H5_PKG_E].name = "e";
- H5_debug_g.pkg[H5_PKG_F].name = "f";
- H5_debug_g.pkg[H5_PKG_G].name = "g";
+ H5_debug_g.pkg[H5_PKG_B].name = "b";
+ H5_debug_g.pkg[H5_PKG_D].name = "d";
+ H5_debug_g.pkg[H5_PKG_E].name = "e";
+ H5_debug_g.pkg[H5_PKG_F].name = "f";
+ H5_debug_g.pkg[H5_PKG_G].name = "g";
H5_debug_g.pkg[H5_PKG_HG].name = "hg";
H5_debug_g.pkg[H5_PKG_HL].name = "hl";
- H5_debug_g.pkg[H5_PKG_I].name = "i";
+ H5_debug_g.pkg[H5_PKG_I].name = "i";
+ H5_debug_g.pkg[H5_PKG_M].name = "m";
H5_debug_g.pkg[H5_PKG_MF].name = "mf";
H5_debug_g.pkg[H5_PKG_MM].name = "mm";
- H5_debug_g.pkg[H5_PKG_O].name = "o";
- H5_debug_g.pkg[H5_PKG_P].name = "p";
- H5_debug_g.pkg[H5_PKG_S].name = "s";
- H5_debug_g.pkg[H5_PKG_T].name = "t";
- H5_debug_g.pkg[H5_PKG_V].name = "v";
- H5_debug_g.pkg[H5_PKG_Z].name = "z";
+ H5_debug_g.pkg[H5_PKG_O].name = "o";
+ H5_debug_g.pkg[H5_PKG_P].name = "p";
+ H5_debug_g.pkg[H5_PKG_S].name = "s";
+ H5_debug_g.pkg[H5_PKG_T].name = "t";
+ H5_debug_g.pkg[H5_PKG_V].name = "v";
+ H5_debug_g.pkg[H5_PKG_VL].name = "vl";
+ H5_debug_g.pkg[H5_PKG_Z].name = "z";
/*
* Install atexit() library cleanup routines unless the H5dont_atexit()
* has been called. Once we add something to the atexit() list it stays
* there permanently, so we set H5_dont_atexit_g after we add it to prevent
- * adding it again later if the library is cosed and reopened.
+ * adding it again later if the library is closed and reopened.
*/
if (!H5_dont_atexit_g) {
@@ -184,12 +221,13 @@ H5_init_library(void)
* This must be entered before the library cleanup code so it's
* executed in LIFO order (i.e., last).
*/
- (void)HDatexit(H5TS_win32_process_exit);
+ (void)HDatexit(H5TS_win32_process_exit);
#endif /* H5_HAVE_THREADSAFE && H5_HAVE_WIN_THREADS */
/* Normal library termination code */
(void)HDatexit(H5_term_library);
- H5_dont_atexit_g = TRUE;
+
+ H5_dont_atexit_g = TRUE;
} /* end if */
/*
@@ -201,51 +239,76 @@ H5_init_library(void)
* property classes.
* The link interface needs to be initialized so that link property lists
* have their properties registered.
+ * The FS module needs to be initialized as a result of the fix for HDFFV-10160:
+ * It might not be initialized during normal file open.
+ * When the application does not close the file, routines in the module might
+ * be called via H5_term_library() when shutting down the file.
+ * 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(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")
+ /* 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 */
+ , {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");
- H5_debug_mask(HDgetenv("HDF5_DEBUG"));
+ H5__debug_mask("-all");
+ H5__debug_mask(HDgetenv("HDF5_DEBUG"));
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5_init_library() */
-
/*-------------------------------------------------------------------------
- * Function: H5_term_library
- *
- * Purpose: Terminate interfaces in a well-defined order due to
- * dependencies among the interfaces, then terminate
- * library-specific data.
- *
- * Return: void
+ * Function: H5_term_library
*
- * Programmer: Robb Matzke
- * Friday, November 20, 1998
+ * Purpose: Terminate interfaces in a well-defined order due to
+ * dependencies among the interfaces, then terminate
+ * library-specific data.
*
- * Modifications:
+ * Return: void
*
*-------------------------------------------------------------------------
*/
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
@@ -255,100 +318,185 @@ H5_term_library(void)
#endif
/* Don't do anything if the library is already closed */
- if(!(H5_INIT_GLOBAL))
- goto done;
+ if (!(H5_INIT_GLOBAL))
+ goto done;
+
+ /* Indicate that the library is being shut down */
+ H5_TERM_GLOBAL = TRUE;
+
+ /* Push the API context without checking for errors */
+ H5CX_push_special();
/* Check if we should display error output */
(void)H5Eget_auto2(H5E_DEFAULT, &func, NULL);
+ /* Iterate over the list of 'atclose' callbacks that have been registered */
+ if (H5_atclose_head) {
+ H5_atclose_node_t *curr_atclose; /* Current 'atclose' node */
+
+ /* Iterate over all 'atclose' nodes, making callbacks */
+ curr_atclose = H5_atclose_head;
+ while (curr_atclose) {
+ H5_atclose_node_t *tmp_atclose; /* Temporary pointer to 'atclose' node */
+
+ /* Invoke callback, providing context */
+ (*curr_atclose->func)(curr_atclose->ctx);
+
+ /* Advance to next node and free this one */
+ tmp_atclose = curr_atclose;
+ curr_atclose = curr_atclose->next;
+ H5FL_FREE(H5_atclose_node_t, tmp_atclose);
+ } /* end while */
+
+ /* Reset list head, in case library is re-initialized */
+ 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_interface()) && (at + 8) < sizeof loop)? \
- (sprintf(loop + at, "%s%s", (at ? "," : ""), #F), \
- at += HDstrlen(loop + at), \
- n): \
- ((n > 0 && (at + 5) < sizeof loop) ? \
- (sprintf(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.
+ */
+ TERMINATOR(ES, false)
+ /* Do not attempt to close down package L until after event sets
+ * have finished closing down.
*/
- pending += DOWN(R);
- pending += DOWN(D);
- pending += DOWN(L);
- pending += DOWN(G);
- pending += DOWN(A);
- pending += DOWN(S);
- pending += DOWN(T);
+ , 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);
-
- /* 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(F, true)
+ /* Don't shut down the property list code until all objects that might
+ * 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.
+ *
+ * Shut down the "bottom" of the attribute, dataset, group,
+ * reference, dataspace, and datatype interfaces, fully closing
+ * out the interfaces now.
+ */
+ , 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);
- pending += DOWN(Z);
- pending += DOWN(FD);
- pending += DOWN(P);
- 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_ else is down */
- if(pending == 0)
- pending += DOWN(FL);
+ , 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);
+ } while (pending && ntries++ < 100);
- if(pending) {
+ /* clang-format on */
+
+ if (pending) {
/* Only display the error message if the user is interested in them. */
- if(func) {
- fprintf(stderr, "HDF5: infinite loop closing library\n");
- fprintf(stderr, " %s\n", loop);
+ if (func) {
+ HDfprintf(stderr, "HDF5: infinite loop closing library\n");
+ HDfprintf(stderr, " %s\n", loop);
#ifndef NDEBUG
HDabort();
-#endif /* NDEBUG */
+#endif /* NDEBUG */
} /* end if */
- } /* end if */
-
-#ifdef H5_HAVE_MPE
- /* Close MPE instrumentation library. May need to move this
- * down if any of the below code involves using the instrumentation code.
- */
- if(H5_MPEinit_g) {
- int mpe_code;
- int mpi_initialized;
-
- MPI_Initialized(&mpi_initialized);
- if(mpi_initialized) {
- mpe_code = MPE_Finish_log("h5log");
- HDassert(mpe_code >=0);
- } /* end if */
- H5_MPEinit_g = FALSE; /* turn it off no matter what */
- } /* end if */
-#endif
+ } /* end if */
/* Free open debugging streams */
- while(H5_debug_g.open_stream) {
- H5_debug_open_stream_t *tmp_open_stream;
+ while (H5_debug_g.open_stream) {
+ H5_debug_open_stream_t *tmp_open_stream;
tmp_open_stream = H5_debug_g.open_stream;
(void)HDfclose(H5_debug_g.open_stream->stream);
@@ -356,50 +504,51 @@ H5_term_library(void)
(void)H5MM_free(tmp_open_stream);
} /* end while */
+ /* Reset flag indicating that the library is being shut down */
+ H5_TERM_GLOBAL = FALSE;
+
/* Mark library as closed */
H5_INIT_GLOBAL = FALSE;
+
+ /* Don't pop the API context (i.e. H5CX_pop), since it's been shut down already */
+
done:
#ifdef H5_HAVE_THREADSAFE
H5_API_UNLOCK
#endif /* H5_HAVE_THREADSAFE */
+
return;
} /* end H5_term_library() */
-
/*-------------------------------------------------------------------------
- * Function: H5dont_atexit
- *
- * Purpose: Indicates that the library is not to clean up after itself
- * when the application exits by calling exit() or returning
- * from main(). This function must be called before any other
- * HDF5 function or constant is used or it will have no effect.
- *
- * If this function is used then certain memory buffers will not
- * be de-allocated nor will open files be flushed automatically.
- * The application may still call H5close() explicitly to
- * accomplish these things.
+ * Function: H5dont_atexit
*
- * Return: Success: non-negative
+ * Purpose: Indicates that the library is not to clean up after itself
+ * when the application exits by calling exit() or returning
+ * from main(). This function must be called before any other
+ * HDF5 function or constant is used or it will have no effect.
*
- * Failure: negative if this function is called more than
- * once or if it is called too late.
+ * If this function is used then certain memory buffers will not
+ * be de-allocated nor will open files be flushed automatically.
+ * The application may still call H5close() explicitly to
+ * accomplish these things.
*
- * Programmer: Robb Matzke
- * Friday, November 20, 1998
+ * Return: Success: non-negative
*
- * Modifications:
+ * Failure: negative if this function is called more than
+ * once or if it is called too late.
*
*-------------------------------------------------------------------------
*/
herr_t
H5dont_atexit(void)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API_NOINIT_NOERR_NOFS
- H5TRACE0("e","");
+ H5TRACE0("e", "");
- if(H5_dont_atexit_g)
+ if (H5_dont_atexit_g)
ret_value = FAIL;
else
H5_dont_atexit_g = TRUE;
@@ -407,50 +556,43 @@ H5dont_atexit(void)
FUNC_LEAVE_API_NOFS(ret_value)
} /* end H5dont_atexit() */
-
/*-------------------------------------------------------------------------
- * Function: H5garbage_collect
+ * Function: H5garbage_collect
*
- * Purpose: Walks through all the garbage collection routines for the
- * library, which are supposed to free any unused memory they have
- * allocated.
+ * Purpose: Walks through all the garbage collection routines for the
+ * library, which are supposed to free any unused memory they have
+ * allocated.
*
- * These should probably be registered dynamicly in a linked list of
+ * These should probably be registered dynamically in a linked list of
* functions to call, but there aren't that many right now, so we
* hard-wire them...
*
- * Return: Success: non-negative
+ * Return: Success: non-negative
*
- * Failure: negative
- *
- * Programmer: Quincey Koziol
- * Saturday, March 11, 2000
- *
- * Modifications:
+ * Failure: negative
*
*-------------------------------------------------------------------------
*/
herr_t
H5garbage_collect(void)
{
- herr_t ret_value = SUCCEED;
+ herr_t ret_value = SUCCEED;
FUNC_ENTER_API(FAIL)
- H5TRACE0("e","");
+ H5TRACE0("e", "");
/* Call the garbage collection routines in the library */
- if(H5FL_garbage_coll()<0)
+ if (H5FL_garbage_coll() < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGC, FAIL, "can't garbage collect objects")
done:
FUNC_LEAVE_API(ret_value)
-} /* end H5garbage_collect() */
+} /* end H5garbage_collect() */
-
/*-------------------------------------------------------------------------
- * Function: H5set_free_list_limits
+ * Function: H5set_free_list_limits
*
- * Purpose: Sets limits on the different kinds of free lists. Setting a value
+ * Purpose: Sets limits on the different kinds of free lists. Setting a value
* of -1 for a limit means no limit of that type. These limits are global
* for the entire library. Each "global" limit only applies to free lists
* of that type, so if an application sets a limit of 1 MB on each of the
@@ -468,336 +610,414 @@ done:
* int blk_global_lim; IN: The limit on all "block" free list memory used
* int blk_list_lim; IN: The limit on memory used in each "block" free list
*
- * Return: Success: non-negative
+ * Return: Success: non-negative
*
- * Failure: negative
- *
- * Programmer: Quincey Koziol
- * Wednesday, August 2, 2000
- *
- * Modifications: Neil Fortner
- * Wednesday, April 8, 2009
- * Added support for factory free lists
+ * Failure: negative
*
*-------------------------------------------------------------------------
*/
herr_t
-H5set_free_list_limits(int reg_global_lim, int reg_list_lim, int arr_global_lim,
- int arr_list_lim, int blk_global_lim, int blk_list_lim)
+H5set_free_list_limits(int reg_global_lim, int reg_list_lim, int arr_global_lim, int arr_list_lim,
+ int blk_global_lim, int blk_list_lim)
{
- herr_t ret_value = SUCCEED;
+ herr_t ret_value = SUCCEED;
FUNC_ENTER_API(FAIL)
- H5TRACE6("e", "IsIsIsIsIsIs", reg_global_lim, reg_list_lim, arr_global_lim,
- arr_list_lim, blk_global_lim, blk_list_lim);
+ H5TRACE6("e", "IsIsIsIsIsIs", reg_global_lim, reg_list_lim, arr_global_lim, arr_list_lim, blk_global_lim,
+ blk_list_lim);
/* Call the free list function to actually set the limits */
- if(H5FL_set_free_list_limits(reg_global_lim, reg_list_lim, arr_global_lim, arr_list_lim,
- blk_global_lim, blk_list_lim, blk_global_lim, blk_list_lim)<0)
+ if (H5FL_set_free_list_limits(reg_global_lim, reg_list_lim, arr_global_lim, arr_list_lim, blk_global_lim,
+ blk_list_lim, blk_global_lim, blk_list_lim) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSET, FAIL, "can't set garbage collection limits")
done:
FUNC_LEAVE_API(ret_value)
-} /* end H5set_free_list_limits() */
+} /* end H5set_free_list_limits() */
-
/*-------------------------------------------------------------------------
- * Function: H5_debug_mask
- *
- * Purpose: Set runtime debugging flags according to the string S. The
- * string should contain file numbers and package names
- * separated by other characters. A file number applies to all
- * following package names up to the next file number. The
- * initial file number is `2' (the standard error stream). Each
- * package name can be preceded by a `+' or `-' to add or remove
- * the package from the debugging list (`+' is the default). The
- * special name `all' means all packages.
- *
- * The name `trace' indicates that API tracing is to be turned
- * on or off.
- *
- * Return: void
- *
- * Programmer: Robb Matzke
- * Wednesday, August 19, 1998
- *
- * Modifications:
- * Robb Matzke, 2002-08-08
- * Accepts the `ttop' word. If enabled then show only the
- * top level API calls, otherwise show all API calls. Also
- * turns on tracing as if the `trace' word was present.
+ * Function: H5get_free_list_sizes
+ *
+ * Purpose: Gets the current size of the different kinds of free lists that
+ * the library uses to manage memory. The free list sizes can be set with
+ * H5set_free_list_limits and garbage collected with H5garbage_collect.
+ * These lists are global for the entire library.
+ *
+ * Parameters:
+ * size_t *reg_size; OUT: The current size of all "regular" free list memory used
+ * size_t *arr_size; OUT: The current size of all "array" free list memory used
+ * size_t *blk_size; OUT: The current size of all "block" free list memory used
+ * size_t *fac_size; OUT: The current size of all "factory" free list memory used
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Friday, March 6, 2020
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5get_free_list_sizes(size_t *reg_size /*out*/, size_t *arr_size /*out*/, size_t *blk_size /*out*/,
+ size_t *fac_size /*out*/)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE4("e", "xxxx", reg_size, arr_size, blk_size, fac_size);
+
+ /* Call the free list function to actually get the sizes */
+ if (H5FL_get_free_list_sizes(reg_size, arr_size, blk_size, fac_size) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't get garbage collection sizes")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5get_free_list_sizes() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5__debug_mask
+ *
+ * Purpose: Set runtime debugging flags according to the string S. The
+ * string should contain file numbers and package names
+ * separated by other characters. A file number applies to all
+ * following package names up to the next file number. The
+ * initial file number is `2' (the standard error stream). Each
+ * package name can be preceded by a `+' or `-' to add or remove
+ * the package from the debugging list (`+' is the default). The
+ * special name `all' means all packages.
+ *
+ * The name `trace' indicates that API tracing is to be turned
+ * on or off.
+ *
+ * The name 'ttop' indicates that only top-level API calls
+ * should be shown. This also turns on tracing as if the
+ * 'trace' word was shown.
+ *
+ * Return: void
+ *
*-------------------------------------------------------------------------
*/
static void
-H5_debug_mask(const char *s)
+H5__debug_mask(const char *s)
{
- FILE *stream = stderr;
- char pkg_name[32], *rest;
- size_t i;
- hbool_t clear;
+ FILE *stream = stderr;
+ char pkg_name[32], *rest;
+ size_t i;
+ hbool_t clear;
while (s && *s) {
- if (HDisalpha(*s) || '-'==*s || '+'==*s) {
- /* Enable or Disable debugging? */
- if ('-'==*s) {
- clear = TRUE;
- s++;
- } else if ('+'==*s) {
- clear = FALSE;
- s++;
- } else {
- clear = FALSE;
- }
-
- /* Get the name */
- for (i=0; HDisalpha(*s); i++, s++)
- if (i<sizeof pkg_name)
+
+ if (HDisalpha(*s) || '-' == *s || '+' == *s) {
+
+ /* Enable or Disable debugging? */
+ if ('-' == *s) {
+ clear = TRUE;
+ s++;
+ }
+ else if ('+' == *s) {
+ clear = FALSE;
+ s++;
+ }
+ else {
+ clear = FALSE;
+ } /* end if */
+
+ /* Get the name */
+ for (i = 0; HDisalpha(*s); i++, s++)
+ if (i < sizeof pkg_name)
pkg_name[i] = *s;
- pkg_name[MIN(sizeof(pkg_name)-1, i)] = '\0';
+ pkg_name[MIN(sizeof(pkg_name) - 1, i)] = '\0';
- /* Trace, all, or one? */
- if (!HDstrcmp(pkg_name, "trace")) {
- H5_debug_g.trace = clear ? NULL : stream;
- } else if (!HDstrcmp(pkg_name, "ttop")) {
- H5_debug_g.trace = stream;
- H5_debug_g.ttop = (hbool_t)!clear;
- } else if (!HDstrcmp(pkg_name, "ttimes")) {
+ /* Trace, all, or one? */
+ if (!HDstrcmp(pkg_name, "trace")) {
+ H5_debug_g.trace = clear ? NULL : stream;
+ }
+ else if (!HDstrcmp(pkg_name, "ttop")) {
H5_debug_g.trace = stream;
+ H5_debug_g.ttop = (hbool_t)!clear;
+ }
+ else if (!HDstrcmp(pkg_name, "ttimes")) {
+ H5_debug_g.trace = stream;
H5_debug_g.ttimes = (hbool_t)!clear;
- } else if (!HDstrcmp(pkg_name, "all")) {
- for (i=0; i<(size_t)H5_NPKGS; i++)
- H5_debug_g.pkg[i].stream = clear ? NULL : stream;
- } else {
- for (i=0; i<(size_t)H5_NPKGS; i++) {
- if (!HDstrcmp(H5_debug_g.pkg[i].name, pkg_name)) {
- H5_debug_g.pkg[i].stream = clear ? NULL : stream;
- break;
- }
- }
- if (i>=(size_t)H5_NPKGS)
- fprintf(stderr, "HDF5_DEBUG: ignored %s\n", pkg_name);
- }
-
- } else if (HDisdigit(*s)) {
- int fd = (int)HDstrtol(s, &rest, 0);
- H5_debug_open_stream_t *open_stream;
-
- if((stream = HDfdopen(fd, "w")) != NULL) {
- (void)HDsetvbuf(stream, NULL, _IOLBF, (size_t)0);
-
- if(NULL == (open_stream = (H5_debug_open_stream_t *)H5MM_malloc(sizeof(H5_debug_open_stream_t)))) {
+ }
+ else if (!HDstrcmp(pkg_name, "all")) {
+ for (i = 0; i < (size_t)H5_NPKGS; i++)
+ H5_debug_g.pkg[i].stream = clear ? NULL : stream;
+ }
+ else {
+ for (i = 0; i < (size_t)H5_NPKGS; i++) {
+ if (!HDstrcmp(H5_debug_g.pkg[i].name, pkg_name)) {
+ H5_debug_g.pkg[i].stream = clear ? NULL : stream;
+ break;
+ } /* end if */
+ } /* end for */
+ if (i >= (size_t)H5_NPKGS)
+ HDfprintf(stderr, "HDF5_DEBUG: ignored %s\n", pkg_name);
+ } /* end if-else */
+ }
+ else if (HDisdigit(*s)) {
+ int fd = (int)HDstrtol(s, &rest, 0);
+ H5_debug_open_stream_t *open_stream;
+
+ if ((stream = HDfdopen(fd, "w")) != NULL) {
+ (void)HDsetvbuf(stream, NULL, _IOLBF, (size_t)0);
+
+ if (NULL ==
+ (open_stream = (H5_debug_open_stream_t *)H5MM_malloc(sizeof(H5_debug_open_stream_t)))) {
(void)HDfclose(stream);
return;
} /* end if */
- open_stream->stream = stream;
- open_stream->next = H5_debug_g.open_stream;
+ open_stream->stream = stream;
+ open_stream->next = H5_debug_g.open_stream;
H5_debug_g.open_stream = open_stream;
} /* end if */
- s = rest;
- } else {
- s++;
- }
- }
-} /* end H5_debug_mask() */
+
+ s = rest;
+ }
+ else {
+ s++;
+ } /* end if-else */
+ } /* end while */
+} /* end H5__debug_mask() */
#ifdef H5_HAVE_PARALLEL
-
+
/*-------------------------------------------------------------------------
- * Function: H5_mpi_delete_cb
+ * Function: H5__mpi_delete_cb
*
- * Purpose: Callback attribute on MPI_COMM_SELF to terminate the HDF5
+ * Purpose: Callback attribute on MPI_COMM_SELF to terminate the HDF5
* library when the communicator is destroyed, i.e. on MPI_Finalize.
*
- * Return: MPI_SUCCESS
- *
- * Programmer: Mohamad Chaarawi, February 2015
+ * Return: MPI_SUCCESS
*
*-------------------------------------------------------------------------
*/
-static int H5_mpi_delete_cb(MPI_Comm UNUSED comm, int UNUSED keyval, void UNUSED *attr_val, int UNUSED *flag)
+static int
+H5__mpi_delete_cb(MPI_Comm H5_ATTR_UNUSED comm, int H5_ATTR_UNUSED keyval, void H5_ATTR_UNUSED *attr_val,
+ int H5_ATTR_UNUSED *flag)
{
H5_term_library();
return MPI_SUCCESS;
}
#endif /*H5_HAVE_PARALLEL*/
-
/*-------------------------------------------------------------------------
- * Function: H5get_libversion
+ * Function: H5get_libversion
*
- * Purpose: Returns the library version numbers through arguments. MAJNUM
- * will be the major revision number of the library, MINNUM the
- * minor revision number, and RELNUM the release revision number.
+ * Purpose: Returns the library version numbers through arguments. MAJNUM
+ * will be the major revision number of the library, MINNUM the
+ * minor revision number, and RELNUM the release revision number.
*
- * Note: When printing an HDF5 version number it should be printed as
+ * Note: When printing an HDF5 version number it should be printed as
*
- * printf("%u.%u.%u", maj, min, rel) or
- * printf("version %u.%u release %u", maj, min, rel)
+ * printf("%u.%u.%u", maj, min, rel) or
+ * printf("version %u.%u release %u", maj, min, rel)
*
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Unknown
- *
- * Modifications:
- * Robb Matzke, 4 Mar 1998
- * Now use "normal" data types for the interface. Any of the arguments
- * may be null pointers
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
herr_t
-H5get_libversion(unsigned *majnum, unsigned *minnum, unsigned *relnum)
+H5get_libversion(unsigned *majnum /*out*/, unsigned *minnum /*out*/, unsigned *relnum /*out*/)
{
- herr_t ret_value = SUCCEED;
+ herr_t ret_value = SUCCEED;
FUNC_ENTER_API(FAIL)
- H5TRACE3("e", "*Iu*Iu*Iu", majnum, minnum, relnum);
+ H5TRACE3("e", "xxx", majnum, minnum, relnum);
/* Set the version information */
- if (majnum) *majnum = H5_VERS_MAJOR;
- if (minnum) *minnum = H5_VERS_MINOR;
- if (relnum) *relnum = H5_VERS_RELEASE;
+ if (majnum)
+ *majnum = H5_VERS_MAJOR;
+ if (minnum)
+ *minnum = H5_VERS_MINOR;
+ if (relnum)
+ *relnum = H5_VERS_RELEASE;
done:
FUNC_LEAVE_API(ret_value)
} /* end H5get_libversion() */
-
/*-------------------------------------------------------------------------
- * Function: H5check_version
+ * Function: H5check_version
*
- * Purpose: Verifies that the arguments match the version numbers
- * compiled into the library. This function is intended to be
- * called from user to verify that the versions of header files
- * compiled into the application match the version of the hdf5
- * library.
+ * Purpose: Verifies that the arguments match the version numbers
+ * compiled into the library. This function is intended to be
+ * called from user to verify that the versions of header files
+ * compiled into the application match the version of the hdf5
+ * library.
+ * Within major.minor.release version, the expectation
+ * is that all release versions are compatible, exceptions to
+ * this rule must be added to the VERS_RELEASE_EXCEPTIONS list.
*
- * Return: Success: SUCCEED
+ * Return: Success: SUCCEED
*
- * Failure: abort()
- *
- * Programmer: Robb Matzke
- * Tuesday, April 21, 1998
- *
- * Modifications:
- * Albert Cheng, May 12, 2001
- * Added verification of H5_VERS_INFO.
+ * Failure: abort()
*
*-------------------------------------------------------------------------
*/
-#define VERSION_MISMATCH_WARNING \
- "Warning! ***HDF5 library version mismatched error***\n" \
- "The HDF5 header files used to compile this application do not match\n" \
- "the version used by the HDF5 library to which this application is linked.\n" \
- "Data corruption or segmentation faults may occur if the application continues.\n" \
- "This can happen when an application was compiled by one version of HDF5 but\n" \
- "linked with a different version of static or shared HDF5 library.\n" \
- "You should recompile the application or check your shared library related\n" \
+#define VERSION_MISMATCH_WARNING \
+ "Warning! ***HDF5 library version mismatched error***\n" \
+ "The HDF5 header files used to compile this application do not match\n" \
+ "the version used by the HDF5 library to which this application is linked.\n" \
+ "Data corruption or segmentation faults may occur if the application continues.\n" \
+ "This can happen when an application was compiled by one version of HDF5 but\n" \
+ "linked with a different version of static or shared HDF5 library.\n" \
+ "You should recompile the application or check your shared library related\n" \
+ "settings such as 'LD_LIBRARY_PATH'.\n"
+#define RELEASE_MISMATCH_WARNING \
+ "Warning! ***HDF5 library release mismatched error***\n" \
+ "The HDF5 header files used to compile this application are not compatible with\n" \
+ "the version used by the HDF5 library to which this application is linked.\n" \
+ "Data corruption or segmentation faults may occur if the application continues.\n" \
+ "This can happen when an application was compiled by one version of HDF5 but\n" \
+ "linked with an incompatible version of static or shared HDF5 library.\n" \
+ "You should recompile the application or check your shared library related\n" \
"settings such as 'LD_LIBRARY_PATH'.\n"
herr_t
H5check_version(unsigned majnum, unsigned minnum, unsigned relnum)
{
- char lib_str[256];
- char substr[] = H5_VERS_SUBRELEASE;
- 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;
- herr_t ret_value = SUCCEED; /* Return value */
+ char lib_str[256];
+ char substr[] = H5_VERS_SUBRELEASE;
+ 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
H5TRACE3("e", "IuIuIu", majnum, minnum, relnum);
/* Don't check again, if we already have */
if (checked)
- HGOTO_DONE(SUCCEED)
+ HGOTO_DONE(SUCCEED)
- { const char *s; /* Environment string for disabling version check */
+ {
+ const char *s; /* Environment string for disabling version check */
/* Allow different versions of the header files and library? */
- s = HDgetenv ("HDF5_DISABLE_VERSION_CHECK");
+ s = HDgetenv("HDF5_DISABLE_VERSION_CHECK");
if (s && HDisdigit(*s))
- disable_version_check = (unsigned int)HDstrtol (s, NULL, 0);
+ disable_version_check = (unsigned int)HDstrtol(s, NULL, 0);
}
- if (H5_VERS_MAJOR!=majnum || H5_VERS_MINOR!=minnum ||
- H5_VERS_RELEASE!=relnum) {
+ /* H5_VERS_MAJOR and H5_VERS_MINOR must match */
+ if (H5_VERS_MAJOR != majnum || H5_VERS_MINOR != minnum) {
switch (disable_version_check) {
- case 0:
- HDfprintf(stderr, "%s%s", version_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");
- /* 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, (unsigned)H5_VERS_RELEASE);
- /* Show library settings if available */
- HDfprintf (stderr, "%s", H5libhdf5_settings);
-
- /* Bail out now. */
- HDfputs ("Bye...\n", stderr);
- HDabort ();
- case 1:
- /* continue with a warning */
- /* Note that the warning message is embedded in the format string.*/
- HDfprintf (stderr,
- "%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);
- /* 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, (unsigned)H5_VERS_RELEASE);
- /* Show library settings if available */
- HDfprintf (stderr, "%s", H5libhdf5_settings);
- break;
- default:
- /* 2 or higer: continue silently */
- break;
+ case 0:
+ HDfprintf(stderr, "%s%s", version_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");
+ /* 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, (unsigned)H5_VERS_RELEASE);
+ /* Show library settings if available */
+ HDfprintf(stderr, "%s", H5libhdf5_settings);
+
+ /* Bail out now. */
+ HDfputs("Bye...\n", stderr);
+ HDabort();
+ case 1:
+ /* continue with a warning */
+ /* Note that the warning message is embedded in the format string.*/
+ HDfprintf(stderr,
+ "%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);
+ /* 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, (unsigned)H5_VERS_RELEASE);
+ /* Show library settings if available */
+ HDfprintf(stderr, "%s", H5libhdf5_settings);
+ break;
+ default:
+ /* 2 or higher: continue silently */
+ break;
} /* end switch */
- } /* end if */
+ } /* 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 */
+ if (VERS_RELEASE_EXCEPTIONS[i] == relnum || VERS_RELEASE_EXCEPTIONS[i] == H5_VERS_RELEASE) {
+ switch (disable_version_check) {
+ case 0:
+ HDfprintf(
+ 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");
+ /* 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,
+ (unsigned)H5_VERS_RELEASE);
+
+ /* Bail out now. */
+ HDfputs("Bye...\n", stderr);
+ HDabort();
+ case 1:
+ /* continue with a warning */
+ /* Note that the warning message is embedded in the format string.*/
+ HDfprintf(stderr,
+ "%s'HDF5_DISABLE_VERSION_CHECK' "
+ "environment variable is set to %d, application will\n"
+ "continue at your own risk.\n",
+ 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,
+ (unsigned)H5_VERS_RELEASE);
+ break;
+ default:
+ /* 2 or higher: continue silently */
+ break;
+ } /* end switch */
+
+ } /* end if */
+
+ } /* end for */
+
+ } /* end if (H5_VERS_RELEASE != relnum) */
/* Indicate that the version check has been performed */
checked = 1;
- if (!disable_version_check){
- /*
- * Verify if H5_VERS_INFO is consistent with the other version information.
- * Check only the first sizeof(lib_str) char. Assume the information
- * will fit within this size or enough significance.
- */
- HDsnprintf(lib_str, sizeof(lib_str), "HDF5 library version: %d.%d.%d",
- H5_VERS_MAJOR, H5_VERS_MINOR, H5_VERS_RELEASE);
- if(*substr) {
- HDstrncat(lib_str, "-", (size_t)1);
- HDstrncat(lib_str, substr, (sizeof(lib_str) - HDstrlen(lib_str)) - 1);
- } /* end if */
- if (HDstrcmp(lib_str, H5_lib_vers_info_g)){
- HDfputs ("Warning! Library version information error.\n"
- "The HDF5 library version information are not "
- "consistent in its source code.\nThis is NOT a fatal error "
- "but should be corrected. Setting the environment\n"
- "variable 'HDF5_DISABLE_VERSION_CHECK' to a value of 1 "
- "will suppress\nthis warning.\n",
- stderr);
- HDfprintf (stderr, "Library version information are:\n"
- "H5_VERS_MAJOR=%d, H5_VERS_MINOR=%d, H5_VERS_RELEASE=%d, "
- "H5_VERS_SUBRELEASE=%s,\nH5_VERS_INFO=%s\n",
- H5_VERS_MAJOR, H5_VERS_MINOR, H5_VERS_RELEASE,
- H5_VERS_SUBRELEASE, H5_VERS_INFO);
- } /* end if */
+ if (!disable_version_check) {
+ /*
+ * Verify if H5_VERS_INFO is consistent with the other version information.
+ * Check only the first sizeof(lib_str) char. Assume the information
+ * will fit within this size or enough significance.
+ */
+ HDsnprintf(lib_str, sizeof(lib_str), "HDF5 library version: %d.%d.%d%s%s", H5_VERS_MAJOR,
+ H5_VERS_MINOR, H5_VERS_RELEASE, (*substr ? "-" : ""), substr);
+
+ if (HDstrcmp(lib_str, H5_lib_vers_info_g) != 0) {
+ HDfputs("Warning! Library version information error.\n"
+ "The HDF5 library version information are not "
+ "consistent in its source code.\nThis is NOT a fatal error "
+ "but should be corrected. Setting the environment\n"
+ "variable 'HDF5_DISABLE_VERSION_CHECK' to a value of 1 "
+ "will suppress\nthis warning.\n",
+ stderr);
+ HDfprintf(stderr,
+ "Library version information are:\n"
+ "H5_VERS_MAJOR=%d, H5_VERS_MINOR=%d, H5_VERS_RELEASE=%d, "
+ "H5_VERS_SUBRELEASE=%s,\nH5_VERS_INFO=%s\n",
+ H5_VERS_MAJOR, H5_VERS_MINOR, H5_VERS_RELEASE, H5_VERS_SUBRELEASE, H5_VERS_INFO);
+ } /* end if */
}
done:
FUNC_LEAVE_API_NOFS(ret_value)
} /* end H5check_version() */
-
/*-------------------------------------------------------------------------
* Function: H5open
*
@@ -806,39 +1026,69 @@ done:
* is failing inexplicably, then try calling this function
* first.
*
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Robb Matzke
- * Tuesday, December 9, 1997
- *
- * Modifications:
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
herr_t
H5open(void)
{
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOPUSH(FAIL)
+ /*NO TRACE*/
- FUNC_ENTER_API_NOCLEAR(FAIL)
- H5TRACE0("e","");
/* all work is done by FUNC_ENTER() */
+
done:
- FUNC_LEAVE_API(ret_value)
+ FUNC_LEAVE_API_NOPUSH(ret_value)
} /* end H5open() */
-
/*-------------------------------------------------------------------------
- * Function: H5close
+ * Function: H5atclose
*
- * Purpose: Terminate the library and release all resources.
+ * Purpose: Register a callback for the library to invoke when it's
+ * closing. Callbacks are invoked in LIFO order.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Robb Matzke
- * Friday, January 30, 1998
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5atclose(H5_atclose_func_t func, void *ctx)
+{
+ H5_atclose_node_t *new_atclose; /* New 'atclose' node */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE2("e", "Hc*x", func, ctx);
+
+ /* Check arguments */
+ if (NULL == func)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL func pointer")
+
+ /* Allocate space for the 'atclose' node */
+ if (NULL == (new_atclose = H5FL_MALLOC(H5_atclose_node_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate 'atclose' node")
+
+ /* Set up 'atclose' node */
+ new_atclose->func = func;
+ new_atclose->ctx = ctx;
+
+ /* Connector to linked-list of 'atclose' nodes */
+ new_atclose->next = H5_atclose_head;
+ H5_atclose_head = new_atclose;
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5atclose() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5close
+ *
+ * Purpose: Terminate the library and release all resources.
*
- * Modifications:
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -851,18 +1101,17 @@ H5close(void)
* this function for an uninitialized library.
*/
FUNC_ENTER_API_NOINIT_NOERR_NOFS
- H5TRACE0("e","");
+ H5TRACE0("e", "");
H5_term_library();
FUNC_LEAVE_API_NOFS(SUCCEED)
} /* end H5close() */
-
/*-------------------------------------------------------------------------
- * Function: H5allocate_memory
+ * Function: H5allocate_memory
*
- * Purpose: Allocate a memory buffer with the semantics of malloc().
+ * Purpose: Allocate a memory buffer with the semantics of malloc().
*
* NOTE: This function is intended for use with filter
* plugins so that all allocation and free operations
@@ -877,9 +1126,10 @@ H5close(void)
*
* Return:
*
- * Success: A pointer to the allocated buffer.
- *
- * Failure: NULL
+ * Success: A pointer to the allocated buffer or NULL if the size
+ * parameter is zero.
+ *
+ * Failure: NULL (but may also be NULL w/ size 0!)
*
*-------------------------------------------------------------------------
*/
@@ -888,23 +1138,24 @@ H5allocate_memory(size_t size, hbool_t clear)
{
void *ret_value = NULL;
- FUNC_ENTER_API_NOINIT;
+ FUNC_ENTER_API_NOINIT
H5TRACE2("*x", "zb", size, clear);
- if(clear)
+ if (0 == size)
+ return NULL;
+
+ if (clear)
ret_value = H5MM_calloc(size);
else
ret_value = H5MM_malloc(size);
- FUNC_LEAVE_API(ret_value)
-
+ FUNC_LEAVE_API_NOINIT(ret_value)
} /* end H5allocate_memory() */
-
/*-------------------------------------------------------------------------
- * Function: H5resize_memory
+ * Function: H5resize_memory
*
- * Purpose: Resize a memory buffer with the semantics of realloc().
+ * Purpose: Resize a memory buffer with the semantics of realloc().
*
* NOTE: This function is intended for use with filter
* plugins so that all allocation and free operations
@@ -920,7 +1171,7 @@ H5allocate_memory(size_t size, hbool_t clear)
* Return:
*
* Success: A pointer to the resized buffer.
- *
+ *
* Failure: NULL (the input buffer will be unchanged)
*
*-------------------------------------------------------------------------
@@ -930,44 +1181,103 @@ H5resize_memory(void *mem, size_t size)
{
void *ret_value = NULL;
- FUNC_ENTER_API_NOINIT;
+ FUNC_ENTER_API_NOINIT
H5TRACE2("*x", "*xz", mem, size);
ret_value = H5MM_realloc(mem, size);
- FUNC_LEAVE_API(ret_value)
-
+ FUNC_LEAVE_API_NOINIT(ret_value)
} /* end H5resize_memory() */
-
/*-------------------------------------------------------------------------
- * Function: H5free_memory
+ * Function: H5free_memory
*
- * Purpose: Frees memory allocated by the library that it is the user's
+ * Purpose: Frees memory allocated by the library that it is the user's
* responsibility to free. Ensures that the same library
* that was used to allocate the memory frees it. Passing
* NULL pointers is allowed.
*
- * Return: SUCCEED/FAIL
+ * Return: SUCCEED/FAIL
*
*-------------------------------------------------------------------------
*/
herr_t
H5free_memory(void *mem)
{
- FUNC_ENTER_API_NOINIT;
+ FUNC_ENTER_API_NOINIT
H5TRACE1("e", "*x", mem);
/* At this time, it is impossible for this to fail. */
- HDfree(mem);
-
- FUNC_LEAVE_API(SUCCEED)
+ H5MM_xfree(mem);
+ FUNC_LEAVE_API_NOINIT(SUCCEED)
} /* end H5free_memory() */
-
-#if defined(H5_HAVE_THREADSAFE) && defined(H5_BUILT_AS_DYNAMIC_LIB) \
- && defined(H5_HAVE_WIN32_API) && defined(H5_HAVE_WIN_THREADS)
+/*-------------------------------------------------------------------------
+ * Function: H5is_library_threadsafe
+ *
+ * Purpose: Checks to see if the library was built with thread-safety
+ * enabled.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5is_library_threadsafe(hbool_t *is_ts /*out*/)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE1("e", "x", is_ts);
+
+ if (is_ts) {
+#ifdef H5_HAVE_THREADSAFE
+ *is_ts = TRUE;
+#else /* H5_HAVE_THREADSAFE */
+ *is_ts = FALSE;
+#endif /* H5_HAVE_THREADSAFE */
+ }
+ else
+ ret_value = FAIL;
+
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5is_library_threadsafe() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5is_library_terminating
+ *
+ * Purpose: Checks to see if the library is shutting down.
+ *
+ * Note: Useful for plugins to detect when the library is terminating.
+ * For example, a VOL connector could check if a "file close"
+ * callback was the result of the library shutdown process, or
+ * an API action from the application.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5is_library_terminating(hbool_t *is_terminating /*out*/)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE1("e", "x", is_terminating);
+
+ HDassert(is_terminating);
+
+ if (is_terminating)
+ *is_terminating = H5_TERM_GLOBAL;
+ else
+ ret_value = FAIL;
+
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5is_library_terminating() */
+
+#if defined(H5_HAVE_THREADSAFE) && defined(H5_BUILT_AS_DYNAMIC_LIB) && defined(H5_HAVE_WIN32_API) && \
+ defined(H5_HAVE_WIN_THREADS)
/*-------------------------------------------------------------------------
* Function: DllMain
*
@@ -995,35 +1305,33 @@ DllMain(_In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVOID lpvReserved)
BOOL fOkay = TRUE;
- switch(fdwReason)
- {
- case DLL_PROCESS_ATTACH:
- break;
+ switch (fdwReason) {
+ case DLL_PROCESS_ATTACH:
+ break;
- case DLL_PROCESS_DETACH:
- break;
+ case DLL_PROCESS_DETACH:
+ break;
- case DLL_THREAD_ATTACH:
+ case DLL_THREAD_ATTACH:
#ifdef H5_HAVE_WIN_THREADS
- if(H5TS_win32_thread_enter() < 0)
- fOkay = FALSE;
+ if (H5TS_win32_thread_enter() < 0)
+ fOkay = FALSE;
#endif /* H5_HAVE_WIN_THREADS */
- break;
+ break;
- case DLL_THREAD_DETACH:
+ case DLL_THREAD_DETACH:
#ifdef H5_HAVE_WIN_THREADS
- if(H5TS_win32_thread_exit() < 0)
- fOkay = FALSE;
+ if (H5TS_win32_thread_exit() < 0)
+ fOkay = FALSE;
#endif /* H5_HAVE_WIN_THREADS */
- break;
+ break;
- default:
- /* Shouldn't get here */
- fOkay = FALSE;
- break;
+ default:
+ /* Shouldn't get here */
+ fOkay = FALSE;
+ break;
}
return fOkay;
}
#endif /* H5_HAVE_WIN32_API && H5_BUILT_AS_DYNAMIC_LIB && H5_HAVE_WIN_THREADS && H5_HAVE_THREADSAFE*/
-