2
0
mirror of https://github.com/HDFGroup/hdf5.git synced 2025-03-25 17:00:45 +08:00

[svn-r150] Changes since 19971219

----------------------

./src/H5private.h
        Changed HDF5_MAJOR_VERSION to 5

./src/H5Aprivate.h
./src/H5Apublic.h
        Added group atoms.

./src/H5D.c
./src/H5P.c
./test/istore.c
./test/tohdr.c
./test/tstab.c
        Updated for symbol table interface changes.

./src/H5F.c
./src/H5Fprivate.h
        Simpler handling of special case files: empty files and files
        with a single object.

./src/H5G.c
./src/H5Gent.c
./src/H5Gnode.c
./src/H5Gpkg.h
./src/H5Gprivate.h
./src/H5Gpublic.h
./src/H5Gshad.c         (DELETED)
./src/H5Gstab.c
./src/Makefile.in
        Removed shadows, simplifying code.  Symbol table entries are
        allowed to cache only constant meta data.  Fixed naming.

./src/H5O.c
./src/H5Oprivate.h
        Access to object headers is always done through a symbol table
        entry instead of a file address.  Added stubs for opening and
        closing object headers to be used when deletion is implemented.
This commit is contained in:
Robb Matzke 1998-01-05 22:07:15 -05:00
parent dfff2572ca
commit 1d17defdfc
23 changed files with 1044 additions and 2035 deletions

@ -63,7 +63,6 @@
./src/H5Gpkg.h
./src/H5Gprivate.h
./src/H5Gpublic.h
./src/H5Gshad.c
./src/H5Gstab.c
./src/H5H.c
./src/H5Hprivate.h

