From 7ead4a900b4b7980688708ee6794def0793f123c Mon Sep 17 00:00:00 2001 From: Robb Matzke Date: Wed, 10 Sep 1997 14:57:56 -0500 Subject: [svn-r71] Lost my changelog, but basically some new caching functions. --- src/H5AC.c | 405 +++++++++++++++++++---- src/H5ACprivate.h | 35 +- src/H5B.c | 573 +++++++++++++++------------------ src/H5Bprivate.h | 6 +- src/H5E.c | 1 + src/H5Epublic.h | 1 + src/H5F.c | 8 +- src/H5Fprivate.h | 2 +- src/H5G.c | 36 +-- src/H5Gnode.c | 194 ++++++----- src/H5Gprivate.h | 8 +- src/H5H.c | 2 +- src/H5Oprivate.h | 4 +- src/H5Ostab.c | 28 +- src/H5detect.c | 941 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 15 files changed, 1723 insertions(+), 521 deletions(-) create mode 100644 src/H5detect.c diff --git a/src/H5AC.c b/src/H5AC.c index c3e4008..478923c 100644 --- a/src/H5AC.c +++ b/src/H5AC.c @@ -31,19 +31,31 @@ */ /* #define SORT_BY_ADDR */ -#define PABLO_MASK H5AC_mask +/* + * Debug H5AC_protect() and H5AC_unprotect() by insuring that nothing + * accesses protected objects. NDEBUG must not be defined in order for + * this to have any effect. + */ +/* #define H5AC_DEBUG_PROTECT */ +/* + * Private file-scope variables. + */ +#define PABLO_MASK H5AC_mask static int interface_initialize_g = FALSE; /*initialized?*/ #ifdef SORT_BY_ADDR -static H5AC_cache_t *current_cache_g = NULL; /*for sorting */ +static H5AC_t *current_cache_g = NULL; /*for sorting */ #endif /*------------------------------------------------------------------------- * Function: H5AC_new * - * Purpose: Initialize the cache just after a file is opened. + * Purpose: Initialize the cache just after a file is opened. The + * SIZE_HINT is the number of cache slots desired. If you + * pass an invalid value then H5AC_NSLOTS is used. You can + * turn off caching by using 1 for the SIZE_HINT value. * * Return: Success: SUCCEED * @@ -58,14 +70,17 @@ static H5AC_cache_t *current_cache_g = NULL; /*for sorting */ *------------------------------------------------------------------------- */ herr_t -H5AC_new (hdf5_file_t *f) +H5AC_new (hdf5_file_t *f, intn size_hint) { FUNC_ENTER (H5AC_new, NULL, FAIL); assert (f); assert (NULL==f->cache); + if (size_hint<1) size_hint = H5AC_NSLOTS; - f->cache = H5MM_xcalloc (H5AC_NSLOTS, sizeof (H5AC_cache_t)); + f->cache = H5MM_xcalloc (1, sizeof (H5AC_t)); + f->cache->nslots = size_hint; + f->cache->slot = H5MM_xcalloc (f->cache->nslots, sizeof (H5AC_slot_t)); FUNC_LEAVE (SUCCEED); } @@ -75,6 +90,8 @@ H5AC_new (hdf5_file_t *f) * Function: H5AC_dest * * Purpose: Flushes all data to disk and destroys the cache. + * This function fails if any object are protected since the + * resulting file might not be consistent. * * Return: Success: SUCCEED * @@ -100,6 +117,19 @@ H5AC_dest (hdf5_file_t *f) HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL); } +#if defined(H5AC_DEBUG_PROTECT) && !defined(NDEBUG) + { + intn i; + for (i=0; icache->nslots; i++) { + f->cache->slot[i].prot = H5MM_xfree (f->cache->slot[i].prot); + f->cache->slot[i].aprots = 0; + f->cache->slot[i].nprots = 0; + } + } +#endif + + f->cache->slot = H5MM_xfree (f->cache->slot); + f->cache->nslots = 0; f->cache = H5MM_xfree (f->cache); FUNC_LEAVE (SUCCEED); } @@ -112,6 +142,14 @@ H5AC_dest (hdf5_file_t *f) * is located in the file, return a pointer to the object. * The optional UDATA structure is passed down to the function * that is responsible for loading the object into memory. + * The pointer is guaranteed to be valid until the next call + * to an H5AC function (if you want a pointer which is valid + * indefinately then see H5AC_protect()). + * + * If H5AC_DEBUG_PROTECT is defined then this function also + * checks that the requested object is not currently + * protected since it is illegal to modify a protected object + * except through the pointer returned by H5AC_protect(). * * Return: Success: Pointer to the object. The pointer is * valid until some other cache function @@ -137,10 +175,11 @@ void * H5AC_find_f (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr, const void *udata) { - unsigned idx = H5AC_HASH(addr); + unsigned idx; herr_t status; void *thing = NULL; herr_t (*flush)(hdf5_file_t*,hbool_t,haddr_t,void*)=NULL; + H5AC_slot_t *slot = NULL; FUNC_ENTER (H5AC_find, NULL, NULL); @@ -149,25 +188,36 @@ H5AC_find_f (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr, assert (type); assert (type->load); assert (type->flush); - + idx = H5AC_HASH (f, addr); + slot = f->cache->slot + idx; + /* * Return right away if the item is in the cache. */ - if (f->cache[idx].type==type && f->cache[idx].addr==addr) { - HRETURN (f->cache[idx].thing); + if (slot->type==type && slot->addr==addr) { + HRETURN (slot->thing); } /* * Fail if the item in the cache is at the correct address but is * of the wrong type. */ - if (f->cache[idx].type && f->cache[idx].addr==addr && - f->cache[idx].type!=type) { + if (slot->type && slot->type!=type && slot->addr==addr) { HRETURN_ERROR (H5E_CACHE, H5E_BADTYPE, NULL); } -#ifdef DO_NOT_CACHE - H5AC_flush (f, NULL, 0, TRUE); +#if defined(H5AC_DEBUG_PROTECT) && !defined(NDEBUG) + /* + * Check that the requested thing isn't protected, for protected things + * can only be modified through the pointer already handed out by the + * H5AC_protect() function. + */ + { + intn i; + for (i=0; inprots; i++) { + assert (addr!=slot->prot[i].addr); + } + } #endif /* @@ -181,9 +231,9 @@ H5AC_find_f (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr, /* * Free the previous cache entry if there is one. */ - if (f->cache[idx].type) { - flush = f->cache[idx].type->flush; - status = (flush)(f, TRUE, f->cache[idx].addr, f->cache[idx].thing); + if (slot->type) { + flush = slot->type->flush; + status = (flush)(f, TRUE, slot->addr, slot->thing); if (status<0) { /* * The old thing could not be removed from the stack. @@ -199,9 +249,9 @@ H5AC_find_f (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr, /* * Make the cache point to the new thing. */ - f->cache[idx].type = type; - f->cache[idx].addr = addr; - f->cache[idx].thing = thing; + slot->type = type; + slot->addr = addr; + slot->thing = thing; FUNC_LEAVE (thing); } @@ -234,11 +284,11 @@ H5AC_compare (const void *_a, const void *_b) assert (current_cache_g); - if (NULL==current_cache_g[a].type) return 1; - if (NULL==current_cache_g[b].type) return -1; + if (NULL==current_cache_g.slot[a].type) return 1; + if (NULL==current_cache_g.slot[b].type) return -1; - if (current_cache_g[a].addr < current_cache_g[b].addr) return -1; - if (current_cache_g[a].addr > current_cache_g[b].addr) return 1; + if (current_cache_g.slot[a].addr < current_cache_g.slot[b].addr) return -1; + if (current_cache_g.slot[a].addr > current_cache_g.slot[b].addr) return 1; return 0; } #endif @@ -252,6 +302,10 @@ H5AC_compare (const void *_a, const void *_b) * all types of entries are flushed. If the ADDR is zero then * all entries of the specified type are flushed. * + * If there are protected objects they will not be flushed. + * However, an attempt will be made to flush all non-protected + * items before this function returns failure. + * * Return: Success: SUCCEED * * Failure: FAIL @@ -268,16 +322,17 @@ herr_t H5AC_flush (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr, hbool_t destroy) { - uintn i = H5AC_HASH(addr); + uintn i; herr_t status; herr_t (*flush)(hdf5_file_t*,hbool_t,haddr_t,void*)=NULL; - H5AC_cache_t *slot; + H5AC_slot_t *slot; intn *map=NULL; FUNC_ENTER (H5AC_flush, NULL, FAIL); assert (f); assert (f->cache); + i = H5AC_HASH (f, addr); if (!type || 0==addr) { @@ -286,23 +341,23 @@ H5AC_flush (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr, * Sort the cache entries by address since flushing them in * ascending order by address may be much more efficient. */ - map = H5MM_xmalloc (H5AC_NSLOTS * sizeof(intn)); - for (i=0; icache->nslots * sizeof(intn)); + for (i=0; icache->nslots; i++) map[i] = i; assert (NULL==current_cache_g); current_cache_g = f->cache; - HDqsort (map, H5AC_NSLOTS, sizeof(intn), H5AC_compare); + HDqsort (map, f->cache->nslots, sizeof(intn), H5AC_compare); current_cache_g = NULL; #endif /* * Look at all cache entries. */ - for (i=0; icache->nslots; i++) { #ifdef SORT_BY_ADDR - slot = f->cache + map[i]; + slot = f->cache->slot + map[i]; if (NULL==slot->type) break; /*the rest are empty*/ #else - slot = f->cache + i; + slot = f->cache->slot + i; if (NULL==slot->type) continue; #endif if ((!type || type==slot->type) && @@ -318,19 +373,28 @@ H5AC_flush (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr, } map = H5MM_xfree (map); - } else if (f->cache[i].type==type && f->cache[i].addr==addr) { + } else if (f->cache->slot[i].type==type && f->cache->slot[i].addr==addr) { /* * Flush just this entry. */ - flush = f->cache[i].type->flush; - status = (flush) (f, destroy, f->cache[i].addr, f->cache[i].thing); + flush = f->cache->slot[i].type->flush; + status = (flush) (f, destroy, f->cache->slot[i].addr, + f->cache->slot[i].thing); if (status<0) { HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL); } - if (destroy) f->cache[i].type = NULL; + if (destroy) f->cache->slot[i].type = NULL; } + /* + * If there are protected objects then fail. However, everything + * else should have been flushed. + */ + if (f->cache->nprots>0) { + HRETURN_ERROR (H5E_CACHE, H5E_PROTECT, FAIL); + } + FUNC_LEAVE (SUCCEED); } @@ -342,6 +406,9 @@ H5AC_flush (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr, * exist on disk yet, but it must have an address and disk * space reserved. * + * If H5AC_DEBUG_PROTECT is defined then this function checks + * that the object being inserted isn't a protected object. + * * Return: Success: SUCCEED * * Failure: FAIL @@ -358,8 +425,9 @@ herr_t H5AC_set (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr, void *thing) { herr_t status; - uintn idx = H5AC_HASH (addr); + uintn idx; herr_t (*flush)(hdf5_file_t*,hbool_t,haddr_t,void*)=NULL; + H5AC_slot_t *slot = NULL; FUNC_ENTER (H5AC_set, NULL, FAIL); @@ -369,18 +437,29 @@ H5AC_set (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr, void *thing) assert (type->flush); assert (addr>=0); assert (thing); - - if (f->cache[idx].type) { - flush = f->cache[idx].type->flush; - status = (flush)(f, TRUE, f->cache[idx].addr, f->cache[idx].thing); + idx = H5AC_HASH (f, addr); + slot = f->cache->slot + idx; + +#if defined(H5AC_DEBUG_PROTECT) && !defined(NDEBUG) + { + intn i; + for (i=0; inprots; i++) { + assert (addr!=slot->prot[i].addr); + } + } +#endif + + if (slot->type) { + flush = slot->type->flush; + status = (flush)(f, TRUE, slot->addr, slot->thing); if (status<0) { HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL); } } - f->cache[idx].type = type; - f->cache[idx].addr = addr; - f->cache[idx].thing = thing; + slot->type = type; + slot->addr = addr; + slot->thing = thing; FUNC_LEAVE (SUCCEED); } @@ -392,6 +471,10 @@ H5AC_set (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr, void *thing) * Purpose: Use this function to notify the cache that an object's * file address changed. * + * If H5AC_DEBUG_PROTECT is defined then this function checks + * that the old and new addresses don't correspond to the + * address of a protected object. + * * Return: Success: SUCCEED * * Failure: FAIL @@ -408,8 +491,7 @@ herr_t H5AC_rename (hdf5_file_t *f, const H5AC_class_t *type, haddr_t old_addr, haddr_t new_addr) { - uintn old_idx = H5AC_HASH (old_addr); - uintn new_idx = H5AC_HASH (new_addr); + uintn old_idx, new_idx; herr_t (*flush)(hdf5_file_t*, hbool_t, haddr_t, void*); herr_t status; @@ -420,23 +502,42 @@ H5AC_rename (hdf5_file_t *f, const H5AC_class_t *type, assert (type); assert (old_addr>=0); assert (new_addr>=0); + old_idx = H5AC_HASH (f, old_addr); + new_idx = H5AC_HASH (f, new_addr); - if (f->cache[old_idx].type!=type || f->cache[old_idx].addr!=old_addr) { +#if defined(H5AC_DEBUG_PROTECT) && !defined(NDEBUG) + { + int i; + + for (i=0; icache->slot[old_idx].nprots; i++) { + assert (old_addr!=f->cache->slot[old_idx].prot[i].addr); + } + for (i=0; icache->slot[new_idx].nprots; i++) { + assert (new_addr!=f->cache->slot[new_idx].prot[i].addr); + } + } +#endif + + /* + * We don't need to do anything if the object isn't cached or if the + * new hash value is the same as the old one. + */ + if (f->cache->slot[old_idx].type!=type || + f->cache->slot[old_idx].addr!=old_addr) { HRETURN (SUCCEED); } - if (old_idx==new_idx) { - f->cache[old_idx].addr = new_addr; + f->cache->slot[old_idx].addr = new_addr; HRETURN (SUCCEED); } /* * Free the item from the destination cache line. */ - if (f->cache[new_idx].type) { - flush = f->cache[new_idx].type->flush; - status = (flush)(f, TRUE, f->cache[new_idx].addr, - f->cache[new_idx].thing); + if (f->cache->slot[new_idx].type) { + flush = f->cache->slot[new_idx].type->flush; + status = (flush)(f, TRUE, f->cache->slot[new_idx].addr, + f->cache->slot[new_idx].thing); if (status<0) { HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL); } @@ -445,11 +546,203 @@ H5AC_rename (hdf5_file_t *f, const H5AC_class_t *type, /* * Move the source to the destination (it might not be cached) */ - f->cache[new_idx].type = f->cache[old_idx].type; - f->cache[new_idx].addr = new_addr; - f->cache[new_idx].thing = f->cache[old_idx].thing; - f->cache[old_idx].type = NULL; + f->cache->slot[new_idx].type = f->cache->slot[old_idx].type; + f->cache->slot[new_idx].addr = new_addr; + f->cache->slot[new_idx].thing = f->cache->slot[old_idx].thing; + f->cache->slot[old_idx].type = NULL; FUNC_LEAVE (SUCCEED); } + +/*------------------------------------------------------------------------- + * Function: H5AC_protect + * + * Purpose: Similar to H5AC_find() except the object is removed from + * the cache and given to the caller, preventing other parts + * of the program from modifying the protected object or + * preempting it from the cache. + * + * The caller must call H5AC_unprotect() when finished with + * the pointer. + * + * If H5AC_DEBUG_PROTECT is defined then we check that the + * requested object isn't already protected. + * + * Return: Success: Ptr to the object. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Sep 2 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void * +H5AC_protect (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr, + const void *udata) +{ + int idx; + void *thing = NULL; + H5AC_slot_t *slot = NULL; + + FUNC_ENTER (H5AC_protect, NULL, NULL); + + /* check args */ + assert (f); + assert (f->cache); + assert (type); + assert (type->load); + assert (type->flush); + idx = H5AC_HASH (f, addr); + slot = f->cache->slot+idx; + + if (slot->type==type && slot->addr==addr) { + /* + * The object is already cached; simply remove it from the cache. + */ + thing = slot->thing; + slot->type = NULL; + slot->addr = 0; + slot->thing = NULL; + + } else if (slot->type && slot->addr==addr) { + /* + * Right address but wrong object type. + */ + HRETURN_ERROR (H5E_CACHE, H5E_BADTYPE, NULL); + + } else { +#if defined(H5AC_DEBUG_PROTECT) && !defined(NDEBUG) + /* + * Check that the requested thing isn't protected, for protected things + * can only be modified through the pointer already handed out by the + * H5AC_protect() function. + */ + intn i; + for (i=0; inprots; i++) { + assert (addr!=slot->prot[i].addr); + } +#endif + + /* + * Load a new thing. If it can't be loaded, then return an error + * without preempting anything. + */ + if (NULL==(thing=(type->load)(f, addr, udata))) { + HRETURN_ERROR (H5E_CACHE, H5E_CANTLOAD, NULL); + } + } + +#if defined(H5AC_DEBUG_PROTECT) && !defined(NDEBUG) + /* + * Add the protected object to the protect debugging fields of the + * cache. + */ + if (slot->nprots>=slot->aprots) { + slot->aprots += 10; + slot->prot = H5MM_xrealloc (slot->prot, + slot->aprots * sizeof(H5AC_prot_t)); + } + slot->prot[slot->nprots].type = type; + slot->prot[slot->nprots].addr = addr; + slot->prot[slot->nprots].thing = thing; + slot->nprots += 1; +#endif + + f->cache->nprots += 1; + FUNC_LEAVE (thing); +} + + +/*------------------------------------------------------------------------- + * Function: H5AC_unprotect + * + * Purpose: This function should be called to undo the effect of + * H5AC_protect(). The TYPE and ADDR arguments should be the + * same as the corresponding call to H5AC_protect() and the + * THING argument should be the value returned by H5AC_protect(). + * + * If H5AC_DEBUG_PROTECT is defined then this function fails + * if the TYPE and ADDR arguments are not what was used when the + * object was protected or if the object was never protected. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Sep 2 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5AC_unprotect (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr, + void *thing) +{ + herr_t status; + uintn idx; + herr_t (*flush)(hdf5_file_t*,hbool_t,haddr_t,void*)=NULL; + H5AC_slot_t *slot = NULL; + + FUNC_ENTER (H5AC_unprotect, NULL, FAIL); + + /* check args */ + assert (f); + assert (f->cache); + assert (type); + assert (type->flush); + assert (addr>=0); + assert (thing); + idx = H5AC_HASH (f, addr); + slot = f->cache->slot + idx; + + /* + * Flush any object already in the cache at that location. It had + * better not be another copy of the protected object. + */ + if (slot->type) { + assert (slot->addr!=addr); + flush = slot->type->flush; + status = (flush)(f, TRUE, slot->addr, slot->thing); + if (status<0) { + HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL); + } + } + +#if defined(H5AC_DEBUG_PROTECT) && !defined(NDEBUG) + /* + * Remove the object's protect data to indicate that it is no longer + * protected. + */ + { + int found, i; + for (i=0,found=FALSE; inprots && !found; i++) { + if (addr==slot->prot[i].addr) { + assert (slot->prot[i].type==type); + HDmemmove (slot->prot+i, slot->prot+i+1, + ((slot->nprots-i)-1) * sizeof(H5AC_prot_t)); + slot->nprots -= 1; + found = TRUE; + } + } + assert (found); + } +#endif + + /* + * Insert the object back into the cache; it is no longer protected. + */ + slot->type = type; + slot->addr = addr; + slot->thing = thing; + f->cache->nprots -= 1; + + FUNC_LEAVE (SUCCEED); +} diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h index 96d32c9..ee002f4 100644 --- a/src/H5ACprivate.h +++ b/src/H5ACprivate.h @@ -50,13 +50,29 @@ typedef struct H5AC_class_t { * own cache, an array of slots. */ #define H5AC_NSLOTS 10330 /*prime number tend to work best */ -#define H5AC_HASH(ADDR) ((unsigned)(ADDR) % H5AC_NSLOTS) +#define H5AC_HASH(F,ADDR) ((unsigned)(ADDR) % (F)->cache->nslots) -typedef struct H5AC_cache_t { +typedef struct H5AC_prot_t { + const H5AC_class_t *type; /*type of protected thing */ + haddr_t addr; /*address of protected thing */ + void *thing; /*(possible) protected thing */ +} H5AC_prot_t; + +typedef struct H5AC_slot_t { const H5AC_class_t *type; /*type of object stored here */ haddr_t addr; /*file address for object */ void *thing; /*the thing which is cached */ -} H5AC_cache_t; + intn nprots; /*number of things protected */ + intn aprots; /*nelmts of `prot' array */ + H5AC_prot_t *prot; /*array of protected things */ +} H5AC_slot_t; + +typedef struct H5AC_t { + intn nslots; /*number of cache slots */ + H5AC_slot_t *slot; /*the cache slots */ + intn nprots; /*number of protected objects */ +} H5AC_t; + /* * Library prototypes. @@ -64,18 +80,23 @@ typedef struct H5AC_cache_t { herr_t H5AC_dest (hdf5_file_t *f); void *H5AC_find_f (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr, const void *udata); +void * H5AC_protect (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr, + const void *udata); +herr_t H5AC_unprotect (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr, + void *thing); herr_t H5AC_flush (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr, hbool_t destroy); -herr_t H5AC_new (hdf5_file_t *f); +herr_t H5AC_new (hdf5_file_t *f, intn size_hint); herr_t H5AC_rename (hdf5_file_t *f, const H5AC_class_t *type, haddr_t old, haddr_t new); herr_t H5AC_set (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr, void *thing); #define H5AC_find(F,TYPE,ADDR,UDATA) \ - (((F)->cache[H5AC_HASH(ADDR)].type==(TYPE) && \ - (F)->cache[H5AC_HASH(ADDR)].addr==(ADDR)) ? \ - (F)->cache[H5AC_HASH(ADDR)].thing : \ + (((F)->cache->slot[H5AC_HASH(F,ADDR)].type==(TYPE) && \ + (F)->cache->slot[H5AC_HASH(F,ADDR)].addr==(ADDR)) ? \ + (F)->cache->slot[H5AC_HASH(F,ADDR)].thing : \ H5AC_find_f (F, TYPE, ADDR, UDATA)) + #endif /* !_H5ACprivate_H */ diff --git a/src/H5B.c b/src/H5B.c index 7023899..c6249eb 100644 --- a/src/H5B.c +++ b/src/H5B.c @@ -101,9 +101,12 @@ /* PRIVATE PROTOTYPES */ static haddr_t H5B_insert_helper (hdf5_file_t *f, haddr_t addr, const H5B_class_t *type, - uint8 *lt_key, intn *lt_key_changed, + uint8 *lt_key, hbool_t *lt_key_changed, uint8 *md_key, void *udata, - uint8 *rt_key, intn *rt_key_changed); + uint8 *rt_key, hbool_t *rt_key_changed); +static herr_t H5B_insert_child (hdf5_file_t *f, const H5B_class_t *type, + H5B_t *bt, intn idx, haddr_t child, + intn anchor, void *md_key); static herr_t H5B_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5B_t *b); static H5B_t *H5B_load (hdf5_file_t *f, haddr_t addr, const void *_data); @@ -166,13 +169,13 @@ H5B_new (hdf5_file_t *f, const H5B_class_t *type) bt = H5MM_xmalloc (sizeof(H5B_t)); bt->type = type; bt->sizeof_rkey = sizeof_rkey; - bt->dirty = 1; + bt->dirty = TRUE; bt->ndirty = 0; bt->type = type; bt->level = 0; bt->left = bt->right = 0; bt->nchildren = 0; - bt->page = H5MM_xmalloc (size); + bt->page = H5MM_xcalloc (1, size); /*use calloc() to keep file clean*/ bt->native = H5MM_xmalloc (total_native_keysize); bt->child = H5MM_xmalloc (2*H5B_K(f,type) * sizeof(haddr_t)); bt->key = H5MM_xmalloc ((2*H5B_K(f,type)+1) * sizeof(H5B_key_t)); @@ -186,7 +189,7 @@ H5B_new (hdf5_file_t *f, const H5B_class_t *type) i<2*H5B_K(f,type); i++,offset+=bt->sizeof_rkey+H5F_SIZEOF_OFFSET(f)) { - bt->key[i].dirty = 0; + bt->key[i].dirty = FALSE; bt->key[i].rkey = bt->page + offset; bt->key[i].nkey = NULL; bt->child[i] = 0; @@ -195,7 +198,7 @@ H5B_new (hdf5_file_t *f, const H5B_class_t *type) /* * The last possible key... */ - bt->key[2*H5B_K(f,type)].dirty = 0; + bt->key[2*H5B_K(f,type)].dirty = FALSE; bt->key[2*H5B_K(f,type)].rkey = bt->page + offset; bt->key[2*H5B_K(f,type)].nkey = NULL; @@ -248,7 +251,7 @@ H5B_load (hdf5_file_t *f, haddr_t addr, const void *_data) bt->sizeof_rkey = (type->get_sizeof_rkey)(f); size = H5B_nodesize (f, type, &total_nkey_size, bt->sizeof_rkey); bt->type = type; - bt->dirty = 0; + bt->dirty = FALSE; bt->ndirty = 0; bt->page = H5MM_xmalloc (size); bt->native = H5MM_xmalloc (total_nkey_size); @@ -277,7 +280,7 @@ H5B_load (hdf5_file_t *f, haddr_t addr, const void *_data) /* the child/key pairs */ for (i=0; i<2*H5B_K(f,type); i++) { - bt->key[i].dirty = 0; + bt->key[i].dirty = FALSE; bt->key[i].rkey = p; p += bt->sizeof_rkey; bt->key[i].nkey = NULL; @@ -290,7 +293,7 @@ H5B_load (hdf5_file_t *f, haddr_t addr, const void *_data) } } - bt->key[2*H5B_K(f,type)].dirty = 0; + bt->key[2*H5B_K(f,type)].dirty = FALSE; bt->key[2*H5B_K(f,type)].rkey = p; bt->key[2*H5B_K(f,type)].nkey = NULL; FUNC_LEAVE (bt); @@ -372,7 +375,7 @@ H5B_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5B_t *bt) HRETURN_ERROR (H5E_BTREE, H5E_CANTENCODE, FAIL); } } - bt->key[i].dirty = 0; + bt->key[i].dirty = FALSE; } p += bt->sizeof_rkey; @@ -392,7 +395,7 @@ H5B_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5B_t *bt) if (H5F_block_write (f, addr, size, bt->page)<0) { HRETURN_ERROR (H5E_BTREE, H5E_CANTFLUSH, FAIL); } - bt->dirty = 0; + bt->dirty = FALSE; bt->ndirty = 0; } @@ -438,9 +441,8 @@ herr_t 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; + int ret_value = FAIL; FUNC_ENTER (H5B_find, NULL, FAIL); @@ -449,7 +451,6 @@ H5B_find (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, void *udata) */ assert (f); assert (type); - assert (type->sizeof_nkey < sizeof lt_key); assert (type->decode); assert (type->cmp); assert (type->found); @@ -457,63 +458,59 @@ H5B_find (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, void *udata) /* * Perform a binary search to locate the child which contains - * the thing for which we're searching. The comparison function - * may preempt the B-tree node from the cache. + * the thing for which we're searching. */ - if (NULL==(bt=H5AC_find (f, H5AC_BT, addr, type))) { - HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); + if (NULL==(bt=H5AC_protect (f, H5AC_BT, addr, type))) { + HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); } rt = bt->nchildren; while (ltkey[idx].nkey && H5B_decode_key (f, bt, idx)<0) { - HRETURN_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); + HGOTO_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)<0) { - HRETURN_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); + HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); } - HDmemcpy (rt_key, bt->key[idx+1].nkey, type->sizeof_nkey); /* compare */ - if ((cmp=(type->cmp)(f, lt_key, udata, rt_key))<0) { + if ((cmp=(type->cmp)(f, bt->key[idx].nkey, udata, + bt->key[idx+1].nkey))<0) { rt = idx; } else { lt = idx+1; } } if (cmp) { - HRETURN_ERROR (H5E_BTREE, H5E_NOTFOUND, FAIL); + HGOTO_ERROR (H5E_BTREE, H5E_NOTFOUND, FAIL); } /* * Follow the link to the subtree or to the data node. */ - 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) { - retval = H5B_find (f, type, bt->child[idx], udata); - if (retval<0) { - HRETURN_ERROR (H5E_BTREE, H5E_NOTFOUND, FAIL); + if ((ret_value = H5B_find (f, type, bt->child[idx], udata))<0) { + HGOTO_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); + ret_value = (type->found)(f, bt->child[idx], bt->key[idx].nkey, + udata, bt->key[idx+1].nkey); + if (ret_value<0) { + HGOTO_ERROR (H5E_BTREE, H5E_NOTFOUND, FAIL); } } - FUNC_LEAVE (retval); +done: + if (bt && H5AC_unprotect (f, H5AC_BT, addr, bt)<0) { + HRETURN_ERROR (H5E_BTREE, H5E_PROTECT, FAIL); + } + FUNC_LEAVE (ret_value); } @@ -525,6 +522,9 @@ H5B_find (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, void *udata) * the old node. If anchor is H5B_ANCHOR_RT then the * new node gets the left half of the old node. * + * The OLD_BT argument is a pointer to a protected B-tree + * node. + * * Return: Success: Address of the new node. * * Failure: FAIL @@ -538,16 +538,13 @@ 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_split (hdf5_file_t *f, const H5B_class_t *type, H5B_t *old_bt, + haddr_t old_addr, intn anchor) { - H5B_t *old = NULL; - H5B_t *bt = NULL; - size_t total_nkey_size, size; - intn i, offset; - intn delta = H5B_ANCHOR_LT==anchor ? H5B_K(f,type) : 0; + H5B_t *new_bt=NULL, *tmp_bt=NULL; + haddr_t ret_value=FAIL, new_addr=FAIL; + intn i, delta; size_t recsize = 0; - haddr_t tmp_addr, new_addr; - H5B_t *tmp=NULL; FUNC_ENTER (H5B_split, NULL, FAIL); @@ -556,157 +553,125 @@ H5B_split (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, intn anchor) */ assert (f); assert (type); - assert (addr>=0); + assert (old_addr>=0); /* - * Initialize variables + * Initialize variables. */ - if (NULL==(old=H5AC_find (f, H5AC_BT, addr, type))) { - HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); - } - assert (old->nchildren == 2*H5B_K(f,type)); - bt = H5MM_xmalloc (sizeof(H5B_t)); - recsize = old->sizeof_rkey + H5F_SIZEOF_OFFSET(f); + assert (old_bt->nchildren == 2*H5B_K(f,type)); + recsize = old_bt->sizeof_rkey + H5F_SIZEOF_OFFSET(f); + delta = H5B_ANCHOR_LT==anchor ? H5B_K(f,type) : 0; /* * Create the new B-tree node. */ - size = H5B_nodesize (f, type, &total_nkey_size, old->sizeof_rkey); - bt->dirty = 1; - bt->sizeof_rkey = old->sizeof_rkey; - bt->ndirty = BOUND (0, old->ndirty-delta, H5B_K(f,type)); - bt->type = type; - bt->level = old->level; - bt->nchildren = H5B_K(f,type); - bt->page = H5MM_xcalloc (size, 1); /*use calloc() to keep file clean*/ - bt->native = H5MM_xmalloc (total_nkey_size); - bt->child = H5MM_xmalloc (2*H5B_K(f,type) * sizeof(haddr_t)); - bt->key = H5MM_xmalloc ((2*H5B_K(f,type)+1) * sizeof(H5B_key_t)); + if ((new_addr = H5B_new (f, type))<0) { + HGOTO_ERROR (H5E_BTREE, H5E_CANTINIT, FAIL); + } + if (NULL==(new_bt=H5AC_protect (f, H5AC_BT, new_addr, type))) { + HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); + } + new_bt->level = old_bt->level; /* - * Copy data into the new node from the old node. + * Copy data from the old node to the new node. */ - HDmemcpy (bt->page + H5B_SIZEOF_HDR(f), - old->page + H5B_SIZEOF_HDR(f) + delta*recsize, - H5B_K(f,type) * recsize + bt->sizeof_rkey); - HDmemcpy (bt->native, - old->native + delta * type->sizeof_nkey, + HDmemcpy (new_bt->page + H5B_SIZEOF_HDR(f), + old_bt->page + H5B_SIZEOF_HDR(f) + delta*recsize, + H5B_K(f,type) * recsize + new_bt->sizeof_rkey); + HDmemcpy (new_bt->native, + old_bt->native + delta * type->sizeof_nkey, (H5B_K(f,type)+1) * type->sizeof_nkey); - for (i=0, offset=H5B_SIZEOF_HDR(f); - i<=2*H5B_K(f,type); - i++,offset+=recsize) { - + for (i=0; i<=2*H5B_K(f,type); i++) { /* key */ if (i<=H5B_K(f,type)) { - bt->key[i].dirty = old->key[delta+i].dirty; - bt->key[i].rkey = bt->page + offset; - if (old->key[delta+i].nkey) { - bt->key[i].nkey = bt->native + i*type->sizeof_nkey; - } else { - bt->key[i].nkey = NULL; + new_bt->key[i].dirty = old_bt->key[delta+i].dirty; + if (old_bt->key[delta+i].nkey) { + new_bt->key[i].nkey = new_bt->native + i*type->sizeof_nkey; } - } else { - bt->key[i].dirty = 0; - bt->key[i].rkey = bt->page + offset; - bt->key[i].nkey = NULL; } - /* child */ if (ichild[i] = old->child[delta+i]; - } else if (i<2*H5B_K(f,type)) { - bt->child[i] = 0; + new_bt->child[i] = old_bt->child[delta+i]; } } - + new_bt->ndirty = BOUND (0, old_bt->ndirty-delta, H5B_K(f,type)); + new_bt->nchildren = H5B_K(f,type); /* * Truncate the old node. */ delta = H5B_ANCHOR_LT==anchor ? 0 : H5B_K(f,type); - old->dirty += 1; - old->ndirty = BOUND (0, old->ndirty-delta, H5B_K(f,type)); - old->nchildren = H5B_K(f,type); + old_bt->dirty = TRUE; + old_bt->ndirty = BOUND (0, old_bt->ndirty-delta, H5B_K(f,type)); + old_bt->nchildren = H5B_K(f,type); if (H5B_ANCHOR_RT==anchor) { - HDmemcpy (old->page + H5B_SIZEOF_HDR(f), - old->page + H5B_SIZEOF_HDR(f) + delta*recsize, + HDmemcpy (old_bt->page + H5B_SIZEOF_HDR(f), + old_bt->page + H5B_SIZEOF_HDR(f) + delta*recsize, H5B_K(f,type) * recsize); - HDmemmove (old->native, - old->native + delta * type->sizeof_nkey, + HDmemmove (old_bt->native, + old_bt->native + delta * type->sizeof_nkey, (H5B_K(f,type)+1) * type->sizeof_nkey); for (i=0; i<=2*H5B_K(f,type); i++) { if (i<=H5B_K(f,type)) { - old->key[i].dirty = old->key[delta+i].dirty; - if (old->key[delta+i].nkey) { - old->key[i].nkey = old->native + i * type->sizeof_nkey; + old_bt->key[i].dirty = old_bt->key[delta+i].dirty; + if (old_bt->key[delta+i].nkey) { + old_bt->key[i].nkey = old_bt->native + i * type->sizeof_nkey; } else { - old->key[i].nkey = NULL; + old_bt->key[i].nkey = NULL; } } else { - old->key[i].nkey = NULL; + old_bt->key[i].nkey = NULL; } if (ichild[i] = old->child[delta+i]; + old_bt->child[i] = old_bt->child[delta+i]; } else if (i<2*H5B_K(f,type)) { - old->child[i] = 0; + old_bt->child[i] = 0; } } } /* - * Update sibling pointers of new node. + * Update sibling pointers. */ if (H5B_ANCHOR_LT==anchor) { - bt->left = addr; - bt->right = old->right; - } else { - bt->left = old->left; - bt->right = addr; - } - - /* - * Add the new node to the cache. - */ - new_addr = H5MF_alloc (f, size); - if (H5AC_set (f, H5AC_BT, new_addr, bt)<0) { - HRETURN_ERROR (H5E_BTREE, H5E_CANTINIT, FAIL); - } + new_bt->left = old_addr; + new_bt->right = old_bt->right; - /* - * Update sibling pointers of old nodes. - */ - 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) { - if (NULL==(tmp = H5AC_find (f, H5AC_BT, tmp_addr, type))) { - HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); + if (old_bt->right) { + if (NULL==(tmp_bt=H5AC_find (f, H5AC_BT, old_bt->right, type))) { + HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); } - tmp->dirty += 1; - tmp->left = new_addr; + tmp_bt->dirty = TRUE; + tmp_bt->left = new_addr; } + old_bt->right = new_addr; } else { - old->dirty += 1; - tmp_addr = old->left; - old->left = new_addr; - if (tmp_addr) { - if (NULL==(tmp = H5AC_find (f, H5AC_BT, tmp_addr, type))) { - HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); + new_bt->left = old_bt->left; + new_bt->right = old_addr; + + if (old_bt->left) { + if (NULL==(tmp_bt=H5AC_find (f, H5AC_BT, old_bt->left, type))) { + HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); } - tmp->dirty += 1; - tmp->right = new_addr; + tmp_bt->dirty = TRUE; + tmp_bt->right = new_addr; } + old_bt->left = new_addr; } + HGOTO_DONE (new_addr); - FUNC_LEAVE (new_addr); +done: + { + if (new_bt && H5AC_unprotect (f, H5AC_BT, new_addr, new_bt)<0) { + HRETURN_ERROR (H5E_BTREE, H5E_PROTECT, FAIL); + } + } + FUNC_LEAVE (ret_value); } @@ -765,7 +730,7 @@ haddr_t H5B_insert (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, void *udata) { uint8 lt_key[256], md_key[256], rt_key[256]; - intn lt_key_changed=FALSE, rt_key_changed=FALSE; + hbool_t lt_key_changed=FALSE, rt_key_changed=FALSE; haddr_t child, new_root; intn level; H5B_t *bt; @@ -846,14 +811,14 @@ H5B_insert (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, void *udata) if (NULL==(bt=H5AC_find (f, H5AC_BT, child, type))) { HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); } - bt->dirty += 1; + bt->dirty = TRUE; bt->left = addr; /* clear the old root at the old address */ if (NULL==(bt=H5AC_find (f, H5AC_BT, new_root, type))) { HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); } - bt->dirty += 1; + bt->dirty = TRUE; bt->ndirty = 0; bt->left = 0; bt->right = 0; @@ -864,22 +829,22 @@ H5B_insert (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, void *udata) if (NULL==(bt = H5AC_find (f, H5AC_BT, new_root, type))) { HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); } - bt->dirty += 1; + bt->dirty = TRUE; bt->ndirty = 2; bt->level = level+1; bt->nchildren = 2; bt->child[0] = addr; - bt->key[0].dirty = 1; + bt->key[0].dirty = TRUE; bt->key[0].nkey = bt->native; HDmemcpy (bt->key[0].nkey, lt_key, type->sizeof_nkey); bt->child[1] = child; - bt->key[1].dirty = 1; + bt->key[1].dirty = TRUE; bt->key[1].nkey = bt->native + type->sizeof_nkey; HDmemcpy (bt->key[1].nkey, md_key, type->sizeof_nkey); - bt->key[2].dirty = 1; + bt->key[2].dirty = TRUE; bt->key[2].nkey = bt->native + 2 * type->sizeof_nkey; HDmemcpy (bt->key[2].nkey, rt_key, type->sizeof_nkey); @@ -891,7 +856,8 @@ H5B_insert (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, void *udata) * Function: H5B_insert_child * * Purpose: Insert a child at the specified address with the - * specified left or right key. + * specified left or right key. The BT argument is a pointer + * to a protected B-tree node. * * Return: Success: SUCCEED * @@ -906,19 +872,16 @@ H5B_insert (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, void *udata) *------------------------------------------------------------------------- */ static herr_t -H5B_insert_child (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, +H5B_insert_child (hdf5_file_t *f, const H5B_class_t *type, H5B_t *bt, intn idx, haddr_t child, intn anchor, void *md_key) { - H5B_t *bt; size_t recsize; intn i; FUNC_ENTER (H5B_insert_child, NULL, FAIL); + assert (bt); - if (NULL==(bt=H5AC_find (f, H5AC_BT, addr, type))) { - HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); - } - bt->dirty += 1; + bt->dirty = TRUE; recsize = bt->sizeof_rkey + H5F_SIZEOF_OFFSET(f); if (H5B_ANCHOR_LT==anchor) { @@ -941,7 +904,7 @@ H5B_insert_child (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, bt->key[i+1].nkey = NULL; } } - bt->key[idx].dirty = 1; + bt->key[idx].dirty = TRUE; bt->key[idx].nkey = bt->native + idx * type->sizeof_nkey; HDmemcpy (bt->key[idx].nkey, md_key, type->sizeof_nkey); @@ -967,7 +930,7 @@ H5B_insert_child (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, bt->key[i+1].nkey = NULL; } } - bt->key[idx+1].dirty = 1; + bt->key[idx+1].dirty = TRUE; bt->key[idx+1].nkey = bt->native + (idx+1) * type->sizeof_nkey; HDmemcpy (bt->key[idx+1].nkey, md_key, type->sizeof_nkey); } @@ -1018,14 +981,14 @@ H5B_insert_child (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, */ static haddr_t H5B_insert_helper (hdf5_file_t *f, haddr_t addr, const H5B_class_t *type, - uint8 *lt_key, intn *lt_key_changed, + uint8 *lt_key, hbool_t *lt_key_changed, uint8 *md_key, void *udata, - uint8 *rt_key, intn *rt_key_changed) + uint8 *rt_key, hbool_t *rt_key_changed) { - H5B_t *bt; + H5B_t *bt=NULL, *twin=NULL, *tmp_bt=NULL; intn lt=0, idx=-1, rt, cmp=-1; + haddr_t child_addr=0, twin_addr=0, ret_value=FAIL; intn anchor; - haddr_t child, twin=0; FUNC_ENTER (H5B_insert_helper, NULL, FAIL); @@ -1045,104 +1008,88 @@ H5B_insert_helper (hdf5_file_t *f, haddr_t addr, const H5B_class_t *type, /* * Use a binary search to find the child that will receive the new - * data. The comparison function may preempt the B-tree node from - * the cache each time through the loop. When the search completes - * IDX points to the child that should get the new data. + * data. When the search completes IDX points to the child that + * should get the new data. */ - if (NULL==(bt=H5AC_find (f, H5AC_BT, addr, type))) { - HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); + if (NULL==(bt=H5AC_protect (f, H5AC_BT, addr, type))) { + HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); } rt = bt->nchildren; while (ltkey[idx].nkey && H5B_decode_key (f, bt, idx)<0) { - HRETURN_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); + HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); } - HDmemcpy (lt_key, bt->key[idx].nkey, type->sizeof_nkey); /* right key */ if (!bt->key[idx+1].nkey && H5B_decode_key (f, bt, idx+1)<0) { - HRETURN_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); + HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); } - HDmemcpy (rt_key, bt->key[idx+1].nkey, type->sizeof_nkey); /* compare */ - if ((cmp=(type->cmp)(f, lt_key, udata, rt_key))<0) { + if ((cmp=(type->cmp)(f, bt->key[idx].nkey, udata, + bt->key[idx+1].nkey))<0) { rt = idx; } else { lt = idx+1; } } - /* - * Adjust for boundary conditions. If adjusting at the leaf level - * update the left and right key buffers since the data node insert - * function needs them as input. Don't worry about it at higher node - * levels because this function uses them for output only. - */ - if (NULL==(bt=H5AC_find (f, H5AC_BT, addr, type))) { - HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); - } if (cmp<0 && idx<=0) { + /* + * Boundary condition: the value to insert is the new minimum + * value in the B-tree. Insert the value in the left-most node. + */ idx = 0; cmp = 0; - if (0==bt->level && bt->nchildren) { - 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); - 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); - } + } else if (cmp>0 && idx+1>=bt->nchildren) { + /* + * Boundary condition: the value to insert is the new maximum + * value in the B-tree. Insert the value in the right-most node. + */ idx = bt->nchildren-1; cmp = 0; - if (0==bt->level && bt->nchildren) { - 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); - 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); - } } assert (0==cmp); - + + /* + * Ensure that both native keys exist since we may have made boundary + * condition adjustments. + */ + if (bt->nchildren) { + if (!bt->key[idx].nkey && H5B_decode_key (f, bt, idx)<0) { + HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); + } + if (!bt->key[idx+1].nkey && H5B_decode_key (f, bt, idx+1)<0) { + HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); + } + } + /* * If there are no children, then create a new child. This can only - * happen at the root of the B-tree. Creating a new child may - * preempt the B-tree node from the cache. The left and right key - * buffers are output values. + * happen at the root of the B-tree. The left and right native keys + * are output values from the node creation function. */ if (0==bt->nchildren) { - 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->key[0].nkey = bt->native; + bt->key[1].nkey = bt->native + type->sizeof_nkey; + + if ((child_addr=(type->new)(f, bt->key[0].nkey, udata, + bt->key[1].nkey))<0) { + bt->key[0].nkey = bt->key[1].nkey = NULL; + HGOTO_ERROR (H5E_BTREE, H5E_CANTINIT, FAIL); } bt->nchildren = 1; - bt->dirty += 1; + bt->dirty = TRUE; bt->ndirty = 1; - bt->child[0] = child; + bt->child[0] = child_addr; - bt->key[0].dirty = 1; - bt->key[0].nkey = bt->native; - HDmemcpy (bt->key[0].nkey, lt_key, type->sizeof_nkey); - - bt->key[1].dirty = 1; - bt->key[1].nkey = bt->native + type->sizeof_nkey; - HDmemcpy (bt->key[1].nkey, rt_key, type->sizeof_nkey); + bt->key[0].dirty = TRUE; + bt->key[1].dirty = TRUE; idx = 0; } @@ -1150,96 +1097,106 @@ H5B_insert_helper (hdf5_file_t *f, haddr_t addr, const H5B_class_t *type, * Insert the new data in the child B-tree node or in the data node. */ if (bt->level > 0) { - child = H5B_insert_helper (f, bt->child[idx], type, - lt_key, lt_key_changed, - md_key, udata, - rt_key, rt_key_changed); + child_addr = H5B_insert_helper (f, bt->child[idx], type, + bt->key[idx].nkey, lt_key_changed, + md_key, udata, + bt->key[idx+1].nkey, rt_key_changed); anchor = H5B_ANCHOR_LT; } else { - child = (type->insert)(f, bt->child[idx], &anchor, - lt_key, lt_key_changed, - md_key, udata, - rt_key, rt_key_changed); - } - 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); + child_addr = (type->insert)(f, bt->child[idx], &anchor, + bt->key[idx].nkey, lt_key_changed, + md_key, udata, + bt->key[idx+1].nkey, rt_key_changed); } + if (child_addr<0) HGOTO_ERROR (H5E_BTREE, H5E_CANTINSERT, FAIL); /* - * Update the left and right keys. + * Update the left and right keys of the current node. */ if (*lt_key_changed) { - bt->key[idx].nkey = bt->native + idx * type->sizeof_nkey; - HDmemcpy (bt->key[idx].nkey, lt_key, type->sizeof_nkey); - bt->dirty += 1; - bt->key[idx].dirty = 1; - if (idx>0) *lt_key_changed = FALSE; + bt->dirty = TRUE; + bt->key[idx].dirty = TRUE; + if (idx>0) { + *lt_key_changed = FALSE; + } else { + HDmemcpy (lt_key, bt->key[idx].nkey, type->sizeof_nkey); + } } if (*rt_key_changed) { - bt->key[idx+1].nkey = bt->native + - (idx+1) * type->sizeof_nkey; - HDmemcpy (bt->key[idx+1].nkey, rt_key, type->sizeof_nkey); - bt->dirty += 1; - bt->key[idx+1].dirty = 1; - if (idx+1nchildren) *rt_key_changed = FALSE; + bt->dirty = TRUE; + bt->key[idx+1].dirty = TRUE; + if (idx+1nchildren) { + *rt_key_changed = FALSE; + } else { + HDmemcpy (rt_key, bt->key[idx+1].nkey, type->sizeof_nkey); + } } /* - * If the child split and the left node is anchored, then the new - * child node gets inserted to the right of our current position. - */ - if (child && H5B_ANCHOR_LT==anchor) idx++; - - /* - * Split this node if the child node split and this node is full. - * Make sure `addr' points to the node that gets the new child - * and that `idx' is adjusted appropriately. + * Insert the child, splitting the current node if necessary. */ - if (child && bt->nchildren==2*H5B_K(f,type)) { - if ((twin = H5B_split (f, type, addr, anchor))<0) { - HRETURN_ERROR (H5E_BTREE, H5E_CANTSPLIT, FAIL); - } - if (idx<=H5B_K(f,type)) { - addr = H5B_ANCHOR_LT==anchor ? addr : twin; + if (child_addr) { + /* + * If the child split and the left node is anchored, then the new + * child node gets inserted to the right of our current position. + */ + if (H5B_ANCHOR_LT==anchor) idx++; + + if (bt->nchildren==2*H5B_K(f,type)) { + /* Split the current node */ + if ((twin_addr = H5B_split (f, type, bt, addr, anchor))<0) { + HGOTO_ERROR (H5E_BTREE, H5E_CANTSPLIT, FAIL); + } + if (NULL==(twin=H5AC_protect (f, H5AC_BT, twin_addr, type))) { + HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); + } + + if (idx<=H5B_K(f,type)) { + tmp_bt = H5B_ANCHOR_LT==anchor ? bt : twin; + } else { + idx -= H5B_K (f, type); + tmp_bt = H5B_ANCHOR_LT==anchor ? twin : bt; + } } else { - idx -= H5B_K(f,type); - addr = H5B_ANCHOR_LT==anchor ? twin : addr; + tmp_bt = bt; } - } - - /* - * If the child split, then insert the new child. - */ - if (child) { - if (H5B_insert_child (f, type, addr, idx, child, anchor, md_key)<0) { - HRETURN_ERROR (H5E_BTREE, H5E_CANTINSERT, FAIL); + + if (H5B_insert_child (f, type, tmp_bt, idx, child_addr, anchor, + md_key)<0) { + HGOTO_ERROR (H5E_BTREE, H5E_CANTINSERT, FAIL); } } + /* * If this node split, return the mid key (the one that is shared * by the left and right node). */ if (twin) { - 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)<0) { - HRETURN_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); + if (!twin->key[0].nkey && H5B_decode_key (f, twin, 0)<0) { + HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); } - HDmemcpy (md_key, bt->key[0].nkey, type->sizeof_nkey); + HDmemcpy (md_key, twin->key[0].nkey, type->sizeof_nkey); } else { - if (!bt->key[bt->nchildren].nkey && - H5B_decode_key (f, bt, bt->nchildren)<0) { - HRETURN_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); + if (!bt->key[0].nkey && H5B_decode_key (f, bt, 0)<0) { + HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); } - HDmemcpy (md_key, bt->key[bt->nchildren].nkey, type->sizeof_nkey); + HDmemcpy (md_key, bt->key[0].nkey, type->sizeof_nkey); + } + } + HGOTO_DONE (twin_addr); + +done: + { + herr_t e1 = (bt && H5AC_unprotect (f, H5AC_BT, addr, bt)<0); + herr_t e2 = (twin && H5AC_unprotect (f, H5AC_BT, twin_addr, twin)<0); + if (e1 || e2) { /*use vars to prevent short-circuit of side effects*/ + HRETURN_ERROR (H5E_BTREE, H5E_PROTECT, FAIL); } } - FUNC_LEAVE (twin); + FUNC_LEAVE (ret_value); } @@ -1264,11 +1221,10 @@ H5B_insert_helper (hdf5_file_t *f, haddr_t addr, const H5B_class_t *type, herr_t 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; - herr_t (*list)(hdf5_file_t*,haddr_t,void*) = NULL; + H5B_t *bt=NULL; + haddr_t next_addr; + intn i; + herr_t ret_value = FAIL; FUNC_ENTER (H5B_list, NULL, FAIL); @@ -1284,7 +1240,7 @@ H5B_list (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, void *udata) if (NULL==(bt = H5AC_find (f, H5AC_BT, addr, type))) { HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); } - + if (bt->level>0) { if (H5B_list (f, type, bt->child[0], udata)<0) { HRETURN_ERROR (H5E_BTREE, H5E_CANTLIST, FAIL); @@ -1292,31 +1248,32 @@ H5B_list (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, void *udata) HRETURN (SUCCEED); } } else { - child = H5MM_xmalloc (2 * H5B_K(f,type) * sizeof(haddr_t)); - list = type->list; - twin = addr; - - while (twin) { /*for each leaf node*/ - if (NULL==(bt=H5AC_find (f, H5AC_BT, twin, type))) { - H5MM_xfree (child); - HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); + + for (/*void*/; addr>0; addr=next_addr) { + if (NULL==(bt=H5AC_protect (f, H5AC_BT, addr, type))) { + HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); } - nchildren = bt->nchildren; - twin = bt->right; - HDmemcpy (child, bt->child, nchildren * sizeof(haddr_t)); - bt = NULL; /*list callback may invalidate the cache*/ - for (i=0; inchildren; i++) { + if ((type->list)(f, bt->child[i], udata)<0) { + HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL); } } + + next_addr = bt->right; + if (H5AC_unprotect (f, H5AC_BT, addr, bt)<0) { + HRETURN_ERROR (H5E_BTREE, H5E_PROTECT, FAIL); + } + bt = NULL; } - H5MM_xfree (child); } + HGOTO_DONE (SUCCEED); - FUNC_LEAVE (SUCCEED); +done: + if (bt && H5AC_unprotect (f, H5AC_BT, addr, bt)<0) { + HRETURN_ERROR (H5E_BTREE, H5E_PROTECT, FAIL); + } + FUNC_LEAVE (ret_value); } @@ -1428,9 +1385,9 @@ H5B_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent, fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth, "Size of raw (disk) key:", (unsigned long)(bt->sizeof_rkey)); - fprintf (stream, "%*s%-*s %d\n", indent, "", fwidth, + fprintf (stream, "%*s%-*s %s\n", indent, "", fwidth, "Dirty flag:", - (int)(bt->dirty)); + bt->dirty?"True":"False"); fprintf (stream, "%*s%-*s %d\n", indent, "", fwidth, "Number of initial dirty children:", (int)(bt->ndirty)); diff --git a/src/H5Bprivate.h b/src/H5Bprivate.h index 5f1d251..597c79f 100644 --- a/src/H5Bprivate.h +++ b/src/H5Bprivate.h @@ -54,7 +54,7 @@ typedef struct H5B_class_t { size_t (*get_sizeof_rkey)(hdf5_file_t*); haddr_t (*new)(hdf5_file_t*,void*,void*,void*); intn (*cmp)(hdf5_file_t*,void*,void*,void*); - herr_t (*found)(hdf5_file_t*,haddr_t,void*,void*,void*); + herr_t (*found)(hdf5_file_t*,haddr_t,const void*,void*,const void*); haddr_t (*insert)(hdf5_file_t*,haddr_t,int*,void*,int*,void*,void*, void*,int*); herr_t (*list)(hdf5_file_t*,haddr_t,void*); @@ -66,7 +66,7 @@ typedef struct H5B_class_t { * The B-tree node as stored in memory... */ typedef struct H5B_key_t { - intn dirty; /*native key is more recent than raw key*/ + hbool_t dirty; /*native key is more recent than raw key*/ uint8 *rkey; /*ptr into node->page for raw key */ void *nkey; /*null or ptr into node->native for key */ } H5B_key_t; @@ -74,7 +74,7 @@ typedef struct H5B_key_t { typedef struct H5B_t { const H5B_class_t *type; /*type of tree */ size_t sizeof_rkey; /*size of raw (disk) key */ - intn dirty; /*something in the tree is dirty */ + hbool_t dirty; /*something in the tree is dirty */ intn ndirty; /*num child ptrs to emit */ intn level; /*node level */ haddr_t left; /*address of left sibling */ diff --git a/src/H5E.c b/src/H5E.c index 0ba21ae..d6474c2 100644 --- a/src/H5E.c +++ b/src/H5E.c @@ -89,6 +89,7 @@ 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_PROTECT, "Protected object error"}, {H5E_NOTFOUND, "Object not found"}, {H5E_EXISTS, "Object already exists"}, {H5E_CANTENCODE, "Can't encode value"}, diff --git a/src/H5Epublic.h b/src/H5Epublic.h index 6bb7704..4793994 100644 --- a/src/H5Epublic.h +++ b/src/H5Epublic.h @@ -84,6 +84,7 @@ typedef enum /* Cache related errors */ H5E_CANTFLUSH, /* Can't flush object from cache */ H5E_CANTLOAD, /* Can't load object into cache */ + H5E_PROTECT, /* Protected object error */ /* B-tree related errors */ H5E_NOTFOUND, /* Object not found */ diff --git a/src/H5F.c b/src/H5F.c index 03a3b52..dfdd862 100644 --- a/src/H5F.c +++ b/src/H5F.c @@ -373,7 +373,7 @@ H5F_new (void) hdf5_file_t *f = H5MM_xcalloc (1, sizeof(hdf5_file_t)); /* Create a cache */ - H5AC_new (f); + H5AC_new (f, H5AC_NSLOTS); /* Create a root symbol slot */ f->root_sym = H5MM_xcalloc (1, sizeof (H5G_entry_t)); @@ -918,6 +918,7 @@ H5F_flush (hdf5_file_t *f, hbool_t invalidate) ARGS BADTYPE Not a file atom. ATOM BADATOM Can't remove atom. ATOM BADATOM Can't unatomize file. + CACHE CANTFLUSH Can't flush cache. RETURNS SUCCEED/FAIL @@ -955,7 +956,10 @@ herr_t H5Fclose(hatom_t fid) if((--file->ref_count)==0) { if(file->file_handle!=H5F_INVALID_FILE) { - H5F_flush (file, TRUE); + if (H5F_flush (file, TRUE)<0) { + /*can't flush cache*/ + HGOTO_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL); + } H5F_CLOSE(file->file_handle); } H5F_dest (file); diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index e517670..275cb1d 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -298,7 +298,7 @@ typedef struct { haddr_t smallobj_off; /* Offset of small-obj heap within the file */ haddr_t freespace_off; /* Offset of free-space info within the file */ size_t logical_len; /* Logical length of file */ - struct H5AC_cache_t *cache; /* The object cache */ + struct H5AC_t *cache; /* The object cache */ file_create_temp_t file_create_parms; /* File-creation template */ #ifdef LATER file_access_temp_t file_access_parms; /* File-access template */ diff --git a/src/H5G.c b/src/H5G.c index 616f7a6..1cffed5 100644 --- a/src/H5G.c +++ b/src/H5G.c @@ -458,7 +458,7 @@ H5G_new (hdf5_file_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent, if (!ent) ent = &_child; /* Create root directory if necessary */ - H5G_mkroot (f, size_hint); + H5G_mkroot (f, H5G_SIZE_HINT); H5ECLEAR; /* lookup name */ @@ -834,10 +834,10 @@ H5G_stab_new (hdf5_file_t *f, H5G_entry_t *self, size_t init) init = MAX(init, H5H_SIZEOF_FREE(f)+2); /* Create symbol table private heap */ - if ((stab.heap = H5H_new (f, H5H_LOCAL, init))<0) { + if ((stab.heap_addr = H5H_new (f, H5H_LOCAL, init))<0) { HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); /*can't create heap*/ } - if ((name = H5H_insert (f, stab.heap, 1, "")<0)) { + if ((name = H5H_insert (f, stab.heap_addr, 1, "")<0)) { HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); /*can't initialize heap*/ } if (0!=name) { @@ -849,7 +849,7 @@ H5G_stab_new (hdf5_file_t *f, H5G_entry_t *self, size_t init) } /* Create the B-tree */ - if ((stab.btree = H5B_new (f, H5B_SNODE))<0) { + if ((stab.btree_addr = H5B_new (f, H5B_SNODE))<0) { HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); /*can't create B-tree*/ } @@ -919,10 +919,10 @@ H5G_stab_find (hdf5_file_t *f, H5G_entry_t *self, const char *name, } udata.operation = H5G_OPER_FIND; udata.name = name; - udata.heap = stab.heap; + udata.heap_addr = stab.heap_addr; /* search the B-tree */ - if (H5B_find (f, H5B_SNODE, stab.btree, &udata)<0) { + if (H5B_find (f, H5B_SNODE, stab.btree_addr, &udata)<0) { HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); /*not found*/ } @@ -977,11 +977,11 @@ H5G_stab_modify (hdf5_file_t *f, H5G_entry_t *self, const char *name, } udata.operation = H5G_OPER_MODIFY; udata.name = name; - udata.heap = stab.heap; + udata.heap_addr = stab.heap_addr; udata.entry = *ent; /* search and modify the B-tree */ - if (H5B_find (f, H5B_SNODE, stab.btree, &udata)<0) { + if (H5B_find (f, H5B_SNODE, stab.btree_addr, &udata)<0) { HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); /*not found*/ } @@ -1032,11 +1032,11 @@ H5G_stab_insert (hdf5_file_t *f, H5G_entry_t *self, const char *name, HRETURN_ERROR (H5E_SYM, H5E_BADMESG, FAIL); /*can't read message*/ } udata.name = name; - udata.heap = stab.heap; + udata.heap_addr = stab.heap_addr; udata.entry = *ent; /* insert */ - if (H5B_insert (f, H5B_SNODE, stab.btree, &udata)<0) { + if (H5B_insert (f, H5B_SNODE, stab.btree_addr, &udata)<0) { HRETURN_ERROR (H5E_SYM, H5E_CANTINSERT, FAIL); /*can't insert entry*/ } @@ -1098,13 +1098,13 @@ H5G_stab_list (hdf5_file_t *f, H5G_entry_t *self, intn maxentries, } udata.entry = entries; udata.name = names; - udata.heap = stab.heap; + udata.heap_addr = stab.heap_addr; udata.maxentries = maxentries; udata.nsyms = 0; if (names) HDmemset (names, 0, maxentries); /* list */ - if (H5B_list (f, H5B_SNODE, stab.btree, &udata)<0) { + if (H5B_list (f, H5B_SNODE, stab.btree_addr, &udata)<0) { if (names) { for (i=0; icache.stab.btree); - UINT32DECODE (*pp, ent->cache.stab.heap); + UINT32DECODE (*pp, ent->cache.stab.btree_addr); + UINT32DECODE (*pp, ent->cache.stab.heap_addr); break; default: @@ -1333,8 +1333,8 @@ H5G_encode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent) break; case H5G_CACHED_STAB: - UINT32ENCODE (*pp, ent->cache.stab.btree); - UINT32ENCODE (*pp, ent->cache.stab.heap); + UINT32ENCODE (*pp, ent->cache.stab.btree_addr); + UINT32ENCODE (*pp, ent->cache.stab.heap_addr); break; default: @@ -1417,10 +1417,10 @@ H5G_debug (hdf5_file_t *f, H5G_entry_t *ent, FILE *stream, intn indent, fprintf (stream, "Symbol Table\n"); fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth, "B-tree address:", - (unsigned long)(ent->cache.stab.btree)); + (unsigned long)(ent->cache.stab.btree_addr)); fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth, "Heap address:", - (unsigned long)(ent->cache.stab.heap)); + (unsigned long)(ent->cache.stab.heap_addr)); break; default: diff --git a/src/H5Gnode.c b/src/H5Gnode.c index 6c0866b..b344713 100644 --- a/src/H5Gnode.c +++ b/src/H5Gnode.c @@ -46,8 +46,9 @@ static H5G_node_t *H5G_node_load (hdf5_file_t *f, haddr_t addr, const void *_data); static intn H5G_node_cmp (hdf5_file_t *f, void *_lt_key, void *_udata, void *_rt_key); -static herr_t H5G_node_found (hdf5_file_t *f, haddr_t addr, void *_lt_key, - void *_udata, void *_rt_key); +static herr_t H5G_node_found (hdf5_file_t *f, haddr_t addr, + const void *_lt_key, void *_udata, + const void *_rt_key); static haddr_t H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor, void *_lt_key, hbool_t *lt_key_changed, void *_md_key, void *_udata, @@ -440,13 +441,13 @@ H5G_node_cmp (hdf5_file_t *f, void *_lt_key, void *_udata, void *_rt_key) FUNC_ENTER (H5G_node_cmp, NULL, FAIL); /* left side */ - if (NULL==(s=H5H_peek (f, udata->heap, lt_key->offset))) { + if (NULL==(s=H5H_peek (f, udata->heap_addr, lt_key->offset))) { HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); } if (HDstrcmp (udata->name, s)<=0) HRETURN (-1); /* right side */ - if (NULL==(s=H5H_peek (f, udata->heap, rt_key->offset))) { + if (NULL==(s=H5H_peek (f, udata->heap_addr, rt_key->offset))) { HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); } if (HDstrcmp (udata->name, s)>0) HRETURN(1); @@ -484,13 +485,14 @@ H5G_node_cmp (hdf5_file_t *f, void *_lt_key, void *_udata, void *_rt_key) *------------------------------------------------------------------------- */ static herr_t -H5G_node_found (hdf5_file_t *f, haddr_t addr, void *_lt_key, void *_udata, - void *_rt_key) +H5G_node_found (hdf5_file_t *f, haddr_t addr, const void *_lt_key, + void *_udata, const void *_rt_key) { H5G_node_ud1_t *udata = (H5G_node_ud1_t *)_udata; - H5G_node_t *sn; + H5G_node_t *sn = NULL; intn lt=0, idx=0, rt, cmp=1; const char *s; + herr_t ret_value = FAIL; FUNC_ENTER (H5G_node_found, NULL, FAIL); @@ -501,21 +503,21 @@ H5G_node_found (hdf5_file_t *f, haddr_t addr, void *_lt_key, void *_udata, assert (addr>=0); assert (udata); - if (NULL==(sn=H5AC_find (f, H5AC_SNODE, addr, NULL))) { - HRETURN_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL); + /* + * Load the symbol table node for exclusive access. + */ + if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, NULL))) { + HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL); } - rt = sn->nsyms; /* * Binary search. */ + rt = sn->nsyms; while (ltheap, sn->entry[idx].name_off))) { - HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); + if (NULL==(s=H5H_peek (f, udata->heap_addr, sn->entry[idx].name_off))) { + HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); } cmp = HDstrcmp (udata->name, s); @@ -525,7 +527,7 @@ H5G_node_found (hdf5_file_t *f, haddr_t addr, void *_lt_key, void *_udata, lt = idx+1; } } - if (cmp) HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); + if (cmp) HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); switch (udata->operation) { case H5G_OPER_FIND: @@ -543,8 +545,13 @@ H5G_node_found (hdf5_file_t *f, haddr_t addr, void *_lt_key, void *_udata, sn->dirty += 1; break; } + ret_value = SUCCEED; - FUNC_LEAVE (SUCCEED); +done: + if (sn && H5AC_unprotect (f, H5AC_SNODE, addr, sn)<0) { + HRETURN_ERROR (H5E_SYM, H5E_PROTECT, FAIL); + } + FUNC_LEAVE (ret_value); } @@ -594,13 +601,11 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor, H5G_node_key_t *rt_key = (H5G_node_key_t *)_rt_key; H5G_node_ud1_t *udata = (H5G_node_ud1_t *)_udata; - H5G_node_t *sn; - H5G_entry_t *ent, _ent[128]; + H5G_node_t *sn=NULL, *snrt=NULL; haddr_t new_node=0, offset; const char *s; - intn idx=-1, nsyms, cmp=1; + intn idx=-1, cmp=1; intn lt=0, rt; /*binary search cntrs */ - hbool_t malloced; haddr_t ret_value = FAIL; FUNC_ENTER (H5G_node_insert, NULL, FAIL); @@ -614,13 +619,6 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor, assert (md_key); assert (rt_key); assert (udata); - if (2*H5G_NODE_K(f)>NELMTS(_ent)) { - ent = H5MM_xmalloc (2*H5G_NODE_K(f) * sizeof(H5G_entry_t)); - malloced = TRUE; - } else { - ent = _ent; - malloced = FALSE; - } /* * Symbol tables are always split so the new symbol table node is @@ -631,22 +629,19 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor, *rt_key_changed = FALSE; /* - * Load the symbol node and buffer the entries so we don't have to - * worry about the cached value disappearing. + * Load the symbol node. */ - if (NULL==(sn=H5AC_find (f, H5AC_SNODE, addr, NULL))) { + if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, NULL))) { HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL); } - HDmemcpy (ent, sn->entry, sn->nsyms * sizeof(H5G_entry_t)); - rt = nsyms = sn->nsyms; - sn = NULL; /* * Where does the new symbol get inserted? We use a binary search. */ + rt = sn->nsyms; while (ltheap, ent[idx].name_off))) { + if (NULL==(s=H5H_peek (f, udata->heap_addr, sn->entry[idx].name_off))) { HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); } if (0==(cmp=HDstrcmp (udata->name, s))) { @@ -665,69 +660,66 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor, * heap address changed and update the symbol table object header * with the new heap address. */ - offset = H5H_insert (f, udata->heap, HDstrlen(udata->name)+1, udata->name); + offset = H5H_insert (f, udata->heap_addr, HDstrlen(udata->name)+1, + udata->name); udata->entry.name_off = offset; if (offset<0) HGOTO_ERROR (H5E_SYM, H5E_CANTINSERT, FAIL); - if (nsyms>=2*H5G_NODE_K(f)) { + if (sn->nsyms>=2*H5G_NODE_K(f)) { /* * The node is full. Split it into a left and right * node and return the address of the new right node (the * left node is at the same address as the original node). */ - - /* The left node */ - if (NULL==(sn=H5AC_find (f, H5AC_SNODE, addr, NULL))) { - HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL); - } - HDmemset (sn->entry+H5G_NODE_K(f), 0, H5G_NODE_K(f)*sizeof(H5G_entry_t)); - sn->nsyms = H5G_NODE_K(f); - sn->dirty += 1; - - if (idx<=H5G_NODE_K(f)) { - HDmemmove (sn->entry+idx+1, sn->entry+idx, - (H5G_NODE_K(f)-idx) * sizeof(H5G_entry_t)); - sn->entry[idx] = udata->entry; - sn->entry[idx].name_off = offset; - sn->nsyms += 1; - } - - /* The middle key */ - md_key->offset = sn->entry[sn->nsyms-1].name_off; /* The right node */ if ((new_node = H5G_node_new (f, NULL, NULL, NULL))<0) { HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); } - if (NULL==(sn=H5AC_find (f, H5AC_SNODE, new_node, NULL))) { + if (NULL==(snrt=H5AC_find (f, H5AC_SNODE, new_node, NULL))) { HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL); } - HDmemcpy (sn->entry, ent+H5G_NODE_K(f), - H5G_NODE_K(f)*sizeof(H5G_entry_t)); - sn->nsyms = H5G_NODE_K(f); + HDmemcpy (snrt->entry, sn->entry + H5G_NODE_K(f), + H5G_NODE_K(f) * sizeof(H5G_entry_t)); + snrt->nsyms = H5G_NODE_K(f); + snrt->dirty += 1; + + /* The left node */ + HDmemset (sn->entry + H5G_NODE_K(f), 0, + H5G_NODE_K(f) * sizeof(H5G_entry_t)); + sn->nsyms = H5G_NODE_K (f); sn->dirty += 1; - if (idx>H5G_NODE_K(f)) { - idx -= H5G_NODE_K(f); - HDmemmove (sn->entry+idx+1, sn->entry+idx, - (H5G_NODE_K(f)-idx) * sizeof (H5G_entry_t)); + /* Insert the new entry */ + if (idx<=H5G_NODE_K(f)) { + HDmemmove (sn->entry + idx + 1, + sn->entry + idx, + (H5G_NODE_K(f)-idx) * sizeof(H5G_entry_t)); sn->entry[idx] = udata->entry; sn->entry[idx].name_off = offset; sn->nsyms += 1; + } else { + idx -= H5G_NODE_K (f); + HDmemmove (snrt->entry + idx + 1, + snrt->entry + idx, + (H5G_NODE_K(f)-idx) * sizeof (H5G_entry_t)); + snrt->entry[idx] = udata->entry; + snrt->entry[idx].name_off = offset; + snrt->nsyms += 1; - if (idx+1==sn->nsyms) { + if (idx+1 == sn->nsyms) { rt_key->offset = offset; *rt_key_changed = TRUE; } } - + + /* The middle key */ + md_key->offset = sn->entry[sn->nsyms-1].name_off; + } else { /* * Add the new symbol to the node. */ - if (NULL==(sn=H5AC_find (f, H5AC_SNODE, addr, NULL))) { - HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL); - } sn->dirty += 1; HDmemmove (sn->entry+idx+1, sn->entry+idx, (sn->nsyms-idx) * sizeof (H5G_entry_t)); @@ -740,11 +732,15 @@ H5G_node_insert (hdf5_file_t *f, haddr_t addr, intn *anchor, *rt_key_changed = TRUE; } } - HRETURN (new_node); -done: /*error*/ - if (malloced) ent = H5MM_xfree (ent); - FUNC_LEAVE (FAIL); + ret_value = new_node; /*successful return */ + +done: + if (sn && H5AC_unprotect (f, H5AC_SNODE, addr, sn)<0) { + HRETURN_ERROR (H5E_SYM, H5E_PROTECT, FAIL); + } + + FUNC_LEAVE (ret_value); } @@ -771,9 +767,9 @@ 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 = NULL; - off_t *offsets = NULL; - intn nsyms, i; + intn i; const char *s; + herr_t ret_value = FAIL; FUNC_ENTER (H5G_node_list, NULL, FAIL); @@ -784,10 +780,9 @@ H5G_node_list (hdf5_file_t *f, haddr_t addr, void *_udata) assert (addr>=0); assert (udata); - if (NULL==(sn=H5AC_find (f, H5AC_SNODE, addr, NULL))) { - HRETURN_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL); + if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, NULL))) { + HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL); } - nsyms = sn->nsyms; /* * If we've already overflowed the user-supplied buffer, then just @@ -795,49 +790,38 @@ H5G_node_list (hdf5_file_t *f, haddr_t addr, void *_udata) * anything else. */ if (udata->nsyms >= udata->maxentries) { - udata->nsyms += nsyms; - HRETURN (SUCCEED); + udata->nsyms += sn->nsyms; + HGOTO_DONE (SUCCEED); } /* - * Save the name offsets because looking up the name may cause the - * symbol table node to be preempted from the cache. + * Save the symbol table entries. */ if (udata->entry) { - for (i=0; insyms+imaxentries; i++) { + for (i=0; insyms && udata->nsyms+imaxentries; i++) { udata->entry[udata->nsyms+i] = sn->entry[i]; } - } else if (udata->name) { - offsets = H5MM_xmalloc (nsyms * sizeof(off_t)); - for (i=0; insyms+imaxentries; i++) { - offsets[i] = sn->entry[i].name_off; - } } - - /* - * Now strdup() the names. - */ - 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++) { - if (NULL==(s=H5H_peek (f, udata->heap, offsets[i]))) { - HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); + if (udata->name) { + for (i=0; insyms && udata->nsyms+imaxentries; i++) { + if (NULL==(s=H5H_peek (f, udata->heap_addr, sn->entry[i].name_off))) { + HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); } udata->name[udata->nsyms+i] = H5MM_xstrdup (s); } - offsets = H5MM_xfree (offsets); } /* * Update the number of symbols. */ - udata->nsyms += nsyms; - FUNC_LEAVE (SUCCEED); + udata->nsyms += sn->nsyms; + ret_value = SUCCEED; + +done: + if (sn && H5AC_unprotect (f, H5AC_SNODE, addr, sn)<0) { + HRETURN_ERROR (H5E_CACHE, H5E_PROTECT, FAIL); + } + FUNC_LEAVE (ret_value); } diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h index 744a525..d9457b1 100644 --- a/src/H5Gprivate.h +++ b/src/H5Gprivate.h @@ -72,8 +72,8 @@ typedef struct H5G_entry_t { } sdata; struct { - haddr_t btree; /*file address of symbol table B-tree */ - haddr_t heap; /*file address of stab name heap */ + haddr_t btree_addr; /*file address of symbol table B-tree */ + haddr_t heap_addr; /*file address of stab name heap */ } stab; } cache; /*cached data from object header */ } H5G_entry_t; @@ -113,7 +113,7 @@ typedef struct H5G_node_ud1_t { /* downward */ H5G_oper_t operation; /*what operation to perform */ const char *name; /*points to temporary memory */ - haddr_t heap; /*symbol table heap address */ + haddr_t heap_addr; /*symbol table heap address */ /* upward for H5G_OPER_FIND, downward for H5G_OPER_MODIFY */ H5G_entry_t entry; /*symbol table entry */ @@ -126,7 +126,7 @@ typedef struct H5G_node_list_t { H5G_entry_t *entry; /*array of entries, alloc'd by caller */ char **name; /*array of string ptrs, allocd by caller*/ intn maxentries; /*size of the ADDR and NAME arrays */ - haddr_t heap; /*heap address */ + haddr_t heap_addr; /*heap address */ /* upward */ intn nsyms; /*num. symbols processed */ diff --git a/src/H5H.c b/src/H5H.c index 3a09c50..dc0a10c 100644 --- a/src/H5H.c +++ b/src/H5H.c @@ -292,7 +292,7 @@ H5H_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5H_t *heap) */ HDmemcpy (p, H5H_MAGIC, H5H_SIZEOF_MAGIC); p += H5H_SIZEOF_MAGIC; H5F_encode_length (f, p, heap->mem_alloc); - H5F_encode_offset (f, p, fl?fl->offset:-1); + H5F_encode_offset (f, p, fl?fl->offset:H5H_FREE_NULL); H5F_encode_offset (f, p, heap->addr); /* diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h index 0f774d3..8aea4c7 100644 --- a/src/H5Oprivate.h +++ b/src/H5Oprivate.h @@ -159,8 +159,8 @@ typedef struct H5O_cont_t { 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 */ + haddr_t btree_addr; /*address of B-tree */ + haddr_t heap_addr; /*address of name heap */ } H5O_stab_t; diff --git a/src/H5Ostab.c b/src/H5Ostab.c index 760fcb4..1710fe3 100644 --- a/src/H5Ostab.c +++ b/src/H5Ostab.c @@ -84,8 +84,8 @@ H5O_stab_decode (hdf5_file_t *f, size_t raw_size, const uint8 *p) /* decode */ stab = H5MM_xcalloc (1, sizeof(H5O_stab_t)); - H5F_decode_offset (f, p, stab->btree); - H5F_decode_offset (f, p, stab->heap); + H5F_decode_offset (f, p, stab->btree_addr); + H5F_decode_offset (f, p, stab->heap_addr); FUNC_LEAVE (stab); } @@ -122,8 +122,8 @@ H5O_stab_encode (hdf5_file_t *f, size_t raw_size, uint8 *p, const void *_mesg) assert (stab); /* encode */ - H5F_encode_offset (f, p, stab->btree); - H5F_encode_offset (f, p, stab->heap); + H5F_encode_offset (f, p, stab->btree_addr); + H5F_encode_offset (f, p, stab->heap_addr); FUNC_LEAVE (SUCCEED); } @@ -160,8 +160,8 @@ H5O_stab_fast (const H5G_entry_t *ent, void *_mesg) 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; + stab->btree_addr = ent->cache.stab.btree_addr; + stab->heap_addr = ent->cache.stab.heap_addr; } else { stab = NULL; } @@ -209,17 +209,17 @@ H5O_stab_cache (H5G_entry_t *ent, const void *_mesg) if (H5G_CACHED_STAB != ent->type) { modified = TRUE; ent->type = H5G_CACHED_STAB; - ent->cache.stab.btree = stab->btree; - ent->cache.stab.heap = stab->heap; + ent->cache.stab.btree_addr = stab->btree_addr; + ent->cache.stab.heap_addr = stab->heap_addr; } else { - if (ent->cache.stab.btree != stab->btree) { + if (ent->cache.stab.btree_addr != stab->btree_addr) { modified = TRUE; - ent->cache.stab.btree = stab->btree; + ent->cache.stab.btree_addr = stab->btree_addr; } - if (ent->cache.stab.heap != stab->heap) { + if (ent->cache.stab.heap_addr != stab->heap_addr) { modified = TRUE; - ent->cache.stab.heap = stab->heap; + ent->cache.stab.heap_addr = stab->heap_addr; } } @@ -325,10 +325,10 @@ H5O_stab_debug (hdf5_file_t *f, const void *_mesg, FILE *stream, fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth, "B-tree address:", - (unsigned long)(stab->btree)); + (unsigned long)(stab->btree_addr)); fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth, "Name heap address:", - (unsigned long)(stab->heap)); + (unsigned long)(stab->heap_addr)); FUNC_LEAVE (SUCCEED); } diff --git a/src/H5detect.c b/src/H5detect.c new file mode 100644 index 0000000..83beb4d --- /dev/null +++ b/src/H5detect.c @@ -0,0 +1,941 @@ +static char *FileHeader = "\n\ +/*-------------------------------------------------------------------------\n\ + * Copyright (C) 1997 National Center for Supercomputing Applications. \n\ + * All rights reserved. \n\ + * \n\ + *-------------------------------------------------------------------------"; +/* + * + * Created: H5detect.c + * 10 Aug 1997 + * Robb Matzke + * + * Purpose: This code was borrowed heavily from the `detect.c' + * program in the AIO distribution from Lawrence + * Livermore National Laboratory. + * + * Detects machine byte order and floating point + * format and generates a C source file (native.c) + * to describe those paramters. + * + * Assumptions: We have an ANSI compiler. We're on a Unix like + * system or configure has detected those Unix + * features which aren't available. We're not + * running on a Vax or other machine with mixed + * endianess. + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAXDETECT 16 + +#ifndef MIN +# define MIN(X,Y) ((X)<(Y)?(X):(Y)) +#endif + +/* + * This structure holds information about a type that + * was detected. + */ +typedef struct detected_t { + char *typename; + char *varname; + int size; + int padding; + int perm[32]; + int sign; + int mpos, msize, imp; + int epos, esize, bias; +} detected_t; + +static void print_results (int nd, detected_t *d); +static void iprint (detected_t*, int); +static void print_known_formats (detected_t*, int); +static int byte_cmp (int, void*, void*); +static int bit_cmp (int, int*, void*, void*); +static void fix_order (int, int, int, int*, char**); +static void fix_padding (detected_t*); +static int imp_bit (int, int*, void*, void*); +static int find_bias (int, int, int, int*, void*); +static void print_header (void); + + +/*------------------------------------------------------------------------- + * For convenience, we place here in a table descriptions of all + * architectures we've seen so far. That way we can print a description + * of the system on which the program is run. We place the system name + * in the VARNAME field. + *------------------------------------------------------------------------- + */ +#define LE {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, \ + 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31} +#define LE_1 LE +#define LE_2 LE +#define LE_4 LE +#define LE_8 LE + +#define BE_1 {0} +#define BE_2 {1,0} +#define BE_4 {3,2,1,0} +#define BE_8 {7,6,5,4,3,2,1,0} + +#define INTEGER 0,0,0,0,0,0,0 + +static detected_t Known[] = { + /* Single-byte quantities */ + {"char", "Byte addressable", + 1, 0, LE_1, INTEGER}, + + /* Little-endian fixed-point */ + {"int16", "Little-endian", + 2, 0, LE_2, INTEGER}, + {"int32", "Little-endian", + 4, 0, LE_4, INTEGER}, + + /* Big-endian fixed-point */ + {"int16", "Big-endian", + 2, 0, BE_2, INTEGER}, + {"int32", "Big-endian", + 4, 0, BE_4, INTEGER}, + + /* Little-endian IEEE floating-point */ + {"float32", "Little-endian IEEE", + 4, 0, LE_4, 31, 0, 23, 1, 23, 8, 127}, + {"float64", "Little-endian IEEE", + 8, 0, LE_8, 63, 0, 52, 1, 52, 11, 1023}, + + /* Big-endian IEEE floating-point */ + {"float32", "Big-endian IEEE", + 4, 0, BE_4, 31, 0, 23, 1, 23, 8, 127}, + {"float64", "Big-endian IEEE", + 8, 0, BE_8, 63, 0, 52, 1, 52, 11, 1023}, +}; + + +/*------------------------------------------------------------------------- + * Function: DETECT_I + * + * Purpose: This macro takes a type like `int' and a base name like + * `nati' and detects the byte order. The VAR is used to + * construct the names of the C variables defined. + * + * Return: void + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jun 12 1996 + * + * Modifications: + * + * Robb Matzke, 4 Nov 1996 + * The INFO.perm now contains `-1' for bytes that aren't used and + * are always zero. This happens on the Cray for `short' where + * sizeof(short) is 8, but only the low-order 4 bytes are ever used. + * + * Robb Matzke, 4 Nov 1996 + * Added a `padding' field to indicate how many zero bytes appear to + * the left (N) or right (-N) of the value. + * + * Robb Matzke, 5 Nov 1996 + * Removed HFILE and CFILE arguments. + * + *------------------------------------------------------------------------- + */ +#define DETECT_I(TYPE,TYPE_S,VAR,VAR_S,INFO) { \ + TYPE _v; \ + int _i, _j; \ + unsigned char *_x; \ + memset (&INFO, 0, sizeof(INFO)); \ + INFO.typename = TYPE_S; \ + INFO.varname = VAR_S; \ + INFO.size = sizeof(TYPE); \ + for (_i=sizeof(TYPE),_v=0; _i>0; --_i) _v = (_v<<8) + _i; \ + for (_i=0,_x=(unsigned char *)&_v; _i=0) { \ + if (0==_i || INFO.perm[_i-1]!=_j) { \ + INFO.perm[_i] = _j; \ + _last = _i; \ + if (_first<0) _first = _i; \ + } \ + } \ + } \ + fix_order (sizeof(TYPE), _first, _last, INFO.perm, &_mesg); \ + \ + /* Implicit mantissa bit */ \ + _v1 = 0.5; \ + _v2 = 1.0; \ + INFO.imp = imp_bit (sizeof(TYPE), INFO.perm, &_v1, &_v2); \ + \ + /* Sign bit */ \ + _v1 = 1.0; \ + _v2 = -1.0; \ + INFO.sign = bit_cmp (sizeof(TYPE), INFO.perm, &_v1, &_v2); \ + \ + /* Mantissa */ \ + INFO.mpos = 0; \ + \ + _v1 = 1.0; \ + _v2 = 1.5; \ + INFO.msize = bit_cmp (sizeof(TYPE), INFO.perm, &_v1, &_v2); \ + INFO.msize += 1 + (INFO.imp?0:1) - INFO.mpos; \ + \ + /* Exponent */ \ + INFO.epos = INFO.mpos + INFO.msize; \ + \ + INFO.esize = INFO.sign - INFO.epos; \ + \ + _v1 = 1.0; \ + INFO.bias = find_bias (INFO.epos, INFO.esize, INFO.imp, INFO.perm, &_v1); \ +} + + +/*------------------------------------------------------------------------- + * Function: print_results + * + * Purpose: Prints information about the detected data types. + * + * Return: void + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jun 14, 1996 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +print_results (int nd, detected_t *d) { + + int i, j; + + printf ("#define DEFAULT_INTEGER_FIELDS {FALSE,0,0,0,0,0}\n\n"); + printf ("#define FALSE 0\n"); + printf ("#define TRUE 1\n"); + + printf ("\ntypedef struct {\n"); + printf (" uintn class, bytes, padding, size, align;\n"); + printf (" uintn order[32], sign, imp, mloc, msize, eloc, esize;\n"); + printf (" uint32 bias;\n"); + printf ("};\n\n"); + + for (i=0; isize-1; i>=0; --i) { + printf ("%4d", d->perm[i]); + if (i>0) fputs (" ", stdout); + if (0==i%4) putchar (' '); + } + putchar ('\n'); + + /* + * Print the bit fields + */ + printf ("%*s * ", indent, ""); + for (i=d->size-1,k=d->size*8-1; i>=0; --i) { + for (j=7; j>=0; --j) { + if (k==d->sign && d->msize) { + putchar ('S'); + } else if (k>=d->epos && kepos+d->esize) { + putchar ('E'); + } else if (k>=d->mpos && kmpos+d->msize) { + putchar ('M'); + } else { + putchar ('I'); + } + --k; + } + if (i>0) { + putchar (' '); + if (0==i%4) putchar (' '); + } + } + putchar ('\n'); + + /* + * Is there an implicit bit in the mantissa. + */ + if (d->msize) { + printf ("%*s * Implicit bit? %s\n", indent, "", d->imp?"yes":"no"); + } +} + + +/*------------------------------------------------------------------------- + * Function: print_known_formats + * + * Purpose: Prints archetecture names for the specified format + * description, if any. + * + * Return: void + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jun 13, 1996 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +print_known_formats (detected_t *d, int indent) { + + int i, j, diff; + int n=sizeof(Known)/sizeof(Known[0]); + + for (i=0; isize != Known[i].size) continue; + for (j=diff=0; !diff && jsize; j++) { + if (d->perm[j] != Known[i].perm[j]) diff = 1; + } + if (diff) continue; + + /* if (d->sign != Known[i].sign) continue;*/ + if (d->mpos != Known[i].mpos) continue; + if (d->msize != Known[i].msize) continue; + if (d->imp != Known[i].imp) continue; + if (d->epos != Known[i].epos) continue; + if (d->esize != Known[i].esize) continue; + if (d->bias != Known[i].bias) continue; + + printf ("%*s * %s %s\n", + indent, "", Known[i].varname, Known[i].typename); + } +} + + +/*------------------------------------------------------------------------- + * Function: byte_cmp + * + * Purpose: Compares two chunks of memory A and B and returns the + * byte index into those arrays of the first byte that + * differs between A and B. + * + * Return: Success: Index of differing byte. + * + * Failure: -1 if all bytes are the same. + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jun 12, 1996 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +byte_cmp (int n, void *_a, void *_b) { + + register int i; + unsigned char *a = (unsigned char *)_a; + unsigned char *b = (unsigned char *)_b; + + for (i=0; i>=1,bb>>=1) { + if ((aa & 1) != (bb & 1)) return i*8 + j; + } + assert ("INTERNAL ERROR" && 0); + } + } + return -1; +} + + +/*------------------------------------------------------------------------- + * Function: fix_order + * + * Purpose: Given an array PERM with elements FIRST through LAST + * initialized with zero origin byte numbers, this function + * creates a permutation vector that maps the actual order + * of a floating point number to little-endian. + * + * This function assumes that the mantissa byte ordering + * implies the total ordering. + * + * Return: void + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jun 13, 1996 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +fix_order (int n, int first, int last, int *perm, char **mesg) { + + int i; + + if (first+1perm[last-1] && perm[last-1]>perm[last-2]) { + /* + * Big endian. + */ + if (mesg) *mesg = "Big-endian"; + for (i=0; iperm[0]<0) { + /* + * Left padding. + */ + for (n=0; nsize && d->perm[n]<0; n++) /*void*/; + for (i=n; isize; i++) d->perm[i-n] = d->perm[i]; + for (i=d->size-n; isize; i++) d->perm[i] = 0; + d->padding = n; + d->size -= n; + + } else if (d->perm[d->size-1]<0) { + /* + * Right padding. + */ + for (n=0; nsize && d->perm[d->size-(n+1)]; n++) /*void*/; + for (i=d->size-n; isize; i++) d->perm[i] = 0; + d->padding = -n; + d->size -= n; + + } else { + /* + * No padding. + */ + d->padding = 0; + } +} + + +/*------------------------------------------------------------------------- + * Function: imp_bit + * + * Purpose: Looks for an implicit bit in the mantissa. The value + * of _A should be 1.0 and the value of _B should be 0.5. + * Some floating-point formats discard the most significant + * bit of the mantissa after normalizing since it will always + * be a one (except for 0.0). If this is true for the native + * floating point values stored in _A and _B then the function + * returns non-zero. + * + * This function assumes that the exponent occupies higher + * order bits than the mantissa and that the most significant + * bit of the mantissa is next to the least signficant bit + * of the exponent. + * + * + * Return: Success: Non-zero if the most significant bit + * of the mantissa is discarded (ie, the + * mantissa has an implicit `one' as the + * most significant bit). Otherwise, + * returns zero. + * + * Failure: exit(1) + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jun 13, 1996 + * + * Modifications: + * + * Robb Matzke, 6 Nov 1996 + * Fixed a bug that occurs with non-implicit architectures. + * + *------------------------------------------------------------------------- + */ +static int +imp_bit (int n, int *perm, void *_a, void *_b) { + + unsigned char *a = (unsigned char *)_a; + unsigned char *b = (unsigned char *)_b; + int changed, major, minor; + int msmb; /*most significant mantissa bit*/ + + /* + * Look for the least significant bit that has changed between + * A and B. This is the least significant bit of the exponent. + */ + changed = bit_cmp (n, perm, a, b); + assert (changed>=0); + + /* + * The bit to the right (less significant) of the changed bit should + * be the most significant bit of the mantissa. If it is non-zero + * then the format does not remove the leading `1' of the mantissa. + */ + msmb = changed-1; + major = msmb / 8; + minor = msmb % 8; + + return (a[perm[major]] >> minor) & 0x01 ? 0 : 1; +} + + +/*------------------------------------------------------------------------- + * Function: find_bias + * + * Purpose: Determines the bias of the exponent. This function should + * be called with _A having a value of `1'. + * + * Return: Success: The exponent bias. + * + * Failure: + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jun 13, 1996 + * + * Modifications: + * + * Robb Matzke, 6 Nov 1996 + * Fixed a bug with non-implicit architectures returning the + * wrong exponent bias. + * + *------------------------------------------------------------------------- + */ +static int +find_bias (int epos, int esize, int imp, int *perm, void *_a) { + + + unsigned char *a = (unsigned char *)_a; + unsigned char mask; + unsigned long b, shift=0, nbits, bias=0; + + while (esize>0) { + nbits = MIN (esize, (8 - epos % 8)); + mask = (1<> (epos % 8)) & mask; + bias |= b << shift; + + shift += nbits; + esize -= nbits; + epos += nbits; + } + + return bias - (imp?0:1); +} + + +/*------------------------------------------------------------------------- + * Function: print_header + * + * Purpose: Prints the C file header for the generated file. + * + * Return: void + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Mar 12 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +print_header (void) { + + time_t now = time (NULL); + struct tm *tm = localtime (&now); + struct passwd *pwd = getpwuid (getuid()); + char real_name[30], *comma; + char host_name[256]; + int i, n; + char *s; + static char *month_name[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + static char *purpose = "\ +This machine-generated source code contains\n\ +information about the various integer and\n\ +floating point numeric formats found on this\n\ +architecture. The parameters below should be\n\ +checked carefully and errors reported to the\n\ +HDF5 maintainer.\n\ +\n\ +Each of the numeric formats listed below are\n\ +printed from most significant bit to least\n\ +significant bit even though the actual bytes\n\ +might be stored in a different order in\n\ +memory. The integers above each binary byte\n\ +indicate the relative order of the bytes in\n\ +memory; little-endian machines have\n\ +decreasing numbers while big-endian machines\n\ +have increasing numbers.\n\ +\n\ +The fields of the numbers are printed as\n\ +letters with `S' for the mantissa sign bit,\n\ +`M' for the mantissa magnitude, and `E' for\n\ +the exponent. The exponent has an associated\n\ +bias which can be subtracted to find the\n\ +true exponent. The radix point is assumed\n\ +to be before the first `M' bit. Any bit\n\ +not falling into one of these categories\n\ +is printed as a question mark, as are all\n\ +bits of integer quantities.\n\ +\n\ +If the most significant bit of the normalized\n\ +mantissa (always a `1' except for `0.0') is\n\ +not stored then an `implicit=yes' appears\n\ +under the field description. In thie case,\n\ +the radix point is still assumed to be\n\ +before the first `M' but after the implicit\n\ +bit."; + + /* + * The real name is the first item from the passwd gecos field. + */ + if (pwd) { + if ((comma=strchr(pwd->pw_gecos,','))) { + n = MIN (sizeof(real_name)-1, comma - pwd->pw_gecos); + strncpy (real_name, pwd->pw_gecos, n); + real_name[n] = '\0'; + } else { + strncpy (real_name, pwd->pw_gecos, sizeof(real_name)); + real_name[sizeof(real_name)-1] = '\0'; + } + } else { + real_name[0] = '\0'; + } + + /* + * The FQDM of this host or the empty string. + */ + if (gethostname(host_name, sizeof(host_name))<0) host_name[0] = '\0'; + + + /* + * The file header: warning, copyright notice, build information. + */ + printf ("/*\n * DO NOT EDIT THIS FILE--IT IS MACHINE GENERATED!\n */\n\n"); + puts (FileHeader); /*the copyright notice--see top of this file*/ + + printf (" *\n * Created:\t\t%s %2d, %4d\n", + month_name[tm->tm_mon], tm->tm_mday, 1900+tm->tm_year); + if (pwd || real_name[0] || host_name[0]) { + printf (" *\t\t\t"); + if (real_name[0]) printf ("%s <", real_name); + if (pwd) fputs (pwd->pw_name, stdout); + if (host_name[0]) printf ("@%s", host_name); + if (real_name[0]) printf (">"); + putchar ('\n'); + } + + printf (" *\n * Purpose:\t\t"); + for (s=purpose; *s; s++) { + putchar (*s); + if ('\n'==*s) printf (" *\t\t\t"); + } + + printf (" *\n * Modifications:\n *\n"); + printf (" *\tDO NOT MAKE MODIFICATIONS TO THIS FILE!\n"); + printf (" *\tIt was generated by code in `H5detect.c'.\n"); + + printf (" *\n *"); + for (i=0; i<73; i++) putchar ('-'); + printf ("\n */\n\n"); + +} + + +/*------------------------------------------------------------------------- + * Function: main + * + * Purpose: Main entry point. + * + * Return: Success: exit(0) + * + * Failure: exit(1) + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jun 12, 1996 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +int +main (int argc, char *argv[]) { + + detected_t d[MAXDETECT]; + int nd=0; + + print_header(); + + DETECT_I (signed char, "signed char", natsc, "natsc", d[nd]); nd++; + DETECT_I (unsigned char, "unsigned char", natuc, "natuc", d[nd]); nd++; + DETECT_I (short, "short", nats, "natss", d[nd]); nd++; + DETECT_I (unsigned short, "unsigned short", nats, "natus", d[nd]); nd++; + DETECT_I (int, "int", nati, "natsi", d[nd]); nd++; + DETECT_I (unsigned int, "unsigned int", nati, "natui", d[nd]); nd++; + DETECT_I (long, "long", natl, "natsl", d[nd]); nd++; + DETECT_I (unsigned long, "unsigned long", natl, "natul", d[nd]); nd++; + DETECT_F (float, "float", natf, "natf", d[nd]); nd++; + DETECT_F (double, "double", natd, "natd", d[nd]); nd++; + + print_results (nd, d); + exit (0); +} -- cgit v0.12