diff options
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 { /* |