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