summaryrefslogtreecommitdiffstats
path: root/src/H5HFsection.c
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2006-06-19 10:06:10 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2006-06-19 10:06:10 (GMT)
commit9db9e82cd1c4e35c6e64fbb2da5eb1db95a0fb55 (patch)
treedf8aaa72b1094bcfacc740a8d33b255c84e1d34e /src/H5HFsection.c
parent54e2de04d3b7a0359c80cc995f94b63123f4a4da (diff)
downloadhdf5-9db9e82cd1c4e35c6e64fbb2da5eb1db95a0fb55.zip
hdf5-9db9e82cd1c4e35c6e64fbb2da5eb1db95a0fb55.tar.gz
hdf5-9db9e82cd1c4e35c6e64fbb2da5eb1db95a0fb55.tar.bz2
[svn-r12424] Purpose:
Code checkpoint Description: Add in more new features for the fractal heap code, mostly bringing in more ability for deleting objects (which isn't completely working yet). Also, checkpoint free space manager code, which is essentially complete (although it needs some more work after the metadata cache has some additional features) Platforms tested: FreeBSD 4.11 (sleipnir) Linux 2.4 (chicago) h5committest
Diffstat (limited to 'src/H5HFsection.c')
-rw-r--r--src/H5HFsection.c1126
1 files changed, 948 insertions, 178 deletions
diff --git a/src/H5HFsection.c b/src/H5HFsection.c
index f164cdb..48e2ddb 100644
--- a/src/H5HFsection.c
+++ b/src/H5HFsection.c
@@ -52,30 +52,41 @@
/********************/
/* Shared routines */
-static herr_t H5HF_sect_node_alloc(H5FS_section_class_t *sect_cls,
- unsigned sect_type, haddr_t sect_addr, hsize_t sect_size,
- H5FS_section_info_t **sect);
+static H5HF_free_section_t *H5HF_sect_node_new(unsigned sect_type,
+ haddr_t sect_addr, hsize_t sect_size, H5FS_section_state_t state);
static herr_t H5HF_sect_node_free(H5HF_free_section_t *sect,
H5HF_indirect_t *parent);
+static herr_t H5HF_sect_revive(H5HF_hdr_t *hdr, hid_t dxpl_id,
+ H5HF_free_section_t *sect);
/* 'single' section callbacks */
-static herr_t H5HF_sect_single_deserialize(H5FS_section_class_t *sect_cls,
- const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size,
- H5FS_section_info_t **sect);
-static htri_t H5HF_sect_single_can_merge(const H5FS_section_info_t *sect1,
- const H5FS_section_info_t *sect2, void *udata);
+static H5FS_section_info_t *H5HF_sect_single_deserialize(const uint8_t *buf,
+ haddr_t sect_addr, hsize_t sect_size);
+static htri_t H5HF_sect_single_can_merge(H5FS_section_info_t *sect1,
+ H5FS_section_info_t *sect2, void *udata);
static herr_t H5HF_sect_single_merge(H5FS_section_info_t *sect1,
H5FS_section_info_t *sect2, void *udata);
-static htri_t H5HF_sect_single_can_shrink(H5FS_section_info_t *sect, void *udata);
-static herr_t H5HF_sect_single_shrink(H5FS_section_info_t **sect, void *udata);
+static htri_t H5HF_sect_single_can_shrink(H5FS_section_info_t *sect,
+ void *udata);
static herr_t H5HF_sect_single_free(H5FS_section_info_t *sect);
+/* 'range' section routines */
+static herr_t H5HF_sect_range_from_single(H5HF_hdr_t *hdr,
+ H5HF_free_section_t *sect, H5HF_direct_t *dblock);
+
/* 'range' section callbacks */
static herr_t H5HF_sect_range_init_cls(H5FS_section_class_t *cls, const void *udata);
static herr_t H5HF_sect_range_serialize(const H5FS_section_info_t *sect, uint8_t *buf);
-static herr_t H5HF_sect_range_deserialize(H5FS_section_class_t *sect_cls,
- const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size,
- H5FS_section_info_t **sect);
+static H5FS_section_info_t *H5HF_sect_range_deserialize(const uint8_t *buf,
+ haddr_t sect_addr, hsize_t sect_size);
+static htri_t H5HF_sect_range_can_merge(H5FS_section_info_t *sect1,
+ H5FS_section_info_t *sect2, void *udata);
+static herr_t H5HF_sect_range_merge(H5FS_section_info_t *sect1,
+ H5FS_section_info_t *sect2, void *udata);
+static htri_t H5HF_sect_range_can_shrink(H5FS_section_info_t *sect,
+ void *udata);
+static herr_t H5HF_sect_range_shrink(H5FS_section_info_t **sect,
+ void *udata);
static herr_t H5HF_sect_range_free(H5FS_section_info_t *sect);
static herr_t H5HF_sect_range_debug(const H5FS_section_info_t *sect,
FILE *stream, int indent, int fwidth);
@@ -83,9 +94,8 @@ static herr_t H5HF_sect_range_debug(const H5FS_section_info_t *sect,
/* 'indirect' section callbacks */
static herr_t H5HF_sect_indirect_init_cls(H5FS_section_class_t *cls, const void *udata);
static herr_t H5HF_sect_indirect_serialize(const H5FS_section_info_t *sect, uint8_t *buf);
-static herr_t H5HF_sect_indirect_deserialize(H5FS_section_class_t *sect_cls,
- const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size,
- H5FS_section_info_t **sect);
+static H5FS_section_info_t *H5HF_sect_indirect_deserialize(const uint8_t *buf,
+ haddr_t sect_addr, hsize_t sect_size);
static herr_t H5HF_sect_indirect_free(H5FS_section_info_t *sect);
static herr_t H5HF_sect_indirect_debug(const H5FS_section_info_t *sect,
FILE *stream, int indent, int fwidth);
@@ -97,8 +107,8 @@ static herr_t H5HF_sect_indirect_debug(const H5FS_section_info_t *sect,
/* Class info for "single" free space sections */
/* (No callbacks necessary) */
-H5FS_section_class_t H5FS_SECT_CLS_FHEAP_SINGLE[1] = {{
- H5FS_SECT_FHEAP_SINGLE, /* Section type */
+H5FS_section_class_t H5HF_FSPACE_SECT_CLS_SINGLE[1] = {{
+ H5HF_FSPACE_SECT_SINGLE, /* Section type */
0, /* Extra serialized size */
NULL, /* Initialize section class */
NULL, /* Serialize section */
@@ -106,29 +116,29 @@ H5FS_section_class_t H5FS_SECT_CLS_FHEAP_SINGLE[1] = {{
H5HF_sect_single_can_merge, /* Can sections merge? */
H5HF_sect_single_merge, /* Merge sections */
H5HF_sect_single_can_shrink, /* Can section shrink container?*/
- H5HF_sect_single_shrink, /* Shrink container w/section */
+ NULL, /* Shrink container w/section */
H5HF_sect_single_free, /* Free section */
NULL, /* Dump debugging for section */
}};
/* Class info for "range" free space sections */
-H5FS_section_class_t H5FS_SECT_CLS_FHEAP_RANGE[1] = {{
- H5FS_SECT_FHEAP_RANGE, /* Section type */
+H5FS_section_class_t H5HF_FSPACE_SECT_CLS_RANGE[1] = {{
+ H5HF_FSPACE_SECT_RANGE, /* Section type */
0, /* Extra serialized size */
H5HF_sect_range_init_cls, /* Initialize section class */
H5HF_sect_range_serialize, /* Serialize section */
H5HF_sect_range_deserialize, /* Deserialize section */
- NULL, /* Can sections merge? */
- NULL, /* Merge sections */
- NULL, /* Can section shrink container?*/
- NULL, /* Shrink container w/section */
+ H5HF_sect_range_can_merge, /* Can sections merge? */
+ H5HF_sect_range_merge, /* Merge sections */
+ H5HF_sect_range_can_shrink, /* Can section shrink container?*/
+ H5HF_sect_range_shrink, /* Shrink container w/section */
H5HF_sect_range_free, /* Free section */
H5HF_sect_range_debug, /* Dump debugging for section */
}};
/* Class info for "indirect" free space sections */
-H5FS_section_class_t H5FS_SECT_CLS_FHEAP_INDIRECT[1] = {{
- H5FS_SECT_FHEAP_INDIRECT, /* Section type */
+H5FS_section_class_t H5HF_FSPACE_SECT_CLS_INDIRECT[1] = {{
+ H5HF_FSPACE_SECT_INDIRECT, /* Section type */
0, /* Extra serialized size */
H5HF_sect_indirect_init_cls, /* Initialize section class */
H5HF_sect_indirect_serialize, /* Serialize section */
@@ -157,7 +167,7 @@ H5FL_DEFINE(H5HF_free_section_t);
/*-------------------------------------------------------------------------
- * Function: H5HF_sect_node_alloc
+ * Function: H5HF_sect_node_new
*
* Purpose: Allocate a free space section node of a particular type
*
@@ -170,38 +180,37 @@ H5FL_DEFINE(H5HF_free_section_t);
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5HF_sect_node_alloc(H5FS_section_class_t *sect_cls, unsigned sect_type,
- haddr_t sect_addr, hsize_t sect_size, H5FS_section_info_t **sect)
+static H5HF_free_section_t *
+H5HF_sect_node_new(unsigned sect_type, haddr_t sect_addr, hsize_t sect_size,
+ H5FS_section_state_t sect_state)
{
H5HF_free_section_t *new_sect; /* New section */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5HF_free_section_t *ret_value; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_node_alloc)
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_node_new)
/* Check arguments. */
HDassert(H5F_addr_defined(sect_addr));
HDassert(sect_size);
- HDassert(sect);
/* Create free list section node */
if(NULL == (new_sect = H5FL_MALLOC(H5HF_free_section_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section")
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for direct block free list section")
/* Set the information passed in */
new_sect->sect_info.addr = sect_addr;
new_sect->sect_info.size = sect_size;
/* Set the section's class & state */
- new_sect->sect_info.cls = &sect_cls[sect_type];
- new_sect->sect_info.state = H5FS_SECT_SERIALIZED;
+ new_sect->sect_info.type = sect_type;
+ new_sect->sect_info.state = sect_state;
- /* Update the return parameter */
- *sect = (H5FS_section_info_t *)new_sect;
+ /* Set return value */
+ ret_value = new_sect;
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5HF_sect_node_alloc() */
+} /* H5HF_sect_node_new() */
/*-------------------------------------------------------------------------
@@ -241,6 +250,121 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_revive
+ *
+ * Purpose: Revive a section node
+ *
+ * Return: Success: non-negative
+ *
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Monday, June 5, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_sect_revive(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_revive)
+
+ /* Sanity check */
+ HDassert(hdr);
+ HDassert(sect);
+
+ /* Call appropriate 'revive' routine */
+ switch(sect->sect_info.type) {
+ case H5HF_FSPACE_SECT_INDIRECT:
+ if(H5HF_sect_indirect_revive(hdr, dxpl_id, sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive range free section")
+ break;
+
+ case H5HF_FSPACE_SECT_RANGE:
+ if(H5HF_sect_range_revive(hdr, dxpl_id, sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive range free section")
+ break;
+
+ case H5HF_FSPACE_SECT_SINGLE:
+ if(H5HF_sect_single_revive(hdr, dxpl_id, sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive single free section")
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "unknown section type")
+ } /* end switch */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5HF_sect_revive() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_single_new
+ *
+ * Purpose: Create a new 'single' section and return it to the caller
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 30 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+H5HF_free_section_t *
+H5HF_sect_single_new(hsize_t sect_off, size_t sect_size,
+ H5HF_indirect_t *parent, unsigned par_entry,
+ haddr_t dblock_addr, size_t dblock_size)
+{
+ H5HF_free_section_t *sect = NULL; /* 'Single' free space section to add */
+ hbool_t par_incr = FALSE; /* Indicate that parent iblock has been incremented */
+ H5HF_free_section_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_single_new)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(sect_size);
+
+ /* Create free space section node */
+ if(NULL == (sect = H5HF_sect_node_new(H5HF_FSPACE_SECT_SINGLE, sect_off, (hsize_t)sect_size, H5FS_SECT_LIVE)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for single section")
+
+ /* Set the 'single' specific fields */
+ sect->u.single.parent = parent;
+ if(sect->u.single.parent) {
+ if(H5HF_iblock_incr(sect->u.single.parent) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared indirect block")
+ par_incr = TRUE;
+ } /* end if */
+ sect->u.single.par_entry = par_entry;
+ sect->u.single.dblock_addr = dblock_addr;
+ sect->u.single.dblock_size = dblock_size;
+
+ /* Set return value */
+ ret_value = sect;
+
+done:
+ if(!ret_value && sect) {
+ /* Check if we should decrement parent ref. count */
+ if(par_incr) {
+ HDassert(sect->u.single.parent);
+ if(H5HF_iblock_decr(sect->u.single.parent) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTDEC, NULL, "can't decrement reference count on parent indirect block")
+ } /* end if */
+
+ /* Release the section */
+ H5FL_FREE(H5HF_free_section_t, sect);
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_sect_single_new() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5HF_sect_single_revive
*
* Purpose: Update the memory information for a 'single' free section
@@ -313,6 +437,58 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_single_reduce
+ *
+ * Purpose: Reduce the size of a single section (possibly freeing it)
+ * and re-add it back to the free space manager for the heap
+ * (if it hasn't been freed)
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 31 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_sect_single_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id,
+ H5HF_free_section_t *sect, size_t amt)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_single_reduce)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+ HDassert(sect);
+ HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_SINGLE);
+ HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
+
+ /* Check for eliminating the section */
+ if(sect->sect_info.size == amt) {
+ /* Free single section */
+ if(H5HF_sect_single_free((H5FS_section_info_t *)sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free single section node")
+ } /* end if */
+ else {
+ /* Adjust information for section */
+ sect->sect_info.addr += amt;
+ sect->sect_info.size -= amt;
+
+ /* Re-insert section node into heap's free space */
+ if(H5HF_space_add(hdr, dxpl_id, sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't re-add single section to free space manager")
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_sect_single_reduce() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5HF_sect_single_deserialize
*
* Purpose: Deserialize a buffer into a "live" single section
@@ -326,12 +502,12 @@ done:
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5HF_sect_single_deserialize(H5FS_section_class_t *sect_cls,
- const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size,
- H5FS_section_info_t **sect)
+static H5FS_section_info_t *
+H5HF_sect_single_deserialize(const uint8_t *buf, haddr_t sect_addr,
+ hsize_t sect_size)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5HF_free_section_t *new_sect; /* New section */
+ H5FS_section_info_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_single_deserialize)
@@ -339,11 +515,13 @@ H5HF_sect_single_deserialize(H5FS_section_class_t *sect_cls,
HDassert(buf);
HDassert(H5F_addr_defined(sect_addr));
HDassert(sect_size);
- HDassert(sect);
/* Create free list section node */
- if(H5HF_sect_node_alloc(sect_cls, H5FS_SECT_FHEAP_SINGLE, sect_addr, sect_size, sect) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "allocation failed for direct block free list section")
+ if(NULL == (new_sect = H5HF_sect_node_new(H5HF_FSPACE_SECT_SINGLE, sect_addr, sect_size, H5FS_SECT_SERIALIZED)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "allocation failed for direct block free list section")
+
+ /* Set return value */
+ ret_value = (H5FS_section_info_t *)new_sect;
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -367,32 +545,87 @@ done:
*-------------------------------------------------------------------------
*/
static htri_t
-H5HF_sect_single_can_merge(const H5FS_section_info_t *sect1,
- const H5FS_section_info_t *sect2, void UNUSED *udata)
+H5HF_sect_single_can_merge(H5FS_section_info_t *_sect1,
+ H5FS_section_info_t *_sect2, void *_udata)
{
+ H5HF_free_section_t *sect1 = (H5HF_free_section_t *)_sect1; /* Fractal heap free section */
+ H5HF_free_section_t *sect2 = (H5HF_free_section_t *)_sect2; /* Fractal heap free section */
+ H5HF_add_ud1_t *udata = (H5HF_add_ud1_t *)_udata; /* User callback data */
+ H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */
+ size_t dblock_size; /* Section's direct block's size */
+ size_t dblock_overhead; /* Direct block's overhead */
+ hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */
htri_t ret_value = FALSE; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_single_can_merge)
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_single_can_merge)
/* Check arguments. */
HDassert(sect1);
HDassert(sect2);
- HDassert(H5F_addr_lt(sect1->addr, sect2->addr));
+ HDassert(H5F_addr_lt(sect1->sect_info.addr, sect2->sect_info.addr));
+
+#ifdef QAK
+HDfprintf(stderr, "%s: sect1->sect_info = {%a, %Hu, %u, %s}\n", FUNC, sect1->sect_info.addr, sect1->sect_info.size, sect1->sect_info.type, (sect1->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED"));
+HDfprintf(stderr, "%s: sect2->sect_info = {%a, %Hu, %u, %s}\n", FUNC, sect2->sect_info.addr, sect2->sect_info.size, sect2->sect_info.type, (sect2->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED"));
+#endif /* QAK */
+
+ /* Check to see if we should revive either section */
+ if(sect1->sect_info.state != H5FS_SECT_LIVE)
+ if(H5HF_sect_single_revive(hdr, dxpl_id, sect1) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive single free section")
+ if(sect2->sect_info.state != H5FS_SECT_LIVE)
+ if(H5HF_sect_revive(hdr, dxpl_id, sect2) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive free section")
+ /* Check for section occupying entire direct block */
+ dblock_size = sect1->u.single.dblock_size;
+ dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr);
#ifdef QAK
-HDfprintf(stderr, "%s: sect1->size = %Hu, sect1->addr = %a\n", "H5HF_sect_single_can_merge", sect1->size, sect1->addr);
-HDfprintf(stderr, "%s: sect2->size = %Hu, sect2->addr = %a\n", "H5HF_sect_single_can_merge", sect2->size, sect2->addr);
+HDfprintf(stderr, "%s: dblock_size = %u\n", FUNC, dblock_size);
#endif /* QAK */
+ if((dblock_size - dblock_overhead) == sect1->sect_info.size) {
+ H5HF_direct_t *dblock; /* Pointer to direct block for section */
+ haddr_t dblock_addr; /* Section's direct block's address */
+
+ /* Protect the direct block for the section */
+ dblock_addr = sect1->u.single.dblock_addr;
+#ifdef QAK
+HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr);
+#endif /* QAK */
+ if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, sect1->u.single.parent, sect1->u.single.par_entry, H5AC_READ)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load fractal heap direct block")
+ HDassert(H5F_addr_eq(dblock->block_off + dblock_overhead, sect1->sect_info.addr));
+
+ /* Convert 'single' section into 'range' section */
+ if(H5HF_sect_range_from_single(hdr, sect1, dblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTCONVERT, FAIL, "can't convert single section into range section")
+
+ /* Destroy direct block */
+ if(H5HF_man_dblock_destroy(hdr, dxpl_id, dblock, dblock_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release direct block")
+ dblock = NULL;
+
+ /* Check if second section is a range section */
+ if(sect2->sect_info.type == H5HF_FSPACE_SECT_RANGE) {
+ htri_t status; /* Status from range 'can merge' call */
+
+ /* Check if two sections can merge now */
+ /* (i.e. assumes responsibility for passing along 'can merge' callback) */
+ if((status = H5HF_sect_range_can_merge((H5FS_section_info_t *)sect1, (H5FS_section_info_t *)sect2, udata)) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTMERGE, FAIL, "can't check for merging sections")
+ HGOTO_DONE(status)
+ } /* end if */
+ } /* end if */
/* Single section can only merge with other single sections */
- if(sect1->cls->type != sect2->cls->type)
+ if(sect1->sect_info.type != sect2->sect_info.type)
HGOTO_DONE(FALSE)
/* Check if second section adjoins first section */
/* (This can only occurs within a direct block, due to the direct block
* overhead at the beginning of a block)
*/
- if(H5F_addr_eq(sect1->addr + sect1->size, sect2->addr))
+ if(H5F_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr))
HGOTO_DONE(TRUE)
done:
@@ -417,30 +650,40 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5HF_sect_single_merge(H5FS_section_info_t *sect1, H5FS_section_info_t *sect2,
+H5HF_sect_single_merge(H5FS_section_info_t *_sect1, H5FS_section_info_t *_sect2,
void UNUSED *udata)
{
+ H5HF_free_section_t *sect1 = (H5HF_free_section_t *)_sect1; /* Fractal heap free section */
+ H5HF_free_section_t *sect2 = (H5HF_free_section_t *)_sect2; /* Fractal heap free section */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_single_merge)
/* Check arguments. */
HDassert(sect1);
+ HDassert(sect1->sect_info.state == H5FS_SECT_LIVE);
HDassert(sect2);
- HDassert(H5F_addr_eq(sect1->addr + sect1->size, sect2->addr));
+ HDassert(sect2->sect_info.state == H5FS_SECT_LIVE);
+ HDassert(H5F_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr));
#ifdef QAK
-HDfprintf(stderr, "%s: sect1->size = %Hu, sect1->addr = %a\n", "H5HF_sect_single_merge", sect1->size, sect1->addr);
-HDfprintf(stderr, "%s: sect2->size = %Hu, sect2->addr = %a\n", "H5HF_sect_single_merge", sect2->size, sect2->addr);
+HDfprintf(stderr, "%s: sect1->sect_info.size = %Hu, sect1->sect_info.addr = %a\n", FUNC, sect1->sect_info.size, sect1->sect_info.addr);
+HDfprintf(stderr, "%s: sect2->sect_info.size = %Hu, sect2->sect_info.addr = %a\n", FUNC, sect2->sect_info.size, sect2->sect_info.addr);
#endif /* QAK */
/* Add second section's size to first section */
- sect1->size += sect2->size;
+ sect1->sect_info.size += sect2->sect_info.size;
/* Get rid of second section */
- if(H5HF_sect_single_free(sect2) < 0)
+ if(H5HF_sect_single_free((H5FS_section_info_t *)sect2) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node")
+ /* Defer checking if 'single' section should be converted into 'range' section
+ * until next pass through the "can merge" callback, to make certain that
+ * removing a direct block in the root indirect block gives neighboring
+ * "range" sections a chance to deserialize. *ick* -QAK
+ */
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5HF_sect_single_merge() */
@@ -449,14 +692,18 @@ done:
/*-------------------------------------------------------------------------
* Function: H5HF_sect_single_can_shrink
*
- * Purpose: Can this section shrink the heap?
+ * Purpose: Can this section shrink the container?
+ *
+ * Note: This isn't actually shrinking the heap (since that's already
+ * been done) as much as it's cleaning up _after_ the heap
+ * shrink.
*
* Return: Success: non-negative (TRUE/FALSE)
*
* Failure: negative
*
* Programmer: Quincey Koziol
- * Wednesday, May 17, 2006
+ * Monday, June 5, 2006
*
*-------------------------------------------------------------------------
*/
@@ -465,117 +712,66 @@ H5HF_sect_single_can_shrink(H5FS_section_info_t *_sect, void *_udata)
{
H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Fractal heap free section */
H5HF_add_ud1_t *udata = (H5HF_add_ud1_t *)_udata; /* User callback data */
- H5HF_hdr_t *hdr; /* Fractal heap header */
- H5HF_direct_t *dblock = NULL; /* Pointer to direct block for section */
- haddr_t dblock_addr; /* Section's direct block's address */
+ H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */
size_t dblock_size; /* Section's direct block's size */
size_t dblock_overhead; /* Direct block's overhead */
- hid_t dxpl_id; /* DXPL ID for operation */
+ hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */
htri_t ret_value = FALSE; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_single_can_shrink)
/* Check arguments. */
HDassert(sect);
- HDassert(udata);
- HDassert(udata->hdr);
+ HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
#ifdef QAK
-HDfprintf(stderr, "%s: sect->sect_info.size = %Hu, sect->sect_info.addr = %a\n", FUNC, sect->sect_info.size, sect->sect_info.addr);
+HDfprintf(stderr, "%s: sect->sect_info = {%a, %Hu, %u, %s}\n", FUNC, sect->sect_info.addr, sect->sect_info.size, sect->sect_info.type, (sect->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED"));
#endif /* QAK */
- /* Initialize some local convenience variables */
- hdr = udata->hdr;
- dxpl_id = udata->dxpl_id;
-
- /* Revive the section, if it's still serialized */
- if(sect->sect_info.state != H5FS_SECT_LIVE) {
+ /* Check to see if we should revive section */
+ if(sect->sect_info.state != H5FS_SECT_LIVE)
if(H5HF_sect_single_revive(hdr, dxpl_id, sect) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive single free section")
- } /* end if */
- /* Protect the direct block for the section */
- dblock_addr = sect->u.single.dblock_addr;
+ /* Check for section occupying entire direct block */
dblock_size = sect->u.single.dblock_size;
+ dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr);
#ifdef QAK
-HDfprintf(stderr, "%s: dblock_size = %u, dblock_addr = %a\n", FUNC, dblock_size, dblock_addr);
+HDfprintf(stderr, "%s: dblock_size = %u\n", FUNC, dblock_size);
#endif /* QAK */
- if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, sect->u.single.parent, sect->u.single.par_entry, H5AC_READ)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load fractal heap direct block")
-
- /* Check for section occupying entire direct block */
- dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr);
- if(H5F_addr_eq(dblock->block_off + dblock_overhead, sect->sect_info.addr) &&
- (dblock_size - dblock_overhead) == sect->sect_info.size) {
- /* Stash the direct block pointer away for the 'shrink' callback */
- udata->dblock = dblock;
-
- /* Indicate that the heap can be shrunk */
- HGOTO_DONE(TRUE)
- } /* end if */
-
-done:
- /* Unprotect the direct block, if we aren't going to use it in the 'shrink' callback */
- if(ret_value != TRUE)
- if(dblock && H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__NO_FLAGS_SET) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5HF_sect_single_can_shrink() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5HF_sect_single_shrink
- *
- * Purpose: Shrink heap w/section
- *
- * Return: Success: non-negative
- *
- * Failure: negative
- *
- * Programmer: Quincey Koziol
- * Wednesday, May 17, 2006
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HF_sect_single_shrink(H5FS_section_info_t **_sect, void *_udata)
-{
- H5HF_free_section_t **sect = (H5HF_free_section_t **)_sect; /* Fractal heap free section */
- H5HF_add_ud1_t *udata = (H5HF_add_ud1_t *)_udata; /* User callback data */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_single_shrink)
-
- /* Check arguments. */
- HDassert(sect);
- HDassert(*sect);
- HDassert((*sect)->sect_info.state == H5FS_SECT_LIVE);
- HDassert(udata);
- HDassert(udata->hdr);
- HDassert(udata->dblock);
+ if((dblock_size - dblock_overhead) == sect->sect_info.size) {
+ H5HF_direct_t *dblock; /* Pointer to direct block for section */
+ haddr_t dblock_addr; /* Section's direct block's address */
+ htri_t status; /* Status from range 'can shrink' call */
+ /* Protect the direct block for the section */
+ dblock_addr = sect->u.single.dblock_addr;
#ifdef QAK
-HDfprintf(stderr, "%s: (*sect)->sect_info.size = %Hu, (*sect)->sect_info.addr = %a\n", "H5HF_sect_single_shrink", (*sect)->sect_info.size, (*sect)->sect_info.addr);
+HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr);
#endif /* QAK */
-
- /* Destroy direct block */
- if(H5HF_man_dblock_destroy(udata->hdr, udata->dxpl_id, udata->dblock, (*sect)->u.single.dblock_addr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release direct block")
-
- /* Mark section as "dead", since it's direct block is destroyed */
- (*sect)->sect_info.state = H5FS_SECT_SERIALIZED;
-
- /* Release section */
- if(H5HF_sect_single_free((H5FS_section_info_t *)*sect) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node")
-
- /* Set section pointer to NULL, to indicate that the section was released */
- *sect = NULL;
+ if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, sect->u.single.parent, sect->u.single.par_entry, H5AC_READ)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load fractal heap direct block")
+ HDassert(H5F_addr_eq(dblock->block_off + dblock_overhead, sect->sect_info.addr));
+
+ /* Convert 'single' section into 'range' section */
+ if(H5HF_sect_range_from_single(hdr, sect, dblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTCONVERT, FAIL, "can't convert single section into range section")
+
+ /* Destroy direct block */
+ if(H5HF_man_dblock_destroy(hdr, dxpl_id, dblock, dblock_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release direct block")
+ dblock = NULL;
+
+ /* Check if section can shrink container now */
+ /* (i.e. assumes responsibility for passing along 'can shrink' callback) */
+ if((status = H5HF_sect_range_can_shrink((H5FS_section_info_t *)sect, udata)) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't check for shrinking container")
+ HGOTO_DONE(status)
+ } /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5HF_sect_single_shrink() */
+} /* H5HF_sect_single_can_shrink() */
/*-------------------------------------------------------------------------
@@ -592,7 +788,7 @@ done:
*
*-------------------------------------------------------------------------
*/
-herr_t
+static herr_t
H5HF_sect_single_free(H5FS_section_info_t *_sect)
{
H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Pointer to section to free */
@@ -651,6 +847,72 @@ H5HF_sect_range_init_cls(H5FS_section_class_t *cls, const void UNUSED *udata)
/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_range_add
+ *
+ * Purpose: Add a new 'range' section to the free space manager for this
+ * heap
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 30 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_sect_range_add(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t sect_off,
+ hsize_t sect_size, H5HF_indirect_t *iblock,
+ unsigned row, unsigned col, unsigned nentries)
+{
+ H5HF_free_section_t *sect = NULL; /* 'Range' free space section to add */
+ hbool_t iblock_incr = FALSE; /* Indicate that parent iblock has been incremented */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_range_add)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+ HDassert(iblock);
+ HDassert(sect_size);
+ HDassert(nentries);
+ HDassert(row < hdr->man_dtable.max_direct_rows); /* Can't handle ranges on indirect blocks */
+
+ /* Create free space section node */
+ if(NULL == (sect = H5HF_sect_node_new(H5HF_FSPACE_SECT_RANGE, sect_off, sect_size, H5FS_SECT_LIVE)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for range section")
+
+ /* Set the 'range' specific fields */
+ sect->u.range.iblock = iblock;
+ if(H5HF_iblock_incr(sect->u.range.iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block")
+ iblock_incr = TRUE;
+ sect->u.range.row = row;
+ sect->u.range.col = col;
+ sect->u.range.num_entries = nentries;
+
+ /* Add new free space to the free space manager for this heap */
+ if(H5HF_space_add(hdr, dxpl_id, sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add range section to free space manager")
+
+done:
+ if(ret_value < 0 && sect) {
+ /* Check if we should decrement parent ref. count */
+ if(iblock_incr)
+ if(H5HF_iblock_decr(sect->u.range.iblock) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block")
+
+ /* Release the section */
+ H5FL_FREE(H5HF_free_section_t, sect);
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_sect_range_add() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5HF_sect_range_revive
*
* Purpose: Update the memory information for a 'range' free section
@@ -705,6 +967,104 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_range_reduce
+ *
+ * Purpose: Reduce the size of a range section (possibly freeing it)
+ * and re-add it back to the free space manager for the heap
+ * (if it hasn't been freed)
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 31 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_sect_range_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id,
+ H5HF_free_section_t *sect)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_range_reduce)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+ HDassert(sect);
+ HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_RANGE);
+ HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
+
+ /* Check for eliminating the section */
+ if(sect->u.range.num_entries == 1) {
+ /* Free range section */
+ if(H5HF_sect_range_free((H5FS_section_info_t *)sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free range section node")
+ } /* end if */
+ else {
+ /* Adjust section information */
+ sect->sect_info.addr += hdr->man_dtable.row_block_size[sect->u.range.row];
+
+ /* Adjust range information */
+ sect->u.range.col++;
+ sect->u.range.num_entries--;
+
+ /* Add section back to free space list */
+ if(H5HF_space_add(hdr, dxpl_id, sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't re-add range section to free space manager")
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_sect_range_reduce() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_range_from_single
+ *
+ * Purpose: Convert a 'single' section into a 'range' section
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 31 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_sect_range_from_single(H5HF_hdr_t *hdr, H5HF_free_section_t *sect,
+ H5HF_direct_t *dblock)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_range_from_single)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+ HDassert(sect);
+ HDassert(dblock);
+#ifdef QAK
+HDfprintf(stderr, "%s: sect.sect_info = {%a, %Hu, %u, %s}\n", "H5HF_sect_range_from_single", sect->sect_info.addr, sect->sect_info.size, sect->sect_info.type, (sect->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED"));
+HDfprintf(stderr, "%s: dblock->parent = %p\n", "H5HF_sect_range_from_single", dblock->parent);
+HDfprintf(stderr, "%s: hdr->man_dtable.curr_root_rows = %u\n", "H5HF_sect_range_from_single", hdr->man_dtable.curr_root_rows);
+#endif /* QAK */
+
+ /* Update information for range block */
+ sect->sect_info.addr = dblock->block_off;
+ sect->sect_info.type = H5HF_FSPACE_SECT_RANGE;
+ sect->u.range.iblock = dblock->parent;
+ sect->u.range.row = dblock->par_entry / hdr->man_dtable.cparam.width;
+ sect->u.range.col = dblock->par_entry % hdr->man_dtable.cparam.width;
+ sect->u.range.num_entries = 1;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5HF_sect_range_from_single() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5HF_sect_range_serialize
*
* Purpose: Serialize a "live" range section into a buffer
@@ -756,12 +1116,12 @@ H5HF_sect_range_serialize(const H5FS_section_info_t *_sect, uint8_t *buf)
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5HF_sect_range_deserialize(H5FS_section_class_t *sect_cls,
- const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size,
- H5FS_section_info_t **sect)
+static H5FS_section_info_t *
+H5HF_sect_range_deserialize(const uint8_t *buf, haddr_t sect_addr,
+ hsize_t sect_size)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5HF_free_section_t *new_sect; /* New section */
+ H5FS_section_info_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_range_deserialize)
@@ -769,20 +1129,22 @@ H5HF_sect_range_deserialize(H5FS_section_class_t *sect_cls,
HDassert(buf);
HDassert(H5F_addr_defined(sect_addr));
HDassert(sect_size);
- HDassert(sect);
/* Create free list section node */
- if(H5HF_sect_node_alloc(sect_cls, H5FS_SECT_FHEAP_RANGE, sect_addr, sect_size, sect) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "allocation failed for direct block free list section")
+ if(NULL == (new_sect = H5HF_sect_node_new(H5HF_FSPACE_SECT_RANGE, sect_addr, sect_size, H5FS_SECT_SERIALIZED)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "allocation failed for direct block free list section")
/* Range's row */
- UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.range.row);
+ UINT16DECODE(buf, new_sect->u.range.row);
/* Range's column */
- UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.range.col);
+ UINT16DECODE(buf, new_sect->u.range.col);
/* Range's # of entries */
- UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.range.num_entries);
+ UINT16DECODE(buf, new_sect->u.range.num_entries);
+
+ /* Set return value */
+ ret_value = (H5FS_section_info_t *)new_sect;
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -790,6 +1152,289 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_range_can_merge
+ *
+ * Purpose: Can two sections of this type merge?
+ *
+ * Note: Second section must be "after" first section
+ *
+ * Return: Success: non-negative (TRUE/FALSE)
+ *
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Monday, June 5, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static htri_t
+H5HF_sect_range_can_merge(H5FS_section_info_t *_sect1,
+ H5FS_section_info_t *_sect2, void *_udata)
+{
+ H5HF_free_section_t *sect1 = (H5HF_free_section_t *)_sect1; /* Fractal heap free section */
+ H5HF_free_section_t *sect2 = (H5HF_free_section_t *)_sect2; /* Fractal heap free section */
+ H5HF_add_ud1_t *udata = (H5HF_add_ud1_t *)_udata; /* User callback data */
+ H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */
+ hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */
+ hsize_t sect2_off; /* Offset of second section in heap */
+ size_t dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr); /* Direct block's overhead */
+ htri_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_range_can_merge)
+
+ /* Check arguments. */
+ HDassert(sect1);
+ HDassert(sect2);
+ HDassert(H5F_addr_lt(sect1->sect_info.addr, sect2->sect_info.addr));
+
+#ifdef QAK
+HDfprintf(stderr, "%s: sect1->sect_info = {%a, %Hu, %u, %s}\n", FUNC, sect1->sect_info.addr, sect1->sect_info.size, sect1->sect_info.type, (sect1->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED"));
+HDfprintf(stderr, "%s: sect2->sect_info = {%a, %Hu, %u, %s}\n", FUNC, sect2->sect_info.addr, sect2->sect_info.size, sect2->sect_info.type, (sect2->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED"));
+#endif /* QAK */
+ /* Check to see if we should revive either section */
+ if(sect1->sect_info.state != H5FS_SECT_LIVE)
+ if(H5HF_sect_range_revive(hdr, dxpl_id, sect1) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive single free section")
+ if(sect2->sect_info.state != H5FS_SECT_LIVE)
+ if(H5HF_sect_revive(hdr, dxpl_id, sect2) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive free section")
+
+ /* Check for special case of delayed conversion of 2nd section from
+ * single -> range section
+ */
+ if(sect2->sect_info.type == H5HF_FSPACE_SECT_SINGLE) {
+ size_t dblock_size; /* Section's direct block's size */
+
+ /* Check for section occupying entire direct block */
+ dblock_size = sect2->u.single.dblock_size;
+ if((dblock_size - dblock_overhead) == sect2->sect_info.size) {
+ H5HF_direct_t *dblock; /* Pointer to direct block for section */
+ haddr_t dblock_addr; /* Section's direct block's address */
+
+ /* Protect the direct block for the section */
+ dblock_addr = sect2->u.single.dblock_addr;
+#ifdef QAK
+HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr);
+#endif /* QAK */
+ if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, sect2->u.single.parent, sect2->u.single.par_entry, H5AC_READ)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load fractal heap direct block")
+ HDassert(H5F_addr_eq(dblock->block_off + dblock_overhead, sect2->sect_info.addr));
+
+ /* Convert 'single' section into 'range' section */
+ if(H5HF_sect_range_from_single(hdr, sect2, dblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTCONVERT, FAIL, "can't convert single section into range section")
+
+ /* Destroy direct block */
+ if(H5HF_man_dblock_destroy(hdr, dxpl_id, dblock, dblock_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release direct block")
+ dblock = NULL;
+#ifdef QAK
+HDfprintf(stderr, "%s: hdr->man_iter_off = %Hu\n", FUNC, hdr->man_iter_off);
+#endif /* QAK */
+ } /* end if */
+ } /* end if */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: sect1.u.range = {%p, %u, %u, %u}\n", FUNC, sect1->u.range.iblock, sect1->u.range.row, sect1->u.range.col, sect1->u.range.num_entries);
+#endif /* QAK */
+
+ /* Range section can only merge with other range sections */
+ if(sect1->sect_info.type != sect2->sect_info.type)
+ HGOTO_DONE(FALSE)
+
+#ifdef QAK
+HDfprintf(stderr, "%s: sect2.u.range = {%p, %u, %u, %u}\n", FUNC, sect2->u.range.iblock, sect2->u.range.row, sect2->u.range.col, sect2->u.range.num_entries);
+HDfprintf(stderr, "%s: sect2.u.range.iblock->nchildren = %u\n", FUNC, sect2->u.range.iblock->nchildren);
+#endif /* QAK */
+
+ /* Check if second section is in indirect block that's being deleted */
+ if(sect2->u.range.iblock->nchildren == 0)
+ HGOTO_DONE(TRUE)
+
+ /* Check if second section is past end of "next block" iterator */
+ sect2_off = sect2->u.range.iblock->block_off;
+ sect2_off += hdr->man_dtable.row_block_off[sect2->u.range.row];
+ sect2_off += hdr->man_dtable.row_block_size[sect2->u.range.row] * sect2->u.range.col;
+#ifdef QAK
+HDfprintf(stderr, "%s: hdr->man_iter_off = %Hu\n", FUNC, hdr->man_iter_off);
+HDfprintf(stderr, "%s: sect2.u.range.iblock->block_off = %Hu\n", FUNC, sect2->u.range.iblock->block_off);
+HDfprintf(stderr, "%s: hdr->man_dtable.row_block_off[%u] = %Hu\n", FUNC, sect2->u.range.row, hdr->man_dtable.row_block_off[sect2->u.range.row]);
+HDfprintf(stderr, "%s: sect2_off = %Hu\n", FUNC, sect2_off);
+#endif /* QAK */
+ if(sect2_off > hdr->man_iter_off)
+ HGOTO_DONE(TRUE)
+
+ /* Check if second section adjoins first section & is in the same row */
+ if(H5F_addr_eq(sect1->sect_info.addr + (sect1->u.range.num_entries * (sect1->sect_info.size + dblock_overhead)), sect2->sect_info.addr) &&
+ sect1->u.range.row == sect2->u.range.row)
+ HGOTO_DONE(TRUE)
+
+done:
+#ifdef QAK
+HDfprintf(stderr, "%s: ret_value = %t\n", FUNC, ret_value);
+#endif /* QAK */
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5HF_sect_range_can_merge() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_range_merge
+ *
+ * Purpose: Merge two sections of this type
+ *
+ * Note: Second section always merges into first node
+ *
+ * Return: Success: non-negative
+ *
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Monday, June 5, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_sect_range_merge(H5FS_section_info_t *_sect1, H5FS_section_info_t *_sect2,
+ void *_udata)
+{
+ H5HF_free_section_t *sect1 = (H5HF_free_section_t *)_sect1; /* Fractal heap free section */
+ H5HF_free_section_t *sect2 = (H5HF_free_section_t *)_sect2; /* Fractal heap free section */
+ H5HF_add_ud1_t *udata = (H5HF_add_ud1_t *)_udata; /* User callback data */
+ H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_range_merge)
+
+ /* Check arguments. */
+ HDassert(sect1);
+ HDassert(sect1->sect_info.state == H5FS_SECT_LIVE);
+ HDassert(sect1->sect_info.type == H5HF_FSPACE_SECT_RANGE);
+ HDassert(sect2);
+ HDassert(sect2->sect_info.state == H5FS_SECT_LIVE);
+ HDassert(sect2->sect_info.type == H5HF_FSPACE_SECT_RANGE);
+
+#ifdef QAK
+HDfprintf(stderr, "%s: sect1.sect_info = {%a, %Hu, %u, %s}\n", FUNC, sect1->sect_info.addr, sect1->sect_info.size, sect1->sect_info.type, (sect1->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED"));
+HDfprintf(stderr, "%s: sect1.u.range = {%p, %u, %u, %u}\n", FUNC, sect1->u.range.iblock, sect1->u.range.row, sect1->u.range.col, sect1->u.range.num_entries);
+HDfprintf(stderr, "%s: sect2.sect_info = {%a, %Hu, %u, %s}\n", FUNC, sect2->sect_info.addr, sect2->sect_info.size, sect2->sect_info.type, (sect2->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED"));
+HDfprintf(stderr, "%s: sect2.u.range = {%p, %u, %u, %u}\n", FUNC, sect2->u.range.iblock, sect2->u.range.row, sect2->u.range.col, sect2->u.range.num_entries);
+#endif /* QAK */
+
+ /* Add second section's size to first section, if it's in the same row */
+ if(sect1->u.range.row == sect2->u.range.row)
+ sect1->u.range.num_entries += sect2->u.range.num_entries;
+
+ /* Get rid of second section */
+ if(H5HF_sect_range_free((H5FS_section_info_t *)sect2) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node")
+
+ /* Check if 'range' section should be converted into 'indirect' section (?) */
+ if(sect1->u.range.num_entries == hdr->man_dtable.cparam.width &&
+ sect1->u.range.row >= hdr->man_dtable.max_direct_rows) {
+HDfprintf(stderr, "%s: converting range section to indirect section not supported yet!\n", FUNC);
+HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "converting range section to indirect section not supported yet")
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5HF_sect_range_merge() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_range_can_shrink
+ *
+ * Purpose: Can this section shrink the container?
+ *
+ * Note: This isn't actually shrinking the heap (since that's already
+ * been done) as much as it's cleaning up _after_ the heap
+ * shrink.
+ *
+ * Return: Success: non-negative (TRUE/FALSE)
+ *
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Monday, June 5, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static htri_t
+H5HF_sect_range_can_shrink(H5FS_section_info_t *_sect, void UNUSED *_udata)
+{
+ const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Fractal heap free section */
+ htri_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_range_can_shrink)
+
+ /* Check arguments. */
+ HDassert(sect);
+ HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
+
+#ifdef QAK
+HDfprintf(stderr, "%s: sect->sect_info = {%a, %Hu, %u, %s}\n", "H5HF_sect_range_can_shrink", sect->sect_info.addr, sect->sect_info.size, sect->sect_info.type, (sect->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED"));
+HDfprintf(stderr, "%s: sect->u.range = {%p, %u, %u, %u}\n", "H5HF_sect_range_can_shrink", sect->u.range.iblock, sect->u.range.row, sect->u.range.col, sect->u.range.num_entries);
+if(sect->u.range.iblock != NULL)
+ HDfprintf(stderr, "%s: sect->u.range.iblock->nchildren = %u\n", "H5HF_sect_range_can_shrink", sect->u.range.iblock->nchildren);
+#endif /* QAK */
+
+ /* If section has no parent, it should go away */
+ if(sect->u.range.iblock == NULL)
+ HGOTO_DONE(TRUE)
+
+ /* If section is in an indirect block with no children, it should go away */
+ if(sect->u.range.iblock->nchildren == 0)
+ HGOTO_DONE(TRUE)
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5HF_sect_range_can_shrink() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_range_shrink
+ *
+ * Purpose: Shrink container with section
+ *
+ * Return: Success: non-negative
+ *
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Monday, June 5, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_sect_range_shrink(H5FS_section_info_t **_sect, void UNUSED *_udata)
+{
+ H5HF_free_section_t **sect = (H5HF_free_section_t **)_sect; /* Fractal heap free section */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_range_shrink)
+
+ /* Check arguments. */
+ HDassert(sect);
+ HDassert(*sect);
+ HDassert((*sect)->sect_info.state == H5FS_SECT_LIVE);
+
+#ifdef QAK
+HDfprintf(stderr, "%s: (*sect).sect_info = {%a, %Hu, %u}\n", FUNC, (*sect)->sect_info.addr, (*sect)->sect_info.size, (*sect)->sect_info.type);
+HDfprintf(stderr, "%s: (*sect).u.range = {%p, %u, %u, %u}\n", FUNC, (*sect)->u.range.iblock, (*sect)->u.range.row, (*sect)->u.range.col, (*sect)->u.range.num_entries);
+#endif /* QAK */
+
+ /* Get rid of section */
+ if(H5HF_sect_range_free((H5FS_section_info_t *)*sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node")
+
+ /* Indicate that the section has been released */
+ *sect = NULL;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5HF_sect_range_shrink() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5HF_sect_range_free
*
* Purpose: Free a 'range' section node
@@ -803,7 +1448,7 @@ done:
*
*-------------------------------------------------------------------------
*/
-herr_t
+static herr_t
H5HF_sect_range_free(H5FS_section_info_t *_sect)
{
H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Pointer to section to free */
@@ -904,6 +1549,74 @@ H5HF_sect_indirect_init_cls(H5FS_section_class_t *cls, const void UNUSED *udata)
/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_indirect_add
+ *
+ * Purpose: Add a new 'indirect' section to the free space manager for this
+ * heap
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 30 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_sect_indirect_add(H5HF_hdr_t *hdr, hid_t dxpl_id,
+ hsize_t sect_off, hsize_t sect_size, H5HF_indirect_t *iblock,
+ unsigned row, unsigned col, unsigned nentries,
+ unsigned indir_row, unsigned indir_nrows)
+{
+ H5HF_free_section_t *sect = NULL; /* 'Indirect' free space section to add */
+ hbool_t iblock_incr = FALSE; /* Indicate that parent iblock has been incremented */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_add)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+ HDassert(iblock);
+ HDassert(sect_size);
+ HDassert(nentries);
+
+ /* Create free space section node */
+ if(NULL == (sect = H5HF_sect_node_new(H5HF_FSPACE_SECT_INDIRECT, sect_off, sect_size, H5FS_SECT_LIVE)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for indirect section")
+
+ /* Set the 'indirect' specific fields */
+ sect->u.indirect.iblock = iblock;
+ if(H5HF_iblock_incr(sect->u.indirect.iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block")
+ iblock_incr = TRUE;
+ sect->u.indirect.row = row;
+ sect->u.indirect.col = col;
+ sect->u.indirect.num_entries = nentries;
+ sect->u.indirect.indir_row = indir_row;
+ sect->u.indirect.indir_nrows = indir_nrows;
+
+ /* Add new free space to the free space manager for the heap */
+ if(H5HF_space_add(hdr, dxpl_id, sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add indirect section to free space")
+
+done:
+ if(ret_value < 0 && sect) {
+ /* Check if we should decrement parent ref. count */
+ if(iblock_incr)
+ if(H5HF_iblock_decr(sect->u.indirect.iblock) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block")
+
+ /* Release the section */
+ H5FL_FREE(H5HF_free_section_t, sect);
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_sect_indirect_add() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5HF_sect_indirect_revive
*
* Purpose: Update the memory information for a 'indirect' free section
@@ -958,6 +1671,61 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_indirect_reduce
+ *
+ * Purpose: Reduce the size of a indirect section (possibly freeing it)
+ * and re-add it back to the free space manager for the heap
+ * (if it hasn't been freed)
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 31 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_sect_indirect_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id,
+ H5HF_free_section_t *sect)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_reduce)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+ HDassert(sect);
+ HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_INDIRECT);
+ HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
+
+ /* Check for eliminating the section */
+ if(sect->u.indirect.num_entries == 1) {
+ /* Free indirect section */
+ if(H5HF_sect_indirect_free((H5FS_section_info_t *)sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node")
+ } /* end if */
+ else {
+ /* Adjust section information */
+ sect->sect_info.addr += hdr->man_dtable.row_block_size[sect->u.indirect.row];
+
+ /* Adjust range information */
+ sect->u.indirect.col++;
+ sect->u.indirect.num_entries--;
+
+ /* Add 'indirect' section back to free space list */
+ if(H5HF_space_add(hdr, dxpl_id, sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't re-add indirect section to free space manager")
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_sect_indirect_reduce() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5HF_sect_indirect_serialize
*
* Purpose: Serialize a "live" indirect section into a buffer
@@ -1015,12 +1783,12 @@ H5HF_sect_indirect_serialize(const H5FS_section_info_t *_sect, uint8_t *buf)
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5HF_sect_indirect_deserialize(H5FS_section_class_t *sect_cls,
- const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size,
- H5FS_section_info_t **sect)
+static H5FS_section_info_t *
+H5HF_sect_indirect_deserialize(const uint8_t *buf, haddr_t sect_addr,
+ hsize_t sect_size)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5HF_free_section_t *new_sect; /* New section */
+ H5FS_section_info_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_deserialize)
@@ -1028,26 +1796,28 @@ H5HF_sect_indirect_deserialize(H5FS_section_class_t *sect_cls,
HDassert(buf);
HDassert(H5F_addr_defined(sect_addr));
HDassert(sect_size);
- HDassert(sect);
/* Create free list section node */
- if(H5HF_sect_node_alloc(sect_cls, H5FS_SECT_FHEAP_INDIRECT, sect_addr, sect_size, sect) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "allocation failed for direct block free list section")
+ if(NULL == (new_sect = H5HF_sect_node_new(H5HF_FSPACE_SECT_INDIRECT, sect_addr, sect_size, H5FS_SECT_SERIALIZED)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "allocation failed for direct block free list section")
/* Range's row */
- UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.indirect.row);
+ UINT16DECODE(buf, new_sect->u.indirect.row);
/* Range's column */
- UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.indirect.col);
+ UINT16DECODE(buf, new_sect->u.indirect.col);
/* Range's # of entries */
- UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.indirect.num_entries);
+ UINT16DECODE(buf, new_sect->u.indirect.num_entries);
/* Range's indirect row */
- UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.indirect.indir_row);
+ UINT16DECODE(buf, new_sect->u.indirect.indir_row);
/* Range's indirect # of rows */
- UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.indirect.indir_nrows);
+ UINT16DECODE(buf, new_sect->u.indirect.indir_nrows);
+
+ /* Set return value */
+ ret_value = (H5FS_section_info_t *)new_sect;
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1068,7 +1838,7 @@ done:
*
*-------------------------------------------------------------------------
*/
-herr_t
+static herr_t
H5HF_sect_indirect_free(H5FS_section_info_t *_sect)
{
H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Pointer to section to free */