diff options
author | Robb Matzke <matzke@llnl.gov> | 1997-11-14 14:42:14 (GMT) |
---|---|---|
committer | Robb Matzke <matzke@llnl.gov> | 1997-11-14 14:42:14 (GMT) |
commit | cdeeb5553a3920565d87201761dadd1fe32aa3b1 (patch) | |
tree | a209c61f85983c1a76bf5c65d1f3285c4861ec46 /src | |
parent | 73897627660169de753597b9ff045d3112646506 (diff) | |
download | hdf5-cdeeb5553a3920565d87201761dadd1fe32aa3b1.zip hdf5-cdeeb5553a3920565d87201761dadd1fe32aa3b1.tar.gz hdf5-cdeeb5553a3920565d87201761dadd1fe32aa3b1.tar.bz2 |
[svn-r136] ./MANIFEST
./src/Makefile.in
Added H5Ffamily.c and H5Fsplit.c
./src/H5B.c
./src/H5Bprivate.h
./src/H5Gnode.c
Added `const' to sublass arguments.
./src/H5F.c
./src/H5Flow.c
./src/H5Fsec2.c
Make sure file buffers get flushed during a call to
H5Fflush(). Check for overflow in address encoding and decoding.
./src/H5Ffam.c
./src/H5Fprivate.c
./test/istore.c
Implementation of file families so 32-bit machines can access
64-bit files.
./src/H5Oprivate.h
Removed H5O_NO_ADDR constant.
./config/freebsd2.2.1
./config/linux
Added -DH5G_DEBUG and -DH5F_DEBUG to the list of debugging flags.
./html/H5.format.html
Changed some <offset>-sized things to <length>-sized things.
./src/H5AC.c
./src/H5ACprivate.h
./src/H5B.c
./src/H5Bprivate.h
./src/H5C.c
./src/H5D.c
./src/H5F.c
./src/H5Fcore.c
./src/H5Fistore.c
./src/H5Flow.c
./src/H5Fprivate.h
./src/H5Fsec2.c
./src/H5Fstdio.c
./src/H5G.c
./src/H5Gent.c
./src/H5Gnode.c
./src/H5Gpkg.h
./src/H5Gprivate.h
./src/H5Gshad.c
./src/H5Gstab.c
./src/H5H.c
./src/H5Hprivate.h
./src/H5MF.c
./src/H5MFprivate.h
./src/H5O.c
./src/H5Ocont.c
./src/H5Oistore.c
./src/H5Oprivate.h
./src/H5Ostab.c
./src/H5Ostdst.c
./src/H5pivate.h
./src/debug.c
./test/istore.c
./test/theap.c
./test/tohdr.c
./test/tstab.c
Lots of changes caused by generalizing addresses. The haddr_t
is now a struct, so you can no longer perform arithmetic on
it. But since it's small, simple, and often used, storage is
allocated like with an integer. But we always pass them
around by reference. That is, when using an address in
another struct, allocate space:
struct my_struct {
char *name;
haddr_t address;
} x;
But when passing it to a function, pass by reference:
H5F_addr_print (stderr, &(x.address));
Addresses should be initialized with
H5F_addr_undef (&(x.address));
Functions for operating on addresses are in H5Flow.c and begin
with H5F_addr_... Functions never return haddr_t or haddr_t*;
they always pass them through arguments instead. A function
that returns an address through an argument does so with its
last argument and it is marked with `/*out*/'. Calls to such
functions also mark output-only arguments with `/*out*/'
./src/H5Fsplit.c (new)
A two-member family where all meta data goes in the first
member and all raw data goes in the second member.
./src/H5B.c
./src/H5D.c
./src/H5F.c
./src/H5Ffamily.c
./src/H5Fistore.c
./src/H5Flow.c
./src/H5Fprivate.h
./src/H5Fsec2.c
./src/H5Fstdio.c
./src/H5Gnode.c
./src/H5H.c
./src/H5MF.c
./src/H5MFprivate.h
./src/H5O.c
Differentiate between meta data storage and raw data
storage. Provide a mechanism so that the file driver can
extend the file to allocate more memory.
./src/H5E.c
./src/H5Epublic.c
Added the error H5E_TRUNCATED to be reported when the file is
shorter than the length recorded in the boot block.
./src/H5F.c
Added H5F_locate_signature() so we only do it in one place
now.
./INSTALL
./INSTALL_MAINT
Just a couple clarifications.
./html/ExternalFiles.html
./html/storage.html
Documents how external files work.
./test/hyperslab.c
./test/istore.c
Fixed printf's on 64-bit machines.
./test/istore.c
Added ifdef's to test the split file driver.
Diffstat (limited to 'src')
-rw-r--r-- | src/H5AC.c | 146 | ||||
-rw-r--r-- | src/H5ACprivate.h | 42 | ||||
-rw-r--r-- | src/H5B.c | 450 | ||||
-rw-r--r-- | src/H5Bprivate.h | 36 | ||||
-rw-r--r-- | src/H5C.c | 8 | ||||
-rw-r--r-- | src/H5D.c | 27 | ||||
-rw-r--r-- | src/H5Distore.c | 92 | ||||
-rw-r--r-- | src/H5E.c | 1 | ||||
-rw-r--r-- | src/H5Epublic.h | 1 | ||||
-rw-r--r-- | src/H5F.c | 553 | ||||
-rw-r--r-- | src/H5Fcore.c | 122 | ||||
-rw-r--r-- | src/H5Ffamily.c | 547 | ||||
-rw-r--r-- | src/H5Fistore.c | 92 | ||||
-rw-r--r-- | src/H5Flow.c | 588 | ||||
-rw-r--r-- | src/H5Fprivate.h | 102 | ||||
-rw-r--r-- | src/H5Fsec2.c | 152 | ||||
-rw-r--r-- | src/H5Fstdio.c | 119 | ||||
-rw-r--r-- | src/H5G.c | 51 | ||||
-rw-r--r-- | src/H5Gent.c | 68 | ||||
-rw-r--r-- | src/H5Gnode.c | 177 | ||||
-rw-r--r-- | src/H5Gpkg.h | 15 | ||||
-rw-r--r-- | src/H5Gprivate.h | 24 | ||||
-rw-r--r-- | src/H5Gshad.c | 217 | ||||
-rw-r--r-- | src/H5Gstab.c | 60 | ||||
-rw-r--r-- | src/H5H.c | 156 | ||||
-rw-r--r-- | src/H5Hprivate.h | 21 | ||||
-rw-r--r-- | src/H5MF.c | 46 | ||||
-rw-r--r-- | src/H5MFprivate.h | 7 | ||||
-rw-r--r-- | src/H5O.c | 142 | ||||
-rw-r--r-- | src/H5Ocont.c | 12 | ||||
-rw-r--r-- | src/H5Oistore.c | 12 | ||||
-rw-r--r-- | src/H5Oprivate.h | 15 | ||||
-rw-r--r-- | src/H5Ostab.c | 29 | ||||
-rw-r--r-- | src/H5Ostdst.c | 12 | ||||
-rw-r--r-- | src/H5private.h | 9 | ||||
-rw-r--r-- | src/Makefile.in | 8 | ||||
-rw-r--r-- | src/debug.c | 27 |
37 files changed, 2823 insertions, 1363 deletions
@@ -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 */ @@ -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, <_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, <_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 @@ -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: @@ -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 */ } @@ -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 */ @@ -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); -} - @@ -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]); } @@ -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 @@ -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 @@ -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 { /* |