summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobb Matzke <matzke@llnl.gov>1997-11-07 05:16:53 (GMT)
committerRobb Matzke <matzke@llnl.gov>1997-11-07 05:16:53 (GMT)
commit73897627660169de753597b9ff045d3112646506 (patch)
treeb02e9ffd202a7448cdf4bc0bdfe5da728dde862b
parent833e82fec5f654c1ed93a6e4e4266f280e20311c (diff)
downloadhdf5-73897627660169de753597b9ff045d3112646506.zip
hdf5-73897627660169de753597b9ff045d3112646506.tar.gz
hdf5-73897627660169de753597b9ff045d3112646506.tar.bz2
[svn-r135] ./config/linux
./config/freebsd2.2.1 Rewritten to be more flexible. ./src/H5AC.c ./src/H5ACprivate.h ./src/H5F.c ./src/H5H.c ./src/H5Gpkg.h ./src/H5Gshad.c ./src/H5O.c ./test/istore.c ./test/tstab.c Accumulates cache statistics and displays the results on stderr when the file is closed if it was opened with H5F_ACC_DEBUG passed into H5F_open() ./src/H5B.c ./src/H5Bprivate.h ./src/H5Fistore.c ./src/H5Gnode.c Added more debugging which is turned on if H5B_DEBUG is defined on the compile command (see config/linux). Fixed a couple of bugs with left insertions which are used by the indexed storage stuff. ./src/H5Flow.c Fixed a memory leak. ./src/H5Fprivate.h Fixed warnings about shifting more than size of object. ./src/H5Fstdio.c Fixed seek optimizations back to the way Quincey originally had them. ./src/H5V.c Removed unused variables.
-rw-r--r--MANIFEST1
-rw-r--r--config/freebsd2.2.150
-rw-r--r--config/linux54
-rw-r--r--src/H5AC.c125
-rw-r--r--src/H5ACprivate.h27
-rw-r--r--src/H5B.c334
-rw-r--r--src/H5Bprivate.h8
-rw-r--r--src/H5Distore.c130
-rw-r--r--src/H5F.c3
-rw-r--r--src/H5Fistore.c130
-rw-r--r--src/H5Flow.c7
-rw-r--r--src/H5Fprivate.h13
-rw-r--r--src/H5Fstdio.c9
-rw-r--r--src/H5Gnode.c93
-rw-r--r--src/H5Gpkg.h2
-rw-r--r--src/H5Gshad.c28
-rw-r--r--src/H5Gstab.c2
-rw-r--r--src/H5H.c8
-rw-r--r--src/H5O.c8
-rw-r--r--src/H5V.c4
-rw-r--r--test/istore.c3
-rw-r--r--test/tstab.c1
22 files changed, 769 insertions, 271 deletions
diff --git a/MANIFEST b/MANIFEST
index b756d89..a2d0052 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -48,6 +48,7 @@
./src/H5Eprivate.h
./src/H5Epublic.h
./src/H5F.c
+./src/H5Fcore.c
./src/H5Fistore.c
./src/H5Flow.c
./src/H5Fsec2.c
diff --git a/config/freebsd2.2.1 b/config/freebsd2.2.1
index 4d83367..35286f0 100644
--- a/config/freebsd2.2.1
+++ b/config/freebsd2.2.1
@@ -1,5 +1,51 @@
+#!/bin/sh
# Site configuration -- do not distribute this file.
-if test "x$CFLAGS" = "x"; then
- CFLAGS="-g -DH5AC_DEBUG_PROTECT -Wall -Wshadow -Wpointer-arith -Wcast-qual -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs"
+
+# Based on the setting of environment variable `HDF5_MODE' we set the
+# compiler flags unless they're already set. Its value can be one or
+# more of the following words:
+#
+# $warn -- Generates compiler warnings. You should always
+# include this since it has no effect on the speed of
+# the code produced.
+#
+# $debug -- Compiles in code to check for invariant conditions
+# and turns on the `-g' flag for interactive
+# debugging. It also turns off seek optimizations in
+# the low-level file driver. This version of the
+# library can be significantly slower than a production
+# version.
+#
+# $production -- Compiles an optimized version of the library
+# and disables code that checks for invariant
+# conditions. It also turns on various optimizations
+# such as seek optimizations in the low level file
+# driver.
+#
+# $profile -- Compiles code with the `-pg' flag which
+# produces a `gmon.out' file when the library
+# runs. The gprof(1) command can read that file
+# and produce detailed run-time statistics.
+#
+# If HDF5_MODE is undefined then we use the value
+#
+# $debug $warn -DH5F_LOW_DFLT=H5F_LOW_SEC2
+#
+
+
+warn="-Wall -Wshadow -Wpointer-arith -Wcast-qual -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs"
+
+profile="-pg"
+
+debug="-g -DH5AC_DEBUG -DH5B_DEBUG -DH5F_OPT_SEEK=0 -fverbose-asm"
+
+production="-O3 -DNDEBUG -DH5F_OPT_SEEK=1 -finline-functions -funroll-loops -malign-double -fomit-frame-pointer"
+
+default_mode='$debug $warn -DH5F_LOW_DFLT=H5F_LOW_SEC2'
+
+# Don't set CFLAGS if the user already did.
+if test -z "$CFLAGS"; then
+ CFLAGS="`eval echo ${HDF5_MODE:-$default_mode}`"
+ export CFLAGS
fi
diff --git a/config/linux b/config/linux
index 642829a..35286f0 100644
--- a/config/linux
+++ b/config/linux
@@ -1,17 +1,51 @@
+#!/bin/sh
# Site configuration -- do not distribute this file.
-CFLAGS_WARN="-Wall -Wshadow -Wpointer-arith -Wcast-qual -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs"
-CFLAGS_DEBUG="-g -DH5AC_DEBUG_PROTECT -DH5F_LOW_DFLT=H5F_LOW_STDIO -DH5F_OPT_SEEK=1 -fverbose-asm"
-CFLAGS_PROFILE="-pg"
-CFLAGS_PRODUCTION="-O3 -UH5AC_DEBUG_PROTECT -DNDEBUG -DH5F_LOW_DFLT=H5F_LOW_STDIO -DH5F_OPT_SEEK=1 -finline-functions -funroll-loops -malign-double -fomit-frame-pointer"
+# Based on the setting of environment variable `HDF5_MODE' we set the
+# compiler flags unless they're already set. Its value can be one or
+# more of the following words:
+#
+# $warn -- Generates compiler warnings. You should always
+# include this since it has no effect on the speed of
+# the code produced.
+#
+# $debug -- Compiles in code to check for invariant conditions
+# and turns on the `-g' flag for interactive
+# debugging. It also turns off seek optimizations in
+# the low-level file driver. This version of the
+# library can be significantly slower than a production
+# version.
+#
+# $production -- Compiles an optimized version of the library
+# and disables code that checks for invariant
+# conditions. It also turns on various optimizations
+# such as seek optimizations in the low level file
+# driver.
+#
+# $profile -- Compiles code with the `-pg' flag which
+# produces a `gmon.out' file when the library
+# runs. The gprof(1) command can read that file
+# and produce detailed run-time statistics.
+#
+# If HDF5_MODE is undefined then we use the value
+#
+# $debug $warn -DH5F_LOW_DFLT=H5F_LOW_SEC2
+#
-if test "x$CFLAGS" = "x"; then
- # Uncomment the following line for a production version of the library.
- #CFLAGS="-pipe $CFLAGS_PRODUCTION $CFLAGS_WARN"
+warn="-Wall -Wshadow -Wpointer-arith -Wcast-qual -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs"
- # Uncomment the following line for normal development
- CFLAGS="-pipe $CFLAGS_DEBUG $CFLAGS_WARN"
-fi
+profile="-pg"
+
+debug="-g -DH5AC_DEBUG -DH5B_DEBUG -DH5F_OPT_SEEK=0 -fverbose-asm"
+
+production="-O3 -DNDEBUG -DH5F_OPT_SEEK=1 -finline-functions -funroll-loops -malign-double -fomit-frame-pointer"
+default_mode='$debug $warn -DH5F_LOW_DFLT=H5F_LOW_SEC2'
+
+# Don't set CFLAGS if the user already did.
+if test -z "$CFLAGS"; then
+ CFLAGS="`eval echo ${HDF5_MODE:-$default_mode}`"
+ export CFLAGS
+fi
diff --git a/src/H5AC.c b/src/H5AC.c
index 1c570e8..c4ee46c 100644
--- a/src/H5AC.c
+++ b/src/H5AC.c
@@ -36,7 +36,9 @@
* accesses protected objects. NDEBUG must not be defined in order for
* this to have any effect.
*/
-/* #define H5AC_DEBUG_PROTECT */
+#ifdef NDEBUG
+# undef H5AC_DEBUG
+#endif
/*
* Private file-scope variables.
@@ -120,7 +122,7 @@ H5AC_dest (H5F_t *f)
HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL);
}
-#if defined(H5AC_DEBUG_PROTECT) && !defined(NDEBUG)
+#ifdef H5AC_DEBUG
{
intn i;
for (i=0; i<cache->nslots; i++) {
@@ -151,7 +153,7 @@ H5AC_dest (H5F_t *f)
* 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
+ * If H5AC_DEBUG 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().
@@ -174,11 +176,15 @@ H5AC_dest (H5F_t *f)
* what type of object is at the address and calls this function with
* various type identifiers until one succeeds (cf., the debugger).
*
+ * Robb Matzke, 30 Oct 1997
+ * Keeps track of hits, misses, and flushes per object type so we have
+ * some cache performance diagnostics.
+ *
*-------------------------------------------------------------------------
*/
void *
H5AC_find_f (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
- void *udata1, void *udata2)
+ const void *udata1, void *udata2)
{
unsigned idx;
herr_t status;
@@ -202,8 +208,10 @@ H5AC_find_f (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
* Return right away if the item is in the cache.
*/
if (slot->type==type && slot->addr==addr) {
+ cache->diagnostics[type->id].nhits++;
HRETURN (slot->thing);
}
+ cache->diagnostics[type->id].nmisses++;
/*
* Fail if the item in the cache is at the correct address but is
@@ -213,7 +221,7 @@ H5AC_find_f (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
HRETURN_ERROR (H5E_CACHE, H5E_BADTYPE, NULL);
}
-#if defined(H5AC_DEBUG_PROTECT) && !defined(NDEBUG)
+#ifdef H5AC_DEBUG
/*
* Check that the requested thing isn't protected, for protected things
* can only be modified through the pointer already handed out by the
@@ -251,6 +259,7 @@ H5AC_find_f (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
}
HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, NULL);
}
+ cache->diagnostics[slot->type->id].nflushes++;
}
/*
@@ -396,6 +405,7 @@ H5AC_flush (H5F_t *f, const H5AC_class_t *type, haddr_t addr, hbool_t destroy)
map = H5MM_xfree (map);
HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL);
}
+ cache->diagnostics[slot->type->id].nflushes++;
if (destroy) slot->type = NULL;
}
}
@@ -420,6 +430,7 @@ H5AC_flush (H5F_t *f, const H5AC_class_t *type, haddr_t addr, hbool_t destroy)
if (status<0) {
HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL);
}
+ cache->diagnostics[cache->slot[i].type->id].nflushes++;
if (destroy) cache->slot[i].type = NULL;
}
@@ -435,7 +446,7 @@ H5AC_flush (H5F_t *f, const H5AC_class_t *type, haddr_t addr, hbool_t destroy)
* exist on disk yet, but it must have an address and disk
* space reserved.
*
- * If H5AC_DEBUG_PROTECT is defined then this function checks
+ * If H5AC_DEBUG is defined then this function checks
* that the object being inserted isn't a protected object.
*
* Return: Success: SUCCEED
@@ -469,9 +480,9 @@ H5AC_set (H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing)
assert (thing);
idx = H5AC_HASH (f, addr);
cache = f->shared->cache;
- slot =cache->slot + idx;
+ slot = cache->slot + idx;
-#if defined(H5AC_DEBUG_PROTECT) && !defined(NDEBUG)
+#ifdef H5AC_DEBUG
{
intn i;
for (i=0; i<slot->nprots; i++) {
@@ -486,11 +497,13 @@ H5AC_set (H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing)
if (status<0) {
HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL);
}
+ cache->diagnostics[slot->type->id].nflushes++;
}
slot->type = type;
slot->addr = addr;
slot->thing = thing;
+ cache->diagnostics[type->id].ninits++;
FUNC_LEAVE (SUCCEED);
}
@@ -502,7 +515,7 @@ H5AC_set (H5F_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
+ * If H5AC_DEBUG is defined then this function checks
* that the old and new addresses don't correspond to the
* address of a protected object.
*
@@ -538,7 +551,7 @@ H5AC_rename (H5F_t *f, const H5AC_class_t *type,
new_idx = H5AC_HASH (f, new_addr);
cache = f->shared->cache;
-#if defined(H5AC_DEBUG_PROTECT) && !defined(NDEBUG)
+#ifdef H5AC_DEBUG
{
int i;
@@ -574,6 +587,7 @@ H5AC_rename (H5F_t *f, const H5AC_class_t *type,
if (status<0) {
HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL);
}
+ cache->diagnostics[cache->slot[new_idx].type->id].nflushes++;
}
/*
@@ -599,7 +613,7 @@ H5AC_rename (H5F_t *f, const H5AC_class_t *type,
* The caller must call H5AC_unprotect() when finished with
* the pointer.
*
- * If H5AC_DEBUG_PROTECT is defined then we check that the
+ * If H5AC_DEBUG is defined then we check that the
* requested object isn't already protected.
*
* Return: Success: Ptr to the object.
@@ -616,12 +630,19 @@ H5AC_rename (H5F_t *f, const H5AC_class_t *type,
*/
void *
H5AC_protect (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
- void *udata1, void *udata2)
+ const void *udata1, void *udata2)
{
int idx;
void *thing = NULL;
H5AC_t *cache = NULL;
H5AC_slot_t *slot = NULL;
+
+#ifdef H5AC_DEBUG
+ static ncalls = 0;
+ if (0==ncalls++) {
+ fprintf (stderr, "HDF5-DIAG: debugging cache (expensive)\n");
+ }
+#endif
FUNC_ENTER (H5AC_protect, NULL, NULL);
@@ -639,6 +660,7 @@ H5AC_protect (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
/*
* The object is already cached; simply remove it from the cache.
*/
+ cache->diagnostics[slot->type->id].nhits++;
thing = slot->thing;
slot->type = NULL;
slot->addr = 0;
@@ -651,7 +673,7 @@ H5AC_protect (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
HRETURN_ERROR (H5E_CACHE, H5E_BADTYPE, NULL);
} else {
-#if defined(H5AC_DEBUG_PROTECT) && !defined(NDEBUG)
+#ifdef H5AC_DEBUG
/*
* Check that the requested thing isn't protected, for protected things
* can only be modified through the pointer already handed out by the
@@ -667,12 +689,13 @@ H5AC_protect (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
* Load a new thing. If it can't be loaded, then return an error
* without preempting anything.
*/
+ cache->diagnostics[type->id].nmisses++;
if (NULL==(thing=(type->load)(f, addr, udata1, udata2))) {
HRETURN_ERROR (H5E_CACHE, H5E_CANTLOAD, NULL);
}
}
-#if defined(H5AC_DEBUG_PROTECT) && !defined(NDEBUG)
+#ifdef H5AC_DEBUG
/*
* Add the protected object to the protect debugging fields of the
* cache.
@@ -701,7 +724,7 @@ H5AC_protect (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
* 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 H5AC_DEBUG 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.
*
@@ -750,9 +773,10 @@ H5AC_unprotect (H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing)
if (status<0) {
HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL);
}
+ cache->diagnostics[slot->type->id].nflushes++;
}
-#if defined(H5AC_DEBUG_PROTECT) && !defined(NDEBUG)
+#ifdef H5AC_DEBUG
/*
* Remove the object's protect data to indicate that it is no longer
* protected.
@@ -782,3 +806,72 @@ H5AC_unprotect (H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing)
FUNC_LEAVE (SUCCEED);
}
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5AC_debug
+ *
+ * Purpose: Prints debugging info about the cache.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Thursday, October 30, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5AC_debug (H5F_t *f)
+{
+ H5AC_subid_t i;
+ char s[32];
+ H5AC_t *cache = f->shared->cache;
+ double miss_rate;
+
+ FUNC_ENTER (H5AC_debug, NULL, FAIL);
+
+ fprintf (stderr, "HDF5-DIAG: cache diagnostics for %s\n", f->name);
+ fprintf (stderr, " %18s %8s %8s %8s %8s+%-8s\n",
+ "", "Hits", "Misses", "MissRate", "Inits", "Flushes");
+
+ for (i=0; i<H5AC_NTYPES; i++) {
+
+ switch (i) {
+ case H5AC_BT_ID:
+ strcpy (s, "B-tree nodes");
+ break;
+ case H5AC_SNODE_ID:
+ strcpy (s, "symbol table nodes");
+ break;
+ case H5AC_HEAP_ID:
+ strcpy (s, "heaps");
+ break;
+ case H5AC_OHDR_ID:
+ strcpy (s, "object headers");
+ break;
+ default:
+ sprintf (s, "unknown id %d", i);
+ }
+
+ if (cache->diagnostics[i].nhits) {
+ miss_rate = 100.0 * cache->diagnostics[i].nmisses /
+ cache->diagnostics[i].nhits;
+ } else {
+ miss_rate = 0.0;
+ }
+
+ fprintf (stderr, " %18s: %8d %8d %7.2f%% %8d%+-9d\n", s,
+ cache->diagnostics[i].nhits,
+ cache->diagnostics[i].nmisses,
+ miss_rate,
+ cache->diagnostics[i].ninits,
+ cache->diagnostics[i].nflushes-cache->diagnostics[i].ninits);
+ }
+
+ FUNC_LEAVE (SUCCEED);
+}
diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h
index 25549ff..884bc3c6 100644
--- a/src/H5ACprivate.h
+++ b/src/H5ACprivate.h
@@ -38,8 +38,18 @@
* function is also responsible for freeing memory allocated
* by the LOAD method if the DEST argument is non-zero.
*/
+typedef enum H5AC_subid_t {
+ H5AC_BT_ID =0, /*B-tree nodes */
+ H5AC_SNODE_ID =1, /*symbol table nodes */
+ H5AC_HEAP_ID =2, /*object or name heap */
+ H5AC_OHDR_ID =3, /*object header */
+ H5AC_NTYPES =4 /*THIS MUST BE LAST!*/
+} H5AC_subid_t;
+
typedef struct H5AC_class_t {
- void *(*load)(H5F_t*, haddr_t addr, void *udata1, void *udata2);
+ H5AC_subid_t id;
+ void *(*load)(H5F_t*, haddr_t addr, const void *udata1,
+ void *udata2);
herr_t (*flush)(H5F_t*, hbool_t dest, haddr_t addr, void *thing);
} H5AC_class_t;
@@ -70,17 +80,22 @@ typedef struct H5AC_t {
intn nslots; /*number of cache slots */
H5AC_slot_t *slot; /*the cache slots */
intn nprots; /*number of protected objects */
+ struct {
+ uintn nhits; /*number of cache hits */
+ uintn nmisses; /*number of cache misses */
+ uintn ninits; /*number of cache initializations */
+ uintn nflushes; /*number of flushes to disk */
+ } diagnostics[H5AC_NTYPES]; /*diagnostics for each type of object */
} H5AC_t;
-
/*
* Library prototypes.
*/
herr_t H5AC_dest (H5F_t *f);
void *H5AC_find_f (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
- void *udata1, void *udata2);
+ const void *udata1, void *udata2);
void * H5AC_protect (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
- void *udata1, void *udata2);
+ const void *udata1, void *udata2);
herr_t H5AC_unprotect (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
void *thing);
herr_t H5AC_flush (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
@@ -90,11 +105,13 @@ herr_t H5AC_rename (H5F_t *f, const H5AC_class_t *type, haddr_t old,
haddr_t new);
herr_t H5AC_set (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
void *thing);
+herr_t H5AC_debug (H5F_t *f);
#define H5AC_find(F,TYPE,ADDR,UDATA1,UDATA2) \
(((F)->shared->cache->slot[H5AC_HASH(F,ADDR)].type==(TYPE) && \
(F)->shared->cache->slot[H5AC_HASH(F,ADDR)].addr==(ADDR)) ? \
- (F)->shared->cache->slot[H5AC_HASH(F,ADDR)].thing : \
+ ((F)->shared->cache->diagnostics[(TYPE)->id].nhits++, \
+ (F)->shared->cache->slot[H5AC_HASH(F,ADDR)].thing) : \
H5AC_find_f (F, TYPE, ADDR, UDATA1, UDATA2))
diff --git a/src/H5B.c b/src/H5B.c
index ccbcdb4..a735799 100644
--- a/src/H5B.c
+++ b/src/H5B.c
@@ -94,6 +94,15 @@
#include <H5MFprivate.h> /*File memory management */
#include <H5MMprivate.h> /*Core memory management */
+/*
+ * Define this constant if you want to check B-tree consistency after each
+ * B-tree operation. Note that this slows down the library considerably!
+ * Debugging the B-tree depends on assert() being enabled.
+ */
+#ifdef NDEBUG
+# undef H5B_DEBUG
+#endif
+
#define PABLO_MASK H5B_mask
#define BOUND(MIN,X,MAX) ((X)<(MIN)?(MIN):((X)>(MAX)?(MAX):(X)))
@@ -108,15 +117,21 @@ static herr_t H5B_insert_child (H5F_t *f, const H5B_class_t *type,
H5B_t *bt, intn idx, haddr_t child,
H5B_ins_t anchor, void *md_key);
static herr_t H5B_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5B_t *b);
-static H5B_t *H5B_load (H5F_t *f, haddr_t addr, void *_type, void *udata);
+static H5B_t *H5B_load (H5F_t *f, haddr_t addr, const void *_type,
+ void *udata);
static herr_t H5B_decode_key (H5F_t *f, H5B_t *bt, intn idx);
static herr_t H5B_decode_keys (H5F_t *f, H5B_t *bt, intn idx);
static size_t H5B_nodesize (H5F_t *f, const H5B_class_t *type,
size_t *total_nkey_size, size_t sizeof_rkey);
+#ifdef H5B_DEBUG
+static herr_t H5B_assert (H5F_t *f, haddr_t addr, const H5B_class_t *type,
+ void *udata);
+#endif
/* H5B inherits cache-like properties from H5AC */
static const H5AC_class_t H5AC_BT[1] = {{
- (void*(*)(H5F_t*,haddr_t,void*,void*))H5B_load,
+ H5AC_BT_ID,
+ (void*(*)(H5F_t*,haddr_t,const void*,void*))H5B_load,
(herr_t(*)(H5F_t*,hbool_t,haddr_t,void*))H5B_flush,
}};
@@ -211,6 +226,9 @@ H5B_new (H5F_t *f, const H5B_class_t *type, void *udata)
HRETURN_ERROR (H5E_BTREE, H5E_CANTINIT, FAIL);
}
+#ifdef H5B_DEBUG
+ H5B_assert (f, addr, type, udata);
+#endif
FUNC_LEAVE (addr);
}
@@ -233,9 +251,9 @@ H5B_new (H5F_t *f, const H5B_class_t *type, void *udata)
*-------------------------------------------------------------------------
*/
static H5B_t *
-H5B_load (H5F_t *f, haddr_t addr, void *_type, void *udata)
+H5B_load (H5F_t *f, haddr_t addr, const void *_type, void *udata)
{
- const H5B_class_t *type = (H5B_class_t *)_type;
+ const H5B_class_t *type = (const H5B_class_t *)_type;
size_t size, total_nkey_size;
H5B_t *bt = NULL;
intn i;
@@ -461,7 +479,7 @@ H5B_find (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata)
assert (f);
assert (type);
assert (type->decode);
- assert (type->cmp);
+ assert (type->cmp3);
assert (type->found);
assert (addr>=0);
@@ -481,8 +499,8 @@ H5B_find (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata)
}
/* compare */
- if ((cmp=(type->cmp)(f, bt->key[idx].nkey, udata,
- bt->key[idx+1].nkey))<0) {
+ if ((cmp=(type->cmp3)(f, bt->key[idx].nkey, udata,
+ bt->key[idx+1].nkey))<0) {
rt = idx;
} else {
lt = idx+1;
@@ -519,12 +537,12 @@ done:
/*-------------------------------------------------------------------------
* Function: H5B_split
*
- * Purpose: Split a single node into two nodes. If anchor is
- * H5B_INS_RIGHT then the new node gets the right half of
- * the old node. If anchor is H5B_INS_LEFT then the
- * new node gets the left half of the old node. The UDATA
- * pointer is passed to the sizeof_rkey() method but is
- * otherwise unused.
+ * Purpose: Split a single node into two nodes. The old node will
+ * contain the left children and the new node will contain the
+ * right children.
+ *
+ * The UDATA pointer is passed to the sizeof_rkey() method but is
+ * otherwise unused.
*
* The OLD_BT argument is a pointer to a protected B-tree
* node.
@@ -543,11 +561,11 @@ done:
*/
static haddr_t
H5B_split (H5F_t *f, H5B_class_t *type, H5B_t *old_bt, haddr_t old_addr,
- H5B_ins_t anchor, void *udata)
+ void *udata)
{
H5B_t *new_bt=NULL, *tmp_bt=NULL;
haddr_t ret_value=FAIL, new_addr=FAIL;
- intn i, delta;
+ intn i, k;
size_t recsize = 0;
FUNC_ENTER (H5B_split, NULL, FAIL);
@@ -558,14 +576,13 @@ H5B_split (H5F_t *f, H5B_class_t *type, H5B_t *old_bt, haddr_t old_addr,
assert (f);
assert (type);
assert (old_addr>=0);
- assert (H5B_INS_LEFT==anchor || H5B_INS_RIGHT==anchor);
/*
* Initialize variables.
*/
assert (old_bt->nchildren == 2*H5B_K(f,type));
recsize = old_bt->sizeof_rkey + H5F_SIZEOF_OFFSET(f);
- delta = H5B_INS_RIGHT==anchor ? H5B_K(f,type) : 0;
+ k = H5B_K(f,type);
/*
* Create the new B-tree node.
@@ -582,94 +599,47 @@ H5B_split (H5F_t *f, H5B_class_t *type, H5B_t *old_bt, haddr_t old_addr,
* Copy data from the old node to the new node.
*/
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);
+ old_bt->page + H5B_SIZEOF_HDR(f) + k*recsize,
+ k*recsize + new_bt->sizeof_rkey);
HDmemcpy (new_bt->native,
- old_bt->native + delta * type->sizeof_nkey,
- (H5B_K(f,type)+1) * type->sizeof_nkey);
+ old_bt->native + k*type->sizeof_nkey,
+ (k+1) * type->sizeof_nkey);
- for (i=0; i<=2*H5B_K(f,type); i++) {
+ for (i=0; i<=k; i++) {
/* key */
- if (i<=H5B_K(f,type)) {
- 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;
- }
+ new_bt->key[i].dirty = old_bt->key[k+i].dirty;
+ if (old_bt->key[k+i].nkey) {
+ new_bt->key[i].nkey = new_bt->native + i*type->sizeof_nkey;
}
/* child */
- if (i<H5B_K(f,type)) {
- new_bt->child[i] = old_bt->child[delta+i];
+ if (i<k) {
+ new_bt->child[i] = old_bt->child[k+i];
}
}
- new_bt->ndirty = BOUND (0, old_bt->ndirty-delta, H5B_K(f,type));
- new_bt->nchildren = H5B_K(f,type);
+ new_bt->ndirty = new_bt->nchildren = k;
/*
* Truncate the old node.
*/
- delta = H5B_INS_RIGHT==anchor ? 0 : H5B_K(f,type);
old_bt->dirty = TRUE;
- old_bt->ndirty = BOUND (0, old_bt->ndirty-delta, H5B_K(f,type));
- old_bt->nchildren = H5B_K(f,type);
+ old_bt->ndirty = old_bt->nchildren = k;
- if (H5B_INS_LEFT==anchor) {
- HDmemcpy (old_bt->page + H5B_SIZEOF_HDR(f),
- old_bt->page + H5B_SIZEOF_HDR(f) + delta*recsize,
- H5B_K(f,type) * recsize);
- 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_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_bt->key[i].nkey = NULL;
- }
- } else {
- old_bt->key[i].nkey = NULL;
- }
- if (i<H5B_K(f,type)) {
- old_bt->child[i] = old_bt->child[delta+i];
- } else if (i<2*H5B_K(f,type)) {
- old_bt->child[i] = 0;
- }
- }
- }
-
/*
* Update sibling pointers.
*/
- if (H5B_INS_RIGHT==anchor) {
- new_bt->left = old_addr;
- new_bt->right = old_bt->right;
+ new_bt->left = old_addr;
+ new_bt->right = old_bt->right;
- if (old_bt->right) {
- if (NULL==(tmp_bt=H5AC_find (f, H5AC_BT, old_bt->right, type,
- udata))) {
- HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL);
- }
- tmp_bt->dirty = TRUE;
- tmp_bt->left = new_addr;
- }
- old_bt->right = new_addr;
- } else {
- 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,
- udata))) {
- HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL);
- }
- tmp_bt->dirty = TRUE;
- tmp_bt->right = new_addr;
+ if (old_bt->right) {
+ if (NULL==(tmp_bt=H5AC_find (f, H5AC_BT, old_bt->right, type,
+ udata))) {
+ HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL);
}
- old_bt->left = new_addr;
+ tmp_bt->dirty = TRUE;
+ tmp_bt->left = new_addr;
}
+ old_bt->right = new_addr;
+
HGOTO_DONE (new_addr);
done:
@@ -894,6 +864,9 @@ H5B_insert (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata)
bt->key[2].nkey = bt->native + 2 * type->sizeof_nkey;
HDmemcpy (bt->key[2].nkey, rt_key, type->sizeof_nkey);
+#ifdef H5B_DEBUG
+ H5B_assert (f, new_root, type, udata);
+#endif
FUNC_LEAVE (new_root);
}
@@ -964,8 +937,8 @@ H5B_insert_child (H5F_t *f, const H5B_class_t *type, H5B_t *bt,
idx*recsize + bt->sizeof_rkey),
(bt->nchildren-idx) * recsize);
- HDmemmove (bt->native + idx + 2,
- bt->native + idx + 1,
+ HDmemmove (bt->native + (idx+2)*type->sizeof_nkey,
+ bt->native + (idx+1)*type->sizeof_nkey,
(bt->nchildren-idx) * type->sizeof_nkey);
for (i=bt->nchildren; i>idx; --i) {
@@ -1047,7 +1020,7 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type,
assert (addr>=0);
assert (type);
assert (type->decode);
- assert (type->cmp);
+ assert (type->cmp3);
assert (type->new);
assert (parent_ins && H5B_INS_ERROR==*parent_ins);
assert (lt_key);
@@ -1073,8 +1046,8 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type,
if (H5B_decode_keys (f, bt, idx)<0) {
HRETURN_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL);
}
- if ((cmp=(type->cmp)(f, bt->key[idx].nkey, udata,
- bt->key[idx+1].nkey))<0) {
+ if ((cmp=(type->cmp3)(f, bt->key[idx].nkey, udata,
+ bt->key[idx+1].nkey))<0) {
rt = idx;
} else {
lt = idx+1;
@@ -1089,7 +1062,7 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type,
assert (0==bt->level);
bt->key[0].nkey = bt->native;
bt->key[1].nkey = bt->native + type->sizeof_nkey;
- if ((child_addr=(type->new)(f, bt->key[0].nkey, udata,
+ if ((child_addr=(type->new)(f, H5B_INS_FIRST, 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);
@@ -1152,7 +1125,8 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type,
}
my_ins = H5B_INS_LEFT;
HDmemcpy (md_key, bt->key[idx].nkey, type->sizeof_nkey);
- child_addr = (type->new)(f, bt->key[idx].nkey, udata, md_key);
+ child_addr = (type->new)(f, H5B_INS_LEFT, bt->key[idx].nkey,
+ udata, md_key);
*lt_key_changed = TRUE;
} else if (cmp>0 && idx+1>=bt->nchildren && bt->level>0) {
@@ -1196,7 +1170,8 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type,
}
my_ins = H5B_INS_RIGHT;
HDmemcpy (md_key, bt->key[idx+1].nkey, type->sizeof_nkey);
- child_addr = (type->new)(f, md_key, udata, bt->key[idx+1].nkey);
+ child_addr = (type->new)(f, H5B_INS_RIGHT, md_key,
+ udata, bt->key[idx+1].nkey);
*rt_key_changed = TRUE;
} else if (cmp) {
@@ -1267,35 +1242,31 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type,
*parent_ins = H5B_INS_NOOP;
} else if (H5B_INS_LEFT==my_ins || H5B_INS_RIGHT==my_ins) {
- /*
- * The child split. If the left node is anchored, then the new
- * child node gets inserted to the right of our current position.
- */
+ /* Make sure IDX is the slot number for the new node. */
if (H5B_INS_RIGHT==my_ins) idx++;
- if (bt->nchildren==2*H5B_K(f,type)) {
- /* Split the current node */
- if ((twin_addr = H5B_split (f, type, bt, addr, my_ins, udata))<0) {
- HGOTO_ERROR (H5E_BTREE, H5E_CANTSPLIT, FAIL);
+ /* If this node is full then split it before inserting the new child. */
+ if (bt->nchildren==2*H5B_K (f, type)) {
+ if ((twin_addr=H5B_split (f, type, bt, addr, udata))<0) {
+ HGOTO_ERROR (H5E_BTREE, H5E_CANTSPLIT, FAIL);/*can't split node*/
}
- if (NULL==(twin=H5AC_protect (f, H5AC_BT, twin_addr, type,
- udata))) {
- HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL);
+ if (NULL==(twin=H5AC_protect (f, H5AC_BT, twin_addr, type, udata))) {
+ HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL);/*can't load B-tree*/
}
-
- if (idx<=H5B_K(f,type)) {
- tmp_bt = H5B_INS_RIGHT==my_ins ? bt : twin;
+ if (idx<=H5B_K (f, type)) {
+ tmp_bt = bt;
} else {
idx -= H5B_K (f, type);
- tmp_bt = H5B_INS_RIGHT==my_ins ? twin : bt;
+ tmp_bt = twin;
}
} else {
tmp_bt = bt;
}
+ /* Insert the child */
if (H5B_insert_child (f, type, tmp_bt, idx, child_addr, my_ins,
md_key)<0) {
- HGOTO_ERROR (H5E_BTREE, H5E_CANTINSERT, FAIL);
+ HGOTO_ERROR (H5E_BTREE, H5E_CANTINSERT, FAIL);/*can't insert child*/
}
}
@@ -1305,18 +1276,24 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type,
* by the left and right node).
*/
if (twin) {
- if (H5B_INS_RIGHT==my_ins) {
- if (!twin->key[0].nkey && H5B_decode_key (f, twin, 0)<0) {
- HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL);
- }
- HDmemcpy (md_key, twin->key[0].nkey, type->sizeof_nkey);
- } else {
- if (!bt->key[0].nkey && H5B_decode_key (f, bt, 0)<0) {
- HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL);
- }
- HDmemcpy (md_key, bt->key[0].nkey, type->sizeof_nkey);
+ if (!twin->key[0].nkey && H5B_decode_key (f, twin, 0)<0) {
+ HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL);
}
+ HDmemcpy (md_key, twin->key[0].nkey, type->sizeof_nkey);
*parent_ins = H5B_INS_RIGHT;
+#ifndef NDEBUG
+ /*
+ * The max key in the original left node must be equal to the min key
+ * in the new node.
+ */
+ if (!bt->key[bt->nchildren].nkey) {
+ herr_t status = H5B_decode_key (f, bt, bt->nchildren);
+ assert (status>=0);
+ cmp = (type->cmp2)(f, bt->key[bt->nchildren].nkey, udata,
+ twin->key[0].nkey);
+ assert (0==cmp);
+ }
+#endif
} else {
*parent_ins = H5B_INS_NOOP;
}
@@ -1554,3 +1531,120 @@ H5B_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent,
FUNC_LEAVE (SUCCEED);
}
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B_assert
+ *
+ * Purpose: Verifies that the tree is structured correctly.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: aborts if something is wrong.
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, November 4, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifdef H5B_DEBUG
+static herr_t
+H5B_assert (H5F_t *f, haddr_t addr, const H5B_class_t *type, void *udata)
+{
+ H5B_t *bt = NULL;
+ intn i, ncell, cmp;
+ static int ncalls=0;
+ herr_t status;
+
+ /* A queue of child data */
+ struct child_t {
+ haddr_t addr;
+ int level;
+ struct child_t *next;
+ } *head=NULL, *tail=NULL, *prev=NULL, *cur=NULL, *tmp=NULL;
+
+ FUNC_ENTER (H5B_assert, NULL, FAIL);
+ if (0==ncalls++) {
+ fprintf (stderr, "HDF5-DIAG: debugging B-trees (expensive)\n");
+ }
+
+ /* Initialize the queue */
+ bt = H5AC_find (f, H5AC_BT, addr, type, udata);
+ assert (bt);
+ cur = H5MM_xcalloc (1, sizeof(struct child_t));
+ cur->addr = addr;
+ cur->level = bt->level;
+ head = tail = cur;
+
+ /*
+ * Do a breadth-first search of the tree. New nodes are added to the end
+ * of the queue as the `cur' pointer is advanced toward the end. We don't
+ * remove any nodes from the queue because we need them in the uniqueness
+ * test.
+ */
+ for (ncell=0; cur; ncell++) {
+ bt = H5AC_protect (f, H5AC_BT, cur->addr, type, udata);
+ assert (bt);
+
+ /* Check node header */
+ assert (bt->ndirty>=0 && bt->ndirty<=bt->nchildren);
+ assert (bt->level==cur->level);
+ if (cur->next && cur->next->level==bt->level) {
+ assert (bt->right==cur->next->addr);
+ } else {
+ assert (bt->right==0);
+ }
+ if (prev && prev->level==bt->level) {
+ assert (bt->left==prev->addr);
+ } else {
+ assert (bt->left==0);
+ }
+
+ if (cur->level>0) {
+ for (i=0; i<bt->nchildren; i++) {
+
+ /*
+ * Check that child nodes haven't already been seen. If they
+ * have then the tree has a cycle.
+ */
+ for (tmp=head; tmp; tmp=tmp->next) {
+ assert (tmp->addr != bt->child[i]);
+ }
+
+ /* Add the child node to the end of the queue */
+ tmp = H5MM_xcalloc (1, sizeof(struct child_t));
+ tmp->addr = bt->child[i];
+ tmp->level = bt->level - 1;
+ tail->next = tmp;
+ tail = tmp;
+
+ /* Check that the keys are monotonically increasing */
+ status = H5B_decode_keys (f, bt, i);
+ assert (status>=0);
+ cmp = (type->cmp2)(f, bt->key[i].nkey, udata, bt->key[i+1].nkey);
+ assert (cmp<0);
+ }
+ }
+
+ /* Release node */
+ status = H5AC_unprotect (f, H5AC_BT, cur->addr, bt);
+ assert (status>=0);
+
+ /* Advance current location in queue */
+ prev = cur;
+ cur = cur->next;
+ }
+
+ /* Free all entries from queue */
+ while (head) {
+ tmp = head->next;
+ H5MM_xfree (head);
+ head = tmp;
+ }
+
+ FUNC_LEAVE (SUCCEED);
+}
+#endif /* H5B_DEBUG */
diff --git a/src/H5Bprivate.h b/src/H5Bprivate.h
index 05e2e56..619a00f 100644
--- a/src/H5Bprivate.h
+++ b/src/H5Bprivate.h
@@ -38,7 +38,8 @@ typedef enum H5B_ins_t {
H5B_INS_NOOP =0, /*insert made no changes */
H5B_INS_LEFT =1, /*insert new node to left of cur node */
H5B_INS_RIGHT =2, /*insert new node to right of cur node */
- H5B_INS_CHANGE =3 /*change child address for cur node */
+ H5B_INS_CHANGE =3, /*change child address for cur node */
+ H5B_INS_FIRST =4 /*insert first node in (sub)tree */
} H5B_ins_t;
typedef enum H5B_subid_t {
@@ -59,8 +60,9 @@ typedef struct H5B_class_t {
H5B_subid_t id; /*id as found in file */
size_t sizeof_nkey; /*size of native (memory) key */
size_t (*get_sizeof_rkey)(H5F_t*,const void*);/*raw key size */
- haddr_t (*new)(H5F_t*,void*,void*,void*); /*create new leaf */
- intn (*cmp)(H5F_t*,void*,void*,void*); /*compare keys */
+ haddr_t (*new)(H5F_t*,H5B_ins_t,void*,void*,void*); /*new leaf */
+ intn (*cmp2)(H5F_t*,void*,void*,void*); /*compare 2 keys */
+ intn (*cmp3)(H5F_t*,void*,void*,void*); /*compare 3 keys */
herr_t (*found)(H5F_t*,haddr_t,const void*,void*,const void*);
haddr_t (*insert)(H5F_t*,haddr_t,H5B_ins_t*,void*,hbool_t*,void*,void*,
void*,hbool_t*); /*insert new data */
diff --git a/src/H5Distore.c b/src/H5Distore.c
index 96ef5fc..06997a1 100644
--- a/src/H5Distore.c
+++ b/src/H5Distore.c
@@ -29,10 +29,12 @@ static hbool_t interface_initialize_g = FALSE;
/* PRIVATE PROTOTYPES */
static size_t H5F_istore_sizeof_rkey (H5F_t *f, const void *_udata);
-static haddr_t H5F_istore_new_node (H5F_t *f, void *_lt_key, void *_udata,
- void *_rt_key);
-static intn H5F_istore_cmp (H5F_t *f, void *_lt_key, void *_udata,
- void *_rt_key);
+static haddr_t H5F_istore_new_node (H5F_t *f, H5B_ins_t, void *_lt_key,
+ void *_udata, void *_rt_key);
+static intn H5F_istore_cmp2 (H5F_t *f, void *_lt_key, void *_udata,
+ void *_rt_key);
+static intn H5F_istore_cmp3 (H5F_t *f, void *_lt_key, void *_udata,
+ void *_rt_key);
static herr_t H5F_istore_found (H5F_t *f, haddr_t addr, const void *_lt_key,
void *_udata, const void *_rt_key);
static haddr_t H5F_istore_insert (H5F_t *f, haddr_t addr, H5B_ins_t *anchor,
@@ -82,7 +84,8 @@ H5B_class_t H5B_ISTORE[1] = {{
sizeof (H5F_istore_key_t), /*sizeof_nkey */
H5F_istore_sizeof_rkey, /*get_sizeof_rkey */
H5F_istore_new_node, /*new */
- H5F_istore_cmp, /*cmp */
+ H5F_istore_cmp2, /*cmp2 */
+ H5F_istore_cmp3, /*cmp3 */
H5F_istore_found, /*found */
H5F_istore_insert, /*insert */
FALSE, /*follow min branch? */
@@ -209,10 +212,51 @@ H5F_istore_encode_key (H5F_t *f, H5B_t *bt, uint8 *raw, void *_key)
FUNC_LEAVE (SUCCEED);
}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_istore_cmp2
+ *
+ * Purpose: Compares two keys sort of like strcmp(). The UDATA pointer
+ * is only to supply extra information not carried in the keys
+ * (in this case, the dimensionality).
+ *
+ * Return: Success: -1 if LT_KEY is less than RT_KEY;
+ * 1 if LT_KEY is greater than RT_KEY;
+ * 0 if LT_KEY and RT_KEY are equal.
+ *
+ * Failure: FAIL (same as LT_KEY<RT_KEY)
+ *
+ * Programmer: Robb Matzke
+ * Thursday, November 6, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static intn
+H5F_istore_cmp2 (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key)
+{
+ H5F_istore_key_t *lt_key = (H5F_istore_key_t *)_lt_key;
+ H5F_istore_key_t *rt_key = (H5F_istore_key_t *)_rt_key;
+ H5F_istore_ud1_t *udata = (H5F_istore_ud1_t *)_udata;
+ intn cmp;
+
+ FUNC_ENTER (H5F_istore_cmp2, NULL, FAIL);
+
+ assert (lt_key);
+ assert (rt_key);
+ assert (udata);
+ assert (udata->mesg.ndims>0 && udata->mesg.ndims<=H5O_ISTORE_NDIMS);
+ cmp = H5V_vector_cmp (udata->mesg.ndims, lt_key->offset, rt_key->offset);
+
+ FUNC_LEAVE (cmp);
+}
+
/*-------------------------------------------------------------------------
- * Function: H5F_istore_cmp
+ * Function: H5F_istore_cmp3
*
* Purpose: Compare the requested datum UDATA with the left and right
* keys of the B-tree.
@@ -241,11 +285,14 @@ H5F_istore_encode_key (H5F_t *f, H5B_t *bt, uint8 *raw, void *_key)
*-------------------------------------------------------------------------
*/
static intn
-H5F_istore_cmp (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key)
+H5F_istore_cmp3 (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key)
{
H5F_istore_key_t *lt_key = (H5F_istore_key_t *)_lt_key;
H5F_istore_key_t *rt_key = (H5F_istore_key_t *)_rt_key;
H5F_istore_ud1_t *udata = (H5F_istore_ud1_t *)_udata;
+ intn cmp = 0;
+
+ FUNC_ENTER (H5F_istore_cmp3, NULL, FAIL);
assert (lt_key);
assert (rt_key);
@@ -253,13 +300,13 @@ H5F_istore_cmp (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key)
assert (udata->mesg.ndims>0 && udata->mesg.ndims<=H5O_ISTORE_NDIMS);
if (H5V_vector_lt (udata->mesg.ndims, udata->key.offset, lt_key->offset)) {
- return -1;
+ cmp = -1;
} else if (H5V_vector_ge (udata->mesg.ndims, udata->key.offset,
rt_key->offset)) {
- return 1;
- } else {
- return 0;
+ cmp = 1;
}
+
+ FUNC_LEAVE (cmp);
}
@@ -283,7 +330,8 @@ H5F_istore_cmp (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key)
*-------------------------------------------------------------------------
*/
static haddr_t
-H5F_istore_new_node (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key)
+H5F_istore_new_node (H5F_t *f, H5B_ins_t op,
+ void *_lt_key, void *_udata, void *_rt_key)
{
H5F_istore_key_t *lt_key = (H5F_istore_key_t *)_lt_key;
H5F_istore_key_t *rt_key = (H5F_istore_key_t *)_rt_key;
@@ -308,16 +356,25 @@ H5F_istore_new_node (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key)
HRETURN_ERROR (H5E_IO, H5E_CANTINIT, FAIL);
}
- /* left key describes the UDATA, right key is a zero-size "edge" */
+ /* Initialize the key(s) */
for (i=0; i<udata->mesg.ndims; i++) {
+ /*
+ * The left key describes the storage of the UDATA chunk being inserted
+ * into the tree.
+ */
lt_key->offset[i] = udata->key.offset[i];
lt_key->size[i] = udata->key.size[i];
assert (udata->key.size[i]>0);
-
- rt_key->offset[i] = udata->key.offset[i] + udata->key.size[i];
- rt_key->size[i] = 0;
- }
+ /*
+ * The right key might already be present. If not, then add
+ * a zero-width chunk.
+ */
+ if (H5B_INS_LEFT!=op) {
+ rt_key->offset[i] = udata->key.offset[i] + udata->key.size[i];
+ rt_key->size[i] = 0;
+ }
+ }
FUNC_LEAVE (udata->addr);
}
@@ -351,7 +408,6 @@ H5F_istore_found (H5F_t *f, haddr_t addr, const void *_lt_key,
{
H5F_istore_ud1_t *udata = (H5F_istore_ud1_t *)_udata;
const H5F_istore_key_t *lt_key = (const H5F_istore_key_t *)_lt_key;
- const H5F_istore_key_t *rt_key = (const H5F_istore_key_t *)_rt_key;
int i;
FUNC_ENTER (H5F_istore_found, NULL, FAIL);
@@ -361,7 +417,6 @@ H5F_istore_found (H5F_t *f, haddr_t addr, const void *_lt_key,
assert (addr>=0);
assert (udata);
assert (lt_key);
- assert (rt_key);
/* Initialize return values */
udata->addr = addr;
@@ -434,7 +489,7 @@ H5F_istore_insert (H5F_t *f, haddr_t addr, H5B_ins_t *parent_ins,
assert (rt_key);
assert (rt_key_changed);
- cmp = H5F_istore_cmp (f, lt_key, udata, rt_key);
+ cmp = H5F_istore_cmp3 (f, lt_key, udata, rt_key);
assert (cmp<=0);
if (cmp<0) {
@@ -531,9 +586,8 @@ H5F_istore_copy_hyperslab (H5F_t *f, const H5O_istore_t *istore, H5F_isop_t op,
size_t idx_min[H5O_ISTORE_NDIMS];
size_t idx_max[H5O_ISTORE_NDIMS];
size_t sub_size[H5O_ISTORE_NDIMS];
- size_t sub_offset_f[H5O_ISTORE_NDIMS];
+ size_t offset_wrt_chunk[H5O_ISTORE_NDIMS];
size_t sub_offset_m[H5O_ISTORE_NDIMS];
- size_t sub_offset_ch[H5O_ISTORE_NDIMS];
size_t chunk_size;
uint8 *chunk=NULL;
H5F_istore_ud1_t udata;
@@ -585,14 +639,25 @@ H5F_istore_copy_hyperslab (H5F_t *f, const H5O_istore_t *istore, H5F_isop_t op,
/* Read/Write chunk or create it if it doesn't exist */
udata.mesg.ndims = istore->ndims;
for (i=0; i<istore->ndims; i++) {
+
+ /* The location and size of the chunk being accessed */
udata.key.offset[i] = idx_cur[i] * istore->alignment[i];
udata.key.size[i] = istore->alignment[i];
- sub_offset_f[i] = MAX ((offset_f?offset_f[i]:0), udata.key.offset[i]);
- sub_offset_m[i] = (offset_m?offset_m[i]:0) +
- sub_offset_f[i] - (offset_f?offset_f[i]:0);
- sub_size[i] = (idx_cur[i]+1)*istore->alignment[i]-sub_offset_f[i];
- sub_offset_ch[i] = sub_offset_f[i] - udata.key.offset[i];
+
+ /* The offset and size wrt the chunk */
+ offset_wrt_chunk[i] = MAX ((offset_f?offset_f[i]:0),
+ udata.key.offset[i]) -
+ udata.key.offset[i];
+ sub_size[i] = MIN ((idx_cur[i]+1)*istore->alignment[i],
+ (offset_f?offset_f[i]:0)+size[i]) -
+ (udata.key.offset[i]+offset_wrt_chunk[i]);
+
+ /* Offset into mem buffer */
+ sub_offset_m[i] = udata.key.offset[i] + offset_wrt_chunk[i] +
+ (offset_m?offset_m[i]:0) -
+ (offset_f?offset_f[i]:0);
}
+
if (H5F_ISTORE_WRITE==op) {
status = H5B_insert (f, H5B_ISTORE, istore->btree_addr, &udata);
assert (status>=0);
@@ -605,10 +670,9 @@ H5F_istore_copy_hyperslab (H5F_t *f, const H5O_istore_t *istore, H5F_isop_t op,
* partial chunk then load the chunk from disk.
*/
if (H5F_ISTORE_READ==op ||
- !H5V_hyper_eq (istore->ndims,
- udata.key.offset, udata.key.size,
- sub_offset_f, sub_size)) {
- if (status>=0) {
+ !H5V_vector_zerop (istore->ndims, offset_wrt_chunk) ||
+ !H5V_vector_eq (istore->ndims, sub_size, udata.key.size)) {
+ if (status>=0 && udata.addr>0) {
if (H5F_block_read (f, udata.addr, chunk_size, chunk)<0) {
HGOTO_ERROR (H5E_IO, H5E_READERROR, FAIL);
}
@@ -620,7 +684,7 @@ H5F_istore_copy_hyperslab (H5F_t *f, const H5O_istore_t *istore, H5F_isop_t op,
/* Transfer data to/from the chunk */
if (H5F_ISTORE_WRITE==op) {
H5V_hyper_copy (istore->ndims, sub_size,
- udata.key.size, sub_offset_ch, chunk,
+ udata.key.size, offset_wrt_chunk, chunk,
size_m, sub_offset_m, buf);
if (H5F_block_write (f, udata.addr, chunk_size, chunk)<0) {
HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL);
@@ -628,7 +692,7 @@ H5F_istore_copy_hyperslab (H5F_t *f, const H5O_istore_t *istore, H5F_isop_t op,
} else {
H5V_hyper_copy (istore->ndims, sub_size,
size_m, sub_offset_m, buf,
- udata.key.size, sub_offset_ch, chunk);
+ udata.key.size, offset_wrt_chunk, chunk);
}
/* Increment indices */
diff --git a/src/H5F.c b/src/H5F.c
index 754be9c..a485f31 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -1191,13 +1191,14 @@ H5F_close (H5F_t *f)
herr_t ret_value = FAIL;
FUNC_ENTER (H5F_close, H5F_init_interface, FAIL);
-
+
if (-2==(ret_value=H5F_flush (f, TRUE))) {
/*objects are still open, but don't fail yet*/
} else if (ret_value<0) {
/*can't flush cache*/
HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL);
}
+ if (f->intent & H5F_ACC_DEBUG) H5AC_debug (f);
H5F_low_close (f->shared->file_handle);
H5F_dest (f);
diff --git a/src/H5Fistore.c b/src/H5Fistore.c
index 96ef5fc..06997a1 100644
--- a/src/H5Fistore.c
+++ b/src/H5Fistore.c
@@ -29,10 +29,12 @@ static hbool_t interface_initialize_g = FALSE;
/* PRIVATE PROTOTYPES */
static size_t H5F_istore_sizeof_rkey (H5F_t *f, const void *_udata);
-static haddr_t H5F_istore_new_node (H5F_t *f, void *_lt_key, void *_udata,
- void *_rt_key);
-static intn H5F_istore_cmp (H5F_t *f, void *_lt_key, void *_udata,
- void *_rt_key);
+static haddr_t H5F_istore_new_node (H5F_t *f, H5B_ins_t, void *_lt_key,
+ void *_udata, void *_rt_key);
+static intn H5F_istore_cmp2 (H5F_t *f, void *_lt_key, void *_udata,
+ void *_rt_key);
+static intn H5F_istore_cmp3 (H5F_t *f, void *_lt_key, void *_udata,
+ void *_rt_key);
static herr_t H5F_istore_found (H5F_t *f, haddr_t addr, const void *_lt_key,
void *_udata, const void *_rt_key);
static haddr_t H5F_istore_insert (H5F_t *f, haddr_t addr, H5B_ins_t *anchor,
@@ -82,7 +84,8 @@ H5B_class_t H5B_ISTORE[1] = {{
sizeof (H5F_istore_key_t), /*sizeof_nkey */
H5F_istore_sizeof_rkey, /*get_sizeof_rkey */
H5F_istore_new_node, /*new */
- H5F_istore_cmp, /*cmp */
+ H5F_istore_cmp2, /*cmp2 */
+ H5F_istore_cmp3, /*cmp3 */
H5F_istore_found, /*found */
H5F_istore_insert, /*insert */
FALSE, /*follow min branch? */
@@ -209,10 +212,51 @@ H5F_istore_encode_key (H5F_t *f, H5B_t *bt, uint8 *raw, void *_key)
FUNC_LEAVE (SUCCEED);
}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_istore_cmp2
+ *
+ * Purpose: Compares two keys sort of like strcmp(). The UDATA pointer
+ * is only to supply extra information not carried in the keys
+ * (in this case, the dimensionality).
+ *
+ * Return: Success: -1 if LT_KEY is less than RT_KEY;
+ * 1 if LT_KEY is greater than RT_KEY;
+ * 0 if LT_KEY and RT_KEY are equal.
+ *
+ * Failure: FAIL (same as LT_KEY<RT_KEY)
+ *
+ * Programmer: Robb Matzke
+ * Thursday, November 6, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static intn
+H5F_istore_cmp2 (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key)
+{
+ H5F_istore_key_t *lt_key = (H5F_istore_key_t *)_lt_key;
+ H5F_istore_key_t *rt_key = (H5F_istore_key_t *)_rt_key;
+ H5F_istore_ud1_t *udata = (H5F_istore_ud1_t *)_udata;
+ intn cmp;
+
+ FUNC_ENTER (H5F_istore_cmp2, NULL, FAIL);
+
+ assert (lt_key);
+ assert (rt_key);
+ assert (udata);
+ assert (udata->mesg.ndims>0 && udata->mesg.ndims<=H5O_ISTORE_NDIMS);
+ cmp = H5V_vector_cmp (udata->mesg.ndims, lt_key->offset, rt_key->offset);
+
+ FUNC_LEAVE (cmp);
+}
+
/*-------------------------------------------------------------------------
- * Function: H5F_istore_cmp
+ * Function: H5F_istore_cmp3
*
* Purpose: Compare the requested datum UDATA with the left and right
* keys of the B-tree.
@@ -241,11 +285,14 @@ H5F_istore_encode_key (H5F_t *f, H5B_t *bt, uint8 *raw, void *_key)
*-------------------------------------------------------------------------
*/
static intn
-H5F_istore_cmp (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key)
+H5F_istore_cmp3 (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key)
{
H5F_istore_key_t *lt_key = (H5F_istore_key_t *)_lt_key;
H5F_istore_key_t *rt_key = (H5F_istore_key_t *)_rt_key;
H5F_istore_ud1_t *udata = (H5F_istore_ud1_t *)_udata;
+ intn cmp = 0;
+
+ FUNC_ENTER (H5F_istore_cmp3, NULL, FAIL);
assert (lt_key);
assert (rt_key);
@@ -253,13 +300,13 @@ H5F_istore_cmp (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key)
assert (udata->mesg.ndims>0 && udata->mesg.ndims<=H5O_ISTORE_NDIMS);
if (H5V_vector_lt (udata->mesg.ndims, udata->key.offset, lt_key->offset)) {
- return -1;
+ cmp = -1;
} else if (H5V_vector_ge (udata->mesg.ndims, udata->key.offset,
rt_key->offset)) {
- return 1;
- } else {
- return 0;
+ cmp = 1;
}
+
+ FUNC_LEAVE (cmp);
}
@@ -283,7 +330,8 @@ H5F_istore_cmp (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key)
*-------------------------------------------------------------------------
*/
static haddr_t
-H5F_istore_new_node (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key)
+H5F_istore_new_node (H5F_t *f, H5B_ins_t op,
+ void *_lt_key, void *_udata, void *_rt_key)
{
H5F_istore_key_t *lt_key = (H5F_istore_key_t *)_lt_key;
H5F_istore_key_t *rt_key = (H5F_istore_key_t *)_rt_key;
@@ -308,16 +356,25 @@ H5F_istore_new_node (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key)
HRETURN_ERROR (H5E_IO, H5E_CANTINIT, FAIL);
}
- /* left key describes the UDATA, right key is a zero-size "edge" */
+ /* Initialize the key(s) */
for (i=0; i<udata->mesg.ndims; i++) {
+ /*
+ * The left key describes the storage of the UDATA chunk being inserted
+ * into the tree.
+ */
lt_key->offset[i] = udata->key.offset[i];
lt_key->size[i] = udata->key.size[i];
assert (udata->key.size[i]>0);
-
- rt_key->offset[i] = udata->key.offset[i] + udata->key.size[i];
- rt_key->size[i] = 0;
- }
+ /*
+ * The right key might already be present. If not, then add
+ * a zero-width chunk.
+ */
+ if (H5B_INS_LEFT!=op) {
+ rt_key->offset[i] = udata->key.offset[i] + udata->key.size[i];
+ rt_key->size[i] = 0;
+ }
+ }
FUNC_LEAVE (udata->addr);
}
@@ -351,7 +408,6 @@ H5F_istore_found (H5F_t *f, haddr_t addr, const void *_lt_key,
{
H5F_istore_ud1_t *udata = (H5F_istore_ud1_t *)_udata;
const H5F_istore_key_t *lt_key = (const H5F_istore_key_t *)_lt_key;
- const H5F_istore_key_t *rt_key = (const H5F_istore_key_t *)_rt_key;
int i;
FUNC_ENTER (H5F_istore_found, NULL, FAIL);
@@ -361,7 +417,6 @@ H5F_istore_found (H5F_t *f, haddr_t addr, const void *_lt_key,
assert (addr>=0);
assert (udata);
assert (lt_key);
- assert (rt_key);
/* Initialize return values */
udata->addr = addr;
@@ -434,7 +489,7 @@ H5F_istore_insert (H5F_t *f, haddr_t addr, H5B_ins_t *parent_ins,
assert (rt_key);
assert (rt_key_changed);
- cmp = H5F_istore_cmp (f, lt_key, udata, rt_key);
+ cmp = H5F_istore_cmp3 (f, lt_key, udata, rt_key);
assert (cmp<=0);
if (cmp<0) {
@@ -531,9 +586,8 @@ H5F_istore_copy_hyperslab (H5F_t *f, const H5O_istore_t *istore, H5F_isop_t op,
size_t idx_min[H5O_ISTORE_NDIMS];
size_t idx_max[H5O_ISTORE_NDIMS];
size_t sub_size[H5O_ISTORE_NDIMS];
- size_t sub_offset_f[H5O_ISTORE_NDIMS];
+ size_t offset_wrt_chunk[H5O_ISTORE_NDIMS];
size_t sub_offset_m[H5O_ISTORE_NDIMS];
- size_t sub_offset_ch[H5O_ISTORE_NDIMS];
size_t chunk_size;
uint8 *chunk=NULL;
H5F_istore_ud1_t udata;
@@ -585,14 +639,25 @@ H5F_istore_copy_hyperslab (H5F_t *f, const H5O_istore_t *istore, H5F_isop_t op,
/* Read/Write chunk or create it if it doesn't exist */
udata.mesg.ndims = istore->ndims;
for (i=0; i<istore->ndims; i++) {
+
+ /* The location and size of the chunk being accessed */
udata.key.offset[i] = idx_cur[i] * istore->alignment[i];
udata.key.size[i] = istore->alignment[i];
- sub_offset_f[i] = MAX ((offset_f?offset_f[i]:0), udata.key.offset[i]);
- sub_offset_m[i] = (offset_m?offset_m[i]:0) +
- sub_offset_f[i] - (offset_f?offset_f[i]:0);
- sub_size[i] = (idx_cur[i]+1)*istore->alignment[i]-sub_offset_f[i];
- sub_offset_ch[i] = sub_offset_f[i] - udata.key.offset[i];
+
+ /* The offset and size wrt the chunk */
+ offset_wrt_chunk[i] = MAX ((offset_f?offset_f[i]:0),
+ udata.key.offset[i]) -
+ udata.key.offset[i];
+ sub_size[i] = MIN ((idx_cur[i]+1)*istore->alignment[i],
+ (offset_f?offset_f[i]:0)+size[i]) -
+ (udata.key.offset[i]+offset_wrt_chunk[i]);
+
+ /* Offset into mem buffer */
+ sub_offset_m[i] = udata.key.offset[i] + offset_wrt_chunk[i] +
+ (offset_m?offset_m[i]:0) -
+ (offset_f?offset_f[i]:0);
}
+
if (H5F_ISTORE_WRITE==op) {
status = H5B_insert (f, H5B_ISTORE, istore->btree_addr, &udata);
assert (status>=0);
@@ -605,10 +670,9 @@ H5F_istore_copy_hyperslab (H5F_t *f, const H5O_istore_t *istore, H5F_isop_t op,
* partial chunk then load the chunk from disk.
*/
if (H5F_ISTORE_READ==op ||
- !H5V_hyper_eq (istore->ndims,
- udata.key.offset, udata.key.size,
- sub_offset_f, sub_size)) {
- if (status>=0) {
+ !H5V_vector_zerop (istore->ndims, offset_wrt_chunk) ||
+ !H5V_vector_eq (istore->ndims, sub_size, udata.key.size)) {
+ if (status>=0 && udata.addr>0) {
if (H5F_block_read (f, udata.addr, chunk_size, chunk)<0) {
HGOTO_ERROR (H5E_IO, H5E_READERROR, FAIL);
}
@@ -620,7 +684,7 @@ H5F_istore_copy_hyperslab (H5F_t *f, const H5O_istore_t *istore, H5F_isop_t op,
/* Transfer data to/from the chunk */
if (H5F_ISTORE_WRITE==op) {
H5V_hyper_copy (istore->ndims, sub_size,
- udata.key.size, sub_offset_ch, chunk,
+ udata.key.size, offset_wrt_chunk, chunk,
size_m, sub_offset_m, buf);
if (H5F_block_write (f, udata.addr, chunk_size, chunk)<0) {
HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL);
@@ -628,7 +692,7 @@ H5F_istore_copy_hyperslab (H5F_t *f, const H5O_istore_t *istore, H5F_isop_t op,
} else {
H5V_hyper_copy (istore->ndims, sub_size,
size_m, sub_offset_m, buf,
- udata.key.size, sub_offset_ch, chunk);
+ udata.key.size, offset_wrt_chunk, chunk);
}
/* Increment indices */
diff --git a/src/H5Flow.c b/src/H5Flow.c
index 6a7de9c..18cc417 100644
--- a/src/H5Flow.c
+++ b/src/H5Flow.c
@@ -108,8 +108,11 @@ H5F_low_close (H5F_low_t *lf)
{
FUNC_ENTER (H5F_low_close, NULL, NULL);
- if (lf && (lf->type->close)(lf)<0) {
- HRETURN_ERROR (H5E_IO, H5E_CLOSEERROR, NULL); /*close failed*/
+ if (lf) {
+ if ((lf->type->close)(lf)<0) {
+ H5MM_xfree (lf);
+ HRETURN_ERROR (H5E_IO, H5E_CLOSEERROR, NULL); /*close failed*/
+ }
H5MM_xfree (lf);
}
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
index ae7e75c..6eb6dd9 100644
--- a/src/H5Fprivate.h
+++ b/src/H5Fprivate.h
@@ -51,6 +51,7 @@
#define H5F_ACC_CREAT 0x0002 /* Create non-existing files */
#define H5F_ACC_EXCL 0x0004 /* Fail if file exists */
#define H5F_ACC_TRUNC 0x0008 /* Truncate existing file */
+#define H5F_ACC_DEBUG 0x00010 /* Print debug info */
/*
@@ -138,22 +139,22 @@
/* WE DON'T CHECK FOR OVERFLOW! */ \
int64 _n = 0; \
intn _i; \
- uint8 *_p = (uint8*)(p)+8; \
+ (p) += 8; \
for (_i=0; _i<sizeof(int64); _i++, _n<<=8) { \
- _n |= *(--_p); \
+ _n |= *(--p); \
} \
- (p) = (uint8*)(p)+8; \
+ (p) += 8; \
}
# define UINT64DECODE(p, n) { \
/* WE DON'T CHECK FOR OVERFLOW! */ \
uint64 _n = 0; \
intn _i; \
- uint8 *_p = (uint8*)(p)+8; \
+ (p) += 8; \
for (_i=0; _i<sizeof(uint64); _i++, _n<<=8) { \
- _n |= *(--_p); \
+ _n |= *(--p); \
} \
- (p) = (uint8*)(p)+8; \
+ (p) += 8; \
}
#else
diff --git a/src/H5Fstdio.c b/src/H5Fstdio.c
index cd47f3a..cc8f4c6 100644
--- a/src/H5Fstdio.c
+++ b/src/H5Fstdio.c
@@ -182,7 +182,7 @@ H5F_stdio_read (H5F_low_t *lf, haddr_t addr, size_t size, uint8 *buf)
* Seek to the correct file position.
*/
if (!H5F_OPT_SEEK ||
- lf->u.stdio.op==H5F_OP_UNKNOWN ||
+ lf->u.stdio.op!=H5F_OP_READ ||
lf->u.stdio.cur!=addr) {
if (fseek (lf->u.stdio.f, addr, SEEK_SET)<0) {
HRETURN_ERROR (H5E_IO, H5E_SEEKERROR, FAIL); /*fseek failed*/
@@ -237,13 +237,15 @@ H5F_stdio_read (H5F_low_t *lf, haddr_t addr, size_t size, uint8 *buf)
static herr_t
H5F_stdio_write (H5F_low_t *lf, haddr_t addr, size_t size, const uint8 *buf)
{
+ int status;
+
FUNC_ENTER (H5F_stdio_write, NULL, FAIL);
/*
* Seek to the correct file position.
*/
if (!H5F_OPT_SEEK ||
- lf->u.stdio.op==H5F_OP_UNKNOWN ||
+ lf->u.stdio.op!=H5F_OP_WRITE ||
lf->u.stdio.cur!=addr) {
if (fseek (lf->u.stdio.f, addr, SEEK_SET)<0) {
HRETURN_ERROR (H5E_IO, H5E_SEEKERROR, FAIL); /*fseek failed*/
@@ -256,7 +258,8 @@ H5F_stdio_write (H5F_low_t *lf, haddr_t addr, size_t size, const uint8 *buf)
* advanced by the number of bytes read. Otherwise nobody knows where it
* is.
*/
- if (size != fwrite (buf, 1, size, lf->u.stdio.f)) {
+ status = fwrite (buf, 1, size, lf->u.stdio.f);
+ if (size != status) {
lf->u.stdio.op = H5F_OP_UNKNOWN;
HRETURN_ERROR (H5E_IO, H5E_WRITEERROR, FAIL); /*fwrite failed*/
}
diff --git a/src/H5Gnode.c b/src/H5Gnode.c
index 58c924c..f578783 100644
--- a/src/H5Gnode.c
+++ b/src/H5Gnode.c
@@ -44,14 +44,16 @@ static herr_t H5G_node_decode_key (H5F_t *f, H5B_t *bt, uint8 *raw,
static herr_t H5G_node_encode_key (H5F_t *f, H5B_t *bt, uint8 *raw,
void *_key);
static size_t H5G_node_size (H5F_t *f);
-static haddr_t H5G_node_new (H5F_t *f, void *_lt_key, void *_udata,
- void *_rt_key);
+static haddr_t H5G_node_new (H5F_t *f, H5B_ins_t op, void *_lt_key,
+ void *_udata, void *_rt_key);
static herr_t H5G_node_flush (H5F_t *f, hbool_t destroy, haddr_t addr,
H5G_node_t *sym);
-static H5G_node_t *H5G_node_load (H5F_t *f, haddr_t addr, void *_udata1,
+static H5G_node_t *H5G_node_load (H5F_t *f, haddr_t addr, const void *_udata1,
void *_udata2);
-static intn H5G_node_cmp (H5F_t *f, void *_lt_key, void *_udata,
- void *_rt_key);
+static intn H5G_node_cmp2 (H5F_t *f, void *_lt_key, void *_udata,
+ void *_rt_key);
+static intn H5G_node_cmp3 (H5F_t *f, void *_lt_key, void *_udata,
+ void *_rt_key);
static herr_t H5G_node_found (H5F_t *f, haddr_t addr,
const void *_lt_key, void *_udata,
const void *_rt_key);
@@ -64,8 +66,9 @@ static size_t H5G_node_sizeof_rkey (H5F_t *f, const void *_udata);
/* H5G inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_SNODE[1] = {{
- (void*(*)(H5F_t*,haddr_t,void*,void*))H5G_node_load,
- (herr_t(*)(H5F_t*,hbool_t,haddr_t,void*))H5G_node_flush,
+ H5AC_SNODE_ID,
+ (void*(*)(H5F_t*,haddr_t,const void*,void*))H5G_node_load,
+ (herr_t(*)(H5F_t*,hbool_t,haddr_t,void*))H5G_node_flush,
}};
/* H5G inherits B-tree like properties from H5B */
@@ -74,7 +77,8 @@ H5B_class_t H5B_SNODE[1] = {{
sizeof (H5G_node_key_t), /*sizeof_nkey */
H5G_node_sizeof_rkey, /*get_sizeof_rkey */
H5G_node_new, /*new */
- H5G_node_cmp, /*cmp */
+ H5G_node_cmp2, /*cmp2 */
+ H5G_node_cmp3, /*cmp3 */
H5G_node_found, /*found */
H5G_node_insert, /*insert */
TRUE, /*follow min branch? */
@@ -227,7 +231,8 @@ H5G_node_size (H5F_t *f)
*-------------------------------------------------------------------------
*/
static haddr_t
-H5G_node_new (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key)
+H5G_node_new (H5F_t *f, H5B_ins_t op,
+ void *_lt_key, void *_udata, void *_rt_key)
{
H5G_node_key_t *lt_key = (H5G_node_key_t*)_lt_key;
H5G_node_key_t *rt_key = (H5G_node_key_t*)_rt_key;
@@ -241,6 +246,7 @@ H5G_node_new (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key)
* Check arguments.
*/
assert (f);
+ assert (H5B_INS_FIRST==op);
sym = H5MM_xcalloc (1, sizeof(H5G_node_t));
size = H5G_node_size (f);
@@ -383,12 +389,12 @@ H5G_node_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5G_node_t *sym)
*-------------------------------------------------------------------------
*/
static H5G_node_t *
-H5G_node_load (H5F_t *f, haddr_t addr, void *_udata1, void *_udata2)
+H5G_node_load (H5F_t *f, haddr_t addr, const void *_udata1, void *_udata2)
{
H5G_node_t *sym = NULL;
size_t size = 0;
uint8 *buf = NULL, *p = NULL;
- H5G_ac_ud1_t *ac_udata = (H5G_ac_ud1_t*)_udata1;
+ const H5G_ac_ud1_t *ac_udata = (const H5G_ac_ud1_t*)_udata1;
H5G_node_t *ret_value = NULL; /*for error handling*/
FUNC_ENTER (H5G_node_load, NULL, NULL);
@@ -457,7 +463,58 @@ H5G_node_load (H5F_t *f, haddr_t addr, void *_udata1, void *_udata2)
/*-------------------------------------------------------------------------
- * Function: H5G_node_cmp
+ * Function: H5G_node_cmp2
+ *
+ * Purpose: Compares two keys from a B-tree node (LT_KEY and RT_KEY).
+ * The UDATA pointer supplies extra data not contained in the
+ * keys (in this case, the heap address).
+ *
+ * Return: Success: negative if LT_KEY is less than RT_KEY.
+ *
+ * positive if LT_KEY is greater than RT_KEY.
+ *
+ * zero if LT_KEY and RT_KEY are equal.
+ *
+ * Failure: FAIL (same as LT_KEY<RT_KEY)
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Jun 23 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static intn
+H5G_node_cmp2 (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key)
+{
+ H5G_bt_ud1_t *udata = (H5G_bt_ud1_t *)_udata;
+ H5G_node_key_t *lt_key = (H5G_node_key_t *)_lt_key;
+ H5G_node_key_t *rt_key = (H5G_node_key_t *)_rt_key;
+ const char *s1, *s2;
+ intn cmp;
+
+ FUNC_ENTER (H5G_node_cmp2, NULL, FAIL);
+
+ assert (udata);
+ assert (lt_key);
+ assert (rt_key);
+
+ if (NULL==(s1=H5H_peek (f, udata->heap_addr, lt_key->offset))) {
+ HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL);
+ }
+ if (NULL==(s2=H5H_peek (f, udata->heap_addr, rt_key->offset))) {
+ HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL);
+ }
+
+ cmp = HDstrcmp (s1, s2);
+
+ FUNC_LEAVE (cmp);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_node_cmp3
*
* Purpose: Compares two keys from a B-tree node (LT_KEY and RT_KEY)
* against another key (not necessarily the same type)
@@ -484,14 +541,14 @@ H5G_node_load (H5F_t *f, haddr_t addr, void *_udata1, void *_udata2)
*-------------------------------------------------------------------------
*/
static intn
-H5G_node_cmp (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key)
+H5G_node_cmp3 (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key)
{
H5G_bt_ud1_t *udata = (H5G_bt_ud1_t *)_udata;
H5G_node_key_t *lt_key = (H5G_node_key_t *)_lt_key;
H5G_node_key_t *rt_key = (H5G_node_key_t *)_rt_key;
const char *s;
- FUNC_ENTER (H5G_node_cmp, NULL, FAIL);
+ FUNC_ENTER (H5G_node_cmp3, NULL, FAIL);
/* left side */
if (NULL==(s=H5H_peek (f, udata->heap_addr, lt_key->offset))) {
@@ -747,7 +804,7 @@ H5G_node_insert (H5F_t *f, haddr_t addr, H5B_ins_t *anchor,
*anchor = H5B_INS_RIGHT;
/* The right node */
- if ((new_node = H5G_node_new (f, NULL, NULL, NULL))<0) {
+ if ((new_node = H5G_node_new (f, H5B_INS_FIRST, NULL, NULL, NULL))<0) {
HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL);
}
if (NULL==(snrt=H5AC_find (f, H5AC_SNODE, new_node, &ac_udata, NULL))) {
@@ -841,7 +898,8 @@ done:
NULL))) {
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL);
}
- assert (sn==bt_udata->node_ptr);
+ bt_udata->node_ptr = sn;
+ bt_udata->entry_ptr = sn->entry + idx;
} else {
/* keep the node protected until we get back to H5G_stab_insert() */
}
@@ -991,7 +1049,7 @@ H5G_node_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent,
* If we couldn't load the symbol table node, then try loading the
* B-tree node.
*/
- if (NULL==(sn=H5AC_find(f, H5AC_SNODE, addr, &ac_udata, NULL))) {
+ if (NULL==(sn=H5AC_protect(f, H5AC_SNODE, addr, &ac_udata, NULL))) {
H5ECLEAR; /*discard that error*/
status = H5B_debug (f, addr, stream, indent, fwidth, H5B_SNODE, NULL);
if (status<0) HRETURN_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL);
@@ -1028,6 +1086,7 @@ H5G_node_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent,
sn->entry[i].shadow ? "Yes":"No");
}
+ H5AC_unprotect (f, H5AC_SNODE, addr, sn);
H5AC_flush (f, H5AC_SNODE, addr, TRUE); /*see note above*/
FUNC_LEAVE (SUCCEED);
}
diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h
index 9421541..0e5db33 100644
--- a/src/H5Gpkg.h
+++ b/src/H5Gpkg.h
@@ -176,7 +176,7 @@ herr_t H5G_shadow_close (H5F_t *f, H5G_entry_t *ent);
hbool_t H5G_shadow_p (H5G_entry_t *ent);
herr_t H5G_shadow_dissociate (H5G_entry_t *ent);
herr_t H5G_shadow_assoc_node (H5F_t *f, H5G_node_t *sym,
- H5G_ac_ud1_t *ac_udata);
+ const H5G_ac_ud1_t *ac_udata);
H5G_shadow_t *H5G_shadow_list (H5F_t *f, haddr_t stab_header_addr);
herr_t H5G_shadow_move (H5F_t *f, H5G_shadow_t *shadow,
const char *new_name, H5G_entry_t *new_entry,
diff --git a/src/H5Gshad.c b/src/H5Gshad.c
index 875f880..253e01e 100644
--- a/src/H5Gshad.c
+++ b/src/H5Gshad.c
@@ -299,7 +299,7 @@ H5G_shadow_list (H5F_t *f, haddr_t grp_addr)
*-------------------------------------------------------------------------
*/
herr_t
-H5G_shadow_assoc_node (H5F_t *f, H5G_node_t *sym, H5G_ac_ud1_t *ac_udata)
+H5G_shadow_assoc_node (H5F_t *f, H5G_node_t *sym, const H5G_ac_ud1_t *ac_udata)
{
H5G_shadow_t *shadow = NULL;
const char *s = NULL;
@@ -395,7 +395,21 @@ H5G_shadow_open (H5F_t *f, H5G_entry_t *grp, H5G_entry_t *ent)
}
+ /*
+ * Build the new shadow.
+ */
shadow = H5MM_xcalloc (1, sizeof(H5G_shadow_t));
+ ent->shadow = shadow;
+ shadow->main = ent;
+ shadow->nrefs = 1;
+ shadow->entry = *ent;
+ shadow->entry.dirty = FALSE;
+ shadow->grp_addr = grp_addr;
+
+ /*
+ * Give the shadow a name. Obtaining the name might remove ENT from the
+ * cache, so we're careful not to reference it again.
+ */
if (ent==f->shared->root_sym && 0==grp_addr) {
/*
* We're opening the root entry.
@@ -419,16 +433,8 @@ H5G_shadow_open (H5F_t *f, H5G_entry_t *grp, H5G_entry_t *ent)
}
shadow->name = H5MM_xstrdup (s);
}
-
- /*
- * Build the new shadow.
- */
- ent->shadow = shadow;
- shadow->main = ent;
- shadow->nrefs = 1;
- shadow->entry = *ent;
- shadow->entry.dirty = FALSE;
- shadow->grp_addr = grp_addr;
+ ent = NULL; /*previous ops might have invalidated it*/
+
/*
* Link it into the shadow heap
diff --git a/src/H5Gstab.c b/src/H5Gstab.c
index 7acaa13..46f1eeb 100644
--- a/src/H5Gstab.c
+++ b/src/H5Gstab.c
@@ -267,7 +267,7 @@ H5G_stab_insert (H5F_t *f, H5G_entry_t *self, const char *name,
if (H5AC_unprotect (f, H5AC_SNODE, udata.node_addr, udata.node_ptr)<0) {
HRETURN_ERROR (H5E_SYM, H5E_PROTECT, NULL); /*can't unprotect*/
}
-
+
/* update the name offset in the entry */
ent->name_off = udata.entry.name_off;
FUNC_LEAVE (udata.entry_ptr);
diff --git a/src/H5H.c b/src/H5H.c
index 4c44613..e1453e5 100644
--- a/src/H5H.c
+++ b/src/H5H.c
@@ -45,14 +45,16 @@ typedef struct H5H_t {
} H5H_t;
/* PRIVATE PROTOTYPES */
-static H5H_t *H5H_load (H5F_t *f, haddr_t addr, void *udata1, void *udata2);
+static H5H_t *H5H_load (H5F_t *f, haddr_t addr, const void *udata1,
+ void *udata2);
static herr_t H5H_flush (H5F_t *f, hbool_t dest, haddr_t addr, H5H_t *heap);
/*
* H5H inherits cache-like properties from H5AC
*/
static const H5AC_class_t H5AC_HEAP[1] = {{
- (void*(*)(H5F_t*,haddr_t,void*,void*))H5H_load,
+ H5AC_HEAP_ID,
+ (void*(*)(H5F_t*,haddr_t,const void*,void*))H5H_load,
(herr_t(*)(H5F_t*,hbool_t,haddr_t,void*))H5H_flush,
}};
@@ -161,7 +163,7 @@ H5H_new (H5F_t *f, H5H_type_t heap_type, size_t size_hint)
*-------------------------------------------------------------------------
*/
static H5H_t *
-H5H_load (H5F_t *f, haddr_t addr, void *udata1, void *udata2)
+H5H_load (H5F_t *f, haddr_t addr, const void *udata1, void *udata2)
{
uint8 hdr[20], *p;
H5H_t *heap=NULL;
diff --git a/src/H5O.c b/src/H5O.c
index 9130de3..43faa6c 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -26,7 +26,8 @@
/* PRIVATE PROTOTYPES */
static herr_t H5O_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5O_t *oh);
-static H5O_t *H5O_load (H5F_t *f, haddr_t addr, void *_udata1, void *_udata2);
+static H5O_t *H5O_load (H5F_t *f, haddr_t addr, const void *_udata1,
+ void *_udata2);
static intn H5O_find_in_ohdr (H5F_t *f, haddr_t addr,
const H5O_class_t **type_p, intn sequence);
static intn H5O_alloc (H5F_t *f, H5O_t *oh, const H5O_class_t *type,
@@ -36,7 +37,8 @@ static intn H5O_alloc_new_chunk (H5F_t *f, H5O_t *oh, size_t size);
/* H5O inherits cache-like properties from H5AC */
static const H5AC_class_t H5AC_OHDR[1] = {{
- (void*(*)(H5F_t*,haddr_t,void*,void*))H5O_load,
+ H5AC_OHDR_ID,
+ (void*(*)(H5F_t*,haddr_t,const void*,void*))H5O_load,
(herr_t(*)(H5F_t*,hbool_t,haddr_t,void*))H5O_flush,
}};
@@ -165,7 +167,7 @@ H5O_new (H5F_t *f, intn nlink, size_t size_hint)
*-------------------------------------------------------------------------
*/
static H5O_t *
-H5O_load (H5F_t *f, haddr_t addr, void *_udata1, void *_udata2)
+H5O_load (H5F_t *f, haddr_t addr, const void *_udata1, void *_udata2)
{
H5O_t *oh = NULL;
H5O_t *ret_value = (void*)1; /*kludge for HGOTO_ERROR*/
diff --git a/src/H5V.c b/src/H5V.c
index e5ad09e..7612ad9 100644
--- a/src/H5V.c
+++ b/src/H5V.c
@@ -298,7 +298,9 @@ H5V_hyper_fill (size_t n, const size_t *_size,
size_t dst_start; /*byte offset to start of stride*/
size_t elmt_size=1; /*bytes per element */
herr_t status; /*function return status */
+#ifndef NDEBUG
int i;
+#endif
FUNC_ENTER (H5V_hyper_fill, NULL, FAIL);
@@ -382,7 +384,9 @@ H5V_hyper_copy (size_t n, const size_t *_size,
size_t dst_start, src_start; /*offset to start at */
size_t elmt_size=1; /*element size in bytes */
herr_t status; /*return status */
+#ifndef NDEBUG
intn i;
+#endif
FUNC_ENTER (H5V_hyper_copy, NULL, FAIL);
diff --git a/test/istore.c b/test/istore.c
index e79696c..c50ef3f 100644
--- a/test/istore.c
+++ b/test/istore.c
@@ -527,7 +527,8 @@ main (int argc, char *argv[])
/* Create the test file */
if (NULL==(f=H5F_open (H5F_LOW_DFLT, FILENAME,
- H5F_ACC_CREAT|H5F_ACC_WRITE|H5F_ACC_TRUNC,
+ (H5F_ACC_CREAT|H5F_ACC_WRITE|H5F_ACC_TRUNC|
+ H5F_ACC_DEBUG),
NULL))) {
printf ("Cannot create file %s; test aborted\n", FILENAME);
exit (1);
diff --git a/test/tstab.c b/test/tstab.c
index d2f6de4..9bac3b7 100644
--- a/test/tstab.c
+++ b/test/tstab.c
@@ -238,6 +238,7 @@ test_2 (void)
CHECK (fid, FAIL, "H5Fcreate");
f = H5Aatom_object (fid);
CHECK (f, NULL, "H5Aatom_object");
+ f->intent |= H5F_ACC_DEBUG;
/*
* Create a directory that has so many entries that the root