From f249eed71d4b646bc57a43f28e32f3c2d9d71050 Mon Sep 17 00:00:00 2001 From: James Laird Date: Fri, 18 Jun 2004 11:56:04 -0500 Subject: [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. --- src/H5.c | 6 +- src/H5A.c | 6 +- src/H5D.c | 6 +- src/H5E.c | 18 +- src/H5F.c | 10 +- src/H5FD.c | 6 +- src/H5G.c | 8 +- src/H5I.c | 1258 ++++++++++++++++++++++++++++++++++++++++-------------- src/H5Ipkg.h | 20 +- src/H5Iprivate.h | 34 +- src/H5Ipublic.h | 63 ++- src/H5P.c | 12 +- src/H5R.c | 6 +- src/H5S.c | 6 +- src/H5T.c | 4 +- test/Makefile.in | 5 +- test/testhdf5.c | 1 + test/testhdf5.h | 1 + test/tid.c | 344 +++++++++++++++ 19 files changed, 1406 insertions(+), 408 deletions(-) create mode 100644 test/tid.c diff --git a/src/H5.c b/src/H5.c index 806d156..87f408a 100644 --- a/src/H5.c +++ b/src/H5.c @@ -2090,7 +2090,7 @@ H5_trace (const double *returning, const char *func, const char *type, ...) } else if (obj<0) { fprintf (out, "FAIL"); } else { - switch (H5I_GRP(obj)) { /* Use internal H5I macro instead of function call */ + switch (H5I_TYPE(obj)) { /* Use internal H5I macro instead of function call */ case H5I_BADID: fprintf (out, "%ld (error)", (long)obj); break; @@ -2335,8 +2335,8 @@ H5_trace (const double *returning, const char *func, const char *type, ...) case H5I_ERROR_STACK: fprintf (out, "H5I_ERROR_STACK"); break; - case H5I_NGROUPS: - fprintf (out, "H5I_NGROUPS"); + case H5I_NTYPES: + fprintf (out, "H5I_NTYPES"); break; default: fprintf (out, "%ld", (long)id_type); diff --git a/src/H5A.c b/src/H5A.c index 5f5b7195..113e2a6 100644 --- a/src/H5A.c +++ b/src/H5A.c @@ -68,7 +68,7 @@ H5A_init_interface(void) /* * Create attribute group. */ - if (H5I_init_group(H5I_ATTR, H5I_ATTRID_HASHSIZE, H5A_RESERVED_ATOMS, (H5I_free_t)H5A_close)<0) + if (H5I_register_type(H5I_ATTR, H5I_ATTRID_HASHSIZE, H5A_RESERVED_ATOMS, (H5I_free_t)H5A_close)<0) HGOTO_ERROR(H5E_INTERNAL, H5E_CANTINIT, FAIL, "unable to initialize interface") done: @@ -101,9 +101,9 @@ H5A_term_interface(void) if (interface_initialize_g) { if ((n=H5I_nmembers(H5I_ATTR))) { - H5I_clear_group(H5I_ATTR, FALSE); + H5I_clear_type(H5I_ATTR, FALSE); } else { - H5I_destroy_group(H5I_ATTR); + H5I_dec_type_ref(H5I_ATTR); interface_initialize_g = 0; n = 1; } diff --git a/src/H5D.c b/src/H5D.c index 65b0879..c808faa 100644 --- a/src/H5D.c +++ b/src/H5D.c @@ -202,7 +202,7 @@ H5D_init_interface(void) FUNC_ENTER_NOAPI_NOINIT(H5D_init_interface) /* Initialize the atom group for the dataset IDs */ - if (H5I_init_group(H5I_DATASET, H5I_DATASETID_HASHSIZE, H5D_RESERVED_ATOMS, (H5I_free_t)H5D_close)<0) + if (H5I_register_type(H5I_DATASET, H5I_DATASETID_HASHSIZE, H5D_RESERVED_ATOMS, (H5I_free_t)H5D_close)<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize interface") /* =========Dataset Transfer Property Class Initialization========= */ @@ -442,9 +442,9 @@ H5D_term_interface(void) * * QAK - 5/13/03 */ - H5I_clear_group(H5I_DATASET, TRUE); + H5I_clear_type(H5I_DATASET, TRUE); } else { - H5I_destroy_group(H5I_DATASET); + H5I_dec_type_ref(H5I_DATASET); interface_initialize_g = 0; n = 1; /*H5I*/ } diff --git a/src/H5E.c b/src/H5E.c index 9678afc..0862e89 100644 --- a/src/H5E.c +++ b/src/H5E.c @@ -145,15 +145,15 @@ H5E_init_interface(void) FUNC_ENTER_NOAPI_NOINIT(H5E_init_interface) /* Initialize the atom group for the error class IDs */ - if(H5I_init_group(H5I_ERROR_CLASS, H5I_ERRCLS_HASHSIZE, H5E_RESERVED_ATOMS, + if(H5I_register_type(H5I_ERROR_CLASS, H5I_ERRCLS_HASHSIZE, H5E_RESERVED_ATOMS, (H5I_free_t)H5E_unregister_class)<0) HGOTO_ERROR(H5E_ATOM, H5E_CANTINIT, FAIL, "unable to initialize ID group") /* Initialize the atom group for the major error IDs */ - if(H5I_init_group(H5I_ERROR_MSG, H5I_ERRMSG_HASHSIZE, H5E_RESERVED_ATOMS, + if(H5I_register_type(H5I_ERROR_MSG, H5I_ERRMSG_HASHSIZE, H5E_RESERVED_ATOMS, (H5I_free_t)H5E_close_msg)<0) HGOTO_ERROR(H5E_ATOM, H5E_CANTINIT, FAIL, "unable to initialize ID group") /* Initialize the atom group for the error stacks */ - if(H5I_init_group(H5I_ERROR_STACK, H5I_ERRSTK_HASHSIZE, H5E_RESERVED_ATOMS, + if(H5I_register_type(H5I_ERROR_STACK, H5I_ERRSTK_HASHSIZE, H5E_RESERVED_ATOMS, (H5I_free_t)H5E_close_stack)<0) HGOTO_ERROR(H5E_ATOM, H5E_CANTINIT, FAIL, "unable to initialize ID group") @@ -213,11 +213,11 @@ H5E_term_interface(void) if(n>0) { /* Clear any outstanding error stacks */ if (nstk>0) - H5I_clear_group(H5I_ERROR_STACK, FALSE); + H5I_clear_type(H5I_ERROR_STACK, FALSE); /* Clear all the error classes */ if (ncls>0) { - H5I_clear_group(H5I_ERROR_CLASS, FALSE); + H5I_clear_type(H5I_ERROR_CLASS, FALSE); /* Reset the HDF5 error class, if its been closed */ if(H5I_nmembers(H5I_ERROR_CLASS)==0) @@ -226,7 +226,7 @@ H5E_term_interface(void) /* Clear all the error messages */ if (nmsg>0) { - H5I_clear_group(H5I_ERROR_MSG, FALSE); + H5I_clear_type(H5I_ERROR_MSG, FALSE); /* Reset the HDF5 error messages, if they've been closed */ if(H5I_nmembers(H5I_ERROR_MSG)==0) { @@ -237,9 +237,9 @@ H5E_term_interface(void) } else { /* Destroy the error class, message, and stack id groups */ - H5I_destroy_group(H5I_ERROR_STACK); - H5I_destroy_group(H5I_ERROR_CLASS); - H5I_destroy_group(H5I_ERROR_MSG); + H5I_dec_type_ref(H5I_ERROR_STACK); + H5I_dec_type_ref(H5I_ERROR_CLASS); + H5I_dec_type_ref(H5I_ERROR_MSG); /* Mark closed */ interface_initialize_g = 0; diff --git a/src/H5F.c b/src/H5F.c index 456a799..8091920 100644 --- a/src/H5F.c +++ b/src/H5F.c @@ -232,8 +232,8 @@ H5F_init_interface(void) * which are pending completion because there are object headers still * open within the file. */ - if (H5I_init_group(H5I_FILE, H5I_FILEID_HASHSIZE, 0, (H5I_free_t)H5F_close)<0 || - H5I_init_group(H5I_FILE_CLOSING, H5I_FILEID_HASHSIZE, 0, (H5I_free_t)H5F_close)<0) + if (H5I_register_type(H5I_FILE, H5I_FILEID_HASHSIZE, 0, (H5I_free_t)H5F_close)<0 || + H5I_register_type(H5I_FILE_CLOSING, H5I_FILEID_HASHSIZE, 0, (H5I_free_t)H5F_close)<0) HGOTO_ERROR (H5E_FILE, H5E_CANTINIT, FAIL, "unable to initialize interface") /* ========== File Creation Property Class Initialization ============*/ @@ -463,10 +463,10 @@ H5F_term_interface(void) if (interface_initialize_g) { if ((n=H5I_nmembers(H5I_FILE))) { - H5I_clear_group(H5I_FILE, FALSE); + H5I_clear_type(H5I_FILE, FALSE); } else if (0==(n=H5I_nmembers(H5I_FILE_CLOSING))) { - H5I_destroy_group(H5I_FILE); - H5I_destroy_group(H5I_FILE_CLOSING); + H5I_dec_type_ref(H5I_FILE); + H5I_dec_type_ref(H5I_FILE_CLOSING); interface_initialize_g = 0; n = 1; /*H5I*/ } diff --git a/src/H5FD.c b/src/H5FD.c index 306bfbc..95b825a 100644 --- a/src/H5FD.c +++ b/src/H5FD.c @@ -124,7 +124,7 @@ H5FD_init_interface(void) FUNC_ENTER_NOAPI_NOINIT(H5FD_init_interface) - if (H5I_init_group(H5I_VFL, H5I_VFL_HASHSIZE, 0, (H5I_free_t)H5FD_free_cls)<0) + if (H5I_register_type(H5I_VFL, H5I_VFL_HASHSIZE, 0, (H5I_free_t)H5FD_free_cls)<0) HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "unable to initialize interface") /* Reset the file serial numbers */ @@ -164,7 +164,7 @@ H5FD_term_interface(void) if (interface_initialize_g) { if ((n=H5I_nmembers(H5I_VFL))) { - H5I_clear_group(H5I_VFL, FALSE); + H5I_clear_type(H5I_VFL, FALSE); /* Reset the VFL drivers, if they've been closed */ if(H5I_nmembers(H5I_VFL)==0) { @@ -192,7 +192,7 @@ H5FD_term_interface(void) #endif } /* end if */ } else { - H5I_destroy_group(H5I_VFL); + H5I_dec_type_ref(H5I_VFL); interface_initialize_g = 0; n = 1; /*H5I*/ } diff --git a/src/H5G.c b/src/H5G.c index f465de6..4c6fd16 100644 --- a/src/H5G.c +++ b/src/H5G.c @@ -954,7 +954,7 @@ H5G_init_interface(void) FUNC_ENTER_NOAPI_NOINIT(H5G_init_interface); /* Initialize the atom group for the group IDs */ - if (H5I_init_group(H5I_GROUP, H5I_GROUPID_HASHSIZE, H5G_RESERVED_ATOMS, + if (H5I_register_type(H5I_GROUP, H5I_GROUPID_HASHSIZE, H5G_RESERVED_ATOMS, (H5I_free_t)H5G_close) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to initialize interface"); @@ -1000,7 +1000,7 @@ H5G_term_interface(void) if (interface_initialize_g) { if ((n=H5I_nmembers(H5I_GROUP))) { - H5I_clear_group(H5I_GROUP, FALSE); + H5I_clear_type(H5I_GROUP, FALSE); } else { /* Empty the object type table */ for (i=0; iid_list) + /* How many types are still being used? */ + for (type=(H5I_type_t)0; typeid_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_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; ihash_size; i++) - for (cur=grp_ptr->id_list[i]; cur; cur=cur->next) + for (i=0; ihash_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; ihash_size; i++) { - for (cur=grp_ptr->id_list[i]; cur; cur=next) { + for (i=0; ihash_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; ireserved; inextid>(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=1 && id_typeobj_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_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; ihash_size; i++) { - id_ptr = grp_ptr->id_list[i]; + for (i=0; ihash_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; isid)==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; iuhash_size; iu++) { - for (js=0, cur=grp_ptr->id_list[iu]; cur; cur=cur->next, js++) { + for (iu=0; iuhash_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; diff --git a/src/H5Ipkg.h b/src/H5Ipkg.h index aab865c..d172f97 100644 --- a/src/H5Ipkg.h +++ b/src/H5Ipkg.h @@ -37,23 +37,25 @@ /**************************/ /* - * Number of bits to use for Group ID in each atom. Increase if H5I_NGROUPS - * becomes too large (an assertion would fail in H5I_init_interface). This is - * the only number that must be changed since all other bit field sizes and - * masks are calculated from GROUP_BITS. + * Number of bits to use for ID Type in each atom. 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. */ -#define GROUP_BITS 5 -#define GROUP_MASK ((1<>ID_BITS) & GROUP_MASK)) +/* Map an atom to an ID type number */ +#define H5I_TYPE(a) ((H5I_type_t)(((hid_t)(a)>>ID_BITS) & TYPE_MASK)) /****************************/ diff --git a/src/H5Iprivate.h b/src/H5Iprivate.h index 79819a5..3f6b65c 100644 --- a/src/H5Iprivate.h +++ b/src/H5Iprivate.h @@ -27,7 +27,10 @@ /* Private headers needed by this file */ #include "H5private.h" -/* Default sizes of the hash-tables for various atom groups */ +/* Macro to determine if a H5I_type_t is a "library type" */ +#define H5I_IS_LIB_TYPE( type ) (type > 0 && type < H5I_NTYPES) + +/* Default sizes of the hash-tables for various atom types */ #define H5I_ERRSTACK_HASHSIZE 64 #define H5I_FILEID_HASHSIZE 64 #define H5I_TEMPID_HASHSIZE 64 @@ -45,30 +48,21 @@ #define H5I_ERRMSG_HASHSIZE 64 #define H5I_ERRSTK_HASHSIZE 64 -/* - * Function for freeing objects. This function will be called with an object - * ID group number (object type) and a pointer to the object. The function - * should free the object and return non-negative to indicate that the object - * can be removed from the ID group. If the function returns negative - * (failure) then the object will remain in the ID group. - */ -typedef herr_t (*H5I_free_t)(void*); - -/* Type of the function to compare objects & keys */ -typedef int (*H5I_search_func_t)(void *obj, hid_t id, void *key); - /* Private Functions in H5I.c */ -H5_DLL int H5I_init_group(H5I_type_t grp, size_t hash_size, unsigned reserved, - H5I_free_t func); -H5_DLL int H5I_nmembers(H5I_type_t grp); -H5_DLL herr_t H5I_clear_group(H5I_type_t grp, hbool_t force); -H5_DLL herr_t H5I_destroy_group(H5I_type_t grp); -H5_DLL hid_t H5I_register(H5I_type_t grp, void *object); +H5_DLL H5I_type_t H5I_register_type(H5I_type_t type_id, size_t hash_size, unsigned reserved, H5I_free_t free_func); +H5_DLL int H5I_nmembers(H5I_type_t type); +H5_DLL herr_t H5I_clear_type(H5I_type_t type, hbool_t force); +H5_DLL int H5I_destroy_type(H5I_type_t type); +H5_DLL hid_t H5I_register(H5I_type_t type, void *object); H5_DLL void *H5I_object(hid_t id); H5_DLL void *H5I_object_verify(hid_t id, H5I_type_t id_type); H5_DLL H5I_type_t H5I_get_type(hid_t id); H5_DLL void *H5I_remove(hid_t id); -H5_DLL void *H5I_search(H5I_type_t grp, H5I_search_func_t func, void *key); +H5_DLL void *H5I_remove_verify(hid_t id, H5I_type_t id_type); +H5_DLL void *H5I_search(H5I_type_t type, H5I_search_func_t func, void *key); H5_DLL int H5I_inc_ref(hid_t id); H5_DLL int H5I_dec_ref(hid_t id); +H5_DLL int H5I_inc_type_ref(H5I_type_t type); +H5_DLL herr_t H5I_dec_type_ref(H5I_type_t type); +H5_DLL int H5I_get_type_ref(H5I_type_t type); #endif diff --git a/src/H5Ipublic.h b/src/H5Ipublic.h index 9c4d950..c8787c9 100644 --- a/src/H5Ipublic.h +++ b/src/H5Ipublic.h @@ -23,32 +23,34 @@ #include "H5public.h" /* - * Group values allowed. Start with `1' instead of `0' because it makes the + * Library type values. Start with `1' instead of `0' because it makes the * tracing output look better when hid_t values are large numbers. Change the - * GROUP_BITS in H5I.c if the MAXID gets larger than 32 (an assertion will + * TYPE_BITS in H5I.c if the MAXID gets larger than 32 (an assertion will * fail otherwise). * - * When adding groups here, add a section to the 'misc19' test in test/tmisc.c + * When adding types here, add a section to the 'misc19' test in test/tmisc.c * to verify that the H5I{inc|dec|get}_ref() routines work correctly with in. * */ typedef enum { - H5I_BADID = (-1), /*invalid Group */ - H5I_FILE = 1, /*group ID for File objects */ + H5I_UNINIT = (-2), /*uninitialized type */ + H5I_BADID = (-1), /*invalid Type */ + H5I_FILE = 1, /*type ID for File objects */ H5I_FILE_CLOSING, /*files pending close due to open objhdrs */ - H5I_GROUP, /*group ID for Group objects */ - H5I_DATATYPE, /*group ID for Datatype objects */ - H5I_DATASPACE, /*group ID for Dataspace objects */ - H5I_DATASET, /*group ID for Dataset objects */ - H5I_ATTR, /*group ID for Attribute objects */ - H5I_REFERENCE, /*group ID for Reference objects */ - H5I_VFL, /*group ID for virtual file layer */ - H5I_GENPROP_CLS, /*group ID for generic property list classes */ - H5I_GENPROP_LST, /*group ID for generic property lists */ - H5I_ERROR_CLASS, /*group ID for error classes */ - H5I_ERROR_MSG, /*group ID for error messages */ - H5I_ERROR_STACK, /*group ID for error stacks */ - H5I_NGROUPS /*number of valid groups, MUST BE LAST! */ + H5I_GROUP, /*type ID for Group objects */ + H5I_DATATYPE, /*type ID for Datatype objects */ + H5I_DATASPACE, /*type ID for Dataspace objects */ + H5I_DATASET, /*type ID for Dataset objects */ + H5I_ATTR, /*type ID for Attribute objects */ + H5I_TEMPBUF, /*type ID for Temporary buffer objects */ + H5I_REFERENCE, /*type ID for Reference objects */ + H5I_VFL, /*type ID for virtual file layer */ + H5I_GENPROP_CLS, /*type ID for generic property list classes */ + H5I_GENPROP_LST, /*type ID for generic property lists */ + H5I_ERROR_CLASS, /*type ID for error classes */ + H5I_ERROR_MSG, /*type ID for error messages */ + H5I_ERROR_STACK, /*type ID for error stacks */ + H5I_NTYPES /*number of library types, MUST BE LAST! */ } H5I_type_t; /* Type of atoms to return to users */ @@ -57,17 +59,42 @@ typedef int hid_t; /* An invalid object ID. This is also negative for error return. */ #define H5I_INVALID_HID (-1) +/* + * Function for freeing objects. This function will be called with an object + * ID type number and a pointer to the object. The function should free the + * object and return non-negative to indicate that the object + * can be removed from the ID type. If the function returns negative + * (failure) then the object will remain in the ID type. + */ +typedef herr_t (*H5I_free_t)(void*); + +/* Type of the function to compare objects & keys */ +typedef int (*H5I_search_func_t)(void *obj, hid_t id, void *key); + #ifdef __cplusplus extern "C" { #endif /* Public API functions */ + +H5_DLL hid_t H5Iregister(H5I_type_t type, void *object); +H5_DLL void *H5Iobject_verify(hid_t id, H5I_type_t id_type); +H5_DLL void *H5Iremove_verify(hid_t id, H5I_type_t id_type); H5_DLL H5I_type_t H5Iget_type(hid_t id); H5_DLL hid_t H5Iget_file_id(hid_t id); H5_DLL ssize_t H5Iget_name(hid_t id, char *name/*out*/, size_t size); H5_DLL int H5Iinc_ref(hid_t id); H5_DLL int H5Idec_ref(hid_t id); H5_DLL int H5Iget_ref(hid_t id); +H5_DLL H5I_type_t H5Iregister_type(size_t hash_size, unsigned reserved, H5I_free_t free_func); +H5_DLL herr_t H5Iclear_type(H5I_type_t type, hbool_t force); +H5_DLL herr_t H5Idestroy_type(H5I_type_t type); +H5_DLL int H5Iinc_type_ref(H5I_type_t type); +H5_DLL int H5Idec_type_ref(H5I_type_t type); +H5_DLL int H5Iget_type_ref(H5I_type_t type); +H5_DLL void *H5Isearch(H5I_type_t type, H5I_search_func_t func, void *key); +H5_DLL int H5Inmembers(H5I_type_t type); + #ifdef __cplusplus } diff --git a/src/H5P.c b/src/H5P.c index cc0eca8..2c198ce 100644 --- a/src/H5P.c +++ b/src/H5P.c @@ -216,9 +216,9 @@ H5P_init_interface(void) /* * Initialize the Generic Property class & object groups. */ - if (H5I_init_group(H5I_GENPROP_CLS, H5I_GENPROPCLS_HASHSIZE, 0, (H5I_free_t)H5P_close_class) < 0) + if (H5I_register_type(H5I_GENPROP_CLS, H5I_GENPROPCLS_HASHSIZE, 0, (H5I_free_t)H5P_close_class) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CANTINIT, FAIL, "unable to initialize ID group"); - if (H5I_init_group(H5I_GENPROP_LST, H5I_GENPROPOBJ_HASHSIZE, 0, (H5I_free_t)H5P_close) < 0) + if (H5I_register_type(H5I_GENPROP_LST, H5I_GENPROPOBJ_HASHSIZE, 0, (H5I_free_t)H5P_close) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CANTINIT, FAIL, "unable to initialize ID group"); /* Create root property list class */ @@ -324,7 +324,7 @@ H5P_term_interface(void) if (n) { /* Clear the lists */ if(nlist>0) { - H5I_clear_group(H5I_GENPROP_LST, FALSE); + H5I_clear_type(H5I_GENPROP_LST, FALSE); /* Reset the default property lists, if they've been closed */ if(H5I_nmembers(H5I_GENPROP_LST)==0) { @@ -339,7 +339,7 @@ H5P_term_interface(void) /* Only attempt to close the classes after all the lists are closed */ if(nlist==0 && nclass>0) { - H5I_clear_group(H5I_GENPROP_CLS, FALSE); + H5I_clear_type(H5I_GENPROP_CLS, FALSE); /* Reset the default property lists, if they've been closed */ if(H5I_nmembers(H5I_GENPROP_CLS)==0) { @@ -352,9 +352,9 @@ H5P_term_interface(void) } /* end if */ } /* end if */ } else { - H5I_destroy_group(H5I_GENPROP_LST); + H5I_dec_type_ref(H5I_GENPROP_LST); n++; /*H5I*/ - H5I_destroy_group(H5I_GENPROP_CLS); + H5I_dec_type_ref(H5I_GENPROP_CLS); n++; /*H5I*/ interface_initialize_g = 0; diff --git a/src/H5R.c b/src/H5R.c index df1041a..72e629d 100644 --- a/src/H5R.c +++ b/src/H5R.c @@ -60,7 +60,7 @@ H5R_init_interface(void) FUNC_ENTER_NOAPI_NOINIT(H5R_init_interface); /* Initialize the atom group for the file IDs */ - if (H5I_init_group(H5I_REFERENCE, H5I_REFID_HASHSIZE, H5R_RESERVED_ATOMS, + if (H5I_register_type(H5I_REFERENCE, H5I_REFID_HASHSIZE, H5R_RESERVED_ATOMS, (H5I_free_t)NULL)<0) HGOTO_ERROR (H5E_REFERENCE, H5E_CANTINIT, FAIL, "unable to initialize interface"); @@ -95,9 +95,9 @@ H5R_term_interface(void) if (interface_initialize_g) { if ((n=H5I_nmembers(H5I_REFERENCE))) { - H5I_clear_group(H5I_REFERENCE, FALSE); + H5I_clear_type(H5I_REFERENCE, FALSE); } else { - H5I_destroy_group(H5I_REFERENCE); + H5I_dec_type_ref(H5I_REFERENCE); interface_initialize_g = 0; n = 1; /*H5I*/ } diff --git a/src/H5S.c b/src/H5S.c index 0de9190..1001395 100644 --- a/src/H5S.c +++ b/src/H5S.c @@ -85,7 +85,7 @@ H5S_init_interface(void) FUNC_ENTER_NOAPI_NOINIT(H5S_init_interface); /* Initialize the atom group for the file IDs */ - if (H5I_init_group(H5I_DATASPACE, H5I_DATASPACEID_HASHSIZE, + if (H5I_register_type(H5I_DATASPACE, H5I_DATASPACEID_HASHSIZE, H5S_RESERVED_ATOMS, (H5I_free_t)H5S_close)<0) HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize interface"); @@ -136,7 +136,7 @@ H5S_term_interface(void) if (interface_initialize_g) { if ((n=H5I_nmembers(H5I_DATASPACE))) { - H5I_clear_group(H5I_DATASPACE, FALSE); + H5I_clear_type(H5I_DATASPACE, FALSE); } else { #ifdef H5S_DEBUG /* @@ -256,7 +256,7 @@ H5S_term_interface(void) #endif /* Free data types */ - H5I_destroy_group(H5I_DATASPACE); + H5I_dec_type_ref(H5I_DATASPACE); /* Clear/free conversion table */ for (i=0; i= 0) + H5Idestroy_type(myType); + + return -1; +} + + + /* A dummy search function for the next test */ +int test_search_func(void * ptr1, void * ptr2); +int test_search_func(void * ptr1, void * ptr2) { return 0; } + + /* Ensure that public functions cannot access "predefined" ID types */ +int id_predefined_test() +{ + void * testObj; + hid_t testID; + hid_t typeID = H5I_INVALID_HID; + int testInt; + void * testPtr; + herr_t testErr; + + testObj = malloc(sizeof(int)); + + /* Try to perform illegal functions on various predefined types */ + H5E_BEGIN_TRY + testID = H5Iregister(H5I_FILE, testObj); + H5E_END_TRY + + VERIFY(testID, H5I_INVALID_HID, "H5Iregister"); + if(testID != H5I_INVALID_HID) + goto out; + + H5E_BEGIN_TRY + testPtr = H5Isearch(H5I_GENPROP_LST, (H5I_search_func_t) test_search_func, testObj); + H5E_END_TRY + + VERIFY(testPtr, NULL, "H5Isearch"); + if(testPtr != NULL) + goto out; + + H5E_BEGIN_TRY + testInt = H5Inmembers(H5I_ERROR_STACK); + H5E_END_TRY + + VERIFY(testInt, -1, "H5Inmembers"); + if(testInt != -1) + goto out; + + H5E_BEGIN_TRY + testErr = H5Iclear_type(H5I_FILE, 0); + H5E_END_TRY + + VERIFY((testErr >= 0), 0, "H5Iclear_type"); + if(testErr >= 0) + goto out; + + H5E_BEGIN_TRY + testErr = H5Idestroy_type(H5I_DATASET); + H5E_END_TRY + + VERIFY((testErr >= 0), 0, "H5Idestroy_type"); + if(testErr >= 0) + goto out; + + /* Create a datatype ID and try to perform illegal functions on it */ + typeID = H5Tcreate(H5T_OPAQUE, 42); + CHECK(typeID, H5I_INVALID_HID, "H5Tcreate"); + if(typeID == H5I_INVALID_HID) + goto out; + + H5E_BEGIN_TRY + testPtr = H5Iremove_verify(typeID, H5I_DATATYPE); + H5E_END_TRY + + VERIFY(testPtr, NULL, "H5Iremove_verify"); + if(testPtr != NULL) + goto out; + + H5E_BEGIN_TRY + testPtr = H5Iobject_verify(typeID, H5I_DATATYPE); + H5E_END_TRY + + VERIFY(testPtr, NULL, "H5Iobject_verify"); + if(testPtr != NULL) + goto out; + + H5Tclose(typeID); + + return 0; + +out: + if(typeID != H5I_INVALID_HID) + H5Tclose(typeID); + + return -1; +} + + + /* Test boundary cases with lots of types */ + + /* Type IDs range from H5I_NTYPES to MAX_NUM_TYPES. The system will assign */ + /* IDs in sequential order until MAX_NUM_TYPES IDs have been given out, at which */ + /* point it will search for type IDs that were allocated but have since been */ + /* deleted. */ + /* This test will allocate IDs up to MAX_NUM_TYPES, ensure that IDs wrap around */ + /* to low values successfully, ensure that an error is thrown when all possible */ + /* type IDs are taken, then ensure that deleting types frees up their IDs. */ + /* Note that this test depends on the implementation of IDs, so may break */ + /* if the implementation changes. */ + /* Also note that if someone else registered a user-defined type and forgot to */ + /* destroy it, this test will mysteriously fail (because it will expect there to */ + /* be one more "free" type ID than there is). */ + /* H5I_NTYPES is defined in h5public.h, MAX_NUM_TYPES is defined in h5pkg.h */ +int test_id_type_list() +{ + H5I_type_t startType; /* The first type ID we were assigned in this test */ + H5I_type_t currentType; + H5I_type_t testType; + int i; /* Just a counter variable */ + + startType = H5Iregister_type(8, 0, (H5I_free_t) free ); + CHECK(startType, H5I_BADID, "H5Iregister_type"); + if(startType == H5I_BADID) + goto out; + + /* Sanity check */ + if(startType >= MAX_NUM_TYPES || startType < H5I_NTYPES) + { + /* Error condition, throw an error */ + CHECK(1, 1, "H5Iregister_type"); + goto out; + } + /* Create types up to MAX_NUM_TYPES */ + for(i = startType + 1; i < MAX_NUM_TYPES; i++) + { + currentType = H5Iregister_type(8, 0, (H5I_free_t) free ); + CHECK(currentType, H5I_BADID, "H5Iregister_type"); + if(currentType == H5I_BADID) + goto out; + } + + /* Wrap around to low type ID numbers */ + for(i = H5I_NTYPES; i < startType; i++) + { + currentType = H5Iregister_type(8, 0, (H5I_free_t) free ); + CHECK(currentType, H5I_BADID, "H5Iregister_type"); + if(currentType == H5I_BADID) + goto out; + } + + /* There should be no room at the inn */ + H5E_BEGIN_TRY + testType = H5Iregister_type(8, 0, (H5I_free_t) free ); + H5E_END_TRY + + VERIFY(testType, H5I_BADID, "H5Iregister_type"); + if(testType != H5I_BADID) + goto out; + + /* Now delete a type and try to insert again */ + H5Idestroy_type(H5I_NTYPES); + testType = H5Iregister_type(8, 0, (H5I_free_t) free ); + + VERIFY(testType, H5I_NTYPES, "H5Iregister_type"); + if(testType != H5I_NTYPES) + goto out; + + /* Cleanup. Destroy all types. */ + for(i = H5I_NTYPES; i < MAX_NUM_TYPES; i++) + H5Idestroy_type((H5I_type_t) i); + + return 0; + +out: + /* Cleanup. For simplicity, just destroy all types and ignore errors. */ + H5E_BEGIN_TRY + for(i = H5I_NTYPES; i < MAX_NUM_TYPES; i++) + H5Idestroy_type((H5I_type_t) i); + H5E_END_TRY + return -1; +} + +void test_ids() +{ + id_test(); + id_predefined_test(); + test_id_type_list(); +} \ No newline at end of file -- cgit v0.12