diff options
Diffstat (limited to 'src/H5HFsection.c')
-rw-r--r-- | src/H5HFsection.c | 1126 |
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 = §_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 */ |