1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * Copyright by The HDF Group.                                               *
3  * Copyright by the Board of Trustees of the University of Illinois.         *
4  * All rights reserved.                                                      *
5  *                                                                           *
6  * This file is part of HDF5.  The full HDF5 copyright notice, including     *
7  * terms governing use, modification, and redistribution, is contained in    *
8  * the files COPYING and Copyright.html.  COPYING can be found at the root   *
9  * of the source code distribution tree; Copyright.html can be found at the  *
10  * root level of an installed copy of the electronic HDF5 document set and   *
11  * is linked from the top-level documents page.  It can also be found at     *
12  * http://hdfgroup.org/HDF5/doc/Copyright.html.  If you do not have          *
13  * access to either file, you may request a copy from help@hdfgroup.org.     *
14  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /*
17  * FILE:	H5I.c - Internal storage routines for handling "IDs"
18  *
19  * REMARKS:	ID's which allow objects (void *'s currently) to be bundled
20  *		into "types" for more general storage.
21  *
22  * DESIGN:	The types are stored in an array of pointers to store each
23  *		type in an element. Each "type" node contains a link to a
24  *		hash table to manage the IDs in each type.  Allowed types are
25  *		values within the range 1 to H5I_MAX_NUM_TYPES and are given out
26  *		at run-time.  Types used by the library are stored in global
27  *		variables defined in H5Ipublic.h.
28  *
29  * AUTHOR:	Quincey Koziol
30  *
31  * MODIFICATIONS:
32  *	1/3/96	- Starting writing specs & coding prototype
33  *	1/7/96	- Finished coding prototype
34  *	6/10/97 - Moved into HDF5 library
35  *	5/18/04 - Expanded to allow registration of new types at run-time
36  */
37 
38 #define H5I_PACKAGE		/*suppress error about including H5Ipkg	  */
39 
40 /* Interface initialization */
41 #define H5_INTERFACE_INIT_FUNC	H5I_init_interface
42 
43 
44 #include "H5private.h"		/* Generic Functions			*/
45 #include "H5ACprivate.h"        /* Metadata cache                       */
46 #include "H5Eprivate.h"		/* Error handling		  	*/
47 #include "H5FLprivate.h"	/* Free Lists                           */
48 #include "H5Ipkg.h"		/* IDs			  		*/
49 #include "H5MMprivate.h"	/* Memory management			*/
50 #include "H5Oprivate.h"		/* Object headers		  	*/
51 #include "H5SLprivate.h"	/* Skip Lists                           */
52 
53 /* Define this to compile in support for dumping ID information */
54 /* #define H5I_DEBUG_OUTPUT */
55 #ifndef H5I_DEBUG_OUTPUT
56 #include "H5Gprivate.h"		/* Groups				*/
57 #else /* H5I_DEBUG_OUTPUT */
58 #define H5G_PACKAGE /*suppress error message about including H5Gpkg.h */
59 #include "H5Gpkg.h"		/* Groups		  		*/
60 #include "H5Dprivate.h"		/* Datasets				*/
61 #include "H5Tprivate.h"		/* Datatypes				*/
62 #endif /* H5I_DEBUG_OUTPUT */
63 
64 /* Local Macros */
65 
66 /* Define the maximum number of returned ID structures to keep around
67    for re-use. */
68 #define MAX_FREE_ID_STRUCTS 1000
69 
70 /* Combine a Type number and an atom index into an atom */
71 #define H5I_MAKE(g,i)	((((hid_t)(g)&TYPE_MASK)<<ID_BITS)|	  \
72 			     ((hid_t)(i)&ID_MASK))
73 
74 /* Local typedefs */
75 
76 /* Atom information structure used */
77 typedef struct H5I_id_info_t {
78     hid_t	id;		/* ID for this info			    */
79     unsigned	count;		/* ref. count for this atom		    */
80     unsigned    app_count;      /* ref. count of application visible atoms  */
81     const void	*obj_ptr;	/* pointer associated with the atom	    */
82 } H5I_id_info_t;
83 
84 /* ID type structure used */
85 typedef struct {
86     const H5I_class_t *cls;     /* Pointer to ID class                      */
87     unsigned	init_count;	/* # of times this type has been initialized*/
88     hbool_t	wrapped;	/* Whether the id count has wrapped around  */
89     unsigned	id_count;	/* Current number of IDs held		    */
90     hid_t	nextid;		/* ID to use for the next atom		    */
91     H5SL_t      *ids;           /* Pointer to skip list that stores IDs     */
92 
93     /* Fields for holding available IDs */
94     unsigned    avail_count;    /* # of available ID structures awaiting recycling */
95     H5SL_t      *avail_ids;     /* pointer to skip list of available IDs */
96 } H5I_id_type_t;
97 
98 typedef struct {
99     H5I_search_func_t app_cb;   /* Application's callback routine */
100     void *app_key;              /* Application's "key" (user data) */
101     void *ret_obj;              /* Object to return */
102 } H5I_search_ud_t;
103 
104 /* User data for iterator callback when IDs have wrapped */
105 typedef struct {
106     hid_t nextid;               /* Next ID to expect */
107 } H5I_wrap_ud_t;
108 
109 /* User data for iterator callback for ID iteration */
110 typedef struct {
111     H5I_search_func_t user_func;        /* 'User' function to invoke */
112     void *user_udata;                   /* User data to pass to 'user' function */
113     hbool_t app_ref;                    /* Whether this is an appl. ref. call */
114 } H5I_iterate_ud_t;
115 
116 /*-------------------- Locally scoped variables -----------------------------*/
117 
118 /* Array of pointers to atomic types */
119 static H5I_id_type_t *H5I_id_type_list_g[H5I_MAX_NUM_TYPES];
120 
121 /* Variable to keep track of the number of types allocated.  Its value is the */
122 /* next type ID to be handed out, so it is always one greater than the number */
123 /* of types. */
124 /* Starts at 1 instead of 0 because it makes trace output look nicer.  If more */
125 /* types (or IDs within a type) are needed, adjust TYPE_BITS in H5Ipkg.h       */
126 /* and/or increase size of hid_t */
127 static H5I_type_t H5I_next_type = (H5I_type_t) H5I_NTYPES;
128 
129 /* Declare a free list to manage the H5I_id_info_t struct */
130 H5FL_DEFINE_STATIC(H5I_id_info_t);
131 
132 /* Declare a free list to manage the H5I_id_type_t struct */
133 H5FL_DEFINE_STATIC(H5I_id_type_t);
134 
135 /* Declare a free list to manage the H5I_class_t struct */
136 H5FL_DEFINE_STATIC(H5I_class_t);
137 
138 /*--------------------- Local function prototypes ---------------------------*/
139 static herr_t H5I__free_cb(void *_item, void *_key, void *_udata);
140 static int H5I__destroy_type(H5I_type_t type);
141 static void *H5I__remove_verify(hid_t id, H5I_type_t id_type);
142 static void *H5I__remove_common(H5I_id_type_t *type_ptr, hid_t id);
143 static int H5I__inc_type_ref(H5I_type_t type);
144 static int H5I__get_type_ref(H5I_type_t type);
145 static H5I_id_info_t *H5I__find_id(hid_t id);
146 #ifdef H5I_DEBUG_OUTPUT
147 static herr_t H5I__debug(H5I_type_t type);
148 #endif /* H5I_DEBUG_OUTPUT */
149 
150 
151 /*--------------------------------------------------------------------------
152 NAME
153    H5I_init_interface -- Initialize interface-specific information
154 USAGE
155     herr_t H5I_init_interface()
156 
157 RETURNS
158     Non-negative on success/Negative on failure
159 DESCRIPTION
160     Initializes any interface-specific data or routines.
161 
162 --------------------------------------------------------------------------*/
163 static herr_t
H5I_init_interface(void)164 H5I_init_interface(void)
165 {
166     FUNC_ENTER_NOAPI_NOINIT_NOERR
167 
168     FUNC_LEAVE_NOAPI(SUCCEED)
169 } /* end H5I_init_interface() */
170 
171 
172 /*-------------------------------------------------------------------------
173  * Function:	H5I_term_interface
174  *
175  * Purpose:	Terminate the H5I interface: release all memory, reset all
176  *		global variables to initial values. This only happens if all
177  *		types have been destroyed from other interfaces.
178  *
179  * Return:	Success:	Positive if any action was taken that might
180  *				affect some other interface; zero otherwise.
181  *
182  * 		Failure:	Negative.
183  *
184  * Programmer:	Unknown
185  *
186  *-------------------------------------------------------------------------
187  */
188 int
H5I_term_interface(void)189 H5I_term_interface(void)
190 {
191     H5I_id_type_t	*type_ptr;
192     H5I_type_t		type;
193     int		n = 0;
194 
195     FUNC_ENTER_NOAPI_NOINIT_NOERR
196 
197     if(H5_interface_initialize_g) {
198         /* How many types are still being used? */
199         for(type = (H5I_type_t)0; type < H5I_next_type; H5_INC_ENUM(H5I_type_t, type)) {
200             if((type_ptr = H5I_id_type_list_g[type]) && type_ptr->ids)
201                 n++;
202         } /* end for */
203 
204         /* If no types are used then clean up */
205         if(0 == n) {
206             for(type = (H5I_type_t)0; type < H5I_next_type; H5_INC_ENUM(H5I_type_t,type)) {
207                 type_ptr = H5I_id_type_list_g[type];
208                 if(type_ptr) {
209                     HDassert(NULL == type_ptr->ids);
210                     type_ptr = H5FL_FREE(H5I_id_type_t, type_ptr);
211                     H5I_id_type_list_g[type] = NULL;
212                 } /* end if */
213             } /* end for */
214         } /* end if */
215 
216         /* Mark interface closed */
217         H5_interface_initialize_g = 0;
218     } /* end if */
219 
220     FUNC_LEAVE_NOAPI(n)
221 } /* end H5I_term_interface() */
222 
223 
224 /*-------------------------------------------------------------------------
225  * Function:	H5Iregister_type
226  *
227  * Purpose:	Public interface to H5I_register_type.  Creates a new type
228  *		of ID's to give out.  A specific number (RESERVED) of type
229  *		entries may be reserved to enable "constant" values to be handed
230  *		out which are valid IDs in the type, but which do not map to any
231  *		data structures and are not allocated dynamically later. HASH_SIZE is
232  *		the minimum hash table size to use for the type. FREE_FUNC is
233  *		called with an object pointer when the object is removed from
234  *		the type.
235  *
236  * Return:	Success:	Type ID of the new type
237  *		Failure:	H5I_BADID
238  *
239  * Programmers:	Nathaniel Furrer
240  *		James Laird
241  *		Friday, April 30, 2004
242  *
243  *-------------------------------------------------------------------------
244  */
245 H5I_type_t
H5Iregister_type(size_t hash_size,unsigned reserved,H5I_free_t free_func)246 H5Iregister_type(size_t hash_size, unsigned reserved, H5I_free_t free_func)
247 {
248     H5I_class_t *cls = NULL;    /* New ID class */
249     H5I_type_t new_type;        /* New ID type value */
250     H5I_type_t ret_value;       /* Return value */
251 
252     FUNC_ENTER_API(H5I_BADID)
253     H5TRACE3("It", "zIux", hash_size, reserved, free_func);
254 
255     /* Generate a new H5I_type_t value */
256 
257     /* Increment the number of types*/
258     if(H5I_next_type < H5I_MAX_NUM_TYPES) {
259         new_type = H5I_next_type;
260         H5_INC_ENUM(H5I_type_t, H5I_next_type);
261     } /* end if */
262     else {
263         hbool_t done;       /* Indicate that search was successful */
264         int i;              /* Local index variable */
265 
266         /* Look for a free type to give out */
267         done = FALSE;
268         for(i = H5I_NTYPES; i < H5I_MAX_NUM_TYPES && done == FALSE; i++) {
269             if(NULL == H5I_id_type_list_g[i]) {
270                 /* Found a free type ID */
271                 new_type = (H5I_type_t)i;
272                 done = TRUE;
273             } /* end if */
274         } /* end for */
275 
276         /* Verify that we found a type to give out */
277         if(done == FALSE)
278             HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5I_BADID, "Maximum number of ID types exceeded.")
279     } /* end else */
280 
281     /* Allocate new ID class */
282     if(NULL == (cls = H5FL_MALLOC(H5I_class_t)))
283         HGOTO_ERROR(H5E_ATOM, H5E_CANTALLOC, H5I_BADID, "ID class allocation failed")
284 
285     /* Initialize class fields */
286     cls->type_id = new_type;
287     cls->flags = H5I_CLASS_IS_APPLICATION;
288     cls->reserved = reserved;
289     cls->free_func = free_func;
290 
291     /* Register the new ID class */
292     if(H5I_register_type(cls) < 0)
293         HGOTO_ERROR(H5E_ATOM, H5E_CANTINIT, H5I_BADID, "can't initialize ID class")
294 
295     /* Set return value */
296     ret_value = new_type;
297 
298 done:
299     /* Clean up on error */
300     if(ret_value < 0) {
301         if(cls)
302             cls = H5FL_FREE(H5I_class_t, cls);
303     } /* end if */
304 
305     FUNC_LEAVE_API(ret_value)
306 } /* end H5Iregister_type() */
307 
308 
309 /*-------------------------------------------------------------------------
310  * Function:	H5I_register_type
311  *
312  * Purpose:	Creates a new type of ID's to give out.
313  *		The class is initialized or its reference count is incremented
314  *              (if it is already initialized).
315  *
316  * Return:	Success:	Type ID of the new type
317  *		Failure:	H5I_BADID
318  *
319  * Programmers:	Nathaniel Furrer
320  *		James Laird
321  *		Friday, April 30, 2004
322  *
323  *-------------------------------------------------------------------------
324  */
325 herr_t
H5I_register_type(const H5I_class_t * cls)326 H5I_register_type(const H5I_class_t *cls)
327 {
328     H5I_id_type_t *type_ptr = NULL;	/* Ptr to the atomic type*/
329     herr_t ret_value = SUCCEED;         /* Return value */
330 
331     FUNC_ENTER_NOAPI(FAIL)
332 
333     /* Sanity check */
334     HDassert(cls);
335     HDassert(cls->type_id > 0 && cls->type_id < H5I_MAX_NUM_TYPES);
336 
337     /* Initialize the type */
338     if(NULL == H5I_id_type_list_g[cls->type_id]) {
339         /* Allocate the type information for new type */
340         if(NULL == (type_ptr = (H5I_id_type_t *)H5FL_CALLOC(H5I_id_type_t)))
341             HGOTO_ERROR(H5E_ATOM, H5E_CANTALLOC, FAIL, "ID type allocation failed")
342         H5I_id_type_list_g[cls->type_id] = type_ptr;
343     } /* end if */
344     else {
345         /* Get the pointer to the existing type */
346         type_ptr = H5I_id_type_list_g[cls->type_id];
347     } /* end else */
348 
349     /* Initialize the ID type structure for new types */
350     if(type_ptr->init_count == 0) {
351         type_ptr->cls = cls;
352         type_ptr->wrapped = FALSE;
353         type_ptr->id_count = 0;
354         type_ptr->nextid = (hid_t)cls->reserved;
355         if(NULL == (type_ptr->ids = H5SL_create(H5SL_TYPE_HID, NULL)))
356             HGOTO_ERROR(H5E_ATOM, H5E_CANTCREATE, FAIL, "skip list creation failed")
357         type_ptr->avail_count = 0;
358         if(NULL == (type_ptr->avail_ids = H5SL_create(H5SL_TYPE_HID, NULL)))
359             HGOTO_ERROR(H5E_ATOM, H5E_CANTCREATE, FAIL, "skip list creation failed")
360     } /* end if */
361 
362     /* Increment the count of the times this type has been initialized */
363     type_ptr->init_count++;
364 
365 done:
366     if(ret_value < 0) {	/* Clean up on error */
367         if(type_ptr) {
368             if(type_ptr->ids)
369                 H5SL_close(type_ptr->ids);
370             if(type_ptr->avail_ids)
371                 H5SL_close(type_ptr->avail_ids);
372             (void)H5FL_FREE(H5I_id_type_t, type_ptr);
373         } /* end if */
374     } /* end if */
375 
376     FUNC_LEAVE_NOAPI(ret_value)
377 } /* end H5I_register_type() */
378 
379 
380 /*-------------------------------------------------------------------------
381  * Function:	H5Itype_exists
382  *
383  * Purpose:     Query function to inform the user if a given type is
384  *              currently registered with the library.
385  *
386  * Return:	Success:        1 if the type is registered, 0 if it is not
387  *		Failure:	Negative
388  *
389  * Programmer:	James Laird
390  *		Nathaniel Furrer
391  *              Tuesday, June 29, 2004
392  *
393  *-------------------------------------------------------------------------
394  */
395 htri_t
H5Itype_exists(H5I_type_t type)396 H5Itype_exists(H5I_type_t type)
397 {
398     htri_t ret_value = TRUE;                      /* Return value */
399 
400     FUNC_ENTER_API(FAIL)
401     H5TRACE1("t", "It", type);
402 
403     if(type <= H5I_BADID || type >= H5I_next_type)
404 	HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
405 
406     if(NULL == H5I_id_type_list_g[type])
407         ret_value = FALSE;
408 
409 done:
410     FUNC_LEAVE_API(ret_value)
411 } /* end H5Itype_exists() */
412 
413 
414 /*-------------------------------------------------------------------------
415  * Function:	H5Inmembers
416  *
417  * Purpose:	Returns the number of members in a type.  Public interface to
418  *		H5I_nmembers.  The public interface throws an error if the
419  *              supplied type does not exist.  This is different than the
420  *              private interface, which will just return 0.
421  *
422  * Return:	Success:	Zero
423  *		Failure:	Negative
424  *
425  * Programmer:	James Laird
426  *		Nathaniel Furrer
427  *              Friday, April 23, 2004
428  *
429  *-------------------------------------------------------------------------
430  */
431 herr_t
H5Inmembers(H5I_type_t type,hsize_t * num_members)432 H5Inmembers(H5I_type_t type, hsize_t *num_members)
433 {
434     int ret_value = SUCCEED;                      /* Return value */
435 
436     FUNC_ENTER_API(FAIL)
437     H5TRACE2("e", "It*h", type, num_members);
438 
439     if(H5I_IS_LIB_TYPE(type))
440         HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type")
441 
442     /* Validate parameters.  This needs to be done here, instead of letting
443      * the private interface handle it, because the public interface throws
444      * an error when the supplied type does not exist.
445      */
446     if(type <= H5I_BADID || type >= H5I_next_type)
447 	HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
448     if(NULL == H5I_id_type_list_g[type])
449 	HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "supplied type does not exist")
450 
451     if(num_members) {
452         int members;
453 
454         if((members = H5I_nmembers(type)) < 0)
455             HGOTO_ERROR(H5E_ATOM, H5E_CANTCOUNT, FAIL, "can't compute number of members")
456 
457         *num_members = (hsize_t)members;
458     } /* end if */
459 
460 done:
461     FUNC_LEAVE_API(ret_value)
462 } /* end H5Inmembers() */
463 
464 
465 /*-------------------------------------------------------------------------
466  * Function:	H5I_nmembers
467  *
468  * Purpose:	Returns the number of members in a type.
469  *
470  * Return:	Success:	Number of members; zero if the type is empty
471  *				or has been deleted.
472  *
473  *		Failure:	Negative
474  *
475  * Programmer:	Robb Matzke
476  *              Wednesday, March 24, 1999
477  *
478  *-------------------------------------------------------------------------
479  */
480 int
H5I_nmembers(H5I_type_t type)481 H5I_nmembers(H5I_type_t type)
482 {
483     H5I_id_type_t	*type_ptr = NULL;
484     int		ret_value;
485 
486     FUNC_ENTER_NOAPI(FAIL)
487 
488     if(type <= H5I_BADID || type >= H5I_next_type)
489 	HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
490     if(NULL == (type_ptr = H5I_id_type_list_g[type]) || type_ptr->init_count <= 0)
491 	HGOTO_DONE(0);
492 
493     /* Set return value */
494     H5_ASSIGN_OVERFLOW(ret_value, type_ptr->id_count, unsigned, int);
495 
496 done:
497     FUNC_LEAVE_NOAPI(ret_value)
498 } /* end H5I_nmembers() */
499 
500 
501 /*-------------------------------------------------------------------------
502  * Function:	H5Iclear_type
503  *
504  * Purpose:	Removes all objects from the type, calling the free
505  *		function for each object regardless of the reference count.
506  *		Public interface to H5I_clear_type.
507  *
508  * Return:	Success:	Non-negative
509  *		Failure:	negative
510  *
511  * Programmer:	James Laird
512  *		Nathaniel Furrer
513  *              Friday, April 23, 2004
514  *
515  *-------------------------------------------------------------------------
516  */
517 herr_t
H5Iclear_type(H5I_type_t type,hbool_t force)518 H5Iclear_type(H5I_type_t type, hbool_t force)
519 {
520     herr_t ret_value;                      /* Return value */
521 
522     FUNC_ENTER_API(FAIL)
523     H5TRACE2("e", "Itb", type, force);
524 
525     if(H5I_IS_LIB_TYPE(type))
526         HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type")
527 
528     ret_value = H5I_clear_type(type, force, TRUE);
529 
530 done:
531     FUNC_LEAVE_API(ret_value)
532 } /* end H5Iclear_type() */
533 
534 
535 /*-------------------------------------------------------------------------
536  * Function:	H5I__free_cb
537  *
538  * Purpose:	Callback for freeing ID nodes in H5I__remove_common
539  *
540  * Return:	Success:	Non-negative
541  *		Failure:	Negative
542  *
543  * Programmer:	Quincey Koziol
544  *              Friday, October 4, 2013
545  *
546  *-------------------------------------------------------------------------
547  */
548 static herr_t
H5I__free_cb(void * _item,void UNUSED * _key,void UNUSED * _udata)549 H5I__free_cb(void *_item, void UNUSED *_key, void UNUSED *_udata)
550 {
551     H5I_id_info_t *item = (H5I_id_info_t *)_item;       /* Pointer to the ID node */
552 
553     FUNC_ENTER_STATIC_NOERR
554 
555     /* Sanity check */
556     HDassert(item);
557 
558     item = H5FL_FREE(H5I_id_info_t, item);
559 
560     FUNC_LEAVE_NOAPI(H5_ITER_CONT)
561 } /* end H5I__free_cb() */
562 
563 
564 /*-------------------------------------------------------------------------
565  * Function:	H5I_clear_type
566  *
567  * Purpose:	Removes all objects from the type, calling the free
568  *		function for each object regardless of the reference count.
569  *
570  * Return:	Success:	Non-negative
571  *		Failure:	negative
572  *
573  * Programmer:	Robb Matzke
574  *              Wednesday, March 24, 1999
575  *
576  *-------------------------------------------------------------------------
577  */
578 herr_t
H5I_clear_type(H5I_type_t type,hbool_t force,hbool_t app_ref)579 H5I_clear_type(H5I_type_t type, hbool_t force, hbool_t app_ref)
580 {
581     H5I_id_type_t *type_ptr;	        /* ptr to the atomic type */
582     H5SL_node_t *curr_node;             /* Current skip list node ptr */
583     H5SL_node_t *next_node;             /* Next skip list node ptr */
584     int		ret_value = SUCCEED;    /* Return value */
585 
586     FUNC_ENTER_NOAPI(FAIL)
587 
588     if(type <= H5I_BADID || type >= H5I_next_type)
589 	HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
590 
591     type_ptr = H5I_id_type_list_g[type];
592     if(type_ptr == NULL || type_ptr->init_count <= 0)
593 	HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type")
594 
595     /*
596      * Call free method for all objects in type regardless of their reference
597      * counts. Ignore the return value from from the free method and remove
598      * object from type regardless if FORCE is non-zero.
599      */
600     for(curr_node = H5SL_first(type_ptr->ids); curr_node; curr_node = next_node) {
601         H5I_id_info_t *cur;         /* Current ID being worked with */
602         hbool_t    delete_node;     /* Flag to indicate node should be removed from linked list */
603 
604         /* Get ID for this node */
605         if(NULL == (cur = (H5I_id_info_t *)H5SL_item(curr_node)))
606             HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't get ID info for node")
607 
608         /*
609          * Do nothing to the object if the reference count is larger than
610          * one and forcing is off.
611          */
612         if(!force && (cur->count - (!app_ref * cur->app_count)) > 1)
613             delete_node = FALSE;
614         else {
615             /* Check for a 'free' function and call it, if it exists */
616             /* (Casting away const OK -QAK) */
617             if(type_ptr->cls->free_func && (type_ptr->cls->free_func)((void *)cur->obj_ptr) < 0) {
618                 if(force) {
619 #ifdef H5I_DEBUG
620                     if(H5DEBUG(I)) {
621                         fprintf(H5DEBUG(I), "H5I: free type=%d obj=0x%08lx "
622                             "failure ignored\n", (int)type,
623                             (unsigned long)(cur->obj_ptr));
624                     } /* end if */
625 #endif /*H5I_DEBUG*/
626 
627                     /* Indicate node should be removed from list */
628                     delete_node = TRUE;
629                 } /* end if */
630                 else {
631                     /* Indicate node should _NOT_ be removed from list */
632                     delete_node = FALSE;
633                 } /* end else */
634             } /* end if */
635             else {
636                 /* Indicate node should be removed from list */
637                 delete_node = TRUE;
638             } /* end else */
639         } /* end else */
640 
641         /* Get the next node in the list */
642         next_node = H5SL_next(curr_node);
643 
644         /* Check if we should delete this node or not */
645         if(delete_node) {
646             /* Decrement the number of IDs in the type */
647             (type_ptr->id_count)--;
648 
649             /* Remove the node from the list */
650             if(NULL == H5SL_remove(type_ptr->ids, &cur->id))
651                 HGOTO_ERROR(H5E_ATOM, H5E_CANTDELETE, FAIL, "can't remove ID node from skip list")
652 
653             /* Free the node */
654             cur = H5FL_FREE(H5I_id_info_t, cur);
655         } /* end if */
656     } /* end for */
657 
658     /* Also free any ID structures being retained for potential re-use */
659     if(type_ptr->avail_count > 0) {
660         if(H5SL_free(type_ptr->avail_ids, H5I__free_cb, NULL) < 0)
661             HGOTO_ERROR(H5E_ATOM, H5E_CANTREMOVE, FAIL, "can't release available ID nodes")
662         type_ptr->avail_count = 0;
663     } /* end if */
664 
665 done:
666     FUNC_LEAVE_NOAPI(ret_value)
667 } /* end H5I_clear_type() */
668 
669 
670 /*-------------------------------------------------------------------------
671  * Function:	H5Idestroy_type
672  *
673  * Purpose:	Destroys a type along with all atoms in that type
674  *		regardless of their reference counts. Destroying IDs
675  *		involves calling the free-func for each ID's object and
676  *		then adding the ID struct to the ID free list.  Public
677  *		interface to H5I__destroy_type.
678  *
679  * Return:	Zero on success/Negative on failure
680  *
681  * Programmer:	Nathaniel Furrer
682  *		James Laird
683  *
684  *-------------------------------------------------------------------------
685  */
686 herr_t
H5Idestroy_type(H5I_type_t type)687 H5Idestroy_type(H5I_type_t type)
688 {
689     herr_t ret_value;           /* Return value */
690 
691     FUNC_ENTER_API(FAIL)
692     H5TRACE1("e", "It", type);
693 
694     if(H5I_IS_LIB_TYPE(type))
695         HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type")
696 
697     ret_value = H5I__destroy_type(type);
698 
699 done:
700     FUNC_LEAVE_API(ret_value)
701 } /* end H5Idestroy_type() */
702 
703 
704 /*-------------------------------------------------------------------------
705  * Function:	H5I__destroy_type
706  *
707  * Purpose:	Destroys a type along with all atoms in that type
708  *		regardless of their reference counts. Destroying IDs
709  *		involves calling the free-func for each ID's object and
710  *		then adding the ID struct to the ID free list.
711  *
712  * Return:	Zero on success/Negative on failure
713  *
714  * Programmer:	Nathaniel Furrer
715  *		James Laird
716  *
717  *-------------------------------------------------------------------------
718  */
719 static herr_t
H5I__destroy_type(H5I_type_t type)720 H5I__destroy_type(H5I_type_t type)
721 {
722     H5I_id_type_t *type_ptr;	/* ptr to the atomic type */
723     herr_t ret_value = SUCCEED; /* Return value */
724 
725     FUNC_ENTER_STATIC
726 
727     if(type <= H5I_BADID || type >= H5I_next_type)
728         HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
729 
730     type_ptr = H5I_id_type_list_g[type];
731     if(type_ptr == NULL || type_ptr->init_count <= 0)
732         HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type")
733 
734     /* Close/clear/destroy all IDs for this type */
735     H5E_BEGIN_TRY {
736         H5I_clear_type(type, TRUE, FALSE);
737     } H5E_END_TRY       /*don't care about errors*/
738 
739     /* Check if we should release the ID class */
740     if(type_ptr->cls->flags & H5I_CLASS_IS_APPLICATION)
741         type_ptr->cls = H5FL_FREE(H5I_class_t, (void *)type_ptr->cls);
742 
743     if(H5SL_close(type_ptr->avail_ids) < 0)
744         HGOTO_ERROR(H5E_ATOM, H5E_CANTCLOSEOBJ, FAIL, "can't close skip list")
745     type_ptr->avail_ids = NULL;
746 
747     if(H5SL_close(type_ptr->ids) < 0)
748         HGOTO_ERROR(H5E_ATOM, H5E_CANTCLOSEOBJ, FAIL, "can't close skip list")
749     type_ptr->ids = NULL;
750 
751     type_ptr = H5FL_FREE(H5I_id_type_t, type_ptr);
752     H5I_id_type_list_g[type] = NULL;
753 
754 done:
755     FUNC_LEAVE_NOAPI(ret_value)
756 } /* end H5I__destroy_type() */
757 
758 
759 /*-------------------------------------------------------------------------
760  * Function:	H5Iregister
761  *
762  * Purpose:	Public interface to H5I_register.
763  *
764  * Return:	Success:	New object id.
765  *		Failure:	Negative
766  *
767  * Programmer:	Nathaniel Furrer
768  *		James Laird
769  *
770  *-------------------------------------------------------------------------
771  */
772 hid_t
H5Iregister(H5I_type_t type,const void * object)773 H5Iregister(H5I_type_t type, const void *object)
774 {
775     hid_t ret_value;                      /* Return value */
776 
777     FUNC_ENTER_API(H5I_INVALID_HID)
778     H5TRACE2("i", "It*x", type, object);
779 
780     if(H5I_IS_LIB_TYPE(type))
781         HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type")
782 
783     ret_value = H5I_register(type, object, TRUE);
784 
785 done:
786     FUNC_LEAVE_API(ret_value)
787 } /* end H5Iregister() */
788 
789 
790 /*-------------------------------------------------------------------------
791  * Function:	H5I__wrapped_cb
792  *
793  * Purpose:	Callback for searching for next free ID, when IDs have wrapped
794  *
795  * Return:	Success:	Non-negative
796  *		Failure:	Negative
797  *
798  * Programmer:	Quincey Koziol
799  *              Thursday, October 3, 2013
800  *
801  *-------------------------------------------------------------------------
802  */
803 static herr_t
H5I__wrapped_cb(void * _item,void UNUSED * _key,void * _udata)804 H5I__wrapped_cb(void *_item, void UNUSED *_key, void *_udata)
805 {
806     H5I_id_info_t *item = (H5I_id_info_t *)_item;       /* Pointer to the ID node */
807     H5I_wrap_ud_t *udata = (H5I_wrap_ud_t *)_udata;     /* Pointer to user data */
808     int ret_value = H5_ITER_CONT;                       /* Return value */
809 
810     FUNC_ENTER_STATIC_NOERR
811 
812     /* Sanity check */
813     HDassert(item);
814     HDassert(udata);
815 
816     /* Break out if we see a free ID */
817     if(udata->nextid != item->id) {
818         /* Sanity check */
819         HDassert(item->id > udata->nextid);
820 
821         ret_value = H5_ITER_STOP;
822     } /* end if */
823     else
824         /* Increment to expect the next ID */
825         udata->nextid++;
826 
827     FUNC_LEAVE_NOAPI(ret_value)
828 } /* end H5I__wrapped_cb() */
829 
830 
831 /*-------------------------------------------------------------------------
832  * Function:	H5I_register
833  *
834  * Purpose:	Registers an OBJECT in a TYPE and returns an ID for it.
835  *		This routine does _not_ check for unique-ness of the objects,
836  *		if you register an object twice, you will get two different
837  *		IDs for it.  This routine does make certain that each ID in a
838  *		type is unique.  IDs are created by getting a unique number
839  *		for the type the ID is in and incorporating the type into
840  *		the ID which is returned to the user.
841  *
842  * Return:	Success:	New object id.
843  *		Failure:	Negative
844  *
845  * Programmer:	Unknown
846  *
847  *-------------------------------------------------------------------------
848  */
849 hid_t
H5I_register(H5I_type_t type,const void * object,hbool_t app_ref)850 H5I_register(H5I_type_t type, const void *object, hbool_t app_ref)
851 {
852     H5I_id_type_t	*type_ptr;	/*ptr to the type		*/
853     H5I_id_info_t	*id_ptr;	/*ptr to the new ID information */
854     hid_t		ret_value = SUCCEED; /*return value		*/
855 
856     FUNC_ENTER_NOAPI(FAIL)
857 
858     /* Check arguments */
859     if(type <= H5I_BADID || type >= H5I_next_type)
860 	HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
861     type_ptr = H5I_id_type_list_g[type];
862     if(NULL == type_ptr || type_ptr->init_count <= 0)
863 	HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type")
864 
865     /* If there is an available ID structure, use it. */
866     if(type_ptr->avail_count > 0) {
867         /* Use existing available ID struct */
868         if(NULL == (id_ptr = (H5I_id_info_t *)H5SL_remove_first(type_ptr->avail_ids)))
869             HGOTO_ERROR(H5E_ATOM, H5E_CANTREMOVE, FAIL, "can't remove ID from available ID list")
870 
871         /* Decrease count of available ID structures */
872         type_ptr->avail_count--;
873     } /* end if */
874     /* If no available ID structure, then create a new id for use, and
875      * allocate a new struct to house it. */
876     else {
877         /* Allocate new ID struct */
878         if(NULL == (id_ptr = H5FL_MALLOC(H5I_id_info_t)))
879             HGOTO_ERROR(H5E_ATOM, H5E_NOSPACE, FAIL, "memory allocation failed")
880 
881         /* Make a new ID */
882         id_ptr->id = H5I_MAKE(type, type_ptr->nextid);
883 
884         /* Increment nextid value */
885         type_ptr->nextid++;
886     } /* end if */
887 
888     /* Fill in remaining fields of ID struct */
889     id_ptr->count = 1; /*initial reference count*/
890     id_ptr->app_count = !!app_ref;
891     id_ptr->obj_ptr = object;
892 
893     /* Insert into the type */
894     if(H5SL_insert(type_ptr->ids, id_ptr, &id_ptr->id) < 0)
895         HGOTO_ERROR(H5E_ATOM, H5E_CANTINSERT, FAIL, "can't insert ID node into skip list")
896     type_ptr->id_count++;
897 
898     /*
899      * This next section of code checks for the 'nextid' getting too large and
900      * wrapping around, thus necessitating checking for duplicate IDs being
901      * handed out.
902      */
903     if(type_ptr->nextid > (hid_t)ID_MASK)
904 	type_ptr->wrapped = TRUE;
905 
906     /*
907      * If we've wrapped around then we need to check for duplicate id's being
908      * handed out.
909      */
910     if(type_ptr->wrapped) {
911         H5I_wrap_ud_t udata;    /* User data for iteration */
912         herr_t iter_status;     /* Iteration status */
913 
914         /* Set up user data for iteration */
915         udata.nextid = (hid_t)type_ptr->cls->reserved;
916 
917         /* Iterate over all the ID nodes, looking for a gap in the ID sequence */
918         if((iter_status = H5SL_iterate(type_ptr->ids, H5I__wrapped_cb, &udata)) < 0)
919             HGOTO_ERROR(H5E_ATOM, H5E_BADITER, FAIL, "ID iteration failed")
920 
921         /* If we didn't break out of the iteration and we're at the max. ID, we've used all the IDs */
922         if(0 == iter_status && udata.nextid >= ID_MASK)
923             HGOTO_ERROR(H5E_ATOM, H5E_NOIDS, FAIL, "no IDs available in type")
924 
925         /* Sanity check */
926         HDassert(udata.nextid < ID_MASK);
927 
928         /* Retain the next ID for the class */
929         type_ptr->nextid = udata.nextid;
930     } /* end if */
931 
932     /* Set return value */
933     ret_value = id_ptr->id;
934 
935 done:
936     FUNC_LEAVE_NOAPI(ret_value)
937 } /* end H5I_register() */
938 
939 
940 /*-------------------------------------------------------------------------
941  * Function:	H5I_subst
942  *
943  * Purpose:	Substitute a new object pointer for the specified ID.
944  *
945  * Return:	Success:	Non-null previous object pointer associated
946  *				with the specified ID.
947  *		Failure:	NULL
948  *
949  * Programmer:	Quincey Koziol
950  *		Saturday, February 27, 2010
951  *
952  *-------------------------------------------------------------------------
953  */
954 void *
H5I_subst(hid_t id,const void * new_object)955 H5I_subst(hid_t id, const void *new_object)
956 {
957     H5I_id_info_t	*id_ptr;	/* Ptr to the atom	*/
958     void		*ret_value;	/* Return value		*/
959 
960     FUNC_ENTER_NOAPI(NULL)
961 
962     /* General lookup of the ID */
963     if(NULL == (id_ptr = H5I__find_id(id)))
964         HGOTO_ERROR(H5E_ATOM, H5E_NOTFOUND, NULL, "can't get ID ref count")
965 
966     /* Get the old object pointer to return */
967     /* (Casting away const OK -QAK) */
968     ret_value = (void *)id_ptr->obj_ptr;
969 
970     /* Set the new object pointer for the ID */
971     id_ptr->obj_ptr = new_object;
972 
973 done:
974     FUNC_LEAVE_NOAPI(ret_value)
975 } /* end if */
976 
977 
978 /*-------------------------------------------------------------------------
979  * Function:	H5I_object
980  *
981  * Purpose:	Find an object pointer for the specified ID.
982  *
983  * Return:	Success:	Non-null object pointer associated with the
984  *				specified ID.
985  *		Failure:	NULL
986  *
987  * Programmer:	Unknown
988  *
989  *-------------------------------------------------------------------------
990  */
991 void *
H5I_object(hid_t id)992 H5I_object(hid_t id)
993 {
994     H5I_id_info_t	*id_ptr;		/*ptr to the new atom	*/
995     void		*ret_value = NULL;	/*return value		*/
996 
997     FUNC_ENTER_NOAPI(NULL)
998 
999     /* General lookup of the ID */
1000     if(NULL != (id_ptr = H5I__find_id(id))) {
1001         /* Get the object pointer to return */
1002         /* (Casting away const OK -QAK) */
1003         ret_value = (void *)id_ptr->obj_ptr;
1004     } /* end if */
1005 
1006 done:
1007     FUNC_LEAVE_NOAPI(ret_value)
1008 } /* end if */
1009 
1010 
1011 /*-------------------------------------------------------------------------
1012  * Function:	H5Iobject_verify
1013  *
1014  * Purpose:	Find an object pointer for the specified ID, verifying that
1015  *                  its in a particular type.  Public interface to
1016  *					H5I_object_verify.
1017  *
1018  * Return:	Success:	Non-null object pointer associated with the
1019  *				specified ID.
1020  *		Failure:	NULL
1021  *
1022  * Programmer:	Nathaniel Furrer
1023  *		James Laird
1024  *		Friday, April 23, 2004
1025  *
1026  *-------------------------------------------------------------------------
1027  */
1028 void *
H5Iobject_verify(hid_t id,H5I_type_t id_type)1029 H5Iobject_verify(hid_t id, H5I_type_t id_type)
1030 {
1031     void * ret_value;                      /* Return value */
1032 
1033     FUNC_ENTER_API(NULL)
1034 
1035     if(H5I_IS_LIB_TYPE(id_type))
1036         HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "cannot call public function on library type")
1037 
1038     if(id_type < 1 || id_type >= H5I_next_type)
1039         HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "identifier has invalid type")
1040 
1041     ret_value = H5I_object_verify(id, id_type);
1042 
1043 done:
1044     FUNC_LEAVE_API(ret_value)
1045 } /* end H5Iobject_verify() */
1046 
1047 
1048 /*-------------------------------------------------------------------------
1049  * Function:	H5I_object_verify
1050  *
1051  * Purpose:	Find an object pointer for the specified ID, verifying that
1052  *                  its in a particular type.
1053  *
1054  * Return:	Success:	Non-null object pointer associated with the
1055  *				specified ID.
1056  *		Failure:	NULL
1057  *
1058  * Programmer:	Quincey Koziol
1059  *		Wednesday, July 31, 2002
1060  *
1061  *-------------------------------------------------------------------------
1062  */
1063 void *
H5I_object_verify(hid_t id,H5I_type_t id_type)1064 H5I_object_verify(hid_t id, H5I_type_t id_type)
1065 {
1066     H5I_id_info_t	*id_ptr = NULL;		/*ptr to the new atom	*/
1067     void		*ret_value = NULL;	/*return value		*/
1068 
1069     FUNC_ENTER_NOAPI(NULL)
1070 
1071     HDassert(id_type >= 1 && id_type < H5I_next_type);
1072 
1073     /* Verify that the type of the ID is correct & lookup the ID */
1074     if(id_type == H5I_TYPE(id) && NULL != (id_ptr = H5I__find_id(id))) {
1075         /* Get the object pointer to return */
1076         /* (Casting away const OK -QAK) */
1077         ret_value = (void *)id_ptr->obj_ptr;
1078     } /* end if */
1079 
1080 done:
1081     FUNC_LEAVE_NOAPI(ret_value)
1082 } /* H5I_object_verify() */
1083 
1084 
1085 /*-------------------------------------------------------------------------
1086  * Function:	H5I_get_type
1087  *
1088  * Purpose:	Given an object ID return the type to which it
1089  *		belongs.  The ID need not be the ID of an object which
1090  *		currently exists because the type number is encoded
1091  *		in the object ID.
1092  *
1093  * Return:	Success:	A valid type number
1094  *		Failure:	H5I_BADID, a negative value.
1095  *
1096  * Programmer:	Robb Matzke
1097  *		Friday, February 19, 1999
1098  *
1099  *-------------------------------------------------------------------------
1100  */
1101 H5I_type_t
H5I_get_type(hid_t id)1102 H5I_get_type(hid_t id)
1103 {
1104     H5I_type_t		ret_value = H5I_BADID;
1105 
1106     FUNC_ENTER_NOAPI(H5I_BADID)
1107 
1108     if(id > 0)
1109         ret_value = H5I_TYPE(id);
1110 
1111     HDassert(ret_value >= H5I_BADID && ret_value < H5I_next_type);
1112 
1113 done:
1114     FUNC_LEAVE_NOAPI(ret_value)
1115 } /* end H5I_get_type() */
1116 
1117 
1118 /*-------------------------------------------------------------------------
1119  * Function:	H5Iget_type
1120  *
1121  * Purpose:	The public version of H5I_get_type(), obtains a type number
1122  *		when given an ID.  The ID need not be the ID of an
1123  *		object which currently exists because the type number is
1124  *		encoded as part of the ID.
1125  *
1126  * Return:	Success:	Type number
1127  *		Failure:	H5I_BADID, a negative value
1128  *
1129  * Programmer:	Unknown
1130  *
1131  *-------------------------------------------------------------------------
1132  */
1133 H5I_type_t
H5Iget_type(hid_t id)1134 H5Iget_type(hid_t id)
1135 {
1136     H5I_type_t		ret_value = H5I_BADID;          /* Return value */
1137 
1138     FUNC_ENTER_API(H5I_BADID)
1139     H5TRACE1("It", "i", id);
1140 
1141     ret_value = H5I_get_type(id);
1142 
1143     if(ret_value <= H5I_BADID || ret_value >= H5I_next_type || NULL == H5I_object(id))
1144 	HGOTO_DONE(H5I_BADID);
1145 
1146 done:
1147     FUNC_LEAVE_API(ret_value)
1148 } /* end H5Iget_type() */
1149 
1150 
1151 /*-------------------------------------------------------------------------
1152  * Function:	H5Iremove_verify
1153  *
1154  * Purpose:	Removes the specified ID from its type, first checking that the
1155  *			type of the ID and the type type are the same.  Public interface to
1156  *			H5I__remove_verify.
1157  *
1158  * Return:	Success:	A pointer to the object that was removed, the
1159  *				same pointer which would have been found by
1160  *				calling H5I_object().
1161  *		Failure:	NULL
1162  *
1163  * Programmer:	James Laird
1164  *		Nathaniel Furrer
1165  *
1166  *-------------------------------------------------------------------------
1167  */
1168 void *
H5Iremove_verify(hid_t id,H5I_type_t id_type)1169 H5Iremove_verify(hid_t id, H5I_type_t id_type)
1170 {
1171     void * ret_value;                      /* Return value */
1172 
1173     FUNC_ENTER_API(NULL)
1174 
1175     if(H5I_IS_LIB_TYPE(id_type))
1176         HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "cannot call public function on library type")
1177 
1178     /* Remove the id */
1179     ret_value = H5I__remove_verify(id, id_type);
1180 
1181 done:
1182     FUNC_LEAVE_API(ret_value)
1183 } /* end H5Iremove_verify() */
1184 
1185 
1186 /*-------------------------------------------------------------------------
1187  * Function:	H5I__remove_verify
1188  *
1189  * Purpose:	Removes the specified ID from its type, first checking that
1190  *			the ID's type is the same as the ID type supplied as an argument
1191  *
1192  * Return:	Success:	A pointer to the object that was removed, the
1193  *				same pointer which would have been found by
1194  *				calling H5I_object().
1195  *		Failure:	NULL
1196  *
1197  * Programmer:	James Laird
1198  *		Nat Furrer
1199  *
1200  *-------------------------------------------------------------------------
1201  */
1202 void *
H5I__remove_verify(hid_t id,H5I_type_t id_type)1203 H5I__remove_verify(hid_t id, H5I_type_t id_type)
1204 {
1205     void * ret_value = NULL;	/*return value			*/
1206 
1207     FUNC_ENTER_STATIC_NOERR
1208 
1209     /* Argument checking will be performed by H5I_remove() */
1210 
1211     /* Verify that the type of the ID is correct */
1212     if(id_type == H5I_TYPE(id))
1213         ret_value = H5I_remove(id);
1214 
1215     FUNC_LEAVE_NOAPI(ret_value)
1216 } /* end H5I__remove_verify() */
1217 
1218 
1219 /*-------------------------------------------------------------------------
1220  * Function:	H5I__remove_common
1221  *
1222  * Purpose:	Common code to remove a specified ID from its type.
1223  *
1224  * Return:	Success:	A pointer to the object that was removed, the
1225  *				same pointer which would have been found by
1226  *				calling H5I_object().
1227  *		Failure:	NULL
1228  *
1229  * Programmer:  Quincey Koziol
1230  *              October 3, 2013
1231  *
1232  *-------------------------------------------------------------------------
1233  */
1234 static void *
H5I__remove_common(H5I_id_type_t * type_ptr,hid_t id)1235 H5I__remove_common(H5I_id_type_t *type_ptr, hid_t id)
1236 {
1237     H5I_id_info_t	*curr_id;	/*ptr to the current atom	*/
1238     void *	        ret_value;	/*return value			*/
1239 
1240     FUNC_ENTER_STATIC
1241 
1242     /* Sanity check */
1243     HDassert(type_ptr);
1244 
1245     /* Get the ID node for the ID */
1246     if(NULL == (curr_id = (H5I_id_info_t *)H5SL_remove(type_ptr->ids, &id)))
1247         HGOTO_ERROR(H5E_ATOM, H5E_CANTDELETE, NULL, "can't remove ID node from skip list")
1248 
1249     /* (Casting away const OK -QAK) */
1250     ret_value = (void *)curr_id->obj_ptr;
1251 
1252     /* If there's room, and we can save IDs of this type, then
1253        save the struct (and its ID) for future re-use */
1254     if((type_ptr->cls->flags & H5I_CLASS_REUSE_IDS)
1255             && (type_ptr->avail_count < MAX_FREE_ID_STRUCTS)) {
1256         if(H5SL_insert(type_ptr->avail_ids, curr_id, &curr_id->id) < 0)
1257             HGOTO_ERROR(H5E_ATOM, H5E_CANTINSERT, NULL, "can't insert available ID node into skip list")
1258         type_ptr->avail_count++;
1259     } /* end if */
1260     /* Otherwise, just toss it. */
1261     else
1262         curr_id = H5FL_FREE(H5I_id_info_t, curr_id);
1263 
1264     /* Decrement the number of IDs in the type */
1265     (type_ptr->id_count)--;
1266 
1267     /* If there are no more IDs of this type, then we can free all available
1268        ID strutures, and reset starting typeid and wrapped status. */
1269     if(0 == type_ptr->id_count) {
1270         if(H5SL_free(type_ptr->avail_ids, H5I__free_cb, NULL) < 0)
1271             HGOTO_ERROR(H5E_ATOM, H5E_CANTREMOVE, NULL, "can't release available ID nodes")
1272         type_ptr->avail_count = 0;
1273 
1274         type_ptr->nextid = (hid_t)type_ptr->cls->reserved;
1275         type_ptr->wrapped = FALSE;
1276     } /* end if */
1277 
1278 done:
1279     FUNC_LEAVE_NOAPI(ret_value)
1280 } /* end H5I__remove_common() */
1281 
1282 
1283 /*-------------------------------------------------------------------------
1284  * Function:	H5I_remove
1285  *
1286  * Purpose:	Removes the specified ID from its type.
1287  *
1288  * Return:	Success:	A pointer to the object that was removed, the
1289  *				same pointer which would have been found by
1290  *				calling H5I_object().
1291  *		Failure:	NULL
1292  *
1293  * Programmer:	Unknown
1294  *
1295  *-------------------------------------------------------------------------
1296  */
1297 void *
H5I_remove(hid_t id)1298 H5I_remove(hid_t id)
1299 {
1300     H5I_id_type_t	*type_ptr;	/*ptr to the atomic type	*/
1301     H5I_type_t		type;		/*atom's atomic type		*/
1302     void *	        ret_value;	/*return value			*/
1303 
1304     FUNC_ENTER_NOAPI(NULL)
1305 
1306     /* Check arguments */
1307     type = H5I_TYPE(id);
1308     if(type <= H5I_BADID || type >= H5I_next_type)
1309 	HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "invalid type number")
1310     type_ptr = H5I_id_type_list_g[type];
1311     if(type_ptr == NULL || type_ptr->init_count <= 0)
1312 	HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "invalid type")
1313 
1314     /* Remove the node from the type */
1315     if(NULL == (ret_value = H5I__remove_common(type_ptr, id)))
1316         HGOTO_ERROR(H5E_ATOM, H5E_CANTDELETE, NULL, "can't remove ID node")
1317 
1318 done:
1319     FUNC_LEAVE_NOAPI(ret_value)
1320 } /* end H5I_remove() */
1321 
1322 
1323 /*-------------------------------------------------------------------------
1324  * Function:	H5Idec_ref
1325  *
1326  * Purpose:	Decrements the number of references outstanding for an ID.
1327  *              If the reference count for an ID reaches zero, the object
1328  *              will be closed.
1329  *
1330  * Return:	Success:	New reference count
1331  *		Failure:	Negative
1332  *
1333  * Programmer:  Quincey Koziol
1334  *              Dec  7, 2003
1335  *
1336  *-------------------------------------------------------------------------
1337  */
1338 int
H5Idec_ref(hid_t id)1339 H5Idec_ref(hid_t id)
1340 {
1341     int ret_value;                      /* Return value */
1342 
1343     FUNC_ENTER_API(FAIL)
1344     H5TRACE1("Is", "i", id);
1345 
1346     /* Check arguments */
1347     if(id < 0)
1348 	HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "invalid ID")
1349 
1350     /* Do actual decrement operation */
1351     if((ret_value = H5I_dec_app_ref(id)) < 0)
1352         HGOTO_ERROR(H5E_ATOM, H5E_CANTDEC, FAIL, "can't decrement ID ref count")
1353 
1354 done:
1355     FUNC_LEAVE_API(ret_value)
1356 } /* end H5Idec_ref() */
1357 
1358 
1359 /*-------------------------------------------------------------------------
1360  * Function:	H5I_dec_ref
1361  *
1362  * Purpose:	Decrements the number of references outstanding for an ID.
1363  *		This will fail if the type is not a reference counted type.
1364  *		The ID type's 'free' function will be called for the ID
1365  *		if the reference count for the ID reaches 0 and a free
1366  *		function has been defined at type creation time.
1367  *
1368  * Return:	Success:	New reference count.
1369  *
1370  *		Failure:	Negative
1371  *
1372  * Programmer:	Unknown
1373  *
1374  *-------------------------------------------------------------------------
1375  */
1376 int
H5I_dec_ref(hid_t id)1377 H5I_dec_ref(hid_t id)
1378 {
1379     H5I_type_t		type;		/*type the object is in*/
1380     H5I_id_type_t	*type_ptr;	/*ptr to the type	*/
1381     H5I_id_info_t	*id_ptr;	/*ptr to the new ID	*/
1382     int ret_value;                      /* Return value */
1383 
1384     FUNC_ENTER_NOAPI(FAIL)
1385 
1386     /* Sanity check */
1387     HDassert(id >= 0);
1388 
1389     /* Check arguments */
1390     type = H5I_TYPE(id);
1391     if(type <= H5I_BADID || type >= H5I_next_type)
1392 	HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
1393     type_ptr = H5I_id_type_list_g[type];
1394     if(NULL == type_ptr || type_ptr->init_count <= 0)
1395 	HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
1396 
1397     /* General lookup of the ID */
1398     if(NULL == (id_ptr = (H5I_id_info_t *)H5SL_search(type_ptr->ids, &id)))
1399 	HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't locate ID")
1400 
1401     /*
1402      * If this is the last reference to the object then invoke the type's
1403      * free method on the object. If the free method is undefined or
1404      * successful then remove the object from the type; otherwise leave
1405      * the object in the type without decrementing the reference
1406      * count. If the reference count is more than one then decrement the
1407      * reference count without calling the free method.
1408      *
1409      * Beware: the free method may call other H5I functions.
1410      *
1411      * If an object is closing, we can remove the ID even though the free
1412      * method might fail.  This can happen when a mandatory filter fails to
1413      * write when a dataset is closed and the chunk cache is flushed to the
1414      * file.  We have to close the dataset anyway. (SLU - 2010/9/7)
1415      */
1416     if(1 == id_ptr->count) {
1417         /* (Casting away const OK -QAK) */
1418         if(!type_ptr->cls->free_func || (type_ptr->cls->free_func)((void *)id_ptr->obj_ptr) >= 0) {
1419             /* Remove the node from the type */
1420             if(NULL == H5I__remove_common(type_ptr, id))
1421                 HGOTO_ERROR(H5E_ATOM, H5E_CANTDELETE, FAIL, "can't remove ID node")
1422             ret_value = 0;
1423         } /* end if */
1424         else
1425             ret_value = FAIL;
1426     } /* end if */
1427     else {
1428         --(id_ptr->count);
1429         ret_value = (int)id_ptr->count;
1430     } /* end else */
1431 
1432 done:
1433     FUNC_LEAVE_NOAPI(ret_value)
1434 } /* end H5I_dec_ref() */
1435 
1436 
1437 /*-------------------------------------------------------------------------
1438  * Function:	H5I_dec_app_ref
1439  *
1440  * Purpose:	H5I_dec_ref wrapper for case of modifying the application ref.
1441  *		count for an ID as well as normal reference count.
1442  *
1443  * Return:	Success:	New app. reference count.
1444  *		Failure:	Negative
1445  *
1446  * Programmer:  Quincey Koziol
1447  *              Sept 16, 2010
1448  *
1449  *-------------------------------------------------------------------------
1450  */
1451 int
H5I_dec_app_ref(hid_t id)1452 H5I_dec_app_ref(hid_t id)
1453 {
1454     H5I_id_info_t	*id_ptr;	/*ptr to the new ID	*/
1455     int ret_value;                      /* Return value */
1456 
1457     FUNC_ENTER_NOAPI(FAIL)
1458 
1459     /* Sanity check */
1460     HDassert(id >= 0);
1461 
1462     /* Call regular decrement reference count routine */
1463     if((ret_value = H5I_dec_ref(id)) < 0)
1464         HGOTO_ERROR(H5E_ATOM, H5E_CANTDEC, FAIL, "can't decrement ID ref count")
1465 
1466     /* Check if the ID still exists */
1467     if(ret_value > 0) {
1468         /* General lookup of the ID */
1469         if(NULL == (id_ptr = H5I__find_id(id)))
1470             HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't locate ID")
1471 
1472         /* Adjust app_ref */
1473         --(id_ptr->app_count);
1474         HDassert(id_ptr->count >= id_ptr->app_count);
1475 
1476         /* Set return value */
1477         ret_value = (int)id_ptr->app_count;
1478     } /* end if */
1479 
1480 done:
1481     FUNC_LEAVE_NOAPI(ret_value)
1482 } /* end H5I_dec_app_ref() */
1483 
1484 
1485 /*-------------------------------------------------------------------------
1486  * Function:	H5I_dec_app_ref_always_close
1487  *
1488  * Purpose:	H5I_dec_app_ref wrapper for case of always closing the ID,
1489  *		even when the free routine fails
1490  *
1491  * Return:	Success:	New app. reference count.
1492  *		Failure:	Negative
1493  *
1494  * Programmer:  Quincey Koziol
1495  *              Sept 16, 2010
1496  *
1497  *-------------------------------------------------------------------------
1498  */
1499 int
H5I_dec_app_ref_always_close(hid_t id)1500 H5I_dec_app_ref_always_close(hid_t id)
1501 {
1502     int ret_value;                      /* Return value */
1503 
1504     FUNC_ENTER_NOAPI(FAIL)
1505 
1506     /* Sanity check */
1507     HDassert(id >= 0);
1508 
1509     /* Call application decrement reference count routine */
1510     ret_value = H5I_dec_app_ref(id);
1511 
1512     /* Check for failure */
1513     if(ret_value < 0) {
1514         /*
1515          * If an object is closing, we can remove the ID even though the free
1516          * method might fail.  This can happen when a mandatory filter fails to
1517          * write when a dataset is closed and the chunk cache is flushed to the
1518          * file.  We have to close the dataset anyway. (SLU - 2010/9/7)
1519          */
1520         H5I_remove(id);
1521 
1522         HGOTO_ERROR(H5E_ATOM, H5E_CANTDEC, FAIL, "can't decrement ID ref count")
1523     } /* end if */
1524 
1525 done:
1526     FUNC_LEAVE_NOAPI(ret_value)
1527 } /* end H5I_dec_app_ref_always_close() */
1528 
1529 
1530 /*-------------------------------------------------------------------------
1531  * Function:	H5Iinc_ref
1532  *
1533  * Purpose:	Increments the number of references outstanding for an ID.
1534  *
1535  * Return:	Success:	New reference count
1536  *		Failure:	Negative
1537  *
1538  * Programmer:  Quincey Koziol
1539  *              Dec  7, 2003
1540  *
1541  *-------------------------------------------------------------------------
1542  */
1543 int
H5Iinc_ref(hid_t id)1544 H5Iinc_ref(hid_t id)
1545 {
1546     int ret_value;                      /* Return value */
1547 
1548     FUNC_ENTER_API(FAIL)
1549     H5TRACE1("Is", "i", id);
1550 
1551     /* Check arguments */
1552     if(id < 0)
1553 	HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "invalid ID")
1554 
1555     /* Do actual increment operation */
1556     if((ret_value = H5I_inc_ref(id, TRUE)) < 0)
1557         HGOTO_ERROR(H5E_ATOM, H5E_CANTINC, FAIL, "can't increment ID ref count")
1558 
1559 done:
1560     FUNC_LEAVE_API(ret_value)
1561 } /* end H5Iinc_ref() */
1562 
1563 
1564 /*-------------------------------------------------------------------------
1565  * Function:	H5I_inc_ref
1566  *
1567  * Purpose:	Increment the reference count for an object.
1568  *
1569  * Return:	Success:	The new reference count.
1570  *		Failure:	Negative
1571  *
1572  * Programmer:	Robb Matzke
1573  *              Thursday, July 29, 1999
1574  *
1575  *-------------------------------------------------------------------------
1576  */
1577 int
H5I_inc_ref(hid_t id,hbool_t app_ref)1578 H5I_inc_ref(hid_t id, hbool_t app_ref)
1579 {
1580     H5I_type_t		type;		/*type the object is in*/
1581     H5I_id_type_t	*type_ptr;	/*ptr to the type	*/
1582     H5I_id_info_t	*id_ptr;	/*ptr to the ID		*/
1583     int ret_value;                      /* Return value */
1584 
1585     FUNC_ENTER_NOAPI(FAIL)
1586 
1587     /* Sanity check */
1588     HDassert(id >= 0);
1589 
1590     /* Check arguments */
1591     type = H5I_TYPE(id);
1592     if(type <= H5I_BADID || type >= H5I_next_type)
1593 	HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
1594     type_ptr = H5I_id_type_list_g[type];
1595     if(!type_ptr || type_ptr->init_count <= 0)
1596 	HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type")
1597 
1598     /* General lookup of the ID */
1599     if(NULL == (id_ptr = (H5I_id_info_t *)H5SL_search(type_ptr->ids, &id)))
1600 	HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't locate ID")
1601 
1602     /* Adjust reference counts */
1603     ++(id_ptr->count);
1604     if (app_ref)
1605         ++(id_ptr->app_count);
1606 
1607     /* Set return value */
1608     ret_value = (int)(app_ref ? id_ptr->app_count : id_ptr->count);
1609 
1610 done:
1611     FUNC_LEAVE_NOAPI(ret_value)
1612 } /* end H5I_inc_ref() */
1613 
1614 
1615 /*-------------------------------------------------------------------------
1616  * Function:	H5Iget_ref
1617  *
1618  * Purpose:	Retrieves the number of references outstanding for an ID.
1619  *
1620  * Return:	Success:	Reference count
1621  *		Failure:	Negative
1622  *
1623  * Programmer:  Quincey Koziol
1624  *              Dec  7, 2003
1625  *
1626  *-------------------------------------------------------------------------
1627  */
1628 int
H5Iget_ref(hid_t id)1629 H5Iget_ref(hid_t id)
1630 {
1631     int ret_value;                      /* Return value */
1632 
1633     FUNC_ENTER_API(FAIL)
1634     H5TRACE1("Is", "i", id);
1635 
1636     /* Check arguments */
1637     if(id < 0)
1638 	HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "invalid ID")
1639 
1640     /* Do actual retrieve operation */
1641     if((ret_value = H5I_get_ref(id, TRUE)) < 0)
1642         HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't get ID ref count")
1643 
1644 done:
1645     FUNC_LEAVE_API(ret_value)
1646 } /* end H5Iget_ref() */
1647 
1648 
1649 /*-------------------------------------------------------------------------
1650  * Function:	H5I_get_ref
1651  *
1652  * Purpose:	Retrieve the reference count for an object.
1653  *
1654  * Return:	Success:	The reference count.
1655  *		Failure:	Negative
1656  *
1657  * Programmer:	Quincey Koziol
1658  *              Saturday, Decemeber  6, 2003
1659  *
1660  *-------------------------------------------------------------------------
1661  */
1662 int
H5I_get_ref(hid_t id,hbool_t app_ref)1663 H5I_get_ref(hid_t id, hbool_t app_ref)
1664 {
1665     H5I_type_t		type;		/*type the object is in*/
1666     H5I_id_type_t	*type_ptr;	/*ptr to the type	*/
1667     H5I_id_info_t	*id_ptr;	/*ptr to the ID		*/
1668     int ret_value;                      /* Return value */
1669 
1670     FUNC_ENTER_NOAPI(FAIL)
1671 
1672     /* Sanity check */
1673     HDassert(id >= 0);
1674 
1675     /* Check arguments */
1676     type = H5I_TYPE(id);
1677     if(type <= H5I_BADID || type >= H5I_next_type)
1678 	HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
1679     type_ptr = H5I_id_type_list_g[type];
1680     if(!type_ptr || type_ptr->init_count <= 0)
1681 	HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type")
1682 
1683     /* General lookup of the ID */
1684     if(NULL == (id_ptr = (H5I_id_info_t *)H5SL_search(type_ptr->ids, &id)))
1685 	HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't locate ID")
1686 
1687     /* Set return value */
1688     ret_value = (int)(app_ref ? id_ptr->app_count : id_ptr->count);
1689 
1690 done:
1691     FUNC_LEAVE_NOAPI(ret_value)
1692 } /* end H5I_get_ref() */
1693 
1694 
1695 /*-------------------------------------------------------------------------
1696  * Function:	H5Iinc_type_ref
1697  *
1698  * Purpose:	Increments the number of references outstanding for an ID type.
1699  *
1700  * Return:	Success:	New reference count
1701  *		Failure:	Negative
1702  *
1703  * Programmer:  Nat Furrer
1704  *		James Laird
1705  *              April 30, 2004
1706  *
1707  *-------------------------------------------------------------------------
1708  */
1709 int
H5Iinc_type_ref(H5I_type_t type)1710 H5Iinc_type_ref(H5I_type_t type)
1711 {
1712     int ret_value;                      /* Return value */
1713 
1714     FUNC_ENTER_API(FAIL)
1715     H5TRACE1("Is", "It", type);
1716 
1717     /* Check arguments */
1718     if(type <= 0 || type >= H5I_next_type)
1719         HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "invalid ID type")
1720 
1721     if(H5I_IS_LIB_TYPE(type))
1722         HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type")
1723 
1724     /* Do actual increment operation */
1725     if((ret_value = H5I__inc_type_ref(type)) < 0)
1726         HGOTO_ERROR(H5E_ATOM, H5E_CANTINC, FAIL, "can't increment ID type ref count")
1727 
1728 done:
1729     FUNC_LEAVE_API(ret_value)
1730 } /* end H5Iinc_ref() */
1731 
1732 
1733 /*-------------------------------------------------------------------------
1734  * Function:	H5I__inc_type_ref
1735  *
1736  * Purpose:	Increment the reference count for an ID type.
1737  *
1738  * Return:	Success:	The new reference count.
1739  *		Failure:	Negative
1740  *
1741  * Programmer:	James Laird
1742  *		Nat Furrer
1743  *              Friday, April 30, 2004
1744  *
1745  *-------------------------------------------------------------------------
1746  */
1747 static int
H5I__inc_type_ref(H5I_type_t type)1748 H5I__inc_type_ref(H5I_type_t type)
1749 {
1750     H5I_id_type_t	*type_ptr;	/* ptr to the type	*/
1751     int ret_value;                      /* Return value */
1752 
1753     FUNC_ENTER_STATIC
1754 
1755     /* Sanity check */
1756     HDassert(type > 0 && type < H5I_next_type);
1757 
1758     /* Check arguments */
1759     type_ptr = H5I_id_type_list_g[type];
1760     if(!type_ptr)
1761 	HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type")
1762 
1763     /* Set return value */
1764     ret_value = (int)(++(type_ptr->init_count));
1765 
1766 done:
1767     FUNC_LEAVE_NOAPI(ret_value)
1768 } /* end H5I__inc_type_ref() */
1769 
1770 
1771 /*-------------------------------------------------------------------------
1772  * Function:	H5Idec_type_ref
1773  *
1774  * Purpose:	Decrements the reference count on an entire type of IDs.
1775  *		If the type reference count becomes zero then the type is
1776  *		destroyed along with all atoms in that type regardless of
1777  *		their reference counts.	 Destroying IDs involves calling
1778  *		the free-func for each ID's object and then adding the ID
1779  *		struct to the ID free list.  Public interface to
1780  *		H5I_dec_type_ref.
1781  *		Returns the number of references to the type on success; a
1782  *		return value of 0 means that the type will have to be
1783  *		re-initialized before it can be used again (and should probably
1784  *		be set to H5I_UNINIT).
1785  *
1786  * Return:	Number of references to type on success/Negative on failure
1787  *
1788  * Programmer:	Nathaniel Furrer
1789  *		James Laird
1790  *
1791  *-------------------------------------------------------------------------
1792  */
1793 herr_t
H5Idec_type_ref(H5I_type_t type)1794 H5Idec_type_ref(H5I_type_t type)
1795 {
1796     herr_t ret_value;           /* Return value */
1797 
1798     FUNC_ENTER_API(FAIL)
1799     H5TRACE1("e", "It", type);
1800 
1801     if(H5I_IS_LIB_TYPE(type))
1802         HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type")
1803 
1804     ret_value = H5I_dec_type_ref(type);
1805 
1806 done:
1807     FUNC_LEAVE_API(ret_value)
1808 } /* end H5Idec_type_ref() */
1809 
1810 
1811 /*-------------------------------------------------------------------------
1812  * Function:	H5I_dec_type_ref
1813  *
1814  * Purpose:	Decrements the reference count on an entire type of IDs.
1815  *		If the type reference count becomes zero then the type is
1816  *		destroyed along with all atoms in that type regardless of
1817  *		their reference counts.	 Destroying IDs involves calling
1818  *		the free-func for each ID's object and then adding the ID
1819  *		struct to the ID free list.
1820  *		Returns the number of references to the type on success; a
1821  *		return value of 0 means that the type will have to be
1822  *		re-initialized before it can be used again (and should probably
1823  *		be set to H5I_UNINIT).
1824  *
1825  * Return:	Number of references to type on success/Negative on failure
1826  *
1827  * Programmer:	Unknown
1828  *
1829  *-------------------------------------------------------------------------
1830  */
1831 herr_t
H5I_dec_type_ref(H5I_type_t type)1832 H5I_dec_type_ref(H5I_type_t type)
1833 {
1834     H5I_id_type_t	*type_ptr;      /* Pointer to the ID type */
1835     herr_t		ret_value;      /* Return value */
1836 
1837     FUNC_ENTER_NOAPI(FAIL)
1838 
1839     if(type <= H5I_BADID || type >= H5I_next_type)
1840 	HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
1841 
1842     type_ptr = H5I_id_type_list_g[type];
1843     if(type_ptr == NULL || type_ptr->init_count <= 0)
1844 	HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type")
1845 
1846     /*
1847      * Decrement the number of users of the atomic type.  If this is the
1848      * last user of the type then release all atoms from the type and
1849      * free all memory it used.  The free function is invoked for each atom
1850      * being freed.
1851      */
1852     if(1 == type_ptr->init_count) {
1853         H5I__destroy_type(type);
1854         ret_value = 0;
1855     } /* end if */
1856     else {
1857         --(type_ptr->init_count);
1858         ret_value = (herr_t)type_ptr->init_count;
1859     } /* end else */
1860 
1861 done:
1862     FUNC_LEAVE_NOAPI(ret_value)
1863 } /* end H5I_dec_type_ref() */
1864 
1865 
1866 /*-------------------------------------------------------------------------
1867  * Function:	H5Iget_type_ref
1868  *
1869  * Purpose:	Retrieves the number of references outstanding for a type.
1870  *
1871  * Return:	Success:	Reference count
1872  *		Failure:	Negative
1873  *
1874  * Programmer:  Nat Furrer
1875  *		James Laird
1876  *              April 30, 2004
1877  *
1878  *-------------------------------------------------------------------------
1879  */
1880 int
H5Iget_type_ref(H5I_type_t type)1881 H5Iget_type_ref(H5I_type_t type)
1882 {
1883     int ret_value;                      /* Return value */
1884 
1885     FUNC_ENTER_API(FAIL)
1886     H5TRACE1("Is", "It", type);
1887 
1888     /* Check arguments */
1889     if(type <= 0 || type >= H5I_next_type)
1890         HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "invalid ID type")
1891 
1892     if(H5I_IS_LIB_TYPE(type))
1893         HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type")
1894 
1895     /* Do actual retrieve operation */
1896     if((ret_value = H5I__get_type_ref(type)) < 0)
1897         HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't get ID type ref count")
1898 
1899 done:
1900     FUNC_LEAVE_API(ret_value)
1901 } /* end H5Iget_ref() */
1902 
1903 
1904 /*-------------------------------------------------------------------------
1905  * Function:	H5I__get_type_ref
1906  *
1907  * Purpose:	Retrieve the reference count for an ID type.
1908  *
1909  * Return:	Success:	The reference count.
1910  *
1911  *		Failure:	Negative
1912  *
1913  * Programmer:  Nat Furrer
1914  *		James Laird
1915  *              April 30, 2004
1916  *
1917  *-------------------------------------------------------------------------
1918  */
1919 static int
H5I__get_type_ref(H5I_type_t type)1920 H5I__get_type_ref(H5I_type_t type)
1921 {
1922     H5I_id_type_t	*type_ptr;	/*ptr to the type	*/
1923     int ret_value;                      /* Return value */
1924 
1925     FUNC_ENTER_STATIC
1926 
1927     /* Sanity check */
1928     HDassert(type >= 0);
1929 
1930     /* Check arguments */
1931     type_ptr = H5I_id_type_list_g[type];
1932     if(!type_ptr)
1933         HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type")
1934 
1935     /* Set return value */
1936     ret_value = (int)type_ptr->init_count;
1937 
1938 done:
1939     FUNC_LEAVE_NOAPI(ret_value)
1940 } /* end H5I__get_type_ref() */
1941 
1942 
1943 /*-------------------------------------------------------------------------
1944  * Function:	H5Iis_valid
1945  *
1946  * Purpose:	Check if the given id is valid.  An id is valid if it is in
1947  *              use and has an application reference count of at least 1.
1948  *
1949  * Return:	Success:        TRUE if the id is valid, FALSE otherwise.
1950  *
1951  *              Failure:	Negative (never fails currently)
1952  *
1953  * Programmer:  Neil Fortner
1954  *              Friday, October 31, 2008 (boo)
1955  *
1956  *-------------------------------------------------------------------------
1957  */
1958 htri_t
H5Iis_valid(hid_t id)1959 H5Iis_valid(hid_t id)
1960 {
1961     H5I_id_info_t   *id_ptr;            /* ptr to the ID */
1962     htri_t          ret_value = TRUE;   /* Return value */
1963 
1964     FUNC_ENTER_API(FAIL)
1965     H5TRACE1("t", "i", id);
1966 
1967     /* Find the ID */
1968     if (NULL == (id_ptr = H5I__find_id(id)))
1969         ret_value = FALSE;
1970 
1971     /* Check if the found id is an internal id */
1972     else if (!id_ptr->app_count)
1973         ret_value = FALSE;
1974 
1975 done:
1976     FUNC_LEAVE_API(ret_value)
1977 } /* end H5Iis_valid() */
1978 
1979 
1980 /*-------------------------------------------------------------------------
1981  * Function:	H5I__search_cb
1982  *
1983  * Purpose:	Callback routine for H5Isearch, when it calls H5I_iterate.
1984  *		Calls "user" callback search function, and then sets return
1985  *		value, based on the result of that callback.
1986  *
1987  * Return:	Success:	The first object in the type for which FUNC
1988  *				returns non-zero. NULL if FUNC returned zero
1989  *				for every object in the type.
1990  *		Failure:	NULL
1991  *
1992  * Programmer:	Quincey Koziol
1993  *		Friday, March 30, 2012
1994  *
1995  *-------------------------------------------------------------------------
1996  */
1997 static int
H5I__search_cb(void * obj,hid_t id,void * _udata)1998 H5I__search_cb(void *obj, hid_t id, void *_udata)
1999 {
2000     H5I_search_ud_t *udata = (H5I_search_ud_t *)_udata; /* User data for callback */
2001     int ret_value;     /* Callback return value */
2002 
2003     FUNC_ENTER_STATIC_NOERR
2004 
2005     ret_value = (*udata->app_cb)(obj, id, udata->app_key);
2006     if(ret_value > 0)
2007         udata->ret_obj = obj;
2008 
2009     FUNC_LEAVE_NOAPI(ret_value)
2010 } /* end H5I__search_cb() */
2011 
2012 
2013 /*-------------------------------------------------------------------------
2014  * Function:	H5Isearch
2015  *
2016  * Purpose:	Apply function FUNC to each member of type TYPE and return a
2017  *		pointer to the first object for which FUNC returns non-zero.
2018  *		The FUNC should take a pointer to the object and the KEY as
2019  *		arguments and return non-zero to terminate the search (zero
2020  *		to continue).  Public interface to H5I_search.
2021  *
2022  * Limitation:	Currently there is no way to start searching from where a
2023  *		previous search left off.
2024  *
2025  * Return:	Success:	The first object in the type for which FUNC
2026  *				returns non-zero. NULL if FUNC returned zero
2027  *				for every object in the type.
2028  *
2029  *		Failure:	NULL
2030  *
2031  * Programmer:	James Laird
2032  *		Nathaniel Furrer
2033  *		Friday, April 23, 2004
2034  *
2035  *-------------------------------------------------------------------------
2036  */
2037 void *
H5Isearch(H5I_type_t type,H5I_search_func_t func,void * key)2038 H5Isearch(H5I_type_t type, H5I_search_func_t func, void *key)
2039 {
2040     H5I_search_ud_t udata;      /* Context for iteration */
2041     void *ret_value;            /* Return value */
2042 
2043     FUNC_ENTER_API(NULL)
2044 
2045     /* Check arguments */
2046     if(H5I_IS_LIB_TYPE(type))
2047         HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "cannot call public function on library type")
2048 
2049     /* Set up udata struct */
2050     udata.app_cb = func;
2051     udata.app_key = key;
2052     udata.ret_obj = NULL;
2053 
2054     /* Note that H5I_iterate returns an error code.  We ignore it
2055      * here, as we can't do anything with it without revising the API.
2056      */
2057     (void)H5I_iterate(type, H5I__search_cb, &udata, TRUE);
2058 
2059     /* Set return value */
2060     ret_value = udata.ret_obj;
2061 
2062 done:
2063     FUNC_LEAVE_API(ret_value)
2064 } /* end H5Isearch() */
2065 
2066 
2067 /*-------------------------------------------------------------------------
2068  * Function:	H5I__iterate_cb
2069  *
2070  * Purpose:	Callback routine for H5I_iterate, invokes "user" callback
2071  *              function, and then sets return value, based on the result of
2072  *              that callback.
2073  *
2074  * Return:	Success:	Non-negative on success
2075  *		Failure:	Negative
2076  *
2077  * Programmer:	Quincey Koziol
2078  *		Thursday, October 3, 2013
2079  *
2080  *-------------------------------------------------------------------------
2081  */
2082 static int
H5I__iterate_cb(void * _item,void UNUSED * _key,void * _udata)2083 H5I__iterate_cb(void *_item, void UNUSED *_key, void *_udata)
2084 {
2085     H5I_id_info_t *item = (H5I_id_info_t *)_item;       /* Pointer to the ID node */
2086     H5I_iterate_ud_t *udata = (H5I_iterate_ud_t *)_udata; /* User data for callback */
2087     int ret_value = H5_ITER_CONT;     /* Callback return value */
2088 
2089     FUNC_ENTER_STATIC_NOERR
2090 
2091     /* Don't make callback if app_ref is set and the appl. ref count is 0 */
2092     if((!udata->app_ref) || (item->app_count > 0)) {
2093         herr_t cb_ret_val;
2094 
2095         /* (Casting away const OK) */
2096         cb_ret_val = (*udata->user_func)((void *)item->obj_ptr, item->id, udata->user_udata);
2097         if(cb_ret_val > 0)
2098             ret_value = H5_ITER_STOP;	/* terminate iteration early */
2099         else if(cb_ret_val < 0)
2100             ret_value = H5_ITER_ERROR;  /* indicate failure (which terminates iteration) */
2101     } /* end if */
2102 
2103     FUNC_LEAVE_NOAPI(ret_value)
2104 } /* end H5I__iterate_cb() */
2105 
2106 
2107 /*-------------------------------------------------------------------------
2108  * Function:	H5I_iterate
2109  *
2110  * Purpose:	Apply function FUNC to each member of type TYPE (with
2111  *		non-zero application reference count if app_ref is TRUE).
2112  *		Stop if FUNC returns a non zero value (i.e. anything
2113  *		other than H5_ITER_CONT).
2114  *
2115  *		If FUNC returns a positive value (i.e. H5_ITER_STOP),
2116  *		return SUCCEED.
2117  *
2118  *		If FUNC returns a negative value (i.e. H5_ITER_ERROR),
2119  *		return FAIL.
2120  *
2121  *		The FUNC should take a pointer to the object and the
2122  *		udata as arguments and return non-zero to terminate
2123  *		siteration, and zero to continue.
2124  *
2125  * Limitation:	Currently there is no way to start the iteration from
2126  *		where a previous iteration left off.
2127  *
2128  * Return:	Success:	SUCCEED
2129  *		Failure:	FAIL
2130  *
2131  * Programmer:	John Mainzer
2132  *		Monday, December 6, 2011
2133  *
2134  *-------------------------------------------------------------------------
2135  */
2136 herr_t
H5I_iterate(H5I_type_t type,H5I_search_func_t func,void * udata,hbool_t app_ref)2137 H5I_iterate(H5I_type_t type, H5I_search_func_t func, void *udata, hbool_t app_ref)
2138 {
2139     H5I_id_type_t *type_ptr;		/*ptr to the type	*/
2140     herr_t	   ret_value = SUCCEED;	/*return value		*/
2141 
2142     FUNC_ENTER_NOAPI(FAIL)
2143 
2144     /* Check arguments */
2145     if(type <= H5I_BADID || type >= H5I_next_type)
2146 	HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
2147     type_ptr = H5I_id_type_list_g[type];
2148 
2149     /* Only iterate through ID list if it is initialized and there are IDs in type */
2150     if(type_ptr && type_ptr->init_count > 0 && type_ptr->id_count > 0) {
2151         H5I_iterate_ud_t iter_udata;    /* User data for iteration callback */
2152         herr_t iter_status;             /* Iteration status */
2153 
2154         /* Set up iterator user data */
2155         iter_udata.user_func = func;
2156         iter_udata.user_udata = udata;
2157         iter_udata.app_ref = app_ref;
2158 
2159         /* Iterate over IDs */
2160         if((iter_status = H5SL_iterate(type_ptr->ids, H5I__iterate_cb, &iter_udata)) < 0)
2161             HGOTO_ERROR(H5E_ATOM, H5E_BADITER, FAIL, "iteration failed")
2162     } /* end if */
2163 
2164 done:
2165     FUNC_LEAVE_NOAPI(ret_value)
2166 } /* end H5I_iterate() */
2167 
2168 
2169 /*-------------------------------------------------------------------------
2170  * Function:	H5I__find_id
2171  *
2172  * Purpose:	Given an object ID find the info struct that describes the
2173  *		object.
2174  *
2175  * Return:	Success:	Ptr to the object's info struct.
2176  *
2177  *		Failure:	NULL
2178  *
2179  * Programmer:	Unknown
2180  *
2181  *-------------------------------------------------------------------------
2182  */
2183 static H5I_id_info_t *
H5I__find_id(hid_t id)2184 H5I__find_id(hid_t id)
2185 {
2186     H5I_id_type_t	*type_ptr;		/*ptr to the type	*/
2187     H5I_type_t		type;			/*ID's type		*/
2188     H5I_id_info_t	*ret_value;		/*return value		*/
2189 
2190     FUNC_ENTER_STATIC_NOERR
2191 
2192     /* Check arguments */
2193     type = H5I_TYPE(id);
2194     if (type <= H5I_BADID || type >= H5I_next_type)
2195         HGOTO_DONE(NULL);
2196 
2197     type_ptr = H5I_id_type_list_g[type];
2198     if (!type_ptr || type_ptr->init_count <= 0)
2199         HGOTO_DONE(NULL);
2200 
2201     /* Locate the ID node for the ID */
2202     ret_value = (H5I_id_info_t *)H5SL_search(type_ptr->ids, &id);
2203 
2204 done:
2205     FUNC_LEAVE_NOAPI(ret_value)
2206 } /* end H5I__find_id() */
2207 
2208 
2209 /*-------------------------------------------------------------------------
2210  * Function: H5Iget_name
2211  *
2212  * Purpose: Gets a name of an object from its ID.
2213  *
2214  * Return: Success: The length of name.
2215  *
2216  *         Failure: -1
2217  *
2218  * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
2219  *
2220  * Date: July 26, 2002
2221  *
2222  * Comments: Public function
2223  *  If `name' is non-NULL then write up to `size' bytes into that
2224  *  buffer and always return the length of the entry name.
2225  *  Otherwise `size' is ignored and the function does not store the name,
2226  *  just returning the number of characters required to store the name.
2227  *  If an error occurs then the buffer pointed to by `name' (NULL or non-NULL)
2228  *  is unchanged and the function returns a negative value.
2229  *  If a zero is returned for the name's length, then there is no name
2230  *  associated with the ID.
2231  *
2232  *-------------------------------------------------------------------------
2233  */
2234 ssize_t
H5Iget_name(hid_t id,char * name,size_t size)2235 H5Iget_name(hid_t id, char *name/*out*/, size_t size)
2236 {
2237     H5G_loc_t     loc;          /* Object location */
2238     ssize_t       ret_value;    /* Return value */
2239 
2240     FUNC_ENTER_API(FAIL)
2241     H5TRACE3("Zs", "ixz", id, name, size);
2242 
2243     /* Get object location */
2244     if(H5G_loc(id, &loc) < 0)
2245 	HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't retrieve object location")
2246 
2247     /* Call internal group routine to retrieve object's name */
2248     if((ret_value = H5G_get_name(&loc, name, size, NULL, H5P_DEFAULT, H5AC_ind_dxpl_id)) < 0)
2249 	HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't retrieve object name")
2250 
2251 done:
2252     FUNC_LEAVE_API(ret_value)
2253 } /* end H5Iget_name() */
2254 
2255 
2256 /*-------------------------------------------------------------------------
2257  * Function:	H5Iget_file_id
2258  *
2259  * Purpose:	The public version of H5I_get_file_id(), obtains the file
2260  *              ID given an object ID.  User has to close this ID.
2261  *
2262  * Return:	Success:	file ID
2263  *
2264  *		Failure:	a negative value
2265  *
2266  * Programmer:  Raymond Lu
2267  *              Oct 27, 2003
2268  *
2269  *-------------------------------------------------------------------------
2270  */
2271 hid_t
H5Iget_file_id(hid_t obj_id)2272 H5Iget_file_id(hid_t obj_id)
2273 {
2274     hid_t ret_value;            /* Return value */
2275 
2276     FUNC_ENTER_API(FAIL)
2277     H5TRACE1("i", "i", obj_id);
2278 
2279     if((ret_value = H5I_get_file_id(obj_id, TRUE)) < 0)
2280         HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't retrieve file ID")
2281 
2282 done:
2283     FUNC_LEAVE_API(ret_value)
2284 } /* end H5Iget_file_id() */
2285 
2286 
2287 /*-------------------------------------------------------------------------
2288  * Function:	H5I_get_file_id
2289  *
2290  * Purpose:	The private version of H5Iget_file_id(), obtains the file
2291  *              ID given an object ID.
2292  *
2293  * Return:	Success:	file ID
2294  *		Failure:	a negative value
2295  *
2296  * Programmer:  Raymond Lu
2297  *              Oct 27, 2003
2298  *
2299  *-------------------------------------------------------------------------
2300  */
2301 hid_t
H5I_get_file_id(hid_t obj_id,hbool_t app_ref)2302 H5I_get_file_id(hid_t obj_id, hbool_t app_ref)
2303 {
2304     H5I_type_t type;            /* ID type */
2305     hid_t ret_value;            /* Return value */
2306 
2307     FUNC_ENTER_NOAPI_NOINIT
2308 
2309     /* Get object type */
2310     type = H5I_TYPE(obj_id);
2311     if(type == H5I_FILE) {
2312         /* Increment reference count on file ID */
2313         if(H5I_inc_ref(obj_id, app_ref) < 0)
2314             HGOTO_ERROR(H5E_ATOM, H5E_CANTSET, FAIL, "incrementing file ID failed")
2315 
2316         /* Set return value */
2317         ret_value = obj_id;
2318     } /* end if */
2319     else if(type == H5I_DATATYPE || type == H5I_GROUP || type == H5I_DATASET || type == H5I_ATTR) {
2320         H5G_loc_t loc;              /* Location of object */
2321 
2322         /* Get the object location information */
2323         if(H5G_loc(obj_id, &loc) < 0)
2324             HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't get object location")
2325 
2326         /* Get the file ID for the object */
2327         if((ret_value = H5F_get_id(loc.oloc->file, app_ref)) < 0)
2328             HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't get file ID")
2329     } /* end if */
2330     else
2331         HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid object ID")
2332 
2333 done:
2334     FUNC_LEAVE_NOAPI(ret_value)
2335 } /* end H5I_get_file_id() */
2336 
2337 #ifdef H5I_DEBUG_OUTPUT
2338 
2339 /*-------------------------------------------------------------------------
2340  * Function:	H5I__debug_cb
2341  *
2342  * Purpose:	Dump the contents of an ID to stderr for debugging.
2343  *
2344  * Return:	Success: Non-negative
2345  *		Failure: Negative
2346  *
2347  * Programmer:	Robb Matzke
2348  *		Friday, February 19, 1999
2349  *
2350  *-------------------------------------------------------------------------
2351  */
2352 static herr_t
H5I__debug_cb(void * _item,void UNUSED * _key,void * _udata)2353 H5I__debug_cb(void *_item, void UNUSED *_key, void *_udata)
2354 {
2355     H5I_id_info_t *item = (H5I_id_info_t *)_item;       /* Pointer to the ID node */
2356     H5I_type_t type = *(H5I_type_t *)_udata;            /* User data */
2357     H5G_name_t *path = NULL;
2358     int ret_value = H5_ITER_CONT;                       /* Return value */
2359 
2360     FUNC_ENTER_STATIC_NOERR
2361 
2362     fprintf(stderr, "		 id = %lu\n", (unsigned long)(item->id));
2363     fprintf(stderr, "		 count = %u\n", item->count);
2364     fprintf(stderr, "		 obj   = 0x%08lx\n", (unsigned long)(item->obj_ptr));
2365 
2366     /* Get the group location, so we get get the name */
2367     switch(type) {
2368         case H5I_GROUP:
2369             path = H5G_nameof((H5G_t*)item->obj_ptr);
2370             break;
2371 
2372         case H5I_DATASET:
2373             path = H5D_nameof((H5D_t*)item->obj_ptr);
2374             break;
2375 
2376         case H5I_DATATYPE:
2377             path = H5T_nameof((H5T_t*)item->obj_ptr);
2378             break;
2379 
2380         default:
2381             break;   /* Other types of IDs are not stored in files */
2382     } /* end switch*/
2383 
2384     if(path) {
2385         if(path->user_path_r)
2386             fprintf(stderr, "                user_path = %s\n", H5RS_get_str(path->user_path_r));
2387         if(path->full_path_r)
2388             fprintf(stderr, "                full_path = %s\n", H5RS_get_str(path->full_path_r));
2389     } /* end if */
2390 
2391     FUNC_LEAVE_NOAPI(SUCCEED)
2392 } /* end H5I__debug_cb() */
2393 
2394 
2395 /*-------------------------------------------------------------------------
2396  * Function:	H5I__debug
2397  *
2398  * Purpose:	Dump the contents of a type to stderr for debugging.
2399  *
2400  * Return:	Success: Non-negative
2401  *		Failure: Negative
2402  *
2403  * Programmer:	Robb Matzke
2404  *		Friday, February 19, 1999
2405  *
2406  *-------------------------------------------------------------------------
2407  */
2408 static herr_t
H5I__debug(H5I_type_t type)2409 H5I__debug(H5I_type_t type)
2410 {
2411     H5I_id_type_t *type_ptr;
2412 
2413     FUNC_ENTER_STATIC_NOERR
2414 
2415     fprintf(stderr, "Dumping ID type %d\n", (int)type);
2416     type_ptr = H5I_id_type_list_g[type];
2417 
2418     /* Header */
2419     fprintf(stderr, "	 init_count = %u\n", type_ptr->init_count);
2420     fprintf(stderr, "	 reserved   = %u\n", type_ptr->cls->reserved);
2421     fprintf(stderr, "	 wrapped    = %u\n", type_ptr->wrapped);
2422     fprintf(stderr, "	 id_count   = %u\n", type_ptr->id_count);
2423     fprintf(stderr, "	 nextid	    = %u\n", type_ptr->nextid);
2424 
2425     /* List */
2426     fprintf(stderr, "	 List:\n");
2427     H5SL_iterate(type_ptr->ids, H5I__debug_cb, &type);
2428 
2429     FUNC_LEAVE_NOAPI(SUCCEED)
2430 } /* end H5I__debug() */
2431 #endif /* H5I_DEBUG_OUTPUT */
2432 
2433