summaryrefslogtreecommitdiffstats
path: root/src/H5HFiblock.c
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2006-06-19 10:06:10 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2006-06-19 10:06:10 (GMT)
commit9db9e82cd1c4e35c6e64fbb2da5eb1db95a0fb55 (patch)
treedf8aaa72b1094bcfacc740a8d33b255c84e1d34e /src/H5HFiblock.c
parent54e2de04d3b7a0359c80cc995f94b63123f4a4da (diff)
downloadhdf5-9db9e82cd1c4e35c6e64fbb2da5eb1db95a0fb55.zip
hdf5-9db9e82cd1c4e35c6e64fbb2da5eb1db95a0fb55.tar.gz
hdf5-9db9e82cd1c4e35c6e64fbb2da5eb1db95a0fb55.tar.bz2
[svn-r12424] Purpose:
Code checkpoint Description: Add in more new features for the fractal heap code, mostly bringing in more ability for deleting objects (which isn't completely working yet). Also, checkpoint free space manager code, which is essentially complete (although it needs some more work after the metadata cache has some additional features) Platforms tested: FreeBSD 4.11 (sleipnir) Linux 2.4 (chicago) h5committest
Diffstat (limited to 'src/H5HFiblock.c')
-rw-r--r--src/H5HFiblock.c1107
1 files changed, 375 insertions, 732 deletions
diff --git a/src/H5HFiblock.c b/src/H5HFiblock.c
index f3d7029..652ae54 100644
--- a/src/H5HFiblock.c
+++ b/src/H5HFiblock.c
@@ -56,24 +56,9 @@
/********************/
/* Local Prototypes */
/********************/
+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);
-/* Free space section routines */
-static herr_t H5HF_man_iblock_skip_blocks(H5HF_hdr_t *hdr, hid_t dxpl_id,
- H5HF_indirect_t *iblock, haddr_t iblock_addr,
- unsigned start_entry, unsigned nentries);
-static herr_t H5HF_man_iblock_skip_ranges(H5HF_hdr_t *hdr, hid_t dxpl_id,
- H5HF_indirect_t *iblock, haddr_t iblock_addr,
- unsigned start_entry, unsigned nentries);
-
-/* Root indirect block routines */
-static herr_t H5HF_man_iblock_root_create(H5HF_hdr_t *hdr, hid_t dxpl_id,
- size_t min_dblock_size);
-static herr_t H5HF_man_iblock_root_double(H5HF_hdr_t *hdr, hid_t dxpl_id,
- size_t min_dblock_size);
-
-/* Misc. indirect block routines */
-static herr_t H5HF_man_iblock_create(H5HF_hdr_t *hdr, hid_t dxpl_id,
- hsize_t block_off, unsigned nrows, unsigned max_rows, haddr_t *addr_p);
/*********************/
/* Package Variables */
@@ -160,10 +145,40 @@ H5HF_iblock_decr(H5HF_indirect_t *iblock)
iblock->rc--;
/* Mark block as evictable again when no child blocks depend on it */
- if(iblock->rc == 0)
+ if(iblock->rc == 0) {
+ H5HF_indirect_t *tmp_iblock; /* Temporary pointer to indirect block */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: indirect block ref. count at zero, iblock->addr = %a\n", FUNC, iblock->addr);
+#endif /* QAK */
+ /* Lock indirect block */
+ if(iblock->nchildren == 0) {
+ if(NULL == (tmp_iblock = H5HF_man_iblock_protect(iblock->hdr, H5AC_dxpl_id, iblock->addr, iblock->nrows, NULL, 0, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
+ HDassert(tmp_iblock == iblock);
+ } /* end if */
+
if(H5AC_unpin_entry(iblock->hdr->f, iblock) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPIN, FAIL, "unable to unpin fractal heap indirect block")
+/* XXX: If the indirect block has no children, delete indirect block's entry
+ * from cache.
+ */
+ 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) {
+ /* Reset root pointer information */
+ iblock->hdr->man_dtable.curr_root_rows = 0;
+ iblock->hdr->man_dtable.table_addr = HADDR_UNDEF;
+ } /* end if */
+
+ /* Unlock indirect block with delete flag */
+ if(H5AC_unprotect(iblock->hdr->f, H5AC_dxpl_id, H5AC_FHEAP_IBLOCK, iblock->addr, tmp_iblock, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
+ tmp_iblock = NULL;
+ } /* end if */
+ } /* end if */
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_iblock_decr() */
@@ -195,23 +210,9 @@ HDfprintf(stderr, "%s: Marking indirect block as dirty\n", FUNC);
/* Sanity check */
HDassert(iblock);
-/* XXX: Need to mark a protected block as dirty eventually also... */
-{
- unsigned entry_status; /* Indirect block entry status */
-
- if(H5AC_get_entry_status(iblock->hdr->f, iblock->addr, &entry_status) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTMARKDIRTY, FAIL, "unable to query fractal heap indirect block status")
- HDassert(entry_status & H5AC_ES__IN_CACHE);
-
- if(!(entry_status & H5AC_ES__IS_PROTECTED)) {
- /* Mark indirect block as dirty in cache */
- if(H5AC_mark_pinned_entry_dirty(iblock->hdr->f, iblock, FALSE, 0) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTMARKDIRTY, FAIL, "unable to mark fractal heap indirect block as dirty")
- } /* end if */
-}
-
- /* Set the dirty flag for the indirect block */
- iblock->dirty = TRUE;
+ /* Mark indirect block as dirty in cache */
+ if(H5AC_mark_pinned_or_protected_entry_dirty(iblock->hdr->f, iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTMARKDIRTY, FAIL, "unable to mark fractal heap indirect block as dirty")
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -219,245 +220,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5HF_man_iblock_skip_blocks
- *
- * Purpose: Add skipped direct blocks to free space for heap
- *
- * Return: SUCCEED/FAIL
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Apr 3 2006
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HF_man_iblock_skip_blocks(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_indirect_t *iblock,
- haddr_t iblock_addr, unsigned start_entry, unsigned nentries)
-{
- H5HF_free_section_t *sec_node; /* Pointer to free list section for range */
- hsize_t sect_off; /* Offset of free section in heap */
- unsigned curr_row; /* Current row in indirect block */
- unsigned curr_col; /* Current column in indirect block */
- unsigned u; /* Local index variables */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_skip_blocks)
-#ifdef QAK
-HDfprintf(stderr, "%s: start_entry = %u, nentries = %u\n", FUNC, start_entry, nentries);
-#endif /* QAK */
-
- /*
- * Check arguments.
- */
- HDassert(hdr);
- HDassert(iblock);
- HDassert(H5F_addr_defined(iblock_addr));
-
- /* Compute starting column & row */
- curr_row = start_entry / hdr->man_dtable.cparam.width;
- curr_col = start_entry % hdr->man_dtable.cparam.width;
-
- /* Initialize information for rows skipped over */
- sect_off = iblock->block_off;
- for(u = 0; u < curr_row; u++)
- sect_off += hdr->man_dtable.row_block_size[u] * hdr->man_dtable.cparam.width;
- sect_off += hdr->man_dtable.row_block_size[curr_row] * curr_col;
-#ifdef QAK
-HDfprintf(stderr, "%s: sect_off = %Zu\n", FUNC, sect_off);
-#endif /* QAK */
-
- /* Loop over the blocks to skip */
- for(u = start_entry; u < (start_entry + nentries); /* u is advanced in loop */) {
- unsigned row_entries; /* Number of entries in a particular row */
-
- /* Compute number of entries in (possible partial) current row */
- row_entries = MIN(hdr->man_dtable.cparam.width - curr_col, (start_entry + nentries) - u);
-#ifdef QAK
-HDfprintf(stderr, "%s: u = %u\n", FUNC, u);
-HDfprintf(stderr, "%s: curr_col = %u, curr_row = %u\n", FUNC, curr_col, curr_row);
-HDfprintf(stderr, "%s: row_entries = %u, hdr->man_dtable.row_dblock_free[%u] = %Hu\n", FUNC, row_entries, curr_row, hdr->man_dtable.row_dblock_free[curr_row]);
-#endif /* QAK */
-
- /* Add free space section for blocks in this row */
-
- /* Create free list section node for blocks skipped over */
- if(NULL == (sec_node = H5FL_MALLOC(H5HF_free_section_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section")
-
- /* Set section's information */
- sec_node->sect_info.addr = sect_off;
- sec_node->sect_info.size = hdr->man_dtable.row_dblock_free[curr_row];
- sec_node->sect_info.cls = &hdr->sect_cls[H5FS_SECT_FHEAP_RANGE];
- sec_node->sect_info.state = H5FS_SECT_LIVE;
- sec_node->u.range.iblock = iblock;
- if(H5HF_iblock_incr(iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block")
- sec_node->u.range.row = curr_row;
- sec_node->u.range.col = curr_col;
- sec_node->u.range.num_entries = row_entries;
-
- /* Add new free space to the global list of space */
- if(H5HF_space_add(hdr, dxpl_id, sec_node) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add indirect block free space to global list")
-
- /* Advance row & column position */
- sect_off += row_entries * hdr->man_dtable.row_block_size[curr_row];
- curr_row++;
- curr_col = 0; /* (first partial row aligns this) */
-
- /* Increment index variable */
- u += row_entries;
- } /* end for */
-#ifdef QAK
-HDfprintf(stderr, "%s: sect_off = %Zu\n", FUNC, sect_off);
-#endif /* QAK */
-
- /* Advance the allocated heap size/new block iterator */
- if(H5HF_hdr_inc_alloc(hdr, sect_off, nentries) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't increase allocated heap size")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_man_iblock_skip_blocks() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5HF_man_iblock_skip_ranges
- *
- * Purpose: Add skipped indirect ranges to free space for heap
- *
- * Return: SUCCEED/FAIL
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Apr 4 2006
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HF_man_iblock_skip_ranges(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_indirect_t *iblock,
- haddr_t iblock_addr, unsigned start_entry, unsigned nentries)
-{
- H5HF_free_section_t *sec_node; /* Pointer to free list section for range */
- hsize_t sect_off; /* Offset of free section in heap */
- size_t row_dblock_free_space; /* Size of free space for row of direct blocks in a row */
- size_t acc_row_dblock_free_space; /* Accumulated size of free space for row of direct blocks in a row */
- unsigned curr_row; /* Current row in indirect block */
- unsigned curr_col; /* Current column in indirect block */
- unsigned u, w; /* Local index variables */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_skip_ranges)
-#ifdef QAK
-HDfprintf(stderr, "%s: start_entry = %u, nentries = %u\n", FUNC, start_entry, nentries);
-#endif /* QAK */
-
- /*
- * Check arguments.
- */
- HDassert(hdr);
- HDassert(iblock);
- HDassert(H5F_addr_defined(iblock_addr));
-
- /* Compute starting column & row */
- curr_row = start_entry / hdr->man_dtable.cparam.width;
- curr_col = start_entry % hdr->man_dtable.cparam.width;
-#ifdef QAK
-HDfprintf(stderr, "%s: curr_col = %u, curr_row = %u\n", FUNC, curr_col, curr_row);
-#endif /* QAK */
-
- /* Initialize information for rows skipped over */
- sect_off = iblock->block_off;
- for(u = 0; u < curr_row; u++)
- sect_off += hdr->man_dtable.row_block_size[u] * hdr->man_dtable.cparam.width;
- sect_off += hdr->man_dtable.row_block_size[curr_row] * curr_col;
-#ifdef QAK
-HDfprintf(stderr, "%s: sect_off = %Zu\n", FUNC, sect_off);
-#endif /* QAK */
-
- /* Loop over the blocks to skip */
- for(u = start_entry; u < (start_entry + nentries); /* u is advanced in loop */) {
- unsigned row_entries; /* Number of entries in a particular row */
- unsigned num_rows; /* Number of rows in indirect blocks referenced */
-
- /* Compute number of rows in indirect blocks covered by entry */
- num_rows = (H5V_log2_of2((uint32_t)hdr->man_dtable.row_block_size[curr_row]) -
- H5V_log2_of2(hdr->man_dtable.cparam.start_block_size)) - 1;
-
- /* Compute number of entries in (possible partial) current row */
- row_entries = MIN(hdr->man_dtable.cparam.width - curr_col, (start_entry + nentries) - u);
-#ifdef QAK
-HDfprintf(stderr, "%s: u = %u\n", FUNC, u);
-HDfprintf(stderr, "%s: curr_col = %u, curr_row = %u\n", FUNC, curr_col, curr_row);
-HDfprintf(stderr, "%s: row_entries = %u, num_rows = %u\n", FUNC, row_entries, num_rows);
-#endif /* QAK */
-
- /* Loop over rows in indirect blocks covered */
- acc_row_dblock_free_space = 0;
- for(w = 0; w < num_rows; w++) {
-
- /* Compute free space in direct blocks for this row */
- row_dblock_free_space = hdr->man_dtable.cparam.width * hdr->man_dtable.row_dblock_free[w];
- acc_row_dblock_free_space += row_dblock_free_space;
-#ifdef QAK
-HDfprintf(stderr, "%s: w = %u\n", FUNC, w);
-HDfprintf(stderr, "%s: hdr->man_dtable.row_dblock_free[%u] = %Zu\n", FUNC, w, hdr->man_dtable.row_dblock_free[w]);
-#endif /* QAK */
-
- /* Add "indirect" free space section for blocks in this row */
-
- /* Create free list section node for blocks skipped over */
- if(NULL == (sec_node = H5FL_MALLOC(H5HF_free_section_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section")
-
- /* Set section's information */
- sec_node->sect_info.addr = sect_off + hdr->man_dtable.row_block_off[w];
-#ifdef QAK
-HDfprintf(stderr, "%s: sec_node->sect_info.addr = %a\n", FUNC, sec_node->sect_info.addr);
-#endif /* QAK */
- sec_node->sect_info.size = hdr->man_dtable.row_dblock_free[w];
- sec_node->sect_info.cls = &hdr->sect_cls[H5FS_SECT_FHEAP_INDIRECT];
- sec_node->sect_info.state = H5FS_SECT_LIVE;
- sec_node->u.indirect.iblock = iblock;
- if(H5HF_iblock_incr(iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block")
- sec_node->u.indirect.row = curr_row;
- sec_node->u.indirect.col = curr_col;
- sec_node->u.indirect.num_entries = row_entries;
- sec_node->u.indirect.indir_row = w;
- sec_node->u.indirect.indir_nrows = num_rows;
-
- /* Add new free space to the global list of space */
- if(H5HF_space_add(hdr, dxpl_id, sec_node) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add indirect block free space to global list")
- } /* end for */
-#ifdef QAK
-HDfprintf(stderr, "%s: acc_row_dblock_free_space = %Zu\n", FUNC, acc_row_dblock_free_space);
-#endif /* QAK */
-
- /* Advance row & column position */
- sect_off += row_entries * hdr->man_dtable.row_block_size[curr_row];
- curr_row++;
- curr_col = 0; /* (first partial row aligns this) */
-
- /* Advance outer loop index */
- u += row_entries;
- } /* end for */
-#ifdef QAK
-HDfprintf(stderr, "%s: sect_off = %Zu\n", FUNC, sect_off);
-#endif /* QAK */
-
- /* Advance the allocated heap size/new block iterator */
- if(H5HF_hdr_inc_alloc(hdr, sect_off, nentries) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't increase allocated heap size")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_man_iblock_skip_ranges() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5HF_man_iblock_root_create
*
* Purpose: Create root indirect block
@@ -470,7 +232,7 @@ done:
*
*-------------------------------------------------------------------------
*/
-static herr_t
+herr_t
H5HF_man_iblock_root_create(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t min_dblock_size)
{
H5HF_indirect_t *iblock; /* Pointer to indirect block */
@@ -508,7 +270,7 @@ HDfprintf(stderr, "%s: nrows = %u\n", FUNC, nrows);
#endif /* QAK */
/* Allocate root indirect block */
- if(H5HF_man_iblock_create(hdr, dxpl_id, (hsize_t)0, nrows, hdr->man_dtable.max_root_rows, &iblock_addr) < 0)
+ if(H5HF_man_iblock_create(hdr, dxpl_id, NULL, 0, nrows, hdr->man_dtable.max_root_rows, &iblock_addr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap indirect block")
#ifdef QAK
HDfprintf(stderr, "%s: iblock_addr = %a\n", FUNC, iblock_addr);
@@ -532,30 +294,27 @@ HDfprintf(stderr, "%s: have_direct_block = %u\n", FUNC, (unsigned)have_direct_bl
if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, hdr->man_dtable.table_addr, hdr->man_dtable.cparam.start_block_size, iblock, 0, H5AC_WRITE)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap direct block")
- /* Point indirect block at direct block to add */
- iblock->ents[0].addr = hdr->man_dtable.table_addr;
-
- /* Make direct block share parent indirect block */
+ /* Attach direct block to new root indirect block */
dblock->parent = iblock;
dblock->par_entry = 0;
- if(H5HF_iblock_incr(iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block")
+ if(H5HF_man_iblock_attach(iblock, 0, hdr->man_dtable.table_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTATTACH, FAIL, "can't attach root direct block to parent indirect block")
- /* Unlock first (root) direct 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")
dblock = NULL;
} /* end if */
- /* Set up iterator at correct location */
- if(H5HF_man_iter_start_entry(hdr, &hdr->next_block, iblock, have_direct_block) < 0)
+ /* Start iterator at correct location */
+ if(H5HF_hdr_start_iter(hdr, iblock, (hsize_t)(have_direct_block ? hdr->man_dtable.cparam.start_block_size : 0), have_direct_block) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize block iterator")
/* Check for skipping over direct blocks, in order to get to large enough block */
if(min_dblock_size > hdr->man_dtable.cparam.start_block_size) {
/* Add skipped blocks to heap's free space */
- if(H5HF_man_iblock_skip_blocks(hdr, dxpl_id, iblock, iblock_addr,
- have_direct_block, ((nrows - 1) * hdr->man_dtable.cparam.width) - have_direct_block) < 0)
+ if(H5HF_hdr_skip_blocks(hdr, dxpl_id, iblock, have_direct_block,
+ ((nrows - 1) * hdr->man_dtable.cparam.width) - have_direct_block) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't add skipped blocks to heap's free space")
} /* end if */
@@ -582,13 +341,9 @@ HDfprintf(stderr, "%s: have_direct_block = %u\n", FUNC, (unsigned)have_direct_bl
acc_dblock_free -= hdr->man_dtable.row_dblock_free[0];
/* Extend heap to cover new root indirect block */
- if(H5HF_hdr_extend_heap(hdr, hdr->man_dtable.row_block_off[nrows], acc_dblock_free) < 0)
+ if(H5HF_hdr_adjust_heap(hdr, hdr->man_dtable.row_block_off[nrows], (hssize_t)acc_dblock_free) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, FAIL, "can't increase space to cover root direct block")
- /* Mark heap header as modified */
- if(H5HF_hdr_dirty(hdr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark header as dirty")
-
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_man_iblock_root_create() */
@@ -607,7 +362,7 @@ done:
*
*-------------------------------------------------------------------------
*/
-static herr_t
+herr_t
H5HF_man_iblock_root_double(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t min_dblock_size)
{
H5HF_indirect_t *iblock; /* Pointer to root indirect block */
@@ -665,7 +420,7 @@ HDfprintf(stderr, "%s: new_next_entry = %u\n", FUNC, new_next_entry);
#endif /* QAK */
/* Currently, the old block data is "thrown away" after the space is reallocated,
-* so avoid data copy in H5MF_realloc() call by just free'ing the space and
+* to avoid data copy in H5MF_realloc() call by just free'ing the space and
* allocating new space.
*
* This also keeps the file smaller, by freeing the space and then
@@ -674,8 +429,8 @@ HDfprintf(stderr, "%s: new_next_entry = %u\n", FUNC, new_next_entry);
* QAK - 3/14/2006
*/
/* Free previous indirect block disk space */
- if(H5MF_xfree(hdr->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, iblock->addr, (hsize_t)iblock->size)<0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap indirect block")
+ if(H5MF_xfree(hdr->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, iblock->addr, (hsize_t)iblock->size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap indirect block file space")
/* Compute size of buffer needed for new indirect block */
iblock->nrows = new_nrows;
@@ -695,8 +450,8 @@ HDfprintf(stderr, "%s: new_addr = %a\n", FUNC, new_addr);
/* Check for skipping over rows and add free section for skipped rows */
if(skip_direct_rows) {
/* Add skipped blocks to heap's free space */
- if(H5HF_man_iblock_skip_blocks(hdr, dxpl_id, iblock, new_addr,
- next_entry, (new_next_entry - next_entry)) < 0)
+ if(H5HF_hdr_skip_blocks(hdr, dxpl_id, iblock, next_entry,
+ (new_next_entry - next_entry)) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't add skipped blocks to heap's free space")
} /* end if */
@@ -714,9 +469,11 @@ HDfprintf(stderr, "%s: new_addr = %a\n", FUNC, new_addr);
HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty")
/* Move object in cache, if it actually was relocated */
- if(H5F_addr_ne(iblock->addr, new_addr))
+ if(H5F_addr_ne(iblock->addr, new_addr)) {
if(H5AC_rename(hdr->f, H5AC_FHEAP_IBLOCK, iblock->addr, new_addr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTSPLIT, FAIL, "unable to move fractal heap root indirect block")
+ iblock->addr = new_addr;
+ } /* end if */
/* Update other shared header info */
hdr->man_dtable.curr_root_rows = new_nrows;
@@ -728,363 +485,186 @@ HDfprintf(stderr, "%s: hdr->man_dtable.row_block_off[new_nrows - 1] = %Hu\n", FU
HDfprintf(stderr, "%s: hdr->man_dtable.row_block_off[new_nrows] = %Hu\n", FUNC, hdr->man_dtable.row_block_off[new_nrows]);
HDfprintf(stderr, "%s: acc_dblock_free = %Hu\n", FUNC, acc_dblock_free);
#endif /* QAK */
- if(H5HF_hdr_extend_heap(hdr, 2 * hdr->man_dtable.row_block_off[new_nrows - 1], acc_dblock_free) < 0)
+ if(H5HF_hdr_adjust_heap(hdr, 2 * hdr->man_dtable.row_block_off[new_nrows - 1], (hssize_t)acc_dblock_free) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, FAIL, "can't increase space to cover root direct block")
- /* Mark heap header as modified */
- if(H5HF_hdr_dirty(hdr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark header as dirty")
-
-/* XXX: Sanity check until can rename pinned entry in metadata cache */
-#ifndef NDEBUG
-{
-H5HF_indirect_t *old_root_iblock = iblock;
-#endif /* NDEBUG */
-
- /* Lock root indirect block (again) */
- if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, new_addr, hdr->man_dtable.curr_root_rows, NULL, 0, H5AC_WRITE)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
- iblock->addr = new_addr;
-
-#ifndef NDEBUG
- HDassert(old_root_iblock == iblock);
-}
-#endif /* NDEBUG */
-
- /* Update the indirect block pointer in iterator */
- /* (pins the indirect block after it's in the new location) */
- if(H5HF_man_iter_update_iblock(&hdr->next_block, iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTMODIFY, FAIL, "unable to update indirect block for block iterator")
-
- /* Release the indirect block (marked as dirty) */
- if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock->addr, iblock, H5AC__DIRTIED_FLAG) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
-
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_man_iblock_root_double() */
/*-------------------------------------------------------------------------
- * Function: H5HF_man_iblock_place_dblock
- *
- * Purpose: Find indirect block with location for placing a direct block
+ * Function: H5HF_man_iblock_root_halve
*
- * Note: Creates necessary indirect blocks
+ * Purpose: Halve size of root indirect block
*
- * Return: Pointer to indirect block on success, NULL on failure
+ * Return: SUCCEED/FAIL
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
- * Mar 14 2006
+ * Jun 12 2006
*
*-------------------------------------------------------------------------
*/
-H5HF_indirect_t *
-H5HF_man_iblock_place_dblock(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t min_dblock_size,
- size_t *entry_p, size_t *dblock_size)
+static herr_t
+H5HF_man_iblock_root_halve(H5HF_indirect_t *iblock, hid_t dxpl_id)
{
- H5HF_indirect_t *ret_value; /* Return value */
+ H5HF_hdr_t *hdr = iblock->hdr; /* Pointer to heap header */
+ 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 new_nrows; /* New # of rows */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_place_dblock)
-#ifdef QAK
-HDfprintf(stderr, "%s: min_dblock_size = %Zu\n", FUNC, min_dblock_size);
-#endif /* QAK */
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_root_halve)
- /*
- * Check arguments.
- */
+ /* Sanity check */
+ HDassert(iblock);
+ HDassert(iblock->parent == NULL);
HDassert(hdr);
- HDassert(min_dblock_size > 0);
-
- /* Check for creating first indirect block */
- if(hdr->man_dtable.curr_root_rows == 0) {
- if(H5HF_man_iblock_root_create(hdr, dxpl_id, min_dblock_size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, NULL, "unable to create root indirect block")
- } /* end if */
- else {
- H5HF_indirect_t *iblock; /* Pointer to indirect block */
- hbool_t walked_up, walked_down; /* Condition variables for finding direct block location */
- unsigned next_row; /* Iterator's next block row */
- unsigned next_entry; /* Iterator's next block entry */
- unsigned min_dblock_row; /* Minimum row for direct block size request */
#ifdef QAK
-HDfprintf(stderr, "%s: searching root indirect block\n", FUNC);
+HDfprintf(stderr, "%s: Reducing root indirect block\n", FUNC);
#endif /* QAK */
- /* Compute min. row for direct block requested */
- min_dblock_row = H5HF_dtable_size_to_row(&hdr->man_dtable, min_dblock_size);
-#ifdef QAK
-HDfprintf(stderr, "%s: min_dblock_size = %Zu, min_dblock_row = %u\n", FUNC, min_dblock_size, min_dblock_row);
-#endif /* QAK */
-
- /* Initialize block iterator, if necessary */
- if(!H5HF_man_iter_ready(&hdr->next_block)) {
-#ifdef QAK
-HDfprintf(stderr, "%s: hdr->man_alloc_size = %Hu\n", FUNC, hdr->man_alloc_size);
-#endif /* QAK */
- /* Start iterator with offset of allocated space */
- if(H5HF_man_iter_start_offset(hdr, dxpl_id, &hdr->next_block, hdr->man_alloc_size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "unable to set block iterator location")
- } /* end if */
- /* Get information about current iterator location */
- if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL,
- &next_entry, &iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, NULL, "unable to retrieve current block iterator location")
+ /* Compute maximum row used by child of indirect block */
+ max_child_row = iblock->max_child / hdr->man_dtable.cparam.width;
+ /* Compute new # of rows in root indirect block */
+ new_nrows = 1 << (1 + H5V_log2_gen((hsize_t)max_child_row));
#ifdef QAK
-HDfprintf(stderr, "%s: Check 1.0\n", FUNC);
-HDfprintf(stderr, "%s: iblock = %p\n", FUNC, iblock);
+HDfprintf(stderr, "%s: new_nrows = %u\n", FUNC, new_nrows);
HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows);
-HDfprintf(stderr, "%s: next_row = %u\n", FUNC, next_row);
-HDfprintf(stderr, "%s: next_entry = %u\n", FUNC, next_entry);
#endif /* QAK */
- /* Check for skipping over blocks in the current block */
- if(min_dblock_row > next_row && next_row < iblock->nrows) {
- unsigned min_entry; /* Min entry for direct block requested */
- unsigned skip_entries; /* Number of entries to skip in the current block */
-
- /* Compute the number of entries to skip in the current block */
- min_entry = min_dblock_row * hdr->man_dtable.cparam.width;
- if(min_dblock_row >= iblock->nrows)
- skip_entries = (iblock->nrows * hdr->man_dtable.cparam.width) - next_entry;
- else
- skip_entries = min_entry - next_entry;
-#ifdef QAK
-HDfprintf(stderr, "%s: min_entry = %u, skip_entries = %u\n", FUNC, min_entry, skip_entries);
-#endif /* QAK */
-
- /* Add skipped direct blocks to heap's free space */
- if(H5HF_man_iblock_skip_blocks(hdr, dxpl_id, iblock, iblock->addr, next_entry, skip_entries) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, NULL, "can't add skipped blocks to heap's free space")
- /* Get information about new iterator location */
- if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL,
- &next_entry, &iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, NULL, "unable to retrieve current block iterator location")
- } /* end if */
+/* Currently, the old block data is "thrown away" after the space is reallocated,
+* to avoid data copy in H5MF_realloc() call by just free'ing the space and
+* allocating new space.
+*
+* This also keeps the file smaller, by freeing the space and then
+* allocating new space, instead of vice versa (in H5MF_realloc).
+*
+* QAK - 6/12/2006
+*/
+ /* Free previous indirect block disk space */
+ if(H5MF_xfree(hdr->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, iblock->addr, (hsize_t)iblock->size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap indirect block file space")
- do {
- /* Reset conditions for leaving loop */
- walked_up = walked_down = FALSE;
+ /* Compute free space in rows to delete */
+ acc_dblock_free = 0;
+ for(u = new_nrows; u < iblock->nrows; u++)
+ acc_dblock_free += hdr->man_dtable.row_dblock_free[u] * hdr->man_dtable.cparam.width;
-#ifdef QAK
-HDfprintf(stderr, "%s: Check 2.0\n", FUNC);
-HDfprintf(stderr, "%s: iblock = %p\n", FUNC, iblock);
-HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows);
-HDfprintf(stderr, "%s: next_row = %u\n", FUNC, next_row);
-HDfprintf(stderr, "%s: next_entry = %u\n", FUNC, next_entry);
-#endif /* QAK */
+ /* Compute size of buffer needed for new indirect block */
+ iblock->nrows = new_nrows;
+ iblock->size = H5HF_MAN_INDIRECT_SIZE(hdr, iblock);
- /* Check for walking off end of indirect block */
- /* (walk up iterator) */
- while(next_row >= iblock->nrows) {
-#ifdef QAK
-HDfprintf(stderr, "%s: Off the end of a block\n", FUNC);
-#endif /* QAK */
- /* Check for needing to expand root indirect block */
- if(iblock->parent == NULL) {
-#ifdef QAK
-HDfprintf(stderr, "%s: Doubling root block\n", FUNC);
-#endif /* QAK */
- if(H5HF_man_iblock_root_double(hdr, dxpl_id, min_dblock_size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, NULL, "unable to double root indirect block")
- } /* end if */
- else {
-#ifdef QAK
-HDfprintf(stderr, "%s: Walking up a level\n", FUNC);
-#endif /* QAK */
- /* Move iterator up one level */
- if(H5HF_man_iter_up(&hdr->next_block) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTNEXT, NULL, "unable to advance current block iterator location")
-
- /* Increment location of next block at this level */
- if(H5HF_man_iter_next(hdr, &hdr->next_block, 1) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't advance fractal heap block location")
- } /* end else */
-
- /* Get information about new iterator location */
- if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL,
- &next_entry, &iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, NULL, "unable to retrieve current block iterator location")
-
- /* Indicate that we walked up */
- walked_up = TRUE;
- } /* end while */
+ /* Allocate space for the new indirect block on disk */
+ if(HADDR_UNDEF == (new_addr = H5MF_alloc(hdr->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, (hsize_t)iblock->size)))
+ HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap indirect block")
#ifdef QAK
-HDfprintf(stderr, "%s: Check 3.0\n", FUNC);
-HDfprintf(stderr, "%s: iblock = %p\n", FUNC, iblock);
-HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows);
-HDfprintf(stderr, "%s: next_row = %u\n", FUNC, next_row);
-HDfprintf(stderr, "%s: next_entry = %u\n", FUNC, next_entry);
+HDfprintf(stderr, "%s: new_addr = %a\n", FUNC, new_addr);
#endif /* QAK */
- /* Check for walking into child indirect block */
- /* (walk down iterator) */
- if(next_row >= hdr->man_dtable.max_direct_rows) {
- hsize_t next_size; /* Size of next direct block to create */
- unsigned child_nrows; /* Number of rows in new indirect block */
+ /* Re-allocate direct block entry table */
+ if(NULL == (iblock->ents = H5FL_SEQ_REALLOC(H5HF_indirect_ent_t, iblock->ents, (iblock->nrows * hdr->man_dtable.cparam.width))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct entries")
-#ifdef QAK
-HDfprintf(stderr, "%s: Walking down into child indirect block\n", FUNC);
-#endif /* QAK */
-#ifdef QAK
-HDfprintf(stderr, "%s: Check 3.1\n", FUNC);
-HDfprintf(stderr, "%s: iblock = %p\n", FUNC, iblock);
-HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows);
-HDfprintf(stderr, "%s: next_row = %u\n", FUNC, next_row);
-HDfprintf(stderr, "%s: next_entry = %u\n", FUNC, next_entry);
-#endif /* QAK */
- HDassert(!H5F_addr_defined(iblock->ents[next_entry].addr));
+ /* Move object in cache, if it actually was relocated */
+ if(H5F_addr_ne(iblock->addr, new_addr)) {
+ if(H5AC_rename(hdr->f, H5AC_FHEAP_IBLOCK, iblock->addr, new_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSPLIT, FAIL, "unable to move fractal heap root indirect block")
+ iblock->addr = new_addr;
+ } /* end if */
- /* Compute # of rows in next child indirect block to use */
- next_size = hdr->man_dtable.row_block_size[next_row];
- child_nrows = (H5V_log2_gen(next_size) - hdr->man_dtable.first_row_bits) + 1;
-#ifdef QAK
-HDfprintf(stderr, "%s: child_nrows = %u\n", FUNC, child_nrows);
-#endif /* QAK */
+ /* 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")
- /* Check for skipping over indirect blocks */
- /* (that don't have direct blocks large enough to hold direct block size requested) */
- if(hdr->man_dtable.row_block_size[child_nrows - 1] < min_dblock_size) {
- unsigned child_rows_needed; /* Number of rows needed to hold direct block */
- unsigned child_entry; /* Entry of child indirect block */
+ /* Update other shared header info */
+ hdr->man_dtable.curr_root_rows = new_nrows;
+ hdr->man_dtable.table_addr = new_addr;
+ /* Shrink heap to only cover new root indirect block */
#ifdef QAK
-HDfprintf(stderr, "%s: Skipping indirect block row that is too small\n", FUNC);
-#endif /* QAK */
- /* Compute # of rows needed in child indirect block */
- child_rows_needed = (H5V_log2_of2(min_dblock_size) - H5V_log2_of2(hdr->man_dtable.cparam.start_block_size)) + 2;
- HDassert(child_rows_needed > child_nrows);
- child_entry = (next_row + (child_rows_needed - child_nrows)) * hdr->man_dtable.cparam.width;
- if(child_entry > (iblock->nrows * hdr->man_dtable.cparam.width))
- child_entry = iblock->nrows * hdr->man_dtable.cparam.width;
-#ifdef QAK
-HDfprintf(stderr, "%s: child_rows_needed = %u\n", FUNC, child_rows_needed);
-HDfprintf(stderr, "%s: child_entry = %u\n", FUNC, child_entry);
+HDfprintf(stderr, "%s: hdr->man_dtable.row_block_off[new_nrows - 1] = %Hu\n", FUNC, hdr->man_dtable.row_block_off[new_nrows - 1]);
+HDfprintf(stderr, "%s: hdr->man_dtable.row_block_off[new_nrows] = %Hu\n", FUNC, hdr->man_dtable.row_block_off[new_nrows]);
+HDfprintf(stderr, "%s: acc_dblock_free = %Hu\n", FUNC, acc_dblock_free);
#endif /* QAK */
+ if(H5HF_hdr_adjust_heap(hdr, 2 * hdr->man_dtable.row_block_off[new_nrows - 1], -(hssize_t)acc_dblock_free) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce space to cover root direct block")
- /* Add skipped indirect ranges to heap's free space */
- if(H5HF_man_iblock_skip_ranges(hdr, dxpl_id, iblock, iblock->addr, next_entry, (child_entry - next_entry)) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, NULL, "can't add skipped blocks to heap's free space")
- } /* end if */
- else {
- H5HF_indirect_t *new_iblock; /* Pointer to new indirect block */
- hsize_t new_iblock_off; /* Direct block offset in heap address space */
- haddr_t new_iblock_addr; /* New indirect block's address */
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_man_iblock_root_halve() */
-#ifdef QAK
-HDfprintf(stderr, "%s: Allocating new child indirect block\n", FUNC);
-#endif /* QAK */
- /* Compute the direct block's offset in the heap's address space */
- new_iblock_off = iblock->block_off;
- new_iblock_off += hdr->man_dtable.row_block_off[next_entry / hdr->man_dtable.cparam.width];
- new_iblock_off += hdr->man_dtable.row_block_size[next_entry / hdr->man_dtable.cparam.width] * (next_entry % hdr->man_dtable.cparam.width);
-
- /* Allocate new indirect block */
- if(H5HF_man_iblock_create(hdr, dxpl_id, new_iblock_off, child_nrows, child_nrows, &new_iblock_addr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "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)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap indirect block")
-
- /* Set parent information */
- HDassert(new_iblock->parent == NULL);
- new_iblock->parent = iblock;
- new_iblock->par_entry = next_entry;
- if(H5HF_iblock_incr(iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared indirect block")
-
- /* Point current indirect block at new indirect block */
- iblock->ents[next_entry].addr = new_iblock_addr;
-
- /* Move iterator down one level */
- if(H5HF_man_iter_down(&hdr->next_block, new_iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTNEXT, NULL, "unable to advance current block iterator location")
-
- /* Get information about new iterator location */
- if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL,
- &next_entry, NULL) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, NULL, "unable to retrieve current block iterator location")
- next_size = hdr->man_dtable.row_block_size[next_row];
-#ifdef QAK
-HDfprintf(stderr, "%s: next_row = %u\n", FUNC, next_row);
-HDfprintf(stderr, "%s: next_entry = %u\n", FUNC, next_entry);
-#endif /* QAK */
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_man_iblock_root_revert
+ *
+ * Purpose: Revert root indirect block back to root direct block
+ *
+ * Note: Any sections left pointing to the old root indirect block
+ * will be cleaned up by the free space manager
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 31 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_man_iblock_root_revert(H5HF_indirect_t *root_iblock, hid_t dxpl_id)
+{
+ H5HF_hdr_t *hdr; /* Pointer to heap's header */
+ H5HF_direct_t *dblock = NULL; /* Pointer to new root indirect block */
+ haddr_t dblock_addr; /* Direct block's address in the file */
+ size_t dblock_size; /* Direct block's size */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_root_revert)
- /* Check for skipping over rows and add free section for skipped rows */
- if(min_dblock_size > next_size) {
- unsigned new_entry; /* Entry of direct block which is large enough */
+ /*
+ * Check arguments.
+ */
+ HDassert(root_iblock);
- /* Compute entry for direct block size requested */
- new_entry = hdr->man_dtable.cparam.width * min_dblock_row;
#ifdef QAK
-HDfprintf(stderr, "%s: Skipping rows in new child indirect block - new_entry = %u\n", FUNC, new_entry);
+HDfprintf(stderr, "%s: Reverting root indirect block\n", FUNC);
#endif /* QAK */
- /* Add skipped blocks to heap's free space */
- if(H5HF_man_iblock_skip_blocks(hdr, dxpl_id, new_iblock, new_iblock->addr, 0, new_entry) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, NULL, "can't add skipped blocks to heap's free space")
- } /* end if */
-
- /* Mark new indirect block as modified */
- if(H5HF_iblock_dirty(new_iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, NULL, "can't mark indirect block as dirty")
+ /* Set up local convenience variables */
+ hdr = root_iblock->hdr;
+ dblock_addr = root_iblock->ents[0].addr;
+ dblock_size = hdr->man_dtable.cparam.start_block_size;
- /* Mark current indirect block as modified */
- if(H5HF_iblock_dirty(iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, NULL, "can't mark indirect block as dirty")
+ /* Get pointer to last direct block */
+ if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, root_iblock, 0, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap direct block")
- /* Unprotect child indirect block */
- if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, new_iblock->addr, new_iblock, H5AC__DIRTIED_FLAG) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, NULL, "unable to release fractal heap indirect block")
- } /* end else */
+ /* Detach direct block from parent */
+ if(H5HF_man_iblock_detach(dblock->parent, dxpl_id, dblock->par_entry) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTATTACH, FAIL, "can't detach direct block from parent indirect block")
+ dblock->parent = NULL;
+ dblock->par_entry = 0;
- /* Get information about new iterator location */
- if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL,
- &next_entry, &iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, NULL, "unable to retrieve current block iterator location")
+ /* Point root at direct block */
+ hdr->man_dtable.curr_root_rows = 0;
+ hdr->man_dtable.table_addr = dblock_addr;
- /* Indicate that we walked down */
- walked_down = TRUE;
- } /* end if */
- } while(walked_down || walked_up);
- } /* end else */
-
- /* Get information about iterator location */
-{
- H5HF_indirect_t *iblock; /* Pointer to indirect block */
- unsigned next_row; /* Iterator's next block row */
- unsigned next_entry; /* Iterator's next block entry */
- size_t next_size; /* Size of next direct block to create */
-
- if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL,
- &next_entry, &iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, NULL, "unable to retrieve current block iterator location")
- HDassert(next_row < iblock->nrows);
- next_size = hdr->man_dtable.row_block_size[next_row];
-
- /* Check for skipping over blocks */
- if(min_dblock_size > next_size) {
-HDfprintf(stderr, "%s: Skipping direct block sizes not supported, min_dblock_size = %Zu, next_size = %Zu\n", FUNC, min_dblock_size, next_size);
-HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, NULL, "skipping direct block sizes not supported yet")
- } /* end if */
-
- /* Set entry for new direct block to use */
- *entry_p = next_entry;
-
- /* Set size of direct block to create */
- *dblock_size = next_size;
-
- /* Set return value */
- ret_value = iblock;
-}
+ /* Reset 'next block' iterator */
+ if(H5HF_hdr_reset_iter(hdr, (hsize_t)dblock_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't reset block iterator")
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")
+
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_man_iblock_place_dblock() */
+} /* end H5HF_man_iblock_root_revert() */
/*-------------------------------------------------------------------------
@@ -1132,12 +712,6 @@ H5HF_man_iblock_alloc_range(H5HF_hdr_t *hdr, hid_t dxpl_id,
/* Compute info about range */
cur_entry = (old_sec_node->u.range.row * hdr->man_dtable.cparam.width) + old_sec_node->u.range.col;
- /* Check for range covering indirect blocks */
- if(old_sec_node->u.range.row >= hdr->man_dtable.max_direct_rows) {
-HDfprintf(stderr, "%s: Can't handle range sections over indirect blocks yet\n", FUNC);
-HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "'range' free space sections over indirect blocks not supported yet")
- } /* end if */
-
/* Get a pointer to the indirect block covering the range */
iblock = old_sec_node->u.range.iblock;
HDassert(iblock);
@@ -1146,42 +720,13 @@ HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "'range' free space sections over i
HDfprintf(stderr, "%s: cur_entry = %u\n", FUNC, cur_entry);
HDfprintf(stderr, "%s: old_sec_node->u.range.num_entries = %u\n", FUNC, old_sec_node->u.range.num_entries);
#endif /* QAK */
-#ifdef QAK
-HDfprintf(stderr, "%s: hdr->man_dtable.row_block_size[old_sec_node->u.range.row] = %Hu\n", FUNC, hdr->man_dtable.row_block_size[old_sec_node->u.range.row]);
-HDfprintf(stderr, "%s: old_sec_node->sect_addr = %a\n", FUNC, old_sec_node->sect_addr);
-#endif /* QAK */
/* Create direct block of appropriate size */
- if(H5HF_man_dblock_create(dxpl_id, hdr, iblock, cur_entry, (size_t)hdr->man_dtable.row_block_size[old_sec_node->u.range.row], (hsize_t)old_sec_node->sect_info.addr, &dblock_addr, &dblock_sec_node) < 0)
+ if(H5HF_man_dblock_create(dxpl_id, hdr, iblock, cur_entry, &dblock_addr, &dblock_sec_node) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap direct block")
- /* Hook direct block up to indirect block */
- iblock->ents[cur_entry].addr = dblock_addr;
-
- /* 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")
-
- /* Check for only single block covered in range section */
- if(old_sec_node->u.range.num_entries == 1) {
- /* Drop reference count on indirect block that free section is in */
- if(H5HF_iblock_decr(iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block")
-
- /* Free section structure */
- H5FL_FREE(H5HF_free_section_t, old_sec_node);
- } /* end if */
- else {
- /* Adjust section information */
- old_sec_node->sect_info.addr += hdr->man_dtable.row_block_size[old_sec_node->u.range.row];
-
- /* Adjust range information */
- old_sec_node->u.range.col++;
- old_sec_node->u.range.num_entries--;
-
- /* Add section back to free space list */
- if(H5HF_space_add(hdr, dxpl_id, old_sec_node) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add indirect block free space to global list")
- } /* end else */
+ /* Reduce (& possibly re-add) 'range' section */
+ if(H5HF_sect_range_reduce(hdr, dxpl_id, old_sec_node) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce indirect section node")
/* Point 'sec_node' at new direct block section node */
*sec_node = dblock_sec_node;
@@ -1217,7 +762,6 @@ H5HF_man_iblock_alloc_indirect(H5HF_hdr_t *hdr, hid_t dxpl_id,
haddr_t child_iblock_addr; /* Address of child indirect block */
haddr_t dblock_addr; /* New direct block's address */
H5HF_free_section_t *dblock_sec_node = NULL; /* Pointer to direct block's section node */
- H5HF_free_section_t *range_sec_node = NULL; /* Pointer to new range section node */
H5HF_free_section_t *old_sec_node = *sec_node; /* Pointer to old indirect section node */
unsigned curr_entry; /* Current entry in indirect block */
unsigned dblock_entry; /* Entry of direct block in child indirect block */
@@ -1246,8 +790,10 @@ H5HF_man_iblock_alloc_indirect(H5HF_hdr_t *hdr, hid_t dxpl_id,
#ifdef QAK
HDfprintf(stderr, "%s: curr_entry = %u\n", FUNC, curr_entry);
+HDfprintf(stderr, "%s: iblock->addr = %a\n", FUNC, iblock->addr);
+HDfprintf(stderr, "%s: iblock->block_off = %Hu\n", FUNC, iblock->block_off);
+HDfprintf(stderr, "%s: iblock->parent = %p\n", FUNC, iblock->parent);
HDfprintf(stderr, "%s: iblock->ents[curr_entry].addr = %a\n", FUNC, iblock->ents[curr_entry].addr);
-HDfprintf(stderr, "%s: iblock->ents[curr_entry].free_space = %Hu\n", FUNC, iblock->ents[curr_entry].free_space);
HDfprintf(stderr, "%s: old_sec_node->u.indirect.indir_nrows = %u\n", FUNC, old_sec_node->u.indirect.indir_nrows);
HDfprintf(stderr, "%s: old_sec_node->u.indirect.num_entries = %u\n", FUNC, old_sec_node->u.indirect.num_entries);
#endif /* QAK */
@@ -1260,42 +806,16 @@ HDfprintf(stderr, "%s: old_sec_node->u.indirect.num_entries = %u\n", FUNC, old_s
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
} /* end if */
else {
- hsize_t new_iblock_off; /* Offset of new indirect block */
-
- /* Compute heap offset of new indirect block */
- new_iblock_off = iblock->block_off +
- hdr->man_dtable.row_block_off[old_sec_node->u.indirect.row] +
- (old_sec_node->u.indirect.col *
- hdr->man_dtable.row_block_size[old_sec_node->u.indirect.row]);
-#ifdef QAK
-HDfprintf(stderr, "%s: iblock->block_off = %Hu\n", FUNC, iblock->block_off);
-HDfprintf(stderr, "%s: new_iblock_off = %Hu\n", FUNC, new_iblock_off);
-#endif /* QAK */
-
/* Create child indirect block */
- if(H5HF_man_iblock_create(hdr, dxpl_id, new_iblock_off, old_sec_node->u.indirect.indir_nrows, old_sec_node->u.indirect.indir_nrows, &child_iblock_addr) < 0)
+ if(H5HF_man_iblock_create(hdr, dxpl_id, iblock, curr_entry, old_sec_node->u.indirect.indir_nrows, old_sec_node->u.indirect.indir_nrows, &child_iblock_addr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap indirect block")
/* Lock new child indirect block */
if(NULL == (child_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, child_iblock_addr, old_sec_node->u.indirect.indir_nrows, iblock, curr_entry, H5AC_WRITE)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
-
- /* Set parent information */
- HDassert(child_iblock->parent == NULL);
- child_iblock->parent = iblock;
- child_iblock->par_entry = curr_entry;
- if(H5HF_iblock_incr(iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block")
#ifdef QAK
HDfprintf(stderr, "%s: child_iblock->child_free_space = %Hu\n", FUNC, child_iblock->child_free_space);
#endif /* QAK */
-
- /* Hook child up to parent indirect block */
- iblock->ents[curr_entry].addr = child_iblock_addr;
-
- /* Mark parent indirect block as modified */
- if(H5HF_iblock_dirty(iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty")
} /* end else */
/* Compute entry for new direct block in child indirect block */
@@ -1308,64 +828,19 @@ HDfprintf(stderr, "%s: old_sec_node->u.indirect.indir_row = %u\n", FUNC, old_sec
HDfprintf(stderr, "%s: hdr->man_dtable.row_block_size[old_sec_node->u.indirect.indir_row] = %Hu\n", FUNC, hdr->man_dtable.row_block_size[old_sec_node->u.indirect.indir_row]);
HDfprintf(stderr, "%s: old_sec_node->sect_addr = %a\n", FUNC, old_sec_node->sect_addr);
#endif /* QAK */
- if(H5HF_man_dblock_create(dxpl_id, hdr, child_iblock, dblock_entry, (size_t)hdr->man_dtable.row_block_size[old_sec_node->u.indirect.indir_row], (hsize_t)old_sec_node->sect_info.addr, &dblock_addr, &dblock_sec_node) < 0)
+ if(H5HF_man_dblock_create(dxpl_id, hdr, child_iblock, dblock_entry, &dblock_addr, &dblock_sec_node) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap direct block")
- /* Hook direct block up to child indirect block */
- child_iblock->ents[dblock_entry].addr = dblock_addr;
-
- /* Mark child indirect block as modified */
- if(H5HF_iblock_dirty(child_iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty")
-
-
/* Create "range" section for other direct blocks in row of child indirect block */
+ if(H5HF_sect_range_add(hdr, dxpl_id, (child_iblock->block_off + hdr->man_dtable.row_block_off[old_sec_node->u.indirect.indir_row]
+ + hdr->man_dtable.row_block_size[old_sec_node->u.indirect.indir_row]),
+ old_sec_node->sect_info.size, child_iblock, old_sec_node->u.indirect.indir_row,
+ 1, hdr->man_dtable.cparam.width - 1) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create range section for indirect block's free space")
- /* Create free list section node for blocks skipped over */
- if(NULL == (range_sec_node = H5FL_MALLOC(H5HF_free_section_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section")
-
- /* Set section's information */
- range_sec_node->sect_info.addr = child_iblock->block_off + hdr->man_dtable.row_block_off[old_sec_node->u.indirect.indir_row]
- + hdr->man_dtable.row_block_size[old_sec_node->u.indirect.indir_row];
- range_sec_node->sect_info.size = old_sec_node->sect_info.size;
- range_sec_node->sect_info.cls = &hdr->sect_cls[H5FS_SECT_FHEAP_RANGE];
- range_sec_node->sect_info.state = H5FS_SECT_LIVE;
- range_sec_node->u.range.iblock = child_iblock;
- if(H5HF_iblock_incr(child_iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block")
- range_sec_node->u.range.row = old_sec_node->u.indirect.indir_row;
- range_sec_node->u.range.col = 1;
- range_sec_node->u.range.num_entries = hdr->man_dtable.cparam.width - 1;
-
- /* Add new free space to the global list of space */
- if(H5HF_space_add(hdr, dxpl_id, range_sec_node) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add indirect block free space to global list")
-
-
- /* Reduce "indirect" section */
-
- /* Check for only single block covered in range section */
- if(old_sec_node->u.indirect.num_entries == 1) {
- /* Drop reference count on indirect block that free section is in */
- if(H5HF_iblock_decr(iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block")
-
- /* Free section structure */
- H5FL_FREE(H5HF_free_section_t, old_sec_node);
- } /* end if */
- else {
- /* Adjust section information */
- old_sec_node->sect_info.addr += hdr->man_dtable.row_block_size[old_sec_node->u.indirect.row];
-
- /* Adjust range information */
- old_sec_node->u.indirect.col++;
- old_sec_node->u.indirect.num_entries--;
-
- /* Add section back to free space list */
- if(H5HF_space_add(hdr, dxpl_id, old_sec_node) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add indirect block free space to global list")
- } /* end else */
+ /* Reduce (& possibly re-add) 'indirect' section */
+ if(H5HF_sect_indirect_reduce(hdr, dxpl_id, old_sec_node) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce indirect section node")
/* Release the child indirect block (marked as dirty) */
if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, child_iblock_addr, child_iblock, H5AC__DIRTIED_FLAG) < 0)
@@ -1392,9 +867,9 @@ done:
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5HF_man_iblock_create(H5HF_hdr_t *hdr, hid_t dxpl_id,
- hsize_t block_off, unsigned nrows, unsigned max_rows, haddr_t *addr_p)
+herr_t
+H5HF_man_iblock_create(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_indirect_t *par_iblock,
+ unsigned par_entry, unsigned nrows, unsigned max_rows, haddr_t *addr_p)
{
H5HF_indirect_t *iblock = NULL; /* Pointer to indirect block */
size_t u; /* Local index variable */
@@ -1424,16 +899,12 @@ H5HF_man_iblock_create(H5HF_hdr_t *hdr, hid_t dxpl_id,
HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared heap header")
#ifdef QAK
-HDfprintf(stderr, "%s: nrows = %u, max_nrows = %u\n", FUNC, nrows, max_nrows);
+HDfprintf(stderr, "%s: nrows = %u, max_rows = %u\n", FUNC, nrows, max_rows);
#endif /* QAK */
/* Set info for direct block */
iblock->rc = 0;
- iblock->parent = NULL; /* Temporary, except for root indirect block */
- iblock->par_entry = 0;
- iblock->block_off = block_off;
iblock->nrows = nrows;
iblock->max_rows = max_rows;
- iblock->dirty = TRUE;
/* Compute size of buffer needed for indirect block */
iblock->size = H5HF_MAN_INDIRECT_SIZE(hdr, iblock);
@@ -1451,7 +922,26 @@ HDfprintf(stderr, "%s: nrows = %u, max_nrows = %u\n", FUNC, nrows, max_nrows);
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap indirect block")
iblock->addr = *addr_p;
-/* XXX: Update indirect statistics when they are added */
+ /* Attach to parent indirect block, if there is one */
+ iblock->parent = par_iblock;
+ iblock->par_entry = par_entry;
+ if(iblock->parent) {
+ /* Attach new block to parent */
+ if(H5HF_man_iblock_attach(iblock->parent, par_entry, *addr_p) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTATTACH, FAIL, "can't attach indirect block to parent indirect block")
+
+ /* Compute the indirect block's offset in the heap's address space */
+ /* (based on parent's block offset) */
+ iblock->block_off = par_iblock->block_off;
+ iblock->block_off += hdr->man_dtable.row_block_off[par_entry / hdr->man_dtable.cparam.width];
+ iblock->block_off += hdr->man_dtable.row_block_size[par_entry / hdr->man_dtable.cparam.width] * (par_entry % hdr->man_dtable.cparam.width);
+ } /* end if */
+ else
+ iblock->block_off = 0; /* Must be the root indirect block... */
+
+ /* Update indirect block's statistics */
+ iblock->nchildren = 0;
+ iblock->max_child = 0;
/* Cache the new fractal heap header */
if(H5AC_set(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, *addr_p, iblock, H5AC__NO_FLAGS_SET) < 0)
@@ -1517,3 +1007,156 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_man_iblock_protect() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_man_iblock_attach
+ *
+ * Purpose: Attach a block to an indirect block
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 30 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_man_iblock_attach(H5HF_indirect_t *iblock, unsigned entry, haddr_t child_addr)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_attach)
+#ifdef QAK
+HDfprintf(stderr, "%s: iblock = %p, entry = %u, child_addr = %a, iblock_nrows = %u\n", FUNC, iblock, entry, child_addr);
+#endif /* QAK */
+
+ /*
+ * Check arguments.
+ */
+ HDassert(iblock);
+ HDassert(H5F_addr_defined(child_addr));
+
+ /* Increment the reference count on this indirect block */
+ 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 */
+ iblock->ents[entry].addr = child_addr;
+
+ /* Check for max. entry used */
+ if(entry > iblock->max_child)
+ iblock->max_child = entry;
+
+ /* Increment the # of child blocks */
+ iblock->nchildren++;
+
+ /* Mark indirect block as modified */
+ if(H5HF_iblock_dirty(iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_man_iblock_attach() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_man_iblock_detach
+ *
+ * Purpose: Detach a block from an indirect block
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 31 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_man_iblock_detach(H5HF_indirect_t *iblock, hid_t dxpl_id, unsigned entry)
+{
+ unsigned start_children; /* # of children of iblock when routine was entered */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_detach)
+#ifdef QAK
+HDfprintf(stderr, "%s: iblock = %p, entry = %u, dblock_addr = %a, iblock_nrows = %u\n", FUNC, iblock, entry, dblock_addr);
+#endif /* QAK */
+
+ /*
+ * Check arguments.
+ */
+ HDassert(iblock);
+ HDassert(iblock->nchildren);
+
+ /* Reset address of entry */
+ iblock->ents[entry].addr = HADDR_UNDEF;
+
+ /* Decrement the # of child blocks */
+ /* (If the number of children drop to 0, the indirect block will be
+ * removed from the heap when it's ref. count drops to zero and the
+ * metadata cache calls the indirect block destructor)
+ */
+ /* (Track the initial # of children before the block gets modified, because
+ * this routine is called recursively)
+ */
+ start_children = iblock->nchildren;
+ iblock->nchildren--;
+
+ /* Reduce the max. entry used, if necessary */
+ if(entry == iblock->max_child) {
+ if(iblock->nchildren > 0)
+ while(!H5F_addr_defined(iblock->ents[iblock->max_child].addr))
+ iblock->max_child--;
+ else
+ iblock->max_child = 0;
+ } /* end if */
+
+ /* If this is the root indirect block handle some special cases */
+ if(iblock->block_off == 0) {
+ /* If the number of children drops to 1, and that child is the first
+ * direct block in the heap, convert the heap back to using a root
+ * direct block
+ */
+ if(iblock->nchildren == 1 && H5F_addr_defined(iblock->ents[0].addr))
+ if(H5HF_man_iblock_root_revert(iblock, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't convert root indirect block back to root direct block")
+
+ /* Check for reducing size of root indirect block */
+ if(iblock->nchildren > 0 && iblock->hdr->man_dtable.cparam.start_root_rows != 0
+ && entry > iblock->max_child) {
+ unsigned max_child_row; /* Row for max. child entry */
+
+ /* Compute information needed for determining whether to reduce size of root indirect block */
+ max_child_row = iblock->max_child / iblock->hdr->man_dtable.cparam.width;
+
+ /* Check if the root indirect block should be reduced */
+ if(iblock->nrows > 1 && max_child_row <= (iblock->nrows / 2))
+ if(H5HF_man_iblock_root_halve(iblock, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce size of root indirect block")
+ } /* end if */
+ } /* end if */
+
+ /* Free indirect block disk space, if it has no children (i.e. it's been deleted) */
+ if(start_children == 1) {
+ HDassert(iblock->nchildren == 0);
+ if(H5MF_xfree(iblock->hdr->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, iblock->addr, (hsize_t)iblock->size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap indirect block disk space")
+ } /* end if */
+
+ /* Mark indirect block as modified */
+ if(H5HF_iblock_dirty(iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty")
+
+ /* Decrement the reference count on this indirect block */
+ /* (should be last, so that potential 'unpin' on this indirect block
+ * doesn't invalidate the 'iblock' variable)
+ */
+ if(H5HF_iblock_decr(iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't decrement reference count on shared indirect block")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_man_iblock_detach() */
+