From 49ab3665aac51d817c362ebbc79d5835eb892484 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Wed, 15 Mar 2006 15:16:04 -0500 Subject: [svn-r12093] Purpose: Code checkpoint Description: Checkpoint fractal heap changes - mostly internal changes to better handle more direct blocks from root indirect block. Platforms tested: FreeBSD 4.11 (sleipnir) Linux 2.4 (chicago) Mac OS X (amazon) --- src/H5B2.c | 5 + src/H5B2cache.c | 6 + src/H5B2dbg.c | 5 + src/H5B2int.c | 6 + src/H5B2stat.c | 5 + src/H5B2test.c | 5 + src/H5HF.c | 5 + src/H5HFcache.c | 129 ++++++++---- src/H5HFdbg.c | 63 ++++-- src/H5HFint.c | 638 ++++++++++++++++++++++++++++++++++++++++++++------------ src/H5HFpkg.h | 35 +++- src/H5HFstat.c | 5 + src/H5HFtest.c | 5 + test/fheap.c | 202 ++++++++++++++++-- 14 files changed, 903 insertions(+), 211 deletions(-) diff --git a/src/H5B2.c b/src/H5B2.c index 57ba36c..98dca71 100644 --- a/src/H5B2.c +++ b/src/H5B2.c @@ -53,6 +53,11 @@ /********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ /* Local Prototypes */ /********************/ diff --git a/src/H5B2cache.c b/src/H5B2cache.c index 062f56c..476e9d1 100644 --- a/src/H5B2cache.c +++ b/src/H5B2cache.c @@ -50,6 +50,12 @@ /* Local Typedefs */ /******************/ + +/********************/ +/* Package Typedefs */ +/********************/ + + /********************/ /* Local Prototypes */ /********************/ diff --git a/src/H5B2dbg.c b/src/H5B2dbg.c index 6e51fbc..0bc8cd9 100644 --- a/src/H5B2dbg.c +++ b/src/H5B2dbg.c @@ -48,6 +48,11 @@ /********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ /* Local Prototypes */ /********************/ diff --git a/src/H5B2int.c b/src/H5B2int.c index 9b4b8db..1d35cbd 100644 --- a/src/H5B2int.c +++ b/src/H5B2int.c @@ -57,6 +57,12 @@ /* Local Typedefs */ /******************/ + +/********************/ +/* Package Typedefs */ +/********************/ + + /********************/ /* Local Prototypes */ /********************/ diff --git a/src/H5B2stat.c b/src/H5B2stat.c index a8f8c54..cd0881c 100644 --- a/src/H5B2stat.c +++ b/src/H5B2stat.c @@ -43,6 +43,11 @@ /********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ /* Local Prototypes */ /********************/ diff --git a/src/H5B2test.c b/src/H5B2test.c index 7749ee7..3d3f787 100644 --- a/src/H5B2test.c +++ b/src/H5B2test.c @@ -44,6 +44,11 @@ /********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ /* Local Prototypes */ /********************/ static herr_t H5B2_test_store(void *nrecord, const void *udata); diff --git a/src/H5HF.c b/src/H5HF.c index f183748..d5649d8 100644 --- a/src/H5HF.c +++ b/src/H5HF.c @@ -53,6 +53,11 @@ /********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ /* Local Prototypes */ /********************/ diff --git a/src/H5HFcache.c b/src/H5HFcache.c index 348f9eb..2b34604 100644 --- a/src/H5HFcache.c +++ b/src/H5HFcache.c @@ -51,6 +51,12 @@ /* Local Typedefs */ /******************/ + +/********************/ +/* Package Typedefs */ +/********************/ + + /********************/ /* Local Prototypes */ /********************/ @@ -177,12 +183,6 @@ H5HF_dtable_decode(H5F_t *f, const uint8_t **pp, H5HF_dtable_t *dtable) /* Next direct block's heap offset */ H5F_DECODE_LENGTH(f, *pp, dtable->next_dir_block); - /* Next direct block size */ - H5F_DECODE_LENGTH(f, *pp, dtable->next_dir_size); - - /* Next direct block column */ - UINT16DECODE(*pp, dtable->next_dir_col); - FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5HF_dtable_decode() */ @@ -236,12 +236,6 @@ H5HF_dtable_encode(H5F_t *f, uint8_t **pp, const H5HF_dtable_t *dtable) /* Next direct block's heap offset */ H5F_ENCODE_LENGTH(f, *pp, dtable->next_dir_block); - /* Next direct block size */ - H5F_ENCODE_LENGTH(f, *pp, dtable->next_dir_size); - - /* Next direct block column */ - UINT16ENCODE(*pp, dtable->next_dir_col); - FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5HF_dtable_encode() */ @@ -591,10 +585,10 @@ H5HF_cache_hdr_size(const H5F_t *f, const H5HF_t UNUSED *fh, size_t *size_ptr) *------------------------------------------------------------------------- */ static H5HF_direct_t * -H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_size, void *_fh_shared) +H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_size, void *_par_shared) { const size_t *size = (const size_t *)_size; /* Size of block */ - H5RC_t *fh_shared = (H5RC_t *)_fh_shared; /* Shared heap information */ + H5HF_parent_shared_t *par_shared = (H5HF_parent_shared_t *)_par_shared; /* Shared direct block information */ H5HF_shared_t *shared = NULL; /* Shared fractal heap information */ H5HF_direct_t *dblock = NULL; /* Direct block info */ const uint8_t *p; /* Pointer into raw data buffer */ @@ -607,7 +601,7 @@ H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_size, /* Check arguments */ HDassert(f); HDassert(H5F_addr_defined(addr)); - HDassert(fh_shared); + HDassert(par_shared); /* Allocate space for the fractal heap direct block */ if(NULL == (dblock = H5FL_MALLOC(H5HF_direct_t))) @@ -615,13 +609,20 @@ H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_size, HDmemset(&dblock->cache_info, 0, sizeof(H5AC_info_t)); /* Share common heap information */ - dblock->shared = fh_shared; + dblock->shared = par_shared->shared; H5RC_INC(dblock->shared); /* Get the pointer to the shared heap info */ shared = H5RC_GET_OBJ(dblock->shared); HDassert(shared); + /* Share common parent [indirect] block information */ + dblock->parent = par_shared->parent; + if(dblock->parent) + H5RC_INC(dblock->parent); + dblock->parent_entry = par_shared->parent_entry; + dblock->blk_free_space = (size_t)par_shared->parent_free_space; + /* Set block's internal information */ dblock->size = *size; dblock->blk_off_size = H5HF_SIZEOF_OFFSET_LEN(dblock->size); @@ -666,9 +667,6 @@ H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_size, /* Offset of heap within the heap's address space */ UINT64DECODE_VAR(p, dblock->block_off, shared->heap_off_size); - /* Total free space in block */ - UINT64DECODE_VAR(p, dblock->blk_free_space, dblock->blk_off_size); - /* Offset of free list head */ /* (Defer deserializing the whole free list until we actually need to modify it) */ UINT64DECODE_VAR(p, dblock->free_list_head, dblock->blk_off_size); @@ -745,9 +743,6 @@ H5HF_cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, if(shared->addrmap != H5HF_ABSOLUTE) HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "encoding mapped direct blocks not supported currently") - /* Total free space in block */ - UINT64ENCODE_VAR(p, dblock->blk_free_space, dblock->blk_off_size); - /* Offset of free list head */ UINT64ENCODE_VAR(p, dblock->free_list_head, dblock->blk_off_size); @@ -832,6 +827,8 @@ H5HF_cache_dblock_dest(H5F_t UNUSED *f, H5HF_direct_t *dblock) /* Decrement reference count on shared fractal heap info */ if(dblock->shared) H5RC_DEC(dblock->shared); + if(dblock->parent) + H5RC_DEC(dblock->parent); /* Check for free list & free it, if necessary */ if(dblock->free_list) { @@ -951,10 +948,10 @@ H5HF_cache_dblock_size(const H5F_t UNUSED *f, const H5HF_direct_t *dblock, size_ *------------------------------------------------------------------------- */ static H5HF_indirect_t * -H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nrows, void *_fh_shared) +H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nrows, void *_par_shared) { const unsigned *nrows = (const unsigned *)_nrows; /* # of rows in indirect block */ - H5RC_t *fh_shared = (H5RC_t *)_fh_shared; /* Shared heap information */ + H5HF_parent_shared_t *par_shared = (H5HF_parent_shared_t *)_par_shared; /* Shared direct block information */ H5HF_shared_t *shared = NULL; /* Shared fractal heap information */ H5HF_indirect_t *iblock = NULL; /* Indirect block info */ uint8_t *buf = NULL; /* Temporary buffer */ @@ -969,7 +966,7 @@ H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nrows /* Check arguments */ HDassert(f); HDassert(H5F_addr_defined(addr)); - HDassert(fh_shared); + HDassert(par_shared); /* Allocate space for the fractal heap indirect block */ if(NULL == (iblock = H5FL_MALLOC(H5HF_indirect_t))) @@ -977,13 +974,24 @@ H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nrows HDmemset(&iblock->cache_info, 0, sizeof(H5AC_info_t)); /* Share common heap information */ - iblock->shared = fh_shared; + iblock->shared = par_shared->shared; H5RC_INC(iblock->shared); /* Get the pointer to the shared heap info */ shared = H5RC_GET_OBJ(iblock->shared); HDassert(shared); + /* Share common parent [indirect] block information */ + iblock->parent = par_shared->parent; + if(iblock->parent) + H5RC_INC(iblock->parent); + iblock->parent_entry = par_shared->parent_entry; + iblock->child_free_space = par_shared->parent_free_space; + + /* Make a reference to this block */ + if(NULL == (iblock->self = H5RC_create(iblock, H5HF_iblock_free))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't create ref-count wrapper for indirect fractal heap block") + /* Set block's internal information */ iblock->nrows = *nrows; if(iblock->nrows > shared->man_dtable.max_direct_rows) { @@ -1041,17 +1049,40 @@ H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nrows HDassert(iblock->ndir_rows > 0); if(NULL == (iblock->dblock_ents = H5FL_SEQ_MALLOC(H5HF_indirect_dblock_ent_t, (iblock->ndir_rows * shared->man_dtable.cparam.width)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for direct entries") + iblock->dir_full = TRUE; for(u = 0; u < (iblock->ndir_rows * shared->man_dtable.cparam.width); u++) { H5F_addr_decode(f, &p, &(iblock->dblock_ents[u].addr)); UINT32DECODE_VAR(p, iblock->dblock_ents[u].free_space, shared->man_dtable.max_dir_blk_off_size); + + /* Check for direct block being undefined and use that for the next one to allocate from this indirect block */ + if(iblock->dir_full) { + if(!H5F_addr_defined(iblock->dblock_ents[u].addr)) { + iblock->next_dir_col = u % shared->man_dtable.cparam.width; + iblock->next_dir_row = u / shared->man_dtable.cparam.width; + iblock->next_dir_entry = u; + if(iblock->next_dir_row == 0) + iblock->next_dir_size = shared->man_dtable.cparam.start_block_size; + else + iblock->next_dir_size = shared->man_dtable.cparam.start_block_size * (1 << (iblock->next_dir_row - 1)); + if(heap_addr == 0) + iblock->max_direct_rows = shared->man_dtable.max_direct_rows; + else + HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, NULL, "computing max direct rows for non-root indirect block not supported yet") + + /* Set the flag to indicate the direct blocks aren't full */ + iblock->dir_full = FALSE; + } /* end if */ + } /* end if */ } /* end for */ if(iblock->nindir_rows > 0) { if(NULL == (iblock->iblock_ents = H5FL_SEQ_MALLOC(H5HF_indirect_iblock_ent_t, (iblock->nindir_rows * shared->man_dtable.cparam.width)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for indirect entries") /* Decode indirect block-specific fields */ - for(u = 0; u < (iblock->nindir_rows * shared->man_dtable.cparam.width); u++) + for(u = 0; u < (iblock->nindir_rows * shared->man_dtable.cparam.width); u++) { H5F_addr_decode(f, &p, &(iblock->iblock_ents[u].addr)); + UINT64DECODE_VAR(p, iblock->iblock_ents[u].free_space, shared->heap_off_size); + } /* end for */ } /* end if */ else iblock->iblock_ents = NULL; @@ -1105,6 +1136,12 @@ H5HF_cache_iblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, uint8_t *p; /* Pointer into raw data buffer */ size_t u; /* Local index variable */ + /* Sanity check */ + HDassert(iblock->dirty); +#ifdef QAK +HDfprintf(stderr, "%s: Flushing indirect block\n", FUNC); +#endif /* QAK */ + /* Get the pointer to the shared heap info */ shared = H5RC_GET_OBJ(iblock->shared); HDassert(shared); @@ -1145,6 +1182,9 @@ HDfprintf(stderr, "%s: shared->man_dtable.cparam.width = %u\n", FUNC, shared->ma /* Offset of block in heap */ UINT64ENCODE_VAR(p, iblock->block_off, shared->heap_off_size); +/* XXX: Fix this when we start writing recursive indirect blocks */ +if(iblock->block_off != 0) + HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "fix computing max direct rows for non-root indirect block for loading") /* Encode indirect block-specific fields */ HDassert(iblock->ndir_rows > 0); @@ -1153,8 +1193,10 @@ HDfprintf(stderr, "%s: shared->man_dtable.cparam.width = %u\n", FUNC, shared->ma UINT32ENCODE_VAR(p, iblock->dblock_ents[u].free_space, shared->man_dtable.max_dir_blk_off_size); } /* end for */ if(iblock->nindir_rows > 0) - for(u = 0; u < (iblock->nindir_rows * shared->man_dtable.cparam.width); u++) + for(u = 0; u < (iblock->nindir_rows * shared->man_dtable.cparam.width); u++) { H5F_addr_encode(f, &p, iblock->iblock_ents[u].addr); + UINT64ENCODE_VAR(p, iblock->iblock_ents[u].free_space, shared->heap_off_size); + } /* end for */ /* Sanity check */ HDassert((size_t)(p - buf) == iblock->size); @@ -1201,19 +1243,26 @@ H5HF_cache_iblock_dest(H5F_t UNUSED *f, H5HF_indirect_t *iblock) * Check arguments. */ HDassert(iblock); +#ifdef QAK +HDfprintf(stderr, "%s: Destroying indirect block\n", "H5HF_cache_iblock_dest"); +#endif /* QAK */ - /* Decrement reference count on shared fractal heap info */ - if(iblock->shared) - H5RC_DEC(iblock->shared); - - /* Release entry tables */ - if(iblock->dblock_ents) - H5FL_SEQ_FREE(H5HF_indirect_dblock_ent_t, iblock->dblock_ents); - if(iblock->iblock_ents) - H5FL_SEQ_FREE(H5HF_indirect_iblock_ent_t, iblock->iblock_ents); - - /* Free fractal heap indirect block info */ - H5FL_FREE(H5HF_indirect_t, iblock); + /* Decrement reference count on self */ + /* (let ref-counting API's callback for the block perform all cleanup) */ +/* XXX: This should actually free all the indirect block info, since this + * routine should not get called until the block has no dependents (once + * the "un-evictable" flag is in the metadata cache) + */ +/* XXX: Once the "un-evictable" flag is working in the metadata cache, can + * get rid of the "self" field and make a wrapper when creating the parent + * info for each "child" block, which will make the indirect block + * un-evictable as well as create the initial ref-counted object. + */ +/* XXX: Once the "un-evictable" flag is working in the metadata cache, the + * ref-counted 'free' callback should just make the indirect block + * evictable again. + */ + H5RC_DEC(iblock->self); FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5HF_cache_iblock_dest() */ diff --git a/src/H5HFdbg.c b/src/H5HFdbg.c index 977f40f..5dddac7 100644 --- a/src/H5HFdbg.c +++ b/src/H5HFdbg.c @@ -49,6 +49,11 @@ /********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ /* Local Prototypes */ /********************/ @@ -124,12 +129,6 @@ H5HF_dtable_debug(H5HF_dtable_t *dtable, FILE *stream, int indent, int fwidth) HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, "Current # of rows in root indirect block:", dtable->curr_root_rows); - HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, - "Next direct block size:", - dtable->next_dir_size); - HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, - "Next direct block column:", - dtable->next_dir_col); /* Computed values */ HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, @@ -257,6 +256,7 @@ H5HF_dblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, { H5HF_t *fh = NULL; /* Fractal heap header info */ H5HF_direct_t *dblock = NULL; /* Fractal heap direct block info */ + H5HF_parent_shared_t par_shared; /* Parent shared information */ H5HF_direct_free_node_t *node; /* Pointer to free list node for block */ H5HF_shared_t *shared; /* Shared fractal heap information */ size_t blk_prefix_size; /* Size of prefix for block */ @@ -293,9 +293,19 @@ H5HF_dblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, /* * Load the heap direct block */ - if(NULL == (dblock = H5AC_protect(f, dxpl_id, H5AC_FHEAP_DBLOCK, addr, &block_size, fh->shared, H5AC_READ))) + par_shared.shared = fh->shared; + par_shared.parent = NULL; + par_shared.parent_entry = 0; + par_shared.parent_free_space = 0; + if(NULL == (dblock = H5AC_protect(f, dxpl_id, H5AC_FHEAP_DBLOCK, addr, &block_size, &par_shared, H5AC_READ))) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap direct block") + /* Check for valid free list */ + if(!dblock->free_list) + if(H5HF_man_dblock_build_freelist(dblock, addr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDECODE, FAIL, "can't decode free list for block") + HDassert(dblock->free_list); + /* Release the heap header */ if(H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, hdr_addr, fh, H5AC__NO_FLAGS_SET) < 0) HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release fractal heap header") @@ -327,12 +337,6 @@ H5HF_dblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, "Offset of free list head:", dblock->free_list_head); - /* Check for valid free list */ - if(!dblock->free_list) - if(H5HF_man_dblock_build_freelist(dblock, addr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDECODE, FAIL, "can't decode free list for block") - HDassert(dblock->free_list); - /* * Traverse the free list and check that all free blocks fall within * the block and that no two free blocks point to the same region of @@ -340,8 +344,9 @@ H5HF_dblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, if(NULL == (marker = H5MM_calloc(dblock->size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") - HDfprintf(stream, "%*sFree Blocks (offset, next offset, size):\n", indent, ""); node = dblock->free_list->first; + if(node) + HDfprintf(stream, "%*sFree Blocks (offset, next offset, size):\n", indent, ""); while(node) { char temp_str[32]; @@ -407,7 +412,9 @@ H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, { H5HF_t *fh = NULL; /* Fractal heap header info */ H5HF_shared_t *shared; /* Shared fractal heap information */ + H5HF_parent_shared_t par_shared; /* Parent shared information */ H5HF_indirect_t *iblock = NULL; /* Fractal heap direct block info */ + size_t dblock_size; /* Current direct block size */ char temp_str[64]; /* Temporary string, for formatting */ size_t u, v; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ @@ -438,7 +445,11 @@ H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, /* * Load the heap direct block */ - if(NULL == (iblock = H5AC_protect(f, dxpl_id, H5AC_FHEAP_IBLOCK, addr, &nrows, fh->shared, H5AC_READ))) + par_shared.shared = fh->shared; + par_shared.parent = NULL; + par_shared.parent_entry = 0; + par_shared.parent_free_space = 0; + if(NULL == (iblock = H5AC_protect(f, dxpl_id, H5AC_FHEAP_IBLOCK, addr, &nrows, &par_shared, H5AC_READ))) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap indirect block") /* Release the heap header */ @@ -458,6 +469,9 @@ H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth, "Offset of indirect block in heap:", iblock->block_off); + HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth, + "Total children free space:", + iblock->child_free_space); HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth, "Size of indirect block:", iblock->size); @@ -470,11 +484,27 @@ H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, "# of indirect rows:", iblock->nindir_rows); + HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, + "Direct blocks full:", + (iblock->dir_full ? "TRUE" : "FALSE")); + HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, + "Max direct block rows:", + iblock->max_direct_rows); + HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, + "Next direct block column:", + iblock->next_dir_col); + HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, + "Next direct block row:", + iblock->next_dir_row); + HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, + "Next direct block size:", + iblock->next_dir_size); /* Print the entry tables */ + dblock_size = shared->man_dtable.cparam.start_block_size; HDfprintf(stream, "%*sDirect Block Entries (address, free space):\n", indent, ""); for(u = 0; u < iblock->ndir_rows; u++) { - sprintf(temp_str, "Row #%u:", (unsigned)u); + sprintf(temp_str, "Row #%u: (block size: %lu)", (unsigned)u, (unsigned long)dblock_size); HDfprintf(stream, "%*s%-*s\n", indent + 3, "", MAX(0, fwidth - 3), temp_str); for(v = 0; v < shared->man_dtable.cparam.width; v++) { @@ -486,6 +516,7 @@ H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, iblock->dblock_ents[off].addr, iblock->dblock_ents[off].free_space); } /* end for */ + dblock_size *= 2; } /* end for */ HDfprintf(stream, "%*sIndirect Block Entries:\n", indent, ""); if(iblock->nindir_rows > 0) { diff --git a/src/H5HFint.c b/src/H5HFint.c index fce8640..627f6e6 100644 --- a/src/H5HFint.c +++ b/src/H5HFint.c @@ -86,15 +86,19 @@ static herr_t H5HF_shared_free(void *_shared); /* Direct block routines */ static herr_t H5HF_dblock_section_node_free_cb(void *item, void UNUSED *key, void UNUSED *op_data); -static herr_t H5HF_man_dblock_inc_size(H5HF_shared_t *shared); -static herr_t H5HF_man_dblock_create(H5RC_t *fh_shared, hid_t dxpl_id, - size_t block_size, hsize_t block_off, haddr_t *addr_p); +static herr_t H5HF_man_dblock_create(H5HF_parent_shared_t *par_shared, + hid_t dxpl_id, size_t block_size, hsize_t block_off, haddr_t *addr_p); static herr_t H5HF_man_dblock_new(H5RC_t *fh_shared, hid_t dxpl_id, size_t request); +static herr_t H5HF_man_dblock_adj_free(H5HF_direct_t *dblock, ssize_t amt); /* Indirect block routines */ +static herr_t H5HF_man_iblock_inc_loc(H5HF_indirect_t *iblock); +static H5HF_indirect_t * H5HF_man_iblock_place_dblock(H5RC_t *fh_shared, hid_t dxpl_id, + size_t min_dblock_size, haddr_t *addr_p, size_t *entry_p, + size_t *dblock_size); static herr_t H5HF_man_iblock_create(H5RC_t *fh_shared, hid_t dxpl_id, - hsize_t block_off, unsigned nrows, haddr_t *addr_p); + hsize_t block_off, unsigned nrows, unsigned max_dir_rows, haddr_t *addr_p); /*********************/ /* Package Variables */ @@ -172,7 +176,6 @@ H5HF_dtable_init(const H5HF_shared_t *shared, H5HF_dtable_t *dtable) H5V_log2_of2(dtable->cparam.start_block_size)) + 2; dtable->num_id_first_row = dtable->cparam.start_block_size * dtable->cparam.width; dtable->max_dir_blk_off_size = H5HF_SIZEOF_OFFSET_LEN(dtable->cparam.max_direct_size); - dtable->next_dir_size = dtable->cparam.start_block_size; /* Build table of block sizes for each row */ if(NULL == (dtable->row_block_size = H5MM_malloc(dtable->max_root_indirect_rows * sizeof(hsize_t)))) @@ -375,6 +378,9 @@ H5HF_shared_create(H5F_t *f, H5HF_t *fh, haddr_t fh_addr, H5HF_create_t *cparam) shared->ref_count_size = cparam->ref_count_size; HDmemcpy(&(shared->man_dtable.cparam), &(cparam->managed), sizeof(H5HF_dtable_cparam_t)); + /* Set root table address */ + shared->man_dtable.table_addr = HADDR_UNDEF; + /* Note that the shared info is dirty (it's not written to the file yet) */ shared->dirty = TRUE; @@ -429,49 +435,62 @@ H5HF_shared_free(void *_shared) /*------------------------------------------------------------------------- - * Function: H5HF_man_dblock_inc_size + * Function: H5HF_man_iblock_inc_loc * - * Purpose: Increment size of next direct block + * Purpose: Increment location of next direct block in indirect block * * Return: SUCCEED/FAIL * * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu - * Mar 6 2006 + * Mar 14 2006 * *------------------------------------------------------------------------- */ static herr_t -H5HF_man_dblock_inc_size(H5HF_shared_t *shared) +H5HF_man_iblock_inc_loc(H5HF_indirect_t *iblock) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_man_dblock_inc_size) + H5HF_shared_t *shared; /* Pointer to shared heap info */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_man_iblock_inc_loc) /* * Check arguments. */ + HDassert(iblock); + + /* Get the pointer to the shared heap info */ + shared = H5RC_GET_OBJ(iblock->shared); HDassert(shared); - /* Check for another block of the same size, in the same row */ - if(shared->man_dtable.next_dir_col < shared->man_dtable.cparam.width) { - /* Move to next column in doubling table */ - shared->man_dtable.next_dir_col++; + /* Increment column */ + iblock->next_dir_col++; + + /* Check for walking off end of column */ + if(iblock->next_dir_col == shared->man_dtable.cparam.width) { + /* Reset column */ + iblock->next_dir_col = 0; + + /* Increment row & direct block size */ + iblock->next_dir_row++; + iblock->next_dir_size *= 2; + + /* Check for filling up all direct block entries in indirect block */ + if(iblock->next_dir_row == iblock->max_direct_rows) + iblock->dir_full = TRUE; } /* end if */ - else { - /* Check for "doubling" block to next row or resetting to initial size */ -/* XXX: The maximum size will vary for different indirect blocks... */ - if(shared->man_dtable.next_dir_size < shared->man_dtable.cparam.max_direct_size) - /* Double block size */ - shared->man_dtable.next_dir_size *= 2; - else - /* Reset to starting block size */ - shared->man_dtable.next_dir_size = shared->man_dtable.cparam.start_block_size; - /* Set next column */ - shared->man_dtable.next_dir_col = 0; - } /* end else */ +#ifdef QAK +HDfprintf(stderr, "%s: iblock->next_dir_row = %u\n", "H5HF_man_iblock_inc_loc", iblock->next_dir_row); +HDfprintf(stderr, "%s: iblock->next_dir_col = %u\n", "H5HF_man_iblock_inc_loc", iblock->next_dir_col); +HDfprintf(stderr, "%s: iblock->next_dir_size = %Zu\n", "H5HF_man_iblock_inc_loc", iblock->next_dir_size); +HDfprintf(stderr, "%s: iblock->dir_full = %u\n", "H5HF_man_iblock_inc_loc", (unsigned)iblock->dir_full); +#endif /* QAK */ + /* Mark heap header as modified */ + shared->dirty = TRUE; FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5HF_man_dblock_inc_size() */ +} /* end H5HF_man_iblock_inc_loc() */ /*------------------------------------------------------------------------- @@ -488,13 +507,14 @@ H5HF_man_dblock_inc_size(H5HF_shared_t *shared) *------------------------------------------------------------------------- */ static herr_t -H5HF_man_dblock_create(H5RC_t *fh_shared, hid_t dxpl_id, +H5HF_man_dblock_create(H5HF_parent_shared_t *par_shared, hid_t dxpl_id, size_t block_size, hsize_t block_off, haddr_t *addr_p) { H5HF_direct_free_node_t *node; /* Pointer to free list node for block */ H5HF_section_free_node_t *sec_node; /* Pointer to free list section for block */ H5HF_shared_t *shared; /* Pointer to shared heap info */ H5HF_direct_t *dblock = NULL; /* Pointer to direct block */ + size_t free_space; /* Free space in new block */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_dblock_create) @@ -502,7 +522,8 @@ H5HF_man_dblock_create(H5RC_t *fh_shared, hid_t dxpl_id, /* * Check arguments. */ - HDassert(fh_shared); + HDassert(par_shared); + HDassert(par_shared->shared); HDassert(block_size > 0); HDassert(addr_p); @@ -516,10 +537,10 @@ H5HF_man_dblock_create(H5RC_t *fh_shared, hid_t dxpl_id, HDmemset(&dblock->cache_info, 0, sizeof(H5AC_info_t)); /* Share common heap information */ - dblock->shared = fh_shared; + dblock->shared = par_shared->shared; H5RC_INC(dblock->shared); - /* Get the pointer to the shared B-tree info */ + /* Get the pointer to the shared heap info */ shared = H5RC_GET_OBJ(dblock->shared); HDassert(shared); @@ -527,11 +548,16 @@ H5HF_man_dblock_create(H5RC_t *fh_shared, hid_t dxpl_id, #ifdef QAK HDfprintf(stderr, "%s: size = %Zu, block_off = %Hu\n", FUNC, block_size, block_off); #endif /* QAK */ + dblock->parent = par_shared->parent; + if(dblock->parent) + H5RC_INC(dblock->parent); + dblock->parent_entry = par_shared->parent_entry; dblock->size = block_size; dblock->block_off = block_off; dblock->blk_off_size = H5HF_SIZEOF_OFFSET_LEN(block_size); dblock->free_list_head = H5HF_MAN_ABS_DIRECT_OVERHEAD_DBLOCK(shared, dblock); - dblock->blk_free_space = block_size - dblock->free_list_head; + dblock->blk_free_space = par_shared->parent_free_space; + free_space = block_size - dblock->free_list_head; /* Allocate buffer for block */ /* XXX: Change to using free-list factories */ @@ -551,7 +577,7 @@ HDmemset(dblock->blk, 0, dblock->size); HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list node") /* Set node's information */ - node->size = dblock->blk_free_space; + node->size = free_space; node->my_offset = dblock->free_list_head; node->next_offset = 0; node->prev = node->next = NULL; @@ -579,8 +605,11 @@ HDmemset(dblock->blk, 0, dblock->size); if(H5HF_flist_add(shared->flist, sec_node, &sec_node->sect_size, &sec_node->sect_addr) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add direct block free space to global list") + /* Adjust free space to include new block's space */ + if(H5HF_man_dblock_adj_free(dblock, (ssize_t)free_space) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't adjust free space for direct block & parents") + /* Update shared heap info */ - shared->total_man_free += dblock->blk_free_space; shared->total_size += dblock->size; shared->man_size += dblock->size; @@ -673,7 +702,7 @@ H5HF_man_dblock_build_freelist(H5HF_direct_t *dblock, haddr_t dblock_addr) hsize_t prev_off; /* Prev node offset in block */ uint8_t *p; /* Temporary pointer to free node info */ - /* Get the pointer to the shared B-tree info */ + /* Get the pointer to the shared heap info */ shared = H5RC_GET_OBJ(dblock->shared); HDassert(shared); @@ -697,6 +726,9 @@ H5HF_man_dblock_build_freelist(H5HF_direct_t *dblock, haddr_t dblock_addr) /* Attach to free list head */ head->first = node; + /* Set block's free space */ + dblock->blk_free_space = free_len; + /* Create free list section node */ if(NULL == (sec_node = H5FL_MALLOC(H5HF_section_free_node_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section") @@ -736,6 +768,9 @@ H5HF_man_dblock_build_freelist(H5HF_direct_t *dblock, haddr_t dblock_addr) node->prev = prev_node; node->next = NULL; + /* Adjust block's free space */ + dblock->blk_free_space += free_len; + /* Create free list section node */ if(NULL == (sec_node = H5FL_MALLOC(H5HF_section_free_node_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section") @@ -770,6 +805,87 @@ done: /*------------------------------------------------------------------------- + * Function: H5HF_man_dblock_adj_free + * + * Purpose: Adjust the free space for a direct block, and it's parents + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 14 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_man_dblock_adj_free(H5HF_direct_t *dblock, ssize_t amt) +{ + H5HF_shared_t *shared; /* Shared heap information */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_man_dblock_adj_free) +#ifdef QAK +HDfprintf(stderr, "%s: amt = %Zd\n", "H5HF_man_dblock_adj_free", amt); +#endif /* QAK */ + + /* + * Check arguments. + */ + HDassert(dblock); + + /* Get the pointer to the shared heap info */ + shared = H5RC_GET_OBJ(dblock->shared); + HDassert(shared); + + /* Adjust space available in block */ + dblock->blk_free_space += amt; + + /* Check if the parent info is set */ + if(dblock->parent) { + H5HF_indirect_t *iblock; /* Block's parent */ + + /* Get the pointer to the shared parent indirect block */ + iblock = H5RC_GET_OBJ(dblock->parent); + HDassert(iblock); + + /* Adjust this indirect block's child free space */ +#ifdef QAK +HDfprintf(stderr, "%s: iblock->child_free_space = %Hu\n", "H5HF_man_dblock_adj_free", iblock->child_free_space); +#endif /* QAK */ + iblock->dblock_ents[dblock->parent_entry].free_space += amt; + iblock->child_free_space += amt; + + /* Mark indirect block as dirty */ + iblock->dirty = TRUE; + + /* Modify the free space in parent block(s) */ + while(iblock->parent) { + size_t parent_entry; /* Entry in parent */ + + /* Get the pointer to the shared parent indirect block */ + parent_entry = iblock->parent_entry; + iblock = H5RC_GET_OBJ(iblock->parent); + HDassert(iblock); + + /* Adjust this indirect block's child free space */ + iblock->iblock_ents[parent_entry].free_space += amt; + iblock->child_free_space += amt; + + /* Mark indirect block as dirty */ + iblock->dirty = TRUE; + } /* end while */ + } /* end if */ + + /* Update shared heap free space info */ + shared->total_man_free += amt; + + /* Mark heap header as modified */ + shared->dirty = TRUE; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HF_man_dblock_adj_free() */ + + +/*------------------------------------------------------------------------- * Function: H5HF_man_dblock_new * * Purpose: Create a direct block large enough to hold an object of @@ -786,8 +902,11 @@ done: static herr_t H5HF_man_dblock_new(H5RC_t *fh_shared, hid_t dxpl_id, size_t request) { - size_t min_dblock_size; /* Min. size of direct block to allocate */ + H5HF_parent_shared_t par_shared; /* Parent shared information */ H5HF_shared_t *shared; /* Shared heap information */ + haddr_t dblock_addr; /* Address of new direct block */ + size_t dblock_size; /* Size of new direct block */ + size_t min_dblock_size; /* Min. size of direct block to allocate */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_dblock_new) @@ -823,106 +942,72 @@ HDfprintf(stderr, "%s: H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN_SIZE = %u\n", FUNC, H5 min_dblock_size *= 2; #ifdef QAK HDfprintf(stderr, "%s: min_dblock_size = %Zu\n", FUNC, min_dblock_size); -HDfprintf(stderr, "%s: shared->man_dtable.next_dir_size = %Zu\n", FUNC, shared->man_dtable.next_dir_size); #endif /* QAK */ - /* Add direct block to heap */ - if(min_dblock_size <= shared->man_dtable.next_dir_size) { - haddr_t dblock_addr; /* Address of new direct block */ - size_t dblock_size; /* SIze of new direct block */ - - /* Create new direct block */ - dblock_size = shared->man_dtable.next_dir_size; - if(H5HF_man_dblock_create(fh_shared, dxpl_id, dblock_size, shared->man_dtable.next_dir_block, &dblock_addr) < 0) + /* Check if this is the first block in the heap */ + if(!H5F_addr_defined(shared->man_dtable.table_addr)) { + /* Create new direct block at corrent location*/ + dblock_size = shared->man_dtable.cparam.start_block_size; + par_shared.shared = fh_shared; + par_shared.parent = NULL; + par_shared.parent_entry = 0; + par_shared.parent_free_space = 0; + if(H5HF_man_dblock_create(&par_shared, dxpl_id, dblock_size, shared->man_dtable.next_dir_block, &dblock_addr) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap direct block") + #ifdef QAK HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr); HDfprintf(stderr, "%s: shared->man_dtable.next_dir_block = %Hu\n", FUNC, shared->man_dtable.next_dir_block); #endif /* QAK */ - /* Check if this is the first block in the heap */ - if(shared->man_dtable.next_dir_block == 0) { - /* Point root at new direct block */ - shared->man_dtable.curr_root_rows = 0; - shared->man_dtable.table_addr = dblock_addr; - } /* end if */ - /* Check for the second block in the heap */ - else if(shared->man_dtable.curr_root_rows == 0) { - H5HF_indirect_t *iblock = NULL; /* Pointer to indirect block to create */ - H5HF_direct_t *dblock = NULL; /* Pointer to direct block to query */ - haddr_t iblock_addr; /* Indirect block's address */ - unsigned nrows; /* Number of rows for root indirect block */ - - /* Check for allocating entire root indirect block initially */ - if(shared->man_dtable.cparam.start_root_rows == 0) - nrows = shared->man_dtable.max_root_indirect_rows; - else - nrows = shared->man_dtable.cparam.start_root_rows; - - /* Allocate root indirect block */ - if(H5HF_man_iblock_create(fh_shared, dxpl_id, (hsize_t)0, nrows, &iblock_addr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap indirect block") + /* Point root at new direct block */ + shared->man_dtable.curr_root_rows = 0; + shared->man_dtable.table_addr = dblock_addr; + } /* end if */ + /* Root entry already exists, go get indirect block for new direct block */ + else { + H5HF_indirect_t *iblock; /* Pointer to indirect block to create */ + haddr_t iblock_addr; /* Indirect block's address */ + size_t dblock_entry; /* Direct entry for new direct block */ + + /* Find indirect block with room for block of correct size */ + if(NULL == (iblock = H5HF_man_iblock_place_dblock(fh_shared, dxpl_id, min_dblock_size, &iblock_addr, &dblock_entry, &dblock_size))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to locate indirect block with space for direct block") #ifdef QAK -HDfprintf(stderr, "%s: iblock_addr = %a\n", FUNC, iblock_addr); +HDfprintf(stderr, "%s: dblock_entry = %Zu\n", FUNC, dblock_entry); #endif /* QAK */ - /* Lock indirect block */ - if(NULL == (iblock = H5AC_protect(shared->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, &nrows, fh_shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") - - /* Lock first (root) direct block */ - if(NULL == (dblock = H5AC_protect(shared->f, dxpl_id, H5AC_FHEAP_DBLOCK, shared->man_dtable.table_addr, &shared->man_dtable.cparam.start_block_size, fh_shared, H5AC_READ))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap direct block") - - /* Point indirect block at direct block to add */ - iblock->dblock_ents[0].addr = shared->man_dtable.table_addr; - iblock->dblock_ents[0].free_space = dblock->blk_free_space; - - /* Unlock first (root) direct block */ - if(H5AC_unprotect(shared->f, dxpl_id, H5AC_FHEAP_DBLOCK, shared->man_dtable.table_addr, dblock, H5AC__NO_FLAGS_SET) < 0) - HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block") - dblock = NULL; - - /* Lock new direct block */ - if(NULL == (dblock = H5AC_protect(shared->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, &shared->man_dtable.cparam.start_block_size, fh_shared, H5AC_READ))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap direct block") - - /* Point indirect block at new direct block */ - iblock->dblock_ents[1].addr = dblock_addr; - iblock->dblock_ents[1].free_space = dblock->blk_free_space; - - /* Unlock new direct block */ - if(H5AC_unprotect(shared->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__NO_FLAGS_SET) < 0) - HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block") - dblock = NULL; + /* Create new direct block at corrent location*/ + par_shared.shared = fh_shared; + par_shared.parent = iblock->self; + par_shared.parent_entry = dblock_entry; + par_shared.parent_free_space = 0; + if(H5HF_man_dblock_create(&par_shared, dxpl_id, dblock_size, shared->man_dtable.next_dir_block, &dblock_addr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap direct block") - /* Point heap header at new indirect block */ - shared->man_dtable.curr_root_rows = nrows; - shared->man_dtable.table_addr = iblock_addr; +#ifdef QAK +HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr); +HDfprintf(stderr, "%s: shared->man_dtable.next_dir_block = %Hu\n", FUNC, shared->man_dtable.next_dir_block); +#endif /* QAK */ - /* Mark heap header as modified */ - shared->dirty = TRUE; + /* Point indirect block at new direct block */ + iblock->dblock_ents[dblock_entry].addr = dblock_addr; - /* Release the indirect block (marked as dirty) */ - if(H5AC_unprotect(shared->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, iblock, H5AC__DIRTIED_FLAG) < 0) - HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") - } /* end if */ - else { -HDfprintf(stderr, "%s: Adding >2nd direct block to heap not supported\n", FUNC); -HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "allocating objects from non root block not supported yet") - } /* end else */ + /* Increment size of next block from this indirect block */ + H5HF_man_iblock_inc_loc(iblock); - /* Update shared info */ - shared->man_dtable.next_dir_block += dblock_size; + /* Mark indirect block as modified */ + iblock->dirty = TRUE; - /* Increment size of next block */ - H5HF_man_dblock_inc_size(shared); - } /* end if */ - else { -HDfprintf(stderr, "%s: Skipping direct block sizes not supported\n", FUNC); -HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "allocating objects from non root block not supported yet") + /* Release the indirect block (marked as dirty) */ + if(H5AC_unprotect(shared->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, iblock, H5AC__DIRTIED_FLAG) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") } /* end else */ + /* Update shared info */ +/* XXX: This is going to cause problems when we support skipping blocks */ + shared->man_dtable.next_dir_block += dblock_size; + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_man_dblock_new() */ @@ -1113,23 +1198,26 @@ H5HF_man_insert(H5RC_t *fh_shared, hid_t dxpl_id, H5HF_section_free_node_t *sec_ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add direct block free space to global list") } /* end else */ + /* Mark free list as dirty */ + dblock->free_list->dirty = TRUE; + /* Compute the size of the space to actually allocate */ /* (includes the metadata for the object & the free space fragment) */ alloc_obj_size = full_obj_size + free_frag_size; - /* Reduce space available in block */ - dblock->blk_free_space -= alloc_obj_size; - - /* Mark free list as dirty */ - dblock->free_list->dirty = TRUE; - - /* Point to location for object */ #ifdef QAK HDfprintf(stderr, "%s: obj_off = %Zu\n", FUNC, obj_off); HDfprintf(stderr, "%s: free_frag_size = %Zu\n", FUNC, free_frag_size); HDfprintf(stderr, "%s: full_obj_size = %Zu\n", FUNC, full_obj_size); HDfprintf(stderr, "%s: alloc_obj_size = %Zu\n", FUNC, alloc_obj_size); #endif /* QAK */ + /* Reduce space available in parent block(s) */ + if(H5HF_man_dblock_adj_free(dblock, -(ssize_t)alloc_obj_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't adjust free space for direct block & parents") + + /* Encode the object in the block */ + + /* Point to location for object */ p = dblock->blk + obj_off; /* Encode the length */ @@ -1162,10 +1250,6 @@ HDfprintf(stderr, "%s: alloc_obj_size = %Zu\n", FUNC, alloc_obj_size); HDfprintf(stderr, "%s: dblock->block_off = %Hu\n", FUNC, dblock->block_off); #endif /* QAK */ UINT64ENCODE_VAR(id, (dblock->block_off + obj_off), shared->heap_off_size); - - /* Update shared heap info */ - shared->total_man_free -= alloc_obj_size; - } /* end if */ else { HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "inserting within mapped managed blocks not supported yet") @@ -1187,11 +1271,284 @@ done: /*------------------------------------------------------------------------- + * Function: H5HF_iblock_free + * + * Purpose: Free fractal heap indirect block + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 13 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_iblock_free(void *_iblock) +{ + H5HF_indirect_t *iblock = (H5HF_indirect_t *)_iblock; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_iblock_free) +#ifdef QAK +HDfprintf(stderr, "%s: Freeing indirect block\n", "H5HF_iblock_free"); +#endif /* QAK */ + + /* Sanity check */ + HDassert(iblock); + + /* Decrement reference count on shared fractal heap info */ + if(iblock->shared) + H5RC_DEC(iblock->shared); + if(iblock->parent) + H5RC_DEC(iblock->parent); + + /* Release entry tables */ + if(iblock->dblock_ents) + H5FL_SEQ_FREE(H5HF_indirect_dblock_ent_t, iblock->dblock_ents); + if(iblock->iblock_ents) + H5FL_SEQ_FREE(H5HF_indirect_iblock_ent_t, iblock->iblock_ents); + + /* Free fractal heap indirect block info */ + H5FL_FREE(H5HF_indirect_t, iblock); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HF_iblock_free() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_man_iblock_place_dblock + * + * Purpose: Find indirect block with location for placing a direct block + * + * Note: Creates necessary indirect blocks + * + * Return: Pointer to indirect block on success, NULL on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 14 2006 + * + *------------------------------------------------------------------------- + */ +static H5HF_indirect_t * +H5HF_man_iblock_place_dblock(H5RC_t *fh_shared, hid_t dxpl_id, + size_t min_dblock_size, haddr_t *addr_p, size_t *entry_p, + size_t *dblock_size) +{ + H5HF_parent_shared_t par_shared; /* Parent shared information */ + H5HF_shared_t *shared; /* Pointer to shared heap info */ + H5HF_indirect_t *iblock; /* Pointer to indirect block */ + H5HF_indirect_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_place_dblock) + + /* + * Check arguments. + */ + HDassert(fh_shared); + HDassert(min_dblock_size > 0); + HDassert(addr_p); + + /* Get the pointer to the shared heap info */ + shared = H5RC_GET_OBJ(fh_shared); + HDassert(shared); + + /* Check for creating first indirect block */ + if(shared->man_dtable.curr_root_rows == 0) { + H5HF_direct_t *dblock; /* Pointer to direct block to query */ + unsigned nrows; /* Number of rows for root indirect block */ + + /* Check for skipping over blocks */ + if(min_dblock_size != shared->man_dtable.cparam.start_block_size) { +HDfprintf(stderr, "%s: Skipping direct block sizes not supported\n", FUNC); +HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, NULL, "skipping direct block sizes not supported yet") + } /* end if */ + +#ifdef QAK +HDfprintf(stderr, "%s: creating first indirect block\n", FUNC); +#endif /* QAK */ + /* Check for allocating entire root indirect block initially */ + if(shared->man_dtable.cparam.start_root_rows == 0) + nrows = shared->man_dtable.max_root_indirect_rows; + else + nrows = shared->man_dtable.cparam.start_root_rows; + + /* Allocate root indirect block */ + if(H5HF_man_iblock_create(fh_shared, dxpl_id, (hsize_t)0, nrows, shared->man_dtable.max_direct_rows, addr_p) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "can't allocate fractal heap indirect block") +#ifdef QAK +HDfprintf(stderr, "%s: *addr_p = %a\n", FUNC, *addr_p); +#endif /* QAK */ + + /* Move current direct block (used as root) into new indirect block */ + + /* Lock new indirect block */ + par_shared.shared = fh_shared; + par_shared.parent = NULL; + par_shared.parent_entry = 0; + par_shared.parent_free_space = 0; + if(NULL == (iblock = H5AC_protect(shared->f, dxpl_id, H5AC_FHEAP_IBLOCK, *addr_p, &nrows, &par_shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap indirect block") + + /* Lock first (root) direct block */ + par_shared.parent_free_space = shared->total_man_free; + if(NULL == (dblock = H5AC_protect(shared->f, dxpl_id, H5AC_FHEAP_DBLOCK, shared->man_dtable.table_addr, &shared->man_dtable.cparam.start_block_size, &par_shared, H5AC_READ))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap direct block") + + /* Point indirect block at direct block to add */ + iblock->dblock_ents[0].addr = shared->man_dtable.table_addr; + iblock->dblock_ents[0].free_space = dblock->blk_free_space; + iblock->child_free_space += dblock->blk_free_space; + + /* Make direct block share parent indirect block */ + dblock->parent = iblock->self; + dblock->parent_entry = 0; + H5RC_INC(dblock->parent); + + /* Unlock first (root) direct block */ + if(H5AC_unprotect(shared->f, dxpl_id, H5AC_FHEAP_DBLOCK, shared->man_dtable.table_addr, dblock, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, NULL, "unable to release fractal heap direct block") + dblock = NULL; + + /* Increment size of next block from this indirect block */ + /* (account for the already existing direct block */ + H5HF_man_iblock_inc_loc(iblock); + + /* Mark indirect block as modified */ + iblock->dirty = TRUE; + + /* Point heap header at new indirect block */ + shared->man_dtable.curr_root_rows = nrows; + shared->man_dtable.table_addr = *addr_p; + + /* Mark heap header as modified */ + shared->dirty = TRUE; + + /* Set entry for direct block */ + *entry_p = 1; + + /* Set size of direct block to create */ + *dblock_size = iblock->next_dir_size; + } /* end if */ + else { +#ifdef QAK +HDfprintf(stderr, "%s: searching root indirect block\n", FUNC); +#endif /* QAK */ + + /* Lock root indirect block */ + par_shared.shared = fh_shared; + par_shared.parent = NULL; + par_shared.parent_entry = 0; + par_shared.parent_free_space = shared->total_man_free; + if(NULL == (iblock = H5AC_protect(shared->f, dxpl_id, H5AC_FHEAP_IBLOCK, shared->man_dtable.table_addr, &shared->man_dtable.curr_root_rows, &par_shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap indirect block") + +#ifdef QAK +HDfprintf(stderr, "%s: iblock->next_dir_row = %u\n", FUNC, iblock->next_dir_row); +HDfprintf(stderr, "%s: iblock->next_dir_col = %u\n", FUNC, iblock->next_dir_col); +HDfprintf(stderr, "%s: iblock->next_dir_size = %Zu\n", FUNC, iblock->next_dir_size); +HDfprintf(stderr, "%s: iblock->dir_full = %u\n", FUNC, (unsigned)iblock->dir_full); +#endif /* QAK */ + /* Check for full direct block entries in root */ + if(iblock->dir_full) { +HDfprintf(stderr, "%s: Adding nested indirect block to heap not supported\n", FUNC); +HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, NULL, "Adding nested indirect block not supported yet") + } /* end if */ + + /* Check for skipping over blocks */ + if(min_dblock_size > iblock->next_dir_size) { +HDfprintf(stderr, "%s: Skipping direct block sizes not supported\n", FUNC); +HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, NULL, "skipping direct block sizes not supported yet") + } /* end if */ + + /* Check if we need a direct block past current allocation */ + if(iblock->next_dir_row == iblock->ndir_rows) { + haddr_t old_addr; /* Old address of indirect block */ + unsigned new_nrows; /* New # of direct rows */ + size_t u; /* Local index variable */ + + /* Check for special case of second row, which has blocks the same size as first row */ + if(iblock->next_dir_row == 1) + iblock->next_dir_size = shared->man_dtable.table_addr; + + /* Compute new # of rows in indirect block */ + new_nrows = 2 * iblock->ndir_rows; + if(new_nrows > iblock->max_direct_rows) + new_nrows = iblock->max_direct_rows; +HDfprintf(stderr, "%s: new_nrows = %u\n", FUNC, new_nrows); + +/* Currently, the old chunk data is "thrown away" after the space is reallocated, + * so avoid data copy in H5MF_realloc() call by just free'ing the space and + * allocating new space. + * + * This should keep the file smaller also, by freeing the space and then + * allocating new space, instead of vice versa (in H5MF_realloc). + * + * QAK - 3/14/2006 + */ + /* Free previous indirect block disk space */ + old_addr = shared->man_dtable.table_addr; + if(H5MF_xfree(shared->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, old_addr, (hsize_t)iblock->size)<0) + HGOTO_ERROR(H5E_STORAGE, H5E_CANTFREE, NULL, "unable to free fractal heap indirect block") + + /* Compute size of buffer needed for new indirect block */ + iblock->ndir_rows = new_nrows; + iblock->size = H5HF_MAN_INDIRECT_SIZE(shared, iblock); + + /* Mark indirect block as dirty */ + iblock->dirty = TRUE; + + /* Allocate space for the new indirect block on disk */ + if(HADDR_UNDEF == (shared->man_dtable.table_addr = H5MF_alloc(shared->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, (hsize_t)iblock->size))) + HGOTO_ERROR(H5E_STORAGE, H5E_NOSPACE, NULL, "file allocation failed for fractal heap indirect block") + + /* Move object in cache */ + if(H5AC_rename(shared->f, H5AC_FHEAP_IBLOCK, shared->man_dtable.table_addr, old_addr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTSPLIT, NULL, "unable to move fractal heap root indirect block") + + /* Re-allocate direct block entry table */ + if(NULL == (iblock->dblock_ents = H5FL_SEQ_REALLOC(H5HF_indirect_dblock_ent_t, iblock->dblock_ents, (iblock->ndir_rows * shared->man_dtable.cparam.width)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for direct entries") + + /* Initialize new direct block entries */ + for(u = (iblock->next_dir_row * shared->man_dtable.cparam.width); + u < (iblock->ndir_rows * shared->man_dtable.cparam.width); + u++) { + iblock->dblock_ents[u].addr = HADDR_UNDEF; + iblock->dblock_ents[u].free_space = 0; + } /* end for */ + + /* Mark heap header as modified */ + shared->dirty = TRUE; + +HDfprintf(stderr, "%s: Adding direct block of different size to heap not supported\n", FUNC); +HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, NULL, "allocating objects from non root block not supported yet") + } /* end if */ + + /* Set address of indirect block */ + *addr_p = shared->man_dtable.table_addr; + + /* Set entry for direct block */ + *entry_p = iblock->next_dir_entry; + + /* Set size of direct block to create */ + *dblock_size = iblock->next_dir_size; + } /* end else */ + + /* Set return value */ + ret_value = iblock; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_man_iblock_place_dblock() */ + + +/*------------------------------------------------------------------------- * Function: H5HF_man_iblock_create * * Purpose: Allocate & initialize a managed indirect block * - * Return: Pointer to new direct block on success, NULL on failure + * Return: SUCCEED/FAIL * * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu @@ -1201,7 +1558,7 @@ done: */ static herr_t H5HF_man_iblock_create(H5RC_t *fh_shared, hid_t dxpl_id, - hsize_t block_off, unsigned nrows, haddr_t *addr_p) + hsize_t block_off, unsigned nrows, unsigned max_dir_rows, haddr_t *addr_p) { H5HF_shared_t *shared; /* Pointer to shared heap info */ H5HF_indirect_t *iblock = NULL; /* Pointer to indirect block */ @@ -1230,16 +1587,29 @@ H5HF_man_iblock_create(H5RC_t *fh_shared, hid_t dxpl_id, iblock->shared = fh_shared; H5RC_INC(iblock->shared); - /* Get the pointer to the shared B-tree info */ + /* Get the pointer to the shared heap info */ shared = H5RC_GET_OBJ(iblock->shared); HDassert(shared); + /* Make a reference to this block */ + if(NULL == (iblock->self = H5RC_create(iblock, H5HF_iblock_free))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create ref-count wrapper for indirect fractal heap block") + #ifdef QAK HDfprintf(stderr, "%s: nrows = %u\n", FUNC, nrows); #endif /* QAK */ /* Set info for direct block */ + iblock->parent = NULL; /* Temporary, except for root indirect block */ + iblock->parent_entry = 0; iblock->block_off = block_off; + iblock->child_free_space = 0; iblock->nrows = nrows; + iblock->dir_full = FALSE; + iblock->next_dir_col = 0; + iblock->next_dir_row = 0; + iblock->next_dir_entry = 0; + iblock->next_dir_size = shared->man_dtable.cparam.start_block_size; + iblock->max_direct_rows = max_dir_rows; if(iblock->nrows > shared->man_dtable.max_direct_rows) { iblock->ndir_rows = shared->man_dtable.max_direct_rows; iblock->nindir_rows = iblock->nrows - iblock->ndir_rows; @@ -1270,9 +1640,9 @@ HDfprintf(stderr, "%s: nrows = %u\n", FUNC, nrows); for(u = 0; u < (iblock->nindir_rows * shared->man_dtable.cparam.width); u++) iblock->iblock_ents[u].addr = HADDR_UNDEF; - /* Allocate space for the header on disk */ + /* Allocate space for the indirect block on disk */ if(HADDR_UNDEF == (*addr_p = H5MF_alloc(shared->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, (hsize_t)iblock->size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap header") + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap indirect block") /* XXX: Update indirect statistics when they are added */ #ifdef LATER diff --git a/src/H5HFpkg.h b/src/H5HFpkg.h index 27085fd..7ccf879 100644 --- a/src/H5HFpkg.h +++ b/src/H5HFpkg.h @@ -66,8 +66,6 @@ + H5F_SIZEOF_ADDR(f) /* File address of table managed */ \ + 2 /* Current # of rows in root indirect block */ \ + H5F_SIZEOF_SIZE(f) /* Next direct block's heap offset */ \ - + H5F_SIZEOF_SIZE(f) /* Next direct block's size */ \ - + 2 /* Next direct block's column */ \ ) /* Size of the fractal heap header on disk */ @@ -121,7 +119,6 @@ /* Fractal heap managed, absolutely mapped direct block specific fields */ \ + H5F_SIZEOF_ADDR((s)->f) /* File address of heap owning the block */ \ + (s)->heap_off_size /* Offset of the block in the heap */ \ - + (d)->blk_off_size /* Total free space in a block */ \ + (d)->blk_off_size /* Offset of first descriptor in free list */ \ ) @@ -134,7 +131,7 @@ + H5F_SIZEOF_ADDR((s)->f) /* File address of heap owning the block */ \ + (s)->heap_off_size /* Offset of the block in the heap */ \ + ((i)->ndir_rows * (s)->man_dtable.cparam.width * (H5F_SIZEOF_ADDR((s)->f) + (s)->man_dtable.max_dir_blk_off_size)) /* Size of entries for direct blocks */ \ - + ((i)->nindir_rows * (s)->man_dtable.cparam.width * H5F_SIZEOF_ADDR((s)->f)) /* Size of entries for indirect blocks */ \ + + ((i)->nindir_rows * (s)->man_dtable.cparam.width * (H5F_SIZEOF_ADDR((s)->f) + (s)->heap_off_size)) /* Size of entries for indirect blocks */ \ ) @@ -159,9 +156,8 @@ typedef struct H5HF_dtable_t { * to direct block (of START_BLOCK_SIZE) instead * of indirect root block. */ +/* XXX: get rid of this global setting */ hsize_t next_dir_block; /* Offset of next direct managed block */ - size_t next_dir_size; /* Size of next managed direct block */ - unsigned next_dir_col; /* "Column" of next managed direct block (in doubling table) */ /* Computed information (not stored) */ unsigned max_root_indirect_rows; /* Maximum # of rows in root indirect block */ @@ -246,7 +242,9 @@ typedef struct H5HF_direct_t { H5AC_info_t cache_info; /* Internal heap information */ - H5RC_t *shared; /* Ref-counted shared info */ + H5RC_t *shared; /* Ref-counted shared heap info */ + H5RC_t *parent; /* Ref-counted shared parent block info */ + size_t parent_entry; /* Entry in parent's table */ size_t size; /* Size of direct block */ unsigned blk_off_size; /* Size of offsets in the block */ H5HF_direct_free_head_t *free_list; /* Pointer to free list for block */ @@ -268,6 +266,7 @@ typedef struct H5HF_indirect_dblock_ent_t { /* Indirect block indirect block entry */ typedef struct H5HF_indirect_iblock_ent_t { haddr_t addr; /* Indirect block's address */ + hsize_t free_space; /* Amount of free space in indirect block child */ } H5HF_indirect_iblock_ent_t; /* Fractal heap indirect block */ @@ -276,18 +275,37 @@ typedef struct H5HF_indirect_t { H5AC_info_t cache_info; /* Internal heap information */ + hbool_t dirty; /* Info is modified */ H5RC_t *shared; /* Ref-counted shared info */ + H5RC_t *parent; /* Ref-counted shared parent block info */ + size_t parent_entry; /* Entry in parent's table */ + H5RC_t *self; /* Ref-counted shared 'self' block info */ unsigned nrows; /* Total # of rows in indirect block */ unsigned ndir_rows; /* # of direct rows in indirect block */ unsigned nindir_rows; /* # of indirect rows in indirect block */ size_t size; /* Size of indirect block on disk */ + hbool_t dir_full; /* Flag to indicate that all direct blocks are allocated */ + unsigned next_dir_col; /* "Column" of next managed direct block (in doubling table) */ + unsigned next_dir_row; /* "Row" of next managed direct block (in doubling table) */ + unsigned next_dir_entry; /* Entry of next managed direct block */ + size_t next_dir_size; /* Size of next managed direct block */ + unsigned max_direct_rows; /* Maximum # of direct rows in indirect block */ H5HF_indirect_dblock_ent_t *dblock_ents; /* Pointer to direct block entry table */ H5HF_indirect_iblock_ent_t *iblock_ents; /* Pointer to indirect block entry table */ /* Stored values */ hsize_t block_off; /* Offset of the block within the heap's address space */ + hsize_t child_free_space; /* Total amount of free space in children */ } H5HF_indirect_t; +/* Shared information for parent of a fractal heap block */ +typedef struct H5HF_parent_shared_t { + H5RC_t *shared; /* Ref-counted shared heap info */ + H5RC_t *parent; /* Ref-counted shared parent block info */ + size_t parent_entry; /* Entry in parent's table */ + hsize_t parent_free_space; /* Free space in block, from parent */ +} H5HF_parent_shared_t; + /* Fractal heap metadata statistics info */ typedef struct H5HF_stat_t { hsize_t total_size; /* Total size of heap allocated (man & std) */ @@ -345,6 +363,9 @@ H5_DLL H5HF_shared_t * H5HF_shared_alloc(H5F_t *f); H5_DLL herr_t H5HF_shared_create(H5F_t *f, H5HF_t *fh, haddr_t heap_addr, H5HF_create_t *cparam); H5_DLL herr_t H5HF_shared_own(H5HF_t *fh, H5HF_shared_t *shared); +/* Indirect block routines */ +H5_DLL herr_t H5HF_iblock_free(void *_iblock); + /* Routines for allocating space */ H5_DLL herr_t H5HF_man_dblock_build_freelist(H5HF_direct_t *dblock, haddr_t dblock_addr); H5_DLL herr_t H5HF_man_find(H5RC_t *fh_shared, hid_t dxpl_id, size_t request, diff --git a/src/H5HFstat.c b/src/H5HFstat.c index 78be450..6cdc61b 100644 --- a/src/H5HFstat.c +++ b/src/H5HFstat.c @@ -37,6 +37,11 @@ /****************/ +/********************/ +/* Package Typedefs */ +/********************/ + + /******************/ /* Local Typedefs */ /******************/ diff --git a/src/H5HFtest.c b/src/H5HFtest.c index 43c9573..c96d516 100644 --- a/src/H5HFtest.c +++ b/src/H5HFtest.c @@ -44,6 +44,11 @@ /********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ /* Local Prototypes */ /********************/ diff --git a/test/fheap.c b/test/fheap.c index b20d333..8afaf36 100644 --- a/test/fheap.c +++ b/test/fheap.c @@ -175,7 +175,7 @@ fill_heap(H5F_t *f, hid_t dxpl, haddr_t fh_addr, hsize_t heap_size, /* Increment object count */ nobjs++; - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, heap_size, heap_size, (hsize_t)0, (hsize_t)(994 - (nobjs * (sizeof(obj) + 3))), (hsize_t)(start_nobjs + nobjs))) + if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, heap_size, heap_size, (hsize_t)0, (hsize_t)(996 - (nobjs * (sizeof(obj) + 3))), (hsize_t)(start_nobjs + nobjs))) FAIL_STACK_ERROR /* Get statistics for heap */ @@ -197,7 +197,7 @@ fill_heap(H5F_t *f, hid_t dxpl, haddr_t fh_addr, hsize_t heap_size, /* Increment object count */ nobjs++; - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, heap_size, heap_size, (hsize_t)0, (hsize_t)(994 - (nobjs * (sizeof(obj) + 3))), (hsize_t)(start_nobjs + nobjs))) + if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, heap_size, heap_size, (hsize_t)0, (hsize_t)(996 - (nobjs * (sizeof(obj) + 3))), (hsize_t)(start_nobjs + nobjs))) FAIL_STACK_ERROR /* Get statistics for heap */ @@ -386,7 +386,7 @@ test_abs_insert_first(hid_t fapl) heap_id = 0; if(H5HF_insert(f, dxpl, fh_addr, sizeof(obj), obj, &heap_id) < 0) FAIL_STACK_ERROR - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)1024, (hsize_t)1024, (hsize_t)0, (hsize_t)981, (hsize_t)1)) + if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)1024, (hsize_t)1024, (hsize_t)0, (hsize_t)983, (hsize_t)1)) FAIL_STACK_ERROR PASSED() @@ -464,13 +464,13 @@ test_abs_insert_second(hid_t fapl) heap_id = 0; if(H5HF_insert(f, dxpl, fh_addr, sizeof(obj), obj, &heap_id) < 0) FAIL_STACK_ERROR - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)1024, (hsize_t)1024, (hsize_t)0, (hsize_t)981, (hsize_t)1)) + if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)1024, (hsize_t)1024, (hsize_t)0, (hsize_t)983, (hsize_t)1)) FAIL_STACK_ERROR heap_id = 0; if(H5HF_insert(f, dxpl, fh_addr, sizeof(obj2), obj2, &heap_id) < 0) FAIL_STACK_ERROR - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)1024, (hsize_t)1024, (hsize_t)0, (hsize_t)958, (hsize_t)2)) + if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)1024, (hsize_t)1024, (hsize_t)0, (hsize_t)960, (hsize_t)2)) FAIL_STACK_ERROR PASSED() @@ -629,7 +629,7 @@ test_abs_insert_force_indirect(hid_t fapl) /* Increment object count */ nobjs++; - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)2048, (hsize_t)2048, (hsize_t)0, (hsize_t)981, (hsize_t)nobjs)) + if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)2048, (hsize_t)2048, (hsize_t)0, (hsize_t)983, (hsize_t)nobjs)) FAIL_STACK_ERROR PASSED() @@ -775,9 +775,6 @@ test_abs_insert_third_direct(hid_t fapl) FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR -#ifndef QAK -HDfprintf(stdout, "Fractal heap header address = %a\n", fh_addr); -#endif /* QAK */ /* * Test inserting mult. (small) objects to create third direct block @@ -800,18 +797,191 @@ HDfprintf(stdout, "Fractal heap header address = %a\n", fh_addr); for(u = 0; u < sizeof(obj); u++) obj[u] = u + nobjs; - /* Insert another object, forcing the creation of an indirect block for the root block */ + /* Insert another object, forcing the creation of the third direct block */ heap_id = 0; if(H5HF_insert(f, dxpl, fh_addr, sizeof(obj), obj, &heap_id) < 0) FAIL_STACK_ERROR + + /* Increment object count */ + tot_nobjs++; + + if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)3072, (hsize_t)3072, (hsize_t)0, (hsize_t)983, (hsize_t)tot_nobjs)) + FAIL_STACK_ERROR + + PASSED() + + /* Close the file */ + if(H5Fclose(file) < 0) + TEST_ERROR + + /* All tests passed */ + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_abs_insert_third_direct() */ + + +/*------------------------------------------------------------------------- + * Function: test_abs_fill_first_row + * + * Purpose: Test inserting mult. objects into absolute heap, creating + * enough direct blocks to fill first row of root indirect + * block. + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Monday, March 13, 2006 + * + *------------------------------------------------------------------------- + */ +static int +test_abs_fill_first_row(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + hid_t dxpl = H5P_DATASET_XFER_DEFAULT; /* DXPL to use */ + char filename[1024]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5HF_create_t cparam; /* Creation parameters for heap */ + haddr_t fh_addr; /* Address of fractal heap created */ + unsigned nobjs = 0; /* Number of objects inserted */ + unsigned tot_nobjs = 0; /* Total number of objects inserted */ + unsigned u; /* Local index variable */ + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + STACK_ERROR + + /* Create absolute heap */ + init_std_cparam(&cparam); + if(H5HF_create(f, dxpl, &cparam, &fh_addr/*out*/) < 0) + FAIL_STACK_ERROR + if(!H5F_addr_defined(fh_addr)) + FAIL_STACK_ERROR + + /* + * Test inserting mult. (small) objects to fill first row in root indirect block + */ + TESTING("inserting enough objects to fill first row of root indirect block"); + + /* Loop over filling direct blocks, until first root indirect row is full */ + for(u = 0; u < STD_MAN_WIDTH; u++) { + /* Fill a direct heap block up */ + if(fill_heap(f, dxpl, fh_addr, (hsize_t)(u + 1) * STD_MAN_START_BLOCK_SIZE, tot_nobjs, &nobjs)) + FAIL_STACK_ERROR + tot_nobjs += nobjs; + } /* end for */ + + PASSED() + + /* Close the file */ + if(H5Fclose(file) < 0) + TEST_ERROR + + /* All tests passed */ + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_abs_fill_first_row() */ + + +/*------------------------------------------------------------------------- + * Function: test_abs_start_second_row + * + * Purpose: Test inserting mult. objects into absolute heap, creating + * enough direct blocks to fill first row of root indirect + * block, then add another object to start second row. + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Tuesday, March 14, 2006 + * + *------------------------------------------------------------------------- + */ +static int +test_abs_start_second_row(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + hid_t dxpl = H5P_DATASET_XFER_DEFAULT; /* DXPL to use */ + char filename[1024]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5HF_create_t cparam; /* Creation parameters for heap */ + haddr_t fh_addr; /* Address of fractal heap created */ + unsigned char obj[10]; /* Buffer for first object to insert */ + hsize_t heap_id; /* Heap ID for object inserted */ + unsigned nobjs = 0; /* Number of objects inserted */ + unsigned tot_nobjs = 0; /* Total number of objects inserted */ + unsigned u; /* Local index variable */ + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + STACK_ERROR + + /* Create absolute heap */ + init_std_cparam(&cparam); + if(H5HF_create(f, dxpl, &cparam, &fh_addr/*out*/) < 0) + FAIL_STACK_ERROR + if(!H5F_addr_defined(fh_addr)) + FAIL_STACK_ERROR #ifndef QAK -HDfprintf(stdout, "heap_id = %Hu\n", heap_id); +HDfprintf(stderr, "Fractal heap header address = %a\n", fh_addr); #endif /* QAK */ + /* + * Test inserting mult. (small) objects to start second row in root indirect block + */ + TESTING("inserting enough objects to start second row of root indirect block"); + + /* Loop over filling direct blocks, until first root indirect row is full */ + for(u = 0; u < STD_MAN_WIDTH; u++) { + /* Fill a direct heap block up */ + if(fill_heap(f, dxpl, fh_addr, (hsize_t)(u + 1) * STD_MAN_START_BLOCK_SIZE, tot_nobjs, &nobjs)) + FAIL_STACK_ERROR + tot_nobjs += nobjs; + } /* end for */ + + /* Insert one more object, to force root indirect block creation */ + + /* Initialize object buffer */ + for(u = 0; u < sizeof(obj); u++) + obj[u] = u + tot_nobjs; + + /* Insert another object, forcing the creation of an indirect block for the root block */ + heap_id = 0; + if(H5HF_insert(f, dxpl, fh_addr, sizeof(obj), obj, &heap_id) < 0) + FAIL_STACK_ERROR + /* Increment object count */ nobjs++; - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)3072, (hsize_t)3072, (hsize_t)0, (hsize_t)982, (hsize_t)nobjs)) + if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)((STD_MAN_WIDTH + 1) * STD_MAN_START_BLOCK_SIZE), (hsize_t)((STD_MAN_WIDTH + 1) * STD_MAN_START_BLOCK_SIZE), (hsize_t)0, (hsize_t)983, (hsize_t)nobjs)) FAIL_STACK_ERROR PASSED() @@ -828,7 +998,7 @@ error: H5Fclose(file); } H5E_END_TRY; return(1); -} /* test_abs_insert_third_direct() */ +} /* test_abs_start_second_row() */ /*------------------------------------------------------------------------- @@ -865,11 +1035,15 @@ main(void) nerrors += test_abs_insert_root_mult(fapl); nerrors += test_abs_insert_force_indirect(fapl); nerrors += test_abs_insert_fill_second(fapl); + nerrors += test_abs_insert_third_direct(fapl); + nerrors += test_abs_fill_first_row(fapl); #else /* QAK */ HDfprintf(stderr, "Uncomment tests!\n"); #endif /* QAK */ #ifdef QAK - nerrors += test_abs_insert_third_direct(fapl); + nerrors += test_abs_start_second_row(fapl); +#else /* QAK */ +HDfprintf(stderr, "Uncomment tests!\n"); #endif /* QAK */ if(nerrors) -- cgit v0.12