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

[svn-r100] Interim checkin for purify. Also contains H5G shadow stuff, changes

to int64 encode/decode to fix purify on 32-bit systems, changes to
H5O_modify, changes to H5D.c to use H5F_open/close(), etc.
Documentation will be mailed shortly...
This commit is contained in:
Robb Matzke 1997-09-19 11:36:59 -05:00
parent 055daa52f0
commit 25d866e9b4
32 changed files with 1433 additions and 641 deletions

@ -173,7 +173,7 @@ H5AC_dest (hdf5_file_t *f)
*/
void *
H5AC_find_f (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr,
const void *udata)
void *udata)
{
unsigned idx;
herr_t status;
@ -298,9 +298,11 @@ H5AC_compare (const void *_a, const void *_b)
* Function: H5AC_flush
*
* Purpose: Flushes (and destroys if DESTROY is non-zero) the specified
* entry from the cache. If the entry type is CACHE_FREE then
* all types of entries are flushed. If the ADDR is zero then
* all entries of the specified type are flushed.
* entry from the cache. If the entry TYPE is CACHE_FREE and
* ADDR is zero then all types of entries are flushed. If TYPE
* is CACHE_FREE and ADDR is non-zero, then whatever is cached
* at ADDR is flushed. Otherwise the thing at ADDR is flushed
* if it is the correct type.
*
* If there are protected objects they will not be flushed.
* However, an attempt will be made to flush all non-protected
@ -334,7 +336,7 @@ H5AC_flush (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr,
assert (f->cache);
i = H5AC_HASH (f, addr);
if (!type || 0==addr) {
if (0==addr) {
#ifdef SORT_BY_ADDR
/*
@ -360,8 +362,7 @@ H5AC_flush (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr,
slot = f->cache->slot + i;
if (NULL==slot->type) continue;
#endif
if ((!type || type==slot->type) &&
(0==addr || addr==slot->addr)) {
if (!type || type==slot->type) {
flush = slot->type->flush;
status = (flush)(f, destroy, slot->addr, slot->thing);
if (status<0) {
@ -373,7 +374,8 @@ H5AC_flush (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr,
}
map = H5MM_xfree (map);
} else if (f->cache->slot[i].type==type && f->cache->slot[i].addr==addr) {
} else if ((!type || f->cache->slot[i].type==type) &&
f->cache->slot[i].addr==addr) {
/*
* Flush just this entry.
*/
@ -583,7 +585,7 @@ H5AC_rename (hdf5_file_t *f, const H5AC_class_t *type,
*/
void *
H5AC_protect (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr,
const void *udata)
void *udata)
{
int idx;
void *thing = NULL;

@ -39,7 +39,7 @@
* by the LOAD method if the DEST argument is non-zero.
*/
typedef struct H5AC_class_t {
void *(*load)(hdf5_file_t*, haddr_t addr, const void *udata);
void *(*load)(hdf5_file_t*, haddr_t addr, void *udata);
herr_t (*flush)(hdf5_file_t*, hbool_t dest, haddr_t addr,
void *thing);
} H5AC_class_t;
@ -79,9 +79,9 @@ typedef struct H5AC_t {
*/
herr_t H5AC_dest (hdf5_file_t *f);
void *H5AC_find_f (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr,
const void *udata);
void *udata);
void * H5AC_protect (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr,
const void *udata);
void *udata);
herr_t H5AC_unprotect (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr,
void *thing);
herr_t H5AC_flush (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr,

@ -100,7 +100,7 @@
/* PRIVATE PROTOTYPES */
static haddr_t H5B_insert_helper (hdf5_file_t *f, haddr_t addr,
const H5B_class_t *type,
H5B_class_t *type,
uint8 *lt_key, hbool_t *lt_key_changed,
uint8 *md_key, void *udata,
uint8 *rt_key, hbool_t *rt_key_changed);
@ -109,14 +109,14 @@ static herr_t H5B_insert_child (hdf5_file_t *f, const H5B_class_t *type,
intn anchor, void *md_key);
static herr_t H5B_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr,
H5B_t *b);
static H5B_t *H5B_load (hdf5_file_t *f, haddr_t addr, const void *_data);
static H5B_t *H5B_load (hdf5_file_t *f, haddr_t addr, void *_data);
static herr_t H5B_decode_key (hdf5_file_t *f, H5B_t *bt, intn idx);
static size_t H5B_nodesize (hdf5_file_t *f, const H5B_class_t *type,
size_t *total_nkey_size, size_t sizeof_rkey);
/* H5B inherits cache-like properties from H5AC */
static const H5AC_class_t H5AC_BT[1] = {{
(void*(*)(hdf5_file_t*,haddr_t,const void*))H5B_load,
(void*(*)(hdf5_file_t*,haddr_t,void*))H5B_load,
(herr_t(*)(hdf5_file_t*,hbool_t,haddr_t,void*))H5B_flush,
}};
@ -231,13 +231,14 @@ H5B_new (hdf5_file_t *f, const H5B_class_t *type)
*-------------------------------------------------------------------------
*/
static H5B_t *
H5B_load (hdf5_file_t *f, haddr_t addr, const void *_data)
H5B_load (hdf5_file_t *f, haddr_t addr, void *_data)
{
const H5B_class_t *type = (const H5B_class_t *)_data;
const H5B_class_t *type = (H5B_class_t *)_data;
size_t size, total_nkey_size;
H5B_t *bt = NULL;
intn i;
uint8 *p;
H5B_t *ret_value = NULL;
FUNC_ENTER (H5B_load, NULL, NULL);
@ -263,11 +264,15 @@ H5B_load (hdf5_file_t *f, haddr_t addr, const void *_data)
p = bt->page;
/* magic number */
if (HDmemcmp (p, H5B_MAGIC, H5B_SIZEOF_MAGIC)) goto error;
if (HDmemcmp (p, H5B_MAGIC, H5B_SIZEOF_MAGIC)) {
HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, NULL);
}
p += 4;
/* node type and level */
if (*p++ != type->id) goto error;
if (*p++ != type->id) {
HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, NULL);
}
bt->level = *p++;
/* entries used */
@ -296,17 +301,18 @@ H5B_load (hdf5_file_t *f, haddr_t addr, const void *_data)
bt->key[2*H5B_K(f,type)].dirty = FALSE;
bt->key[2*H5B_K(f,type)].rkey = p;
bt->key[2*H5B_K(f,type)].nkey = NULL;
FUNC_LEAVE (bt);
ret_value = bt;
error:
if (bt) {
done:
if (!ret_value && bt) {
H5MM_xfree (bt->child);
H5MM_xfree (bt->key);
H5MM_xfree (bt->page);
H5MM_xfree (bt->native);
H5MM_xfree (bt);
}
HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, NULL);
FUNC_LEAVE (ret_value);
}
@ -438,7 +444,7 @@ H5B_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5B_t *bt)
*-------------------------------------------------------------------------
*/
herr_t
H5B_find (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, void *udata)
H5B_find (hdf5_file_t *f, H5B_class_t *type, haddr_t addr, void *udata)
{
H5B_t *bt=NULL;
intn idx=-1, lt=0, rt, cmp=1;
@ -538,7 +544,7 @@ done:
*-------------------------------------------------------------------------
*/
static haddr_t
H5B_split (hdf5_file_t *f, const H5B_class_t *type, H5B_t *old_bt,
H5B_split (hdf5_file_t *f, H5B_class_t *type, H5B_t *old_bt,
haddr_t old_addr, intn anchor)
{
H5B_t *new_bt=NULL, *tmp_bt=NULL;
@ -727,7 +733,7 @@ H5B_decode_key (hdf5_file_t *f, H5B_t *bt, intn idx)
*-------------------------------------------------------------------------
*/
haddr_t
H5B_insert (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, void *udata)
H5B_insert (hdf5_file_t *f, H5B_class_t *type, haddr_t addr, void *udata)
{
uint8 lt_key[256], md_key[256], rt_key[256];
hbool_t lt_key_changed=FALSE, rt_key_changed=FALSE;
@ -980,7 +986,7 @@ H5B_insert_child (hdf5_file_t *f, const H5B_class_t *type, H5B_t *bt,
*-------------------------------------------------------------------------
*/
static haddr_t
H5B_insert_helper (hdf5_file_t *f, haddr_t addr, const H5B_class_t *type,
H5B_insert_helper (hdf5_file_t *f, haddr_t addr, H5B_class_t *type,
uint8 *lt_key, hbool_t *lt_key_changed,
uint8 *md_key, void *udata,
uint8 *rt_key, hbool_t *rt_key_changed)
@ -1219,7 +1225,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
H5B_list (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, void *udata)
H5B_list (hdf5_file_t *f, H5B_class_t *type, haddr_t addr, void *udata)
{
H5B_t *bt=NULL;
haddr_t next_addr;
@ -1352,7 +1358,7 @@ H5B_nodesize (hdf5_file_t *f, const H5B_class_t *type,
*/
herr_t
H5B_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent,
intn fwidth, const H5B_class_t *type)
intn fwidth, H5B_class_t *type)
{
H5B_t *bt = NULL;
int i;

@ -91,13 +91,13 @@ typedef struct H5B_t {
* Library prototypes.
*/
herr_t H5B_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent,
intn fwidth, const H5B_class_t *type);
intn fwidth, H5B_class_t *type);
haddr_t H5B_new (hdf5_file_t *f, const H5B_class_t *type);
herr_t H5B_find (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr,
herr_t H5B_find (hdf5_file_t *f, H5B_class_t *type, haddr_t addr,
void *udata);
haddr_t H5B_insert (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr,
haddr_t H5B_insert (hdf5_file_t *f, H5B_class_t *type, haddr_t addr,
void *udata);
herr_t H5B_list (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr,
herr_t H5B_list (hdf5_file_t *f, H5B_class_t *type, haddr_t addr,
void *udata);

188
src/H5D.c

@ -45,6 +45,18 @@ static char RcsId[] = "@(#)$Revision$";
#define PABLO_MASK H5D_mask
/*
* A dataset is the following struct.
*/
typedef struct H5D_t {
hdf5_file_t *file; /* File store for this object */
H5G_entry_t *ent; /* Cached object header stuff */
h5_datatype_t *type; /* Datatype of this dataset */
H5P_dim_t *dim; /* Dimensionality of this dataset */
haddr_t data_addr; /* Data storage address */
hbool_t dirty; /* Header messages not updated yet */
} H5D_t;
/*--------------------- Locally scoped variables -----------------------------*/
/* Whether we've installed the library termination function yet for this interface */
@ -110,15 +122,16 @@ void H5D_term_interface (void)
RETURNS
Returns ID (atom) on success, FAIL on failure
DESCRIPTION
This function actually creates the dataset object, but it cannot be
accessed by name until it is stored in the file.
This function actually creates a dataset object in a file (of course,
output might not happen for some time).
--------------------------------------------------------------------------*/
hatom_t H5D_create(hatom_t owner_id, hobjtype_t type, const char *name)
{
H5D_t *new_dset; /* new dataset object to create */
hatom_t ret_value = SUCCEED;
hdf5_file_t *file = NULL;
hdf5_file_t *file = NULL;
H5G_entry_t tmp_ent;
FUNC_ENTER(H5D_create, H5D_init_interface, FAIL);
/* Clear errors and check args and all the boring stuff. */
@ -135,14 +148,37 @@ hatom_t H5D_create(hatom_t owner_id, hobjtype_t type, const char *name)
/* Initialize the dataset object */
new_dset->file = file;
new_dset->name = H5MM_xstrdup (name);
new_dset->cwd = file->root_sym;
new_dset->ent.header = -1; /* Not on disk yet */
new_dset->ent.type = H5G_NOTHING_CACHED;
new_dset->type=NULL; /* No type yet */
new_dset->dim=NULL; /* No dimensions yet */
new_dset->data_addr = -1; /* No data yet */
new_dset->modified=BTRUE; /* Yep, we're new */
new_dset->dirty = FALSE; /* There are no messages yet */
/* Create the (empty) object header in the file */
memset (&tmp_ent, 0, sizeof(tmp_ent));
if ((tmp_ent.header = H5O_new (file, 0, H5D_MINHDR_SIZE))<0) {
HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); /*can't create header*/
}
/*
* Link the (empty) object header into the symbol table so others can
* access it. At least that way no one will try to create another one of
* these things with the same name. We also hold the object open while
* H5D has a handle, preventing others from moving or deleting it from
* under us.
*/
#ifdef LATER
/* We should use the real CWD instead of always the root object! */
#else
H5G_shadow_sync (file->root_sym);
if (H5G_insert (file, file->root_sym, NULL, name, &tmp_ent)<0) {
/* Something by that name already exists, or some other failure */
HGOTO_ERROR (H5E_SYM, H5E_EXISTS, FAIL);
}
if (NULL==(new_dset->ent = H5G_open (file, file->root_sym, name))) {
/* Can't open the header we just created -- should never happen */
HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL);
}
#endif
/* Register the new datatype and get an ID for it */
if((ret_value=H5Aregister_atom(H5_DATASET, (const VOIDP)new_dset))<0)
@ -197,39 +233,44 @@ hatom_t H5D_find_name(hatom_t grp_id, hobjtype_t type, const char *name)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL);
/* Initialize file, directory, name fields */
dset->modified = FALSE;
dset->file = file;
dset->name = H5MM_xstrdup (name);
/* WARNING! WARNING! WARNING! */
/* The following line explicitly uses the root symbol as the
current working directory. This should be changed to something more
appropriate and is only hacked in here to get the prototype working. -QAK
*/
/* WARNING! WARNING! WARNING! */
dset->cwd = file->root_sym;
/* Get the dataset's symbol table entry */
if (H5G_find (dset->file, dset->cwd, NULL, dset->name, &(dset->ent))<0)
HGOTO_ERROR(H5E_DATASET, H5E_NOTFOUND, FAIL);
dset->dirty = FALSE;
#ifdef LATER
/* We should really use the real CWD instead of the root object! */
#else
/*
* WARNING! WARNING! WARNING!
* The following line explicitly uses the root symbol as the current
* working directory. This should be changed to something more
* appropriate and is only hacked in here to get the prototype working.
* -QAK
* WARNING! WARNING! WARNING!
*/
H5G_shadow_sync (file->root_sym);
if (NULL==(dset->ent=H5G_open (file, file->root_sym, name))) {
HGOTO_ERROR (H5E_DATASET, H5E_NOTFOUND, FAIL);
}
#endif
/* Get the dataset's type (currently only atomic types) */
if((dset->type=HDcalloc(1,sizeof(h5_datatype_t)))==NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL);
if (NULL==H5O_read (dset->file, dset->ent.header, &(dset->ent),
H5O_SIM_DTYPE, 0, dset->type))
if (NULL==H5O_read (dset->file, NO_ADDR, dset->ent, H5O_SIM_DTYPE, 0,
dset->type))
HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL);
/* Get the dataset's dimensionality (currently only simple dataspaces) */
if((dset->dim=HDcalloc(1,sizeof(H5P_dim_t)))==NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL);
dset->dim->type=H5P_TYPE_SIMPLE; /* for now... */
if (NULL==(dset->dim->s=H5O_read (dset->file, dset->ent.header,
&(dset->ent), H5O_SIM_DIM, 0, NULL)))
if (NULL==(dset->dim->s=H5O_read (dset->file, NO_ADDR, dset->ent,
H5O_SIM_DIM, 0, NULL)))
HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL);
/* Get the dataset's data offset (currently only standard storage) */
if (NULL==H5O_read (dset->file, dset->ent.header ,&(dset->ent),
H5O_STD_STORE, 0, &store))
if (NULL==H5O_read (dset->file, NO_ADDR, dset->ent, H5O_STD_STORE, 0,
&store))
HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL);
dset->data_addr=store.off;
@ -241,7 +282,6 @@ done:
if(ret_value == FAIL)
{ /* Error condition cleanup */
if (dset) {
dset->name = H5MM_xfree (dset->name);
#ifdef LATER
/* We might need to free the `type' and `dim' fields also... */
#endif
@ -290,9 +330,10 @@ herr_t H5Dset_info(hatom_t oid, hatom_t tid, hatom_t did)
if(dataset->type || dataset->dim)
HGOTO_ERROR(H5E_FUNC, H5E_ALREADYINIT, FAIL);
/* Update the dataset in memory */
dataset->type=H5Aatom_object(tid);
dataset->dim=H5Aatom_object(did);
dataset->modified=BTRUE; /* indicate the values have changed */
dataset->dirty = TRUE;
done:
if(ret_value == FAIL)
@ -499,7 +540,7 @@ herr_t H5Dwrite(hatom_t oid, hatom_t did, VOIDP buf)
if(dataset->data_addr<0) {
if((dataset->data_addr=H5MF_alloc(dataset->file,towrite))<0)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL);
dataset->modified = TRUE;
dataset->dirty = TRUE;
}
/* Check memory to disk datatype conversions, etc. */
@ -551,9 +592,6 @@ herr_t H5D_flush(hatom_t oid)
{
H5D_t *dataset; /* dataset object to release */
herr_t ret_value = SUCCEED;
intn mesg_sequence = 0; /*message sequence number */
hbool_t new_dataset; /*is this a new dataset on disk?*/
hbool_t entry_changed = FALSE; /*did symbol table entry change?*/
FUNC_ENTER(H5D_flush, H5D_init_interface, FAIL);
@ -564,37 +602,15 @@ herr_t H5D_flush(hatom_t oid)
if((dataset=H5Aatom_object(oid))==NULL)
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);
if (dataset->modified) {
/*
* A new dataset is one which doesn't exist on disk yet.
*/
new_dataset = (dataset->ent.header < 0);
/*
* If the dataset is new then create an object header for it. Set the
* message sequence numbers to H5O_NEW_MESSAGE so we create new
* messages instead of trying to modify existing messages.
*/
if (new_dataset) {
dataset->ent.type = H5G_NOTHING_CACHED;
if ((dataset->ent.header = H5O_new (dataset->file, 0,
H5D_MINHDR_SIZE))<0) {
/* Can't create header. */
HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL);
}
mesg_sequence = H5O_NEW_MESG;
}
if (dataset->dirty) {
/*
* Create or update messages for this dataset. Begin with the
* Modify/create messages for this dataset. Begin with the
* type information.
*/
if (H5T_is_atomic (dataset->type)) {
if (H5O_modify (dataset->file, dataset->ent.header,
&(dataset->ent), &entry_changed, H5O_SIM_DTYPE,
mesg_sequence, dataset->type)<0) {
if (H5O_modify (dataset->file, NO_ADDR, dataset->ent,
H5O_SIM_DTYPE, 0, dataset->type)<0) {
/* Can't create/update type message */
HGOTO_ERROR (H5E_INTERNAL, H5E_CANTCREATE, FAIL);
}
@ -604,12 +620,11 @@ herr_t H5D_flush(hatom_t oid)
}
/*
* Write the dimensionality information.
* Modify/create the dimensionality information.
*/
if (H5P_is_simple (dataset->dim)) {
if (H5O_modify (dataset->file, dataset->ent.header,
&(dataset->ent), &entry_changed, H5O_SIM_DIM,
mesg_sequence, dataset->dim->s)<0) {
if (H5O_modify (dataset->file, NO_ADDR, dataset->ent,
H5O_SIM_DIM, 0, dataset->dim->s)<0) {
/* Can't create/update dimensionality message */
HGOTO_ERROR (H5E_INTERNAL, H5E_CANTCREATE, FAIL);
}
@ -619,7 +634,7 @@ herr_t H5D_flush(hatom_t oid)
}
/*
* Write the dataset's storage information.
* Modify/create the dataset's storage information.
*/
if (dataset->data_addr>=0) {
H5O_std_store_t store; /* standard storage info */
@ -627,41 +642,21 @@ herr_t H5D_flush(hatom_t oid)
store.len = H5T_size (dataset->type, BTRUE) *
H5P_nelem (dataset->dim);
store.off = dataset->data_addr;
if (H5O_modify (dataset->file, dataset->ent.header,
&(dataset->ent), &entry_changed, H5O_STD_STORE,
mesg_sequence, &store)<0) {
if (H5O_modify (dataset->file, NO_ADDR, dataset->ent,
H5O_STD_STORE, 0, &store)<0) {
/* Can't create/modify storage information */
HGOTO_ERROR (H5E_INTERNAL, H5E_CANTCREATE, FAIL);
}
}
/*
* If this is a new dataset then we must give it a name so others can
* access it.
*/
if (new_dataset) {
assert (dataset->name);
if (H5G_insert (dataset->file, dataset->cwd, NULL,
dataset->name, &(dataset->ent))<0) {
/* Can't name dataset */
HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL);
}
} else if (entry_changed) {
if (H5G_modify (dataset->file, dataset->cwd, NULL,
dataset->name, &(dataset->ent))<0) {
/* Can't update symbol table entry */
HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL);
}
}
#ifdef ROBB
/* Flush dataset header to disk */
if (H5O_flush (dataset->file, FALSE, dataset->ent.header, NULL)<0) {
#if 1
/* Flush dataset header to disk -- just for debugging */
if (H5AC_flush (dataset->file, NULL, dataset->ent->header, FALSE)<0) {
HRETURN_ERROR (H5E_OHDR, H5E_CANTFLUSH, FAIL);
}
#endif /* ROBB */
dataset->modified = FALSE; /*it's clean now*/
#endif
dataset->dirty = FALSE; /*it's clean now*/
}
done:
@ -703,13 +698,16 @@ herr_t H5D_release(hatom_t oid)
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);
/* Check if we have information to flush to the file... */
if(dataset->modified && H5D_flush(oid)<0) {
if(dataset->dirty && H5D_flush(oid)<0) {
/* Can't flush dataset */
HGOTO_ERROR (H5E_OHDR, H5E_CANTFLUSH, FAIL);
}
/* Close the dataset object */
H5G_close (dataset->file, dataset->ent);
dataset->ent = NULL;
/* release the memory used for the dataset */
dataset->name = H5MM_xfree (dataset->name);
H5MM_xfree (dataset);
/* Delete the dataset from the atom group */

@ -28,21 +28,6 @@
#include <H5Pprivate.h> /* for the H5P_sdim_t type */
#include <H5Oprivate.h> /* Object Headers */
/*
* A dataset is the following struct. It can exist in memory without
* existing in a file.
*/
typedef struct H5D_t {
hdf5_file_t *file; /* File store for this object */
char *name; /* Name of dataset, relative or absolute */
H5G_entry_t *cwd; /* Directory for relative name lookup */
H5G_entry_t ent; /* Cached object header stuff */
h5_datatype_t *type; /* Datatype of this dataset */
H5P_dim_t *dim; /* Dimensionality of this dataset */
haddr_t data_addr; /* Data storage address */
hbool_t modified; /* Is memory out of data wrt file? */
} H5D_t;
#define H5D_RESERVED_ATOMS 0
/* Set the minimum object header size to create objects with */

@ -77,7 +77,8 @@ static const hdf_min_error_messages_t hdf_min_error_messages[] =
{H5E_FILEEXISTS, "File already exists"},
{H5E_FILEOPEN, "File already open"},
{H5E_CANTCREATE, "Can't create file"},
{H5E_CANTOPEN, "Can't open file"},
{H5E_CANTOPENFILE, "Can't open file"},
{H5E_CANTOPENOBJ, "Can't open object"},
{H5E_NOTHDF5, "Not an HDF5 format file"},
{H5E_BADFILE, "Bad file ID accessed"},
{H5E_SEEKERROR, "Seek failed"},
@ -90,6 +91,7 @@ static const hdf_min_error_messages_t hdf_min_error_messages[] =
{H5E_CANTFLUSH, "Can't flush object from cache"},
{H5E_CANTLOAD, "Can't load object into cache"},
{H5E_PROTECT, "Protected object error"},
{H5E_NOTCACHED, "Object not currently cached"},
{H5E_NOTFOUND, "Object not found"},
{H5E_EXISTS, "Object already exists"},
{H5E_CANTENCODE, "Can't encode value"},

@ -64,7 +64,7 @@ typedef enum
H5E_FILEEXISTS, /* File already exists */
H5E_FILEOPEN, /* File already open */
H5E_CANTCREATE, /* Can't create file */
H5E_CANTOPEN, /* Can't open file */
H5E_CANTOPENFILE, /* Can't open file */
H5E_NOTHDF5, /* Not an HDF5 format file */
H5E_BADFILE, /* Bad file ID accessed */
@ -85,7 +85,8 @@ typedef enum
H5E_CANTFLUSH, /* Can't flush object from cache */
H5E_CANTLOAD, /* Can't load object into cache */
H5E_PROTECT, /* Protected object error */
H5E_NOTCACHED, /* Object not currently cached */
/* B-tree related errors */
H5E_NOTFOUND, /* Object not found */
H5E_EXISTS, /* Object already exists */
@ -102,6 +103,7 @@ typedef enum
H5E_BADMESG, /* Unrecognized message */
/* Directory related errors */
H5E_CANTOPENOBJ, /* Can't open object */
H5E_COMPLEN, /* Name component is too long */
H5E_LINK /* Link count failure */
}

@ -399,8 +399,7 @@ H5F_new (void)
H5AC_new (f, H5AC_NSLOTS);
/* Create a root symbol slot */
f->root_sym = H5MM_xcalloc (1, sizeof (H5G_entry_t));
f->root_sym->type = H5G_NOTHING_CACHED;
f->root_sym = H5G_new_entry ();
return f;
}
@ -688,7 +687,7 @@ hatom_t H5Fopen(const char *filename, uintn flags, hatom_t access_temp)
/* Check if the file already exists */
f_handle=H5F_OPEN(filename,flags);
if(H5F_OPENERR(f_handle))
HGOTO_ERROR(H5E_FILE, H5E_CANTOPEN, FAIL);/*file doesn't exist*/
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL);/*file doesn't exist*/
/* Create the file node */
if (NULL==(new_file=H5F_new()))

@ -185,10 +185,22 @@ typedef MPFILE *hdf_file_t;
*(p) = (uint8)(((uint64)(i) >> 8) & 0xff); (p)++; \
*(p) = (uint8)(((uint64)(i) >> 16) & 0xff); (p)++; \
*(p) = (uint8)(((uint64)(i) >> 24) & 0xff); (p)++; \
*(p) = (uint8)(((uint64)(i) >> 32) & 0xff); (p)++; \
*(p) = (uint8)(((uint64)(i) >> 40) & 0xff); (p)++; \
*(p) = (uint8)(((uint64)(i) >> 48) & 0xff); (p)++; \
*(p) = (uint8)(((uint64)(i) >> 56) & 0xff); (p)++; \
if (sizeof(int64)>4) { \
*(p) = (uint8)(((uint64)(i) >> 32) & 0xff); (p)++; \
*(p) = (uint8)(((uint64)(i) >> 40) & 0xff); (p)++; \
*(p) = (uint8)(((uint64)(i) >> 48) & 0xff); (p)++; \
*(p) = (uint8)(((uint64)(i) >> 56) & 0xff); (p)++; \
} else if ((i)<0) { \
*(p)++ = 0xff; \
*(p)++ = 0xff; \
*(p)++ = 0xff; \
*(p)++ = 0xff; \
} else { \
*(p)++ = 0x00; \
*(p)++ = 0x00; \
*(p)++ = 0x00; \
*(p)++ = 0x00; \
} \
}
# define UINT64ENCODE(p, i) { \
@ -196,10 +208,17 @@ typedef MPFILE *hdf_file_t;
*(p) = (uint8)(((i) >> 8) & 0xff); (p)++; \
*(p) = (uint8)(((i) >> 16) & 0xff); (p)++; \
*(p) = (uint8)(((i) >> 24) & 0xff); (p)++; \
*(p) = (uint8)(((i) >> 32) & 0xff); (p)++; \
*(p) = (uint8)(((i) >> 40) & 0xff); (p)++; \
*(p) = (uint8)(((i) >> 48) & 0xff); (p)++; \
*(p) = (uint8)(((i) >> 56) & 0xff); (p)++; \
if (sizeof(uint64)>4) { \
*(p) = (uint8)(((i) >> 32) & 0xff); (p)++; \
*(p) = (uint8)(((i) >> 40) & 0xff); (p)++; \
*(p) = (uint8)(((i) >> 48) & 0xff); (p)++; \
*(p) = (uint8)(((i) >> 56) & 0xff); (p)++; \
} else { \
*(p)++ = 0x00; \
*(p)++ = 0x00; \
*(p)++ = 0x00; \
*(p)++ = 0x00; \
} \
}
# define INT16DECODE(p, i) { \
@ -231,10 +250,14 @@ typedef MPFILE *hdf_file_t;
(i) |= ((int64)(*(p) & 0xff) << 8); (p)++; \
(i) |= ((int64)(*(p) & 0xff) << 16); (p)++; \
(i) |= ((int64)(*(p) & 0xff) << 24); (p)++; \
(i) |= ((int64)(*(p) & 0xff) << 32); (p)++; \
(i) |= ((int64)(*(p) & 0xff) << 40); (p)++; \
(i) |= ((int64)(*(p) & 0xff) << 48); (p)++; \
(i) |= ((int64)(*(p) & 0xff) << 56); (p)++; \
if (sizeof(int64)>4) { \
(i) |= ((int64)(*(p) & 0xff) << 32); (p)++; \
(i) |= ((int64)(*(p) & 0xff) << 40); (p)++; \
(i) |= ((int64)(*(p) & 0xff) << 48); (p)++; \
(i) |= ((int64)(*(p) & 0xff) << 56); (p)++; \
} else { \
(p) += 4; \
} \
}
# define UINT64DECODE(p, i) { \
@ -242,10 +265,14 @@ typedef MPFILE *hdf_file_t;
(i) |= ((uint64)(*(p) & 0xff) << 8); (p)++; \
(i) |= ((uint64)(*(p) & 0xff) << 16); (p)++; \
(i) |= ((uint64)(*(p) & 0xff) << 24); (p)++; \
(i) |= ((uint64)(*(p) & 0xff) << 32); (p)++; \
(i) |= ((uint64)(*(p) & 0xff) << 40); (p)++; \
(i) |= ((uint64)(*(p) & 0xff) << 48); (p)++; \
(i) |= ((uint64)(*(p) & 0xff) << 56); (p)++; \
if (sizeof(uint64)>4) { \
(i) |= ((uint64)(*(p) & 0xff) << 32); (p)++; \
(i) |= ((uint64)(*(p) & 0xff) << 40); (p)++; \
(i) |= ((uint64)(*(p) & 0xff) << 48); (p)++; \
(i) |= ((uint64)(*(p) & 0xff) << 56); (p)++; \
} else { \
(p) += 4; \
} \
}
#else
@ -254,8 +281,29 @@ typedef MPFILE *hdf_file_t;
# define UINT16ENCODE(p, i) { *((uint16 *)(p)) = (uint16)(i); (p)+=2; }
# define INT32ENCODE(p, i) { *((int32 *)(p)) = (int32)(i); (p)+=4; }
# define UINT32ENCODE(p, i) { *((uint32 *)(p)) = (uint32)(i); (p)+=4; }
# define INT64ENCODE(p, i) { *((int64 *)(p)) = (int64)(i); (p)+=8; }
# define UINT64ENCODE(p, i) { *((uint64 *)(p)) = (uint64)(i); (p)+=8; }
# define INT64ENCODE(p, i) { \
*((int64 *)(p)) = (int64)(i); \
(p) += sizeof(int64); \
if (4==sizeof(int64)) { \
*(p)++ = (i)<0?0xff:0x00; \
*(p)++ = (i)<0?0xff:0x00; \
*(p)++ = (i)<0?0xff:0x00; \
*(p)++ = (i)<0?0xff:0x00; \
} \
}
# define UINT64ENCODE(p, i) { \
*((uint64 *)(p)) = (uint64)(i); \
(p) += sizeof(uint64); \
if (4==sizeof(uint64)) { \
*(p)++ = 0x00; \
*(p)++ = 0x00; \
*(p)++ = 0x00; \
*(p)++ = 0x00; \
} \
}
# define INT16DECODE(p, i) { (i) = (int16)(*(const int16 *)(p)); (p)+=2; }
# define UINT16DECODE(p, i) { (i) = (uint16)(*(const uint16 *)(p)); (p)+=2; }
# define INT32DECODE(p, i) { (i) = (int32)(*(const int32 *)(p)); (p)+=4; }

