diff options
author | James Laird <jlaird@hdfgroup.org> | 2004-06-18 16:56:04 (GMT) |
---|---|---|
committer | James Laird <jlaird@hdfgroup.org> | 2004-06-18 16:56:04 (GMT) |
commit | f249eed71d4b646bc57a43f28e32f3c2d9d71050 (patch) | |
tree | 831e79372ff27e582d5a1022e189a71d192256eb /src/H5I.c | |
parent | a83233a2c9f1fff24cffe02d4fa3fdaab3f92ff1 (diff) | |
download | hdf5-f249eed71d4b646bc57a43f28e32f3c2d9d71050.zip hdf5-f249eed71d4b646bc57a43f28e32f3c2d9d71050.tar.gz hdf5-f249eed71d4b646bc57a43f28e32f3c2d9d71050.tar.bz2 |
[svn-r8707] Changed the way HDF5 handles hid_t's and added API functions to allow users to register IDs and ID types at runtime.
Diffstat (limited to 'src/H5I.c')
-rw-r--r-- | src/H5I.c | 1258 |
1 files changed, 943 insertions, 315 deletions
@@ -16,13 +16,14 @@ * FILE: H5I.c - Internal storage routines for handling "IDs" * * REMARKS: ID's which allow objects (void *'s currently) to be bundled - * into "groups" for more general storage. + * into "types" for more general storage. * - * DESIGN: The groups are stored in an array of pointers to store each - * group in an element. Each "group" node contains a link to a - * hash table to manage the IDs in each group. The allowed - * "groups" are stored in an enum (called group_t) in - * H5Ipublic.h. + * 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 MAX_NUM_TYPES and are given out + * at run-time. Types used by the library are stored in global + * variables defined in H5Ipublic.h. * * AUTHOR: Quincey Koziol * @@ -30,6 +31,7 @@ * 1/3/96 - Starting writing specs & coding prototype * 1/7/96 - Finished coding prototype * 6/10/97 - Moved into HDF5 library + * 5/18/04 - Expanded to allow registration of new types at run-time */ #define H5I_PACKAGE /*suppress error about including H5Ipkg */ @@ -80,8 +82,8 @@ static int interface_initialize_g = 0; # define H5I_LOC(a,s) (((hid_t)(a)&ID_MASK)%(s)) #endif -/* Combine a Group number and an atom index into an atom */ -#define H5I_MAKE(g,i) ((((hid_t)(g)&GROUP_MASK)<<ID_BITS)| \ +/* 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 */ @@ -94,9 +96,9 @@ typedef struct H5I_id_info_t { struct H5I_id_info_t *next; /* link to next atom (in case of hash-clash)*/ } H5I_id_info_t; -/* ID group structure used */ +/* ID type structure used */ typedef struct { - unsigned count; /*# of times this group has been initialized*/ + unsigned count; /*# of times this type has been initialized*/ unsigned reserved; /*# of IDs to reserve for constant IDs */ unsigned wrapped; /*whether the id count has wrapped around */ size_t hash_size; /*sizeof the hash table to store the IDs in */ @@ -104,12 +106,21 @@ typedef struct { unsigned nextid; /*ID to use for the next atom */ H5I_free_t free_func; /*release object method */ H5I_id_info_t **id_list; /*pointer to an array of ptrs to IDs */ -} H5I_id_group_t; +} H5I_id_type_t; + /*-------------------- Locally scoped variables -----------------------------*/ -/* Array of pointers to atomic groups */ -static H5I_id_group_t *H5I_id_group_list_g[H5I_NGROUPS]; +/* Array of pointers to atomic types */ +static H5I_id_type_t *H5I_id_type_list_g[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 H5I_type_t H5I_next_type = (H5I_type_t) H5I_NTYPES; /* Declare a free list to manage the H5I_id_info_t struct */ H5FL_DEFINE_STATIC(H5I_id_info_t); @@ -120,7 +131,7 @@ static H5I_id_info_t *H5I_find_id(hid_t id); static hid_t H5I_get_file_id(hid_t obj_id); static int H5I_get_ref(hid_t id); #ifdef H5I_DEBUG_OUTPUT -static herr_t H5I_debug(H5I_type_t grp); +static herr_t H5I_debug(H5I_type_t type); #endif /* H5I_DEBUG_OUTPUT */ @@ -144,12 +155,6 @@ H5I_init_interface(void) { FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5I_init_interface); - /* - * Make certain the ID types don't overflow the number of bits allocated - * for them in an ID. - */ - assert(H5I_NGROUPS<=(1<<GROUP_BITS)); - FUNC_LEAVE_NOAPI(SUCCEED); } @@ -159,7 +164,7 @@ H5I_init_interface(void) * * Purpose: Terminate the H5I interface: release all memory, reset all * global variables to initial values. This only happens if all - * groups have been destroyed from other interfaces. + * types have been destroyed from other interfaces. * * Return: Success: Positive if any action was taken that might * affect some other interface; zero otherwise. @@ -175,25 +180,25 @@ H5I_init_interface(void) int H5I_term_interface(void) { - H5I_id_group_t *grp_ptr; - H5I_type_t grp; + H5I_id_type_t *type_ptr; + H5I_type_t type; int n=0; FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5I_term_interface); if (interface_initialize_g) { - /* How many groups are still being used? */ - for (grp=(H5I_type_t)0; grp<H5I_NGROUPS; H5_INC_ENUM(H5I_type_t,grp)) { - if ((grp_ptr=H5I_id_group_list_g[grp]) && grp_ptr->id_list) + /* How many types are still being used? */ + for (type=(H5I_type_t)0; type<H5I_next_type; H5_INC_ENUM(H5I_type_t,type)) { + if ((type_ptr=H5I_id_type_list_g[type]) && type_ptr->id_list) n++; } - /* If no groups are used then clean up */ + /* If no types are used then clean up */ if (0==n) { - for (grp=(H5I_type_t)0; grp<H5I_NGROUPS; H5_INC_ENUM(H5I_type_t,grp)) { - grp_ptr = H5I_id_group_list_g[grp]; - H5MM_xfree(grp_ptr); - H5I_id_group_list_g[grp] = NULL; + for (type=(H5I_type_t)0; type<H5I_next_type; H5_INC_ENUM(H5I_type_t,type)) { + type_ptr = H5I_id_type_list_g[type]; + H5MM_xfree(type_ptr); + H5I_id_type_list_g[type] = NULL; } } @@ -202,31 +207,69 @@ H5I_term_interface(void) } FUNC_LEAVE_NOAPI(n); } - - /*------------------------------------------------------------------------- - * Function: H5I_init_group - * - * Purpose: Initialize an ID group whose ID number is specified by GRP, - * If the group has already been initialized, this routine just - * increments the count of number of initializations and returns - * without trying to change the size of the hash table. A - * specific number (RESERVED) of group entries may be reserved - * to enable "constant" values to be handed out which are valid - * IDs in the group, but which do not map to any data structures - * and are not allocated dynamicly later. HASH_SIZE is the - * minimum hash table size to use for the group. FREE_FUNC is + * Function: H5Iregister_type + * + * Purpose: Public interface to H5I_register_type. Creates a new type + * of ID's to give out. A specific number (RESERVED) of type + * entries may be reserved to enable "constant" values to be handed + * out which are valid IDs in the type, but which do not map to any + * data structures and are not allocated dynamically later. HASH_SIZE is + * the minimum hash table size to use for the type. FREE_FUNC is * called with an object pointer when the object is removed from - * the group. + * the type. * - * Return: Success: Non-negative + * Return: Success: Type ID of the new type * - * Failure: Negative + * Failure: H5I_BADID * - * Programmer: Robb Matzke - * Friday, February 19, 1999 + * Programmers: Nathaniel Furrer + * James Laird + * Friday, April 30, 2004 * * Modifications: + * + *------------------------------------------------------------------------- + */ +H5I_type_t H5Iregister_type(size_t hash_size, unsigned reserved, H5I_free_t free_func) +{ + H5I_type_t ret_value; + FUNC_ENTER_API(H5Iregister_type, H5I_BADID); + + /* Call H5I_register_type with a value of 0 to get a new type */ + ret_value = H5I_register_type(0, hash_size, reserved, free_func); + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5I_register_type + * + * Purpose: Creates a new type of ID's to give out. A specific number + * (RESERVED) of type entries may be reserved to enable "constant" + * values to be handed out which are valid IDs in the type, but + * which do not map to any data structures and are not allocated + * dynamically later. TYPE_ID is the H5I_type_t value of the type + * to be initialized. If this value is zero, a new type is created. + * If this value is one of the library types, that type is + * initialized or its reference count is incremented (if it is already + * initialized). HASH_SIZE is the minimum hash table size to + * use for the type. FREE_FUNC is called with an object pointer + * when the object is removed from the type. + * + * Return: Success: Type ID of the new type + * Failure: H5I_BADID + * + * Programmers: Nathaniel Furrer + * James Laird + * Friday, April 30, 2004 + * + * Modifications: The initialization section of this function was formerly + * H5I_init_type, programmed by Robb Matzke on February 19, + * 1999. + * * Bill Wendling, 2000-05-05 * Instead of the ugly test of whether hash_size is a power of * two, I placed it in a macro POWER_OF_TWO which uses the fact @@ -238,68 +281,142 @@ H5I_term_interface(void) * *------------------------------------------------------------------------- */ -int -H5I_init_group(H5I_type_t grp, size_t hash_size, unsigned reserved, - H5I_free_t free_func) + +H5I_type_t H5I_register_type(H5I_type_t type_id, size_t hash_size, unsigned reserved, H5I_free_t free_func) { - H5I_id_group_t *grp_ptr = NULL; /*ptr to the atomic group*/ - int ret_value = SUCCEED; /*return value */ + H5I_type_t ret_value; /* type ID to return */ + H5I_id_type_t *type_ptr = NULL; /*ptr to the atomic type*/ + int i; + int done; + + FUNC_ENTER_NOAPI(H5I_register_type, H5I_BADID); - FUNC_ENTER_NOAPI(H5I_init_group, FAIL); + /* Check that type_id is either a library type or zero */ + if(type_id < 0 || type_id >= H5I_NTYPES) + { + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, H5I_BADID, "invalid type ID"); + } + + if(type_id == 0) /* Generate a new H5I_type_t value */ + { + /* Increment the number of types*/ + if (H5I_next_type < MAX_NUM_TYPES) + { + ret_value = H5I_next_type; + H5I_next_type++; + } + else + { + done = 0; + /* Look for a free type to give out */ + for(i = H5I_NTYPES; i < MAX_NUM_TYPES && done==0; i++) + { + if(H5I_id_type_list_g[i] == NULL) + { + /* Found a free type ID */ + ret_value = i; + done = 1; + } + } + + /* Verify that we found a type to give out */ + if(done == 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5I_BADID, "Maximum number of ID types exceeded."); + } + } + else /* type_id is a library type; use this value. */ + { + ret_value = type_id; + } + + /* Initialize the type */ /* Check arguments */ - if ((grp <= H5I_BADID || grp >= H5I_NGROUPS) && hash_size > 0) - HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid group number"); #ifdef HASH_SIZE_POWER_2 if (!POWER_OF_TWO(hash_size) || hash_size == 1) - HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid hash size"); + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, H5I_BADID, "invalid hash size"); #endif /* HASH_SIZE_POWER_2 */ - if (H5I_id_group_list_g[grp] == NULL) { - /* Allocate the group information for new group */ - if (NULL==(grp_ptr = H5MM_calloc(sizeof(H5I_id_group_t)))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - H5I_id_group_list_g[grp] = grp_ptr; + if (H5I_id_type_list_g[ret_value] == NULL) { + /* Allocate the type information for new type */ + if (NULL==(type_ptr = H5MM_calloc(sizeof(H5I_id_type_t)))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, H5I_BADID, "memory allocation failed"); + H5I_id_type_list_g[ret_value] = type_ptr; } else { - /* Get the pointer to the existing group */ - grp_ptr = H5I_id_group_list_g[grp]; + /* Get the pointer to the existing type */ + type_ptr = H5I_id_type_list_g[ret_value]; } - if (grp_ptr->count == 0) { - /* Initialize the ID group structure for new groups */ - grp_ptr->hash_size = hash_size; - grp_ptr->reserved = reserved; - grp_ptr->wrapped = 0; - grp_ptr->ids = 0; - grp_ptr->nextid = reserved; - grp_ptr->free_func = free_func; - grp_ptr->id_list = H5MM_calloc(hash_size*sizeof(H5I_id_info_t *)); - if (NULL==grp_ptr->id_list) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + if (type_ptr->count == 0) { + /* Initialize the ID type structure for new types */ + type_ptr->hash_size = hash_size; + type_ptr->reserved = reserved; + type_ptr->wrapped = 0; + type_ptr->ids = 0; + type_ptr->nextid = reserved; + type_ptr->free_func = free_func; + type_ptr->id_list = H5MM_calloc(hash_size*sizeof(H5I_id_info_t *)); + if (NULL==type_ptr->id_list) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, H5I_BADID, "memory allocation failed"); } - - /* Increment the count of the times this group has been initialized */ - grp_ptr->count++; -done: - if (ret_value<0) { - /* Error condition cleanup */ - if (grp_ptr != NULL) { - H5MM_xfree(grp_ptr->id_list); - H5MM_xfree(grp_ptr); + /* Increment the count of the times this type has been initialized */ + type_ptr->count++; + + done: + if(ret_value == H5I_BADID) /* Clean up on error */ + { + if (type_ptr != NULL) + { + H5MM_xfree(type_ptr->id_list); + H5MM_xfree(type_ptr); + } } - } - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value); } - +/*------------------------------------------------------------------------- + * Function: H5Inmembers + * + * Purpose: Returns the number of members in a type. Public interface to + * H5I_nmembers. + * + * Return: Success: Number of members; zero if the type is empty + * or has been deleted. + * + * Failure: Negative + * + * Programmer: James Laird + * Nathaniel Furrer + * Friday, April 23, 2004 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +int H5Inmembers(H5I_type_t type) +{ + int ret_value; /* Return value */ + + FUNC_ENTER_API(H5Inmembers, FAIL); + + if( H5I_IS_LIB_TYPE( type ) ) + { + HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type"); + } + + ret_value = H5I_nmembers(type); + + done: + FUNC_LEAVE_API(ret_value); +} /*------------------------------------------------------------------------- * Function: H5I_nmembers * - * Purpose: Returns the number of members in a group. + * Purpose: Returns the number of members in a type. * - * Return: Success: Number of members; zero if the group is empty + * Return: Success: Number of members; zero if the type is empty * or has been deleted. * * Failure: Negative @@ -312,9 +429,9 @@ done: *------------------------------------------------------------------------- */ int -H5I_nmembers(H5I_type_t grp) +H5I_nmembers(H5I_type_t type) { - H5I_id_group_t *grp_ptr = NULL; + H5I_id_type_t *type_ptr = NULL; H5I_id_info_t *cur=NULL; int n=0; unsigned i; @@ -322,13 +439,13 @@ H5I_nmembers(H5I_type_t grp) FUNC_ENTER_NOAPI(H5I_nmembers, FAIL); - if (grp<=H5I_BADID || grp>=H5I_NGROUPS) - HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid group number"); - if (NULL==(grp_ptr=H5I_id_group_list_g[grp]) || grp_ptr->count<=0) + if (type<=H5I_BADID || 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->count<=0) HGOTO_DONE(0); - for (i=0; i<grp_ptr->hash_size; i++) - for (cur=grp_ptr->id_list[i]; cur; cur=cur->next) + for (i=0; i<type_ptr->hash_size; i++) + for (cur=type_ptr->id_list[i]; cur; cur=cur->next) n++; /* Set return value */ @@ -338,11 +455,45 @@ done: FUNC_LEAVE_NOAPI(ret_value); } - /*------------------------------------------------------------------------- - * Function: H5I_clear_group + * Function: H5Iclear_type * - * Purpose: Removes all objects from the group, calling the free + * Purpose: Removes all objects from the type, calling the free + * function for each object regardless of the reference count. + * Public interface to H5I_clear_type. + * + * Return: Success: Non-negative + * + * Failure: negative + * + * Programmer: James Laird + * Nathaniel Furrer + * Friday, April 23, 2004 + * + * Modifications: + *------------------------------------------------------------------------- + */ +herr_t H5Iclear_type(H5I_type_t type, hbool_t force) +{ + herr_t ret_value; /* Return value */ + + FUNC_ENTER_API(H5Iclear_type, FAIL); + + if( H5I_IS_LIB_TYPE( type ) ) + { + HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type"); + } + + ret_value = H5I_clear_type(type, force); + + done: + FUNC_LEAVE_API(ret_value); +} + +/*------------------------------------------------------------------------- + * Function: H5I_clear_type + * + * Purpose: Removes all objects from the type, calling the free * function for each object regardless of the reference count. * * Return: Success: Non-negative @@ -368,9 +519,9 @@ done: *------------------------------------------------------------------------- */ herr_t -H5I_clear_group(H5I_type_t grp, hbool_t force) +H5I_clear_type(H5I_type_t type, hbool_t force) { - H5I_id_group_t *grp_ptr = NULL; /* ptr to the atomic group */ + H5I_id_type_t *type_ptr = NULL; /* ptr to the atomic type */ H5I_id_info_t *cur=NULL; /* Current node being worked with */ H5I_id_info_t *next=NULL; /* Next node in list */ H5I_id_info_t *last=NULL; /* Last node seen */ @@ -379,22 +530,22 @@ H5I_clear_group(H5I_type_t grp, hbool_t force) unsigned delete_node; /* Flag to indicate node should be removed from linked list */ unsigned i; - FUNC_ENTER_NOAPI(H5I_clear_group, FAIL); + FUNC_ENTER_NOAPI(H5I_clear_type, FAIL); - if (grp <= H5I_BADID || grp >= H5I_NGROUPS) - HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid group number"); + if (type <= H5I_BADID || type >= H5I_next_type) + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number"); - grp_ptr = H5I_id_group_list_g[grp]; - if (grp_ptr == NULL || grp_ptr->count <= 0) - HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid group"); + type_ptr = H5I_id_type_list_g[type]; + if (type_ptr == NULL || type_ptr->count <= 0) + HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type"); /* - * Call free method for all objects in group regardless of their reference + * Call free method for all objects in type regardless of their reference * counts. Ignore the return value from from the free method and remove - * object from group regardless if FORCE is non-zero. + * object from type regardless if FORCE is non-zero. */ - for (i=0; i<grp_ptr->hash_size; i++) { - for (cur=grp_ptr->id_list[i]; cur; cur=next) { + for (i=0; i<type_ptr->hash_size; i++) { + for (cur=type_ptr->id_list[i]; cur; cur=next) { /* * Do nothing to the object if the reference count is larger than * one and forcing is off. @@ -405,12 +556,12 @@ H5I_clear_group(H5I_type_t grp, hbool_t force) } /* end if */ /* Check for a 'free' function and call it, if it exists */ - if (grp_ptr->free_func && (grp_ptr->free_func)(cur->obj_ptr)<0) { + if (type_ptr->free_func && (type_ptr->free_func)(cur->obj_ptr)<0) { if (force) { #ifdef H5I_DEBUG if (H5DEBUG(I)) { - fprintf(H5DEBUG(I), "H5I: free grp=%d obj=0x%08lx " - "failure ignored\n", (int)grp, + fprintf(H5DEBUG(I), "H5I: free type=%d obj=0x%08lx " + "failure ignored\n", (int)type, (unsigned long)(cur->obj_ptr)); } /* end if */ #endif /*H5I_DEBUG*/ @@ -430,8 +581,8 @@ H5I_clear_group(H5I_type_t grp, hbool_t force) /* Check if we should delete this node or not */ if(delete_node) { - /* Decrement the number of IDs in the group */ - (grp_ptr->ids)--; + /* Decrement the number of IDs in the type */ + (type_ptr->ids)--; /* Advance to next node */ next = cur->next; @@ -442,7 +593,7 @@ H5I_clear_group(H5I_type_t grp, hbool_t force) /* make an H5I call, which could potentially change the */ /* order of the nodes on the list - QAK) */ last=NULL; - tmp=grp_ptr->id_list[i]; + tmp=type_ptr->id_list[i]; while(tmp!=cur) { assert(tmp!=NULL); last=tmp; @@ -452,8 +603,8 @@ H5I_clear_group(H5I_type_t grp, hbool_t force) /* Delete the node from the list */ if(last==NULL) { /* Node at head of list, just advance the list head to next node */ - assert(grp_ptr->id_list[i]==cur); - grp_ptr->id_list[i] = next; + assert(type_ptr->id_list[i]==cur); + type_ptr->id_list[i] = next; } /* end if */ else { /* Node in middle of list, jump over it */ @@ -475,71 +626,126 @@ done: FUNC_LEAVE_NOAPI(ret_value); } - /*------------------------------------------------------------------------- - * Function: H5I_destroy_group + * Function: H5Idestroy_type * - * Purpose: Decrements the reference count on an entire group of IDs. - * If the group reference count becomes zero then the group is - * destroyed along with all atoms in that group 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. + * 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. Public + * interface to H5I_destroy_type. * - * Return: Non-negative on success/Negative on failure + * Return: Zero on success/Negative on failure * - * Programmer: Unknown + * Programmer: Nathaniel Furrer + * James Laird * * Modifications: * - * Robb Matzke, 25 Feb 1998 - * IDs are freed when a group is destroyed. + *------------------------------------------------------------------------- + */ +herr_t H5Idestroy_type(H5I_type_t type) +{ + herr_t ret_value; + + FUNC_ENTER_API(H5Idestroy_type, FAIL); + + if( H5I_IS_LIB_TYPE( type ) ) + { + HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type"); + } + + ret_value = H5I_destroy_type(type); + + done: + FUNC_LEAVE_API(ret_value); +} + +/*------------------------------------------------------------------------- + * 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: Zero on success/Negative on failure + * + * Programmer: Nathaniel Furrer + * James Laird + * + * Modifications: * *------------------------------------------------------------------------- */ -herr_t -H5I_destroy_group(H5I_type_t grp) +herr_t H5I_destroy_type(H5I_type_t type) { - H5I_id_group_t *grp_ptr = NULL; /* ptr to the atomic group */ - int ret_value = SUCCEED; + herr_t ret_value = FAIL; + H5I_id_type_t *type_ptr = NULL; /* ptr to the atomic type */ - FUNC_ENTER_NOAPI(H5I_destroy_group, FAIL); + FUNC_ENTER_NOAPI(H5I_destroy_type, FAIL); - if (grp <= H5I_BADID || grp >= H5I_NGROUPS) - HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid group number"); - - grp_ptr = H5I_id_group_list_g[grp]; - if (grp_ptr == NULL || grp_ptr->count <= 0) - HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid group"); + if (type <= H5I_BADID || type >= H5I_next_type) + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number"); - /* - * Decrement the number of users of the atomic group. If this is the - * last user of the group then release all atoms from the group. The - * free function is invoked for each atom being freed. - */ - if (1==grp_ptr->count) { - H5I_clear_group(grp, TRUE); - H5E_clear(NULL); /*don't care about errors*/ - H5MM_xfree(grp_ptr->id_list); - HDmemset (grp_ptr, 0, sizeof(*grp_ptr)); - } else { - --(grp_ptr->count); - } - - done: - FUNC_LEAVE_NOAPI(ret_value); + type_ptr = H5I_id_type_list_g[type]; + if (type_ptr == NULL || type_ptr->count <= 0) + HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type"); + + H5I_clear_type(type, TRUE); + H5E_clear(NULL); /*don't care about errors*/ + H5MM_xfree(type_ptr->id_list); + + H5MM_free(type_ptr); + H5I_id_type_list_g[type] = NULL; + ret_value = 0; + +done: + FUNC_LEAVE_NOAPI(ret_value); +} + +/*------------------------------------------------------------------------- + * Function: H5Iregister + * + * Purpose: Public interface to H5I_register. + * + * Return: Success: New object id. + * + * Failure: Negative + * + * Programmer: Nathaniel Furrer + * James Laird + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +hid_t H5Iregister(H5I_type_t type, void *object) +{ + hid_t ret_value; /* Return value */ + + FUNC_ENTER_API(H5Iregister, H5I_INVALID_HID); + + if( H5I_IS_LIB_TYPE( type ) ) + { + HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type"); + } + + ret_value = H5I_register(type, object); + + done: + FUNC_LEAVE_API(ret_value); } - /*------------------------------------------------------------------------- * Function: H5I_register * - * Purpose: Registers an OBJECT in a GROUP and returns an ID for it. + * 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 - * group is unique. IDs are created by getting a unique number - * for the group the ID is in and incorporating the group into + * 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. @@ -553,9 +759,9 @@ H5I_destroy_group(H5I_type_t grp) *------------------------------------------------------------------------- */ hid_t -H5I_register(H5I_type_t grp, void *object) +H5I_register(H5I_type_t type, void *object) { - H5I_id_group_t *grp_ptr=NULL; /*ptr to the group */ + 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; /*new ID */ unsigned hash_loc; /*new item's hash table location*/ @@ -567,61 +773,61 @@ H5I_register(H5I_type_t grp, void *object) FUNC_ENTER_NOAPI(H5I_register, FAIL); /* Check arguments */ - if (grp <= H5I_BADID || grp >= H5I_NGROUPS) - HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid group number"); - grp_ptr = H5I_id_group_list_g[grp]; - if (grp_ptr == NULL || grp_ptr->count <= 0) - HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid group"); + if (type <= H5I_BADID || 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->count <= 0) + HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type"); if ((id_ptr = H5FL_MALLOC(H5I_id_info_t)) == NULL) HGOTO_ERROR(H5E_ATOM, H5E_NOSPACE, FAIL, "memory allocation failed"); /* Create the struct & it's ID */ - new_id = H5I_MAKE(grp, grp_ptr->nextid); + new_id = H5I_MAKE(type, type_ptr->nextid); id_ptr->id = new_id; id_ptr->count = 1; /*initial reference count*/ id_ptr->obj_ptr = object; id_ptr->next = NULL; /* hash bucket already full, prepend to front of chain */ - hash_loc = grp_ptr->nextid % (unsigned) grp_ptr->hash_size; - if (grp_ptr->id_list[hash_loc] != NULL) - id_ptr->next = grp_ptr->id_list[hash_loc]; + hash_loc = type_ptr->nextid % (unsigned) type_ptr->hash_size; + if (type_ptr->id_list[hash_loc] != NULL) + id_ptr->next = type_ptr->id_list[hash_loc]; - /* Insert into the group */ - grp_ptr->id_list[hash_loc] = id_ptr; - grp_ptr->ids++; - grp_ptr->nextid++; + /* Insert into the type */ + type_ptr->id_list[hash_loc] = id_ptr; + type_ptr->ids++; + type_ptr->nextid++; /* * This next section of code checks for the 'nextid' getting too large and * wrapping around, thus necessitating checking for duplicate IDs being * handed out. */ - if (grp_ptr->nextid > (unsigned)ID_MASK) { - grp_ptr->wrapped = 1; - grp_ptr->nextid = grp_ptr->reserved; + if (type_ptr->nextid > (unsigned)ID_MASK) { + type_ptr->wrapped = 1; + type_ptr->nextid = type_ptr->reserved; } /* * If we've wrapped around then we need to check for duplicate id's being * handed out. */ - if (grp_ptr->wrapped) { + if (type_ptr->wrapped) { /* * Make sure we check all available ID's. If we're about at the end * of the range then wrap around and check the beginning values. If * we check all possible values and didn't find any free ones *then* * we can fail. */ - for (i=grp_ptr->reserved; i<ID_MASK; i++) { + for (i=type_ptr->reserved; i<ID_MASK; i++) { /* Handle end of range by wrapping to beginning */ - if (grp_ptr->nextid>(unsigned)ID_MASK) - grp_ptr->nextid = grp_ptr->reserved; + if (type_ptr->nextid>(unsigned)ID_MASK) + type_ptr->nextid = type_ptr->reserved; /* new ID to check for */ - next_id = H5I_MAKE(grp, grp_ptr->nextid); - hash_loc = H5I_LOC (grp_ptr->nextid, grp_ptr->hash_size); - curr_id = grp_ptr->id_list[hash_loc]; + next_id = H5I_MAKE(type, type_ptr->nextid); + hash_loc = H5I_LOC (type_ptr->nextid, type_ptr->hash_size); + curr_id = type_ptr->id_list[hash_loc]; if (curr_id == NULL) break; /* Ha! this is not likely... */ @@ -632,12 +838,12 @@ H5I_register(H5I_type_t grp, void *object) } if (!curr_id) break; /* must not have found a match */ - grp_ptr->nextid++; + type_ptr->nextid++; } if (i>=(unsigned)ID_MASK) /* All the IDs are gone! */ - HGOTO_ERROR(H5E_ATOM, H5E_NOIDS, FAIL, "no IDs available in group"); + HGOTO_ERROR(H5E_ATOM, H5E_NOIDS, FAIL, "no IDs available in type"); } ret_value = new_id; @@ -680,12 +886,48 @@ done: FUNC_LEAVE_NOAPI(ret_value); } - +/*------------------------------------------------------------------------- + * Function: H5Iobject_verify + * + * Purpose: Find an object pointer for the specified ID, verifying that + * its in a particular type. Public interface to + * H5I_object_verify. + * + * Return: Success: Non-null object pointer associated with the + * specified ID. + * + * Failure: NULL + * + * Programmer: Nathaniel Furrer + * James Laird + * Friday, April 23, 2004 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void *H5Iobject_verify(hid_t id, H5I_type_t id_type) +{ + void * ret_value; /* Return value */ + + FUNC_ENTER_API(H5Iobject_verify, NULL); + + if( H5I_IS_LIB_TYPE( id_type ) ) + { + HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "cannot call public function on library type"); + } + + ret_value = H5I_object_verify(id, id_type); + + done: + FUNC_LEAVE_API(ret_value); +} + /*------------------------------------------------------------------------- * Function: H5I_object_verify * * Purpose: Find an object pointer for the specified ID, verifying that - * its in a particular group. + * its in a particular type. * * Return: Success: Non-null object pointer associated with the * specified ID. @@ -707,10 +949,10 @@ H5I_object_verify(hid_t id, H5I_type_t id_type) FUNC_ENTER_NOAPI(H5I_object_verify, NULL); - assert(id_type>=H5I_FILE && id_type<H5I_NGROUPS); + assert(id_type>=1 && id_type<H5I_next_type); - /* Verify that the group of the ID is correct & lookup the ID */ - if(id_type == H5I_GRP(id) && NULL!=(id_ptr = H5I_find_id(id))) { + /* 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 = id_ptr->obj_ptr; } /* end if */ @@ -723,12 +965,12 @@ done: /*------------------------------------------------------------------------- * Function: H5I_get_type * - * Purpose: Given an object ID return the group (type) to which it + * 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 group number (type) is encoded + * currently exists because the type number is encoded * in the object ID. * - * Return: Success: A valid group number (type) + * Return: Success: A valid type number * * Failure: H5I_BADID, a negative value. * @@ -747,9 +989,9 @@ H5I_get_type(hid_t id) FUNC_ENTER_NOAPI(H5I_get_type, H5I_BADID); if (id>0) - ret_value = H5I_GRP(id); + ret_value = H5I_TYPE(id); - assert(ret_value>=H5I_BADID && ret_value<H5I_NGROUPS); + assert(ret_value>=H5I_BADID && ret_value<H5I_next_type); done: FUNC_LEAVE_NOAPI(ret_value); @@ -759,12 +1001,12 @@ done: /*------------------------------------------------------------------------- * Function: H5Iget_type * - * Purpose: The public version of H5I_get_type(), obtains a group number - * (type) when given an ID. The ID need not be the ID of an - * object which currently exists because the group number is + * Purpose: The public version of H5I_get_type(), obtains a type number + * when given an ID. The ID need not be the ID of an + * object which currently exists because the type number is * encoded as part of the ID. * - * Return: Success: Group number (type) + * Return: Success: Type number * * Failure: H5I_BADID, a negative value * @@ -772,7 +1014,7 @@ done: * * Modifications: * Robb Matzke, 1999-08-23 - * Also fails if the ID has a valid group but no longer exists + * Also fails if the ID has a valid type but no longer exists * in the ID tables. *------------------------------------------------------------------------- */ @@ -786,7 +1028,7 @@ H5Iget_type(hid_t id) ret_value = H5I_get_type(id); - if (ret_value <= H5I_BADID || ret_value >= H5I_NGROUPS || NULL==H5I_object(id)) + if (ret_value <= H5I_BADID || ret_value >= H5I_next_type || NULL==H5I_object(id)) HGOTO_DONE(H5I_BADID); done: @@ -849,47 +1091,120 @@ H5I_get_file_id(hid_t obj_id) { H5G_entry_t *ent; hid_t ret_value; + H5I_type_t type; FUNC_ENTER_NOAPI_NOINIT(H5I_get_file_id); /* Get object type */ - switch(H5I_GRP(obj_id)) { - case H5I_FILE: - ret_value = obj_id; - - /* Increment reference count on atom. */ - if (H5I_inc_ref(ret_value)<0) - HGOTO_ERROR (H5E_ATOM, H5E_CANTSET, FAIL, "incrementing file ID failed"); + type = H5I_TYPE(obj_id); + if(type == H5I_FILE) + { + ret_value = obj_id; + + /* Increment reference count on atom. */ + if (H5I_inc_ref(ret_value)<0) + HGOTO_ERROR (H5E_ATOM, H5E_CANTSET, FAIL, "incrementing file ID failed"); + } + else if(type == H5I_DATATYPE) + { + if((ent = H5G_loc(obj_id))==NULL) + HGOTO_ERROR (H5E_ATOM, H5E_CANTGET, FAIL, "not a named datatype"); + ret_value = H5F_get_id(ent->file); + } + else if(type == H5I_GROUP || type == H5I_DATASET || type == H5I_ATTR) + { + if((ent = H5G_loc(obj_id))==NULL) + HGOTO_ERROR (H5E_ATOM, H5E_CANTGET, FAIL, "can't get symbol table info"); + ret_value = H5F_get_id(ent->file); + } + else + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid object ID"); - break; +done: + FUNC_LEAVE_NOAPI(ret_value); +} - case H5I_DATATYPE: - if((ent = H5G_loc(obj_id))==NULL) - HGOTO_ERROR (H5E_ATOM, H5E_CANTGET, FAIL, "not a named datatype"); - ret_value = H5F_get_id(ent->file); - break; +/*------------------------------------------------------------------------- + * Function: H5Iremove_verify + * + * Purpose: Removes the specified ID from its type, first checking that the + * type of the ID and the type type are the same. Public interface to + * H5I_remove_verify. + * + * 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 + * Nathaniel Furrer + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void *H5Iremove_verify(hid_t id, H5I_type_t id_type) +{ + void * ret_value; /* Return value */ - case H5I_GROUP: - case H5I_DATASET: - case H5I_ATTR: - if((ent = H5G_loc(obj_id))==NULL) - HGOTO_ERROR (H5E_ATOM, H5E_CANTGET, FAIL, "can't get symbol table info"); - ret_value = H5F_get_id(ent->file); - break; + FUNC_ENTER_API(H5Iremove_verify, NULL); + + if( H5I_IS_LIB_TYPE( id_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); + + done: + FUNC_LEAVE_API(ret_value); +} + +/*------------------------------------------------------------------------- + * 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 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void * +H5I_remove_verify(hid_t id, H5I_type_t id_type) +{ + void * ret_value = NULL; /*return value */ + + FUNC_ENTER_NOAPI(H5I_remove_verify, NULL); - default: - HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid object ID"); - } + /* 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); + } done: FUNC_LEAVE_NOAPI(ret_value); } - + /*------------------------------------------------------------------------- * Function: H5I_remove * - * Purpose: Removes the specified ID from its group. + * 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 @@ -906,26 +1221,26 @@ done: void * H5I_remove(hid_t id) { - H5I_id_group_t *grp_ptr = NULL;/*ptr to the atomic group */ + H5I_id_type_t *type_ptr = NULL;/*ptr to the atomic type */ H5I_id_info_t *curr_id; /*ptr to the current atom */ H5I_id_info_t *last_id; /*ptr to the last atom */ - H5I_type_t grp; /*atom's atomic group */ + H5I_type_t type; /*atom's atomic type */ unsigned hash_loc; /*atom's hash table location */ void * ret_value = NULL; /*return value */ FUNC_ENTER_NOAPI(H5I_remove, NULL); /* Check arguments */ - grp = H5I_GRP(id); - if (grp <= H5I_BADID || grp >= H5I_NGROUPS) - HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "invalid group number"); - grp_ptr = H5I_id_group_list_g[grp]; - if (grp_ptr == NULL || grp_ptr->count <= 0) - HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "invalid group"); + type = H5I_TYPE(id); + if (type <= H5I_BADID || 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->count <= 0) + HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "invalid type"); /* Get the bucket in which the ID is located */ - hash_loc = (unsigned) H5I_LOC(id, grp_ptr->hash_size); - curr_id = grp_ptr->id_list[hash_loc]; + hash_loc = (unsigned) H5I_LOC(id, type_ptr->hash_size); + curr_id = type_ptr->id_list[hash_loc]; if (curr_id == NULL) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, NULL, "invalid ID"); @@ -940,7 +1255,7 @@ H5I_remove(hid_t id) if (curr_id != NULL) { if (last_id == NULL) { /* ID is the first in the chain */ - grp_ptr->id_list[hash_loc] = curr_id->next; + type_ptr->id_list[hash_loc] = curr_id->next; } else { last_id->next = curr_id->next; } @@ -951,14 +1266,14 @@ H5I_remove(hid_t id) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, NULL, "invalid ID"); } - /* Decrement the number of IDs in the group */ - (grp_ptr->ids)--; + /* Decrement the number of IDs in the type */ + (type_ptr->ids)--; done: FUNC_LEAVE_NOAPI(ret_value); } - + /*------------------------------------------------------------------------- * Function: H5Idec_ref * @@ -1001,10 +1316,10 @@ done: * Function: H5I_dec_ref * * Purpose: Decrements the number of references outstanding for an ID. - * This will fail if the group is not a reference counted group. - * The ID group's 'free' function will be called for the 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 group creation time. + * function has been defined at type creation time. * * Return: Success: New reference count. * @@ -1025,8 +1340,8 @@ done: * * Robb Matzke, 19 Feb 1999 * If the free method is defined and fails then the object is not - * removed from the group and its reference count is not decremented. - * The group number is now passed to the free method. + * removed from the type and its reference count is not decremented. + * The type number is now passed to the free method. * * Raymond, 11 Dec 2001 * If the freeing function fails, return failure instead of reference @@ -1038,8 +1353,8 @@ done: int H5I_dec_ref(hid_t id) { - H5I_type_t grp; /*group the object is in*/ - H5I_id_group_t *grp_ptr; /*ptr to the group */ + H5I_type_t type; /*type the object is in*/ + H5I_id_type_t *type_ptr; /*ptr to the type */ H5I_id_info_t *id_ptr; /*ptr to the new ID */ int ret_value; /* Return value */ @@ -1049,29 +1364,29 @@ H5I_dec_ref(hid_t id) assert(id>=0); /* Check arguments */ - grp = H5I_GRP(id); - if (grp <= H5I_BADID || grp >= H5I_NGROUPS) - HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid group number"); - grp_ptr = H5I_id_group_list_g[grp]; - if (grp_ptr == NULL || grp_ptr->count <= 0) - HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid group number"); + type = H5I_TYPE(id); + if (type <= H5I_BADID || 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->count <= 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number"); /* General lookup of the ID */ if ((id_ptr=H5I_find_id(id))==NULL) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't locate ID"); /* - * If this is the last reference to the object then invoke the group's + * 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 group; otherwise leave - * the object in the group without decrementing the reference + * 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 (1==id_ptr->count) { - if (!grp_ptr->free_func || (grp_ptr->free_func)(id_ptr->obj_ptr)>=0) { + if (!type_ptr->free_func || (type_ptr->free_func)(id_ptr->obj_ptr)>=0) { H5I_remove(id); ret_value = 0; } else { @@ -1141,8 +1456,8 @@ done: int H5I_inc_ref(hid_t id) { - H5I_type_t grp; /*group the object is in*/ - H5I_id_group_t *grp_ptr; /*ptr to the group */ + H5I_type_t type; /*type the object is in*/ + H5I_id_type_t *type_ptr; /*ptr to the type */ H5I_id_info_t *id_ptr; /*ptr to the ID */ int ret_value; /* Return value */ @@ -1152,12 +1467,12 @@ H5I_inc_ref(hid_t id) assert(id>=0); /* Check arguments */ - grp = H5I_GRP(id); - if (grp <= H5I_BADID || grp >= H5I_NGROUPS) - HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid group number"); - grp_ptr = H5I_id_group_list_g[grp]; - if (!grp_ptr || grp_ptr->count<=0) - HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid group"); + type = H5I_TYPE(id); + if (type <= H5I_BADID || type >= H5I_next_type) + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number"); + type_ptr = H5I_id_type_list_g[type]; + if (!type_ptr || type_ptr->count<=0) + HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type"); /* General lookup of the ID */ if (NULL==(id_ptr=H5I_find_id(id))) @@ -1226,8 +1541,8 @@ done: static int H5I_get_ref(hid_t id) { - H5I_type_t grp; /*group the object is in*/ - H5I_id_group_t *grp_ptr; /*ptr to the group */ + H5I_type_t type; /*type the object is in*/ + H5I_id_type_t *type_ptr; /*ptr to the type */ H5I_id_info_t *id_ptr; /*ptr to the ID */ int ret_value; /* Return value */ @@ -1237,12 +1552,12 @@ H5I_get_ref(hid_t id) assert(id>=0); /* Check arguments */ - grp = H5I_GRP(id); - if (grp <= H5I_BADID || grp >= H5I_NGROUPS) - HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid group number"); - grp_ptr = H5I_id_group_list_g[grp]; - if (!grp_ptr || grp_ptr->count<=0) - HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid group"); + type = H5I_TYPE(id); + if (type <= H5I_BADID || type >= H5I_next_type) + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number"); + type_ptr = H5I_id_type_list_g[type]; + if (!type_ptr || type_ptr->count<=0) + HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type"); /* General lookup of the ID */ if (NULL==(id_ptr=H5I_find_id(id))) @@ -1255,11 +1570,323 @@ 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. + * + * Return: Success: New reference count + * Failure: Negative + * + * Programmer: Nat Furrer + * James Laird + * April 30, 2004 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +int +H5Iinc_type_ref(H5I_type_t type) +{ + int ret_value; /* Return value */ + + FUNC_ENTER_API(H5Iinc_type_ref, FAIL); + H5TRACE1("Is","It",type); + + /* Check arguments */ + if (type<=0 || type >= H5I_next_type) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "invalid ID type"); + + if( H5I_IS_LIB_TYPE( type ) ) + { + HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "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, FAIL, "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: Negative + * + * Programmer: James Laird + * Nat Furrer + * Friday, April 30, 2004 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +int +H5I_inc_type_ref(H5I_type_t type) +{ + H5I_id_type_t *type_ptr; /* ptr to the type */ + int ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5I_inc_type_ref, FAIL); + + /* Sanity check */ + assert(type>0 && type < H5I_next_type); + + /* 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=++(type_ptr->count); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} + +/*------------------------------------------------------------------------- + * 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 + * 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 + * H5I_dec_type_ref. + * 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: Number of references to type on success/Negative on failure + * + * Programmer: Nathaniel Furrer + * James Laird + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t H5Idec_type_ref(H5I_type_t type) +{ + herr_t ret_value; + + FUNC_ENTER_API(H5Idec_type_ref, FAIL); + + if( H5I_IS_LIB_TYPE( type ) ) + { + HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type"); + } + + ret_value = H5I_dec_type_ref(type); + + done: + FUNC_LEAVE_API(ret_value); +} + +/*------------------------------------------------------------------------- + * 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: Number of references to type on success/Negative on failure + * + * Programmer: Unknown + * + * Modifications: + * + * Robb Matzke, 25 Feb 1998 + * IDs are freed when a type is destroyed. + * + *------------------------------------------------------------------------- + */ +herr_t +H5I_dec_type_ref(H5I_type_t type) +{ + H5I_id_type_t *type_ptr = NULL; /* ptr to the atomic type */ + herr_t ret_value = FAIL; + + FUNC_ENTER_NOAPI(H5I_dec_type_ref, FAIL); + + if (type <= H5I_BADID || 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->count <= 0) + HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "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->count) + { + H5I_destroy_type(type); + ret_value = 0; + } + else + { + --(type_ptr->count); + ret_value = type_ptr->count; + } + + done: + FUNC_LEAVE_NOAPI(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Iget_type_ref + * + * Purpose: Retrieves the number of references outstanding for a type. + * + * Return: Success: Reference count + * Failure: Negative + * + * Programmer: Nat Furrer + * James Laird + * April 30, 2004 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +int +H5Iget_type_ref(H5I_type_t type) +{ + int ret_value; /* Return value */ + + FUNC_ENTER_API(H5Iget_type_ref, FAIL); + H5TRACE1("Is","It",type); + + /* Check arguments */ + if (type<=0 || type >= H5I_next_type) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "invalid ID type"); + + if( H5I_IS_LIB_TYPE( type ) ) + { + HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type"); + } + + /* Do actual retrieve operation */ + if((ret_value = H5I_get_type_ref(type))<0) + HGOTO_ERROR (H5E_ATOM, H5E_CANTGET, FAIL, "can't get ID type ref count"); + +done: + FUNC_LEAVE_API(ret_value); +} /* end H5Iget_ref() */ + + +/*------------------------------------------------------------------------- + * Function: H5I_get_type_ref + * + * Purpose: Retrieve the reference count for an ID type. + * + * Return: Success: The reference count. + * + * Failure: Negative + * + * Programmer: Nat Furrer + * James Laird + * April 30, 2004 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +int +H5I_get_type_ref(H5I_type_t type) +{ + H5I_id_type_t *type_ptr; /*ptr to the type */ + int ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5I_get_type_ref, FAIL); + + /* Sanity check */ + assert(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=type_ptr->count; + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5I_get_ref() */ + + +/*------------------------------------------------------------------------- + * Function: H5Isearch + * + * Purpose: Apply function FUNC to each member of type TYPE and return a + * pointer to the first object for which FUNC returns non-zero. + * The FUNC should take a pointer to the object and the KEY as + * arguments and return non-zero to terminate the search (zero + * to continue). Public interface to H5I_search. + * + * Limitation: Currently there is no way to start searching from where a + * previous search left off. + * + * Return: Success: The first object in the type for which FUNC + * returns non-zero. NULL if FUNC returned zero + * for every object in the type. + * + * Failure: NULL + * + * Programmer: James Laird + * Nathaniel Furrer + * Friday, April 23, 2004 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void *H5Isearch(H5I_type_t type, H5I_search_func_t func, void *key) +{ + void * ret_value; /* Return value */ + + FUNC_ENTER_API(H5Isearch, NULL); + + if( H5I_IS_LIB_TYPE( type ) ) + { + HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "cannot call public function on library type"); + } + + ret_value = H5I_search(type, func, key); + + done: + FUNC_LEAVE_API(ret_value); +} + +/*------------------------------------------------------------------------- * Function: H5I_search * - * Purpose: Apply function FUNC to each member of group GRP and return a + * Purpose: Apply function FUNC to each member of type TYPE and return a * pointer to the first object for which FUNC returns non-zero. * The FUNC should take a pointer to the object and the KEY as * arguments and return non-zero to terminate the search (zero @@ -1268,9 +1895,9 @@ done: * Limitation: Currently there is no way to start searching from where a * previous search left off. * - * Return: Success: The first object in the group for which FUNC + * Return: Success: The first object in the type for which FUNC * returns non-zero. NULL if FUNC returned zero - * for every object in the group. + * for every object in the type. * * Failure: NULL * @@ -1282,9 +1909,9 @@ done: *------------------------------------------------------------------------- */ void * -H5I_search(H5I_type_t grp, H5I_search_func_t func, void *key) +H5I_search(H5I_type_t type, H5I_search_func_t func, void *key) { - H5I_id_group_t *grp_ptr = NULL; /*ptr to the group */ + H5I_id_type_t *type_ptr = NULL; /*ptr to the type */ H5I_id_info_t *id_ptr = NULL; /*ptr to the new ID */ H5I_id_info_t *next_id = NULL; /*ptr to the next ID */ unsigned i; /*counter */ @@ -1293,15 +1920,15 @@ H5I_search(H5I_type_t grp, H5I_search_func_t func, void *key) FUNC_ENTER_NOAPI(H5I_search, NULL); /* Check arguments */ - if (grp <= H5I_BADID || grp >= H5I_NGROUPS) - HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "invalid group number"); - grp_ptr = H5I_id_group_list_g[grp]; - if (grp_ptr == NULL || grp_ptr->count <= 0) - HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "invalid group"); + if (type <= H5I_BADID || 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->count <= 0) + HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "invalid type"); /* Start at the beginning of the array */ - for (i=0; i<grp_ptr->hash_size; i++) { - id_ptr = grp_ptr->id_list[i]; + for (i=0; i<type_ptr->hash_size; i++) { + id_ptr = type_ptr->id_list[i]; while (id_ptr) { next_id= id_ptr->next; /* Protect against ID being deleted in callback */ if ((*func)(id_ptr->obj_ptr, id_ptr->id, key)) @@ -1334,24 +1961,25 @@ done: static H5I_id_info_t * H5I_find_id(hid_t id) { - H5I_id_group_t *grp_ptr; /*ptr to the group */ + H5I_id_type_t *type_ptr; /*ptr to the type */ H5I_id_info_t *last_id; /*ptr to the last ID */ H5I_id_info_t *id_ptr; /*ptr to the new ID */ - H5I_type_t grp; /*ID's group */ + H5I_type_t type; /*ID's type */ unsigned hash_loc; /*bucket pointer */ H5I_id_info_t *ret_value = NULL; /*return value */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5I_find_id); /* Check arguments */ - grp = H5I_GRP(id); - assert(grp > H5I_BADID && grp < H5I_NGROUPS); - grp_ptr = H5I_id_group_list_g[grp]; - assert(grp_ptr && grp_ptr->count > 0); + type = H5I_TYPE(id); + assert(type > H5I_BADID && type < H5I_next_type); + type_ptr = H5I_id_type_list_g[type]; + + assert(type_ptr && type_ptr->count > 0); /* Get the bucket in which the ID is located */ - hash_loc = (unsigned)H5I_LOC(id, grp_ptr->hash_size); - id_ptr = grp_ptr->id_list[hash_loc]; + hash_loc = (unsigned)H5I_LOC(id, type_ptr->hash_size); + id_ptr = type_ptr->id_list[hash_loc]; /* Scan the bucket's linked list for a match */ last_id=NULL; @@ -1360,8 +1988,8 @@ H5I_find_id(hid_t id) /* If we found an object, move it to the front of the list, if it isn't there already */ if(last_id!=NULL) { last_id->next=id_ptr->next; - id_ptr->next=grp_ptr->id_list[hash_loc]; - grp_ptr->id_list[hash_loc]=id_ptr; + id_ptr->next=type_ptr->id_list[hash_loc]; + type_ptr->id_list[hash_loc]=id_ptr; } /* end if */ break; } /* end if */ @@ -1435,7 +2063,7 @@ done: /*------------------------------------------------------------------------- * Function: H5I_debug * - * Purpose: Dump the contents of a group to stderr for debugging. + * Purpose: Dump the contents of a type to stderr for debugging. * * Return: Success: Non-negative * @@ -1453,9 +2081,9 @@ done: */ #ifdef H5I_DEBUG_OUTPUT static herr_t -H5I_debug(H5I_type_t grp) +H5I_debug(H5I_type_t type) { - H5I_id_group_t *grp_ptr; + H5I_id_type_t *type_ptr; H5I_id_info_t *cur; H5G_entry_t *ent = NULL; int is, js; @@ -1464,21 +2092,21 @@ H5I_debug(H5I_type_t grp) FUNC_ENTER_NOAPI(H5I_debug, FAIL); - fprintf(stderr, "Dumping group %d\n", (int)grp); - grp_ptr = H5I_id_group_list_g[grp]; + fprintf(stderr, "Dumping ID type %d\n", (int)type); + type_ptr = H5I_id_type_list_g[type]; /* Header */ - fprintf(stderr, " count = %u\n", grp_ptr->count); - fprintf(stderr, " reserved = %u\n", grp_ptr->reserved); - fprintf(stderr, " wrapped = %u\n", grp_ptr->wrapped); - fprintf(stderr, " hash_size = %lu\n", (unsigned long)grp_ptr->hash_size); - fprintf(stderr, " ids = %u\n", grp_ptr->ids); - fprintf(stderr, " nextid = %u\n", grp_ptr->nextid); + fprintf(stderr, " count = %u\n", type_ptr->count); + fprintf(stderr, " reserved = %u\n", type_ptr->reserved); + fprintf(stderr, " wrapped = %u\n", type_ptr->wrapped); + fprintf(stderr, " hash_size = %lu\n", (unsigned long)type_ptr->hash_size); + fprintf(stderr, " ids = %u\n", type_ptr->ids); + fprintf(stderr, " nextid = %u\n", type_ptr->nextid); /* Cache */ fprintf(stderr, " Cache:\n"); for (is=0; is<ID_CACHE_SIZE; is++) { - if (H5I_cache_g[is] && H5I_GRP(H5I_cache_g[is]->id)==grp) { + if (H5I_cache_g[is] && H5I_TYPE(H5I_cache_g[is]->id)==type) { fprintf(stderr, " Entry-%d, ID=%lu\n", is, (unsigned long)(H5I_cache_g[is]->id)); } @@ -1486,15 +2114,15 @@ H5I_debug(H5I_type_t grp) /* List */ fprintf(stderr, " List:\n"); - for (iu=0; iu<grp_ptr->hash_size; iu++) { - for (js=0, cur=grp_ptr->id_list[iu]; cur; cur=cur->next, js++) { + for (iu=0; iu<type_ptr->hash_size; iu++) { + for (js=0, cur=type_ptr->id_list[iu]; cur; cur=cur->next, js++) { fprintf(stderr, " #%u.%d\n", iu, js); fprintf(stderr, " id = %lu\n", (unsigned long)(cur->id)); fprintf(stderr, " count = %u\n", cur->count); fprintf(stderr, " obj = 0x%08lx\n", (unsigned long)(cur->obj_ptr)); /* Get the symbol table entry, so we get get the name */ - switch(grp) { + switch(type) { case H5I_GROUP: ent = H5G_entof((H5G_t*)cur->obj_ptr); break; |