summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2006-03-31 15:43:14 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2006-03-31 15:43:14 (GMT)
commit244fdb6d8936f9bc2363d3f64ddd8c674f53dfcf (patch)
treeaf716c87891b52d4e9cea4a828d74db057f9d795 /src
parent6864ebdd6aeb44aa86193f7723b872dbf1ed26fa (diff)
downloadhdf5-244fdb6d8936f9bc2363d3f64ddd8c674f53dfcf.zip
hdf5-244fdb6d8936f9bc2363d3f64ddd8c674f53dfcf.tar.gz
hdf5-244fdb6d8936f9bc2363d3f64ddd8c674f53dfcf.tar.bz2
[svn-r12184] Purpose:
Code checkpoint Description: Checkpoint recent additions to fractal heap code, which allow for better support of objects that don't fit into current direct block, requiring skipped direct blocks to be tracked in free section list. Platforms tested: FreeBSD 4.11 (sleipnir) Linux 2.4 (chicago & heping) Linux 2.4 (mir) w/64-bit & FORTRAN & C++ Mac OSX (amazon)
Diffstat (limited to 'src')
-rw-r--r--src/H5HFflist.c30
-rw-r--r--src/H5HFint.c379
2 files changed, 378 insertions, 31 deletions
diff --git a/src/H5HFflist.c b/src/H5HFflist.c
index d879a23..c12bb51 100644
--- a/src/H5HFflist.c
+++ b/src/H5HFflist.c
@@ -70,6 +70,7 @@ struct H5HF_freelist_t {
unsigned nbins; /* Number of bins */
H5SL_operator_t node_free_op; /* Callback for freeing nodes when free list is destroyed */
H5SL_t **bins; /* Pointer to array of lists of free nodes */
+ hbool_t using_bins; /* Flag to indicate that all nodes are in the bins */
};
@@ -144,6 +145,7 @@ H5HF_flist_create(size_t max_block_size, H5SL_operator_t node_free_op)
flist->nbins = H5V_log2_of2(max_block_size);
flist->node_free_op = node_free_op;
flist->bins = NULL;
+ flist->using_bins = FALSE;
/* Set return value */
ret_value = flist;
@@ -263,8 +265,8 @@ HDfprintf(stderr, "%s: *size_key = %Zu, *addr_key = %a\n", FUNC, *size_key, *add
} /* end if */
else {
/* Have a single section, put it into the bins */
-/* XXX: Take out the "&& flist->bins == NULL" when bins converted back into single section */
- if(flist->sec_count == 1 && flist->bins == NULL) {
+/* XXX: Take out the "&& !flist->using_bins" when bins converted back into single section */
+ if(flist->sec_count == 1 && !flist->using_bins) {
HDassert(flist->single.node);
/* Check if we should allocate the bins */
@@ -277,6 +279,9 @@ HDfprintf(stderr, "%s: *size_key = %Zu, *addr_key = %a\n", FUNC, *size_key, *add
if(H5HF_flist_add_bin_node(flist, flist->single.node, flist->single.size_key, flist->single.addr_key) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "can't insert free list node into skip list")
flist->single.node = NULL;
+
+ /* Using bins for storing nodes now */
+ flist->using_bins = TRUE;
} /* end if */
HDassert(flist->single.node == NULL);
@@ -395,6 +400,9 @@ H5HF_flist_find(H5HF_freelist_t *flist, size_t request, void **node)
htri_t ret_value = FALSE; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_flist_find)
+#ifdef QAK
+HDfprintf(stderr, "%s: request = %Zu\n", FUNC, request);
+#endif /* QAK */
/* Check arguments. */
HDassert(flist);
@@ -404,7 +412,8 @@ H5HF_flist_find(H5HF_freelist_t *flist, size_t request, void **node)
/* Check for any sections on free list */
if(flist->sec_count > 0) {
/* Check for single section */
- if(flist->sec_count == 1) {
+/* XXX: Take out the "&& !flist->using_bins" when bins converted back into single section */
+ if(flist->sec_count == 1 && !flist->using_bins) {
HDassert(flist->single.node);
/* See if single section is large enough */
@@ -413,6 +422,8 @@ H5HF_flist_find(H5HF_freelist_t *flist, size_t request, void **node)
flist->single.node = NULL;
ret_value = TRUE;
} /* end if */
+ else
+ HGOTO_DONE(FALSE)
} /* end if */
else {
HDassert(flist->single.node == NULL);
@@ -424,7 +435,15 @@ H5HF_flist_find(H5HF_freelist_t *flist, size_t request, void **node)
/* Decrement # of sections on free list */
flist->sec_count--;
-/* XXX: Should check for only one section in bins & convert to single section */
+/* XXX: Should check for only one section in bins & convert to single section
+ * This is somewhat hard because we "lose" the the size & address keys
+ * (The address key is actually available, but the size key is gone, unless
+ * we start tracking it.
+ *
+ * Drop back to using a "single" node when the bins are empty.
+ */
+ if(flist->sec_count == 0)
+ flist->using_bins = FALSE;
} /* end if */
done:
@@ -490,7 +509,8 @@ H5HF_flist_free(H5HF_freelist_t *flist)
HDassert(flist);
/* Check for single section to free */
- if(flist->sec_count == 1) {
+/* XXX: Take out the "&& !flist->using_bins" when bins converted back into single section */
+ if(flist->sec_count == 1 && !flist->using_bins) {
HDassert(flist->single.node != NULL);
flist->node_free_op(flist->single.node, flist->single.addr_key, NULL);
flist->single.node = NULL;
diff --git a/src/H5HFint.c b/src/H5HFint.c
index b73f908..72eace9 100644
--- a/src/H5HFint.c
+++ b/src/H5HFint.c
@@ -102,7 +102,7 @@ static herr_t H5HF_dblock_section_node_free_cb(void *item, void UNUSED *key,
void UNUSED *op_data);
static herr_t H5HF_man_dblock_create(hid_t dxpl_id, H5HF_t *hdr,
H5HF_indirect_t *par_iblock, unsigned par_entry, size_t block_size,
- hsize_t block_off, haddr_t *addr_p);
+ hsize_t block_off, haddr_t *addr_p, H5HF_section_free_node_t **ret_sec_node);
static herr_t H5HF_man_dblock_new(H5HF_t *fh, hid_t dxpl_id,
size_t request);
static herr_t H5HF_man_dblock_adj_free(hid_t dxpl_id, H5HF_direct_t *dblock, ssize_t amt);
@@ -110,9 +110,12 @@ static herr_t H5HF_man_dblock_adj_free(hid_t dxpl_id, H5HF_direct_t *dblock, ssi
/* Indirect block routines */
static herr_t H5HF_man_iblock_inc_loc(H5HF_indirect_t *iblock);
static herr_t H5HF_iblock_dirty(hid_t dxpl_id, H5HF_indirect_t *iblock);
+static herr_t H5HF_man_iblock_adj_free(hid_t dxpl_id, H5HF_indirect_t *iblock, ssize_t amt);
static H5HF_indirect_t * H5HF_man_iblock_place_dblock(H5HF_t *fh, hid_t dxpl_id,
size_t min_dblock_size, haddr_t *addr_p, size_t *entry_p,
size_t *dblock_size);
+static herr_t H5HF_man_iblock_alloc_range(H5HF_t *hdr, hid_t dxpl_id,
+ H5HF_section_free_node_t **sec_node, size_t obj_size);
static herr_t H5HF_man_iblock_create(H5HF_t *fh, hid_t dxpl_id,
hsize_t block_off, unsigned nrows, unsigned max_rows, haddr_t *addr_p);
@@ -519,8 +522,8 @@ done:
*/
static herr_t
H5HF_man_dblock_create(hid_t dxpl_id, H5HF_t *hdr, H5HF_indirect_t *par_iblock,
- unsigned par_entry,
- size_t block_size, hsize_t block_off, haddr_t *addr_p)
+ unsigned par_entry, size_t block_size, hsize_t block_off, haddr_t *addr_p,
+ H5HF_section_free_node_t **ret_sec_node)
{
H5HF_direct_free_node_t *node; /* Pointer to free list node for block */
H5HF_section_free_node_t *sec_node; /* Pointer to free list section for block */
@@ -617,12 +620,18 @@ HDmemset(dblock->blk, 0, dblock->size);
sec_node->u.single.dblock_addr = *addr_p;
sec_node->u.single.dblock_size = block_size;
- /* Add new free space to the global list of space */
- if(H5HF_flist_add(hdr->flist, sec_node, &sec_node->sect_size, &sec_node->sect_addr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add direct block free space to global list")
+ /* Check what to do with section node */
+ if(ret_sec_node)
+ /* Pass back the pointer to the section instead of adding it to the free list */
+ *ret_sec_node = sec_node;
+ else {
+ /* Add new free space to the global list of space */
+ if(H5HF_flist_add(hdr->flist, sec_node, &sec_node->sect_size, &sec_node->sect_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add direct block free space to global list")
+ } /* end else */
/* Adjust free space to include new block's space */
- if(H5HF_man_dblock_adj_free(dxpl_id, dblock, (ssize_t)free_space) < 0)
+ if(H5HF_man_dblock_adj_free(dxpl_id, dblock, (ssize_t)sec_node->sect_size) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't adjust free space for direct block & parents")
/* Update shared heap header */
@@ -843,7 +852,7 @@ H5HF_man_dblock_adj_free(hid_t dxpl_id, H5HF_direct_t *dblock, ssize_t amt)
FUNC_ENTER_NOAPI_NOINIT(H5HF_man_dblock_adj_free)
#ifdef QAK
-HDfprintf(stderr, "%s: amt = %Zd\n", "H5HF_man_dblock_adj_free", amt);
+HDfprintf(stderr, "%s: amt = %Zd\n", FUNC, amt);
#endif /* QAK */
/*
@@ -855,6 +864,7 @@ HDfprintf(stderr, "%s: amt = %Zd\n", "H5HF_man_dblock_adj_free", amt);
hdr = dblock->shared;
/* Adjust space available in block */
+ HDassert(amt > 0 || dblock->blk_free_space >= (size_t)-amt);
dblock->blk_free_space += amt;
/* Check if the parent info is set */
@@ -866,9 +876,11 @@ HDfprintf(stderr, "%s: amt = %Zd\n", "H5HF_man_dblock_adj_free", amt);
/* Adjust this indirect block's child free space */
#ifdef QAK
-HDfprintf(stderr, "%s: iblock->child_free_space = %Hu\n", "H5HF_man_dblock_adj_free", iblock->child_free_space);
+HDfprintf(stderr, "%s: iblock->child_free_space = %Hu\n", FUNC, iblock->child_free_space);
#endif /* QAK */
+ HDassert(amt > 0 || iblock->ents[dblock->par_entry].free_space >= (hsize_t)-amt);
iblock->ents[dblock->par_entry].free_space += amt;
+ HDassert(amt > 0 || iblock->child_free_space >= (hsize_t)-amt);
iblock->child_free_space += amt;
/* Mark indirect block as dirty */
@@ -885,7 +897,9 @@ HDfprintf(stderr, "%s: iblock->child_free_space = %Hu\n", "H5HF_man_dblock_adj_f
HDassert(iblock);
/* Adjust this indirect block's child free space */
+ HDassert(amt > 0 || iblock->ents[par_entry].free_space >= (hsize_t)-amt);
iblock->ents[par_entry].free_space += amt;
+ HDassert(amt > 0 || iblock->child_free_space >= (hsize_t)-amt);
iblock->child_free_space += amt;
/* Mark indirect block as dirty */
@@ -895,7 +909,11 @@ HDfprintf(stderr, "%s: iblock->child_free_space = %Hu\n", "H5HF_man_dblock_adj_f
} /* end if */
/* Update shared heap free space header */
+ HDassert(amt > 0 || hdr->total_man_free >= (hsize_t)-amt);
hdr->total_man_free += amt;
+#ifdef QAK
+HDfprintf(stderr, "%s: hdr->total_man_free = %Hu\n", FUNC, hdr->total_man_free);
+#endif /* QAK */
/* Mark heap header as modified */
if(H5HF_hdr_dirty(dxpl_id, hdr) < 0)
@@ -965,7 +983,7 @@ HDfprintf(stderr, "%s: Check 2 - min_dblock_size = %Zu\n", FUNC, min_dblock_size
min_dblock_size == hdr->man_dtable.cparam.start_block_size) {
/* Create new direct block at starting offset */
dblock_size = hdr->man_dtable.cparam.start_block_size;
- if(H5HF_man_dblock_create(dxpl_id, hdr, NULL, 0, dblock_size, (hsize_t)0, &dblock_addr) < 0)
+ if(H5HF_man_dblock_create(dxpl_id, hdr, NULL, 0, dblock_size, (hsize_t)0, &dblock_addr, NULL) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap direct block")
#ifdef QAK
@@ -998,7 +1016,7 @@ HDfprintf(stderr, "%s: dblock_size = %Zu\n", FUNC, dblock_size);
dblock_off += hdr->man_dtable.row_block_size[dblock_entry / hdr->man_dtable.cparam.width] * (dblock_entry % hdr->man_dtable.cparam.width);
/* Create new direct block at current location*/
- if(H5HF_man_dblock_create(dxpl_id, hdr, iblock, dblock_entry, dblock_size, dblock_off, &dblock_addr) < 0)
+ if(H5HF_man_dblock_create(dxpl_id, hdr, iblock, dblock_entry, dblock_size, dblock_off, &dblock_addr, NULL) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap direct block")
#ifdef QAK
@@ -1118,11 +1136,27 @@ H5HF_man_insert(H5HF_t *hdr, hid_t dxpl_id, H5HF_section_free_node_t *sec_node,
/* Check for range section */
if(sec_node->type == H5HF_SECT_RANGE) {
-HDfprintf(stderr, "%s: Can't handle range sections yet\n", FUNC);
-HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "'range' free space sections not supported yet")
+#ifdef QAK
+HDfprintf(stderr, "%s: sec_node->sect_addr = %a\n", FUNC, sec_node->sect_addr);
+HDfprintf(stderr, "%s: sec_node->sect_size = %Zu\n", FUNC, sec_node->sect_size);
+HDfprintf(stderr, "%s: sec_node->u.range.iblock_addr = %a\n", FUNC, sec_node->u.range.iblock_addr);
+HDfprintf(stderr, "%s: sec_node->u.range.iblock_nrows = %u\n", FUNC, sec_node->u.range.iblock_nrows);
+HDfprintf(stderr, "%s: sec_node->u.range.entry = %u\n", FUNC, sec_node->u.range.entry);
+HDfprintf(stderr, "%s: sec_node->u.range.num_entries = %u\n", FUNC, sec_node->u.range.num_entries);
+HDfprintf(stderr, "%s: sec_node->u.range.range = %Hu\n", FUNC, sec_node->u.range.range);
+#endif /* QAK */
+ /* Allocate 'single' selection out of range selection */
+ if(H5HF_man_iblock_alloc_range(hdr, dxpl_id, &sec_node, obj_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't break up range free section")
} /* end if */
/* Lock direct block */
+#ifdef QAK
+HDfprintf(stderr, "%s: sec_node->sect_addr = %a\n", FUNC, sec_node->sect_addr);
+HDfprintf(stderr, "%s: sec_node->sect_size = %Zu\n", FUNC, sec_node->sect_size);
+HDfprintf(stderr, "%s: sec_node->u.single.dblock_addr = %a\n", FUNC, sec_node->u.single.dblock_addr);
+HDfprintf(stderr, "%s: sec_node->u.single.dblock_size = %Zu\n", FUNC, sec_node->u.single.dblock_size);
+#endif /* QAK */
dblock_addr = sec_node->u.single.dblock_addr;
if(NULL == (dblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, &sec_node->u.single.dblock_size, hdr, H5AC_WRITE)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load fractal heap direct block")
@@ -1136,6 +1170,8 @@ HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "'range' free space sections not su
size_t obj_off; /* Offset of object within block */
size_t full_obj_size; /* Size of object including metadata */
size_t alloc_obj_size; /* Size of object including metadata & any free space fragment */
+ size_t free_obj_size; /* Size of space to free for object */
+ hbool_t whole_node = FALSE; /* Whether we've used the whole node or not */
unsigned char free_frag_size; /* Size of free space fragment */
/* Locate "local" free list node for section */
@@ -1149,12 +1185,15 @@ HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "'range' free space sections not su
full_obj_size = obj_size + H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr);
/* Sanity checks */
- HDassert(dblock->blk_free_space >= full_obj_size);
+ HDassert(dblock->blk_free_space >= obj_size);
HDassert(dblock->free_list);
HDassert(node->size >= full_obj_size);
/* Check for using entire node */
free_frag_size = 0;
+#ifdef QAK
+HDfprintf(stderr, "%s: node->size = %Zu\n", FUNC, node->size);
+#endif /* QAK */
if(node->size <= (full_obj_size + H5HF_MAN_ABS_DIRECT_FREE_NODE_SIZE(dblock))) {
/* Set the offset of the object within the block */
obj_off = node->my_offset;
@@ -1184,6 +1223,7 @@ HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "'range' free space sections not su
/* Set the free fragment size */
free_frag_size = (unsigned char )(node->size - full_obj_size);
+ whole_node = TRUE;
/* Release the memory for the free list node & section */
H5FL_FREE(H5HF_direct_free_node_t, node);
@@ -1210,6 +1250,10 @@ HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "'range' free space sections not su
/* (includes the metadata for the object & the free space fragment) */
alloc_obj_size = full_obj_size + free_frag_size;
+ /* Compute the size of the free space to reduce */
+ /* (does not include the object prefix if this object uses a whole node) */
+ free_obj_size = obj_size + (whole_node ? free_frag_size : H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr));
+
#ifdef QAK
HDfprintf(stderr, "%s: obj_off = %Zu\n", FUNC, obj_off);
HDfprintf(stderr, "%s: free_frag_size = %Zu\n", FUNC, free_frag_size);
@@ -1217,7 +1261,7 @@ HDfprintf(stderr, "%s: full_obj_size = %Zu\n", FUNC, full_obj_size);
HDfprintf(stderr, "%s: alloc_obj_size = %Zu\n", FUNC, alloc_obj_size);
#endif /* QAK */
/* Reduce space available in parent block(s) */
- if(H5HF_man_dblock_adj_free(dxpl_id, dblock, -(ssize_t)alloc_obj_size) < 0)
+ if(H5HF_man_dblock_adj_free(dxpl_id, dblock, -(ssize_t)free_obj_size) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't adjust free space for direct block & parents")
/* Encode the object in the block */
@@ -1657,6 +1701,81 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5HF_man_iblock_adj_free
+ *
+ * Purpose: Adjust the free space for an indirect block, and it's parents
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Mar 28 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_man_iblock_adj_free(hid_t dxpl_id, H5HF_indirect_t *iblock, ssize_t amt)
+{
+ H5HF_t *hdr; /* Shared heap information */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_adj_free)
+#ifdef QAK
+HDfprintf(stderr, "%s: amt = %Zd\n", FUNC, amt);
+#endif /* QAK */
+
+ /*
+ * Check arguments.
+ */
+ HDassert(iblock);
+
+ /* Get the pointer to the shared heap header */
+ hdr = iblock->shared;
+
+ /* Adjust space available in block */
+ HDassert(amt > 0 || iblock->child_free_space >= (hsize_t)-amt);
+ iblock->child_free_space += amt;
+
+ /* Check if the parent info is set */
+ while(iblock->parent) {
+ size_t par_entry; /* Entry in parent */
+
+ /* Get the pointer to the shared parent indirect block */
+ par_entry = iblock->par_entry;
+ iblock = iblock->parent;
+ HDassert(iblock);
+
+ /* Adjust this indirect block's child free space */
+#ifdef QAK
+HDfprintf(stderr, "%s: iblock->child_free_space = %Hu\n", FUNC, iblock->child_free_space);
+#endif /* QAK */
+ HDassert(amt > 0 || iblock->ents[par_entry].free_space >= (hsize_t)-amt);
+ iblock->ents[par_entry].free_space += amt;
+ HDassert(amt > 0 || iblock->child_free_space >= (hsize_t)-amt);
+ iblock->child_free_space += amt;
+
+ /* Mark indirect block as dirty */
+ if(H5HF_iblock_dirty(dxpl_id, iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty")
+ } /* end if */
+
+ /* Update shared heap free space header */
+ HDassert(amt > 0 || hdr->total_man_free >= (hsize_t)-amt);
+ hdr->total_man_free += amt;
+#ifdef QAK
+HDfprintf(stderr, "%s: hdr->total_man_free = %Hu\n", FUNC, hdr->total_man_free);
+#endif /* QAK */
+
+ /* Mark heap header as modified */
+ if(H5HF_hdr_dirty(dxpl_id, hdr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_man_iblock_adj_free() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5HF_man_iblock_place_dblock
*
* Purpose: Find indirect block with location for placing a direct block
@@ -1776,8 +1895,8 @@ HDfprintf(stderr, "%s: iblock_addr = %a\n", FUNC, iblock_addr);
iblock->ents[cur_entry].free_space = dblock_free_space;
/* Increment block and heap's free space */
- iblock->child_free_space += dblock_free_space;
- hdr->total_man_free += dblock_free_space;
+ if(H5HF_man_iblock_adj_free(dxpl_id, iblock, (ssize_t)dblock_free_space) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, NULL, "can't adjust free space for indirect block & parents")
/* Increment range skipped */
range += hdr->man_dtable.row_block_size[u];
@@ -2030,6 +2149,223 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5HF_man_iblock_alloc_range
+ *
+ * Purpose: Allocate a "single" section for an object, out of a "range"
+ * section
+ *
+ * Note: Creates necessary direct & indirect blocks
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Mar 28 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_man_iblock_alloc_range(H5HF_t *hdr, hid_t dxpl_id,
+ H5HF_section_free_node_t **sec_node, size_t obj_size)
+{
+ H5HF_indirect_t *iblock; /* Pointer to indirect block */
+ haddr_t iblock_addr; /* Indirect block's address */
+ haddr_t dblock_addr; /* Direct block's address */
+ unsigned iblock_nrows; /* Indirect block's number of rows */
+ H5HF_section_free_node_t *dblock_sec_node = NULL; /* Pointer to direct block's section node */
+ H5HF_section_free_node_t *old_sec_node = *sec_node; /* Pointer to old section node */
+ size_t full_obj_size; /* Size of object including metadata */
+ unsigned cur_entry; /* Current entry in indirect block */
+ unsigned cur_row; /* Current row in indirect block */
+ size_t row_size; /* Size of objects in current row */
+ hsize_t range_covered; /* Range covered while searching for block to use */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_alloc_range)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+ HDassert(sec_node && *sec_node);
+ HDassert(obj_size > 0);
+
+ /* Compute info about range */
+ cur_entry = old_sec_node->u.range.entry;
+
+ /* Check for range covering indirect blocks */
+ if((cur_entry / hdr->man_dtable.cparam.width) >= hdr->man_dtable.max_direct_rows ||
+ ((cur_entry + old_sec_node->u.range.num_entries) / hdr->man_dtable.cparam.width)
+ >= 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 information about indirect block covering section */
+ /* (Allow for root indirect block being resized) */
+ iblock_addr = old_sec_node->u.range.iblock_addr;
+ if(H5F_addr_eq(iblock_addr, hdr->man_dtable.table_addr))
+ iblock_nrows = hdr->man_dtable.curr_root_rows;
+ else
+ iblock_nrows = old_sec_node->u.range.iblock_nrows;
+
+ /* Get a pointer to the indirect block covering the range */
+ if(NULL == (iblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, &iblock_nrows, hdr, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
+
+ /* Compute size of object, with metadata overhead */
+ full_obj_size = obj_size + H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr);
+
+ /* Look for first direct block that will fulfill request */
+ range_covered = 0;
+ for(u = 0; u < old_sec_node->u.range.num_entries; ) {
+ unsigned skip_blocks; /* # of blocks to skip over to next row */
+
+ /* Compute informatio about current row */
+ cur_row = cur_entry / hdr->man_dtable.cparam.width;
+ row_size = hdr->man_dtable.row_block_size[cur_row];
+
+ /* Check if first available block in this row will hold block */
+ if((H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE(hdr, row_size) + full_obj_size) <= row_size)
+ break;
+
+ /* Compute number of blocks to skip in row */
+ skip_blocks = ((cur_row + 1) * hdr->man_dtable.cparam.width) - cur_entry;
+
+ /* Advance values to beginning of next row */
+ range_covered += row_size * skip_blocks;
+ u += skip_blocks;
+ cur_entry += skip_blocks;
+ } /* end for */
+#ifdef QAK
+HDfprintf(stderr, "%s: cur_entry = %u, cur_row = %u, row_size = %Zu\n", FUNC, cur_entry, cur_row, row_size);
+HDfprintf(stderr, "%s: range_covered = %Hu, u = %u\n", FUNC, range_covered, u);
+HDfprintf(stderr, "%s: old_sec_node->u.range.num_entries = %u\n", FUNC, old_sec_node->u.range.num_entries);
+#endif /* QAK */
+ /* Must find direct block of useful size */
+ HDassert(u < old_sec_node->u.range.num_entries);
+
+ /* Create direct block of appropriate size */
+ if(H5HF_man_dblock_create(dxpl_id, hdr, iblock, cur_entry, row_size, (hsize_t)(old_sec_node->sect_addr + range_covered), &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;
+ iblock->ents[cur_entry].free_space = dblock_sec_node->sect_size;
+
+ /* Adjust free space in block & heap */
+ if(H5HF_man_iblock_adj_free(dxpl_id, iblock, -(ssize_t)dblock_sec_node->sect_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't adjust free space for indirect block & parents")
+
+ /* Break range section up into zero, one or two range sections and add them
+ * back to the free sections for the file
+ */
+
+ /* Check for only single block covered in range section */
+ if(old_sec_node->u.range.num_entries == 1)
+ H5FL_FREE(H5HF_section_free_node_t, old_sec_node);
+ else {
+ size_t next_block_size; /* Next entry after block used */
+
+ /* Check for using first block in range section */
+ if(u == 0) {
+#ifdef QAK
+HDfprintf(stderr, "%s: range type 1\n", FUNC);
+#endif /* QAK */
+ /* Adjust section information */
+ old_sec_node->sect_addr += row_size;
+ /* Section size stays the same, since we just grabbed the smallest block in the range */
+
+ /* Adjust range information */
+ old_sec_node->u.range.entry++;
+ old_sec_node->u.range.num_entries--;
+ old_sec_node->u.range.range -= row_size;
+
+ /* Add section back to free space list */
+ if(H5HF_flist_add(hdr->flist, old_sec_node, &old_sec_node->sect_size, &old_sec_node->sect_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add indirect block free space to global list")
+ } /* end if */
+ /* Check for using middle block from range section */
+ else if(u < (old_sec_node->u.range.num_entries -1)) {
+ H5HF_section_free_node_t *new_sec_node; /* Pointer to new free list section for block */
+#ifdef QAK
+HDfprintf(stderr, "%s: range type 2\n", FUNC);
+#endif /* QAK */
+
+ /* Create new section node for space after block used */
+ if(NULL == (new_sec_node = H5FL_MALLOC(H5HF_section_free_node_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for indirect block free list section")
+
+ /* Set section information for new node */
+ new_sec_node->sect_addr = old_sec_node->sect_addr + range_covered + row_size;
+ new_sec_node->sect_size = old_sec_node->sect_size;
+
+ /* Set range information */
+ new_sec_node->type = H5HF_SECT_RANGE;
+ new_sec_node->u.range.iblock_addr = old_sec_node->u.range.iblock_addr;
+ new_sec_node->u.range.iblock_nrows = old_sec_node->u.range.iblock_nrows;
+ new_sec_node->u.range.entry = cur_entry + 1;
+ new_sec_node->u.range.num_entries = old_sec_node->u.range.num_entries - (u + 1);
+ new_sec_node->u.range.range = old_sec_node->u.range.range - (range_covered + row_size);
+
+ /* Add new section to free space list */
+ if(H5HF_flist_add(hdr->flist, new_sec_node, &new_sec_node->sect_size, &new_sec_node->sect_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add indirect block free space to global list")
+
+
+ /* Compute size of block before the one used */
+ next_block_size = hdr->man_dtable.row_block_size[(cur_entry - 1) /
+ hdr->man_dtable.cparam.width];
+
+ /* Adjust current section information */
+ old_sec_node->sect_size = next_block_size -
+ (H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE(hdr, row_size) + H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr));
+
+ /* Adjust range information */
+ old_sec_node->u.range.num_entries = u;
+ old_sec_node->u.range.range = range_covered;
+
+ /* Add section back to free space list */
+ if(H5HF_flist_add(hdr->flist, old_sec_node, &old_sec_node->sect_size, &old_sec_node->sect_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add indirect block free space to global list")
+ } /* end if */
+ /* Must be using last block in range section */
+ else {
+#ifdef QAK
+HDfprintf(stderr, "%s: range type 3\n", FUNC);
+#endif /* QAK */
+ /* Compute size of next block after the one used */
+ next_block_size = hdr->man_dtable.row_block_size[(cur_entry - 1) /
+ hdr->man_dtable.cparam.width];
+
+ /* Adjust section information */
+ old_sec_node->sect_size = next_block_size -
+ (H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE(hdr, row_size) + H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr));
+
+ /* Adjust range information */
+ old_sec_node->u.range.num_entries--;
+ old_sec_node->u.range.range -= row_size;
+
+ /* Add section back to free space list */
+ if(H5HF_flist_add(hdr->flist, old_sec_node, &old_sec_node->sect_size, &old_sec_node->sect_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add indirect block free space to global list")
+ } /* end else */
+ } /* end if */
+
+ /* Release the indirect block (marked as dirty) */
+ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, iblock, H5AC__DIRTIED_FLAG) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
+
+ /* Point 'sec_node' at new direct block section node */
+ *sec_node = dblock_sec_node;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_man_iblock_alloc_range() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5HF_man_iblock_create
*
* Purpose: Allocate & initialize a managed indirect block
@@ -2112,15 +2448,6 @@ HDfprintf(stderr, "%s: nrows = %u, max_nrows = %u\n", FUNC, nrows, max_nrows);
iblock->addr = *addr_p;
/* XXX: Update indirect statistics when they are added */
-#ifdef LATER
- /* Update shared heap info */
- hdr->total_man_free += dblock->blk_free_space;
- hdr->total_size += dblock->size;
- hdr->man_size += dblock->size;
-
- /* Mark heap header as modified */
- hdr->dirty = TRUE;
-#endif /* LATER */
/* Cache the new fractal heap header */
if(H5AC_set(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, *addr_p, iblock, H5AC__NO_FLAGS_SET) < 0)