462
src/H5G.c

@ -28,25 +28,29 @@
* Robb Matzke, 30 Aug 1997
* Added `Errors:' field to function prologues.
*
* Robb Matzke, 18 Sep 1997
* Added shadow entry support.
*
*-------------------------------------------------------------------------
*/
#define H5G_PACKAGE /*suppress error message about including H5Gpkg.h*/
/* Packages needed by this file... */
#include <H5private.h>
#include <H5Bprivate.h>
#include <H5Eprivate.h>
#include <H5Gprivate.h>
#include <H5Gpkg.h>
#include <H5Hprivate.h>
#include <H5MMprivate.h>
#include <H5Oprivate.h>
#define H5G_INIT_HEAP 8192
#define PABLO_MASK H5G_mask
#define PABLO_MASK H5G_mask
static herr_t H5G_mkroot (hdf5_file_t *f, size_t size_hint);
/* Is the interface initialized? */
static intn interface_initialize_g = FALSE;
static hbool_t interface_initialize_g = FALSE;
/*-------------------------------------------------------------------------
@ -155,37 +159,35 @@ H5G_basename (const char *name, size_t *size_p)
*
* If the name cannot be fully resolved, then REST will
* point to the part of NAME where the traversal failed
* (REST will always point to a relative name) and BASE_ENT
* will not be initialized. DIR_ENT will be initialized with
* (REST will always point to a relative name) and this
* function will return null. DIR_ENT will be initialized with
* information about the directory (or other object) at which
* the traversal failed. However, if the name can be fully
* resolved, then REST points to the null terminator of NAME.
*
* As a special case, if the NAME is the name `/' (or
* equivalent) then DIR_ENT is initialized to all zero and
* BASE_ENT is initialized with the contents of the root
* symbol table entry.
* equivalent) then DIR_ENT is initialized to all zero
* and a pointer to the root symbol table entry is returned.
*
* As a special case, if the NAME is the string `/foo' (or
* equivalent) and the root symbol table entry points to a
* non-directory object with a name message with the value
* `foo' then DIR_ENT is initialized to all zero and BASE_ENT
* is initialized with the contents of the root symbol table
* entry.
* `foo' then DIR_ENT is initialized to all zero and a pointer
* to the root symbol table entry is returned.
*
* Errors:
* DIRECTORY COMPLEN Component is too long.
* DIRECTORY NOTFOUND Component not found.
* DIRECTORY NOTFOUND Root not found.
*
* Return: Success: SUCCEED if the name can be fully
* resolved.
* Return: Success: Pointer to a cached symbol table entry if the
* name can be fully resolved. The pointer is
* valid until one of the H5AC (cache) functions
* is called.
*
* Failure: FAIL if something bad happened (REST and
* DIR_ENT have undefined values).
*
* -2 if the name could not be fully resolved
* (REST and DIR_ENT are initialized).
* Failure: Null if the name could not be fully resolved.
* REST and DIR_ENT are initialized (possibly to
* zero if the failure occurred soon enough).
*
* Programmer: Robb Matzke
* robb@maya.nuance.com
@ -195,17 +197,21 @@ H5G_basename (const char *name, size_t *size_p)
*
*-------------------------------------------------------------------------
*/
static herr_t
static H5G_entry_t *
H5G_namei (hdf5_file_t *f, H5G_entry_t *cwd, const char *name,
const char **rest, H5G_entry_t *dir_ent, H5G_entry_t *base_ent)
const char **rest, H5G_entry_t *dir_ent)
{
H5G_entry_t ent[2];
H5G_entry_t *tmp, *dir, *base; /*ptrs to DIR and BASE entries */
H5G_entry_t dir; /*entry for current directory */
size_t nchars; /*component name length */
char comp[1024]; /*component name buffer */
hbool_t aside = FALSE; /*did we look at a name message?*/
H5G_entry_t *ret_value=NULL; /*return value */
/* clear output args before FUNC_ENTER() in case it fails */
if (rest) *rest = name;
if (dir_ent) memset (dir_ent, 0, sizeof(H5G_entry_t));
FUNC_ENTER (H5G_namei, NULL, FAIL);
FUNC_ENTER (H5G_namei, NULL, NULL);
/* check args */
assert (f);
@ -214,26 +220,30 @@ H5G_namei (hdf5_file_t *f, H5G_entry_t *cwd, const char *name,
assert (cwd || '/'==*name);
/* starting point */
dir = ent+0;
base = ent+1;
if ('/'==*name) {
ent[0] = ent[1] = *(f->root_sym);
if (f->root_sym->header<=0) {
HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, NULL);
}
ret_value = f->root_sym;
dir = *(f->root_sym);
} else {
ent[0] = ent[1] = *cwd;
ret_value = cwd;
dir = *cwd;
}
/* traverse the name */
while ((name=H5G_component (name, &nchars)) && *name) {
/*
* The special name `.'.
* The special name `.' is a no-op.
*/
if ('.'==name[0] && !name[1]) continue;
/*
* Advance.
* Advance to the next component of the name.
*/
tmp=dir; dir=base; base=tmp; /*swap*/
dir = *ret_value;
ret_value = NULL;
if (rest) *rest = name;
/*
@ -242,38 +252,32 @@ H5G_namei (hdf5_file_t *f, H5G_entry_t *cwd, const char *name,
*/
if (nchars+1 > sizeof(comp)) {
/* component is too long */
if (dir_ent) *dir_ent = *dir;
HRETURN_ERROR (H5E_DIRECTORY, H5E_COMPLEN, -2);
if (dir_ent) *dir_ent = dir;
HRETURN_ERROR (H5E_DIRECTORY, H5E_COMPLEN, NULL);
}
HDmemcpy (comp, name, nchars);
comp[nchars] = '\0';
if (H5G_stab_find (f, dir, comp, base)<0) {
if (NULL==(ret_value=H5G_stab_find (f, NO_ADDR, &dir, comp))) {
/*
* Component was not found in the current symbol table, probably
* because it isn't a symbol table. If it is the root symbol then
* Component was not found in the current symbol table, possibly
* because DIR isn't a symbol table. If it is the root symbol then
* see if it has the appropriate name field. The ASIDE variable
* prevents us from saying `/foo/foo' where the root object has
* the name `foo'.
*/
H5O_name_t mesg={0};
if (!aside && dir->header==f->root_sym->header &&
H5O_read (f, dir->header, dir, H5O_NAME, 0, &mesg)) {
if (!HDstrcmp (mesg.s, comp)) {
H5O_reset (H5O_NAME, &mesg);
*base = *dir;
aside = TRUE;
} else {
/* component not found */
H5O_reset (H5O_NAME, &mesg);
if (dir_ent) *dir_ent = *dir;
HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, -2);
}
if (!aside && dir.header==f->root_sym->header &&
H5O_read (f, dir.header, &dir, H5O_NAME, 0, &mesg) &&
!HDstrcmp (mesg.s, comp)) {
H5O_reset (H5O_NAME, &mesg);
ret_value = f->root_sym;
aside = TRUE;
} else {
/* component not found */
if (dir_ent) *dir_ent = *dir;
HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, -2);
H5O_reset (H5O_NAME, &mesg);
if (dir_ent) *dir_ent = dir;
HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, NULL);
}
}
@ -284,20 +288,19 @@ H5G_namei (hdf5_file_t *f, H5G_entry_t *cwd, const char *name,
/* output parameters */
if (rest) *rest = name; /*final null*/
if (dir_ent) {
if (base->header == f->root_sym->header) {
if (ret_value->header == f->root_sym->header) {
HDmemset (dir_ent, 0, sizeof(H5G_entry_t)); /*root has no parent*/
} else {
*dir_ent = *dir;
*dir_ent = dir;
}
}
if (base_ent) *base_ent = *base;
/* Perhaps the root object doesn't even exist! */
if (base->header<=0) {
HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, -2); /*root not found*/
if (ret_value->header<=0) {
HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, NULL); /*root not found*/
}
FUNC_LEAVE (SUCCEED);
FUNC_LEAVE (ret_value);
}
@ -338,29 +341,30 @@ H5G_mkroot (hdf5_file_t *f, size_t size_hint)
H5G_entry_t root; /*old root entry */
const char *root_name=NULL; /*name of old root object */
intn nlinks; /*number of links */
hbool_t reset = FALSE; /*should name message be reset? */
H5G_entry_t *handle; /*handle for open object */
FUNC_ENTER (H5G_mkroot, NULL, FAIL);
/*
* Make sure we have the latest info since someone might have the root
* object open for modifications.
*/
H5G_shadow_sync (f->root_sym);
/*
* Is there already a root object that needs to move into the new
* root symbol table? The root object is a symbol table if we can
* read the H5O_STAB message.
*/
if (f->root_sym->header>0) {
if (H5O_read (f, f->root_sym->header, f->root_sym, H5O_STAB, 0, &stab)) {
if (H5O_read (f, NO_ADDR, f->root_sym, H5O_STAB, 0, &stab)) {
/* root directory already exists */
HRETURN_ERROR (H5E_DIRECTORY, H5E_EXISTS, FAIL);
} else if (H5O_read (f, f->root_sym->header, f->root_sym, H5O_NAME,
0, &name)) {
/*dont reset name until root_name is done*/
root_name = name.s;
reset = TRUE;
/* remove all name messages -- don't care if it fails */
root_name = name.s; /*dont reset name until root_name is done!*/
root = *(f->root_sym);
H5O_remove (f, root.header, &root, NULL, H5O_NAME, H5O_ALL);
} else {
root = *(f->root_sym);
@ -392,15 +396,31 @@ H5G_mkroot (hdf5_file_t *f, size_t size_hint)
nlinks = H5O_link (f, root.header, &root, 0);
assert (1==nlinks);
#endif
if (H5G_stab_insert (f, f->root_sym, root_name, &root)) {
if (H5G_stab_insert (f, f->root_sym, root_name, &root)<0) {
/*
* This should never happen. If it does and the root object is
* open, then bad things are going to happen because we've just
* deleted the symbol table entry for the open root object!
*/
#ifndef NDEBUG
abort ();
#endif
/* can't insert old root object in new root directory */
H5O_reset (H5O_NAME, &name);
HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL);
}
if (reset) H5O_reset (H5O_NAME, &name);
/* remove all name messages -- don't care if it fails */
if ((handle = H5G_open (f, f->root_sym, root_name))) {
H5O_remove (f, NO_ADDR, handle, H5O_NAME, H5O_ALL);
H5G_shadow_close (f, handle);
handle = NULL;
}
H5ECLEAR;
}
H5O_reset (H5O_NAME, &name);
FUNC_LEAVE (SUCCEED);
}
@ -449,7 +469,6 @@ H5G_new (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
{
const char *rest=NULL;
H5G_entry_t _parent, _child;
herr_t status;
char _comp[1024];
size_t nchars;
@ -467,10 +486,7 @@ H5G_new (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
H5ECLEAR;
/* lookup name */
status = H5G_namei (f, cwd, name, &rest, dir_ent, NULL);
if (status<0 && !rest) {
HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL); /*lookup failed*/
} else if (0==status) {
if (H5G_namei (f, cwd, name, &rest, dir_ent)) {
HRETURN_ERROR (H5E_DIRECTORY, H5E_EXISTS, FAIL); /*already exists*/
}
H5ECLEAR; /*it's OK that we didn't find it*/
@ -506,6 +522,91 @@ H5G_new (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
FUNC_LEAVE (SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5G_open
*
* Purpose: Opens an object. That is, it prepares the object for
* modification by returning a handle to the object
* symbol table entry. Opening an object twice with the
* same name (or more precisely, through the same final
* symbol table entry) will return pointers to the same
* H5G_entry_t struct. But opening an object through
* different final H5G_entry_t structs (which implies
* different names) returns pointers to different
* structs. The structs that are returned should be
* released by calling H5G_close().
*
* Return: Success: Ptr to a handle for the object.
*
* Failure: NULL
*
* Programmer: Robb Matzke
* Wednesday, September 17, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
H5G_entry_t *
H5G_open (hdf5_file_t *f, H5G_entry_t *cwd, const char *name)
{
H5G_entry_t *ent=NULL;
H5G_entry_t *handle=NULL;
H5G_entry_t dir;
FUNC_ENTER (H5G_open, NULL, NULL);
/* check args */
assert (f);
assert (name && *name);
assert (cwd || '/'==*name);
if (f->root_sym->header<=0) {
HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, NULL); /*object not found*/
}
if (NULL==(ent=H5G_namei (f, cwd, name, NULL, &dir))) {
HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, NULL); /*object not found*/
}
if (NULL==(handle=H5G_shadow_open (f, &dir, ent))) {
HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTOPENOBJ, NULL);
}
FUNC_LEAVE (handle);
}
/*-------------------------------------------------------------------------
* Function: H5G_close
*
* Purpose: Closes an object that was open for modification.
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Thursday, September 18, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5G_close (hdf5_file_t *f, H5G_entry_t *ent)
{
FUNC_ENTER (H5G_close, NULL, FAIL);
if (H5G_shadow_close (f, ent)<0) {
HRETURN_ERROR (H5E_SYM, H5E_CANTFLUSH, FAIL);
}
FUNC_LEAVE (SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5G_find
@ -527,7 +628,14 @@ H5G_new (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
* Errors:
* DIRECTORY NOTFOUND Object not found.
*
* Return: Success: SUCCEED with DIR_ENT and ENT initialized.
* Return: Success: SUCCEED with DIR_ENT and ENT initialized. ENT
* is intended for immediate read-only access.
* If the object that ENT refers to is open
* through the ENT entry (see H5G_open()) then
* the returned ENT will contain the latest
* information. However, subsequent changes to
* the symbol table entry will not be reflected
* in ENT since it is a copy of the symbol table.
*
* Failure: FAIL
*
@ -543,6 +651,7 @@ herr_t
H5G_find (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
const char *name, H5G_entry_t *ent)
{
H5G_entry_t *ent_p = NULL;
FUNC_ENTER (H5G_find, NULL, FAIL);
/* check args */
@ -554,10 +663,11 @@ H5G_find (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, FAIL); /*object not found*/
}
if (H5G_namei (f, cwd, name, NULL, dir_ent, ent)<0) {
if (NULL==(ent_p=H5G_namei (f, cwd, name, NULL, dir_ent))) {
HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, FAIL); /*object not found*/
}
if (ent) *ent = *ent_p;
FUNC_LEAVE (SUCCEED);
}
@ -608,7 +718,6 @@ herr_t
H5G_insert (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
const char *name, H5G_entry_t *ent)
{
herr_t status;
const char *rest=NULL;
H5G_entry_t _parent;
size_t nchars;
@ -622,8 +731,9 @@ H5G_insert (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
assert (name && *name);
assert (cwd || '/'==*name);
assert (ent);
assert (!ent->shadow);
if (!dir_ent) dir_ent = &_parent;
/*
* If there's already an object or if this object is a directory then
* create a root directory. The object is a directory if we can read
@ -639,10 +749,7 @@ H5G_insert (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
/*
* Look up the name -- it shouldn't exist yet.
*/
status = H5G_namei (f, cwd, name, &rest, dir_ent, NULL);
if (status<0 && !rest) {
HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL); /*lookup failed*/
} else if (0==status) {
if (H5G_namei (f, cwd, name, &rest, dir_ent)) {
HRETURN_ERROR (H5E_DIRECTORY, H5E_EXISTS, FAIL); /*already exists*/
}
H5ECLEAR; /*it's OK that we didn't find it*/
@ -687,14 +794,12 @@ H5G_insert (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
/*
* If this is the only object then insert it as the root object. Add
* a name messaage to the object header (or modify the first one we
* find).
* find). We don't have to worry about it being open.
*/
if (f->root_sym->header<=0) {
H5O_name_t name_mesg;
name_mesg.s = rest;
if (H5O_modify (f, ent->header, ent, NULL, H5O_NAME, 0, &name_mesg)<0 &&
H5O_modify (f, ent->header, ent, NULL, H5O_NAME, H5O_NEW_MESG,
&name_mesg)<0) {
if (H5O_modify (f, NO_ADDR, ent, H5O_NAME, 0, &name_mesg)<0) {
/* cannot add/change name message */
HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL);
}
@ -719,73 +824,6 @@ H5G_insert (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
FUNC_LEAVE (SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5G_modify
*
* Purpose: Modifies the symbol table entry for the object with the
* specified NAME by copying the new symbol table entry ENT
* over the top of the old one. If NAME is relative then it
* is interpreted with respect to the CWD pointer. If non-null,
* DIR_ENT will be initialized with the symbol table entry for the
* directory which contains the new ENT.
*
* Do not use this function to change the entry for the root
* symbol since that's a special case. This function returns
* failure if that is attempted.
*
* Errors:
* DIRECTORY CANTINIT Can't modify.
* DIRECTORY NOTFOUND Entry not found.
*
* Return: Success: SUCCEED with optional DIR_ENT initialized with
* the symbol table entry for the directory
* which contains the new ENT.
*
* Failure: FAIL (DIR_ENT is not modified).
*
* Programmer: Robb Matzke
* robb@maya.nuance.com
* Aug 11 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5G_modify (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
const char *name, H5G_entry_t *ent)
{
const char *rest=NULL;
H5G_entry_t _parent;
FUNC_ENTER (H5G_modify, NULL, FAIL);
/* check args */
assert (f);
assert (name && *name);
assert (cwd || '/'==*name);
assert (ent);
if (!dir_ent) dir_ent = &_parent;
/* lookup name */
if (H5G_namei (f, cwd, name, &rest, dir_ent, NULL)<0) {
HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, FAIL); /*entry not found*/
}
/*
* Modify the entry in the parent or in the file struct.
*/
if (dir_ent->header<=0) {
*(f->root_sym) = *ent;
} else if (H5G_stab_modify (f, dir_ent, rest, ent)<0) {
HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL); /*can't modify*/
}
FUNC_LEAVE (SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5G_stab_new
@ -869,11 +907,10 @@ H5G_stab_new (hdf5_file_t *f, H5G_entry_t *self, size_t init)
/* insert the symbol table message */
if (self) {
self->name_off = 0;
memset (self, 0, sizeof(H5G_entry_t));
self->header = addr;
self->type = H5G_NOTHING_CACHED;
}
if (H5O_modify(f, addr, self, NULL, H5O_STAB, H5O_NEW_MESG, &stab)<0) {
if (H5O_modify(f, addr, self, H5O_STAB, H5O_NEW_MESG, &stab)<0) {
HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); /*can't create message*/
}
@ -886,15 +923,22 @@ H5G_stab_new (hdf5_file_t *f, H5G_entry_t *self, size_t init)
*
* Purpose: Finds a symbol named NAME in the symbol table whose
* description is stored in SELF in file F and returns a
* copy of the symbol table entry through the ENT argument.
* pointer to the symbol table entry. SELF is optional if the
* symbol table address is supplied through ADDR.
*
* Errors:
* SYM BADMESG Can't read message.
* SYM NOTFOUND Not found.
*
* Return: Success: Address corresponding to the name.
* Return: Success: Pointer to the symbol table entry.
* The pointer is intended for immediate
* read-only access since it points
* directly to an entry in a cached
* symbol table node. The pointer is
* guaranteed to be valid only until the
* next call to one of the H5AC functions.
*
* Failure: FAIL
* Failure: NULL
*
* Programmer: Robb Matzke
* matzke@llnl.gov
@ -904,93 +948,41 @@ H5G_stab_new (hdf5_file_t *f, H5G_entry_t *self, size_t init)
*
*-------------------------------------------------------------------------
*/
haddr_t
H5G_stab_find (hdf5_file_t *f, H5G_entry_t *self, const char *name,
H5G_entry_t *ent)
H5G_entry_t *
H5G_stab_find (hdf5_file_t *f, haddr_t addr, H5G_entry_t *self,
const char *name)
{
H5G_node_ud1_t udata; /*data to pass through B-tree */
H5G_bt_ud1_t udata; /*data to pass through B-tree */
H5O_stab_t stab; /*symbol table message */
FUNC_ENTER (H5G_stab_find, NULL, FAIL);
FUNC_ENTER (H5G_stab_find, NULL, NULL);
/* Check arguments */
assert (f);
assert (self && self->header>=0);
assert (name && *name);
if (addr<=0 && (!self || self->header<=0)) {
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL);
}
if (!name || !*name) {
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL);
}
if (addr<=0) addr = self->header;
/* set up the udata */
if (NULL==H5O_read (f, self->header, self, H5O_STAB, 0, &stab)) {
HRETURN_ERROR (H5E_SYM, H5E_BADMESG, FAIL); /*can't read message*/
if (NULL==H5O_read (f, addr, self, H5O_STAB, 0, &stab)) {
HRETURN_ERROR (H5E_SYM, H5E_BADMESG, NULL); /*can't read message*/
}
udata.operation = H5G_OPER_FIND;
udata.name = name;
udata.heap_addr = stab.heap_addr;
udata.dir_addr = addr;
/* search the B-tree */
if (H5B_find (f, H5B_SNODE, stab.btree_addr, &udata)<0) {
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); /*not found*/
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL); /*not found*/
}
/* return the result */
if (ent) *ent = udata.entry;
FUNC_LEAVE (udata.entry.header);
}
/*-------------------------------------------------------------------------
* Function: H5G_stab_modify
*
* Purpose: Modifies the entry for an existing symbol. The name of the
* symbol is NAME in the symbol table described by SELF in
* file F. ENT is the new symbol table entry to use for the
* symbol.
*
* Errors:
* SYM BADMESG Can't read message.
* SYM NOTFOUND Not found.
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* matzke@llnl.gov
* Aug 1 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5G_stab_modify (hdf5_file_t *f, H5G_entry_t *self, const char *name,
H5G_entry_t *ent)
{
H5G_node_ud1_t udata; /*data to pass through B-tree */
H5O_stab_t stab; /*symbol table message */
FUNC_ENTER (H5G_stab_modify, NULL, FAIL);
/* check arguments */
assert (f);
assert (self && self->header>=0);
assert (name && *name);
assert (ent);
/* set up the udata */
if (NULL==H5O_read (f, self->header, self, H5O_STAB, 0, &stab)) {
HRETURN_ERROR (H5E_SYM, H5E_BADMESG, FAIL); /*can't read message*/
}
udata.operation = H5G_OPER_MODIFY;
udata.name = name;
udata.heap_addr = stab.heap_addr;
udata.entry = *ent;
/* search and modify the B-tree */
if (H5B_find (f, H5B_SNODE, stab.btree_addr, &udata)<0) {
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); /*not found*/
}
FUNC_LEAVE (SUCCEED);
FUNC_LEAVE (udata.entry_ptr);
}
@ -1015,6 +1007,10 @@ H5G_stab_modify (hdf5_file_t *f, H5G_entry_t *self, const char *name,
*
* Modifications:
*
* Robb Matzke, 18 Sep 1997
* If ENT has a shadow, then the shadow will be associated with the
* entry when it is added to the symbol table.
*
*-------------------------------------------------------------------------
*/
herr_t
@ -1022,7 +1018,7 @@ H5G_stab_insert (hdf5_file_t *f, H5G_entry_t *self, const char *name,
H5G_entry_t *ent)
{
H5O_stab_t stab; /*symbol table message */
H5G_node_ud1_t udata; /*data to pass through B-tree */
H5G_bt_ud1_t udata; /*data to pass through B-tree */
FUNC_ENTER (H5G_stab_insert, NULL, FAIL);
@ -1036,9 +1032,13 @@ H5G_stab_insert (hdf5_file_t *f, H5G_entry_t *self, const char *name,
if (NULL==H5O_read (f, self->header, self, H5O_STAB, 0, &stab)) {
HRETURN_ERROR (H5E_SYM, H5E_BADMESG, FAIL); /*can't read message*/
}
udata.operation = H5G_OPER_INSERT;
udata.name = name;
udata.heap_addr = stab.heap_addr;
udata.dir_addr = self->header;
udata.entry = *ent;
udata.entry.name_off = -1;
/* insert */
if (H5B_insert (f, H5B_SNODE, stab.btree_addr, &udata)<0) {
@ -1086,7 +1086,7 @@ intn
H5G_stab_list (hdf5_file_t *f, H5G_entry_t *self, intn maxentries,
char *names[], H5G_entry_t entries[])
{
H5G_node_list_t udata;
H5G_bt_ud2_t udata;
H5O_stab_t stab;
intn i;
@ -1103,6 +1103,7 @@ H5G_stab_list (hdf5_file_t *f, H5G_entry_t *self, intn maxentries,
}
udata.entry = entries;
udata.name = names;
udata.dir_addr = self->header;
udata.heap_addr = stab.heap_addr;
udata.maxentries = maxentries;
udata.nsyms = 0;
@ -1388,6 +1389,13 @@ H5G_debug (hdf5_file_t *f, H5G_entry_t *ent, FILE *stream, intn indent,
fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth,
"Object header address:",
(unsigned long)(ent->header));
fprintf (stream, "%*s%-*s %s\n", indent, "", fwidth,
"Dirty:",
ent->dirty ? "Yes" : "No");
fprintf (stream, "%*s%-*s %s\n", indent, "", fwidth,
"Has a shadow:",
H5G_shadow_p (ent)?"This is a shadow!" :
(ent->shadow ? "Yes" : "No"));
fprintf (stream, "%*s%-*s ", indent, "", fwidth,
"Symbol type:");

@ -18,22 +18,26 @@
* Robb Matzke, 5 Aug 1997
* Added calls to H5E.
*
* Robb Matzke, 18 Sep 1997
* Added shadow entries.
*
*-------------------------------------------------------------------------
*/
#define H5G_PACKAGE /*suppress error message about including H5Gpkg.h*/
/* Packages needed by this file... */
#include <H5private.h> /*library */
#include <H5ACprivate.h> /*cache */
#include <H5Bprivate.h> /*B-link trees */
#include <H5Eprivate.h> /*error handling */
#include <H5Gprivate.h> /*me */
#include <H5Gpkg.h> /*me */
#include <H5Hprivate.h> /*heap */
#include <H5MFprivate.h> /*file memory management */
#include <H5MMprivate.h> /*core memory management */
#include <H5Oprivate.h> /*header messages */
#define PABLO_MASK H5G_node_mask
/* PRIVATE PROTOTYPES */
static herr_t H5G_node_decode_key (hdf5_file_t *f, uint8 *raw, void *_key);
static herr_t H5G_node_encode_key (hdf5_file_t *f, uint8 *raw, void *_key);
@ -42,8 +46,7 @@ static haddr_t H5G_node_new (hdf5_file_t *f, void *_lt_key, void *_udata,
void *_rt_key);
static herr_t H5G_node_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr,
H5G_node_t *sym);
static H5G_node_t *H5G_node_load (hdf5_file_t *f, haddr_t addr,
const void *_data);
static H5G_node_t *H5G_node_load (hdf5_file_t *f, haddr_t addr, void *_data);
static intn H5G_node_cmp (hdf5_file_t *f, void *_lt_key, void *_udata,
void *_rt_key);
static herr_t H5G_node_found (hdf5_file_t *f, haddr_t addr,
@ -58,12 +61,12 @@ static size_t H5G_node_sizeof_rkey (hdf5_file_t *f);
/* H5G inherits cache-like properties from H5AC */
static const H5AC_class_t H5AC_SNODE[1] = {{
(void*(*)(hdf5_file_t*,haddr_t,const void*))H5G_node_load,
(void*(*)(hdf5_file_t*,haddr_t,void*))H5G_node_load,
(herr_t(*)(hdf5_file_t*,hbool_t,haddr_t,void*))H5G_node_flush,
}};
/* H5G inherits B-tree like properties from H5B */
const H5B_class_t H5B_SNODE[1] = {{
H5B_class_t H5B_SNODE[1] = {{
H5B_SNODE_ID, /*id */
sizeof (H5G_node_key_t), /*sizeof_nkey */
H5G_node_sizeof_rkey, /*get_sizeof_rkey */
@ -265,7 +268,10 @@ H5G_node_new (hdf5_file_t *f, void *_lt_key, void *_udata, void *_rt_key)
/*-------------------------------------------------------------------------
* Function: H5G_node_flush
*
* Purpose: Flush a symbol table node to disk.
* Purpose: Flush a symbol table node to disk. If any entries have dirty
* shadows, the shadow value is copied into the entry before the
* entry is flushed. The association between shadows and
* entries is broken.
*
* Return: Success: SUCCEED
*
@ -285,6 +291,7 @@ H5G_node_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5G_node_t *sym)
uint8 *buf=NULL, *p=NULL;
size_t size;
herr_t status;
int i;
FUNC_ENTER (H5G_node_flush, NULL, FAIL);
@ -295,6 +302,19 @@ H5G_node_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5G_node_t *sym)
assert (addr>=0);
assert (sym);
/*
* Synchronize all entries with their corresponding shadow if they have
* one.
*/
for (i=0; i<sym->nsyms; i++) {
if (H5G_shadow_sync (sym->entry+i)<0) {
HRETURN_ERROR (H5E_SYM, H5E_CANTFLUSH, FAIL);
}
}
/*
* Write the symbol node to disk.
*/
if (sym->dirty) {
size = H5G_node_size (f);
buf = p = H5MM_xmalloc (size);
@ -321,7 +341,15 @@ H5G_node_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5G_node_t *sym)
if (status<0) HRETURN_ERROR (H5E_SYM, H5E_WRITEERROR, FAIL);
}
/*
* Destroy the symbol node? This might happen if the node is being
* preempted from the cache. We should also dissociate the shadow
* from the entry.
*/
if (destroy) {
for (i=0; i<sym->nsyms; i++) {
H5G_shadow_dissociate (sym->entry+i);
}
sym->entry = H5MM_xfree (sym->entry);
H5MM_xfree (sym);
}
@ -333,7 +361,8 @@ H5G_node_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5G_node_t *sym)
/*-------------------------------------------------------------------------
* Function: H5G_node_load
*
* Purpose: Loads a symbol table from the file.
* Purpose: Loads a symbol table from the file and associates shadows
* with their entries.
*
* Return: Success: Ptr to the new table.
*
@ -348,11 +377,13 @@ H5G_node_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5G_node_t *sym)
*-------------------------------------------------------------------------
*/
static H5G_node_t *
H5G_node_load (hdf5_file_t *f, haddr_t addr, const void *_udata)
H5G_node_load (hdf5_file_t *f, haddr_t addr, void *_udata)
{
H5G_node_t *sym = NULL;
size_t size = 0;
uint8 *buf = NULL, *p = NULL;
H5G_entry_t *self = NULL;
H5G_node_t *ret_value = NULL; /*for error handling*/
FUNC_ENTER (H5G_node_load, NULL, NULL);
@ -361,7 +392,8 @@ H5G_node_load (hdf5_file_t *f, haddr_t addr, const void *_udata)
*/
assert (f);
assert (addr>=0);
assert (NULL==_udata);
assert (_udata);
self = (H5G_entry_t*)_udata;
/*
* Initialize variables.
@ -372,17 +404,19 @@ H5G_node_load (hdf5_file_t *f, haddr_t addr, const void *_udata)
sym->entry = H5MM_xcalloc (2*H5G_NODE_K(f), sizeof(H5G_entry_t));
if (H5F_block_read (f, addr, size, buf)<0) {
H5MM_xfree (sym->entry);
H5MM_xfree (sym);
HRETURN_ERROR (H5E_SYM, H5E_READERROR, NULL);
HGOTO_ERROR (H5E_SYM, H5E_READERROR, NULL);
}
/* magic */
if (HDmemcmp (p, H5G_NODE_MAGIC, H5G_NODE_SIZEOF_MAGIC)) goto error;
if (HDmemcmp (p, H5G_NODE_MAGIC, H5G_NODE_SIZEOF_MAGIC)) {
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, NULL);
}
p += 4;
/* version */
if (H5G_NODE_VERS!=*p++) goto error;
if (H5G_NODE_VERS!=*p++) {
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, NULL);
}
/* reserved */
p++;
@ -391,15 +425,28 @@ H5G_node_load (hdf5_file_t *f, haddr_t addr, const void *_udata)
UINT16DECODE (p, sym->nsyms);
/* entries */
if (H5G_decode_vec (f, &p, sym->entry, sym->nsyms)<0) goto error;
if (H5G_decode_vec (f, &p, sym->entry, sym->nsyms)<0) {
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, NULL);
}
buf = H5MM_xfree (buf);
H5MM_xfree (buf);
FUNC_LEAVE (sym);
/* shadows */
if (H5G_shadow_assoc_node (f, sym, self)<0) {
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, NULL);
}
ret_value = sym;
error:
H5MM_xfree (buf);
H5MM_xfree (sym);
HRETURN_ERROR (H5E_SYM, H5E_CANTLOAD, NULL);
done:
if (!ret_value) {
buf = H5MM_xfree (buf);
if (sym) {
sym->entry = H5MM_xfree (sym->entry);
sym = H5MM_xfree (sym);
}
}
FUNC_LEAVE (ret_value);
}
@ -433,7 +480,7 @@ error:
static intn
H5G_node_cmp (hdf5_file_t *f, void *_lt_key, void *_udata, void *_rt_key)
{
H5G_node_ud1_t *udata = (H5G_node_ud1_t *)_udata;
H5G_bt_ud1_t *udata = (H5G_bt_ud1_t *)_udata;
H5G_node_key_t *lt_key = (H5G_node_key_t *)_lt_key;
H5G_node_key_t *rt_key = (H5G_node_key_t *)_rt_key;
const char *s;
@ -488,7 +535,8 @@ static herr_t
H5G_node_found (hdf5_file_t *f, haddr_t addr, const void *_lt_key,
void *_udata, const void *_rt_key)
{
H5G_node_ud1_t *udata = (H5G_node_ud1_t *)_udata;
H5G_bt_ud1_t *bt_udata = (H5G_bt_ud1_t *)_udata;
H5G_ac_ud1_t ac_udata;
H5G_node_t *sn = NULL;
intn lt=0, idx=0, rt, cmp=1;
const char *s;
@ -501,12 +549,15 @@ H5G_node_found (hdf5_file_t *f, haddr_t addr, const void *_lt_key,
*/
assert (f);
assert (addr>=0);
assert (udata);
assert (bt_udata);
ac_udata.dir_addr = bt_udata->dir_addr;
ac_udata.heap_addr = bt_udata->heap_addr;
/*
* Load the symbol table node for exclusive access.
*/
if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, NULL))) {
if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, &ac_udata))) {
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL);
}
@ -516,10 +567,11 @@ H5G_node_found (hdf5_file_t *f, haddr_t addr, const void *_lt_key,
rt = sn->nsyms;
while (lt<rt && cmp) {
idx = (lt + rt) / 2;
if (NULL==(s=H5H_peek (f, udata->heap_addr, sn->entry[idx].name_off))) {
if (NULL==(s=H5H_peek (f, bt_udata->heap_addr,
sn->entry[idx].name_off))) {
HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL);
}
cmp = HDstrcmp (udata->name, s);
cmp = HDstrcmp (bt_udata->name, s);
if (cmp<0) {
rt = idx;
@ -529,20 +581,18 @@ H5G_node_found (hdf5_file_t *f, haddr_t addr, const void *_lt_key,
}
if (cmp) HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL);
switch (udata->operation) {
switch (bt_udata->operation) {
case H5G_OPER_FIND:
/*
* The caller is querying the symbol entry.
* The caller is querying the symbol entry. Return just a pointer to
* the entry. The pointer is valid until the next call to H5AC.
*/
udata->entry = sn->entry[idx];
H5G_shadow_sync (sn->entry+idx);
bt_udata->entry_ptr = sn->entry+idx;
break;
case H5G_OPER_MODIFY:
/*
* The caller is modifying the symbol entry.
*/
sn->entry[idx] = udata->entry;
sn->dirty += 1;
default:
HRETURN_ERROR (H5E_SYM, H5E_UNSUPPORTED, FAIL);
break;
}
ret_value = SUCCEED;
@ -589,6 +639,10 @@ done:
*
* Modifications:
*
* Robb Matzke, 18 Sep 1997
* If the shadow pointer is non-null then the shadow is updated to point
* to the new entry.
*
*-------------------------------------------------------------------------
*/
static haddr_t
@ -599,14 +653,17 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor,
{
H5G_node_key_t *md_key = (H5G_node_key_t *)_md_key;
H5G_node_key_t *rt_key = (H5G_node_key_t *)_rt_key;
H5G_node_ud1_t *udata = (H5G_node_ud1_t *)_udata;
H5G_bt_ud1_t *bt_udata = (H5G_bt_ud1_t *)_udata;
H5G_ac_ud1_t ac_udata;
H5G_node_t *sn=NULL, *snrt=NULL;
haddr_t new_node=0, offset;
const char *s;
intn idx=-1, cmp=1;
intn lt=0, rt; /*binary search cntrs */
intn i;
haddr_t ret_value = FAIL;
H5G_shadow_t *shadow = NULL;
FUNC_ENTER (H5G_node_insert, NULL, FAIL);
@ -618,7 +675,8 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor,
assert (anchor);
assert (md_key);
assert (rt_key);
assert (udata);
assert (bt_udata);
bt_udata->entry_ptr = NULL;
/*
* Symbol tables are always split so the new symbol table node is
@ -631,7 +689,9 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor,
/*
* Load the symbol node.
*/
if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, NULL))) {
ac_udata.dir_addr = bt_udata->dir_addr;
ac_udata.heap_addr = bt_udata->heap_addr;
if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, &ac_udata))) {
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL);
}
@ -641,10 +701,11 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor,
rt = sn->nsyms;
while (lt<rt) {
idx = (lt + rt) / 2;
if (NULL==(s=H5H_peek (f, udata->heap_addr, sn->entry[idx].name_off))) {
if (NULL==(s=H5H_peek (f, bt_udata->heap_addr,
sn->entry[idx].name_off))) {
HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL);
}
if (0==(cmp=HDstrcmp (udata->name, s))) {
if (0==(cmp=HDstrcmp (bt_udata->name, s))) {
HGOTO_ERROR (H5E_SYM, H5E_CANTINSERT, FAIL); /*already present*/
}
if (cmp<0) {
@ -660,9 +721,9 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor,
* heap address changed and update the symbol table object header
* with the new heap address.
*/
offset = H5H_insert (f, udata->heap_addr, HDstrlen(udata->name)+1,
udata->name);
udata->entry.name_off = offset;
offset = H5H_insert (f, bt_udata->heap_addr, HDstrlen(bt_udata->name)+1,
bt_udata->name);
bt_udata->entry.name_off = offset;
if (offset<0) HGOTO_ERROR (H5E_SYM, H5E_CANTINSERT, FAIL);
if (sn->nsyms>=2*H5G_NODE_K(f)) {
@ -676,7 +737,7 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor,
if ((new_node = H5G_node_new (f, NULL, NULL, NULL))<0) {
HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL);
}
if (NULL==(snrt=H5AC_find (f, H5AC_SNODE, new_node, NULL))) {
if (NULL==(snrt=H5AC_find (f, H5AC_SNODE, new_node, &ac_udata))) {
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL);
}
HDmemcpy (snrt->entry, sn->entry + H5G_NODE_K(f),
@ -684,6 +745,13 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor,
snrt->nsyms = H5G_NODE_K(f);
snrt->dirty += 1;
/* Right shadows */
for (i=0; i<H5G_NODE_K(f); i++) {
if ((shadow = snrt->entry[i].shadow)) {
shadow->main = snrt->entry + i;
}
}
/* The left node */
HDmemset (sn->entry + H5G_NODE_K(f), 0,
H5G_NODE_K(f) * sizeof(H5G_entry_t));
@ -692,19 +760,46 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor,
/* Insert the new entry */
if (idx<=H5G_NODE_K(f)) {
/* Adjust shadows */
for (i=idx; i<sn->nsyms; i++) {
if (sn->entry[i].shadow) {
sn->entry[i].shadow->main = sn->entry + i + 1;
}
}
if (bt_udata->entry.shadow) {
bt_udata->entry.shadow->main = sn->entry + idx;
}
/* Move entries */
HDmemmove (sn->entry + idx + 1,
sn->entry + idx,
(H5G_NODE_K(f)-idx) * sizeof(H5G_entry_t));
sn->entry[idx] = udata->entry;
sn->entry[idx] = bt_udata->entry;
sn->entry[idx].name_off = offset;
sn->entry[idx].dirty = TRUE;
sn->nsyms += 1;
} else {
idx -= H5G_NODE_K (f);
/* Adjust shadows */
for (i=idx; i<snrt->nsyms; i++) {
if (snrt->entry[i].shadow) {
snrt->entry[i].shadow->main = snrt->entry + i + 1;
}
}
if (bt_udata->entry.shadow) {
bt_udata->entry.shadow->main = snrt->entry + idx;
}
/* Move entries */
HDmemmove (snrt->entry + idx + 1,
snrt->entry + idx,
(H5G_NODE_K(f)-idx) * sizeof (H5G_entry_t));
snrt->entry[idx] = udata->entry;
snrt->entry[idx] = bt_udata->entry;
snrt->entry[idx].name_off = offset;
snrt->entry[idx].dirty = TRUE;
snrt->nsyms += 1;
if (idx+1 == sn->nsyms) {
@ -721,12 +816,21 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor,
* Add the new symbol to the node.
*/
sn->dirty += 1;
for (i=idx; i<sn->nsyms; i++) {
if (sn->entry[i].shadow) {
sn->entry[i].shadow->main = sn->entry + i + 1;
}
}
if (bt_udata->entry.shadow) {
bt_udata->entry.shadow->main = sn->entry + idx;
}
HDmemmove (sn->entry+idx+1, sn->entry+idx,
(sn->nsyms-idx) * sizeof (H5G_entry_t));
sn->nsyms += 1;
sn->entry[idx] = udata->entry;
sn->entry[idx] = bt_udata->entry;
sn->entry[idx].name_off = offset;
sn->entry[idx].dirty = TRUE;
if (idx+1==sn->nsyms) {
rt_key->offset = offset;
*rt_key_changed = TRUE;
@ -765,12 +869,13 @@ done:
static herr_t
H5G_node_list (hdf5_file_t *f, haddr_t addr, void *_udata)
{
H5G_node_list_t *udata = (H5G_node_list_t *)_udata;
H5G_bt_ud2_t *bt_udata = (H5G_bt_ud2_t *)_udata;
H5G_node_t *sn = NULL;
intn i;
const char *s;
herr_t ret_value = FAIL;
H5G_ac_ud1_t ac_udata;
FUNC_ENTER (H5G_node_list, NULL, FAIL);
/*
@ -778,9 +883,11 @@ H5G_node_list (hdf5_file_t *f, haddr_t addr, void *_udata)
*/
assert (f);
assert (addr>=0);
assert (udata);
assert (bt_udata);
if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, NULL))) {
ac_udata.dir_addr = bt_udata->dir_addr;
ac_udata.heap_addr = bt_udata->heap_addr;
if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, &ac_udata))) {
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL);
}
@ -789,32 +896,34 @@ H5G_node_list (hdf5_file_t *f, haddr_t addr, void *_udata)
* keep track of how many names we've seen and don't bother doing
* anything else.
*/
if (udata->nsyms >= udata->maxentries) {
udata->nsyms += sn->nsyms;
if (bt_udata->nsyms >= bt_udata->maxentries) {
bt_udata->nsyms += sn->nsyms;
HGOTO_DONE (SUCCEED);
}
/*
* Save the symbol table entries.
*/
if (udata->entry) {
for (i=0; i<sn->nsyms && udata->nsyms+i<udata->maxentries; i++) {
udata->entry[udata->nsyms+i] = sn->entry[i];
if (bt_udata->entry) {
for (i=0; i<sn->nsyms && bt_udata->nsyms+i<bt_udata->maxentries; i++) {
H5G_shadow_sync (sn->entry+i);
bt_udata->entry[bt_udata->nsyms+i] = sn->entry[i];
}
}
if (udata->name) {
for (i=0; i<sn->nsyms && udata->nsyms+i<udata->maxentries; i++) {
if (NULL==(s=H5H_peek (f, udata->heap_addr, sn->entry[i].name_off))) {
if (bt_udata->name) {
for (i=0; i<sn->nsyms && bt_udata->nsyms+i<bt_udata->maxentries; i++) {
if (NULL==(s=H5H_peek (f, bt_udata->heap_addr,
sn->entry[i].name_off))) {
HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL);
}
udata->name[udata->nsyms+i] = H5MM_xstrdup (s);
bt_udata->name[bt_udata->nsyms+i] = H5MM_xstrdup (s);
}
}
/*
* Update the number of symbols.
*/
udata->nsyms += sn->nsyms;
bt_udata->nsyms += sn->nsyms;
ret_value = SUCCEED;
done:
@ -847,10 +956,11 @@ herr_t
H5G_node_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent,
intn fwidth, haddr_t heap)
{
int i;
int i, acc;
H5G_node_t *sn = NULL;
herr_t status;
const char *s;
H5G_ac_ud1_t ac_udata;
FUNC_ENTER (H5G_node_debug, NULL, FAIL);
@ -863,6 +973,18 @@ H5G_node_debug (hdf5_file_t *f, 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 `-1' as the directory address which causes no open objects to be
* associated with the node. For that reason, we flush this node from the
* cache when we're done so if some later caller knows the header address
* they'll be able to access the open objects.
*/
ac_udata.dir_addr = -1;
ac_udata.heap_addr = heap;
/*
* If we couldn't load the symbol table node, then try loading the
* B-tree node.
@ -882,6 +1004,12 @@ H5G_node_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent,
fprintf (stream, "%*s%-*s %d of %d\n", indent, "", fwidth,
"Number of Symbols:",
sn->nsyms, 2*H5G_NODE_K(f));
for (i=acc=0; i<sn->nsyms; i++) {
if (sn->entry[i].shadow) acc++;
}
fprintf (stream, "%*s%-*s %d\n", indent, "", fwidth,
"Shadows:", acc);
indent += 3;
fwidth = MAX (0, fwidth-3);
@ -893,8 +1021,12 @@ H5G_node_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent,
s);
}
H5G_debug (f, sn->entry+i, stream, indent, fwidth);
fprintf (stream, "%*s%-*s %s\n", indent+3, "", MAX (0, fwidth-3),
"Shadow:",
sn->entry[i].shadow ? "Yes":"No");
}
H5AC_flush (f, H5AC_SNODE, addr, TRUE); /*see note above*/
FUNC_LEAVE (SUCCEED);
}

