#include "H5Imodule.h"
#define H5T_FRIEND
#include "H5private.h"
#include "H5ACprivate.h"
#include "H5CXprivate.h"
#include "H5Dprivate.h"
#include "H5Eprivate.h"
#include "H5FLprivate.h"
#include "H5Gprivate.h"
#include "H5Ipkg.h"
#include "H5MMprivate.h"
#include "H5Oprivate.h"
#include "H5SLprivate.h"
#include "H5Tpkg.h"
#define H5I_MAKE(g,i) ((((hid_t)(g) & TYPE_MASK) << ID_BITS) | \
((hid_t)(i) & ID_MASK))
typedef struct H5I_id_info_t {
hid_t id;
unsigned count;
unsigned app_count;
const void *obj_ptr;
} H5I_id_info_t;
typedef struct {
const H5I_class_t *cls;
unsigned init_count;
uint64_t id_count;
uint64_t nextid;
H5SL_t *ids;
} H5I_id_type_t;
typedef struct {
H5I_search_func_t app_cb;
void *app_key;
void *ret_obj;
} H5I_search_ud_t;
typedef struct {
H5I_search_func_t user_func;
void *user_udata;
hbool_t app_ref;
} H5I_iterate_ud_t;
typedef struct {
H5I_id_type_t *type_ptr;
hbool_t force;
hbool_t app_ref;
} H5I_clear_type_ud_t;
hbool_t H5_PKG_INIT_VAR = FALSE;
static H5I_id_type_t *H5I_id_type_list_g[H5I_MAX_NUM_TYPES];
static int H5I_next_type = (int)H5I_NTYPES;
H5FL_DEFINE_STATIC(H5I_id_info_t);
H5FL_DEFINE_STATIC(H5I_id_type_t);
H5FL_DEFINE_STATIC(H5I_class_t);
static htri_t H5I__clear_type_cb(void *_id, void *key, void *udata);
static int H5I__destroy_type(H5I_type_t type);
static void *H5I__remove_verify(hid_t id, H5I_type_t id_type);
static void *H5I__remove_common(H5I_id_type_t *type_ptr, hid_t id);
static int H5I__inc_type_ref(H5I_type_t type);
static int H5I__get_type_ref(H5I_type_t type);
static int H5I__search_cb(void *obj, hid_t id, void *_udata);
static H5I_id_info_t *H5I__find_id(hid_t id);
static int H5I__debug_cb(void *_item, void *_key, void *_udata);
static int H5I__id_dump_cb(void *_item, void *_key, void *_udata);
int
H5I_term_package(void)
{
int n = 0;
FUNC_ENTER_NOAPI_NOINIT_NOERR
if(H5_PKG_INIT_VAR) {
H5I_id_type_t *type_ptr;
int type;
for(type = 0; type < H5I_next_type; type++)
if((type_ptr = H5I_id_type_list_g[type]) && type_ptr->ids)
n++;
if(0 == n) {
for(type = 0; type < H5I_next_type; type++) {
type_ptr = H5I_id_type_list_g[type];
if(type_ptr) {
HDassert(NULL == type_ptr->ids);
type_ptr = H5FL_FREE(H5I_id_type_t, type_ptr);
H5I_id_type_list_g[type] = NULL;
n++;
}
}
if(0 == n)
H5_PKG_INIT_VAR = FALSE;
}
}
FUNC_LEAVE_NOAPI(n)
}
H5I_type_t
H5Iregister_type(size_t H5_ATTR_DEBUG_API_USED hash_size, unsigned reserved,
H5I_free_t free_func)
{
H5I_class_t *cls = NULL;
H5I_type_t new_type;
H5I_type_t ret_value = H5I_BADID;
FUNC_ENTER_API(H5I_BADID)
H5TRACE3("It", "zIux", hash_size, reserved, free_func);
if(H5I_next_type < H5I_MAX_NUM_TYPES) {
new_type = (H5I_type_t)H5I_next_type;
H5I_next_type++;
}
else {
hbool_t done;
int i;
done = FALSE;
for(i = H5I_NTYPES; i < H5I_MAX_NUM_TYPES && done == FALSE; i++) {
if(NULL == H5I_id_type_list_g[i]) {
new_type = (H5I_type_t)i;
done = TRUE;
}
}
if(done == FALSE)
HGOTO_ERROR(H5E_ATOM, H5E_NOSPACE, H5I_BADID, "Maximum number of ID types exceeded")
}
if(NULL == (cls = H5FL_CALLOC(H5I_class_t)))
HGOTO_ERROR(H5E_ATOM, H5E_CANTALLOC, H5I_BADID, "ID class allocation failed")
cls->type_id = new_type;
cls->flags = H5I_CLASS_IS_APPLICATION;
cls->reserved = reserved;
cls->free_func = free_func;
if(H5I_register_type(cls) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTINIT, H5I_BADID, "can't initialize ID class")
ret_value = new_type;
done:
if(ret_value < 0)
if(cls)
cls = H5FL_FREE(H5I_class_t, cls);
FUNC_LEAVE_API(ret_value)
}
herr_t
H5I_register_type(const H5I_class_t *cls)
{
H5I_id_type_t *type_ptr = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(cls);
HDassert(cls->type_id > 0 && (int)cls->type_id < H5I_MAX_NUM_TYPES);
if(NULL == H5I_id_type_list_g[cls->type_id]) {
if(NULL == (type_ptr = (H5I_id_type_t *)H5FL_CALLOC(H5I_id_type_t)))
HGOTO_ERROR(H5E_ATOM, H5E_CANTALLOC, FAIL, "ID type allocation failed")
H5I_id_type_list_g[cls->type_id] = type_ptr;
}
else {
type_ptr = H5I_id_type_list_g[cls->type_id];
}
if(type_ptr->init_count == 0) {
type_ptr->cls = cls;
type_ptr->id_count = 0;
type_ptr->nextid = cls->reserved;
if(NULL == (type_ptr->ids = H5SL_create(H5SL_TYPE_HID, NULL)))
HGOTO_ERROR(H5E_ATOM, H5E_CANTCREATE, FAIL, "skip list creation failed")
}
type_ptr->init_count++;
done:
if(ret_value < 0) {
if(type_ptr) {
if(type_ptr->ids)
H5SL_close(type_ptr->ids);
(void)H5FL_FREE(H5I_id_type_t, type_ptr);
}
}
FUNC_LEAVE_NOAPI(ret_value)
}
htri_t
H5Itype_exists(H5I_type_t type)
{
htri_t ret_value = TRUE;
FUNC_ENTER_API(FAIL)
H5TRACE1("t", "It", type);
if(H5I_IS_LIB_TYPE(type))
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type")
if(type <= H5I_BADID || (int)type >= H5I_next_type)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
if(NULL == H5I_id_type_list_g[type])
ret_value = FALSE;
done:
FUNC_LEAVE_API(ret_value)
}
herr_t
H5Inmembers(H5I_type_t type, hsize_t *num_members)
{
int ret_value = SUCCEED;
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "It*h", type, num_members);
if(H5I_IS_LIB_TYPE(type))
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type")
if(type <= H5I_BADID || (int)type >= H5I_next_type)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
if(NULL == H5I_id_type_list_g[type])
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "supplied type does not exist")
if(num_members) {
int64_t members;
if((members = H5I_nmembers(type)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTCOUNT, FAIL, "can't compute number of members")
H5_CHECKED_ASSIGN(*num_members, hsize_t, members, int64_t);
}
done:
FUNC_LEAVE_API(ret_value)
}
int64_t
H5I_nmembers(H5I_type_t type)
{
H5I_id_type_t *type_ptr;
int64_t ret_value = 0;
FUNC_ENTER_NOAPI(FAIL)
if(type <= H5I_BADID || (int)type >= H5I_next_type)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
if(NULL == (type_ptr = H5I_id_type_list_g[type]) || type_ptr->init_count <= 0)
HGOTO_DONE(0);
H5_CHECKED_ASSIGN(ret_value, int64_t, type_ptr->id_count, uint64_t);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5Iclear_type(H5I_type_t type, hbool_t force)
{
herr_t ret_value = FAIL;
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "Itb", type, force);
if(H5I_IS_LIB_TYPE(type))
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type")
ret_value = H5I_clear_type(type, force, TRUE);
done:
FUNC_LEAVE_API(ret_value)
}
herr_t
H5I_clear_type(H5I_type_t type, hbool_t force, hbool_t app_ref)
{
H5I_clear_type_ud_t udata;
int ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
if(type <= H5I_BADID || (int)type >= H5I_next_type)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
udata.type_ptr = H5I_id_type_list_g[type];
if(udata.type_ptr == NULL || udata.type_ptr->init_count <= 0)
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type")
udata.force = force;
udata.app_ref = app_ref;
if(H5SL_try_free_safe(udata.type_ptr->ids, H5I__clear_type_cb, &udata) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTDELETE, FAIL, "can't free ids in type")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static htri_t
H5I__clear_type_cb(void *_id, void H5_ATTR_UNUSED *key, void *_udata)
{
H5I_id_info_t *id = (H5I_id_info_t *)_id;
H5I_clear_type_ud_t *udata = (H5I_clear_type_ud_t *)_udata;
htri_t ret_value = FALSE;
FUNC_ENTER_STATIC_NOERR
HDassert(id);
HDassert(udata);
HDassert(udata->type_ptr);
if(udata->force || (id->count - (!udata->app_ref * id->app_count)) <= 1) {
if(udata->type_ptr->cls->free_func && (udata->type_ptr->cls->free_func)((void *)id->obj_ptr) < 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_ptr->cls->type_id,
(unsigned long)(id->obj_ptr));
}
#endif
ret_value = TRUE;
}
}
else {
ret_value = TRUE;
}
if(ret_value) {
id = H5FL_FREE(H5I_id_info_t, id);
udata->type_ptr->id_count--;
}
}
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5Idestroy_type(H5I_type_t type)
{
herr_t ret_value = FAIL;
FUNC_ENTER_API(FAIL)
H5TRACE1("e", "It", type);
if(H5I_IS_LIB_TYPE(type))
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type")
ret_value = H5I__destroy_type(type);
done:
FUNC_LEAVE_API(ret_value)
}
static herr_t
H5I__destroy_type(H5I_type_t type)
{
H5I_id_type_t *type_ptr;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
if(type <= H5I_BADID || (int)type >= H5I_next_type)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
type_ptr = H5I_id_type_list_g[type];
if(type_ptr == NULL || type_ptr->init_count <= 0)
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type")
H5E_BEGIN_TRY {
H5I_clear_type(type, TRUE, FALSE);
} H5E_END_TRY
if(type_ptr->cls->flags & H5I_CLASS_IS_APPLICATION)
type_ptr->cls = H5FL_FREE(H5I_class_t, (void *)type_ptr->cls);
if(H5SL_close(type_ptr->ids) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTCLOSEOBJ, FAIL, "can't close skip list")
type_ptr->ids = NULL;
type_ptr = H5FL_FREE(H5I_id_type_t, type_ptr);
H5I_id_type_list_g[type] = NULL;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
hid_t
H5Iregister(H5I_type_t type, const void *object)
{
hid_t ret_value = H5I_INVALID_HID;
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE2("i", "It*x", type, object);
if(H5I_IS_LIB_TYPE(type))
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type")
ret_value = H5I_register(type, object, TRUE);
done:
FUNC_LEAVE_API(ret_value)
}
hid_t
H5I_register(H5I_type_t type, const void *object, hbool_t app_ref)
{
H5I_id_type_t *type_ptr = NULL;
H5I_id_info_t *id_ptr = NULL;
hid_t new_id = -1;
hid_t ret_value = H5I_INVALID_HID;
FUNC_ENTER_NOAPI(FAIL)
if (type <= H5I_BADID || (int)type >= H5I_next_type)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, H5I_INVALID_HID, "invalid type number")
type_ptr = H5I_id_type_list_g[type];
if ((NULL == type_ptr) || (type_ptr->init_count <= 0))
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, H5I_INVALID_HID, "invalid type")
if (NULL == (id_ptr = H5FL_MALLOC(H5I_id_info_t)))
HGOTO_ERROR(H5E_ATOM, H5E_NOSPACE, H5I_INVALID_HID, "memory allocation failed")
new_id = H5I_MAKE(type, type_ptr->nextid);
id_ptr->id = new_id;
id_ptr->count = 1;
id_ptr->app_count = !!app_ref;
id_ptr->obj_ptr = object;
if (H5SL_insert(type_ptr->ids, id_ptr, &id_ptr->id) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTINSERT, H5I_INVALID_HID, "can't insert ID node into skip list")
type_ptr->id_count++;
type_ptr->nextid++;
HDassert(type_ptr->nextid <= ID_MASK);
ret_value = new_id;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5I_register_using_existing_id(H5I_type_t type, void *object, hbool_t app_ref, hid_t existing_id)
{
H5I_id_type_t *type_ptr;
H5I_id_info_t *id_ptr;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(object);
if(NULL != (id_ptr = H5I__find_id(existing_id)))
HGOTO_ERROR(H5E_ATOM, H5E_BADRANGE, FAIL, "ID already in use")
if(type <= H5I_BADID || (int)type >= H5I_next_type)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
type_ptr = H5I_id_type_list_g[type];
if(NULL == type_ptr || type_ptr->init_count <= 0)
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type")
if(H5I_TYPE(existing_id) != type)
HGOTO_ERROR(H5E_ATOM, H5E_BADRANGE, FAIL, "invalid type for provided ID")
if(NULL == (id_ptr = H5FL_MALLOC(H5I_id_info_t)))
HGOTO_ERROR(H5E_ATOM, H5E_NOSPACE, FAIL, "memory allocation failed")
id_ptr->id = existing_id;
id_ptr->count = 1;
id_ptr->app_count = !!app_ref;
id_ptr->obj_ptr = object;
if(H5SL_insert(type_ptr->ids, id_ptr, &id_ptr->id) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTINSERT, FAIL, "can't insert ID node into skip list")
type_ptr->id_count++;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
void *
H5I_subst(hid_t id, const void *new_object)
{
H5I_id_info_t *id_ptr;
void *ret_value = NULL;
FUNC_ENTER_NOAPI(NULL)
if(NULL == (id_ptr = H5I__find_id(id)))
HGOTO_ERROR(H5E_ATOM, H5E_NOTFOUND, NULL, "can't get ID ref count")
ret_value = (void *)id_ptr->obj_ptr;
id_ptr->obj_ptr = new_object;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
void *
H5I_object(hid_t id)
{
H5I_id_info_t *id_ptr;
void *ret_value = NULL;
FUNC_ENTER_NOAPI_NOERR
if(NULL != (id_ptr = H5I__find_id(id))) {
ret_value = (void *)id_ptr->obj_ptr;
}
FUNC_LEAVE_NOAPI(ret_value)
}
void *
H5Iobject_verify(hid_t id, H5I_type_t id_type)
{
void *ret_value = NULL;
FUNC_ENTER_API(NULL)
H5TRACE2("*x", "iIt", id, id_type);
if(H5I_IS_LIB_TYPE(id_type))
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "cannot call public function on library type")
if(id_type < 1 || (int)id_type >= H5I_next_type)
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "identifier has invalid type")
ret_value = H5I_object_verify(id, id_type);
done:
FUNC_LEAVE_API(ret_value)
}
void *
H5I_object_verify(hid_t id, H5I_type_t id_type)
{
H5I_id_info_t *id_ptr = NULL;
void *ret_value = NULL;
FUNC_ENTER_NOAPI_NOERR
HDassert(id_type >= 1 && (int)id_type < H5I_next_type);
if(id_type == H5I_TYPE(id) && NULL != (id_ptr = H5I__find_id(id))) {
ret_value = (void *)id_ptr->obj_ptr;
}
FUNC_LEAVE_NOAPI(ret_value)
}
H5I_type_t
H5I_get_type(hid_t id)
{
H5I_type_t ret_value = H5I_BADID;
FUNC_ENTER_NOAPI_NOERR
if(id > 0)
ret_value = H5I_TYPE(id);
HDassert(ret_value >= H5I_BADID && (int)ret_value < H5I_next_type);
FUNC_LEAVE_NOAPI(ret_value)
}
H5I_type_t
H5Iget_type(hid_t id)
{
H5I_type_t ret_value = H5I_BADID;
FUNC_ENTER_API(H5I_BADID)
H5TRACE1("It", "i", id);
ret_value = H5I_get_type(id);
if(ret_value <= H5I_BADID || (int)ret_value >= H5I_next_type || NULL == H5I_object(id))
HGOTO_DONE(H5I_BADID);
done:
FUNC_LEAVE_API(ret_value)
}
void *
H5Iremove_verify(hid_t id, H5I_type_t id_type)
{
void *ret_value = NULL;
FUNC_ENTER_API(NULL)
H5TRACE2("*x", "iIt", id, id_type);
if(H5I_IS_LIB_TYPE(id_type))
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "cannot call public function on library type")
ret_value = H5I__remove_verify(id, id_type);
done:
FUNC_LEAVE_API(ret_value)
}
static void *
H5I__remove_verify(hid_t id, H5I_type_t id_type)
{
void * ret_value = NULL;
FUNC_ENTER_STATIC_NOERR
if(id_type == H5I_TYPE(id))
ret_value = H5I_remove(id);
FUNC_LEAVE_NOAPI(ret_value)
}
static void *
H5I__remove_common(H5I_id_type_t *type_ptr, hid_t id)
{
H5I_id_info_t *curr_id;
void *ret_value = NULL;
FUNC_ENTER_STATIC
HDassert(type_ptr);
if(NULL == (curr_id = (H5I_id_info_t *)H5SL_remove(type_ptr->ids, &id)))
HGOTO_ERROR(H5E_ATOM, H5E_CANTDELETE, NULL, "can't remove ID node from skip list")
ret_value = (void *)curr_id->obj_ptr;
curr_id = H5FL_FREE(H5I_id_info_t, curr_id);
(type_ptr->id_count)--;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
void *
H5I_remove(hid_t id)
{
H5I_id_type_t *type_ptr;
H5I_type_t type;
void * ret_value = NULL;
FUNC_ENTER_NOAPI(NULL)
type = H5I_TYPE(id);
if(type <= H5I_BADID || (int)type >= H5I_next_type)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "invalid type number")
type_ptr = H5I_id_type_list_g[type];
if(type_ptr == NULL || type_ptr->init_count <= 0)
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "invalid type")
if(NULL == (ret_value = H5I__remove_common(type_ptr, id)))
HGOTO_ERROR(H5E_ATOM, H5E_CANTDELETE, NULL, "can't remove ID node")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
int
H5Idec_ref(hid_t id)
{
int ret_value = 0;
FUNC_ENTER_API((-1))
H5TRACE1("Is", "i", id);
if(id < 0)
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, (-1), "invalid ID")
if((ret_value = H5I_dec_app_ref(id)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTDEC, (-1), "can't decrement ID ref count")
done:
FUNC_LEAVE_API(ret_value)
}
int
H5I_dec_ref(hid_t id)
{
H5I_id_info_t *id_ptr;
int ret_value = 0;
FUNC_ENTER_NOAPI((-1))
HDassert(id >= 0);
if(NULL == (id_ptr = H5I__find_id(id)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, (-1), "can't locate ID")
if(1 == id_ptr->count) {
H5I_id_type_t *type_ptr;
type_ptr = H5I_id_type_list_g[H5I_TYPE(id)];
if(!type_ptr->cls->free_func || (type_ptr->cls->free_func)((void *)id_ptr->obj_ptr) >= 0) {
if(NULL == H5I__remove_common(type_ptr, id))
HGOTO_ERROR(H5E_ATOM, H5E_CANTDELETE, (-1), "can't remove ID node")
ret_value = 0;
}
else
ret_value = -1;
}
else {
--(id_ptr->count);
ret_value = (int)id_ptr->count;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
int
H5I_dec_app_ref(hid_t id)
{
H5I_id_info_t *id_ptr;
int ret_value = 0;
FUNC_ENTER_NOAPI((-1))
HDassert(id >= 0);
if((ret_value = H5I_dec_ref(id)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTDEC, (-1), "can't decrement ID ref count")
if(ret_value > 0) {
if(NULL == (id_ptr = H5I__find_id(id)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, (-1), "can't locate ID")
--(id_ptr->app_count);
HDassert(id_ptr->count >= id_ptr->app_count);
ret_value = (int)id_ptr->app_count;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
int
H5I_dec_app_ref_always_close(hid_t id)
{
int ret_value = 0;
FUNC_ENTER_NOAPI((-1))
HDassert(id >= 0);
ret_value = H5I_dec_app_ref(id);
if (ret_value < 0) {
H5I_remove(id);
HGOTO_ERROR(H5E_ATOM, H5E_CANTDEC, (-1), "can't decrement ID ref count")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
int
H5Iinc_ref(hid_t id)
{
int ret_value;
FUNC_ENTER_API((-1))
H5TRACE1("Is", "i", id);
if (id < 0)
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, (-1), "invalid ID")
if ((ret_value = H5I_inc_ref(id, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTINC, (-1), "can't increment ID ref count")
done:
FUNC_LEAVE_API(ret_value)
}
int
H5I_inc_ref(hid_t id, hbool_t app_ref)
{
H5I_id_info_t *id_ptr;
int ret_value = 0;
FUNC_ENTER_NOAPI((-1))
HDassert(id >= 0);
if (NULL == (id_ptr = H5I__find_id(id)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, (-1), "can't locate ID")
++(id_ptr->count);
if (app_ref)
++(id_ptr->app_count);
ret_value = (int)(app_ref ? id_ptr->app_count : id_ptr->count);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
int
H5Iget_ref(hid_t id)
{
int ret_value;
FUNC_ENTER_API((-1))
H5TRACE1("Is", "i", id);
if (id < 0)
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, (-1), "invalid ID")
if ((ret_value = H5I_get_ref(id, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, (-1), "can't get ID ref count")
done:
FUNC_LEAVE_API(ret_value)
}
int
H5I_get_ref(hid_t id, hbool_t app_ref)
{
H5I_id_info_t *id_ptr;
int ret_value = 0;
FUNC_ENTER_NOAPI((-1))
HDassert(id >= 0);
if (NULL == (id_ptr = H5I__find_id(id)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, (-1), "can't locate ID")
ret_value = (int)(app_ref ? id_ptr->app_count : id_ptr->count);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
int
H5Iinc_type_ref(H5I_type_t type)
{
int ret_value;
FUNC_ENTER_API((-1))
H5TRACE1("Is", "It", type);
if(type <= 0 || (int)type >= H5I_next_type)
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, (-1), "invalid ID type")
if(H5I_IS_LIB_TYPE(type))
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, (-1), "cannot call public function on library type")
if((ret_value = H5I__inc_type_ref(type)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTINC, (-1), "can't increment ID type ref count")
done:
FUNC_LEAVE_API(ret_value)
}
static int
H5I__inc_type_ref(H5I_type_t type)
{
H5I_id_type_t *type_ptr;
int ret_value = -1;
FUNC_ENTER_STATIC
HDassert(type > 0 && (int)type < H5I_next_type);
type_ptr = H5I_id_type_list_g[type];
if(NULL == type_ptr)
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, (-1), "invalid type")
ret_value = (int)(++(type_ptr->init_count));
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5Idec_type_ref(H5I_type_t type)
{
herr_t ret_value = 0;
FUNC_ENTER_API((-1))
H5TRACE1("e", "It", type);
if (H5I_IS_LIB_TYPE(type))
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, (-1), "cannot call public function on library type")
ret_value = H5I_dec_type_ref(type);
done:
FUNC_LEAVE_API(ret_value)
}
int
H5I_dec_type_ref(H5I_type_t type)
{
H5I_id_type_t *type_ptr;
herr_t ret_value = 0;
FUNC_ENTER_NOAPI((-1))
if(type <= H5I_BADID || (int)type >= H5I_next_type)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, (-1), "invalid type number")
type_ptr = H5I_id_type_list_g[type];
if(type_ptr == NULL || type_ptr->init_count <= 0)
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, (-1), "invalid type")
if(1 == type_ptr->init_count) {
H5I__destroy_type(type);
ret_value = 0;
}
else {
--(type_ptr->init_count);
ret_value = (herr_t)type_ptr->init_count;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
int
H5Iget_type_ref(H5I_type_t type)
{
int ret_value;
FUNC_ENTER_API((-1))
H5TRACE1("Is", "It", type);
if(type <= 0 || (int)type >= H5I_next_type)
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, (-1), "invalid ID type")
if(H5I_IS_LIB_TYPE(type))
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, (-1), "cannot call public function on library type")
if((ret_value = H5I__get_type_ref(type)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, (-1), "can't get ID type ref count")
done:
FUNC_LEAVE_API(ret_value)
}
static int
H5I__get_type_ref(H5I_type_t type)
{
H5I_id_type_t *type_ptr;
int ret_value = -1;
FUNC_ENTER_STATIC
HDassert(type >= 0);
type_ptr = H5I_id_type_list_g[type];
if (!type_ptr)
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type")
ret_value = (int)type_ptr->init_count;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
htri_t
H5Iis_valid(hid_t id)
{
H5I_id_info_t *id_ptr;
htri_t ret_value = TRUE;
FUNC_ENTER_API(FAIL)
H5TRACE1("t", "i", id);
if (NULL == (id_ptr = H5I__find_id(id)))
ret_value = FALSE;
else if (!id_ptr->app_count)
ret_value = FALSE;
done:
FUNC_LEAVE_API(ret_value)
}
static int
H5I__search_cb(void *obj, hid_t id, void *_udata)
{
H5I_search_ud_t *udata = (H5I_search_ud_t *)_udata;
herr_t cb_ret_val;
int ret_value = H5_ITER_ERROR;
FUNC_ENTER_STATIC_NOERR
cb_ret_val = (*udata->app_cb)(obj, id, udata->app_key);
if(cb_ret_val > 0) {
ret_value = H5_ITER_STOP;
udata->ret_obj = obj;
}
else if(cb_ret_val < 0)
ret_value = H5_ITER_ERROR;
FUNC_LEAVE_NOAPI(ret_value)
}
void *
H5Isearch(H5I_type_t type, H5I_search_func_t func, void *key)
{
H5I_search_ud_t udata;
void *ret_value;
FUNC_ENTER_API(NULL)
H5TRACE3("*x", "Itx*x", type, func, key);
if (H5I_IS_LIB_TYPE(type))
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "cannot call public function on library type")
udata.app_cb = func;
udata.app_key = key;
udata.ret_obj = NULL;
(void)H5I_iterate(type, H5I__search_cb, &udata, TRUE);
ret_value = udata.ret_obj;
done:
FUNC_LEAVE_API(ret_value)
}
static int
H5I__iterate_cb(void *_item, void H5_ATTR_UNUSED *_key, void *_udata)
{
H5I_id_info_t *item = (H5I_id_info_t *)_item;
H5I_iterate_ud_t *udata = (H5I_iterate_ud_t *)_udata;
int ret_value = H5_ITER_CONT;
FUNC_ENTER_STATIC_NOERR
if((!udata->app_ref) || (item->app_count > 0)) {
herr_t cb_ret_val;
cb_ret_val = (*udata->user_func)((void *)item->obj_ptr, item->id, udata->user_udata);
if(cb_ret_val > 0)
ret_value = H5_ITER_STOP;
else if(cb_ret_val < 0)
ret_value = H5_ITER_ERROR;
}
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5I_iterate(H5I_type_t type, H5I_search_func_t func, void *udata, hbool_t app_ref)
{
H5I_id_type_t *type_ptr;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
if(type <= H5I_BADID || (int)type >= H5I_next_type)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
type_ptr = H5I_id_type_list_g[type];
if(type_ptr && type_ptr->init_count > 0 && type_ptr->id_count > 0) {
H5I_iterate_ud_t iter_udata;
herr_t iter_status;
iter_udata.user_func = func;
iter_udata.user_udata = udata;
iter_udata.app_ref = app_ref;
if((iter_status = H5SL_iterate(type_ptr->ids, H5I__iterate_cb, &iter_udata)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_BADITER, FAIL, "iteration failed")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static H5I_id_info_t *
H5I__find_id(hid_t id)
{
H5I_type_t type;
H5I_id_type_t *type_ptr;
H5I_id_info_t *ret_value = NULL;
FUNC_ENTER_STATIC_NOERR
type = H5I_TYPE(id);
if(type <= H5I_BADID || (int)type >= H5I_next_type)
HGOTO_DONE(NULL)
type_ptr = H5I_id_type_list_g[type];
if(!type_ptr || type_ptr->init_count <= 0)
HGOTO_DONE(NULL)
ret_value = (H5I_id_info_t *)H5SL_search(type_ptr->ids, &id);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
ssize_t
H5Iget_name(hid_t id, char *name, size_t size)
{
H5G_loc_t loc;
ssize_t ret_value;
FUNC_ENTER_API((-1))
H5TRACE3("Zs", "ixz", id, name, size);
if(H5G_loc(id, &loc) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, (-1), "can't retrieve object location")
if((ret_value = H5G_get_name(&loc, name, size, NULL)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, (-1), "can't retrieve object name")
done:
FUNC_LEAVE_API(ret_value)
}
hid_t
H5Iget_file_id(hid_t obj_id)
{
H5I_type_t type;
hid_t ret_value = H5I_INVALID_HID;
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE1("i", "i", obj_id);
type = H5I_TYPE(obj_id);
if(H5I_FILE == type || H5I_DATATYPE == type || H5I_GROUP == type || H5I_DATASET == type || H5I_ATTR == type) {
if((ret_value = H5I_get_file_id(obj_id, type)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, H5I_INVALID_HID, "can't retrieve file ID")
}
else
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, H5I_INVALID_HID, "not an ID of a file object")
done:
FUNC_LEAVE_API(ret_value)
}
hid_t
H5I_get_file_id(hid_t obj_id, H5I_type_t type)
{
hid_t ret_value = H5I_INVALID_HID;
FUNC_ENTER_NOAPI_NOINIT
if (type == H5I_FILE) {
if(H5I_inc_ref(obj_id, TRUE) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTSET, H5I_INVALID_HID, "incrementing file ID failed")
ret_value = obj_id;
}
else {
H5G_loc_t loc;
if(H5G_loc(obj_id, &loc) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, H5I_INVALID_HID, "can't get object location")
if((ret_value = H5F_get_id(loc.oloc->file, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, H5I_INVALID_HID, "can't get file ID")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static int
H5I__id_dump_cb(void *_item, void H5_ATTR_UNUSED *_key, void *_udata)
{
H5I_id_info_t *item = (H5I_id_info_t *)_item;
H5I_type_t type = *(H5I_type_t *)_udata;
H5G_name_t *path = NULL;
FUNC_ENTER_STATIC_NOERR
HDfprintf(stderr, " id = %lu\n", (unsigned long)(item->id));
HDfprintf(stderr, " count = %u\n", item->count);
HDfprintf(stderr, " obj = 0x%08lx\n", (unsigned long)(item->obj_ptr));
switch (type) {
case H5I_GROUP:
{
path = H5G_nameof((const H5G_t *)item->obj_ptr);
break;
}
case H5I_DATASET:
{
path = H5D_nameof((const H5D_t *)item->obj_ptr);
break;
}
case H5I_DATATYPE:
{
path = H5T_nameof((const H5T_t *)item->obj_ptr);
break;
}
case H5I_UNINIT:
case H5I_BADID:
case H5I_FILE:
case H5I_DATASPACE:
case H5I_ATTR:
case H5I_REFERENCE:
case H5I_VFL:
case H5I_GENPROP_CLS:
case H5I_GENPROP_LST:
case H5I_ERROR_CLASS:
case H5I_ERROR_MSG:
case H5I_ERROR_STACK:
case H5I_NTYPES:
default:
break;
}
if (path) {
if (path->user_path_r)
HDfprintf(stderr, " user_path = %s\n", H5RS_get_str(path->user_path_r));
if (path->full_path_r)
HDfprintf(stderr, " full_path = %s\n", H5RS_get_str(path->full_path_r));
}
FUNC_LEAVE_NOAPI(H5_ITER_CONT)
}
herr_t
H5I_dump_ids_for_type(H5I_type_t type)
{
H5I_id_type_t *type_ptr = NULL;
FUNC_ENTER_NOAPI_NOERR
HDfprintf(stderr, "Dumping ID type %d\n", (int)type);
type_ptr = H5I_id_type_list_g[type];
if(type_ptr) {
HDfprintf(stderr, " init_count = %u\n", type_ptr->init_count);
HDfprintf(stderr, " reserved = %u\n", type_ptr->cls->reserved);
HDfprintf(stderr, " id_count = %llu\n", (unsigned long long)type_ptr->id_count);
HDfprintf(stderr, " nextid = %llu\n", (unsigned long long)type_ptr->nextid);
if(type_ptr->id_count > 0) {
HDfprintf(stderr, " List:\n");
H5SL_iterate(type_ptr->ids, H5I__id_dump_cb, &type);
}
}
else
HDfprintf(stderr, "Global type info/tracking pointer for that type is NULL\n");
FUNC_LEAVE_NOAPI(SUCCEED)
}