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