diff options
Diffstat (limited to 'src/H5MFsection.c')
-rw-r--r-- | src/H5MFsection.c | 724 |
1 files changed, 640 insertions, 84 deletions
diff --git a/src/H5MFsection.c b/src/H5MFsection.c index e5a0cf0..0dd26b3 100644 --- a/src/H5MFsection.c +++ b/src/H5MFsection.c @@ -5,12 +5,10 @@ * * * This file is part of HDF5. The full HDF5 copyright notice, including * * terms governing use, modification, and redistribution, is contained in * - * the files COPYING and Copyright.html. COPYING can be found at the root * - * of the source code distribution tree; Copyright.html can be found at the * - * root level of an installed copy of the electronic HDF5 document set and * - * is linked from the top-level documents page. It can also be found at * - * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * - * access to either file, you may request a copy from help@hdfgroup.org. * + * the COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* @@ -57,18 +55,47 @@ /* Local Prototypes */ /********************/ -/* 'simple' section callbacks */ -static H5FS_section_info_t *H5MF_sect_simple_deserialize(const H5FS_section_class_t *cls, +/* 'simple/small/large' section callbacks */ +static H5FS_section_info_t *H5MF_sect_deserialize(const H5FS_section_class_t *cls, hid_t dxpl_id, const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size, unsigned *des_flags); +static herr_t H5MF_sect_valid(const H5FS_section_class_t *cls, + const H5FS_section_info_t *sect, hid_t dxpl_id); +static H5FS_section_info_t *H5MF_sect_split(H5FS_section_info_t *sect, + hsize_t frag_size); + + +/* 'simple' section callbacks */ static htri_t H5MF_sect_simple_can_merge(const H5FS_section_info_t *sect1, const H5FS_section_info_t *sect2, void *udata); -static herr_t H5MF_sect_simple_merge(H5FS_section_info_t *sect1, +static herr_t H5MF_sect_simple_merge(H5FS_section_info_t **sect1, H5FS_section_info_t *sect2, void *udata); -static herr_t H5MF_sect_simple_valid(const H5FS_section_class_t *cls, - const H5FS_section_info_t *sect, hid_t dxpl_id); -static H5FS_section_info_t *H5MF_sect_simple_split(H5FS_section_info_t *sect, - hsize_t frag_size); +static htri_t H5MF_sect_simple_can_shrink(const H5FS_section_info_t *_sect, + void *udata); +static herr_t H5MF_sect_simple_shrink(H5FS_section_info_t **_sect, + void *udata); + + +/* 'small' section callbacks */ +static herr_t H5MF_sect_small_add(H5FS_section_info_t **_sect, unsigned *flags, void *_udata); +static htri_t H5MF_sect_small_can_merge(const H5FS_section_info_t *sect1, + const H5FS_section_info_t *sect2, void *udata); +static herr_t H5MF_sect_small_merge(H5FS_section_info_t **sect1, + H5FS_section_info_t *sect2, void *udata); +static htri_t H5MF_sect_small_can_shrink(const H5FS_section_info_t *_sect, + void *udata); +static herr_t H5MF_sect_small_shrink(H5FS_section_info_t **_sect, + void *udata); + +/* 'large' section callbacks */ +static htri_t H5MF_sect_large_can_merge(const H5FS_section_info_t *sect1, + const H5FS_section_info_t *sect2, void *udata); +static herr_t H5MF_sect_large_merge(H5FS_section_info_t **sect1, + H5FS_section_info_t *sect2, void *udata); +static htri_t H5MF_sect_large_can_shrink(const H5FS_section_info_t *_sect, + void *udata); +static herr_t H5MF_sect_large_shrink(H5FS_section_info_t **_sect, + void *udata); /*********************/ /* Package Variables */ @@ -89,17 +116,68 @@ H5FS_section_class_t H5MF_FSPACE_SECT_CLS_SIMPLE[1] = {{ /* Object methods */ NULL, /* Add section */ NULL, /* Serialize section */ - H5MF_sect_simple_deserialize, /* Deserialize section */ + H5MF_sect_deserialize, /* Deserialize section */ H5MF_sect_simple_can_merge, /* Can sections merge? */ H5MF_sect_simple_merge, /* Merge sections */ H5MF_sect_simple_can_shrink, /* Can section shrink container?*/ H5MF_sect_simple_shrink, /* Shrink container w/section */ - H5MF_sect_simple_free, /* Free section */ - H5MF_sect_simple_valid, /* Check validity of section */ - H5MF_sect_simple_split, /* Split section node for alignment */ + H5MF_sect_free, /* Free section */ + H5MF_sect_valid, /* Check validity of section */ + H5MF_sect_split, /* Split section node for alignment */ NULL, /* Dump debugging for section */ }}; +/* Class info for "small" free space sections */ +H5FS_section_class_t H5MF_FSPACE_SECT_CLS_SMALL[1] = {{ + /* Class variables */ + H5MF_FSPACE_SECT_SMALL, /* Section type */ + 0, /* Extra serialized size */ + H5FS_CLS_MERGE_SYM | H5FS_CLS_ADJUST_OK, /* Class flags */ + NULL, /* Class private info */ + + /* Class methods */ + NULL, /* Initialize section class */ + NULL, /* Terminate section class */ + + /* Object methods */ + H5MF_sect_small_add, /* Add section */ + NULL, /* Serialize section */ + H5MF_sect_deserialize, /* Deserialize section */ + H5MF_sect_small_can_merge, /* Can sections merge? */ + H5MF_sect_small_merge, /* Merge sections */ + H5MF_sect_small_can_shrink, /* Can section shrink container?*/ + H5MF_sect_small_shrink, /* Shrink container w/section */ + H5MF_sect_free, /* Free section */ + H5MF_sect_valid, /* Check validity of section */ + H5MF_sect_split, /* Split section node for alignment */ + NULL, /* Dump debugging for section */ +}}; + +/* Class info for "large" free space sections */ +H5FS_section_class_t H5MF_FSPACE_SECT_CLS_LARGE[1] = {{ + /* Class variables */ + H5MF_FSPACE_SECT_LARGE, /* Section type */ + 0, /* Extra serialized size */ + H5FS_CLS_MERGE_SYM | H5FS_CLS_ADJUST_OK, /* Class flags */ + NULL, /* Class private info */ + + /* Class methods */ + NULL, /* Initialize section class */ + NULL, /* Terminate section class */ + + /* Object methods */ + NULL, /* Add section */ + NULL, /* Serialize section */ + H5MF_sect_deserialize, /* Deserialize section */ + H5MF_sect_large_can_merge, /* Can sections merge? */ + H5MF_sect_large_merge, /* Merge sections */ + H5MF_sect_large_can_shrink, /* Can section shrink container?*/ + H5MF_sect_large_shrink, /* Shrink container w/section */ + H5MF_sect_free, /* Free section */ + H5MF_sect_valid, /* Check validity of section */ + H5MF_sect_split, /* Split section node for alignment */ + NULL, /* Dump debugging for section */ +}}; /*****************************/ /* Library Private Variables */ @@ -113,12 +191,15 @@ H5FS_section_class_t H5MF_FSPACE_SECT_CLS_SIMPLE[1] = {{ /* Declare a free list to manage the H5MF_free_section_t struct */ H5FL_DEFINE(H5MF_free_section_t); +/* + * "simple/small/large" section callbacks + */ /*------------------------------------------------------------------------- - * Function: H5MF_sect_simple_new + * Function: H5MF_sect_new * - * Purpose: Create a new 'simple' section and return it to the caller + * Purpose: Create a new section of "ctype" and return it to the caller * * Return: Pointer to new section on success/NULL on failure * @@ -129,9 +210,9 @@ H5FL_DEFINE(H5MF_free_section_t); *------------------------------------------------------------------------- */ H5MF_free_section_t * -H5MF_sect_simple_new(haddr_t sect_off, hsize_t sect_size) +H5MF_sect_new(unsigned ctype, haddr_t sect_off, hsize_t sect_size) { - H5MF_free_section_t *sect = NULL; /* 'Simple' free space section to add */ + H5MF_free_section_t *sect; /* 'Simple' free space section to add */ H5MF_free_section_t *ret_value = NULL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -148,7 +229,7 @@ H5MF_sect_simple_new(haddr_t sect_off, hsize_t sect_size) sect->sect_info.size = sect_size; /* Set the section's class & state */ - sect->sect_info.type = H5MF_FSPACE_SECT_SIMPLE; + sect->sect_info.type = ctype; sect->sect_info.state = H5FS_SECT_LIVE; /* Set return value */ @@ -156,13 +237,43 @@ H5MF_sect_simple_new(haddr_t sect_off, hsize_t sect_size) done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5MF_sect_simple_new() */ +} /* end H5MF_sect_new() */ /*------------------------------------------------------------------------- - * Function: H5MF_sect_simple_deserialize + * Function: H5MF_sect_free * - * Purpose: Deserialize a buffer into a "live" single section + * Purpose: Free a 'simple/small/large' section node + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * Tuesday, January 8, 2008 + * + *------------------------------------------------------------------------- + */ +herr_t +H5MF_sect_free(H5FS_section_info_t *_sect) +{ + H5MF_free_section_t *sect = (H5MF_free_section_t *)_sect; /* File free section */ + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + /* Check arguments. */ + HDassert(sect); + + /* Release the section */ + sect = H5FL_FREE(H5MF_free_section_t, sect); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5MF_sect_free() */ + + +/*------------------------------------------------------------------------- + * Function: H5MF_sect_deserialize + * + * Purpose: Deserialize a buffer into a "live" section * * Return: Success: non-negative * Failure: negative @@ -173,7 +284,7 @@ done: *------------------------------------------------------------------------- */ static H5FS_section_info_t * -H5MF_sect_simple_deserialize(const H5FS_section_class_t H5_ATTR_UNUSED *cls, +H5MF_sect_deserialize(const H5FS_section_class_t *cls, hid_t H5_ATTR_UNUSED dxpl_id, const uint8_t H5_ATTR_UNUSED *buf, haddr_t sect_addr, hsize_t sect_size, unsigned H5_ATTR_UNUSED *des_flags) { @@ -183,11 +294,12 @@ H5MF_sect_simple_deserialize(const H5FS_section_class_t H5_ATTR_UNUSED *cls, FUNC_ENTER_NOAPI_NOINIT /* Check arguments. */ + HDassert(cls); HDassert(H5F_addr_defined(sect_addr)); HDassert(sect_size); /* Create free space section for block */ - if(NULL == (sect = H5MF_sect_simple_new(sect_addr, sect_size))) + if(NULL == (sect = H5MF_sect_new(cls->type, sect_addr, sect_size))) HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, NULL, "can't initialize free space section") /* Set return value */ @@ -195,10 +307,80 @@ H5MF_sect_simple_deserialize(const H5FS_section_class_t H5_ATTR_UNUSED *cls, done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5MF_sect_simple_deserialize() */ +} /* H5MF_sect_deserialize() */ /*------------------------------------------------------------------------- + * Function: H5MF_sect_valid + * + * Purpose: Check the validity of a section + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * Tuesday, January 8, 2008 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5MF_sect_valid(const H5FS_section_class_t H5_ATTR_UNUSED *cls, + const H5FS_section_info_t +#ifdef NDEBUG + H5_ATTR_UNUSED +#endif /* NDEBUG */ + *_sect, hid_t H5_ATTR_UNUSED dxpl_id) +{ +#ifndef NDEBUG + const H5MF_free_section_t *sect = (const H5MF_free_section_t *)_sect; /* File free section */ +#endif /* NDEBUG */ + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + /* Check arguments. */ + HDassert(sect); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5MF_sect_valid() */ + + +/*------------------------------------------------------------------------- + * Function: H5MF_sect_split + * + * Purpose: Split SECT into 2 sections: fragment for alignment & the aligned section + * SECT's addr and size are updated to point to the aligned section + * + * Return: Success: the fragment for aligning sect + * Failure: null + * + * Programmer: Vailin Choi, July 29, 2008 + * + *------------------------------------------------------------------------- + */ +static H5FS_section_info_t * +H5MF_sect_split(H5FS_section_info_t *sect, hsize_t frag_size) +{ + H5MF_free_section_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Allocate space for new section */ + if(NULL == (ret_value = H5MF_sect_new(sect->type, sect->addr, frag_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, NULL, "can't initialize free space section") + + /* Set new section's info */ + sect->addr += frag_size; + sect->size -= frag_size; + +done: + FUNC_LEAVE_NOAPI((H5FS_section_info_t *)ret_value) +} /* end H5MF_sect_split() */ + +/* + * "simple" section callbacks + */ + +/*------------------------------------------------------------------------- * Function: H5MF_sect_simple_can_merge * * Purpose: Can two sections of this type merge? @@ -252,10 +434,10 @@ H5MF_sect_simple_can_merge(const H5FS_section_info_t *_sect1, *------------------------------------------------------------------------- */ static herr_t -H5MF_sect_simple_merge(H5FS_section_info_t *_sect1, H5FS_section_info_t *_sect2, +H5MF_sect_simple_merge(H5FS_section_info_t **_sect1, H5FS_section_info_t *_sect2, void H5_ATTR_UNUSED *_udata) { - H5MF_free_section_t *sect1 = (H5MF_free_section_t *)_sect1; /* File free section */ + H5MF_free_section_t **sect1 = (H5MF_free_section_t **)_sect1; /* File free section */ H5MF_free_section_t *sect2 = (H5MF_free_section_t *)_sect2; /* File free section */ herr_t ret_value = SUCCEED; /* Return value */ @@ -263,16 +445,16 @@ H5MF_sect_simple_merge(H5FS_section_info_t *_sect1, H5FS_section_info_t *_sect2, /* Check arguments. */ HDassert(sect1); - HDassert(sect1->sect_info.type == H5MF_FSPACE_SECT_SIMPLE); + HDassert((*sect1)->sect_info.type == H5MF_FSPACE_SECT_SIMPLE); HDassert(sect2); HDassert(sect2->sect_info.type == H5MF_FSPACE_SECT_SIMPLE); - HDassert(H5F_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr)); + HDassert(H5F_addr_eq((*sect1)->sect_info.addr + (*sect1)->sect_info.size, sect2->sect_info.addr)); /* Add second section's size to first section */ - sect1->sect_info.size += sect2->sect_info.size; + (*sect1)->sect_info.size += sect2->sect_info.size; /* Get rid of second section */ - if(H5MF_sect_simple_free((H5FS_section_info_t *)sect2) < 0) + if(H5MF_sect_free((H5FS_section_info_t *)sect2) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free section node") done: @@ -293,7 +475,7 @@ done: * *------------------------------------------------------------------------- */ -htri_t +static htri_t H5MF_sect_simple_can_shrink(const H5FS_section_info_t *_sect, void *_udata) { const H5MF_free_section_t *sect = (const H5MF_free_section_t *)_sect; /* File free section */ @@ -392,7 +574,7 @@ done: * *------------------------------------------------------------------------- */ -herr_t +static herr_t H5MF_sect_simple_shrink(H5FS_section_info_t **_sect, void *_udata) { H5MF_free_section_t **sect = (H5MF_free_section_t **)_sect; /* File free section */ @@ -411,8 +593,8 @@ H5MF_sect_simple_shrink(H5FS_section_info_t **_sect, void *_udata) /* Sanity check */ HDassert(H5F_INTENT(udata->f) & H5F_ACC_RDWR); - /* Release section's space at EOA with file driver */ - if(H5FD_free(udata->f->shared->lf, udata->dxpl_id, udata->alloc_type, udata->f, (*sect)->sect_info.addr, (*sect)->sect_info.size) < 0) + /* Release section's space at EOA */ + if(H5F_free(udata->f, udata->dxpl_id, udata->alloc_type, (*sect)->sect_info.addr, (*sect)->sect_info.size) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "driver free request failed") } /* end if */ else { @@ -427,7 +609,7 @@ H5MF_sect_simple_shrink(H5FS_section_info_t **_sect, void *_udata) /* Check for freeing section */ if(udata->shrink != H5MF_SHRINK_SECT_ABSORB_AGGR) { /* Free section */ - if(H5MF_sect_simple_free((H5FS_section_info_t *)*sect) < 0) + if(H5MF_sect_free((H5FS_section_info_t *)*sect) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free simple section node") /* Mark section as freed, for free space manager */ @@ -438,100 +620,474 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* H5MF_sect_simple_shrink() */ +/* + * "small" section callbacks + */ + + +/*------------------------------------------------------------------------- + * Function: H5MF_sect_small_add + * + * Purpose: Perform actions on a small "meta" action before adding it to the free space manager: + * 1) Drop the section if it is at page end and its size <= page end threshold + * 2) Adjust section size to include page end threshold if + * (section size + threshold) is at page end + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Vailin Choi; Dec 2012 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5MF_sect_small_add(H5FS_section_info_t **_sect, unsigned *flags, void *_udata) +{ + H5MF_free_section_t **sect = (H5MF_free_section_t **)_sect; /* Fractal heap free section */ + H5MF_sect_ud_t *udata = (H5MF_sect_ud_t *)_udata; /* User data for callback */ + haddr_t sect_end; + hsize_t rem, prem; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + +#ifdef H5MF_ALLOC_DEBUG_MORE +HDfprintf(stderr, "%s: Entering, section {%a, %Hu}\n", FUNC, (*sect)->sect_info.addr, (*sect)->sect_info.size); +#endif /* H5MF_ALLOC_DEBUG_MORE */ + + /* Do not adjust the section raw data or global heap data */ + if(udata->alloc_type == H5FD_MEM_DRAW || udata->alloc_type == H5FD_MEM_GHEAP) + HGOTO_DONE(ret_value); + + sect_end = (*sect)->sect_info.addr + (*sect)->sect_info.size; + rem = sect_end % udata->f->shared->fs_page_size; + prem = udata->f->shared->fs_page_size - rem; + + /* Drop the section if it is at page end and its size is <= pgend threshold */ + if(!rem && (*sect)->sect_info.size <= H5F_PGEND_META_THRES(udata->f) && (*flags & H5FS_ADD_RETURNED_SPACE)) { + if(H5MF_sect_free((H5FS_section_info_t *)(*sect)) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free section node") + *sect = NULL; + *flags &= (unsigned)~H5FS_ADD_RETURNED_SPACE; + *flags |= H5FS_PAGE_END_NO_ADD; +#ifdef H5MF_ALLOC_DEBUG_MORE +HDfprintf(stderr, "%s: section is dropped\n", FUNC); +#endif /* H5MF_ALLOC_DEBUG_MORE */ + } /* end if */ + /* Adjust the section if it is not at page end but its size + pgend threshold is at page end */ + else + if(prem <= H5F_PGEND_META_THRES(udata->f)) { + (*sect)->sect_info.size += prem; +#ifdef H5MF_ALLOC_DEBUG_MORE +HDfprintf(stderr, "%s: section is adjusted {%a, %Hu}\n", FUNC, (*sect)->sect_info.addr, (*sect)->sect_info.size); +#endif /* H5MF_ALLOC_DEBUG_MORE */ + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5MF_sect_small_add() */ + + +/*------------------------------------------------------------------------- + * Function: H5MF_sect_small_can_shrink + * + * Purpose: Can this section shrink the container? + * + * Note: A small section is allowed to shrink only at closing. + * + * Return: Success: non-negative (TRUE/FALSE) + * Failure: negative + * + * Programmer: Vailin Choi; Dec 2012 + * + *------------------------------------------------------------------------- + */ +static htri_t +H5MF_sect_small_can_shrink(const H5FS_section_info_t *_sect, void *_udata) +{ + const H5MF_free_section_t *sect = (const H5MF_free_section_t *)_sect; /* File free section */ + H5MF_sect_ud_t *udata = (H5MF_sect_ud_t *)_udata; /* User data for callback */ + haddr_t eoa; /* End of address space in the file */ + haddr_t end; /* End of section to extend */ + htri_t ret_value = FALSE; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Check arguments. */ + HDassert(sect); + HDassert(udata); + HDassert(udata->f); + + /* Retrieve the end of the file's address space */ + if(HADDR_UNDEF == (eoa = H5FD_get_eoa(udata->f->shared->lf, udata->alloc_type))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "driver get_eoa request failed") + + /* Compute address of end of section to check */ + end = sect->sect_info.addr + sect->sect_info.size; + + /* Check if the section is exactly at the end of the allocated space in the file */ + if(H5F_addr_eq(end, eoa) && sect->sect_info.size == udata->f->shared->fs_page_size) { + udata->shrink = H5MF_SHRINK_EOA; + +#ifdef H5MF_ALLOC_DEBUG_MORE +HDfprintf(stderr, "%s: section {%a, %Hu}, shrinks file, eoa = %a\n", FUNC, sect->sect_info.addr, sect->sect_info.size, eoa); +#endif /* H5MF_ALLOC_DEBUG_MORE */ + + /* Indicate shrinking can occur */ + HGOTO_DONE(TRUE) + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5MF_sect_small_can_shrink() */ + /*------------------------------------------------------------------------- - * Function: H5MF_sect_simple_free + * Function: H5MF_sect_small_shrink * - * Purpose: Free a 'single' section node + * Purpose: Shrink container with section * * Return: Success: non-negative - * Failure: negative + * Failure: negative + * + * Programmer: Vailin Choi; Dec 2012 * - * Programmer: Quincey Koziol - * Tuesday, January 8, 2008 + *------------------------------------------------------------------------- + */ +static herr_t +H5MF_sect_small_shrink(H5FS_section_info_t **_sect, void *_udata) +{ + H5MF_free_section_t **sect = (H5MF_free_section_t **)_sect; /* File free section */ + H5MF_sect_ud_t *udata = (H5MF_sect_ud_t *)_udata; /* User data for callback */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Check arguments. */ + HDassert(sect); + HDassert((*sect)->sect_info.type == H5MF_FSPACE_SECT_SMALL); + HDassert(udata); + HDassert(udata->f); + HDassert(udata->shrink == H5MF_SHRINK_EOA); + HDassert(H5F_INTENT(udata->f) & H5F_ACC_RDWR); + + /* Release section's space at EOA */ + if(H5F_free(udata->f, udata->dxpl_id, udata->alloc_type, (*sect)->sect_info.addr, (*sect)->sect_info.size) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "driver free request failed") + + /* Free section */ + if(H5MF_sect_free((H5FS_section_info_t *)*sect) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free simple section node") + + /* Mark section as freed, for free space manager */ + *sect = NULL; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5MF_sect_small_shrink() */ + + +/*------------------------------------------------------------------------- + * Function: H5MF_sect_small_can_merge + * + * Purpose: Can two sections of this type merge? + * + * Note: Second section must be "after" first section + * The "merged" section cannot cross page boundary. + * + * Return: Success: non-negative (TRUE/FALSE) + * Failure: negative + * + * Programmer: Vailin Choi; Dec 2012 * *------------------------------------------------------------------------- */ -herr_t -H5MF_sect_simple_free(H5FS_section_info_t *_sect) +static htri_t +H5MF_sect_small_can_merge(const H5FS_section_info_t *_sect1, + const H5FS_section_info_t *_sect2, void *_udata) { - H5MF_free_section_t *sect = (H5MF_free_section_t *)_sect; /* File free section */ + const H5MF_free_section_t *sect1 = (const H5MF_free_section_t *)_sect1; /* File free section */ + const H5MF_free_section_t *sect2 = (const H5MF_free_section_t *)_sect2; /* File free section */ + H5MF_sect_ud_t *udata = (H5MF_sect_ud_t *)_udata; /* User data for callback */ + htri_t ret_value = FALSE; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOERR /* Check arguments. */ - HDassert(sect); + HDassert(sect1); + HDassert(sect2); + HDassert(sect1->sect_info.type == sect2->sect_info.type); /* Checks "MERGE_SYM" flag */ + HDassert(H5F_addr_lt(sect1->sect_info.addr, sect2->sect_info.addr)); - /* Release the section */ - sect = H5FL_FREE(H5MF_free_section_t, sect); + /* Check if second section adjoins first section */ + ret_value = H5F_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr); + if(ret_value > 0) + /* If they are on different pages, couldn't merge */ + if((sect1->sect_info.addr / udata->f->shared->fs_page_size) != (((sect2->sect_info.addr + sect2->sect_info.size - 1) / udata->f->shared->fs_page_size))) + ret_value = FALSE; - FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5MF_sect_simple_free() */ +#ifdef H5MF_ALLOC_DEBUG_MORE +HDfprintf(stderr, "%s: Leaving: ret_value = %t\n", FUNC, ret_value); +#endif /* H5MF_ALLOC_DEBUG_MORE */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5MF_sect_small_can_merge() */ /*------------------------------------------------------------------------- - * Function: H5MF_sect_simple_valid + * Function: H5MF_sect_small_merge * - * Purpose: Check the validity of a section + * Purpose: Merge two sections of this type + * + * Note: Second section always merges into first node. + * If the size of the "merged" section is equal to file space page size, + * free the section. * * Return: Success: non-negative * Failure: negative * - * Programmer: Quincey Koziol - * Tuesday, January 8, 2008 + * Programmer: Vailin Choi; Dec 2012 * *------------------------------------------------------------------------- */ static herr_t -H5MF_sect_simple_valid(const H5FS_section_class_t H5_ATTR_UNUSED *cls, - const H5FS_section_info_t -#ifdef NDEBUG - H5_ATTR_UNUSED -#endif /* NDEBUG */ - *_sect, hid_t H5_ATTR_UNUSED dxpl_id) +H5MF_sect_small_merge(H5FS_section_info_t **_sect1, H5FS_section_info_t *_sect2, + void *_udata) { -#ifndef NDEBUG - const H5MF_free_section_t *sect = (const H5MF_free_section_t *)_sect; /* File free section */ -#endif /* NDEBUG */ + H5MF_free_section_t **sect1 = (H5MF_free_section_t **)_sect1; /* File free section */ + H5MF_free_section_t *sect2 = (H5MF_free_section_t *)_sect2; /* File free section */ + H5MF_sect_ud_t *udata = (H5MF_sect_ud_t *)_udata; /* User data for callback */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Check arguments. */ + HDassert(sect1); + HDassert((*sect1)->sect_info.type == H5MF_FSPACE_SECT_SMALL); + HDassert(sect2); + HDassert(sect2->sect_info.type == H5MF_FSPACE_SECT_SMALL); + HDassert(H5F_addr_eq((*sect1)->sect_info.addr + (*sect1)->sect_info.size, sect2->sect_info.addr)); + + /* Add second section's size to first section */ + (*sect1)->sect_info.size += sect2->sect_info.size; + + if((*sect1)->sect_info.size == udata->f->shared->fs_page_size) { + if(H5MF_xfree(udata->f, udata->alloc_type, udata->dxpl_id, (*sect1)->sect_info.addr, (*sect1)->sect_info.size) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "can't free merged section") + + /* Need to free possible metadata page in the PB cache */ + /* This is in response to the data corruption bug from fheap.c with page buffering + page strategy */ + /* Note: Large metadata page bypasses the PB cache */ + /* Note: Update of raw data page (large or small sized) is handled by the PB cache */ + if(udata->f->shared->page_buf != NULL && udata->alloc_type != H5FD_MEM_DRAW) + if(H5PB_remove_entry(udata->f, (*sect1)->sect_info.addr) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "can't free merged section") + + if(H5MF_sect_free((H5FS_section_info_t *)(*sect1)) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free section node") + *sect1 = NULL; + } /* end if */ + + /* Get rid of second section */ + if(H5MF_sect_free((H5FS_section_info_t *)sect2) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free section node") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5MF_sect_small_merge() */ + +/* + * "Large" section callbacks + */ + + +/*------------------------------------------------------------------------- + * Function: H5MF_sect_large_can_merge (same as H5MF_sect_simple_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: Vailin Choi; Dec 2012 + * + *------------------------------------------------------------------------- + */ +static htri_t +H5MF_sect_large_can_merge(const H5FS_section_info_t *_sect1, + const H5FS_section_info_t *_sect2, void H5_ATTR_UNUSED *_udata) +{ + const H5MF_free_section_t *sect1 = (const H5MF_free_section_t *)_sect1; /* File free section */ + const H5MF_free_section_t *sect2 = (const H5MF_free_section_t *)_sect2; /* File free section */ + htri_t ret_value = FALSE; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOERR /* Check arguments. */ + HDassert(sect1); + HDassert(sect2); + HDassert(sect1->sect_info.type == sect2->sect_info.type); /* Checks "MERGE_SYM" flag */ + HDassert(H5F_addr_lt(sect1->sect_info.addr, sect2->sect_info.addr)); + + ret_value = H5F_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr); + +#ifdef H5MF_ALLOC_DEBUG_MORE +HDfprintf(stderr, "%s: Leaving: ret_value = %t\n", FUNC, ret_value); +#endif /* H5MF_ALLOC_DEBUG_MORE */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5MF_sect_large_can_merge() */ + + +/*------------------------------------------------------------------------- + * Function: H5MF_sect_large_merge (same as H5MF_sect_simple_merge) + * + * Purpose: Merge two sections of this type + * + * Note: Second section always merges into first node + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Vailin Choi; Dec 2012 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5MF_sect_large_merge(H5FS_section_info_t **_sect1, H5FS_section_info_t *_sect2, + void H5_ATTR_UNUSED *_udata) +{ + H5MF_free_section_t **sect1 = (H5MF_free_section_t **)_sect1; /* File free section */ + H5MF_free_section_t *sect2 = (H5MF_free_section_t *)_sect2; /* File free section */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Check arguments. */ + HDassert(sect1); + HDassert((*sect1)->sect_info.type == H5MF_FSPACE_SECT_LARGE); + HDassert(sect2); + HDassert(sect2->sect_info.type == H5MF_FSPACE_SECT_LARGE); + HDassert(H5F_addr_eq((*sect1)->sect_info.addr + (*sect1)->sect_info.size, sect2->sect_info.addr)); + + /* Add second section's size to first section */ + (*sect1)->sect_info.size += sect2->sect_info.size; + + /* Get rid of second section */ + if(H5MF_sect_free((H5FS_section_info_t *)sect2) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free section node") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5MF_sect_large_merge() */ + + +/*------------------------------------------------------------------------- + * Function: H5MF_sect_large_can_shrink + * + * Purpose: Can this section shrink the container? + * + * Return: Success: non-negative (TRUE/FALSE) + * Failure: negative + * + * Programmer: Vailin Choi; Dec 2012 + * + *------------------------------------------------------------------------- + */ +static htri_t +H5MF_sect_large_can_shrink(const H5FS_section_info_t *_sect, void *_udata) +{ + const H5MF_free_section_t *sect = (const H5MF_free_section_t *)_sect; /* File free section */ + H5MF_sect_ud_t *udata = (H5MF_sect_ud_t *)_udata; /* User data for callback */ + haddr_t eoa; /* End of address space in the file */ + haddr_t end; /* End of section to extend */ + htri_t ret_value = FALSE; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Check arguments. */ HDassert(sect); + HDassert(sect->sect_info.type == H5MF_FSPACE_SECT_LARGE); + HDassert(udata); + HDassert(udata->f); - FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5MF_sect_simple_valid() */ + /* Retrieve the end of the file's address space */ + if(HADDR_UNDEF == (eoa = H5FD_get_eoa(udata->f->shared->lf, udata->alloc_type))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "driver get_eoa request failed") + + /* Compute address of end of section to check */ + end = sect->sect_info.addr + sect->sect_info.size; + + /* Check if the section is exactly at the end of the allocated space in the file */ + if(H5F_addr_eq(end, eoa) && sect->sect_info.size >= udata->f->shared->fs_page_size) { + /* Set the shrinking type */ + udata->shrink = H5MF_SHRINK_EOA; +#ifdef H5MF_ALLOC_DEBUG_MORE +HDfprintf(stderr, "%s: section {%a, %Hu}, shrinks file, eoa = %a\n", FUNC, sect->sect_info.addr, sect->sect_info.size, eoa); +#endif /* H5MF_ALLOC_DEBUG_MORE */ + /* Indicate shrinking can occur */ + HGOTO_DONE(TRUE) + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5MF_sect_large_can_shrink() */ + /*------------------------------------------------------------------------- - * Function: H5MF_sect_simple_split + * Function: H5MF_sect_large_shrink * - * Purpose: Split SECT into 2 sections: fragment for alignment & the aligned section - * SECT's addr and size are updated to point to the aligned section + * Purpose: Shrink a large-sized section * - * Return: Success: the fragment for aligning sect - * Failure: null + * Return: Success: non-negative + * Failure: negative * - * Programmer: Vailin Choi, July 29, 2008 + * Programmer: Vailin Choi; Dec 2012 * *------------------------------------------------------------------------- */ -static H5FS_section_info_t * -H5MF_sect_simple_split(H5FS_section_info_t *sect, hsize_t frag_size) +static herr_t +H5MF_sect_large_shrink(H5FS_section_info_t **_sect, void *_udata) { - H5MF_free_section_t *ret_value = NULL; /* Return value */ + H5MF_free_section_t **sect = (H5MF_free_section_t **)_sect; /* File free section */ + H5MF_sect_ud_t *udata = (H5MF_sect_ud_t *)_udata; /* User data for callback */ + hsize_t frag_size = 0; /* Fragment size */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT - /* Allocate space for new section */ - if(NULL == (ret_value = H5MF_sect_simple_new(sect->addr, frag_size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, NULL, "can't initialize free space section") + /* Check arguments. */ + HDassert(sect); + HDassert((*sect)->sect_info.type == H5MF_FSPACE_SECT_LARGE); + HDassert(udata); + HDassert(udata->f); + HDassert(udata->shrink == H5MF_SHRINK_EOA); + HDassert(H5F_INTENT(udata->f) & H5F_ACC_RDWR); + HDassert(H5F_PAGED_AGGR(udata->f)); - /* Set new section's info */ - sect->addr += frag_size; - sect->size -= frag_size; + /* Calculate possible mis-aligned fragment */ + H5MF_EOA_MISALIGN(udata->f, (*sect)->sect_info.addr, udata->f->shared->fs_page_size, frag_size); + + /* Free full pages from EOA */ + /* Retain partial page in the free-space manager so as to keep EOA at page boundary */ + if(H5F_free(udata->f, udata->dxpl_id, udata->alloc_type, (*sect)->sect_info.addr+frag_size, (*sect)->sect_info.size-frag_size) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "driver free request failed") + + if(frag_size) /* Adjust section size for the partial page */ + (*sect)->sect_info.size = frag_size; + else { + /* Free section */ + if(H5MF_sect_free((H5FS_section_info_t *)*sect) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free simple section node") + + /* Mark section as freed, for free space manager */ + *sect = NULL; + } /* end else */ done: - FUNC_LEAVE_NOAPI((H5FS_section_info_t *)ret_value) -} /* end H5MF_sect_simple_split() */ + FUNC_LEAVE_NOAPI(ret_value) +} /* H5MF_sect_large_shrink() */ |