summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--INSTALL3
-rw-r--r--INSTALL_MAINT7
-rw-r--r--MANIFEST2
-rw-r--r--config/freebsd2.2.115
-rw-r--r--config/linux15
-rw-r--r--src/H5AC.c146
-rw-r--r--src/H5ACprivate.h42
-rw-r--r--src/H5B.c450
-rw-r--r--src/H5Bprivate.h36
-rw-r--r--src/H5C.c8
-rw-r--r--src/H5D.c27
-rw-r--r--src/H5Distore.c92
-rw-r--r--src/H5E.c1
-rw-r--r--src/H5Epublic.h1
-rw-r--r--src/H5F.c553
-rw-r--r--src/H5Fcore.c122
-rw-r--r--src/H5Ffamily.c547
-rw-r--r--src/H5Fistore.c92
-rw-r--r--src/H5Flow.c588
-rw-r--r--src/H5Fprivate.h102
-rw-r--r--src/H5Fsec2.c152
-rw-r--r--src/H5Fstdio.c119
-rw-r--r--src/H5G.c51
-rw-r--r--src/H5Gent.c68
-rw-r--r--src/H5Gnode.c177
-rw-r--r--src/H5Gpkg.h15
-rw-r--r--src/H5Gprivate.h24
-rw-r--r--src/H5Gshad.c217
-rw-r--r--src/H5Gstab.c60
-rw-r--r--src/H5H.c156
-rw-r--r--src/H5Hprivate.h21
-rw-r--r--src/H5MF.c46
-rw-r--r--src/H5MFprivate.h7
-rw-r--r--src/H5O.c142
-rw-r--r--src/H5Ocont.c12
-rw-r--r--src/H5Oistore.c12
-rw-r--r--src/H5Oprivate.h15
-rw-r--r--src/H5Ostab.c29
-rw-r--r--src/H5Ostdst.c12
-rw-r--r--src/H5private.h9
-rw-r--r--src/Makefile.in8
-rw-r--r--src/debug.c27
-rw-r--r--test/hyperslab.c27
-rw-r--r--test/istore.c117
-rw-r--r--test/theap.c15
-rw-r--r--test/tohdr.c81
-rw-r--r--test/tstab.c52
47 files changed, 3030 insertions, 1490 deletions
diff --git a/INSTALL b/INSTALL
index 7851e22..68885e8 100644
--- a/INSTALL
+++ b/INSTALL
@@ -68,4 +68,5 @@ distribution directory:
To build/install HDF5 on non-Unix systems from the root of the
distribution directory:
- * To be written later.
+ * To be written later. Basically, there will be a separate
+ makefile (or equivalent) for each platform.
diff --git a/INSTALL_MAINT b/INSTALL_MAINT
index 78c3297..e889b00 100644
--- a/INSTALL_MAINT
+++ b/INSTALL_MAINT
@@ -17,12 +17,12 @@ Information for HDF5 maintainers:
mostlyclean -- remove temp files (eg, *.o but not *.a).
clean -- mostlyclean plus libs and progs.
distclean -- all non-distributed files.
- maintainer-clean -- all but H5config.h.in and configure.
+ maintainer-clean -- all derived files but H5config.h.in and configure.
* Most Makefiles also understand:
TAGS -- build a tags table
- dep depend -- recalculate source dependencies
+ dep, depend -- recalculate source dependencies
lib -- build just the libraries w/o programs
* If you have personal preferences for which make, compiler, compiler
@@ -60,6 +60,7 @@ Information for HDF5 maintainers:
`.depend' file from each directory and type `make depend'. For
instance:
+ $ cd $HDF5_HOME
$ find . -name .depend -exec rm {} \;
$ make depend
@@ -72,5 +73,5 @@ Information for HDF5 maintainers:
that ends with `.c' and the other that has the library
name wrapped around each `.o' file.
- 2. Some versions of make/ar have problems with modifications
+ 2. Some versions of make/ar have problems with modification
times of archive members.
diff --git a/MANIFEST b/MANIFEST
index a2d0052..10a58e7 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -49,9 +49,11 @@
./src/H5Epublic.h
./src/H5F.c
./src/H5Fcore.c
+./src/H5Ffamily.c
./src/H5Fistore.c
./src/H5Flow.c
./src/H5Fsec2.c
+./src/H5Fsplit.c
./src/H5Fstdio.c
./src/H5Fprivate.h
./src/H5Fpublic.h
diff --git a/config/freebsd2.2.1 b/config/freebsd2.2.1
index 35286f0..f3bd304 100644
--- a/config/freebsd2.2.1
+++ b/config/freebsd2.2.1
@@ -4,7 +4,9 @@
# 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:
+# more of the following words (be sure to use single quotes when
+# setting its value or the dollar signs will be expanded as variables
+# too soon):
#
# $warn -- Generates compiler warnings. You should always
# include this since it has no effect on the speed of
@@ -19,9 +21,7 @@
#
# $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.
+# conditions.
#
# $profile -- Compiles code with the `-pg' flag which
# produces a `gmon.out' file when the library
@@ -33,14 +33,17 @@
# $debug $warn -DH5F_LOW_DFLT=H5F_LOW_SEC2
#
+# Unconditionally set the compiler to gcc since the following flags
+# only apply to that compiler.
+CC=gcc
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"
+debug="-g -DH5AC_DEBUG -DH5B_DEBUG -DH5F_DEBUG -DH5G_DEBUG -DH5F_OPT_SEEK=0 -fverbose-asm"
-production="-O3 -DNDEBUG -DH5F_OPT_SEEK=1 -finline-functions -funroll-loops -malign-double -fomit-frame-pointer"
+production="-O3 -DNDEBUG -finline-functions -funroll-loops -malign-double -fomit-frame-pointer"
default_mode='$debug $warn -DH5F_LOW_DFLT=H5F_LOW_SEC2'
diff --git a/config/linux b/config/linux
index 35286f0..f3bd304 100644
--- a/config/linux
+++ b/config/linux
@@ -4,7 +4,9 @@
# 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:
+# more of the following words (be sure to use single quotes when
+# setting its value or the dollar signs will be expanded as variables
+# too soon):
#
# $warn -- Generates compiler warnings. You should always
# include this since it has no effect on the speed of
@@ -19,9 +21,7 @@
#
# $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.
+# conditions.
#
# $profile -- Compiles code with the `-pg' flag which
# produces a `gmon.out' file when the library
@@ -33,14 +33,17 @@
# $debug $warn -DH5F_LOW_DFLT=H5F_LOW_SEC2
#
+# Unconditionally set the compiler to gcc since the following flags
+# only apply to that compiler.
+CC=gcc
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"
+debug="-g -DH5AC_DEBUG -DH5B_DEBUG -DH5F_DEBUG -DH5G_DEBUG -DH5F_OPT_SEEK=0 -fverbose-asm"
-production="-O3 -DNDEBUG -DH5F_OPT_SEEK=1 -finline-functions -funroll-loops -malign-double -fomit-frame-pointer"
+production="-O3 -DNDEBUG -finline-functions -funroll-loops -malign-double -fomit-frame-pointer"
default_mode='$debug $warn -DH5F_LOW_DFLT=H5F_LOW_SEC2'
diff --git a/src/H5AC.c b/src/H5AC.c
index c4ee46c..e19a94f 100644
--- a/src/H5AC.c
+++ b/src/H5AC.c
@@ -32,15 +32,6 @@
/* #define H5AC_SORT_BY_ADDR */
/*
- * Debug H5AC_protect() and H5AC_unprotect() by insuring that nothing
- * accesses protected objects. NDEBUG must not be defined in order for
- * this to have any effect.
- */
-#ifdef NDEBUG
-# undef H5AC_DEBUG
-#endif
-
-/*
* Private file-scope variables.
*/
#define PABLO_MASK H5AC_mask
@@ -118,7 +109,7 @@ H5AC_dest (H5F_t *f)
assert (f->shared->cache);
cache = f->shared->cache;
- if (H5AC_flush (f, NULL, 0, TRUE)<0) {
+ if (H5AC_flush (f, NULL, NO_ADDR, TRUE)<0) {
HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL);
}
@@ -183,13 +174,13 @@ H5AC_dest (H5F_t *f)
*-------------------------------------------------------------------------
*/
void *
-H5AC_find_f (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
+H5AC_find_f (H5F_t *f, const H5AC_class_t *type, const haddr_t *addr,
const void *udata1, void *udata2)
{
unsigned idx;
herr_t status;
void *thing = NULL;
- herr_t (*flush)(H5F_t*,hbool_t,haddr_t,void*)=NULL;
+ herr_t (*flush)(H5F_t*,hbool_t,const haddr_t*,void*)=NULL;
H5AC_slot_t *slot = NULL;
H5AC_t *cache = NULL;
@@ -200,6 +191,7 @@ H5AC_find_f (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
assert (type);
assert (type->load);
assert (type->flush);
+ assert (addr && H5F_addr_defined (addr));
idx = H5AC_HASH (f, addr);
cache = f->shared->cache;
slot = cache->slot + idx;
@@ -207,7 +199,7 @@ 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) {
+ if (slot->type==type && H5F_addr_eq (&(slot->addr), addr)) {
cache->diagnostics[type->id].nhits++;
HRETURN (slot->thing);
}
@@ -217,7 +209,7 @@ H5AC_find_f (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
* Fail if the item in the cache is at the correct address but is
* of the wrong type.
*/
- if (slot->type && slot->type!=type && slot->addr==addr) {
+ if (slot->type && slot->type!=type && H5F_addr_eq (&(slot->addr), addr)) {
HRETURN_ERROR (H5E_CACHE, H5E_BADTYPE, NULL);
}
@@ -230,7 +222,7 @@ H5AC_find_f (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
{
intn i;
for (i=0; i<slot->nprots; i++) {
- assert (addr!=slot->prot[i].addr);
+ assert (H5F_addr_ne (addr, &(slot->prot[i].addr)));
}
}
#endif
@@ -248,7 +240,7 @@ H5AC_find_f (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
*/
if (slot->type) {
flush = slot->type->flush;
- status = (flush)(f, TRUE, slot->addr, slot->thing);
+ status = (flush)(f, TRUE, &(slot->addr), slot->thing);
if (status<0) {
/*
* The old thing could not be removed from the stack.
@@ -266,7 +258,7 @@ H5AC_find_f (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
* Make the cache point to the new thing.
*/
slot->type = type;
- slot->addr = addr;
+ slot->addr = *addr;
slot->thing = thing;
FUNC_LEAVE (thing);
@@ -323,10 +315,10 @@ H5AC_compare (const void *_a, const void *_b)
*
* Purpose: Flushes (and destroys if DESTROY is non-zero) the specified
* entry from the cache. If the entry TYPE is CACHE_FREE and
- * ADDR is zero then all types of entries are flushed. If TYPE
- * is CACHE_FREE and ADDR is non-zero, then whatever is cached
- * at ADDR is flushed. Otherwise the thing at ADDR is flushed
- * if it is the correct type.
+ * ADDR is the null pointer then all types of entries are
+ * flushed. If TYPE is CACHE_FREE and ADDR is non-null, then
+ * whatever is cached at ADDR is flushed. Otherwise the thing
+ * at ADDR is flushed if it is the correct type.
*
* If there are protected objects they will not be flushed.
* However, an attempt will be made to flush all non-protected
@@ -346,11 +338,12 @@ H5AC_compare (const void *_a, const void *_b)
*-------------------------------------------------------------------------
*/
herr_t
-H5AC_flush (H5F_t *f, const H5AC_class_t *type, haddr_t addr, hbool_t destroy)
+H5AC_flush (H5F_t *f, const H5AC_class_t *type, const haddr_t *addr,
+ hbool_t destroy)
{
uintn i;
herr_t status;
- herr_t (*flush)(H5F_t*,hbool_t,haddr_t,void*)=NULL;
+ herr_t (*flush)(H5F_t*,hbool_t,const haddr_t*,void*)=NULL;
H5AC_slot_t *slot;
intn *map=NULL;
intn nslots;
@@ -360,10 +353,9 @@ H5AC_flush (H5F_t *f, const H5AC_class_t *type, haddr_t addr, hbool_t destroy)
assert (f);
assert (f->shared->cache);
- i = H5AC_HASH (f, addr);
cache = f->shared->cache;
- if (0==addr) {
+ if (!addr) {
#ifdef H5AC_SORT_BY_ADDR
/*
@@ -380,7 +372,8 @@ H5AC_flush (H5F_t *f, const H5AC_class_t *type, haddr_t addr, hbool_t destroy)
current_cache_g = NULL;
#ifdef NDEBUG
for (i=1; i<nslots; i++) {
- assert (cache->slot[i-1].addr < cache->slot[i].addr);
+ assert (H5F_addr_lt (&(cache->slot[i-1].addr),
+ &(cache->slot[i].addr)));
}
#endif
#else
@@ -400,7 +393,7 @@ H5AC_flush (H5F_t *f, const H5AC_class_t *type, haddr_t addr, hbool_t destroy)
#endif
if (!type || type==slot->type) {
flush = slot->type->flush;
- status = (flush)(f, destroy, slot->addr, slot->thing);
+ status = (flush)(f, destroy, &(slot->addr), slot->thing);
if (status<0) {
map = H5MM_xfree (map);
HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL);
@@ -419,20 +412,22 @@ H5AC_flush (H5F_t *f, const H5AC_class_t *type, haddr_t addr, hbool_t destroy)
HRETURN_ERROR (H5E_CACHE, H5E_PROTECT, FAIL);
}
- } else if ((!type || cache->slot[i].type==type) &&
- cache->slot[i].addr==addr) {
- /*
- * Flush just this entry.
- */
- flush = cache->slot[i].type->flush;
- status = (flush) (f, destroy, cache->slot[i].addr,
- cache->slot[i].thing);
- if (status<0) {
- HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL);
+ } else {
+ i = H5AC_HASH (f, addr);
+ if ((!type || cache->slot[i].type==type) &&
+ H5F_addr_eq (&(cache->slot[i].addr), addr)) {
+ /*
+ * Flush just this entry.
+ */
+ flush = cache->slot[i].type->flush;
+ status = (flush) (f, destroy, &(cache->slot[i].addr),
+ cache->slot[i].thing);
+ 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;
}
- cache->diagnostics[cache->slot[i].type->id].nflushes++;
- if (destroy) cache->slot[i].type = NULL;
-
}
FUNC_LEAVE (SUCCEED);
@@ -462,11 +457,11 @@ H5AC_flush (H5F_t *f, const H5AC_class_t *type, haddr_t addr, hbool_t destroy)
*-------------------------------------------------------------------------
*/
herr_t
-H5AC_set (H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing)
+H5AC_set (H5F_t *f, const H5AC_class_t *type, const haddr_t *addr, void *thing)
{
herr_t status;
uintn idx;
- herr_t (*flush)(H5F_t*,hbool_t,haddr_t,void*)=NULL;
+ herr_t (*flush)(H5F_t*,hbool_t,const haddr_t*,void*)=NULL;
H5AC_slot_t *slot = NULL;
H5AC_t *cache=NULL;
@@ -476,7 +471,7 @@ H5AC_set (H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing)
assert (f->shared->cache);
assert (type);
assert (type->flush);
- assert (addr>=0);
+ assert (addr && H5F_addr_defined (addr));
assert (thing);
idx = H5AC_HASH (f, addr);
cache = f->shared->cache;
@@ -486,14 +481,14 @@ H5AC_set (H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing)
{
intn i;
for (i=0; i<slot->nprots; i++) {
- assert (addr!=slot->prot[i].addr);
+ assert (H5F_addr_ne (addr, &(slot->prot[i].addr)));
}
}
#endif
if (slot->type) {
flush = slot->type->flush;
- status = (flush)(f, TRUE, slot->addr, slot->thing);
+ status = (flush)(f, TRUE, &(slot->addr), slot->thing);
if (status<0) {
HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL);
}
@@ -501,7 +496,7 @@ H5AC_set (H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing)
}
slot->type = type;
- slot->addr = addr;
+ slot->addr = *addr;
slot->thing = thing;
cache->diagnostics[type->id].ninits++;
@@ -533,10 +528,10 @@ H5AC_set (H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing)
*/
herr_t
H5AC_rename (H5F_t *f, const H5AC_class_t *type,
- haddr_t old_addr, haddr_t new_addr)
+ const haddr_t *old_addr, const haddr_t *new_addr)
{
uintn old_idx, new_idx;
- herr_t (*flush)(H5F_t*, hbool_t, haddr_t, void*);
+ herr_t (*flush)(H5F_t*, hbool_t, const haddr_t*, void*);
herr_t status;
H5AC_t *cache=NULL;
@@ -545,8 +540,8 @@ H5AC_rename (H5F_t *f, const H5AC_class_t *type,
assert (f);
assert (f->shared->cache);
assert (type);
- assert (old_addr>=0);
- assert (new_addr>=0);
+ assert (old_addr);
+ assert (new_addr);
old_idx = H5AC_HASH (f, old_addr);
new_idx = H5AC_HASH (f, new_addr);
cache = f->shared->cache;
@@ -556,10 +551,10 @@ H5AC_rename (H5F_t *f, const H5AC_class_t *type,
int i;
for (i=0; i<cache->slot[old_idx].nprots; i++) {
- assert (old_addr!=cache->slot[old_idx].prot[i].addr);
+ assert (H5F_addr_ne (old_addr, &(cache->slot[old_idx].prot[i].addr)));
}
for (i=0; i<cache->slot[new_idx].nprots; i++) {
- assert (new_addr!=cache->slot[new_idx].prot[i].addr);
+ assert (H5F_addr_ne (new_addr, &(cache->slot[new_idx].prot[i].addr)));
}
}
#endif
@@ -569,11 +564,11 @@ H5AC_rename (H5F_t *f, const H5AC_class_t *type,
* new hash value is the same as the old one.
*/
if (cache->slot[old_idx].type!=type ||
- cache->slot[old_idx].addr!=old_addr) {
+ H5F_addr_ne (&(cache->slot[old_idx].addr), old_addr)) {
HRETURN (SUCCEED);
}
if (old_idx==new_idx) {
- cache->slot[old_idx].addr = new_addr;
+ cache->slot[old_idx].addr = *new_addr;
HRETURN (SUCCEED);
}
@@ -582,7 +577,7 @@ H5AC_rename (H5F_t *f, const H5AC_class_t *type,
*/
if (cache->slot[new_idx].type) {
flush = cache->slot[new_idx].type->flush;
- status = (flush)(f, TRUE, cache->slot[new_idx].addr,
+ status = (flush)(f, TRUE, &(cache->slot[new_idx].addr),
cache->slot[new_idx].thing);
if (status<0) {
HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL);
@@ -594,7 +589,7 @@ H5AC_rename (H5F_t *f, const H5AC_class_t *type,
* Move the source to the destination (it might not be cached)
*/
cache->slot[new_idx].type = cache->slot[old_idx].type;
- cache->slot[new_idx].addr = new_addr;
+ cache->slot[new_idx].addr = *new_addr;
cache->slot[new_idx].thing = cache->slot[old_idx].thing;
cache->slot[old_idx].type = NULL;
@@ -629,7 +624,7 @@ H5AC_rename (H5F_t *f, const H5AC_class_t *type,
*-------------------------------------------------------------------------
*/
void *
-H5AC_protect (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
+H5AC_protect (H5F_t *f, const H5AC_class_t *type, const haddr_t *addr,
const void *udata1, void *udata2)
{
int idx;
@@ -652,21 +647,22 @@ H5AC_protect (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
assert (type);
assert (type->load);
assert (type->flush);
+ assert (addr && H5F_addr_defined (addr));
idx = H5AC_HASH (f, addr);
cache = f->shared->cache;
slot = cache->slot+idx;
- if (slot->type==type && slot->addr==addr) {
+ if (slot->type==type && H5F_addr_eq (&(slot->addr), 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;
+ H5F_addr_undef (&(slot->addr));
slot->thing = NULL;
- } else if (slot->type && slot->addr==addr) {
+ } else if (slot->type && H5F_addr_eq (&(slot->addr), addr)) {
/*
* Right address but wrong object type.
*/
@@ -681,7 +677,7 @@ H5AC_protect (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
*/
intn i;
for (i=0; i<slot->nprots; i++) {
- assert (addr!=slot->prot[i].addr);
+ assert (H5F_addr_ne (addr, &(slot->prot[i].addr)));
}
#endif
@@ -706,7 +702,7 @@ H5AC_protect (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
slot->aprots * sizeof(H5AC_prot_t));
}
slot->prot[slot->nprots].type = type;
- slot->prot[slot->nprots].addr = addr;
+ slot->prot[slot->nprots].addr = *addr;
slot->prot[slot->nprots].thing = thing;
slot->nprots += 1;
#endif
@@ -741,11 +737,12 @@ H5AC_protect (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
*-------------------------------------------------------------------------
*/
herr_t
-H5AC_unprotect (H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing)
+H5AC_unprotect (H5F_t *f, const H5AC_class_t *type, const haddr_t *addr,
+ void *thing)
{
herr_t status;
uintn idx;
- herr_t (*flush)(H5F_t*,hbool_t,haddr_t,void*)=NULL;
+ herr_t (*flush)(H5F_t*,hbool_t,const haddr_t*,void*)=NULL;
H5AC_t *cache = NULL;
H5AC_slot_t *slot = NULL;
@@ -756,7 +753,7 @@ H5AC_unprotect (H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing)
assert (f->shared->cache);
assert (type);
assert (type->flush);
- assert (addr>=0);
+ assert (addr && H5F_addr_defined (addr));
assert (thing);
idx = H5AC_HASH (f, addr);
cache = f->shared->cache;
@@ -767,9 +764,9 @@ H5AC_unprotect (H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing)
* better not be another copy of the protected object.
*/
if (slot->type) {
- assert (slot->addr!=addr);
+ assert (H5F_addr_ne (&(slot->addr), addr));
flush = slot->type->flush;
- status = (flush)(f, TRUE, slot->addr, slot->thing);
+ status = (flush)(f, TRUE, &(slot->addr), slot->thing);
if (status<0) {
HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL);
}
@@ -784,7 +781,7 @@ H5AC_unprotect (H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing)
{
int found, i;
for (i=0,found=FALSE; i<slot->nprots && !found; i++) {
- if (addr==slot->prot[i].addr) {
+ if (H5F_addr_eq (addr, &(slot->prot[i].addr))) {
assert (slot->prot[i].type==type);
HDmemmove (slot->prot+i, slot->prot+i+1,
((slot->nprots-i)-1) * sizeof(H5AC_prot_t));
@@ -800,7 +797,7 @@ H5AC_unprotect (H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing)
* Insert the object back into the cache; it is no longer protected.
*/
slot->type = type;
- slot->addr = addr;
+ slot->addr = *addr;
slot->thing = thing;
cache->nprots -= 1;
@@ -829,7 +826,7 @@ herr_t
H5AC_debug (H5F_t *f)
{
H5AC_subid_t i;
- char s[32];
+ char s[32], ascii[32];
H5AC_t *cache = f->shared->cache;
double miss_rate;
@@ -865,10 +862,15 @@ H5AC_debug (H5F_t *f)
miss_rate = 0.0;
}
- fprintf (stderr, " %18s: %8d %8d %7.2f%% %8d%+-9d\n", s,
+ if (miss_rate>100) {
+ sprintf (ascii, "%7d%%", (int)(miss_rate+0.5));
+ } else {
+ sprintf (ascii, "%7.2f%%", miss_rate);
+ }
+ fprintf (stderr, " %18s: %8d %8d %7s %8d%+-9d\n", s,
cache->diagnostics[i].nhits,
cache->diagnostics[i].nmisses,
- miss_rate,
+ ascii,
cache->diagnostics[i].ninits,
cache->diagnostics[i].nflushes-cache->diagnostics[i].ninits);
}
diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h
index 884bc3c6..28710d9 100644
--- a/src/H5ACprivate.h
+++ b/src/H5ACprivate.h
@@ -24,6 +24,16 @@
#include <H5Fprivate.h>
/*
+ * Feature: Define H5AC_DEBUG on the compiler command line if you want to
+ * debug H5AC_protect() and H5AC_unprotect() by insuring that
+ * nothing accesses protected objects. NDEBUG must not be defined
+ * in order for this to have any effect.
+ */
+#ifdef NDEBUG
+# undef H5AC_DEBUG
+#endif
+
+/*
* Class methods pertaining to caching. Each type of cached object will
* have a constant variable with permanent life-span that describes how
* to cache the object. That variable will be of type H5AC_class_t and
@@ -48,9 +58,10 @@ typedef enum H5AC_subid_t {
typedef struct H5AC_class_t {
H5AC_subid_t id;
- void *(*load)(H5F_t*, haddr_t addr, const void *udata1,
+ void *(*load)(H5F_t*, const haddr_t *addr, const void *udata1,
void *udata2);
- herr_t (*flush)(H5F_t*, hbool_t dest, haddr_t addr, void *thing);
+ herr_t (*flush)(H5F_t*, hbool_t dest, const haddr_t *addr,
+ void *thing);
} H5AC_class_t;
/*
@@ -59,7 +70,7 @@ typedef struct H5AC_class_t {
* own cache, an array of slots.
*/
#define H5AC_NSLOTS 10330 /*prime number tend to work best */
-#define H5AC_HASH(F,ADDR) ((unsigned)(ADDR) % (F)->shared->cache->nslots)
+#define H5AC_HASH(F,ADDR_P) H5F_addr_hash(ADDR_P,(F)->shared->cache->nslots)
typedef struct H5AC_prot_t {
const H5AC_class_t *type; /*type of protected thing */
@@ -92,27 +103,28 @@ typedef struct 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 *H5AC_find_f (H5F_t *f, const H5AC_class_t *type, const haddr_t *addr,
const void *udata1, void *udata2);
-void * H5AC_protect (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
+void * H5AC_protect (H5F_t *f, const H5AC_class_t *type, const haddr_t *addr,
const void *udata1, void *udata2);
-herr_t H5AC_unprotect (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
+herr_t H5AC_unprotect (H5F_t *f, const H5AC_class_t *type, const haddr_t *addr,
void *thing);
-herr_t H5AC_flush (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
+herr_t H5AC_flush (H5F_t *f, const H5AC_class_t *type, const haddr_t *addr,
hbool_t destroy);
herr_t H5AC_new (H5F_t *f, intn size_hint);
-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,
+herr_t H5AC_rename (H5F_t *f, const H5AC_class_t *type,
+ const haddr_t *old_addr, const haddr_t *new_addr);
+herr_t H5AC_set (H5F_t *f, const H5AC_class_t *type, const 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)) ? \
+#define H5AC_find(F,TYPE,ADDR_P,UDATA1,UDATA2) \
+ (((F)->shared->cache->slot[H5AC_HASH(F,ADDR_P)].type==(TYPE) && \
+ H5F_addr_eq (&((F)->shared->cache->slot[H5AC_HASH(F,ADDR_P)].addr), \
+ ADDR_P)) ? \
((F)->shared->cache->diagnostics[(TYPE)->id].nhits++, \
- (F)->shared->cache->slot[H5AC_HASH(F,ADDR)].thing) : \
- H5AC_find_f (F, TYPE, ADDR, UDATA1, UDATA2))
+ (F)->shared->cache->slot[H5AC_HASH(F,ADDR_P)].thing) : \
+ H5AC_find_f (F, TYPE, ADDR_P, UDATA1, UDATA2))
#endif /* !_H5ACprivate_H */
diff --git a/src/H5B.c b/src/H5B.c
index a735799..23bc08c 100644
--- a/src/H5B.c
+++ b/src/H5B.c
@@ -94,45 +94,41 @@
#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)))
/* PRIVATE PROTOTYPES */
-static haddr_t H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type,
- H5B_ins_t *anchor,
- uint8 *lt_key, hbool_t *lt_key_changed,
- uint8 *md_key, void *udata,
- uint8 *rt_key, hbool_t *rt_key_changed);
+static H5B_ins_t H5B_insert_helper (H5F_t *f, const haddr_t *addr,
+ const H5B_class_t *type,
+ uint8 *lt_key, hbool_t *lt_key_changed,
+ uint8 *md_key, void *udata,
+ uint8 *rt_key, hbool_t *rt_key_changed,
+ haddr_t *retval);
static herr_t H5B_insert_child (H5F_t *f, const H5B_class_t *type,
- H5B_t *bt, intn idx, haddr_t child,
+ H5B_t *bt, intn idx, const 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, const void *_type,
+static herr_t H5B_flush (H5F_t *f, hbool_t destroy, const haddr_t *addr,
+ H5B_t *b);
+static H5B_t *H5B_load (H5F_t *f, const 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);
+static herr_t H5B_split (H5F_t *f, const H5B_class_t *type, H5B_t *old_bt,
+ const haddr_t *old_addr, void *udata,
+ haddr_t *new_addr /*out*/);
#ifdef H5B_DEBUG
-static herr_t H5B_assert (H5F_t *f, haddr_t addr, const H5B_class_t *type,
- void *udata);
+static herr_t H5B_assert (H5F_t *f, const 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] = {{
H5AC_BT_ID,
- (void*(*)(H5F_t*,haddr_t,const void*,void*))H5B_load,
- (herr_t(*)(H5F_t*,hbool_t,haddr_t,void*))H5B_flush,
+ (void*(*)(H5F_t*,const haddr_t*,const void*,void*))H5B_load,
+ (herr_t(*)(H5F_t*,hbool_t,const haddr_t*,void*))H5B_flush,
}};
/* Is the H5B interface initialized? */
@@ -146,7 +142,8 @@ static interface_initialize_g = FALSE;
* passed as an argument to the sizeof_rkey() method for the
* B-tree.
*
- * Return: Success: address of new node.
+ * Return: Success: SUCCEED, address of new node is returned
+ * through the RETVAL argument.
*
* Failure: FAIL
*
@@ -158,11 +155,10 @@ static interface_initialize_g = FALSE;
*
*-------------------------------------------------------------------------
*/
-haddr_t
-H5B_new (H5F_t *f, const H5B_class_t *type, void *udata)
+herr_t
+H5B_new (H5F_t *f, const H5B_class_t *type, void *udata, haddr_t *retval)
{
H5B_t *bt=NULL;
- haddr_t addr;
size_t size, sizeof_rkey;
size_t total_native_keysize;
intn offset, i;
@@ -174,13 +170,14 @@ H5B_new (H5F_t *f, const H5B_class_t *type, void *udata)
*/
assert (f);
assert (type);
+ assert (retval);
/*
* Allocate file and memory data structures.
*/
sizeof_rkey = (type->get_sizeof_rkey)(f, udata);
size = H5B_nodesize (f, type, &total_native_keysize, sizeof_rkey);
- if ((addr = H5MF_alloc (f, size))<0) {
+ if (H5MF_alloc (f, H5MF_META, size, retval)<0) {
HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL);
}
bt = H5MM_xmalloc (sizeof(H5B_t));
@@ -190,7 +187,8 @@ H5B_new (H5F_t *f, const H5B_class_t *type, void *udata)
bt->ndirty = 0;
bt->type = type;
bt->level = 0;
- bt->left = bt->right = 0;
+ H5F_addr_undef (&(bt->left));
+ H5F_addr_undef (&(bt->right));
bt->nchildren = 0;
bt->page = H5MM_xcalloc (1, size); /*use calloc() to keep file clean*/
bt->native = H5MM_xmalloc (total_native_keysize);
@@ -209,7 +207,7 @@ H5B_new (H5F_t *f, const H5B_class_t *type, void *udata)
bt->key[i].dirty = FALSE;
bt->key[i].rkey = bt->page + offset;
bt->key[i].nkey = NULL;
- bt->child[i] = 0;
+ H5F_addr_undef (bt->child+i);
}
/*
@@ -222,14 +220,14 @@ H5B_new (H5F_t *f, const H5B_class_t *type, void *udata)
/*
* Cache the new B-tree node.
*/
- if (H5AC_set (f, H5AC_BT, addr, bt)<0) {
+ if (H5AC_set (f, H5AC_BT, retval, bt)<0) {
HRETURN_ERROR (H5E_BTREE, H5E_CANTINIT, FAIL);
}
#ifdef H5B_DEBUG
- H5B_assert (f, addr, type, udata);
+ H5B_assert (f, retval, type, udata);
#endif
- FUNC_LEAVE (addr);
+ FUNC_LEAVE (SUCCEED);
}
@@ -251,7 +249,7 @@ H5B_new (H5F_t *f, const H5B_class_t *type, void *udata)
*-------------------------------------------------------------------------
*/
static H5B_t *
-H5B_load (H5F_t *f, haddr_t addr, const void *_type, void *udata)
+H5B_load (H5F_t *f, const haddr_t *addr, const void *_type, void *udata)
{
const H5B_class_t *type = (const H5B_class_t *)_type;
size_t size, total_nkey_size;
@@ -264,7 +262,7 @@ H5B_load (H5F_t *f, haddr_t addr, const void *_type, void *udata)
/* Check arguments */
assert (f);
- assert (addr>=0);
+ assert (addr && H5F_addr_defined (addr));
assert (type);
assert (type->get_sizeof_rkey);
@@ -299,8 +297,8 @@ H5B_load (H5F_t *f, haddr_t addr, const void *_type, void *udata)
UINT16DECODE (p, bt->nchildren);
/* sibling pointers */
- H5F_decode_offset (f, p, bt->left);
- H5F_decode_offset (f, p, bt->right);
+ H5F_addr_decode (f, (const uint8**)&p, &(bt->left));
+ H5F_addr_decode (f, (const uint8**)&p, &(bt->right));
/* the child/key pairs */
for (i=0; i<2*H5B_K(f,type); i++) {
@@ -311,9 +309,9 @@ H5B_load (H5F_t *f, haddr_t addr, const void *_type, void *udata)
bt->key[i].nkey = NULL;
if (i<bt->nchildren) {
- H5F_decode_offset (f, p, bt->child[i]);
+ H5F_addr_decode (f, (const uint8**)&p, bt->child+i);
} else {
- bt->child[i] = 0;
+ H5F_addr_undef (bt->child+i);
p += H5F_SIZEOF_OFFSET(f);
}
}
@@ -354,7 +352,7 @@ H5B_load (H5F_t *f, haddr_t addr, const void *_type, void *udata)
*-------------------------------------------------------------------------
*/
static herr_t
-H5B_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5B_t *bt)
+H5B_flush (H5F_t *f, hbool_t destroy, const haddr_t *addr, H5B_t *bt)
{
intn i;
size_t size = 0;
@@ -366,7 +364,7 @@ H5B_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5B_t *bt)
* Check arguments.
*/
assert (f);
- assert (addr>=0);
+ assert (addr && H5F_addr_defined (addr));
assert (bt);
assert (bt->type);
assert (bt->type->encode);
@@ -387,8 +385,8 @@ H5B_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5B_t *bt)
UINT16ENCODE (p, bt->nchildren);
/* sibling pointers */
- H5F_encode_offset (f, p, bt->left);
- H5F_encode_offset (f, p, bt->right);
+ H5F_addr_encode (f, &p, &(bt->left));
+ H5F_addr_encode (f, &p, &(bt->right));
/* child keys and pointers */
for (i=0; i<=bt->nchildren; i++) {
@@ -408,7 +406,7 @@ H5B_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5B_t *bt)
/* encode the child address */
if (i<bt->ndirty) {
- H5F_encode_offset (f, p, bt->child[i]);
+ H5F_addr_encode (f, &p, &(bt->child[i]));
} else {
p += H5F_SIZEOF_OFFSET(f);
}
@@ -451,10 +449,10 @@ H5B_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5B_t *bt)
* pointers since it assumes that all nodes can be reached
* from the parent node.
*
- * Return: Success: 0 if found, values returned through the
- * RETVAL argument.
+ * Return: Success: SUCCEED if found, values returned through the
+ * UDATA argument.
*
- * Failure: -1 if not found.
+ * Failure: FAIL if not found, UDATA is undefined.
*
* Programmer: Robb Matzke
* matzke@llnl.gov
@@ -465,7 +463,7 @@ H5B_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5B_t *bt)
*-------------------------------------------------------------------------
*/
herr_t
-H5B_find (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata)
+H5B_find (H5F_t *f, const H5B_class_t *type, const haddr_t *addr, void *udata)
{
H5B_t *bt=NULL;
intn idx=-1, lt=0, rt, cmp=1;
@@ -481,7 +479,7 @@ H5B_find (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata)
assert (type->decode);
assert (type->cmp3);
assert (type->found);
- assert (addr>=0);
+ assert (addr && H5F_addr_defined (addr));
/*
* Perform a binary search to locate the child which contains
@@ -515,11 +513,11 @@ H5B_find (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata)
*/
assert (idx>=0 && idx<bt->nchildren);
if (bt->level > 0) {
- if ((ret_value = H5B_find (f, type, bt->child[idx], udata))<0) {
+ if ((ret_value = H5B_find (f, type, bt->child+idx, udata))<0) {
HGOTO_ERROR (H5E_BTREE, H5E_NOTFOUND, FAIL);
}
} else {
- ret_value = (type->found)(f, bt->child[idx], bt->key[idx].nkey,
+ ret_value = (type->found)(f, bt->child+idx, bt->key[idx].nkey,
udata, bt->key[idx+1].nkey);
if (ret_value<0) {
HGOTO_ERROR (H5E_BTREE, H5E_NOTFOUND, FAIL);
@@ -547,7 +545,8 @@ done:
* The OLD_BT argument is a pointer to a protected B-tree
* node.
*
- * Return: Success: Address of the new node.
+ * Return: Success: SUCCEED. The address of the new node is
+ * returned through the NEW_ADDR argument.
*
* Failure: FAIL
*
@@ -559,12 +558,12 @@ done:
*
*-------------------------------------------------------------------------
*/
-static haddr_t
-H5B_split (H5F_t *f, H5B_class_t *type, H5B_t *old_bt, haddr_t old_addr,
- void *udata)
+static herr_t
+H5B_split (H5F_t *f, const H5B_class_t *type, H5B_t *old_bt,
+ const haddr_t *old_addr, void *udata, haddr_t *new_addr /*out*/)
{
H5B_t *new_bt=NULL, *tmp_bt=NULL;
- haddr_t ret_value=FAIL, new_addr=FAIL;
+ herr_t ret_value=FAIL;
intn i, k;
size_t recsize = 0;
@@ -575,7 +574,7 @@ 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 (old_addr && H5F_addr_defined (old_addr));
/*
* Initialize variables.
@@ -587,7 +586,7 @@ H5B_split (H5F_t *f, H5B_class_t *type, H5B_t *old_bt, haddr_t old_addr,
/*
* Create the new B-tree node.
*/
- if ((new_addr = H5B_new (f, type, udata))<0) {
+ if (H5B_new (f, type, udata, new_addr/*out*/)<0) {
HGOTO_ERROR (H5E_BTREE, H5E_CANTINIT, FAIL);
}
if (NULL==(new_bt=H5AC_protect (f, H5AC_BT, new_addr, type, udata))) {
@@ -627,20 +626,20 @@ H5B_split (H5F_t *f, H5B_class_t *type, H5B_t *old_bt, haddr_t old_addr,
/*
* Update sibling pointers.
*/
- new_bt->left = old_addr;
+ 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,
+ if (H5F_addr_defined (&(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;
+ tmp_bt->left = *new_addr;
}
- old_bt->right = new_addr;
+ old_bt->right = *new_addr;
- HGOTO_DONE (new_addr);
+ HGOTO_DONE (SUCCEED);
done:
{
@@ -726,9 +725,7 @@ H5B_decode_keys (H5F_t *f, H5B_t *bt, intn idx)
* Purpose: Adds a new item to the B-tree. If the root node of
* the B-tree splits then the B-tree gets a new address.
*
- * Return: Success: Address of the root of the B-tree. The
- * B-tree root address may change if the old
- * root is split.
+ * Return: Success: SUCCEED.
*
* Failure: FAIL
*
@@ -740,18 +737,18 @@ H5B_decode_keys (H5F_t *f, H5B_t *bt, intn idx)
*
*-------------------------------------------------------------------------
*/
-haddr_t
-H5B_insert (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata)
+herr_t
+H5B_insert (H5F_t *f, const H5B_class_t *type, const haddr_t *addr,
+ void *udata)
{
- uint8 lt_key[256], md_key[256], rt_key[256];
+ uint8 lt_key[512], md_key[512], rt_key[512];
hbool_t lt_key_changed=FALSE, rt_key_changed=FALSE;
- haddr_t child, new_root;
+ haddr_t child, old_root;
intn level;
H5B_t *bt;
size_t size;
uint8 *buf;
- haddr_t tmp_addr;
- H5B_ins_t anchor = H5B_INS_ERROR;
+ H5B_ins_t my_ins = H5B_INS_ERROR;
FUNC_ENTER (H5B_insert, NULL, FAIL);
@@ -761,14 +758,15 @@ H5B_insert (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata)
assert (f);
assert (type);
assert (type->sizeof_nkey <= sizeof lt_key);
+ assert (addr && H5F_addr_defined (addr));
- child = H5B_insert_helper (f, addr, type, &anchor, lt_key, &lt_key_changed,
- md_key, udata, rt_key, &rt_key_changed);
- if (child<0 || anchor<0) {
+ if ((my_ins=H5B_insert_helper (f, addr, type, lt_key, &lt_key_changed,
+ md_key, udata, rt_key, &rt_key_changed,
+ &child/*out*/))<0 || my_ins<0) {
HRETURN_ERROR (H5E_BTREE, H5E_CANTINIT, FAIL);
}
- if (H5B_INS_NOOP==anchor) HRETURN (addr);
- assert (H5B_INS_RIGHT==anchor);
+ if (H5B_INS_NOOP==my_ins) HRETURN (SUCCEED);
+ assert (H5B_INS_RIGHT==my_ins);
/* the current root */
if (NULL==(bt = H5AC_find (f, H5AC_BT, addr, type, udata))) {
@@ -783,7 +781,7 @@ H5B_insert (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata)
}
/* the new node */
- if (NULL==(bt = H5AC_find (f, H5AC_BT, child, type, udata))) {
+ if (NULL==(bt = H5AC_find (f, H5AC_BT, &child, type, udata))) {
HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL);
}
if (!rt_key_changed) {
@@ -801,9 +799,7 @@ H5B_insert (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata)
*/
size = H5B_nodesize (f, type, NULL, bt->sizeof_rkey);
buf = H5MM_xmalloc (size);
- tmp_addr = H5MF_alloc (f, size);
-
- if (tmp_addr<0) {
+ if (H5MF_alloc (f, H5MF_META, size, &old_root/*out*/)<0) {
HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL);
}
if (H5AC_flush (f, H5AC_BT, addr, FALSE)<0) {
@@ -812,37 +808,34 @@ H5B_insert (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata)
if (H5F_block_read (f, addr, size, buf)<0) {
HRETURN_ERROR (H5E_BTREE, H5E_READERROR, FAIL);
}
- if (H5F_block_write (f, tmp_addr, size, buf)<0) {
+ if (H5F_block_write (f, &old_root, size, buf)<0) {
HRETURN_ERROR (H5E_BTREE, H5E_WRITEERROR, FAIL);
}
- if (H5AC_rename (f, H5AC_BT, addr, tmp_addr)<0) {
+ if (H5AC_rename (f, H5AC_BT, addr, &old_root)<0) {
HRETURN_ERROR (H5E_BTREE, H5E_CANTSPLIT, FAIL);
}
buf = H5MM_xfree (buf);
- new_root = addr;
- addr = tmp_addr;
/* update the new child's left pointer */
- if (NULL==(bt=H5AC_find (f, H5AC_BT, child, type, udata))) {
+ if (NULL==(bt=H5AC_find (f, H5AC_BT, &child, type, udata))) {
HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL);
}
bt->dirty = TRUE;
- bt->left = addr;
+ bt->left = old_root;
- /* clear the old root at the old address */
- if (NULL==(bt=H5AC_find (f, H5AC_BT, new_root, type, udata))) {
+ /* clear the old root at the old address (we already copied it)*/
+ if (NULL==(bt=H5AC_find (f, H5AC_BT, addr, type, udata))) {
HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL);
}
bt->dirty = TRUE;
bt->ndirty = 0;
- bt->left = 0;
- bt->right = 0;
+ H5F_addr_undef (&(bt->left));
+ H5F_addr_undef (&(bt->right));
bt->nchildren = 0;
-
/* the new root */
- if (NULL==(bt = H5AC_find (f, H5AC_BT, new_root, type, udata))) {
+ if (NULL==(bt = H5AC_find (f, H5AC_BT, addr, type, udata))) {
HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL);
}
bt->dirty = TRUE;
@@ -850,7 +843,7 @@ H5B_insert (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata)
bt->level = level+1;
bt->nchildren = 2;
- bt->child[0] = addr;
+ bt->child[0] = old_root;
bt->key[0].dirty = TRUE;
bt->key[0].nkey = bt->native;
HDmemcpy (bt->key[0].nkey, lt_key, type->sizeof_nkey);
@@ -865,9 +858,9 @@ H5B_insert (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata)
HDmemcpy (bt->key[2].nkey, rt_key, type->sizeof_nkey);
#ifdef H5B_DEBUG
- H5B_assert (f, new_root, type, udata);
+ H5B_assert (f, addr, type, udata);
#endif
- FUNC_LEAVE (new_root);
+ FUNC_LEAVE (SUCCEED);
}
@@ -892,13 +885,15 @@ H5B_insert (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata)
*/
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)
+ intn idx, const haddr_t *child, H5B_ins_t anchor,
+ void *md_key)
{
size_t recsize;
intn i;
FUNC_ENTER (H5B_insert_child, NULL, FAIL);
assert (bt);
+ assert (child);
bt->dirty = TRUE;
recsize = bt->sizeof_rkey + H5F_SIZEOF_OFFSET(f);
@@ -958,7 +953,7 @@ H5B_insert_child (H5F_t *f, const H5B_class_t *type, H5B_t *bt,
bt->child + idx,
(bt->nchildren - idx) * sizeof(haddr_t));
- bt->child[idx] = child;
+ bt->child[idx] = *child;
bt->nchildren += 1;
bt->ndirty = bt->nchildren;
@@ -982,14 +977,12 @@ H5B_insert_child (H5F_t *f, const H5B_class_t *type, H5B_t *bt,
* appears as the max key in the left node and the min key
* in the right node).
*
- * Return: Success: Address of the new node if the node
- * splits. The new node is always to the
- * right of the previous node.
- *
- * 0 if the node didn't split. The MD_KEY
- * buffer is undefined.
+ * Return: Success: A B-tree operation. The address of the new
+ * node, if the node splits, is returned through
+ * the NEW_NODE argument. The new node is always
+ * to the right of the previous node.
*
- * Failure: FAIL
+ * Failure: H5B_INS_ERROR
*
* Programmer: Robb Matzke
* matzke@llnl.gov
@@ -999,34 +992,35 @@ H5B_insert_child (H5F_t *f, const H5B_class_t *type, H5B_t *bt,
*
*-------------------------------------------------------------------------
*/
-static haddr_t
-H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type,
- H5B_ins_t *parent_ins,
+static H5B_ins_t
+H5B_insert_helper (H5F_t *f, const haddr_t *addr, const H5B_class_t *type,
uint8 *lt_key, hbool_t *lt_key_changed,
uint8 *md_key, void *udata,
- uint8 *rt_key, hbool_t *rt_key_changed)
+ uint8 *rt_key, hbool_t *rt_key_changed,
+ haddr_t *new_node/*out*/)
{
H5B_t *bt=NULL, *twin=NULL, *tmp_bt=NULL;
intn lt=0, idx=-1, rt, cmp=-1;
- haddr_t child_addr=0, twin_addr=0, ret_value=FAIL;
+ haddr_t child_addr;
H5B_ins_t my_ins = H5B_INS_ERROR;
+ H5B_ins_t ret_value = H5B_INS_ERROR;
- FUNC_ENTER (H5B_insert_helper, NULL, FAIL);
+ FUNC_ENTER (H5B_insert_helper, NULL, H5B_INS_ERROR);
/*
* Check arguments
*/
assert (f);
- assert (addr>=0);
+ assert (addr && H5F_addr_defined (addr));
assert (type);
assert (type->decode);
assert (type->cmp3);
assert (type->new);
- assert (parent_ins && H5B_INS_ERROR==*parent_ins);
assert (lt_key);
assert (lt_key_changed);
assert (rt_key);
assert (rt_key_changed);
+ assert (new_node);
*lt_key_changed = FALSE;
*rt_key_changed = FALSE;
@@ -1037,14 +1031,14 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type,
* should get the new data.
*/
if (NULL==(bt=H5AC_protect (f, H5AC_BT, addr, type, udata))) {
- HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL);
+ HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, H5B_INS_ERROR);
}
rt = bt->nchildren;
while (lt<rt && cmp) {
idx = (lt + rt) / 2;
if (H5B_decode_keys (f, bt, idx)<0) {
- HRETURN_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL);
+ HRETURN_ERROR (H5E_BTREE, H5E_CANTDECODE, H5B_INS_ERROR);
}
if ((cmp=(type->cmp3)(f, bt->key[idx].nkey, udata,
bt->key[idx+1].nkey))<0) {
@@ -1062,24 +1056,27 @@ 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, H5B_INS_FIRST, bt->key[0].nkey, udata,
- bt->key[1].nkey))<0) {
+ if ((type->new)(f, H5B_INS_FIRST, bt->key[0].nkey, udata,
+ bt->key[1].nkey, bt->child+0/*out*/)<0) {
bt->key[0].nkey = bt->key[1].nkey = NULL;
- HGOTO_ERROR (H5E_BTREE, H5E_CANTINIT, FAIL);
+ HGOTO_ERROR (H5E_BTREE, H5E_CANTINIT, H5B_INS_ERROR);
}
bt->nchildren = 1;
bt->dirty = TRUE;
bt->ndirty = 1;
- bt->child[0] = child_addr;
bt->key[0].dirty = TRUE;
bt->key[1].dirty = TRUE;
idx = 0;
if (type->follow_min) {
- child_addr = (type->insert)(f, bt->child[idx], &my_ins,
- bt->key[idx].nkey, lt_key_changed,
- md_key, udata,
- bt->key[idx+1].nkey, rt_key_changed);
+ if ((my_ins=(type->insert)(f, bt->child+idx,
+ bt->key[idx].nkey, lt_key_changed,
+ md_key, udata,
+ bt->key[idx+1].nkey, rt_key_changed,
+ &child_addr/*out*/))<0) {
+ /* Can't insert first leaf node */
+ HGOTO_ERROR (H5E_BTREE, H5E_CANTINSERT, H5B_INS_ERROR);
+ }
} else {
my_ins = H5B_INS_NOOP;
}
@@ -1091,13 +1088,17 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type,
*/
idx = 0;
if (H5B_decode_keys (f, bt, idx)<0) {
- HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL);
+ HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, H5B_INS_ERROR);
}
- child_addr = H5B_insert_helper (f, bt->child[idx], type, &my_ins,
- bt->key[idx].nkey, lt_key_changed,
- md_key, udata,
- bt->key[idx+1].nkey, rt_key_changed);
-
+ if ((my_ins=H5B_insert_helper (f, bt->child+idx, type,
+ bt->key[idx].nkey, lt_key_changed,
+ md_key, udata,
+ bt->key[idx+1].nkey, rt_key_changed,
+ &child_addr/*out*/))<0) {
+ /* Can't insert minimum subtree */
+ HGOTO_ERROR (H5E_BTREE, H5E_CANTINSERT, H5B_INS_ERROR);
+ }
+
} else if (cmp<0 && idx<=0 && type->follow_min) {
/*
* The value being inserted is less than any leaf node out of this
@@ -1106,12 +1107,16 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type,
*/
idx = 0;
if (H5B_decode_keys (f, bt, idx)<0) {
- HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL);
+ HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, H5B_INS_ERROR);
+ }
+ if ((my_ins=(type->insert)(f, bt->child+idx,
+ bt->key[idx].nkey, lt_key_changed,
+ md_key, udata,
+ bt->key[idx+1].nkey, rt_key_changed,
+ &child_addr/*out*/))<0) {
+ /* Can't insert minimum leaf node */
+ HGOTO_ERROR (H5E_BTREE, H5E_CANTINSERT, H5B_INS_ERROR);
}
- child_addr = (type->insert)(f, bt->child[idx], &my_ins,
- bt->key[idx].nkey, lt_key_changed,
- md_key, udata,
- bt->key[idx+1].nkey, rt_key_changed);
} else if (cmp<0 && idx<=0) {
/*
@@ -1121,12 +1126,15 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type,
*/
idx = 0;
if (H5B_decode_keys (f, bt, idx)<0) {
- HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL);
+ HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, H5B_INS_ERROR);
}
my_ins = H5B_INS_LEFT;
HDmemcpy (md_key, bt->key[idx].nkey, type->sizeof_nkey);
- child_addr = (type->new)(f, H5B_INS_LEFT, bt->key[idx].nkey,
- udata, md_key);
+ if ((type->new)(f, H5B_INS_LEFT, bt->key[idx].nkey, udata, md_key,
+ &child_addr/*out*/)<0) {
+ /* Can't insert minimum leaf node */
+ HGOTO_ERROR (H5E_BTREE, H5E_CANTINSERT, H5B_INS_ERROR);
+ }
*lt_key_changed = TRUE;
} else if (cmp>0 && idx+1>=bt->nchildren && bt->level>0) {
@@ -1136,12 +1144,16 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type,
*/
idx = bt->nchildren - 1;
if (H5B_decode_keys (f, bt, idx)<0) {
- HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL);
+ HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, H5B_INS_ERROR);
+ }
+ if ((my_ins=H5B_insert_helper (f, bt->child+idx, type,
+ bt->key[idx].nkey, lt_key_changed,
+ md_key, udata,
+ bt->key[idx+1].nkey, rt_key_changed,
+ &child_addr/*out*/))<0) {
+ /* Can't insert maximum subtree */
+ HGOTO_ERROR (H5E_BTREE, H5E_CANTINSERT, H5B_INS_ERROR);
}
- child_addr = H5B_insert_helper (f, bt->child[idx], type, &my_ins,
- bt->key[idx].nkey, lt_key_changed,
- md_key, udata,
- bt->key[idx+1].nkey, rt_key_changed);
} else if (cmp>0 && idx+1>=bt->nchildren && type->follow_max) {
/*
@@ -1151,12 +1163,16 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type,
*/
idx = bt->nchildren - 1;
if (H5B_decode_keys (f, bt, idx)<0) {
- HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL);
+ HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, H5B_INS_ERROR);
+ }
+ if ((my_ins=(type->insert)(f, bt->child+idx,
+ bt->key[idx].nkey, lt_key_changed,
+ md_key, udata,
+ bt->key[idx+1].nkey, rt_key_changed,
+ &child_addr/*out*/))<0) {
+ /* Can't insert maximum leaf node */
+ HGOTO_ERROR (H5E_BTREE, H5E_CANTINSERT, H5B_INS_ERROR);
}
- child_addr = (type->insert)(f, bt->child[idx], &my_ins,
- bt->key[idx].nkey, lt_key_changed,
- md_key, udata,
- bt->key[idx+1].nkey, rt_key_changed);
} else if (cmp>0 && idx+1>=bt->nchildren) {
/*
@@ -1166,12 +1182,15 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type,
*/
idx = bt->nchildren - 1;
if (H5B_decode_keys (f, bt, idx)<0) {
- HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL);
+ HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, H5B_INS_ERROR);
}
my_ins = H5B_INS_RIGHT;
HDmemcpy (md_key, bt->key[idx+1].nkey, type->sizeof_nkey);
- child_addr = (type->new)(f, H5B_INS_RIGHT, md_key,
- udata, bt->key[idx+1].nkey);
+ if ((type->new)(f, H5B_INS_RIGHT, md_key, udata, bt->key[idx+1].nkey,
+ &child_addr/*out*/)<0) {
+ /* Can't insert maximum leaf node */
+ HGOTO_ERROR (H5E_BTREE, H5E_CANTINSERT, H5B_INS_ERROR);
+ }
*rt_key_changed = TRUE;
} else if (cmp) {
@@ -1186,29 +1205,31 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type,
* Follow a branch out of this node to another subtree.
*/
assert (idx>=0 && idx<bt->nchildren);
- child_addr = H5B_insert_helper (f, bt->child[idx], type, &my_ins,
- bt->key[idx].nkey, lt_key_changed,
- md_key, udata,
- bt->key[idx+1].nkey, rt_key_changed);
-
+ if ((my_ins=H5B_insert_helper (f, bt->child+idx, type,
+ bt->key[idx].nkey, lt_key_changed,
+ md_key, udata,
+ bt->key[idx+1].nkey, rt_key_changed,
+ &child_addr/*out*/))<0) {
+ /* Can't insert subtree */
+ HGOTO_ERROR (H5E_BTREE, H5E_CANTINSERT, H5B_INS_ERROR);
+ }
} else {
/*
* Follow a branch out of this node to a leaf node of some other type.
*/
assert (idx>=0 && idx<bt->nchildren);
- child_addr = (type->insert)(f, bt->child[idx], &my_ins,
- bt->key[idx].nkey, lt_key_changed,
- md_key, udata,
- bt->key[idx+1].nkey, rt_key_changed);
+ if ((my_ins=(type->insert)(f, bt->child+idx,
+ bt->key[idx].nkey, lt_key_changed,
+ md_key, udata,
+ bt->key[idx+1].nkey, rt_key_changed,
+ &child_addr/*out*/))<0) {
+ /* Can't insert leaf node */
+ HGOTO_ERROR (H5E_BTREE, H5E_CANTINSERT, H5B_INS_ERROR);
+ }
}
-
- if (child_addr<0 || my_ins<0) {
- /* Insertion failed */
- HGOTO_ERROR (H5E_BTREE, H5E_CANTINSERT, FAIL);
- }
-
+ assert (my_ins>=0);
/*
* Update the left and right keys of the current node.
@@ -1239,7 +1260,7 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type,
bt->child[idx] = child_addr;
bt->dirty = TRUE;
bt->ndirty = MAX (bt->ndirty, idx+1);
- *parent_ins = H5B_INS_NOOP;
+ ret_value = H5B_INS_NOOP;
} else if (H5B_INS_LEFT==my_ins || H5B_INS_RIGHT==my_ins) {
/* Make sure IDX is the slot number for the new node. */
@@ -1247,11 +1268,13 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type,
/* 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 (H5B_split (f, type, bt, addr, udata, new_node/*out*/)<0) {
+ /*can't split node*/
+ HGOTO_ERROR (H5E_BTREE, H5E_CANTSPLIT, H5B_INS_ERROR);
}
- 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 (NULL==(twin=H5AC_protect (f, H5AC_BT, new_node, type, udata))) {
+ /*can't load B-tree*/
+ HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, H5B_INS_ERROR);
}
if (idx<=H5B_K (f, type)) {
tmp_bt = bt;
@@ -1264,9 +1287,10 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type,
}
/* Insert the child */
- if (H5B_insert_child (f, type, tmp_bt, idx, child_addr, my_ins,
+ if (H5B_insert_child (f, type, tmp_bt, idx, &child_addr, my_ins,
md_key)<0) {
- HGOTO_ERROR (H5E_BTREE, H5E_CANTINSERT, FAIL);/*can't insert child*/
+ /*can't insert child*/
+ HGOTO_ERROR (H5E_BTREE, H5E_CANTINSERT, H5B_INS_ERROR);
}
}
@@ -1277,11 +1301,11 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type,
*/
if (twin) {
if (!twin->key[0].nkey && H5B_decode_key (f, twin, 0)<0) {
- HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL);
+ HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, H5B_INS_ERROR);
}
HDmemcpy (md_key, twin->key[0].nkey, type->sizeof_nkey);
- *parent_ins = H5B_INS_RIGHT;
-#ifndef NDEBUG
+ ret_value = H5B_INS_RIGHT;
+#ifdef H5B_DEBUG
/*
* The max key in the original left node must be equal to the min key
* in the new node.
@@ -1289,23 +1313,21 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type,
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);
}
+ cmp = (type->cmp2)(f, bt->key[bt->nchildren].nkey, udata,
+ twin->key[0].nkey);
+ assert (0==cmp);
#endif
} else {
- *parent_ins = H5B_INS_NOOP;
+ ret_value = H5B_INS_NOOP;
}
- HGOTO_DONE (twin_addr);
-
done:
{
herr_t e1 = (bt && H5AC_unprotect (f, H5AC_BT, addr, bt)<0);
- herr_t e2 = (twin && H5AC_unprotect (f, H5AC_BT, twin_addr, twin)<0);
+ herr_t e2 = (twin && H5AC_unprotect (f, H5AC_BT, new_node, twin)<0);
if (e1 || e2) { /*use vars to prevent short-circuit of side effects*/
- HRETURN_ERROR (H5E_BTREE, H5E_PROTECT, FAIL);
+ HRETURN_ERROR (H5E_BTREE, H5E_PROTECT, H5B_INS_ERROR);
}
}
@@ -1332,10 +1354,11 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5B_list (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata)
+H5B_list (H5F_t *f, const H5B_class_t *type, const haddr_t *addr, void *udata)
{
H5B_t *bt=NULL;
haddr_t next_addr;
+ const haddr_t *cur_addr=NULL;
intn i;
herr_t ret_value = FAIL;
@@ -1347,7 +1370,7 @@ H5B_list (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata)
assert (f);
assert (type);
assert (type->list);
- assert (addr>=0);
+ assert (addr && H5F_addr_defined (addr));
assert (udata);
if (NULL==(bt = H5AC_find (f, H5AC_BT, addr, type, udata))) {
@@ -1355,20 +1378,20 @@ H5B_list (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata)
}
if (bt->level>0) {
- if (H5B_list (f, type, bt->child[0], udata)<0) {
+ if (H5B_list (f, type, bt->child+0, udata)<0) {
HRETURN_ERROR (H5E_BTREE, H5E_CANTLIST, FAIL);
} else {
HRETURN (SUCCEED);
}
} else {
- for (/*void*/; addr>0; addr=next_addr) {
- if (NULL==(bt=H5AC_protect (f, H5AC_BT, addr, type, udata))) {
+ for (cur_addr=addr; !H5F_addr_defined (cur_addr); cur_addr=&next_addr) {
+ if (NULL==(bt=H5AC_protect (f, H5AC_BT, cur_addr, type, udata))) {
HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL);
}
for (i=0; i<bt->nchildren; i++) {
- if ((type->list)(f, bt->child[i], udata)<0) {
+ if ((type->list)(f, bt->child+i, udata)<0) {
HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL);
}
}
@@ -1383,7 +1406,7 @@ H5B_list (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata)
HGOTO_DONE (SUCCEED);
done:
- if (bt && H5AC_unprotect (f, H5AC_BT, addr, bt)<0) {
+ if (bt && H5AC_unprotect (f, H5AC_BT, cur_addr, bt)<0) {
HRETURN_ERROR (H5E_BTREE, H5E_PROTECT, FAIL);
}
FUNC_LEAVE (ret_value);
@@ -1465,8 +1488,8 @@ H5B_nodesize (H5F_t *f, const H5B_class_t *type,
*-------------------------------------------------------------------------
*/
herr_t
-H5B_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent,
- intn fwidth, H5B_class_t *type, void *udata)
+H5B_debug (H5F_t *f, const haddr_t *addr, FILE *stream, intn indent,
+ intn fwidth, const H5B_class_t *type, void *udata)
{
H5B_t *bt = NULL;
int i;
@@ -1477,7 +1500,7 @@ H5B_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent,
* Check arguments.
*/
assert (f);
- assert (addr>=0);
+ assert (addr && H5F_addr_defined (addr));
assert (stream);
assert (indent>=0);
assert (fwidth>=0);
@@ -1508,12 +1531,17 @@ H5B_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent,
fprintf (stream, "%*s%-*s %d\n", indent, "", fwidth,
"Level:",
(int)(bt->level));
- fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth,
- "Address of left sibling:",
- (unsigned long)(bt->left));
- fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth,
- "Address of right sibling:",
- (unsigned long)(bt->right));
+
+ fprintf (stream, "%*s%-*s ", indent, "", fwidth,
+ "Address of left sibling:");
+ H5F_addr_print (stream, &(bt->left));
+ fprintf (stream, "\n");
+
+ fprintf (stream, "%*s%-*s ", indent, "", fwidth,
+ "Address of right sibling:");
+ H5F_addr_print (stream, &(bt->right));
+ fprintf (stream, "\n");
+
fprintf (stream, "%*s%-*s %d (%d)\n", indent, "", fwidth,
"Number of children (max):",
(int)(bt->nchildren),
@@ -1524,9 +1552,10 @@ H5B_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent,
*/
for (i=0; i<bt->nchildren; i++) {
fprintf (stream, "%*sChild %d...\n", indent, "", i);
- fprintf (stream, "%*s%-*s %lu\n", indent+3, "", MAX(0,fwidth-3),
- "Address:",
- (unsigned long)(bt->child[i]));
+ fprintf (stream, "%*s%-*s ", indent+3, "", MAX(0,fwidth-3),
+ "Address:");
+ H5F_addr_print (stream, bt->child+i);
+ fprintf (stream, "\n");
}
FUNC_LEAVE (SUCCEED);
@@ -1552,7 +1581,8 @@ H5B_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent,
*/
#ifdef H5B_DEBUG
static herr_t
-H5B_assert (H5F_t *f, haddr_t addr, const H5B_class_t *type, void *udata)
+H5B_assert (H5F_t *f, const haddr_t *addr, const H5B_class_t *type,
+ void *udata)
{
H5B_t *bt = NULL;
intn i, ncell, cmp;
@@ -1575,7 +1605,7 @@ H5B_assert (H5F_t *f, haddr_t addr, const H5B_class_t *type, void *udata)
bt = H5AC_find (f, H5AC_BT, addr, type, udata);
assert (bt);
cur = H5MM_xcalloc (1, sizeof(struct child_t));
- cur->addr = addr;
+ cur->addr = *addr;
cur->level = bt->level;
head = tail = cur;
@@ -1586,21 +1616,21 @@ H5B_assert (H5F_t *f, haddr_t addr, const H5B_class_t *type, void *udata)
* test.
*/
for (ncell=0; cur; ncell++) {
- bt = H5AC_protect (f, H5AC_BT, cur->addr, type, udata);
+ 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);
+ assert (H5F_addr_eq (&(bt->right), &(cur->next->addr)));
} else {
- assert (bt->right==0);
+ assert (!H5F_addr_defined (&(bt->right)));
}
if (prev && prev->level==bt->level) {
- assert (bt->left==prev->addr);
+ assert (H5F_addr_eq (&(bt->left), &(prev->addr)));
} else {
- assert (bt->left==0);
+ assert (!H5F_addr_defined (&(bt->left)));
}
if (cur->level>0) {
@@ -1611,7 +1641,7 @@ H5B_assert (H5F_t *f, haddr_t addr, const H5B_class_t *type, void *udata)
* have then the tree has a cycle.
*/
for (tmp=head; tmp; tmp=tmp->next) {
- assert (tmp->addr != bt->child[i]);
+ assert (H5F_addr_ne (&(tmp->addr), bt->child+i));
}
/* Add the child node to the end of the queue */
@@ -1630,7 +1660,7 @@ H5B_assert (H5F_t *f, haddr_t addr, const H5B_class_t *type, void *udata)
}
/* Release node */
- status = H5AC_unprotect (f, H5AC_BT, cur->addr, bt);
+ status = H5AC_unprotect (f, H5AC_BT, &(cur->addr), bt);
assert (status>=0);
/* Advance current location in queue */
diff --git a/src/H5Bprivate.h b/src/H5Bprivate.h
index 619a00f..8438ae2 100644
--- a/src/H5Bprivate.h
+++ b/src/H5Bprivate.h
@@ -22,6 +22,17 @@
#include <H5private.h>
#include <H5Fprivate.h>
+/*
+ * Feature: 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 H5B_MAGIC "TREE" /*tree node magic number */
#define H5B_SIZEOF_MAGIC 4 /*size of magic number */
@@ -60,15 +71,15 @@ 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*,H5B_ins_t,void*,void*,void*); /*new leaf */
+ herr_t (*new)(H5F_t*,H5B_ins_t,void*,void*,void*,haddr_t*);
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 */
+ herr_t (*found)(H5F_t*,const haddr_t*,const void*,void*,const void*);
+ H5B_ins_t (*insert)(H5F_t*,const haddr_t*,void*,hbool_t*,void*,void*,
+ void*,hbool_t*,haddr_t*); /*insert new data */
hbool_t follow_min; /*min insert uses min leaf, not new() */
hbool_t follow_max; /*max insert uses max leaf, not new() */
- herr_t (*list)(H5F_t*,haddr_t,void*); /*traverse leaf nodes */
+ herr_t (*list)(H5F_t*,const haddr_t*,void*); /*walk leaf nodes */
herr_t (*decode)(H5F_t*,struct H5B_t*,uint8*,void*);
herr_t (*encode)(H5F_t*,struct H5B_t*,uint8*,void*);
} H5B_class_t;
@@ -101,12 +112,15 @@ typedef struct H5B_t {
/*
* Library prototypes.
*/
-herr_t H5B_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent,
- intn fwidth, H5B_class_t *type, void *udata);
-haddr_t H5B_new (H5F_t *f, const H5B_class_t *type, void *udata);
-herr_t H5B_find (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata);
-haddr_t H5B_insert (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata);
-herr_t H5B_list (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata);
+herr_t H5B_debug (H5F_t *f, const haddr_t *addr, FILE *stream, intn indent,
+ intn fwidth, const H5B_class_t *type, void *udata);
+herr_t H5B_new (H5F_t *f, const H5B_class_t *type, void *udata, haddr_t*);
+herr_t H5B_find (H5F_t *f, const H5B_class_t *type, const haddr_t *addr,
+ void *udata);
+herr_t H5B_insert (H5F_t *f, const H5B_class_t *type, const haddr_t *addr,
+ void *udata);
+herr_t H5B_list (H5F_t *f, const H5B_class_t *type, const haddr_t *addr,
+ void *udata);
#endif
diff --git a/src/H5C.c b/src/H5C.c
index 67be020..0ccef61 100644
--- a/src/H5C.c
+++ b/src/H5C.c
@@ -353,11 +353,11 @@ herr_t H5Cgetparm(hid_t tid, file_create_param_t parm, VOIDP buf)
break;
case H5_OFFSET_SIZE:
- *(uint8 *)buf=template->offset_size;
+ *(uint8 *)buf=template->sizeof_addr;
break;
case H5_LENGTH_SIZE:
- *(uint8 *)buf=template->length_size;
+ *(uint8 *)buf=template->sizeof_size;
break;
case H5_SYM_LEAF_K:
@@ -479,14 +479,14 @@ herr_t H5Csetparm(hid_t tid, file_create_param_t parm, const VOIDP buf)
val = *(const uint8 *)buf;
if(!(val==2 || val==4 || val==8 || val==16 || val==32 || val==64 || val==128 || val==256))
HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL);
- template->offset_size=val;
+ template->sizeof_addr=val;
break;
case H5_LENGTH_SIZE:
val = *(const uint8 *)buf;
if(!(val==2 || val==4 || val==8 || val==16 || val==32 || val==64 || val==128 || val==256))
HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL);
- template->length_size=val;
+ template->sizeof_size=val;
break;
case H5_SYM_LEAF_K:
diff --git a/src/H5D.c b/src/H5D.c
index 7d8b2d3..0b99e86 100644
--- a/src/H5D.c
+++ b/src/H5D.c
@@ -153,7 +153,7 @@ hid_t H5D_create(hid_t owner_id, hobjtype_t type, const char *name)
new_dset->file = file;
new_dset->tid=(-1); /* No type yet */
new_dset->sid=(-1); /* No dimensions yet */
- new_dset->data_addr = -1; /* No data yet */
+ H5F_addr_undef (&(new_dset->data_addr)); /* No data yet */
new_dset->dirty = FALSE; /* There are no messages yet */
/* Open (and create) a new file object */
@@ -429,7 +429,8 @@ herr_t H5Dread(hid_t oid, hid_t did, VOIDP buf)
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);
/* Check that the datatype & dataspace have already been initialized */
- if(dataset->tid==(-1) || dataset->sid==(-1) || dataset->data_addr<0)
+ if(dataset->tid==(-1) || dataset->sid==(-1) ||
+ !H5F_addr_defined (&(dataset->data_addr)))
HGOTO_ERROR(H5E_FUNC, H5E_UNINITIALIZED, FAIL);
/* Compute the number of bytes to read */
@@ -451,8 +452,10 @@ herr_t H5Dread(hid_t oid, hid_t did, VOIDP buf)
/* Read data from disk */
- if(H5F_block_read(dataset->file,dataset->data_addr,toread,readbuf)==FAIL)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL);
+ if (H5F_block_read (dataset->file, &(dataset->data_addr), toread,
+ readbuf)<0) {
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL);
+ }
if(free_buf!=0)
H5D_convert_buf(buf,readbuf,toread,H5Tsize(dataset->tid,BTRUE));
@@ -523,9 +526,11 @@ herr_t H5Dwrite(hid_t oid, hid_t did, VOIDP buf)
HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL);
/* Check if we have space for the dataset yet */
- if(dataset->data_addr<0) {
- if((dataset->data_addr=H5MF_alloc(dataset->file,towrite))<0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL);
+ if (!H5F_addr_defined (&(dataset->data_addr))) {
+ if (H5MF_alloc (dataset->file, H5MF_RAW, towrite,
+ &(dataset->data_addr)/*out*/)<0) {
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL);
+ }
dataset->dirty = TRUE;
}
@@ -542,8 +547,10 @@ herr_t H5Dwrite(hid_t oid, hid_t did, VOIDP buf)
writebuf=buf;
/* Write the data out to disk */
- if(H5F_block_write(dataset->file,dataset->data_addr,towrite,writebuf)<0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL);
+ if (H5F_block_write (dataset->file, &(dataset->data_addr), towrite,
+ writebuf)<0) {
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL);
+ }
done:
if(ret_value == FAIL)
@@ -626,7 +633,7 @@ herr_t H5D_flush(hid_t oid)
/*
* Modify/create the dataset's storage information.
*/
- if (dataset->data_addr>=0) {
+ if (H5F_addr_defined (&(dataset->data_addr))) {
H5O_std_store_t store; /* standard storage info */
store.len = H5Tsize (dataset->tid, BTRUE) * H5Pnelem (dataset->sid);
diff --git a/src/H5Distore.c b/src/H5Distore.c
index 06997a1..b997945 100644
--- a/src/H5Distore.c
+++ b/src/H5Distore.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 1997 Spizella Software
+ * Copyright (C) 1997 NCSA
* All rights reserved.
*
- * Programmer: Robb Matzke <robb@arborea.spizella.com>
+ * Programmer: Robb Matzke <matzke@llnl.gov>
* Wednesday, October 8, 1997
*/
#include <H5private.h>
@@ -29,18 +29,20 @@ 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, H5B_ins_t, void *_lt_key,
- void *_udata, void *_rt_key);
+static herr_t H5F_istore_new_node (H5F_t *f, H5B_ins_t, void *_lt_key,
+ void *_udata, void *_rt_key, haddr_t*);
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,
- void *_lt_key, hbool_t *lt_key_changed,
- void *_md_key, void *_udata,
- void *_rt_key, hbool_t *rt_key_changed);
+static herr_t H5F_istore_found (H5F_t *f, const haddr_t *addr,
+ const void *_lt_key, void *_udata,
+ const void *_rt_key);
+static H5B_ins_t H5F_istore_insert (H5F_t *f, const haddr_t *addr,
+ void *_lt_key, hbool_t *lt_key_changed,
+ void *_md_key, void *_udata,
+ void *_rt_key, hbool_t *rt_key_changed,
+ haddr_t*);
static herr_t H5F_istore_decode_key (H5F_t *f, H5B_t *bt, uint8 *raw,
void *_key);
static herr_t H5F_istore_encode_key (H5F_t *f, H5B_t *bt, uint8 *raw,
@@ -317,8 +319,9 @@ H5F_istore_cmp3 (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key)
* the domain represented by UDATA doesn't intersect the domain
* already represented by the B-tree.
*
- * Return: Success: Address of leaf, which is passed in from the
- * UDATA pointer.
+ * Return: Success: SUCCEED. The address of leaf is returned
+ * through the ADDR argument. It is also added
+ * to the UDATA.
*
* Failure: FAIL
*
@@ -329,9 +332,10 @@ H5F_istore_cmp3 (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key)
*
*-------------------------------------------------------------------------
*/
-static haddr_t
+static herr_t
H5F_istore_new_node (H5F_t *f, H5B_ins_t op,
- void *_lt_key, void *_udata, void *_rt_key)
+ void *_lt_key, void *_udata, void *_rt_key,
+ haddr_t *addr/*out*/)
{
H5F_istore_key_t *lt_key = (H5F_istore_key_t *)_lt_key;
H5F_istore_key_t *rt_key = (H5F_istore_key_t *)_rt_key;
@@ -347,14 +351,16 @@ H5F_istore_new_node (H5F_t *f, H5B_ins_t op,
assert (rt_key);
assert (udata);
assert (udata->mesg.ndims>=0 && udata->mesg.ndims<H5O_ISTORE_NDIMS);
+ assert (addr);
/* Allocate new storage */
nbytes = H5V_vector_reduce_product (udata->mesg.ndims, udata->key.size);
assert (nbytes>0);
- if ((udata->addr=H5MF_alloc (f, nbytes))<0) {
+ if (H5MF_alloc (f, H5MF_RAW, nbytes, addr/*out*/)<0) {
/* Couldn't allocate new file storage */
HRETURN_ERROR (H5E_IO, H5E_CANTINIT, FAIL);
}
+ udata->addr = *addr;
/* Initialize the key(s) */
for (i=0; i<udata->mesg.ndims; i++) {
@@ -376,7 +382,7 @@ H5F_istore_new_node (H5F_t *f, H5B_ins_t op,
}
}
- FUNC_LEAVE (udata->addr);
+ FUNC_LEAVE (SUCCEED);
}
@@ -403,7 +409,7 @@ H5F_istore_new_node (H5F_t *f, H5B_ins_t op,
*-------------------------------------------------------------------------
*/
static herr_t
-H5F_istore_found (H5F_t *f, haddr_t addr, const void *_lt_key,
+H5F_istore_found (H5F_t *f, const haddr_t *addr, const void *_lt_key,
void *_udata, const void *_rt_key)
{
H5F_istore_ud1_t *udata = (H5F_istore_ud1_t *)_udata;
@@ -414,12 +420,12 @@ H5F_istore_found (H5F_t *f, haddr_t addr, const void *_lt_key,
/* Check arguments */
assert (f);
- assert (addr>=0);
+ assert (addr && H5F_addr_defined (addr));
assert (udata);
assert (lt_key);
/* Initialize return values */
- udata->addr = addr;
+ udata->addr = *addr;
for (i=0; i<udata->mesg.ndims; i++) {
udata->key.offset[i] = lt_key->offset[i];
udata->key.size[i] = lt_key->size[i];
@@ -447,13 +453,12 @@ H5F_istore_found (H5F_t *f, haddr_t addr, const void *_lt_key,
* `offset' and `size' fields). On return, UDATA describes the
* logical addresses contained in a chunk on disk.
*
- * Return: Success: SUCCEED, with UDATA containing information
- * about the (newly allocated) chunk.
+ * Return: Success: An insertion command for the caller, one of
+ * the H5B_INS_* constants. The address of the
+ * new chunk is returned through the NEW_NODE
+ * argument.
*
- * If the storage address has changed then the
- * new address is returned.
- *
- * Failure: FAIL
+ * Failure: H5B_INS_ERROR
*
* Programmer: Robb Matzke
* Thursday, October 9, 1997
@@ -462,32 +467,33 @@ H5F_istore_found (H5F_t *f, haddr_t addr, const void *_lt_key,
*
*-------------------------------------------------------------------------
*/
-static haddr_t
-H5F_istore_insert (H5F_t *f, haddr_t addr, H5B_ins_t *parent_ins,
+static H5B_ins_t
+H5F_istore_insert (H5F_t *f, const haddr_t *addr,
void *_lt_key, hbool_t *lt_key_changed,
void *_md_key, void *_udata,
- void *_rt_key, hbool_t *rt_key_changed)
+ void *_rt_key, hbool_t *rt_key_changed,
+ haddr_t *new_node/*out*/)
{
H5F_istore_key_t *lt_key = (H5F_istore_key_t *)_lt_key;
H5F_istore_key_t *md_key = (H5F_istore_key_t *)_md_key;
H5F_istore_key_t *rt_key = (H5F_istore_key_t *)_rt_key;
H5F_istore_ud1_t *udata = (H5F_istore_ud1_t *)_udata;
intn i, cmp;
- haddr_t ret_value = 0;
+ H5B_ins_t ret_value = H5B_INS_ERROR;
size_t nbytes;
FUNC_ENTER (H5F_istore_insert, NULL, FAIL);
/* check args */
assert (f);
- assert (addr>=0);
- assert (parent_ins);
+ assert (addr && H5F_addr_defined (addr));
assert (lt_key);
assert (lt_key_changed);
assert (md_key);
assert (udata);
assert (rt_key);
assert (rt_key_changed);
+ assert (new_node);
cmp = H5F_istore_cmp3 (f, lt_key, udata, rt_key);
assert (cmp<=0);
@@ -503,8 +509,8 @@ H5F_istore_insert (H5F_t *f, haddr_t addr, H5B_ins_t *parent_ins,
/*
* Already exists. Just return the info.
*/
- udata->addr = addr;
- *parent_ins = H5B_INS_NOOP;
+ udata->addr = *addr;
+ ret_value = H5B_INS_NOOP;
} else if (H5V_hyper_disjointp (udata->mesg.ndims,
lt_key->offset, lt_key->size,
@@ -528,11 +534,11 @@ H5F_istore_insert (H5F_t *f, haddr_t addr, H5B_ins_t *parent_ins,
/*
* Allocate storage for the new chunk
*/
- if ((udata->addr=ret_value=H5MF_alloc (f, nbytes))<=0) {
+ if (H5MF_alloc (f, H5MF_RAW, nbytes, new_node/*out*/)<0) {
HRETURN_ERROR (H5E_IO, H5E_CANTINIT, FAIL);
}
-
- *parent_ins = H5B_INS_RIGHT;
+ udata->addr = *new_node;
+ ret_value = H5B_INS_RIGHT;
} else {
assert ("HDF5 INTERNAL ERROR -- see rpm" && 0);
@@ -599,7 +605,7 @@ H5F_istore_copy_hyperslab (H5F_t *f, const H5O_istore_t *istore, H5F_isop_t op,
/* check args */
assert (f);
assert (istore);
- assert (istore->btree_addr>0);
+ assert (H5F_addr_defined (&(istore->btree_addr)));
assert (istore->ndims>0 && istore->ndims<=H5O_ISTORE_NDIMS);
assert (H5F_ISTORE_READ==op || H5F_ISTORE_WRITE==op);
assert (size);
@@ -659,10 +665,10 @@ H5F_istore_copy_hyperslab (H5F_t *f, const H5O_istore_t *istore, H5F_isop_t op,
}
if (H5F_ISTORE_WRITE==op) {
- status = H5B_insert (f, H5B_ISTORE, istore->btree_addr, &udata);
+ status = H5B_insert (f, H5B_ISTORE, &(istore->btree_addr), &udata);
assert (status>=0);
} else {
- status = H5B_find (f, H5B_ISTORE, istore->btree_addr, &udata);
+ status = H5B_find (f, H5B_ISTORE, &(istore->btree_addr), &udata);
}
/*
@@ -672,8 +678,8 @@ H5F_istore_copy_hyperslab (H5F_t *f, const H5O_istore_t *istore, H5F_isop_t op,
if (H5F_ISTORE_READ==op ||
!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) {
+ if (status>=0 && H5F_addr_defined (&(udata.addr))) {
+ if (H5F_block_read (f, &(udata.addr), chunk_size, chunk)<0) {
HGOTO_ERROR (H5E_IO, H5E_READERROR, FAIL);
}
} else {
@@ -686,7 +692,7 @@ H5F_istore_copy_hyperslab (H5F_t *f, const H5O_istore_t *istore, H5F_isop_t op,
H5V_hyper_copy (istore->ndims, sub_size,
udata.key.size, offset_wrt_chunk, chunk,
size_m, sub_offset_m, buf);
- if (H5F_block_write (f, udata.addr, chunk_size, chunk)<0) {
+ if (H5F_block_write (f, &(udata.addr), chunk_size, chunk)<0) {
HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL);
}
} else {
@@ -835,7 +841,7 @@ H5F_istore_new (H5F_t *f, struct H5O_istore_t *istore,
#endif
udata.mesg.ndims = istore->ndims = ndims;
- if ((istore->btree_addr=H5B_new (f, H5B_ISTORE, &udata))<0) {
+ if (H5B_new (f, H5B_ISTORE, &udata, &(istore->btree_addr)/*out*/)<0) {
HRETURN_ERROR (H5E_IO, H5E_CANTINIT, FAIL); /* Can't create B-tree */
}
diff --git a/src/H5E.c b/src/H5E.c
index 5310352..f35041c 100644
--- a/src/H5E.c
+++ b/src/H5E.c
@@ -81,6 +81,7 @@ static const hdf_min_error_messages_t hdf_min_error_messages[] =
{H5E_CANTOPENOBJ, "Can't open object"},
{H5E_NOTHDF5, "Not an HDF5 format file"},
{H5E_BADFILE, "Bad file ID accessed"},
+ {H5E_TRUNCATED, "File has been truncated"},
{H5E_SEEKERROR, "Seek failed"},
{H5E_READERROR, "Read failed"},
{H5E_WRITEERROR, "Write failed"},
diff --git a/src/H5Epublic.h b/src/H5Epublic.h
index 38d9516..79337e7 100644
--- a/src/H5Epublic.h
+++ b/src/H5Epublic.h
@@ -67,6 +67,7 @@ typedef enum
H5E_CANTOPENFILE, /* Can't open file */
H5E_NOTHDF5, /* Not an HDF5 format file */
H5E_BADFILE, /* Bad file ID accessed */
+ H5E_TRUNCATED, /* File has been truncated */
/* Generic low-level file I/O errors */
H5E_SEEKERROR, /* Seek failed */
diff --git a/src/H5F.c b/src/H5F.c
index a485f31..0fa3f71 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -46,6 +46,7 @@ static char RcsId[] = "@(#)$Revision$";
#include <H5Mprivate.h> /*meta data */
#include <H5MMprivate.h> /*core memory management */
+#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -69,6 +70,7 @@ static herr_t H5F_init_interface(void);
static H5F_t *H5F_new (H5F_file_t *shared);
static H5F_t *H5F_dest (H5F_t *f);
static herr_t H5F_flush (H5F_t *f, hbool_t invalidate);
+static herr_t H5F_locate_signature (H5F_low_t *f_handle, haddr_t *addr/*out*/);
/*--------------------------------------------------------------------------
NAME
@@ -123,7 +125,6 @@ void H5F_term_interface (void)
H5Adestroy_group(H5_FILE);
} /* end H5F_term_interface() */
-#ifdef LATER
/*--------------------------------------------------------------------------
NAME
H5F_encode_length_unusual -- encode an unusual length size
@@ -170,51 +171,6 @@ done:
/*--------------------------------------------------------------------------
NAME
- H5F_encode_offset_unusual -- encode an unusual offset size
- USAGE
- void H5F_encode_offset_unusual(f, p, o)
- const H5F_t *f; IN: pointer to the file record
- uint8 **p; IN: pointer to buffer pointer to encode offset in
- uint8 *o; IN: pointer to offset to encode
-
-ERRORS
-
- RETURNS
- none
- DESCRIPTION
- Encode non-standard (i.e. not 2, 4 or 8-byte) offsets in file meta-data.
---------------------------------------------------------------------------*/
-void H5F_encode_offset_unusual(const H5F_t *f, uint8 **p, uint8 *o)
-{
- intn i = H5F_SIZEOF_OFFSET(f);
-
-#ifdef WORDS_BIGENDIAN
- /*
- * For non-little-endian platforms, encode each byte in memory backwards.
- */
- for(; i>=0; i--,(*p)++)
- *(*p)=*(o+i);
-#else
- /* platform has little-endian integers */
- for(; i>=0; i--,(*p)++)
- *(*p)=*o;
-#endif
-
-#ifdef LATER
-done:
- if(ret_value == FALSE)
- { /* Error condition cleanup */
-
- } /* end if */
-#endif /* LATER */
-
- /* Normal function cleanup */
-
-} /* H5F_encode_offset_unusual */
-#endif /* LATER */
-
-/*--------------------------------------------------------------------------
- NAME
H5F_compare_files -- compare file objects for the atom API
USAGE
intn HPcompare_filename(obj, key)
@@ -297,7 +253,49 @@ done:
/* Normal function cleanup */
FUNC_LEAVE(ret_value);
-} /* end H5Fget_create_template() */
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_locate_signature
+ *
+ * Purpose: Finds the HDF5 boot block signature in a file. The signature
+ * can appear at address 0, or any power of two beginning with
+ * 512.
+ *
+ * Return: Success: SUCCEED. The address of the signature is
+ * returned through the ADDR argument.
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Friday, November 7, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5F_locate_signature (H5F_low_t *f_handle, haddr_t *addr/*out*/)
+{
+ haddr_t max_addr;
+ uint8 buf[H5F_SIGNATURE_LEN];
+ uintn n=9;
+
+ FUNC_ENTER (H5F_locate_signature, H5F_init_interface, FAIL);
+
+ H5F_low_size (f_handle, &max_addr);
+ H5F_addr_reset (addr);
+ while (H5F_addr_lt (addr, &max_addr)) {
+ if (H5F_low_read (f_handle, addr, H5F_SIGNATURE_LEN, buf)<0) {
+ HRETURN_ERROR (H5E_IO, H5E_READERROR, FAIL);
+ }
+ if (!HDmemcmp (buf, H5F_SIGNATURE, H5F_SIGNATURE_LEN)) break;
+ H5F_addr_pow2 (n++, addr);
+ }
+
+ FUNC_LEAVE (SUCCEED);
+}
/*--------------------------------------------------------------------------
NAME
@@ -326,9 +324,7 @@ done:
hbool_t H5Fis_hdf5(const char *filename)
{
H5F_low_t *f_handle=NULL; /* file handle */
- uint8 temp_buf[H5F_SIGNATURE_LEN]; /* temporary buffer for checking file signature */
- haddr_t curr_off=0; /* The current offset to check in the file */
- size_t file_len=0; /* The length of the file we are checking */
+ haddr_t addr; /* Address of file signature & header */
hbool_t ret_value = BFALSE;
FUNC_ENTER(H5Fis_hdf5, H5F_init_interface, BFAIL);
@@ -344,23 +340,9 @@ hbool_t H5Fis_hdf5(const char *filename)
HGOTO_ERROR(H5E_FILE, H5E_BADFILE, BFAIL);
}
- /* Get the length of the file */
- file_len = H5F_low_size (f_handle);
-
- /* Check the offsets where the file signature is possible */
- while(curr_off<file_len) {
- if (H5F_low_read (f_handle, curr_off, H5F_SIGNATURE_LEN, temp_buf)<0) {
- HGOTO_ERROR(H5E_IO, H5E_READERROR, BFAIL); /*read error*/
- }
- if(HDmemcmp(temp_buf,H5F_SIGNATURE,H5F_SIGNATURE_LEN)==0) {
- ret_value=BTRUE;
- break;
- }
- if(curr_off==0)
- curr_off=512;
- else
- curr_off*=2;
- } /* end while */
+ if (H5F_locate_signature (f_handle, &addr)>=0) {
+ ret_value = BTRUE;
+ }
done:
H5F_low_close(f_handle); /* close the file we opened */
@@ -402,6 +384,11 @@ H5F_new (H5F_file_t *shared)
if (!f->shared) {
f->shared = H5MM_xcalloc (1, sizeof(H5F_file_t));
+ H5F_addr_undef (&(f->shared->boot_addr));
+ H5F_addr_undef (&(f->shared->base_addr));
+ H5F_addr_undef (&(f->shared->smallobj_addr));
+ H5F_addr_undef (&(f->shared->freespace_addr));
+ H5F_addr_undef (&(f->shared->hdf5_eof));
/* Create a main cache */
H5AC_new (f, H5AC_NSLOTS);
@@ -511,17 +498,15 @@ H5F_dest (H5F_t *f)
* intent.
* FILE BADVALUE Can't truncate without write intent.
* FILE CANTCREATE Can't create file.
- * FILE CANTCREATE Can't stat file.
* FILE CANTCREATE Can't truncate file.
* FILE CANTINIT Can't get default file create template
* id.
* FILE CANTINIT Can't write file boot block.
- * FILE CANTINIT Cannot determine file size.
+ * FILE CANTOPENFILE Bad address size.
* FILE CANTOPENFILE Bad boot block version number.
* FILE CANTOPENFILE Bad free space version number.
* FILE CANTOPENFILE Bad length size.
* FILE CANTOPENFILE Bad object dir version number.
- * FILE CANTOPENFILE Bad offset size.
* FILE CANTOPENFILE Bad shared header version number.
* FILE CANTOPENFILE Bad small object heap version number.
* FILE CANTOPENFILE Bad symbol table internal node 1/2
@@ -532,12 +517,16 @@ H5F_dest (H5F_t *f)
* FILE CANTOPENFILE File cannot be reopened with write
* access.
* FILE CANTOPENFILE File does not exist.
+ * FILE CANTOPENFILE Invalid file family name.
* FILE FILEEXISTS File already exists - CREAT EXCL
* failed.
* FILE FILEOPEN File already open - TRUNC failed.
+ * FILE NOTHDF5 Can't find signature.
* FILE NOTHDF5 Can't read boot block.
* FILE READERROR File is not readable.
+ * FILE TRUNCATED Truncated file?
* FILE WRITEERROR File is not writable.
+ * IO READERROR Can't read boot block.
*
* Return: Success: Ptr to the file pointer.
*
@@ -548,6 +537,11 @@ H5F_dest (H5F_t *f)
*
* Modifications:
*
+ * Robb Matzke, 11 Nov 1997
+ * If the name contains the pattern /[^%]%\d*[duxX]/ then the file is
+ * assumed to be a family of files. The TYPE argument is ignored and
+ * H5F_LOW_FAM is used instead.
+ *
*-------------------------------------------------------------------------
*/
H5F_t *
@@ -561,17 +555,67 @@ H5F_open (const H5F_low_class_t *type, const char *name, uintn flags,
H5F_low_t *fd = NULL; /*low level file desc */
hbool_t empty_file = FALSE; /*is file empty? */
hbool_t file_exists = FALSE; /*file already exists */
- uint8 buf[256], *p=NULL; /*I/O buffer and ptr into it */
+ uint8 buf[256]; /*I/O buffer.. */
+ const uint8 *p=NULL; /* ..and pointer into it*/
size_t fixed_size = 24; /*size of fixed part of boot blk*/
size_t variable_size; /*variable part of boot block */
- intn i;
file_create_temp_t *cp=NULL; /*file creation parameters */
+ haddr_t addr1, addr2; /*temporary address */
+ const char *s = name;
FUNC_ENTER (H5F_open, H5F_init_interface, NULL);
assert (name && *name);
/*
+ * Does the name look like a family name? A family name always has a
+ * percent (not preceded by a percent) followed by an optional plus and/or
+ * minus, followed by optional digits, followed by the letter `d', `u',
+ * `x', or `X'. This is a printf() format for an integer.
+ */
+ while (*s) {
+ if ('%'!=*s++) continue;
+ if ('%'==*s) {
+ s++;
+ continue;
+ }
+ while (*s && isdigit (*s)) s++;
+ if ('d'!=*s && 'u'!=*s && 'x'!=*s && 'X'!=*s) continue;
+ break;
+ }
+ if (*s) {
+#ifdef H5F_DEBUG
+ if (type!=H5F_LOW_FAM) {
+ fprintf (stderr, "HDF5-DIAG: opening a file family\n");
+ }
+#endif
+ type = H5F_LOW_FAM;
+ } else if (type==H5F_LOW_FAM) {
+ /* Invalid file family name */
+ HRETURN_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL);
+ }
+
+ /*
+ * If the name ends with `.h5' and there's another file that ends with
+ * `.raw' then open the file as a split file.
+ */
+ {
+ if (H5F_LOW_SPLIT!=type && (s=strstr (name, ".h5")) && !s[3]) {
+ char fullname[4096];
+ strncpy (fullname, name, s-name);
+ strcpy (fullname+(s-name), ".raw");
+ if (H5F_low_access (H5F_LOW_DFLT, fullname, F_OK, NULL)) {
+#ifdef H5F_DEBUG
+ fprintf (stderr, "HDF5-DIAG: opening a split file\n");
+#endif
+ fullname[s-name] = '\0';
+ f = H5F_open (H5F_LOW_SPLIT, fullname, flags, create_parms);
+ HRETURN (f);
+ }
+ }
+ }
+
+ /*
* If no file creation parameters are supplied then use defaults.
*/
if (!create_parms) {
@@ -624,8 +668,8 @@ H5F_open (const H5F_low_class_t *type, const char *name, uintn flags,
/* File cannot be reopened with write access */
HRETURN_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL);
}
- H5F_low_close (old->shared->file_handle);
- old->shared->file_handle = fd;
+ H5F_low_close (old->shared->lf);
+ old->shared->lf = fd;
old->shared->flags |= H5F_ACC_WRITE;
fd = NULL; /*so we don't close it during error*/
}
@@ -645,7 +689,7 @@ H5F_open (const H5F_low_class_t *type, const char *name, uintn flags,
f = H5F_new (NULL);
f->shared->key = search;
f->shared->flags = flags;
- f->shared->file_handle = fd;
+ f->shared->lf = fd;
empty_file = TRUE;
} else {
@@ -657,7 +701,7 @@ H5F_open (const H5F_low_class_t *type, const char *name, uintn flags,
f = H5F_new (NULL);
f->shared->key = search;
f->shared->flags = flags;
- f->shared->file_handle = fd;
+ f->shared->lf = fd;
}
} else if (flags & H5F_ACC_CREAT) {
@@ -675,9 +719,9 @@ H5F_open (const H5F_low_class_t *type, const char *name, uintn flags,
f = H5F_new (NULL);
f->shared->key = search;
f->shared->flags = flags;
- f->shared->file_handle = fd;
+ f->shared->lf = fd;
empty_file = TRUE;
-
+
} else {
/* File does not exist */
HRETURN_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL);
@@ -708,7 +752,17 @@ H5F_open (const H5F_low_class_t *type, const char *name, uintn flags,
* Read or write the file boot block.
*/
if (empty_file) {
- /* For new files we must write the boot block. */
+ /*
+ * For new files we must write the boot block. The boot block starts
+ * immediately after the user-defined header, which we have already
+ * insured is a proper size. The base address is set to the same thing
+ * as the boot block.
+ */
+ H5F_addr_reset (&(f->shared->boot_addr));
+ H5F_addr_inc (&(f->shared->boot_addr),
+ f->shared->file_create_parms.userblock_size);
+ f->shared->base_addr = f->shared->boot_addr;
+
f->shared->consist_flags = 0x03;
if (H5F_flush (f, FALSE)<0) {
/* Can't write file boot block */
@@ -716,117 +770,157 @@ H5F_open (const H5F_low_class_t *type, const char *name, uintn flags,
}
} else if (1==f->shared->nrefs) {
/* For existing files we must read the boot block. */
- assert (fixed_size <= sizeof buf);
- for (i=8; i<32*sizeof(haddr_t); i++) {
- cp->userblock_size = (8==i ? 0 : 1<<i);
-
- /* Read the fixed size part of the boot block */
- if (H5F_block_read (f, 0, fixed_size, buf)<0) {
- /*can't read boot block*/
- HGOTO_ERROR (H5E_FILE, H5E_NOTHDF5, NULL);
- }
-
- /*
- * Decode the fixed size part of the boot block. For each of the
- * version parameters, check that the library is able to handle that
- * version.
- */
- p = buf;
- if (HDmemcmp (p, H5F_SIGNATURE, H5F_SIGNATURE_LEN)) continue;
- p += H5F_SIGNATURE_LEN;
-
- cp->bootblock_ver = *p++;
- if (cp->bootblock_ver != HDF5_BOOTBLOCK_VERSION) {
- /* Bad boot block version number */
- HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL);
- }
+ if (H5F_locate_signature (f->shared->lf, &(f->shared->boot_addr))<0) {
+ HGOTO_ERROR (H5E_FILE, H5E_NOTHDF5, NULL);/*Can't find signature*/
+ }
+ if (H5F_low_read (f->shared->lf, &(f->shared->boot_addr),
+ fixed_size, buf)<0) {
+ HGOTO_ERROR (H5E_IO, H5E_READERROR, NULL);/*Can't read boot block*/
+ }
+
+ /*
+ * All addresses are relative to a base address. Eventually, the base
+ * address will be able to be set independently of the boot block
+ * address, but for now, all addresses are relative to the beginning of
+ * the boot block. Anything before the base address is assumed to be
+ * user-defined data.
+ */
+ f->shared->base_addr = f->shared->boot_addr;
+ f->shared->file_create_parms.userblock_size=f->shared->base_addr.offset;
+
+ /*
+ * Decode the fixed size part of the boot block. For each of the
+ * version parameters, check that the library is able to handle that
+ * version.
+ */
+ p = buf + H5F_SIGNATURE_LEN; /*already checked*/
+
+ cp->bootblock_ver = *p++;
+ if (cp->bootblock_ver != HDF5_BOOTBLOCK_VERSION) {
+ /* Bad boot block version number */
+ HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL);
+ }
- cp->smallobject_ver = *p++;
- if (cp->smallobject_ver != HDF5_SMALLOBJECT_VERSION) {
- /* Bad small object heap version number */
- HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL);
- }
+ cp->smallobject_ver = *p++;
+ if (cp->smallobject_ver != HDF5_SMALLOBJECT_VERSION) {
+ /* Bad small object heap version number */
+ HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL);
+ }
- cp->freespace_ver = *p++;
- if (cp->freespace_ver != HDF5_FREESPACE_VERSION) {
- /* Bad free space version number */
- HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL);
- }
+ cp->freespace_ver = *p++;
+ if (cp->freespace_ver != HDF5_FREESPACE_VERSION) {
+ /* Bad free space version number */
+ HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL);
+ }
- cp->objectdir_ver = *p++;
- if (cp->objectdir_ver != HDF5_OBJECTDIR_VERSION) {
- /* Bad object dir version number */
- HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL);
- }
+ cp->objectdir_ver = *p++;
+ if (cp->objectdir_ver != HDF5_OBJECTDIR_VERSION) {
+ /* Bad object dir version number */
+ HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL);
+ }
- cp->sharedheader_ver = *p++;
- if (cp->sharedheader_ver != HDF5_SHAREDHEADER_VERSION) {
- /* Bad shared header version number */
- HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL);
- }
+ cp->sharedheader_ver = *p++;
+ if (cp->sharedheader_ver != HDF5_SHAREDHEADER_VERSION) {
+ /* Bad shared header version number */
+ HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL);
+ }
- cp->offset_size = *p++;
- if (cp->offset_size!=2 &&
- cp->offset_size!=4 &&
- cp->offset_size!=8) {
- /* Bad offset size */
- HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL);
- }
+ cp->sizeof_addr = *p++;
+ if (cp->sizeof_addr!=2 &&
+ cp->sizeof_addr!=4 &&
+ cp->sizeof_addr!=8 &&
+ cp->sizeof_addr!=16 &&
+ cp->sizeof_addr!=32) {
+ /* Bad address size */
+ HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL);
+ }
- cp->length_size = *p++;
- if (cp->length_size!=2 &&
- cp->length_size!=4 &&
- cp->length_size!=8) {
- /* Bad length size */
- HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL);
- }
+ cp->sizeof_size = *p++;
+ if (cp->sizeof_size!=2 &&
+ cp->sizeof_size!=4 &&
+ cp->sizeof_size!=8 &&
+ cp->sizeof_size!=16 &&
+ cp->sizeof_size!=32) {
+ /* Bad length size */
+ HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL);
+ }
- /* Reserved byte */
- p++;
+ /* Reserved byte */
+ p++;
- UINT16DECODE (p, cp->sym_leaf_k);
- if (cp->sym_leaf_k<1) {
- /* Bad symbol table leaf node 1/2 rank */
- HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL);
- }
+ UINT16DECODE (p, cp->sym_leaf_k);
+ if (cp->sym_leaf_k<1) {
+ /* Bad symbol table leaf node 1/2 rank */
+ HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL);
+ }
- UINT16DECODE (p, cp->btree_k[H5B_SNODE_ID]);
- if (cp->btree_k[H5B_SNODE_ID]<1) {
- /* Bad symbol table internal node 1/2 rank */
- HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL);
- }
-
- UINT32DECODE (p, f->shared->consist_flags);
- /* nothing to check for consistency flags */
-
- assert (p-buf == fixed_size);
+ UINT16DECODE (p, cp->btree_k[H5B_SNODE_ID]);
+ if (cp->btree_k[H5B_SNODE_ID]<1) {
+ /* Bad symbol table internal node 1/2 rank */
+ HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL);
+ }
- /* Read the variable length part of the boot block... */
- variable_size = H5F_SIZEOF_OFFSET (f) + /*global small obj heap*/
- H5F_SIZEOF_OFFSET (f) + /*global free list addr*/
- H5F_SIZEOF_SIZE (f) + /*logical file size*/
- H5G_SIZEOF_ENTRY (f);
- assert (variable_size <= sizeof buf);
- if (H5F_block_read (f, fixed_size, variable_size, buf)<0) {
- /*can't read boot block*/
- HGOTO_ERROR (H5E_FILE, H5E_NOTHDF5, NULL);
- }
+ UINT32DECODE (p, f->shared->consist_flags);
+ /* nothing to check for consistency flags */
+
+ assert (p-buf == fixed_size);
+
+ /* Read the variable length part of the boot block... */
+ variable_size = H5F_SIZEOF_OFFSET (f) + /*global small obj heap*/
+ H5F_SIZEOF_OFFSET (f) + /*global free list addr*/
+ H5F_SIZEOF_SIZE (f) + /*logical file size*/
+ H5G_SIZEOF_ENTRY (f);
+ assert (variable_size <= sizeof buf);
+ addr1 = f->shared->boot_addr;
+ H5F_addr_inc (&addr1, fixed_size);
+ if (H5F_low_read (f->shared->lf, &addr1, variable_size, buf)<0) {
+ /*can't read boot block*/
+ HGOTO_ERROR (H5E_FILE, H5E_NOTHDF5, NULL);
+ }
- p = buf;
- H5F_decode_offset (f, p, f->shared->smallobj_off);
- H5F_decode_offset (f, p, f->shared->freespace_off);
- H5F_decode_length (f, p, f->shared->logical_len);
- if (H5G_ent_decode (f, &p, f->shared->root_sym)<0) {
- /*can't read root symbol entry*/
- HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL);
- }
- break;
+ p = buf;
+ H5F_addr_decode (f, &p, &(f->shared->smallobj_addr));
+ H5F_addr_decode (f, &p, &(f->shared->freespace_addr));
+ H5F_addr_decode (f, &p, &(f->shared->hdf5_eof));
+ if (H5G_ent_decode (f, &p, f->shared->root_sym)<0) {
+ /*can't read root symbol entry*/
+ HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL);
}
}
- /* What is the current size of the file? */
- f->shared->logical_len = H5F_low_size (f->shared->file_handle);
-
+ /*
+ * What is the current size of the file? The max_addr field is a relative
+ * address while H5F_low_size() returns an absolute address.
+ */
+ H5F_low_size (f->shared->lf, &addr1);
+ addr2 = f->shared->hdf5_eof;
+ H5F_addr_add (&addr2, &(f->shared->base_addr));
+ if (H5F_addr_lt (&addr1, &addr2)) {
+ /*
+ * Truncated file? This might happen if one tries to open the first
+ * member of a file family.
+ */
+ HGOTO_ERROR (H5E_FILE, H5E_TRUNCATED, NULL);
+ } else if (H5F_addr_gt (&addr1, &addr2)) {
+ /*
+ * The file is larger than the hdf5 data. It either has extra junk at
+ * the end, or a wrapper. In either case, make the file think it's
+ * shorter so when we allocate memory from the file for hdf5 it's
+ * allocated immediately after the end of the previous hdf5 data. This
+ * will cause internal wrappers to be overwritten if they follow the
+ * hdf5 data.
+ */
+#ifdef H5F_DEBUG
+ fprintf (stderr, "HDF5-DIAG: resetting EOF from ");
+ H5F_addr_print (stderr, &addr1);
+ fprintf (stderr, " to ");
+ H5F_addr_print (stderr, &addr2);
+ fprintf (stderr, " (abs)\n");
+#endif
+ H5F_low_seteof (f->shared->lf, &addr2);
+ }
+
+
/* Success! */
ret_value = f;
@@ -1094,18 +1188,27 @@ H5F_flush (H5F_t *f, hbool_t invalidate)
UINT16ENCODE (p, f->shared->file_create_parms.sym_leaf_k);
UINT16ENCODE (p, f->shared->file_create_parms.btree_k[H5B_SNODE_ID]);
UINT32ENCODE (p, f->shared->consist_flags);
- H5F_encode_offset (f, p, f->shared->smallobj_off);
- H5F_encode_offset (f, p, f->shared->freespace_off);
- H5F_encode_length (f, p, f->shared->logical_len);
+ H5F_addr_encode (f, &p, &(f->shared->smallobj_addr));
+ H5F_addr_encode (f, &p, &(f->shared->freespace_addr));
+ H5F_addr_encode (f, &p, &(f->shared->hdf5_eof));
H5G_ent_encode (f, &p, f->shared->root_sym);
+ /* update file length if necessary */
+ if (!H5F_addr_defined (&(f->shared->hdf5_eof))) {
+ H5F_addr_reset (&(f->shared->hdf5_eof));
+ H5F_addr_inc (&(f->shared->hdf5_eof), p-buf);
+ H5F_low_seteof (f->shared->lf, &(f->shared->hdf5_eof));
+ }
+
/* write the boot block to disk */
- if (H5F_block_write (f, 0, p-buf, buf)<0) {
+ if (H5F_low_write (f->shared->lf, &(f->shared->boot_addr), p-buf, buf)<0) {
HRETURN_ERROR (H5E_IO, H5E_WRITEERROR, FAIL); /*can't write header*/
}
- /* update file length if necessary */
- if (f->shared->logical_len<=0) f->shared->logical_len = p-buf;
+ /* Flush file buffers to disk */
+ if (H5F_low_flush (f->shared->lf)<0) {
+ HRETURN_ERROR (H5E_IO, H5E_WRITEERROR, FAIL); /*low level flush failed*/
+ }
/* Did shadow flush fail above? */
if (shadow_flush<0) {
@@ -1124,7 +1227,7 @@ H5F_flush (H5F_t *f, hbool_t invalidate)
data.
USAGE
- herr_t H5Fclose(fid, invalidate)
+ herr_t H5Fflush(fid, invalidate)
hid_t fid; IN: File ID of file to close.
hbool_t invalidate; IN: Invalidate all of the cache?
@@ -1199,7 +1302,7 @@ H5F_close (H5F_t *f)
HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL);
}
if (f->intent & H5F_ACC_DEBUG) H5AC_debug (f);
- H5F_low_close (f->shared->file_handle);
+ H5F_low_close (f->shared->lf);
H5F_dest (f);
/* Did the H5F_flush() fail because of open objects? */
@@ -1274,7 +1377,8 @@ done:
* Function: H5F_block_read
*
* Purpose: Reads some data from a file/server/etc into a buffer.
- * The data is contiguous.
+ * The data is contiguous. The address is relative to the base
+ * address for the file.
*
* Errors:
* IO READERROR Low-level read failed.
@@ -1292,14 +1396,20 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5F_block_read (H5F_t *f, haddr_t addr, size_t size, void *buf)
+H5F_block_read (H5F_t *f, const haddr_t *addr, size_t size, void *buf)
{
+ haddr_t abs_addr;
+
FUNC_ENTER (H5F_block_read, H5F_init_interface, FAIL);
if (0==size) return 0;
- addr += f->shared->file_create_parms.userblock_size;
- if (H5F_low_read (f->shared->file_handle, addr, size, buf)<0) {
+ /* convert the relative address to an absolute address */
+ abs_addr = f->shared->base_addr;
+ H5F_addr_add (&abs_addr, addr);
+
+ /* Read the data */
+ if (H5F_low_read (f->shared->lf, &abs_addr, size, buf)<0) {
HRETURN_ERROR (H5E_IO, H5E_READERROR, FAIL); /*low-level read failed*/
}
@@ -1311,7 +1421,8 @@ H5F_block_read (H5F_t *f, haddr_t addr, size_t size, void *buf)
* Function: H5F_block_write
*
* Purpose: Writes some data from memory to a file/server/etc. The
- * data is contiguous.
+ * data is contiguous. The address is relative to the base
+ * address.
*
* Errors:
* IO WRITEERROR Low-level write failed.
@@ -1330,19 +1441,25 @@ H5F_block_read (H5F_t *f, haddr_t addr, size_t size, void *buf)
*-------------------------------------------------------------------------
*/
herr_t
-H5F_block_write (H5F_t *f, haddr_t addr, size_t size, void *buf)
+H5F_block_write (H5F_t *f, const haddr_t *addr, size_t size, void *buf)
{
+ haddr_t abs_addr;
+
FUNC_ENTER (H5F_block_write, H5F_init_interface, FAIL);
if (0==size) return 0;
- addr += f->shared->file_create_parms.userblock_size;
if (0==(f->intent & H5F_ACC_WRITE)) {
/* no write intent */
HRETURN_ERROR (H5E_IO, H5E_WRITEERROR, FAIL);
}
- if (H5F_low_write (f->shared->file_handle, addr, size, buf)) {
+ /* Convert the relative address to an absolute address */
+ abs_addr = f->shared->base_addr;
+ H5F_addr_add (&abs_addr, addr);
+
+ /* Write the data */
+ if (H5F_low_write (f->shared->lf, &abs_addr, size, buf)) {
HRETURN_ERROR (H5E_IO, H5E_WRITEERROR, FAIL);/*low-level write failed*/
}
@@ -1372,13 +1489,14 @@ H5F_block_write (H5F_t *f, haddr_t addr, size_t size, void *buf)
*-------------------------------------------------------------------------
*/
herr_t
-H5F_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent, intn fwidth)
+H5F_debug (H5F_t *f, const haddr_t *addr, FILE *stream, intn indent,
+ intn fwidth)
{
FUNC_ENTER (H5F_debug, H5F_init_interface, FAIL);
/* check args */
assert (f);
- assert (addr>=0);
+ assert (addr && H5F_addr_defined (addr));
assert (stream);
assert (indent>=0);
assert (fwidth>=0);
@@ -1398,24 +1516,41 @@ H5F_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent, intn fwidth)
fprintf (stream, "%*s%-*s 0x%08lx\n", indent, "", fwidth,
"Consistency flags:",
(unsigned long)(f->shared->consist_flags));
- fprintf (stream, "%*s%-*s %ld\n", indent, "", fwidth,
- "Small object heap address:",
- (long)(f->shared->smallobj_off));
- fprintf (stream, "%*s%-*s %ld\n", indent, "", fwidth,
- "Free list address:",
- (long)(f->shared->freespace_off));
- fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth,
- "Logical file length:",
- (unsigned long)(f->shared->logical_len));
- fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth,
+
+ fprintf (stream, "%*s%-*s ", indent, "", fwidth,
+ "Address of boot block:");
+ H5F_addr_print (stream, &(f->shared->boot_addr));
+ fprintf (stream, " (abs)\n");
+
+ fprintf (stream, "%*s%-*s ", indent, "", fwidth,
+ "Base address:");
+ H5F_addr_print (stream, &(f->shared->base_addr));
+ fprintf (stream, " (abs)\n");
+
+ fprintf (stream, "%*s%-*s ", indent, "", fwidth,
+ "Small object heap address:");
+ H5F_addr_print (stream, &(f->shared->smallobj_addr));
+ fprintf (stream, " (rel)\n");
+
+ fprintf (stream, "%*s%-*s ", indent, "", fwidth,
+ "Free list address:");
+ H5F_addr_print (stream, &(f->shared->freespace_addr));
+ fprintf (stream, " (rel)\n");
+
+ fprintf (stream, "%*s%-*s ", indent, "", fwidth,
+ "Total size of hdf5 data:");
+ H5F_addr_print (stream, &(f->shared->hdf5_eof));
+ fprintf (stream, " bytes\n");
+
+ fprintf (stream, "%*s%-*s %lu bytes\n", indent, "", fwidth,
"Size of user block:",
(unsigned long)(f->shared->file_create_parms.userblock_size));
- fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth,
+ fprintf (stream, "%*s%-*s %u bytes\n", indent, "", fwidth,
"Size of file size_t type:",
- (unsigned)(f->shared->file_create_parms.offset_size));
- fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth,
- "Size of file off_t type:",
- (unsigned)(f->shared->file_create_parms.length_size));
+ (unsigned)(f->shared->file_create_parms.sizeof_size));
+ fprintf (stream, "%*s%-*s %u bytes\n", indent, "", fwidth,
+ "Size of file haddr_t type:",
+ (unsigned)(f->shared->file_create_parms.sizeof_addr));
fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth,
"Symbol table leaf node 1/2 rank:",
(unsigned)(f->shared->file_create_parms.sym_leaf_k));
diff --git a/src/H5Fcore.c b/src/H5Fcore.c
index b28a12a..d520cc1 100644
--- a/src/H5Fcore.c
+++ b/src/H5Fcore.c
@@ -28,13 +28,10 @@ static hbool_t interface_initialize_g = FALSE;
static hbool_t H5F_core_access (const char *name, int mode, H5F_search_t *key);
static H5F_low_t *H5F_core_open (const char *name, uintn flags, H5F_search_t*);
static herr_t H5F_core_close (H5F_low_t *lf);
-static herr_t H5F_core_read (H5F_low_t *lf, haddr_t addr, size_t size,
+static herr_t H5F_core_read (H5F_low_t *lf, const haddr_t *addr, size_t size,
uint8 *buf);
-static herr_t H5F_core_write (H5F_low_t *lf, haddr_t addr, size_t size,
+static herr_t H5F_core_write (H5F_low_t *lf, const haddr_t *addr, size_t size,
const uint8 *buf);
-static herr_t H5F_core_flush (H5F_low_t *lf);
-static size_t H5F_core_size (H5F_low_t *lf);
-
const H5F_low_class_t H5F_LOW_CORE[1] = {{
H5F_core_access, /* access method */
@@ -42,8 +39,8 @@ const H5F_low_class_t H5F_LOW_CORE[1] = {{
H5F_core_close, /* close method */
H5F_core_read, /* read method */
H5F_core_write, /* write method */
- H5F_core_flush, /* flush method */
- H5F_core_size, /* file size method */
+ NULL, /* flush method */
+ NULL, /* extend method */
}};
@@ -53,7 +50,7 @@ const H5F_low_class_t H5F_LOW_CORE[1] = {{
* Purpose: Determines if the specified file already exists. This driver
* doesn't use names, so every call to H5F_core_open() would
* create a new file. Therefore, this function always returns
- * false.
+ * false and KEY is never initialized.
*
* Return: Success: FALSE
*
@@ -67,7 +64,7 @@ const H5F_low_class_t H5F_LOW_CORE[1] = {{
*-------------------------------------------------------------------------
*/
static hbool_t
-H5F_core_access (const char *name, int mode, H5F_search_t *key)
+H5F_core_access (const char *name, int mode, H5F_search_t *key/*out*/)
{
FUNC_ENTER (H5F_core_access, NULL, FAIL);
FUNC_LEAVE (FALSE);
@@ -112,6 +109,7 @@ H5F_core_open (const char *name, uintn flags, H5F_search_t *key)
lf->u.core.mem = H5MM_xmalloc (H5F_CORE_INC);
lf->u.core.alloc = H5F_CORE_INC;
lf->u.core.size = 0;
+ H5F_addr_reset (&(lf->eof));
if (key) {
key->dev = H5F_CORE_DEV;
@@ -121,7 +119,6 @@ H5F_core_open (const char *name, uintn flags, H5F_search_t *key)
FUNC_LEAVE (lf);
}
-
/*-------------------------------------------------------------------------
* Function: H5F_core_close
@@ -158,8 +155,8 @@ H5F_core_close (H5F_low_t *lf)
* Function: H5F_core_read
*
* Purpose: Reads SIZE bytes beginning at address ADDR in file LF and
- * places them in buffer BUF. Reading past the end of the
- * file returns zeros instead of failing.
+ * places them in buffer BUF. Reading past the logical or
+ * physical end of the file returns zeros instead of failing.
*
* Errors:
*
@@ -175,17 +172,24 @@ H5F_core_close (H5F_low_t *lf)
*-------------------------------------------------------------------------
*/
static herr_t
-H5F_core_read (H5F_low_t *lf, haddr_t addr, size_t size, uint8 *buf)
+H5F_core_read (H5F_low_t *lf, const haddr_t *addr, size_t size, uint8 *buf)
{
size_t n;
+ size_t eof;
FUNC_ENTER (H5F_core_read, NULL, FAIL);
- if (addr>=lf->u.core.size) {
+ assert (lf);
+ assert (addr && H5F_addr_defined (addr));
+ assert (buf);
+
+ eof = MIN (lf->eof.offset, lf->u.core.size);
+
+ if (addr->offset>=eof) {
HDmemset (buf, 0, size);
} else {
- n = MIN (size, lf->u.core.size - addr);
- HDmemcpy (buf, lf->u.core.mem + addr, n);
+ n = MIN (size, eof - addr->offset);
+ HDmemcpy (buf, lf->u.core.mem + addr->offset, n);
HDmemset (buf+n, 0, size-n);
}
@@ -198,7 +202,8 @@ H5F_core_read (H5F_low_t *lf, haddr_t addr, size_t size, uint8 *buf)
* Function: H5F_core_write
*
* Purpose: Writes SIZE bytes from the beginning of BUF into file LF at
- * file address ADDR.
+ * file address ADDR. The file is extended as necessary to
+ * accommodate the new data.
*
* Errors:
*
@@ -214,84 +219,31 @@ H5F_core_read (H5F_low_t *lf, haddr_t addr, size_t size, uint8 *buf)
*-------------------------------------------------------------------------
*/
static herr_t
-H5F_core_write (H5F_low_t *lf, haddr_t addr, size_t size, const uint8 *buf)
+H5F_core_write (H5F_low_t *lf, const haddr_t *addr, size_t size,
+ const uint8 *buf)
{
+ size_t inc_amount;
+
FUNC_ENTER (H5F_core_write, NULL, FAIL);
+ assert (lf);
+ assert (addr && H5F_addr_defined (addr));
+ assert (buf);
+
/* Allocate more space */
- if (addr+size>lf->u.core.alloc) {
- lf->u.core.alloc = lf->u.core.alloc + MAX (addr+size-lf->u.core.alloc,
- H5F_CORE_INC);
+ if (addr->offset+size>lf->u.core.alloc) {
+ inc_amount = MAX (addr->offset+size-lf->u.core.alloc, H5F_CORE_INC);
+ lf->u.core.alloc = lf->u.core.alloc + inc_amount;
lf->u.core.mem = H5MM_xrealloc (lf->u.core.mem, lf->u.core.alloc);
}
- /* Move EOF marker */
- if (addr+size>lf->u.core.size) {
- lf->u.core.size = addr + size;
+ /* Move the physical EOF marker */
+ if (addr->offset+size>lf->u.core.size) {
+ lf->u.core.size = addr->offset + size;
}
/* Copy data */
- HDmemcpy (lf->u.core.mem+addr, buf, size);
+ HDmemcpy (lf->u.core.mem+addr->offset, buf, size);
FUNC_LEAVE (SUCCEED);
}
-
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_core_flush
- *
- * Purpose: Makes sure that all data is flushed. This doesn't apply to
- * this driver.
- *
- * Errors:
- *
- * Return: Success: SUCCEED
- *
- * Failure: FAIL
- *
- * Programmer: Robb Matzke
- * Wednesday, October 22, 1997
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5F_core_flush (H5F_low_t *lf)
-{
- FUNC_ENTER (H5F_core_flush, NULL, FAIL);
-
- /* Not necessary with this driver */
-
- FUNC_LEAVE (SUCCEED);
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_core_size
- *
- * Purpose: Returns the current size of the file in bytes.
- *
- * Bugs: There is no way to determine if this function failed.
- *
- * Errors:
- *
- * Return: Success: Size of file in bytes
- *
- * Failure: 0
- *
- * Programmer: Robb Matzke
- * Wednesday, October 22, 1997
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static size_t
-H5F_core_size (H5F_low_t *lf)
-{
- FUNC_ENTER (H5F_core_size, NULL, 0);
-
- FUNC_LEAVE (lf->u.core.size);
-}
diff --git a/src/H5Ffamily.c b/src/H5Ffamily.c
new file mode 100644
index 0000000..6840c03
--- /dev/null
+++ b/src/H5Ffamily.c
@@ -0,0 +1,547 @@
+/*
+ * Copyright (C) 1997 Spizella Software
+ * All rights reserved.
+ *
+ * Programmer: Robb Matzke <matzke@llnl.gov>
+ * Monday, November 10, 1997
+ *
+ * Purpose: Implements a family of files that acts as a single hdf5
+ * file. The purpose is to be able to split a huge file on a
+ * 64-bit platform, transfer all the <2GB members to a 32-bit
+ * platform, and then access the entire huge file on the 32-bit
+ * platform.
+ *
+ * All family members are logically the same size although their
+ * physical sizes may vary. The logical member size is
+ * determined by looking at the physical size of the first
+ * member and rounding that up to the next power of two. When
+ * creating a file family, the first member is created with a
+ * predefined physical size (actually, this happens when the
+ * file family is flushed, and can be quite time consuming on
+ * file systems that don't implement holes, like nfs).
+ *
+ */
+#include <H5private.h>
+#include <H5Eprivate.h>
+#include <H5Fprivate.h>
+#include <H5MMprivate.h>
+
+#define PABLO_MASK H5F_family
+static hbool_t interface_initialize_g = FALSE;
+
+/*
+ * Number of bits in the member address. This can be up to (but not
+ * including) the number of bits in the `off_t' type, but be warned that some
+ * operating systems are not able to write to the last possible address of a
+ * file, so a safe maximum is two less than the number of bits in an `off_t'.
+ * Smaller values result in files of a more manageable size (from a human
+ * perspective) but also limit the total logical size of the hdf5 file.
+ */
+#define H5F_FAM_DFLT_NBITS 26u /*64MB*/
+
+#define H5F_FAM_MASK(N) (((uint64)1<<(N))-1)
+#define H5F_FAM_OFFSET(ADDR,N) ((ADDR)->offset & H5F_FAM_MASK(N))
+#define H5F_FAM_MEMBNO(ADDR,N) ((ADDR)->offset >> N)
+
+static hbool_t H5F_fam_access (const char *name, int mode, H5F_search_t *key);
+static H5F_low_t *H5F_fam_open (const char *name, uintn flags, H5F_search_t*);
+static herr_t H5F_fam_close (H5F_low_t *lf);
+static herr_t H5F_fam_read (H5F_low_t *lf, const haddr_t *addr, size_t size,
+ uint8 *buf);
+static herr_t H5F_fam_write (H5F_low_t *lf, const haddr_t *addr, size_t size,
+ const uint8 *buf);
+static herr_t H5F_fam_flush (H5F_low_t *lf);
+
+const H5F_low_class_t H5F_LOW_FAM[1] = {{
+ H5F_fam_access, /* access method */
+ H5F_fam_open, /* open method */
+ H5F_fam_close, /* close method */
+ H5F_fam_read, /* read method */
+ H5F_fam_write, /* write method */
+ H5F_fam_flush, /* flush method */
+ NULL, /* extend method */
+}};
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_fam_open
+ *
+ * Purpose: Opens a file family with the specified base name. The name
+ * should contain a printf-style "%d" field which will be
+ * expanded with a zero-origin family member number.
+ *
+ * Bugs: We don't check for overflow on the name, so keep it under
+ * 4kb, please. Also, we don't actually check for the `%d'
+ * field because we assume that the caller already did. Who
+ * knows what happens when all the family member names are the
+ * same!
+ *
+ * Return: Success: Low-level file pointer
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Monday, November 10, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5F_low_t *
+H5F_fam_open (const char *name, uintn flags, H5F_search_t *key/*out*/)
+{
+ H5F_low_t *ret_value = NULL, *lf=NULL;
+ H5F_low_t *member = NULL; /*a family member */
+ char member_name[4096]; /*name of family member */
+ intn membno; /*member number (zero-origin) */
+ size_t nbits=H5F_FAM_DFLT_NBITS;/*num bits in an offset */
+ haddr_t tmp_addr; /*temporary address */
+
+ FUNC_ENTER (H5F_fam_open, NULL, NULL);
+
+ /*
+ * If we're truncating the file then delete all but the first family
+ * member. Use the default number of bits for the offset.
+ */
+ if ((flags & H5F_ACC_WRITE) && (flags & H5F_ACC_TRUNC)) {
+ for (membno=1; /*void*/; membno++) {
+ sprintf (member_name, name, membno);
+ if (!H5F_low_access (H5F_LOW_DFLT, member_name, F_OK, NULL)) {
+ break;
+ } else if (unlink (member_name)<0) {
+ HGOTO_ERROR (H5E_IO, H5E_CANTINIT, NULL);/*can't delete member*/
+ }
+ }
+ }
+
+ /* Create the file descriptor */
+ lf = H5MM_xcalloc (1, sizeof(H5F_low_t));
+ lf->u.fam.name = H5MM_xstrdup (name);
+ lf->u.fam.flags = (flags & ~H5F_ACC_CREAT);
+
+ /* Open all existing members */
+ for (membno=0; /*void*/; membno++) {
+ sprintf (member_name, name, membno);
+
+ /*
+ * Open the family member. After the first member is opened or created,
+ * turn off the creation flag so we don't create a zillion family
+ * members.
+ */
+ member = H5F_low_open (H5F_LOW_DFLT, member_name, flags,
+ 0==membno?key:NULL);
+ if (!member) {
+ if (0==membno) {
+ /* Can't open first family member */
+ HGOTO_ERROR (H5E_IO, H5E_CANTOPENFILE, NULL);
+ }
+ break;
+ }
+ flags &= ~H5F_ACC_CREAT;
+
+ /* Add the member to the family */
+ if (lf->u.fam.nmemb>=lf->u.fam.nalloc) {
+ lf->u.fam.nalloc = MAX (100, 2*lf->u.fam.nalloc);
+ lf->u.fam.memb = H5MM_xrealloc (lf->u.fam.memb,
+ lf->u.fam.nalloc*sizeof(H5F_low_t*));
+ }
+ lf->u.fam.memb[lf->u.fam.nmemb++] = member;
+ member = NULL;
+ }
+
+ /*
+ * If the first and second files exists then round the first file size up
+ * to the next power of two and use that as the number of bits per family
+ * member.
+ */
+ if (lf->u.fam.nmemb>=2) {
+ size_t size = H5F_low_size (lf->u.fam.memb[0], &tmp_addr);
+ for (nbits=8*sizeof(size_t)-1; nbits>0; --nbits) {
+ size_t mask = (size_t)1 << nbits;
+ if (size & mask) {
+ if (size != mask) {
+ size++;
+#ifdef H5F_DEBUG
+ fprintf (stderr, "HDF5-DIAG: family member size was rounded up "
+ "to a power of 2");
+#endif
+ }
+ break;
+ }
+ }
+ }
+ lf->u.fam.offset_bits = nbits;
+
+#ifdef H5F_DEBUG
+ if (nbits>=30) {
+ fprintf (stderr, "HDF5-DIAG: family members are %dGB\n", 1<<(nbits-30));
+ } else if (nbits>=20) {
+ fprintf (stderr, "HDF5-DIAG: family members are %dMB\n", 1<<(nbits-20));
+ } else if (nbits>=10) {
+ fprintf (stderr, "HDF5-DIAG: family members are %dkB\n", 1<<(nbits-10));
+ } else {
+ fprintf (stderr, "HDF5-DIAG: family members are %d bytes\n", 1<<nbits);
+ }
+#endif
+
+ /*
+ * Get the total family size and store it in the max_addr field.
+ */
+ assert (lf->u.fam.nmemb>=1);
+ lf->eof.offset = (size_t)1 << lf->u.fam.offset_bits;
+ lf->eof.offset *= (lf->u.fam.nmemb-1);
+ lf->eof.offset += lf->u.fam.memb[lf->u.fam.nmemb-1]->eof.offset;
+
+ HRETURN (lf);
+
+ done:
+ if (!ret_value) {
+ if (lf) {
+ H5F_fam_close (lf);
+ H5MM_xfree (lf);
+ }
+ }
+ FUNC_LEAVE (ret_value);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_fam_close
+ *
+ * Purpose: Closes all members of a file family and releases resources
+ * used by the file descriptor.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Monday, November 10, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5F_fam_close (H5F_low_t *lf)
+{
+ intn membno;
+
+ FUNC_ENTER (H5F_fam_close, NULL, FAIL);
+
+ assert (lf);
+
+ for (membno=0; membno<lf->u.fam.nmemb; membno++) {
+ lf->u.fam.memb[membno] = H5F_low_close (lf->u.fam.memb[membno]);
+ }
+ H5MM_xfree (lf->u.fam.memb);
+ H5MM_xfree (lf->u.fam.name);
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_fam_read
+ *
+ * Purpose: Reads a chunk of contiguous data from the file family.
+ * Reading past the physical end of a file returns zeros instead
+ * of failing. We must insure that if the logical end of file is
+ * before the physical end of file that we will read zeros there
+ * also (the only time this can happen is if we create a family
+ * and then close it before the first member is filled, since
+ * flushing the file causes the first member to be physically
+ * extended to it's maximum size).
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Monday, November 10, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5F_fam_read (H5F_low_t *lf, const haddr_t *addr, size_t size, uint8 *buf)
+{
+ size_t nbytes;
+ haddr_t cur_addr;
+ uintn membno;
+ off_t offset;
+ size_t member_size;
+
+ FUNC_ENTER (H5F_fam_read, NULL, FAIL);
+
+ assert (lf);
+ assert (addr && H5F_addr_defined (addr));
+ assert (buf);
+
+ member_size = (size_t)1 << lf->u.fam.offset_bits;
+ membno = H5F_FAM_MEMBNO (addr, lf->u.fam.offset_bits);
+ offset = H5F_FAM_OFFSET (addr, lf->u.fam.offset_bits);
+ cur_addr = *addr;
+
+ while (size>0) {
+ if (membno>=lf->u.fam.nmemb) {
+ HDmemset (buf, 0, size);
+ break;
+ } else {
+ nbytes = MIN (size, member_size-offset);
+ cur_addr.offset = offset;
+ if (H5F_low_read (lf->u.fam.memb[membno], &cur_addr,
+ nbytes, buf)<0) {
+ /* Can't read from family member */
+ HRETURN_ERROR (H5E_IO, H5E_READERROR, FAIL);
+ }
+ buf += nbytes;
+ size -= nbytes;
+ membno++;
+ offset=0;
+ }
+ }
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_fam_write
+ *
+ * Purpose: Writes BUF to the family of files. The superclass has
+ * already insured that we aren't writing past the logical end
+ * of file, so this function will extend the physical file to
+ * accommodate the new data if necessary.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Monday, November 10, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5F_fam_write (H5F_low_t *lf, const haddr_t *addr, size_t size,
+ const uint8 *buf)
+{
+ size_t nbytes;
+ haddr_t cur_addr, max_addr;
+ uintn membno;
+ off_t offset;
+ H5F_low_t *member = NULL;
+ char member_name[4096];
+ intn i;
+ size_t member_size;
+
+ FUNC_ENTER (H5F_fam_write, NULL, FAIL);
+
+ assert (lf);
+ assert (addr && H5F_addr_defined (addr));
+ assert (buf);
+
+ member_size = (size_t)1 << lf->u.fam.offset_bits;
+ membno = H5F_FAM_MEMBNO (addr, lf->u.fam.offset_bits);
+ offset = H5F_FAM_OFFSET (addr, lf->u.fam.offset_bits);
+ cur_addr = *addr;
+
+ while (size>0) {
+ nbytes = MIN (size, member_size-offset);
+ cur_addr.offset = offset;
+
+ if (membno>=lf->u.fam.nmemb) {
+ /*
+ * We're writing past the end of the last family member--create the
+ * new family member(s)
+ */
+ for (i=lf->u.fam.nmemb; i<=membno; i++) {
+ sprintf (member_name, lf->u.fam.name, i);
+ member = H5F_low_open (H5F_LOW_DFLT, member_name,
+ lf->u.fam.flags|H5F_ACC_CREAT,
+ NULL);
+ if (!member) {
+ /* Can't create a new member */
+ HRETURN_ERROR (H5E_IO, H5E_CANTOPENFILE, FAIL);
+ }
+
+ /*
+ * For members in the middle, set their logical eof to the
+ * maximum possible value.
+ */
+ if (i<membno) {
+ H5F_addr_reset (&max_addr);
+ H5F_addr_inc (&max_addr, member_size);
+ H5F_low_seteof (member, &max_addr);
+ }
+
+ if (lf->u.fam.nmemb>=lf->u.fam.nalloc) {
+ lf->u.fam.nalloc *= 2;
+ lf->u.fam.memb = H5MM_xrealloc (lf->u.fam.memb,
+ (lf->u.fam.nalloc *
+ sizeof(H5F_low_t*)));
+ }
+ lf->u.fam.memb[lf->u.fam.nmemb++] = member;
+ }
+ }
+
+ /*
+ * Make sure the logical eof is large enough to handle the request.
+ */
+ max_addr = cur_addr;
+ H5F_addr_inc (&max_addr, nbytes);
+ H5F_low_seteof (lf->u.fam.memb[membno], &max_addr);
+
+
+ /* Write the data to the member */
+ if (H5F_low_write (lf->u.fam.memb[membno], &cur_addr,
+ nbytes, buf)<0) {
+ /* Can't write to family member */
+ HRETURN_ERROR (H5E_IO, H5E_WRITEERROR, FAIL);
+ }
+ buf += nbytes;
+ size -= nbytes;
+ membno++;
+ offset=0;
+ }
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_fam_flush
+ *
+ * Purpose: Flushes all data to disk and makes sure that the first member
+ * is as large as a member can be so we can accurately detect
+ * the member size if we open this file for read access at a
+ * later date.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Monday, November 10, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5F_fam_flush (H5F_low_t *lf)
+{
+ int membno, nerrors=0;
+ uint8 buf[1];
+ haddr_t addr1, addr2, addr3;
+ size_t max_offset;
+
+ FUNC_ENTER (H5F_fam_flush, NULL, FAIL);
+
+ /*
+ * Make sure that the first family member is the maximum size because
+ * H5F_fam_open() looks at the size of the first member to determine the
+ * number of bits to use for each family member offset. We do this by
+ * reading the last possible byte from the member (which defaults to zero
+ * if we're reading past the end of the member) and then writing it back.
+ */
+ max_offset = H5F_FAM_MASK (lf->u.fam.offset_bits);
+ H5F_addr_reset (&addr1);
+ H5F_addr_inc (&addr1, max_offset);
+ H5F_low_size (lf->u.fam.memb[0], &addr2); /*remember logical eof*/
+ addr3 = addr1;
+ H5F_addr_inc (&addr3, (size_t)1);
+ H5F_low_seteof (lf->u.fam.memb[0], &addr3); /*prevent a warning*/
+ if (H5F_low_read (lf->u.fam.memb[0], &addr1, 1, buf)<0) {
+ /* Can't read from first family member */
+ HRETURN_ERROR (H5E_IO, H5E_READERROR, FAIL);
+ }
+ if (H5F_low_write (lf->u.fam.memb[0], &addr1, 1, buf)<0) {
+ /* Can't write to first family member */
+ HRETURN_ERROR (H5E_IO, H5E_WRITEERROR, FAIL);
+ }
+ H5F_low_seteof (lf->u.fam.memb[0], &addr2); /*reset old eof*/
+
+ /*
+ * Flush each member file. Don't return an error status until we've
+ * flushed as much as possible.
+ */
+ for (membno=0; membno<lf->u.fam.nmemb; membno++) {
+ if (H5F_low_flush (lf->u.fam.memb[membno])<0) {
+ nerrors++;
+ }
+ }
+ if (nerrors) {
+ /* Can't flush family member */
+ HRETURN_ERROR (H5E_IO, H5E_WRITEERROR, FAIL);
+ }
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_fam_access
+ *
+ * Purpose: Determines if all members of the file family can be accessed
+ * and returns the key for the first member of the family.
+ *
+ * Return: Success: TRUE or FALSE
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Monday, November 10, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static hbool_t
+H5F_fam_access (const char *name, int mode, H5F_search_t *key/*out*/)
+{
+ intn membno;
+ char member_name[4096];
+ hbool_t status;
+
+ FUNC_ENTER (H5F_fam_access, NULL, FAIL);
+
+ for (membno=0; /*void*/; membno++) {
+ sprintf (member_name, name, membno);
+ status = H5F_low_access (H5F_LOW_DFLT, member_name, mode,
+ 0==membno?key:NULL);
+
+ if (!status) {
+ if (F_OK==mode) {
+ /*
+ * If we didn't find a member then we must have gotten to the end
+ * of the family. As long as we found the first member(s) the
+ * family exists.
+ */
+ HRETURN (membno>0);
+ } else if (H5F_low_access (H5F_LOW_DFLT, member_name, F_OK, NULL)) {
+ /*
+ * The file exists but didn't have the write access permissions.
+ */
+ HRETURN (FALSE);
+ } else {
+ /*
+ * The file doesn't exist because we got to the end of the
+ * family.
+ */
+ HRETURN (TRUE);
+ }
+ }
+
+ if (status<0) {
+ /* Access method failed for a member file */
+ HRETURN_ERROR (H5E_IO, H5E_CANTOPENFILE, FAIL);
+ }
+ }
+
+ FUNC_LEAVE (TRUE);
+}
diff --git a/src/H5Fistore.c b/src/H5Fistore.c
index 06997a1..b997945 100644
--- a/src/H5Fistore.c
+++ b/src/H5Fistore.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 1997 Spizella Software
+ * Copyright (C) 1997 NCSA
* All rights reserved.
*
- * Programmer: Robb Matzke <robb@arborea.spizella.com>
+ * Programmer: Robb Matzke <matzke@llnl.gov>
* Wednesday, October 8, 1997
*/
#include <H5private.h>
@@ -29,18 +29,20 @@ 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, H5B_ins_t, void *_lt_key,
- void *_udata, void *_rt_key);
+static herr_t H5F_istore_new_node (H5F_t *f, H5B_ins_t, void *_lt_key,
+ void *_udata, void *_rt_key, haddr_t*);
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,
- void *_lt_key, hbool_t *lt_key_changed,
- void *_md_key, void *_udata,
- void *_rt_key, hbool_t *rt_key_changed);
+static herr_t H5F_istore_found (H5F_t *f, const haddr_t *addr,
+ const void *_lt_key, void *_udata,
+ const void *_rt_key);
+static H5B_ins_t H5F_istore_insert (H5F_t *f, const haddr_t *addr,
+ void *_lt_key, hbool_t *lt_key_changed,
+ void *_md_key, void *_udata,
+ void *_rt_key, hbool_t *rt_key_changed,
+ haddr_t*);
static herr_t H5F_istore_decode_key (H5F_t *f, H5B_t *bt, uint8 *raw,
void *_key);
static herr_t H5F_istore_encode_key (H5F_t *f, H5B_t *bt, uint8 *raw,
@@ -317,8 +319,9 @@ H5F_istore_cmp3 (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key)
* the domain represented by UDATA doesn't intersect the domain
* already represented by the B-tree.
*
- * Return: Success: Address of leaf, which is passed in from the
- * UDATA pointer.
+ * Return: Success: SUCCEED. The address of leaf is returned
+ * through the ADDR argument. It is also added
+ * to the UDATA.
*
* Failure: FAIL
*
@@ -329,9 +332,10 @@ H5F_istore_cmp3 (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key)
*
*-------------------------------------------------------------------------
*/
-static haddr_t
+static herr_t
H5F_istore_new_node (H5F_t *f, H5B_ins_t op,
- void *_lt_key, void *_udata, void *_rt_key)
+ void *_lt_key, void *_udata, void *_rt_key,
+ haddr_t *addr/*out*/)
{
H5F_istore_key_t *lt_key = (H5F_istore_key_t *)_lt_key;
H5F_istore_key_t *rt_key = (H5F_istore_key_t *)_rt_key;
@@ -347,14 +351,16 @@ H5F_istore_new_node (H5F_t *f, H5B_ins_t op,
assert (rt_key);
assert (udata);
assert (udata->mesg.ndims>=0 && udata->mesg.ndims<H5O_ISTORE_NDIMS);
+ assert (addr);
/* Allocate new storage */
nbytes = H5V_vector_reduce_product (udata->mesg.ndims, udata->key.size);
assert (nbytes>0);
- if ((udata->addr=H5MF_alloc (f, nbytes))<0) {
+ if (H5MF_alloc (f, H5MF_RAW, nbytes, addr/*out*/)<0) {
/* Couldn't allocate new file storage */
HRETURN_ERROR (H5E_IO, H5E_CANTINIT, FAIL);
}
+ udata->addr = *addr;
/* Initialize the key(s) */
for (i=0; i<udata->mesg.ndims; i++) {
@@ -376,7 +382,7 @@ H5F_istore_new_node (H5F_t *f, H5B_ins_t op,
}
}
- FUNC_LEAVE (udata->addr);
+ FUNC_LEAVE (SUCCEED);
}
@@ -403,7 +409,7 @@ H5F_istore_new_node (H5F_t *f, H5B_ins_t op,
*-------------------------------------------------------------------------
*/
static herr_t
-H5F_istore_found (H5F_t *f, haddr_t addr, const void *_lt_key,
+H5F_istore_found (H5F_t *f, const haddr_t *addr, const void *_lt_key,
void *_udata, const void *_rt_key)
{
H5F_istore_ud1_t *udata = (H5F_istore_ud1_t *)_udata;
@@ -414,12 +420,12 @@ H5F_istore_found (H5F_t *f, haddr_t addr, const void *_lt_key,
/* Check arguments */
assert (f);
- assert (addr>=0);
+ assert (addr && H5F_addr_defined (addr));
assert (udata);
assert (lt_key);
/* Initialize return values */
- udata->addr = addr;
+ udata->addr = *addr;
for (i=0; i<udata->mesg.ndims; i++) {
udata->key.offset[i] = lt_key->offset[i];
udata->key.size[i] = lt_key->size[i];
@@ -447,13 +453,12 @@ H5F_istore_found (H5F_t *f, haddr_t addr, const void *_lt_key,
* `offset' and `size' fields). On return, UDATA describes the
* logical addresses contained in a chunk on disk.
*
- * Return: Success: SUCCEED, with UDATA containing information
- * about the (newly allocated) chunk.
+ * Return: Success: An insertion command for the caller, one of
+ * the H5B_INS_* constants. The address of the
+ * new chunk is returned through the NEW_NODE
+ * argument.
*
- * If the storage address has changed then the
- * new address is returned.
- *
- * Failure: FAIL
+ * Failure: H5B_INS_ERROR
*
* Programmer: Robb Matzke
* Thursday, October 9, 1997
@@ -462,32 +467,33 @@ H5F_istore_found (H5F_t *f, haddr_t addr, const void *_lt_key,
*
*-------------------------------------------------------------------------
*/
-static haddr_t
-H5F_istore_insert (H5F_t *f, haddr_t addr, H5B_ins_t *parent_ins,
+static H5B_ins_t
+H5F_istore_insert (H5F_t *f, const haddr_t *addr,
void *_lt_key, hbool_t *lt_key_changed,
void *_md_key, void *_udata,
- void *_rt_key, hbool_t *rt_key_changed)
+ void *_rt_key, hbool_t *rt_key_changed,
+ haddr_t *new_node/*out*/)
{
H5F_istore_key_t *lt_key = (H5F_istore_key_t *)_lt_key;
H5F_istore_key_t *md_key = (H5F_istore_key_t *)_md_key;
H5F_istore_key_t *rt_key = (H5F_istore_key_t *)_rt_key;
H5F_istore_ud1_t *udata = (H5F_istore_ud1_t *)_udata;
intn i, cmp;
- haddr_t ret_value = 0;
+ H5B_ins_t ret_value = H5B_INS_ERROR;
size_t nbytes;
FUNC_ENTER (H5F_istore_insert, NULL, FAIL);
/* check args */
assert (f);
- assert (addr>=0);
- assert (parent_ins);
+ assert (addr && H5F_addr_defined (addr));
assert (lt_key);
assert (lt_key_changed);
assert (md_key);
assert (udata);
assert (rt_key);
assert (rt_key_changed);
+ assert (new_node);
cmp = H5F_istore_cmp3 (f, lt_key, udata, rt_key);
assert (cmp<=0);
@@ -503,8 +509,8 @@ H5F_istore_insert (H5F_t *f, haddr_t addr, H5B_ins_t *parent_ins,
/*
* Already exists. Just return the info.
*/
- udata->addr = addr;
- *parent_ins = H5B_INS_NOOP;
+ udata->addr = *addr;
+ ret_value = H5B_INS_NOOP;
} else if (H5V_hyper_disjointp (udata->mesg.ndims,
lt_key->offset, lt_key->size,
@@ -528,11 +534,11 @@ H5F_istore_insert (H5F_t *f, haddr_t addr, H5B_ins_t *parent_ins,
/*
* Allocate storage for the new chunk
*/
- if ((udata->addr=ret_value=H5MF_alloc (f, nbytes))<=0) {
+ if (H5MF_alloc (f, H5MF_RAW, nbytes, new_node/*out*/)<0) {
HRETURN_ERROR (H5E_IO, H5E_CANTINIT, FAIL);
}
-
- *parent_ins = H5B_INS_RIGHT;
+ udata->addr = *new_node;
+ ret_value = H5B_INS_RIGHT;
} else {
assert ("HDF5 INTERNAL ERROR -- see rpm" && 0);
@@ -599,7 +605,7 @@ H5F_istore_copy_hyperslab (H5F_t *f, const H5O_istore_t *istore, H5F_isop_t op,
/* check args */
assert (f);
assert (istore);
- assert (istore->btree_addr>0);
+ assert (H5F_addr_defined (&(istore->btree_addr)));
assert (istore->ndims>0 && istore->ndims<=H5O_ISTORE_NDIMS);
assert (H5F_ISTORE_READ==op || H5F_ISTORE_WRITE==op);
assert (size);
@@ -659,10 +665,10 @@ H5F_istore_copy_hyperslab (H5F_t *f, const H5O_istore_t *istore, H5F_isop_t op,
}
if (H5F_ISTORE_WRITE==op) {
- status = H5B_insert (f, H5B_ISTORE, istore->btree_addr, &udata);
+ status = H5B_insert (f, H5B_ISTORE, &(istore->btree_addr), &udata);
assert (status>=0);
} else {
- status = H5B_find (f, H5B_ISTORE, istore->btree_addr, &udata);
+ status = H5B_find (f, H5B_ISTORE, &(istore->btree_addr), &udata);
}
/*
@@ -672,8 +678,8 @@ H5F_istore_copy_hyperslab (H5F_t *f, const H5O_istore_t *istore, H5F_isop_t op,
if (H5F_ISTORE_READ==op ||
!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) {
+ if (status>=0 && H5F_addr_defined (&(udata.addr))) {
+ if (H5F_block_read (f, &(udata.addr), chunk_size, chunk)<0) {
HGOTO_ERROR (H5E_IO, H5E_READERROR, FAIL);
}
} else {
@@ -686,7 +692,7 @@ H5F_istore_copy_hyperslab (H5F_t *f, const H5O_istore_t *istore, H5F_isop_t op,
H5V_hyper_copy (istore->ndims, sub_size,
udata.key.size, offset_wrt_chunk, chunk,
size_m, sub_offset_m, buf);
- if (H5F_block_write (f, udata.addr, chunk_size, chunk)<0) {
+ if (H5F_block_write (f, &(udata.addr), chunk_size, chunk)<0) {
HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL);
}
} else {
@@ -835,7 +841,7 @@ H5F_istore_new (H5F_t *f, struct H5O_istore_t *istore,
#endif
udata.mesg.ndims = istore->ndims = ndims;
- if ((istore->btree_addr=H5B_new (f, H5B_ISTORE, &udata))<0) {
+ if (H5B_new (f, H5B_ISTORE, &udata, &(istore->btree_addr)/*out*/)<0) {
HRETURN_ERROR (H5E_IO, H5E_CANTINIT, FAIL); /* Can't create B-tree */
}
diff --git a/src/H5Flow.c b/src/H5Flow.c
index 18cc417..55010bc 100644
--- a/src/H5Flow.c
+++ b/src/H5Flow.c
@@ -22,7 +22,6 @@
#define PABLO_MASK H5F_low
static hbool_t interface_initialize_g = FALSE;
-
/*-------------------------------------------------------------------------
* Function: H5F_low_open
@@ -46,8 +45,12 @@ static hbool_t interface_initialize_g = FALSE;
* overwritten.
*
* The KEY argument is initialized with data which is unique to
- * this file. For unix files, it's the device number and
- * i-node. Other low level drivers might use data.
+ * this file. Opening the same file (even by a different name)
+ * should return the same key.
+ *
+ * This is a virtual function only; the actual open operation is
+ * performed by the subclass. This function will fail if the
+ * subclass hasn't defined an open method.
*
* Errors:
* IO CANTOPENFILE Open failed.
@@ -65,7 +68,7 @@ static hbool_t interface_initialize_g = FALSE;
*/
H5F_low_t *
H5F_low_open (const H5F_low_class_t *type, const char *name, uintn flags,
- H5F_search_t *key)
+ H5F_search_t *key/*out*/)
{
H5F_low_t *lf = NULL;
@@ -82,12 +85,20 @@ H5F_low_open (const H5F_low_class_t *type, const char *name, uintn flags,
FUNC_LEAVE (lf);
}
-
/*-------------------------------------------------------------------------
* Function: H5F_low_close
*
- * Purpose: Closes a low-level file.
+ * Purpose: Closes a low-level file. The subclass should free all
+ * resources used by the file descriptor but should not free the
+ * file descriptor itself. The close method in the subclass is
+ * optional; lack of a close method results in only the file
+ * descriptor being freed.
+ *
+ * It is safe to call this function with a null pointer for the
+ * file descriptor. This function returns a null pointer that
+ * the caller can assign to the file descriptor pointer as it's
+ * closed like `desc=H5F_low_close(desc)'.
*
* Errors:
* IO CLOSEERROR Close failed.
@@ -124,7 +135,12 @@ H5F_low_close (H5F_low_t *lf)
* Function: H5F_low_read
*
* Purpose: Reads SIZE bytes of data beginning at address ADDR of the
- * file LF and puts the result in BUF.
+ * file LF and puts the result in BUF. Behavior when reading
+ * past the logical or physical end of file is to return zeros
+ * for that part of the request.
+ *
+ * This is only a virtual function; the subclass must define a
+ * read method or this function will fail.
*
* Errors:
* IO READERROR Read failed.
@@ -142,13 +158,15 @@ H5F_low_close (H5F_low_t *lf)
*-------------------------------------------------------------------------
*/
herr_t
-H5F_low_read (H5F_low_t *lf, haddr_t addr, size_t size, uint8 *buf)
+H5F_low_read (H5F_low_t *lf, const haddr_t *addr, size_t size,
+ uint8 *buf/*out*/)
{
herr_t ret_value = FAIL;
FUNC_ENTER (H5F_low_read, NULL, FAIL);
assert (lf && lf->type);
+ assert (addr && H5F_addr_defined (addr));
assert (buf);
if (lf->type->read) {
@@ -167,7 +185,11 @@ H5F_low_read (H5F_low_t *lf, haddr_t addr, size_t size, uint8 *buf)
* Function: H5F_low_write
*
* Purpose: Writes SIZE bytes of data from BUF into the file LF beginning
- * at address ADDR of the file.
+ * at address ADDR of the file. Writing past the logical or
+ * physical end of file causes the file to be extended.
+ *
+ * This is a virtual function only; if the subclass doesn't
+ * define a write method then this function will fail.
*
* Errors:
* IO UNSUPPORTED No write method.
@@ -185,15 +207,27 @@ H5F_low_read (H5F_low_t *lf, haddr_t addr, size_t size, uint8 *buf)
*-------------------------------------------------------------------------
*/
herr_t
-H5F_low_write (H5F_low_t *lf, haddr_t addr, size_t size, const uint8 *buf)
+H5F_low_write (H5F_low_t *lf, const haddr_t *addr, size_t size,
+ const uint8 *buf)
{
herr_t ret_value = FAIL;
+ haddr_t tmp_addr;
FUNC_ENTER (H5F_low_write, NULL, FAIL);
assert (lf && lf->type);
+ assert (addr && H5F_addr_defined (addr));
assert (buf);
+ /* Extend the file eof marker if we write past it */
+ tmp_addr = *addr;
+ H5F_addr_inc (&tmp_addr, size);
+ if (H5F_addr_gt (&tmp_addr, &(lf->eof))) {
+ fprintf (stderr, "HDF5-DIAG: extending file w/o allocation\n");
+ lf->eof = tmp_addr;
+ }
+
+ /* Write the data */
if (lf->type->write) {
if ((ret_value = (lf->type->write)(lf, addr, size, buf))<0) {
HRETURN_ERROR (H5E_IO, H5E_WRITEERROR, ret_value);/*write failed*/
@@ -204,13 +238,63 @@ H5F_low_write (H5F_low_t *lf, haddr_t addr, size_t size, const uint8 *buf)
FUNC_LEAVE (ret_value);
}
-
/*-------------------------------------------------------------------------
+ * Function: H5F_low_flush
+ *
+ * Purpose: Flushes file buffers to disk. For instance, the stdio.h
+ * driver would call fflush().
+ *
+ * If the subclass doesn't define a flush method then this
+ * function doesn't do anything.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Monday, November 10, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_low_flush (H5F_low_t *lf)
+{
+ FUNC_ENTER (H5F_low_flush, NULL, FAIL);
+
+ assert (lf && lf->type);
+
+ if (lf->type->flush) {
+ if ((lf->type->flush)(lf)<0) {
+ /* Low level flush failed */
+ HRETURN_ERROR (H5E_IO, H5E_WRITEERROR, FAIL);
+ }
+ }
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
* Function: H5F_low_size
*
- * Purpose: Returns the current size of the file in bytes.
+ * Purpose: Returns the current logical size of the file in bytes. This
+ * may differ from the physical size of the file (most
+ * subclasses extend the physical file size during the write
+ * operation instead of the alloc operation).
+ *
+ * The next absolute file address is returned through the
+ * EOF argument. This is the address of the logical end of
+ * file (that is, the address of the first byte past the last
+ * byte which is logically in the file).
+ *
+ * Warning: The return value type (size_t) may not be large enough to
+ * represent the true size of the file. In such cases, the
+ * maximum possible size is returned. It is better to look at
+ * the EOF output argument to determine the total size.
*
* Errors:
* IO UNSUPPORTED No size method.
@@ -227,36 +311,48 @@ H5F_low_write (H5F_low_t *lf, haddr_t addr, size_t size, const uint8 *buf)
*-------------------------------------------------------------------------
*/
size_t
-H5F_low_size (H5F_low_t *lf)
+H5F_low_size (H5F_low_t *lf, haddr_t *eof/*out*/)
{
- size_t size;
+ size_t size = (size_t)(-1); /*max possible size*/
FUNC_ENTER (H5F_low_size, NULL, 0);
assert (lf && lf->type);
+ assert (eof);
- if (lf->type->size) {
- size = (lf->type->size)(lf);
- } else {
- HRETURN_ERROR (H5E_IO, H5E_UNSUPPORTED, 0);/*no size method*/
- }
+ *eof = lf->eof;
+ if (eof->offset < size) size = eof->offset;
FUNC_LEAVE (size);
}
-
/*-------------------------------------------------------------------------
* Function: H5F_low_access
*
- * Purpose: Sort of like access(2) except it might do special things for
- * various types of low-level file drivers.
+ * Purpose: Determines if a file can be accessed in a particular way by a
+ * particular subclass. The access modes for a file are the
+ * same as those of access(2), namely
+ *
+ * F_OK: determines if the file (or all parts of a multi-part
+ * file) exists.
+ *
+ * R_OK: determines if the file (or all parts of a multi-part
+ * file) are readable.
+ *
+ * W_OK: determines if the file (or all parts of a multi-part
+ * file) are writable.
+ *
+ * If a subclass doesn't define an access method, then we treat
+ * the name as if it were a local Unix file and test
+ * accessibility with the access(2) function. The KEY is
+ * returned as a device number and i-node pair.
*
* Return: Success: TRUE or FALSE. If TRUE, then KEY is
* initialized with data that makes this file
- * unique.
+ * unique (same value as H5F_low_open).
*
- * Failure: FAIL
+ * Failure: FAIL, KEY is undefined.
*
* Programmer: Robb Matzke
* Friday, October 24, 1997
@@ -267,7 +363,7 @@ H5F_low_size (H5F_low_t *lf)
*/
hbool_t
H5F_low_access (const H5F_low_class_t *type, const char *name, int mode,
- H5F_search_t *key)
+ H5F_search_t *key/*out*/)
{
hbool_t ret_value;
struct stat sb;
@@ -276,7 +372,7 @@ H5F_low_access (const H5F_low_class_t *type, const char *name, int mode,
assert (type);
if (type->access) {
- ret_value = (type->access)(name, mode, key);
+ ret_value = (type->access)(name, mode, key/*out*/);
} else {
ret_value = (0==access (name, mode));
@@ -289,3 +385,443 @@ H5F_low_access (const H5F_low_class_t *type, const char *name, int mode,
FUNC_LEAVE (ret_value);
}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_low_extend
+ *
+ * Purpose: Increases the logical size of a file by moving the logical
+ * end of file marker. A subclass can override this function by
+ * providing its own allocation method.
+ *
+ * Return: Success: SUCCEED, the address of the old end-of-file
+ * is returned through the ADDR argument and the
+ * logical size of the file has been extended by
+ * SIZE bytes.
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Thursday, November 13, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_low_extend (H5F_low_t *lf, intn op, size_t size, haddr_t *addr/*out*/)
+{
+ FUNC_ENTER (H5F_low_alloc, NULL, FAIL);
+
+ assert (lf);
+ assert (size>0);
+ assert (addr);
+
+ if (lf->type->extend) {
+ if ((lf->type->extend)(lf, op, size, addr/*out*/)<0) {
+ /* Unable to extend file */
+ HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL);
+ }
+ } else {
+ *addr = lf->eof;
+ H5F_addr_inc (&(lf->eof), size);
+ }
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_low_seteof
+ *
+ * Purpose: Sets the logical end-of-file to the specified address.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Thursday, November 13, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_low_seteof (H5F_low_t *lf, const haddr_t *addr)
+{
+ FUNC_ENTER (H5F_low_seteof, NULL, FAIL);
+
+ assert (lf);
+ assert (addr && H5F_addr_defined (addr));
+
+ lf->eof = *addr;
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_addr_cmp
+ *
+ * Purpose: Compares two addresses.
+ *
+ * Return: Success: <0 if A1<A2
+ * =0 if A1=A2
+ * >0 if A1>A2
+ *
+ * Failure: never fails
+ *
+ * Programmer: Robb Matzke
+ * Friday, November 7, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+intn
+H5F_addr_cmp (const haddr_t *a1, const haddr_t *a2)
+{
+ FUNC_ENTER (H5F_addr_cmp, NULL, FAIL);
+
+ assert (a1 && H5F_addr_defined (a1));
+ assert (a2 && H5F_addr_defined (a2));
+
+ if (a1->offset<a2->offset) HRETURN (-1);
+ if (a1->offset>a2->offset) HRETURN (1);
+
+ FUNC_LEAVE (0);
+}
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_addr_undef
+ *
+ * Purpose: Cause an address to become undefined.
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * Friday, November 7, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+H5F_addr_undef (haddr_t *addr)
+{
+ addr->offset = -1;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_addr_defined
+ *
+ * Purpose: Determines if an address has a defined value.
+ *
+ * Return: Success: TRUE or FALSE
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Friday, November 7, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+hbool_t
+H5F_addr_defined (const haddr_t *addr)
+{
+ FUNC_ENTER (H5F_addr_defined, NULL, FAIL);
+ FUNC_LEAVE (-1!=addr->offset && addr->offset>=0);
+}
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_addr_reset
+ *
+ * Purpose: Reset the address to zero.
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * Friday, November 7, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+H5F_addr_reset (haddr_t *addr)
+{
+ addr->offset = 0;
+}
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_addr_zerop
+ *
+ * Purpose: Determines if an address is zero.
+ *
+ * Return: Success: TRUE or FALSE
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Friday, November 7, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+hbool_t
+H5F_addr_zerop (const haddr_t *addr)
+{
+ FUNC_ENTER (H5F_addr_zerop, NULL, FAIL);
+ FUNC_LEAVE (0==addr->offset);
+}
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_addr_encode
+ *
+ * Purpose: Encodes an address into the buffer pointed to by *PP and
+ * then increments the pointer to the first byte after the
+ * address. An undefined value is stored as all 1's.
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * Friday, November 7, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+H5F_addr_encode (H5F_t *f, uint8 **pp, const haddr_t *addr)
+{
+ int i;
+ haddr_t tmp;
+
+ assert (f);
+ assert (pp && *pp);
+ assert (addr);
+
+ if (H5F_addr_defined (addr)) {
+ tmp = *addr;
+ for (i=0; i<H5F_SIZEOF_OFFSET (f); i++) {
+ *(*pp)++ = tmp.offset & 0xff;
+ tmp.offset >>= 8;
+ }
+ assert ("overflow" && 0==tmp.offset);
+
+ } else {
+ for (i=0; i<H5F_SIZEOF_OFFSET (f); i++) {
+ *(*pp)++ = 0xff;
+ }
+ }
+}
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_addr_decode
+ *
+ * Purpose: Decodes an address from the buffer pointed to by *PP and
+ * updates the pointer to point to the next byte after the
+ * address.
+ *
+ * If the value read is all 1's then the address is returned
+ * with an undefined value.
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * Friday, November 7, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+H5F_addr_decode (H5F_t *f, const uint8 **pp, haddr_t *addr/*out*/)
+{
+ int i;
+ haddr_t tmp;
+ uint8 c;
+ hbool_t all_zero = TRUE;
+
+ assert (f);
+ assert (pp && *pp);
+ assert (addr);
+
+ addr->offset = 0;
+ for (i=0; i<H5F_SIZEOF_OFFSET (f); i++) {
+ c = *(*pp)++;
+ if (c!=0xff) all_zero = FALSE;
+
+ if (i<sizeof(addr->offset)) {
+ tmp.offset = c;
+ tmp.offset <<= i*8; /*use tmp to get casting right*/
+ addr->offset |= tmp.offset;
+ } else if (!all_zero) {
+ assert (0==**pp); /*overflow*/
+ }
+ }
+ if (all_zero) H5F_addr_undef (addr);
+}
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_addr_print
+ *
+ * Purpose: Print an address
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * Friday, November 7, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+H5F_addr_print (FILE *stream, const haddr_t *addr)
+{
+ haddr_t tmp;
+
+ assert (stream);
+ assert (addr);
+
+ if (H5F_addr_defined (addr)) {
+ /*
+ * It would be nice if we could use the `%Lu', `%llu', or `%qu', but
+ * we don't know which is supported. So we split the address into a
+ * low 4-bytes and a high 4-bytes. If the high 4-bytes are non-zero
+ * then we print the address in hexadecimal, otherwise we use decimal.
+ */
+ tmp = *addr;
+ tmp.offset >>= 32;
+ if (tmp.offset) {
+ fprintf (stream, "0x%08lx%08lx",
+ (unsigned long)(tmp.offset),
+ (unsigned long)(addr->offset & 0xffffffff));
+ } else {
+ fprintf (stream, "%lu", (unsigned long)(addr->offset));
+ }
+ } else {
+ fprintf (stream, "UNDEF");
+ }
+}
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_addr_pow2
+ *
+ * Purpose: Returns an address which is a power of two.
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * Friday, November 7, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+H5F_addr_pow2 (uintn n, haddr_t *addr/*out*/)
+{
+ assert (n>=0);
+ assert (addr);
+ assert (n<8*sizeof(addr->offset));
+
+ addr->offset = 1;
+ addr->offset <<= n;
+}
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_addr_inc
+ *
+ * Purpose: Increments an address by some number of bytes.
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * Friday, November 7, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+H5F_addr_inc (haddr_t *addr/*in,out*/, size_t inc)
+{
+ assert (addr && H5F_addr_defined (addr));
+ assert (addr->offset<=addr->offset+inc);
+ addr->offset += inc;
+}
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_addr_add
+ *
+ * Purpose: Adds two addresses and puts the result in the first argument.
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * Friday, November 7, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+H5F_addr_add (haddr_t *a1/*in,out*/, const haddr_t *a2)
+{
+ assert (a1 && H5F_addr_defined (a1));
+ assert (a2 && H5F_addr_defined (a2));
+ a1->offset += a2->offset;
+}
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_addr_hash
+ *
+ * Purpose: Computes a hash value of an address between 0 and MOD-1,
+ * inclusive.
+ *
+ * Return: Success: The hash value
+ *
+ * Failure: never fails
+ *
+ * Programmer: Robb Matzke
+ * Friday, November 7, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+uintn
+H5F_addr_hash (const haddr_t *addr, uintn mod)
+{
+ assert (addr && H5F_addr_defined (addr));
+ assert (mod>0);
+
+ return addr->offset % mod; /*ignore file number*/
+}
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
index 6eb6dd9..af994c3 100644
--- a/src/H5Fprivate.h
+++ b/src/H5Fprivate.h
@@ -33,6 +33,14 @@
# define H5F_OPT_SEEK 1
#endif
+/*
+ * Feature: Define this constant on the compiler command-line if you want to
+ * see some debugging messages on stderr.
+ */
+#ifdef NDEBUG
+# undef H5F_DEBUG
+#endif
+
/* Maximum size of boot-block buffer */
#define H5F_BOOTBLOCK_SIZE 1024
@@ -41,8 +49,8 @@
#define H5F_SIGNATURE_LEN 8
/* size of size_t and off_t as they exist on disk */
-#define H5F_SIZEOF_OFFSET(F) ((F)->shared->file_create_parms.offset_size)
-#define H5F_SIZEOF_SIZE(F) ((F)->shared->file_create_parms.length_size)
+#define H5F_SIZEOF_OFFSET(F) ((F)->shared->file_create_parms.sizeof_addr)
+#define H5F_SIZEOF_SIZE(F) ((F)->shared->file_create_parms.sizeof_size)
/*
* File open flags.
@@ -208,8 +216,8 @@ typedef struct {
uintn userblock_size; /* Size of the file user block in bytes */
uintn sym_leaf_k; /* 1/2 rank for symbol table leaf nodes */
uintn btree_k[8]; /* 1/2 rank for btree internal nodes */
- uint8 offset_size; /* Number of bytes for offsets */
- uint8 length_size; /* Number of bytes for lengths */
+ uint8 sizeof_addr; /* Number of bytes in an address */
+ uint8 sizeof_size; /* Number of bytes for obj sizes */
uint8 bootblock_ver; /* Version # of the bootblock */
uint8 smallobject_ver; /* Version # of the small-object heap */
uint8 freespace_ver; /* Version # of the free-space information */
@@ -240,28 +248,47 @@ typedef struct H5F_low_class_t {
hbool_t (*access)(const char*, int, H5F_search_t*);
struct H5F_low_t *(*open)(const char*, uintn, H5F_search_t*);
herr_t (*close)(struct H5F_low_t*);
- herr_t (*read)(struct H5F_low_t*, haddr_t, size_t, uint8*);
- herr_t (*write)(struct H5F_low_t*, haddr_t, size_t, const uint8*);
+ herr_t (*read)(struct H5F_low_t*, const haddr_t*, size_t, uint8*);
+ herr_t (*write)(struct H5F_low_t*, const haddr_t*, size_t, const uint8*);
herr_t (*flush)(struct H5F_low_t*);
- size_t (*size)(struct H5F_low_t*);
+ herr_t (*extend)(struct H5F_low_t*, intn, size_t, haddr_t*);
} H5F_low_class_t;
typedef struct H5F_low_t {
const H5F_low_class_t *type; /* What type of file is this? */
+ haddr_t eof; /* Address of logical end-of-file */
union {
+ /* File families */
+ struct {
+ char *name; /* Family name */
+ uintn flags; /* Flags for opening member files */
+ intn nmemb; /* Number of family members */
+ intn nalloc; /* Size of member table in elements */
+ struct H5F_low_t **memb;/* An array of family members */
+ size_t offset_bits;/* Number of bits in a member offset*/
+ } fam;
+
+ /* Split meta/raw data */
+ struct {
+ char *name; /* Base name w/o extension */
+ uint64 mask; /* Bit that determines which file to use*/
+ struct H5F_low_t *meta;/* Meta data file */
+ struct H5F_low_t *raw; /* Raw data file */
+ } split;
+
/* Posix section 2 I/O */
struct {
int fd; /* The unix file descriptor */
H5F_fileop_t op; /* Previous file operation */
- haddr_t cur; /* Current file position */
+ off_t cur; /* Current file position */
} sec2;
/* Posix stdio */
struct {
FILE *f; /* Posix stdio file */
H5F_fileop_t op; /* Previous file operation */
- haddr_t cur; /* Current file position */
+ off_t cur; /* Current file position */
} stdio;
/* In-core temp file */
@@ -281,7 +308,8 @@ typedef struct H5F_low_t {
extern const H5F_low_class_t H5F_LOW_SEC2[]; /* Posix section 2 */
extern const H5F_low_class_t H5F_LOW_STDIO[]; /* Posix stdio */
extern const H5F_low_class_t H5F_LOW_CORE[]; /* In-core temp file */
-
+extern const H5F_low_class_t H5F_LOW_FAM[]; /* File family */
+extern const H5F_low_class_t H5F_LOW_SPLIT[]; /* Split meta/raw data */
/*
* Define the structure to store the file information for HDF5 files. One of
@@ -290,12 +318,14 @@ extern const H5F_low_class_t H5F_LOW_CORE[]; /* In-core temp file */
typedef struct H5F_file_t {
H5F_search_t key; /* The key for looking up files */
uintn flags; /* Access Permissions for file */
- H5F_low_t *file_handle; /* Lower level file handle for I/O */
+ H5F_low_t *lf; /* Lower level file handle for I/O */
uintn nrefs; /* Ref count for times file is opened */
uint32 consist_flags; /* File Consistency Flags */
- haddr_t smallobj_off; /* Offset of small-obj heap within the file */
- haddr_t freespace_off; /* Offset of free-space info within the file */
- size_t logical_len; /* Logical length of file */
+ haddr_t boot_addr; /* Absolute address of boot block */
+ haddr_t base_addr; /* Absolute base address for rel.addrs. */
+ haddr_t smallobj_addr; /* Relative address of small-obj heap */
+ haddr_t freespace_addr; /* Relative address of free-space info */
+ haddr_t hdf5_eof; /* Relative addr of end of all hdf5 data*/
struct H5AC_t *cache; /* The object cache */
file_create_temp_t file_create_parms; /* File-creation template */
#ifdef LATER
@@ -322,17 +352,17 @@ typedef struct H5F_t {
#ifdef NOT_YET
-#define H5F_encode_offset(f,p,o) (H5F_SIZEOF_OFFSET(f)==4 ? UINT32ENCODE(p,o) \
+#define H5F_ENCODE_OFFSET(f,p,o) (H5F_SIZEOF_OFFSET(f)==4 ? UINT32ENCODE(p,o) \
: H5F_SIZEOF_OFFSET(f)==8 ? UINT64ENCODE(p,o) \
: H5F_SIZEOF_OFFSET(f)==2 ? UINT16ENCODE(p,o) \
: H5FPencode_unusual_offset(f,&(p),(uint8 *)&(o)))
#else /* NOT_YET */
-#define H5F_encode_offset(f,p,o) switch(H5F_SIZEOF_OFFSET(f)) { case 4: UINT32ENCODE(p,o); break;\
+#define H5F_ENCODE_OFFSET(f,p,o) switch(H5F_SIZEOF_OFFSET(f)) { case 4: UINT32ENCODE(p,o); break;\
case 8: UINT64ENCODE(p,o); break;\
case 2: UINT16ENCODE(p,o); break;}
#endif /* NOT_YET */
-#define H5F_decode_offset(f,p,o) \
+#define H5F_DECODE_OFFSET(f,p,o) \
switch (H5F_SIZEOF_OFFSET (f)) { \
case 4: \
UINT32DECODE (p, o); \
@@ -369,11 +399,10 @@ struct H5O_istore_t; /*forward decl for prototype arguments*/
/* Private functions, not part of the publicly documented API */
void H5F_encode_length_unusual(const H5F_t *f, uint8 **p, uint8 *l);
-void H5F_encode_offset_unusual(const H5F_t *f, uint8 **p, uint8 *o);
H5F_t *H5F_open (const H5F_low_class_t *type, const char *name, uintn flags,
const file_create_temp_t *create_parms);
herr_t H5F_close (H5F_t *f);
-herr_t H5F_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent,
+herr_t H5F_debug (H5F_t *f, const haddr_t *addr, FILE *stream, intn indent,
intn fwidth);
/* Functions that operate on indexed storage */
@@ -387,18 +416,43 @@ herr_t H5F_istore_write (H5F_t *f, const struct H5O_istore_t *mesg,
void *buf);
/* Functions that operate on contiguous storage wrt boot block */
-herr_t H5F_block_read (H5F_t *f, haddr_t addr, size_t size, void *buf);
-herr_t H5F_block_write (H5F_t *f, haddr_t addr, size_t size, void *buf);
+herr_t H5F_block_read (H5F_t *f, const haddr_t *addr, size_t size, void *buf);
+herr_t H5F_block_write (H5F_t *f, const haddr_t *addr, size_t size, void *buf);
/* Functions that operate directly on low-level files */
+herr_t H5F_low_extend (H5F_low_t *lf, intn op, size_t size, haddr_t *addr);
+herr_t H5F_low_seteof (H5F_low_t *lf, const haddr_t *addr);
hbool_t H5F_low_access (const H5F_low_class_t *type, const char *name,
int mode, H5F_search_t *key);
H5F_low_t *H5F_low_open (const H5F_low_class_t *type, const char *name,
uintn flags, H5F_search_t *key);
H5F_low_t *H5F_low_close (H5F_low_t *lf);
-size_t H5F_low_size (H5F_low_t *lf);
-herr_t H5F_low_read (H5F_low_t *lf, haddr_t addr, size_t size, uint8 *buf);
-herr_t H5F_low_write (H5F_low_t *lf, haddr_t addr, size_t size,
+size_t H5F_low_size (H5F_low_t *lf, haddr_t *addr);
+herr_t H5F_low_read (H5F_low_t *lf, const haddr_t *addr, size_t size,
+ uint8 *buf);
+herr_t H5F_low_write (H5F_low_t *lf, const haddr_t *addr, size_t size,
const uint8 *buf);
+herr_t H5F_low_flush (H5F_low_t *lf);
+
+
+/* Functions that operate on addresses */
+#define H5F_addr_eq(A1,A2) (H5F_addr_cmp(A1,A2)==0)
+#define H5F_addr_ne(A1,A2) (H5F_addr_cmp(A1,A2)!=0)
+#define H5F_addr_lt(A1,A2) (H5F_addr_cmp(A1,A2)<0)
+#define H5F_addr_le(A1,A2) (H5F_addr_cmp(A1,A2)<=0)
+#define H5F_addr_gt(A1,A2) (H5F_addr_cmp(A1,A2)>0)
+#define H5F_addr_ge(A1,A2) (H5F_addr_cmp(A1,A2)>=0)
+intn H5F_addr_cmp (const haddr_t*, const haddr_t*);
+hbool_t H5F_addr_defined (const haddr_t*);
+void H5F_addr_undef (haddr_t*);
+void H5F_addr_reset (haddr_t*);
+hbool_t H5F_addr_zerop (const haddr_t*);
+void H5F_addr_encode (H5F_t*, uint8**, const haddr_t*);
+void H5F_addr_decode (H5F_t*, const uint8**, haddr_t*);
+void H5F_addr_print (FILE*, const haddr_t*);
+void H5F_addr_pow2 (uintn, haddr_t*);
+void H5F_addr_inc (haddr_t*, size_t);
+void H5F_addr_add (haddr_t*, const haddr_t *);
+uintn H5F_addr_hash (const haddr_t*, uintn mod);
#endif
diff --git a/src/H5Fsec2.c b/src/H5Fsec2.c
index 5aa3e31..531bf10 100644
--- a/src/H5Fsec2.c
+++ b/src/H5Fsec2.c
@@ -28,22 +28,19 @@ static hbool_t interface_initialize_g = FALSE;
static H5F_low_t *H5F_sec2_open (const char *name, uintn flags, H5F_search_t*);
static herr_t H5F_sec2_close (H5F_low_t *lf);
-static herr_t H5F_sec2_read (H5F_low_t *lf, haddr_t addr, size_t size,
+static herr_t H5F_sec2_read (H5F_low_t *lf, const haddr_t *addr, size_t size,
uint8 *buf);
-static herr_t H5F_sec2_write (H5F_low_t *lf, haddr_t addr, size_t size,
+static herr_t H5F_sec2_write (H5F_low_t *lf, const haddr_t *addr, size_t size,
const uint8 *buf);
-static herr_t H5F_sec2_flush (H5F_low_t *lf);
-static size_t H5F_sec2_size (H5F_low_t *lf);
-
const H5F_low_class_t H5F_LOW_SEC2[1] = {{
- NULL, /* use default access(2) func */
+ NULL, /* access method */
H5F_sec2_open, /* open method */
H5F_sec2_close, /* close method */
H5F_sec2_read, /* read method */
H5F_sec2_write, /* write method */
- H5F_sec2_flush, /* flush method */
- H5F_sec2_size, /* file size method */
+ NULL, /* flush method */
+ NULL, /* extend method */
}};
@@ -69,7 +66,7 @@ const H5F_low_class_t H5F_LOW_SEC2[1] = {{
*-------------------------------------------------------------------------
*/
static H5F_low_t *
-H5F_sec2_open (const char *name, uintn flags, H5F_search_t *key)
+H5F_sec2_open (const char *name, uintn flags, H5F_search_t *key/*out*/)
{
uintn oflags;
H5F_low_t *lf = NULL;
@@ -91,9 +88,10 @@ H5F_sec2_open (const char *name, uintn flags, H5F_search_t *key)
lf->u.sec2.fd = fd;
lf->u.sec2.op = H5F_OP_SEEK;
lf->u.sec2.cur = 0;
+ fstat (fd, &sb);
+ lf->eof.offset = sb.st_size;
if (key) {
- fstat (fd, &sb);
key->dev = sb.st_dev;
key->ino = sb.st_ino;
}
@@ -101,7 +99,6 @@ H5F_sec2_open (const char *name, uintn flags, H5F_search_t *key)
FUNC_LEAVE (lf);
}
-
/*-------------------------------------------------------------------------
* Function: H5F_sec2_close
@@ -140,8 +137,8 @@ H5F_sec2_close (H5F_low_t *lf)
* Function: H5F_sec2_read
*
* Purpose: Reads SIZE bytes beginning at address ADDR in file LF and
- * places them in buffer BUF. Reading past the end of the
- * file returns zeros instead of failing.
+ * places them in buffer BUF. Reading past the logical or
+ * physical end of file returns zeros instead of failing.
*
* Errors:
* IO READERROR Read failed.
@@ -159,22 +156,46 @@ H5F_sec2_close (H5F_low_t *lf)
*-------------------------------------------------------------------------
*/
static herr_t
-H5F_sec2_read (H5F_low_t *lf, haddr_t addr, size_t size, uint8 *buf)
+H5F_sec2_read (H5F_low_t *lf, const haddr_t *addr, size_t size, uint8 *buf)
{
ssize_t n;
+ off_t offset;
FUNC_ENTER (H5F_sec2_read, NULL, FAIL);
+
+ /* Check for overflow */
+ offset = addr->offset;
+ assert ("address overflowed" && offset==addr->offset);
+ assert ("overflow" && offset+size>=offset);
+
+ /* Check easy cases */
+ if (0==size) HRETURN (SUCCEED);
+ if (offset>=lf->eof.offset) {
+ HDmemset (buf, 0, size);
+ HRETURN (SUCCEED);
+ }
+
/*
- * Optimize seeking. If that optimization is disabled then alwasy call
+ * Optimize seeking. If that optimization is disabled then always call
* lseek().
*/
if (!H5F_OPT_SEEK ||
- lf->u.sec2.op==H5F_OP_UNKNOWN || lf->u.sec2.cur!=addr) {
- if (lseek (lf->u.sec2.fd, addr, SEEK_SET)<0) {
+ lf->u.sec2.op==H5F_OP_UNKNOWN ||
+ lf->u.sec2.cur!=offset) {
+ if (lseek (lf->u.sec2.fd, offset, SEEK_SET)<0) {
HRETURN_ERROR (H5E_IO, H5E_SEEKERROR, FAIL); /*lseek failed*/
}
- lf->u.sec2.cur = addr;
+ lf->u.sec2.cur = offset;
+ }
+
+ /*
+ * Read zeros past the logical end of file (physical is handled below)
+ */
+ if ((size_t)offset+size>lf->eof.offset) {
+ size_t nbytes = (size_t)offset+size - lf->eof.offset;
+ HDmemset (buf+size-nbytes, 0, nbytes);
+ size -= nbytes;
}
/*
@@ -193,12 +214,12 @@ H5F_sec2_read (H5F_low_t *lf, haddr_t addr, size_t size, uint8 *buf)
* might be different than the number requested.
*/
lf->u.sec2.op = H5F_OP_READ;
- lf->u.sec2.cur = addr + n;
+ lf->u.sec2.cur = offset + n;
+ assert ("address overflowed" && lf->u.sec2.cur>=offset);
FUNC_LEAVE (SUCCEED);
}
-
/*-------------------------------------------------------------------------
* Function: H5F_sec2_write
@@ -222,24 +243,33 @@ H5F_sec2_read (H5F_low_t *lf, haddr_t addr, size_t size, uint8 *buf)
*-------------------------------------------------------------------------
*/
static herr_t
-H5F_sec2_write (H5F_low_t *lf, haddr_t addr, size_t size, const uint8 *buf)
+H5F_sec2_write (H5F_low_t *lf, const haddr_t *addr, size_t size,
+ const uint8 *buf)
{
+ off_t offset;
+
FUNC_ENTER (H5F_sec2_write, NULL, FAIL);
+ /* Check for overflow */
+ offset = addr->offset;
+ assert ("address overflowed" && offset==addr->offset);
+ assert ("overflow" && offset+size>=offset);
+
/*
* Optimize seeking. If that optimization is disabled then always call
* lseek().
*/
if (!H5F_OPT_SEEK ||
- lf->u.sec2.op==H5F_OP_UNKNOWN || lf->u.sec2.cur!=addr) {
- if (lseek (lf->u.sec2.fd, addr, SEEK_SET)<0) {
+ lf->u.sec2.op==H5F_OP_UNKNOWN ||
+ lf->u.sec2.cur!=offset) {
+ if (lseek (lf->u.sec2.fd, offset, SEEK_SET)<0) {
HRETURN_ERROR (H5E_IO, H5E_SEEKERROR, FAIL); /*lseek failed*/
}
- lf->u.sec2.cur = addr;
+ lf->u.sec2.cur = offset;
}
/*
- * Read the data from the file. If the write failed then set the
+ * Write the data to the file. If the write failed then set the
* operation back to UNKNOWN since Posix doesn't gurantee its value.
*/
if (size != write (lf->u.sec2.fd, buf, size)) {
@@ -251,76 +281,8 @@ H5F_sec2_write (H5F_low_t *lf, haddr_t addr, size_t size, const uint8 *buf)
* Update the file position.
*/
lf->u.sec2.op = H5F_OP_WRITE;
- lf->u.sec2.cur = addr + size;
- FUNC_LEAVE (SUCCEED);
-}
-
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_sec2_flush
- *
- * Purpose: Makes sure that all data is on disk.
- *
- * Errors:
- *
- * Return: Success: SUCCEED
- *
- * Failure: FAIL
- *
- * Programmer: Robb Matzke
- * Wednesday, October 22, 1997
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5F_sec2_flush (H5F_low_t *lf)
-{
- FUNC_ENTER (H5F_sec2_flush, NULL, FAIL);
-
- /* Not necessary with this driver */
+ lf->u.sec2.cur = offset + size;
+ assert ("address overflowed" && lf->u.sec2.cur>=offset);
FUNC_LEAVE (SUCCEED);
}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_sec2_size
- *
- * Purpose: Returns the current size of the file in bytes.
- *
- * Bugs: There is no way to determine if this function failed.
- *
- * Errors:
- * IO SEEKERROR Lseek failed.
- *
- * Return: Success: Size of file in bytes
- *
- * Failure: 0
- *
- * Programmer: Robb Matzke
- * Wednesday, October 22, 1997
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static size_t
-H5F_sec2_size (H5F_low_t *lf)
-{
- off_t size;
-
- FUNC_ENTER (H5F_sec2_size, NULL, 0);
-
- if ((size=lseek (lf->u.sec2.fd, 0, SEEK_END))<0) {
- lf->u.sec2.op = H5F_OP_UNKNOWN;
- HRETURN_ERROR (H5E_IO, H5E_SEEKERROR, 0); /*lseek failed*/
- }
-
- lf->u.sec2.op = H5F_OP_SEEK;
- lf->u.sec2.cur = size;
-
- FUNC_LEAVE (size);
-}
diff --git a/src/H5Fstdio.c b/src/H5Fstdio.c
index cc8f4c6..2cd613b 100644
--- a/src/H5Fstdio.c
+++ b/src/H5Fstdio.c
@@ -23,13 +23,11 @@ static hbool_t interface_initialize_g = FALSE;
static H5F_low_t *H5F_stdio_open (const char *name, uintn flags,
H5F_search_t *key);
static herr_t H5F_stdio_close (H5F_low_t *lf);
-static herr_t H5F_stdio_read (H5F_low_t *lf, haddr_t addr, size_t size,
+static herr_t H5F_stdio_read (H5F_low_t *lf, const haddr_t *addr, size_t size,
uint8 *buf);
-static herr_t H5F_stdio_write (H5F_low_t *lf, haddr_t addr, size_t size,
+static herr_t H5F_stdio_write (H5F_low_t *lf, const haddr_t *addr, size_t size,
const uint8 *buf);
static herr_t H5F_stdio_flush (H5F_low_t *lf);
-static size_t H5F_stdio_size (H5F_low_t *lf);
-
const H5F_low_class_t H5F_LOW_STDIO[1] = {{
NULL, /* use default access(2) func */
@@ -38,10 +36,9 @@ const H5F_low_class_t H5F_LOW_STDIO[1] = {{
H5F_stdio_read, /* read method */
H5F_stdio_write, /* write method */
H5F_stdio_flush, /* flush method */
- H5F_stdio_size, /* file size method */
+ NULL, /* extend method */
}};
-
/*-------------------------------------------------------------------------
* Function: H5F_stdio_open
@@ -70,7 +67,7 @@ const H5F_low_class_t H5F_LOW_STDIO[1] = {{
*-------------------------------------------------------------------------
*/
static H5F_low_t *
-H5F_stdio_open (const char *name, uintn flags, H5F_search_t *key)
+H5F_stdio_open (const char *name, uintn flags, H5F_search_t *key/*out*/)
{
H5F_low_t *lf=NULL;
FILE *f=NULL;
@@ -104,6 +101,12 @@ H5F_stdio_open (const char *name, uintn flags, H5F_search_t *key)
lf->u.stdio.f = f;
lf->u.stdio.op = H5F_OP_SEEK;
lf->u.stdio.cur = 0;
+ H5F_addr_reset (&(lf->eof));
+ if (fseek (lf->u.stdio.f, 0, SEEK_END)<=0) {
+ lf->u.stdio.op = H5F_OP_UNKNOWN;
+ } else {
+ H5F_addr_inc (&(lf->eof), ftell (lf->u.stdio.f));
+ }
/* The unique key */
if (key) {
@@ -153,8 +156,8 @@ H5F_stdio_close (H5F_low_t *lf)
* Function: H5F_stdio_read
*
* Purpose: Reads SIZE bytes beginning at address ADDR in file LF and
- * places them in buffer BUF. Reading past the end of the
- * file returns zeros instead of failing.
+ * places them in buffer BUF. Reading past the logical or
+ * physical end of file returns zeros instead of failing.
*
* Errors:
* IO READERROR Fread failed.
@@ -172,22 +175,44 @@ H5F_stdio_close (H5F_low_t *lf)
*-------------------------------------------------------------------------
*/
static herr_t
-H5F_stdio_read (H5F_low_t *lf, haddr_t addr, size_t size, uint8 *buf)
+H5F_stdio_read (H5F_low_t *lf, const haddr_t *addr, size_t size, uint8 *buf)
{
size_t n;
+ off_t offset;
FUNC_ENTER (H5F_stdio_read, NULL, FAIL);
+ /* Check for overflow */
+ offset = addr->offset;
+ assert ("address overflowed" && offset==addr->offset);
+ assert ("overflow" && offset+size>=offset);
+
+ /* Check easy cases */
+ if (0==size) HRETURN (SUCCEED);
+ if (offset>=lf->eof.offset) {
+ HDmemset (buf, 0, size);
+ HRETURN (SUCCEED);
+ }
+
/*
* Seek to the correct file position.
*/
if (!H5F_OPT_SEEK ||
lf->u.stdio.op!=H5F_OP_READ ||
- lf->u.stdio.cur!=addr) {
- if (fseek (lf->u.stdio.f, addr, SEEK_SET)<0) {
+ lf->u.stdio.cur!=offset) {
+ if (fseek (lf->u.stdio.f, offset, SEEK_SET)<0) {
HRETURN_ERROR (H5E_IO, H5E_SEEKERROR, FAIL); /*fseek failed*/
}
- lf->u.stdio.cur = addr;
+ lf->u.stdio.cur = offset;
+ }
+
+ /*
+ * Read zeros past the logical end of file (physical is handled below)
+ */
+ if ((size_t)offset+size>lf->eof.offset) {
+ size_t nbytes = (size_t)offset+size - lf->eof.offset;
+ HDmemset (buf+size-nbytes, 0, nbytes);
+ size -= nbytes;
}
/*
@@ -207,11 +232,10 @@ H5F_stdio_read (H5F_low_t *lf, haddr_t addr, size_t size, uint8 *buf)
* Update the file position data.
*/
lf->u.stdio.op = H5F_OP_READ;
- lf->u.stdio.cur = addr + n;
+ lf->u.stdio.cur = offset + n;
FUNC_LEAVE (SUCCEED);
}
-
/*-------------------------------------------------------------------------
* Function: H5F_stdio_write
@@ -235,22 +259,28 @@ 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)
+H5F_stdio_write (H5F_low_t *lf, const haddr_t *addr, size_t size,
+ const uint8 *buf)
{
- int status;
+ off_t offset;
FUNC_ENTER (H5F_stdio_write, NULL, FAIL);
+ /* Check for overflow */
+ offset = addr->offset;
+ assert ("address overflowed" && offset==addr->offset);
+ assert ("overflow" && offset+size>=offset);
+
/*
* Seek to the correct file position.
*/
if (!H5F_OPT_SEEK ||
lf->u.stdio.op!=H5F_OP_WRITE ||
- lf->u.stdio.cur!=addr) {
- if (fseek (lf->u.stdio.f, addr, SEEK_SET)<0) {
+ lf->u.stdio.cur!=offset) {
+ if (fseek (lf->u.stdio.f, offset, SEEK_SET)<0) {
HRETURN_ERROR (H5E_IO, H5E_SEEKERROR, FAIL); /*fseek failed*/
}
- lf->u.stdio.cur = addr;
+ lf->u.stdio.cur = offset;
}
/*
@@ -258,8 +288,7 @@ 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.
*/
- status = fwrite (buf, 1, size, lf->u.stdio.f);
- if (size != status) {
+ if (size != fwrite (buf, 1, size, lf->u.stdio.f)) {
lf->u.stdio.op = H5F_OP_UNKNOWN;
HRETURN_ERROR (H5E_IO, H5E_WRITEERROR, FAIL); /*fwrite failed*/
}
@@ -268,11 +297,10 @@ H5F_stdio_write (H5F_low_t *lf, haddr_t addr, size_t size, const uint8 *buf)
* Update seek optimizing data.
*/
lf->u.stdio.op = H5F_OP_WRITE;
- lf->u.stdio.cur = addr + size;
+ lf->u.stdio.cur = offset + size;
FUNC_LEAVE (SUCCEED);
}
-
/*-------------------------------------------------------------------------
* Function: H5F_stdio_flush
@@ -313,46 +341,3 @@ H5F_stdio_flush (H5F_low_t *lf)
FUNC_LEAVE (SUCCEED);
}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_stdio_size
- *
- * Purpose: Returns the current size of the file in bytes.
- *
- * Bugs: There is no way to determine if this function failed.
- *
- * Errors:
- * IO SEEKERROR Fseek failed.
- *
- * Return: Success: Size of file in bytes
- *
- * Failure: 0
- *
- * Programmer: Robb Matzke
- * Wednesday, October 22, 1997
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static size_t
-H5F_stdio_size (H5F_low_t *lf)
-{
- off_t size;
-
- FUNC_ENTER (H5F_stdio_size, NULL, 0);
-
- /* Seek to the end and get the file offset */
- if (fseek (lf->u.stdio.f, 0, SEEK_END)<0) {
- HRETURN_ERROR (H5E_IO, H5E_SEEKERROR, 0); /*fseek failed*/
- }
- size = ftell (lf->u.stdio.f);
-
- /* Update seek opt data */
- lf->u.stdio.op = H5F_OP_SEEK;
- lf->u.stdio.cur = size;
-
- FUNC_LEAVE (size);
-}
-
diff --git a/src/H5G.c b/src/H5G.c
index c251b14..5c1e2cd 100644
--- a/src/H5G.c
+++ b/src/H5G.c
@@ -426,13 +426,15 @@ H5G_basename (const char *name, size_t *size_p)
*
* As a special case, if the NAME is the name `/' (or
* equivalent) then GRP_ENT is initialized to all zero
- * and a pointer to the root symbol table entry is returned.
+ * and an invalid header address and a pointer to the root
+ * symbol table entry is returned.
*
* As a special case, if the NAME is the string `/foo' (or
* equivalent) and the root symbol table entry points to a
* non-group object with a name message with the value
- * `foo' then GRP_ENT is initialized to all zero and a pointer
- * to the root symbol table entry is returned.
+ * `foo' then GRP_ENT is initialized to all zero (except for an
+ * invalid header address) and a pointer to the root symbol
+ * table entry is returned.
*
* Errors:
* SYM COMPLEN Component is too long.
@@ -459,7 +461,7 @@ H5G_basename (const char *name, size_t *size_p)
*/
static H5G_entry_t *
H5G_namei (H5F_t *f, H5G_entry_t *cwg, const char *name,
- const char **rest, H5G_entry_t *grp_ent)
+ const char **rest/*out*/, H5G_entry_t *grp_ent/*out*/)
{
H5G_entry_t grp; /*entry for current group */
size_t nchars; /*component name length */
@@ -469,7 +471,10 @@ H5G_namei (H5F_t *f, H5G_entry_t *cwg, const char *name,
/* clear output args before FUNC_ENTER() in case it fails */
if (rest) *rest = name;
- if (grp_ent) memset (grp_ent, 0, sizeof(H5G_entry_t));
+ if (grp_ent) {
+ memset (grp_ent, 0, sizeof(H5G_entry_t));
+ H5F_addr_undef (&(grp_ent->header));
+ }
FUNC_ENTER (H5G_namei, NULL, NULL);
@@ -481,7 +486,7 @@ H5G_namei (H5F_t *f, H5G_entry_t *cwg, const char *name,
/* starting point */
if ('/'==*name) {
- if (f->shared->root_sym->header<=0) {
+ if (!H5F_addr_defined (&(f->shared->root_sym->header))) {
/* No root group */
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL);
}
@@ -528,8 +533,11 @@ H5G_namei (H5F_t *f, H5G_entry_t *cwg, const char *name,
* the name `foo'.
*/
H5O_name_t mesg={0};
- if (!aside && grp.header==f->shared->root_sym->header &&
- H5O_read (f, grp.header, &grp, H5O_NAME, 0, &mesg) &&
+ if (!aside &&
+ H5F_addr_defined (&(grp.header)) &&
+ H5F_addr_defined (&(f->shared->root_sym->header)) &&
+ H5F_addr_eq (&(grp.header), &(f->shared->root_sym->header)) &&
+ H5O_read (f, &(grp.header), &grp, H5O_NAME, 0, &mesg) &&
!HDstrcmp (mesg.s, comp)) {
H5O_reset (H5O_NAME, &mesg);
ret_value = f->shared->root_sym;
@@ -549,15 +557,16 @@ H5G_namei (H5F_t *f, H5G_entry_t *cwg, const char *name,
/* output parameters */
if (rest) *rest = name; /*final null*/
if (grp_ent) {
- if (ret_value->header == f->shared->root_sym->header) {
+ if (H5F_addr_eq (&(ret_value->header), &(f->shared->root_sym->header))) {
HDmemset (grp_ent, 0, sizeof(H5G_entry_t)); /*root has no parent*/
+ H5F_addr_undef (&(grp_ent->header));
} else {
*grp_ent = grp;
}
}
/* Perhaps the root object doesn't even exist! */
- if (ret_value->header<=0) {
+ if (!H5F_addr_defined (&(ret_value->header))) {
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL); /*root not found*/
}
@@ -627,7 +636,7 @@ H5G_mkroot (H5F_t *f, size_t size_hint)
* re-inserted back into the group directed graph. We might leak file
* memory, but at least we don't loose the original root object.
*/
- if (f->shared->root_sym->header>0) {
+ if (H5F_addr_defined (&(f->shared->root_sym->header))) {
if (H5O_read (f, NO_ADDR, f->shared->root_sym, H5O_STAB, 0, &stab)) {
/* root group already exists */
HGOTO_ERROR (H5E_SYM, H5E_EXISTS, -2);
@@ -1093,10 +1102,10 @@ H5G_create (H5F_t *f, const char *name, size_t ohdr_hint)
* doesn't have a name or we shouldn't interfere with the name
* it already has as a message.
*/
- if (f->shared->root_sym->header>0) {
+ if (H5F_addr_defined (&(f->shared->root_sym->header))) {
HRETURN_ERROR (H5E_SYM, H5E_EXISTS, NULL); /*root exists*/
}
- if ((ent.header = H5O_new (f, 0, ohdr_hint))<0) {
+ if (H5O_new (f, 0, ohdr_hint, &(ent.header)/*out*/)<0) {
/* can't create header */
HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL);
}
@@ -1104,7 +1113,7 @@ H5G_create (H5F_t *f, const char *name, size_t ohdr_hint)
HRETURN_ERROR (H5E_SYM, H5E_LINK, NULL); /*bad link count*/
}
*(f->shared->root_sym) = ent;
- if (NULL==(ret_value=H5G_shadow_open (f, &grp, f->shared->root_sym))) {
+ if (NULL==(ret_value=H5G_shadow_open (f, NULL, f->shared->root_sym))) {
HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL);
}
HRETURN (ret_value);
@@ -1132,12 +1141,12 @@ H5G_create (H5F_t *f, const char *name, size_t ohdr_hint)
/*
* Create the object header.
*/
- if ((ent.header = H5O_new (f, 0, ohdr_hint))<0) {
+ if (H5O_new (f, 0, ohdr_hint, &(ent.header)/*out*/)<0) {
HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL);
}
- if (f->shared->root_sym->header<=0) {
+ if (!H5F_addr_defined (&(f->shared->root_sym->header))) {
/*
* This will be the only object in the file. Insert it as the root
* object and add a name messaage to the object header (or modify
@@ -1163,7 +1172,8 @@ H5G_create (H5F_t *f, const char *name, size_t ohdr_hint)
* Make sure the root group exists. Ignore the failure if it's
* because the group already exists.
*/
- hbool_t update_grp = (grp.header==f->shared->root_sym->header);
+ hbool_t update_grp = H5F_addr_eq (&(grp.header),
+ &(f->shared->root_sym->header));
herr_t status = H5G_mkroot (f, H5G_SIZE_HINT);
if (status<0 && -2!=status) {
/* Can't create root group */
@@ -1240,7 +1250,7 @@ H5G_open (H5F_t *f, const char *name)
cwg = H5G_getcwg (f);
assert (cwg || '/'==*name);
- if (f->shared->root_sym->header<=0) {
+ if (!H5F_addr_defined (&(f->shared->root_sym->header))) {
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL); /*object not found*/
}
if (NULL==(ent=H5G_namei (f, cwg, name, NULL, &grp))) {
@@ -1329,7 +1339,8 @@ H5G_close (H5F_t *f, H5G_entry_t *ent)
*-------------------------------------------------------------------------
*/
herr_t
-H5G_find (H5F_t *f, const char *name, H5G_entry_t *grp_ent, H5G_entry_t *ent)
+H5G_find (H5F_t *f, const char *name,
+ H5G_entry_t *grp_ent/*out*/, H5G_entry_t *ent/*out*/)
{
H5G_entry_t *ent_p = NULL;
H5G_entry_t *cwg = NULL;
@@ -1342,7 +1353,7 @@ H5G_find (H5F_t *f, const char *name, H5G_entry_t *grp_ent, H5G_entry_t *ent)
cwg = H5G_getcwg (f);
assert (cwg || '/'==*name);
- if (f->shared->root_sym->header<=0) {
+ if (!H5F_addr_defined (&(f->shared->root_sym->header))) {
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); /*object not found*/
}
diff --git a/src/H5Gent.c b/src/H5Gent.c
index b5cddce..e7da78b 100644
--- a/src/H5Gent.c
+++ b/src/H5Gent.c
@@ -36,7 +36,11 @@ static hbool_t interface_initialize_g = FALSE;
H5G_entry_t *
H5G_ent_calloc (void)
{
- return H5MM_xcalloc (1, sizeof(H5G_entry_t));
+ H5G_entry_t *ent;
+
+ ent = H5MM_xcalloc (1, sizeof(H5G_entry_t));
+ H5F_addr_undef (&(ent->header));
+ return ent;
}
@@ -78,7 +82,8 @@ H5G_ent_invalidate (H5G_entry_t *ent)
* Purpose: Returns the header address associated with a symbol table
* entry.
*
- * Return: Success: Address
+ * Return: Success: SUCCED with the address returned in the ADDR
+ * argument.
*
* Failure: FAIL
*
@@ -89,13 +94,15 @@ H5G_ent_invalidate (H5G_entry_t *ent)
*
*-------------------------------------------------------------------------
*/
-haddr_t
-H5G_ent_addr (H5G_entry_t *ent)
+herr_t
+H5G_ent_addr (H5G_entry_t *ent, haddr_t *addr/*out*/)
{
FUNC_ENTER (H5G_ent_addr, NULL, FAIL);
+
assert (ent);
+ *addr = ent->header;
- FUNC_LEAVE (ent->header);
+ FUNC_LEAVE (SUCCEED);
}
@@ -186,7 +193,7 @@ H5G_ent_modified (H5G_entry_t *ent, H5G_type_t cache_type)
*-------------------------------------------------------------------------
*/
herr_t
-H5G_ent_decode_vec (H5F_t *f, uint8 **pp, H5G_entry_t *ent, intn n)
+H5G_ent_decode_vec (H5F_t *f, const uint8 **pp, H5G_entry_t *ent, intn n)
{
intn i;
@@ -230,9 +237,9 @@ H5G_ent_decode_vec (H5F_t *f, uint8 **pp, H5G_entry_t *ent, intn n)
*-------------------------------------------------------------------------
*/
herr_t
-H5G_ent_decode (H5F_t *f, uint8 **pp, H5G_entry_t *ent)
+H5G_ent_decode (H5F_t *f, const uint8 **pp, H5G_entry_t *ent)
{
- uint8 *p_ret = *pp;
+ const uint8 *p_ret = *pp;
FUNC_ENTER (H5G_ent_decode, NULL, FAIL);
@@ -242,8 +249,8 @@ H5G_ent_decode (H5F_t *f, uint8 **pp, H5G_entry_t *ent)
assert (ent);
/* decode header */
- H5F_decode_offset (f, *pp, ent->name_off);
- H5F_decode_offset (f, *pp, ent->header);
+ H5F_decode_length (f, *pp, ent->name_off);
+ H5F_addr_decode (f, pp, &(ent->header));
UINT32DECODE (*pp, ent->type);
/* decode scratch-pad */
@@ -252,6 +259,7 @@ H5G_ent_decode (H5F_t *f, uint8 **pp, H5G_entry_t *ent)
break;
case H5G_CACHED_SDATA:
+ assert (1+1+2+(5*4) <= H5G_SIZEOF_SCRATCH);
ent->cache.sdata.nt.length= *(*pp)++;
ent->cache.sdata.nt.arch= *(*pp)++;
UINT16DECODE (*pp, ent->cache.sdata.nt.type);
@@ -263,8 +271,9 @@ H5G_ent_decode (H5F_t *f, uint8 **pp, H5G_entry_t *ent)
break;
case H5G_CACHED_STAB:
- UINT32DECODE (*pp, ent->cache.stab.btree_addr);
- UINT32DECODE (*pp, ent->cache.stab.heap_addr);
+ assert (2*H5F_SIZEOF_OFFSET (f) <= H5G_SIZEOF_SCRATCH);
+ H5F_addr_decode (f, pp, &(ent->cache.stab.btree_addr));
+ H5F_addr_decode (f, pp, &(ent->cache.stab.heap_addr));
break;
default:
@@ -361,8 +370,8 @@ H5G_ent_encode (H5F_t *f, uint8 **pp, H5G_entry_t *ent)
assert (ent);
/* encode header */
- H5F_encode_offset (f, *pp, ent->name_off);
- H5F_encode_offset (f, *pp, ent->header);
+ H5F_encode_length (f, *pp, ent->name_off);
+ H5F_addr_encode (f, pp, &(ent->header));
UINT32ENCODE (*pp, ent->type);
/* encode scratch-pad */
@@ -371,6 +380,7 @@ H5G_ent_encode (H5F_t *f, uint8 **pp, H5G_entry_t *ent)
break;
case H5G_CACHED_SDATA:
+ assert (1+1+2+(5*4) <= H5G_SIZEOF_SCRATCH);
*(*pp)++= ent->cache.sdata.nt.length;
*(*pp)++= ent->cache.sdata.nt.arch;
UINT16ENCODE (*pp, ent->cache.sdata.nt.type);
@@ -382,8 +392,9 @@ H5G_ent_encode (H5F_t *f, uint8 **pp, H5G_entry_t *ent)
break;
case H5G_CACHED_STAB:
- UINT32ENCODE (*pp, ent->cache.stab.btree_addr);
- UINT32ENCODE (*pp, ent->cache.stab.heap_addr);
+ assert (2*H5F_SIZEOF_OFFSET (f) <= H5G_SIZEOF_SCRATCH);
+ H5F_addr_encode (f, pp, &(ent->cache.stab.btree_addr));
+ H5F_addr_encode (f, pp, &(ent->cache.stab.heap_addr));
break;
default:
@@ -429,9 +440,12 @@ H5G_ent_debug (H5F_t *f, H5G_entry_t *ent, FILE *stream, intn indent,
fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth,
"Name offset into private heap:",
(unsigned long)(ent->name_off));
- fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth,
- "Object header address:",
- (unsigned long)(ent->header));
+
+ fprintf (stream, "%*s%-*s ", indent, "", fwidth,
+ "Object header address:");
+ H5F_addr_print (stream, &(ent->header));
+ fprintf (stream, "\n");
+
fprintf (stream, "%*s%-*s %s\n", indent, "", fwidth,
"Dirty:",
ent->dirty ? "Yes" : "No");
@@ -471,12 +485,16 @@ H5G_ent_debug (H5F_t *f, H5G_entry_t *ent, FILE *stream, intn indent,
case H5G_CACHED_STAB:
fprintf (stream, "Symbol Table\n");
- fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth,
- "B-tree address:",
- (unsigned long)(ent->cache.stab.btree_addr));
- fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth,
- "Heap address:",
- (unsigned long)(ent->cache.stab.heap_addr));
+
+ fprintf (stream, "%*s%-*s ", indent, "", fwidth,
+ "B-tree address:");
+ H5F_addr_print (stream, &(ent->cache.stab.btree_addr));
+ fprintf (stream, "\n");
+
+ fprintf (stream, "%*s%-*s ", indent, "", fwidth,
+ "Heap address:");
+ H5F_addr_print (stream, &(ent->cache.stab.heap_addr));
+ fprintf (stream, "\n");
break;
default:
diff --git a/src/H5Gnode.c b/src/H5Gnode.c
index f578783..1ec6daf 100644
--- a/src/H5Gnode.c
+++ b/src/H5Gnode.c
@@ -44,31 +44,32 @@ 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, 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,
+static herr_t H5G_node_new (H5F_t *f, H5B_ins_t op, void *_lt_key,
+ void *_udata, void *_rt_key, haddr_t *addr/*out*/);
+static herr_t H5G_node_flush (H5F_t *f, hbool_t destroy, const haddr_t *addr,
H5G_node_t *sym);
-static H5G_node_t *H5G_node_load (H5F_t *f, haddr_t addr, const void *_udata1,
- void *_udata2);
+static H5G_node_t *H5G_node_load (H5F_t *f, const haddr_t *addr,
+ const void *_udata1, void *_udata2);
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,
+static herr_t H5G_node_found (H5F_t *f, const haddr_t *addr,
const void *_lt_key, void *_udata,
const void *_rt_key);
-static haddr_t H5G_node_insert (H5F_t *f, haddr_t addr, H5B_ins_t *anchor,
- void *_lt_key, hbool_t *lt_key_changed,
- void *_md_key, void *_udata,
- void *_rt_key, hbool_t *rt_key_changed);
-static herr_t H5G_node_list (H5F_t *f, haddr_t addr, void *_udata);
+static H5B_ins_t H5G_node_insert (H5F_t *f, const haddr_t *addr,
+ void *_lt_key, hbool_t *lt_key_changed,
+ void *_md_key, void *_udata,
+ void *_rt_key, hbool_t *rt_key_changed,
+ haddr_t *new_node/*out*/);
+static herr_t H5G_node_list (H5F_t *f, const haddr_t *addr, void *_udata);
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] = {{
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,
+ (void*(*)(H5F_t*,const haddr_t*,const void*,void*))H5G_node_load,
+ (herr_t(*)(H5F_t*,hbool_t,const haddr_t*,void*))H5G_node_flush,
}};
/* H5G inherits B-tree like properties from H5B */
@@ -113,7 +114,7 @@ static intn interface_initialize_g = FALSE;
static size_t
H5G_node_sizeof_rkey (H5F_t *f, const void *udata __attribute__((unused)))
{
- return H5F_SIZEOF_OFFSET(f);
+ return H5F_SIZEOF_SIZE(f); /*the name offset*/
}
@@ -145,7 +146,7 @@ H5G_node_decode_key (H5F_t *f, H5B_t *bt, uint8 *raw, void *_key)
assert (raw);
assert (key);
- H5F_decode_offset (f, raw, key->offset);
+ H5F_decode_length (f, raw, key->offset);
FUNC_LEAVE (SUCCEED);
}
@@ -179,7 +180,7 @@ H5G_node_encode_key (H5F_t *f, H5B_t *bt, uint8 *raw, void *_key)
assert (raw);
assert (key);
- H5F_encode_offset (f, raw, key->offset);
+ H5F_encode_length (f, raw, key->offset);
FUNC_LEAVE (SUCCEED);
}
@@ -218,7 +219,8 @@ H5G_node_size (H5F_t *f)
* also called internally to split a symbol node with
* LT_KEY and RT_KEY null pointers.
*
- * Return: Success: Address of symbol table node.
+ * Return: Success: SUCCEED. The address of symbol table node is
+ * returned through the ADDR argument.
*
* Failure: FAIL
*
@@ -230,15 +232,15 @@ H5G_node_size (H5F_t *f)
*
*-------------------------------------------------------------------------
*/
-static haddr_t
+static herr_t
H5G_node_new (H5F_t *f, H5B_ins_t op,
- void *_lt_key, void *_udata, void *_rt_key)
+ void *_lt_key, void *_udata, void *_rt_key,
+ haddr_t *addr/*out*/)
{
H5G_node_key_t *lt_key = (H5G_node_key_t*)_lt_key;
H5G_node_key_t *rt_key = (H5G_node_key_t*)_rt_key;
H5G_node_t *sym = NULL;
size_t size = 0;
- haddr_t addr;
FUNC_ENTER (H5G_node_new, NULL, FAIL);
@@ -250,7 +252,7 @@ H5G_node_new (H5F_t *f, H5B_ins_t op,
sym = H5MM_xcalloc (1, sizeof(H5G_node_t));
size = H5G_node_size (f);
- if ((addr = H5MF_alloc (f, size))<0) {
+ if (H5MF_alloc (f, H5MF_META, size, addr/*out*/)<0) {
H5MM_xfree (sym);
HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL);
}
@@ -272,7 +274,7 @@ H5G_node_new (H5F_t *f, H5B_ins_t op,
if (lt_key) lt_key->offset = 0;
if (rt_key) rt_key->offset = 0;
- FUNC_LEAVE (addr);
+ FUNC_LEAVE (SUCCEED);
}
@@ -297,7 +299,8 @@ H5G_node_new (H5F_t *f, H5B_ins_t op,
*-------------------------------------------------------------------------
*/
static herr_t
-H5G_node_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5G_node_t *sym)
+H5G_node_flush (H5F_t *f, hbool_t destroy, const haddr_t *addr,
+ H5G_node_t *sym)
{
uint8 *buf=NULL, *p=NULL;
size_t size;
@@ -310,7 +313,7 @@ H5G_node_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5G_node_t *sym)
* Check arguments.
*/
assert (f);
- assert (addr>=0);
+ assert (addr && H5F_addr_defined (addr));
assert (sym);
/*
@@ -389,11 +392,13 @@ 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, const void *_udata1, void *_udata2)
+H5G_node_load (H5F_t *f, const haddr_t *addr, const void *_udata1,
+ void *_udata2)
{
H5G_node_t *sym = NULL;
size_t size = 0;
- uint8 *buf = NULL, *p = NULL;
+ uint8 *buf = NULL;
+ const uint8 *p = NULL;
const H5G_ac_ud1_t *ac_udata = (const H5G_ac_ud1_t*)_udata1;
H5G_node_t *ret_value = NULL; /*for error handling*/
@@ -403,7 +408,7 @@ H5G_node_load (H5F_t *f, haddr_t addr, const void *_udata1, void *_udata2)
* Check arguments.
*/
assert (f);
- assert (addr>=0);
+ assert (addr && H5F_addr_defined (addr));
assert (ac_udata);
assert (NULL==_udata2);
@@ -411,7 +416,7 @@ H5G_node_load (H5F_t *f, haddr_t addr, const void *_udata1, void *_udata2)
* Initialize variables.
*/
size = H5G_node_size (f);
- buf = p = H5MM_xmalloc (size);
+ p = buf = H5MM_xmalloc (size);
sym = H5MM_xcalloc (1, sizeof(H5G_node_t));
sym->entry = H5MM_xcalloc (2*H5G_NODE_K(f), sizeof(H5G_entry_t));
@@ -500,10 +505,10 @@ H5G_node_cmp2 (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key)
assert (lt_key);
assert (rt_key);
- if (NULL==(s1=H5H_peek (f, udata->heap_addr, lt_key->offset))) {
+ 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))) {
+ if (NULL==(s2=H5H_peek (f, &(udata->heap_addr), rt_key->offset))) {
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL);
}
@@ -551,13 +556,13 @@ H5G_node_cmp3 (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key)
FUNC_ENTER (H5G_node_cmp3, NULL, FAIL);
/* left side */
- if (NULL==(s=H5H_peek (f, udata->heap_addr, lt_key->offset))) {
+ if (NULL==(s=H5H_peek (f, &(udata->heap_addr), lt_key->offset))) {
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL);
}
if (HDstrcmp (udata->name, s)<=0) HRETURN (-1);
/* right side */
- if (NULL==(s=H5H_peek (f, udata->heap_addr, rt_key->offset))) {
+ if (NULL==(s=H5H_peek (f, &(udata->heap_addr), rt_key->offset))) {
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL);
}
if (HDstrcmp (udata->name, s)>0) HRETURN(1);
@@ -595,7 +600,7 @@ 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,
+H5G_node_found (H5F_t *f, const haddr_t *addr, const void *_lt_key,
void *_udata, const void *_rt_key)
{
H5G_bt_ud1_t *bt_udata = (H5G_bt_ud1_t *)_udata;
@@ -611,7 +616,7 @@ H5G_node_found (H5F_t *f, haddr_t addr, const void *_lt_key,
* Check arguments.
*/
assert (f);
- assert (addr>=0);
+ assert (addr && H5F_addr_defined (addr));
assert (bt_udata);
ac_udata.grp_addr = bt_udata->grp_addr;
@@ -630,7 +635,7 @@ H5G_node_found (H5F_t *f, haddr_t addr, const void *_lt_key,
rt = sn->nsyms;
while (lt<rt && cmp) {
idx = (lt + rt) / 2;
- if (NULL==(s=H5H_peek (f, bt_udata->heap_addr,
+ if (NULL==(s=H5H_peek (f, &(bt_udata->heap_addr),
sn->entry[idx].name_off))) {
HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL);
}
@@ -652,7 +657,7 @@ H5G_node_found (H5F_t *f, haddr_t addr, const void *_lt_key,
*/
H5G_shadow_sync (sn->entry+idx);
bt_udata->entry_ptr = sn->entry+idx;
- bt_udata->node_addr = addr;
+ bt_udata->node_addr = *addr;
bt_udata->node_ptr = sn;
break;
@@ -696,15 +701,15 @@ done:
* If the new key is larger than RIGHT then update RIGHT
* with the new key.
*
- * Return: Success: Address of new node if the node was
- * split. MID has been initialized with
- * the high key of the left node, RIGHT
- * has the high key of the right node.
+ * Return: Success: An insertion command for the caller, one of
+ * the H5B_INS_* constants. The address of the
+ * new node, if any, is returned through the
+ * NEW_NODE argument. NEW_NODE might not be
+ * initialized if the return value is
+ * H5B_INS_NOOP.
*
- * Zero if the node didn't split. RIGHT has the
- * high key of the right node.
- *
- * Failure: -1
+ * Failure: H5B_INS_ERROR, NEW_NODE might not be
+ * initialized.
*
* Programmer: Robb Matzke
* matzke@llnl.gov
@@ -718,11 +723,12 @@ done:
*
*-------------------------------------------------------------------------
*/
-static haddr_t
-H5G_node_insert (H5F_t *f, haddr_t addr, H5B_ins_t *anchor,
+static H5B_ins_t
+H5G_node_insert (H5F_t *f, const haddr_t *addr,
void *_lt_key, hbool_t *lt_key_changed,
void *_md_key, void *_udata,
- void *_rt_key, hbool_t *rt_key_changed)
+ void *_rt_key, hbool_t *rt_key_changed,
+ haddr_t *new_node)
{
H5G_node_key_t *md_key = (H5G_node_key_t *)_md_key;
H5G_node_key_t *rt_key = (H5G_node_key_t *)_rt_key;
@@ -730,28 +736,30 @@ H5G_node_insert (H5F_t *f, haddr_t addr, H5B_ins_t *anchor,
H5G_ac_ud1_t ac_udata;
H5G_node_t *sn=NULL, *snrt=NULL;
- haddr_t new_node=0, offset;
+ size_t offset; /*offset of name in heap*/
const char *s;
intn idx=-1, cmp=1;
intn lt=0, rt; /*binary search cntrs */
intn i;
- haddr_t ret_value = FAIL;
+ H5B_ins_t ret_value = H5B_INS_ERROR;
H5G_shadow_t *shadow = NULL;
H5G_node_t *insert_into=NULL; /*node that gets new entry*/
- haddr_t insert_addr=-1; /*address of that node */
+ haddr_t insert_addr; /*address of that node */
- FUNC_ENTER (H5G_node_insert, NULL, FAIL);
+ FUNC_ENTER (H5G_node_insert, NULL, H5B_INS_ERROR);
/*
* Check arguments.
*/
assert (f);
- assert (addr>=0);
- assert (anchor);
+ assert (addr && H5F_addr_defined (addr));
assert (md_key);
assert (rt_key);
assert (bt_udata);
- bt_udata->node_addr = -1;
+ assert (new_node);
+
+ /* Init return value */
+ H5F_addr_undef (&(bt_udata->node_addr));
bt_udata->node_ptr = NULL;
bt_udata->entry_ptr = NULL;
@@ -761,7 +769,7 @@ H5G_node_insert (H5F_t *f, haddr_t addr, H5B_ins_t *anchor,
ac_udata.grp_addr = bt_udata->grp_addr;
ac_udata.heap_addr = bt_udata->heap_addr;
if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, &ac_udata, NULL))) {
- HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL);
+ HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR);
}
/*
@@ -770,12 +778,13 @@ H5G_node_insert (H5F_t *f, haddr_t addr, H5B_ins_t *anchor,
rt = sn->nsyms;
while (lt<rt) {
idx = (lt + rt) / 2;
- if (NULL==(s=H5H_peek (f, bt_udata->heap_addr,
+ if (NULL==(s=H5H_peek (f, &(bt_udata->heap_addr),
sn->entry[idx].name_off))) {
- HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL);
+ HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, H5B_INS_ERROR);
}
if (0==(cmp=HDstrcmp (bt_udata->name, s))) {
- HGOTO_ERROR (H5E_SYM, H5E_CANTINSERT, FAIL); /*already present*/
+ /*already present*/
+ HGOTO_ERROR (H5E_SYM, H5E_CANTINSERT, H5B_INS_ERROR);
}
if (cmp<0) {
rt = idx;
@@ -790,10 +799,10 @@ H5G_node_insert (H5F_t *f, haddr_t addr, H5B_ins_t *anchor,
* heap address changed and update the symbol table object header
* with the new heap address.
*/
- offset = H5H_insert (f, bt_udata->heap_addr, HDstrlen(bt_udata->name)+1,
+ offset = H5H_insert (f, &(bt_udata->heap_addr), HDstrlen(bt_udata->name)+1,
bt_udata->name);
bt_udata->entry.name_off = offset;
- if (offset<0) HGOTO_ERROR (H5E_SYM, H5E_CANTINSERT, FAIL);
+ if (offset<=0) HGOTO_ERROR (H5E_SYM, H5E_CANTINSERT, H5B_INS_ERROR);
if (sn->nsyms>=2*H5G_NODE_K(f)) {
/*
@@ -801,14 +810,15 @@ H5G_node_insert (H5F_t *f, haddr_t addr, H5B_ins_t *anchor,
* node and return the address of the new right node (the
* left node is at the same address as the original node).
*/
- *anchor = H5B_INS_RIGHT;
+ ret_value = H5B_INS_RIGHT;
/* The right node */
- if ((new_node = H5G_node_new (f, H5B_INS_FIRST, NULL, NULL, NULL))<0) {
- HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL);
+ if (H5G_node_new (f, H5B_INS_FIRST, NULL, NULL, NULL,
+ new_node/*out*/)<0) {
+ HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, H5B_INS_ERROR);
}
if (NULL==(snrt=H5AC_find (f, H5AC_SNODE, new_node, &ac_udata, NULL))) {
- HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL);
+ HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR);
}
HDmemcpy (snrt->entry, sn->entry + H5G_NODE_K(f),
H5G_NODE_K(f) * sizeof(H5G_entry_t));
@@ -834,26 +844,24 @@ H5G_node_insert (H5F_t *f, haddr_t addr, H5B_ins_t *anchor,
/* Where to insert the new entry? */
if (idx<=H5G_NODE_K(f)) {
insert_into = sn;
- insert_addr = addr;
+ insert_addr = *addr;
if (idx==H5G_NODE_K(f)) md_key->offset = offset;
} else {
idx -= H5G_NODE_K (f);
insert_into = snrt;
- insert_addr = new_node;
+ insert_addr = *new_node;
}
- ret_value = new_node;
} else {
/* Where to insert the new entry? */
- *anchor = H5B_INS_NOOP;
+ ret_value = H5B_INS_NOOP;
sn->dirty = TRUE;
insert_into = sn;
- insert_addr = addr;
+ insert_addr = *addr;
if (idx==sn->nsyms) {
rt_key->offset = offset;
*rt_key_changed = TRUE;
}
- ret_value = 0;
}
/* Adjust shadows */
@@ -866,7 +874,7 @@ H5G_node_insert (H5F_t *f, haddr_t addr, H5B_ins_t *anchor,
H5G_shadow_move (f, bt_udata->entry.shadow,
bt_udata->name,
insert_into->entry + idx,
- bt_udata->grp_addr);
+ &(bt_udata->grp_addr));
}
/* Move entries */
@@ -887,16 +895,16 @@ done:
if (ret_value<0) {
/* failing... */
if (sn && H5AC_unprotect (f, H5AC_SNODE, addr, sn)<0) {
- HRETURN_ERROR (H5E_SYM, H5E_PROTECT, FAIL);
+ HRETURN_ERROR (H5E_SYM, H5E_PROTECT, H5B_INS_ERROR);
}
} else if (insert_into!=sn) {
/* unprotect the first node and protect the return value */
if (H5AC_unprotect (f, H5AC_SNODE, addr, sn)<0) {
- HRETURN_ERROR (H5E_SYM, H5E_PROTECT, FAIL);
+ HRETURN_ERROR (H5E_SYM, H5E_PROTECT, H5B_INS_ERROR);
}
- if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, insert_addr, &ac_udata,
+ if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, &insert_addr, &ac_udata,
NULL))) {
- HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL);
+ HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR);
}
bt_udata->node_ptr = sn;
bt_udata->entry_ptr = sn->entry + idx;
@@ -927,7 +935,7 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5G_node_list (H5F_t *f, haddr_t addr, void *_udata)
+H5G_node_list (H5F_t *f, const haddr_t *addr, void *_udata)
{
H5G_bt_ud2_t *bt_udata = (H5G_bt_ud2_t *)_udata;
H5G_node_t *sn = NULL;
@@ -942,7 +950,7 @@ H5G_node_list (H5F_t *f, haddr_t addr, void *_udata)
* Check arguments.
*/
assert (f);
- assert (addr>=0);
+ assert (addr && H5F_addr_defined (addr));
assert (bt_udata);
ac_udata.grp_addr = bt_udata->grp_addr;
@@ -972,7 +980,7 @@ H5G_node_list (H5F_t *f, haddr_t addr, void *_udata)
}
if (bt_udata->name) {
for (i=0; i<sn->nsyms && bt_udata->nsyms+i<bt_udata->maxentries; i++) {
- if (NULL==(s=H5H_peek (f, bt_udata->heap_addr,
+ if (NULL==(s=H5H_peek (f, &(bt_udata->heap_addr),
sn->entry[i].name_off))) {
HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL);
}
@@ -1013,8 +1021,8 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5G_node_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent,
- intn fwidth, haddr_t heap)
+H5G_node_debug (H5F_t *f, const haddr_t *addr, FILE *stream, intn indent,
+ intn fwidth, const haddr_t *heap)
{
int i, acc;
H5G_node_t *sn = NULL;
@@ -1028,7 +1036,7 @@ H5G_node_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent,
* Check arguments.
*/
assert (f);
- assert (addr>=0);
+ assert (addr && H5F_addr_defined (addr));
assert (stream);
assert (indent>=0);
assert (fwidth>=0);
@@ -1042,8 +1050,8 @@ H5G_node_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent,
* cache when we're done so if some later caller knows the header address
* they'll be able to access the open objects.
*/
- ac_udata.grp_addr = -1;
- ac_udata.heap_addr = heap;
+ H5F_addr_undef (&(ac_udata.grp_addr));
+ ac_udata.heap_addr = *heap;
/*
* If we couldn't load the symbol table node, then try loading the
@@ -1075,7 +1083,8 @@ H5G_node_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent,
fwidth = MAX (0, fwidth-3);
for (i=0; i<sn->nsyms; i++) {
fprintf (stream, "%*sSymbol %d:\n", indent-3, "", i);
- if (heap>0 && (s = H5H_peek (f, heap, sn->entry[i].name_off))) {
+ if (H5F_addr_defined (heap) &&
+ (s = H5H_peek (f, heap, sn->entry[i].name_off))) {
fprintf (stream, "%*s%-*s `%s'\n", indent, "", fwidth,
"Name:",
s);
diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h
index 0e5db33..89152c2 100644
--- a/src/H5Gpkg.h
+++ b/src/H5Gpkg.h
@@ -33,7 +33,7 @@
*/
struct H5G_entry_t {
hbool_t dirty; /*entry out-of-date? */
- off_t name_off; /*offset of name within name heap */
+ size_t name_off; /*offset of name within name heap */
haddr_t header; /*file address of object header */
H5G_type_t type; /*type of information cached */
H5G_cache_t cache; /*cached data from object header */
@@ -74,7 +74,7 @@ struct H5G_shadow_t {
* nodes consists of this structure...
*/
typedef struct H5G_node_key_t {
- off_t offset; /*offset into heap for name */
+ size_t offset; /*offset into heap for name */
} H5G_node_key_t;
/*
@@ -158,8 +158,8 @@ extern const H5AC_class_t H5AC_SNODE[1];
* functions that understand names are exported to the rest of
* the library and appear in H5Gprivate.h.
*/
-haddr_t H5G_stab_new (H5F_t *f, H5G_entry_t *self, size_t init);
-H5G_entry_t *H5G_stab_find (H5F_t *f, haddr_t addr, H5G_entry_t *self,
+herr_t H5G_stab_new (H5F_t *f, H5G_entry_t *self, size_t init);
+H5G_entry_t *H5G_stab_find (H5F_t *f, const haddr_t *addr, H5G_entry_t *self,
const char *name);
H5G_entry_t *H5G_stab_insert (H5F_t *f, H5G_entry_t *self,
const char *name, H5G_entry_t *ent);
@@ -177,15 +177,16 @@ 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,
const H5G_ac_ud1_t *ac_udata);
-H5G_shadow_t *H5G_shadow_list (H5F_t *f, haddr_t stab_header_addr);
+H5G_shadow_t *H5G_shadow_list (H5F_t *f, const 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,
- haddr_t grp_addr);
+ const haddr_t *grp_addr);
/*
* Functions that understand symbol table entries.
*/
-herr_t H5G_ent_decode_vec (H5F_t *f, uint8 **pp, H5G_entry_t *ent, intn n);
+herr_t H5G_ent_decode_vec (H5F_t *f, const uint8 **pp, H5G_entry_t *ent,
+ intn n);
herr_t H5G_ent_encode_vec (H5F_t *f, uint8 **pp, H5G_entry_t *ent, intn n);
#endif
diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h
index 4641d90..b15ea0e 100644
--- a/src/H5Gprivate.h
+++ b/src/H5Gprivate.h
@@ -23,6 +23,17 @@
#include <H5Bprivate.h>
#include <H5Fprivate.h>
+/*
+ * FEATURE: If this macro is defined then H5G_shadow_check() is occassionally
+ * (actually, quite often) called to check the consistency of the
+ * shadow table. If there's something wrong with the table then
+ * abort() is called. Shadow table checking is a rather expensive
+ * operation.
+ */
+#ifdef NDEBUG
+# undef H5G_DEBUG
+#endif
+
#define H5G_NODE_MAGIC "SNOD" /*symbol table node magic number */
#define H5G_NODE_SIZEOF_MAGIC 4 /*sizeof symbol node magic number */
#define H5G_NO_CHANGE (-1) /*see H5G_ent_modified() */
@@ -31,11 +42,12 @@
/*
* The disk size for a symbol table entry...
*/
+#define H5G_SIZEOF_SCRATCH 24
#define H5G_SIZEOF_ENTRY(F) \
- (H5F_SIZEOF_OFFSET(F) + /*offset of name into heap */ \
+ (H5F_SIZEOF_SIZE(F) + /*offset of name into heap */ \
H5F_SIZEOF_OFFSET(F) + /*address of object header */ \
4 + /*entry type */ \
- 24) /*scratch pad space */
+ H5G_SIZEOF_SCRATCH) /*scratch pad space */
/*
* Various types of object header information can be cached in a symbol
@@ -92,13 +104,13 @@ herr_t H5G_close (H5F_t *f, H5G_entry_t *ent);
herr_t H5G_find (H5F_t *f, const char *name, H5G_entry_t *grp_ent,
H5G_entry_t *ent);
herr_t H5G_ent_encode (H5F_t *f, uint8 **pp, H5G_entry_t *ent);
-herr_t H5G_ent_decode (H5F_t *f, uint8 **pp, H5G_entry_t *ent);
+herr_t H5G_ent_decode (H5F_t *f, const uint8 **pp, H5G_entry_t *ent);
/*
* These functions operate on symbol table nodes.
*/
-herr_t H5G_node_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent,
- intn fwidth, haddr_t heap);
+herr_t H5G_node_debug (H5F_t *f, const haddr_t *addr, FILE *stream,
+ intn indent, intn fwidth, const haddr_t *heap);
/*
* These functions operate on shadow entries.
@@ -112,7 +124,7 @@ herr_t H5G_shadow_flush (H5F_t *f, hbool_t invalidate);
*/
H5G_entry_t *H5G_ent_calloc (void);
herr_t H5G_ent_invalidate (H5G_entry_t *ent);
-haddr_t H5G_ent_addr (H5G_entry_t *ent);
+herr_t H5G_ent_addr (H5G_entry_t *ent, haddr_t *retval/*out*/);
H5G_cache_t *H5G_ent_cache (H5G_entry_t *ent, H5G_type_t *cache_type);
herr_t H5G_ent_modified (H5G_entry_t *ent, H5G_type_t cache_type);
herr_t H5G_ent_debug (H5F_t *f, H5G_entry_t *ent, FILE *stream,
diff --git a/src/H5Gshad.c b/src/H5Gshad.c
index 253e01e..5636585 100644
--- a/src/H5Gshad.c
+++ b/src/H5Gshad.c
@@ -14,15 +14,6 @@
#include <H5MMprivate.h> /*memory management */
#include <H5Oprivate.h> /*object header messages */
-/*
- * FEATURE: If this macro is defined then H5G_shadow_check() is occassionally
- * (actually, quite often) called to check the consistency of the
- * shadow table. If there's something wrong with the table then
- * abort() is called. Shadow table checking is a rather expensive
- * operation.
- */
-/* #define H5G_DEBUG_SHADOWS */
-
#define PABLO_MASK H5G_shadow_mask
/* Is the interface initialized? */
@@ -51,8 +42,8 @@ typedef struct H5G_hash_t {
*
*-------------------------------------------------------------------------
*/
-#ifdef H5G_DEBUG_SHADOWS
-void
+#ifdef H5G_DEBUG
+static void
H5G_shadow_check (H5F_t *f)
{
H5G_hash_t *hash=NULL;
@@ -62,10 +53,12 @@ H5G_shadow_check (H5F_t *f)
uintn nerrors=0;
static int ncalls=0;
- ncalls++;
+ if (0==ncalls++) {
+ fprintf (stderr, "HDF5-DIAG: debugging group shadows (expensive)\n");
+ }
- for (idx=0; idx<f->nshadows; idx++) {
- for (hash=f->shadow[idx]; hash; hash=hash->next) {
+ for (idx=0; idx<f->shared->nshadows; idx++) {
+ for (hash=f->shared->shadow[idx]; hash; hash=hash->next) {
for (shadow=hash->head,prev_shadow=NULL;
shadow;
shadow=shadow->next) {
@@ -81,15 +74,42 @@ H5G_shadow_check (H5F_t *f)
shadow_error = TRUE;
}
- /* Valid group addresses */
- if (shadow->grp_addr<0 || (shadow->grp_addr==0 && idx!=0)) {
- fprintf (stderr, "grp_addr=%lu, ",
- (unsigned long)(shadow->grp_addr));
+ /*
+ * Valid group addresses. The root (which is hashed to entry
+ * zero) always has an undefined group address.
+ */
+ if (idx==0 &&
+ !H5F_addr_defined (&(shadow->grp_addr)) &&
+ !H5F_addr_defined (&(hash->grp_addr))) {
+ /*
+ * The shadow for the root object always has an undefined
+ * group address.
+ */
+
+ } else if (!H5F_addr_defined (&(shadow->grp_addr)) ||
+ !H5F_addr_defined (&(hash->grp_addr))) {
+ /*
+ * Non-root objects must have defined group addresses.
+ */
+ fprintf (stderr, "grp_addr=");
+ H5F_addr_print (stderr, &(shadow->grp_addr));
+ fprintf (stderr, ", hash_addr=");
+ H5F_addr_print (stderr, &(hash->grp_addr));
+ fprintf (stderr, ", ");
+ shadow_error = TRUE;
+
+ } else if (H5F_addr_ne (&(shadow->grp_addr), &(hash->grp_addr))) {
+ /*
+ * Something's wrong with the data structure. The hash
+ * address should always be the same as the shadow group
+ * address.
+ */
+ fprintf (stderr, "grp_addr=");
+ H5F_addr_print (stderr, &(shadow->grp_addr));
+ fprintf (stderr, " (should be ");
+ H5F_addr_print (stderr, &(hash->grp_addr));
+ fprintf (stderr, "), ");
shadow_error = TRUE;
- } else if (shadow->grp_addr!=hash->grp_addr) {
- fprintf (stderr, "grp_addr=%lu (not %lu), ",
- (unsigned long)(shadow->grp_addr),
- (unsigned long)(hash->grp_addr));
}
/* Linked to symbol table entry */
@@ -107,9 +127,10 @@ H5G_shadow_check (H5F_t *f)
/* If an error occurred then print other info */
if (shadow_error) {
- fprintf (stderr, "idx=%u, shadow=0x%08lx, grp_addr=%lu\n",
- idx, (unsigned long)shadow,
- (unsigned long)(shadow->grp_addr));
+ fprintf (stderr, "idx=%u, shadow=0x%08lx, grp_addr=",
+ idx, (unsigned long)shadow);
+ H5F_addr_print (stderr, &(shadow->grp_addr));
+ fprintf (stderr, "\n");
nerrors++;
}
}
@@ -261,16 +282,20 @@ H5G_shadow_sync (H5G_entry_t *ent)
*-------------------------------------------------------------------------
*/
H5G_shadow_t *
-H5G_shadow_list (H5F_t *f, haddr_t grp_addr)
+H5G_shadow_list (H5F_t *f, const haddr_t *grp_addr)
{
- uintn idx = grp_addr % f->shared->nshadows;
+ uintn idx = H5F_addr_hash (grp_addr, f->shared->nshadows);
H5G_hash_t *bucket = NULL;
FUNC_ENTER (H5G_shadows, NULL, NULL);
for (bucket=f->shared->shadow[idx]; bucket; bucket=bucket->next) {
- if (bucket->grp_addr==grp_addr) {
- HRETURN (bucket->head);
+ if (0==idx &&
+ !H5F_addr_defined (&(bucket->grp_addr)) &&
+ !H5F_addr_defined (grp_addr)) {
+ HRETURN (bucket->head);/*shadow list for root object*/
+ } else if (H5F_addr_eq (&(bucket->grp_addr), grp_addr)) {
+ HRETURN (bucket->head);/*shadow list for other objects*/
}
}
FUNC_LEAVE (NULL);
@@ -313,17 +338,17 @@ H5G_shadow_assoc_node (H5F_t *f, H5G_node_t *sym, const H5G_ac_ud1_t *ac_udata)
assert (sym); /* The symbol table node */
assert (ac_udata); /* The symbol table header info */
-#ifdef H5G_DEBUG_SHADOWS
+#ifdef H5G_DEBUG
H5G_shadow_check (f);
#endif
- if ((shadow=H5G_shadow_list (f, ac_udata->grp_addr))) {
+ if ((shadow=H5G_shadow_list (f, &(ac_udata->grp_addr)))) {
heap_addr = ac_udata->heap_addr;
while (i<sym->nsyms && shadow) {
/* Advance the Entry ptr until it gets to the next shadow. */
while (i<sym->nsyms &&
- (s=H5H_peek (f, heap_addr, sym->entry[i].name_off)) &&
+ (s=H5H_peek (f, &heap_addr, sym->entry[i].name_off)) &&
strcmp (s, shadow->name)<0) i++;
/* Advance the Shadow ptr until it gets to the next entry. */
@@ -352,7 +377,9 @@ H5G_shadow_assoc_node (H5F_t *f, H5G_node_t *sym, const H5G_ac_ud1_t *ac_udata)
* object, open the object (again) and return a handle
* to it.
*
- * GRP can be the null pointer if `ent' is the root entry.
+ * If ENT refers to the root object, then GRP can be a null
+ * pointer or a pointer to an entry with an invalid header
+ * address.
*
* Return: Success: Handle to open object
*
@@ -376,24 +403,35 @@ H5G_shadow_open (H5F_t *f, H5G_entry_t *grp, H5G_entry_t *ent)
uintn idx;
H5O_name_t name_mesg = {NULL};
H5G_entry_t *ret_value = NULL;
- haddr_t grp_addr;
+ haddr_t grp_header;
FUNC_ENTER (H5G_shadow_open, NULL, NULL);
/* check args */
assert (f);
- assert (ent==f->shared->root_sym || grp);
assert (ent);
- grp_addr = grp ? grp->header : 0;
if ((shadow = ent->shadow)) {
- /*
- * Object is already open. Open it again.
- */
+ /* Object is already open. Open it again */
shadow->nrefs += 1;
HRETURN (&(shadow->entry));
}
+ /*
+ * If the root object is being opened then the GRP argument is optional.
+ * If it's supplied then it had better have an undefined header address.
+ * For all other objects the GRP argument is required to have a valid
+ * header address.
+ */
+ if (ent==f->shared->root_sym) {
+ assert (!grp || !H5F_addr_defined (&(grp->header)));
+ H5F_addr_undef (&grp_header);
+ idx = 0;
+ } else {
+ assert (grp && H5F_addr_defined (&(grp->header)));
+ grp_header = grp->header;
+ idx = H5F_addr_hash (&grp_header, f->shared->nshadows);
+ }
/*
* Build the new shadow.
@@ -404,15 +442,16 @@ H5G_shadow_open (H5F_t *f, H5G_entry_t *grp, H5G_entry_t *ent)
shadow->nrefs = 1;
shadow->entry = *ent;
shadow->entry.dirty = FALSE;
- shadow->grp_addr = grp_addr;
+ shadow->grp_addr = grp_header;
/*
* 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) {
+ if (ent==f->shared->root_sym) {
/*
- * We're opening the root entry.
+ * We're opening the root entry. Get the name from the name message or
+ * use a generic default.
*/
if (H5O_read (f, NO_ADDR, ent, H5O_NAME, 0, &name_mesg)) {
shadow->name = H5MM_xstrdup (name_mesg.s);
@@ -428,7 +467,7 @@ H5G_shadow_open (H5F_t *f, H5G_entry_t *grp, H5G_entry_t *ent)
if (NULL==H5O_read (f, NO_ADDR, grp, H5O_STAB, 0, &stab)) {
HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, NULL);
}
- if (NULL==(s=H5H_peek (f, stab.heap_addr, ent->name_off))) {
+ if (NULL==(s=H5H_peek (f, &(stab.heap_addr), ent->name_off))) {
HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, NULL);
}
shadow->name = H5MM_xstrdup (s);
@@ -439,13 +478,18 @@ H5G_shadow_open (H5F_t *f, H5G_entry_t *grp, H5G_entry_t *ent)
/*
* Link it into the shadow heap
*/
- idx = grp_addr % f->shared->nshadows;
for (hash=f->shared->shadow[idx]; hash; hash=hash->next) {
- if (hash->grp_addr==grp_addr) break;
+ if (0==idx &&
+ !H5F_addr_defined (&(hash->grp_addr)) &&
+ !H5F_addr_defined (&grp_header)) {
+ break; /*shadow list for root object*/
+ } else if (H5F_addr_eq (&(hash->grp_addr), &grp_header)) {
+ break; /*shadow list for other objects*/
+ }
}
if (!hash) {
hash = H5MM_xcalloc (1, sizeof(H5G_hash_t));
- hash->grp_addr = grp_addr;
+ hash->grp_addr = grp_header;
hash->next = f->shared->shadow[idx];
f->shared->shadow[idx] = hash;
if (hash->next) hash->next->prev = hash;
@@ -477,7 +521,7 @@ H5G_shadow_open (H5F_t *f, H5G_entry_t *grp, H5G_entry_t *ent)
hash->head = shadow;
}
-#ifdef H5G_DEBUG_SHADOWS
+#ifdef H5G_DEBUG
H5G_shadow_check (f);
#endif
@@ -530,7 +574,7 @@ H5G_shadow_close (H5F_t *f, H5G_entry_t *ent)
/* clean the shadow */
if (1==shadow->nrefs && ent->dirty) {
if (!shadow->main &&
- NULL==H5G_stab_find (f, shadow->grp_addr, NULL, shadow->name)) {
+ NULL==H5G_stab_find (f, &(shadow->grp_addr), NULL, shadow->name)) {
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL);
}
assert (shadow->main);
@@ -545,10 +589,24 @@ H5G_shadow_close (H5F_t *f, H5G_entry_t *ent)
/* dissociate shadow and entry */
H5G_shadow_dissociate (ent);
- /* find symtabs shadow list */
- idx = shadow->grp_addr % f->shared->nshadows;
+ /*
+ * find symtabs shadow list -- if this is a shadow of the root object
+ * then use zero for the hash value. The root object always has an
+ * undefined group address.
+ */
+ if (H5F_addr_defined (&(shadow->grp_addr))) {
+ idx = H5F_addr_hash (&(shadow->grp_addr), f->shared->nshadows);
+ } else {
+ idx = 0;
+ }
for (hash=f->shared->shadow[idx]; hash; hash=hash->next) {
- if (hash->grp_addr==shadow->grp_addr) break;
+ if (0==idx &&
+ !H5F_addr_defined (&(hash->grp_addr)) &&
+ !H5F_addr_defined (&(shadow->grp_addr))) {
+ break; /*shadow list for root object*/
+ } else if (H5F_addr_eq (&(hash->grp_addr), &(shadow->grp_addr))) {
+ break; /*shadow list for other objects*/
+ }
}
assert (hash);
@@ -599,7 +657,7 @@ H5G_shadow_close (H5F_t *f, H5G_entry_t *ent)
*/
herr_t
H5G_shadow_move (H5F_t *f, H5G_shadow_t *shadow, const char *new_name,
- H5G_entry_t *new_entry, haddr_t grp_addr)
+ H5G_entry_t *new_entry, const haddr_t *grp_addr)
{
H5G_hash_t *hash;
uintn idx;
@@ -608,29 +666,29 @@ H5G_shadow_move (H5F_t *f, H5G_shadow_t *shadow, const char *new_name,
assert (shadow);
assert (new_entry);
- assert (grp_addr>0);
+ assert (grp_addr && H5F_addr_defined (grp_addr));
- if (0==shadow->grp_addr) {
+ if (!H5F_addr_defined (&(shadow->grp_addr))) {
/*
* We're moving the shadow for the root object. This simplifies things
* greatly since it implies that this is the only shadow currently
* defined for the entire file.
*/
- idx = grp_addr % f->shared->nshadows;
+ idx = H5F_addr_hash (grp_addr, f->shared->nshadows);
assert (NULL==f->shared->shadow[idx]); /*Nothing at new idx... */
hash = f->shared->shadow[0];
assert (hash); /*..but root idx has something. */
- assert (0==hash->grp_addr); /*..and it's the root something */
+ assert (!H5F_addr_defined (&(hash->grp_addr)));/*..it's the root obj*/
assert (NULL==hash->next); /*..and just that */
assert (hash->head==shadow); /*..and exactly that */
/* Move root entry to new hash bucket */
f->shared->shadow[idx] = hash;
f->shared->shadow[0] = NULL;
- hash->grp_addr = grp_addr;
+ hash->grp_addr = *grp_addr;
/* Associate SHADOW with NEW_ENTRY */
- shadow->grp_addr = grp_addr;
+ shadow->grp_addr = *grp_addr;
shadow->main = new_entry;
new_entry->shadow = shadow;
@@ -642,7 +700,7 @@ H5G_shadow_move (H5F_t *f, H5G_shadow_t *shadow, const char *new_name,
/*
* Other shadows never move.
*/
- assert (shadow->grp_addr==grp_addr);
+ assert (H5F_addr_eq (&(shadow->grp_addr), grp_addr));
shadow->main = new_entry;
new_entry->shadow = shadow;
}
@@ -687,30 +745,41 @@ H5G_shadow_flush (H5F_t *f, hbool_t invalidate)
* symbol table node.
*/
if (shadow->entry.dirty) {
- if (!shadow->main &&
- NULL==H5G_stab_find (f, shadow->grp_addr, NULL,
- shadow->name)) {
- HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL);
+ if (0==idx && !H5F_addr_defined (&(shadow->grp_addr)) &&
+ shadow->main==f->shared->root_sym) {
+ /*
+ * The shadow for the root entry gets copied back into the
+ * root symbol
+ */
+ *f->shared->root_sym = shadow->entry;
+ } else {
+ /*
+ * Other shadows get copied back into the symbol table.
+ */
+ if (!shadow->main &&
+ NULL==H5G_stab_find (f, &(shadow->grp_addr), NULL,
+ shadow->name)) {
+ HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL);
+ }
+ assert (shadow->main);
+ *(shadow->main) = shadow->entry;
+ shadow->entry.dirty = FALSE;
+ nfound++;
}
- assert (shadow->main);
- *(shadow->main) = shadow->entry;
- shadow->entry.dirty = FALSE;
- nfound++;
-
}
#ifndef NDEBUG
/*
* This is usually a bad thing--an hdf5 programmer forgot to close
* some object before closing the file. Since this is hard to
* debug, we'll be nice and print the names here. We don't know
- * the full name, but we'll print the file address (relative to
- * the boot block) of the object header for the group that
- * contains the open object.
+ * the full name, but we'll print the relative file address
+ * of the object header for the group that contains the open
+ * object.
*/
if (invalidate) {
- fprintf (stderr, "Warning: open object <%lu>/%s",
- (unsigned long)(shadow->grp_addr),
- shadow->name);
+ fprintf (stderr, "HDF5-DIAG: warning: open object <");
+ H5F_addr_print (stderr, &(shadow->grp_addr));
+ fprintf (stderr, ">/%s", shadow->name);
if (shadow->nrefs>1) {
fprintf (stderr, " (%d times)", shadow->nrefs);
}
diff --git a/src/H5Gstab.c b/src/H5Gstab.c
index 46f1eeb..4e16a2c 100644
--- a/src/H5Gstab.c
+++ b/src/H5Gstab.c
@@ -41,10 +41,7 @@ static hbool_t interface_initialize_g = FALSE;
* SYM CANTINIT Can't create message.
* SYM CANTINIT Can't initialize heap.
*
- * Return: Success: Address of new symbol table header. If
- * the caller supplies a symbol table entry
- * SELF then it will be initialized to point to
- * this symbol table.
+ * Return: Success: SUCCEED
*
* Failure: FAIL
*
@@ -56,10 +53,10 @@ static hbool_t interface_initialize_g = FALSE;
*
*-------------------------------------------------------------------------
*/
-haddr_t
+herr_t
H5G_stab_new (H5F_t *f, H5G_entry_t *self, size_t init)
{
- off_t name; /*offset of "" name */
+ size_t name; /*offset of "" name */
haddr_t addr; /*object header address */
H5O_stab_t stab; /*symbol table message */
@@ -69,13 +66,14 @@ H5G_stab_new (H5F_t *f, H5G_entry_t *self, size_t init)
* Check arguments.
*/
assert (f);
+ assert (self);
init = MAX(init, H5H_SIZEOF_FREE(f)+2);
/* Create symbol table private heap */
- if ((stab.heap_addr = H5H_new (f, H5H_LOCAL, init))<0) {
+ if (H5H_new (f, H5H_LOCAL, init, &(stab.heap_addr)/*out*/)<0) {
HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); /*can't create heap*/
}
- if ((name = H5H_insert (f, stab.heap_addr, 1, "")<0)) {
+ if ((name = H5H_insert (f, &(stab.heap_addr), 1, "")<0)) {
HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); /*can't initialize heap*/
}
if (0!=name) {
@@ -87,7 +85,7 @@ H5G_stab_new (H5F_t *f, H5G_entry_t *self, size_t init)
}
/* Create the B-tree */
- if ((stab.btree_addr = H5B_new (f, H5B_SNODE, NULL))<0) {
+ if (H5B_new (f, H5B_SNODE, NULL, &(stab.btree_addr)/*out*/)<0) {
HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); /*can't create B-tree*/
}
@@ -96,20 +94,18 @@ H5G_stab_new (H5F_t *f, H5G_entry_t *self, size_t init)
* since nothing refers to it yet. The link count will be
* incremented if the object is added to the group directed graph.
*/
- if ((addr = H5O_new (f, 0, 4+2*H5F_SIZEOF_OFFSET(f)))<0) {
+ if (H5O_new (f, 0, 4+2*H5F_SIZEOF_OFFSET(f), &addr/*out*/)<0) {
HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); /*can't create header*/
}
/* insert the symbol table message */
- if (self) {
- memset (self, 0, sizeof(H5G_entry_t));
- self->header = addr;
- }
- if (H5O_modify(f, addr, self, H5O_STAB, H5O_NEW_MESG, &stab)<0) {
+ memset (self, 0, sizeof(H5G_entry_t));
+ self->header = addr;
+ if (H5O_modify(f, NO_ADDR, self, H5O_STAB, H5O_NEW_MESG, &stab)<0) {
HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); /*can't create message*/
}
- FUNC_LEAVE (addr);
+ FUNC_LEAVE (SUCCEED);
}
@@ -144,7 +140,7 @@ H5G_stab_new (H5F_t *f, H5G_entry_t *self, size_t init)
*-------------------------------------------------------------------------
*/
H5G_entry_t *
-H5G_stab_find (H5F_t *f, haddr_t addr, H5G_entry_t *self,
+H5G_stab_find (H5F_t *f, const haddr_t *addr, H5G_entry_t *self,
const char *name)
{
H5G_bt_ud1_t udata; /*data to pass through B-tree */
@@ -154,13 +150,14 @@ H5G_stab_find (H5F_t *f, haddr_t addr, H5G_entry_t *self,
/* Check arguments */
assert (f);
- if (addr<=0 && (!self || self->header<=0)) {
+ assert (!addr || H5F_addr_defined (addr));
+ if (!addr && (!self || !H5F_addr_defined (&(self->header)))) {
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL);
}
if (!name || !*name) {
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL);
}
- if (addr<=0) addr = self->header;
+ if (!addr) addr = &(self->header);
/* set up the udata */
if (NULL==H5O_read (f, addr, self, H5O_STAB, 0, &stab)) {
@@ -169,20 +166,21 @@ H5G_stab_find (H5F_t *f, haddr_t addr, H5G_entry_t *self,
udata.operation = H5G_OPER_FIND;
udata.name = name;
udata.heap_addr = stab.heap_addr;
- udata.grp_addr = addr;
+ udata.grp_addr = *addr;
udata.node_ptr = NULL;
/* search the B-tree */
- if (H5B_find (f, H5B_SNODE, stab.btree_addr, &udata)<0) {
+ if (H5B_find (f, H5B_SNODE, &(stab.btree_addr), &udata)<0) {
if (udata.node_ptr) {
- H5AC_unprotect (f, H5AC_SNODE, udata.node_addr, udata.node_ptr);
+ H5AC_unprotect (f, H5AC_SNODE, &(udata.node_addr), udata.node_ptr);
}
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL); /*not found*/
}
/* Unprotect the symbol table node */
if (udata.node_ptr) {
- if (H5AC_unprotect (f, H5AC_SNODE, udata.node_addr, udata.node_ptr)<0) {
+ if (H5AC_unprotect (f, H5AC_SNODE, &(udata.node_addr),
+ udata.node_ptr)<0) {
HRETURN_ERROR (H5E_SYM, H5E_PROTECT, NULL);
}
}
@@ -233,12 +231,12 @@ H5G_stab_insert (H5F_t *f, H5G_entry_t *self, const char *name,
/* check arguments */
assert (f);
- assert (self && self->header>=0);
+ assert (self && H5F_addr_defined (&(self->header)));
assert (name && *name);
assert (ent);
/* initialize data to pass through B-tree */
- if (NULL==H5O_read (f, self->header, self, H5O_STAB, 0, &stab)) {
+ if (NULL==H5O_read (f, &(self->header), self, H5O_STAB, 0, &stab)) {
HRETURN_ERROR (H5E_SYM, H5E_BADMESG, NULL); /*can't read message*/
}
@@ -251,9 +249,9 @@ H5G_stab_insert (H5F_t *f, H5G_entry_t *self, const char *name,
udata.node_ptr = NULL;
/* insert */
- if (H5B_insert (f, H5B_SNODE, stab.btree_addr, &udata)<0) {
+ if (H5B_insert (f, H5B_SNODE, &(stab.btree_addr), &udata)<0) {
if (udata.node_ptr) {
- H5AC_unprotect (f, H5AC_SNODE, udata.node_addr, udata.node_ptr);
+ H5AC_unprotect (f, H5AC_SNODE, &(udata.node_addr), udata.node_ptr);
}
HRETURN_ERROR (H5E_SYM, H5E_CANTINSERT, NULL); /*can't insert entry*/
}
@@ -264,7 +262,7 @@ H5G_stab_insert (H5F_t *f, H5G_entry_t *self, const char *name,
* B-tree code. We unprotect it now, but the pointer will remain valid
* until the next call to H5AC.
*/
- if (H5AC_unprotect (f, H5AC_SNODE, udata.node_addr, udata.node_ptr)<0) {
+ if (H5AC_unprotect (f, H5AC_SNODE, &(udata.node_addr), udata.node_ptr)<0) {
HRETURN_ERROR (H5E_SYM, H5E_PROTECT, NULL); /*can't unprotect*/
}
@@ -317,11 +315,11 @@ H5G_stab_list (H5F_t *f, H5G_entry_t *self, intn maxentries,
/* check args */
assert (f);
- assert (self && self->header>=0);
+ assert (self && H5F_addr_defined (&(self->header)));
assert (maxentries>=0);
/* initialize data to pass through B-tree */
- if (NULL==H5O_read (f, self->header, self, H5O_STAB, 0, &stab)) {
+ if (NULL==H5O_read (f, &(self->header), self, H5O_STAB, 0, &stab)) {
HRETURN_ERROR (H5E_SYM, H5E_BADMESG, FAIL); /*not a symbol table*/
}
udata.entry = entries;
@@ -333,7 +331,7 @@ H5G_stab_list (H5F_t *f, H5G_entry_t *self, intn maxentries,
if (names) HDmemset (names, 0, maxentries);
/* list */
- if (H5B_list (f, H5B_SNODE, stab.btree_addr, &udata)<0) {
+ if (H5B_list (f, H5B_SNODE, &(stab.btree_addr), &udata)<0) {
if (names) {
for (i=0; i<maxentries; i++) H5MM_xfree (names[i]);
}
diff --git a/src/H5H.c b/src/H5H.c
index e1453e5..f6a429c 100644
--- a/src/H5H.c
+++ b/src/H5H.c
@@ -29,7 +29,7 @@
#define PABLO_MASK H5H_mask
typedef struct H5H_free_t {
- off_t offset; /*offset of free block */
+ size_t offset; /*offset of free block */
size_t size; /*size of free block */
struct H5H_free_t *prev; /*previous entry in free list */
struct H5H_free_t *next; /*next entry in free list */
@@ -45,17 +45,18 @@ typedef struct H5H_t {
} H5H_t;
/* PRIVATE PROTOTYPES */
-static H5H_t *H5H_load (H5F_t *f, haddr_t addr, const void *udata1,
+static H5H_t *H5H_load (H5F_t *f, const 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);
+static herr_t H5H_flush (H5F_t *f, hbool_t dest, const haddr_t *addr,
+ H5H_t *heap);
/*
* H5H inherits cache-like properties from H5AC
*/
static const H5AC_class_t H5AC_HEAP[1] = {{
H5AC_HEAP_ID,
- (void*(*)(H5F_t*,haddr_t,const void*,void*))H5H_load,
- (herr_t(*)(H5F_t*,hbool_t,haddr_t,void*))H5H_flush,
+ (void*(*)(H5F_t*,const haddr_t*,const void*,void*))H5H_load,
+ (herr_t(*)(H5F_t*,hbool_t,const haddr_t*,void*))H5H_flush,
}};
/* Is the interface initialized? */
@@ -72,7 +73,8 @@ static intn interface_initialize_g = FALSE;
* If the heap ever has to grow, then REALLOC_HINT is the
* minimum amount by which the heap will grow.
*
- * Return: Success: File address of new heap.
+ * Return: Success: SUCCEED. The file address of new heap is
+ * returned through the ADDR argument.
*
* Failure: FAIL
*
@@ -88,17 +90,18 @@ static intn interface_initialize_g = FALSE;
*
*-------------------------------------------------------------------------
*/
-haddr_t
-H5H_new (H5F_t *f, H5H_type_t heap_type, size_t size_hint)
+herr_t
+H5H_new (H5F_t *f, H5H_type_t heap_type, size_t size_hint,
+ haddr_t *addr/*out*/)
{
H5H_t *heap = NULL;
size_t total_size; /*total heap size on disk */
- haddr_t addr; /*heap file address */
FUNC_ENTER (H5H_new, NULL, FAIL);
/* check arguments */
assert (f);
+ assert (addr);
if (H5H_GLOBAL==heap_type) {
#ifndef NDEBUG
fprintf (stderr, "H5H_new: a local heap is used as the global heap\n");
@@ -112,13 +115,14 @@ H5H_new (H5F_t *f, H5H_type_t heap_type, size_t size_hint)
/* allocate file version */
total_size = H5H_SIZEOF_HDR(f) + size_hint;
- if ((addr = H5MF_alloc (f, total_size))<0) {
+ if (H5MF_alloc (f, H5MF_META, total_size, addr/*out*/)<0) {
HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL);
}
/* allocate memory version */
heap = H5MM_xcalloc (1, sizeof(H5H_t));
- heap->addr = addr + H5H_SIZEOF_HDR(f);
+ heap->addr = *addr;
+ H5F_addr_inc (&(heap->addr), H5H_SIZEOF_HDR (f));
heap->disk_alloc = size_hint;
heap->mem_alloc = size_hint;
heap->chunk = H5MM_xcalloc (1, H5H_SIZEOF_HDR(f)+size_hint);
@@ -141,7 +145,7 @@ H5H_new (H5F_t *f, H5H_type_t heap_type, size_t size_hint)
HRETURN_ERROR (H5E_HEAP, H5E_CANTINIT, FAIL);
}
- FUNC_LEAVE (addr);
+ FUNC_LEAVE (SUCCEED);
}
@@ -163,19 +167,20 @@ 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, const void *udata1, void *udata2)
+H5H_load (H5F_t *f, const haddr_t *addr, const void *udata1, void *udata2)
{
- uint8 hdr[20], *p;
+ uint8 hdr[20];
+ const uint8 *p=NULL;
H5H_t *heap=NULL;
H5H_free_t *fl=NULL, *tail=NULL;
- haddr_t free_block=H5H_FREE_NULL;
+ size_t free_block=H5H_FREE_NULL;
H5H_t *ret_value=NULL;
FUNC_ENTER (H5H_load, NULL, NULL);
/* check arguments */
assert (f);
- assert (addr>0);
+ assert (addr && H5F_addr_defined (addr));
assert (H5H_SIZEOF_HDR(f) <= sizeof hdr);
assert (!udata1);
assert (!udata2);
@@ -197,23 +202,23 @@ H5H_load (H5F_t *f, haddr_t addr, const void *udata1, void *udata2)
heap->mem_alloc = heap->disk_alloc;
/* free list head */
- H5F_decode_offset (f, p, free_block);
- if (-1!=free_block && (free_block<0 || free_block>=heap->disk_alloc)) {
+ H5F_decode_length (f, p, free_block);
+ if (free_block!=H5H_FREE_NULL && free_block>=heap->disk_alloc) {
HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL);
}
/* data */
- H5F_decode_offset (f, p, heap->addr);
+ H5F_addr_decode (f, &p, &(heap->addr));
heap->chunk = H5MM_xcalloc (1, H5H_SIZEOF_HDR(f) + heap->mem_alloc);
if (heap->disk_alloc &&
- H5F_block_read (f, heap->addr, heap->disk_alloc,
+ H5F_block_read (f, &(heap->addr), heap->disk_alloc,
heap->chunk + H5H_SIZEOF_HDR(f))<0) {
HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL);
}
/* free list */
while (H5H_FREE_NULL!=free_block) {
- if (free_block<0 || free_block>=heap->disk_alloc) {
+ if (free_block>=heap->disk_alloc) {
HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL);
}
fl = H5MM_xmalloc (sizeof (H5H_free_t));
@@ -225,7 +230,7 @@ H5H_load (H5F_t *f, haddr_t addr, const void *udata1, void *udata2)
if (!heap->freelist) heap->freelist = fl;
p = heap->chunk + H5H_SIZEOF_HDR(f) + free_block;
- H5F_decode_offset (f, p, free_block);
+ H5F_decode_length (f, p, free_block);
H5F_decode_length (f, p, fl->size);
if (fl->offset + fl->size > heap->disk_alloc) {
@@ -268,16 +273,17 @@ H5H_load (H5F_t *f, haddr_t addr, const void *udata1, void *udata2)
*-------------------------------------------------------------------------
*/
static herr_t
-H5H_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5H_t *heap)
+H5H_flush (H5F_t *f, hbool_t destroy, const haddr_t *addr, H5H_t *heap)
{
uint8 *p = heap->chunk;
H5H_free_t *fl = heap->freelist;
+ haddr_t hdr_end_addr;
FUNC_ENTER (H5H_flush, NULL, FAIL);
/* check arguments */
assert (f);
- assert (addr>0);
+ assert (addr && H5F_addr_defined (addr));
assert (heap);
if (heap->dirty) {
@@ -288,11 +294,13 @@ H5H_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5H_t *heap)
* disk storage.
*/
if (heap->mem_alloc > heap->disk_alloc) {
- haddr_t old_addr = heap->addr;
- if ((heap->addr = H5MF_alloc (f, heap->mem_alloc))<0) {
+ haddr_t old_addr = heap->addr, new_addr;
+ if (H5MF_alloc (f, H5MF_META, heap->mem_alloc, &new_addr/*out*/)<0) {
HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL);
}
- H5MF_free (f, old_addr, heap->disk_alloc); /*don't care if fail*/
+ heap->addr = new_addr;
+ H5MF_free (f, &old_addr, heap->disk_alloc);
+ H5ECLEAR;/*don't really care if the free failed*/
heap->disk_alloc = heap->mem_alloc;
}
@@ -301,8 +309,8 @@ H5H_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5H_t *heap)
*/
HDmemcpy (p, H5H_MAGIC, H5H_SIZEOF_MAGIC); p += H5H_SIZEOF_MAGIC;
H5F_encode_length (f, p, heap->mem_alloc);
- H5F_encode_offset (f, p, fl?fl->offset:H5H_FREE_NULL);
- H5F_encode_offset (f, p, heap->addr);
+ H5F_encode_length (f, p, fl?fl->offset:H5H_FREE_NULL);
+ H5F_addr_encode (f, &p, &(heap->addr));
/*
* Write the free list.
@@ -310,9 +318,9 @@ H5H_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5H_t *heap)
while (fl) {
p = heap->chunk + H5H_SIZEOF_HDR(f) + fl->offset;
if (fl->next) {
- H5F_encode_offset (f, p, fl->next->offset);
+ H5F_encode_length (f, p, fl->next->offset);
} else {
- H5F_encode_offset (f, p, H5H_FREE_NULL);
+ H5F_encode_length (f, p, H5H_FREE_NULL);
}
H5F_encode_length (f, p, fl->size);
fl = fl->next;
@@ -321,7 +329,10 @@ H5H_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5H_t *heap)
/*
* Copy buffer to disk.
*/
- if (heap->addr == addr + H5H_SIZEOF_HDR(f)) {
+ hdr_end_addr = *addr;
+ H5F_addr_inc (&hdr_end_addr, H5H_SIZEOF_HDR (f));
+ if (H5F_addr_eq (&(heap->addr), &hdr_end_addr)) {
+ /* The header and data are contiguous */
if (H5F_block_write (f, addr, H5H_SIZEOF_HDR(f)+heap->disk_alloc,
heap->chunk)<0) {
HRETURN_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL);
@@ -330,7 +341,7 @@ H5H_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5H_t *heap)
if (H5F_block_write (f, addr, H5H_SIZEOF_HDR(f), heap->chunk)<0) {
HRETURN_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL);
}
- if (H5F_block_write (f, heap->addr, heap->disk_alloc,
+ if (H5F_block_write (f, &(heap->addr), heap->disk_alloc,
heap->chunk + H5H_SIZEOF_HDR(f))<0) {
HRETURN_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL);
}
@@ -370,8 +381,8 @@ H5H_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5H_t *heap)
* Attempting to read past the end of an object may cause this
* function to fail.
*
- * If the heap address ADDR is the constant H5H_GLOBAL then
- * the address comes from the H5F_t global heap field.
+ * If the heap address ADDR is the the null pointer then the
+ * address comes from the H5F_t global heap field.
*
* Return: Success: BUF (or the allocated buffer)
*
@@ -386,7 +397,7 @@ H5H_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5H_t *heap)
*-------------------------------------------------------------------------
*/
void *
-H5H_read (H5F_t *f, haddr_t addr, off_t offset, size_t size, void *buf)
+H5H_read (H5F_t *f, const haddr_t *addr, size_t offset, size_t size, void *buf)
{
H5H_t *heap = NULL;
@@ -394,8 +405,8 @@ H5H_read (H5F_t *f, haddr_t addr, off_t offset, size_t size, void *buf)
/* check arguments */
assert (f);
- if (H5H_GLOBAL==addr) addr = f->shared->smallobj_off;
- assert (addr>0);
+ if (!addr) addr = &(f->shared->smallobj_addr);
+ assert (H5F_addr_defined (addr));
assert (offset>=0);
if (NULL==(heap=H5AC_find (f, H5AC_HEAP, addr, NULL, NULL))) {
@@ -424,7 +435,7 @@ H5H_read (H5F_t *f, haddr_t addr, off_t offset, size_t size, void *buf)
* byte offset of the object from the beginning of the heap and
* may include an offset into the interior of the object.
*
- * If the heap address ADDR is the constant H5H_GLOBAL then
+ * If the heap address ADDR is the null pointer then
* the address comes from the H5F_t global heap field.
*
* Return: Success: Ptr to the object. The pointer points to
@@ -445,7 +456,7 @@ H5H_read (H5F_t *f, haddr_t addr, off_t offset, size_t size, void *buf)
*-------------------------------------------------------------------------
*/
const void *
-H5H_peek (H5F_t *f, haddr_t addr, off_t offset)
+H5H_peek (H5F_t *f, const haddr_t *addr, size_t offset)
{
H5H_t *heap = NULL;
const void *retval = NULL;
@@ -454,8 +465,8 @@ H5H_peek (H5F_t *f, haddr_t addr, off_t offset)
/* check arguments */
assert (f);
- if (H5H_GLOBAL==addr) addr = f->shared->smallobj_off;
- assert (addr>0);
+ if (!addr) addr = &(f->shared->smallobj_addr);
+ assert (H5F_addr_defined (addr));
assert (offset>=0);
if (NULL==(heap=H5AC_find (f, H5AC_HEAP, addr, NULL, NULL))) {
@@ -500,7 +511,7 @@ H5H_remove_free (H5H_t *heap, H5H_free_t *fl)
*
* Purpose: Inserts a new item into the heap.
*
- * If the heap address ADDR is the constant H5H_GLOBAL then
+ * If the heap address ADDR is the null pointer then
* the address comes from the H5F_t global heap field.
*
* Return: Success: Offset of new item within heap.
@@ -515,13 +526,14 @@ H5H_remove_free (H5H_t *heap, H5H_free_t *fl)
*
*-------------------------------------------------------------------------
*/
-off_t
-H5H_insert (H5F_t *f, haddr_t addr, size_t buf_size, const void *buf)
+size_t
+H5H_insert (H5F_t *f, const haddr_t *addr, size_t buf_size, const void *buf)
{
H5H_t *heap=NULL;
H5H_free_t *fl=NULL, *max_fl=NULL;
- off_t offset = -1;
+ size_t offset = 0;
size_t old_size, need_more;
+ hbool_t found;
#ifndef NDEBUG
static nmessages = 0;
#endif
@@ -530,8 +542,8 @@ H5H_insert (H5F_t *f, haddr_t addr, size_t buf_size, const void *buf)
/* check arguments */
assert (f);
- if (H5H_GLOBAL==addr) addr = f->shared->smallobj_off;
- assert (addr>0);
+ if (!addr) addr = &(f->shared->smallobj_addr);
+ assert (H5F_addr_defined (addr));
assert (buf_size>0);
assert (buf);
@@ -544,17 +556,22 @@ H5H_insert (H5F_t *f, haddr_t addr, size_t buf_size, const void *buf)
* Look for a free slot large enough for this object and which would
* leave zero or at least H5G_SIZEOF_FREE bytes left over.
*/
- for (fl=heap->freelist; fl; fl=fl->next) {
+ for (fl=heap->freelist,found=FALSE; fl; fl=fl->next) {
if (fl->size>buf_size && fl->size-buf_size>=H5H_SIZEOF_FREE(f)) {
+ /* a bigger free block was found */
offset = fl->offset;
fl->offset += buf_size;
fl->size -= buf_size;
+ found = TRUE;
break;
} else if (fl->size==buf_size) {
+ /* free block of exact size found */
offset = fl->offset;
fl = H5H_remove_free (heap, fl);
+ found = TRUE;
break;
} else if (!max_fl || max_fl->offset < fl->offset) {
+ /* use worst fit */
max_fl = fl;
}
}
@@ -566,7 +583,7 @@ H5H_insert (H5F_t *f, haddr_t addr, size_t buf_size, const void *buf)
* can extend that free chunk. Otherwise we'll have to make another
* free chunk. If the heap must expand, we double its size.
*/
- if (offset<0) {
+ if (!found) {
need_more = MAX3 (buf_size, heap->mem_alloc, H5H_SIZEOF_FREE(f));
@@ -581,8 +598,8 @@ H5H_insert (H5F_t *f, haddr_t addr, size_t buf_size, const void *buf)
if (max_fl->size < H5H_SIZEOF_FREE(f)) {
#ifndef NDEBUG
if (max_fl->size) {
- fprintf (stderr, "H5H_insert: lost %d bytes at line %d\n",
- max_fl->size, __LINE__);
+ fprintf (stderr, "H5H_insert: lost %lu bytes at line %d\n",
+ (unsigned long)(max_fl->size), __LINE__);
if (0==nmessages++) {
fprintf (stderr, "Messages from H5H_insert() will go away "
"when assertions are turned off.\n");
@@ -608,8 +625,8 @@ H5H_insert (H5F_t *f, haddr_t addr, size_t buf_size, const void *buf)
heap->freelist = fl;
#ifndef NDEBUG
} else if (need_more>buf_size) {
- fprintf (stderr, "H5H_insert: lost %d bytes at line %d\n",
- need_more-buf_size, __LINE__);
+ fprintf (stderr, "H5H_insert: lost %lu bytes at line %d\n",
+ (unsigned long)(need_more-buf_size), __LINE__);
if (0==nmessages++) {
fprintf (stderr, "Messages from H5H_insert() will go away "
"when assertions are turned off.\n");
@@ -655,7 +672,7 @@ H5H_insert (H5F_t *f, haddr_t addr, size_t buf_size, const void *buf)
* Do not partially write an object to create it; the first
* write for an object must be for the entire object.
*
- * If the heap address ADDR is the constant H5H_GLOBAL then
+ * If the heap address ADDR is the null pointer then
* the address comes from the H5F_t global heap field.
*
* Return: Success: SUCCEED
@@ -671,7 +688,7 @@ H5H_insert (H5F_t *f, haddr_t addr, size_t buf_size, const void *buf)
*-------------------------------------------------------------------------
*/
herr_t
-H5H_write (H5F_t *f, haddr_t addr, off_t offset, size_t size,
+H5H_write (H5F_t *f, const haddr_t *addr, size_t offset, size_t size,
const void *buf)
{
H5H_t *heap = NULL;
@@ -680,8 +697,8 @@ H5H_write (H5F_t *f, haddr_t addr, off_t offset, size_t size,
/* check arguments */
assert (f);
- if (H5H_GLOBAL==addr) addr = f->shared->smallobj_off;
- assert (addr>0);
+ if (!addr) addr = &(f->shared->smallobj_addr);
+ assert (H5F_addr_defined (addr));
assert (offset>=0);
assert (buf);
@@ -714,7 +731,7 @@ H5H_write (H5F_t *f, haddr_t addr, off_t offset, size_t size,
* in two separate objects, one at the original offset and
* one at the first offset past the removed portion.
*
- * If the heap address ADDR is the constant H5H_GLOBAL then
+ * If the heap address ADDR is the null pointer then
* the address comes from the H5F_t global heap field.
*
* Return: Success: SUCCEED
@@ -730,7 +747,7 @@ H5H_write (H5F_t *f, haddr_t addr, off_t offset, size_t size,
*-------------------------------------------------------------------------
*/
herr_t
-H5H_remove (H5F_t *f, haddr_t addr, off_t offset, size_t size)
+H5H_remove (H5F_t *f, const haddr_t *addr, size_t offset, size_t size)
{
H5H_t *heap = NULL;
H5H_free_t *fl = heap->freelist, *fl2 = NULL;
@@ -742,8 +759,8 @@ H5H_remove (H5F_t *f, haddr_t addr, off_t offset, size_t size)
/* check arguments */
assert (f);
- if (H5H_GLOBAL==addr) addr = f->shared->smallobj_off;
- assert (addr>0);
+ if (!addr) addr = &(f->shared->smallobj_addr);
+ assert (H5F_addr_defined (addr));
assert (offset>=0);
assert (size>0);
@@ -799,7 +816,7 @@ H5H_remove (H5F_t *f, haddr_t addr, off_t offset, size_t size)
*/
if (size < H5H_SIZEOF_FREE(f)) {
#ifndef NDEBUG
- fprintf (stderr, "H5H_remove: lost %d bytes\n", size);
+ fprintf (stderr, "H5H_remove: lost %lu bytes\n", (unsigned long)size);
if (0==nmessages++) {
fprintf (stderr, "Messages from H5H_remove() will go away "
"when assertions are turned off.\n");
@@ -828,7 +845,7 @@ H5H_remove (H5F_t *f, haddr_t addr, off_t offset, size_t size)
*
* Purpose: Prints debugging information about a heap.
*
- * If the heap address ADDR is the constant H5H_GLOBAL then
+ * If the heap address ADDR is the null pointer then
* the address comes from the H5F_t global heap field.
*
* Return: Success: SUCCEED
@@ -844,7 +861,7 @@ H5H_remove (H5F_t *f, haddr_t addr, off_t offset, size_t size)
*-------------------------------------------------------------------------
*/
herr_t
-H5H_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent, intn fwidth)
+H5H_debug (H5F_t *f, const haddr_t *addr, FILE *stream, intn indent, intn fwidth)
{
H5H_t *h = NULL;
int i, j, overlap;
@@ -857,8 +874,8 @@ H5H_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent, intn fwidth)
/* check arguments */
assert (f);
- if (H5H_GLOBAL==addr) addr = f->shared->smallobj_off;
- assert (addr>0);
+ if (!addr) addr = &(f->shared->smallobj_addr);
+ assert (H5F_addr_defined (addr));
assert (stream);
assert (indent>=0);
assert (fwidth>=0);
@@ -906,9 +923,10 @@ H5H_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent, intn fwidth)
}
if (h->mem_alloc) {
- fprintf (stream, "%*s%-*s %d\n", indent, "", fwidth,
+ fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth,
"Percent of heap used:",
- 100 * (h->mem_alloc - amount_free) / h->mem_alloc);
+ (unsigned long)(100 * (h->mem_alloc - amount_free) /
+ h->mem_alloc));
}
/*
diff --git a/src/H5Hprivate.h b/src/H5Hprivate.h
index 151127a..f649bbf 100644
--- a/src/H5Hprivate.h
+++ b/src/H5Hprivate.h
@@ -28,11 +28,11 @@
#define H5H_SIZEOF_HDR(F) \
(H5H_SIZEOF_MAGIC + /*heap signature */ \
H5F_SIZEOF_SIZE (F) + /*data size */ \
- H5F_SIZEOF_OFFSET (F) + /*free list head */ \
+ H5F_SIZEOF_SIZE (F) + /*free list head */ \
H5F_SIZEOF_OFFSET (F)) /*data address */
#define H5H_SIZEOF_FREE(F) \
- (H5F_SIZEOF_OFFSET (F) + /*ptr to next free block */ \
+ (H5F_SIZEOF_SIZE (F) + /*ptr to next free block */ \
H5F_SIZEOF_SIZE (F)) /*size of this free block */
@@ -44,14 +44,17 @@ typedef enum H5H_type_t {
/*
* Library prototypes...
*/
-haddr_t H5H_new (H5F_t *f, H5H_type_t type, size_t size_hint);
-void *H5H_read (H5F_t *f, haddr_t addr, off_t offset, size_t size, void *buf);
-const void *H5H_peek (H5F_t *f, haddr_t addr, off_t offset);
-off_t H5H_insert (H5F_t *f, haddr_t addr, size_t size, const void *buf);
-herr_t H5H_write (H5F_t *f, haddr_t addr, off_t offset, size_t size,
+herr_t H5H_new (H5F_t *f, H5H_type_t type, size_t size_hint,
+ haddr_t *addr/*out*/);
+void *H5H_read (H5F_t *f, const haddr_t *addr, size_t offset, size_t size,
+ void *buf);
+const void *H5H_peek (H5F_t *f, const haddr_t *addr, size_t offset);
+size_t H5H_insert (H5F_t *f, const haddr_t *addr, size_t size,
+ const void *buf);
+herr_t H5H_write (H5F_t *f, const haddr_t *addr, size_t offset, size_t size,
const void *buf);
-herr_t H5H_remove (H5F_t *f, haddr_t addr, off_t offset, size_t size);
-herr_t H5H_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent,
+herr_t H5H_remove (H5F_t *f, const haddr_t *addr, size_t offset, size_t size);
+herr_t H5H_debug (H5F_t *f, const haddr_t *addr, FILE *stream, intn indent,
intn fwidth);
#endif
diff --git a/src/H5MF.c b/src/H5MF.c
index b32e093..47ec30d 100644
--- a/src/H5MF.c
+++ b/src/H5MF.c
@@ -33,9 +33,12 @@ static intn interface_initialize_g = FALSE;
*
* Purpose: Allocate at least SIZE bytes of file memory and return
* the address where that contiguous chunk of file memory
- * exists.
+ * exists. The allocation operation should be either H5MF_META or
+ * H5MF_RAW depending on the purpose for which the storage is
+ * being requested.
*
- * Return: Success: File address of new chunk.
+ * Return: Success: SUCCEED. The file address of new chunk is
+ * returned through the ADDR argument.
*
* Failure: FAIL
*
@@ -47,23 +50,39 @@ static intn interface_initialize_g = FALSE;
*
*-------------------------------------------------------------------------
*/
-haddr_t
-H5MF_alloc (H5F_t *f, size_t size)
+herr_t
+H5MF_alloc (H5F_t *f, intn op, size_t size, haddr_t *addr/*out*/)
{
- haddr_t addr;
-
+ haddr_t tmp_addr;
+
FUNC_ENTER (H5MF_alloc, NULL, FAIL);
/* check arguments */
assert (f);
- assert (f->shared->logical_len>0);
+ assert (H5MF_META==op || H5MF_RAW==op);
assert (size>0);
+ assert (addr);
- /* reserve space from the end of the file */
- addr = f->shared->logical_len;
- f->shared->logical_len += size;
+ /*
+ * Eventually we'll maintain a free list(s) and try to satisfy requests
+ * from there. But for now we just allocate more memory from the end of
+ * the file.
+ */
+ if (H5F_low_extend (f->shared->lf, op, size, addr/*out*/)<0) {
+ /* Low level mem management failed */
+ HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL);
+ }
+ /* Convert from absolute to relative */
+ addr->offset -= f->shared->base_addr.offset;
- FUNC_LEAVE (addr);
+ /* Did we extend the size of the hdf5 data? */
+ tmp_addr = *addr;
+ H5F_addr_inc (&tmp_addr, size);
+ if (H5F_addr_gt (&tmp_addr, &(f->shared->hdf5_eof))) {
+ f->shared->hdf5_eof = tmp_addr;
+ }
+
+ FUNC_LEAVE (SUCCEED);
}
@@ -88,13 +107,14 @@ H5MF_alloc (H5F_t *f, size_t size)
*-------------------------------------------------------------------------
*/
herr_t
-H5MF_free (H5F_t *f, haddr_t addr, size_t size)
+H5MF_free (H5F_t *f, const haddr_t *addr, size_t size)
{
FUNC_ENTER (H5MF_free, NULL, FAIL);
/* check arguments */
assert (f);
- if (addr<=0 || 0==size) HRETURN (SUCCEED);
+ if (!addr || !H5F_addr_defined (addr) || 0==size) HRETURN (SUCCEED);
+ assert (!H5F_addr_zerop (addr));
#ifndef NDEBUG
fprintf (stderr, "H5MF_free: lost %lu bytes of file storage\n",
diff --git a/src/H5MFprivate.h b/src/H5MFprivate.h
index 3bb7205..470db89 100644
--- a/src/H5MFprivate.h
+++ b/src/H5MFprivate.h
@@ -22,10 +22,13 @@
#include <H5private.h>
#include <H5Fprivate.h>
+#define H5MF_META 0 /*request storage for meta data */
+#define H5MF_RAW 1 /*request storage for raw data */
+
/*
* Library prototypes...
*/
-haddr_t H5MF_alloc (H5F_t *f, size_t size);
-herr_t H5MF_free (H5F_t *f, haddr_t addr, size_t size);
+herr_t H5MF_alloc (H5F_t *f, intn, size_t size, haddr_t *addr/*out*/);
+herr_t H5MF_free (H5F_t *f, const haddr_t *addr, size_t size);
#endif
diff --git a/src/H5O.c b/src/H5O.c
index 43faa6c..045b98e 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -25,10 +25,11 @@
#define PABLO_MASK H5O_mask
/* 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, const void *_udata1,
+static herr_t H5O_flush (H5F_t *f, hbool_t destroy, const haddr_t *addr,
+ H5O_t *oh);
+static H5O_t *H5O_load (H5F_t *f, const haddr_t *addr, const void *_udata1,
void *_udata2);
-static intn H5O_find_in_ohdr (H5F_t *f, haddr_t addr,
+static intn H5O_find_in_ohdr (H5F_t *f, const 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,
size_t size);
@@ -38,8 +39,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] = {{
H5AC_OHDR_ID,
- (void*(*)(H5F_t*,haddr_t,const void*,void*))H5O_load,
- (herr_t(*)(H5F_t*,hbool_t,haddr_t,void*))H5O_flush,
+ (void*(*)(H5F_t*,const haddr_t*,const void*,void*))H5O_load,
+ (herr_t(*)(H5F_t*,hbool_t,const haddr_t*,void*))H5O_flush,
}};
/* Is the interface initialized? */
@@ -74,7 +75,8 @@ static const H5O_class_t *const message_type_g[] = {
* Purpose: Creates a new object header, sets the link count
* to NLINK, and caches the header.
*
- * Return: Success: Address of new header.
+ * Return: Success: SUCCEED, the address of new header is
+ * returned through the ADDR argument.
*
* Failure: FAIL
*
@@ -86,24 +88,25 @@ static const H5O_class_t *const message_type_g[] = {
*
*-------------------------------------------------------------------------
*/
-haddr_t
-H5O_new (H5F_t *f, intn nlink, size_t size_hint)
+herr_t
+H5O_new (H5F_t *f, intn nlink, size_t size_hint, haddr_t *addr/*out*/)
{
size_t size; /*total size of object header */
- haddr_t addr = FAIL; /*address of object header */
H5O_t *oh = NULL;
+ haddr_t tmp_addr;
FUNC_ENTER (H5O_new, NULL, FAIL);
/* check args */
assert (f);
assert (nlink>=0);
+ assert (addr);
if (size_hint<H5O_MIN_SIZE) size_hint = H5O_MIN_SIZE;
H5O_ALIGN (size_hint, H5O_ALIGNMENT);
/* allocate disk space for header and first chunk */
size = H5O_SIZEOF_HDR(f) + size_hint;
- if ((addr = H5MF_alloc (f, size))<0) {
+ if (H5MF_alloc (f, H5MF_META, size, addr/*out*/)<0) {
HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL);
}
@@ -118,9 +121,11 @@ H5O_new (H5F_t *f, intn nlink, size_t size_hint)
oh->nchunks = 1;
oh->alloc_nchunks = H5O_NCHUNKS;
oh->chunk = H5MM_xmalloc (oh->alloc_nchunks * sizeof (H5O_chunk_t));
-
+
+ tmp_addr = *addr;
+ H5F_addr_inc (&tmp_addr, H5O_SIZEOF_HDR (f));
oh->chunk[0].dirty = TRUE;
- oh->chunk[0].addr = addr + H5O_SIZEOF_HDR(f);
+ oh->chunk[0].addr = tmp_addr;
oh->chunk[0].size = size_hint;
oh->chunk[0].image = H5MM_xcalloc (1, size_hint);
@@ -142,7 +147,7 @@ H5O_new (H5F_t *f, intn nlink, size_t size_hint)
HRETURN_ERROR (H5E_OHDR, H5E_CANTINIT, FAIL);
}
- FUNC_LEAVE (addr);
+ FUNC_LEAVE (SUCCEED);
}
@@ -167,7 +172,7 @@ H5O_new (H5F_t *f, intn nlink, size_t size_hint)
*-------------------------------------------------------------------------
*/
static H5O_t *
-H5O_load (H5F_t *f, haddr_t addr, const void *_udata1, void *_udata2)
+H5O_load (H5F_t *f, const haddr_t *addr, const void *_udata1, void *_udata2)
{
H5O_t *oh = NULL;
H5O_t *ret_value = (void*)1; /*kludge for HGOTO_ERROR*/
@@ -183,7 +188,7 @@ H5O_load (H5F_t *f, haddr_t addr, const void *_udata1, void *_udata2)
/* check args */
assert (f);
- assert (addr>=0);
+ assert (addr && H5F_addr_defined (addr));
assert (!_udata1);
assert (!_udata2);
@@ -216,7 +221,8 @@ H5O_load (H5F_t *f, haddr_t addr, const void *_udata1, void *_udata2)
UINT32DECODE (p, oh->nlink);
/* decode first chunk info */
- chunk_addr = addr + H5O_SIZEOF_HDR(f);
+ chunk_addr = *addr;
+ H5F_addr_inc (&chunk_addr, H5O_SIZEOF_HDR (f));
UINT32DECODE (p, chunk_size);
/* build the message array */
@@ -224,7 +230,7 @@ H5O_load (H5F_t *f, haddr_t addr, const void *_udata1, void *_udata2)
oh->mesg = H5MM_xcalloc (oh->alloc_nmesgs, sizeof(H5O_mesg_t));
/* read each chunk from disk */
- while (chunk_addr) {
+ while (H5F_addr_defined (&chunk_addr)) {
/* increase chunk array size */
if (oh->nchunks>=oh->alloc_nchunks) {
@@ -239,7 +245,7 @@ H5O_load (H5F_t *f, haddr_t addr, const void *_udata1, void *_udata2)
oh->chunk[chunkno].addr = chunk_addr;
oh->chunk[chunkno].size = chunk_size;
oh->chunk[chunkno].image = H5MM_xmalloc (chunk_size);
- if (H5F_block_read (f, chunk_addr, chunk_size,
+ if (H5F_block_read (f, &chunk_addr, chunk_size,
oh->chunk[chunkno].image)<0) {
HGOTO_ERROR (H5E_OHDR, H5E_READERROR, NULL);
}
@@ -282,7 +288,9 @@ H5O_load (H5F_t *f, haddr_t addr, const void *_udata1, void *_udata2)
assert (p == oh->chunk[chunkno].image + chunk_size);
/* decode next object header continuation message */
- for (chunk_addr=0; 0==chunk_addr && curmesg<oh->nmesgs; curmesg++) {
+ for (H5F_addr_undef (&chunk_addr);
+ !H5F_addr_defined (&chunk_addr) && curmesg<oh->nmesgs;
+ curmesg++) {
if (H5O_CONT_ID==oh->mesg[curmesg].type->id) {
uint8 *p2 = oh->mesg[curmesg].raw;
cont = (H5O_CONT->decode)(f, oh->mesg[curmesg].raw_size, p2);
@@ -330,7 +338,7 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5O_t *oh)
+H5O_flush (H5F_t *f, hbool_t destroy, const haddr_t *addr, H5O_t *oh)
{
uint8 buf[16], *p;
int i;
@@ -340,7 +348,7 @@ H5O_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5O_t *oh)
/* check args */
assert (f);
- assert (addr>=0);
+ assert (addr && H5F_addr_defined (addr));
assert (oh);
/* flush */
@@ -378,14 +386,15 @@ H5O_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5O_t *oh)
/* allocate file space for chunks that have none yet */
if (H5O_CONT_ID==oh->mesg[i].type->id &&
- ((H5O_cont_t*)(oh->mesg[i].native))->addr<0) {
+ !H5F_addr_defined (&(((H5O_cont_t*)
+ (oh->mesg[i].native))->addr))) {
cont = (H5O_cont_t*)(oh->mesg[i].native);
assert (cont->chunkno >= 0);
assert (cont->chunkno < oh->nchunks);
- assert (oh->chunk[cont->chunkno].addr<0);
+ assert (!H5F_addr_defined(&(oh->chunk[cont->chunkno].addr)));
cont->size = oh->chunk[cont->chunkno].size;
- cont->addr = H5MF_alloc (f, cont->size);
- if (cont->addr<0) {
+ if (H5MF_alloc (f, H5MF_META, cont->size,
+ &(cont->addr)/*out*/)<0) {
HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL);
}
oh->chunk[cont->chunkno].addr = cont->addr;
@@ -411,8 +420,8 @@ H5O_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5O_t *oh)
/* write each chunk to disk */
for (i=0; i<oh->nchunks; i++) {
if (oh->chunk[i].dirty) {
- assert (oh->chunk[i].addr>0);
- if (H5F_block_write (f, oh->chunk[i].addr, oh->chunk[i].size,
+ assert (H5F_addr_defined (&(oh->chunk[i].addr)));
+ if (H5F_block_write (f, &(oh->chunk[i].addr), oh->chunk[i].size,
oh->chunk[i].image)<0) {
HRETURN_ERROR (H5E_OHDR, H5E_WRITEERROR, FAIL);
}
@@ -512,11 +521,12 @@ H5O_link (H5F_t *f, H5G_entry_t *ent, intn adjust)
/* check args */
assert (f);
- assert (ent && H5G_ent_addr (ent)>0);
- addr = H5G_ent_addr (ent);
+ assert (ent);
+ H5G_ent_addr (ent, &addr);
+ assert (H5F_addr_defined (&addr));
/* get header */
- if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL, NULL))) {
+ if (NULL==(oh=H5AC_find (f, H5AC_OHDR, &addr, NULL, NULL))) {
HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL);
}
@@ -562,7 +572,7 @@ H5O_link (H5F_t *f, H5G_entry_t *ent, intn adjust)
*-------------------------------------------------------------------------
*/
void *
-H5O_read (H5F_t *f, haddr_t addr, H5G_entry_t *ent,
+H5O_read (H5F_t *f, const haddr_t *addr, H5G_entry_t *ent,
const H5O_class_t *type, intn sequence, void *mesg)
{
H5O_t *oh = NULL;
@@ -570,17 +580,19 @@ H5O_read (H5F_t *f, haddr_t addr, H5G_entry_t *ent,
intn idx;
H5G_cache_t *cache = NULL;
H5G_type_t cache_type;
+ haddr_t _addr;
FUNC_ENTER (H5O_read, NULL, NULL);
/* check args */
assert (f);
- if (addr<=0 && !ent) {
- HRETURN_ERROR (H5E_OHDR, H5E_NOTFOUND, NULL);
- }
- if (addr<=0 && (addr=H5G_ent_addr (ent))<=0) {
- HRETURN_ERROR (H5E_OHDR, H5E_NOTFOUND, NULL);
+ if (!addr) {
+ if (!ent || H5G_ent_addr (ent, &_addr/*out*/)) {
+ HRETURN_ERROR (H5E_OHDR, H5E_NOTFOUND, NULL);
+ }
+ addr = &_addr;
}
+ assert (H5F_addr_defined (addr));
assert (sequence>=0);
/* can we get it from the symbol table? */
@@ -632,7 +644,7 @@ H5O_read (H5F_t *f, haddr_t addr, H5G_entry_t *ent,
*-------------------------------------------------------------------------
*/
static intn
-H5O_find_in_ohdr (H5F_t *f, haddr_t addr, const H5O_class_t **type_p,
+H5O_find_in_ohdr (H5F_t *f, const haddr_t *addr, const H5O_class_t **type_p,
intn sequence)
{
H5O_t *oh = NULL;
@@ -642,7 +654,7 @@ H5O_find_in_ohdr (H5F_t *f, haddr_t addr, const H5O_class_t **type_p,
/* check args */
assert (f);
- assert (addr>=0);
+ assert (addr && H5F_addr_defined (addr));
assert (type_p);
/* load the object header */
@@ -699,7 +711,8 @@ H5O_find_in_ohdr (H5F_t *f, haddr_t addr, const H5O_class_t **type_p,
*-------------------------------------------------------------------------
*/
const void *
-H5O_peek (H5F_t *f, haddr_t addr, const H5O_class_t *type, intn sequence)
+H5O_peek (H5F_t *f, const haddr_t *addr, const H5O_class_t *type,
+ intn sequence)
{
intn idx;
H5O_t *oh = NULL;
@@ -708,7 +721,7 @@ H5O_peek (H5F_t *f, haddr_t addr, const H5O_class_t *type, intn sequence)
/* check args */
assert (f);
- assert (addr>0);
+ assert (addr && H5F_addr_defined (addr));
if ((idx = H5O_find_in_ohdr (f, addr, &type, sequence))<0) {
HRETURN_ERROR (H5E_OHDR, H5E_NOTFOUND, NULL);
@@ -754,21 +767,27 @@ H5O_peek (H5F_t *f, haddr_t addr, const H5O_class_t *type, intn sequence)
*-------------------------------------------------------------------------
*/
intn
-H5O_modify (H5F_t *f, haddr_t addr, H5G_entry_t *ent,
+H5O_modify (H5F_t *f, const haddr_t *addr, H5G_entry_t *ent,
const H5O_class_t *type, intn overwrite, const void *mesg)
{
H5O_t *oh = NULL;
intn idx, sequence;
size_t size;
+ haddr_t _addr;
FUNC_ENTER (H5O_modify, NULL, FAIL);
/* check args */
assert (f);
- assert (addr>0 || (ent && H5G_ent_addr (ent)>0));
assert (type);
assert (mesg);
- if (addr<=0) addr = H5G_ent_addr (ent);
+ if (!addr) {
+ if (!ent || H5G_ent_addr (ent, &_addr)<0) {
+ HRETURN_ERROR (H5E_OHDR, H5E_CANTINIT, FAIL);
+ }
+ addr = &_addr;
+ }
+ assert (H5F_addr_defined (addr));
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL, NULL))) {
HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL);
@@ -853,19 +872,25 @@ H5O_modify (H5F_t *f, haddr_t addr, H5G_entry_t *ent,
*-------------------------------------------------------------------------
*/
herr_t
-H5O_remove (H5F_t *f, haddr_t addr, H5G_entry_t *ent,
+H5O_remove (H5F_t *f, const haddr_t *addr, H5G_entry_t *ent,
const H5O_class_t *type, intn sequence)
{
H5O_t *oh = NULL;
intn i, seq;
+ haddr_t _addr;
FUNC_ENTER (H5O_remove, NULL, FAIL);
/* check args */
assert (f);
- assert (addr>0 || (ent && H5G_ent_addr (ent)>0));
assert (type);
- if (addr<=0) addr = H5G_ent_addr (ent);
+ if (!addr) {
+ if (!ent || H5G_ent_addr (ent, &_addr)<0) {
+ HRETURN_ERROR (H5E_OHDR, H5E_CANTINIT, FAIL);
+ }
+ addr = &_addr;
+ }
+ assert (H5F_addr_defined (addr));
/* load the object header */
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL, NULL))) {
@@ -936,7 +961,7 @@ H5O_alloc_extend_chunk (H5O_t *oh, intn chunkno, size_t size)
assert (chunkno>=0 && chunkno<oh->nchunks);
assert (size>0);
- if (H5O_NO_ADDR!=oh->chunk[chunkno].addr) {
+ if (H5F_addr_defined (&(oh->chunk[chunkno].addr))) {
HRETURN_ERROR (H5E_OHDR, H5E_NOSPACE, FAIL); /*chunk is on disk*/
}
@@ -1104,7 +1129,7 @@ H5O_alloc_new_chunk (H5F_t *f, H5O_t *oh, size_t size)
}
chunkno = oh->nchunks++;
oh->chunk[chunkno].dirty = TRUE;
- oh->chunk[chunkno].addr = H5O_NO_ADDR;
+ H5F_addr_undef (&(oh->chunk[chunkno].addr));
oh->chunk[chunkno].size = size;
oh->chunk[chunkno].image = p = H5MM_xcalloc (1, size);
@@ -1169,7 +1194,7 @@ H5O_alloc_new_chunk (H5F_t *f, H5O_t *oh, size_t size)
oh->mesg[found_null].type = H5O_CONT;
oh->mesg[found_null].dirty = TRUE;
cont = H5MM_xcalloc (1, sizeof(H5O_cont_t));
- cont->addr = H5O_NO_ADDR;
+ H5F_addr_undef (&(cont->addr));
cont->size = 0;
cont->chunkno = chunkno;
oh->mesg[found_null].native = cont;
@@ -1296,18 +1321,20 @@ H5O_alloc (H5F_t *f, H5O_t *oh, const H5O_class_t *type, size_t size)
*-------------------------------------------------------------------------
*/
herr_t
-H5O_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent, intn fwidth)
+H5O_debug (H5F_t *f, const haddr_t *addr, FILE *stream, intn indent,
+ intn fwidth)
{
H5O_t *oh = NULL;
intn i, chunkno;
size_t mesg_total=0, chunk_total=0;
int *sequence;
+ haddr_t tmp_addr;
FUNC_ENTER (H5O_debug, NULL, FAIL);
/* check args */
assert (f);
- assert (addr>=0);
+ assert (addr && H5F_addr_defined (addr));
assert (stream);
assert (indent>=0);
assert (fwidth>=0);
@@ -1346,10 +1373,15 @@ H5O_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent, intn fwidth)
fprintf (stream, "%*s%-*s %d\n", indent+3, "", MAX(0,fwidth-3),
"Dirty:",
(int)(oh->chunk[i].dirty));
- fprintf (stream, "%*s%-*s %lu\n", indent+3, "", MAX(0,fwidth-3),
- "Address:",
- (unsigned long)(oh->chunk[i].addr));
- if (0==i && oh->chunk[i].addr!=addr+H5O_SIZEOF_HDR(f)) {
+
+ fprintf (stream, "%*s%-*s ", indent+3, "", MAX(0,fwidth-3),
+ "Address:");
+ H5F_addr_print (stream, &(oh->chunk[i].addr));
+ fprintf (stream, "\n");
+
+ tmp_addr = *addr;
+ H5F_addr_inc (&tmp_addr, H5O_SIZEOF_HDR(f));
+ if (0==i && H5F_addr_ne (&(oh->chunk[i].addr), &tmp_addr)) {
fprintf (stream, "*** WRONG ADDRESS!\n");
}
fprintf (stream, "%*s%-*s %lu\n", indent+3, "", MAX(0,fwidth-3),
diff --git a/src/H5Ocont.c b/src/H5Ocont.c
index 88f5a46..4d63fdb 100644
--- a/src/H5Ocont.c
+++ b/src/H5Ocont.c
@@ -82,7 +82,7 @@ H5O_cont_decode (H5F_t *f, size_t raw_size, const uint8 *p)
/* decode */
cont = H5MM_xcalloc (1, sizeof(H5O_cont_t));
- H5F_decode_offset (f, p, cont->addr);
+ H5F_addr_decode (f, &p, &(cont->addr));
H5F_decode_length (f, p, cont->size);
FUNC_LEAVE ((void*)cont);
@@ -120,7 +120,7 @@ H5O_cont_encode (H5F_t *f, size_t size, uint8 *p, const void *_mesg)
assert (cont);
/* encode */
- H5F_encode_offset (f, p, cont->addr);
+ H5F_addr_encode (f, &p, &(cont->addr));
H5F_encode_length (f, p, cont->size);
FUNC_LEAVE (SUCCEED);
@@ -159,9 +159,11 @@ H5O_cont_debug (H5F_t *f, const void *_mesg, FILE *stream,
assert (indent>=0);
assert (fwidth>=0);
- fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth,
- "Continuation address:",
- (unsigned long)(cont->addr));
+ fprintf (stream, "%*s%-*s ", indent, "", fwidth,
+ "Continuation address:");
+ H5F_addr_print (stream, &(cont->addr));
+ fprintf (stream, "\n");
+
fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth,
"Continuation size in bytes:",
(unsigned long)(cont->size));
diff --git a/src/H5Oistore.c b/src/H5Oistore.c
index 1ed275e..89812a4 100644
--- a/src/H5Oistore.c
+++ b/src/H5Oistore.c
@@ -73,7 +73,7 @@ H5O_istore_decode (H5F_t *f, size_t raw_size, const uint8 *p)
/* decode */
mesg = H5MM_xcalloc (1, sizeof(H5O_istore_t));
- H5F_decode_offset (f, p, mesg->btree_addr);
+ H5F_addr_decode (f, &p, &(mesg->btree_addr));
mesg->ndims = *p++;
assert (raw_size == H5O_istore_size (f, mesg));
@@ -122,7 +122,7 @@ H5O_istore_encode (H5F_t *f, size_t raw_size, uint8 *p, const void *_mesg)
assert (p);
/* encode B-tree offset */
- H5F_encode_offset (f, p, mesg->btree_addr);
+ H5F_addr_encode (f, &p, &(mesg->btree_addr));
/* number of dimensions */
*p++ = mesg->ndims;
@@ -250,9 +250,11 @@ H5O_istore_debug (H5F_t *f, const void *_mesg, FILE *stream, intn indent,
assert (indent>=0);
assert (fwidth>=0);
- fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth,
- "B-tree address:",
- (unsigned long)(mesg->btree_addr));
+ fprintf (stream, "%*s%-*s ", indent, "", fwidth,
+ "B-tree address:");
+ H5F_addr_print (stream, &(mesg->btree_addr));
+ fprintf (stream, "\n");
+
fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth,
"Number of dimensions:",
(unsigned long)(mesg->ndims));
diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h
index c4ad1cb..d6c9ab2 100644
--- a/src/H5Oprivate.h
+++ b/src/H5Oprivate.h
@@ -29,7 +29,6 @@
#define H5O_NMESGS 32 /*initial number of messages */
#define H5O_NCHUNKS 8 /*initial number of chunks */
#define H5O_NEW_MESG (-1) /*new message */
-#define H5O_NO_ADDR (-1) /*no disk address yet */
#define H5O_ALL (-1) /*delete all messages of type */
#define H5O_VERSION 1
@@ -117,7 +116,7 @@ extern const H5O_class_t H5O_STD_STORE[1];
typedef struct H5O_std_store_t {
haddr_t off;
- haddr_t len;
+ size_t len;
} H5O_std_store_t;
/*
@@ -170,18 +169,18 @@ typedef struct H5O_stab_t {
-haddr_t H5O_new (H5F_t *f, intn nlink, size_t size_hint);
+herr_t H5O_new (H5F_t *f, intn nlink, size_t size_hint, haddr_t*);
intn H5O_link (H5F_t *f, H5G_entry_t *ent, intn adjust);
-void *H5O_read (H5F_t *f, haddr_t addr, H5G_entry_t *ent,
+void *H5O_read (H5F_t *f, const haddr_t *addr, H5G_entry_t *ent,
const H5O_class_t *type, intn sequence, void *mesg);
-const void *H5O_peek (H5F_t *f, haddr_t addr, const H5O_class_t *type,
+const void *H5O_peek (H5F_t *f, const haddr_t *addr, const H5O_class_t *type,
intn sequence);
-intn H5O_modify (H5F_t *f, haddr_t addr, H5G_entry_t *ent,
+intn H5O_modify (H5F_t *f, const haddr_t *addr, H5G_entry_t *ent,
const H5O_class_t *type, intn overwrite, const void *mesg);
-herr_t H5O_remove (H5F_t *f, haddr_t addr, H5G_entry_t *ent,
+herr_t H5O_remove (H5F_t *f, const haddr_t *addr, H5G_entry_t *ent,
const H5O_class_t *type, intn sequence);
herr_t H5O_reset (const H5O_class_t *type, void *native);
-herr_t H5O_debug (H5F_t *f, haddr_t addr, FILE *stream,
+herr_t H5O_debug (H5F_t *f, const haddr_t *addr, FILE *stream,
intn indent, intn fwidth);
#endif
diff --git a/src/H5Ostab.c b/src/H5Ostab.c
index cd8b708..c02885a 100644
--- a/src/H5Ostab.c
+++ b/src/H5Ostab.c
@@ -86,8 +86,8 @@ H5O_stab_decode (H5F_t *f, size_t raw_size, const uint8 *p)
/* decode */
stab = H5MM_xcalloc (1, sizeof(H5O_stab_t));
- H5F_decode_offset (f, p, stab->btree_addr);
- H5F_decode_offset (f, p, stab->heap_addr);
+ H5F_addr_decode (f, &p, &(stab->btree_addr));
+ H5F_addr_decode (f, &p, &(stab->heap_addr));
FUNC_LEAVE (stab);
}
@@ -124,8 +124,8 @@ H5O_stab_encode (H5F_t *f, size_t raw_size, uint8 *p, const void *_mesg)
assert (stab);
/* encode */
- H5F_encode_offset (f, p, stab->btree_addr);
- H5F_encode_offset (f, p, stab->heap_addr);
+ H5F_addr_encode (f, &p, &(stab->btree_addr));
+ H5F_addr_encode (f, &p, &(stab->heap_addr));
FUNC_LEAVE (SUCCEED);
}
@@ -207,12 +207,12 @@ H5O_stab_cache (H5G_type_t *cache_type, H5G_cache_t *cache, const void *_mesg)
cache->stab.btree_addr = stab->btree_addr;
cache->stab.heap_addr = stab->heap_addr;
} else {
- if (cache->stab.btree_addr != stab->btree_addr) {
+ if (H5F_addr_ne (&(cache->stab.btree_addr), &(stab->btree_addr))) {
modified = TRUE;
cache->stab.btree_addr = stab->btree_addr;
}
- if (cache->stab.heap_addr != stab->heap_addr) {
+ if (H5F_addr_ne (&(cache->stab.heap_addr), &(stab->heap_addr))) {
modified = TRUE;
cache->stab.heap_addr = stab->heap_addr;
}
@@ -318,13 +318,16 @@ H5O_stab_debug (H5F_t *f, const void *_mesg, FILE *stream, intn indent,
assert (indent>=0);
assert (fwidth>=0);
- fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth,
- "B-tree address:",
- (unsigned long)(stab->btree_addr));
- fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth,
- "Name heap address:",
- (unsigned long)(stab->heap_addr));
-
+ fprintf (stream, "%*s%-*s ", indent, "", fwidth,
+ "B-tree address:");
+ H5F_addr_print (stream, &(stab->btree_addr));
+ fprintf (stream, "\n");
+
+ fprintf (stream, "%*s%-*s ", indent, "", fwidth,
+ "Name heap address:");
+ H5F_addr_print (stream, &(stab->heap_addr));
+ fprintf (stream, "\n");
+
FUNC_LEAVE (SUCCEED);
}
diff --git a/src/H5Ostdst.c b/src/H5Ostdst.c
index 48c8c97..d0156f2 100644
--- a/src/H5Ostdst.c
+++ b/src/H5Ostdst.c
@@ -98,7 +98,7 @@ H5O_std_store_decode (H5F_t *f, size_t raw_size, const uint8 *p)
/* decode */
if((store = H5MM_xcalloc (1, sizeof(H5O_std_store_t)))!=NULL)
{
- H5F_decode_offset(f,p,store->off);
+ H5F_addr_decode (f, &p,&(store->off));
H5F_decode_length(f,p,store->len);
} /* end if */
@@ -146,7 +146,7 @@ H5O_std_store_encode (H5F_t *f, size_t raw_size, uint8 *p, const void *mesg)
assert (store);
/* encode */
- H5F_encode_offset(f,p,store->off);
+ H5F_addr_encode (f, &p, &(store->off));
H5F_encode_length(f,p,store->len);
FUNC_LEAVE (SUCCEED);
@@ -248,9 +248,11 @@ H5O_std_store_debug (H5F_t *f, const void *mesg, FILE *stream,
assert (indent>=0);
assert (fwidth>=0);
- fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth,
- "Offset:",
- (unsigned long)(store->off));
+ fprintf (stream, "%*s%-*s ", indent, "", fwidth,
+ "Offset:");
+ H5F_addr_print (stream, &(store->off));
+ fprintf (stream, "\n");
+
fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth,
"Length:",
(unsigned long)(store->len));
diff --git a/src/H5private.h b/src/H5private.h
index 12d8a59..68d5079 100644
--- a/src/H5private.h
+++ b/src/H5private.h
@@ -97,10 +97,13 @@
#endif
/*
- * File offsets.
+ * File addresses.
*/
-typedef off_t haddr_t;
-#define NO_ADDR (-1)
+typedef struct {
+ uint64 offset;
+} haddr_t;
+
+#define NO_ADDR NULL
/*
* Some compilers have problems declaring auto variables that point
diff --git a/src/Makefile.in b/src/Makefile.in
index c6f0a27..a083e22 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -15,10 +15,10 @@ PROGS=debug
# Source and object files for the library (lexicographically)...
LIB_SRC=H5.c H5A.c H5AC.c H5B.c H5C.c H5D.c H5Dconv.c H5E.c H5F.c H5Fcore.c \
- H5Fistore.c H5Flow.c H5Fsec2.c H5Fstdio.c H5G.c H5Gent.c H5Gnode.c \
- H5Gshad.c H5Gstab.c H5H.c H5M.c H5MF.c H5MM.c H5O.c H5Ocont.c \
- H5Oistore.c H5Oname.c H5Onull.c H5Osdtyp.c H5Osdim.c H5Ostab.c \
- H5Ostdst.c H5P.c H5T.c H5V.c
+ H5Ffamily.c H5Fistore.c H5Flow.c H5Fsec2.c H5Fsplit.c H5Fstdio.c \
+ H5G.c H5Gent.c H5Gnode.c H5Gshad.c H5Gstab.c H5H.c H5M.c H5MF.c \
+ H5MM.c H5O.c H5Ocont.c H5Oistore.c H5Oname.c H5Onull.c H5Osdtyp.c \
+ H5Osdim.c H5Ostab.c H5Ostdst.c H5P.c H5T.c H5V.c
LIB_OBJ=$(LIB_SRC:.c=.o)
diff --git a/src/debug.c b/src/debug.c
index 016eaf9..445ff67 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -47,21 +47,24 @@ main (int argc, char *argv[])
{
hid_t fid;
H5F_t *f;
- haddr_t addr = 0;
+ haddr_t addr;
uint8 sig[16];
intn i;
herr_t status = SUCCEED;
- haddr_t extra = 0;
+ haddr_t extra;
+ H5F_addr_reset (&addr);
+ H5F_addr_reset (&extra);
+
/*
* Parse command arguments.
*/
if (argc>2) {
printf ("New address: %s\n", argv[2]);
- addr = HDstrtol (argv[2], NULL, 0);
+ addr.offset = HDstrtol (argv[2], NULL, 0);
}
if (argc>3) {
- extra = HDstrtol (argv[3], NULL, 0);
+ extra.offset = HDstrtol (argv[3], NULL, 0);
}
/*
@@ -79,8 +82,10 @@ main (int argc, char *argv[])
/*
* Read the signature at the specified file position.
*/
- printf ("Reading signature at byte %lu\n", (unsigned long)addr);
- if (H5F_block_read (f, addr, sizeof(sig), sig)<0) {
+ printf ("Reading signature at address ");
+ H5F_addr_print (stdout, &addr);
+ printf (" (rel)\n");
+ if (H5F_block_read (f, &addr, sizeof(sig), sig)<0) {
fprintf (stderr, "cannot read signature\n");
HDexit (3);
}
@@ -89,19 +94,19 @@ main (int argc, char *argv[])
/*
* Debug the boot block.
*/
- status = H5F_debug (f, 0, stdout, 0, VCOL);
+ status = H5F_debug (f, &addr, stdout, 0, VCOL);
} else if (!HDmemcmp (sig, H5H_MAGIC, H5H_SIZEOF_MAGIC)) {
/*
* Debug a heap.
*/
- status = H5H_debug (f, addr, stdout, 0, VCOL);
+ status = H5H_debug (f, &addr, stdout, 0, VCOL);
} else if (!HDmemcmp (sig, H5G_NODE_MAGIC, H5G_NODE_SIZEOF_MAGIC)) {
/*
* Debug a symbol table node.
*/
- status = H5G_node_debug (f, addr, stdout, 0, VCOL, extra);
+ status = H5G_node_debug (f, &addr, stdout, 0, VCOL, &extra);
} else if (!HDmemcmp (sig, H5B_MAGIC, H5B_SIZEOF_MAGIC)) {
/*
@@ -112,7 +117,7 @@ main (int argc, char *argv[])
H5B_subid_t subtype = sig[H5B_SIZEOF_MAGIC];
switch (subtype) {
case H5B_SNODE_ID:
- status = H5G_node_debug (f, addr, stdout, 0, VCOL, extra);
+ status = H5G_node_debug (f, &addr, stdout, 0, VCOL, &extra);
break;
default:
@@ -125,7 +130,7 @@ main (int argc, char *argv[])
* This could be an object header. Since they don't have a signature
* it's a somewhat "ify" detection.
*/
- status = H5O_debug (f, addr, stdout, 0, VCOL);
+ status = H5O_debug (f, &addr, stdout, 0, VCOL);
} else {
/*
diff --git a/test/hyperslab.c b/test/hyperslab.c
index b07a8fa..f985608 100644
--- a/test/hyperslab.c
+++ b/test/hyperslab.c
@@ -166,15 +166,16 @@ test_fill (size_t nx, size_t ny, size_t nz,
if (0==ny) {
ndims = 1;
ny = nz = 1;
- sprintf (dim, "%d", nx);
+ sprintf (dim, "%lu", (unsigned long)nx);
} else {
ndims = 2;
nz = 1;
- sprintf (dim, "%dx%d", nx, ny);
+ sprintf (dim, "%lux%lu", (unsigned long)nx, (unsigned long)ny);
}
} else {
ndims = 3;
- sprintf (dim, "%dx%dx%d", nx, ny, nz);
+ sprintf (dim, "%lux%lux%lu",
+ (unsigned long)nx, (unsigned long)ny, (unsigned long)nz);
}
sprintf (s, "Testing hyperslab fill %-11s variable hyperslab ", dim);
printf ("%-70s", s);
@@ -326,15 +327,16 @@ test_copy (int mode,
if (0==ny) {
ndims = 1;
ny = nz = 1;
- sprintf (dim, "%d", nx);
+ sprintf (dim, "%lu", (unsigned long)nx);
} else {
ndims = 2;
nz = 1;
- sprintf (dim, "%dx%d", nx, ny);
+ sprintf (dim, "%lux%lu", (unsigned long)nx, (unsigned long)ny);
}
} else {
ndims = 3;
- sprintf (dim, "%dx%dx%d", nx, ny, nz);
+ sprintf (dim, "%lux%lux%lu",
+ (unsigned long)nx, (unsigned long)ny, (unsigned long)nz);
}
switch (mode) {
@@ -760,7 +762,8 @@ test_transpose (size_t nx, size_t ny)
size_t size[2];
char s[256];
- sprintf (s, "Testing 2d transpose by stride %4dx%-4d", nx, ny);
+ sprintf (s, "Testing 2d transpose by stride %4lux%-lud",
+ (unsigned long)nx, (unsigned long)ny);
printf ("%-70s", s);
fflush (stdout);
@@ -867,8 +870,9 @@ test_sub_super (size_t nx, size_t ny)
int i, j;
char s[256];
- sprintf (s, "Testing image sampling %4dx%-4d to %4dx%-4d ",
- 2*nx, 2*ny, nx, ny);
+ sprintf (s, "Testing image sampling %4lux%-4lu to %4lux%-4lu ",
+ (unsigned long)(2*nx), (unsigned long)(2*ny),
+ (unsigned long)nx, (unsigned long)ny);
printf ("%-70s", s);
fflush (stdout);
@@ -914,8 +918,9 @@ test_sub_super (size_t nx, size_t ny)
* Test replicating pixels to produce an image twice as large in each
* dimension.
*/
- sprintf (s, "Testing image sampling %4dx%-4d to %4dx%-4d ",
- nx, ny, 2*nx, 2*ny);
+ sprintf (s, "Testing image sampling %4lux%-4lu to %4lux%-4lu ",
+ (unsigned long)nx, (unsigned long)ny,
+ (unsigned long)(2*nx), (unsigned long)(2*ny));
printf ("%-70s", s);
fflush (stdout);
diff --git a/test/istore.c b/test/istore.c
index c50ef3f..6487a30 100644
--- a/test/istore.c
+++ b/test/istore.c
@@ -14,14 +14,25 @@
#include <H5Oprivate.h>
#include <H5Vprivate.h>
-#define FILENAME "istore.h5"
+#if 0
+# define FILETYPE H5F_LOW_DFLT
+# define FILENAME "istore.h5"
+#elif 0
+# define FILETYPE H5F_LOW_FAM
+# define FILENAME "istore-%05d.h5"
+#else
+# define FILETYPE H5F_LOW_SPLIT
+# define FILENAME "istore-split"
+#endif
#define TEST_SMALL 0x0001
#define TEST_MEDIUM 0x0002
+#define TEST_LARGE 0x0004
#define AT() printf (" at %s:%d in %s()...\n", \
__FILE__, __LINE__, __FUNCTION__);
-
+
+size_t align_g[3] = {50, 50, 50};
/*-------------------------------------------------------------------------
@@ -99,9 +110,16 @@ new_object (H5F_t *f, const char *name, size_t ndims)
}
/* Add the indexed-storage message */
- for (i=0; i<ndims; i++) alignment[i] = 2;
+ for (i=0; i<ndims; i++) {
+ if (i<NELMTS (align_g)) {
+ alignment[i] = align_g[i];
+ } else {
+ alignment[i] = 2;
+ }
+ }
+
H5F_istore_new (f, &istore, ndims, alignment);
- if (H5O_modify (f, H5O_NO_ADDR, handle, H5O_ISTORE, H5O_NEW_MESG,
+ if (H5O_modify (f, NO_ADDR, handle, H5O_ISTORE, H5O_NEW_MESG,
&istore)<0) {
printf ("*FAILED*\n");
if (!isatty (1)) {
@@ -140,7 +158,6 @@ test_create (H5F_t *f, const char *prefix)
char name[256];
printf ("%-70s", "Testing istore create");
- fflush (stdout);
for (i=1; i<=H5O_ISTORE_NDIMS; i++) {
sprintf (name, "%s_%02d", prefix, i);
@@ -191,21 +208,21 @@ test_extend (H5F_t *f, const char *prefix,
if (!ny) {
ndims = 1;
ny = nz = 1;
- sprintf (dims, "%d", nx);
+ sprintf (dims, "%lu", (unsigned long)nx);
} else {
ndims = 2;
nz = 1;
- sprintf (dims, "%dx%d", nx, ny);
+ sprintf (dims, "%lux%lu", (unsigned long)nx, (unsigned long)ny);
}
} else {
ndims = 3;
- sprintf (dims, "%dx%dx%d", nx, ny, nz);
+ sprintf (dims, "%lux%lux%lu",
+ (unsigned long)nx, (unsigned long)ny, (unsigned long)nz);
}
sprintf (s, "Testing istore extend: %s", dims);
printf ("%-70s", s);
- fflush (stdout);
buf = H5MM_xmalloc (nx*ny*nz);
check = H5MM_xmalloc (nx*ny*nz);
whole = H5MM_xcalloc (nx*ny*nz, 1);
@@ -219,7 +236,7 @@ test_extend (H5F_t *f, const char *prefix,
}
goto error;
}
- if (NULL==H5O_read (f, H5O_NO_ADDR, handle, H5O_ISTORE, 0, &istore)) {
+ if (NULL==H5O_read (f, NO_ADDR, handle, H5O_ISTORE, 0, &istore)) {
puts ("*FAILED*");
if (!isatty (1)) {
AT ();
@@ -274,7 +291,6 @@ test_extend (H5F_t *f, const char *prefix,
printf ("), %d element%s", nelmts, 1==nelmts?"":"s");
if (0==nelmts) printf (" *SKIPPED*");
printf ("\n");
- fflush (stdout);
#endif
/* Fill the source array */
@@ -309,7 +325,7 @@ test_extend (H5F_t *f, const char *prefix,
printf (" Wrote:\n");
print_array (buf, size[0], size[1], size[2]);
printf (" Read:\n");
- print_array (buf, size[0], size[1], size[2]);
+ print_array (check, size[0], size[1], size[2]);
}
goto error;
}
@@ -395,7 +411,7 @@ test_sparse (H5F_t *f, const char *prefix, size_t nblocks,
{
intn ndims, ctr;
char dims[64], s[256], name[256];
- size_t offset[3], size[3];
+ size_t offset[3], size[3], total=0;
H5G_entry_t *handle = NULL;
H5O_istore_t istore;
uint8 *buf = NULL;
@@ -404,20 +420,20 @@ test_sparse (H5F_t *f, const char *prefix, size_t nblocks,
if (!ny) {
ndims = 1;
ny = nz = 1;
- sprintf (dims, "%d", nx);
+ sprintf (dims, "%lu", (unsigned long)nx);
} else {
ndims = 2;
nz = 1;
- sprintf (dims, "%dx%d", nx, ny);
+ sprintf (dims, "%lux%lu", (unsigned long)nx, (unsigned long)ny);
}
} else {
ndims = 3;
- sprintf (dims, "%dx%dx%d", nx, ny, nz);
+ sprintf (dims, "%lux%lux%lu",
+ (unsigned long)nx, (unsigned long)ny, (unsigned long)nz);
}
sprintf (s, "Testing istore sparse: %s", dims);
printf ("%-70s", s);
- fflush (stdout);
buf = H5MM_xmalloc (nx*ny*nz);
/* Build the new empty object */
@@ -429,7 +445,7 @@ test_sparse (H5F_t *f, const char *prefix, size_t nblocks,
}
goto error;
}
- if (NULL==H5O_read (f, H5O_NO_ADDR, handle, H5O_ISTORE, 0, &istore)) {
+ if (NULL==H5O_read (f, NO_ADDR, handle, H5O_ISTORE, 0, &istore)) {
puts ("*FAILED*");
if (!isatty (1)) {
AT ();
@@ -453,16 +469,20 @@ test_sparse (H5F_t *f, const char *prefix, size_t nblocks,
if (!isatty (1)) {
AT ();
printf (" Write failed: ctr=%d\n", ctr);
- printf (" offset=(%d", offset[0]);
- if (ndims>1) printf (",%d", offset[1]);
- if (ndims>2) printf (",%d", offset[2]);
- printf ("), size=(%d", size[0]);
- if (ndims>1) printf (",%d", size[1]);
- if (ndims>2) printf (",%d", size[2]);
+ printf (" offset=(%lu", (unsigned long)(offset[0]));
+ if (ndims>1) printf (",%lu", (unsigned long)(offset[1]));
+ if (ndims>2) printf (",%lu", (unsigned long)(offset[2]));
+ printf ("), size=(%lu", (unsigned long)(size[0]));
+ if (ndims>1) printf (",%lu", (unsigned long)(size[1]));
+ if (ndims>2) printf (",%lu", (unsigned long)(size[2]));
printf (")\n");
}
goto error;
}
+ total += nx*ny*nz;
+#if 0
+ printf ("ctr: ctr=%d, total=%lu\n", ctr, (unsigned long)total);
+#endif
/* We don't test reading yet.... */
}
@@ -502,6 +522,12 @@ main (int argc, char *argv[])
herr_t status;
int nerrors = 0;
uintn size_of_test;
+ uint8 offset_size;
+ H5G_entry_t *ent = NULL;
+ hid_t template_id;
+ file_create_temp_t *creation_template = NULL;
+
+ setbuf (stdout, NULL);
/* Parse arguments or assume `small' */
if (1==argc) {
@@ -513,6 +539,8 @@ main (int argc, char *argv[])
size_of_test |= TEST_SMALL;
} else if (!strcmp (argv[i], "medium")) {
size_of_test |= TEST_MEDIUM;
+ } else if (!strcmp (argv[i], "large")) {
+ size_of_test |= TEST_LARGE;
} else {
printf ("unrecognized argument: %s\n", argv[i]);
exit (1);
@@ -522,18 +550,47 @@ main (int argc, char *argv[])
printf ("Test sizes: ");
if (size_of_test & TEST_SMALL) printf (" SMALL");
if (size_of_test & TEST_MEDIUM) printf (" MEDIUM");
+ if (size_of_test & TEST_LARGE) printf (" LARGE");
printf ("\n");
-
+
+ /*
+ * Use larger file addresses...
+ */
+ offset_size = 8;
+ template_id = H5C_copy (H5C_get_default_atom (H5_TEMPLATE));
+ H5Csetparm (template_id, H5_OFFSET_SIZE, &offset_size);
+ creation_template = H5Aatom_object (template_id);
/* Create the test file */
- if (NULL==(f=H5F_open (H5F_LOW_DFLT, FILENAME,
+ if (NULL==(f=H5F_open (FILETYPE, FILENAME,
(H5F_ACC_CREAT|H5F_ACC_WRITE|H5F_ACC_TRUNC|
H5F_ACC_DEBUG),
- NULL))) {
+ creation_template))) {
printf ("Cannot create file %s; test aborted\n", FILENAME);
exit (1);
}
+#if 0
+ {
+ /*
+ * For testing file families, fool the library into thinking it already
+ * allocated a whole bunch of data.
+ */
+ haddr_t addr;
+ addr.offset = (uint64)1<<33; /*8GB*/
+ H5F_low_seteof (f->shared->lf, &addr);
+ }
+#endif
+
+ /*
+ * By creating a group we cause the library to emit it's debugging
+ * diagnostic messages before we begin testing...
+ */
+ ent = H5G_new (f, "flushing_diagnostics", 0);
+ H5G_close (f, ent);
+ ent = NULL;
+
+
/*
* Creation test: Creates empty objects with various raw data sizes
* and alignments.
@@ -557,7 +614,6 @@ main (int argc, char *argv[])
status = test_extend (f, "extend", 10, 400, 10);
nerrors += status<0 ? 1 : 0;
}
-
if (size_of_test & TEST_SMALL) {
status = test_sparse (f, "sparse", 100, 5, 0, 0);
nerrors += status<0 ? 1 : 0;
@@ -574,6 +630,11 @@ main (int argc, char *argv[])
status = test_sparse (f, "sparse", 2000, 4, 2, 3);
nerrors += status<0 ? 1 : 0;
}
+ if (size_of_test & TEST_LARGE) {
+ status = test_sparse (f, "sparse", 800, 50, 50, 50);
+ nerrors += status<0 ? 1 : 0;
+ }
+
/* Close the test file and exit */
H5F_close (f);
diff --git a/test/theap.c b/test/theap.c
index 1dc38e1..d46726f 100644
--- a/test/theap.c
+++ b/test/theap.c
@@ -45,10 +45,11 @@ test_heap (void)
int i, j;
hid_t fid;
H5F_t *f;
- off_t heap;
+ haddr_t heap_addr;
char buf[NOBJS+8];
const char *s;
- off_t obj[NOBJS];
+ size_t obj[NOBJS];
+ herr_t status;
MESSAGE (5, ("Testing Heaps\n"));
@@ -59,8 +60,8 @@ test_heap (void)
CHECK (f, NULL, "H5Aatom_object");
/* Create a new heap */
- heap = H5H_new (f, H5H_LOCAL, 0);
- CHECK_I (heap, "H5H_new");
+ status = H5H_new (f, H5H_LOCAL, 0, &heap_addr/*out*/);
+ CHECK_I (status, "H5H_new");
/* Add stuff to the heap */
for (i=0; i<NOBJS; i++) {
@@ -68,8 +69,8 @@ test_heap (void)
for (j=4; j<i; j++) buf[j] = '0' + j%10;
if (j>4) buf[j] = '\0';
- obj[i] = H5H_insert (f, heap, strlen(buf)+1, buf);
- CHECK_I (heap, "H5H_insert");
+ obj[i] = H5H_insert (f, &heap_addr, strlen(buf)+1, buf);
+ CHECK_I (obj[i], "H5H_insert");
}
/* Flush the cache and invalidate everything */
@@ -77,7 +78,7 @@ test_heap (void)
/* Read the objects back out */
for (i=0; i<NOBJS; i++) {
- s = H5H_peek (f, heap, obj[i]);
+ s = H5H_peek (f, &heap_addr, obj[i]);
MESSAGE (8, ("object is `%s'\n", s));
}
diff --git a/test/tohdr.c b/test/tohdr.c
index c8da399..2ea0896 100644
--- a/test/tohdr.c
+++ b/test/tohdr.c
@@ -49,7 +49,7 @@ test_ohdr (void)
{
hid_t fid;
H5F_t *f;
- haddr_t oh;
+ haddr_t oh_addr;
H5O_stab_t stab, ro;
herr_t status;
void *ptr;
@@ -66,84 +66,89 @@ test_ohdr (void)
/* the new object header */
MESSAGE (8, ("Creating new object header...\n"));
- oh = H5O_new (f, 1, 64);
+ status = H5O_new (f, 1, 64, &oh_addr/*out*/);
+ CHECK_I (status, "H5O_new");
/*
* Test creation of a new message.
*/
MESSAGE (8, ("Creating new message...\n"));
- stab.btree_addr = 11111111;
- stab.heap_addr = 22222222;
- status = H5O_modify (f, oh, NULL, H5O_STAB, H5O_NEW_MESG, &stab);
+ stab.btree_addr.offset = 11111111;
+ stab.heap_addr.offset = 22222222;
+ status = H5O_modify (f, &oh_addr, NULL, H5O_STAB, H5O_NEW_MESG, &stab);
VERIFY (status, 0, "H5O_modify");
H5AC_flush (f, NULL, 0, TRUE);
- ptr = H5O_read (f, oh, NULL, H5O_STAB, 0, &ro);
+ ptr = H5O_read (f, &oh_addr, NULL, H5O_STAB, 0, &ro);
CHECK_PTR (ptr, "H5O_read");
VERIFY (ptr, &ro, "H5O_read");
- VERIFY (ro.btree_addr, stab.btree_addr, "H5O_read");
- VERIFY (ro.heap_addr, stab.heap_addr, "H5O_read");
+ VERIFY (ro.btree_addr.offset, stab.btree_addr.offset, "H5O_read");
+ VERIFY (ro.heap_addr.offset, stab.heap_addr.offset, "H5O_read");
/*
* Test modification of an existing message.
*/
MESSAGE (8, ("Modifying message...\n"));
- stab.btree_addr = 33333333;
- stab.heap_addr = 44444444;
- status = H5O_modify (f, oh, NULL, H5O_STAB, 0, &stab);
+ stab.btree_addr.offset = 33333333;
+ stab.heap_addr.offset = 44444444;
+ status = H5O_modify (f, &oh_addr, NULL, H5O_STAB, 0, &stab);
VERIFY (status, 0, "H5O_modify");
H5AC_flush (f, NULL, 0, TRUE);
- ptr = H5O_read (f, oh, NULL, H5O_STAB, 0, &ro);
+ ptr = H5O_read (f, &oh_addr, NULL, H5O_STAB, 0, &ro);
CHECK_PTR (ptr, "H5O_read");
VERIFY (ptr, &ro, "H5O_read");
- VERIFY (ro.btree_addr, stab.btree_addr, "H5O_read");
- VERIFY (ro.heap_addr, stab.heap_addr, "H5O_read");
+ VERIFY (ro.btree_addr.offset, stab.btree_addr.offset, "H5O_read");
+ VERIFY (ro.heap_addr.offset, stab.heap_addr.offset, "H5O_read");
/*
* Test creation of a second message of the same type with a symbol
* table.
*/
MESSAGE (8, ("Creating a duplicate message...\n"));
- ent.header = 0;
+ ent.header.offset = 0;
ent.type = H5G_NOTHING_CACHED;
ent.dirty = FALSE;
- stab.btree_addr = 55555555;
- stab.heap_addr = 66666666;
- status = H5O_modify (f, oh, &ent, H5O_STAB, H5O_NEW_MESG, &stab);
+ stab.btree_addr.offset = 55555555;
+ stab.heap_addr.offset = 66666666;
+ status = H5O_modify (f, &oh_addr, &ent, H5O_STAB, H5O_NEW_MESG, &stab);
VERIFY (status, 1, "H5O_modify");
VERIFY (ent.dirty, TRUE, "H5O_modify");
VERIFY (ent.type, H5G_CACHED_STAB, "H5O_modify");
- VERIFY (ent.cache.stab.heap_addr, stab.heap_addr, "H5O_modify");
- VERIFY (ent.cache.stab.btree_addr, stab.btree_addr, "H5O_modify");
+ VERIFY (ent.cache.stab.heap_addr.offset, stab.heap_addr.offset,
+ "H5O_modify");
+ VERIFY (ent.cache.stab.btree_addr.offset, stab.btree_addr.offset,
+ "H5O_modify");
H5AC_flush (f, NULL, 0, TRUE);
- ptr = H5O_read (f, oh, NULL, H5O_STAB, 1, &ro);
+ ptr = H5O_read (f, &oh_addr, NULL, H5O_STAB, 1, &ro);
CHECK_PTR (ptr, "H5O_read");
VERIFY (ptr, &ro, "H5O_read");
- VERIFY (ro.btree_addr, stab.btree_addr, "H5O_read");
- VERIFY (ro.heap_addr, stab.heap_addr, "H5O_read");
+ VERIFY (ro.btree_addr.offset, stab.btree_addr.offset, "H5O_read");
+ VERIFY (ro.heap_addr.offset, stab.heap_addr.offset, "H5O_read");
/*
* Test modification of the second message with a symbol table.
*/
MESSAGE (8, ("Modifying the duplicate message...\n"));
ent.dirty = FALSE;
- stab.btree_addr = 77777777;
- stab.heap_addr = 88888888;
- status = H5O_modify (f, oh, &ent, H5O_STAB, 1, &stab);
+ stab.btree_addr.offset = 77777777;
+ stab.heap_addr.offset = 88888888;
+ status = H5O_modify (f, &oh_addr, &ent, H5O_STAB, 1, &stab);
VERIFY (status, 1, "H5O_modify");
VERIFY (ent.dirty, TRUE, "H5O_modify");
VERIFY (ent.type, H5G_CACHED_STAB, "H5O_modify");
- VERIFY (ent.cache.stab.heap_addr, stab.heap_addr, "H5O_modify");
- VERIFY (ent.cache.stab.btree_addr, stab.btree_addr, "H5O_modify");
+ VERIFY (ent.cache.stab.heap_addr.offset, stab.heap_addr.offset,
+ "H5O_modify");
+ VERIFY (ent.cache.stab.btree_addr.offset, stab.btree_addr.offset,
+ "H5O_modify");
H5AC_flush (f, NULL, 0, TRUE);
- ptr = H5O_read (f, oh, NULL, H5O_STAB, 1, &ro);
+ ptr = H5O_read (f, &oh_addr, NULL, H5O_STAB, 1, &ro);
CHECK_PTR (ptr, "H5O_read");
VERIFY (ptr, &ro, "H5O_read");
- VERIFY (ro.btree_addr, stab.btree_addr, "H5O_read");
- VERIFY (ro.heap_addr, stab.heap_addr, "H5O_read");
+ VERIFY (ro.btree_addr.offset, stab.btree_addr.offset, "H5O_read");
+ VERIFY (ro.heap_addr.offset, stab.heap_addr.offset, "H5O_read");
/*
* Test creation of a bunch of messages one after another to see
@@ -151,9 +156,9 @@ test_ohdr (void)
*/
MESSAGE (8, ("Overflowing header in core...\n"));
for (i=0; i<40; i++) {
- stab.btree_addr = (i+1)*1000 + 1;
- stab.heap_addr = (i+1)*1000 + 2;
- status = H5O_modify (f, oh, NULL, H5O_STAB, H5O_NEW_MESG, &stab);
+ stab.btree_addr.offset = (i+1)*1000 + 1;
+ stab.heap_addr.offset = (i+1)*1000 + 2;
+ status = H5O_modify (f, &oh_addr, NULL, H5O_STAB, H5O_NEW_MESG, &stab);
VERIFY (status, 2+i, "H5O_modify");
}
H5AC_flush (f, NULL, 0, TRUE);
@@ -164,9 +169,9 @@ test_ohdr (void)
*/
MESSAGE (8, ("Overflowing header on disk...\n"));
for (i=0; i<10; i++) {
- stab.btree_addr = (i+1)*1000 + 10;
- stab.heap_addr = (i+1)*1000 + 20;
- status = H5O_modify (f, oh, NULL, H5O_STAB, H5O_NEW_MESG, &stab);
+ stab.btree_addr.offset = (i+1)*1000 + 10;
+ stab.heap_addr.offset = (i+1)*1000 + 20;
+ status = H5O_modify (f, &oh_addr, NULL, H5O_STAB, H5O_NEW_MESG, &stab);
VERIFY (status, 42+i, "H5O_modify");
H5AC_flush (f, NULL, 0, TRUE);
}
@@ -174,7 +179,7 @@ test_ohdr (void)
/*
* Delete all symbol table messages.
*/
- status = H5O_remove (f, oh, NULL, H5O_STAB, H5O_ALL);
+ status = H5O_remove (f, &oh_addr, NULL, H5O_STAB, H5O_ALL);
CHECK_I (status, "H5O_remove");
/* close the file */
diff --git a/test/tstab.c b/test/tstab.c
index 9bac3b7..e2384f8 100644
--- a/test/tstab.c
+++ b/test/tstab.c
@@ -56,6 +56,7 @@ test_1 (void)
herr_t status;
H5O_name_t name_mesg;
void *status_ptr;
+ hbool_t b;
MESSAGE (2, ("........non-directory files\n"));
@@ -82,20 +83,18 @@ test_1 (void)
/*
* Test 1B: Attempt to read the root object using the name `/'.
*/
- HDmemset (&dir_ent, 0, sizeof(H5G_entry_t));
- HDmemset (&ent1, 0, sizeof(H5G_entry_t));
+ memset (&dir_ent, 0xff, sizeof(H5G_entry_t));
+ memset (&ent1, 0xff, sizeof(H5G_entry_t));
status = H5G_find (f, "/", &dir_ent, &ent1);
CHECK_I (status, "H5G_find");
- VERIFY (dir_ent.header, 0, "H5G_find");
- VERIFY (ent1.header, obj1->header, "H5G_find");
- /* is it really the root symbol? */
- VERIFY (dir_ent.header, 0, "H5G_insert");
- VERIFY (obj1->header, f->shared->root_sym->header, "H5G_insert");
+ /* Is it really the root object? */
+ b = H5F_addr_defined (&(dir_ent.header));
+ VERIFY (b, FALSE, "H5G_create");
+ b = H5F_addr_eq (&(ent1.header), &(obj1->header));
+ VERIFY (b, TRUE, "H5G_create");
-
-
/*
* Test 1C: Add a second object to the file to see if the first object
* gets moved into the new root directory along with the second object.
@@ -106,10 +105,13 @@ test_1 (void)
CHECK_PTR (obj2, "H5G_new");
/* try to read the first object */
- HDmemset (&ent1, 0, sizeof(H5G_entry_t));
+ HDmemset (&ent1, 0xff, sizeof(H5G_entry_t));
status = H5G_find (f, "/Root Object", NULL, &ent1);
CHECK_I (status, "H5G_find");
- VERIFY (ent1.header, obj1->header, "H5G_find");
+ b = H5F_addr_defined (&(ent1.header));
+ VERIFY (b, TRUE, "H5G_create");
+ b = H5F_addr_eq (&(ent1.header), &(obj1->header));
+ VERIFY (b, TRUE, "H5G_create");
/* close the objects */
H5G_close (f, obj1);
@@ -120,7 +122,7 @@ test_1 (void)
/* close the file */
H5Fclose (fid);
-
+
/*
* Test 1D: Create an empty file and add a non-directory object
@@ -136,7 +138,7 @@ test_1 (void)
/* create the object */
obj1 = H5G_create (f, "/foo", 0);
- CHECK_PTR (obj1, "H5G_new");
+ CHECK_PTR (obj1, "H5G_create");
/* does it have the correct name message? */
status_ptr = H5O_read (f, NO_ADDR, obj1, H5O_NAME, 0, &name_mesg);
@@ -153,25 +155,20 @@ test_1 (void)
HDmemset (&ent1, 0, sizeof(H5G_entry_t));
status = H5G_find (f, "/", &dir_ent, &ent1);
CHECK_I (status, "H5G_find");
- VERIFY (dir_ent.header, 0, "H5G_find");
- VERIFY (ent1.header, obj1->header, "H5G_find");
-
- /* is it really the root symbol? */
- VERIFY (dir_ent.header, 0, "H5G_insert");
- VERIFY (obj1->header, f->shared->root_sym->header, "H5G_insert");
+ b = H5F_addr_defined (&(dir_ent.header));
+ VERIFY (b, FALSE, "H5G_create");
+ b = H5F_addr_eq (&(ent1.header), &(obj1->header));
+ VERIFY (b, TRUE, "H5G_create");
/* now as `/foo' */
HDmemset (&dir_ent, 0, sizeof(H5G_entry_t));
HDmemset (&ent1, 0, sizeof(H5G_entry_t));
status = H5G_find (f, "/foo", &dir_ent, &ent1);
CHECK_I (status, "H5G_find");
- VERIFY (dir_ent.header, 0, "H5G_find");
- VERIFY (ent1.header, obj1->header, "H5G_find");
-
- /* is it really the root symbol? */
- VERIFY (dir_ent.header, 0, "H5G_insert");
- VERIFY (obj1->header, f->shared->root_sym->header, "H5G_insert");
-
+ b = H5F_addr_defined (&(dir_ent.header));
+ VERIFY (b, FALSE, "H5G_create");
+ b = H5F_addr_eq (&(ent1.header), &(obj1->header));
+ VERIFY (b, TRUE, "H5G_find");
/*
@@ -187,7 +184,8 @@ test_1 (void)
HDmemset (&ent1, 0, sizeof(H5G_entry_t));
status = H5G_find (f, "/foo", NULL, &ent1);
CHECK_I (status, "H5G_find");
- VERIFY (ent1.header, obj1->header, "H5G_find");
+ b = H5F_addr_eq (&(ent1.header), &(obj1->header));
+ VERIFY (b, TRUE, "H5G_find");
/* the first object should not have a name message */
status_ptr = H5O_read (f, NO_ADDR, obj1, H5O_NAME, 0, &name_mesg);