summaryrefslogtreecommitdiffstats
path: root/src/H5MFsection.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5MFsection.c')
-rw-r--r--src/H5MFsection.c714
1 files changed, 636 insertions, 78 deletions
diff --git a/src/H5MFsection.c b/src/H5MFsection.c
index e5a0cf0..617cb59 100644
--- a/src/H5MFsection.c
+++ b/src/H5MFsection.c
@@ -57,18 +57,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 +118,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 +193,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 +212,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 +231,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 +239,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 +286,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 +296,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 +309,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 +436,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 +447,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 +477,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 +576,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 +595,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 +611,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 +622,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() */