@ -63,7 +63,8 @@
#define H5A_DATATYPEID_HASHSIZE 64
#define H5A_DATASPACEID_HASHSIZE 64
#define H5A_DATASETID_HASHSIZE 64
#define H5A_OID_HASHSIZE 64
#define H5A_OID_HASHSIZE 64
#define H5A_GROUPID_HASHSIZE 64
/* Atom information structure used */
typedef struct atom_info_struct_tag {

@ -38,6 +38,7 @@ typedef enum {
#ifndef NDEBUG
H5_TEMPLATE_MAX, /* Not really a group ID */
#endif
H5_GROUP, /* Group ID for Group objects */
H5_DATATYPE, /* Group ID for Datatype objects */
H5_DATASPACE, /* Group ID for Dataspace objects */
H5_DATASET, /* Group ID for Dataset objects */

@ -37,7 +37,7 @@ static char RcsId[] = "@(#)$Revision$";
*/
struct H5D_t {
H5F_t *file; /*file store for this object */
H5G_entry_t *ent; /*cached object header stuff */
H5G_entry_t ent; /*cached object header stuff */
H5T_t *type; /*datatype of this dataset */
H5P_t *space; /*dataspace of this dataset */
H5D_create_t create_parms; /*creation parameters */
@ -53,7 +53,7 @@ const H5D_create_t H5D_create_dflt = {
1, /* Chunk dimensions */
{1, 1, 1, 1, 1, 1, 1, 1, /* Chunk size. These default values....*/
1, 1, 1, 1, 1, 1, 1, 1, /*...are quite useless. Larger chunks..*/
1, 1, 1, 1, 1, 1, 1, 1, /*...produces fewer, but larger I/O.....*/
1, 1, 1, 1, 1, 1, 1, 1, /*...produce fewer, but larger I/O......*/
1, 1, 1, 1, 1, 1, 1, 1}, /*...requests. */
};
@ -576,26 +576,22 @@ H5D_create (H5F_t *f, const char *name, const H5T_t *type, const H5P_t *space,
/* Initialize the dataset object */
new_dset = H5MM_xcalloc (1, sizeof(H5D_t));
new_dset->file = f;
H5F_addr_undef (&(new_dset->ent.header));
new_dset->type = H5T_copy (type);
new_dset->space = H5P_copy (space);
new_dset->create_parms = *create_parms;
/*
* Open (and create) a new file object and update the object header
* immediately with the new information so when others access the dataset
* they see the most current info. This `write through the dataset'
* policy is used throughout this package, and because the object header
* is cached it shouldn't cause any disk activity.
* Create (open for write access) an object header.
*/
if (NULL==(new_dset->ent = H5G_create (f, name, H5D_MINHDR_SIZE))) {
if (H5O_create (f, 0, &(new_dset->ent))<0) {
HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, NULL,
"problem with the dataset name");
"unable to create dataset object header");
}
/* Update the type and space header messages */
if (H5O_modify (f, NO_ADDR, new_dset->ent, H5O_DTYPE, 0,
new_dset->type)<0 ||
H5P_modify (f, new_dset->ent, new_dset->space)<0) {
if (H5O_modify (f, &(new_dset->ent), H5O_DTYPE, 0, new_dset->type)<0 ||
H5P_modify (f, &(new_dset->ent), new_dset->space)<0) {
HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, NULL,
"can't update type or space header messages");
}
@ -612,7 +608,7 @@ H5D_create (H5F_t *f, const char *name, const H5T_t *type, const H5P_t *space,
HGOTO_ERROR (H5E_DATASET, H5E_NOSPACE, NULL,
"can't allocate raw file storage");
}
if (H5O_modify (f, NO_ADDR, new_dset->ent, H5O_CSTORE, 0,
if (H5O_modify (f, &(new_dset->ent), H5O_CSTORE, 0,
&(new_dset->storage.cstore))<0) {
HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, NULL,
"can't update dataset object header");
@ -639,7 +635,7 @@ H5D_create (H5F_t *f, const char *name, const H5T_t *type, const H5P_t *space,
HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, NULL,
"can't initialize chunked storage");
}
if (H5O_modify (f, NO_ADDR, new_dset->ent, H5O_ISTORE, 0,
if (H5O_modify (f, &(new_dset->ent), H5O_ISTORE, 0,
&(new_dset->storage.istore))<0) {
HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, NULL,
"can't update dataset object header");
@ -651,6 +647,11 @@ H5D_create (H5F_t *f, const char *name, const H5T_t *type, const H5P_t *space,
HGOTO_ERROR (H5E_DATASET, H5E_UNSUPPORTED, NULL, "not implemented yet");
}
/* Give the dataset a name */
if (H5G_insert (f, name, &(new_dset->ent))<0) {
HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, NULL, "unable to name dataset");
}
/* Success */
ret_value = new_dset;
@ -659,7 +660,9 @@ H5D_create (H5F_t *f, const char *name, const H5T_t *type, const H5P_t *space,
if (!ret_value && new_dset) {
if (new_dset->type) H5T_close (new_dset->type);
if (new_dset->space) H5P_close (new_dset->space);
if (new_dset->ent) H5G_close (f, new_dset->ent);
if (H5F_addr_defined (&(new_dset->ent.header))) {
H5O_close (f, &(new_dset->ent));
}
new_dset->file = NULL;
H5MM_xfree (new_dset);
}
@ -704,16 +707,20 @@ H5D_open (H5F_t *f, const char *name)
dataset = H5MM_xcalloc (1, sizeof(H5D_t));
dataset->file = f;
dataset->create_parms = H5D_create_dflt;
H5F_addr_undef (&(dataset->ent.header));
/* Open the dataset object */
if (NULL==(dataset->ent=H5G_open (f, name))) {
if (H5G_find (f, name, NULL, &(dataset->ent))<0) {
HGOTO_ERROR (H5E_DATASET, H5E_NOTFOUND, NULL, "not found");
}
if (H5O_open (f, &(dataset->ent))<0) {
HGOTO_ERROR (H5E_DATASET, H5E_CANTOPENOBJ, NULL, "unable to open");
}
/* Get the type and space */
if (NULL==(dataset->type = H5O_read (f, NO_ADDR, dataset->ent, H5O_DTYPE,
if (NULL==(dataset->type = H5O_read (f, &(dataset->ent), H5O_DTYPE,
0, NULL)) ||
NULL==(dataset->space = H5P_read (f, dataset->ent))) {
NULL==(dataset->space = H5P_read (f, &(dataset->ent)))) {
HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, NULL,
"can't load type of space info from dataset header");
}
@ -724,12 +731,12 @@ H5D_open (H5F_t *f, const char *name)
* values are copied to the dataset create template so the user can query
* them.
*/
if (H5O_read (dataset->file, NO_ADDR, dataset->ent, H5O_CSTORE, 0,
if (H5O_read (dataset->file, &(dataset->ent), H5O_CSTORE, 0,
&(dataset->storage.cstore))) {
/* Contiguous storage */
dataset->create_parms.layout = H5D_CONTIGUOUS;
} else if (H5O_read (dataset->file, NO_ADDR, dataset->ent, H5O_ISTORE, 0,
} else if (H5O_read (dataset->file, &(dataset->ent), H5O_ISTORE, 0,
&(dataset->storage.istore))) {
/*
* Chunked storage. The creation template's dimension is one less than
@ -755,7 +762,9 @@ H5D_open (H5F_t *f, const char *name)
done:
if (!ret_value && dataset) {
if (dataset->ent) H5G_close (f, dataset->ent);
if (H5F_addr_defined (&(dataset->ent.header))) {
H5O_close (f, &(dataset->ent));
}
if (dataset->type) H5T_close (dataset->type);
if (dataset->space) H5P_close (dataset->space);
dataset->file = NULL;
@ -799,8 +808,7 @@ H5D_close (H5D_t *dataset)
assert (dataset && dataset->file);
/* Close the dataset object */
H5G_close (dataset->file, dataset->ent);
dataset->ent = NULL;
H5O_close (dataset->file, &(dataset->ent));
/*
* Release dataset type and space - there isn't much we can do if one of

@ -417,14 +417,6 @@ H5F_new (H5F_file_t *shared)
/* Create a main cache */
H5AC_create (f, H5AC_NSLOTS);
/* Create the shadow hash table */
f->shared->nshadows = H5G_NSHADOWS;
f->shared->shadow = H5MM_xcalloc (f->shared->nshadows,
sizeof(struct H5G_hash_t*));
/* Create a root symbol slot */
f->shared->root_sym = H5G_ent_calloc ();
}
f->shared->nrefs++;
@ -463,9 +455,7 @@ H5F_dest (H5F_t *f)
if (f) {
if (0 == --(f->shared->nrefs)) {
H5AC_dest (f);
f->shared->root_sym = H5MM_xfree (f->shared->root_sym);
f->shared->nshadows = 0;
f->shared->shadow = H5MM_xfree (f->shared->shadow);
f->shared->root_ent = H5MM_xfree (f->shared->root_ent);
f->shared = H5MM_xfree (f->shared);
}
f->name = H5MM_xfree (f->name);
@ -586,6 +576,7 @@ H5F_open (const H5F_low_class_t *type, const char *name, uintn flags,
size_t variable_size; /*variable part of boot block */
H5F_create_t *cp=NULL; /*file creation parameters */
haddr_t addr1, addr2; /*temporary address */
H5G_entry_t root_ent; /*root symbol table entry */
const char *s = name;
FUNC_ENTER (H5F_open, NULL);
@ -887,10 +878,15 @@ H5F_open (const H5F_low_class_t *type, const char *name, uintn flags,
H5F_addr_decode (f, &p, &(f->shared->smallobj_addr));
H5F_addr_decode (f, &p, &(f->shared->freespace_addr));
H5F_addr_decode (f, &p, &(f->shared->hdf5_eof));
if (H5G_ent_decode (f, &p, f->shared->root_sym)<0) {
if (H5G_ent_decode (f, &p, &root_ent)<0) {
HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL,
"can't read root symbol entry");
}
if (H5F_addr_defined (&(root_ent.header))) {
f->shared->root_ent = H5MM_xmalloc (sizeof(H5G_entry_t));
*(f->shared->root_ent) = root_ent;
}
/*
* The userdefined data is the area of the file before the base
@ -1150,8 +1146,6 @@ hid_t H5Fopen(const char *filename, uintn flags, hid_t access_temp)
* Return: Success: SUCCEED
*
* Failure: FAIL
* -2 if the there are open objects and
* INVALIDATE was non-zero.
*
* Programmer: Robb Matzke
* matzke@llnl.gov
@ -1165,7 +1159,6 @@ static herr_t
H5F_flush (H5F_t *f, hbool_t invalidate)
{
uint8 buf[2048], *p=buf;
herr_t shadow_flush;
FUNC_ENTER (H5F_flush, FAIL);
@ -1177,12 +1170,6 @@ H5F_flush (H5F_t *f, hbool_t invalidate)
*/
if (0==(H5F_ACC_WRITE & f->shared->flags)) HRETURN (SUCCEED);
/*
* Flush all open object info. If this fails just remember it and return
* failure at the end. At least that way we get a consistent file.
*/
shadow_flush = H5G_shadow_flush (f, invalidate);
/* flush (and invalidate) the entire cache */
if (H5AC_flush (f, NULL, 0, invalidate)<0) {
HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL, "can't flush cache");
@ -1207,7 +1194,7 @@ H5F_flush (H5F_t *f, hbool_t invalidate)
H5F_addr_encode (f, &p, &(f->shared->smallobj_addr));
H5F_addr_encode (f, &p, &(f->shared->freespace_addr));
H5F_addr_encode (f, &p, &(f->shared->hdf5_eof));
H5G_ent_encode (f, &p, f->shared->root_sym);
H5G_ent_encode (f, &p, f->shared->root_ent);
/* update file length if necessary */
if (!H5F_addr_defined (&(f->shared->hdf5_eof))) {
@ -1226,11 +1213,6 @@ H5F_flush (H5F_t *f, hbool_t invalidate)
HRETURN_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "low level flush failed");
}
/* Did shadow flush fail above? */
if (shadow_flush<0) {
HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, -2, "object are still open");
}
FUNC_LEAVE (SUCCEED);
}
@ -1242,8 +1224,7 @@ H5F_flush (H5F_t *f, hbool_t invalidate)
*
* Return: Success: SUCCEED
*
* Failure: FAIL, or -2 if the failure is due to objects
* still being open.
* Failure: FAIL
*
* Programmer: Robb Matzke
* Tuesday, September 23, 1997
@ -1255,27 +1236,24 @@ H5F_flush (H5F_t *f, hbool_t invalidate)
herr_t
H5F_close (H5F_t *f)
{
herr_t ret_value = FAIL;
FUNC_ENTER (H5F_close, FAIL);
if (-2==(ret_value=H5F_flush (f, TRUE))) {
/*objects are still open, but don't fail yet*/
} else if (ret_value<0) {
HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL,
"can't flush cache");
/* Close all current working groups */
while (H5G_pop (f)>=0) /*void*/;
/* Flush the boot block and caches */
if (H5F_flush (f, TRUE)<0) {
HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL, "can't flush cache");
}
/* Dump debugging info */
if (f->intent & H5F_ACC_DEBUG) H5AC_debug (f);
/* Close files and release resources */
H5F_low_close (f->shared->lf);
H5F_dest (f);
f = H5F_dest (f);
/* Did the H5F_flush() fail because of open objects? */
if (ret_value<0) {
HRETURN_ERROR (H5E_SYM, H5E_CANTFLUSH, ret_value, "objects are open");
}
FUNC_LEAVE (ret_value);
FUNC_LEAVE (SUCCEED);
}
/*--------------------------------------------------------------------------
@ -1537,8 +1515,14 @@ H5F_debug (H5F_t *f, const haddr_t *addr, FILE *stream, intn indent,
"Shared header version number:",
(unsigned)(f->shared->create_parms.sharedheader_ver));
fprintf (stream, "%*sRoot symbol table entry:\n", indent, "");
H5G_ent_debug (f, f->shared->root_sym, stream, indent+3, MAX(0, fwidth-3));
fprintf (stream, "%*s%-*s %s\n", indent, "", fwidth,
"Root symbol table entry:",
f->shared->root_ent ? "" : "(none)");
if (f->shared->root_ent) {
H5G_ent_debug (f, f->shared->root_ent, stream,
indent+3, MAX(0, fwidth-3));
}
FUNC_LEAVE (SUCCEED);
}

@ -331,9 +331,7 @@ typedef struct H5F_file_t {
#ifdef LATER
file_access_temp_t file_access_parms; /* File-access template */
#endif
struct H5G_entry_t *root_sym; /* Root symbol table entry */
uintn nshadows; /* Size of shadow hash table */
struct H5G_hash_t **shadow; /* The shadow hash table */
struct H5G_entry_t *root_ent; /* Root symbol table entry */
} H5F_file_t;
/*

1135
src/H5G.c

File diff suppressed because it is too large Load Diff

@ -364,35 +364,42 @@ H5G_ent_encode (H5F_t *f, uint8 **pp, H5G_entry_t *ent)
/* check arguments */
assert (f);
assert (pp);
assert (ent);
/* encode header */
H5F_encode_length (f, *pp, ent->name_off);
H5F_addr_encode (f, pp, &(ent->header));
UINT32ENCODE (*pp, ent->type);
if (ent) {
/* encode header */
H5F_encode_length (f, *pp, ent->name_off);
H5F_addr_encode (f, pp, &(ent->header));
UINT32ENCODE (*pp, ent->type);
/* encode scratch-pad */
switch (ent->type) {
case H5G_NOTHING_CACHED:
break;
/* encode scratch-pad */
switch (ent->type) {
case H5G_NOTHING_CACHED:
break;
case H5G_CACHED_SDSPACE:
assert (5*4 <= H5G_SIZEOF_SCRATCH);
UINT32ENCODE (*pp, ent->cache.sdspace.ndim);
UINT32ENCODE (*pp, ent->cache.sdspace.dim[0]);
UINT32ENCODE (*pp, ent->cache.sdspace.dim[1]);
UINT32ENCODE (*pp, ent->cache.sdspace.dim[2]);
UINT32ENCODE (*pp, ent->cache.sdspace.dim[3]);
break;
case H5G_CACHED_SDSPACE:
assert (5*4 <= H5G_SIZEOF_SCRATCH);
UINT32ENCODE (*pp, ent->cache.sdspace.ndim);
UINT32ENCODE (*pp, ent->cache.sdspace.dim[0]);
UINT32ENCODE (*pp, ent->cache.sdspace.dim[1]);
UINT32ENCODE (*pp, ent->cache.sdspace.dim[2]);
UINT32ENCODE (*pp, ent->cache.sdspace.dim[3]);
break;
case H5G_CACHED_STAB:
assert (2*H5F_SIZEOF_ADDR (f) <= H5G_SIZEOF_SCRATCH);
H5F_addr_encode (f, pp, &(ent->cache.stab.btree_addr));
H5F_addr_encode (f, pp, &(ent->cache.stab.heap_addr));
break;
case H5G_CACHED_STAB:
assert (2*H5F_SIZEOF_ADDR (f) <= H5G_SIZEOF_SCRATCH);
H5F_addr_encode (f, pp, &(ent->cache.stab.btree_addr));
H5F_addr_encode (f, pp, &(ent->cache.stab.heap_addr));
break;
default:
HDabort();
default:
HDabort();
}
} else {
haddr_t undef;
H5F_encode_length (f, *pp, 0);
H5F_addr_undef (&undef);
H5F_addr_encode (f, pp, &undef);
UINT32ENCODE (*pp, H5G_NOTHING_CACHED);
}
/* fill with zero */
@ -443,11 +450,6 @@ H5G_ent_debug (H5F_t *f, H5G_entry_t *ent, FILE *stream, intn indent,
fprintf (stream, "%*s%-*s %s\n", indent, "", fwidth,
"Dirty:",
ent->dirty ? "Yes" : "No");
fprintf (stream, "%*s%-*s %s\n", indent, "", fwidth,
"Has a shadow:",
H5G_shadow_p (ent)?"This is a shadow!" :
(ent->shadow ? "Yes" : "No"));
fprintf (stream, "%*s%-*s ", indent, "", fwidth,
"Symbol type:");
switch (ent->type) {

@ -15,12 +15,6 @@
*
* Modifications:
*
* 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*/
@ -216,10 +210,10 @@ H5G_node_size (H5F_t *f)
/*-------------------------------------------------------------------------
* Function: H5G_node_create
*
* Purpose: Creates a new empty symbol table. This function is called
* by the B-tree insert function for an empty tree. It is
* also called internally to split a symbol node with
* LT_KEY and RT_KEY null pointers.
* Purpose: Creates a new empty symbol table node. This function is
* called by the B-tree insert function for an empty tree. It
* is also called internally to split a symbol node with LT_KEY
* and RT_KEY null pointers.
*
* Return: Success: SUCCEED. The address of symbol table node is
* returned through the ADDR argument.
@ -285,10 +279,7 @@ H5G_node_create (H5F_t *f, H5B_ins_t op,
/*-------------------------------------------------------------------------
* Function: H5G_node_flush
*
* 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.
* Purpose: Flush a symbol table node to disk.
*
* Return: Success: SUCCEED
*
@ -321,15 +312,9 @@ H5G_node_flush (H5F_t *f, hbool_t destroy, const haddr_t *addr,
assert (sym);
/*
* Synchronize all entries with their corresponding shadow if they have
* one. Also look for dirty entries and set the node dirty flag.
* Look for dirty entries and set the node dirty flag.
*/
for (i=0; i<sym->nsyms; i++) {
if (H5G_shadow_sync (sym->entry+i)<0) {
HRETURN_ERROR (H5E_SYM, H5E_CANTFLUSH, FAIL,
"unable to synchronize symbol table node with open "
"objects");
}
if (sym->entry[i].dirty) sym->dirty = TRUE;
}
@ -366,13 +351,9 @@ H5G_node_flush (H5F_t *f, hbool_t destroy, const haddr_t *addr,
/*
* 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.
* preempted from the cache.
*/
if (destroy) {
for (i=0; i<sym->nsyms; i++) {
H5G_shadow_dissociate (sym->entry+i);
}
sym->entry = H5MM_xfree (sym->entry);
H5MM_xfree (sym);
}
@ -384,8 +365,7 @@ H5G_node_flush (H5F_t *f, hbool_t destroy, const haddr_t *addr,
/*-------------------------------------------------------------------------
* Function: H5G_node_load
*
* Purpose: Loads a symbol table from the file and associates shadows
* with their entries.
* Purpose: Loads a symbol table node from the file.
*
* Return: Success: Ptr to the new table.
*
@ -407,7 +387,6 @@ H5G_node_load (H5F_t *f, const haddr_t *addr, const void *_udata1,
size_t size = 0;
uint8 *buf = NULL;
const uint8 *p = NULL;
const H5G_ac_ud1_t *ac_udata = (const H5G_ac_ud1_t*)_udata1;
H5G_node_t *ret_value = NULL; /*for error handling*/
FUNC_ENTER (H5G_node_load, NULL);
@ -417,7 +396,7 @@ H5G_node_load (H5F_t *f, const haddr_t *addr, const void *_udata1,
*/
assert (f);
assert (addr && H5F_addr_defined (addr));
assert (ac_udata);
assert (!_udata1);
assert (NULL==_udata2);
/*
@ -459,18 +438,6 @@ H5G_node_load (H5F_t *f, const haddr_t *addr, const void *_udata1,
}
buf = H5MM_xfree (buf);
/*
* shadows. If we are running this under the debugger, then the grp_addr
* field of ac_udata might be undefined. If that's the case, then we
* don't try to associate any shadows with this symbol table node.
*/
if (H5F_addr_defined (&(ac_udata->grp_addr)) &&
H5G_shadow_assoc_node (f, sym, ac_udata)<0) {
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, NULL,
"unable to associate symbol table node with open "
"objects");
}
ret_value = sym;
@ -609,8 +576,8 @@ H5G_node_cmp3 (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key)
* entry field. Otherwise the entry is copied from the
* UDATA entry field to the symbol table.
*
* Return: Success: SUCCEED if found and data returned through the
* UDATA pointer.
* Return: Success: SUCCEED if found and data returned through
* the UDATA pointer.
*
* Failure: FAIL if not found.
*
@ -627,7 +594,6 @@ H5G_node_found (H5F_t *f, const haddr_t *addr, const void *_lt_key,
void *_udata, const void *_rt_key)
{
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;
@ -642,13 +608,11 @@ H5G_node_found (H5F_t *f, const haddr_t *addr, const void *_lt_key,
assert (addr && H5F_addr_defined (addr));
assert (bt_udata);
ac_udata.grp_addr = bt_udata->grp_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, &ac_udata, NULL))) {
if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, NULL, NULL))) {
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL,
"unable to protect symbol table node");
}
@ -680,10 +644,7 @@ H5G_node_found (H5F_t *f, const haddr_t *addr, const void *_lt_key,
* The caller is querying the symbol entry. Return just a pointer to
* the entry. The pointer is valid until the next call to H5AC.
*/
H5G_shadow_sync (sn->entry+idx);
bt_udata->entry_ptr = sn->entry+idx;
bt_udata->node_addr = *addr;
bt_udata->node_ptr = sn;
bt_udata->ent = sn->entry[idx];
break;
default:
@ -694,16 +655,9 @@ H5G_node_found (H5F_t *f, const haddr_t *addr, const void *_lt_key,
ret_value = SUCCEED;
done:
/*
* Don't unprotect the symbol table entry if we're returning success since
* this might invalidate the bt_udata->entry_ptr and bt_udata->node_ptr
* pointers. Instead, we unprotect it in H5G_stab_find().
*/
if (ret_value<0) {
if (sn && H5AC_unprotect (f, H5AC_SNODE, addr, sn)<0) {
HRETURN_ERROR (H5E_SYM, H5E_PROTECT, FAIL,
"unable to release symbol table node");
}
if (sn && H5AC_unprotect (f, H5AC_SNODE, addr, sn)<0) {
HRETURN_ERROR (H5E_SYM, H5E_PROTECT, FAIL,
"unable to release symbol table node");
}
FUNC_LEAVE (ret_value);
@ -744,10 +698,6 @@ 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 H5B_ins_t
@ -761,15 +711,12 @@ H5G_node_insert (H5F_t *f, const haddr_t *addr,
H5G_node_key_t *rt_key = (H5G_node_key_t *)_rt_key;
H5G_bt_ud1_t *bt_udata = (H5G_bt_ud1_t *)_udata;
H5G_ac_ud1_t ac_udata;
H5G_node_t *sn=NULL, *snrt=NULL;
size_t offset; /*offset of name in heap*/
const char *s;
intn idx=-1, cmp=1;
intn lt=0, rt; /*binary search cntrs */
intn i;
H5B_ins_t ret_value = H5B_INS_ERROR;
H5G_shadow_t *shadow = NULL;
H5G_node_t *insert_into=NULL; /*node that gets new entry*/
haddr_t insert_addr; /*address of that node */
@ -785,17 +732,10 @@ H5G_node_insert (H5F_t *f, const haddr_t *addr,
assert (bt_udata);
assert (new_node);
/* Init return value */
H5F_addr_undef (&(bt_udata->node_addr));
bt_udata->node_ptr = NULL;
bt_udata->entry_ptr = NULL;
/*
* Load the symbol node.
*/
ac_udata.grp_addr = bt_udata->grp_addr;
ac_udata.heap_addr = bt_udata->heap_addr;
if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, &ac_udata, NULL))) {
if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, NULL, NULL))) {
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR,
"unable to protect symbol table node");
}
@ -831,7 +771,7 @@ H5G_node_insert (H5F_t *f, const haddr_t *addr,
*/
offset = H5H_insert (f, &(bt_udata->heap_addr), HDstrlen(bt_udata->name)+1,
bt_udata->name);
bt_udata->entry.name_off = offset;
bt_udata->ent.name_off = offset;
if (offset<=0) {
HGOTO_ERROR (H5E_SYM, H5E_CANTINSERT, H5B_INS_ERROR,
"unable to insert symbol name into heap");
@ -851,7 +791,7 @@ H5G_node_insert (H5F_t *f, const haddr_t *addr,
HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, H5B_INS_ERROR,
"unable to split symbol table node");
}
if (NULL==(snrt=H5AC_find (f, H5AC_SNODE, new_node, &ac_udata, NULL))) {
if (NULL==(snrt=H5AC_find (f, H5AC_SNODE, new_node, NULL, NULL))) {
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR,
"unable to split symbol table node");
}
@ -860,13 +800,6 @@ H5G_node_insert (H5F_t *f, const haddr_t *addr,
snrt->nsyms = H5G_NODE_K(f);
snrt->dirty = TRUE;
/* 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));
@ -899,55 +832,18 @@ H5G_node_insert (H5F_t *f, const haddr_t *addr,
}
}
/* Adjust shadows */
for (i=idx; i<insert_into->nsyms; i++) {
if (insert_into->entry[i].shadow) {
insert_into->entry[i].shadow->main = insert_into->entry + i + 1;
}
}
if (bt_udata->entry.shadow) {
H5G_shadow_move (f, bt_udata->entry.shadow,
bt_udata->name,
insert_into->entry + idx,
&(bt_udata->grp_addr));
}
/* Move entries */
HDmemmove (insert_into->entry + idx + 1,
insert_into->entry + idx,
(insert_into->nsyms-idx) * sizeof(H5G_entry_t));
insert_into->entry[idx] = bt_udata->entry;
insert_into->entry[idx].name_off = offset;
insert_into->entry[idx] = bt_udata->ent;
insert_into->entry[idx].dirty = TRUE;
insert_into->nsyms += 1;
/* Update udata return values */
bt_udata->node_addr = insert_addr;
bt_udata->node_ptr = insert_into;
bt_udata->entry_ptr = insert_into->entry + idx;
done:
if (ret_value<0) {
/* failing... */
if (sn && H5AC_unprotect (f, H5AC_SNODE, addr, sn)<0) {
HRETURN_ERROR (H5E_SYM, H5E_PROTECT, H5B_INS_ERROR,
"unable to release symbol table node");
}
} else if (insert_into!=sn) {
/* unprotect the first node and protect the return value */
if (H5AC_unprotect (f, H5AC_SNODE, addr, sn)<0) {
HRETURN_ERROR (H5E_SYM, H5E_PROTECT, H5B_INS_ERROR,
"unable to release symbol table node");
}
if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, &insert_addr, &ac_udata,
NULL))) {
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR,
"unable to protect symbol table node");
}
bt_udata->node_ptr = sn;
bt_udata->entry_ptr = sn->entry + idx;
} else {
/* keep the node protected until we get back to H5G_stab_insert() */
if (sn && H5AC_unprotect (f, H5AC_SNODE, addr, sn)<0) {
HRETURN_ERROR (H5E_SYM, H5E_PROTECT, H5B_INS_ERROR,
"unable to release symbol table node");
}
FUNC_LEAVE (ret_value);
@ -980,7 +876,6 @@ H5G_node_list (H5F_t *f, const haddr_t *addr, void *_udata)
intn i;
const char *s;
herr_t ret_value = FAIL;
H5G_ac_ud1_t ac_udata;
FUNC_ENTER (H5G_node_list, FAIL);
@ -991,9 +886,7 @@ H5G_node_list (H5F_t *f, const haddr_t *addr, void *_udata)
assert (addr && H5F_addr_defined (addr));
assert (bt_udata);
ac_udata.grp_addr = bt_udata->grp_addr;
ac_udata.heap_addr = bt_udata->heap_addr;
if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, &ac_udata, NULL))) {
if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, NULL, NULL))) {
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL,
"unable to protect symbol table node");
}
@ -1013,7 +906,6 @@ H5G_node_list (H5F_t *f, const haddr_t *addr, void *_udata)
*/
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];
}
}
@ -1065,11 +957,10 @@ herr_t
H5G_node_debug (H5F_t *f, const haddr_t *addr, FILE *stream, intn indent,
intn fwidth, const haddr_t *heap)
{
int i, acc;
int i;
H5G_node_t *sn = NULL;
herr_t status;
const char *s;
H5G_ac_ud1_t ac_udata;
FUNC_ENTER (H5G_node_debug, FAIL);
@ -1082,23 +973,12 @@ H5G_node_debug (H5F_t *f, const haddr_t *addr, FILE *stream, intn indent,
assert (indent>=0);
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 UNDEF as the group 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.
*/
H5F_addr_undef (&(ac_udata.grp_addr));
ac_udata.heap_addr = *heap;
/*
* If we couldn't load the symbol table node, then try loading the
* B-tree node.
*/
if (NULL==(sn=H5AC_protect(f, H5AC_SNODE, addr, &ac_udata, NULL))) {
if (NULL==(sn=H5AC_protect(f, H5AC_SNODE, addr, NULL, NULL))) {
H5ECLEAR; /*discard that error*/
status = H5B_debug (f, addr, stream, indent, fwidth, H5B_SNODE, NULL);
if (status<0) {
@ -1116,11 +996,6 @@ H5G_node_debug (H5F_t *f, const 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;
@ -1134,13 +1009,9 @@ H5G_node_debug (H5F_t *f, const haddr_t *addr, FILE *stream, intn indent,
s);
}
H5G_ent_debug (f, sn->entry+i, stream, indent, fwidth);
fprintf (stream, "%*s%-*s %s\n", indent+3, "", MAX (0, fwidth-3),
"Shadow:",
sn->entry[i].shadow ? "Yes":"No");
}
H5AC_unprotect (f, H5AC_SNODE, addr, sn);
H5AC_flush (f, H5AC_SNODE, addr, TRUE); /*see note above*/
FUNC_LEAVE (SUCCEED);
}

@ -25,21 +25,6 @@
#define H5G_NODE_SIZEOF_HDR(F) (H5G_NODE_SIZEOF_MAGIC + 4)
#define H5G_DEFAULT_ROOT_SIZE 32
/*
* A symbol table entry. The two important fields are `name_off' and
* `header'. The remaining fields are used for caching information that
* also appears in the object header to which this symbol table entry
* points.
*/
struct H5G_entry_t {
hbool_t dirty; /*entry out-of-date? */
size_t name_off; /*offset of name within name heap */
haddr_t header; /*file address of object header */
H5G_type_t type; /*type of information cached */
H5G_cache_t cache; /*cached data from object header */
H5G_shadow_t *shadow; /*optional ptr to the shadow */
};
/*
* A 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
@ -52,23 +37,6 @@ typedef struct H5G_node_t {
H5G_entry_t *entry; /*array of symbol table entries */
} H5G_node_t;
/*
* 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 grp_addr; /*hdr addr for group 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 */
};
/*
* Each key field of the B-link tree that points to symbol table
* nodes consists of this structure...
@ -77,14 +45,24 @@ typedef struct H5G_node_key_t {
size_t offset; /*offset into heap for name */
} H5G_node_key_t;
/*
* A group handle passed around through layers of the library within and
* above the H5G layer.
*/
struct H5G_t {
H5F_t *file; /*file containing group */
int nref; /*open reference count */
H5G_entry_t ent; /*info about the group */
};
/*
* Each file has a stack of open groups with the latest entry on the
* stack the current working group. If the stack is empty then the
* current working group is the root object.
*/
typedef struct H5G_cwgstk_t {
H5G_entry_t *handle; /*a handle to an open group */
struct H5G_cwgstk_t *next; /*next item (earlier) on stack */
H5G_t *grp; /*a handle to an open group */
struct H5G_cwgstk_t *next; /*next item (earlier) on stack */
} H5G_cwgstk_t;
/*
@ -106,16 +84,10 @@ typedef struct H5G_bt_ud1_t {
/* downward */
H5G_oper_t operation; /*what operation to perform */
const char *name; /*points to temporary memory */
haddr_t grp_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 and INSERT */
haddr_t node_addr; /*address of node for this entry */
H5G_node_t *node_ptr; /*ptr to the node containing the entry */
H5G_entry_t *entry_ptr; /*ptr into cached symbol table node */
/* downward for INSERT, upward for FIND */
H5G_entry_t ent; /*entry to insert into table */
} H5G_bt_ud1_t;
@ -129,7 +101,6 @@ typedef struct H5G_bt_ud2_t {
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 grp_addr; /*symbol table header address */
haddr_t heap_addr; /*heap address */
/* upward */
@ -142,14 +113,6 @@ typedef struct H5G_bt_ud2_t {
*/
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 grp_addr;
} H5G_ac_ud1_t;
/* The cache subclass */
extern const H5AC_class_t H5AC_SNODE[1];
@ -158,30 +121,14 @@ extern const H5AC_class_t H5AC_SNODE[1];
* functions that understand names are exported to the rest of
* the library and appear in H5Gprivate.h.
*/
herr_t H5G_stab_create (H5F_t *f, H5G_entry_t *self, size_t init);
H5G_entry_t *H5G_stab_find (H5F_t *f, const haddr_t *addr, H5G_entry_t *self,
const char *name);
H5G_entry_t *H5G_stab_insert (H5F_t *f, H5G_entry_t *self,
const char *name, H5G_entry_t *ent);
herr_t H5G_stab_create (H5F_t *f, size_t size_hint, H5G_entry_t *ent/*out*/);
herr_t H5G_stab_find (H5F_t *f, H5G_entry_t *grp_ent, const char *name,
H5G_entry_t *obj_ent/*out*/);
herr_t H5G_stab_insert (H5F_t *f, H5G_entry_t *grp_ent, const char *name,
H5G_entry_t *obj_ent);
intn H5G_stab_list (H5F_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 (H5F_t *f, H5G_entry_t *grp,
H5G_entry_t *ent);
herr_t H5G_shadow_close (H5F_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 (H5F_t *f, H5G_node_t *sym,
const H5G_ac_ud1_t *ac_udata);
H5G_shadow_t *H5G_shadow_list (H5F_t *f, const haddr_t *stab_header_addr);
herr_t H5G_shadow_move (H5F_t *f, H5G_shadow_t *shadow,
const char *new_name, H5G_entry_t *new_entry,
const haddr_t *grp_addr);
/*
* Functions that understand symbol table entries.
*/

@ -24,11 +24,7 @@
#include <H5Fprivate.h>
/*
* FEATURE: If this macro is defined then H5G_shadow_check() is occassionally
* (actually, quite often) called to check the consistency of the
* shadow table. If there's something wrong with the table then
* abort() is called. Shadow table checking is a rather expensive
* operation.
* Define this to enable debugging.
*/
#ifdef NDEBUG
# undef H5G_DEBUG
@ -37,7 +33,6 @@
#define H5G_NODE_MAGIC "SNOD" /*symbol table node magic number */
#define H5G_NODE_SIZEOF_MAGIC 4 /*sizeof symbol node magic number */
#define H5G_NO_CHANGE (-1) /*see H5G_ent_modified() */
#define H5G_NSHADOWS 10331 /*default size of shadow hash table */
/*
* The disk size for a symbol table entry...
@ -78,24 +73,33 @@ typedef union H5G_cache_t {
} 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.
* 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_shadow_t H5G_shadow_t;
typedef struct H5G_entry_t H5G_entry_t;
typedef struct H5G_entry_t {
hbool_t dirty; /*entry out-of-date? */
size_t name_off; /*offset of name within name heap */
haddr_t header; /*file address of object header */
H5G_type_t type; /*type of information cached */
H5G_cache_t cache; /*cached data from object header */
} H5G_entry_t;
typedef struct H5G_t H5G_t;
/*
* Library prototypes... These are the ones that other packages routinely
* call.
*/
H5G_entry_t *H5G_new (H5F_t *f, const char *name, size_t size_hint);
herr_t H5G_set (H5F_t *f, const char *name);
herr_t H5G_push (H5F_t *f, const char *name);
H5G_t *H5G_create (H5F_t *f, const char *name, size_t size_hint);
H5G_t *H5G_open (H5F_t *f, const char *name);
H5G_t *H5G_reopen (H5G_t *grp);
herr_t H5G_close (H5G_t *grp);
herr_t H5G_set (H5F_t *f, H5G_t *grp);
herr_t H5G_push (H5F_t *f, H5G_t *grp);
herr_t H5G_pop (H5F_t *f);
H5G_entry_t *H5G_create (H5F_t *f, const char *name, size_t ohdr_hint);
H5G_entry_t *H5G_open (H5F_t *f, const char *name);
herr_t H5G_close (H5F_t *f, H5G_entry_t *ent);
herr_t H5G_insert (H5F_t *f, const char *name, H5G_entry_t *ent);
herr_t H5G_find (H5F_t *f, const char *name, H5G_entry_t *grp_ent,
H5G_entry_t *ent);
herr_t H5G_ent_encode (H5F_t *f, uint8 **pp, H5G_entry_t *ent);
@ -107,11 +111,6 @@ herr_t H5G_ent_decode (H5F_t *f, const uint8 **pp, H5G_entry_t *ent);
herr_t H5G_node_debug (H5F_t *f, const haddr_t *addr, FILE *stream,
intn indent, intn fwidth, const haddr_t *heap);
/*
* These functions operate on shadow entries.
*/
herr_t H5G_shadow_flush (H5F_t *f, hbool_t invalidate);
/*
* These functions operate on symbol table entries. They're used primarily
* in the H5O package where header messages are cached in symbol table

@ -27,9 +27,12 @@
extern "C" {
#endif
herr_t H5Gnew (hid_t file, const char *name, size_t size_hint);
herr_t H5Gset (hid_t file, const char *name);
herr_t H5Gpush (hid_t file, const char *name);
hid_t H5Gcreate (hid_t file_id, const char *name, size_t size_hint);
hid_t H5Gopen (hid_t file_id, const char *name);
herr_t H5Gclose (hid_t grp_id);
herr_t H5Gset (hid_t file, hid_t grp_id);
herr_t H5Gpush (hid_t file, hid_t grp_id);
herr_t H5Gpop (hid_t file);
#ifdef __cplusplus

@ -1,810 +0,0 @@
/*
* 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
/* Interface initialization */
static hbool_t interface_initialize_g = FALSE;
#define INTERFACE_INIT NULL
typedef struct H5G_hash_t {
haddr_t grp_addr;
H5G_shadow_t *head;
struct H5G_hash_t *next;
struct H5G_hash_t *prev;
} H5G_hash_t;
/*-------------------------------------------------------------------------
* Function: H5G_shadow_check
*
* Purpose: Checks the shadow data structures for validity. This is a
* debugging function only--it aborts on failure!
*
* Return: void
*
* Programmer: Robb Matzke
* Sunday, September 21, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
#ifdef H5G_DEBUG
static void
H5G_shadow_check (H5F_t *f)
{
H5G_hash_t *hash=NULL;
H5G_shadow_t *shadow=NULL, *prev_shadow=NULL;
uintn idx;
hbool_t shadow_error=FALSE;
uintn nerrors=0;
static int ncalls=0;
if (0==ncalls++) {
fprintf (stderr, "HDF5-DIAG: debugging group shadows (expensive)\n");
}
for (idx=0; idx<f->shared->nshadows; idx++) {
for (hash=f->shared->shadow[idx]; hash; hash=hash->next) {
for (shadow=hash->head,prev_shadow=NULL;
shadow;
shadow=shadow->next) {
shadow_error = FALSE;
/* Each shadow has a name and the names are in order */
if (!shadow->name) {
fprintf (stderr, "name=NULL, ");
shadow_error = TRUE;
}
if (prev_shadow && strcmp (prev_shadow->name, shadow->name)>=0) {
fprintf (stderr, "names not sorted, ");
shadow_error = TRUE;
}
/*
* Valid group addresses. The root (which is hashed to entry
* zero) always has an undefined group address.
*/
if (idx==0 &&
!H5F_addr_defined (&(shadow->grp_addr)) &&
!H5F_addr_defined (&(hash->grp_addr))) {
/*
* The shadow for the root object always has an undefined
* group address.
*/
} else if (!H5F_addr_defined (&(shadow->grp_addr)) ||
!H5F_addr_defined (&(hash->grp_addr))) {
/*
* Non-root objects must have defined group addresses.
*/
fprintf (stderr, "grp_addr=");
H5F_addr_print (stderr, &(shadow->grp_addr));
fprintf (stderr, ", hash_addr=");
H5F_addr_print (stderr, &(hash->grp_addr));
fprintf (stderr, ", ");
shadow_error = TRUE;
} else if (H5F_addr_ne (&(shadow->grp_addr), &(hash->grp_addr))) {
/*
* Something's wrong with the data structure. The hash
* address should always be the same as the shadow group
* address.
*/
fprintf (stderr, "grp_addr=");
H5F_addr_print (stderr, &(shadow->grp_addr));
fprintf (stderr, " (should be ");
H5F_addr_print (stderr, &(hash->grp_addr));
fprintf (stderr, "), ");
shadow_error = TRUE;
}
/* Linked to symbol table entry */
if (shadow->main && shadow!=shadow->main->shadow) {
fprintf (stderr, "entry linkage problem, ");
shadow_error = TRUE;
}
/* Shadow linked list is consistent */
if (shadow->prev && prev_shadow!=shadow->prev) {
fprintf (stderr, "shadow linked list problem, ");
shadow_error = TRUE;
}
prev_shadow = shadow;
/* If an error occurred then print other info */
if (shadow_error) {
fprintf (stderr, "idx=%u, shadow=0x%08lx, grp_addr=",
idx, (unsigned long)shadow);
H5F_addr_print (stderr, &(shadow->grp_addr));
fprintf (stderr, "\n");
nerrors++;
}
}
}
}
if (nerrors) {
fprintf (stderr, "Error in H5G_shadow_check, call %d\n", ncalls);
abort ();
}
}
#endif
/*-------------------------------------------------------------------------
* 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, 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, 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, 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) {
HRETURN_ERROR (H5E_SYM, H5E_NOTCACHED, FAIL,
"main entry is not cached");
}
*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 GRP_ADDR.
*
* Return: Success: Ptr shadow list or null.
*
* Failure: NULL
*
* Programmer: Robb Matzke
* Wednesday, September 17, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
H5G_shadow_t *
H5G_shadow_list (H5F_t *f, const haddr_t *grp_addr)
{
uintn idx = H5F_addr_hash (grp_addr, f->shared->nshadows);
H5G_hash_t *bucket = NULL;
FUNC_ENTER (H5G_shadows, NULL);
for (bucket=f->shared->shadow[idx]; bucket; bucket=bucket->next) {
if (0==idx &&
!H5F_addr_defined (&(bucket->grp_addr)) &&
!H5F_addr_defined (grp_addr)) {
HRETURN (bucket->head);/*shadow list for root object*/
} else if (H5F_addr_eq (&(bucket->grp_addr), grp_addr)) {
HRETURN (bucket->head);/*shadow list for other objects*/
}
}
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 (H5F_t *f, H5G_node_t *sym, const H5G_ac_ud1_t *ac_udata)
{
H5G_shadow_t *shadow = NULL;
const char *s = NULL;
intn i = 0;
haddr_t heap_addr;
FUNC_ENTER (H5G_shadow_assoc_node, FAIL);
/* Check arguments */
assert (f); /* The file */
assert (sym); /* The symbol table node */
assert (ac_udata); /* The symbol table header info */
#ifdef H5G_DEBUG
H5G_shadow_check (f);
#endif
if ((shadow=H5G_shadow_list (f, &(ac_udata->grp_addr)))) {
heap_addr = ac_udata->heap_addr;
while (i<sym->nsyms && shadow) {
/* Advance the Entry ptr until it gets to the next shadow. */
while (i<sym->nsyms &&
(s=H5H_peek (f, &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;
i++;
shadow = shadow->next;
}
}
}
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.
*
* If ENT refers to the root object, then GRP can be a null
* pointer or a pointer to an entry with an invalid header
* address.
*
* Return: Success: Handle to open object
*
* Failure: NULL
*
* Programmer: Robb Matzke
* Thursday, September 18, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
H5G_entry_t *
H5G_shadow_open (H5F_t *f, H5G_entry_t *grp, 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, *prev_ent = NULL;
uintn idx;
H5O_name_t name_mesg = {NULL};
H5G_entry_t *ret_value = NULL;
haddr_t grp_header;
FUNC_ENTER (H5G_shadow_open, NULL);
/* check args */
assert (f);
assert (ent);
if ((shadow = ent->shadow)) {
/* Object is already open. Open it again */
shadow->nrefs += 1;
HRETURN (&(shadow->entry));
}
/*
* If the root object is being opened then the GRP argument is optional.
* If it's supplied then it had better have an undefined header address.
* For all other objects the GRP argument is required to have a valid
* header address.
*/
if (ent==f->shared->root_sym) {
assert (!grp || !H5F_addr_defined (&(grp->header)));
H5F_addr_undef (&grp_header);
idx = 0;
} else {
assert (grp && H5F_addr_defined (&(grp->header)));
grp_header = grp->header;
idx = H5F_addr_hash (&grp_header, f->shared->nshadows);
}
/*
* Build the new shadow.
*/
shadow = H5MM_xcalloc (1, sizeof(H5G_shadow_t));
ent->shadow = shadow;
shadow->main = ent;
shadow->nrefs = 1;
shadow->entry = *ent;
shadow->entry.dirty = FALSE;
shadow->grp_addr = grp_header;
/*
* Give the shadow a name. Obtaining the name might remove ENT from the
* cache, so we're careful not to reference it again.
*/
if (ent==f->shared->root_sym) {
/*
* We're opening the root entry. Get the name from the name message or
* use a generic default.
*/
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, grp, H5O_STAB, 0, &stab)) {
HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, NULL,
"unable to read symbol table object header message");
}
if (NULL==(s=H5H_peek (f, &(stab.heap_addr), ent->name_off))) {
HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, NULL,
"unable to read symbol name");
}
shadow->name = H5MM_xstrdup (s);
}
ent = NULL; /*previous ops might have invalidated it*/
/*
* Link it into the shadow heap
*/
for (hash=f->shared->shadow[idx]; hash; hash=hash->next) {
if (0==idx &&
!H5F_addr_defined (&(hash->grp_addr)) &&
!H5F_addr_defined (&grp_header)) {
break; /*shadow list for root object*/
} else if (H5F_addr_eq (&(hash->grp_addr), &grp_header)) {
break; /*shadow list for other objects*/
}
}
if (!hash) {
hash = H5MM_xcalloc (1, sizeof(H5G_hash_t));
hash->grp_addr = grp_header;
hash->next = f->shared->shadow[idx];
f->shared->shadow[idx] = hash;
if (hash->next) hash->next->prev = hash;
}
if (hash->head) {
for (hash_ent=hash->head,prev_ent=NULL;
hash_ent;
hash_ent=hash_ent->next) {
if (strcmp (shadow->name, hash_ent->name)<0) break;
prev_ent = hash_ent;
}
if (hash_ent) {
/* Insert SHADOW before HASH_ENT */
if (hash_ent->prev) hash_ent->prev->next = shadow;
else hash->head = shadow;
shadow->prev = hash_ent->prev;
shadow->next = hash_ent;
hash_ent->prev = shadow;
} else {
/* Append SHADOW to list */
assert (prev_ent && NULL==prev_ent->next);
prev_ent->next = shadow;
shadow->prev = prev_ent;
}
} else {
/* Insert shadow at head of list */
shadow->next = hash->head;
if (hash->head) hash->head->prev = shadow;
hash->head = shadow;
}
#ifdef H5G_DEBUG
H5G_shadow_check (f);
#endif
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 (H5F_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, 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->grp_addr), NULL, shadow->name)) {
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL,
"unable to find shadow name in symbol table");
}
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 -- if this is a shadow of the root object
* then use zero for the hash value. The root object always has an
* undefined group address.
*/
if (H5F_addr_defined (&(shadow->grp_addr))) {
idx = H5F_addr_hash (&(shadow->grp_addr), f->shared->nshadows);
} else {
idx = 0;
}
for (hash=f->shared->shadow[idx]; hash; hash=hash->next) {
if (0==idx &&
!H5F_addr_defined (&(hash->grp_addr)) &&
!H5F_addr_defined (&(shadow->grp_addr))) {
break; /*shadow list for root object*/
} else if (H5F_addr_eq (&(hash->grp_addr), &(shadow->grp_addr))) {
break; /*shadow list for other objects*/
}
}
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 f->shared->shadow[idx] = hash->next;
if (hash->next) hash->next->prev = hash->prev;
H5MM_xfree (hash);
}
}
FUNC_LEAVE (SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5G_shadow_move
*
* Purpose: Moves the SHADOW for some entry to correspond to a
* NEW_ENTRY. The GRP_ADDR is the address for the group
* which contains NEW_ENTRY.
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Friday, September 19, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5G_shadow_move (H5F_t *f, H5G_shadow_t *shadow, const char *new_name,
H5G_entry_t *new_entry, const haddr_t *grp_addr)
{
H5G_hash_t *hash;
uintn idx;
FUNC_ENTER (H5G_shadow_move, FAIL);
assert (shadow);
assert (new_entry);
assert (grp_addr && H5F_addr_defined (grp_addr));
if (!H5F_addr_defined (&(shadow->grp_addr))) {
/*
* We're moving the shadow for the root object. This simplifies things
* greatly since it implies that this is the only shadow currently
* defined for the entire file.
*/
idx = H5F_addr_hash (grp_addr, f->shared->nshadows);
assert (NULL==f->shared->shadow[idx]); /*Nothing at new idx... */
hash = f->shared->shadow[0];
assert (hash); /*..but root idx has something. */
assert (!H5F_addr_defined (&(hash->grp_addr)));/*..it's the root obj*/
assert (NULL==hash->next); /*..and just that */
assert (hash->head==shadow); /*..and exactly that */
/* Move root entry to new hash bucket */
f->shared->shadow[idx] = hash;
f->shared->shadow[0] = NULL;
hash->grp_addr = *grp_addr;
/* Associate SHADOW with NEW_ENTRY */
shadow->grp_addr = *grp_addr;
shadow->main = new_entry;
new_entry->shadow = shadow;
/* Give the shadow a new name */
H5MM_xfree (shadow->name);
shadow->name = H5MM_xstrdup (new_name);
} else {
/*
* Other shadows never move.
*/
assert (H5F_addr_eq (&(shadow->grp_addr), grp_addr));
shadow->main = new_entry;
new_entry->shadow = shadow;
}
FUNC_LEAVE (SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5G_shadow_flush
*
* Purpose: Flush all open object information to the main cache.
*
* Return: Success: SUCCEED
*
* Failure: FAIL if INVALIDATE is non-zero and there are
* open objects.
*
* Programmer: Robb Matzke
* Friday, September 19, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5G_shadow_flush (H5F_t *f, hbool_t invalidate)
{
uintn idx;
H5G_hash_t *hash = NULL;
H5G_shadow_t *shadow = NULL;
intn nfound=0;
FUNC_ENTER (H5G_shadow_flush, FAIL);
for (idx=0; idx<f->shared->nshadows; idx++) {
for (hash=f->shared->shadow[idx]; hash; hash=hash->next) {
for (shadow=hash->head; shadow; shadow=shadow->next) {
/*
* If the shadow is dirty, then transfer the shadow info to the
* symbol table node.
*/
if (shadow->entry.dirty) {
if (0==idx && !H5F_addr_defined (&(shadow->grp_addr)) &&
shadow->main==f->shared->root_sym) {
/*
* The shadow for the root entry gets copied back into the
* root symbol
*/
*f->shared->root_sym = shadow->entry;
} else {
/*
* Other shadows get copied back into the symbol table.
*/
if (!shadow->main &&
NULL==H5G_stab_find (f, &(shadow->grp_addr), NULL,
shadow->name)) {
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL,
"unable to find shadow name in symbol "
"table");
}
assert (shadow->main);
*(shadow->main) = shadow->entry;
shadow->entry.dirty = FALSE;
nfound++;
}
}
#ifndef NDEBUG
/*
* This is usually a bad thing--an hdf5 programmer forgot to close
* some object before closing the file. Since this is hard to
* debug, we'll be nice and print the names here. We don't know
* the full name, but we'll print the relative file address
* of the object header for the group that contains the open
* object.
*/
if (invalidate) {
fprintf (stderr, "HDF5-DIAG: warning: open object <");
H5F_addr_print (stderr, &(shadow->grp_addr));
fprintf (stderr, ">/%s", shadow->name);
if (shadow->nrefs>1) {
fprintf (stderr, " (%d times)", shadow->nrefs);
}
fputc ('\n', stderr);
}
#endif
}
}
}
if (invalidate && nfound) {
/*
* No clean easy way to do this, just leak the memory. If we free a
* shadow and then something else tries to access it (perhaps to close
* it) then they trample on freed memory.
*/
HRETURN_ERROR (H5E_SYM, H5E_UNSUPPORTED, FAIL,
"leaking memory due to shadow errors");
}
FUNC_LEAVE (SUCCEED);
}

@ -26,21 +26,14 @@ static hbool_t interface_initialize_g = FALSE;
*
* Purpose: Creates a new empty symbol table (object header, name heap,
* and B-tree). The caller can specify an initial size for the
* name heap.
* name heap. The object header of the group is opened for
* write access.
*
* In order for the B-tree to operate correctly, the first
* item in the heap is the empty string, and must appear at
* heap offset zero.
*
* Errors:
* INTERNAL CANTINIT B-tree's won't work if the first
* name isn't at the beginning of the
* heap.
* SYM CANTINIT Can't create B-tree.
* SYM CANTINIT Can't create header.
* SYM CANTINIT Can't create heap.
* SYM CANTINIT Can't create message.
* SYM CANTINIT Can't initialize heap.
*
* Return: Success: SUCCEED
*
@ -55,10 +48,9 @@ static hbool_t interface_initialize_g = FALSE;
*-------------------------------------------------------------------------
*/
herr_t
H5G_stab_create (H5F_t *f, H5G_entry_t *self, size_t init)
H5G_stab_create (H5F_t *f, size_t init, H5G_entry_t *self/*out*/)
{
size_t name; /*offset of "" name */
haddr_t addr; /*object header address */
H5O_stab_t stab; /*symbol table message */
FUNC_ENTER (H5G_stab_create, FAIL);
@ -77,14 +69,11 @@ H5G_stab_create (H5F_t *f, H5G_entry_t *self, size_t init)
if ((name = H5H_insert (f, &(stab.heap_addr), 1, "")<0)) {
HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, "can't initialize heap");
}
if (0!=name) {
/*
* B-tree's won't work if the first name isn't at the beginning
* of the heap.
*/
HRETURN_ERROR (H5E_INTERNAL, H5E_CANTINIT, FAIL,
"internal error (heap doesn't begin at zero)");
}
/*
* B-tree's won't work if the first name isn't at the beginning
* of the heap.
*/
assert (0==name);
/* Create the B-tree */
if (H5B_create (f, H5B_SNODE, NULL, &(stab.btree_addr)/*out*/)<0) {
@ -96,14 +85,13 @@ H5G_stab_create (H5F_t *f, H5G_entry_t *self, size_t init)
* since nothing refers to it yet. The link count will be
* incremented if the object is added to the group directed graph.
*/
if (H5O_create (f, 0, 4+2*H5F_SIZEOF_ADDR(f), &addr/*out*/)<0) {
if (H5O_create (f, 4+2*H5F_SIZEOF_ADDR(f), self/*out*/)<0) {
HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, "can't create header");
}
/* insert the symbol table message */
memset (self, 0, sizeof(H5G_entry_t));
self->header = addr;
if (H5O_modify(f, NO_ADDR, self, H5O_STAB, H5O_NEW_MESG, &stab)<0) {
if (H5O_modify (f, self, H5O_STAB, H5O_NEW_MESG, &stab)<0) {
H5O_close (f, self);
HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, "can't create message");
}
@ -115,23 +103,14 @@ H5G_stab_create (H5F_t *f, H5G_entry_t *self, size_t init)
* Function: H5G_stab_find
*
* Purpose: Finds a symbol named NAME in the symbol table whose
* description is stored in SELF in file F and returns a
* pointer to the symbol table entry. SELF is optional if the
* symbol table address is supplied through ADDR.
* description is stored in GRP_ENT in file F and returns its
* symbol table entry through OBJ_ENT (which is optional).
*
* Errors:
* SYM BADMESG Can't read message.
* SYM NOTFOUND Not found.
*
* Return: Success: Pointer to the symbol table entry.
* The pointer is intended for immediate
* read-only access since it points
* directly to an entry in a cached
* symbol table node. The pointer is
* guaranteed to be valid only until the
* next call to one of the H5AC functions.
* Return: Success: SUCCEED
*
* Failure: NULL
* Failure: FAIL
*
* Programmer: Robb Matzke
* matzke@llnl.gov
@ -141,75 +120,50 @@ H5G_stab_create (H5F_t *f, H5G_entry_t *self, size_t init)
*
*-------------------------------------------------------------------------
*/
H5G_entry_t *
H5G_stab_find (H5F_t *f, const haddr_t *addr, H5G_entry_t *self,
const char *name)
herr_t
H5G_stab_find (H5F_t *f, H5G_entry_t *grp_ent, const char *name,
H5G_entry_t *obj_ent/*out*/)
{
H5G_bt_ud1_t udata; /*data to pass through B-tree */
H5O_stab_t stab; /*symbol table message */
FUNC_ENTER (H5G_stab_find, NULL);
FUNC_ENTER (H5G_stab_find, FAIL);
/* Check arguments */
assert (f);
assert (!addr || H5F_addr_defined (addr));
if (!addr && (!self || !H5F_addr_defined (&(self->header)))) {
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL, "bad address");
}
if (!name || !*name) {
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL, "no name");
}
if (!addr) addr = &(self->header);
assert (grp_ent);
assert (name && *name);
/* set up the udata */
if (NULL==H5O_read (f, addr, self, H5O_STAB, 0, &stab)) {
HRETURN_ERROR (H5E_SYM, H5E_BADMESG, NULL, "can't read message");
if (NULL==H5O_read (f, grp_ent, H5O_STAB, 0, &stab)) {
HRETURN_ERROR (H5E_SYM, H5E_BADMESG, FAIL, "can't read message");
}
udata.operation = H5G_OPER_FIND;
udata.name = name;
udata.heap_addr = stab.heap_addr;
udata.grp_addr = *addr;
udata.node_ptr = NULL;
/* search the B-tree */
if (H5B_find (f, H5B_SNODE, &(stab.btree_addr), &udata)<0) {
if (udata.node_ptr) {
H5AC_unprotect (f, H5AC_SNODE, &(udata.node_addr), udata.node_ptr);
}
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL, "not found");
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "not found");
}
/* Unprotect the symbol table node */
if (udata.node_ptr) {
if (H5AC_unprotect (f, H5AC_SNODE, &(udata.node_addr),
udata.node_ptr)<0) {
HRETURN_ERROR (H5E_SYM, H5E_PROTECT, NULL,
"unable to release symbol table node");
}
}
/* return the result */
FUNC_LEAVE (udata.entry_ptr);
if (obj_ent) *obj_ent = udata.ent;
FUNC_LEAVE (SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5G_stab_insert
*
* Purpose: Insert a new symbol into the table described by SELF in
* Purpose: Insert a new symbol into the table described by GRP_ENT in
* file F. The name of the new symbol is NAME and its symbol
* table entry is ENT.
* table entry is OBJ_ENT.
*
* Errors:
* SYM BADMESG Can't read message.
* SYM CANTINSERT Can't insert entry.
*
* Return: Success: Pointer to the cached symbol table entry.
* This is a pointer directly into a symbol
* table node and will become invalid on the
* next call to the H5AC package.
* Return: Success: SUCCEED
*
* Failure: NULL
* Failure: FAIL
*
* Programmer: Robb Matzke
* matzke@llnl.gov
@ -217,61 +171,41 @@ H5G_stab_find (H5F_t *f, const haddr_t *addr, H5G_entry_t *self,
*
* Modifications:
*
* Robb Matzke, 18 Sep 1997
* If ENT has a shadow, then the shadow will be associated with the
* entry when it is added to the symbol table.
*
*-------------------------------------------------------------------------
*/
H5G_entry_t *
H5G_stab_insert (H5F_t *f, H5G_entry_t *self, const char *name,
H5G_entry_t *ent)
herr_t
H5G_stab_insert (H5F_t *f, H5G_entry_t *grp_ent, const char *name,
H5G_entry_t *obj_ent)
{
H5O_stab_t stab; /*symbol table message */
H5G_bt_ud1_t udata; /*data to pass through B-tree */
FUNC_ENTER (H5G_stab_insert, NULL);
FUNC_ENTER (H5G_stab_insert, FAIL);
/* check arguments */
assert (f);
assert (self && H5F_addr_defined (&(self->header)));
assert (grp_ent && H5F_addr_defined (&(grp_ent->header)));
assert (name && *name);
assert (ent);
assert (obj_ent && H5F_addr_defined (&(obj_ent->header)));
/* initialize data to pass through B-tree */
if (NULL==H5O_read (f, &(self->header), self, H5O_STAB, 0, &stab)) {
HRETURN_ERROR (H5E_SYM, H5E_BADMESG, NULL, "can't read message");
if (NULL==H5O_read (f, grp_ent, H5O_STAB, 0, &stab)) {
HRETURN_ERROR (H5E_SYM, H5E_BADMESG, FAIL, "not a symbol table");
}
udata.operation = H5G_OPER_INSERT;
udata.name = name;
udata.heap_addr = stab.heap_addr;
udata.grp_addr = self->header;
udata.entry = *ent;
udata.entry.name_off = -1;
udata.node_ptr = NULL;
udata.ent = *obj_ent;
/* insert */
if (H5B_insert (f, H5B_SNODE, &(stab.btree_addr), &udata)<0) {
if (udata.node_ptr) {
H5AC_unprotect (f, H5AC_SNODE, &(udata.node_addr), udata.node_ptr);
}
HRETURN_ERROR (H5E_SYM, H5E_CANTINSERT, NULL, "can't insert entry");
HRETURN_ERROR (H5E_SYM, H5E_CANTINSERT, FAIL, "can't insert entry");
}
/*
* The H5G_node_insert() called H5AC_protect() for the node so that the
* udata.entry_ptr field didn't become invalid on the way back out of the
* B-tree code. We unprotect it now, but the pointer will remain valid
* until the next call to H5AC.
*/
if (H5AC_unprotect (f, H5AC_SNODE, &(udata.node_addr), udata.node_ptr)<0) {
HRETURN_ERROR (H5E_SYM, H5E_PROTECT, NULL, "can't unprotect");
}
/* update the name offset in the entry */
ent->name_off = udata.entry.name_off;
FUNC_LEAVE (udata.entry_ptr);
obj_ent->name_off = udata.ent.name_off;
FUNC_LEAVE (SUCCEED);
}
@ -307,7 +241,7 @@ H5G_stab_insert (H5F_t *f, H5G_entry_t *self, const char *name,
*-------------------------------------------------------------------------
*/
intn
H5G_stab_list (H5F_t *f, H5G_entry_t *self, intn maxentries,
H5G_stab_list (H5F_t *f, H5G_entry_t *grp_ent, intn maxentries,
char *names[], H5G_entry_t entries[])
{
H5G_bt_ud2_t udata;
@ -318,16 +252,15 @@ H5G_stab_list (H5F_t *f, H5G_entry_t *self, intn maxentries,
/* check args */
assert (f);
assert (self && H5F_addr_defined (&(self->header)));
assert (grp_ent && H5F_addr_defined (&(grp_ent->header)));
assert (maxentries>=0);
/* initialize data to pass through B-tree */
if (NULL==H5O_read (f, &(self->header), self, H5O_STAB, 0, &stab)) {
if (NULL==H5O_read (f, grp_ent, H5O_STAB, 0, &stab)) {
HRETURN_ERROR (H5E_SYM, H5E_BADMESG, FAIL, "not a symbol table");
}
udata.entry = entries;
udata.name = names;
udata.grp_addr = self->header;
udata.heap_addr = stab.heap_addr;
udata.maxentries = maxentries;
udata.nsyms = 0;

179
src/H5O.c

@ -74,10 +74,13 @@ static const H5O_class_t *const message_type_g[] = {
* Function: H5O_create
*
* Purpose: Creates a new object header, sets the link count
* to NLINK, and caches the header.
* to 0, and caches the header. The object header is opened for
* write access and should eventually be closed by calling
* H5O_close().
*
* Return: Success: SUCCEED, the address of new header is
* returned through the ADDR argument.
* Return: Success: SUCCEED, the ENT argument contains
* information about the object header,
* including its address.
*
* Failure: FAIL
*
@ -90,7 +93,7 @@ static const H5O_class_t *const message_type_g[] = {
*-------------------------------------------------------------------------
*/
herr_t
H5O_create (H5F_t *f, intn nlink, size_t size_hint, haddr_t *addr/*out*/)
H5O_create (H5F_t *f, size_t size_hint, H5G_entry_t *ent/*out*/)
{
size_t size; /*total size of object header */
H5O_t *oh = NULL;
@ -100,14 +103,14 @@ H5O_create (H5F_t *f, intn nlink, size_t size_hint, haddr_t *addr/*out*/)
/* check args */
assert (f);
assert (nlink>=0);
assert (addr);
assert (ent);
HDmemset (ent, 0, sizeof(H5G_entry_t));
if (size_hint<H5O_MIN_SIZE) size_hint = H5O_MIN_SIZE;
H5O_ALIGN (size_hint, H5O_ALIGNMENT);
/* allocate disk space for header and first chunk */
size = H5O_SIZEOF_HDR(f) + size_hint;
if (H5MF_alloc (f, H5MF_META, size, addr/*out*/)<0) {
if (H5MF_alloc (f, H5MF_META, size, &(ent->header)/*out*/)<0) {
HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL,
"unable to allocate file space for object header hdr");
}
@ -117,14 +120,14 @@ H5O_create (H5F_t *f, intn nlink, size_t size_hint, haddr_t *addr/*out*/)
oh->dirty = TRUE;
oh->version = H5O_VERSION;
oh->alignment = H5O_ALIGNMENT;
oh->nlink = nlink;
oh->nlink = 0;
/* create the chunk list and initialize the first chunk */
oh->nchunks = 1;
oh->alloc_nchunks = H5O_NCHUNKS;
oh->chunk = H5MM_xmalloc (oh->alloc_nchunks * sizeof (H5O_chunk_t));
tmp_addr = *addr;
tmp_addr = ent->header;
H5F_addr_inc (&tmp_addr, H5O_SIZEOF_HDR (f));
oh->chunk[0].dirty = TRUE;
oh->chunk[0].addr = tmp_addr;
@ -144,12 +147,82 @@ H5O_create (H5F_t *f, intn nlink, size_t size_hint, haddr_t *addr/*out*/)
oh->mesg[0].chunkno = 0;
/* cache it */
if (H5AC_set (f, H5AC_OHDR, addr, oh)<0) {
if (H5AC_set (f, H5AC_OHDR, &(ent->header), oh)<0) {
H5MM_xfree (oh);
HRETURN_ERROR (H5E_OHDR, H5E_CANTINIT, FAIL,
"unable to cache object header");
}
/* open it */
if (H5O_open (f, ent)<0) {
HRETURN_ERROR (H5E_OHDR, H5E_CANTOPENOBJ, FAIL,
"unable to open object header");
}
FUNC_LEAVE (SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5O_open
*
* Purpose: Opens an object header which is described by the symbol table
* entry OBJ_ENT.
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Monday, January 5, 1998
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5O_open (H5F_t *f, H5G_entry_t *obj_ent)
{
FUNC_ENTER (H5O_open, FAIL);
/*
* There is nothing to do here now. Opening an object header should
* eventually do something to prevent the object header from being deleted,
* but since object deletion isn't implemented yet, we don't care.
*/
FUNC_LEAVE (SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5O_close
*
* Purpose: Closes an object header that was previously open.
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Monday, January 5, 1998
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5O_close (H5F_t *f, H5G_entry_t *obj_ent)
{
FUNC_ENTER (H5O_close, FAIL);
/*
* There is nothing to do here now. See H5O_open(). Eventually this
* function will free resources if the object header hard link count is
* zero and this was the last oustanding open for the object. Since
* object deletion isn't implemented yet, we don't care.
*/
FUNC_LEAVE (SUCCEED);
}
@ -590,52 +663,40 @@ H5O_link (H5F_t *f, H5G_entry_t *ent, intn adjust)
*-------------------------------------------------------------------------
*/
void *
H5O_read (H5F_t *f, const haddr_t *addr, H5G_entry_t *ent,
const H5O_class_t *type, intn sequence, void *mesg)
H5O_read (H5F_t *f, H5G_entry_t *ent, const H5O_class_t *type,
intn sequence, void *mesg)
{
H5O_t *oh = NULL;
void *retval = NULL;
intn idx;
H5G_cache_t *cache = NULL;
H5G_type_t cache_type;
haddr_t _addr;
FUNC_ENTER (H5O_read, NULL);
/* check args */
assert (f);
if (!addr) {
if (!ent || H5G_ent_addr (ent, &_addr/*out*/)) {
HRETURN_ERROR (H5E_OHDR, H5E_NOTFOUND, NULL,
"invalid symbol table entry");
}
addr = &_addr;
}
assert (H5F_addr_defined (addr));
assert (ent);
assert (H5F_addr_defined (&(ent->header)));
assert (type);
assert (sequence>=0);
/* can we get it from the symbol table? */
if (ent) {
cache = H5G_ent_cache (ent, &cache_type);
if (type && cache_type==type->cache_type && type->fast) {
retval = (type->fast)(cache, mesg);
if (retval) HRETURN (retval);
H5ECLEAR;
}
cache = H5G_ent_cache (ent, &cache_type);
if (type && cache_type==type->cache_type && type->fast) {
retval = (type->fast)(cache, mesg);
if (retval) HRETURN (retval);
H5ECLEAR;
}
/* can we get it from the object header? */
if ((idx = H5O_find_in_ohdr (f, addr, &type, sequence))<0) {
if ((idx = H5O_find_in_ohdr (f, &(ent->header), &type, sequence))<0) {
HRETURN_ERROR (H5E_OHDR, H5E_NOTFOUND, NULL,
"unable to find message in object header");
}
#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, NULL))) {
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, &(ent->header), NULL, NULL))) {
HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, NULL,
"unable to load object header");
}
@ -740,7 +801,7 @@ H5O_find_in_ohdr (H5F_t *f, const haddr_t *addr, const H5O_class_t **type_p,
*-------------------------------------------------------------------------
*/
const void *
H5O_peek (H5F_t *f, const haddr_t *addr, const H5O_class_t *type,
H5O_peek (H5F_t *f, H5G_entry_t *ent, const H5O_class_t *type,
intn sequence)
{
intn idx;
@ -750,13 +811,13 @@ H5O_peek (H5F_t *f, const haddr_t *addr, const H5O_class_t *type,
/* check args */
assert (f);
assert (addr && H5F_addr_defined (addr));
assert (ent && H5F_addr_defined (&(ent->header)));
if ((idx = H5O_find_in_ohdr (f, addr, &type, sequence))<0) {
if ((idx = H5O_find_in_ohdr (f, &(ent->header), &type, sequence))<0) {
HRETURN_ERROR (H5E_OHDR, H5E_NOTFOUND, NULL,
"unable to find object header message");
}
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL, NULL))) {
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, &(ent->header), NULL, NULL))) {
HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, NULL,
"unable to load object header");
}
@ -769,11 +830,8 @@ H5O_peek (H5F_t *f, const 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 (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.
* The cache fields in that symbol table entry ENT are updated
* as appropriate.
*
* The OVERWRITE argument is either a sequence number of a
* message to overwrite (usually zero) or the constant
@ -798,30 +856,23 @@ H5O_peek (H5F_t *f, const haddr_t *addr, const H5O_class_t *type,
*-------------------------------------------------------------------------
*/
intn
H5O_modify (H5F_t *f, const haddr_t *addr, H5G_entry_t *ent,
const H5O_class_t *type, intn overwrite, const void *mesg)
H5O_modify (H5F_t *f, H5G_entry_t *ent, const H5O_class_t *type,
intn overwrite, const void *mesg)
{
H5O_t *oh = NULL;
intn idx, sequence;
size_t size;
haddr_t _addr;
FUNC_ENTER (H5O_modify, FAIL);
/* check args */
assert (f);
assert (ent);
assert (H5F_addr_defined (&(ent->header)));
assert (type);
assert (mesg);
if (!addr) {
if (!ent || H5G_ent_addr (ent, &_addr)<0) {
HRETURN_ERROR (H5E_OHDR, H5E_CANTINIT, FAIL,
"invalid object header address");
}
addr = &_addr;
}
assert (H5F_addr_defined (addr));
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL, NULL))) {
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, &(ent->header), NULL, NULL))) {
HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL,
"unable to load object header");
}
@ -866,7 +917,7 @@ H5O_modify (H5F_t *f, const haddr_t *addr, H5G_entry_t *ent,
oh->dirty = TRUE;
/* Copy into the symbol table entry */
if (oh->nlink<=1 && ent && type->cache) {
if (oh->nlink<=1 && type->cache) {
H5G_type_t cache_type;
H5G_cache_t *cache = H5G_ent_cache (ent, &cache_type);
hbool_t modified = (type->cache)(&cache_type, cache, mesg);
@ -909,29 +960,21 @@ H5O_modify (H5F_t *f, const haddr_t *addr, H5G_entry_t *ent,
*-------------------------------------------------------------------------
*/
herr_t
H5O_remove (H5F_t *f, const haddr_t *addr, H5G_entry_t *ent,
const H5O_class_t *type, intn sequence)
H5O_remove (H5F_t *f, H5G_entry_t *ent, const H5O_class_t *type, intn sequence)
{
H5O_t *oh = NULL;
intn i, seq;
haddr_t _addr;
FUNC_ENTER (H5O_remove, FAIL);
/* check args */
assert (f);
assert (ent);
assert (H5F_addr_defined (&(ent->header)));
assert (type);
if (!addr) {
if (!ent || H5G_ent_addr (ent, &_addr)<0) {
HRETURN_ERROR (H5E_OHDR, H5E_CANTINIT, FAIL,
"invalid object header address");
}
addr = &_addr;
}
assert (H5F_addr_defined (addr));
/* load the object header */
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL, NULL))) {
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, &(ent->header), NULL, NULL))) {
HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL,
"unable to load object header");
}

@ -180,16 +180,18 @@ typedef struct H5O_stab_t {
herr_t H5O_create (H5F_t *f, intn nlink, size_t size_hint, haddr_t*);
herr_t H5O_create (H5F_t *f, size_t size_hint, H5G_entry_t *ent/*out*/);
herr_t H5O_open (H5F_t *f, H5G_entry_t *ent);
herr_t H5O_close (H5F_t *f, H5G_entry_t *ent);
intn H5O_link (H5F_t *f, H5G_entry_t *ent, intn adjust);
void *H5O_read (H5F_t *f, const haddr_t *addr, H5G_entry_t *ent,
const H5O_class_t *type, intn sequence, void *mesg);
const void *H5O_peek (H5F_t *f, const haddr_t *addr, const H5O_class_t *type,
void *H5O_read (H5F_t *f, H5G_entry_t *ent, const H5O_class_t *type,
intn sequence, void *mesg);
const void *H5O_peek (H5F_t *f, H5G_entry_t *ent, const H5O_class_t *type,
intn sequence);
intn H5O_modify (H5F_t *f, const haddr_t *addr, H5G_entry_t *ent,
const H5O_class_t *type, intn overwrite, const void *mesg);
herr_t H5O_remove (H5F_t *f, const haddr_t *addr, H5G_entry_t *ent,
const H5O_class_t *type, intn sequence);
intn H5O_modify (H5F_t *f, H5G_entry_t *ent, const H5O_class_t *type,
intn overwrite, const void *mesg);
herr_t H5O_remove (H5F_t *f, H5G_entry_t *ent, const H5O_class_t *type,
intn sequence);
herr_t H5O_reset (const H5O_class_t *type, void *native);
herr_t H5O_debug (H5F_t *f, const haddr_t *addr, FILE *stream,
intn indent, intn fwidth);

@ -610,7 +610,7 @@ H5P_modify (H5F_t *f, H5G_entry_t *ent, const H5P_t *ds)
"scalar data spaces are not implemented yet");
case H5P_SIMPLE:
if (H5O_modify (f, NO_ADDR, ent, H5O_SDSPACE, 0, &(ds->u.simple))<0) {
if (H5O_modify (f, ent, H5O_SDSPACE, 0, &(ds->u.simple))<0) {
HRETURN_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL,
"can't update simple data space message");
}
@ -658,7 +658,7 @@ H5P_read (H5F_t *f, H5G_entry_t *ent)
ds = H5MM_xcalloc (1, sizeof(H5P_t));
if (H5O_read (f, NO_ADDR, ent, H5O_SDSPACE, 0, &(ds->u.simple))) {
if (H5O_read (f, ent, H5O_SDSPACE, 0, &(ds->u.simple))) {
ds->type = H5P_SIMPLE;
} else {

@ -22,7 +22,7 @@
#include <H5public.h> /* Include Public Definitions */
/* Version #'s of library code */
#define HDF5_MAJOR_VERSION 0 /* For major interface changes */
#define HDF5_MAJOR_VERSION 5 /* For major interface changes */
#define HDF5_MINOR_VERSION 0 /* For minor interface changes */
#define HDF5_RELEASE_VERSION 0 /* For interface tweaks & bug-fixes */
#define HDF5_PATCH_VERSION 0 /* For small groups of bug fixes*/

@ -16,10 +16,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 H5Fcore.c \
H5Ffamily.c H5Fistore.c H5Flow.c H5Fsec2.c H5Fsplit.c H5Fstdio.c \
H5G.c H5Gent.c H5Gnode.c H5Gshad.c H5Gstab.c H5H.c H5M.c H5MF.c \
H5MM.c H5O.c H5Ocont.c H5Ocstore.c H5Odtype.c H5Oefl.c H5Oistore.c \
H5Oname.c H5Onull.c H5Osdspace.c H5Ostab.c H5P.c H5T.c H5Tinit.c \
H5V.c
H5G.c H5Gent.c H5Gnode.c H5Gstab.c H5H.c H5M.c H5MF.c H5MM.c H5O.c \
H5Ocont.c H5Ocstore.c H5Odtype.c H5Oefl.c H5Oistore.c H5Oname.c \
H5Onull.c H5Osdspace.c H5Ostab.c H5P.c H5T.c H5Tinit.c H5V.c
LIB_OBJ=$(LIB_SRC:.c=.o)

@ -15,10 +15,10 @@
#include <H5Oprivate.h>
#include <H5Vprivate.h>
#if 0
#if 1
# define FILETYPE H5F_LOW_DFLT
# define FILENAME "istore.h5"
#elif 1
#elif 0
# define FILETYPE H5F_LOW_FAM
# define FILENAME "istore-%05d.h5"
# define TEST_FAMILY 1
@ -96,22 +96,21 @@ print_array (uint8 *array, size_t nx, size_t ny, size_t nz)
*
*-------------------------------------------------------------------------
*/
static H5G_entry_t *
new_object (H5F_t *f, const char *name, size_t ndims)
static int
new_object (H5F_t *f, const char *name, size_t ndims, H5G_entry_t *ent/*out*/)
{
H5G_entry_t *handle = NULL;
H5O_istore_t istore;
size_t alignment[H5O_ISTORE_NDIMS];
intn i;
/* Create the object symbol table entry and header */
if (NULL==(handle=H5G_create (f, name, 64))) {
/* Create the object header */
if (H5O_create (f, 64, ent)) {
puts ("*FAILED*");
if (!isatty (1)) {
AT ();
printf (" H5G_create (f, name=\"%s\") = NULL\n", name);
printf (" H5O_create() = NULL\n");
}
return NULL;
return -1;
}
/* Add the indexed-storage message */
@ -122,19 +121,30 @@ new_object (H5F_t *f, const char *name, size_t ndims)
alignment[i] = 2;
}
}
H5F_istore_create (f, &istore, ndims, alignment);
if (H5O_modify (f, NO_ADDR, handle, H5O_ISTORE, H5O_NEW_MESG,
&istore)<0) {
if (H5O_modify (f, ent, H5O_ISTORE, H5O_NEW_MESG, &istore)<0) {
printf ("*FAILED*\n");
if (!isatty (1)) {
AT();
printf (" H5G_modify istore message failure\n");
printf (" H5O_modify istore message failure\n");
}
return NULL;
return -1;
}
return handle;
/* Give the object header a name */
if (H5G_insert (f, name, ent)<0) {
printf ("*FAILED*\n");
if (!isatty (1)) {
AT ();
printf (" H5G_insert(f, name=\"%s\", ent) failed\n", name);
}
return -1;
}
/* Close the header */
H5O_close (f, ent);
return 0;
}
@ -158,7 +168,7 @@ new_object (H5F_t *f, const char *name, size_t ndims)
static herr_t
test_create (H5F_t *f, const char *prefix)
{
H5G_entry_t *handle = NULL;
H5G_entry_t handle;
intn i;
char name[256];
@ -166,8 +176,7 @@ test_create (H5F_t *f, const char *prefix)
for (i=1; i<=H5O_ISTORE_NDIMS; i++) {
sprintf (name, "%s_%02d", prefix, i);
if (NULL==(handle=new_object (f, name, i))) return FAIL;
H5G_close (f, handle);
if (new_object (f, name, i, &handle)<0) return FAIL;
}
puts (" PASSED");
@ -198,7 +207,7 @@ static herr_t
test_extend (H5F_t *f, const char *prefix,
size_t nx, size_t ny, size_t nz)
{
H5G_entry_t *handle = NULL;
H5G_entry_t handle;
int i, j, k, ndims, ctr;
uint8 *buf=NULL, *check=NULL, *whole=NULL;
char dims[64], s[256], name[256];
@ -234,14 +243,14 @@ test_extend (H5F_t *f, const char *prefix,
/* Build the new empty object */
sprintf (name, "%s_%s", prefix, dims);
if (NULL==(handle=new_object (f, name, ndims))) {
if (new_object (f, name, ndims, &handle)<0) {
if (!isatty (1)) {
AT ();
printf (" Cannot create %d-d object `%s'\n", ndims, name);
}
goto error;
}
if (NULL==H5O_read (f, NO_ADDR, handle, H5O_ISTORE, 0, &istore)) {
if (NULL==H5O_read (f, &handle, H5O_ISTORE, 0, &istore)) {
puts ("*FAILED*");
if (!isatty (1)) {
AT ();
@ -377,7 +386,6 @@ test_extend (H5F_t *f, const char *prefix,
}
}
H5G_close (f, handle);
puts (" PASSED");
H5MM_xfree (buf);
H5MM_xfree (check);
@ -417,7 +425,7 @@ test_sparse (H5F_t *f, const char *prefix, size_t nblocks,
intn ndims, ctr;
char dims[64], s[256], name[256];
size_t offset[3], size[3], total=0;
H5G_entry_t *handle = NULL;
H5G_entry_t handle;
H5O_istore_t istore;
uint8 *buf = NULL;
@ -443,14 +451,14 @@ test_sparse (H5F_t *f, const char *prefix, size_t nblocks,
/* Build the new empty object */
sprintf (name, "%s_%s", prefix, dims);
if (NULL==(handle=new_object (f, name, ndims))) {
if (new_object (f, name, ndims, &handle)<0) {
if (!isatty (1)) {
AT ();
printf (" Cannot create %d-d object `%s'\n", ndims, name);
}
goto error;
}
if (NULL==H5O_read (f, NO_ADDR, handle, H5O_ISTORE, 0, &istore)) {
if (NULL==H5O_read (f, &handle, H5O_ISTORE, 0, &istore)) {
puts ("*FAILED*");
if (!isatty (1)) {
AT ();
@ -493,7 +501,6 @@ test_sparse (H5F_t *f, const char *prefix, size_t nblocks,
}
H5G_close (f, handle);
puts (" PASSED");
H5MM_xfree (buf);
return SUCCEED;
@ -528,9 +535,9 @@ main (int argc, char *argv[])
int nerrors = 0;
uintn size_of_test;
size_t offset_size;
H5G_entry_t *ent = NULL;
hid_t template_id;
H5F_create_t *creation_template = NULL;
H5G_t *dir = NULL;
setbuf (stdout, NULL);
@ -591,9 +598,9 @@ main (int argc, char *argv[])
* By creating a group we cause the library to emit it's debugging
* diagnostic messages before we begin testing...
*/
ent = H5G_new (f, "flushing_diagnostics", 0);
H5G_close (f, ent);
ent = NULL;
dir = H5G_create (f, "flushing_diagnostics", 0);
H5G_close (dir);
dir = NULL;
/*

@ -163,8 +163,8 @@ int main(int argc, char *argv[])
H5version(&major, &minor, &release, &patch);
print_func("\nFor help use: testhdf5 -help\n");
print_func("Built with HDF5 Library Version: %u.%ur%u, patch %u\n\n", (unsigned) major,
(unsigned) minor, (unsigned) release, (unsigned)patch);
print_func("Linked with HDF %u.%u.%u%c\n\n", (unsigned) major,
(unsigned) minor, (unsigned) release, 'a'+patch);
for (CLLoop = 1; CLLoop < argc; CLLoop++)
{
if ((argc > CLLoop + 1) && ((HDstrcmp(argv[CLLoop], "-verbose") == 0) ||

@ -49,11 +49,10 @@ test_ohdr (void)
{
hid_t fid;
H5F_t *f;
haddr_t oh_addr;
H5G_entry_t oh_ent;
H5O_stab_t stab, ro;
herr_t status;
void *ptr;
H5G_entry_t ent;
int i;
MESSAGE (5, ("Testing Object Headers\n"));
@ -66,7 +65,7 @@ test_ohdr (void)
/* the new object header */
MESSAGE (8, ("Creating new object header...\n"));
status = H5O_create (f, 1, 64, &oh_addr/*out*/);
status = H5O_create (f, 64, &oh_ent/*out*/);
CHECK_I (status, "H5O_new");
/*
@ -75,11 +74,11 @@ test_ohdr (void)
MESSAGE (8, ("Creating new message...\n"));
stab.btree_addr.offset = 11111111;
stab.heap_addr.offset = 22222222;
status = H5O_modify (f, &oh_addr, NULL, H5O_STAB, H5O_NEW_MESG, &stab);
status = H5O_modify (f, &oh_ent, H5O_STAB, H5O_NEW_MESG, &stab);
VERIFY (status, 0, "H5O_modify");
H5AC_flush (f, NULL, 0, TRUE);
ptr = H5O_read (f, &oh_addr, NULL, H5O_STAB, 0, &ro);
ptr = H5O_read (f, &oh_ent, H5O_STAB, 0, &ro);
CHECK_PTR (ptr, "H5O_read");
VERIFY (ptr, &ro, "H5O_read");
VERIFY (ro.btree_addr.offset, stab.btree_addr.offset, "H5O_read");
@ -91,11 +90,11 @@ test_ohdr (void)
MESSAGE (8, ("Modifying message...\n"));
stab.btree_addr.offset = 33333333;
stab.heap_addr.offset = 44444444;
status = H5O_modify (f, &oh_addr, NULL, H5O_STAB, 0, &stab);
status = H5O_modify (f, &oh_ent, H5O_STAB, 0, &stab);
VERIFY (status, 0, "H5O_modify");
H5AC_flush (f, NULL, 0, TRUE);
ptr = H5O_read (f, &oh_addr, NULL, H5O_STAB, 0, &ro);
ptr = H5O_read (f, &oh_ent, H5O_STAB, 0, &ro);
CHECK_PTR (ptr, "H5O_read");
VERIFY (ptr, &ro, "H5O_read");
VERIFY (ro.btree_addr.offset, stab.btree_addr.offset, "H5O_read");
@ -106,22 +105,19 @@ test_ohdr (void)
* table.
*/
MESSAGE (8, ("Creating a duplicate message...\n"));
ent.header.offset = 0;
ent.type = H5G_NOTHING_CACHED;
ent.dirty = FALSE;
stab.btree_addr.offset = 55555555;
stab.heap_addr.offset = 66666666;
status = H5O_modify (f, &oh_addr, &ent, 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.dirty, TRUE, "H5O_modify");
VERIFY (ent.type, H5G_CACHED_STAB, "H5O_modify");
VERIFY (ent.cache.stab.heap_addr.offset, stab.heap_addr.offset,
VERIFY (oh_ent.dirty, TRUE, "H5O_modify");
VERIFY (oh_ent.type, H5G_CACHED_STAB, "H5O_modify");
VERIFY (oh_ent.cache.stab.heap_addr.offset, stab.heap_addr.offset,
"H5O_modify");
VERIFY (ent.cache.stab.btree_addr.offset, stab.btree_addr.offset,
VERIFY (oh_ent.cache.stab.btree_addr.offset, stab.btree_addr.offset,
"H5O_modify");
H5AC_flush (f, NULL, 0, TRUE);
ptr = H5O_read (f, &oh_addr, NULL, H5O_STAB, 1, &ro);
ptr = H5O_read (f, &oh_ent, H5O_STAB, 1, &ro);
CHECK_PTR (ptr, "H5O_read");
VERIFY (ptr, &ro, "H5O_read");
VERIFY (ro.btree_addr.offset, stab.btree_addr.offset, "H5O_read");
@ -131,20 +127,19 @@ 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.offset = 77777777;
stab.heap_addr.offset = 88888888;
status = H5O_modify (f, &oh_addr, &ent, H5O_STAB, 1, &stab);
status = H5O_modify (f, &oh_ent, H5O_STAB, 1, &stab);
VERIFY (status, 1, "H5O_modify");
VERIFY (ent.dirty, TRUE, "H5O_modify");
VERIFY (ent.type, H5G_CACHED_STAB, "H5O_modify");
VERIFY (ent.cache.stab.heap_addr.offset, stab.heap_addr.offset,
VERIFY (oh_ent.dirty, TRUE, "H5O_modify");
VERIFY (oh_ent.type, H5G_CACHED_STAB, "H5O_modify");
VERIFY (oh_ent.cache.stab.heap_addr.offset, stab.heap_addr.offset,
"H5O_modify");
VERIFY (ent.cache.stab.btree_addr.offset, stab.btree_addr.offset,
VERIFY (oh_ent.cache.stab.btree_addr.offset, stab.btree_addr.offset,
"H5O_modify");
H5AC_flush (f, NULL, 0, TRUE);
ptr = H5O_read (f, &oh_addr, NULL, H5O_STAB, 1, &ro);
ptr = H5O_read (f, &oh_ent, H5O_STAB, 1, &ro);
CHECK_PTR (ptr, "H5O_read");
VERIFY (ptr, &ro, "H5O_read");
VERIFY (ro.btree_addr.offset, stab.btree_addr.offset, "H5O_read");
@ -158,7 +153,7 @@ test_ohdr (void)
for (i=0; i<40; i++) {
stab.btree_addr.offset = (i+1)*1000 + 1;
stab.heap_addr.offset = (i+1)*1000 + 2;
status = H5O_modify (f, &oh_addr, NULL, H5O_STAB, H5O_NEW_MESG, &stab);
status = H5O_modify (f, &oh_ent, H5O_STAB, H5O_NEW_MESG, &stab);
VERIFY (status, 2+i, "H5O_modify");
}
H5AC_flush (f, NULL, 0, TRUE);
@ -171,7 +166,7 @@ test_ohdr (void)
for (i=0; i<10; i++) {
stab.btree_addr.offset = (i+1)*1000 + 10;
stab.heap_addr.offset = (i+1)*1000 + 20;
status = H5O_modify (f, &oh_addr, NULL, H5O_STAB, H5O_NEW_MESG, &stab);
status = H5O_modify (f, &oh_ent, H5O_STAB, H5O_NEW_MESG, &stab);
VERIFY (status, 42+i, "H5O_modify");
H5AC_flush (f, NULL, 0, TRUE);
}
@ -179,7 +174,7 @@ test_ohdr (void)
/*
* Delete all symbol table messages.
*/
status = H5O_remove (f, &oh_addr, NULL, H5O_STAB, H5O_ALL);
status = H5O_remove (f, &oh_ent, H5O_STAB, H5O_ALL);
CHECK_I (status, "H5O_remove");
/* close the file */

@ -18,6 +18,7 @@
#include <H5private.h>
#include <H5ACprivate.h>
#include <H5Cprivate.h>
#include <H5Fprivate.h>
#include <H5Gprivate.h>
#include <H5Oprivate.h>
@ -51,8 +52,7 @@ test_1 (void)
{
hid_t fid;
H5F_t *f;
H5G_entry_t *obj1=NULL, *obj2=NULL;
H5G_entry_t ent1, dir_ent;
H5G_entry_t ent1, ent2, obj_ent, dir_ent;
herr_t status;
H5O_name_t name_mesg;
void *status_ptr;
@ -73,26 +73,28 @@ test_1 (void)
CHECK (f, NULL, "H5Aatom_object");
/* create the object */
obj1 = H5G_create (f, "/", 0);
CHECK_PTR (obj1, "H5G_new");
status = H5O_create (f, 0, &ent1);
CHECK_I (status, "H5O_create");
status = H5G_insert (f, "/", &ent1);
CHECK_I (status, "H5G_insert");
/* look for a name message -- it shouldn't be present */
status_ptr = H5O_read (f, NO_ADDR, obj1, H5O_NAME, 0, &name_mesg);
status_ptr = H5O_read (f, &ent1, H5O_NAME, 0, &name_mesg);
VERIFY (status_ptr, NULL, "H5O_read [didn't fail but should have]");
/*
* Test 1B: Attempt to read the root object using the name `/'.
*/
memset (&dir_ent, 0xff, sizeof(H5G_entry_t));
memset (&ent1, 0xff, sizeof(H5G_entry_t));
status = H5G_find (f, "/", &dir_ent, &ent1);
memset (&obj_ent, 0xff, sizeof(H5G_entry_t));
status = H5G_find (f, "/", &dir_ent, &obj_ent);
CHECK_I (status, "H5G_find");
/* Is it really the root object? */
b = H5F_addr_defined (&(dir_ent.header));
VERIFY (b, FALSE, "H5G_create");
b = H5F_addr_eq (&(ent1.header), &(obj1->header));
VERIFY (b, TRUE, "H5G_create");
VERIFY (b, FALSE, "H5G_insert");
b = H5F_addr_eq (&(obj_ent.header), &(ent1.header));
VERIFY (b, TRUE, "H5G_insert");
/*
@ -101,24 +103,20 @@ test_1 (void)
*/
/* create the object */
obj2 = H5G_create (f, "/second", 0);
CHECK_PTR (obj2, "H5G_new");
status = H5O_create (f, 0, &ent2);
CHECK_I (status, "H5O_create");
status = H5G_insert (f, "/second", &ent2);
CHECK_I (status, "H5G_insert");
/* try to read the first object */
HDmemset (&ent1, 0xff, sizeof(H5G_entry_t));
status = H5G_find (f, "/Root Object", NULL, &ent1);
HDmemset (&obj_ent, 0xff, sizeof(H5G_entry_t));
status = H5G_find (f, "/Root Object", NULL, &obj_ent);
CHECK_I (status, "H5G_find");
b = H5F_addr_defined (&(ent1.header));
VERIFY (b, TRUE, "H5G_create");
b = H5F_addr_eq (&(ent1.header), &(obj1->header));
b = H5F_addr_defined (&(obj_ent.header));
VERIFY (b, TRUE, "H5G_insert");
b = H5F_addr_eq (&(obj_ent.header), &(ent1.header));
VERIFY (b, TRUE, "H5G_create");
/* close the objects */
H5G_close (f, obj1);
obj1 = NULL;
H5G_close (f, obj2);
obj2 = NULL;
/* close the file */
H5Fclose (fid);
@ -137,14 +135,16 @@ test_1 (void)
CHECK (f, NULL, "H5Aatom_object");
/* create the object */
obj1 = H5G_create (f, "/foo", 0);
CHECK_PTR (obj1, "H5G_create");
status = H5O_create (f, 0, &ent1);
CHECK_I (status, "H5O_create");
status = H5G_insert (f, "/foo", &ent1);
CHECK_I (status, "H5G_insert");
/* does it have the correct name message? */
status_ptr = H5O_read (f, NO_ADDR, obj1, H5O_NAME, 0, &name_mesg);
status_ptr = H5O_read (f, &ent1, H5O_NAME, 0, &name_mesg);
CHECK_PTR (status_ptr, "H5O_read");
CHECK_PTR (name_mesg.s, "H5O_read");
VERIFY (strcmp(name_mesg.s, "foo"), 0, "H5O_read");
VERIFY (strcmp(name_mesg.s, "foo"), 0, "H5G_insert");
if (status_ptr) H5O_reset (H5O_NAME, &name_mesg); /*free message data*/
@ -152,23 +152,23 @@ test_1 (void)
* Test 1E: Try to read the root object with the name `/' and `/foo'
*/
HDmemset (&dir_ent, 0, sizeof(H5G_entry_t));
HDmemset (&ent1, 0, sizeof(H5G_entry_t));
status = H5G_find (f, "/", &dir_ent, &ent1);
HDmemset (&obj_ent, 0, sizeof(H5G_entry_t));
status = H5G_find (f, "/", &dir_ent, &obj_ent);
CHECK_I (status, "H5G_find");
b = H5F_addr_defined (&(dir_ent.header));
VERIFY (b, FALSE, "H5G_create");
b = H5F_addr_eq (&(ent1.header), &(obj1->header));
VERIFY (b, TRUE, "H5G_create");
VERIFY (b, FALSE, "H5G_insert");
b = H5F_addr_eq (&(obj_ent.header), &(ent1.header));
VERIFY (b, TRUE, "H5G_insert");
/* now as `/foo' */
HDmemset (&dir_ent, 0, sizeof(H5G_entry_t));
HDmemset (&ent1, 0, sizeof(H5G_entry_t));
status = H5G_find (f, "/foo", &dir_ent, &ent1);
HDmemset (&obj_ent, 0, sizeof(H5G_entry_t));
status = H5G_find (f, "/foo", &dir_ent, &obj_ent);
CHECK_I (status, "H5G_find");
b = H5F_addr_defined (&(dir_ent.header));
VERIFY (b, FALSE, "H5G_create");
b = H5F_addr_eq (&(ent1.header), &(obj1->header));
VERIFY (b, TRUE, "H5G_find");
VERIFY (b, FALSE, "H5G_insert");
b = H5F_addr_eq (&(obj_ent.header), &(ent1.header));
VERIFY (b, TRUE, "H5G_insert");
/*
@ -177,26 +177,22 @@ test_1 (void)
*/
/* create the object */
obj2 = H5G_create (f, "/second", 0);
CHECK_PTR (obj2, "H5G_new");
status = H5O_create (f, 0, &ent2);
CHECK_I (status, "H5O_create");
status = H5G_insert (f, "/second", &ent2);
CHECK_I (status, "H5G_insert");
/* try to read the first object */
HDmemset (&ent1, 0, sizeof(H5G_entry_t));
status = H5G_find (f, "/foo", NULL, &ent1);
HDmemset (&obj_ent, 0, sizeof(H5G_entry_t));
status = H5G_find (f, "/foo", NULL, &obj_ent);
CHECK_I (status, "H5G_find");
b = H5F_addr_eq (&(ent1.header), &(obj1->header));
VERIFY (b, TRUE, "H5G_find");
b = H5F_addr_eq (&(obj_ent.header), &(ent1.header));
VERIFY (b, TRUE, "H5G_insert");
/* the first object should not have a name message */
status_ptr = H5O_read (f, NO_ADDR, obj1, H5O_NAME, 0, &name_mesg);
status_ptr = H5O_read (f, &ent1, H5O_NAME, 0, &name_mesg);
VERIFY (status_ptr, NULL, "H5O_read [didn't fail but should have]");
/* close the objects */
H5G_close (f, obj1);
obj1 = NULL;
H5G_close (f, obj2);
obj2 = NULL;
/* close the file */
status = H5Fclose (fid);
CHECK_I (status, "H5Fclose");
@ -221,18 +217,28 @@ test_1 (void)
static void
test_2 (void)
{
hid_t fid;
hid_t fid, props;
H5F_t *f;
H5G_entry_t *obj1=NULL;
int i;
char name[256];
herr_t status;
int nsyms = 5000;
H5G_t *dir = NULL;
MESSAGE (2, ("........large directories\n"));
/*
* Use larger symbol table data structures to be more efficient, use
* defaults to bang harder on the library for testing.
*/
props = H5Ccreate (H5C_FILE_CREATE);
#if 1
H5Cset_prop (props, H5F_SYM_LEAF_K, 16);
H5Cset_prop (props, H5F_SYM_INTERN_K, 16);
#endif
/* create the file */
fid = H5Fcreate ("tstab2.h5", H5ACC_OVERWRITE, 0, 0);
fid = H5Fcreate ("tstab2.h5", H5ACC_OVERWRITE, props, 0);
CHECK (fid, FAIL, "H5Fcreate");
f = H5Aatom_object (fid);
CHECK (f, NULL, "H5Aatom_object");
@ -242,19 +248,17 @@ test_2 (void)
* Create a directory that has so many entries that the root
* of the B-tree ends up splitting.
*/
obj1 = H5G_new (f, "/big", nsyms*12+2);
CHECK_PTR (obj1, "H5G_mkdir");
H5G_close (f, obj1);
obj1 = NULL;
dir = H5G_create (f, "/big", nsyms*12+2);
CHECK_PTR (dir, "H5G_mkdir");
status = H5G_close (dir);
CHECK_I (status, "H5G_close");
for (i=0; i<nsyms; i++) {
sprintf (name, "/big/%05d%05d", rand()%100000, i);
MESSAGE (8, ("%s\n", name));
obj1 = H5G_create (f, name, 0);
CHECK_PTR (obj1, "H5G_mkdir");
H5G_close (f, obj1);
obj1 = NULL;
dir = H5G_create (f, name, 0);
CHECK_PTR (dir, "H5G_create");
H5G_close (dir);
}