From 133c0ad36f5a5864b840a26b6d85b13ad59b6819 Mon Sep 17 00:00:00 2001 From: Dana Robinson <43805+derobins@users.noreply.github.com> Date: Fri, 20 Nov 2020 21:17:36 -0800 Subject: Minor/id code cleanup (#114) * Revert "Switch ID code to use a hash table instead of a skip list (#52)" This reverts commit a50d211755cb272b2e468144e7d892a4c90813c4. * H5I_id_type_t and H5I_class_t are no longer managed via free lists * Fixed commenting issues * Naming and commenting cleanup in H5I.c * H5I cleanup * Header cleanup * Commenting * More uniform naming * Renames H5I_id_type_t and related in H5I.c * Adds gcc pragmas to ignore H5I const casting * Split H5I code into multiple files * Rename id_type to simply type in H5I code * Minor typo in H5Itest.c --- MANIFEST | 2 + src/CMakeLists.txt | 2 + src/H5I.c | 1802 ++++------------------------------------------------ src/H5Idbg.c | 191 ++++++ src/H5Iint.c | 1476 ++++++++++++++++++++++++++++++++++++++++++ src/H5Imodule.h | 12 +- src/H5Ipkg.h | 46 +- src/H5Iprivate.h | 4 +- src/H5Ipublic.h | 18 +- src/H5Itest.c | 7 +- src/Makefile.am | 2 +- 11 files changed, 1862 insertions(+), 1700 deletions(-) create mode 100644 src/H5Idbg.c create mode 100644 src/H5Iint.c diff --git a/MANIFEST b/MANIFEST index 28b6826..3acf466 100644 --- a/MANIFEST +++ b/MANIFEST @@ -825,6 +825,8 @@ ./src/H5HP.c ./src/H5HPprivate.h ./src/H5I.c +./src/H5Idbg.c +./src/H5Iint.c ./src/H5Imodule.h ./src/H5Ipkg.h ./src/H5Iprivate.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 221b629..e5136c5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -380,6 +380,8 @@ IDE_GENERATED_PROPERTIES ("H5HP" "${H5HP_HDRS}" "${H5HP_SOURCES}" ) set (H5I_SOURCES ${HDF5_SRC_DIR}/H5I.c + ${HDF5_SRC_DIR}/H5Idbg.c + ${HDF5_SRC_DIR}/H5Iint.c ${HDF5_SRC_DIR}/H5Itest.c ) set (H5I_HDRS diff --git a/src/H5I.c b/src/H5I.c index 18ba809..055b08e 100644 --- a/src/H5I.c +++ b/src/H5I.c @@ -11,62 +11,33 @@ * help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* - * FILE: H5I.c - Internal storage routines for handling "IDs" - * - * REMARKS: IDs which allow objects (void * currently) to be bundled - * into "types" for more general storage. - * - * DESIGN: The types are stored in an array of pointers to store each - * type in an element. Each "type" node contains a link to a - * hash table to manage the IDs in each type. Allowed types are - * values within the range 1 to H5I_MAX_NUM_TYPES and are given out - * at run-time. Types used by the library are stored in global - * variables defined in H5Ipublic.h. +/* + * H5I.c - Public routines for handling IDs */ +/****************/ +/* Module Setup */ +/****************/ + #include "H5Imodule.h" /* This source code file is part of the H5I module */ -#define H5T_FRIEND /* Suppress error about including H5Tpkg */ +/***********/ +/* Headers */ +/***********/ #include "H5private.h" /* Generic Functions */ -#include "H5ACprivate.h" /* Metadata cache */ -#include "H5CXprivate.h" /* API Contexts */ -#include "H5Dprivate.h" /* Datasets */ #include "H5Eprivate.h" /* Error handling */ -#include "H5Fprivate.h" /* File access */ -#include "H5FLprivate.h" /* Free Lists */ -#include "H5Gprivate.h" /* Groups */ +#include "H5Fprivate.h" /* Files */ #include "H5Ipkg.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ -#include "H5Oprivate.h" /* Object headers */ -#include "H5SLprivate.h" /* Skip Lists */ -#include "H5Tpkg.h" /* Datatypes */ -#include "H5VLprivate.h" /* Virtual Object Layer */ +#include "H5Pprivate.h" /* Property lists */ +/****************/ /* Local Macros */ +/****************/ -/* Combine a Type number and an atom index into an atom */ -#define H5I_MAKE(g, i) ((((hid_t)(g)&TYPE_MASK) << ID_BITS) | ((hid_t)(i)&ID_MASK)) - -/* Local typedefs */ - -/* Atom information structure used */ -typedef struct H5I_id_info_t { - hid_t id; /* ID for this info */ - unsigned count; /* ref. count for this atom */ - unsigned app_count; /* ref. count of application visible atoms */ - const void *obj_ptr; /* pointer associated with the atom */ -} H5I_id_info_t; - -/* ID type structure used */ -typedef struct { - const H5I_class_t *cls; /* Pointer to ID class */ - unsigned init_count; /* # of times this type has been initialized*/ - uint64_t id_count; /* Current number of IDs held */ - uint64_t nextid; /* ID to use for the next atom */ - H5I_id_info_t * last_info; /* Info for most recent ID looked up */ - H5SL_t * ids; /* Pointer to skip list that stores IDs */ -} H5I_id_type_t; +/******************/ +/* Local Typedefs */ +/******************/ typedef struct { H5I_search_func_t app_cb; /* Application's callback routine */ @@ -79,119 +50,28 @@ typedef struct { void * op_data; /* Application's user data */ } H5I_iterate_pub_ud_t; -/* 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; +/********************/ +/* Package Typedefs */ +/********************/ -/* 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; +/********************/ +/* Local Prototypes */ +/********************/ -/* User data for H5I__clear_type_cb */ -typedef struct { - H5I_id_type_t *type_ptr; /* Pointer to the type being cleard */ - 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 initialization variable */ -hbool_t H5_PKG_INIT_VAR = FALSE; - -/*-------------------- Locally scoped variables -----------------------------*/ - -/* Array of pointers to atomic types */ -static H5I_id_type_t *H5I_id_type_list_g[H5I_MAX_NUM_TYPES]; - -/* Variable to keep track of the number of types allocated. Its value is the */ -/* next type ID to be handed out, so it is always one greater than the number */ -/* of types. */ -/* Starts at 1 instead of 0 because it makes trace output look nicer. If more */ -/* types (or IDs within a type) are needed, adjust TYPE_BITS in H5Ipkg.h */ -/* and/or increase size of hid_t */ -static int H5I_next_type = (int)H5I_NTYPES; - -/* Declare a free list to manage the H5I_id_info_t struct */ -H5FL_DEFINE_STATIC(H5I_id_info_t); - -/* Declare a free list to manage the H5I_id_type_t struct */ -H5FL_DEFINE_STATIC(H5I_id_type_t); - -/* Declare a free list to manage the H5I_class_t struct */ -H5FL_DEFINE_STATIC(H5I_class_t); - -H5FL_EXTERN(H5VL_object_t); - -/*--------------------- Local function prototypes ---------------------------*/ -static void * H5I__unwrap(void *obj_ptr, H5I_type_t type); -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__iterate_pub_cb(void *obj, hid_t id, void *udata); -static int H5I__find_id_cb(void *_item, void *_key, void *_udata); -static int H5I__id_dump_cb(void *_item, void *_key, void *_udata); +static int H5I__search_cb(void *obj, hid_t id, void *_udata); +static int H5I__iterate_pub_cb(void *obj, hid_t id, void *udata); -/*------------------------------------------------------------------------- - * 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 n = 0; - - FUNC_ENTER_NOAPI_NOINIT_NOERR - - if (H5_PKG_INIT_VAR) { - H5I_id_type_t *type_ptr; /* Pointer to ID type */ - int type; /* Type of ID */ - - /* How many types are still being used? */ - for (type = 0; type < H5I_next_type; type++) - if ((type_ptr = H5I_id_type_list_g[type]) && type_ptr->ids) - n++; - - /* If no types are used then clean up */ - 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++; - } /* end if */ - } /* end for */ - - /* Mark interface closed */ - if (0 == n) - H5_PKG_INIT_VAR = FALSE; - } /* end if */ - } /* end if */ - - FUNC_LEAVE_NOAPI(n) -} /* end H5I_term_package() */ +/*********************/ +/* Package Variables */ +/*********************/ + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + +/*******************/ +/* Local Variables */ +/*******************/ /*------------------------------------------------------------------------- * Function: H5Iregister_type @@ -214,7 +94,7 @@ 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; /* New ID class */ - H5I_type_t new_type; /* New ID type value */ + H5I_type_t new_type = H5I_BADID; /* New ID type value */ H5I_type_t ret_value = H5I_BADID; /* Return value */ FUNC_ENTER_API(H5I_BADID) @@ -223,35 +103,35 @@ H5Iregister_type(size_t H5_ATTR_DEBUG_API_USED hash_size, unsigned reserved, H5I /* Generate a new H5I_type_t value */ /* Increment the number of types */ - if (H5I_next_type < H5I_MAX_NUM_TYPES) { - new_type = (H5I_type_t)H5I_next_type; - H5I_next_type++; - } /* end if */ + if (H5I_next_type_g < H5I_MAX_NUM_TYPES) { + new_type = (H5I_type_t)H5I_next_type_g; + H5I_next_type_g++; + } else { hbool_t done; /* Indicate that search was successful */ - int i; /* Local index variable */ + int i; /* Look for a free type to give out */ done = FALSE; for (i = H5I_NTYPES; i < H5I_MAX_NUM_TYPES && done == FALSE; i++) { - if (NULL == H5I_id_type_list_g[i]) { + if (NULL == H5I_type_info_array_g[i]) { /* Found a free type ID */ new_type = (H5I_type_t)i; done = TRUE; - } /* end if */ - } /* end for */ + } + } /* Verify that we found a type to give out */ if (done == FALSE) HGOTO_ERROR(H5E_ATOM, H5E_NOSPACE, H5I_BADID, "Maximum number of ID types exceeded") - } /* end else */ + } /* Allocate new ID class */ - if (NULL == (cls = H5FL_CALLOC(H5I_class_t))) + if (NULL == (cls = H5MM_calloc(sizeof(H5I_class_t)))) HGOTO_ERROR(H5E_ATOM, H5E_CANTALLOC, H5I_BADID, "ID class allocation failed") /* Initialize class fields */ - cls->type_id = new_type; + cls->type = new_type; cls->flags = H5I_CLASS_IS_APPLICATION; cls->reserved = reserved; cls->free_func = free_func; @@ -267,72 +147,12 @@ done: /* Clean up on error */ if (ret_value < 0) if (cls) - cls = H5FL_FREE(H5I_class_t, cls); + cls = H5MM_xfree(cls); FUNC_LEAVE_API(ret_value) } /* end H5Iregister_type() */ /*------------------------------------------------------------------------- - * 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_id_type_t *type_ptr = NULL; /* Ptr to the atomic type*/ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(FAIL) - - /* Sanity check */ - HDassert(cls); - HDassert(cls->type_id > 0 && (int)cls->type_id < H5I_MAX_NUM_TYPES); - - /* Initialize the type */ - if (NULL == H5I_id_type_list_g[cls->type_id]) { - /* Allocate the type information for new type */ - 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; - } /* end if */ - else { - /* Get the pointer to the existing type */ - type_ptr = H5I_id_type_list_g[cls->type_id]; - } /* end else */ - - /* Initialize the ID type structure for new types */ - if (type_ptr->init_count == 0) { - type_ptr->cls = cls; - type_ptr->id_count = 0; - type_ptr->nextid = cls->reserved; - type_ptr->last_info = NULL; - if (NULL == (type_ptr->ids = H5SL_create(H5SL_TYPE_HID, NULL))) - HGOTO_ERROR(H5E_ATOM, H5E_CANTCREATE, FAIL, "skip list creation failed") - } /* end if */ - - /* Increment the count of the times this type has been initialized */ - type_ptr->init_count++; - -done: - if (ret_value < 0) { /* Clean up on error */ - if (type_ptr) { - if (type_ptr->ids) - H5SL_close(type_ptr->ids); - (void)H5FL_FREE(H5I_id_type_t, type_ptr); - } /* end if */ - } /* end if */ - - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5I_register_type() */ - -/*------------------------------------------------------------------------- * Function: H5Itype_exists * * Purpose: Query function to inform the user if a given type is @@ -353,10 +173,10 @@ H5Itype_exists(H5I_type_t type) /* Validate parameter */ 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) + if (type <= H5I_BADID || (int)type >= H5I_next_type_g) HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number") - if (NULL == H5I_id_type_list_g[type]) + if (NULL == H5I_type_info_array_g[type]) ret_value = FALSE; done: @@ -373,8 +193,8 @@ done: * * Return: SUCCEED/FAIL * - * Programmer: James Laird - * Nathaniel Furrer + * Programmer: James Laird + * Nathaniel Furrer * Friday, April 23, 2004 * *------------------------------------------------------------------------- @@ -382,7 +202,7 @@ done: herr_t H5Inmembers(H5I_type_t type, hsize_t *num_members) { - int ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE2("e", "It*h", type, num_members); @@ -394,9 +214,9 @@ H5Inmembers(H5I_type_t type, hsize_t *num_members) * the private interface handle it, because the public interface throws * an error when the supplied type does not exist. */ - if (type <= H5I_BADID || (int)type >= H5I_next_type) + if (type <= H5I_BADID || (int)type >= H5I_next_type_g) HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number") - if (NULL == H5I_id_type_list_g[type]) + if (NULL == H5I_type_info_array_g[type]) HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "supplied type does not exist") if (num_members) { @@ -406,92 +226,13 @@ H5Inmembers(H5I_type_t type, hsize_t *num_members) HGOTO_ERROR(H5E_ATOM, H5E_CANTCOUNT, FAIL, "can't compute number of members") H5_CHECKED_ASSIGN(*num_members, hsize_t, members, int64_t); - } /* end if */ + } done: FUNC_LEAVE_API(ret_value) } /* end H5Inmembers() */ /*------------------------------------------------------------------------- - * 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_id_type_t *type_ptr; /* Pointer to the ID type */ - int64_t ret_value = 0; /* Return value */ - - FUNC_ENTER_NOAPI(FAIL) - - /* Validate parameter */ - 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); - - /* Set return value */ - H5_CHECKED_ASSIGN(ret_value, int64_t, type_ptr->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 *obj_ptr, H5I_type_t type) -{ - void *ret_value = NULL; /* Return value */ - - FUNC_ENTER_STATIC_NOERR - - /* Sanity checks */ - HDassert(obj_ptr); - - /* 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 *)obj_ptr; - ret_value = H5VL_object_data(vol_obj); - } /* end if */ - else if (H5I_DATATYPE == type) { - H5T_t *dt = (H5T_t *)obj_ptr; - - ret_value = (void *)H5T_get_actual_type(dt); - } /* end if */ - else - ret_value = obj_ptr; - - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5I__unwrap() */ - -/*------------------------------------------------------------------------- * Function: H5Iclear_type * * Purpose: Removes all objects from the type, calling the free @@ -500,8 +241,8 @@ H5I__unwrap(void *obj_ptr, H5I_type_t type) * * Return: SUCCEED/FAIL * - * Programmer: James Laird - * Nathaniel Furrer + * Programmer: James Laird + * Nathaniel Furrer * Friday, April 23, 2004 * *------------------------------------------------------------------------- @@ -524,116 +265,9 @@ done: } /* end H5Iclear_type() */ /*------------------------------------------------------------------------- - * 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 */ - int ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(FAIL) - - /* Validate parameters */ - 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") - - /* Finish constructing udata */ - udata.force = force; - udata.app_ref = app_ref; - - /* Attempt to free all ids in the type */ - 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) -} /* end H5I_clear_type() */ - -/*------------------------------------------------------------------------- - * Function: H5I__clear_type_cb - * - * Purpose: Attempts to free the specified ID, calling the free - * function for the object. - * - * Return: TRUE/FALSE/FAIL - * - * Programmer: Neil Fortner - * Friday, July 10, 2015 - * - *------------------------------------------------------------------------- - */ -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; /* Current ID being worked with */ - H5I_clear_type_ud_t *udata = (H5I_clear_type_ud_t *)_udata; /* udata struct */ - htri_t ret_value = FALSE; /* Return value */ - - FUNC_ENTER_STATIC_NOERR - - /* Sanity checks */ - HDassert(id); - HDassert(udata); - HDassert(udata->type_ptr); - - /* Do nothing to the object if the reference count is larger than - * one and forcing is off. - */ - if (udata->force || (id->count - (!udata->app_ref * id->app_count)) <= 1) { - /* Check for a 'free' function and call it, if it exists */ - if (udata->type_ptr->cls->free_func && - (udata->type_ptr->cls->free_func)((void *)id->obj_ptr) < 0) { /* (Casting away const OK -QAK) */ - 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)); - } /* end if */ -#endif /*H5I_DEBUG*/ - - /* Indicate node should be removed from list */ - ret_value = TRUE; - } /* end if */ - } /* end if */ - else { - /* Indicate node should be removed from list */ - ret_value = TRUE; - } /* end else */ - - /* Remove ID if requested */ - if (ret_value) { - /* Free ID info */ - id = H5FL_FREE(H5I_id_info_t, id); - - /* Decrement the number of IDs in the type */ - udata->type_ptr->id_count--; - } /* end if */ - } /* end if */ - - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5I__clear_type_cb() */ - -/*------------------------------------------------------------------------- * Function: H5Idestroy_type * - * Purpose: Destroys a type along with all atoms in that 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. Public @@ -641,8 +275,8 @@ H5I__clear_type_cb(void *_id, void H5_ATTR_UNUSED *key, void *_udata) * * Return: SUCCEED/FAIL * - * Programmer: Nathaniel Furrer - * James Laird + * Programmer: Nathaniel Furrer + * James Laird * *------------------------------------------------------------------------- */ @@ -664,56 +298,6 @@ done: } /* end H5Idestroy_type() */ /*------------------------------------------------------------------------- - * Function: H5I__destroy_type - * - * Purpose: Destroys a type along with all atoms 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 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5I__destroy_type(H5I_type_t type) -{ - H5I_id_type_t *type_ptr; /* ptr to the atomic type */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_STATIC - - /* Validate parameter */ - 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") - - /* 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_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) -} /* end H5I__destroy_type() */ - -/*------------------------------------------------------------------------- * Function: H5Iregister * * Purpose: Public interface to H5I_register. @@ -732,7 +316,7 @@ H5Iregister(H5I_type_t type, const void *object) 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") + HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, H5I_INVALID_HID, "cannot call public function on library type") ret_value = H5I_register(type, object, TRUE); @@ -741,202 +325,6 @@ done: } /* end H5Iregister() */ /*------------------------------------------------------------------------- - * 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. - * - * 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_id_type_t *type_ptr = NULL; /* ptr to the type */ - H5I_id_info_t *id_ptr = NULL; /* ptr to the new ID information */ - hid_t new_id = -1; /* new ID */ - hid_t ret_value = H5I_INVALID_HID; /* return value */ - - FUNC_ENTER_NOAPI(FAIL) - - /* Check arguments */ - 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") - - /* Create the struct & its ID */ - new_id = H5I_MAKE(type, type_ptr->nextid); - id_ptr->id = new_id; - id_ptr->count = 1; /* initial reference count */ - id_ptr->app_count = !!app_ref; - id_ptr->obj_ptr = object; - - /* Insert into the type */ - 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++; - - /* Sanity check for the 'nextid' getting too large and wrapping around */ - HDassert(type_ptr->nextid <= ID_MASK); - - /* Set the most recent ID to this object */ - type_ptr->last_info = id_ptr; - - /* Set return value */ - ret_value = new_id; - -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_id_type_t *type_ptr; /* ptr to the type */ - H5I_id_info_t *id_ptr; /* ptr 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 != (id_ptr = H5I__find_id(existing_id))) - HGOTO_ERROR(H5E_ATOM, H5E_BADRANGE, FAIL, "ID already in use") - - /* Make sure type number is valid */ - if (type <= H5I_BADID || (int)type >= H5I_next_type) - HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number") - - /* Get type pointer from list of types */ - 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") - - /* Make sure requested ID belongs to object's type */ - if (H5I_TYPE(existing_id) != type) - HGOTO_ERROR(H5E_ATOM, H5E_BADRANGE, FAIL, "invalid type for provided ID") - - /* Allocate new structure to house this ID */ - if (NULL == (id_ptr = H5FL_MALLOC(H5I_id_info_t))) - HGOTO_ERROR(H5E_ATOM, H5E_NOSPACE, FAIL, "memory allocation failed") - - /* Create the struct & insert requested ID */ - id_ptr->id = existing_id; - id_ptr->count = 1; /* initial reference count*/ - id_ptr->app_count = !!app_ref; - id_ptr->obj_ptr = object; - - /* Insert into the type */ - 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++; - - /* Set the most recent ID to this object */ - type_ptr->last_info = id_ptr; - -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 *id_ptr; /* Pointer to the atom */ - void * ret_value = NULL; /* Return value */ - - FUNC_ENTER_NOAPI(NULL) - - /* General lookup of the ID */ - if (NULL == (id_ptr = H5I__find_id(id))) - HGOTO_ERROR(H5E_ATOM, H5E_NOTFOUND, NULL, "can't get ID ref count") - - /* Get the old object pointer to return */ - ret_value = (void *)id_ptr->obj_ptr; /* (Casting away const OK -QAK) */ - - /* Set the new object pointer for the ID */ - id_ptr->obj_ptr = 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 *id_ptr; /* Pointer to the new atom */ - void * ret_value = NULL; /* Return value */ - - FUNC_ENTER_NOAPI_NOERR - - /* General lookup of the ID */ - if (NULL != (id_ptr = H5I__find_id(id))) { - /* Get the object pointer to return */ - ret_value = (void *)id_ptr->obj_ptr; /* (Casting away const OK -QAK) */ - } - - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5I_object() */ - -/*------------------------------------------------------------------------- * Function: H5Iobject_verify * * Purpose: Find an object pointer for the specified ID, verifying that @@ -950,93 +338,26 @@ H5I_object(hid_t id) *------------------------------------------------------------------------- */ void * -H5Iobject_verify(hid_t id, H5I_type_t id_type) +H5Iobject_verify(hid_t id, H5I_type_t type) { void *ret_value = NULL; /* Return value */ FUNC_ENTER_API(NULL) - H5TRACE2("*x", "iIt", id, id_type); + H5TRACE2("*x", "iIt", id, type); /* Validate parameters */ - if (H5I_IS_LIB_TYPE(id_type)) + if (H5I_IS_LIB_TYPE(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) + if (type < 1 || (int)type >= H5I_next_type_g) HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "identifier has invalid type") - ret_value = H5I_object_verify(id, id_type); + ret_value = H5I_object_verify(id, type); done: FUNC_LEAVE_API(ret_value) } /* end H5Iobject_verify() */ /*------------------------------------------------------------------------- - * 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 id_type) -{ - H5I_id_info_t *id_ptr = NULL; /* Pointer to the new atom */ - void * ret_value = NULL; /* Return value */ - - FUNC_ENTER_NOAPI_NOERR - - HDassert(id_type >= 1 && (int)id_type < H5I_next_type); - - /* Verify that the type of the ID is correct & lookup the ID */ - if (id_type == H5I_TYPE(id) && NULL != (id_ptr = H5I__find_id(id))) { - /* Get the object pointer to return */ - ret_value = (void *)id_ptr->obj_ptr; /* (Casting away const OK -QAK) */ - } - - 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); - - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5I_get_type() */ - -/*------------------------------------------------------------------------- * Function: H5Iget_type * * Purpose: The public version of H5I_get_type(), obtains a type number @@ -1061,7 +382,7 @@ H5Iget_type(hid_t id) ret_value = H5I_get_type(id); - if (ret_value <= H5I_BADID || (int)ret_value >= H5I_next_type || NULL == H5I_object(id)) + if (ret_value <= H5I_BADID || (int)ret_value >= H5I_next_type_g || NULL == H5I_object(id)) HGOTO_DONE(H5I_BADID); done: @@ -1069,54 +390,6 @@ done: } /* end H5Iget_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 id_type = H5I_get_type(id); - htri_t ret_value = FAIL; - - FUNC_ENTER_NOAPI(FAIL); - - /* Fail if the ID type is out of range */ - if (id_type < 1 || id_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 == id_type || H5I_GROUP == id_type || H5I_MAP == id_type) - ret_value = TRUE; - else if (H5I_DATATYPE == id_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: H5Iremove_verify * * Purpose: Removes the specified ID from its type, first checking that the @@ -1128,145 +401,30 @@ done: * calling H5I_object(). * Failure: NULL * - * Programmer: James Laird - * Nathaniel Furrer + * Programmer: James Laird + * Nathaniel Furrer * *------------------------------------------------------------------------- */ void * -H5Iremove_verify(hid_t id, H5I_type_t id_type) +H5Iremove_verify(hid_t id, H5I_type_t type) { void *ret_value = NULL; /* Return value */ FUNC_ENTER_API(NULL) - H5TRACE2("*x", "iIt", id, id_type); + H5TRACE2("*x", "iIt", id, type); - if (H5I_IS_LIB_TYPE(id_type)) + if (H5I_IS_LIB_TYPE(type)) HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "cannot call public function on library type") /* Remove the id */ - ret_value = H5I__remove_verify(id, id_type); + ret_value = H5I__remove_verify(id, type); done: FUNC_LEAVE_API(ret_value) } /* end H5Iremove_verify() */ /*------------------------------------------------------------------------- - * 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 - * - *------------------------------------------------------------------------- - */ -static void * -H5I__remove_verify(hid_t id, H5I_type_t id_type) -{ - void *ret_value = NULL; /*return value */ - - FUNC_ENTER_STATIC_NOERR - - /* Argument checking will be performed by H5I_remove() */ - - /* Verify that the type of the ID is correct */ - if (id_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_id_type_t *type_ptr, hid_t id) -{ - H5I_id_info_t *curr_id; /* Pointer to the current atom */ - void * ret_value = NULL; /* Return value */ - - FUNC_ENTER_STATIC - - /* Sanity check */ - HDassert(type_ptr); - - /* Get the ID node for the ID */ - 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") - - /* Check if this ID was the last one accessed */ - if (type_ptr->last_info == curr_id) - type_ptr->last_info = NULL; - - ret_value = (void *)curr_id->obj_ptr; /* (Casting away const OK -QAK) */ - curr_id = H5FL_FREE(H5I_id_info_t, curr_id); - - /* Decrement the number of IDs in the type */ - (type_ptr->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 - * - * Programmer: Unknown - * - *------------------------------------------------------------------------- - */ -void * -H5I_remove(hid_t id) -{ - H5I_id_type_t *type_ptr; /* Pointer to the atomic type */ - H5I_type_t type; /* Atom's atomic 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) - 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") - - /* Remove the node from the 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) -} /* end H5I_remove() */ - -/*------------------------------------------------------------------------- * Function: H5Idec_ref * * Purpose: Decrements the number of references outstanding for an ID. @@ -1302,163 +460,6 @@ done: } /* end H5Idec_ref() */ /*------------------------------------------------------------------------- - * Function: H5I_dec_ref - * - * Purpose: Decrements the number of references outstanding for an ID. - * 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. - * - * Return: Success: New reference count - * - * Failure: -1 - * - *------------------------------------------------------------------------- - */ -int -H5I_dec_ref(hid_t id) -{ - H5I_id_info_t *id_ptr; /* Pointer to the new ID */ - int ret_value = 0; /* Return value */ - - FUNC_ENTER_NOAPI((-1)) - - /* Sanity check */ - HDassert(id >= 0); - - /* General lookup of the ID */ - if (NULL == (id_ptr = H5I__find_id(id))) - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, (-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 == id_ptr->count) { - H5I_id_type_t *type_ptr; /*ptr to the type */ - - /* Get the ID's type */ - type_ptr = H5I_id_type_list_g[H5I_TYPE(id)]; - - /* (Casting away const OK -QAK) */ - if (!type_ptr->cls->free_func || (type_ptr->cls->free_func)((void *)id_ptr->obj_ptr) >= 0) { - /* Remove the node from the type */ - if (NULL == H5I__remove_common(type_ptr, id)) - HGOTO_ERROR(H5E_ATOM, H5E_CANTDELETE, (-1), "can't remove ID node") - ret_value = 0; - } /* end if */ - else - ret_value = -1; - } /* end if */ - else { - --(id_ptr->count); - ret_value = (int)id_ptr->count; - } /* end else */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5I_dec_ref() */ - -/*------------------------------------------------------------------------- - * Function: H5I_dec_app_ref - * - * Purpose: H5I_dec_ref 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) -{ - H5I_id_info_t *id_ptr; /* Pointer to the new ID */ - int ret_value = 0; /* Return value */ - - FUNC_ENTER_NOAPI((-1)) - - /* Sanity check */ - HDassert(id >= 0); - - /* Call regular decrement reference count routine */ - if ((ret_value = H5I_dec_ref(id)) < 0) - HGOTO_ERROR(H5E_ATOM, H5E_CANTDEC, (-1), "can't decrement ID ref count") - - /* Check if the ID still exists */ - if (ret_value > 0) { - /* General lookup of the ID */ - if (NULL == (id_ptr = H5I__find_id(id))) - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, (-1), "can't locate ID") - - /* Adjust app_ref */ - --(id_ptr->app_count); - HDassert(id_ptr->count >= id_ptr->app_count); - - /* Set return value */ - ret_value = (int)id_ptr->app_count; - } /* end if */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5I_dec_app_ref() */ - -/*------------------------------------------------------------------------- - * Function: H5I_dec_app_ref_always_close - * - * Purpose: H5I_dec_app_ref 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); - - /* Call application decrement reference count routine */ - ret_value = H5I_dec_app_ref(id); - - /* 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_ATOM, H5E_CANTDEC, (-1), "can't decrement ID ref count") - } - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5I_dec_app_ref_always_close() */ - -/*------------------------------------------------------------------------- * Function: H5Iinc_ref * * Purpose: Increments the number of references outstanding for an ID. @@ -1471,7 +472,7 @@ done: int H5Iinc_ref(hid_t id) { - int ret_value; /* Return value */ + int ret_value = -1; /* Return value */ FUNC_ENTER_API((-1)) H5TRACE1("Is", "i", id); @@ -1489,43 +490,6 @@ done: } /* end H5Iinc_ref() */ /*------------------------------------------------------------------------- - * 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 *id_ptr; /* 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 == (id_ptr = H5I__find_id(id))) - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, (-1), "can't locate ID") - - /* Adjust reference counts */ - ++(id_ptr->count); - if (app_ref) - ++(id_ptr->app_count); - - /* Set return value */ - ret_value = (int)(app_ref ? id_ptr->app_count : id_ptr->count); - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5I_inc_ref() */ - -/*------------------------------------------------------------------------- * Function: H5Iget_ref * * Purpose: Retrieves the number of references outstanding for an ID. @@ -1538,7 +502,7 @@ done: int H5Iget_ref(hid_t id) { - int ret_value; /* Return value */ + int ret_value = -1; /* Return value */ FUNC_ENTER_API((-1)) H5TRACE1("Is", "i", id); @@ -1556,38 +520,6 @@ done: } /* end H5Iget_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 *id_ptr; /* 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 == (id_ptr = H5I__find_id(id))) - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, (-1), "can't locate ID") - - /* Set return value */ - ret_value = (int)(app_ref ? id_ptr->app_count : id_ptr->count); - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5I_get_ref() */ - -/*------------------------------------------------------------------------- * Function: H5Iinc_type_ref * * Purpose: Increments the number of references outstanding for an ID type. @@ -1600,64 +532,31 @@ done: int H5Iinc_type_ref(H5I_type_t type) { - int ret_value; /* Return value */ + int ret_value = -1; /* Return value */ FUNC_ENTER_API((-1)) H5TRACE1("Is", "It", type); /* Check arguments */ - 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") - - /* Do actual increment operation */ - 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) -} /* end H5Iinc_ref() */ - -/*------------------------------------------------------------------------- - * Function: H5I__inc_type_ref - * - * Purpose: Increment the reference count for an ID type. - * - * Return: Success: The new reference count - * Failure: -1 - * - *------------------------------------------------------------------------- - */ -static int -H5I__inc_type_ref(H5I_type_t type) -{ - H5I_id_type_t *type_ptr; /* Pointer to the type */ - int ret_value = -1; /* Return value */ - - FUNC_ENTER_STATIC - - /* Sanity check */ - HDassert(type > 0 && (int)type < H5I_next_type); - - /* Check arguments */ - type_ptr = H5I_id_type_list_g[type]; - if (NULL == type_ptr) - HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, (-1), "invalid type") + if (type <= 0 || (int)type >= H5I_next_type_g) + 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") - /* Set return value */ - ret_value = (int)(++(type_ptr->init_count)); + /* Do actual increment operation */ + 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_NOAPI(ret_value) -} /* end H5I__inc_type_ref() */ + FUNC_LEAVE_API(ret_value) +} /* end H5Iinc_ref() */ /*------------------------------------------------------------------------- * Function: H5Idec_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 atoms in that type regardless of + * 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. Public interface to @@ -1694,58 +593,6 @@ done: } /* end H5Idec_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 atoms 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_id_type_t *type_ptr; /* 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) - 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") - - /* Decrement the number of users of the atomic type. If this is the - * last user of the type then release all atoms from the type and - * free all memory it used. The free function is invoked for each atom - * being freed. - */ - if (1 == type_ptr->init_count) { - H5I__destroy_type(type); - ret_value = 0; - } /* end if */ - else { - --(type_ptr->init_count); - ret_value = (herr_t)type_ptr->init_count; - } /* end else */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5I_dec_type_ref() */ - -/*------------------------------------------------------------------------- * Function: H5Iget_type_ref * * Purpose: Retrieves the number of references outstanding for a type. @@ -1758,13 +605,13 @@ done: int H5Iget_type_ref(H5I_type_t type) { - int ret_value; /* Return value */ + int ret_value = -1; /* Return value */ FUNC_ENTER_API((-1)) H5TRACE1("Is", "It", type); /* Check arguments */ - if (type <= 0 || (int)type >= H5I_next_type) + if (type <= 0 || (int)type >= H5I_next_type_g) 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") @@ -1778,40 +625,6 @@ done: } /* end H5Iget_ref() */ /*------------------------------------------------------------------------- - * Function: H5I__get_type_ref - * - * Purpose: Retrieve the reference count for an ID type. - * - * Return: Success: The reference count - * - * Failure: -1 - * - *------------------------------------------------------------------------- - */ -static int -H5I__get_type_ref(H5I_type_t type) -{ - H5I_id_type_t *type_ptr; /* Pointer to the type */ - int ret_value = -1; /* Return value */ - - FUNC_ENTER_STATIC - - /* Sanity check */ - HDassert(type >= 0); - - /* Check arguments */ - type_ptr = H5I_id_type_list_g[type]; - if (!type_ptr) - HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type") - - /* Set return value */ - ret_value = (int)type_ptr->init_count; - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5I__get_type_ref() */ - -/*------------------------------------------------------------------------- * Function: H5Iis_valid * * Purpose: Check if the given id is valid. An id is valid if it is in @@ -1824,16 +637,16 @@ done: htri_t H5Iis_valid(hid_t id) { - H5I_id_info_t *id_ptr; /* ptr to the ID */ - htri_t ret_value = TRUE; /* Return value */ + H5I_id_info_t *info = NULL; /* Pointer to the ID info */ + htri_t ret_value = TRUE; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE1("t", "i", id); /* Find the ID */ - if (NULL == (id_ptr = H5I__find_id(id))) + if (NULL == (info = H5I__find_id(id))) ret_value = FALSE; - else if (!id_ptr->app_count) /* Check if the found id is an internal id */ + else if (!info->app_count) /* Check if the found id is an internal id */ ret_value = FALSE; done: @@ -1897,8 +710,8 @@ H5I__search_cb(void *obj, hid_t id, void *_udata) void * H5Isearch(H5I_type_t type, H5I_search_func_t func, void *key) { - H5I_search_ud_t udata; /* Context for iteration */ - void * ret_value; /* Return value */ + H5I_search_ud_t udata; /* Context for iteration */ + void * ret_value = NULL; /* Return value */ FUNC_ENTER_API(NULL) H5TRACE3("*x", "Itx*x", type, func, key); @@ -1944,7 +757,7 @@ static int H5I__iterate_pub_cb(void H5_ATTR_UNUSED *obj, hid_t id, void *_udata) { H5I_iterate_pub_ud_t *udata = (H5I_iterate_pub_ud_t *)_udata; /* User data for callback */ - herr_t cb_ret_val; /* User callback return value */ + herr_t cb_ret_val = FAIL; /* User callback return value */ int ret_value = H5_ITER_ERROR; /* Callback return value */ FUNC_ENTER_STATIC_NOERR @@ -1990,7 +803,7 @@ herr_t H5Iiterate(H5I_type_t type, H5I_iterate_func_t op, void *op_data) { H5I_iterate_pub_ud_t int_udata; /* Internal user data */ - herr_t ret_value; /* Return value */ + herr_t ret_value = FAIL; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE3("e", "Itx*x", type, op, op_data); @@ -2010,154 +823,48 @@ done: } /* end H5Iiterate() */ /*------------------------------------------------------------------------- - * 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 * item = (H5I_id_info_t *)_item; /* Pointer to the ID node */ - 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_STATIC_NOERR - - /* Only invoke the callback function if this ID is visible externally and - * its reference count is positive. - */ - if ((!udata->app_ref) || (item->app_count > 0)) { - H5I_type_t type = udata->obj_type; - void * obj_ptr; - 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.). - */ - obj_ptr = H5I__unwrap((void *)item->obj_ptr, type); - - /* Invoke callback function */ - cb_ret_val = - (*udata->user_func)((void *)obj_ptr, item->id, udata->user_udata); /* (Casting away const OK) */ - - /* 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) */ - } /* end if */ - - 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. + * Function: H5Iget_file_id * - * 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. + * Purpose: Obtains the file ID given an object ID. The user has to + * close this ID. * - * Limitation: Currently there is no way to start the iteration from - * where a previous iteration left off. + * Return: Success: The file ID associated with the object * - * Return: SUCCEED/FAIL + * Failure: H5I_INVALID_HID * *------------------------------------------------------------------------- */ -herr_t -H5I_iterate(H5I_type_t type, H5I_search_func_t func, void *udata, hbool_t app_ref) +hid_t +H5Iget_file_id(hid_t obj_id) { - H5I_id_type_t *type_ptr; /* 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) - HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number") - type_ptr = H5I_id_type_list_g[type]; - - /* Only iterate through ID list if it is initialized and there are IDs in type */ - if (type_ptr && type_ptr->init_count > 0 && type_ptr->id_count > 0) { - H5I_iterate_ud_t iter_udata; /* User data for iteration callback */ - herr_t iter_status; /* Iteration status */ - - /* 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 */ - if ((iter_status = H5SL_iterate(type_ptr->ids, H5I__iterate_cb, &iter_udata)) < 0) - HGOTO_ERROR(H5E_ATOM, H5E_BADITER, FAIL, "iteration failed") - } /* end if */ + H5I_type_t type; /* ID type */ + hid_t ret_value = H5I_INVALID_HID; /* Return value */ -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5I_iterate() */ + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE1("i", "i", obj_id); -/*------------------------------------------------------------------------- - * 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 - * - *------------------------------------------------------------------------- - */ -static H5I_id_info_t * -H5I__find_id(hid_t id) -{ - H5I_type_t type; /*ID's type */ - H5I_id_type_t *type_ptr; /*ptr to the type */ - H5I_id_info_t *ret_value = NULL; /* Return value */ + /* Get object type */ + type = H5I_TYPE(obj_id); - FUNC_ENTER_STATIC_NOERR + /* Call internal function */ + if (H5I_FILE == type || H5I_DATATYPE == type || H5I_GROUP == type || H5I_DATASET == type || + H5I_ATTR == type) { + H5VL_object_t *vol_obj; /* Object of obj_id */ - /* Check arguments */ - 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) - - /* Check for same ID as we have looked up last time */ - if (type_ptr->last_info && type_ptr->last_info->id == id) - ret_value = type_ptr->last_info; - else { - /* Locate the ID node for the ID */ - ret_value = (H5I_id_info_t *)H5SL_search(type_ptr->ids, &id); + /* Get the VOL object */ + if (NULL == (vol_obj = H5VL_vol_object(obj_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier") - /* Remember this ID */ - type_ptr->last_info = ret_value; - } /* end else */ + /* Get the file ID */ + if ((ret_value = H5F_get_file_id(vol_obj, type, TRUE)) < 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_NOAPI(ret_value) -} /* end H5I__find_id() */ + FUNC_LEAVE_API(ret_value) +} /* end H5Iget_file_id() */ /*------------------------------------------------------------------------- * Function: H5Iget_name @@ -2168,10 +875,7 @@ done: * * Failure: -1 * - * NOTE: Not safe for arbitrary VOL connectors as it relies on - * private H5G calls. - * - * Comments: Public function + * Notes: * If 'name' is non-NULL then write up to 'size' bytes into that * buffer and always return the length of the entry name. * Otherwise 'size' is ignored and the function does not store the name, @@ -2186,9 +890,9 @@ done: ssize_t H5Iget_name(hid_t id, char *name /*out*/, size_t size) { - H5VL_object_t * vol_obj; /* Object of loc_id */ + H5VL_object_t * vol_obj = NULL; /* Object stored in ID */ H5VL_loc_params_t loc_params; - ssize_t ret_value; /* Return value */ + ssize_t ret_value = -1; /* Return value */ FUNC_ENTER_API((-1)) H5TRACE3("Zs", "ixz", id, name, size); @@ -2210,254 +914,4 @@ done: FUNC_LEAVE_API(ret_value) } /* end H5Iget_name() */ -/*------------------------------------------------------------------------- - * Function: H5Iget_file_id - * - * Purpose: Obtains the file ID given an object ID. The user has to - * close this ID. - * - * Return: Success: The file ID associated with the object - * - * Failure: H5I_INVALID_HID - * - *------------------------------------------------------------------------- - */ -hid_t -H5Iget_file_id(hid_t obj_id) -{ - H5I_type_t type; /* ID type */ - hid_t ret_value = H5I_INVALID_HID; /* Return value */ - - FUNC_ENTER_API(FAIL) - H5TRACE1("i", "i", obj_id); - - /* Get object type */ - type = H5I_TYPE(obj_id); - - /* Call internal function */ - if (H5I_FILE == type || H5I_DATATYPE == type || H5I_GROUP == type || H5I_DATASET == type || - H5I_ATTR == type) { - H5VL_object_t *vol_obj; /* Object of obj_id */ - - /* Get the VOL object */ - if (NULL == (vol_obj = H5VL_vol_object(obj_id))) - HGOTO_ERROR(H5E_ATOM, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier") - - /* Get the file ID */ - if ((ret_value = H5F_get_file_id(vol_obj, type, TRUE)) < 0) - HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, H5I_INVALID_HID, "can't retrieve file ID") - } /* end if */ - else - HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, H5I_INVALID_HID, "not an ID of a file object") - -done: - FUNC_LEAVE_API(ret_value) -} /* end H5Iget_file_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 * item = (H5I_id_info_t *)_item; /* Pointer to the ID node */ - 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 * obj_ptr = NULL; - int ret_value = H5_ITER_CONT; /* Return value */ - - FUNC_ENTER_STATIC_NOERR - - /* Sanity check */ - HDassert(item); - HDassert(udata); - - /* Get a pointer to the VOL connector's data */ - obj_ptr = H5I__unwrap(item->obj_ptr, type); - - /* Check for a match */ - if (obj_ptr == udata->object) { - udata->ret_id = item->id; - ret_value = H5_ITER_STOP; - } /* end if */ - - 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_id_type_t *type_ptr; /* Pointer to the type */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(FAIL) - - HDassert(id); - - *id = H5I_INVALID_HID; - - type_ptr = H5I_id_type_list_g[type]; - if (!type_ptr || type_ptr->init_count <= 0) - HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type") - - /* Only iterate through ID list if it is initialized and there are IDs in type */ - if (type_ptr->init_count > 0 && type_ptr->id_count > 0) { - H5I_get_id_ud_t udata; /* User data */ - herr_t iter_status; /* Iteration status */ - - /* 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 */ - if ((iter_status = H5SL_iterate(type_ptr->ids, H5I__find_id_cb, &udata)) < 0) - HGOTO_ERROR(H5E_ATOM, H5E_BADITER, FAIL, "iteration failed") - - *id = udata.ret_id; - } /* end if */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5I_find_id() */ - -/*------------------------------------------------------------------------- - * Function: H5I__id_dump_cb - * - * Purpose: Dump the contents of an ID to stderr for debugging. - * - * Return: H5_ITER_CONT (always) - * - *------------------------------------------------------------------------- - */ -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; /* Pointer to the ID node */ - H5I_type_t type = *(H5I_type_t *)_udata; /* User data */ - H5G_name_t * path = NULL; /* Path to file object */ - const void * obj_ptr = NULL; /* Pointer to VOL connector object */ - - FUNC_ENTER_STATIC_NOERR - - HDfprintf(stderr, " id = %" PRIdHID "\n", item->id); - HDfprintf(stderr, " count = %u\n", item->count); - HDfprintf(stderr, " obj = 0x%8p\n", item->obj_ptr); - - /* Get the group location, so we get get the name */ - switch (type) { - case H5I_GROUP: { - const H5VL_object_t *vol_obj = (const H5VL_object_t *)item->obj_ptr; - - obj_ptr = H5VL_object_data(vol_obj); - if (H5_VOL_NATIVE == vol_obj->connector->cls->value) - path = H5G_nameof((const H5G_t *)obj_ptr); - break; - } - - case H5I_DATASET: { - const H5VL_object_t *vol_obj = (const H5VL_object_t *)item->obj_ptr; - - obj_ptr = H5VL_object_data(vol_obj); - if (H5_VOL_NATIVE == vol_obj->connector->cls->value) - path = H5D_nameof((const H5D_t *)obj_ptr); - break; - } - - case H5I_DATATYPE: { - const H5T_t *dt = (const H5T_t *)item->obj_ptr; - - obj_ptr = (void *)H5T_get_actual_type((H5T_t *)dt); /* Casting away const OK - QAK */ - path = H5T_nameof((const H5T_t *)obj_ptr); - break; - } - - /* TODO: Maps will have to be added when they are supported in the - * native VOL connector. - */ - case H5I_MAP: - - case H5I_UNINIT: - case H5I_BADID: - case H5I_FILE: - case H5I_DATASPACE: - case H5I_ATTR: - case H5I_VFL: - case H5I_VOL: - case H5I_GENPROP_CLS: - case H5I_GENPROP_LST: - case H5I_ERROR_CLASS: - case H5I_ERROR_MSG: - case H5I_ERROR_STACK: - case H5I_SPACE_SEL_ITER: - case H5I_NTYPES: - default: - break; /* Other types of IDs are not stored in files */ - } - - 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) -} /* end H5I__id_dump_cb() */ - -/*------------------------------------------------------------------------- - * Function: H5I_dump_ids_for_type - * - * Purpose: Dump the contents of a type to stderr for debugging. - * - * Return: SUCCEED/FAIL - * - *------------------------------------------------------------------------- - */ -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) { - - /* Header */ - 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); - - /* List */ - 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) -} /* end H5I_dump_ids_for_type() */ diff --git a/src/H5Idbg.c b/src/H5Idbg.c new file mode 100644 index 0000000..3d6d401 --- /dev/null +++ b/src/H5Idbg.c @@ -0,0 +1,191 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * H5Idbg.c - Debugging 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 "H5Dprivate.h" /* Datasets */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Gprivate.h" /* Groups */ +#include "H5Ipkg.h" /* IDs */ +#include "H5RSprivate.h" /* Reference-counted strings */ +#include "H5SLprivate.h" /* Skip Lists */ +#include "H5Tprivate.h" /* Datatypes */ +#include "H5VLprivate.h" /* Virtual Object Layer */ + +/****************/ +/* Local Macros */ +/****************/ + +/******************/ +/* Local Typedefs */ +/******************/ + +/********************/ +/* Package Typedefs */ +/********************/ + +/********************/ +/* Local Prototypes */ +/********************/ + +static int H5I__id_dump_cb(void *_item, void *_key, void *_udata); + +/*********************/ +/* Package Variables */ +/*********************/ + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + +/*******************/ +/* Local Variables */ +/*******************/ + +/*------------------------------------------------------------------------- + * Function: H5I__id_dump_cb + * + * Purpose: Dump the contents of an ID to stderr for debugging. + * + * Return: H5_ITER_CONT (always) + * + *------------------------------------------------------------------------- + */ +static int +H5I__id_dump_cb(void *_item, void H5_ATTR_UNUSED *_key, void *_udata) +{ + H5I_id_info_t *info = (H5I_id_info_t *)_item; /* Pointer to the ID node */ + H5I_type_t type = *(H5I_type_t *)_udata; /* User data */ + H5G_name_t * path = NULL; /* Path to file object */ + const void * object = NULL; /* Pointer to VOL connector object */ + + FUNC_ENTER_STATIC_NOERR + + HDfprintf(stderr, " id = %" PRIdHID "\n", info->id); + HDfprintf(stderr, " count = %u\n", info->count); + HDfprintf(stderr, " obj = 0x%8p\n", info->object); + + /* Get the group location, so we get get the name */ + switch (type) { + case H5I_GROUP: { + const H5VL_object_t *vol_obj = (const H5VL_object_t *)info->object; + + object = H5VL_object_data(vol_obj); + if (H5_VOL_NATIVE == vol_obj->connector->cls->value) + path = H5G_nameof((const H5G_t *)object); + break; + } + + case H5I_DATASET: { + const H5VL_object_t *vol_obj = (const H5VL_object_t *)info->object; + + object = H5VL_object_data(vol_obj); + if (H5_VOL_NATIVE == vol_obj->connector->cls->value) + path = H5D_nameof((const H5D_t *)object); + break; + } + + case H5I_DATATYPE: { + const H5T_t *dt = (const H5T_t *)info->object; + + H5_GCC_DIAG_OFF("cast-qual") + object = (void *)H5T_get_actual_type((H5T_t *)dt); /* Casting away const OK - QAK */ + H5_GCC_DIAG_ON("cast-qual") + + path = H5T_nameof((const H5T_t *)object); + break; + } + + /* TODO: Maps will have to be added when they are supported in the + * native VOL connector. + */ + case H5I_MAP: + + case H5I_UNINIT: + case H5I_BADID: + case H5I_FILE: + case H5I_DATASPACE: + case H5I_ATTR: + case H5I_VFL: + case H5I_VOL: + case H5I_GENPROP_CLS: + case H5I_GENPROP_LST: + case H5I_ERROR_CLASS: + case H5I_ERROR_MSG: + case H5I_ERROR_STACK: + case H5I_SPACE_SEL_ITER: + case H5I_NTYPES: + default: + break; /* Other types of IDs are not stored in files */ + } + + 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) +} /* end H5I__id_dump_cb() */ + +/*------------------------------------------------------------------------- + * Function: H5I_dump_ids_for_type + * + * Purpose: Dump the contents of a type to stderr for debugging. + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5I_dump_ids_for_type(H5I_type_t type) +{ + H5I_type_info_t *type_info = NULL; + + FUNC_ENTER_NOAPI_NOERR + + HDfprintf(stderr, "Dumping ID type %d\n", (int)type); + type_info = H5I_type_info_array_g[type]; + + if (type_info) { + + /* Header */ + HDfprintf(stderr, " init_count = %u\n", type_info->init_count); + HDfprintf(stderr, " reserved = %u\n", type_info->cls->reserved); + HDfprintf(stderr, " id_count = %llu\n", (unsigned long long)type_info->id_count); + HDfprintf(stderr, " nextid = %llu\n", (unsigned long long)type_info->nextid); + + /* List */ + if (type_info->id_count > 0) { + HDfprintf(stderr, " List:\n"); + H5SL_iterate(type_info->ids, H5I__id_dump_cb, &type); + } + } + else + HDfprintf(stderr, "Global type info/tracking pointer for that type is NULL\n"); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5I_dump_ids_for_type() */ diff --git a/src/H5Iint.c b/src/H5Iint.c new file mode 100644 index 0000000..fa08253 --- /dev/null +++ b/src/H5Iint.c @@ -0,0 +1,1476 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. * + * 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 "H5SLprivate.h" /* Skip Lists */ +#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 htri_t H5I__clear_type_cb(void *_id, void *key, void *udata); +static void * H5I__remove_common(H5I_type_info_t *type_info, hid_t id); +static int H5I__find_id_cb(void *_item, void *_key, void *_udata); + +/*********************/ +/* Package Variables */ +/*********************/ + +/* Package initialization variable */ +hbool_t H5_PKG_INIT_VAR = FALSE; + +/* 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); + +/*****************************/ +/* 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 + + if (H5_PKG_INIT_VAR) { + 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->ids) + 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->ids); + type_info = H5MM_xfree(type_info); + H5I_type_info_array_g[i] = NULL; + in_use++; + } + } + + /* Mark interface closed */ + if (0 == in_use) + H5_PKG_INIT_VAR = FALSE; + } + } + + 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_ATOM, 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; + if (NULL == (type_info->ids = H5SL_create(H5SL_TYPE_HID, NULL))) + HGOTO_ERROR(H5E_ATOM, H5E_CANTCREATE, FAIL, "skip list creation failed") + } + + /* 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) { + if (type_info->ids) + H5SL_close(type_info->ids); + 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_STATIC_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 */ + 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_ATOM, H5E_BADGROUP, FAIL, "invalid type") + + /* Finish constructing udata */ + udata.force = force; + udata.app_ref = app_ref; + + /* Attempt to free all ids in the type */ + if (H5SL_try_free_safe(udata.type_info->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) +} /* end H5I_clear_type() */ + +/*------------------------------------------------------------------------- + * Function: H5I__clear_type_cb + * + * Purpose: Attempts to free the specified ID, calling the free + * function for the object. + * + * Return: TRUE/FALSE/FAIL + * + * Programmer: Neil Fortner + * Friday, July 10, 2015 + * + *------------------------------------------------------------------------- + */ +static htri_t +H5I__clear_type_cb(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 */ + htri_t ret_value = FALSE; /* Return value */ + + FUNC_ENTER_STATIC_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 for a 'free' function and call it, if it exists */ + H5_GCC_DIAG_OFF("cast-qual") + if (udata->type_info->cls->free_func && + (udata->type_info->cls->free_func)((void *)info->object) < 0) { /* (Casting away const OK -QAK) */ + 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 */ + ret_value = TRUE; + } + } + else { + /* Indicate node should be removed from list */ + ret_value = TRUE; + } + H5_GCC_DIAG_ON("cast-qual") + + /* Remove ID if requested */ + if (ret_value) { + /* Free ID info */ + info = H5FL_FREE(H5I_id_info_t, info); + + /* Decrement the number of IDs in the type */ + udata->type_info->id_count--; + } + } + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5I__clear_type_cb() */ + +/*------------------------------------------------------------------------- + * 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_ATOM, 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); + + if (H5SL_close(type_info->ids) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTCLOSEOBJ, FAIL, "can't close skip list") + type_info->ids = 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. + * + * 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_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_NOAPI(H5I_INVALID_HID) + + /* 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_ATOM, H5E_BADGROUP, H5I_INVALID_HID, "invalid type") + if (NULL == (info = H5FL_MALLOC(H5I_id_info_t))) + HGOTO_ERROR(H5E_ATOM, 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; + + /* Insert into the type */ + if (H5SL_insert(type_info->ids, info, &info->id) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTINSERT, H5I_INVALID_HID, "can't insert ID node into skip list") + 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_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_ATOM, 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_ATOM, H5E_BADGROUP, FAIL, "invalid type") + + /* Make sure requested ID belongs to object's type */ + if (H5I_TYPE(existing_id) != type) + HGOTO_ERROR(H5E_ATOM, H5E_BADRANGE, FAIL, "invalid type for provided ID") + + /* Allocate new structure to house this ID */ + if (NULL == (info = H5FL_MALLOC(H5I_id_info_t))) + HGOTO_ERROR(H5E_ATOM, 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; + + /* Insert into the type */ + if (H5SL_insert(type_info->ids, info, &info->id) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTINSERT, FAIL, "can't insert ID node into skip list") + 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_ATOM, H5E_NOTFOUND, NULL, "can't get ID ref count") + + /* Get the old object pointer to return */ + H5_GCC_DIAG_OFF("cast-qual") + ret_value = (void *)info->object; /* (Casting away const OK -QAK) */ + H5_GCC_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_DIAG_OFF("cast-qual") + ret_value = (void *)info->object; /* (Casting away const OK -QAK) */ + H5_GCC_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_DIAG_OFF("cast-qual") + ret_value = (void *)info->object; /* (Casting away const OK -QAK) */ + H5_GCC_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_STATIC_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_STATIC + + /* Sanity check */ + HDassert(type_info); + + /* Get the ID node for the ID */ + if (NULL == (info = (H5I_id_info_t *)H5SL_remove(type_info->ids, &id))) + HGOTO_ERROR(H5E_ATOM, H5E_CANTDELETE, NULL, "can't remove ID node from skip list") + + /* Check if this ID was the last one accessed */ + if (type_info->last_id_info == info) + type_info->last_id_info = NULL; + + H5_GCC_DIAG_OFF("cast-qual") + ret_value = (void *)info->object; /* (Casting away const OK -QAK) */ + H5_GCC_DIAG_ON("cast-qual") + + 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_ATOM, H5E_BADGROUP, NULL, "invalid type") + + /* Remove the node from the type */ + if (NULL == (ret_value = H5I__remove_common(type_info, id))) + HGOTO_ERROR(H5E_ATOM, H5E_CANTDELETE, NULL, "can't remove ID node") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5I_remove() */ + +/*------------------------------------------------------------------------- + * Function: H5I_dec_ref + * + * Purpose: Decrements the number of references outstanding for an ID. + * 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. + * + * Return: Success: New reference count + * + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +int +H5I_dec_ref(hid_t id) +{ + 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_ATOM, H5E_BADATOM, (-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_DIAG_OFF("cast-qual") + /* (Casting away const OK -QAK) */ + if (!type_info->cls->free_func || (type_info->cls->free_func)((void *)info->object) >= 0) { + /* Remove the node from the type */ + if (NULL == H5I__remove_common(type_info, id)) + HGOTO_ERROR(H5E_ATOM, H5E_CANTDELETE, (-1), "can't remove ID node") + ret_value = 0; + } + else + ret_value = -1; + H5_GCC_DIAG_ON("cast-qual") + } + else { + --(info->count); + ret_value = (int)info->count; + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5I_dec_ref() */ + +/*------------------------------------------------------------------------- + * Function: H5I_dec_app_ref + * + * Purpose: H5I_dec_ref 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) +{ + 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); + + /* Call regular decrement reference count routine */ + if ((ret_value = H5I_dec_ref(id)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTDEC, (-1), "can't decrement ID ref count") + + /* Check if the ID still exists */ + if (ret_value > 0) { + /* General lookup of the ID */ + if (NULL == (info = H5I__find_id(id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, (-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; + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5I_dec_app_ref() */ + +/*------------------------------------------------------------------------- + * Function: H5I_dec_app_ref_always_close + * + * Purpose: H5I_dec_app_ref 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); + + /* Call application decrement reference count routine */ + ret_value = H5I_dec_app_ref(id); + + /* 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_ATOM, H5E_CANTDEC, (-1), "can't decrement ID ref count") + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5I_dec_app_ref_always_close() */ + +/*------------------------------------------------------------------------- + * 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_ATOM, H5E_BADATOM, (-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_ATOM, H5E_BADATOM, (-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_STATIC + + /* 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_ATOM, 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_ATOM, 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_STATIC + + /* Sanity check */ + HDassert(type >= 0); + + /* Check arguments */ + type_info = H5I_type_info_array_g[type]; + if (!type_info) + HGOTO_ERROR(H5E_ATOM, 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_STATIC_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_DIAG_OFF("cast-qual") + object = H5I__unwrap((void *)info->object, type); /* Casting away const OK */ + H5_GCC_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 */ + herr_t iter_status; /* Iteration status */ + + /* 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 */ + if ((iter_status = H5SL_iterate(type_info->ids, H5I__iterate_cb, &iter_udata)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_BADITER, FAIL, "iteration failed") + } + +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 *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) + ret_value = type_info->last_id_info; + else { + /* Locate the ID node for the ID */ + ret_value = (H5I_id_info_t *)H5SL_search(type_info->ids, &id); + + /* Remember this ID */ + type_info->last_id_info = ret_value; + } + +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_STATIC_NOERR + + /* Sanity check */ + HDassert(info); + HDassert(udata); + + /* Get a pointer to the VOL connector's data */ + H5_GCC_DIAG_OFF("cast-qual") + object = H5I__unwrap((void *)info->object, type); /* Casting away const OK */ + H5_GCC_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_ATOM, 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 */ + herr_t iter_status; /* Iteration status */ + + /* 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 */ + if ((iter_status = H5SL_iterate(type_info->ids, H5I__find_id_cb, &udata)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_BADITER, FAIL, "iteration failed") + + *id = udata.ret_id; + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5I_find_id() */ + + diff --git a/src/H5Imodule.h b/src/H5Imodule.h index 4e08098..7fc6af0 100644 --- a/src/H5Imodule.h +++ b/src/H5Imodule.h @@ -11,18 +11,18 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Quincey Koziol - * Saturday, September 12, 2015 + * Programmer: Quincey Koziol + * Saturday, September 12, 2015 * - * Purpose: This file contains declarations which define macros for the - * H5I package. Including this header means that the source file - * is part of the H5I package. + * Purpose: This file contains declarations which define macros for the + * H5I package. Including this header means that the source file + * is part of the H5I package. */ #ifndef _H5Imodule_H #define _H5Imodule_H /* Define the proper control macros for the generic FUNC_ENTER/LEAVE and error - * reporting macros. + * reporting macros. */ #define H5I_MODULE #define H5_MY_PKG H5I diff --git a/src/H5Ipkg.h b/src/H5Ipkg.h index 25b4a97..7fc2668 100644 --- a/src/H5Ipkg.h +++ b/src/H5Ipkg.h @@ -30,13 +30,14 @@ #include "H5Iprivate.h" /* Other private headers needed by this file */ +#include "H5SLprivate.h" /* Skip Lists */ /**************************/ /* Package Private Macros */ /**************************/ /* - * Number of bits to use for ID Type in each atom. Increase if more types + * Number of bits to use for ID Type in each ID. Increase if more types * are needed (though this will decrease the number of available IDs per * type). This is the only number that must be changed since all other bit * field sizes and masks are calculated from TYPE_BITS. @@ -47,23 +48,62 @@ #define H5I_MAX_NUM_TYPES TYPE_MASK /* - * Number of bits to use for the Atom index in each atom (assumes 8-bit + * Number of bits to use for the ID index in each ID (assumes 8-bit * bytes). We don't use the sign bit. */ #define ID_BITS ((sizeof(hid_t) * 8) - (TYPE_BITS + 1)) #define ID_MASK (((hid_t)1 << ID_BITS) - 1) -/* Map an atom to an ID type number */ +/* Map an ID to an ID type number */ #define H5I_TYPE(a) ((H5I_type_t)(((hid_t)(a) >> ID_BITS) & TYPE_MASK)) /****************************/ /* Package Private Typedefs */ /****************************/ +/* ID information structure used */ +typedef struct H5I_id_info_t { + hid_t id; /* ID for this info */ + unsigned count; /* Ref. count for this ID */ + unsigned app_count; /* Ref. count of application visible IDs */ + const void *object; /* Pointer associated with the ID */ +} H5I_id_info_t; + +/* Type information structure used */ +typedef struct H5I_type_info_t { + const H5I_class_t *cls; /* Pointer to ID class */ + unsigned init_count; /* # of times this type has been initialized */ + uint64_t id_count; /* Current number of IDs held */ + uint64_t nextid; /* ID to use for the next object */ + H5I_id_info_t * last_id_info; /* Info for most recent ID looked up */ + H5SL_t * ids; /* Pointer to skip list that stores IDs */ +} H5I_type_info_t; + +/*****************************/ +/* Package Private Variables */ +/*****************************/ + +/* Array of pointers to ID types */ +H5_DLLVAR H5I_type_info_t *H5I_type_info_array_g[H5I_MAX_NUM_TYPES]; + +/* Variable to keep track of the number of types allocated. Its value is the */ +/* next type ID to be handed out, so it is always one greater than the number */ +/* of types. */ +/* Starts at 1 instead of 0 because it makes trace output look nicer. If more */ +/* types (or IDs within a type) are needed, adjust TYPE_BITS in H5Ipkg.h */ +/* and/or increase size of hid_t */ +H5_DLLVAR int H5I_next_type_g; + /******************************/ /* Package Private Prototypes */ /******************************/ +H5_DLL int H5I__destroy_type(H5I_type_t type); +H5_DLL void * H5I__remove_verify(hid_t id, H5I_type_t type); +H5_DLL int H5I__inc_type_ref(H5I_type_t type); +H5_DLL int H5I__get_type_ref(H5I_type_t type); +H5_DLL H5I_id_info_t *H5I__find_id(hid_t id); + /* Testing functions */ #ifdef H5I_TESTING H5_DLL ssize_t H5I__get_name_test(hid_t id, char *name /*out*/, size_t size, hbool_t *cached); diff --git a/src/H5Iprivate.h b/src/H5Iprivate.h index d4d1721..d8d80f9 100644 --- a/src/H5Iprivate.h +++ b/src/H5Iprivate.h @@ -42,7 +42,7 @@ /****************************/ typedef struct H5I_class_t { - H5I_type_t type_id; /* Class ID for the type */ + H5I_type_t type; /* Class "value" for the type */ unsigned flags; /* Class behavior flags */ unsigned reserved; /* Number of reserved IDs for this type */ /* [A specific number of type entries may be @@ -86,7 +86,7 @@ H5_DLL herr_t H5I_find_id(const void *object, H5I_type_t type, hid_t *id /*o /* Functions that manipulate objects */ H5_DLL void * H5I_object(hid_t id); -H5_DLL void * H5I_object_verify(hid_t id, H5I_type_t id_type); +H5_DLL void * H5I_object_verify(hid_t id, H5I_type_t type); H5_DLL void * H5I_remove(hid_t id); H5_DLL void * H5I_subst(hid_t id, const void *new_object); H5_DLL htri_t H5I_is_file_object(hid_t id); diff --git a/src/H5Ipublic.h b/src/H5Ipublic.h index a7c4961..cb234cf 100644 --- a/src/H5Ipublic.h +++ b/src/H5Ipublic.h @@ -54,7 +54,7 @@ typedef enum H5I_type_t { } H5I_type_t; /** - * Type of atoms to return to users + * Type of IDs to return to users */ typedef int64_t hid_t; @@ -130,13 +130,13 @@ H5_DLL hid_t H5Iregister(H5I_type_t type, const void *object); * \brief Returns the object referenced by an ID * * \param[in] id ID to be dereferenced - * \param[in] id_type The identifier type + * \param[in] type The identifier type * * \return Pointer to the object referenced by \p id on success, NULL on failure. * * \details H5Iobject_verify() returns a pointer to the memory referenced by id - * after verifying that \p id is of type \p id_type. This function is + * after verifying that \p id is of type \p type. This function is * analogous to dereferencing a pointer in C with type checking. * * \note H5Iobject_verify() does not change the ID it is called on in any way @@ -146,24 +146,24 @@ H5_DLL hid_t H5Iregister(H5I_type_t type, const void *object); * \see H5Iregister() * */ -H5_DLL void * H5Iobject_verify(hid_t id, H5I_type_t id_type); +H5_DLL void * H5Iobject_verify(hid_t id, H5I_type_t type); /** * \ingroup H5I * * \brief Removes an ID from its type * * \param[in] id The ID to be removed from its type - * \param[in] id_type The identifier type + * \param[in] type The identifier type * * \return Returns a pointer to the memory referred to by \p id on success, * NULL on failure. * - * \details H5Iremove_verify() first ensures that \p id belongs to \p id_type. + * \details H5Iremove_verify() first ensures that \p id belongs to \p type. * If so, it removes \p id from its type and returns the pointer * to the memory it referred to. This pointer is the same pointer that * was placed in storage by H5Iregister(). If id does not belong to - * \p id_type, then NULL is returned. + * \p type, then NULL is returned. * * The \p id parameter is the ID which is to be removed from its type. * @@ -176,7 +176,7 @@ H5_DLL void * H5Iobject_verify(hid_t id, H5I_type_t id_type); * to avoid memory leaks. * */ -H5_DLL void * H5Iremove_verify(hid_t id, H5I_type_t id_type); +H5_DLL void * H5Iremove_verify(hid_t id, H5I_type_t type); /** * \ingroup H5I * @@ -190,7 +190,7 @@ H5_DLL void * H5Iremove_verify(hid_t id, H5I_type_t id_type); * \p id. * * Valid types returned by the function are: - * \id_types + * \types * * If no valid type can be determined or the identifier submitted is * invalid, the function returns #H5I_BADID. diff --git a/src/H5Itest.c b/src/H5Itest.c index 83e0a84..21c9dac 100644 --- a/src/H5Itest.c +++ b/src/H5Itest.c @@ -11,10 +11,8 @@ * help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* Programmer: Quincey Koziol - * Tuesday, July 27, 2010 - * - * Purpose: ID testing functions. +/* + * H5Itest.c - ID testing functions */ /****************/ @@ -28,7 +26,6 @@ /* Headers */ /***********/ #include "H5private.h" /* Generic Functions */ -#include "H5ACprivate.h" /* Metadata cache */ #include "H5CXprivate.h" /* API Contexts */ #include "H5Eprivate.h" /* Error handling */ #include "H5Gprivate.h" /* Groups */ diff --git a/src/Makefile.am b/src/Makefile.am index f61b2a6..e18b0ae 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -77,7 +77,7 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5lib_settings.c H5system.c \ H5HG.c H5HGcache.c H5HGdbg.c H5HGquery.c \ H5HL.c H5HLcache.c H5HLdbg.c H5HLint.c H5HLprfx.c H5HLdblk.c \ H5HP.c \ - H5I.c H5Itest.c \ + H5I.c H5Idbg.c H5Iint.c H5Itest.c \ H5L.c H5Ldeprec.c H5Lexternal.c \ H5M.c \ H5MF.c H5MFaggr.c H5MFdbg.c H5MFsection.c \ -- cgit v0.12