summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobb Matzke <matzke@llnl.gov>1997-09-10 19:57:56 (GMT)
committerRobb Matzke <matzke@llnl.gov>1997-09-10 19:57:56 (GMT)
commit7ead4a900b4b7980688708ee6794def0793f123c (patch)
tree0c8da24c4ccccd85e105c8da4e6595cc352c720f
parent0a379e1cc1a0cfcc51d3bb1a3e90cbc3310aa820 (diff)
downloadhdf5-7ead4a900b4b7980688708ee6794def0793f123c.zip
hdf5-7ead4a900b4b7980688708ee6794def0793f123c.tar.gz
hdf5-7ead4a900b4b7980688708ee6794def0793f123c.tar.bz2
[svn-r71] Lost my changelog, but basically some new caching functions.
-rw-r--r--src/H5AC.c405
-rw-r--r--src/H5ACprivate.h35
-rw-r--r--src/H5B.c573
-rw-r--r--src/H5Bprivate.h6
-rw-r--r--src/H5E.c1
-rw-r--r--src/H5Epublic.h1
-rw-r--r--src/H5F.c8
-rw-r--r--src/H5Fprivate.h2
-rw-r--r--src/H5G.c36
-rw-r--r--src/H5Gnode.c194
-rw-r--r--src/H5Gprivate.h8
-rw-r--r--src/H5H.c2
-rw-r--r--src/H5Oprivate.h4
-rw-r--r--src/H5Ostab.c28
-rw-r--r--src/H5detect.c941
15 files changed, 1723 insertions, 521 deletions
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; i<f->cache->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; i<slot->nprots; 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; i<H5AC_NSLOTS; i++) map[i] = i;
+ map = H5MM_xmalloc (f->cache->nslots * sizeof(intn));
+ for (i=0; i<f->cache->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; i<H5AC_NSLOTS; i++) {
+ for (i=0; i<f->cache->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; i<slot->nprots; 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; i<f->cache->slot[old_idx].nprots; i++) {
+ assert (old_addr!=f->cache->slot[old_idx].prot[i].addr);
+ }
+ for (i=0; i<f->cache->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; i<slot->nprots; 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; i<slot->nprots && !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 (lt<rt && cmp) {
idx = (lt + rt) / 2;
- if (NULL==(bt=H5AC_find (f, H5AC_BT, addr, type))) {
- HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL);
- }
/* the left key */
if (!bt->key[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 && idx<bt->nchildren);
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 (i<H5B_K(f,type)) {
- bt->child[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 (i<H5B_K(f,type)) {
- old->child[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 (lt<rt && cmp) {
idx = (lt + rt) / 2;
- if (NULL==(bt=H5AC_find (f, H5AC_BT, addr, type))) {
- HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL);
- }
/* left key */
if (!bt->key[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+1<bt->nchildren) *rt_key_changed = FALSE;
+ bt->dirty = TRUE;
+ bt->key[idx+1].dirty = TRUE;
+ if (idx+1<bt->nchildren) {
+ *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; i<nchildren; i++) {
- if ((list)(f, child[i], udata)<0) {
- H5MM_xfree (child);
- HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL);
+ for (i=0; i<bt->nchildren; 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; i<maxentries; i++) H5MM_xfree (names[i]);
}
@@ -1215,8 +1215,8 @@ H5G_decode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent)
break;
case H5G_CACHED_STAB:
- UINT32DECODE (*pp, ent->cache.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 (lt<rt && cmp) {
idx = (lt + rt) / 2;
- 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);
+ 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 (lt<rt) {
idx = (lt + rt) / 2;
- if (NULL==(s=H5H_peek (f, udata->heap, 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; i<nsyms && udata->nsyms+i<udata->maxentries; i++) {
+ for (i=0; i<sn->nsyms && udata->nsyms+i<udata->maxentries; i++) {
udata->entry[udata->nsyms+i] = sn->entry[i];
}
- } else if (udata->name) {
- offsets = H5MM_xmalloc (nsyms * sizeof(off_t));
- for (i=0; i<nsyms && udata->nsyms+i<udata->maxentries; i++) {
- offsets[i] = sn->entry[i].name_off;
- }
}
-
- /*
- * Now strdup() the names.
- */
- if (udata->name && udata->entry) {
- for (i=0; i<nsyms && udata->nsyms+i<udata->maxentries; 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; i<nsyms && udata->nsyms+i<udata->maxentries; i++) {
- if (NULL==(s=H5H_peek (f, udata->heap, offsets[i]))) {
- HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL);
+ if (udata->name) {
+ for (i=0; i<sn->nsyms && udata->nsyms+i<udata->maxentries; i++) {
+ if (NULL==(s=H5H_peek (f, udata->heap_addr, sn->entry[i].name_off))) {
+ 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 <assert.h>
+#include <math.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+
+#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<sizeof(TYPE); _i++) { \
+ _j = (*_x++)-1; \
+ assert (_j<(signed)sizeof(TYPE)); \
+ INFO.perm[_i] = _j; \
+ } \
+ fix_padding (&(INFO)); \
+ if (!strncmp(TYPE_S, "unsigned", 8)) INFO.sign = 0; \
+ else INFO.sign = 1; \
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: DETECT_F
+ *
+ * Purpose: This macro takes a floating point type like `double' and
+ * a base name like `natd' and detects byte order, mantissa
+ * location, exponent location, sign bit location, presence or
+ * absence of implicit mantissa bit, and exponent bias and
+ * initializes a detected_t structure with those properties.
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Jun 12 1996
+ *
+ * Modifications:
+ *
+ * Robb Matzke, 14 Aug 1996
+ * The byte order detection has been changed because on the Cray
+ * the last pass causes a rounding to occur that causes the least
+ * significant mantissa byte to change unexpectedly.
+ *
+ * Robb Matzke, 5 Nov 1996
+ * Removed HFILE and CFILE arguments.
+ *-------------------------------------------------------------------------
+ */
+#define DETECT_F(TYPE,TYPE_S,VAR,VAR_S,INFO) { \
+ TYPE _v1, _v2, _v3; \
+ int _i, _j, _first=(-1), _last=(-1); \
+ char *_mesg; \
+ \
+ memset (&INFO, 0, sizeof(INFO)); \
+ INFO.typename = TYPE_S; \
+ INFO.varname = VAR_S; \
+ INFO.size = sizeof(TYPE); \
+ INFO.padding = 0; \
+ \
+ /* Byte Order */ \
+ for (_i=0,_v1=0.0,_v2=1.0; _i<sizeof(TYPE); _i++) { \
+ _v3 = _v1; _v1 += _v2; _v2 /= 256.0; \
+ if ((_j=byte_cmp(sizeof(TYPE), &_v3, &_v1))>=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; i<nd; i++) {
+ printf ("\n/*\n");
+ iprint (d+i, 0);
+ print_known_formats (d+i, 0);
+ printf (" */\n");
+ printf ("const H5T_desc_t H5T_%s[1] = {{\n",
+ d[i].varname);
+ printf (" /* Class */ %s,\n",
+ d[i].msize?"H5T_FLOAT":"H5T_FIXED");
+ printf (" /* Number of bytes */ %d,\n", d[i].size);
+ printf (" /* Zero padding */ %d,\n", d[i].padding);
+ printf (" /* sizeof() */ %d,\n",
+ d[i].size + abs (d[i].padding));
+
+ /* alignment isn't detected yet */
+ printf (" /* Alignment */ %d,\n",
+ d[i].size + abs (d[i].padding));
+
+ printf (" /* Byte order */ {");
+ for (j=0; j<32; j++) {
+ if (j && 0==j%8) printf ("\n ");
+ printf ("%3d%s", j<d[i].size?d[i].perm[j]:-1, j+1<32?",":"");
+ }
+ printf ("},\n");
+
+ if (d[i].msize) {
+ printf (" /* Float sign loc */ %d,\n", d[i].sign);
+ printf (" /* Float implicit bit */ %s,\n",
+ d[i].imp?"TRUE":"FALSE");
+ printf (" /* Float mantissa loc */ %d,\n", d[i].mpos);
+ printf (" /* Float matnissa size */ %d,\n", d[i].msize);
+ printf (" /* Float exponent loc */ %d,\n", d[i].epos);
+ printf (" /* Float exponent size */ %d,\n", d[i].esize);
+ printf (" /* Float exponent bias */ 0x%x,\n", d[i].bias);
+ } else {
+ printf (" /* Signed? */ %s,\n",
+ d[i].sign?"TRUE":"FALSE");
+ printf (" DEFAULT_INTEGER_FIELDS,\n");
+ }
+ printf ("}};\n\n");
+ }
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: tprint
+ *
+ * Purpose: Prints a binary number beginning with the most
+ * significant bit and continuing to the least
+ * significant bit.
+ *
+ * If PERM is the null pointer then it isn't used and
+ * _A is assumed to be in big endian order.
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Jun 13, 1996
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+#if 0
+static void
+tprint (int nbytes, int *perm, void *_a) {
+
+ int i, j;
+ unsigned char *a = (unsigned char *)_a;
+ unsigned char b;
+
+ for (i=0; i<nbytes; i++) {
+ if (perm) {
+ assert (perm[i]<nbytes);
+ b = a[perm[i]];
+ } else {
+ b = a[i];
+ }
+ for (j=0; j<8; j++,b<<=1) putchar (b & 0x80 ? '1' : '0');
+ if (i+1<nbytes) {
+ putchar (' ');
+ if (0==(i+1)%4) putchar (' ');
+ }
+ }
+ putchar ('\n');
+}
+#endif
+
+
+/*-------------------------------------------------------------------------
+ * Function: iprint
+ *
+ * Purpose: Prints information about the fields of a floating point
+ * format.
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Jun 13, 1996
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void
+iprint (detected_t *d, int indent) {
+
+ int i, j, k;
+
+ /*
+ * Print the byte ordering above the bit fields.
+ */
+ printf ("%*s * ", indent, "");
+ for (i=d->size-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 && k<d->epos+d->esize) {
+ putchar ('E');
+ } else if (k>=d->mpos && k<d->mpos+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; i<n; i++) {
+ if (d->size != Known[i].size) continue;
+ for (j=diff=0; !diff && j<d->size; 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<n; i++) if (a[i]!=b[i]) return i;
+ return -1;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: bit_cmp
+ *
+ * Purpose: Compares two bit vectors and returns the index for the
+ * first bit that differs between the two vectors. The
+ * size of the vector is NBYTES. PERM is a mapping from
+ * actual order to little endian.
+ *
+ * Return: Success: Index of first differing bit.
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Jun 13, 1996
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+bit_cmp (int nbytes, int *perm, void *_a, void *_b) {
+
+ int i, j;
+ unsigned char *a = (unsigned char *)_a;
+ unsigned char *b = (unsigned char *)_b;
+ unsigned char aa, bb;
+
+ for (i=0; i<nbytes; i++) {
+ assert (perm[i]<nbytes);
+ if ((aa=a[perm[i]]) != (bb=b[perm[i]])) {
+ for (j=0; j<8; j++,aa>>=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+1<last) {
+ /*
+ * We have at least three points to consider.
+ */
+ if (perm[last]<perm[last-1] && perm[last-1]<perm[last-2]) {
+ /*
+ * Little endian.
+ */
+ if (mesg) *mesg = "Little-endian";
+ for (i=0; i<n; i++) perm[i] = i;
+
+ } else if (perm[last]>perm[last-1] && perm[last-1]>perm[last-2]) {
+ /*
+ * Big endian.
+ */
+ if (mesg) *mesg = "Big-endian";
+ for (i=0; i<n; i++) perm[i] = (n-1)-i;
+
+ } else {
+ /*
+ * Bi-endian machines like VAX.
+ */
+ assert (0==n/2);
+ if (mesg) *mesg = "VAX";
+ for (i=0; i<n; i+=2) {
+ perm[i] = (n-2)-i;
+ perm[i+1] = (n-1)-i;
+ }
+ }
+ } else {
+ fprintf (stderr,
+ "Failed to detect byte order of %d-byte floating point.\n", n);
+ exit (1);
+ }
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: fix_padding
+ *
+ * Purpose: The permutation can have negative values at the beginning
+ * or end which represent zero padding. The amount of padding
+ * is subtracted from the size, the negative values are removed
+ * from the permutation, and the `padding' field is set to an
+ * appropriate value.
+ *
+ * If N bytes of padding appear to the left (lower address) of
+ * the value, then `padding=N'. If N bytes of padding appear
+ * to the right of the value then `padding=(-N)'.
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Nov 4 1996
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void
+fix_padding (detected_t *d) {
+
+ int i, n;
+
+ if (d->perm[0]<0) {
+ /*
+ * Left padding.
+ */
+ for (n=0; n<d->size && d->perm[n]<0; n++) /*void*/;
+ for (i=n; i<d->size; i++) d->perm[i-n] = d->perm[i];
+ for (i=d->size-n; i<d->size; i++) d->perm[i] = 0;
+ d->padding = n;
+ d->size -= n;
+
+ } else if (d->perm[d->size-1]<0) {
+ /*
+ * Right padding.
+ */
+ for (n=0; n<d->size && d->perm[d->size-(n+1)]; n++) /*void*/;
+ for (i=d->size-n; i<d->size; 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<<nbits) - 1;
+ b = (a[perm[epos/8]] >> (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);
+}