summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobb Matzke <matzke@llnl.gov>1997-09-22 02:08:54 (GMT)
committerRobb Matzke <matzke@llnl.gov>1997-09-22 02:08:54 (GMT)
commit8c8ae76bf5ba6fdc01ce73ff6988064b86e48a9d (patch)
treebdc348ec43b98a67a08790f414c72f0c6b52d9bc
parented9584cc92e4eb561ad47636c3ce87836a2ad8f0 (diff)
downloadhdf5-8c8ae76bf5ba6fdc01ce73ff6988064b86e48a9d.zip
hdf5-8c8ae76bf5ba6fdc01ce73ff6988064b86e48a9d.tar.gz
hdf5-8c8ae76bf5ba6fdc01ce73ff6988064b86e48a9d.tar.bz2
[svn-r106] Fixed some symbol table bugs. Fixed a free memory read in H5Osdim.c.
-rw-r--r--src/H5AC.c19
-rw-r--r--src/H5D.c54
-rw-r--r--src/H5F.c39
-rw-r--r--src/H5Fprivate.h2
-rw-r--r--src/H5G.c1126
-rw-r--r--src/H5Gent.c488
-rw-r--r--src/H5Gnode.c156
-rw-r--r--src/H5Gpkg.h39
-rw-r--r--src/H5Gprivate.h60
-rw-r--r--src/H5Gshad.c387
-rw-r--r--src/H5Gstab.c345
-rw-r--r--src/H5O.c53
-rw-r--r--src/H5Oprivate.h6
-rw-r--r--src/H5Osdim.c72
-rw-r--r--src/H5Osdtyp.c57
-rw-r--r--src/H5Ostab.c54
-rw-r--r--src/Makefile.in6
17 files changed, 1778 insertions, 1185 deletions
diff --git a/src/H5AC.c b/src/H5AC.c
index 9dc49ed..d82cb6f 100644
--- a/src/H5AC.c
+++ b/src/H5AC.c
@@ -310,7 +310,8 @@ H5AC_compare (const void *_a, const void *_b)
*
* Return: Success: SUCCEED
*
- * Failure: FAIL
+ * Failure: FAIL if there was a request to flush all
+ * items and something was protected.
*
* Programmer: Robb Matzke
* matzke@llnl.gov
@@ -374,6 +375,14 @@ H5AC_flush (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr,
}
map = H5MM_xfree (map);
+ /*
+ * If there are protected object then fail. However, everything
+ * else should have been flushed.
+ */
+ if (f->cache->nprots>0) {
+ HRETURN_ERROR (H5E_CACHE, H5E_PROTECT, FAIL);
+ }
+
} else if ((!type || f->cache->slot[i].type==type) &&
f->cache->slot[i].addr==addr) {
/*
@@ -389,14 +398,6 @@ H5AC_flush (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr,
}
- /*
- * If there are protected objects then fail. However, everything
- * else should have been flushed.
- */
- if (f->cache->nprots>0) {
- HRETURN_ERROR (H5E_CACHE, H5E_PROTECT, FAIL);
- }
-
FUNC_LEAVE (SUCCEED);
}
diff --git a/src/H5D.c b/src/H5D.c
index 8566816..08dfd81 100644
--- a/src/H5D.c
+++ b/src/H5D.c
@@ -130,7 +130,6 @@ hatom_t H5D_create(hatom_t owner_id, hobjtype_t type, const char *name)
H5D_t *new_dset; /* new dataset object to create */
hatom_t ret_value = SUCCEED;
hdf5_file_t *file = NULL;
- H5G_entry_t tmp_ent;
FUNC_ENTER(H5D_create, H5D_init_interface, FAIL);
@@ -153,33 +152,11 @@ hatom_t H5D_create(hatom_t owner_id, hobjtype_t type, const char *name)
new_dset->data_addr = -1; /* No data yet */
new_dset->dirty = FALSE; /* There are no messages yet */
- /* Create the (empty) object header in the file */
- memset (&tmp_ent, 0, sizeof(tmp_ent));
- if ((tmp_ent.header = H5O_new (file, 0, H5D_MINHDR_SIZE))<0) {
- HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); /*can't create header*/
+ /* Open (and create) a new file object */
+ if (NULL==(new_dset->ent = H5G_create (file, name, H5D_MINHDR_SIZE))) {
+ HGOTO_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL);
}
- /*
- * Link the (empty) object header into the symbol table so others can
- * access it. At least that way no one will try to create another one of
- * these things with the same name. We also hold the object open while
- * H5D has a handle, preventing others from moving or deleting it from
- * under us.
- */
-#ifdef LATER
- /* We should use the real CWD instead of always the root object! */
-#else
- H5G_shadow_sync (file->root_sym);
- if (H5G_insert (file, file->root_sym, NULL, name, &tmp_ent)<0) {
- /* Something by that name already exists, or some other failure */
- HGOTO_ERROR (H5E_SYM, H5E_EXISTS, FAIL);
- }
- if (NULL==(new_dset->ent = H5G_open (file, file->root_sym, name))) {
- /* Can't open the header we just created -- should never happen */
- HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL);
- }
-#endif
-
/* Register the new datatype and get an ID for it */
if((ret_value=H5Aregister_atom(H5_DATASET, (const VOIDP)new_dset))<0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL);
@@ -236,22 +213,10 @@ hatom_t H5D_find_name(hatom_t grp_id, hobjtype_t type, const char *name)
dset->file = file;
dset->dirty = FALSE;
-#ifdef LATER
- /* We should really use the real CWD instead of the root object! */
-#else
- /*
- * WARNING! WARNING! WARNING!
- * The following line explicitly uses the root symbol as the current
- * working directory. This should be changed to something more
- * appropriate and is only hacked in here to get the prototype working.
- * -QAK
- * WARNING! WARNING! WARNING!
- */
- H5G_shadow_sync (file->root_sym);
- if (NULL==(dset->ent=H5G_open (file, file->root_sym, name))) {
+ /* Open the dataset object */
+ if (NULL==(dset->ent=H5G_open (file, name))) {
HGOTO_ERROR (H5E_DATASET, H5E_NOTFOUND, FAIL);
}
-#endif
/* Get the dataset's type (currently only atomic types) */
if((dset->type=HDcalloc(1,sizeof(h5_datatype_t)))==NULL)
@@ -422,7 +387,7 @@ done:
herr_t H5Dread(hatom_t oid, hatom_t did, VOIDP buf)
{
H5D_t *dataset; /* dataset object to do I/O on */
- void *readbuf; /* pointer to buffer to write out */
+ void *readbuf=NULL; /* pointer to buffer to write out */
uintn free_buf=0; /* if temporary conversion buffer needs to be free'd */
uintn toread; /* number of bytes to read in */
herr_t ret_value = SUCCEED;
@@ -507,7 +472,7 @@ herr_t H5Dwrite(hatom_t oid, hatom_t did, VOIDP buf)
{
H5D_t *dataset; /* dataset object to do I/O on */
uintn towrite; /* number of bytes to write out */
- void *writebuf; /* pointer to buffer to write out */
+ void *writebuf=NULL; /* pointer to buffer to write out */
uintn free_buf=0; /* if temporary conversion buffer needs to be free'd */
herr_t ret_value = SUCCEED;
@@ -649,11 +614,6 @@ herr_t H5D_flush(hatom_t oid)
}
}
- /* Flush dataset header to disk -- just for debugging */
- if (H5AC_flush (dataset->file, NULL, dataset->ent->header, FALSE)<0) {
- HRETURN_ERROR (H5E_OHDR, H5E_CANTFLUSH, FAIL);
- }
-
dataset->dirty = FALSE; /*it's clean now*/
}
diff --git a/src/H5F.c b/src/H5F.c
index 6d1aec0..c3f0a66 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -395,11 +395,15 @@ H5F_new (void)
{
hdf5_file_t *f = H5MM_xcalloc (1, sizeof(hdf5_file_t));
- /* Create a cache */
+ /* Create a main cache */
H5AC_new (f, H5AC_NSLOTS);
+ /* Create the shadow hash table */
+ f->nshadows = H5G_NSHADOWS;
+ f->shadow = H5MM_xcalloc (f->nshadows, sizeof(struct H5G_hash_t*));
+
/* Create a root symbol slot */
- f->root_sym = H5G_new_entry ();
+ f->root_sym = H5G_ent_calloc ();
return f;
}
@@ -434,6 +438,8 @@ H5F_dest (hdf5_file_t *f)
f->dir = H5MM_xfree (f->dir);
f->filename = H5MM_xfree (f->filename);
f->root_sym = H5MM_xfree (f->root_sym);
+ f->nshadows = 0;
+ f->shadow = H5MM_xfree (f->shadow);
H5MM_xfree (f);
}
return NULL;
@@ -777,7 +783,7 @@ hatom_t H5Fopen(const char *filename, uintn flags, hatom_t access_temp)
H5F_decode_length(new_file,p,new_file->logical_len); /* Decode logical length of file */
/* Decode the root symbol table entry */
- if (H5G_decode (new_file, &p, new_file->root_sym)<0) {
+ if (H5G_ent_decode (new_file, &p, new_file->root_sym)<0) {
/*can't decode root symbol table entry */
HGOTO_ERROR (H5E_IO, H5E_READERROR, FAIL);
}
@@ -870,6 +876,8 @@ H5Fflush (hatom_t fid, hbool_t invalidate)
* Return: Success: SUCCEED
*
* Failure: FAIL
+ * -2 if the there are open objects and
+ * INVALIDATE was non-zero.
*
* Programmer: Robb Matzke
* robb@maya.nuance.com
@@ -883,12 +891,19 @@ static herr_t
H5F_flush (hdf5_file_t *f, hbool_t invalidate)
{
uint8 buf[2048], *p=buf;
+ herr_t shadow_flush;
FUNC_ENTER (H5F_flush, H5F_init_interface, FAIL);
/* nothing to do if the file is read only */
if (0==(H5ACC_WRITE & f->acc_perm)) HRETURN (SUCCEED);
+ /*
+ * Flush all open object info. If this fails just remember it and return
+ * failure at the end. At least that way we get a consistent file.
+ */
+ shadow_flush = H5G_shadow_flush (f, invalidate);
+
/* flush (and invalidate) the entire cache */
if (H5AC_flush (f, NULL, 0, invalidate)<0) {
HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL); /*can't flush cache*/
@@ -912,7 +927,7 @@ H5F_flush (hdf5_file_t *f, hbool_t invalidate)
H5F_encode_offset (f, p, f->smallobj_off);
H5F_encode_offset (f, p, f->freespace_off);
H5F_encode_length (f, p, f->logical_len);
- H5G_encode (f, &p, f->root_sym);
+ H5G_ent_encode (f, &p, f->root_sym);
/* write the boot block to disk */
if (H5F_block_write (f, 0, p-buf, buf)<0) {
@@ -922,6 +937,11 @@ H5F_flush (hdf5_file_t *f, hbool_t invalidate)
/* update file length if necessary */
if (f->logical_len<=0) f->logical_len = p-buf;
+ /* Did shadow flush fail above? */
+ if (shadow_flush<0) {
+ HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, -2);/*object are still open*/
+ }
+
FUNC_LEAVE (SUCCEED);
}
@@ -978,7 +998,9 @@ herr_t H5Fclose(hatom_t fid)
if((--file->ref_count)==0)
{
if(file->file_handle!=H5F_INVALID_FILE) {
- if (H5F_flush (file, TRUE)<0) {
+ if (-2==(ret_value=H5F_flush (file, TRUE))) {
+ /*objects are still open*/
+ } else if (ret_value<0) {
/*can't flush cache*/
HGOTO_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL);
}
@@ -990,6 +1012,11 @@ herr_t H5Fclose(hatom_t fid)
}
} /* end if */
+ /* Did the H5F_flush() fail because of open objects? */
+ if (ret_value<0) {
+ HGOTO_ERROR (H5E_SYM, H5E_CANTFLUSH, FAIL);
+ }
+
done:
if(ret_value == FAIL)
{ /* Error condition cleanup */
@@ -1180,7 +1207,7 @@ H5F_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent,
(unsigned)(f->file_create_parms.sharedheader_ver));
fprintf (stream, "%*sRoot symbol table entry:\n", indent, "");
- H5G_debug (f, f->root_sym, stream, indent+3, MAX(0, fwidth-3));
+ H5G_ent_debug (f, f->root_sym, stream, indent+3, MAX(0, fwidth-3));
FUNC_LEAVE (SUCCEED);
}
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
index f1c7b59..08cfd8f 100644
--- a/src/H5Fprivate.h
+++ b/src/H5Fprivate.h
@@ -352,6 +352,8 @@ typedef struct {
file_access_temp_t file_access_parms; /* File-access template */
#endif
struct H5G_entry_t *root_sym; /* Root symbol table entry */
+ uintn nshadows; /* Size of shadow hash table */
+ struct H5G_hash_t **shadow; /* The shadow hash table */
} hdf5_file_t;
diff --git a/src/H5G.c b/src/H5G.c
index 88c8576..0c38a00 100644
--- a/src/H5G.c
+++ b/src/H5G.c
@@ -47,11 +47,10 @@
#define H5G_INIT_HEAP 8192
#define PABLO_MASK H5G_mask
-static herr_t H5G_mkroot (hdf5_file_t *f, size_t size_hint);
-
/* Is the interface initialized? */
static hbool_t interface_initialize_g = FALSE;
+
/*-------------------------------------------------------------------------
* Function: H5G_component
@@ -315,6 +314,8 @@ H5G_namei (hdf5_file_t *f, H5G_entry_t *cwd, const char *name,
* is removed). If the root object doesn't have a name message
* then the name `Root Object' is used.
*
+ * Warning: This function has a few subtleties. Be warned!
+ *
* Errors:
* DIRECTORY CANTINIT Can't create root.
* DIRECTORY CANTINIT Can't insert old root object in
@@ -323,7 +324,9 @@ H5G_namei (hdf5_file_t *f, H5G_entry_t *cwd, const char *name,
*
* Return: Success: SUCCEED
*
- * Failure: FAIL
+ * Failure: FAIL. This function returns -2 if the
+ * failure is because a root directory already
+ * exists.
*
* Programmer: Robb Matzke
* robb@maya.nuance.com
@@ -336,104 +339,103 @@ H5G_namei (hdf5_file_t *f, H5G_entry_t *cwd, const char *name,
static herr_t
H5G_mkroot (hdf5_file_t *f, size_t size_hint)
{
+ H5G_entry_t *handle=NULL; /*handle to open object */
+ herr_t ret_value=FAIL; /*return value */
+ H5O_name_t name={NULL}; /*object name */
H5O_stab_t stab; /*symbol table message */
- H5O_name_t name={0}; /*object name message */
- H5G_entry_t root; /*old root entry */
- const char *root_name=NULL; /*name of old root object */
- intn nlinks; /*number of links */
- H5G_entry_t *handle; /*handle for open object */
+ H5G_entry_t *ent_ptr=NULL; /*pointer to a symbol table entry*/
+ const char *obj_name=NULL; /*name of old root object */
FUNC_ENTER (H5G_mkroot, NULL, FAIL);
/*
- * Make sure we have the latest info since someone might have the root
- * object open for modifications.
+ * Make sure that the file descriptor has the latest info -- someone might
+ * have the root object open.
*/
H5G_shadow_sync (f->root_sym);
/*
- * Is there already a root object that needs to move into the new
- * root symbol table? The root object is a symbol table if we can
- * read the H5O_STAB message.
+ * If we already have a root object, then open it and get it's name. The
+ * root object had better not already be a directory. Once the old root
+ * object is opened and we have a HANDLE, set the dirty bit on the handle.
+ * This causes the handle data to be written back into f->root_sym by
+ * H5G_close() if something goes wrong before the old root object is
+ * re-inserted back into the directory hierarchy. We might leak file
+ * memory, but at least we don't loose the original root object.
*/
if (f->root_sym->header>0) {
if (H5O_read (f, NO_ADDR, 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_name = name.s; /*dont reset name until root_name is done!*/
- root = *(f->root_sym);
-
+ HGOTO_ERROR (H5E_DIRECTORY, H5E_EXISTS, -2);
+ } else if (NULL==(handle=H5G_shadow_open (f, NULL, f->root_sym))) {
+ /* can't open root object */
+ HGOTO_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL);
+ } else if (NULL==H5O_read (f, NO_ADDR, handle, H5O_NAME, 0, &name)) {
+ obj_name = "Root Object";
} else {
- root = *(f->root_sym);
- root_name = "Root Object";
+ obj_name = name.s; /*don't reset message until the end!*/
}
+ handle->dirty = TRUE;
}
/*
- * Create the root directory.
+ * Create the new root directory directly into the file descriptor. If
+ * something goes wrong at this step, closing the `handle' will rewrite
+ * info back into f->root_sym because we set the dirty bit.
*/
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 root*/
+ HGOTO_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL); /*cant create root*/
+ }
+ if (1!=H5O_link (f, f->root_sym, 1)) {
+ HGOTO_ERROR (H5E_DIRECTORY, H5E_LINK, FAIL);
}
/*
- * Increase the link count for the root symbol table!
- */
- nlinks = H5O_link (f, f->root_sym->header, f->root_sym, 1);
- assert (1==nlinks);
-
- /*
- * Insert the old root object. It should already have a link count
- * of 1.
+ * If there was a previous root object then insert it into the new root
+ * symbol table with the specified name. Inserting the object will update
+ * the handle to point to the new symbol table slot instead of f->root_sym.
*/
- if (root_name) {
-
-#ifndef NDEBUG
- nlinks = H5O_link (f, root.header, &root, 0);
- assert (1==nlinks);
-#endif
- if (H5G_stab_insert (f, f->root_sym, root_name, &root)<0) {
- /*
- * This should never happen. If it does and the root object is
- * open, then bad things are going to happen because we've just
- * deleted the symbol table entry for the open root object!
- */
-#ifndef NDEBUG
- abort ();
-#endif
-
- /* can't insert old root object in new root directory */
- H5O_reset (H5O_NAME, &name);
- HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL);
+ if (obj_name) {
+ if (1!=H5O_link (f, handle, 0)) {
+ HGOTO_ERROR (H5E_DIRECTORY, H5E_LINK, FAIL);
}
-
- /* remove all name messages -- don't care if it fails */
- if ((handle = H5G_open (f, f->root_sym, root_name))) {
- H5O_remove (f, NO_ADDR, handle, H5O_NAME, H5O_ALL);
- H5G_shadow_close (f, handle);
- handle = NULL;
+ if (NULL==(ent_ptr=H5G_stab_insert (f, f->root_sym, obj_name,
+ handle))) {
+ HGOTO_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL);
}
- H5ECLEAR;
+
+ /*
+ * Remove all `name' messages from the old root object. The only time
+ * a name message should ever appear is to give the root object a name,
+ * but the old root object is no longer the root object.
+ */
+ H5O_remove (f, NO_ADDR, handle, H5O_NAME, H5O_ALL);
+ H5ECLEAR; /*who really cares?*/
}
-
+
+ ret_value = SUCCEED;
+
+ done:
+ /*
+ * If the handle is closed before the H5G_stab_insert() call that
+ * reinserts the root object into the directory hierarchy, then
+ * H5G_close() will reset f->root_sym to point to the old root symbol and
+ * the new root directory (if it was created) will be unlinked from the
+ * directory hierarchy (and memory leaked).
+ */
+ if (handle) H5G_close (f, handle);
H5O_reset (H5O_NAME, &name);
- FUNC_LEAVE (SUCCEED);
+
+ FUNC_LEAVE (ret_value);
}
/*-------------------------------------------------------------------------
- * Function: H5G_new
+ * Function: H5G_mkdir
*
- * 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.
+ * Purpose: Creates a new empty directory with the specified name,
+ * opening it as an object. The name is either an absolute name
+ * or is relative to the current working directory.
*
* A root directory is created implicitly by this function
* when necessary. Calling this function with the name "/"
@@ -448,12 +450,10 @@ H5G_mkroot (hdf5_file_t *f, size_t size_hint)
* DIRECTORY EXISTS Already exists.
* DIRECTORY NOTFOUND Missing component.
*
- * 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.
+ * Return: Success: A handle to the open directory. Please call
+ * H5G_close() when you're done with it.
*
- * Failure: FAIL, the memory pointed to by CWD is
- * not modified.
+ * Failure: NULL
*
* Programmer: Robb Matzke
* robb@maya.nuance.com
@@ -463,31 +463,43 @@ 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)
+H5G_entry_t *
+H5G_mkdir (hdf5_file_t *f, const char *name, size_t size_hint)
{
- const char *rest=NULL;
- H5G_entry_t _parent, _child;
- char _comp[1024];
- size_t nchars;
+ const char *rest=NULL; /*the base name */
+ H5G_entry_t *cwd=NULL; /*current working directory */
+ H5G_entry_t dir_ent; /*directory containing new dir */
+ H5G_entry_t ent; /*new directory entry */
+ H5G_entry_t *ent_ptr=NULL; /*ptr to new directory entry */
+ H5G_entry_t *ret_value=NULL; /*handle return value */
+ char _comp[1024]; /*name component */
+ size_t nchars; /*number of characters in compon*/
+ herr_t status; /*function return status */
- FUNC_ENTER (H5G_new, NULL, FAIL);
+ FUNC_ENTER (H5G_mkdir, NULL, NULL);
/* check args */
assert (f);
assert (name && *name);
+#ifndef LATER
+ /* Get current working directory */
+ H5G_shadow_sync (f->root_sym);
+ cwd = f->root_sym;
+#endif
assert (cwd || '/'==*name);
- if (!dir_ent) dir_ent = &_parent;
- if (!ent) ent = &_child;
- /* Create root directory if necessary */
- H5G_mkroot (f, H5G_SIZE_HINT);
+ /*
+ * Try to create the root directory. Ignore the error if this function
+ * fails because the root directory already exists.
+ */
+ if ((status=H5G_mkroot (f, H5G_SIZE_HINT))<0 && -2!=status) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL);
+ }
H5ECLEAR;
/* lookup name */
- if (H5G_namei (f, cwd, name, &rest, dir_ent)) {
- HRETURN_ERROR (H5E_DIRECTORY, H5E_EXISTS, FAIL); /*already exists*/
+ if (H5G_namei (f, cwd, name, &rest, &dir_ent)) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_EXISTS, NULL); /*already exists*/
}
H5ECLEAR; /*it's OK that we didn't find it*/
@@ -497,10 +509,10 @@ H5G_new (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
if (rest[nchars]) {
if (H5G_component (rest+nchars, NULL)) {
/* missing component */
- HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, FAIL);
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, NULL);
} else if (nchars+1 > sizeof _comp) {
/* component is too long */
- HRETURN_ERROR (H5E_DIRECTORY, H5E_COMPLEN, FAIL);
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_COMPLEN, NULL);
} else {
/* null terminate */
HDmemcpy (_comp, rest, nchars);
@@ -510,266 +522,165 @@ H5G_new (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
}
/* create directory */
- if (H5G_stab_new (f, ent, size_hint)<0) {
- HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL); /*can't create dir*/
+ if (H5G_stab_new (f, &ent, size_hint)<0) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL); /*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*/
+ if (NULL==(ent_ptr=H5G_stab_insert (f, &dir_ent, rest, &ent))) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL); /*can't insert*/
}
- FUNC_LEAVE (SUCCEED);
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5G_open
- *
- * Purpose: Opens an object. That is, it prepares the object for
- * modification by returning a handle to the object
- * symbol table entry. Opening an object twice with the
- * same name (or more precisely, through the same final
- * symbol table entry) will return pointers to the same
- * H5G_entry_t struct. But opening an object through
- * different final H5G_entry_t structs (which implies
- * different names) returns pointers to different
- * structs. The structs that are returned should be
- * released by calling H5G_close().
- *
- * Return: Success: Ptr to a handle for the object.
- *
- * Failure: NULL
- *
- * Programmer: Robb Matzke
- * Wednesday, September 17, 1997
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-H5G_entry_t *
-H5G_open (hdf5_file_t *f, H5G_entry_t *cwd, const char *name)
-{
- H5G_entry_t *ent=NULL;
- H5G_entry_t *handle=NULL;
- H5G_entry_t dir;
-
- FUNC_ENTER (H5G_open, NULL, NULL);
-
- /* check args */
- assert (f);
- assert (name && *name);
- assert (cwd || '/'==*name);
-
- if (f->root_sym->header<=0) {
- HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, NULL); /*object not found*/
- }
-
- if (NULL==(ent=H5G_namei (f, cwd, name, NULL, &dir))) {
- HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, NULL); /*object not found*/
- }
-
- if (NULL==(handle=H5G_shadow_open (f, &dir, ent))) {
- HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTOPENOBJ, NULL);
+ /* open the directory */
+ if (NULL==(ret_value=H5G_shadow_open (f, &dir_ent, ent_ptr))) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL); /*can't open*/
}
- FUNC_LEAVE (handle);
+ FUNC_LEAVE (ret_value);
}
/*-------------------------------------------------------------------------
- * Function: H5G_close
+ * Function: H5G_pushd
*
- * Purpose: Closes an object that was open for modification.
+ * Purpose: Pushes a new current working directory onto the stack.
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
* Programmer: Robb Matzke
- * Thursday, September 18, 1997
+ * Friday, September 19, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
-H5G_close (hdf5_file_t *f, H5G_entry_t *ent)
+H5G_pushd (hdf5_file_t *f, const char *name)
{
- FUNC_ENTER (H5G_close, NULL, FAIL);
+ FUNC_ENTER (H5G_pushd, NULL, FAIL);
- if (H5G_shadow_close (f, ent)<0) {
- HRETURN_ERROR (H5E_SYM, H5E_CANTFLUSH, FAIL);
+#ifndef LATER
+ /*
+ * Current working directories are not implemented yet.
+ */
+ if (strcmp (name, "/")) {
+ HRETURN_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, FAIL);
}
+#endif
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 (or all zero if
- * the returned object is the root object) 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).
+ * Function: H5G_popd
*
- * This function will fail if the root object is
- * requested and there is none.
- *
- * Errors:
- * DIRECTORY NOTFOUND Object not found.
+ * Purpose: Pops the top current working directory off the stack.
*
- * Return: Success: SUCCEED with DIR_ENT and ENT initialized. ENT
- * is intended for immediate read-only access.
- * If the object that ENT refers to is open
- * through the ENT entry (see H5G_open()) then
- * the returned ENT will contain the latest
- * information. However, subsequent changes to
- * the symbol table entry will not be reflected
- * in ENT since it is a copy of the symbol table.
+ * Return: Success: SUCCEED
*
* Failure: FAIL
*
* Programmer: Robb Matzke
- * robb@maya.nuance.com
- * Aug 12 1997
+ * Friday, September 19, 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)
+H5G_popd (hdf5_file_t *f)
{
- H5G_entry_t *ent_p = NULL;
- FUNC_ENTER (H5G_find, NULL, FAIL);
-
- /* check args */
- assert (f);
- assert (name && *name);
- assert (cwd || '/'==*name);
-
- if (f->root_sym->header<=0) {
- HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, FAIL); /*object not found*/
- }
+ FUNC_ENTER (H5G_popd, NULL, FAIL);
- if (NULL==(ent_p=H5G_namei (f, cwd, name, NULL, dir_ent))) {
- HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, FAIL); /*object not found*/
- }
+#ifndef LATER
+ /* CWD is not implemented yet. */
+#endif
- if (ent) *ent = *ent_p;
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 (or all
- * zero if the new ENT is the root object).
- *
- * This function attempts to use a non-directory file if
- * the file contains just one object. The one object
- * will be the root object.
- *
- * Inserting an object entry into the symbol table increments
- * the link counter for that object.
+ * Function: H5G_create
*
- * Errors:
- * DIRECTORY CANTINIT Can't insert.
- * DIRECTORY CANTINIT Cannot add/change name message.
- * DIRECTORY CANTINIT Lookup failed.
- * DIRECTORY COMPLEN Component is too long.
- * DIRECTORY EXISTS Already exists.
- * DIRECTORY EXISTS Root exists.
- * DIRECTORY LINK Bad link count.
- * DIRECTORY LINK Link inc failure.
- * DIRECTORY NOTFOUND Component not found.
+ * Purpose: Creates a new empty object header, gives it a name, opens
+ * the object for modification, and returns a handle to the
+ * object. The initial size of the object header can be
+ * supplied with the OHDR_HINT argument.
*
- * Return: Success: SUCCEED with optional DIR_ENT initialized with
- * the symbol table entry for the directory
- * which contains the new ENT.
+ * Return: Success: A handle for the object. Be sure to
+ * eventually close it.
*
- * Failure: FAIL (DIR_ENT is not modified).
+ * Failure: FAIL
*
* Programmer: Robb Matzke
- * robb@maya.nuance.com
- * Aug 11 1997
+ * Friday, September 19, 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)
+H5G_entry_t *
+H5G_create (hdf5_file_t *f, const char *name, size_t ohdr_hint)
{
- const char *rest=NULL;
- H5G_entry_t _parent;
- size_t nchars;
- char _comp[1024];
- H5O_stab_t stab;
+ H5G_entry_t ent; /*entry data for the new object */
+ H5G_entry_t *ent_ptr; /*ptr into symbol node for entry*/
+ H5G_entry_t *cwd=NULL; /*ptr to CWD handle */
+ const char *rest = NULL; /*part of name not existing yet */
+ H5G_entry_t dir; /*entry for dir to contain obj */
+ H5G_entry_t *ret_value=NULL; /*the object handle */
+ size_t nchars; /*number of characters in name */
+ char _comp[1024]; /*name component */
- FUNC_ENTER (H5G_insert, NULL, FAIL);
+ FUNC_ENTER (H5G_create, NULL, NULL);
- /* check args */
+ /* Check args. */
assert (f);
assert (name && *name);
- assert (cwd || '/'==*name);
- assert (ent);
- assert (!ent->shadow);
- if (!dir_ent) dir_ent = &_parent;
-
+ HDmemset (&ent, 0, sizeof(H5G_entry_t));
+
/*
- * If there's already an object or if this object is a directory then
- * create a root directory. The object is a directory if we can read
- * the symbol table message from its header. H5G_mkroot() fails if
- * the root object is already a directory, but we don't care.
+ * Get the current working directory.
*/
- if (f->root_sym->header>0 ||
- H5O_read (f, ent->header, ent, H5O_STAB, 0, &stab)) {
- H5G_mkroot (f, H5G_SIZE_HINT);
- H5ECLEAR;
- }
+#ifndef LATER
+ H5G_shadow_sync (f->root_sym);
+ cwd = f->root_sym;
+#endif
/*
* Look up the name -- it shouldn't exist yet.
*/
- if (H5G_namei (f, cwd, name, &rest, dir_ent)) {
- HRETURN_ERROR (H5E_DIRECTORY, H5E_EXISTS, FAIL); /*already exists*/
+ if (H5G_namei (f, cwd, name, &rest, &dir)) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_EXISTS, NULL); /*already exists*/
}
H5ECLEAR; /*it's OK that we didn't find it*/
-
- /*
- * The caller may be attempting to insert a root object that either
- * doesn't have a name or we shouldn't interfere with the name
- * it already has.
- */
rest = H5G_component (rest, &nchars);
+
if (!rest || !*rest) {
+ /*
+ * The caller is attempting to insert a root object that either
+ * doesn't have a name or we shouldn't interfere with the name
+ * it already has as a message.
+ */
if (f->root_sym->header>0) {
- HRETURN_ERROR (H5E_DIRECTORY, H5E_EXISTS, FAIL); /*root exists*/
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_EXISTS, NULL); /*root exists*/
+ }
+ if ((ent.header = H5O_new (f, 0, ohdr_hint))<0) {
+ /* can't create header */
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL);
}
- HDmemset (dir_ent, 0, sizeof(H5G_entry_t));
- if (1!=H5O_link (f, ent->header, ent, 1)) {
- HRETURN_ERROR (H5E_DIRECTORY, H5E_LINK, FAIL); /*bad link count*/
+ if (1!=H5O_link (f, &ent, 1)) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_LINK, NULL); /*bad link count*/
}
- *(f->root_sym) = *ent;
- HRETURN (SUCCEED);
+ *(f->root_sym) = ent;
+ if (NULL==(ret_value=H5G_shadow_open (f, &dir, f->root_sym))) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL);
+ }
+ HRETURN (ret_value);
}
/*
@@ -779,10 +690,10 @@ H5G_insert (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
if (rest[nchars]) {
if (H5G_component (rest+nchars, NULL)) {
/* component not found */
- HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, FAIL);
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, NULL);
} else if (nchars+1 > sizeof _comp) {
/* component is too long */
- HRETURN_ERROR (H5E_DIRECTORY, H5E_COMPLEN, FAIL);
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_COMPLEN, NULL);
} else {
/* null terminate */
HDmemcpy (_comp, rest, nchars);
@@ -792,654 +703,219 @@ H5G_insert (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
}
/*
- * If this is the only object then insert it as the root object. Add
- * a name messaage to the object header (or modify the first one we
- * find). We don't have to worry about it being open.
+ * Create the object header.
*/
+ if ((ent.header = H5O_new (f, 0, ohdr_hint))<0) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL);
+ }
+
+
if (f->root_sym->header<=0) {
+ /*
+ * This will be the only object in the file. Insert it as the root
+ * object and add a name messaage to the object header (or modify
+ * the first one we find). Although the header exists we can guarantee
+ * that it isn't open since it has no name.
+ */
H5O_name_t name_mesg;
name_mesg.s = rest;
- if (H5O_modify (f, NO_ADDR, ent, H5O_NAME, 0, &name_mesg)<0) {
+ if (H5O_modify (f, NO_ADDR, &ent, H5O_NAME, 0, &name_mesg)<0) {
/* cannot add/change name message */
- HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL);
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL);
}
- if (1!=H5O_link (f, ent->header, ent, 1)) {
- HRETURN_ERROR (H5E_DIRECTORY, H5E_LINK, FAIL); /*bad link count*/
+ if (1!=H5O_link (f, &ent, 1)) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_LINK, NULL); /*bad link count*/
}
- *(f->root_sym) = *ent;
- HRETURN (SUCCEED);
- }
-
- /* increment the link count */
- if (H5O_link (f, ent->header, ent, 1)<0) {
- HRETURN_ERROR (H5E_DIRECTORY, H5E_LINK, FAIL); /*link inc failure*/
- }
-
- /* insert entry into parent */
- if (H5G_stab_insert (f, dir_ent, rest, ent)<0) {
- H5O_link (f, ent->header, ent, -1); /*don't care if it fails*/
- HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL); /*can't insert*/
- }
-
- 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.
- *
- * 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.
- *
- * Errors:
- * INTERNAL CANTINIT B-tree's won't work if the first
- * name isn't at the beginning of the
- * heap.
- * SYM CANTINIT Can't create B-tree.
- * SYM CANTINIT Can't create header.
- * SYM CANTINIT Can't create heap.
- * SYM CANTINIT Can't create message.
- * SYM CANTINIT Can't initialize heap.
- *
- * Return: Success: Address of new symbol table header. If
- * the caller supplies a symbol table entry
- * SELF then it will be initialized to point to
- * this symbol table.
- *
- * Failure: FAIL
- *
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Aug 1 1997
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-haddr_t
-H5G_stab_new (hdf5_file_t *f, H5G_entry_t *self, size_t init)
-{
- off_t name; /*offset of "" name */
- haddr_t addr; /*object header address */
- H5O_stab_t stab; /*symbol table message */
-
- FUNC_ENTER (H5G_stab_new, NULL, FAIL);
-
- /*
- * Check arguments.
- */
- assert (f);
- init = MAX(init, H5H_SIZEOF_FREE(f)+2);
-
- /* Create symbol table private heap */
- if ((stab.heap_addr = H5H_new (f, H5H_LOCAL, init))<0) {
- HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); /*can't create heap*/
- }
- if ((name = H5H_insert (f, stab.heap_addr, 1, "")<0)) {
- HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); /*can't initialize heap*/
- }
- if (0!=name) {
+ *(f->root_sym) = ent;
+ if (NULL==(ret_value=H5G_shadow_open (f, &dir, f->root_sym))) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL);
+ }
+ HRETURN (ret_value);
+ } else {
/*
- * B-tree's won't work if the first name isn't at the beginning
- * of the heap.
+ * Make sure the root directory exists. Ignore the failure if it's
+ * because the directory already exists.
*/
- HRETURN_ERROR (H5E_INTERNAL, H5E_CANTINIT, FAIL);
- }
-
- /* Create the B-tree */
- if ((stab.btree_addr = H5B_new (f, H5B_SNODE))<0) {
- HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); /*can't create B-tree*/
+ hbool_t update_dir = (dir.header==f->root_sym->header);
+ herr_t status = H5G_mkroot (f, H5G_SIZE_HINT);
+ if (status<0 && -2!=status) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL);
+ }
+ H5ECLEAR;
+ if (update_dir) dir = *(f->root_sym);
}
-
+
/*
- * Create symbol table object header. It has a zero link count
- * since nothing refers to it yet. The link count will be
- * incremented if the object is added to the directory hierarchy.
+ * This is the normal case. The object is just being inserted as a normal
+ * entry into a symbol table.
*/
- if ((addr = H5O_new (f, 0, 4+2*H5F_SIZEOF_OFFSET(f)))<0) {
- HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); /*can't create header*/
+ if (H5O_link (f, &ent, 1)<0) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_LINK, NULL); /*link inc failure*/
}
-
- /* insert the symbol table message */
- if (self) {
- memset (self, 0, sizeof(H5G_entry_t));
- self->header = addr;
+ if (NULL==(ent_ptr=H5G_stab_insert (f, &dir, rest, &ent))) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL); /*can't insert*/
}
- if (H5O_modify(f, addr, self, H5O_STAB, H5O_NEW_MESG, &stab)<0) {
- HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); /*can't create message*/
+ if (NULL==(ret_value=H5G_shadow_open (f, &dir, ent_ptr))) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL); /*can't open object*/
}
-
- FUNC_LEAVE (addr);
+ FUNC_LEAVE (ret_value);
}
/*-------------------------------------------------------------------------
- * Function: H5G_stab_find
- *
- * Purpose: Finds a symbol named NAME in the symbol table whose
- * description is stored in SELF in file F and returns a
- * pointer to the symbol table entry. SELF is optional if the
- * symbol table address is supplied through ADDR.
+ * Function: H5G_open
*
- * Errors:
- * SYM BADMESG Can't read message.
- * SYM NOTFOUND Not found.
+ * Purpose: Opens an object. That is, it prepares the object for
+ * modification by returning a handle to the object
+ * symbol table entry. Opening an object twice with the
+ * same name (or more precisely, through the same final
+ * symbol table entry) will return pointers to the same
+ * H5G_entry_t struct. But opening an object through
+ * different final H5G_entry_t structs (which implies
+ * different names) returns pointers to different
+ * structs. The structs that are returned should be
+ * released by calling H5G_close().
*
- * Return: Success: Pointer to the symbol table entry.
- * The pointer is intended for immediate
- * read-only access since it points
- * directly to an entry in a cached
- * symbol table node. The pointer is
- * guaranteed to be valid only until the
- * next call to one of the H5AC functions.
+ * Return: Success: Ptr to a handle for the object.
*
* Failure: NULL
*
* Programmer: Robb Matzke
- * matzke@llnl.gov
- * Aug 1 1997
+ * Wednesday, September 17, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
H5G_entry_t *
-H5G_stab_find (hdf5_file_t *f, haddr_t addr, H5G_entry_t *self,
- const char *name)
+H5G_open (hdf5_file_t *f, const char *name)
{
- H5G_bt_ud1_t udata; /*data to pass through B-tree */
- H5O_stab_t stab; /*symbol table message */
-
- FUNC_ENTER (H5G_stab_find, NULL, NULL);
+ H5G_entry_t *ent=NULL;
+ H5G_entry_t *ret_value=NULL;
+ H5G_entry_t dir;
+ H5G_entry_t *cwd=NULL;
+
+ FUNC_ENTER (H5G_open, NULL, NULL);
- /* Check arguments */
+ /* check args */
assert (f);
- if (addr<=0 && (!self || self->header<=0)) {
- HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL);
- }
if (!name || !*name) {
- HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL);
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_BADVALUE, NULL);
}
- if (addr<=0) addr = self->header;
- /* set up the udata */
- if (NULL==H5O_read (f, addr, self, H5O_STAB, 0, &stab)) {
- HRETURN_ERROR (H5E_SYM, H5E_BADMESG, NULL); /*can't read message*/
- }
- udata.operation = H5G_OPER_FIND;
- udata.name = name;
- udata.heap_addr = stab.heap_addr;
- udata.dir_addr = addr;
+ /* Get CWD */
+#ifndef LATER
+ H5G_shadow_sync (f->root_sym);
+ cwd = f->root_sym;
+#endif
+ assert (cwd || '/'==*name);
- /* search the B-tree */
- if (H5B_find (f, H5B_SNODE, stab.btree_addr, &udata)<0) {
- HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL); /*not found*/
+ if (f->root_sym->header<=0) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, NULL); /*object not found*/
}
-
- /* return the result */
- FUNC_LEAVE (udata.entry_ptr);
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5G_stab_insert
- *
- * Purpose: Insert a new symbol into the table described by SELF in
- * file F. The name of the new symbol is NAME and its symbol
- * table entry is ENT.
- *
- * Errors:
- * SYM BADMESG Can't read message.
- * SYM CANTINSERT Can't insert entry.
- *
- * Return: Success: SUCCEED
- *
- * Failure: FAIL
- *
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Aug 1 1997
- *
- * Modifications:
- *
- * Robb Matzke, 18 Sep 1997
- * If ENT has a shadow, then the shadow will be associated with the
- * entry when it is added to the symbol table.
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5G_stab_insert (hdf5_file_t *f, H5G_entry_t *self, const char *name,
- H5G_entry_t *ent)
-{
- H5O_stab_t stab; /*symbol table message */
- H5G_bt_ud1_t udata; /*data to pass through B-tree */
-
- FUNC_ENTER (H5G_stab_insert, NULL, FAIL);
-
- /* check arguments */
- assert (f);
- assert (self && self->header>=0);
- assert (name && *name);
- assert (ent);
-
- /* 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); /*can't read message*/
+ if (NULL==(ent=H5G_namei (f, cwd, name, NULL, &dir))) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, NULL); /*object not found*/
}
-
- udata.operation = H5G_OPER_INSERT;
- udata.name = name;
- udata.heap_addr = stab.heap_addr;
- udata.dir_addr = self->header;
- udata.entry = *ent;
- udata.entry.name_off = -1;
-
- /* insert */
- if (H5B_insert (f, H5B_SNODE, stab.btree_addr, &udata)<0) {
- HRETURN_ERROR (H5E_SYM, H5E_CANTINSERT, FAIL); /*can't insert entry*/
+ if (NULL==(ret_value=H5G_shadow_open (f, &dir, ent))) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTOPENOBJ, NULL);
}
- /* update the name offset in the entry */
- ent->name_off = udata.entry.name_off;
- FUNC_LEAVE (SUCCEED);
+ FUNC_LEAVE (ret_value);
}
-
-/*-------------------------------------------------------------------------
- * Function: H5G_stab_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.
- *
- * Errors:
- * SYM BADMESG Not a symbol table.
- * SYM CANTLIST B-tree list failure.
- *
- * 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: FAIL, the pointers in NAMES are undefined but
- * no memory is allocated. The values in
- * ENTRIES are undefined.
- *
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Aug 1 1997
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-intn
-H5G_stab_list (hdf5_file_t *f, H5G_entry_t *self, intn maxentries,
- char *names[], H5G_entry_t entries[])
-{
- H5G_bt_ud2_t udata;
- H5O_stab_t stab;
- intn i;
-
- FUNC_ENTER (H5G_stab_list, NULL, FAIL);
-
- /* check args */
- assert (f);
- 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); /*not a symbol table*/
- }
- udata.entry = entries;
- udata.name = names;
- udata.dir_addr = self->header;
- udata.heap_addr = stab.heap_addr;
- udata.maxentries = maxentries;
- udata.nsyms = 0;
- if (names) HDmemset (names, 0, maxentries);
-
- /* list */
- if (H5B_list (f, H5B_SNODE, stab.btree_addr, &udata)<0) {
- if (names) {
- for (i=0; i<maxentries; i++) H5MM_xfree (names[i]);
- }
- HRETURN_ERROR (H5E_SYM, H5E_CANTLIST, FAIL); /*B-tree list failure*/
- }
- FUNC_LEAVE (udata.nsyms);
-}
-
/*-------------------------------------------------------------------------
- * Function: H5G_decode_vec
- *
- * Purpose: Same as H5G_decode() except it does it for an array of
- * symbol table entries.
+ * Function: H5G_close
*
- * Errors:
- * SYM CANTDECODE Can't decode.
+ * Purpose: Closes an object that was open for modification.
*
- * Return: Success: SUCCEED, with *pp pointing to the first byte
- * after the last symbol.
+ * Return: Success: SUCCEED
*
* Failure: FAIL
*
* Programmer: Robb Matzke
- * matzke@llnl.gov
- * Jul 18 1997
+ * Thursday, September 18, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
-H5G_decode_vec (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent, intn n)
+H5G_close (hdf5_file_t *f, H5G_entry_t *ent)
{
- intn i;
-
- FUNC_ENTER (H5G_decode_vec, NULL, FAIL);
+ FUNC_ENTER (H5G_close, NULL, FAIL);
- /* check arguments */
assert (f);
- assert (pp);
- assert (ent);
- assert (n>=0);
- /* decode entries */
- for (i=0; i<n; i++) {
- if (H5G_decode (f, pp, ent+i)<0) {
- HRETURN_ERROR (H5E_SYM, H5E_CANTDECODE, FAIL); /*can't decode*/
- }
+ if (ent && H5G_shadow_close (f, ent)<0) {
+ HRETURN_ERROR (H5E_SYM, H5E_CANTFLUSH, FAIL);
}
-
+
FUNC_LEAVE (SUCCEED);
}
/*-------------------------------------------------------------------------
- * Function: H5G_decode
- *
- * Purpose: Decodes a symbol table entry pointed to by `*pp'.
- *
- * Errors:
- *
- * Return: Success: SUCCEED with *pp pointing to the first byte
- * following the symbol table entry.
- *
- * Failure: FAIL
- *
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Jul 18 1997
- *
- * Modifications:
+ * Function: H5G_find
*
- *-------------------------------------------------------------------------
- */
-herr_t
-H5G_decode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent)
-{
- uint8 *p_ret = *pp;
-
- FUNC_ENTER (H5G_decode, NULL, FAIL);
-
- /* check arguments */
- assert (f);
- assert (pp);
- assert (ent);
-
- /* decode header */
- H5F_decode_offset (f, *pp, ent->name_off);
- H5F_decode_offset (f, *pp, ent->header);
- UINT32DECODE (*pp, ent->type);
-
- /* decode scratch-pad */
- switch (ent->type) {
- case H5G_NOTHING_CACHED:
- break;
-
- case H5G_CACHED_SDATA:
- ent->cache.sdata.nt.length= *(*pp)++;
- ent->cache.sdata.nt.arch= *(*pp)++;
- UINT16DECODE (*pp, ent->cache.sdata.nt.type);
- UINT32DECODE (*pp, ent->cache.sdata.ndim);
- UINT32DECODE (*pp, ent->cache.sdata.dim[0]);
- UINT32DECODE (*pp, ent->cache.sdata.dim[1]);
- UINT32DECODE (*pp, ent->cache.sdata.dim[2]);
- UINT32DECODE (*pp, ent->cache.sdata.dim[3]);
- break;
-
- case H5G_CACHED_STAB:
- UINT32DECODE (*pp, ent->cache.stab.btree_addr);
- UINT32DECODE (*pp, ent->cache.stab.heap_addr);
- break;
-
- default:
- HDabort();
- }
-
- *pp = p_ret + H5G_SIZEOF_ENTRY(f);
- FUNC_LEAVE (SUCCEED);
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5G_encode_vec
+ * 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 (or all zero if
+ * the returned object is the root object) 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).
*
- * Purpose: Same as H5G_encode() except it does it for an array of
- * symbol table entries.
+ * This function will fail if the root object is
+ * requested and there is none.
*
* Errors:
- * SYM CANTENCODE Can't encode.
+ * DIRECTORY NOTFOUND Object not found.
*
- * Return: Success: SUCCEED, with *pp pointing to the first byte
- * after the last symbol.
+ * Return: Success: SUCCEED with DIR_ENT and ENT initialized. ENT
+ * is intended for immediate read-only access.
+ * If the object that ENT refers to is open
+ * through the ENT entry (see H5G_open()) then
+ * the returned ENT will contain the latest
+ * information. However, subsequent changes to
+ * the symbol table entry will not be reflected
+ * in ENT since it is a copy of the symbol table.
*
* Failure: FAIL
*
* Programmer: Robb Matzke
- * matzke@llnl.gov
- * Jul 18 1997
+ * robb@maya.nuance.com
+ * Aug 12 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
-H5G_encode_vec (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent, intn n)
+H5G_find (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
+ const char *name, H5G_entry_t *ent)
{
- intn i;
-
- FUNC_ENTER (H5G_encode_vec, NULL, FAIL);
+ H5G_entry_t *ent_p = NULL;
+ FUNC_ENTER (H5G_find, NULL, FAIL);
- /* check arguments */
+ /* check args */
assert (f);
- assert (pp);
- assert (ent);
- assert (n>=0);
+ assert (name && *name);
+ assert (cwd || '/'==*name);
- /* encode entries */
- for (i=0; i<n; i++) {
- if (H5G_encode (f, pp, ent+i)<0) {
- HRETURN_ERROR (H5E_SYM, H5E_CANTENCODE, FAIL); /*can't encode*/
- }
+ if (f->root_sym->header<=0) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, FAIL); /*object not found*/
}
- FUNC_LEAVE (SUCCEED);
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5G_encode
- *
- * Purpose: Encodes the specified symbol table entry into the buffer
- * pointed to by *pp.
- *
- * Errors:
- *
- * Return: Success: SUCCEED, with *pp pointing to the first byte
- * after the symbol table entry.
- *
- * Failure: FAIL
- *
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Jul 18 1997
- *
- * Modifications:
- *
- * Robb Matzke, 8 Aug 1997
- * Writes zeros for the bytes that aren't used so the file doesn't
- * contain junk.
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5G_encode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent)
-{
- uint8 *p_ret = *pp + H5G_SIZEOF_ENTRY(f);
-
- FUNC_ENTER (H5G_encode, NULL, FAIL);
-
- /* check arguments */
- assert (f);
- assert (pp);
- assert (ent);
-
- /* encode header */
- H5F_encode_offset (f, *pp, ent->name_off);
- H5F_encode_offset (f, *pp, ent->header);
- UINT32ENCODE (*pp, ent->type);
-
- /* encode scratch-pad */
- switch (ent->type) {
- case H5G_NOTHING_CACHED:
- break;
-
- case H5G_CACHED_SDATA:
- *(*pp)++= ent->cache.sdata.nt.length;
- *(*pp)++= ent->cache.sdata.nt.arch;
- UINT16ENCODE (*pp, ent->cache.sdata.nt.type);
- UINT32ENCODE (*pp, ent->cache.sdata.ndim);
- UINT32ENCODE (*pp, ent->cache.sdata.dim[0]);
- UINT32ENCODE (*pp, ent->cache.sdata.dim[1]);
- UINT32ENCODE (*pp, ent->cache.sdata.dim[2]);
- UINT32ENCODE (*pp, ent->cache.sdata.dim[3]);
- break;
-
- case H5G_CACHED_STAB:
- UINT32ENCODE (*pp, ent->cache.stab.btree_addr);
- UINT32ENCODE (*pp, ent->cache.stab.heap_addr);
- break;
-
- default:
- HDabort();
+ if (NULL==(ent_p=H5G_namei (f, cwd, name, NULL, dir_ent))) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, FAIL); /*object not found*/
}
- /* fill with zero */
- while (*pp<p_ret) *(*pp)++ = 0;
-
- *pp = p_ret;
+ if (ent) *ent = *ent_p;
FUNC_LEAVE (SUCCEED);
}
-
-/*-------------------------------------------------------------------------
- * Function: H5G_debug
- *
- * Purpose: Prints debugging information about a symbol table entry.
- *
- * Errors:
- *
- * Return: Success: SUCCEED
- *
- * Failure: FAIL
- *
- * Programmer: Robb Matzke
- * robb@maya.nuance.com
- * Aug 29 1997
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5G_debug (hdf5_file_t *f, H5G_entry_t *ent, FILE *stream, intn indent,
- intn fwidth)
-{
- int i;
- char buf[64];
-
- FUNC_ENTER (H5G_debug, NULL, FAIL);
-
- fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth,
- "Name offset into private heap:",
- (unsigned long)(ent->name_off));
- fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth,
- "Object header address:",
- (unsigned long)(ent->header));
- fprintf (stream, "%*s%-*s %s\n", indent, "", fwidth,
- "Dirty:",
- ent->dirty ? "Yes" : "No");
- fprintf (stream, "%*s%-*s %s\n", indent, "", fwidth,
- "Has a shadow:",
- H5G_shadow_p (ent)?"This is a shadow!" :
- (ent->shadow ? "Yes" : "No"));
-
- fprintf (stream, "%*s%-*s ", indent, "", fwidth,
- "Symbol type:");
- switch (ent->type) {
- case H5G_NOTHING_CACHED:
- fprintf (stream, "Nothing Cached\n");
- break;
-
- case H5G_CACHED_SDATA:
- fprintf (stream, "S-data\n");
- fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth,
- "Number type length:",
- (unsigned)(ent->cache.sdata.nt.length));
- fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth,
- "Number type architecture:",
- (unsigned)(ent->cache.sdata.nt.arch));
- fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth,
- "Number type type:",
- (unsigned)(ent->cache.sdata.nt.type));
- fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth,
- "Dimensionality:",
- (unsigned)(ent->cache.sdata.ndim));
- for (i=0; i<ent->cache.sdata.ndim && i<4; i++) {
- sprintf (buf, "Dimension %d", i);
- fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth,
- buf,
- (unsigned)(ent->cache.sdata.dim[i]));
- }
- break;
-
- case H5G_CACHED_STAB:
- fprintf (stream, "Symbol Table\n");
- fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth,
- "B-tree address:",
- (unsigned long)(ent->cache.stab.btree_addr));
- fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth,
- "Heap address:",
- (unsigned long)(ent->cache.stab.heap_addr));
- break;
-
- default:
- fprintf (stream, "*** Unknown symbol type %d\n", ent->type);
- break;
- }
-
- FUNC_LEAVE (SUCCEED);
-}
diff --git a/src/H5Gent.c b/src/H5Gent.c
new file mode 100644
index 0000000..bc54161
--- /dev/null
+++ b/src/H5Gent.c
@@ -0,0 +1,488 @@
+/*
+ * Copyright (C) 1997 National Center for Supercomputing Applications.
+ * All rights reserved.
+ *
+ * Programmer: Robb Matzke <matzke@llnl.gov>
+ * Friday, September 19, 1997
+ */
+#define H5G_PACKAGE
+
+#include <H5private.h>
+#include <H5Eprivate.h>
+#include <H5Gpkg.h>
+#include <H5MMprivate.h>
+
+#define PABLO_MASK H5G_ent_mask
+
+static hbool_t interface_initialize_g = FALSE;
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_ent_calloc
+ *
+ * Purpose: Returns a pointer to a malloc'd, zeroed symbol table entry.
+ *
+ * Return: Success: Ptr to entry
+ *
+ * Failure: never fails
+ *
+ * Programmer: Robb Matzke
+ * Friday, September 19, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+H5G_entry_t *
+H5G_ent_calloc (void)
+{
+ return H5MM_xcalloc (1, sizeof(H5G_entry_t));
+}
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_ent_invalidate
+ *
+ * Purpose: Invalidates the cache in a symbol table entry.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Friday, September 19, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_ent_invalidate (H5G_entry_t *ent)
+{
+ FUNC_ENTER (H5G_ent_invalidate, NULL, FAIL);
+
+ if (ent && H5G_NOTHING_CACHED!=ent->type) {
+ ent->dirty = TRUE;
+ ent->type = H5G_NOTHING_CACHED;
+ }
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_ent_addr
+ *
+ * Purpose: Returns the header address associated with a symbol table
+ * entry.
+ *
+ * Return: Success: Address
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Friday, September 19, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+haddr_t
+H5G_ent_addr (H5G_entry_t *ent)
+{
+ FUNC_ENTER (H5G_ent_addr, NULL, FAIL);
+ assert (ent);
+
+ FUNC_LEAVE (ent->header);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_ent_cache
+ *
+ * Purpose: Returns a pointer to the cache associated with the symbol
+ * table entry. You should modify the cache directly, then call
+ * H5G_modified() with the new cache type (even if the type is
+ * still the same).
+ *
+ * Return: Success: Ptr to the cache in the symbol table entry.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Friday, September 19, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+H5G_cache_t *
+H5G_ent_cache (H5G_entry_t *ent, H5G_type_t *cache_type)
+{
+ FUNC_ENTER (H5G_ent_cache, NULL, NULL);
+ if (!ent) {
+ HRETURN_ERROR (H5E_SYM, H5E_BADVALUE, NULL);
+ }
+ if (cache_type) *cache_type = ent->type;
+
+ FUNC_LEAVE (&(ent->cache));
+}
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_ent_modified
+ *
+ * Purpose: This function should be called after you make any
+ * modifications to a symbol table entry cache. Supply the new
+ * type for the cache. If CACHE_TYPE is the constant
+ * H5G_NO_CHANGE then the cache type isn't changed--just the
+ * dirty bit is set.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Friday, September 19, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_ent_modified (H5G_entry_t *ent, H5G_type_t cache_type)
+{
+ FUNC_ENTER (H5G_ent_modified, NULL, FAIL);
+ assert (ent);
+ if (H5G_NO_CHANGE!=ent->type) ent->type = cache_type;
+ ent->dirty = TRUE;
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_ent_decode_vec
+ *
+ * Purpose: Same as H5G_ent_decode() except it does it for an array of
+ * symbol table entries.
+ *
+ * Errors:
+ * SYM CANTDECODE Can't decode.
+ *
+ * Return: Success: SUCCEED, with *pp pointing to the first byte
+ * after the last symbol.
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Jul 18 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_ent_decode_vec (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent, intn n)
+{
+ intn i;
+
+ FUNC_ENTER (H5G_ent_decode_vec, NULL, FAIL);
+
+ /* check arguments */
+ assert (f);
+ assert (pp);
+ assert (ent);
+ assert (n>=0);
+
+ /* decode entries */
+ for (i=0; i<n; i++) {
+ if (H5G_ent_decode (f, pp, ent+i)<0) {
+ HRETURN_ERROR (H5E_SYM, H5E_CANTDECODE, FAIL); /*can't decode*/
+ }
+ }
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_ent_decode
+ *
+ * Purpose: Decodes a symbol table entry pointed to by `*pp'.
+ *
+ * Errors:
+ *
+ * Return: Success: SUCCEED with *pp pointing to the first byte
+ * following the symbol table entry.
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Jul 18 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_ent_decode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent)
+{
+ uint8 *p_ret = *pp;
+
+ FUNC_ENTER (H5G_ent_decode, NULL, FAIL);
+
+ /* check arguments */
+ assert (f);
+ assert (pp);
+ assert (ent);
+
+ /* decode header */
+ H5F_decode_offset (f, *pp, ent->name_off);
+ H5F_decode_offset (f, *pp, ent->header);
+ UINT32DECODE (*pp, ent->type);
+
+ /* decode scratch-pad */
+ switch (ent->type) {
+ case H5G_NOTHING_CACHED:
+ break;
+
+ case H5G_CACHED_SDATA:
+ ent->cache.sdata.nt.length= *(*pp)++;
+ ent->cache.sdata.nt.arch= *(*pp)++;
+ UINT16DECODE (*pp, ent->cache.sdata.nt.type);
+ UINT32DECODE (*pp, ent->cache.sdata.ndim);
+ UINT32DECODE (*pp, ent->cache.sdata.dim[0]);
+ UINT32DECODE (*pp, ent->cache.sdata.dim[1]);
+ UINT32DECODE (*pp, ent->cache.sdata.dim[2]);
+ UINT32DECODE (*pp, ent->cache.sdata.dim[3]);
+ break;
+
+ case H5G_CACHED_STAB:
+ UINT32DECODE (*pp, ent->cache.stab.btree_addr);
+ UINT32DECODE (*pp, ent->cache.stab.heap_addr);
+ break;
+
+ default:
+ HDabort();
+ }
+
+ *pp = p_ret + H5G_SIZEOF_ENTRY(f);
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_ent_encode_vec
+ *
+ * Purpose: Same as H5G_ent_encode() except it does it for an array of
+ * symbol table entries.
+ *
+ * Errors:
+ * SYM CANTENCODE Can't encode.
+ *
+ * Return: Success: SUCCEED, with *pp pointing to the first byte
+ * after the last symbol.
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Jul 18 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_ent_encode_vec (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent, intn n)
+{
+ intn i;
+
+ FUNC_ENTER (H5G_ent_encode_vec, NULL, FAIL);
+
+ /* check arguments */
+ assert (f);
+ assert (pp);
+ assert (ent);
+ assert (n>=0);
+
+ /* encode entries */
+ for (i=0; i<n; i++) {
+ if (H5G_ent_encode (f, pp, ent+i)<0) {
+ HRETURN_ERROR (H5E_SYM, H5E_CANTENCODE, FAIL); /*can't encode*/
+ }
+ }
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_ent_encode
+ *
+ * Purpose: Encodes the specified symbol table entry into the buffer
+ * pointed to by *pp.
+ *
+ * Errors:
+ *
+ * Return: Success: SUCCEED, with *pp pointing to the first byte
+ * after the symbol table entry.
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Jul 18 1997
+ *
+ * Modifications:
+ *
+ * Robb Matzke, 8 Aug 1997
+ * Writes zeros for the bytes that aren't used so the file doesn't
+ * contain junk.
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_ent_encode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent)
+{
+ uint8 *p_ret = *pp + H5G_SIZEOF_ENTRY(f);
+
+ FUNC_ENTER (H5G_ent_encode, NULL, FAIL);
+
+ /* check arguments */
+ assert (f);
+ assert (pp);
+ assert (ent);
+
+ /* encode header */
+ H5F_encode_offset (f, *pp, ent->name_off);
+ H5F_encode_offset (f, *pp, ent->header);
+ UINT32ENCODE (*pp, ent->type);
+
+ /* encode scratch-pad */
+ switch (ent->type) {
+ case H5G_NOTHING_CACHED:
+ break;
+
+ case H5G_CACHED_SDATA:
+ *(*pp)++= ent->cache.sdata.nt.length;
+ *(*pp)++= ent->cache.sdata.nt.arch;
+ UINT16ENCODE (*pp, ent->cache.sdata.nt.type);
+ UINT32ENCODE (*pp, ent->cache.sdata.ndim);
+ UINT32ENCODE (*pp, ent->cache.sdata.dim[0]);
+ UINT32ENCODE (*pp, ent->cache.sdata.dim[1]);
+ UINT32ENCODE (*pp, ent->cache.sdata.dim[2]);
+ UINT32ENCODE (*pp, ent->cache.sdata.dim[3]);
+ break;
+
+ case H5G_CACHED_STAB:
+ UINT32ENCODE (*pp, ent->cache.stab.btree_addr);
+ UINT32ENCODE (*pp, ent->cache.stab.heap_addr);
+ break;
+
+ default:
+ HDabort();
+ }
+
+ /* fill with zero */
+ while (*pp<p_ret) *(*pp)++ = 0;
+
+ *pp = p_ret;
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_ent_debug
+ *
+ * Purpose: Prints debugging information about a symbol table entry.
+ *
+ * Errors:
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Aug 29 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_ent_debug (hdf5_file_t *f, H5G_entry_t *ent, FILE *stream, intn indent,
+ intn fwidth)
+{
+ int i;
+ char buf[64];
+
+ FUNC_ENTER (H5G_ent_debug, NULL, FAIL);
+
+ fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth,
+ "Name offset into private heap:",
+ (unsigned long)(ent->name_off));
+ fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth,
+ "Object header address:",
+ (unsigned long)(ent->header));
+ fprintf (stream, "%*s%-*s %s\n", indent, "", fwidth,
+ "Dirty:",
+ ent->dirty ? "Yes" : "No");
+ fprintf (stream, "%*s%-*s %s\n", indent, "", fwidth,
+ "Has a shadow:",
+ H5G_shadow_p (ent)?"This is a shadow!" :
+ (ent->shadow ? "Yes" : "No"));
+
+ fprintf (stream, "%*s%-*s ", indent, "", fwidth,
+ "Symbol type:");
+ switch (ent->type) {
+ case H5G_NOTHING_CACHED:
+ fprintf (stream, "Nothing Cached\n");
+ break;
+
+ case H5G_CACHED_SDATA:
+ fprintf (stream, "S-data\n");
+ fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth,
+ "Number type length:",
+ (unsigned)(ent->cache.sdata.nt.length));
+ fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth,
+ "Number type architecture:",
+ (unsigned)(ent->cache.sdata.nt.arch));
+ fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth,
+ "Number type type:",
+ (unsigned)(ent->cache.sdata.nt.type));
+ fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth,
+ "Dimensionality:",
+ (unsigned)(ent->cache.sdata.ndim));
+ for (i=0; i<ent->cache.sdata.ndim && i<4; i++) {
+ sprintf (buf, "Dimension %d", i);
+ fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth,
+ buf,
+ (unsigned)(ent->cache.sdata.dim[i]));
+ }
+ break;
+
+ case H5G_CACHED_STAB:
+ fprintf (stream, "Symbol Table\n");
+ fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth,
+ "B-tree address:",
+ (unsigned long)(ent->cache.stab.btree_addr));
+ fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth,
+ "Heap address:",
+ (unsigned long)(ent->cache.stab.heap_addr));
+ break;
+
+ default:
+ fprintf (stream, "*** Unknown symbol type %d\n", ent->type);
+ break;
+ }
+
+ FUNC_LEAVE (SUCCEED);
+}
diff --git a/src/H5Gnode.c b/src/H5Gnode.c
index aa3175c..ffa1f86 100644
--- a/src/H5Gnode.c
+++ b/src/H5Gnode.c
@@ -60,7 +60,7 @@ static herr_t H5G_node_list (hdf5_file_t *f, haddr_t addr, void *_udata);
static size_t H5G_node_sizeof_rkey (hdf5_file_t *f);
/* H5G inherits cache-like properties from H5AC */
-static const H5AC_class_t H5AC_SNODE[1] = {{
+const H5AC_class_t H5AC_SNODE[1] = {{
(void*(*)(hdf5_file_t*,haddr_t,void*))H5G_node_load,
(herr_t(*)(hdf5_file_t*,hbool_t,haddr_t,void*))H5G_node_flush,
}};
@@ -310,6 +310,7 @@ H5G_node_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5G_node_t *sym)
if (H5G_shadow_sync (sym->entry+i)<0) {
HRETURN_ERROR (H5E_SYM, H5E_CANTFLUSH, FAIL);
}
+ if (sym->entry[i].dirty) sym->dirty = TRUE;
}
/*
@@ -333,7 +334,7 @@ H5G_node_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5G_node_t *sym)
UINT16ENCODE (p, sym->nsyms);
/* entries */
- H5G_encode_vec (f, &p, sym->entry, sym->nsyms);
+ H5G_ent_encode_vec (f, &p, sym->entry, sym->nsyms);
HDmemset (p, 0, size - (p-buf));
status = H5F_block_write (f, addr, size, buf);
@@ -424,7 +425,7 @@ H5G_node_load (hdf5_file_t *f, haddr_t addr, void *_udata)
UINT16DECODE (p, sym->nsyms);
/* entries */
- if (H5G_decode_vec (f, &p, sym->entry, sym->nsyms)<0) {
+ if (H5G_ent_decode_vec (f, &p, sym->entry, sym->nsyms)<0) {
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, NULL);
}
buf = H5MM_xfree (buf);
@@ -588,6 +589,8 @@ H5G_node_found (hdf5_file_t *f, haddr_t addr, const void *_lt_key,
*/
H5G_shadow_sync (sn->entry+idx);
bt_udata->entry_ptr = sn->entry+idx;
+ bt_udata->node_addr = addr;
+ bt_udata->node_ptr = sn;
break;
default:
@@ -597,9 +600,17 @@ H5G_node_found (hdf5_file_t *f, haddr_t addr, const void *_lt_key,
ret_value = SUCCEED;
done:
- if (sn && H5AC_unprotect (f, H5AC_SNODE, addr, sn)<0) {
- HRETURN_ERROR (H5E_SYM, H5E_PROTECT, FAIL);
+ /*
+ * Don't unprotect the symbol table entry if we're returning success since
+ * this might invalidate the bt_udata->entry_ptr and bt_udata->node_ptr
+ * pointers. Instead, we unprotect it in H5G_stab_find().
+ */
+ if (ret_value<0) {
+ if (sn && H5AC_unprotect (f, H5AC_SNODE, addr, sn)<0) {
+ HRETURN_ERROR (H5E_SYM, H5E_PROTECT, FAIL);
+ }
}
+
FUNC_LEAVE (ret_value);
}
@@ -663,6 +674,8 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor,
intn i;
haddr_t ret_value = FAIL;
H5G_shadow_t *shadow = NULL;
+ H5G_node_t *insert_into=NULL; /*node that gets new entry*/
+ haddr_t insert_addr=-1; /*address of that node */
FUNC_ENTER (H5G_node_insert, NULL, FAIL);
@@ -675,6 +688,8 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor,
assert (md_key);
assert (rt_key);
assert (bt_udata);
+ bt_udata->node_addr = -1;
+ bt_udata->node_ptr = NULL;
bt_udata->entry_ptr = NULL;
/*
@@ -757,90 +772,77 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor,
sn->nsyms = H5G_NODE_K (f);
sn->dirty += 1;
- /* Insert the new entry */
- if (idx<=H5G_NODE_K(f)) {
-
- /* Adjust shadows */
- for (i=idx; i<sn->nsyms; i++) {
- if (sn->entry[i].shadow) {
- sn->entry[i].shadow->main = sn->entry + i + 1;
- }
- }
- if (bt_udata->entry.shadow) {
- bt_udata->entry.shadow->main = sn->entry + idx;
- }
+ /* The middle key */
+ md_key->offset = sn->entry[sn->nsyms-1].name_off;
- /* Move entries */
- HDmemmove (sn->entry + idx + 1,
- sn->entry + idx,
- (H5G_NODE_K(f)-idx) * sizeof(H5G_entry_t));
- sn->entry[idx] = bt_udata->entry;
- sn->entry[idx].name_off = offset;
- sn->entry[idx].dirty = TRUE;
- sn->nsyms += 1;
-
+ /* Where to insert the new entry? */
+ if (idx<=H5G_NODE_K(f)) {
+ insert_into = sn;
+ insert_addr = addr;
+ if (idx==H5G_NODE_K(f)) md_key->offset = offset;
} else {
idx -= H5G_NODE_K (f);
-
- /* Adjust shadows */
- for (i=idx; i<snrt->nsyms; i++) {
- if (snrt->entry[i].shadow) {
- snrt->entry[i].shadow->main = snrt->entry + i + 1;
- }
- }
- if (bt_udata->entry.shadow) {
- bt_udata->entry.shadow->main = snrt->entry + idx;
- }
-
- /* Move entries */
- HDmemmove (snrt->entry + idx + 1,
- snrt->entry + idx,
- (H5G_NODE_K(f)-idx) * sizeof (H5G_entry_t));
- snrt->entry[idx] = bt_udata->entry;
- snrt->entry[idx].name_off = offset;
- snrt->entry[idx].dirty = TRUE;
- snrt->nsyms += 1;
-
- if (idx+1 == sn->nsyms) {
- rt_key->offset = offset;
- *rt_key_changed = TRUE;
- }
+ insert_into = snrt;
+ insert_addr = new_node;
}
-
- /* The middle key */
- md_key->offset = sn->entry[sn->nsyms-1].name_off;
+ ret_value = new_node;
} else {
- /*
- * Add the new symbol to the node.
- */
+ /* Where to insert the new entry? */
sn->dirty += 1;
- for (i=idx; i<sn->nsyms; i++) {
- if (sn->entry[i].shadow) {
- sn->entry[i].shadow->main = sn->entry + i + 1;
- }
- }
- if (bt_udata->entry.shadow) {
- bt_udata->entry.shadow->main = sn->entry + idx;
- }
- HDmemmove (sn->entry+idx+1, sn->entry+idx,
- (sn->nsyms-idx) * sizeof (H5G_entry_t));
- sn->nsyms += 1;
- sn->entry[idx] = bt_udata->entry;
- sn->entry[idx].name_off = offset;
- sn->entry[idx].dirty = TRUE;
-
- if (idx+1==sn->nsyms) {
+ insert_into = sn;
+ insert_addr = addr;
+ if (idx==sn->nsyms) {
rt_key->offset = offset;
*rt_key_changed = TRUE;
}
+ ret_value = 0;
+ }
+
+ /* Adjust shadows */
+ for (i=idx; i<insert_into->nsyms; i++) {
+ if (insert_into->entry[i].shadow) {
+ insert_into->entry[i].shadow->main = insert_into->entry + i + 1;
+ }
+ }
+ if (bt_udata->entry.shadow) {
+ H5G_shadow_move (f, bt_udata->entry.shadow,
+ bt_udata->name,
+ insert_into->entry + idx,
+ bt_udata->dir_addr);
}
- ret_value = new_node; /*successful return */
+ /* Move entries */
+ HDmemmove (insert_into->entry + idx + 1,
+ insert_into->entry + idx,
+ (insert_into->nsyms-idx) * sizeof(H5G_entry_t));
+ insert_into->entry[idx] = bt_udata->entry;
+ insert_into->entry[idx].name_off = offset;
+ insert_into->entry[idx].dirty = TRUE;
+ insert_into->nsyms += 1;
+
+ /* Update udata return values */
+ bt_udata->node_addr = insert_addr;
+ bt_udata->node_ptr = insert_into;
+ bt_udata->entry_ptr = insert_into->entry + idx;
done:
- if (sn && H5AC_unprotect (f, H5AC_SNODE, addr, sn)<0) {
- HRETURN_ERROR (H5E_SYM, H5E_PROTECT, FAIL);
+ if (ret_value<0) {
+ /* failing... */
+ if (sn && H5AC_unprotect (f, H5AC_SNODE, addr, sn)<0) {
+ HRETURN_ERROR (H5E_SYM, H5E_PROTECT, FAIL);
+ }
+ } else if (insert_into!=sn) {
+ /* unprotect the first node and protect the return value */
+ if (H5AC_unprotect (f, H5AC_SNODE, addr, sn)<0) {
+ HRETURN_ERROR (H5E_SYM, H5E_PROTECT, FAIL);
+ }
+ if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, insert_addr, &ac_udata))) {
+ HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL);
+ }
+ assert (sn==bt_udata->node_ptr);
+ } else {
+ /* keep the node protected until we get back to H5G_stab_insert() */
}
FUNC_LEAVE (ret_value);
@@ -988,7 +990,7 @@ H5G_node_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent,
* If we couldn't load the symbol table node, then try loading the
* B-tree node.
*/
- if (NULL==(sn=H5AC_find(f, H5AC_SNODE, addr, NULL))) {
+ if (NULL==(sn=H5AC_find(f, H5AC_SNODE, addr, &ac_udata))) {
H5ECLEAR; /*discard that error*/
status = H5B_debug (f, addr, stream, indent, fwidth, H5B_SNODE);
if (status<0) HRETURN_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL);
@@ -1019,7 +1021,7 @@ H5G_node_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent,
"Name:",
s);
}
- H5G_debug (f, sn->entry+i, stream, indent, fwidth);
+ H5G_ent_debug (f, sn->entry+i, stream, indent, fwidth);
fprintf (stream, "%*s%-*s %s\n", indent+3, "", MAX (0, fwidth-3),
"Shadow:",
sn->entry[i].shadow ? "Yes":"No");
diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h
index c5ccae9..74881f7 100644
--- a/src/H5Gpkg.h
+++ b/src/H5Gpkg.h
@@ -16,6 +16,7 @@
#ifndef _H5Gpkg_H
#define _H5Gpkg_H
+#include <H5ACprivate.h>
#include <H5Gprivate.h>
#define H5G_NODE_VERS 1 /*symbol table node version number */
@@ -24,6 +25,20 @@
#define H5G_NODE_SIZEOF_HDR(F) (H5G_NODE_SIZEOF_MAGIC + 4)
#define H5G_DEFAULT_ROOT_SIZE 32
+/*
+ * A symbol table entry. The two important fields are `name_off' and
+ * `header'. The remaining fields are used for caching information that
+ * also appears in the object header to which this symbol table entry
+ * points.
+ */
+struct H5G_entry_t {
+ hbool_t dirty; /*entry out-of-date? */
+ off_t name_off; /*offset of name within name heap */
+ haddr_t header; /*file address of object header */
+ H5G_type_t type; /*type of information cached */
+ H5G_cache_t cache; /*cached data from object header */
+ H5G_shadow_t *shadow; /*optional ptr to the shadow */
+};
/*
* A shadow is a copy of a symbol table entry which corresponds to an
@@ -68,7 +83,7 @@ typedef struct H5G_node_key_t {
*/
typedef enum H5G_oper_t {
H5G_OPER_FIND =0, /*find a symbol */
- H5G_OPER_INSERT =1, /*insert a new symbol */
+ H5G_OPER_INSERT =1 /*insert a new symbol */
} H5G_oper_t;
/*
@@ -87,7 +102,9 @@ typedef struct H5G_bt_ud1_t {
/* downward for INSERT */
H5G_entry_t entry; /*entry to insert into table */
- /* upward for FIND */
+ /* upward for FIND and INSERT */
+ haddr_t node_addr; /*address of node for this entry */
+ H5G_node_t *node_ptr; /*ptr to the node containing the entry */
H5G_entry_t *entry_ptr; /*ptr into cached symbol table node */
} H5G_bt_ud1_t;
@@ -123,6 +140,9 @@ typedef struct H5G_ac_ud1_t {
haddr_t dir_addr;
} H5G_ac_ud1_t;
+/* The cache subclass */
+extern const H5AC_class_t H5AC_SNODE[1];
+
/*
* Functions that understand symbol tables but not directories. The
* functions that understand directories are exported to the rest of
@@ -131,8 +151,8 @@ typedef struct H5G_ac_ud1_t {
haddr_t H5G_stab_new (hdf5_file_t *f, H5G_entry_t *self, size_t init);
H5G_entry_t *H5G_stab_find (hdf5_file_t *f, haddr_t addr, H5G_entry_t *self,
const char *name);
-herr_t H5G_stab_insert (hdf5_file_t *f, H5G_entry_t *self, const char *name,
- H5G_entry_t *ent);
+H5G_entry_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[]);
@@ -147,12 +167,17 @@ hbool_t H5G_shadow_p (H5G_entry_t *ent);
herr_t H5G_shadow_dissociate (H5G_entry_t *ent);
herr_t H5G_shadow_assoc_node (hdf5_file_t *f, H5G_node_t *sym,
H5G_ac_ud1_t *ac_udata);
-H5G_shadow_t *H5G_shadow_list (haddr_t stab_header_addr);
+H5G_shadow_t *H5G_shadow_list (hdf5_file_t *f, haddr_t stab_header_addr);
+herr_t H5G_shadow_move (hdf5_file_t *f, H5G_shadow_t *shadow,
+ const char *new_name, H5G_entry_t *new_entry,
+ haddr_t dir_addr);
/*
* Functions that understand symbol table entries.
*/
-herr_t H5G_decode_vec (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent, intn n);
-herr_t H5G_encode_vec (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent, intn n);
+herr_t H5G_ent_decode_vec (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent,
+ intn n);
+herr_t H5G_ent_encode_vec (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent,
+ intn n);
#endif
diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h
index dd26902..97355c2 100644
--- a/src/H5Gprivate.h
+++ b/src/H5Gprivate.h
@@ -25,7 +25,8 @@
#define H5G_NODE_MAGIC "SNOD" /*symbol table node magic number */
#define H5G_NODE_SIZEOF_MAGIC 4 /*sizeof symbol node magic number */
-#define H5G_new_entry() H5MM_xcalloc (1, sizeof(H5G_entry_t))
+#define H5G_NO_CHANGE (-1) /*see H5G_ent_modified() */
+#define H5G_NSHADOWS 10331 /*default size of shadow hash table */
/*
* The disk size for a symbol table entry...
@@ -75,41 +76,46 @@ typedef union H5G_cache_t {
* important outside H5G.
*/
typedef struct H5G_shadow_t H5G_shadow_t;
+typedef struct H5G_entry_t H5G_entry_t;
/*
- * A symbol table entry. The two important fields are `name_off' and
- * `header'. The remaining fields are used for caching information that
- * also appears in the object header to which this symbol table entry
- * points.
+ * Library prototypes... These are the ones that other packages routinely
+ * call.
*/
-typedef struct H5G_entry_t {
- hbool_t dirty; /*entry out-of-date? */
- off_t name_off; /*offset of name within name heap */
- haddr_t header; /*file address of object header */
- H5G_type_t type; /*type of information cached */
- H5G_cache_t cache; /*cached data from object header */
- H5G_shadow_t *shadow; /*optional ptr to the shadow */
-} H5G_entry_t;
-
-/*
- * Library prototypes...
- */
-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);
-H5G_entry_t *H5G_open (hdf5_file_t *f, H5G_entry_t *cwd, const char *name);
+H5G_entry_t *H5G_mkdir (hdf5_file_t *f, const char *name, size_t size_hint);
+herr_t H5G_pushd (hdf5_file_t *f, const char *name);
+herr_t H5G_popd (hdf5_file_t *f);
+H5G_entry_t *H5G_create (hdf5_file_t *f, const char *name, size_t ohdr_hint);
+H5G_entry_t *H5G_open (hdf5_file_t *f, const char *name);
herr_t H5G_close (hdf5_file_t *f, 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_set_root (hdf5_file_t *f, const char *name, H5G_entry_t *ent);
-herr_t H5G_encode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent);
-herr_t H5G_decode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent);
-herr_t H5G_debug (hdf5_file_t *f, H5G_entry_t *ent, FILE *stream, intn indent,
- intn fwidth);
+herr_t H5G_ent_encode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent);
+herr_t H5G_ent_decode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent);
+
+/*
+ * These functions operate on symbol table nodes.
+ */
herr_t H5G_node_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent,
intn fwidth, haddr_t heap);
+/*
+ * These functions operate on shadow entries.
+ */
+herr_t H5G_shadow_flush (hdf5_file_t *f, hbool_t invalidate);
+
+/*
+ * These functions operate on symbol table entries. They're used primarily
+ * in the H5O package where header messages are cached in symbol table
+ * entries. The subclasses of H5O probably don't need them though.
+ */
+H5G_entry_t *H5G_ent_calloc (void);
+herr_t H5G_ent_invalidate (H5G_entry_t *ent);
+haddr_t H5G_ent_addr (H5G_entry_t *ent);
+H5G_cache_t *H5G_ent_cache (H5G_entry_t *ent, H5G_type_t *cache_type);
+herr_t H5G_ent_modified (H5G_entry_t *ent, H5G_type_t cache_type);
+herr_t H5G_ent_debug (hdf5_file_t *f, H5G_entry_t *ent, FILE *stream,
+ intn indent, intn fwidth);
#endif
diff --git a/src/H5Gshad.c b/src/H5Gshad.c
index 6dc997f..315abed 100644
--- a/src/H5Gshad.c
+++ b/src/H5Gshad.c
@@ -15,13 +15,11 @@
#include <H5Oprivate.h> /*object header messages */
#define PABLO_MASK H5G_shadow_mask
+#undef DEBUG_SHADOWS
/* Is the interface initialized? */
static hbool_t interface_initialize_g = FALSE;
-/* Shadow hash table */
-#define H5G_NSHADOWS 10331
-
typedef struct H5G_hash_t {
haddr_t dir_addr;
H5G_shadow_t *head;
@@ -29,8 +27,92 @@ typedef struct H5G_hash_t {
struct H5G_hash_t *prev;
} H5G_hash_t;
-static H5G_hash_t *H5G_shadow_g[H5G_NSHADOWS];
-
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_shadow_check
+ *
+ * Purpose: Checks the shadow data structures for validity. This is a
+ * debugging function only--it aborts on failure!
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * Sunday, September 21, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifdef DEBUG_SHADOWS
+void
+H5G_shadow_check (hdf5_file_t *f)
+{
+ H5G_hash_t *hash=NULL;
+ H5G_shadow_t *shadow=NULL, *prev_shadow=NULL;
+ uintn idx;
+ hbool_t shadow_error=FALSE;
+ uintn nerrors=0;
+ static int ncalls=0;
+
+ ncalls++;
+
+ for (idx=0; idx<f->nshadows; idx++) {
+ for (hash=f->shadow[idx]; hash; hash=hash->next) {
+ for (shadow=hash->head,prev_shadow=NULL;
+ shadow;
+ shadow=shadow->next) {
+ shadow_error = FALSE;
+
+ /* Each shadow has a name and the names are in order */
+ if (!shadow->name) {
+ fprintf (stderr, "name=NULL, ");
+ shadow_error = TRUE;
+ }
+ if (prev_shadow && strcmp (prev_shadow->name, shadow->name)>=0) {
+ fprintf (stderr, "names not sorted, ");
+ shadow_error = TRUE;
+ }
+
+ /* Valid directory addresses */
+ if (shadow->dir_addr<0 || (shadow->dir_addr==0 && idx!=0)) {
+ fprintf (stderr, "dir_addr=%lu, ",
+ (unsigned long)(shadow->dir_addr));
+ shadow_error = TRUE;
+ } else if (shadow->dir_addr!=hash->dir_addr) {
+ fprintf (stderr, "dir_addr=%lu (not %lu), ",
+ (unsigned long)(shadow->dir_addr),
+ (unsigned long)(hash->dir_addr));
+ }
+
+ /* Linked to symbol table entry */
+ if (shadow->main && shadow!=shadow->main->shadow) {
+ fprintf (stderr, "entry linkage problem, ");
+ shadow_error = TRUE;
+ }
+
+ /* Shadow linked list is consistent */
+ if (shadow->prev && prev_shadow!=shadow->prev) {
+ fprintf (stderr, "shadow linked list problem, ");
+ shadow_error = TRUE;
+ }
+ prev_shadow = shadow;
+
+ /* If an error occurred then print other info */
+ if (shadow_error) {
+ fprintf (stderr, "idx=%u, shadow=0x%08lx, dir_addr=%lu\n",
+ idx, (unsigned long)shadow,
+ (unsigned long)(shadow->dir_addr));
+ nerrors++;
+ }
+ }
+ }
+ }
+ if (nerrors) {
+ fprintf (stderr, "Error in H5G_shadow_check, call %d\n", ncalls);
+ abort ();
+ }
+}
+#endif
/*-------------------------------------------------------------------------
@@ -171,14 +253,14 @@ H5G_shadow_sync (H5G_entry_t *ent)
*-------------------------------------------------------------------------
*/
H5G_shadow_t *
-H5G_shadow_list (haddr_t dir_addr)
+H5G_shadow_list (hdf5_file_t *f, haddr_t dir_addr)
{
- uintn idx = dir_addr % H5G_NSHADOWS;
+ uintn idx = dir_addr % f->nshadows;
H5G_hash_t *bucket = NULL;
FUNC_ENTER (H5G_shadows, NULL, NULL);
- for (bucket=H5G_shadow_g[idx]; bucket; bucket=bucket->next) {
+ for (bucket=f->shadow[idx]; bucket; bucket=bucket->next) {
if (bucket->dir_addr==dir_addr) {
HRETURN (bucket->head);
}
@@ -223,7 +305,11 @@ H5G_shadow_assoc_node (hdf5_file_t *f, H5G_node_t *sym, H5G_ac_ud1_t *ac_udata)
assert (sym); /* The symbol table node */
assert (ac_udata); /* The symbol table header info */
- if ((shadow=H5G_shadow_list (ac_udata->dir_addr))) {
+#ifdef DEBUG_SHADOWS
+ H5G_shadow_check (f);
+#endif
+
+ if ((shadow=H5G_shadow_list (f, ac_udata->dir_addr))) {
heap_addr = ac_udata->heap_addr;
while (i<sym->nsyms && shadow) {
@@ -240,6 +326,8 @@ H5G_shadow_assoc_node (hdf5_file_t *f, H5G_node_t *sym, H5G_ac_ud1_t *ac_udata)
if (i<sym->nsyms && s && shadow && !strcmp (s, shadow->name)) {
shadow->main = sym->entry + i;
sym->entry[i].shadow = shadow;
+ i++;
+ shadow = shadow->next;
}
}
}
@@ -247,7 +335,6 @@ H5G_shadow_assoc_node (hdf5_file_t *f, H5G_node_t *sym, H5G_ac_ud1_t *ac_udata)
FUNC_LEAVE (SUCCEED);
}
-
/*-------------------------------------------------------------------------
* Function: H5G_shadow_open
@@ -257,6 +344,8 @@ H5G_shadow_assoc_node (hdf5_file_t *f, H5G_node_t *sym, H5G_ac_ud1_t *ac_udata)
* object, open the object (again) and return a handle
* to it.
*
+ * DIR can be the null pointer if `ent' is the root entry.
+ *
* Return: Success: Handle to open object
*
* Failure: NULL
@@ -275,89 +364,109 @@ H5G_shadow_open (hdf5_file_t *f, H5G_entry_t *dir, H5G_entry_t *ent)
H5O_stab_t stab;
const char *s = NULL;
H5G_hash_t *hash = NULL;
- H5G_shadow_t *hash_ent = NULL;
+ H5G_shadow_t *hash_ent = NULL, *prev_ent = NULL;
uintn idx;
H5O_name_t name_mesg = {NULL};
H5G_entry_t *ret_value = NULL;
+ haddr_t dir_addr;
FUNC_ENTER (H5G_shadow_open, NULL, NULL);
/* check args */
assert (f);
- assert (dir);
+ assert (ent==f->root_sym || dir);
assert (ent);
+ dir_addr = dir ? dir->header : 0;
- if (ent->shadow) {
+ if ((shadow = ent->shadow)) {
/*
* Object is already open. Open it again.
*/
- ent->shadow->nrefs += 1;
- HRETURN (ent);
-
- } else {
- shadow = H5MM_xcalloc (1, sizeof(H5G_shadow_t));
-
- if (ent==f->root_sym && dir->header<=0) {
- /*
- * We're opening the root entry.
- */
- if (H5O_read (f, NO_ADDR, ent, H5O_NAME, 0, &name_mesg)) {
- shadow->name = H5MM_xstrdup (name_mesg.s);
- H5O_reset (H5O_NAME, &name_mesg);
- } else {
- shadow->name = H5MM_xstrdup ("Root Object");
- }
+ shadow->nrefs += 1;
+ HRETURN (&(shadow->entry));
+ }
- } else {
- /*
- * Some entry other than the root.
- */
- if (NULL==H5O_read (f, NO_ADDR, dir, H5O_STAB, 0, &stab)) {
- HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, NULL);
- }
- if (NULL==(s=H5H_peek (f, stab.heap_addr, ent->name_off))) {
- HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, NULL);
- }
- shadow->name = H5MM_xstrdup (s);
- }
-
+
+ shadow = H5MM_xcalloc (1, sizeof(H5G_shadow_t));
+ if (ent==f->root_sym && 0==dir_addr) {
/*
- * Build the new shadow.
+ * We're opening the root entry.
*/
- ent->shadow = shadow;
- shadow->main = ent;
- shadow->nrefs = 1;
- shadow->entry = *ent;
- shadow->entry.dirty = FALSE;
- shadow->dir_addr = dir->header;
-
+ if (H5O_read (f, NO_ADDR, ent, H5O_NAME, 0, &name_mesg)) {
+ shadow->name = H5MM_xstrdup (name_mesg.s);
+ H5O_reset (H5O_NAME, &name_mesg);
+ } else {
+ shadow->name = H5MM_xstrdup ("Root Object");
+ }
+
+ } else {
/*
- * Link it into the shadow heap
+ * Some entry other than the root.
*/
- idx = dir->header % H5G_NSHADOWS;
- for (hash=H5G_shadow_g[idx]; hash; hash=hash->next) {
- if (hash->dir_addr==dir->header) break;
+ if (NULL==H5O_read (f, NO_ADDR, dir, H5O_STAB, 0, &stab)) {
+ HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, NULL);
}
- if (!hash) {
- hash = H5MM_xcalloc (1, sizeof(H5G_hash_t));
- hash->dir_addr = dir->header;
- hash->next = H5G_shadow_g[idx];
- H5G_shadow_g[idx] = hash;
+ if (NULL==(s=H5H_peek (f, stab.heap_addr, ent->name_off))) {
+ HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, NULL);
}
- for (hash_ent=hash->head; hash_ent; hash_ent=hash_ent->next) {
+ shadow->name = H5MM_xstrdup (s);
+ }
+
+ /*
+ * Build the new shadow.
+ */
+ ent->shadow = shadow;
+ shadow->main = ent;
+ shadow->nrefs = 1;
+ shadow->entry = *ent;
+ shadow->entry.dirty = FALSE;
+ shadow->dir_addr = dir_addr;
+
+ /*
+ * Link it into the shadow heap
+ */
+ idx = dir_addr % f->nshadows;
+ for (hash=f->shadow[idx]; hash; hash=hash->next) {
+ if (hash->dir_addr==dir_addr) break;
+ }
+ if (!hash) {
+ hash = H5MM_xcalloc (1, sizeof(H5G_hash_t));
+ hash->dir_addr = dir_addr;
+ hash->next = f->shadow[idx];
+ f->shadow[idx] = hash;
+ if (hash->next) hash->next->prev = hash;
+ }
+ if (hash->head) {
+ for (hash_ent=hash->head,prev_ent=NULL;
+ hash_ent;
+ hash_ent=hash_ent->next) {
if (strcmp (shadow->name, hash_ent->name)<0) break;
+ prev_ent = hash_ent;
}
if (hash_ent) {
+ /* Insert SHADOW before HASH_ENT */
if (hash_ent->prev) hash_ent->prev->next = shadow;
else hash->head = shadow;
shadow->prev = hash_ent->prev;
shadow->next = hash_ent;
hash_ent->prev = shadow;
} else {
- hash->head = shadow;
+ /* Append SHADOW to list */
+ assert (prev_ent && NULL==prev_ent->next);
+ prev_ent->next = shadow;
+ shadow->prev = prev_ent;
}
+ } else {
+ /* Insert shadow at head of list */
+ shadow->next = hash->head;
+ if (hash->head) hash->head->prev = shadow;
+ hash->head = shadow;
}
+#ifdef DEBUG_SHADOWS
+ H5G_shadow_check (f);
+#endif
+
ret_value = &(shadow->entry);
done:
@@ -423,8 +532,8 @@ H5G_shadow_close (hdf5_file_t *f, H5G_entry_t *ent)
H5G_shadow_dissociate (ent);
/* find symtabs shadow list */
- idx = shadow->dir_addr % H5G_NSHADOWS;
- for (hash=H5G_shadow_g[idx]; hash; hash=hash->next) {
+ idx = shadow->dir_addr % f->nshadows;
+ for (hash=f->shadow[idx]; hash; hash=hash->next) {
if (hash->dir_addr==shadow->dir_addr) break;
}
assert (hash);
@@ -445,7 +554,7 @@ H5G_shadow_close (hdf5_file_t *f, H5G_entry_t *ent)
/* remove symtab's shadow list if empty */
if (!hash->head) {
if (hash->prev) hash->prev->next = hash->next;
- else H5G_shadow_g[idx] = hash->next;
+ else f->shadow[idx] = hash->next;
if (hash->next) hash->next->prev = hash->prev;
H5MM_xfree (hash);
}
@@ -453,3 +562,153 @@ H5G_shadow_close (hdf5_file_t *f, H5G_entry_t *ent)
FUNC_LEAVE (SUCCEED);
}
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_shadow_move
+ *
+ * Purpose: Moves the SHADOW for some entry to correspond to a
+ * NEW_ENTRY. The DIR_ADDR is the address for the directory
+ * which contains NEW_ENTRY.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Friday, September 19, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_shadow_move (hdf5_file_t *f, H5G_shadow_t *shadow, const char *new_name,
+ H5G_entry_t *new_entry, haddr_t dir_addr)
+{
+ H5G_hash_t *hash;
+ uintn idx;
+
+ FUNC_ENTER (H5G_shadow_move, NULL, FAIL);
+
+ assert (shadow);
+ assert (new_entry);
+ assert (dir_addr>0);
+
+ if (0==shadow->dir_addr) {
+ /*
+ * We're moving the shadow for the root object. This simplifies things
+ * greatly since it implies that this is the only shadow currently
+ * defined for the entire file.
+ */
+ idx = dir_addr % f->nshadows;
+ assert (NULL==f->shadow[idx]); /*Nothing at new idx... */
+ hash = f->shadow[0];
+ assert (hash); /*..but root idx has something. */
+ assert (0==hash->dir_addr); /*..and it's the root something */
+ assert (NULL==hash->next); /*..and just that */
+ assert (hash->head==shadow); /*..and exactly that */
+
+ /* Move root entry to new hash bucket */
+ f->shadow[idx] = hash;
+ f->shadow[0] = NULL;
+ hash->dir_addr = dir_addr;
+
+ /* Associate SHADOW with NEW_ENTRY */
+ shadow->dir_addr = dir_addr;
+ shadow->main = new_entry;
+ new_entry->shadow = shadow;
+
+ /* Give the shadow a new name */
+ H5MM_xfree (shadow->name);
+ shadow->name = H5MM_xstrdup (new_name);
+
+ } else {
+ /*
+ * Other shadows never move.
+ */
+ assert (shadow->dir_addr==dir_addr);
+ shadow->main = new_entry;
+ new_entry->shadow = shadow;
+ }
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_shadow_flush
+ *
+ * Purpose: Flush all open object information to the main cache.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL if INVALIDATE is non-zero and there are
+ * open objects.
+ *
+ * Programmer: Robb Matzke
+ * Friday, September 19, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_shadow_flush (hdf5_file_t *f, hbool_t invalidate)
+{
+ uintn idx;
+ H5G_hash_t *hash = NULL;
+ H5G_shadow_t *shadow = NULL;
+ intn nfound=0;
+
+ FUNC_ENTER (H5G_shadow_flush, NULL, FAIL);
+
+ for (idx=0; idx<f->nshadows; idx++) {
+ for (hash=f->shadow[idx]; hash; hash=hash->next) {
+ for (shadow=hash->head; shadow; shadow=shadow->next) {
+ if (!shadow->main &&
+ NULL==H5G_stab_find (f, shadow->dir_addr, NULL,
+ shadow->name)) {
+ HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL);
+ }
+ assert (shadow->main);
+ *(shadow->main) = shadow->entry;
+ shadow->entry.dirty = FALSE;
+ nfound++;
+
+#ifndef NDEBUG
+ /*
+ * This is usually a bad thing--an hdf5 programmer forgot to
+ * close some object before closing the file. Since this is hard
+ * to debug, we'll be nice and print the names here. We don't
+ * know the full name, but we'll print the file address (relative
+ * to the boot block) of the object header for the directory that
+ * contains the open object.
+ */
+ if (invalidate) {
+ fprintf (stderr, "Open object <%lu>/%s",
+ (unsigned long)(shadow->dir_addr),
+ shadow->name);
+ if (shadow->nrefs>1) {
+ fprintf (stderr, " (%d times)", shadow->nrefs);
+ }
+ fputc ('\n', stderr);
+ }
+#endif
+ }
+ }
+ }
+
+ if (invalidate && nfound) {
+ /*
+ * No clean easy way to do this, just leak the memory. If we free a
+ * shadow and then something else tries to access it (perhaps to close
+ * it) then they trample on freed memory.
+ */
+ HRETURN_ERROR (H5E_SYM, H5E_UNSUPPORTED, FAIL);
+ }
+
+ FUNC_LEAVE (SUCCEED);
+}
diff --git a/src/H5Gstab.c b/src/H5Gstab.c
new file mode 100644
index 0000000..209cbc4
--- /dev/null
+++ b/src/H5Gstab.c
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) 1997 National Center for Supercomputing Applications
+ * All rights reserved.
+ *
+ * Programmer: Robb Matzke <matzke@llnl.gov>
+ * Friday, September 19, 1997
+ *
+ */
+#define H5G_PACKAGE
+
+#include <H5private.h>
+#include <H5ACprivate.h>
+#include <H5Eprivate.h>
+#include <H5Gpkg.h>
+#include <H5Hprivate.h>
+#include <H5MMprivate.h>
+#include <H5Oprivate.h>
+
+#define PABLO_MASK H5G_stab_mask
+static hbool_t interface_initialize_g = FALSE;
+
+
+/*-------------------------------------------------------------------------
+ * 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.
+ *
+ * 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.
+ *
+ * Errors:
+ * INTERNAL CANTINIT B-tree's won't work if the first
+ * name isn't at the beginning of the
+ * heap.
+ * SYM CANTINIT Can't create B-tree.
+ * SYM CANTINIT Can't create header.
+ * SYM CANTINIT Can't create heap.
+ * SYM CANTINIT Can't create message.
+ * SYM CANTINIT Can't initialize heap.
+ *
+ * Return: Success: Address of new symbol table header. If
+ * the caller supplies a symbol table entry
+ * SELF then it will be initialized to point to
+ * this symbol table.
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Aug 1 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+haddr_t
+H5G_stab_new (hdf5_file_t *f, H5G_entry_t *self, size_t init)
+{
+ off_t name; /*offset of "" name */
+ haddr_t addr; /*object header address */
+ H5O_stab_t stab; /*symbol table message */
+
+ FUNC_ENTER (H5G_stab_new, NULL, FAIL);
+
+ /*
+ * Check arguments.
+ */
+ assert (f);
+ init = MAX(init, H5H_SIZEOF_FREE(f)+2);
+
+ /* Create symbol table private heap */
+ if ((stab.heap_addr = H5H_new (f, H5H_LOCAL, init))<0) {
+ HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); /*can't create heap*/
+ }
+ if ((name = H5H_insert (f, stab.heap_addr, 1, "")<0)) {
+ HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); /*can't initialize heap*/
+ }
+ 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);
+ }
+
+ /* Create the B-tree */
+ if ((stab.btree_addr = H5B_new (f, H5B_SNODE))<0) {
+ HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); /*can't create B-tree*/
+ }
+
+ /*
+ * Create symbol table object header. It has a zero link count
+ * since nothing refers to it yet. The link count will be
+ * incremented if the object is added to the directory hierarchy.
+ */
+ if ((addr = H5O_new (f, 0, 4+2*H5F_SIZEOF_OFFSET(f)))<0) {
+ HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); /*can't create header*/
+ }
+
+ /* insert the symbol table message */
+ if (self) {
+ memset (self, 0, sizeof(H5G_entry_t));
+ self->header = addr;
+ }
+ if (H5O_modify(f, addr, self, H5O_STAB, H5O_NEW_MESG, &stab)<0) {
+ HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); /*can't create message*/
+ }
+
+ FUNC_LEAVE (addr);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_stab_find
+ *
+ * Purpose: Finds a symbol named NAME in the symbol table whose
+ * description is stored in SELF in file F and returns a
+ * pointer to the symbol table entry. SELF is optional if the
+ * symbol table address is supplied through ADDR.
+ *
+ * Errors:
+ * SYM BADMESG Can't read message.
+ * SYM NOTFOUND Not found.
+ *
+ * Return: Success: Pointer to the symbol table entry.
+ * The pointer is intended for immediate
+ * read-only access since it points
+ * directly to an entry in a cached
+ * symbol table node. The pointer is
+ * guaranteed to be valid only until the
+ * next call to one of the H5AC functions.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Aug 1 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+H5G_entry_t *
+H5G_stab_find (hdf5_file_t *f, haddr_t addr, H5G_entry_t *self,
+ const char *name)
+{
+ H5G_bt_ud1_t udata; /*data to pass through B-tree */
+ H5O_stab_t stab; /*symbol table message */
+
+ FUNC_ENTER (H5G_stab_find, NULL, NULL);
+
+ /* Check arguments */
+ assert (f);
+ if (addr<=0 && (!self || self->header<=0)) {
+ HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL);
+ }
+ if (!name || !*name) {
+ HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL);
+ }
+ if (addr<=0) addr = self->header;
+
+ /* set up the udata */
+ if (NULL==H5O_read (f, addr, self, H5O_STAB, 0, &stab)) {
+ HRETURN_ERROR (H5E_SYM, H5E_BADMESG, NULL); /*can't read message*/
+ }
+ udata.operation = H5G_OPER_FIND;
+ udata.name = name;
+ udata.heap_addr = stab.heap_addr;
+ udata.dir_addr = addr;
+ udata.node_ptr = NULL;
+
+ /* search the B-tree */
+ if (H5B_find (f, H5B_SNODE, stab.btree_addr, &udata)<0) {
+ if (udata.node_ptr) {
+ H5AC_unprotect (f, H5AC_SNODE, udata.node_addr, udata.node_ptr);
+ }
+ HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL); /*not found*/
+ }
+
+ /* Unprotect the symbol table node */
+ if (udata.node_ptr) {
+ if (H5AC_unprotect (f, H5AC_SNODE, udata.node_addr, udata.node_ptr)<0) {
+ HRETURN_ERROR (H5E_SYM, H5E_PROTECT, NULL);
+ }
+ }
+
+ /* return the result */
+ FUNC_LEAVE (udata.entry_ptr);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_stab_insert
+ *
+ * Purpose: Insert a new symbol into the table described by SELF in
+ * file F. The name of the new symbol is NAME and its symbol
+ * table entry is ENT.
+ *
+ * Errors:
+ * SYM BADMESG Can't read message.
+ * SYM CANTINSERT Can't insert entry.
+ *
+ * Return: Success: Pointer to the cached symbol table entry.
+ * This is a pointer directly into a symbol
+ * table node and will become invalid on the
+ * next call to the H5AC package.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Aug 1 1997
+ *
+ * Modifications:
+ *
+ * Robb Matzke, 18 Sep 1997
+ * If ENT has a shadow, then the shadow will be associated with the
+ * entry when it is added to the symbol table.
+ *
+ *-------------------------------------------------------------------------
+ */
+H5G_entry_t *
+H5G_stab_insert (hdf5_file_t *f, H5G_entry_t *self, const char *name,
+ H5G_entry_t *ent)
+{
+ H5O_stab_t stab; /*symbol table message */
+ H5G_bt_ud1_t udata; /*data to pass through B-tree */
+
+ FUNC_ENTER (H5G_stab_insert, NULL, NULL);
+
+ /* check arguments */
+ assert (f);
+ assert (self && self->header>=0);
+ assert (name && *name);
+ assert (ent);
+
+ /* 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, NULL); /*can't read message*/
+ }
+
+ udata.operation = H5G_OPER_INSERT;
+ udata.name = name;
+ udata.heap_addr = stab.heap_addr;
+ udata.dir_addr = self->header;
+ udata.entry = *ent;
+ udata.entry.name_off = -1;
+ udata.node_ptr = NULL;
+
+ /* insert */
+ if (H5B_insert (f, H5B_SNODE, stab.btree_addr, &udata)<0) {
+ if (udata.node_ptr) {
+ H5AC_unprotect (f, H5AC_SNODE, udata.node_addr, udata.node_ptr);
+ }
+ HRETURN_ERROR (H5E_SYM, H5E_CANTINSERT, NULL); /*can't insert entry*/
+ }
+
+ /*
+ * The H5G_node_insert() called H5AC_protect() for the node so that the
+ * udata.entry_ptr field didn't become invalid on the way back out of the
+ * B-tree code. We unprotect it now, but the pointer will remain valid
+ * until the next call to H5AC.
+ */
+ if (H5AC_unprotect (f, H5AC_SNODE, udata.node_addr, udata.node_ptr)<0) {
+ HRETURN_ERROR (H5E_SYM, H5E_PROTECT, NULL); /*can't unprotect*/
+ }
+
+ /* update the name offset in the entry */
+ ent->name_off = udata.entry.name_off;
+ FUNC_LEAVE (udata.entry_ptr);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_stab_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.
+ *
+ * Errors:
+ * SYM BADMESG Not a symbol table.
+ * SYM CANTLIST B-tree list failure.
+ *
+ * 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: FAIL, the pointers in NAMES are undefined but
+ * no memory is allocated. The values in
+ * ENTRIES are undefined.
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Aug 1 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+intn
+H5G_stab_list (hdf5_file_t *f, H5G_entry_t *self, intn maxentries,
+ char *names[], H5G_entry_t entries[])
+{
+ H5G_bt_ud2_t udata;
+ H5O_stab_t stab;
+ intn i;
+
+ FUNC_ENTER (H5G_stab_list, NULL, FAIL);
+
+ /* check args */
+ assert (f);
+ 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); /*not a symbol table*/
+ }
+ udata.entry = entries;
+ udata.name = names;
+ udata.dir_addr = self->header;
+ udata.heap_addr = stab.heap_addr;
+ udata.maxentries = maxentries;
+ udata.nsyms = 0;
+ if (names) HDmemset (names, 0, maxentries);
+
+ /* list */
+ if (H5B_list (f, H5B_SNODE, stab.btree_addr, &udata)<0) {
+ if (names) {
+ for (i=0; i<maxentries; i++) H5MM_xfree (names[i]);
+ }
+ HRETURN_ERROR (H5E_SYM, H5E_CANTLIST, FAIL); /*B-tree list failure*/
+ }
+
+ FUNC_LEAVE (udata.nsyms);
+}
+
diff --git a/src/H5O.c b/src/H5O.c
index 8509e41..96a9063 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -501,16 +501,17 @@ H5O_reset (const H5O_class_t *type, void *native)
*-------------------------------------------------------------------------
*/
intn
-H5O_link (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent, intn adjust)
+H5O_link (hdf5_file_t *f, H5G_entry_t *ent, intn adjust)
{
H5O_t *oh = NULL;
+ haddr_t addr;
FUNC_ENTER (H5O_link, NULL, FAIL);
/* check args */
assert (f);
- assert (addr>0 || (ent && ent->header>0));
- if (addr<=0) addr = ent->header;
+ assert (ent && H5G_ent_addr (ent)>0);
+ addr = H5G_ent_addr (ent);
/* get header */
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) {
@@ -529,10 +530,7 @@ H5O_link (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent, intn adjust)
}
} else {
oh->nlink += adjust;
- if (oh->nlink>1 && ent && H5G_NOTHING_CACHED!=ent->type) {
- ent->dirty = TRUE;
- ent->type = H5G_NOTHING_CACHED;
- }
+ if (oh->nlink>1) H5G_ent_invalidate (ent);
}
oh->dirty = TRUE;
@@ -568,22 +566,29 @@ H5O_read (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
H5O_t *oh = NULL;
void *retval = NULL;
intn idx;
+ H5G_cache_t *cache = NULL;
+ H5G_type_t cache_type;
FUNC_ENTER (H5O_read, NULL, NULL);
/* check args */
assert (f);
- if (addr<=0 && (!ent || ent->header<=0)) {
+ if (addr<=0 && !ent) {
+ HRETURN_ERROR (H5E_OHDR, H5E_NOTFOUND, NULL);
+ }
+ if (addr<=0 && (addr=H5G_ent_addr (ent))<=0) {
HRETURN_ERROR (H5E_OHDR, H5E_NOTFOUND, NULL);
}
- if (addr<=0) addr = ent->header;
assert (sequence>=0);
/* can we get it from the symbol table? */
- if (ent && H5G_NOTHING_CACHED!=ent->type && type && type->fast) {
- retval = (type->fast)(ent, mesg);
- if (retval) HRETURN (retval);
- H5ECLEAR;
+ if (ent) {
+ cache = H5G_ent_cache (ent, &cache_type);
+ if (type && cache_type==type->cache_type && type->fast) {
+ retval = (type->fast)(cache, mesg);
+ if (retval) HRETURN (retval);
+ H5ECLEAR;
+ }
}
/* can we get it from the object header? */
@@ -759,10 +764,10 @@ H5O_modify (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
/* check args */
assert (f);
- assert (addr>0 || (ent && ent->header>0));
+ assert (addr>0 || (ent && H5G_ent_addr (ent)>0));
assert (type);
assert (mesg);
- if (addr<=0) addr = ent->header;
+ if (addr<=0) addr = H5G_ent_addr (ent);
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) {
HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL);
@@ -805,8 +810,11 @@ H5O_modify (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
/* Copy into the symbol table entry */
if (oh->nlink<=1 && ent && type->cache) {
- hbool_t modified = (type->cache)(ent, mesg);
- if (ent && !ent->dirty) ent->dirty = modified;
+ H5G_type_t cache_type;
+ H5G_cache_t *cache = H5G_ent_cache (ent, &cache_type);
+ hbool_t modified = (type->cache)(&cache_type, cache, mesg);
+ if (modified) H5G_ent_modified (ent, cache_type);
+
}
FUNC_LEAVE (sequence);
@@ -854,9 +862,9 @@ H5O_remove (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
/* check args */
assert (f);
- assert (addr>0 || (ent && ent->header>0));
+ assert (addr>0 || (ent && H5G_ent_addr (ent)>0));
assert (type);
- if (addr<=0) addr = ent->header;
+ if (addr<=0) addr = H5G_ent_addr (ent);
/* load the object header */
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) {
@@ -866,11 +874,12 @@ H5O_remove (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
for (i=seq=0; i<oh->nmesgs; i++) {
if (type->id != oh->mesg[i].type->id) continue;
if (seq++ == sequence || H5O_ALL==sequence) {
+ H5G_type_t cache_type;
+ H5G_ent_cache (ent, &cache_type);
/* clear symbol table entry cache */
- if (ent && type->cache && type->cache_type==ent->type) {
- ent->type = H5G_NOTHING_CACHED;
- ent->dirty = TRUE;
+ if (ent && type->cache && type->cache_type==cache_type) {
+ H5G_ent_invalidate (ent);
}
/* change message type to nil and zero it */
diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h
index 30b0af1..d5666eb 100644
--- a/src/H5Oprivate.h
+++ b/src/H5Oprivate.h
@@ -50,8 +50,8 @@ typedef struct H5O_class_t {
H5G_type_t cache_type; /*type field in symbol table */
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*/
- hbool_t (*cache)(H5G_entry_t*,const void*); /*put into entry */
+ void *(*fast)(const H5G_cache_t*, void*);/*get from of entry */
+ hbool_t (*cache)(H5G_type_t*, H5G_cache_t*,const void*); /*into entry*/
void *(*copy)(const void*,void*); /*copy native value */
size_t (*raw_size)(hdf5_file_t*,const void*); /*sizeof raw val */
herr_t (*reset)(void*); /*free nested data structures */
@@ -158,7 +158,7 @@ typedef struct H5O_stab_t {
haddr_t H5O_new (hdf5_file_t *f, intn nlink, size_t size_hint);
-intn H5O_link (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent, intn adjust);
+intn H5O_link (hdf5_file_t *f, H5G_entry_t *ent, intn adjust);
void *H5O_read (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
const H5O_class_t *type, intn sequence, void *mesg);
const void *H5O_peek (hdf5_file_t *f, haddr_t addr, const H5O_class_t *type,
diff --git a/src/H5Osdim.c b/src/H5Osdim.c
index 923ceea..312249b 100644
--- a/src/H5Osdim.c
+++ b/src/H5Osdim.c
@@ -41,8 +41,9 @@ static char RcsId[] = "@(#)$Revision$";
static void *H5O_sim_dim_decode (hdf5_file_t *f, size_t raw_size, const uint8 *p);
static herr_t H5O_sim_dim_encode (hdf5_file_t *f, size_t size, uint8 *p,
const void *_mesg);
-static void *H5O_sim_dim_fast (const H5G_entry_t *ent, void *_mesg);
-static hbool_t H5O_sim_dim_cache (H5G_entry_t *ent, const void *_mesg);
+static void *H5O_sim_dim_fast (const H5G_cache_t *cache, void *_mesg);
+static hbool_t H5O_sim_dim_cache (H5G_type_t *cache_type, H5G_cache_t *cache,
+ const void *_mesg);
static void *H5O_sim_dim_copy (const void *_mesg, void *_dest);
static size_t H5O_sim_dim_size (hdf5_file_t *f, const void *_mesg);
static herr_t H5O_sim_dim_debug (hdf5_file_t *f, const void *_mesg,
@@ -208,7 +209,7 @@ H5O_sim_dim_encode (hdf5_file_t *f, size_t raw_size, uint8 *p, const void *mesg)
for simple dimensionality, as they can be cached in the symbol-table entry)
--------------------------------------------------------------------------*/
static void *
-H5O_sim_dim_fast (const H5G_entry_t *ent, void *mesg)
+H5O_sim_dim_fast (const H5G_cache_t *cache, void *mesg)
{
H5O_sim_dim_t *sdim = (H5O_sim_dim_t *)mesg;
uintn u; /* local counting variable */
@@ -216,19 +217,15 @@ H5O_sim_dim_fast (const H5G_entry_t *ent, void *mesg)
FUNC_ENTER (H5O_sim_dim_fast, NULL, NULL);
/* check args */
- assert (ent);
-
- if (H5G_CACHED_SDATA==ent->type) {
- if (!sdim) sdim = H5MM_xcalloc (1, sizeof(H5O_sim_dim_t));
- sdim->rank = ent->cache.sdata.ndim;
- assert (sdim->rank<=NELMTS (ent->cache.sdata.dim));
- sdim->dim_flags = 0;
- sdim->size = H5MM_xmalloc (sizeof(uint32) * sdim->rank);
- for (u=0; u<sdim->rank; u++) {
- sdim->size[u] = ent->cache.sdata.dim[u];
- }
- } else {
- sdim = NULL;
+ assert (cache);
+
+ if (!sdim) sdim = H5MM_xcalloc (1, sizeof(H5O_sim_dim_t));
+ sdim->rank = cache->sdata.ndim;
+ assert (sdim->rank<=NELMTS (cache->sdata.dim));
+ sdim->dim_flags = 0;
+ sdim->size = H5MM_xmalloc (sizeof(uint32) * sdim->rank);
+ for (u=0; u<sdim->rank; u++) {
+ sdim->size[u] = cache->sdata.dim[u];
}
FUNC_LEAVE (sdim);
@@ -246,6 +243,7 @@ H5O_sim_dim_fast (const H5G_entry_t *ent, void *mesg)
const void *mesg; IN: Pointer to the simple dimensionality struct
RETURNS
BTRUE if symbol-table modified, BFALSE if not modified, BFAIL on failure.
+ The new cache type is returned through the CACHE_TYPE argument.
DESCRIPTION
This function is the opposite of the H5O_sim_dim_fast method, it
copies a message into the cached portion of a symbol-table entry. (This
@@ -253,7 +251,8 @@ H5O_sim_dim_fast (const H5G_entry_t *ent, void *mesg)
the symbol-table entry)
--------------------------------------------------------------------------*/
static hbool_t
-H5O_sim_dim_cache (H5G_entry_t *ent, const void *mesg)
+H5O_sim_dim_cache (H5G_type_t *cache_type, H5G_cache_t *cache,
+ const void *mesg)
{
const H5O_sim_dim_t *sdim = (const H5O_sim_dim_t *)mesg;
uintn u; /* Local counting variable */
@@ -262,41 +261,42 @@ H5O_sim_dim_cache (H5G_entry_t *ent, const void *mesg)
FUNC_ENTER (H5O_sim_dim_cache, NULL, BFAIL);
/* check args */
- assert (ent);
+ assert (cache_type);
+ assert (cache);
assert (sdim);
- if (sdim->rank <= NELMTS (ent->cache.sdata.dim)) {
- if (H5G_CACHED_SDATA != ent->type) {
+ if (sdim->rank <= NELMTS (cache->sdata.dim)) {
+ if (H5G_CACHED_SDATA != *cache_type) {
modified = BTRUE;
- ent->type = H5G_CACHED_SDATA;
- ent->cache.sdata.ndim = sdim->rank;
+ *cache_type = H5G_CACHED_SDATA;
+ cache->sdata.ndim = sdim->rank;
for (u=0; u<=sdim->rank; u++) {
- ent->cache.sdata.dim[u] = sdim->size[u];
+ cache->sdata.dim[u] = sdim->size[u];
}
} else {
- if(ent->cache.sdata.ndim!= sdim->rank) {
+ if(cache->sdata.ndim != sdim->rank) {
modified = BTRUE;
- ent->cache.sdata.ndim = sdim->rank;
+ cache->sdata.ndim = sdim->rank;
}
/* Check each dimension */
- if (NULL==ent->cache.sdata.dim) {
+ if (NULL==cache->sdata.dim) {
modified = BTRUE;
} else {
for (u=0; u<sdim->rank; u++) {
- if (ent->cache.sdata.dim[u] != sdim->size[u]) {
+ if (cache->sdata.dim[u] != sdim->size[u]) {
modified = BTRUE;
- ent->cache.sdata.dim[u] = sdim->size[u];
+ cache->sdata.dim[u] = sdim->size[u];
}
}
}
}
- } else if (H5G_CACHED_SDATA == ent->type) {
+ } else if (H5G_CACHED_SDATA == *cache_type) {
/*
* Number of dimensions is too large to cache.
*/
modified = TRUE;
- ent->type = H5G_NOTHING_CACHED;
+ *cache_type = H5G_NOTHING_CACHED;
}
FUNC_LEAVE (modified);
@@ -330,25 +330,23 @@ H5O_sim_dim_copy (const void *mesg, void *dest)
if (!dst)
dst = H5MM_xcalloc (1, sizeof(H5O_sim_dim_t));
- /* copy */
+ /* deep copy -- pointed-to values are copied also */
HDmemcpy(dst,src,sizeof(H5O_sim_dim_t));
+ if (src->size) dst->size = H5MM_xcalloc (src->rank, sizeof(uint32));
+ if (src->max) dst->max = H5MM_xcalloc (src->rank, sizeof(uint32));
+ if (src->perm) dst->perm = H5MM_xcalloc (src->rank, sizeof(uint32));
+
if(src->rank>0)
{
- if(dst->size==NULL)
- dst->size = H5MM_xcalloc (src->rank, sizeof(uint32));
HDmemcpy(dst->size,src->size,src->rank*sizeof(uint32));
/* Check for maximum dimensions and copy those */
if((src->dim_flags&0x01)>0)
{
- if(dst->max==NULL)
- dst->max = H5MM_xcalloc (src->rank, sizeof(uint32));
HDmemcpy(dst->max,src->max,src->rank*sizeof(uint32));
} /* end if */
/* Check for dimension permutation and copy those */
if((src->dim_flags&0x02)>0)
{
- if(dst->max==NULL)
- dst->perm = H5MM_xcalloc (src->rank, sizeof(uint32));
HDmemcpy(dst->perm,src->perm,src->rank*sizeof(uint32));
} /* end if */
} /* end if */
diff --git a/src/H5Osdtyp.c b/src/H5Osdtyp.c
index 8920625..08fbba4 100644
--- a/src/H5Osdtyp.c
+++ b/src/H5Osdtyp.c
@@ -41,8 +41,9 @@ static char RcsId[] = "@(#)$Revision$";
static void *H5O_sim_dtype_decode (hdf5_file_t *f, size_t raw_size, const uint8 *p);
static herr_t H5O_sim_dtype_encode (hdf5_file_t *f, size_t size, uint8 *p,
const void *_mesg);
-static void *H5O_sim_dtype_fast (const H5G_entry_t *ent, void *_mesg);
-static hbool_t H5O_sim_dtype_cache (H5G_entry_t *ent, const void *_mesg);
+static void *H5O_sim_dtype_fast (const H5G_cache_t *cache, void *_mesg);
+static hbool_t H5O_sim_dtype_cache (H5G_type_t *cache_type, H5G_cache_t *cache,
+ const void *_mesg);
static void *H5O_sim_dtype_copy (const void *_mesg, void *_dest);
static size_t H5O_sim_dtype_size (hdf5_file_t *f, const void *_mesg);
static herr_t H5O_sim_dtype_debug (hdf5_file_t *f, const void *_mesg,
@@ -166,25 +167,21 @@ H5O_sim_dtype_encode (hdf5_file_t *f, size_t raw_size, uint8 *p, const void *mes
for simple datatypes, as they can be cached in the symbol-table entry)
--------------------------------------------------------------------------*/
static void *
-H5O_sim_dtype_fast (const H5G_entry_t *ent, void *mesg)
+H5O_sim_dtype_fast (const H5G_cache_t *cache, void *mesg)
{
H5O_sim_dtype_t *sdtype = (H5O_sim_dtype_t *)mesg;
FUNC_ENTER (H5O_sim_dtype_fast, NULL, NULL);
/* check args */
- assert (ent);
+ assert (cache);
- if (H5G_CACHED_SDATA==ent->type) {
- if (!sdtype) sdtype = H5MM_xcalloc (1, sizeof(H5O_sim_dtype_t));
- sdtype->len = ent->cache.sdata.nt.length;
- sdtype->arch = ent->cache.sdata.nt.arch;
+ if (!sdtype) sdtype = H5MM_xcalloc (1, sizeof(H5O_sim_dtype_t));
+ sdtype->len = cache->sdata.nt.length;
+ sdtype->arch = cache->sdata.nt.arch;
- /* Convert into atomic base type. */
- sdtype->base = MAKE_ATOM (H5_DATATYPE, ent->cache.sdata.nt.type);
- } else {
- sdtype = NULL;
- }
+ /* Convert into atomic base type. */
+ sdtype->base = MAKE_ATOM (H5_DATATYPE, cache->sdata.nt.type);
FUNC_LEAVE (sdtype);
} /* end H5O_sim_dtype_fast() */
@@ -201,50 +198,54 @@ H5O_sim_dtype_fast (const H5G_entry_t *ent, void *mesg)
const void *mesg; IN: Pointer to the simple datatype struct
RETURNS
BTRUE if symbol-table modified, BFALSE if not modified, BFAIL on failure.
+ The new cache type is returned through the CACHE_TYPE argument.
DESCRIPTION
This function is the opposite of the H5O_sim_dtype_fast method, it
copies a message into the cached portion of a symbol-table entry. (This
method is required for simple datatypes, as they can be cached in the
symbol-table entry)
--------------------------------------------------------------------------*/
-static hbool_t
-H5O_sim_dtype_cache (H5G_entry_t *ent, const void *mesg)
+static herr_t
+H5O_sim_dtype_cache (H5G_type_t *cache_type, H5G_cache_t *cache,
+ const void *mesg)
{
const H5O_sim_dtype_t *sdtype = (const H5O_sim_dtype_t *)mesg;
hbool_t modified = BFALSE;
-
+
FUNC_ENTER (H5O_sim_dtype_cache, NULL, BFAIL);
/* check args */
- assert (ent);
+ assert (cache_type);
+ assert (cache);
assert (sdtype);
- if (H5G_CACHED_SDATA != ent->type) {
+ if (H5G_CACHED_SDATA != *cache_type) {
/*
* No sdata cached yet.
*/
modified = BTRUE;
- ent->type = H5G_CACHED_SDATA;
- ent->cache.sdata.nt.length = sdtype->len;
- ent->cache.sdata.nt.arch = sdtype->arch;
- ent->cache.sdata.nt.type = sdtype->base;
+ *cache_type = H5G_CACHED_SDATA;
+ cache->sdata.nt.length = sdtype->len;
+ cache->sdata.nt.arch = sdtype->arch;
+ cache->sdata.nt.type = sdtype->base;
+
} else {
/*
* Some sdata already cached.
*/
- if (ent->cache.sdata.nt.length != sdtype->len) {
+ if (cache->sdata.nt.length != sdtype->len) {
modified = BTRUE;
- ent->cache.sdata.nt.length = sdtype->len;
+ cache->sdata.nt.length = sdtype->len;
}
- if (ent->cache.sdata.nt.arch != sdtype->arch) {
+ if (cache->sdata.nt.arch != sdtype->arch) {
modified = BTRUE;
- ent->cache.sdata.nt.arch = sdtype->arch;
+ cache->sdata.nt.arch = sdtype->arch;
}
- if (ent->cache.sdata.nt.type != (uint16)sdtype->base) {
+ if (cache->sdata.nt.type != (uint16)sdtype->base) {
modified = BTRUE;
- ent->cache.sdata.nt.type = (uint16)sdtype->base;
+ cache->sdata.nt.type = (uint16)sdtype->base;
}
}
diff --git a/src/H5Ostab.c b/src/H5Ostab.c
index 0b67a73..c4bb67c 100644
--- a/src/H5Ostab.c
+++ b/src/H5Ostab.c
@@ -26,8 +26,9 @@
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);
-static hbool_t H5O_stab_cache (H5G_entry_t *ent, const void *_mesg);
+static void *H5O_stab_fast (const H5G_cache_t *cache, void *_mesg);
+static hbool_t H5O_stab_cache (H5G_type_t *cache_type, H5G_cache_t *cache,
+ const void *_mesg);
static void *H5O_stab_copy (const void *_mesg, void *_dest);
static size_t H5O_stab_size (hdf5_file_t *f, const void *_mesg);
static herr_t H5O_stab_debug (hdf5_file_t *f, const void *_mesg,
@@ -133,8 +134,8 @@ H5O_stab_encode (hdf5_file_t *f, size_t raw_size, uint8 *p, const void *_mesg)
/*-------------------------------------------------------------------------
* Function: H5O_stab_fast
*
- * Purpose: Initializes a new message struct with info from a symbol
- * table entry.
+ * Purpose: Initializes a new message struct with info from the cache of
+ * a symbol table entry.
*
* Return: Success: Ptr to message struct, allocated if none
* supplied.
@@ -150,22 +151,18 @@ H5O_stab_encode (hdf5_file_t *f, size_t raw_size, uint8 *p, const void *_mesg)
*-------------------------------------------------------------------------
*/
static void *
-H5O_stab_fast (const H5G_entry_t *ent, void *_mesg)
+H5O_stab_fast (const H5G_cache_t *cache, void *_mesg)
{
H5O_stab_t *stab = (H5O_stab_t *)_mesg;
FUNC_ENTER (H5O_stab_fast, NULL, NULL);
/* check args */
- assert (ent);
+ assert (cache);
- if (H5G_CACHED_STAB==ent->type) {
- if (!stab) stab = H5MM_xcalloc (1, sizeof(H5O_stab_t));
- stab->btree_addr = ent->cache.stab.btree_addr;
- stab->heap_addr = ent->cache.stab.heap_addr;
- } else {
- stab = NULL;
- }
+ if (!stab) stab = H5MM_xcalloc (1, sizeof(H5O_stab_t));
+ stab->btree_addr = cache->stab.btree_addr;
+ stab->heap_addr = cache->stab.heap_addr;
FUNC_LEAVE (stab);
}
@@ -177,8 +174,9 @@ H5O_stab_fast (const H5G_entry_t *ent, void *_mesg)
* Purpose: Copies a message into the cache portion of a symbol table
* entry.
*
- * Return: Success: TRUE if modified.
- * FALSE if not modified.
+ * Return: Success: TRUE if modified; FALSE if not modified.
+ * In either case, the new cache type is
+ * returned through the CACHE_TYPE argument.
*
* Failure: FAIL
*
@@ -191,7 +189,7 @@ H5O_stab_fast (const H5G_entry_t *ent, void *_mesg)
*-------------------------------------------------------------------------
*/
static hbool_t
-H5O_stab_cache (H5G_entry_t *ent, const void *_mesg)
+H5O_stab_cache (H5G_type_t *cache_type, H5G_cache_t *cache, const void *_mesg)
{
const H5O_stab_t *stab = (const H5O_stab_t *)_mesg;
hbool_t modified = FALSE;
@@ -199,28 +197,24 @@ H5O_stab_cache (H5G_entry_t *ent, const void *_mesg)
FUNC_ENTER (H5O_stab_cache, NULL, FAIL);
/* check args */
- assert (ent);
+ assert (cache_type);
+ assert (cache);
assert (stab);
- /*
- * We do this in two steps so Purify doesn't complain about
- * uninitialized memory reads even though they don't bother
- * anything.
- */
- if (H5G_CACHED_STAB != ent->type) {
+ if (H5G_CACHED_STAB != *cache_type) {
modified = TRUE;
- ent->type = H5G_CACHED_STAB;
- ent->cache.stab.btree_addr = stab->btree_addr;
- ent->cache.stab.heap_addr = stab->heap_addr;
+ *cache_type = H5G_CACHED_STAB;
+ cache->stab.btree_addr = stab->btree_addr;
+ cache->stab.heap_addr = stab->heap_addr;
} else {
- if (ent->cache.stab.btree_addr != stab->btree_addr) {
+ if (cache->stab.btree_addr != stab->btree_addr) {
modified = TRUE;
- ent->cache.stab.btree_addr = stab->btree_addr;
+ cache->stab.btree_addr = stab->btree_addr;
}
- if (ent->cache.stab.heap_addr != stab->heap_addr) {
+ if (cache->stab.heap_addr != stab->heap_addr) {
modified = TRUE;
- ent->cache.stab.heap_addr = stab->heap_addr;
+ cache->stab.heap_addr = stab->heap_addr;
}
}
diff --git a/src/Makefile.in b/src/Makefile.in
index 9308965..cebf3c1 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -15,9 +15,9 @@ PROGS=debug
# Source and object files for the library (lexicographically)...
LIB_SRC=H5.c H5A.c H5AC.c H5B.c H5C.c H5D.c H5Dconv.c H5E.c H5F.c H5G.c \
- H5Gnode.c H5Gshad.c H5H.c H5M.c H5MF.c H5MM.c H5O.c H5Ocont.c \
- H5Oname.c H5Onull.c H5Osdtyp.c H5Osdim.c H5Ostab.c H5Ostdst.c H5P.c \
- H5T.c
+ H5Gent.c H5Gnode.c H5Gshad.c H5Gstab.c H5H.c H5M.c H5MF.c H5MM.c \
+ H5O.c H5Ocont.c H5Oname.c H5Onull.c H5Osdtyp.c H5Osdim.c H5Ostab.c \
+ H5Ostdst.c H5P.c H5T.c
LIB_OBJ=$(LIB_SRC:.c=.o)