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:
parent
055daa52f0
commit
25d866e9b4
20
src/H5AC.c
20
src/H5AC.c
@ -173,7 +173,7 @@ H5AC_dest (hdf5_file_t *f)
|
||||
*/
|
||||
void *
|
||||
H5AC_find_f (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr,
|
||||
const void *udata)
|
||||
void *udata)
|
||||
{
|
||||
unsigned idx;
|
||||
herr_t status;
|
||||
@ -298,9 +298,11 @@ H5AC_compare (const void *_a, const void *_b)
|
||||
* Function: H5AC_flush
|
||||
*
|
||||
* Purpose: Flushes (and destroys if DESTROY is non-zero) the specified
|
||||
* entry from the cache. If the entry type is CACHE_FREE then
|
||||
* all types of entries are flushed. If the ADDR is zero then
|
||||
* all entries of the specified type are flushed.
|
||||
* entry from the cache. If the entry TYPE is CACHE_FREE and
|
||||
* ADDR is zero then all types of entries are flushed. If TYPE
|
||||
* is CACHE_FREE and ADDR is non-zero, then whatever is cached
|
||||
* at ADDR is flushed. Otherwise the thing at ADDR is flushed
|
||||
* if it is the correct type.
|
||||
*
|
||||
* If there are protected objects they will not be flushed.
|
||||
* However, an attempt will be made to flush all non-protected
|
||||
@ -334,7 +336,7 @@ H5AC_flush (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr,
|
||||
assert (f->cache);
|
||||
i = H5AC_HASH (f, addr);
|
||||
|
||||
if (!type || 0==addr) {
|
||||
if (0==addr) {
|
||||
|
||||
#ifdef SORT_BY_ADDR
|
||||
/*
|
||||
@ -360,8 +362,7 @@ H5AC_flush (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr,
|
||||
slot = f->cache->slot + i;
|
||||
if (NULL==slot->type) continue;
|
||||
#endif
|
||||
if ((!type || type==slot->type) &&
|
||||
(0==addr || addr==slot->addr)) {
|
||||
if (!type || type==slot->type) {
|
||||
flush = slot->type->flush;
|
||||
status = (flush)(f, destroy, slot->addr, slot->thing);
|
||||
if (status<0) {
|
||||
@ -373,7 +374,8 @@ H5AC_flush (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr,
|
||||
}
|
||||
map = H5MM_xfree (map);
|
||||
|
||||
} else if (f->cache->slot[i].type==type && f->cache->slot[i].addr==addr) {
|
||||
} else if ((!type || f->cache->slot[i].type==type) &&
|
||||
f->cache->slot[i].addr==addr) {
|
||||
/*
|
||||
* Flush just this entry.
|
||||
*/
|
||||
@ -583,7 +585,7 @@ H5AC_rename (hdf5_file_t *f, const H5AC_class_t *type,
|
||||
*/
|
||||
void *
|
||||
H5AC_protect (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr,
|
||||
const void *udata)
|
||||
void *udata)
|
||||
{
|
||||
int idx;
|
||||
void *thing = NULL;
|
||||
|
@ -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,
|
||||
|
40
src/H5B.c
40
src/H5B.c
@ -100,7 +100,7 @@
|
||||
|
||||
/* PRIVATE PROTOTYPES */
|
||||
static haddr_t H5B_insert_helper (hdf5_file_t *f, haddr_t addr,
|
||||
const H5B_class_t *type,
|
||||
H5B_class_t *type,
|
||||
uint8 *lt_key, hbool_t *lt_key_changed,
|
||||
uint8 *md_key, void *udata,
|
||||
uint8 *rt_key, hbool_t *rt_key_changed);
|
||||
@ -109,14 +109,14 @@ static herr_t H5B_insert_child (hdf5_file_t *f, const H5B_class_t *type,
|
||||
intn anchor, void *md_key);
|
||||
static herr_t H5B_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr,
|
||||
H5B_t *b);
|
||||
static H5B_t *H5B_load (hdf5_file_t *f, haddr_t addr, const void *_data);
|
||||
static H5B_t *H5B_load (hdf5_file_t *f, haddr_t addr, void *_data);
|
||||
static herr_t H5B_decode_key (hdf5_file_t *f, H5B_t *bt, intn idx);
|
||||
static size_t H5B_nodesize (hdf5_file_t *f, const H5B_class_t *type,
|
||||
size_t *total_nkey_size, size_t sizeof_rkey);
|
||||
|
||||
/* H5B inherits cache-like properties from H5AC */
|
||||
static const H5AC_class_t H5AC_BT[1] = {{
|
||||
(void*(*)(hdf5_file_t*,haddr_t,const void*))H5B_load,
|
||||
(void*(*)(hdf5_file_t*,haddr_t,void*))H5B_load,
|
||||
(herr_t(*)(hdf5_file_t*,hbool_t,haddr_t,void*))H5B_flush,
|
||||
}};
|
||||
|
||||
@ -231,13 +231,14 @@ H5B_new (hdf5_file_t *f, const H5B_class_t *type)
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static H5B_t *
|
||||
H5B_load (hdf5_file_t *f, haddr_t addr, const void *_data)
|
||||
H5B_load (hdf5_file_t *f, haddr_t addr, void *_data)
|
||||
{
|
||||
const H5B_class_t *type = (const H5B_class_t *)_data;
|
||||
const H5B_class_t *type = (H5B_class_t *)_data;
|
||||
size_t size, total_nkey_size;
|
||||
H5B_t *bt = NULL;
|
||||
intn i;
|
||||
uint8 *p;
|
||||
H5B_t *ret_value = NULL;
|
||||
|
||||
FUNC_ENTER (H5B_load, NULL, NULL);
|
||||
|
||||
@ -263,11 +264,15 @@ H5B_load (hdf5_file_t *f, haddr_t addr, const void *_data)
|
||||
p = bt->page;
|
||||
|
||||
/* magic number */
|
||||
if (HDmemcmp (p, H5B_MAGIC, H5B_SIZEOF_MAGIC)) goto error;
|
||||
if (HDmemcmp (p, H5B_MAGIC, H5B_SIZEOF_MAGIC)) {
|
||||
HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, NULL);
|
||||
}
|
||||
p += 4;
|
||||
|
||||
/* node type and level */
|
||||
if (*p++ != type->id) goto error;
|
||||
if (*p++ != type->id) {
|
||||
HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, NULL);
|
||||
}
|
||||
bt->level = *p++;
|
||||
|
||||
/* entries used */
|
||||
@ -296,17 +301,18 @@ H5B_load (hdf5_file_t *f, haddr_t addr, const void *_data)
|
||||
bt->key[2*H5B_K(f,type)].dirty = FALSE;
|
||||
bt->key[2*H5B_K(f,type)].rkey = p;
|
||||
bt->key[2*H5B_K(f,type)].nkey = NULL;
|
||||
FUNC_LEAVE (bt);
|
||||
ret_value = bt;
|
||||
|
||||
error:
|
||||
if (bt) {
|
||||
done:
|
||||
if (!ret_value && bt) {
|
||||
H5MM_xfree (bt->child);
|
||||
H5MM_xfree (bt->key);
|
||||
H5MM_xfree (bt->page);
|
||||
H5MM_xfree (bt->native);
|
||||
H5MM_xfree (bt);
|
||||
}
|
||||
HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, NULL);
|
||||
|
||||
FUNC_LEAVE (ret_value);
|
||||
}
|
||||
|
||||
|
||||
@ -438,7 +444,7 @@ H5B_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5B_t *bt)
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5B_find (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, void *udata)
|
||||
H5B_find (hdf5_file_t *f, H5B_class_t *type, haddr_t addr, void *udata)
|
||||
{
|
||||
H5B_t *bt=NULL;
|
||||
intn idx=-1, lt=0, rt, cmp=1;
|
||||
@ -538,7 +544,7 @@ done:
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static haddr_t
|
||||
H5B_split (hdf5_file_t *f, const H5B_class_t *type, H5B_t *old_bt,
|
||||
H5B_split (hdf5_file_t *f, H5B_class_t *type, H5B_t *old_bt,
|
||||
haddr_t old_addr, intn anchor)
|
||||
{
|
||||
H5B_t *new_bt=NULL, *tmp_bt=NULL;
|
||||
@ -727,7 +733,7 @@ H5B_decode_key (hdf5_file_t *f, H5B_t *bt, intn idx)
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
haddr_t
|
||||
H5B_insert (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, void *udata)
|
||||
H5B_insert (hdf5_file_t *f, H5B_class_t *type, haddr_t addr, void *udata)
|
||||
{
|
||||
uint8 lt_key[256], md_key[256], rt_key[256];
|
||||
hbool_t lt_key_changed=FALSE, rt_key_changed=FALSE;
|
||||
@ -980,7 +986,7 @@ H5B_insert_child (hdf5_file_t *f, const H5B_class_t *type, H5B_t *bt,
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static haddr_t
|
||||
H5B_insert_helper (hdf5_file_t *f, haddr_t addr, const H5B_class_t *type,
|
||||
H5B_insert_helper (hdf5_file_t *f, haddr_t addr, H5B_class_t *type,
|
||||
uint8 *lt_key, hbool_t *lt_key_changed,
|
||||
uint8 *md_key, void *udata,
|
||||
uint8 *rt_key, hbool_t *rt_key_changed)
|
||||
@ -1219,7 +1225,7 @@ done:
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5B_list (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, void *udata)
|
||||
H5B_list (hdf5_file_t *f, H5B_class_t *type, haddr_t addr, void *udata)
|
||||
{
|
||||
H5B_t *bt=NULL;
|
||||
haddr_t next_addr;
|
||||
@ -1352,7 +1358,7 @@ H5B_nodesize (hdf5_file_t *f, const H5B_class_t *type,
|
||||
*/
|
||||
herr_t
|
||||
H5B_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent,
|
||||
intn fwidth, const H5B_class_t *type)
|
||||
intn fwidth, H5B_class_t *type)
|
||||
{
|
||||
H5B_t *bt = NULL;
|
||||
int i;
|
||||
|
@ -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
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
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:");
|
||||
|
264
src/H5Gnode.c
264
src/H5Gnode.c
@ -18,22 +18,26 @@
|
||||
* Robb Matzke, 5 Aug 1997
|
||||
* Added calls to H5E.
|
||||
*
|
||||
* Robb Matzke, 18 Sep 1997
|
||||
* Added shadow entries.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#define H5G_PACKAGE /*suppress error message about including H5Gpkg.h*/
|
||||
|
||||
/* Packages needed by this file... */
|
||||
#include <H5private.h> /*library */
|
||||
#include <H5ACprivate.h> /*cache */
|
||||
#include <H5Bprivate.h> /*B-link trees */
|
||||
#include <H5Eprivate.h> /*error handling */
|
||||
#include <H5Gprivate.h> /*me */
|
||||
#include <H5Gpkg.h> /*me */
|
||||
#include <H5Hprivate.h> /*heap */
|
||||
#include <H5MFprivate.h> /*file memory management */
|
||||
#include <H5MMprivate.h> /*core memory management */
|
||||
#include <H5Oprivate.h> /*header messages */
|
||||
|
||||
#define PABLO_MASK H5G_node_mask
|
||||
|
||||
|
||||
/* PRIVATE PROTOTYPES */
|
||||
static herr_t H5G_node_decode_key (hdf5_file_t *f, uint8 *raw, void *_key);
|
||||
static herr_t H5G_node_encode_key (hdf5_file_t *f, uint8 *raw, void *_key);
|
||||
@ -42,8 +46,7 @@ static haddr_t H5G_node_new (hdf5_file_t *f, void *_lt_key, void *_udata,
|
||||
void *_rt_key);
|
||||
static herr_t H5G_node_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr,
|
||||
H5G_node_t *sym);
|
||||
static H5G_node_t *H5G_node_load (hdf5_file_t *f, haddr_t addr,
|
||||
const void *_data);
|
||||
static H5G_node_t *H5G_node_load (hdf5_file_t *f, haddr_t addr, void *_data);
|
||||
static intn H5G_node_cmp (hdf5_file_t *f, void *_lt_key, void *_udata,
|
||||
void *_rt_key);
|
||||
static herr_t H5G_node_found (hdf5_file_t *f, haddr_t addr,
|
||||
@ -58,12 +61,12 @@ static size_t H5G_node_sizeof_rkey (hdf5_file_t *f);
|
||||
|
||||
/* H5G inherits cache-like properties from H5AC */
|
||||
static const H5AC_class_t H5AC_SNODE[1] = {{
|
||||
(void*(*)(hdf5_file_t*,haddr_t,const void*))H5G_node_load,
|
||||
(void*(*)(hdf5_file_t*,haddr_t,void*))H5G_node_load,
|
||||
(herr_t(*)(hdf5_file_t*,hbool_t,haddr_t,void*))H5G_node_flush,
|
||||
}};
|
||||
|
||||
/* H5G inherits B-tree like properties from H5B */
|
||||
const H5B_class_t H5B_SNODE[1] = {{
|
||||
H5B_class_t H5B_SNODE[1] = {{
|
||||
H5B_SNODE_ID, /*id */
|
||||
sizeof (H5G_node_key_t), /*sizeof_nkey */
|
||||
H5G_node_sizeof_rkey, /*get_sizeof_rkey */
|
||||
@ -265,7 +268,10 @@ H5G_node_new (hdf5_file_t *f, void *_lt_key, void *_udata, void *_rt_key)
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5G_node_flush
|
||||
*
|
||||
* Purpose: Flush a symbol table node to disk.
|
||||
* Purpose: Flush a symbol table node to disk. If any entries have dirty
|
||||
* shadows, the shadow value is copied into the entry before the
|
||||
* entry is flushed. The association between shadows and
|
||||
* entries is broken.
|
||||
*
|
||||
* Return: Success: SUCCEED
|
||||
*
|
||||
@ -285,6 +291,7 @@ H5G_node_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5G_node_t *sym)
|
||||
uint8 *buf=NULL, *p=NULL;
|
||||
size_t size;
|
||||
herr_t status;
|
||||
int i;
|
||||
|
||||
FUNC_ENTER (H5G_node_flush, NULL, FAIL);
|
||||
|
||||
@ -295,6 +302,19 @@ H5G_node_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5G_node_t *sym)
|
||||
assert (addr>=0);
|
||||
assert (sym);
|
||||
|
||||
/*
|
||||
* Synchronize all entries with their corresponding shadow if they have
|
||||
* one.
|
||||
*/
|
||||
for (i=0; i<sym->nsyms; i++) {
|
||||
if (H5G_shadow_sync (sym->entry+i)<0) {
|
||||
HRETURN_ERROR (H5E_SYM, H5E_CANTFLUSH, FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the symbol node to disk.
|
||||
*/
|
||||
if (sym->dirty) {
|
||||
size = H5G_node_size (f);
|
||||
buf = p = H5MM_xmalloc (size);
|
||||
@ -321,7 +341,15 @@ H5G_node_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5G_node_t *sym)
|
||||
if (status<0) HRETURN_ERROR (H5E_SYM, H5E_WRITEERROR, FAIL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy the symbol node? This might happen if the node is being
|
||||
* preempted from the cache. We should also dissociate the shadow
|
||||
* from the entry.
|
||||
*/
|
||||
if (destroy) {
|
||||
for (i=0; i<sym->nsyms; i++) {
|
||||
H5G_shadow_dissociate (sym->entry+i);
|
||||
}
|
||||
sym->entry = H5MM_xfree (sym->entry);
|
||||
H5MM_xfree (sym);
|
||||
}
|
||||
@ -333,7 +361,8 @@ H5G_node_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5G_node_t *sym)
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5G_node_load
|
||||
*
|
||||
* Purpose: Loads a symbol table from the file.
|
||||
* Purpose: Loads a symbol table from the file and associates shadows
|
||||
* with their entries.
|
||||
*
|
||||
* Return: Success: Ptr to the new table.
|
||||
*
|
||||
@ -348,11 +377,13 @@ H5G_node_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5G_node_t *sym)
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static H5G_node_t *
|
||||
H5G_node_load (hdf5_file_t *f, haddr_t addr, const void *_udata)
|
||||
H5G_node_load (hdf5_file_t *f, haddr_t addr, void *_udata)
|
||||
{
|
||||
H5G_node_t *sym = NULL;
|
||||
size_t size = 0;
|
||||
uint8 *buf = NULL, *p = NULL;
|
||||
H5G_entry_t *self = NULL;
|
||||
H5G_node_t *ret_value = NULL; /*for error handling*/
|
||||
|
||||
FUNC_ENTER (H5G_node_load, NULL, NULL);
|
||||
|
||||
@ -361,7 +392,8 @@ H5G_node_load (hdf5_file_t *f, haddr_t addr, const void *_udata)
|
||||
*/
|
||||
assert (f);
|
||||
assert (addr>=0);
|
||||
assert (NULL==_udata);
|
||||
assert (_udata);
|
||||
self = (H5G_entry_t*)_udata;
|
||||
|
||||
/*
|
||||
* Initialize variables.
|
||||
@ -372,17 +404,19 @@ H5G_node_load (hdf5_file_t *f, haddr_t addr, const void *_udata)
|
||||
sym->entry = H5MM_xcalloc (2*H5G_NODE_K(f), sizeof(H5G_entry_t));
|
||||
|
||||
if (H5F_block_read (f, addr, size, buf)<0) {
|
||||
H5MM_xfree (sym->entry);
|
||||
H5MM_xfree (sym);
|
||||
HRETURN_ERROR (H5E_SYM, H5E_READERROR, NULL);
|
||||
HGOTO_ERROR (H5E_SYM, H5E_READERROR, NULL);
|
||||
}
|
||||
|
||||
/* magic */
|
||||
if (HDmemcmp (p, H5G_NODE_MAGIC, H5G_NODE_SIZEOF_MAGIC)) goto error;
|
||||
if (HDmemcmp (p, H5G_NODE_MAGIC, H5G_NODE_SIZEOF_MAGIC)) {
|
||||
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, NULL);
|
||||
}
|
||||
p += 4;
|
||||
|
||||
/* version */
|
||||
if (H5G_NODE_VERS!=*p++) goto error;
|
||||
if (H5G_NODE_VERS!=*p++) {
|
||||
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, NULL);
|
||||
}
|
||||
|
||||
/* reserved */
|
||||
p++;
|
||||
@ -391,15 +425,28 @@ H5G_node_load (hdf5_file_t *f, haddr_t addr, const void *_udata)
|
||||
UINT16DECODE (p, sym->nsyms);
|
||||
|
||||
/* entries */
|
||||
if (H5G_decode_vec (f, &p, sym->entry, sym->nsyms)<0) goto error;
|
||||
if (H5G_decode_vec (f, &p, sym->entry, sym->nsyms)<0) {
|
||||
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, NULL);
|
||||
}
|
||||
buf = H5MM_xfree (buf);
|
||||
|
||||
H5MM_xfree (buf);
|
||||
FUNC_LEAVE (sym);
|
||||
/* shadows */
|
||||
if (H5G_shadow_assoc_node (f, sym, self)<0) {
|
||||
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, NULL);
|
||||
}
|
||||
|
||||
ret_value = sym;
|
||||
|
||||
|
||||
error:
|
||||
H5MM_xfree (buf);
|
||||
H5MM_xfree (sym);
|
||||
HRETURN_ERROR (H5E_SYM, H5E_CANTLOAD, NULL);
|
||||
done:
|
||||
if (!ret_value) {
|
||||
buf = H5MM_xfree (buf);
|
||||
if (sym) {
|
||||
sym->entry = H5MM_xfree (sym->entry);
|
||||
sym = H5MM_xfree (sym);
|
||||
}
|
||||
}
|
||||
FUNC_LEAVE (ret_value);
|
||||
}
|
||||
|
||||
|
||||
@ -433,7 +480,7 @@ error:
|
||||
static intn
|
||||
H5G_node_cmp (hdf5_file_t *f, void *_lt_key, void *_udata, void *_rt_key)
|
||||
{
|
||||
H5G_node_ud1_t *udata = (H5G_node_ud1_t *)_udata;
|
||||
H5G_bt_ud1_t *udata = (H5G_bt_ud1_t *)_udata;
|
||||
H5G_node_key_t *lt_key = (H5G_node_key_t *)_lt_key;
|
||||
H5G_node_key_t *rt_key = (H5G_node_key_t *)_rt_key;
|
||||
const char *s;
|
||||
@ -488,7 +535,8 @@ static herr_t
|
||||
H5G_node_found (hdf5_file_t *f, haddr_t addr, const void *_lt_key,
|
||||
void *_udata, const void *_rt_key)
|
||||
{
|
||||
H5G_node_ud1_t *udata = (H5G_node_ud1_t *)_udata;
|
||||
H5G_bt_ud1_t *bt_udata = (H5G_bt_ud1_t *)_udata;
|
||||
H5G_ac_ud1_t ac_udata;
|
||||
H5G_node_t *sn = NULL;
|
||||
intn lt=0, idx=0, rt, cmp=1;
|
||||
const char *s;
|
||||
@ -501,12 +549,15 @@ H5G_node_found (hdf5_file_t *f, haddr_t addr, const void *_lt_key,
|
||||
*/
|
||||
assert (f);
|
||||
assert (addr>=0);
|
||||
assert (udata);
|
||||
assert (bt_udata);
|
||||
|
||||
ac_udata.dir_addr = bt_udata->dir_addr;
|
||||
ac_udata.heap_addr = bt_udata->heap_addr;
|
||||
|
||||
/*
|
||||
* Load the symbol table node for exclusive access.
|
||||
*/
|
||||
if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, NULL))) {
|
||||
if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, &ac_udata))) {
|
||||
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL);
|
||||
}
|
||||
|
||||
@ -516,10 +567,11 @@ H5G_node_found (hdf5_file_t *f, haddr_t addr, const void *_lt_key,
|
||||
rt = sn->nsyms;
|
||||
while (lt<rt && cmp) {
|
||||
idx = (lt + rt) / 2;
|
||||
if (NULL==(s=H5H_peek (f, udata->heap_addr, sn->entry[idx].name_off))) {
|
||||
if (NULL==(s=H5H_peek (f, bt_udata->heap_addr,
|
||||
sn->entry[idx].name_off))) {
|
||||
HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL);
|
||||
}
|
||||
cmp = HDstrcmp (udata->name, s);
|
||||
cmp = HDstrcmp (bt_udata->name, s);
|
||||
|
||||
if (cmp<0) {
|
||||
rt = idx;
|
||||
@ -529,20 +581,18 @@ H5G_node_found (hdf5_file_t *f, haddr_t addr, const void *_lt_key,
|
||||
}
|
||||
if (cmp) HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL);
|
||||
|
||||
switch (udata->operation) {
|
||||
switch (bt_udata->operation) {
|
||||
case H5G_OPER_FIND:
|
||||
/*
|
||||
* The caller is querying the symbol entry.
|
||||
* The caller is querying the symbol entry. Return just a pointer to
|
||||
* the entry. The pointer is valid until the next call to H5AC.
|
||||
*/
|
||||
udata->entry = sn->entry[idx];
|
||||
H5G_shadow_sync (sn->entry+idx);
|
||||
bt_udata->entry_ptr = sn->entry+idx;
|
||||
break;
|
||||
|
||||
case H5G_OPER_MODIFY:
|
||||
/*
|
||||
* The caller is modifying the symbol entry.
|
||||
*/
|
||||
sn->entry[idx] = udata->entry;
|
||||
sn->dirty += 1;
|
||||
default:
|
||||
HRETURN_ERROR (H5E_SYM, H5E_UNSUPPORTED, FAIL);
|
||||
break;
|
||||
}
|
||||
ret_value = SUCCEED;
|
||||
@ -589,6 +639,10 @@ done:
|
||||
*
|
||||
* Modifications:
|
||||
*
|
||||
* Robb Matzke, 18 Sep 1997
|
||||
* If the shadow pointer is non-null then the shadow is updated to point
|
||||
* to the new entry.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static haddr_t
|
||||
@ -599,14 +653,17 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor,
|
||||
{
|
||||
H5G_node_key_t *md_key = (H5G_node_key_t *)_md_key;
|
||||
H5G_node_key_t *rt_key = (H5G_node_key_t *)_rt_key;
|
||||
H5G_node_ud1_t *udata = (H5G_node_ud1_t *)_udata;
|
||||
|
||||
H5G_bt_ud1_t *bt_udata = (H5G_bt_ud1_t *)_udata;
|
||||
|
||||
H5G_ac_ud1_t ac_udata;
|
||||
H5G_node_t *sn=NULL, *snrt=NULL;
|
||||
haddr_t new_node=0, offset;
|
||||
const char *s;
|
||||
intn idx=-1, cmp=1;
|
||||
intn lt=0, rt; /*binary search cntrs */
|
||||
intn i;
|
||||
haddr_t ret_value = FAIL;
|
||||
H5G_shadow_t *shadow = NULL;
|
||||
|
||||
FUNC_ENTER (H5G_node_insert, NULL, FAIL);
|
||||
|
||||
@ -618,7 +675,8 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor,
|
||||
assert (anchor);
|
||||
assert (md_key);
|
||||
assert (rt_key);
|
||||
assert (udata);
|
||||
assert (bt_udata);
|
||||
bt_udata->entry_ptr = NULL;
|
||||
|
||||
/*
|
||||
* Symbol tables are always split so the new symbol table node is
|
||||
@ -631,7 +689,9 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor,
|
||||
/*
|
||||
* Load the symbol node.
|
||||
*/
|
||||
if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, NULL))) {
|
||||
ac_udata.dir_addr = bt_udata->dir_addr;
|
||||
ac_udata.heap_addr = bt_udata->heap_addr;
|
||||
if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, &ac_udata))) {
|
||||
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL);
|
||||
}
|
||||
|
||||
@ -641,10 +701,11 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor,
|
||||
rt = sn->nsyms;
|
||||
while (lt<rt) {
|
||||
idx = (lt + rt) / 2;
|
||||
if (NULL==(s=H5H_peek (f, udata->heap_addr, sn->entry[idx].name_off))) {
|
||||
if (NULL==(s=H5H_peek (f, bt_udata->heap_addr,
|
||||
sn->entry[idx].name_off))) {
|
||||
HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL);
|
||||
}
|
||||
if (0==(cmp=HDstrcmp (udata->name, s))) {
|
||||
if (0==(cmp=HDstrcmp (bt_udata->name, s))) {
|
||||
HGOTO_ERROR (H5E_SYM, H5E_CANTINSERT, FAIL); /*already present*/
|
||||
}
|
||||
if (cmp<0) {
|
||||
@ -660,9 +721,9 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor,
|
||||
* heap address changed and update the symbol table object header
|
||||
* with the new heap address.
|
||||
*/
|
||||
offset = H5H_insert (f, udata->heap_addr, HDstrlen(udata->name)+1,
|
||||
udata->name);
|
||||
udata->entry.name_off = offset;
|
||||
offset = H5H_insert (f, bt_udata->heap_addr, HDstrlen(bt_udata->name)+1,
|
||||
bt_udata->name);
|
||||
bt_udata->entry.name_off = offset;
|
||||
if (offset<0) HGOTO_ERROR (H5E_SYM, H5E_CANTINSERT, FAIL);
|
||||
|
||||
if (sn->nsyms>=2*H5G_NODE_K(f)) {
|
||||
@ -676,7 +737,7 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor,
|
||||
if ((new_node = H5G_node_new (f, NULL, NULL, NULL))<0) {
|
||||
HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL);
|
||||
}
|
||||
if (NULL==(snrt=H5AC_find (f, H5AC_SNODE, new_node, NULL))) {
|
||||
if (NULL==(snrt=H5AC_find (f, H5AC_SNODE, new_node, &ac_udata))) {
|
||||
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL);
|
||||
}
|
||||
HDmemcpy (snrt->entry, sn->entry + H5G_NODE_K(f),
|
||||
@ -684,6 +745,13 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor,
|
||||
snrt->nsyms = H5G_NODE_K(f);
|
||||
snrt->dirty += 1;
|
||||
|
||||
/* Right shadows */
|
||||
for (i=0; i<H5G_NODE_K(f); i++) {
|
||||
if ((shadow = snrt->entry[i].shadow)) {
|
||||
shadow->main = snrt->entry + i;
|
||||
}
|
||||
}
|
||||
|
||||
/* The left node */
|
||||
HDmemset (sn->entry + H5G_NODE_K(f), 0,
|
||||
H5G_NODE_K(f) * sizeof(H5G_entry_t));
|
||||
@ -692,19 +760,46 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor,
|
||||
|
||||
/* Insert the new entry */
|
||||
if (idx<=H5G_NODE_K(f)) {
|
||||
|
||||
/* Adjust shadows */
|
||||
for (i=idx; i<sn->nsyms; i++) {
|
||||
if (sn->entry[i].shadow) {
|
||||
sn->entry[i].shadow->main = sn->entry + i + 1;
|
||||
}
|
||||
}
|
||||
if (bt_udata->entry.shadow) {
|
||||
bt_udata->entry.shadow->main = sn->entry + idx;
|
||||
}
|
||||
|
||||
/* Move entries */
|
||||
HDmemmove (sn->entry + idx + 1,
|
||||
sn->entry + idx,
|
||||
(H5G_NODE_K(f)-idx) * sizeof(H5G_entry_t));
|
||||
sn->entry[idx] = udata->entry;
|
||||
sn->entry[idx] = bt_udata->entry;
|
||||
sn->entry[idx].name_off = offset;
|
||||
sn->entry[idx].dirty = TRUE;
|
||||
sn->nsyms += 1;
|
||||
|
||||
} else {
|
||||
idx -= H5G_NODE_K (f);
|
||||
|
||||
/* Adjust shadows */
|
||||
for (i=idx; i<snrt->nsyms; i++) {
|
||||
if (snrt->entry[i].shadow) {
|
||||
snrt->entry[i].shadow->main = snrt->entry + i + 1;
|
||||
}
|
||||
}
|
||||
if (bt_udata->entry.shadow) {
|
||||
bt_udata->entry.shadow->main = snrt->entry + idx;
|
||||
}
|
||||
|
||||
/* Move entries */
|
||||
HDmemmove (snrt->entry + idx + 1,
|
||||
snrt->entry + idx,
|
||||
(H5G_NODE_K(f)-idx) * sizeof (H5G_entry_t));
|
||||
snrt->entry[idx] = udata->entry;
|
||||
snrt->entry[idx] = bt_udata->entry;
|
||||
snrt->entry[idx].name_off = offset;
|
||||
snrt->entry[idx].dirty = TRUE;
|
||||
snrt->nsyms += 1;
|
||||
|
||||
if (idx+1 == sn->nsyms) {
|
||||
@ -721,12 +816,21 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor,
|
||||
* Add the new symbol to the node.
|
||||
*/
|
||||
sn->dirty += 1;
|
||||
for (i=idx; i<sn->nsyms; i++) {
|
||||
if (sn->entry[i].shadow) {
|
||||
sn->entry[i].shadow->main = sn->entry + i + 1;
|
||||
}
|
||||
}
|
||||
if (bt_udata->entry.shadow) {
|
||||
bt_udata->entry.shadow->main = sn->entry + idx;
|
||||
}
|
||||
HDmemmove (sn->entry+idx+1, sn->entry+idx,
|
||||
(sn->nsyms-idx) * sizeof (H5G_entry_t));
|
||||
sn->nsyms += 1;
|
||||
sn->entry[idx] = udata->entry;
|
||||
sn->entry[idx] = bt_udata->entry;
|
||||
sn->entry[idx].name_off = offset;
|
||||
|
||||
sn->entry[idx].dirty = TRUE;
|
||||
|
||||
if (idx+1==sn->nsyms) {
|
||||
rt_key->offset = offset;
|
||||
*rt_key_changed = TRUE;
|
||||
@ -765,12 +869,13 @@ done:
|
||||
static herr_t
|
||||
H5G_node_list (hdf5_file_t *f, haddr_t addr, void *_udata)
|
||||
{
|
||||
H5G_node_list_t *udata = (H5G_node_list_t *)_udata;
|
||||
H5G_bt_ud2_t *bt_udata = (H5G_bt_ud2_t *)_udata;
|
||||
H5G_node_t *sn = NULL;
|
||||
intn i;
|
||||
const char *s;
|
||||
herr_t ret_value = FAIL;
|
||||
|
||||
H5G_ac_ud1_t ac_udata;
|
||||
|
||||
FUNC_ENTER (H5G_node_list, NULL, FAIL);
|
||||
|
||||
/*
|
||||
@ -778,9 +883,11 @@ H5G_node_list (hdf5_file_t *f, haddr_t addr, void *_udata)
|
||||
*/
|
||||
assert (f);
|
||||
assert (addr>=0);
|
||||
assert (udata);
|
||||
assert (bt_udata);
|
||||
|
||||
if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, NULL))) {
|
||||
ac_udata.dir_addr = bt_udata->dir_addr;
|
||||
ac_udata.heap_addr = bt_udata->heap_addr;
|
||||
if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, &ac_udata))) {
|
||||
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL);
|
||||
}
|
||||
|
||||
@ -789,32 +896,34 @@ H5G_node_list (hdf5_file_t *f, haddr_t addr, void *_udata)
|
||||
* keep track of how many names we've seen and don't bother doing
|
||||
* anything else.
|
||||
*/
|
||||
if (udata->nsyms >= udata->maxentries) {
|
||||
udata->nsyms += sn->nsyms;
|
||||
if (bt_udata->nsyms >= bt_udata->maxentries) {
|
||||
bt_udata->nsyms += sn->nsyms;
|
||||
HGOTO_DONE (SUCCEED);
|
||||
}
|
||||
|
||||
/*
|
||||
* Save the symbol table entries.
|
||||
*/
|
||||
if (udata->entry) {
|
||||
for (i=0; i<sn->nsyms && udata->nsyms+i<udata->maxentries; i++) {
|
||||
udata->entry[udata->nsyms+i] = sn->entry[i];
|
||||
if (bt_udata->entry) {
|
||||
for (i=0; i<sn->nsyms && bt_udata->nsyms+i<bt_udata->maxentries; i++) {
|
||||
H5G_shadow_sync (sn->entry+i);
|
||||
bt_udata->entry[bt_udata->nsyms+i] = sn->entry[i];
|
||||
}
|
||||
}
|
||||
if (udata->name) {
|
||||
for (i=0; i<sn->nsyms && udata->nsyms+i<udata->maxentries; i++) {
|
||||
if (NULL==(s=H5H_peek (f, udata->heap_addr, sn->entry[i].name_off))) {
|
||||
if (bt_udata->name) {
|
||||
for (i=0; i<sn->nsyms && bt_udata->nsyms+i<bt_udata->maxentries; i++) {
|
||||
if (NULL==(s=H5H_peek (f, bt_udata->heap_addr,
|
||||
sn->entry[i].name_off))) {
|
||||
HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL);
|
||||
}
|
||||
udata->name[udata->nsyms+i] = H5MM_xstrdup (s);
|
||||
bt_udata->name[bt_udata->nsyms+i] = H5MM_xstrdup (s);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the number of symbols.
|
||||
*/
|
||||
udata->nsyms += sn->nsyms;
|
||||
bt_udata->nsyms += sn->nsyms;
|
||||
ret_value = SUCCEED;
|
||||
|
||||
done:
|
||||
@ -847,10 +956,11 @@ herr_t
|
||||
H5G_node_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent,
|
||||
intn fwidth, haddr_t heap)
|
||||
{
|
||||
int i;
|
||||
int i, acc;
|
||||
H5G_node_t *sn = NULL;
|
||||
herr_t status;
|
||||
const char *s;
|
||||
H5G_ac_ud1_t ac_udata;
|
||||
|
||||
FUNC_ENTER (H5G_node_debug, NULL, FAIL);
|
||||
|
||||
@ -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
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
|
150
src/H5Gprivate.h
150
src/H5Gprivate.h
@ -8,7 +8,7 @@
|
||||
* Jul 11 1997
|
||||
* Robb Matzke <matzke@llnl.gov>
|
||||
*
|
||||
* Purpose: Private stuff for the H5G package (symbol tables).
|
||||
* Purpose: Library-visible declarations.
|
||||
*
|
||||
* Modifications:
|
||||
*
|
||||
@ -25,18 +25,17 @@
|
||||
|
||||
#define H5G_NODE_MAGIC "SNOD" /*symbol table node magic number */
|
||||
#define H5G_NODE_SIZEOF_MAGIC 4 /*sizeof symbol node magic number */
|
||||
#define H5G_NODE_VERS 1 /*symbol table node version number */
|
||||
#define H5G_SIZE_HINT 1024 /*default root dir size hint */
|
||||
#define H5G_NODE_K(F) ((F)->file_create_parms.sym_leaf_k)
|
||||
#define H5G_NODE_SIZEOF_HDR(F) (H5G_NODE_SIZEOF_MAGIC + 4)
|
||||
#define H5G_new_entry() H5MM_xcalloc (1, sizeof(H5G_entry_t))
|
||||
|
||||
/*
|
||||
* The disk size for a symbol table entry...
|
||||
*/
|
||||
#define H5G_SIZEOF_ENTRY(F) \
|
||||
(H5F_SIZEOF_OFFSET(F) + /*offset of name into heap */ \
|
||||
H5F_SIZEOF_OFFSET(F) + /*address of object header */ \
|
||||
4 + /*entry type */ \
|
||||
24) /*scratch pad space */
|
||||
|
||||
#define H5G_DEFAULT_ROOT_SIZE 32
|
||||
|
||||
/*
|
||||
* Various types of object header information can be cached in a symbol
|
||||
* table entry (it's normal home is the object header to which the entry
|
||||
@ -44,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
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);
|
||||
}
|
49
src/H5H.c
49
src/H5H.c
@ -45,7 +45,7 @@ typedef struct H5H_t {
|
||||
} H5H_t;
|
||||
|
||||
/* PRIVATE PROTOTYPES */
|
||||
static H5H_t *H5H_load (hdf5_file_t *f, haddr_t addr, const void *udata);
|
||||
static H5H_t *H5H_load (hdf5_file_t *f, haddr_t addr, void *udata);
|
||||
static herr_t H5H_flush (hdf5_file_t *f, hbool_t dest, haddr_t addr,
|
||||
H5H_t *heap);
|
||||
|
||||
@ -53,7 +53,7 @@ static herr_t H5H_flush (hdf5_file_t *f, hbool_t dest, haddr_t addr,
|
||||
* H5H inherits cache-like properties from H5AC
|
||||
*/
|
||||
static const H5AC_class_t H5AC_HEAP[1] = {{
|
||||
(void*(*)(hdf5_file_t*,haddr_t,const void*))H5H_load,
|
||||
(void*(*)(hdf5_file_t*,haddr_t,void*))H5H_load,
|
||||
(herr_t(*)(hdf5_file_t*,hbool_t,haddr_t,void*))H5H_flush,
|
||||
}};
|
||||
|
||||
@ -162,12 +162,13 @@ H5H_new (hdf5_file_t *f, H5H_type_t heap_type, size_t size_hint)
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static H5H_t *
|
||||
H5H_load (hdf5_file_t *f, haddr_t addr, const void *udata)
|
||||
H5H_load (hdf5_file_t *f, haddr_t addr, void *udata)
|
||||
{
|
||||
uint8 hdr[20], *p;
|
||||
H5H_t *heap=NULL;
|
||||
H5H_free_t *fl=NULL, *tail=NULL;
|
||||
haddr_t free_block=H5H_FREE_NULL;
|
||||
H5H_t *ret_value=NULL;
|
||||
|
||||
FUNC_ENTER (H5H_load, NULL, NULL);
|
||||
|
||||
@ -184,7 +185,9 @@ H5H_load (hdf5_file_t *f, haddr_t addr, const void *udata)
|
||||
heap = H5MM_xcalloc (1, sizeof(H5H_t));
|
||||
|
||||
/* magic number */
|
||||
if (HDmemcmp (hdr, H5H_MAGIC, H5H_SIZEOF_MAGIC)) goto error;
|
||||
if (HDmemcmp (hdr, H5H_MAGIC, H5H_SIZEOF_MAGIC)) {
|
||||
HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL);
|
||||
}
|
||||
p += H5H_SIZEOF_MAGIC;
|
||||
|
||||
/* heap data size */
|
||||
@ -194,7 +197,7 @@ H5H_load (hdf5_file_t *f, haddr_t addr, const void *udata)
|
||||
/* free list head */
|
||||
H5F_decode_offset (f, p, free_block);
|
||||
if (-1!=free_block && (free_block<0 || free_block>=heap->disk_alloc)) {
|
||||
goto error;
|
||||
HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL);
|
||||
}
|
||||
|
||||
/* data */
|
||||
@ -203,12 +206,14 @@ H5H_load (hdf5_file_t *f, haddr_t addr, const void *udata)
|
||||
if (heap->disk_alloc &&
|
||||
H5F_block_read (f, heap->addr, heap->disk_alloc,
|
||||
heap->chunk + H5H_SIZEOF_HDR(f))<0) {
|
||||
goto error;
|
||||
HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL);
|
||||
}
|
||||
|
||||
/* free list */
|
||||
while (H5H_FREE_NULL!=free_block) {
|
||||
if (free_block<0 || free_block>=heap->disk_alloc) goto error;
|
||||
if (free_block<0 || free_block>=heap->disk_alloc) {
|
||||
HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL);
|
||||
}
|
||||
fl = H5MM_xmalloc (sizeof (H5H_free_t));
|
||||
fl->offset = free_block;
|
||||
fl->prev = tail;
|
||||
@ -221,14 +226,15 @@ H5H_load (hdf5_file_t *f, haddr_t addr, const void *udata)
|
||||
H5F_decode_offset (f, p, free_block);
|
||||
H5F_decode_length (f, p, fl->size);
|
||||
|
||||
if (fl->offset + fl->size > heap->disk_alloc) goto error;
|
||||
if (fl->offset + fl->size > heap->disk_alloc) {
|
||||
HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
FUNC_LEAVE (heap);
|
||||
ret_value = heap;
|
||||
|
||||
|
||||
error:
|
||||
if (heap) {
|
||||
done:
|
||||
if (!ret_value && heap) {
|
||||
heap->chunk = H5MM_xfree (heap->chunk);
|
||||
H5MM_xfree (heap);
|
||||
for (fl=heap->freelist; fl; fl=tail) {
|
||||
@ -236,7 +242,8 @@ error:
|
||||
H5MM_xfree (fl);
|
||||
}
|
||||
}
|
||||
HRETURN_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL);
|
||||
|
||||
FUNC_LEAVE (ret_value);
|
||||
}
|
||||
|
||||
|
||||
@ -462,9 +469,10 @@ H5H_peek (hdf5_file_t *f, haddr_t addr, off_t offset)
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5H_remove_free
|
||||
*
|
||||
* Purpose: Removes free list element FL from the specified heap.
|
||||
* Purpose: Removes free list element FL from the specified heap and
|
||||
* frees it.
|
||||
*
|
||||
* Return: void
|
||||
* Return: NULL
|
||||
*
|
||||
* Programmer: Robb Matzke
|
||||
* matzke@llnl.gov
|
||||
@ -474,13 +482,14 @@ H5H_peek (hdf5_file_t *f, haddr_t addr, off_t offset)
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static void
|
||||
static H5H_free_t *
|
||||
H5H_remove_free (H5H_t *heap, H5H_free_t *fl)
|
||||
{
|
||||
if (fl->prev) fl->prev->next = fl->next;
|
||||
if (fl->next) fl->next->prev = fl->prev;
|
||||
|
||||
if (!fl->prev) heap->freelist = fl->next;
|
||||
return H5MM_xfree (fl);
|
||||
}
|
||||
|
||||
|
||||
@ -545,7 +554,7 @@ H5H_insert (hdf5_file_t *f, haddr_t addr, size_t buf_size, const void *buf)
|
||||
break;
|
||||
} else if (fl->size==need) {
|
||||
offset = fl->offset;
|
||||
H5H_remove_free (heap, fl);
|
||||
fl = H5H_remove_free (heap, fl);
|
||||
break;
|
||||
} else if (!max_fl || max_fl->offset < fl->offset) {
|
||||
max_fl = fl;
|
||||
@ -582,7 +591,7 @@ H5H_insert (hdf5_file_t *f, haddr_t addr, size_t buf_size, const void *buf)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
H5H_remove_free (heap, max_fl);
|
||||
max_fl = H5H_remove_free (heap, max_fl);
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -762,7 +771,7 @@ H5H_remove (hdf5_file_t *f, haddr_t addr, off_t offset, size_t size)
|
||||
if (fl2->offset + fl2->size == fl->offset) {
|
||||
fl->offset = fl2->offset;
|
||||
fl->size += fl2->size;
|
||||
H5H_remove_free (heap, fl2);
|
||||
fl2 = H5H_remove_free (heap, fl2);
|
||||
HRETURN (SUCCEED);
|
||||
}
|
||||
}
|
||||
@ -774,7 +783,7 @@ H5H_remove (hdf5_file_t *f, haddr_t addr, off_t offset, size_t size)
|
||||
while (fl2) {
|
||||
if (fl->offset + fl->size == fl2->offset) {
|
||||
fl->size += fl2->size;
|
||||
H5H_remove_free (heap, fl2);
|
||||
fl2 = H5H_remove_free (heap, fl2);
|
||||
HRETURN (SUCCEED);
|
||||
}
|
||||
}
|
||||
|
12
src/H5MM.c
12
src/H5MM.c
@ -168,6 +168,16 @@ H5MM_xstrdup (const char *s)
|
||||
void *
|
||||
H5MM_xfree (const void *mem)
|
||||
{
|
||||
if (mem) HDfree (mem);
|
||||
/*
|
||||
* free(3) takes a non-const pointer as an argument even though
|
||||
* conceptually the argument could be a constant because by time
|
||||
* free() mucks with it's contents, it should already be free :-)
|
||||
* Instead of passing a const arg to free, which generates a
|
||||
* compiler warning, we cast it to a non-const arg first. With
|
||||
* gcc, this results in a warning only if -Wcast-qual is turned on.
|
||||
*/
|
||||
void *non_const_mem = mem;
|
||||
|
||||
if (mem) HDfree (non_const_mem);
|
||||
return NULL;
|
||||
}
|
||||
|
79
src/H5O.c
79
src/H5O.c
@ -27,7 +27,7 @@
|
||||
/* PRIVATE PROTOTYPES */
|
||||
static herr_t H5O_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr,
|
||||
H5O_t *oh);
|
||||
static H5O_t *H5O_load (hdf5_file_t *f, haddr_t addr, const void *_data);
|
||||
static H5O_t *H5O_load (hdf5_file_t *f, haddr_t addr, void *_data);
|
||||
static intn H5O_find_in_ohdr (hdf5_file_t *f, haddr_t addr,
|
||||
const H5O_class_t **type_p, intn sequence);
|
||||
static intn H5O_alloc (hdf5_file_t *f, H5O_t *oh, const H5O_class_t *type,
|
||||
@ -37,7 +37,7 @@ static intn H5O_alloc_new_chunk (hdf5_file_t *f, H5O_t *oh, size_t size);
|
||||
|
||||
/* H5O inherits cache-like properties from H5AC */
|
||||
static const H5AC_class_t H5AC_OHDR[1] = {{
|
||||
(void*(*)(hdf5_file_t*,haddr_t,const void*))H5O_load,
|
||||
(void*(*)(hdf5_file_t*,haddr_t,void*))H5O_load,
|
||||
(herr_t(*)(hdf5_file_t*,hbool_t,haddr_t,void*))H5O_flush,
|
||||
}};
|
||||
|
||||
@ -166,7 +166,7 @@ H5O_new (hdf5_file_t *f, intn nlink, size_t size_hint)
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static H5O_t *
|
||||
H5O_load (hdf5_file_t *f, haddr_t addr, const void *_data)
|
||||
H5O_load (hdf5_file_t *f, haddr_t addr, void *_data)
|
||||
{
|
||||
H5O_t *oh = NULL;
|
||||
H5O_t *ret_value = (void*)1; /*kludge for HGOTO_ERROR*/
|
||||
@ -509,8 +509,9 @@ H5O_link (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent, intn adjust)
|
||||
|
||||
/* check args */
|
||||
assert (f);
|
||||
assert (addr>=0);
|
||||
|
||||
assert (addr>0 || (ent && ent->header>0));
|
||||
if (addr<=0) addr = ent->header;
|
||||
|
||||
/* get header */
|
||||
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) {
|
||||
HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL);
|
||||
@ -528,9 +529,11 @@ H5O_link (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent, intn adjust)
|
||||
}
|
||||
} else {
|
||||
oh->nlink += adjust;
|
||||
if (oh->nlink>1 && ent) ent->type = H5G_NOTHING_CACHED;
|
||||
if (oh->nlink>1 && ent && H5G_NOTHING_CACHED!=ent->type) {
|
||||
ent->dirty = TRUE;
|
||||
ent->type = H5G_NOTHING_CACHED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
oh->dirty = TRUE;
|
||||
FUNC_LEAVE (oh->nlink);
|
||||
@ -570,7 +573,10 @@ H5O_read (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
|
||||
|
||||
/* check args */
|
||||
assert (f);
|
||||
assert (addr>=0);
|
||||
if (addr<=0 && (!ent || ent->header<=0)) {
|
||||
HRETURN_ERROR (H5E_OHDR, H5E_NOTFOUND, NULL);
|
||||
}
|
||||
if (addr<=0) addr = ent->header;
|
||||
assert (sequence>=0);
|
||||
|
||||
/* can we get it from the symbol table? */
|
||||
@ -585,6 +591,10 @@ H5O_read (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
|
||||
HRETURN_ERROR (H5E_OHDR, H5E_NOTFOUND, NULL);
|
||||
}
|
||||
|
||||
#ifdef LATER
|
||||
/* should we cache it in ENT? */
|
||||
#endif
|
||||
|
||||
/* copy the message to the user-supplied buffer */
|
||||
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) {
|
||||
HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, NULL);
|
||||
@ -692,7 +702,7 @@ H5O_peek (hdf5_file_t *f, haddr_t addr, const H5O_class_t *type,
|
||||
|
||||
/* check args */
|
||||
assert (f);
|
||||
assert (addr>=0);
|
||||
assert (addr>0);
|
||||
|
||||
if ((idx = H5O_find_in_ohdr (f, addr, &type, sequence))<0) {
|
||||
HRETURN_ERROR (H5E_OHDR, H5E_NOTFOUND, NULL);
|
||||
@ -709,17 +719,20 @@ H5O_peek (hdf5_file_t *f, haddr_t addr, const H5O_class_t *type,
|
||||
* Function: H5O_modify
|
||||
*
|
||||
* Purpose: Modifies an existing message or creates a new message.
|
||||
* The object header is at file address ADDR of file F. An
|
||||
* The object header is at file address ADDR of file F (but if
|
||||
* ENT is present then its `header' field is used instead). An
|
||||
* optional symbol table entry ENT can be supplied in which
|
||||
* case the cache fields in that symbol table are updated if
|
||||
* appropriate. If the symbol table entry changes then the
|
||||
* optional ENT_MODIFIED arg will point to a non-zero value,
|
||||
* otherwise ENT_MODIFIED isn't changed.
|
||||
* appropriate.
|
||||
*
|
||||
* The OVERWRITE argument is either a sequence number of a
|
||||
* message to overwrite (usually zero) or the constant
|
||||
* H5O_NEW_MESSAGE (-1) to indicate that a new message is to
|
||||
* be created.
|
||||
* be created. If the message to overwrite doesn't exist then
|
||||
* it is created (but only if it can be inserted so its sequence
|
||||
* number is OVERWRITE; that is, you can create a message with
|
||||
* the sequence number 5 if there is no message with sequence
|
||||
* number 4).
|
||||
*
|
||||
* Return: Success: The sequence number of the message that
|
||||
* was modified or created.
|
||||
@ -736,8 +749,7 @@ H5O_peek (hdf5_file_t *f, haddr_t addr, const H5O_class_t *type,
|
||||
*/
|
||||
intn
|
||||
H5O_modify (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
|
||||
hbool_t *ent_modified, const H5O_class_t *type,
|
||||
intn overwrite, const void *mesg)
|
||||
const H5O_class_t *type, intn overwrite, const void *mesg)
|
||||
{
|
||||
H5O_t *oh = NULL;
|
||||
intn idx, sequence;
|
||||
@ -747,10 +759,11 @@ H5O_modify (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
|
||||
|
||||
/* check args */
|
||||
assert (f);
|
||||
assert (addr>=0);
|
||||
assert (addr>0 || (ent && ent->header>0));
|
||||
assert (type);
|
||||
assert (mesg);
|
||||
|
||||
if (addr<=0) addr = ent->header;
|
||||
|
||||
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) {
|
||||
HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL);
|
||||
}
|
||||
@ -764,7 +777,13 @@ H5O_modify (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
|
||||
/* Was the right message found? */
|
||||
if (overwrite>=0 &&
|
||||
(idx>=oh->nmesgs || sequence!=overwrite)) {
|
||||
HRETURN_ERROR (H5E_OHDR, H5E_NOTFOUND, FAIL); /*message not found*/
|
||||
|
||||
/* But can we insert a new one with this sequence number? */
|
||||
if (overwrite==sequence+1) {
|
||||
overwrite = -1;
|
||||
} else {
|
||||
HRETURN_ERROR (H5E_OHDR, H5E_NOTFOUND, FAIL); /*message not found*/
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate space for the new message */
|
||||
@ -787,7 +806,7 @@ H5O_modify (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
|
||||
/* Copy into the symbol table entry */
|
||||
if (oh->nlink<=1 && ent && type->cache) {
|
||||
hbool_t modified = (type->cache)(ent, mesg);
|
||||
if (modified && ent_modified) *ent_modified = modified;
|
||||
if (ent && !ent->dirty) ent->dirty = modified;
|
||||
}
|
||||
|
||||
FUNC_LEAVE (sequence);
|
||||
@ -826,7 +845,7 @@ H5O_modify (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
|
||||
*/
|
||||
herr_t
|
||||
H5O_remove (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
|
||||
hbool_t *ent_modified, const H5O_class_t *type, intn sequence)
|
||||
const H5O_class_t *type, intn sequence)
|
||||
{
|
||||
H5O_t *oh = NULL;
|
||||
intn i, seq;
|
||||
@ -835,8 +854,9 @@ H5O_remove (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
|
||||
|
||||
/* check args */
|
||||
assert (f);
|
||||
assert (addr>=0);
|
||||
assert (addr>0 || (ent && ent->header>0));
|
||||
assert (type);
|
||||
if (addr<=0) addr = ent->header;
|
||||
|
||||
/* load the object header */
|
||||
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) {
|
||||
@ -848,9 +868,9 @@ H5O_remove (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent,
|
||||
if (seq++ == sequence || H5O_ALL==sequence) {
|
||||
|
||||
/* clear symbol table entry cache */
|
||||
if (ent && type->cache && H5G_NOTHING_CACHED!=ent->type) {
|
||||
if (ent && type->cache && type->cache_type==ent->type) {
|
||||
ent->type = H5G_NOTHING_CACHED;
|
||||
if (ent_modified) *ent_modified = TRUE;
|
||||
ent->dirty = TRUE;
|
||||
}
|
||||
|
||||
/* change message type to nil and zero it */
|
||||
@ -922,9 +942,14 @@ H5O_alloc_extend_chunk (H5O_t *oh, intn chunkno, size_t size)
|
||||
oh->mesg[idx].raw_size += delta;
|
||||
|
||||
old_addr = oh->chunk[chunkno].image;
|
||||
oh->chunk[chunkno].size += delta;
|
||||
|
||||
/* Be careful not to indroduce garbage */
|
||||
oh->chunk[chunkno].image = H5MM_xrealloc (old_addr,
|
||||
oh->chunk[chunkno].size);
|
||||
(oh->chunk[chunkno].size +
|
||||
delta));
|
||||
HDmemset (oh->chunk[chunkno].image + oh->chunk[chunkno].size,
|
||||
0, delta);
|
||||
oh->chunk[chunkno].size += delta;
|
||||
|
||||
/* adjust raw addresses for messages of this chunk */
|
||||
if (old_addr != oh->chunk[chunkno].image) {
|
||||
@ -1071,7 +1096,7 @@ H5O_alloc_new_chunk (hdf5_file_t *f, H5O_t *oh, size_t size)
|
||||
oh->chunk[chunkno].dirty = TRUE;
|
||||
oh->chunk[chunkno].addr = H5O_NO_ADDR;
|
||||
oh->chunk[chunkno].size = size;
|
||||
oh->chunk[chunkno].image = p = H5MM_xmalloc (size);
|
||||
oh->chunk[chunkno].image = p = H5MM_xcalloc (1, size);
|
||||
|
||||
/*
|
||||
* Make sure we have enough space for all possible new messages
|
||||
|
@ -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");
|
||||
|
21
test/tohdr.c
21
test/tohdr.c
@ -48,7 +48,6 @@ test_ohdr (void)
|
||||
herr_t status;
|
||||
void *ptr;
|
||||
H5G_entry_t ent;
|
||||
hbool_t ent_mod;
|
||||
int i;
|
||||
|
||||
MESSAGE (5, ("Testing Object Headers\n"));
|
||||
@ -69,7 +68,7 @@ test_ohdr (void)
|
||||
MESSAGE (8, ("Creating new message...\n"));
|
||||
stab.btree_addr = 11111111;
|
||||
stab.heap_addr = 22222222;
|
||||
status = H5O_modify (f, oh, NULL, NULL, H5O_STAB, H5O_NEW_MESG, &stab);
|
||||
status = H5O_modify (f, oh, NULL, H5O_STAB, H5O_NEW_MESG, &stab);
|
||||
VERIFY (status, 0, "H5O_modify");
|
||||
|
||||
H5AC_flush (f, NULL, 0, TRUE);
|
||||
@ -85,7 +84,7 @@ test_ohdr (void)
|
||||
MESSAGE (8, ("Modifying message...\n"));
|
||||
stab.btree_addr = 33333333;
|
||||
stab.heap_addr = 44444444;
|
||||
status = H5O_modify (f, oh, NULL, NULL, H5O_STAB, 0, &stab);
|
||||
status = H5O_modify (f, oh, NULL, H5O_STAB, 0, &stab);
|
||||
VERIFY (status, 0, "H5O_modify");
|
||||
|
||||
H5AC_flush (f, NULL, 0, TRUE);
|
||||
@ -102,11 +101,12 @@ test_ohdr (void)
|
||||
MESSAGE (8, ("Creating a duplicate message...\n"));
|
||||
ent.header = 0;
|
||||
ent.type = H5G_NOTHING_CACHED;
|
||||
ent.dirty = FALSE;
|
||||
stab.btree_addr = 55555555;
|
||||
stab.heap_addr = 66666666;
|
||||
status = H5O_modify (f, oh, &ent, &ent_mod, H5O_STAB, H5O_NEW_MESG, &stab);
|
||||
status = H5O_modify (f, oh, &ent, H5O_STAB, H5O_NEW_MESG, &stab);
|
||||
VERIFY (status, 1, "H5O_modify");
|
||||
VERIFY (ent_mod, TRUE, "H5O_modify");
|
||||
VERIFY (ent.dirty, TRUE, "H5O_modify");
|
||||
VERIFY (ent.type, H5G_CACHED_STAB, "H5O_modify");
|
||||
VERIFY (ent.cache.stab.heap_addr, stab.heap_addr, "H5O_modify");
|
||||
VERIFY (ent.cache.stab.btree_addr, stab.btree_addr, "H5O_modify");
|
||||
@ -122,11 +122,12 @@ test_ohdr (void)
|
||||
* Test modification of the second message with a symbol table.
|
||||
*/
|
||||
MESSAGE (8, ("Modifying the duplicate message...\n"));
|
||||
ent.dirty = FALSE;
|
||||
stab.btree_addr = 77777777;
|
||||
stab.heap_addr = 88888888;
|
||||
status = H5O_modify (f, oh, &ent, &ent_mod, H5O_STAB, 1, &stab);
|
||||
status = H5O_modify (f, oh, &ent, H5O_STAB, 1, &stab);
|
||||
VERIFY (status, 1, "H5O_modify");
|
||||
VERIFY (ent_mod, TRUE, "H5O_modify");
|
||||
VERIFY (ent.dirty, TRUE, "H5O_modify");
|
||||
VERIFY (ent.type, H5G_CACHED_STAB, "H5O_modify");
|
||||
VERIFY (ent.cache.stab.heap_addr, stab.heap_addr, "H5O_modify");
|
||||
VERIFY (ent.cache.stab.btree_addr, stab.btree_addr, "H5O_modify");
|
||||
@ -146,7 +147,7 @@ test_ohdr (void)
|
||||
for (i=0; i<40; i++) {
|
||||
stab.btree_addr = (i+1)*1000 + 1;
|
||||
stab.heap_addr = (i+1)*1000 + 2;
|
||||
status = H5O_modify (f, oh, NULL, NULL, H5O_STAB, H5O_NEW_MESG, &stab);
|
||||
status = H5O_modify (f, oh, NULL, H5O_STAB, H5O_NEW_MESG, &stab);
|
||||
VERIFY (status, 2+i, "H5O_modify");
|
||||
}
|
||||
H5AC_flush (f, NULL, 0, TRUE);
|
||||
@ -159,7 +160,7 @@ test_ohdr (void)
|
||||
for (i=0; i<10; i++) {
|
||||
stab.btree_addr = (i+1)*1000 + 10;
|
||||
stab.heap_addr = (i+1)*1000 + 20;
|
||||
status = H5O_modify (f, oh, NULL, NULL, H5O_STAB, H5O_NEW_MESG, &stab);
|
||||
status = H5O_modify (f, oh, NULL, H5O_STAB, H5O_NEW_MESG, &stab);
|
||||
VERIFY (status, 42+i, "H5O_modify");
|
||||
H5AC_flush (f, NULL, 0, TRUE);
|
||||
}
|
||||
@ -167,7 +168,7 @@ test_ohdr (void)
|
||||
/*
|
||||
* Delete all symbol table messages.
|
||||
*/
|
||||
status = H5O_remove (f, oh, NULL, NULL, H5O_STAB, H5O_ALL);
|
||||
status = H5O_remove (f, oh, NULL, H5O_STAB, H5O_ALL);
|
||||
CHECK_I (status, "H5O_remove");
|
||||
|
||||
/* close the file */
|
||||
|
@ -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*/
|
||||
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user