diff options
-rw-r--r-- | src/H5Bprivate.h | 2 | ||||
-rw-r--r-- | src/H5G.c | 248 | ||||
-rw-r--r-- | src/H5Gnode.c | 98 | ||||
-rw-r--r-- | src/H5Gprivate.h | 32 |
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)) @@ -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); |