summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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
an>hid_t class_id) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(H5Eunregister_class, FAIL) H5TRACE1("e","i",class_id); /* Check arguments */ if (H5I_ERROR_CLASS != H5I_get_type(class_id)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an error class") /* * Decrement the counter on the dataset. It will be freed if the count * reaches zero. */ if(H5I_dec_ref(class_id)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTDEC, FAIL, "unable to decrement ref count on error class") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_unregister_class * * Purpose: Private function to close an error class. * * Return: Non-negative value on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 11, 2003 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t H5E_unregister_class(H5E_cls_t *cls) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5E_unregister_class, FAIL) /* Check arguments */ assert(cls); /* Iterate over all the messages and delete those in this error class */ /* (Ignore return value, since callback isn't designed to return a particular object) */ (void)H5I_search(H5I_ERROR_MSG, H5E_close_msg_cb, cls); /* Free error class structure */ if(cls->cls_name) H5MM_xfree((void*)cls->cls_name); if(cls->lib_name) H5MM_xfree((void*)cls->lib_name); if(cls->lib_vers) H5MM_xfree((void*)cls->lib_vers); H5MM_xfree((void*)cls); done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5Eget_class_name * * Purpose: Retrieves error class name. * * Return: Non-negative for name length if succeeds(zero means no name); * otherwise returns negative value. * * Programmer: Raymond Lu * Friday, July 11, 2003 * * Modifications: * *------------------------------------------------------------------------- */ ssize_t H5Eget_class_name(hid_t class_id, char *name, size_t size) { H5E_cls_t *cls; /* Pointer to error class */ ssize_t ret_value; /* Return value */ FUNC_ENTER_API(H5Eget_class_name, FAIL) H5TRACE3("Zs","isz",class_id,name,size); /* Get the error class */ if(NULL==(cls = H5I_object_verify(class_id, H5I_ERROR_CLASS))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error class ID") /* Retrieve the class name */ if((ret_value = H5E_get_class_name(cls, name, size))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get error class name") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_get_class_name * * Purpose: Private function to retrieve error class name. * * Return: Non-negative for name length if succeeds(zero means no name); * otherwise returns negative value. * * Programmer: Raymond Lu * Friday, July 11, 2003 * * Modifications: * *------------------------------------------------------------------------- */ static ssize_t H5E_get_class_name(const H5E_cls_t *cls, char *name, size_t size) { ssize_t len; /* Length of rror class's name */ ssize_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5E_get_class_name, FAIL) /* Check arguments */ assert(cls); /* Get the class's name */ len = (ssize_t)HDstrlen(cls->cls_name); /* Set the user's buffer, if provided */ if(name) { HDstrncpy(name, cls->cls_name, MIN((size_t)(len+1), size)); if((size_t)len >= size) name[size-1]='\0'; } /* Return the full length */ ret_value = len; done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_close_msg_cb * * Purpose: H5I_search callback function to close error messages in the * error class. * * Programmer: Raymond Lu * July 14, 2003 * * Return: Non-negative value on success/Negative on failure * * Modifications: * *------------------------------------------------------------------------- */ static int H5E_close_msg_cb(void *obj_ptr, hid_t obj_id, void *key) { H5E_msg_t *err_msg = (H5E_msg_t*)obj_ptr; H5E_cls_t *cls = (H5E_cls_t*)key; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5E_close_msg_cb, FAIL) /* Check arguments */ assert(err_msg); /* Close the message if it is in the class being closed */ if(err_msg->cls == cls) if(H5I_dec_ref(obj_id)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTDEC, FAIL, "unable to decrement ref count on error message") done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5Eclose_msg * * Purpose: Closes a major or minor error. * * Return: Non-negative value on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 11, 2003 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5Eclose_msg(hid_t err_id) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(H5Eclose_msg, FAIL) H5TRACE1("e","i",err_id); /* Check arguments */ if (H5I_ERROR_MSG != H5I_get_type(err_id)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an error class") /* Decrement the counter. It will be freed if the count reaches zero. */ if(H5I_dec_ref(err_id)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTDEC, FAIL, "unable to decrement ref count on error message") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_close_msg * * Purpose: Private function to close an error messge. * * Return: Non-negative value on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 11, 2003 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t H5E_close_msg(H5E_msg_t *err) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5E_close_msg, FAIL) /* Check arguments */ assert(err); if(err->msg) H5MM_xfree((void*)err->msg); /* Don't free err->cls here */ H5MM_xfree((void*)err); done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5Ecreate_msg * * Purpose: Creates a major or minor error, returns an ID. * * Return: Non-negative value on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 11, 2003 * * Modifications: * *------------------------------------------------------------------------- */ hid_t H5Ecreate_msg(hid_t class_id, H5E_type_t msg_type, const char *msg_str) { H5E_cls_t *cls; /* Pointer to error class */ H5E_msg_t *msg; /* Pointer to new error message */ hid_t ret_value; /* Return value */ FUNC_ENTER_API(H5Ecreate_msg, FAIL) H5TRACE3("i","iEts",class_id,msg_type,msg_str); /* Check arguments */ if(msg_type!=H5E_MAJOR && msg_type!=H5E_MINOR) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a valid message type") if(msg_str==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "message is NULL") /* Get the error class */ if(NULL==(cls = H5I_object_verify(class_id, H5I_ERROR_CLASS))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error class ID") /* Create the new error message object */ if((msg = H5E_create_msg(cls, msg_type, msg_str))==NULL) HGOTO_ERROR(H5E_ERROR, H5E_CANTCREATE, FAIL, "can't create error message") /* Register the new error class to get an ID for it */ if((ret_value = H5I_register(H5I_ERROR_MSG, msg))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_create_msg * * Purpose: Private function to create a major or minor error. * * Return: Non-negative value on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 11, 2003 * * Modifications: * *------------------------------------------------------------------------- */ static H5E_msg_t * H5E_create_msg(H5E_cls_t *cls, H5E_type_t msg_type, const char *msg_str) { H5E_msg_t *msg; /* Pointer to new error message */ H5E_msg_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5E_create_msg, NULL) /* Check arguments */ assert(cls); assert(msg_type==H5E_MAJOR || msg_type==H5E_MINOR); assert(msg_str); /* Allocate new message object */ if((msg = H5MM_malloc(sizeof(H5E_msg_t)))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Fill new message object */ msg->cls = cls; msg->type = msg_type; if((msg->msg = HDstrdup(msg_str))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Set return value */ ret_value = msg; done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5Eget_major * * Purpose: Retrieves a major error message. * * Return: Returns message if succeeds. * otherwise returns NULL. * * Programmer: Raymond Lu * Friday, July 14, 2003 * * Modifications: * *------------------------------------------------------------------------- */ const char * H5Eget_major(H5E_major_t maj) { H5E_msg_t *msg; /* Pointer to error message */ ssize_t size = 0; /* Return value */ H5E_type_t type; char *msg_str; char *ret_value = NULL; FUNC_ENTER_API_NOCLEAR(H5Eget_major,NULL) /* Get the message object */ if((msg = H5I_object_verify(maj, H5I_ERROR_MSG))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a error message ID") /* Get the message's text */ if((size = H5E_get_msg(msg, &type, NULL, 0))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, NULL, "can't get error message text"); if(type != H5E_MAJOR) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, NULL, "Error message isn't a major one"); /* Don't know who is going to free it */ msg_str = (char*)H5MM_malloc((size_t)(++size)*sizeof(char)); if(H5E_get_msg(msg, NULL, msg_str, (size_t)size)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, NULL, "can't get error message text") ret_value = msg_str; done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5Eget_minor * * Purpose: Retrieves a minor error message. * * Return: Returns message if succeeds. * otherwise returns NULL. * * Programmer: Raymond Lu * Friday, July 14, 2003 * * Modifications: * *------------------------------------------------------------------------- */ const char * H5Eget_minor(H5E_minor_t min) { H5E_msg_t *msg; /* Pointer to error message */ ssize_t size = 0; /* Return value */ H5E_type_t type; char *msg_str; char *ret_value = NULL; FUNC_ENTER_API_NOCLEAR(H5Eget_minor,NULL) /* Get the message object */ if((msg = H5I_object_verify(min, H5I_ERROR_MSG))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a error message ID") /* Get the message's text */ if((size = H5E_get_msg(msg, &type, NULL, 0))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, NULL, "can't get error message text"); if(type != H5E_MINOR) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, NULL, "Error message isn't a minor one"); /* Don't know who is going to free it */ msg_str = (char*)H5MM_malloc((size_t)(++size)*sizeof(char)); if(H5E_get_msg(msg, NULL, msg_str, (size_t)size)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, NULL, "can't get error message text") ret_value = msg_str; done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5Eget_msg * * Purpose: Retrieves an error message. * * Return: Non-negative for message length if succeeds(zero means no message); * otherwise returns negative value. * * Programmer: Raymond Lu * Friday, July 14, 2003 * * Modifications: * *------------------------------------------------------------------------- */ ssize_t H5Eget_msg(hid_t msg_id, H5E_type_t *type, char *msg_str, size_t size) { H5E_msg_t *msg; /* Pointer to error message */ ssize_t ret_value; /* Return value */ FUNC_ENTER_API(H5Eget_msg, FAIL) H5TRACE4("Zs","i*Etsz",msg_id,type,msg_str,size); /* Get the message object */ if((msg = H5I_object_verify(msg_id, H5I_ERROR_MSG))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error message ID") /* Get the message's text */ if((ret_value = H5E_get_msg(msg, type, msg_str, size))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get error message text") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_get_msg * * Purpose: Private function to retrieve an error message. * * Return: Non-negative for name length if succeeds(zero means no name); * otherwise returns negative value. * * Programmer: Raymond Lu * Friday, July 14, 2003 * * Modifications: * *------------------------------------------------------------------------- */ static ssize_t H5E_get_msg(const H5E_msg_t *msg, H5E_type_t *type, char *msg_str, size_t size) { ssize_t len; /* Length of rror class's name */ ssize_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5E_get_msg, FAIL) /* Check arguments */ assert(msg); /* Get the length of the message string */ len = (ssize_t)HDstrlen(msg->msg); /* Copy the message into the user's buffer, if given */ if(msg_str) { HDstrncpy(msg_str, msg->msg, MIN((size_t)(len+1), size)); if((size_t)len >= size) msg_str[size-1]='\0'; } /* Give the message type, if asked */ if(type) *type = msg->type; /* Set the return value to the full length of the message */ ret_value = len; done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5Eget_current_stack * * Purpose: Registers current error stack, returns object handle for it, * clears it. * * Return: Non-negative value as stack ID on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 14, 2003 * * Modifications: * *------------------------------------------------------------------------- */ hid_t H5Eget_current_stack(void) { H5E_t *stk; /* Error stack */ hid_t ret_value; /* Return value */ /* Don't clear the error stack! :-) */ FUNC_ENTER_API_NOCLEAR(H5Eget_current_stack, FAIL) H5TRACE0("i",""); /* Get the current stack */ if((stk=H5E_get_current_stack())==NULL) HGOTO_ERROR(H5E_ERROR, H5E_CANTCREATE, FAIL, "can't create error stack") /* Register the stack */ if((ret_value = H5I_register(H5I_ERROR_STACK, stk))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't create error stack") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_get_current_stack * * Purpose: Private function to register an error stack. * * Return: Non-negative value as class ID on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 11, 2003 * * Modifications: * *------------------------------------------------------------------------- */ static H5E_t * H5E_get_current_stack(void) { H5E_t *current_stack; /* Pointer to the current error stack */ H5E_t *estack_copy=NULL; /* Pointer to new error stack to return */ unsigned u; /* Local index variable */ H5E_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5E_get_current_stack, NULL) /* Get a pointer to the current error stack */ if((current_stack = H5E_get_my_stack ())==NULL) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, NULL, "can't get current error stack") /* Allocate a new error stack */ if((estack_copy = H5MM_malloc(sizeof(H5E_t)))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Make a copy of current error stack */ estack_copy->nused = current_stack->nused; for(u=0; u<current_stack->nused; u++) { H5E_error_t *current_error, *new_error; /* Pointers to errors on each stack */ /* Get pointers into the current error stack location */ current_error = &(current_stack->slot[u]); new_error = &(estack_copy->slot[u]); /* Increment the IDs to indicate that they are used in this stack */ if(H5I_inc_ref(current_error->cls_id)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, NULL, "unable to increment ref count on error class") new_error->cls_id = current_error->cls_id; if(H5I_inc_ref(current_error->maj_num)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, NULL, "unable to increment ref count on error message") new_error->maj_num = current_error->maj_num; if(H5I_inc_ref(current_error->min_num)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, NULL, "unable to increment ref count on error message") new_error->min_num = current_error->min_num; if((new_error->func_name = HDstrdup(current_error->func_name))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") if((new_error->file_name = HDstrdup(current_error->file_name))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") new_error->line = current_error->line; if((new_error->desc = HDstrdup(current_error->desc))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") } /* end for */ /* Empty current error stack */ H5E_clear_stack(current_stack); /* Set the return value */ ret_value = estack_copy; done: if(ret_value==NULL) { if(estack_copy!=NULL) H5MM_xfree((void*)estack_copy); } /* end if */ FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5Eset_current_stack * * Purpose: Replaces current stack with specified stack. * * Return: Non-negative value on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 15, 2003 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5Eset_current_stack(hid_t err_stack) { H5E_t *estack; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(H5Eset_current_stack, FAIL) H5TRACE1("e","i",err_stack); if(err_stack != H5E_DEFAULT) { if((estack = H5I_object_verify(err_stack, H5I_ERROR_STACK))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID") /* Set the current error stack */ if(H5E_set_current_stack(estack)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTSET, FAIL, "unable to set error stack") } /* end if */ done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_set_current_stack * * Purpose: Private function to replace an error stack. * * Return: Non-negative value on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 15, 2003 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t H5E_set_current_stack(H5E_t *estack) { H5E_t *current_stack; /* Default error stack */ unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5E_set_current_stack, FAIL) /* Sanity check */ assert(estack); /* Get a pointer to the current error stack */ if((current_stack = H5E_get_my_stack ())==NULL) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack") /* Empty current error stack */ H5E_clear_stack(current_stack); /* Copy new stack to current error stack */ current_stack->nused = estack->nused; for(u=0; u<current_stack->nused; u++) { H5E_error_t *current_error, *new_error; /* Pointers to errors on each stack */ /* Get pointers into the current error stack location */ current_error = &(current_stack->slot[u]); new_error = &(estack->slot[u]); /* Increment the IDs to indicate that they are used in this stack */ if(H5I_inc_ref(new_error->cls_id)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, FAIL, "unable to decrement ref count on error class") current_error->cls_id = new_error->cls_id; if(H5I_inc_ref(new_error->maj_num)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, FAIL, "unable to decrement ref count on error class") current_error->maj_num = new_error->maj_num; if(H5I_inc_ref(new_error->min_num)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, FAIL, "unable to decrement ref count on error class") current_error->min_num = new_error->min_num; if((current_error->func_name = HDstrdup(new_error->func_name))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") if((current_error->file_name = HDstrdup(new_error->file_name))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") current_error->line = new_error->line; if((current_error->desc = HDstrdup(new_error->desc))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") } /* end for */ done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5Eclose_stack * * Purpose: Closes an error stack. * * Return: Non-negative value on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 14, 2003 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5Eclose_stack(hid_t stack_id) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(H5Eclose_stack, FAIL) H5TRACE1("e","i",stack_id); if(H5E_DEFAULT != stack_id) { /* * Decrement the counter on the error stack. It will be freed if the count * reaches zero. */ if(H5I_dec_ref(stack_id)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTDEC, FAIL, "unable to decrement ref count on error stack") } /* end if */ done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_close_stack * * Purpose: Private function to close an error stack. * * Return: Non-negative value on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 14, 2003 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t H5E_close_stack(H5E_t *estack) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5E_close_stack, FAIL) /* Sanity check */ assert(estack); /* Release the stack's error information */ H5E_clear_stack(estack); /* Free the stack structure */ H5MM_xfree((void*)estack); done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5Eget_num * * Purpose: Retrieves the number of error message. * * Return: Non-negative value on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 15, 2003 * * Modifications: * *------------------------------------------------------------------------- */ int H5Eget_num(hid_t error_stack_id) { H5E_t *estack; /* Error stack to operate on */ int ret_value; /* Return value */ /* Don't clear the error stack! :-) */ FUNC_ENTER_API_NOCLEAR(H5Eget_num, FAIL) H5TRACE1("Is","i",error_stack_id); /* Need to check for errors */ if(error_stack_id == H5E_DEFAULT) { if((estack = H5E_get_my_stack())==NULL) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack") } /* end if */ else { /* Only clear the error stack if it's not the default stack */ H5E_clear_stack(NULL); /* Get the error stack to operate on */ if((estack = H5I_object_verify(error_stack_id, H5I_ERROR_STACK))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID") } /* end else */ /* Get the number of errors on stack */ if((ret_value=H5E_get_num(estack))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get number of errors") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_get_num * * Purpose: Private function to retrieve number of errors in error stack. * * Return: Non-negative value on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 15, 2003 * * Modifications: * *------------------------------------------------------------------------- */ static int H5E_get_num(const H5E_t *estack) { int ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5E_get_num, FAIL) assert(estack); H5_ASSIGN_OVERFLOW(ret_value,estack->nused,size_t,int); done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5Epop * * Purpose: Deletes some error messages from the top of error stack. * * Return: Non-negative value on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 16, 2003 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5Epop(hid_t err_stack, size_t count) { H5E_t *estack; herr_t ret_value = SUCCEED; /* Return value */ /* Don't clear the error stack! :-) */ FUNC_ENTER_API_NOCLEAR(H5Epop, FAIL) H5TRACE2("e","iz",err_stack,count); /* Need to check for errors */ if(err_stack == H5E_DEFAULT) { if((estack = H5E_get_my_stack())==NULL) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack") } /* end if */ else { /* Only clear the error stack if it's not the default stack */ H5E_clear_stack(NULL); /* Get the error stack to operate on */ if((estack = H5I_object_verify(err_stack, H5I_ERROR_STACK))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID") } /* end else */ /* Range limit the number of errors to pop off stack */ if(count > estack->nused) count = estack->nused; /* Pop the errors off the stack */ if(H5E_pop(estack, count)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTRELEASE, FAIL, "can't pop errors from stack") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_pop * * Purpose: Private function to delete some error messages from the top * of error stack. * * Return: Non-negative value on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 16, 2003 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5E_pop(H5E_t *estack, size_t count) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5E_pop, FAIL) /* Sanity check */ assert(estack); assert(estack->nused>=count); /* Remove the entries from the error stack */ if(H5E_clear_entries(estack, count)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTRELEASE, FAIL, "can't remove errors from stack") done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5Epush * * Purpose: This function definition is for backward compatibility only. * It doesn't have error stack and error class as parameters. * The old definition of major and minor is casted as HID_T * in H5Epublic.h * * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu * Tuesday, Sep 16, 2003 * * Notes: Basically a public API wrapper around the H5E_push_stack * function. For backward compatibility, it maintains the * same parameter as the old function, in contrary to * H5Epush_stack. * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5Epush(const char *file, const char *func, unsigned line, H5E_major_t maj, H5E_minor_t min, const char *str) { H5E_t *estack = NULL; /* Default error stack */ herr_t ret_value=SUCCEED; /* Return value */ /* Don't clear the error stack! :-) */ FUNC_ENTER_API_NOCLEAR(H5Epush, FAIL) H5TRACE6("e","ssIuiis",file,func,line,maj,min,str); /* Push the error on the stack */ if(H5E_push_stack(estack, file, func, line, H5E_ERR_CLS_g, maj, min, str)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTSET, FAIL, "can't push error on stack") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5Epush_stack * * Purpose: Pushes a new error record onto error stack for the current * thread. The error has major and minor IDs MAJ_ID and * MIN_ID, the name of a function where the error was detected, * the name of the file where the error was detected, the * line within that file, and an error description string. The * function name, file name, and error description strings must * be statically allocated. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * Monday, October 18, 1999 * * Notes: Basically a new public API wrapper around the H5E_push_stack * function. * * Modifications: * Raymond Lu * Tuesday, July 15, 2003 * * Added the ID of the error stack to which the error is pushed * on. The error message can be appended more message in the * same control format as printf and fprintf. * *------------------------------------------------------------------------- */ herr_t H5Epush_stack(hid_t err_stack, const char *file, const char *func, unsigned line, hid_t cls_id, hid_t maj_id, hid_t min_id, const char *fmt, ...) { va_list ap; /* Varargs info */ H5E_t *estack; /* Pointer to error stack to modify */ H5E_msg_t *maj_ptr, *min_ptr; /* Pointer to major and minor error info */ int tmp_len; /* Current size of description buffer */ int desc_len; /* Actual length of description when formatted */ char *tmp=NULL; /* Buffer to place formatted description in */ herr_t ret_value=SUCCEED; /* Return value */ /* Don't clear the error stack! :-) */ FUNC_ENTER_API_NOCLEAR(H5Epush_stack, FAIL) H5TRACE7("e","issIuiis",err_stack,file,func,line,maj_id,min_id,fmt); if(err_stack == H5E_DEFAULT) estack = NULL; else { /* Only clear the error stack if it's not the default stack */ H5E_clear_stack(NULL); /* Get the error stack to operate on */ if((estack = H5I_object_verify(err_stack, H5I_ERROR_STACK))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID") } /* end else */ /* Check for mis-matches in major & minor error classes */ if((maj_ptr = H5I_object_verify(maj_id, H5I_ERROR_MSG))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error message ID") if((min_ptr = H5I_object_verify(min_id, H5I_ERROR_MSG))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error message ID") if(maj_ptr->cls != min_ptr->cls) HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "major and minor errors not from same error class") /* Format the description */ va_start(ap, fmt); /* Allocate space for the formatted description buffer */ tmp_len=128; if((tmp=H5MM_malloc((size_t)tmp_len))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") /* If the description doesn't fit into the initial buffer size, allocate more space and try again */ while((desc_len=HDvsnprintf(tmp, (size_t)tmp_len, fmt, ap))>tmp_len) { /* shutdown & restart the va_list */ va_end(ap); va_start(ap, fmt); /* Release the previous description, it's too small */ H5MM_xfree(tmp); /* Allocate a description of the appropriate length */ tmp_len = desc_len+1; if((tmp=H5MM_malloc((size_t)tmp_len))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") } /* end while */ va_end(ap); /* Push the error on the stack */ if(H5E_push_stack(estack, file, func, line, cls_id, maj_id, min_id, tmp)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTSET, FAIL, "can't push error on stack") done: if(tmp) H5MM_xfree(tmp); FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_push_stack * * Purpose: Pushes a new error record onto error stack for the current * thread. The error has major and minor IDs MAJ_ID and * MIN_ID, the name of a function where the error was detected, * the name of the file where the error was detected, the * line within that file, and an error description string. The * function name, file name, and error description strings must * be statically allocated (the FUNC_ENTER() macro takes care of * the function name and file name automatically, but the * programmer is responsible for the description string). * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * Friday, December 12, 1997 * * Modifications: * Raymond Lu * Tuesday, July 15, 2003 * * Added the ID of the error stack to which the error is pushed * on. The error message can be appended more message in the * same control format as printf and fprintf. * *------------------------------------------------------------------------- */ herr_t H5E_push_stack(H5E_t *estack, const char *file, const char *func, unsigned line, hid_t cls_id, hid_t maj_id, hid_t min_id, const char *desc) { herr_t ret_value=SUCCEED; /* Return value */ /* * WARNING: We cannot call HERROR() from within this function or else we * could enter infinite recursion. Furthermore, we also cannot * call any other HDF5 macro or function which might call * HERROR(). HERROR() is called by HRETURN_ERROR() which could * be called by FUNC_ENTER(). */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5E_push_stack) /* Sanity check */ assert(cls_id>0); assert(maj_id>0); assert(min_id>0); /* Check for 'default' error stack */ if(estack==NULL) if((estack = H5E_get_my_stack())==NULL) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_DONE(FAIL) /* * Don't fail if arguments are bad. Instead, substitute some default * value. */ if (!func) func = "Unknown_Function"; if (!file) file = "Unknown_File"; if (!desc) desc = "No description given"; /* * Push the error if there's room. Otherwise just forget it. */ assert (estack); if (estack->nused<H5E_NSLOTS) { /* Increment the IDs to indicate that they are used in this stack */ if(H5I_inc_ref(cls_id)<0) HGOTO_DONE(FAIL) estack->slot[estack->nused].cls_id = cls_id; if(H5I_inc_ref(maj_id)<0) HGOTO_DONE(FAIL) estack->slot[estack->nused].maj_num = maj_id; if(H5I_inc_ref(min_id)<0) HGOTO_DONE(FAIL) estack->slot[estack->nused].min_num = min_id; if((estack->slot[estack->nused].func_name = HDstrdup(func))==NULL) HGOTO_DONE(FAIL) if((estack->slot[estack->nused].file_name = HDstrdup(file))==NULL) HGOTO_DONE(FAIL) estack->slot[estack->nused].line = line; if((estack->slot[estack->nused].desc = HDstrdup(desc))==NULL) HGOTO_DONE(FAIL) estack->nused++; } done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5Eclear * * Purpose: This function is for backward compatbility. * Clears the error stack for the specified error stack. * * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu * Wednesday, July 16, 2003 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5Eclear(void) { H5E_t *estack = NULL; /* Default error stack to operate on */ herr_t ret_value=SUCCEED; /* Return value */ /* Don't clear the error stack! :-) */ FUNC_ENTER_API_NOCLEAR(H5Eclear, FAIL) H5TRACE0("e",""); /* Clear the error stack */ if(H5E_clear_stack(estack)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTSET, FAIL, "can't clear error stack") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5Eclear_stack * * Purpose: Clears the error stack for the specified error stack. * * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu * Wednesday, July 16, 2003 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5Eclear_stack(hid_t err_stack) { H5E_t *estack; /* Error stack to operate on */ herr_t ret_value=SUCCEED; /* Return value */ /* Don't clear the error stack! :-) */ FUNC_ENTER_API_NOCLEAR(H5Eclear_stack, FAIL) H5TRACE1("e","i",err_stack); /* Need to check for errors */ if(err_stack == H5E_DEFAULT) estack = NULL; else { /* Only clear the error stack if it's not the default stack */ H5E_clear_stack(NULL); if((estack = H5I_object_verify(err_stack, H5I_ERROR_STACK))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID") } /* end else */ /* Clear the error stack */ if(H5E_clear_stack(estack)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTSET, FAIL, "can't clear error stack") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_clear_entries * * Purpose: Private function to clear the error stack entries for the * specified error stack. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * Wednesday, August 6, 2003 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t H5E_clear_entries(H5E_t *estack, unsigned nentries) { H5E_error_t *error; /* Pointer to error stack entry to clear */ unsigned u; /* Local index variable */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5E_clear_entries, FAIL) /* Sanity check */ assert(estack); assert(estack->nused>=nentries); /* Empty the error stack from the top down */ for(u=0; nentries>0; nentries--,u++) { error = &(estack->slot[estack->nused-(u+1)]); /* Decrement the IDs to indicate that they are no longer used by this stack */ /* (In reverse order that they were incremented, so that reference counts work well) */ if(H5I_dec_ref(error->min_num)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTDEC, FAIL, "unable to decrement ref count on error message") if(H5I_dec_ref(error->maj_num)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTDEC, FAIL, "unable to decrement ref count on error message") if(H5I_dec_ref(error->cls_id)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTDEC, FAIL, "unable to decrement ref count on error class") /* Release strings */ if(error->func_name) H5MM_xfree((void*)error->func_name); if(error->file_name) H5MM_xfree((void*)error->file_name); if(error->desc) H5MM_xfree((void*)error->desc); } /* end for */ /* Decrement number of errors on stack */ estack->nused-=u; done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_clear_stack * * Purpose: Private function to clear the error stack for the * specified error stack. * * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu * Wednesday, July 16, 2003 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5E_clear_stack(H5E_t *estack) { herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5E_clear_stack, FAIL) /* Check for 'default' error stack */ if(estack==NULL) if((estack = H5E_get_my_stack())==NULL) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack") /* Empty the error stack */ assert(estack); if(estack->nused) if(H5E_clear_entries(estack, estack->nused)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTSET, FAIL, "can't clear error stack") done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5Eprint * * Purpose: This function is for backward compatbility. * Prints the error stack in some default way. This is just a * convenience function for H5Ewalk() with a function that * prints error messages. Users are encouraged to write there * own more specific error handlers. * * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu * Sep 16, 2003 * * Modifications: * Albert Cheng, 2000/12/02 * Show MPI process rank id if applicable. * Albert Cheng, 2001/07/14 * Show HDF5 library version information string too. * *------------------------------------------------------------------------- */ herr_t H5Eprint(FILE *stream) { H5E_t *estack; /* Error stack to operate on */ herr_t ret_value=SUCCEED; /* Return value */ /* Don't clear the error stack! :-) */ FUNC_ENTER_API_NOCLEAR(H5Eprint, FAIL) /*NO TRACE*/ if((estack = H5E_get_my_stack())==NULL) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack") /* Print error stack */ if(H5E_print_stack(estack, stream)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTLIST, FAIL, "can't display error stack") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5Eprint_stack * * Purpose: Prints the error stack in some default way. This is just a * convenience function for H5Ewalk() with a function that * prints error messages. Users are encouraged to write there * own more specific error handlers. * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * Friday, February 27, 1998 * * Modifications: * Albert Cheng, 2000/12/02 * Show MPI process rank id if applicable. * Albert Cheng, 2001/07/14 * Show HDF5 library version information string too. * * Raymond Lu, 2003/7/16 * Print for specified error stack. A line will appear before the error * messages of each error class. It states the information of library * name, version number and thread ID. * *------------------------------------------------------------------------- */ herr_t H5Eprint_stack(hid_t err_stack, FILE *stream) { H5E_t *estack; /* Error stack to operate on */ herr_t ret_value=SUCCEED; /* Return value */ /* Don't clear the error stack! :-) */ FUNC_ENTER_API_NOCLEAR(H5Eprint_stack, FAIL) /*NO TRACE*/ /* Need to check for errors */ if(err_stack == H5E_DEFAULT) { if((estack = H5E_get_my_stack())==NULL) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack") } /* end if */ else { /* Only clear the error stack if it's not the default stack */ H5E_clear_stack(NULL); if((estack = H5I_object_verify(err_stack, H5I_ERROR_STACK))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID") } /* end else */ /* Print error stack */ if(H5E_print_stack(estack, stream)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTLIST, FAIL, "can't display error stack") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_print_stack * * Purpose: Private function to print the error stack in some default * way. This is just a convenience function for H5Ewalk() and * H5Ewalk_stack() with a function that prints error messages. * Users are encouraged to write there own more specific error * handlers. * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * Friday, February 27, 1998 * * Modifications: * Albert Cheng, 2000/12/02 * Show MPI process rank id if applicable. * Albert Cheng, 2001/07/14 * Show HDF5 library version information string too. * * Raymond Lu, 2003/7/16 * Print for specified error stack. A line will appear before the error * messages of each error class. It states the information of library * name, version number and thread ID. * *------------------------------------------------------------------------- */ static herr_t H5E_print_stack(const H5E_t *estack, FILE *stream) { H5E_print_t eprint; /* Callback information to pass to H5E_walk_cb() */ herr_t ret_value = SUCCEED; /* Don't clear the error stack! :-) */ FUNC_ENTER_NOAPI(H5E_print_stack, FAIL) /* Sanity check */ assert(estack); /* If no stream was given, use stderr */ if (!stream) eprint.stream = stderr; else eprint.stream = stream; /* Reset the original error class information */ HDmemset(&eprint.cls,0,sizeof(H5E_cls_t)); /* Walk the error stack */ if(H5E_walk_stack(estack, H5E_WALK_DOWNWARD, H5E_walk_cb, (void*)&eprint)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTLIST, FAIL, "can't walk error stack") done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5Ewalk * * Purpose: This function is for backward compatbility. * Walks the error stack for the current thread and calls some * function for each error along the way. * * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu * Sep 16, 2003 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5Ewalk(H5E_direction_t direction, H5E_walk_t func, void *client_data) { H5E_t *estack; /* Error stack to operate on */ herr_t ret_value=SUCCEED; /* Return value */ /* Don't clear the error stack! :-) */ FUNC_ENTER_API_NOCLEAR(H5Ewalk, FAIL) /*NO TRACE*/ if((estack = H5E_get_my_stack())==NULL) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack") /* Walk the error stack */ if(H5E_walk_stack(estack, direction, func, client_data)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTLIST, FAIL, "can't walk error stack") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5Ewalk_stack * * Purpose: Walks the error stack for the current thread and calls some * function for each error along the way. * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * Friday, February 27, 1998 * * Modifications: * * Raymond Lu * Wednesday, July 16, 2003 * Let it walk through specified error stack. * *------------------------------------------------------------------------- */ herr_t H5Ewalk_stack(hid_t err_stack, H5E_direction_t direction, H5E_walk_t func, void *client_data) { H5E_t *estack; /* Error stack to operate on */ herr_t ret_value=SUCCEED; /* Return value */ /* Don't clear the error stack! :-) */ FUNC_ENTER_API_NOCLEAR(H5Ewalk_stack, FAIL) /*NO TRACE*/ /* Need to check for errors */ if(err_stack == H5E_DEFAULT) { if((estack = H5E_get_my_stack())==NULL) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack") } /* end if */ else { /* Only clear the error stack if it's not the default stack */ H5E_clear_stack(NULL); if((estack = H5I_object_verify(err_stack, H5I_ERROR_STACK))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID") } /* end else */ /* Walk the error stack */ if(H5E_walk_stack(estack, direction, func, client_data)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTLIST, FAIL, "can't walk error stack") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_walk_stack * * Purpose: Private function for H5Ewalk. * Walks the error stack, calling the specified function for * each error on the stack. The DIRECTION argument determines * whether the stack is walked from the inside out or the * outside in. The value H5E_WALK_UPWARD means begin with the * most specific error and end at the API; H5E_WALK_DOWNWARD * means to start at the API and end at the inner-most function * where the error was first detected. * * The function pointed to by FUNC will be called for each error * in the error stack. It's arguments will include an index * number (beginning at zero regardless of stack traversal * direction), an error stack entry, and the CLIENT_DATA pointer * passed to H5E_print. * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * Friday, December 12, 1997 * * Modifications: * * Raymond Lu * Wednesday, July 16, 2003 * Let it walk through specified error stack. * *------------------------------------------------------------------------- */ static herr_t H5E_walk_stack(const H5E_t *estack, H5E_direction_t direction, H5E_walk_t func, void *client_data) { int i; /* Local index variable */ herr_t status; /* Status from callback function */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5E_walk_stack, FAIL) /* Sanity check */ assert (estack); /* check args, but rather than failing use some default value */ if (direction!=H5E_WALK_UPWARD && direction!=H5E_WALK_DOWNWARD) direction = H5E_WALK_UPWARD; /* Walk the stack if a callback function was given */ if(func) { status=SUCCEED; if (H5E_WALK_UPWARD==direction) { for (i=0; i<(int)estack->nused && status>=0; i++) status = (func)((unsigned)i, estack->slot+i, client_data); } else { H5_CHECK_OVERFLOW(estack->nused-1,size_t,int); for (i=(int)(estack->nused-1); i>=0 && status>=0; i--) status = (func)((unsigned)(estack->nused-(size_t)(i+1)), estack->slot+i, client_data); } if(status<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTLIST, FAIL, "can't walk error stack") } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_walk_cb * * Purpose: This is a default error stack traversal callback function * that prints error messages to the specified output stream. * It is not meant to be called directly but rather as an * argument to the H5Ewalk() function. This function is called * also by H5Eprint(). Application writers are encouraged to * use this function as a model for their own error stack * walking functions. * * N is a counter for how many times this function has been * called for this particular traversal of the stack. It always * begins at zero for the first error on the stack (either the * top or bottom error, or even both, depending on the traversal * direction and the size of the stack). * * ERR_DESC is an error description. It contains all the * information about a particular error. * * CLIENT_DATA is the same pointer that was passed as the * CLIENT_DATA argument of H5Ewalk(). It is expected to be a * file pointer (or stderr if null). * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * Friday, December 12, 1997 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t H5E_walk_cb(unsigned n, const H5E_error_t *err_desc, void *client_data) { H5E_print_t *eprint = (H5E_print_t *)client_data; FILE *stream; /* I/O stream to print output to */ H5E_cls_t *cls_ptr; /* Pointer to error class */ H5E_msg_t *maj_ptr; /* Pointer to major error info */ H5E_msg_t *min_ptr; /* Pointer to minor error info */ const char *maj_str = "No major description"; /* Major error description */ const char *min_str = "No minor description"; /* Minor error description */ unsigned have_desc=1; /* Flag to indicate whether the error has a "real" description */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5E_walk_cb) /* Check arguments */ assert (err_desc); /* If no client data was passed, output to stderr */ if (!client_data) stream = stderr; else stream = eprint->stream; /* Get descriptions for the major and minor error numbers */ maj_ptr = H5I_object_verify(err_desc->maj_num, H5I_ERROR_MSG); min_ptr = H5I_object_verify(err_desc->min_num, H5I_ERROR_MSG); assert(maj_ptr && min_ptr); if(maj_ptr->msg) maj_str = maj_ptr->msg; if(min_ptr->msg) min_str = min_ptr->msg; /* Get error class info */ cls_ptr = maj_ptr->cls; /* Print error class header if new class */ if(eprint->cls.lib_name==NULL || HDstrcmp(cls_ptr->lib_name, eprint->cls.lib_name)) { /* update to the new class information */ if(cls_ptr->cls_name) eprint->cls.cls_name = cls_ptr->cls_name; if(cls_ptr->lib_name) eprint->cls.lib_name = cls_ptr->lib_name; if(cls_ptr->lib_vers) eprint->cls.lib_vers = cls_ptr->lib_vers; fprintf (stream, "%s-DIAG: Error detected in %s (%s) ", cls_ptr->cls_name, cls_ptr->lib_name, cls_ptr->lib_vers); /* try show the process or thread id in multiple processes cases*/ #ifdef H5_HAVE_PARALLEL { int mpi_rank, mpi_initialized; MPI_Initialized(&mpi_initialized); if (mpi_initialized){ MPI_Comm_rank(MPI_COMM_WORLD,&mpi_rank); fprintf (stream, "MPI-process %d", mpi_rank); }else fprintf (stream, "thread 0"); } #elif defined(H5_HAVE_THREADSAFE) fprintf (stream, "thread %lu", (unsigned long)pthread_self()); #else fprintf (stream, "thread 0"); #endif fprintf (stream, ":\n"); } /* Check for "real" error description - used to format output more nicely */ if(err_desc->desc==NULL || HDstrlen(err_desc->desc)==0) have_desc=0; /* Print error message */ fprintf (stream, "%*s#%03u: %s line %u in %s()%s%s\n", H5E_INDENT, "", n, err_desc->file_name, err_desc->line, err_desc->func_name, (have_desc ? ": " : ""), (have_desc ? err_desc->desc : "")); fprintf (stream, "%*smajor: %s\n", H5E_INDENT*2, "", maj_str); fprintf (stream, "%*sminor: %s\n", H5E_INDENT*2, "", min_str); FUNC_LEAVE_NOAPI(SUCCEED) } /*------------------------------------------------------------------------- * Function: H5Eget_auto * * Purpose: This function is for backward compatbility. * Returns the current settings for the automatic error stack * traversal function and its data for specific error stack. * Either (or both) arguments may be null in which case the * value is not returned. * * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu * Sep 16, 2003 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5Eget_auto(H5E_auto_t *func, void **client_data) { H5E_t *estack; /* Error stack to operate on */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_API(H5Eget_auto, FAIL) H5TRACE2("e","*xx",func,client_data); /* Retrieve default error stack */ if((estack = H5E_get_my_stack())==NULL) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack") /* Get the automatic error reporting information */ if(H5E_get_auto_stack(estack, FALSE, (void **)func, client_data)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get automatic error info") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5Eget_auto_stack * * Purpose: Returns the current settings for the automatic error stack * traversal function and its data for specific error stack. * Either (or both) arguments may be null in which case the * value is not returned. * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * Saturday, February 28, 1998 * * Modifications: * Raymond Lu * July 18, 2003 * Added error stack in the parameters. It returns the * traversal function and data for that error stack. * *------------------------------------------------------------------------- */ herr_t H5Eget_auto_stack(hid_t estack_id, H5E_auto_stack_t *func, void **client_data) { H5E_t *estack; /* Error stack to operate on */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_API(H5Eget_auto_stack, FAIL) H5TRACE3("e","i*xx",estack_id,func,client_data); if(estack_id == H5E_DEFAULT) { if((estack = H5E_get_my_stack())==NULL) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack") } /* end if */ else if((estack = H5I_object_verify(estack_id, H5I_ERROR_STACK))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID") /* Get the automatic error reporting information */ if(H5E_get_auto_stack(estack, TRUE, (void **)func, client_data)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get automatic error info") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_get_auto_stack * * Purpose: Private function to return the current settings for the * automatic error stack traversal function and its data * for specific error stack. Either (or both) arguments may * be null in which case the value is not returned. * * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu * July 18, 2003 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t H5E_get_auto_stack(const H5E_t *estack, hbool_t new_api, void * *func, void **client_data) { herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5E_get_auto_stack, FAIL) assert (estack); /* Retrieve the requested information */ if(func) *func = new_api ? (void *)estack->u.func_stack : (void *)estack->u.func; if(client_data) *client_data = estack->auto_data; done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5Eset_auto * * Purpose: This function is for backward compatbility. * Turns on or off automatic printing of errors for certain * error stack. When turned on (non-null FUNC pointer) any * API function which returns an error indication will first * call FUNC passing it CLIENT_DATA as an argument. * * The default values before this function is called are * H5Eprint() with client data being the standard error stream, * stderr. * * Automatic stack traversal is always in the H5E_WALK_DOWNWARD * direction. * * See Also: H5Ewalk() * * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu * Sep 16, 2003 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5Eset_auto(H5E_auto_t func, void *client_data) { H5E_t *estack; /* Error stack to operate on */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_API(H5Eset_auto, FAIL) H5TRACE2("e","xx",func,client_data); if((estack = H5E_get_my_stack())==NULL) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack") /* Set the automatic error reporting information */ if(H5E_set_auto_stack(estack, FALSE, (void *)func, client_data)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTSET, FAIL, "can't set automatic error info") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5Eset_auto_stack * * Purpose: Turns on or off automatic printing of errors for certain * error stack. When turned on (non-null FUNC pointer) any * API function which returns an error indication will first * call FUNC passing it CLIENT_DATA as an argument. * * The default values before this function is called are * H5Eprint() with client data being the standard error stream, * stderr. * * Automatic stack traversal is always in the H5E_WALK_DOWNWARD * direction. * * See Also: H5Ewalk() * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * Friday, February 27, 1998 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5Eset_auto_stack(hid_t estack_id, H5E_auto_stack_t func, void *client_data) { H5E_t *estack; /* Error stack to operate on */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_API(H5Eset_auto_stack, FAIL) H5TRACE3("e","ixx",estack_id,func,client_data); if(estack_id == H5E_DEFAULT) { if((estack = H5E_get_my_stack())==NULL) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack") } /* end if */ else if((estack = H5I_object_verify(estack_id, H5I_ERROR_STACK))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID") /* Set the automatic error reporting information */ if(H5E_set_auto_stack(estack, TRUE, (void *)func, client_data)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTSET, FAIL, "can't set automatic error info") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_set_auto_stack * * Purpose: Private function to turn on or off automatic printing of * errors for certain error stack. When turned on (non-null * FUNC pointer) any API function which returns an error * indication will first call FUNC passing it CLIENT_DATA * as an argument. * * The default values before this function is called are * H5Eprint() with client data being the standard error stream, * stderr. * * Automatic stack traversal is always in the H5E_WALK_DOWNWARD * direction. * * See Also: H5Ewalk() * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * Friday, February 27, 1998 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t H5E_set_auto_stack(H5E_t *estack, hbool_t new_api, void *func, void *client_data) { herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5E_set_auto_stack, FAIL) assert(estack); /* Set the automatic error reporting info */ estack->new_api = new_api; if(new_api) estack->u.func_stack = (H5E_auto_stack_t)func; else estack->u.func = (H5E_auto_t)func; estack->auto_data = client_data; done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_dump_api_stack * * Purpose: Private function to dump the error stack during an error in * an API function if a callback function is defined for the * current error stack. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * Wednesday, August 6, 2003 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5E_dump_api_stack(int is_api) { herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5E_dump_api_stack, FAIL) /* Only dump the error stack during an API call */ if(is_api) { H5E_t *estack = H5E_get_my_stack(); assert(estack); if(estack->new_api) { if (estack->u.func_stack) (void)((estack->u.func_stack)(H5E_DEFAULT, estack->auto_data)); } /* end if */ else { if (estack->u.func) (void)((estack->u.func)(estack->auto_data)); } /* end else */ } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5Eauto_is_stack * * Purpose: Determines if the error auto reporting function for an * error stack conforms to the H5E_auto_stack_t typedef * or the H5E_auto_t typedef. The IS_STACK parameter is set * to 1 for the first case and 0 for the latter case. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * Wednesday, September 8, 2004 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5Eauto_is_stack(hid_t estack_id, unsigned *is_stack) { H5E_t *estack; /* Error stack to operate on */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_API(H5Eauto_is_stack, FAIL) H5TRACE2("e","i*Iu",estack_id,is_stack); if(estack_id == H5E_DEFAULT) { if((estack = H5E_get_my_stack())==NULL) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack") } /* end if */ else if((estack = H5I_object_verify(estack_id, H5I_ERROR_STACK))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID") /* Check if the error stack reporting function is the "newer" stack type */ if(is_stack) *is_stack=estack->new_api; done: FUNC_LEAVE_API(ret_value) } /* end H5Eauto_is_stack() */