158
src/H5Gpkg.h Normal file

@ -0,0 +1,158 @@
/*
* Copyright (C) 1997 National Center for Supercomputing Applications.
* All rights reserved.
*
* Programmer: Robb Matzke <matzke@llnl.gov>
* Thursday, September 18, 1997
*
* Purpose: This file contains declarations which are visible
* only within the H5G package. Source files outside the
* H5G package should include H5Gprivate.h instead.
*/
#ifndef H5G_PACKAGE
#error "Do not include this file outside the H5G package!"
#endif
#ifndef _H5Gpkg_H
#define _H5Gpkg_H
#include <H5Gprivate.h>
#define H5G_NODE_VERS 1 /*symbol table node version number */
#define H5G_SIZE_HINT 1024 /*default root dir size hint */
#define H5G_NODE_K(F) ((F)->file_create_parms.sym_leaf_k)
#define H5G_NODE_SIZEOF_HDR(F) (H5G_NODE_SIZEOF_MAGIC + 4)
#define H5G_DEFAULT_ROOT_SIZE 32
/*
* A shadow is a copy of a symbol table entry which corresponds to an
* `open' object. Shadows are necessary because normal symbol table
* entries can be preempted from the main cache. The `shadow' field
* of the `entry' points to the beginning of the shadow just like the
* shadow field from symbol table entries in H5G_node_t.
*/
struct H5G_shadow_t {
char *name; /*name for this entry */
haddr_t dir_addr; /*hdr addr for dir containing shadow */
uintn nrefs; /*reference counter */
H5G_entry_t entry; /*local copy of symbol table entry */
H5G_entry_t *main; /*main entry in stab node if cached */
struct H5G_shadow_t *next; /*next shadow for same symbol table */
struct H5G_shadow_t *prev; /*previous shadow for same symbol table */
};
/*
* A symbol table node is a collection of symbol table entries. It can
* be thought of as the lowest level of the B-link tree that points to
* a collection of symbol table entries that belong to a specific symbol
* table or directory.
*/
typedef struct H5G_node_t {
int dirty; /*has cache been modified? */
int nsyms; /*number of symbols */
H5G_entry_t *entry; /*array of symbol table entries */
} H5G_node_t;
/*
* Each key field of the B-link tree that points to symbol table
* nodes consists of this structure...
*/
typedef struct H5G_node_key_t {
off_t offset; /*offset into heap for name */
} H5G_node_key_t;
/*
* These operations can be passed down from the H5G_stab layer to the
* H5G_node layer through the B-tree layer.
*/
typedef enum H5G_oper_t {
H5G_OPER_FIND =0, /*find a symbol */
H5G_OPER_INSERT =1, /*insert a new symbol */
} H5G_oper_t;
/*
* Data exchange structure for symbol table nodes. This structure is
* passed through the B-link tree layer to the methods for the objects
* to which the B-link tree points.
*/
typedef struct H5G_bt_ud1_t {
/* downward */
H5G_oper_t operation; /*what operation to perform */
const char *name; /*points to temporary memory */
haddr_t dir_addr; /*symbol table header address */
haddr_t heap_addr; /*symbol table heap address */
/* downward for INSERT */
H5G_entry_t entry; /*entry to insert into table */
/* upward for FIND */
H5G_entry_t *entry_ptr; /*ptr into cached symbol table node */
} H5G_bt_ud1_t;
/*
* Data exchange structure to pass through the B-tree layer for the
* H5B_list function.
*/
typedef struct H5G_bt_ud2_t {
/* downward */
H5G_entry_t *entry; /*array of entries, alloc'd by caller */
char **name; /*array of string ptrs, allocd by caller*/
intn maxentries; /*size of the ADDR and NAME arrays */
haddr_t dir_addr; /*symbol table header address */
haddr_t heap_addr; /*heap address */
/* upward */
intn nsyms; /*num. symbols processed */
} H5G_bt_ud2_t;
/*
* This is the class identifier to give to the B-tree functions.
*/
extern H5B_class_t H5B_SNODE[1];
/*
* This struct passes information through the H5AC layer.
*/
typedef struct H5G_ac_ud1_t {
haddr_t heap_addr;
haddr_t dir_addr;
} H5G_ac_ud1_t;
/*
* Functions that understand symbol tables but not directories. The
* functions that understand directories are exported to the rest of
* the library and appear in H5Gprivate.h.
*/
haddr_t H5G_stab_new (hdf5_file_t *f, H5G_entry_t *self, size_t init);
H5G_entry_t *H5G_stab_find (hdf5_file_t *f, haddr_t addr, H5G_entry_t *self,
const char *name);
herr_t H5G_stab_insert (hdf5_file_t *f, H5G_entry_t *self, const char *name,
H5G_entry_t *ent);
intn H5G_stab_list (hdf5_file_t *f, H5G_entry_t *self, intn maxentries,
char *names[], H5G_entry_t entries[]);
/*
* Functions that understand shadow entries.
*/
herr_t H5G_shadow_sync (H5G_entry_t *ent);
H5G_entry_t *H5G_shadow_open (hdf5_file_t *f, H5G_entry_t *dir,
H5G_entry_t *ent);
herr_t H5G_shadow_close (hdf5_file_t *f, H5G_entry_t *ent);
hbool_t H5G_shadow_p (H5G_entry_t *ent);
herr_t H5G_shadow_dissociate (H5G_entry_t *ent);
herr_t H5G_shadow_assoc_node (hdf5_file_t *f, H5G_node_t *sym,
H5G_entry_t *self);
H5G_shadow_t *H5G_shadow_list (haddr_t stab_header_addr);
/*
* Functions that understand symbol table entries.
*/
herr_t H5G_decode_vec (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent, intn n);
herr_t H5G_encode_vec (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent, intn n);
#endif

