diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/H5A.c | 2 | ||||
-rw-r--r-- | src/H5AC.c | 26 | ||||
-rw-r--r-- | src/H5ACprivate.h | 10 | ||||
-rw-r--r-- | src/H5Apublic.h | 2 | ||||
-rw-r--r-- | src/H5B.c | 369 | ||||
-rw-r--r-- | src/H5Bprivate.h | 35 | ||||
-rw-r--r-- | src/H5C.c | 20 | ||||
-rw-r--r-- | src/H5Cprivate.h | 2 | ||||
-rw-r--r-- | src/H5Cpublic.h | 1 | ||||
-rw-r--r-- | src/H5D.c | 8 | ||||
-rw-r--r-- | src/H5Distore.c | 740 | ||||
-rw-r--r-- | src/H5E.c | 5 | ||||
-rw-r--r-- | src/H5Epublic.h | 9 | ||||
-rw-r--r-- | src/H5F.c | 40 | ||||
-rw-r--r-- | src/H5Fistore.c | 740 | ||||
-rw-r--r-- | src/H5Fprivate.h | 11 | ||||
-rw-r--r-- | src/H5G.c | 799 | ||||
-rw-r--r-- | src/H5Gent.c | 2 | ||||
-rw-r--r-- | src/H5Gnode.c | 81 | ||||
-rw-r--r-- | src/H5Gpkg.h | 30 | ||||
-rw-r--r-- | src/H5Gprivate.h | 11 | ||||
-rw-r--r-- | src/H5Gpublic.h | 10 | ||||
-rw-r--r-- | src/H5Gshad.c | 86 | ||||
-rw-r--r-- | src/H5Gstab.c | 10 | ||||
-rw-r--r-- | src/H5H.c | 21 | ||||
-rw-r--r-- | src/H5O.c | 43 | ||||
-rw-r--r-- | src/H5Oistore.c | 271 | ||||
-rw-r--r-- | src/H5Oname.c | 14 | ||||
-rw-r--r-- | src/H5Oprivate.h | 21 | ||||
-rw-r--r-- | src/H5Osdtyp.c | 2 | ||||
-rw-r--r-- | src/H5config.h.in | 12 | ||||
-rw-r--r-- | src/H5private.h | 14 | ||||
-rw-r--r-- | src/Makefile.in | 10 |
33 files changed, 2943 insertions, 514 deletions
@@ -276,7 +276,7 @@ done: *******************************************************************************/ hid_t H5Aregister_atom(group_t grp, /* IN: Group to register the object in */ - const VOIDP object /* IN: Object to attach to atom */ + const void *object /* IN: Object to attach to atom */ ) { atom_group_t *grp_ptr=NULL; /* ptr to the atomic group */ @@ -143,10 +143,12 @@ H5AC_dest (H5F_t *f) * * Purpose: Given an object type and the address at which that object * is located in the file, return a pointer to the object. - * The optional UDATA structure is passed down to the function - * that is responsible for loading the object into memory. - * The pointer is guaranteed to be valid until the next call - * to an H5AC function (if you want a pointer which is valid + * The optional UDATA1 and UDATA2 structures are passed down to + * the function that is responsible for loading the object into + * memory. + * + * The returned pointer is guaranteed to be valid until the next + * call to an H5AC function (if you want a pointer which is valid * indefinately then see H5AC_protect()). * * If H5AC_DEBUG_PROTECT is defined then this function also @@ -175,7 +177,8 @@ H5AC_dest (H5F_t *f) *------------------------------------------------------------------------- */ void * -H5AC_find_f (H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *udata) +H5AC_find_f (H5F_t *f, const H5AC_class_t *type, haddr_t addr, + void *udata1, void *udata2) { unsigned idx; herr_t status; @@ -228,7 +231,7 @@ H5AC_find_f (H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *udata) * Load a new thing. If it can't be loaded, then return an error * without preempting anything. */ - if (NULL==(thing=(type->load)(f, addr, udata))) { + if (NULL==(thing=(type->load)(f, addr, udata1, udata2))) { HRETURN_ERROR (H5E_CACHE, H5E_CANTLOAD, NULL); } @@ -272,7 +275,7 @@ H5AC_find_f (H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *udata) * Failure: never fails * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Aug 12 1997 * * Modifications: @@ -604,7 +607,7 @@ H5AC_rename (H5F_t *f, const H5AC_class_t *type, * Failure: NULL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Sep 2 1997 * * Modifications: @@ -612,7 +615,8 @@ H5AC_rename (H5F_t *f, const H5AC_class_t *type, *------------------------------------------------------------------------- */ void * -H5AC_protect (H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *udata) +H5AC_protect (H5F_t *f, const H5AC_class_t *type, haddr_t addr, + void *udata1, void *udata2) { int idx; void *thing = NULL; @@ -663,7 +667,7 @@ H5AC_protect (H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *udata) * Load a new thing. If it can't be loaded, then return an error * without preempting anything. */ - if (NULL==(thing=(type->load)(f, addr, udata))) { + if (NULL==(thing=(type->load)(f, addr, udata1, udata2))) { HRETURN_ERROR (H5E_CACHE, H5E_CANTLOAD, NULL); } } @@ -706,7 +710,7 @@ H5AC_protect (H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *udata) * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Sep 2 1997 * * Modifications: diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h index a028d9c..25549ff 100644 --- a/src/H5ACprivate.h +++ b/src/H5ACprivate.h @@ -39,7 +39,7 @@ * by the LOAD method if the DEST argument is non-zero. */ typedef struct H5AC_class_t { - void *(*load)(H5F_t*, haddr_t addr, void *udata); + void *(*load)(H5F_t*, haddr_t addr, void *udata1, void *udata2); herr_t (*flush)(H5F_t*, hbool_t dest, haddr_t addr, void *thing); } H5AC_class_t; @@ -78,9 +78,9 @@ typedef struct H5AC_t { */ herr_t H5AC_dest (H5F_t *f); void *H5AC_find_f (H5F_t *f, const H5AC_class_t *type, haddr_t addr, - void *udata); + void *udata1, void *udata2); void * H5AC_protect (H5F_t *f, const H5AC_class_t *type, haddr_t addr, - void *udata); + void *udata1, void *udata2); herr_t H5AC_unprotect (H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing); herr_t H5AC_flush (H5F_t *f, const H5AC_class_t *type, haddr_t addr, @@ -91,11 +91,11 @@ herr_t H5AC_rename (H5F_t *f, const H5AC_class_t *type, haddr_t old, herr_t H5AC_set (H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing); -#define H5AC_find(F,TYPE,ADDR,UDATA) \ +#define H5AC_find(F,TYPE,ADDR,UDATA1,UDATA2) \ (((F)->shared->cache->slot[H5AC_HASH(F,ADDR)].type==(TYPE) && \ (F)->shared->cache->slot[H5AC_HASH(F,ADDR)].addr==(ADDR)) ? \ (F)->shared->cache->slot[H5AC_HASH(F,ADDR)].thing : \ - H5AC_find_f (F, TYPE, ADDR, UDATA)) + H5AC_find_f (F, TYPE, ADDR, UDATA1, UDATA2)) #endif /* !_H5ACprivate_H */ diff --git a/src/H5Apublic.h b/src/H5Apublic.h index 36cceed..efae778 100644 --- a/src/H5Apublic.h +++ b/src/H5Apublic.h @@ -110,7 +110,7 @@ intn H5Adestroy_group(group_t grp /* IN: Group to destroy */ *******************************************************************************/ hid_t H5Aregister_atom(group_t grp, /* IN: Group to register the object in */ - const VOIDP object /* IN: Object to attach to atom */ + const void *object /* IN: Object to attach to atom */ ); /****************************************************************************** @@ -100,21 +100,23 @@ /* PRIVATE PROTOTYPES */ static haddr_t H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type, + H5B_ins_t *anchor, uint8 *lt_key, hbool_t *lt_key_changed, uint8 *md_key, void *udata, uint8 *rt_key, hbool_t *rt_key_changed); static herr_t H5B_insert_child (H5F_t *f, const H5B_class_t *type, H5B_t *bt, intn idx, haddr_t child, - intn anchor, void *md_key); + H5B_ins_t anchor, void *md_key); static herr_t H5B_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5B_t *b); -static H5B_t *H5B_load (H5F_t *f, haddr_t addr, void *_data); +static H5B_t *H5B_load (H5F_t *f, haddr_t addr, void *_type, void *udata); static herr_t H5B_decode_key (H5F_t *f, H5B_t *bt, intn idx); +static herr_t H5B_decode_keys (H5F_t *f, H5B_t *bt, intn idx); static size_t H5B_nodesize (H5F_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*(*)(H5F_t*,haddr_t,void*))H5B_load, + (void*(*)(H5F_t*,haddr_t,void*,void*))H5B_load, (herr_t(*)(H5F_t*,hbool_t,haddr_t,void*))H5B_flush, }}; @@ -125,7 +127,9 @@ static interface_initialize_g = FALSE; /*------------------------------------------------------------------------- * Function: H5B_new * - * Purpose: Creates a new empty B-tree leaf node. + * Purpose: Creates a new empty B-tree leaf node. The UDATA pointer is + * passed as an argument to the sizeof_rkey() method for the + * B-tree. * * Return: Success: address of new node. * @@ -140,7 +144,7 @@ static interface_initialize_g = FALSE; *------------------------------------------------------------------------- */ haddr_t -H5B_new (H5F_t *f, const H5B_class_t *type) +H5B_new (H5F_t *f, const H5B_class_t *type, void *udata) { H5B_t *bt=NULL; haddr_t addr; @@ -159,7 +163,7 @@ H5B_new (H5F_t *f, const H5B_class_t *type) /* * Allocate file and memory data structures. */ - sizeof_rkey = (type->get_sizeof_rkey)(f); + sizeof_rkey = (type->get_sizeof_rkey)(f, udata); size = H5B_nodesize (f, type, &total_native_keysize, sizeof_rkey); if ((addr = H5MF_alloc (f, size))<0) { HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL); @@ -229,9 +233,9 @@ H5B_new (H5F_t *f, const H5B_class_t *type) *------------------------------------------------------------------------- */ static H5B_t * -H5B_load (H5F_t *f, haddr_t addr, void *_data) +H5B_load (H5F_t *f, haddr_t addr, void *_type, void *udata) { - const H5B_class_t *type = (H5B_class_t *)_data; + const H5B_class_t *type = (H5B_class_t *)_type; size_t size, total_nkey_size; H5B_t *bt = NULL; intn i; @@ -247,7 +251,7 @@ H5B_load (H5F_t *f, haddr_t addr, void *_data) assert (type->get_sizeof_rkey); bt = H5MM_xmalloc (sizeof(H5B_t)); - bt->sizeof_rkey = (type->get_sizeof_rkey)(f); + bt->sizeof_rkey = (type->get_sizeof_rkey)(f, udata); size = H5B_nodesize (f, type, &total_nkey_size, bt->sizeof_rkey); bt->type = type; bt->dirty = FALSE; @@ -375,7 +379,8 @@ H5B_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5B_t *bt) assert (bt->key[i].rkey == p); if (bt->key[i].dirty) { if (bt->key[i].nkey) { - if ((bt->type->encode)(f, bt->key[i].rkey, bt->key[i].nkey)<0) { + if ((bt->type->encode)(f, bt, bt->key[i].rkey, + bt->key[i].nkey)<0) { HRETURN_ERROR (H5E_BTREE, H5E_CANTENCODE, FAIL); } } @@ -464,21 +469,14 @@ H5B_find (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata) * Perform a binary search to locate the child which contains * the thing for which we're searching. */ - if (NULL==(bt=H5AC_protect (f, H5AC_BT, addr, type))) { + if (NULL==(bt=H5AC_protect (f, H5AC_BT, addr, type, udata))) { HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); } rt = bt->nchildren; while (lt<rt && cmp) { idx = (lt + rt) / 2; - - /* the left key */ - if (!bt->key[idx].nkey && H5B_decode_key (f, bt, idx)<0) { - HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); - } - - /* the right key */ - if (!bt->key[idx+1].nkey && H5B_decode_key (f, bt, idx+1)<0) { + if (H5B_decode_keys (f, bt, idx)<0) { HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); } @@ -522,9 +520,11 @@ done: * Function: H5B_split * * Purpose: Split a single node into two nodes. If anchor is - * H5B_ANCHOR_LT then the new node gets the right half of - * the old node. If anchor is H5B_ANCHOR_RT then the - * new node gets the left half of the old node. + * H5B_INS_RIGHT then the new node gets the right half of + * the old node. If anchor is H5B_INS_LEFT then the + * new node gets the left half of the old node. The UDATA + * pointer is passed to the sizeof_rkey() method but is + * otherwise unused. * * The OLD_BT argument is a pointer to a protected B-tree * node. @@ -543,7 +543,7 @@ done: */ static haddr_t H5B_split (H5F_t *f, H5B_class_t *type, H5B_t *old_bt, haddr_t old_addr, - intn anchor) + H5B_ins_t anchor, void *udata) { H5B_t *new_bt=NULL, *tmp_bt=NULL; haddr_t ret_value=FAIL, new_addr=FAIL; @@ -558,21 +558,22 @@ H5B_split (H5F_t *f, H5B_class_t *type, H5B_t *old_bt, haddr_t old_addr, assert (f); assert (type); assert (old_addr>=0); + assert (H5B_INS_LEFT==anchor || H5B_INS_RIGHT==anchor); /* * Initialize variables. */ assert (old_bt->nchildren == 2*H5B_K(f,type)); recsize = old_bt->sizeof_rkey + H5F_SIZEOF_OFFSET(f); - delta = H5B_ANCHOR_LT==anchor ? H5B_K(f,type) : 0; + delta = H5B_INS_RIGHT==anchor ? H5B_K(f,type) : 0; /* * Create the new B-tree node. */ - if ((new_addr = H5B_new (f, type))<0) { + if ((new_addr = H5B_new (f, type, udata))<0) { HGOTO_ERROR (H5E_BTREE, H5E_CANTINIT, FAIL); } - if (NULL==(new_bt=H5AC_protect (f, H5AC_BT, new_addr, type))) { + if (NULL==(new_bt=H5AC_protect (f, H5AC_BT, new_addr, type, udata))) { HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); } new_bt->level = old_bt->level; @@ -606,12 +607,12 @@ H5B_split (H5F_t *f, H5B_class_t *type, H5B_t *old_bt, haddr_t old_addr, /* * Truncate the old node. */ - delta = H5B_ANCHOR_LT==anchor ? 0 : H5B_K(f,type); + delta = H5B_INS_RIGHT==anchor ? 0 : H5B_K(f,type); old_bt->dirty = TRUE; old_bt->ndirty = BOUND (0, old_bt->ndirty-delta, H5B_K(f,type)); old_bt->nchildren = H5B_K(f,type); - if (H5B_ANCHOR_RT==anchor) { + if (H5B_INS_LEFT==anchor) { HDmemcpy (old_bt->page + H5B_SIZEOF_HDR(f), old_bt->page + H5B_SIZEOF_HDR(f) + delta*recsize, H5B_K(f,type) * recsize); @@ -642,12 +643,13 @@ H5B_split (H5F_t *f, H5B_class_t *type, H5B_t *old_bt, haddr_t old_addr, /* * Update sibling pointers. */ - if (H5B_ANCHOR_LT==anchor) { + if (H5B_INS_RIGHT==anchor) { new_bt->left = old_addr; new_bt->right = old_bt->right; if (old_bt->right) { - if (NULL==(tmp_bt=H5AC_find (f, H5AC_BT, old_bt->right, type))) { + if (NULL==(tmp_bt=H5AC_find (f, H5AC_BT, old_bt->right, type, + udata))) { HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); } tmp_bt->dirty = TRUE; @@ -659,7 +661,8 @@ H5B_split (H5F_t *f, H5B_class_t *type, H5B_t *old_bt, haddr_t old_addr, new_bt->right = old_addr; if (old_bt->left) { - if (NULL==(tmp_bt=H5AC_find (f, H5AC_BT, old_bt->left, type))) { + if (NULL==(tmp_bt=H5AC_find (f, H5AC_BT, old_bt->left, type, + udata))) { HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); } tmp_bt->dirty = TRUE; @@ -702,7 +705,44 @@ H5B_decode_key (H5F_t *f, H5B_t *bt, intn idx) FUNC_ENTER (H5B_decode_key, NULL, FAIL); bt->key[idx].nkey = bt->native + idx * bt->type->sizeof_nkey; - if ((bt->type->decode)(f, bt->key[idx].rkey, bt->key[idx].nkey)<0) { + if ((bt->type->decode)(f, bt, bt->key[idx].rkey, + bt->key[idx].nkey)<0) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); + } + + FUNC_LEAVE (SUCCEED); +} + + +/*------------------------------------------------------------------------- + * Function: H5B_decode_keys + * + * Purpose: Decode keys on either side of the specified branch. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Tuesday, October 14, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5B_decode_keys (H5F_t *f, H5B_t *bt, intn idx) +{ + FUNC_ENTER (H5B_decode_keys, NULL, FAIL); + + assert (f); + assert (bt); + assert (idx>=0 && idx<bt->nchildren); + + if (!bt->key[idx].nkey && H5B_decode_key (f, bt, idx)<0) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); + } + if (!bt->key[idx+1].nkey && H5B_decode_key (f, bt, idx+1)<0) { HRETURN_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); } @@ -741,6 +781,7 @@ H5B_insert (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata) size_t size; uint8 *buf; haddr_t tmp_addr; + H5B_ins_t anchor = H5B_INS_ERROR; FUNC_ENTER (H5B_insert, NULL, FAIL); @@ -749,17 +790,18 @@ H5B_insert (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata) */ assert (f); assert (type); - assert (type->sizeof_nkey < sizeof lt_key); + assert (type->sizeof_nkey <= sizeof lt_key); - child = H5B_insert_helper (f, addr, type, lt_key, <_key_changed, + child = H5B_insert_helper (f, addr, type, &anchor, lt_key, <_key_changed, md_key, udata, rt_key, &rt_key_changed); - if (child<0) { + if (child<0 || anchor<0) { HRETURN_ERROR (H5E_BTREE, H5E_CANTINIT, FAIL); } - if (0==child) HRETURN (addr); + if (H5B_INS_NOOP==anchor) HRETURN (addr); + assert (H5B_INS_RIGHT==anchor); /* the current root */ - if (NULL==(bt = H5AC_find (f, H5AC_BT, addr, type))) { + if (NULL==(bt = H5AC_find (f, H5AC_BT, addr, type, udata))) { HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); } level = bt->level; @@ -771,7 +813,7 @@ H5B_insert (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata) } /* the new node */ - if (NULL==(bt = H5AC_find (f, H5AC_BT, child, type))) { + if (NULL==(bt = H5AC_find (f, H5AC_BT, child, type, udata))) { HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); } if (!rt_key_changed) { @@ -812,14 +854,14 @@ H5B_insert (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata) addr = tmp_addr; /* update the new child's left pointer */ - if (NULL==(bt=H5AC_find (f, H5AC_BT, child, type))) { + if (NULL==(bt=H5AC_find (f, H5AC_BT, child, type, udata))) { HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); } bt->dirty = TRUE; bt->left = addr; /* clear the old root at the old address */ - if (NULL==(bt=H5AC_find (f, H5AC_BT, new_root, type))) { + if (NULL==(bt=H5AC_find (f, H5AC_BT, new_root, type, udata))) { HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); } bt->dirty = TRUE; @@ -830,7 +872,7 @@ H5B_insert (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata) /* the new root */ - if (NULL==(bt = H5AC_find (f, H5AC_BT, new_root, type))) { + if (NULL==(bt = H5AC_find (f, H5AC_BT, new_root, type, udata))) { HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); } bt->dirty = TRUE; @@ -877,7 +919,7 @@ H5B_insert (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata) */ static herr_t H5B_insert_child (H5F_t *f, const H5B_class_t *type, H5B_t *bt, - intn idx, haddr_t child, intn anchor, void *md_key) + intn idx, haddr_t child, H5B_ins_t anchor, void *md_key) { size_t recsize; intn i; @@ -888,7 +930,7 @@ H5B_insert_child (H5F_t *f, const H5B_class_t *type, H5B_t *bt, bt->dirty = TRUE; recsize = bt->sizeof_rkey + H5F_SIZEOF_OFFSET(f); - if (H5B_ANCHOR_LT==anchor) { + if (H5B_INS_RIGHT==anchor) { /* * The MD_KEY is the left key of the new node. */ @@ -950,6 +992,7 @@ H5B_insert_child (H5F_t *f, const H5B_class_t *type, H5B_t *bt, FUNC_LEAVE (SUCCEED); } + /*------------------------------------------------------------------------- * Function: H5B_insert_helper @@ -985,6 +1028,7 @@ H5B_insert_child (H5F_t *f, const H5B_class_t *type, H5B_t *bt, */ static haddr_t H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type, + H5B_ins_t *parent_ins, uint8 *lt_key, hbool_t *lt_key_changed, uint8 *md_key, void *udata, uint8 *rt_key, hbool_t *rt_key_changed) @@ -992,7 +1036,7 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type, H5B_t *bt=NULL, *twin=NULL, *tmp_bt=NULL; intn lt=0, idx=-1, rt, cmp=-1; haddr_t child_addr=0, twin_addr=0, ret_value=FAIL; - intn anchor; + H5B_ins_t my_ins = H5B_INS_ERROR; FUNC_ENTER (H5B_insert_helper, NULL, FAIL); @@ -1005,35 +1049,30 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type, assert (type->decode); assert (type->cmp); assert (type->new); + assert (parent_ins && H5B_INS_ERROR==*parent_ins); assert (lt_key); assert (lt_key_changed); assert (rt_key); assert (rt_key_changed); + *lt_key_changed = FALSE; + *rt_key_changed = FALSE; + /* * Use a binary search to find the child that will receive the new * data. When the search completes IDX points to the child that * should get the new data. */ - if (NULL==(bt=H5AC_protect (f, H5AC_BT, addr, type))) { + if (NULL==(bt=H5AC_protect (f, H5AC_BT, addr, type, udata))) { HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); } rt = bt->nchildren; while (lt<rt && cmp) { idx = (lt + rt) / 2; - - /* left key */ - if (!bt->key[idx].nkey && H5B_decode_key (f, bt, idx)<0) { - HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); - } - - /* right key */ - if (!bt->key[idx+1].nkey && H5B_decode_key (f, bt, idx+1)<0) { - HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); + if (H5B_decode_keys (f, bt, idx)<0) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); } - - /* compare */ if ((cmp=(type->cmp)(f, bt->key[idx].nkey, udata, bt->key[idx+1].nkey))<0) { rt = idx; @@ -1042,46 +1081,14 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type, } } - if (cmp<0 && idx<=0) { - /* - * Boundary condition: the value to insert is the new minimum - * value in the B-tree. Insert the value in the left-most node. - */ - idx = 0; - cmp = 0; - - } else if (cmp>0 && idx+1>=bt->nchildren) { + if (0==bt->nchildren) { /* - * Boundary condition: the value to insert is the new maximum - * value in the B-tree. Insert the value in the right-most node. + * The value being inserted will be the only value in this tree. We + * must necessarily be at level zero. */ - idx = bt->nchildren-1; - cmp = 0; - } - assert (0==cmp); - - /* - * Ensure that both native keys exist since we may have made boundary - * condition adjustments. - */ - if (bt->nchildren) { - if (!bt->key[idx].nkey && H5B_decode_key (f, bt, idx)<0) { - HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); - } - if (!bt->key[idx+1].nkey && H5B_decode_key (f, bt, idx+1)<0) { - HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); - } - } - - /* - * If there are no children, then create a new child. This can only - * happen at the root of the B-tree. The left and right native keys - * are output values from the node creation function. - */ - if (0==bt->nchildren) { + assert (0==bt->level); bt->key[0].nkey = bt->native; bt->key[1].nkey = bt->native + type->sizeof_nkey; - if ((child_addr=(type->new)(f, bt->key[0].nkey, udata, bt->key[1].nkey))<0) { bt->key[0].nkey = bt->key[1].nkey = NULL; @@ -1091,28 +1098,142 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type, bt->dirty = TRUE; bt->ndirty = 1; bt->child[0] = child_addr; - bt->key[0].dirty = TRUE; bt->key[1].dirty = TRUE; idx = 0; - } - /* - * Insert the new data in the child B-tree node or in the data node. - */ - if (bt->level > 0) { - child_addr = H5B_insert_helper (f, bt->child[idx], type, + if (type->follow_min) { + child_addr = (type->insert)(f, bt->child[idx], &my_ins, + bt->key[idx].nkey, lt_key_changed, + md_key, udata, + bt->key[idx+1].nkey, rt_key_changed); + } else { + my_ins = H5B_INS_NOOP; + } + + } else if (cmp<0 && idx<=0 && bt->level>0) { + /* + * The value being inserted is less than any value in this tree. Follow + * the minimum branch out of this node to a subtree. + */ + idx = 0; + if (H5B_decode_keys (f, bt, idx)<0) { + HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); + } + child_addr = H5B_insert_helper (f, bt->child[idx], type, &my_ins, bt->key[idx].nkey, lt_key_changed, md_key, udata, bt->key[idx+1].nkey, rt_key_changed); - anchor = H5B_ANCHOR_LT; + + } else if (cmp<0 && idx<=0 && type->follow_min) { + /* + * The value being inserted is less than any leaf node out of this + * current node. Follow the minimum branch to a leaf node and let the + * subclass handle the problem. + */ + idx = 0; + if (H5B_decode_keys (f, bt, idx)<0) { + HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); + } + child_addr = (type->insert)(f, bt->child[idx], &my_ins, + bt->key[idx].nkey, lt_key_changed, + md_key, udata, + bt->key[idx+1].nkey, rt_key_changed); + + } else if (cmp<0 && idx<=0) { + /* + * The value being inserted is less than any leaf node out of the + * current node. Create a new minimum leaf node out of this B-tree + * node. This node is not empty (handled above). + */ + idx = 0; + if (H5B_decode_keys (f, bt, idx)<0) { + HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); + } + my_ins = H5B_INS_LEFT; + HDmemcpy (md_key, bt->key[idx].nkey, type->sizeof_nkey); + child_addr = (type->new)(f, bt->key[idx].nkey, udata, md_key); + *lt_key_changed = TRUE; + + } else if (cmp>0 && idx+1>=bt->nchildren && bt->level>0) { + /* + * The value being inserted is larger than any value in this tree. + * Follow the maximum branch out of this node to a subtree. + */ + idx = bt->nchildren - 1; + if (H5B_decode_keys (f, bt, idx)<0) { + HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); + } + child_addr = H5B_insert_helper (f, bt->child[idx], type, &my_ins, + bt->key[idx].nkey, lt_key_changed, + md_key, udata, + bt->key[idx+1].nkey, rt_key_changed); + + } else if (cmp>0 && idx+1>=bt->nchildren && type->follow_max) { + /* + * The value being inserted is larger than any leaf node out of the + * current node. Follow the maximum branch to a leaf node and let the + * subclass handle the problem. + */ + idx = bt->nchildren - 1; + if (H5B_decode_keys (f, bt, idx)<0) { + HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); + } + child_addr = (type->insert)(f, bt->child[idx], &my_ins, + bt->key[idx].nkey, lt_key_changed, + md_key, udata, + bt->key[idx+1].nkey, rt_key_changed); + + } else if (cmp>0 && idx+1>=bt->nchildren) { + /* + * The value being inserted is larger than any leaf node out of the + * current node. Create a new maximum leaf node out of this B-tree + * node. + */ + idx = bt->nchildren - 1; + if (H5B_decode_keys (f, bt, idx)<0) { + HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); + } + my_ins = H5B_INS_RIGHT; + HDmemcpy (md_key, bt->key[idx+1].nkey, type->sizeof_nkey); + child_addr = (type->new)(f, md_key, udata, bt->key[idx+1].nkey); + *rt_key_changed = TRUE; + + } else if (cmp) { + /* + * We couldn't figure out which branch to follow out of this node. THIS + * IS A MAJOR PROBLEM THAT NEEDS TO BE FIXED --rpm. + */ + assert ("INTERNAL HDF5 ERROR (see rpm)" && 0); + + } else if (bt->level>0) { + /* + * Follow a branch out of this node to another subtree. + */ + assert (idx>=0 && idx<bt->nchildren); + child_addr = H5B_insert_helper (f, bt->child[idx], type, &my_ins, + bt->key[idx].nkey, lt_key_changed, + md_key, udata, + bt->key[idx+1].nkey, rt_key_changed); + + } else { - child_addr = (type->insert)(f, bt->child[idx], &anchor, + /* + * Follow a branch out of this node to a leaf node of some other type. + */ + assert (idx>=0 && idx<bt->nchildren); + child_addr = (type->insert)(f, bt->child[idx], &my_ins, bt->key[idx].nkey, lt_key_changed, md_key, udata, bt->key[idx+1].nkey, rt_key_changed); + + } + + if (child_addr<0 || my_ins<0) { + /* Insertion failed */ + HGOTO_ERROR (H5E_BTREE, H5E_CANTINSERT, FAIL); } - if (child_addr<0) HGOTO_ERROR (H5E_BTREE, H5E_CANTINSERT, FAIL); + /* * Update the left and right keys of the current node. @@ -1136,36 +1257,43 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type, } } - /* - * Insert the child, splitting the current node if necessary. - */ - if (child_addr) { + if (H5B_INS_CHANGE==my_ins) { + /* + * The insertion simply changed the address for the child. + */ + bt->child[idx] = child_addr; + bt->dirty = TRUE; + bt->ndirty = MAX (bt->ndirty, idx+1); + *parent_ins = H5B_INS_NOOP; + + } else if (H5B_INS_LEFT==my_ins || H5B_INS_RIGHT==my_ins) { /* - * If the child split and the left node is anchored, then the new + * The child split. If the left node is anchored, then the new * child node gets inserted to the right of our current position. */ - if (H5B_ANCHOR_LT==anchor) idx++; + if (H5B_INS_RIGHT==my_ins) idx++; if (bt->nchildren==2*H5B_K(f,type)) { /* Split the current node */ - if ((twin_addr = H5B_split (f, type, bt, addr, anchor))<0) { + if ((twin_addr = H5B_split (f, type, bt, addr, my_ins, udata))<0) { HGOTO_ERROR (H5E_BTREE, H5E_CANTSPLIT, FAIL); } - if (NULL==(twin=H5AC_protect (f, H5AC_BT, twin_addr, type))) { + if (NULL==(twin=H5AC_protect (f, H5AC_BT, twin_addr, type, + udata))) { HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); } if (idx<=H5B_K(f,type)) { - tmp_bt = H5B_ANCHOR_LT==anchor ? bt : twin; + tmp_bt = H5B_INS_RIGHT==my_ins ? bt : twin; } else { idx -= H5B_K (f, type); - tmp_bt = H5B_ANCHOR_LT==anchor ? twin : bt; + tmp_bt = H5B_INS_RIGHT==my_ins ? twin : bt; } } else { tmp_bt = bt; } - if (H5B_insert_child (f, type, tmp_bt, idx, child_addr, anchor, + if (H5B_insert_child (f, type, tmp_bt, idx, child_addr, my_ins, md_key)<0) { HGOTO_ERROR (H5E_BTREE, H5E_CANTINSERT, FAIL); } @@ -1177,7 +1305,7 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type, * by the left and right node). */ if (twin) { - if (H5B_ANCHOR_LT==anchor) { + if (H5B_INS_RIGHT==my_ins) { if (!twin->key[0].nkey && H5B_decode_key (f, twin, 0)<0) { HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); } @@ -1188,7 +1316,11 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type, } HDmemcpy (md_key, bt->key[0].nkey, type->sizeof_nkey); } + *parent_ins = H5B_INS_RIGHT; + } else { + *parent_ins = H5B_INS_NOOP; } + HGOTO_DONE (twin_addr); done: @@ -1241,7 +1373,7 @@ H5B_list (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata) assert (addr>=0); assert (udata); - if (NULL==(bt = H5AC_find (f, H5AC_BT, addr, type))) { + if (NULL==(bt = H5AC_find (f, H5AC_BT, addr, type, udata))) { HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); } @@ -1254,7 +1386,7 @@ H5B_list (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata) } else { for (/*void*/; addr>0; addr=next_addr) { - if (NULL==(bt=H5AC_protect (f, H5AC_BT, addr, type))) { + if (NULL==(bt=H5AC_protect (f, H5AC_BT, addr, type, udata))) { HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); } @@ -1318,6 +1450,7 @@ H5B_nodesize (H5F_t *f, const H5B_class_t *type, assert (f); assert (type); assert (sizeof_rkey>0); + assert (H5B_K (f, type)>0); /* * Total native key size. @@ -1356,7 +1489,7 @@ H5B_nodesize (H5F_t *f, const H5B_class_t *type, */ herr_t H5B_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent, - intn fwidth, H5B_class_t *type) + intn fwidth, H5B_class_t *type, void *udata) { H5B_t *bt = NULL; int i; @@ -1376,7 +1509,7 @@ H5B_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent, /* * Load the tree node. */ - if (NULL==(bt=H5AC_find (f, H5AC_BT, addr, type))) { + if (NULL==(bt=H5AC_find (f, H5AC_BT, addr, type, udata))) { HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); } diff --git a/src/H5Bprivate.h b/src/H5Bprivate.h index 7814eeb..05e2e56 100644 --- a/src/H5Bprivate.h +++ b/src/H5Bprivate.h @@ -33,11 +33,17 @@ #define H5B_K(F,TYPE) /*K value given file and Btree subclass */ \ ((F)->shared->file_create_parms.btree_k[(TYPE)->id]) -#define H5B_ANCHOR_LT 0 /* left node is anchored, right is new */ -#define H5B_ANCHOR_RT 1 /* right node is anchored, left is new */ +typedef enum H5B_ins_t { + H5B_INS_ERROR =-1, /*error return value */ + H5B_INS_NOOP =0, /*insert made no changes */ + H5B_INS_LEFT =1, /*insert new node to left of cur node */ + H5B_INS_RIGHT =2, /*insert new node to right of cur node */ + H5B_INS_CHANGE =3 /*change child address for cur node */ +} H5B_ins_t; typedef enum H5B_subid_t { - H5B_SNODE_ID =0 /*B-tree is for symbol table nodes */ + H5B_SNODE_ID =0, /*B-tree is for symbol table nodes */ + H5B_ISTORE_ID =1 /*B-tree is for indexed object storage */ } H5B_subid_t; @@ -48,18 +54,21 @@ typedef enum H5B_subid_t { * has an array of K values indexed by the `id' class field below. The * array is initialized with the HDF5_BTREE_K_DEFAULT macro. */ +struct H5B_t; /*forward decl*/ typedef struct H5B_class_t { H5B_subid_t id; /*id as found in file */ size_t sizeof_nkey; /*size of native (memory) key */ - size_t (*get_sizeof_rkey)(H5F_t*); - haddr_t (*new)(H5F_t*,void*,void*,void*); - intn (*cmp)(H5F_t*,void*,void*,void*); + size_t (*get_sizeof_rkey)(H5F_t*,const void*);/*raw key size */ + haddr_t (*new)(H5F_t*,void*,void*,void*); /*create new leaf */ + intn (*cmp)(H5F_t*,void*,void*,void*); /*compare keys */ herr_t (*found)(H5F_t*,haddr_t,const void*,void*,const void*); - haddr_t (*insert)(H5F_t*,haddr_t,int*,void*,hbool_t*,void*,void*, - void*,hbool_t*); - herr_t (*list)(H5F_t*,haddr_t,void*); - herr_t (*decode)(H5F_t*,uint8*,void*); - herr_t (*encode)(H5F_t*,uint8*,void*); + haddr_t (*insert)(H5F_t*,haddr_t,H5B_ins_t*,void*,hbool_t*,void*,void*, + void*,hbool_t*); /*insert new data */ + hbool_t follow_min; /*min insert uses min leaf, not new() */ + hbool_t follow_max; /*max insert uses max leaf, not new() */ + herr_t (*list)(H5F_t*,haddr_t,void*); /*traverse leaf nodes */ + herr_t (*decode)(H5F_t*,struct H5B_t*,uint8*,void*); + herr_t (*encode)(H5F_t*,struct H5B_t*,uint8*,void*); } H5B_class_t; /* @@ -91,8 +100,8 @@ typedef struct H5B_t { * Library prototypes. */ herr_t H5B_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent, - intn fwidth, H5B_class_t *type); -haddr_t H5B_new (H5F_t *f, const H5B_class_t *type); + intn fwidth, H5B_class_t *type, void *udata); +haddr_t H5B_new (H5F_t *f, const H5B_class_t *type, void *udata); herr_t H5B_find (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata); haddr_t H5B_insert (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata); herr_t H5B_list (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata); @@ -146,7 +146,7 @@ hid_t H5C_get_default_atom(hobjtype_t type) case H5_TEMPLATE: if(default_file_id==FAIL) { - if((default_file_id=H5Aregister_atom(H5_TEMPLATE, (const VOIDP)&default_file_create))==FAIL) + if((default_file_id=H5Aregister_atom(H5_TEMPLATE, (const void *)&default_file_create))==FAIL) HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL); } /* end else */ HGOTO_DONE(default_file_id); @@ -324,6 +324,9 @@ done: Robb Matzke, 13 Aug 1997 Removed H5_BTREE_SIZE and replaced it with H5_SYM_LEAF_K and H5_SYM_INTERN_K. + + Robb Matzke, 17 Oct 1997 + Added H5_ISTORE_K. --------------------------------------------------------------------------*/ herr_t H5Cgetparm(hid_t tid, file_create_param_t parm, VOIDP buf) { @@ -365,6 +368,10 @@ herr_t H5Cgetparm(hid_t tid, file_create_param_t parm, VOIDP buf) *(uintn *)buf = template->btree_k[H5B_SNODE_ID]; break; + case H5_ISTORE_K: + *(uintn *)buf = template->btree_k[H5B_ISTORE_ID]; + break; + case H5_BOOTBLOCK_VER: *(uint8 *)buf=template->bootblock_ver; break; @@ -430,6 +437,9 @@ done: Robb Matzke, 15 Sep 1997 Fixed the power-of-two test to work with any size integer. + + Robb Matzke, 17 Oct 1997 + Added H5_ISTORE_K. --------------------------------------------------------------------------*/ herr_t H5Csetparm(hid_t tid, file_create_param_t parm, const VOIDP buf) { @@ -494,6 +504,14 @@ herr_t H5Csetparm(hid_t tid, file_create_param_t parm, const VOIDP buf) } template->btree_k[H5B_SNODE_ID] = val; break; + + case H5_ISTORE_K: + val = *(const uintn *)buf; + if (val<2) { + HGOTO_ERROR (H5E_ARGS, H5E_BADRANGE, FAIL); + } + template->btree_k[H5B_ISTORE_ID] = val; + break; case H5_BOOTBLOCK_VER: /* this should be range checked */ template->bootblock_ver=*(const uint8 *)buf; diff --git a/src/H5Cprivate.h b/src/H5Cprivate.h index 675fba6..168b253 100644 --- a/src/H5Cprivate.h +++ b/src/H5Cprivate.h @@ -34,7 +34,7 @@ #define H5C_BTREE_K_DEFAULT { \ 16, /* Symbol table internal nodes */ \ - 0, /* unused */ \ + 32, /* Indexed storage intern nodes */ \ 0, /* unused */ \ 0, /* unused */ \ 0, /* unused */ \ diff --git a/src/H5Cpublic.h b/src/H5Cpublic.h index 08e7656..4d2fd7d 100644 --- a/src/H5Cpublic.h +++ b/src/H5Cpublic.h @@ -37,6 +37,7 @@ typedef enum { H5_LENGTH_SIZE, /* (uint8) Number of bytes for lengths */ H5_SYM_LEAF_K, /* (uintn) 1/2 rank for symbol table leaf nodes */ H5_SYM_INTERN_K, /* (uintn) 1/2 rank for symbol table internal nodes */ + H5_ISTORE_K, /* (uintn) 1/2 rank for indexed storage nodes */ H5_BOOTBLOCK_VER, /* (uint8) Version # of the boot-block format */ H5_SMALLOBJECT_VER, /* (uint8) Version # of the small-object heap format */ H5_FREESPACE_VER, /* (uint8) Version # of the free-space info format */ @@ -158,7 +158,7 @@ hid_t H5D_create(hid_t owner_id, hobjtype_t type, const char *name) /* Open (and create) a new file object */ if (NULL==(new_dset->ent = H5G_create (file, name, H5D_MINHDR_SIZE))) { - HGOTO_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL); + HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); } /* Register the new datatype and get an ID for it */ @@ -183,14 +183,14 @@ done: Get the OID for accessing an existing HDF5 dataset object USAGE hoid_t H5D_find_name(grp_id, type, name) - hid_t grp_id; IN: Atom for directory to search for dataset + hid_t grp_id; IN: Atom for group to search for dataset hobjtype_t type; IN: Type of object to search for (dataset in this case) const char *name; IN: Name of the object to search for RETURNS Returns ID (atom) on success, FAIL on failure DESCRIPTION - This function finds for a dataset by name in a directory. + This function finds for a dataset by name in a group. --------------------------------------------------------------------------*/ hid_t H5D_find_name(hid_t grp_id, hobjtype_t obj_type, const char *name) { @@ -215,7 +215,7 @@ hid_t H5D_find_name(hid_t grp_id, hobjtype_t obj_type, const char *name) if(NULL==(dset=HDcalloc(1, sizeof(H5D_t)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL); - /* Initialize file, directory, name fields */ + /* Initialize file, group, name fields */ dset->file = file; dset->dirty = FALSE; diff --git a/src/H5Distore.c b/src/H5Distore.c new file mode 100644 index 0000000..b52288c --- /dev/null +++ b/src/H5Distore.c @@ -0,0 +1,740 @@ +/* + * Copyright (C) 1997 Spizella Software + * All rights reserved. + * + * Programmer: Robb Matzke <robb@arborea.spizella.com> + * Wednesday, October 8, 1997 + */ +#include <H5private.h> +#include <H5Eprivate.h> +#include <H5Fprivate.h> +#include <H5MFprivate.h> +#include <H5MMprivate.h> +#include <H5Oprivate.h> +#include <H5Vprivate.h> + +typedef enum H5F_isop_t { + H5F_ISTORE_READ, /*read from file to memory */ + H5F_ISTORE_WRITE /*write from memory to file */ +} H5F_isop_t; + +/* Does the array domain include negative indices? */ +#undef H5F_ISTORE_NEGATIVE_DOMAIN + + +#define PABLO_MASK H5F_istore_mask + +/* Is the interface initialized? */ +static hbool_t interface_initialize_g = FALSE; + +/* PRIVATE PROTOTYPES */ +static size_t H5F_istore_sizeof_rkey (H5F_t *f, const void *_udata); +static haddr_t H5F_istore_new (H5F_t *f, void *_lt_key, void *_udata, + void *_rt_key); +static intn H5F_istore_cmp (H5F_t *f, void *_lt_key, void *_udata, + void *_rt_key); +static herr_t H5F_istore_found (H5F_t *f, haddr_t addr, const void *_lt_key, + void *_udata, const void *_rt_key); +static haddr_t H5F_istore_insert (H5F_t *f, haddr_t addr, H5B_ins_t *anchor, + void *_lt_key, hbool_t *lt_key_changed, + void *_md_key, void *_udata, + void *_rt_key, hbool_t *rt_key_changed); +static herr_t H5F_istore_decode_key (H5F_t *f, H5B_t *bt, uint8 *raw, + void *_key); +static herr_t H5F_istore_encode_key (H5F_t *f, H5B_t *bt, uint8 *raw, + void *_key); +static herr_t H5F_istore_copy_hyperslab (H5F_t *f, H5O_istore_t *istore, + H5F_isop_t op, size_t offset_f[], + size_t size[], size_t offset_m[], + size_t size_m[], void *buf); + + +/* + * B-tree key. A key contains the minimum logical N-dimensional address and + * the logical size of the chunk to which this key refers. The + * fastest-varying dimension is assumed to reference individual bytes of the + * array, so a 100-element 1-d array of 4-byte integers would really be a 2-d + * array with the slow varying dimension of size 100 and the fast varying + * dimension of size 4 (the storage dimensionality has very little to do with + * the real dimensionality). + * + * Only the first few values of the OFFSET and SIZE fields are actually + * stored on disk, depending on the dimensionality. + * + * The storage file address is part of the B-tree and not part of the key. + */ +typedef struct H5F_istore_key_t { + size_t offset[H5O_ISTORE_NDIMS]; /*logical offset to start*/ + size_t size[H5O_ISTORE_NDIMS]; /*logical chunk size */ +} H5F_istore_key_t; + +typedef struct H5F_istore_ud1_t { + H5F_istore_key_t key; /*key values */ + haddr_t addr; /*file address of chunk */ + H5O_istore_t mesg; /*storage message */ +} H5F_istore_ud1_t; + +/* inherits B-tree like properties from H5B */ +H5B_class_t H5B_ISTORE[1] = {{ + H5B_ISTORE_ID, /*id */ + sizeof (H5F_istore_key_t), /*sizeof_nkey */ + H5F_istore_sizeof_rkey, /*get_sizeof_rkey */ + H5F_istore_new, /*new */ + H5F_istore_cmp, /*cmp */ + H5F_istore_found, /*found */ + H5F_istore_insert, /*insert */ + FALSE, /*follow min branch? */ + FALSE, /*follow max branch? */ + NULL, /*list */ + H5F_istore_decode_key, /*decode */ + H5F_istore_encode_key, /*encode */ +}}; + + + +/*------------------------------------------------------------------------- + * Function: H5F_istore_sizeof_rkey + * + * Purpose: Returns the size of a raw key for the specified UDATA. The + * size of the key is dependent on the number of dimensions for + * the object to which this B-tree points. The dimensionality + * of the UDATA is the only portion that's referenced here. + * + * Return: Success: Size of raw key in bytes. + * + * Failure: abort() + * + * Programmer: Robb Matzke + * Wednesday, October 8, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static size_t +H5F_istore_sizeof_rkey (H5F_t *f, const void *_udata) +{ + const H5F_istore_ud1_t *udata = (const H5F_istore_ud1_t *)_udata; + + assert (udata); + assert (udata->mesg.ndims>0 && udata->mesg.ndims<=H5O_ISTORE_NDIMS); + + return udata->mesg.ndims * (4 + 4); +} + + + +/*------------------------------------------------------------------------- + * Function: H5F_istore_decode_key + * + * Purpose: Decodes a raw key into a native key for the B-tree + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Friday, October 10, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5F_istore_decode_key (H5F_t *f, H5B_t *bt, uint8 *raw, void *_key) +{ + H5F_istore_key_t *key = (H5F_istore_key_t *)_key; + int i; + int ndims = bt->sizeof_rkey / 8; + + FUNC_ENTER (H5F_istore_decode_key, NULL, FAIL); + + /* check args */ + assert (f); + assert (bt); + assert (raw); + assert (key); + assert (ndims>0 && ndims<=H5O_ISTORE_NDIMS && 8*ndims==bt->sizeof_rkey); + + /* decode */ + for (i=0; i<ndims; i++) { + UINT32DECODE (raw, key->offset[i]); + UINT32DECODE (raw, key->size[i]); + } + + FUNC_LEAVE (SUCCEED); + +} + + +/*------------------------------------------------------------------------- + * Function: H5F_istore_encode_key + * + * Purpose: Encode a key from native format to raw format. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Friday, October 10, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5F_istore_encode_key (H5F_t *f, H5B_t *bt, uint8 *raw, void *_key) +{ + H5F_istore_key_t *key = (H5F_istore_key_t *)_key; + intn ndims = bt->sizeof_rkey / 8; + intn i; + + FUNC_ENTER (H5F_istore_encode_key, NULL, FAIL); + + /* check args */ + assert (f); + assert (bt); + assert (raw); + assert (key); + assert (ndims>0 && ndims<=H5O_ISTORE_NDIMS && 8*ndims==bt->sizeof_rkey); + + /* encode */ + for (i=0; i<ndims; i++) { + UINT32ENCODE (raw, key->offset[i]); + UINT32ENCODE (raw, key->size[i]); + } + + FUNC_LEAVE (SUCCEED); +} + + +/*------------------------------------------------------------------------- + * Function: H5F_istore_cmp + * + * Purpose: Compare the requested datum UDATA with the left and right + * keys of the B-tree. + * + * Return: Success: negative if the min_corner of UDATA is less + * than the min_corner of LT_KEY. + * + * positive if the min_corner of UDATA is + * greater than or equal the min_corner of + * RT_KEY. + * + * zero otherwise. The min_corner of UDATA is + * not necessarily contained within the address + * space represented by LT_KEY, but a key that + * would describe the UDATA min_corner address + * would fall lexicographically between LT_KEY + * and RT_KEY. + * + * Failure: FAIL (same as UDATA < LT_KEY) + * + * Programmer: Robb Matzke + * Wednesday, October 8, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static intn +H5F_istore_cmp (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key) +{ + H5F_istore_key_t *lt_key = (H5F_istore_key_t *)_lt_key; + H5F_istore_key_t *rt_key = (H5F_istore_key_t *)_rt_key; + H5F_istore_ud1_t *udata = (H5F_istore_ud1_t *)_udata; + + assert (lt_key); + assert (rt_key); + assert (udata); + assert (udata->mesg.ndims>0 && udata->mesg.ndims<=H5O_ISTORE_NDIMS); + + if (H5V_vector_lt (udata->mesg.ndims, udata->key.offset, lt_key->offset)) { + return -1; + } else if (H5V_vector_ge (udata->mesg.ndims, udata->key.offset, + rt_key->offset)) { + return 1; + } else { + return 0; + } +} + + +/*------------------------------------------------------------------------- + * Function: H5F_istore_new + * + * Purpose: Adds a new entry to an i-storage B-tree. We can assume that + * the domain represented by UDATA doesn't intersect the domain + * already represented by the B-tree. + * + * Return: Success: Address of leaf, which is passed in from the + * UDATA pointer. + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Tuesday, October 14, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static haddr_t +H5F_istore_new (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key) +{ + H5F_istore_key_t *lt_key = (H5F_istore_key_t *)_lt_key; + H5F_istore_key_t *rt_key = (H5F_istore_key_t *)_rt_key; + H5F_istore_ud1_t *udata = (H5F_istore_ud1_t *)_udata; + size_t nbytes; + intn i; + + FUNC_ENTER (H5F_istore_new, NULL, FAIL); + + /* check args */ + assert (f); + assert (lt_key); + assert (rt_key); + assert (udata); + assert (udata->mesg.ndims>=0 && udata->mesg.ndims<H5O_ISTORE_NDIMS); + + /* Allocate new storage */ + nbytes = H5V_vector_reduce_product (udata->mesg.ndims, udata->key.size); + assert (nbytes>0); + if ((udata->addr=H5MF_alloc (f, nbytes))<0) { + /* Couldn't allocate new file storage */ + HRETURN_ERROR (H5E_IO, H5E_CANTINIT, FAIL); + } + + /* left key describes the UDATA, right key is a zero-size "edge" */ + for (i=0; i<udata->mesg.ndims; i++) { + lt_key->offset[i] = udata->key.offset[i]; + lt_key->size[i] = udata->key.size[i]; + assert (udata->key.size[i]>0); + + rt_key->offset[i] = udata->key.offset[i] + udata->key.size[i]; + rt_key->size[i] = 0; + } + + + FUNC_LEAVE (udata->addr); +} + + +/*------------------------------------------------------------------------- + * Function: H5F_istore_found + * + * Purpose: This function is called when the B-tree search engine has + * found the leaf entry that points to a chunk of storage that + * contains the beginning of the logical address space + * represented by UDATA. The LT_KEY is the left key (the one + * that describes the chunk) and RT_KEY is the right key (the + * one that describes the next or last chunk). + * + * Return: Success: SUCCEED with information about the chunk + * returned through the UDATA argument. + * + * Failure: FAIL if not found. + * + * Programmer: Robb Matzke + * Thursday, October 9, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5F_istore_found (H5F_t *f, haddr_t addr, const void *_lt_key, + void *_udata, const void *_rt_key) +{ + H5F_istore_ud1_t *udata = (H5F_istore_ud1_t *)_udata; + const H5F_istore_key_t *lt_key = (const H5F_istore_key_t *)_lt_key; + const H5F_istore_key_t *rt_key = (const H5F_istore_key_t *)_rt_key; + int i; + + FUNC_ENTER (H5F_istore_found, NULL, FAIL); + + /* Check arguments */ + assert (f); + assert (addr>=0); + assert (udata); + assert (lt_key); + assert (rt_key); + + /* Initialize return values */ + udata->addr = addr; + for (i=0; i<udata->mesg.ndims; i++) { + udata->key.offset[i] = lt_key->offset[i]; + udata->key.size[i] = lt_key->size[i]; + assert (lt_key->size[i]>0); + } + + FUNC_LEAVE (SUCCEED); +} + + + +/*------------------------------------------------------------------------- + * Function: H5F_istore_insert + * + * Purpose: This function is called when the B-tree insert engine finds + * the node to use to insert new data. The UDATA argument + * points to a struct that describes the logical addresses being + * added to the file. This function allocates space for the + * data and returns information through UDATA describing a + * file chunk to receive (part of) the data. + * + * The LT_KEY is always the key describing the chunk of file + * memory at address ADDR. On entry, UDATA describes the logical + * addresses for which storage is being requested (through the + * `offset' and `size' fields). On return, UDATA describes the + * logical addresses contained in a chunk on disk. + * + * Return: Success: SUCCEED, with UDATA containing information + * about the (newly allocated) chunk. + * + * If the storage address has changed then the + * new address is returned. + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Thursday, October 9, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static haddr_t +H5F_istore_insert (H5F_t *f, haddr_t addr, H5B_ins_t *parent_ins, + void *_lt_key, hbool_t *lt_key_changed, + void *_md_key, void *_udata, + void *_rt_key, hbool_t *rt_key_changed) +{ + H5F_istore_key_t *lt_key = (H5F_istore_key_t *)_lt_key; + H5F_istore_key_t *md_key = (H5F_istore_key_t *)_md_key; + H5F_istore_key_t *rt_key = (H5F_istore_key_t *)_rt_key; + H5F_istore_ud1_t *udata = (H5F_istore_ud1_t *)_udata; + intn i, cmp; + haddr_t ret_value = 0; + size_t nbytes; + + FUNC_ENTER (H5F_istore_insert, NULL, FAIL); + + /* check args */ + assert (f); + assert (addr>=0); + assert (parent_ins); + assert (lt_key); + assert (lt_key_changed); + assert (md_key); + assert (udata); + assert (rt_key); + assert (rt_key_changed); + + cmp = H5F_istore_cmp (f, lt_key, udata, rt_key); + assert (cmp<=0); + + if (cmp<0) { + /* Negative indices not supported yet */ + assert ("HDF5 INTERNAL ERROR -- see rpm" && 0); + HRETURN_ERROR (H5E_STORAGE, H5E_UNSUPPORTED, FAIL); + + } else if (H5V_hyper_eq (udata->mesg.ndims, + udata->key.offset, udata->key.size, + lt_key->offset, lt_key->size)) { + /* + * Already exists. Just return the info. + */ + udata->addr = addr; + *parent_ins = H5B_INS_NOOP; + + } else if (H5V_hyper_disjointp (udata->mesg.ndims, + lt_key->offset, lt_key->size, + udata->key.offset, udata->key.size)) { + assert (H5V_hyper_disjointp (udata->mesg.ndims, + rt_key->offset, rt_key->size, + udata->key.offset, udata->key.size)); + + /* + * Split this node, inserting the new new node to the right of the + * current node. The MD_KEY is where the split occurs. + */ + for (i=0, nbytes=1; i<udata->mesg.ndims; i++) { + assert (0==udata->key.offset[i] % udata->mesg.alignment[i]); + assert (udata->key.size[i] == udata->mesg.alignment[i]); + md_key->offset[i] = udata->key.offset[i]; + md_key->size[i] = udata->key.size[i]; + nbytes *= udata->key.size[i]; + } + + /* + * Allocate storage for the new chunk + */ + if ((udata->addr=ret_value=H5MF_alloc (f, nbytes))<=0) { + HRETURN_ERROR (H5E_IO, H5E_CANTINIT, FAIL); + } + + *parent_ins = H5B_INS_RIGHT; + + } else { + assert ("HDF5 INTERNAL ERROR -- see rpm" && 0); + HRETURN_ERROR (H5E_IO, H5E_UNSUPPORTED, FAIL); + } + + FUNC_LEAVE (ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5F_istore_copy_hyperslab + * + * Purpose: Reads or writes a hyperslab to disk depending on whether OP + * is H5F_ISTORE_READ or H5F_ISTORE_WRITE. The hyperslab + * storage is described with ISTORE and exists in file F. The + * file hyperslab begins at location OFFSET_F[] (an N-dimensional + * point in the domain in terms of elements) in the file and + * OFFSET_M[] in memory pointed to by BUF. Its size is SIZE[] + * elements. The dimensionality of memory is assumed to be the + * same as the file and the total size of the multi-dimensional + * memory buffer is SIZE_M[]. + * + * The slowest varying dimension is always listed first in the + * various offset and size arrays. + * + * A `chunk' is a hyperslab of the disk array which is stored + * contiguously. I/O occurs in units of chunks where the size of + * a chunk is determined by the alignment constraints specified + * in ISTORE. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Friday, October 17, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5F_istore_copy_hyperslab (H5F_t *f, H5O_istore_t *istore, H5F_isop_t op, + size_t offset_f[], size_t size[], + size_t offset_m[], size_t size_m[], void *buf) +{ + intn i, carry; + size_t idx_cur[H5O_ISTORE_NDIMS]; + size_t idx_min[H5O_ISTORE_NDIMS]; + size_t idx_max[H5O_ISTORE_NDIMS]; + size_t sub_size[H5O_ISTORE_NDIMS]; + size_t sub_offset_f[H5O_ISTORE_NDIMS]; + size_t sub_offset_m[H5O_ISTORE_NDIMS]; + size_t sub_offset_ch[H5O_ISTORE_NDIMS]; + size_t chunk_size; + uint8 *chunk=NULL; + H5F_istore_ud1_t udata; + herr_t status; + herr_t ret_value = FAIL; + + FUNC_ENTER (H5F_istore_copy_hyperslab, NULL, FAIL); + + /* check args */ + assert (f); + assert (istore); + assert (istore->ndims>0 && istore->ndims<=H5O_ISTORE_NDIMS); + assert (H5F_ISTORE_READ==op || H5F_ISTORE_WRITE==op); + assert (size); + assert (size_m); + assert (buf); +#ifndef NDEBUG + for (i=0; i<istore->ndims; i++) { + assert (!offset_f || offset_f[i]>=0);/*neg domains unsupported */ + assert (!offset_m || offset_m[i]>=0);/*mem array offset never neg */ + assert (size[i]>=0); /*size may be zero, implies no-op */ + assert (size_m[i]>0); /*destination must exist */ + /*hyperslab must fit in BUF*/ + assert ((offset_m?offset_m[i]:0)+size[i]<=size_m[i]); + assert (istore->alignment[i]>0); + } +#endif + + /* + * Does the B-tree exist? + */ + if (istore->btree_addr<=0) { + if (H5F_ISTORE_WRITE==op) { + udata.mesg.ndims = istore->ndims; + if ((istore->btree_addr=H5B_new (f, H5B_ISTORE, &udata))<0) { + /* Can't create B-tree */ + HGOTO_ERROR (H5E_IO, H5E_CANTINIT, FAIL); + } + } else { + H5V_hyper_fill (istore->ndims, size, size_m, offset_m, buf, 0); + HRETURN (SUCCEED); + } + } + + /* Initialize indices */ + for (i=0; i<istore->ndims; i++) { + idx_min[i] = (offset_f?offset_f[i]:0) / istore->alignment[i]; + idx_max[i] = ((offset_f?offset_f[i]:0)+size[i]-1)/istore->alignment[i]+1; + idx_cur[i] = idx_min[i]; + } + + /* Allocate buffers */ + for (i=0, chunk_size=1; i<istore->ndims; i++) { + chunk_size *= istore->alignment[i]; + } + chunk = H5MM_xmalloc (chunk_size); + + /* Initialize non-changing part of udata */ + udata.mesg = *istore; + + /* Loop over all chunks */ + while (1) { + + /* Read/Write chunk or create it if it doesn't exist */ + udata.mesg.ndims = istore->ndims; + for (i=0; i<istore->ndims; i++) { + udata.key.offset[i] = idx_cur[i] * istore->alignment[i]; + udata.key.size[i] = istore->alignment[i]; + sub_offset_f[i] = MAX ((offset_f?offset_f[i]:0), udata.key.offset[i]); + sub_offset_m[i] = (offset_m?offset_m[i]:0) + + sub_offset_f[i] - (offset_f?offset_f[i]:0); + sub_size[i] = (idx_cur[i]+1)*istore->alignment[i]-sub_offset_f[i]; + sub_offset_ch[i] = sub_offset_f[i] - udata.key.offset[i]; + } + if (H5F_ISTORE_WRITE==op) { + status = H5B_insert (f, H5B_ISTORE, istore->btree_addr, &udata); + assert (status>=0); + } else { + status = H5B_find (f, H5B_ISTORE, istore->btree_addr, &udata); + } + + /* + * If the operation is reading from the disk or if we are writing a + * partial chunk then load the chunk from disk. + */ + if (H5F_ISTORE_READ==op || + !H5V_hyper_eq (istore->ndims, + udata.key.offset, udata.key.size, + sub_offset_f, sub_size)) { + if (status>=0) { + if (H5F_block_read (f, udata.addr, chunk_size, chunk)<0) { + HGOTO_ERROR (H5E_IO, H5E_READERROR, FAIL); + } + } else { + HDmemset (chunk, 0, chunk_size); + } + } + + /* Transfer data to/from the chunk */ + if (H5F_ISTORE_WRITE==op) { + H5V_hyper_copy (istore->ndims, sub_size, + udata.key.size, sub_offset_ch, chunk, + size_m, sub_offset_m, buf); + if (H5F_block_write (f, udata.addr, chunk_size, chunk)<0) { + HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL); + } + } else { + H5V_hyper_copy (istore->ndims, sub_size, + size_m, sub_offset_m, buf, + udata.key.size, sub_offset_ch, chunk); + } + + /* Increment indices */ + for (i=istore->ndims-1, carry=1; i>=0 && carry; --i) { + if (++idx_cur[i]>=idx_max[i]) idx_cur[i] = idx_min[i]; + else carry = 0; + } + if (carry) break; + } + ret_value = SUCCEED; + + + done: + chunk = H5MM_xfree (chunk); + FUNC_LEAVE (ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5F_istore_read + * + * Purpose: Reads a multi-dimensional buffer from (part of) an indexed raw + * storage array. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Wednesday, October 15, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_istore_read (H5F_t *f, struct H5O_istore_t *istore, + size_t offset[], size_t size[], void *buf) +{ + FUNC_ENTER (H5F_istore_read, NULL, FAIL); + + /* Check args */ + assert (f); + assert (istore); + assert (istore->ndims>0 && istore->ndims<=H5O_ISTORE_NDIMS); + assert (size); + assert (buf); + + if (H5F_istore_copy_hyperslab (f, istore, H5F_ISTORE_READ, + offset, size, H5V_ZERO, size, buf)<0) { + /* hyperslab output failure */ + HRETURN_ERROR (H5E_IO, H5E_READERROR, FAIL); + } + + FUNC_LEAVE (SUCCEED); +} + + +/*------------------------------------------------------------------------- + * Function: H5F_istore_write + * + * Purpose: Writes a multi-dimensional buffer to (part of) an indexed raw + * storage array. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Wednesday, October 15, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_istore_write (H5F_t *f, struct H5O_istore_t *istore, + size_t offset[], size_t size[], void *buf) +{ + FUNC_ENTER (H5F_istore_write, NULL, FAIL); + + /* Check args */ + assert (f); + assert (istore); + assert (istore->ndims>0 && istore->ndims<=H5O_ISTORE_NDIMS); + assert (size); + assert (buf); + + if (H5F_istore_copy_hyperslab (f, istore, H5F_ISTORE_WRITE, + offset, size, H5V_ZERO, size, buf)<0) { + /* hyperslab output failure */ + HRETURN_ERROR (H5E_IO, H5E_WRITEERROR, FAIL); + } + + FUNC_LEAVE (SUCCEED); +} + @@ -59,10 +59,10 @@ static const hdf_maj_error_messages_t hdf_maj_error_messages[] = {H5E_SYM, "Symbol Table"}, {H5E_HEAP, "Heap"}, {H5E_OHDR, "Object Header"}, - {H5E_DIRECTORY, "Directory"}, {H5E_DATATYPE, "Datatype"}, {H5E_DATASPACE, "Dataspace"}, - {H5E_DATASET, "Dataset"} + {H5E_DATASET, "Dataset"}, + {H5E_STORAGE, "Data Storage"}, }; static const hdf_min_error_messages_t hdf_min_error_messages[] = @@ -104,6 +104,7 @@ static const hdf_min_error_messages_t hdf_min_error_messages[] = {H5E_ALIGNMENT, "Alignment error"}, {H5E_BADMESG, "Unrecognized message"}, {H5E_COMPLEN, "Name component is too long"}, + {H5E_CWG, "Problem with current working group"}, {H5E_LINK, "Link count failure"}, }; diff --git a/src/H5Epublic.h b/src/H5Epublic.h index bde74e5..abb6e3c 100644 --- a/src/H5Epublic.h +++ b/src/H5Epublic.h @@ -38,10 +38,10 @@ typedef enum H5E_SYM, /* Symbol Table */ H5E_HEAP, /* Heap */ H5E_OHDR, /* Object Header */ - H5E_DIRECTORY, /* Directory */ H5E_DATATYPE, /* Datatype */ - H5E_DATASPACE, /* Dataspace */ - H5E_DATASET /* Dataset */ + H5E_DATASPACE, /* Dataspace */ + H5E_DATASET, /* Dataset */ + H5E_STORAGE /* Data storage */ } hdf_maj_err_code_t; @@ -102,9 +102,10 @@ typedef enum H5E_ALIGNMENT, /* Alignment error */ H5E_BADMESG, /* Unrecognized message */ - /* Directory related errors */ + /* Group related errors */ H5E_CANTOPENOBJ, /* Can't open object */ H5E_COMPLEN, /* Name component is too long */ + H5E_CWG, /* Problem with current working group */ H5E_LINK /* Link count failure */ } hdf_min_err_code_t; @@ -69,7 +69,6 @@ static herr_t H5F_init_interface(void); static H5F_t *H5F_new (H5F_file_t *shared); static H5F_t *H5F_dest (H5F_t *f); static herr_t H5F_flush (H5F_t *f, hbool_t invalidate); -static herr_t H5F_close (H5F_t *f); /*-------------------------------------------------------------------------- NAME @@ -500,7 +499,7 @@ H5F_dest (H5F_t *f) * block is written. This operation will fail * if the file is already open. * - * Unlinking the file name from the directory hierarchy while + * Unlinking the file name from the group directed graph while * the file is opened causes the file to continue to exist but * one will not be able to upgrade the file from read-only * access to read-write access by reopening it. Disk resources @@ -508,13 +507,20 @@ H5F_dest (H5F_t *f) * closed. NOTE: This paragraph probably only applies to Unix; * deleting the file name in other OS's has undefined results. * + * The CREATE_PARMS argument is optional. A null pointer will + * cause the default file creation parameters to be used. + * * Errors: + * ATOM BADATOM Can't unatomize default template + * id. * FILE BADVALUE Can't create file without write * intent. * FILE BADVALUE Can't truncate without write intent. * FILE CANTCREATE Can't create file. * FILE CANTCREATE Can't stat file. * FILE CANTCREATE Can't truncate file. + * FILE CANTINIT Can't get default file create template + * id. * FILE CANTINIT Can't write file boot block. * FILE CANTINIT Cannot determine file size. * FILE CANTOPENFILE Bad boot block version number. @@ -550,7 +556,7 @@ H5F_dest (H5F_t *f) * *------------------------------------------------------------------------- */ -static H5F_t * +H5F_t * H5F_open (const char *name, uintn flags, const file_create_temp_t *create_parms) { @@ -573,6 +579,21 @@ H5F_open (const char *name, uintn flags, assert (name && *name); /* + * If no file creation parameters are supplied then use defaults. + */ + if (!create_parms) { + hid_t create_temp = H5C_get_default_atom (H5_TEMPLATE); + if (create_temp<0) { + /* Can't get default file create template id */ + HRETURN_ERROR (H5E_FILE, H5E_CANTINIT, NULL); + } + if (NULL==(create_parms=H5Aatom_object (create_temp))) { + /* Can't unatomize default template id */ + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, NULL); + } + } + + /* * Does the file exist? If so, get the device and i-node values so we can * compare them with other files already open. On Unix (and other systems * with hard or soft links) it doesn't work to compare files based only on @@ -984,11 +1005,6 @@ hid_t H5Fcreate(const char *filename, uintn flags, hid_t create_temp, hid_t H5Fopen(const char *filename, uintn flags, hid_t access_temp) { H5F_t *new_file=NULL; /* file struct for new file */ - hid_t create_temp; /* file-creation template ID */ - const file_create_temp_t *f_create_parms; /* pointer to the parameters - * to use when creating the - * file - */ hid_t ret_value = FAIL; FUNC_ENTER(H5Fopen, H5F_init_interface, FAIL); @@ -999,10 +1015,6 @@ hid_t H5Fopen(const char *filename, uintn flags, hid_t access_temp) HGOTO_ERROR (H5E_ARGS, H5E_BADRANGE, FAIL);/*invalid file name*/ flags = flags & H5ACC_WRITE ? H5F_ACC_WRITE : 0; - create_temp = H5C_get_default_atom (H5_TEMPLATE); - if (NULL==(f_create_parms=H5Aatom_object(create_temp))) - HGOTO_ERROR (H5E_ATOM, H5E_BADATOM, FAIL);/*can't unatomize template*/ - #ifdef LATER if (access_temp<=0) access_temp = H5CPget_default_atom (H5_TEMPLATE); @@ -1011,7 +1023,7 @@ hid_t H5Fopen(const char *filename, uintn flags, hid_t access_temp) #endif /* Open the file */ - if (NULL==(new_file=H5F_open (filename, flags, f_create_parms))) { + if (NULL==(new_file=H5F_open (filename, flags, NULL))) { HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, FAIL); /*cant open file*/ } @@ -1188,7 +1200,7 @@ H5Fflush (hid_t fid, hbool_t invalidate) * *------------------------------------------------------------------------- */ -static herr_t +herr_t H5F_close (H5F_t *f) { herr_t ret_value = FAIL; diff --git a/src/H5Fistore.c b/src/H5Fistore.c new file mode 100644 index 0000000..b52288c --- /dev/null +++ b/src/H5Fistore.c @@ -0,0 +1,740 @@ +/* + * Copyright (C) 1997 Spizella Software + * All rights reserved. + * + * Programmer: Robb Matzke <robb@arborea.spizella.com> + * Wednesday, October 8, 1997 + */ +#include <H5private.h> +#include <H5Eprivate.h> +#include <H5Fprivate.h> +#include <H5MFprivate.h> +#include <H5MMprivate.h> +#include <H5Oprivate.h> +#include <H5Vprivate.h> + +typedef enum H5F_isop_t { + H5F_ISTORE_READ, /*read from file to memory */ + H5F_ISTORE_WRITE /*write from memory to file */ +} H5F_isop_t; + +/* Does the array domain include negative indices? */ +#undef H5F_ISTORE_NEGATIVE_DOMAIN + + +#define PABLO_MASK H5F_istore_mask + +/* Is the interface initialized? */ +static hbool_t interface_initialize_g = FALSE; + +/* PRIVATE PROTOTYPES */ +static size_t H5F_istore_sizeof_rkey (H5F_t *f, const void *_udata); +static haddr_t H5F_istore_new (H5F_t *f, void *_lt_key, void *_udata, + void *_rt_key); +static intn H5F_istore_cmp (H5F_t *f, void *_lt_key, void *_udata, + void *_rt_key); +static herr_t H5F_istore_found (H5F_t *f, haddr_t addr, const void *_lt_key, + void *_udata, const void *_rt_key); +static haddr_t H5F_istore_insert (H5F_t *f, haddr_t addr, H5B_ins_t *anchor, + void *_lt_key, hbool_t *lt_key_changed, + void *_md_key, void *_udata, + void *_rt_key, hbool_t *rt_key_changed); +static herr_t H5F_istore_decode_key (H5F_t *f, H5B_t *bt, uint8 *raw, + void *_key); +static herr_t H5F_istore_encode_key (H5F_t *f, H5B_t *bt, uint8 *raw, + void *_key); +static herr_t H5F_istore_copy_hyperslab (H5F_t *f, H5O_istore_t *istore, + H5F_isop_t op, size_t offset_f[], + size_t size[], size_t offset_m[], + size_t size_m[], void *buf); + + +/* + * B-tree key. A key contains the minimum logical N-dimensional address and + * the logical size of the chunk to which this key refers. The + * fastest-varying dimension is assumed to reference individual bytes of the + * array, so a 100-element 1-d array of 4-byte integers would really be a 2-d + * array with the slow varying dimension of size 100 and the fast varying + * dimension of size 4 (the storage dimensionality has very little to do with + * the real dimensionality). + * + * Only the first few values of the OFFSET and SIZE fields are actually + * stored on disk, depending on the dimensionality. + * + * The storage file address is part of the B-tree and not part of the key. + */ +typedef struct H5F_istore_key_t { + size_t offset[H5O_ISTORE_NDIMS]; /*logical offset to start*/ + size_t size[H5O_ISTORE_NDIMS]; /*logical chunk size */ +} H5F_istore_key_t; + +typedef struct H5F_istore_ud1_t { + H5F_istore_key_t key; /*key values */ + haddr_t addr; /*file address of chunk */ + H5O_istore_t mesg; /*storage message */ +} H5F_istore_ud1_t; + +/* inherits B-tree like properties from H5B */ +H5B_class_t H5B_ISTORE[1] = {{ + H5B_ISTORE_ID, /*id */ + sizeof (H5F_istore_key_t), /*sizeof_nkey */ + H5F_istore_sizeof_rkey, /*get_sizeof_rkey */ + H5F_istore_new, /*new */ + H5F_istore_cmp, /*cmp */ + H5F_istore_found, /*found */ + H5F_istore_insert, /*insert */ + FALSE, /*follow min branch? */ + FALSE, /*follow max branch? */ + NULL, /*list */ + H5F_istore_decode_key, /*decode */ + H5F_istore_encode_key, /*encode */ +}}; + + + +/*------------------------------------------------------------------------- + * Function: H5F_istore_sizeof_rkey + * + * Purpose: Returns the size of a raw key for the specified UDATA. The + * size of the key is dependent on the number of dimensions for + * the object to which this B-tree points. The dimensionality + * of the UDATA is the only portion that's referenced here. + * + * Return: Success: Size of raw key in bytes. + * + * Failure: abort() + * + * Programmer: Robb Matzke + * Wednesday, October 8, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static size_t +H5F_istore_sizeof_rkey (H5F_t *f, const void *_udata) +{ + const H5F_istore_ud1_t *udata = (const H5F_istore_ud1_t *)_udata; + + assert (udata); + assert (udata->mesg.ndims>0 && udata->mesg.ndims<=H5O_ISTORE_NDIMS); + + return udata->mesg.ndims * (4 + 4); +} + + + +/*------------------------------------------------------------------------- + * Function: H5F_istore_decode_key + * + * Purpose: Decodes a raw key into a native key for the B-tree + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Friday, October 10, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5F_istore_decode_key (H5F_t *f, H5B_t *bt, uint8 *raw, void *_key) +{ + H5F_istore_key_t *key = (H5F_istore_key_t *)_key; + int i; + int ndims = bt->sizeof_rkey / 8; + + FUNC_ENTER (H5F_istore_decode_key, NULL, FAIL); + + /* check args */ + assert (f); + assert (bt); + assert (raw); + assert (key); + assert (ndims>0 && ndims<=H5O_ISTORE_NDIMS && 8*ndims==bt->sizeof_rkey); + + /* decode */ + for (i=0; i<ndims; i++) { + UINT32DECODE (raw, key->offset[i]); + UINT32DECODE (raw, key->size[i]); + } + + FUNC_LEAVE (SUCCEED); + +} + + +/*------------------------------------------------------------------------- + * Function: H5F_istore_encode_key + * + * Purpose: Encode a key from native format to raw format. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Friday, October 10, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5F_istore_encode_key (H5F_t *f, H5B_t *bt, uint8 *raw, void *_key) +{ + H5F_istore_key_t *key = (H5F_istore_key_t *)_key; + intn ndims = bt->sizeof_rkey / 8; + intn i; + + FUNC_ENTER (H5F_istore_encode_key, NULL, FAIL); + + /* check args */ + assert (f); + assert (bt); + assert (raw); + assert (key); + assert (ndims>0 && ndims<=H5O_ISTORE_NDIMS && 8*ndims==bt->sizeof_rkey); + + /* encode */ + for (i=0; i<ndims; i++) { + UINT32ENCODE (raw, key->offset[i]); + UINT32ENCODE (raw, key->size[i]); + } + + FUNC_LEAVE (SUCCEED); +} + + +/*------------------------------------------------------------------------- + * Function: H5F_istore_cmp + * + * Purpose: Compare the requested datum UDATA with the left and right + * keys of the B-tree. + * + * Return: Success: negative if the min_corner of UDATA is less + * than the min_corner of LT_KEY. + * + * positive if the min_corner of UDATA is + * greater than or equal the min_corner of + * RT_KEY. + * + * zero otherwise. The min_corner of UDATA is + * not necessarily contained within the address + * space represented by LT_KEY, but a key that + * would describe the UDATA min_corner address + * would fall lexicographically between LT_KEY + * and RT_KEY. + * + * Failure: FAIL (same as UDATA < LT_KEY) + * + * Programmer: Robb Matzke + * Wednesday, October 8, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static intn +H5F_istore_cmp (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key) +{ + H5F_istore_key_t *lt_key = (H5F_istore_key_t *)_lt_key; + H5F_istore_key_t *rt_key = (H5F_istore_key_t *)_rt_key; + H5F_istore_ud1_t *udata = (H5F_istore_ud1_t *)_udata; + + assert (lt_key); + assert (rt_key); + assert (udata); + assert (udata->mesg.ndims>0 && udata->mesg.ndims<=H5O_ISTORE_NDIMS); + + if (H5V_vector_lt (udata->mesg.ndims, udata->key.offset, lt_key->offset)) { + return -1; + } else if (H5V_vector_ge (udata->mesg.ndims, udata->key.offset, + rt_key->offset)) { + return 1; + } else { + return 0; + } +} + + +/*------------------------------------------------------------------------- + * Function: H5F_istore_new + * + * Purpose: Adds a new entry to an i-storage B-tree. We can assume that + * the domain represented by UDATA doesn't intersect the domain + * already represented by the B-tree. + * + * Return: Success: Address of leaf, which is passed in from the + * UDATA pointer. + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Tuesday, October 14, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static haddr_t +H5F_istore_new (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key) +{ + H5F_istore_key_t *lt_key = (H5F_istore_key_t *)_lt_key; + H5F_istore_key_t *rt_key = (H5F_istore_key_t *)_rt_key; + H5F_istore_ud1_t *udata = (H5F_istore_ud1_t *)_udata; + size_t nbytes; + intn i; + + FUNC_ENTER (H5F_istore_new, NULL, FAIL); + + /* check args */ + assert (f); + assert (lt_key); + assert (rt_key); + assert (udata); + assert (udata->mesg.ndims>=0 && udata->mesg.ndims<H5O_ISTORE_NDIMS); + + /* Allocate new storage */ + nbytes = H5V_vector_reduce_product (udata->mesg.ndims, udata->key.size); + assert (nbytes>0); + if ((udata->addr=H5MF_alloc (f, nbytes))<0) { + /* Couldn't allocate new file storage */ + HRETURN_ERROR (H5E_IO, H5E_CANTINIT, FAIL); + } + + /* left key describes the UDATA, right key is a zero-size "edge" */ + for (i=0; i<udata->mesg.ndims; i++) { + lt_key->offset[i] = udata->key.offset[i]; + lt_key->size[i] = udata->key.size[i]; + assert (udata->key.size[i]>0); + + rt_key->offset[i] = udata->key.offset[i] + udata->key.size[i]; + rt_key->size[i] = 0; + } + + + FUNC_LEAVE (udata->addr); +} + + +/*------------------------------------------------------------------------- + * Function: H5F_istore_found + * + * Purpose: This function is called when the B-tree search engine has + * found the leaf entry that points to a chunk of storage that + * contains the beginning of the logical address space + * represented by UDATA. The LT_KEY is the left key (the one + * that describes the chunk) and RT_KEY is the right key (the + * one that describes the next or last chunk). + * + * Return: Success: SUCCEED with information about the chunk + * returned through the UDATA argument. + * + * Failure: FAIL if not found. + * + * Programmer: Robb Matzke + * Thursday, October 9, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5F_istore_found (H5F_t *f, haddr_t addr, const void *_lt_key, + void *_udata, const void *_rt_key) +{ + H5F_istore_ud1_t *udata = (H5F_istore_ud1_t *)_udata; + const H5F_istore_key_t *lt_key = (const H5F_istore_key_t *)_lt_key; + const H5F_istore_key_t *rt_key = (const H5F_istore_key_t *)_rt_key; + int i; + + FUNC_ENTER (H5F_istore_found, NULL, FAIL); + + /* Check arguments */ + assert (f); + assert (addr>=0); + assert (udata); + assert (lt_key); + assert (rt_key); + + /* Initialize return values */ + udata->addr = addr; + for (i=0; i<udata->mesg.ndims; i++) { + udata->key.offset[i] = lt_key->offset[i]; + udata->key.size[i] = lt_key->size[i]; + assert (lt_key->size[i]>0); + } + + FUNC_LEAVE (SUCCEED); +} + + + +/*------------------------------------------------------------------------- + * Function: H5F_istore_insert + * + * Purpose: This function is called when the B-tree insert engine finds + * the node to use to insert new data. The UDATA argument + * points to a struct that describes the logical addresses being + * added to the file. This function allocates space for the + * data and returns information through UDATA describing a + * file chunk to receive (part of) the data. + * + * The LT_KEY is always the key describing the chunk of file + * memory at address ADDR. On entry, UDATA describes the logical + * addresses for which storage is being requested (through the + * `offset' and `size' fields). On return, UDATA describes the + * logical addresses contained in a chunk on disk. + * + * Return: Success: SUCCEED, with UDATA containing information + * about the (newly allocated) chunk. + * + * If the storage address has changed then the + * new address is returned. + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Thursday, October 9, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static haddr_t +H5F_istore_insert (H5F_t *f, haddr_t addr, H5B_ins_t *parent_ins, + void *_lt_key, hbool_t *lt_key_changed, + void *_md_key, void *_udata, + void *_rt_key, hbool_t *rt_key_changed) +{ + H5F_istore_key_t *lt_key = (H5F_istore_key_t *)_lt_key; + H5F_istore_key_t *md_key = (H5F_istore_key_t *)_md_key; + H5F_istore_key_t *rt_key = (H5F_istore_key_t *)_rt_key; + H5F_istore_ud1_t *udata = (H5F_istore_ud1_t *)_udata; + intn i, cmp; + haddr_t ret_value = 0; + size_t nbytes; + + FUNC_ENTER (H5F_istore_insert, NULL, FAIL); + + /* check args */ + assert (f); + assert (addr>=0); + assert (parent_ins); + assert (lt_key); + assert (lt_key_changed); + assert (md_key); + assert (udata); + assert (rt_key); + assert (rt_key_changed); + + cmp = H5F_istore_cmp (f, lt_key, udata, rt_key); + assert (cmp<=0); + + if (cmp<0) { + /* Negative indices not supported yet */ + assert ("HDF5 INTERNAL ERROR -- see rpm" && 0); + HRETURN_ERROR (H5E_STORAGE, H5E_UNSUPPORTED, FAIL); + + } else if (H5V_hyper_eq (udata->mesg.ndims, + udata->key.offset, udata->key.size, + lt_key->offset, lt_key->size)) { + /* + * Already exists. Just return the info. + */ + udata->addr = addr; + *parent_ins = H5B_INS_NOOP; + + } else if (H5V_hyper_disjointp (udata->mesg.ndims, + lt_key->offset, lt_key->size, + udata->key.offset, udata->key.size)) { + assert (H5V_hyper_disjointp (udata->mesg.ndims, + rt_key->offset, rt_key->size, + udata->key.offset, udata->key.size)); + + /* + * Split this node, inserting the new new node to the right of the + * current node. The MD_KEY is where the split occurs. + */ + for (i=0, nbytes=1; i<udata->mesg.ndims; i++) { + assert (0==udata->key.offset[i] % udata->mesg.alignment[i]); + assert (udata->key.size[i] == udata->mesg.alignment[i]); + md_key->offset[i] = udata->key.offset[i]; + md_key->size[i] = udata->key.size[i]; + nbytes *= udata->key.size[i]; + } + + /* + * Allocate storage for the new chunk + */ + if ((udata->addr=ret_value=H5MF_alloc (f, nbytes))<=0) { + HRETURN_ERROR (H5E_IO, H5E_CANTINIT, FAIL); + } + + *parent_ins = H5B_INS_RIGHT; + + } else { + assert ("HDF5 INTERNAL ERROR -- see rpm" && 0); + HRETURN_ERROR (H5E_IO, H5E_UNSUPPORTED, FAIL); + } + + FUNC_LEAVE (ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5F_istore_copy_hyperslab + * + * Purpose: Reads or writes a hyperslab to disk depending on whether OP + * is H5F_ISTORE_READ or H5F_ISTORE_WRITE. The hyperslab + * storage is described with ISTORE and exists in file F. The + * file hyperslab begins at location OFFSET_F[] (an N-dimensional + * point in the domain in terms of elements) in the file and + * OFFSET_M[] in memory pointed to by BUF. Its size is SIZE[] + * elements. The dimensionality of memory is assumed to be the + * same as the file and the total size of the multi-dimensional + * memory buffer is SIZE_M[]. + * + * The slowest varying dimension is always listed first in the + * various offset and size arrays. + * + * A `chunk' is a hyperslab of the disk array which is stored + * contiguously. I/O occurs in units of chunks where the size of + * a chunk is determined by the alignment constraints specified + * in ISTORE. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Friday, October 17, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5F_istore_copy_hyperslab (H5F_t *f, H5O_istore_t *istore, H5F_isop_t op, + size_t offset_f[], size_t size[], + size_t offset_m[], size_t size_m[], void *buf) +{ + intn i, carry; + size_t idx_cur[H5O_ISTORE_NDIMS]; + size_t idx_min[H5O_ISTORE_NDIMS]; + size_t idx_max[H5O_ISTORE_NDIMS]; + size_t sub_size[H5O_ISTORE_NDIMS]; + size_t sub_offset_f[H5O_ISTORE_NDIMS]; + size_t sub_offset_m[H5O_ISTORE_NDIMS]; + size_t sub_offset_ch[H5O_ISTORE_NDIMS]; + size_t chunk_size; + uint8 *chunk=NULL; + H5F_istore_ud1_t udata; + herr_t status; + herr_t ret_value = FAIL; + + FUNC_ENTER (H5F_istore_copy_hyperslab, NULL, FAIL); + + /* check args */ + assert (f); + assert (istore); + assert (istore->ndims>0 && istore->ndims<=H5O_ISTORE_NDIMS); + assert (H5F_ISTORE_READ==op || H5F_ISTORE_WRITE==op); + assert (size); + assert (size_m); + assert (buf); +#ifndef NDEBUG + for (i=0; i<istore->ndims; i++) { + assert (!offset_f || offset_f[i]>=0);/*neg domains unsupported */ + assert (!offset_m || offset_m[i]>=0);/*mem array offset never neg */ + assert (size[i]>=0); /*size may be zero, implies no-op */ + assert (size_m[i]>0); /*destination must exist */ + /*hyperslab must fit in BUF*/ + assert ((offset_m?offset_m[i]:0)+size[i]<=size_m[i]); + assert (istore->alignment[i]>0); + } +#endif + + /* + * Does the B-tree exist? + */ + if (istore->btree_addr<=0) { + if (H5F_ISTORE_WRITE==op) { + udata.mesg.ndims = istore->ndims; + if ((istore->btree_addr=H5B_new (f, H5B_ISTORE, &udata))<0) { + /* Can't create B-tree */ + HGOTO_ERROR (H5E_IO, H5E_CANTINIT, FAIL); + } + } else { + H5V_hyper_fill (istore->ndims, size, size_m, offset_m, buf, 0); + HRETURN (SUCCEED); + } + } + + /* Initialize indices */ + for (i=0; i<istore->ndims; i++) { + idx_min[i] = (offset_f?offset_f[i]:0) / istore->alignment[i]; + idx_max[i] = ((offset_f?offset_f[i]:0)+size[i]-1)/istore->alignment[i]+1; + idx_cur[i] = idx_min[i]; + } + + /* Allocate buffers */ + for (i=0, chunk_size=1; i<istore->ndims; i++) { + chunk_size *= istore->alignment[i]; + } + chunk = H5MM_xmalloc (chunk_size); + + /* Initialize non-changing part of udata */ + udata.mesg = *istore; + + /* Loop over all chunks */ + while (1) { + + /* Read/Write chunk or create it if it doesn't exist */ + udata.mesg.ndims = istore->ndims; + for (i=0; i<istore->ndims; i++) { + udata.key.offset[i] = idx_cur[i] * istore->alignment[i]; + udata.key.size[i] = istore->alignment[i]; + sub_offset_f[i] = MAX ((offset_f?offset_f[i]:0), udata.key.offset[i]); + sub_offset_m[i] = (offset_m?offset_m[i]:0) + + sub_offset_f[i] - (offset_f?offset_f[i]:0); + sub_size[i] = (idx_cur[i]+1)*istore->alignment[i]-sub_offset_f[i]; + sub_offset_ch[i] = sub_offset_f[i] - udata.key.offset[i]; + } + if (H5F_ISTORE_WRITE==op) { + status = H5B_insert (f, H5B_ISTORE, istore->btree_addr, &udata); + assert (status>=0); + } else { + status = H5B_find (f, H5B_ISTORE, istore->btree_addr, &udata); + } + + /* + * If the operation is reading from the disk or if we are writing a + * partial chunk then load the chunk from disk. + */ + if (H5F_ISTORE_READ==op || + !H5V_hyper_eq (istore->ndims, + udata.key.offset, udata.key.size, + sub_offset_f, sub_size)) { + if (status>=0) { + if (H5F_block_read (f, udata.addr, chunk_size, chunk)<0) { + HGOTO_ERROR (H5E_IO, H5E_READERROR, FAIL); + } + } else { + HDmemset (chunk, 0, chunk_size); + } + } + + /* Transfer data to/from the chunk */ + if (H5F_ISTORE_WRITE==op) { + H5V_hyper_copy (istore->ndims, sub_size, + udata.key.size, sub_offset_ch, chunk, + size_m, sub_offset_m, buf); + if (H5F_block_write (f, udata.addr, chunk_size, chunk)<0) { + HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL); + } + } else { + H5V_hyper_copy (istore->ndims, sub_size, + size_m, sub_offset_m, buf, + udata.key.size, sub_offset_ch, chunk); + } + + /* Increment indices */ + for (i=istore->ndims-1, carry=1; i>=0 && carry; --i) { + if (++idx_cur[i]>=idx_max[i]) idx_cur[i] = idx_min[i]; + else carry = 0; + } + if (carry) break; + } + ret_value = SUCCEED; + + + done: + chunk = H5MM_xfree (chunk); + FUNC_LEAVE (ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5F_istore_read + * + * Purpose: Reads a multi-dimensional buffer from (part of) an indexed raw + * storage array. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Wednesday, October 15, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_istore_read (H5F_t *f, struct H5O_istore_t *istore, + size_t offset[], size_t size[], void *buf) +{ + FUNC_ENTER (H5F_istore_read, NULL, FAIL); + + /* Check args */ + assert (f); + assert (istore); + assert (istore->ndims>0 && istore->ndims<=H5O_ISTORE_NDIMS); + assert (size); + assert (buf); + + if (H5F_istore_copy_hyperslab (f, istore, H5F_ISTORE_READ, + offset, size, H5V_ZERO, size, buf)<0) { + /* hyperslab output failure */ + HRETURN_ERROR (H5E_IO, H5E_READERROR, FAIL); + } + + FUNC_LEAVE (SUCCEED); +} + + +/*------------------------------------------------------------------------- + * Function: H5F_istore_write + * + * Purpose: Writes a multi-dimensional buffer to (part of) an indexed raw + * storage array. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Wednesday, October 15, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_istore_write (H5F_t *f, struct H5O_istore_t *istore, + size_t offset[], size_t size[], void *buf) +{ + FUNC_ENTER (H5F_istore_write, NULL, FAIL); + + /* Check args */ + assert (f); + assert (istore); + assert (istore->ndims>0 && istore->ndims<=H5O_ISTORE_NDIMS); + assert (size); + assert (buf); + + if (H5F_istore_copy_hyperslab (f, istore, H5F_ISTORE_WRITE, + offset, size, H5V_ZERO, size, buf)<0) { + /* hyperslab output failure */ + HRETURN_ERROR (H5E_IO, H5E_WRITEERROR, FAIL); + } + + FUNC_LEAVE (SUCCEED); +} + diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index 81f43ce..0d0a65c 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -20,7 +20,7 @@ #define _H5Fprivate_H #include <H5Fpublic.h> -/* Private headers needed by this file */ +/* This is a near top-level header! Try not to include much! */ #include <H5private.h> /* Maximum size of boot-block buffer */ @@ -397,6 +397,7 @@ typedef struct H5F_t { uintn intent; /* The flags passed to H5F_open() */ char *name; /* Name used to open file */ H5F_file_t *shared; /* The shared file info */ + struct H5G_cwgstk_t *cwg_stack; /* CWG stack for push/pop functions */ } H5F_t; @@ -446,12 +447,20 @@ typedef struct H5F_t { case 2: UINT16DECODE(p,l); break; \ } +struct H5O_istore_t; /*forward decl for prototype arguments*/ /* Private functions, not part of the publicly documented API */ void H5F_encode_length_unusual(const H5F_t *f, uint8 **p, uint8 *l); void H5F_encode_offset_unusual(const H5F_t *f, uint8 **p, uint8 *o); +H5F_t *H5F_open (const char *name, uintn flags, + const file_create_temp_t *create_parms); +herr_t H5F_close (H5F_t *f); herr_t H5F_block_read (H5F_t *f, haddr_t addr, size_t size, void *buf); herr_t H5F_block_write (H5F_t *f, haddr_t addr, size_t size, void *buf); +herr_t H5F_istore_read (H5F_t *f, struct H5O_istore_t *mesg, + size_t offset[], size_t size[], void *buf); +herr_t H5F_istore_write (H5F_t *f, struct H5O_istore_t *mesg, + size_t offset[], size_t size[], void *buf); herr_t H5F_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent, intn fwidth); @@ -10,15 +10,15 @@ * * Purpose: Symbol table functions. The functions that * begin with `H5G_stab_' don't understand the - * directory hierarchy; they operate on a single + * naming system; they operate on a single * symbol table at a time. * * The functions that begin with `H5G_node_' operate * on the leaf nodes of a symbol table B-tree. They * should be defined in the H5Gnode.c file. * - * The remaining functions know about the directory - * hierarchy. + * The remaining functions know how to traverse the + * group directed graph * * Modifications: * @@ -53,6 +53,266 @@ static hbool_t interface_initialize_g = FALSE; /*------------------------------------------------------------------------- + * Function: H5Gnew + * + * Purpose: Creates a new group in FILE and gives it the specified + * NAME. Unless NAME begins with `/' it is relative to the + * current working group. + * + * The optional SIZE_HINT specifies how much file space to + * reserve to store the names that will appear in this + * group (an even number of characters, counting the null + * terminator, is allocated for each name). If a non-positive + * value is supplied for the SIZE_HINT then a default size is + * chosen. + * + * See also: H5Gset(), H5Gpush(), H5Gpop() + * + * Errors: + * ARGS BADTYPE Not a file atom. + * ARGS BADVALUE No name given. + * ATOM BADATOM Can't unatomize file. + * SYM CANTINIT Can't close handle. + * SYM CANTINIT Can't create group. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Wednesday, September 24, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Gnew (hid_t file, const char *name, size_t size_hint) +{ + H5F_t *f=NULL; + H5G_entry_t *grp_handle=NULL; + + FUNC_ENTER (H5Gnew, NULL, FAIL); + + /* Check/fix arguments */ + if (!name || !*name) { + HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL);/*no name given*/ + } + if (H5_FILE!=H5Aatom_group (file)) { + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL);/*not a file atom*/ + } + if (NULL==(f=H5Aatom_object (file))) { + HRETURN_ERROR (H5E_ATOM, H5E_BADATOM, FAIL);/*can't unatomize file*/ + } + + /* Create the group */ + if (NULL==(grp_handle=H5G_new (f, name, size_hint))) { + /*can't create group*/ + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); + } + + /* Close the group handle */ + if (H5G_close (f, grp_handle)<0) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL);/*can't close handle*/ + } + + FUNC_LEAVE (SUCCEED); +} + + + +/*------------------------------------------------------------------------- + * Function: H5Gset + * + * Purpose: Sets the working group for file handle FILE to the + * specified NAME. Unless NAME begins with a `/' it is + * interpretted relative to the current working group. + * + * Each file handle maintains its own notion of the current + * working group. That is, if a single file is opened with + * multiple calls to H5Fopen(), which returns multiple file + * handles, then each handle's current working group can be + * set independently of the other file handles for that file. + * + * See also: H5Gpush(), H5Gpop() + * + * Errors: + * ARGS BADTYPE Not a file atom. + * ARGS BADVALUE No name given. + * ATOM BADATOM Can't unatomize file. + * SYM CANTINIT Can't change current working group. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Wednesday, September 24, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Gset (hid_t file, const char *name) +{ + H5F_t *f=NULL; + + FUNC_ENTER (H5Gset, NULL, FAIL); + + /* Check/fix arguments */ + if (!name || !*name) { + HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL);/*no name given*/ + } + if (H5_FILE!=H5Aatom_group (file)) { + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL);/*not a file atom*/ + } + if (NULL==(f=H5Aatom_object (file))) { + HRETURN_ERROR (H5E_ATOM, H5E_BADATOM, FAIL);/*can't unatomize file*/ + } + + if (H5G_set (f, name)<0) { + /* Can't change current working group */ + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); + } + + FUNC_LEAVE (SUCCEED); +} + + + +/*------------------------------------------------------------------------- + * Function: H5Gpush + * + * Purpose: Similar to H5Gset() except the new working group is pushed + * on a stack. + * + * Each file handle maintains its own notion of the current + * working group. That is, if a single file is opened with + * multiple calls to H5Fopen(), which returns multiple file + * handles, then each handle's current working group can be + * set independently of the other file handles for that file. + * + * See also: H5Gset(), H5Gpop() + * + * Errors: + * ARGS BADTYPE Not a file atom. + * ARGS BADVALUE No name given. + * ATOM BADATOM Can't unatomize file. + * SYM CANTINIT Can't change current working group. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Wednesday, September 24, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Gpush (hid_t file, const char *name) +{ + H5F_t *f=NULL; + + FUNC_ENTER (H5Gpush, NULL, FAIL); + + /* Check/fix arguments */ + if (!name || !*name) { + HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL);/*no name given*/ + } + if (H5_FILE!=H5Aatom_group (file)) { + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL);/*not a file atom*/ + } + if (NULL==(f=H5Aatom_object (file))) { + HRETURN_ERROR (H5E_ATOM, H5E_BADATOM, FAIL);/*can't unatomize file*/ + } + + if (H5G_push (f, name)<0) { + /* Can't change current working group */ + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); + } + + FUNC_LEAVE (SUCCEED); +} + + + +/*------------------------------------------------------------------------- + * Function: H5Gpop + * + * Purpose: Removes the top (latest) entry from the working group stack + * and sets the current working group to the previous value. + * + * Each file handle maintains its own notion of the current + * working group. That is, if a single file is opened with + * multiple calls to H5Fopen(), which returns multiple file + * handles, then each handle's current working group can be + * set independently of the other file handles for that file. + * + * See also: H5Gset(), H5Gpush() + * + * Errors: + * ARGS BADTYPE Not a file atom. + * ATOM BADATOM Can't unatomize file. + * SYM CANTINIT Stack is empty. + * + * Return: Success: SUCCEED + * + * Failure: FAIL. The final entry cannot be popped from + * the group stack (but it can be changed + * with H5Gset()). + * + * Programmer: Robb Matzke + * Wednesday, September 24, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Gpop (hid_t file) +{ + H5F_t *f=NULL; + + FUNC_ENTER (H5Gpop, NULL, FAIL); + + /* Check/fix arguments */ + if (H5_FILE!=H5Aatom_group (file)) { + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL);/*not a file atom*/ + } + if (NULL==(f=H5Aatom_object (file))) { + HRETURN_ERROR (H5E_ATOM, H5E_BADATOM, FAIL);/*can't unatomize file*/ + } + + if (H5G_pop (f)<0) { + /* Stack is empty */ + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); + } + + FUNC_LEAVE (SUCCEED); +} + + + + +/* + *------------------------------------------------------------------------- + *------------------------------------------------------------------------- + * N O A P I F U N C T I O N S B E Y O N D T H I S P O I N T + *------------------------------------------------------------------------- + *------------------------------------------------------------------------- + */ + + + + + + + +/*------------------------------------------------------------------------- * Function: H5G_component * * Purpose: Returns the pointer to the first component of the @@ -67,7 +327,7 @@ static hbool_t interface_initialize_g = FALSE; * Failure: Ptr to the null terminator of NAME. * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Aug 11 1997 * * Modifications: @@ -102,7 +362,7 @@ H5G_component (const char *name, size_t *size_p) * Failure: Ptr to the null terminator of NAME. * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Aug 11 1997 * * Modifications: @@ -122,7 +382,7 @@ H5G_basename (const char *name, size_t *size_p) while (s>name && '/'!=s[-1]) --s; /*skip past base name*/ /* - * If the input was the name of the root directory `/' (or + * If the input was the name of the root group `/' (or * equivalent) then return the null string. */ if ('/'==*s) { @@ -142,42 +402,43 @@ H5G_basename (const char *name, size_t *size_p) * Purpose: (Partially) translates a name to a symbol table entry. * * Given a name (absolute or relative) return the symbol table - * entry for that name and for the directory that contains the - * base name. These entries (DIR_ENT and BASE_ENT) are returned + * entry for that name and for the group that contains the + * base name. These entries (GRP_ENT and BASE_ENT) are returned * through memory passed into the function by the caller. Either * or both pointers may be null. Absolute names are looked up - * relative to the root directory of file F while relative - * names are traversed beginning at the CWD argument. + * relative to the root group of file F while relative + * names are traversed beginning at the CWG argument. * * Consecutive slash characters are treated like single * slash characters. Trailing slashes are ignored. The - * component `.' is recognized as the current directory - * during the traversal (initially CWD), but the component + * component `.' is recognized as the current group + * during the traversal (initially CWG), but the component * `..' is not internally recognized (it is recognized if * such a name appears in the symbol table). * * 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 this - * function will return null. DIR_ENT will be initialized with - * information about the directory (or other object) at which + * function will return null. GRP_ENT will be initialized with + * information about the group (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 + * equivalent) then GRP_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 a pointer + * non-group object with a name message with the value + * `foo' then GRP_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. + * SYM COMPLEN Component is too long. + * SYM NOTFOUND Component not found. + * SYM NOTFOUND No root group. + * SYM NOTFOUND Root not found. * * Return: Success: Pointer to a cached symbol table entry if the * name can be fully resolved. The pointer is @@ -185,11 +446,11 @@ H5G_basename (const char *name, size_t *size_p) * is called. * * Failure: Null if the name could not be fully resolved. - * REST and DIR_ENT are initialized (possibly to + * REST and GRP_ENT are initialized (possibly to * zero if the failure occurred soon enough). * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Aug 11 1997 * * Modifications: @@ -197,10 +458,10 @@ H5G_basename (const char *name, size_t *size_p) *------------------------------------------------------------------------- */ static H5G_entry_t * -H5G_namei (H5F_t *f, H5G_entry_t *cwd, const char *name, - const char **rest, H5G_entry_t *dir_ent) +H5G_namei (H5F_t *f, H5G_entry_t *cwg, const char *name, + const char **rest, H5G_entry_t *grp_ent) { - H5G_entry_t dir; /*entry for current directory */ + H5G_entry_t grp; /*entry for current group */ size_t nchars; /*component name length */ char comp[1024]; /*component name buffer */ hbool_t aside = FALSE; /*did we look at a name message?*/ @@ -208,7 +469,7 @@ H5G_namei (H5F_t *f, H5G_entry_t *cwd, const char *name, /* 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)); + if (grp_ent) memset (grp_ent, 0, sizeof(H5G_entry_t)); FUNC_ENTER (H5G_namei, NULL, NULL); @@ -216,18 +477,19 @@ H5G_namei (H5F_t *f, H5G_entry_t *cwd, const char *name, assert (f); assert (f->shared->root_sym); assert (name && *name); - assert (cwd || '/'==*name); + assert (cwg || '/'==*name); /* starting point */ if ('/'==*name) { if (f->shared->root_sym->header<=0) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, NULL); + /* No root group */ + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL); } ret_value = f->shared->root_sym; - dir = *(f->shared->root_sym); + grp = *(f->shared->root_sym); } else { - ret_value = cwd; - dir = *cwd; + ret_value = cwg; + grp = *cwg; } /* traverse the name */ @@ -241,7 +503,7 @@ H5G_namei (H5F_t *f, H5G_entry_t *cwd, const char *name, /* * Advance to the next component of the name. */ - dir = *ret_value; + grp = *ret_value; ret_value = NULL; if (rest) *rest = name; @@ -251,23 +513,23 @@ H5G_namei (H5F_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, NULL); + if (grp_ent) *grp_ent = grp; + HRETURN_ERROR (H5E_SYM, H5E_COMPLEN, NULL); } HDmemcpy (comp, name, nchars); comp[nchars] = '\0'; - if (NULL==(ret_value=H5G_stab_find (f, NO_ADDR, &dir, comp))) { + if (NULL==(ret_value=H5G_stab_find (f, NO_ADDR, &grp, comp))) { /* * Component was not found in the current symbol table, possibly - * because DIR isn't a symbol table. If it is the root symbol then + * because GRP 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->shared->root_sym->header && - H5O_read (f, dir.header, &dir, H5O_NAME, 0, &mesg) && + if (!aside && grp.header==f->shared->root_sym->header && + H5O_read (f, grp.header, &grp, H5O_NAME, 0, &mesg) && !HDstrcmp (mesg.s, comp)) { H5O_reset (H5O_NAME, &mesg); ret_value = f->shared->root_sym; @@ -275,8 +537,8 @@ H5G_namei (H5F_t *f, H5G_entry_t *cwd, const char *name, } else { /* component not found */ H5O_reset (H5O_NAME, &mesg); - if (dir_ent) *dir_ent = dir; - HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, NULL); + if (grp_ent) *grp_ent = grp; + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL); } } @@ -286,17 +548,17 @@ H5G_namei (H5F_t *f, H5G_entry_t *cwd, const char *name, /* output parameters */ if (rest) *rest = name; /*final null*/ - if (dir_ent) { + if (grp_ent) { if (ret_value->header == f->shared->root_sym->header) { - HDmemset (dir_ent, 0, sizeof(H5G_entry_t)); /*root has no parent*/ + HDmemset (grp_ent, 0, sizeof(H5G_entry_t)); /*root has no parent*/ } else { - *dir_ent = dir; + *grp_ent = grp; } } /* Perhaps the root object doesn't even exist! */ if (ret_value->header<=0) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, NULL); /*root not found*/ + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL); /*root not found*/ } FUNC_LEAVE (ret_value); @@ -306,10 +568,10 @@ H5G_namei (H5F_t *f, H5G_entry_t *cwd, const char *name, /*------------------------------------------------------------------------- * Function: H5G_mkroot * - * Purpose: Creates the root directory if it doesn't exist; otherwise + * Purpose: Creates the root group if it doesn't exist; otherwise * nothing happens. If the root symbol table entry previously - * pointed to something other than a directory, then that object - * is made a member of the root directory and is given a name + * pointed to something other than a group, then that object + * is made a member of the root group and is given a name * corresponding to the object's name message (the name message * is removed). If the root object doesn't have a name message * then the name `Root Object' is used. @@ -317,19 +579,21 @@ H5G_namei (H5F_t *f, H5G_entry_t *cwd, const char *name, * Warning: This function has a few subtleties. Be warned! * * Errors: - * DIRECTORY CANTINIT Can't create root. - * DIRECTORY CANTINIT Can't insert old root object in - * new root directory. - * DIRECTORY EXISTS Root directory already exists. + * SYM CANTINIT Can't open root object. + * SYM CANTINIT Can't reinsert old root object. + * SYM CANTINIT Cant create root. + * SYM EXISTS Root group already exists. + * SYM LINK Bad link count on old root object. + * SYM LINK Cant create root. * * Return: Success: SUCCEED * * Failure: FAIL. This function returns -2 if the - * failure is because a root directory already + * failure is because a root group already * exists. * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Aug 11 1997 * * Modifications: @@ -356,20 +620,21 @@ H5G_mkroot (H5F_t *f, size_t size_hint) /* * If we already have a root object, then open it and get it's name. The - * root object had better not already be a directory. Once the old root + * root object had better not already be a group. Once the old root * object is opened and we have a HANDLE, set the dirty bit on the handle. * This causes the handle data to be written back into f->root_sym by * H5G_close() if something goes wrong before the old root object is - * re-inserted back into the directory hierarchy. We might leak file + * re-inserted back into the group directed graph. We might leak file * memory, but at least we don't loose the original root object. */ if (f->shared->root_sym->header>0) { if (H5O_read (f, NO_ADDR, f->shared->root_sym, H5O_STAB, 0, &stab)) { - /* root directory already exists */ - HGOTO_ERROR (H5E_DIRECTORY, H5E_EXISTS, -2); - } else if (NULL==(handle=H5G_shadow_open (f, NULL, f->shared->root_sym))) { + /* root group already exists */ + HGOTO_ERROR (H5E_SYM, H5E_EXISTS, -2); + } else if (NULL==(handle=H5G_shadow_open (f, NULL, + f->shared->root_sym))) { /* can't open root object */ - HGOTO_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL); + HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); } else if (NULL==H5O_read (f, NO_ADDR, handle, H5O_NAME, 0, &name)) { obj_name = "Root Object"; } else { @@ -379,15 +644,15 @@ H5G_mkroot (H5F_t *f, size_t size_hint) } /* - * Create the new root directory directly into the file descriptor. If + * Create the new root group directly into the file descriptor. If * something goes wrong at this step, closing the `handle' will rewrite * info back into f->root_sym because we set the dirty bit. */ if (H5G_stab_new (f, f->shared->root_sym, size_hint)<0) { - HGOTO_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL); /*cant create root*/ + HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); /*cant create root*/ } if (1!=H5O_link (f, f->shared->root_sym, 1)) { - HGOTO_ERROR (H5E_DIRECTORY, H5E_LINK, FAIL); + HGOTO_ERROR (H5E_SYM, H5E_LINK, FAIL); } /* @@ -397,11 +662,13 @@ H5G_mkroot (H5F_t *f, size_t size_hint) */ if (obj_name) { if (1!=H5O_link (f, handle, 0)) { - HGOTO_ERROR (H5E_DIRECTORY, H5E_LINK, FAIL); + /* Bad link count on old root object */ + HGOTO_ERROR (H5E_SYM, H5E_LINK, FAIL); } if (NULL==(ent_ptr=H5G_stab_insert (f, f->shared->root_sym, obj_name, handle))) { - HGOTO_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL); + /* Can't reinsert old root object */ + HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); } /* @@ -418,10 +685,10 @@ H5G_mkroot (H5F_t *f, size_t size_hint) done: /* * If the handle is closed before the H5G_stab_insert() call that - * reinserts the root object into the directory hierarchy, then + * reinserts the root object into the group directed graph, then * H5G_close() will reset f->root_sym to point to the old root symbol and - * the new root directory (if it was created) will be unlinked from the - * directory hierarchy (and memory leaked). + * the new root group (if it was created) will be unlinked from the + * group directed graph (and memory leaked). */ if (handle) H5G_close (f, handle); H5O_reset (H5O_NAME, &name); @@ -431,32 +698,33 @@ H5G_mkroot (H5F_t *f, size_t size_hint) /*------------------------------------------------------------------------- - * Function: H5G_mkdir + * Function: H5G_new * - * Purpose: Creates a new empty directory with the specified name, + * Purpose: Creates a new empty group with the specified name, * opening it as an object. The name is either an absolute name - * or is relative to the current working directory. + * or is relative to the current working group. * - * A root directory is created implicitly by this function + * A root group is created implicitly by this function * when necessary. Calling this function with the name "/" * (or any equivalent name) will result in an H5E_EXISTS * failure. * * Errors: - * DIRECTORY CANTINIT Can't create dir. - * DIRECTORY CANTINIT Can't insert. - * DIRECTORY CANTINIT Lookup failed. - * DIRECTORY COMPLEN Component is too long. - * DIRECTORY EXISTS Already exists. - * DIRECTORY NOTFOUND Missing component. - * - * Return: Success: A handle to the open directory. Please call + * SYM CANTINIT Can't create grp. + * SYM CANTINIT Can't create root group. + * SYM CANTINIT Can't insert. + * SYM CANTINIT Can't open. + * SYM COMPLEN Component is too long. + * SYM EXISTS Already exists. + * SYM NOTFOUND Missing component. + * + * Return: Success: A handle to the open group. Please call * H5G_close() when you're done with it. * * Failure: NULL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Aug 11 1997 * * Modifications: @@ -464,42 +732,43 @@ H5G_mkroot (H5F_t *f, size_t size_hint) *------------------------------------------------------------------------- */ H5G_entry_t * -H5G_mkdir (H5F_t *f, const char *name, size_t size_hint) +H5G_new (H5F_t *f, const char *name, size_t size_hint) { const char *rest=NULL; /*the base name */ - H5G_entry_t *cwd=NULL; /*current working directory */ - H5G_entry_t dir_ent; /*directory containing new dir */ - H5G_entry_t ent; /*new directory entry */ - H5G_entry_t *ent_ptr=NULL; /*ptr to new directory entry */ + H5G_entry_t *cwg=NULL; /*current working group */ + H5G_entry_t grp_ent; /*group containing new group */ + H5G_entry_t ent; /*new group entry */ + H5G_entry_t *ent_ptr=NULL; /*ptr to new group entry */ H5G_entry_t *ret_value=NULL; /*handle return value */ char _comp[1024]; /*name component */ size_t nchars; /*number of characters in compon*/ herr_t status; /*function return status */ - FUNC_ENTER (H5G_mkdir, NULL, NULL); + FUNC_ENTER (H5G_new, NULL, NULL); /* check args */ assert (f); assert (name && *name); #ifndef LATER - /* Get current working directory */ + /* Get current working group */ H5G_shadow_sync (f->shared->root_sym); - cwd = f->shared->root_sym; + cwg = f->shared->root_sym; #endif - assert (cwd || '/'==*name); + assert (cwg || '/'==*name); /* - * Try to create the root directory. Ignore the error if this function - * fails because the root directory already exists. + * Try to create the root group. Ignore the error if this function + * fails because the root group already exists. */ if ((status=H5G_mkroot (f, H5G_SIZE_HINT))<0 && -2!=status) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL); + /* Can't create root group */ + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL); } H5ECLEAR; /* lookup name */ - if (H5G_namei (f, cwd, name, &rest, &dir_ent)) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_EXISTS, NULL); /*already exists*/ + if (H5G_namei (f, cwg, name, &rest, &grp_ent)) { + HRETURN_ERROR (H5E_SYM, H5E_EXISTS, NULL); /*already exists*/ } H5ECLEAR; /*it's OK that we didn't find it*/ @@ -509,10 +778,10 @@ H5G_mkdir (H5F_t *f, const char *name, size_t size_hint) if (rest[nchars]) { if (H5G_component (rest+nchars, NULL)) { /* missing component */ - HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, NULL); + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL); } else if (nchars+1 > sizeof _comp) { /* component is too long */ - HRETURN_ERROR (H5E_DIRECTORY, H5E_COMPLEN, NULL); + HRETURN_ERROR (H5E_SYM, H5E_COMPLEN, NULL); } else { /* null terminate */ HDmemcpy (_comp, rest, nchars); @@ -521,19 +790,19 @@ H5G_mkdir (H5F_t *f, const char *name, size_t size_hint) } } - /* create directory */ + /* create group */ if (H5G_stab_new (f, &ent, size_hint)<0) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL); /*can't create dir*/ + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL); /*can't create grp*/ } /* insert child name into parent */ - if (NULL==(ent_ptr=H5G_stab_insert (f, &dir_ent, rest, &ent))) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL); /*can't insert*/ + if (NULL==(ent_ptr=H5G_stab_insert (f, &grp_ent, rest, &ent))) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL); /*can't insert*/ } - /* open the directory */ - if (NULL==(ret_value=H5G_shadow_open (f, &dir_ent, ent_ptr))) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL); /*can't open*/ + /* open the group */ + if (NULL==(ret_value=H5G_shadow_open (f, &grp_ent, ent_ptr))) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL); /*can't open*/ } FUNC_LEAVE (ret_value); @@ -542,9 +811,121 @@ H5G_mkdir (H5F_t *f, const char *name, size_t size_hint) /*------------------------------------------------------------------------- - * Function: H5G_pushd + * Function: H5G_set + * + * Purpose: Sets the current working group to be the specified name. + * This affects only the top item on the group stack for the + * specified file as accessed through this file handle. If the + * file is opened multiple times, then the current working group + * for this file handle is the only one that is changed. * - * Purpose: Pushes a new current working directory onto the stack. + * Errors: + * SYM CWG Can't open group. + * SYM CWG Couldn't close previous c.w.g. + * SYM CWG Not a group. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Wednesday, September 24, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_set (H5F_t *f, const char *name) +{ + H5G_entry_t *handle=NULL; + H5O_stab_t stab_mesg; + herr_t ret_value=FAIL; + + FUNC_ENTER (H5G_set, NULL, FAIL); + + if (NULL==(handle=H5G_open (f, name))) { + /* Can't open group */ + HGOTO_ERROR (H5E_SYM, H5E_CWG, FAIL); + } + if (NULL==H5O_read (f, NO_ADDR, handle, H5O_NAME, 0, &stab_mesg)) { + /* Not a group */ + HGOTO_ERROR (H5E_SYM, H5E_CWG, FAIL); + } + + /* + * If there is no stack then create one, otherwise close the current + * working group. + */ + if (!f->cwg_stack) { + f->cwg_stack = H5MM_xcalloc (1, sizeof(H5G_cwgstk_t)); + f->cwg_stack->handle = handle; + } else { + if (H5G_close (f, f->cwg_stack->handle)<0) { + /* Couldn't close previous c.w.g. */ + HGOTO_ERROR (H5E_SYM, H5E_CWG, FAIL); + } + f->cwg_stack->handle = handle; + } + ret_value = SUCCEED; + + done: + if (ret_value<0 && handle) { + H5G_close (f, handle); + } + + FUNC_LEAVE (ret_value); +} + + + +/*------------------------------------------------------------------------- + * Function: H5G_getcwg + * + * Purpose: Returns a handle for the current working group. If there + * is no current working group then a pointer to the root + * symbol is returned but that object is not opened (and it + * might not even be a group). + * + * Return: Success: Ptr to open group handle with exceptions + * noted above. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * Wednesday, September 24, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static H5G_entry_t * +H5G_getcwg (H5F_t *f) +{ + H5G_entry_t *handle=NULL; + + FUNC_ENTER (H5G_getcwg, NULL, NULL); + + if (f->cwg_stack && f->cwg_stack->handle) { + handle = f->cwg_stack->handle; + } else { + H5G_shadow_sync (f->shared->root_sym); + handle = f->shared->root_sym; + } + + FUNC_LEAVE (handle); +} + + + +/*------------------------------------------------------------------------- + * Function: H5G_push + * + * Purpose: Pushes a new current working group onto the stack. + * + * Errors: + * SYM CWG Can't open group. + * SYM CWG Not a group. * * Return: Success: SUCCEED * @@ -558,31 +939,54 @@ H5G_mkdir (H5F_t *f, const char *name, size_t size_hint) *------------------------------------------------------------------------- */ herr_t -H5G_pushd (H5F_t *f, const char *name) +H5G_push (H5F_t *f, const char *name) { + H5G_entry_t *handle=NULL; + H5G_cwgstk_t *stack=NULL; + H5O_stab_t stab_mesg; + herr_t ret_value = FAIL; + FUNC_ENTER (H5G_pushd, NULL, FAIL); -#ifndef LATER + if (NULL==(handle=H5G_open (f, name))) { + /* Can't open group */ + HGOTO_ERROR (H5E_SYM, H5E_CWG, FAIL); + } + if (NULL==H5O_read (f, NO_ADDR, handle, H5O_NAME, 0, &stab_mesg)) { + /* Not a group */ + HGOTO_ERROR (H5E_SYM, H5E_CWG, FAIL); + } + /* - * Current working directories are not implemented yet. + * Push a new entry onto the stack. */ - if (strcmp (name, "/")) { - HRETURN_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, FAIL); + stack = H5MM_xcalloc (1, sizeof(H5G_cwgstk_t)); + stack->handle = handle; + stack->next = f->cwg_stack; + f->cwg_stack = stack; + ret_value = SUCCEED; + + done: + if (ret_value<0 && handle) { + H5G_close (f, handle); } -#endif - + FUNC_LEAVE (SUCCEED); } /*------------------------------------------------------------------------- - * Function: H5G_popd + * Function: H5G_pop * - * Purpose: Pops the top current working directory off the stack. + * Purpose: Pops the top current working group off the stack. + * + * Errors: + * SYM CWG Can't close current working group. + * SYM CWG Stack is empty. * * Return: Success: SUCCEED * - * Failure: FAIL + * Failure: FAIL if the stack is empty. * * Programmer: Robb Matzke * Friday, September 19, 1997 @@ -592,13 +996,24 @@ H5G_pushd (H5F_t *f, const char *name) *------------------------------------------------------------------------- */ herr_t -H5G_popd (H5F_t *f) +H5G_pop (H5F_t *f) { - FUNC_ENTER (H5G_popd, NULL, FAIL); + H5G_cwgstk_t *stack=NULL; + + FUNC_ENTER (H5G_pop, NULL, FAIL); -#ifndef LATER - /* CWD is not implemented yet. */ -#endif + if ((stack=f->cwg_stack)) { + if (H5G_close (f, stack->handle)<0) { + /* Can't close current working group */ + HRETURN_ERROR (H5E_SYM, H5E_CWG, FAIL); + } + f->cwg_stack = stack->next; + stack->handle = NULL; + H5MM_xfree (stack); + } else { + /* Stack is empty */ + HRETURN_ERROR (H5E_SYM, H5E_CWG, FAIL); + } FUNC_LEAVE (SUCCEED); } @@ -612,6 +1027,21 @@ H5G_popd (H5F_t *f) * object. The initial size of the object header can be * supplied with the OHDR_HINT argument. * + * Errors: + * SYM CANTINIT Bad link count. + * SYM CANTINIT Can't create header. + * SYM CANTINIT Can't create root group. + * SYM CANTINIT Can't insert. + * SYM CANTINIT Can't open object. + * SYM CANTINIT Cannot add/change name message. + * SYM CANTINIT Create the object header. + * SYM COMPLEN Component is too long. + * SYM EXISTS Already exists. + * SYM EXISTS Root exists. + * SYM LINK Bad link count. + * SYM LINK Link inc failure. + * SYM NOTFOUND Component not found. + * * Return: Success: A handle for the object. Be sure to * eventually close it. * @@ -629,9 +1059,9 @@ H5G_create (H5F_t *f, const char *name, size_t ohdr_hint) { H5G_entry_t ent; /*entry data for the new object */ H5G_entry_t *ent_ptr; /*ptr into symbol node for entry*/ - H5G_entry_t *cwd=NULL; /*ptr to CWD handle */ + H5G_entry_t *cwg=NULL; /*ptr to c.w.g. handle */ const char *rest = NULL; /*part of name not existing yet */ - H5G_entry_t dir; /*entry for dir to contain obj */ + H5G_entry_t grp; /*entry for group to contain obj*/ H5G_entry_t *ret_value=NULL; /*the object handle */ size_t nchars; /*number of characters in name */ char _comp[1024]; /*name component */ @@ -644,18 +1074,15 @@ H5G_create (H5F_t *f, const char *name, size_t ohdr_hint) HDmemset (&ent, 0, sizeof(H5G_entry_t)); /* - * Get the current working directory. + * Get the current working group. */ -#ifndef LATER - H5G_shadow_sync (f->shared->root_sym); - cwd = f->shared->root_sym; -#endif + cwg = H5G_getcwg (f); /* * Look up the name -- it shouldn't exist yet. */ - if (H5G_namei (f, cwd, name, &rest, &dir)) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_EXISTS, NULL); /*already exists*/ + if (H5G_namei (f, cwg, name, &rest, &grp)) { + HRETURN_ERROR (H5E_SYM, H5E_EXISTS, NULL); /*already exists*/ } H5ECLEAR; /*it's OK that we didn't find it*/ rest = H5G_component (rest, &nchars); @@ -667,18 +1094,18 @@ H5G_create (H5F_t *f, const char *name, size_t ohdr_hint) * it already has as a message. */ if (f->shared->root_sym->header>0) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_EXISTS, NULL); /*root exists*/ + HRETURN_ERROR (H5E_SYM, H5E_EXISTS, NULL); /*root exists*/ } if ((ent.header = H5O_new (f, 0, ohdr_hint))<0) { /* can't create header */ - HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL); + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL); } if (1!=H5O_link (f, &ent, 1)) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_LINK, NULL); /*bad link count*/ + HRETURN_ERROR (H5E_SYM, H5E_LINK, NULL); /*bad link count*/ } *(f->shared->root_sym) = ent; - if (NULL==(ret_value=H5G_shadow_open (f, &dir, f->shared->root_sym))) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL); + if (NULL==(ret_value=H5G_shadow_open (f, &grp, f->shared->root_sym))) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL); } HRETURN (ret_value); } @@ -690,10 +1117,10 @@ H5G_create (H5F_t *f, const char *name, size_t ohdr_hint) if (rest[nchars]) { if (H5G_component (rest+nchars, NULL)) { /* component not found */ - HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, NULL); + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL); } else if (nchars+1 > sizeof _comp) { /* component is too long */ - HRETURN_ERROR (H5E_DIRECTORY, H5E_COMPLEN, NULL); + HRETURN_ERROR (H5E_SYM, H5E_COMPLEN, NULL); } else { /* null terminate */ HDmemcpy (_comp, rest, nchars); @@ -706,7 +1133,7 @@ H5G_create (H5F_t *f, const char *name, size_t ohdr_hint) * Create the object header. */ if ((ent.header = H5O_new (f, 0, ohdr_hint))<0) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL); + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL); } @@ -721,28 +1148,29 @@ H5G_create (H5F_t *f, const char *name, size_t ohdr_hint) name_mesg.s = rest; if (H5O_modify (f, NO_ADDR, &ent, H5O_NAME, 0, &name_mesg)<0) { /* cannot add/change name message */ - HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL); + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL); } if (1!=H5O_link (f, &ent, 1)) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_LINK, NULL); /*bad link count*/ + HRETURN_ERROR (H5E_SYM, H5E_LINK, NULL); /*bad link count*/ } *(f->shared->root_sym) = ent; - if (NULL==(ret_value=H5G_shadow_open (f, &dir, f->shared->root_sym))) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL); + if (NULL==(ret_value=H5G_shadow_open (f, &grp, f->shared->root_sym))) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL); } HRETURN (ret_value); } else { /* - * Make sure the root directory exists. Ignore the failure if it's - * because the directory already exists. + * Make sure the root group exists. Ignore the failure if it's + * because the group already exists. */ - hbool_t update_dir = (dir.header==f->shared->root_sym->header); + hbool_t update_grp = (grp.header==f->shared->root_sym->header); herr_t status = H5G_mkroot (f, H5G_SIZE_HINT); if (status<0 && -2!=status) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL); + /* Can't create root group */ + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL); } H5ECLEAR; - if (update_dir) dir = *(f->shared->root_sym); + if (update_grp) grp = *(f->shared->root_sym); } /* @@ -750,13 +1178,13 @@ H5G_create (H5F_t *f, const char *name, size_t ohdr_hint) * entry into a symbol table. */ if (H5O_link (f, &ent, 1)<0) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_LINK, NULL); /*link inc failure*/ + HRETURN_ERROR (H5E_SYM, H5E_LINK, NULL); /*link inc failure*/ } - if (NULL==(ent_ptr=H5G_stab_insert (f, &dir, rest, &ent))) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL); /*can't insert*/ + if (NULL==(ent_ptr=H5G_stab_insert (f, &grp, rest, &ent))) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL); /*can't insert*/ } - if (NULL==(ret_value=H5G_shadow_open (f, &dir, ent_ptr))) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL); /*can't open object*/ + if (NULL==(ret_value=H5G_shadow_open (f, &grp, ent_ptr))) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL); /*can't open object*/ } FUNC_LEAVE (ret_value); } @@ -776,6 +1204,11 @@ H5G_create (H5F_t *f, const char *name, size_t ohdr_hint) * structs. The structs that are returned should be * released by calling H5G_close(). * + * Errors: + * SYM BADVALUE Check args. + * SYM CANTOPENOBJ Can't open obj. + * SYM NOTFOUND Object not found. + * * Return: Success: Ptr to a handle for the object. * * Failure: NULL @@ -792,32 +1225,29 @@ H5G_open (H5F_t *f, const char *name) { H5G_entry_t *ent=NULL; H5G_entry_t *ret_value=NULL; - H5G_entry_t dir; - H5G_entry_t *cwd=NULL; + H5G_entry_t grp; + H5G_entry_t *cwg=NULL; FUNC_ENTER (H5G_open, NULL, NULL); /* check args */ assert (f); if (!name || !*name) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_BADVALUE, NULL); + HRETURN_ERROR (H5E_SYM, H5E_BADVALUE, NULL); } - /* Get CWD */ -#ifndef LATER - H5G_shadow_sync (f->shared->root_sym); - cwd = f->shared->root_sym; -#endif - assert (cwd || '/'==*name); + /* Get CWG */ + cwg = H5G_getcwg (f); + assert (cwg || '/'==*name); if (f->shared->root_sym->header<=0) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, NULL); /*object not found*/ + HRETURN_ERROR (H5E_SYM, 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==(ent=H5G_namei (f, cwg, name, NULL, &grp))) { + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL); /*object not found*/ } - if (NULL==(ret_value=H5G_shadow_open (f, &dir, ent))) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTOPENOBJ, NULL); + if (NULL==(ret_value=H5G_shadow_open (f, &grp, ent))) { + HRETURN_ERROR (H5E_SYM, H5E_CANTOPENOBJ, NULL); /*can't open obj*/ } FUNC_LEAVE (ret_value); @@ -830,6 +1260,9 @@ H5G_open (H5F_t *f, const char *name) * * Purpose: Closes an object that was open for modification. * + * Errors: + * SYM CANTFLUSH Can't close object. + * * Return: Success: SUCCEED * * Failure: FAIL @@ -849,6 +1282,7 @@ H5G_close (H5F_t *f, H5G_entry_t *ent) assert (f); if (ent && H5G_shadow_close (f, ent)<0) { + /* Can't close object */ HRETURN_ERROR (H5E_SYM, H5E_CANTFLUSH, FAIL); } @@ -861,22 +1295,21 @@ H5G_close (H5F_t *f, H5G_entry_t *ent) * * Purpose: Finds an object with the specified NAME in file F. If * the name is relative then it is interpretted relative - * to CWD, a symbol table entry for a symbol table. On - * successful return, DIR_ENT (if non-null) will be - * initialized with the symbol table information for the - * directory in which the object appears (or all zero if - * the returned object is the root object) and ENT will - * be initialized with the symbol table entry for the - * object (ENT is optional when the caller is interested - * only in the existence of the object). + * to the current working group. On successful return, + * GRP_ENT (if non-null) will be initialized with the symbol + * table information for the group in which the object + * appears (or all zero if the returned object is the root + * object) and ENT will be initialized with the symbol table + * entry for the object (ENT is optional when the caller is + * interested only in the existence of the object). * * This function will fail if the root object is * requested and there is none. * * Errors: - * DIRECTORY NOTFOUND Object not found. + * SYM NOTFOUND Object not found. * - * Return: Success: SUCCEED with DIR_ENT and ENT initialized. ENT + * Return: Success: SUCCEED with GRP_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 @@ -888,7 +1321,7 @@ H5G_close (H5F_t *f, H5G_entry_t *ent) * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Aug 12 1997 * * Modifications: @@ -896,23 +1329,25 @@ H5G_close (H5F_t *f, H5G_entry_t *ent) *------------------------------------------------------------------------- */ herr_t -H5G_find (H5F_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent, - const char *name, H5G_entry_t *ent) +H5G_find (H5F_t *f, const char *name, H5G_entry_t *grp_ent, H5G_entry_t *ent) { H5G_entry_t *ent_p = NULL; + H5G_entry_t *cwg = NULL; + FUNC_ENTER (H5G_find, NULL, FAIL); /* check args */ assert (f); assert (name && *name); - assert (cwd || '/'==*name); + cwg = H5G_getcwg (f); + assert (cwg || '/'==*name); if (f->shared->root_sym->header<=0) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, FAIL); /*object not found*/ + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); /*object not found*/ } - if (NULL==(ent_p=H5G_namei (f, cwd, name, NULL, dir_ent))) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, FAIL); /*object not found*/ + if (NULL==(ent_p=H5G_namei (f, cwg, name, NULL, grp_ent))) { + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); /*object not found*/ } if (ent) *ent = *ent_p; diff --git a/src/H5Gent.c b/src/H5Gent.c index f9ca290..b5cddce 100644 --- a/src/H5Gent.c +++ b/src/H5Gent.c @@ -410,7 +410,7 @@ H5G_ent_encode (H5F_t *f, uint8 **pp, H5G_entry_t *ent) * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Aug 29 1997 * * Modifications: diff --git a/src/H5Gnode.c b/src/H5Gnode.c index 84dc0e5..58c924c 100644 --- a/src/H5Gnode.c +++ b/src/H5Gnode.c @@ -39,29 +39,32 @@ #define PABLO_MASK H5G_node_mask /* PRIVATE PROTOTYPES */ -static herr_t H5G_node_decode_key (H5F_t *f, uint8 *raw, void *_key); -static herr_t H5G_node_encode_key (H5F_t *f, uint8 *raw, void *_key); +static herr_t H5G_node_decode_key (H5F_t *f, H5B_t *bt, uint8 *raw, + void *_key); +static herr_t H5G_node_encode_key (H5F_t *f, H5B_t *bt, uint8 *raw, + void *_key); static size_t H5G_node_size (H5F_t *f); static haddr_t H5G_node_new (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key); static herr_t H5G_node_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5G_node_t *sym); -static H5G_node_t *H5G_node_load (H5F_t *f, haddr_t addr, void *_data); +static H5G_node_t *H5G_node_load (H5F_t *f, haddr_t addr, void *_udata1, + void *_udata2); static intn H5G_node_cmp (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key); static herr_t H5G_node_found (H5F_t *f, haddr_t addr, const void *_lt_key, void *_udata, const void *_rt_key); -static haddr_t H5G_node_insert (H5F_t *f, haddr_t addr, intn *anchor, +static haddr_t H5G_node_insert (H5F_t *f, haddr_t addr, H5B_ins_t *anchor, void *_lt_key, hbool_t *lt_key_changed, void *_md_key, void *_udata, void *_rt_key, hbool_t *rt_key_changed); static herr_t H5G_node_list (H5F_t *f, haddr_t addr, void *_udata); -static size_t H5G_node_sizeof_rkey (H5F_t *f); +static size_t H5G_node_sizeof_rkey (H5F_t *f, const void *_udata); /* H5G inherits cache-like properties from H5AC */ const H5AC_class_t H5AC_SNODE[1] = {{ - (void*(*)(H5F_t*,haddr_t,void*))H5G_node_load, + (void*(*)(H5F_t*,haddr_t,void*,void*))H5G_node_load, (herr_t(*)(H5F_t*,hbool_t,haddr_t,void*))H5G_node_flush, }}; @@ -74,6 +77,8 @@ H5B_class_t H5B_SNODE[1] = {{ H5G_node_cmp, /*cmp */ H5G_node_found, /*found */ H5G_node_insert, /*insert */ + TRUE, /*follow min branch? */ + TRUE, /*follow max branch? */ H5G_node_list, /*list */ H5G_node_decode_key, /*decode */ H5G_node_encode_key, /*encode */ @@ -102,7 +107,7 @@ static intn interface_initialize_g = FALSE; *------------------------------------------------------------------------- */ static size_t -H5G_node_sizeof_rkey (H5F_t *f) +H5G_node_sizeof_rkey (H5F_t *f, const void *udata __attribute__((unused))) { return H5F_SIZEOF_OFFSET(f); } @@ -126,7 +131,7 @@ H5G_node_sizeof_rkey (H5F_t *f) *------------------------------------------------------------------------- */ static herr_t -H5G_node_decode_key (H5F_t *f, uint8 *raw, void *_key) +H5G_node_decode_key (H5F_t *f, H5B_t *bt, uint8 *raw, void *_key) { H5G_node_key_t *key = (H5G_node_key_t *)_key; @@ -160,7 +165,7 @@ H5G_node_decode_key (H5F_t *f, uint8 *raw, void *_key) *------------------------------------------------------------------------- */ static herr_t -H5G_node_encode_key (H5F_t *f, uint8 *raw, void *_key) +H5G_node_encode_key (H5F_t *f, H5B_t *bt, uint8 *raw, void *_key) { H5G_node_key_t *key = (H5G_node_key_t *)_key; @@ -378,12 +383,12 @@ H5G_node_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5G_node_t *sym) *------------------------------------------------------------------------- */ static H5G_node_t * -H5G_node_load (H5F_t *f, haddr_t addr, void *_udata) +H5G_node_load (H5F_t *f, haddr_t addr, void *_udata1, void *_udata2) { H5G_node_t *sym = NULL; size_t size = 0; uint8 *buf = NULL, *p = NULL; - H5G_ac_ud1_t *ac_udata = (H5G_ac_ud1_t*)_udata; + H5G_ac_ud1_t *ac_udata = (H5G_ac_ud1_t*)_udata1; H5G_node_t *ret_value = NULL; /*for error handling*/ FUNC_ENTER (H5G_node_load, NULL, NULL); @@ -394,6 +399,7 @@ H5G_node_load (H5F_t *f, haddr_t addr, void *_udata) assert (f); assert (addr>=0); assert (ac_udata); + assert (NULL==_udata2); /* * Initialize variables. @@ -453,21 +459,21 @@ H5G_node_load (H5F_t *f, haddr_t addr, void *_udata) /*------------------------------------------------------------------------- * Function: H5G_node_cmp * - * Purpose: Compares two keys from a B-tree node (LEFT and RIGHT) + * Purpose: Compares two keys from a B-tree node (LT_KEY and RT_KEY) * against another key (not necessarily the same type) * pointed to by UDATA. * * Return: Success: negative if the UDATA key is less than - * or equal to the LEFT key. + * or equal to the LT_KEY * * positive if the UDATA key is greater - * than the RIGHT key. + * than the RT_KEY. * * zero if the UDATA key falls between - * the LEFT key (exclusive) and the - * RIGHT key (inclusive). + * the LT_KEY (exclusive) and the + * RT_KEY (inclusive). * - * Failure: FAIL (same as LT < RT) + * Failure: FAIL (same as UDATA < LT_KEY) * * Programmer: Robb Matzke * matzke@llnl.gov @@ -551,13 +557,13 @@ H5G_node_found (H5F_t *f, haddr_t addr, const void *_lt_key, assert (addr>=0); assert (bt_udata); - ac_udata.dir_addr = bt_udata->dir_addr; + ac_udata.grp_addr = bt_udata->grp_addr; ac_udata.heap_addr = bt_udata->heap_addr; /* * Load the symbol table node for exclusive access. */ - if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, &ac_udata))) { + if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, &ac_udata, NULL))) { HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL); } @@ -656,7 +662,7 @@ done: *------------------------------------------------------------------------- */ static haddr_t -H5G_node_insert (H5F_t *f, haddr_t addr, intn *anchor, +H5G_node_insert (H5F_t *f, haddr_t addr, H5B_ins_t *anchor, void *_lt_key, hbool_t *lt_key_changed, void *_md_key, void *_udata, void *_rt_key, hbool_t *rt_key_changed) @@ -693,19 +699,11 @@ H5G_node_insert (H5F_t *f, haddr_t addr, intn *anchor, bt_udata->entry_ptr = NULL; /* - * Symbol tables are always split so the new symbol table node is - * to the right of the old one. - */ - *anchor = H5B_ANCHOR_LT; - *lt_key_changed = FALSE; - *rt_key_changed = FALSE; - - /* * Load the symbol node. */ - ac_udata.dir_addr = bt_udata->dir_addr; + ac_udata.grp_addr = bt_udata->grp_addr; ac_udata.heap_addr = bt_udata->heap_addr; - if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, &ac_udata))) { + if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, &ac_udata, NULL))) { HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL); } @@ -746,12 +744,13 @@ H5G_node_insert (H5F_t *f, haddr_t addr, intn *anchor, * node and return the address of the new right node (the * left node is at the same address as the original node). */ + *anchor = H5B_INS_RIGHT; /* The right node */ 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, &ac_udata))) { + if (NULL==(snrt=H5AC_find (f, H5AC_SNODE, new_node, &ac_udata, NULL))) { HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL); } HDmemcpy (snrt->entry, sn->entry + H5G_NODE_K(f), @@ -789,6 +788,7 @@ H5G_node_insert (H5F_t *f, haddr_t addr, intn *anchor, } else { /* Where to insert the new entry? */ + *anchor = H5B_INS_NOOP; sn->dirty = TRUE; insert_into = sn; insert_addr = addr; @@ -809,7 +809,7 @@ H5G_node_insert (H5F_t *f, haddr_t addr, intn *anchor, H5G_shadow_move (f, bt_udata->entry.shadow, bt_udata->name, insert_into->entry + idx, - bt_udata->dir_addr); + bt_udata->grp_addr); } /* Move entries */ @@ -837,7 +837,8 @@ done: if (H5AC_unprotect (f, H5AC_SNODE, addr, sn)<0) { HRETURN_ERROR (H5E_SYM, H5E_PROTECT, FAIL); } - if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, insert_addr, &ac_udata))) { + if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, insert_addr, &ac_udata, + NULL))) { HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL); } assert (sn==bt_udata->node_ptr); @@ -852,7 +853,7 @@ done: /*------------------------------------------------------------------------- * Function: H5G_node_list * - * Purpose: This function gets called during a directory list operation. + * Purpose: This function gets called during a group list operation. * It should fill in data in the UDATA struct. * * Return: Success: SUCCEED @@ -886,9 +887,9 @@ H5G_node_list (H5F_t *f, haddr_t addr, void *_udata) assert (addr>=0); assert (bt_udata); - ac_udata.dir_addr = bt_udata->dir_addr; + ac_udata.grp_addr = bt_udata->grp_addr; ac_udata.heap_addr = bt_udata->heap_addr; - if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, &ac_udata))) { + if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, &ac_udata, NULL))) { HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL); } @@ -978,21 +979,21 @@ H5G_node_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent, * 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 + * supply `-1' as the group address which causes no open objects to be * associated with the node. For that reason, we flush this node from the * cache when we're done so if some later caller knows the header address * they'll be able to access the open objects. */ - ac_udata.dir_addr = -1; + ac_udata.grp_addr = -1; ac_udata.heap_addr = heap; /* * If we couldn't load the symbol table node, then try loading the * B-tree node. */ - if (NULL==(sn=H5AC_find(f, H5AC_SNODE, addr, &ac_udata))) { + if (NULL==(sn=H5AC_find(f, H5AC_SNODE, addr, &ac_udata, NULL))) { H5ECLEAR; /*discard that error*/ - status = H5B_debug (f, addr, stream, indent, fwidth, H5B_SNODE); + status = H5B_debug (f, addr, stream, indent, fwidth, H5B_SNODE, NULL); if (status<0) HRETURN_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL); HRETURN (SUCCEED); } diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h index e0d6f8d..9421541 100644 --- a/src/H5Gpkg.h +++ b/src/H5Gpkg.h @@ -20,7 +20,7 @@ #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_SIZE_HINT 1024 /*default root grp size hint */ #define H5G_NODE_K(F) ((F)->shared->file_create_parms.sym_leaf_k) #define H5G_NODE_SIZEOF_HDR(F) (H5G_NODE_SIZEOF_MAGIC + 4) #define H5G_DEFAULT_ROOT_SIZE 32 @@ -44,7 +44,7 @@ struct 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. + * table or group. */ typedef struct H5G_node_t { hbool_t dirty; /*has cache been modified? */ @@ -61,7 +61,7 @@ typedef struct H5G_node_t { */ struct H5G_shadow_t { char *name; /*name for this entry */ - haddr_t dir_addr; /*hdr addr for dir containing shadow */ + haddr_t grp_addr; /*hdr addr for group containing shadow */ uintn nrefs; /*reference counter */ H5G_entry_t entry; /*local copy of symbol table entry */ H5G_entry_t *main; /*main entry in stab node if cached */ @@ -78,6 +78,16 @@ typedef struct H5G_node_key_t { } H5G_node_key_t; /* + * Each file has a stack of open groups with the latest entry on the + * stack the current working group. If the stack is empty then the + * current working group is the root object. + */ +typedef struct H5G_cwgstk_t { + H5G_entry_t *handle; /*a handle to an open group */ + struct H5G_cwgstk_t *next; /*next item (earlier) on stack */ +} H5G_cwgstk_t; + +/* * These operations can be passed down from the H5G_stab layer to the * H5G_node layer through the B-tree layer. */ @@ -96,7 +106,7 @@ 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 grp_addr; /*symbol table header address */ haddr_t heap_addr; /*symbol table heap address */ /* downward for INSERT */ @@ -119,7 +129,7 @@ typedef struct H5G_bt_ud2_t { H5G_entry_t *entry; /*array of entries, alloc'd by caller */ char **name; /*array of string ptrs, allocd by caller*/ intn maxentries; /*size of the ADDR and NAME arrays */ - haddr_t dir_addr; /*symbol table header address */ + haddr_t grp_addr; /*symbol table header address */ haddr_t heap_addr; /*heap address */ /* upward */ @@ -137,15 +147,15 @@ extern H5B_class_t H5B_SNODE[1]; */ typedef struct H5G_ac_ud1_t { haddr_t heap_addr; - haddr_t dir_addr; + haddr_t grp_addr; } H5G_ac_ud1_t; /* The cache subclass */ extern const H5AC_class_t H5AC_SNODE[1]; /* - * Functions that understand symbol tables but not directories. The - * functions that understand directories are exported to the rest of + * Functions that understand symbol tables but not names. The + * functions that understand names are exported to the rest of * the library and appear in H5Gprivate.h. */ haddr_t H5G_stab_new (H5F_t *f, H5G_entry_t *self, size_t init); @@ -160,7 +170,7 @@ intn H5G_stab_list (H5F_t *f, H5G_entry_t *self, intn maxentries, * Functions that understand shadow entries. */ herr_t H5G_shadow_sync (H5G_entry_t *ent); -H5G_entry_t *H5G_shadow_open (H5F_t *f, H5G_entry_t *dir, +H5G_entry_t *H5G_shadow_open (H5F_t *f, H5G_entry_t *grp, H5G_entry_t *ent); herr_t H5G_shadow_close (H5F_t *f, H5G_entry_t *ent); hbool_t H5G_shadow_p (H5G_entry_t *ent); @@ -170,7 +180,7 @@ herr_t H5G_shadow_assoc_node (H5F_t *f, H5G_node_t *sym, H5G_shadow_t *H5G_shadow_list (H5F_t *f, haddr_t stab_header_addr); herr_t H5G_shadow_move (H5F_t *f, H5G_shadow_t *shadow, const char *new_name, H5G_entry_t *new_entry, - haddr_t dir_addr); + haddr_t grp_addr); /* * Functions that understand symbol table entries. diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h index 79666e7..4641d90 100644 --- a/src/H5Gprivate.h +++ b/src/H5Gprivate.h @@ -82,14 +82,15 @@ typedef struct H5G_entry_t H5G_entry_t; * Library prototypes... These are the ones that other packages routinely * call. */ -H5G_entry_t *H5G_mkdir (H5F_t *f, const char *name, size_t size_hint); -herr_t H5G_pushd (H5F_t *f, const char *name); -herr_t H5G_popd (H5F_t *f); +H5G_entry_t *H5G_new (H5F_t *f, const char *name, size_t size_hint); +herr_t H5G_set (H5F_t *f, const char *name); +herr_t H5G_push (H5F_t *f, const char *name); +herr_t H5G_pop (H5F_t *f); H5G_entry_t *H5G_create (H5F_t *f, const char *name, size_t ohdr_hint); H5G_entry_t *H5G_open (H5F_t *f, const char *name); herr_t H5G_close (H5F_t *f, H5G_entry_t *ent); -herr_t H5G_find (H5F_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent, - const char *name, H5G_entry_t *ent); +herr_t H5G_find (H5F_t *f, const char *name, H5G_entry_t *grp_ent, + H5G_entry_t *ent); herr_t H5G_ent_encode (H5F_t *f, uint8 **pp, H5G_entry_t *ent); herr_t H5G_ent_decode (H5F_t *f, uint8 **pp, H5G_entry_t *ent); diff --git a/src/H5Gpublic.h b/src/H5Gpublic.h index 049c823..e546e6d 100644 --- a/src/H5Gpublic.h +++ b/src/H5Gpublic.h @@ -19,15 +19,19 @@ #define _H5Gpublic_H /* Public headers needed by this file */ +#include <sys/types.h> #include <H5public.h> - -/* Default root directory size */ -#define H5G_DEFAULT_ROOT SIZE 256 +#include <H5Apublic.h> #ifdef __cplusplus extern "C" { #endif +herr_t H5Gnew (hid_t file, const char *name, size_t size_hint); +herr_t H5Gset (hid_t file, const char *name); +herr_t H5Gpush (hid_t file, const char *name); +herr_t H5Gpop (hid_t file); + #ifdef __cplusplus } #endif diff --git a/src/H5Gshad.c b/src/H5Gshad.c index 9bf80d8..875f880 100644 --- a/src/H5Gshad.c +++ b/src/H5Gshad.c @@ -29,7 +29,7 @@ static hbool_t interface_initialize_g = FALSE; typedef struct H5G_hash_t { - haddr_t dir_addr; + haddr_t grp_addr; H5G_shadow_t *head; struct H5G_hash_t *next; struct H5G_hash_t *prev; @@ -81,15 +81,15 @@ H5G_shadow_check (H5F_t *f) shadow_error = TRUE; } - /* Valid directory addresses */ - if (shadow->dir_addr<0 || (shadow->dir_addr==0 && idx!=0)) { - fprintf (stderr, "dir_addr=%lu, ", - (unsigned long)(shadow->dir_addr)); + /* Valid group addresses */ + if (shadow->grp_addr<0 || (shadow->grp_addr==0 && idx!=0)) { + fprintf (stderr, "grp_addr=%lu, ", + (unsigned long)(shadow->grp_addr)); shadow_error = TRUE; - } else if (shadow->dir_addr!=hash->dir_addr) { - fprintf (stderr, "dir_addr=%lu (not %lu), ", - (unsigned long)(shadow->dir_addr), - (unsigned long)(hash->dir_addr)); + } else if (shadow->grp_addr!=hash->grp_addr) { + fprintf (stderr, "grp_addr=%lu (not %lu), ", + (unsigned long)(shadow->grp_addr), + (unsigned long)(hash->grp_addr)); } /* Linked to symbol table entry */ @@ -107,9 +107,9 @@ H5G_shadow_check (H5F_t *f) /* If an error occurred then print other info */ if (shadow_error) { - fprintf (stderr, "idx=%u, shadow=0x%08lx, dir_addr=%lu\n", + fprintf (stderr, "idx=%u, shadow=0x%08lx, grp_addr=%lu\n", idx, (unsigned long)shadow, - (unsigned long)(shadow->dir_addr)); + (unsigned long)(shadow->grp_addr)); nerrors++; } } @@ -247,7 +247,7 @@ H5G_shadow_sync (H5G_entry_t *ent) * Function: H5G_shadow_list * * Purpose: Returns a doubly linked list of shadows for the symbol - * table whose header address is DIR_ADDR. + * table whose header address is GRP_ADDR. * * Return: Success: Ptr shadow list or null. * @@ -261,15 +261,15 @@ H5G_shadow_sync (H5G_entry_t *ent) *------------------------------------------------------------------------- */ H5G_shadow_t * -H5G_shadow_list (H5F_t *f, haddr_t dir_addr) +H5G_shadow_list (H5F_t *f, haddr_t grp_addr) { - uintn idx = dir_addr % f->shared->nshadows; + uintn idx = grp_addr % f->shared->nshadows; H5G_hash_t *bucket = NULL; FUNC_ENTER (H5G_shadows, NULL, NULL); for (bucket=f->shared->shadow[idx]; bucket; bucket=bucket->next) { - if (bucket->dir_addr==dir_addr) { + if (bucket->grp_addr==grp_addr) { HRETURN (bucket->head); } } @@ -317,7 +317,7 @@ H5G_shadow_assoc_node (H5F_t *f, H5G_node_t *sym, H5G_ac_ud1_t *ac_udata) H5G_shadow_check (f); #endif - if ((shadow=H5G_shadow_list (f, ac_udata->dir_addr))) { + if ((shadow=H5G_shadow_list (f, ac_udata->grp_addr))) { heap_addr = ac_udata->heap_addr; while (i<sym->nsyms && shadow) { @@ -352,7 +352,7 @@ H5G_shadow_assoc_node (H5F_t *f, H5G_node_t *sym, H5G_ac_ud1_t *ac_udata) * object, open the object (again) and return a handle * to it. * - * DIR can be the null pointer if `ent' is the root entry. + * GRP can be the null pointer if `ent' is the root entry. * * Return: Success: Handle to open object * @@ -366,7 +366,7 @@ H5G_shadow_assoc_node (H5F_t *f, H5G_node_t *sym, H5G_ac_ud1_t *ac_udata) *------------------------------------------------------------------------- */ H5G_entry_t * -H5G_shadow_open (H5F_t *f, H5G_entry_t *dir, H5G_entry_t *ent) +H5G_shadow_open (H5F_t *f, H5G_entry_t *grp, H5G_entry_t *ent) { H5G_shadow_t *shadow = NULL; H5O_stab_t stab; @@ -376,15 +376,15 @@ H5G_shadow_open (H5F_t *f, H5G_entry_t *dir, H5G_entry_t *ent) uintn idx; H5O_name_t name_mesg = {NULL}; H5G_entry_t *ret_value = NULL; - haddr_t dir_addr; + haddr_t grp_addr; FUNC_ENTER (H5G_shadow_open, NULL, NULL); /* check args */ assert (f); - assert (ent==f->shared->root_sym || dir); + assert (ent==f->shared->root_sym || grp); assert (ent); - dir_addr = dir ? dir->header : 0; + grp_addr = grp ? grp->header : 0; if ((shadow = ent->shadow)) { /* @@ -396,7 +396,7 @@ H5G_shadow_open (H5F_t *f, H5G_entry_t *dir, H5G_entry_t *ent) shadow = H5MM_xcalloc (1, sizeof(H5G_shadow_t)); - if (ent==f->shared->root_sym && 0==dir_addr) { + if (ent==f->shared->root_sym && 0==grp_addr) { /* * We're opening the root entry. */ @@ -411,7 +411,7 @@ H5G_shadow_open (H5F_t *f, H5G_entry_t *dir, H5G_entry_t *ent) /* * Some entry other than the root. */ - if (NULL==H5O_read (f, NO_ADDR, dir, H5O_STAB, 0, &stab)) { + if (NULL==H5O_read (f, NO_ADDR, grp, H5O_STAB, 0, &stab)) { HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, NULL); } if (NULL==(s=H5H_peek (f, stab.heap_addr, ent->name_off))) { @@ -428,18 +428,18 @@ H5G_shadow_open (H5F_t *f, H5G_entry_t *dir, H5G_entry_t *ent) shadow->nrefs = 1; shadow->entry = *ent; shadow->entry.dirty = FALSE; - shadow->dir_addr = dir_addr; + shadow->grp_addr = grp_addr; /* * Link it into the shadow heap */ - idx = dir_addr % f->shared->nshadows; + idx = grp_addr % f->shared->nshadows; for (hash=f->shared->shadow[idx]; hash; hash=hash->next) { - if (hash->dir_addr==dir_addr) break; + if (hash->grp_addr==grp_addr) break; } if (!hash) { hash = H5MM_xcalloc (1, sizeof(H5G_hash_t)); - hash->dir_addr = dir_addr; + hash->grp_addr = grp_addr; hash->next = f->shared->shadow[idx]; f->shared->shadow[idx] = hash; if (hash->next) hash->next->prev = hash; @@ -524,7 +524,7 @@ H5G_shadow_close (H5F_t *f, H5G_entry_t *ent) /* clean the shadow */ if (1==shadow->nrefs && ent->dirty) { if (!shadow->main && - NULL==H5G_stab_find (f, shadow->dir_addr, NULL, shadow->name)) { + NULL==H5G_stab_find (f, shadow->grp_addr, NULL, shadow->name)) { HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); } assert (shadow->main); @@ -540,9 +540,9 @@ H5G_shadow_close (H5F_t *f, H5G_entry_t *ent) H5G_shadow_dissociate (ent); /* find symtabs shadow list */ - idx = shadow->dir_addr % f->shared->nshadows; + idx = shadow->grp_addr % f->shared->nshadows; for (hash=f->shared->shadow[idx]; hash; hash=hash->next) { - if (hash->dir_addr==shadow->dir_addr) break; + if (hash->grp_addr==shadow->grp_addr) break; } assert (hash); @@ -577,7 +577,7 @@ H5G_shadow_close (H5F_t *f, H5G_entry_t *ent) * Function: H5G_shadow_move * * Purpose: Moves the SHADOW for some entry to correspond to a - * NEW_ENTRY. The DIR_ADDR is the address for the directory + * NEW_ENTRY. The GRP_ADDR is the address for the group * which contains NEW_ENTRY. * * Return: Success: SUCCEED @@ -593,7 +593,7 @@ H5G_shadow_close (H5F_t *f, H5G_entry_t *ent) */ herr_t H5G_shadow_move (H5F_t *f, H5G_shadow_t *shadow, const char *new_name, - H5G_entry_t *new_entry, haddr_t dir_addr) + H5G_entry_t *new_entry, haddr_t grp_addr) { H5G_hash_t *hash; uintn idx; @@ -602,29 +602,29 @@ H5G_shadow_move (H5F_t *f, H5G_shadow_t *shadow, const char *new_name, assert (shadow); assert (new_entry); - assert (dir_addr>0); + assert (grp_addr>0); - if (0==shadow->dir_addr) { + if (0==shadow->grp_addr) { /* * We're moving the shadow for the root object. This simplifies things * greatly since it implies that this is the only shadow currently * defined for the entire file. */ - idx = dir_addr % f->shared->nshadows; + idx = grp_addr % f->shared->nshadows; assert (NULL==f->shared->shadow[idx]); /*Nothing at new idx... */ hash = f->shared->shadow[0]; assert (hash); /*..but root idx has something. */ - assert (0==hash->dir_addr); /*..and it's the root something */ + assert (0==hash->grp_addr); /*..and it's the root something */ assert (NULL==hash->next); /*..and just that */ assert (hash->head==shadow); /*..and exactly that */ /* Move root entry to new hash bucket */ f->shared->shadow[idx] = hash; f->shared->shadow[0] = NULL; - hash->dir_addr = dir_addr; + hash->grp_addr = grp_addr; /* Associate SHADOW with NEW_ENTRY */ - shadow->dir_addr = dir_addr; + shadow->grp_addr = grp_addr; shadow->main = new_entry; new_entry->shadow = shadow; @@ -636,7 +636,7 @@ H5G_shadow_move (H5F_t *f, H5G_shadow_t *shadow, const char *new_name, /* * Other shadows never move. */ - assert (shadow->dir_addr==dir_addr); + assert (shadow->grp_addr==grp_addr); shadow->main = new_entry; new_entry->shadow = shadow; } @@ -682,7 +682,7 @@ H5G_shadow_flush (H5F_t *f, hbool_t invalidate) */ if (shadow->entry.dirty) { if (!shadow->main && - NULL==H5G_stab_find (f, shadow->dir_addr, NULL, + NULL==H5G_stab_find (f, shadow->grp_addr, NULL, shadow->name)) { HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); } @@ -698,12 +698,12 @@ H5G_shadow_flush (H5F_t *f, hbool_t invalidate) * some object before closing the file. Since this is hard to * debug, we'll be nice and print the names here. We don't know * the full name, but we'll print the file address (relative to - * the boot block) of the object header for the directory that + * the boot block) of the object header for the group that * contains the open object. */ if (invalidate) { - fprintf (stderr, "Open object <%lu>/%s", - (unsigned long)(shadow->dir_addr), + fprintf (stderr, "Warning: open object <%lu>/%s", + (unsigned long)(shadow->grp_addr), shadow->name); if (shadow->nrefs>1) { fprintf (stderr, " (%d times)", shadow->nrefs); diff --git a/src/H5Gstab.c b/src/H5Gstab.c index b600e90..7acaa13 100644 --- a/src/H5Gstab.c +++ b/src/H5Gstab.c @@ -87,14 +87,14 @@ H5G_stab_new (H5F_t *f, H5G_entry_t *self, size_t init) } /* Create the B-tree */ - if ((stab.btree_addr = H5B_new (f, H5B_SNODE))<0) { + if ((stab.btree_addr = H5B_new (f, H5B_SNODE, NULL))<0) { HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); /*can't create B-tree*/ } /* * Create symbol table object header. It has a zero link count * since nothing refers to it yet. The link count will be - * incremented if the object is added to the directory hierarchy. + * incremented if the object is added to the group directed graph. */ if ((addr = H5O_new (f, 0, 4+2*H5F_SIZEOF_OFFSET(f)))<0) { HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); /*can't create header*/ @@ -169,7 +169,7 @@ H5G_stab_find (H5F_t *f, haddr_t addr, H5G_entry_t *self, udata.operation = H5G_OPER_FIND; udata.name = name; udata.heap_addr = stab.heap_addr; - udata.dir_addr = addr; + udata.grp_addr = addr; udata.node_ptr = NULL; /* search the B-tree */ @@ -245,7 +245,7 @@ H5G_stab_insert (H5F_t *f, H5G_entry_t *self, const char *name, udata.operation = H5G_OPER_INSERT; udata.name = name; udata.heap_addr = stab.heap_addr; - udata.dir_addr = self->header; + udata.grp_addr = self->header; udata.entry = *ent; udata.entry.name_off = -1; udata.node_ptr = NULL; @@ -326,7 +326,7 @@ H5G_stab_list (H5F_t *f, H5G_entry_t *self, intn maxentries, } udata.entry = entries; udata.name = names; - udata.dir_addr = self->header; + udata.grp_addr = self->header; udata.heap_addr = stab.heap_addr; udata.maxentries = maxentries; udata.nsyms = 0; @@ -45,14 +45,14 @@ typedef struct H5H_t { } H5H_t; /* PRIVATE PROTOTYPES */ -static H5H_t *H5H_load (H5F_t *f, haddr_t addr, void *udata); +static H5H_t *H5H_load (H5F_t *f, haddr_t addr, void *udata1, void *udata2); static herr_t H5H_flush (H5F_t *f, hbool_t dest, haddr_t addr, H5H_t *heap); /* * H5H inherits cache-like properties from H5AC */ static const H5AC_class_t H5AC_HEAP[1] = {{ - (void*(*)(H5F_t*,haddr_t,void*))H5H_load, + (void*(*)(H5F_t*,haddr_t,void*,void*))H5H_load, (herr_t(*)(H5F_t*,hbool_t,haddr_t,void*))H5H_flush, }}; @@ -161,7 +161,7 @@ H5H_new (H5F_t *f, H5H_type_t heap_type, size_t size_hint) *------------------------------------------------------------------------- */ static H5H_t * -H5H_load (H5F_t *f, haddr_t addr, void *udata) +H5H_load (H5F_t *f, haddr_t addr, void *udata1, void *udata2) { uint8 hdr[20], *p; H5H_t *heap=NULL; @@ -175,7 +175,8 @@ H5H_load (H5F_t *f, haddr_t addr, void *udata) assert (f); assert (addr>0); assert (H5H_SIZEOF_HDR(f) <= sizeof hdr); - assert (!udata); + assert (!udata1); + assert (!udata2); if (H5F_block_read (f, addr, H5H_SIZEOF_HDR(f), hdr)<0) { HRETURN_ERROR (H5E_HEAP, H5E_READERROR, NULL); @@ -395,7 +396,7 @@ H5H_read (H5F_t *f, haddr_t addr, off_t offset, size_t size, void *buf) assert (addr>0); assert (offset>=0); - if (NULL==(heap=H5AC_find (f, H5AC_HEAP, addr, NULL))) { + if (NULL==(heap=H5AC_find (f, H5AC_HEAP, addr, NULL, NULL))) { HRETURN_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL); } assert (offset<heap->mem_alloc); @@ -455,7 +456,7 @@ H5H_peek (H5F_t *f, haddr_t addr, off_t offset) assert (addr>0); assert (offset>=0); - if (NULL==(heap=H5AC_find (f, H5AC_HEAP, addr, NULL))) { + if (NULL==(heap=H5AC_find (f, H5AC_HEAP, addr, NULL, NULL))) { HRETURN_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL); } assert (offset<heap->mem_alloc); @@ -536,7 +537,7 @@ H5H_insert (H5F_t *f, haddr_t addr, size_t buf_size, const void *buf) need = buf_size; H5H_ALIGN (need); - if (NULL==(heap=H5AC_find (f, H5AC_HEAP, addr, NULL))) { + if (NULL==(heap=H5AC_find (f, H5AC_HEAP, addr, NULL, NULL))) { HRETURN_ERROR (H5E_HEAP, H5E_CANTLOAD, FAIL); } heap->dirty += 1; @@ -686,7 +687,7 @@ H5H_write (H5F_t *f, haddr_t addr, off_t offset, size_t size, assert (offset>=0); assert (buf); - if (NULL==(heap=H5AC_find (f, H5AC_HEAP, addr, NULL))) { + if (NULL==(heap=H5AC_find (f, H5AC_HEAP, addr, NULL, NULL))) { HRETURN_ERROR (H5E_HEAP, H5E_CANTLOAD, FAIL); } assert (offset<heap->mem_alloc); @@ -748,7 +749,7 @@ H5H_remove (H5F_t *f, haddr_t addr, off_t offset, size_t size) assert (offset>=0); assert (size>0); - if (NULL==(heap=H5AC_find (f, H5AC_HEAP, addr, NULL))) { + if (NULL==(heap=H5AC_find (f, H5AC_HEAP, addr, NULL, NULL))) { HRETURN_ERROR (H5E_HEAP, H5E_CANTLOAD, FAIL); } assert (offset<heap->mem_alloc); @@ -864,7 +865,7 @@ H5H_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent, intn fwidth) assert (indent>=0); assert (fwidth>=0); - if (NULL==(h=H5AC_find (f, H5AC_HEAP, addr, NULL))) { + if (NULL==(h=H5AC_find (f, H5AC_HEAP, addr, NULL, NULL))) { HRETURN_ERROR (H5E_HEAP, H5E_CANTLOAD, FAIL); } @@ -26,7 +26,7 @@ /* PRIVATE PROTOTYPES */ static herr_t H5O_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5O_t *oh); -static H5O_t *H5O_load (H5F_t *f, haddr_t addr, void *_data); +static H5O_t *H5O_load (H5F_t *f, haddr_t addr, void *_udata1, void *_udata2); static intn H5O_find_in_ohdr (H5F_t *f, haddr_t addr, const H5O_class_t **type_p, intn sequence); static intn H5O_alloc (H5F_t *f, H5O_t *oh, const H5O_class_t *type, @@ -36,7 +36,7 @@ static intn H5O_alloc_new_chunk (H5F_t *f, H5O_t *oh, size_t size); /* H5O inherits cache-like properties from H5AC */ static const H5AC_class_t H5AC_OHDR[1] = {{ - (void*(*)(H5F_t*,haddr_t,void*))H5O_load, + (void*(*)(H5F_t*,haddr_t,void*,void*))H5O_load, (herr_t(*)(H5F_t*,hbool_t,haddr_t,void*))H5O_flush, }}; @@ -45,17 +45,17 @@ static intn interface_initialize_g = FALSE; /* ID to type mapping */ static const H5O_class_t *const message_type_g[] = { - H5O_NULL, /*0x0000 Null */ - H5O_SIM_DIM, /*0x0001 Simple dimensionality */ + H5O_NULL, /*0x0000 Null */ + H5O_SIM_DIM, /*0x0001 Simple dimensionality */ NULL, /*0x0002 Data space (fiber bundle?) */ - H5O_SIM_DTYPE, /*0x0003 Simple data type */ + H5O_SIM_DTYPE, /*0x0003 Simple data type */ NULL, /*0x0004 Compound data type */ - H5O_STD_STORE, /*0x0005 Data storage -- standard object */ + H5O_STD_STORE, /*0x0005 Data storage -- standard object */ NULL, /*0x0006 Data storage -- compact object */ NULL, /*0x0007 Data storage -- external object */ - NULL, /*0x0008 Data storage -- indexed object */ - NULL, /*0x0009 Data storage -- chunked object */ - NULL, /*0x000A Data storage -- sparse object */ + H5O_ISTORE, /*0x0008 Data storage -- indexed object */ + NULL, /*0x0009 Not assigned */ + NULL, /*0x000A Not assigned */ NULL, /*0x000B Data storage -- compressed object */ NULL, /*0x000C Attribute list */ H5O_NAME, /*0x000D Object name */ @@ -105,7 +105,7 @@ H5O_new (H5F_t *f, intn nlink, size_t size_hint) HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL); } - /* allocate the object header in fill in header fields */ + /* allocate the object header and fill in header fields */ oh = H5MM_xcalloc (1, sizeof(H5O_t)); oh->dirty = TRUE; oh->version = H5O_VERSION; @@ -165,7 +165,7 @@ H5O_new (H5F_t *f, intn nlink, size_t size_hint) *------------------------------------------------------------------------- */ static H5O_t * -H5O_load (H5F_t *f, haddr_t addr, void *_data) +H5O_load (H5F_t *f, haddr_t addr, void *_udata1, void *_udata2) { H5O_t *oh = NULL; H5O_t *ret_value = (void*)1; /*kludge for HGOTO_ERROR*/ @@ -182,7 +182,8 @@ H5O_load (H5F_t *f, haddr_t addr, void *_data) /* check args */ assert (f); assert (addr>=0); - assert (!_data); + assert (!_udata1); + assert (!_udata2); /* allocate ohdr and init chunk list */ oh = H5MM_xcalloc (1, sizeof(H5O_t)); @@ -454,7 +455,7 @@ H5O_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5O_t *oh) * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Aug 12 1997 * * Modifications: @@ -513,7 +514,7 @@ H5O_link (H5F_t *f, H5G_entry_t *ent, intn adjust) addr = H5G_ent_addr (ent); /* get header */ - if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) { + if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL, NULL))) { HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL); } @@ -600,7 +601,7 @@ H5O_read (H5F_t *f, haddr_t addr, H5G_entry_t *ent, #endif /* copy the message to the user-supplied buffer */ - if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) { + if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL, NULL))) { HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, NULL); } retval = (type->copy)(oh->mesg[idx].native, mesg); @@ -643,7 +644,7 @@ H5O_find_in_ohdr (H5F_t *f, haddr_t addr, const H5O_class_t **type_p, assert (type_p); /* load the object header */ - if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) { + if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL, NULL))) { HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL); } @@ -710,7 +711,7 @@ H5O_peek (H5F_t *f, haddr_t addr, const H5O_class_t *type, intn sequence) if ((idx = H5O_find_in_ohdr (f, addr, &type, sequence))<0) { HRETURN_ERROR (H5E_OHDR, H5E_NOTFOUND, NULL); } - if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) { + if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL, NULL))) { HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, NULL); } @@ -767,7 +768,7 @@ H5O_modify (H5F_t *f, haddr_t addr, H5G_entry_t *ent, assert (mesg); if (addr<=0) addr = H5G_ent_addr (ent); - if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) { + if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL, NULL))) { HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL); } @@ -842,7 +843,7 @@ H5O_modify (H5F_t *f, haddr_t addr, H5G_entry_t *ent, * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Aug 28 1997 * * Modifications: @@ -865,7 +866,7 @@ H5O_remove (H5F_t *f, haddr_t addr, H5G_entry_t *ent, if (addr<=0) addr = H5G_ent_addr (ent); /* load the object header */ - if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) { + if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL, NULL))) { HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL); } @@ -1309,7 +1310,7 @@ H5O_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent, intn fwidth) assert (indent>=0); assert (fwidth>=0); - if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) { + if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL, NULL))) { HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL); } diff --git a/src/H5Oistore.c b/src/H5Oistore.c new file mode 100644 index 0000000..1ed275e --- /dev/null +++ b/src/H5Oistore.c @@ -0,0 +1,271 @@ +/* + * Copyright (C) 1997 NCSA + * All rights reserved. + * + * Programmer: Robb Matzke <matzke@llnl.gov> + * Wednesday, October 8, 1997 + */ +#include <H5private.h> +#include <H5Eprivate.h> +#include <H5MMprivate.h> +#include <H5Oprivate.h> + +#define PABLO_MASK H5O_istore_mask + +/* PRIVATE PROTOTYPES */ +static void *H5O_istore_decode (H5F_t *f, size_t raw_size, const uint8 *p); +static herr_t H5O_istore_encode (H5F_t *f, size_t size, uint8 *p, + const void *_mesg); +static void *H5O_istore_copy (const void *_mesg, void *_dest); +static size_t H5O_istore_size (H5F_t *f, const void *_mesg); +static herr_t H5O_istore_debug (H5F_t *f, const void *_mesg, FILE *stream, + intn indent, intn fwidth); + +/* This message derives from H5O */ +const H5O_class_t H5O_ISTORE[1] = {{ + H5O_ISTORE_ID, /*message id number */ + "istore", /*message name for debugging */ + sizeof(H5O_istore_t), /*native message size */ + H5G_NOTHING_CACHED, /*symtab entry `type' field */ + H5O_istore_decode, /*decode message */ + H5O_istore_encode, /*encode message */ + NULL, /*get messsage from stab entry */ + NULL, /*put message into stab entry */ + H5O_istore_copy, /*copy the native value */ + H5O_istore_size, /*size of message on disk */ + NULL, /*reset method */ + H5O_istore_debug, /*debug the message */ +}}; + +/* Is the interface initialized? */ +static hbool_t interface_initialize_g = FALSE; + + + +/*------------------------------------------------------------------------- + * Function: H5O_istore_decode + * + * Purpose: Decode an indexed storage message and return a pointer to a + * new one created with malloc(). + * + * Return: Success: Ptr to new message in native order. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * Wednesday, October 8, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void * +H5O_istore_decode (H5F_t *f, size_t raw_size, const uint8 *p) +{ + H5O_istore_t *mesg = NULL; + intn i; + + FUNC_ENTER (H5O_istore_decode, NULL, NULL); + + /* check args */ + assert (f); + assert (p); + + /* decode */ + mesg = H5MM_xcalloc (1, sizeof(H5O_istore_t)); + H5F_decode_offset (f, p, mesg->btree_addr); + mesg->ndims = *p++; + assert (raw_size == H5O_istore_size (f, mesg)); + + /* Reserved bytes */ + p += 7; + + /* Read the min_corner, max_corner, and alignment values */ + for (i=0; i<mesg->ndims; i++) { + UINT32DECODE (p, mesg->alignment[i]); + } + + FUNC_LEAVE (mesg); +} + + + +/*------------------------------------------------------------------------- + * Function: H5O_istore_encode + * + * Purpose: Encodes a message. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Wednesday, October 8, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_istore_encode (H5F_t *f, size_t raw_size, uint8 *p, const void *_mesg) +{ + const H5O_istore_t *mesg = (const H5O_istore_t *)_mesg; + int i; + + FUNC_ENTER (H5O_istore_encode, NULL, FAIL); + + /* check args */ + assert (f); + assert (mesg); + assert (mesg->ndims>0 && mesg->ndims<=H5O_ISTORE_NDIMS); + assert (raw_size == H5O_istore_size (f, _mesg)); + assert (p); + + /* encode B-tree offset */ + H5F_encode_offset (f, p, mesg->btree_addr); + + /* number of dimensions */ + *p++ = mesg->ndims; + + /* reserved bytes should be zero */ + for (i=0; i<7; i++) *p++ = 0; + + /* min_corner, max_corner, and alignment */ + for (i=0; i<mesg->ndims; i++) { + UINT32ENCODE (p, mesg->alignment[i]); + } + + FUNC_LEAVE (SUCCEED); +} + + + +/*------------------------------------------------------------------------- + * Function: H5O_istore_copy + * + * Purpose: Copies a message from _MESG to _DEST, allocating _DEST if + * necessary. + * + * Return: Success: Ptr to _DEST + * + * Failure: NULL + * + * Programmer: Robb Matzke + * Wednesday, October 8, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void * +H5O_istore_copy (const void *_mesg, void *_dest) +{ + const H5O_istore_t *mesg = (const H5O_istore_t *)_mesg; + H5O_istore_t *dest = (H5O_istore_t *)_dest; + + FUNC_ENTER (H5O_istore_copy, NULL, NULL); + + /* check args */ + assert (mesg); + if (!dest) dest = H5MM_xcalloc (1, sizeof(H5O_istore_t)); + + /* copy */ + *dest = *mesg; + + FUNC_LEAVE ((void*)dest); +} + + + +/*------------------------------------------------------------------------- + * Function: H5O_istore_size + * + * Purpose: Returns the size of the raw message in bytes not counting the + * message type or size fields, but only the data fields. This + * function doesn't take into account message alignment. + * + * Return: Success: Message data size in bytes + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Wednesday, October 8, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static size_t +H5O_istore_size (H5F_t *f, const void *_mesg) +{ + const H5O_istore_t *mesg = (const H5O_istore_t *)_mesg; + size_t ret_value = FAIL; + + FUNC_ENTER (H5O_istore_size, NULL, FAIL); + + /* check args */ + assert (f); + assert (mesg); + assert (mesg->ndims>0 && mesg->ndims<=H5O_ISTORE_NDIMS); + + ret_value = H5F_SIZEOF_OFFSET (f) + /* B-tree address */ + 1 + /* max dimension index */ + 7 + /* reserved bytes */ + mesg->ndims * 4; /* alignment */ + + FUNC_LEAVE (ret_value); +} + + + +/*------------------------------------------------------------------------- + * Function: H5O_istore_debug + * + * Purpose: Prints debugging info for a message. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Wednesday, October 8, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_istore_debug (H5F_t *f, const void *_mesg, FILE *stream, intn indent, + intn fwidth) +{ + const H5O_istore_t *mesg = (const H5O_istore_t *)_mesg; + intn i; + + FUNC_ENTER (H5O_istore_debug, NULL, FAIL); + + /* check args */ + assert (f); + assert (mesg); + assert (stream); + assert (indent>=0); + assert (fwidth>=0); + + fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth, + "B-tree address:", + (unsigned long)(mesg->btree_addr)); + fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth, + "Number of dimensions:", + (unsigned long)(mesg->ndims)); + + /* Alignment */ + fprintf (stream, "%*s%-*s {", indent, "", fwidth, + "Alignment:"); + for (i=0; i<mesg->ndims; i++) { + fprintf (stream, "%s%lu", i?", ":"", + (unsigned long)(mesg->alignment[i])); + } + fprintf (stream, "}\n"); + + FUNC_LEAVE (SUCCEED); +} + diff --git a/src/H5Oname.c b/src/H5Oname.c index 7d76fa5..9d8aa09 100644 --- a/src/H5Oname.c +++ b/src/H5Oname.c @@ -6,7 +6,7 @@ * * Created: H5Oname.c * Aug 12 1997 - * Robb Matzke <robb@maya.nuance.com> + * Robb Matzke <matzke@llnl.gov> * * Purpose: Object name message. * @@ -62,7 +62,7 @@ static hbool_t interface_initialize_g = FALSE; * Failure: NULL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Aug 12 1997 * * Modifications: @@ -101,7 +101,7 @@ H5O_name_decode (H5F_t *f, size_t raw_size, const uint8 *p) * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Aug 12 1997 * * Modifications: @@ -144,7 +144,7 @@ H5O_name_encode (H5F_t *f, size_t raw_size, uint8 *p, const void *_mesg) * Failure: NULL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Aug 12 1997 * * Modifications: @@ -184,7 +184,7 @@ H5O_name_copy (const void *_mesg, void *_dest) * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Aug 12 1997 * * Modifications: @@ -219,7 +219,7 @@ H5O_name_size (H5F_t *f, const void *_mesg) * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Aug 12 1997 * * Modifications: @@ -253,7 +253,7 @@ H5O_name_reset (void *_mesg) * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Aug 12 1997 * * Modifications: diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h index 94dd764..c4ad1cb 100644 --- a/src/H5Oprivate.h +++ b/src/H5Oprivate.h @@ -115,10 +115,23 @@ typedef h5_atomic_type_t H5O_sim_dtype_t; #define H5O_STD_STORE_ID 0x0005 extern const H5O_class_t H5O_STD_STORE[1]; -typedef struct H5O_std_store { - haddr_t off; - haddr_t len; - } H5O_std_store_t; +typedef struct H5O_std_store_t { + haddr_t off; + haddr_t len; +} H5O_std_store_t; + +/* + * Indexed Data Storage message. + */ +#define H5O_ISTORE_ID 0x0008 +#define H5O_ISTORE_NDIMS 32 +extern const H5O_class_t H5O_ISTORE[1]; + +typedef struct H5O_istore_t { + haddr_t btree_addr; /*file address of B-tree */ + uintn ndims; /*num dimensions in stored data */ + size_t alignment[H5O_ISTORE_NDIMS]; /*algn in logical space */ +} H5O_istore_t; /* * Object name message. diff --git a/src/H5Osdtyp.c b/src/H5Osdtyp.c index 367af17..0800e30 100644 --- a/src/H5Osdtyp.c +++ b/src/H5Osdtyp.c @@ -205,7 +205,7 @@ H5O_sim_dtype_fast (const H5G_cache_t *cache, void *mesg) method is required for simple datatypes, as they can be cached in the symbol-table entry) --------------------------------------------------------------------------*/ -static herr_t +static hbool_t H5O_sim_dtype_cache (H5G_type_t *cache_type, H5G_cache_t *cache, const void *mesg) { diff --git a/src/H5config.h.in b/src/H5config.h.in index 20da7a1..07a0615 100644 --- a/src/H5config.h.in +++ b/src/H5config.h.in @@ -1,5 +1,11 @@ /* src/H5config.h.in. Generated automatically from configure.in by autoheader. */ +/* Define to empty if the keyword does not work. */ +#undef const + +/* Define as __inline if that's what the C compiler calls it. */ +#undef inline + /* Define to `long' if <sys/types.h> doesn't define. */ #undef off_t @@ -13,6 +19,12 @@ byte first (like Motorola and SPARC, unlike Intel and VAX). */ #undef WORDS_BIGENDIAN +/* Define if the __attribute__(()) extension is present */ +/* #define HAVE_ATTRIBUTE */ + +/* Define if the compiler understands the __FUNCTION__ keyword. */ +/* #define HAVE_FUNCTION */ + /* The number of bytes in a double. */ #undef SIZEOF_DOUBLE diff --git a/src/H5private.h b/src/H5private.h index f13ff59..58db166 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -63,8 +63,19 @@ #define MACIO 2 #define WINNTIO 3 #define PAGEBUFIO 4 -#define FILELIB POSIXBUFIO +#ifndef FILELIB +# define FILELIB POSIXBUFIO +#endif + +/* Does the compiler support the __attribute__(()) syntax? */ +#ifndef HAVE_ATTRIBUTE +# define __attribute__(X) /*void*/ +#endif +/* Does the compiler expand __FUNCTION__? */ +#ifndef HAVE_FUNCTION +# define __FUNCTION__ "NoFuntionName" +#endif /* number of members in an array */ #ifndef NELMTS @@ -359,6 +370,7 @@ typedef off_t haddr_t; /* * And now for a couple non-Posix functions... */ +extern char *strdup (const char *s); #define HDstrdup(S) strdup(S) /*------------------------------------------------------------------------- diff --git a/src/Makefile.in b/src/Makefile.in index cebf3c1..8776376 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -14,10 +14,10 @@ LIB=libhdf5.a 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 \ - H5Gent.c H5Gnode.c H5Gshad.c H5Gstab.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_SRC=H5.c H5A.c H5AC.c H5B.c H5C.c H5D.c H5Dconv.c H5E.c H5F.c H5Fistore.c \ + H5G.c H5Gent.c H5Gnode.c H5Gshad.c H5Gstab.c H5H.c H5M.c H5MF.c \ + H5MM.c H5O.c H5Ocont.c H5Oistore.c H5Oname.c H5Onull.c H5Osdtyp.c \ + H5Osdim.c H5Ostab.c H5Ostdst.c H5P.c H5T.c H5V.c LIB_OBJ=$(LIB_SRC:.c=.o) @@ -35,7 +35,7 @@ PUB_HDR=H5public.h H5Apublic.h H5ACpublic.h H5Bpublic.h H5Cpublic.h \ PRIVATE_HDR=H5private.h H5Aprivate.h H5ACprivate.h H5Bprivate.h \ H5Cprivate.h H5Dprivate.h H5Eprivate.h H5Fprivate.h H5Gprivate.h \ H5Gpkg.h H5Hprivate.h H5Mprivate.h H5MFprivate.h H5MMprivate.h \ - H5Oprivate.h H5Pprivate.h H5Tprivate.h + H5Oprivate.h H5Pprivate.h H5Tprivate.h H5Vprivate.h # How to build the programs... debug: debug.o $(LIB) |