代码拉取完成,页面将自动刷新
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the COPYING file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* H5Iint.c - Private routines for handling IDs
*/
/****************/
/* Module Setup */
/****************/
#include "H5Imodule.h" /* This source code file is part of the H5I module */
/***********/
/* Headers */
/***********/
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
#include "H5FLprivate.h" /* Free Lists */
#include "H5Ipkg.h" /* IDs */
#include "H5MMprivate.h" /* Memory management */
#include "H5Tprivate.h" /* Datatypes */
#include "H5VLprivate.h" /* Virtual Object Layer */
/****************/
/* Local Macros */
/****************/
/* Combine a Type number and an ID index into an ID */
#define H5I_MAKE(g, i) ((((hid_t)(g)&TYPE_MASK) << ID_BITS) | ((hid_t)(i)&ID_MASK))
/******************/
/* Local Typedefs */
/******************/
/* User data for iterator callback for retrieving an ID corresponding to an object pointer */
typedef struct {
const void *object; /* object pointer to search for */
H5I_type_t obj_type; /* type of object we are searching for */
hid_t ret_id; /* ID returned */
} H5I_get_id_ud_t;
/* User data for iterator callback for ID iteration */
typedef struct {
H5I_search_func_t user_func; /* 'User' function to invoke */
void *user_udata; /* User data to pass to 'user' function */
hbool_t app_ref; /* Whether this is an appl. ref. call */
H5I_type_t obj_type; /* Type of object we are iterating over */
} H5I_iterate_ud_t;
/* User data for H5I__clear_type_cb */
typedef struct {
H5I_type_info_t *type_info; /* Pointer to the type's info to be cleared */
hbool_t force; /* Whether to always remove the ID */
hbool_t app_ref; /* Whether this is an appl. ref. call */
} H5I_clear_type_ud_t;
/********************/
/* Package Typedefs */
/********************/
/********************/
/* Local Prototypes */
/********************/
static void *H5I__unwrap(void *object, H5I_type_t type);
static herr_t H5I__mark_node(void *_id, void *key, void *udata);
static void *H5I__remove_common(H5I_type_info_t *type_info, hid_t id);
static int H5I__dec_ref(hid_t id, void **request);
static int H5I__dec_app_ref(hid_t id, void **request);
static int H5I__dec_app_ref_always_close(hid_t id, void **request);
static int H5I__find_id_cb(void *_item, void *_key, void *_udata);
/*********************/
/* Package Variables */
/*********************/
/* Declared extern in H5Ipkg.h and documented there */
H5I_type_info_t *H5I_type_info_array_g[H5I_MAX_NUM_TYPES];
int H5I_next_type_g = (int)H5I_NTYPES;
/* Declare a free list to manage the H5I_id_info_t struct */
H5FL_DEFINE_STATIC(H5I_id_info_t);
/* Whether deletes are actually marks (for mark-and-sweep) */
hbool_t H5I_marking_g = FALSE;
/*****************************/
/* Library Private Variables */
/*****************************/
/*******************/
/* Local Variables */
/*******************/
/*-------------------------------------------------------------------------
* Function: H5I_term_package
*
* Purpose: Terminate the H5I interface: release all memory, reset all
* global variables to initial values. This only happens if all
* types have been destroyed from other interfaces.
*
* Return: Success: Positive if any action was taken that might
* affect some other interface; zero otherwise.
*
* Failure: Negative
*
*-------------------------------------------------------------------------
*/
int
H5I_term_package(void)
{
int in_use = 0; /* Number of ID types still in use */
FUNC_ENTER_NOAPI_NOINIT_NOERR
H5I_type_info_t *type_info = NULL; /* Pointer to ID type */
int i;
/* Count the number of types still in use */
for (i = 0; i < H5I_next_type_g; i++)
if ((type_info = H5I_type_info_array_g[i]) && type_info->hash_table)
in_use++;
/* If no types are still being used then clean up */
if (0 == in_use) {
for (i = 0; i < H5I_next_type_g; i++) {
type_info = H5I_type_info_array_g[i];
if (type_info) {
HDassert(NULL == type_info->hash_table);
type_info = H5MM_xfree(type_info);
H5I_type_info_array_g[i] = NULL;
in_use++;
}
}
}
FUNC_LEAVE_NOAPI(in_use)
} /* end H5I_term_package() */
/*-------------------------------------------------------------------------
* Function: H5I_register_type
*
* Purpose: Creates a new type of ID's to give out.
* The class is initialized or its reference count is incremented
* (if it is already initialized).
*
* Return: SUCCEED/FAIL
*
*-------------------------------------------------------------------------
*/
herr_t
H5I_register_type(const H5I_class_t *cls)
{
H5I_type_info_t *type_info = NULL; /* Pointer to the ID type*/
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/* Sanity check */
HDassert(cls);
HDassert(cls->type > 0 && (int)cls->type < H5I_MAX_NUM_TYPES);
/* Initialize the type */
if (NULL == H5I_type_info_array_g[cls->type]) {
/* Allocate the type information for new type */
if (NULL == (type_info = (H5I_type_info_t *)H5MM_calloc(sizeof(H5I_type_info_t))))
HGOTO_ERROR(H5E_ID, H5E_CANTALLOC, FAIL, "ID type allocation failed")
H5I_type_info_array_g[cls->type] = type_info;
}
else {
/* Get the pointer to the existing type */
type_info = H5I_type_info_array_g[cls->type];
}
/* Initialize the ID type structure for new types */
if (type_info->init_count == 0) {
type_info->cls = cls;
type_info->id_count = 0;
type_info->nextid = cls->reserved;
type_info->last_id_info = NULL;
type_info->hash_table = NULL;
}
/* Increment the count of the times this type has been initialized */
type_info->init_count++;
done:
/* Clean up on error */
if (ret_value < 0)
if (type_info)
H5MM_free(type_info);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I_register_type() */
/*-------------------------------------------------------------------------
* Function: H5I_nmembers
*
* Purpose: Returns the number of members in a type.
*
* Return: Success: Number of members; zero if the type is empty
* or has been deleted.
*
* Failure: Negative
*
* Programmer: Robb Matzke
* Wednesday, March 24, 1999
*
*-------------------------------------------------------------------------
*/
int64_t
H5I_nmembers(H5I_type_t type)
{
H5I_type_info_t *type_info = NULL; /* Pointer to the ID type */
int64_t ret_value = 0; /* Return value */
FUNC_ENTER_NOAPI((-1))
/* Validate parameter */
if (type <= H5I_BADID || (int)type >= H5I_next_type_g)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
if (NULL == (type_info = H5I_type_info_array_g[type]) || type_info->init_count <= 0)
HGOTO_DONE(0);
/* Set return value */
H5_CHECKED_ASSIGN(ret_value, int64_t, type_info->id_count, uint64_t);
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I_nmembers() */
/*-------------------------------------------------------------------------
* Function: H5I__unwrap
*
* Purpose: Unwraps the object pointer for the 'item' that corresponds
* to an ID.
*
* Return: Pointer to the unwrapped pointer (can't fail)
*
* Programmer: Quincey Koziol
* Friday, October 19, 2018
*
*-------------------------------------------------------------------------
*/
static void *
H5I__unwrap(void *object, H5I_type_t type)
{
void *ret_value = NULL; /* Return value */
FUNC_ENTER_PACKAGE_NOERR
/* Sanity checks */
HDassert(object);
/* The stored object pointer might be an H5VL_object_t, in which
* case we'll need to get the wrapped object struct (H5F_t *, etc.).
*/
if (H5I_FILE == type || H5I_GROUP == type || H5I_DATASET == type || H5I_ATTR == type) {
const H5VL_object_t *vol_obj;
vol_obj = (const H5VL_object_t *)object;
ret_value = H5VL_object_data(vol_obj);
}
else if (H5I_DATATYPE == type) {
H5T_t *dt = (H5T_t *)object;
ret_value = (void *)H5T_get_actual_type(dt);
}
else
ret_value = object;
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I__unwrap() */
/*-------------------------------------------------------------------------
* Function: H5I_clear_type
*
* Purpose: Removes all objects from the type, calling the free
* function for each object regardless of the reference count.
*
* Return: SUCCEED/FAIL
*
* Programmer: Robb Matzke
* Wednesday, March 24, 1999
*
*-------------------------------------------------------------------------
*/
herr_t
H5I_clear_type(H5I_type_t type, hbool_t force, hbool_t app_ref)
{
H5I_clear_type_ud_t udata; /* udata struct for callback */
H5I_id_info_t *item = NULL;
H5I_id_info_t *tmp = NULL;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/* Validate parameters */
if (type <= H5I_BADID || (int)type >= H5I_next_type_g)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
udata.type_info = H5I_type_info_array_g[type];
if (udata.type_info == NULL || udata.type_info->init_count <= 0)
HGOTO_ERROR(H5E_ID, H5E_BADGROUP, FAIL, "invalid type")
/* Finish constructing udata */
udata.force = force;
udata.app_ref = app_ref;
/* Clearing a type is done in two phases (mark-and-sweep). This is because
* the type's free callback can free other IDs, potentially corrupting
* the data structure during the traversal.
*/
/* Set marking flag */
H5I_marking_g = TRUE;
/* Mark nodes for deletion */
HASH_ITER(hh, udata.type_info->hash_table, item, tmp)
{
if (!item->marked)
if (H5I__mark_node((void *)item, NULL, (void *)&udata) < 0)
HGOTO_ERROR(H5E_ID, H5E_BADITER, FAIL, "iteration failed while clearing the ID type")
}
/* Unset marking flag */
H5I_marking_g = FALSE;
/* Perform sweep */
HASH_ITER(hh, udata.type_info->hash_table, item, tmp)
{
if (item->marked) {
HASH_DELETE(hh, udata.type_info->hash_table, item);
item = H5FL_FREE(H5I_id_info_t, item);
}
}
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I_clear_type() */
/*-------------------------------------------------------------------------
* Function: H5I__mark_node
*
* Purpose: Attempts to mark the node for freeing and calls the free
* function for the object, if any
*
* Return: SUCCEED/FAIL
*
* Programmer: Neil Fortner
* Friday, July 10, 2015
*
*-------------------------------------------------------------------------
*/
static herr_t
H5I__mark_node(void *_info, void H5_ATTR_UNUSED *key, void *_udata)
{
H5I_id_info_t *info = (H5I_id_info_t *)_info; /* Current ID info being worked with */
H5I_clear_type_ud_t *udata = (H5I_clear_type_ud_t *)_udata; /* udata struct */
hbool_t mark = FALSE;
FUNC_ENTER_PACKAGE_NOERR
/* Sanity checks */
HDassert(info);
HDassert(udata);
HDassert(udata->type_info);
/* Do nothing to the object if the reference count is larger than
* one and forcing is off.
*/
if (udata->force || (info->count - (!udata->app_ref * info->app_count)) <= 1) {
/* Check if this is an un-realized future object */
H5_GCC_CLANG_DIAG_OFF("cast-qual")
if (info->is_future) {
/* Discard the future object */
if ((info->discard_cb)((void *)info->object) < 0) {
if (udata->force) {
#ifdef H5I_DEBUG
if (H5DEBUG(I)) {
HDfprintf(H5DEBUG(I),
"H5I: discard type=%d obj=0x%08lx "
"failure ignored\n",
(int)udata->type_info->cls->type, (unsigned long)(info->object));
}
#endif /* H5I_DEBUG */
/* Indicate node should be removed from list */
mark = TRUE;
}
}
else {
/* Indicate node should be removed from list */
mark = TRUE;
}
}
else {
/* Check for a 'free' function and call it, if it exists */
if (udata->type_info->cls->free_func &&
(udata->type_info->cls->free_func)((void *)info->object, H5_REQUEST_NULL) < 0) {
if (udata->force) {
#ifdef H5I_DEBUG
if (H5DEBUG(I)) {
HDfprintf(H5DEBUG(I),
"H5I: free type=%d obj=0x%08lx "
"failure ignored\n",
(int)udata->type_info->cls->type, (unsigned long)(info->object));
}
#endif /* H5I_DEBUG */
/* Indicate node should be removed from list */
mark = TRUE;
}
}
else {
/* Indicate node should be removed from list */
mark = TRUE;
}
}
H5_GCC_CLANG_DIAG_ON("cast-qual")
/* Remove ID if requested */
if (mark) {
/* Mark ID for deletion */
info->marked = TRUE;
/* Decrement the number of IDs in the type */
udata->type_info->id_count--;
}
}
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5I__mark_node() */
/*-------------------------------------------------------------------------
* Function: H5I__destroy_type
*
* Purpose: Destroys a type along with all IDs in that type
* regardless of their reference counts. Destroying IDs
* involves calling the free-func for each ID's object and
* then adding the ID struct to the ID free list.
*
* Return: SUCCEED/FAIL
*
* Programmer: Nathaniel Furrer
* James Laird
*
*-------------------------------------------------------------------------
*/
herr_t
H5I__destroy_type(H5I_type_t type)
{
H5I_type_info_t *type_info = NULL; /* Pointer to the ID type */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* Validate parameter */
if (type <= H5I_BADID || (int)type >= H5I_next_type_g)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
type_info = H5I_type_info_array_g[type];
if (type_info == NULL || type_info->init_count <= 0)
HGOTO_ERROR(H5E_ID, H5E_BADGROUP, FAIL, "invalid type")
/* Close/clear/destroy all IDs for this type */
H5E_BEGIN_TRY
{
H5I_clear_type(type, TRUE, FALSE);
}
H5E_END_TRY /* don't care about errors */
/* Check if we should release the ID class */
if (type_info->cls->flags & H5I_CLASS_IS_APPLICATION)
type_info->cls = H5MM_xfree_const(type_info->cls);
HASH_CLEAR(hh, type_info->hash_table);
type_info->hash_table = NULL;
type_info = H5MM_xfree(type_info);
H5I_type_info_array_g[type] = NULL;
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I__destroy_type() */
/*-------------------------------------------------------------------------
* Function: H5I__register
*
* Purpose: Registers an OBJECT in a TYPE and returns an ID for it.
* This routine does _not_ check for unique-ness of the objects,
* if you register an object twice, you will get two different
* IDs for it. This routine does make certain that each ID in a
* type is unique. IDs are created by getting a unique number
* for the type the ID is in and incorporating the TYPE into
* the ID which is returned to the user.
*
* IDs are marked as "future" if the realize_cb and discard_cb
* parameters are non-NULL.
*
* Return: Success: New object ID
* Failure: H5I_INVALID_HID
*
*-------------------------------------------------------------------------
*/
hid_t
H5I__register(H5I_type_t type, const void *object, hbool_t app_ref, H5I_future_realize_func_t realize_cb,
H5I_future_discard_func_t discard_cb)
{
H5I_type_info_t *type_info = NULL; /* Pointer to the type */
H5I_id_info_t *info = NULL; /* Pointer to the new ID information */
hid_t new_id = H5I_INVALID_HID; /* New ID */
hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_PACKAGE
/* Check arguments */
if (type <= H5I_BADID || (int)type >= H5I_next_type_g)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, H5I_INVALID_HID, "invalid type number")
type_info = H5I_type_info_array_g[type];
if ((NULL == type_info) || (type_info->init_count <= 0))
HGOTO_ERROR(H5E_ID, H5E_BADGROUP, H5I_INVALID_HID, "invalid type")
if (NULL == (info = H5FL_CALLOC(H5I_id_info_t)))
HGOTO_ERROR(H5E_ID, H5E_NOSPACE, H5I_INVALID_HID, "memory allocation failed")
/* Create the struct & its ID */
new_id = H5I_MAKE(type, type_info->nextid);
info->id = new_id;
info->count = 1; /* initial reference count */
info->app_count = !!app_ref;
info->object = object;
info->is_future = (NULL != realize_cb);
info->realize_cb = realize_cb;
info->discard_cb = discard_cb;
info->marked = FALSE;
/* Insert into the type */
HASH_ADD(hh, type_info->hash_table, id, sizeof(hid_t), info);
type_info->id_count++;
type_info->nextid++;
/* Sanity check for the 'nextid' getting too large and wrapping around */
HDassert(type_info->nextid <= ID_MASK);
/* Set the most recent ID to this object */
type_info->last_id_info = info;
/* Set return value */
ret_value = new_id;
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I__register() */
/*-------------------------------------------------------------------------
* Function: H5I_register
*
* Purpose: Library-private wrapper for H5I__register.
*
* Return: Success: New object ID
* Failure: H5I_INVALID_HID
*
*-------------------------------------------------------------------------
*/
hid_t
H5I_register(H5I_type_t type, const void *object, hbool_t app_ref)
{
hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_NOAPI(H5I_INVALID_HID)
/* Sanity checks */
HDassert(type >= H5I_FILE && type < H5I_NTYPES);
HDassert(object);
/* Retrieve ID for object */
if (H5I_INVALID_HID == (ret_value = H5I__register(type, object, app_ref, NULL, NULL)))
HGOTO_ERROR(H5E_ID, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register object")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I_register() */
/*-------------------------------------------------------------------------
* Function: H5I_register_using_existing_id
*
* Purpose: Registers an OBJECT in a TYPE with the supplied ID for it.
* This routine will check to ensure the supplied ID is not already
* in use, and ensure that it is a valid ID for the given type,
* but will NOT check to ensure the OBJECT is not already
* registered (thus, it is possible to register one object under
* multiple IDs).
*
* NOTE: Intended for use in refresh calls, where we have to close
* and re-open the underlying data, then hook the object back
* up to the original ID.
*
* Return: SUCCEED/FAIL
*
*-------------------------------------------------------------------------
*/
herr_t
H5I_register_using_existing_id(H5I_type_t type, void *object, hbool_t app_ref, hid_t existing_id)
{
H5I_type_info_t *type_info = NULL; /* Pointer to the type */
H5I_id_info_t *info = NULL; /* Pointer to the new ID information */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/* Check arguments */
HDassert(object);
/* Make sure ID is not already in use */
if (NULL != (info = H5I__find_id(existing_id)))
HGOTO_ERROR(H5E_ID, H5E_BADRANGE, FAIL, "ID already in use")
/* Make sure type number is valid */
if (type <= H5I_BADID || (int)type >= H5I_next_type_g)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
/* Get type pointer from list of types */
type_info = H5I_type_info_array_g[type];
if (NULL == type_info || type_info->init_count <= 0)
HGOTO_ERROR(H5E_ID, H5E_BADGROUP, FAIL, "invalid type")
/* Make sure requested ID belongs to object's type */
if (H5I_TYPE(existing_id) != type)
HGOTO_ERROR(H5E_ID, H5E_BADRANGE, FAIL, "invalid type for provided ID")
/* Allocate new structure to house this ID */
if (NULL == (info = H5FL_CALLOC(H5I_id_info_t)))
HGOTO_ERROR(H5E_ID, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Create the struct & insert requested ID */
info->id = existing_id;
info->count = 1; /* initial reference count*/
info->app_count = !!app_ref;
info->object = object;
/* This API call is only used by the native VOL connector, which is
* not asynchronous.
*/
info->is_future = FALSE;
info->realize_cb = NULL;
info->discard_cb = NULL;
info->marked = FALSE;
/* Insert into the type */
HASH_ADD(hh, type_info->hash_table, id, sizeof(hid_t), info);
type_info->id_count++;
/* Set the most recent ID to this object */
type_info->last_id_info = info;
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I_register_using_existing_id() */
/*-------------------------------------------------------------------------
* Function: H5I_subst
*
* Purpose: Substitute a new object pointer for the specified ID.
*
* Return: Success: Non-NULL previous object pointer associated
* with the specified ID.
* Failure: NULL
*
* Programmer: Quincey Koziol
* Saturday, February 27, 2010
*
*-------------------------------------------------------------------------
*/
void *
H5I_subst(hid_t id, const void *new_object)
{
H5I_id_info_t *info = NULL; /* Pointer to the ID's info */
void *ret_value = NULL; /* Return value */
FUNC_ENTER_NOAPI(NULL)
/* General lookup of the ID */
if (NULL == (info = H5I__find_id(id)))
HGOTO_ERROR(H5E_ID, H5E_NOTFOUND, NULL, "can't get ID ref count")
/* Get the old object pointer to return */
H5_GCC_CLANG_DIAG_OFF("cast-qual")
ret_value = (void *)info->object;
H5_GCC_CLANG_DIAG_ON("cast-qual")
/* Set the new object pointer for the ID */
info->object = new_object;
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I_subst() */
/*-------------------------------------------------------------------------
* Function: H5I_object
*
* Purpose: Find an object pointer for the specified ID.
*
* Return: Success: Non-NULL object pointer associated with the
* specified ID
*
* Failure: NULL
*
*-------------------------------------------------------------------------
*/
void *
H5I_object(hid_t id)
{
H5I_id_info_t *info = NULL; /* Pointer to the ID info */
void *ret_value = NULL; /* Return value */
FUNC_ENTER_NOAPI_NOERR
/* General lookup of the ID */
if (NULL != (info = H5I__find_id(id))) {
/* Get the object pointer to return */
H5_GCC_CLANG_DIAG_OFF("cast-qual")
ret_value = (void *)info->object;
H5_GCC_CLANG_DIAG_ON("cast-qual")
}
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I_object() */
/*-------------------------------------------------------------------------
* Function: H5I_object_verify
*
* Purpose: Find an object pointer for the specified ID, verifying that
* its in a particular type.
*
* Return: Success: Non-NULL object pointer associated with the
* specified ID.
* Failure: NULL
*
* Programmer: Quincey Koziol
* Wednesday, July 31, 2002
*
*-------------------------------------------------------------------------
*/
void *
H5I_object_verify(hid_t id, H5I_type_t type)
{
H5I_id_info_t *info = NULL; /* Pointer to the ID info */
void *ret_value = NULL; /* Return value */
FUNC_ENTER_NOAPI_NOERR
HDassert(type >= 1 && (int)type < H5I_next_type_g);
/* Verify that the type of the ID is correct & lookup the ID */
if (type == H5I_TYPE(id) && NULL != (info = H5I__find_id(id))) {
/* Get the object pointer to return */
H5_GCC_CLANG_DIAG_OFF("cast-qual")
ret_value = (void *)info->object;
H5_GCC_CLANG_DIAG_ON("cast-qual")
}
FUNC_LEAVE_NOAPI(ret_value)
} /* H5I_object_verify() */
/*-------------------------------------------------------------------------
* Function: H5I_get_type
*
* Purpose: Given an object ID return the type to which it
* belongs. The ID need not be the ID of an object which
* currently exists because the type number is encoded
* in the object ID.
*
* Return: Success: A positive integer (corresponding to an H5I_type_t
* enum value for library ID types, but not for user
* ID types).
* Failure: H5I_BADID
*
* Programmer: Robb Matzke
* Friday, February 19, 1999
*
*-------------------------------------------------------------------------
*/
H5I_type_t
H5I_get_type(hid_t id)
{
H5I_type_t ret_value = H5I_BADID; /* Return value */
FUNC_ENTER_NOAPI_NOERR
if (id > 0)
ret_value = H5I_TYPE(id);
HDassert(ret_value >= H5I_BADID && (int)ret_value < H5I_next_type_g);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I_get_type() */
/*-------------------------------------------------------------------------
* Function: H5I_is_file_object
*
* Purpose: Convenience function to determine if an ID represents
* a file object.
*
* In H5O calls, you can't use object_verify to ensure
* the ID was of the correct class since there's no
* H5I_OBJECT ID class.
*
* Return: Success: TRUE/FALSE
* Failure: FAIL
*
*-------------------------------------------------------------------------
*/
htri_t
H5I_is_file_object(hid_t id)
{
H5I_type_t type = H5I_get_type(id);
htri_t ret_value = FAIL;
FUNC_ENTER_NOAPI(FAIL);
/* Fail if the ID type is out of range */
if (type < 1 || type >= H5I_NTYPES)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID type out of range");
/* Return TRUE if the ID is a file object (dataset, group, map, or committed
* datatype), FALSE otherwise.
*/
if (H5I_DATASET == type || H5I_GROUP == type || H5I_MAP == type)
ret_value = TRUE;
else if (H5I_DATATYPE == type) {
H5T_t *dt = NULL;
if (NULL == (dt = (H5T_t *)H5I_object(id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "unable to get underlying datatype struct");
ret_value = H5T_is_named(dt);
}
else
ret_value = FALSE;
done:
FUNC_LEAVE_NOAPI(ret_value);
} /* H5I_is_file_object() */
/*-------------------------------------------------------------------------
* Function: H5I__remove_verify
*
* Purpose: Removes the specified ID from its type, first checking that
* the ID's type is the same as the ID type supplied as an argument
*
* Return: Success: A pointer to the object that was removed, the
* same pointer which would have been found by
* calling H5I_object().
* Failure: NULL
*
* Programmer: James Laird
* Nat Furrer
*
*-------------------------------------------------------------------------
*/
void *
H5I__remove_verify(hid_t id, H5I_type_t type)
{
void *ret_value = NULL; /*return value */
FUNC_ENTER_PACKAGE_NOERR
/* Argument checking will be performed by H5I_remove() */
/* Verify that the type of the ID is correct */
if (type == H5I_TYPE(id))
ret_value = H5I_remove(id);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I__remove_verify() */
/*-------------------------------------------------------------------------
* Function: H5I__remove_common
*
* Purpose: Common code to remove a specified ID from its type.
*
* Return: Success: A pointer to the object that was removed, the
* same pointer which would have been found by
* calling H5I_object().
* Failure: NULL
*
* Programmer: Quincey Koziol
* October 3, 2013
*
*-------------------------------------------------------------------------
*/
static void *
H5I__remove_common(H5I_type_info_t *type_info, hid_t id)
{
H5I_id_info_t *info = NULL; /* Pointer to the current ID */
void *ret_value = NULL; /* Return value */
FUNC_ENTER_PACKAGE
/* Sanity check */
HDassert(type_info);
/* Delete or mark the node */
HASH_FIND(hh, type_info->hash_table, &id, sizeof(hid_t), info);
if (info) {
HDassert(!info->marked);
if (!H5I_marking_g)
HASH_DELETE(hh, type_info->hash_table, info);
else
info->marked = TRUE;
}
else
HGOTO_ERROR(H5E_ID, H5E_CANTDELETE, NULL, "can't remove ID node from hash table")
/* Check if this ID was the last one accessed */
if (type_info->last_id_info == info)
type_info->last_id_info = NULL;
H5_GCC_CLANG_DIAG_OFF("cast-qual")
ret_value = (void *)info->object;
H5_GCC_CLANG_DIAG_ON("cast-qual")
if (!H5I_marking_g)
info = H5FL_FREE(H5I_id_info_t, info);
/* Decrement the number of IDs in the type */
(type_info->id_count)--;
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I__remove_common() */
/*-------------------------------------------------------------------------
* Function: H5I_remove
*
* Purpose: Removes the specified ID from its type.
*
* Return: Success: A pointer to the object that was removed, the
* same pointer which would have been found by
* calling H5I_object().
* Failure: NULL
*
*-------------------------------------------------------------------------
*/
void *
H5I_remove(hid_t id)
{
H5I_type_info_t *type_info = NULL; /* Pointer to the ID type */
H5I_type_t type = H5I_BADID; /* ID's type */
void *ret_value = NULL; /* Return value */
FUNC_ENTER_NOAPI(NULL)
/* Check arguments */
type = H5I_TYPE(id);
if (type <= H5I_BADID || (int)type >= H5I_next_type_g)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "invalid type number")
type_info = H5I_type_info_array_g[type];
if (type_info == NULL || type_info->init_count <= 0)
HGOTO_ERROR(H5E_ID, H5E_BADGROUP, NULL, "invalid type")
/* Remove the node from the type */
if (NULL == (ret_value = H5I__remove_common(type_info, id)))
HGOTO_ERROR(H5E_ID, H5E_CANTDELETE, NULL, "can't remove ID node")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I_remove() */
/*-------------------------------------------------------------------------
* Function: H5I__dec_ref
*
* Purpose: This will fail if the type is not a reference counted type.
* The ID type's 'free' function will be called for the ID
* if the reference count for the ID reaches 0 and a free
* function has been defined at type creation time.
*
* Note: Allows for asynchronous 'close' operation on object, with
* request != H5_REQUEST_NULL.
*
* Return: Success: New reference count
* Failure: -1
*
*-------------------------------------------------------------------------
*/
static int
H5I__dec_ref(hid_t id, void **request)
{
H5I_id_info_t *info = NULL; /* Pointer to the ID */
int ret_value = 0; /* Return value */
FUNC_ENTER_PACKAGE
/* Sanity check */
HDassert(id >= 0);
/* General lookup of the ID */
if (NULL == (info = H5I__find_id(id)))
HGOTO_ERROR(H5E_ID, H5E_BADID, (-1), "can't locate ID")
/* If this is the last reference to the object then invoke the type's
* free method on the object. If the free method is undefined or
* successful then remove the object from the type; otherwise leave
* the object in the type without decrementing the reference
* count. If the reference count is more than one then decrement the
* reference count without calling the free method.
*
* Beware: the free method may call other H5I functions.
*
* If an object is closing, we can remove the ID even though the free
* method might fail. This can happen when a mandatory filter fails to
* write when a dataset is closed and the chunk cache is flushed to the
* file. We have to close the dataset anyway. (SLU - 2010/9/7)
*/
if (1 == info->count) {
H5I_type_info_t *type_info; /*ptr to the type */
/* Get the ID's type */
type_info = H5I_type_info_array_g[H5I_TYPE(id)];
H5_GCC_CLANG_DIAG_OFF("cast-qual")
if (!type_info->cls->free_func || (type_info->cls->free_func)((void *)info->object, request) >= 0) {
/* Remove the node from the type */
if (NULL == H5I__remove_common(type_info, id))
HGOTO_ERROR(H5E_ID, H5E_CANTDELETE, (-1), "can't remove ID node")
ret_value = 0;
} /* end if */
else
ret_value = -1;
H5_GCC_CLANG_DIAG_ON("cast-qual")
} /* end if */
else {
--(info->count);
ret_value = (int)info->count;
} /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I__dec_ref */
/*-------------------------------------------------------------------------
* Function: H5I_dec_ref
*
* Purpose: Decrements the number of references outstanding for an ID.
*
* Return: Success: New reference count
* Failure: -1
*
*-------------------------------------------------------------------------
*/
int
H5I_dec_ref(hid_t id)
{
int ret_value = 0; /* Return value */
FUNC_ENTER_NOAPI((-1))
/* Sanity check */
HDassert(id >= 0);
/* Synchronously decrement refcount on ID */
if ((ret_value = H5I__dec_ref(id, H5_REQUEST_NULL)) < 0)
HGOTO_ERROR(H5E_ID, H5E_CANTDEC, (-1), "can't decrement ID ref count")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I_dec_ref() */
/*-------------------------------------------------------------------------
* Function: H5I__dec_app_ref
*
* Purpose: Wrapper for case of modifying the application ref.
* count for an ID as well as normal reference count.
*
* Note: Allows for asynchronous 'close' operation on object, with
* request != H5_REQUEST_NULL.
*
* Return: Success: New app. reference count
* Failure: -1
*
*-------------------------------------------------------------------------
*/
static int
H5I__dec_app_ref(hid_t id, void **request)
{
int ret_value = 0; /* Return value */
FUNC_ENTER_PACKAGE
/* Sanity check */
HDassert(id >= 0);
/* Call regular decrement reference count routine */
if ((ret_value = H5I__dec_ref(id, request)) < 0)
HGOTO_ERROR(H5E_ID, H5E_CANTDEC, (-1), "can't decrement ID ref count")
/* Check if the ID still exists */
if (ret_value > 0) {
H5I_id_info_t *info = NULL; /* Pointer to the ID info */
/* General lookup of the ID */
if (NULL == (info = H5I__find_id(id)))
HGOTO_ERROR(H5E_ID, H5E_BADID, (-1), "can't locate ID")
/* Adjust app_ref */
--(info->app_count);
HDassert(info->count >= info->app_count);
/* Set return value */
ret_value = (int)info->app_count;
} /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I__dec_app_ref() */
/*-------------------------------------------------------------------------
* Function: H5I_dec_app_ref
*
* Purpose: Wrapper for case of modifying the application ref. count for
* an ID as well as normal reference count.
*
* Return: Success: New app. reference count
* Failure: -1
*
* Programmer: Quincey Koziol
* Sept 16, 2010
*
*-------------------------------------------------------------------------
*/
int
H5I_dec_app_ref(hid_t id)
{
int ret_value = 0; /* Return value */
FUNC_ENTER_NOAPI((-1))
/* Sanity check */
HDassert(id >= 0);
/* Synchronously decrement refcount on ID */
if ((ret_value = H5I__dec_app_ref(id, H5_REQUEST_NULL)) < 0)
HGOTO_ERROR(H5E_ID, H5E_CANTDEC, (-1), "can't decrement ID ref count")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I_dec_app_ref() */
/*-------------------------------------------------------------------------
* Function: H5I_dec_app_ref_async
*
* Purpose: Asynchronous wrapper for case of modifying the application ref.
* count for an ID as well as normal reference count.
*
* Note: Allows for asynchronous 'close' operation on object, with
* token != H5_REQUEST_NULL.
*
* Return: Success: New app. reference count
* Failure: -1
*
* Programmer: Houjun Tang
* Oct 21, 2019
*
*-------------------------------------------------------------------------
*/
int
H5I_dec_app_ref_async(hid_t id, void **token)
{
int ret_value = 0; /* Return value */
FUNC_ENTER_NOAPI((-1))
/* Sanity check */
HDassert(id >= 0);
/* [Possibly] aynchronously decrement refcount on ID */
if ((ret_value = H5I__dec_app_ref(id, token)) < 0)
HGOTO_ERROR(H5E_ID, H5E_CANTDEC, (-1), "can't asynchronously decrement ID ref count")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I_dec_app_ref_async() */
/*-------------------------------------------------------------------------
* Function: H5I__dec_app_ref_always_close
*
* Purpose: Wrapper for case of always closing the ID, even when the free
* routine fails
*
* Note: Allows for asynchronous 'close' operation on object, with
* request != H5_REQUEST_NULL.
*
* Return: Success: New app. reference count
* Failure: -1
*
*-------------------------------------------------------------------------
*/
static int
H5I__dec_app_ref_always_close(hid_t id, void **request)
{
int ret_value = 0; /* Return value */
FUNC_ENTER_PACKAGE
/* Sanity check */
HDassert(id >= 0);
/* Call application decrement reference count routine */
ret_value = H5I__dec_app_ref(id, request);
/* Check for failure */
if (ret_value < 0) {
/*
* If an object is closing, we can remove the ID even though the free
* method might fail. This can happen when a mandatory filter fails to
* write when a dataset is closed and the chunk cache is flushed to the
* file. We have to close the dataset anyway. (SLU - 2010/9/7)
*/
H5I_remove(id);
HGOTO_ERROR(H5E_ID, H5E_CANTDEC, (-1), "can't decrement ID ref count")
} /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I__dec_app_ref_always_close() */
/*-------------------------------------------------------------------------
* Function: H5I_dec_app_ref_always_close
*
* Purpose: Wrapper for case of always closing the ID, even when the free
* routine fails.
*
* Return: Success: New app. reference count
* Failure: -1
*
*-------------------------------------------------------------------------
*/
int
H5I_dec_app_ref_always_close(hid_t id)
{
int ret_value = 0; /* Return value */
FUNC_ENTER_NOAPI((-1))
/* Sanity check */
HDassert(id >= 0);
/* Synchronously decrement refcount on ID */
if ((ret_value = H5I__dec_app_ref_always_close(id, H5_REQUEST_NULL)) < 0)
HGOTO_ERROR(H5E_ID, H5E_CANTDEC, (-1), "can't decrement ID ref count")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I_dec_app_ref_always_close() */
/*-------------------------------------------------------------------------
* Function: H5I_dec_app_ref_always_close_async
*
* Purpose: Asynchronous wrapper for case of always closing the ID, even
* when the free routine fails
*
* Note: Allows for asynchronous 'close' operation on object, with
* token != H5_REQUEST_NULL.
*
* Return: Success: New app. reference count
* Failure: -1
*
*-------------------------------------------------------------------------
*/
int
H5I_dec_app_ref_always_close_async(hid_t id, void **token)
{
int ret_value = 0; /* Return value */
FUNC_ENTER_NOAPI((-1))
/* Sanity check */
HDassert(id >= 0);
/* [Possibly] aynchronously decrement refcount on ID */
if ((ret_value = H5I__dec_app_ref_always_close(id, token)) < 0)
HGOTO_ERROR(H5E_ID, H5E_CANTDEC, (-1), "can't asynchronously decrement ID ref count")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I_dec_app_ref_always_close_async() */
/*-------------------------------------------------------------------------
* Function: H5I_inc_ref
*
* Purpose: Increment the reference count for an object.
*
* Return: Success: The new reference count
* Failure: -1
*
*-------------------------------------------------------------------------
*/
int
H5I_inc_ref(hid_t id, hbool_t app_ref)
{
H5I_id_info_t *info = NULL; /* Pointer to the ID info */
int ret_value = 0; /* Return value */
FUNC_ENTER_NOAPI((-1))
/* Sanity check */
HDassert(id >= 0);
/* General lookup of the ID */
if (NULL == (info = H5I__find_id(id)))
HGOTO_ERROR(H5E_ID, H5E_BADID, (-1), "can't locate ID")
/* Adjust reference counts */
++(info->count);
if (app_ref)
++(info->app_count);
/* Set return value */
ret_value = (int)(app_ref ? info->app_count : info->count);
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I_inc_ref() */
/*-------------------------------------------------------------------------
* Function: H5I_get_ref
*
* Purpose: Retrieve the reference count for an object.
*
* Return: Success: The reference count
* Failure: -1
*
*-------------------------------------------------------------------------
*/
int
H5I_get_ref(hid_t id, hbool_t app_ref)
{
H5I_id_info_t *info = NULL; /* Pointer to the ID */
int ret_value = 0; /* Return value */
FUNC_ENTER_NOAPI((-1))
/* Sanity check */
HDassert(id >= 0);
/* General lookup of the ID */
if (NULL == (info = H5I__find_id(id)))
HGOTO_ERROR(H5E_ID, H5E_BADID, (-1), "can't locate ID")
/* Set return value */
ret_value = (int)(app_ref ? info->app_count : info->count);
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I_get_ref() */
/*-------------------------------------------------------------------------
* Function: H5I__inc_type_ref
*
* Purpose: Increment the reference count for an ID type.
*
* Return: Success: The new reference count
* Failure: -1
*
*-------------------------------------------------------------------------
*/
int
H5I__inc_type_ref(H5I_type_t type)
{
H5I_type_info_t *type_info = NULL; /* Pointer to the type */
int ret_value = -1; /* Return value */
FUNC_ENTER_PACKAGE
/* Sanity check */
HDassert(type > 0 && (int)type < H5I_next_type_g);
/* Check arguments */
type_info = H5I_type_info_array_g[type];
if (NULL == type_info)
HGOTO_ERROR(H5E_ID, H5E_BADGROUP, (-1), "invalid type")
/* Set return value */
ret_value = (int)(++(type_info->init_count));
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I__inc_type_ref() */
/*-------------------------------------------------------------------------
* Function: H5I_dec_type_ref
*
* Purpose: Decrements the reference count on an entire type of IDs.
* If the type reference count becomes zero then the type is
* destroyed along with all IDs in that type regardless of
* their reference counts. Destroying IDs involves calling
* the free-func for each ID's object and then adding the ID
* struct to the ID free list.
* Returns the number of references to the type on success; a
* return value of 0 means that the type will have to be
* re-initialized before it can be used again (and should probably
* be set to H5I_UNINIT).
*
* Return: Success: Number of references to type
* Failure: -1
*
*-------------------------------------------------------------------------
*/
int
H5I_dec_type_ref(H5I_type_t type)
{
H5I_type_info_t *type_info = NULL; /* Pointer to the ID type */
herr_t ret_value = 0; /* Return value */
FUNC_ENTER_NOAPI((-1))
if (type <= H5I_BADID || (int)type >= H5I_next_type_g)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, (-1), "invalid type number")
type_info = H5I_type_info_array_g[type];
if (type_info == NULL || type_info->init_count <= 0)
HGOTO_ERROR(H5E_ID, H5E_BADGROUP, (-1), "invalid type")
/* Decrement the number of users of the ID type. If this is the
* last user of the type then release all IDs from the type and
* free all memory it used. The free function is invoked for each ID
* being freed.
*/
if (1 == type_info->init_count) {
H5I__destroy_type(type);
ret_value = 0;
}
else {
--(type_info->init_count);
ret_value = (herr_t)type_info->init_count;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I_dec_type_ref() */
/*-------------------------------------------------------------------------
* Function: H5I__get_type_ref
*
* Purpose: Retrieve the reference count for an ID type.
*
* Return: Success: The reference count
*
* Failure: -1
*
*-------------------------------------------------------------------------
*/
int
H5I__get_type_ref(H5I_type_t type)
{
H5I_type_info_t *type_info = NULL; /* Pointer to the type */
int ret_value = -1; /* Return value */
FUNC_ENTER_PACKAGE
/* Sanity check */
HDassert(type >= 0);
/* Check arguments */
type_info = H5I_type_info_array_g[type];
if (!type_info)
HGOTO_ERROR(H5E_ID, H5E_BADGROUP, (-1), "invalid type")
/* Set return value */
ret_value = (int)type_info->init_count;
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I__get_type_ref() */
/*-------------------------------------------------------------------------
* Function: H5I__iterate_cb
*
* Purpose: Callback routine for H5I_iterate, invokes "user" callback
* function, and then sets return value, based on the result of
* that callback.
*
* Return: Success: H5_ITER_CONT (0) or H5_ITER_STOP (1)
* Failure: H5_ITER_ERROR (-1)
*
*-------------------------------------------------------------------------
*/
static int
H5I__iterate_cb(void *_item, void H5_ATTR_UNUSED *_key, void *_udata)
{
H5I_id_info_t *info = (H5I_id_info_t *)_item; /* Pointer to the ID info */
H5I_iterate_ud_t *udata = (H5I_iterate_ud_t *)_udata; /* User data for callback */
int ret_value = H5_ITER_CONT; /* Callback return value */
FUNC_ENTER_PACKAGE_NOERR
/* Only invoke the callback function if this ID is visible externally and
* its reference count is positive.
*/
if ((!udata->app_ref) || (info->app_count > 0)) {
H5I_type_t type = udata->obj_type;
void *object;
herr_t cb_ret_val;
/* The stored object pointer might be an H5VL_object_t, in which
* case we'll need to get the wrapped object struct (H5F_t *, etc.).
*/
H5_GCC_CLANG_DIAG_OFF("cast-qual")
object = H5I__unwrap((void *)info->object, type);
H5_GCC_CLANG_DIAG_ON("cast-qual")
/* Invoke callback function */
cb_ret_val = (*udata->user_func)((void *)object, info->id, udata->user_udata);
/* Set the return value based on the callback's return value */
if (cb_ret_val > 0)
ret_value = H5_ITER_STOP; /* terminate iteration early */
else if (cb_ret_val < 0)
ret_value = H5_ITER_ERROR; /* indicate failure (which terminates iteration) */
}
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I__iterate_cb() */
/*-------------------------------------------------------------------------
* Function: H5I_iterate
*
* Purpose: Apply function FUNC to each member of type TYPE (with
* non-zero application reference count if app_ref is TRUE).
* Stop if FUNC returns a non zero value (i.e. anything
* other than H5_ITER_CONT).
*
* If FUNC returns a positive value (i.e. H5_ITER_STOP),
* return SUCCEED.
*
* If FUNC returns a negative value (i.e. H5_ITER_ERROR),
* return FAIL.
*
* The FUNC should take a pointer to the object and the
* udata as arguments and return non-zero to terminate
* siteration, and zero to continue.
*
* Limitation: Currently there is no way to start the iteration from
* where a previous iteration left off.
*
* Return: SUCCEED/FAIL
*
*-------------------------------------------------------------------------
*/
herr_t
H5I_iterate(H5I_type_t type, H5I_search_func_t func, void *udata, hbool_t app_ref)
{
H5I_type_info_t *type_info = NULL; /* Pointer to the type */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/* Check arguments */
if (type <= H5I_BADID || (int)type >= H5I_next_type_g)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
type_info = H5I_type_info_array_g[type];
/* Only iterate through ID list if it is initialized and there are IDs in type */
if (type_info && type_info->init_count > 0 && type_info->id_count > 0) {
H5I_iterate_ud_t iter_udata; /* User data for iteration callback */
H5I_id_info_t *item = NULL;
H5I_id_info_t *tmp = NULL;
/* Set up iterator user data */
iter_udata.user_func = func;
iter_udata.user_udata = udata;
iter_udata.app_ref = app_ref;
iter_udata.obj_type = type;
/* Iterate over IDs */
HASH_ITER(hh, type_info->hash_table, item, tmp)
{
if (!item->marked) {
int ret = H5I__iterate_cb((void *)item, NULL, (void *)&iter_udata);
if (H5_ITER_ERROR == ret)
HGOTO_ERROR(H5E_ID, H5E_BADITER, FAIL, "iteration failed")
if (H5_ITER_STOP == ret)
break;
}
}
}
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I_iterate() */
/*-------------------------------------------------------------------------
* Function: H5I__find_id
*
* Purpose: Given an object ID find the info struct that describes the
* object.
*
* Return: Success: A pointer to the object's info struct.
*
* Failure: NULL
*
*-------------------------------------------------------------------------
*/
H5I_id_info_t *
H5I__find_id(hid_t id)
{
H5I_type_t type; /* ID's type */
H5I_type_info_t *type_info = NULL; /* Pointer to the type */
H5I_id_info_t *id_info = NULL; /* ID's info */
H5I_id_info_t *ret_value = NULL; /* Return value */
FUNC_ENTER_PACKAGE_NOERR
/* Check arguments */
type = H5I_TYPE(id);
if (type <= H5I_BADID || (int)type >= H5I_next_type_g)
HGOTO_DONE(NULL)
type_info = H5I_type_info_array_g[type];
if (!type_info || type_info->init_count <= 0)
HGOTO_DONE(NULL)
/* Check for same ID as we have looked up last time */
if (type_info->last_id_info && type_info->last_id_info->id == id)
id_info = type_info->last_id_info;
else {
HASH_FIND(hh, type_info->hash_table, &id, sizeof(hid_t), id_info);
/* Remember this ID */
type_info->last_id_info = id_info;
}
/* Check if this is a future ID */
H5_GCC_CLANG_DIAG_OFF("cast-qual")
if (id_info && id_info->is_future) {
hid_t actual_id = H5I_INVALID_HID; /* ID for actual object */
void *future_object; /* Pointer to the future object */
void *actual_object; /* Pointer to the actual object */
/* Invoke the realize callback, to get the actual object */
if ((id_info->realize_cb)((void *)id_info->object, &actual_id) < 0)
HGOTO_DONE(NULL)
/* Verify that we received a valid ID, of the same type */
if (H5I_INVALID_HID == actual_id)
HGOTO_DONE(NULL)
if (H5I_TYPE(id) != H5I_TYPE(actual_id))
HGOTO_DONE(NULL)
/* Swap the actual object in for the future object */
future_object = (void *)id_info->object;
actual_object = H5I__remove_common(type_info, actual_id);
HDassert(actual_object);
id_info->object = actual_object;
/* Discard the future object */
if ((id_info->discard_cb)(future_object) < 0)
HGOTO_DONE(NULL)
future_object = NULL;
/* Change the ID from 'future' to 'actual' */
id_info->is_future = FALSE;
id_info->realize_cb = NULL;
id_info->discard_cb = NULL;
}
H5_GCC_CLANG_DIAG_ON("cast-qual")
/* Set return value */
ret_value = id_info;
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I__find_id() */
/*-------------------------------------------------------------------------
* Function: H5I__find_id_cb
*
* Purpose: Callback for searching for an ID with a specific pointer
*
* Return: Success: H5_ITER_CONT (0) or H5_ITER_STOP (1)
* Failure: H5_ITER_ERROR (-1)
*
*-------------------------------------------------------------------------
*/
static int
H5I__find_id_cb(void *_item, void H5_ATTR_UNUSED *_key, void *_udata)
{
H5I_id_info_t *info = (H5I_id_info_t *)_item; /* Pointer to the ID info */
H5I_get_id_ud_t *udata = (H5I_get_id_ud_t *)_udata; /* Pointer to user data */
H5I_type_t type = udata->obj_type;
const void *object = NULL;
int ret_value = H5_ITER_CONT; /* Return value */
FUNC_ENTER_PACKAGE_NOERR
/* Sanity check */
HDassert(info);
HDassert(udata);
/* Get a pointer to the VOL connector's data */
H5_GCC_CLANG_DIAG_OFF("cast-qual")
object = H5I__unwrap((void *)info->object, type);
H5_GCC_CLANG_DIAG_ON("cast-qual")
/* Check for a match */
if (object == udata->object) {
udata->ret_id = info->id;
ret_value = H5_ITER_STOP;
}
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I__find_id_cb() */
/*-------------------------------------------------------------------------
* Function: H5I_find_id
*
* Purpose: Return the ID of an object by searching through the ID list
* for the type.
*
* Return: SUCCEED/FAIL
* (id will be set to H5I_INVALID_HID on errors or not found)
*
*-------------------------------------------------------------------------
*/
herr_t
H5I_find_id(const void *object, H5I_type_t type, hid_t *id)
{
H5I_type_info_t *type_info = NULL; /* Pointer to the type */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
HDassert(id);
*id = H5I_INVALID_HID;
type_info = H5I_type_info_array_g[type];
if (!type_info || type_info->init_count <= 0)
HGOTO_ERROR(H5E_ID, H5E_BADGROUP, FAIL, "invalid type")
/* Only iterate through ID list if it is initialized and there are IDs in type */
if (type_info->init_count > 0 && type_info->id_count > 0) {
H5I_get_id_ud_t udata; /* User data */
H5I_id_info_t *item = NULL;
H5I_id_info_t *tmp = NULL;
/* Set up iterator user data */
udata.object = object;
udata.obj_type = type;
udata.ret_id = H5I_INVALID_HID;
/* Iterate over IDs for the ID type */
HASH_ITER(hh, type_info->hash_table, item, tmp)
{
int ret = H5I__find_id_cb((void *)item, NULL, (void *)&udata);
if (H5_ITER_ERROR == ret)
HGOTO_ERROR(H5E_ID, H5E_BADITER, FAIL, "iteration failed")
if (H5_ITER_STOP == ret)
break;
}
*id = udata.ret_id;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I_find_id() */
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。