@ -8,7 +8,7 @@
* Jul 11 1997
* Robb Matzke <matzke@llnl.gov>
*
* Purpose: Private stuff for the H5G package (symbol tables).
* Purpose: Library-visible declarations.
*
* Modifications:
*
@ -25,18 +25,17 @@
#define H5G_NODE_MAGIC "SNOD" /*symbol table node magic number */
#define H5G_NODE_SIZEOF_MAGIC 4 /*sizeof symbol node magic number */
#define H5G_NODE_VERS 1 /*symbol table node version number */
#define H5G_SIZE_HINT 1024 /*default root dir size hint */
#define H5G_NODE_K(F) ((F)->file_create_parms.sym_leaf_k)
#define H5G_NODE_SIZEOF_HDR(F) (H5G_NODE_SIZEOF_MAGIC + 4)
#define H5G_new_entry() H5MM_xcalloc (1, sizeof(H5G_entry_t))
/*
* The disk size for a symbol table entry...
*/
#define H5G_SIZEOF_ENTRY(F) \
(H5F_SIZEOF_OFFSET(F) + /*offset of name into heap */ \
H5F_SIZEOF_OFFSET(F) + /*address of object header */ \
4 + /*entry type */ \
24) /*scratch pad space */
#define H5G_DEFAULT_ROOT_SIZE 32
/*
* Various types of object header information can be cached in a symbol
* table entry (it's normal home is the object header to which the entry
@ -44,11 +43,39 @@
* symbol table entry.
*/
typedef enum H5G_type_t {
H5G_NOTHING_CACHED =0, /*nothing is cached */
H5G_NOTHING_CACHED =0, /*nothing is cached, must be 0 */
H5G_CACHED_SDATA =1, /*simple dataset, `sdata' */
H5G_CACHED_STAB =2 /*symbol table, `stab' */
} H5G_type_t;
/*
* A symbol table entry caches these parameters from object header
* messages...
*/
typedef union H5G_cache_t {
struct {
struct {
uint8 length;
uint8 arch;
uint16 type;
} nt ; /*number type */
uint32 ndim; /*number of dimensions */
uint32 dim[4]; /*dimension sizes */
} sdata;
struct {
haddr_t btree_addr; /*file address of symbol table B-tree */
haddr_t heap_addr; /*file address of stab name heap */
} stab;
} H5G_cache_t;
/*
* An H5G_shadow_t is the struct used to describe object headers that
* are currently open for modification. It's contents is not
* important outside H5G.
*/
typedef struct H5G_shadow_t H5G_shadow_t;
/*
* A symbol table entry. The two important fields are `name_off' and
* `header'. The remaining fields are used for caching information that
@ -56,122 +83,33 @@ typedef enum H5G_type_t {
* points.
*/
typedef struct H5G_entry_t {
hbool_t dirty; /*entry out-of-date? */
off_t name_off; /*offset of name within name heap */
haddr_t header; /*file address of object header */
H5G_type_t type; /*type of information cached */
union {
struct {
struct {
uint8 length;
uint8 arch;
uint16 type;
} nt ; /*number type */
uint32 ndim; /*number of dimensions */
uint32 dim[4]; /*dimension sizes */
} sdata;
struct {
haddr_t btree_addr; /*file address of symbol table B-tree */
haddr_t heap_addr; /*file address of stab name heap */
} stab;
} cache; /*cached data from object header */
H5G_cache_t cache; /*cached data from object header */
H5G_shadow_t *shadow; /*optional ptr to the shadow */
} H5G_entry_t;
/*
* A symbol table node is a collection of symbol table entries. It can
* be thought of as the lowest level of the B-link tree that points to
* a collection of symbol table entries that belong to a specific symbol
* table or directory.
*/
typedef struct H5G_node_t {
int dirty; /*has cache been modified? */
int nsyms; /*number of symbols */
H5G_entry_t *entry; /*symbol table entries */
} H5G_node_t;
/*
* Each key field of the B-link tree that points to symbol table
* nodes consists of this structure...
*/
typedef struct H5G_node_key_t {
off_t offset; /*offset into heap for name */
} H5G_node_key_t;
typedef enum H5G_oper_t {
H5G_OPER_FIND =0, /*find a symbol */
H5G_OPER_MODIFY =1 /*modify a symbol */
} H5G_oper_t;
/*
* Data exchange structure for symbol table nodes. This structure is
* passed through the B-link tree layer to the methods for the objects
* to which the B-link tree points.
*/
typedef struct H5G_node_ud1_t {
/* downward */
H5G_oper_t operation; /*what operation to perform */
const char *name; /*points to temporary memory */
haddr_t heap_addr; /*symbol table heap address */
/* upward for H5G_OPER_FIND, downward for H5G_OPER_MODIFY */
H5G_entry_t entry; /*symbol table entry */
} H5G_node_ud1_t;
typedef struct H5G_node_list_t {
/* downward */
H5G_entry_t *entry; /*array of entries, alloc'd by caller */
char **name; /*array of string ptrs, allocd by caller*/
intn maxentries; /*size of the ADDR and NAME arrays */
haddr_t heap_addr; /*heap address */
/* upward */
intn nsyms; /*num. symbols processed */
} H5G_node_list_t;
extern const H5B_class_t H5B_SNODE[1];
/*
* Library prototypes...
*/
/* functions that understand directories */
herr_t H5G_new (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
const char *name, size_t size_hint, H5G_entry_t *ent);
H5G_entry_t *H5G_open (hdf5_file_t *f, H5G_entry_t *cwd, const char *name);
herr_t H5G_close (hdf5_file_t *f, H5G_entry_t *ent);
herr_t H5G_find (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
const char *name, H5G_entry_t *ent);
herr_t H5G_insert (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
const char *name, H5G_entry_t *ent);
herr_t H5G_modify (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
const char *name, H5G_entry_t *ent);
herr_t H5G_set_root (hdf5_file_t *f, const char *name, H5G_entry_t *ent);
/* functions that understand symbol tables */
haddr_t H5G_stab_new (hdf5_file_t *f, H5G_entry_t *self, size_t init);
haddr_t H5G_stab_find (hdf5_file_t *f, H5G_entry_t *self, const char *name,
H5G_entry_t *ent);
herr_t H5G_stab_modify (hdf5_file_t *f, H5G_entry_t *self, const char *name,
H5G_entry_t *ent);
herr_t H5G_stab_insert (hdf5_file_t *f, H5G_entry_t *self, const char *name,
H5G_entry_t *ent);
intn H5G_stab_list (hdf5_file_t *f, H5G_entry_t *self, intn maxentries,
char *names[], H5G_entry_t entries[]);
/* functions that understand symbol table nodes */
herr_t H5G_encode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent);
herr_t H5G_decode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent);
herr_t H5G_debug (hdf5_file_t *f, H5G_entry_t *ent, FILE *stream, intn indent,
intn fwidth);
herr_t H5G_node_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent,
intn fwidth, haddr_t heap);
/* functions that understand symbol table entries */
herr_t H5G_decode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent);
herr_t H5G_decode_vec (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent, intn n);
herr_t H5G_encode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent);
herr_t H5G_encode_vec (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent, intn n);
herr_t H5G_debug (hdf5_file_t *f, H5G_entry_t *ent, FILE *stream, intn indent,
intn fwidth);
#endif

