summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/H5FS.c897
-rw-r--r--src/H5FScache.c20
-rw-r--r--src/H5FSdbg.c10
-rw-r--r--src/H5FSpkg.h19
-rw-r--r--src/H5FSprivate.h35
-rw-r--r--src/H5Gdeprec.c1
-rw-r--r--src/H5HFdbg.c10
-rw-r--r--src/H5HFdblock.c23
-rw-r--r--src/H5HFdtable.c13
-rw-r--r--src/H5HFhdr.c203
-rw-r--r--src/H5HFiblock.c228
-rw-r--r--src/H5HFint.c53
-rw-r--r--src/H5HFpkg.h87
-rw-r--r--src/H5HFsection.c3442
-rw-r--r--src/H5HFspace.c90
-rw-r--r--src/H5HFtest.c2
16 files changed, 3871 insertions, 1262 deletions
diff --git a/src/H5FS.c b/src/H5FS.c
index 1da16da..7b8e222 100644
--- a/src/H5FS.c
+++ b/src/H5FS.c
@@ -12,7 +12,8 @@
* access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-/* Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
+/*
+ * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
* Tuesday, May 2, 2006
*
* Purpose: Free space tracking functions.
@@ -61,6 +62,9 @@
+ H5F_SIZEOF_ADDR(f) /* Address of free space header for these sections */ \
)
+/* Uncomment this macro to enable extra sanity checking */
+/* #define H5FS_DEBUG */
+
/******************/
/* Local Typedefs */
/******************/
@@ -68,6 +72,8 @@
/* Free space node for free space sections of the same size */
typedef struct H5FS_node_t {
hsize_t sect_size; /* Size of all sections on list */
+ size_t serial_count; /* # of serializable sections on list */
+ size_t ghost_count; /* # of un-serializable sections on list */
H5SL_t *sect_list; /* Skip list to hold pointers to actual free list section node */
} H5FS_node_t;
@@ -105,8 +111,24 @@ static herr_t H5FS_open_remove(H5FS_t *fspace);
static herr_t H5FS_init(H5FS_t *fspace);
static herr_t H5FS_sect_free_cb(void *item, void *key, void *op_data);
static herr_t H5FS_node_free_cb(void *item, void *key, void *op_data);
-static herr_t H5FS_sect_increase(H5FS_t *fspace);
-static herr_t H5FS_sect_decrease(H5FS_t *fspace);
+static herr_t H5FS_sect_increase(H5FS_t *fspace, const H5FS_section_class_t *cls);
+static herr_t H5FS_sect_decrease(H5FS_t *fspace, const H5FS_section_class_t *cls);
+static herr_t H5FS_size_node_decr(H5FS_t *fspace, unsigned bin, H5FS_node_t *fspace_node,
+ const H5FS_section_class_t *cls);
+static herr_t H5FS_sect_unlink_size(H5FS_t *fspace, const H5FS_section_class_t *cls,
+ H5FS_section_info_t *sect);
+static herr_t H5FS_sect_unlink_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
+ const H5FS_section_class_t *cls, H5FS_section_info_t *sect);
+static herr_t H5FS_sect_unlink(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
+ H5FS_section_info_t *sect);
+static herr_t H5FS_sect_link_size_bin(H5FS_t *fspace, const H5FS_section_class_t *cls,
+ H5FS_section_info_t *sect);
+static herr_t H5FS_sect_link_size(H5FS_t *fspace, const H5FS_section_class_t *cls,
+ H5FS_section_info_t *sect);
+static herr_t H5FS_sect_link_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
+ const H5FS_section_class_t *cls, H5FS_section_info_t *sect);
+static herr_t H5FS_sect_link(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
+ H5FS_section_info_t *sect);
static htri_t H5FS_find_bin_node(H5FS_t *fspace, hsize_t request, H5FS_section_info_t **node);
static herr_t H5FS_serialize_sect_cb(void *_item, void UNUSED *key, void *_udata);
static herr_t H5FS_serialize_node_cb(void *_item, void UNUSED *key, void *_udata);
@@ -114,6 +136,9 @@ static size_t H5FS_serialize_size(H5FS_t *fspace);
static herr_t H5FS_serialize_bins(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace);
static herr_t H5FS_deserialize_bins(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace);
static herr_t H5FS_flush_cb(void *_item, void *key, void *_udata);
+#ifdef H5FS_DEBUG
+herr_t H5FS_assert(const H5FS_t *fspace);
+#endif /* H5FS_DEBUG */
/*********************/
@@ -316,7 +341,7 @@ H5FS_init(H5FS_t *fspace)
fspace->bins = NULL;
fspace->merge_list = NULL;
fspace->serial_size = 0;
- fspace->size_count = 0;
+ fspace->tot_size_count = fspace->serial_size_count = fspace->ghost_size_count = 0;
FUNC_LEAVE_NOAPI(SUCCEED)
} /* H5FS_init() */
@@ -338,7 +363,7 @@ H5FS_init(H5FS_t *fspace)
*/
H5FS_t *
H5FS_create(H5F_t *f, hid_t dxpl_id, haddr_t *fs_addr, const H5FS_create_t *fs_create,
- size_t nclasses, const H5FS_section_class_t *classes[], const void *cls_init_udata)
+ size_t nclasses, const H5FS_section_class_t *classes[], void *cls_init_udata)
{
H5FS_t *fspace = NULL; /* New free space structure */
H5FS_hdr_t *fs_hdr = NULL; /* New free space header */
@@ -390,7 +415,7 @@ H5FS_create(H5F_t *f, hid_t dxpl_id, haddr_t *fs_addr, const H5FS_create_t *fs_c
/* Initialize information for header */
fs_hdr->tot_space = 0;
- fs_hdr->sect_count = 0;
+ fs_hdr->tot_sect_count = fs_hdr->serial_sect_count = fs_hdr->ghost_sect_count = 0;
fs_hdr->nclasses = nclasses;
fs_hdr->client = fs_create->client;
fs_hdr->shrink_percent = fs_create->shrink_percent;
@@ -439,6 +464,9 @@ HDfprintf(stderr, "%s: fspace->hdr->sect_size = %Hu\n", FUNC, fspace->hdr->sect_
/* Flag the free space as dirty */
fspace->dirty = TRUE;
+ /* Reset flag for deserializing the sections */
+ fspace->must_deserialize = FALSE;
+
/* Add the free space manager to the list of open free space managers */
if(H5FS_open_add(fspace) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, NULL, "can't add free space header to open list")
@@ -473,7 +501,7 @@ done:
*/
H5FS_t *
H5FS_open(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr, size_t nclasses,
- const H5FS_section_class_t *classes[], const void *cls_init_udata)
+ const H5FS_section_class_t *classes[], void *cls_init_udata)
{
H5FS_hdr_t *fs_hdr = NULL; /* Free space header loaded from file */
H5FS_t *fspace = NULL; /* New free space structure */
@@ -499,6 +527,11 @@ HDfprintf(stderr, "%s: Opening free space manager\n", FUNC);
/* Point free space wrapper at header and pin it in the cache */
fspace->hdr = fs_hdr;
+#ifdef QAK
+HDfprintf(stderr, "%s: fspace->hdr->tot_sect_count = %Hu\n", FUNC, fspace->hdr->tot_sect_count);
+HDfprintf(stderr, "%s: fspace->hdr->serial_sect_count = %Hu\n", FUNC, fspace->hdr->serial_sect_count);
+HDfprintf(stderr, "%s: fspace->hdr->ghost_sect_count = %Hu\n", FUNC, fspace->hdr->ghost_sect_count);
+#endif /* QAK */
if(H5AC_pin_protected_entry(f, fs_hdr) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTPIN, NULL, "unable to pin free space header")
@@ -541,16 +574,17 @@ HDfprintf(stderr, "%s: fspace->sect_off_size = %u, fspace->sect_len_size = %u\n"
/* The free space is clean, currently */
fspace->dirty = FALSE;
- /* Go get all the sections, if there are any */
+ /* Set flag for delayed deserialization appropriately */
#ifdef QAK
HDfprintf(stderr, "%s: fspace->hdr->sect_addr = %a\n", FUNC, fspace->hdr->sect_addr);
#endif /* QAK */
- if(fspace->hdr->sect_count > 0) {
+ if(fspace->hdr->serial_sect_count > 0) {
HDassert(H5F_addr_defined(fspace->hdr->sect_addr));
HDassert(fspace->hdr->sect_size > 0);
- if(H5FS_deserialize_bins(f, dxpl_id, fspace) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTDECODE, NULL, "can't deserialize sections")
+ fspace->must_deserialize = TRUE;
} /* end if */
+ else
+ fspace->must_deserialize = FALSE;
/* Add the free space manager to the list of open free space managers */
if(H5FS_open_add(fspace) < 0)
@@ -586,19 +620,27 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_sect_increase(H5FS_t *fspace)
+H5FS_sect_increase(H5FS_t *fspace, const H5FS_section_class_t *cls)
{
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_sect_increase)
/* Check arguments. */
HDassert(fspace);
HDassert(fspace->hdr);
+ HDassert(cls);
- /* Increment # of sections on free space list */
- fspace->hdr->sect_count++;
+ /* Increment total # of sections on free space list */
+ fspace->hdr->tot_sect_count++;
- /* Update the free space sections' serialized size */
- fspace->hdr->sect_size = H5FS_serialize_size(fspace);
+ /* Check for serializable or 'ghost' section */
+ if(cls->flags & H5FS_CLS_GHOST_OBJ)
+ fspace->hdr->ghost_sect_count++;
+ else {
+ fspace->hdr->serial_sect_count++;
+
+ /* Update the free space sections' serialized size */
+ fspace->hdr->sect_size = H5FS_serialize_size(fspace);
+ } /* end else */
FUNC_LEAVE_NOAPI(SUCCEED)
} /* H5FS_sect_increase() */
@@ -620,7 +662,7 @@ H5FS_sect_increase(H5FS_t *fspace)
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_sect_decrease(H5FS_t *fspace)
+H5FS_sect_decrease(H5FS_t *fspace, const H5FS_section_class_t *cls)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -629,67 +671,82 @@ H5FS_sect_decrease(H5FS_t *fspace)
/* Check arguments. */
HDassert(fspace);
HDassert(fspace->hdr);
+ HDassert(cls);
/* Decrement total # of sections in free space manager */
- fspace->hdr->sect_count--;
-
- /* Drop back to using a "single" node when there's only one section */
- if(fspace->hdr->sect_count == 1) {
- H5FS_node_t *fspace_node; /* Free list size node */
- H5FS_section_info_t *sect; /* Section to move to 'single' info */
- unsigned bin; /* Bin with node */
- unsigned u; /* Local index variable */
-
- /* Sanity check */
- HDassert(fspace->single == NULL);
- HDassert(fspace->size_count == 1);
-
- /* Search for the bin with the node */
- for(u = 0; u < fspace->nbins; u++)
- if(fspace->bins[u].sect_count) {
- HDassert(fspace->bins[u].sect_count == 1);
- bin = u;
- break;
- } /* end if */
-
+ fspace->hdr->tot_sect_count--;
+ if(cls->flags & H5FS_CLS_GHOST_OBJ)
+ fspace->hdr->ghost_sect_count--;
+ else
+ fspace->hdr->serial_sect_count--;
+
+ /* Check for sections to manage */
+ if(fspace->hdr->tot_sect_count > 0) {
+ /* Drop back to using a "single" node when there's only one section */
+ if(fspace->hdr->tot_sect_count == 1) {
+ H5FS_node_t *fspace_node; /* Free list size node */
+ H5FS_section_info_t *sect; /* Section to move to 'single' info */
+ unsigned bin; /* Bin with node */
+ unsigned u; /* Local index variable */
+
+ /* Sanity check */
+ HDassert(fspace->single == NULL);
+ HDassert(fspace->tot_size_count == 1);
+
+ /* Search for the bin with the node */
+ for(u = 0; u < fspace->nbins; u++)
+ if(fspace->bins[u].tot_sect_count) {
+ /* Sanity check section size count for bin */
+ HDassert(H5SL_count(fspace->bins[u].bin_list) == 1);
+ HDassert(fspace->bins[u].tot_sect_count == 1);
+ HDassert((fspace->bins[u].serial_sect_count +
+ fspace->bins[u].ghost_sect_count) == 1);
+
+ /* Save bin index & get out */
+ bin = u;
+ break;
+ } /* end if */
#ifndef NDEBUG
- /* Sanity check rest of bins */
- for(u++ ; u < fspace->nbins; u++)
- HDassert(fspace->bins[u].sect_count == 0);
+ /* Sanity check rest of bins */
+ for(u++; u < fspace->nbins; u++) {
+ HDassert(fspace->bins[u].tot_sect_count == 0);
+ HDassert(fspace->bins[u].serial_sect_count == 0);
+ HDassert(fspace->bins[u].ghost_sect_count == 0);
+ } /* end for */
#endif /* NDEBUG */
- /* Sanity check section size count for bin */
- HDassert(H5SL_count(fspace->bins[bin].bin_list) == 1);
- HDassert(fspace->bins[bin].sect_count == 1);
+ /* Remove the free space section size node from the bin list */
+ if(NULL == (fspace_node = H5SL_remove_first(fspace->bins[bin].bin_list)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space section size node from skip list")
- /* Remove the free space section size node from the bin list */
- if(NULL == (fspace_node = H5SL_remove_first(fspace->bins[bin].bin_list)))
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space section size node from skip list")
+ /* Decrement # of section sizes in bin */
+ fspace->bins[bin].tot_sect_count = 0;
+ fspace->bins[bin].serial_sect_count = 0;
+ fspace->bins[bin].ghost_sect_count = 0;
- /* Decrement # of section sizes in bin */
- fspace->bins[bin].sect_count = 0;
+ /* Make certain there's only one section of this size */
+ HDassert(H5SL_count(fspace_node->sect_list) == 1);
+ HDassert((fspace_node->serial_count + fspace_node->ghost_count) == 1);
- /* Make certain there's only one section of this size */
- HDassert(H5SL_count(fspace_node->sect_list) == 1);
+ /* Remove the free space section from the section size list */
+ if(NULL == (sect = H5SL_remove_first(fspace_node->sect_list)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space section from skip list")
- /* Remove the free space section from the section size list */
- if(NULL == (sect = H5SL_remove_first(fspace_node->sect_list)))
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space section from skip list")
+ /* Destroy skip list for size tracking node */
+ if(H5SL_close(fspace_node->sect_list) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTCLOSEOBJ, FAIL, "can't destroy size tracking node's skip list")
- /* Destroy skip list for size tracking node */
- if(H5SL_close(fspace_node->sect_list) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTCLOSEOBJ, FAIL, "can't destroy size tracking node's skip list")
+ /* Release free space list node */
+ H5FL_FREE(H5FS_node_t, fspace_node);
- /* Release free space list node */
- H5FL_FREE(H5FS_node_t, fspace_node);
+ /* Capture single section's information */
+ fspace->single = sect;
+ } /* end if */
- /* Capture single section's information */
- fspace->single = sect;
+ /* Update the free space sections' serialized size */
+ if(!(cls->flags & H5FS_CLS_GHOST_OBJ))
+ fspace->hdr->sect_size = H5FS_serialize_size(fspace);
} /* end if */
-
- /* Update the free space sections' serialized size */
- if(fspace->hdr->sect_count > 0)
- fspace->hdr->sect_size = H5FS_serialize_size(fspace);
else
fspace->hdr->sect_size = 0;
@@ -714,7 +771,8 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_size_node_decr(H5FS_t *fspace, H5FS_node_t *fspace_node, unsigned bin)
+H5FS_size_node_decr(H5FS_t *fspace, unsigned bin, H5FS_node_t *fspace_node,
+ const H5FS_section_class_t *cls)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -723,11 +781,49 @@ H5FS_size_node_decr(H5FS_t *fspace, H5FS_node_t *fspace_node, unsigned bin)
/* Check arguments. */
HDassert(fspace);
HDassert(fspace_node);
+ HDassert(cls);
+
+ /* Decrement the # of sections in this bin */
+ /* (Different from the # of items in the bin's skiplist, since each node on
+ * the bin's skiplist is also a skiplist...)
+ */
+ fspace->bins[bin].tot_sect_count--;
+#ifdef QAK
+HDfprintf(stderr, "%s: fspace->bins[%u].sect_count = %Zu\n", FUNC, bin, fspace->bins[bin].sect_count);
+#endif /* QAK */
+
+ /* Check for 'ghost' or 'serializable' section */
+ if(cls->flags & H5FS_CLS_GHOST_OBJ) {
+ /* Decrement node's ghost section count */
+ fspace_node->ghost_count--;
+
+ /* Decrement bin's ghost section count */
+ fspace->bins[bin].ghost_sect_count--;
+
+ /* If the node has no more ghost sections, decrement number of ghost section sizes managed */
+ if(fspace_node->ghost_count == 0)
+ fspace->ghost_size_count--;
+ } /* end if */
+ else {
+ /* Decrement node's serializable section count */
+ fspace_node->serial_count--;
+
+ /* Decrement bin's serializable section count */
+ fspace->bins[bin].serial_sect_count--;
+
+ /* If the node has no more serializable sections, decrement number of serializable section sizes managed */
+ if(fspace_node->serial_count == 0)
+ fspace->serial_size_count--;
+ } /* end else */
/* Check for no more nodes on list of that size */
if(H5SL_count(fspace_node->sect_list) == 0) {
H5FS_node_t *tmp_fspace_node; /* Free space list size node */
+ /* Sanity checks */
+ HDassert(fspace_node->ghost_count == 0);
+ HDassert(fspace_node->serial_count == 0);
+
/* Remove size tracking list from bin */
tmp_fspace_node = H5SL_remove(fspace->bins[bin].bin_list, &fspace_node->sect_size);
if(tmp_fspace_node == NULL || tmp_fspace_node != fspace_node)
@@ -740,19 +836,10 @@ H5FS_size_node_decr(H5FS_t *fspace, H5FS_node_t *fspace_node, unsigned bin)
/* Release free space list node */
H5FL_FREE(H5FS_node_t, fspace_node);
- /* Decrement number of section sizes */
- fspace->size_count--;
+ /* Decrement total number of section sizes managed */
+ fspace->tot_size_count--;
} /* end if */
- /* Decrement the # of sections in this bin */
- /* (Different from the # of items in the bin's skiplist, since each node on
- * the bin's skiplist is also a skiplist...)
- */
- fspace->bins[bin].sect_count--;
-#ifdef QAK
-HDfprintf(stderr, "%s: fspace->bins[%u].sect_count = %Zu\n", FUNC, bin, fspace->bins[bin].sect_count);
-#endif /* QAK */
-
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5FS_size_node_decr() */
@@ -774,7 +861,8 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_sect_unlink_size(H5FS_t *fspace, H5FS_section_info_t *sect)
+H5FS_sect_unlink_size(H5FS_t *fspace, const H5FS_section_class_t *cls,
+ H5FS_section_info_t *sect)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -783,6 +871,7 @@ H5FS_sect_unlink_size(H5FS_t *fspace, H5FS_section_info_t *sect)
/* Check arguments. */
HDassert(fspace);
HDassert(sect);
+ HDassert(cls);
/* Check for only a single section */
if(fspace->single) {
@@ -793,8 +882,8 @@ H5FS_sect_unlink_size(H5FS_t *fspace, H5FS_section_info_t *sect)
/* Reset 'single' section pointer */
fspace->single = NULL;
- /* Decrement number of section sizes */
- fspace->size_count--;
+ /* Reset number of section sizes */
+ fspace->tot_size_count = fspace->serial_size_count = fspace->ghost_size_count = 0;
} /* end if */
else {
H5FS_node_t *fspace_node; /* Free list size node */
@@ -820,7 +909,7 @@ H5FS_sect_unlink_size(H5FS_t *fspace, H5FS_section_info_t *sect)
HGOTO_ERROR(H5E_FSPACE, H5E_NOTFOUND, FAIL, "can't find section node on size list")
/* Decrement # of sections in section size node */
- if(H5FS_size_node_decr(fspace, fspace_node, bin) < 0)
+ if(H5FS_size_node_decr(fspace, bin, fspace_node, cls) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space size node from skip list")
} /* end else */
@@ -846,7 +935,8 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_sect_unlink_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t *sect)
+H5FS_sect_unlink_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
+ const H5FS_section_class_t *cls, H5FS_section_info_t *sect)
{
H5FS_section_info_t *tmp_sect_node; /* Temporary section node */
herr_t ret_value = SUCCEED; /* Return value */
@@ -856,6 +946,7 @@ H5FS_sect_unlink_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info
/* Check arguments. */
HDassert(f);
HDassert(fspace);
+ HDassert(cls);
HDassert(sect);
/* Remove node from merge list */
@@ -872,7 +963,7 @@ HDfprintf(stderr, "%s: fspace->sect_cls[%u].serial_size = %Zu\n", FUNC, sect->ty
#endif /* QAK */
/* Update section info & check if we need less room for the serialized free space sections */
- if(H5FS_sect_decrease(fspace) < 0)
+ if(H5FS_sect_decrease(fspace, cls) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't increase free space section size on disk")
/* Decrement amount of free space managed */
@@ -903,6 +994,7 @@ done:
static herr_t
H5FS_sect_unlink(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t *sect)
{
+ const H5FS_section_class_t *cls; /* Class of section */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_unlink)
@@ -912,12 +1004,15 @@ H5FS_sect_unlink(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t *s
HDassert(fspace);
HDassert(sect);
+ /* Get section's class */
+ cls = &fspace->sect_cls[sect->type];
+
/* Remove node from size tracked data structures */
- if(H5FS_sect_unlink_size(fspace, sect) < 0)
+ if(H5FS_sect_unlink_size(fspace, cls, sect) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "can't remove section from size tracking data structures")
/* Update rest of free space manager data structures for node removal */
- if(H5FS_sect_unlink_rest(f, dxpl_id, fspace, sect) < 0)
+ if(H5FS_sect_unlink_rest(f, dxpl_id, fspace, cls, sect) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "can't remove section from non-size tracking data structures")
done:
@@ -940,7 +1035,8 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_sect_link_size_bin(H5FS_t *fspace, H5FS_section_info_t *sect)
+H5FS_sect_link_size_bin(H5FS_t *fspace, const H5FS_section_class_t *cls,
+ H5FS_section_info_t *sect)
{
H5FS_node_t *fspace_node = NULL; /* Pointer to free space node of the correct size */
unsigned bin; /* Bin to put the free space section in */
@@ -977,6 +1073,7 @@ HDfprintf(stderr, "%s: sect->size = %Hu, sect->addr = %a\n", FUNC, sect->size, s
/* Initialize the free list size node */
fspace_node->sect_size = sect->size;
+ fspace_node->serial_count = fspace_node->ghost_count = 0;
if(NULL == (fspace_node->sect_list = H5SL_create(H5SL_TYPE_HADDR, 0.5, H5FS_DEFAULT_SKIPLIST_HEIGHT)))
HGOTO_ERROR(H5E_FSPACE, H5E_CANTCREATE, FAIL, "can't create skip list for free space nodes")
@@ -985,7 +1082,7 @@ HDfprintf(stderr, "%s: sect->size = %Hu, sect->addr = %a\n", FUNC, sect->size, s
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't insert free space node into skip list")
/* Increment number of section sizes */
- fspace->size_count++;
+ fspace->tot_size_count++;
} /* end if */
/* Increment # of section in bin */
@@ -995,7 +1092,23 @@ HDfprintf(stderr, "%s: sect->size = %Hu, sect->addr = %a\n", FUNC, sect->size, s
#ifdef QAK
HDfprintf(stderr, "%s: fspace->bins[%u].sect_count = %Zu\n", FUNC, bin, fspace->bins[bin].sect_count);
#endif /* QAK */
- fspace->bins[bin].sect_count++;
+ fspace->bins[bin].tot_sect_count++;
+ if(cls->flags & H5FS_CLS_GHOST_OBJ) {
+ fspace->bins[bin].ghost_sect_count++;
+ fspace_node->ghost_count++;
+
+ /* Check for first ghost section in node */
+ if(fspace_node->ghost_count == 1)
+ fspace->ghost_size_count++;
+ } /* end if */
+ else {
+ fspace->bins[bin].serial_sect_count++;
+ fspace_node->serial_count++;
+
+ /* Check for first serializable section in node */
+ if(fspace_node->serial_count == 1)
+ fspace->serial_size_count++;
+ } /* end else */
/* Insert free space node into correct skip list */
if(H5SL_insert(fspace_node->sect_list, sect, &sect->addr) < 0)
@@ -1021,7 +1134,8 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_sect_link_size(H5FS_t *fspace, H5FS_section_info_t *sect)
+H5FS_sect_link_size(H5FS_t *fspace, const H5FS_section_class_t *cls,
+ H5FS_section_info_t *sect)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -1033,43 +1147,73 @@ H5FS_sect_link_size(H5FS_t *fspace, H5FS_section_info_t *sect)
/* Check for special cases of # of sections on free list */
#ifdef QAK
-HDfprintf(stderr, "%s: fspace->hdr->sect_count = %Hu\n", FUNC, fspace->hdr->sect_count);
+HDfprintf(stderr, "%s: fspace->tot_size_count = %Zu\n", FUNC, fspace->tot_size_count);
+HDfprintf(stderr, "%s: fspace->serial_size_count = %Zu\n", FUNC, fspace->serial_size_count);
+HDfprintf(stderr, "%s: fspace->ghost_size_count = %Zu\n", FUNC, fspace->ghost_size_count);
#endif /* QAK */
- if(fspace->hdr->sect_count == 0) {
+ if(fspace->hdr->tot_sect_count == 0) {
HDassert(fspace->single == NULL);
/* Capture single section's information */
fspace->single = sect;
/* Increment number of section sizes */
- fspace->size_count++;
+ HDassert(fspace->tot_size_count == 0);
+ HDassert(fspace->serial_size_count == 0);
+ HDassert(fspace->ghost_size_count == 0);
+ fspace->tot_size_count = 1;
+ if(cls->flags & H5FS_CLS_GHOST_OBJ)
+ fspace->ghost_size_count = 1;
+ else
+ fspace->serial_size_count = 1;
} /* end if */
else {
/* Have a single section, put it into the bins */
if(fspace->single) {
+ const H5FS_section_class_t *single_cls; /* Single section's class */
+
/* Check if we should allocate the bins */
if(fspace->bins == NULL)
/* Allocate the bins for free space sizes */
if(NULL == (fspace->bins = H5FL_SEQ_CALLOC(H5FS_bin_t, fspace->nbins)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for free space bins")
+ /* Get single section's class */
+ single_cls = &fspace->sect_cls[fspace->single->type];
+
/* Insert the current single section into the bins */
- if(H5FS_sect_link_size_bin(fspace, fspace->single) < 0)
+ if(H5FS_sect_link_size_bin(fspace, single_cls, fspace->single) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't insert free space node into skip list")
fspace->single = NULL;
/* Decrement number of section sizes */
/* (from increment in H5FS_sect_link_size_bin for inserting the single section) */
- fspace->size_count--;
+ fspace->tot_size_count--;
+ if(single_cls->flags & H5FS_CLS_GHOST_OBJ)
+ fspace->ghost_size_count--;
+ else
+ fspace->serial_size_count--;
+#ifdef QAK
+HDfprintf(stderr, "%s: After adjusting single section\n", FUNC);
+HDfprintf(stderr, "%s: fspace->tot_size_count = %Zu\n", FUNC, fspace->tot_size_count);
+HDfprintf(stderr, "%s: fspace->serial_size_count = %Zu\n", FUNC, fspace->serial_size_count);
+HDfprintf(stderr, "%s: fspace->ghost_size_count = %Zu\n", FUNC, fspace->ghost_size_count);
+#endif /* QAK */
} /* end if */
HDassert(fspace->single == NULL);
/* Put new section into bins */
- if(H5FS_sect_link_size_bin(fspace, sect) < 0)
+ if(H5FS_sect_link_size_bin(fspace, cls, sect) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't insert free space node into skip list")
} /* end else */
done:
+#ifdef QAK
+HDfprintf(stderr, "%s: Leaving\n", FUNC);
+HDfprintf(stderr, "%s: fspace->tot_size_count = %Zu\n", FUNC, fspace->tot_size_count);
+HDfprintf(stderr, "%s: fspace->serial_size_count = %Zu\n", FUNC, fspace->serial_size_count);
+HDfprintf(stderr, "%s: fspace->ghost_size_count = %Zu\n", FUNC, fspace->ghost_size_count);
+#endif /* QAK */
FUNC_LEAVE_NOAPI(ret_value)
} /* H5FS_sect_link_size() */
@@ -1090,7 +1234,8 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_sect_link_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t *sect)
+H5FS_sect_link_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, const H5FS_section_class_t *cls,
+ H5FS_section_info_t *sect)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -1111,12 +1256,12 @@ H5FS_sect_link_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t
/* Increment amount of space required to serialize all sections */
#ifdef QAK
HDfprintf(stderr, "%s: fspace->serial_size = %Zu\n", FUNC, fspace->serial_size);
-HDfprintf(stderr, "%s: fspace->sect_cls[sect->cls->type].serial_size = %Zu\n", FUNC, fspace->sect_cls[sect->cls->type].serial_size);
+HDfprintf(stderr, "%s: cls->serial_size = %Zu\n", FUNC, cls->serial_size);
#endif /* QAK */
- fspace->serial_size += fspace->sect_cls[sect->type].serial_size;
+ fspace->serial_size += cls->serial_size;
/* Update section info & check if we need more room for the serialized free space sections */
- if(H5FS_sect_increase(fspace) < 0)
+ if(H5FS_sect_increase(fspace, cls) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't increase free space section size on disk")
/* Increment amount of free space managed */
@@ -1142,8 +1287,10 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_sect_link(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t *sect)
+H5FS_sect_link(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
+ H5FS_section_info_t *sect)
{
+ const H5FS_section_class_t *cls; /* Class of section */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_link)
@@ -1153,18 +1300,21 @@ H5FS_sect_link(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t *sec
HDassert(fspace);
HDassert(sect);
+ /* Get section's class */
+ cls = &fspace->sect_cls[sect->type];
+
/* Add section to size tracked data structures */
#ifdef QAK
HDfprintf(stderr, "%s: Check 1.0 - fspace->hdr->tot_space = %Hu\n", FUNC, fspace->hdr->tot_space);
#endif /* QAK */
- if(H5FS_sect_link_size(fspace, sect) < 0)
+ if(H5FS_sect_link_size(fspace, cls, sect) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't add section to size tracking data structures")
#ifdef QAK
HDfprintf(stderr, "%s: Check 2.0 - fspace->hdr->tot_space = %Hu\n", FUNC, fspace->hdr->tot_space);
#endif /* QAK */
/* Update rest of free space manager data structures for section addition */
- if(H5FS_sect_link_rest(f, dxpl_id, fspace, sect) < 0)
+ if(H5FS_sect_link_rest(f, dxpl_id, fspace, cls, sect) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't add section to non-size tracking data structures")
#ifdef QAK
HDfprintf(stderr, "%s: Check 3.0 - fspace->hdr->tot_space = %Hu\n", FUNC, fspace->hdr->tot_space);
@@ -1280,6 +1430,9 @@ H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
} /* end if */
} while(merged);
HDassert(*sect);
+#ifdef QAK
+HDfprintf(stderr, "%s: Done merging, (*sect) = {%a, %Hu, %u, %s}\n", FUNC, (*sect)->addr, (*sect)->size, (*sect)->type, ((*sect)->state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED"));
+#endif /* QAK */
/* Check for (possibly merged) section able to shrink the size of the container */
sect_cls = &fspace->sect_cls[(*sect)->type];
@@ -1301,6 +1454,9 @@ HDfprintf(stderr, "%s: Can shrink!\n", FUNC);
} /* end if */
done:
+#ifdef QAK
+HDfprintf(stderr, "%s: Leaving, ret_value = %d\n", FUNC, ret_value);
+#endif /* QAK */
FUNC_LEAVE_NOAPI(ret_value)
} /* H5FS_sect_merge() */
@@ -1337,8 +1493,15 @@ HDfprintf(stderr, "%s: sect->size = %Hu, sect->addr = %a, sect->type = %u\n", FU
HDassert(H5F_addr_defined(sect->addr));
HDassert(sect->size);
+ /* Check if we need to go deserialize the sections */
+ if(fspace->must_deserialize) {
+ fspace->must_deserialize = FALSE;
+ if(H5FS_deserialize_bins(f, dxpl_id, fspace) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTDECODE, FAIL, "can't deserialize sections")
+ } /* end if */
+
/* Check for merging returned space with existing section node */
- if(flags & H5FS_ADD_RETURNED_SPACE && fspace->hdr->sect_count > 0) {
+ if((flags & H5FS_ADD_RETURNED_SPACE) && fspace->hdr->tot_sect_count > 0) {
#ifdef QAK
HDfprintf(stderr, "%s: Returning space\n", FUNC);
#endif /* QAK */
@@ -1365,6 +1528,10 @@ HDfprintf(stderr, "%s: fspace->hdr->tot_space = %Hu\n", FUNC, fspace->hdr->tot_s
fspace->dirty = TRUE;
done:
+#ifdef H5FS_DEBUG
+if(!(flags & H5FS_ADD_DESERIALIZING))
+ H5FS_assert(fspace);
+#endif /* H5FS_DEBUG */
FUNC_LEAVE_NOAPI(ret_value)
} /* H5FS_add() */
@@ -1419,12 +1586,17 @@ HDfprintf(stderr, "%s: bin = %u\n", FUNC, bin);
if(fspace->bins[bin].bin_list)
/* Check for large enough list of sections on list */
if((fspace_node = H5SL_greater(fspace->bins[bin].bin_list, &request))) {
+ const H5FS_section_class_t *cls; /* Class of section */
+
/* Take first node off of the list (ie. node w/lowest address) */
if(NULL == (*node = H5SL_remove_first(fspace_node->sect_list)))
HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space node from skip list")
+ /* Get section's class */
+ cls = &fspace->sect_cls[(*node)->type];
+
/* Decrement # of sections in section size node */
- if(H5FS_size_node_decr(fspace, fspace_node, bin) < 0)
+ if(H5FS_size_node_decr(fspace, bin, fspace_node, cls) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space size node from skip list")
/* Indicate that we found a node for the request */
@@ -1471,11 +1643,20 @@ HDfprintf(stderr, "%s: request = %Hu\n", FUNC, request);
HDassert(request);
HDassert(node);
+ /* Check if we need to go deserialize the sections */
+ if(fspace->must_deserialize) {
+ fspace->must_deserialize = FALSE;
+ if(H5FS_deserialize_bins(f, dxpl_id, fspace) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTDECODE, FAIL, "can't deserialize sections")
+ } /* end if */
+
/* Check for any sections on free space list */
#ifdef QAK
-HDfprintf(stderr, "%s: fspace->hdr->sect_count = %Hu\n", FUNC, fspace->hdr->sect_count);
+HDfprintf(stderr, "%s: fspace->hdr->tot_sect_count = %Hu\n", FUNC, fspace->hdr->tot_sect_count);
+HDfprintf(stderr, "%s: fspace->hdr->serial_sect_count = %Hu\n", FUNC, fspace->hdr->serial_sect_count);
+HDfprintf(stderr, "%s: fspace->hdr->ghost_sect_count = %Hu\n", FUNC, fspace->hdr->ghost_sect_count);
#endif /* QAK */
- if(fspace->hdr->sect_count > 0) {
+ if(fspace->hdr->tot_sect_count > 0) {
/* Check for single section */
if(fspace->single) {
/* See if single section is large enough */
@@ -1485,7 +1666,8 @@ HDfprintf(stderr, "%s: fspace->hdr->sect_count = %Hu\n", FUNC, fspace->hdr->sect
fspace->single = NULL;
/* Decrement number of section sizes */
- fspace->size_count--;
+ fspace->tot_size_count = 0;
+ fspace->serial_size_count = fspace->ghost_size_count = 0;
/* Found a good section */
ret_value = TRUE;
@@ -1501,16 +1683,24 @@ HDfprintf(stderr, "%s: fspace->hdr->sect_count = %Hu\n", FUNC, fspace->hdr->sect
/* Decrement # of sections on free list, if we found an object */
if(ret_value > 0) {
+ const H5FS_section_class_t *cls; /* Class of section */
+
+ /* Get section's class */
+ cls = &fspace->sect_cls[(*node)->type];
+
/* Update rest of free space manager data structures for node removal */
- if(H5FS_sect_unlink_rest(f, dxpl_id, fspace, *node) < 0)
+ if(H5FS_sect_unlink_rest(f, dxpl_id, fspace, cls, *node) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "can't remove section from non-size tracking data structures")
#ifdef QAK
-HDfprintf(stderr, "%s: (*node)->size = %Hu, (*node)->addr = %a, (*node)->cls->type = %u\n", FUNC, (*node)->size, (*node)->addr, (*node)->cls->type);
+HDfprintf(stderr, "%s: (*node)->size = %Hu, (*node)->addr = %a, (*node)->type = %u\n", FUNC, (*node)->size, (*node)->addr, (*node)->type);
#endif /* QAK */
} /* end if */
} /* end if */
done:
+#ifdef H5FS_DEBUG
+ H5FS_assert(fspace);
+#endif /* H5FS_DEBUG */
FUNC_LEAVE_NOAPI(ret_value)
} /* H5FS_find() */
@@ -1611,29 +1801,34 @@ H5FS_serialize_sect_cb(void *_item, void UNUSED *key, void *_udata)
HDassert(udata->fspace);
HDassert(udata->p);
- /* The address of the section */
- UINT64ENCODE_VAR(*udata->p, sect->addr, udata->fspace->sect_off_size);
+ /* Get section's class */
+ sect_cls = &udata->fspace->sect_cls[sect->type];
+
+ /* Check if this section should be serialized (i.e. is not a ghost section) */
+ if(!(sect_cls->flags & H5FS_CLS_GHOST_OBJ)) {
+ /* The address of the section */
+ UINT64ENCODE_VAR(*udata->p, sect->addr, udata->fspace->sect_off_size);
#ifdef QAK
HDfprintf(stderr, "%s: sect->addr = %a\n", FUNC, sect->addr);
#endif /* QAK */
- /* The type of this section */
- *(*udata->p)++ = (uint8_t)sect->type;
+ /* The type of this section */
+ *(*udata->p)++ = (uint8_t)sect->type;
#ifdef QAK
HDfprintf(stderr, "%s: sect->type = %u\n", FUNC, (unsigned)sect->type);
#endif /* QAK */
- /* Call 'serialize' callback for this section */
- sect_cls = &udata->fspace->sect_cls[sect->type];
- if(sect_cls->serialize) {
- if((*sect_cls->serialize)(sect, *udata->p) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTSERIALIZE, FAIL, "can't syncronize section")
+ /* Call 'serialize' callback for this section */
+ if(sect_cls->serialize) {
+ if((*sect_cls->serialize)(sect_cls, sect, *udata->p) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTSERIALIZE, FAIL, "can't syncronize section")
- /* Update offset in serialization buffer */
- (*udata->p) += sect_cls->serial_size;
+ /* Update offset in serialization buffer */
+ (*udata->p) += sect_cls->serial_size;
+ } /* end if */
+ else
+ HDassert(sect_cls->serial_size == 0);
} /* end if */
- else
- HDassert(sect_cls->serial_size == 0);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1660,7 +1855,6 @@ H5FS_serialize_node_cb(void *_item, void UNUSED *key, void *_udata)
{
H5FS_node_t *fspace_node = (H5FS_node_t *)_item; /* Free space size node to work on */
H5FS_iter_ud2_t *udata = (H5FS_iter_ud2_t *)_udata; /* Callback info */
- size_t node_count; /* Number of sections of this size */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5FS_serialize_node_cb)
@@ -1670,24 +1864,25 @@ H5FS_serialize_node_cb(void *_item, void UNUSED *key, void *_udata)
HDassert(udata->fspace);
HDassert(udata->p);
- /* The number of sections of this node's size */
- node_count = H5SL_count(fspace_node->sect_list);
- HDassert(node_count);
- UINT64ENCODE_VAR(*udata->p, node_count, udata->sect_cnt_size);
+ /* Check if this node has any serializable sections */
+ if(fspace_node->serial_count > 0) {
+ /* The number of serializable sections of this node's size */
+ UINT64ENCODE_VAR(*udata->p, fspace_node->serial_count, udata->sect_cnt_size);
#ifdef QAK
-HDfprintf(stderr, "%s: node_count = %Zu\n", FUNC, node_count);
+HDfprintf(stderr, "%s: fspace_node->serial_count = %Zu\n", FUNC, fspace_node->serial_count);
#endif /* QAK */
- /* The size of the sections for this node */
- UINT64ENCODE_VAR(*udata->p, fspace_node->sect_size, udata->fspace->sect_len_size);
+ /* The size of the sections for this node */
+ UINT64ENCODE_VAR(*udata->p, fspace_node->sect_size, udata->fspace->sect_len_size);
#ifdef QAK
HDfprintf(stderr, "%s: sect_size = %Hu\n", FUNC, fspace_node->sect_size);
#endif /* QAK */
- /* Iterate through all the sections of this size */
- HDassert(fspace_node->sect_list);
- if(H5SL_iterate(fspace_node->sect_list, H5FS_serialize_sect_cb, udata) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_BADITER, FAIL, "can't iterate over section nodes")
+ /* Iterate through all the sections of this size */
+ HDassert(fspace_node->sect_list);
+ if(H5SL_iterate(fspace_node->sect_list, H5FS_serialize_sect_cb, udata) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_BADITER, FAIL, "can't iterate over section nodes")
+ } /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1723,17 +1918,21 @@ H5FS_serialize_size(H5FS_t *fspace)
/* Serialized sections prefix */
sect_buf_size = fspace->sect_prefix_size;
- /* Count for each differently sized section */
- sect_buf_size += fspace->size_count * MAX(1, ((H5V_log2_gen(fspace->hdr->sect_count) + 7) / 8));
+ /* Count for each differently sized serializable section */
+#ifdef QAK
+HDfprintf(stderr, "%s: fspace->serial_size_count = %Zu\n", "H5FS_serialize_size", fspace->serial_size_count);
+HDfprintf(stderr, "%s: fspace->hdr->serial_sect_count = %Hu\n", "H5FS_serialize_size", fspace->hdr->serial_sect_count);
+#endif /* QAK */
+ sect_buf_size += fspace->serial_size_count * MAX(1, ((H5V_log2_gen(fspace->hdr->serial_sect_count) + 7) / 8));
- /* Size for each differently sized section */
- sect_buf_size += fspace->size_count * fspace->sect_len_size;
+ /* Size for each differently sized serializable section */
+ sect_buf_size += fspace->serial_size_count * fspace->sect_len_size;
/* Offsets of each section in address space */
- sect_buf_size += fspace->hdr->sect_count * fspace->sect_off_size;
+ sect_buf_size += fspace->hdr->serial_sect_count * fspace->sect_off_size;
/* Class of each section */
- sect_buf_size += fspace->hdr->sect_count * 1;
+ sect_buf_size += fspace->hdr->serial_sect_count * 1;
/* Extra space required to serialize each section */
sect_buf_size += fspace->serial_size;
@@ -1774,12 +1973,17 @@ H5FS_serialize_bins(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace)
#ifdef QAK
HDfprintf(stderr, "%s: fspace->hdr->sect_addr = %a\n", FUNC, fspace->hdr->sect_addr);
HDfprintf(stderr, "%s: fspace->hdr->sect_size = %Hu\n", FUNC, fspace->hdr->sect_size);
-HDfprintf(stderr, "%s: fspace->hdr->sect_count = %Hu\n", FUNC, fspace->hdr->sect_count);
+HDfprintf(stderr, "%s: fspace->hdr->tot_sect_count = %Hu\n", FUNC, fspace->hdr->tot_sect_count);
+HDfprintf(stderr, "%s: fspace->hdr->serial_sect_count = %Hu\n", FUNC, fspace->hdr->serial_sect_count);
+HDfprintf(stderr, "%s: fspace->hdr->ghost_sect_count = %Hu\n", FUNC, fspace->hdr->ghost_sect_count);
HDfprintf(stderr, "%s: fspace->serial_size = %Zu\n", FUNC, fspace->serial_size);
+HDfprintf(stderr, "%s: fspace->single = %p\n", FUNC, fspace->single);
+if(fspace->single)
+ HDfprintf(stderr, "%s: fspace->single = {%a, %Hu, %u, %s}\n", FUNC, fspace->single->addr, fspace->single->size, fspace->single->type, (fspace->single->state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED"));
#endif /* QAK */
/* Check for no free sections */
- if(fspace->hdr->sect_count == 0) {
+ if(fspace->hdr->serial_sect_count == 0) {
/* Check for existing serialized sections on disk to release */
if(H5F_addr_defined(fspace->hdr->sect_addr)) {
/* Free previous serialized sections disk space */
@@ -1802,9 +2006,9 @@ HDfprintf(stderr, "%s: Releasing space for serialized sections\n", FUNC);
/* Allocate space for the new serialized sections on disk */
#ifdef QAK
-HDfprintf(stderr, "%s: Allocating space for serialized sections\n", FUNC);
+HDfprintf(stderr, "%s: Allocating space for serialized sections, fspace->hdr->alloc_sect_size = %Hu\n", FUNC, fspace->hdr->alloc_sect_size);
#endif /* QAK */
- if(HADDR_UNDEF == (fspace->hdr->sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SECTS, dxpl_id, (hsize_t)fspace->hdr->alloc_sect_size)))
+ if(HADDR_UNDEF == (fspace->hdr->sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SECTS, dxpl_id, fspace->hdr->alloc_sect_size)))
HGOTO_ERROR(H5E_STORAGE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections")
} /* end if */
else {
@@ -1901,11 +2105,11 @@ HDfprintf(stderr, "%s: Allocating space for smaller serialized sections\n", FUNC
*p++ = H5FS_SECTS_VERSION;
/* Metadata status flags */
- /* XXX: Set this? */
+/* XXX: Set this? */
*p++ = 0;
/* Metadata checksum */
- /* XXX: Set this! (After all the metadata is in the buffer) */
+/* XXX: Set this! (After all the metadata is in the buffer) */
HDmemset(p, 0, 4);
p += 4;
@@ -1915,7 +2119,7 @@ HDfprintf(stderr, "%s: Allocating space for smaller serialized sections\n", FUNC
/* Set up user data for iterator */
udata.fspace = fspace;
udata.p = &p;
- udata.sect_cnt_size = MAX(1, (H5V_log2_gen(fspace->hdr->sect_count) + 7) / 8);
+ udata.sect_cnt_size = MAX(1, (H5V_log2_gen(fspace->hdr->serial_sect_count) + 7) / 8);
#ifdef QAK
HDfprintf(stderr, "%s: udata.sect_cnt_size = %u\n", FUNC, udata.sect_cnt_size);
#endif /* QAK */
@@ -2052,26 +2256,34 @@ HDfprintf(stderr, "%s: fspace->hdr->sect_size = %Hu\n", FUNC, fspace->hdr->sect_
HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, FAIL, "incorrect header address for free space sections")
/* Check for any serialized sections */
- if(fspace->hdr->sect_count > 0) {
- hsize_t old_sect_count; /* Section count from header */
+ if(fspace->hdr->serial_sect_count > 0) {
+ hsize_t old_tot_sect_count; /* Total section count from header */
+ hsize_t old_serial_sect_count; /* Total serializable section count from header */
+ hsize_t old_ghost_sect_count; /* Total ghost section count from header */
hsize_t old_tot_space; /* Total space managed from header */
unsigned sect_cnt_size; /* The size of the section size counts */
/* Compute the size of the section counts */
- sect_cnt_size = MAX(1, (H5V_log2_gen(fspace->hdr->sect_count) + 7) / 8);
+ sect_cnt_size = MAX(1, (H5V_log2_gen(fspace->hdr->serial_sect_count) + 7) / 8);
#ifdef QAK
HDfprintf(stderr, "%s: sect_cnt_size = %u\n", FUNC, sect_cnt_size);
HDfprintf(stderr, "%s: fspace->sect_len_size = %u\n", FUNC, fspace->sect_len_size);
#endif /* QAK */
/* Reset the section count, the "add" routine will update it */
- old_sect_count = fspace->hdr->sect_count;
+ old_tot_sect_count = fspace->hdr->tot_sect_count;
+ old_serial_sect_count = fspace->hdr->serial_sect_count;
+ old_ghost_sect_count = fspace->hdr->ghost_sect_count;
old_tot_space = fspace->hdr->tot_space;
#ifdef QAK
-HDfprintf(stderr, "%s: fspace->hdr->sect_count = %Hu\n", FUNC, fspace->hdr->sect_count);
+HDfprintf(stderr, "%s: fspace->hdr->tot_sect_count = %Hu\n", FUNC, fspace->hdr->tot_sect_count);
+HDfprintf(stderr, "%s: fspace->hdr->serial_sect_count = %Hu\n", FUNC, fspace->hdr->serial_sect_count);
+HDfprintf(stderr, "%s: fspace->hdr->ghost_sect_count = %Hu\n", FUNC, fspace->hdr->ghost_sect_count);
HDfprintf(stderr, "%s: fspace->hdr->tot_space = %Hu\n", FUNC, fspace->hdr->tot_space);
#endif /* QAK */
- fspace->hdr->sect_count = 0;
+ fspace->hdr->tot_sect_count = 0;
+ fspace->hdr->serial_sect_count = 0;
+ fspace->hdr->ghost_sect_count = 0;
fspace->hdr->tot_space = 0;
/* Walk through the buffer, deserializing sections */
@@ -2099,6 +2311,7 @@ HDfprintf(stderr, "%s: sect_size = %Hu\n", FUNC, sect_size);
H5FS_section_info_t *new_sect; /* Section that was deserialized */
haddr_t sect_addr; /* Address of free space section in the address space */
unsigned sect_type; /* Type of free space section */
+ unsigned des_flags; /* Flags from deserialize callback */
/* The address of the section */
UINT64DECODE_VAR(p, sect_addr, fspace->sect_off_size);
@@ -2113,23 +2326,30 @@ HDfprintf(stderr, "%s: sect_type = %u\n", FUNC, sect_type);
#endif /* QAK */
/* Call 'deserialize' callback for this section */
+ des_flags = 0;
HDassert(fspace->sect_cls[sect_type].deserialize);
- if(NULL == (new_sect = (*fspace->sect_cls[sect_type].deserialize)(p, sect_addr, sect_size)))
+ if(NULL == (new_sect = (*fspace->sect_cls[sect_type].deserialize)(&fspace->sect_cls[sect_type], dxpl_id, p, sect_addr, sect_size, &des_flags)))
HGOTO_ERROR(H5E_FSPACE, H5E_CANTDECODE, FAIL, "can't deserialize section")
/* Update offset in serialization buffer */
p += fspace->sect_cls[sect_type].serial_size;
+#ifdef QAK
+HDfprintf(stderr, "%s: fspace->sect_cls[%u].serial_size = %Zu\n", FUNC, sect_type, fspace->sect_cls[sect_type].serial_size);
+#endif /* QAK */
- /* Insert section in free space manager */
- if(H5FS_add(f, dxpl_id, fspace, new_sect, H5FS_ADD_DESERIALIZING, NULL) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't add section to free space manager")
+ /* Insert section in free space manager, unless requested not to */
+ if(!(des_flags & H5FS_DESERIALIZE_NO_ADD))
+ if(H5FS_add(f, dxpl_id, fspace, new_sect, H5FS_ADD_DESERIALIZING, NULL) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't add section to free space manager")
} /* end for */
} while(p < (sect_buf + old_sect_size));
/* Sanity check */
HDassert((size_t)(p - sect_buf) == old_sect_size);
HDassert(old_sect_size == fspace->hdr->sect_size);
- HDassert(old_sect_count == fspace->hdr->sect_count);
+ HDassert(old_tot_sect_count == fspace->hdr->tot_sect_count);
+ HDassert(old_serial_sect_count == fspace->hdr->serial_sect_count);
+ HDassert(old_ghost_sect_count == fspace->hdr->ghost_sect_count);
HDassert(old_tot_space == fspace->hdr->tot_space);
} /* end if */
@@ -2236,7 +2456,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5FS_iterate(H5FS_t *fspace, H5FS_operator_t op, void *op_data)
+H5FS_iterate(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_operator_t op, void *op_data)
{
H5FS_iter_ud3_t udata; /* User data for callbacks */
herr_t ret_value = SUCCEED; /* Return value */
@@ -2247,6 +2467,13 @@ H5FS_iterate(H5FS_t *fspace, H5FS_operator_t op, void *op_data)
HDassert(fspace);
HDassert(op);
+ /* Check if we need to go deserialize the sections */
+ if(fspace->must_deserialize) {
+ fspace->must_deserialize = FALSE;
+ if(H5FS_deserialize_bins(f, dxpl_id, fspace) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTDECODE, FAIL, "can't deserialize sections")
+ } /* end if */
+
#ifdef QAK
HDfprintf(stderr, "%s: fspace->hdr->sect_count = %Hu\n", FUNC, fspace->hdr->sect_count);
#endif /* QAK */
@@ -2257,7 +2484,7 @@ HDfprintf(stderr, "%s: fspace->hdr->sect_count = %Hu\n", FUNC, fspace->hdr->sect
udata.op_data = op_data;
/* Iterate over sections, if there are any */
- if(fspace->hdr->sect_count) {
+ if(fspace->hdr->tot_sect_count) {
/* Check for whether to iterate over a single section */
if(fspace->single) {
#ifdef QAK
@@ -2316,7 +2543,7 @@ H5FS_get_sect_count(const H5FS_t *fspace, hsize_t *nsects)
HDassert(nsects);
/* Get the section count */
- *nsects = fspace->hdr->sect_count;
+ *nsects = fspace->hdr->tot_sect_count;
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -2324,6 +2551,152 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5FS_sect_change_class
+ *
+ * Purpose: Make appropriate adjustments to internal data structures when
+ * a section changes class
+ *
+ * Return: Success: non-negative
+ *
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Monday, July 10, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FS_sect_change_class(H5FS_t *fspace, H5FS_section_info_t *sect, unsigned new_class)
+{
+ const H5FS_section_class_t *old_cls; /* Old class of section */
+ const H5FS_section_class_t *new_cls; /* New class of section */
+ unsigned old_class; /* Old class ID of section */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_sect_change_class)
+
+ /* Check arguments. */
+ HDassert(fspace);
+ HDassert(fspace->must_deserialize == FALSE);
+ HDassert(sect);
+ HDassert(sect->type < fspace->hdr->nclasses);
+ HDassert(new_class < fspace->hdr->nclasses);
+#ifdef QAK
+HDfprintf(stderr, "%s: Called\n", "H5FS_sect_change_class");
+#endif /* QAK */
+
+ /* Get class info */
+ old_class = sect->type;
+ old_cls = &fspace->sect_cls[sect->type];
+ new_cls = &fspace->sect_cls[new_class];
+
+ /* Check if the section's class change will affect the # of serializable or ghost sections */
+ if((old_cls->flags & H5FS_CLS_GHOST_OBJ) != (new_cls->flags & H5FS_CLS_GHOST_OBJ)) {
+ hbool_t to_ghost; /* Flag if the section is changing to a ghost section */
+
+ /* Determine if this section is becoming a ghost or is becoming serializable */
+ if(old_cls->flags & H5FS_CLS_GHOST_OBJ)
+ to_ghost = FALSE;
+ else
+ to_ghost = TRUE;
+#ifdef QAK
+HDfprintf(stderr, "%s: to_ghost = %u\n", "H5FS_sect_change_class", to_ghost);
+#endif /* QAK */
+
+ /* Check for single vs. multiple sections managed */
+ if(fspace->single) {
+ /* Adjust serializable/ghost counts */
+ if(to_ghost) {
+ fspace->serial_size_count = 0;
+ fspace->ghost_size_count = 1;
+ fspace->hdr->serial_sect_count = 0;
+ fspace->hdr->ghost_sect_count = 1;
+ } /* end if */
+ else {
+ fspace->serial_size_count = 1;
+ fspace->ghost_size_count = 0;
+ fspace->hdr->serial_sect_count = 1;
+ fspace->hdr->ghost_sect_count = 0;
+ } /* end else */
+ } /* end if */
+ else {
+ H5FS_node_t *fspace_node; /* Free list size node */
+ unsigned bin; /* Bin to put the free space section in */
+
+ /* Sanity check */
+ HDassert(fspace->bins);
+
+ /* Determine correct bin which holds items of at least the section's size */
+ bin = H5V_log2_gen(sect->size);
+ HDassert(bin < fspace->nbins);
+ HDassert(fspace->bins[bin].bin_list);
+
+ /* Get space node for section's size */
+ fspace_node = H5SL_search(fspace->bins[bin].bin_list, &sect->size);
+ HDassert(fspace_node);
+
+ /* Adjust serializable/ghost counts */
+ if(to_ghost) {
+ /* Adjust global section count totals */
+ fspace->hdr->serial_sect_count--;
+ fspace->hdr->ghost_sect_count++;
+
+ /* Adjust bin's section count totals */
+ fspace->bins[bin].serial_sect_count--;
+ fspace->bins[bin].ghost_sect_count++;
+
+ /* Adjust section size node's section count totals */
+ fspace_node->serial_count--;
+ fspace_node->ghost_count++;
+
+ /* Check if we switched a section size node's status */
+ if(fspace_node->serial_count == 0)
+ fspace->serial_size_count--;
+ if(fspace_node->ghost_count == 1)
+ fspace->ghost_size_count++;
+ } /* end if */
+ else {
+ /* Adjust global section count totals */
+ fspace->hdr->serial_sect_count++;
+ fspace->hdr->ghost_sect_count--;
+
+ /* Adjust bin's section count totals */
+ fspace->bins[bin].serial_sect_count++;
+ fspace->bins[bin].ghost_sect_count--;
+
+ /* Adjust section size node's section count totals */
+ fspace_node->serial_count++;
+ fspace_node->ghost_count--;
+
+ /* Check if we switched a section size node's status */
+ if(fspace_node->serial_count == 1)
+ fspace->serial_size_count++;
+ if(fspace_node->ghost_count == 0)
+ fspace->ghost_size_count--;
+ } /* end else */
+ } /* end else */
+ } /* end if */
+
+ /* Change the section's class */
+ sect->type = new_class;
+
+ /* Change the serialized size of sections */
+ fspace->serial_size -= fspace->sect_cls[old_class].serial_size;
+ fspace->serial_size += fspace->sect_cls[new_class].serial_size;
+
+ /* Update current space used for free space sections */
+ fspace->hdr->sect_size = H5FS_serialize_size(fspace);
+
+ /* Mark free space as dirty also */
+ fspace->dirty = TRUE;
+
+#ifdef H5FS_DEBUG
+ H5FS_assert(fspace);
+#endif /* H5FS_DEBUG */
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5FS_sect_change_class() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5FS_flush_cb
*
* Purpose: Skip list iterator callback to syncronize free space sections
@@ -2353,9 +2726,11 @@ H5FS_flush_cb(void *_item, void UNUSED *key, void *_udata)
HDassert(udata->f);
/* Serialize the bins for this free space manager, if they are dirty */
- if(fspace->dirty)
+ if(fspace->dirty) {
+ HDassert(fspace->must_deserialize == FALSE);
if(H5FS_serialize_bins(udata->f, udata->dxpl_id, fspace) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTSERIALIZE, FAIL, "can't syncronize bins")
+ } /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -2439,7 +2814,7 @@ HDfprintf(stderr, "%s: Deleting free space manager\n", FUNC);
#ifdef QAK
HDfprintf(stderr, "%s: fs_hdr->sect_addr = %a\n", FUNC, fs_hdr->sect_addr);
#endif /* QAK */
- if(fs_hdr->sect_count > 0) {
+ if(fs_hdr->serial_sect_count > 0) {
HDassert(H5F_addr_defined(fs_hdr->sect_addr));
HDassert(fs_hdr->sect_size > 0);
if(H5MF_xfree(f, H5FD_MEM_FSPACE_SECTS, dxpl_id, fs_hdr->sect_addr, fs_hdr->alloc_sect_size)<0)
@@ -2486,16 +2861,24 @@ H5FS_close(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace)
/* Check arguments. */
HDassert(f);
HDassert(fspace);
+#ifdef QAK
+HDfprintf(stderr, "%s: Entering\n", FUNC);
+#endif /* QAK */
/* Remove the free space manager from the list of open free space managers */
if(H5FS_open_remove(fspace) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't remove free space header from open list")
/* Serialize the sections in the bins, if necessary */
- if(fspace->dirty)
+ if(fspace->dirty) {
+ HDassert(fspace->must_deserialize == FALSE);
if(H5FS_serialize_bins(f, dxpl_id, fspace) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTSERIALIZE, FAIL, "can't syncronize bins")
+ } /* end if */
+#ifdef QAK
+HDfprintf(stderr, "%s: fspace->hdr->tot_sect_count = %Hu\n", FUNC, fspace->hdr->tot_sect_count);
+#endif /* QAK */
/* Check for single section to free */
if(fspace->single) {
/* Call the 'free' callback for the section */
@@ -2525,6 +2908,14 @@ H5FS_close(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace)
if(H5AC_unpin_entry(f, fspace->hdr) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPIN, FAIL, "unable to unpin free space header")
+ /* Terminate the section classes for this free space list */
+ for(u = 0; u < fspace->hdr->nclasses ; u++) {
+ /* Call the class termination routine, if there is one */
+ if(fspace->sect_cls[u].term_cls)
+ if((fspace->sect_cls[u].term_cls)(&fspace->sect_cls[u]) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "unable to finalize section class")
+ } /* end for */
+
/* Release the memory for the free space section classes */
fspace->sect_cls = H5FL_SEQ_FREE(H5FS_section_class_t, fspace->sect_cls);
@@ -2556,3 +2947,181 @@ H5FS_debug_test(const H5FS_t *fspace)
FUNC_LEAVE_NOAPI(SUCCEED)
}
+#ifdef H5FS_DEBUG
+
+/*-------------------------------------------------------------------------
+ * Function: H5FS_assert
+ *
+ * Purpose: Verify that the sections managed are mostly sane
+ *
+ * Return: Non-negative on success, negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jul 17 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FS_assert(const H5FS_t *fspace)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_assert)
+#ifdef QAK
+HDfprintf(stderr, "%s: fspace->hdr->tot_sect_count = %Hu\n", "H5FS_assert", fspace->hdr->tot_sect_count);
+#endif /* QAK */
+
+ /* Check for single vs. multiple sections managed */
+ if(fspace->single) {
+ const H5FS_section_class_t *cls; /* Class of section */
+
+ HDassert(fspace->tot_size_count == 1);
+ HDassert(fspace->hdr->tot_sect_count == 1);
+
+ /* Get section's class */
+ cls = &fspace->sect_cls[fspace->single->type];
+#ifdef QAK
+HDfprintf(stderr, "%s: fspace->single->size = %Hu, fspace->single->addr = %a, fspace->single->type = %u\n", "H5FS_assert", fspace->single->size, fspace->single->addr, fspace->single->type);
+#endif /* QAK */
+
+ /* Sanity checks on counts */
+ if(cls->flags & H5FS_CLS_GHOST_OBJ) {
+ HDassert(fspace->serial_size_count == 0);
+ HDassert(fspace->ghost_size_count == 1);
+ HDassert(fspace->hdr->serial_sect_count == 0);
+ HDassert(fspace->hdr->ghost_sect_count == 1);
+ } /* end if */
+ else {
+ HDassert(fspace->serial_size_count == 1);
+ HDassert(fspace->ghost_size_count == 0);
+ HDassert(fspace->hdr->serial_sect_count == 1);
+ HDassert(fspace->hdr->ghost_sect_count == 0);
+ } /* end else */
+ } /* end if */
+ else if(fspace->bins) {
+ hsize_t acc_tot_sect_count; /* Accumulated total section count from bins */
+ hsize_t acc_serial_sect_count; /* Accumulated serializable section count from bins */
+ hsize_t acc_ghost_sect_count; /* Accumulated ghost section count from bins */
+ size_t acc_tot_size_count; /* Accumulated total section size count from bins */
+ size_t acc_serial_size_count; /* Accumulated serializable section size count from bins */
+ size_t acc_ghost_size_count; /* Accumulated ghost section size count from bins */
+ unsigned u; /* Local index variable */
+
+ /* Walk through all sections in bins */
+ acc_tot_sect_count = 0;
+ acc_serial_sect_count = 0;
+ acc_ghost_sect_count = 0;
+ acc_tot_size_count = 0;
+ acc_serial_size_count = 0;
+ acc_ghost_size_count = 0;
+ for(u = 0; u < fspace->nbins; u++) {
+ acc_tot_sect_count += fspace->bins[u].tot_sect_count;
+ acc_serial_sect_count += fspace->bins[u].serial_sect_count;
+ acc_ghost_sect_count += fspace->bins[u].ghost_sect_count;
+ if(fspace->bins[u].bin_list) {
+ H5SL_node_t *curr_size_node; /* Current section size node in skip list */
+ size_t bin_serial_count; /* # of serializable sections in this bin */
+ size_t bin_ghost_count; /* # of ghost sections in this bin */
+
+ acc_tot_size_count += H5SL_count(fspace->bins[u].bin_list);
+
+ /* Walk through the sections in this bin */
+ curr_size_node = H5SL_first(fspace->bins[u].bin_list);
+ bin_serial_count = 0;
+ bin_ghost_count = 0;
+ while(curr_size_node != NULL) {
+ H5FS_node_t *fspace_node; /* Section size node */
+ H5SL_node_t *curr_sect_node; /* Current section node in skip list */
+ size_t size_serial_count; /* # of serializable sections of this size */
+ size_t size_ghost_count; /* # of ghost sections of this size */
+
+ /* Get section size node */
+ fspace_node = H5SL_item(curr_size_node);
+
+ /* Check sections on list */
+ curr_sect_node = H5SL_first(fspace_node->sect_list);
+ size_serial_count = 0;
+ size_ghost_count = 0;
+ while(curr_sect_node != NULL) {
+ H5FS_section_class_t *cls; /* Class of section */
+ H5FS_section_info_t *sect; /* Section */
+
+ /* Get section node & it's class */
+ sect = H5SL_item(curr_sect_node);
+ cls = &fspace->sect_cls[sect->type];
+#ifdef QAK
+HDfprintf(stderr, "%s: sect->size = %Hu, sect->addr = %a, sect->type = %u\n", "H5FS_assert", sect->size, sect->addr, sect->type);
+#endif /* QAK */
+
+ /* Sanity check section */
+ HDassert(H5F_addr_defined(sect->addr));
+ HDassert(fspace_node->sect_size == sect->size);
+ if(cls->valid)
+ (*cls->valid)(cls, sect);
+
+ /* Add to correct count */
+ if(cls->flags & H5FS_CLS_GHOST_OBJ)
+ size_ghost_count++;
+ else
+ size_serial_count++;
+
+ /* Get the next section node in the list */
+ curr_sect_node = H5SL_next(curr_sect_node);
+ } /* end while */
+
+ /* Check the number of serializable & ghost sections of this size */
+ HDassert(fspace_node->serial_count == size_serial_count);
+ HDassert(fspace_node->ghost_count == size_ghost_count);
+
+ /* Add to global count of serializable & ghost section sizes */
+ if(fspace_node->serial_count > 0)
+ acc_serial_size_count++;
+ if(fspace_node->ghost_count > 0)
+ acc_ghost_size_count++;
+
+ /* Add to bin's serializable & ghost counts */
+ bin_serial_count += size_serial_count;
+ bin_ghost_count += size_ghost_count;
+
+ /* Get the next section size node in the list */
+ curr_size_node = H5SL_next(curr_size_node);
+ } /* end while */
+
+ /* Check the number of serializable & ghost sections in this bin */
+ HDassert(fspace->bins[u].tot_sect_count == (bin_serial_count + bin_ghost_count));
+ HDassert(fspace->bins[u].serial_sect_count == bin_serial_count);
+ HDassert(fspace->bins[u].ghost_sect_count == bin_ghost_count);
+ } /* end if */
+ } /* end for */
+
+ /* Check counts from bins vs. global counts */
+ HDassert(fspace->tot_size_count == acc_tot_size_count);
+ HDassert(fspace->serial_size_count == acc_serial_size_count);
+ HDassert(fspace->ghost_size_count == acc_ghost_size_count);
+ HDassert(fspace->hdr->tot_sect_count == acc_tot_sect_count);
+ HDassert(fspace->hdr->serial_sect_count == acc_serial_sect_count);
+ HDassert(fspace->hdr->ghost_sect_count == acc_ghost_sect_count);
+ } /* end else */
+ else {
+ /* Check counts are zero */
+ HDassert(fspace->hdr->tot_sect_count == 0);
+ HDassert(fspace->hdr->serial_sect_count == 0);
+ HDassert(fspace->hdr->ghost_sect_count == 0);
+ } /* end else */
+
+ /* General assumptions about the section size counts */
+ HDassert(fspace->tot_size_count >= fspace->serial_size_count);
+ HDassert(fspace->tot_size_count >= fspace->ghost_size_count);
+
+ /* General assumptions about the section counts */
+ HDassert(fspace->hdr->tot_sect_count >= fspace->hdr->serial_sect_count);
+ HDassert(fspace->hdr->tot_sect_count >= fspace->hdr->ghost_sect_count);
+ HDassert(fspace->hdr->tot_sect_count == (fspace->hdr->serial_sect_count + fspace->hdr->ghost_sect_count));
+
+ /* Make certain that the number of sections on the address list is correct */
+ if(fspace->merge_list)
+ HDassert(fspace->hdr->tot_sect_count == H5SL_count(fspace->merge_list));
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5FS_assert() */
+#endif /* H5FS_DEBUG */
+
diff --git a/src/H5FScache.c b/src/H5FScache.c
index c87cdc0..c6fd297 100644
--- a/src/H5FScache.c
+++ b/src/H5FScache.c
@@ -173,8 +173,14 @@ HDfprintf(stderr, "%s: Load free space header, addr = %a\n", FUNC, addr);
/* Total space tracked */
H5F_DECODE_LENGTH(f, p, hdr->tot_space);
- /* # of free space sections tracked */
- H5F_DECODE_LENGTH(f, p, hdr->sect_count);
+ /* Total # of free space sections tracked */
+ H5F_DECODE_LENGTH(f, p, hdr->tot_sect_count);
+
+ /* # of serializable free space sections tracked */
+ H5F_DECODE_LENGTH(f, p, hdr->serial_sect_count);
+
+ /* # of ghost free space sections tracked */
+ H5F_DECODE_LENGTH(f, p, hdr->ghost_sect_count);
/* # of section classes */
UINT16DECODE(p, hdr->nclasses);
@@ -279,8 +285,14 @@ HDfprintf(stderr, "%s: Flushing free space header, addr = %a, destroy = %u\n", F
/* Total space tracked */
H5F_ENCODE_LENGTH(f, p, hdr->tot_space);
- /* # of free space sections tracked */
- H5F_ENCODE_LENGTH(f, p, hdr->sect_count);
+ /* Total # of free space sections tracked */
+ H5F_ENCODE_LENGTH(f, p, hdr->tot_sect_count);
+
+ /* # of serializable free space sections tracked */
+ H5F_ENCODE_LENGTH(f, p, hdr->serial_sect_count);
+
+ /* # of ghost free space sections tracked */
+ H5F_ENCODE_LENGTH(f, p, hdr->ghost_sect_count);
/* # of section classes */
UINT16ENCODE(p, hdr->nclasses);
diff --git a/src/H5FSdbg.c b/src/H5FSdbg.c
index a946cf0..69c0f80 100644
--- a/src/H5FSdbg.c
+++ b/src/H5FSdbg.c
@@ -122,8 +122,14 @@ H5FS_hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent,
"Total free space tracked:",
hdr->tot_space);
HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
- "Number of free space sections tracked:",
- hdr->sect_count);
+ "Total number of free space sections tracked:",
+ hdr->tot_sect_count);
+ HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
+ "Number of serializable free space sections tracked:",
+ hdr->serial_sect_count);
+ HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
+ "Number of ghost free space sections tracked:",
+ hdr->ghost_sect_count);
HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
"Number of free space section classes:",
hdr->nclasses);
diff --git a/src/H5FSpkg.h b/src/H5FSpkg.h
index 0f9aaad..c3d9f1c 100644
--- a/src/H5FSpkg.h
+++ b/src/H5FSpkg.h
@@ -60,7 +60,9 @@
/* Free space header specific fields */ \
+ 1 /* Client ID */ \
+ H5F_SIZEOF_SIZE(f) /* Total free space tracked */ \
- + H5F_SIZEOF_SIZE(f) /* # of sections tracked */ \
+ + H5F_SIZEOF_SIZE(f) /* Total # of sections tracked */ \
+ + H5F_SIZEOF_SIZE(f) /* # of serializable sections tracked */ \
+ + H5F_SIZEOF_SIZE(f) /* # of ghost sections tracked */ \
+ 2 /* Number of section classes */ \
+ 2 /* Shrink percent */ \
+ 2 /* Expand percent */ \
@@ -82,7 +84,9 @@ typedef struct H5FS_hdr_t {
/* Statistics */
hsize_t tot_space; /* Total amount of space tracked */
- hsize_t sect_count; /* # of sections tracked */
+ hsize_t tot_sect_count; /* Total # of sections tracked */
+ hsize_t serial_sect_count; /* # of serializable sections tracked */
+ hsize_t ghost_sect_count; /* # of un-serializable sections tracked */
/* Creation information */
H5FS_client_t client; /* Type of user of this free space manager */
@@ -100,7 +104,9 @@ typedef struct H5FS_hdr_t {
/* Free space section bin info */
typedef struct H5FS_bin_t {
- size_t sect_count; /* Total # of sections in this bin */
+ size_t tot_sect_count; /* Total # of sections in this bin */
+ size_t serial_sect_count; /* # of serializable sections in this bin */
+ size_t ghost_sect_count; /* # of un-serializable sections in this bin */
H5SL_t *bin_list; /* Skip list of differently sized sections */
} H5FS_bin_t;
@@ -112,11 +118,14 @@ struct H5FS_t {
/* Computed/cached values */
haddr_t addr; /* Address of free space header on disk */
unsigned nbins; /* Number of bins */
- size_t serial_size; /* Total serialized size of all section nodes */
- size_t size_count; /* Number of differently sized sections */
+ size_t serial_size; /* Total size of all serializable sections */
+ size_t tot_size_count; /* Total number of differently sized sections */
+ size_t serial_size_count; /* Total number of differently sized serializable sections */
+ size_t ghost_size_count; /* Total number of differently sized un-serializable sections */
unsigned sect_prefix_size; /* Size of the section serialization prefix (in bytes) */
unsigned sect_off_size; /* Size of a section offset (in bytes) */
unsigned sect_len_size; /* Size of a section length (in bytes) */
+ hbool_t must_deserialize; /* Sections must be deserialized */
hbool_t dirty; /* Space information is dirty */
/* Memory data structures (not stored directly) */
diff --git a/src/H5FSprivate.h b/src/H5FSprivate.h
index ada35e0..25383cc 100644
--- a/src/H5FSprivate.h
+++ b/src/H5FSprivate.h
@@ -38,9 +38,13 @@
/* Library Private Macros */
/**************************/
+/* Flags for H5FS_section_class_t 'flags' field */
+#define H5FS_CLS_GHOST_OBJ 0x01 /* Objects in this class shouldn't be
+ * serialized to the file.
+ */
+
/* Flags for H5FS_add() */
#define H5FS_ADD_DESERIALIZING 0x01 /* Free space is being deserialized
- * (for package use only)
*/
#define H5FS_ADD_RETURNED_SPACE 0x02 /* Section was previously allocated
* and is being returned to the
@@ -49,6 +53,13 @@
* object)
*/
+/* Flags for deserialize callback */
+#define H5FS_DESERIALIZE_NO_ADD 0x01 /* Don't add section to free space
+ * manager after it's deserialized
+ * (its only here for it's side-
+ * effects).
+ */
+
/****************************/
/* Library Private Typedefs */
@@ -63,20 +74,24 @@ typedef struct H5FS_section_info_t H5FS_section_info_t;
/* Free space section class info */
typedef struct H5FS_section_class_t {
/* Class variables */
- const unsigned type; /* Type of free space section */
- size_t serial_size; /* Size of serialized form of section */
+ const unsigned type; /* Type of free space section */
+ size_t serial_size; /* Size of serialized form of section */
+ unsigned flags; /* Class flags */
+ void *cls_private; /* Class private information */
/* Class methods */
- herr_t (*init_cls)(struct H5FS_section_class_t *, const void *); /* Routine to initialize class-specific settings */
+ herr_t (*init_cls)(struct H5FS_section_class_t *, void *); /* Routine to initialize class-specific settings */
+ herr_t (*term_cls)(struct H5FS_section_class_t *); /* Routine to terminate class-specific settings */
/* Object methods */
- herr_t (*serialize)(const H5FS_section_info_t *, uint8_t *); /* Routine to serialize a "live" section into a buffer */
- H5FS_section_info_t *(*deserialize)(const uint8_t *, haddr_t, hsize_t); /* Routine to deserialize a buffer into a "live" section */
+ herr_t (*serialize)(const struct H5FS_section_class_t *, const H5FS_section_info_t *, uint8_t *); /* Routine to serialize a "live" section into a buffer */
+ H5FS_section_info_t *(*deserialize)(const struct H5FS_section_class_t *, hid_t dxpl_id, const uint8_t *, haddr_t, hsize_t, unsigned *); /* Routine to deserialize a buffer into a "live" section */
htri_t (*can_merge)(H5FS_section_info_t *, H5FS_section_info_t *, void *); /* Routine to determine if two nodes are mergable */
herr_t (*merge)(H5FS_section_info_t *, H5FS_section_info_t *, void *); /* Routine to merge two nodes */
htri_t (*can_shrink)(H5FS_section_info_t *, void *); /* Routine to determine if node can shrink container */
herr_t (*shrink)(H5FS_section_info_t **, void *); /* Routine to shrink container */
herr_t (*free)(H5FS_section_info_t *); /* Routine to free node */
+ herr_t (*valid)(const struct H5FS_section_class_t *, const H5FS_section_info_t *); /* Routine to check if a section is valid */
herr_t (*debug)(const H5FS_section_info_t *, FILE *, int , int ); /* Routine to dump debugging information about a section */
} H5FS_section_class_t;
@@ -127,15 +142,17 @@ H5FL_SEQ_EXTERN(H5FS_section_class_t);
/***************************************/
H5_DLL H5FS_t *H5FS_create(H5F_t *f, hid_t dxpl_id, haddr_t *fs_addr,
const H5FS_create_t *fs_create, size_t nclasses,
- const H5FS_section_class_t *classes[], const void *cls_init_udata);
+ const H5FS_section_class_t *classes[], void *cls_init_udata);
H5_DLL H5FS_t *H5FS_open(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr,
- size_t nclasses, const H5FS_section_class_t *classes[], const void *cls_init_udata);
+ size_t nclasses, const H5FS_section_class_t *classes[], void *cls_init_udata);
H5_DLL herr_t H5FS_add(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
H5FS_section_info_t *node, unsigned flags, void *op_data);
H5_DLL htri_t H5FS_find(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
hsize_t request, H5FS_section_info_t **node);
-H5_DLL herr_t H5FS_iterate(H5FS_t *fspace, H5FS_operator_t op, void *op_data);
+H5_DLL herr_t H5FS_iterate(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_operator_t op, void *op_data);
H5_DLL herr_t H5FS_get_sect_count(const H5FS_t *fspace, hsize_t *nsects);
+H5_DLL herr_t H5FS_sect_change_class(H5FS_t *fspace, H5FS_section_info_t *sect,
+ unsigned new_class);
H5_DLL herr_t H5FS_flush(H5F_t *f, hid_t dxpl_id, unsigned flags);
H5_DLL herr_t H5FS_delete(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr);
H5_DLL herr_t H5FS_close(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace);
diff --git a/src/H5Gdeprec.c b/src/H5Gdeprec.c
index 98d2cf8..4f2b837 100644
--- a/src/H5Gdeprec.c
+++ b/src/H5Gdeprec.c
@@ -83,6 +83,7 @@ H5Glink2(hid_t cur_loc_id, const char *cur_name, H5L_link_t type,
herr_t ret_value;
FUNC_ENTER_API(H5Glink2, FAIL)
+ H5TRACE5("e","isLlis",cur_loc_id,cur_name,type,new_loc_id,new_name);
if(type == H5L_LINK_HARD) {
if((ret_value = H5Lcreate_hard(cur_loc_id, cur_name, new_loc_id, new_name, H5P_DEFAULT)) < 0)
diff --git a/src/H5HFdbg.c b/src/H5HFdbg.c
index c8945fd..2d878f9 100644
--- a/src/H5HFdbg.c
+++ b/src/H5HFdbg.c
@@ -435,7 +435,7 @@ H5HF_dblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream,
HDfprintf(stream, "%*sFree Blocks (offset, size):\n", indent, "");
/* Iterate over the free space sections, to detect overlaps with this block */
- if(H5FS_iterate(hdr->fspace, H5HF_dblock_debug_cb, &udata) < 0)
+ if(H5FS_iterate(f, dxpl_id, hdr->fspace, H5HF_dblock_debug_cb, &udata) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_BADITER, FAIL, "can't iterate over heap's free space")
/* Close the free space information */
@@ -488,7 +488,6 @@ H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream,
{
H5HF_hdr_t *hdr = NULL; /* Fractal heap header info */
H5HF_indirect_t *iblock = NULL; /* Fractal heap direct block info */
- size_t dblock_size; /* Current direct block size */
char temp_str[64]; /* Temporary string, for formatting */
size_t u, v; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
@@ -557,7 +556,6 @@ H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream,
temp_str,
iblock->ents[off].addr);
} /* end for */
- dblock_size *= 2;
} /* end for */
HDfprintf(stream, "%*sIndirect Block Entries:\n", indent, "");
if(iblock->nrows > hdr->man_dtable.max_direct_rows) {
@@ -633,8 +631,8 @@ H5HF_sects_debug_cb(const H5FS_section_info_t *_sect, void *_udata)
HDfprintf(udata->stream, "%*s%-*s %s\n", udata->indent, "", udata->fwidth,
"Section type:",
(sect->sect_info.type == H5HF_FSPACE_SECT_SINGLE ? "single" :
- (sect->sect_info.type == H5HF_FSPACE_SECT_RANGE ? "range" :
- (sect->sect_info.type == H5HF_FSPACE_SECT_INDIRECT ? "indirect" : "unknown"))));
+ (sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW ? "first row" :
+ (sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW ? "normal row" : "unknown"))));
HDfprintf(udata->stream, "%*s%-*s %s\n", udata->indent, "", udata->fwidth,
"Section state:",
(sect->sect_info.state == H5FS_SECT_LIVE ? "live" : "serialized"));
@@ -697,7 +695,7 @@ H5HF_sects_debug(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr,
udata.fwidth = fwidth;
/* Iterate over all the free space sections */
- if(H5FS_iterate(hdr->fspace, H5HF_sects_debug_cb, &udata) < 0)
+ if(H5FS_iterate(f, dxpl_id, hdr->fspace, H5HF_sects_debug_cb, &udata) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_BADITER, FAIL, "can't iterate over heap's free space")
/* Close the free space information */
diff --git a/src/H5HFdblock.c b/src/H5HFdblock.c
index c8abfd4..590d8f3 100644
--- a/src/H5HFdblock.c
+++ b/src/H5HFdblock.c
@@ -96,6 +96,7 @@ H5HF_man_dblock_create(hid_t dxpl_id, H5HF_hdr_t *hdr, H5HF_indirect_t *par_iblo
{
H5HF_free_section_t *sec_node; /* Pointer to free space section for block */
H5HF_direct_t *dblock = NULL; /* Pointer to direct block */
+ haddr_t dblock_addr; /* Direct block's address */
size_t free_space; /* Free space in new block */
herr_t ret_value = SUCCEED; /* Return value */
@@ -105,7 +106,6 @@ H5HF_man_dblock_create(hid_t dxpl_id, H5HF_hdr_t *hdr, H5HF_indirect_t *par_iblo
* Check arguments.
*/
HDassert(hdr);
- HDassert(addr_p);
/*
* Allocate file and memory data structures.
@@ -148,22 +148,22 @@ HDmemset(dblock->blk, 0, dblock->size);
#endif /* H5_USING_PURIFY */
/* Allocate space for the header on disk */
- if(HADDR_UNDEF == (*addr_p = H5MF_alloc(hdr->f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)dblock->size)))
+ if(HADDR_UNDEF == (dblock_addr = H5MF_alloc(hdr->f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)dblock->size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block")
#ifdef QAK
-HDfprintf(stderr, "%s: direct block address = %a\n", FUNC, *addr_p);
+HDfprintf(stderr, "%s: direct block address = %a\n", FUNC, dblock_addr);
#endif /* QAK */
/* Attach to parent indirect block, if there is one */
dblock->parent = par_iblock;
if(dblock->parent)
- if(H5HF_man_iblock_attach(dblock->parent, par_entry, *addr_p) < 0)
+ if(H5HF_man_iblock_attach(dblock->parent, par_entry, dblock_addr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTATTACH, FAIL, "can't attach direct block to parent indirect block")
dblock->par_entry = par_entry;
/* Create a new 'single' section for the free space in the block */
if(NULL == (sec_node = H5HF_sect_single_new((dblock->block_off + H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr)),
- free_space, dblock->parent, dblock->par_entry, *addr_p, dblock->size)))
+ free_space, dblock->parent, dblock->par_entry, dblock_addr, dblock->size)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create section for new direct block's free space")
/* Check what to do with section node */
@@ -172,18 +172,22 @@ HDfprintf(stderr, "%s: direct block address = %a\n", FUNC, *addr_p);
*ret_sec_node = sec_node;
else {
/* Add new free space to the heap's list of space */
- if(H5HF_space_add(hdr, dxpl_id, sec_node) < 0)
+ if(H5HF_space_add(hdr, dxpl_id, sec_node, 0) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add direct block free space to global list")
} /* end else */
/* Cache the new fractal heap direct block */
- if(H5AC_set(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, *addr_p, dblock, H5AC__NO_FLAGS_SET) < 0)
+ if(H5AC_set(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add fractal heap direct block to cache")
/* Increase the allocated heap size */
if(H5HF_hdr_inc_alloc(hdr, dblock->size) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't increase allocated heap size")
+ /* Set the address of of direct block, if requested */
+ if(addr_p)
+ *addr_p = dblock_addr;
+
done:
if(ret_value < 0)
if(dblock)
@@ -242,7 +246,6 @@ HDfprintf(stderr, "%s: root direct block\n", FUNC);
HDassert(!H5HF_man_iter_ready(&hdr->next_block));
/* Reset root pointer information */
- hdr->man_dtable.curr_root_rows = 0;
hdr->man_dtable.table_addr = HADDR_UNDEF;
/* Reset header information back to "empty heap" state */
@@ -282,7 +285,7 @@ HDfprintf(stderr, "%s: Reversing iterator\n", FUNC);
par_col = dblock->par_entry % hdr->man_dtable.cparam.width;
/* Add a 'range' section for the space in the destroyed block */
- if(H5HF_sect_range_add(hdr, dxpl_id, dblock->block_off, hdr->man_dtable.row_dblock_free[par_row],
+ if(H5HF_sect_range_add(hdr, dxpl_id, dblock->block_off, hdr->man_dtable.row_tot_dblock_free[par_row],
dblock->parent, par_row, par_col, 1) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "can't create range section for direct block being destroyed")
} /* end else */
@@ -380,7 +383,7 @@ HDfprintf(stderr, "%s: root direct block, dblock_addr = %a\n", FUNC, dblock_addr
hdr->man_dtable.table_addr = dblock_addr;
/* Extend heap to cover new direct block */
- if(H5HF_hdr_adjust_heap(hdr, (hsize_t)hdr->man_dtable.cparam.start_block_size, (hssize_t)hdr->man_dtable.row_dblock_free[0]) < 0)
+ if(H5HF_hdr_adjust_heap(hdr, (hsize_t)hdr->man_dtable.cparam.start_block_size, (hssize_t)hdr->man_dtable.row_tot_dblock_free[0]) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, FAIL, "can't increase space to cover root direct block")
} /* end if */
/* Root entry already exists, allocate direct block from root indirect block */
diff --git a/src/H5HFdtable.c b/src/H5HFdtable.c
index 1461cd7..4c41805 100644
--- a/src/H5HFdtable.c
+++ b/src/H5HFdtable.c
@@ -116,8 +116,10 @@ H5HF_dtable_init(H5HF_dtable_t *dtable)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create doubling table block size table")
if(NULL == (dtable->row_block_off = H5MM_malloc(dtable->max_root_rows * sizeof(hsize_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create doubling table block offset table")
- if(NULL == (dtable->row_dblock_free = H5MM_malloc(dtable->max_root_rows * sizeof(hsize_t))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create doubling table direct block free space table")
+ if(NULL == (dtable->row_tot_dblock_free = H5MM_malloc(dtable->max_root_rows * sizeof(hsize_t))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create doubling table total direct block free space table")
+ if(NULL == (dtable->row_max_dblock_free = H5MM_malloc(dtable->max_root_rows * sizeof(size_t))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create doubling table max. direct block free space table")
tmp_block_size = dtable->cparam.start_block_size;
acc_block_off = dtable->cparam.start_block_size * dtable->cparam.width;
dtable->row_block_size[0] = dtable->cparam.start_block_size;
@@ -205,8 +207,11 @@ H5HF_dtable_dest(H5HF_dtable_t *dtable)
/* Free the block offset lookup table for the doubling table */
H5MM_xfree(dtable->row_block_off);
- /* Free the direct block free space lookup table for the doubling table */
- H5MM_xfree(dtable->row_dblock_free);
+ /* Free the total direct block free space lookup table for the doubling table */
+ H5MM_xfree(dtable->row_tot_dblock_free);
+
+ /* Free the max. direct block free space lookup table for the doubling table */
+ H5MM_xfree(dtable->row_max_dblock_free);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5HF_dtable_dest() */
diff --git a/src/H5HFhdr.c b/src/H5HFhdr.c
index d5af3fe..fc67aed 100644
--- a/src/H5HFhdr.c
+++ b/src/H5HFhdr.c
@@ -68,10 +68,6 @@
/* Local Prototypes */
/********************/
-/* Free space section routines */
-static herr_t H5HF_hdr_skip_ranges(H5HF_hdr_t *hdr, hid_t dxpl_id,
- H5HF_indirect_t *iblock, unsigned start_entry, unsigned nentries);
-
/*********************/
/* Package Variables */
@@ -153,13 +149,15 @@ done:
*
*-------------------------------------------------------------------------
*/
-static hsize_t
-H5HF_hdr_compute_free_space(H5HF_hdr_t *hdr, hsize_t iblock_size)
+static herr_t
+H5HF_hdr_compute_free_space(H5HF_hdr_t *hdr, unsigned iblock_row)
{
hsize_t acc_heap_size; /* Accumumated heap space */
+ hsize_t iblock_size; /* Size of indirect block to calculate for */
hsize_t acc_dblock_free; /* Accumumated direct block free space */
+ size_t max_dblock_free; /* Max. direct block free space */
unsigned curr_row; /* Current row in block */
- hsize_t ret_value; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_hdr_compute_free_space)
@@ -167,22 +165,27 @@ H5HF_hdr_compute_free_space(H5HF_hdr_t *hdr, hsize_t iblock_size)
* Check arguments.
*/
HDassert(hdr);
- HDassert(iblock_size > hdr->man_dtable.cparam.max_direct_size);
+ HDassert(iblock_row >= hdr->man_dtable.max_direct_rows);
/* Set the free space in direct blocks */
acc_heap_size = 0;
acc_dblock_free = 0;
+ max_dblock_free = 0;
+ iblock_size = hdr->man_dtable.row_block_size[iblock_row];
curr_row = 0;
while(acc_heap_size < iblock_size) {
acc_heap_size += hdr->man_dtable.row_block_size[curr_row] *
hdr->man_dtable.cparam.width;
- acc_dblock_free += hdr->man_dtable.row_dblock_free[curr_row] *
+ acc_dblock_free += hdr->man_dtable.row_tot_dblock_free[curr_row] *
hdr->man_dtable.cparam.width;
+ if(hdr->man_dtable.row_max_dblock_free[curr_row] > max_dblock_free)
+ max_dblock_free = hdr->man_dtable.row_max_dblock_free[curr_row];
curr_row++;
} /* end while */
- /* Set return value */
- ret_value = acc_dblock_free;
+ /* Set direct block free space values for indirect block */
+ hdr->man_dtable.row_tot_dblock_free[iblock_row] = acc_dblock_free;
+ hdr->man_dtable.row_max_dblock_free[iblock_row] = max_dblock_free;
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_hdr_compute_free_space() */
@@ -226,15 +229,19 @@ H5HF_hdr_finish_init(H5HF_hdr_t *hdr)
/* Set the free space in direct blocks */
for(u = 0; u < hdr->man_dtable.max_root_rows; u++) {
- if(u < hdr->man_dtable.max_direct_rows)
- hdr->man_dtable.row_dblock_free[u] = hdr->man_dtable.row_block_size[u] -
+ if(u < hdr->man_dtable.max_direct_rows) {
+ hdr->man_dtable.row_tot_dblock_free[u] = hdr->man_dtable.row_block_size[u] -
H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr);
+ hdr->man_dtable.row_max_dblock_free[u] = hdr->man_dtable.row_tot_dblock_free[u];
+ } /* end if */
else
- hdr->man_dtable.row_dblock_free[u] = H5HF_hdr_compute_free_space(hdr, hdr->man_dtable.row_block_size[u]);
+ if(H5HF_hdr_compute_free_space(hdr, u) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize direct block free space for indirect block")
#ifdef QAK
HDfprintf(stderr, "%s: row_block_size[%Zu] = %Hu\n", FUNC, u, hdr->man_dtable.row_block_size[u]);
HDfprintf(stderr, "%s: row_block_off[%Zu] = %Hu\n", FUNC, u, hdr->man_dtable.row_block_off[u]);
-HDfprintf(stderr, "%s: row_dblock_free[%Zu] = %Hu\n", FUNC, u, hdr->man_dtable.row_dblock_free[u]);
+HDfprintf(stderr, "%s: row_tot_dblock_free[%Zu] = %Hu\n", FUNC, u, hdr->man_dtable.row_tot_dblock_free[u]);
+HDfprintf(stderr, "%s: row_max_dblock_free[%Zu] = %Zu\n", FUNC, u, hdr->man_dtable.row_max_dblock_free[u]);
#endif /* QAK */
} /* end for */
@@ -652,10 +659,7 @@ herr_t
H5HF_hdr_skip_blocks(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_indirect_t *iblock,
unsigned start_entry, unsigned nentries)
{
- hsize_t sect_off; /* Offset of free section in heap */
- unsigned curr_row; /* Current row in indirect block */
- unsigned curr_col; /* Current column in indirect block */
- unsigned u; /* Local index variables */
+ hsize_t sect_off; /* Offset of section in heap space */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_skip_blocks)
@@ -670,46 +674,11 @@ HDfprintf(stderr, "%s: start_entry = %u, nentries = %u\n", FUNC, start_entry, ne
HDassert(iblock);
HDassert(nentries);
- /* Compute starting column & row */
- curr_row = start_entry / hdr->man_dtable.cparam.width;
- curr_col = start_entry % hdr->man_dtable.cparam.width;
-
- /* Initialize information for rows skipped over */
- sect_off = iblock->block_off;
- for(u = 0; u < curr_row; u++)
- sect_off += hdr->man_dtable.row_block_size[u] * hdr->man_dtable.cparam.width;
- sect_off += hdr->man_dtable.row_block_size[curr_row] * curr_col;
-#ifdef QAK
-HDfprintf(stderr, "%s: sect_off = %Zu\n", FUNC, sect_off);
-#endif /* QAK */
-
- /* Loop over the blocks to skip */
- for(u = start_entry; u < (start_entry + nentries); /* u is advanced in loop */) {
- unsigned row_entries; /* Number of entries in a particular row */
-
- /* Compute number of entries in (possible partial) current row */
- row_entries = MIN(hdr->man_dtable.cparam.width - curr_col, (start_entry + nentries) - u);
+ /* Add 'indirect' section for blocks skipped in this row */
+ if(H5HF_sect_indirect_add(hdr, dxpl_id, iblock, start_entry, nentries, &sect_off) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section for indirect block's free space")
#ifdef QAK
-HDfprintf(stderr, "%s: u = %u\n", FUNC, u);
-HDfprintf(stderr, "%s: curr_col = %u, curr_row = %u\n", FUNC, curr_col, curr_row);
-HDfprintf(stderr, "%s: row_entries = %u, hdr->man_dtable.row_dblock_free[%u] = %Hu\n", FUNC, row_entries, curr_row, hdr->man_dtable.row_dblock_free[curr_row]);
-#endif /* QAK */
-
- /* Add 'range' section for blocks skipped in this row */
- if(H5HF_sect_range_add(hdr, dxpl_id, sect_off, hdr->man_dtable.row_dblock_free[curr_row],
- iblock, curr_row, curr_col, row_entries) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create range section for indirect block's free space")
-
- /* Advance row & column position */
- sect_off += row_entries * hdr->man_dtable.row_block_size[curr_row];
- curr_row++;
- curr_col = 0; /* (first partial row aligns this) */
-
- /* Increment index variable */
- u += row_entries;
- } /* end for */
-#ifdef QAK
-HDfprintf(stderr, "%s: sect_off = %Zu\n", FUNC, sect_off);
+HDfprintf(stderr, "%s: sect_off = %Hu\n", FUNC, sect_off);
#endif /* QAK */
/* Advance the new block iterator */
@@ -722,120 +691,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5HF_hdr_skip_ranges
- *
- * Purpose: Add skipped indirect ranges to free space for heap
- *
- * Return: SUCCEED/FAIL
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Apr 4 2006
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HF_hdr_skip_ranges(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_indirect_t *iblock,
- unsigned start_entry, unsigned nentries)
-{
- hsize_t sect_off; /* Offset of free section in heap */
- size_t row_dblock_free_space; /* Size of free space for row of direct blocks in a row */
- size_t acc_row_dblock_free_space; /* Accumulated size of free space for row of direct blocks in a row */
- unsigned curr_row; /* Current row in indirect block */
- unsigned curr_col; /* Current column in indirect block */
- unsigned u, w; /* Local index variables */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_skip_ranges)
-#ifdef QAK
-HDfprintf(stderr, "%s: start_entry = %u, nentries = %u\n", FUNC, start_entry, nentries);
-#endif /* QAK */
-
- /*
- * Check arguments.
- */
- HDassert(hdr);
- HDassert(iblock);
- HDassert(nentries);
-
- /* Compute starting column & row */
- curr_row = start_entry / hdr->man_dtable.cparam.width;
- curr_col = start_entry % hdr->man_dtable.cparam.width;
-#ifdef QAK
-HDfprintf(stderr, "%s: curr_col = %u, curr_row = %u\n", FUNC, curr_col, curr_row);
-#endif /* QAK */
-
- /* Initialize information for rows skipped over */
- sect_off = iblock->block_off;
- for(u = 0; u < curr_row; u++)
- sect_off += hdr->man_dtable.row_block_size[u] * hdr->man_dtable.cparam.width;
- sect_off += hdr->man_dtable.row_block_size[curr_row] * curr_col;
-#ifdef QAK
-HDfprintf(stderr, "%s: sect_off = %Zu\n", FUNC, sect_off);
-#endif /* QAK */
-
- /* Loop over the blocks to skip */
- for(u = start_entry; u < (start_entry + nentries); /* u is advanced in loop */) {
- unsigned row_entries; /* Number of entries in a particular row */
- unsigned num_rows; /* Number of rows in indirect blocks referenced */
-
- /* Compute number of rows in indirect blocks covered by entry */
- num_rows = (H5V_log2_of2((uint32_t)hdr->man_dtable.row_block_size[curr_row]) -
- H5V_log2_of2(hdr->man_dtable.cparam.start_block_size)) - 1;
-
- /* Compute number of entries in (possible partial) current row */
- row_entries = MIN(hdr->man_dtable.cparam.width - curr_col, (start_entry + nentries) - u);
-#ifdef QAK
-HDfprintf(stderr, "%s: u = %u\n", FUNC, u);
-HDfprintf(stderr, "%s: curr_col = %u, curr_row = %u\n", FUNC, curr_col, curr_row);
-HDfprintf(stderr, "%s: row_entries = %u, num_rows = %u\n", FUNC, row_entries, num_rows);
-#endif /* QAK */
-
- /* Loop over rows in indirect blocks covered */
- acc_row_dblock_free_space = 0;
- for(w = 0; w < num_rows; w++) {
-
- /* Compute free space in direct blocks for this row */
- row_dblock_free_space = hdr->man_dtable.cparam.width * hdr->man_dtable.row_dblock_free[w];
- acc_row_dblock_free_space += row_dblock_free_space;
-#ifdef QAK
-HDfprintf(stderr, "%s: w = %u\n", FUNC, w);
-HDfprintf(stderr, "%s: hdr->man_dtable.row_dblock_free[%u] = %Zu\n", FUNC, w, hdr->man_dtable.row_dblock_free[w]);
-#endif /* QAK */
-
- /* Add "indirect" free space section for blocks in this row */
-
- /* Create free list section node for blocks skipped over */
- if(H5HF_sect_indirect_add(hdr, dxpl_id, (sect_off + hdr->man_dtable.row_block_off[w]),
- hdr->man_dtable.row_dblock_free[w], iblock, curr_row, curr_col, row_entries, w, num_rows) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section for indirect block's free space")
- } /* end for */
-#ifdef QAK
-HDfprintf(stderr, "%s: acc_row_dblock_free_space = %Zu\n", FUNC, acc_row_dblock_free_space);
-#endif /* QAK */
-
- /* Advance row & column position */
- sect_off += row_entries * hdr->man_dtable.row_block_size[curr_row];
- curr_row++;
- curr_col = 0; /* (first partial row aligns this) */
-
- /* Advance outer loop index */
- u += row_entries;
- } /* end for */
-#ifdef QAK
-HDfprintf(stderr, "%s: sect_off = %Zu\n", FUNC, sect_off);
-#endif /* QAK */
-
- /* Advance the new block iterator */
- if(H5HF_hdr_inc_iter(hdr, (sect_off - hdr->man_iter_off), nentries) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't increase allocated heap size")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_hdr_skip_ranges() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5HF_hdr_update_iter
*
* Purpose: Update state of heap to account for current iterator
@@ -1036,8 +891,8 @@ HDfprintf(stderr, "%s: child_rows_needed = %u\n", FUNC, child_rows_needed);
HDfprintf(stderr, "%s: child_entry = %u\n", FUNC, child_entry);
#endif /* QAK */
- /* Add skipped indirect ranges to heap's free space */
- if(H5HF_hdr_skip_ranges(hdr, dxpl_id, iblock, next_entry, (child_entry - next_entry)) < 0)
+ /* Add skipped indirect blocks to heap's free space */
+ if(H5HF_hdr_skip_blocks(hdr, dxpl_id, iblock, next_entry, (child_entry - next_entry)) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't add skipped blocks to heap's free space")
} /* end if */
else {
diff --git a/src/H5HFiblock.c b/src/H5HFiblock.c
index 1fa7c35..f48b4c2 100644
--- a/src/H5HFiblock.c
+++ b/src/H5HFiblock.c
@@ -112,6 +112,10 @@ H5HF_iblock_incr(H5HF_indirect_t *iblock)
/* Increment reference count on shared indirect block */
iblock->rc++;
+#ifdef QAK
+HDfprintf(stderr, "%s: iblock->addr = %a, iblock->rc = %Zu\n", FUNC, iblock->addr, iblock->rc);
+HDfprintf(stderr, "%s: iblock->block_off = %Hu\n", FUNC, iblock->block_off);
+#endif /* QAK */
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -143,6 +147,10 @@ H5HF_iblock_decr(H5HF_indirect_t *iblock)
/* Decrement reference count on shared indirect block */
iblock->rc--;
+#ifdef QAK
+HDfprintf(stderr, "%s: iblock->addr = %a, iblock->rc = %Zu\n", FUNC, iblock->addr, iblock->rc);
+HDfprintf(stderr, "%s: iblock->block_off = %Hu\n", FUNC, iblock->block_off);
+#endif /* QAK */
/* Mark block as evictable again when no child blocks depend on it */
if(iblock->rc == 0) {
@@ -350,11 +358,11 @@ HDfprintf(stderr, "%s: have_direct_block = %u\n", FUNC, (unsigned)have_direct_bl
/* Compute free space in direct blocks referenced from entries in root indirect block */
acc_dblock_free = 0;
for(u = 0; u < nrows; u++)
- acc_dblock_free += hdr->man_dtable.row_dblock_free[u] * hdr->man_dtable.cparam.width;
+ acc_dblock_free += hdr->man_dtable.row_tot_dblock_free[u] * hdr->man_dtable.cparam.width;
/* Account for potential initial direct block */
if(have_direct_block)
- acc_dblock_free -= hdr->man_dtable.row_dblock_free[0];
+ acc_dblock_free -= hdr->man_dtable.row_tot_dblock_free[0];
/* Extend heap to cover new root indirect block */
if(H5HF_hdr_adjust_heap(hdr, hdr->man_dtable.row_block_off[nrows], (hssize_t)acc_dblock_free) < 0)
@@ -487,7 +495,7 @@ HDfprintf(stderr, "%s: new_addr = %a\n", FUNC, new_addr);
unsigned row = u / hdr->man_dtable.cparam.width; /* Row for current entry */
iblock->ents[u].addr = HADDR_UNDEF;
- acc_dblock_free += hdr->man_dtable.row_dblock_free[row];
+ acc_dblock_free += hdr->man_dtable.row_tot_dblock_free[row];
} /* end for */
/* Mark indirect block as dirty */
@@ -580,7 +588,7 @@ HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows);
/* Compute free space in rows to delete */
acc_dblock_free = 0;
for(u = new_nrows; u < iblock->nrows; u++)
- acc_dblock_free += hdr->man_dtable.row_dblock_free[u] * hdr->man_dtable.cparam.width;
+ acc_dblock_free += hdr->man_dtable.row_tot_dblock_free[u] * hdr->man_dtable.cparam.width;
/* Compute size of buffer needed for new indirect block */
iblock->nrows = new_nrows;
@@ -686,7 +694,7 @@ HDfprintf(stderr, "%s: Reverting root indirect block\n", FUNC);
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't reset block iterator")
/* Extend heap to just cover first direct block */
- if(H5HF_hdr_adjust_heap(hdr, (hsize_t)hdr->man_dtable.cparam.start_block_size, (hssize_t)hdr->man_dtable.row_dblock_free[0]) < 0)
+ if(H5HF_hdr_adjust_heap(hdr, (hsize_t)hdr->man_dtable.cparam.start_block_size, (hssize_t)hdr->man_dtable.row_tot_dblock_free[0]) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, FAIL, "can't increase space to cover root direct block")
done:
@@ -698,80 +706,10 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5HF_man_iblock_alloc_range
- *
- * Purpose: Allocate a "single" section for an object, out of a "range"
- * section
- *
- * Note: Creates necessary direct & indirect blocks
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Mar 28 2006
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5HF_man_iblock_alloc_range(H5HF_hdr_t *hdr, hid_t dxpl_id,
- H5HF_free_section_t **sec_node)
-{
- H5HF_indirect_t *iblock = NULL; /* Pointer to indirect block */
- haddr_t dblock_addr; /* Direct block's address */
- H5HF_free_section_t *dblock_sec_node = NULL; /* Pointer to direct block's section node */
- H5HF_free_section_t *old_sec_node = *sec_node; /* Pointer to old section node */
- unsigned cur_entry; /* Current entry in indirect block */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_alloc_range)
-
- /*
- * Check arguments.
- */
- HDassert(hdr);
- HDassert(sec_node && *sec_node);
-
- /* Check for serialized section */
- if(old_sec_node->sect_info.state == H5FS_SECT_SERIALIZED) {
- /* Revive range section */
- if(H5HF_sect_range_revive(hdr, dxpl_id, old_sec_node) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTREVIVE, FAIL, "can't revive range section")
- } /* end if */
-
- /* Compute info about range */
- cur_entry = (old_sec_node->u.range.row * hdr->man_dtable.cparam.width) + old_sec_node->u.range.col;
-
- /* Get a pointer to the indirect block covering the range */
- iblock = old_sec_node->u.range.iblock;
- HDassert(iblock);
-
-#ifdef QAK
-HDfprintf(stderr, "%s: cur_entry = %u\n", FUNC, cur_entry);
-HDfprintf(stderr, "%s: old_sec_node->u.range.num_entries = %u\n", FUNC, old_sec_node->u.range.num_entries);
-#endif /* QAK */
- /* Create direct block of appropriate size */
- if(H5HF_man_dblock_create(dxpl_id, hdr, iblock, cur_entry, &dblock_addr, &dblock_sec_node) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap direct block")
-
- /* Reduce (& possibly re-add) 'range' section */
- if(H5HF_sect_range_reduce(hdr, dxpl_id, old_sec_node) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce indirect section node")
-
- /* Point 'sec_node' at new direct block section node */
- *sec_node = dblock_sec_node;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_man_iblock_alloc_range() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5HF_man_iblock_alloc_indirect
+ * Function: H5HF_man_iblock_alloc_indirect2
*
- * Purpose: Allocate a "single" section for an object, out of an
- * "indirect" section, possibly creating "range" section as a
- * byproduct.
+ * Purpose: Allocate a "single" section for an object, out of a
+ * "row" section.
*
* Note: Creates necessary direct & indirect blocks
*
@@ -779,110 +717,70 @@ done:
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
- * Apr 4 2006
+ * July 6 2006
*
*-------------------------------------------------------------------------
*/
herr_t
-H5HF_man_iblock_alloc_indirect(H5HF_hdr_t *hdr, hid_t dxpl_id,
- H5HF_free_section_t **sec_node)
+H5HF_man_iblock_alloc_row(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t **sec_node)
{
H5HF_indirect_t *iblock; /* Pointer to indirect block */
- H5HF_indirect_t *child_iblock; /* Pointer to child indirect block */
- haddr_t child_iblock_addr; /* Address of child indirect block */
- haddr_t dblock_addr; /* New direct block's address */
- H5HF_free_section_t *dblock_sec_node = NULL; /* Pointer to direct block's section node */
H5HF_free_section_t *old_sec_node = *sec_node; /* Pointer to old indirect section node */
- unsigned curr_entry; /* Current entry in indirect block */
- unsigned dblock_entry; /* Entry of direct block in child indirect block */
+ unsigned dblock_entry; /* Entry for direct block */
+ hbool_t iblock_held = FALSE; /* Flag to indicate that indirect block is held */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_alloc_indirect)
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_alloc_row)
/*
* Check arguments.
*/
HDassert(hdr);
- HDassert(sec_node && *sec_node);
+ HDassert(sec_node && old_sec_node);
+ HDassert(old_sec_node->u.row.row < hdr->man_dtable.max_direct_rows);
/* Check for serialized section */
if(old_sec_node->sect_info.state == H5FS_SECT_SERIALIZED) {
/* Revive indirect section */
- if(H5HF_sect_indirect_revive(hdr, dxpl_id, old_sec_node) < 0)
+ if(H5HF_sect_row_revive(hdr, dxpl_id, old_sec_node) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTREVIVE, FAIL, "can't revive indirect section")
} /* end if */
- /* Compute info about range */
- curr_entry = (old_sec_node->u.indirect.row * hdr->man_dtable.cparam.width) + old_sec_node->u.indirect.col;
-
/* Get a pointer to the indirect block covering the section */
- iblock = old_sec_node->u.indirect.iblock;
+ if(NULL == (iblock = H5HF_sect_row_get_iblock(old_sec_node)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't retrieve indirect block for row section")
#ifdef QAK
-HDfprintf(stderr, "%s: curr_entry = %u\n", FUNC, curr_entry);
HDfprintf(stderr, "%s: iblock->addr = %a\n", FUNC, iblock->addr);
HDfprintf(stderr, "%s: iblock->block_off = %Hu\n", FUNC, iblock->block_off);
HDfprintf(stderr, "%s: iblock->parent = %p\n", FUNC, iblock->parent);
-HDfprintf(stderr, "%s: iblock->ents[curr_entry].addr = %a\n", FUNC, iblock->ents[curr_entry].addr);
-HDfprintf(stderr, "%s: old_sec_node->u.indirect.indir_nrows = %u\n", FUNC, old_sec_node->u.indirect.indir_nrows);
-HDfprintf(stderr, "%s: old_sec_node->u.indirect.num_entries = %u\n", FUNC, old_sec_node->u.indirect.num_entries);
+HDfprintf(stderr, "%s: iblock->rc = %Zu\n", FUNC, iblock->rc);
#endif /* QAK */
- /* Check if indirect block for this indirect section has already been created */
- if(H5F_addr_defined(iblock->ents[curr_entry].addr)) {
- /* Look up existing child indirect block */
- child_iblock_addr = iblock->ents[curr_entry].addr;
- if(NULL == (child_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, child_iblock_addr, old_sec_node->u.indirect.indir_nrows, iblock, curr_entry, H5AC_WRITE)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
- } /* end if */
- else {
- /* Create child indirect block */
- if(H5HF_man_iblock_create(hdr, dxpl_id, iblock, curr_entry, old_sec_node->u.indirect.indir_nrows, old_sec_node->u.indirect.indir_nrows, &child_iblock_addr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap indirect block")
-
- /* Lock new child indirect block */
- if(NULL == (child_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, child_iblock_addr, old_sec_node->u.indirect.indir_nrows, iblock, curr_entry, H5AC_WRITE)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
-#ifdef QAK
-HDfprintf(stderr, "%s: child_iblock->child_free_space = %Hu\n", FUNC, child_iblock->child_free_space);
-#endif /* QAK */
- } /* end else */
+ /* Hold indirect block in memory, until direct block can point to it */
+ if(H5HF_iblock_incr(iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block")
+ iblock_held = TRUE;
- /* Compute entry for new direct block in child indirect block */
- dblock_entry = old_sec_node->u.indirect.indir_row * hdr->man_dtable.cparam.width;
+ /* Reduce (& possibly re-add) 'row' section */
+ if(H5HF_sect_row_reduce(hdr, dxpl_id, old_sec_node, &dblock_entry) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce row section node")
- /* Create direct block of correct size */
- /* (creates a 'single' free space section also) */
+ /* Create direct block & single section */
#ifdef QAK
-HDfprintf(stderr, "%s: old_sec_node->u.indirect.indir_row = %u\n", FUNC, old_sec_node->u.indirect.indir_row);
-HDfprintf(stderr, "%s: hdr->man_dtable.row_block_size[old_sec_node->u.indirect.indir_row] = %Hu\n", FUNC, hdr->man_dtable.row_block_size[old_sec_node->u.indirect.indir_row]);
-HDfprintf(stderr, "%s: old_sec_node->sect_info.addr = %a\n", FUNC, old_sec_node->sect_info.addr);
-HDfprintf(stderr, "%s: dblock_entry = %u\n", FUNC, dblock_entry);
+HDfprintf(stderr, "%s: Allocating direct block, dblock_entry = %u\n", FUNC, dblock_entry);
#endif /* QAK */
- if(H5HF_man_dblock_create(dxpl_id, hdr, child_iblock, dblock_entry, &dblock_addr, &dblock_sec_node) < 0)
+ if(H5HF_man_dblock_create(dxpl_id, hdr, iblock, dblock_entry, NULL, sec_node) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap direct block")
- /* Create "range" section for other direct blocks in row of child indirect block */
- if(H5HF_sect_range_add(hdr, dxpl_id, (child_iblock->block_off + hdr->man_dtable.row_block_off[old_sec_node->u.indirect.indir_row]
- + hdr->man_dtable.row_block_size[old_sec_node->u.indirect.indir_row]),
- old_sec_node->sect_info.size, child_iblock, old_sec_node->u.indirect.indir_row,
- 1, hdr->man_dtable.cparam.width - 1) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create range section for indirect block's free space")
-
- /* Reduce (& possibly re-add) 'indirect' section */
- if(H5HF_sect_indirect_reduce(hdr, dxpl_id, old_sec_node) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce indirect section node")
-
- /* Release the child indirect block (marked as dirty) */
- if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, child_iblock_addr, child_iblock, H5AC__DIRTIED_FLAG) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
-
- /* Point 'sec_node' at new direct block section node */
- *sec_node = dblock_sec_node;
-
done:
+ /* Release hold on indirect block */
+ if(iblock_held)
+ if(H5HF_iblock_decr(iblock) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't decrement reference count on shared indirect block")
+
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_man_iblock_alloc_indirect() */
+} /* end H5HF_man_iblock_alloc_row() */
/*-------------------------------------------------------------------------
@@ -1109,9 +1007,6 @@ done:
herr_t
H5HF_man_iblock_detach(H5HF_indirect_t *iblock, hid_t dxpl_id, unsigned entry)
{
-#ifdef OLD_WAY
- unsigned start_children; /* # of children of iblock when routine was entered */
-#endif /* OLD_WAY */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_detach)
@@ -1134,12 +1029,6 @@ HDfprintf(stderr, "%s: iblock->block_off = %Hu, iblock->nchildren = %u\n", FUNC,
* removed from the heap when it's ref. count drops to zero and the
* metadata cache calls the indirect block destructor)
*/
- /* (Track the initial # of children before the block gets modified, because
- * this routine is called recursively)
- */
-#ifdef OLD_WAY
- start_children = iblock->nchildren;
-#endif /* OLD_WAY */
iblock->nchildren--;
/* Reduce the max. entry used, if necessary */
@@ -1195,3 +1084,34 @@ HDfprintf(stderr, "%s: iblock->block_off = %Hu, iblock->nchildren = %u\n", FUNC,
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_man_iblock_detach() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_man_iblock_entry_addr
+ *
+ * Purpose: Retrieve the address of an indirect block's child
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * July 10 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_man_iblock_entry_addr(H5HF_indirect_t *iblock, unsigned entry, haddr_t *child_addr)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_man_iblock_entry_addr)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(iblock);
+ HDassert(child_addr);
+
+ /* Reset address of entry */
+ *child_addr = iblock->ents[entry].addr;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5HF_man_iblock_entry_addr() */
+
diff --git a/src/H5HFint.c b/src/H5HFint.c
index 833bc0f..e9fe631 100644
--- a/src/H5HFint.c
+++ b/src/H5HFint.c
@@ -115,11 +115,11 @@ HDfprintf(stderr, "%s: obj_off = %Hu\n", FUNC, obj_off);
/* Set up target bottom & top rows */
if(locate_indirect) {
bot_row = hdr->man_dtable.max_direct_rows;
- top_row = hdr->man_dtable.max_direct_rows + (H5V_log2_of2(hdr->man_dtable.cparam.width) + 1);
+ top_row = hdr->man_dtable.max_direct_rows + H5V_log2_of2(hdr->man_dtable.cparam.width);
} /* end if */
else {
bot_row = 0;
- top_row = hdr->man_dtable.max_direct_rows;
+ top_row = hdr->man_dtable.max_direct_rows - 1;
} /* end else */
#ifdef QAK
HDfprintf(stderr, "%s: bot_row = %u, top_row = %u\n", FUNC, bot_row, top_row);
@@ -143,7 +143,7 @@ HDfprintf(stderr, "%s: iblock_addr = %a\n", FUNC, iblock_addr);
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
/* Check for indirect block row */
- while(row < bot_row || row >= top_row) {
+ while(row < bot_row || row > top_row) {
haddr_t new_iblock_addr; /* New indirect block's address */
H5HF_indirect_t *new_iblock; /* Pointer to new indirect block */
unsigned nrows; /* Number of rows in new indirect block */
@@ -196,7 +196,8 @@ HDfprintf(stderr, "%s: row = %u, col = %u\n", FUNC, row, col);
} /* end while */
/* Set return parameters */
- *ret_entry = (row * hdr->man_dtable.cparam.width) + col;
+ if(ret_entry)
+ *ret_entry = (row * hdr->man_dtable.cparam.width) + col;
*ret_iblock = iblock;
done:
@@ -296,40 +297,22 @@ HDfprintf(stderr, "%s: obj_size = %Zu\n", FUNC, obj_size);
HDassert(obj);
HDassert(id);
- /* Check for indirect section */
- if(sec_node->sect_info.type == H5HF_FSPACE_SECT_INDIRECT) {
+ /* Check for row section */
+ if(sec_node->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW ||
+ sec_node->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW) {
#ifdef QAK
HDfprintf(stderr, "%s: sec_node->sect_info.addr = %a\n", FUNC, sec_node->sect_info.addr);
-HDfprintf(stderr, "%s: sec_node->sect_info.size = %Zu\n", FUNC, sec_node->sect_info.size);
-HDfprintf(stderr, "%s: sec_node->u.indirect.iblock = %p\n", FUNC, sec_node->u.indirect.iblock);
-if(sec_node->sect_info.state == H5FS_SECT_LIVE && sec_node->u.indirect.iblock)
- HDfprintf(stderr, "%s: sec_node->u.indirect.iblock->addr = %a\n", FUNC, sec_node->u.indirect.iblock->addr);
-HDfprintf(stderr, "%s: sec_node->u.indirect.row = %u\n", FUNC, sec_node->u.indirect.row);
-HDfprintf(stderr, "%s: sec_node->u.indirect.col = %u\n", FUNC, sec_node->u.indirect.col);
-HDfprintf(stderr, "%s: sec_node->u.indirect.num_entries = %u\n", FUNC, sec_node->u.indirect.num_entries);
-HDfprintf(stderr, "%s: sec_node->u.indirect.indir_row = %u\n", FUNC, sec_node->u.indirect.indir_row);
-HDfprintf(stderr, "%s: sec_node->u.indirect.indir_nrows = %u\n", FUNC, sec_node->u.indirect.indir_nrows);
+HDfprintf(stderr, "%s: sec_node->sect_info.size = %Hu\n", FUNC, sec_node->sect_info.size);
+HDfprintf(stderr, "%s: sec_node->sect_info.type = %s\n", FUNC, (sec_node->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW ? "H5HF_FSPACE_SECT_FIRST_ROW" : "H5HF_FSPACE_SECT_NORMAL_ROW"));
+HDfprintf(stderr, "%s: sec_node->u.row.under = %p\n", FUNC, sec_node->u.row.under);
+HDfprintf(stderr, "%s: sec_node->u.row.row = %u\n", FUNC, sec_node->u.row.row);
+HDfprintf(stderr, "%s: sec_node->u.row.col = %u\n", FUNC, sec_node->u.row.col);
+HDfprintf(stderr, "%s: sec_node->u.row.num_entries = %u\n", FUNC, sec_node->u.row.num_entries);
#endif /* QAK */
- /* Allocate 'single' selection out of 'indirect' selection */
- if(H5HF_man_iblock_alloc_indirect(hdr, dxpl_id, &sec_node) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't break up indirect free section")
- } /* end if */
- /* Check for range section */
- else if(sec_node->sect_info.type == H5HF_FSPACE_SECT_RANGE) {
-#ifdef QAK
-HDfprintf(stderr, "%s: sec_node->sect_info.addr = %a\n", FUNC, sec_node->sect_info.addr);
-HDfprintf(stderr, "%s: sec_node->sect_info.size = %Zu\n", FUNC, sec_node->sect_info.size);
-HDfprintf(stderr, "%s: sec_node->u.range.iblock = %p\n", FUNC, sec_node->u.range.iblock);
-if(sec_node->sect_info.state == H5FS_SECT_LIVE && sec_node->u.range.iblock)
- HDfprintf(stderr, "%s: sec_node->u.range.iblock->addr = %a\n", FUNC, sec_node->u.range.iblock->addr);
-HDfprintf(stderr, "%s: sec_node->u.range.row = %u\n", FUNC, sec_node->u.range.row);
-HDfprintf(stderr, "%s: sec_node->u.range.col = %u\n", FUNC, sec_node->u.range.col);
-HDfprintf(stderr, "%s: sec_node->u.range.num_entries = %u\n", FUNC, sec_node->u.range.num_entries);
-#endif /* QAK */
- /* Allocate 'single' selection out of 'range' selection */
- if(H5HF_man_iblock_alloc_range(hdr, dxpl_id, &sec_node) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't break up range free section")
+ /* Allocate 'single' selection out of 'row' selection */
+ if(H5HF_man_iblock_alloc_row(hdr, dxpl_id, &sec_node) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't break up row section")
} /* end if */
HDassert(sec_node->sect_info.type == H5HF_FSPACE_SECT_SINGLE);
@@ -630,7 +613,7 @@ HDfprintf(stderr, "%s: blk_off = %Zu\n", FUNC, blk_off);
HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't adjust free space for heap")
/* Return free space to the heap's list of space */
- if(H5HF_space_return(hdr, dxpl_id, sec_node) < 0)
+ if(H5HF_space_add(hdr, dxpl_id, sec_node, H5FS_ADD_RETURNED_SPACE) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add direct block free space to global list")
done:
diff --git a/src/H5HFpkg.h b/src/H5HFpkg.h
index d5b4da0..15f0665 100644
--- a/src/H5HFpkg.h
+++ b/src/H5HFpkg.h
@@ -126,9 +126,10 @@
/* Free space section types for fractal heap */
/* (values stored in free space data structures in file) */
-#define H5HF_FSPACE_SECT_SINGLE 0 /* Section is actual bytes in a direct block */
-#define H5HF_FSPACE_SECT_RANGE 1 /* Section is a range of direct blocks */
-#define H5HF_FSPACE_SECT_INDIRECT 2 /* Section is a range of _indirect_ blocks in an indirect block row */
+#define H5HF_FSPACE_SECT_SINGLE 0 /* Section is a range of actual bytes in a direct block */
+#define H5HF_FSPACE_SECT_FIRST_ROW 1 /* Section is first range of blocks in an indirect block row */
+#define H5HF_FSPACE_SECT_NORMAL_ROW 2 /* Section is a range of blocks in an indirect block row */
+#define H5HF_FSPACE_SECT_INDIRECT 3 /* Section is a span of blocks in an indirect block */
/****************************/
/* Package Private Typedefs */
@@ -158,10 +159,15 @@ typedef struct H5HF_dtable_t {
hsize_t num_id_first_row; /* Number of IDs in first row of table */
hsize_t *row_block_size; /* Block size per row of indirect block */
hsize_t *row_block_off; /* Cumulative offset per row of indirect block */
- hsize_t *row_dblock_free; /* Free space in dblocks for this row */
+ hsize_t *row_tot_dblock_free; /* Total free space in dblocks for this row */
/* (For indirect block rows, it's the total
* free space in all direct blocks referenced
- * from the indirect block
+ * from the indirect block)
+ */
+ size_t *row_max_dblock_free; /* Max. free space in dblocks for this row */
+ /* (For indirect block rows, it's the maximum
+ * free space in a direct block referenced
+ * from the indirect block)
*/
} H5HF_dtable_t;
@@ -205,18 +211,39 @@ typedef struct H5HF_free_section_t {
/* (Needed to retrieve root direct block) */
} single;
struct {
- H5HF_indirect_t *iblock; /* Indirect block for free section */
+ struct H5HF_free_section_t *under; /* Pointer to indirect block underlying row section */
unsigned row; /* Row for range of blocks */
unsigned col; /* Column for range of blocks */
unsigned num_entries; /* Number of entries covered */
- } range;
+
+ /* Fields that aren't stored */
+ hbool_t checked_out; /* Flag to indicate that a row section is temporarily out of the free space manager */
+ } row;
struct {
- H5HF_indirect_t *iblock; /* Indirect block for free section */
+ /* Holds either a pointer to an indirect block (if its "live") or
+ * the block offset of it's indirect block (if its "serialized")
+ * (This allows the indirect block that the section is within to
+ * be compared with other sections, whether its serialized
+ * or not)
+ */
+ union {
+ H5HF_indirect_t *iblock; /* Indirect block for free section */
+ hsize_t iblock_off; /* Indirect block offset in "heap space" */
+ } u;
unsigned row; /* Row for range of blocks */
unsigned col; /* Column for range of blocks */
unsigned num_entries; /* Number of entries covered */
- unsigned indir_row; /* Row for indirect range of blocks */
- unsigned indir_nrows; /* Number of rows in indirect blocks */
+
+ /* Fields that aren't stored */
+ struct H5HF_free_section_t *parent; /* Pointer to "parent" indirect section */
+ unsigned par_entry; /* Entry within parent indirect section */
+ hsize_t span_size; /* Size of space tracked, in "heap space" */
+ unsigned iblock_entries; /* Number of entries in indirect block where section is located */
+ unsigned rc; /* Reference count of outstanding row & child indirect sections */
+ unsigned dir_nrows; /* Number of direct rows in section */
+ struct H5HF_free_section_t **dir_rows; /* Array of pointers to outstanding row sections */
+ unsigned indir_nents; /* Number of indirect entries in section */
+ struct H5HF_free_section_t **indir_ents; /* Array of pointers to outstanding child indirect sections */
} indirect;
} u;
} H5HF_free_section_t;
@@ -332,7 +359,7 @@ typedef struct H5HF_parent_t {
typedef struct {
H5HF_hdr_t *hdr; /* Fractal heap header */
hid_t dxpl_id; /* DXPL ID for operation */
- H5HF_direct_t *dblock; /* Direct block */
+ hbool_t adjoin; /* Whether two spans of blocks adjoin each other */
} H5HF_add_ud1_t;
/*****************************/
@@ -351,8 +378,11 @@ H5_DLLVAR const H5AC_class_t H5AC_FHEAP_IBLOCK[1];
/* H5HF single section inherits serializable properties from H5FS_section_class_t */
H5_DLLVAR H5FS_section_class_t H5HF_FSPACE_SECT_CLS_SINGLE[1];
-/* H5HF range section inherits serializable properties from H5FS_section_class_t */
-H5_DLLVAR H5FS_section_class_t H5HF_FSPACE_SECT_CLS_RANGE[1];
+/* H5HF 'first' row section inherits serializable properties from H5FS_section_class_t */
+H5_DLLVAR H5FS_section_class_t H5HF_FSPACE_SECT_CLS_FIRST_ROW[1];
+
+/* H5HF 'normal' row section inherits serializable properties from H5FS_section_class_t */
+H5_DLLVAR H5FS_section_class_t H5HF_FSPACE_SECT_CLS_NORMAL_ROW[1];
/* H5HF indirect section inherits serializable properties from H5FS_section_class_t */
H5_DLLVAR H5FS_section_class_t H5HF_FSPACE_SECT_CLS_INDIRECT[1];
@@ -415,9 +445,7 @@ H5_DLL herr_t H5HF_man_iblock_root_create(H5HF_hdr_t *hdr, hid_t dxpl_id,
size_t min_dblock_size);
H5_DLL herr_t H5HF_man_iblock_root_double(H5HF_hdr_t *hdr, hid_t dxpl_id,
size_t min_dblock_size);
-H5_DLL herr_t H5HF_man_iblock_alloc_range(H5HF_hdr_t *hdr, hid_t dxpl_id,
- H5HF_free_section_t **sec_node);
-H5_DLL herr_t H5HF_man_iblock_alloc_indirect(H5HF_hdr_t *hdr, hid_t dxpl_id,
+H5_DLL herr_t H5HF_man_iblock_alloc_row(H5HF_hdr_t *hdr, hid_t dxpl_id,
H5HF_free_section_t **sec_node);
H5_DLL herr_t H5HF_man_iblock_create(H5HF_hdr_t *hdr, hid_t dxpl_id,
H5HF_indirect_t *par_iblock, unsigned par_entry, unsigned nrows,
@@ -429,6 +457,8 @@ H5_DLL H5HF_indirect_t *H5HF_man_iblock_protect(H5HF_hdr_t *hdr, hid_t dxpl_id,
H5_DLL herr_t H5HF_man_iblock_attach(H5HF_indirect_t *iblock, unsigned entry,
haddr_t dblock_addr);
H5_DLL herr_t H5HF_man_iblock_detach(H5HF_indirect_t *iblock, hid_t dxpl_id, unsigned entry);
+H5_DLL herr_t H5HF_man_iblock_entry_addr(H5HF_indirect_t *iblock, unsigned entry,
+ haddr_t *child_addr);
/* Direct block routines */
H5_DLL herr_t H5HF_man_dblock_new(H5HF_hdr_t *fh, hid_t dxpl_id, size_t request,
@@ -494,11 +524,11 @@ H5_DLL herr_t H5HF_space_start(H5HF_hdr_t *hdr, hid_t dxpl_id);
H5_DLL htri_t H5HF_space_find(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t request,
H5HF_free_section_t **node);
H5_DLL herr_t H5HF_space_add(H5HF_hdr_t *hdr, hid_t dxpl_id,
- H5HF_free_section_t *node);
-H5_DLL herr_t H5HF_space_return(H5HF_hdr_t *hdr, hid_t dxpl_id,
- H5HF_free_section_t *node);
+ H5HF_free_section_t *node, unsigned flags);
H5_DLL herr_t H5HF_space_close(H5HF_hdr_t *hdr, hid_t dxpl_id);
H5_DLL herr_t H5HF_space_delete(H5HF_hdr_t *hdr, hid_t dxpl_id);
+H5_DLL herr_t H5HF_space_sect_change_class(H5HF_hdr_t *hdr, H5HF_free_section_t *sect,
+ unsigned new_class);
/* Free space section routines */
H5_DLL H5HF_free_section_t *H5HF_sect_single_new(hsize_t sect_off,
@@ -508,21 +538,14 @@ H5_DLL herr_t H5HF_sect_single_revive(H5HF_hdr_t *hdr, hid_t dxpl_id,
H5HF_free_section_t *sect);
H5_DLL herr_t H5HF_sect_single_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id,
H5HF_free_section_t *sect, size_t amt);
-H5_DLL 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);
-H5_DLL herr_t H5HF_sect_range_revive(H5HF_hdr_t *hdr, hid_t dxpl_id,
- H5HF_free_section_t *sect);
-H5_DLL herr_t H5HF_sect_range_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id,
+H5_DLL herr_t H5HF_sect_row_revive(H5HF_hdr_t *hdr, hid_t dxpl_id,
H5HF_free_section_t *sect);
+H5_DLL herr_t H5HF_sect_row_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id,
+ H5HF_free_section_t *sect, unsigned *entry_p);
+H5_DLL H5HF_indirect_t *H5HF_sect_row_get_iblock(H5HF_free_section_t *sect);
H5_DLL 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);
-H5_DLL herr_t H5HF_sect_indirect_revive(H5HF_hdr_t *hdr, hid_t dxpl_id,
- H5HF_free_section_t *sect);
-H5_DLL herr_t H5HF_sect_indirect_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id,
- H5HF_free_section_t *sect);
+ H5HF_indirect_t *iblock, unsigned start_entry, unsigned nentries,
+ hsize_t *sect_off);
/* Testing routines */
#ifdef H5HF_TESTING
diff --git a/src/H5HFsection.c b/src/H5HFsection.c
index 7fe557b..b12fc2b 100644
--- a/src/H5HFsection.c
+++ b/src/H5HFsection.c
@@ -12,7 +12,8 @@
* access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-/* Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
+/*
+ * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
* Monday, May 1, 2006
*
* Purpose: Free space section routines for fractal heaps.
@@ -31,6 +32,8 @@
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
#include "H5HFpkg.h" /* Fractal heaps */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5Vprivate.h" /* Vectors and arrays */
/****************/
/* Local Macros */
@@ -41,6 +44,11 @@
/* Local Typedefs */
/******************/
+/* Typedef for "class private" information for indirect sections */
+typedef struct {
+ H5HF_hdr_t *hdr; /* Pointer to fractal heap header */
+} H5HF_sect_indirect_private_t;
+
/********************/
/* Package Typedefs */
@@ -56,47 +64,96 @@ 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 H5FS_section_info_t *H5HF_sect_single_deserialize(const uint8_t *buf,
- haddr_t sect_addr, hsize_t sect_size);
+static H5FS_section_info_t *H5HF_sect_single_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 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 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,
+static herr_t H5HF_sect_single_valid(const H5FS_section_class_t *cls,
+ const H5FS_section_info_t *sect);
+
+/* 'row' section routines */
+static H5HF_free_section_t *H5HF_sect_row_create(haddr_t sect_off,
+ hsize_t sect_size, hbool_t is_first, unsigned row, unsigned col,
+ unsigned nentries, H5HF_free_section_t *under_sect);
+static herr_t H5HF_sect_row_first(H5HF_hdr_t *hdr, H5HF_free_section_t *sect);
+static herr_t H5HF_sect_row_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 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,
+static herr_t H5HF_sect_row_iblock_same(const H5HF_free_section_t *sect1,
+ const H5HF_free_section_t *sect2);
+
+/* 'row' section callbacks */
+static herr_t H5HF_sect_row_init_cls(H5FS_section_class_t *cls, void *udata);
+static herr_t H5HF_sect_row_term_cls(H5FS_section_class_t *cls);
+static herr_t H5HF_sect_row_serialize(const H5FS_section_class_t *cls,
+ const H5FS_section_info_t *sect, uint8_t *buf);
+static H5FS_section_info_t *H5HF_sect_row_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 htri_t H5HF_sect_row_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,
+static herr_t H5HF_sect_row_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,
+static htri_t H5HF_sect_row_can_shrink(H5FS_section_info_t *sect,
void *udata);
-static herr_t H5HF_sect_range_shrink(H5FS_section_info_t **sect,
+static herr_t H5HF_sect_row_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);
+static herr_t H5HF_sect_row_free(H5FS_section_info_t *sect);
+static herr_t H5HF_sect_row_valid(const H5FS_section_class_t *cls,
+ const H5FS_section_info_t *sect);
+
+/* 'indirect' section routines */
+static H5HF_free_section_t *H5HF_sect_indirect_new(haddr_t sect_off,
+ hsize_t sect_size, H5HF_indirect_t *iblock, hsize_t iblock_off,
+ unsigned row, unsigned col, unsigned nentries);
+static herr_t H5HF_sect_indirect_init_rows(H5HF_hdr_t *hdr, hid_t dxpl_id,
+ H5HF_free_section_t *sect, hbool_t first_child, unsigned space_flags,
+ unsigned start_row, unsigned start_col, unsigned end_row, unsigned end_col);
+static H5HF_free_section_t *H5HF_sect_indirect_for_row(H5HF_hdr_t *hdr,
+ H5HF_indirect_t *iblock, H5HF_free_section_t *row_sect);
+static herr_t H5HF_sect_indirect_decr(H5HF_free_section_t *sect);
+static herr_t H5HF_sect_indirect_revive_row(H5HF_hdr_t *hdr, hid_t dxpl_id,
+ H5HF_free_section_t *sect);
+static herr_t H5HF_sect_indirect_revive(H5HF_hdr_t *hdr, hid_t dxpl_id,
+ H5HF_free_section_t *sect, H5HF_indirect_t *sect_iblock);
+static herr_t H5HF_sect_indirect_reduce_row(H5HF_hdr_t *hdr,
+ H5HF_free_section_t *row_sect, hbool_t *alloc_from_start);
+static herr_t H5HF_sect_indirect_reduce(H5HF_hdr_t *hdr,
+ H5HF_free_section_t *sect, unsigned child_entry);
+static herr_t H5HF_sect_indirect_first(H5HF_hdr_t *hdr, H5HF_free_section_t *sect);
+static hbool_t H5HF_sect_indirect_is_first(H5HF_free_section_t *sect);
+static H5HF_indirect_t * H5HF_sect_indirect_get_iblock(H5HF_free_section_t *sect);
+static herr_t H5HF_sect_indirect_span_size(H5HF_hdr_t *hdr,
+ H5HF_free_section_t *sect);
+static herr_t H5HF_sect_indirect_iblock_entries(H5HF_hdr_t *hdr,
+ H5HF_free_section_t *sect);
+static herr_t H5HF_sect_indirect_iblock_same(const H5HF_free_section_t *sect1,
+ const H5HF_free_section_t *sect2);
+static hbool_t H5HF_sect_indirect_is_last_row(const H5HF_free_section_t *row_sect);
+static herr_t H5HF_sect_indirect_merge_row(H5HF_hdr_t *hdr, hid_t dxpl_id,
+ H5HF_free_section_t *sect1, H5HF_free_section_t *sect2);
+static herr_t H5HF_sect_indirect_shrink_row(H5HF_free_section_t *row_sect);
+static herr_t H5HF_sect_indirect_serialize(H5HF_hdr_t *hdr,
+ const H5HF_free_section_t *sect, uint8_t *buf);
+static H5FS_section_info_t *H5HF_sect_indirect_deserialize(H5HF_hdr_t *hdr,
+ hid_t dxpl_id, const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size,
+ unsigned *des_flags);
+static herr_t H5HF_sect_indirect_free(H5HF_free_section_t *sect);
+static herr_t H5HF_sect_indirect_valid(const H5FS_section_class_t *row_cls,
+ const H5HF_free_section_t *row_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 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_init_cls(H5FS_section_class_t *cls, void *udata);
+static herr_t H5HF_sect_indirect_term_cls(H5FS_section_class_t *cls);
static herr_t H5HF_sect_indirect_debug(const H5FS_section_info_t *sect,
FILE *stream, int indent, int fwidth);
@@ -106,48 +163,104 @@ 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 H5HF_FSPACE_SECT_CLS_SINGLE[1] = {{
+ /* Class variables */
H5HF_FSPACE_SECT_SINGLE, /* Section type */
0, /* Extra serialized size */
+ 0, /* Class flags */
+ NULL, /* Class private info */
+
+ /* Class methods */
NULL, /* Initialize section class */
+ NULL, /* Terminate section class */
+
+ /* Object methods */
NULL, /* Serialize section */
H5HF_sect_single_deserialize, /* Deserialize section */
H5HF_sect_single_can_merge, /* Can sections merge? */
H5HF_sect_single_merge, /* Merge sections */
H5HF_sect_single_can_shrink, /* Can section shrink container?*/
- NULL, /* Shrink container w/section */
+ H5HF_sect_single_shrink, /* Shrink container w/section */
H5HF_sect_single_free, /* Free section */
+ H5HF_sect_single_valid, /* Check validity of section */
NULL, /* Dump debugging for section */
}};
-/* Class info for "range" free space sections */
-H5FS_section_class_t H5HF_FSPACE_SECT_CLS_RANGE[1] = {{
- H5HF_FSPACE_SECT_RANGE, /* Section type */
+/* Class info for "first row" free space sections */
+/* (Same as "normal" row sections, except they also act as a proxy for the
+ * underlying indirect section
+ */
+H5FS_section_class_t H5HF_FSPACE_SECT_CLS_FIRST_ROW[1] = {{
+ /* Class variables */
+ H5HF_FSPACE_SECT_FIRST_ROW, /* 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 */
- 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 */
+ 0, /* Class flags */
+ NULL, /* Class private info */
+
+ /* Class methods */
+ H5HF_sect_row_init_cls, /* Initialize section class */
+ H5HF_sect_row_term_cls, /* Terminate section class */
+
+ /* Object methods */
+ H5HF_sect_row_serialize, /* Serialize section */
+ H5HF_sect_row_deserialize, /* Deserialize section */
+ H5HF_sect_row_can_merge, /* Can sections merge? */
+ H5HF_sect_row_merge, /* Merge sections */
+ H5HF_sect_row_can_shrink, /* Can section shrink container?*/
+ H5HF_sect_row_shrink, /* Shrink container w/section */
+ H5HF_sect_row_free, /* Free section */
+ H5HF_sect_row_valid, /* Check validity of section */
+ NULL, /* Dump debugging for section */
+}};
+
+/* Class info for "normal row" free space sections */
+H5FS_section_class_t H5HF_FSPACE_SECT_CLS_NORMAL_ROW[1] = {{
+ /* Class variables */
+ H5HF_FSPACE_SECT_NORMAL_ROW, /* Section type */
+ 0, /* Extra serialized size */
+ H5FS_CLS_GHOST_OBJ, /* Class flags */
+ NULL, /* Class private info */
+
+ /* Class methods */
+ NULL, /* Initialize section class */
+ NULL, /* Terminate section class */
+
+ /* Object methods */
+ NULL, /* Serialize section */
+ NULL, /* Deserialize section */
+ H5HF_sect_row_can_merge, /* Can sections merge? */
+ H5HF_sect_row_merge, /* Merge sections */
+ H5HF_sect_row_can_shrink, /* Can section shrink container?*/
+ H5HF_sect_row_shrink, /* Shrink container w/section */
+ H5HF_sect_row_free, /* Free section */
+ H5HF_sect_row_valid, /* Check validity of section */
+ NULL, /* Dump debugging for section */
}};
/* Class info for "indirect" free space sections */
+/* (No object callbacks necessary - objects of this class should never be in
+ * section manager)
+ */
H5FS_section_class_t H5HF_FSPACE_SECT_CLS_INDIRECT[1] = {{
+ /* Class variables */
H5HF_FSPACE_SECT_INDIRECT, /* Section type */
0, /* Extra serialized size */
+ H5FS_CLS_GHOST_OBJ, /* Class flags */
+ NULL, /* Class private info */
+
+ /* Class methods */
H5HF_sect_indirect_init_cls, /* Initialize section class */
- H5HF_sect_indirect_serialize, /* Serialize section */
- H5HF_sect_indirect_deserialize, /* Deserialize section */
+ H5HF_sect_indirect_term_cls, /* Terminate section class */
+
+ /* Object methods */
+ NULL, /* Serialize section */
+ NULL, /* Deserialize section */
NULL, /* Can sections merge? */
NULL, /* Merge sections */
NULL, /* Can section shrink container?*/
NULL, /* Shrink container w/section */
- H5HF_sect_indirect_free, /* Free section */
+ NULL, /* Free section */
+ NULL, /* Check validity of section */
H5HF_sect_indirect_debug, /* Dump debugging for section */
}};
@@ -191,7 +304,6 @@ H5HF_sect_node_new(unsigned sect_type, haddr_t sect_addr, hsize_t sect_size,
/* Check arguments. */
HDassert(H5F_addr_defined(sect_addr));
- HDassert(sect_size);
/* Create free list section node */
if(NULL == (new_sect = H5FL_MALLOC(H5HF_free_section_t)))
@@ -228,7 +340,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5HF_sect_node_free(H5HF_free_section_t *sect, H5HF_indirect_t *parent)
+H5HF_sect_node_free(H5HF_free_section_t *sect, H5HF_indirect_t *iblock)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -237,9 +349,9 @@ H5HF_sect_node_free(H5HF_free_section_t *sect, H5HF_indirect_t *parent)
HDassert(sect);
/* Release indirect block, if there was one */
- if(parent)
- if(H5HF_iblock_decr(parent) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on parent indirect block")
+ if(iblock)
+ if(H5HF_iblock_decr(iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on section's indirect block")
/* Release the section */
H5FL_FREE(H5HF_free_section_t, sect);
@@ -250,57 +362,6 @@ 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
@@ -479,7 +540,7 @@ H5HF_sect_single_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id,
sect->sect_info.size -= amt;
/* Re-insert section node into heap's free space */
- if(H5HF_space_add(hdr, dxpl_id, sect) < 0)
+ if(H5HF_space_add(hdr, dxpl_id, sect, 0) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't re-add single section to free space manager")
} /* end else */
@@ -503,8 +564,9 @@ done:
*-------------------------------------------------------------------------
*/
static H5FS_section_info_t *
-H5HF_sect_single_deserialize(const uint8_t *buf, haddr_t sect_addr,
- hsize_t sect_size)
+H5HF_sect_single_deserialize(const H5FS_section_class_t UNUSED *cls,
+ hid_t UNUSED dxpl_id, const uint8_t *buf, haddr_t sect_addr,
+ hsize_t sect_size, unsigned UNUSED *des_flags)
{
H5HF_free_section_t *new_sect; /* New section */
H5FS_section_info_t *ret_value; /* Return value */
@@ -546,18 +608,13 @@ done:
*/
static htri_t
H5HF_sect_single_can_merge(H5FS_section_info_t *_sect1,
- H5FS_section_info_t *_sect2, void *_udata)
+ 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 */
- 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(H5HF_sect_single_can_merge)
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_single_can_merge)
/* Check arguments. */
HDassert(sect1);
@@ -565,70 +622,18 @@ H5HF_sect_single_can_merge(H5FS_section_info_t *_sect1,
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: 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);
+HDfprintf(stderr, "%s: sect1->sect_info = {%a, %Hu, %u, %s}\n", "H5HF_sect_single_can_merge", 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", "H5HF_sect_single_can_merge", 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 */
- 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")
-
-#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 */
-
- /* 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->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)
+ /* (This can only occur within a direct block, due to the direct block
+ * overhead at the beginning of a block, so no need to check if sections
+ * are actually within the same direct block)
*/
if(H5F_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr))
HGOTO_DONE(TRUE)
@@ -656,24 +661,27 @@ done:
*/
static herr_t
H5HF_sect_single_merge(H5FS_section_info_t *_sect1, H5FS_section_info_t *_sect2,
- void UNUSED *udata)
+ 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 */
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(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->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);
+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 */
/* Add second section's size to first section */
@@ -683,11 +691,48 @@ HDfprintf(stderr, "%s: sect2->sect_info.size = %Hu, sect2->sect_info.addr = %a\n
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
- */
+ /* Check to see if we should revive first 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")
+
+ /* Check for section occupying entire direct block */
+ /* (and not the root direct block) */
+ dblock_size = sect1->u.single.dblock_size;
+ dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr);
+#ifdef QAK
+HDfprintf(stderr, "%s: dblock_size = %u\n", FUNC, dblock_size);
+HDfprintf(stderr, "%s: dblock_overhead = %Zu\n", FUNC, dblock_overhead);
+HDfprintf(stderr, "%s: hdr->man_iter_off = %Hu\n", FUNC, hdr->man_iter_off);
+#endif /* QAK */
+ if((dblock_size - dblock_overhead) == sect1->sect_info.size &&
+ hdr->man_dtable.curr_root_rows > 0) {
+ 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 'row' section */
+ if(H5HF_sect_row_from_single(hdr, sect1, dblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTCONVERT, FAIL, "can't convert single section into row section")
+
+#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.row = {%p, %u, %u, %u, %t}\n", FUNC, sect1->u.row.under, sect1->u.row.row, sect1->u.row.col, sect1->u.row.num_entries, sect1->u.row.checked_out);
+#endif /* QAK */
+
+ /* 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;
+ } /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -716,14 +761,15 @@ static htri_t
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 */
+#ifndef NDEBUG
H5HF_add_ud1_t *udata = (H5HF_add_ud1_t *)_udata; /* User callback data */
H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */
+#endif /* NDEBUG */
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(H5HF_sect_single_can_shrink)
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_single_can_shrink)
/* Check arguments. */
HDassert(sect);
@@ -733,50 +779,101 @@ H5HF_sect_single_can_shrink(H5FS_section_info_t *_sect, void *_udata)
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 */
- /* 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")
-
/* 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\n", FUNC, dblock_size);
+HDfprintf(stderr, "%s: dblock_size = %Zu\n", FUNC, dblock_size);
+HDfprintf(stderr, "%s: dblock_overhead = %Zu\n", FUNC, dblock_overhead);
#endif /* QAK */
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 */
+ /* We shouldn't ever have a single section that occupies an entire
+ * direct block, unless it's in the root direct block (and
+ * therefore there's no parent indirect block to hook into)
+ */
+ HDassert(hdr->man_dtable.curr_root_rows == 0);
+ HGOTO_DONE(TRUE)
+ } /* end if */
+ else {
+ /* We shouldn't have a situation where the 'next block' iterator
+ * is moved before a direct block that still has objects within it.
+ */
+ HDassert(hdr->man_dtable.curr_root_rows == 0 || hdr->man_iter_off > sect->sect_info.addr);
+ HGOTO_DONE(FALSE)
+ } /* end else */
- /* Protect the direct block for the section */
- dblock_addr = sect->u.single.dblock_addr;
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5HF_sect_single_can_shrink() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_single_shrink
+ *
+ * Purpose: Shrink container with section
+ *
+ * Return: Success: non-negative
+ *
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Monday, July 17, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_sect_single_shrink(H5FS_section_info_t **_sect, void UNUSED *_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 = udata->hdr; /* Fractal heap header */
+ hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */
+ H5HF_direct_t *dblock; /* Pointer to direct block for section */
+ haddr_t dblock_addr; /* Section's direct block's address */
+ 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.type == H5HF_FSPACE_SECT_SINGLE);
+
+#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);
+#endif /* QAK */
+
+ /* Check to see if we should revive either 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")
+
+ /* Protect the direct block for the section */
+ dblock_addr = (*sect)->u.single.dblock_addr;
+ HDassert(dblock_addr == hdr->man_dtable.table_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, 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));
+ if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr,
+ (*sect)->u.single.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 + (*sect)->u.single.dblock_size, (*sect)->sect_info.addr + (*sect)->sect_info.size));
- /* 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;
- /* 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;
+ /* Get rid of section */
+ if(H5HF_sect_single_free((H5FS_section_info_t *)*sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node")
- /* 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 */
+ /* Indicate that the section has been released */
+ *sect = NULL;
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5HF_sect_single_can_shrink() */
+} /* H5HF_sect_single_shrink() */
/*-------------------------------------------------------------------------
@@ -821,160 +918,248 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5HF_sect_range_init_cls
+ * Function: H5HF_sect_single_valid
*
- * Purpose: Initialize the "range" class structure
+ * Purpose: Check the validity of a section
*
* Return: Success: non-negative
- *
* Failure: negative
*
* Programmer: Quincey Koziol
- * Monday, May 1, 2006
+ * Friday, July 21, 2006
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5HF_sect_range_init_cls(H5FS_section_class_t *cls, const void UNUSED *udata)
+H5HF_sect_single_valid(const H5FS_section_class_t *cls, const H5FS_section_info_t *_sect)
{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_range_init_cls)
+ const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Pointer to section to check */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_single_valid)
- /* Check arguments. */
HDassert(cls);
+ HDassert(sect);
- /* Set the size of all serialized objects of this class of sections */
- cls->serial_size = 2 /* Row */
- + 2 /* Column */
- + 2; /* # of entries */
+#ifdef QAK
+HDfprintf(stderr, "%s: sect->sect_info = {%a, %Hu, %u, %s}\n", "H5HF_sect_single_valid", 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 */
+ if(sect->sect_info.state == H5FS_SECT_LIVE) {
+ /* Check if this section is not in a direct block that is the root direct block */
+ /* (not enough information to check on a single section in a root direct block) */
+ if(sect->u.single.parent != NULL) {
+ H5HF_indirect_t *iblock; /* Indirect block that section's direct block resides in */
+ H5HF_direct_t *dblock; /* Direct block for section */
+ herr_t status; /* Generic status value */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: sect->u.single = {%p, %u, %a, %Zu}\n", "H5HF_sect_single_valid", sect->u.single.parent, sect->u.single.par_entry, sect->u.single.dblock_addr, sect->u.single.dblock_size);
+#endif /* QAK */
+ /* Sanity check settings for section's direct block's parent */
+ iblock = sect->u.single.parent;
+ HDassert(H5F_addr_defined(iblock->ents[sect->u.single.par_entry].addr));
+ HDassert(H5F_addr_eq(iblock->ents[sect->u.single.par_entry].addr,
+ sect->u.single.dblock_addr));
+
+ /* Protect the direct block for the section */
+ dblock = H5HF_man_dblock_protect(iblock->hdr, H5AC_dxpl_id, sect->u.single.dblock_addr, sect->u.single.dblock_size, iblock, sect->u.single.par_entry, H5AC_READ);
+ HDassert(dblock);
+
+ /* Sanity check settings for section */
+ HDassert(sect->u.single.dblock_size > 0);
+ HDassert(sect->u.single.dblock_size == dblock->size);
+ HDassert(dblock->size > sect->sect_info.size);
+ HDassert(H5F_addr_lt(dblock->block_off, sect->sect_info.addr));
+ HDassert(H5F_addr_ge((dblock->block_off + dblock->size),
+ (sect->sect_info.addr + sect->sect_info.size)));
+
+ /* Release direct block */
+ status = H5AC_unprotect(iblock->hdr->f, H5AC_dxpl_id, H5AC_FHEAP_DBLOCK, sect->u.single.dblock_addr, dblock, H5AC__NO_FLAGS_SET);
+ HDassert(status >= 0);
+ } /* end if */
+ } /* end if */
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5HF_sect_range_init_cls() */
+} /* H5HF_sect_single_valid() */
/*-------------------------------------------------------------------------
- * Function: H5HF_sect_range_add
+ * Function: H5HF_sect_row_create
*
- * Purpose: Add a new 'range' section to the free space manager for this
- * heap
+ * Purpose: Create a new 'row' section
+ *
+ * Return: Success: pointer to new section
+ *
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, July 6, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5HF_free_section_t *
+H5HF_sect_row_create(haddr_t sect_off, hsize_t sect_size, hbool_t is_first,
+ unsigned row, unsigned col, unsigned nentries, H5HF_free_section_t *under_sect)
+{
+ H5HF_free_section_t *sect = NULL; /* 'Row' section created */
+ H5HF_free_section_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_row_create)
+
+ /* Check arguments. */
+ HDassert(sect_size);
+ HDassert(nentries);
+ HDassert(under_sect);
+
+ /* Create 'row' free space section node */
+ /* ("inherits" underlying indirect section's state) */
+ if(NULL == (sect = H5HF_sect_node_new((unsigned)(is_first ? H5HF_FSPACE_SECT_FIRST_ROW : H5HF_FSPACE_SECT_NORMAL_ROW), sect_off, sect_size, under_sect->sect_info.state)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for row section")
+
+ /* Set the 'row' specific fields */
+ sect->u.row.under = under_sect;
+ sect->u.row.row = row;
+ sect->u.row.col = col;
+ sect->u.row.num_entries = nentries;
+ sect->u.row.checked_out = FALSE;
+
+ /* Set return value */
+ ret_value = sect;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5HF_sect_row_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_row_from_single
+ *
+ * Purpose: Convert a 'single' section into a 'row' section
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
- * May 30 2006
+ * July 6 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)
+static herr_t
+H5HF_sect_row_from_single(H5HF_hdr_t *hdr, H5HF_free_section_t *sect,
+ H5HF_direct_t *dblock)
{
- 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)
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_row_from_single)
/*
* 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 */
+ HDassert(sect);
+ HDassert(dblock);
+#ifdef QAK
+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"));
+HDfprintf(stderr, "%s: dblock->parent = %p\n", FUNC, dblock->parent);
+HDfprintf(stderr, "%s: hdr->man_dtable.curr_root_rows = %u\n", FUNC, hdr->man_dtable.curr_root_rows);
+#endif /* QAK */
- /* 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")
+ /* Convert 'single' section information to 'row' section info */
+ sect->sect_info.addr = dblock->block_off;
+ sect->sect_info.type = H5HF_FSPACE_SECT_FIRST_ROW;
+ sect->u.row.row = dblock->par_entry / hdr->man_dtable.cparam.width;
+ sect->u.row.col = dblock->par_entry % hdr->man_dtable.cparam.width;
+ sect->u.row.num_entries = 1;
+ sect->u.row.checked_out = FALSE;
+
+ /* Create indirect section that underlies the row section */
+ if(NULL == (sect->u.row.under = H5HF_sect_indirect_for_row(hdr, dblock->parent, sect)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, "serializing row section not supported yet")
+
+ /* Release single section's hold on underlying indirect block */
+ if(H5HF_iblock_decr(dblock->parent) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block")
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")
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_sect_row_from_single() */
- /* Release the section */
- H5FL_FREE(H5HF_free_section_t, sect);
- } /* end if */
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_row_iblock_same
+ *
+ * Purpose: Check if two row sections are located in the same indirect block
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * July 6 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static htri_t
+H5HF_sect_row_iblock_same(const H5HF_free_section_t *row_sect1,
+ const H5HF_free_section_t *row_sect2)
+{
+ htri_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_row_iblock_same)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(row_sect1);
+ HDassert(row_sect2);
+
+ /* Compare the underlying indirect sections */
+ ret_value = H5HF_sect_indirect_iblock_same(row_sect1->u.row.under, row_sect2->u.row.under);
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_sect_range_add() */
+} /* end H5HF_sect_row_iblock_same() */
/*-------------------------------------------------------------------------
- * Function: H5HF_sect_range_revive
+ * Function: H5HF_sect_row_revive
*
- * Purpose: Update the memory information for a 'range' free section
+ * Purpose: Update the memory information for a 'row' free section
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
- * May 8 2006
+ * July 6 2006
*
*-------------------------------------------------------------------------
*/
herr_t
-H5HF_sect_range_revive(H5HF_hdr_t *hdr, hid_t dxpl_id,
- H5HF_free_section_t *sect)
+H5HF_sect_row_revive(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect)
{
- H5HF_indirect_t *sec_iblock; /* Pointer to section indirect block */
- unsigned sec_entry; /* Entry within section indirect block */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_range_revive)
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_row_revive)
/*
* Check arguments.
*/
HDassert(hdr);
HDassert(sect);
+ HDassert(sect->u.row.under);
HDassert(sect->sect_info.state == H5FS_SECT_SERIALIZED);
- /* Look up indirect block containing direct blocks for range */
- if(H5HF_man_locate_block(hdr, dxpl_id, sect->sect_info.addr, FALSE, &sec_iblock, &sec_entry, H5AC_READ) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of section")
-
- /* Increment reference count on indirect block that free section is in */
- if(H5HF_iblock_incr(sec_iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block")
-
- /* Set the pointer to the section's indirect block */
- sect->u.range.iblock = sec_iblock;
-
- /* Unlock indirect block */
- if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, sec_iblock->addr, sec_iblock, H5AC__NO_FLAGS_SET) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
- sec_iblock = NULL;
-
- /* Section is "live" now */
- sect->sect_info.state = H5FS_SECT_LIVE;
+ /* Pass along "revive" request to underlying indirect section */
+ /* (which will mark this section as "live") */
+ if(H5HF_sect_indirect_revive_row(hdr, dxpl_id, sect->u.row.under) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTREVIVE, FAIL, "can't revive indirect section")
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_sect_range_revive() */
+} /* end H5HF_sect_row_revive() */
/*-------------------------------------------------------------------------
- * Function: H5HF_sect_range_reduce
+ * Function: H5HF_sect_row_reduce
*
- * Purpose: Reduce the size of a range section (possibly freeing it)
+ * Purpose: Reduce the size of a row section (possibly freeing it)
* and re-add it back to the free space manager for the heap
* (if it hasn't been freed)
*
@@ -982,186 +1167,316 @@ done:
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
- * May 31 2006
+ * July 6 2006
*
*-------------------------------------------------------------------------
*/
herr_t
-H5HF_sect_range_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id,
- H5HF_free_section_t *sect)
+H5HF_sect_row_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect,
+ unsigned *entry_p)
{
+ hbool_t alloc_from_start; /* Whether to allocate from the end of the row */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_range_reduce)
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_row_reduce)
/*
* Check arguments.
*/
HDassert(hdr);
HDassert(sect);
- HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_RANGE);
+ HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW ||
+ sect->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW);
HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
+ HDassert(entry_p);
+#ifdef QAK
+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"));
+HDfprintf(stderr, "%s: sect->u.row = {%p, %u, %u, %u, %t}\n", FUNC, sect->u.row.under, sect->u.row.row, sect->u.row.col, sect->u.row.num_entries, sect->u.row.checked_out);
+#endif /* QAK */
+
+ /* Mark the row as checked out from the free space manager */
+ HDassert(sect->u.row.checked_out == FALSE);
+ sect->u.row.checked_out = TRUE;
+
+ /* Forward row section to indirect routines, to handle reducing underlying indirect section */
+ alloc_from_start = FALSE;
+ if(H5HF_sect_indirect_reduce_row(hdr, sect, &alloc_from_start) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce underlying section")
+
+ /* Determine entry allocated */
+ *entry_p = (sect->u.row.row * hdr->man_dtable.cparam.width) + sect->u.row.col;
+ if(!alloc_from_start)
+ *entry_p += (sect->u.row.num_entries - 1);
/* 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")
+ if(sect->u.row.num_entries == 1) {
+#ifdef QAK
+HDfprintf(stderr, "%s: Freeing row section\n", FUNC);
+#endif /* QAK */
+ /* Free row section */
+ if(H5HF_sect_row_free((H5FS_section_info_t *)sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free row section node")
} /* end if */
else {
- /* Adjust section information */
- sect->sect_info.addr += hdr->man_dtable.row_block_size[sect->u.range.row];
+ /* Check whether to allocate from the beginning or end of the row */
+ if(alloc_from_start) {
+ /* Adjust section start */
+ sect->sect_info.addr += hdr->man_dtable.row_block_size[sect->u.row.row];
+ sect->u.row.col++;
+ } /* end else */
- /* Adjust range information */
- sect->u.range.col++;
- sect->u.range.num_entries--;
+ /* Adjust span of blocks covered */
+ sect->u.row.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")
+ /* Check the row back in */
+ sect->u.row.checked_out = FALSE;
+
+ /* Add 'row' section back to free space list */
+ if(H5HF_space_add(hdr, dxpl_id, sect, 0) < 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_range_reduce() */
+} /* end H5HF_sect_row_reduce() */
/*-------------------------------------------------------------------------
- * Function: H5HF_sect_range_from_single
+ * Function: H5HF_sect_row_first
*
- * Purpose: Convert a 'single' section into a 'range' section
+ * Purpose: Make row a "first row"
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
- * May 31 2006
+ * July 10 2006
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5HF_sect_range_from_single(H5HF_hdr_t *hdr, H5HF_free_section_t *sect,
- H5HF_direct_t *dblock)
+H5HF_sect_row_first(H5HF_hdr_t *hdr, H5HF_free_section_t *sect)
{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_range_from_single)
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_row_first)
+
+ /* Sanity check */
+ HDassert(hdr);
+ HDassert(sect);
+ HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW);
+
+ /* If the row is already checked out from the free space manager, just
+ * change it's class directly and the free space manager will adjust when
+ * it is checked back in.
+ */
+ if(sect->u.row.checked_out)
+ sect->sect_info.type = H5HF_FSPACE_SECT_FIRST_ROW;
+ else {
+ /* Change row section to be the "first row" */
+ if(H5HF_space_sect_change_class(hdr, sect, H5HF_FSPACE_SECT_FIRST_ROW) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSET, FAIL, "can't set row section to be first row")
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_sect_row_first() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_row_get_iblock
+ *
+ * Purpose: Retrieve the indirect block for a row section
+ *
+ * Return: Pointer to indirect block on success/NULL on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * July 9 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+H5HF_indirect_t *
+H5HF_sect_row_get_iblock(H5HF_free_section_t *sect)
+{
+ H5HF_indirect_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_row_get_iblock)
/*
* 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 */
+ HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW ||
+ sect->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW);
+ HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
- /* 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;
+ ret_value = H5HF_sect_indirect_get_iblock(sect->u.row.under);
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5HF_sect_range_from_single() */
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_sect_row_get_iblock() */
/*-------------------------------------------------------------------------
- * Function: H5HF_sect_range_serialize
+ * Function: H5HF_sect_row_init_cls
*
- * Purpose: Serialize a "live" range section into a buffer
+ * Purpose: Initialize the "row" section class structure
+ *
+ * Note: Since 'row' sections are proxies for 'indirect' sections, this
+ * routine forwards call to 'indirect' class initialization
*
* Return: Success: non-negative
*
* Failure: negative
*
* Programmer: Quincey Koziol
- * Monday, May 1, 2006
+ * Monday, July 6, 2006
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5HF_sect_range_serialize(const H5FS_section_info_t *_sect, uint8_t *buf)
+H5HF_sect_row_init_cls(H5FS_section_class_t *cls, void *_udata)
{
- const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect;
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_range_serialize)
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_row_init_cls)
/* Check arguments. */
- HDassert(buf);
- HDassert(sect);
+ HDassert(cls);
+ HDassert(!cls->cls_private);
+
+ /* Forward call to indirect class initialization */
+ if(H5HF_sect_indirect_init_cls(cls, _udata) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize row section class")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5HF_sect_row_init_cls() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_row_term_cls
+ *
+ * Purpose: Terminate the "row" section class structure
+ *
+ * Note: Since 'row' sections are proxies for 'indirect' sections, this
+ * routine forwards call to 'indirect' class termination
+ *
+ * Return: Success: non-negative
+ *
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Monday, July 6, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_sect_row_term_cls(H5FS_section_class_t *cls)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
- /* Range's row */
- UINT16ENCODE(buf, sect->u.range.row);
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_row_term_cls)
- /* Range's column */
- UINT16ENCODE(buf, sect->u.range.col);
+ /* Check arguments. */
+ HDassert(cls);
- /* Range's # of entries */
- UINT16ENCODE(buf, sect->u.range.num_entries);
+ /* Forward call to indirect class termination */
+ if(H5HF_sect_indirect_term_cls(cls) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't terminate row section class")
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5HF_sect_range_serialize() */
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5HF_sect_row_term_cls() */
/*-------------------------------------------------------------------------
- * Function: H5HF_sect_range_deserialize
+ * Function: H5HF_sect_row_serialize
*
- * Purpose: Deserialize a buffer into a "live" range section
+ * Purpose: Serialize a "live" row section into a buffer
*
* Return: Success: non-negative
*
* Failure: negative
*
* Programmer: Quincey Koziol
- * Monday, May 1, 2006
+ * Thursday, July 6, 2006
*
*-------------------------------------------------------------------------
*/
-static H5FS_section_info_t *
-H5HF_sect_range_deserialize(const uint8_t *buf, haddr_t sect_addr,
- hsize_t sect_size)
+static herr_t
+H5HF_sect_row_serialize(const H5FS_section_class_t *cls,
+ const H5FS_section_info_t *_sect, uint8_t *buf)
{
- H5HF_free_section_t *new_sect; /* New section */
- H5FS_section_info_t *ret_value; /* Return value */
+ H5HF_hdr_t *hdr; /* Fractal heap header */
+ const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect;
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_range_deserialize)
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_row_serialize)
/* Check arguments. */
+ HDassert(cls);
HDassert(buf);
- HDassert(H5F_addr_defined(sect_addr));
- HDassert(sect_size);
+ HDassert(sect);
+ HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW);
+ HDassert(sect->sect_info.addr == sect->u.row.under->sect_info.addr);
- /* Create free list section node */
- 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")
+ /* Forward to indirect routine to serialize underlying section */
+ hdr = ((H5HF_sect_indirect_private_t *)(cls->cls_private))->hdr;
+ if(H5HF_sect_indirect_serialize(hdr, sect->u.row.under, buf) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSERIALIZE, FAIL, "can't serialize row section's underlying indirect section")
- /* Range's indirect block */
- /* (Section needs to be "revived" before this is correct) */
- new_sect->u.range.iblock = NULL;
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5HF_sect_row_serialize() */
- /* Range's row */
- UINT16DECODE(buf, new_sect->u.range.row);
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_row_deserialize
+ *
+ * Purpose: Deserialize a buffer into a "live" row section
+ *
+ * Note: Actually this routine just forwards to the 'indirect'
+ * deserialize routine, which creates the row section.
+ *
+ * Return: Success: non-negative
+ *
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Saturday, July 15, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5FS_section_info_t *
+H5HF_sect_row_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)
+{
+ H5HF_hdr_t *hdr; /* Fractal heap header */
+ H5FS_section_info_t *ret_value; /* Return value */
- /* Range's column */
- UINT16DECODE(buf, new_sect->u.range.col);
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_row_deserialize)
- /* Range's # of entries */
- UINT16DECODE(buf, new_sect->u.range.num_entries);
+ /* Check arguments. */
+ HDassert(cls);
+ HDassert(buf);
+ HDassert(H5F_addr_defined(sect_addr));
+ HDassert(sect_size);
- /* Set return value */
- ret_value = (H5FS_section_info_t *)new_sect;
+ /* Forward to indirect routine to deserialize underlying section */
+ hdr = ((H5HF_sect_indirect_private_t *)(cls->cls_private))->hdr;
+ if(NULL == (ret_value = H5HF_sect_indirect_deserialize(hdr, dxpl_id, buf,
+ sect_addr, sect_size, des_flags)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDECODE, NULL, "can't deserialize row section's underlying indirect section")
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5HF_sect_range_deserialize() */
+} /* H5HF_sect_row_deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5HF_sect_range_can_merge
+ * Function: H5HF_sect_row_can_merge
*
* Purpose: Can two sections of this type merge?
*
@@ -1172,23 +1487,21 @@ done:
* Failure: negative
*
* Programmer: Quincey Koziol
- * Monday, June 5, 2006
+ * Thursday, July 6, 2006
*
*-------------------------------------------------------------------------
*/
static htri_t
-H5HF_sect_range_can_merge(H5FS_section_info_t *_sect1,
+H5HF_sect_row_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 */
- 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)
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_row_can_merge)
/* Check arguments. */
HDassert(sect1);
@@ -1196,80 +1509,65 @@ H5HF_sect_range_can_merge(H5FS_section_info_t *_sect1,
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"));
+HDfprintf(stderr, "%s: sect1->sect_info = {%a, %Hu, %u, %s}\n", "H5HF_sect_row_can_merge", 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", "H5HF_sect_row_can_merge", 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 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 to see if we should revive the 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 = 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);
+HDfprintf(stderr, "%s: sect1->u.row = {%p, %u, %u, %u, %t}\n", "H5HF_sect_row_can_merge", sect1->u.row.under, sect1->u.row.row, sect1->u.row.col, sect1->u.row.num_entries, sect1->u.row.checked_out);
+if(sect2->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW ||
+ sect2->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW)
+ HDfprintf(stderr, "%s: sect2->u.row = {%p, %u, %u, %u, %t}\n", "H5HF_sect_row_can_merge", sect2->u.row.under, sect2->u.row.row, sect2->u.row.col, sect2->u.row.num_entries, sect2->u.row.checked_out);
#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 */
+ /* Row section can only merge with other row sections */
+ if(!((sect1->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW ||
+ sect1->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW)
+ && (sect2->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW ||
+ sect2->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW)))
+ HGOTO_DONE(FALSE)
#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);
-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: hdr->man_iter_off = %Hu\n", "H5HF_sect_row_can_merge", hdr->man_iter_off);
#endif /* QAK */
+ /* If second section is after current 'next block' iterator and it's the
+ * last row in the underlying indirect section, it should go away
+ */
+ if(sect2->sect_info.addr >= hdr->man_iter_off && H5HF_sect_indirect_is_last_row(sect2))
+ HGOTO_DONE(TRUE)
- /* Range section can only merge with other range sections */
- if(sect1->sect_info.type != sect2->sect_info.type)
- HGOTO_DONE(FALSE)
+ /* Check if second section shares the same underlying indirect block as
+ * the first section, but doesn't already have same underlying indirect
+ * section.
+ */
+ if(H5HF_sect_row_iblock_same(sect1, sect2)) {
+ HDassert((sect1->u.row.row != sect2->u.row.row) ||
+ (((sect1->u.row.col + sect1->u.row.num_entries) - 1)
+ < sect2->u.row.col));
+ if(sect1->u.row.under != sect2->u.row.under) {
+ size_t dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr); /* Direct block's overhead */
#ifdef QAK
-HDfprintf(stderr, "%s: hdr->man_iter_off = %Hu\n", FUNC, hdr->man_iter_off);
+HDfprintf(stderr, "%s: dblock_overhead = %Zu\n", "H5HF_sect_row_can_merge", dblock_overhead);
#endif /* QAK */
- if(sect2->sect_info.addr >= 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)
+ /* Check if second section adjoins first section */
+ if(H5F_addr_eq(sect1->sect_info.addr + (sect1->u.row.num_entries * (sect1->sect_info.size + dblock_overhead)), sect2->sect_info.addr)) {
+ udata->adjoin = TRUE;
+ HGOTO_DONE(TRUE)
+ } /* end if */
+ } /* end if */
+ } /* end if */
done:
#ifdef QAK
-HDfprintf(stderr, "%s: ret_value = %t\n", FUNC, ret_value);
+HDfprintf(stderr, "%s: ret_value = %t\n", "H5HF_sect_row_can_merge", ret_value);
#endif /* QAK */
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5HF_sect_range_can_merge() */
+} /* H5HF_sect_row_can_merge() */
/*-------------------------------------------------------------------------
- * Function: H5HF_sect_range_merge
+ * Function: H5HF_sect_row_merge
*
* Purpose: Merge two sections of this type
*
@@ -1280,57 +1578,85 @@ HDfprintf(stderr, "%s: ret_value = %t\n", FUNC, ret_value);
* Failure: negative
*
* Programmer: Quincey Koziol
- * Monday, June 5, 2006
+ * Thursday, July 6, 2006
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5HF_sect_range_merge(H5FS_section_info_t *_sect1, H5FS_section_info_t *_sect2,
+H5HF_sect_row_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 */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_range_merge)
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_row_merge)
/* Check arguments. */
HDassert(sect1);
- HDassert(sect1->sect_info.type == H5HF_FSPACE_SECT_RANGE);
+ HDassert(sect1->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW ||
+ sect1->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW);
HDassert(sect2);
- HDassert(sect2->sect_info.type == H5HF_FSPACE_SECT_RANGE);
+ HDassert(sect2->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW ||
+ sect2->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW);
#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);
+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 */
- /* 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;
+ /* Check to see if we should revive second section */
+ if(sect2->sect_info.state != H5FS_SECT_LIVE)
+ if(H5HF_sect_row_revive(hdr, dxpl_id, sect2) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive single free section")
+#ifdef QAK
+HDfprintf(stderr, "%s: sect2->u.row = {%p, %u, %u, %u}\n", FUNC, sect2->u.row.under, sect2->u.row.row, sect2->u.row.col, sect2->u.row.num_entries);
+#endif /* QAK */
- /* 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 rows adjoin each other */
+ /* (as opposed to second row just being after the end of the heap and
+ * needed to be pruned away)
+ */
+ if(udata->adjoin) {
+#ifdef QAK
+HDfprintf(stderr, "%s: Merging underlying indirect blocks\n", FUNC);
+#endif /* QAK */
+ /* Check to see if we should revive first section */
+ if(sect1->sect_info.state != H5FS_SECT_LIVE)
+ if(H5HF_sect_row_revive(hdr, dxpl_id, sect1) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive single free section")
+#ifdef QAK
+HDfprintf(stderr, "%s: sect1->u.row = {%p, %u, %u, %u}\n", FUNC, sect1->u.row.under, sect1->u.row.row, sect1->u.row.col, sect1->u.row.num_entries);
+#endif /* QAK */
- /* 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")
+ /* Merge rows' underlying indirect sections together */
+ if(H5HF_sect_indirect_merge_row(hdr, dxpl_id, sect1, sect2) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTMERGE, FAIL, "can't merge underlying indirect sections")
} /* end if */
+ else {
+#ifdef QAK
+HDfprintf(stderr, "%s: Shrinking away second section\n", FUNC);
+#endif /* QAK */
+ /* Shrink size of underlying indirect section */
+ if(H5HF_sect_indirect_shrink_row(sect2) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't shrink underlying indirect section")
+
+ /* Get rid of second section */
+ if(H5HF_sect_row_free((H5FS_section_info_t *)sect2) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node")
+ sect2 = NULL;
+ } /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5HF_sect_range_merge() */
+} /* H5HF_sect_row_merge() */
/*-------------------------------------------------------------------------
- * Function: H5HF_sect_range_can_shrink
+ * Function: H5HF_sect_row_can_shrink
*
* Purpose: Can this section shrink the container?
*
@@ -1343,43 +1669,44 @@ done:
* Failure: negative
*
* Programmer: Quincey Koziol
- * Monday, June 5, 2006
+ * Thursday, July 6, 2006
*
*-------------------------------------------------------------------------
*/
static htri_t
-H5HF_sect_range_can_shrink(H5FS_section_info_t *_sect, void UNUSED *_udata)
+H5HF_sect_row_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 */
H5HF_add_ud1_t *udata = (H5HF_add_ud1_t *)_udata; /* User callback data */
H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */
htri_t ret_value = FALSE; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_range_can_shrink)
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_row_can_shrink)
/* Check arguments. */
HDassert(sect);
- HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_RANGE);
+ HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW ||
+ sect->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW);
#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);
+HDfprintf(stderr, "%s: sect->sect_info = {%a, %Hu, %u, %s}\n", "H5HF_sect_row_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.row = {%p, %u, %u, %u}\n", "H5HF_sect_row_can_shrink", sect->u.row.under, sect->u.row.row, sect->u.row.col, sect->u.row.num_entries);
#endif /* QAK */
/* Check if section is past end of "next block" iterator */
#ifdef QAK
-HDfprintf(stderr, "%s: hdr->man_iter_off = %Hu\n", "H5HF_sect_range_can_shrink", hdr->man_iter_off);
+HDfprintf(stderr, "%s: hdr->man_iter_off = %Hu\n", "H5HF_sect_row_can_shrink", hdr->man_iter_off);
#endif /* QAK */
- if(sect->sect_info.addr >= hdr->man_iter_off)
+ if(sect->sect_info.addr >= hdr->man_iter_off && H5HF_sect_indirect_is_last_row(sect))
HGOTO_DONE(TRUE)
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5HF_sect_range_can_shrink() */
+} /* H5HF_sect_row_can_shrink() */
/*-------------------------------------------------------------------------
- * Function: H5HF_sect_range_shrink
+ * Function: H5HF_sect_row_shrink
*
* Purpose: Shrink container with section
*
@@ -1388,30 +1715,35 @@ done:
* Failure: negative
*
* Programmer: Quincey Koziol
- * Monday, June 5, 2006
+ * Thursday, July 6, 2006
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5HF_sect_range_shrink(H5FS_section_info_t **_sect, void UNUSED *_udata)
+H5HF_sect_row_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)
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_row_shrink)
/* Check arguments. */
HDassert(sect);
HDassert(*sect);
- HDassert((*sect)->sect_info.type == H5HF_FSPACE_SECT_RANGE);
+ HDassert((*sect)->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW ||
+ (*sect)->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW);
#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);
+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"));
+HDfprintf(stderr, "%s: (*sect)->u.row = {%p, %u, %u, %u}\n", FUNC, (*sect)->u.row.under, (*sect)->u.row.row, (*sect)->u.row.col, (*sect)->u.row.num_entries);
#endif /* QAK */
+ /* Shrink size of underlying indirect section */
+ if(H5HF_sect_indirect_shrink_row(*sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't shrink underlying indirect section")
+
/* Get rid of section */
- if(H5HF_sect_range_free((H5FS_section_info_t *)*sect) < 0)
+ if(H5HF_sect_row_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 */
@@ -1419,88 +1751,344 @@ HDfprintf(stderr, "%s: (*sect).u.range = {%p, %u, %u, %u}\n", FUNC, (*sect)->u.r
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5HF_sect_range_shrink() */
+} /* H5HF_sect_row_shrink() */
/*-------------------------------------------------------------------------
- * Function: H5HF_sect_range_free
+ * Function: H5HF_sect_row_free
*
- * Purpose: Free a 'range' section node
+ * Purpose: Free a 'row' section node
*
* Return: Success: non-negative
*
* Failure: negative
*
* Programmer: Quincey Koziol
- * Wednesday, May 17, 2006
+ * Thursday, July 6, 2006
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5HF_sect_range_free(H5FS_section_info_t *_sect)
+H5HF_sect_row_free(H5FS_section_info_t *_sect)
{
H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Pointer to section to free */
- H5HF_indirect_t *parent = NULL; /* Parent indirect block for section */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_range_free)
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_row_free)
HDassert(sect);
+ HDassert(sect->u.row.under);
- /* Check for live reference to an indirect block */
- if(sect->sect_info.state == H5FS_SECT_LIVE) {
- /* Get parent indirect block, if there was one */
- if(sect->u.range.iblock)
- parent = sect->u.range.iblock;
- } /* end if */
+ /* Decrement the ref. count on the row section's underlying indirect section */
+ if(H5HF_sect_indirect_decr(sect->u.row.under) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't detach section node")
/* Release the section */
- if(H5HF_sect_node_free(sect, parent) < 0)
+ if(H5HF_sect_node_free(sect, NULL) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node")
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5HF_sect_range_free() */
+} /* H5HF_sect_row_free() */
/*-------------------------------------------------------------------------
- * Function: H5HF_sect_range_debug
+ * Function: H5HF_sect_row_valid
*
- * Purpose: Dump debugging information about an range free space section
+ * Purpose: Check the validity of a section
*
* Return: Success: non-negative
- *
* Failure: negative
*
* Programmer: Quincey Koziol
- * Saturday, May 13, 2006
+ * Friday, July 21, 2006
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5HF_sect_range_debug(const H5FS_section_info_t *_sect,
- FILE *stream, int indent, int fwidth)
+H5HF_sect_row_valid(const H5FS_section_class_t *cls, const H5FS_section_info_t *_sect)
{
- const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Section to dump info */
+ const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Pointer to section to check */
+ const H5HF_free_section_t *indir_sect; /* Pointer to underlying indirect section */
+ unsigned indir_idx; /* Index of row in underlying indirect section's row array */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_range_debug)
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_row_valid)
- /* Check arguments. */
+ HDassert(cls);
HDassert(sect);
- /* Print range section information */
- HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
- "Row:",
- sect->u.range.row);
- HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
- "Column:",
- sect->u.range.col);
- HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
- "Number of entries:",
- sect->u.range.num_entries);
+#ifdef QAK
+HDfprintf(stderr, "%s: sect->sect_info = {%a, %Hu, %u, %s}\n", "H5HF_sect_row_valid", 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.row = {%p, %u, %u, %u, %t}\n", "H5HF_sect_row_valid", sect->u.row.under, sect->u.row.row, sect->u.row.col, sect->u.row.num_entries, sect->u.row.checked_out);
+#endif /* QAK */
+ /* Sanity checking on the row */
+ HDassert(sect->u.row.under);
+ HDassert(sect->u.row.num_entries);
+ HDassert(sect->u.row.checked_out == FALSE);
+ indir_sect = sect->u.row.under;
+ indir_idx = sect->u.row.row - indir_sect->u.indirect.row;
+#ifdef QAK
+HDfprintf(stderr, "%s: indir_idx = %u\n", "H5HF_sect_row_valid", indir_idx);
+#endif /* QAK */
+ HDassert(indir_sect->u.indirect.dir_rows[indir_idx] == sect);
+
+ /* Different checking for different kinds of rows */
+ if(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW) {
+ /* Some extra sanity checks on the row */
+ HDassert(sect->u.row.row == indir_sect->u.indirect.row);
+
+ /* Check that the row's underlying indirect section is valid */
+ H5HF_sect_indirect_valid(cls, sect);
+ } /* end if */
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5HF_sect_range_debug() */
+} /* H5HF_sect_row_valid() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_indirect_span_size
+ *
+ * Purpose: Compute the span size covered by an indirect section
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * July 3 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_sect_indirect_span_size(H5HF_hdr_t *hdr, H5HF_free_section_t *sect)
+{
+ unsigned start_row; /* Row for first block covered */
+ unsigned start_col; /* Column for first block covered */
+ unsigned start_entry; /* Entry for first block covered */
+ unsigned end_row; /* Row for last block covered */
+ unsigned end_col; /* Column for last block covered */
+ unsigned end_entry; /* Entry for last block covered */
+ hsize_t acc_span_size; /* Accumulated span size */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_indirect_span_size)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+ HDassert(sect);
+ HDassert(sect->u.indirect.num_entries > 0);
+
+ /* Compute starting entry, column & row */
+ start_row = sect->u.indirect.row;
+ start_col = sect->u.indirect.col;
+ start_entry = (start_row * hdr->man_dtable.cparam.width) + start_col;
+
+ /* Compute ending entry, column & row */
+ end_entry = (start_entry + sect->u.indirect.num_entries) - 1;
+ end_row = end_entry / hdr->man_dtable.cparam.width;
+ end_col = end_entry % hdr->man_dtable.cparam.width;
+#ifdef QAK
+HDfprintf(stderr, "%s: start_row = %u, start_col = %u, start_entry = %u\n", "H5HF_sect_indirect_span_size", start_row, start_col, start_entry);
+HDfprintf(stderr, "%s: end_row = %u, end_col = %u, end_entry = %u\n", "H5HF_sect_indirect_span_size", end_row, end_col, end_entry);
+#endif /* QAK */
+
+ /* Initialize accumulated span size */
+ acc_span_size = 0;
+
+ /* Compute span size covered */
+
+ /* Check for multi-row span */
+ if(start_row != end_row) {
+ /* Accomodate partial starting row */
+ if(start_col > 0) {
+ acc_span_size = hdr->man_dtable.row_block_size[start_row] *
+ (hdr->man_dtable.cparam.width - start_col);
+ start_row++;
+ } /* end if */
+
+ /* Accumulate full rows */
+ while(start_row < end_row) {
+ acc_span_size += hdr->man_dtable.row_block_size[start_row] *
+ hdr->man_dtable.cparam.width;
+ start_row++;
+ } /* end while */
+
+ /* Accomodate partial ending row */
+ acc_span_size += hdr->man_dtable.row_block_size[start_row] *
+ (end_col + 1);
+ } /* end if */
+ else {
+ /* Span is in same row */
+ acc_span_size = hdr->man_dtable.row_block_size[start_row] *
+ ((end_col - start_col) + 1);
+ } /* end else */
+
+ /* Set the span size for the indirect section */
+#ifdef QAK
+HDfprintf(stderr, "%s: acc_span_size = %Hu\n", "H5HF_sect_indirect_span_size", acc_span_size);
+#endif /* QAK */
+ sect->u.indirect.span_size = acc_span_size;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5HF_sect_indirect_span_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_indirect_iblock_entries
+ *
+ * Purpose: Compute the number of entries for the iblock that an
+ * indirect section is located in
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * July 3 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_sect_indirect_iblock_entries(H5HF_hdr_t *hdr, H5HF_free_section_t *sect)
+{
+ unsigned nrows; /* Number of rows in target indirect block */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_iblock_entries)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+ HDassert(sect);
+
+ /* If the section is 'live', just use it's indirect block */
+ if(sect->sect_info.state == H5FS_SECT_LIVE) {
+ HDassert(sect->u.indirect.u.iblock);
+ nrows = sect->u.indirect.u.iblock->nrows;
+ } /* end if */
+ else {
+ hsize_t curr_off; /* Current search offset */
+ hsize_t iblock_off; /* Temporary copy of indirect block's offset */
+ unsigned curr_row, curr_col; /* Current search row & column */
+
+ /* Set starting offset for search */
+ iblock_off = sect->u.indirect.u.iblock_off;
+
+ curr_off = 0;
+ do {
+ /* Compute block's new offset */
+ iblock_off -= curr_off;
+
+ /* Look up row & column in new indirect block for object */
+ if(H5HF_dtable_lookup(&hdr->man_dtable, iblock_off, &curr_row, &curr_col) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of object")
+ HDassert(curr_row >= hdr->man_dtable.max_direct_rows);
+
+ /* Compute offset of block indicated */
+ curr_off = hdr->man_dtable.row_block_off[curr_row] +
+ hdr->man_dtable.row_block_size[curr_row] * curr_col;
+ } while(curr_off != iblock_off);
+
+ /* Compute # of rows in indirect block */
+ nrows = (H5V_log2_gen(hdr->man_dtable.row_block_size[curr_row]) - hdr->man_dtable.first_row_bits) + 1;
+#ifdef QAK
+HDfprintf(stderr, "%s: nrows = %u\n", FUNC, nrows);
+#endif /* QAK */
+ } /* end else */
+ HDassert(nrows);
+
+ /* Compute number of entries in indirect block */
+ sect->u.indirect.iblock_entries = hdr->man_dtable.cparam.width * nrows;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_sect_indirect_iblock_entries() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_indirect_iblock_same
+ *
+ * Purpose: Check if two indirect sections are located in the same indirect block
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * July 6 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static htri_t
+H5HF_sect_indirect_iblock_same(const H5HF_free_section_t *sect1,
+ const H5HF_free_section_t *sect2)
+{
+ htri_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_indirect_iblock_same)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(sect1);
+ HDassert(sect2);
+
+ ret_value = ((sect1->sect_info.state == H5FS_SECT_LIVE ? sect1->u.indirect.u.iblock->block_off : sect1->u.indirect.u.iblock_off)
+ == (sect2->sect_info.state == H5FS_SECT_LIVE ? sect2->u.indirect.u.iblock->block_off : sect2->u.indirect.u.iblock_off));
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Leaving, ret_value = %t\n", "H5HF_sect_indirect_iblock_same", ret_value);
+#endif /* QAK */
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_sect_indirect_iblock_same() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_indirect_is_last_row
+ *
+ * Purpose: Check if a row is the last row in an indirect section
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * July 18 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static hbool_t
+H5HF_sect_indirect_is_last_row(const H5HF_free_section_t *row_sect)
+{
+ const H5HF_free_section_t *sect; /* Underlying indirect section */
+ hbool_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_indirect_is_last_row)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(row_sect);
+
+ /* Check for any child indirect sections or if this row is not the last row */
+ sect = row_sect->u.row.under;
+#ifdef QAK
+HDfprintf(stderr, "%s: sect->u.indirect.indir_nents = %u\n", "H5HF_sect_indirect_is_last_row", sect->u.indirect.indir_nents);
+HDfprintf(stderr, "%s: sect->u.indirect.row = %u\n", "H5HF_sect_indirect_is_last_row", sect->u.indirect.row);
+HDfprintf(stderr, "%s: sect->u.indirect.dir_nrows = %u\n", "H5HF_sect_indirect_is_last_row", sect->u.indirect.dir_nrows);
+HDfprintf(stderr, "%s: row_sect->u.row.row = %u\n", "H5HF_sect_indirect_is_last_row", row_sect->u.row.row);
+#endif /* QAK */
+ if(sect->u.indirect.indir_nents > 0)
+ ret_value = FALSE;
+ else if(((sect->u.indirect.row + sect->u.indirect.dir_nrows) - 1) ==
+ row_sect->u.row.row)
+ ret_value = TRUE;
+ else
+ ret_value = FALSE;
+
+#ifdef QAK
+HDfprintf(stderr, "%s: ret_value = %t\n", "H5HF_sect_indirect_is_last_row", ret_value);
+#endif /* QAK */
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_sect_indirect_is_last_row() */
/*-------------------------------------------------------------------------
@@ -1513,99 +2101,595 @@ H5HF_sect_range_debug(const H5FS_section_info_t *_sect,
* Failure: negative
*
* Programmer: Quincey Koziol
- * Monday, May 1, 2006
+ * Monday, July 3, 2006
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5HF_sect_indirect_init_cls(H5FS_section_class_t *cls, const void UNUSED *udata)
+H5HF_sect_indirect_init_cls(H5FS_section_class_t *cls, void *_udata)
{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_indirect_init_cls)
+ H5HF_hdr_t *hdr = (H5HF_hdr_t *)_udata; /* Fractal heap header */
+ H5HF_sect_indirect_private_t *cls_prvt; /* Pointer to class private info */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_init_cls)
/* Check arguments. */
HDassert(cls);
+ HDassert(!cls->cls_private);
+
+ /* Allocate & initialize the class-private (i.e. private shared) information
+ * for this type of section
+ */
+ if(NULL == (cls_prvt = H5MM_malloc(sizeof(H5HF_sect_indirect_private_t))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ cls_prvt->hdr = hdr;
+ cls->cls_private = cls_prvt;
/* Set the size of all serialized objects of this class of sections */
- cls->serial_size = 2 /* Row */
+ cls->serial_size = hdr->heap_off_size /* Indirect block's offset in "heap space" */
+ + 2 /* Row */
+ 2 /* Column */
- + 2 /* # of entries */
- + 2 /* Indirect row */
- + 2; /* Indirect # of rows */
+ + 2; /* # of entries */
- FUNC_LEAVE_NOAPI(SUCCEED)
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* H5HF_sect_indirect_init_cls() */
/*-------------------------------------------------------------------------
- * Function: H5HF_sect_indirect_add
+ * Function: H5HF_sect_indirect_term_cls
*
- * Purpose: Add a new 'indirect' section to the free space manager for this
- * heap
+ * Purpose: Terminate the "indirect" class structure
+ *
+ * Return: Success: non-negative
+ *
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Monday, July 3, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_sect_indirect_term_cls(H5FS_section_class_t *cls)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_indirect_term_cls)
+
+ /* Check arguments. */
+ HDassert(cls);
+
+ /* Free the class private information */
+ cls->cls_private = H5MM_xfree(cls->cls_private);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5HF_sect_indirect_term_cls() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_indirect_new
+ *
+ * Purpose: Create a new 'indirect' section for other routines to finish
+ * initializing.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
- * May 30 2006
+ * July 6 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)
+static H5HF_free_section_t *
+H5HF_sect_indirect_new(haddr_t sect_off, hsize_t sect_size,
+ H5HF_indirect_t *iblock, hsize_t iblock_off, unsigned row, unsigned col,
+ unsigned nentries)
{
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 */
+ H5HF_free_section_t *ret_value; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_add)
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_new)
/*
* 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")
+ if(NULL == (sect = H5HF_sect_node_new(H5HF_FSPACE_SECT_INDIRECT, sect_off,
+ sect_size, (iblock ? H5FS_SECT_LIVE : H5FS_SECT_SERIALIZED))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "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;
+ if(iblock) {
+ sect->u.indirect.u.iblock = iblock;
+ if(H5HF_iblock_incr(sect->u.indirect.u.iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared indirect block")
+ iblock_incr = TRUE;
+ } /* end if */
+ else
+ sect->u.indirect.u.iblock_off = iblock_off;
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")
+ /* Reset the non-stored fields, they are computed later, on demand */
+ sect->u.indirect.span_size = 0;
+ sect->u.indirect.iblock_entries = 0;
+
+ /* This indirect section doesn't (currently) have a parent */
+ sect->u.indirect.parent = NULL;
+ sect->u.indirect.par_entry = 0;
+
+ /* Set return value */
+ ret_value = sect;
done:
- if(ret_value < 0 && sect) {
+ if(!ret_value && 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")
+ if(H5HF_iblock_decr(sect->u.indirect.u.iblock) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTDEC, NULL, "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_new() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_indirect_row
+ *
+ * Purpose: Create the underlying indirect section for a new row section
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * July 6 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5HF_free_section_t *
+H5HF_sect_indirect_for_row(H5HF_hdr_t *hdr, H5HF_indirect_t *iblock,
+ H5HF_free_section_t *row_sect)
+{
+ H5HF_free_section_t *sect = NULL; /* 'Indirect' free space section to add */
+ H5HF_free_section_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_for_row)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+ HDassert(iblock);
+ HDassert(row_sect);
+ HDassert(row_sect->u.row.row < hdr->man_dtable.max_direct_rows);
+#ifdef QAK
+HDfprintf(stderr, "%s: Entering\n", FUNC);
+#endif /* QAK */
+
+ /* Create free space section node */
+ if(NULL == (sect = H5HF_sect_indirect_new(row_sect->sect_info.addr,
+ row_sect->sect_info.size, iblock, iblock->block_off,
+ row_sect->u.row.row, row_sect->u.row.col, row_sect->u.row.num_entries)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't create indirect section")
+
+ /* Set # of direct rows covered */
+ sect->u.indirect.dir_nrows = 1;
+
+ /* Allocate space for the derived row sections */
+ if(NULL == (sect->u.indirect.dir_rows = H5MM_malloc(sizeof(H5HF_free_section_t *))))
+ HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, NULL, "allocation failed for row section pointer array")
+
+ /* Atatch the new row section to indirect section */
+ sect->u.indirect.dir_rows[0] = row_sect;
+ sect->u.indirect.rc = 1;
+
+ /* No indirect rows in current section */
+ sect->u.indirect.indir_nents = 0;
+ sect->u.indirect.indir_ents = NULL;
+
+ /* Set return value */
+ ret_value = sect;
+
+done:
+ if(!ret_value && sect)
+ if(H5HF_sect_indirect_free(sect) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTRELEASE, NULL, "can't free indirect section node")
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Leaving\n", FUNC);
+#endif /* QAK */
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_sect_indirect_for_row() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_indirect_init_rows
+ *
+ * Purpose: Initialize the derived row sections for a newly created
+ * indirect section
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * July 6 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_sect_indirect_init_rows(H5HF_hdr_t *hdr, hid_t dxpl_id,
+ H5HF_free_section_t *sect, hbool_t first_child, unsigned space_flags,
+ unsigned start_row, unsigned start_col,
+ unsigned end_row, unsigned end_col)
+{
+ hsize_t curr_off; /* Offset of new section in "heap space" */
+ size_t dblock_overhead; /* Direct block's overhead */
+ unsigned row_entries; /* # of entries in row */
+ unsigned row_col; /* Column within current row */
+ unsigned curr_entry; /* Current entry within indirect section */
+ unsigned curr_indir_entry; /* Current indirect entry within indirect section */
+ unsigned curr_row; /* Current row within indirect section */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_init_rows)
+#ifdef QAK
+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"));
+HDfprintf(stderr, "%s: first_child = %t\n", FUNC, first_child);
+HDfprintf(stderr, "%s: start_row = %u, start_col = %u\n", FUNC, start_row, start_col);
+HDfprintf(stderr, "%s: end_row = %u, end_col = %u\n", FUNC, end_row, end_col);
+#endif /* QAK */
+
+ /*
+ * Check arguments.
+ */
+ HDassert(sect);
+
+ /* Reset reference count for indirect section */
+ sect->u.indirect.rc = 0;
+
+ /* Set up direct block information, if necessary */
+ if(start_row < hdr->man_dtable.max_direct_rows) {
+ unsigned max_direct_row; /* Max. direct row covered */
+
+ /* Compute max. direct row covered by indirect section */
+ max_direct_row = MIN(end_row, (hdr->man_dtable.max_direct_rows - 1));
+
+ /* Compute # of direct rows covered */
+ sect->u.indirect.dir_nrows = (max_direct_row - start_row) + 1;
+
+ /* Allocate space for the derived row sections */
+ if(NULL == (sect->u.indirect.dir_rows = H5MM_malloc(sizeof(H5HF_free_section_t *) * sect->u.indirect.dir_nrows)))
+ HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for row section pointer array")
+ } /* end if */
+ else {
+ /* No rows of direct blocks covered, reset direct row information */
+ sect->u.indirect.dir_nrows = 0;
+ sect->u.indirect.dir_rows = NULL;
+ } /* end else */
+
+ /* Set up indirect block information, if necessary */
+ if(end_row >= hdr->man_dtable.max_direct_rows) {
+ unsigned indirect_start_row; /* Row to start indirect entries on */
+ unsigned indirect_start_col; /* Column to start indirect entries on */
+ unsigned indirect_start_entry; /* Index of starting indirect entry */
+ unsigned indirect_end_entry; /* Index of ending indirect entry */
+
+ /* Compute starting indirect entry */
+ if(start_row < hdr->man_dtable.max_direct_rows) {
+ indirect_start_row = hdr->man_dtable.max_direct_rows;
+ indirect_start_col = 0;
+ } /* end if */
+ else {
+ indirect_start_row = start_row;
+ indirect_start_col = start_col;
+ } /* end else */
+ indirect_start_entry = (indirect_start_row * hdr->man_dtable.cparam.width)
+ + indirect_start_col;
+
+ /* Compute ending indirect entry */
+ indirect_end_entry = (end_row * hdr->man_dtable.cparam.width) +
+ end_col;
+
+ /* Compute # of indirect entries covered */
+ sect->u.indirect.indir_nents = (indirect_end_entry - indirect_start_entry) + 1;
+
+ /* Allocate space for the child indirect sections */
+ if(NULL == (sect->u.indirect.indir_ents = H5MM_malloc(sizeof(H5HF_free_section_t *) * sect->u.indirect.indir_nents)))
+ HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for indirect section pointer array")
+ } /* end if */
+ else {
+ /* No indirect block entries covered, reset indirect row information */
+ sect->u.indirect.indir_nents = 0;
+ sect->u.indirect.indir_ents = NULL;
+ } /* end else */
+
+ /* Set up initial row information */
+ if(start_row == end_row)
+ row_entries = (end_col - start_col) + 1;
+ else
+ row_entries = hdr->man_dtable.cparam.width - start_col;
+ row_col = start_col;
+
+ /* Loop over creating the sections covered by this indirect section */
+ curr_off = sect->sect_info.addr;
+ curr_entry = (start_row * hdr->man_dtable.cparam.width) + start_col;
+ curr_row = 0;
+ curr_indir_entry = 0;
+ dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr);
+ for(u = start_row; u <= end_row; u++, curr_row++) {
+ if(u < hdr->man_dtable.max_direct_rows) {
+ H5HF_free_section_t *row_sect = NULL; /* 'Row' free space section to add */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Creating direct row, row_col = %u, row_entries = %u\n", FUNC, row_col, row_entries);
+#endif /* QAK */
+ /* Create 'row' free space section node */
+ if(NULL == (row_sect = H5HF_sect_row_create(curr_off,
+ (hdr->man_dtable.row_block_size[u] - dblock_overhead), first_child, u, row_col,
+ row_entries, sect)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, "creation failed for child row section")
+
+ /* Add new row section to array for indirect section */
+ sect->u.indirect.dir_rows[curr_row] = row_sect;
+
+ /* Add new row section to free space manager for the heap */
+ if(H5HF_space_add(hdr, dxpl_id, row_sect, space_flags) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add row section to free space")
+
+ /* Add new row section to array for indirect section */
+ sect->u.indirect.rc++;
+
+ /* Advance the offset to the next section */
+ curr_off += row_entries * hdr->man_dtable.row_block_size[u];
+
+ /* Advance the current entry to the next row*/
+ curr_entry += row_entries;
+
+ /* Reset the 'first child' flag */
+ first_child = FALSE;
+ } /* end if */
+ else {
+ H5HF_indirect_t *child_iblock; /* Child indirect block */
+ H5HF_free_section_t *child_sect; /* Child 'indirect' section to add */
+ unsigned child_nrows; /* Number of child rows in indirect blocks for this row */
+ unsigned child_nentries; /* Number of child entries in indirect blocks for this row */
+ unsigned v; /* Local index variable */
+
+ /* Compute info about row's indirect blocks for child section */
+ child_nrows = H5HF_dtable_size_to_rows(&hdr->man_dtable, hdr->man_dtable.row_block_size[u]);
+ child_nentries = child_nrows * hdr->man_dtable.cparam.width;
+#ifdef QAK
+HDfprintf(stderr, "%s: child_nrows = %u\n", FUNC, child_nrows);
+HDfprintf(stderr, "%s: child_nentries = %u\n", FUNC, child_nentries);
+HDfprintf(stderr, "%s: row_entries = %u\n", FUNC, row_entries);
+#endif /* QAK */
+
+ /* Add an indirect section for each indirect block in the row */
+ for(v = 0; v < row_entries; v++) {
+ /* Try to get the child section's indirect block, if it's available */
+ if(sect->sect_info.state == H5FS_SECT_LIVE) {
+ haddr_t child_iblock_addr; /* Child indirect block's address on disk */
+
+ /* Get the address of the child indirect block */
+ if(H5HF_man_iblock_entry_addr(sect->u.indirect.u.iblock, curr_entry, &child_iblock_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to retrieve child indirect block's address")
+#ifdef QAK
+HDfprintf(stderr, "%s: child_iblock_addr = %a\n", FUNC, child_iblock_addr);
+#endif /* QAK */
+
+ /* If the child indirect block's address is defined, protect it */
+ if(H5F_addr_defined(child_iblock_addr)) {
+ if(NULL == (child_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, child_iblock_addr, child_nrows, NULL, 0, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
+ } /* end if */
+ else
+ child_iblock = NULL;
+ } /* end if */
+ else
+ child_iblock = NULL;
+
+ /* Create free space section node */
+ if(NULL == (child_sect = H5HF_sect_indirect_new(curr_off, (hsize_t)0,
+ child_iblock, curr_off, 0, 0, child_nentries)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section")
+
+ /* Initialize rows for new indirect section */
+ if(H5HF_sect_indirect_init_rows(hdr, dxpl_id, child_sect,
+ first_child, space_flags, 0, 0, (child_nrows - 1),
+ (hdr->man_dtable.cparam.width - 1)) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize indirect section")
+
+ /* If we have a valid child indirect block, release it now */
+ if(child_iblock)
+ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, child_iblock->addr, child_iblock, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
+
+ /* Attach child section to this section */
+ child_sect->u.indirect.parent = sect;
+ child_sect->u.indirect.par_entry = curr_entry;
+ sect->u.indirect.indir_ents[curr_indir_entry] = child_sect;
+ sect->u.indirect.rc++;
+
+ /* Advance the offset for the next section */
+ curr_off += hdr->man_dtable.row_block_size[u];
+
+ /* Advance to the next entry */
+ curr_entry++;
+ curr_indir_entry++;
+
+ /* Reset the 'first child' flag */
+ first_child = FALSE;
+ } /* end for */
+ } /* end else */
+
+ /* Compute the # of entries for the next row */
+ if(u < (end_row - 1))
+ row_entries = hdr->man_dtable.cparam.width;
+ else
+ row_entries = end_col + 1;
+
+ /* Reset column for all other rows */
+ row_col = 0;
+ } /* end for */
+ /* Make certain we've tracked the section's dependents correctly */
+ HDassert(sect->u.indirect.rc ==
+ (sect->u.indirect.indir_nents + sect->u.indirect.dir_nrows));
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_sect_indirect_init_rows() */
+
+
+/*-------------------------------------------------------------------------
+ * 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
+ * July 3 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_sect_indirect_add(H5HF_hdr_t *hdr, hid_t dxpl_id,
+ H5HF_indirect_t *iblock, unsigned start_entry, unsigned nentries,
+ hsize_t *end_off /*out*/)
+{
+ H5HF_free_section_t *sect = NULL; /* 'Indirect3' free space section to add */
+ hsize_t sect_off; /* Offset of section in heap space */
+ unsigned start_row; /* Start row in indirect block */
+ unsigned start_col; /* Start column in indirect block */
+ unsigned end_entry; /* End entry in indirect block */
+ unsigned end_row; /* End row in indirect block */
+ unsigned end_col; /* End column in indirect block */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_add)
+#ifdef QAK
+HDfprintf(stderr, "%s: start_entry = %u, nentries = %u\n", FUNC, start_entry, nentries);
+#endif /* QAK */
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+ HDassert(iblock);
+ HDassert(nentries);
+
+ /* Compute starting column & row */
+ start_row = start_entry / hdr->man_dtable.cparam.width;
+ start_col = start_entry % hdr->man_dtable.cparam.width;
+
+ /* Compute end column & row */
+ end_entry = (start_entry + nentries) - 1;
+ end_row = end_entry / hdr->man_dtable.cparam.width;
+ end_col = end_entry % hdr->man_dtable.cparam.width;
+
+ /* Initialize information for rows skipped over */
+ sect_off = iblock->block_off;
+ for(u = 0; u < start_row; u++)
+ sect_off += hdr->man_dtable.row_block_size[u] * hdr->man_dtable.cparam.width;
+ sect_off += hdr->man_dtable.row_block_size[start_row] * start_col;
+#ifdef QAK
+HDfprintf(stderr, "%s: sect_off = %Hu\n", FUNC, sect_off);
+#endif /* QAK */
+
+ /* Create free space section node */
+ if(NULL == (sect = H5HF_sect_indirect_new(sect_off, (hsize_t)0, iblock,
+ iblock->block_off, start_row, start_col, nentries)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section")
+
+ /* Initialize rows for new indirect section */
+ if(H5HF_sect_indirect_init_rows(hdr, dxpl_id, sect, TRUE, 0, start_row,
+ start_col, end_row, end_col) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize indirect section")
+
+ /* Get end of section offset to return, if requested */
+ if(end_off) {
+ /* Set the span size of the new section */
+ if(H5HF_sect_indirect_span_size(hdr, sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute span size of section")
+
+ /* Compute the end of the section */
+ *end_off = sect_off + sect->u.indirect.span_size;
+#ifdef QAK
+HDfprintf(stderr, "%s: *end_off = %Hu\n", FUNC, *end_off);
+#endif /* QAK */
+ } /* end if */
+
+done:
+ if(ret_value < 0 && sect)
+ if(H5HF_sect_indirect_free(sect) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node")
+
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_sect_indirect_add() */
/*-------------------------------------------------------------------------
- * Function: H5HF_sect_indirect_revive
+ * Function: H5HF_sect_indirect_decr
+ *
+ * Purpose: Decrement ref. count on indirect section
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * July 6 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_sect_indirect_decr(H5HF_free_section_t *sect)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_decr)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(sect);
+ HDassert(sect->u.indirect.rc);
+#ifdef QAK
+HDfprintf(stderr, "%s: sect->u.indirect.rc = %u\n", FUNC, sect->u.indirect.rc);
+#endif /* QAK */
+
+ /* Decrement ref. count for indirect section */
+ sect->u.indirect.rc--;
+
+ /* If the indirect section's ref. count drops to zero, free the section */
+ if(sect->u.indirect.rc == 0) {
+ /* Decrement ref. count on indirect section's parent */
+ if(sect->u.indirect.parent)
+ if(H5HF_sect_indirect_decr(sect->u.indirect.parent) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't decrement ref. count on parent indirect section")
+
+ /* Free indirect section */
+ if(H5HF_sect_indirect_free(sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node")
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_sect_indirect_decr() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_indirect_revive_row
*
* Purpose: Update the memory information for a 'indirect' free section
*
@@ -1613,19 +2697,18 @@ done:
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
- * May 8 2006
+ * July 3 2006
*
*-------------------------------------------------------------------------
*/
-herr_t
-H5HF_sect_indirect_revive(H5HF_hdr_t *hdr, hid_t dxpl_id,
- H5HF_free_section_t *sect)
+static herr_t
+H5HF_sect_indirect_revive_row(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect)
{
H5HF_indirect_t *sec_iblock; /* Pointer to section indirect block */
- unsigned sec_entry; /* Entry within section indirect block */
+ unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_revive)
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_revive_row)
/*
* Check arguments.
@@ -1635,7 +2718,11 @@ H5HF_sect_indirect_revive(H5HF_hdr_t *hdr, hid_t dxpl_id,
HDassert(sect->sect_info.state == H5FS_SECT_SERIALIZED);
/* Look up indirect block containing indirect blocks for section */
- if(H5HF_man_locate_block(hdr, dxpl_id, sect->sect_info.addr, TRUE, &sec_iblock, &sec_entry, H5AC_READ) < 0)
+#ifdef QAK
+HDfprintf(stderr, "%s: sect->sect_info.addr = %a\n", FUNC, sect->sect_info.addr);
+HDfprintf(stderr, "%s: sect->u.indirect.u.iblock_off = %Hu\n", FUNC, sect->u.indirect.u.iblock_off);
+#endif /* QAK */
+ if(H5HF_man_locate_block(hdr, dxpl_id, sect->sect_info.addr, FALSE, &sec_iblock, NULL, H5AC_READ) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of section")
/* Increment reference count on indirect block that free section is in */
@@ -1643,7 +2730,7 @@ H5HF_sect_indirect_revive(H5HF_hdr_t *hdr, hid_t dxpl_id,
HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block")
/* Set the pointer to the section's indirect block */
- sect->u.indirect.iblock = sec_iblock;
+ sect->u.indirect.u.iblock = sec_iblock;
/* Unlock indirect block */
if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, sec_iblock->addr, sec_iblock, H5AC__NO_FLAGS_SET) < 0)
@@ -1653,12 +2740,369 @@ H5HF_sect_indirect_revive(H5HF_hdr_t *hdr, hid_t dxpl_id,
/* Section is "live" now */
sect->sect_info.state = H5FS_SECT_LIVE;
+ /* Loop over derived row sections and mark them all as 'live' now */
+ for(u = 0; u < sect->u.indirect.dir_nrows; u++)
+ sect->u.indirect.dir_rows[u]->sect_info.state = H5FS_SECT_LIVE;
+
+ /* Revive parent indirect section, if there is one */
+ if(sect->u.indirect.parent && sect->u.indirect.parent->sect_info.state == H5FS_SECT_SERIALIZED)
+ if(H5HF_sect_indirect_revive(hdr, dxpl_id, sect->u.indirect.parent, sect->u.indirect.u.iblock->parent) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTREVIVE, FAIL, "can't revive indirect section")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_sect_indirect_revive_row() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_indirect_revive
+ *
+ * Purpose: Update the memory information for a 'indirect' free section
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * July 10 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_sect_indirect_revive(H5HF_hdr_t *hdr, hid_t dxpl_id,
+ H5HF_free_section_t *sect, H5HF_indirect_t *sect_iblock)
+{
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_revive)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+ HDassert(sect);
+ HDassert(sect->sect_info.state == H5FS_SECT_SERIALIZED);
+ HDassert(sect_iblock);
+
+#ifdef QAK
+HDfprintf(stderr, "%s: sect->sect_info.addr = %a\n", FUNC, sect->sect_info.addr);
+HDfprintf(stderr, "%s: sect->u.indirect.u.iblock_off = %Hu\n", FUNC, sect->u.indirect.u.iblock_off);
+#endif /* QAK */
+ /* Increment reference count on indirect block that free section is in */
+ if(H5HF_iblock_incr(sect_iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block")
+
+ /* Set the pointer to the section's indirect block */
+ sect->u.indirect.u.iblock = sect_iblock;
+
+ /* Section is "live" now */
+ sect->sect_info.state = H5FS_SECT_LIVE;
+
+ /* Loop over derived row sections and mark them all as 'live' now */
+ for(u = 0; u < sect->u.indirect.dir_nrows; u++)
+ sect->u.indirect.dir_rows[u]->sect_info.state = H5FS_SECT_LIVE;
+
+ /* Revive parent indirect section, if there is one */
+ if(sect->u.indirect.parent && sect->u.indirect.parent->sect_info.state == H5FS_SECT_SERIALIZED)
+ if(H5HF_sect_indirect_revive(hdr, dxpl_id, sect->u.indirect.parent, sect->u.indirect.u.iblock->parent) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTREVIVE, FAIL, "can't revive indirect section")
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_sect_indirect_revive() */
/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_indirect_reduce_row
+ *
+ * Purpose: Remove a block from an 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
+ * July 10 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_sect_indirect_reduce_row(H5HF_hdr_t *hdr, H5HF_free_section_t *row_sect,
+ hbool_t *alloc_from_start)
+{
+ H5HF_free_section_t *sect; /* Indirect3 section underlying row section */
+ unsigned row_start_entry; /* Entry for first block covered in row section */
+ unsigned row_end_entry; /* Entry for last block covered in row section */
+ unsigned row_entry; /* Entry to allocate in row section */
+ unsigned start_entry; /* Entry for first block covered */
+ unsigned start_row; /* Start row in indirect block */
+ unsigned start_col; /* Start column in indirect block */
+ unsigned end_entry; /* Entry for last block covered */
+ unsigned end_row; /* End row in indirect block */
+ unsigned end_col; /* End column in indirect block */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_reduce_row)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+ HDassert(row_sect);
+
+ /* Compute starting & ending information for row section */
+ row_start_entry = (row_sect->u.row.row * hdr->man_dtable.cparam.width) + row_sect->u.row.col;
+ row_end_entry = (row_start_entry + row_sect->u.row.num_entries) - 1;
+#ifdef QAK
+HDfprintf(stderr, "%s: row_sect->sect_info = {%a, %Hu, %u, %s}\n", FUNC, row_sect->sect_info.addr, row_sect->sect_info.size, row_sect->sect_info.type, (row_sect->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED"));
+HDfprintf(stderr, "%s: row_sect->u.row.row = %u, row_sect->u.row.col = %u, row_sect->u.row.num_entries = %u\n", FUNC, row_sect->u.row.row, row_sect->u.row.col, row_sect->u.row.num_entries);
+HDfprintf(stderr, "%s: row_start_entry = %u, row_end_entry = %u\n", FUNC, row_start_entry, row_end_entry);
+#endif /* QAK */
+
+ /* Compute starting & ending information for indirect section */
+ sect = row_sect->u.row.under;
+ start_row = sect->u.indirect.row;
+ start_col = sect->u.indirect.col;
+ start_entry = (start_row * hdr->man_dtable.cparam.width) + start_col;
+ end_entry = (start_entry + sect->u.indirect.num_entries) - 1;
+ end_row = end_entry / hdr->man_dtable.cparam.width;
+ end_col = end_entry % hdr->man_dtable.cparam.width;
+
+ /* Additional sanity check */
+ HDassert(sect->u.indirect.dir_rows);
+ HDassert(sect->u.indirect.dir_rows[(row_sect->u.row.row - start_row)] == row_sect);
+#ifdef QAK
+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"));
+HDfprintf(stderr, "%s: sect->u.indirect.parent = %p, sect->u.indirect.par_entry = %u\n", FUNC, sect->u.indirect.parent, sect->u.indirect.par_entry);
+HDfprintf(stderr, "%s: start_entry = %u, start_row = %u, start_col = %u\n", FUNC, start_entry, start_row, start_col);
+HDfprintf(stderr, "%s: end_entry = %u, end_row = %u, end_col = %u\n", FUNC, end_entry, end_row, end_col);
+#endif /* QAK */
+
+ /* Check if we should allocate from end of indirect section */
+ if(row_end_entry == end_entry && start_row != end_row) {
+ *alloc_from_start = FALSE;
+ row_entry = row_end_entry;
+#ifdef QAK
+HDfprintf(stderr, "%s: Row is at end of indirect section\n", FUNC);
+#endif /* QAK */
+ } /* end if */
+ else {
+ *alloc_from_start = TRUE;
+ row_entry = row_start_entry;
+#ifdef QAK
+HDfprintf(stderr, "%s: Row is NOT at end of indirect section\n", FUNC);
+#endif /* QAK */
+ } /* end else */
+#ifdef QAK
+HDfprintf(stderr, "%s: row_entry = %u\n", FUNC, row_entry);
+#endif /* QAK */
+
+ /* Check if we have a parent section to be detached from */
+ if(sect->u.indirect.parent) {
+ hbool_t is_first; /* Flag to indicate that this section is the first section in hierarchy */
+
+ /* Check if this section is the first section */
+ is_first = H5HF_sect_indirect_is_first(sect);
+
+ /* Remove this indirect section from parent indirect section */
+ if(H5HF_sect_indirect_reduce(hdr, sect->u.indirect.parent, sect->u.indirect.par_entry) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce parent indirect section")
+ sect->u.indirect.parent = NULL;
+ sect->u.indirect.par_entry = 0;
+
+ /* If we weren't the first section, set "first row" for this indirect section */
+ if(!is_first)
+ if(H5HF_sect_indirect_first(hdr, sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't make new 'first row' for indirect section")
+ } /* end if */
+
+ /* Adjust indirect section's span size, if it's set */
+ if(sect->u.indirect.span_size > 0)
+ sect->u.indirect.span_size -= row_sect->sect_info.size;
+
+ /* Check how to adjust section for allocated entry */
+ if(sect->u.indirect.num_entries > 1) {
+ if(row_entry == start_entry) {
+#ifdef QAK
+HDfprintf(stderr, "%s: Entry is at start of indirect section\n", FUNC);
+#endif /* QAK */
+ /* Adjust section start */
+ sect->sect_info.addr += hdr->man_dtable.row_block_size[sect->u.indirect.row];
+
+ /* Adjust block coordinates of span */
+ sect->u.indirect.col++;
+ if(sect->u.indirect.col == hdr->man_dtable.cparam.width) {
+ HDassert(row_sect->u.row.num_entries == 1);
+
+ /* Adjust direct row information */
+ sect->u.indirect.dir_nrows--;
+#ifdef QAK
+HDfprintf(stderr, "%s: sect->u.indirect.dir_nrows = %u\n", FUNC, sect->u.indirect.dir_nrows);
+#endif /* QAK */
+
+ /* Adjust direct row sections for indirect section */
+ if(sect->u.indirect.dir_nrows > 0) {
+ HDmemmove(&sect->u.indirect.dir_rows[0],
+ &sect->u.indirect.dir_rows[1],
+ sect->u.indirect.dir_nrows * sizeof(H5HF_free_section_t *));
+ HDassert(sect->u.indirect.dir_rows[0]);
+
+ /* Make new "first row" in indirect section */
+ if(row_sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW)
+ if(H5HF_sect_row_first(hdr, sect->u.indirect.dir_rows[0]) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't make new 'first row' for indirect section")
+ } /* end if */
+ else {
+ /* Sanity check */
+ HDassert(sect->u.indirect.indir_ents);
+
+ /* Eliminate direct rows for this section */
+ sect->u.indirect.dir_rows = H5MM_xfree(sect->u.indirect.dir_rows);
+
+ /* Make new "first row" in indirect section */
+ if(row_sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW)
+ if(H5HF_sect_indirect_first(hdr, sect->u.indirect.indir_ents[0]) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't make new 'first row' for child indirect section")
+ } /* end else */
+
+ sect->u.indirect.row++;
+ sect->u.indirect.col = 0;
+ } /* end if */
+
+ /* Adjust number of entries covered */
+ sect->u.indirect.num_entries--;
+ } /* end if */
+ else if(row_entry == end_entry) {
+ unsigned new_end_row; /* New end row for entries */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Entry is at end of indirect section\n", FUNC);
+#endif /* QAK */
+ /* Sanity check */
+ HDassert(sect->u.indirect.indir_ents == NULL);
+
+ /* Adjust number of entries covered */
+ sect->u.indirect.num_entries--;
+
+ /* Check for eliminating a direct row */
+ new_end_row = ((start_entry + sect->u.indirect.num_entries) - 1) / hdr->man_dtable.cparam.width;
+ HDassert(new_end_row <= end_row);
+ if(new_end_row < end_row) {
+ HDassert(new_end_row == (end_row - 1));
+ sect->u.indirect.dir_nrows--;
+ } /* end if */
+ } /* end if */
+ else {
+ H5HF_free_section_t *peer_sect; /* Peer indirect section */
+ H5HF_indirect_t *iblock; /* Pointer to indirect block for this section */
+ hsize_t iblock_off; /* Section's indirect block's offset in "heap space" */
+ unsigned peer_nentries; /* Number of entries in new peer indirect section */
+ unsigned peer_dir_nrows; /* Number of direct rows in new peer indirect section */
+ unsigned new_start_row; /* New starting row for current indirect section */
+ unsigned u; /* Local index variable */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Entry is in middle of indirect section\n", FUNC);
+#endif /* QAK */
+ /* Sanity checks */
+ HDassert(row_sect->u.row.col == 0);
+ HDassert(row_sect->u.row.row > 0);
+ HDassert(row_sect->u.row.row < hdr->man_dtable.max_direct_rows);
+ HDassert(row_sect->u.row.num_entries == hdr->man_dtable.cparam.width);
+ HDassert(row_sect->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW);
+
+ /* Compute basic information about peer & current indirect sections */
+ new_start_row = row_sect->u.row.row;
+ peer_nentries = row_entry - start_entry;
+ peer_dir_nrows = new_start_row - start_row;
+#ifdef QAK
+HDfprintf(stderr, "%s: peer_nentries = %u, peer_dir_nrows = %u\n", FUNC, peer_nentries, peer_dir_nrows);
+HDfprintf(stderr, "%s: new_start_row = %u\n", FUNC, new_start_row);
+#endif /* QAK */
+
+ /* Get indirect block information for peer */
+ if(sect->sect_info.state == H5FS_SECT_LIVE) {
+ iblock = sect->u.indirect.u.iblock;
+ iblock_off = sect->u.indirect.u.iblock->block_off;
+ } /* end if */
+ else {
+ iblock = NULL;
+ iblock_off = sect->u.indirect.u.iblock_off;
+ } /* end else */
+#ifdef QAK
+HDfprintf(stderr, "%s: iblock = %p, iblock_off = %Hu\n", FUNC, iblock, iblock_off);
+#endif /* QAK */
+
+ /* Create peer indirect section */
+ if(NULL == (peer_sect = H5HF_sect_indirect_new(sect->sect_info.addr,
+ sect->sect_info.size, iblock, iblock_off, start_row, start_col,
+ peer_nentries)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section")
+
+ /* Set up direct row & indirect entry information for peer section */
+ peer_sect->u.indirect.dir_nrows = peer_dir_nrows;
+ if(NULL == (peer_sect->u.indirect.dir_rows = H5MM_malloc(sizeof(H5HF_free_section_t *) * peer_dir_nrows)))
+ HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for row section pointer array")
+ peer_sect->u.indirect.indir_nents = 0;
+ peer_sect->u.indirect.indir_ents = NULL;
+
+ /* Transfer row sections between current & peer sections */
+ HDmemcpy(&peer_sect->u.indirect.dir_rows[0],
+ &sect->u.indirect.dir_rows[0],
+ (sizeof(H5HF_free_section_t *) * peer_dir_nrows));
+ HDmemmove(&sect->u.indirect.dir_rows[0],
+ &sect->u.indirect.dir_rows[peer_dir_nrows],
+ (sizeof(H5HF_free_section_t *) * (sect->u.indirect.dir_nrows - peer_dir_nrows)));
+ sect->u.indirect.dir_nrows -= peer_dir_nrows;
+ HDassert(row_sect == sect->u.indirect.dir_rows[0]);
+
+ /* Re-target transferred row sections to point to new underlying indirect section */
+ for(u = 0; u < peer_dir_nrows; u++)
+ peer_sect->u.indirect.dir_rows[u]->u.row.under = peer_sect;
+
+ /* Change first row section in indirect section to be the "first row" */
+ /* (But we don't have to tell the free space manager about it,
+ * because the row section is "checked out" from the free space
+ * manager currently.
+ */
+ row_sect->sect_info.type = H5HF_FSPACE_SECT_FIRST_ROW;
+
+ /* Adjust reference counts for current & peer sections */
+ peer_sect->u.indirect.rc = peer_dir_nrows;
+ sect->u.indirect.rc -= peer_dir_nrows;
+
+ /* Transfer/update cached information about indirect block */
+ peer_sect->u.indirect.iblock_entries = sect->u.indirect.iblock_entries;
+ peer_sect->u.indirect.span_size = row_sect->sect_info.addr - peer_sect->sect_info.addr;
+ if(sect->u.indirect.span_size > 0)
+ /* (span for row section has already been removed) */
+ sect->u.indirect.span_size -= peer_sect->u.indirect.span_size;
+
+ /* Update information for current section */
+ sect->sect_info.addr = row_sect->sect_info.addr + hdr->man_dtable.row_block_size[new_start_row];
+ sect->u.indirect.row = new_start_row;
+ sect->u.indirect.col = row_sect->u.row.col + 1;
+ sect->u.indirect.num_entries -= (peer_nentries + 1); /* Transferred entries, plus the entry allocated out of the row */
+
+ /* Make certain we've tracked the sections' dependents correctly */
+ HDassert(sect->u.indirect.rc ==
+ (sect->u.indirect.indir_nents + sect->u.indirect.dir_nrows));
+ HDassert(peer_sect->u.indirect.rc ==
+ (peer_sect->u.indirect.indir_nents + peer_sect->u.indirect.dir_nrows));
+ } /* end else */
+ } /* end if */
+ else {
+ sect->u.indirect.num_entries--;
+ sect->u.indirect.dir_nrows--;
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_sect_indirect_reduce_row() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5HF_sect_indirect_reduce
*
* Purpose: Reduce the size of a indirect section (possibly freeing it)
@@ -1669,14 +3113,20 @@ done:
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
- * May 31 2006
+ * July 10 2006
*
*-------------------------------------------------------------------------
*/
-herr_t
-H5HF_sect_indirect_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id,
- H5HF_free_section_t *sect)
+static herr_t
+H5HF_sect_indirect_reduce(H5HF_hdr_t *hdr, H5HF_free_section_t *sect,
+ unsigned child_entry)
{
+ unsigned start_entry; /* Entry for first block covered */
+ unsigned start_row; /* Start row in indirect block */
+ unsigned start_col; /* Start column in indirect block */
+ unsigned end_entry; /* Entry for last block covered */
+ unsigned end_row; /* End row in indirect block */
+ unsigned end_col; /* End column in indirect block */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_reduce)
@@ -1686,34 +3136,624 @@ H5HF_sect_indirect_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id,
*/
HDassert(hdr);
HDassert(sect);
- HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_INDIRECT);
- HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
+#ifdef QAK
+HDfprintf(stderr, "%s: child_entry = %u\n", FUNC, child_entry);
+#endif /* QAK */
- /* 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")
+ /* Compute starting & ending information for indirect section */
+ start_row = sect->u.indirect.row;
+ start_col = sect->u.indirect.col;
+ start_entry = (start_row * hdr->man_dtable.cparam.width) + start_col;
+ end_entry = (start_entry + sect->u.indirect.num_entries) - 1;
+ end_row = end_entry / hdr->man_dtable.cparam.width;
+ end_col = end_entry % hdr->man_dtable.cparam.width;
+#ifdef QAK
+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"));
+HDfprintf(stderr, "%s: sect->u.indirect.parent = %p, sect->u.indirect.par_entry = %u\n", FUNC, sect->u.indirect.parent, sect->u.indirect.par_entry);
+HDfprintf(stderr, "%s: start_entry = %u, start_row = %u, start_col = %u\n", FUNC, start_entry, start_row, start_col);
+HDfprintf(stderr, "%s: end_entry = %u, end_row = %u, end_col = %u\n", FUNC, end_entry, end_row, end_col);
+#endif /* QAK */
+
+ /* Check how to adjust section for allocated entry */
+ if(sect->u.indirect.num_entries > 1) {
+ /* Check if we have a parent section to be detached from */
+ if(sect->u.indirect.parent) {
+ hbool_t is_first; /* Flag to indicate that this section is the first section in hierarchy */
+
+ /* Check if this section is the first section */
+ is_first = H5HF_sect_indirect_is_first(sect);
+
+ /* Reduce parent indirect section */
+ if(H5HF_sect_indirect_reduce(hdr, sect->u.indirect.parent, sect->u.indirect.par_entry) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce parent indirect section")
+ sect->u.indirect.parent = NULL;
+ sect->u.indirect.par_entry = 0;
+
+ /* If we weren't the first section, set "first row" for this indirect section */
+ if(!is_first)
+ if(H5HF_sect_indirect_first(hdr, sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't make new 'first row' for indirect section")
+ } /* end if */
+
+ /* Check if we can allocate from start of indirect section */
+ if(child_entry == start_entry) {
+#ifdef QAK
+HDfprintf(stderr, "%s: Child is at start of indirect section\n", FUNC);
+#endif /* QAK */
+ /* Sanity check */
+ HDassert(sect->u.indirect.dir_rows == NULL);
+ HDassert(sect->u.indirect.indir_ents);
+
+ /* Adjust section start */
+ sect->sect_info.addr += hdr->man_dtable.row_block_size[start_row];
+
+ /* Adjust span of blocks covered */
+ sect->u.indirect.col++;
+ if(sect->u.indirect.col == hdr->man_dtable.cparam.width) {
+ sect->u.indirect.row++;
+ sect->u.indirect.col = 0;
+ } /* end if */
+ sect->u.indirect.num_entries--;
+ if(sect->u.indirect.span_size > 0)
+ sect->u.indirect.span_size -= hdr->man_dtable.row_block_size[start_row];
+
+ /* Adjust indirect entry information */
+ sect->u.indirect.indir_nents--;
+ HDmemmove(&sect->u.indirect.indir_ents[0],
+ &sect->u.indirect.indir_ents[1],
+ sect->u.indirect.indir_nents * sizeof(H5HF_free_section_t *));
+ HDassert(sect->u.indirect.indir_ents[0]);
+
+ /* Make new "first row" in new first indirect child section */
+ if(H5HF_sect_indirect_first(hdr, sect->u.indirect.indir_ents[0]) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't make new 'first row' for child indirect section")
+ } /* end if */
+ else if(child_entry == end_entry) {
+#ifdef QAK
+HDfprintf(stderr, "%s: Child is at end of indirect section\n", FUNC);
+#endif /* QAK */
+ /* Sanity check */
+ HDassert(sect->u.indirect.indir_ents);
+
+ /* Adjust span of blocks covered */
+ sect->u.indirect.num_entries--;
+ if(sect->u.indirect.span_size > 0)
+ sect->u.indirect.span_size -= hdr->man_dtable.row_block_size[end_row];
+
+ /* Adjust indirect entry information */
+ sect->u.indirect.indir_nents--;
+ if(sect->u.indirect.indir_nents == 0)
+ sect->u.indirect.indir_ents = H5MM_xfree(sect->u.indirect.indir_ents);
+ } /* end if */
+ else {
+ H5HF_free_section_t *peer_sect; /* Peer indirect section */
+ H5HF_indirect_t *iblock; /* Pointer to indirect block for this section */
+ hsize_t iblock_off; /* Section's indirect block's offset in "heap space" */
+ haddr_t peer_sect_addr; /* Address of new peer section in "heap space" */
+ unsigned peer_nentries; /* Number of entries in new peer indirect section */
+ unsigned peer_start_row; /* Starting row for new peer indirect section */
+ unsigned peer_start_col; /* Starting column for new peer indirect section */
+ unsigned child_row; /* Row where child entry is located */
+ unsigned new_nentries; /* New number of entries for current indirect section */
+ unsigned old_nentries; /* Old number of entries for current indirect section */
+ unsigned u; /* Local index variable */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Child is in middle of indirect section\n", FUNC);
+#endif /* QAK */
+ /* Sanity check */
+ HDassert(sect->u.indirect.indir_ents);
+
+ /* Compute basic information about peer & current indirect sections */
+ peer_nentries = end_entry - child_entry;
+ peer_start_row = (child_entry + 1) / hdr->man_dtable.cparam.width;
+ peer_start_col = (child_entry + 1) % hdr->man_dtable.cparam.width;
+ child_row = child_entry / hdr->man_dtable.cparam.width;
+ new_nentries = sect->u.indirect.num_entries - (peer_nentries + 1);
+ old_nentries = sect->u.indirect.num_entries;
+#ifdef QAK
+HDfprintf(stderr, "%s: peer_nentries = %u, peer_start_row = %u, peer_start_col = %u\n", FUNC, peer_nentries, peer_start_row, peer_start_col);
+HDfprintf(stderr, "%s: new_nentries = %u\n", FUNC, new_nentries);
+#endif /* QAK */
+
+ /* Get indirect block information for peer */
+ if(sect->sect_info.state == H5FS_SECT_LIVE) {
+ iblock = sect->u.indirect.u.iblock;
+ iblock_off = sect->u.indirect.u.iblock->block_off;
+ } /* end if */
+ else {
+ iblock = NULL;
+ iblock_off = sect->u.indirect.u.iblock_off;
+ } /* end else */
+#ifdef QAK
+HDfprintf(stderr, "%s: iblock = %p, iblock_off = %Hu\n", FUNC, iblock, iblock_off);
+#endif /* QAK */
+
+ /* Update the number of entries in current section & calculate it's span size */
+ /* (Will use this to compute the section address for th peer section */
+ sect->u.indirect.num_entries = new_nentries;
+ if(H5HF_sect_indirect_span_size(hdr, sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute span size of section")
+#ifdef QAK
+HDfprintf(stderr, "%s: sect->u.indirect.span_size = %Hu\n", FUNC, sect->u.indirect.span_size);
+#endif /* QAK */
+
+ /* Compute address of peer indirect section */
+ peer_sect_addr = sect->sect_info.addr;
+ peer_sect_addr += sect->u.indirect.span_size;
+ peer_sect_addr += hdr->man_dtable.row_block_size[child_row];
+#ifdef QAK
+HDfprintf(stderr, "%s: peer_sect_addr = %a\n", FUNC, peer_sect_addr);
+#endif /* QAK */
+
+ /* Create peer indirect section */
+ if(NULL == (peer_sect = H5HF_sect_indirect_new(peer_sect_addr,
+ sect->sect_info.size, iblock, iblock_off, peer_start_row,
+ peer_start_col, peer_nentries)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section")
+
+ /* Set up direct row & indirect entry information for peer section */
+ peer_sect->u.indirect.dir_nrows = 0;
+ peer_sect->u.indirect.dir_rows = NULL;
+ peer_sect->u.indirect.indir_nents = peer_nentries;
+ if(NULL == (peer_sect->u.indirect.indir_ents = H5MM_malloc(sizeof(H5HF_free_section_t *) * peer_nentries)))
+ HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for indirect section pointer array")
+
+ /* Transfer child indirect sections between current & peer sections */
+ HDmemcpy(&peer_sect->u.indirect.indir_ents[0],
+ &sect->u.indirect.indir_ents[old_nentries - peer_nentries],
+ (sizeof(H5HF_free_section_t *) * peer_nentries));
+ sect->u.indirect.indir_nents -= (peer_nentries + 1); /* Transferred blocks, plus child entry */
+#ifdef QAK
+HDfprintf(stderr, "%s: sect->u.indirect.indir_nents = %u, old_nentries = %u\n", FUNC, sect->u.indirect.indir_nents, old_nentries);
+#endif /* QAK */
+
+ /* Re-target transferred row sections to point to new underlying indirect section */
+ for(u = 0; u < peer_nentries; u++)
+ peer_sect->u.indirect.indir_ents[u]->u.indirect.parent = peer_sect;
+
+ /* Make new "first row" in peer section */
+ if(H5HF_sect_indirect_first(hdr, peer_sect->u.indirect.indir_ents[0]) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't make new 'first row' for peer indirect section")
+
+ /* Adjust reference counts for current & peer sections */
+ peer_sect->u.indirect.rc = peer_nentries;
+ sect->u.indirect.rc -= peer_nentries;
+#ifdef QAK
+HDfprintf(stderr, "%s: sect->u.indirect.rc = %u\n", FUNC, sect->u.indirect.rc);
+HDfprintf(stderr, "%s: peer_sect->u.indirect.rc = %u\n", FUNC, peer_sect->u.indirect.rc);
+#endif /* QAK */
+
+ /* Transfer cached information about indirect block */
+ peer_sect->u.indirect.iblock_entries = sect->u.indirect.iblock_entries;
+
+ /* Make certain we've tracked the sections' dependents correctly */
+ /* (Note modified on current section's ref. count, since we haven't
+ * detached the child section yet)
+ */
+ HDassert((sect->u.indirect.rc - 1) ==
+ (sect->u.indirect.indir_nents + sect->u.indirect.dir_nrows));
+ HDassert(peer_sect->u.indirect.rc ==
+ (peer_sect->u.indirect.indir_nents + peer_sect->u.indirect.dir_nrows));
+ } /* end else */
} /* 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")
+ sect->u.indirect.indir_nents--;
} /* end else */
+ /* Decrement # of sections which depend on this row */
+ /* (Must be last as section can be freed) */
+ if(H5HF_sect_indirect_decr(sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't decrement section's ref. count ")
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_sect_indirect_reduce() */
/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_indirect_is_first
+ *
+ * Purpose: Check if indirect section is first in all parents
+ *
+ * Return: Non-negative (TRUE/FALSE) on success/<can't fail>
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * July 17 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static hbool_t
+H5HF_sect_indirect_is_first(H5HF_free_section_t *sect)
+{
+ hbool_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_indirect_is_first)
+
+ /* Sanity check */
+ HDassert(sect);
+
+ /* Recurse to parent */
+ if(sect->u.indirect.parent) {
+ if(sect->sect_info.addr == sect->u.indirect.parent->sect_info.addr)
+ ret_value = H5HF_sect_indirect_is_first(sect->u.indirect.parent);
+ } /* end if */
+ else
+ ret_value = TRUE;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_sect_indirect_first() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_indirect_first
+ *
+ * Purpose: Make new 'first row' for indirect section
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * July 10 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_sect_indirect_first(H5HF_hdr_t *hdr, H5HF_free_section_t *sect)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_first)
+
+ /* Sanity check */
+ HDassert(hdr);
+ HDassert(sect);
+
+ /* Check if this indirect section has direct block rows */
+ if(sect->u.indirect.dir_nrows > 0) {
+ /* Sanity checks */
+ HDassert(sect->u.indirect.row == 0);
+ HDassert(sect->u.indirect.col == 0);
+ HDassert(sect->u.indirect.dir_rows[0]);
+
+ /* Change first row section in indirect section to be the "first row" */
+ if(H5HF_sect_row_first(hdr, sect->u.indirect.dir_rows[0]) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSET, FAIL, "can't set row section to be first row")
+ } /* end if */
+ else {
+ /* Sanity checks */
+ HDassert(sect->u.indirect.indir_nents > 0);
+ HDassert(sect->u.indirect.indir_ents[0]);
+
+ /* Forward to first child indirect section */
+ if(H5HF_sect_indirect_first(hdr, sect->u.indirect.indir_ents[0]) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSET, FAIL, "can't set child indirect section to be first row")
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_sect_indirect_first() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_indirect_get_iblock
+ *
+ * Purpose: Retrieve the indirect block for a indirect section
+ *
+ * Return: Pointer to indirect block on success/NULL on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * July 9 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5HF_indirect_t *
+H5HF_sect_indirect_get_iblock(H5HF_free_section_t *sect)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_indirect_get_iblock)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(sect);
+ HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_INDIRECT);
+ HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
+
+ FUNC_LEAVE_NOAPI(sect->u.indirect.u.iblock)
+} /* end H5HF_sect_indirect_get_iblock() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_indirect_merge_row
+ *
+ * Purpose: Merge two sections of this type
+ *
+ * Note: Second section always merges into first node
+ *
+ * Return: Success: non-negative
+ *
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, July 18, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_sect_indirect_merge_row(H5HF_hdr_t *hdr, hid_t dxpl_id,
+ H5HF_free_section_t *row_sect1, H5HF_free_section_t *row_sect2)
+{
+ H5HF_free_section_t *sect1, *sect2; /* Indirect sections underlying row sections */
+ hsize_t iblock_off1, iblock_off2; /* The offset of the indirect blocks for the indirect sections (in "heap space") */
+ unsigned start_entry1; /* Start entry for section #1 */
+ unsigned start_row1, start_col1; /* Starting row & column for section #1 */
+ unsigned end_entry1; /* End entry for section #1 */
+ unsigned end_row1, end_col1; /* Ending row & column for section #1 */
+ unsigned start_entry2; /* Start entry for section #2 */
+ unsigned start_row2, start_col2; /* Starting row & column for section #2 */
+ unsigned end_row2, end_col2; /* Ending row & column for section #2 */
+ unsigned end_entry2; /* End entry for section #2 */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_merge_row)
+
+ /* Sanity check parameters */
+ HDassert(hdr);
+ HDassert(row_sect1);
+ HDassert(row_sect1->u.row.under);
+ HDassert(row_sect1->sect_info.state == H5FS_SECT_LIVE);
+ HDassert(row_sect2);
+ HDassert(row_sect2->u.row.under);
+ HDassert(row_sect2->sect_info.state == H5FS_SECT_LIVE);
+ HDassert(row_sect2->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW);
+
+ /* Set up indirect section information */
+ sect1 = row_sect1->u.row.under;
+ sect2 = row_sect2->u.row.under;
+#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 */
+
+ /* Sanity check some assumptions about the indirect sections */
+ HDassert(sect1->u.indirect.dir_nrows > 0);
+ HDassert(sect1->u.indirect.dir_rows);
+ HDassert(sect1->u.indirect.indir_nents == 0);
+ HDassert(sect1->u.indirect.indir_ents == NULL);
+ HDassert(sect2->u.indirect.dir_nrows > 0);
+ HDassert(sect2->u.indirect.dir_rows);
+
+ /* Set up span information */
+ start_row1 = sect1->u.indirect.row;
+ start_col1 = sect1->u.indirect.col;
+ start_entry1 = (start_row1 * hdr->man_dtable.cparam.width) + start_col1;
+ end_entry1 = (start_entry1 + sect1->u.indirect.num_entries) - 1;
+ end_row1 = end_entry1 / hdr->man_dtable.cparam.width;
+ end_col1 = end_entry1 % hdr->man_dtable.cparam.width;
+ HDassert(end_row1 == row_sect1->u.row.row);
+#ifdef QAK
+HDfprintf(stderr, "%s: start_row1 = %u, start_col1 = %u, start_entry1 = %u\n", FUNC, start_row1, start_col1, start_entry1);
+HDfprintf(stderr, "%s: sect1->u.indirect.num_entries = %u\n", FUNC, sect1->u.indirect.num_entries);
+HDfprintf(stderr, "%s: end_row1 = %u, end_col1 = %u, end_entry1 = %u\n", FUNC, end_row1, end_col1, end_entry1);
+#endif /* QAK */
+ start_row2 = sect2->u.indirect.row;
+ start_col2 = sect2->u.indirect.col;
+ start_entry2 = (start_row2 * hdr->man_dtable.cparam.width) + start_col2;
+ end_entry2 = (start_entry2 + sect2->u.indirect.num_entries) - 1;
+ end_row2 = end_entry2 / hdr->man_dtable.cparam.width;
+ end_col2 = end_entry2 % hdr->man_dtable.cparam.width;
+ HDassert(start_row2 == row_sect2->u.row.row);
+#ifdef QAK
+HDfprintf(stderr, "%s: start_row2 = %u, start_col2 = %u, start_entry2 = %u\n", FUNC, start_row2, start_col2, start_entry2);
+HDfprintf(stderr, "%s: sect2->u.indirect.num_entries = %u\n", FUNC, sect2->u.indirect.num_entries);
+HDfprintf(stderr, "%s: end_row2 = %u, end_col2 = %u, end_entry2 = %u\n", FUNC, end_row2, end_col2, end_entry2);
+#endif /* QAK */
+ if(sect1->sect_info.state == H5FS_SECT_LIVE)
+ iblock_off1 = sect1->u.indirect.u.iblock->block_off;
+ else
+ iblock_off1 = sect1->u.indirect.u.iblock_off;
+ if(sect2->sect_info.state == H5FS_SECT_LIVE)
+ iblock_off2 = sect2->u.indirect.u.iblock->block_off;
+ else
+ iblock_off2 = sect2->u.indirect.u.iblock_off;
+#ifdef QAK
+HDfprintf(stderr, "%s: iblock_off1 = %Hu\n", FUNC, iblock_off1);
+HDfprintf(stderr, "%s: iblock_off2 = %Hu\n", FUNC, iblock_off2);
+#endif /* QAK */
+
+ /* Determine if the two indirect sections are in the same indirect block */
+ if(iblock_off1 == iblock_off2) {
+ unsigned src_row2; /* Source row for copying from second section */
+ unsigned new_dir_nrows; /* New value for number of direct rows in first section */
+ unsigned nrows_moved; /* Number of rows to move from second section to first */
+ unsigned u; /* Local index variable */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: sect1->u.indirect.dir_nrows = %u\n", FUNC, sect1->u.indirect.dir_nrows);
+HDfprintf(stderr, "%s: sect2->u.indirect.dir_nrows = %u\n", FUNC, sect2->u.indirect.dir_nrows);
+#endif /* QAK */
+
+ /* Check for sections sharing a row */
+ if(end_row1 == start_row2) {
+#ifdef QAK
+HDfprintf(stderr, "%s: Sections share a row\n", FUNC);
+#endif /* QAK */
+
+ /* Adjust info for first row section, to absorb second row section */
+ HDassert((row_sect1->u.row.col + row_sect1->u.row.num_entries) == row_sect2->u.row.col);
+ row_sect1->u.row.num_entries += row_sect2->u.row.num_entries;
+
+ /* Set up parameters for transfer of rows */
+ src_row2 = 1;
+ nrows_moved = sect2->u.indirect.dir_nrows - 1;
+ new_dir_nrows = (sect1->u.indirect.dir_nrows + sect2->u.indirect.dir_nrows) - 1;
+ } /* end if */
+ else {
+#ifdef QAK
+HDfprintf(stderr, "%s: Sections don't share a row\n", FUNC);
+#endif /* QAK */
+
+ /* Set up parameters for transfer of rows */
+ src_row2 = 0;
+ nrows_moved = sect2->u.indirect.dir_nrows;
+ new_dir_nrows = sect1->u.indirect.dir_nrows + sect2->u.indirect.dir_nrows;
+ } /* end else */
+#ifdef QAK
+HDfprintf(stderr, "%s: src_row2 = %u\n", FUNC, src_row2);
+HDfprintf(stderr, "%s: nrows_moved = %u\n", FUNC, nrows_moved);
+HDfprintf(stderr, "%s: new_dir_nrows = %u\n", FUNC, new_dir_nrows);
+#endif /* QAK */
+
+ /* Check if we need to move additional rows */
+ if(nrows_moved > 0) {
+ /* Extend the first section's row array */
+ if(NULL == (sect1->u.indirect.dir_rows = H5MM_realloc(sect1->u.indirect.dir_rows, sizeof(H5HF_free_section_t *) * new_dir_nrows)))
+ HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for row section pointer array")
+
+ /* Transfer the second section's rows to first section */
+ HDmemcpy(&sect1->u.indirect.dir_rows[sect1->u.indirect.dir_nrows],
+ &sect2->u.indirect.dir_rows[src_row2],
+ (sizeof(H5HF_free_section_t *) * nrows_moved));
+
+ /* Re-target the row sections moved from second section */
+ for(u = sect1->u.indirect.dir_nrows; u < new_dir_nrows; u++)
+ sect1->u.indirect.dir_rows[u]->u.row.under = sect1;
+
+ /* Adjust reference counts to account for transferred rows */
+ sect1->u.indirect.rc += nrows_moved;
+ sect2->u.indirect.rc -= nrows_moved;
+ } /* end if */
+
+ /* Check for indirect sections in second section */
+ if(sect2->u.indirect.indir_nents > 0) {
+ HDassert(sect2->u.indirect.rc > 0);
+ HDassert(sect2->u.indirect.indir_ents);
+
+ /* Copy over any child indirect sections in second section */
+
+ /* Re-target the child indirect sections moved from second section */
+
+ /* Adjust reference counts for transferred child indirect sections */
+
+HDfprintf(stderr, "%s: moving child indirect sections between indirect sections not supported yet!\n", FUNC);
+HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "moving child indirect sections between two indirect sections not supported yet")
+ } /* end if */
+
+ /* Update information for first section */
+ sect1->u.indirect.dir_nrows = new_dir_nrows;
+ sect1->u.indirect.num_entries += sect2->u.indirect.num_entries;
+ if(sect1->u.indirect.span_size) {
+ if(sect2->u.indirect.span_size)
+ sect1->u.indirect.span_size += sect2->u.indirect.span_size;
+ else
+ sect1->u.indirect.span_size = 0;
+ } /* end if */
+ if(sect1->u.indirect.iblock_entries == 0)
+ sect1->u.indirect.iblock_entries = sect2->u.indirect.iblock_entries;
+
+ /* Make certain we've tracked the first section's dependents correctly */
+ HDassert(sect1->u.indirect.rc ==
+ (sect1->u.indirect.indir_nents + sect1->u.indirect.dir_nrows));
+
+ /* Wrap up, for indirect sections not sharing a row */
+ /* (want this to be after the first indirection section is consistent again) */
+ if(end_row1 == start_row2) {
+#ifdef QAK
+HDfprintf(stderr, "%s: Finishing sections share a row\n", FUNC);
+#endif /* QAK */
+ /* Release second row section */
+ /* (also releases second indirect section, since all of it's other
+ * dependents are gone)
+ */
+ HDassert(sect2->u.indirect.rc == 1);
+ if(H5HF_sect_row_free((H5FS_section_info_t *)row_sect2) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free row section")
+ } /* end if */
+ else {
+#ifdef QAK
+HDfprintf(stderr, "%s: Finishing sections don't share a row\n", FUNC);
+#endif /* QAK */
+ /* Decrement ref. count on second indirect section's parent */
+ HDassert(sect2->u.indirect.rc == 0);
+ if(sect2->u.indirect.parent)
+ if(H5HF_sect_indirect_decr(sect2->u.indirect.parent) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't decrement ref. count on parent indirect section")
+
+ /* Free second indirect section */
+ if(H5HF_sect_indirect_free(sect2) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node")
+
+ /* Re-add the second section's first row */
+ /* (it's already been added to first section, but it's been removed
+ * from the free space manager and needs to be re-added)
+ */
+#ifdef QAK
+HDfprintf(stderr, "%s: Re-inserting second row section\n", FUNC);
+#endif /* QAK */
+ row_sect2->sect_info.type = H5HF_FSPACE_SECT_NORMAL_ROW;
+ HDassert(row_sect2->u.row.under == sect1);
+ if(H5HF_space_add(hdr, dxpl_id, row_sect2, H5FS_ADD_RETURNED_SPACE) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't re-add second row section to free space")
+#ifdef QAK
+HDfprintf(stderr, "%s: Done re-inserting second row section\n", FUNC);
+#endif /* QAK */
+ } /* end else */
+ } /* end if */
+ else {
+HDfprintf(stderr, "%s: merging two indirect sections in different indirect blocks not supported yet!\n", FUNC);
+HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "merging two indirect sections in different indirect blocks not supported yet")
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_sect_indirect_merge_row() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_indirect_shrink_row
+ *
+ * Purpose: "Shrink" an indirect by eliminating it's last row
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, July 18, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_sect_indirect_shrink_row(H5HF_free_section_t *row_sect)
+{
+ H5HF_free_section_t *sect; /* Indirect section underlying row section */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_indirect_shrink_row)
+
+ /* Sanity check parameters */
+ HDassert(row_sect);
+ HDassert(row_sect->u.row.under);
+
+ /* Set up indirect section information */
+ sect = row_sect->u.row.under;
+
+ /* Sanity check some assumptions about the indirect section */
+ HDassert(sect->u.indirect.dir_nrows > 0);
+ HDassert(sect->u.indirect.dir_rows);
+ HDassert(sect->u.indirect.indir_nents == 0);
+ HDassert(sect->u.indirect.indir_ents == NULL);
+
+ /* Decrement the number of rows */
+ /* (other cleanup will be taken care of when the section is freed) */
+ sect->u.indirect.dir_nrows--;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5HF_sect_indirect_shrink_row() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5HF_sect_indirect_serialize
*
* Purpose: Serialize a "live" indirect section into a buffer
@@ -1723,37 +3763,70 @@ done:
* Failure: negative
*
* Programmer: Quincey Koziol
- * Monday, May 1, 2006
+ * Monday, July 3, 2006
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5HF_sect_indirect_serialize(const H5FS_section_info_t *_sect, uint8_t *buf)
+H5HF_sect_indirect_serialize(H5HF_hdr_t *hdr, const H5HF_free_section_t *sect,
+ uint8_t *buf)
{
- const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect;
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_indirect_serialize)
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_serialize)
/* Check arguments. */
+ HDassert(hdr);
+ HDassert(sect);
HDassert(buf);
- HDassert(_sect);
-
- /* Range's row */
- UINT16ENCODE(buf, sect->u.indirect.row);
+#ifdef QAK
+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 */
- /* Range's column */
- UINT16ENCODE(buf, sect->u.indirect.col);
+ /* Check if this indirect section has a parent & forward if this section is first */
+ if(sect->u.indirect.parent) {
+ if(sect->sect_info.addr == sect->u.indirect.parent->sect_info.addr)
+ if(H5HF_sect_indirect_serialize(hdr, sect->u.indirect.parent, buf) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSERIALIZE, FAIL, "can't serialize indirect section's parent indirect section")
+ } /* end if */
+ else {
+ /* Indirect range's indirect block's block offset */
+ if(sect->sect_info.state == H5FS_SECT_LIVE) {
+ HDassert(sect->u.indirect.u.iblock);
+ UINT64ENCODE_VAR(buf, sect->u.indirect.u.iblock->block_off, hdr->heap_off_size);
+#ifdef QAK
+HDfprintf(stderr, "%s: sect->u.indirect.u.iblock->block_off = %Hu\n", FUNC, sect->u.indirect.u.iblock->block_off);
+#endif /* QAK */
+ } /* end if */
+ else
+{
+ UINT64ENCODE_VAR(buf, sect->u.indirect.u.iblock_off, hdr->heap_off_size);
+#ifdef QAK
+HDfprintf(stderr, "%s: sect->u.indirect.u.iblock_off = %Hu\n", FUNC, sect->u.indirect.u.iblock_off);
+#endif /* QAK */
+}
- /* Range's # of entries */
- UINT16ENCODE(buf, sect->u.indirect.num_entries);
+ /* Indirect range's row */
+ UINT16ENCODE(buf, sect->u.indirect.row);
+#ifdef QAK
+HDfprintf(stderr, "%s: sect->u.indirect.row = %u\n", FUNC, sect->u.indirect.row);
+#endif /* QAK */
- /* Range's indirect row */
- UINT16ENCODE(buf, sect->u.indirect.indir_row);
+ /* Indirect range's column */
+ UINT16ENCODE(buf, sect->u.indirect.col);
+#ifdef QAK
+HDfprintf(stderr, "%s: sect->u.indirect.col = %u\n", FUNC, sect->u.indirect.col);
+#endif /* QAK */
- /* Range's indirect # of rows */
- UINT16ENCODE(buf, sect->u.indirect.indir_nrows);
+ /* Indirect range's # of entries */
+ UINT16ENCODE(buf, sect->u.indirect.num_entries);
+#ifdef QAK
+HDfprintf(stderr, "%s: sect->u.indirect.num_entries = %u\n", FUNC, sect->u.indirect.num_entries);
+#endif /* QAK */
+ } /* end else */
- FUNC_LEAVE_NOAPI(SUCCEED)
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* H5HF_sect_indirect_serialize() */
@@ -1767,42 +3840,81 @@ H5HF_sect_indirect_serialize(const H5FS_section_info_t *_sect, uint8_t *buf)
* Failure: negative
*
* Programmer: Quincey Koziol
- * Monday, May 1, 2006
+ * Monday, July 3, 2006
*
*-------------------------------------------------------------------------
*/
static H5FS_section_info_t *
-H5HF_sect_indirect_deserialize(const uint8_t *buf, haddr_t sect_addr,
- hsize_t sect_size)
+H5HF_sect_indirect_deserialize(H5HF_hdr_t *hdr, hid_t dxpl_id,
+ const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size,
+ unsigned *des_flags)
{
- H5HF_free_section_t *new_sect; /* New section */
+ H5HF_free_section_t *new_sect; /* New indirect section */
+ hsize_t iblock_off; /* Indirect block's offset */
+ unsigned start_row; /* Indirect3 section's start row */
+ unsigned start_col; /* Indirect3 section's start column */
+ unsigned nentries; /* Indirect3 section's number of entries */
+ unsigned start_entry; /* Start entry in indirect block */
+ unsigned end_entry; /* End entry in indirect block */
+ unsigned end_row; /* End row in indirect block */
+ unsigned end_col; /* End column in indirect block */
H5FS_section_info_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_deserialize)
/* Check arguments. */
+ HDassert(hdr);
HDassert(buf);
HDassert(H5F_addr_defined(sect_addr));
HDassert(sect_size);
+#ifdef QAK
+HDfprintf(stderr, "%s: sect_addr = %a, sect_size = %Hu\n", FUNC, sect_addr, sect_size);
+#endif /* QAK */
- /* Create free list section node */
- 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")
+ /* Indirect range's indirect block's block offset */
+ UINT64DECODE_VAR(buf, iblock_off, hdr->heap_off_size);
+#ifdef QAK
+HDfprintf(stderr, "%s: iblock_off = %Hu\n", FUNC, iblock_off);
+#endif /* QAK */
+
+ /* Indirect3 section's row */
+ UINT16DECODE(buf, start_row);
+#ifdef QAK
+HDfprintf(stderr, "%s: start_row = %u\n", FUNC, start_row);
+#endif /* QAK */
+
+ /* Indirect3 section's column */
+ UINT16DECODE(buf, start_col);
+#ifdef QAK
+HDfprintf(stderr, "%s: start_col = %u\n", FUNC, start_col);
+#endif /* QAK */
+
+ /* Indirect3 section's # of entries */
+ UINT16DECODE(buf, nentries);
+#ifdef QAK
+HDfprintf(stderr, "%s: nentries = %u\n", FUNC, nentries);
+#endif /* QAK */
- /* Range's row */
- UINT16DECODE(buf, new_sect->u.indirect.row);
+ /* Create free space section node */
+ if(NULL == (new_sect = H5HF_sect_indirect_new(sect_addr, sect_size, NULL,
+ iblock_off, start_row, start_col, nentries)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't create indirect section")
- /* Range's column */
- UINT16DECODE(buf, new_sect->u.indirect.col);
+ /* Compute start entry */
+ start_entry = (start_row * hdr->man_dtable.cparam.width) + start_col;
- /* Range's # of entries */
- UINT16DECODE(buf, new_sect->u.indirect.num_entries);
+ /* Compute end column & row */
+ end_entry = (start_entry + nentries) - 1;
+ end_row = end_entry / hdr->man_dtable.cparam.width;
+ end_col = end_entry % hdr->man_dtable.cparam.width;
- /* Range's indirect row */
- UINT16DECODE(buf, new_sect->u.indirect.indir_row);
+ /* Initialize rows for new indirect section */
+ if(H5HF_sect_indirect_init_rows(hdr, dxpl_id, new_sect, TRUE, H5FS_ADD_DESERIALIZING,
+ new_sect->u.indirect.row, new_sect->u.indirect.col, end_row, end_col) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't initialize indirect section")
- /* Range's indirect # of rows */
- UINT16DECODE(buf, new_sect->u.indirect.indir_nrows);
+ /* Indicate that this section shouldn't be added to free space manager's list */
+ *des_flags |= H5FS_DESERIALIZE_NO_ADD;
/* Set return value */
ret_value = (H5FS_section_info_t *)new_sect;
@@ -1822,30 +3934,35 @@ done:
* Failure: negative
*
* Programmer: Quincey Koziol
- * Wednesday, May 17, 2006
+ * Monday, July 3, 2006
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5HF_sect_indirect_free(H5FS_section_info_t *_sect)
+H5HF_sect_indirect_free(H5HF_free_section_t *sect)
{
- H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Pointer to section to free */
- H5HF_indirect_t *parent = NULL; /* Parent indirect block for section */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5HF_indirect_t *iblock = NULL; /* Indirect block for section */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_free)
HDassert(sect);
+ /* Release the memory for tracking direct rows */
+ sect->u.indirect.dir_rows = H5MM_xfree(sect->u.indirect.dir_rows);
+
+ /* Release the memory for tracking indirect entries */
+ sect->u.indirect.indir_ents = H5MM_xfree(sect->u.indirect.indir_ents);
+
/* Check for live reference to an indirect block */
if(sect->sect_info.state == H5FS_SECT_LIVE) {
- /* Get parent indirect block, if there was one */
- if(sect->u.indirect.iblock)
- parent = sect->u.indirect.iblock;
+ /* Get indirect block, if there was one */
+ if(sect->u.indirect.u.iblock)
+ iblock = sect->u.indirect.u.iblock;
} /* end if */
/* Release the sections */
- if(H5HF_sect_node_free(sect, parent) < 0)
+ if(H5HF_sect_node_free(sect, iblock) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node")
done:
@@ -1854,6 +3971,101 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_indirect_valid
+ *
+ * Purpose: Check the validity of a section
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Friday, July 21, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_sect_indirect_valid(const H5FS_section_class_t *row_cls, const H5HF_free_section_t *row_sect)
+{
+ const H5HF_free_section_t *sect; /* Pointer to underlying indirect section */
+ H5HF_sect_indirect_private_t *cls_prvt; /* Pointer to class private info */
+ const H5HF_hdr_t *hdr; /* Fractal heap header */
+ hsize_t iblock_off; /* Indirect block's offset in "heap space" */
+ unsigned start_row; /* Row for first block covered */
+ unsigned start_col; /* Column for first block covered */
+ unsigned start_entry; /* Entry for first block covered */
+ unsigned end_row; /* Row for last block covered */
+ unsigned end_col; /* Column for last block covered */
+ unsigned end_entry; /* Entry for last block covered */
+ unsigned dir_nrows; /* Number of direct rows in section */
+ unsigned u; /* Local index variable */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_indirect_valid)
+
+ /* Sanity check arguments */
+ HDassert(row_cls);
+ HDassert(row_sect);
+
+ /* Set up indirect section */
+ sect = row_sect->u.row.under;
+ cls_prvt = row_cls->cls_private;
+ hdr = cls_prvt->hdr;
+ HDassert(sect);
+ HDassert(hdr);
+#ifdef QAK
+HDfprintf(stderr, "%s: sect->sect_info = {%a, %Hu, %u, %s}\n", "H5HF_sect_indirect_valid", 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"));
+if(sect->sect_info.state == H5FS_SECT_LIVE)
+ HDfprintf(stderr, "%s: sect->u.indirect = {%p, ", "H5HF_sect_indirect_valid", sect->u.indirect.u.iblock);
+else
+ HDfprintf(stderr, "%s: sect->u.indirect = {%Hu, ", "H5HF_sect_indirect_valid", sect->u.indirect.u.iblock_off);
+HDfprintf(stderr, "%u, %u, %u}\n", sect->u.indirect.row, sect->u.indirect.col, sect->u.indirect.num_entries);
+#endif /* QAK */
+
+ /* Retrieve the indirect block's offset */
+ if(sect->sect_info.state == H5FS_SECT_LIVE)
+ iblock_off = sect->u.indirect.u.iblock->block_off;
+ else
+ iblock_off = sect->u.indirect.u.iblock_off;
+
+#ifdef QAK
+HDfprintf(stderr, "%s: iblock_off = %Hu\n", "H5HF_sect_indirect_valid", iblock_off);
+#endif /* QAK */
+
+ /* Compute starting entry, column & row */
+ start_row = sect->u.indirect.row;
+ start_col = sect->u.indirect.col;
+ start_entry = (start_row * hdr->man_dtable.cparam.width) + start_col;
+
+ /* Compute ending entry, column & row */
+ end_entry = (start_entry + sect->u.indirect.num_entries) - 1;
+ end_row = end_entry / hdr->man_dtable.cparam.width;
+ end_col = end_entry % hdr->man_dtable.cparam.width;
+#ifdef QAK
+HDfprintf(stderr, "%s: start_row = %u, start_col = %u, start_entry = %u\n", "H5HF_sect_indirect_valid", start_row, start_col, start_entry);
+HDfprintf(stderr, "%s: end_row = %u, end_col = %u, end_entry = %u\n", "H5HF_sect_indirect_valid", end_row, end_col, end_entry);
+#endif /* QAK */
+
+ /* Iterate over direct rows, checking pointer references */
+ dir_nrows = (end_row - start_row) + 1;
+ HDassert(dir_nrows == sect->u.indirect.dir_nrows);
+ for(u = 0; u < dir_nrows; u++) {
+ const H5HF_free_section_t *tmp_row_sect; /* Pointer to row section */
+
+ tmp_row_sect = sect->u.indirect.dir_rows[u];
+ HDassert(tmp_row_sect->u.row.under == sect);
+ HDassert(tmp_row_sect->u.row.row == (start_row + u));
+ if(u < (dir_nrows - 1)) {
+ const H5HF_free_section_t *tmp2_row_sect; /* Pointer to row section */
+
+ tmp2_row_sect = sect->u.indirect.dir_rows[u + 1];
+ HDassert(tmp_row_sect->u.row.row != tmp2_row_sect->u.row.row);
+ } /* end if */
+ } /* end for */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5HF_sect_indirect_valid() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5HF_sect_indirect_debug
*
* Purpose: Dump debugging information about an indirect free space section
@@ -1863,7 +4075,7 @@ done:
* Failure: negative
*
* Programmer: Quincey Koziol
- * Saturday, May 13, 2006
+ * Monday, July 3, 2006
*
*-------------------------------------------------------------------------
*/
@@ -1888,12 +4100,6 @@ H5HF_sect_indirect_debug(const H5FS_section_info_t *_sect,
HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
"Number of entries:",
sect->u.indirect.num_entries);
- HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
- "Indirect row:",
- sect->u.indirect.indir_row);
- HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
- "Indirect number of rows:",
- sect->u.indirect.indir_nrows);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* H5HF_sect_indirect_debug() */
diff --git a/src/H5HFspace.c b/src/H5HFspace.c
index 3519e91..4634e49 100644
--- a/src/H5HFspace.c
+++ b/src/H5HFspace.c
@@ -97,7 +97,8 @@ H5HF_space_start(H5HF_hdr_t *hdr, hid_t dxpl_id)
{
const H5FS_section_class_t *classes[] = { /* Free space section classes implemented for fractal heap */
H5HF_FSPACE_SECT_CLS_SINGLE,
- H5HF_FSPACE_SECT_CLS_RANGE,
+ H5HF_FSPACE_SECT_CLS_FIRST_ROW,
+ H5HF_FSPACE_SECT_CLS_NORMAL_ROW,
H5HF_FSPACE_SECT_CLS_INDIRECT};
herr_t ret_value = SUCCEED; /* Return value */
@@ -194,55 +195,18 @@ done:
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
- * May 2 2006
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5HF_space_add(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *node)
-{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5HF_space_add)
-
- /*
- * Check arguments.
- */
- HDassert(hdr);
- HDassert(node);
- HDassert(hdr->fspace);
-
- /* Add to the free space for the heap */
- if(H5FS_add(hdr->f, dxpl_id, hdr->fspace, (H5FS_section_info_t *)node, 0, NULL) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "can't add section to heap free space")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_space_add() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5HF_space_return
- *
- * Purpose: Return a freedsection to the free space for the heap
- *
- * Return: Success: non-negative
- *
- * Failure: negative
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
* May 15 2006
*
*-------------------------------------------------------------------------
*/
herr_t
-H5HF_space_return(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *node)
+H5HF_space_add(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *node,
+ unsigned flags)
{
H5HF_add_ud1_t udata; /* User data for free space manager 'add' */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5HF_space_return)
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_space_add)
/*
* Check arguments.
@@ -258,15 +222,15 @@ H5HF_space_return(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *node)
/* Construct user data */
udata.hdr = hdr;
udata.dxpl_id = dxpl_id;
- udata.dblock = NULL;
+ udata.adjoin = 0;
/* Add to the free space for the heap */
- if(H5FS_add(hdr->f, dxpl_id, hdr->fspace, (H5FS_section_info_t *)node, H5FS_ADD_RETURNED_SPACE, &udata) < 0)
+ if(H5FS_add(hdr->f, dxpl_id, hdr->fspace, (H5FS_section_info_t *)node, flags, &udata) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "can't add section to heap free space")
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_space_return() */
+} /* end H5HF_space_add() */
/*-------------------------------------------------------------------------
@@ -324,3 +288,41 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_space_close() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_space_change_sect_class
+ *
+ * Purpose: Change a section's class
+ *
+ * Return: Success: non-negative
+ *
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * July 10 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_space_sect_change_class(H5HF_hdr_t *hdr, H5HF_free_section_t *sect, unsigned new_class)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_space_sect_change_class)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+ HDassert(hdr->fspace);
+ HDassert(sect);
+
+ /* Notify the free space manager that a section has changed class */
+ if(H5FS_sect_change_class(hdr->fspace, (H5FS_section_info_t *)sect, new_class) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTMODIFY, FAIL, "can't modify class of free space section")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_space_sect_change_class() */
+
diff --git a/src/H5HFtest.c b/src/H5HFtest.c
index a3b524b..d34f1f6 100644
--- a/src/H5HFtest.c
+++ b/src/H5HFtest.c
@@ -288,7 +288,7 @@ H5HF_get_dblock_free_test(const H5HF_t *fh, unsigned row)
HDassert(fh);
/* Return direct block free space */
- ret_value = fh->hdr->man_dtable.row_dblock_free[row];
+ ret_value = fh->hdr->man_dtable.row_tot_dblock_free[row];
FUNC_LEAVE_NOAPI(ret_value)
} /* H5HF_get_dblock_free_test() */