mirror of
https://github.com/HDFGroup/hdf5.git
synced 2025-03-25 17:00:45 +08:00
Code/comment cleanup Description: Made more information about reference-counted strings private to the H5RS package by trimming the typedef used in H5RSprivate.h and switching from using macros for a couple of operations to using functions. Updated copyright information for a few of these files. Platforms tested: Tested h5committest {arabica (fortran), eirene (fortran, C++) modi4 (parallel, fortran)}
1271 lines
39 KiB
C
1271 lines
39 KiB
C
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||
* Copyright by the Board of Trustees of the University of Illinois. *
|
||
* All rights reserved. *
|
||
* *
|
||
* This file is part of HDF5. The full HDF5 copyright notice, including *
|
||
* terms governing use, modification, and redistribution, is contained in *
|
||
* the files COPYING and Copyright.html. COPYING can be found at the root *
|
||
* of the source code distribution tree; Copyright.html can be found at the *
|
||
* root level of an installed copy of the electronic HDF5 document set and *
|
||
* is linked from the top-level documents page. It can also be found at *
|
||
* http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have *
|
||
* access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. *
|
||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||
|
||
/*
|
||
* FILE: H5I.c - Internal storage routines for handling "IDs"
|
||
*
|
||
* REMARKS: ID's which allow objects (void *'s currently) to be bundled
|
||
* into "groups" for more general storage.
|
||
*
|
||
* DESIGN: The groups are stored in an array of pointers to store each
|
||
* group in an element. Each "group" node contains a link to a
|
||
* hash table to manage the IDs in each group. The allowed
|
||
* "groups" are stored in an enum (called group_t) in
|
||
* H5Ipublic.h.
|
||
*
|
||
* AUTHOR: Quincey Koziol
|
||
*
|
||
* MODIFICATIONS:
|
||
* 1/3/96 - Starting writing specs & coding prototype
|
||
* 1/7/96 - Finished coding prototype
|
||
* 6/10/97 - Moved into HDF5 library
|
||
*/
|
||
|
||
#include "H5private.h"
|
||
#include "H5Eprivate.h"
|
||
#include "H5FLprivate.h" /*Free Lists */
|
||
#include "H5Iprivate.h"
|
||
#include "H5MMprivate.h"
|
||
|
||
/* Define this to compile in support for dumping ID information */
|
||
/* #define H5I_DEBUG_OUTPUT */
|
||
#ifndef H5I_DEBUG_OUTPUT
|
||
#include "H5Gprivate.h" /*symbol tables */
|
||
#else /* H5I_DEBUG_OUTPUT */
|
||
#define H5G_PACKAGE /*suppress error message about including H5Gpkg.h */
|
||
#include "H5Gpkg.h"
|
||
#include "H5Dprivate.h" /*datasets */
|
||
#include "H5Tprivate.h" /*data types */
|
||
#endif /* H5I_DEBUG_OUTPUT */
|
||
|
||
/* Interface initialialization? */
|
||
#define PABLO_MASK H5I_mask
|
||
static int interface_initialize_g = 0;
|
||
#define INTERFACE_INIT H5I_init_interface
|
||
static herr_t H5I_init_interface(void);
|
||
|
||
/*-------------------- Locally scoped variables -----------------------------*/
|
||
|
||
#ifdef IDS_ARE_CACHED
|
||
/* ID Cache */
|
||
static H5I_id_info_t *H5I_cache_g[ID_CACHE_SIZE];
|
||
#endif
|
||
|
||
/* Array of pointers to atomic groups */
|
||
static H5I_id_group_t *H5I_id_group_list_g[H5I_NGROUPS];
|
||
|
||
/* Declare a free list to manage the H5I_id_info_t struct */
|
||
H5FL_DEFINE_STATIC(H5I_id_info_t);
|
||
|
||
/*--------------------- Local function prototypes ---------------------------*/
|
||
static H5I_id_info_t *H5I_find_id(hid_t id);
|
||
#ifdef H5I_DEBUG_OUTPUT
|
||
static herr_t H5I_debug(H5I_type_t grp);
|
||
#endif /* H5I_DEBUG_OUTPUT */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5I_init_interface
|
||
*
|
||
* Purpose: Initialize interface-specific information.
|
||
*
|
||
* Return: Success: Non-negative
|
||
*
|
||
* Failure: Negative
|
||
*
|
||
* Programmer:
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5I_init_interface(void)
|
||
{
|
||
FUNC_ENTER_NOINIT(H5I_init_interface);
|
||
|
||
/*
|
||
* Make certain the ID types don't overflow the number of bits allocated
|
||
* for them in an ID.
|
||
*/
|
||
assert(H5I_NGROUPS<=(1<<GROUP_BITS));
|
||
|
||
FUNC_LEAVE_NOAPI(SUCCEED);
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5I_term_interface
|
||
*
|
||
* Purpose: Terminate the H5I interface: release all memory, reset all
|
||
* global variables to initial values. This only happens if all
|
||
* groups have been destroyed from other interfaces.
|
||
*
|
||
* Return: Success: Positive if any action was taken that might
|
||
* affect some other interface; zero otherwise.
|
||
*
|
||
* Failure: Negative.
|
||
*
|
||
* Programmer:
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
int
|
||
H5I_term_interface(void)
|
||
{
|
||
H5I_id_group_t *grp_ptr;
|
||
H5I_type_t grp;
|
||
int n=0;
|
||
|
||
FUNC_ENTER_NOINIT(H5I_term_interface);
|
||
|
||
if (interface_initialize_g) {
|
||
/* How many groups are still being used? */
|
||
for (grp=(H5I_type_t)0; grp<H5I_NGROUPS; H5_INC_ENUM(H5I_type_t,grp)) {
|
||
if ((grp_ptr=H5I_id_group_list_g[grp]) && grp_ptr->id_list)
|
||
n++;
|
||
}
|
||
|
||
/* If no groups are used then clean up */
|
||
if (0==n) {
|
||
for (grp=(H5I_type_t)0; grp<H5I_NGROUPS; H5_INC_ENUM(H5I_type_t,grp)) {
|
||
grp_ptr = H5I_id_group_list_g[grp];
|
||
H5MM_xfree(grp_ptr);
|
||
H5I_id_group_list_g[grp] = NULL;
|
||
}
|
||
}
|
||
|
||
/* Mark interface closed */
|
||
interface_initialize_g = 0;
|
||
}
|
||
FUNC_LEAVE_NOAPI(n);
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5I_init_group
|
||
*
|
||
* Purpose: Initialize an ID group whose ID number is specified by GRP,
|
||
* If the group has already been initialized, this routine just
|
||
* increments the count of number of initializations and returns
|
||
* without trying to change the size of the hash table. A
|
||
* specific number (RESERVED) of group entries may be reserved
|
||
* to enable "constant" values to be handed out which are valid
|
||
* IDs in the group, but which do not map to any data structures
|
||
* and are not allocated dynamicly later. HASH_SIZE is the
|
||
* minimum hash table size to use for the group. FREE_FUNC is
|
||
* called with an object pointer when the object is removed from
|
||
* the group.
|
||
*
|
||
* Return: Success: Non-negative
|
||
*
|
||
* Failure: Negative
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Friday, February 19, 1999
|
||
*
|
||
* Modifications:
|
||
* Bill Wendling, 2000-05-05
|
||
* Instead of the ugly test of whether hash_size is a power of
|
||
* two, I placed it in a macro POWER_OF_TWO which uses the fact
|
||
* that a number that is a power of two has only 1 bit set.
|
||
*
|
||
* Bill Wendling, 2000-05-09
|
||
* Changed POWER_OF_TWO macro to allow 1 as a valid power of two.
|
||
* Changed test below accordingly.
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
int
|
||
H5I_init_group(H5I_type_t grp, size_t hash_size, unsigned reserved,
|
||
H5I_free_t free_func)
|
||
{
|
||
H5I_id_group_t *grp_ptr = NULL; /*ptr to the atomic group*/
|
||
int ret_value = SUCCEED; /*return value */
|
||
|
||
FUNC_ENTER_NOAPI(H5I_init_group, FAIL);
|
||
|
||
/* Check arguments */
|
||
if ((grp <= H5I_BADID || grp >= H5I_NGROUPS) && hash_size > 0)
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid group number");
|
||
#ifdef HASH_SIZE_POWER_2
|
||
if (!POWER_OF_TWO(hash_size) || hash_size == 1)
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid hash size");
|
||
#endif /* HASH_SIZE_POWER_2 */
|
||
|
||
if (H5I_id_group_list_g[grp] == NULL) {
|
||
/* Allocate the group information for new group */
|
||
if (NULL==(grp_ptr = H5MM_calloc(sizeof(H5I_id_group_t))))
|
||
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
|
||
H5I_id_group_list_g[grp] = grp_ptr;
|
||
} else {
|
||
/* Get the pointer to the existing group */
|
||
grp_ptr = H5I_id_group_list_g[grp];
|
||
}
|
||
|
||
if (grp_ptr->count == 0) {
|
||
/* Initialize the ID group structure for new groups */
|
||
grp_ptr->hash_size = hash_size;
|
||
grp_ptr->reserved = reserved;
|
||
grp_ptr->wrapped = 0;
|
||
grp_ptr->ids = 0;
|
||
grp_ptr->nextid = reserved;
|
||
grp_ptr->free_func = free_func;
|
||
grp_ptr->id_list = H5MM_calloc(hash_size*sizeof(H5I_id_info_t *));
|
||
if (NULL==grp_ptr->id_list)
|
||
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
|
||
}
|
||
|
||
/* Increment the count of the times this group has been initialized */
|
||
grp_ptr->count++;
|
||
|
||
done:
|
||
if (ret_value<0) {
|
||
/* Error condition cleanup */
|
||
if (grp_ptr != NULL) {
|
||
H5MM_xfree(grp_ptr->id_list);
|
||
H5MM_xfree(grp_ptr);
|
||
}
|
||
}
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value);
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5I_nmembers
|
||
*
|
||
* Purpose: Returns the number of members in a group.
|
||
*
|
||
* Return: Success: Number of members; zero if the group is empty
|
||
* or has been deleted.
|
||
*
|
||
* Failure: Negative
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Wednesday, March 24, 1999
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
int
|
||
H5I_nmembers(H5I_type_t grp)
|
||
{
|
||
H5I_id_group_t *grp_ptr = NULL;
|
||
H5I_id_info_t *cur=NULL;
|
||
int n=0;
|
||
unsigned i;
|
||
int ret_value;
|
||
|
||
FUNC_ENTER_NOAPI(H5I_nmembers, FAIL);
|
||
|
||
if (grp<=H5I_BADID || grp>=H5I_NGROUPS)
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid group number");
|
||
if (NULL==(grp_ptr=H5I_id_group_list_g[grp]) || grp_ptr->count<=0)
|
||
HGOTO_DONE(0);
|
||
|
||
for (i=0; i<grp_ptr->hash_size; i++)
|
||
for (cur=grp_ptr->id_list[i]; cur; cur=cur->next)
|
||
n++;
|
||
|
||
/* Set return value */
|
||
ret_value=n;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value);
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5I_clear_group
|
||
*
|
||
* Purpose: Removes all objects from the group, calling the free
|
||
* function for each object regardless of the reference count.
|
||
*
|
||
* Return: Success: Non-negative
|
||
*
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Wednesday, March 24, 1999
|
||
*
|
||
* Modifications:
|
||
* Robb Matzke, 1999-04-27
|
||
* If FORCE is zero then any item for which the free callback
|
||
* failed is not removed. This function returns failure if
|
||
* items could not be removed.
|
||
*
|
||
* Robb Matzke, 1999-08-17
|
||
* If the object reference count is larger than one then it must
|
||
* be because the library is using the object internally. This
|
||
* happens for instance for file driver ID's which are stored in
|
||
* things like property lists, files, etc. Objects that have a
|
||
* reference count larger than one are not affected unless FORCE
|
||
* is non-zero.
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5I_clear_group(H5I_type_t grp, hbool_t force)
|
||
{
|
||
H5I_id_group_t *grp_ptr = NULL; /* ptr to the atomic group */
|
||
H5I_id_info_t *cur=NULL; /* Current node being worked with */
|
||
H5I_id_info_t *next=NULL; /* Next node in list */
|
||
H5I_id_info_t *last=NULL; /* Last node seen */
|
||
H5I_id_info_t *tmp=NULL; /* Temporary node ptr */
|
||
int ret_value = SUCCEED;
|
||
unsigned delete_node; /* Flag to indicate node should be removed from linked list */
|
||
unsigned i,j;
|
||
|
||
FUNC_ENTER_NOAPI(H5I_clear_group, FAIL);
|
||
|
||
if (grp <= H5I_BADID || grp >= H5I_NGROUPS)
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid group number");
|
||
|
||
grp_ptr = H5I_id_group_list_g[grp];
|
||
if (grp_ptr == NULL || grp_ptr->count <= 0)
|
||
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid group");
|
||
|
||
#ifdef IDS_ARE_CACHED
|
||
/*
|
||
* Remove atoms from the global atom cache.
|
||
*/
|
||
for (i=0; i<ID_CACHE_SIZE; i++) {
|
||
if (H5I_cache_g[i] && H5I_GROUP(H5I_cache_g[i]->id) == grp)
|
||
H5I_cache_g[i] = NULL;
|
||
}
|
||
#endif /* IDS_ARE_CACHED */
|
||
|
||
/*
|
||
* Call free method for all objects in group regardless of their reference
|
||
* counts. Ignore the return value from from the free method and remove
|
||
* object from group regardless if FORCE is non-zero.
|
||
*/
|
||
for (i=0; i<grp_ptr->hash_size; i++) {
|
||
for (cur=grp_ptr->id_list[i]; cur; cur=next) {
|
||
/*
|
||
* Do nothing to the object if the reference count is larger than
|
||
* one and forcing is off.
|
||
*/
|
||
if (!force && cur->count>1) {
|
||
next=cur->next;
|
||
continue;
|
||
} /* end if */
|
||
|
||
/* Check for a 'free' function and call it, if it exists */
|
||
if (grp_ptr->free_func && (grp_ptr->free_func)(cur->obj_ptr)<0) {
|
||
if (force) {
|
||
#ifdef H5I_DEBUG
|
||
if (H5DEBUG(I)) {
|
||
fprintf(H5DEBUG(I), "H5I: free grp=%d obj=0x%08lx "
|
||
"failure ignored\n", (int)grp,
|
||
(unsigned long)(cur->obj_ptr));
|
||
} /* end if */
|
||
#endif /*H5I_DEBUG*/
|
||
|
||
/* Indicate node should be removed from list */
|
||
delete_node=1;
|
||
} /* end if */
|
||
else {
|
||
/* Indicate node should _NOT_ be remove from list */
|
||
delete_node=0;
|
||
} /* end else */
|
||
} /* end if */
|
||
else {
|
||
/* Indicate node should be removed from list */
|
||
delete_node=1;
|
||
} /* end else */
|
||
|
||
/* Check if we should delete this node or not */
|
||
if(delete_node) {
|
||
/* Decrement the number of IDs in the group */
|
||
(grp_ptr->ids)--;
|
||
|
||
/* Advance to next node */
|
||
next = cur->next;
|
||
|
||
/* Re-scan the list of nodes and remove the node from the list */
|
||
/* (can't maintain static pointers to the previous node in the */
|
||
/* list, because the node's 'free' callback could have */
|
||
/* make an H5I call, which could potentially change the */
|
||
/* order of the nodes on the list - QAK) */
|
||
last=NULL;
|
||
tmp=grp_ptr->id_list[i];
|
||
while(tmp!=cur) {
|
||
assert(tmp!=NULL);
|
||
last=tmp;
|
||
tmp=tmp->next;
|
||
} /* end while */
|
||
|
||
/* Delete the node from the list */
|
||
if(last==NULL) {
|
||
/* Node at head of list, just advance the list head to next node */
|
||
assert(grp_ptr->id_list[i]==cur);
|
||
grp_ptr->id_list[i] = next;
|
||
} /* end if */
|
||
else {
|
||
/* Node in middle of list, jump over it */
|
||
assert(last->next==cur);
|
||
last->next=next;
|
||
} /* end else */
|
||
|
||
#ifdef IDS_ARE_CACHED
|
||
/* Scan through cache & remove node, if present */
|
||
/* (node's 'free' callback function could have made an H5I */
|
||
/* call, which would probably put the node back in */
|
||
/* the cache - QAK) */
|
||
for(j=0; j<ID_CACHE_SIZE; j++)
|
||
if(H5I_cache_g[j]==cur)
|
||
H5I_cache_g[j]=NULL;
|
||
#endif /* IDS_ARE_CACHED */
|
||
|
||
/* Free the node */
|
||
H5FL_FREE(H5I_id_info_t,cur);
|
||
} /* end if */
|
||
else {
|
||
/* Advance to next node */
|
||
next = cur->next;
|
||
} /* end else */
|
||
} /* end for */
|
||
} /* end for */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value);
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5I_destroy_group
|
||
*
|
||
* Purpose: Decrements the reference count on an entire group of IDs.
|
||
* If the group reference count becomes zero then the group is
|
||
* destroyed along with all atoms in that group regardless of
|
||
* their reference counts. Destroying IDs involves calling
|
||
* the free-func for each ID's object and then adding the ID
|
||
* struct to the ID free list.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Unknown
|
||
*
|
||
* Modifications:
|
||
*
|
||
* Robb Matzke, 25 Feb 1998
|
||
* IDs are freed when a group is destroyed.
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5I_destroy_group(H5I_type_t grp)
|
||
{
|
||
H5I_id_group_t *grp_ptr = NULL; /* ptr to the atomic group */
|
||
int ret_value = SUCCEED;
|
||
|
||
FUNC_ENTER_NOAPI(H5I_destroy_group, FAIL);
|
||
|
||
if (grp <= H5I_BADID || grp >= H5I_NGROUPS)
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid group number");
|
||
|
||
grp_ptr = H5I_id_group_list_g[grp];
|
||
if (grp_ptr == NULL || grp_ptr->count <= 0)
|
||
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid group");
|
||
|
||
/*
|
||
* Decrement the number of users of the atomic group. If this is the
|
||
* last user of the group then release all atoms from the group. The
|
||
* free function is invoked for each atom being freed.
|
||
*/
|
||
if (1==grp_ptr->count) {
|
||
H5I_clear_group(grp, TRUE);
|
||
H5E_clear(); /*don't care about errors*/
|
||
H5MM_xfree(grp_ptr->id_list);
|
||
HDmemset (grp_ptr, 0, sizeof(*grp_ptr));
|
||
} else {
|
||
--(grp_ptr->count);
|
||
}
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value);
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5I_register
|
||
*
|
||
* Purpose: Registers an OBJECT in a GROUP and returns an ID for it.
|
||
* This routine does _not_ check for unique-ness of the objects,
|
||
* if you register an object twice, you will get two different
|
||
* IDs for it. This routine does make certain that each ID in a
|
||
* group is unique. IDs are created by getting a unique number
|
||
* for the group the ID is in and incorporating the group into
|
||
* the ID which is returned to the user.
|
||
*
|
||
* Return: Success: New object id.
|
||
*
|
||
* Failure: Negative
|
||
*
|
||
* Programmer: Unknown
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
hid_t
|
||
H5I_register(H5I_type_t grp, void *object)
|
||
{
|
||
H5I_id_group_t *grp_ptr=NULL; /*ptr to the group */
|
||
H5I_id_info_t *id_ptr=NULL; /*ptr to the new ID information */
|
||
hid_t new_id; /*new ID */
|
||
unsigned hash_loc; /*new item's hash table location*/
|
||
hid_t next_id; /*next ID to check */
|
||
hid_t ret_value=SUCCEED; /*return value */
|
||
H5I_id_info_t *curr_id; /*ptr to the current atom */
|
||
unsigned i; /*counter */
|
||
|
||
FUNC_ENTER_NOAPI(H5I_register, FAIL);
|
||
|
||
/* Check arguments */
|
||
if (grp <= H5I_BADID || grp >= H5I_NGROUPS)
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid group number");
|
||
grp_ptr = H5I_id_group_list_g[grp];
|
||
if (grp_ptr == NULL || grp_ptr->count <= 0)
|
||
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid group");
|
||
if ((id_ptr = H5FL_MALLOC(H5I_id_info_t)) == NULL)
|
||
HGOTO_ERROR(H5E_ATOM, H5E_NOSPACE, FAIL, "memory allocation failed");
|
||
|
||
/* Create the struct & it's ID */
|
||
new_id = H5I_MAKE(grp, grp_ptr->nextid);
|
||
id_ptr->id = new_id;
|
||
id_ptr->count = 1; /*initial reference count*/
|
||
id_ptr->obj_ptr = object;
|
||
id_ptr->next = NULL;
|
||
|
||
/* hash bucket already full, prepend to front of chain */
|
||
hash_loc = grp_ptr->nextid % (unsigned) grp_ptr->hash_size;
|
||
if (grp_ptr->id_list[hash_loc] != NULL)
|
||
id_ptr->next = grp_ptr->id_list[hash_loc];
|
||
|
||
/* Insert into the group */
|
||
grp_ptr->id_list[hash_loc] = id_ptr;
|
||
grp_ptr->ids++;
|
||
grp_ptr->nextid++;
|
||
|
||
/*
|
||
* This next section of code checks for the 'nextid' getting too large and
|
||
* wrapping around, thus necessitating checking for duplicate IDs being
|
||
* handed out.
|
||
*/
|
||
if (grp_ptr->nextid > (unsigned)ID_MASK) {
|
||
grp_ptr->wrapped = 1;
|
||
grp_ptr->nextid = grp_ptr->reserved;
|
||
}
|
||
|
||
/*
|
||
* If we've wrapped around then we need to check for duplicate id's being
|
||
* handed out.
|
||
*/
|
||
if (grp_ptr->wrapped) {
|
||
/*
|
||
* Make sure we check all available ID's. If we're about at the end
|
||
* of the range then wrap around and check the beginning values. If
|
||
* we check all possible values and didn't find any free ones *then*
|
||
* we can fail.
|
||
*/
|
||
for (i=grp_ptr->reserved; i<ID_MASK; i++) {
|
||
/* Handle end of range by wrapping to beginning */
|
||
if (grp_ptr->nextid>(unsigned)ID_MASK)
|
||
grp_ptr->nextid = grp_ptr->reserved;
|
||
|
||
/* new ID to check for */
|
||
next_id = H5I_MAKE(grp, grp_ptr->nextid);
|
||
hash_loc = H5I_LOC (grp_ptr->nextid, grp_ptr->hash_size);
|
||
curr_id = grp_ptr->id_list[hash_loc];
|
||
if (curr_id == NULL)
|
||
break; /* Ha! this is not likely... */
|
||
|
||
while (curr_id) {
|
||
if (curr_id->id == next_id)
|
||
break;
|
||
curr_id = curr_id->next;
|
||
}
|
||
if (!curr_id)
|
||
break; /* must not have found a match */
|
||
grp_ptr->nextid++;
|
||
}
|
||
|
||
if (i>=(unsigned)ID_MASK)
|
||
/* All the IDs are gone! */
|
||
HGOTO_ERROR(H5E_ATOM, H5E_NOIDS, FAIL, "no IDs available in group");
|
||
}
|
||
ret_value = new_id;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value);
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5I_object
|
||
*
|
||
* Purpose: Find an object pointer for the specified ID.
|
||
*
|
||
* Return: Success: Non-null object pointer associated with the
|
||
* specified ID.
|
||
*
|
||
* Failure: NULL
|
||
*
|
||
* Programmer:
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
void *
|
||
H5I_object(hid_t id)
|
||
{
|
||
H5I_id_info_t *id_ptr = NULL; /*ptr to the new atom */
|
||
void *ret_value = NULL; /*return value */
|
||
|
||
FUNC_ENTER_NOAPI(H5I_object, NULL);
|
||
|
||
/* General lookup of the ID */
|
||
if (NULL!=(id_ptr = H5I_find_id(id))) {
|
||
/* Get the object pointer to return */
|
||
ret_value = id_ptr->obj_ptr;
|
||
} /* end if */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value);
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5I_object_verify
|
||
*
|
||
* Purpose: Find an object pointer for the specified ID, verifying that
|
||
* its in a particular group.
|
||
*
|
||
* Return: Success: Non-null object pointer associated with the
|
||
* specified ID.
|
||
*
|
||
* Failure: NULL
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Wednesday, July 31, 2002
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
void *
|
||
H5I_object_verify(hid_t id, H5I_type_t id_type)
|
||
{
|
||
H5I_id_info_t *id_ptr = NULL; /*ptr to the new atom */
|
||
void *ret_value = NULL; /*return value */
|
||
|
||
FUNC_ENTER_NOAPI(H5I_object_verify, NULL);
|
||
|
||
assert(id_type>=H5I_FILE && id_type<H5I_NGROUPS);
|
||
|
||
/* Verify that the group of the ID is correct & lookup the ID */
|
||
if(id_type == H5I_GROUP(id) && NULL!=(id_ptr = H5I_find_id(id))) {
|
||
/* Get the object pointer to return */
|
||
ret_value = id_ptr->obj_ptr;
|
||
} /* end if */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value);
|
||
} /* H5I_object_verify() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5I_get_type
|
||
*
|
||
* Purpose: Given an object ID return the group (type) to which it
|
||
* belongs. The ID need not be the ID of an object which
|
||
* currently exists because the group number (type) is encoded
|
||
* in the object ID.
|
||
*
|
||
* Return: Success: A valid group number (type)
|
||
*
|
||
* Failure: H5I_BADID, a negative value.
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Friday, February 19, 1999
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
H5I_type_t
|
||
H5I_get_type(hid_t id)
|
||
{
|
||
H5I_type_t ret_value = H5I_BADID;
|
||
|
||
FUNC_ENTER_NOAPI(H5I_get_type, H5I_BADID);
|
||
|
||
if (id>0)
|
||
ret_value = H5I_GROUP(id);
|
||
|
||
assert(ret_value>=H5I_BADID && ret_value<H5I_NGROUPS);
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value);
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5Iget_type
|
||
*
|
||
* Purpose: The public version of H5I_get_type(), obtains a group number
|
||
* (type) when given an ID. The ID need not be the ID of an
|
||
* object which currently exists because the group number is
|
||
* encoded as part of the ID.
|
||
*
|
||
* Return: Success: Group number (type)
|
||
*
|
||
* Failure: H5I_BADID, a negative value
|
||
*
|
||
* Programmer:
|
||
*
|
||
* Modifications:
|
||
* Robb Matzke, 1999-08-23
|
||
* Also fails if the ID has a valid group but no longer exists
|
||
* in the ID tables.
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
H5I_type_t
|
||
H5Iget_type(hid_t id)
|
||
{
|
||
H5I_type_t ret_value = H5I_BADID;
|
||
|
||
FUNC_ENTER_API(H5Iget_type, H5I_BADID);
|
||
H5TRACE1("It","i",id);
|
||
|
||
ret_value = H5I_get_type(id);
|
||
|
||
if (ret_value <= H5I_BADID || ret_value >= H5I_NGROUPS || NULL==H5I_object(id))
|
||
HGOTO_DONE(H5I_BADID);
|
||
|
||
done:
|
||
FUNC_LEAVE_API(ret_value);
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5I_remove
|
||
*
|
||
* Purpose: Removes the specified ID from its group.
|
||
*
|
||
* Return: Success: A pointer to the object that was removed, the
|
||
* same pointer which would have been found by
|
||
* calling H5I_object().
|
||
*
|
||
* Failure: NULL
|
||
*
|
||
* Programmer:
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
void *
|
||
H5I_remove(hid_t id)
|
||
{
|
||
H5I_id_group_t *grp_ptr = NULL;/*ptr to the atomic group */
|
||
H5I_id_info_t *curr_id; /*ptr to the current atom */
|
||
H5I_id_info_t *last_id; /*ptr to the last atom */
|
||
H5I_type_t grp; /*atom's atomic group */
|
||
unsigned hash_loc; /*atom's hash table location */
|
||
#ifdef IDS_ARE_CACHED
|
||
unsigned i; /*local counting variable */
|
||
#endif
|
||
void * ret_value = NULL; /*return value */
|
||
|
||
FUNC_ENTER_NOAPI(H5I_remove, NULL);
|
||
|
||
/* Check arguments */
|
||
grp = H5I_GROUP(id);
|
||
if (grp <= H5I_BADID || grp >= H5I_NGROUPS)
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "invalid group number");
|
||
grp_ptr = H5I_id_group_list_g[grp];
|
||
if (grp_ptr == NULL || grp_ptr->count <= 0)
|
||
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "invalid group");
|
||
|
||
/* Get the bucket in which the ID is located */
|
||
hash_loc = (unsigned) H5I_LOC(id, grp_ptr->hash_size);
|
||
curr_id = grp_ptr->id_list[hash_loc];
|
||
if (curr_id == NULL)
|
||
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, NULL, "invalid ID");
|
||
|
||
last_id = NULL;
|
||
while (curr_id != NULL) {
|
||
if (curr_id->id == id)
|
||
break;
|
||
last_id = curr_id;
|
||
curr_id = curr_id->next;
|
||
}
|
||
|
||
#ifdef IDS_ARE_CACHED
|
||
/* Delete object from cache */
|
||
for (i = 0; i < ID_CACHE_SIZE; i++)
|
||
if (H5I_cache_g[i] && H5I_cache_g[i]->id == id) {
|
||
H5I_cache_g[i] = NULL;
|
||
break; /* we assume there is only one instance in the cache */
|
||
}
|
||
#endif /* IDS_ARE_CACHED */
|
||
|
||
if (curr_id != NULL) {
|
||
if (last_id == NULL) {
|
||
/* ID is the first in the chain */
|
||
grp_ptr->id_list[hash_loc] = curr_id->next;
|
||
} else {
|
||
last_id->next = curr_id->next;
|
||
}
|
||
ret_value = curr_id->obj_ptr;
|
||
H5FL_FREE(H5I_id_info_t,curr_id);
|
||
} else {
|
||
/* couldn't find the ID in the proper place */
|
||
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, NULL, "invalid ID");
|
||
}
|
||
|
||
/* Decrement the number of IDs in the group */
|
||
(grp_ptr->ids)--;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value);
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5I_dec_ref
|
||
*
|
||
* Purpose: Decrements the number of references outstanding for an ID.
|
||
* This will fail if the group is not a reference counted group.
|
||
* The ID group's 'free' function will be called for the ID
|
||
* if the reference count for the ID reaches 0 and a free
|
||
* function has been defined at group creation time.
|
||
*
|
||
* Return: Success: New reference count.
|
||
*
|
||
* Failure: Negative
|
||
*
|
||
* Programmer: Unknown
|
||
*
|
||
* Modifications:
|
||
*
|
||
* Robb Matzke, 19 Feb 1998
|
||
* It is no longer an error when the reference count of an item reaches
|
||
* zero and no `free' function has been defined. The object is still
|
||
* removed from the list.
|
||
*
|
||
* Robb Matzke, 30 Dec 1998
|
||
* Fixed a bug where the return value was always zero instead of the new
|
||
* reference count.
|
||
*
|
||
* Robb Matzke, 19 Feb 1999
|
||
* If the free method is defined and fails then the object is not
|
||
* removed from the group and its reference count is not decremented.
|
||
* The group number is now passed to the free method.
|
||
*
|
||
* Raymond, 11 Dec 2001
|
||
* If the freeing function fails, return failure instead of reference
|
||
* count 1. This feature is needed by file close with H5F_CLOSE_SEMI
|
||
* value.
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
int
|
||
H5I_dec_ref(hid_t id)
|
||
{
|
||
H5I_type_t grp = H5I_GROUP(id); /*group the object is in*/
|
||
H5I_id_group_t *grp_ptr = NULL; /*ptr to the group */
|
||
H5I_id_info_t *id_ptr = NULL; /*ptr to the new ID */
|
||
int ret_value=FAIL; /*return value */
|
||
|
||
FUNC_ENTER_NOAPI(H5I_dec_ref, FAIL);
|
||
|
||
/* Check arguments */
|
||
grp_ptr = H5I_id_group_list_g[grp];
|
||
if (grp_ptr == NULL || grp_ptr->count <= 0)
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid group number");
|
||
|
||
/* General lookup of the ID */
|
||
if ((id_ptr=H5I_find_id(id))) {
|
||
/*
|
||
* If this is the last reference to the object then invoke the group's
|
||
* free method on the object. If the free method is undefined or
|
||
* successful then remove the object from the group; otherwise leave
|
||
* the object in the group without decrementing the reference
|
||
* count. If the reference count is more than one then decrement the
|
||
* reference count without calling the free method.
|
||
*
|
||
* Beware: the free method may call other H5I functions.
|
||
*/
|
||
if (1==id_ptr->count) {
|
||
if (!grp_ptr->free_func ||
|
||
(grp_ptr->free_func)(id_ptr->obj_ptr)>=0) {
|
||
H5I_remove(id);
|
||
ret_value = 0;
|
||
} else {
|
||
ret_value = FAIL;
|
||
}
|
||
} else {
|
||
ret_value = --(id_ptr->count);
|
||
}
|
||
}
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value);
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5I_inc_ref
|
||
*
|
||
* Purpose: Increment the reference count for an object.
|
||
*
|
||
* Return: Success: The new reference count.
|
||
*
|
||
* Failure: Negative
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Thursday, July 29, 1999
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
int
|
||
H5I_inc_ref(hid_t id)
|
||
{
|
||
H5I_type_t grp = H5I_GROUP(id); /*group the object is in*/
|
||
H5I_id_group_t *grp_ptr = NULL; /*ptr to the group */
|
||
H5I_id_info_t *id_ptr = NULL; /*ptr to the ID */
|
||
int ret_value; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(H5I_inc_ref, FAIL);
|
||
|
||
/* Check arguments */
|
||
if (id<0)
|
||
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "invalid ID");
|
||
grp_ptr = H5I_id_group_list_g[grp];
|
||
if (!grp_ptr || grp_ptr->count<=0)
|
||
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid group");
|
||
|
||
/* General lookup of the ID */
|
||
if (NULL==(id_ptr=H5I_find_id(id)))
|
||
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't locate ID");
|
||
id_ptr->count++;
|
||
|
||
/* Set return value */
|
||
ret_value=id_ptr->count;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value);
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5I_search
|
||
*
|
||
* Purpose: Apply function FUNC to each member of group GRP and return a
|
||
* pointer to the first object for which FUNC returns non-zero.
|
||
* The FUNC should take a pointer to the object and the KEY as
|
||
* arguments and return non-zero to terminate the search (zero
|
||
* to continue).
|
||
*
|
||
* Limitation: Currently there is no way to start searching from where a
|
||
* previous search left off.
|
||
*
|
||
* Return: Success: The first object in the group for which FUNC
|
||
* returns non-zero. NULL if FUNC returned zero
|
||
* for every object in the group.
|
||
*
|
||
* Failure: NULL
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Friday, February 19, 1999
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
void *
|
||
H5I_search(H5I_type_t grp, H5I_search_func_t func, const void *key)
|
||
{
|
||
H5I_id_group_t *grp_ptr = NULL; /*ptr to the group */
|
||
H5I_id_info_t *id_ptr = NULL; /*ptr to the new ID */
|
||
unsigned i; /*counter */
|
||
void *ret_value = NULL; /*return value */
|
||
|
||
FUNC_ENTER_NOAPI(H5I_search, NULL);
|
||
|
||
/* Check arguments */
|
||
if (grp <= H5I_BADID || grp >= H5I_NGROUPS)
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "invalid group number");
|
||
grp_ptr = H5I_id_group_list_g[grp];
|
||
if (grp_ptr == NULL || grp_ptr->count <= 0)
|
||
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "invalid group");
|
||
|
||
/* Start at the beginning of the array */
|
||
for (i=0; i<grp_ptr->hash_size; i++) {
|
||
id_ptr = grp_ptr->id_list[i];
|
||
while (id_ptr) {
|
||
if ((*func)(id_ptr->obj_ptr, id_ptr->id, key))
|
||
HGOTO_DONE(id_ptr->obj_ptr); /*found the item*/
|
||
id_ptr = id_ptr->next;
|
||
}
|
||
}
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value);
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5I_find_id
|
||
*
|
||
* Purpose: Given an object ID find the info struct that describes the
|
||
* object.
|
||
*
|
||
* Return: Success: Ptr to the object's info struct.
|
||
*
|
||
* Failure: NULL
|
||
*
|
||
* Programmer:
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static H5I_id_info_t *
|
||
H5I_find_id(hid_t id)
|
||
{
|
||
H5I_id_group_t *grp_ptr = NULL; /*ptr to the group */
|
||
H5I_id_info_t *id_ptr = NULL; /*ptr to the new ID */
|
||
H5I_type_t grp; /*ID's group */
|
||
unsigned hash_loc; /*bucket pointer */
|
||
H5I_id_info_t *ret_value = NULL; /*return value */
|
||
#ifdef IDS_ARE_CACHED
|
||
int i;
|
||
#endif
|
||
|
||
FUNC_ENTER_NOINIT(H5I_find_id);
|
||
|
||
/* Check arguments */
|
||
grp = H5I_GROUP(id);
|
||
if (grp <= H5I_BADID || grp >= H5I_NGROUPS)
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "invalid group number");
|
||
grp_ptr = H5I_id_group_list_g[grp];
|
||
if (grp_ptr == NULL || grp_ptr->count <= 0)
|
||
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "invalid group");
|
||
|
||
#ifdef IDS_ARE_CACHED
|
||
/*
|
||
* Look for the ID in the cache first. Implement a simple "move
|
||
* forward" caching scheme by swapping the found cache item with the
|
||
* previous cache item. This gradually migrates used cache items toward
|
||
* the front of the cache and unused items toward the end. For instance,
|
||
* finding `e' in the cache results in:
|
||
*
|
||
* Before: a b c d e f g h i j
|
||
* | | | X | | | | |
|
||
* After: a b c e d f g h i j
|
||
*/
|
||
for (i=0; i<ID_CACHE_SIZE; i++)
|
||
if (H5I_cache_g[i] && H5I_cache_g[i]->id == id) {
|
||
ret_value = H5I_cache_g[i];
|
||
if (i > 0) {
|
||
H5I_id_info_t *tmp = H5I_cache_g[i-1];
|
||
H5I_cache_g[i-1] = H5I_cache_g[i];
|
||
H5I_cache_g[i] = tmp;
|
||
}
|
||
HGOTO_DONE(ret_value);
|
||
}
|
||
#endif /* IDS_ARE_CACHED */
|
||
|
||
/* Get the bucket in which the ID is located */
|
||
hash_loc = (unsigned)H5I_LOC(id, grp_ptr->hash_size);
|
||
id_ptr = grp_ptr->id_list[hash_loc];
|
||
if (id_ptr == NULL)
|
||
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, NULL, "invalid ID");
|
||
|
||
/* Scan the bucket's linked list for a match */
|
||
while (id_ptr) {
|
||
if (id_ptr->id == id)
|
||
break;
|
||
id_ptr = id_ptr->next;
|
||
}
|
||
ret_value = id_ptr;
|
||
|
||
#ifdef IDS_ARE_CACHED
|
||
/* Add id to the end of the cache */
|
||
H5I_cache_g[ID_CACHE_SIZE-1] = id_ptr;
|
||
#endif /* IDS_ARE_CACHED */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value);
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5Iget_name
|
||
*
|
||
* Purpose: Gets a name of an object from its ID.
|
||
*
|
||
* Return: Success: 0, Failure: -1
|
||
*
|
||
* Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
|
||
*
|
||
* Date: July 26, 2002
|
||
*
|
||
* Comments: Public function
|
||
* If `name' is non-NULL then write up to `size' bytes into that
|
||
* buffer and always return the length of the entry name.
|
||
* Otherwise `size' is ignored and the function does not store the name,
|
||
* just returning the number of characters required to store the name.
|
||
* If an error occurs then the buffer pointed to by `name' (NULL or non-NULL)
|
||
* is unchanged and the function returns a negative value.
|
||
* If a zero is returned for the name's length, then there is no name
|
||
* associated with the ID.
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
ssize_t
|
||
H5Iget_name(hid_t id, char *name/*out*/, size_t size)
|
||
{
|
||
H5G_entry_t *ent; /*symbol table entry */
|
||
size_t len=0;
|
||
ssize_t ret_value;
|
||
|
||
FUNC_ENTER_API (H5Iget_name, FAIL);
|
||
H5TRACE3("Zs","ixz",id,name,size);
|
||
|
||
/* get symbol table entry */
|
||
if(NULL!=(ent = H5G_loc(id))) {
|
||
if (ent->user_path_r != NULL && ent->user_path_hidden==0) {
|
||
len = H5RS_len(ent->user_path_r);
|
||
|
||
if(name) {
|
||
HDstrncpy(name, H5RS_get_str(ent->user_path_r), MIN(len+1,size));
|
||
if(len >= size)
|
||
name[size-1]='\0';
|
||
} /* end if */
|
||
} /* end if */
|
||
} /* end if */
|
||
|
||
/* Set return value */
|
||
ret_value=(ssize_t)len;
|
||
|
||
done:
|
||
FUNC_LEAVE_API(ret_value);
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5I_debug
|
||
*
|
||
* Purpose: Dump the contents of a group to stderr for debugging.
|
||
*
|
||
* Return: Success: Non-negative
|
||
*
|
||
* Failure: Negative
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Friday, February 19, 1999
|
||
*
|
||
* Modifications:
|
||
*
|
||
* Pedro Vicente, <pvn@ncsa.uiuc.edu> 22 Aug 2002
|
||
* Added `id to name' support.
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
#ifdef H5I_DEBUG_OUTPUT
|
||
static herr_t
|
||
H5I_debug(H5I_type_t grp)
|
||
{
|
||
H5I_id_group_t *grp_ptr;
|
||
H5I_id_info_t *cur;
|
||
H5G_entry_t *ent = NULL;
|
||
int is, js;
|
||
unsigned int iu;
|
||
herr_t ret_value; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(H5I_debug, FAIL);
|
||
|
||
fprintf(stderr, "Dumping group %d\n", (int)grp);
|
||
grp_ptr = H5I_id_group_list_g[grp];
|
||
|
||
/* Header */
|
||
fprintf(stderr, " count = %u\n", grp_ptr->count);
|
||
fprintf(stderr, " reserved = %u\n", grp_ptr->reserved);
|
||
fprintf(stderr, " wrapped = %u\n", grp_ptr->wrapped);
|
||
fprintf(stderr, " hash_size = %lu\n", (unsigned long)grp_ptr->hash_size);
|
||
fprintf(stderr, " ids = %u\n", grp_ptr->ids);
|
||
fprintf(stderr, " nextid = %u\n", grp_ptr->nextid);
|
||
|
||
/* Cache */
|
||
fprintf(stderr, " Cache:\n");
|
||
for (is=0; is<ID_CACHE_SIZE; is++) {
|
||
if (H5I_cache_g[is] && H5I_GROUP(H5I_cache_g[is]->id)==grp) {
|
||
fprintf(stderr, " Entry-%d, ID=%lu\n",
|
||
is, (unsigned long)(H5I_cache_g[is]->id));
|
||
}
|
||
}
|
||
|
||
/* List */
|
||
fprintf(stderr, " List:\n");
|
||
for (iu=0; iu<grp_ptr->hash_size; iu++) {
|
||
for (js=0, cur=grp_ptr->id_list[iu]; cur; cur=cur->next, js++) {
|
||
fprintf(stderr, " #%u.%d\n", iu, js);
|
||
fprintf(stderr, " id = %lu\n", (unsigned long)(cur->id));
|
||
fprintf(stderr, " count = %u\n", cur->count);
|
||
fprintf(stderr, " obj = 0x%08lx\n", (unsigned long)(cur->obj_ptr));
|
||
|
||
/* Get the symbol table entry, so we get get the name */
|
||
switch(grp) {
|
||
case H5I_GROUP:
|
||
ent = H5G_entof((H5G_t*)cur->obj_ptr);
|
||
break;
|
||
case H5I_DATASET:
|
||
ent = H5D_entof((H5D_t*)cur->obj_ptr);
|
||
break;
|
||
case H5I_DATATYPE:
|
||
ent = H5T_entof((H5T_t*)cur->obj_ptr);
|
||
break;
|
||
default:
|
||
continue; /* Other types of IDs are not stored in files */
|
||
} /* end switch*/
|
||
|
||
if(ent) {
|
||
if(ent->name)
|
||
fprintf(stderr, " name = %s\n",ent->name);
|
||
if(ent->old_name)
|
||
fprintf(stderr, " old_name = %s\n",ent->old_name);
|
||
} /* end if */
|
||
} /* end for */
|
||
} /* end for */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(SUCCEED);
|
||
}
|
||
#endif /* H5I_DEBUG_OUTPUT */
|
||
|