460
src/H5Gshad.c Normal file

@ -0,0 +1,460 @@
/*
* Copyright (C) 1997 National Center for Supercomputing Applications.
* All rights reserved.
*
* Programmer: Robb Matzke <matzke@llnl.gov>
* Thursday, September 18, 1997
*/
#define H5G_PACKAGE /*suppress error message about including H5Gpkg.h*/
#include <H5private.h> /*library */
#include <H5Eprivate.h> /*error handling */
#include <H5Gpkg.h> /*symbol tables */
#include <H5Hprivate.h> /*heap functions */
#include <H5MMprivate.h> /*memory management */
#include <H5Oprivate.h> /*object header messages */
#define PABLO_MASK H5G_shadow_mask
/* Is the interface initialized? */
static hbool_t interface_initialize_g = FALSE;
/* Shadow hash table */
#define H5G_NSHADOWS 10331
typedef struct H5G_hash_t {
haddr_t dir_addr;
H5G_shadow_t *head;
struct H5G_hash_t *next;
struct H5G_hash_t *prev;
} H5G_hash_t;
static H5G_hash_t *H5G_shadow_g[H5G_NSHADOWS];
/*-------------------------------------------------------------------------
* Function: H5G_shadow_p
*
* Purpose: Determines if ENT is a shadow or a real symbol table entry.
*
* Return: Success: Non-zero if ENT is a shadow; zero otherwise.
*
* Failure: FALSE
*
* Programmer: Robb Matzke
* Thursday, September 18, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
hbool_t
H5G_shadow_p (H5G_entry_t *ent)
{
H5G_shadow_t tmp;
size_t delta = (char*)&(tmp.entry) - (char*)&tmp;
hbool_t ret_value = FALSE;
FUNC_ENTER (H5G_shadow_p, NULL, FALSE);
if (!ent || !ent->shadow) return FALSE;
ret_value = ((char*)ent - (char*)(ent->shadow) == delta);
FUNC_LEAVE (ret_value);
}
/*-------------------------------------------------------------------------
* Function: H5G_shadow_dissociate
*
* Purpose: Removes the association between a shadow and its entry or an
* entry and its shadow. The ENT argument can be a shadow or a
* cached entry.
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Thursday, September 18, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5G_shadow_dissociate (H5G_entry_t *ent)
{
FUNC_ENTER (H5G_shadow_dissociate, NULL, FAIL);
if (H5G_shadow_p (ent)) {
if (ent->shadow->main) {
ent->shadow->main->shadow = NULL;
ent->shadow->main = NULL;
}
} else if (ent && ent->shadow) {
ent->shadow->main = NULL;
ent->shadow = NULL;
}
FUNC_LEAVE (SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5G_shadow_sync
*
* Purpose: Synchronizes a shadow with an entry by copying the
* shadow contents to the entry if the shadow is dirty,
* and then clearing the shadow dirty bit. You may call this
* function with either a shadow or a real entry.
*
* If ENT is a shadow, then the shadow is synchronized only if
* the entry is currently cached.
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Thursday, September 18, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5G_shadow_sync (H5G_entry_t *ent)
{
H5G_shadow_t *shadow = NULL;
FUNC_ENTER (H5G_shadow_sync, NULL, FAIL);
/*
* If the caller supplied us with a shadow instead of the main entry, then
* adjust the arguments.
*/
if (H5G_shadow_p (ent)) {
shadow = ent->shadow;
ent = shadow->main;
} else {
shadow = ent->shadow;
}
if (shadow && shadow->entry.dirty) {
if (!ent) {
/* Main entry is not cached */
HRETURN_ERROR (H5E_SYM, H5E_NOTCACHED, FAIL);
}
*ent = shadow->entry;
shadow->entry.dirty = FALSE;
}
FUNC_LEAVE (SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5G_shadow_list
*
* Purpose: Returns a doubly linked list of shadows for the symbol
* table whose header address is DIR_ADDR.
*
* Return: Success: Ptr shadow list or null.
*
* Failure: NULL
*
* Programmer: Robb Matzke
* Wednesday, September 17, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
H5G_shadow_t *
H5G_shadow_list (haddr_t dir_addr)
{
uintn idx = dir_addr % H5G_NSHADOWS;
H5G_hash_t *bucket = NULL;
FUNC_ENTER (H5G_shadows, NULL, NULL);
for (bucket=H5G_shadow_g[idx]; bucket; bucket=bucket->next) {
if (bucket->dir_addr==dir_addr) {
HRETURN (bucket->head);
}
}
FUNC_LEAVE (NULL);
}
/*-------------------------------------------------------------------------
* Function: H5G_shadow_assoc_node
*
* Purpose: Given a new symbol table node and a symbol table header
* address, associate entries in that node with their shadow if
* they have one.
*
* SYM must be an uncached or protected symbol table node.
*
* Return: Success: SUCCEED
*
* Failure: FAIL, if an error occurs then none of the
* entries are associated with shadows.
*
* Programmer: Robb Matzke
* Wednesday, September 17, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5G_shadow_assoc_node (hdf5_file_t *f, H5G_node_t *sym, H5G_entry_t *self)
{
H5G_shadow_t *shadow = NULL;
H5O_stab_t stab;
const char *s = NULL;
intn i = 0;
FUNC_ENTER (H5G_shadow_assoc_node, NULL, FAIL);
/* Check arguments */
assert (f); /* The file */
assert (sym); /* The symbol table node */
assert (self); /* The symbol table header info */
if ((shadow=H5G_shadow_list (self->header))) {
/* We need the heap address so we can see the symbol names */
if (NULL==H5O_read (f, self->header, self, H5O_NAME, 0, &stab)) {
HRETURN_ERROR (H5E_SYM, H5E_BADMESG, FAIL);
}
while (i<sym->nsyms && shadow) {
/* Advance the Entry ptr until it gets to the next shadow. */
while (i<sym->nsyms &&
(s=H5H_peek (f, stab.heap_addr, sym->entry[i].name_off)) &&
strcmp (s, shadow->name)<0) i++;
/* Advance the Shadow ptr until it gets to the next entry. */
while (i<sym->nsyms && s && shadow &&
strcmp (s, shadow->name)>0) shadow = shadow->next;
/* Did we find a match? */
if (i<sym->nsyms && s && shadow && !strcmp (s, shadow->name)) {
shadow->main = sym->entry + i;
sym->entry[i].shadow = shadow;
}
}
}
FUNC_LEAVE (SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5G_shadow_open
*
* Purpose: Given a handle to an already open object, or given a
* pointer to the cached symbol table entry for that
* object, open the object (again) and return a handle
* to it.
*
* Return: Success: Handle to open object
*
* Failure: NULL
*
* Programmer: Robb Matzke
* Thursday, September 18, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
H5G_entry_t *
H5G_shadow_open (hdf5_file_t *f, H5G_entry_t *dir, H5G_entry_t *ent)
{
H5G_shadow_t *shadow = NULL;
H5O_stab_t stab;
const char *s = NULL;
H5G_hash_t *hash = NULL;
H5G_shadow_t *hash_ent = NULL;
uintn idx;
H5O_name_t name_mesg = {NULL};
H5G_entry_t *ret_value = NULL;
FUNC_ENTER (H5G_shadow_open, NULL, NULL);
/* check args */
assert (f);
assert (dir);
assert (ent);
if (ent->shadow) {
/*
* Object is already open. Open it again.
*/
ent->shadow->nrefs += 1;
HRETURN (ent);
} else {
shadow = H5MM_xcalloc (1, sizeof(H5G_shadow_t));
if (ent==f->root_sym && dir->header<=0) {
/*
* We're opening the root entry.
*/
if (H5O_read (f, NO_ADDR, ent, H5O_NAME, 0, &name_mesg)) {
shadow->name = H5MM_xstrdup (name_mesg.s);
H5O_reset (H5O_NAME, &name_mesg);
} else {
shadow->name = H5MM_xstrdup ("Root Object");
}
} else {
/*
* Some entry other than the root.
*/
if (NULL==H5O_read (f, NO_ADDR, dir, H5O_STAB, 0, &stab)) {
HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, NULL);
}
if (NULL==(s=H5H_peek (f, stab.heap_addr, ent->name_off))) {
HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, NULL);
}
shadow->name = H5MM_xstrdup (s);
}
/*
* Build the new shadow.
*/
ent->shadow = shadow;
shadow->main = ent;
shadow->nrefs = 1;
shadow->entry = *ent;
shadow->entry.dirty = FALSE;
shadow->dir_addr = dir->header;
/*
* Link it into the shadow heap
*/
idx = dir->header % H5G_NSHADOWS;
for (hash=H5G_shadow_g[idx]; hash; hash=hash->next) {
if (hash->dir_addr==dir->header) break;
}
if (!hash) {
hash = H5MM_xcalloc (1, sizeof(H5G_hash_t));
hash->dir_addr = dir->header;
hash->next = H5G_shadow_g[idx];
H5G_shadow_g[idx] = hash;
}
for (hash_ent=hash->head; hash_ent; hash_ent=hash_ent->next) {
if (strcmp (shadow->name, hash_ent->name)<0) break;
}
if (hash_ent) {
if (hash_ent->prev) hash_ent->prev->next = shadow;
else hash->head = shadow;
shadow->prev = hash_ent->prev;
shadow->next = hash_ent;
hash_ent->prev = shadow;
} else {
hash->head = shadow;
}
}
ret_value = &(shadow->entry);
done:
if (!ret_value) {
if (shadow) {
H5MM_xfree (shadow->name);
H5MM_xfree (shadow);
}
}
FUNC_LEAVE (ret_value);
}
/*-------------------------------------------------------------------------
* Function: H5G_shadow_close
*
* Purpose: Closes an open object.
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Thursday, September 18, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5G_shadow_close (hdf5_file_t *f, H5G_entry_t *ent)
{
uintn idx;
H5G_hash_t *hash=NULL;
H5G_shadow_t *hash_ent=NULL, *shadow=NULL;
FUNC_ENTER (H5G_shadow_close, NULL, FAIL);
/* check args */
assert (ent);
assert (H5G_shadow_p (ent));
assert (ent->shadow->nrefs>0);
shadow = ent->shadow;
/* clean the shadow */
if (1==shadow->nrefs && ent->dirty) {
if (!shadow->main &&
NULL==H5G_stab_find (f, shadow->dir_addr, NULL, shadow->name)) {
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL);
}
assert (shadow->main);
*(shadow->main) = *ent;
ent->dirty = FALSE;
}
/* close */
shadow->nrefs -= 1;
if (0==shadow->nrefs) {
/* dissociate shadow and entry */
H5G_shadow_dissociate (ent);
/* find symtabs shadow list */
idx = shadow->dir_addr % H5G_NSHADOWS;
for (hash=H5G_shadow_g[idx]; hash; hash=hash->next) {
if (hash->dir_addr==shadow->dir_addr) break;
}
assert (hash);
/* find shadow in shadow list */
for (hash_ent=hash->head; hash_ent; hash_ent=hash_ent->next) {
if (hash_ent==shadow) break;
}
assert (hash_ent);
/* remove shadow from shadow list */
if (hash_ent->prev) hash_ent->prev->next = hash_ent->next;
else hash->head = hash_ent->next;
if (hash_ent->next) hash_ent->next->prev = hash_ent->prev;
H5MM_xfree (shadow->name);
H5MM_xfree (shadow);
/* remove symtab's shadow list if empty */
if (!hash->head) {
if (hash->prev) hash->prev->next = hash->next;
else H5G_shadow_g[idx] = hash->next;
if (hash->next) hash->next->prev = hash->prev;
H5MM_xfree (hash);
}
}
FUNC_LEAVE (SUCCEED);
}

