summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/H5AC.c20
-rw-r--r--src/H5ACprivate.h6
-rw-r--r--src/H5B.c40
-rw-r--r--src/H5Bprivate.h8
-rw-r--r--src/H5D.c188
-rw-r--r--src/H5Dprivate.h15
-rw-r--r--src/H5E.c4
-rw-r--r--src/H5Epublic.h6
-rw-r--r--src/H5F.c5
-rw-r--r--src/H5Fprivate.h84
-rw-r--r--src/H5G.c462
-rw-r--r--src/H5Gnode.c264
-rw-r--r--src/H5Gpkg.h158
-rw-r--r--src/H5Gprivate.h150
-rw-r--r--src/H5Gshad.c460
-rw-r--r--src/H5H.c49
-rw-r--r--src/H5MM.c12
-rw-r--r--src/H5O.c79
-rw-r--r--src/H5Ocont.c1
-rw-r--r--src/H5Oname.c1
-rw-r--r--src/H5Onull.c1
-rw-r--r--src/H5Oprivate.h7
-rw-r--r--src/H5Osdim.c1
-rw-r--r--src/H5Osdtyp.c9
-rw-r--r--src/H5Ostab.c1
-rw-r--r--src/H5Ostdst.c1
-rw-r--r--src/H5private.h9
-rw-r--r--src/Makefile.in5
-rw-r--r--test/Makefile.in2
-rw-r--r--test/th5d.c2
-rw-r--r--test/tohdr.c21
-rw-r--r--test/tstab.c3
32 files changed, 1433 insertions, 641 deletions
diff --git a/src/H5AC.c b/src/H5AC.c
index 478923c..9dc49ed 100644
--- a/src/H5AC.c
+++ b/src/H5AC.c
@@ -173,7 +173,7 @@ H5AC_dest (hdf5_file_t *f)
*/
void *
H5AC_find_f (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr,
- const void *udata)
+ void *udata)
{
unsigned idx;
herr_t status;
@@ -298,9 +298,11 @@ H5AC_compare (const void *_a, const void *_b)
* Function: H5AC_flush
*
* Purpose: Flushes (and destroys if DESTROY is non-zero) the specified
- * entry from the cache. If the entry type is CACHE_FREE then
- * all types of entries are flushed. If the ADDR is zero then
- * all entries of the specified type are flushed.
+ * entry from the cache. If the entry TYPE is CACHE_FREE and
+ * ADDR is zero then all types of entries are flushed. If TYPE
+ * is CACHE_FREE and ADDR is non-zero, then whatever is cached
+ * at ADDR is flushed. Otherwise the thing at ADDR is flushed
+ * if it is the correct type.
*
* If there are protected objects they will not be flushed.
* However, an attempt will be made to flush all non-protected
@@ -334,7 +336,7 @@ H5AC_flush (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr,
assert (f->cache);
i = H5AC_HASH (f, addr);
- if (!type || 0==addr) {
+ if (0==addr) {
#ifdef SORT_BY_ADDR
/*
@@ -360,8 +362,7 @@ H5AC_flush (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr,
slot = f->cache->slot + i;
if (NULL==slot->type) continue;
#endif
- if ((!type || type==slot->type) &&
- (0==addr || addr==slot->addr)) {
+ if (!type || type==slot->type) {
flush = slot->type->flush;
status = (flush)(f, destroy, slot->addr, slot->thing);
if (status<0) {
@@ -373,7 +374,8 @@ H5AC_flush (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr,
}
map = H5MM_xfree (map);
- } else if (f->cache->slot[i].type==type && f->cache->slot[i].addr==addr) {
+ } else if ((!type || f->cache->slot[i].type==type) &&
+ f->cache->slot[i].addr==addr) {
/*
* Flush just this entry.
*/
@@ -583,7 +585,7 @@ H5AC_rename (hdf5_file_t *f, const H5AC_class_t *type,
*/
void *
H5AC_protect (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr,
- const void *udata)
+ void *udata)
{
int idx;
void *thing = NULL;
diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h
index ee002f4..83a1b38 100644
--- a/src/H5ACprivate.h
+++ b/src/H5ACprivate.h
@@ -39,7 +39,7 @@
* by the LOAD method if the DEST argument is non-zero.
*/
typedef struct H5AC_class_t {
- void *(*load)(hdf5_file_t*, haddr_t addr, const void *udata);
+ void *(*load)(hdf5_file_t*, haddr_t addr, void *udata);
herr_t (*flush)(hdf5_file_t*, hbool_t dest, haddr_t addr,
void *thing);
} H5AC_class_t;
@@ -79,9 +79,9 @@ typedef struct H5AC_t {
*/
herr_t H5AC_dest (hdf5_file_t *f);
void *H5AC_find_f (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr,
- const void *udata);
+ void *udata);
void * H5AC_protect (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr,
- const void *udata);
+ void *udata);
herr_t H5AC_unprotect (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr,
void *thing);
herr_t H5AC_flush (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr,
diff --git a/src/H5B.c b/src/H5B.c
index c6249eb..8fe6790 100644
--- a/src/H5B.c
+++ b/src/H5B.c
@@ -100,7 +100,7 @@
/* PRIVATE PROTOTYPES */
static haddr_t H5B_insert_helper (hdf5_file_t *f, haddr_t addr,
- const H5B_class_t *type,
+ H5B_class_t *type,
uint8 *lt_key, hbool_t *lt_key_changed,
uint8 *md_key, void *udata,
uint8 *rt_key, hbool_t *rt_key_changed);
@@ -109,14 +109,14 @@ static herr_t H5B_insert_child (hdf5_file_t *f, const H5B_class_t *type,
intn anchor, void *md_key);
static herr_t H5B_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr,
H5B_t *b);
-static H5B_t *H5B_load (hdf5_file_t *f, haddr_t addr, const void *_data);
+static H5B_t *H5B_load (hdf5_file_t *f, haddr_t addr, void *_data);
static herr_t H5B_decode_key (hdf5_file_t *f, H5B_t *bt, intn idx);
static size_t H5B_nodesize (hdf5_file_t *f, const H5B_class_t *type,
size_t *total_nkey_size, size_t sizeof_rkey);
/* H5B inherits cache-like properties from H5AC */
static const H5AC_class_t H5AC_BT[1] = {{
- (void*(*)(hdf5_file_t*,haddr_t,const void*))H5B_load,
+ (void*(*)(hdf5_file_t*,haddr_t,void*))H5B_load,
(herr_t(*)(hdf5_file_t*,hbool_t,haddr_t,void*))H5B_flush,
}};
@@ -231,13 +231,14 @@ H5B_new (hdf5_file_t *f, const H5B_class_t *type)
*-------------------------------------------------------------------------
*/
static H5B_t *
-H5B_load (hdf5_file_t *f, haddr_t addr, const void *_data)
+H5B_load (hdf5_file_t *f, haddr_t addr, void *_data)
{
- const H5B_class_t *type = (const H5B_class_t *)_data;
+ const H5B_class_t *type = (H5B_class_t *)_data;
size_t size, total_nkey_size;
H5B_t *bt = NULL;
intn i;
uint8 *p;
+ H5B_t *ret_value = NULL;
FUNC_ENTER (H5B_load, NULL, NULL);
@@ -263,11 +264,15 @@ H5B_load (hdf5_file_t *f, haddr_t addr, const void *_data)
p = bt->page;
/* magic number */
- if (HDmemcmp (p, H5B_MAGIC, H5B_SIZEOF_MAGIC)) goto error;
+ if (HDmemcmp (p, H5B_MAGIC, H5B_SIZEOF_MAGIC)) {
+ HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, NULL);
+ }
p += 4;
/* node type and level */
- if (*p++ != type->id) goto error;
+ if (*p++ != type->id) {
+ HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, NULL);
+ }
bt->level = *p++;
/* entries used */
@@ -296,17 +301,18 @@ H5B_load (hdf5_file_t *f, haddr_t addr, const void *_data)
bt->key[2*H5B_K(f,type)].dirty = FALSE;
bt->key[2*H5B_K(f,type)].rkey = p;
bt->key[2*H5B_K(f,type)].nkey = NULL;
- FUNC_LEAVE (bt);
+ ret_value = bt;
-error:
- if (bt) {
+ done:
+ if (!ret_value && bt) {
H5MM_xfree (bt->child);
H5MM_xfree (bt->key);
H5MM_xfree (bt->page);
H5MM_xfree (bt->native);
H5MM_xfree (bt);
}
- HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, NULL);
+
+ FUNC_LEAVE (ret_value);
}
@@ -438,7 +444,7 @@ H5B_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5B_t *bt)
*-------------------------------------------------------------------------
*/
herr_t
-H5B_find (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, void *udata)
+H5B_find (hdf5_file_t *f, H5B_class_t *type, haddr_t addr, void *udata)
{
H5B_t *bt=NULL;
intn idx=-1, lt=0, rt, cmp=1;
@@ -538,7 +544,7 @@ done:
*-------------------------------------------------------------------------
*/
static haddr_t
-H5B_split (hdf5_file_t *f, const H5B_class_t *type, H5B_t *old_bt,
+H5B_split (hdf5_file_t *f, H5B_class_t *type, H5B_t *old_bt,
haddr_t old_addr, intn anchor)
{
H5B_t *new_bt=NULL, *tmp_bt=NULL;
@@ -727,7 +733,7 @@ H5B_decode_key (hdf5_file_t *f, H5B_t *bt, intn idx)
*-------------------------------------------------------------------------
*/
haddr_t
-H5B_insert (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, void *udata)
+H5B_insert (hdf5_file_t *f, H5B_class_t *type, haddr_t addr, void *udata)
{
uint8 lt_key[256], md_key[256], rt_key[256];
hbool_t lt_key_changed=FALSE, rt_key_changed=FALSE;
@@ -980,7 +986,7 @@ H5B_insert_child (hdf5_file_t *f, const H5B_class_t *type, H5B_t *bt,
*-------------------------------------------------------------------------
*/
static haddr_t
-H5B_insert_helper (hdf5_file_t *f, haddr_t addr, const H5B_class_t *type,
+H5B_insert_helper (hdf5_file_t *f, haddr_t addr, H5B_class_t *type,
uint8 *lt_key, hbool_t *lt_key_changed,
uint8 *md_key, void *udata,
uint8 *rt_key, hbool_t *rt_key_changed)
@@ -1219,7 +1225,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5B_list (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, void *udata)
+H5B_list (hdf5_file_t *f, H5B_class_t *type, haddr_t addr, void *udata)
{
H5B_t *bt=NULL;
haddr_t next_addr;
@@ -1352,7 +1358,7 @@ H5B_nodesize (hdf5_file_t *f, const H5B_class_t *type,
*/
herr_t
H5B_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent,
- intn fwidth, const H5B_class_t *type)
+ intn fwidth, H5B_class_t *type)
{
H5B_t *bt = NULL;
int i;
diff --git a/src/H5Bprivate.h b/src/H5Bprivate.h
index 457c8af..f7c3e50 100644
--- a/src/H5Bprivate.h
+++ b/src/H5Bprivate.h
@@ -91,13 +91,13 @@ typedef struct H5B_t {
* Library prototypes.
*/
herr_t H5B_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent,
- intn fwidth, const H5B_class_t *type);
+ intn fwidth, H5B_class_t *type);
haddr_t H5B_new (hdf5_file_t *f, const H5B_class_t *type);
-herr_t H5B_find (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr,
+herr_t H5B_find (hdf5_file_t *f, H5B_class_t *type, haddr_t addr,
void *udata);
-haddr_t H5B_insert (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr,
+haddr_t H5B_insert (hdf5_file_t *f, H5B_class_t *type, haddr_t addr,
void *udata);
-herr_t H5B_list (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr,
+herr_t H5B_list (hdf5_file_t *f, H5B_class_t *type, haddr_t addr,
void *udata);
diff --git a/src/H5D.c b/src/H5D.c
index 8ab6b19..d3c1a5d 100644
--- a/src/H5D.c
+++ b/src/H5D.c
@@ -45,6 +45,18 @@ static char RcsId[] = "@(#)$Revision$";
#define PABLO_MASK H5D_mask
+/*
+ * A dataset is the following struct.
+ */
+typedef struct H5D_t {
+ hdf5_file_t *file; /* File store for this object */
+ H5G_entry_t *ent; /* Cached object header stuff */
+ h5_datatype_t *type; /* Datatype of this dataset */
+ H5P_dim_t *dim; /* Dimensionality of this dataset */
+ haddr_t data_addr; /* Data storage address */
+ hbool_t dirty; /* Header messages not updated yet */
+} H5D_t;
+
/*--------------------- Locally scoped variables -----------------------------*/
/* Whether we've installed the library termination function yet for this interface */
@@ -110,15 +122,16 @@ void H5D_term_interface (void)
RETURNS
Returns ID (atom) on success, FAIL on failure
DESCRIPTION
- This function actually creates the dataset object, but it cannot be
- accessed by name until it is stored in the file.
+ This function actually creates a dataset object in a file (of course,
+ output might not happen for some time).
--------------------------------------------------------------------------*/
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;
-
+ hdf5_file_t *file = NULL;
+ H5G_entry_t tmp_ent;
+
FUNC_ENTER(H5D_create, H5D_init_interface, FAIL);
/* Clear errors and check args and all the boring stuff. */
@@ -135,14 +148,37 @@ hatom_t H5D_create(hatom_t owner_id, hobjtype_t type, const char *name)
/* Initialize the dataset object */
new_dset->file = file;
- new_dset->name = H5MM_xstrdup (name);
- new_dset->cwd = file->root_sym;
- new_dset->ent.header = -1; /* Not on disk yet */
- new_dset->ent.type = H5G_NOTHING_CACHED;
new_dset->type=NULL; /* No type yet */
new_dset->dim=NULL; /* No dimensions yet */
new_dset->data_addr = -1; /* No data yet */
- new_dset->modified=BTRUE; /* Yep, we're new */
+ 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*/
+ }
+
+ /*
+ * 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)
@@ -197,39 +233,44 @@ hatom_t H5D_find_name(hatom_t grp_id, hobjtype_t type, const char *name)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL);
/* Initialize file, directory, name fields */
- dset->modified = FALSE;
dset->file = file;
- dset->name = H5MM_xstrdup (name);
-/* 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! */
- dset->cwd = file->root_sym;
-
- /* Get the dataset's symbol table entry */
- if (H5G_find (dset->file, dset->cwd, NULL, dset->name, &(dset->ent))<0)
- HGOTO_ERROR(H5E_DATASET, H5E_NOTFOUND, FAIL);
+ 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))) {
+ 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)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL);
- if (NULL==H5O_read (dset->file, dset->ent.header, &(dset->ent),
- H5O_SIM_DTYPE, 0, dset->type))
+ if (NULL==H5O_read (dset->file, NO_ADDR, dset->ent, H5O_SIM_DTYPE, 0,
+ dset->type))
HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL);
/* Get the dataset's dimensionality (currently only simple dataspaces) */
if((dset->dim=HDcalloc(1,sizeof(H5P_dim_t)))==NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL);
dset->dim->type=H5P_TYPE_SIMPLE; /* for now... */
- if (NULL==(dset->dim->s=H5O_read (dset->file, dset->ent.header,
- &(dset->ent), H5O_SIM_DIM, 0, NULL)))
+ if (NULL==(dset->dim->s=H5O_read (dset->file, NO_ADDR, dset->ent,
+ H5O_SIM_DIM, 0, NULL)))
HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL);
/* Get the dataset's data offset (currently only standard storage) */
- if (NULL==H5O_read (dset->file, dset->ent.header ,&(dset->ent),
- H5O_STD_STORE, 0, &store))
+ if (NULL==H5O_read (dset->file, NO_ADDR, dset->ent, H5O_STD_STORE, 0,
+ &store))
HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL);
dset->data_addr=store.off;
@@ -241,7 +282,6 @@ done:
if(ret_value == FAIL)
{ /* Error condition cleanup */
if (dset) {
- dset->name = H5MM_xfree (dset->name);
#ifdef LATER
/* We might need to free the `type' and `dim' fields also... */
#endif
@@ -290,9 +330,10 @@ herr_t H5Dset_info(hatom_t oid, hatom_t tid, hatom_t did)
if(dataset->type || dataset->dim)
HGOTO_ERROR(H5E_FUNC, H5E_ALREADYINIT, FAIL);
+ /* Update the dataset in memory */
dataset->type=H5Aatom_object(tid);
dataset->dim=H5Aatom_object(did);
- dataset->modified=BTRUE; /* indicate the values have changed */
+ dataset->dirty = TRUE;
done:
if(ret_value == FAIL)
@@ -499,7 +540,7 @@ herr_t H5Dwrite(hatom_t oid, hatom_t did, VOIDP buf)
if(dataset->data_addr<0) {
if((dataset->data_addr=H5MF_alloc(dataset->file,towrite))<0)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL);
- dataset->modified = TRUE;
+ dataset->dirty = TRUE;
}
/* Check memory to disk datatype conversions, etc. */
@@ -551,9 +592,6 @@ herr_t H5D_flush(hatom_t oid)
{
H5D_t *dataset; /* dataset object to release */
herr_t ret_value = SUCCEED;
- intn mesg_sequence = 0; /*message sequence number */
- hbool_t new_dataset; /*is this a new dataset on disk?*/
- hbool_t entry_changed = FALSE; /*did symbol table entry change?*/
FUNC_ENTER(H5D_flush, H5D_init_interface, FAIL);
@@ -564,37 +602,15 @@ herr_t H5D_flush(hatom_t oid)
if((dataset=H5Aatom_object(oid))==NULL)
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);
- if (dataset->modified) {
- /*
- * A new dataset is one which doesn't exist on disk yet.
- */
- new_dataset = (dataset->ent.header < 0);
-
-
- /*
- * If the dataset is new then create an object header for it. Set the
- * message sequence numbers to H5O_NEW_MESSAGE so we create new
- * messages instead of trying to modify existing messages.
- */
- if (new_dataset) {
- dataset->ent.type = H5G_NOTHING_CACHED;
- if ((dataset->ent.header = H5O_new (dataset->file, 0,
- H5D_MINHDR_SIZE))<0) {
- /* Can't create header. */
- HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL);
- }
- mesg_sequence = H5O_NEW_MESG;
- }
-
+ if (dataset->dirty) {
/*
- * Create or update messages for this dataset. Begin with the
+ * Modify/create messages for this dataset. Begin with the
* type information.
*/
if (H5T_is_atomic (dataset->type)) {
- if (H5O_modify (dataset->file, dataset->ent.header,
- &(dataset->ent), &entry_changed, H5O_SIM_DTYPE,
- mesg_sequence, dataset->type)<0) {
+ if (H5O_modify (dataset->file, NO_ADDR, dataset->ent,
+ H5O_SIM_DTYPE, 0, dataset->type)<0) {
/* Can't create/update type message */
HGOTO_ERROR (H5E_INTERNAL, H5E_CANTCREATE, FAIL);
}
@@ -604,12 +620,11 @@ herr_t H5D_flush(hatom_t oid)
}
/*
- * Write the dimensionality information.
+ * Modify/create the dimensionality information.
*/
if (H5P_is_simple (dataset->dim)) {
- if (H5O_modify (dataset->file, dataset->ent.header,
- &(dataset->ent), &entry_changed, H5O_SIM_DIM,
- mesg_sequence, dataset->dim->s)<0) {
+ if (H5O_modify (dataset->file, NO_ADDR, dataset->ent,
+ H5O_SIM_DIM, 0, dataset->dim->s)<0) {
/* Can't create/update dimensionality message */
HGOTO_ERROR (H5E_INTERNAL, H5E_CANTCREATE, FAIL);
}
@@ -619,7 +634,7 @@ herr_t H5D_flush(hatom_t oid)
}
/*
- * Write the dataset's storage information.
+ * Modify/create the dataset's storage information.
*/
if (dataset->data_addr>=0) {
H5O_std_store_t store; /* standard storage info */
@@ -627,41 +642,21 @@ herr_t H5D_flush(hatom_t oid)
store.len = H5T_size (dataset->type, BTRUE) *
H5P_nelem (dataset->dim);
store.off = dataset->data_addr;
- if (H5O_modify (dataset->file, dataset->ent.header,
- &(dataset->ent), &entry_changed, H5O_STD_STORE,
- mesg_sequence, &store)<0) {
+ if (H5O_modify (dataset->file, NO_ADDR, dataset->ent,
+ H5O_STD_STORE, 0, &store)<0) {
/* Can't create/modify storage information */
HGOTO_ERROR (H5E_INTERNAL, H5E_CANTCREATE, FAIL);
}
}
- /*
- * If this is a new dataset then we must give it a name so others can
- * access it.
- */
- if (new_dataset) {
- assert (dataset->name);
- if (H5G_insert (dataset->file, dataset->cwd, NULL,
- dataset->name, &(dataset->ent))<0) {
- /* Can't name dataset */
- HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL);
- }
- } else if (entry_changed) {
- if (H5G_modify (dataset->file, dataset->cwd, NULL,
- dataset->name, &(dataset->ent))<0) {
- /* Can't update symbol table entry */
- HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL);
- }
- }
-
-#ifdef ROBB
- /* Flush dataset header to disk */
- if (H5O_flush (dataset->file, FALSE, dataset->ent.header, NULL)<0) {
+#if 1
+ /* 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);
}
-#endif /* ROBB */
-
- dataset->modified = FALSE; /*it's clean now*/
+#endif
+
+ dataset->dirty = FALSE; /*it's clean now*/
}
done:
@@ -703,13 +698,16 @@ herr_t H5D_release(hatom_t oid)
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);
/* Check if we have information to flush to the file... */
- if(dataset->modified && H5D_flush(oid)<0) {
+ if(dataset->dirty && H5D_flush(oid)<0) {
/* Can't flush dataset */
HGOTO_ERROR (H5E_OHDR, H5E_CANTFLUSH, FAIL);
}
+
+ /* Close the dataset object */
+ H5G_close (dataset->file, dataset->ent);
+ dataset->ent = NULL;
/* release the memory used for the dataset */
- dataset->name = H5MM_xfree (dataset->name);
H5MM_xfree (dataset);
/* Delete the dataset from the atom group */
diff --git a/src/H5Dprivate.h b/src/H5Dprivate.h
index f0a08a2..149de5e 100644
--- a/src/H5Dprivate.h
+++ b/src/H5Dprivate.h
@@ -28,21 +28,6 @@
#include <H5Pprivate.h> /* for the H5P_sdim_t type */
#include <H5Oprivate.h> /* Object Headers */
-/*
- * A dataset is the following struct. It can exist in memory without
- * existing in a file.
- */
-typedef struct H5D_t {
- hdf5_file_t *file; /* File store for this object */
- char *name; /* Name of dataset, relative or absolute */
- H5G_entry_t *cwd; /* Directory for relative name lookup */
- H5G_entry_t ent; /* Cached object header stuff */
- h5_datatype_t *type; /* Datatype of this dataset */
- H5P_dim_t *dim; /* Dimensionality of this dataset */
- haddr_t data_addr; /* Data storage address */
- hbool_t modified; /* Is memory out of data wrt file? */
-} H5D_t;
-
#define H5D_RESERVED_ATOMS 0
/* Set the minimum object header size to create objects with */
diff --git a/src/H5E.c b/src/H5E.c
index 2a586e1..137a970 100644
--- a/src/H5E.c
+++ b/src/H5E.c
@@ -77,7 +77,8 @@ static const hdf_min_error_messages_t hdf_min_error_messages[] =
{H5E_FILEEXISTS, "File already exists"},
{H5E_FILEOPEN, "File already open"},
{H5E_CANTCREATE, "Can't create file"},
- {H5E_CANTOPEN, "Can't open file"},
+ {H5E_CANTOPENFILE, "Can't open file"},
+ {H5E_CANTOPENOBJ, "Can't open object"},
{H5E_NOTHDF5, "Not an HDF5 format file"},
{H5E_BADFILE, "Bad file ID accessed"},
{H5E_SEEKERROR, "Seek failed"},
@@ -90,6 +91,7 @@ static const hdf_min_error_messages_t hdf_min_error_messages[] =
{H5E_CANTFLUSH, "Can't flush object from cache"},
{H5E_CANTLOAD, "Can't load object into cache"},
{H5E_PROTECT, "Protected object error"},
+ {H5E_NOTCACHED, "Object not currently cached"},
{H5E_NOTFOUND, "Object not found"},
{H5E_EXISTS, "Object already exists"},
{H5E_CANTENCODE, "Can't encode value"},
diff --git a/src/H5Epublic.h b/src/H5Epublic.h
index 101ad76..bde74e5 100644
--- a/src/H5Epublic.h
+++ b/src/H5Epublic.h
@@ -64,7 +64,7 @@ typedef enum
H5E_FILEEXISTS, /* File already exists */
H5E_FILEOPEN, /* File already open */
H5E_CANTCREATE, /* Can't create file */
- H5E_CANTOPEN, /* Can't open file */
+ H5E_CANTOPENFILE, /* Can't open file */
H5E_NOTHDF5, /* Not an HDF5 format file */
H5E_BADFILE, /* Bad file ID accessed */
@@ -85,7 +85,8 @@ typedef enum
H5E_CANTFLUSH, /* Can't flush object from cache */
H5E_CANTLOAD, /* Can't load object into cache */
H5E_PROTECT, /* Protected object error */
-
+ H5E_NOTCACHED, /* Object not currently cached */
+
/* B-tree related errors */
H5E_NOTFOUND, /* Object not found */
H5E_EXISTS, /* Object already exists */
@@ -102,6 +103,7 @@ typedef enum
H5E_BADMESG, /* Unrecognized message */
/* Directory related errors */
+ H5E_CANTOPENOBJ, /* Can't open object */
H5E_COMPLEN, /* Name component is too long */
H5E_LINK /* Link count failure */
}
diff --git a/src/H5F.c b/src/H5F.c
index 348e477..6d1aec0 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -399,8 +399,7 @@ H5F_new (void)
H5AC_new (f, H5AC_NSLOTS);
/* Create a root symbol slot */
- f->root_sym = H5MM_xcalloc (1, sizeof (H5G_entry_t));
- f->root_sym->type = H5G_NOTHING_CACHED;
+ f->root_sym = H5G_new_entry ();
return f;
}
@@ -688,7 +687,7 @@ hatom_t H5Fopen(const char *filename, uintn flags, hatom_t access_temp)
/* Check if the file already exists */
f_handle=H5F_OPEN(filename,flags);
if(H5F_OPENERR(f_handle))
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPEN, FAIL);/*file doesn't exist*/
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL);/*file doesn't exist*/
/* Create the file node */
if (NULL==(new_file=H5F_new()))
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
index 275cb1d..f1c7b59 100644
--- a/src/H5Fprivate.h
+++ b/src/H5Fprivate.h
@@ -185,10 +185,22 @@ typedef MPFILE *hdf_file_t;
*(p) = (uint8)(((uint64)(i) >> 8) & 0xff); (p)++; \
*(p) = (uint8)(((uint64)(i) >> 16) & 0xff); (p)++; \
*(p) = (uint8)(((uint64)(i) >> 24) & 0xff); (p)++; \
- *(p) = (uint8)(((uint64)(i) >> 32) & 0xff); (p)++; \
- *(p) = (uint8)(((uint64)(i) >> 40) & 0xff); (p)++; \
- *(p) = (uint8)(((uint64)(i) >> 48) & 0xff); (p)++; \
- *(p) = (uint8)(((uint64)(i) >> 56) & 0xff); (p)++; \
+ if (sizeof(int64)>4) { \
+ *(p) = (uint8)(((uint64)(i) >> 32) & 0xff); (p)++; \
+ *(p) = (uint8)(((uint64)(i) >> 40) & 0xff); (p)++; \
+ *(p) = (uint8)(((uint64)(i) >> 48) & 0xff); (p)++; \
+ *(p) = (uint8)(((uint64)(i) >> 56) & 0xff); (p)++; \
+ } else if ((i)<0) { \
+ *(p)++ = 0xff; \
+ *(p)++ = 0xff; \
+ *(p)++ = 0xff; \
+ *(p)++ = 0xff; \
+ } else { \
+ *(p)++ = 0x00; \
+ *(p)++ = 0x00; \
+ *(p)++ = 0x00; \
+ *(p)++ = 0x00; \
+ } \
}
# define UINT64ENCODE(p, i) { \
@@ -196,10 +208,17 @@ typedef MPFILE *hdf_file_t;
*(p) = (uint8)(((i) >> 8) & 0xff); (p)++; \
*(p) = (uint8)(((i) >> 16) & 0xff); (p)++; \
*(p) = (uint8)(((i) >> 24) & 0xff); (p)++; \
- *(p) = (uint8)(((i) >> 32) & 0xff); (p)++; \
- *(p) = (uint8)(((i) >> 40) & 0xff); (p)++; \
- *(p) = (uint8)(((i) >> 48) & 0xff); (p)++; \
- *(p) = (uint8)(((i) >> 56) & 0xff); (p)++; \
+ if (sizeof(uint64)>4) { \
+ *(p) = (uint8)(((i) >> 32) & 0xff); (p)++; \
+ *(p) = (uint8)(((i) >> 40) & 0xff); (p)++; \
+ *(p) = (uint8)(((i) >> 48) & 0xff); (p)++; \
+ *(p) = (uint8)(((i) >> 56) & 0xff); (p)++; \
+ } else { \
+ *(p)++ = 0x00; \
+ *(p)++ = 0x00; \
+ *(p)++ = 0x00; \
+ *(p)++ = 0x00; \
+ } \
}
# define INT16DECODE(p, i) { \
@@ -231,10 +250,14 @@ typedef MPFILE *hdf_file_t;
(i) |= ((int64)(*(p) & 0xff) << 8); (p)++; \
(i) |= ((int64)(*(p) & 0xff) << 16); (p)++; \
(i) |= ((int64)(*(p) & 0xff) << 24); (p)++; \
- (i) |= ((int64)(*(p) & 0xff) << 32); (p)++; \
- (i) |= ((int64)(*(p) & 0xff) << 40); (p)++; \
- (i) |= ((int64)(*(p) & 0xff) << 48); (p)++; \
- (i) |= ((int64)(*(p) & 0xff) << 56); (p)++; \
+ if (sizeof(int64)>4) { \
+ (i) |= ((int64)(*(p) & 0xff) << 32); (p)++; \
+ (i) |= ((int64)(*(p) & 0xff) << 40); (p)++; \
+ (i) |= ((int64)(*(p) & 0xff) << 48); (p)++; \
+ (i) |= ((int64)(*(p) & 0xff) << 56); (p)++; \
+ } else { \
+ (p) += 4; \
+ } \
}
# define UINT64DECODE(p, i) { \
@@ -242,10 +265,14 @@ typedef MPFILE *hdf_file_t;
(i) |= ((uint64)(*(p) & 0xff) << 8); (p)++; \
(i) |= ((uint64)(*(p) & 0xff) << 16); (p)++; \
(i) |= ((uint64)(*(p) & 0xff) << 24); (p)++; \
- (i) |= ((uint64)(*(p) & 0xff) << 32); (p)++; \
- (i) |= ((uint64)(*(p) & 0xff) << 40); (p)++; \
- (i) |= ((uint64)(*(p) & 0xff) << 48); (p)++; \
- (i) |= ((uint64)(*(p) & 0xff) << 56); (p)++; \
+ if (sizeof(uint64)>4) { \
+ (i) |= ((uint64)(*(p) & 0xff) << 32); (p)++; \
+ (i) |= ((uint64)(*(p) & 0xff) << 40); (p)++; \
+ (i) |= ((uint64)(*(p) & 0xff) << 48); (p)++; \
+ (i) |= ((uint64)(*(p) & 0xff) << 56); (p)++; \
+ } else { \
+ (p) += 4; \
+ } \
}
#else
@@ -254,8 +281,29 @@ typedef MPFILE *hdf_file_t;
# define UINT16ENCODE(p, i) { *((uint16 *)(p)) = (uint16)(i); (p)+=2; }
# define INT32ENCODE(p, i) { *((int32 *)(p)) = (int32)(i); (p)+=4; }
# define UINT32ENCODE(p, i) { *((uint32 *)(p)) = (uint32)(i); (p)+=4; }
-# define INT64ENCODE(p, i) { *((int64 *)(p)) = (int64)(i); (p)+=8; }
-# define UINT64ENCODE(p, i) { *((uint64 *)(p)) = (uint64)(i); (p)+=8; }
+
+# define INT64ENCODE(p, i) { \
+ *((int64 *)(p)) = (int64)(i); \
+ (p) += sizeof(int64); \
+ if (4==sizeof(int64)) { \
+ *(p)++ = (i)<0?0xff:0x00; \
+ *(p)++ = (i)<0?0xff:0x00; \
+ *(p)++ = (i)<0?0xff:0x00; \
+ *(p)++ = (i)<0?0xff:0x00; \
+ } \
+}
+
+# define UINT64ENCODE(p, i) { \
+ *((uint64 *)(p)) = (uint64)(i); \
+ (p) += sizeof(uint64); \
+ if (4==sizeof(uint64)) { \
+ *(p)++ = 0x00; \
+ *(p)++ = 0x00; \
+ *(p)++ = 0x00; \
+ *(p)++ = 0x00; \
+ } \
+}
+
# define INT16DECODE(p, i) { (i) = (int16)(*(const int16 *)(p)); (p)+=2; }
# define UINT16DECODE(p, i) { (i) = (uint16)(*(const uint16 *)(p)); (p)+=2; }
# define INT32DECODE(p, i) { (i) = (int32)(*(const int32 *)(p)); (p)+=4; }
diff --git a/src/H5G.c b/src/H5G.c
index ea2ae3e..88c8576 100644
--- a/src/H5G.c
+++ b/src/H5G.c
@@ -28,25 +28,29 @@
* Robb Matzke, 30 Aug 1997
* Added `Errors:' field to function prologues.
*
+ * Robb Matzke, 18 Sep 1997
+ * Added shadow entry support.
+ *
*-------------------------------------------------------------------------
*/
+#define H5G_PACKAGE /*suppress error message about including H5Gpkg.h*/
/* Packages needed by this file... */
#include <H5private.h>
#include <H5Bprivate.h>
#include <H5Eprivate.h>
-#include <H5Gprivate.h>
+#include <H5Gpkg.h>
#include <H5Hprivate.h>
#include <H5MMprivate.h>
#include <H5Oprivate.h>
#define H5G_INIT_HEAP 8192
-#define PABLO_MASK H5G_mask
+#define PABLO_MASK H5G_mask
static herr_t H5G_mkroot (hdf5_file_t *f, size_t size_hint);
/* Is the interface initialized? */
-static intn interface_initialize_g = FALSE;
+static hbool_t interface_initialize_g = FALSE;
/*-------------------------------------------------------------------------
@@ -155,37 +159,35 @@ H5G_basename (const char *name, size_t *size_p)
*
* If the name cannot be fully resolved, then REST will
* point to the part of NAME where the traversal failed
- * (REST will always point to a relative name) and BASE_ENT
- * will not be initialized. DIR_ENT will be initialized with
+ * (REST will always point to a relative name) and this
+ * function will return null. DIR_ENT will be initialized with
* information about the directory (or other object) at which
* the traversal failed. However, if the name can be fully
* resolved, then REST points to the null terminator of NAME.
*
* As a special case, if the NAME is the name `/' (or
- * equivalent) then DIR_ENT is initialized to all zero and
- * BASE_ENT is initialized with the contents of the root
- * symbol table entry.
+ * equivalent) then DIR_ENT is initialized to all zero
+ * and a pointer to the root symbol table entry is returned.
*
* As a special case, if the NAME is the string `/foo' (or
* equivalent) and the root symbol table entry points to a
* non-directory object with a name message with the value
- * `foo' then DIR_ENT is initialized to all zero and BASE_ENT
- * is initialized with the contents of the root symbol table
- * entry.
+ * `foo' then DIR_ENT is initialized to all zero and a pointer
+ * to the root symbol table entry is returned.
*
* Errors:
* DIRECTORY COMPLEN Component is too long.
* DIRECTORY NOTFOUND Component not found.
* DIRECTORY NOTFOUND Root not found.
*
- * Return: Success: SUCCEED if the name can be fully
- * resolved.
+ * Return: Success: Pointer to a cached symbol table entry if the
+ * name can be fully resolved. The pointer is
+ * valid until one of the H5AC (cache) functions
+ * is called.
*
- * Failure: FAIL if something bad happened (REST and
- * DIR_ENT have undefined values).
- *
- * -2 if the name could not be fully resolved
- * (REST and DIR_ENT are initialized).
+ * Failure: Null if the name could not be fully resolved.
+ * REST and DIR_ENT are initialized (possibly to
+ * zero if the failure occurred soon enough).
*
* Programmer: Robb Matzke
* robb@maya.nuance.com
@@ -195,17 +197,21 @@ H5G_basename (const char *name, size_t *size_p)
*
*-------------------------------------------------------------------------
*/
-static herr_t
+static H5G_entry_t *
H5G_namei (hdf5_file_t *f, H5G_entry_t *cwd, const char *name,
- const char **rest, H5G_entry_t *dir_ent, H5G_entry_t *base_ent)
+ const char **rest, H5G_entry_t *dir_ent)
{
- H5G_entry_t ent[2];
- H5G_entry_t *tmp, *dir, *base; /*ptrs to DIR and BASE entries */
+ H5G_entry_t dir; /*entry for current directory */
size_t nchars; /*component name length */
char comp[1024]; /*component name buffer */
hbool_t aside = FALSE; /*did we look at a name message?*/
+ H5G_entry_t *ret_value=NULL; /*return value */
+
+ /* clear output args before FUNC_ENTER() in case it fails */
+ if (rest) *rest = name;
+ if (dir_ent) memset (dir_ent, 0, sizeof(H5G_entry_t));
- FUNC_ENTER (H5G_namei, NULL, FAIL);
+ FUNC_ENTER (H5G_namei, NULL, NULL);
/* check args */
assert (f);
@@ -214,26 +220,30 @@ H5G_namei (hdf5_file_t *f, H5G_entry_t *cwd, const char *name,
assert (cwd || '/'==*name);
/* starting point */
- dir = ent+0;
- base = ent+1;
if ('/'==*name) {
- ent[0] = ent[1] = *(f->root_sym);
+ if (f->root_sym->header<=0) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, NULL);
+ }
+ ret_value = f->root_sym;
+ dir = *(f->root_sym);
} else {
- ent[0] = ent[1] = *cwd;
+ ret_value = cwd;
+ dir = *cwd;
}
/* traverse the name */
while ((name=H5G_component (name, &nchars)) && *name) {
/*
- * The special name `.'.
+ * The special name `.' is a no-op.
*/
if ('.'==name[0] && !name[1]) continue;
/*
- * Advance.
+ * Advance to the next component of the name.
*/
- tmp=dir; dir=base; base=tmp; /*swap*/
+ dir = *ret_value;
+ ret_value = NULL;
if (rest) *rest = name;
/*
@@ -242,38 +252,32 @@ H5G_namei (hdf5_file_t *f, H5G_entry_t *cwd, const char *name,
*/
if (nchars+1 > sizeof(comp)) {
/* component is too long */
- if (dir_ent) *dir_ent = *dir;
- HRETURN_ERROR (H5E_DIRECTORY, H5E_COMPLEN, -2);
+ if (dir_ent) *dir_ent = dir;
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_COMPLEN, NULL);
}
HDmemcpy (comp, name, nchars);
comp[nchars] = '\0';
- if (H5G_stab_find (f, dir, comp, base)<0) {
+ if (NULL==(ret_value=H5G_stab_find (f, NO_ADDR, &dir, comp))) {
/*
- * Component was not found in the current symbol table, probably
- * because it isn't a symbol table. If it is the root symbol then
+ * Component was not found in the current symbol table, possibly
+ * because DIR isn't a symbol table. If it is the root symbol then
* see if it has the appropriate name field. The ASIDE variable
* prevents us from saying `/foo/foo' where the root object has
* the name `foo'.
*/
H5O_name_t mesg={0};
- if (!aside && dir->header==f->root_sym->header &&
- H5O_read (f, dir->header, dir, H5O_NAME, 0, &mesg)) {
- if (!HDstrcmp (mesg.s, comp)) {
- H5O_reset (H5O_NAME, &mesg);
- *base = *dir;
- aside = TRUE;
- } else {
- /* component not found */
- H5O_reset (H5O_NAME, &mesg);
- if (dir_ent) *dir_ent = *dir;
- HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, -2);
- }
+ if (!aside && dir.header==f->root_sym->header &&
+ H5O_read (f, dir.header, &dir, H5O_NAME, 0, &mesg) &&
+ !HDstrcmp (mesg.s, comp)) {
H5O_reset (H5O_NAME, &mesg);
+ ret_value = f->root_sym;
+ aside = TRUE;
} else {
/* component not found */
- if (dir_ent) *dir_ent = *dir;
- HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, -2);
+ H5O_reset (H5O_NAME, &mesg);
+ if (dir_ent) *dir_ent = dir;
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, NULL);
}
}
@@ -284,20 +288,19 @@ H5G_namei (hdf5_file_t *f, H5G_entry_t *cwd, const char *name,
/* output parameters */
if (rest) *rest = name; /*final null*/
if (dir_ent) {
- if (base->header == f->root_sym->header) {
+ if (ret_value->header == f->root_sym->header) {
HDmemset (dir_ent, 0, sizeof(H5G_entry_t)); /*root has no parent*/
} else {
- *dir_ent = *dir;
+ *dir_ent = dir;
}
}
- if (base_ent) *base_ent = *base;
/* Perhaps the root object doesn't even exist! */
- if (base->header<=0) {
- HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, -2); /*root not found*/
+ if (ret_value->header<=0) {
+ HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, NULL); /*root not found*/
}
- FUNC_LEAVE (SUCCEED);
+ FUNC_LEAVE (ret_value);
}
@@ -338,29 +341,30 @@ H5G_mkroot (hdf5_file_t *f, size_t size_hint)
H5G_entry_t root; /*old root entry */
const char *root_name=NULL; /*name of old root object */
intn nlinks; /*number of links */
- hbool_t reset = FALSE; /*should name message be reset? */
+ H5G_entry_t *handle; /*handle for open object */
FUNC_ENTER (H5G_mkroot, NULL, FAIL);
/*
+ * Make sure we have the latest info since someone might have the root
+ * object open for modifications.
+ */
+ 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 (f->root_sym->header>0) {
- if (H5O_read (f, f->root_sym->header, f->root_sym, H5O_STAB, 0, &stab)) {
+ 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)) {
- /*dont reset name until root_name is done*/
- root_name = name.s;
- reset = TRUE;
-
- /* remove all name messages -- don't care if it fails */
+ root_name = name.s; /*dont reset name until root_name is done!*/
root = *(f->root_sym);
- H5O_remove (f, root.header, &root, NULL, H5O_NAME, H5O_ALL);
} else {
root = *(f->root_sym);
@@ -392,15 +396,31 @@ H5G_mkroot (hdf5_file_t *f, size_t size_hint)
nlinks = H5O_link (f, root.header, &root, 0);
assert (1==nlinks);
#endif
-
- if (H5G_stab_insert (f, f->root_sym, root_name, &root)) {
+ 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 (reset) H5O_reset (H5O_NAME, &name);
+
+ /* 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;
+ }
+ H5ECLEAR;
}
+ H5O_reset (H5O_NAME, &name);
FUNC_LEAVE (SUCCEED);
}
@@ -449,7 +469,6 @@ H5G_new (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
{
const char *rest=NULL;
H5G_entry_t _parent, _child;
- herr_t status;
char _comp[1024];
size_t nchars;
@@ -467,10 +486,7 @@ H5G_new (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
H5ECLEAR;
/* lookup name */
- status = H5G_namei (f, cwd, name, &rest, dir_ent, NULL);
- if (status<0 && !rest) {
- HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL); /*lookup failed*/
- } else if (0==status) {
+ if (H5G_namei (f, cwd, name, &rest, dir_ent)) {
HRETURN_ERROR (H5E_DIRECTORY, H5E_EXISTS, FAIL); /*already exists*/
}
H5ECLEAR; /*it's OK that we didn't find it*/
@@ -508,6 +524,91 @@ H5G_new (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
/*-------------------------------------------------------------------------
+ * 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);
+ }
+
+ FUNC_LEAVE (handle);
+}
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_close
+ *
+ * Purpose: Closes an object that was open for modification.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Thursday, September 18, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_close (hdf5_file_t *f, H5G_entry_t *ent)
+{
+ FUNC_ENTER (H5G_close, NULL, FAIL);
+
+ if (H5G_shadow_close (f, ent)<0) {
+ HRETURN_ERROR (H5E_SYM, H5E_CANTFLUSH, FAIL);
+ }
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
* Function: H5G_find
*
* Purpose: Finds an object with the specified NAME in file F. If
@@ -527,7 +628,14 @@ H5G_new (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
* Errors:
* DIRECTORY NOTFOUND Object not found.
*
- * Return: Success: SUCCEED with DIR_ENT and ENT initialized.
+ * 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
*
@@ -543,6 +651,7 @@ 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_entry_t *ent_p = NULL;
FUNC_ENTER (H5G_find, NULL, FAIL);
/* check args */
@@ -554,10 +663,11 @@ H5G_find (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, FAIL); /*object not found*/
}
- if (H5G_namei (f, cwd, name, NULL, dir_ent, ent)<0) {
+ if (NULL==(ent_p=H5G_namei (f, cwd, name, NULL, dir_ent))) {
HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, FAIL); /*object not found*/
}
+ if (ent) *ent = *ent_p;
FUNC_LEAVE (SUCCEED);
}
@@ -608,7 +718,6 @@ herr_t
H5G_insert (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
const char *name, H5G_entry_t *ent)
{
- herr_t status;
const char *rest=NULL;
H5G_entry_t _parent;
size_t nchars;
@@ -622,8 +731,9 @@ H5G_insert (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
assert (name && *name);
assert (cwd || '/'==*name);
assert (ent);
+ assert (!ent->shadow);
if (!dir_ent) dir_ent = &_parent;
-
+
/*
* 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
@@ -639,10 +749,7 @@ H5G_insert (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
/*
* Look up the name -- it shouldn't exist yet.
*/
- status = H5G_namei (f, cwd, name, &rest, dir_ent, NULL);
- if (status<0 && !rest) {
- HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL); /*lookup failed*/
- } else if (0==status) {
+ if (H5G_namei (f, cwd, name, &rest, dir_ent)) {
HRETURN_ERROR (H5E_DIRECTORY, H5E_EXISTS, FAIL); /*already exists*/
}
H5ECLEAR; /*it's OK that we didn't find it*/
@@ -687,14 +794,12 @@ 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).
+ * find). We don't have to worry about it being open.
*/
if (f->root_sym->header<=0) {
H5O_name_t name_mesg;
name_mesg.s = rest;
- if (H5O_modify (f, ent->header, ent, NULL, H5O_NAME, 0, &name_mesg)<0 &&
- H5O_modify (f, ent->header, ent, NULL, H5O_NAME, H5O_NEW_MESG,
- &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);
}
@@ -721,73 +826,6 @@ H5G_insert (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
/*-------------------------------------------------------------------------
- * Function: H5G_modify
- *
- * Purpose: Modifies the symbol table entry for the object with the
- * specified NAME by copying the new symbol table entry ENT
- * over the top of the old one. If NAME is relative then it
- * is interpreted with respect to the CWD pointer. If non-null,
- * DIR_ENT will be initialized with the symbol table entry for the
- * directory which contains the new ENT.
- *
- * Do not use this function to change the entry for the root
- * symbol since that's a special case. This function returns
- * failure if that is attempted.
- *
- * Errors:
- * DIRECTORY CANTINIT Can't modify.
- * DIRECTORY NOTFOUND Entry not found.
- *
- * Return: Success: SUCCEED with optional DIR_ENT initialized with
- * the symbol table entry for the directory
- * which contains the new ENT.
- *
- * Failure: FAIL (DIR_ENT is not modified).
- *
- * Programmer: Robb Matzke
- * robb@maya.nuance.com
- * Aug 11 1997
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5G_modify (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
- const char *name, H5G_entry_t *ent)
-{
- const char *rest=NULL;
- H5G_entry_t _parent;
-
- FUNC_ENTER (H5G_modify, NULL, FAIL);
-
- /* check args */
- assert (f);
- assert (name && *name);
- assert (cwd || '/'==*name);
- assert (ent);
- if (!dir_ent) dir_ent = &_parent;
-
- /* lookup name */
- if (H5G_namei (f, cwd, name, &rest, dir_ent, NULL)<0) {
- HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, FAIL); /*entry not found*/
- }
-
- /*
- * Modify the entry in the parent or in the file struct.
- */
- if (dir_ent->header<=0) {
- *(f->root_sym) = *ent;
- } else if (H5G_stab_modify (f, dir_ent, rest, ent)<0) {
- HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL); /*can't modify*/
- }
-
- FUNC_LEAVE (SUCCEED);
-}
-
-
-
-/*-------------------------------------------------------------------------
* Function: H5G_stab_new
*
* Purpose: Creates a new empty symbol table (object header, name heap,
@@ -869,11 +907,10 @@ H5G_stab_new (hdf5_file_t *f, H5G_entry_t *self, size_t init)
/* insert the symbol table message */
if (self) {
- self->name_off = 0;
+ memset (self, 0, sizeof(H5G_entry_t));
self->header = addr;
- self->type = H5G_NOTHING_CACHED;
}
- if (H5O_modify(f, addr, self, NULL, H5O_STAB, H5O_NEW_MESG, &stab)<0) {
+ if (H5O_modify(f, addr, self, H5O_STAB, H5O_NEW_MESG, &stab)<0) {
HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); /*can't create message*/
}
@@ -886,15 +923,22 @@ H5G_stab_new (hdf5_file_t *f, H5G_entry_t *self, size_t init)
*
* Purpose: Finds a symbol named NAME in the symbol table whose
* description is stored in SELF in file F and returns a
- * copy of the symbol table entry through the ENT argument.
+ * 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: Address corresponding to the name.
+ * 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: FAIL
+ * Failure: NULL
*
* Programmer: Robb Matzke
* matzke@llnl.gov
@@ -904,93 +948,41 @@ H5G_stab_new (hdf5_file_t *f, H5G_entry_t *self, size_t init)
*
*-------------------------------------------------------------------------
*/
-haddr_t
-H5G_stab_find (hdf5_file_t *f, H5G_entry_t *self, const char *name,
- H5G_entry_t *ent)
+H5G_entry_t *
+H5G_stab_find (hdf5_file_t *f, haddr_t addr, H5G_entry_t *self,
+ const char *name)
{
- H5G_node_ud1_t udata; /*data to pass through B-tree */
+ H5G_bt_ud1_t udata; /*data to pass through B-tree */
H5O_stab_t stab; /*symbol table message */
- FUNC_ENTER (H5G_stab_find, NULL, FAIL);
+ FUNC_ENTER (H5G_stab_find, NULL, NULL);
/* Check arguments */
assert (f);
- assert (self && self->header>=0);
- assert (name && *name);
+ 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, self->header, self, H5O_STAB, 0, &stab)) {
- HRETURN_ERROR (H5E_SYM, H5E_BADMESG, FAIL); /*can't read message*/
+ 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;
/* search the B-tree */
if (H5B_find (f, H5B_SNODE, stab.btree_addr, &udata)<0) {
- HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); /*not found*/
+ HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL); /*not found*/
}
/* return the result */
- if (ent) *ent = udata.entry;
- FUNC_LEAVE (udata.entry.header);
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5G_stab_modify
- *
- * Purpose: Modifies the entry for an existing symbol. The name of the
- * symbol is NAME in the symbol table described by SELF in
- * file F. ENT is the new symbol table entry to use for the
- * symbol.
- *
- * Errors:
- * SYM BADMESG Can't read message.
- * SYM NOTFOUND Not found.
- *
- * Return: Success: SUCCEED
- *
- * Failure: FAIL
- *
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Aug 1 1997
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5G_stab_modify (hdf5_file_t *f, H5G_entry_t *self, const char *name,
- H5G_entry_t *ent)
-{
- H5G_node_ud1_t udata; /*data to pass through B-tree */
- H5O_stab_t stab; /*symbol table message */
-
- FUNC_ENTER (H5G_stab_modify, NULL, FAIL);
-
- /* check arguments */
- assert (f);
- assert (self && self->header>=0);
- assert (name && *name);
- assert (ent);
-
- /* set up the udata */
- if (NULL==H5O_read (f, self->header, self, H5O_STAB, 0, &stab)) {
- HRETURN_ERROR (H5E_SYM, H5E_BADMESG, FAIL); /*can't read message*/
- }
- udata.operation = H5G_OPER_MODIFY;
- udata.name = name;
- udata.heap_addr = stab.heap_addr;
- udata.entry = *ent;
-
- /* search and modify the B-tree */
- if (H5B_find (f, H5B_SNODE, stab.btree_addr, &udata)<0) {
- HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); /*not found*/
- }
-
- FUNC_LEAVE (SUCCEED);
+ FUNC_LEAVE (udata.entry_ptr);
}
@@ -1015,6 +1007,10 @@ H5G_stab_modify (hdf5_file_t *f, H5G_entry_t *self, const char *name,
*
* 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
@@ -1022,7 +1018,7 @@ 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_node_ud1_t udata; /*data to pass through B-tree */
+ H5G_bt_ud1_t udata; /*data to pass through B-tree */
FUNC_ENTER (H5G_stab_insert, NULL, FAIL);
@@ -1036,9 +1032,13 @@ H5G_stab_insert (hdf5_file_t *f, H5G_entry_t *self, const char *name,
if (NULL==H5O_read (f, self->header, self, H5O_STAB, 0, &stab)) {
HRETURN_ERROR (H5E_SYM, H5E_BADMESG, FAIL); /*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;
/* insert */
if (H5B_insert (f, H5B_SNODE, stab.btree_addr, &udata)<0) {
@@ -1086,7 +1086,7 @@ intn
H5G_stab_list (hdf5_file_t *f, H5G_entry_t *self, intn maxentries,
char *names[], H5G_entry_t entries[])
{
- H5G_node_list_t udata;
+ H5G_bt_ud2_t udata;
H5O_stab_t stab;
intn i;
@@ -1103,6 +1103,7 @@ H5G_stab_list (hdf5_file_t *f, H5G_entry_t *self, intn maxentries,
}
udata.entry = entries;
udata.name = names;
+ udata.dir_addr = self->header;
udata.heap_addr = stab.heap_addr;
udata.maxentries = maxentries;
udata.nsyms = 0;
@@ -1388,6 +1389,13 @@ H5G_debug (hdf5_file_t *f, H5G_entry_t *ent, FILE *stream, intn indent,
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:");
diff --git a/src/H5Gnode.c b/src/H5Gnode.c
index b344713..0729a78 100644
--- a/src/H5Gnode.c
+++ b/src/H5Gnode.c
@@ -18,22 +18,26 @@
* Robb Matzke, 5 Aug 1997
* Added calls to H5E.
*
+ * Robb Matzke, 18 Sep 1997
+ * Added shadow entries.
+ *
*-------------------------------------------------------------------------
*/
+#define H5G_PACKAGE /*suppress error message about including H5Gpkg.h*/
/* Packages needed by this file... */
#include <H5private.h> /*library */
#include <H5ACprivate.h> /*cache */
#include <H5Bprivate.h> /*B-link trees */
#include <H5Eprivate.h> /*error handling */
-#include <H5Gprivate.h> /*me */
+#include <H5Gpkg.h> /*me */
#include <H5Hprivate.h> /*heap */
#include <H5MFprivate.h> /*file memory management */
#include <H5MMprivate.h> /*core memory management */
+#include <H5Oprivate.h> /*header messages */
#define PABLO_MASK H5G_node_mask
-
/* PRIVATE PROTOTYPES */
static herr_t H5G_node_decode_key (hdf5_file_t *f, uint8 *raw, void *_key);
static herr_t H5G_node_encode_key (hdf5_file_t *f, uint8 *raw, void *_key);
@@ -42,8 +46,7 @@ static haddr_t H5G_node_new (hdf5_file_t *f, void *_lt_key, void *_udata,
void *_rt_key);
static herr_t H5G_node_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr,
H5G_node_t *sym);
-static H5G_node_t *H5G_node_load (hdf5_file_t *f, haddr_t addr,
- const void *_data);
+static H5G_node_t *H5G_node_load (hdf5_file_t *f, haddr_t addr, void *_data);
static intn H5G_node_cmp (hdf5_file_t *f, void *_lt_key, void *_udata,
void *_rt_key);
static herr_t H5G_node_found (hdf5_file_t *f, haddr_t addr,
@@ -58,12 +61,12 @@ 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] = {{
- (void*(*)(hdf5_file_t*,haddr_t,const void*))H5G_node_load,
+ (void*(*)(hdf5_file_t*,haddr_t,void*))H5G_node_load,
(herr_t(*)(hdf5_file_t*,hbool_t,haddr_t,void*))H5G_node_flush,
}};
/* H5G inherits B-tree like properties from H5B */
-const H5B_class_t H5B_SNODE[1] = {{
+H5B_class_t H5B_SNODE[1] = {{
H5B_SNODE_ID, /*id */
sizeof (H5G_node_key_t), /*sizeof_nkey */
H5G_node_sizeof_rkey, /*get_sizeof_rkey */
@@ -265,7 +268,10 @@ H5G_node_new (hdf5_file_t *f, void *_lt_key, void *_udata, void *_rt_key)
/*-------------------------------------------------------------------------
* Function: H5G_node_flush
*
- * Purpose: Flush a symbol table node to disk.
+ * Purpose: Flush a symbol table node to disk. If any entries have dirty
+ * shadows, the shadow value is copied into the entry before the
+ * entry is flushed. The association between shadows and
+ * entries is broken.
*
* Return: Success: SUCCEED
*
@@ -285,6 +291,7 @@ H5G_node_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5G_node_t *sym)
uint8 *buf=NULL, *p=NULL;
size_t size;
herr_t status;
+ int i;
FUNC_ENTER (H5G_node_flush, NULL, FAIL);
@@ -295,6 +302,19 @@ H5G_node_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5G_node_t *sym)
assert (addr>=0);
assert (sym);
+ /*
+ * Synchronize all entries with their corresponding shadow if they have
+ * one.
+ */
+ for (i=0; i<sym->nsyms; i++) {
+ if (H5G_shadow_sync (sym->entry+i)<0) {
+ HRETURN_ERROR (H5E_SYM, H5E_CANTFLUSH, FAIL);
+ }
+ }
+
+ /*
+ * Write the symbol node to disk.
+ */
if (sym->dirty) {
size = H5G_node_size (f);
buf = p = H5MM_xmalloc (size);
@@ -321,7 +341,15 @@ H5G_node_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5G_node_t *sym)
if (status<0) HRETURN_ERROR (H5E_SYM, H5E_WRITEERROR, FAIL);
}
+ /*
+ * Destroy the symbol node? This might happen if the node is being
+ * preempted from the cache. We should also dissociate the shadow
+ * from the entry.
+ */
if (destroy) {
+ for (i=0; i<sym->nsyms; i++) {
+ H5G_shadow_dissociate (sym->entry+i);
+ }
sym->entry = H5MM_xfree (sym->entry);
H5MM_xfree (sym);
}
@@ -333,7 +361,8 @@ H5G_node_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5G_node_t *sym)
/*-------------------------------------------------------------------------
* Function: H5G_node_load
*
- * Purpose: Loads a symbol table from the file.
+ * Purpose: Loads a symbol table from the file and associates shadows
+ * with their entries.
*
* Return: Success: Ptr to the new table.
*
@@ -348,11 +377,13 @@ H5G_node_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5G_node_t *sym)
*-------------------------------------------------------------------------
*/
static H5G_node_t *
-H5G_node_load (hdf5_file_t *f, haddr_t addr, const void *_udata)
+H5G_node_load (hdf5_file_t *f, haddr_t addr, void *_udata)
{
H5G_node_t *sym = NULL;
size_t size = 0;
uint8 *buf = NULL, *p = NULL;
+ H5G_entry_t *self = NULL;
+ H5G_node_t *ret_value = NULL; /*for error handling*/
FUNC_ENTER (H5G_node_load, NULL, NULL);
@@ -361,7 +392,8 @@ H5G_node_load (hdf5_file_t *f, haddr_t addr, const void *_udata)
*/
assert (f);
assert (addr>=0);
- assert (NULL==_udata);
+ assert (_udata);
+ self = (H5G_entry_t*)_udata;
/*
* Initialize variables.
@@ -372,17 +404,19 @@ H5G_node_load (hdf5_file_t *f, haddr_t addr, const void *_udata)
sym->entry = H5MM_xcalloc (2*H5G_NODE_K(f), sizeof(H5G_entry_t));
if (H5F_block_read (f, addr, size, buf)<0) {
- H5MM_xfree (sym->entry);
- H5MM_xfree (sym);
- HRETURN_ERROR (H5E_SYM, H5E_READERROR, NULL);
+ HGOTO_ERROR (H5E_SYM, H5E_READERROR, NULL);
}
/* magic */
- if (HDmemcmp (p, H5G_NODE_MAGIC, H5G_NODE_SIZEOF_MAGIC)) goto error;
+ if (HDmemcmp (p, H5G_NODE_MAGIC, H5G_NODE_SIZEOF_MAGIC)) {
+ HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, NULL);
+ }
p += 4;
/* version */
- if (H5G_NODE_VERS!=*p++) goto error;
+ if (H5G_NODE_VERS!=*p++) {
+ HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, NULL);
+ }
/* reserved */
p++;
@@ -391,15 +425,28 @@ H5G_node_load (hdf5_file_t *f, haddr_t addr, const void *_udata)
UINT16DECODE (p, sym->nsyms);
/* entries */
- if (H5G_decode_vec (f, &p, sym->entry, sym->nsyms)<0) goto error;
+ if (H5G_decode_vec (f, &p, sym->entry, sym->nsyms)<0) {
+ HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, NULL);
+ }
+ buf = H5MM_xfree (buf);
- H5MM_xfree (buf);
- FUNC_LEAVE (sym);
+ /* shadows */
+ if (H5G_shadow_assoc_node (f, sym, self)<0) {
+ HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, NULL);
+ }
+
+ ret_value = sym;
+
-error:
- H5MM_xfree (buf);
- H5MM_xfree (sym);
- HRETURN_ERROR (H5E_SYM, H5E_CANTLOAD, NULL);
+ done:
+ if (!ret_value) {
+ buf = H5MM_xfree (buf);
+ if (sym) {
+ sym->entry = H5MM_xfree (sym->entry);
+ sym = H5MM_xfree (sym);
+ }
+ }
+ FUNC_LEAVE (ret_value);
}
@@ -433,7 +480,7 @@ error:
static intn
H5G_node_cmp (hdf5_file_t *f, void *_lt_key, void *_udata, void *_rt_key)
{
- H5G_node_ud1_t *udata = (H5G_node_ud1_t *)_udata;
+ H5G_bt_ud1_t *udata = (H5G_bt_ud1_t *)_udata;
H5G_node_key_t *lt_key = (H5G_node_key_t *)_lt_key;
H5G_node_key_t *rt_key = (H5G_node_key_t *)_rt_key;
const char *s;
@@ -488,7 +535,8 @@ static herr_t
H5G_node_found (hdf5_file_t *f, haddr_t addr, const void *_lt_key,
void *_udata, const void *_rt_key)
{
- H5G_node_ud1_t *udata = (H5G_node_ud1_t *)_udata;
+ H5G_bt_ud1_t *bt_udata = (H5G_bt_ud1_t *)_udata;
+ H5G_ac_ud1_t ac_udata;
H5G_node_t *sn = NULL;
intn lt=0, idx=0, rt, cmp=1;
const char *s;
@@ -501,12 +549,15 @@ H5G_node_found (hdf5_file_t *f, haddr_t addr, const void *_lt_key,
*/
assert (f);
assert (addr>=0);
- assert (udata);
+ assert (bt_udata);
+
+ ac_udata.dir_addr = bt_udata->dir_addr;
+ ac_udata.heap_addr = bt_udata->heap_addr;
/*
* Load the symbol table node for exclusive access.
*/
- if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, NULL))) {
+ if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, &ac_udata))) {
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL);
}
@@ -516,10 +567,11 @@ H5G_node_found (hdf5_file_t *f, haddr_t addr, const void *_lt_key,
rt = sn->nsyms;
while (lt<rt && cmp) {
idx = (lt + rt) / 2;
- if (NULL==(s=H5H_peek (f, udata->heap_addr, sn->entry[idx].name_off))) {
+ if (NULL==(s=H5H_peek (f, bt_udata->heap_addr,
+ sn->entry[idx].name_off))) {
HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL);
}
- cmp = HDstrcmp (udata->name, s);
+ cmp = HDstrcmp (bt_udata->name, s);
if (cmp<0) {
rt = idx;
@@ -529,20 +581,18 @@ H5G_node_found (hdf5_file_t *f, haddr_t addr, const void *_lt_key,
}
if (cmp) HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL);
- switch (udata->operation) {
+ switch (bt_udata->operation) {
case H5G_OPER_FIND:
/*
- * The caller is querying the symbol entry.
+ * The caller is querying the symbol entry. Return just a pointer to
+ * the entry. The pointer is valid until the next call to H5AC.
*/
- udata->entry = sn->entry[idx];
+ H5G_shadow_sync (sn->entry+idx);
+ bt_udata->entry_ptr = sn->entry+idx;
break;
- case H5G_OPER_MODIFY:
- /*
- * The caller is modifying the symbol entry.
- */
- sn->entry[idx] = udata->entry;
- sn->dirty += 1;
+ default:
+ HRETURN_ERROR (H5E_SYM, H5E_UNSUPPORTED, FAIL);
break;
}
ret_value = SUCCEED;
@@ -589,6 +639,10 @@ done:
*
* Modifications:
*
+ * Robb Matzke, 18 Sep 1997
+ * If the shadow pointer is non-null then the shadow is updated to point
+ * to the new entry.
+ *
*-------------------------------------------------------------------------
*/
static haddr_t
@@ -599,14 +653,17 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor,
{
H5G_node_key_t *md_key = (H5G_node_key_t *)_md_key;
H5G_node_key_t *rt_key = (H5G_node_key_t *)_rt_key;
- H5G_node_ud1_t *udata = (H5G_node_ud1_t *)_udata;
-
+ H5G_bt_ud1_t *bt_udata = (H5G_bt_ud1_t *)_udata;
+
+ H5G_ac_ud1_t ac_udata;
H5G_node_t *sn=NULL, *snrt=NULL;
haddr_t new_node=0, offset;
const char *s;
intn idx=-1, cmp=1;
intn lt=0, rt; /*binary search cntrs */
+ intn i;
haddr_t ret_value = FAIL;
+ H5G_shadow_t *shadow = NULL;
FUNC_ENTER (H5G_node_insert, NULL, FAIL);
@@ -618,7 +675,8 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor,
assert (anchor);
assert (md_key);
assert (rt_key);
- assert (udata);
+ assert (bt_udata);
+ bt_udata->entry_ptr = NULL;
/*
* Symbol tables are always split so the new symbol table node is
@@ -631,7 +689,9 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor,
/*
* Load the symbol node.
*/
- if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, NULL))) {
+ ac_udata.dir_addr = bt_udata->dir_addr;
+ ac_udata.heap_addr = bt_udata->heap_addr;
+ if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, &ac_udata))) {
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL);
}
@@ -641,10 +701,11 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor,
rt = sn->nsyms;
while (lt<rt) {
idx = (lt + rt) / 2;
- if (NULL==(s=H5H_peek (f, udata->heap_addr, sn->entry[idx].name_off))) {
+ if (NULL==(s=H5H_peek (f, bt_udata->heap_addr,
+ sn->entry[idx].name_off))) {
HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL);
}
- if (0==(cmp=HDstrcmp (udata->name, s))) {
+ if (0==(cmp=HDstrcmp (bt_udata->name, s))) {
HGOTO_ERROR (H5E_SYM, H5E_CANTINSERT, FAIL); /*already present*/
}
if (cmp<0) {
@@ -660,9 +721,9 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor,
* heap address changed and update the symbol table object header
* with the new heap address.
*/
- offset = H5H_insert (f, udata->heap_addr, HDstrlen(udata->name)+1,
- udata->name);
- udata->entry.name_off = offset;
+ offset = H5H_insert (f, bt_udata->heap_addr, HDstrlen(bt_udata->name)+1,
+ bt_udata->name);
+ bt_udata->entry.name_off = offset;
if (offset<0) HGOTO_ERROR (H5E_SYM, H5E_CANTINSERT, FAIL);
if (sn->nsyms>=2*H5G_NODE_K(f)) {
@@ -676,7 +737,7 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor,
if ((new_node = H5G_node_new (f, NULL, NULL, NULL))<0) {
HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL);
}
- if (NULL==(snrt=H5AC_find (f, H5AC_SNODE, new_node, NULL))) {
+ if (NULL==(snrt=H5AC_find (f, H5AC_SNODE, new_node, &ac_udata))) {
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL);
}
HDmemcpy (snrt->entry, sn->entry + H5G_NODE_K(f),
@@ -684,6 +745,13 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor,
snrt->nsyms = H5G_NODE_K(f);
snrt->dirty += 1;
+ /* Right shadows */
+ for (i=0; i<H5G_NODE_K(f); i++) {
+ if ((shadow = snrt->entry[i].shadow)) {
+ shadow->main = snrt->entry + i;
+ }
+ }
+
/* The left node */
HDmemset (sn->entry + H5G_NODE_K(f), 0,
H5G_NODE_K(f) * sizeof(H5G_entry_t));
@@ -692,19 +760,46 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor,
/* 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;
+ }
+
+ /* Move entries */
HDmemmove (sn->entry + idx + 1,
sn->entry + idx,
(H5G_NODE_K(f)-idx) * sizeof(H5G_entry_t));
- sn->entry[idx] = udata->entry;
+ sn->entry[idx] = bt_udata->entry;
sn->entry[idx].name_off = offset;
+ sn->entry[idx].dirty = TRUE;
sn->nsyms += 1;
+
} 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] = udata->entry;
+ 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) {
@@ -721,12 +816,21 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor,
* Add the new symbol to the node.
*/
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] = udata->entry;
+ sn->entry[idx] = bt_udata->entry;
sn->entry[idx].name_off = offset;
-
+ sn->entry[idx].dirty = TRUE;
+
if (idx+1==sn->nsyms) {
rt_key->offset = offset;
*rt_key_changed = TRUE;
@@ -765,12 +869,13 @@ done:
static herr_t
H5G_node_list (hdf5_file_t *f, haddr_t addr, void *_udata)
{
- H5G_node_list_t *udata = (H5G_node_list_t *)_udata;
+ H5G_bt_ud2_t *bt_udata = (H5G_bt_ud2_t *)_udata;
H5G_node_t *sn = NULL;
intn i;
const char *s;
herr_t ret_value = FAIL;
-
+ H5G_ac_ud1_t ac_udata;
+
FUNC_ENTER (H5G_node_list, NULL, FAIL);
/*
@@ -778,9 +883,11 @@ H5G_node_list (hdf5_file_t *f, haddr_t addr, void *_udata)
*/
assert (f);
assert (addr>=0);
- assert (udata);
+ assert (bt_udata);
- if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, NULL))) {
+ ac_udata.dir_addr = bt_udata->dir_addr;
+ ac_udata.heap_addr = bt_udata->heap_addr;
+ if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, &ac_udata))) {
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL);
}
@@ -789,32 +896,34 @@ H5G_node_list (hdf5_file_t *f, haddr_t addr, void *_udata)
* keep track of how many names we've seen and don't bother doing
* anything else.
*/
- if (udata->nsyms >= udata->maxentries) {
- udata->nsyms += sn->nsyms;
+ if (bt_udata->nsyms >= bt_udata->maxentries) {
+ bt_udata->nsyms += sn->nsyms;
HGOTO_DONE (SUCCEED);
}
/*
* Save the symbol table entries.
*/
- if (udata->entry) {
- for (i=0; i<sn->nsyms && udata->nsyms+i<udata->maxentries; i++) {
- udata->entry[udata->nsyms+i] = sn->entry[i];
+ if (bt_udata->entry) {
+ for (i=0; i<sn->nsyms && bt_udata->nsyms+i<bt_udata->maxentries; i++) {
+ H5G_shadow_sync (sn->entry+i);
+ bt_udata->entry[bt_udata->nsyms+i] = sn->entry[i];
}
}
- if (udata->name) {
- for (i=0; i<sn->nsyms && udata->nsyms+i<udata->maxentries; i++) {
- if (NULL==(s=H5H_peek (f, udata->heap_addr, sn->entry[i].name_off))) {
+ if (bt_udata->name) {
+ for (i=0; i<sn->nsyms && bt_udata->nsyms+i<bt_udata->maxentries; i++) {
+ if (NULL==(s=H5H_peek (f, bt_udata->heap_addr,
+ sn->entry[i].name_off))) {
HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL);
}
- udata->name[udata->nsyms+i] = H5MM_xstrdup (s);
+ bt_udata->name[bt_udata->nsyms+i] = H5MM_xstrdup (s);
}
}
/*
* Update the number of symbols.
*/
- udata->nsyms += sn->nsyms;
+ bt_udata->nsyms += sn->nsyms;
ret_value = SUCCEED;
done:
@@ -847,10 +956,11 @@ herr_t
H5G_node_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent,
intn fwidth, haddr_t heap)
{
- int i;
+ int i, acc;
H5G_node_t *sn = NULL;
herr_t status;
const char *s;
+ H5G_ac_ud1_t ac_udata;
FUNC_ENTER (H5G_node_debug, NULL, FAIL);
@@ -864,6 +974,18 @@ H5G_node_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent,
assert (fwidth>=0);
/*
+ * We have absolutely no idea where the object header for the symbol table
+ * to which this node belongs is located. In fact, if the file is corrupt,
+ * there may not even be an object header for that symbol table. So we
+ * supply `-1' as the directory address which causes no open objects to be
+ * associated with the node. For that reason, we flush this node from the
+ * cache when we're done so if some later caller knows the header address
+ * they'll be able to access the open objects.
+ */
+ ac_udata.dir_addr = -1;
+ ac_udata.heap_addr = heap;
+
+ /*
* If we couldn't load the symbol table node, then try loading the
* B-tree node.
*/
@@ -882,6 +1004,12 @@ H5G_node_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent,
fprintf (stream, "%*s%-*s %d of %d\n", indent, "", fwidth,
"Number of Symbols:",
sn->nsyms, 2*H5G_NODE_K(f));
+ for (i=acc=0; i<sn->nsyms; i++) {
+ if (sn->entry[i].shadow) acc++;
+ }
+ fprintf (stream, "%*s%-*s %d\n", indent, "", fwidth,
+ "Shadows:", acc);
+
indent += 3;
fwidth = MAX (0, fwidth-3);
@@ -893,8 +1021,12 @@ H5G_node_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent,
s);
}
H5G_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");
}
+ H5AC_flush (f, H5AC_SNODE, addr, TRUE); /*see note above*/
FUNC_LEAVE (SUCCEED);
}
diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h
new file mode 100644
index 0000000..5a33d8d
--- /dev/null
+++ b/src/H5Gpkg.h
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 1997 National Center for Supercomputing Applications.
+ * All rights reserved.
+ *
+ * Programmer: Robb Matzke <matzke@llnl.gov>
+ * Thursday, September 18, 1997
+ *
+ * Purpose: This file contains declarations which are visible
+ * only within the H5G package. Source files outside the
+ * H5G package should include H5Gprivate.h instead.
+ */
+#ifndef H5G_PACKAGE
+#error "Do not include this file outside the H5G package!"
+#endif
+
+#ifndef _H5Gpkg_H
+#define _H5Gpkg_H
+
+#include <H5Gprivate.h>
+
+#define H5G_NODE_VERS 1 /*symbol table node version number */
+#define H5G_SIZE_HINT 1024 /*default root dir size hint */
+#define H5G_NODE_K(F) ((F)->file_create_parms.sym_leaf_k)
+#define H5G_NODE_SIZEOF_HDR(F) (H5G_NODE_SIZEOF_MAGIC + 4)
+#define H5G_DEFAULT_ROOT_SIZE 32
+
+
+/*
+ * A shadow is a copy of a symbol table entry which corresponds to an
+ * `open' object. Shadows are necessary because normal symbol table
+ * entries can be preempted from the main cache. The `shadow' field
+ * of the `entry' points to the beginning of the shadow just like the
+ * shadow field from symbol table entries in H5G_node_t.
+ */
+struct H5G_shadow_t {
+ char *name; /*name for this entry */
+ haddr_t dir_addr; /*hdr addr for dir containing shadow */
+ uintn nrefs; /*reference counter */
+ H5G_entry_t entry; /*local copy of symbol table entry */
+ H5G_entry_t *main; /*main entry in stab node if cached */
+ struct H5G_shadow_t *next; /*next shadow for same symbol table */
+ struct H5G_shadow_t *prev; /*previous shadow for same symbol table */
+};
+
+/*
+ * A symbol table node is a collection of symbol table entries. It can
+ * be thought of as the lowest level of the B-link tree that points to
+ * a collection of symbol table entries that belong to a specific symbol
+ * table or directory.
+ */
+typedef struct H5G_node_t {
+ int dirty; /*has cache been modified? */
+ int nsyms; /*number of symbols */
+ H5G_entry_t *entry; /*array of symbol table entries */
+} H5G_node_t;
+
+/*
+ * Each key field of the B-link tree that points to symbol table
+ * nodes consists of this structure...
+ */
+typedef struct H5G_node_key_t {
+ off_t offset; /*offset into heap for name */
+} H5G_node_key_t;
+
+/*
+ * These operations can be passed down from the H5G_stab layer to the
+ * H5G_node layer through the B-tree layer.
+ */
+typedef enum H5G_oper_t {
+ H5G_OPER_FIND =0, /*find a symbol */
+ H5G_OPER_INSERT =1, /*insert a new symbol */
+} H5G_oper_t;
+
+/*
+ * Data exchange structure for symbol table nodes. This structure is
+ * passed through the B-link tree layer to the methods for the objects
+ * to which the B-link tree points.
+ */
+typedef struct H5G_bt_ud1_t {
+
+ /* downward */
+ H5G_oper_t operation; /*what operation to perform */
+ const char *name; /*points to temporary memory */
+ haddr_t dir_addr; /*symbol table header address */
+ haddr_t heap_addr; /*symbol table heap address */
+
+ /* downward for INSERT */
+ H5G_entry_t entry; /*entry to insert into table */
+
+ /* upward for FIND */
+ H5G_entry_t *entry_ptr; /*ptr into cached symbol table node */
+
+} H5G_bt_ud1_t;
+
+/*
+ * Data exchange structure to pass through the B-tree layer for the
+ * H5B_list function.
+ */
+typedef struct H5G_bt_ud2_t {
+
+ /* downward */
+ H5G_entry_t *entry; /*array of entries, alloc'd by caller */
+ char **name; /*array of string ptrs, allocd by caller*/
+ intn maxentries; /*size of the ADDR and NAME arrays */
+ haddr_t dir_addr; /*symbol table header address */
+ haddr_t heap_addr; /*heap address */
+
+ /* upward */
+ intn nsyms; /*num. symbols processed */
+
+} H5G_bt_ud2_t;
+
+/*
+ * This is the class identifier to give to the B-tree functions.
+ */
+extern H5B_class_t H5B_SNODE[1];
+
+/*
+ * This struct passes information through the H5AC layer.
+ */
+typedef struct H5G_ac_ud1_t {
+ haddr_t heap_addr;
+ haddr_t dir_addr;
+} H5G_ac_ud1_t;
+
+/*
+ * Functions that understand symbol tables but not directories. The
+ * functions that understand directories are exported to the rest of
+ * the library and appear in H5Gprivate.h.
+ */
+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);
+intn H5G_stab_list (hdf5_file_t *f, H5G_entry_t *self, intn maxentries,
+ char *names[], H5G_entry_t entries[]);
+
+/*
+ * Functions that understand shadow entries.
+ */
+herr_t H5G_shadow_sync (H5G_entry_t *ent);
+H5G_entry_t *H5G_shadow_open (hdf5_file_t *f, H5G_entry_t *dir,
+ H5G_entry_t *ent);
+herr_t H5G_shadow_close (hdf5_file_t *f, H5G_entry_t *ent);
+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_entry_t *self);
+H5G_shadow_t *H5G_shadow_list (haddr_t stab_header_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);
+
+#endif
diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h
index e6f5df4..dd26902 100644
--- a/src/H5Gprivate.h
+++ b/src/H5Gprivate.h
@@ -8,7 +8,7 @@
* Jul 11 1997
* Robb Matzke <matzke@llnl.gov>
*
- * Purpose: Private stuff for the H5G package (symbol tables).
+ * Purpose: Library-visible declarations.
*
* Modifications:
*
@@ -25,18 +25,17 @@
#define H5G_NODE_MAGIC "SNOD" /*symbol table node magic number */
#define H5G_NODE_SIZEOF_MAGIC 4 /*sizeof symbol node magic number */
-#define H5G_NODE_VERS 1 /*symbol table node version number */
-#define H5G_SIZE_HINT 1024 /*default root dir size hint */
-#define H5G_NODE_K(F) ((F)->file_create_parms.sym_leaf_k)
-#define H5G_NODE_SIZEOF_HDR(F) (H5G_NODE_SIZEOF_MAGIC + 4)
+#define H5G_new_entry() H5MM_xcalloc (1, sizeof(H5G_entry_t))
+
+/*
+ * The disk size for a symbol table entry...
+ */
#define H5G_SIZEOF_ENTRY(F) \
(H5F_SIZEOF_OFFSET(F) + /*offset of name into heap */ \
H5F_SIZEOF_OFFSET(F) + /*address of object header */ \
4 + /*entry type */ \
24) /*scratch pad space */
-#define H5G_DEFAULT_ROOT_SIZE 32
-
/*
* Various types of object header information can be cached in a symbol
* table entry (it's normal home is the object header to which the entry
@@ -44,134 +43,73 @@
* symbol table entry.
*/
typedef enum H5G_type_t {
- H5G_NOTHING_CACHED =0, /*nothing is cached */
+ H5G_NOTHING_CACHED =0, /*nothing is cached, must be 0 */
H5G_CACHED_SDATA =1, /*simple dataset, `sdata' */
H5G_CACHED_STAB =2 /*symbol table, `stab' */
} H5G_type_t;
/*
+ * A symbol table entry caches these parameters from object header
+ * messages...
+ */
+typedef union H5G_cache_t {
+ struct {
+ struct {
+ uint8 length;
+ uint8 arch;
+ uint16 type;
+ } nt ; /*number type */
+ uint32 ndim; /*number of dimensions */
+ uint32 dim[4]; /*dimension sizes */
+ } sdata;
+
+ struct {
+ haddr_t btree_addr; /*file address of symbol table B-tree */
+ haddr_t heap_addr; /*file address of stab name heap */
+ } stab;
+} H5G_cache_t;
+
+/*
+ * An H5G_shadow_t is the struct used to describe object headers that
+ * are currently open for modification. It's contents is not
+ * important outside H5G.
+ */
+typedef struct H5G_shadow_t H5G_shadow_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.
*/
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 */
-
- union {
- struct {
- struct {
- uint8 length;
- uint8 arch;
- uint16 type;
- } nt ; /*number type */
- uint32 ndim; /*number of dimensions */
- uint32 dim[4]; /*dimension sizes */
- } sdata;
-
- struct {
- haddr_t btree_addr; /*file address of symbol table B-tree */
- haddr_t heap_addr; /*file address of stab name heap */
- } stab;
- } cache; /*cached data from object header */
+ H5G_cache_t cache; /*cached data from object header */
+ H5G_shadow_t *shadow; /*optional ptr to the shadow */
} H5G_entry_t;
/*
- * A symbol table node is a collection of symbol table entries. It can
- * be thought of as the lowest level of the B-link tree that points to
- * a collection of symbol table entries that belong to a specific symbol
- * table or directory.
- */
-typedef struct H5G_node_t {
- int dirty; /*has cache been modified? */
- int nsyms; /*number of symbols */
- H5G_entry_t *entry; /*symbol table entries */
-} H5G_node_t;
-
-/*
- * Each key field of the B-link tree that points to symbol table
- * nodes consists of this structure...
- */
-typedef struct H5G_node_key_t {
- off_t offset; /*offset into heap for name */
-} H5G_node_key_t;
-
-typedef enum H5G_oper_t {
- H5G_OPER_FIND =0, /*find a symbol */
- H5G_OPER_MODIFY =1 /*modify a symbol */
-} H5G_oper_t;
-
-/*
- * Data exchange structure for symbol table nodes. This structure is
- * passed through the B-link tree layer to the methods for the objects
- * to which the B-link tree points.
- */
-typedef struct H5G_node_ud1_t {
-
- /* downward */
- H5G_oper_t operation; /*what operation to perform */
- const char *name; /*points to temporary memory */
- haddr_t heap_addr; /*symbol table heap address */
-
- /* upward for H5G_OPER_FIND, downward for H5G_OPER_MODIFY */
- H5G_entry_t entry; /*symbol table entry */
-
-} H5G_node_ud1_t;
-
-typedef struct H5G_node_list_t {
-
- /* downward */
- H5G_entry_t *entry; /*array of entries, alloc'd by caller */
- char **name; /*array of string ptrs, allocd by caller*/
- intn maxentries; /*size of the ADDR and NAME arrays */
- haddr_t heap_addr; /*heap address */
-
- /* upward */
- intn nsyms; /*num. symbols processed */
-
-} H5G_node_list_t;
-
-extern const H5B_class_t H5B_SNODE[1];
-
-/*
* Library prototypes...
*/
-
-/* functions that understand directories */
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);
+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_modify (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);
-
-/* functions that understand symbol tables */
-haddr_t H5G_stab_new (hdf5_file_t *f, H5G_entry_t *self, size_t init);
-haddr_t H5G_stab_find (hdf5_file_t *f, H5G_entry_t *self, const char *name,
- H5G_entry_t *ent);
-herr_t H5G_stab_modify (hdf5_file_t *f, H5G_entry_t *self, const char *name,
- H5G_entry_t *ent);
-herr_t H5G_stab_insert (hdf5_file_t *f, H5G_entry_t *self, const char *name,
- H5G_entry_t *ent);
-intn H5G_stab_list (hdf5_file_t *f, H5G_entry_t *self, intn maxentries,
- char *names[], H5G_entry_t entries[]);
-
-/* functions that understand symbol table nodes */
-herr_t H5G_node_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent,
- intn fwidth, haddr_t heap);
-
-/* functions that understand symbol table entries */
-herr_t H5G_decode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent);
-herr_t H5G_decode_vec (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent, intn n);
herr_t H5G_encode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent);
-herr_t H5G_encode_vec (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent, intn n);
+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_node_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent,
+ intn fwidth, haddr_t heap);
+
#endif
diff --git a/src/H5Gshad.c b/src/H5Gshad.c
new file mode 100644
index 0000000..5de4b29
--- /dev/null
+++ b/src/H5Gshad.c
@@ -0,0 +1,460 @@
+/*
+ * Copyright (C) 1997 National Center for Supercomputing Applications.
+ * All rights reserved.
+ *
+ * Programmer: Robb Matzke <matzke@llnl.gov>
+ * Thursday, September 18, 1997
+ */
+#define H5G_PACKAGE /*suppress error message about including H5Gpkg.h*/
+
+#include <H5private.h> /*library */
+#include <H5Eprivate.h> /*error handling */
+#include <H5Gpkg.h> /*symbol tables */
+#include <H5Hprivate.h> /*heap functions */
+#include <H5MMprivate.h> /*memory management */
+#include <H5Oprivate.h> /*object header messages */
+
+#define PABLO_MASK H5G_shadow_mask
+
+/* 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;
+ struct H5G_hash_t *next;
+ struct H5G_hash_t *prev;
+} H5G_hash_t;
+
+static H5G_hash_t *H5G_shadow_g[H5G_NSHADOWS];
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_shadow_p
+ *
+ * Purpose: Determines if ENT is a shadow or a real symbol table entry.
+ *
+ * Return: Success: Non-zero if ENT is a shadow; zero otherwise.
+ *
+ * Failure: FALSE
+ *
+ * Programmer: Robb Matzke
+ * Thursday, September 18, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+hbool_t
+H5G_shadow_p (H5G_entry_t *ent)
+{
+ H5G_shadow_t tmp;
+ size_t delta = (char*)&(tmp.entry) - (char*)&tmp;
+ hbool_t ret_value = FALSE;
+
+ FUNC_ENTER (H5G_shadow_p, NULL, FALSE);
+
+ if (!ent || !ent->shadow) return FALSE;
+ ret_value = ((char*)ent - (char*)(ent->shadow) == delta);
+
+ FUNC_LEAVE (ret_value);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_shadow_dissociate
+ *
+ * Purpose: Removes the association between a shadow and its entry or an
+ * entry and its shadow. The ENT argument can be a shadow or a
+ * cached entry.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Thursday, September 18, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_shadow_dissociate (H5G_entry_t *ent)
+{
+ FUNC_ENTER (H5G_shadow_dissociate, NULL, FAIL);
+
+ if (H5G_shadow_p (ent)) {
+ if (ent->shadow->main) {
+ ent->shadow->main->shadow = NULL;
+ ent->shadow->main = NULL;
+ }
+ } else if (ent && ent->shadow) {
+ ent->shadow->main = NULL;
+ ent->shadow = NULL;
+ }
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_shadow_sync
+ *
+ * Purpose: Synchronizes a shadow with an entry by copying the
+ * shadow contents to the entry if the shadow is dirty,
+ * and then clearing the shadow dirty bit. You may call this
+ * function with either a shadow or a real entry.
+ *
+ * If ENT is a shadow, then the shadow is synchronized only if
+ * the entry is currently cached.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Thursday, September 18, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_shadow_sync (H5G_entry_t *ent)
+{
+ H5G_shadow_t *shadow = NULL;
+ FUNC_ENTER (H5G_shadow_sync, NULL, FAIL);
+
+ /*
+ * If the caller supplied us with a shadow instead of the main entry, then
+ * adjust the arguments.
+ */
+ if (H5G_shadow_p (ent)) {
+ shadow = ent->shadow;
+ ent = shadow->main;
+ } else {
+ shadow = ent->shadow;
+ }
+
+ if (shadow && shadow->entry.dirty) {
+ if (!ent) {
+ /* Main entry is not cached */
+ HRETURN_ERROR (H5E_SYM, H5E_NOTCACHED, FAIL);
+ }
+ *ent = shadow->entry;
+ shadow->entry.dirty = FALSE;
+ }
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_shadow_list
+ *
+ * Purpose: Returns a doubly linked list of shadows for the symbol
+ * table whose header address is DIR_ADDR.
+ *
+ * Return: Success: Ptr shadow list or null.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, September 17, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+H5G_shadow_t *
+H5G_shadow_list (haddr_t dir_addr)
+{
+ uintn idx = dir_addr % H5G_NSHADOWS;
+ H5G_hash_t *bucket = NULL;
+
+ FUNC_ENTER (H5G_shadows, NULL, NULL);
+
+ for (bucket=H5G_shadow_g[idx]; bucket; bucket=bucket->next) {
+ if (bucket->dir_addr==dir_addr) {
+ HRETURN (bucket->head);
+ }
+ }
+ FUNC_LEAVE (NULL);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_shadow_assoc_node
+ *
+ * Purpose: Given a new symbol table node and a symbol table header
+ * address, associate entries in that node with their shadow if
+ * they have one.
+ *
+ * SYM must be an uncached or protected symbol table node.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL, if an error occurs then none of the
+ * entries are associated with shadows.
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, September 17, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_shadow_assoc_node (hdf5_file_t *f, H5G_node_t *sym, H5G_entry_t *self)
+{
+ H5G_shadow_t *shadow = NULL;
+ H5O_stab_t stab;
+ const char *s = NULL;
+ intn i = 0;
+
+ FUNC_ENTER (H5G_shadow_assoc_node, NULL, FAIL);
+
+ /* Check arguments */
+ assert (f); /* The file */
+ assert (sym); /* The symbol table node */
+ assert (self); /* The symbol table header info */
+
+ if ((shadow=H5G_shadow_list (self->header))) {
+
+ /* We need the heap address so we can see the symbol names */
+ if (NULL==H5O_read (f, self->header, self, H5O_NAME, 0, &stab)) {
+ HRETURN_ERROR (H5E_SYM, H5E_BADMESG, FAIL);
+ }
+
+ while (i<sym->nsyms && shadow) {
+
+ /* Advance the Entry ptr until it gets to the next shadow. */
+ while (i<sym->nsyms &&
+ (s=H5H_peek (f, stab.heap_addr, sym->entry[i].name_off)) &&
+ strcmp (s, shadow->name)<0) i++;
+
+ /* Advance the Shadow ptr until it gets to the next entry. */
+ while (i<sym->nsyms && s && shadow &&
+ strcmp (s, shadow->name)>0) shadow = shadow->next;
+
+ /* Did we find a match? */
+ if (i<sym->nsyms && s && shadow && !strcmp (s, shadow->name)) {
+ shadow->main = sym->entry + i;
+ sym->entry[i].shadow = shadow;
+ }
+ }
+ }
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_shadow_open
+ *
+ * Purpose: Given a handle to an already open object, or given a
+ * pointer to the cached symbol table entry for that
+ * object, open the object (again) and return a handle
+ * to it.
+ *
+ * Return: Success: Handle to open object
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Thursday, September 18, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+H5G_entry_t *
+H5G_shadow_open (hdf5_file_t *f, H5G_entry_t *dir, H5G_entry_t *ent)
+{
+ H5G_shadow_t *shadow = NULL;
+ H5O_stab_t stab;
+ const char *s = NULL;
+ H5G_hash_t *hash = NULL;
+ H5G_shadow_t *hash_ent = NULL;
+ uintn idx;
+ H5O_name_t name_mesg = {NULL};
+ H5G_entry_t *ret_value = NULL;
+
+ FUNC_ENTER (H5G_shadow_open, NULL, NULL);
+
+ /* check args */
+ assert (f);
+ assert (dir);
+ assert (ent);
+
+ if (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");
+ }
+
+ } 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);
+ }
+
+ /*
+ * Build the new shadow.
+ */
+ ent->shadow = shadow;
+ shadow->main = ent;
+ shadow->nrefs = 1;
+ shadow->entry = *ent;
+ shadow->entry.dirty = FALSE;
+ shadow->dir_addr = dir->header;
+
+ /*
+ * Link it into the shadow heap
+ */
+ idx = dir->header % H5G_NSHADOWS;
+ for (hash=H5G_shadow_g[idx]; hash; hash=hash->next) {
+ if (hash->dir_addr==dir->header) break;
+ }
+ 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;
+ }
+ for (hash_ent=hash->head; hash_ent; hash_ent=hash_ent->next) {
+ if (strcmp (shadow->name, hash_ent->name)<0) break;
+ }
+ if (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;
+ }
+ }
+
+ ret_value = &(shadow->entry);
+
+ done:
+ if (!ret_value) {
+ if (shadow) {
+ H5MM_xfree (shadow->name);
+ H5MM_xfree (shadow);
+ }
+ }
+
+ FUNC_LEAVE (ret_value);
+}
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_shadow_close
+ *
+ * Purpose: Closes an open object.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Thursday, September 18, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_shadow_close (hdf5_file_t *f, H5G_entry_t *ent)
+{
+ uintn idx;
+ H5G_hash_t *hash=NULL;
+ H5G_shadow_t *hash_ent=NULL, *shadow=NULL;
+
+ FUNC_ENTER (H5G_shadow_close, NULL, FAIL);
+
+ /* check args */
+ assert (ent);
+ assert (H5G_shadow_p (ent));
+ assert (ent->shadow->nrefs>0);
+ shadow = ent->shadow;
+
+ /* clean the shadow */
+ if (1==shadow->nrefs && ent->dirty) {
+ 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) = *ent;
+ ent->dirty = FALSE;
+ }
+
+ /* close */
+ shadow->nrefs -= 1;
+
+ if (0==shadow->nrefs) {
+ /* dissociate shadow and entry */
+ H5G_shadow_dissociate (ent);
+
+ /* find symtabs shadow list */
+ idx = shadow->dir_addr % H5G_NSHADOWS;
+ for (hash=H5G_shadow_g[idx]; hash; hash=hash->next) {
+ if (hash->dir_addr==shadow->dir_addr) break;
+ }
+ assert (hash);
+
+ /* find shadow in shadow list */
+ for (hash_ent=hash->head; hash_ent; hash_ent=hash_ent->next) {
+ if (hash_ent==shadow) break;
+ }
+ assert (hash_ent);
+
+ /* remove shadow from shadow list */
+ if (hash_ent->prev) hash_ent->prev->next = hash_ent->next;
+ else hash->head = hash_ent->next;
+ if (hash_ent->next) hash_ent->next->prev = hash_ent->prev;
+ H5MM_xfree (shadow->name);
+ H5MM_xfree (shadow);
+
+ /* 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;
+ if (hash->next) hash->next->prev = hash->prev;
+ H5MM_xfree (hash);
+ }
+ }
+
+ FUNC_LEAVE (SUCCEED);
+}
diff --git a/src/H5H.c b/src/H5H.c
index dc0a10c..8afcea4 100644
--- a/src/H5H.c
+++ b/src/H5H.c
@@ -45,7 +45,7 @@ typedef struct H5H_t {
} H5H_t;
/* PRIVATE PROTOTYPES */
-static H5H_t *H5H_load (hdf5_file_t *f, haddr_t addr, const void *udata);
+static H5H_t *H5H_load (hdf5_file_t *f, haddr_t addr, void *udata);
static herr_t H5H_flush (hdf5_file_t *f, hbool_t dest, haddr_t addr,
H5H_t *heap);
@@ -53,7 +53,7 @@ static herr_t H5H_flush (hdf5_file_t *f, hbool_t dest, haddr_t addr,
* H5H inherits cache-like properties from H5AC
*/
static const H5AC_class_t H5AC_HEAP[1] = {{
- (void*(*)(hdf5_file_t*,haddr_t,const void*))H5H_load,
+ (void*(*)(hdf5_file_t*,haddr_t,void*))H5H_load,
(herr_t(*)(hdf5_file_t*,hbool_t,haddr_t,void*))H5H_flush,
}};
@@ -162,12 +162,13 @@ H5H_new (hdf5_file_t *f, H5H_type_t heap_type, size_t size_hint)
*-------------------------------------------------------------------------
*/
static H5H_t *
-H5H_load (hdf5_file_t *f, haddr_t addr, const void *udata)
+H5H_load (hdf5_file_t *f, haddr_t addr, void *udata)
{
uint8 hdr[20], *p;
H5H_t *heap=NULL;
H5H_free_t *fl=NULL, *tail=NULL;
haddr_t free_block=H5H_FREE_NULL;
+ H5H_t *ret_value=NULL;
FUNC_ENTER (H5H_load, NULL, NULL);
@@ -184,7 +185,9 @@ H5H_load (hdf5_file_t *f, haddr_t addr, const void *udata)
heap = H5MM_xcalloc (1, sizeof(H5H_t));
/* magic number */
- if (HDmemcmp (hdr, H5H_MAGIC, H5H_SIZEOF_MAGIC)) goto error;
+ if (HDmemcmp (hdr, H5H_MAGIC, H5H_SIZEOF_MAGIC)) {
+ HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL);
+ }
p += H5H_SIZEOF_MAGIC;
/* heap data size */
@@ -194,7 +197,7 @@ H5H_load (hdf5_file_t *f, haddr_t addr, const void *udata)
/* free list head */
H5F_decode_offset (f, p, free_block);
if (-1!=free_block && (free_block<0 || free_block>=heap->disk_alloc)) {
- goto error;
+ HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL);
}
/* data */
@@ -203,12 +206,14 @@ H5H_load (hdf5_file_t *f, haddr_t addr, const void *udata)
if (heap->disk_alloc &&
H5F_block_read (f, heap->addr, heap->disk_alloc,
heap->chunk + H5H_SIZEOF_HDR(f))<0) {
- goto error;
+ HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL);
}
/* free list */
while (H5H_FREE_NULL!=free_block) {
- if (free_block<0 || free_block>=heap->disk_alloc) goto error;
+ if (free_block<0 || free_block>=heap->disk_alloc) {
+ HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL);
+ }
fl = H5MM_xmalloc (sizeof (H5H_free_t));
fl->offset = free_block;
fl->prev = tail;
@@ -221,14 +226,15 @@ H5H_load (hdf5_file_t *f, haddr_t addr, const void *udata)
H5F_decode_offset (f, p, free_block);
H5F_decode_length (f, p, fl->size);
- if (fl->offset + fl->size > heap->disk_alloc) goto error;
+ if (fl->offset + fl->size > heap->disk_alloc) {
+ HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL);
+ }
}
- FUNC_LEAVE (heap);
+ ret_value = heap;
-
-error:
- if (heap) {
+ done:
+ if (!ret_value && heap) {
heap->chunk = H5MM_xfree (heap->chunk);
H5MM_xfree (heap);
for (fl=heap->freelist; fl; fl=tail) {
@@ -236,7 +242,8 @@ error:
H5MM_xfree (fl);
}
}
- HRETURN_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL);
+
+ FUNC_LEAVE (ret_value);
}
@@ -462,9 +469,10 @@ H5H_peek (hdf5_file_t *f, haddr_t addr, off_t offset)
/*-------------------------------------------------------------------------
* Function: H5H_remove_free
*
- * Purpose: Removes free list element FL from the specified heap.
+ * Purpose: Removes free list element FL from the specified heap and
+ * frees it.
*
- * Return: void
+ * Return: NULL
*
* Programmer: Robb Matzke
* matzke@llnl.gov
@@ -474,13 +482,14 @@ H5H_peek (hdf5_file_t *f, haddr_t addr, off_t offset)
*
*-------------------------------------------------------------------------
*/
-static void
+static H5H_free_t *
H5H_remove_free (H5H_t *heap, H5H_free_t *fl)
{
if (fl->prev) fl->prev->next = fl->next;
if (fl->next) fl->next->prev = fl->prev;
if (!fl->prev) heap->freelist = fl->next;
+ return H5MM_xfree (fl);
}
@@ -545,7 +554,7 @@ H5H_insert (hdf5_file_t *f, haddr_t addr, size_t buf_size, const void *buf)
break;
} else if (fl->size==need) {
offset = fl->offset;
- H5H_remove_free (heap, fl);
+ fl = H5H_remove_free (heap, fl);
break;
} else if (!max_fl || max_fl->offset < fl->offset) {
max_fl = fl;
@@ -582,7 +591,7 @@ H5H_insert (hdf5_file_t *f, haddr_t addr, size_t buf_size, const void *buf)
}
}
#endif
- H5H_remove_free (heap, max_fl);
+ max_fl = H5H_remove_free (heap, max_fl);
}
} else {
@@ -762,7 +771,7 @@ H5H_remove (hdf5_file_t *f, haddr_t addr, off_t offset, size_t size)
if (fl2->offset + fl2->size == fl->offset) {
fl->offset = fl2->offset;
fl->size += fl2->size;
- H5H_remove_free (heap, fl2);
+ fl2 = H5H_remove_free (heap, fl2);
HRETURN (SUCCEED);
}
}
@@ -774,7 +783,7 @@ H5H_remove (hdf5_file_t *f, haddr_t addr, off_t offset, size_t size)
while (fl2) {
if (fl->offset + fl->size == fl2->offset) {
fl->size += fl2->size;
- H5H_remove_free (heap, fl2);
+ fl2 = H5H_remove_free (heap, fl2);
HRETURN (SUCCEED);
}
}
diff --git a/src/H5MM.c b/src/H5MM.c
index 39da6d7..eb9c76e 100644
--- a/src/H5MM.c
+++ b/src/H5MM.c
@@ -168,6 +168,16 @@ H5MM_xstrdup (const char *s)
void *
H5MM_xfree (const void *mem)
{
- if (mem) HDfree (mem);
+ /*
+ * free(3) takes a non-const pointer as an argument even though
+ * conceptually the argument could be a constant because by time
+ * free() mucks with it's contents, it should already be free :-)
+ * Instead of passing a const arg to free, which generates a
+ * compiler warning, we cast it to a non-const arg first. With
+ * gcc, this results in a warning only if -Wcast-qual is turned on.
+ */
+ void *non_const_mem = mem;
+
+ if (mem) HDfree (non_const_mem);
return NULL;
}
diff --git a/src/H5O.c b/src/H5O.c
index 75a5993..8509e41 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -27,7 +27,7 @@
/* PRIVATE PROTOTYPES */
static herr_t H5O_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr,
H5O_t *oh);
-static H5O_t *H5O_load (hdf5_file_t *f, haddr_t addr, const void *_data);
+static H5O_t *H5O_load (hdf5_file_t *f, haddr_t addr, void *_data);
static intn H5O_find_in_ohdr (hdf5_file_t *f, haddr_t addr,
const H5O_class_t **type_p, intn sequence);
static intn H5O_alloc (hdf5_file_t *f, H5O_t *oh, const H5O_class_t *type,
@@ -37,7 +37,7 @@ static intn H5O_alloc_new_chunk (hdf5_file_t *f, H5O_t *oh, size_t size);
/* H5O inherits cache-like properties from H5AC */
static const H5AC_class_t H5AC_OHDR[1] = {{
- (void*(*)(hdf5_file_t*,haddr_t,const void*))H5O_load,
+ (void*(*)(hdf5_file_t*,haddr_t,void*))H5O_load,
(herr_t(*)(hdf5_file_t*,hbool_t,haddr_t,void*))H5O_flush,
}};
@@ -166,7 +166,7 @@ H5O_new (hdf5_file_t *f, intn nlink, size_t size_hint)
*-------------------------------------------------------------------------
*/
static H5O_t *
-H5O_load (hdf5_file_t *f, haddr_t addr, const void *_data)
+H5O_load (hdf5_file_t *f, haddr_t addr, void *_data)
{
H5O_t *oh = NULL;
H5O_t *ret_value = (void*)1; /*kludge for HGOTO_ERROR*/
@@ -509,8 +509,9 @@ H5O_link (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent, intn adjust)
/* check args */
assert (f);
- assert (addr>=0);
-
+ assert (addr>0 || (ent && ent->header>0));
+ if (addr<=0) addr = ent->header;
+
/* get header */
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) {
HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL);
@@ -528,9 +529,11 @@ H5O_link (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent, intn adjust)
}
} else {
oh->nlink += adjust;
- if (oh->nlink>1 && ent) ent->type = H5G_NOTHING_CACHED;
+ if (oh->nlink>1 && ent && H5G_NOTHING_CACHED!=ent->type) {
+ ent->dirty = TRUE;
+ ent->type = H5G_NOTHING_CACHED;
+ }
}
-
oh->dirty = TRUE;
FUNC_LEAVE (oh->nlink);
@@ -570,7 +573,10 @@ H5O_read (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
/* check args */
assert (f);
- assert (addr>=0);
+ if (addr<=0 && (!ent || ent->header<=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? */
@@ -585,6 +591,10 @@ H5O_read (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
HRETURN_ERROR (H5E_OHDR, H5E_NOTFOUND, NULL);
}
+#ifdef LATER
+ /* should we cache it in ENT? */
+#endif
+
/* copy the message to the user-supplied buffer */
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) {
HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, NULL);
@@ -692,7 +702,7 @@ H5O_peek (hdf5_file_t *f, haddr_t addr, const H5O_class_t *type,
/* check args */
assert (f);
- assert (addr>=0);
+ assert (addr>0);
if ((idx = H5O_find_in_ohdr (f, addr, &type, sequence))<0) {
HRETURN_ERROR (H5E_OHDR, H5E_NOTFOUND, NULL);
@@ -709,17 +719,20 @@ H5O_peek (hdf5_file_t *f, haddr_t addr, const H5O_class_t *type,
* Function: H5O_modify
*
* Purpose: Modifies an existing message or creates a new message.
- * The object header is at file address ADDR of file F. An
+ * The object header is at file address ADDR of file F (but if
+ * ENT is present then its `header' field is used instead). An
* optional symbol table entry ENT can be supplied in which
* case the cache fields in that symbol table are updated if
- * appropriate. If the symbol table entry changes then the
- * optional ENT_MODIFIED arg will point to a non-zero value,
- * otherwise ENT_MODIFIED isn't changed.
+ * appropriate.
*
* The OVERWRITE argument is either a sequence number of a
* message to overwrite (usually zero) or the constant
* H5O_NEW_MESSAGE (-1) to indicate that a new message is to
- * be created.
+ * be created. If the message to overwrite doesn't exist then
+ * it is created (but only if it can be inserted so its sequence
+ * number is OVERWRITE; that is, you can create a message with
+ * the sequence number 5 if there is no message with sequence
+ * number 4).
*
* Return: Success: The sequence number of the message that
* was modified or created.
@@ -736,8 +749,7 @@ H5O_peek (hdf5_file_t *f, haddr_t addr, const H5O_class_t *type,
*/
intn
H5O_modify (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
- hbool_t *ent_modified, const H5O_class_t *type,
- intn overwrite, const void *mesg)
+ const H5O_class_t *type, intn overwrite, const void *mesg)
{
H5O_t *oh = NULL;
intn idx, sequence;
@@ -747,10 +759,11 @@ H5O_modify (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
/* check args */
assert (f);
- assert (addr>=0);
+ assert (addr>0 || (ent && ent->header>0));
assert (type);
assert (mesg);
-
+ if (addr<=0) addr = ent->header;
+
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) {
HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL);
}
@@ -764,7 +777,13 @@ H5O_modify (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
/* Was the right message found? */
if (overwrite>=0 &&
(idx>=oh->nmesgs || sequence!=overwrite)) {
- HRETURN_ERROR (H5E_OHDR, H5E_NOTFOUND, FAIL); /*message not found*/
+
+ /* But can we insert a new one with this sequence number? */
+ if (overwrite==sequence+1) {
+ overwrite = -1;
+ } else {
+ HRETURN_ERROR (H5E_OHDR, H5E_NOTFOUND, FAIL); /*message not found*/
+ }
}
/* Allocate space for the new message */
@@ -787,7 +806,7 @@ 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 (modified && ent_modified) *ent_modified = modified;
+ if (ent && !ent->dirty) ent->dirty = modified;
}
FUNC_LEAVE (sequence);
@@ -826,7 +845,7 @@ H5O_modify (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
*/
herr_t
H5O_remove (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
- hbool_t *ent_modified, const H5O_class_t *type, intn sequence)
+ const H5O_class_t *type, intn sequence)
{
H5O_t *oh = NULL;
intn i, seq;
@@ -835,8 +854,9 @@ H5O_remove (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
/* check args */
assert (f);
- assert (addr>=0);
+ assert (addr>0 || (ent && ent->header>0));
assert (type);
+ if (addr<=0) addr = ent->header;
/* load the object header */
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) {
@@ -848,9 +868,9 @@ H5O_remove (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
if (seq++ == sequence || H5O_ALL==sequence) {
/* clear symbol table entry cache */
- if (ent && type->cache && H5G_NOTHING_CACHED!=ent->type) {
+ if (ent && type->cache && type->cache_type==ent->type) {
ent->type = H5G_NOTHING_CACHED;
- if (ent_modified) *ent_modified = TRUE;
+ ent->dirty = TRUE;
}
/* change message type to nil and zero it */
@@ -922,9 +942,14 @@ H5O_alloc_extend_chunk (H5O_t *oh, intn chunkno, size_t size)
oh->mesg[idx].raw_size += delta;
old_addr = oh->chunk[chunkno].image;
- oh->chunk[chunkno].size += delta;
+
+ /* Be careful not to indroduce garbage */
oh->chunk[chunkno].image = H5MM_xrealloc (old_addr,
- oh->chunk[chunkno].size);
+ (oh->chunk[chunkno].size +
+ delta));
+ HDmemset (oh->chunk[chunkno].image + oh->chunk[chunkno].size,
+ 0, delta);
+ oh->chunk[chunkno].size += delta;
/* adjust raw addresses for messages of this chunk */
if (old_addr != oh->chunk[chunkno].image) {
@@ -1071,7 +1096,7 @@ H5O_alloc_new_chunk (hdf5_file_t *f, H5O_t *oh, size_t size)
oh->chunk[chunkno].dirty = TRUE;
oh->chunk[chunkno].addr = H5O_NO_ADDR;
oh->chunk[chunkno].size = size;
- oh->chunk[chunkno].image = p = H5MM_xmalloc (size);
+ oh->chunk[chunkno].image = p = H5MM_xcalloc (1, size);
/*
* Make sure we have enough space for all possible new messages
diff --git a/src/H5Ocont.c b/src/H5Ocont.c
index 2f8bb58..2b01838 100644
--- a/src/H5Ocont.c
+++ b/src/H5Ocont.c
@@ -36,6 +36,7 @@ const H5O_class_t H5O_CONT[1] = {{
H5O_CONT_ID, /*message id number */
"hdr continuation", /*message name for debugging */
sizeof (H5O_cont_t), /*native message size */
+ H5G_NOTHING_CACHED, /*symbol table type field */
H5O_cont_decode, /*decode message */
H5O_cont_encode, /*encode message */
NULL, /*no fast method */
diff --git a/src/H5Oname.c b/src/H5Oname.c
index cec5d34..6224401 100644
--- a/src/H5Oname.c
+++ b/src/H5Oname.c
@@ -36,6 +36,7 @@ const H5O_class_t H5O_NAME[1] = {{
H5O_NAME_ID, /*message id number */
"name", /*message name for debugging */
sizeof (H5O_name_t), /*native message size */
+ H5G_NOTHING_CACHED, /*symbol table entry type field */
H5O_name_decode, /*decode message */
H5O_name_encode, /*encode message */
NULL, /*no stab entry fields */
diff --git a/src/H5Onull.c b/src/H5Onull.c
index 467e26a..25579f0 100644
--- a/src/H5Onull.c
+++ b/src/H5Onull.c
@@ -24,6 +24,7 @@ const H5O_class_t H5O_NULL[1] = {{
H5O_NULL_ID, /*message id number */
"null", /*message name for debugging */
0, /*native message size */
+ H5G_NOTHING_CACHED, /*symtab entry `type' field */
NULL, /*no decode method */
NULL, /*no encode method */
NULL, /*no fast method */
diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h
index 4d11e9b..30b0af1 100644
--- a/src/H5Oprivate.h
+++ b/src/H5Oprivate.h
@@ -47,6 +47,7 @@ typedef struct H5O_class_t {
intn id; /*message type ID on disk */
const char *name; /*message name for debugging */
size_t native_size; /*size of native message */
+ 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*/
@@ -163,11 +164,9 @@ void *H5O_read (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
const void *H5O_peek (hdf5_file_t *f, haddr_t addr, const H5O_class_t *type,
intn sequence);
intn H5O_modify (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
- hbool_t *ent_modified, const H5O_class_t *type,
- intn overwrite, const void *mesg);
+ const H5O_class_t *type, intn overwrite, const void *mesg);
herr_t H5O_remove (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
- hbool_t *ent_modified, const H5O_class_t *type,
- intn sequence);
+ const H5O_class_t *type, intn sequence);
herr_t H5O_reset (const H5O_class_t *type, void *native);
herr_t H5O_debug (hdf5_file_t *f, haddr_t addr, FILE *stream,
intn indent, intn fwidth);
diff --git a/src/H5Osdim.c b/src/H5Osdim.c
index 80b9735..923ceea 100644
--- a/src/H5Osdim.c
+++ b/src/H5Osdim.c
@@ -53,6 +53,7 @@ const H5O_class_t H5O_SIM_DIM[1] = {{
H5O_SIM_DIM_ID, /* message id number */
"sim_dim", /* message name for debugging */
sizeof (H5O_sim_dim_t), /* native message size */
+ H5G_CACHED_SDATA, /* symtab entry `type' field */
H5O_sim_dim_decode, /* decode message */
H5O_sim_dim_encode, /* encode message */
H5O_sim_dim_fast, /* get message from stab entry */
diff --git a/src/H5Osdtyp.c b/src/H5Osdtyp.c
index 19af66b..8920625 100644
--- a/src/H5Osdtyp.c
+++ b/src/H5Osdtyp.c
@@ -50,16 +50,17 @@ static herr_t H5O_sim_dtype_debug (hdf5_file_t *f, const void *_mesg,
/* This message derives from H5O */
const H5O_class_t H5O_SIM_DTYPE[1] = {{
- H5O_SIM_DTYPE_ID, /* message id number */
- "sim_dtype", /* message name for debugging */
- sizeof (H5O_sim_dtype_t), /* native message size */
+ H5O_SIM_DTYPE_ID, /* message id number */
+ "sim_dtype", /* message name for debugging */
+ sizeof (H5O_sim_dtype_t), /* native message size */
+ H5G_CACHED_SDATA, /* symtab entry `type' field */
H5O_sim_dtype_decode, /* decode message */
H5O_sim_dtype_encode, /* encode message */
H5O_sim_dtype_fast, /* get message from stab entry */
H5O_sim_dtype_cache, /* put message into stab entry */
H5O_sim_dtype_copy, /* copy the native value */
H5O_sim_dtype_size, /* size of symbol table entry */
- NULL, /* default reset method */
+ NULL, /* default reset method */
H5O_sim_dtype_debug, /* debug the message */
}};
diff --git a/src/H5Ostab.c b/src/H5Ostab.c
index 1710fe3..0b67a73 100644
--- a/src/H5Ostab.c
+++ b/src/H5Ostab.c
@@ -38,6 +38,7 @@ const H5O_class_t H5O_STAB[1] = {{
H5O_STAB_ID, /*message id number */
"stab", /*message name for debugging */
sizeof (H5O_stab_t), /*native message size */
+ H5G_CACHED_STAB, /*symtab entry `type' field */
H5O_stab_decode, /*decode message */
H5O_stab_encode, /*encode message */
H5O_stab_fast, /*get message from stab entry */
diff --git a/src/H5Ostdst.c b/src/H5Ostdst.c
index 85da813..0186b44 100644
--- a/src/H5Ostdst.c
+++ b/src/H5Ostdst.c
@@ -51,6 +51,7 @@ const H5O_class_t H5O_STD_STORE[1] = {{
H5O_STD_STORE_ID, /* message id number */
"std_store", /* message name for debugging */
sizeof (H5O_std_store_t),/* native message size */
+ H5G_NOTHING_CACHED, /* symtab entry `type' field */
H5O_std_store_decode, /* decode message */
H5O_std_store_encode, /* encode message */
NULL, /* get message from stab entry */
diff --git a/src/H5private.h b/src/H5private.h
index 070dca9..f13ff59 100644
--- a/src/H5private.h
+++ b/src/H5private.h
@@ -101,6 +101,7 @@
* File offsets.
*/
typedef off_t haddr_t;
+#define NO_ADDR (-1)
/*
* Some compilers have problems declaring auto variables that point
@@ -402,7 +403,7 @@ typedef off_t haddr_t;
extern hbool_t library_initialize_g; /*good thing C's lazy about extern!*/
extern hbool_t thread_initialize_g; /*don't decl interface_initialize_g */
-#define FUNC_ENTER(func_name,interface_init_func,err) \
+#define FUNC_ENTER(func_name,interface_init_func,err) { \
CONSTR (FUNC, #func_name); \
PABLO_SAVE (ID_ ## func_name); \
\
@@ -428,8 +429,8 @@ extern hbool_t thread_initialize_g; /*don't decl interface_initialize_g */
((herr_t(*)(void))interface_init_func)()<0) { \
HRETURN_ERROR (H5E_FUNC, H5E_CANTINIT, err); \
} \
- }
-
+ } \
+ {
/*-------------------------------------------------------------------------
@@ -447,7 +448,7 @@ extern hbool_t thread_initialize_g; /*don't decl interface_initialize_g */
*
*-------------------------------------------------------------------------
*/
-#define FUNC_LEAVE(return_value) HRETURN(return_value)
+#define FUNC_LEAVE(return_value) HRETURN(return_value)}}
/*
* The FUNC_ENTER() and FUNC_LEAVE() macros make calls to Pablo functions
diff --git a/src/Makefile.in b/src/Makefile.in
index d77a356..0a66e9d 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -15,8 +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 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
+ 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
LIB_OBJ=$(LIB_SRC:.c=.o)
diff --git a/test/Makefile.in b/test/Makefile.in
index 339ebc3..8a7d4f0 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -22,6 +22,6 @@ PRIVATE_HDR=testhdf5.h
# How to build the programs...
testhdf5: $(PROG_OBJ) ../src/libhdf5.a
- $(CC) $(CFLAGS) -o $@ $(PROG_OBJ) ../src/libhdf5.a
+ $(CC) $(CFLAGS) -o $@ $(PROG_OBJ) ../src/libhdf5.a $(LIBS)
@CONCLUDE@
diff --git a/test/th5d.c b/test/th5d.c
index 604aaef..90e1234 100644
--- a/test/th5d.c
+++ b/test/th5d.c
@@ -107,7 +107,7 @@ static void test_h5d_basic_write(void)
CHECK(ret,FAIL,"H5Tset_type");
did1=H5Mcreate(fid1,H5_DATASET,DATA1_NAME);
- CHECK(sid1,FAIL,"H5Mcreate");
+ CHECK(did1,FAIL,"H5Mcreate");
ret=H5Dset_info(did1,tid1,sid1);
CHECK(ret,FAIL,"H5Dset_info");
diff --git a/test/tohdr.c b/test/tohdr.c
index fc19d4e..b3a0b10 100644
--- a/test/tohdr.c
+++ b/test/tohdr.c
@@ -48,7 +48,6 @@ test_ohdr (void)
herr_t status;
void *ptr;
H5G_entry_t ent;
- hbool_t ent_mod;
int i;
MESSAGE (5, ("Testing Object Headers\n"));
@@ -69,7 +68,7 @@ test_ohdr (void)
MESSAGE (8, ("Creating new message...\n"));
stab.btree_addr = 11111111;
stab.heap_addr = 22222222;
- status = H5O_modify (f, oh, NULL, NULL, H5O_STAB, H5O_NEW_MESG, &stab);
+ status = H5O_modify (f, oh, NULL, H5O_STAB, H5O_NEW_MESG, &stab);
VERIFY (status, 0, "H5O_modify");
H5AC_flush (f, NULL, 0, TRUE);
@@ -85,7 +84,7 @@ test_ohdr (void)
MESSAGE (8, ("Modifying message...\n"));
stab.btree_addr = 33333333;
stab.heap_addr = 44444444;
- status = H5O_modify (f, oh, NULL, NULL, H5O_STAB, 0, &stab);
+ status = H5O_modify (f, oh, NULL, H5O_STAB, 0, &stab);
VERIFY (status, 0, "H5O_modify");
H5AC_flush (f, NULL, 0, TRUE);
@@ -102,11 +101,12 @@ test_ohdr (void)
MESSAGE (8, ("Creating a duplicate message...\n"));
ent.header = 0;
ent.type = H5G_NOTHING_CACHED;
+ ent.dirty = FALSE;
stab.btree_addr = 55555555;
stab.heap_addr = 66666666;
- status = H5O_modify (f, oh, &ent, &ent_mod, H5O_STAB, H5O_NEW_MESG, &stab);
+ status = H5O_modify (f, oh, &ent, H5O_STAB, H5O_NEW_MESG, &stab);
VERIFY (status, 1, "H5O_modify");
- VERIFY (ent_mod, TRUE, "H5O_modify");
+ VERIFY (ent.dirty, TRUE, "H5O_modify");
VERIFY (ent.type, H5G_CACHED_STAB, "H5O_modify");
VERIFY (ent.cache.stab.heap_addr, stab.heap_addr, "H5O_modify");
VERIFY (ent.cache.stab.btree_addr, stab.btree_addr, "H5O_modify");
@@ -122,11 +122,12 @@ test_ohdr (void)
* Test modification of the second message with a symbol table.
*/
MESSAGE (8, ("Modifying the duplicate message...\n"));
+ ent.dirty = FALSE;
stab.btree_addr = 77777777;
stab.heap_addr = 88888888;
- status = H5O_modify (f, oh, &ent, &ent_mod, H5O_STAB, 1, &stab);
+ status = H5O_modify (f, oh, &ent, H5O_STAB, 1, &stab);
VERIFY (status, 1, "H5O_modify");
- VERIFY (ent_mod, TRUE, "H5O_modify");
+ VERIFY (ent.dirty, TRUE, "H5O_modify");
VERIFY (ent.type, H5G_CACHED_STAB, "H5O_modify");
VERIFY (ent.cache.stab.heap_addr, stab.heap_addr, "H5O_modify");
VERIFY (ent.cache.stab.btree_addr, stab.btree_addr, "H5O_modify");
@@ -146,7 +147,7 @@ test_ohdr (void)
for (i=0; i<40; i++) {
stab.btree_addr = (i+1)*1000 + 1;
stab.heap_addr = (i+1)*1000 + 2;
- status = H5O_modify (f, oh, NULL, NULL, H5O_STAB, H5O_NEW_MESG, &stab);
+ status = H5O_modify (f, oh, NULL, H5O_STAB, H5O_NEW_MESG, &stab);
VERIFY (status, 2+i, "H5O_modify");
}
H5AC_flush (f, NULL, 0, TRUE);
@@ -159,7 +160,7 @@ test_ohdr (void)
for (i=0; i<10; i++) {
stab.btree_addr = (i+1)*1000 + 10;
stab.heap_addr = (i+1)*1000 + 20;
- status = H5O_modify (f, oh, NULL, NULL, H5O_STAB, H5O_NEW_MESG, &stab);
+ status = H5O_modify (f, oh, NULL, H5O_STAB, H5O_NEW_MESG, &stab);
VERIFY (status, 42+i, "H5O_modify");
H5AC_flush (f, NULL, 0, TRUE);
}
@@ -167,7 +168,7 @@ test_ohdr (void)
/*
* Delete all symbol table messages.
*/
- status = H5O_remove (f, oh, NULL, NULL, H5O_STAB, H5O_ALL);
+ status = H5O_remove (f, oh, NULL, H5O_STAB, H5O_ALL);
CHECK_I (status, "H5O_remove");
/* close the file */
diff --git a/test/tstab.c b/test/tstab.c
index 4e6c21e..d525758 100644
--- a/test/tstab.c
+++ b/test/tstab.c
@@ -65,6 +65,7 @@ test_1 (void)
CHECK (f, NULL, "H5Aatom_object");
/* create the object */
+ memset (&ent, 0, sizeof(ent));
ent.header = H5O_new (f, 0, 64);
CHECK_I (ent.header, "H5O_new");
ent.type = H5G_NOTHING_CACHED;
@@ -152,7 +153,7 @@ test_1 (void)
CHECK_PTR (status_ptr, "H5O_read");
CHECK_PTR (name_mesg.s, "H5O_read");
VERIFY (strcmp(name_mesg.s, "foo"), 0, "H5O_read");
-
+ if (status_ptr) H5O_reset (H5O_NAME, &name_mesg); /*free message data*/
/*