summaryrefslogtreecommitdiffstats
path: root/src/H5HFiblock.c
diff options
context:
space:
mode:
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() */
+