From 5a7ef381b26985886a88ad88b2afda703b578d24 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Fri, 18 Aug 2006 21:42:18 -0500 Subject: [svn-r12598] Description: - Migrate "direct block location" routine from H5HFman.c to H5HFdblock.c, which is a more appropriate location - Optimize performance of heap code by taking advantage of pinned indirect blocks and use them without putting a metadata cache protect/unprotect pair around them. - Other minor compiler warning cleanups and optimizations... Tested On: FreeBSD/32 4.11 (sleipnir) Linux/64 2.4 (mir) Solaris/64 2.9 (shanti) --- src/H5HF.c | 3 + src/H5HFcache.c | 16 +++ src/H5HFdbg.c | 7 +- src/H5HFdblock.c | 118 +++++++++++++++++++++ src/H5HFhdr.c | 16 +-- src/H5HFiblock.c | 304 ++++++++++++++++++++++++++++++++++++++++++++++++++---- src/H5HFiter.c | 6 +- src/H5HFman.c | 156 +++------------------------- src/H5HFpkg.h | 22 ++-- src/H5HFsection.c | 17 +-- test/fheap.c | 2 +- 11 files changed, 476 insertions(+), 191 deletions(-) diff --git a/src/H5HF.c b/src/H5HF.c index 12822d5..c1a46e0 100644 --- a/src/H5HF.c +++ b/src/H5HF.c @@ -680,6 +680,9 @@ HDfprintf(stderr, "%s: fh_addr = %a\n", FUNC, fh_addr); HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap header") /* Check for free space manager for heap */ + /* (must occur before attempting to delete the heap, so indirect blocks + * will get unpinned) + */ if(H5F_addr_defined(hdr->fs_addr)) { #ifdef QAK HDfprintf(stderr, "%s: hdr->fs_addr = %a\n", FUNC, hdr->fs_addr); diff --git a/src/H5HFcache.c b/src/H5HFcache.c index 63e4e46..e0b0c16 100644 --- a/src/H5HFcache.c +++ b/src/H5HFcache.c @@ -1164,6 +1164,20 @@ HDfprintf(stderr, "%s: iblock->ents[%Zu] = {%a}\n", FUNC, u, iblock->ents[u].add #endif /* QAK */ } /* end for */ + /* Check if we have any indirect block children */ + if(iblock->nrows > hdr->man_dtable.max_direct_rows) { + unsigned indir_rows; /* Number of indirect rows in this indirect block */ + + /* Compute the number of indirect rows for this indirect block */ + indir_rows = iblock->nrows - hdr->man_dtable.max_direct_rows; + + /* Allocate & initialize child indirect block pointer array */ + if(NULL == (iblock->child_iblocks = H5FL_SEQ_CALLOC(H5HF_indirect_ptr_t, (size_t)(indir_rows * hdr->man_dtable.cparam.width)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for block entries") + } /* end if */ + else + iblock->child_iblocks = NULL; + /* Sanity checks */ HDassert((size_t)(p - buf) == iblock->size); HDassert(iblock->nchildren); /* indirect blocks w/no children should have been deleted */ @@ -1372,6 +1386,8 @@ HDfprintf(stderr, "%s: Destroying indirect block\n", FUNC); H5FL_SEQ_FREE(H5HF_indirect_ent_t, iblock->ents); if(iblock->filt_ents) H5FL_SEQ_FREE(H5HF_indirect_filt_ent_t, iblock->filt_ents); + if(iblock->child_iblocks) + H5FL_SEQ_FREE(H5HF_indirect_ptr_t, iblock->child_iblocks); /* Free fractal heap indirect block info */ H5FL_FREE(H5HF_indirect_t, iblock); diff --git a/src/H5HFdbg.c b/src/H5HFdbg.c index b7d8b79..ce17e60 100644 --- a/src/H5HFdbg.c +++ b/src/H5HFdbg.c @@ -508,6 +508,7 @@ H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, { H5HF_hdr_t *hdr = NULL; /* Fractal heap header info */ H5HF_indirect_t *iblock = NULL; /* Fractal heap direct block info */ + hbool_t did_protect; /* Whether we protected the indirect block or not */ char temp_str[64]; /* Temporary string, for formatting */ size_t u, v; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ @@ -532,9 +533,9 @@ H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap header") /* - * Load the heap direct block + * Load the heap indirect block */ - if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, addr, nrows, NULL, 0, H5AC_READ))) + if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, addr, nrows, NULL, 0, FALSE, H5AC_READ, &did_protect))) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap indirect block") /* Print opening message */ @@ -604,7 +605,7 @@ H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, ""); done: - if(iblock && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_IBLOCK, addr, iblock, H5AC__NO_FLAGS_SET) < 0) + if(iblock && H5HF_man_iblock_unprotect(iblock, dxpl_id, H5AC__NO_FLAGS_SET, did_protect) < 0) HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release fractal heap direct block") if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, hdr_addr, hdr, H5AC__NO_FLAGS_SET) < 0) HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release fractal heap header") diff --git a/src/H5HFdblock.c b/src/H5HFdblock.c index e6b45ce..548e32f 100644 --- a/src/H5HFdblock.c +++ b/src/H5HFdblock.c @@ -491,6 +491,124 @@ done: /*------------------------------------------------------------------------- + * Function: H5HF_man_dblock_locate + * + * Purpose: Locate a direct block in a managed heap + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 8 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_man_dblock_locate(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t obj_off, + H5HF_indirect_t **ret_iblock, unsigned *ret_entry, hbool_t *ret_did_protect, + H5AC_protect_t rw) +{ + haddr_t iblock_addr; /* Indirect block's address */ + H5HF_indirect_t *iblock; /* Pointer to indirect block */ + hbool_t did_protect; /* Whether we protected the indirect block or not */ + unsigned row, col; /* Row & column for object's block */ + unsigned entry; /* Entry of block */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_man_dblock_locate) +#ifdef QAK +HDfprintf(stderr, "%s: obj_off = %Hu\n", FUNC, obj_off); +#endif /* QAK */ + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(hdr->man_dtable.curr_root_rows); /* Only works for heaps with indirect root block */ + HDassert(ret_iblock); + HDassert(ret_did_protect); + + /* Look up row & column for object */ + if(H5HF_dtable_lookup(&hdr->man_dtable, obj_off, &row, &col) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of object") +#ifdef QAK +HDfprintf(stderr, "%s: row = %u, col = %u\n", FUNC, row, col); +#endif /* QAK */ + + /* Set initial indirect block info */ + iblock_addr = hdr->man_dtable.table_addr; +#ifdef QAK +HDfprintf(stderr, "%s: iblock_addr = %a\n", FUNC, iblock_addr); +#endif /* QAK */ + + /* Lock root indirect block */ + if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, hdr->man_dtable.curr_root_rows, NULL, 0, FALSE, rw, &did_protect))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") + + /* Check for indirect block row */ + while(row >= hdr->man_dtable.max_direct_rows) { + H5HF_indirect_t *new_iblock; /* Pointer to new indirect block */ + hbool_t new_did_protect; /* Whether we protected the indirect block or not */ + unsigned nrows; /* Number of rows in new indirect block */ + unsigned cache_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting parent indirect block */ + + /* Compute # of rows in child indirect block */ + nrows = (H5V_log2_gen(hdr->man_dtable.row_block_size[row]) - hdr->man_dtable.first_row_bits) + 1; + + /* Compute indirect block's entry */ + entry = (row * hdr->man_dtable.cparam.width) + col; +#ifdef QAK +HDfprintf(stderr, "%s: entry = %Zu\n", FUNC, entry); +#endif /* QAK */ + + /* Locate child indirect block */ + iblock_addr = iblock->ents[entry].addr; + + /* Check if we need to (re-)create the child indirect block */ + if(!H5F_addr_defined(iblock_addr)) { + if(H5HF_man_iblock_create(hdr, dxpl_id, iblock, entry, nrows, nrows, &iblock_addr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap indirect block") + + /* Indicate that the parent indirect block was modified */ + cache_flags |= H5AC__DIRTIED_FLAG; + } /* end if */ + + /* Lock child indirect block */ + if(NULL == (new_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, nrows, iblock, entry, FALSE, rw, &new_did_protect))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") + + /* Release the current indirect block */ + if(H5HF_man_iblock_unprotect(iblock, dxpl_id, cache_flags, did_protect) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") + + /* Switch variables to use new indirect block */ + iblock = new_iblock; + did_protect = new_did_protect; +#ifdef QAK +HDfprintf(stderr, "%s: iblock->addr = %a\n", FUNC, iblock->addr); +HDfprintf(stderr, "%s: iblock->block_off = %Hu\n", FUNC, iblock->block_off); +#endif /* QAK */ + + /* Look up row & column in new indirect block for object */ + if(H5HF_dtable_lookup(&hdr->man_dtable, (obj_off - iblock->block_off), &row, &col) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of object") +#ifdef QAK +HDfprintf(stderr, "%s: row = %u, col = %u\n", FUNC, row, col); +#endif /* QAK */ + } /* end while */ + + /* Set return parameters */ + if(ret_entry) + *ret_entry = (row * hdr->man_dtable.cparam.width) + col; + *ret_iblock = iblock; + *ret_did_protect = did_protect; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_man_dblock_locate() */ + + +/*------------------------------------------------------------------------- * Function: H5HF_man_dblock_delete * * Purpose: Delete a managed direct block diff --git a/src/H5HFhdr.c b/src/H5HFhdr.c index 8376da4..e239aeb 100644 --- a/src/H5HFhdr.c +++ b/src/H5HFhdr.c @@ -1086,6 +1086,7 @@ HDfprintf(stderr, "%s: child_entry = %u\n", FUNC, child_entry); } /* end if */ else { H5HF_indirect_t *new_iblock; /* Pointer to new indirect block */ + hbool_t did_protect; /* Whether we protected the indirect block or not */ haddr_t new_iblock_addr; /* New indirect block's address */ #ifdef QAK @@ -1096,10 +1097,10 @@ HDfprintf(stderr, "%s: Allocating new child indirect block\n", FUNC); HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap indirect block") /* Lock new indirect block */ - if(NULL == (new_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, new_iblock_addr, child_nrows, iblock, next_entry, H5AC_WRITE))) + if(NULL == (new_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, new_iblock_addr, child_nrows, iblock, next_entry, FALSE, H5AC_WRITE, &did_protect))) HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") - /* Move iterator down one level */ + /* Move iterator down one level (pins indirect block) */ if(H5HF_man_iter_down(&hdr->next_block, new_iblock) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTNEXT, FAIL, "unable to advance current block iterator location") @@ -1119,7 +1120,7 @@ HDfprintf(stderr, "%s: Skipping rows in new child indirect block - new_entry = % } /* end if */ /* Unprotect child indirect block */ - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, new_iblock->addr, new_iblock, H5AC__NO_FLAGS_SET) < 0) + if(H5HF_man_iblock_unprotect(new_iblock, dxpl_id, H5AC__NO_FLAGS_SET, did_protect) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") } /* end else */ @@ -1321,8 +1322,9 @@ HDfprintf(stderr, "%s: curr_entry = %u\n", FUNC, curr_entry); #endif /* QAK */ } /* end if */ else { - H5HF_indirect_t *child_iblock; /* Pointer to child indirect block */ - unsigned child_nrows; /* # of rows in child block */ + H5HF_indirect_t *child_iblock; /* Pointer to child indirect block */ + hbool_t did_protect; /* Whether we protected the indirect block or not */ + unsigned child_nrows; /* # of rows in child block */ #ifdef QAK HDfprintf(stderr, "%s: Walking down into child block\n", FUNC); @@ -1331,7 +1333,7 @@ HDfprintf(stderr, "%s: Walking down into child block\n", FUNC); child_nrows = H5HF_dtable_size_to_rows(&hdr->man_dtable, hdr->man_dtable.row_block_size[row]); /* Lock child indirect block */ - if(NULL == (child_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock->ents[curr_entry].addr, child_nrows, iblock, curr_entry, H5AC_WRITE))) + if(NULL == (child_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock->ents[curr_entry].addr, child_nrows, iblock, curr_entry, FALSE, H5AC_WRITE, &did_protect))) HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") /* Set the current location of the iterator */ @@ -1352,7 +1354,7 @@ HDfprintf(stderr, "%s: curr_entry = %u\n", FUNC, curr_entry); #endif /* QAK */ /* Unprotect child indirect block */ - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, child_iblock->addr, child_iblock, H5AC__NO_FLAGS_SET) < 0) + if(H5HF_man_iblock_unprotect(child_iblock, dxpl_id, H5AC__NO_FLAGS_SET, did_protect) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") /* Note that we walked down */ diff --git a/src/H5HFiblock.c b/src/H5HFiblock.c index 70e3aac..6d0df44 100644 --- a/src/H5HFiblock.c +++ b/src/H5HFiblock.c @@ -56,6 +56,8 @@ /********************/ /* Local Prototypes */ /********************/ +static herr_t H5HF_iblock_pin(H5HF_indirect_t *iblock); +static herr_t H5HF_iblock_unpin(H5HF_indirect_t *iblock); static herr_t H5HF_man_iblock_root_halve(H5HF_indirect_t *root_iblock, hid_t dxpl_id); static herr_t H5HF_man_iblock_root_revert(H5HF_indirect_t *root_iblock, hid_t dxpl_id); @@ -73,6 +75,9 @@ H5FL_SEQ_DEFINE(H5HF_indirect_ent_t); /* Declare a free list to manage the H5HF_indirect_filt_ent_t sequence information */ H5FL_SEQ_DEFINE(H5HF_indirect_filt_ent_t); +/* Declare a free list to manage the H5HF_indirect_t * sequence information */ +H5FL_SEQ_DEFINE(H5HF_indirect_ptr_t); + /*****************************/ /* Library Private Variables */ @@ -86,6 +91,122 @@ H5FL_SEQ_DEFINE(H5HF_indirect_filt_ent_t); /*------------------------------------------------------------------------- + * Function: H5HF_iblock_pin + * + * Purpose: Pin an indirect block in memory + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Aug 17 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_iblock_pin(H5HF_indirect_t *iblock) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_iblock_pin) + + /* Sanity checks */ + HDassert(iblock); + + /* Mark block as un-evictable */ + if(H5AC_pin_protected_entry(iblock->hdr->f, iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPIN, FAIL, "unable to pin fractal heap indirect block") + + /* If this indirect block has a parent, update it's child iblock pointer */ + if(iblock->parent) { + H5HF_indirect_t *par_iblock = iblock->parent; /* Parent indirect block */ + unsigned indir_idx; /* Index in parent's child iblock pointer array */ + + /* Sanity check */ + HDassert(par_iblock->child_iblocks); + HDassert(iblock->par_entry >= (iblock->hdr->man_dtable.max_direct_rows + * iblock->hdr->man_dtable.cparam.width)); + + /* Compute index in parent's child iblock pointer array */ + indir_idx = iblock->par_entry - (iblock->hdr->man_dtable.max_direct_rows + * iblock->hdr->man_dtable.cparam.width); + + /* Set pointer to pinned indirect block in parent */ + HDassert(par_iblock->child_iblocks[indir_idx] == NULL); + par_iblock->child_iblocks[indir_idx] = iblock; + } /* end if */ + else { + /* Check for pinning the root indirect block */ + if(iblock->block_off == 0) { + HDassert(iblock->hdr->root_iblock == NULL); + iblock->hdr->root_iblock = iblock; + } /* end if */ + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_iblock_pin() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_iblock_unpin + * + * Purpose: Unpin an indirect block in the metadata cache + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Aug 17 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_iblock_unpin(H5HF_indirect_t *iblock) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_iblock_unpin) + + /* Sanity check */ + HDassert(iblock); + + /* If this indirect block has a parent, reset it's child iblock pointer */ + if(iblock->parent) { + H5HF_indirect_t *par_iblock = iblock->parent; /* Parent indirect block */ + unsigned indir_idx; /* Index in parent's child iblock pointer array */ + + /* Sanity check */ + HDassert(par_iblock->child_iblocks); + HDassert(iblock->par_entry >= (iblock->hdr->man_dtable.max_direct_rows + * iblock->hdr->man_dtable.cparam.width)); + + /* Compute index in parent's child iblock pointer array */ + indir_idx = iblock->par_entry - (iblock->hdr->man_dtable.max_direct_rows + * iblock->hdr->man_dtable.cparam.width); + + /* Reset pointer to pinned child indirect block in parent */ + HDassert(par_iblock->child_iblocks[indir_idx]); + par_iblock->child_iblocks[indir_idx] = NULL; + } /* end if */ + else { + /* Check for unpinning the root indirect block */ + if(iblock->block_off == 0) { + HDassert(iblock->hdr->root_iblock); + iblock->hdr->root_iblock = NULL; + } /* end if */ + } /* end if */ + + /* Mark block as evictable again */ + if(H5AC_unpin_entry(iblock->hdr->f, iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPIN, FAIL, "unable to unpin fractal heap indirect block") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_iblock_unpin() */ + + +/*------------------------------------------------------------------------- * Function: H5HF_iblock_incr * * Purpose: Increment reference count on shared indirect block @@ -105,12 +226,13 @@ H5HF_iblock_incr(H5HF_indirect_t *iblock) FUNC_ENTER_NOAPI_NOINIT(H5HF_iblock_incr) - /* Sanity check */ + /* Sanity checks */ HDassert(iblock); + HDassert(iblock->block_off == 0 || iblock->parent); /* Mark block as un-evictable when a child block is depending on it */ if(iblock->rc == 0) - if(H5AC_pin_protected_entry(iblock->hdr->f, iblock) < 0) + if(H5HF_iblock_pin(iblock) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTPIN, FAIL, "unable to pin fractal heap indirect block") /* Increment reference count on shared indirect block */ @@ -160,7 +282,7 @@ HDfprintf(stderr, "%s: iblock->block_off = %Hu\n", FUNC, iblock->block_off); #ifdef QAK HDfprintf(stderr, "%s: indirect block ref. count at zero, iblock->addr = %a\n", FUNC, iblock->addr); #endif /* QAK */ - if(H5AC_unpin_entry(iblock->hdr->f, iblock) < 0) + if(H5HF_iblock_unpin(iblock) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPIN, FAIL, "unable to unpin fractal heap indirect block") if(iblock->nchildren == 0) { @@ -257,6 +379,7 @@ H5HF_man_iblock_root_create(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t min_dblock_si haddr_t iblock_addr; /* Indirect block's address */ hsize_t acc_dblock_free; /* Accumulated free space in direct blocks */ hbool_t have_direct_block; /* Flag to indicate a direct block already exists */ + hbool_t did_protect; /* Whether we protected the indirect block or not */ unsigned nrows; /* Number of rows for root indirect block */ unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ @@ -297,7 +420,7 @@ HDfprintf(stderr, "%s: iblock_addr = %a\n", FUNC, iblock_addr); /* Move current direct block (used as root) into new indirect block */ /* Lock new indirect block */ - if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, nrows, NULL, 0, H5AC_WRITE))) + if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, nrows, NULL, 0, FALSE, H5AC_WRITE, &did_protect))) HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") /* Check if there's already a direct block as root) */ @@ -341,7 +464,7 @@ HDfprintf(stderr, "%s: have_direct_block = %u\n", FUNC, (unsigned)have_direct_bl HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty") /* Unprotect root indirect block (it's pinned by the iterator though) */ - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock->addr, iblock, H5AC__DIRTIED_FLAG) < 0) + if(H5HF_man_iblock_unprotect(iblock, dxpl_id, H5AC__DIRTIED_FLAG, did_protect) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") iblock = NULL; @@ -504,7 +627,6 @@ HDfprintf(stderr, "%s: Check 1.0 - iblock->addr = %a, new_addr = %a\n", FUNC, ib /* Compute the number of direct rows for this indirect block */ dir_rows = MIN(iblock->nrows, hdr->man_dtable.max_direct_rows); -HDfprintf(stderr, "%s: dir_rows = %u\n", FUNC, dir_rows); HDassert(dir_rows > old_nrows); /* Re-allocate filtered direct block entry array */ @@ -518,6 +640,29 @@ HDfprintf(stderr, "%s: dir_rows = %u\n", FUNC, dir_rows); } /* end for */ } /* end if */ + /* Check for needing to re-allocate child iblock pointer array */ + if(iblock->nrows > hdr->man_dtable.max_direct_rows) { + unsigned indir_rows; /* Number of indirect rows in this indirect block */ + unsigned old_indir_rows; /* Previous number of indirect rows in this indirect block */ + + /* Compute the number of direct rows for this indirect block */ + indir_rows = iblock->nrows - hdr->man_dtable.max_direct_rows; + + /* Re-allocate child indirect block array */ + if(NULL == (iblock->child_iblocks = H5FL_SEQ_REALLOC(H5HF_indirect_ptr_t, iblock->child_iblocks, (size_t)(indir_rows * hdr->man_dtable.cparam.width)))) + HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "memory allocation failed for filtered direct entries") + + /* Compute the previous # of indirect rows in this block */ + if(old_nrows < hdr->man_dtable.max_direct_rows) + old_indir_rows = 0; + else + old_indir_rows = old_nrows - hdr->man_dtable.max_direct_rows; + + /* Initialize new entries allocated */ + for(u = (old_indir_rows * hdr->man_dtable.cparam.width); u < (indir_rows * hdr->man_dtable.cparam.width); u++) + iblock->child_iblocks[u] = NULL; + } /* end if */ + /* Mark indirect block as dirty */ if(H5HF_iblock_dirty(iblock) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty") @@ -560,6 +705,7 @@ H5HF_man_iblock_root_halve(H5HF_indirect_t *iblock, hid_t dxpl_id) haddr_t new_addr; /* New address of indirect block */ hsize_t acc_dblock_free; /* Accumulated free space in direct blocks */ unsigned max_child_row; /* Row for max. child entry */ + unsigned old_nrows; /* Old # of rows */ unsigned new_nrows; /* New # of rows */ unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ @@ -604,6 +750,7 @@ HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows); acc_dblock_free += hdr->man_dtable.row_tot_dblock_free[u] * hdr->man_dtable.cparam.width; /* Compute size of buffer needed for new indirect block */ + old_nrows = iblock->nrows; iblock->nrows = new_nrows; iblock->size = H5HF_MAN_INDIRECT_SIZE(hdr, iblock); @@ -622,7 +769,7 @@ HDfprintf(stderr, "%s: new_addr = %a\n", FUNC, new_addr); } /* end if */ /* Re-allocate child block entry array */ - if(NULL == (iblock->ents = H5FL_SEQ_REALLOC(H5HF_indirect_ent_t, iblock->ents, (iblock->nrows * hdr->man_dtable.cparam.width)))) + if(NULL == (iblock->ents = H5FL_SEQ_REALLOC(H5HF_indirect_ent_t, iblock->ents, (size_t)(iblock->nrows * hdr->man_dtable.cparam.width)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct entries") /* Check for needing to re-allocate filtered entry array */ @@ -632,6 +779,23 @@ HDfprintf(stderr, "%s: new_addr = %a\n", FUNC, new_addr); HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "memory allocation failed for filtered direct entries") } /* end if */ + /* Check for needing to re-allocate child iblock pointer array */ + if(old_nrows > hdr->man_dtable.max_direct_rows) { + /* Check for shrinking away child iblock pointer array */ + if(iblock->nrows > hdr->man_dtable.max_direct_rows) { + unsigned indir_rows; /* Number of indirect rows in this indirect block */ + + /* Compute the number of direct rows for this indirect block */ + indir_rows = iblock->nrows - hdr->man_dtable.max_direct_rows; + + /* Re-allocate child indirect block array */ + if(NULL == (iblock->child_iblocks = H5FL_SEQ_REALLOC(H5HF_indirect_ptr_t, iblock->child_iblocks, (size_t)(indir_rows * hdr->man_dtable.cparam.width)))) + HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "memory allocation failed for filtered direct entries") + } /* end if */ + else + iblock->child_iblocks = H5FL_SEQ_FREE(H5HF_indirect_ptr_t, iblock->child_iblocks); + } /* end if */ + /* Mark indirect block as dirty */ if(H5HF_iblock_dirty(iblock) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty") @@ -883,6 +1047,20 @@ HDfprintf(stderr, "%s: dir_rows = %u\n", FUNC, dir_rows); else iblock->filt_ents = NULL; + /* Check if we have any indirect block children */ + if(iblock->nrows > hdr->man_dtable.max_direct_rows) { + unsigned indir_rows; /* Number of indirect rows in this indirect block */ + + /* Compute the number of indirect rows for this indirect block */ + indir_rows = iblock->nrows - hdr->man_dtable.max_direct_rows; + + /* Allocate & initialize child indirect block pointer array */ + if(NULL == (iblock->child_iblocks = H5FL_SEQ_CALLOC(H5HF_indirect_ptr_t, (size_t)(indir_rows * hdr->man_dtable.cparam.width)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for block entries") + } /* end if */ + else + iblock->child_iblocks = NULL; + /* Allocate space for the indirect block on disk */ if(HADDR_UNDEF == (*addr_p = H5MF_alloc(hdr->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, (hsize_t)iblock->size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap indirect block") @@ -909,7 +1087,7 @@ HDfprintf(stderr, "%s: dir_rows = %u\n", FUNC, dir_rows); iblock->nchildren = 0; iblock->max_child = 0; - /* Cache the new fractal heap header */ + /* Cache the new indirect block */ if(H5AC_set(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, *addr_p, iblock, H5AC__NO_FLAGS_SET) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add fractal heap indirect block to cache") @@ -926,7 +1104,6 @@ done: * Function: H5HF_man_iblock_protect * * Purpose: Convenience wrapper around H5AC_protect on a indirect block - * (Use H5AC_unprotect to unprotect it for now) * * Return: Pointer to indirect block on success, NULL on failure * @@ -939,10 +1116,11 @@ done: H5HF_indirect_t * H5HF_man_iblock_protect(H5HF_hdr_t *hdr, hid_t dxpl_id, haddr_t iblock_addr, unsigned iblock_nrows, H5HF_indirect_t *par_iblock, unsigned par_entry, - H5AC_protect_t rw) + hbool_t must_protect, H5AC_protect_t rw, hbool_t *did_protect) { H5HF_parent_t par_info; /* Parent info for loading block */ - H5HF_indirect_t *iblock; /* Indirect block from cache */ + H5HF_indirect_t *iblock = NULL; /* Indirect block from cache */ + hbool_t should_protect = FALSE; /* Whether we should protect the indirect block or not */ H5HF_indirect_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_protect) @@ -956,15 +1134,57 @@ HDfprintf(stderr, "%s: iblock_addr = %a, iblock_nrows = %u\n", FUNC, iblock_addr HDassert(hdr); HDassert(H5F_addr_defined(iblock_addr)); HDassert(iblock_nrows > 0); + HDassert(did_protect); + + /* Check if we are allow to use existing pinned iblock pointer */ + if(!must_protect) { + /* Check for this block already being pinned */ + if(par_iblock) { + unsigned indir_idx; /* Index in parent's child iblock pointer array */ + + /* Sanity check */ + HDassert(par_iblock->child_iblocks); + HDassert(par_entry >= (hdr->man_dtable.max_direct_rows + * hdr->man_dtable.cparam.width)); + + /* Compute index in parent's child iblock pointer array */ + indir_idx = par_entry - (hdr->man_dtable.max_direct_rows + * hdr->man_dtable.cparam.width); + + /* Check for pointer to pinned indirect block in parent */ + if(par_iblock->child_iblocks[indir_idx]) + iblock = par_iblock->child_iblocks[indir_idx]; + else + should_protect = TRUE; + } /* end if */ + else { + /* Check for root indirect block */ + if(H5F_addr_eq(iblock_addr, hdr->man_dtable.table_addr)) { + /* Check for pointer to pinned indirect block in root */ + if(hdr->root_iblock) + iblock = hdr->root_iblock; + else + should_protect = TRUE; + } /* end if */ + else + should_protect = TRUE; + } /* end else */ + } /* end if */ - /* Set up parent info */ - par_info.hdr = hdr; - par_info.iblock = par_iblock; - par_info.entry = par_entry; - - /* Protect the indirect block */ - if(NULL == (iblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, &iblock_nrows, &par_info, rw))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap indirect block") + /* Check for protecting indirect block */ + if(must_protect || should_protect) { + /* Set up parent info */ + par_info.hdr = hdr; + par_info.iblock = par_iblock; + par_info.entry = par_entry; + + /* Protect the indirect block */ + if(NULL == (iblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, &iblock_nrows, &par_info, rw))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap indirect block") + *did_protect = TRUE; + } /* end if */ + else + *did_protect = FALSE; /* Set the return value */ ret_value = iblock; @@ -975,6 +1195,45 @@ done: /*------------------------------------------------------------------------- + * Function: H5HF_man_iblock_unprotect + * + * Purpose: Convenience wrapper around H5AC_unprotect on a indirect block + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Aug 17 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_man_iblock_unprotect(H5HF_indirect_t *iblock, hid_t dxpl_id, + unsigned cache_flags, hbool_t did_protect) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_unprotect) + + /* + * Check arguments. + */ + HDassert(iblock); + + /* Check if we previously protected this indirect block */ + /* (as opposed to using an existing pointer to a pinned child indirect block) */ + if(did_protect) { + /* Unprotect the indirect block */ + if(H5AC_unprotect(iblock->hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock->addr, iblock, cache_flags) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_man_iblock_unprotect() */ + + +/*------------------------------------------------------------------------- * Function: H5HF_man_iblock_attach * * Purpose: Attach a block to an indirect block @@ -1209,6 +1468,7 @@ H5HF_man_iblock_delete(H5HF_hdr_t *hdr, hid_t dxpl_id, haddr_t iblock_addr, H5HF_indirect_t *iblock; /* Pointer to indirect block */ unsigned row, col; /* Current row & column in indirect block */ unsigned entry; /* Current entry in row */ + hbool_t did_protect; /* Whether we protected the indirect block or not */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_delete) @@ -1224,8 +1484,10 @@ HDfprintf(stderr, "%s: iblock_addr = %a, iblock_nrows = %u\n", FUNC, iblock_addr HDassert(iblock_nrows > 0); /* Lock indirect block */ - if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, iblock_nrows, par_iblock, par_entry, H5AC_WRITE))) + if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, iblock_nrows, par_iblock, par_entry, TRUE, H5AC_WRITE, &did_protect))) HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") + HDassert(iblock->nchildren > 0); + HDassert(did_protect == TRUE); /* Iterate over rows in this indirect block */ entry = 0; @@ -1277,7 +1539,7 @@ HDfprintf(stderr, "%s: iblock_addr = %a, iblock_nrows = %u\n", FUNC, iblock_addr #endif /* NDEBUG */ /* Finished deleting indirect block in metadata cache */ - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, iblock, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG) < 0) + if(H5HF_man_iblock_unprotect(iblock, dxpl_id, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG, did_protect) < 0) HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") iblock = NULL; diff --git a/src/H5HFiter.c b/src/H5HFiter.c index 94f0b8b..25e1d67 100644 --- a/src/H5HFiter.c +++ b/src/H5HFiter.c @@ -169,6 +169,8 @@ HDfprintf(stderr, "%s: offset = %Hu\n", FUNC, offset); */ do { + hbool_t did_protect; /* Whether we protected the indirect block or not */ + /* Walk down the rows in the doubling table until we've found the correct row for the next block */ for(row = 0; row < hdr->man_dtable.max_root_rows; row++) if((offset >= hdr->man_dtable.row_block_off[row]) && @@ -224,7 +226,7 @@ HDfprintf(stderr, "%s: biter->curr->entry = %u\n", FUNC, biter->curr->entry); } /* end else */ /* Load indirect block for this context location */ - if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, iblock_nrows, iblock_parent, iblock_par_entry, H5AC_WRITE))) + if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, iblock_nrows, iblock_parent, iblock_par_entry, FALSE, H5AC_WRITE, &did_protect))) HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") /* Make indirect block the context for the current location */ @@ -235,7 +237,7 @@ HDfprintf(stderr, "%s: biter->curr->entry = %u\n", FUNC, biter->curr->entry); HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block") /* Release the current indirect block */ - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, iblock, H5AC__NO_FLAGS_SET) < 0) + if(H5HF_man_iblock_unprotect(iblock, dxpl_id, H5AC__NO_FLAGS_SET, did_protect) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") iblock = NULL; diff --git a/src/H5HFman.c b/src/H5HFman.c index 38e8d43..abe01d1 100644 --- a/src/H5HFman.c +++ b/src/H5HFman.c @@ -76,136 +76,6 @@ /*------------------------------------------------------------------------- - * Function: H5HF_man_locate_block - * - * Purpose: Locate a block in a managed heap - * - * Return: SUCCEED/FAIL - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * May 8 2006 - * - *------------------------------------------------------------------------- - */ -herr_t -H5HF_man_locate_block(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t obj_off, - hbool_t locate_indirect, - H5HF_indirect_t **ret_iblock, unsigned *ret_entry, - H5AC_protect_t rw) -{ - haddr_t iblock_addr; /* Indirect block's address */ - H5HF_indirect_t *iblock; /* Pointer to indirect block */ - unsigned bot_row, top_row; /* Bottom & top acceptable rows */ - unsigned row, col; /* Row & column for object's block */ - unsigned entry; /* Entry of block */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_man_locate_block) -#ifdef QAK -HDfprintf(stderr, "%s: obj_off = %Hu\n", FUNC, obj_off); -#endif /* QAK */ - - /* - * Check arguments. - */ - HDassert(hdr); - HDassert(hdr->man_dtable.curr_root_rows); /* Only works for heaps with indirect root block */ - - /* Set up target bottom & top rows */ - if(locate_indirect) { - bot_row = hdr->man_dtable.max_direct_rows; - top_row = hdr->man_dtable.max_direct_rows + H5V_log2_of2(hdr->man_dtable.cparam.width); - } /* end if */ - else { - bot_row = 0; - top_row = hdr->man_dtable.max_direct_rows - 1; - } /* end else */ -#ifdef QAK -HDfprintf(stderr, "%s: bot_row = %u, top_row = %u\n", FUNC, bot_row, top_row); -#endif /* QAK */ - - /* Look up row & column for object */ - if(H5HF_dtable_lookup(&hdr->man_dtable, obj_off, &row, &col) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of object") -#ifdef QAK -HDfprintf(stderr, "%s: row = %u, col = %u\n", FUNC, row, col); -#endif /* QAK */ - - /* Set initial indirect block info */ - iblock_addr = hdr->man_dtable.table_addr; -#ifdef QAK -HDfprintf(stderr, "%s: iblock_addr = %a\n", FUNC, iblock_addr); -#endif /* QAK */ - - /* Lock root indirect block */ - if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, hdr->man_dtable.curr_root_rows, NULL, 0, rw))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") - - /* Check for indirect block row */ - while(row < bot_row || row > top_row) { - haddr_t new_iblock_addr; /* New indirect block's address */ - H5HF_indirect_t *new_iblock; /* Pointer to new indirect block */ - unsigned nrows; /* Number of rows in new indirect block */ - unsigned cache_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting parent indirect block */ - - /* Compute # of rows in child indirect block */ - nrows = (H5V_log2_gen(hdr->man_dtable.row_block_size[row]) - hdr->man_dtable.first_row_bits) + 1; - - /* Compute indirect block's entry */ - entry = (row * hdr->man_dtable.cparam.width) + col; -#ifdef QAK -HDfprintf(stderr, "%s: entry = %Zu\n", FUNC, entry); -#endif /* QAK */ - - /* Locate child indirect block */ - new_iblock_addr = iblock->ents[entry].addr; - - /* Check if we need to (re-)create the child indirect block */ - if(!H5F_addr_defined(new_iblock_addr)) { - if(H5HF_man_iblock_create(hdr, dxpl_id, iblock, entry, nrows, nrows, &new_iblock_addr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap indirect block") - - /* Indicate that the parent indirect block was modified */ - cache_flags |= H5AC__DIRTIED_FLAG; - } /* end if */ - - /* Lock new indirect block */ - if(NULL == (new_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, new_iblock_addr, nrows, iblock, entry, rw))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") - - /* Release the current indirect block */ - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, iblock, cache_flags) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") - - /* Switch variables to use new indirect block */ - iblock = new_iblock; - iblock_addr = new_iblock_addr; -#ifdef QAK -HDfprintf(stderr, "%s: iblock_addr = %a\n", FUNC, iblock_addr); -HDfprintf(stderr, "%s: iblock->block_off = %Hu\n", FUNC, iblock->block_off); -#endif /* QAK */ - - /* Look up row & column in new indirect block for object */ - if(H5HF_dtable_lookup(&hdr->man_dtable, (obj_off - iblock->block_off), &row, &col) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of object") - -#ifdef QAK -HDfprintf(stderr, "%s: row = %u, col = %u\n", FUNC, row, col); -#endif /* QAK */ - } /* end while */ - - /* Set return parameters */ - if(ret_entry) - *ret_entry = (row * hdr->man_dtable.cparam.width) + col; - *ret_iblock = iblock; - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_man_locate_block() */ - - -/*------------------------------------------------------------------------- * Function: H5HF_man_insert * * Purpose: Insert an object in a managed direct block @@ -316,10 +186,6 @@ HDfprintf(stderr, "%s: dblock->block_off = %Hu\n", FUNC, dblock->block_off); if(H5HF_sect_single_reduce(hdr, dxpl_id, sec_node, obj_size) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce single section node") - /* Reduce space available in heap */ - if(H5HF_hdr_adj_free(hdr, -(ssize_t)obj_size) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't adjust free space for heap") - /* Encode the object in the block */ { uint8_t *p; /* Temporary pointer to obj info in block */ @@ -347,9 +213,9 @@ HDfprintf(stderr, "%s: obj_off = %Hu, obj_len = %Zu\n", FUNC, (dblock->block_off /* Update statistics about heap */ hdr->man_nobjs++; - /* Mark heap header as modified */ - if(H5HF_hdr_dirty(hdr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty") + /* Reduce space available in heap (marks header dirty) */ + if(H5HF_hdr_adj_free(hdr, -(ssize_t)obj_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't adjust free space for heap") done: /* Release the direct block (marked as dirty) */ @@ -418,10 +284,11 @@ HDfprintf(stderr, "%s: obj_off = %Hu, obj_len = %Zu\n", FUNC, obj_off, obj_len); } /* end if */ else { H5HF_indirect_t *iblock; /* Pointer to indirect block */ + hbool_t did_protect; /* Whether we protected the indirect block or not */ unsigned entry; /* Entry of block */ /* Look up indirect block containing direct block */ - if(H5HF_man_locate_block(hdr, dxpl_id, obj_off, FALSE, &iblock, &entry, H5AC_READ) < 0) + if(H5HF_man_dblock_locate(hdr, dxpl_id, obj_off, &iblock, &entry, &did_protect, H5AC_READ) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of section") #ifdef QAK HDfprintf(stderr, "%s: entry address = %a\n", FUNC, iblock->ents[entry].addr); @@ -436,7 +303,7 @@ HDfprintf(stderr, "%s: entry address = %a\n", FUNC, iblock->ents[entry].addr); HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap direct block") /* Unlock indirect block */ - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock->addr, iblock, H5AC__NO_FLAGS_SET) < 0) + if(H5HF_man_iblock_unprotect(iblock, dxpl_id, H5AC__NO_FLAGS_SET, did_protect) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") iblock = NULL; } /* end else */ @@ -535,13 +402,14 @@ HDfprintf(stderr, "%s: direct root block\n", FUNC); } /* end if */ else { H5HF_indirect_t *iblock; /* Pointer to indirect block */ + hbool_t did_protect; /* Whether we protected the indirect block or not */ unsigned entry; /* Entry of block */ #ifdef QAK HDfprintf(stderr, "%s: indirect root block\n", FUNC); #endif /* QAK */ /* Look up indirect block containing direct block */ - if(H5HF_man_locate_block(hdr, dxpl_id, obj_off, FALSE, &iblock, &entry, H5AC_WRITE) < 0) + if(H5HF_man_dblock_locate(hdr, dxpl_id, obj_off, &iblock, &entry, &did_protect, H5AC_WRITE) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of section") #ifdef QAK HDfprintf(stderr, "%s: entry address = %a\n", FUNC, iblock->ents[entry].addr); @@ -554,7 +422,7 @@ HDfprintf(stderr, "%s: entry address = %a\n", FUNC, iblock->ents[entry].addr); /* Check for offset of invalid direct block */ if(!H5F_addr_defined(dblock_addr)) { /* Unlock indirect block */ - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock->addr, iblock, H5AC__NO_FLAGS_SET) < 0) + if(H5HF_man_iblock_unprotect(iblock, dxpl_id, H5AC__NO_FLAGS_SET, did_protect) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "fractal heap ID not in allocated direct block") @@ -563,14 +431,14 @@ HDfprintf(stderr, "%s: entry address = %a\n", FUNC, iblock->ents[entry].addr); /* Lock direct block */ if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, iblock, entry, H5AC_WRITE))) { /* Unlock indirect block */ - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock->addr, iblock, H5AC__NO_FLAGS_SET) < 0) + if(H5HF_man_iblock_unprotect(iblock, dxpl_id, H5AC__NO_FLAGS_SET, did_protect) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap direct block") } /* end if */ /* Unlock indirect block */ - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock->addr, iblock, H5AC__NO_FLAGS_SET) < 0) + if(H5HF_man_iblock_unprotect(iblock, dxpl_id, H5AC__NO_FLAGS_SET, did_protect) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") iblock = NULL; } /* end else */ @@ -606,7 +474,7 @@ HDfprintf(stderr, "%s: blk_off = %Zu\n", FUNC, blk_off); /* Update statistics about heap */ hdr->man_nobjs--; - /* Reduce space available in heap */ + /* Increase space available in heap (marks header dirty) */ if(H5HF_hdr_adj_free(hdr, (ssize_t)obj_len) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't adjust free space for heap") diff --git a/src/H5HFpkg.h b/src/H5HFpkg.h index 947f3ad..bc9e23a 100644 --- a/src/H5HFpkg.h +++ b/src/H5HFpkg.h @@ -346,6 +346,7 @@ typedef struct H5HF_hdr_t { H5F_t *f; /* Pointer to file for heap */ size_t sizeof_size; /* Size of file sizes */ size_t sizeof_addr; /* Size of file addresses */ + struct H5HF_indirect_t *root_iblock; /* Pointer to pinned root indirect block */ H5FS_t *fspace; /* Free space list for objects in heap */ H5HF_block_iter_t next_block; /* Block iterator for searching for next block with space */ hsize_t huge_max_id; /* Max. 'huge' heap ID before rolling 'huge' heap IDs over */ @@ -376,16 +377,17 @@ struct H5HF_indirect_t { H5AC_info_t cache_info; /* Internal heap information (not stored) */ - size_t rc; /* Reference count of child blocks */ + size_t rc; /* Reference count of objects using this block */ H5HF_hdr_t *hdr; /* Shared heap header info */ struct H5HF_indirect_t *parent; /* Shared parent indirect block info */ unsigned par_entry; /* Entry in parent's table */ haddr_t addr; /* Address of this indirect block on disk */ + size_t size; /* Size of indirect block on disk */ unsigned nrows; /* Total # of rows in indirect block */ unsigned max_rows; /* Max. # of rows in indirect block */ unsigned nchildren; /* Number of child blocks */ unsigned max_child; /* Max. offset used in child entries */ - size_t size; /* Size of indirect block on disk */ + struct H5HF_indirect_t **child_iblocks; /* Array of pointers to pinned child indirect blocks */ /* Stored values */ hsize_t block_off; /* Offset of the block within the heap's address space */ @@ -521,6 +523,10 @@ H5FL_SEQ_EXTERN(H5HF_indirect_ent_t); /* Declare a free list to manage the H5HF_indirect_filt_ent_t sequence information */ H5FL_SEQ_EXTERN(H5HF_indirect_filt_ent_t); +/* Declare a free list to manage the H5HF_indirect_t * sequence information */ +typedef H5HF_indirect_t *H5HF_indirect_ptr_t; +H5FL_SEQ_EXTERN(H5HF_indirect_ptr_t); + /******************************/ /* Package Private Prototypes */ @@ -575,8 +581,10 @@ H5_DLL herr_t H5HF_man_iblock_create(H5HF_hdr_t *hdr, hid_t dxpl_id, unsigned max_rows, haddr_t *addr_p); H5_DLL H5HF_indirect_t *H5HF_man_iblock_protect(H5HF_hdr_t *hdr, hid_t dxpl_id, haddr_t iblock_addr, unsigned iblock_nrows, - H5HF_indirect_t *par_iblock, unsigned par_entry, - H5AC_protect_t rw); + H5HF_indirect_t *par_iblock, unsigned par_entry, hbool_t must_protect, + H5AC_protect_t rw, hbool_t *did_protect); +H5_DLL herr_t H5HF_man_iblock_unprotect(H5HF_indirect_t *iblock, hid_t dxpl_id, + unsigned cache_flags, hbool_t did_protect); H5_DLL herr_t H5HF_man_iblock_attach(H5HF_indirect_t *iblock, unsigned entry, haddr_t dblock_addr); H5_DLL herr_t H5HF_man_iblock_detach(H5HF_indirect_t *iblock, hid_t dxpl_id, unsigned entry); @@ -598,13 +606,13 @@ H5_DLL H5HF_direct_t *H5HF_man_dblock_protect(H5HF_hdr_t *hdr, hid_t dxpl_id, haddr_t dblock_addr, size_t dblock_size, H5HF_indirect_t *par_iblock, unsigned par_entry, H5AC_protect_t rw); +H5_DLL herr_t H5HF_man_dblock_locate(H5HF_hdr_t *hdr, hid_t dxpl_id, + hsize_t obj_off, H5HF_indirect_t **par_iblock, + unsigned *par_entry, hbool_t *par_did_protect, H5AC_protect_t rw); H5_DLL herr_t H5HF_man_dblock_delete(H5F_t *f, hid_t dxpl_id, haddr_t dblock_addr, hsize_t dblock_size); /* Managed object routines */ -H5_DLL herr_t H5HF_man_locate_block(H5HF_hdr_t *hdr, hid_t dxpl_id, - hsize_t obj_off, hbool_t locate_indirect, H5HF_indirect_t **par_iblock, - unsigned *par_entry, H5AC_protect_t rw); H5_DLL herr_t H5HF_man_insert(H5HF_hdr_t *fh, hid_t dxpl_id, size_t obj_size, const void *obj, void *id); H5_DLL herr_t H5HF_man_read(H5HF_hdr_t *fh, hid_t dxpl_id, const uint8_t *id, diff --git a/src/H5HFsection.c b/src/H5HFsection.c index 24c6256..717c7f8 100644 --- a/src/H5HFsection.c +++ b/src/H5HFsection.c @@ -571,8 +571,10 @@ H5HF_sect_single_revive(H5HF_hdr_t *hdr, hid_t dxpl_id, sect->u.single.dblock_size = hdr->man_dtable.cparam.start_block_size; } /* end if */ else { + hbool_t did_protect; /* Whether we protected the indirect block or not */ + /* Look up indirect block containing direct blocks for range */ - if(H5HF_man_locate_block(hdr, dxpl_id, sect->sect_info.addr, FALSE, &sec_iblock, &sec_entry, H5AC_READ) < 0) + if(H5HF_man_dblock_locate(hdr, dxpl_id, sect->sect_info.addr, &sec_iblock, &sec_entry, &did_protect, H5AC_READ) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of section") /* Increment reference count on indirect block that free section is in */ @@ -588,7 +590,7 @@ H5HF_sect_single_revive(H5HF_hdr_t *hdr, hid_t dxpl_id, sect->u.single.dblock_size = hdr->man_dtable.row_block_size[sec_entry / hdr->man_dtable.cparam.width]; /* Unlock indirect block */ - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, sec_iblock->addr, sec_iblock, H5AC__NO_FLAGS_SET) < 0) + if(H5HF_man_iblock_unprotect(sec_iblock, dxpl_id, H5AC__NO_FLAGS_SET, did_protect) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") sec_iblock = NULL; } /* end else */ @@ -2585,6 +2587,8 @@ HDfprintf(stderr, "%s: row_entries = %u\n", FUNC, row_entries); /* Add an indirect section for each indirect block in the row */ for(v = 0; v < row_entries; v++) { + hbool_t did_protect; /* Whether we protected the indirect block or not */ + /* Try to get the child section's indirect block, if it's available */ if(sect->sect_info.state == H5FS_SECT_LIVE) { haddr_t child_iblock_addr; /* Child indirect block's address on disk */ @@ -2598,7 +2602,7 @@ HDfprintf(stderr, "%s: child_iblock_addr = %a\n", FUNC, child_iblock_addr); /* If the child indirect block's address is defined, protect it */ if(H5F_addr_defined(child_iblock_addr)) { - if(NULL == (child_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, child_iblock_addr, child_nrows, sect->u.indirect.u.iblock, curr_entry, H5AC_WRITE))) + if(NULL == (child_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, child_iblock_addr, child_nrows, sect->u.indirect.u.iblock, curr_entry, FALSE, H5AC_WRITE, &did_protect))) HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") } /* end if */ else @@ -2621,7 +2625,7 @@ HDfprintf(stderr, "%s: child_iblock_addr = %a\n", FUNC, child_iblock_addr); /* If we have a valid child indirect block, release it now */ /* (will be pinned, if rows reference it) */ if(child_iblock) - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, child_iblock->addr, child_iblock, H5AC__NO_FLAGS_SET) < 0) + if(H5HF_man_iblock_unprotect(child_iblock, dxpl_id, H5AC__NO_FLAGS_SET, did_protect) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") /* Attach child section to this section */ @@ -2821,6 +2825,7 @@ static herr_t H5HF_sect_indirect_revive_row(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect) { H5HF_indirect_t *sec_iblock; /* Pointer to section indirect block */ + hbool_t did_protect; /* Whether we protected the indirect block or not */ unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ @@ -2838,7 +2843,7 @@ H5HF_sect_indirect_revive_row(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_ HDfprintf(stderr, "%s: sect->sect_info.addr = %a\n", FUNC, sect->sect_info.addr); HDfprintf(stderr, "%s: sect->u.indirect.u.iblock_off = %Hu\n", FUNC, sect->u.indirect.u.iblock_off); #endif /* QAK */ - if(H5HF_man_locate_block(hdr, dxpl_id, sect->sect_info.addr, FALSE, &sec_iblock, NULL, H5AC_READ) < 0) + if(H5HF_man_dblock_locate(hdr, dxpl_id, sect->sect_info.addr, &sec_iblock, NULL, &did_protect, H5AC_READ) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of section") /* Increment reference count on indirect block that free section is in */ @@ -2853,7 +2858,7 @@ HDfprintf(stderr, "%s: sect->u.indirect.u.iblock_off = %Hu\n", FUNC, sect->u.ind sect->u.indirect.u.iblock->max_rows; /* Unlock indirect block */ - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, sec_iblock->addr, sec_iblock, H5AC__NO_FLAGS_SET) < 0) + if(H5HF_man_iblock_unprotect(sec_iblock, dxpl_id, H5AC__NO_FLAGS_SET, did_protect) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") sec_iblock = NULL; diff --git a/test/fheap.c b/test/fheap.c index ade01a5..d7f679b 100644 --- a/test/fheap.c +++ b/test/fheap.c @@ -12488,7 +12488,7 @@ test_filtered_huge(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tparam unsigned char obj_type; /* Type of storage for object */ fheap_heap_state_t state; /* State of fractal heap */ unsigned deflate_level; /* Deflation level */ - unsigned old_actual_id_len; /* Old actual ID length */ + unsigned old_actual_id_len = 0; /* Old actual ID length */ hbool_t huge_ids_direct; /* Are 'huge' objects directly acccessed? */ const char *base_desc = "insert 'huge' object into heap with I/O filters, then remove %s"; /* Test description */ -- cgit v0.12