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