summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobb Matzke <matzke@llnl.gov>1997-08-12 22:44:46 (GMT)
committerRobb Matzke <matzke@llnl.gov>1997-08-12 22:44:46 (GMT)
commitfb947c34b142578774d5bb657c0b3e2a9b4781c7 (patch)
treec695cac8789bbe5fc92a5324e3027856bf3858bc
parent326981f421b993815657daecc8b37bd732513d82 (diff)
downloadhdf5-fb947c34b142578774d5bb657c0b3e2a9b4781c7.zip
hdf5-fb947c34b142578774d5bb657c0b3e2a9b4781c7.tar.gz
hdf5-fb947c34b142578774d5bb657c0b3e2a9b4781c7.tar.bz2
[svn-r25] ./src/H5AC.c
We sort the cache before a complete flush because it might be more efficient to write things back to disk in order of increasing address. If you want the old way then undef the SORT_BY_ADDR constant at the top of H5AC.c I haven't determined which systems and I/O libraries this helps or hurts. (This is currently off because of a bug I need to track down that causes qsort() to run for a really long time). ./src/H5B.c Fixed a couple more bugs. ./src/H5Eprivate.h ./src/H5Eproto.h Added major H5E_DIRECTORY and minor H5E_EXISTS, H5E_COMPLEN. ./src/H5G.c Added directory-aware functions. The heap and B-tree are created when a directory is created instead of when the first symbol is added. This simplifies symbol table entry caching for the directory since the cached value never changes now. ./src/H5Gnode.c ./src/H5Gprivate.h Fine tuned the B-tree K values for symbol tables assuming an average number of symbols is about 100 per directory. The tuning minimizes storage space. Fixed a return value in H5G_node_cmp(). ./src/H5H.c ./src/H5Hprivate.h Moved some macros the the header file. ./src/H5O.c ./src/H5Ocont.c ./src/H5Onull.c ./src/H5Ostab.c Changed the arguments for the decode method for messages. The second argument is the raw message size. Added a class variable for native message size. Added H5O_reset() to free memory used internally by a message. ./src/H5Oname.c NEW ./src/H5Oprivate.h ./src/Makefile The object name message. ./src/hdf5port.h Added defn for HDstrdup()
-rw-r--r--src/H5AC.c79
-rw-r--r--src/H5B.c9
-rw-r--r--src/H5Eprivate.h3
-rw-r--r--src/H5Eproto.h9
-rw-r--r--src/H5G.c643
-rw-r--r--src/H5Gnode.c4
-rw-r--r--src/H5Gprivate.h23
-rw-r--r--src/H5H.c10
-rw-r--r--src/H5Hprivate.h11
-rw-r--r--src/H5O.c61
-rw-r--r--src/H5Ocont.c13
-rw-r--r--src/H5Oname.c283
-rw-r--r--src/H5Onull.c3
-rw-r--r--src/H5Oprivate.h20
-rw-r--r--src/H5Ostab.c16
-rw-r--r--src/Makefile6
-rw-r--r--src/hdf5port.h2
17 files changed, 1080 insertions, 115 deletions
diff --git a/src/H5AC.c b/src/H5AC.c
index 41e2f88..ce8415e 100644
--- a/src/H5AC.c
+++ b/src/H5AC.c
@@ -27,9 +27,16 @@
#include "H5ACprivate.h"
#include "H5MMprivate.h"
+/*
+ * Sorting the cache by address before flushing is sometimes faster
+ * than flushing in cache order.
+ */
+/* #define SORT_BY_ADDR */
+
#define PABLO_MASK H5AC_mask
static int interface_initialize_g = FALSE; /*initialized?*/
+static H5AC_cache_t *current_cache_g = NULL; /*for sorting */
/*-------------------------------------------------------------------------
@@ -200,6 +207,41 @@ H5AC_find_f (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr,
/*-------------------------------------------------------------------------
+ * Function: H5AC_compare
+ *
+ * Purpose: Compare two hash entries by address. Unused entries are
+ * all equal to one another and greater than all used entries.
+ *
+ * Return: Success: -1, 0, 1
+ *
+ * Failure: never fails
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Aug 12 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+H5AC_compare (const void *_a, const void *_b)
+{
+ intn a = *((const intn *)_a);
+ intn b = *((const intn *)_b);
+
+ assert (current_cache_g);
+
+ if (NULL==current_cache_g[a].type) return 1;
+ if (NULL==current_cache_g[b].type) return -1;
+
+ if (current_cache_g[a].addr < current_cache_g[b].addr) return -1;
+ if (current_cache_g[a].addr > current_cache_g[b].addr) return 1;
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------
* Function: H5AC_flush
*
* Purpose: Flushes (and destroys if DESTROY is non-zero) the specified
@@ -226,6 +268,8 @@ H5AC_flush (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr,
uintn i = H5AC_HASH(addr);
herr_t status;
herr_t (*flush)(hdf5_file_t*,hbool_t,haddr_t,void*)=NULL;
+ H5AC_cache_t *slot;
+ intn *map=NULL;
FUNC_ENTER (H5AC_flush, NULL, FAIL);
@@ -233,22 +277,43 @@ H5AC_flush (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr,
assert (f->cache);
if (!type || 0==addr) {
+
+#ifdef SORT_BY_ADDR
+ /*
+ * Sort the cache entries by address since flushing them in
+ * ascending order by address may be much more efficient.
+ */
+ map = H5MM_xmalloc (H5AC_NSLOTS * sizeof(intn));
+ for (i=0; i<H5AC_NSLOTS; i++) map[i] = i;
+ assert (NULL==current_cache_g);
+ current_cache_g = f->cache;
+ qsort (map, H5AC_NSLOTS, sizeof(intn), H5AC_compare);
+ current_cache_g = NULL;
+#endif
+
/*
* Look at all cache entries.
*/
for (i=0; i<H5AC_NSLOTS; i++) {
- if (NULL==f->cache[i].type) continue;
- if ((!type || type==f->cache[i].type) &&
- (0==addr || addr==f->cache[i].addr)) {
- flush = f->cache[i].type->flush;
- status = (flush)(f, destroy, f->cache[i].addr,
- f->cache[i].thing);
+#ifdef SORT_BY_ADDR
+ slot = f->cache + map[i];
+ if (NULL==slot->type) break; /*the rest are empty*/
+#else
+ slot = f->cache + i;
+ if (NULL==slot->type) continue;
+#endif
+ if ((!type || type==slot->type) &&
+ (0==addr || addr==slot->addr)) {
+ flush = slot->type->flush;
+ status = (flush)(f, destroy, slot->addr, slot->thing);
if (status<0) {
+ map = H5MM_xfree (map);
HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL);
}
- if (destroy) f->cache[i].type = NULL;
+ if (destroy) slot->type = NULL;
}
}
+ map = H5MM_xfree (map);
} else if (f->cache[i].type==type && f->cache[i].addr==addr) {
/*
diff --git a/src/H5B.c b/src/H5B.c
index d700a7c..21dc174 100644
--- a/src/H5B.c
+++ b/src/H5B.c
@@ -113,7 +113,7 @@
#define PABLO_MASK H5B_mask
-#define BOUND(MIN,X,MAX) ((MIN)<(X)?(MIN):((MAX)>(X)?(MAX):(X)))
+#define BOUND(MIN,X,MAX) ((X)<(MIN)?(MIN):((X)>(MAX)?(MAX):(X)))
#define false 0
#define true 1
@@ -173,7 +173,6 @@ H5B_new (hdf5_file_t *f, const H5B_class_t *type)
*/
assert (f);
assert (type);
- assert (sizeof_rkey>0);
/*
* Allocate file and memory data structures.
@@ -608,7 +607,7 @@ H5B_split (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, intn anchor)
*/
memcpy (bt->page + H5B_SIZEOF_HDR(f),
old->page + H5B_SIZEOF_HDR(f) + delta*recsize,
- type->k * recsize);
+ type->k * recsize + bt->sizeof_rkey);
memcpy (bt->native,
old->native + delta * type->sizeof_nkey,
(type->k+1) * type->sizeof_nkey);
@@ -626,7 +625,7 @@ H5B_split (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, intn anchor)
}
} else {
bt->key[i].dirty = 0;
- bt->key[i].rkey = bt->native + offset;
+ bt->key[i].rkey = bt->page + offset;
bt->key[i].nkey = NULL;
}
@@ -642,7 +641,7 @@ H5B_split (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, intn anchor)
/*
* Truncate the old node.
*/
- delta = H5B_ANCHOR_LT ? 0 : type->k;
+ delta = H5B_ANCHOR_LT==anchor ? 0 : type->k;
old->dirty += 1;
old->ndirty = BOUND (0, old->ndirty-delta, type->k);
old->nchildren = type->k;
diff --git a/src/H5Eprivate.h b/src/H5Eprivate.h
index 4a6ad8f..c8678cc 100644
--- a/src/H5Eprivate.h
+++ b/src/H5Eprivate.h
@@ -62,6 +62,7 @@ static const hdf_maj_error_messages_t hdf_maj_error_messages[] =
{H5E_SYM, "Symbol Table"},
{H5E_HEAP, "Heap"},
{H5E_OHDR, "Object Header"},
+ {H5E_DIRECTORY, "Directory"},
};
typedef struct
@@ -96,6 +97,7 @@ static const hdf_min_error_messages_t hdf_min_error_messages[] =
{H5E_CANTFLUSH, "Can't flush object from cache"},
{H5E_CANTLOAD, "Can't load object into cache"},
{H5E_NOTFOUND, "Object not found"},
+ {H5E_EXISTS, "Object already exists"},
{H5E_CANTENCODE, "Can't encode value"},
{H5E_CANTDECODE, "Can't decode value"},
{H5E_CANTSPLIT, "Can't split node"},
@@ -105,6 +107,7 @@ static const hdf_min_error_messages_t hdf_min_error_messages[] =
{H5E_VERSION, "Wrong version number"},
{H5E_ALIGNMENT, "Alignment error"},
{H5E_BADMESG, "Unrecognized message"},
+ {H5E_COMPLEN, "Name component is too long"},
};
/* We use a stack to hold the errors plus we keep track of the function,
diff --git a/src/H5Eproto.h b/src/H5Eproto.h
index 187737f..c61704c 100644
--- a/src/H5Eproto.h
+++ b/src/H5Eproto.h
@@ -81,7 +81,8 @@ typedef enum
H5E_BTREE, /* B-Tree Node */
H5E_SYM, /* Symbol Table */
H5E_HEAP, /* Heap */
- H5E_OHDR /* Object Header */
+ H5E_OHDR, /* Object Header */
+ H5E_DIRECTORY /* Directory */
}
hdf_maj_err_code_t;
@@ -127,6 +128,7 @@ typedef enum
/* B-tree related errors */
H5E_NOTFOUND, /* Object not found */
+ H5E_EXISTS, /* Object already exists */
H5E_CANTENCODE, /* Can't encode value */
H5E_CANTDECODE, /* Can't decode value */
H5E_CANTSPLIT, /* Can't split node */
@@ -137,7 +139,10 @@ typedef enum
H5E_LINKCOUNT, /* Bad object header link count */
H5E_VERSION, /* Wrong version number */
H5E_ALIGNMENT, /* Alignment error */
- H5E_BADMESG /* Unrecognized message */
+ H5E_BADMESG, /* Unrecognized message */
+
+ /* Directory related errors */
+ H5E_COMPLEN /* Name component is too long */
}
hdf_min_err_code_t;
diff --git a/src/H5G.c b/src/H5G.c
index 458792b..45aada7 100644
--- a/src/H5G.c
+++ b/src/H5G.c
@@ -49,15 +49,570 @@ static intn interface_initialize_g = FALSE;
/*-------------------------------------------------------------------------
+ * Function: H5G_component
+ *
+ * Purpose: Returns the pointer to the first component of the
+ * specified name by skipping leading slashes. Returns
+ * the size in characters of the component through SIZE_P not
+ * counting leading slashes or the null terminator.
+ *
+ * Return: Success: Ptr into NAME.
+ *
+ * Failure: Ptr to the null terminator of NAME.
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Aug 11 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static const char *
+H5G_component (const char *name, size_t *size_p)
+{
+ assert (name);
+
+ while ('/'==*name) name++;
+ if (size_p) *size_p = strcspn (name, "/");
+ return name;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_basename
+ *
+ * Purpose: Returns a pointer into NAME for the start of the last
+ * component of NAME. On return, the optional SIZE_P is
+ * initialized to point to the size of the base name not
+ * counting trailing slashes or the null character.
+ *
+ * Return: Success: Ptr to base name within NAME with SIZE_P
+ * pointing to the number of characters in the
+ * base name.
+ *
+ * Failure: Ptr to the null terminator of NAME.
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Aug 11 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static const char *
+H5G_basename (const char *name, size_t *size_p)
+{
+ const char *s;
+
+ assert (name);
+
+ s = name + strlen(name);
+ while (s>name && '/'==s[-1]) --s; /*skip past trailing slashes*/
+ while (s>name && '/'!=s[-1]) --s; /*skip past base name*/
+
+ /*
+ * If the input was the name of the root directory `/' (or
+ * equivalent) then return the null string.
+ */
+ if ('/'==*s) {
+ if (size_p) *size_p = 0;
+ return s + strlen(s); /*null terminator*/
+ }
+
+ if (size_p) *size_p = strcspn (s, "/");
+ return s;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_namei
+ *
+ * Purpose: Given a name (absolute or relative) return the symbol table
+ * entry for that name and for the directory that contains the
+ * base name. These entries (DIR_ENT and BASE_ENT) are returned
+ * through memory passed into the function by the caller. Either
+ * or both pointers may be null. Absolute names are looked up
+ * relative to the root directory of file F while relative
+ * names are traversed beginning at the CWD argument.
+ *
+ * Consecutive slash characters are treated like single
+ * slash characters. Trailing slashes are ignored. The
+ * component `.' is recognized as the current directory
+ * during the traversal (initially CWD), but the component
+ * `..' is not internally recognized (it is recognized if
+ * such a name appears in the symbol table).
+ *
+ * As a special case, if the NAME is the string `/' (or
+ * equivalent) then DIR_ENT and BASE_ENT are both initialized
+ * to the contents of the root symbol table entry. However,
+ * the contents of the root symbol table entry may be
+ * uninitialized.
+ *
+ * If the name cannot be fully resolved, then REST will
+ * point to the part of NAME where the traversal failed
+ * (REST will always point to a relative name) and BASE_ENT
+ * will not be initialized. DIR_ENT will be initialized with
+ * information about the directory (or other object) at which
+ * the traversal failed. However, if the name can be fully
+ * resolved, then REST points to the null terminator of NAME.
+ *
+ * Return: Success: SUCCEED if the name can be fully
+ * resolved.
+ *
+ * Failure: FAIL if something bad happened (REST and
+ * DIR_ENT have undefined values).
+ *
+ * -2 if the name could not be fully resolved
+ * (REST and DIR_ENT are initialized).
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Aug 11 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5G_namei (hdf5_file_t *f, H5G_entry_t *cwd, const char *name,
+ const char **rest, H5G_entry_t *dir_ent, H5G_entry_t *base_ent)
+{
+ H5G_entry_t ent[2];
+ H5G_entry_t *tmp, *dir, *base; /*ptrs to DIR and BASE entries */
+ size_t nchars; /*component name length */
+ char comp[1024]; /*component name buffer */
+
+ FUNC_ENTER (H5G_namei, NULL, FAIL);
+
+ /* check args */
+ assert (f);
+ assert (f->root_sym);
+ assert (name && *name);
+ assert (cwd || '/'==*name);
+
+ /* starting point */
+ dir = ent+0;
+ base = ent+1;
+ if ('/'==*name) {
+ ent[0] = ent[1] = *(f->root_sym);
+ } else {
+ ent[0] = ent[1] = *cwd;
+ }
+
+ /* traverse the name */
+ while ((name=H5G_component (name, &nchars)) && *name) {
+
+ /*
+ * The special name `.'.
+ */
+ if ('.'==name[0] && !name[1]) continue;
+
+ /*
+ * Advance.
+ */
+ tmp=dir; dir=base; base=tmp; /*swap*/
+ if (rest) *rest = name;
+
+ /*
+ * Copy the component name into a null-terminated buffer so
+ * we can pass it down to the other symbol table functions.
+ */
+ if (nchars+1 > sizeof(comp)) {
+ /* component name is too long */
+ if (dir_ent) *dir_ent = *dir;
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_COMPLEN, -2);
+ }
+ HDmemcpy (comp, name, nchars);
+ comp[nchars] = '\0';
+
+ /*
+ * Look for the component in the current symbol table.
+ */
+ if (H5G_stab_find (f, dir, comp, base)<0) {
+ /* component not found */
+ if (dir_ent) *dir_ent = *dir;
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, -2);
+ }
+
+ /* next component */
+ name += nchars;
+ }
+
+ /* output parameters */
+ if (rest) *rest = name; /*final null*/
+ if (dir_ent) *dir_ent = *dir;
+ if (base_ent) *base_ent = *base;
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_mkroot
+ *
+ * Purpose: Creates the root directory if it doesn't exist; otherwise
+ * nothing happens. If the root symbol table previously
+ * pointed to something other than a directory, then that
+ * object is made a member of the root directory and is
+ * given a name corresponding to the object name message.
+ * If the root object doesn't have an object name message
+ * then the name `Root Object' is used.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Aug 11 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_mkroot (hdf5_file_t *f, size_t size_hint)
+{
+ H5O_stab_t stab; /*symbol table message */
+ H5O_name_t name; /*object name message */
+ H5G_entry_t root; /*old root entry */
+ const char *root_name=NULL; /*name of old root object */
+
+ FUNC_ENTER (H5G_mkroot, NULL, FAIL);
+
+ /*
+ * Is there already a root object that needs to move into the new
+ * root symbol table?
+ */
+ name.s = NULL;
+ if (f->root_sym->header>0) {
+ if (H5O_read (f, f->root_sym->header, f->root_sym, H5O_STAB, 0, &stab)) {
+ /* root directory already exists */
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_EXISTS, FAIL);
+ } else if (H5O_read (f, f->root_sym->header, f->root_sym, H5O_NAME,
+ 0, &name)) {
+ root = *(f->root_sym);
+ root_name = name.s; /*dont reset name until root_name is done*/
+ } else {
+ root = *(f->root_sym);
+ root_name = "Root Object";
+ }
+ }
+
+ /*
+ * Create the root directory.
+ */
+ if (H5G_stab_new (f, f->root_sym, size_hint)<0) {
+ H5O_reset (H5O_NAME, &name);
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL); /*can't create dir*/
+ }
+
+ /*
+ * Insert the old root object.
+ */
+ if (root_name) {
+ if (H5G_stab_insert (f, f->root_sym, root_name, &root)) {
+ /* can't insert old root object in new root directory */
+ H5O_reset (H5O_NAME, &name);
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL);
+ }
+ H5O_reset (H5O_NAME, &name);
+ }
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_new
+ *
+ * Purpose: Creates a new empty directory with the specified name. The
+ * name is either an absolute name or is relative to the
+ * directory whose symbol table entry is CWD. On return, the
+ * optional DIR_ENT pointer is initialized with the symbol
+ * table entry for the new directory's parent and ENT will
+ * contain the symbol table entry for the new directory.
+ *
+ * Do not use this function to create the root symbol table
+ * since it is a special case. Use H5G_mkroot() instead.
+ * Creating `/' with this function will return failure.
+ *
+ * Return: Success: SUCCEED, if DIR_ENT is not the null pointer
+ * then it will be initialized with the
+ * symbol table entry for the new directory.
+ *
+ * Failure: FAIL, the memory pointed to by CWD is
+ * not modified.
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Aug 11 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_new (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
+ const char *name, size_t size_hint, H5G_entry_t *ent)
+{
+ const char *rest=NULL;
+ H5G_entry_t _parent, _child;
+ herr_t status;
+ char _comp[1024];
+ size_t nchars;
+
+ FUNC_ENTER (H5G_new, NULL, FAIL);
+
+ /* check args */
+ assert (f);
+ assert (name && *name);
+ assert (cwd || '/'==*name);
+ if (!dir_ent) dir_ent = &_parent;
+ if (!ent) ent = &_child;
+
+ /* lookup name */
+ status = H5G_namei (f, cwd, name, &rest, dir_ent, NULL);
+ if (status<0 && !rest) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL); /*lookup failed*/
+ } else if (0==status) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_EXISTS, FAIL); /*already exists*/
+ }
+ H5ECLEAR; /*it's OK that we didn't find it*/
+
+ /* should be one null-terminated component left */
+ rest = H5G_component (rest, &nchars);
+ assert (rest && *rest);
+ if (rest[nchars]) {
+ if (H5G_component (rest+nchars, NULL)) {
+ /* missing component */
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, FAIL);
+ } else if (nchars+1 > sizeof _comp) {
+ /* component name is too long */
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_COMPLEN, FAIL);
+ } else {
+ /* null terminate */
+ memcpy (_comp, rest, nchars);
+ _comp[nchars] = '\0';
+ rest = _comp;
+ }
+ }
+
+ /* create directory */
+ if (H5G_stab_new (f, ent, size_hint)<0) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL); /*can't create dir*/
+ }
+
+ /* insert child name into parent */
+ if (H5G_stab_insert (f, dir_ent, rest, ent)<0) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL); /*can't insert*/
+ }
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_find
+ *
+ * Purpose: Finds an object with the specified NAME in file F. If the
+ * name is relative then it is interpretted relative to CWD,
+ * a symbol table entry for a symbol table. On successful return,
+ * DIR_ENT (if non-null) will be initialized with the symbol table
+ * information for the directory in which the object appears
+ * and ENT will be initialized with the symbol table entry for
+ * the object.
+ *
+ * ENT is optional when the caller is interested only in the
+ * existence of the object.
+ *
+ * Return: Success: SUCCEED with DIR_ENT and ENT initialized.
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Aug 12 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_find (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
+ const char *name, H5G_entry_t *ent)
+{
+ FUNC_ENTER (H5G_find, NULL, FAIL);
+
+ /* check args */
+ assert (f);
+ assert (name && *name);
+ assert (cwd || '/'==*name);
+
+ if (H5G_namei (f, cwd, name, NULL, dir_ent, ent)<0) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, FAIL); /*object not found*/
+ }
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_insert
+ *
+ * Purpose: Inserts symbol table ENT into the directory hierarchy
+ * giving it the specified NAME. If NAME is relative then
+ * it is interpreted with respect to the CWD pointer. If
+ * non-null, DIR_ENT will be initialized with the symbol table
+ * entry for the directory which contains the new ENT.
+ *
+ * NAME must not be the name of the root symbol table entry
+ * ('/') since that is a special case. If NAME is the root
+ * symbol table entry, then this function will return failure.
+ *
+ * Return: Success: SUCCEED with optional DIR_ENT initialized with
+ * the symbol table entry for the directory
+ * which contains the new ENT.
+ *
+ * Failure: FAIL (DIR_ENT is not modified).
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Aug 11 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_insert (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
+ const char *name, H5G_entry_t *ent)
+{
+ herr_t status;
+ const char *rest=NULL;
+ H5G_entry_t _parent;
+ size_t nchars;
+ char _comp[1024];
+
+ FUNC_ENTER (H5G_insert, NULL, FAIL);
+
+ /* check args */
+ assert (f);
+ assert (name && *name);
+ assert (cwd || '/'==*name);
+ assert (ent);
+ if (!dir_ent) dir_ent = &_parent;
+
+ /* lookup name */
+ status = H5G_namei (f, cwd, name, &rest, dir_ent, NULL);
+ if (status<0 && !rest) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL); /*lookup failed*/
+ } else if (0==status) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_EXISTS, FAIL); /*already exists*/
+ }
+ H5ECLEAR; /*it's OK that we didn't find it*/
+
+ /* should be one null-terminated component left */
+ rest = H5G_component (rest, &nchars);
+ assert (rest && *rest);
+ if (rest[nchars]) {
+ if (H5G_component (rest+nchars, NULL)) {
+ /* missing component */
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, FAIL);
+ } else if (nchars+1 > sizeof _comp) {
+ /* component name is too long */
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_COMPLEN, FAIL);
+ } else {
+ /* null terminate */
+ memcpy (_comp, rest, nchars);
+ _comp[nchars] = '\0';
+ rest = _comp;
+ }
+ }
+
+ /* insert entry into parent */
+ if (H5G_stab_insert (f, dir_ent, rest, ent)<0) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL); /*can't insert*/
+ }
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_modify
+ *
+ * Purpose: Modifies the symbol table entry for the object with the
+ * specified NAME by copying the new symbol table entry ENT
+ * over the top of the old one. If NAME is relative then it
+ * is interpreted with respect to the CWD pointer. If non-null,
+ * DIR_ENT will be initialized with the symbol table entry for the
+ * directory which contains the new ENT.
+ *
+ * Do not use this function to change the entry for the root
+ * symbol since that's a special case. This function returns
+ * failure if that is attempted.
+ *
+ * Return: Success: SUCCEED with optional DIR_ENT initialized with
+ * the symbol table entry for the directory
+ * which contains the new ENT.
+ *
+ * Failure: FAIL (DIR_ENT is not modified).
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Aug 11 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_modify (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
+ const char *name, H5G_entry_t *ent)
+{
+ const char *rest=NULL;
+ H5G_entry_t _parent;
+ size_t nchars;
+
+ FUNC_ENTER (H5G_modify, NULL, FAIL);
+
+ /* check args */
+ assert (f);
+ assert (name && *name);
+ assert (cwd || '/'==*name);
+ assert (ent);
+ if (!dir_ent) dir_ent = &_parent;
+
+ /* lookup name */
+ if (H5G_namei (f, cwd, name, &rest, dir_ent, NULL)<0) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, FAIL); /*entry not found*/
+ }
+
+ /* get the base name */
+ rest = H5G_basename (name, &nchars);
+
+ /* cannot modify the root symbol entry */
+ if (!*rest) HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, FAIL);
+
+ /* modify entry in parent */
+ if (H5G_stab_modify (f, dir_ent, rest, ent)<0) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL); /*can't modify*/
+ }
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+
+/*-------------------------------------------------------------------------
* Function: H5G_stab_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.
+ * name heap.
*
* In order for the B-tree to operate correctly, the first
* item in the heap is the empty string, and must appear at
@@ -91,40 +646,39 @@ H5G_stab_new (hdf5_file_t *f, H5G_entry_t *self, size_t init)
* Check arguments.
*/
assert (f);
+ init = MAX(init, H5H_SIZEOF_FREE(f)+2);
/* Create symbol table private heap */
- if (init>0) {
- if ((stab.heap = H5H_new (f, H5H_LOCAL, init))<0) {
- HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL);
- }
- if ((name = H5H_insert (f, stab.heap, 1, "")<0)) {
- HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL);
- }
- if (0!=name) {
- /*
- * B-tree's won't work if the first name isn't at the beginning
- * of the heap.
- */
- HRETURN_ERROR (H5E_INTERNAL, H5E_CANTINIT, FAIL);
- }
- } else {
- stab.heap = 0; /*we'll create it later*/
+ if ((stab.heap = H5H_new (f, H5H_LOCAL, init))<0) {
+ HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL);
+ }
+ if ((name = H5H_insert (f, stab.heap, 1, "")<0)) {
+ HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL);
+ }
+ if (0!=name) {
+ /*
+ * B-tree's won't work if the first name isn't at the beginning
+ * of the heap.
+ */
+ HRETURN_ERROR (H5E_INTERNAL, H5E_CANTINIT, FAIL);
}
- /* The B-tree is created on demand later */
- stab.btree = 0;
+ /* Create the B-tree */
+ if ((stab.btree = H5B_new (f, H5B_SNODE))<0) {
+ HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL);
+ }
/* Create symbol table object header with a single link */
if ((addr = H5O_new (f, 1, 4+2*H5F_SIZEOF_OFFSET(f)))<0) {
HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL);
}
+
+ /* insert the symbol table message */
if (self) {
self->name_off = 0;
self->header = addr;
self->type = H5G_NOTHING_CACHED;
}
-
- /* insert the symbol table message */
if (H5O_modify(f, addr, self, NULL, H5O_STAB, H5O_NEW_MESG, &stab)<0) {
HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL);
}
@@ -165,15 +719,11 @@ H5G_stab_find (hdf5_file_t *f, H5G_entry_t *self, const char *name,
assert (f);
assert (self && self->header>=0);
assert (name && *name);
- assert (ent);
/* set up the udata */
if (NULL==H5O_read (f, self->header, self, H5O_STAB, 0, &stab)) {
HRETURN_ERROR (H5E_SYM, H5E_BADMESG, FAIL);
}
- if (stab.btree<=0 || stab.heap<=0) {
- HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); /*empty symbol table*/
- }
udata.operation = H5G_OPER_FIND;
udata.name = name;
udata.heap = stab.heap;
@@ -228,9 +778,6 @@ H5G_stab_modify (hdf5_file_t *f, H5G_entry_t *self, const char *name,
if (NULL==H5O_read (f, self->header, self, H5O_STAB, 0, &stab)) {
HRETURN_ERROR (H5E_SYM, H5E_BADMESG, FAIL);
}
- if (stab.btree<=0 || stab.heap<=0) {
- HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); /*empty symbol table*/
- }
udata.operation = H5G_OPER_MODIFY;
udata.name = name;
udata.heap = stab.heap;
@@ -270,7 +817,6 @@ H5G_stab_insert (hdf5_file_t *f, H5G_entry_t *self, const char *name,
{
H5O_stab_t stab; /*symbol table message */
H5G_node_ud1_t udata; /*data to pass through B-tree */
- off_t offset; /*offset of name within heap */
FUNC_ENTER (H5G_stab_insert, NULL, FAIL);
@@ -280,34 +826,15 @@ H5G_stab_insert (hdf5_file_t *f, H5G_entry_t *self, const char *name,
assert (name && *name);
assert (ent);
- /* make sure we have a B-tree and a heap */
+ /* initialize data to pass through B-tree */
if (NULL==H5O_read (f, self->header, self, H5O_STAB, 0, &stab)) {
HRETURN_ERROR (H5E_SYM, H5E_BADMESG, FAIL);
}
- if (stab.btree<=0 || stab.heap<=0) {
- if (stab.btree<=0 &&
- (stab.btree = H5B_new (f, H5B_SNODE))<0) {
- HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL);
- }
- if (stab.heap<=0) {
- stab.heap = H5H_new (f, H5H_LOCAL,
- MAX(strlen(name)+1, H5G_INIT_HEAP));
- if (stab.heap<0) {
- HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL);
- }
- if (0!=(offset = H5H_insert (f, stab.heap, 1, ""))) {
- HRETURN_ERROR (H5E_INTERNAL, H5E_CANTINIT, FAIL);
- }
- }
- if (H5O_modify (f, self->header, self, NULL, H5O_STAB, 0, &stab)<0) {
- HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL);
- }
- }
-
- /* initialize data to pass through B-tree */
udata.name = name;
udata.heap = stab.heap;
udata.entry = *ent;
+
+ /* insert */
if (H5B_insert (f, H5B_SNODE, stab.btree, &udata)<0) {
HRETURN_ERROR (H5E_SYM, H5E_CANTINSERT, FAIL);
}
@@ -358,18 +885,18 @@ H5G_stab_list (hdf5_file_t *f, H5G_entry_t *self, intn maxentries,
assert (self && self->header>=0);
assert (maxentries>=0);
+ /* initialize data to pass through B-tree */
if (NULL==H5O_read (f, self->header, self, H5O_STAB, 0, &stab)) {
HRETURN_ERROR (H5E_SYM, H5E_BADMESG, FAIL);
}
- if (stab.btree<=0 || stab.heap<=0) HRETURN (0); /*empty directory*/
-
udata.entry = entries;
udata.name = names;
udata.heap = stab.heap;
udata.maxentries = maxentries;
udata.nsyms = 0;
-
if (names) HDmemset (names, 0, maxentries);
+
+ /* list */
if (H5B_list (f, H5B_SNODE, stab.btree, &udata)<0) {
if (names) {
for (i=0; i<maxentries; i++) H5MM_xfree (names[i]);
diff --git a/src/H5Gnode.c b/src/H5Gnode.c
index 11950f2..9b33515 100644
--- a/src/H5Gnode.c
+++ b/src/H5Gnode.c
@@ -68,7 +68,7 @@ static const H5AC_class_t H5AC_SNODE[1] = {{
/* H5G inherits B-tree like properties from H5B */
const H5B_class_t H5B_SNODE[1] = {{
H5B_SUBTYPE_SNODE, /*id */
- 64, /*k */
+ 16, /*k */
sizeof (H5G_node_key_t), /*sizeof_nkey */
H5G_node_sizeof_rkey, /*get_sizeof_rkey */
H5G_node_new, /*new */
@@ -454,7 +454,7 @@ H5G_node_cmp (hdf5_file_t *f, void *_lt_key, void *_udata, void *_rt_key)
if (NULL==(s=H5H_peek (f, udata->heap, rt_key->offset))) {
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL);
}
- if (HDstrcmp (udata->name, s)>0) HRETURN(-1);
+ if (HDstrcmp (udata->name, s)>0) HRETURN(1);
FUNC_LEAVE (0);
}
diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h
index 0e4057d..bbfe9a0 100644
--- a/src/H5Gprivate.h
+++ b/src/H5Gprivate.h
@@ -27,7 +27,7 @@
#define H5G_NODE_MAGIC "SNOD" /*symbol table node magic number */
#define H5G_NODE_SIZEOF_MAGIC 4 /*sizeof symbol node magic number */
#define H5G_NODE_VERS 1 /*symbol table node version number */
-#define H5G_NODE_K 64 /*min degree. max degree is twice this */
+#define H5G_NODE_K 4 /*min degree. max degree is twice this */
#define H5G_NODE_SIZEOF_HDR(F) (H5G_NODE_SIZEOF_MAGIC + 4)
#define H5G_SIZEOF_ENTRY(F) \
(H5F_SIZEOF_OFFSET(F) + /*offset of name into heap */ \
@@ -133,8 +133,19 @@ extern const H5B_class_t H5B_SNODE[1];
/*
* Library prototypes...
*/
-herr_t H5G_node_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent,
- intn fwidth, haddr_t heap);
+
+/* functions that understand directories */
+herr_t H5G_mkroot (hdf5_file_t *f, size_t size_hint);
+herr_t H5G_new (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
+ const char *name, size_t size_hint, H5G_entry_t *ent);
+herr_t H5G_find (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
+ const char *name, H5G_entry_t *ent);
+herr_t H5G_insert (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
+ const char *name, H5G_entry_t *ent);
+herr_t H5G_modify (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
+ const char *name, H5G_entry_t *ent);
+
+/* functions that understand symbol tables */
haddr_t H5G_stab_new (hdf5_file_t *f, H5G_entry_t *self, size_t init);
haddr_t H5G_stab_find (hdf5_file_t *f, H5G_entry_t *self, const char *name,
H5G_entry_t *ent);
@@ -144,6 +155,12 @@ herr_t H5G_stab_insert (hdf5_file_t *f, H5G_entry_t *self, const char *name,
H5G_entry_t *ent);
intn H5G_stab_list (hdf5_file_t *f, H5G_entry_t *self, intn maxentries,
char *names[], H5G_entry_t entries[]);
+
+/* functions that understand symbol table nodes */
+herr_t H5G_node_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent,
+ intn fwidth, haddr_t heap);
+
+/* functions that understand symbol table 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);
diff --git a/src/H5H.c b/src/H5H.c
index 8c90095..ddf5055 100644
--- a/src/H5H.c
+++ b/src/H5H.c
@@ -30,16 +30,6 @@
#define H5H_FREE_NULL 1 /*end of free list on disk */
#define PABLO_MASK H5H_mask
-#define H5H_SIZEOF_HDR(F) \
- (H5H_SIZEOF_MAGIC + /*heap signature */ \
- H5F_SIZEOF_SIZE (F) + /*data size */ \
- H5F_SIZEOF_OFFSET (F) + /*free list head */ \
- H5F_SIZEOF_OFFSET (F)) /*data address */
-
-#define H5H_SIZEOF_FREE(F) \
- (H5F_SIZEOF_OFFSET (F) + /*ptr to next free block */ \
- H5F_SIZEOF_SIZE (F)) /*size of this free block */
-
typedef struct H5H_free_t {
off_t offset; /*offset of free block */
size_t size; /*size of free block */
diff --git a/src/H5Hprivate.h b/src/H5Hprivate.h
index 6a05049..a11adde 100644
--- a/src/H5Hprivate.h
+++ b/src/H5Hprivate.h
@@ -24,6 +24,17 @@
#define H5H_SIZEOF_MAGIC 4
#define H5H_ALIGN(X) ((X)=((X)+1) & ~0x01)
+#define H5H_SIZEOF_HDR(F) \
+ (H5H_SIZEOF_MAGIC + /*heap signature */ \
+ H5F_SIZEOF_SIZE (F) + /*data size */ \
+ H5F_SIZEOF_OFFSET (F) + /*free list head */ \
+ H5F_SIZEOF_OFFSET (F)) /*data address */
+
+#define H5H_SIZEOF_FREE(F) \
+ (H5F_SIZEOF_OFFSET (F) + /*ptr to next free block */ \
+ H5F_SIZEOF_SIZE (F)) /*size of this free block */
+
+
typedef enum H5H_type_t {
H5H_LOCAL =0, /*local symtab name heap */
H5H_GLOBAL =1 /*global small object heap */
diff --git a/src/H5O.c b/src/H5O.c
index 1b259ba..c594964 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -62,7 +62,7 @@ static const H5O_class_t *const message_type_g[] = {
NULL, /*0x000A Data storage -- sparse object */
NULL, /*0x000B Data storage -- compressed object */
NULL, /*0x000C Attribute list */
- NULL, /*0x000D Object name */
+ H5O_NAME, /*0x000D Object name */
NULL, /*0x000E Object modification date and time */
NULL, /*0x000F Shared header message */
H5O_CONT, /*0x0010 Object header continuation */
@@ -273,8 +273,8 @@ H5O_load (hdf5_file_t *f, haddr_t addr, const void *_data)
for (chunk_addr=0; 0==chunk_addr && curmesg<oh->nmesgs; curmesg++) {
if (H5O_CONT_ID==oh->mesg[curmesg].type->id) {
uint8 *p2 = oh->mesg[curmesg].raw;
- oh->mesg[curmesg].native = (H5O_CONT->decode)(f, p2);
- cont = (H5O_cont_t*)(oh->mesg[curmesg].native);
+ cont = (H5O_CONT->decode)(f, oh->mesg[curmesg].raw_size, p2);
+ oh->mesg[curmesg].native = cont;
chunk_addr = cont->addr;
chunk_size = cont->size;
cont->chunkno = oh->nchunks; /*the next chunk to allocate*/
@@ -407,12 +407,8 @@ H5O_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5O_t *oh)
/* destroy messages */
for (i=0; i<oh->nmesgs; i++) {
if (oh->mesg[i].native) {
- if (oh->mesg[i].type->free) {
- (oh->mesg[i].type->free)(oh->mesg[i].native);
- oh->mesg[i].native = NULL;
- } else {
- oh->mesg[i].native = H5MM_xfree (oh->mesg[i].native);
- }
+ H5O_reset (oh->mesg[i].type, oh->mesg[i].native);
+ oh->mesg[i].native = H5MM_xfree (oh->mesg[i].native);
}
}
oh->mesg = H5MM_xfree (oh->mesg);
@@ -426,6 +422,43 @@ H5O_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5O_t *oh)
/*-------------------------------------------------------------------------
+ * Function: H5O_reset
+ *
+ * Purpose: Some message data structures have internal fields that
+ * need to be freed. This function does that if appropriate
+ * but doesn't free NATIVE.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Aug 12 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O_reset (const H5O_class_t *type, void *native)
+{
+ FUNC_ENTER (H5O_reset, NULL, FAIL);
+
+ if (type->reset) {
+ if ((type->reset)(native)<0) {
+ /* reset class method failed */
+ HRETURN_ERROR (H5E_OHDR, H5E_CANTINIT, FAIL);
+ }
+ } else {
+ HDmemset (native, 0, type->native_size);
+ }
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
* Function: H5O_link
*
* Purpose: Adjust the link count for an object header by adding
@@ -586,7 +619,9 @@ H5O_find_in_ohdr (hdf5_file_t *f, haddr_t addr, const H5O_class_t **type_p,
/* decode the message if necessary */
if (NULL==oh->mesg[i].native) {
assert (oh->mesg[i].type->decode);
- oh->mesg[i].native = (oh->mesg[i].type->decode)(f, oh->mesg[i].raw);
+ oh->mesg[i].native = (oh->mesg[i].type->decode)(f,
+ oh->mesg[i].raw_size,
+ oh->mesg[i].raw);
if (NULL==oh->mesg[i].native) {
HRETURN_ERROR (H5E_OHDR, H5E_CANTDECODE, FAIL);
}
@@ -709,7 +744,7 @@ H5O_modify (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
/* Allocate space for the new message */
if (overwrite<0) {
- size = (type->size)(f, mesg);
+ size = (type->raw_size)(f, mesg);
H5O_ALIGN (size, oh->alignment);
idx = H5O_alloc (f, oh, type, size);
if (idx<0) HRETURN_ERROR (H5E_OHDR, H5E_CANTINIT, FAIL);
@@ -1220,7 +1255,9 @@ H5O_debug (hdf5_file_t *f, haddr_t addr, FILE *stream,
/* decode the message */
if (NULL==oh->mesg[i].native && oh->mesg[i].type->decode) {
- oh->mesg[i].native = (oh->mesg[i].type->decode)(f, oh->mesg[i].raw);
+ oh->mesg[i].native = (oh->mesg[i].type->decode)(f,
+ oh->mesg[i].raw_size,
+ oh->mesg[i].raw);
}
/* print the message */
diff --git a/src/H5Ocont.c b/src/H5Ocont.c
index 7b184cb..045489c 100644
--- a/src/H5Ocont.c
+++ b/src/H5Ocont.c
@@ -26,7 +26,7 @@
#define PABLO_MASK H5O_cont_mask
/* PRIVATE PROTOTYPES */
-static void *H5O_cont_decode (hdf5_file_t *f, const uint8 *p);
+static void *H5O_cont_decode (hdf5_file_t *f, size_t raw_size, const uint8 *p);
static herr_t H5O_cont_encode (hdf5_file_t *f, size_t size, uint8 *p,
const void *_mesg);
static herr_t H5O_cont_debug (hdf5_file_t *f, const void *_mesg, FILE *stream,
@@ -36,13 +36,14 @@ static herr_t H5O_cont_debug (hdf5_file_t *f, const void *_mesg, FILE *stream,
const H5O_class_t H5O_CONT[1] = {{
H5O_CONT_ID, /*message id number */
"hdr continuation", /*message name for debugging */
+ sizeof (H5O_cont_t), /*native message size */
H5O_cont_decode, /*decode message */
H5O_cont_encode, /*encode message */
NULL, /*no fast method */
NULL, /*no cache method */
NULL, /*no copy method */
NULL, /*no size method */
- NULL, /*default free method */
+ NULL, /*default reset method */
H5O_cont_debug, /*debugging */
}};
@@ -68,12 +69,18 @@ static intn interface_initialize_g = FALSE;
*-------------------------------------------------------------------------
*/
static void *
-H5O_cont_decode (hdf5_file_t *f, const uint8 *p)
+H5O_cont_decode (hdf5_file_t *f, size_t raw_size, const uint8 *p)
{
H5O_cont_t *cont = NULL;
FUNC_ENTER (H5O_cont_decode, NULL, NULL);
+ /* check args */
+ assert (f);
+ assert (raw_size == H5F_SIZEOF_OFFSET(f) + H5F_SIZEOF_SIZE(f));
+ assert (p);
+
+ /* decode */
cont = H5MM_xcalloc (1, sizeof(H5O_cont_t));
H5F_decode_offset (f, p, cont->addr);
H5F_decode_length (f, p, cont->size);
diff --git a/src/H5Oname.c b/src/H5Oname.c
new file mode 100644
index 0000000..643efcc
--- /dev/null
+++ b/src/H5Oname.c
@@ -0,0 +1,283 @@
+/*-------------------------------------------------------------------------
+ * Copyright (C) 1997 National Center for Supercomputing Applications.
+ * All rights reserved.
+ *
+ *-------------------------------------------------------------------------
+ *
+ * Created: H5Oname.c
+ * Aug 12 1997
+ * Robb Matzke <robb@maya.nuance.com>
+ *
+ * Purpose: Object name message.
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <assert.h>
+
+#include "hdf5.h"
+
+#include "H5private.h"
+#include "H5MMprivate.h"
+#include "H5Oprivate.h"
+
+#define PABLO_MASK H5O_name_mask
+
+/* PRIVATE PROTOTYPES */
+static void *H5O_name_decode (hdf5_file_t *f, size_t raw_size, const uint8 *p);
+static herr_t H5O_name_encode (hdf5_file_t *f, size_t raw_size, uint8 *p,
+ const void *_mesg);
+static void *H5O_name_copy (const void *_mesg, void *_dest);
+static size_t H5O_name_size (hdf5_file_t *f, const void *_mesg);
+static herr_t H5O_name_reset (void *_mesg);
+static herr_t H5O_name_debug (hdf5_file_t *f, const void *_mesg, FILE *stream,
+ intn indent, intn fwidth);
+
+/* This message derives from H5O */
+const H5O_class_t H5O_NAME[1] = {{
+ H5O_NAME_ID, /*message id number */
+ "name", /*message name for debugging */
+ sizeof (H5O_name_t), /*native message size */
+ H5O_name_decode, /*decode message */
+ H5O_name_encode, /*encode message */
+ NULL, /*no stab entry fields */
+ NULL, /*no stab entry fields */
+ H5O_name_copy, /*copy the native value */
+ H5O_name_size, /*raw message size */
+ H5O_name_reset, /*free internal memory */
+ H5O_name_debug, /*debug the message */
+}};
+
+/* Is the interface initialized? */
+static hbool_t interface_initialize_g = FALSE;
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_name_decode
+ *
+ * Purpose: Decode a name message and return a pointer to a new
+ * native message struct.
+ *
+ * Return: Success: Ptr to new message in native struct.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Aug 12 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5O_name_decode (hdf5_file_t *f, size_t raw_size, const uint8 *p)
+{
+ H5O_name_t *mesg;
+
+ FUNC_ENTER (H5O_name_decode, NULL, NULL);
+
+ /* check args */
+ assert (f);
+ assert (p);
+
+ /* decode */
+ mesg = H5MM_xcalloc (1, sizeof(H5O_name_t));
+ mesg->s = H5MM_xmalloc (raw_size);
+ HDmemcpy (mesg->s, p, raw_size);
+
+ FUNC_LEAVE (mesg);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_name_encode
+ *
+ * Purpose: Encodes a name message.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Aug 12 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_name_encode (hdf5_file_t *f, size_t raw_size, uint8 *p, const void *_mesg)
+{
+ const H5O_name_t *mesg = (const H5O_name_t *)_mesg;
+ size_t size;
+
+ FUNC_ENTER (H5O_name_encode, NULL, FAIL);
+
+ /* check args */
+ assert (f);
+ assert (p);
+ assert (mesg && mesg->s);
+
+ /* message size */
+ size = strlen (mesg->s)+1;
+ assert (size<=raw_size);
+
+ /* encode */
+ HDmemcpy (p, mesg->s, size);
+ HDmemset (p+size, 0, raw_size-size);
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_name_copy
+ *
+ * Purpose: Copies a message from _MESG to _DEST, allocating _DEST if
+ * necessary.
+ *
+ * Return: Success: Ptr to _DEST
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Aug 12 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5O_name_copy (const void *_mesg, void *_dest)
+{
+ const H5O_name_t *mesg = (const H5O_name_t *)_mesg;
+ H5O_name_t *dest = (H5O_name_t *)_dest;
+
+ FUNC_ENTER (H5O_name_copy, NULL, NULL);
+
+ /* check args */
+ assert (mesg);
+ if (!dest) dest = H5MM_xcalloc (1, sizeof(H5O_name_t));
+
+ /* copy */
+ *dest = *mesg;
+ dest->s = H5MM_xstrdup (mesg->s);
+
+ FUNC_LEAVE ((void*)dest);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_name_size
+ *
+ * Purpose: Returns the size of the raw message in bytes not
+ * counting the message typ or size fields, but only the data
+ * fields. This function doesn't take into account
+ * alignment.
+ *
+ * Return: Success: Message data size in bytes w/o alignment.
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Aug 12 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static size_t
+H5O_name_size (hdf5_file_t *f, const void *_mesg)
+{
+ const H5O_name_t *mesg = (const H5O_name_t *)_mesg;
+ size_t size;
+
+ FUNC_ENTER (H5O_stab_size, NULL, FAIL);
+
+ /* check args */
+ assert (f);
+ assert (mesg);
+
+ size = mesg->s ? HDstrlen (mesg->s)+1 : 0;
+ FUNC_LEAVE (size);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_name_reset
+ *
+ * Purpose: Frees internal pointers and resets the message to an
+ * initial state.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Aug 12 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_name_reset (void *_mesg)
+{
+ H5O_name_t *mesg = (H5O_name_t *)_mesg;
+
+ FUNC_ENTER (H5O_name_reset, NULL, FAIL);
+
+ /* check args */
+ assert (mesg);
+
+ /* reset */
+ mesg->s = H5MM_xfree (mesg->s);
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_name_debug
+ *
+ * Purpose: Prints debugging info for the message.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Aug 12 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_name_debug (hdf5_file_t *f, const void *_mesg, FILE *stream,
+ intn indent, intn fwidth)
+{
+ const H5O_name_t *mesg = (const H5O_name_t *)_mesg;
+
+ FUNC_ENTER (H5O_name_debug, NULL, FAIL);
+
+ /* check args */
+ assert (f);
+ assert (mesg);
+ assert (stream);
+ assert (indent>=0);
+ assert (fwidth>=0);
+
+ fprintf (stream, "%*s%-*s `%s'\n", indent, "", fwidth,
+ "Name:",
+ mesg->s);
+
+ FUNC_LEAVE (SUCCEED);
+}
diff --git a/src/H5Onull.c b/src/H5Onull.c
index 965266d..7175273 100644
--- a/src/H5Onull.c
+++ b/src/H5Onull.c
@@ -24,12 +24,13 @@
const H5O_class_t H5O_NULL[1] = {{
H5O_NULL_ID, /*message id number */
"null", /*message name for debugging */
+ 0, /*native message size */
NULL, /*no decode method */
NULL, /*no encode method */
NULL, /*no fast method */
NULL, /*no cache method */
NULL, /*no copy method */
NULL, /*no size method */
- NULL, /*no free method */
+ NULL, /*no reset method */
NULL, /*no debug method */
}};
diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h
index 40d4a36..f56146c 100644
--- a/src/H5Oprivate.h
+++ b/src/H5Oprivate.h
@@ -41,13 +41,14 @@
typedef struct H5O_class_t {
intn id; /*message type ID on disk */
const char *name; /*message name for debugging */
- void *(*decode)(hdf5_file_t*,const uint8*); /*decode mesg */
+ size_t native_size; /*size of native message */
+ void *(*decode)(hdf5_file_t*,size_t,const uint8*);
herr_t (*encode)(hdf5_file_t*,size_t,uint8*,const void*);
- void *(*fast)(const H5G_entry_t*, void*); /*get from stab ent */
+ void *(*fast)(const H5G_entry_t*, void*); /*get from stab ent*/
hbool_t (*cache)(H5G_entry_t*,const void*); /*put into entry */
void *(*copy)(const void*,void*); /*copy native value */
- size_t (*size)(hdf5_file_t*,const void*); /*size of raw value */
- void *(*free)(void*); /*free native data struct */
+ size_t (*raw_size)(hdf5_file_t*,const void*); /*sizeof raw val */
+ herr_t (*reset)(void*); /*free nested data structures */
herr_t (*debug)(hdf5_file_t*,const void*, FILE*, intn, intn);
} H5O_class_t;
@@ -87,6 +88,16 @@ typedef struct H5O_t {
extern const H5O_class_t H5O_NULL[1];
/*
+ * Object name message.
+ */
+#define H5O_NAME_ID 0x000d
+extern const H5O_class_t H5O_NAME[1];
+
+typedef struct H5O_name_t {
+ char *s; /*ptr to malloc'd memory */
+} H5O_name_t;
+
+/*
* Object header continuation message.
*/
#define H5O_CONT_ID 0x0010
@@ -121,6 +132,7 @@ const void *H5O_peek (hdf5_file_t *f, haddr_t addr, const H5O_class_t *type,
intn H5O_modify (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
hbool_t *ent_modified, const H5O_class_t *type,
intn overwrite, const void *mesg);
+herr_t H5O_reset (const H5O_class_t *type, void *native);
herr_t H5O_debug (hdf5_file_t *f, haddr_t addr, FILE *stream,
intn indent, intn fwidth);
diff --git a/src/H5Ostab.c b/src/H5Ostab.c
index d2c1394..926eeef 100644
--- a/src/H5Ostab.c
+++ b/src/H5Ostab.c
@@ -26,7 +26,7 @@
#define PABLO_MASK H5O_stab_mask
/* PRIVATE PROTOTYPES */
-static void *H5O_stab_decode (hdf5_file_t *f, const uint8 *p);
+static void *H5O_stab_decode (hdf5_file_t *f, size_t raw_size, const uint8 *p);
static herr_t H5O_stab_encode (hdf5_file_t *f, size_t size, uint8 *p,
const void *_mesg);
static void *H5O_stab_fast (const H5G_entry_t *ent, void *_mesg);
@@ -40,18 +40,19 @@ static herr_t H5O_stab_debug (hdf5_file_t *f, const void *_mesg,
const H5O_class_t H5O_STAB[1] = {{
H5O_STAB_ID, /*message id number */
"stab", /*message name for debugging */
+ sizeof (H5O_stab_t), /*native message size */
H5O_stab_decode, /*decode message */
H5O_stab_encode, /*encode message */
H5O_stab_fast, /*get message from stab entry */
H5O_stab_cache, /*put message into stab entry */
H5O_stab_copy, /*copy the native value */
H5O_stab_size, /*size of symbol table entry */
- NULL, /*default free method */
+ NULL, /*default reset method */
H5O_stab_debug, /*debug the message */
}};
/* Is the interface initialized? */
-static intn interface_initialize_g = FALSE;
+static hbool_t interface_initialize_g = FALSE;
/*-------------------------------------------------------------------------
@@ -73,7 +74,7 @@ static intn interface_initialize_g = FALSE;
*-------------------------------------------------------------------------
*/
static void *
-H5O_stab_decode (hdf5_file_t *f, const uint8 *p)
+H5O_stab_decode (hdf5_file_t *f, size_t raw_size, const uint8 *p)
{
H5O_stab_t *stab;
@@ -81,6 +82,7 @@ H5O_stab_decode (hdf5_file_t *f, const uint8 *p)
/* check args */
assert (f);
+ assert (raw_size == 2*H5F_SIZEOF_OFFSET(f));
assert (p);
/* decode */
@@ -95,7 +97,7 @@ H5O_stab_decode (hdf5_file_t *f, const uint8 *p)
/*-------------------------------------------------------------------------
* Function: H5O_stab_encode
*
- * Purpose: Encodes a symbol table entry.
+ * Purpose: Encodes a symbol table message.
*
* Return: Success: SUCCEED
*
@@ -110,7 +112,7 @@ H5O_stab_decode (hdf5_file_t *f, const uint8 *p)
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_stab_encode (hdf5_file_t *f, size_t size, uint8 *p, const void *_mesg)
+H5O_stab_encode (hdf5_file_t *f, size_t raw_size, uint8 *p, const void *_mesg)
{
const H5O_stab_t *stab = (const H5O_stab_t *)_mesg;
@@ -118,7 +120,7 @@ H5O_stab_encode (hdf5_file_t *f, size_t size, uint8 *p, const void *_mesg)
/* check args */
assert (f);
- assert (size == 2 * H5F_SIZEOF_OFFSET(f));
+ assert (raw_size == 2 * H5F_SIZEOF_OFFSET(f));
assert (p);
assert (stab);
diff --git a/src/Makefile b/src/Makefile
index 94dcd67..cfda7af 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -28,7 +28,8 @@ CFLAGS = -c $(MACHINE) $(DEFS)
INCL = hdf5.h
OBJ = H5.o H5E.o H5A.o H5F.o H5C.o H5M.o H5AC.o H5B.o H5MM.o H5MF.o H5T.o \
- H5Gnode.o H5H.o H5G.o H5P.o H5D.o H5O.o H5Onull.o H5Ocont.o H5Ostab.o
+ H5Gnode.o H5H.o H5G.o H5P.o H5D.o H5O.o H5Onull.o H5Ocont.o H5Ostab.o \
+ H5Oname.o
$(TARGET): $(OBJ)
$(AR) $(ARFLAGS) $(TARGET) $(OBJ)
@@ -111,3 +112,6 @@ H5Ocont.o: H5Ocont.c $(INCL) H5Oprivate.h H5Oproto.h
H5Ostab.o: H5Ostab.c $(INCL) H5Oprivate.h H5Oproto.h
$(CC) $(CFLAGS) H5Ostab.c
+
+H5Oname.o: H5Oname.c $(INCL) H5Oprivate.h H5Oproto.h
+ $(CC) $(CFLAGS) H5Oname.c
diff --git a/src/hdf5port.h b/src/hdf5port.h
index 3f3a5c2..4045435 100644
--- a/src/hdf5port.h
+++ b/src/hdf5port.h
@@ -170,6 +170,8 @@ typedef MPFILE *hdf_file_t;
/* non-standard function, not defined on the following mahcines - */
#if !(defined VMS || defined macintosh || defined MAC || defined __MWERKS__ || defined SYMANTEC_C || defined MIPSEL || defined NEXT || defined CONVEX || defined IBM6000 || defined ANSISUN || defined IRIX)
# define HDstrdup(s) ((char *)strdup((const char *)(s)))
+#else
+# define HDstrdup(s) strdup(s)
#endif /* !(VMS | etc..) */