diff options
Diffstat (limited to 'src/H5HFcache.c')
-rw-r--r-- | src/H5HFcache.c | 482 |
1 files changed, 314 insertions, 168 deletions
diff --git a/src/H5HFcache.c b/src/H5HFcache.c index 1fd3b51..ab6ea76 100644 --- a/src/H5HFcache.c +++ b/src/H5HFcache.c @@ -259,7 +259,6 @@ static H5HF_t * H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *udata1, void UNUSED *udata2) { H5HF_t *fh = NULL; /* Fractal heap info */ - H5HF_shared_t *shared = NULL; /* Shared fractal heap information */ size_t size; /* Header size */ uint8_t *buf = NULL; /* Temporary buffer */ const uint8_t *p; /* Pointer into raw data buffer */ @@ -267,23 +266,23 @@ H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *ud H5HF_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5HF_cache_hdr_load, NULL) +#ifdef QAK +HDfprintf(stderr, "%s: Load heap header, addr = %a\n", FUNC, addr); +#endif /* QAK */ /* Check arguments */ HDassert(f); HDassert(H5F_addr_defined(addr)); /* Allocate space for the fractal heap data structure */ - if(NULL == (fh = H5FL_MALLOC(H5HF_t))) + if(NULL == (fh = H5HF_alloc(f))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - HDmemset(&fh->cache_info, 0, sizeof(H5AC_info_t)); - /* Allocate & basic initialization for the shared info struct */ - if(NULL == (shared = H5HF_shared_alloc(f))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate space for shared heap info") - shared->heap_addr = addr; + /* Set the heap header's address */ + fh->heap_addr = addr; /* Compute the size of the fractal heap header on disk */ - size = H5HF_HEADER_SIZE(shared); + size = H5HF_HEADER_SIZE(fh); /* Allocate temporary buffer */ if((buf = H5FL_BLK_MALLOC(header_block, size)) == NULL) @@ -316,36 +315,33 @@ H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *ud HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect metadata checksum for fractal heap header") /* Heap address mapping */ - shared->addrmap = *p++; + fh->addrmap = *p++; HDassert(H5HF_ABSOLUTE == 0); - if(shared->addrmap > H5HF_MAPPED) + if(fh->addrmap > H5HF_MAPPED) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect fractal heap address mapping") /* Min. size of standalone objects */ - UINT32DECODE(p, shared->standalone_size); - - /* Size of ref. count for objects in heap */ - shared->ref_count_size = *p++; + UINT32DECODE(p, fh->standalone_size); /* Internal management information */ - H5F_DECODE_LENGTH(f, p, shared->total_man_free); - H5F_DECODE_LENGTH(f, p, shared->total_std_free); + H5F_DECODE_LENGTH(f, p, fh->total_man_free); + H5F_DECODE_LENGTH(f, p, fh->total_std_free); /* Statistics information */ - H5F_DECODE_LENGTH(f, p, shared->total_size); - H5F_DECODE_LENGTH(f, p, shared->man_size); - H5F_DECODE_LENGTH(f, p, shared->std_size); - H5F_DECODE_LENGTH(f, p, shared->nobjs); + H5F_DECODE_LENGTH(f, p, fh->total_size); + H5F_DECODE_LENGTH(f, p, fh->man_size); + H5F_DECODE_LENGTH(f, p, fh->std_size); + H5F_DECODE_LENGTH(f, p, fh->nobjs); /* Managed objects' doubling-table info */ - if(H5HF_dtable_decode(shared->f, &p, &(shared->man_dtable)) < 0) + if(H5HF_dtable_decode(fh->f, &p, &(fh->man_dtable)) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTENCODE, NULL, "unable to encode managed obj. doubling table info") HDassert((size_t)(p - buf) == size); /* Make shared heap info reference counted */ - if(H5HF_shared_own(fh, shared) < 0) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't create ref-count wrapper for shared fractal heap info") + if(H5HF_finish_init(fh) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't create ref-count wrapper for shared fractal heap header") /* Set return value */ ret_value = fh; @@ -376,30 +372,28 @@ done: static herr_t H5HF_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_t *fh) { - H5HF_shared_t *shared; /* Shared fractal heap information */ - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5HF_cache_hdr_flush, FAIL) +#ifdef QAK +HDfprintf(stderr, "%s: Flushing heap header, addr = %a, destroy = %u\n", FUNC, addr, (unsigned)destroy); +#endif /* QAK */ /* check arguments */ HDassert(f); HDassert(H5F_addr_defined(addr)); HDassert(fh); - /* Get the pointer to the shared heap info */ - shared = H5RC_GET_OBJ(fh->shared); - HDassert(shared); - if(fh->cache_info.is_dirty) { uint8_t *buf = NULL; /* Temporary raw data buffer */ uint8_t *p; /* Pointer into raw data buffer */ size_t size; /* Header size on disk */ /* Sanity check */ - HDassert(shared->dirty); + HDassert(fh->dirty); /* Compute the size of the heap header on disk */ - size = H5HF_HEADER_SIZE(shared); + size = H5HF_HEADER_SIZE(fh); /* Allocate temporary buffer */ if((buf = H5FL_BLK_MALLOC(header_block, size)) == NULL) @@ -424,26 +418,23 @@ H5HF_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5H p += 4; /* Heap address mapping */ - *p++ = shared->addrmap; + *p++ = fh->addrmap; /* Min. size of standalone objects */ - UINT32ENCODE(p, shared->standalone_size); - - /* Size of ref. count for objects in heap */ - *p++ = shared->ref_count_size; + UINT32ENCODE(p, fh->standalone_size); /* Internal management information */ - H5F_ENCODE_LENGTH(f, p, shared->total_man_free); - H5F_ENCODE_LENGTH(f, p, shared->total_std_free); + H5F_ENCODE_LENGTH(f, p, fh->total_man_free); + H5F_ENCODE_LENGTH(f, p, fh->total_std_free); /* Statistics information */ - H5F_ENCODE_LENGTH(f, p, shared->total_size); - H5F_ENCODE_LENGTH(f, p, shared->man_size); - H5F_ENCODE_LENGTH(f, p, shared->std_size); - H5F_ENCODE_LENGTH(f, p, shared->nobjs); + H5F_ENCODE_LENGTH(f, p, fh->total_size); + H5F_ENCODE_LENGTH(f, p, fh->man_size); + H5F_ENCODE_LENGTH(f, p, fh->std_size); + H5F_ENCODE_LENGTH(f, p, fh->nobjs); /* Managed objects' doubling-table info */ - if(H5HF_dtable_encode(shared->f, &p, &(shared->man_dtable)) < 0) + if(H5HF_dtable_encode(fh->f, &p, &(fh->man_dtable)) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTENCODE, FAIL, "unable to encode managed obj. doubling table info") /* Write the heap header. */ @@ -453,7 +444,7 @@ H5HF_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5H H5FL_BLK_FREE(header_block, buf); - shared->dirty = FALSE; + fh->dirty = FALSE; fh->cache_info.is_dirty = FALSE; } /* end if */ @@ -467,6 +458,47 @@ done: /*------------------------------------------------------------------------- + * Function: H5HF_cache_hdr_dest_real + * + * Purpose: Destroys a fractal heap header in memory. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 24 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_cache_hdr_dest_real(H5HF_t *fh) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_cache_hdr_dest_real) + + /* + * Check arguments. + */ + HDassert(fh); +/* XXX: Take out this goofy routine, after metadata cache is supporting + * "un-evictable" flag + */ + if(fh->rc == 0 && fh->evicted == TRUE) { + /* Free the free list information for the heap */ + if(fh->flist) + H5HF_flist_free(fh->flist); + + /* Free the block size lookup table for the doubling table */ + H5HF_dtable_dest(&fh->man_dtable); + + /* Free the shared info itself */ + H5FL_FREE(H5HF_t, fh); + } /* end if */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HF_cache_hdr_dest_real() */ + + +/*------------------------------------------------------------------------- * Function: H5HF_cache_hdr_dest * * Purpose: Destroys a fractal heap header in memory. @@ -489,13 +521,17 @@ H5HF_cache_hdr_dest(H5F_t UNUSED *f, H5HF_t *fh) * Check arguments. */ HDassert(fh); - - /* Decrement reference count on shared fractal heap info */ - if(fh->shared) - H5RC_DEC(fh->shared); - - /* Free fractal heap header info */ - H5FL_FREE(H5HF_t, fh); +/* XXX: Enable this after the metadata cache supports the "un-evictable" flag */ +/* HDassert(fh->rc == 0); */ +/* XXX: Take out this goofy 'if' statement, after metadata cache is supporting + * "un-evictable" flag + */ +/* XXX: Take out 'evicted' flag after "un-evictable" flag is working */ + fh->evicted = TRUE; +/* XXX: Take out this goofy routine, after metadata cache is supporting + * "un-evictable" flag + */ + H5HF_cache_hdr_dest_real(fh); FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5HF_cache_hdr_dest() */ @@ -556,8 +592,6 @@ done: static herr_t H5HF_cache_hdr_size(const H5F_t *f, const H5HF_t *fh, size_t *size_ptr) { - H5HF_shared_t *shared; /* Shared fractal heap information */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_cache_hdr_size) /* check arguments */ @@ -565,12 +599,8 @@ H5HF_cache_hdr_size(const H5F_t *f, const H5HF_t *fh, size_t *size_ptr) HDassert(fh); HDassert(size_ptr); - /* Get the pointer to the shared heap info */ - shared = H5RC_GET_OBJ(fh->shared); - HDassert(shared); - /* Set size value */ - *size_ptr = H5HF_HEADER_SIZE(shared); + *size_ptr = H5HF_HEADER_SIZE(fh); FUNC_LEAVE_NOAPI(SUCCEED) } /* H5HF_cache_hdr_size() */ @@ -592,11 +622,10 @@ H5HF_cache_hdr_size(const H5F_t *f, const H5HF_t *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 *_par_shared) +H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_size, void *_hdr) { const size_t *size = (const size_t *)_size; /* Size of block */ - 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_t *hdr = (H5HF_t *)_hdr; /* Shared heap header information */ H5HF_direct_t *dblock = NULL; /* Direct block info */ const uint8_t *p; /* Pointer into raw data buffer */ haddr_t heap_addr; /* Address of heap header in the file */ @@ -608,7 +637,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(par_shared); + HDassert(hdr); /* Allocate space for the fractal heap direct block */ if(NULL == (dblock = H5FL_MALLOC(H5HF_direct_t))) @@ -616,19 +645,9 @@ 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 = 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; + dblock->shared = hdr; + if(H5HF_hdr_incr(hdr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared heap header") /* Set block's internal information */ dblock->size = *size; @@ -668,11 +687,48 @@ H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_size, /* Address of heap that owns this block (skip) */ H5F_addr_decode(f, &p, &heap_addr); - if(H5F_addr_ne(heap_addr, shared->heap_addr)) + if(H5F_addr_ne(heap_addr, hdr->heap_addr)) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect heap header address for direct block") + /* Address of parent block */ + H5F_addr_decode(f, &p, &dblock->par_addr); + UINT16DECODE(p, dblock->par_entry); + UINT16DECODE(p, dblock->par_nrows); + if(H5F_addr_defined(dblock->par_addr)) { + H5HF_indirect_t *iblock; /* Pointer to parent indirect block */ + + /* Check for direct block as a child of the root indirect block + * and retrieve the # of rows in the root indirect block from + * the shared heap header, because the root indirect block can + * change size. + */ + if(H5F_addr_eq(iblock->par_addr, hdr->man_dtable.table_addr)) + dblock->par_nrows = hdr->man_dtable.curr_root_rows; + + /* Protect parent indirect block */ + if(NULL == (iblock = H5AC_protect(f, dxpl_id, H5AC_FHEAP_IBLOCK, dblock->par_addr, &dblock->par_nrows, hdr, hdr->mode))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap indirect block") + + /* Share parent block */ + dblock->parent = iblock; + if(H5HF_iblock_incr(iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared indirect block") + + /* Retrieve this block's free space from parent */ + dblock->blk_free_space = iblock->ents[dblock->par_entry].free_space; + + /* Release the indirect block */ + if(H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_IBLOCK, dblock->par_addr, iblock, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, NULL, "unable to release fractal heap indirect block") + } /* end if */ + else { + /* Direct block is linked directly from heap header */ + dblock->parent = NULL; + dblock->blk_free_space = hdr->total_man_free; + } /* end else */ + /* Offset of heap within the heap's address space */ - UINT64DECODE_VAR(p, dblock->block_off, shared->heap_off_size); + UINT64DECODE_VAR(p, dblock->block_off, hdr->heap_off_size); /* Offset of free list head */ /* (Defer deserializing the whole free list until we actually need to modify it) */ @@ -715,12 +771,11 @@ H5HF_cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, HDassert(dblock); if(dblock->cache_info.is_dirty) { - H5HF_shared_t *shared; /* Shared fractal heap information */ - uint8_t *p; /* Pointer into raw data buffer */ + H5HF_t *hdr; /* Shared fractal heap information */ + uint8_t *p; /* Pointer into raw data buffer */ - /* Get the pointer to the shared heap info */ - shared = H5RC_GET_OBJ(dblock->shared); - HDassert(shared); + /* Get the pointer to the shared heap header */ + hdr = dblock->shared; p = dblock->blk; @@ -741,20 +796,25 @@ H5HF_cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, p += 4; /* Address of heap header for heap which owns this block */ - H5F_addr_encode(f, &p, shared->heap_addr); + H5F_addr_encode(f, &p, hdr->heap_addr); + + /* Info for parent block of this block */ + H5F_addr_encode(f, &p, dblock->par_addr); + UINT16ENCODE(p, dblock->par_entry); + UINT16ENCODE(p, dblock->par_nrows); /* Offset of block in heap */ - UINT64ENCODE_VAR(p, dblock->block_off, shared->heap_off_size); + UINT64ENCODE_VAR(p, dblock->block_off, hdr->heap_off_size); /* Check for (currently) unsupported address mapping */ - if(shared->addrmap != H5HF_ABSOLUTE) + if(hdr->addrmap != H5HF_ABSOLUTE) HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "encoding mapped direct blocks not supported currently") /* Offset of free list head */ UINT64ENCODE_VAR(p, dblock->free_list_head, dblock->blk_off_size); /* Sanity check */ - HDassert((size_t)(p - dblock->blk) == H5HF_MAN_ABS_DIRECT_OVERHEAD_DBLOCK(shared, dblock)); + HDassert((size_t)(p - dblock->blk) == H5HF_MAN_ABS_DIRECT_OVERHEAD_DBLOCK(hdr, dblock)); /* Check for dirty free list */ if(dblock->free_list && dblock->free_list->dirty) { @@ -824,7 +884,9 @@ done: herr_t H5HF_cache_dblock_dest(H5F_t UNUSED *f, H5HF_direct_t *dblock) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_cache_dblock_dest) + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_cache_dblock_dest) /* * Check arguments. @@ -832,10 +894,12 @@ H5HF_cache_dblock_dest(H5F_t UNUSED *f, H5HF_direct_t *dblock) HDassert(dblock); /* Decrement reference count on shared fractal heap info */ - if(dblock->shared) - H5RC_DEC(dblock->shared); + HDassert(dblock->shared); + if(H5HF_hdr_decr(dblock->shared) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared heap header") if(dblock->parent) - H5RC_DEC(dblock->parent); + if(H5HF_iblock_decr(dblock->parent) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block") /* Check for free list & free it, if necessary */ if(dblock->free_list) { @@ -864,7 +928,8 @@ H5HF_cache_dblock_dest(H5F_t UNUSED *f, H5HF_direct_t *dblock) /* Free fractal heap direct block info */ H5FL_FREE(H5HF_direct_t, dblock); - FUNC_LEAVE_NOAPI(SUCCEED) +done: + FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_cache_dblock_dest() */ @@ -955,11 +1020,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 *_par_shared) +H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nrows, void *_hdr) { const unsigned *nrows = (const unsigned *)_nrows; /* # of rows in indirect block */ - 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_t *hdr = (H5HF_t *)_hdr; /* Shared header information */ H5HF_indirect_t *iblock = NULL; /* Indirect block info */ uint8_t *buf = NULL; /* Temporary buffer */ const uint8_t *p; /* Pointer into raw data buffer */ @@ -969,11 +1033,14 @@ H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nrows H5HF_indirect_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5HF_cache_iblock_load, NULL) +#ifdef QAK +HDfprintf(stderr, "%s: Load indirect block, addr = %a\n", FUNC, addr); +#endif /* QAK */ /* Check arguments */ HDassert(f); HDassert(H5F_addr_defined(addr)); - HDassert(par_shared); + HDassert(hdr); /* Allocate space for the fractal heap indirect block */ if(NULL == (iblock = H5FL_MALLOC(H5HF_indirect_t))) @@ -981,33 +1048,19 @@ 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 = 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") + iblock->shared = hdr; + if(H5HF_hdr_incr(hdr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared heap header") /* Set block's internal information */ + iblock->rc = 0; iblock->nrows = *nrows; - if(!iblock->parent) - iblock->max_rows = shared->man_dtable.max_root_rows; - else - iblock->max_rows = *nrows; + iblock->addr = addr; + iblock->dirty = FALSE; + iblock->evicted = FALSE; /* Compute size of indirect block */ - iblock->size = H5HF_MAN_INDIRECT_SIZE(shared, iblock); + iblock->size = H5HF_MAN_INDIRECT_SIZE(hdr, iblock); /* Allocate buffer to decode block */ /* XXX: Use free list factories? */ @@ -1042,33 +1095,77 @@ H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nrows /* Address of heap that owns this block */ H5F_addr_decode(f, &p, &heap_addr); - if(H5F_addr_ne(heap_addr, shared->heap_addr)) + if(H5F_addr_ne(heap_addr, hdr->heap_addr)) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect heap header address for direct block") + /* Address of parent block */ + H5F_addr_decode(f, &p, &iblock->par_addr); + UINT16DECODE(p, iblock->par_entry); + UINT16DECODE(p, iblock->par_nrows); + if(H5F_addr_defined(iblock->par_addr)) { + H5HF_indirect_t *tmp_iblock; /* Pointer to parent indirect block */ + + /* Check for indirect block as a child of the root indirect block + * and retrieve the # of rows in the root indirect block from + * the shared heap header, because the root indirect block can + * change size. + */ + if(H5F_addr_eq(iblock->par_addr, hdr->man_dtable.table_addr)) + iblock->par_nrows = hdr->man_dtable.curr_root_rows; + + /* Protect parent indirect block */ + if(NULL == (tmp_iblock = H5AC_protect(f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock->par_addr, &iblock->par_nrows, hdr, hdr->mode))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap indirect block") + + /* Share parent block */ + iblock->parent = tmp_iblock; + if(H5HF_iblock_incr(tmp_iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared indirect block") + + /* Retrieve this block's free space from parent */ + iblock->child_free_space = tmp_iblock->ents[iblock->par_entry].free_space; + + /* Release the indirect block */ + if(H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock->par_addr, tmp_iblock, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, NULL, "unable to release fractal heap indirect block") + tmp_iblock = NULL; + + /* Set max. # of rows in this block */ + iblock->max_rows = iblock->nrows; + } /* end if */ + else { + /* Direct block is linked directly from heap header */ + iblock->parent = NULL; + iblock->child_free_space = hdr->total_man_free; + + /* Set max. # of rows in this block */ + iblock->max_rows = hdr->man_dtable.max_root_rows; + } /* end else */ + /* Offset of heap within the heap's address space */ - UINT64DECODE_VAR(p, iblock->block_off, shared->heap_off_size); + UINT64DECODE_VAR(p, iblock->block_off, hdr->heap_off_size); /* Offset of next entry to allocate within this block */ UINT32DECODE(p, iblock->next_entry); /* Compute next block column, row & size */ - iblock->next_col = iblock->next_entry % shared->man_dtable.cparam.width; - iblock->next_row = iblock->next_entry / shared->man_dtable.cparam.width; - iblock->next_size = shared->man_dtable.row_block_size[iblock->next_row]; + iblock->next_col = iblock->next_entry % hdr->man_dtable.cparam.width; + iblock->next_row = iblock->next_entry / hdr->man_dtable.cparam.width; + iblock->next_size = hdr->man_dtable.row_block_size[iblock->next_row]; /* Allocate & decode indirect block entry tables */ HDassert(iblock->nrows > 0); - if(NULL == (iblock->ents = H5FL_SEQ_MALLOC(H5HF_indirect_ent_t, (iblock->nrows * shared->man_dtable.cparam.width)))) + if(NULL == (iblock->ents = H5FL_SEQ_MALLOC(H5HF_indirect_ent_t, (iblock->nrows * hdr->man_dtable.cparam.width)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for direct entries") - for(u = 0; u < (iblock->nrows * shared->man_dtable.cparam.width); u++) { + for(u = 0; u < (iblock->nrows * hdr->man_dtable.cparam.width); u++) { /* Decode block address */ H5F_addr_decode(f, &p, &(iblock->ents[u].addr)); /* Decode direct & indirect blocks differently */ - if(u < (shared->man_dtable.max_direct_rows * shared->man_dtable.cparam.width)) - UINT32DECODE_VAR(p, iblock->ents[u].free_space, shared->man_dtable.max_dir_blk_off_size) + if(u < (hdr->man_dtable.max_direct_rows * hdr->man_dtable.cparam.width)) + UINT32DECODE_VAR(p, iblock->ents[u].free_space, hdr->man_dtable.max_dir_blk_off_size) else - UINT64DECODE_VAR(p, iblock->ents[u].free_space, shared->heap_off_size) + UINT64DECODE_VAR(p, iblock->ents[u].free_space, hdr->heap_off_size) } /* end for */ /* Sanity check */ @@ -1108,6 +1205,9 @@ H5HF_cache_iblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5HF_cache_iblock_flush, FAIL) +#ifdef QAK +HDfprintf(stderr, "%s: Flushing indirect block, addr = %a, destroy = %u\n", FUNC, addr, (unsigned)destroy); +#endif /* QAK */ /* check arguments */ HDassert(f); @@ -1115,20 +1215,16 @@ H5HF_cache_iblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, HDassert(iblock); if(iblock->cache_info.is_dirty) { - H5HF_shared_t *shared; /* Shared fractal heap information */ - uint8_t *buf = NULL; /* Temporary buffer */ - uint8_t *p; /* Pointer into raw data buffer */ - size_t u; /* Local index variable */ + H5HF_t *hdr; /* Shared fractal heap information */ + uint8_t *buf = NULL; /* Temporary buffer */ + 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); + /* Get the pointer to the shared heap header */ + hdr = iblock->shared; /* Allocate buffer to encode block */ /* XXX: Use free list factories? */ @@ -1136,7 +1232,7 @@ HDfprintf(stderr, "%s: Flushing indirect block\n", FUNC); HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows); HDfprintf(stderr, "%s: iblock->size = %Zu\n", FUNC, iblock->size); HDfprintf(stderr, "%s: iblock->block_off = %Hu\n", FUNC, iblock->block_off); -HDfprintf(stderr, "%s: shared->man_dtable.cparam.width = %u\n", FUNC, shared->man_dtable.cparam.width); +HDfprintf(stderr, "%s: hdr->man_dtable.cparam.width = %u\n", FUNC, hdr->man_dtable.cparam.width); #endif /* QAK */ if((buf = H5FL_BLK_MALLOC(indirect_block, iblock->size)) == NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") @@ -1160,24 +1256,32 @@ HDfprintf(stderr, "%s: shared->man_dtable.cparam.width = %u\n", FUNC, shared->ma p += 4; /* Address of heap header for heap which owns this block */ - H5F_addr_encode(f, &p, shared->heap_addr); + H5F_addr_encode(f, &p, hdr->heap_addr); + + /* Info for parent block of this block */ + H5F_addr_encode(f, &p, iblock->par_addr); + UINT16ENCODE(p, iblock->par_entry); + UINT16ENCODE(p, iblock->par_nrows); /* Offset of block in heap */ - UINT64ENCODE_VAR(p, iblock->block_off, shared->heap_off_size); + UINT64ENCODE_VAR(p, iblock->block_off, hdr->heap_off_size); /* Next block entry to allocate from */ UINT32ENCODE(p, iblock->next_entry); /* Encode indirect block-specific fields */ - for(u = 0; u < (iblock->nrows * shared->man_dtable.cparam.width); u++) { + for(u = 0; u < (iblock->nrows * hdr->man_dtable.cparam.width); u++) { +#ifdef QAK +HDfprintf(stderr, "%s: iblock->ents[%Zu] = {%a, %Hu}\n", FUNC, u, iblock->ents[u].addr, iblock->ents[u].free_space); +#endif /* QAK */ /* Encode block address */ H5F_addr_encode(f, &p, iblock->ents[u].addr); /* Encode direct & indirect blocks differently */ - if(u < (shared->man_dtable.max_direct_rows * shared->man_dtable.cparam.width)) - UINT32ENCODE_VAR(p, iblock->ents[u].free_space, shared->man_dtable.max_dir_blk_off_size) + if(u < (hdr->man_dtable.max_direct_rows * hdr->man_dtable.cparam.width)) + UINT32ENCODE_VAR(p, iblock->ents[u].free_space, hdr->man_dtable.max_dir_blk_off_size) else - UINT64ENCODE_VAR(p, iblock->ents[u].free_space, shared->heap_off_size) + UINT64ENCODE_VAR(p, iblock->ents[u].free_space, hdr->heap_off_size) } /* end for */ /* Sanity check */ @@ -1190,6 +1294,8 @@ HDfprintf(stderr, "%s: shared->man_dtable.cparam.width = %u\n", FUNC, shared->ma /* Free buffer */ H5FL_BLK_FREE(indirect_block, buf); + /* Reset dirty flags */ + iblock->dirty = FALSE; iblock->cache_info.is_dirty = FALSE; } /* end if */ @@ -1203,6 +1309,58 @@ done: /*------------------------------------------------------------------------- + * Function: H5HF_cache_iblock_dest_real + * + * Purpose: Destroys a fractal heap indirect block in memory. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 6 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_cache_iblock_dest_real(H5HF_indirect_t *iblock) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_cache_iblock_dest_real) + + /* + * Check arguments. + */ + HDassert(iblock); +#ifdef QAK +HDfprintf(stderr, "%s: Destroying indirect block\n", "H5HF_cache_iblock_dest"); +#endif /* QAK */ +/* XXX: Take out this goofy routine, after metadata cache is supporting + * "un-evictable" flag + */ + if(iblock->rc == 0 && iblock->evicted) { + /* Decrement reference count on shared info */ + HDassert(iblock->shared); + if(H5HF_hdr_decr(iblock->shared) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared heap header") + if(iblock->parent) + if(H5HF_iblock_decr(iblock->parent) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block") + + /* Release entry tables */ + if(iblock->ents) + H5FL_SEQ_FREE(H5HF_indirect_ent_t, iblock->ents); + + /* Free fractal heap indirect block info */ + H5FL_FREE(H5HF_indirect_t, iblock); + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_cache_iblock_dest_real() */ + + +/*------------------------------------------------------------------------- * Function: H5HF_cache_iblock_dest * * Purpose: Destroys a fractal heap indirect block in memory. @@ -1219,34 +1377,28 @@ done: herr_t H5HF_cache_iblock_dest(H5F_t UNUSED *f, H5HF_indirect_t *iblock) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_cache_iblock_dest) + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_cache_iblock_dest) /* * Check arguments. */ HDassert(iblock); +/* XXX: Enable this after the metadata cache supports the "un-evictable" flag */ +/* HDassert(iblock->rc == 0); */ #ifdef QAK HDfprintf(stderr, "%s: Destroying indirect block\n", "H5HF_cache_iblock_dest"); #endif /* QAK */ - - /* 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: Take out 'evicted' flag after "un-evictable" flag is working */ + iblock->evicted = TRUE; +/* XXX: Take out this goofy routine, after metadata cache is supporting + * "un-evictable" flag */ -/* 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); + ret_value = H5HF_cache_iblock_dest_real(iblock); - FUNC_LEAVE_NOAPI(SUCCEED) +done: + FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_cache_iblock_dest() */ @@ -1305,18 +1457,12 @@ done: static herr_t H5HF_cache_iblock_size(const H5F_t UNUSED *f, const H5HF_indirect_t *iblock, size_t *size_ptr) { - H5HF_shared_t *shared; /* Shared fractal heap information */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_cache_iblock_size) /* check arguments */ HDassert(iblock); HDassert(size_ptr); - /* Get the pointer to the shared heap info */ - shared = H5RC_GET_OBJ(iblock->shared); - HDassert(shared); - /* Set size value */ *size_ptr = iblock->size; |