From 73897627660169de753597b9ff045d3112646506 Mon Sep 17 00:00:00 2001 From: Robb Matzke Date: Fri, 7 Nov 1997 00:16:53 -0500 Subject: [PATCH] [svn-r135] ./config/linux ./config/freebsd2.2.1 Rewritten to be more flexible. ./src/H5AC.c ./src/H5ACprivate.h ./src/H5F.c ./src/H5H.c ./src/H5Gpkg.h ./src/H5Gshad.c ./src/H5O.c ./test/istore.c ./test/tstab.c Accumulates cache statistics and displays the results on stderr when the file is closed if it was opened with H5F_ACC_DEBUG passed into H5F_open() ./src/H5B.c ./src/H5Bprivate.h ./src/H5Fistore.c ./src/H5Gnode.c Added more debugging which is turned on if H5B_DEBUG is defined on the compile command (see config/linux). Fixed a couple of bugs with left insertions which are used by the indexed storage stuff. ./src/H5Flow.c Fixed a memory leak. ./src/H5Fprivate.h Fixed warnings about shifting more than size of object. ./src/H5Fstdio.c Fixed seek optimizations back to the way Quincey originally had them. ./src/H5V.c Removed unused variables. --- MANIFEST | 1 + config/freebsd2.2.1 | 50 ++++++- config/linux | 54 +++++-- src/H5AC.c | 125 ++++++++++++++--- src/H5ACprivate.h | 27 +++- src/H5B.c | 334 ++++++++++++++++++++++++++++---------------- src/H5Bprivate.h | 8 +- src/H5Distore.c | 132 ++++++++++++----- src/H5F.c | 3 +- src/H5Fistore.c | 132 ++++++++++++----- src/H5Flow.c | 7 +- src/H5Fprivate.h | 13 +- src/H5Fstdio.c | 9 +- src/H5Gnode.c | 93 +++++++++--- src/H5Gpkg.h | 2 +- src/H5Gshad.c | 28 ++-- src/H5Gstab.c | 2 +- src/H5H.c | 8 +- src/H5O.c | 8 +- src/H5V.c | 4 + test/istore.c | 3 +- test/tstab.c | 1 + 22 files changed, 771 insertions(+), 273 deletions(-) diff --git a/MANIFEST b/MANIFEST index b756d89a56..a2d00521bf 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 4d833674b7..35286f004f 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 642829a375..35286f004f 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" +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 1c570e89d3..c4ee46c210 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; inslots; 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; inprots; 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; idiagnostics[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 25549ffb81..884bc3c63f 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 ccbcdb4244..a735799ca1 100644 --- a/src/H5B.c +++ b/src/H5B.c @@ -94,6 +94,15 @@ #include /*File memory management */ #include /*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 (ichild[i] = old_bt->child[delta+i]; + if (ichild[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 (ichild[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; + 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->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; - } - 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; inchildren; 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 05e2e568a6..619a00fdd9 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 96ef5fc6ec..06997a14b0 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_cmp + * 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_KEYmesg.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_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; imesg.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; indims; 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 754be9c677..a485f312f2 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 96ef5fc6ec..06997a14b0 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_cmp + * 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_KEYmesg.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_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; imesg.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; indims; 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 6a7de9cb03..18cc417750 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 ae7e75c471..6eb6dd939e 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; _iu.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 58c924ce4e..f578783e2d 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_KEYheap_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 9421541e4a..0e5db3384d 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 875f880922..253e01e1cd 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 7acaa13172..46f1eebd5a 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 4c446131d9..e1453e5475 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 9130de36ad..43faa6c942 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 e5ad09eb43..7612ad9b16 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 e79696cd9d..c50ef3f644 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 d2f6de4770..9bac3b7b77 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