@ -45,7 +45,7 @@ typedef struct H5H_t {
} H5H_t;
/* PRIVATE PROTOTYPES */
static H5H_t *H5H_load (hdf5_file_t *f, haddr_t addr, const void *udata);
static H5H_t *H5H_load (hdf5_file_t *f, haddr_t addr, void *udata);
static herr_t H5H_flush (hdf5_file_t *f, hbool_t dest, haddr_t addr,
H5H_t *heap);
@ -53,7 +53,7 @@ static herr_t H5H_flush (hdf5_file_t *f, hbool_t dest, haddr_t addr,
* H5H inherits cache-like properties from H5AC
*/
static const H5AC_class_t H5AC_HEAP[1] = {{
(void*(*)(hdf5_file_t*,haddr_t,const void*))H5H_load,
(void*(*)(hdf5_file_t*,haddr_t,void*))H5H_load,
(herr_t(*)(hdf5_file_t*,hbool_t,haddr_t,void*))H5H_flush,
}};
@ -162,12 +162,13 @@ H5H_new (hdf5_file_t *f, H5H_type_t heap_type, size_t size_hint)
*-------------------------------------------------------------------------
*/
static H5H_t *
H5H_load (hdf5_file_t *f, haddr_t addr, const void *udata)
H5H_load (hdf5_file_t *f, haddr_t addr, void *udata)
{
uint8 hdr[20], *p;
H5H_t *heap=NULL;
H5H_free_t *fl=NULL, *tail=NULL;
haddr_t free_block=H5H_FREE_NULL;
H5H_t *ret_value=NULL;
FUNC_ENTER (H5H_load, NULL, NULL);
@ -184,7 +185,9 @@ H5H_load (hdf5_file_t *f, haddr_t addr, const void *udata)
heap = H5MM_xcalloc (1, sizeof(H5H_t));
/* magic number */
if (HDmemcmp (hdr, H5H_MAGIC, H5H_SIZEOF_MAGIC)) goto error;
if (HDmemcmp (hdr, H5H_MAGIC, H5H_SIZEOF_MAGIC)) {
HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL);
}
p += H5H_SIZEOF_MAGIC;
/* heap data size */
@ -194,7 +197,7 @@ H5H_load (hdf5_file_t *f, haddr_t addr, const void *udata)
/* free list head */
H5F_decode_offset (f, p, free_block);
if (-1!=free_block && (free_block<0 || free_block>=heap->disk_alloc)) {
goto error;
HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL);
}
/* data */
@ -203,12 +206,14 @@ H5H_load (hdf5_file_t *f, haddr_t addr, const void *udata)
if (heap->disk_alloc &&
H5F_block_read (f, heap->addr, heap->disk_alloc,
heap->chunk + H5H_SIZEOF_HDR(f))<0) {
goto error;
HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL);
}
/* free list */
while (H5H_FREE_NULL!=free_block) {
if (free_block<0 || free_block>=heap->disk_alloc) goto error;
if (free_block<0 || free_block>=heap->disk_alloc) {
HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL);
}
fl = H5MM_xmalloc (sizeof (H5H_free_t));
fl->offset = free_block;
fl->prev = tail;
@ -221,14 +226,15 @@ H5H_load (hdf5_file_t *f, haddr_t addr, const void *udata)
H5F_decode_offset (f, p, free_block);
H5F_decode_length (f, p, fl->size);
if (fl->offset + fl->size > heap->disk_alloc) goto error;
if (fl->offset + fl->size > heap->disk_alloc) {
HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL);
}
}
FUNC_LEAVE (heap);
ret_value = heap;
error:
if (heap) {
done:
if (!ret_value && heap) {
heap->chunk = H5MM_xfree (heap->chunk);
H5MM_xfree (heap);
for (fl=heap->freelist; fl; fl=tail) {
@ -236,7 +242,8 @@ error:
H5MM_xfree (fl);
}
}
HRETURN_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL);
FUNC_LEAVE (ret_value);
}
@ -462,9 +469,10 @@ H5H_peek (hdf5_file_t *f, haddr_t addr, off_t offset)
/*-------------------------------------------------------------------------
* Function: H5H_remove_free
*
* Purpose: Removes free list element FL from the specified heap.
* Purpose: Removes free list element FL from the specified heap and
* frees it.
*
* Return: void
* Return: NULL
*
* Programmer: Robb Matzke
* matzke@llnl.gov
@ -474,13 +482,14 @@ H5H_peek (hdf5_file_t *f, haddr_t addr, off_t offset)
*
*-------------------------------------------------------------------------
*/
static void
static H5H_free_t *
H5H_remove_free (H5H_t *heap, H5H_free_t *fl)
{
if (fl->prev) fl->prev->next = fl->next;
if (fl->next) fl->next->prev = fl->prev;
if (!fl->prev) heap->freelist = fl->next;
return H5MM_xfree (fl);
}
@ -545,7 +554,7 @@ H5H_insert (hdf5_file_t *f, haddr_t addr, size_t buf_size, const void *buf)
break;
} else if (fl->size==need) {
offset = fl->offset;
H5H_remove_free (heap, fl);
fl = H5H_remove_free (heap, fl);
break;
} else if (!max_fl || max_fl->offset < fl->offset) {
max_fl = fl;
@ -582,7 +591,7 @@ H5H_insert (hdf5_file_t *f, haddr_t addr, size_t buf_size, const void *buf)
}
}
#endif
H5H_remove_free (heap, max_fl);
max_fl = H5H_remove_free (heap, max_fl);
}
} else {
@ -762,7 +771,7 @@ H5H_remove (hdf5_file_t *f, haddr_t addr, off_t offset, size_t size)
if (fl2->offset + fl2->size == fl->offset) {
fl->offset = fl2->offset;
fl->size += fl2->size;
H5H_remove_free (heap, fl2);
fl2 = H5H_remove_free (heap, fl2);
HRETURN (SUCCEED);
}
}
@ -774,7 +783,7 @@ H5H_remove (hdf5_file_t *f, haddr_t addr, off_t offset, size_t size)
while (fl2) {
if (fl->offset + fl->size == fl2->offset) {
fl->size += fl2->size;
H5H_remove_free (heap, fl2);
fl2 = H5H_remove_free (heap, fl2);
HRETURN (SUCCEED);
}
}

