summaryrefslogtreecommitdiffstats
path: root/tools/lib/h5tools_ref.c
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2005-08-25 20:16:40 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2005-08-25 20:16:40 (GMT)
commita4329aaa478d76dc954216b86c74539861aedf38 (patch)
tree0d005e1ba2c3c78450187bd74c146a0d329032c6 /tools/lib/h5tools_ref.c
parentab6656c52c8186fc9bca911f7dfb4df967b26817 (diff)
downloadhdf5-a4329aaa478d76dc954216b86c74539861aedf38.zip
hdf5-a4329aaa478d76dc954216b86c74539861aedf38.tar.gz
hdf5-a4329aaa478d76dc954216b86c74539861aedf38.tar.bz2
[svn-r11297] Purpose:
Code cleanup & speedup Description: Refactor h5dump & related code to be considerably cleaner & faster for files with large #'s of objects. Platforms tested: FreeBS 4.11 (sleipnir) Linux 2.4
Diffstat (limited to 'tools/lib/h5tools_ref.c')
-rw-r--r--tools/lib/h5tools_ref.c343
1 files changed, 199 insertions, 144 deletions
diff --git a/tools/lib/h5tools_ref.c b/tools/lib/h5tools_ref.c
index fbcc734..df2873d 100644
--- a/tools/lib/h5tools_ref.c
+++ b/tools/lib/h5tools_ref.c
@@ -16,6 +16,7 @@
#include <stdlib.h>
#include "h5tools_ref.h"
#include "H5private.h"
+#include "H5SLprivate.h"
#include "h5tools.h"
#include "h5tools_utils.h"
@@ -34,15 +35,107 @@
* method of selecting which one.
*/
+typedef struct {
+ haddr_t objno; /* Object ID (i.e. address) */
+ const char *path; /* Object path */
+} ref_path_node_t;
+
+static H5SL_t *ref_path_table = NULL; /* the "table" (implemented with a skip list) */
+static hid_t thefile;
-extern hid_t thefile;
-size_t prefix_len = 1024;
-char *prefix;
extern char *progname;
extern int d_status;
+static int ref_path_table_put(const char *, haddr_t objno);
+static hbool_t ref_path_table_find(haddr_t objno);
-ref_path_table_entry_t *ref_path_table = NULL; /* the table */
+/*-------------------------------------------------------------------------
+ * Function: init_ref_path_table
+ *
+ * Purpose: Enter the root group ("/") into the path table
+ *
+ * Return: Non-negative on success, negative on failure
+ *
+ * Programmer: Quincey Koziol
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+init_ref_path_table(hid_t fid)
+{
+ H5G_stat_t sb;
+ char *root_path;
+
+ /* Set file ID for later queries (XXX: this should be fixed) */
+ thefile = fid;
+
+ /* Create skip list to store reference path information */
+ if((ref_path_table = H5SL_create(H5SL_TYPE_HADDR, 0.5, (size_t)16))==NULL)
+ return (-1);
+
+ if((root_path = HDstrdup("/")) == NULL)
+ return (-1);
+
+ if(H5Gget_objinfo(fid, "/", TRUE, &sb)<0) {
+ /* fatal error? */
+ HDfree(root_path);
+ return (-1);
+ }
+
+ /* Insert into table (takes ownership of path) */
+ ref_path_table_put(root_path, sb.objno);
+
+ return(0);
+}
+
+/*-------------------------------------------------------------------------
+ * Function: free_ref_path_info
+ *
+ * Purpose: Free the key for a reference path table node
+ *
+ * Return: Non-negative on success, negative on failure
+ *
+ * Programmer: Quincey Koziol
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+free_ref_path_info(void *item, void UNUSED *key, void UNUSED *operator_data/*in,out*/)
+{
+ ref_path_node_t *node = (ref_path_node_t *)item;
+
+ HDfree(node->path);
+ HDfree(node);
+
+ return(0);
+}
+
+/*-------------------------------------------------------------------------
+ * Function: term_ref_path_table
+ *
+ * Purpose: Terminate the reference path table
+ *
+ * Return: Non-negative on success, negative on failure
+ *
+ * Programmer: Quincey Koziol
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+term_ref_path_table(void)
+{
+ /* Destroy reference path table, freeing all memory */
+ if(ref_path_table)
+ H5SL_destroy(ref_path_table, free_ref_path_info, NULL);
+
+ return(0);
+}
/*-------------------------------------------------------------------------
* Function: ref_path_table_lookup
@@ -59,34 +152,60 @@ ref_path_table_entry_t *ref_path_table = NULL; /* the table */
*
*-------------------------------------------------------------------------
*/
-ref_path_table_entry_t *
+haddr_t
ref_path_table_lookup(const char *thepath)
{
- H5G_stat_t sb;
- ref_path_table_entry_t *pte = ref_path_table;
+ H5G_stat_t sb;
+ haddr_t ret_value;
+ /* Get object ID for object at path */
if(H5Gget_objinfo(thefile, thepath, TRUE, &sb)<0)
/* fatal error ? */
- return NULL;
+ return HADDR_UNDEF;
- while(pte!=NULL) {
- if (sb.objno==pte->statbuf.objno)
- return pte;
- pte = pte->next;
- }
+ /* Return OID or HADDR_UNDEF */
+ ret_value = ref_path_table_find(sb.objno) ? sb.objno : HADDR_UNDEF;
+
+ return(ret_value);
+}
+
+/*-------------------------------------------------------------------------
+ * Function: ref_path_table_find
+ *
+ * Purpose: Looks up a table entry given a object number.
+ * Used during construction of the table.
+ *
+ * Return: TRUE/FALSE on success, can't fail
+ *
+ * Programmer: Quincey Koziol
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static hbool_t
+ref_path_table_find(haddr_t objno)
+{
+ HDassert(ref_path_table);
- return NULL;
+ if(H5SL_search(ref_path_table, &objno) == NULL)
+ return FALSE;
+ else
+ return TRUE;
}
/*-------------------------------------------------------------------------
* Function: ref_path_table_put
*
- * Purpose: Enter the 'obj' with 'path' in the table if
- * not already there.
+ * Purpose: Enter the 'obj' with 'path' in the table (assumes its not
+ * already there)
+ *
* Create an object reference, pte, and store them
* in the table.
*
- * Return: The object reference for the object.
+ * NOTE: Takes ownership of the path name string passed in!
+ *
+ * Return: Non-negative on success, negative on failure
*
* Programmer: REMcG
*
@@ -94,37 +213,21 @@ ref_path_table_lookup(const char *thepath)
*
*-------------------------------------------------------------------------
*/
-ref_path_table_entry_t *
-ref_path_table_put(hid_t obj, const char *path)
+static int
+ref_path_table_put(const char *path, haddr_t objno)
{
- ref_path_table_entry_t *pte;
+ ref_path_node_t *new_node;
- /* look up 'obj'. If already in table, return */
- pte = ref_path_table_lookup(path);
- if (pte != NULL)
- return pte;
+ HDassert(ref_path_table);
+ HDassert(path);
- /* if not found, then make new entry */
+ if((new_node = HDmalloc(sizeof(ref_path_node_t))) == NULL)
+ return(-1);
- pte = (ref_path_table_entry_t *) malloc(sizeof(ref_path_table_entry_t));
- if (pte == NULL)
- /* fatal error? */
- return NULL;
-
- pte->obj = obj;
-
- pte->apath = HDstrdup(path);
-
- if(H5Gget_objinfo(thefile, path, TRUE, &pte->statbuf)<0) {
- /* fatal error? */
- free(pte);
- return NULL;
- }
+ new_node->objno = objno;
+ new_node->path = path;
- pte->next = ref_path_table;
- ref_path_table = pte;
-
- return pte;
+ return(H5SL_insert(ref_path_table, new_node, &(new_node->objno)));
}
/*
@@ -133,7 +236,7 @@ ref_path_table_put(hid_t obj, const char *path)
int xid = 1;
int get_next_xid() {
- return xid++;
+ return xid++;
}
/*
@@ -145,42 +248,33 @@ int get_next_xid() {
haddr_t fake_xid = HADDR_MAX;
haddr_t
get_fake_xid () {
- return (fake_xid--);
+ return (fake_xid--);
}
/*
* for an object that does not have an object id (e.g., soft link),
* create a table entry with a fake object id as the key.
+ *
+ * Assumes 'path' is for an object that is not in the table.
+ *
*/
-ref_path_table_entry_t *
+haddr_t
ref_path_table_gen_fake(const char *path)
{
- ref_path_table_entry_t *pte;
-
- /* look up 'obj'. If already in table, return */
- pte = ref_path_table_lookup(path);
- if (pte != NULL)
- return pte;
+ const char *dup_path;
+ haddr_t fake_objno;
- /* if not found, then make new entry */
+ if((dup_path = HDstrdup(path)) == NULL)
+ return HADDR_UNDEF;
- pte = (ref_path_table_entry_t *) malloc(sizeof(ref_path_table_entry_t));
- if (pte == NULL)
- /* fatal error? */
- return NULL;
-
- pte->obj = (hid_t)-1;
-
- memset(&pte->statbuf,0,sizeof(H5G_stat_t));
- pte->statbuf.objno = get_fake_xid();
+ /* Generate fake ID for string */
+ fake_objno = get_fake_xid();
- pte->apath = HDstrdup(path);
+ /* Insert "fake" object into table (takes ownership of path) */
+ ref_path_table_put(dup_path, fake_objno);
- pte->next = ref_path_table;
- ref_path_table = pte;
-
- return pte;
+ return(fake_objno);
}
/*-------------------------------------------------------------------------
@@ -196,17 +290,18 @@ ref_path_table_gen_fake(const char *path)
*
*-------------------------------------------------------------------------
*/
-char *
-lookup_ref_path(hobj_ref_t ref)
+const char *
+lookup_ref_path(haddr_t ref)
{
- ref_path_table_entry_t *pte = ref_path_table;
+ ref_path_node_t *node;
- while(pte!=NULL) {
- if (ref==pte->statbuf.objno)
- return pte->apath;
- pte = pte->next;
- }
- return NULL;
+ /* Be safer for h5ls */
+ if(!ref_path_table)
+ return(NULL);
+
+ node = H5SL_search(ref_path_table, &ref);
+
+ return(node ? node->path : NULL);
}
/*-------------------------------------------------------------------------
@@ -224,84 +319,44 @@ lookup_ref_path(hobj_ref_t ref)
*-------------------------------------------------------------------------
*/
herr_t
-fill_ref_path_table(hid_t group, const char *name, void UNUSED * op_data)
+fill_ref_path_table(hid_t group, const char *obj_name, void *op_data)
{
- hid_t obj;
- char *tmp;
- size_t tmp_len;
+ const char *obj_prefix = (const char *)op_data;
H5G_stat_t statbuf;
- ref_path_table_entry_t *pte;
- char *thepath;
- H5Gget_objinfo(group, name, FALSE, &statbuf);
- tmp_len = strlen(prefix) + strlen(name) + 2;
- tmp = (char *) malloc(tmp_len);
+ H5Gget_objinfo(group, obj_name, FALSE, &statbuf);
- if (tmp == NULL)
- return FAIL;
+ /* Check if the object is in the path table */
+ if (!ref_path_table_find(statbuf.objno)) {
+ size_t tmp_len;
+ char *thepath;
- thepath = (char *) malloc(tmp_len);
+ /* Compute length for this object's path */
+ tmp_len = HDstrlen(obj_prefix) + HDstrlen(obj_name) + 2;
- if (thepath == NULL) {
- free(tmp);
- return FAIL;
- }
+ /* Allocate room for the path for this object */
+ if ((thepath = (char *) HDmalloc(tmp_len)) == NULL)
+ return FAIL;
- strcpy(tmp, prefix);
-
- strcpy(thepath, prefix);
- strcat(thepath, "/");
- strcat(thepath, name);
-
- switch (statbuf.type) {
- case H5G_DATASET:
- if ((obj = H5Dopen(group, name)) >= 0) {
- pte = ref_path_table_lookup(thepath);
- if (pte == NULL)
- ref_path_table_put(obj, thepath);
- H5Dclose(obj);
- } else {
- error_msg(progname, "unable to get dataset \"%s\"\n", name);
- d_status = EXIT_FAILURE;
- }
- break;
- case H5G_GROUP:
- if ((obj = H5Gopen(group, name)) >= 0) {
- if (prefix_len <= tmp_len) {
- prefix_len = tmp_len + 1;
- prefix = realloc(prefix, prefix_len);
- }
+ /* Build the name for this object */
+ HDstrcpy(thepath, obj_prefix);
+ HDstrcat(thepath, "/");
+ HDstrcat(thepath, obj_name);
- strcat(strcat(prefix, "/"), name);
- pte = ref_path_table_lookup(thepath);
- if (pte == NULL) {
- ref_path_table_put(obj, thepath);
- H5Giterate(obj, ".", NULL, fill_ref_path_table, NULL);
- strcpy(prefix, tmp);
- }
- H5Gclose(obj);
- } else {
- error_msg(progname, "unable to dump group \"%s\"\n", name);
- d_status = EXIT_FAILURE;
- }
- break;
- case H5G_TYPE:
- if ((obj = H5Topen(group, name)) >= 0) {
- pte = ref_path_table_lookup(thepath);
- if (pte == NULL)
- ref_path_table_put(obj, thepath);
- H5Tclose(obj);
- } else {
- error_msg(progname, "unable to get dataset \"%s\"\n", name);
- d_status = EXIT_FAILURE;
- }
- break;
- default:
- break;
+ /* Insert the object into the path table */
+ ref_path_table_put(thepath, statbuf.objno);
+
+ if(statbuf.type == H5G_GROUP) {
+ /* Iterate over objects in this group, using this group's
+ * name as their prefix
+ */
+ if(H5Giterate(group, obj_name, NULL, fill_ref_path_table, thepath) < 0) {
+ error_msg(progname, "unable to dump group \"%s\"\n", obj_name);
+ d_status = EXIT_FAILURE;
+ }
+ }
}
- free(tmp);
- free(thepath);
return 0;
}