From a905a3a1e343d4507049c30512842957e2f6307c Mon Sep 17 00:00:00 2001 From: Robb Matzke Date: Thu, 7 Aug 1997 14:23:00 -0500 Subject: [svn-r15] ./src/H5AC.c ./src/H5ACprivate.h ./src/H5ACproto.h ./src/H5Bproto.h ./src/H5Gproto.h ./src/H5Hproto.h ./src/H5MFprivate.h ./src/H5MFproto.h ./src/H5MM.c ./src/H5MMprivate.h ./src/H5MMproto.h Changed my e-mail address. ./src/H5O.c NEW ./src/H5Onull.c NEW ./src/H5Ocont. NEW ./src/H5Ostab.c NEW New functions for dealing with object headers. The H5O.c is the generic stuff, and each particular message has a source file for the specific stuff. Use ./src/H5Ostab.c as a model for implementing other messages. ./src/Makefile ./src/test/Makefile Added new files ./src/debug.c Added debugging calls for object headers. ./src/H5B.c ./src/H5Bprivate.h ./src/H5Gnode.c ./src/H5MF.c Changed my e-mail address. Improved error handling. ./src/H5Eprivate.h ./src/H5Eproto.h Added more error symbols ./src/H5F.c Changed my e-mail address. Used macros for sizeof offsets and lengths. Added the interface initialization function to H5F_block_read() and H5F_block_write(). Updated H5F_debug() ./src/H5Fprivate.h Got rid of H5F_symbol_table_size(). Use H5G_SIZEOF_ENTRY() instead. Reformatted H5F_decode_offset() for readability. ./src/H5G.c Changed my e-mail address. Improved error handling. Replaced not_implemented_yet__*() with real functions from H5O. ./src/H5Gprivate.h Changed `symtab' to `stab' to be consistent with other stuff. ./src/H5H.c ./src/H5Hprivate.h Changed my e-mail address. Improved error handling. Added an extra argument to H5H_new() to indicate whether you want a global heap or a local heap. ./src/hdf5gen.h Added NELMTS() Fixed FUNC_ENTER() Rewrote FUNC_LEAVE() in terms of HRETURN(). ./src/hdf5meta.h Added `const' to the decode macros. ./src/hdf5pabl.h Added PABLO_SAVE() ./test/testhdf5.c ./test/testhdf5.h Added calls for object header testing. ./test/theap.c Turned off some output. --- src/H5AC.c | 14 +- src/H5ACprivate.h | 2 +- src/H5ACproto.h | 2 +- src/H5B.c | 478 +++++++++++++++------ src/H5Bprivate.h | 4 +- src/H5Bproto.h | 2 +- src/H5Eprivate.h | 14 + src/H5Eproto.h | 22 +- src/H5F.c | 37 +- src/H5Fprivate.h | 22 +- src/H5G.c | 297 +++++++++---- src/H5Gnode.c | 313 ++++++++++---- src/H5Gprivate.h | 8 +- src/H5Gproto.h | 2 +- src/H5H.c | 306 ++++++++++--- src/H5Hprivate.h | 9 +- src/H5Hproto.h | 2 +- src/H5MF.c | 40 +- src/H5MFprivate.h | 2 +- src/H5MFproto.h | 2 +- src/H5MM.c | 12 +- src/H5MMprivate.h | 2 +- src/H5MMproto.h | 2 +- src/H5O.c | 1242 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/H5Ocont.c | 164 +++++++ src/H5Onull.c | 33 ++ src/H5Oprivate.h | 127 ++++++ src/H5Oproto.h | 30 ++ src/H5Ostab.c | 328 ++++++++++++++ src/Makefile | 14 +- src/debug.c | 26 +- src/hdf5gen.h | 15 +- src/hdf5meta.h | 12 +- src/hdf5pabl.h | 6 +- 34 files changed, 3155 insertions(+), 436 deletions(-) create mode 100644 src/H5O.c create mode 100644 src/H5Ocont.c create mode 100644 src/H5Onull.c create mode 100644 src/H5Oprivate.h create mode 100644 src/H5Oproto.h create mode 100644 src/H5Ostab.c diff --git a/src/H5AC.c b/src/H5AC.c index 3a2e446..2adbafb 100644 --- a/src/H5AC.c +++ b/src/H5AC.c @@ -43,7 +43,7 @@ static int interface_initialize_g = FALSE; /*initialized?*/ * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 9 1997 * * Modifications: @@ -74,7 +74,7 @@ H5AC_new (hdf5_file_t *f) * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 9 1997 * * Modifications: @@ -113,7 +113,7 @@ H5AC_dest (hdf5_file_t *f) * Failure: NULL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 9 1997 * * Modifications: @@ -147,7 +147,7 @@ H5AC_find (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr, * Return right away if the item is in the cache. */ if (f->cache[idx].type==type && f->cache[idx].addr==addr) { - return f->cache[idx].thing; + HRETURN (f->cache[idx].thing); } /* @@ -209,7 +209,7 @@ H5AC_find (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr, * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 9 1997 * * Modifications: @@ -276,7 +276,7 @@ H5AC_flush (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr, * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 9 1997 * * Modifications: @@ -326,7 +326,7 @@ H5AC_set (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr, void *thing) * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 9 1997 * * Modifications: diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h index 9d10f19..d5c8cad 100644 --- a/src/H5ACprivate.h +++ b/src/H5ACprivate.h @@ -6,7 +6,7 @@ * * Created: H5ACprivate.h * Jul 9 1997 - * Robb Matzke + * Robb Matzke * * Purpose: Constants and typedefs available to the rest of the * library. diff --git a/src/H5ACproto.h b/src/H5ACproto.h index 25218a9..1423333 100644 --- a/src/H5ACproto.h +++ b/src/H5ACproto.h @@ -6,7 +6,7 @@ * * Created: H5ACproto.h * Jul 10 1997 - * Robb Matzke + * Robb Matzke * * Purpose: Function prototypes for the H5AC package. * diff --git a/src/H5B.c b/src/H5B.c index 89316b2..0ffdc61 100644 --- a/src/H5B.c +++ b/src/H5B.c @@ -6,7 +6,7 @@ * * Created: hdf5btree.c * Jul 10 1997 - * Robb Matzke + * Robb Matzke * * Purpose: Implements balanced, sibling-linked, N-ary trees * capable of storing any type of data with unique key @@ -79,7 +79,10 @@ * that type of B-tree. * * - * Modifications: + * Modifications: + * + * Robb Matzke, 4 Aug 1997 + * Added calls to H5E. * *------------------------------------------------------------------------- */ @@ -102,11 +105,14 @@ #include "hdf5.h" /* private headers */ +#include "H5private.h" /*library */ #include "H5ACprivate.h" /*cache */ #include "H5Bprivate.h" /*B-link trees */ #include "H5MFprivate.h" /*File memory management */ #include "H5MMprivate.h" /*Core memory management */ +#define PABLO_MASK H5B_mask + #define BOUND(MIN,X,MAX) ((MIN)<(X)?(MIN):((MAX)>(X)?(MAX):(X))) #define false 0 #define true 1 @@ -130,6 +136,9 @@ static const H5AC_class_t H5AC_BT[1] = {{ (herr_t(*)(hdf5_file_t*,hbool_t,haddr_t,void*))H5B_flush, }}; +/* Is the H5B interface initialized? */ +static interface_initialize_g = FALSE; + /*------------------------------------------------------------------------- * Function: H5B_new @@ -138,10 +147,10 @@ static const H5AC_class_t H5AC_BT[1] = {{ * * Return: Success: address of new node. * - * Failure: -1 + * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jun 23 1997 * * Modifications: @@ -157,11 +166,22 @@ H5B_new (hdf5_file_t *f, const H5B_class_t *type, size_t sizeof_rkey) size_t total_native_keysize; intn offset, i; + FUNC_ENTER (H5B_new, NULL, FAIL); + + /* + * Check arguments. + */ + assert (f); + assert (type); + assert (sizeof_rkey>0); + /* * Allocate file and memory data structures. */ size = H5B_nodesize (f, type, &total_native_keysize, sizeof_rkey); - if ((addr = H5MF_alloc (f, size))<=0) return -1; + if ((addr = H5MF_alloc (f, size))<0) { + HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL); + } bt = H5MM_xmalloc (sizeof(H5B_t)); bt->type = type; bt->sizeof_rkey = sizeof_rkey; @@ -201,8 +221,11 @@ H5B_new (hdf5_file_t *f, const H5B_class_t *type, size_t sizeof_rkey) /* * Cache the new B-tree node. */ - H5AC_set (f, H5AC_BT, addr, bt); - return addr; + if (H5AC_set (f, H5AC_BT, addr, bt)<0) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTINIT, FAIL); + } + + FUNC_LEAVE (addr); } @@ -216,7 +239,7 @@ H5B_new (hdf5_file_t *f, const H5B_class_t *type, size_t sizeof_rkey) * Failure: NULL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jun 23 1997 * * Modifications: @@ -228,14 +251,19 @@ H5B_load (hdf5_file_t *f, haddr_t addr, const void *_data) { const H5B_class_t *type = (const H5B_class_t *)_data; size_t size, total_nkey_size; - H5B_t *bt = H5MM_xmalloc (sizeof(H5B_t)); + H5B_t *bt = NULL; intn i; uint8 *p; + FUNC_ENTER (H5B_load, NULL, NULL); + + /* Check arguments */ + assert (f); + assert (addr>=0); assert (type); assert (type->get_sizeof_rkey); - - + + bt = H5MM_xmalloc (sizeof(H5B_t)); bt->sizeof_rkey = (type->get_sizeof_rkey)(f); size = H5B_nodesize (f, type, &total_nkey_size, bt->sizeof_rkey); bt->type = type; @@ -245,7 +273,9 @@ H5B_load (hdf5_file_t *f, haddr_t addr, const void *_data) bt->native = H5MM_xmalloc (total_nkey_size); bt->key = H5MM_xmalloc ((2*type->k+1) * sizeof(H5B_key_t)); bt->child = H5MM_xmalloc (2 * type->k * sizeof(haddr_t)); - H5F_block_read (f, addr, size, bt->page); + if (H5F_block_read (f, addr, size, bt->page)<0) { + HRETURN_ERROR (H5E_BTREE, H5E_READERROR, NULL); + } p = bt->page; /* magic number */ @@ -282,7 +312,7 @@ H5B_load (hdf5_file_t *f, haddr_t addr, const void *_data) bt->key[2*type->k].dirty = 0; bt->key[2*type->k].rkey = p; bt->key[2*type->k].nkey = NULL; - return bt; + FUNC_LEAVE (bt); error: if (bt) { @@ -292,7 +322,7 @@ error: H5MM_xfree (bt->native); H5MM_xfree (bt); } - return NULL; + HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, NULL); } @@ -301,12 +331,12 @@ error: * * Purpose: Flushes a dirty B-tree node to disk. * - * Return: Success: 0 + * Return: Success: SUCCEED * - * Failure: -1 + * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jun 23 1997 * * Modifications: @@ -317,11 +347,21 @@ static herr_t H5B_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5B_t *bt) { intn i; - size_t size = H5B_nodesize (f, bt->type, NULL, bt->sizeof_rkey); + size_t size = 0; uint8 *p = bt->page; + FUNC_ENTER (H5B_flush, NULL, FAIL); + + /* + * Check arguments. + */ + assert (f); + assert (addr>=0); + assert (bt); assert (bt->type); assert (bt->type->encode); + + size = H5B_nodesize (f, bt->type, NULL, bt->sizeof_rkey); if (bt->dirty) { @@ -347,7 +387,9 @@ H5B_flush (hdf5_file_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) { - (bt->type->encode)(f, bt->key[i].rkey, bt->key[i].nkey); + if ((bt->type->encode)(f, bt->key[i].rkey, bt->key[i].nkey)<0) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTENCODE, FAIL); + } } bt->key[i].dirty = 0; } @@ -366,7 +408,9 @@ H5B_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5B_t *bt) * bother writing data for the child entries that don't exist or * for the final unchanged children. */ - H5F_block_write (f, addr, size, bt->page); + if (H5F_block_write (f, addr, size, bt->page)<0) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTFLUSH, FAIL); + } bt->dirty = 0; bt->ndirty = 0; } @@ -378,7 +422,8 @@ H5B_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5B_t *bt) H5MM_xfree (bt->native); H5MM_xfree (bt); } - return 0; + + FUNC_LEAVE (SUCCEED); } @@ -401,7 +446,7 @@ H5B_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5B_t *bt) * Failure: -1 if not found. * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jun 23 1997 * * Modifications: @@ -414,32 +459,47 @@ H5B_find (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, void *udata) H5B_t *bt=NULL; uint8 lt_key[256], rt_key[256]; intn idx=-1, lt=0, rt, cmp=1; + int retval = FAIL; + FUNC_ENTER (H5B_find, NULL, FAIL); + + /* + * Check arguments. + */ + assert (f); assert (type); assert (type->sizeof_nkey < sizeof lt_key); assert (type->decode); assert (type->cmp); assert (type->found); + assert (addr>=0); /* * Perform a binary search to locate the child which contains * the thing for which we're searching. The comparison function * may preempt the B-tree node from the cache. */ - bt = H5AC_find (f, H5AC_BT, addr, type); + if (NULL==(bt=H5AC_find (f, H5AC_BT, addr, type))) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); + } rt = bt->nchildren; while (ltkey[idx].nkey) H5B_decode_key (f, bt, idx); + if (!bt->key[idx].nkey && H5B_decode_key (f, bt, idx)<0) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); + } HDmemcpy (lt_key, bt->key[idx].nkey, type->sizeof_nkey); /* the right key */ - if (!bt->key[idx+1].nkey) H5B_decode_key (f, bt, idx+1); + if (!bt->key[idx+1].nkey && H5B_decode_key (f, bt, idx+1)<0) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); + } HDmemcpy (rt_key, bt->key[idx+1].nkey, type->sizeof_nkey); /* compare */ @@ -449,18 +509,30 @@ H5B_find (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, void *udata) lt = idx+1; } } - if (cmp) return -1; + if (cmp) { + HRETURN_ERROR (H5E_BTREE, H5E_NOTFOUND, FAIL); + } /* * Follow the link to the subtree or to the data node. */ - bt = H5AC_find (f, H5AC_BT, addr, type); + if (NULL==(bt=H5AC_find (f, H5AC_BT, addr, type))) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); + } assert (idx>=0 && idxnchildren); if (bt->level > 0) { - return H5B_find (f, type, bt->child[idx], udata); + retval = H5B_find (f, type, bt->child[idx], udata); + if (retval<0) { + HRETURN_ERROR (H5E_BTREE, H5E_NOTFOUND, FAIL); + } + } else { + retval = (type->found)(f, bt->child[idx], lt_key, udata, rt_key); + if (retval<0) { + HRETURN_ERROR (H5E_BTREE, H5E_NOTFOUND, FAIL); + } } - - return (type->found)(f, bt->child[idx], lt_key, udata, rt_key); + + FUNC_LEAVE (retval); } @@ -474,10 +546,10 @@ H5B_find (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, void *udata) * * Return: Success: Address of the new node. * - * Failure: -1 + * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 3 1997 * * Modifications: @@ -487,15 +559,33 @@ H5B_find (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, void *udata) static haddr_t H5B_split (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, intn anchor) { - H5B_t *old = H5AC_find (f, H5AC_BT, addr, type); - H5B_t *bt = H5MM_xmalloc (sizeof(H5B_t)); + H5B_t *old = NULL; + H5B_t *bt = NULL; size_t total_nkey_size, size; intn i, offset; intn delta = H5B_ANCHOR_LT==anchor ? type->k : 0; - size_t recsize = old->sizeof_rkey + H5F_SIZEOF_OFFSET(f); + size_t recsize = 0; haddr_t tmp_addr, new_addr; H5B_t *tmp=NULL; + FUNC_ENTER (H5B_split, NULL, FAIL); + + /* + * Check arguments. + */ + assert (f); + assert (type); + assert (addr>=0); + + /* + * Initialize variables + */ + if (NULL==(old=H5AC_find (f, H5AC_BT, addr, type))) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); + } + bt = H5MM_xmalloc (sizeof(H5B_t)); + recsize = old->sizeof_rkey + H5F_SIZEOF_OFFSET(f); + /* * Create the new B-tree node. */ @@ -597,18 +687,24 @@ H5B_split (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, intn anchor) * Add the new node to the cache. */ new_addr = H5MF_alloc (f, size); - H5AC_set (f, H5AC_BT, new_addr, bt); + if (H5AC_set (f, H5AC_BT, new_addr, bt)<0) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTINIT, FAIL); + } /* * Update sibling pointers of old nodes. */ - old = H5AC_find (f, H5AC_BT, addr, type); + if (NULL==(old = H5AC_find (f, H5AC_BT, addr, type))) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); + } if (H5B_ANCHOR_LT==anchor) { old->dirty += 1; tmp_addr = old->right; old->right = new_addr; if (tmp_addr) { - tmp = H5AC_find (f, H5AC_BT, tmp_addr, type); + if (NULL==(tmp = H5AC_find (f, H5AC_BT, tmp_addr, type))) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); + } tmp->dirty += 1; tmp->left = new_addr; } @@ -617,13 +713,15 @@ H5B_split (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, intn anchor) tmp_addr = old->left; old->left = new_addr; if (tmp_addr) { - tmp = H5AC_find (f, H5AC_BT, tmp_addr, type); + if (NULL==(tmp = H5AC_find (f, H5AC_BT, tmp_addr, type))) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); + } tmp->dirty += 1; tmp->right = new_addr; } } - return new_addr; + FUNC_LEAVE (new_addr); } @@ -632,12 +730,12 @@ H5B_split (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, intn anchor) * * Purpose: Decode the specified key into native format. * - * Return: Success: 0 + * Return: Success: SUCCEED * - * Failure: -1 + * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 8 1997 * * Modifications: @@ -647,9 +745,14 @@ H5B_split (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, intn anchor) static herr_t H5B_decode_key (hdf5_file_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; - (bt->type->decode)(f, bt->key[idx].rkey, bt->key[idx].nkey); - return 0; + if ((bt->type->decode)(f, bt->key[idx].rkey, bt->key[idx].nkey)<0) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); + } + + FUNC_LEAVE (SUCCEED); } @@ -663,10 +766,10 @@ H5B_decode_key (hdf5_file_t *f, H5B_t *bt, intn idx) * B-tree root address may change if the old * root is split. * - * Failure: -1 + * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jun 23 1997 * * Modifications: @@ -682,26 +785,43 @@ H5B_insert (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, void *udata) intn level; H5B_t *bt; + FUNC_ENTER (H5B_insert, NULL, FAIL); + + /* + * Check arguments. + */ + assert (f); assert (type); assert (type->sizeof_nkey < sizeof lt_key); child = H5B_insert_helper (f, addr, type, lt_key, <_key_changed, md_key, udata, rt_key, &rt_key_changed); - if (child<0) return -1; - if (0==child) return addr; + if (child<0) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTINIT, FAIL); + } + if (0==child) HRETURN (addr); /* the current root */ - bt = H5AC_find (f, H5AC_BT, addr, type); + if (NULL==(bt = H5AC_find (f, H5AC_BT, addr, type))) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); + } level = bt->level; if (!lt_key_changed) { - if (!bt->key[0].nkey) H5B_decode_key (f, bt, 0); + if (!bt->key[0].nkey && H5B_decode_key (f, bt, 0)<0) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); + } memcpy (lt_key, bt->key[0].nkey, type->sizeof_nkey); } /* the new node */ - bt = H5AC_find (f, H5AC_BT, child, type); + if (NULL==(bt = H5AC_find (f, H5AC_BT, child, type))) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); + } if (!rt_key_changed) { - if (!bt->key[bt->nchildren].nkey) H5B_decode_key (f, bt, bt->nchildren); + if (!bt->key[bt->nchildren].nkey && + H5B_decode_key (f, bt, bt->nchildren)<0) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); + } memcpy (rt_key, bt->key[bt->nchildren].nkey, type->sizeof_nkey); } @@ -716,22 +836,37 @@ H5B_insert (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, void *udata) uint8 *buf = H5MM_xmalloc (size); haddr_t tmp_addr = H5MF_alloc (f, size); - H5AC_flush (f, H5AC_BT, addr, FALSE); - H5F_block_read (f, addr, size, buf); - H5F_block_write (f, tmp_addr, size, buf); - H5AC_rename (f, H5AC_BT, addr, tmp_addr); + if (tmp_addr<0) { + HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL); + } + if (H5AC_flush (f, H5AC_BT, addr, FALSE)<0) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTFLUSH, FAIL); + } + if (H5F_block_read (f, addr, size, buf)<0) { + HRETURN_ERROR (H5E_BTREE, H5E_READERROR, FAIL); + } + if (H5F_block_write (f, tmp_addr, size, buf)<0) { + HRETURN_ERROR (H5E_BTREE, H5E_WRITEERROR, FAIL); + } + if (H5AC_rename (f, H5AC_BT, addr, tmp_addr)<0) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTSPLIT, FAIL); + } buf = H5MM_xfree (buf); new_root = addr; addr = tmp_addr; /* update the new child's left pointer */ - bt = H5AC_find (f, H5AC_BT, child, type); + if (NULL==(bt=H5AC_find (f, H5AC_BT, child, type))) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); + } bt->dirty += 1; bt->left = addr; /* clear the old root at the old address */ - bt = H5AC_find (f, H5AC_BT, new_root, type); + if (NULL==(bt=H5AC_find (f, H5AC_BT, new_root, type))) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); + } bt->dirty += 1; bt->ndirty = 0; bt->left = 0; @@ -742,11 +877,15 @@ H5B_insert (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, void *udata) /* * The new root is created at a new file location. */ - new_root = H5B_new (f, type, bt->sizeof_rkey); + if ((new_root = H5B_new (f, type, bt->sizeof_rkey))<0) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTINIT, FAIL); + } #endif /* the new root */ - bt = H5AC_find (f, H5AC_BT, new_root, type); + if (NULL==(bt = H5AC_find (f, H5AC_BT, new_root, type))) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); + } bt->dirty += 1; bt->ndirty = 2; bt->level = level+1; @@ -766,7 +905,7 @@ H5B_insert (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, void *udata) bt->key[2].nkey = bt->native + 2 * type->sizeof_nkey; memcpy (bt->key[2].nkey, rt_key, type->sizeof_nkey); - return new_root; + FUNC_LEAVE (new_root); } @@ -776,17 +915,19 @@ H5B_insert (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, void *udata) * Purpose: Insert a child at the specified address with the * specified left or right key. * - * Return: void + * Return: Success: SUCCEED + * + * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 8 1997 * * Modifications: * *------------------------------------------------------------------------- */ -static void +static herr_t H5B_insert_child (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, intn idx, haddr_t child, intn anchor, void *md_key) { @@ -794,8 +935,11 @@ H5B_insert_child (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, size_t recsize; intn i; - bt = H5AC_find (f, H5AC_BT, addr, type); - assert (bt); + FUNC_ENTER (H5B_insert_child, NULL, FAIL); + + if (NULL==(bt=H5AC_find (f, H5AC_BT, addr, type))) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); + } bt->dirty += 1; recsize = bt->sizeof_rkey + H5F_SIZEOF_OFFSET(f); @@ -848,6 +992,8 @@ H5B_insert_child (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, bt->child[idx] = child; bt->nchildren += 1; bt->ndirty = bt->nchildren; + + FUNC_LEAVE (SUCCEED); } @@ -873,10 +1019,10 @@ H5B_insert_child (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, * 0 if the node didn't split. The MD_KEY * buffer is undefined. * - * Failure: -1 + * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 9 1997 * * Modifications: @@ -894,10 +1040,21 @@ H5B_insert_helper (hdf5_file_t *f, haddr_t addr, const H5B_class_t *type, intn anchor; haddr_t child, twin=0; + FUNC_ENTER (H5B_insert_helper, NULL, FAIL); + + /* + * Check arguments + */ + assert (f); + assert (addr>=0); assert (type); assert (type->decode); assert (type->cmp); assert (type->new); + assert (lt_key); + assert (lt_key_changed); + assert (rt_key); + assert (rt_key_changed); /* * Use a binary search to find the child that will receive the new @@ -905,21 +1062,27 @@ H5B_insert_helper (hdf5_file_t *f, haddr_t addr, const H5B_class_t *type, * the cache each time through the loop. When the search completes * IDX points to the child that should get the new data. */ - bt = H5AC_find (f, H5AC_BT, addr, type); - if (!bt) goto error; + if (NULL==(bt=H5AC_find (f, H5AC_BT, addr, type))) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); + } rt = bt->nchildren; while (ltkey[idx].nkey) H5B_decode_key (f, bt, idx); + if (!bt->key[idx].nkey && H5B_decode_key (f, bt, idx)<0) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); + } memcpy (lt_key, bt->key[idx].nkey, type->sizeof_nkey); /* right key */ - if (!bt->key[idx+1].nkey) H5B_decode_key (f, bt, idx+1); + if (!bt->key[idx+1].nkey && H5B_decode_key (f, bt, idx+1)<0) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); + } memcpy (rt_key, bt->key[idx+1].nkey, type->sizeof_nkey); /* compare */ @@ -936,23 +1099,33 @@ H5B_insert_helper (hdf5_file_t *f, haddr_t addr, const H5B_class_t *type, * function needs them as input. Don't worry about it at higher node * levels because this function uses them for output only. */ - bt = H5AC_find (f, H5AC_BT, addr, type); + if (NULL==(bt=H5AC_find (f, H5AC_BT, addr, type))) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); + } if (cmp<0 && idx<=0) { idx = 0; cmp = 0; if (0==bt->level && bt->nchildren) { - if (!bt->key[idx].nkey) H5B_decode_key (f, bt, idx); + if (!bt->key[idx].nkey && H5B_decode_key (f, bt, idx)<0) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); + } memcpy (lt_key, bt->key[idx].nkey, type->sizeof_nkey); - if (!bt->key[idx+1].nkey) H5B_decode_key (f, bt, idx+1); + if (!bt->key[idx+1].nkey && H5B_decode_key (f, bt, idx+1)<0) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); + } memcpy (rt_key, bt->key[idx+1].nkey, type->sizeof_nkey); } } else if (cmp>0 && idx+1>=bt->nchildren) { idx = bt->nchildren-1; cmp = 0; if (0==bt->level && bt->nchildren) { - if (!bt->key[idx].nkey) H5B_decode_key (f, bt, idx); + if (!bt->key[idx].nkey && H5B_decode_key (f, bt, idx)<0) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); + } memcpy (lt_key, bt->key[idx].nkey, type->sizeof_nkey); - if (!bt->key[idx+1].nkey) H5B_decode_key (f, bt, idx+1); + if (!bt->key[idx+1].nkey && H5B_decode_key (f, bt, idx+1)<0) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); + } memcpy (rt_key, bt->key[idx+1].nkey, type->sizeof_nkey); } } @@ -965,9 +1138,12 @@ H5B_insert_helper (hdf5_file_t *f, haddr_t addr, const H5B_class_t *type, * buffers are output values. */ if (0==bt->nchildren) { - child = (type->new)(f, lt_key, udata, rt_key); - if (child<=0) goto error; - bt = H5AC_find (f, H5AC_BT, addr, type); + if ((child = (type->new)(f, lt_key, udata, rt_key))<0) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTINIT, FAIL); + } + if (NULL==(bt=H5AC_find (f, H5AC_BT, addr, type))) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); + } bt->nchildren = 1; bt->dirty += 1; bt->ndirty = 1; @@ -998,8 +1174,10 @@ H5B_insert_helper (hdf5_file_t *f, haddr_t addr, const H5B_class_t *type, md_key, udata, rt_key, rt_key_changed); } - if (child<0) goto error; - bt = H5AC_find (f, H5AC_BT, addr, type); + if (child<0) HRETURN_ERROR (H5E_BTREE, H5E_CANTINSERT, FAIL); + if (NULL==(bt=H5AC_find (f, H5AC_BT, addr, type))) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); + } /* * Update the left and right keys. @@ -1032,7 +1210,9 @@ H5B_insert_helper (hdf5_file_t *f, haddr_t addr, const H5B_class_t *type, * and that `idx' is adjusted appropriately. */ if (child && bt->nchildren==2*type->k) { - twin = H5B_split (f, type, addr, anchor); + if ((twin = H5B_split (f, type, addr, anchor))<0) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTSPLIT, FAIL); + } if (idx<=type->k) { addr = H5B_ANCHOR_LT==anchor ? addr : twin; } else { @@ -1045,7 +1225,9 @@ H5B_insert_helper (hdf5_file_t *f, haddr_t addr, const H5B_class_t *type, * If the child split, then insert the new child. */ if (child) { - H5B_insert_child (f, type, addr, idx, child, anchor, md_key); + if (H5B_insert_child (f, type, addr, idx, child, anchor, md_key)<0) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTINSERT, FAIL); + } } /* @@ -1053,24 +1235,24 @@ H5B_insert_helper (hdf5_file_t *f, haddr_t addr, const H5B_class_t *type, * by the left and right node). */ if (twin) { - bt = H5AC_find (f, H5AC_BT, twin, type); + if (NULL==(bt=H5AC_find (f, H5AC_BT, twin, type))) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); + } if (H5B_ANCHOR_LT==anchor) { - if (!bt->key[0].nkey) { - H5B_decode_key (f, bt, 0); + if (!bt->key[0].nkey && H5B_decode_key (f, bt, 0)<0) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); } memcpy (md_key, bt->key[0].nkey, type->sizeof_nkey); } else { - if (!bt->key[bt->nchildren].nkey) { - H5B_decode_key (f, bt, bt->nchildren); + if (!bt->key[bt->nchildren].nkey && + H5B_decode_key (f, bt, bt->nchildren)<0) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); } memcpy (md_key, bt->key[bt->nchildren].nkey, type->sizeof_nkey); } } - return twin; - -error: - return -1; + FUNC_LEAVE (twin); } @@ -1080,12 +1262,12 @@ error: * Purpose: Calls the list callback for each leaf node of the * B-tree, passing it the UDATA structure. * - * Return: Success: 0 + * Return: Success: SUCCEED * - * Failure: -1 + * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jun 23 1997 * * Modifications: @@ -1098,27 +1280,39 @@ H5B_list (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, void *udata) H5B_t *bt; haddr_t *child=NULL; haddr_t twin; - intn i, nchildren, status; - herr_t (*list)(hdf5_file_t*,haddr_t,void*); + intn i, nchildren; + herr_t (*list)(hdf5_file_t*,haddr_t,void*) = NULL; + FUNC_ENTER (H5B_list, NULL, FAIL); + + /* + * Check arguments. + */ + assert (f); assert (type); assert (type->list); + assert (addr>=0); + assert (udata); - bt = H5AC_find (f, H5AC_BT, addr, type); - if (!bt) return -1; + if (NULL==(bt = H5AC_find (f, H5AC_BT, addr, type))) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); + } if (bt->level>0) { - return H5B_list (f, type, bt->child[0], udata); + if (H5B_list (f, type, bt->child[0], udata)<0) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTLIST, FAIL); + } else { + HRETURN (SUCCEED); + } } else { child = H5MM_xmalloc (2 * type->k * sizeof(haddr_t)); list = type->list; twin = addr; while (twin) { /*for each leaf node*/ - bt = H5AC_find (f, H5AC_BT, twin, type); - if (!bt) { + if (NULL==(bt=H5AC_find (f, H5AC_BT, twin, type))) { H5MM_xfree (child); - return -1; + HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); } nchildren = bt->nchildren; twin = bt->right; @@ -1126,16 +1320,16 @@ H5B_list (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, void *udata) bt = NULL; /*list callback may invalidate the cache*/ for (i=0; i0); + + /* + * Total native key size. + */ if (total_nkey_size) { *total_nkey_size = (2 * type->k + 1) * type->sizeof_nkey; } - return (H5B_SIZEOF_HDR(f) + /*node header */ + /* + * Total node size. + */ + size = (H5B_SIZEOF_HDR(f) + /*node header */ 2 * type->k * H5F_SIZEOF_OFFSET(f) + /*child pointers*/ (2*type->k+1) * sizeof_rkey); /*keys */ + + FUNC_LEAVE (size); } @@ -1181,12 +1394,12 @@ H5B_nodesize (hdf5_file_t *f, const H5B_class_t *type, * * Purpose: Prints debugging info about a B-tree. * - * Return: Success: 0 + * Return: Success: SUCCEED * - * Failure: -1 + * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Aug 4 1997 * * Modifications: @@ -1197,10 +1410,30 @@ herr_t H5B_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent, intn fwidth, const H5B_class_t *type) { - H5B_t *bt = H5AC_find (f, H5AC_BT, addr, type); + H5B_t *bt = NULL; + + FUNC_ENTER (H5B_debug, NULL, FAIL); + + /* + * Check arguments. + */ + assert (f); + assert (addr>=0); + assert (stream); + assert (indent>=0); + assert (fwidth>=0); + assert (type); - if (!bt) return -1; + /* + * Load the tree node. + */ + if (NULL==(bt=H5AC_find (f, H5AC_BT, addr, type))) { + HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); + } + /* + * Print the values. + */ fprintf (stream, "%*s%-*s %d\n", indent, "", fwidth, "Tree type ID:", (int)(bt->type->id)); @@ -1225,5 +1458,6 @@ H5B_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent, fprintf (stream, "%*s%-*s %d\n", indent, "", fwidth, "Number of children:", (int)(bt->nchildren)); - return 0; + + FUNC_LEAVE (SUCCEED); } diff --git a/src/H5Bprivate.h b/src/H5Bprivate.h index bb9d95c..4364203 100644 --- a/src/H5Bprivate.h +++ b/src/H5Bprivate.h @@ -52,8 +52,8 @@ typedef struct H5B_class_t { haddr_t (*insert)(hdf5_file_t*,haddr_t,int*,void*,int*,void*,void*, void*,int*); herr_t (*list)(hdf5_file_t*,haddr_t,void*); - void (*decode)(hdf5_file_t*,uint8*,void*); - void (*encode)(hdf5_file_t*,uint8*,void*); + herr_t (*decode)(hdf5_file_t*,uint8*,void*); + herr_t (*encode)(hdf5_file_t*,uint8*,void*); } H5B_class_t; /* diff --git a/src/H5Bproto.h b/src/H5Bproto.h index 3869db4..b1eb82c 100644 --- a/src/H5Bproto.h +++ b/src/H5Bproto.h @@ -6,7 +6,7 @@ * * Created: H5Bproto.h * Jul 10 1997 - * Robb Matzke + * Robb Matzke * * Purpose: Non-API function prototypes for B-link trees. * diff --git a/src/H5Eprivate.h b/src/H5Eprivate.h index d21adde..d36b2a2 100644 --- a/src/H5Eprivate.h +++ b/src/H5Eprivate.h @@ -58,6 +58,10 @@ static const hdf_maj_error_messages_t hdf_maj_error_messages[] = {H5E_FUNC, "Function Entry/Exit"}, {H5E_ATOM, "Object Atom"}, {H5E_CACHE, "Object Cache"}, + {H5E_BTREE, "B-Tree Node"}, + {H5E_SYM, "Symbol Table"}, + {H5E_HEAP, "Heap"}, + {H5E_OHDR, "Object Header"}, }; typedef struct @@ -90,6 +94,16 @@ static const hdf_min_error_messages_t hdf_min_error_messages[] = {H5E_CANTREGISTER, "Can't register new atom"}, {H5E_CANTFLUSH, "Can't flush object from cache"}, {H5E_CANTLOAD, "Can't load object into cache"}, + {H5E_NOTFOUND, "Object not found"}, + {H5E_CANTENCODE, "Can't encode value"}, + {H5E_CANTDECODE, "Can't decode value"}, + {H5E_CANTSPLIT, "Can't split node"}, + {H5E_CANTINSERT, "Can't insert object"}, + {H5E_CANTLIST, "Can't list node"}, + {H5E_LINKCOUNT, "Bad object header link count"}, + {H5E_VERSION, "Wrong version number"}, + {H5E_ALIGNMENT, "Alignment error"}, + {H5E_BADMESG, "Unrecognized message"}, }; /* We use a stack to hold the errors plus we keep track of the function, diff --git a/src/H5Eproto.h b/src/H5Eproto.h index c51ceac..95c198c 100644 --- a/src/H5Eproto.h +++ b/src/H5Eproto.h @@ -77,7 +77,11 @@ typedef enum H5E_IO, /* Low-level I/O */ H5E_FUNC, /* Function Entry/Exit */ H5E_ATOM, /* Object Atom */ - H5E_CACHE /* Object Cache */ + H5E_CACHE, /* Object Cache */ + H5E_BTREE, /* B-Tree Node */ + H5E_SYM, /* Symbol Table */ + H5E_HEAP, /* Heap */ + H5E_OHDR /* Object Header */ } hdf_maj_err_code_t; @@ -118,7 +122,21 @@ typedef enum /* Cache related errors */ H5E_CANTFLUSH, /* Can't flush object from cache */ - H5E_CANTLOAD /* Can't load object into cache */ + H5E_CANTLOAD, /* Can't load object into cache */ + + /* B-tree related errors */ + H5E_NOTFOUND, /* Object not found */ + H5E_CANTENCODE, /* Can't encode value */ + H5E_CANTDECODE, /* Can't decode value */ + H5E_CANTSPLIT, /* Can't split node */ + H5E_CANTINSERT, /* Can't insert object */ + H5E_CANTLIST, /* Can't list node */ + + /* Object header related errors */ + H5E_LINKCOUNT, /* Bad object header link count */ + H5E_VERSION, /* Wrong version number */ + H5E_ALIGNMENT, /* Alignment error */ + H5E_BADMESG /* Unrecognized message */ } hdf_min_err_code_t; diff --git a/src/H5F.c b/src/H5F.c index 3c756c4..145e4a7 100644 --- a/src/H5F.c +++ b/src/H5F.c @@ -32,6 +32,8 @@ static char RcsId[] = "@(#)$Revision$"; H5F_init_interface -- initialize the H5F interface */ +#include + #define HDF5_FILE_MASTER #include "hdf5.h" #undef HDF5_FILE_MASTER @@ -318,7 +320,7 @@ done: * Failure: NULL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 18 1997 * * Modifications: @@ -353,7 +355,7 @@ H5F_new (void) * Failure: NULL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 18 1997 * * Modifications: @@ -495,7 +497,9 @@ hatom_t H5Fcreate(const char *filename, uintn flags, hatom_t create_temp, hatom_ H5F_encode_offset(new_file,p,new_file->smallobj_off); /* Encode offset of global small-object heap */ H5F_encode_offset(new_file,p,new_file->freespace_off); /* Encode offset of global free-space heap */ /* Predict the header length and encode it: */ - H5F_encode_length(new_file,p,(p-temp_buf)+f_create_parms->length_size+H5F_symbol_table_size(new_file)); /* Encode length of boot-block */ + H5F_encode_length(new_file,p,((p-temp_buf) + + H5F_SIZEOF_SIZE(new_file) + + H5G_SIZEOF_ENTRY(new_file))); /* Encode the (bogus) symbol-table entry */ if (H5G_encode (new_file, &p, new_file->root_sym)<0) { @@ -779,7 +783,7 @@ done: * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 10 1997 * * Modifications: @@ -789,7 +793,7 @@ done: herr_t H5F_block_read (hdf5_file_t *f, haddr_t addr, size_t size, void *buf) { - FUNC_ENTER (H5F_block_read, NULL, FAIL); + FUNC_ENTER (H5F_block_read, H5F_init_interface, FAIL); if (0==size) return 0; addr += f->file_create_parms.userblock_size; @@ -816,7 +820,7 @@ H5F_block_read (hdf5_file_t *f, haddr_t addr, size_t size, void *buf) * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 10 1997 * * Modifications: @@ -826,7 +830,7 @@ H5F_block_read (hdf5_file_t *f, haddr_t addr, size_t size, void *buf) herr_t H5F_block_write (hdf5_file_t *f, haddr_t addr, size_t size, void *buf) { - FUNC_ENTER (H5F_block_write, NULL, FAIL); + FUNC_ENTER (H5F_block_write, H5F_init_interface, FAIL); if (0==size) return 0; addr += f->file_create_parms.userblock_size; @@ -849,12 +853,12 @@ H5F_block_write (hdf5_file_t *f, haddr_t addr, size_t size, void *buf) * is indented and the field name occupies the specified width * number of characters. * - * Return: Success: 0 + * Return: Success: SUCCEED * - * Failure: -1 + * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Aug 1 1997 * * Modifications: @@ -865,6 +869,16 @@ herr_t H5F_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent, intn fwidth) { + FUNC_ENTER (H5F_debug, H5F_init_interface, FAIL); + + /* check args */ + assert (f); + assert (addr>=0); + assert (stream); + assert (indent>=0); + assert (fwidth>=0); + + /* debug */ fprintf (stream, "%*sFile Boot Block...\n", indent, ""); fprintf (stream, "%*s%-*s %s\n", indent, "", fwidth, @@ -919,6 +933,5 @@ H5F_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent, "Shared header version number:", (unsigned)(f->file_create_parms.sharedheader_ver)); - - return 0; + FUNC_LEAVE (SUCCEED); } diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index fde8fb3..687072b 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -51,12 +51,6 @@ typedef struct { struct H5G_entry_t *root_sym; /* Extra for the root symbol in the file */ } hdf5_file_t; -/* Define a macro to ease calculation of the symbol-table entry size */ -#define H5F_symbol_table_size(f) (4+ /* "Symbol-type" bytes */ \ - H5F_SIZEOF_OFFSET(f)+ /* Offset bytes */ \ - H5F_SIZEOF_SIZE(f)+ /* Length bytes */ \ - 4+ /* Name offset in local heap */ \ - 24) /* "Scratch" space */ #ifdef NOT_YET #define H5F_encode_offset(f,p,o) (H5F_SIZEOF_OFFSET(f)==4 ? UINT32ENCODE(p,o) \ @@ -68,9 +62,19 @@ typedef struct { case 8: UINT64ENCODE(p,o); break;\ case 2: UINT16ENCODE(p,o); break;} #endif /* NOT_YET */ -#define H5F_decode_offset(f,p,o) switch(H5F_SIZEOF_OFFSET(f)) { case 4: UINT32DECODE(p,o); break;\ - case 8: UINT64DECODE(p,o); break;\ - case 2: UINT16DECODE(p,o); break;} + +#define H5F_decode_offset(f,p,o) \ + switch (H5F_SIZEOF_OFFSET (f)) { \ + case 4: \ + UINT32DECODE (p, o); \ + break; \ + case 8: \ + UINT64DECODE (p, o); \ + break; \ + case 2: \ + UINT16DECODE (p, o); \ + break; \ + } #ifdef NOT_YET #define H5F_encode_length(f,p,l) (H5F_SIZEOF_SIZE(f)==4 ? UINT32ENCODE(p,l) \ diff --git a/src/H5G.c b/src/H5G.c index fa7da12..19ba355 100644 --- a/src/H5G.c +++ b/src/H5G.c @@ -6,11 +6,14 @@ * * Created: H5G.c * Jul 18 1997 - * Robb Matzke + * Robb Matzke * * Purpose: * - * Modifications: + * Modifications: + * + * Robb Matzke, 5 Aug 1997 + * Added calls to H5E. * *------------------------------------------------------------------------- */ @@ -21,12 +24,19 @@ #define H5G_INIT_HEAP 8192 /* Packages needed by this file... */ +#include "H5private.h" #include "H5Bprivate.h" #include "H5Gprivate.h" #include "H5Hprivate.h" #include "H5MMprivate.h" +#include "H5Oprivate.h" + +#define PABLO_MASK H5G_mask + + +/* Is the interface initialized? */ +static intn interface_initialize_g = FALSE; -/* PRIVATE PROTOTYPES */ /*------------------------------------------------------------------------- @@ -46,10 +56,10 @@ * * Return: Success: Address of new symbol table. * - * Failure: -1 + * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Aug 1 1997 * * Modifications: @@ -59,27 +69,48 @@ haddr_t H5G_new (hdf5_file_t *f, size_t init) { - haddr_t addr; /*symtab object header */ - haddr_t heap; /*private heap */ off_t name; /*offset of "" name */ + haddr_t addr; /*object header address */ + H5O_stab_t stab; /*symbol table message */ + + FUNC_ENTER (H5G_new, NULL, FAIL); + + /* + * Check arguments. + */ + assert (f); /* Create symbol table private heap */ if (init>0) { - if ((heap = H5H_new (f, init))<0) return -1; - if ((name = H5H_insert (f, heap, 1, "")<0)) return -1; - assert (0==name); /*or B-tree's won't work*/ + if ((stab.heap = H5H_new (f, H5H_LOCAL, init))<0) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); + } + if ((name = H5H_insert (f, stab.heap, 1, "")<0)) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); + } + if (0!=name) { + /* + * B-tree's won't work if the first name isn't at the beginning + * of the heap. + */ + HRETURN_ERROR (H5E_INTERNAL, H5E_CANTINIT, FAIL); + } } else { - heap = 0; /*we'll create it later*/ + stab.heap = 0; /*we'll create it later*/ } - /* Create symbol table object header */ - addr = not_implemented_yet__create_object_header(); - if (addr<0) return -1; + /* The B-tree is created on demand later */ + stab.btree = 0; - /* Insert the heap and B-tree addresses */ - not_implemented_yet__insert_symtab_message (f, addr, heap, 0); + /* Create symbol table object header */ + if ((addr = H5O_new (f, 0, 4+2*H5F_SIZEOF_OFFSET(f)))<0) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); + } + if (H5O_modify(f, addr, NULL, NULL, H5O_STAB, H5O_NEW_MESG, &stab)<0) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); + } - return addr; + FUNC_LEAVE (addr); } @@ -92,10 +123,10 @@ H5G_new (hdf5_file_t *f, size_t init) * * Return: Success: Address corresponding to the name. * - * Failure: -1 + * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Aug 1 1997 * * Modifications: @@ -106,20 +137,35 @@ haddr_t H5G_find (hdf5_file_t *f, haddr_t addr, const char *name, H5G_entry_t *entry) { H5G_node_ud1_t udata; /*data to pass through B-tree */ - haddr_t btree; /*address of B-tree */ + H5O_stab_t stab; /*symbol table message */ + + FUNC_ENTER (H5G_find, NULL, FAIL); + + /* Check arguments */ + assert (f); + assert (addr>=0); + assert (name && *name); + assert (entry); /* set up the udata */ - not_implemented_yet__get_symtab_message (f, addr, &(udata.heap), &btree); - if (btree<=0 || udata.heap<=0) return -1; /*empty symbol table*/ + if (NULL==H5O_read (f, addr, NULL, H5O_STAB, 0, &stab)) { + HRETURN_ERROR (H5E_SYM, H5E_BADMESG, FAIL); + } + if (stab.btree<=0 || stab.heap<=0) { + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); /*empty symbol table*/ + } udata.operation = H5G_OPER_FIND; udata.name = name; + udata.heap = stab.heap; /* search the B-tree */ - if (H5B_find (f, H5B_SNODE, btree, &udata)<0) return -1; + if (H5B_find (f, H5B_SNODE, stab.btree, &udata)<0) { + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); + } /* return the result */ if (entry) *entry = udata.entry; - return udata.entry.header; + FUNC_LEAVE (udata.entry.header); } @@ -131,12 +177,12 @@ H5G_find (hdf5_file_t *f, haddr_t addr, const char *name, H5G_entry_t *entry) * file F. ENTRY is the new symbol table entry to use for the * symbol. * - * Return: Success: 0 + * Return: Success: SUCCEED * - * Failure: -1 + * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Aug 1 1997 * * Modifications: @@ -147,18 +193,34 @@ herr_t H5G_modify (hdf5_file_t *f, haddr_t addr, const char *name, H5G_entry_t *entry) { H5G_node_ud1_t udata; /*data to pass through B-tree */ - haddr_t btree; /*address of B-tree */ + H5O_stab_t stab; /*symbol table message */ + + FUNC_ENTER (H5G_modify, NULL, FAIL); + + /* check arguments */ + assert (f); + assert (addr>=0); + assert (name && *name); + assert (entry); /* set up the udata */ - not_implemented_yet__get_symtab_message (f, addr, &(udata.heap), &btree); - if (btree<=0 || udata.heap<=0) return -1; /*empty symbol table*/ + if (NULL==H5O_read (f, addr, NULL, H5O_STAB, 0, &stab)) { + HRETURN_ERROR (H5E_SYM, H5E_BADMESG, FAIL); + } + if (stab.btree<=0 || stab.heap<=0) { + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); /*empty symbol table*/ + } udata.operation = H5G_OPER_MODIFY; udata.name = name; + udata.heap = stab.heap; udata.entry = *entry; /* search and modify the B-tree */ - if (H5B_find (f, H5B_SNODE, btree, &udata)<0) return -1; - return 0; + if (H5B_find (f, H5B_SNODE, stab.btree, &udata)<0) { + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); + } + + FUNC_LEAVE (SUCCEED); } @@ -169,12 +231,12 @@ H5G_modify (hdf5_file_t *f, haddr_t addr, const char *name, H5G_entry_t *entry) * file F. The name of the new symbol is NAME and its symbol * table entry is ENTRY. * - * Return: Success: 0 + * Return: Success: SUCCEED * - * Failure: -1 + * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Aug 1 1997 * * Modifications: @@ -184,31 +246,51 @@ H5G_modify (hdf5_file_t *f, haddr_t addr, const char *name, H5G_entry_t *entry) herr_t H5G_insert (hdf5_file_t *f, haddr_t addr, const char *name, H5G_entry_t *entry) { - haddr_t btree; /*file address of B-tree */ + H5O_stab_t stab; /*symbol table message */ H5G_node_ud1_t udata; /*data to pass through B-tree */ off_t offset; /*offset of name within heap */ + FUNC_ENTER (H5G_insert, NULL, FAIL); + + /* check arguments */ + assert (f); + assert (addr>=0); + assert (name && *name); + assert (entry); + /* make sure we have a B-tree and a heap */ - not_implemented_yet__get_symtab_message (f, addr, &btree, &(udata.heap)); - if (btree<=0 || udata.heap<=0) { - if (btree<=0 && - (btree = H5B_new (f, H5B_SNODE, sizeof(H5G_node_key_t)))<0) { - return -1; + if (NULL==H5O_read (f, addr, NULL, H5O_STAB, 0, &stab)) { + HRETURN_ERROR (H5E_SYM, H5E_BADMESG, FAIL); + } + if (stab.btree<=0 || stab.heap<=0) { + if (stab.btree<=0 && + (stab.btree = H5B_new (f, H5B_SNODE, sizeof(H5G_node_key_t)))<0) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); + } + if (stab.heap<=0) { + stab.heap = H5H_new (f, H5H_LOCAL, + MAX(strlen(name)+1, H5G_INIT_HEAP)); + if (stab.heap<0) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); + } + if (0!=(offset = H5H_insert (f, stab.heap, 1, ""))) { + HRETURN_ERROR (H5E_INTERNAL, H5E_CANTINIT, FAIL); + } } - if (udata.heap<=0) { - udata.heap = H5H_new (f, MAX(strlen(name)+1, H5G_INIT_HEAP)); - if (udata.heap<0) return -1; - if (0!=(offset = H5H_insert (f, udata.heap, 1, ""))) return -1; + if (H5O_modify (f, addr, NULL, NULL, H5O_STAB, 0, &stab)<0) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); } - not_implemented_yet__update_symtab_message (f, addr, udata.heap, btree); } /* initialize data to pass through B-tree */ udata.name = name; + udata.heap = stab.heap; udata.entry = *entry; - if (H5B_insert (f, H5B_SNODE, btree, &udata)<0) return -1; + if (H5B_insert (f, H5B_SNODE, stab.btree, &udata)<0) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINSERT, FAIL); + } - return 0; + FUNC_LEAVE (SUCCEED); } @@ -227,12 +309,12 @@ H5G_insert (hdf5_file_t *f, haddr_t addr, const char *name, H5G_entry_t *entry) * but at most MAXENTRIES values are copied * into the NAMES and ENTRIES arrays. * - * Failure: -1, the pointers in NAMES are undefined but + * Failure: FAIL, the pointers in NAMES are undefined but * no memory is allocated. The values in * ENTRIES are undefined. * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Aug 1 1997 * * Modifications: @@ -244,26 +326,31 @@ H5G_list (hdf5_file_t *f, haddr_t addr, int maxentries, char *names[], H5G_entry_t entries[]) { H5G_node_list_t udata; - haddr_t btree; + H5O_stab_t stab; intn i; - - not_implemented_yet__get_symtab_message (f, addr, &btree, &(udata.heap)); - if (btree<=0 || udata.heap<=0) return 0; /*empty directory*/ + + FUNC_ENTER (H5G_list, NULL, FAIL); + + if (NULL==H5O_read (f, addr, NULL, H5O_STAB, 0, &stab)) { + HRETURN_ERROR (H5E_SYM, H5E_BADMESG, FAIL); + } + if (stab.btree<=0 || stab.heap<=0) HRETURN (0); /*empty directory*/ udata.entry = entries; udata.name = names; + udata.heap = stab.heap; udata.maxentries = maxentries; udata.nsyms = 0; if (names) HDmemset (names, 0, maxentries); - if (H5B_list (f, H5B_SNODE, btree, &udata)<0) { + if (H5B_list (f, H5B_SNODE, stab.btree, &udata)<0) { if (names) { for (i=0; i=0); + + /* decode entries */ for (i=0; iname_off); H5F_decode_offset (f, *pp, ent->header); UINT32DECODE (*pp, ent->type); + /* decode scratch-pad */ switch (ent->type) { case H5G_NOTHING_CACHED: break; @@ -338,9 +446,9 @@ H5G_decode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent) UINT32DECODE (*pp, ent->cache.sdata.dim[3]); break; - case H5G_CACHED_SYMTAB: - UINT32DECODE (*pp, ent->cache.symtab.btree); - UINT32DECODE (*pp, ent->cache.symtab.heap); + case H5G_CACHED_STAB: + UINT32DECODE (*pp, ent->cache.stab.btree); + UINT32DECODE (*pp, ent->cache.stab.heap); break; default: @@ -348,7 +456,7 @@ H5G_decode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent) } *pp = p_ret + H5G_SIZEOF_ENTRY(f); - return 0; + FUNC_LEAVE (SUCCEED); } @@ -358,13 +466,13 @@ H5G_decode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent) * Purpose: Same as H5G_encode() except it does it for an array of * symbol table entries. * - * Return: Success: 0, with *pp pointing to the first byte + * Return: Success: SUCCEED, with *pp pointing to the first byte * after the last symbol. * - * Failure: -1 + * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 18 1997 * * Modifications: @@ -376,10 +484,22 @@ H5G_encode_vec (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent, intn n) { intn i; + FUNC_ENTER (H5G_encode_vec, NULL, FAIL); + + /* check arguments */ + assert (f); + assert (pp); + assert (ent); + assert (n>=0); + + /* encode entries */ for (i=0; iname_off); H5F_encode_offset (f, *pp, ent->header); UINT32ENCODE (*pp, ent->type); + /* encode scratch-pad */ switch (ent->type) { case H5G_NOTHING_CACHED: break; @@ -424,9 +553,9 @@ H5G_encode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent) UINT32ENCODE (*pp, ent->cache.sdata.dim[3]); break; - case H5G_CACHED_SYMTAB: - UINT32ENCODE (*pp, ent->cache.symtab.btree); - UINT32ENCODE (*pp, ent->cache.symtab.heap); + case H5G_CACHED_STAB: + UINT32ENCODE (*pp, ent->cache.stab.btree); + UINT32ENCODE (*pp, ent->cache.stab.heap); break; default: @@ -434,11 +563,7 @@ H5G_encode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent) } *pp = p_ret + H5G_SIZEOF_ENTRY(f); - return 0; + FUNC_LEAVE (SUCCEED); } -herr_t not_implemented_yet__create_object_header (void) {return FAIL;} -herr_t not_implemented_yet__insert_symtab_message (hdf5_file_t* f, haddr_t addr, haddr_t heap, haddr_t btree) {return FAIL;} -herr_t not_implemented_yet__get_symtab_message (hdf5_file_t *f, haddr_t addr, haddr_t *heap, haddr_t *btree) {return FAIL;} -herr_t not_implemented_yet__update_symtab_message (hdf5_file_t *f, haddr_t addr, haddr_t heap, haddr_t btree) {return FAIL;} diff --git a/src/H5Gnode.c b/src/H5Gnode.c index 3ce046e..9e66188 100644 --- a/src/H5Gnode.c +++ b/src/H5Gnode.c @@ -13,7 +13,10 @@ * table entries. A B-tree usually points to the * symbol table nodes for any given symbol table. * - * Modifications: + * Modifications: + * + * Robb Matzke, 5 Aug 1997 + * Added calls to H5E. * *------------------------------------------------------------------------- */ @@ -24,6 +27,7 @@ #include "hdf5.h" /* Packages needed by this file... */ +#include "H5private.h" /*library */ #include "H5ACprivate.h" /*cache */ #include "H5Bprivate.h" /*B-link trees */ #include "H5Gprivate.h" /*me */ @@ -31,9 +35,12 @@ #include "H5MFprivate.h" /*file memory management */ #include "H5MMprivate.h" /*core memory management */ +#define PABLO_MASK H5G_node_mask + + /* PRIVATE PROTOTYPES */ -static void H5G_node_decode_key (hdf5_file_t *f, uint8 *raw, void *_key); -static void H5G_node_encode_key (hdf5_file_t *f, uint8 *raw, void *_key); +static herr_t H5G_node_decode_key (hdf5_file_t *f, uint8 *raw, void *_key); +static herr_t H5G_node_encode_key (hdf5_file_t *f, uint8 *raw, void *_key); static size_t H5G_node_size (hdf5_file_t *f); static haddr_t H5G_node_new (hdf5_file_t *f, void *_lt_key, void *_udata, void *_rt_key); @@ -73,6 +80,9 @@ const H5B_class_t H5B_SNODE[1] = {{ H5G_node_encode_key, /*encode */ }}; +/* Has the interface been initialized? */ +static intn interface_initialize_g = FALSE; + /*------------------------------------------------------------------------- * Function: H5G_node_sizeof_rkey @@ -85,7 +95,7 @@ const H5B_class_t H5B_SNODE[1] = {{ * Failure: never fails * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 14 1997 * * Modifications: @@ -104,22 +114,32 @@ H5G_node_sizeof_rkey (hdf5_file_t *f) * * Purpose: Decodes a raw key into a native key. * - * Return: void + * Return: Success: SUCCEED + * + * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 8 1997 * * Modifications: * *------------------------------------------------------------------------- */ -static void +static herr_t H5G_node_decode_key (hdf5_file_t *f, uint8 *raw, void *_key) { H5G_node_key_t *key = (H5G_node_key_t *)_key; + FUNC_ENTER (H5G_node_decode_key, NULL, FAIL); + + assert (f); + assert (raw); + assert (key); + H5F_decode_offset (f, raw, key->offset); + + FUNC_LEAVE (SUCCEED); } @@ -128,22 +148,32 @@ H5G_node_decode_key (hdf5_file_t *f, uint8 *raw, void *_key) * * Purpose: Encodes a native key into a raw key. * - * Return: void + * Return: Success: SUCCEED + * + * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 8 1997 * * Modifications: * *------------------------------------------------------------------------- */ -static void +static herr_t H5G_node_encode_key (hdf5_file_t *f, uint8 *raw, void *_key) { H5G_node_key_t *key = (H5G_node_key_t *)_key; + FUNC_ENTER (H5G_node_encode_key, NULL, FAIL); + + assert (f); + assert (raw); + assert (key); + H5F_encode_offset (f, raw, key->offset); + + FUNC_LEAVE (SUCCEED); } @@ -157,7 +187,7 @@ H5G_node_encode_key (hdf5_file_t *f, uint8 *raw, void *_key) * Failure: Never fails. * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jun 23 1997 * * Modifications: @@ -182,10 +212,10 @@ H5G_node_size (hdf5_file_t *f) * * Return: Success: Address of symbol table node. * - * Failure: 0 + * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jun 23 1997 * * Modifications: @@ -197,23 +227,44 @@ H5G_node_new (hdf5_file_t *f, void *_lt_key, void *_udata, void *_rt_key) { H5G_node_key_t *lt_key = (H5G_node_key_t*)_lt_key; H5G_node_key_t *rt_key = (H5G_node_key_t*)_rt_key; - H5G_node_t *sym = H5MM_xcalloc (1, sizeof(H5G_node_t)); - size_t size = H5G_node_size (f); - haddr_t addr = H5MF_alloc (f, size); + H5G_node_t *sym = NULL; + size_t size = 0; + haddr_t addr; + + FUNC_ENTER (H5G_node_new, NULL, FAIL); + + /* + * Check arguments. + */ + assert (f); + assert (lt_key); + assert (rt_key); + + sym = H5MM_xcalloc (1, sizeof(H5G_node_t)); + size = H5G_node_size (f); + if ((addr = H5MF_alloc (f, size))<0) { + H5MM_xfree (sym); + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); + } sym->dirty = 1; sym->entry = H5MM_xcalloc (2 * H5G_NODE_K, sizeof(H5G_entry_t)); - H5AC_set (f, H5AC_SNODE, addr, sym); + if (H5AC_set (f, H5AC_SNODE, addr, sym)<0) { + H5MM_xfree (sym->entry); + H5MM_xfree (sym); + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); + } /* * The left and right symbols in an empty tree are both the - * empty string stored at offset zero by the symtab.c functions. This + * empty string stored at offset zero by the H5G functions. This * allows the comparison functions to work correctly without knowing * that there are no symbols. */ if (lt_key) lt_key->offset = 0; if (rt_key) rt_key->offset = 0; - return addr; + + FUNC_LEAVE (addr); } @@ -222,12 +273,12 @@ H5G_node_new (hdf5_file_t *f, void *_lt_key, void *_udata, void *_rt_key) * * Purpose: Flush a symbol table node to disk. * - * Return: Success: 0 + * Return: Success: SUCCEED * - * Failure: -1 + * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jun 23 1997 * * Modifications: @@ -239,6 +290,16 @@ H5G_node_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5G_node_t *sym) { uint8 *buf=NULL, *p=NULL; size_t size; + herr_t status; + + FUNC_ENTER (H5G_node_flush, NULL, FAIL); + + /* + * Check arguments. + */ + assert (f); + assert (addr>=0); + assert (sym); if (sym->dirty) { size = H5G_node_size (f); @@ -261,8 +322,9 @@ H5G_node_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5G_node_t *sym) H5G_encode_vec (f, &p, sym->entry, sym->nsyms); - H5F_block_write (f, addr, p-buf, buf); + status = H5F_block_write (f, addr, p-buf, buf); buf = H5MM_xfree (buf); + if (status<0) HRETURN_ERROR (H5E_SYM, H5E_WRITEERROR, FAIL); } if (destroy) { @@ -270,7 +332,7 @@ H5G_node_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5G_node_t *sym) H5MM_xfree (sym); } - return 0; + FUNC_LEAVE (SUCCEED); } @@ -284,7 +346,7 @@ H5G_node_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5G_node_t *sym) * Failure: NULL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jun 23 1997 * * Modifications: @@ -294,14 +356,32 @@ H5G_node_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5G_node_t *sym) static H5G_node_t * H5G_node_load (hdf5_file_t *f, haddr_t addr, const void *_udata) { - H5G_node_t *sym = H5MM_xcalloc (1, sizeof(H5G_node_t)); - size_t size = H5G_node_size (f); - uint8 *buf = H5MM_xmalloc (size); - uint8 *p = buf; - + H5G_node_t *sym = NULL; + size_t size = 0; + uint8 *buf = NULL, *p = NULL; + FUNC_ENTER (H5G_node_load, NULL, NULL); + + /* + * Check arguments. + */ + assert (f); + assert (addr>=0); + assert (NULL==_udata); + + /* + * Initialize variables. + */ + size = H5G_node_size (f); + buf = p = H5MM_xmalloc (size); + sym = H5MM_xcalloc (1, sizeof(H5G_node_t)); sym->entry = H5MM_xcalloc (2*H5G_NODE_K, sizeof(H5G_entry_t)); - H5F_block_read (f, addr, size, buf); + + if (H5F_block_read (f, addr, size, buf)<0) { + H5MM_xfree (sym->entry); + H5MM_xfree (sym); + HRETURN_ERROR (H5E_SYM, H5E_READERROR, NULL); + } /* magic */ if (HDmemcmp (p, H5G_NODE_MAGIC, H5G_NODE_SIZEOF_MAGIC)) goto error; @@ -317,15 +397,15 @@ H5G_node_load (hdf5_file_t *f, haddr_t addr, const void *_udata) UINT16DECODE (p, sym->nsyms); /* entries */ - H5G_decode_vec (f, &p, sym->entry, sym->nsyms); + if (H5G_decode_vec (f, &p, sym->entry, sym->nsyms)<0) goto error; H5MM_xfree (buf); - return sym; + FUNC_LEAVE (sym); error: H5MM_xfree (buf); H5MM_xfree (sym); - return NULL; + HRETURN_ERROR (H5E_SYM, H5E_CANTLOAD, NULL); } @@ -346,10 +426,10 @@ error: * the LEFT key (exclusive) and the * RIGHT key (inclusive). * - * Failure: Never fails + * Failure: FAIL (same as LT < RT) * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jun 23 1997 * * Modifications: @@ -364,15 +444,21 @@ H5G_node_cmp (hdf5_file_t *f, void *_lt_key, void *_udata, void *_rt_key) H5G_node_key_t *rt_key = (H5G_node_key_t *)_rt_key; const char *s; + FUNC_ENTER (H5G_node_cmp, NULL, FAIL); + /* left side */ - s = H5H_peek (f, udata->heap, lt_key->offset); - if (HDstrcmp (udata->name, s)<=0) return -1; + if (NULL==(s=H5H_peek (f, udata->heap, lt_key->offset))) { + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); + } + if (HDstrcmp (udata->name, s)<=0) HRETURN (-1); /* right side */ - s = H5H_peek (f, udata->heap, rt_key->offset); - if (HDstrcmp (udata->name, s)>0) return 1; + if (NULL==(s=H5H_peek (f, udata->heap, rt_key->offset))) { + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); + } + if (HDstrcmp (udata->name, s)>0) HRETURN(-1); - return 0; + FUNC_LEAVE (0); } @@ -391,13 +477,13 @@ H5G_node_cmp (hdf5_file_t *f, void *_lt_key, void *_udata, void *_rt_key) * entry field. Otherwise the entry is copied from the * UDATA entry field to the symbol table. * - * Return: Success: 0 if found and data returned through the + * Return: Success: SUCCEED if found and data returned through the * UDATA pointer. * - * Failure: -1 if not found. + * Failure: FAIL if not found. * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jun 23 1997 * * Modifications: @@ -413,8 +499,18 @@ H5G_node_found (hdf5_file_t *f, haddr_t addr, void *_lt_key, void *_udata, intn lt=0, idx=0, rt, cmp=1; const char *s; - sn = H5AC_find (f, H5AC_SNODE, addr, NULL); - if (!sn) return -1; + FUNC_ENTER (H5G_node_found, NULL, FAIL); + + /* + * Check arguments. + */ + assert (f); + assert (addr>=0); + assert (udata); + + if (NULL==(sn=H5AC_find (f, H5AC_SNODE, addr, NULL))) { + HRETURN_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL); + } rt = sn->nsyms; /* @@ -422,8 +518,12 @@ H5G_node_found (hdf5_file_t *f, haddr_t addr, void *_lt_key, void *_udata, */ while (ltheap, sn->entry[idx].name_off); + if (NULL==(sn=H5AC_find (f, H5AC_SNODE, addr, NULL))) { + HRETURN_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL); + } + if (NULL==(s=H5H_peek (f, udata->heap, sn->entry[idx].name_off))) { + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); + } cmp = HDstrcmp (udata->name, s); if (cmp<0) { @@ -432,7 +532,7 @@ H5G_node_found (hdf5_file_t *f, haddr_t addr, void *_lt_key, void *_udata, lt = idx+1; } } - if (cmp) return -1; + if (cmp) HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); switch (udata->operation) { case H5G_OPER_FIND: @@ -451,7 +551,7 @@ H5G_node_found (hdf5_file_t *f, haddr_t addr, void *_lt_key, void *_udata, break; } - return 0; + FUNC_LEAVE (SUCCEED); } @@ -484,7 +584,7 @@ H5G_node_found (hdf5_file_t *f, haddr_t addr, void *_lt_key, void *_udata, * Failure: -1 * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jun 24 1997 * * Modifications: @@ -508,6 +608,18 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor, intn idx=-1, nsyms, cmp=1; intn lt=0, rt; /*binary search cntrs */ + FUNC_ENTER (H5G_node_insert, NULL, FAIL); + + /* + * Check arguments. + */ + assert (f); + assert (addr>=0); + assert (anchor); + assert (md_key); + assert (rt_key); + assert (udata); + /* * Symbol tables are always split so the new symbol table node is * to the right of the old one. @@ -520,8 +632,9 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor, * Load the symbol node and buffer the entries so we don't have to * worry about the cached value disappearing. */ - sn = H5AC_find (f, H5AC_SNODE, addr, NULL); - if (!sn) return -1; + if (NULL==(sn=H5AC_find (f, H5AC_SNODE, addr, NULL))) { + HRETURN_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL); + } HDmemcpy (ent, sn->entry, sn->nsyms * sizeof(H5G_entry_t)); rt = nsyms = sn->nsyms; sn = NULL; @@ -531,8 +644,12 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor, */ while (ltheap, ent[idx].name_off); - if (0==(cmp=HDstrcmp (udata->name, s))) return -1; /*already present*/ + if (NULL==(s=H5H_peek (f, udata->heap, ent[idx].name_off))) { + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); + } + if (0==(cmp=HDstrcmp (udata->name, s))) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINSERT, FAIL); /*already present*/ + } if (cmp<0) { rt = idx; } else { @@ -547,6 +664,7 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor, * with the new heap address. */ offset = H5H_insert (f, udata->heap, strlen(udata->name)+1, udata->name); + if (offset<0) HRETURN_ERROR (H5E_SYM, H5E_CANTINSERT, FAIL); if (nsyms>=2*H5G_NODE_K) { /* @@ -556,7 +674,9 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor, */ /* The left node */ - sn = H5AC_find (f, H5AC_SNODE, addr, NULL); + if (NULL==(sn=H5AC_find (f, H5AC_SNODE, addr, NULL))) { + HRETURN_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL); + } HDmemset (sn->entry+H5G_NODE_K, 0, H5G_NODE_K*sizeof(H5G_entry_t)); sn->nsyms = H5G_NODE_K; sn->dirty += 1; @@ -573,8 +693,12 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor, md_key->offset = sn->entry[sn->nsyms-1].name_off; /* The right node */ - new_node = H5G_node_new (f, NULL, NULL, NULL); - sn = H5AC_find (f, H5AC_SNODE, new_node, NULL); + if ((new_node = H5G_node_new (f, NULL, NULL, NULL))<0) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); + } + if (NULL==(sn=H5AC_find (f, H5AC_SNODE, new_node, NULL))) { + HRETURN_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL); + } HDmemcpy (sn->entry, ent+H5G_NODE_K, H5G_NODE_K*sizeof(H5G_entry_t)); sn->nsyms = H5G_NODE_K; @@ -598,7 +722,9 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor, /* * Add the new symbol to the node. */ - sn = H5AC_find (f, H5AC_SNODE, addr, NULL); + if (NULL==(sn=H5AC_find (f, H5AC_SNODE, addr, NULL))) { + HRETURN_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL); + } sn->dirty += 1; HDmemmove (sn->entry+idx+1, sn->entry+idx, (sn->nsyms-idx) * sizeof (H5G_entry_t)); @@ -612,7 +738,7 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor, } } - return new_node; + FUNC_LEAVE (new_node); } @@ -622,12 +748,12 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor, * Purpose: This function gets called during a directory list operation. * It should fill in data in the UDATA struct. * - * Return: Success: 0 + * Return: Success: SUCCEED * - * Failure: -1 + * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jun 24 1997 * * Modifications: @@ -638,12 +764,23 @@ static herr_t H5G_node_list (hdf5_file_t *f, haddr_t addr, void *_udata) { H5G_node_list_t *udata = (H5G_node_list_t *)_udata; - H5G_node_t *sn = H5AC_find (f, H5AC_SNODE, addr, NULL); + H5G_node_t *sn = NULL; off_t *offsets = NULL; intn nsyms, i; const char *s; - if (!sn) return -1; + FUNC_ENTER (H5G_node_list, NULL, FAIL); + + /* + * Check arguments. + */ + assert (f); + assert (addr>=0); + assert (udata); + + if (NULL==(sn=H5AC_find (f, H5AC_SNODE, addr, NULL))) { + HRETURN_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL); + } nsyms = sn->nsyms; /* @@ -653,7 +790,7 @@ H5G_node_list (hdf5_file_t *f, haddr_t addr, void *_udata) */ if (udata->nsyms >= udata->maxentries) { udata->nsyms += nsyms; - return 0; + HRETURN (SUCCEED); } /* @@ -677,11 +814,14 @@ H5G_node_list (hdf5_file_t *f, haddr_t addr, void *_udata) if (udata->name && udata->entry) { for (i=0; insyms+imaxentries; i++) { s = H5H_peek (f, udata->heap, udata->entry[udata->nsyms+i].name_off); + if (!s) HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); udata->name[udata->nsyms+i] = H5MM_xstrdup (s); } } else if (udata->name) { for (i=0; insyms+imaxentries; i++) { - s = H5H_peek (f, udata->heap, offsets[i]); + if (NULL==(s=H5H_peek (f, udata->heap, offsets[i]))) { + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); + } udata->name[udata->nsyms+i] = H5MM_xstrdup (s); } offsets = H5MM_xfree (offsets); @@ -691,7 +831,7 @@ H5G_node_list (hdf5_file_t *f, haddr_t addr, void *_udata) * Update the number of symbols. */ udata->nsyms += nsyms; - return 0; + FUNC_LEAVE (SUCCEED); } @@ -701,12 +841,12 @@ H5G_node_list (hdf5_file_t *f, haddr_t addr, void *_udata) * Purpose: Prints debugging information about a symbol table node * or a B-tree node for a symbol table B-tree. * - * Return: Success: 0 + * Return: Success: SUCCEED * - * Failure: -1 + * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Aug 4 1997 * * Modifications: @@ -719,18 +859,32 @@ H5G_node_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent, { int i, j; char buf[64]; - H5G_node_t *sn = H5AC_find (f, H5AC_SNODE, addr, NULL); + H5G_node_t *sn = NULL; + herr_t status; + + FUNC_ENTER (H5G_node_debug, NULL, FAIL); + + /* + * Check arguments. + */ + assert (f); + assert (addr>=0); + assert (stream); + assert (indent>=0); + assert (fwidth>=0); /* * If we couldn't load the symbol table node, then try loading the * B-tree node. */ - if (!sn) { - return H5B_debug (f, addr, stream, indent, fwidth, H5B_SNODE); + if (NULL==(sn=H5AC_find(f, H5AC_SNODE, addr, NULL))) { + H5ECLEAR; /*discard that error*/ + status = H5B_debug (f, addr, stream, indent, fwidth, H5B_SNODE); + if (status<0) HRETURN_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL); + HRETURN (SUCCEED); } - if (!sn) return -1; fprintf (stream, "%*sSymbol Table Node...\n", indent, ""); fprintf (stream, "%*s%-*s %d\n", indent, "", fwidth, "Dirty:", @@ -773,14 +927,14 @@ H5G_node_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent, } break; - case H5G_CACHED_SYMTAB: + case H5G_CACHED_STAB: fprintf (stream, "Symbol Table\n"); fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth, "B-tree address:", - (unsigned long)(sn->entry[i].cache.symtab.btree)); + (unsigned long)(sn->entry[i].cache.stab.btree)); fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth, "Heap address:", - (unsigned long)(sn->entry[i].cache.symtab.heap)); + (unsigned long)(sn->entry[i].cache.stab.heap)); break; default: @@ -788,6 +942,7 @@ H5G_node_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent, break; } } - return 0; + + FUNC_LEAVE (SUCCEED); } diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h index 5e08c4d..fdfa10c 100644 --- a/src/H5Gprivate.h +++ b/src/H5Gprivate.h @@ -6,7 +6,7 @@ * * Created: H5Gprivate.h * Jul 11 1997 - * Robb Matzke + * Robb Matzke * * Purpose: Private stuff for the H5G package (symbol tables). * @@ -45,7 +45,7 @@ typedef enum H5G_type_t { H5G_NOTHING_CACHED =0, /*nothing is cached */ H5G_CACHED_SDATA =1, /*simple dataset, `sdata' */ - H5G_CACHED_SYMTAB =2 /*symbol table, `symtab' */ + H5G_CACHED_STAB =2 /*symbol table, `stab' */ } H5G_type_t; /* @@ -68,8 +68,8 @@ typedef struct H5G_entry_t { struct { haddr_t btree; /*file address of symbol table B-tree */ - haddr_t heap; /*file address of symtab name heap */ - } symtab; + haddr_t heap; /*file address of stab name heap */ + } stab; } cache; /*cached data from object header */ } H5G_entry_t; diff --git a/src/H5Gproto.h b/src/H5Gproto.h index 5c7a66d..4b0569f 100644 --- a/src/H5Gproto.h +++ b/src/H5Gproto.h @@ -6,7 +6,7 @@ * * Created: H5Gproto.h * Jul 11 1997 - * Robb Matzke + * Robb Matzke * * Purpose: Prototypes for the H5G package (symbol tables). * diff --git a/src/H5H.c b/src/H5H.c index 11ed3b2..8a58f2a 100644 --- a/src/H5H.c +++ b/src/H5H.c @@ -6,23 +6,29 @@ * * Created: H5H.c * Jul 16 1997 - * Robb Matzke + * Robb Matzke * - * Purpose: Heap functions. + * Purpose: Heap functions for the global small object heap + * and for local symbol table name heaps. * - * Modifications: + * Modifications: + * + * Robb Matzke, 5 Aug 1997 + * Added calls to H5E. * *------------------------------------------------------------------------- */ #include #include "hdf5.h" +#include "H5private.h" /*library */ #include "H5ACprivate.h" /*cache */ #include "H5Hprivate.h" /*self */ #include "H5MFprivate.h" /*file memory management */ #include "H5MMprivate.h" /*core memory management */ #define H5H_FREE_NULL 1 /*end of free list on disk */ +#define PABLO_MASK H5H_mask #define H5H_SIZEOF_HDR(F) \ (H5H_SIZEOF_MAGIC + /*heap signature */ \ @@ -50,6 +56,7 @@ typedef struct H5H_t { H5H_free_t *freelist; /*the free list */ } H5H_t; +/* PRIVATE PROTOTYPES */ static H5H_t *H5H_load (hdf5_file_t *f, haddr_t addr, const void *udata); static herr_t H5H_flush (hdf5_file_t *f, hbool_t dest, haddr_t addr, H5H_t *heap); @@ -62,6 +69,9 @@ static const H5AC_class_t H5AC_HEAP[1] = {{ (herr_t(*)(hdf5_file_t*,hbool_t,haddr_t,void*))H5H_flush, }}; +/* Is the interface initialized? */ +static intn interface_initialize_g = FALSE; + /*------------------------------------------------------------------------- * Function: H5H_new @@ -75,24 +85,37 @@ static const H5AC_class_t H5AC_HEAP[1] = {{ * * Return: Success: File address of new heap. * - * Failure: -1 + * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 16 1997 * * Modifications: * + * Robb Matzke, 5 Aug 1997 + * Takes a flag that determines the type of heap that is + * created. + * *------------------------------------------------------------------------- */ haddr_t -H5H_new (hdf5_file_t *f, size_t size_hint) +H5H_new (hdf5_file_t *f, H5H_type_t heap_type, size_t size_hint) { H5H_t *heap = NULL; size_t total_size; /*total heap size on disk */ haddr_t addr; /*heap file address */ - + + FUNC_ENTER (H5H_new, NULL, FAIL); + + /* check arguments */ assert (f); + if (H5H_GLOBAL==heap_type) { +#ifndef NDEBUG + fprintf (stderr, "H5H_new: a local heap is used as the global heap\n"); +#endif + } + size_hint = MAX (0, size_hint); if (size_hint && size_hintdirty = 1; - H5AC_set (f, H5AC_HEAP, addr, heap); - - return addr; + if (H5AC_set (f, H5AC_HEAP, addr, heap)<0) { + heap->chunk = H5MM_xfree (heap->chunk); + heap->freelist = H5MM_xfree (heap->freelist); + HRETURN_ERROR (H5E_HEAP, H5E_CANTINIT, FAIL); + } + + FUNC_LEAVE (addr); } @@ -137,7 +166,7 @@ H5H_new (hdf5_file_t *f, size_t size_hint) * Failure: NULL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 17 1997 * * Modifications: @@ -148,16 +177,23 @@ static H5H_t * H5H_load (hdf5_file_t *f, haddr_t addr, const void *udata) { uint8 hdr[20], *p; - H5H_t *heap = H5MM_xcalloc (1, sizeof(H5H_t)); + H5H_t *heap=NULL; H5H_free_t *fl=NULL, *tail=NULL; haddr_t free_block; + FUNC_ENTER (H5H_load, NULL, NULL); + + /* check arguments */ + assert (f); assert (addr>0); assert (H5H_SIZEOF_HDR(f) <= sizeof hdr); assert (!udata); - if (H5F_block_read (f, addr, H5H_SIZEOF_HDR(f), hdr)<0) goto error; + if (H5F_block_read (f, addr, H5H_SIZEOF_HDR(f), hdr)<0) { + HRETURN_ERROR (H5E_HEAP, H5E_READERROR, NULL); + } p = hdr; + heap = H5MM_xcalloc (1, sizeof(H5H_t)); /* magic number */ if (HDmemcmp (hdr, H5H_MAGIC, H5H_SIZEOF_MAGIC)) goto error; @@ -169,7 +205,9 @@ H5H_load (hdf5_file_t *f, haddr_t addr, const void *udata) /* free list head */ H5F_decode_offset (f, p, free_block); - assert (-1==free_block || (free_block>=0 && free_blockdisk_alloc)); + if (-1!=free_block && (free_block<0 || free_block>=heap->disk_alloc)) { + goto error; + } /* data */ H5F_decode_offset (f, p, heap->addr); @@ -182,7 +220,7 @@ H5H_load (hdf5_file_t *f, haddr_t addr, const void *udata) /* free list */ while (H5H_FREE_NULL!=free_block) { - assert (free_block>=0 && free_blockdisk_alloc); + if (free_block<0 || free_block>=heap->disk_alloc) goto error; fl = H5MM_xmalloc (sizeof (H5H_free_t)); fl->offset = free_block; fl->prev = tail; @@ -195,16 +233,22 @@ H5H_load (hdf5_file_t *f, haddr_t addr, const void *udata) H5F_decode_offset (f, p, free_block); H5F_decode_length (f, p, fl->size); - assert (fl->offset + fl->size <= heap->disk_alloc); + if (fl->offset + fl->size > heap->disk_alloc) goto error; } - return heap; + + FUNC_LEAVE (heap); + error: if (heap) { heap->chunk = H5MM_xfree (heap->chunk); H5MM_xfree (heap); + for (fl=heap->freelist; fl; fl=tail) { + tail = fl->next; + H5MM_xfree (fl); + } } - return NULL; + HRETURN_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL); } @@ -214,12 +258,12 @@ error: * Purpose: Flushes a heap from memory to disk if it's dirty. Optionally * deletes the heap from memory. * - * Return: Success: 0 + * Return: Success: SUCCEED * - * Failure: -1 + * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 17 1997 * * Modifications: @@ -231,6 +275,13 @@ H5H_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5H_t *heap) { uint8 *p = heap->chunk; H5H_free_t *fl = heap->freelist; + + FUNC_ENTER (H5H_flush, NULL, FAIL); + + /* check arguments */ + assert (f); + assert (addr>0); + assert (heap); if (heap->dirty) { @@ -240,8 +291,11 @@ H5H_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5H_t *heap) * disk storage. */ if (heap->mem_alloc > heap->disk_alloc) { - H5MF_free (f, heap->addr, heap->disk_alloc); - heap->addr = H5MF_alloc (f, heap->mem_alloc); + haddr_t old_addr = heap->addr; + if ((heap->addr = H5MF_alloc (f, heap->mem_alloc))<0) { + HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL); + } + H5MF_free (f, old_addr, heap->disk_alloc); /*don't care if fail*/ heap->disk_alloc = heap->mem_alloc; } @@ -273,15 +327,15 @@ H5H_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5H_t *heap) if (heap->addr == addr + H5H_SIZEOF_HDR(f)) { if (H5F_block_write (f, addr, H5H_SIZEOF_HDR(f)+heap->disk_alloc, heap->chunk)<0) { - return -1; + HRETURN_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL); } } else { if (H5F_block_write (f, addr, H5H_SIZEOF_HDR(f), heap->chunk)<0) { - return -1; + HRETURN_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL); } if (H5F_block_write (f, heap->addr, heap->disk_alloc, heap->chunk + H5H_SIZEOF_HDR(f))<0) { - return -1; + HRETURN_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL); } } @@ -301,7 +355,7 @@ H5H_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5H_t *heap) H5MM_xfree (heap); } - return 0; + FUNC_LEAVE (SUCCEED); } @@ -319,12 +373,15 @@ H5H_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5H_t *heap) * Attempting to read past the end of an object may cause this * function to fail. * + * If the heap address ADDR is the constant H5H_GLOBAL then + * the address comes from the hdf5_file_t global heap field. + * * Return: Success: BUF (or the allocated buffer) * * Failure: NULL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 16 1997 * * Modifications: @@ -334,14 +391,26 @@ H5H_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5H_t *heap) void * H5H_read (hdf5_file_t *f, haddr_t addr, off_t offset, size_t size, void *buf) { - H5H_t *heap = H5AC_find (f, H5AC_HEAP, addr, NULL); + H5H_t *heap = NULL; + + FUNC_ENTER (H5H_read, NULL, NULL); + + /* check arguments */ + assert (f); + if (H5H_GLOBAL==addr) addr = f->smallobj_off; + assert (addr>0); + assert (offset>=0); - assert (offset>=0 && offsetmem_alloc); + if (NULL==(heap=H5AC_find (f, H5AC_HEAP, addr, NULL))) { + HRETURN_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL); + } + assert (offsetmem_alloc); assert (offset+size<=heap->mem_alloc); if (!buf) buf = H5MM_xmalloc (size); HDmemcpy (buf, heap->chunk+H5H_SIZEOF_HDR(f)+offset, size); - return buf; + + FUNC_LEAVE (buf); } @@ -358,6 +427,9 @@ H5H_read (hdf5_file_t *f, haddr_t addr, off_t offset, size_t size, void *buf) * byte offset of the object from the beginning of the heap and * may include an offset into the interior of the object. * + * If the heap address ADDR is the constant H5H_GLOBAL then + * the address comes from the hdf5_file_t global heap field. + * * Return: Success: Ptr to the object. The pointer points to * a chunk of memory large enough to hold the * object from the specified offset (usually @@ -368,7 +440,7 @@ H5H_read (hdf5_file_t *f, haddr_t addr, off_t offset, size_t size, void *buf) * Failure: NULL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 16 1997 * * Modifications: @@ -378,10 +450,24 @@ H5H_read (hdf5_file_t *f, haddr_t addr, off_t offset, size_t size, void *buf) const void * H5H_peek (hdf5_file_t *f, haddr_t addr, off_t offset) { - H5H_t *heap = H5AC_find (f, H5AC_HEAP, addr, NULL); + H5H_t *heap = NULL; + const void *retval = NULL; - assert (offset>=0 && offsetmem_alloc); - return heap->chunk+H5H_SIZEOF_HDR(f)+offset; + FUNC_ENTER (H5H_peek, NULL, NULL); + + /* check arguments */ + assert (f); + if (H5H_GLOBAL==addr) addr = f->smallobj_off; + assert (addr>0); + assert (offset>=0); + + if (NULL==(heap=H5AC_find (f, H5AC_HEAP, addr, NULL))) { + HRETURN_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL); + } + assert (offsetmem_alloc); + + retval = heap->chunk+H5H_SIZEOF_HDR(f)+offset; + FUNC_LEAVE (retval); } @@ -393,7 +479,7 @@ H5H_peek (hdf5_file_t *f, haddr_t addr, off_t offset) * Return: void * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 17 1997 * * Modifications: @@ -415,12 +501,15 @@ H5H_remove_free (H5H_t *heap, H5H_free_t *fl) * * Purpose: Inserts a new item into the heap. * + * If the heap address ADDR is the constant H5H_GLOBAL then + * the address comes from the hdf5_file_t global heap field. + * * Return: Success: Offset of new item within heap. * - * Failure: -1 + * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 17 1997 * * Modifications: @@ -430,11 +519,26 @@ H5H_remove_free (H5H_t *heap, H5H_free_t *fl) off_t H5H_insert (hdf5_file_t *f, haddr_t addr, size_t size, const void *buf) { - H5H_t *heap = H5AC_find (f, H5AC_HEAP, addr, NULL); + H5H_t *heap=NULL; H5H_free_t *fl=NULL, *max_fl=NULL; off_t offset = -1; size_t need_more; +#ifndef NDEBUG + static nmessages = 0; +#endif + + FUNC_ENTER (H5H_insert, NULL, FAIL); + + /* check arguments */ + assert (f); + if (H5H_GLOBAL==addr) addr = f->smallobj_off; + assert (addr>0); + assert (size>0); + assert (buf); + if (NULL==(heap=H5AC_find (f, H5AC_HEAP, addr, NULL))) { + HRETURN_ERROR (H5E_HEAP, H5E_CANTLOAD, FAIL); + } heap->dirty += 1; /* @@ -477,10 +581,16 @@ H5H_insert (hdf5_file_t *f, haddr_t addr, size_t size, const void *buf) max_fl->size += need_more - size; if (max_fl->size < H5H_SIZEOF_FREE(f)) { +#ifndef NDEBUG if (max_fl->size) { fprintf (stderr, "H5H_insert: lost %d bytes at line %d\n", max_fl->size, __LINE__); + if (0==nmessages++) { + fprintf (stderr, "Messages from H5H_insert() will go away " + "when assertions are turned off.\n"); + } } +#endif H5H_remove_free (heap, max_fl); } @@ -498,15 +608,27 @@ H5H_insert (hdf5_file_t *f, haddr_t addr, size_t size, const void *buf) fl->next = heap->freelist; if (heap->freelist) heap->freelist->prev = fl; heap->freelist = fl; +#ifndef NDEBUG } else if (need_more>size) { fprintf (stderr, "H5H_insert: lost %d bytes at line %d\n", need_more-size, __LINE__); + if (0==nmessages++) { + fprintf (stderr, "Messages from H5H_insert() will go away " + "when assertions are turned off.\n"); + } +#endif } } +#ifndef NDEBUG fprintf (stderr, "H5H_insert: resize mem buf from %lu to %lu bytes\n", (unsigned long)(heap->mem_alloc), (unsigned long)(heap->mem_alloc + need_more)); + if (0==nmessages++) { + fprintf (stderr, "Messages from H5H_insert() will go away " + "when assertions are turned off.\n"); + } +#endif heap->mem_alloc += need_more; heap->chunk = H5MM_xrealloc (heap->chunk, H5H_SIZEOF_HDR(f)+heap->mem_alloc); @@ -516,7 +638,7 @@ H5H_insert (hdf5_file_t *f, haddr_t addr, size_t size, const void *buf) * Copy the data into the heap */ HDmemcpy (heap->chunk + H5H_SIZEOF_HDR(f) + offset, buf, size); - return offset; + FUNC_LEAVE (offset); } @@ -531,12 +653,15 @@ H5H_insert (hdf5_file_t *f, haddr_t addr, size_t size, const void *buf) * Do not partially write an object to create it; the first * write for an object must be for the entire object. * - * Return: Success: 0 + * If the heap address ADDR is the constant H5H_GLOBAL then + * the address comes from the hdf5_file_t global heap field. * - * Failure: -1 + * Return: Success: SUCCEED + * + * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 16 1997 * * Modifications: @@ -547,15 +672,27 @@ herr_t H5H_write (hdf5_file_t *f, haddr_t addr, off_t offset, size_t size, const void *buf) { - H5H_t *heap = H5AC_find (f, H5AC_HEAP, addr, NULL); + H5H_t *heap = NULL; - assert (offset>=0 && offsetmem_alloc); - assert (offset+size<=heap->mem_alloc); + FUNC_ENTER (H5H_write, NULL, FAIL); + + /* check arguments */ + assert (f); + if (H5H_GLOBAL==addr) addr = f->smallobj_off; + assert (addr>0); + assert (offset>=0); assert (buf); + if (NULL==(heap=H5AC_find (f, H5AC_HEAP, addr, NULL))) { + HRETURN_ERROR (H5E_HEAP, H5E_CANTLOAD, FAIL); + } + assert (offsetmem_alloc); + assert (offset+size<=heap->mem_alloc); + heap->dirty += 1; HDmemcpy (heap->chunk+H5H_SIZEOF_HDR(f)+offset, buf, size); - return 0; + + FUNC_LEAVE (SUCCEED); } @@ -575,12 +712,15 @@ H5H_write (hdf5_file_t *f, haddr_t addr, off_t offset, size_t size, * in two separate objects, one at the original offset and * one at the first offset past the removed portion. * - * Return: Success: 0 + * If the heap address ADDR is the constant H5H_GLOBAL then + * the address comes from the hdf5_file_t global heap field. * - * Failure: -1 + * Return: Success: SUCCEED + * + * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 16 1997 * * Modifications: @@ -590,10 +730,25 @@ H5H_write (hdf5_file_t *f, haddr_t addr, off_t offset, size_t size, herr_t H5H_remove (hdf5_file_t *f, haddr_t addr, off_t offset, size_t size) { - H5H_t *heap = H5AC_find (f, H5AC_HEAP, addr, NULL); + H5H_t *heap = NULL; H5H_free_t *fl = heap->freelist, *fl2 = NULL; +#ifndef NDEBUG + static int nmessages = 0; +#endif + + FUNC_ENTER (H5H_remove, NULL, FAIL); - assert (offset>=0 && offsetmem_alloc); + /* check arguments */ + assert (f); + if (H5H_GLOBAL==addr) addr = f->smallobj_off; + assert (addr>0); + assert (offset>=0); + assert (size>0); + + if (NULL==(heap=H5AC_find (f, H5AC_HEAP, addr, NULL))) { + HRETURN_ERROR (H5E_HEAP, H5E_CANTLOAD, FAIL); + } + assert (offsetmem_alloc); assert (offset+size<=heap->mem_alloc); heap->dirty += 1; @@ -613,10 +768,10 @@ H5H_remove (hdf5_file_t *f, haddr_t addr, off_t offset, size_t size) fl->offset = fl2->offset; fl->size += fl2->size; H5H_remove_free (heap, fl2); - return 0; + HRETURN (SUCCEED); } } - return 0; + HRETURN (SUCCEED); } else if (fl->offset + fl->size == offset) { fl->size += size; @@ -625,10 +780,10 @@ H5H_remove (hdf5_file_t *f, haddr_t addr, off_t offset, size_t size) if (fl->offset + fl->size == fl2->offset) { fl->size += fl2->size; H5H_remove_free (heap, fl2); - return 0; + HRETURN (SUCCEED); } } - return 0; + HRETURN (SUCCEED); } fl = fl->next; @@ -641,8 +796,14 @@ H5H_remove (hdf5_file_t *f, haddr_t addr, off_t offset, size_t size) * lost. */ if (size < H5H_SIZEOF_FREE(f)) { +#ifndef NDEUBG fprintf (stderr, "H5H_remove: lost %d bytes\n", size); - return 0; + if (0==nmessages++) { + fprintf (stderr, "Messages from H5H_remove() will go away " + "when assertions are turned off.\n"); + } +#endif + HRETURN (SUCCEED); } /* @@ -656,7 +817,7 @@ H5H_remove (hdf5_file_t *f, haddr_t addr, off_t offset, size_t size) if (heap->freelist) heap->freelist->prev = fl; heap->freelist = fl; - return 0; + FUNC_LEAVE (SUCCEED); } @@ -665,12 +826,15 @@ H5H_remove (hdf5_file_t *f, haddr_t addr, off_t offset, size_t size) * * Purpose: Prints debugging information about a heap. * - * Return: Success: 0 + * If the heap address ADDR is the constant H5H_GLOBAL then + * the address comes from the hdf5_file_t global heap field. * - * Failure: -1 + * Return: Success: SUCCEED + * + * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Aug 1 1997 * * Modifications: @@ -681,14 +845,26 @@ herr_t H5H_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent, intn fwidth) { - H5H_t *h = H5AC_find (f, H5AC_HEAP, addr, NULL); + H5H_t *h = NULL; int i, j, overlap; uint8 c; H5H_free_t *freelist=NULL; uint8 *marker = NULL; size_t amount_free = 0; - if (!h) return -1; + FUNC_ENTER (H5H_debug, NULL, FAIL); + + /* check arguments */ + assert (f); + if (H5H_GLOBAL==addr) addr = f->smallobj_off; + assert (addr>0); + assert (stream); + assert (indent>=0); + assert (fwidth>=0); + + if (NULL==(h=H5AC_find (f, H5AC_HEAP, addr, NULL))) { + HRETURN_ERROR (H5E_HEAP, H5E_CANTLOAD, FAIL); + } fprintf (stream, "%*sHeap...\n", indent, ""); fprintf (stream, "%*s%-*s %d\n", indent, "", fwidth, @@ -771,5 +947,5 @@ H5H_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent, } H5MM_xfree (marker); - return 0; + FUNC_LEAVE (SUCCEED); } diff --git a/src/H5Hprivate.h b/src/H5Hprivate.h index 0c31df3..dc5318f 100644 --- a/src/H5Hprivate.h +++ b/src/H5Hprivate.h @@ -6,7 +6,7 @@ * * Created: H5Hprivate.h * Jul 16 1997 - * Robb Matzke + * Robb Matzke * * Purpose: * @@ -23,10 +23,15 @@ #define H5H_MAGIC "HEAP" /*heap magic number */ #define H5H_SIZEOF_MAGIC 4 +typedef enum H5H_type_t { + H5H_LOCAL =0, /*local symtab name heap */ + H5H_GLOBAL =1 /*global small object heap */ +} H5H_type_t; + /* * Library prototypes... */ -haddr_t H5H_new (hdf5_file_t *f, size_t size_hint); +haddr_t H5H_new (hdf5_file_t *f, H5H_type_t type, size_t size_hint); void *H5H_read (hdf5_file_t *f, haddr_t addr, off_t offset, size_t size, void *buf); const void *H5H_peek (hdf5_file_t *f, haddr_t addr, off_t offset); diff --git a/src/H5Hproto.h b/src/H5Hproto.h index fcf36f8..93661ac 100644 --- a/src/H5Hproto.h +++ b/src/H5Hproto.h @@ -6,7 +6,7 @@ * * Created: H5Hproto.h * Jul 16 1997 - * Robb Matzke + * Robb Matzke * * Purpose: * diff --git a/src/H5MF.c b/src/H5MF.c index 16c2746..b6900cc 100644 --- a/src/H5MF.c +++ b/src/H5MF.c @@ -6,20 +6,29 @@ * * Created: H5MF.c * Jul 11 1997 - * Robb Matzke + * Robb Matzke * * Purpose: File memory management functions. * - * Modifications: + * Modifications: + * + * Robb Matzke, 5 Aug 1997 + * Added calls to H5E. * *------------------------------------------------------------------------- */ #include #include "hdf5.h" +#include "H5private.h" #include "H5Fprivate.h" #include "H5MFprivate.h" +#define PABLO_MASK H5MF_mask + +/* Is the interface initialized? */ +static intn interface_initialize_g = FALSE; + /*------------------------------------------------------------------------- * Function: H5MF_alloc @@ -30,10 +39,10 @@ * * Return: Success: File address of new chunk. * - * Failure: -1 + * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 11 1997 * * Modifications: @@ -44,14 +53,19 @@ haddr_t H5MF_alloc (hdf5_file_t *f, size_t size) { haddr_t addr; - + + FUNC_ENTER (H5MF_alloc, NULL, FAIL); + + /* check arguments */ assert (f); assert (f->logical_len>0); assert (size>0); + /* reserve space from the end of the file */ addr = f->logical_len; f->logical_len += size; - return addr; + + FUNC_LEAVE (addr); } @@ -68,7 +82,7 @@ H5MF_alloc (hdf5_file_t *f, size_t size) * Failure: -1 * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 17 1997 * * Modifications: @@ -78,11 +92,17 @@ H5MF_alloc (hdf5_file_t *f, size_t size) herr_t H5MF_free (hdf5_file_t *f, haddr_t addr, size_t size) { - if (addr<=0 || 0==size) return 0; + FUNC_ENTER (H5MF_free, NULL, FAIL); + /* check arguments */ + assert (f); + if (addr<=0 || 0==size) HRETURN (SUCCEED); + +#ifndef NDEBUG fprintf (stderr, "H5MF_free: lost %lu bytes of file storage\n", (unsigned long)size); - - return 0; +#endif + + FUNC_LEAVE (SUCCEED); } diff --git a/src/H5MFprivate.h b/src/H5MFprivate.h index 19265ac..e87ca58 100644 --- a/src/H5MFprivate.h +++ b/src/H5MFprivate.h @@ -6,7 +6,7 @@ * * Created: H5MFprivate.h * Jul 11 1997 - * Robb Matzke + * Robb Matzke * * Purpose: Private header file for file memory management. * diff --git a/src/H5MFproto.h b/src/H5MFproto.h index 3b54ecd..72e24f6 100644 --- a/src/H5MFproto.h +++ b/src/H5MFproto.h @@ -6,7 +6,7 @@ * * Created: H5MFproto.h * Jul 11 1997 - * Robb Matzke + * Robb Matzke * * Purpose: Prototypes for file memory management. * diff --git a/src/H5MM.c b/src/H5MM.c index 725085f..74cce42 100644 --- a/src/H5MM.c +++ b/src/H5MM.c @@ -6,7 +6,7 @@ * * Created: H5MM.c * Jul 10 1997 - * Robb Matzke + * Robb Matzke * * Purpose: Memory management functions. * @@ -30,7 +30,7 @@ * Failure: abort() * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 10 1997 * * Modifications: @@ -56,7 +56,7 @@ H5MM_xmalloc (size_t size) * Failure: abort() * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 10 1997 * * Modifications: @@ -89,7 +89,7 @@ H5MM_xcalloc (size_t n, size_t size) * Failure: abort() * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 10 1997 * * Modifications: @@ -127,7 +127,7 @@ H5MM_xrealloc (void *mem, size_t size) * Failure: abort() * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 10 1997 * * Modifications: @@ -160,7 +160,7 @@ H5MM_xstrdup (const char *s) * Failure: never fails * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 10 1997 * * Modifications: diff --git a/src/H5MMprivate.h b/src/H5MMprivate.h index 68dd73b..f4890df 100644 --- a/src/H5MMprivate.h +++ b/src/H5MMprivate.h @@ -6,7 +6,7 @@ * * Created: H5MMprivate.h * Jul 10 1997 - * Robb Matzke + * Robb Matzke * * Purpose: Private header for memory management. * diff --git a/src/H5MMproto.h b/src/H5MMproto.h index e1598f8..c4ef18f 100644 --- a/src/H5MMproto.h +++ b/src/H5MMproto.h @@ -6,7 +6,7 @@ * * Created: H5MMproto.h * Jul 10 1997 - * Robb Matzke + * Robb Matzke * * Purpose: Function prototypes for memory management. * diff --git a/src/H5O.c b/src/H5O.c new file mode 100644 index 0000000..6e899fc --- /dev/null +++ b/src/H5O.c @@ -0,0 +1,1242 @@ +/*------------------------------------------------------------------------- + * Copyright (C) 1997 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + * + * Created: H5O.c + * Aug 5 1997 + * Robb Matzke + * + * Purpose: Object header virtual functions. + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#include + +#include "hdf5.h" + +#include "H5private.h" +#include "H5ACprivate.h" +#include "H5Fprivate.h" +#include "H5MFprivate.h" +#include "H5MMprivate.h" +#include "H5Oprivate.h" + +#define PABLO_MASK H5O_mask + +/* PRIVATE PROTOTYPES */ +static herr_t H5O_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, + H5O_t *oh); +static H5O_t *H5O_load (hdf5_file_t *f, haddr_t addr, const void *_data); +static intn H5O_find_in_ohdr (hdf5_file_t *f, haddr_t addr, + const H5O_class_t **type_p, intn sequence); +static intn H5O_alloc (hdf5_file_t *f, H5O_t *oh, const H5O_class_t *type, + size_t size); +static intn H5O_alloc_extend_chunk (H5O_t *oh, intn chunkno, size_t size); +static intn H5O_alloc_new_chunk (hdf5_file_t *f, H5O_t *oh, size_t size); + +/* H5O inherits cache-like properties from H5AC */ +static const H5AC_class_t H5AC_OHDR[1] = {{ + (void*(*)(hdf5_file_t*,haddr_t,const void*))H5O_load, + (herr_t(*)(hdf5_file_t*,hbool_t,haddr_t,void*))H5O_flush, +}}; + +/* Is the interface initialized? */ +static intn interface_initialize_g = FALSE; + +/* ID to type mapping */ +static const H5O_class_t *const message_type_g[] = { + H5O_NULL, /*0x0000 Null */ + NULL, /*0x0001 Simple dimensionality */ + NULL, /*0x0002 Data space (fiber bundle?) */ + NULL, /*0x0003 Simple data type */ + NULL, /*0x0004 Compound data type */ + NULL, /*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 */ + NULL, /*0x000B Data storage -- compressed object */ + NULL, /*0x000C Attribute list */ + NULL, /*0x000D Object name */ + NULL, /*0x000E Object modification date and time */ + NULL, /*0x000F Shared header message */ + H5O_CONT, /*0x0010 Object header continuation */ + H5O_STAB, /*0x0011 Symbol table */ +}; + + +/*------------------------------------------------------------------------- + * Function: H5O_new + * + * Purpose: Creates a new object header, sets the link count + * to NLINK, and caches the header. + * + * Return: Success: Address of new header. + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 5 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +haddr_t +H5O_new (hdf5_file_t *f, intn nlink, size_t size_hint) +{ + size_t size; /*total size of object header */ + haddr_t addr = FAIL; /*address of object header */ + H5O_t *oh = NULL; + + FUNC_ENTER (H5O_new, NULL, FAIL); + + /* check args */ + assert (f); + assert (nlink>0); + if (size_hintdirty = TRUE; + oh->version = H5O_VERSION; + oh->alignment = H5O_ALIGNMENT; + oh->nlink = nlink; + + /* create the chunk list and initialize the first chunk */ + oh->nchunks = 1; + oh->alloc_nchunks = H5O_NCHUNKS; + oh->chunk = H5MM_xmalloc (oh->alloc_nchunks * sizeof (H5O_chunk_t)); + + oh->chunk[0].dirty = TRUE; + oh->chunk[0].addr = addr + H5O_SIZEOF_HDR(f); + oh->chunk[0].size = size_hint; + oh->chunk[0].image = H5MM_xmalloc (size_hint); + + /* create the message list and initialize the first message */ + oh->nmesgs = 1; + oh->alloc_nmesgs = H5O_NMESGS; + oh->mesg = H5MM_xcalloc (oh->alloc_nmesgs, sizeof(H5O_mesg_t)); + + oh->mesg[0].type = H5O_NULL; + oh->mesg[0].dirty = TRUE; + oh->mesg[0].native = NULL; + oh->mesg[0].raw = oh->chunk[0].image + 4; /*skip id and size fields */ + oh->mesg[0].raw_size = size_hint - 4; + oh->mesg[0].chunkno = 0; + + /* cache it */ + if (H5AC_set (f, H5AC_OHDR, addr, oh)<0) { + H5MM_xfree (oh); + HRETURN_ERROR (H5E_OHDR, H5E_CANTINIT, FAIL); + } + + FUNC_LEAVE (addr); +} + + +/*------------------------------------------------------------------------- + * Function: H5O_load + * + * Purpose: Loads an object header from disk. + * + * Return: Success: Pointer to the new object header. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 5 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static H5O_t * +H5O_load (hdf5_file_t *f, haddr_t addr, const void *_data) +{ + H5O_t *oh = NULL; + uint8 buf[16], *p; + size_t hdr_size, mesg_size; + uintn id; + intn mesgno, chunkno, curmesg=0, nmesgs; + haddr_t chunk_addr; + size_t chunk_size; + H5O_cont_t *cont=NULL; + + FUNC_ENTER (H5O_load, NULL, NULL); + + /* check args */ + assert (f); + assert (addr>=0); + assert (!_data); + + /* allocate ohdr and init chunk list */ + oh = H5MM_xcalloc (1, sizeof(H5O_t)); + + /* read fixed-lenth part of object header */ + hdr_size = H5O_SIZEOF_HDR (f); + if (H5F_block_read (f, addr, hdr_size, buf)<0) { + HRETURN_ERROR (H5E_OHDR, H5E_READERROR, NULL); + } + p = buf; + + /* decode version */ + oh->version = *p++; + if (H5O_VERSION!=oh->version) { + HRETURN_ERROR (H5E_OHDR, H5E_VERSION, NULL); + } + + /* decode alignment */ + oh->alignment = *p++; + if (4!=oh->alignment) { + HRETURN_ERROR (H5E_OHDR, H5E_ALIGNMENT, NULL); + } + + /* decode number of messages */ + UINT16DECODE (p, nmesgs); + + /* decode link count */ + UINT32DECODE (p, oh->nlink); + + /* decode first chunk info */ + chunk_addr = addr + H5O_SIZEOF_HDR(f); + UINT32DECODE (p, chunk_size); + + /* build the message array */ + oh->alloc_nmesgs = MAX (H5O_NMESGS, nmesgs); + oh->mesg = H5MM_xcalloc (oh->alloc_nmesgs, sizeof(H5O_mesg_t)); + + /* read each chunk from disk */ + while (chunk_addr) { + + /* increase chunk array size */ + if (oh->nchunks>=oh->alloc_nchunks) { + oh->alloc_nchunks += H5O_NCHUNKS; + oh->chunk = H5MM_xrealloc (oh->chunk, + oh->alloc_nchunks * sizeof(H5O_chunk_t)); + } + + /* read the chunk raw data */ + chunkno = oh->nchunks++; + oh->chunk[chunkno].dirty = FALSE; + oh->chunk[chunkno].addr = chunk_addr; + oh->chunk[chunkno].size = chunk_size; + oh->chunk[chunkno].image = H5MM_xmalloc (chunk_size); + if (H5F_block_read (f, chunk_addr, chunk_size, + oh->chunk[chunkno].image)<0) { + HRETURN_ERROR (H5E_OHDR, H5E_READERROR, NULL); + } + + + /* load messages from this chunk */ + for (p = oh->chunk[chunkno].image; + p < oh->chunk[chunkno].image + chunk_size; + p += mesg_size) { + UINT16DECODE (p, id); + UINT16DECODE (p, mesg_size); + + if (id>=NELMTS(message_type_g) || NULL==message_type_g[id]) { + HRETURN_ERROR (H5E_OHDR, H5E_BADMESG, NULL); + } + if (p + mesg_size > oh->chunk[chunkno].image + chunk_size) { + HRETURN_ERROR (H5E_OHDR, H5E_CANTINIT, NULL); + } + + mesgno = oh->nmesgs++; + if (mesgno>=nmesgs) { + HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, NULL); + } + oh->mesg[mesgno].type = message_type_g[id]; + oh->mesg[mesgno].dirty = FALSE; + oh->mesg[mesgno].native = NULL; + oh->mesg[mesgno].raw = p; + oh->mesg[mesgno].raw_size = mesg_size; + oh->mesg[mesgno].chunkno = chunkno; + } + assert (p == oh->chunk[chunkno].image + chunk_size); + + /* decode next object header continuation message */ + for (chunk_addr=0; 0==chunk_addr && curmesgnmesgs; curmesg++) { + if (H5O_CONT_ID==oh->mesg[curmesg].type->id) { + uint8 *p2 = oh->mesg[curmesg].raw; + oh->mesg[curmesg].native = (H5O_CONT->decode)(f, p2); + cont = (H5O_cont_t*)(oh->mesg[curmesg].native); + chunk_addr = cont->addr; + chunk_size = cont->size; + cont->chunkno = oh->nchunks; /*the next chunk to allocate*/ + } + } + } + + FUNC_LEAVE (oh); +} + + +/*------------------------------------------------------------------------- + * Function: H5O_flush + * + * Purpose: Flushes (and destroys) an object header. + * + * Return: Success: SUCCESS + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 5 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5O_t *oh) +{ + uint8 buf[16], *p; + int i; + H5O_cont_t *cont = NULL; + + FUNC_ENTER (H5O_flush, NULL, FAIL); + + /* check args */ + assert (f); + assert (addr>=0); + assert (oh); + + /* flush */ + if (oh->dirty) { + p = buf; + + /* encode version */ + *p++ = oh->version; + + /* encode alingment */ + *p++ = oh->alignment; + + /* encode number of messages */ + UINT16ENCODE (p, oh->nmesgs); + + /* encode link count */ + UINT32ENCODE (p, oh->nlink); + + /* encode body size */ + UINT32ENCODE (p, oh->chunk[0].size); + + /* write the object header header */ + if (H5F_block_write (f, addr, H5O_SIZEOF_HDR(f), buf)<0) { + HRETURN_ERROR (H5E_OHDR, H5E_WRITEERROR, FAIL); + } + + /* encode messages */ + for (i=0; inmesgs; i++) { + if (oh->mesg[i].dirty) { + p = oh->mesg[i].raw - 4; + UINT16ENCODE (p, oh->mesg[i].type->id); + UINT16ENCODE (p, oh->mesg[i].raw_size); + if (oh->mesg[i].native) { + assert (oh->mesg[i].type->encode); + + /* allocate file space for chunks that have none yet */ + if (H5O_CONT_ID==oh->mesg[i].type->id && + ((H5O_cont_t*)(oh->mesg[i].native))->addr<0) { + cont = (H5O_cont_t*)(oh->mesg[i].native); + assert (cont->chunkno >= 0); + assert (cont->chunkno < oh->nchunks); + assert (oh->chunk[cont->chunkno].addr<0); + cont->size = oh->chunk[cont->chunkno].size; + cont->addr = H5MF_alloc (f, cont->size); + if (cont->addr<0) { + HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL); + } + oh->chunk[cont->chunkno].addr = cont->addr; + } + + /* encode the message */ + assert (oh->mesg[i].raw >= + oh->chunk[oh->mesg[i].chunkno].image); + assert (oh->mesg[i].raw + oh->mesg[i].raw_size <= + oh->chunk[oh->mesg[i].chunkno].image + + oh->chunk[oh->mesg[i].chunkno].size); + if ((oh->mesg[i].type->encode)(f, oh->mesg[i].raw_size, + oh->mesg[i].raw, + oh->mesg[i].native)<0) { + HRETURN_ERROR (H5E_OHDR, H5E_CANTENCODE, FAIL); + } + } + oh->mesg[i].dirty = FALSE; + oh->chunk[oh->mesg[i].chunkno].dirty = TRUE; + } + } + + /* write each chunk to disk */ + for (i=0; inchunks; i++) { + if (oh->chunk[i].dirty) { + assert (oh->chunk[i].addr>0); + if (H5F_block_write (f, oh->chunk[i].addr, oh->chunk[i].size, + oh->chunk[i].image)<0) { + HRETURN_ERROR (H5E_OHDR, H5E_WRITEERROR, FAIL); + } + oh->chunk[i].dirty = FALSE; + } + } + oh->dirty = FALSE; + } + + + if (destroy) { + /* destroy chunks */ + for (i=0; inchunks; i++) { + oh->chunk[i].image = H5MM_xfree (oh->chunk[i].image); + } + oh->chunk = H5MM_xfree (oh->chunk); + + /* destroy messages */ + for (i=0; inmesgs; i++) { + if (oh->mesg[i].native) { + if (oh->mesg[i].type->free) { + (oh->mesg[i].type->free)(oh->mesg[i].native); + oh->mesg[i].native = NULL; + } else { + oh->mesg[i].native = H5MM_xfree (oh->mesg[i].native); + } + } + } + oh->mesg = H5MM_xfree (oh->mesg); + + /* destroy object header */ + H5MM_xfree (oh); + } + + FUNC_LEAVE (SUCCEED); +} + + +/*------------------------------------------------------------------------- + * Function: H5O_link + * + * Purpose: Adjust the link count for an object header by adding + * ADJUST to the link count. + * + * Return: Success: New link count + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 5 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +intn +H5O_link (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent, intn adjust) +{ + H5O_t *oh = NULL; + + FUNC_ENTER (H5O_link, NULL, FAIL); + + /* check args */ + assert (f); + assert (addr>=0); + + /* get header */ + if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) { + HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL); + } + + /* adjust link count */ + if (adjust<0) { + if (oh->nlink + adjust < 0) { + HRETURN_ERROR (H5E_OHDR, H5E_LINKCOUNT, FAIL); + } + oh->nlink += adjust; + if (1==oh->nlink && ent) { + fprintf (stderr, "H5O_link: no symbol table entry caching " + "(not implemented yet)\n"); + } + } else { + oh->nlink += adjust; + if (oh->nlink>1 && ent) ent->type = H5G_NOTHING_CACHED; + } + + + oh->dirty = TRUE; + FUNC_LEAVE (oh->nlink); +} + + +/*------------------------------------------------------------------------- + * Function: H5O_read + * + * Purpose: Reads a message from an object header and returns a pointer + * to it. The caller will usually supply the memory through + * MESG and the return value will be MESG. But if MESG is + * the null pointer, then this function will malloc() memory + * to hold the result and return its pointer instead. + * + * Return: Success: Ptr to message in native format. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 6 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void * +H5O_read (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent, + const H5O_class_t *type, intn sequence, void *mesg) +{ + H5O_t *oh = NULL; + void *retval = NULL; + intn idx; + + FUNC_ENTER (H5O_read, NULL, NULL); + + /* check args */ + assert (f); + assert (addr>=0); + assert (sequence>=0); + + /* can we get it from the symbol table? */ + if (ent && H5G_NOTHING_CACHED!=ent->type && type && type->fast) { + retval = (type->fast)(ent, mesg); + if (retval) HRETURN (retval); + H5ECLEAR; + } + + /* can we get it from the object header? */ + if ((idx = H5O_find_in_ohdr (f, addr, &type, sequence))<0) { + HRETURN_ERROR (H5E_OHDR, H5E_NOTFOUND, NULL); + } + + /* copy the message to the user-supplied buffer */ + if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) { + HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, NULL); + } + retval = (type->copy)(oh->mesg[idx].native, mesg); + if (!retval) HRETURN_ERROR (H5E_OHDR, H5E_CANTINIT, NULL); + + FUNC_LEAVE (retval); +} + + +/*------------------------------------------------------------------------- + * Function: H5O_find_in_ohdr + * + * Purpose: Find a message in the object header without consulting + * a symbol table entry. + * + * Return: Success: Index number of message. + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 6 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static intn +H5O_find_in_ohdr (hdf5_file_t *f, haddr_t addr, const H5O_class_t **type_p, + intn sequence) +{ + H5O_t *oh = NULL; + int i; + + FUNC_ENTER (H5O_find_in_ohdr, NULL, FAIL); + + /* check args */ + assert (f); + assert (addr>=0); + assert (type_p); + + /* load the object header */ + if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) { + HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL); + } + + /* scan through the messages looking for the right one */ + for (i=0; inmesgs; i++) { + if (*type_p && (*type_p)->id!=oh->mesg[i].type->id) continue; + if (--sequence<0) break; + } + if (sequence>=0) HRETURN_ERROR (H5E_OHDR, H5E_NOTFOUND, FAIL); + + /* decode the message if necessary */ + if (NULL==oh->mesg[i].native) { + assert (oh->mesg[i].type->decode); + oh->mesg[i].native = (oh->mesg[i].type->decode)(f, oh->mesg[i].raw); + if (NULL==oh->mesg[i].native) { + HRETURN_ERROR (H5E_OHDR, H5E_CANTDECODE, FAIL); + } + } + + /*return the message type */ + *type_p = oh->mesg[i].type; + + FUNC_LEAVE (i); +} + + +/*------------------------------------------------------------------------- + * Function: H5O_peek + * + * Purpose: Returns a pointer to a message stored in native format. + * The returned memory is read-only, and points directly into + * the cache. It is therefore valid only until the next cache + * function is called. + * + * Return: Success: Ptr to read-only message in native format. + * The pointer is guranteed to be valid only + * until the next call (directly or indirectly) + * to an H5AC function. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 6 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +const void * +H5O_peek (hdf5_file_t *f, haddr_t addr, const H5O_class_t *type, + intn sequence) +{ + intn idx; + H5O_t *oh = NULL; + + FUNC_ENTER (H5O_peek, NULL, NULL); + + /* check args */ + assert (f); + assert (addr>=0); + + 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))) { + HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, NULL); + } + + FUNC_LEAVE (oh->mesg[idx].native); +} + + +/*------------------------------------------------------------------------- + * Function: H5O_modify + * + * Purpose: Modifies an existing message or creates a new message. + * The object header is at file address ADDR of file F. An + * optional symbol table entry ENT can be supplied in which + * case the cache fields in that symbol table are updated if + * appropriate. If the symbol table entry changes then the + * optional ENT_MODIFIED arg will point to a non-zero value. + * + * The OVERWRITE argument is either a sequence number of a + * message to overwrite (usually zero) or the constant + * H5O_NEW_MESSAGE (-1) to indicate that a new message is to + * be created. + * + * Return: Success: The sequence number of the message that + * was modified or created. + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 6 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +intn +H5O_modify (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent, + hbool_t *ent_modified, const H5O_class_t *type, + intn overwrite, const void *mesg) +{ + H5O_t *oh = NULL; + intn idx, sequence; + size_t size; + + FUNC_ENTER (H5O_modify, NULL, FAIL); + + /* check args */ + assert (f); + assert (addr>=0); + assert (type); + assert (mesg); + + if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) { + HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL); + } + + /* Count similar messages */ + for (idx=sequence=0; idxnmesgs; idx++) { + if (type->id != oh->mesg[idx].type->id) continue; + if (sequence==overwrite) break; + sequence++; + } + + /* Was the right message found? */ + if (overwrite>=0 && sequence!=overwrite) { + HRETURN_ERROR (H5E_OHDR, H5E_NOTFOUND, FAIL); + } + + /* Allocate space for the new message */ + if (overwrite<0) { + size = (type->size)(f, mesg); + H5O_ALIGN (size, oh->alignment); + idx = H5O_alloc (f, oh, type, size); + if (idx<0) HRETURN_ERROR (H5E_OHDR, H5E_CANTINIT, FAIL); + } + + /* Copy the native value into the object header */ + oh->mesg[idx].native = (type->copy)(mesg, oh->mesg[idx].native); + if (NULL==oh->mesg[idx].native) { + HRETURN_ERROR (H5E_OHDR, H5E_CANTINIT, FAIL); + } + oh->mesg[idx].dirty = TRUE; + oh->dirty = TRUE; + + /* Copy into the symbol table entry */ + if (1==oh->nlink && ent && type->cache) { + hbool_t modified = (type->cache)(ent, mesg); + if (ent_modified) *ent_modified = modified; + } + + FUNC_LEAVE (sequence); +} + + +/*------------------------------------------------------------------------- + * Function: H5O_alloc_extend_chunk + * + * Purpose: Extends a chunk which hasn't been allocated on disk yet + * to make the chunk large enough to contain a message whose + * data size is at least SIZE bytes. + * + * If the last message of the chunk is the null message, then + * that message will be extended with the chunk. Otherwise a + * new null message is created. + * + * Return: Success: Message index for null message which + * is large enough to hold SIZE bytes. + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 7 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static intn +H5O_alloc_extend_chunk (H5O_t *oh, intn chunkno, size_t size) +{ + intn idx, i; + size_t delta; + uint8 *old_addr; + + FUNC_ENTER (H5O_alloc_extend_chunk, NULL, FAIL); + + /* check args */ + assert (oh); + assert (chunkno>=0 && chunknonchunks); + assert (size>0); + + if (H5O_NO_ADDR!=oh->chunk[chunkno].addr) { + HRETURN_ERROR (H5E_OHDR, H5E_NOSPACE, FAIL); /*chunk is on disk*/ + } + + /* try to extend a null message */ + for (idx=0; idxnmesgs; idx++) { + if (H5O_NULL_ID==oh->mesg[idx].type->id && + (oh->mesg[idx].raw + oh->mesg[idx].raw_size == + oh->chunk[chunkno].image + oh->chunk[chunkno].size)) { + + delta = MAX (H5O_MIN_SIZE, size-oh->mesg[idx].raw_size); + H5O_ALIGN (delta, oh->alignment); + oh->mesg[idx].dirty = TRUE; + oh->mesg[idx].raw_size += delta; + + old_addr = oh->chunk[chunkno].image; + oh->chunk[chunkno].size += delta; + oh->chunk[chunkno].image = H5MM_xrealloc (old_addr, + oh->chunk[chunkno].size); + + /* adjust raw addresses for messages of this chunk */ + if (old_addr != oh->chunk[chunkno].image) { + for (i=0; inmesgs; i++) { + if (oh->mesg[i].chunkno==chunkno) { + oh->mesg[i].raw = oh->chunk[chunkno].image + + (oh->mesg[i].raw - old_addr); + } + } + } + HRETURN (idx); + } + } + + /* create a new null message */ + if (oh->nmesgs >= oh->alloc_nmesgs) { + oh->alloc_nmesgs += H5O_NMESGS; + oh->mesg = H5MM_xrealloc (oh->mesg, + oh->alloc_nmesgs * sizeof(H5O_mesg_t)); + } + + delta = MAX (H5O_MIN_SIZE, 4+size); + H5O_ALIGN (delta, oh->alignment); + idx = oh->nmesgs++; + oh->mesg[idx].type = H5O_NULL; + oh->mesg[idx].dirty = TRUE; + oh->mesg[idx].native = NULL; + oh->mesg[idx].raw = oh->chunk[chunkno].image + oh->chunk[chunkno].size + 4; + oh->mesg[idx].raw_size = delta-4; + oh->mesg[idx].chunkno = chunkno; + + old_addr = oh->chunk[chunkno].image; + oh->chunk[chunkno].size += delta; + oh->chunk[chunkno].image = H5MM_xrealloc (old_addr, + oh->chunk[chunkno].size); + + /* adjust raw addresses for messages of this chunk */ + if (old_addr != oh->chunk[chunkno].image) { + for (i=0; inmesgs; i++) { + if (oh->mesg[i].chunkno==chunkno) { + oh->mesg[i].raw = oh->chunk[chunkno].image + + (oh->mesg[i].raw - old_addr); + } + } + } + + FUNC_LEAVE (idx); +} + + +/*------------------------------------------------------------------------- + * Function: H5O_alloc_new_chunk + * + * Purpose: Allocates a new chunk for the object header but doen't + * give the new chunk a file address yet. One of the other + * chunks will get an object continuation message. If there + * isn't room in any other chunk for the object continuation + * message, then some message from another chunk is moved into + * this chunk to make room. + * + * Return: Success: Index number of the null message for the + * new chunk. The null message will be at + * least SIZE bytes not counting the message + * ID or size fields. + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 7 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static intn +H5O_alloc_new_chunk (hdf5_file_t *f, H5O_t *oh, size_t size) +{ + size_t cont_size; /*continuation message size */ + intn found_null=(-1); /*best fit null message */ + intn found_other=(-1); /*best fit other message */ + intn idx=FAIL; /*message number return value */ + uint8 *p = NULL; /*ptr into new chunk */ + H5O_cont_t *cont = NULL; /*native continuation message */ + intn i, chunkno; + + FUNC_ENTER (H5O_alloc_new_chunk, NULL, FAIL); + + /* check args */ + assert (oh); + assert (size>0); + + /* + * Find the smallest null message that will hold an object + * continuation message. Failing that, find the smallest message + * that could be moved to make room for the continuation message. + * Don't ever move continuation message from one chunk to another. + */ + cont_size = H5F_SIZEOF_OFFSET(f) + H5F_SIZEOF_SIZE(f); + for (i=0; inmesgs; i++) { + if (H5O_NULL_ID == oh->mesg[i].type->id) { + if (cont_size == oh->mesg[i].raw_size) { + found_null = i; + break; + } else if (oh->mesg[i].raw_size >= cont_size && + (found_null<0 || + oh->mesg[i].raw_size < oh->mesg[found_null].raw_size)) { + found_null = i; + } + } else if (H5O_CONT_ID == oh->mesg[i].type->id) { + /*don't consider continuation messages */ + } else if (oh->mesg[i].raw_size >= cont_size && + (found_other<0 || + oh->mesg[i].raw_size < oh->mesg[found_other].raw_size)) { + found_other = i; + } + } + assert (found_null>=0 || found_other>=0); + + /* + * If we must move some other message to make room for the null + * message, then make sure the new chunk has enough room for that + * other message. + */ + if (found_null<0) size += 4 + oh->mesg[found_other].raw_size; + + /* + * The total chunk size must include the requested space plus enough + * for the message header. This must be at least some minimum and a + * multiple of the alignment size. + */ + size = MAX (H5O_MIN_SIZE, size+4); + H5O_ALIGN (size, oh->alignment); + + /* + * Create the new chunk without giving it a file address. + */ + if (oh->nchunks >= oh->alloc_nchunks) { + oh->alloc_nchunks += H5O_NCHUNKS; + oh->chunk = H5MM_xrealloc (oh->chunk, + oh->alloc_nchunks * sizeof(H5O_chunk_t)); + } + chunkno = oh->nchunks++; + oh->chunk[chunkno].dirty = TRUE; + oh->chunk[chunkno].addr = H5O_NO_ADDR; + oh->chunk[chunkno].size = size; + oh->chunk[chunkno].image = p = H5MM_xmalloc (size); + + /* + * Make sure we have enough space for all possible new messages + * that could be generated below. + */ + if (oh->nmesgs+3 > oh->alloc_nmesgs) { + oh->alloc_nmesgs += MAX (H5O_NMESGS, 3); + oh->mesg = H5MM_xrealloc (oh->mesg, + oh->alloc_nmesgs * sizeof(H5O_mesg_t)); + } + + /* + * Describe the messages of the new chunk. + */ + if (found_null<0) { + found_null = i = oh->nmesgs++; + oh->mesg[i].type = H5O_NULL; + oh->mesg[i].dirty = TRUE; + oh->mesg[i].native = NULL; + oh->mesg[i].raw = oh->mesg[found_other].raw; + oh->mesg[i].raw_size = oh->mesg[found_other].raw_size; + oh->mesg[i].chunkno = oh->mesg[found_other].chunkno; + + oh->mesg[found_other].dirty = TRUE; + oh->mesg[found_other].raw = p+4; + oh->mesg[found_other].chunkno = chunkno; + p += 4 + oh->mesg[found_other].raw_size; + size -= 4 + oh->mesg[found_other].raw_size; + } + + idx = oh->nmesgs++; + oh->mesg[idx].type = H5O_NULL; + oh->mesg[idx].dirty = TRUE; + oh->mesg[idx].native = NULL; + oh->mesg[idx].raw = p+4; + oh->mesg[idx].raw_size = size-4; + oh->mesg[idx].chunkno = chunkno; + + /* + * If the null message that will receive the continuation message + * is larger than the continuation message, then split it into + * two null messages. + */ + if (oh->mesg[found_null].raw_size > cont_size) { + i = oh->nmesgs++; + oh->mesg[i].type = H5O_NULL; + oh->mesg[i].dirty = TRUE; + oh->mesg[i].native = NULL; + oh->mesg[i].raw = oh->mesg[found_null].raw + cont_size + 4; + oh->mesg[i].raw_size = oh->mesg[found_null].raw_size - (cont_size+4); + oh->mesg[i].chunkno = oh->mesg[found_null].chunkno; + + oh->mesg[found_null].dirty = TRUE; + oh->mesg[found_null].raw_size = cont_size; + } + + /* + * Initialize the continuation message. + */ + oh->mesg[found_null].type = H5O_CONT; + oh->mesg[found_null].dirty = TRUE; + cont = H5MM_xcalloc (1, sizeof(H5O_cont_t)); + cont->addr = H5O_NO_ADDR; + cont->size = 0; + cont->chunkno = chunkno; + oh->mesg[found_null].native = cont; + + + FUNC_LEAVE (idx); +} + + +/*------------------------------------------------------------------------- + * Function: H5O_alloc + * + * Purpose: Allocate enough space in the object header for this message. + * + * Return: Success: Index of message + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 6 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static intn +H5O_alloc (hdf5_file_t *f, H5O_t *oh, const H5O_class_t *type, size_t size) +{ + intn chunkno; + intn idx; + intn null_idx; + + FUNC_ENTER (H5O_alloc, NULL, FAIL); + + /* check args */ + assert (oh); + assert (type); + assert (size>=0); + H5O_ALIGN (size, oh->alignment); + + /* look for a null message which is large enough */ + for (idx=0; idxnmesgs; idx++) { + if (H5O_NULL_ID==oh->mesg[idx].type->id && + oh->mesg[idx].raw_size>=size) break; + } + + /* if we didn't find one, then allocate more header space */ + if (idx>=oh->nmesgs) { + + /* + * Look for a chunk which hasn't had disk space allocated yet + * since we can just increase the size of that chunk. + */ + for (chunkno=0; chunknonchunks; chunkno++) { + if ((idx=H5O_alloc_extend_chunk (oh, chunkno, size))>=0) break; + H5ECLEAR; + } + + /* + * Create a new chunk + */ + if (idx<0) { + if ((idx=H5O_alloc_new_chunk (f, oh, size))<0) { + HRETURN_ERROR (H5E_OHDR, H5E_NOSPACE, FAIL); + } + } + } + + /* do we need to split the null message? */ + if (oh->mesg[idx].raw_size > size) { + assert (oh->mesg[idx].raw_size - size >= 4); /*room for type & size */ + + if (oh->nmesgs >= oh->alloc_nmesgs) { + oh->alloc_nmesgs += H5O_NMESGS; + oh->mesg = H5MM_xrealloc (oh->mesg, + oh->alloc_nmesgs * sizeof(H5O_mesg_t)); + } + + null_idx = oh->nmesgs++; + oh->mesg[null_idx].type = H5O_NULL; + oh->mesg[null_idx].dirty = TRUE; + oh->mesg[null_idx].native = NULL; + oh->mesg[null_idx].raw = oh->mesg[idx].raw + size + 4; + oh->mesg[null_idx].raw_size = oh->mesg[idx].raw_size - (size + 4); + oh->mesg[null_idx].chunkno = oh->mesg[idx].chunkno; + oh->mesg[idx].raw_size = size; + } + + /* initialize the new message */ + oh->mesg[idx].type = type; + oh->mesg[idx].dirty = TRUE; + oh->mesg[idx].native = NULL; + + oh->dirty = TRUE; + FUNC_LEAVE (idx); +} + + +/*------------------------------------------------------------------------- + * Function: H5O_debug + * + * Purpose: Prints debugging info about an object header. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 6 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, + intn indent, intn fwidth) +{ + H5O_t *oh = NULL; + intn i, chunkno; + size_t mesg_total=0, chunk_total=0; + int *sequence; + + FUNC_ENTER (H5O_debug, NULL, FAIL); + + /* check args */ + assert (f); + assert (addr>=0); + assert (stream); + assert (indent>=0); + assert (fwidth>=0); + + if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) { + HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL); + } + + /* debug */ + fprintf (stream, "%*sObject Header...\n", indent, ""); + + fprintf (stream, "%*s%-*s %d\n", indent, "", fwidth, + "Dirty:", + (int)(oh->dirty)); + fprintf (stream, "%*s%-*s %d\n", indent, "", fwidth, + "Version:", + (int)(oh->version)); + fprintf (stream, "%*s%-*s %d\n", indent, "", fwidth, + "Alignment:", + (int)(oh->alignment)); + fprintf (stream, "%*s%-*s %d\n", indent, "", fwidth, + "Number of links:", + (int)(oh->nlink)); + fprintf (stream, "%*s%-*s %d (%d)\n", indent, "", fwidth, + "Number of messages (allocated):", + (int)(oh->nmesgs), (int)(oh->alloc_nmesgs)); + fprintf (stream, "%*s%-*s %d (%d)\n", indent, "", fwidth, + "Number of chunks (allocated):", + (int)(oh->nchunks), (int)(oh->alloc_nchunks)); + + /* debug each chunk */ + for (i=chunk_total=0; inchunks; i++) { + chunk_total += oh->chunk[i].size; + fprintf (stream, "%*sChunk %d...\n", indent, "", i); + + fprintf (stream, "%*s%-*s %d\n", indent+3, "", MAX(0,fwidth-3), + "Dirty:", + (int)(oh->chunk[i].dirty)); + fprintf (stream, "%*s%-*s %lu\n", indent+3, "", MAX(0,fwidth-3), + "Address:", + (unsigned long)(oh->chunk[i].addr)); + if (0==i && oh->chunk[i].addr!=addr+H5O_SIZEOF_HDR(f)) { + fprintf (stream, "*** WRONG ADDRESS!\n"); + } + fprintf (stream, "%*s%-*s %lu\n", indent+3, "", MAX(0,fwidth-3), + "Size in bytes:", + (unsigned long)(oh->chunk[i].size)); + } + + /* debug each message */ + sequence = H5MM_xcalloc (NELMTS(message_type_g), sizeof(int)); + for (i=mesg_total=0; inmesgs; i++) { + mesg_total += 4 + oh->mesg[i].raw_size; + fprintf (stream, "%*sMessage %d...\n", indent, "", i); + + /* check for bad message id */ + if (oh->mesg[i].type->id<0 || + oh->mesg[i].type->id>=NELMTS(message_type_g)) { + fprintf (stream, "*** BAD MESSAGE ID 0x%04x\n", + oh->mesg[i].type->id); + continue; + } + + /* message name and size */ + fprintf (stream, "%*s%-*s 0x%04x %s(%d)\n", + indent+3, "", MAX (0, fwidth-3), + "Message ID:", + (unsigned)(oh->mesg[i].type->id), + oh->mesg[i].type->name, + sequence[oh->mesg[i].type->id]++); + fprintf (stream, "%*s%-*s %lu\n", indent+3, "", MAX (0, fwidth-3), + "Raw size in bytes:", + (unsigned long)(oh->mesg[i].raw_size)); + + fprintf (stream, "%*s%-*s %d\n", indent+3, "", MAX(0,fwidth-3), + "Chunk number:", + (int)(oh->mesg[i].chunkno)); + chunkno = oh->mesg[i].chunkno; + if (chunkno<0 || chunkno>=oh->nchunks) { + fprintf (stream, "*** BAD CHUNK NUMBER\n"); + } + + /* check the size */ + if ((oh->mesg[i].raw + oh->mesg[i].raw_size > + oh->chunk[chunkno].image + oh->chunk[chunkno].size) || + (oh->mesg[i].raw < oh->chunk[chunkno].image)) { + fprintf (stream, "*** BAD MESSAGE RAW ADDRESS\n"); + } + + /* decode the message */ + if (NULL==oh->mesg[i].native && oh->mesg[i].type->decode) { + oh->mesg[i].native = (oh->mesg[i].type->decode)(f, oh->mesg[i].raw); + } + + /* print the message */ + if (oh->mesg[i].type->debug) { + (oh->mesg[i].type->debug)(f, oh->mesg[i].native, stream, indent+3, + MAX(0, fwidth-3)); + } else { + fprintf (stream, "%*sNo info for this message.\n", indent+3, ""); + } + } + sequence = H5MM_xfree (sequence); + + if (mesg_total != chunk_total) { + fprintf (stream, "*** TOTAL SIZE DOES NOT MATCH ALLOCATED SIZE!\n"); + } + + FUNC_LEAVE (SUCCEED); +} diff --git a/src/H5Ocont.c b/src/H5Ocont.c new file mode 100644 index 0000000..068a768 --- /dev/null +++ b/src/H5Ocont.c @@ -0,0 +1,164 @@ +/*------------------------------------------------------------------------- + * Copyright (C) 1997 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + * + * Created: H5Ocont.c + * Aug 6 1997 + * Robb Matzke + * + * Purpose: The object header continuation message. This + * message is only generated and read from within + * the H5O package. Therefore, do not change + * any definitions in this file! + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#include +#include "hdf5.h" +#include "H5private.h" +#include "H5MMprivate.h" +#include "H5Oprivate.h" + +/* PRIVATE PROTOTYPES */ +static void *H5O_cont_decode (hdf5_file_t *f, const uint8 *p); +static herr_t H5O_cont_encode (hdf5_file_t *f, size_t size, uint8 *p, + const void *_mesg); +static herr_t H5O_cont_debug (hdf5_file_t *f, const void *_mesg, FILE *stream, + intn indent, intn fwidth); + +/* This message derives from H5O */ +const H5O_class_t H5O_CONT[1] = {{ + H5O_CONT_ID, /*message id number */ + "hdr continuation", /*message name for debugging */ + H5O_cont_decode, /*decode message */ + H5O_cont_encode, /*encode message */ + NULL, /*no fast method */ + NULL, /*no cache method */ + NULL, /*no copy method */ + NULL, /*no size method */ + NULL, /*default free method */ + H5O_cont_debug, /*debugging */ +}}; + +/* Is the interface initialized? */ +static intn interface_initialize_g = FALSE; + + +/*------------------------------------------------------------------------- + * Function: H5O_cont_decode + * + * Purpose: Decode the raw header continuation message. + * + * Return: Success: Ptr to the new native message + * + * Failure: NULL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 6 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void * +H5O_cont_decode (hdf5_file_t *f, const uint8 *p) +{ + H5O_cont_t *cont = NULL; + + FUNC_ENTER (H5O_cont_decode, NULL, NULL); + + cont = H5MM_xcalloc (1, sizeof(H5O_cont_t)); + H5F_decode_offset (f, p, cont->addr); + H5F_decode_length (f, p, cont->size); + + FUNC_LEAVE ((void*)cont); +} + + +/*------------------------------------------------------------------------- + * Function: H5O_cont_encode + * + * Purpose: Encodes a continuation message. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 7 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_cont_encode (hdf5_file_t *f, size_t size, uint8 *p, const void *_mesg) +{ + const H5O_cont_t *cont = (const H5O_cont_t *)_mesg; + + FUNC_ENTER (H5O_cont_encode, NULL, FAIL); + + /* check args */ + assert (f); + assert (size == H5F_SIZEOF_OFFSET(f) + H5F_SIZEOF_SIZE(f)); + assert (p); + assert (cont); + + /* encode */ + H5F_encode_offset (f, p, cont->addr); + H5F_encode_length (f, p, cont->size); + + FUNC_LEAVE (SUCCEED); +} + + +/*------------------------------------------------------------------------- + * Function: H5O_cont_debug + * + * Purpose: Prints debugging info. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 6 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_cont_debug (hdf5_file_t *f, const void *_mesg, FILE *stream, + intn indent, intn fwidth) +{ + const H5O_cont_t *cont = (const H5O_cont_t *)_mesg; + + FUNC_ENTER (H5O_cont_debug, NULL, FAIL); + + /* check args */ + assert (f); + assert (cont); + assert (stream); + assert (indent>=0); + assert (fwidth>=0); + + fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth, + "Continuation address:", + (unsigned long)(cont->addr)); + fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth, + "Continuation size in bytes:", + (unsigned long)(cont->size)); + fprintf (stream, "%*s%-*s %d\n", indent, "", fwidth, + "Points to chunk number:", + (int)(cont->chunkno)); + + FUNC_LEAVE (SUCCEED); +} diff --git a/src/H5Onull.c b/src/H5Onull.c new file mode 100644 index 0000000..97e1ff7 --- /dev/null +++ b/src/H5Onull.c @@ -0,0 +1,33 @@ +/*------------------------------------------------------------------------- + * Copyright (C) 1997 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + * + * Created: H5Onull.c + * Aug 6 1997 + * Robb Matzke + * + * Purpose: The null message. + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#include "hdf5.h" +#include "H5private.h" +#include "H5Oprivate.h" + +/* This message derives from H5O */ +const H5O_class_t H5O_NULL[1] = {{ + H5O_NULL_ID, /*message id number */ + "null", /*message name for debugging */ + NULL, /*no decode method */ + NULL, /*no encode method */ + NULL, /*no fast method */ + NULL, /*no cache method */ + NULL, /*no copy method */ + NULL, /*no size method */ + NULL, /*no free method */ + NULL, /*no debug method */ +}}; diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h new file mode 100644 index 0000000..dfaa5b5 --- /dev/null +++ b/src/H5Oprivate.h @@ -0,0 +1,127 @@ +/*------------------------------------------------------------------------- + * Copyright (C) 1997 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + * + * Created: H5Oprivate.h + * Aug 5 1997 + * Robb Matzke + * + * Purpose: Object header private include file. + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#ifndef _H5Oprivate_H +#define _H5Oprivate_H +#include "H5Oproto.h" + +#include "H5Fprivate.h" +#include "H5Gprivate.h" + +#define H5O_MIN_SIZE 64 /*min obj header data size */ +#define H5O_NMESGS 64 /*initial number of messages */ +#define H5O_NCHUNKS 64 /*initial number of chunks */ +#define H5O_NEW_MESG (-1) /*new message */ +#define H5O_NO_ADDR (-1) /*no disk address yet */ + +#define H5O_VERSION 1 +#define H5O_ALIGNMENT 4 +#define H5O_ALIGN(X,A) ((X)=(A)*(((X)+(A)-1)/(A))) + +#define H5O_SIZEOF_HDR(F) \ + (1 + /*version number */ \ + 1 + /*alignment */ \ + 2 + /*number of messages */ \ + 4 + /*reference count */ \ + 4) /*header data size */ + +typedef struct H5O_class_t { + intn id; /*message type ID on disk */ + const char *name; /*message name for debugging */ + void *(*decode)(hdf5_file_t*,const uint8*); /*decode mesg */ + herr_t (*encode)(hdf5_file_t*,size_t,uint8*,const void*); + void *(*fast)(const H5G_entry_t*, void*); /*get from stab ent */ + hbool_t (*cache)(H5G_entry_t*,const void*); /*put into entry */ + void *(*copy)(const void*,void*); /*copy native value */ + size_t (*size)(hdf5_file_t*,const void*); /*size of raw value */ + void *(*free)(void*); /*free native data struct */ + herr_t (*debug)(hdf5_file_t*,const void*, FILE*, intn, intn); +} H5O_class_t; + +typedef struct H5O_mesg_t { + const H5O_class_t *type; /*type of message */ + hbool_t dirty; /*raw out of date wrt native */ + void *native; /*native format message */ + uint8 *raw; /*ptr to raw data */ + size_t raw_size; /*size with alignment */ + intn chunkno; /*chunk number for this mesg */ +} H5O_mesg_t; + +typedef struct H5O_chunk_t { + hbool_t dirty; /*dirty flag */ + haddr_t addr; /*chunk file address */ + size_t size; /*chunk size */ + uint8 *image; /*image of file */ +} H5O_chunk_t; + +typedef struct H5O_t { + hbool_t dirty; /*out of data wrt disk */ + intn version; /*version number */ + intn alignment; /*message alignment */ + intn nlink; /*link count */ + intn nmesgs; /*number of messages */ + intn alloc_nmesgs; /*number of message slots */ + H5O_mesg_t *mesg; /*array of messages */ + intn nchunks; /*number of chunks */ + intn alloc_nchunks; /*chunks allocated */ + H5O_chunk_t *chunk; /*array of chunks */ +} H5O_t; + +/* + * Null message. + */ +#define H5O_NULL_ID 0x0000 +extern const H5O_class_t H5O_NULL[1]; + +/* + * Object header continuation message. + */ +#define H5O_CONT_ID 0x0010 +extern const H5O_class_t H5O_CONT[1]; + +typedef struct H5O_cont_t { + haddr_t addr; /*address of continuation block */ + size_t size; /*size of continuation block */ + + /* the following field(s) do not appear on disk */ + intn chunkno; /*chunk this mesg refers to */ +} H5O_cont_t; + +/* + * Symbol table message. + */ +#define H5O_STAB_ID 0x0011 +extern const H5O_class_t H5O_STAB[1]; + +typedef struct H5O_stab_t { + haddr_t btree; /*address of B-tree */ + haddr_t heap; /*address of name heap */ +} H5O_stab_t; + + +haddr_t H5O_new (hdf5_file_t *f, intn nlink, size_t size_hint); +intn H5O_link (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent, intn adjust); +void *H5O_read (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent, + const H5O_class_t *type, intn sequence, void *mesg); +const void *H5O_peek (hdf5_file_t *f, haddr_t addr, const H5O_class_t *type, + intn sequence); +intn H5O_modify (hdf5_file_t *f, haddr_t addr, H5G_entry_t *ent, + hbool_t *ent_modified, const H5O_class_t *type, + intn overwrite, const void *mesg); +herr_t H5O_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, + intn indent, intn fwidth); + +#endif diff --git a/src/H5Oproto.h b/src/H5Oproto.h new file mode 100644 index 0000000..df94835 --- /dev/null +++ b/src/H5Oproto.h @@ -0,0 +1,30 @@ +/*------------------------------------------------------------------------- + * Copyright (C) 1997 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + * + * Created: H5Oproto.h + * Aug 5 1997 + * Robb Matzke + * + * Purpose: Object header public prototypes + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#ifndef _H5Oproto_H +#define _H5Oproto_H + +#if defined c_plusplus || defined __cplusplus +extern "C" +{ +#endif + +#if defined c_plusplus || defined __cplusplus +} +#endif + + +#endif diff --git a/src/H5Ostab.c b/src/H5Ostab.c new file mode 100644 index 0000000..ec6dd61 --- /dev/null +++ b/src/H5Ostab.c @@ -0,0 +1,328 @@ +/*------------------------------------------------------------------------- + * Copyright (C) 1997 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + * + * Created: H5Ostab.c + * Aug 6 1997 + * Robb Matzke + * + * Purpose: Symbol table messages. + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#include + +#include "hdf5.h" + +#include "H5private.h" +#include "H5Gprivate.h" +#include "H5MMprivate.h" +#include "H5Oprivate.h" + +/* PRIVATE PROTOTYPES */ +static void *H5O_stab_decode (hdf5_file_t *f, const uint8 *p); +static herr_t H5O_stab_encode (hdf5_file_t *f, size_t size, uint8 *p, + const void *_mesg); +static void *H5O_stab_fast (const H5G_entry_t *ent, void *_mesg); +static hbool_t H5O_stab_cache (H5G_entry_t *ent, const void *_mesg); +static void *H5O_stab_copy (const void *_mesg, void *_dest); +static size_t H5O_stab_size (hdf5_file_t *f, const void *_mesg); +static herr_t H5O_stab_debug (hdf5_file_t *f, const void *_mesg, + FILE *stream, intn indent, intn fwidth); + +/* This message derives from H5O */ +const H5O_class_t H5O_STAB[1] = {{ + H5O_STAB_ID, /*message id number */ + "stab", /*message name for debugging */ + H5O_stab_decode, /*decode message */ + H5O_stab_encode, /*encode message */ + H5O_stab_fast, /*get message from stab entry */ + H5O_stab_cache, /*put message into stab entry */ + H5O_stab_copy, /*copy the native value */ + H5O_stab_size, /*size of symbol table entry */ + NULL, /*default free method */ + H5O_stab_debug, /*debug the message */ +}}; + +/* Is the interface initialized? */ +static intn interface_initialize_g = FALSE; + + +/*------------------------------------------------------------------------- + * Function: H5O_stab_decode + * + * Purpose: Decode a symbol table 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 + * matzke@llnl.gov + * Aug 6 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void * +H5O_stab_decode (hdf5_file_t *f, const uint8 *p) +{ + H5O_stab_t *stab; + + FUNC_ENTER (H5O_stab_decode, NULL, NULL); + + /* check args */ + assert (f); + assert (p); + + /* decode */ + stab = H5MM_xcalloc (1, sizeof(H5O_stab_t)); + H5F_decode_offset (f, p, stab->btree); + H5F_decode_offset (f, p, stab->heap); + + FUNC_LEAVE (stab); +} + + +/*------------------------------------------------------------------------- + * Function: H5O_stab_encode + * + * Purpose: Encodes a symbol table entry. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 6 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_stab_encode (hdf5_file_t *f, size_t size, uint8 *p, const void *_mesg) +{ + const H5O_stab_t *stab = (const H5O_stab_t *)_mesg; + + FUNC_ENTER (H5O_stab_encode, NULL, FAIL); + + /* check args */ + assert (f); + assert (size == 2 * H5F_SIZEOF_OFFSET(f)); + assert (p); + assert (stab); + + /* encode */ + H5F_encode_offset (f, p, stab->btree); + H5F_encode_offset (f, p, stab->heap); + + FUNC_LEAVE (SUCCEED); +} + + +/*------------------------------------------------------------------------- + * Function: H5O_stab_fast + * + * Purpose: Initializes a new message struct with info from a symbol + * table entry. + * + * Return: Success: Ptr to message struct, allocated if none + * supplied. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 6 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void * +H5O_stab_fast (const H5G_entry_t *ent, void *_mesg) +{ + H5O_stab_t *stab = (H5O_stab_t *)_mesg; + + FUNC_ENTER (H5O_stab_fast, NULL, NULL); + + /* check args */ + assert (ent); + + if (H5G_CACHED_STAB==ent->type) { + if (!stab) stab = H5MM_xcalloc (1, sizeof(H5O_stab_t)); + stab->btree = ent->cache.stab.btree; + stab->heap = ent->cache.stab.heap; + } else { + stab = NULL; + } + + FUNC_LEAVE (stab); +} + + +/*------------------------------------------------------------------------- + * Function: H5O_stab_cache + * + * Purpose: Copies a message into the cache portion of a symbol table + * entry. + * + * Return: Success: TRUE if modified. + * FALSE if not modified. + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 6 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static hbool_t +H5O_stab_cache (H5G_entry_t *ent, const void *_mesg) +{ + const H5O_stab_t *stab = (const H5O_stab_t *)_mesg; + hbool_t modified = FALSE; + + FUNC_ENTER (H5O_stab_cache, NULL, FAIL); + + /* check args */ + assert (ent); + assert (stab); + + /* cache */ + if (H5G_CACHED_STAB != ent->type) { + modified = TRUE; + ent->type = H5G_CACHED_STAB; + } + + if (ent->cache.stab.btree != stab->btree) { + modified = TRUE; + ent->cache.stab.btree = stab->btree; + } + + if (ent->cache.stab.heap != stab->heap) { + modified = TRUE; + ent->cache.stab.heap = stab->heap; + } + + FUNC_LEAVE (modified); +} + + +/*------------------------------------------------------------------------- + * Function: H5O_stab_copy + * + * Purpose: Copies a message from _MESG to _DEST, allocating _DEST if + * necessary. + * + * Return: Success: Ptr to _DEST + * + * Failure: NULL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 6 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void * +H5O_stab_copy (const void *_mesg, void *_dest) +{ + const H5O_stab_t *stab = (const H5O_stab_t *)_mesg; + H5O_stab_t *dest = (H5O_stab_t *)_dest; + + FUNC_ENTER (H5O_stab_copy, NULL, NULL); + + /* check args */ + assert (stab); + if (!dest) dest = H5MM_xcalloc (1, sizeof(H5O_stab_t)); + + /* copy */ + *dest = *stab; + + FUNC_LEAVE ((void*)dest); +} + + +/*------------------------------------------------------------------------- + * Function: H5O_stab_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 alignment. + * + * Return: Success: Message data size in bytes without alignment. + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 6 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static size_t +H5O_stab_size (hdf5_file_t *f, const void *_mesg) +{ + FUNC_ENTER (H5O_stab_size, NULL, FAIL); + FUNC_LEAVE (2 * H5F_SIZEOF_OFFSET(f)); +} + + +/*------------------------------------------------------------------------- + * Function: H5O_stab_debug + * + * Purpose: Prints debugging info for a symbol table message. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 6 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_stab_debug (hdf5_file_t *f, const void *_mesg, FILE *stream, + intn indent, intn fwidth) +{ + const H5O_stab_t *stab = (const H5O_stab_t *)_mesg; + + FUNC_ENTER (H5O_stab_debug, NULL, FAIL); + + /* check args */ + assert (f); + assert (stab); + assert (stream); + assert (indent>=0); + assert (fwidth>=0); + + fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth, + "B-tree address:", + (unsigned long)(stab->btree)); + fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth, + "Name heap address:", + (unsigned long)(stab->heap)); + + FUNC_LEAVE (SUCCEED); +} + diff --git a/src/Makefile b/src/Makefile index 022f392..94dcd67 100644 --- a/src/Makefile +++ b/src/Makefile @@ -28,7 +28,7 @@ CFLAGS = -c $(MACHINE) $(DEFS) INCL = hdf5.h OBJ = H5.o H5E.o H5A.o H5F.o H5C.o H5M.o H5AC.o H5B.o H5MM.o H5MF.o H5T.o \ - H5Gnode.o H5H.o H5G.o H5P.o H5D.o + H5Gnode.o H5H.o H5G.o H5P.o H5D.o H5O.o H5Onull.o H5Ocont.o H5Ostab.o $(TARGET): $(OBJ) $(AR) $(ARFLAGS) $(TARGET) $(OBJ) @@ -99,3 +99,15 @@ H5P.o: H5P.c $(INCL) H5Pprivate.h H5Pproto.h H5D.o: H5D.c $(INCL) H5Dprivate.h H5Dproto.h $(CC) $(CFLAGS) H5D.c + +H5O.o: H5O.c $(INCL) H5Oprivate.h H5Oproto.h + $(CC) $(CFLAGS) H5O.c + +H5Onull.o: H5Onull.c $(INCL) H5Oprivate.h H5Oproto.h + $(CC) $(CFLAGS) H5Onull.c + +H5Ocont.o: H5Ocont.c $(INCL) H5Oprivate.h H5Oproto.h + $(CC) $(CFLAGS) H5Ocont.c + +H5Ostab.o: H5Ostab.c $(INCL) H5Oprivate.h H5Oproto.h + $(CC) $(CFLAGS) H5Ostab.c diff --git a/src/debug.c b/src/debug.c index f061d4c..d07b2cb 100644 --- a/src/debug.c +++ b/src/debug.c @@ -6,7 +6,7 @@ * * Created: debug.c * Jul 18 1997 - * Robb Matzke + * Robb Matzke * * Purpose: Debugs an existing HDF5 file at a low level. * @@ -21,6 +21,7 @@ #include "H5Fprivate.h" #include "H5Gprivate.h" #include "H5Hprivate.h" +#include "H5Oprivate.h" #define INDENT 3 #define VCOL 50 @@ -36,7 +37,7 @@ * Failure: exit (non-zero) * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Jul 18 1997 * * Modifications: @@ -51,6 +52,7 @@ main (int argc, char *argv[]) haddr_t addr = 0; uint8 sig[16]; intn i; + herr_t status = SUCCEED; /* * Parse command arguments. @@ -85,19 +87,19 @@ main (int argc, char *argv[]) /* * Debug the boot block. */ - H5F_debug (f, 0, stdout, 0, VCOL); + status = H5F_debug (f, 0, stdout, 0, VCOL); } else if (!memcmp (sig, H5H_MAGIC, H5H_SIZEOF_MAGIC)) { /* * Debug a heap. */ - H5H_debug (f, addr, stdout, 0, VCOL); + status = H5H_debug (f, addr, stdout, 0, VCOL); } else if (!memcmp (sig, H5G_NODE_MAGIC, H5G_NODE_SIZEOF_MAGIC)) { /* * Debug a symbol table node. */ - H5G_node_debug (f, addr, stdout, 0, VCOL); + status = H5G_node_debug (f, addr, stdout, 0, VCOL); } else if (!memcmp (sig, H5B_MAGIC, H5B_SIZEOF_MAGIC)) { /* @@ -108,13 +110,20 @@ main (int argc, char *argv[]) H5B_subid_t subtype = sig[H5B_SIZEOF_MAGIC]; switch (subtype) { case H5B_SUBTYPE_SNODE: - H5G_node_debug (f, addr, stdout, 0, VCOL); + status = H5G_node_debug (f, addr, stdout, 0, VCOL); break; default: fprintf (stderr, "Unknown B-tree subtype %u\n", (unsigned)(subtype)); exit (4); } + + } else if (sig[0]==H5O_VERSION && sig[1]==H5O_ALIGNMENT) { + /* + * This could be an object header. Since they don't have a signature + * it's a somewhat "ify" detection. + */ + status = H5O_debug (f, addr, stdout, 0, VCOL); } else { /* @@ -137,6 +146,11 @@ main (int argc, char *argv[]) exit (4); } + if (status<0) { + fprintf (stderr, "An error occurred\n"); + exit (5); + } + H5Fclose (fid); exit (0); } diff --git a/src/hdf5gen.h b/src/hdf5gen.h index 39e3d05..628f5c3 100644 --- a/src/hdf5gen.h +++ b/src/hdf5gen.h @@ -15,6 +15,7 @@ /* * This file contains general macros used throughout HDF5 library & interfaces */ +#include "hdf5pabl.h" #ifndef HDF5GEN_H #define HDF5GEN_H @@ -36,6 +37,11 @@ # define TRUE (!FALSE) #endif +/* number of members in an array */ +#ifndef NELMTS +# define NELMTS(X) (sizeof(X)/sizeof(X[0])) +#endif + /*------------------------------------------------------------------------- * Purpose: Register function entry for library initialization and code * profiling. @@ -77,9 +83,9 @@ */ #define FUNC_ENTER(func_name,interface_init_func,err) \ CONSTR (FUNC, #func_name); \ - /* int pablo_func_id = ID_ ## func_name; */ \ + PABLO_SAVE (ID_ ## func_name); \ \ - PABLO_TRACE_ON (PABLO_MASK, ID_ ## func_name); \ + PABLO_TRACE_ON (PABLO_MASK, pablo_func_id); \ \ if (!library_initialize_g) { \ library_initialize_g = TRUE; \ @@ -120,10 +126,7 @@ * *------------------------------------------------------------------------- */ -#define FUNC_LEAVE(return_value) { \ - PABLO_TRACE_OFF (PABLO_MASK, pablo_func_id); \ - return (return_value); \ -} +#define FUNC_LEAVE(return_value) HRETURN(return_value) #endif /* HDF5GEN_H */ diff --git a/src/hdf5meta.h b/src/hdf5meta.h index 025b4e6..2716537 100644 --- a/src/hdf5meta.h +++ b/src/hdf5meta.h @@ -123,13 +123,13 @@ #else /* HDF5_HAVE_NATIVE_INT64 */ #error "Define int64 on platforms which don't support it" #endif /* HDF5_HAVE_NATIVE_INT64 */ -# define INT16DECODE(p, i) { (i) = (int16)(*(int16 *)(p)); (p)+=2; } -# define UINT16DECODE(p, i) { (i) = (uint16)(*(uint16 *)(p)); (p)+=2; } -# define INT32DECODE(p, i) { (i) = (int32)(*(int32 *)(p)); (p)+=4; } -# define UINT32DECODE(p, i) { (i) = (uint32)(*(uint32 *)(p)); (p)+=4; } +# define INT16DECODE(p, i) { (i) = (int16)(*(const int16 *)(p)); (p)+=2; } +# define UINT16DECODE(p, i) { (i) = (uint16)(*(const uint16 *)(p)); (p)+=2; } +# define INT32DECODE(p, i) { (i) = (int32)(*(const int32 *)(p)); (p)+=4; } +# define UINT32DECODE(p, i) { (i) = (uint32)(*(const uint32 *)(p)); (p)+=4; } #ifdef HDF5_HAVE_NATIVE_INT64 -# define INT64DECODE(p, i) { (i) = (int64)(*(int64 *)(p)); (p)+=8; } -# define UINT64DECODE(p, i) { (i) = (uint64)(*(uint64 *)(p)); (p)+=8; } +# define INT64DECODE(p, i) { (i) = (int64)(*(const int64 *)(p)); (p)+=8; } +# define UINT64DECODE(p, i) { (i) = (uint64)(*(const uint64 *)(p)); (p)+=8; } #else /* HDF5_HAVE_NATIVE_INT64 */ #error "Define int64 on platforms which don't support it" #endif /* HDF5_HAVE_NATIVE_INT64 */ diff --git a/src/hdf5pabl.h b/src/hdf5pabl.h index 0df5913..008a265 100644 --- a/src/hdf5pabl.h +++ b/src/hdf5pabl.h @@ -20,11 +20,13 @@ #define HDF5PABL_H #ifdef HAVE_PABLO +#define PABLO_SAVE(func_id) int pablo_func_id = func_id #define PABLO_TRACE_ON(m, f) TRACE_ON(m,f) #define PABLO_TRACE_OFF(m, f) TRACE_OFF(m,f) #else /* no Pablo tracing enabled */ -#define PABLO_TRACE_ON(m, f) -#define PABLO_TRACE_OFF(m, f) +#define PABLO_SAVE(func_id) /*void*/ +#define PABLO_TRACE_ON(m, f) /*void*/ +#define PABLO_TRACE_OFF(m, f) /*void*/ #endif /* HAVE_PABLO */ #endif /* HDF5PABL_H */ -- cgit v0.12