diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2013-10-07 22:04:27 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2013-10-07 22:04:27 (GMT) |
commit | 3a96de8b17df2964f4ad7da5c9742b3bd71b3c38 (patch) | |
tree | 93e44fbe16b9b6227fb28f7f415939a1e1602237 | |
parent | 307f88870c18d050912cb7bb614480420a794a9c (diff) | |
download | hdf5-3a96de8b17df2964f4ad7da5c9742b3bd71b3c38.zip hdf5-3a96de8b17df2964f4ad7da5c9742b3bd71b3c38.tar.gz hdf5-3a96de8b17df2964f4ad7da5c9742b3bd71b3c38.tar.bz2 |
[svn-r24262] Description:
Bring r24256 & r24261 from trunk to 1.8 branch:
Switch H5I internal data structure from using hash table to skip lists.
Also, a few misc. cleanups.
Tested on:
FreeBSD/32 8.2 (loyalty) w/gcc4.6, w/C++ & FORTRAN, in debug mode
FreeBSD/64 8.2 (freedom) w/gcc4.6, w/C++ & FORTRAN, in debug mode
Linux/32 2.6 (jam) w/PGI compilers, w/default API=1.8.x,
w/C++ & FORTRAN, w/threadsafe, in debug mode
Linux/64-amd64 2.6 (koala) w/Intel compilers, w/default API=1.6.x,
w/C++ & FORTRAN, in production mode
Solaris/32 2.11 (emu) w/deprecated symbols disabled, w/C++ & FORTRAN,
w/szip filter, w/threadsafe, in production mode
Linux/PPC 2.6 (ostrich) w/C++ & FORTRAN, w/threadsafe, in debug mode
-rwxr-xr-x | configure | 60 | ||||
-rw-r--r-- | configure.ac | 6 | ||||
-rw-r--r-- | src/H5A.c | 3 | ||||
-rw-r--r-- | src/H5ACprivate.h | 3 | ||||
-rw-r--r-- | src/H5B2cache.c | 8 | ||||
-rw-r--r-- | src/H5Dint.c | 3 | ||||
-rw-r--r-- | src/H5E.c | 9 | ||||
-rw-r--r-- | src/H5F.c | 3 | ||||
-rw-r--r-- | src/H5FD.c | 3 | ||||
-rw-r--r-- | src/H5Fprivate.h | 1 | ||||
-rw-r--r-- | src/H5G.c | 3 | ||||
-rw-r--r-- | src/H5I.c | 889 | ||||
-rw-r--r-- | src/H5Iprivate.h | 6 | ||||
-rw-r--r-- | src/H5Pint.c | 4 | ||||
-rw-r--r-- | src/H5R.c | 3 | ||||
-rw-r--r-- | src/H5S.c | 3 | ||||
-rw-r--r-- | src/H5SL.c | 43 | ||||
-rw-r--r-- | src/H5SLprivate.h | 1 | ||||
-rw-r--r-- | src/H5T.c | 1 | ||||
-rw-r--r-- | src/H5private.h | 36 |
20 files changed, 549 insertions, 539 deletions
@@ -28775,9 +28775,9 @@ else unset MPE fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CLOG_Init in -llmpe" >&5 -$as_echo_n "checking for CLOG_Init in -llmpe... " >&6; } -if ${ac_cv_lib_lmpe_CLOG_Init+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MPE_Init_mpi_io in -llmpe" >&5 +$as_echo_n "checking for MPE_Init_mpi_io in -llmpe... " >&6; } +if ${ac_cv_lib_lmpe_MPE_Init_mpi_io+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -28791,7 +28791,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext #ifdef __cplusplus extern "C" #endif -char CLOG_Init (); +char MPE_Init_mpi_io (); #ifdef FC_DUMMY_MAIN #ifndef FC_DUMMY_MAIN_EQ_F77 # ifdef __cplusplus @@ -28803,23 +28803,23 @@ char CLOG_Init (); int main () { -return CLOG_Init (); +return MPE_Init_mpi_io (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_lmpe_CLOG_Init=yes + ac_cv_lib_lmpe_MPE_Init_mpi_io=yes else - ac_cv_lib_lmpe_CLOG_Init=no + ac_cv_lib_lmpe_MPE_Init_mpi_io=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lmpe_CLOG_Init" >&5 -$as_echo "$ac_cv_lib_lmpe_CLOG_Init" >&6; } -if test "x$ac_cv_lib_lmpe_CLOG_Init" = xyes; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lmpe_MPE_Init_mpi_io" >&5 +$as_echo "$ac_cv_lib_lmpe_MPE_Init_mpi_io" >&6; } +if test "x$ac_cv_lib_lmpe_MPE_Init_mpi_io" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBLMPE 1 _ACEOF @@ -28950,9 +28950,9 @@ else LDFLAGS="$saved_LDFLAGS"; AM_LDFLAGS="$saved_AM_LDFLAGS"; unset MPE fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CLOG_Init in -llmpe" >&5 -$as_echo_n "checking for CLOG_Init in -llmpe... " >&6; } -if ${ac_cv_lib_lmpe_CLOG_Init+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MPE_Init_mpi_io in -llmpe" >&5 +$as_echo_n "checking for MPE_Init_mpi_io in -llmpe... " >&6; } +if ${ac_cv_lib_lmpe_MPE_Init_mpi_io+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -28966,7 +28966,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext #ifdef __cplusplus extern "C" #endif -char CLOG_Init (); +char MPE_Init_mpi_io (); #ifdef FC_DUMMY_MAIN #ifndef FC_DUMMY_MAIN_EQ_F77 # ifdef __cplusplus @@ -28978,23 +28978,23 @@ char CLOG_Init (); int main () { -return CLOG_Init (); +return MPE_Init_mpi_io (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_lmpe_CLOG_Init=yes + ac_cv_lib_lmpe_MPE_Init_mpi_io=yes else - ac_cv_lib_lmpe_CLOG_Init=no + ac_cv_lib_lmpe_MPE_Init_mpi_io=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lmpe_CLOG_Init" >&5 -$as_echo "$ac_cv_lib_lmpe_CLOG_Init" >&6; } -if test "x$ac_cv_lib_lmpe_CLOG_Init" = xyes; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lmpe_MPE_Init_mpi_io" >&5 +$as_echo "$ac_cv_lib_lmpe_MPE_Init_mpi_io" >&6; } +if test "x$ac_cv_lib_lmpe_MPE_Init_mpi_io" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBLMPE 1 _ACEOF @@ -29062,9 +29062,9 @@ else unset MPE fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CLOG_Init in -llmpe" >&5 -$as_echo_n "checking for CLOG_Init in -llmpe... " >&6; } -if ${ac_cv_lib_lmpe_CLOG_Init+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MPE_Init_mpi_io in -llmpe" >&5 +$as_echo_n "checking for MPE_Init_mpi_io in -llmpe... " >&6; } +if ${ac_cv_lib_lmpe_MPE_Init_mpi_io+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -29078,7 +29078,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext #ifdef __cplusplus extern "C" #endif -char CLOG_Init (); +char MPE_Init_mpi_io (); #ifdef FC_DUMMY_MAIN #ifndef FC_DUMMY_MAIN_EQ_F77 # ifdef __cplusplus @@ -29090,23 +29090,23 @@ char CLOG_Init (); int main () { -return CLOG_Init (); +return MPE_Init_mpi_io (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_lmpe_CLOG_Init=yes + ac_cv_lib_lmpe_MPE_Init_mpi_io=yes else - ac_cv_lib_lmpe_CLOG_Init=no + ac_cv_lib_lmpe_MPE_Init_mpi_io=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lmpe_CLOG_Init" >&5 -$as_echo "$ac_cv_lib_lmpe_CLOG_Init" >&6; } -if test "x$ac_cv_lib_lmpe_CLOG_Init" = xyes; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lmpe_MPE_Init_mpi_io" >&5 +$as_echo "$ac_cv_lib_lmpe_MPE_Init_mpi_io" >&6; } +if test "x$ac_cv_lib_lmpe_MPE_Init_mpi_io" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBLMPE 1 _ACEOF diff --git a/configure.ac b/configure.ac index 78108ec..3291bfc 100644 --- a/configure.ac +++ b/configure.ac @@ -2864,7 +2864,7 @@ if test -n "$PARALLEL"; then X-yes) AC_CHECK_HEADERS([mpe.h],, [unset MPE]) AC_CHECK_LIB([mpe], [MPE_Init_log],, [unset MPE]) - AC_CHECK_LIB([lmpe], [CLOG_Init],, [unset MPE]) + AC_CHECK_LIB([lmpe], [MPE_Init_mpi_io],, [unset MPE]) ;; *) case "$withval" in @@ -2906,12 +2906,12 @@ if test -n "$PARALLEL"; then AM_LDFLAGS="$AM_LDFLAGS -L$mpe_lib" AC_CHECK_LIB([mpe], [MPE_Init_log],, [LDFLAGS="$saved_LDFLAGS"; AM_LDFLAGS="$saved_AM_LDFLAGS"; unset MPE]) - AC_CHECK_LIB([lmpe], [CLOG_Init],, + AC_CHECK_LIB([lmpe], [MPE_Init_mpi_io],, [LDFLAGS="$saved_LDFLAGS"; AM_LDFLAGS="$saved_AM_LDFLAGS"; unset MPE]) else AC_CHECK_LIB([mpe], [MPE_Init_log],, [unset MPE]) - AC_CHECK_LIB([lmpe], [CLOG_Init],, [unset MPE]) + AC_CHECK_LIB([lmpe], [MPE_Init_mpi_io],, [unset MPE]) fi ;; esac @@ -94,8 +94,7 @@ H5FL_BLK_DEFINE(attr_buf); /* Attribute ID class */ static const H5I_class_t H5I_ATTR_CLS[1] = {{ H5I_ATTR, /* ID class value */ - 0, /* Class flags */ - 64, /* Minimum hash size for class */ + H5I_CLASS_REUSE_IDS, /* Class flags */ 0, /* # of reserved IDs for class */ (H5I_free_t)H5A_close /* Callback routine for closing objects of this class */ }}; diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h index 68412a0..2e7bcd7 100644 --- a/src/H5ACprivate.h +++ b/src/H5ACprivate.h @@ -319,8 +319,7 @@ H5_DLL herr_t H5AC_insert_entry(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *typ haddr_t addr, void *thing, unsigned int flags); H5_DLL herr_t H5AC_pin_protected_entry(void *thing); H5_DLL void * H5AC_protect(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, - haddr_t addr, void *udata, - H5AC_protect_t rw); + haddr_t addr, void *udata, H5AC_protect_t rw); H5_DLL herr_t H5AC_resize_entry(void *thing, size_t new_size); H5_DLL herr_t H5AC_unpin_entry(void *thing); H5_DLL herr_t H5AC_unprotect(H5F_t *f, hid_t dxpl_id, diff --git a/src/H5B2cache.c b/src/H5B2cache.c index 87684f0..4d4b69f 100644 --- a/src/H5B2cache.c +++ b/src/H5B2cache.c @@ -190,12 +190,12 @@ H5B2__cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata) /* Magic number */ if(HDmemcmp(p, H5B2_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC)) - HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree header signature") + HGOTO_ERROR(H5E_BTREE, H5E_BADVALUE, NULL, "wrong B-tree header signature") p += H5_SIZEOF_MAGIC; /* Version */ if(*p++ != H5B2_HDR_VERSION) - HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree header version") + HGOTO_ERROR(H5E_BTREE, H5E_BADRANGE, NULL, "wrong B-tree header version") /* B-tree class */ id = (H5B2_subid_t)*p++; @@ -529,12 +529,12 @@ H5B2__cache_internal_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata) /* Magic number */ if(HDmemcmp(p, H5B2_INT_MAGIC, (size_t)H5_SIZEOF_MAGIC)) - HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree internal node signature") + HGOTO_ERROR(H5E_BTREE, H5E_BADVALUE, NULL, "wrong B-tree internal node signature") p += H5_SIZEOF_MAGIC; /* Version */ if(*p++ != H5B2_INT_VERSION) - HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree internal node version") + HGOTO_ERROR(H5E_BTREE, H5E_BADRANGE, NULL, "wrong B-tree internal node version") /* B-tree type */ if(*p++ != (uint8_t)udata->hdr->cls->id) diff --git a/src/H5Dint.c b/src/H5Dint.c index 8ce842b..1704c0f 100644 --- a/src/H5Dint.c +++ b/src/H5Dint.c @@ -109,8 +109,7 @@ static H5D_shared_t H5D_def_dset; /* Dataset ID class */ static const H5I_class_t H5I_DATASET_CLS[1] = {{ H5I_DATASET, /* ID class value */ - 0, /* Class flags */ - 64, /* Minimum hash size for class */ + H5I_CLASS_REUSE_IDS, /* Class flags */ 0, /* # of reserved IDs for class */ (H5I_free_t)H5D_close /* Callback routine for closing objects of this class */ }}; @@ -122,8 +122,7 @@ H5FL_DEFINE_STATIC(H5E_msg_t); /* Error class ID class */ static const H5I_class_t H5I_ERRCLS_CLS[1] = {{ H5I_ERROR_CLASS, /* ID class value */ - 0, /* Class flags */ - 64, /* Minimum hash size for class */ + H5I_CLASS_REUSE_IDS, /* Class flags */ 0, /* # of reserved IDs for class */ (H5I_free_t)H5E_unregister_class /* Callback routine for closing objects of this class */ }}; @@ -131,8 +130,7 @@ static const H5I_class_t H5I_ERRCLS_CLS[1] = {{ /* Error message ID class */ static const H5I_class_t H5I_ERRMSG_CLS[1] = {{ H5I_ERROR_MSG, /* ID class value */ - 0, /* Class flags */ - 64, /* Minimum hash size for class */ + H5I_CLASS_REUSE_IDS, /* Class flags */ 0, /* # of reserved IDs for class */ (H5I_free_t)H5E_close_msg /* Callback routine for closing objects of this class */ }}; @@ -140,8 +138,7 @@ static const H5I_class_t H5I_ERRMSG_CLS[1] = {{ /* Error stack ID class */ static const H5I_class_t H5I_ERRSTK_CLS[1] = {{ H5I_ERROR_STACK, /* ID class value */ - 0, /* Class flags */ - 64, /* Minimum hash size for class */ + H5I_CLASS_REUSE_IDS, /* Class flags */ 0, /* # of reserved IDs for class */ (H5I_free_t)H5E_close_stack /* Callback routine for closing objects of this class */ }}; @@ -122,8 +122,7 @@ H5FL_DEFINE(H5F_file_t); /* File ID class */ static const H5I_class_t H5I_FILE_CLS[1] = {{ H5I_FILE, /* ID class value */ - 0, /* Class flags */ - 64, /* Minimum hash size for class */ + H5I_CLASS_REUSE_IDS, /* Class flags */ 0, /* # of reserved IDs for class */ (H5I_free_t)H5F_close /* Callback routine for closing objects of this class */ }}; @@ -116,8 +116,7 @@ static unsigned long file_serial_no; /* File driver ID class */ static const H5I_class_t H5I_VFL_CLS[1] = {{ H5I_VFL, /* ID class value */ - 0, /* Class flags */ - 64, /* Minimum hash size for class */ + H5I_CLASS_REUSE_IDS, /* Class flags */ 0, /* # of reserved IDs for class */ (H5I_free_t)H5FD_free_cls /* Callback routine for closing objects of this class */ }}; diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index 770d868..1c6913c 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -501,7 +501,6 @@ H5_DLL unsigned H5F_decr_nopen_objs(H5F_t *f); H5_DLL hid_t H5F_get_file_id(const H5F_t *f); H5_DLL H5F_t *H5F_get_parent(const H5F_t *f); H5_DLL unsigned H5F_get_nmounts(const H5F_t *f); -H5_DLL herr_t H5F_flush_mounts(H5F_t *f, hid_t dxpl_id); H5_DLL hid_t H5F_get_access_plist(H5F_t *f, hbool_t app_ref); H5_DLL hid_t H5F_get_id(H5F_t *file, hbool_t app_ref); H5_DLL herr_t H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref, size_t *obj_id_count_ptr); @@ -133,8 +133,7 @@ /* Group ID class */ static const H5I_class_t H5I_GROUP_CLS[1] = {{ H5I_GROUP, /* ID class value */ - 0, /* Class flags */ - 64, /* Minimum hash size for class */ + H5I_CLASS_REUSE_IDS, /* Class flags */ 0, /* # of reserved IDs for class */ (H5I_free_t)H5G_close /* Callback routine for closing objects of this class */ }}; @@ -48,6 +48,7 @@ #include "H5Ipkg.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ #include "H5Oprivate.h" /* Object headers */ +#include "H5SLprivate.h" /* Skip Lists */ /* Define this to compile in support for dumping ID information */ /* #define H5I_DEBUG_OUTPUT */ @@ -66,25 +67,6 @@ for re-use. */ #define MAX_FREE_ID_STRUCTS 1000 -/* - * Define the following macro for fast hash calculations (but limited - * hash sizes) - */ -#define HASH_SIZE_POWER_2 - -#ifdef HASH_SIZE_POWER_2 -/* - * Map an ID to a hash location (assumes s is a power of 2 and smaller - * than the ID_MASK constant). - */ -# define H5I_LOC(a,s) ((hid_t)((size_t)(a)&((s)-1))) -#else -/* - * Map an ID to a hash location. - */ -# define H5I_LOC(a,s) (((hid_t)(a)&ID_MASK)%(s)) -#endif - /* Combine a Type number and an atom index into an atom */ #define H5I_MAKE(g,i) ((((hid_t)(g)&TYPE_MASK)<<ID_BITS)| \ ((hid_t)(i)&ID_MASK)) @@ -97,20 +79,20 @@ typedef struct H5I_id_info_t { unsigned count; /* ref. count for this atom */ unsigned app_count; /* ref. count of application visible atoms */ const void *obj_ptr; /* pointer associated with the atom */ - struct H5I_id_info_t *next; /* link to next atom (in case of hash-clash)*/ } H5I_id_info_t; /* ID type structure used */ typedef struct { const H5I_class_t *cls; /* Pointer to ID class */ - unsigned count; /*# of times this type has been initialized*/ - unsigned free_count; /* # of available ID structures awaiting recycling */ - unsigned wrapped; /*whether the id count has wrapped around */ - unsigned ids; /*current number of IDs held */ - unsigned nextid; /*ID to use for the next atom */ - unsigned reuse_ids; /* whether to reuse returned IDs for this type */ - H5I_id_info_t * next_id_ptr; /* pointer to head of available ID list */ - H5I_id_info_t **id_list; /*pointer to an array of ptrs to IDs */ + unsigned init_count; /* # of times this type has been initialized*/ + hbool_t wrapped; /* Whether the id count has wrapped around */ + unsigned id_count; /* Current number of IDs held */ + hid_t nextid; /* ID to use for the next atom */ + H5SL_t *ids; /* Pointer to skip list that stores IDs */ + + /* Fields for holding available IDs */ + unsigned avail_count; /* # of available ID structures awaiting recycling */ + H5SL_t *avail_ids; /* pointer to skip list of available IDs */ } H5I_id_type_t; typedef struct { @@ -119,6 +101,18 @@ typedef struct { void *ret_obj; /* Object to return */ } H5I_search_ud_t; +/* User data for iterator callback when IDs have wrapped */ +typedef struct { + hid_t nextid; /* Next ID to expect */ +} H5I_wrap_ud_t; + +/* User data for iterator callback for ID iteration */ +typedef struct { + H5I_search_func_t user_func; /* 'User' function to invoke */ + void *user_udata; /* User data to pass to 'user' function */ + hbool_t app_ref; /* Whether this is an appl. ref. call */ +} H5I_iterate_ud_t; + /*-------------------- Locally scoped variables -----------------------------*/ /* Array of pointers to atomic types */ @@ -142,10 +136,15 @@ H5FL_DEFINE_STATIC(H5I_id_type_t); H5FL_DEFINE_STATIC(H5I_class_t); /*--------------------- Local function prototypes ---------------------------*/ -static H5I_id_info_t *H5I_find_id(hid_t id); -static int H5I_search_cb(void *obj, hid_t id, void *udata); +static herr_t H5I__free_cb(void *_item, void *_key, void *_udata); +static int H5I__destroy_type(H5I_type_t type); +static void *H5I__remove_verify(hid_t id, H5I_type_t id_type); +static void *H5I__remove_common(H5I_id_type_t *type_ptr, hid_t id); +static int H5I__inc_type_ref(H5I_type_t type); +static int H5I__get_type_ref(H5I_type_t type); +static H5I_id_info_t *H5I__find_id(hid_t id); #ifdef H5I_DEBUG_OUTPUT -static herr_t H5I_debug(H5I_type_t type); +static herr_t H5I__debug(H5I_type_t type); #endif /* H5I_DEBUG_OUTPUT */ @@ -198,7 +197,7 @@ H5I_term_interface(void) if(H5_interface_initialize_g) { /* How many types are still being used? */ for(type = (H5I_type_t)0; type < H5I_next_type; H5_INC_ENUM(H5I_type_t, type)) { - if((type_ptr = H5I_id_type_list_g[type]) && type_ptr->id_list) + if((type_ptr = H5I_id_type_list_g[type]) && type_ptr->ids) n++; } /* end for */ @@ -207,7 +206,7 @@ H5I_term_interface(void) for(type = (H5I_type_t)0; type < H5I_next_type; H5_INC_ENUM(H5I_type_t,type)) { type_ptr = H5I_id_type_list_g[type]; if(type_ptr) { - HDassert(NULL == type_ptr->id_list); + HDassert(NULL == type_ptr->ids); type_ptr = H5FL_FREE(H5I_id_type_t, type_ptr); H5I_id_type_list_g[type] = NULL; } /* end if */ @@ -286,7 +285,6 @@ H5Iregister_type(size_t hash_size, unsigned reserved, H5I_free_t free_func) /* Initialize class fields */ cls->type_id = new_type; cls->flags = H5I_CLASS_IS_APPLICATION; - cls->hash_size = hash_size; cls->reserved = reserved; cls->free_func = free_func; @@ -337,13 +335,6 @@ H5I_register_type(const H5I_class_t *cls) HDassert(cls->type_id > 0 && cls->type_id < H5I_MAX_NUM_TYPES); /* Initialize the type */ - - /* Check arguments */ -#ifdef HASH_SIZE_POWER_2 - if(!POWER_OF_TWO(cls->hash_size) || cls->hash_size == 1) - HGOTO_ERROR(H5E_ATOM, H5E_BADRANGE, FAIL, "invalid hash size") -#endif /* HASH_SIZE_POWER_2 */ - if(NULL == H5I_id_type_list_g[cls->type_id]) { /* Allocate the type information for new type */ if(NULL == (type_ptr = (H5I_id_type_t *)H5FL_CALLOC(H5I_id_type_t))) @@ -356,35 +347,28 @@ H5I_register_type(const H5I_class_t *cls) } /* end else */ /* Initialize the ID type structure for new types */ - if(type_ptr->count == 0) { + if(type_ptr->init_count == 0) { type_ptr->cls = cls; - type_ptr->wrapped = 0; - type_ptr->ids = 0; - type_ptr->nextid = cls->reserved; - type_ptr->next_id_ptr = NULL; - type_ptr->id_list = (H5I_id_info_t **)H5MM_calloc(cls->hash_size * sizeof(H5I_id_info_t *)); - if(NULL == type_ptr->id_list) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5I_BADID, "memory allocation failed") - - /* Don't re-use IDs for property lists, as this causes problems - * with some virtual file drivers. Also, open datatypes are not - * getting reduced to zero before file close in some situations, - * resulting in memory leak, so skip them for now as well. */ - if(cls->type_id == H5I_GENPROP_LST || cls->type_id == H5I_DATATYPE) - type_ptr->reuse_ids = FALSE; - else - type_ptr->reuse_ids = TRUE; - + type_ptr->wrapped = FALSE; + type_ptr->id_count = 0; + type_ptr->nextid = (hid_t)cls->reserved; + if(NULL == (type_ptr->ids = H5SL_create(H5SL_TYPE_HID, NULL))) + HGOTO_ERROR(H5E_ATOM, H5E_CANTCREATE, FAIL, "skip list creation failed") + type_ptr->avail_count = 0; + if(NULL == (type_ptr->avail_ids = H5SL_create(H5SL_TYPE_HID, NULL))) + HGOTO_ERROR(H5E_ATOM, H5E_CANTCREATE, FAIL, "skip list creation failed") } /* end if */ /* Increment the count of the times this type has been initialized */ - type_ptr->count++; + type_ptr->init_count++; done: if(ret_value < 0) { /* Clean up on error */ if(type_ptr) { - if(type_ptr->id_list) - H5MM_xfree(type_ptr->id_list); + if(type_ptr->ids) + H5SL_close(type_ptr->ids); + if(type_ptr->avail_ids) + H5SL_close(type_ptr->avail_ids); (void)H5FL_FREE(H5I_id_type_t, type_ptr); } /* end if */ } /* end if */ @@ -503,11 +487,11 @@ H5I_nmembers(H5I_type_t type) if(type <= H5I_BADID || type >= H5I_next_type) HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number") - if(NULL == (type_ptr = H5I_id_type_list_g[type]) || type_ptr->count <= 0) + if(NULL == (type_ptr = H5I_id_type_list_g[type]) || type_ptr->init_count <= 0) HGOTO_DONE(0); /* Set return value */ - H5_ASSIGN_OVERFLOW(ret_value, type_ptr->ids, unsigned, int); + H5_ASSIGN_OVERFLOW(ret_value, type_ptr->id_count, unsigned, int); done: FUNC_LEAVE_NOAPI(ret_value) @@ -549,6 +533,35 @@ done: /*------------------------------------------------------------------------- + * Function: H5I__free_cb + * + * Purpose: Callback for freeing ID nodes in H5I__remove_common + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Friday, October 4, 2013 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5I__free_cb(void *_item, void UNUSED *_key, void UNUSED *_udata) +{ + H5I_id_info_t *item = (H5I_id_info_t *)_item; /* Pointer to the ID node */ + + FUNC_ENTER_STATIC_NOERR + + /* Sanity check */ + HDassert(item); + + item = H5FL_FREE(H5I_id_info_t, item); + + FUNC_LEAVE_NOAPI(H5_ITER_CONT) +} /* end H5I__free_cb() */ + + +/*------------------------------------------------------------------------- * Function: H5I_clear_type * * Purpose: Removes all objects from the type, calling the free @@ -560,32 +573,14 @@ done: * 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. - * - * Neil Fortner, 2008-08-08 - * Added app_ref parameter. If app_ref is FALSE, then the - * application reference count is ignored (i.e. subtracted from - * the total reference count) when determining which id's to - * close. *------------------------------------------------------------------------- */ herr_t H5I_clear_type(H5I_type_t type, hbool_t force, hbool_t app_ref) { H5I_id_type_t *type_ptr; /* ptr to the atomic type */ - unsigned i; /* Local index variable */ + H5SL_node_t *curr_node; /* Current skip list node ptr */ + H5SL_node_t *next_node; /* Next skip list node ptr */ int ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -594,7 +589,7 @@ H5I_clear_type(H5I_type_t type, hbool_t force, hbool_t app_ref) HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number") type_ptr = H5I_id_type_list_g[type]; - if(type_ptr == NULL || type_ptr->count <= 0) + if(type_ptr == NULL || type_ptr->init_count <= 0) HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type") /* @@ -602,22 +597,21 @@ H5I_clear_type(H5I_type_t type, hbool_t force, hbool_t app_ref) * counts. Ignore the return value from from the free method and remove * object from type regardless if FORCE is non-zero. */ - for(i = 0; i < type_ptr->cls->hash_size; i++) { - H5I_id_info_t *cur; /* Current node being worked with */ - H5I_id_info_t *next; /* Next node in list */ - - for(cur = type_ptr->id_list[i]; cur; cur = next) { - hbool_t delete_node; /* Flag to indicate node should be removed from linked list */ - - /* - * Do nothing to the object if the reference count is larger than - * one and forcing is off. - */ - if(!force && (cur->count - (!app_ref * cur->app_count)) > 1) { - next = cur->next; - continue; - } /* end if */ + for(curr_node = H5SL_first(type_ptr->ids); curr_node; curr_node = next_node) { + H5I_id_info_t *cur; /* Current ID being worked with */ + hbool_t delete_node; /* Flag to indicate node should be removed from linked list */ + + /* Get ID for this node */ + if(NULL == (cur = (H5I_id_info_t *)H5SL_item(curr_node))) + HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't get ID info for node") + /* + * Do nothing to the object if the reference count is larger than + * one and forcing is off. + */ + if(!force && (cur->count - (!app_ref * cur->app_count)) > 1) + delete_node = FALSE; + else { /* Check for a 'free' function and call it, if it exists */ /* (Casting away const OK -QAK) */ if(type_ptr->cls->free_func && (type_ptr->cls->free_func)((void *)cur->obj_ptr) < 0) { @@ -642,62 +636,31 @@ H5I_clear_type(H5I_type_t type, hbool_t force, hbool_t app_ref) /* Indicate node should be removed from list */ delete_node = TRUE; } /* end else */ + } /* end else */ - /* Check if we should delete this node or not */ - if(delete_node) { - H5I_id_info_t *last; /* Last node seen */ - H5I_id_info_t *tmp; /* Temporary node ptr */ - - /* Decrement the number of IDs in the type */ - (type_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 = type_ptr->id_list[i]; - while(tmp != cur) { - HDassert(tmp != NULL); - last = tmp; - tmp = tmp->next; - } /* end while */ - - /* Delete the node from the list */ - if(NULL == last) { - /* Node at head of list, just advance the list head to next node */ - HDassert(type_ptr->id_list[i] == cur); - type_ptr->id_list[i] = next; - } /* end if */ - else { - /* Node in middle of list, jump over it */ - HDassert(last->next == cur); - last->next = next; - } /* end else */ + /* Get the next node in the list */ + next_node = H5SL_next(curr_node); - /* Free the node */ - cur = H5FL_FREE(H5I_id_info_t, cur); - } /* end if */ - else { - /* Advance to next node */ - next = cur->next; - } /* end else */ - } /* end for */ + /* Check if we should delete this node or not */ + if(delete_node) { + /* Decrement the number of IDs in the type */ + (type_ptr->id_count)--; + + /* Remove the node from the list */ + if(NULL == H5SL_remove(type_ptr->ids, &cur->id)) + HGOTO_ERROR(H5E_ATOM, H5E_CANTDELETE, FAIL, "can't remove ID node from skip list") + + /* Free the node */ + cur = H5FL_FREE(H5I_id_info_t, cur); + } /* end if */ } /* end for */ /* Also free any ID structures being retained for potential re-use */ - while(type_ptr->next_id_ptr) { - H5I_id_info_t *tmp_id_ptr; /* temp ptr to next atom */ - - tmp_id_ptr = type_ptr->next_id_ptr->next; - (void)H5FL_FREE(H5I_id_info_t, type_ptr->next_id_ptr); - type_ptr->next_id_ptr = tmp_id_ptr; - } /* end while */ - type_ptr->free_count = 0; + if(type_ptr->avail_count > 0) { + if(H5SL_free(type_ptr->avail_ids, H5I__free_cb, NULL) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREMOVE, FAIL, "can't release available ID nodes") + type_ptr->avail_count = 0; + } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) @@ -711,7 +674,7 @@ done: * regardless of their reference counts. Destroying IDs * involves calling the free-func for each ID's object and * then adding the ID struct to the ID free list. Public - * interface to H5I_destroy_type. + * interface to H5I__destroy_type. * * Return: Zero on success/Negative on failure * @@ -731,7 +694,7 @@ H5Idestroy_type(H5I_type_t type) if(H5I_IS_LIB_TYPE(type)) HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type") - ret_value = H5I_destroy_type(type); + ret_value = H5I__destroy_type(type); done: FUNC_LEAVE_API(ret_value) @@ -739,7 +702,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5I_destroy_type + * Function: H5I__destroy_type * * Purpose: Destroys a type along with all atoms in that type * regardless of their reference counts. Destroying IDs @@ -753,19 +716,19 @@ done: * *------------------------------------------------------------------------- */ -herr_t -H5I_destroy_type(H5I_type_t type) +static herr_t +H5I__destroy_type(H5I_type_t type) { H5I_id_type_t *type_ptr; /* ptr to the atomic type */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_STATIC if(type <= H5I_BADID || type >= H5I_next_type) HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number") type_ptr = H5I_id_type_list_g[type]; - if(type_ptr == NULL || type_ptr->count <= 0) + if(type_ptr == NULL || type_ptr->init_count <= 0) HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type") /* Close/clear/destroy all IDs for this type */ @@ -777,14 +740,20 @@ H5I_destroy_type(H5I_type_t type) if(type_ptr->cls->flags & H5I_CLASS_IS_APPLICATION) type_ptr->cls = H5FL_FREE(H5I_class_t, (void *)type_ptr->cls); - type_ptr->id_list = H5MM_xfree(type_ptr->id_list); + if(H5SL_close(type_ptr->avail_ids) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTCLOSEOBJ, FAIL, "can't close skip list") + type_ptr->avail_ids = NULL; + + if(H5SL_close(type_ptr->ids) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTCLOSEOBJ, FAIL, "can't close skip list") + type_ptr->ids = NULL; type_ptr = H5FL_FREE(H5I_id_type_t, type_ptr); H5I_id_type_list_g[type] = NULL; done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5I_destroy_type() */ +} /* end H5I__destroy_type() */ /*------------------------------------------------------------------------- @@ -819,6 +788,47 @@ done: /*------------------------------------------------------------------------- + * Function: H5I__wrapped_cb + * + * Purpose: Callback for searching for next free ID, when IDs have wrapped + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Thursday, October 3, 2013 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5I__wrapped_cb(void *_item, void UNUSED *_key, void *_udata) +{ + H5I_id_info_t *item = (H5I_id_info_t *)_item; /* Pointer to the ID node */ + H5I_wrap_ud_t *udata = (H5I_wrap_ud_t *)_udata; /* Pointer to user data */ + int ret_value = H5_ITER_CONT; /* Return value */ + + FUNC_ENTER_STATIC_NOERR + + /* Sanity check */ + HDassert(item); + HDassert(udata); + + /* Break out if we see a free ID */ + if(udata->nextid != item->id) { + /* Sanity check */ + HDassert(item->id > udata->nextid); + + ret_value = H5_ITER_STOP; + } /* end if */ + else + /* Increment to expect the next ID */ + udata->nextid++; + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5I__wrapped_cb() */ + + +/*------------------------------------------------------------------------- * Function: H5I_register * * Purpose: Registers an OBJECT in a TYPE and returns an ID for it. @@ -834,13 +844,6 @@ done: * * Programmer: Unknown * - * Modifications: - * - * Neil Fortner, 7 Aug 2008 - * Added app_ref parameter and support for the app_count field, to - * distiguish between reference count from the library and from the - * application. - * *------------------------------------------------------------------------- */ hid_t @@ -848,10 +851,6 @@ H5I_register(H5I_type_t type, const void *object, hbool_t app_ref) { H5I_id_type_t *type_ptr; /*ptr to the type */ H5I_id_info_t *id_ptr; /*ptr to the new ID information */ - unsigned hash_loc; /*new item's hash table location*/ - hid_t next_id; /*next ID to check */ - H5I_id_info_t *curr_id; /*ptr to the current atom */ - unsigned i; /*counter */ hid_t ret_value = SUCCEED; /*return value */ FUNC_ENTER_NOAPI(FAIL) @@ -860,19 +859,17 @@ H5I_register(H5I_type_t type, const void *object, hbool_t app_ref) if(type <= H5I_BADID || type >= H5I_next_type) HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number") type_ptr = H5I_id_type_list_g[type]; - if(NULL == type_ptr || type_ptr->count <= 0) + if(NULL == type_ptr || type_ptr->init_count <= 0) HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type") /* If there is an available ID structure, use it. */ - if(type_ptr->next_id_ptr) { + if(type_ptr->avail_count > 0) { /* Use existing available ID struct */ - id_ptr = type_ptr->next_id_ptr; + if(NULL == (id_ptr = (H5I_id_info_t *)H5SL_remove_first(type_ptr->avail_ids))) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREMOVE, FAIL, "can't remove ID from available ID list") - /* Remove struct from list of available ones */ - type_ptr->next_id_ptr = type_ptr->next_id_ptr->next; - /* Decrease count of available ID structures */ - type_ptr->free_count--; + type_ptr->avail_count--; } /* end if */ /* If no available ID structure, then create a new id for use, and * allocate a new struct to house it. */ @@ -892,63 +889,44 @@ H5I_register(H5I_type_t type, const void *object, hbool_t app_ref) id_ptr->count = 1; /*initial reference count*/ id_ptr->app_count = !!app_ref; id_ptr->obj_ptr = object; - id_ptr->next = NULL; - - /* hash bucket already full, prepend to front of chain */ - hash_loc = id_ptr->id % (unsigned)type_ptr->cls->hash_size; - if(type_ptr->id_list[hash_loc] != NULL) - id_ptr->next = type_ptr->id_list[hash_loc]; /* Insert into the type */ - type_ptr->id_list[hash_loc] = id_ptr; - type_ptr->ids++; + if(H5SL_insert(type_ptr->ids, id_ptr, &id_ptr->id) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTINSERT, FAIL, "can't insert ID node into skip list") + type_ptr->id_count++; /* * 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(type_ptr->nextid > (unsigned)ID_MASK) { - type_ptr->wrapped = 1; - type_ptr->nextid = type_ptr->cls->reserved; - } /* end if */ + if(type_ptr->nextid > (hid_t)ID_MASK) + type_ptr->wrapped = TRUE; /* * If we've wrapped around then we need to check for duplicate id's being * handed out. */ if(type_ptr->wrapped) { - /* - * Make sure we check all available ID's. If we're about at the end - * of the range then wrap around and check the beginning values. If - * we check all possible values and didn't find any free ones *then* - * we can fail. - */ - for(i = type_ptr->cls->reserved; i < ID_MASK; i++) { - /* Handle end of range by wrapping to beginning */ - if(type_ptr->nextid > (unsigned)ID_MASK) - type_ptr->nextid = type_ptr->cls->reserved; - - /* new ID to check for */ - next_id = H5I_MAKE(type, type_ptr->nextid); - hash_loc = (unsigned)H5I_LOC(type_ptr->nextid, type_ptr->cls->hash_size); - curr_id = type_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; - } /* end while */ - if(!curr_id) - break; /* must not have found a match */ - type_ptr->nextid++; - } /* end for */ - - if(i >= (unsigned)ID_MASK) - /* All the IDs are gone! */ + H5I_wrap_ud_t udata; /* User data for iteration */ + herr_t iter_status; /* Iteration status */ + + /* Set up user data for iteration */ + udata.nextid = (hid_t)type_ptr->cls->reserved; + + /* Iterate over all the ID nodes, looking for a gap in the ID sequence */ + if((iter_status = H5SL_iterate(type_ptr->ids, H5I__wrapped_cb, &udata)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_BADITER, FAIL, "ID iteration failed") + + /* If we didn't break out of the iteration and we're at the max. ID, we've used all the IDs */ + if(0 == iter_status && udata.nextid >= ID_MASK) HGOTO_ERROR(H5E_ATOM, H5E_NOIDS, FAIL, "no IDs available in type") + + /* Sanity check */ + HDassert(udata.nextid < ID_MASK); + + /* Retain the next ID for the class */ + type_ptr->nextid = udata.nextid; } /* end if */ /* Set return value */ @@ -982,7 +960,7 @@ H5I_subst(hid_t id, const void *new_object) FUNC_ENTER_NOAPI(NULL) /* General lookup of the ID */ - if(NULL == (id_ptr = H5I_find_id(id))) + if(NULL == (id_ptr = H5I__find_id(id))) HGOTO_ERROR(H5E_ATOM, H5E_NOTFOUND, NULL, "can't get ID ref count") /* Get the old object pointer to return */ @@ -1019,7 +997,7 @@ H5I_object(hid_t id) FUNC_ENTER_NOAPI(NULL) /* General lookup of the ID */ - if(NULL != (id_ptr = H5I_find_id(id))) { + if(NULL != (id_ptr = H5I__find_id(id))) { /* Get the object pointer to return */ /* (Casting away const OK -QAK) */ ret_value = (void *)id_ptr->obj_ptr; @@ -1093,7 +1071,7 @@ H5I_object_verify(hid_t id, H5I_type_t id_type) HDassert(id_type >= 1 && id_type < H5I_next_type); /* Verify that the type of the ID is correct & lookup the ID */ - if(id_type == H5I_TYPE(id) && NULL != (id_ptr = H5I_find_id(id))) { + if(id_type == H5I_TYPE(id) && NULL != (id_ptr = H5I__find_id(id))) { /* Get the object pointer to return */ /* (Casting away const OK -QAK) */ ret_value = (void *)id_ptr->obj_ptr; @@ -1175,7 +1153,7 @@ done: * * Purpose: Removes the specified ID from its type, first checking that the * type of the ID and the type type are the same. Public interface to - * H5I_remove_verify. + * H5I__remove_verify. * * Return: Success: A pointer to the object that was removed, the * same pointer which would have been found by @@ -1198,7 +1176,7 @@ H5Iremove_verify(hid_t id, H5I_type_t id_type) HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "cannot call public function on library type") /* Remove the id */ - ret_value = H5I_remove_verify(id, id_type); + ret_value = H5I__remove_verify(id, id_type); done: FUNC_LEAVE_API(ret_value) @@ -1206,7 +1184,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5I_remove_verify + * Function: H5I__remove_verify * * Purpose: Removes the specified ID from its type, first checking that * the ID's type is the same as the ID type supplied as an argument @@ -1222,11 +1200,11 @@ done: *------------------------------------------------------------------------- */ void * -H5I_remove_verify(hid_t id, H5I_type_t id_type) +H5I__remove_verify(hid_t id, H5I_type_t id_type) { void * ret_value = NULL; /*return value */ - FUNC_ENTER_NOAPI(NULL) + FUNC_ENTER_STATIC_NOERR /* Argument checking will be performed by H5I_remove() */ @@ -1234,10 +1212,72 @@ H5I_remove_verify(hid_t id, H5I_type_t id_type) if(id_type == H5I_TYPE(id)) ret_value = H5I_remove(id); -done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5I_remove_verify() */ +} /* end H5I__remove_verify() */ + + +/*------------------------------------------------------------------------- + * Function: H5I__remove_common + * + * Purpose: Common code to remove a specified ID from its type. + * + * 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: Quincey Koziol + * October 3, 2013 + * + *------------------------------------------------------------------------- + */ +static void * +H5I__remove_common(H5I_id_type_t *type_ptr, hid_t id) +{ + H5I_id_info_t *curr_id; /*ptr to the current atom */ + void * ret_value; /*return value */ + + FUNC_ENTER_STATIC + + /* Sanity check */ + HDassert(type_ptr); + + /* Get the ID node for the ID */ + if(NULL == (curr_id = (H5I_id_info_t *)H5SL_remove(type_ptr->ids, &id))) + HGOTO_ERROR(H5E_ATOM, H5E_CANTDELETE, NULL, "can't remove ID node from skip list") + /* (Casting away const OK -QAK) */ + ret_value = (void *)curr_id->obj_ptr; + + /* If there's room, and we can save IDs of this type, then + save the struct (and its ID) for future re-use */ + if((type_ptr->cls->flags & H5I_CLASS_REUSE_IDS) + && (type_ptr->avail_count < MAX_FREE_ID_STRUCTS)) { + if(H5SL_insert(type_ptr->avail_ids, curr_id, &curr_id->id) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTINSERT, NULL, "can't insert available ID node into skip list") + type_ptr->avail_count++; + } /* end if */ + /* Otherwise, just toss it. */ + else + curr_id = H5FL_FREE(H5I_id_info_t, curr_id); + + /* Decrement the number of IDs in the type */ + (type_ptr->id_count)--; + + /* If there are no more IDs of this type, then we can free all available + ID strutures, and reset starting typeid and wrapped status. */ + if(0 == type_ptr->id_count) { + if(H5SL_free(type_ptr->avail_ids, H5I__free_cb, NULL) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREMOVE, NULL, "can't release available ID nodes") + type_ptr->avail_count = 0; + + type_ptr->nextid = (hid_t)type_ptr->cls->reserved; + type_ptr->wrapped = FALSE; + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5I__remove_common() */ /*------------------------------------------------------------------------- @@ -1258,12 +1298,8 @@ void * H5I_remove(hid_t id) { H5I_id_type_t *type_ptr; /*ptr to the atomic type */ - H5I_id_info_t *curr_id; /*ptr to the current atom */ - H5I_id_info_t *last_id; /*ptr to the last atom */ - H5I_id_info_t *tmp_id_ptr; /*temp ptr to next atom */ H5I_type_t type; /*atom's atomic type */ - unsigned hash_loc; /*atom's hash table location */ - void * ret_value = NULL; /*return value */ + void * ret_value; /*return value */ FUNC_ENTER_NOAPI(NULL) @@ -1272,65 +1308,12 @@ H5I_remove(hid_t id) if(type <= H5I_BADID || type >= H5I_next_type) HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "invalid type number") type_ptr = H5I_id_type_list_g[type]; - if(type_ptr == NULL || type_ptr->count <= 0) + if(type_ptr == NULL || type_ptr->init_count <= 0) HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "invalid type") - /* Get the bucket in which the ID is located */ - hash_loc = (unsigned)H5I_LOC(id, type_ptr->cls->hash_size); - curr_id = type_ptr->id_list[hash_loc]; - if(NULL == curr_id) - 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; - } /* end while */ - - if(curr_id != NULL) { - if(last_id == NULL) { - /* ID is the first in the chain */ - type_ptr->id_list[hash_loc] = curr_id->next; - } else { - last_id->next = curr_id->next; - } - /* (Casting away const OK -QAK) */ - ret_value = (void *)curr_id->obj_ptr; - - /* If there's room, and we can save IDs of this type, then - save the struct (and its ID) for future re-use */ - if((type_ptr->reuse_ids)&&(type_ptr->free_count < MAX_FREE_ID_STRUCTS)) { - curr_id->next = type_ptr->next_id_ptr; - type_ptr->next_id_ptr = curr_id; - type_ptr->free_count++; - } /* end if */ - /* Otherwise, just toss it. */ - else - curr_id = H5FL_FREE(H5I_id_info_t, curr_id); - } /* end if */ - 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 type */ - (type_ptr->ids)--; - - /* If there are no more IDs of this type, then we can free all available - ID strutures, and reset starting typeid and wrapped status. */ - if(type_ptr->ids == 0) { - while(type_ptr->next_id_ptr) { - tmp_id_ptr = type_ptr->next_id_ptr->next; - (void)H5FL_FREE(H5I_id_info_t, type_ptr->next_id_ptr); - type_ptr->next_id_ptr = tmp_id_ptr; - } /* end while */ - type_ptr->free_count = 0; - - type_ptr->nextid = type_ptr->cls->reserved; - type_ptr->wrapped = FALSE; - } /* end if */ + /* Remove the node from the type */ + if(NULL == (ret_value = H5I__remove_common(type_ptr, id))) + HGOTO_ERROR(H5E_ATOM, H5E_CANTDELETE, NULL, "can't remove ID node") done: FUNC_LEAVE_NOAPI(ret_value) @@ -1408,11 +1391,11 @@ H5I_dec_ref(hid_t id) if(type <= H5I_BADID || type >= H5I_next_type) HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number") type_ptr = H5I_id_type_list_g[type]; - if(NULL == type_ptr || type_ptr->count <= 0) + if(NULL == type_ptr || type_ptr->init_count <= 0) HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number") /* General lookup of the ID */ - if(NULL == (id_ptr = H5I_find_id(id))) + if(NULL == (id_ptr = (H5I_id_info_t *)H5SL_search(type_ptr->ids, &id))) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't locate ID") /* @@ -1433,7 +1416,9 @@ H5I_dec_ref(hid_t id) if(1 == id_ptr->count) { /* (Casting away const OK -QAK) */ if(!type_ptr->cls->free_func || (type_ptr->cls->free_func)((void *)id_ptr->obj_ptr) >= 0) { - H5I_remove(id); + /* Remove the node from the type */ + if(NULL == H5I__remove_common(type_ptr, id)) + HGOTO_ERROR(H5E_ATOM, H5E_CANTDELETE, FAIL, "can't remove ID node") ret_value = 0; } /* end if */ else @@ -1481,7 +1466,7 @@ H5I_dec_app_ref(hid_t id) /* Check if the ID still exists */ if(ret_value > 0) { /* General lookup of the ID */ - if(NULL == (id_ptr = H5I_find_id(id))) + if(NULL == (id_ptr = H5I__find_id(id))) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't locate ID") /* Adjust app_ref */ @@ -1587,13 +1572,6 @@ done: * Programmer: Robb Matzke * Thursday, July 29, 1999 * - * Modifications: - * - * Neil Fortner, 7 Aug 2008 - * Added app_ref parameter and support for the app_count field, to - * distiguish between reference count from the library and from the - * application. - * *------------------------------------------------------------------------- */ int @@ -1614,11 +1592,11 @@ H5I_inc_ref(hid_t id, hbool_t app_ref) if(type <= H5I_BADID || type >= H5I_next_type) HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number") type_ptr = H5I_id_type_list_g[type]; - if(!type_ptr || type_ptr->count <= 0) + if(!type_ptr || type_ptr->init_count <= 0) HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type") /* General lookup of the ID */ - if(NULL == (id_ptr = H5I_find_id(id))) + if(NULL == (id_ptr = (H5I_id_info_t *)H5SL_search(type_ptr->ids, &id))) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't locate ID") /* Adjust reference counts */ @@ -1679,13 +1657,6 @@ done: * Programmer: Quincey Koziol * Saturday, Decemeber 6, 2003 * - * Modifications: - * - * Neil Fortner, 7 Aug 2008 - * Added app_ref parameter and support for the app_count field, to - * distiguish between reference count from the library and from the - * application. - * *------------------------------------------------------------------------- */ int @@ -1706,11 +1677,11 @@ H5I_get_ref(hid_t id, hbool_t app_ref) if(type <= H5I_BADID || type >= H5I_next_type) HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number") type_ptr = H5I_id_type_list_g[type]; - if(!type_ptr || type_ptr->count <= 0) + if(!type_ptr || type_ptr->init_count <= 0) HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type") /* General lookup of the ID */ - if(NULL == (id_ptr = H5I_find_id(id))) + if(NULL == (id_ptr = (H5I_id_info_t *)H5SL_search(type_ptr->ids, &id))) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't locate ID") /* Set return value */ @@ -1751,7 +1722,7 @@ H5Iinc_type_ref(H5I_type_t type) HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type") /* Do actual increment operation */ - if((ret_value = H5I_inc_type_ref(type)) < 0) + if((ret_value = H5I__inc_type_ref(type)) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CANTINC, FAIL, "can't increment ID type ref count") done: @@ -1760,7 +1731,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5I_inc_type_ref + * Function: H5I__inc_type_ref * * Purpose: Increment the reference count for an ID type. * @@ -1773,13 +1744,13 @@ done: * *------------------------------------------------------------------------- */ -int -H5I_inc_type_ref(H5I_type_t type) +static int +H5I__inc_type_ref(H5I_type_t type) { H5I_id_type_t *type_ptr; /* ptr to the type */ int ret_value; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_STATIC /* Sanity check */ HDassert(type > 0 && type < H5I_next_type); @@ -1790,11 +1761,11 @@ H5I_inc_type_ref(H5I_type_t type) HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type") /* Set return value */ - ret_value = (int)(++(type_ptr->count)); + ret_value = (int)(++(type_ptr->init_count)); done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5I_inc_type_ref() */ +} /* end H5I__inc_type_ref() */ /*------------------------------------------------------------------------- @@ -1869,7 +1840,7 @@ H5I_dec_type_ref(H5I_type_t type) HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number") type_ptr = H5I_id_type_list_g[type]; - if(type_ptr == NULL || type_ptr->count <= 0) + if(type_ptr == NULL || type_ptr->init_count <= 0) HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type") /* @@ -1878,13 +1849,13 @@ H5I_dec_type_ref(H5I_type_t type) * free all memory it used. The free function is invoked for each atom * being freed. */ - if(1 == type_ptr->count) { - H5I_destroy_type(type); + if(1 == type_ptr->init_count) { + H5I__destroy_type(type); ret_value = 0; } /* end if */ else { - --(type_ptr->count); - ret_value = (herr_t)type_ptr->count; + --(type_ptr->init_count); + ret_value = (herr_t)type_ptr->init_count; } /* end else */ done: @@ -1922,7 +1893,7 @@ H5Iget_type_ref(H5I_type_t type) HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type") /* Do actual retrieve operation */ - if((ret_value = H5I_get_type_ref(type)) < 0) + if((ret_value = H5I__get_type_ref(type)) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't get ID type ref count") done: @@ -1931,7 +1902,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5I_get_type_ref + * Function: H5I__get_type_ref * * Purpose: Retrieve the reference count for an ID type. * @@ -1945,13 +1916,13 @@ done: * *------------------------------------------------------------------------- */ -int -H5I_get_type_ref(H5I_type_t type) +static int +H5I__get_type_ref(H5I_type_t type) { H5I_id_type_t *type_ptr; /*ptr to the type */ int ret_value; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_STATIC /* Sanity check */ HDassert(type >= 0); @@ -1962,11 +1933,11 @@ H5I_get_type_ref(H5I_type_t type) HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type") /* Set return value */ - ret_value = (int)type_ptr->count; + ret_value = (int)type_ptr->init_count; done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5I_get_type_ref() */ +} /* end H5I__get_type_ref() */ /*------------------------------------------------------------------------- @@ -1994,7 +1965,7 @@ H5Iis_valid(hid_t id) H5TRACE1("t", "i", id); /* Find the ID */ - if (NULL == (id_ptr = H5I_find_id(id))) + if (NULL == (id_ptr = H5I__find_id(id))) ret_value = FALSE; /* Check if the found id is an internal id */ @@ -2007,7 +1978,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5I_search_cb + * Function: H5I__search_cb * * Purpose: Callback routine for H5Isearch, when it calls H5I_iterate. * Calls "user" callback search function, and then sets return @@ -2024,19 +1995,19 @@ done: *------------------------------------------------------------------------- */ static int -H5I_search_cb(void *obj, hid_t id, void *_udata) +H5I__search_cb(void *obj, hid_t id, void *_udata) { H5I_search_ud_t *udata = (H5I_search_ud_t *)_udata; /* User data for callback */ int ret_value; /* Callback return value */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR ret_value = (*udata->app_cb)(obj, id, udata->app_key); if(ret_value > 0) udata->ret_obj = obj; FUNC_LEAVE_NOAPI(ret_value) -} /* end H5I_search_cb() */ +} /* end H5I__search_cb() */ /*------------------------------------------------------------------------- @@ -2083,7 +2054,7 @@ H5Isearch(H5I_type_t type, H5I_search_func_t func, void *key) /* Note that H5I_iterate returns an error code. We ignore it * here, as we can't do anything with it without revising the API. */ - H5I_iterate(type, H5I_search_cb, &udata, TRUE); + (void)H5I_iterate(type, H5I__search_cb, &udata, TRUE); /* Set return value */ ret_value = udata.ret_obj; @@ -2094,6 +2065,46 @@ done: /*------------------------------------------------------------------------- + * Function: H5I__iterate_cb + * + * Purpose: Callback routine for H5I_iterate, invokes "user" callback + * function, and then sets return value, based on the result of + * that callback. + * + * Return: Success: Non-negative on success + * Failure: Negative + * + * Programmer: Quincey Koziol + * Thursday, October 3, 2013 + * + *------------------------------------------------------------------------- + */ +static int +H5I__iterate_cb(void *_item, void UNUSED *_key, void *_udata) +{ + H5I_id_info_t *item = (H5I_id_info_t *)_item; /* Pointer to the ID node */ + H5I_iterate_ud_t *udata = (H5I_iterate_ud_t *)_udata; /* User data for callback */ + int ret_value = H5_ITER_CONT; /* Callback return value */ + + FUNC_ENTER_STATIC_NOERR + + /* Don't make callback if app_ref is set and the appl. ref count is 0 */ + if((!udata->app_ref) || (item->app_count > 0)) { + herr_t cb_ret_val; + + /* (Casting away const OK) */ + cb_ret_val = (*udata->user_func)((void *)item->obj_ptr, item->id, udata->user_udata); + if(cb_ret_val > 0) + ret_value = H5_ITER_STOP; /* terminate iteration early */ + else if(cb_ret_val < 0) + ret_value = H5_ITER_ERROR; /* indicate failure (which terminates iteration) */ + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5I__iterate_cb() */ + + +/*------------------------------------------------------------------------- * Function: H5I_iterate * * Purpose: Apply function FUNC to each member of type TYPE (with @@ -2135,33 +2146,19 @@ H5I_iterate(H5I_type_t type, H5I_search_func_t func, void *udata, hbool_t app_re HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number") type_ptr = H5I_id_type_list_g[type]; - /* Only iterate through hash table if it is initialized and there are IDs in group */ - if(type_ptr && type_ptr->count > 0 && type_ptr->ids > 0) { - unsigned u; /* Counter */ - - /* Start at the beginning of the array */ - for(u = 0; u < type_ptr->cls->hash_size; u++) { - H5I_id_info_t *id_ptr; /* Ptr to the new ID */ - - id_ptr = type_ptr->id_list[u]; - while(id_ptr) { - H5I_id_info_t *next_id; /* Ptr to the next ID */ - - /* Protect against ID being deleted in callback */ - next_id = id_ptr->next; - if((!app_ref) || (id_ptr->app_count > 0)) { - herr_t cb_ret_val; /* Callback return value */ - - /* (Casting away const OK) */ - cb_ret_val = (*func)((void *)id_ptr->obj_ptr, id_ptr->id, udata); - if(cb_ret_val > 0) - HGOTO_DONE(SUCCEED) /* terminate iteration early */ - else if(cb_ret_val < 0) - HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "func failed") - } /* end if */ - id_ptr = next_id; - } /* end while */ - } /* end for */ + /* Only iterate through ID list if it is initialized and there are IDs in type */ + if(type_ptr && type_ptr->init_count > 0 && type_ptr->id_count > 0) { + H5I_iterate_ud_t iter_udata; /* User data for iteration callback */ + herr_t iter_status; /* Iteration status */ + + /* Set up iterator user data */ + iter_udata.user_func = func; + iter_udata.user_udata = udata; + iter_udata.app_ref = app_ref; + + /* Iterate over IDs */ + if((iter_status = H5SL_iterate(type_ptr->ids, H5I__iterate_cb, &iter_udata)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_BADITER, FAIL, "iteration failed") } /* end if */ done: @@ -2170,7 +2167,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5I_find_id + * Function: H5I__find_id * * Purpose: Given an object ID find the info struct that describes the * object. @@ -2184,16 +2181,13 @@ done: *------------------------------------------------------------------------- */ static H5I_id_info_t * -H5I_find_id(hid_t id) +H5I__find_id(hid_t id) { H5I_id_type_t *type_ptr; /*ptr to the type */ - H5I_id_info_t *last_id; /*ptr to the last ID */ - H5I_id_info_t *id_ptr; /*ptr to the new ID */ H5I_type_t type; /*ID's type */ - unsigned hash_loc; /*bucket pointer */ H5I_id_info_t *ret_value; /*return value */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR /* Check arguments */ type = H5I_TYPE(id); @@ -2201,35 +2195,15 @@ H5I_find_id(hid_t id) HGOTO_DONE(NULL); type_ptr = H5I_id_type_list_g[type]; - if (!type_ptr || type_ptr->count <= 0) + if (!type_ptr || type_ptr->init_count <= 0) HGOTO_DONE(NULL); - /* Get the bucket in which the ID is located */ - hash_loc = (unsigned)H5I_LOC(id, type_ptr->cls->hash_size); - id_ptr = type_ptr->id_list[hash_loc]; - - /* Scan the bucket's linked list for a match */ - last_id = NULL; - while(id_ptr) { - if(id_ptr->id == id) { - /* If we found an object, move it to the front of the list, if it isn't there already */ - if(last_id != NULL) { - last_id->next = id_ptr->next; - id_ptr->next = type_ptr->id_list[hash_loc]; - type_ptr->id_list[hash_loc] = id_ptr; - } /* end if */ - break; - } /* end if */ - last_id = id_ptr; - id_ptr = id_ptr->next; - } /* end while */ - - /* Set the return value */ - ret_value = id_ptr; + /* Locate the ID node for the ID */ + ret_value = (H5I_id_info_t *)H5SL_search(type_ptr->ids, &id); done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5I_find_id() */ +} /* end H5I__find_id() */ /*------------------------------------------------------------------------- @@ -2360,9 +2334,66 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5I_get_file_id() */ +#ifdef H5I_DEBUG_OUTPUT /*------------------------------------------------------------------------- - * Function: H5I_debug + * Function: H5I__debug_cb + * + * Purpose: Dump the contents of an ID to stderr for debugging. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Robb Matzke + * Friday, February 19, 1999 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5I__debug_cb(void *_item, void UNUSED *_key, void *_udata) +{ + H5I_id_info_t *item = (H5I_id_info_t *)_item; /* Pointer to the ID node */ + H5I_type_t type = *(H5I_type_t *)_udata; /* User data */ + H5G_name_t *path = NULL; + int ret_value = H5_ITER_CONT; /* Return value */ + + FUNC_ENTER_STATIC_NOERR + + fprintf(stderr, " id = %lu\n", (unsigned long)(item->id)); + fprintf(stderr, " count = %u\n", item->count); + fprintf(stderr, " obj = 0x%08lx\n", (unsigned long)(item->obj_ptr)); + + /* Get the group location, so we get get the name */ + switch(type) { + case H5I_GROUP: + path = H5G_nameof((H5G_t*)item->obj_ptr); + break; + + case H5I_DATASET: + path = H5D_nameof((H5D_t*)item->obj_ptr); + break; + + case H5I_DATATYPE: + path = H5T_nameof((H5T_t*)item->obj_ptr); + break; + + default: + break; /* Other types of IDs are not stored in files */ + } /* end switch*/ + + if(path) { + if(path->user_path_r) + fprintf(stderr, " user_path = %s\n", H5RS_get_str(path->user_path_r)); + if(path->full_path_r) + fprintf(stderr, " full_path = %s\n", H5RS_get_str(path->full_path_r)); + } /* end if */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5I__debug_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5I__debug * * Purpose: Dump the contents of a type to stderr for debugging. * @@ -2374,74 +2405,28 @@ done: * *------------------------------------------------------------------------- */ -#ifdef H5I_DEBUG_OUTPUT static herr_t -H5I_debug(H5I_type_t type) +H5I__debug(H5I_type_t type) { H5I_id_type_t *type_ptr; - H5I_id_info_t *cur; - H5G_name_t *path; - int is, js; - unsigned int iu; - herr_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_STATIC_NOERR fprintf(stderr, "Dumping ID type %d\n", (int)type); type_ptr = H5I_id_type_list_g[type]; /* Header */ - fprintf(stderr, " count = %u\n", type_ptr->count); - fprintf(stderr, " reserved = %u\n", type_ptr->cls->reserved); - fprintf(stderr, " wrapped = %u\n", type_ptr->wrapped); - fprintf(stderr, " hash_size = %lu\n", (unsigned long)type_ptr->cls->hash_size); - fprintf(stderr, " ids = %u\n", type_ptr->ids); - fprintf(stderr, " nextid = %u\n", type_ptr->nextid); - - /* Cache */ - fprintf(stderr, " Cache:\n"); - for (is=0; is<ID_CACHE_SIZE; is++) { - if (H5I_cache_g[is] && H5I_TYPE(H5I_cache_g[is]->id)==type) { - fprintf(stderr, " Entry-%d, ID=%lu\n", - is, (unsigned long)(H5I_cache_g[is]->id)); - } - } + fprintf(stderr, " init_count = %u\n", type_ptr->init_count); + fprintf(stderr, " reserved = %u\n", type_ptr->cls->reserved); + fprintf(stderr, " wrapped = %u\n", type_ptr->wrapped); + fprintf(stderr, " id_count = %u\n", type_ptr->id_count); + fprintf(stderr, " nextid = %u\n", type_ptr->nextid); /* List */ fprintf(stderr, " List:\n"); - for (iu=0; iu<type_ptr->hash_size; iu++) { - for (js=0, cur=type_ptr->id_list[iu]; cur; cur=cur->next, js++) { - fprintf(stderr, " #%u.%d\n", iu, js); - fprintf(stderr, " id = %lu\n", (unsigned long)(cur->id)); - fprintf(stderr, " count = %u\n", cur->count); - fprintf(stderr, " obj = 0x%08lx\n", (unsigned long)(cur->obj_ptr)); - - /* Get the group location, so we get get the name */ - switch(type) { - case H5I_GROUP: - path = H5G_nameof((H5G_t*)cur->obj_ptr); - break; - case H5I_DATASET: - path = H5D_nameof((H5D_t*)cur->obj_ptr); - break; - case H5I_DATATYPE: - path = H5T_nameof((H5T_t*)cur->obj_ptr); - break; - default: - continue; /* Other types of IDs are not stored in files */ - } /* end switch*/ - - if(path) { - if(path->user_path_r) - fprintf(stderr, " user_path = %s\n", H5RS_get_str(path->user_path_r)); - if(ent->canon_path_r) - fprintf(stderr, " canon_path = %s\n", H5RS_get_str(path->canon_path_r)); - } /* end if */ - } /* end for */ - } /* end for */ + H5SL_iterate(type_ptr->ids, H5I__debug_cb, &type); -done: FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5I_debug() */ +} /* end H5I__debug() */ #endif /* H5I_DEBUG_OUTPUT */ diff --git a/src/H5Iprivate.h b/src/H5Iprivate.h index ff1463d..88c2432 100644 --- a/src/H5Iprivate.h +++ b/src/H5Iprivate.h @@ -37,6 +37,7 @@ /* Flags for ID class */ #define H5I_CLASS_IS_APPLICATION 0x01 +#define H5I_CLASS_REUSE_IDS 0x02 /****************************/ @@ -46,7 +47,6 @@ typedef struct H5I_class_t { H5I_type_t type_id; /* Class ID for the type */ unsigned flags; /* Class behavior flags */ - size_t hash_size; /* Minimum hash table size for the type */ unsigned reserved; /* Number of reserved IDs for this type */ /* [A specific number of type entries may be * reserved to enable "constant" values to be @@ -69,7 +69,6 @@ typedef struct H5I_class_t { H5_DLL herr_t H5I_register_type(const H5I_class_t *cls); H5_DLL int H5I_nmembers(H5I_type_t type); H5_DLL herr_t H5I_clear_type(H5I_type_t type, hbool_t force, hbool_t app_ref); -H5_DLL int H5I_destroy_type(H5I_type_t type); H5_DLL hid_t H5I_register(H5I_type_t type, const void *object, hbool_t app_ref); H5_DLL void *H5I_subst(hid_t id, const void *new_object); H5_DLL void *H5I_object(hid_t id); @@ -77,16 +76,13 @@ H5_DLL void *H5I_object_verify(hid_t id, H5I_type_t id_type); H5_DLL H5I_type_t H5I_get_type(hid_t id); H5_DLL hid_t H5I_get_file_id(hid_t obj_id, hbool_t app_ref); H5_DLL void *H5I_remove(hid_t id); -H5_DLL void *H5I_remove_verify(hid_t id, H5I_type_t id_type); H5_DLL herr_t H5I_iterate(H5I_type_t type, H5I_search_func_t func, void *udata, hbool_t app_ref); H5_DLL int H5I_get_ref(hid_t id, hbool_t app_ref); H5_DLL int H5I_inc_ref(hid_t id, hbool_t app_ref); H5_DLL int H5I_dec_ref(hid_t id); H5_DLL int H5I_dec_app_ref(hid_t id); H5_DLL int H5I_dec_app_ref_always_close(hid_t id); -H5_DLL int H5I_inc_type_ref(H5I_type_t type); H5_DLL herr_t H5I_dec_type_ref(H5I_type_t type); -H5_DLL int H5I_get_type_ref(H5I_type_t type); #endif /* _H5Iprivate_H */ diff --git a/src/H5Pint.c b/src/H5Pint.c index b15f039..19b22c8 100644 --- a/src/H5Pint.c +++ b/src/H5Pint.c @@ -268,8 +268,7 @@ H5FL_DEFINE_STATIC(H5P_genplist_t); /* Generic Property Class ID class */ static const H5I_class_t H5I_GENPROPCLS_CLS[1] = {{ H5I_GENPROP_CLS, /* ID class value */ - 0, /* Class flags */ - 64, /* Minimum hash size for class */ + H5I_CLASS_REUSE_IDS, /* Class flags */ 0, /* # of reserved IDs for class */ (H5I_free_t)H5P_close_class /* Callback routine for closing objects of this class */ }}; @@ -278,7 +277,6 @@ static const H5I_class_t H5I_GENPROPCLS_CLS[1] = {{ static const H5I_class_t H5I_GENPROPLST_CLS[1] = {{ H5I_GENPROP_LST, /* ID class value */ 0, /* Class flags */ - 128, /* Minimum hash size for class */ 0, /* # of reserved IDs for class */ (H5I_free_t)H5P_close /* Callback routine for closing objects of this class */ }}; @@ -78,8 +78,7 @@ static ssize_t H5R_get_name(H5F_t *file, hid_t lapl_id, hid_t dxpl_id, hid_t id, /* Reference ID class */ static const H5I_class_t H5I_REFERENCE_CLS[1] = {{ H5I_REFERENCE, /* ID class value */ - 0, /* Class flags */ - 64, /* Minimum hash size for class */ + H5I_CLASS_REUSE_IDS, /* Class flags */ 0, /* # of reserved IDs for class */ NULL /* Callback routine for closing objects of this class */ }}; @@ -89,8 +89,7 @@ H5FL_ARR_DEFINE(hsize_t,H5S_MAX_RANK); /* Dataspace ID class */ static const H5I_class_t H5I_DATASPACE_CLS[1] = {{ H5I_DATASPACE, /* ID class value */ - 0, /* Class flags */ - 64, /* Minimum hash size for class */ + H5I_CLASS_REUSE_IDS, /* Class flags */ 2, /* # of reserved IDs for class */ (H5I_free_t)H5S_close /* Callback routine for closing objects of this class */ }}; @@ -549,10 +549,12 @@ H5SL_init_interface(void) /* Allocate space for array of factories */ H5SL_fac_g = (H5FL_fac_head_t **)H5MM_malloc(sizeof(H5FL_fac_head_t *)); + HDassert(H5SL_fac_g); H5SL_fac_nalloc_g = 1; /* Initialize first factory */ H5SL_fac_g[0] = H5FL_fac_init(sizeof(H5SL_node_t *)); + HDassert(H5SL_fac_g[0]); H5SL_fac_nused_g = 1; FUNC_LEAVE_NOAPI(SUCCEED) @@ -681,6 +683,10 @@ H5SL_insert_common(H5SL_t *slist, void *item, const void *key) H5SL_INSERT(OBJ, slist, prev, const H5_obj_t, key, -) break; + case H5SL_TYPE_HID: + H5SL_INSERT(SCALAR, slist, prev, const hid_t, key, -) + break; + case H5SL_TYPE_GENERIC: H5SL_INSERT(GENERIC, slist, prev, const void, key, -) break; @@ -1110,6 +1116,10 @@ H5SL_remove(H5SL_t *slist, const void *key) H5SL_REMOVE(OBJ, slist, x, const H5_obj_t, key, -) break; + case H5SL_TYPE_HID: + H5SL_REMOVE(SCALAR, slist, x, const hid_t, key, -) + break; + case H5SL_TYPE_GENERIC: H5SL_REMOVE(GENERIC, slist, x, const void, key, -) break; @@ -1293,6 +1303,10 @@ H5SL_search(H5SL_t *slist, const void *key) H5SL_SEARCH(OBJ, slist, x, const H5_obj_t, key, -) break; + case H5SL_TYPE_HID: + H5SL_SEARCH(SCALAR, slist, x, const hid_t, key, -) + break; + case H5SL_TYPE_GENERIC: H5SL_SEARCH(GENERIC, slist, x, const void, key, -) break; @@ -1382,6 +1396,10 @@ H5SL_less(H5SL_t *slist, const void *key) H5SL_SEARCH(OBJ, slist, x, const H5_obj_t, key, -) break; + case H5SL_TYPE_HID: + H5SL_SEARCH(SCALAR, slist, x, const hid_t, key, -) + break; + case H5SL_TYPE_GENERIC: H5SL_SEARCH(GENERIC, slist, x, const void, key, -) break; @@ -1484,6 +1502,10 @@ H5SL_greater(H5SL_t *slist, const void *key) H5SL_SEARCH(OBJ, slist, x, const H5_obj_t, key, -) break; + case H5SL_TYPE_HID: + H5SL_SEARCH(SCALAR, slist, x, const hid_t, key, -) + break; + case H5SL_TYPE_GENERIC: H5SL_SEARCH(GENERIC, slist, x, const void, key, -) break; @@ -1576,6 +1598,10 @@ H5SL_find(H5SL_t *slist, const void *key) H5SL_FIND(OBJ, slist, x, const H5_obj_t, key, -) break; + case H5SL_TYPE_HID: + H5SL_FIND(SCALAR, slist, x, const hid_t, key, -) + break; + case H5SL_TYPE_GENERIC: H5SL_FIND(GENERIC, slist, x, const void, key, -) break; @@ -1665,6 +1691,10 @@ H5SL_below(H5SL_t *slist, const void *key) H5SL_FIND(OBJ, slist, x, const H5_obj_t, key, -) break; + case H5SL_TYPE_HID: + H5SL_FIND(SCALAR, slist, x, const hid_t, key, -) + break; + case H5SL_TYPE_GENERIC: H5SL_FIND(GENERIC, slist, x, const void, key, -) break; @@ -1767,6 +1797,10 @@ H5SL_above(H5SL_t *slist, const void *key) H5SL_FIND(OBJ, slist, x, const H5_obj_t, key, -) break; + case H5SL_TYPE_HID: + H5SL_FIND(SCALAR, slist, x, const hid_t, key, -) + break; + case H5SL_TYPE_GENERIC: H5SL_FIND(GENERIC, slist, x, const void, key, -) break; @@ -1994,7 +2028,8 @@ H5SL_item(H5SL_node_t *slist_node) herr_t H5SL_iterate(H5SL_t *slist, H5SL_operator_t op, void *op_data) { - H5SL_node_t *node; /* Pointers to skip list nodes */ + H5SL_node_t *node; /* Pointer to current skip list node */ + H5SL_node_t *next; /* Pointer to next skip list node */ herr_t ret_value = 0; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOERR @@ -2008,12 +2043,16 @@ H5SL_iterate(H5SL_t *slist, H5SL_operator_t op, void *op_data) /* Free skip list nodes */ node = slist->header->forward[0]; while(node != NULL) { + /* Protect against the node being deleted by the callback */ + next = node->forward[0]; + /* Call the iterator callback */ /* Casting away const OK -QAK */ if((ret_value = (op)(node->item, (void *)node->key, op_data)) != 0) break; - node = node->forward[0]; + /* Advance to next node */ + node = next; } /* end while */ FUNC_LEAVE_NOAPI(ret_value) diff --git a/src/H5SLprivate.h b/src/H5SLprivate.h index 07ee414..ce2f091 100644 --- a/src/H5SLprivate.h +++ b/src/H5SLprivate.h @@ -48,6 +48,7 @@ typedef enum { H5SL_TYPE_UNSIGNED, /* Skip list keys are 'unsigned's */ H5SL_TYPE_SIZE, /* Skip list keys are 'size_t's */ H5SL_TYPE_OBJ, /* Skip list keys are 'H5_obj_t's */ + H5SL_TYPE_HID, /* Skip list keys are 'hid_t's */ H5SL_TYPE_GENERIC /* Skip list keys are unknown, comparison callback supplied */ } H5SL_type_t; @@ -530,7 +530,6 @@ H5FL_DEFINE_STATIC(H5T_path_t); static const H5I_class_t H5I_DATATYPE_CLS[1] = {{ H5I_DATATYPE, /* ID class value */ 0, /* Class flags */ - 64, /* Minimum hash size for class */ 8, /* # of reserved IDs for class */ (H5I_free_t)H5T_close /* Callback routine for closing objects of this class */ }}; diff --git a/src/H5private.h b/src/H5private.h index f828a46..ac4574f 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -210,10 +210,11 @@ */ #define eventa(func_name) h5_mpe_eventa #define eventb(func_name) h5_mpe_eventb -#define MPE_LOG_VARS \ - static int eventa(FUNC) = -1; \ - static int eventb(FUNC) = -1; \ - const char* p_event_start = "start" FUNC; +#define MPE_LOG_VARS \ + static int h5_mpe_eventa = -1; \ + static int h5_mpe_eventb = -1; \ + static char p_event_start[128]; \ + static char p_event_end[128]; /* Hardwire the color to "red", since that's what all the routines are using * now. In the future, if we want to change that color for a given routine, @@ -222,15 +223,18 @@ * color information down to the BEGIN_MPE_LOG macro (which should have a new * BEGIN_MPE_LOG_COLOR variant). -QAK */ -#define BEGIN_MPE_LOG \ - if (H5_MPEinit_g){ \ - if (eventa(FUNC) == -1 && eventb(FUNC) == -1) { \ - const char* p_color = "red"; \ - eventa(FUNC)=MPE_Log_get_event_number(); \ - eventb(FUNC)=MPE_Log_get_event_number(); \ - MPE_Describe_state(eventa(FUNC), eventb(FUNC), (char *)FUNC, (char *)p_color); \ - } \ - MPE_Log_event(eventa(FUNC), 0, (char *)p_event_start); \ +#define BEGIN_MPE_LOG \ + if(H5_MPEinit_g) { \ + if(h5_mpe_eventa == -1 && h5_mpe_eventb == -1) { \ + const char *p_color = "red"; \ + \ + h5_mpe_eventa = MPE_Log_get_event_number(); \ + h5_mpe_eventb = MPE_Log_get_event_number(); \ + HDsnprintf(p_event_start, sizeof(p_event_start) - 1, "start_%s", FUNC); \ + HDsnprintf(p_event_end, sizeof(p_event_end) - 1, "end_%s", FUNC); \ + MPE_Describe_state(h5_mpe_eventa, h5_mpe_eventb, (char *)FUNC, (char *)p_color); \ + } \ + MPE_Log_event(h5_mpe_eventa, 0, p_event_start); \ } @@ -240,9 +244,9 @@ * * Programmer: Long Wang */ -#define FINISH_MPE_LOG \ - if (H5_MPEinit_g) { \ - MPE_Log_event(eventb(FUNC), 0, (char *)FUNC); \ +#define FINISH_MPE_LOG \ + if(H5_MPEinit_g) { \ + MPE_Log_event(h5_mpe_eventb, 0, p_event_end); \ } #else /* H5_HAVE_MPE */ |