diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2012-04-01 23:53:17 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2012-04-01 23:53:17 (GMT) |
commit | 42306f8ed4ade51a8629b9c5a159d1afac5f617f (patch) | |
tree | a503b4e463f3888709d893eae564898d899135bb /src/H5HFiblock.c | |
parent | 982f1ff8ff1687cc62e310c991c0d56929b271fd (diff) | |
download | hdf5-42306f8ed4ade51a8629b9c5a159d1afac5f617f.zip hdf5-42306f8ed4ade51a8629b9c5a159d1afac5f617f.tar.gz hdf5-42306f8ed4ade51a8629b9c5a159d1afac5f617f.tar.bz2 |
[svn-r22233] Description:
Correct several errors in fractal heap code: root indirect block was
getting pinned/protected more than once, "single" free space sections weren't
getting "re-parented" correctly when the heap transitioned between having a
root indirect block and a root direct block, and several related issues. Also
cleaned up some warnings in library/tests.
Tested on:
FreeBSD/32 8.2 (loyalty) w/gcc4.6, w/C++ & FORTRAN, in debug mode
FreeBSD/64 8.2 (freedom) w/gcc4.6, w/C++ & FORTRAN, in debug mode
Linux/32 2.6 (jam) w/PGI compilers, w/default API=1.8.x,
w/C++ & FORTRAN, w/threadsafe, in debug mode
Linux/64-amd64 2.6 (koala) w/Intel compilers, w/default API=1.6.x,
w/C++ & FORTRAN, in production mode
Mac OSX/64 10.7.3 (amazon) w/debug
Diffstat (limited to 'src/H5HFiblock.c')
-rw-r--r-- | src/H5HFiblock.c | 146 |
1 files changed, 122 insertions, 24 deletions
diff --git a/src/H5HFiblock.c b/src/H5HFiblock.c index 6c19b4f..342e228 100644 --- a/src/H5HFiblock.c +++ b/src/H5HFiblock.c @@ -140,8 +140,17 @@ H5HF_iblock_pin(H5HF_indirect_t *iblock) else { /* Check for pinning the root indirect block */ if(iblock->block_off == 0) { - HDassert(iblock->hdr->root_iblock == NULL); - iblock->hdr->root_iblock = iblock; + /* Sanity check - shouldn't be recursively pinning root indirect block */ + HDassert(0 == (iblock->hdr->root_iblock_flags & H5HF_ROOT_IBLOCK_PINNED)); + + /* Check if we should set the root iblock pointer */ + if(0 == iblock->hdr->root_iblock_flags) { + HDassert(NULL == iblock->hdr->root_iblock); + iblock->hdr->root_iblock = iblock; + } /* end if */ + + /* Indicate that the root indirect block is pinned */ + iblock->hdr->root_iblock_flags |= H5HF_ROOT_IBLOCK_PINNED; } /* end if */ } /* end if */ @@ -192,12 +201,21 @@ H5HF_iblock_unpin(H5HF_indirect_t *iblock) par_iblock->child_iblocks[indir_idx] = NULL; } /* end if */ else { - /* Check for unpinning the root indirect block */ + /* Check for root indirect block */ if(iblock->block_off == 0) { - HDassert(iblock->hdr->root_iblock); - iblock->hdr->root_iblock = NULL; + /* Sanity check - shouldn't be recursively unpinning root indirect block */ + HDassert(iblock->hdr->root_iblock_flags & H5HF_ROOT_IBLOCK_PINNED); + + /* Check if we should reset the root iblock pointer */ + if(H5HF_ROOT_IBLOCK_PINNED == iblock->hdr->root_iblock_flags) { + HDassert(NULL != iblock->hdr->root_iblock); + iblock->hdr->root_iblock = NULL; + } /* end if */ + + /* Indicate that the root indirect block is unpinned */ + iblock->hdr->root_iblock_flags &= ~(H5HF_ROOT_IBLOCK_PINNED); } /* end if */ - } /* end if */ + } /* end else */ /* Mark block as evictable again */ if(H5AC_unpin_entry(iblock) < 0) @@ -273,18 +291,23 @@ H5HF_iblock_decr(H5HF_indirect_t *iblock) /* Mark block as evictable again when no child blocks depend on it */ if(iblock->rc == 0) { - if(H5HF_iblock_unpin(iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPIN, FAIL, "unable to unpin fractal heap indirect block") + H5HF_hdr_t *hdr; /* Fractal heap header */ + haddr_t iblock_addr; /* Address of fractal heap */ + hbool_t expunge_iblock = FALSE; /* Whether to expunge indirect block from heap */ + + /* Set up convenience variables */ + hdr = iblock->hdr; + iblock_addr = iblock->addr; if(iblock->nchildren == 0) { /* Check for deleting root indirect block (and no root direct block) */ - if(iblock->block_off == 0 && iblock->hdr->man_dtable.curr_root_rows > 0) { + if(iblock->block_off == 0 && hdr->man_dtable.curr_root_rows > 0) { /* Reset root pointer information */ - iblock->hdr->man_dtable.curr_root_rows = 0; - iblock->hdr->man_dtable.table_addr = HADDR_UNDEF; + hdr->man_dtable.curr_root_rows = 0; + hdr->man_dtable.table_addr = HADDR_UNDEF; /* Reset header information back to "empty heap" state */ - if(H5HF_hdr_empty(iblock->hdr) < 0) + if(H5HF_hdr_empty(hdr) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't make heap empty") } /* end if */ @@ -297,8 +320,18 @@ H5HF_iblock_decr(H5HF_indirect_t *iblock) iblock->par_entry = 0; } /* end if */ + /* Mark indirect block for removal from the metadata cache */ + expunge_iblock = TRUE; + } /* end if */ + + /* Unpin the indirect block */ + if(H5HF_iblock_unpin(iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPIN, FAIL, "unable to unpin fractal heap indirect block") + + /* Check for expunging the indirect block from the metadata cache */ + if(expunge_iblock) { /* Evict the indirect block from the metadata cache */ - if(H5AC_expunge_entry(iblock->hdr->f, H5AC_dxpl_id, H5AC_FHEAP_IBLOCK, iblock->addr, H5AC__FREE_FILE_SPACE_FLAG) < 0) + if(H5AC_expunge_entry(hdr->f, H5AC_dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, H5AC__FREE_FILE_SPACE_FLAG) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "unable to remove indirect block from cache") } /* end if */ } /* end if */ @@ -420,6 +453,10 @@ H5HF_man_iblock_root_create(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t min_dblock_si hdr->pline_root_direct_filter_mask = 0; } /* end if */ + /* Scan free space sections to set any 'parent' pointers to new indirect block */ + if(H5HF_space_create_root(hdr, dxpl_id, iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTSET, FAIL, "can't set free space section info to new root indirect block") + /* Unlock first (previously the root) direct block */ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, hdr->man_dtable.table_addr, dblock, H5AC__NO_FLAGS_SET) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block") @@ -859,6 +896,11 @@ H5HF_man_iblock_root_revert(H5HF_indirect_t *root_iblock, hid_t dxpl_id) if(H5HF_hdr_adjust_heap(hdr, (hsize_t)hdr->man_dtable.cparam.start_block_size, (hssize_t)hdr->man_dtable.row_tot_dblock_free[0]) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, FAIL, "can't increase space to cover root direct block") + /* Scan free space sections to reset any 'parent' pointers */ + if(H5HF_space_revert_root(hdr, dxpl_id) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRESET, FAIL, "can't reset free space section info") + + done: if(dblock && H5AC_unprotect(hdr->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") @@ -1126,11 +1168,20 @@ H5HF_man_iblock_protect(H5HF_hdr_t *hdr, hid_t dxpl_id, haddr_t iblock_addr, 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) + /* Check for valid pointer to pinned indirect block in root */ + if(H5HF_ROOT_IBLOCK_PINNED == hdr->root_iblock_flags) { + /* Sanity check */ + HDassert(NULL != hdr->root_iblock); + + /* Return the pointer to the pinned root indirect block */ iblock = hdr->root_iblock; - else + } /* end if */ + else { + /* Sanity check */ + HDassert(NULL == hdr->root_iblock); + should_protect = TRUE; + } /* end else */ } /* end if */ else should_protect = TRUE; @@ -1158,6 +1209,21 @@ H5HF_man_iblock_protect(H5HF_hdr_t *hdr, hid_t dxpl_id, haddr_t iblock_addr, /* Set the indirect block's address */ iblock->addr = iblock_addr; + /* Check for root indirect block */ + if(iblock->block_off == 0) { + /* Sanity check - shouldn't be recursively protecting root indirect block */ + HDassert(0 == (hdr->root_iblock_flags & H5HF_ROOT_IBLOCK_PROTECTED)); + + /* Check if we should set the root iblock pointer */ + if(0 == hdr->root_iblock_flags) { + HDassert(NULL == hdr->root_iblock); + hdr->root_iblock = iblock; + } /* end if */ + + /* Indicate that the root indirect block is protected */ + hdr->root_iblock_flags |= H5HF_ROOT_IBLOCK_PROTECTED; + } /* end if */ + /* Indicate that the indirect block was protected */ *did_protect = TRUE; } /* end if */ @@ -1202,6 +1268,21 @@ H5HF_man_iblock_unprotect(H5HF_indirect_t *iblock, hid_t dxpl_id, /* Check if we previously protected this indirect block */ /* (as opposed to using an existing pointer to a pinned child indirect block) */ if(did_protect) { + /* Check for root indirect block */ + if(iblock->block_off == 0) { + /* Sanity check - shouldn't be recursively unprotecting root indirect block */ + HDassert(iblock->hdr->root_iblock_flags & H5HF_ROOT_IBLOCK_PROTECTED); + + /* Check if we should reset the root iblock pointer */ + if(H5HF_ROOT_IBLOCK_PROTECTED == iblock->hdr->root_iblock_flags) { + HDassert(NULL != iblock->hdr->root_iblock); + iblock->hdr->root_iblock = NULL; + } /* end if */ + + /* Indicate that the root indirect block is unprotected */ + iblock->hdr->root_iblock_flags &= ~(H5HF_ROOT_IBLOCK_PROTECTED); + } /* end if */ + /* 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") @@ -1215,7 +1296,7 @@ done: /*------------------------------------------------------------------------- * Function: H5HF_man_iblock_attach * - * Purpose: Attach a block to an indirect block + * Purpose: Attach a child block (direct or indirect) to an indirect block * * Return: SUCCEED/FAIL * @@ -1243,7 +1324,7 @@ H5HF_man_iblock_attach(H5HF_indirect_t *iblock, unsigned entry, haddr_t child_ad if(H5HF_iblock_incr(iblock) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block") - /* Point at the direct block */ + /* Point at the child block */ iblock->ents[entry].addr = child_addr; /* Check for I/O filters on this heap */ @@ -1280,7 +1361,7 @@ done: /*------------------------------------------------------------------------- * Function: H5HF_man_iblock_detach * - * Purpose: Detach a block from an indirect block + * Purpose: Detach a child block (direct or indirect) from an indirect block * * Return: SUCCEED/FAIL * @@ -1293,6 +1374,7 @@ done: herr_t H5HF_man_iblock_detach(H5HF_indirect_t *iblock, hid_t dxpl_id, unsigned entry) { + unsigned row; /* Row for entry */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -1306,16 +1388,14 @@ H5HF_man_iblock_detach(H5HF_indirect_t *iblock, hid_t dxpl_id, unsigned entry) /* Reset address of entry */ iblock->ents[entry].addr = HADDR_UNDEF; + /* Compute row for entry */ + row = entry / iblock->hdr->man_dtable.cparam.width; + /* Check for I/O filters on this heap */ if(iblock->hdr->filter_len > 0) { - unsigned row; /* Row for entry */ - /* Sanity check */ HDassert(iblock->filt_ents); - /* Compute row for entry */ - row = entry / iblock->hdr->man_dtable.cparam.width; - /* If this is a direct block, reset its initial size */ if(row < iblock->hdr->man_dtable.max_direct_rows) { iblock->filt_ents[entry].size = 0; @@ -1323,6 +1403,24 @@ H5HF_man_iblock_detach(H5HF_indirect_t *iblock, hid_t dxpl_id, unsigned entry) } /* end if */ } /* end if */ + /* Check for indirect block being detached */ + if(row >= iblock->hdr->man_dtable.max_direct_rows) { + unsigned indir_idx; /* Index in parent's child iblock pointer array */ + + /* Sanity check */ + HDassert(iblock->child_iblocks); + + /* Compute index in child iblock pointer array */ + indir_idx = entry - (iblock->hdr->man_dtable.max_direct_rows + * iblock->hdr->man_dtable.cparam.width); + + /* Sanity check */ + HDassert(iblock->child_iblocks[indir_idx]); + + /* Reset pointer to child indirect block in parent */ + iblock->child_iblocks[indir_idx] = NULL; + } /* end if */ + /* Decrement the # of child blocks */ /* (If the number of children drop to 0, the indirect block will be * removed from the heap when its ref. count drops to zero and the |