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:
parent
dfff2572ca
commit
1d17defdfc
1
MANIFEST
1
MANIFEST
@ -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 */
|
||||
|
54
src/H5D.c
54
src/H5D.c
@ -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
|
||||
|
74
src/H5F.c
74
src/H5F.c
@ -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;
|
||||
|
||||
/*
|
||||
|
60
src/H5Gent.c
60
src/H5Gent.c
@ -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) {
|
||||
|
181
src/H5Gnode.c
181
src/H5Gnode.c
@ -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);
|
||||
}
|
||||
|
||||
|
91
src/H5Gpkg.h
91
src/H5Gpkg.h
@ -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
|
||||
|
810
src/H5Gshad.c
810
src/H5Gshad.c
@ -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);
|
||||
}
|
157
src/H5Gstab.c
157
src/H5Gstab.c
@ -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
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) ||
|
||||
|
47
test/tohdr.c
47
test/tohdr.c
@ -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 */
|
||||
|
128
test/tstab.c
128
test/tstab.c
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user