summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/H5Bprivate.h2
-rw-r--r--src/H5G.c248
-rw-r--r--src/H5Gnode.c98
-rw-r--r--src/H5Gprivate.h32
4 files changed, 341 insertions, 39 deletions
diff --git a/src/H5Bprivate.h b/src/H5Bprivate.h
index b6e31a8..3a029e4 100644
--- a/src/H5Bprivate.h
+++ b/src/H5Bprivate.h
@@ -19,7 +19,7 @@
#include "H5Bproto.h" /*API prototypes */
-
+#include "H5Fprivate.h"
#define H5B_MAGIC "TREE" /* tree node magic number */
#define H5B_HDR_SIZE(F) (8+2*H5F_SIZEOF_OFFSET(F))
diff --git a/src/H5G.c b/src/H5G.c
index 1af38f3..3c1f21a 100644
--- a/src/H5G.c
+++ b/src/H5G.c
@@ -18,13 +18,256 @@
#include "hdf5.h"
+#define H5G_INIT_HEAP 8192
+
/* Packages needed by this file... */
+#include "H5Bprivate.h"
#include "H5Gprivate.h"
+#include "H5Hprivate.h"
+#include "H5MMprivate.h"
/* PRIVATE PROTOTYPES */
/*-------------------------------------------------------------------------
+ * Function: H5G_new
+ *
+ * Purpose: Creates a new empty symbol table (object header, name heap,
+ * and B-tree). The caller can specify an initial size for the
+ * name heap. If no size is specified then a default heap is
+ * created when the first symbol is added to the table.
+ *
+ * The B-tree is created when the first symbol is added to
+ * the table.
+ *
+ * In order for the B-tree to operate correctly, the first
+ * item in the heap is the empty string, and must appear at
+ * heap offset zero.
+ *
+ * Return: Success: Address of new symbol table.
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Aug 1 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+haddr_t
+H5G_new (hdf5_file_t *f, size_t init)
+{
+ haddr_t addr; /*symtab object header */
+ haddr_t heap; /*private heap */
+ off_t name; /*offset of "" name */
+
+ /* Create symbol table private heap */
+ if (init>0) {
+ if ((heap = H5H_new (f, init))<0) return -1;
+ if ((name = H5H_insert (f, heap, 1, "")<0)) return -1;
+ assert (0==name); /*or B-tree's won't work*/
+ } else {
+ heap = 0; /*we'll create it later*/
+ }
+
+ /* Create symbol table object header */
+ addr = not_implemented_yet__create_object_header();
+ if (addr<0) return -1;
+
+ /* Insert the heap and B-tree addresses */
+ not_implemented_yet__insert_symtab_message (f, addr, heap, 0);
+
+ return addr;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_find
+ *
+ * Purpose: Finds a symbol named NAME in the symbol table whose address
+ * is ADDR and returns a copy of the symbol table entry through
+ * the ENTRY argument.
+ *
+ * Return: Success: Address corresponding to the name.
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Aug 1 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+haddr_t
+H5G_find (hdf5_file_t *f, haddr_t addr, const char *name, H5G_entry_t *entry)
+{
+ H5G_node_ud1_t udata; /*data to pass through B-tree */
+ haddr_t btree; /*address of B-tree */
+
+ /* set up the udata */
+ not_implemented_yet__get_symtab_message (f, addr, &(udata.heap), &btree);
+ if (btree<=0 || udata.heap<=0) return -1; /*empty symbol table*/
+ udata.operation = H5G_OPER_FIND;
+ udata.name = name;
+
+ /* search the B-tree */
+ if (H5B_find (f, H5B_SNODE, btree, &udata)<0) return -1;
+
+ /* return the result */
+ if (entry) *entry = udata.entry;
+ return udata.entry.header;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_modify
+ *
+ * Purpose: Modifies the entry for an existing symbol. The name of the
+ * symbol is NAME in the symbol table whose address is ADDR in
+ * file F. ENTRY is the new symbol table entry to use for the
+ * symbol.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Aug 1 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_modify (hdf5_file_t *f, haddr_t addr, const char *name, H5G_entry_t *entry)
+{
+ H5G_node_ud1_t udata; /*data to pass through B-tree */
+ haddr_t btree; /*address of B-tree */
+
+ /* set up the udata */
+ not_implemented_yet__get_symtab_message (f, addr, &(udata.heap), &btree);
+ if (btree<=0 || udata.heap<=0) return -1; /*empty symbol table*/
+ udata.operation = H5G_OPER_MODIFY;
+ udata.name = name;
+ udata.entry = *entry;
+
+ /* search and modify the B-tree */
+ if (H5B_find (f, H5B_SNODE, btree, &udata)<0) return -1;
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_insert
+ *
+ * Purpose: Insert a new symbol into the table whose address is ADDR in
+ * file F. The name of the new symbol is NAME and its symbol
+ * table entry is ENTRY.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Aug 1 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_insert (hdf5_file_t *f, haddr_t addr, const char *name, H5G_entry_t *entry)
+{
+ haddr_t btree; /*file address of B-tree */
+ H5G_node_ud1_t udata; /*data to pass through B-tree */
+ off_t offset; /*offset of name within heap */
+
+ /* make sure we have a B-tree and a heap */
+ not_implemented_yet__get_symtab_message (f, addr, &btree, &(udata.heap));
+ if (btree<=0 || udata.heap<=0) {
+ if (btree<=0 &&
+ (btree = H5B_new (f, H5B_SNODE, sizeof(H5G_node_key_t)))<0) {
+ return -1;
+ }
+ if (udata.heap<=0) {
+ udata.heap = H5H_new (f, MAX(strlen(name)+1, H5G_INIT_HEAP));
+ if (udata.heap<0) return -1;
+ if (0!=(offset = H5H_insert (f, udata.heap, 1, ""))) return -1;
+ }
+ not_implemented_yet__update_symtab_message (f, addr, udata.heap, btree);
+ }
+
+ /* initialize data to pass through B-tree */
+ udata.name = name;
+ udata.entry = *entry;
+ if (H5B_insert (f, H5B_SNODE, btree, &udata)<0) return -1;
+
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_list
+ *
+ * Purpose: Returns a list of all the symbols in a symbol table.
+ * The caller allocates an array of pointers which this
+ * function will fill in with malloc'd names. The caller
+ * also allocates an array of symbol table entries which will
+ * be filled in with data from the symbol table. Each of these
+ * arrays should have at least MAXENTRIES elements.
+ *
+ * Return: Success: The total number of symbols in the
+ * symbol table. This may exceed MAXENTRIES,
+ * but at most MAXENTRIES values are copied
+ * into the NAMES and ENTRIES arrays.
+ *
+ * Failure: -1, the pointers in NAMES are undefined but
+ * no memory is allocated. The values in
+ * ENTRIES are undefined.
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Aug 1 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+intn
+H5G_list (hdf5_file_t *f, haddr_t addr, int maxentries,
+ char *names[], H5G_entry_t entries[])
+{
+ H5G_node_list_t udata;
+ haddr_t btree;
+ intn i;
+
+ not_implemented_yet__get_symtab_message (f, addr, &btree, &(udata.heap));
+ if (btree<=0 || udata.heap<=0) return 0; /*empty directory*/
+
+ udata.entry = entries;
+ udata.name = names;
+ udata.maxentries = maxentries;
+ udata.nsyms = 0;
+
+ if (names) HDmemset (names, 0, maxentries);
+ if (H5B_list (f, H5B_SNODE, btree, &udata)<0) {
+ if (names) {
+ for (i=0; i<maxentries; i++) H5MM_xfree (names[i]);
+ }
+ return -1;
+ }
+
+ return udata.nsyms;
+}
+
+
+/*-------------------------------------------------------------------------
* Function: H5G_decode_vec
*
* Purpose: Same as H5G_decode() except it does it for an array of
@@ -194,3 +437,8 @@ H5G_encode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent)
return 0;
}
+
+herr_t not_implemented_yet__create_object_header (void) {return FAIL;}
+herr_t not_implemented_yet__insert_symtab_message (hdf5_file_t* f, haddr_t addr, haddr_t heap, haddr_t btree) {return FAIL;}
+herr_t not_implemented_yet__get_symtab_message (hdf5_file_t *f, haddr_t addr, haddr_t *heap, haddr_t *btree) {return FAIL;}
+herr_t not_implemented_yet__update_symtab_message (hdf5_file_t *f, haddr_t addr, haddr_t heap, haddr_t btree) {return FAIL;}
diff --git a/src/H5Gnode.c b/src/H5Gnode.c
index 53b28c6..52638eb 100644
--- a/src/H5Gnode.c
+++ b/src/H5Gnode.c
@@ -59,7 +59,7 @@ static const H5AC_class_t H5AC_SNODE[1] = {{
}};
/* H5G inherits B-tree like properties from H5B */
-static const H5B_class_t H5B_SNODE[1] = {{
+const H5B_class_t H5B_SNODE[1] = {{
0, /*id */
64, /*k */
sizeof (H5G_node_key_t), /*sizeof_nkey */
@@ -385,6 +385,11 @@ H5G_node_cmp (hdf5_file_t *f, void *_lt_key, void *_udata, void *_rt_key)
* structure which contains the symbol name on function
* entry.
*
+ * If the operation flag in UDATA is H5G_OPER_FIND, then
+ * the entry is copied from the symbol table to the UDATA
+ * entry field. Otherwise the entry is copied from the
+ * UDATA entry field to the symbol table.
+ *
* Return: Success: 0 if found and data returned through the
* UDATA pointer.
*
@@ -428,7 +433,23 @@ H5G_node_found (hdf5_file_t *f, haddr_t addr, void *_lt_key, void *_udata,
}
if (cmp) return -1;
- udata->entry = sn->entry[idx];
+ switch (udata->operation) {
+ case H5G_OPER_FIND:
+ /*
+ * The caller is querying the symbol entry.
+ */
+ udata->entry = sn->entry[idx];
+ break;
+
+ case H5G_OPER_MODIFY:
+ /*
+ * The caller is modifying the symbol entry.
+ */
+ sn->entry[idx] = udata->entry;
+ sn->dirty += 1;
+ break;
+ }
+
return 0;
}
@@ -616,46 +637,59 @@ static herr_t
H5G_node_list (hdf5_file_t *f, haddr_t addr, void *_udata)
{
H5G_node_list_t *udata = (H5G_node_list_t *)_udata;
- H5G_entry_t *ent;
- intn i, nsyms;
- const char *s;
- H5G_node_t *sn;
+ H5G_node_t *sn = H5AC_find (f, H5AC_SNODE, addr, NULL);
+ off_t *offsets = NULL;
+ intn nsyms, i;
+ const char *s;
- /*
- * Read the symbol table and save the entry info. We save it
- * in a separate buffer if names are requested because the name
- * lookup may invalidate the symbol table.
- */
- sn = H5AC_find (f, H5AC_SNODE, addr, NULL);
if (!sn) return -1;
nsyms = sn->nsyms;
- if (udata->name) {
- ent = H5MM_xmalloc (nsyms * sizeof(H5G_entry_t));
- HDmemcpy (ent, sn->entry, nsyms*sizeof(H5G_entry_t));
- sn = NULL;
- } else {
- ent = sn->entry;
+
+ /*
+ * If we've already overflowed the user-supplied buffer, then just
+ * keep track of how many names we've seen and don't bother doing
+ * anything else.
+ */
+ if (udata->nsyms >= udata->maxentries) {
+ udata->nsyms += nsyms;
+ return 0;
}
/*
- * Gather the info.
+ * Save the name offsets because looking up the name may cause the
+ * symbol table node to be preempted from the cache.
*/
- if (udata->name || udata->entry) {
- for (i=0; i<nsyms && udata->nused<udata->nentries; i++) {
- if (udata->name) {
- s = H5H_peek (f, udata->heap, ent[i].name_off);
- udata->name[udata->nused] = H5MM_xstrdup (s);
- }
- if (udata->entry) {
- udata->entry[udata->nused] = ent[i];
- }
- udata->nused += 1;
+ if (udata->entry) {
+ for (i=0; i<nsyms && udata->nsyms+i<udata->maxentries; i++) {
+ udata->entry[udata->nsyms+i] = sn->entry[i];
+ }
+ } else if (udata->name) {
+ offsets = H5MM_xmalloc (nsyms * sizeof(off_t));
+ for (i=0; i<nsyms && udata->nsyms+i<udata->maxentries; i++) {
+ offsets[i] = sn->entry[i].name_off;
}
- } else {
- udata->nused += sn->nsyms;
}
- if (!sn) H5MM_xfree (ent);
+ /*
+ * Now strdup() the names.
+ */
+ if (udata->name && udata->entry) {
+ for (i=0; i<nsyms && udata->nsyms+i<udata->maxentries; i++) {
+ s = H5H_peek (f, udata->heap, udata->entry[udata->nsyms+i].name_off);
+ udata->name[udata->nsyms+i] = H5MM_xstrdup (s);
+ }
+ } else if (udata->name) {
+ for (i=0; i<nsyms && udata->nsyms+i<udata->maxentries; i++) {
+ s = H5H_peek (f, udata->heap, offsets[i]);
+ udata->name[udata->nsyms+i] = H5MM_xstrdup (s);
+ }
+ offsets = H5MM_xfree (offsets);
+ }
+
+ /*
+ * Update the number of symbols.
+ */
+ udata->nsyms += nsyms;
return 0;
}
diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h
index 4b7930d..73a06ee 100644
--- a/src/H5Gprivate.h
+++ b/src/H5Gprivate.h
@@ -17,9 +17,12 @@
#ifndef _H5Gprivate_H
#define _H5Gprivate_H
-#include "H5Gproto.h" /*include public declarations */
+/*include public declarations */
+#include "H5Gproto.h"
-#include "H5Fprivate.h" /*include packages needed by this header*/
+/*include packages needed by this header*/
+#include "H5Bprivate.h"
+#include "H5Fprivate.h"
#define H5G_NODE_MAGIC "SNOD" /*symbol table node magic number */
#define H5G_NODE_VERS 1 /*symbol table node version number */
@@ -83,6 +86,11 @@ typedef struct H5G_node_key_t {
off_t offset; /*offset into heap for name */
} H5G_node_key_t;
+typedef enum H5G_oper_t {
+ H5G_OPER_FIND =0, /*find a symbol */
+ H5G_OPER_MODIFY =1 /*modify a symbol */
+} H5G_oper_t;
+
/*
* Data exchange structure for symbol table nodes. This structure is
* passed through the B-link tree layer to the methods for the objects
@@ -91,10 +99,11 @@ typedef struct H5G_node_key_t {
typedef struct H5G_node_ud1_t {
/* downward */
- char *name; /*points to temporary memory */
+ H5G_oper_t operation; /*what operation to perform */
+ const char *name; /*points to temporary memory */
haddr_t heap; /*symbol table heap address */
- /* upward */
+ /* upward for H5G_OPER_FIND, downward for H5G_OPER_MODIFY */
H5G_entry_t entry; /*symbol table entry */
} H5G_node_ud1_t;
@@ -104,17 +113,28 @@ typedef struct H5G_node_list_t {
/* downward */
H5G_entry_t *entry; /*array of entries, alloc'd by caller */
char **name; /*array of string ptrs, allocd by caller*/
- intn nentries; /*size of the ADDR and NAME arrays */
+ intn maxentries; /*size of the ADDR and NAME arrays */
haddr_t heap; /*heap address */
/* upward */
- intn nused; /*num. symbols processed */
+ intn nsyms; /*num. symbols processed */
} H5G_node_list_t;
+extern const H5B_class_t H5B_SNODE[1];
+
/*
* Library prototypes...
*/
+haddr_t H5G_new (hdf5_file_t *f, size_t init);
+haddr_t H5G_find (hdf5_file_t *f, haddr_t addr, const char *name,
+ H5G_entry_t *entry);
+herr_t H5G_modify (hdf5_file_t *f, haddr_t addr, const char *name,
+ H5G_entry_t *entry);
+herr_t H5G_insert (hdf5_file_t *f, haddr_t addr, const char *name,
+ H5G_entry_t *entry);
+intn H5G_list (hdf5_file_t *f, haddr_t addr, int maxentries,
+ char *names[], H5G_entry_t entries[]);
herr_t H5G_decode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent);
herr_t H5G_decode_vec (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent, intn n);
herr_t H5G_encode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent);