Merge pull request #1599 in HDFFV/hdf5 from preserve_lib_state to develop

* commit '86598573641dfa27278c9e29df0fa79bd7d8e07f':
  Add API routines to retrieve, restore, reset, and free library state.
This commit is contained in:
Quincey Koziol 2019-03-12 11:48:11 -05:00
commit 07baf44a86
6 changed files with 783 additions and 46 deletions

View File

@ -64,17 +64,22 @@
#define H5CX_get_my_context() (&H5CX_head_g)
#endif /* H5_HAVE_THREADSAFE */
/* Common macro for the retrieving the pointer to a property list */
#define H5CX_RETRIEVE_PLIST(PL, FAILVAL) \
/* Check if the property list is already available */ \
if(NULL == (*head)->ctx.PL) \
/* Get the property list pointer */ \
if(NULL == ((*head)->ctx.PL = (H5P_genplist_t *)H5I_object((*head)->ctx.H5_GLUE(PL,_id)))) \
HGOTO_ERROR(H5E_CONTEXT, H5E_BADTYPE, (FAILVAL), "can't get property list")
/* Common macro for the duplicated code to retrieve properties from a property list */
#define H5CX_RETRIEVE_PROP_COMMON(PL, DEF_PL, PROP_NAME, PROP_FIELD) \
/* Check for default property list */ \
if((*head)->ctx.H5_GLUE(PL,_id) == (DEF_PL)) \
HDmemcpy(&(*head)->ctx.PROP_FIELD, &H5_GLUE3(H5CX_def_,PL,_cache).PROP_FIELD, sizeof(H5_GLUE3(H5CX_def_,PL,_cache).PROP_FIELD)); \
else { \
/* Check if the property list is already available */ \
if(NULL == (*head)->ctx.PL) \
/* Get the dataset transfer property list pointer */ \
if(NULL == ((*head)->ctx.PL = (H5P_genplist_t *)H5I_object((*head)->ctx.H5_GLUE(PL,_id)))) \
HGOTO_ERROR(H5E_CONTEXT, H5E_BADTYPE, FAIL, "can't get default dataset transfer property list") \
/* Retrieve the property list */ \
H5CX_RETRIEVE_PLIST(PL, FAIL) \
\
/* Get the property */ \
if(H5P_get((*head)->ctx.PL, (PROP_NAME), &(*head)->ctx.PROP_FIELD) < 0) \
@ -108,11 +113,8 @@
\
/* Check if property exists in DXPL */ \
if(!(*head)->ctx.H5_GLUE(PROP_FIELD,_set)) { \
/* Check if the property list is already available */ \
if(NULL == (*head)->ctx.dxpl) \
/* Get the dataset transfer property list pointer */ \
if(NULL == ((*head)->ctx.dxpl = (H5P_genplist_t *)H5I_object((*head)->ctx.dxpl_id))) \
HGOTO_ERROR(H5E_CONTEXT, H5E_BADTYPE, FAIL, "can't get default dataset transfer property list") \
/* Retrieve the dataset transfer property list */ \
H5CX_RETRIEVE_PLIST(dxpl, FAIL) \
\
if((check_prop = H5P_exist_plist((*head)->ctx.dxpl, PROP_NAME)) < 0) \
HGOTO_ERROR(H5E_CONTEXT, H5E_CANTGET, FAIL, "error checking for property") \
@ -129,15 +131,12 @@
/* Macro for the duplicated code to test and set properties for a property list */
#define H5CX_SET_PROP(PROP_NAME, PROP_FIELD) \
if((*head)->ctx.H5_GLUE(PROP_FIELD,_set)) { \
/* Check if the property list is already available */ \
if(NULL == (*head)->ctx.dxpl) \
/* Get the dataset transfer property list pointer */ \
if(NULL == ((*head)->ctx.dxpl = (H5P_genplist_t *)H5I_object((*head)->ctx.dxpl_id))) \
HGOTO_ERROR(H5E_CONTEXT, H5E_BADTYPE, NULL, "can't get default dataset transfer property list") \
/* Retrieve the dataset transfer property list */ \
H5CX_RETRIEVE_PLIST(dxpl, NULL) \
\
/* Set the chunk filter mask property */ \
/* Set the property */ \
if(H5P_set((*head)->ctx.dxpl, PROP_NAME, &(*head)->ctx.PROP_FIELD) < 0) \
HGOTO_ERROR(H5E_CONTEXT, H5E_CANTSET, NULL, "error setting filter mask xfer property") \
HGOTO_ERROR(H5E_CONTEXT, H5E_CANTSET, NULL, "error setting data xfer property") \
} /* end if */
#endif /* H5_HAVE_PARALLEL */
@ -175,7 +174,7 @@
* corresponding property in the property list to be set when the API
* context is popped, when returning from the API routine. Note that the
* naming of these fields, <foo> and <foo>_set, is important for the
* H5CX_TEST_SET_PROP and H5CX_SET_PROP macros to work properly.
* H5CX_TEST_SET_PROP and H5CX_SET_PROP macros to work properly.
*/
typedef struct H5CX_t {
/* DXPL */
@ -378,6 +377,9 @@ static H5CX_dcpl_cache_t H5CX_def_dcpl_cache;
/* Declare a static free list to manage H5CX_node_t structs */
H5FL_DEFINE_STATIC(H5CX_node_t);
/* Declare a static free list to manage H5CX_state_t structs */
H5FL_DEFINE_STATIC(H5CX_state_t);
/*--------------------------------------------------------------------------
@ -707,6 +709,226 @@ H5CX_push_special(void)
FUNC_LEAVE_NOAPI_VOID
} /* end H5CX_push_special() */
/*-------------------------------------------------------------------------
* Function: H5CX_retrieve_state
*
* Purpose: Retrieve the state of an API context, for later resumption.
*
* Note: This routine _only_ tracks the state of API context information
* set before the VOL callback is invoked, not values that are
* set internal to the library. It's main purpose is to provide
* API context state to VOL connectors.
*
* Return: Non-negative on success / Negative on failure
*
* Programmer: Quincey Koziol
* January 8, 2019
*
*-------------------------------------------------------------------------
*/
herr_t
H5CX_retrieve_state(H5CX_state_t **api_state)
{
H5CX_node_t **head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/* Sanity check */
HDassert(head && *head);
HDassert(api_state);
/* Allocate & clear API context state */
if(NULL == (*api_state = H5FL_CALLOC(H5CX_state_t)))
HGOTO_ERROR(H5E_CONTEXT, H5E_CANTALLOC, FAIL, "unable to allocate new API context state")
/* Check for non-default DXPL */
if(H5P_DATASET_XFER_DEFAULT != (*head)->ctx.dxpl_id) {
/* Retrieve the DXPL property list */
H5CX_RETRIEVE_PLIST(dxpl, FAIL)
/* Copy the DXPL ID */
if(((*api_state)->dxpl_id = H5P_copy_plist((H5P_genplist_t *)(*head)->ctx.dxpl, FALSE)) < 0)
HGOTO_ERROR(H5E_CONTEXT, H5E_CANTCOPY, FAIL, "can't copy property list")
} /* end if */
else
(*api_state)->dxpl_id = H5P_DATASET_XFER_DEFAULT;
/* Check for non-default LAPL */
if(H5P_LINK_ACCESS_DEFAULT != (*head)->ctx.lapl_id) {
/* Retrieve the LAPL property list */
H5CX_RETRIEVE_PLIST(lapl, FAIL)
/* Copy the LAPL ID */
if(((*api_state)->lapl_id = H5P_copy_plist((H5P_genplist_t *)(*head)->ctx.lapl, FALSE)) < 0)
HGOTO_ERROR(H5E_CONTEXT, H5E_CANTCOPY, FAIL, "can't copy property list")
} /* end if */
else
(*api_state)->lapl_id = H5P_LINK_ACCESS_DEFAULT;
/* Keep a reference to the current VOL wrapping context */
(*api_state)->vol_wrap_ctx = (*head)->ctx.vol_wrap_ctx;
if(NULL != (*api_state)->vol_wrap_ctx)
if(H5VL_inc_vol_wrapper((*api_state)->vol_wrap_ctx) < 0)
HGOTO_ERROR(H5E_CONTEXT, H5E_CANTINC, FAIL, "can't increment refcount on VOL wrapping context")
/* Keep a copy of the VOL connector property, if there is one */
if((*head)->ctx.vol_connector_prop_valid && (*head)->ctx.vol_connector_prop.connector_id > 0) {
/* Get the connector property */
HDmemcpy(&(*api_state)->vol_connector_prop, &(*head)->ctx.vol_connector_prop, sizeof(H5VL_connector_prop_t));
/* Check for actual VOL connector property */
if((*api_state)->vol_connector_prop.connector_id) {
/* Copy connector info, if it exists */
if((*api_state)->vol_connector_prop.connector_info) {
H5VL_class_t *connector; /* Pointer to connector */
void *new_connector_info = NULL; /* Copy of connector info */
/* Retrieve the connector for the ID */
if(NULL == (connector = (H5VL_class_t *)H5I_object((*api_state)->vol_connector_prop.connector_id)))
HGOTO_ERROR(H5E_CONTEXT, H5E_BADTYPE, FAIL, "not a VOL connector ID")
/* Allocate and copy connector info */
if(H5VL_copy_connector_info(connector, &new_connector_info, (*api_state)->vol_connector_prop.connector_info) < 0)
HGOTO_ERROR(H5E_CONTEXT, H5E_CANTCOPY, FAIL, "connector info copy failed")
(*api_state)->vol_connector_prop.connector_info = new_connector_info;
} /* end if */
/* Increment the refcount on the connector ID */
if(H5I_inc_ref((*api_state)->vol_connector_prop.connector_id, FALSE) < 0)
HGOTO_ERROR(H5E_CONTEXT, H5E_CANTINC, FAIL, "incrementing VOL connector ID failed")
} /* end if */
} /* end if */
#ifdef H5_HAVE_PARALLEL
/* Save parallel I/O settings */
(*api_state)->coll_metadata_read = (*head)->ctx.coll_metadata_read;
#endif /* H5_HAVE_PARALLEL */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5CX_retrieve_state() */
/*-------------------------------------------------------------------------
* Function: H5CX_restore_state
*
* Purpose: Restore an API context, from a previously retrieved state.
*
* Note: This routine _only_ resets the state of API context information
* set before the VOL callback is invoked, not values that are
* set internal to the library. It's main purpose is to restore
* API context state from VOL connectors.
*
* Return: Non-negative on success / Negative on failure
*
* Programmer: Quincey Koziol
* January 9, 2019
*
*-------------------------------------------------------------------------
*/
herr_t
H5CX_restore_state(const H5CX_state_t *api_state)
{
H5CX_node_t **head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */
FUNC_ENTER_NOAPI_NOINIT_NOERR
/* Sanity check */
HDassert(head && *head);
HDassert(api_state);
/* Restore the DXPL info */
(*head)->ctx.dxpl_id = api_state->dxpl_id;
(*head)->ctx.dxpl = NULL;
/* Restore the LAPL info */
(*head)->ctx.lapl_id = api_state->lapl_id;
(*head)->ctx.lapl = NULL;
/* Restore the VOL wrapper context */
(*head)->ctx.vol_wrap_ctx = api_state->vol_wrap_ctx;
/* Restore the VOL connector info */
if(api_state->vol_connector_prop.connector_id) {
HDmemcpy(&(*head)->ctx.vol_connector_prop, &api_state->vol_connector_prop, sizeof(H5VL_connector_prop_t));
(*head)->ctx.vol_connector_prop_valid = TRUE;
} /* end if */
#ifdef H5_HAVE_PARALLEL
/* Restore parallel I/O settings */
(*head)->ctx.coll_metadata_read = api_state->coll_metadata_read;
#endif /* H5_HAVE_PARALLEL */
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5CX_restore_state() */
/*-------------------------------------------------------------------------
* Function: H5CX_free_state
*
* Purpose: Free a previously retrievedAPI context state
*
* Return: Non-negative on success / Negative on failure
*
* Programmer: Quincey Koziol
* January 9, 2019
*
*-------------------------------------------------------------------------
*/
herr_t
H5CX_free_state(H5CX_state_t *api_state)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/* Sanity check */
HDassert(api_state);
/* Release the DXPL */
if(api_state->dxpl_id != H5P_DATASET_XFER_DEFAULT)
if(H5I_dec_ref(api_state->dxpl_id) < 0)
HGOTO_ERROR(H5E_CONTEXT, H5E_CANTDEC, FAIL, "can't decrement refcount on DXPL")
/* Release the LAPL */
if(api_state->lapl_id != H5P_LINK_ACCESS_DEFAULT)
if(H5I_dec_ref(api_state->lapl_id) < 0)
HGOTO_ERROR(H5E_CONTEXT, H5E_CANTDEC, FAIL, "can't decrement refcount on LAPL")
/* Release the VOL wrapper context */
if(api_state->vol_wrap_ctx)
if(H5VL_dec_vol_wrapper(api_state->vol_wrap_ctx) < 0)
HGOTO_ERROR(H5E_CONTEXT, H5E_CANTDEC, FAIL, "can't decrement refcount on VOL wrapping context")
/* Release the VOL connector property, if it was set */
if(api_state->vol_connector_prop.connector_id) {
/* Clean up any VOL connector info */
if(api_state->vol_connector_prop.connector_info) {
H5VL_class_t *connector; /* Pointer to connector */
/* Retrieve the connector for the ID */
if(NULL == (connector = (H5VL_class_t *)H5I_object(api_state->vol_connector_prop.connector_id)))
HGOTO_ERROR(H5E_CONTEXT, H5E_BADTYPE, FAIL, "not a VOL connector ID")
/* Free the connector info */
if(H5VL_free_connector_info(connector, api_state->vol_connector_prop.connector_info) < 0)
HGOTO_ERROR(H5E_CONTEXT, H5E_CANTRELEASE, FAIL, "unable to release VOL connector info object")
} /* end if */
/* Decrement connector ID */
if(H5I_dec_ref(api_state->vol_connector_prop.connector_id) < 0)
HDONE_ERROR(H5E_CONTEXT, H5E_CANTDEC, FAIL, "can't close VOL connector ID")
} /* end if */
/* Free the state */
api_state = H5FL_FREE(H5CX_state_t, api_state);
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5CX_free_state() */
/*-------------------------------------------------------------------------
* Function: H5CX_is_def_dxpl
@ -951,6 +1173,7 @@ H5CX_set_loc(hid_t
#endif /* H5_HAVE_PARALLEL */
loc_id)
{
#ifdef H5_HAVE_PARALLEL
H5CX_node_t **head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */
herr_t ret_value = SUCCEED; /* Return value */
@ -959,7 +1182,6 @@ H5CX_set_loc(hid_t
/* Sanity check */
HDassert(head && *head);
#ifdef H5_HAVE_PARALLEL
/* Set collective metadata read flag */
(*head)->ctx.coll_metadata_read = TRUE;
@ -980,10 +1202,14 @@ H5CX_set_loc(hid_t
if(mpi_comm != MPI_COMM_NULL)
MPI_Barrier(mpi_comm);
} /* end if */
#endif /* H5_HAVE_PARALLEL */
done:
FUNC_LEAVE_NOAPI(ret_value)
#else /* H5_HAVE_PARALLEL */
FUNC_ENTER_NOAPI_NOINIT_NOERR
FUNC_LEAVE_NOAPI(SUCCEED)
#endif /* H5_HAVE_PARALLEL */
} /* end H5CX_set_loc() */

View File

@ -39,6 +39,19 @@
/* Library Private Typedefs */
/****************************/
/* API context state */
typedef struct H5CX_state_t {
hid_t dxpl_id; /* DXPL for operation */
hid_t lapl_id; /* LAPL for operation */
void *vol_wrap_ctx; /* VOL connector's "wrap context" for creating IDs */
H5VL_connector_prop_t vol_connector_prop; /* VOL connector property */
#ifdef H5_HAVE_PARALLEL
/* Internal: Parallel I/O settings */
hbool_t coll_metadata_read; /* Whether to use collective I/O for metadata read */
#endif /* H5_HAVE_PARALLEL */
} H5CX_state_t;
/*****************************/
/* Library-private Variables */
@ -57,6 +70,11 @@ H5_DLL herr_t H5CX_pop(void);
H5_DLL void H5CX_push_special(void);
H5_DLL hbool_t H5CX_is_def_dxpl(void);
/* API context state routines */
H5_DLL herr_t H5CX_retrieve_state(H5CX_state_t **api_state);
H5_DLL herr_t H5CX_restore_state(const H5CX_state_t *api_state);
H5_DLL herr_t H5CX_free_state(H5CX_state_t *api_state);
/* "Setter" routines for API context info */
H5_DLL void H5CX_set_dxpl(hid_t dxpl_id);
H5_DLL void H5CX_set_lapl(hid_t lapl_id);

View File

@ -488,6 +488,9 @@ done:
*
* Purpose: Compares two connector classes (based on their value field)
*
* Note: This routine is _only_ for HDF5 VOL connector authors! It is
* _not_ part of the public API for HDF5 application developers.
*
* Return: Success: Non-negative, *cmp set to a value like strcmp
*
* Failure: Negative, *cmp unset
@ -587,3 +590,159 @@ done:
FUNC_LEAVE_API(ret_value)
} /* H5VLobject() */
/*---------------------------------------------------------------------------
* Function: H5VLretrieve_lib_state
*
* Purpose: Retrieves a copy of the internal state of the HDF5 library,
* so that it can be restored later.
*
* Note: This routine is _only_ for HDF5 VOL connector authors! It is
* _not_ part of the public API for HDF5 application developers.
*
* Return: Success: Non-negative, *state set
* Failure: Negative, *state unset
*
* Programmer: Quincey Koziol
* Thursday, January 10, 2019
*
*---------------------------------------------------------------------------
*/
herr_t
H5VLretrieve_lib_state(void **state)
{
herr_t ret_value = SUCCEED; /* Return value */
/* Must use this, to avoid modifying the API context stack in FUNC_ENTER */
FUNC_ENTER_API_NOINIT
H5TRACE1("e", "**x", state);
/* Check args */
if(NULL == state)
HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "invalid state pointer")
/* Retrieve the library state */
if(H5VL_retrieve_lib_state(state) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't retrieve library state")
done:
FUNC_LEAVE_API_NOINIT(ret_value)
} /* H5VLretrieve_lib_state() */
/*---------------------------------------------------------------------------
* Function: H5VLrestore_lib_state
*
* Purpose: Restores the internal state of the HDF5 library.
*
* Note: This routine is _only_ for HDF5 VOL connector authors! It is
* _not_ part of the public API for HDF5 application developers.
*
* Return: Success: Non-negative
* Failure: Negative
*
* Programmer: Quincey Koziol
* Thursday, January 10, 2019
*
*---------------------------------------------------------------------------
*/
herr_t
H5VLrestore_lib_state(const void *state)
{
herr_t ret_value = SUCCEED; /* Return value */
/* Must use this, to avoid modifying the API context stack in FUNC_ENTER */
FUNC_ENTER_API_NOINIT
H5TRACE1("e", "*x", state);
/* Check args */
if(NULL == state)
HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "invalid state pointer")
/* Restore the library state */
if(H5VL_restore_lib_state(state) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't restore library state")
done:
FUNC_LEAVE_API_NOINIT(ret_value)
} /* H5VLrestore_lib_state() */
/*---------------------------------------------------------------------------
* Function: H5VLreset_lib_state
*
* Purpose: Resets the internal state of the HDF5 library, undoing the
* affects of H5VLrestore_lib_state.
*
* Note: This routine is _only_ for HDF5 VOL connector authors! It is
* _not_ part of the public API for HDF5 application developers.
*
* Note: This routine must be called as a "pair" with
* H5VLrestore_lib_state. It can be called before / after /
* independently of H5VLfree_lib_state.
*
* Return: Success: Non-negative
* Failure: Negative
*
* Programmer: Quincey Koziol
* Saturday, February 23, 2019
*
*---------------------------------------------------------------------------
*/
herr_t
H5VLreset_lib_state(void)
{
herr_t ret_value = SUCCEED; /* Return value */
/* Must use this, to avoid modifying the API context stack in FUNC_ENTER */
FUNC_ENTER_API_NOINIT
H5TRACE0("e","");
/* Reset the library state */
if(H5VL_reset_lib_state() < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTRESET, FAIL, "can't reset library state")
done:
FUNC_LEAVE_API_NOINIT(ret_value)
} /* H5VLreset_lib_state() */
/*---------------------------------------------------------------------------
* Function: H5VLfree_lib_state
*
* Purpose: Free a retrieved library state.
*
* Note: This routine is _only_ for HDF5 VOL connector authors! It is
* _not_ part of the public API for HDF5 application developers.
*
* Note: This routine must be called as a "pair" with
* H5VLretrieve_lib_state.
*
* Return: Success: Non-negative
* Failure: Negative
*
* Programmer: Quincey Koziol
* Thursday, January 10, 2019
*
*---------------------------------------------------------------------------
*/
herr_t
H5VLfree_lib_state(void *state)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE1("e", "*x", state);
/* Check args */
if(NULL == state)
HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "invalid state pointer")
/* Free the library state */
if(H5VL_free_lib_state(state) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "can't free library state")
done:
FUNC_LEAVE_API(ret_value)
} /* H5VLfree_lib_state() */

View File

@ -51,7 +51,7 @@
/* Object wrapping context info */
typedef struct H5VL_wrap_ctx_t {
unsigned rc; /* Ref. count for the # of times the context was set / reset */
const H5VL_t *connector; /* VOL connector for "outermost" class to start wrap */
H5VL_t *connector; /* VOL connector for "outermost" class to start wrap */
void *obj_wrap_ctx; /* "wrap context" for outermost connector */
} H5VL_wrap_ctx_t;
@ -68,7 +68,10 @@ static herr_t H5VL__free_cls(H5VL_class_t *cls);
static void *H5VL__wrap_obj(void *obj, H5I_type_t obj_type);
static H5VL_object_t *H5VL__new_vol_obj(H5I_type_t type, void *object,
H5VL_t *vol_connector, hbool_t wrap_obj);
static int64_t H5VL__conn_inc_rc(H5VL_t *connector);
static int64_t H5VL__conn_dec_rc(H5VL_t *connector);
static void *H5VL__object(hid_t id, H5I_type_t obj_type);
static herr_t H5VL__free_vol_wrapper(H5VL_wrap_ctx_t *vol_wrap_ctx);
/*********************/
@ -317,7 +320,7 @@ H5VL__new_vol_obj(H5I_type_t type, void *object, H5VL_t *vol_connector, hbool_t
new_vol_obj->data = object;
/* Bump the reference count on the VOL connector */
vol_connector->nrefs++;
H5VL__conn_inc_rc(vol_connector);
/* If this is a datatype, we have to hide the VOL object under the H5T_t pointer */
if(H5I_DATATYPE == type) {
@ -548,6 +551,76 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5VL_register_using_vol_id() */
/*-------------------------------------------------------------------------
* Function: H5VL__conn_inc_rc
*
* Purpose: Wrapper to increment the ref. count on a connector.
*
* Return: Current ref. count (can't fail)
*
* Programmer: Quincey Koziol
* February 23, 2019
*
*-------------------------------------------------------------------------
*/
static int64_t
H5VL__conn_inc_rc(H5VL_t *connector)
{
FUNC_ENTER_STATIC_NOERR
/* Check arguments */
HDassert(connector);
/* Increment refcount for connector */
connector->nrefs++;
FUNC_LEAVE_NOAPI(connector->nrefs)
} /* end H5VL__conn_inc_rc() */
/*-------------------------------------------------------------------------
* Function: H5VL__conn_dec_rc
*
* Purpose: Wrapper to decrement the ref. count on a connector.
*
* Return: Current ref. count (>=0) on success, <0 on failure
*
* Programmer: Quincey Koziol
* February 23, 2019
*
*-------------------------------------------------------------------------
*/
static int64_t
H5VL__conn_dec_rc(H5VL_t *connector)
{
int64_t ret_value = -1; /* Return value */
FUNC_ENTER_STATIC
/* Check arguments */
HDassert(connector);
/* Decrement refcount for connector */
connector->nrefs--;
/* Check for last reference */
if(0 == connector->nrefs) {
if(H5I_dec_ref(connector->id) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTDEC, FAIL, "unable to decrement ref count on VOL connector")
H5FL_FREE(H5VL_t, connector);
/* Set return value */
ret_value = 0;
} /* end if */
else
/* Set return value */
ret_value = connector->nrefs;
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5VL__conn_dec_rc() */
/*-------------------------------------------------------------------------
* Function: H5VL_free_object
@ -562,20 +635,16 @@ done:
herr_t
H5VL_free_object(H5VL_object_t *vol_obj)
{
herr_t ret_value = SUCCEED;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(SUCCEED)
FUNC_ENTER_NOAPI(FAIL)
/* Check arguments */
HDassert(vol_obj);
vol_obj->connector->nrefs --;
if(0 == vol_obj->connector->nrefs) {
if(H5I_dec_ref(vol_obj->connector->id) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTDEC, FAIL, "unable to decrement ref count on VOL connector")
vol_obj->connector = H5FL_FREE(H5VL_t, vol_obj->connector);
} /* end if */
/* Decrement refcount on connector */
if(H5VL__conn_dec_rc(vol_obj->connector) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTDEC, FAIL, "unable to decrement ref count on VOL connector")
vol_obj = H5FL_FREE(H5VL_object_t, vol_obj);
@ -950,6 +1019,189 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5VL_cmp_connector_cls() */
/*-------------------------------------------------------------------------
* Function: H5VL_retrieve_lib_state
*
* Purpose: Retrieve the state of the library.
*
* Note: Currently just retrieves the API context state, but could be
* expanded in the future.
*
* Return: Success: Non-negative, *state set
* Failure: Negative, *state unset
*
*-------------------------------------------------------------------------
*/
herr_t
H5VL_retrieve_lib_state(void **state)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/* Sanity checks */
HDassert(state);
/* Retrieve the API context state */
if(H5CX_retrieve_state((H5CX_state_t **)state) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get API context state")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5VL_retrieve_lib_state() */
/*-------------------------------------------------------------------------
* Function: H5VL_restore_lib_state
*
* Purpose: Restore the state of the library.
*
* Note: Currently just restores the API context state, but could be
* expanded in the future.
*
* Return: SUCCEED / FAIL
*
* Programmer: Quincey Koziol
* Thursday, January 10, 2019
*
*-------------------------------------------------------------------------
*/
herr_t
H5VL_restore_lib_state(const void *state)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/* Sanity checks */
HDassert(state);
/* Push a new API context on the stack */
if(H5CX_push() < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't push API context")
/* Restore the API context state */
if(H5CX_restore_state((const H5CX_state_t *)state) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set API context state")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5VL_restore_lib_state() */
/*-------------------------------------------------------------------------
* Function: H5VL_reset_lib_state
*
* Purpose: Reset the state of the library, undoing affects of
* H5VL_restore_lib_state.
*
* Note: Currently just resets the API context state, but could be
* expanded in the future.
*
* Note: This routine must be called as a "pair" with
* H5VL_restore_lib_state. It can be called before / after /
* independently of H5VL_free_lib_state.
*
* Return: SUCCEED / FAIL
*
* Programmer: Quincey Koziol
* Saturday, February 23, 2019
*
*-------------------------------------------------------------------------
*/
herr_t
H5VL_reset_lib_state(void)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/* Pop the API context off the stack */
if(H5CX_pop() < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTRESET, FAIL, "can't pop API context")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5VL_reset_lib_state() */
/*-------------------------------------------------------------------------
* Function: H5VL_free_lib_state
*
* Purpose: Free a library state.
*
* Note: This routine must be called as a "pair" with
* H5VL_retrieve_lib_state.
*
* Return: SUCCEED / FAIL
*
* Programmer: Quincey Koziol
* Thursday, January 10, 2019
*
*-------------------------------------------------------------------------
*/
herr_t
H5VL_free_lib_state(void *state)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/* Sanity checks */
HDassert(state);
/* Free the API context state */
if(H5CX_free_state((H5CX_state_t *)state) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "can't free API context state")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5VL_free_lib_state() */
/*-------------------------------------------------------------------------
* Function: H5VL__free_vol_wrapper
*
* Purpose: Free object wrapping context for VOL connector
*
* Return: SUCCEED / FAIL
*
* Programmer: Quincey Koziol
* Wednesday, January 9, 2019
*
*-------------------------------------------------------------------------
*/
static herr_t
H5VL__free_vol_wrapper(H5VL_wrap_ctx_t *vol_wrap_ctx)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
/* Sanity check */
HDassert(vol_wrap_ctx);
HDassert(0 == vol_wrap_ctx->rc);
HDassert(vol_wrap_ctx->connector);
HDassert(vol_wrap_ctx->connector->cls);
/* If there is a VOL connector object wrapping context, release it */
if(vol_wrap_ctx->obj_wrap_ctx)
/* Release the VOL connector's object wrapping context */
if((*vol_wrap_ctx->connector->cls->wrap_cls.free_wrap_ctx)(vol_wrap_ctx->obj_wrap_ctx) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "unable to release connector's object wrapping context")
/* Decrement refcount on connector */
if(H5VL__conn_dec_rc(vol_wrap_ctx->connector) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTDEC, FAIL, "unable to decrement ref count on VOL connector")
/* Release object wrapping context */
H5FL_FREE(H5VL_wrap_ctx_t, vol_wrap_ctx);
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5VL__free_vol_wrapper() */
/*-------------------------------------------------------------------------
* Function: H5VL_set_vol_wrapper
@ -961,7 +1213,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
H5VL_set_vol_wrapper(void *obj, const H5VL_t *connector)
H5VL_set_vol_wrapper(void *obj, H5VL_t *connector)
{
H5VL_wrap_ctx_t *vol_wrap_ctx = NULL; /* Object wrapping context */
void *obj_wrap_ctx = NULL; /* VOL connector's wrapping context */
@ -993,8 +1245,11 @@ H5VL_set_vol_wrapper(void *obj, const H5VL_t *connector)
if(NULL == (vol_wrap_ctx = H5FL_MALLOC(H5VL_wrap_ctx_t)))
HGOTO_ERROR(H5E_VOL, H5E_CANTALLOC, FAIL, "can't allocate VOL wrap context")
/* Increment the outstanding objects that are using the connector */
H5VL__conn_inc_rc(connector);
/* Set up VOL object wrapper context */
vol_wrap_ctx->rc = 1;;
vol_wrap_ctx->rc = 1;
vol_wrap_ctx->connector = connector;
vol_wrap_ctx->obj_wrap_ctx = obj_wrap_ctx;
} /* end if */
@ -1014,6 +1269,80 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5VL_set_vol_wrapper() */
/*-------------------------------------------------------------------------
* Function: H5VL_inc_vol_wrapper
*
* Purpose: Increment refcount on object wrapping context
*
* Return: SUCCEED / FAIL
*
* Programmer: Quincey Koziol
* Wednesday, January 9, 2019
*
*-------------------------------------------------------------------------
*/
herr_t
H5VL_inc_vol_wrapper(void *_vol_wrap_ctx)
{
H5VL_wrap_ctx_t *vol_wrap_ctx = (H5VL_wrap_ctx_t *)_vol_wrap_ctx; /* VOL object wrapping context */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/* Check for valid, active VOL object wrap context */
if(NULL == vol_wrap_ctx)
HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "no VOL object wrap context?")
if(0 == vol_wrap_ctx->rc)
HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "bad VOL object wrap context refcount?")
/* Increment ref count on wrapping context */
vol_wrap_ctx->rc++;
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5VL_inc_vol_wrapper() */
/*-------------------------------------------------------------------------
* Function: H5VL_dec_vol_wrapper
*
* Purpose: Decrement refcount on object wrapping context, releasing it
* if the refcount drops to zero.
*
* Return: SUCCEED / FAIL
*
* Programmer: Quincey Koziol
* Wednesday, January 9, 2019
*
*-------------------------------------------------------------------------
*/
herr_t
H5VL_dec_vol_wrapper(void *_vol_wrap_ctx)
{
H5VL_wrap_ctx_t *vol_wrap_ctx = (H5VL_wrap_ctx_t *)_vol_wrap_ctx; /* VOL object wrapping context */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/* Check for valid, active VOL object wrap context */
if(NULL == vol_wrap_ctx)
HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "no VOL object wrap context?")
if(0 == vol_wrap_ctx->rc)
HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "bad VOL object wrap context refcount?")
/* Decrement ref count on wrapping context */
vol_wrap_ctx->rc--;
/* Release context if the ref count drops to zero */
if(0 == vol_wrap_ctx->rc)
if(H5VL__free_vol_wrapper(vol_wrap_ctx) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "unable to release VOL object wrapping context")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5VL_dec_vol_wrapper() */
/*-------------------------------------------------------------------------
* Function: H5VL_reset_vol_wrapper
@ -1045,25 +1374,18 @@ H5VL_reset_vol_wrapper(void)
/* Release context if the ref count drops to zero */
if(0 == vol_wrap_ctx->rc) {
/* If there is a VOL connector object wrapping context, release it */
if(vol_wrap_ctx->obj_wrap_ctx) {
/* Release the VOL connector's object wrapping context */
if((*vol_wrap_ctx->connector->cls->wrap_cls.free_wrap_ctx)(vol_wrap_ctx->obj_wrap_ctx) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "unable to release connector's object wrapping context")
} /* end if */
/* Release object wrapping context */
H5FL_FREE(H5VL_wrap_ctx_t, vol_wrap_ctx);
if(H5VL__free_vol_wrapper(vol_wrap_ctx) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "unable to release VOL object wrapping context")
/* Reset the wrapper context */
if(H5CX_set_vol_wrap_ctx(NULL) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL object wrap context")
} /* end if */
else {
else
/* Save the updated wrapper context */
if(H5CX_set_vol_wrap_ctx(vol_wrap_ctx) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL object wrap context")
} /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)

View File

@ -41,8 +41,8 @@ typedef struct H5VL_object_t {
/* Internal structure to hold the connector ID & info for FAPLs */
typedef struct H5VL_connector_prop_t {
hid_t connector_id; /* VOL connector's ID */
const void *connector_info; /* VOL connector info, for open callbacks */
hid_t connector_id; /* VOL connector's ID */
void *connector_info; /* VOL connector info, for open callbacks */
} H5VL_connector_prop_t;
/* Which kind of VOL connector field to use for searching */
@ -92,11 +92,19 @@ H5_DLL herr_t H5VL_free_object(H5VL_object_t *obj);
H5_DLL herr_t H5VL_get_wrap_ctx(const H5VL_class_t *connector, void *obj,
void **wrap_ctx);
H5_DLL herr_t H5VL_free_wrap_ctx(const H5VL_class_t *connector, void *wrap_ctx);
H5_DLL herr_t H5VL_set_vol_wrapper(void *obj, const H5VL_t *vol_connector);
H5_DLL herr_t H5VL_set_vol_wrapper(void *obj, H5VL_t *vol_connector);
H5_DLL herr_t H5VL_inc_vol_wrapper(void *vol_wrap_ctx);
H5_DLL herr_t H5VL_dec_vol_wrapper(void *vol_wrap_ctx);
H5_DLL herr_t H5VL_reset_vol_wrapper(void);
H5_DLL void * H5VL_wrap_object(const H5VL_class_t *connector, void *wrap_ctx,
void *obj, H5I_type_t obj_type);
/* Library state functions */
H5_DLL herr_t H5VL_retrieve_lib_state(void **state);
H5_DLL herr_t H5VL_restore_lib_state(const void *state);
H5_DLL herr_t H5VL_reset_lib_state(void);
H5_DLL herr_t H5VL_free_lib_state(void *state);
/* ID registration functions */
H5_DLL hid_t H5VL_register(H5I_type_t type, void *object, H5VL_t *vol_connector, hbool_t app_ref);
H5_DLL hid_t H5VL_wrap_register(H5I_type_t type, void *obj, hbool_t app_ref);

View File

@ -450,6 +450,10 @@ H5_DLL herr_t H5VLunregister_connector(hid_t connector_id);
H5_DLL herr_t H5VLcmp_connector_cls(int *cmp, hid_t connector_id1, hid_t connector_id2);
H5_DLL hid_t H5VLwrap_register(void *obj, H5I_type_t type);
H5_DLL void *H5VLobject(hid_t obj_id);
H5_DLL herr_t H5VLretrieve_lib_state(void **state);
H5_DLL herr_t H5VLrestore_lib_state(const void *state);
H5_DLL herr_t H5VLreset_lib_state(void);
H5_DLL herr_t H5VLfree_lib_state(void *state);
/* Public wrappers for generic callbacks */