summaryrefslogtreecommitdiffstats
path: root/src/H5P.c
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2003-01-09 17:20:03 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2003-01-09 17:20:03 (GMT)
commit9a433b99a56dc575f1c0b11f95b744de61859dbb (patch)
treed8c766537cb9adc364c902bd45477d97f67a4a9f /src/H5P.c
parent7fd449cb7987772a2881a5ced2ae7ad5231f1fa3 (diff)
downloadhdf5-9a433b99a56dc575f1c0b11f95b744de61859dbb.zip
hdf5-9a433b99a56dc575f1c0b11f95b744de61859dbb.tar.gz
hdf5-9a433b99a56dc575f1c0b11f95b744de61859dbb.tar.bz2
[svn-r6252] Purpose:
Lots of performance improvements & a couple new internal API interfaces. Description: Performance Improvements: - Cached file offset & length sizes in shared file struct, to avoid constantly looking them up in the FCPL. - Generic property improvements: - Added "revision" number to generic property classes to speed up comparisons. - Changed method of storing properties from using a hash-table to the TBBT routines in the library. - Share the propery names between classes and the lists derived from them. - Removed redundant 'def_value' buffer from each property. - Switching code to use a "copy on write" strategy for properties in each list, where the properties in each list are shared with the properties in the class, until a property's value is changed in a list. - Fixed error in layout code which was allocating too many buffers. - Redefined public macros of the form (H5open()/H5check, <variable>) internally to only be (<variable>), avoiding innumerable useless calls to H5open() and H5check_version(). - Reuse already zeroed buffers in H5F_contig_fill instead of constantly re-zeroing them. - Don't write fill values if writing entire dataset. - Use gettimeofday() system call instead of time() system when checking the modification time of a dataset. - Added reference counted string API and use it for tracking the names of objects opening in a file (for the ID->name code). - Removed redundant H5P_get() calls in B-tree routines. - Redefine H5T datatype macros internally to the library, to avoid calling H5check redundantly. - Keep dataspace information for dataset locally instead of reading from disk each time. Added new module to track open objects in a file, to allow this (which will be useful eventually for some FPH5 metadata caching issues). - Remove H5AC_find macro which was inlining metadata cache lookups, and call function instead. - Remove redundant memset() calls from H5G_namei() routine. - Remove redundant checking of object type when locating objects in metadata cache and rely on the address only. - Create default dataset object to use when default dataset creation property list is used to create datasets, bypassing querying for all the property list values. - Use default I/O vector size when performing raw data with the default dataset transfer property list, instead of querying for I/O vector size. - Remove H5P_DEFAULT internally to the library, replacing it with more specific default property list based on the type of property list needed. - Remove redundant memset() calls in object header message (H5O*) routines. - Remove redunant memset() calls in data I/O routines. - Split free-list allocation routines into malloc() and calloc()- like routines, instead of one combined routine. - Remove lots of indirection in H5O*() routines. - Simplify metadata cache entry comparison routine (used when flushing entire cache out). - Only enable metadata cache statistics when H5AC_DEBUG is turned on, instead of always tracking them. - Simplify address comparison macro (H5F_addr_eq). - Remove redundant metadata cache entry protections during dataset creation by protecting the object header once and making all the modifications necessary for the dataset creation before unprotecting it. - Reduce # of "number of element in extent" computations performed by computing and storing the value during dataspace creation. - Simplify checking for group location's file information, when file has not been involving in file-mounting operations. - Use binary encoding for modification time, instead of ASCII. - Hoist H5HL_peek calls (to get information in a local heap) out of loops in many group routine. - Use static variable for iterators of selections, instead of dynamically allocation them each time. - Lookup & insert new entries in one step, avoiding traversing group's B-tree twice. - Fixed memory leak in H5Gget_objname_idx() routine (tangential to performance improvements, but fixed along the way). - Use free-list for reference counted strings. - Don't bother copying object names into cached group entries, since they are re-created when an object is opened. The benchmark I used to measure these results created several thousand small (2K) datasets in a file and wrote out the data for them. This is Elena's "regular.c" benchmark. These changes resulted in approximately ~4.3x speedup of the development branch when compared to the previous code in the development branch and ~1.4x speedup compared to the release branch. Additionally, these changes reduce the total memory used (code and data) by the development branch by ~800KB, bringing the development branch back into the same ballpark as the release branch. I'll send out a more detailed description of the benchmark results as a followup note. New internal API routines: Added "reference counted strings" API for tracking strings that get used by multiple owners without duplicating the strings. Added "ternary search tree" API for text->object mappings. Platforms tested: Tested h5committest {arabica (fortran), eirene (fortran, C++) modi4 (parallel, fortran)} Other platforms/configurations tested? FreeBSD 4.7 (sleipnir) serial & parallel Solaris 2.6 (baldric) serial
Diffstat (limited to 'src/H5P.c')
-rw-r--r--src/H5P.c1891
1 files changed, 1237 insertions, 654 deletions
diff --git a/src/H5P.c b/src/H5P.c
index 7913b78..a7341cb 100644
--- a/src/H5P.c
+++ b/src/H5P.c
@@ -21,7 +21,8 @@
#include "H5private.h" /* Generic Functions */
#include "H5Dprivate.h" /* Datasets */
#include "H5Eprivate.h" /* Error handling */
-#include "H5Fprivate.h" /* Files */
+#include "H5Fprivate.h" /* Files */
+#include "H5FLprivate.h" /* Free lists */
#include "H5Iprivate.h" /* IDs */
#include "H5MMprivate.h" /* Memory management */
#include "H5Ppkg.h" /* Property lists */
@@ -34,6 +35,8 @@ static int interface_initialize_g = 0;
#define INTERFACE_INIT H5P_init_interface
static herr_t H5P_init_interface(void);
+/* Local variables */
+
/*
* Predefined property list classes. These are initialized at runtime by
* H5P_init_interface() in this source file.
@@ -56,6 +59,19 @@ hid_t H5P_LST_DATASET_CREATE_g = FAIL;
hid_t H5P_LST_DATASET_XFER_g = FAIL;
hid_t H5P_LST_MOUNT_g = FAIL;
+/* Track the revision count of a class, to make comparisons faster */
+static unsigned H5P_next_rev=0;
+#define H5P_GET_NEXT_REV (H5P_next_rev++)
+
+/* Declare a free list to manage the H5P_genprop_t struct */
+H5FL_DEFINE(H5P_genprop_t);
+
+/* Declare a free list to manage the H5P_genplist_t struct */
+H5FL_DEFINE(H5P_genplist_t);
+
+/* Declare a free list to manage the H5P_genclass_t struct */
+H5FL_DEFINE_STATIC(H5P_genclass_t);
+
/* Local typedefs */
/* Typedef for checking for duplicate class names in parent class */
@@ -66,15 +82,84 @@ typedef struct {
/* Local static functions */
static H5P_genclass_t *H5P_create_class(H5P_genclass_t *par_class,
- const char *name, unsigned hashsize, unsigned internal,
+ const char *name, unsigned internal,
H5P_cls_create_func_t cls_create, void *create_data,
H5P_cls_copy_func_t cls_copy, void *copy_data,
H5P_cls_close_func_t cls_close, void *close_data);
static herr_t H5P_unregister(H5P_genclass_t *pclass, const char *name);
-static H5P_genprop_t *H5P_dup_prop(H5P_genprop_t *oprop);
+static H5P_genprop_t *H5P_dup_prop(H5P_genprop_t *oprop, H5P_prop_within_t type);
static herr_t H5P_free_prop(H5P_genprop_t *prop);
+/*--------------------------------------------------------------------------
+ NAME
+ H5P_do_prop_cb1
+ PURPOSE
+ Internal routine to call a property list callback routine and update
+ the property list accordingly.
+ USAGE
+ herr_t H5P_do_prop_cb1(tree,prop,cb)
+ H5TB_TREE *tree; IN/OUT: TBBT to hold changed properties
+ H5P_genprop_t *prop; IN: Property to call callback for
+ H5P_prp_cb1_t *cb; IN: Callback routine to call
+ RETURNS
+ Returns non-negative on success, negative on failure.
+ DESCRIPTION
+ Calls the callback routine passed in. If the callback routine changes
+ the property value, then the property is duplicated and added to TBBT.
+
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static herr_t
+H5P_do_prop_cb1(H5TB_TREE *tree, H5P_genprop_t *prop, H5P_prp_cb1_t cb)
+{
+ void *tmp_value=NULL; /* Temporary value buffer */
+ H5P_genprop_t *pcopy=NULL; /* Copy of property to insert into TBBT */
+ herr_t ret_value=SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOINIT(H5P_do_prop_cb1);
+
+ /* Allocate space for a temporary copy of the property value */
+ if (NULL==(tmp_value=H5MM_malloc(prop->size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for temporary property value");
+ HDmemcpy(tmp_value,prop->value,prop->size);
+
+ /* Call "type 1" callback ('create', 'copy' or 'close') */
+ if(cb(prop->name,prop->size,tmp_value)<0)
+ HGOTO_ERROR (H5E_PLIST, H5E_CANTINIT, NULL,"Property callback failed");
+
+ /* Check if the property value changed */
+ if(HDmemcmp(tmp_value,prop->value,prop->size)) {
+ /* Make a copy of the class's property */
+ if((pcopy=H5P_dup_prop(prop,H5P_PROP_WITHIN_LIST))==NULL)
+ HGOTO_ERROR (H5E_PLIST, H5E_CANTCOPY, NULL,"Can't copy property");
+
+ /* Copy the changed value into the new property */
+ HDmemcpy(pcopy->value,tmp_value,prop->size);
+
+ /* Insert the changed property into the property list */
+ if(H5P_add_prop(tree,pcopy)<0)
+ HGOTO_ERROR (H5E_PLIST, H5E_CANTINSERT, NULL,"Can't insert property into TBBT");
+ } /* end if */
+
+done:
+ /* Release the temporary value buffer */
+ if(tmp_value!=NULL)
+ H5MM_xfree(tmp_value);
+
+ /* Cleanup on failure */
+ if(ret_value<0) {
+ if(pcopy!=NULL)
+ H5P_free_prop(pcopy);
+ } /* end if */
+
+ FUNC_LEAVE(ret_value);
+} /* end H5P_do_prop_cb1() */
+
+
/*-------------------------------------------------------------------------
* Function: H5P_init
*
@@ -106,60 +191,6 @@ done:
/*--------------------------------------------------------------------------
NAME
- H5P_xor_name -- Generate an xor'ed value for a string
-USAGE
- unsigned H5P_xor_name(s)
- const char *s; IN: String to operate over
-RETURNS
- Always returns valid value
-DESCRIPTION
- Generates an xor'ed value for a string
---------------------------------------------------------------------------*/
-static unsigned
-H5P_xor_name(const char *s)
-{
- unsigned ret=0;
- unsigned char temp;
-
- /* Use FUNC_ENTER_NOINIT here to avoid performance issues */
- FUNC_ENTER_NOINIT(H5P_xor_name);
-
- if(s!=NULL)
- while(*s!='\0') {
- temp=(ret>>24)&0xff;
- ret <<= 8;
- ret |= temp;
- ret ^= *s++;
- }
-
- FUNC_LEAVE(ret);
-} /* end H5P_xor_name() */
-
-
-/*--------------------------------------------------------------------------
-NAME
- H5P_hash_name -- Generate a hash value for a string
-USAGE
- unsigned H5P_hash_name(s, hashsize)
- const char *s; IN: String to operate over
- unsigned; IN: Size of hash table to clip against
-RETURNS
- Always returns valid value
-DESCRIPTION
- Generates a hash location based on an xor'ed value for a string
---------------------------------------------------------------------------*/
-static unsigned
-H5P_hash_name(const char *s, unsigned hashsize)
-{
- /* Use FUNC_ENTER_NOINIT here to avoid performance issues */
- FUNC_ENTER_NOINIT(H5P_hash_name);
-
- FUNC_LEAVE(H5P_xor_name(s)%hashsize);
-} /* end H5P_hash_name() */
-
-
-/*--------------------------------------------------------------------------
-NAME
H5P_init_interface -- Initialize interface-specific information
USAGE
herr_t H5P_init_interface()
@@ -195,7 +226,7 @@ H5P_init_interface(void)
/* Allocate the root class */
assert(H5P_CLS_NO_CLASS_g==(-1));
- if (NULL==(root_class = H5P_create_class (NULL,"root",H5P_NO_CLASS_HASH_SIZE,1,NULL,NULL,NULL,NULL,NULL,NULL)))
+ if (NULL==(root_class = H5P_create_class (NULL,"root",1,NULL,NULL,NULL,NULL,NULL,NULL)))
HGOTO_ERROR (H5E_PLIST, H5E_CANTINIT, FAIL, "class initialization failed");
/* Register the root class */
@@ -206,7 +237,7 @@ H5P_init_interface(void)
/* Allocate the file creation class */
assert(H5P_CLS_FILE_CREATE_g==(-1));
- if (NULL==(pclass = H5P_create_class (root_class,"file create",H5P_FILE_CREATE_HASH_SIZE,1,NULL,NULL,NULL,NULL,NULL,NULL)))
+ if (NULL==(pclass = H5P_create_class (root_class,"file create",1,NULL,NULL,NULL,NULL,NULL,NULL)))
HGOTO_ERROR (H5E_PLIST, H5E_CANTINIT, FAIL, "class initialization failed");
/* Register the file creation class */
@@ -215,7 +246,7 @@ H5P_init_interface(void)
/* Allocate the file access class */
assert(H5P_CLS_FILE_ACCESS_g==(-1));
- if (NULL==(pclass = H5P_create_class (root_class,"file access",H5P_FILE_ACCESS_HASH_SIZE,1,H5F_acs_create,NULL,H5F_acs_copy,NULL,H5F_acs_close,NULL)))
+ if (NULL==(pclass = H5P_create_class (root_class,"file access",1,H5F_acs_create,NULL,H5F_acs_copy,NULL,H5F_acs_close,NULL)))
HGOTO_ERROR (H5E_PLIST, H5E_CANTINIT, FAIL, "class initialization failed");
/* Register the file access class */
@@ -226,7 +257,7 @@ H5P_init_interface(void)
/* Allocate the dataset creation class */
assert(H5P_CLS_DATASET_CREATE_g==(-1));
- if (NULL==(pclass = H5P_create_class (root_class,"dataset create",H5P_DATASET_CREATE_HASH_SIZE,1,NULL,NULL,H5D_crt_copy,NULL,H5D_crt_close,NULL)))
+ if (NULL==(pclass = H5P_create_class (root_class,"dataset create",1,NULL,NULL,H5D_crt_copy,NULL,H5D_crt_close,NULL)))
HGOTO_ERROR (H5E_PLIST, H5E_CANTINIT, FAIL, "class initialization failed");
/* Register the dataset creation class */
@@ -235,7 +266,7 @@ H5P_init_interface(void)
/* Allocate the data xfer class */
assert(H5P_CLS_DATASET_XFER_g==(-1));
- if (NULL==(pclass = H5P_create_class (root_class,"data xfer",H5P_DATASET_XFER_HASH_SIZE,1,H5D_xfer_create,NULL,H5D_xfer_copy,NULL,H5D_xfer_close,NULL)))
+ if (NULL==(pclass = H5P_create_class (root_class,"data xfer",1,H5D_xfer_create,NULL,H5D_xfer_copy,NULL,H5D_xfer_close,NULL)))
HGOTO_ERROR (H5E_PLIST, H5E_CANTINIT, FAIL, "class initialization failed");
/* Register the data xfer class */
@@ -244,7 +275,7 @@ H5P_init_interface(void)
/* Allocate the mount class */
assert(H5P_CLS_MOUNT_g==(-1));
- if (NULL==(pclass = H5P_create_class (root_class,"file mount",H5P_MOUNT_HASH_SIZE,1,NULL,NULL,NULL,NULL,NULL,NULL)))
+ if (NULL==(pclass = H5P_create_class (root_class,"file mount",1,NULL,NULL,NULL,NULL,NULL,NULL)))
HGOTO_ERROR (H5E_PLIST, H5E_CANTINIT, FAIL, "class initialization failed");
/* Register the mount class */
@@ -357,10 +388,8 @@ H5P_term_interface(void)
static H5P_genclass_t *
H5P_copy_pclass(H5P_genclass_t *pclass)
{
- H5P_genclass_t *new_pclass = NULL; /* Property list class copied */
- H5P_genprop_t *tmp; /* Temporary pointer to parent class properties */
- H5P_genprop_t *pcopy; /* Copy of property to insert into class */
- unsigned u; /* Local index variable */
+ H5P_genclass_t *new_pclass = NULL; /* Property list class copied */
+ H5P_genprop_t *pcopy; /* Copy of property to insert into class */
H5P_genclass_t *ret_value=NULL; /* return value */
FUNC_ENTER_NOINIT(H5P_copy_pclass);
@@ -372,32 +401,30 @@ H5P_copy_pclass(H5P_genclass_t *pclass)
*/
/* Create the new property list class */
- if (NULL==(new_pclass=H5P_create_class(pclass->parent, pclass->name, pclass->hashsize, 0, pclass->create_func, pclass->create_data, pclass->copy_func, pclass->copy_data, pclass->close_func, pclass->close_data)))
+ if (NULL==(new_pclass=H5P_create_class(pclass->parent, pclass->name, 0, pclass->create_func, pclass->create_data, pclass->copy_func, pclass->copy_data, pclass->close_func, pclass->close_data)))
HGOTO_ERROR(H5E_PLIST, H5E_CANTCREATE, NULL, "unable to create property list class");
/* Copy the properties registered for this class */
if(pclass->nprops>0) {
- /* Walk through the hash table */
- for(u=0; u<pclass->hashsize; u++) {
- tmp=pclass->props[u];
+ H5TB_NODE *curr_node; /* Current node in TBBT */
- /* Walk through the list of properties at each hash location */
- while(tmp!=NULL) {
- /* Make a copy of the class's property */
- if((pcopy=H5P_dup_prop(tmp))==NULL)
- HGOTO_ERROR (H5E_PLIST, H5E_CANTCOPY, NULL,"Can't copy property");
+ /* Walk through the properties in the old class */
+ curr_node=H5TB_first(pclass->props->root);
+ while(curr_node!=NULL) {
+ /* Make a copy of the class's property */
+ if((pcopy=H5P_dup_prop(curr_node->data,H5P_PROP_WITHIN_CLASS))==NULL)
+ HGOTO_ERROR (H5E_PLIST, H5E_CANTCOPY, NULL,"Can't copy property");
- /* Insert the initialized property into the property list */
- if(H5P_add_prop(new_pclass->props,new_pclass->hashsize,pcopy)<0)
- HGOTO_ERROR (H5E_PLIST, H5E_CANTINSERT, NULL,"Can't insert property into class");
+ /* Insert the initialized property into the property list */
+ if(H5P_add_prop(new_pclass->props,pcopy)<0)
+ HGOTO_ERROR (H5E_PLIST, H5E_CANTINSERT, NULL,"Can't insert property into class");
- /* Increment property count for class */
- new_pclass->nprops++;
+ /* Increment property count for class */
+ new_pclass->nprops++;
- /* Go to next registered property in class */
- tmp=tmp->next;
- } /* end while */
- } /* end for */
+ /* Get the next property node in the TBBT */
+ curr_node=H5TB_next(curr_node);
+ } /* end while */
} /* end if */
/* Set the return value */
@@ -432,13 +459,16 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-hid_t H5P_copy_plist(H5P_genplist_t *old_plist)
+hid_t
+H5P_copy_plist(H5P_genplist_t *old_plist)
{
+ H5P_genclass_t *tclass; /* Temporary class pointer */
H5P_genplist_t *new_plist=NULL; /* New property list generated from copy */
- H5P_genprop_t *tprop; /* Temporary pointer to properties */
+ H5P_genprop_t *tmp; /* Temporary pointer to properties */
H5P_genprop_t *new_prop; /* New property created for copy */
hid_t new_plist_id; /* Property list ID of new list created */
- unsigned u; /* Local index variable */
+ H5TB_NODE *curr_node; /* Current node in TBBT */
+ H5TB_TREE *seen=NULL; /* TBBT containing properties already seen */
hid_t ret_value=FAIL; /* return value */
FUNC_ENTER_NOAPI(H5P_copy_plist, FAIL);
@@ -449,8 +479,8 @@ hid_t H5P_copy_plist(H5P_genplist_t *old_plist)
* Create new property list object
*/
- /* Allocate room for the property list & it's hash table of properties */
- if (NULL==(new_plist = H5MM_calloc (sizeof(H5P_genplist_t)+((old_plist->pclass->hashsize-1)*sizeof(H5P_genprop_t *)))))
+ /* Allocate room for the property list */
+ if (NULL==(new_plist = H5FL_CALLOC(H5P_genplist_t)))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL,"memory allocation failed");
/* Set class state */
@@ -458,14 +488,54 @@ hid_t H5P_copy_plist(H5P_genplist_t *old_plist)
new_plist->nprops = 0; /* Initially the plist has the same number of properties as the class */
new_plist->class_init = 0; /* Initially, wait until the class callback finishes to set */
+ /* Initialize the TBBT to hold the changed properties */
+ if((new_plist->props=H5TB_fast_dmake(H5TB_FAST_STR_COMPARE))==NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_CANTMAKETREE,FAIL,"can't create TBBT for changed properties");
+
+ /* Create the TBBT for deleted properties */
+ if((new_plist->del=H5TB_fast_dmake(H5TB_FAST_STR_COMPARE))==NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_CANTMAKETREE,NULL,"can't create TBBT for deleted properties");
+
+ /* Create the TBBT to hold names of properties already seen
+ * (This prevents a property in the class hierarchy from having it's
+ * 'create' callback called, if a property in the class hierarchy has
+ * already been seen)
+ */
+ if((seen=H5TB_fast_dmake(H5TB_FAST_STR_COMPARE))==NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_CANTMAKETREE,NULL,"can't create TBBT for seen properties");
+
+ /* Cycle through the deleted properties & copy them into the new list's deleted section */
+ if(old_plist->del->root) {
+ curr_node=H5TB_first(old_plist->del->root);
+ while(curr_node) {
+ char *new_name; /* Pointer to new name */
+
+ /* Duplicate string for insertion into new deleted property TBBT */
+ if((new_name=H5MM_xstrdup(curr_node->data))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE,H5E_NOSPACE,FAIL,"memory allocation failed");
+
+ /* Insert property name into deleted list */
+ if(H5TB_dins(new_plist->del,new_name,new_name)==NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_CANTINSERT,NULL,"can't insert property into deleted TBBT");
+
+ /* Add property name to "seen" list */
+ if(H5TB_dins(seen,new_name,new_name)==NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_CANTINSERT,NULL,"can't insert property into seen TBBT");
+
+ /* Get the next property node in the TBBT */
+ curr_node=H5TB_next(curr_node);
+ } /* end while */
+ } /* end if */
+
/* Cycle through the properties and copy them also */
- for(u=0; u<old_plist->pclass->hashsize; u++) {
- tprop=old_plist->props[u];
+ if(old_plist->props->root) {
+ curr_node=H5TB_first(old_plist->props->root);
+ while(curr_node) {
+ /* Get a pointer to the node's property */
+ tmp=curr_node->data;
- /* Walk through the list of properties at each hash location */
- while(tprop!=NULL) {
/* Make a copy of the list's property */
- if((new_prop=H5P_dup_prop(tprop))==NULL)
+ if((new_prop=H5P_dup_prop(tmp,H5P_PROP_WITHIN_LIST))==NULL)
HGOTO_ERROR (H5E_PLIST, H5E_CANTCOPY, FAIL,"Can't copy property");
/* Call property copy callback, if it exists */
@@ -477,16 +547,61 @@ hid_t H5P_copy_plist(H5P_genplist_t *old_plist)
} /* end if */
/* Insert the initialized property into the property list */
- if(H5P_add_prop(new_plist->props,new_plist->pclass->hashsize,new_prop)<0)
+ if(H5P_add_prop(new_plist->props,new_prop)<0) {
+ H5P_free_prop(new_prop);
HGOTO_ERROR (H5E_PLIST, H5E_CANTINSERT, FAIL,"Can't insert property into list");
+ } /* end if */
+
+ /* Add property name to "seen" list */
+ if(H5TB_dins(seen,new_prop->name,new_prop->name)==NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_CANTINSERT,NULL,"can't insert property into seen TBBT");
/* Increment the number of properties in list */
new_plist->nprops++;
- /* Go to next registered property in class */
- tprop=tprop->next;
+ /* Get the next property node in the TBBT */
+ curr_node=H5TB_next(curr_node);
} /* end while */
- } /* end for */
+ } /* end if */
+
+ /*
+ * Check for copying class properties (up through list of parent classes also),
+ * initialize each with default value & make property 'copy' callback.
+ */
+ tclass=old_plist->pclass;
+ while(tclass!=NULL) {
+ if(tclass->nprops>0) {
+ /* Walk through the properties in the old class */
+ curr_node=H5TB_first(tclass->props->root);
+ while(curr_node!=NULL) {
+ /* Get pointer to property from node */
+ tmp=curr_node->data;
+
+ /* Only "copy" properties we haven't seen before */
+ if(H5TB_dfind(seen,tmp->name,NULL)==NULL) {
+ /* Call property creation callback, if it exists */
+ if(tmp->copy) {
+ /* Call the callback & insert changed value into tree (if necessary) */
+ if(H5P_do_prop_cb1(new_plist->props,tmp,tmp->copy)<0)
+ HGOTO_ERROR (H5E_PLIST, H5E_CANTCOPY, NULL,"Can't create property");
+ } /* end if */
+
+ /* Add property name to "seen" list */
+ if(H5TB_dins(seen,tmp->name,tmp->name)==NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_CANTINSERT,NULL,"can't insert property into seen TBBT");
+
+ /* Increment the number of properties in list */
+ new_plist->nprops++;
+ } /* end if */
+
+ /* Get the next property node in the TBBT */
+ curr_node=H5TB_next(curr_node);
+ } /* end while */
+ } /* end if */
+
+ /* Go up to parent class */
+ tclass=tclass->parent;
+ } /* end while */
/* Increment the number of property lists derived from class */
if(H5P_access_class(new_plist->pclass,H5P_MOD_INC_LST)<0)
@@ -515,6 +630,10 @@ hid_t H5P_copy_plist(H5P_genplist_t *old_plist)
ret_value=new_plist_id;
done:
+ /* Release the tree of 'seen' properties */
+ if(seen!=NULL)
+ H5TB_dfree(seen,NULL,NULL);
+
if (ret_value<0 && new_plist)
H5P_close(new_plist);
@@ -543,7 +662,8 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-hid_t H5Pcopy(hid_t id)
+hid_t
+H5Pcopy(hid_t id)
{
void *obj; /* Property object to copy */
hid_t ret_value=FALSE; /* return value */
@@ -592,6 +712,7 @@ done:
USAGE
H5P_genprop_t *H5P_dup_prop(oprop)
H5P_genprop_t *oprop; IN: Pointer to property to copy
+ H5P_prop_within_t type; IN: Type of object the property will be inserted into
RETURNS
Returns a pointer to the newly created duplicate of a property on success,
NULL on failure.
@@ -603,7 +724,7 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
static H5P_genprop_t *
-H5P_dup_prop(H5P_genprop_t *oprop)
+H5P_dup_prop(H5P_genprop_t *oprop, H5P_prop_within_t type)
{
H5P_genprop_t *prop=NULL; /* Pointer to new property copied */
H5P_genprop_t *ret_value; /* Return value */
@@ -611,16 +732,47 @@ H5P_dup_prop(H5P_genprop_t *oprop)
FUNC_ENTER_NOINIT(H5P_dup_prop);
assert(oprop);
+ assert(type!=H5P_PROP_WITHIN_UNKNOWN);
/* Allocate the new property */
- if (NULL==(prop = H5MM_malloc (sizeof(H5P_genprop_t))))
+ if (NULL==(prop = H5FL_MALLOC (H5P_genprop_t)))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
/* Copy basic property information */
HDmemcpy(prop,oprop,sizeof(H5P_genprop_t));
- /* Duplicate name */
- prop->name = H5MM_xstrdup(oprop->name);
+ /* Check if we should duplicate the name or share it */
+
+ /* Duplicating property for a class */
+ if(type==H5P_PROP_WITHIN_CLASS) {
+ assert(oprop->type==H5P_PROP_WITHIN_CLASS);
+ assert(oprop->shared_name==0);
+
+ /* Duplicate name */
+ prop->name = H5MM_xstrdup(oprop->name);
+ } /* end if */
+ /* Duplicating property for a list */
+ else {
+ /* Check if we are duplicating a property from a list or a class */
+
+ /* Duplicating a property from a list */
+ if(oprop->type==H5P_PROP_WITHIN_LIST) {
+ /* If the old property's name wasn't shared, we have to copy it here also */
+ if(!oprop->shared_name)
+ prop->name = H5MM_xstrdup(oprop->name);
+ } /* end if */
+ /* Duplicating a property from a class */
+ else {
+ assert(oprop->type==H5P_PROP_WITHIN_CLASS);
+ assert(oprop->shared_name==0);
+
+ /* Share the name */
+ prop->shared_name=1;
+
+ /* Set the type */
+ prop->type=type;
+ } /* end else */
+ } /* end else */
/* Duplicate current value, if it exists */
if(oprop->value!=NULL) {
@@ -630,17 +782,6 @@ H5P_dup_prop(H5P_genprop_t *oprop)
HDmemcpy(prop->value,oprop->value,prop->size);
} /* end if */
- /* Duplicate default value, if it exists */
- if(oprop->def_value!=NULL) {
- assert(prop->size>0);
- if (NULL==(prop->def_value = H5MM_malloc (prop->size)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
- HDmemcpy(prop->def_value,oprop->def_value,prop->size);
- } /* end if */
-
- /* Reset the link to the next property */
- prop->next=NULL;
-
/* Set return value */
ret_value=prop;
@@ -652,9 +793,7 @@ done:
H5MM_xfree(prop->name);
if(prop->value!=NULL)
H5MM_xfree(prop->value);
- if(prop->def_value!=NULL)
- H5MM_xfree(prop->def_value);
- H5MM_xfree(prop);
+ H5FL_FREE(H5P_genprop_t,prop);
} /* end if */
} /* end if */
@@ -668,12 +807,12 @@ done:
PURPOSE
Internal routine to create a new property
USAGE
- H5P_genprop_t *H5P_create_prop(name,size,def_value,prp_create,prp_set,
+ H5P_genprop_t *H5P_create_prop(name,size,type,value,prp_create,prp_set,
prp_get,prp_delete,prp_close)
const char *name; IN: Name of property to register
size_t size; IN: Size of property in bytes
- void *def_value; IN: Pointer to buffer containing default value
- for property in newly created property lists
+ H5P_prop_within_t type; IN: Type of object the property will be inserted into
+ void *value; IN: Pointer to buffer containing value for property
H5P_prp_create_func_t prp_create; IN: Function pointer to property
creation callback
H5P_prp_set_func_t prp_set; IN: Function pointer to property set callback
@@ -693,7 +832,8 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
static H5P_genprop_t *
-H5P_create_prop(const char *name, size_t size, void *def_value, void *value,
+H5P_create_prop(const char *name, size_t size, H5P_prop_within_t type,
+ void *value,
H5P_prp_create_func_t prp_create, H5P_prp_set_func_t prp_set,
H5P_prp_get_func_t prp_get, H5P_prp_delete_func_t prp_delete,
H5P_prp_copy_func_t prp_copy, H5P_prp_close_func_t prp_close)
@@ -704,16 +844,18 @@ H5P_create_prop(const char *name, size_t size, void *def_value, void *value,
FUNC_ENTER_NOINIT(H5P_create_prop);
assert(name);
- assert((size>0 && (def_value!=NULL || value!=NULL)) || (size==0));
+ assert((size>0 && value!=NULL) || (size==0));
+ assert(type!=H5P_PROP_WITHIN_UNKNOWN);
/* Allocate the new property */
- if (NULL==(prop = H5MM_malloc (sizeof(H5P_genprop_t))))
+ if (NULL==(prop = H5FL_MALLOC (H5P_genprop_t)))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
/* Set the property initial values */
- prop->xor_val = H5P_xor_name(name); /* Generate the XOR'd value for the name */
prop->name = H5MM_xstrdup(name); /* Duplicate name */
+ prop->shared_name=0;
prop->size=size;
+ prop->type=type;
/* Duplicate value, if it exists */
if(value!=NULL) {
@@ -724,15 +866,6 @@ H5P_create_prop(const char *name, size_t size, void *def_value, void *value,
else
prop->value=NULL;
- /* Duplicate default value, if it exists */
- if(def_value!=NULL) {
- if (NULL==(prop->def_value = H5MM_malloc (prop->size)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
- HDmemcpy(prop->def_value,def_value,prop->size);
- } /* end if */
- else
- prop->def_value=NULL;
-
/* Set the function pointers */
prop->create=prp_create;
prop->set=prp_set;
@@ -741,9 +874,6 @@ H5P_create_prop(const char *name, size_t size, void *def_value, void *value,
prop->copy=prp_copy;
prop->close=prp_close;
- /* Reset the link to the next property */
- prop->next=NULL;
-
/* Set return value */
ret_value=prop;
@@ -755,9 +885,7 @@ done:
H5MM_xfree(prop->name);
if(prop->value!=NULL)
H5MM_xfree(prop->value);
- if(prop->def_value!=NULL)
- H5MM_xfree(prop->def_value);
- H5MM_xfree(prop);
+ H5FL_FREE(H5P_genprop_t,prop);
} /* end if */
} /* end if */
@@ -769,95 +897,142 @@ done:
NAME
H5P_add_prop
PURPOSE
- Internal routine to insert a property into a property hash table
+ Internal routine to insert a property into a property TBBT
USAGE
- herr_t H5P_add_prop(hash, hashsize, prop)
- H5P_gen_prop_t *hash[]; IN/OUT: Pointer to array of properties for hash table
- unsigned hashsize; IN: Size of hash table
+ herr_t H5P_add_prop(tree, prop)
+ H5TB_TREE *tree; IN/OUT: Pointer to TBBT of properties
H5P_genprop_t *prop; IN: Pointer to property to insert
RETURNS
Returns non-negative on success, negative on failure.
DESCRIPTION
- Inserts a property into a hash table of properties, using the hashed
- property name.
+ Inserts a property into a TBBT of properties.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
herr_t
-H5P_add_prop(H5P_genprop_t *hash[], unsigned hashsize, H5P_genprop_t *prop)
+H5P_add_prop(H5TB_TREE *tree, H5P_genprop_t *prop)
{
- unsigned loc; /* Hash table location */
+ herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOINIT(H5P_add_prop);
+ FUNC_ENTER_NOAPI(H5P_add_prop,FAIL);
- assert(hash);
- assert(hashsize>0);
+ assert(tree);
assert(prop);
+ assert(prop->type!=H5P_PROP_WITHIN_UNKNOWN);
- /* Get correct hash table location */
- loc=H5P_hash_name(prop->name,hashsize);
-
- /* Insert property into hash table */
- prop->next=hash[loc];
- hash[loc]=prop;
+ /* Insert property into TBBT */
+ if(H5TB_dins(tree,prop,prop->name)==NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_CANTINSERT,FAIL,"can't insert property into TBBT");
- FUNC_LEAVE (SUCCEED);
+done:
+ FUNC_LEAVE(ret_value);
} /* H5P_add_prop() */
/*--------------------------------------------------------------------------
NAME
- H5P_find_prop
+ H5P_find_prop_plist
PURPOSE
- Internal routine to check for a property in a hash table
+ Internal routine to check for a property in a property list's TBBT
USAGE
- H5P_genprop_t *H5P_find_prop(hash, hashsize, name)
- H5P_genprop_t *hash[]; IN: Pointer to array of properties for hash table
- unsigned hashsize; IN: Size of hash table
+ H5P_genprop_t *H5P_find_prop(plist, name)
+ H5P_genplist_t *plist; IN: Pointer to property list to check
const char *name; IN: Name of property to check for
RETURNS
Returns pointer to property on success, NULL on failure.
DESCRIPTION
- Checks for a property in a hash table of properties.
+ Checks for a property in a property list's TBBT of properties.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
static H5P_genprop_t *
-H5P_find_prop(H5P_genprop_t *hash[], unsigned hashsize, const char *name)
+H5P_find_prop_plist(H5P_genplist_t *plist, const char *name)
{
+ H5TB_NODE *prop_node; /* TBBT node holding property */
H5P_genprop_t *ret_value; /* Property pointer return value */
- unsigned loc; /* Hash table location */
- unsigned xor_val; /* XOR'ed value of the name to look for */
- FUNC_ENTER_NOINIT(H5P_find_prop);
+ FUNC_ENTER_NOINIT(H5P_find_prop_plist);
- assert(hash);
- assert(hashsize>0);
+ assert(plist);
assert(name);
- /* Get correct hash table location */
- loc=H5P_hash_name(name,hashsize);
-
- /* Get the XOR'ed value for the name to search for, to speed up comparisons */
- xor_val=H5P_xor_name(name);
-
- /* Locate property in list */
- ret_value=hash[loc];
- while(ret_value!=NULL) {
- /* Check for name matching */
- if(ret_value->xor_val==xor_val && HDstrcmp(ret_value->name,name)==0)
- break;
-
- /* Advance to the next property */
- ret_value=ret_value->next;
- } /* end while */
+ /* Check if the property has been deleted from list */
+ if(H5TB_dfind(plist->del,name,NULL)!=NULL) {
+ HGOTO_ERROR(H5E_PLIST,H5E_NOTFOUND,NULL,"can't find property in TBBT");
+ } /* end if */
+ else {
+ /* Get the property node from the TBBT */
+ if((prop_node=H5TB_dfind(plist->props,name,NULL))!=NULL) {
+ /* Get the property from the node */
+ ret_value=prop_node->data;
+ } /* end if */
+ else {
+ H5P_genclass_t *tclass; /* Temporary class pointer */
+
+ tclass=plist->pclass;
+ while(tclass!=NULL) {
+ /* Find the property in the class */
+ if((prop_node=H5TB_dfind(tclass->props,name,NULL))!=NULL)
+ /* Get pointer to actual property & leave */
+ HGOTO_DONE(prop_node->data);
+
+ /* Go up to parent class */
+ tclass=tclass->parent;
+ } /* end while */
+
+ /* If we've gotten this far, we haven't found the property */
+ HGOTO_ERROR(H5E_PLIST,H5E_NOTFOUND,NULL,"can't find property in TBBT");
+ } /* end else */
+ } /* end else */
+
+done:
+ FUNC_LEAVE (ret_value);
+} /* H5P_find_prop_plist() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5P_find_prop_pclass
+ PURPOSE
+ Internal routine to check for a property in a class TBBT
+ USAGE
+ H5P_genprop_t *H5P_find_prop_class(tree, name)
+ H5P_genclass *pclass; IN: Pointer generic property class to check
+ const char *name; IN: Name of property to check for
+ RETURNS
+ Returns pointer to property on success, NULL on failure.
+ DESCRIPTION
+ Checks for a property in a class' TBBT of properties.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static H5P_genprop_t *
+H5P_find_prop_pclass(H5P_genclass_t *pclass, const char *name)
+{
+ H5TB_NODE *prop_node; /* TBBT node holding property */
+ H5P_genprop_t *ret_value; /* Property pointer return value */
+
+ FUNC_ENTER_NOINIT(H5P_find_prop_pclass);
+
+ assert(pclass);
+ assert(name);
+
+ /* Get the property node from the TBBT */
+ if((prop_node=H5TB_dfind(pclass->props,name,NULL))==NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_NOTFOUND,NULL,"can't find property in TBBT");
+
+ /* Get the property from the node */
+ ret_value=prop_node->data;
+done:
FUNC_LEAVE (ret_value);
-} /* H5P_find_prop() */
+} /* H5P_find_prop_pclass() */
/*--------------------------------------------------------------------------
@@ -885,15 +1060,15 @@ H5P_free_prop(H5P_genprop_t *prop)
assert(prop);
- /* Release the property value and default value if they exist */
- if(prop->size>0) {
- if(prop->value)
- H5MM_xfree(prop->value);
- if(prop->def_value)
- H5MM_xfree(prop->def_value);
- } /* end if */
- H5MM_xfree(prop->name);
- H5MM_xfree(prop);
+ /* Release the property value if it exists */
+ if(prop->value)
+ H5MM_xfree(prop->value);
+
+ /* Only free the name if we own it */
+ if(prop->shared_name==0)
+ H5MM_xfree(prop->name);
+
+ H5FL_FREE(H5P_genprop_t,prop);
FUNC_LEAVE (SUCCEED);
} /* H5P_free_prop() */
@@ -903,11 +1078,10 @@ H5P_free_prop(H5P_genprop_t *prop)
NAME
H5P_free_all_prop
PURPOSE
- Internal routine to remove all properties from a property hash table
+ Internal routine to remove all properties from a property TBBT
USAGE
- herr_t H5P_free_all_prop(hash, hashsize, make_cb)
- H5P_gen_prop_t *hash[]; IN/OUT: Pointer to array of properties for hash table
- unsigned hashsize; IN: Size of hash table
+ herr_t H5P_free_all_prop(tree, make_cb)
+ H5TB_TREE *tree; IN/OUT: Pointer to property TBBT
unsigned make_cb; IN: Whether to make property callbacks or not
RETURNS
Returns non-negative on success, negative on failure.
@@ -920,35 +1094,39 @@ H5P_free_prop(H5P_genprop_t *prop)
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5P_free_all_prop(H5P_genprop_t *hash[], unsigned hashsize, unsigned make_cb)
+H5P_free_all_prop(H5TB_TREE *tree,unsigned make_cb)
{
- H5P_genprop_t *tprop, *next;/* Temporary pointer to properties */
- unsigned u; /* Local index variable */
+ H5P_genprop_t *tprop; /* Temporary pointer to properties */
+ H5TB_NODE *curr_node, *next_node; /* Current & next nodes in TBBT */
+ herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOINIT(H5P_free_all_prop);
- assert(hash);
- assert(hashsize>0);
+ assert(tree);
/* Work through all the properties... */
- for(u=0; u<hashsize; u++) {
- tprop=hash[u];
- while(tprop!=NULL) {
- /* Find next node right away, to avoid accessing the current node after it's been free'd */
- next=tprop->next;
+ curr_node=H5TB_first(tree->root);
+ while(curr_node!=NULL) {
+ /* Get the next node in the TBBT */
+ next_node=H5TB_next(curr_node);
- /* Call the close callback and ignore the return value, there's nothing we can do about it */
- if(make_cb && tprop->close!=NULL)
- (tprop->close)(tprop->name,tprop->size,tprop->value);
+ /* Remove the node from the TBBT */
+ if((tprop=H5TB_rem(&tree->root,curr_node,NULL))==NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_CANTDELETE,FAIL,"can't remove property from TBBT");
- /* Free the property, ignoring return value, nothing we can do */
- H5P_free_prop(tprop);
+ /* Call the close callback and ignore the return value, there's nothing we can do about it */
+ if(make_cb && tprop->close!=NULL)
+ (tprop->close)(tprop->name,tprop->size,tprop->value);
- tprop=next;
- } /* end while */
- } /* end for */
+ /* Free the property, ignoring return value, nothing we can do */
+ H5P_free_prop(tprop);
- FUNC_LEAVE (SUCCEED);
+ /* Advance to the next property node in the TBBT */
+ curr_node=next_node;
+ } /* end while */
+
+done:
+ FUNC_LEAVE (ret_value);
} /* H5P_free_all_prop() */
@@ -1027,9 +1205,13 @@ H5P_access_class(H5P_genclass_t *pclass, H5P_class_mod_t mod)
H5MM_xfree(pclass->name);
/* Free the class properties without making callbacks */
- H5P_free_all_prop(pclass->props,pclass->hashsize,0);
+ if(pclass->nprops>0)
+ H5P_free_all_prop(pclass->props,0);
- H5MM_xfree(pclass);
+ /* Free the property tree itself */
+ H5TB_dfree(pclass->props,NULL,NULL);
+
+ H5FL_FREE(H5P_genclass_t,pclass);
/* Reduce the number of dependent classes on parent class also */
if(par_class!=NULL)
@@ -1091,11 +1273,10 @@ H5P_check_class(void *_obj, hid_t id, const void *_key)
PURPOSE
Internal routine to create a new property list class.
USAGE
- H5P_genclass_t H5P_create_class(par_class, name, hashsize, internal,
+ H5P_genclass_t H5P_create_class(par_class, name, internal,
cls_create, create_data, cls_close, close_data)
H5P_genclass_t *par_class; IN: Pointer to parent class
const char *name; IN: Name of class we are creating
- unsigned hashsize; IN: Number of buckets in hash table
unsigned internal; IN: Whether this is an internal class or not
H5P_cls_create_func_t; IN: The callback function to call when each
property list in this class is created.
@@ -1120,7 +1301,7 @@ H5P_check_class(void *_obj, hid_t id, const void *_key)
REVISION LOG
--------------------------------------------------------------------------*/
static H5P_genclass_t *
-H5P_create_class(H5P_genclass_t *par_class, const char *name, unsigned hashsize, unsigned internal,
+H5P_create_class(H5P_genclass_t *par_class, const char *name, unsigned internal,
H5P_cls_create_func_t cls_create, void *create_data,
H5P_cls_copy_func_t cls_copy, void *copy_data,
H5P_cls_close_func_t cls_close, void *close_data
@@ -1136,23 +1317,26 @@ H5P_create_class(H5P_genclass_t *par_class, const char *name, unsigned hashsize,
/* (This allows the root of the tree to be created with this routine -QAK) */
if(!internal) {
assert(par_class);
- assert(hashsize>0);
}
- /* Allocate room for the class & it's hash table of properties */
- if (NULL==(pclass = H5MM_calloc (sizeof(H5P_genclass_t)+((hashsize-1)*sizeof(H5P_genprop_t *)))))
+ /* Allocate room for the class */
+ if (NULL==(pclass = H5FL_CALLOC(H5P_genclass_t)))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL,"memory allocation failed");
/* Set class state */
pclass->parent = par_class;
pclass->name = H5MM_xstrdup(name);
pclass->nprops = 0; /* Classes are created without properties initially */
- pclass->hashsize = hashsize;
pclass->plists = 0; /* No properties lists of this class yet */
pclass->classes = 0; /* No classes derived from this class yet */
pclass->ref_count = 1; /* This is the first reference to the new class */
pclass->internal = internal;
pclass->deleted = 0; /* Not deleted yet... :-) */
+ pclass->revision = H5P_GET_NEXT_REV; /* Get a revision number for the class */
+
+ /* Create the TBBT for properties */
+ if((pclass->props=H5TB_fast_dmake(H5TB_FAST_STR_COMPARE))==NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_CANTMAKETREE,NULL,"can't create TBBT for properties");
/* Set callback functions and pass-along data */
pclass->create_func = cls_create;
@@ -1175,7 +1359,7 @@ done:
/* Free any resources allocated */
if(ret_value==NULL) {
if(pclass!=NULL)
- H5MM_xfree(pclass);
+ H5FL_FREE(H5P_genclass_t,pclass);
}
FUNC_LEAVE (ret_value);
@@ -1188,11 +1372,10 @@ done:
PURPOSE
Create a new property list class.
USAGE
- hid_t H5Pcreate_class(parent, name, hashsize, cls_create, create_data,
+ hid_t H5Pcreate_class(parent, name, cls_create, create_data,
cls_close, close_data)
hid_t parent; IN: Property list class ID of parent class
const char *name; IN: Name of class we are creating
- unsigned hashsize; IN: Number of buckets in hash table
H5P_cls_create_func_t cls_create; IN: The callback function to call
when each property list in this class is
created.
@@ -1218,7 +1401,7 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
hid_t
-H5Pcreate_class(hid_t parent, const char *name, unsigned hashsize,
+H5Pcreate_class(hid_t parent, const char *name,
H5P_cls_create_func_t cls_create, void *create_data,
H5P_cls_copy_func_t cls_copy, void *copy_data,
H5P_cls_close_func_t cls_close, void *close_data
@@ -1229,7 +1412,7 @@ H5Pcreate_class(hid_t parent, const char *name, unsigned hashsize,
hid_t ret_value; /* Return value */
FUNC_ENTER_API(H5Pcreate_class, FAIL);
- H5TRACE9("i","isIuxxxxxx",parent,name,hashsize,cls_create,create_data,
+ H5TRACE8("i","isxxxxxx",parent,name,cls_create,create_data,
cls_copy,copy_data,cls_close,close_data);
/* Check arguments. */
@@ -1237,8 +1420,6 @@ H5Pcreate_class(hid_t parent, const char *name, unsigned hashsize,
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list class");
if (!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid class name");
- if (hashsize==0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "hashsize too small");
if ((create_data!=NULL && cls_create==NULL)
|| (copy_data!=NULL && cls_copy==NULL)
|| (close_data!=NULL && cls_close==NULL))
@@ -1251,7 +1432,7 @@ H5Pcreate_class(hid_t parent, const char *name, unsigned hashsize,
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't retrieve parent class");
/* Create the new property list class */
- if (NULL==(pclass=H5P_create_class(par_class, name, hashsize, 0, cls_create, create_data, cls_copy, copy_data, cls_close, close_data)))
+ if (NULL==(pclass=H5P_create_class(par_class, name, 0, cls_create, create_data, cls_copy, copy_data, cls_close, close_data)))
HGOTO_ERROR(H5E_PLIST, H5E_CANTCREATE, FAIL, "unable to create property list class");
/* Get an atom for the class */
@@ -1291,14 +1472,14 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-static H5P_genplist_t *H5P_create(H5P_genclass_t *pclass)
+static H5P_genplist_t *
+H5P_create(H5P_genclass_t *pclass)
{
- H5P_genclass_t *tclass=NULL; /* Temporary class pointer */
- H5P_genplist_t *plist=NULL; /* New property list created */
- H5P_genplist_t *ret_value; /* return value */
- H5P_genprop_t *tmp; /* Temporary pointer to parent class properties */
- H5P_genprop_t *pcopy; /* Copy of property to insert into class */
- unsigned u; /* Local index variable */
+ H5P_genclass_t *tclass; /* Temporary class pointer */
+ H5P_genplist_t *plist=NULL; /* New property list created */
+ H5P_genprop_t *tmp; /* Temporary pointer to parent class properties */
+ H5TB_TREE *seen=NULL; /* TBBT to hold names of properties already seen */
+ H5P_genplist_t *ret_value; /* Return value */
FUNC_ENTER_NOINIT(H5P_create);
@@ -1308,8 +1489,8 @@ static H5P_genplist_t *H5P_create(H5P_genclass_t *pclass)
* Create new property list object
*/
- /* Allocate room for the property list & it's hash table of properties */
- if (NULL==(plist = H5MM_calloc (sizeof(H5P_genplist_t)+((pclass->hashsize-1)*sizeof(H5P_genprop_t *)))))
+ /* Allocate room for the property list */
+ if (NULL==(plist = H5FL_CALLOC(H5P_genplist_t)))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL,"memory allocation failed");
/* Set class state */
@@ -1317,57 +1498,57 @@ static H5P_genplist_t *H5P_create(H5P_genclass_t *pclass)
plist->nprops = 0; /* Initially the plist has the same number of properties as the class */
plist->class_init = 0; /* Initially, wait until the class callback finishes to set */
+ /* Create the TBBT for changed properties */
+ if((plist->props=H5TB_fast_dmake(H5TB_FAST_STR_COMPARE))==NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_CANTMAKETREE,NULL,"can't create TBBT for changed properties");
+
+ /* Create the TBBT for deleted properties */
+ if((plist->del=H5TB_fast_dmake(H5TB_FAST_STR_COMPARE))==NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_CANTMAKETREE,NULL,"can't create TBBT for deleted properties");
+
+ /* Create the TBBT to hold names of properties already seen
+ * (This prevents a property in the class hierarchy from having it's
+ * 'create' callback called, if a property in the class hierarchy has
+ * already been seen)
+ */
+ if((seen=H5TB_fast_dmake(H5TB_FAST_STR_COMPARE))==NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_CANTMAKETREE,NULL,"can't create TBBT for seen properties");
+
/*
- * Copy class properties (up through list of parent classes also),
+ * Check if we should copy class properties (up through list of parent classes also),
* initialize each with default value & make property 'create' callback.
*/
tclass=pclass;
while(tclass!=NULL) {
if(tclass->nprops>0) {
- /* Walk through the hash table */
- for(u=0; u<tclass->hashsize; u++) {
- tmp=tclass->props[u];
- /* Walk through the list of properties at each hash location */
- while(tmp!=NULL) {
- /* Check for property already existing in list */
- if(H5P_find_prop(plist->props,pclass->hashsize,tmp->name)==NULL) {
- /* Make a copy of the class's property */
- if((pcopy=H5P_dup_prop(tmp))==NULL)
- HGOTO_ERROR (H5E_PLIST, H5E_CANTCOPY, NULL,"Can't copy property");
-
- /* Create initial value from default value for non-zero sized properties */
- if(pcopy->size>0) {
- /* Properties from the class should have any values yet, but should have a default */
- assert(pcopy->value==NULL);
- assert(pcopy->def_value);
-
- /* Allocate space for the property value & copy default value */
- if (NULL==(pcopy->value = H5MM_malloc (pcopy->size)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
-
- HDmemcpy(pcopy->value,pcopy->def_value,pcopy->size);
- } /* end if */
-
- /* Call property creation callback, if it exists */
- if(pcopy->create) {
- if((pcopy->create)(pcopy->name,pcopy->size,pcopy->value)<0) {
- H5P_free_prop(pcopy);
- HGOTO_ERROR (H5E_PLIST, H5E_CANTINIT, NULL,"Can't initialize property");
- } /* end if */
- } /* end if */
+ H5TB_NODE *curr_node; /* Current node in TBBT */
+
+ /* Walk through the properties in the old class */
+ curr_node=H5TB_first(tclass->props->root);
+ while(curr_node!=NULL) {
+ /* Get pointer to property from node */
+ tmp=curr_node->data;
+
+ /* Only "create" properties we haven't seen before */
+ if(H5TB_dfind(seen,tmp->name,NULL)==NULL) {
+ /* Call property creation callback, if it exists */
+ if(tmp->create) {
+ /* Call the callback & insert changed value into tree (if necessary) */
+ if(H5P_do_prop_cb1(plist->props,tmp,tmp->create)<0)
+ HGOTO_ERROR (H5E_PLIST, H5E_CANTCOPY, NULL,"Can't create property");
+ } /* end if */
- /* Insert the initialized property into the property list */
- if(H5P_add_prop(plist->props,pclass->hashsize,pcopy)<0)
- HGOTO_ERROR (H5E_PLIST, H5E_CANTINSERT, NULL,"Can't insert property into class");
+ /* Add property name to "seen" list */
+ if(H5TB_dins(seen,tmp->name,tmp->name)==NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_CANTINSERT,NULL,"can't insert property into seen TBBT");
- /* Increment the number of properties in list */
- plist->nprops++;
- } /* end if */
+ /* Increment the number of properties in list */
+ plist->nprops++;
+ } /* end if */
- /* Go to next registered property in class */
- tmp=tmp->next;
- } /* end while */
- } /* end for */
+ /* Get the next property node in the TBBT */
+ curr_node=H5TB_next(curr_node);
+ } /* end while */
} /* end if */
/* Go up to parent class */
@@ -1382,14 +1563,25 @@ static H5P_genplist_t *H5P_create(H5P_genclass_t *pclass)
ret_value=plist;
done:
+ /* Release the tree of 'seen' properties */
+ if(seen!=NULL)
+ H5TB_dfree(seen,NULL,NULL);
+
/* Release resources allocated on failure */
if(ret_value==NULL) {
if(plist!=NULL) {
- /* Close & free all the properties */
- H5P_free_all_prop(plist->props,pclass->hashsize,1);
+ /* Close & free any changed properties */
+ if(plist->props) {
+ H5P_free_all_prop(plist->props,1);
+ H5TB_dfree(plist->props,NULL,NULL);
+ } /* end if */
- /* Decrement the number of property lists derived from the class */
- pclass->plists--;
+ /* Release the deleted property TBBT */
+ if(plist->del)
+ H5TB_dfree(plist->del,NULL,NULL);
+
+ /* Release the property list itself */
+ H5FL_FREE(H5P_genplist_t,plist);
} /* end if */
} /* end if */
@@ -1419,7 +1611,8 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-hid_t H5P_create_id(H5P_genclass_t *pclass)
+hid_t
+H5P_create_id(H5P_genclass_t *pclass)
{
H5P_genplist_t *plist=NULL; /* Property list created */
hid_t plist_id=FAIL; /* Property list ID */
@@ -1485,7 +1678,8 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-hid_t H5Pcreate(hid_t cls_id)
+hid_t
+H5Pcreate(hid_t cls_id)
{
H5P_genclass_t *pclass; /* Property list class to modify */
hid_t ret_value; /* return value */
@@ -1636,16 +1830,15 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-herr_t H5P_register(H5P_genclass_t *pclass, const char *name, size_t size,
+herr_t
+H5P_register(H5P_genclass_t *pclass, const char *name, size_t size,
void *def_value, H5P_prp_create_func_t prp_create, H5P_prp_set_func_t prp_set,
H5P_prp_get_func_t prp_get, H5P_prp_delete_func_t prp_delete,
H5P_prp_copy_func_t prp_copy, H5P_prp_close_func_t prp_close)
{
H5P_genclass_t *new_class; /* New class pointer */
- H5P_genprop_t *tmp_prop; /* Temporary property pointer */
H5P_genprop_t *new_prop=NULL; /* Temporary property pointer */
H5P_genprop_t *pcopy; /* Property copy */
- unsigned u; /* Local index variable */
herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5P_register, FAIL);
@@ -1655,51 +1848,60 @@ herr_t H5P_register(H5P_genclass_t *pclass, const char *name, size_t size,
assert((size>0 && def_value!=NULL) || (size==0));
/* Check for duplicate named properties */
- if((tmp_prop=H5P_find_prop(pclass->props,pclass->hashsize,name))!=NULL)
+ if(H5TB_dfind(pclass->props,name,NULL)!=NULL)
HGOTO_ERROR(H5E_PLIST, H5E_EXISTS, FAIL, "property already exists");
/* Check if class needs to be split because property lists or classes have
* been created since the last modification was made to the class.
*/
if(pclass->plists>0 || pclass->classes>0) {
- if((new_class=H5P_create_class(pclass->parent,pclass->name,pclass->hashsize,
+ if((new_class=H5P_create_class(pclass->parent,pclass->name,
pclass->internal,pclass->create_func,pclass->create_data,
pclass->copy_func,pclass->copy_data,
pclass->close_func,pclass->close_data))==NULL)
HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "can't copy class");
- /* Walk through the hash table of the old class and copy properties */
- for(u=0; u<pclass->hashsize; u++) {
- tmp_prop=pclass->props[u];
- while(tmp_prop!=NULL) {
+ /* Walk through the TBBT of the old class and copy properties */
+ if(pclass->nprops>0) {
+ H5TB_NODE *curr_node; /* Current node in TBBT */
+
+ /* Walk through the properties in the old class */
+ curr_node=H5TB_first(pclass->props->root);
+ while(curr_node!=NULL) {
/* Make a copy of the class's property */
- if((pcopy=H5P_dup_prop(tmp_prop))==NULL)
- HGOTO_ERROR (H5E_PLIST, H5E_CANTCOPY, FAIL,"Can't copy property");
+ if((pcopy=H5P_dup_prop(curr_node->data,H5P_PROP_WITHIN_CLASS))==NULL)
+ HGOTO_ERROR (H5E_PLIST, H5E_CANTCOPY, NULL,"Can't copy property");
+
+ /* Insert the initialized property into the property list */
+ if(H5P_add_prop(new_class->props,pcopy)<0)
+ HGOTO_ERROR (H5E_PLIST, H5E_CANTINSERT, NULL,"Can't insert property into class");
- /* Insert the property into the new property class */
- if(H5P_add_prop(new_class->props,pclass->hashsize,pcopy)<0)
- HGOTO_ERROR (H5E_PLIST, H5E_CANTINSERT, FAIL,"Can't insert property into class");
+ /* Increment property count for class */
+ new_class->nprops++;
- /* Go to next registered property in class */
- tmp_prop=tmp_prop->next;
+ /* Get the next property node in the TBBT */
+ curr_node=H5TB_next(curr_node);
} /* end while */
- } /* end for */
+ } /* end if */
/* Use the new class instead of the old one */
pclass=new_class;
} /* end if */
/* Create property object from parameters */
- if((new_prop=H5P_create_prop(name,size,def_value,NULL,prp_create,prp_set,prp_get,prp_delete,prp_copy,prp_close))==NULL)
+ if((new_prop=H5P_create_prop(name,size,H5P_PROP_WITHIN_CLASS,def_value,prp_create,prp_set,prp_get,prp_delete,prp_copy,prp_close))==NULL)
HGOTO_ERROR (H5E_PLIST, H5E_CANTCREATE, FAIL,"Can't create property");
/* Insert property into property list class */
- if(H5P_add_prop(pclass->props,pclass->hashsize,new_prop)<0)
+ if(H5P_add_prop(pclass->props,new_prop)<0)
HGOTO_ERROR (H5E_PLIST, H5E_CANTINSERT, FAIL,"Can't insert property into class");
/* Increment property count for class */
pclass->nprops++;
+ /* Update the revision for the class */
+ pclass->revision = H5P_GET_NEXT_REV;
+
done:
if(ret_value==FAIL) {
if(new_prop!=NULL) {
@@ -1707,9 +1909,7 @@ done:
H5MM_xfree(new_prop->name);
if(new_prop->value!=NULL)
H5MM_xfree(new_prop->value);
- if(new_prop->def_value!=NULL)
- H5MM_xfree(new_prop->def_value);
- H5MM_xfree(new_prop);
+ H5FL_FREE(H5P_genprop_t,new_prop);
} /* end if */
} /* end if */
FUNC_LEAVE (ret_value);
@@ -1847,7 +2047,8 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-herr_t H5Pregister(hid_t cls_id, const char *name, size_t size, void *def_value,
+herr_t
+H5Pregister(hid_t cls_id, const char *name, size_t size, void *def_value,
H5P_prp_create_func_t prp_create, H5P_prp_set_func_t prp_set,
H5P_prp_get_func_t prp_get, H5P_prp_delete_func_t prp_delete,
H5P_prp_copy_func_t prp_copy, H5P_prp_close_func_t prp_close)
@@ -1986,8 +2187,9 @@ H5P_insert(H5P_genplist_t *plist, const char *name, size_t size,
H5P_prp_delete_func_t prp_delete, H5P_prp_copy_func_t prp_copy,
H5P_prp_close_func_t prp_close)
{
- H5P_genprop_t *new_prop=NULL; /* Temporary property pointer */
- herr_t ret_value=SUCCEED; /* Return value */
+ H5P_genprop_t *new_prop=NULL; /* Temporary property pointer */
+ H5TB_NODE *prop_node; /* TBBT node holding property */
+ herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOINIT(H5P_insert);
@@ -1996,15 +2198,44 @@ H5P_insert(H5P_genplist_t *plist, const char *name, size_t size,
assert((size>0 && value!=NULL) || (size==0));
/* Check for duplicate named properties */
- if(H5P_find_prop(plist->props,plist->pclass->hashsize,name)!=NULL)
+ if(H5TB_dfind(plist->props,name,NULL)!=NULL)
HGOTO_ERROR(H5E_PLIST, H5E_EXISTS, FAIL, "property already exists");
+ /* Check if the property has been deleted */
+ if((prop_node=H5TB_dfind(plist->del,name,NULL))!=NULL) {
+ /* Remove the property name from the deleted property TBBT */
+ if(H5TB_rem(&plist->del->root,prop_node,NULL)==NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_CANTDELETE,FAIL,"can't remove property from deleted TBBT");
+
+ /* Fall through to add property to list */
+ } /* end if */
+ else {
+ H5P_genclass_t *tclass; /* Temporary class pointer */
+
+ /* Check if the property is already in the class hierarchy */
+ tclass=plist->pclass;
+ while(tclass!=NULL) {
+ if(tclass->nprops>0) {
+ /* Find the property in the class */
+ if(H5TB_dfind(tclass->props,name,NULL)!=NULL)
+ HGOTO_ERROR(H5E_PLIST, H5E_EXISTS, FAIL, "property already exists");
+ } /* end if */
+
+ /* Go up to parent class */
+ tclass=tclass->parent;
+ } /* end while */
+
+ /* Fall through to add property to list */
+ } /* end else */
+
+ /* Ok to add to property list */
+
/* Create property object from parameters */
- if((new_prop=H5P_create_prop(name,size,NULL,value,NULL,prp_set,prp_get,prp_delete,prp_copy,prp_close))==NULL)
+ if((new_prop=H5P_create_prop(name,size,H5P_PROP_WITHIN_LIST,value,NULL,prp_set,prp_get,prp_delete,prp_copy,prp_close))==NULL)
HGOTO_ERROR (H5E_PLIST, H5E_CANTCREATE, FAIL,"Can't create property");
/* Insert property into property list class */
- if(H5P_add_prop(plist->props,plist->pclass->hashsize,new_prop)<0)
+ if(H5P_add_prop(plist->props,new_prop)<0)
HGOTO_ERROR (H5E_PLIST, H5E_CANTINSERT, FAIL,"Can't insert property into class");
/* Increment property count for class */
@@ -2017,9 +2248,7 @@ done:
H5MM_xfree(new_prop->name);
if(new_prop->value!=NULL)
H5MM_xfree(new_prop->value);
- if(new_prop->def_value!=NULL)
- H5MM_xfree(new_prop->def_value);
- H5MM_xfree(new_prop);
+ H5FL_FREE(H5P_genprop_t,new_prop);
} /* end if */
} /* end if */
@@ -2132,7 +2361,8 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-herr_t H5Pinsert(hid_t plist_id, const char *name, size_t size, void *value,
+herr_t
+H5Pinsert(hid_t plist_id, const char *name, size_t size, void *value,
H5P_prp_set_func_t prp_set, H5P_prp_get_func_t prp_get,
H5P_prp_delete_func_t prp_delete, H5P_prp_copy_func_t prp_copy,
H5P_prp_close_func_t prp_close)
@@ -2190,9 +2420,12 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-herr_t H5P_set(H5P_genplist_t *plist, const char *name, const void *value)
+herr_t
+H5P_set(H5P_genplist_t *plist, const char *name, const void *value)
{
+ H5P_genclass_t *tclass; /* Temporary class pointer */
H5P_genprop_t *prop; /* Temporary property pointer */
+ H5TB_NODE *prop_node; /* TBBT node holding property */
herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5P_set, FAIL);
@@ -2201,36 +2434,123 @@ herr_t H5P_set(H5P_genplist_t *plist, const char *name, const void *value)
assert(name);
assert(value);
- /* Find property */
- if((prop=H5P_find_prop(plist->props,plist->pclass->hashsize,name))==NULL)
+ /* Check if the property has been deleted */
+ if(H5TB_dfind(plist->del,name,NULL)!=NULL)
HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "property doesn't exist");
- /* Check for property size >0 */
- if(prop->size==0)
- HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "property has zero size");
+ /* Find property in changed list */
+ if((prop_node=H5TB_dfind(plist->props,name,NULL))!=NULL) {
+ /* Get pointer to actual property */
+ prop=prop_node->data;
+
+ /* Check for property size >0 */
+ if(prop->size==0)
+ HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "property has zero size");
- /* Make a copy of the value and pass to 'set' callback */
- if(prop->set!=NULL) {
- void *tmp_value; /* Temporary value for property */
+ /* Make a copy of the value and pass to 'set' callback */
+ if(prop->set!=NULL) {
+ void *tmp_value; /* Temporary value for property */
- /* Make a copy of the current value, in case the callback fails */
- if (NULL==(tmp_value=H5MM_malloc(prop->size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed temporary property value");
- HDmemcpy(tmp_value,value,prop->size);
+ /* Make a copy of the current value, in case the callback fails */
+ if (NULL==(tmp_value=H5MM_malloc(prop->size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed temporary property value");
+ HDmemcpy(tmp_value,value,prop->size);
- /* Call user's callback */
- if((*(prop->set))(plist->plist_id,name,prop->size,tmp_value)<0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "can't set property value");
+ /* Call user's callback */
+ if((*(prop->set))(plist->plist_id,name,prop->size,tmp_value)<0) {
+ H5MM_xfree(tmp_value);
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "can't set property value");
+ } /* end if */
- /* Copy new [possibly unchanged] value into property value */
- HDmemcpy(prop->value,tmp_value,prop->size);
+ /* Copy new [possibly unchanged] value into property value */
+ HDmemcpy(prop->value,tmp_value,prop->size);
- /* Free the temporary value buffer */
- H5MM_xfree(tmp_value);
+ /* Free the temporary value buffer */
+ H5MM_xfree(tmp_value);
+ } /* end if */
+ /* No 'set' callback, just copy value */
+ else
+ HDmemcpy(prop->value,value,prop->size);
} /* end if */
- /* No 'set' callback, just copy value */
- else
- HDmemcpy(prop->value,value,prop->size);
+ else {
+ /*
+ * Check if we should set class properties (up through list of parent classes also),
+ * & make property 'set' callback.
+ */
+ tclass=plist->pclass;
+ while(tclass!=NULL) {
+ if(tclass->nprops>0) {
+ /* Find the property in the class */
+ if((prop_node=H5TB_dfind(tclass->props,name,NULL))!=NULL) {
+ H5P_genprop_t *pcopy; /* Copy of property to insert into TBBT */
+
+ /* Get pointer to actual property */
+ prop=prop_node->data;
+
+ /* Check for property size >0 */
+ if(prop->size==0)
+ HGOTO_ERROR(H5E_PLIST,H5E_BADVALUE,FAIL,"property has zero size");
+
+ /* Make a copy of the value and pass to 'set' callback */
+ if(prop->set!=NULL) {
+ void *tmp_value; /* Temporary value for property */
+
+ /* Make a copy of the current value, in case the callback fails */
+ if (NULL==(tmp_value=H5MM_malloc(prop->size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed temporary property value");
+ HDmemcpy(tmp_value,value,prop->size);
+
+ /* Call user's callback */
+ if((*(prop->set))(plist->plist_id,name,prop->size,tmp_value)<0) {
+ H5MM_xfree(tmp_value);
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "can't set property value");
+ } /* end if */
+
+ if(HDmemcmp(tmp_value,prop->value,prop->size)) {
+ /* Make a copy of the class's property */
+ if((pcopy=H5P_dup_prop(prop,H5P_PROP_WITHIN_LIST))==NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_CANTCOPY,FAIL,"Can't copy property");
+
+ /* Copy new value into property value */
+ HDmemcpy(pcopy->value,tmp_value,pcopy->size);
+
+ /* Insert the changed property into the property list */
+ if(H5P_add_prop(plist->props,pcopy)<0)
+ HGOTO_ERROR (H5E_PLIST, H5E_CANTINSERT, FAIL,"Can't insert changed property into TBBT");
+ } /* end if */
+
+ /* Free the temporary value buffer */
+ H5MM_xfree(tmp_value);
+ } /* end if */
+ /* No 'set' callback, just copy value */
+ else {
+ if(HDmemcmp(value,prop->value,prop->size)) {
+ /* Make a copy of the class's property */
+ if((pcopy=H5P_dup_prop(prop,H5P_PROP_WITHIN_LIST))==NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_CANTCOPY,FAIL,"Can't copy property");
+
+ HDmemcpy(pcopy->value,value,pcopy->size);
+
+ /* Insert the changed property into the property list */
+ if(H5P_add_prop(plist->props,pcopy)<0)
+ HGOTO_ERROR (H5E_PLIST, H5E_CANTINSERT, FAIL,"Can't insert changed property into TBBT");
+ } /* end if */
+ } /* end else */
+
+ /* Leave */
+ HGOTO_DONE(SUCCEED);
+ } /* end while */
+ } /* end if */
+
+ /* Go up to parent class */
+ tclass=tclass->parent;
+ } /* end while */
+
+ /* If we get this far, then it wasn't in the list of changed properties,
+ * nor in the properties in the class hierarchy, indicate an error
+ */
+ HGOTO_ERROR(H5E_PLIST,H5E_NOTFOUND,FAIL,"can't find property in TBBT");
+ } /* end else */
done:
FUNC_LEAVE (ret_value);
@@ -2268,7 +2588,8 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-herr_t H5Pset(hid_t plist_id, const char *name, void *value)
+herr_t
+H5Pset(hid_t plist_id, const char *name, void *value)
{
H5P_genplist_t *plist; /* Property list to modify */
herr_t ret_value=SUCCEED; /* return value */
@@ -2323,12 +2644,31 @@ H5P_exist_plist(H5P_genplist_t *plist, const char *name)
assert(plist);
assert(name);
- /* Check for property in property list */
- if(H5P_find_prop(plist->props,plist->pclass->hashsize,name)==NULL)
+ /* Check for property in deleted property list */
+ if(H5TB_dfind(plist->del,name,NULL)!=NULL)
ret_value=0;
- else
- ret_value=1;
+ else {
+ /* Check for property in changed property list */
+ if(H5TB_dfind(plist->props,name,NULL)!=NULL)
+ ret_value=1;
+ else {
+ H5P_genclass_t *tclass; /* Temporary class pointer */
+
+ tclass=plist->pclass;
+ while(tclass!=NULL) {
+ if(H5TB_dfind(tclass->props,name,NULL)!=NULL)
+ HGOTO_DONE(1);
+
+ /* Go up to parent class */
+ tclass=tclass->parent;
+ } /* end while */
+
+ /* If we've reached here, we couldn't find the property */
+ ret_value=0;
+ } /* end else */
+ } /* end else */
+done:
FUNC_LEAVE (ret_value);
} /* H5P_exist_plist() */
@@ -2365,7 +2705,7 @@ H5P_exist_pclass(H5P_genclass_t *pclass, const char *name)
assert(name);
/* Check for property in property list */
- if(H5P_find_prop(pclass->props,pclass->hashsize,name)==NULL)
+ if(H5TB_dfind(pclass->props,name,NULL)==NULL)
ret_value=0;
else
ret_value=1;
@@ -2396,7 +2736,8 @@ H5P_exist_pclass(H5P_genclass_t *pclass, const char *name)
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-htri_t H5Pexist(hid_t id, const char *name)
+htri_t
+H5Pexist(hid_t id, const char *name)
{
H5P_genplist_t *plist; /* Property list to query */
H5P_genclass_t *pclass; /* Property class to query */
@@ -2467,7 +2808,7 @@ H5P_get_size_plist(H5P_genplist_t *plist, const char *name, size_t *size)
assert(size);
/* Find property */
- if((prop=H5P_find_prop(plist->props,plist->pclass->hashsize,name))==NULL)
+ if((prop=H5P_find_prop_plist(plist,name))==NULL)
HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "property doesn't exist");
/* Get property size */
@@ -2513,7 +2854,7 @@ H5P_get_size_pclass(H5P_genclass_t *pclass, const char *name, size_t *size)
assert(size);
/* Find property */
- if((prop=H5P_find_prop(pclass->props,pclass->hashsize,name))==NULL)
+ if((prop=H5P_find_prop_pclass(pclass,name))==NULL)
HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "property doesn't exist");
/* Get property size */
@@ -2547,7 +2888,8 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-herr_t H5Pget_size(hid_t id, const char *name, size_t *size)
+herr_t
+H5Pget_size(hid_t id, const char *name, size_t *size)
{
H5P_genclass_t *pclass; /* Property class to query */
H5P_genplist_t *plist; /* Property list to query */
@@ -2643,7 +2985,8 @@ H5P_get_class(H5P_genplist_t *plist)
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-hid_t H5Pget_class(hid_t plist_id)
+hid_t
+H5Pget_class(hid_t plist_id)
{
H5P_genplist_t *plist; /* Property list to query */
H5P_genclass_t *pclass=NULL; /* Property list class */
@@ -2730,7 +3073,8 @@ H5P_get_nprops_plist(H5P_genplist_t *plist, size_t *nprops)
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-herr_t H5P_get_nprops_pclass(H5P_genclass_t *pclass, size_t *nprops)
+herr_t
+H5P_get_nprops_pclass(H5P_genclass_t *pclass, size_t *nprops)
{
herr_t ret_value=SUCCEED; /* Return value */
@@ -2770,7 +3114,8 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-herr_t H5Pget_nprops(hid_t id, size_t *nprops)
+herr_t
+H5Pget_nprops(hid_t id, size_t *nprops)
{
H5P_genplist_t *plist; /* Property list to query */
H5P_genclass_t *pclass; /* Property class to query */
@@ -2853,13 +3198,6 @@ H5P_cmp_prop(H5P_genprop_t *prop1, H5P_genprop_t *prop2)
if((cmp_value=HDmemcmp(prop1->value,prop2->value,prop1->size))!=0)
HGOTO_DONE(cmp_value);
- /* Check if they both have default values allocated (or not allocated) */
- if(prop1->def_value==NULL && prop2->def_value!=NULL) HGOTO_DONE(-1);
- if(prop1->def_value!=NULL && prop2->def_value==NULL) HGOTO_DONE(1);
- if(prop1->def_value!=NULL)
- if((cmp_value=HDmemcmp(prop1->def_value,prop2->def_value,prop1->size))!=0)
- HGOTO_DONE(cmp_value);
-
/* Check if they both have the same 'create' callback */
if(prop1->create==NULL && prop2->create!=NULL) HGOTO_DONE(-1);
if(prop1->create!=NULL && prop2->create==NULL) HGOTO_DONE(1);
@@ -2890,8 +3228,6 @@ H5P_cmp_prop(H5P_genprop_t *prop1, H5P_genprop_t *prop2)
if(prop1->close!=NULL && prop2->close==NULL) HGOTO_DONE(1);
if(prop1->close!=prop2->close) HGOTO_DONE(-1);
- /* Don't check the 'next' field, they must be equal by now */
-
done:
FUNC_LEAVE (ret_value);
} /* H5P_cmp_prop() */
@@ -2922,16 +3258,19 @@ done:
static int
H5P_cmp_class(H5P_genclass_t *pclass1, H5P_genclass_t *pclass2)
{
- H5P_genprop_t *tprop1, *tprop2;/* Temporary pointer to properties */
- unsigned u; /* Local index variable */
- int cmp_value; /* Value from comparison */
- int ret_value=0; /* return value */
+ H5TB_NODE *tnode1,*tnode2; /* Temporary pointer to propery nodes */
+ int cmp_value; /* Value from comparison */
+ int ret_value=0; /* Return value */
FUNC_ENTER_NOINIT(H5P_cmp_class);
assert(pclass1);
assert(pclass2);
+ /* Use the revision number to quickly check for identical classes */
+ if(pclass1->revision==pclass2->revision)
+ HGOTO_DONE(0);
+
/* Check the name */
if((cmp_value=HDstrcmp(pclass1->name,pclass2->name))!=0)
HGOTO_DONE(cmp_value);
@@ -2940,10 +3279,6 @@ H5P_cmp_class(H5P_genclass_t *pclass1, H5P_genclass_t *pclass2)
if(pclass1->nprops < pclass2->nprops) HGOTO_DONE(-1);
if(pclass1->nprops > pclass2->nprops) HGOTO_DONE(1);
- /* Check the hashsize */
- if(pclass1->hashsize < pclass2->hashsize) HGOTO_DONE(-1);
- if(pclass1->hashsize > pclass2->hashsize) HGOTO_DONE(1);
-
/* Check the number of property lists created from the class */
if(pclass1->plists < pclass2->plists) HGOTO_DONE(-1);
if(pclass1->plists > pclass2->plists) HGOTO_DONE(1);
@@ -2979,29 +3314,21 @@ H5P_cmp_class(H5P_genclass_t *pclass1, H5P_genclass_t *pclass2)
if(pclass1->close_data > pclass2->close_data) HGOTO_DONE(1);
/* Cycle through the properties and compare them also */
- for(u=0; u<pclass1->hashsize; u++) {
- tprop1=pclass1->props[u];
- tprop2=pclass2->props[u];
-
- /* Check if they both have properties in this hash location */
- if(tprop1==NULL && tprop2!=NULL) HGOTO_DONE(-1);
- if(tprop1!=NULL && tprop2==NULL) HGOTO_DONE(1);
-
- /* Check the actual properties */
- while(tprop1!=NULL && tprop2!=NULL) {
- /* Compare the two properties */
- if((cmp_value=H5P_cmp_prop(tprop1,tprop2))!=0)
- HGOTO_DONE(cmp_value);
-
- /* Advance the pointers */
- tprop1=tprop1->next;
- tprop2=tprop2->next;
+ tnode1=H5TB_first(pclass1->props->root);
+ tnode2=H5TB_first(pclass2->props->root);
+ while(tnode1 || tnode2) {
+ /* Check if they both have properties in this TBBT node */
+ if(tnode1==NULL && tnode2!=NULL) HGOTO_DONE(-1);
+ if(tnode1!=NULL && tnode2==NULL) HGOTO_DONE(1);
+
+ /* Compare the two properties */
+ if((cmp_value=H5P_cmp_prop(tnode1->data,tnode2->data))!=0)
+ HGOTO_DONE(cmp_value);
- /* Check if they both have properties in this location */
- if(tprop1==NULL && tprop2!=NULL) HGOTO_DONE(-1);
- if(tprop1!=NULL && tprop2==NULL) HGOTO_DONE(1);
- } /* end while */
- } /* end for */
+ /* Advance the pointers */
+ tnode1=H5TB_next(tnode1);
+ tnode2=H5TB_next(tnode2);
+ } /* end while */
done:
FUNC_LEAVE (ret_value);
@@ -3033,8 +3360,7 @@ done:
static int
H5P_cmp_plist(H5P_genplist_t *plist1, H5P_genplist_t *plist2)
{
- H5P_genprop_t *tprop1, *tprop2;/* Temporary pointer to properties */
- unsigned u; /* Local index variable */
+ H5TB_NODE *tnode1,*tnode2; /* Temporary pointer to propery nodes */
int cmp_value; /* Value from comparison */
int ret_value=0; /* return value */
@@ -3043,10 +3369,6 @@ H5P_cmp_plist(H5P_genplist_t *plist1, H5P_genplist_t *plist2)
assert(plist1);
assert(plist2);
- /* Check the parent class */
- if(plist1->pclass < plist2->pclass) HGOTO_DONE(-1);
- if(plist1->pclass > plist2->pclass) HGOTO_DONE(1);
-
/* Check the number of properties */
if(plist1->nprops < plist2->nprops) HGOTO_DONE(-1);
if(plist1->nprops > plist2->nprops) HGOTO_DONE(1);
@@ -3055,24 +3377,57 @@ H5P_cmp_plist(H5P_genplist_t *plist1, H5P_genplist_t *plist2)
if(plist1->class_init < plist2->class_init) HGOTO_DONE(-1);
if(plist1->class_init > plist2->class_init) HGOTO_DONE(1);
- /* Cycle through the properties and compare them also */
- for(u=0; u<plist1->pclass->hashsize; u++) {
- tprop1=plist1->props[u];
+ /* Check for identical deleted properties */
+ if(plist1->del->root) {
+ /* Check for no deleted properties in plist2 */
+ if(plist2->del->root==NULL) HGOTO_DONE(1);
+
+ tnode1=H5TB_first(plist1->del->root);
+ tnode2=H5TB_first(plist2->del->root);
+ while(tnode1 || tnode2) {
+ /* Check if they both have properties in this TBBT node */
+ if(tnode1==NULL && tnode2!=NULL) HGOTO_DONE(-1);
+ if(tnode1!=NULL && tnode2==NULL) HGOTO_DONE(1);
+
+ /* Compare the two deleted properties */
+ if((cmp_value=HDstrcmp(tnode1->data,tnode2->data))!=0)
+ HGOTO_DONE(cmp_value);
+
+ /* Advance the pointers */
+ tnode1=H5TB_next(tnode1);
+ tnode2=H5TB_next(tnode2);
+ } /* end while */
+ } /* end if */
+ else
+ if(plist2->del->root!=NULL) HGOTO_DONE (-1);
- /* Check the actual properties */
- while(tprop1!=NULL) {
- /* Find a property with the same name in the second property list */
- if((tprop2=H5P_find_prop(plist2->props,plist2->pclass->hashsize,tprop1->name))==NULL)
- HGOTO_DONE(1);
+ /* Cycle through the changed properties and compare them also */
+ if(plist1->props->root) {
+ /* Check for no changed properties in plist2 */
+ if(plist2->props->root==NULL) HGOTO_DONE(1);
+
+ tnode1=H5TB_first(plist1->props->root);
+ tnode2=H5TB_first(plist2->props->root);
+ while(tnode1 || tnode2) {
+ /* Check if they both have properties in this TBBT node */
+ if(tnode1==NULL && tnode2!=NULL) HGOTO_DONE(-1);
+ if(tnode1!=NULL && tnode2==NULL) HGOTO_DONE(1);
/* Compare the two properties */
- if((cmp_value=H5P_cmp_prop(tprop1,tprop2))!=0)
+ if((cmp_value=H5P_cmp_prop(tnode1->data,tnode2->data))!=0)
HGOTO_DONE(cmp_value);
- /* Advance to next property */
- tprop1=tprop1->next;
+ /* Advance the pointers */
+ tnode1=H5TB_next(tnode1);
+ tnode2=H5TB_next(tnode2);
} /* end while */
- } /* end for */
+ } /* end if */
+ else
+ if(plist2->props->root!=NULL) HGOTO_DONE (-1);
+
+ /* Check the parent classes */
+ if((cmp_value=H5P_cmp_class(plist1->pclass,plist2->pclass))!=0)
+ HGOTO_DONE(cmp_value);
done:
FUNC_LEAVE (ret_value);
@@ -3099,7 +3454,8 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-htri_t H5Pequal(hid_t id1, hid_t id2)
+htri_t
+H5Pequal(hid_t id1, hid_t id2)
{
void *obj1, *obj2; /* Property objects to compare */
htri_t ret_value=FALSE; /* return value */
@@ -3205,7 +3561,8 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-htri_t H5P_isa_class(hid_t plist_id, hid_t pclass_id)
+htri_t
+H5P_isa_class(hid_t plist_id, hid_t pclass_id)
{
H5P_genplist_t *plist; /* Property list to query */
H5P_genclass_t *pclass; /* Property list class */
@@ -3251,7 +3608,8 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-htri_t H5Pisa_class(hid_t plist_id, hid_t pclass_id)
+htri_t
+H5Pisa_class(hid_t plist_id, hid_t pclass_id)
{
htri_t ret_value; /* return value */
@@ -3300,7 +3658,8 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-void *H5P_object_verify(hid_t plist_id, hid_t pclass_id)
+void *
+H5P_object_verify(hid_t plist_id, hid_t pclass_id)
{
void *ret_value; /* return value */
@@ -3321,100 +3680,6 @@ done:
/*--------------------------------------------------------------------------
NAME
- H5P_iterate_props
- PURPOSE
- Internal routine to iterate over a hashtable of properties
- USAGE
- herr_t H5P_iterate_props(id, hash, hashsize, idx, iter_func, iter_data)
- hid_t id; IN: ID of property object iterating over
- H5P_gen_prop_t *hash[]; IN: Pointer to array of properties for hash table
- unsigned hashsize; IN: Size of hash table
- int *idx; IN/OUT: Index of the property to begin with
- H5P_iterate_t iter_func; IN: Function pointer to function to be
- called with each property iterated over.
- void *iter_data; IN/OUT: Pointer to iteration data from user
- RETURNS
- Success: Returns the return value of the last call to ITER_FUNC if it was
- non-zero, or zero if all properties have been processed.
- Failure: negative value
- DESCRIPTION
- This routine iterates over the properties in the property object specified
-with ID. For each property in the object, the ITER_DATA and some
-additional information, specified below, are passed to the ITER_FUNC function.
-The iteration begins with the IDX property in the object and the next element
-to be processed by the operator is returned in IDX. If IDX is NULL, then the
-iterator starts at the first property; since no stopping point is returned in
-this case, the iterator cannot be restarted if one of the calls to its operator
-returns non-zero.
-
-The prototype for H5P_iterate_t is:
- typedef herr_t (*H5P_iterate_t)(hid_t id, const char *name, void *iter_data);
-The operation receives the property list or class identifier for the object
-being iterated over, ID, the name of the current property within the object,
-NAME, and the pointer to the operator data passed in to H5Piterate, ITER_DATA.
-
-The return values from an operator are:
- Zero causes the iterator to continue, returning zero when all properties
- have been processed.
- Positive causes the iterator to immediately return that positive value,
- indicating short-circuit success. The iterator can be restarted at the
- index of the next property.
- Negative causes the iterator to immediately return that value, indicating
- failure. The iterator can be restarted at the index of the next
- property.
-
-H5Piterate assumes that the properties in the object identified by ID remains
-unchanged through the iteration. If the membership changes during the
-iteration, the function's behavior is undefined.
-
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-static int
-H5P_iterate_props(hid_t id, H5P_genprop_t *hash[], unsigned hashsize, int *idx, H5P_iterate_t iter_func, void *iter_data)
-{
- H5P_genprop_t *prop; /* Temporary property pointer */
- unsigned u; /* Local index variable */
- int curr_idx=0; /* Current iteration index */
- int ret_value=0; /* Return value */
-
- FUNC_ENTER_NOINIT(H5P_iterate_props);
-
- assert(hash);
- assert(hashsize>0);
- assert(idx);
- assert(iter_func);
-
- /* Cycle through the properties and compare them also */
- for(u=0; u<hashsize && ret_value==0; u++) {
- prop=hash[u];
-
- /* Check the actual properties */
- while(prop!=NULL && ret_value==0) {
- /* Check if we are at the object to start iterating over */
- if(curr_idx>=*idx)
- ret_value=(*iter_func)(id,prop->name,iter_data);
-
- /* Increment the iteration index if iteration function succeeded */
- if(ret_value==0)
- curr_idx++;
-
- /* Advance the pointer */
- prop=prop->next;
- } /* end while */
- } /* end for */
-
- /* Set the index we stopped at */
- *idx=curr_idx;
-
- FUNC_LEAVE (ret_value);
-} /* H5P_iterate_props() */
-
-
-/*--------------------------------------------------------------------------
- NAME
H5P_iterate_plist
PURPOSE
Internal routine to iterate over the properties in a property list
@@ -3467,8 +3732,13 @@ iteration, the function's behavior is undefined.
static int
H5P_iterate_plist(hid_t plist_id, int *idx, H5P_iterate_t iter_func, void *iter_data)
{
+ H5P_genclass_t *tclass; /* Temporary class pointer */
H5P_genplist_t *plist; /* Property list pointer */
- int ret_value; /* Return value */
+ H5P_genprop_t *tmp; /* Temporary pointer to properties */
+ H5TB_TREE *seen=NULL; /* TBBT to hold names of properties already seen */
+ H5TB_NODE *curr_node; /* Current node in TBBT */
+ int curr_idx=0; /* Current iteration index */
+ int ret_value=FAIL; /* Return value */
FUNC_ENTER_NOINIT(H5P_iterate_plist);
@@ -3479,10 +3749,90 @@ H5P_iterate_plist(hid_t plist_id, int *idx, H5P_iterate_t iter_func, void *iter_
if (NULL == (plist = H5I_object_verify(plist_id, H5I_GENPROP_LST)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list");
- /* Iterate through the properties in the property list */
- ret_value=H5P_iterate_props(plist_id, plist->props, plist->pclass->hashsize, idx, iter_func, iter_data);
+ /* Create the TBBT to hold names of properties already seen
+ */
+ if((seen=H5TB_fast_dmake(H5TB_FAST_STR_COMPARE))==NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_CANTMAKETREE,NULL,"can't create TBBT for seen properties");
+
+ /* Walk through the changed properties in the list */
+ if(plist->props->root) {
+ curr_node=H5TB_first(plist->props->root);
+ while(curr_node!=NULL) {
+ /* Get pointer to property from node */
+ tmp=curr_node->data;
+
+ /* Check if we've found the correctly indexed property */
+ if(curr_idx>=*idx) {
+ /* Call the callback function */
+ ret_value=(*iter_func)(plist_id,tmp->name,iter_data);
+
+ if(ret_value!=0)
+ HGOTO_DONE(ret_value);
+ } /* end if */
+
+ /* Increment the current index */
+ curr_idx++;
+
+ /* Add property name to "seen" list */
+ if(H5TB_dins(seen,tmp->name,tmp->name)==NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_CANTINSERT,NULL,"can't insert property into seen TBBT");
+
+ /* Get the next property node in the TBBT */
+ curr_node=H5TB_next(curr_node);
+ } /* end while */
+ } /* end if */
+
+ /* Walk up the class hiearchy */
+ tclass=plist->pclass;
+ while(tclass!=NULL) {
+ if(tclass->nprops>0) {
+ /* Walk through the properties in the class */
+ curr_node=H5TB_first(tclass->props->root);
+ while(curr_node!=NULL) {
+ /* Get pointer to property from node */
+ tmp=curr_node->data;
+
+ /* Only call iterator callback for properties we haven't seen
+ * before and that haven't been deleted
+ */
+ if(H5TB_dfind(seen,tmp->name,NULL)==NULL &&
+ H5TB_dfind(plist->del,tmp->name,NULL)==NULL) {
+
+
+ /* Check if we've found the correctly indexed property */
+ if(curr_idx>=*idx) {
+ /* Call the callback function */
+ ret_value=(*iter_func)(plist_id,tmp->name,iter_data);
+
+ if(ret_value!=0)
+ HGOTO_DONE(ret_value);
+ } /* end if */
+
+ /* Increment the current index */
+ curr_idx++;
+
+ /* Add property name to "seen" list */
+ if(H5TB_dins(seen,tmp->name,tmp->name)==NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_CANTINSERT,NULL,"can't insert property into seen TBBT");
+ } /* end if */
+
+ /* Get the next property node in the TBBT */
+ curr_node=H5TB_next(curr_node);
+ } /* end while */
+ } /* end if */
+
+ /* Go up to parent class */
+ tclass=tclass->parent;
+ } /* end while */
done:
+ /* Set the index we stopped at */
+ *idx=curr_idx;
+
+ /* Release the tree of 'seen' properties */
+ if(seen!=NULL)
+ H5TB_dfree(seen,NULL,NULL);
+
FUNC_LEAVE (ret_value);
} /* H5P_iterate_plist() */
@@ -3542,7 +3892,10 @@ static int
H5P_iterate_pclass(hid_t pclass_id, int *idx, H5P_iterate_t iter_func, void *iter_data)
{
H5P_genclass_t *pclass; /* Property list pointer */
- int ret_value; /* Return value */
+ H5TB_NODE *curr_node; /* Current node in TBBT */
+ H5P_genprop_t *prop; /* Temporary property pointer */
+ int curr_idx=0; /* Current iteration index */
+ int ret_value=FAIL; /* Return value */
FUNC_ENTER_NOINIT(H5P_iterate_pclass);
@@ -3553,10 +3906,33 @@ H5P_iterate_pclass(hid_t pclass_id, int *idx, H5P_iterate_t iter_func, void *ite
if (NULL == (pclass = H5I_object_verify(pclass_id, H5I_GENPROP_CLS)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property class");
- /* Iterate through the properties in the property list */
- ret_value=H5P_iterate_props(pclass_id, pclass->props, pclass->hashsize, idx, iter_func, iter_data);
+ /* Set the current index */
+ curr_idx=*idx;
+
+ /* Cycle through the properties and call the callback */
+ curr_node=H5TB_index(pclass->props->root,(unsigned)*idx);
+ while(curr_node!=NULL) {
+ /* Get the property for the node */
+ prop=curr_node->data;
+
+ /* Call the callback function */
+ ret_value=(*iter_func)(pclass_id,prop->name,iter_data);
+
+ /* Check if iteration function succeeded */
+ if(ret_value!=0)
+ HGOTO_DONE(ret_value);
+
+ /* Increment the iteration index */
+ curr_idx++;
+
+ /* Get the next property node in the TBBT */
+ curr_node=H5TB_next(curr_node);
+ } /* end while */
done:
+ /* Set the index we stopped at */
+ *idx=curr_idx;
+
FUNC_LEAVE (ret_value);
} /* H5P_iterate_pclass() */
@@ -3613,7 +3989,8 @@ iteration, the function's behavior is undefined.
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-int H5Piterate(hid_t id, int *idx, H5P_iterate_t iter_func, void *iter_data)
+int
+H5Piterate(hid_t id, int *idx, H5P_iterate_t iter_func, void *iter_data)
{
int fake_idx=0; /* Index when user doesn't provide one */
int ret_value; /* return value */
@@ -3672,7 +4049,8 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-unsigned H5P_peek_unsigned(H5P_genplist_t *plist, const char *name)
+unsigned
+H5P_peek_unsigned(H5P_genplist_t *plist, const char *name)
{
unsigned ret_value; /* return value */
@@ -3716,7 +4094,8 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-hid_t H5P_peek_hid_t(H5P_genplist_t *plist, const char *name)
+hid_t
+H5P_peek_hid_t(H5P_genplist_t *plist, const char *name)
{
hid_t ret_value; /* return value */
@@ -3760,7 +4139,8 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-void *H5P_peek_voidp(H5P_genplist_t *plist, const char *name)
+void *
+H5P_peek_voidp(H5P_genplist_t *plist, const char *name)
{
void * ret_value; /* return value */
@@ -3804,7 +4184,8 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-hsize_t H5P_peek_hsize_t(H5P_genplist_t *plist, const char *name)
+hsize_t
+H5P_peek_hsize_t(H5P_genplist_t *plist, const char *name)
{
hsize_t ret_value; /* return value */
@@ -3848,7 +4229,8 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-size_t H5P_peek_size_t(H5P_genplist_t *plist, const char *name)
+size_t
+H5P_peek_size_t(H5P_genplist_t *plist, const char *name)
{
size_t ret_value; /* return value */
@@ -3893,9 +4275,12 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-herr_t H5P_get(H5P_genplist_t *plist, const char *name, void *value)
+herr_t
+H5P_get(H5P_genplist_t *plist, const char *name, void *value)
{
+ H5P_genclass_t *tclass; /* Temporary class pointer */
H5P_genprop_t *prop; /* Temporary property pointer */
+ H5TB_NODE *prop_node; /* TBBT node holding property */
herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5P_get, FAIL);
@@ -3904,36 +4289,113 @@ herr_t H5P_get(H5P_genplist_t *plist, const char *name, void *value)
assert(name);
assert(value);
- /* Find property */
- if((prop=H5P_find_prop(plist->props,plist->pclass->hashsize,name))==NULL)
+ /* Check if the property has been deleted */
+ if(H5TB_dfind(plist->del,name,NULL)!=NULL)
HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "property doesn't exist");
- /* Check for property size >0 */
- if(prop->size==0)
- HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "property has zero size");
+ /* Find property */
+ if((prop_node=H5TB_dfind(plist->props,name,NULL))!=NULL) {
+ /* Get pointer to actual property */
+ prop=prop_node->data;
+
+ /* Check for property size >0 */
+ if(prop->size==0)
+ HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "property has zero size");
- /* Make a copy of the value and pass to 'get' callback */
- if(prop->get!=NULL) {
- void *tmp_value; /* Temporary value for property */
+ /* Make a copy of the value and pass to 'get' callback */
+ if(prop->get!=NULL) {
+ void *tmp_value; /* Temporary value for property */
- /* Make a copy of the current value, in case the callback fails */
- if (NULL==(tmp_value=H5MM_malloc(prop->size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed temporary property value");
- HDmemcpy(tmp_value,prop->value,prop->size);
+ /* Make a copy of the current value, in case the callback fails */
+ if (NULL==(tmp_value=H5MM_malloc(prop->size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed temporary property value");
+ HDmemcpy(tmp_value,prop->value,prop->size);
- /* Call user's callback */
- if((*(prop->get))(plist->plist_id,name,prop->size,tmp_value)<0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "can't get property value");
+ /* Call user's callback */
+ if((*(prop->get))(plist->plist_id,name,prop->size,tmp_value)<0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "can't get property value");
- /* Copy new [possibly unchanged] value into return value */
- HDmemcpy(value,tmp_value,prop->size);
+ /* Copy new [possibly unchanged] value into return value */
+ HDmemcpy(value,tmp_value,prop->size);
- /* Free the temporary value buffer */
- H5MM_xfree(tmp_value);
+ /* Free the temporary value buffer */
+ H5MM_xfree(tmp_value);
+ } /* end if */
+ /* No 'get' callback, just copy value */
+ else
+ HDmemcpy(value,prop->value,prop->size);
} /* end if */
- /* No 'get' callback, just copy value */
- else
- HDmemcpy(value,prop->value,prop->size);
+ else {
+ /*
+ * Check if we should get class properties (up through list of parent classes also),
+ * & make property 'get' callback.
+ */
+ tclass=plist->pclass;
+ while(tclass!=NULL) {
+ if(tclass->nprops>0) {
+ /* Find the property in the class */
+ if((prop_node=H5TB_dfind(tclass->props,name,NULL))!=NULL) {
+ /* Get pointer to actual property */
+ prop=prop_node->data;
+
+ /* Check for property size >0 */
+ if(prop->size==0)
+ HGOTO_ERROR(H5E_PLIST,H5E_BADVALUE,FAIL,"property has zero size");
+
+ /* Call the 'get' callback, if there is one */
+ if(prop->get!=NULL) {
+ void *tmp_value; /* Temporary value for property */
+
+ /* Make a copy of the current value, in case the callback fails */
+ if (NULL==(tmp_value=H5MM_malloc(prop->size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed temporary property value");
+ HDmemcpy(tmp_value,prop->value,prop->size);
+
+ /* Call user's callback */
+ if((*(prop->get))(plist->plist_id,name,prop->size,tmp_value)<0) {
+ H5MM_xfree(tmp_value);
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "can't set property value");
+ } /* end if */
+
+ if(HDmemcmp(tmp_value,prop->value,prop->size)) {
+ H5P_genprop_t *pcopy; /* Copy of property to insert into TBBT */
+
+ /* Make a copy of the class's property */
+ if((pcopy=H5P_dup_prop(prop,H5P_PROP_WITHIN_LIST))==NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_CANTCOPY,FAIL,"Can't copy property");
+
+ /* Copy new value into property value */
+ HDmemcpy(pcopy->value,tmp_value,prop->size);
+
+ /* Insert the changed property into the property list */
+ if(H5P_add_prop(plist->props,pcopy)<0)
+ HGOTO_ERROR (H5E_PLIST, H5E_CANTINSERT, FAIL,"Can't insert changed property into TBBT");
+ } /* end if */
+
+ /* Copy new [possibly unchanged] value into return value */
+ HDmemcpy(value,tmp_value,prop->size);
+
+ /* Free the temporary value buffer */
+ H5MM_xfree(tmp_value);
+ } /* end if */
+ /* No 'get' callback, just copy value */
+ else
+ HDmemcpy(value,prop->value,prop->size);
+
+ /* Leave */
+ HGOTO_DONE(SUCCEED);
+ } /* end while */
+ } /* end if */
+
+ /* Go up to parent class */
+ tclass=tclass->parent;
+ } /* end while */
+
+ /* If we get this far, then it wasn't in the list of changed properties,
+ * nor in the properties in the class hierarchy, indicate an error
+ */
+ HGOTO_ERROR(H5E_PLIST,H5E_NOTFOUND,FAIL,"can't find property in TBBT");
+ } /* end else */
done:
FUNC_LEAVE (ret_value);
@@ -3968,7 +4430,8 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-herr_t H5Pget(hid_t plist_id, const char *name, void * value)
+herr_t
+H5Pget(hid_t plist_id, const char *name, void * value)
{
H5P_genplist_t *plist; /* Property list pointer */
herr_t ret_value=SUCCEED; /* return value */
@@ -4021,63 +4484,106 @@ done:
herr_t
H5P_remove(hid_t plist_id, H5P_genplist_t *plist, const char *name)
{
+ H5P_genclass_t *tclass; /* Temporary class pointer */
+ H5TB_NODE *curr_node; /* TBBT node holding property */
H5P_genprop_t *prop; /* Temporary property pointer */
- H5P_genprop_t *tprop, *prev;/* Temporary pointer to properties */
- unsigned loc; /* Hash table location */
- herr_t ret_value=SUCCEED; /* Return value */
+ char *del_name; /* Pointer to deleted name */
+ herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOINIT(H5P_remove);
+ FUNC_ENTER_NOAPI(H5P_remove,FAIL);
assert(plist);
assert(name);
- /* Find the property in the property list */
- if((prop=H5P_find_prop(plist->props,plist->pclass->hashsize,name))==NULL)
- HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "property doesn't exist");
+ /* Indicate that the property isn't in the list if it has been deleted already */
+ if(H5TB_dfind(plist->del,name,NULL)!=NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_NOTFOUND,FAIL,"can't find property in TBBT");
- /* Pass value to 'close' callback, if it exists */
- if(prop->del!=NULL) {
- /* Call user's callback */
- if((*(prop->del))(plist_id,name,prop->size,prop->value)<0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "can't close property value");
- } /* end if */
+ /* Get the property node from the changed property TBBT */
+ if((curr_node=H5TB_dfind(plist->props,name,NULL))!=NULL) {
+ /* Get pointer to property for node */
+ prop=curr_node->data;
- /* Get correct hash table location */
- loc=H5P_hash_name(name,plist->pclass->hashsize);
-
- /* Remove property from property list */
- /* Check if the property being removed is at the head of the list for a hash location */
- if(prop==plist->props[loc]) {
- /* Jump over the property we are deleting */
- plist->props[loc]=prop->next;
+ /* Pass value to 'close' callback, if it exists */
+ if(prop->del!=NULL) {
+ /* Call user's callback */
+ if((*(prop->del))(plist_id,name,prop->size,prop->value)<0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "can't close property value");
+ } /* end if */
+
+ /* Duplicate string for insertion into new deleted property TBBT */
+ if((del_name=H5MM_xstrdup(name))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE,H5E_NOSPACE,FAIL,"memory allocation failed");
+
+ /* Insert property name into deleted list */
+ if(H5TB_dins(plist->del,del_name,del_name)==NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_CANTINSERT,FAIL,"can't insert property into deleted TBBT");
+
+ /* Remove the property from the TBBT */
+ if(H5TB_rem(&plist->props->root,curr_node,NULL)==NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_CANTDELETE,FAIL,"can't remove property from TBBT");
/* Free the property, ignoring return value, nothing we can do */
H5P_free_prop(prop);
+
+ /* Decrement the number of properties in list */
+ plist->nprops--;
} /* end if */
+ /* Walk through all the properties in the class hierarchy, looking for the property */
else {
- /* Set up initial pointers */
- prev=tprop=plist->props[loc];
- tprop=tprop->next;
- while(tprop!=NULL) {
- if(tprop==prop) {
- /* Jump over the property we are deleting */
- prev->next=prop->next;
-
- /* Free the property, ignoring return value, nothing we can do */
- H5P_free_prop(prop);
-
- /* Break out of while loop */
- break;
+ /*
+ * Check if we should delete class properties (up through list of parent classes also),
+ * & make property 'delete' callback.
+ */
+ tclass=plist->pclass;
+ while(tclass!=NULL) {
+ if(tclass->nprops>0) {
+ /* Find the property in the class */
+ if((prop=H5P_find_prop_pclass(tclass,name))!=NULL) {
+ /* Pass value to 'del' callback, if it exists */
+ if(prop->del!=NULL) {
+ void *tmp_value; /* Temporary value buffer */
+
+ /* Allocate space for a temporary copy of the property value */
+ if (NULL==(tmp_value=H5MM_malloc(prop->size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for temporary property value");
+ HDmemcpy(tmp_value,prop->value,prop->size);
+
+ /* Call user's callback */
+ if((*(prop->del))(plist_id,name,prop->size,tmp_value)<0) {
+ H5MM_xfree(tmp_value);
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "can't close property value");
+ } /* end if */
+
+ /* Release the temporary value buffer */
+ H5MM_xfree(tmp_value);
+ } /* end if */
+
+ /* Duplicate string for insertion into new deleted property TBBT */
+ if((del_name=H5MM_xstrdup(name))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE,H5E_NOSPACE,FAIL,"memory allocation failed");
+
+ /* Insert property name into deleted list */
+ if(H5TB_dins(plist->del,del_name,del_name)==NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_CANTINSERT,FAIL,"can't insert property into deleted TBBT");
+
+ /* Decrement the number of properties in list */
+ plist->nprops--;
+
+ /* Leave */
+ HGOTO_DONE(SUCCEED);
+ } /* end while */
} /* end if */
- /* Move to the next nodes */
- prev=tprop;
- tprop=tprop->next;
+ /* Go up to parent class */
+ tclass=tclass->parent;
} /* end while */
- } /* end else */
- /* Decrement the number of properties in list */
- plist->nprops--;
+ /* If we get this far, then it wasn't in the list of changed properties,
+ * nor in the properties in the class hierarchy, indicate an error
+ */
+ HGOTO_ERROR(H5E_PLIST,H5E_NOTFOUND,FAIL,"can't find property in TBBT");
+ } /* end else */
done:
FUNC_LEAVE (ret_value);
@@ -4110,7 +4616,8 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-herr_t H5Premove(hid_t plist_id, const char *name)
+herr_t
+H5Premove(hid_t plist_id, const char *name)
{
H5P_genplist_t *plist; /* Property list to modify */
herr_t ret_value; /* return value */
@@ -4180,20 +4687,17 @@ H5P_copy_prop_plist(hid_t dst_id, hid_t src_id, const char *name)
if(NULL == (src_plist = H5I_object(src_id)) || NULL == (dst_plist = H5I_object(dst_id)))
HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "property object doesn't exist");
- /* Check if the property exists in the destination */
- prop=H5P_find_prop(dst_plist->props,dst_plist->pclass->hashsize,name);
-
/* If the property exists in the destination alread */
- if(prop!=NULL) {
+ if(H5P_find_prop_plist(dst_plist,name)!=NULL) {
/* Delete the property from the destination list, calling the 'close' callback if necessary */
if(H5P_remove(dst_id,dst_plist,name)<0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTDELETE, FAIL, "unable to remove property");
/* Get the pointer to the source property */
- prop=H5P_find_prop(src_plist->props,src_plist->pclass->hashsize,name);
+ prop=H5P_find_prop_plist(src_plist,name);
/* Make a copy of the source property */
- if((new_prop=H5P_dup_prop(prop))==NULL)
+ if((new_prop=H5P_dup_prop(prop,H5P_PROP_WITHIN_LIST))==NULL)
HGOTO_ERROR (H5E_PLIST, H5E_CANTCOPY, FAIL,"Can't copy property");
/* Call property copy callback, if it exists */
@@ -4203,7 +4707,7 @@ H5P_copy_prop_plist(hid_t dst_id, hid_t src_id, const char *name)
} /* end if */
/* Insert the initialized property into the property list */
- if(H5P_add_prop(dst_plist->props,dst_plist->pclass->hashsize,new_prop)<0)
+ if(H5P_add_prop(dst_plist->props,new_prop)<0)
HGOTO_ERROR (H5E_PLIST, H5E_CANTINSERT, FAIL,"Can't insert property into list");
/* Increment the number of properties in list */
@@ -4212,10 +4716,10 @@ H5P_copy_prop_plist(hid_t dst_id, hid_t src_id, const char *name)
/* If not, get the information required to do an H5Pinsert with the property into the destination list */
else {
/* Get the pointer to the source property */
- prop=H5P_find_prop(src_plist->props,src_plist->pclass->hashsize,name);
+ prop=H5P_find_prop_plist(src_plist,name);
/* Create property object from parameters */
- if((new_prop=H5P_create_prop(prop->name,prop->size,prop->def_value,prop->value,prop->create,prop->set,prop->get,prop->del,prop->copy,prop->copy))==NULL)
+ if((new_prop=H5P_create_prop(prop->name,prop->size,H5P_PROP_WITHIN_LIST,prop->value,prop->create,prop->set,prop->get,prop->del,prop->copy,prop->copy))==NULL)
HGOTO_ERROR (H5E_PLIST, H5E_CANTCREATE, FAIL,"Can't create property");
/* Call property creation callback, if it exists */
@@ -4225,7 +4729,7 @@ H5P_copy_prop_plist(hid_t dst_id, hid_t src_id, const char *name)
} /* end if */
/* Insert property into property list class */
- if(H5P_add_prop(dst_plist->props,dst_plist->pclass->hashsize,new_prop)<0)
+ if(H5P_add_prop(dst_plist->props,new_prop)<0)
HGOTO_ERROR (H5E_PLIST, H5E_CANTINSERT, FAIL,"Can't insert property into class");
/* Increment property count for class */
@@ -4274,7 +4778,7 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5P_copy_prop_pclass(H5P_genclass_t *dst_pclass, H5P_genclass_t UNUSED *src_pclass, const char *name)
+H5P_copy_prop_pclass(H5P_genclass_t *dst_pclass, H5P_genclass_t *src_pclass, const char *name)
{
H5P_genprop_t *prop; /* Temporary property pointer */
herr_t ret_value=SUCCEED; /* return value */
@@ -4285,18 +4789,19 @@ H5P_copy_prop_pclass(H5P_genclass_t *dst_pclass, H5P_genclass_t UNUSED *src_pcla
assert(src_pclass);
assert(name);
- /* Check if the property exists in the destination */
- prop=H5P_find_prop(dst_pclass->props,dst_pclass->hashsize,name);
-
/* If the property exists in the destination already */
- if(prop!=NULL) {
+ if(H5P_exist_pclass(dst_pclass,name)) {
/* Delete the old property from the destination class */
if(H5P_unregister(dst_pclass,name)<0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTDELETE, FAIL, "unable to remove property");
} /* end if */
+ /* Get the property from the source */
+ if((prop=H5P_find_prop_pclass(src_pclass,name))==NULL)
+ HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "unable to locate property");
+
/* Register the property into the destination */
- if(H5P_register(dst_pclass,name,prop->size,prop->def_value,prop->create,prop->set,prop->get,prop->del,prop->copy,prop->close)<0)
+ if(H5P_register(dst_pclass,name,prop->size,prop->value,prop->create,prop->set,prop->get,prop->del,prop->copy,prop->close)<0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTDELETE, FAIL, "unable to remove property");
done:
@@ -4404,9 +4909,8 @@ done:
static herr_t
H5P_unregister(H5P_genclass_t *pclass, const char *name)
{
+ H5TB_NODE *prop_node; /* TBBT node holding property */
H5P_genprop_t *prop; /* Temporary property pointer */
- H5P_genprop_t *tprop, *prev;/* Temporary pointer to properties */
- unsigned loc; /* Hash table location */
herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOINIT(H5P_unregister);
@@ -4414,46 +4918,26 @@ H5P_unregister(H5P_genclass_t *pclass, const char *name)
assert(pclass);
assert(name);
- /* Find the property in the property list */
- if((prop=H5P_find_prop(pclass->props,pclass->hashsize,name))==NULL)
- HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "property doesn't exist");
+ /* Get the property node from the TBBT */
+ if((prop_node=H5TB_dfind(pclass->props,name,NULL))==NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_NOTFOUND,NULL,"can't find property in TBBT");
- /* Get correct hash table location */
- loc=H5P_hash_name(name,pclass->hashsize);
-
- /* Remove property from property list */
- /* Check if the property being removed is at the head of the list for a hash location */
- if(prop==pclass->props[loc]) {
- pclass->props[loc]=prop->next;
+ /* Get the pointer to the property */
+ prop=prop_node->data;
- /* Free the property, ignoring return value, nothing we can do */
- H5P_free_prop(prop);
- } /* end if */
- else {
- /* Set up initial pointers */
- prev=tprop=pclass->props[loc];
- tprop=tprop->next;
- while(tprop!=NULL) {
- if(tprop==prop) {
- /* Jump over the property we are deleting */
- prev->next=prop->next;
-
- /* Free the property, ignoring return value, nothing we can do */
- H5P_free_prop(prop);
-
- /* Break out of while loop */
- break;
- } /* end if */
+ /* Remove the property from the TBBT */
+ if(H5TB_rem(&pclass->props->root,prop_node,NULL)==NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_CANTDELETE,FAIL,"can't remove property from TBBT");
- /* Move to the next nodes */
- prev=tprop;
- tprop=tprop->next;
- } /* end while */
- } /* end else */
+ /* Free the property, ignoring return value, nothing we can do */
+ H5P_free_prop(prop);
/* Decrement the number of registered properties in class */
pclass->nprops--;
+ /* Update the revision for the class */
+ pclass->revision = H5P_GET_NEXT_REV;
+
done:
FUNC_LEAVE (ret_value);
} /* H5P_unregister() */
@@ -4480,7 +4964,8 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-herr_t H5Punregister(hid_t pclass_id, const char *name)
+herr_t
+H5Punregister(hid_t pclass_id, const char *name)
{
H5P_genclass_t *pclass; /* Property list class to modify */
herr_t ret_value; /* return value */
@@ -4529,8 +5014,12 @@ done:
herr_t
H5P_close(void *_plist)
{
+ H5P_genclass_t *tclass; /* Temporary class pointer */
H5P_genplist_t *plist=(H5P_genplist_t *)_plist;
- herr_t ret_value=SUCCEED; /* return value */
+ H5TB_TREE *seen=NULL; /* TBBT to hold names of properties already seen */
+ H5TB_NODE *curr_node; /* Current node in TBBT */
+ H5P_genprop_t *tmp; /* Temporary pointer to properties */
+ herr_t ret_value=SUCCEED; /* return value */
FUNC_ENTER_NOINIT(H5P_close);
@@ -4542,17 +5031,106 @@ H5P_close(void *_plist)
(plist->pclass->close_func)(plist->plist_id,plist->pclass->close_data);
} /* end if */
- /* Make calls to any property close callbacks which exist */
- H5P_free_all_prop(plist->props,plist->pclass->hashsize,1);
+ /* Create the TBBT to hold names of properties already seen
+ * (This prevents a property in the class hierarchy from having it's
+ * 'close' callback called, if a property in the class hierarchy has
+ * already been seen)
+ */
+ if((seen=H5TB_fast_dmake(H5TB_FAST_STR_COMPARE))==NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_CANTMAKETREE,NULL,"can't create TBBT for seen properties");
+
+ /* Walk through the changed properties in the list */
+ if(plist->props->root) {
+ curr_node=H5TB_first(plist->props->root);
+ while(curr_node!=NULL) {
+ /* Get pointer to property from node */
+ tmp=curr_node->data;
+
+ /* Call property close callback, if it exists */
+ if(tmp->close) {
+ /* Call the 'close' callback */
+ (tmp->close)(tmp->name,tmp->size,tmp->value);
+ } /* end if */
+
+ /* Add property name to "seen" list */
+ if(H5TB_dins(seen,tmp->name,tmp->name)==NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_CANTINSERT,NULL,"can't insert property into seen TBBT");
+
+ /* Get the next property node in the TBBT */
+ curr_node=H5TB_next(curr_node);
+ } /* end while */
+ } /* end if */
+
+ /*
+ * Check if we should remove class properties (up through list of parent classes also),
+ * initialize each with default value & make property 'remove' callback.
+ */
+ tclass=plist->pclass;
+ while(tclass!=NULL) {
+ if(tclass->nprops>0) {
+ /* Walk through the properties in the class */
+ curr_node=H5TB_first(tclass->props->root);
+ while(curr_node!=NULL) {
+ /* Get pointer to property from node */
+ tmp=curr_node->data;
+
+ /* Only "delete" properties we haven't seen before
+ * and that haven't already been deleted
+ */
+ if(H5TB_dfind(seen,tmp->name,NULL)==NULL &&
+ H5TB_dfind(plist->del,tmp->name,NULL)==NULL) {
+
+ /* Call property close callback, if it exists */
+ if(tmp->close) {
+ void *tmp_value; /* Temporary value buffer */
+
+ /* Allocate space for a temporary copy of the property value */
+ if (NULL==(tmp_value=H5MM_malloc(tmp->size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for temporary property value");
+ HDmemcpy(tmp_value,tmp->value,tmp->size);
+
+ /* Call the 'close' callback */
+ (tmp->close)(tmp->name,tmp->size,tmp_value);
+
+ /* Release the temporary value buffer */
+ H5MM_xfree(tmp_value);
+ } /* end if */
+
+ /* Add property name to "seen" list */
+ if(H5TB_dins(seen,tmp->name,tmp->name)==NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_CANTINSERT,NULL,"can't insert property into seen TBBT");
+ } /* end if */
+
+ /* Get the next property node in the TBBT */
+ curr_node=H5TB_next(curr_node);
+ } /* end while */
+ } /* end if */
+
+ /* Go up to parent class */
+ tclass=tclass->parent;
+ } /* end while */
/* Decrement class's dependant property list value! */
if(H5P_access_class(plist->pclass,H5P_MOD_DEC_LST)<0)
HGOTO_ERROR (H5E_PLIST, H5E_CANTINIT, FAIL, "Can't decrement class ref count");
+ /* Free the list of 'seen' properties */
+ seen=H5TB_dfree(seen,NULL,NULL);
+
+ /* Free the list of deleted property names */
+ H5TB_dfree(plist->del,free,NULL);
+
+ /* Free the property tree itself */
+ H5TB_dfree(plist->props,H5P_free_prop,NULL);
+
/* Destroy property list object */
- H5MM_xfree(plist);
+ H5FL_FREE(H5P_genplist_t,plist);
done:
+ /* Release the tree of 'seen' properties */
+ if(seen!=NULL)
+ H5TB_dfree(seen,NULL,NULL);
+
FUNC_LEAVE (ret_value);
} /* H5P_close() */
@@ -4578,7 +5156,8 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-herr_t H5Pclose(hid_t plist_id)
+herr_t
+H5Pclose(hid_t plist_id)
{
H5P_genplist_t *plist; /* Property list created */
herr_t ret_value=SUCCEED; /* return value */
@@ -4625,7 +5204,8 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-char *H5P_get_class_name(H5P_genclass_t *pclass)
+char *
+H5P_get_class_name(H5P_genclass_t *pclass)
{
char *ret_value; /* return value */
@@ -4661,7 +5241,8 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-char *H5Pget_class_name(hid_t pclass_id)
+char *
+H5Pget_class_name(hid_t pclass_id)
{
H5P_genclass_t *pclass; /* Property class to query */
char *ret_value; /* return value */
@@ -4889,7 +5470,8 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-hid_t H5P_open_class_path_test(const char *path)
+hid_t
+H5P_open_class_path_test(const char *path)
{
H5P_genclass_t *pclass=NULL;/* Property class to query */
hid_t ret_value; /* Return value */
@@ -4970,7 +5552,8 @@ H5P_get_class_parent(H5P_genclass_t *pclass)
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-hid_t H5Pget_class_parent(hid_t pclass_id)
+hid_t
+H5Pget_class_parent(hid_t pclass_id)
{
H5P_genclass_t *pclass; /* Property class to query */
H5P_genclass_t *parent=NULL; /* Parent's property class */