@ -168,6 +168,16 @@ H5MM_xstrdup (const char *s)
void *
H5MM_xfree (const void *mem)
{
if (mem) HDfree (mem);
/*
* free(3) takes a non-const pointer as an argument even though
* conceptually the argument could be a constant because by time
* free() mucks with it's contents, it should already be free :-)
* Instead of passing a const arg to free, which generates a
* compiler warning, we cast it to a non-const arg first. With
* gcc, this results in a warning only if -Wcast-qual is turned on.
*/
void *non_const_mem = mem;
if (mem) HDfree (non_const_mem);
return NULL;
}

@ -27,7 +27,7 @@
/* PRIVATE PROTOTYPES */
static herr_t H5O_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr,
H5O_t *oh);
static H5O_t *H5O_load (hdf5_file_t *f, haddr_t addr, const void *_data);
static H5O_t *H5O_load (hdf5_file_t *f, haddr_t addr, void *_data);
static intn H5O_find_in_ohdr (hdf5_file_t *f, haddr_t addr,
const H5O_class_t **type_p, intn sequence);
static intn H5O_alloc (hdf5_file_t *f, H5O_t *oh, const H5O_class_t *type,
@ -37,7 +37,7 @@ static intn H5O_alloc_new_chunk (hdf5_file_t *f, H5O_t *oh, size_t size);
/* H5O inherits cache-like properties from H5AC */
static const H5AC_class_t H5AC_OHDR[1] = {{
(void*(*)(hdf5_file_t*,haddr_t,const void*))H5O_load,
(void*(*)(hdf5_file_t*,haddr_t,void*))H5O_load,
(herr_t(*)(hdf5_file_t*,hbool_t,haddr_t,void*))H5O_flush,
}};
@ -166,7 +166,7 @@ H5O_new (hdf5_file_t *f, intn nlink, size_t size_hint)
*-------------------------------------------------------------------------
*/
static H5O_t *
H5O_load (hdf5_file_t *f, haddr_t addr, const void *_data)
H5O_load (hdf5_file_t *f, haddr_t addr, void *_data)
{
H5O_t *oh = NULL;
H5O_t *ret_value = (void*)1; /*kludge for HGOTO_ERROR*/
@ -509,8 +509,9 @@ H5O_link (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent, intn adjust)
/* check args */
assert (f);
assert (addr>=0);
assert (addr>0 || (ent && ent->header>0));
if (addr<=0) addr = ent->header;
/* get header */
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) {
HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL);
@ -528,9 +529,11 @@ H5O_link (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent, intn adjust)
}
} else {
oh->nlink += adjust;
if (oh->nlink>1 && ent) ent->type = H5G_NOTHING_CACHED;
if (oh->nlink>1 && ent && H5G_NOTHING_CACHED!=ent->type) {
ent->dirty = TRUE;
ent->type = H5G_NOTHING_CACHED;
}
}
oh->dirty = TRUE;
FUNC_LEAVE (oh->nlink);
@ -570,7 +573,10 @@ H5O_read (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
/* check args */
assert (f);
assert (addr>=0);
if (addr<=0 && (!ent || ent->header<=0)) {
HRETURN_ERROR (H5E_OHDR, H5E_NOTFOUND, NULL);
}
if (addr<=0) addr = ent->header;
assert (sequence>=0);
/* can we get it from the symbol table? */
@ -585,6 +591,10 @@ H5O_read (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
HRETURN_ERROR (H5E_OHDR, H5E_NOTFOUND, NULL);
}
#ifdef LATER
/* should we cache it in ENT? */
#endif
/* copy the message to the user-supplied buffer */
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) {
HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, NULL);
@ -692,7 +702,7 @@ H5O_peek (hdf5_file_t *f, haddr_t addr, const H5O_class_t *type,
/* check args */
assert (f);
assert (addr>=0);
assert (addr>0);
if ((idx = H5O_find_in_ohdr (f, addr, &type, sequence))<0) {
HRETURN_ERROR (H5E_OHDR, H5E_NOTFOUND, NULL);
@ -709,17 +719,20 @@ H5O_peek (hdf5_file_t *f, haddr_t addr, const H5O_class_t *type,
* Function: H5O_modify
*
* Purpose: Modifies an existing message or creates a new message.
* The object header is at file address ADDR of file F. An
* The object header is at file address ADDR of file F (but if
* ENT is present then its `header' field is used instead). An
* optional symbol table entry ENT can be supplied in which
* case the cache fields in that symbol table are updated if
* appropriate. If the symbol table entry changes then the
* optional ENT_MODIFIED arg will point to a non-zero value,
* otherwise ENT_MODIFIED isn't changed.
* appropriate.
*
* The OVERWRITE argument is either a sequence number of a
* message to overwrite (usually zero) or the constant
* H5O_NEW_MESSAGE (-1) to indicate that a new message is to
* be created.
* be created. If the message to overwrite doesn't exist then
* it is created (but only if it can be inserted so its sequence
* number is OVERWRITE; that is, you can create a message with
* the sequence number 5 if there is no message with sequence
* number 4).
*
* Return: Success: The sequence number of the message that
* was modified or created.
@ -736,8 +749,7 @@ H5O_peek (hdf5_file_t *f, haddr_t addr, const H5O_class_t *type,
*/
intn
H5O_modify (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
hbool_t *ent_modified, const H5O_class_t *type,
intn overwrite, const void *mesg)
const H5O_class_t *type, intn overwrite, const void *mesg)
{
H5O_t *oh = NULL;
intn idx, sequence;
@ -747,10 +759,11 @@ H5O_modify (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
/* check args */
assert (f);
assert (addr>=0);
assert (addr>0 || (ent && ent->header>0));
assert (type);
assert (mesg);
if (addr<=0) addr = ent->header;
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) {
HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL);
}
@ -764,7 +777,13 @@ H5O_modify (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
/* Was the right message found? */
if (overwrite>=0 &&
(idx>=oh->nmesgs || sequence!=overwrite)) {
HRETURN_ERROR (H5E_OHDR, H5E_NOTFOUND, FAIL); /*message not found*/
/* But can we insert a new one with this sequence number? */
if (overwrite==sequence+1) {
overwrite = -1;
} else {
HRETURN_ERROR (H5E_OHDR, H5E_NOTFOUND, FAIL); /*message not found*/
}
}
/* Allocate space for the new message */
@ -787,7 +806,7 @@ H5O_modify (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
/* Copy into the symbol table entry */
if (oh->nlink<=1 && ent && type->cache) {
hbool_t modified = (type->cache)(ent, mesg);
if (modified && ent_modified) *ent_modified = modified;
if (ent && !ent->dirty) ent->dirty = modified;
}
FUNC_LEAVE (sequence);
@ -826,7 +845,7 @@ H5O_modify (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
*/
herr_t
H5O_remove (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
hbool_t *ent_modified, const H5O_class_t *type, intn sequence)
const H5O_class_t *type, intn sequence)
{
H5O_t *oh = NULL;
intn i, seq;
@ -835,8 +854,9 @@ H5O_remove (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
/* check args */
assert (f);
assert (addr>=0);
assert (addr>0 || (ent && ent->header>0));
assert (type);
if (addr<=0) addr = ent->header;
/* load the object header */
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) {
@ -848,9 +868,9 @@ H5O_remove (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
if (seq++ == sequence || H5O_ALL==sequence) {
/* clear symbol table entry cache */
if (ent && type->cache && H5G_NOTHING_CACHED!=ent->type) {
if (ent && type->cache && type->cache_type==ent->type) {
ent->type = H5G_NOTHING_CACHED;
if (ent_modified) *ent_modified = TRUE;
ent->dirty = TRUE;
}
/* change message type to nil and zero it */
@ -922,9 +942,14 @@ H5O_alloc_extend_chunk (H5O_t *oh, intn chunkno, size_t size)
oh->mesg[idx].raw_size += delta;
old_addr = oh->chunk[chunkno].image;
oh->chunk[chunkno].size += delta;
/* Be careful not to indroduce garbage */
oh->chunk[chunkno].image = H5MM_xrealloc (old_addr,
oh->chunk[chunkno].size);
(oh->chunk[chunkno].size +
delta));
HDmemset (oh->chunk[chunkno].image + oh->chunk[chunkno].size,
0, delta);
oh->chunk[chunkno].size += delta;
/* adjust raw addresses for messages of this chunk */
if (old_addr != oh->chunk[chunkno].image) {
@ -1071,7 +1096,7 @@ H5O_alloc_new_chunk (hdf5_file_t *f, H5O_t *oh, size_t size)
oh->chunk[chunkno].dirty = TRUE;
oh->chunk[chunkno].addr = H5O_NO_ADDR;
oh->chunk[chunkno].size = size;
oh->chunk[chunkno].image = p = H5MM_xmalloc (size);
oh->chunk[chunkno].image = p = H5MM_xcalloc (1, size);
/*
* Make sure we have enough space for all possible new messages

@ -36,6 +36,7 @@ const H5O_class_t H5O_CONT[1] = {{
H5O_CONT_ID, /*message id number */
"hdr continuation", /*message name for debugging */
sizeof (H5O_cont_t), /*native message size */
H5G_NOTHING_CACHED, /*symbol table type field */
H5O_cont_decode, /*decode message */
H5O_cont_encode, /*encode message */
NULL, /*no fast method */

@ -36,6 +36,7 @@ const H5O_class_t H5O_NAME[1] = {{
H5O_NAME_ID, /*message id number */
"name", /*message name for debugging */
sizeof (H5O_name_t), /*native message size */
H5G_NOTHING_CACHED, /*symbol table entry type field */
H5O_name_decode, /*decode message */
H5O_name_encode, /*encode message */
NULL, /*no stab entry fields */

@ -24,6 +24,7 @@ const H5O_class_t H5O_NULL[1] = {{
H5O_NULL_ID, /*message id number */
"null", /*message name for debugging */
0, /*native message size */
H5G_NOTHING_CACHED, /*symtab entry `type' field */
NULL, /*no decode method */
NULL, /*no encode method */
NULL, /*no fast method */

@ -47,6 +47,7 @@ typedef struct H5O_class_t {
intn id; /*message type ID on disk */
const char *name; /*message name for debugging */
size_t native_size; /*size of native message */
H5G_type_t cache_type; /*type field in symbol table */
void *(*decode)(hdf5_file_t*,size_t,const uint8*);
herr_t (*encode)(hdf5_file_t*,size_t,uint8*,const void*);
void *(*fast)(const H5G_entry_t*, void*); /*get from stab ent*/
@ -163,11 +164,9 @@ void *H5O_read (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
const void *H5O_peek (hdf5_file_t *f, haddr_t addr, const H5O_class_t *type,
intn sequence);
intn H5O_modify (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
hbool_t *ent_modified, const H5O_class_t *type,
intn overwrite, const void *mesg);
const H5O_class_t *type, intn overwrite, const void *mesg);
herr_t H5O_remove (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
hbool_t *ent_modified, const H5O_class_t *type,
intn sequence);
const H5O_class_t *type, intn sequence);
herr_t H5O_reset (const H5O_class_t *type, void *native);
herr_t H5O_debug (hdf5_file_t *f, haddr_t addr, FILE *stream,
intn indent, intn fwidth);

@ -53,6 +53,7 @@ const H5O_class_t H5O_SIM_DIM[1] = {{
H5O_SIM_DIM_ID, /* message id number */
"sim_dim", /* message name for debugging */
sizeof (H5O_sim_dim_t), /* native message size */
H5G_CACHED_SDATA, /* symtab entry `type' field */
H5O_sim_dim_decode, /* decode message */
H5O_sim_dim_encode, /* encode message */
H5O_sim_dim_fast, /* get message from stab entry */

@ -50,16 +50,17 @@ static herr_t H5O_sim_dtype_debug (hdf5_file_t *f, const void *_mesg,
/* This message derives from H5O */
const H5O_class_t H5O_SIM_DTYPE[1] = {{
H5O_SIM_DTYPE_ID, /* message id number */
"sim_dtype", /* message name for debugging */
sizeof (H5O_sim_dtype_t), /* native message size */
H5O_SIM_DTYPE_ID, /* message id number */
"sim_dtype", /* message name for debugging */
sizeof (H5O_sim_dtype_t), /* native message size */
H5G_CACHED_SDATA, /* symtab entry `type' field */
H5O_sim_dtype_decode, /* decode message */
H5O_sim_dtype_encode, /* encode message */
H5O_sim_dtype_fast, /* get message from stab entry */
H5O_sim_dtype_cache, /* put message into stab entry */
H5O_sim_dtype_copy, /* copy the native value */
H5O_sim_dtype_size, /* size of symbol table entry */
NULL, /* default reset method */
NULL, /* default reset method */
H5O_sim_dtype_debug, /* debug the message */
}};

@ -38,6 +38,7 @@ const H5O_class_t H5O_STAB[1] = {{
H5O_STAB_ID, /*message id number */
"stab", /*message name for debugging */
sizeof (H5O_stab_t), /*native message size */
H5G_CACHED_STAB, /*symtab entry `type' field */
H5O_stab_decode, /*decode message */
H5O_stab_encode, /*encode message */
H5O_stab_fast, /*get message from stab entry */

@ -51,6 +51,7 @@ const H5O_class_t H5O_STD_STORE[1] = {{
H5O_STD_STORE_ID, /* message id number */
"std_store", /* message name for debugging */
sizeof (H5O_std_store_t),/* native message size */
H5G_NOTHING_CACHED, /* symtab entry `type' field */
H5O_std_store_decode, /* decode message */
H5O_std_store_encode, /* encode message */
NULL, /* get message from stab entry */

@ -101,6 +101,7 @@
* File offsets.
*/
typedef off_t haddr_t;
#define NO_ADDR (-1)
/*
* Some compilers have problems declaring auto variables that point
@ -402,7 +403,7 @@ typedef off_t haddr_t;
extern hbool_t library_initialize_g; /*good thing C's lazy about extern!*/
extern hbool_t thread_initialize_g; /*don't decl interface_initialize_g */
#define FUNC_ENTER(func_name,interface_init_func,err) \
#define FUNC_ENTER(func_name,interface_init_func,err) { \
CONSTR (FUNC, #func_name); \
PABLO_SAVE (ID_ ## func_name); \
\
@ -428,8 +429,8 @@ extern hbool_t thread_initialize_g; /*don't decl interface_initialize_g */
((herr_t(*)(void))interface_init_func)()<0) { \
HRETURN_ERROR (H5E_FUNC, H5E_CANTINIT, err); \
} \
}
} \
{
/*-------------------------------------------------------------------------
@ -447,7 +448,7 @@ extern hbool_t thread_initialize_g; /*don't decl interface_initialize_g */
*
*-------------------------------------------------------------------------
*/
#define FUNC_LEAVE(return_value) HRETURN(return_value)
#define FUNC_LEAVE(return_value) HRETURN(return_value)}}
/*
* The FUNC_ENTER() and FUNC_LEAVE() macros make calls to Pablo functions

@ -15,8 +15,9 @@ PROGS=debug
# Source and object files for the library (lexicographically)...
LIB_SRC=H5.c H5A.c H5AC.c H5B.c H5C.c H5D.c H5Dconv.c H5E.c H5F.c H5G.c \
H5Gnode.c H5H.c H5M.c H5MF.c H5MM.c H5O.c H5Ocont.c H5Oname.c \
H5Onull.c H5Osdtyp.c H5Osdim.c H5Ostab.c H5Ostdst.c H5P.c H5T.c
H5Gnode.c H5Gshad.c H5H.c H5M.c H5MF.c H5MM.c H5O.c H5Ocont.c \
H5Oname.c H5Onull.c H5Osdtyp.c H5Osdim.c H5Ostab.c H5Ostdst.c H5P.c \
H5T.c
LIB_OBJ=$(LIB_SRC:.c=.o)

@ -22,6 +22,6 @@ PRIVATE_HDR=testhdf5.h
# How to build the programs...
testhdf5: $(PROG_OBJ) ../src/libhdf5.a
$(CC) $(CFLAGS) -o $@ $(PROG_OBJ) ../src/libhdf5.a
$(CC) $(CFLAGS) -o $@ $(PROG_OBJ) ../src/libhdf5.a $(LIBS)
@CONCLUDE@

@ -107,7 +107,7 @@ static void test_h5d_basic_write(void)
CHECK(ret,FAIL,"H5Tset_type");
did1=H5Mcreate(fid1,H5_DATASET,DATA1_NAME);
CHECK(sid1,FAIL,"H5Mcreate");
CHECK(did1,FAIL,"H5Mcreate");
ret=H5Dset_info(did1,tid1,sid1);
CHECK(ret,FAIL,"H5Dset_info");

@ -48,7 +48,6 @@ test_ohdr (void)
herr_t status;
void *ptr;
H5G_entry_t ent;
hbool_t ent_mod;
int i;
MESSAGE (5, ("Testing Object Headers\n"));
@ -69,7 +68,7 @@ test_ohdr (void)
MESSAGE (8, ("Creating new message...\n"));
stab.btree_addr = 11111111;
stab.heap_addr = 22222222;
status = H5O_modify (f, oh, NULL, NULL, H5O_STAB, H5O_NEW_MESG, &stab);
status = H5O_modify (f, oh, NULL, H5O_STAB, H5O_NEW_MESG, &stab);
VERIFY (status, 0, "H5O_modify");
H5AC_flush (f, NULL, 0, TRUE);
@ -85,7 +84,7 @@ test_ohdr (void)
MESSAGE (8, ("Modifying message...\n"));
stab.btree_addr = 33333333;
stab.heap_addr = 44444444;
status = H5O_modify (f, oh, NULL, NULL, H5O_STAB, 0, &stab);
status = H5O_modify (f, oh, NULL, H5O_STAB, 0, &stab);
VERIFY (status, 0, "H5O_modify");
H5AC_flush (f, NULL, 0, TRUE);
@ -102,11 +101,12 @@ test_ohdr (void)
MESSAGE (8, ("Creating a duplicate message...\n"));
ent.header = 0;
ent.type = H5G_NOTHING_CACHED;
ent.dirty = FALSE;
stab.btree_addr = 55555555;
stab.heap_addr = 66666666;
status = H5O_modify (f, oh, &ent, &ent_mod, H5O_STAB, H5O_NEW_MESG, &stab);
status = H5O_modify (f, oh, &ent, H5O_STAB, H5O_NEW_MESG, &stab);
VERIFY (status, 1, "H5O_modify");
VERIFY (ent_mod, TRUE, "H5O_modify");
VERIFY (ent.dirty, TRUE, "H5O_modify");
VERIFY (ent.type, H5G_CACHED_STAB, "H5O_modify");
VERIFY (ent.cache.stab.heap_addr, stab.heap_addr, "H5O_modify");
VERIFY (ent.cache.stab.btree_addr, stab.btree_addr, "H5O_modify");
@ -122,11 +122,12 @@ test_ohdr (void)
* Test modification of the second message with a symbol table.
*/
MESSAGE (8, ("Modifying the duplicate message...\n"));
ent.dirty = FALSE;
stab.btree_addr = 77777777;
stab.heap_addr = 88888888;
status = H5O_modify (f, oh, &ent, &ent_mod, H5O_STAB, 1, &stab);
status = H5O_modify (f, oh, &ent, H5O_STAB, 1, &stab);
VERIFY (status, 1, "H5O_modify");
VERIFY (ent_mod, TRUE, "H5O_modify");
VERIFY (ent.dirty, TRUE, "H5O_modify");
VERIFY (ent.type, H5G_CACHED_STAB, "H5O_modify");
VERIFY (ent.cache.stab.heap_addr, stab.heap_addr, "H5O_modify");
VERIFY (ent.cache.stab.btree_addr, stab.btree_addr, "H5O_modify");
@ -146,7 +147,7 @@ test_ohdr (void)
for (i=0; i<40; i++) {
stab.btree_addr = (i+1)*1000 + 1;
stab.heap_addr = (i+1)*1000 + 2;
status = H5O_modify (f, oh, NULL, NULL, H5O_STAB, H5O_NEW_MESG, &stab);
status = H5O_modify (f, oh, NULL, H5O_STAB, H5O_NEW_MESG, &stab);
VERIFY (status, 2+i, "H5O_modify");
}
H5AC_flush (f, NULL, 0, TRUE);
@ -159,7 +160,7 @@ test_ohdr (void)
for (i=0; i<10; i++) {
stab.btree_addr = (i+1)*1000 + 10;
stab.heap_addr = (i+1)*1000 + 20;
status = H5O_modify (f, oh, NULL, NULL, H5O_STAB, H5O_NEW_MESG, &stab);
status = H5O_modify (f, oh, NULL, H5O_STAB, H5O_NEW_MESG, &stab);
VERIFY (status, 42+i, "H5O_modify");
H5AC_flush (f, NULL, 0, TRUE);
}
@ -167,7 +168,7 @@ test_ohdr (void)
/*
* Delete all symbol table messages.
*/
status = H5O_remove (f, oh, NULL, NULL, H5O_STAB, H5O_ALL);
status = H5O_remove (f, oh, NULL, H5O_STAB, H5O_ALL);
CHECK_I (status, "H5O_remove");
/* close the file */

@ -65,6 +65,7 @@ test_1 (void)
CHECK (f, NULL, "H5Aatom_object");
/* create the object */
memset (&ent, 0, sizeof(ent));
ent.header = H5O_new (f, 0, 64);
CHECK_I (ent.header, "H5O_new");
ent.type = H5G_NOTHING_CACHED;
@ -152,7 +153,7 @@ test_1 (void)
CHECK_PTR (status_ptr, "H5O_read");
CHECK_PTR (name_mesg.s, "H5O_read");
VERIFY (strcmp(name_mesg.s, "foo"), 0, "H5O_read");
if (status_ptr) H5O_reset (H5O_NAME, &name_mesg); /*free message data*/
/*