summaryrefslogtreecommitdiffstats
path: root/src/H5HFint.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5HFint.c')
-rw-r--r--src/H5HFint.c227
1 files changed, 197 insertions, 30 deletions
diff --git a/src/H5HFint.c b/src/H5HFint.c
index 64de9c4..e8b380d 100644
--- a/src/H5HFint.c
+++ b/src/H5HFint.c
@@ -57,6 +57,7 @@
/********************/
/* Local Prototypes */
/********************/
+static herr_t H5HF_man_start_freelist(H5HF_hdr_t *hdr, hid_t dxpl_id);
/*********************/
@@ -93,20 +94,135 @@ H5FL_DEFINE(H5HF_free_section_t);
*-------------------------------------------------------------------------
*/
herr_t
-H5HF_free_section_free_cb(void *item, void UNUSED *key, void UNUSED *op_data)
+H5HF_free_section_free_cb(void *_sect, void UNUSED *key, void UNUSED *op_data)
{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_free_section_free_cb)
+ H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect;
+ H5HF_indirect_t *iblock = NULL; /* Indirect block referenced */
+ herr_t ret_value = 0; /* Return value */
- HDassert(item);
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_free_section_free_cb)
+
+ HDassert(sect);
+
+ /* Find indirect block that free section references */
+ switch(sect->type) {
+ case H5HF_SECT_SINGLE:
+ iblock = sect->u.single.parent;
+ break;
+
+ case H5HF_SECT_OPAQUE:
+ iblock = sect->u.opaque.iblock;
+ break;
+
+ case H5HF_SECT_RANGE:
+ iblock = sect->u.range.iblock;
+ break;
+
+ case H5HF_SECT_INDIRECT:
+ iblock = sect->u.indirect.iblock;
+ break;
+ } /* end switch */
+
+ /* Release indirect block, if there was one */
+ if(iblock)
+ if(H5HF_iblock_decr(iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block")
/* Release the sections */
- H5FL_FREE(H5HF_free_section_t, item);
+ H5FL_FREE(H5HF_free_section_t, sect);
- FUNC_LEAVE_NOAPI(0)
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* H5HF_free_section_free_cb() */
/*-------------------------------------------------------------------------
+ * Function: H5HF_man_start_freelist
+ *
+ * Purpose: Start free list for existing heap, by bringing in root direct
+ * or indirect block and it's free space sections.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Apr 25 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_man_start_freelist(H5HF_hdr_t *hdr, hid_t dxpl_id)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_start_freelist)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+
+ /* Check for empty heap */
+ if(!H5F_addr_defined(hdr->man_dtable.table_addr)) {
+#ifdef QAK
+HDfprintf(stderr, "%s: Empty heap to [not] start\n", FUNC);
+#endif /* QAK */
+ /* Nothing to do */
+ ;
+ } /* end if */
+ /* Check for root direct block */
+ else if(hdr->man_dtable.curr_root_rows == 0) {
+ H5HF_direct_t *dblock; /* Pointer to direct block to query */
+ haddr_t dblock_addr; /* Direct block address */
+ size_t dblock_size; /* Direct block size */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Root direct block to start\n", FUNC);
+#endif /* QAK */
+ /* Bring root direct block into memory */
+ /* (which will parse it's free list) */
+ /* (Could create an "opaque" section for it, but it doesn't seem worthwhile) */
+ dblock_addr = hdr->man_dtable.table_addr;
+ dblock_size = hdr->man_dtable.cparam.start_block_size;
+ if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, NULL, 0, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap direct block")
+
+ /* Unlock direct block */
+ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block")
+ dblock = NULL;
+ } /* end if */
+ /* Must be a root indirect block */
+ else {
+ H5HF_indirect_t *iblock; /* Pointer to root indirect block to query */
+ haddr_t iblock_addr; /* Indirect block's address */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Root indirect block to start\n", FUNC);
+#endif /* QAK */
+ /* Get indirect block info */
+ iblock_addr = hdr->man_dtable.table_addr;
+
+ /* Lock root indirect block */
+ /* (which will parse it's free space) */
+ if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, hdr->man_dtable.curr_root_rows, NULL, 0, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
+
+ /* Release the root indirect block */
+ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, iblock, H5AC__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
+ iblock = NULL;
+ } /* end else */
+
+ /* Mark heap as being in sync now */
+ hdr->freelist_sync = TRUE;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_man_start_freelist() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5HF_man_find
*
* Purpose: Find space for an object in a managed obj. heap
@@ -121,10 +237,11 @@ H5HF_free_section_free_cb(void *item, void UNUSED *key, void UNUSED *op_data)
*-------------------------------------------------------------------------
*/
herr_t
-H5HF_man_find(H5HF_t *hdr, hid_t dxpl_id, size_t request,
+H5HF_man_find(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t request,
H5HF_free_section_t **sec_node/*out*/)
{
htri_t node_found; /* Whether an existing free list node was found */
+ hbool_t search_again; /* Whether to search again for another free section */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_man_find)
@@ -139,14 +256,51 @@ HDfprintf(stderr, "%s: request = %Zu\n", FUNC, request);
HDassert(request > 0);
HDassert(sec_node);
- /* Look for free space in global free list */
- if((node_found = H5HF_flist_find(hdr->flist, request, (void **)sec_node)) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't locate free space in fractal heap direct block")
+ /* Search for free space in the globel free list, until a non-opaque node is found */
+ do {
+ /* Done searching, unless opaque node found */
+ search_again = FALSE;
+
+ /* Look for free space in global free list */
+ if((node_found = H5HF_flist_find(hdr->flist, request, (void **)sec_node)) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't locate free space in fractal heap direct block")
+
+ /* Check for opaque section */
+ if(node_found) {
+ if((*sec_node)->type == H5HF_SECT_OPAQUE) {
+ /* Break opaque section down into component sections */
+ if(H5HF_man_iblock_alloc_opaque(hdr, dxpl_id, sec_node) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't break up opaque free section")
+
+ /* Search again */
+ search_again = TRUE;
+ } /* end if */
+ } /* end if */
+ /* If we didn't find a node, check if we've looked in all the direct blocks in the heap for space */
+ else {
+#ifdef QAK
+HDfprintf(stderr, "%s: hdr->freelist_sync = %u\n", FUNC, (unsigned)hdr->freelist_sync);
+#endif /* QAK */
+ if(!hdr->freelist_sync) {
+#ifdef QAK
+HDfprintf(stderr, "%s: Start free list for existing blocks in heap\n", FUNC);
+#endif /* QAK */
+ /* Start freelist for existing heap */
+ if(H5HF_man_start_freelist(hdr, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, "can't start fractal heap free list")
+
+ /* Search again */
+ search_again = TRUE;
+ } /* end if */
+ } /* end else */
+ } while(search_again);
-/* XXX: Make certain we've loaded all the direct blocks in the heap */
/* If we didn't find a node, go make one big enough to hold the requested block */
if(!node_found) {
+#ifdef QAK
+HDfprintf(stderr, "%s: Allocate new direct block\n", FUNC);
+#endif /* QAK */
/* Allocate direct block big enough to hold requested size */
if(H5HF_man_dblock_new(hdr, dxpl_id, request) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, "can't create fractal heap direct block")
@@ -158,10 +312,9 @@ HDfprintf(stderr, "%s: request = %Zu\n", FUNC, request);
} /* end if */
HDassert(*sec_node);
#ifdef QAK
-HDfprintf(stderr, "%s: (*sec_node)->block_addr = %a\n", FUNC, (*sec_node)->block_addr);
-HDfprintf(stderr, "%s: (*sec_node)->block_size = %Zu\n", FUNC, (*sec_node)->block_size);
HDfprintf(stderr, "%s: (*sec_node)->sect_addr = %a\n", FUNC, (*sec_node)->sect_addr);
HDfprintf(stderr, "%s: (*sec_node)->sect_size = %Zu\n", FUNC, (*sec_node)->sect_size);
+HDfprintf(stderr, "%s: (*sec_node)->type = %u\n", FUNC, (unsigned)(*sec_node)->type);
#endif /* QAK */
done:
@@ -183,7 +336,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5HF_man_insert(H5HF_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sec_node,
+H5HF_man_insert(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sec_node,
size_t obj_size, const void *obj, void *id)
{
H5HF_direct_t *dblock = NULL; /* Pointer to direct block to modify */
@@ -205,8 +358,9 @@ H5HF_man_insert(H5HF_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sec_node,
#ifdef QAK
HDfprintf(stderr, "%s: sec_node->sect_addr = %a\n", FUNC, sec_node->sect_addr);
HDfprintf(stderr, "%s: sec_node->sect_size = %Zu\n", FUNC, sec_node->sect_size);
-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.iblock_nrows = %u\n", FUNC, sec_node->u.indirect.iblock_nrows);
+HDfprintf(stderr, "%s: sec_node->u.indirect.iblock = %p\n", FUNC, sec_node->u.indirect.iblock);
+if(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);
@@ -215,7 +369,7 @@ HDfprintf(stderr, "%s: sec_node->u.indirect.indir_nrows = %u\n", FUNC, sec_node-
#endif /* QAK */
/* Allocate 'single' selection out of 'indirect' selection */
- if(H5HF_man_iblock_alloc_indirect(hdr, dxpl_id, &sec_node, obj_size) < 0)
+ 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 */
@@ -223,14 +377,15 @@ HDfprintf(stderr, "%s: sec_node->u.indirect.indir_nrows = %u\n", FUNC, sec_node-
#ifdef QAK
HDfprintf(stderr, "%s: sec_node->sect_addr = %a\n", FUNC, sec_node->sect_addr);
HDfprintf(stderr, "%s: sec_node->sect_size = %Zu\n", FUNC, sec_node->sect_size);
-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.iblock_nrows = %u\n", FUNC, sec_node->u.range.iblock_nrows);
+HDfprintf(stderr, "%s: sec_node->u.range.iblock = %p\n", FUNC, sec_node->u.range.iblock);
+if(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, obj_size) < 0)
+ 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")
} /* end if */
@@ -238,11 +393,15 @@ HDfprintf(stderr, "%s: sec_node->u.range.num_entries = %u\n", FUNC, sec_node->u.
#ifdef QAK
HDfprintf(stderr, "%s: sec_node->sect_addr = %a\n", FUNC, sec_node->sect_addr);
HDfprintf(stderr, "%s: sec_node->sect_size = %Zu\n", FUNC, sec_node->sect_size);
+HDfprintf(stderr, "%s: sec_node->u.single.parent = %p\n", FUNC, sec_node->u.single.parent);
+if(sec_node->u.single.parent)
+ HDfprintf(stderr, "%s: sec_node->u.single.parent->addr = %a\n", FUNC, sec_node->u.single.parent->addr);
+HDfprintf(stderr, "%s: sec_node->u.single.par_entry = %u\n", FUNC, sec_node->u.single.par_entry);
HDfprintf(stderr, "%s: sec_node->u.single.dblock_addr = %a\n", FUNC, sec_node->u.single.dblock_addr);
HDfprintf(stderr, "%s: sec_node->u.single.dblock_size = %Zu\n", FUNC, sec_node->u.single.dblock_size);
#endif /* QAK */
dblock_addr = sec_node->u.single.dblock_addr;
- if(NULL == (dblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, &sec_node->u.single.dblock_size, hdr, H5AC_WRITE)))
+ if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, sec_node->u.single.dblock_size, sec_node->u.single.parent, sec_node->u.single.par_entry, H5AC_WRITE)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load fractal heap direct block")
/* Insert object into block */
@@ -314,6 +473,14 @@ HDfprintf(stderr, "%s: node->size = %Zu\n", FUNC, node->size);
free_frag_size = (unsigned char )(node->size - full_obj_size);
whole_node = TRUE;
+ /* Drop reference count on parent indirect block of direct block that free section is in */
+ HDassert(dblock->parent == NULL ||
+ sec_node->u.single.parent == NULL ||
+ dblock->parent == sec_node->u.single.parent);
+ if(sec_node->u.single.parent)
+ if(H5HF_iblock_decr(sec_node->u.single.parent) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block")
+
/* Release the memory for the free list node & section */
H5FL_FREE(H5HF_direct_free_node_t, node);
H5FL_FREE(H5HF_free_section_t, sec_node);
@@ -350,7 +517,7 @@ HDfprintf(stderr, "%s: full_obj_size = %Zu\n", FUNC, full_obj_size);
HDfprintf(stderr, "%s: alloc_obj_size = %Zu\n", FUNC, alloc_obj_size);
#endif /* QAK */
/* Reduce space available in parent block(s) */
- if(H5HF_man_dblock_adj_free(dxpl_id, dblock, -(ssize_t)free_obj_size) < 0)
+ if(H5HF_man_dblock_adj_free(dblock, -(ssize_t)free_obj_size) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't adjust free space for direct block & parents")
/* Encode the object in the block */
@@ -391,7 +558,7 @@ HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "inserting within mapped managed bl
hdr->nobjs++;
/* Mark heap header as modified */
- if(H5HF_hdr_dirty(dxpl_id, hdr) < 0)
+ if(H5HF_hdr_dirty(hdr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
done:
@@ -417,7 +584,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5HF_man_read(H5HF_t *hdr, hid_t dxpl_id, hsize_t obj_off, size_t obj_len, void *obj)
+H5HF_man_read(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t obj_off, size_t obj_len, void *obj)
{
H5HF_direct_t *dblock; /* Pointer to direct block to query */
size_t blk_off; /* Offset of object in block */
@@ -441,11 +608,11 @@ HDfprintf(stderr, "%s: obj_off = %Hu, obj_len = %Zu\n", FUNC, obj_off, obj_len);
/* Check for root direct block */
if(hdr->man_dtable.curr_root_rows == 0) {
/* Set direct block info */
- dblock_addr = hdr->man_dtable.table_addr;
- dblock_size = hdr->man_dtable.cparam.start_block_size;
+ dblock_addr = hdr->man_dtable.table_addr;
+ dblock_size = hdr->man_dtable.cparam.start_block_size;
/* Lock direct block */
- if(NULL == (dblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, &dblock_size, hdr, H5AC_READ)))
+ if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, NULL, 0, H5AC_READ)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap direct block")
} /* end if */
else {
@@ -467,8 +634,8 @@ HDfprintf(stderr, "%s: row = %u, col = %u\n", FUNC, row, col);
HDfprintf(stderr, "%s: iblock_addr = %a\n", FUNC, iblock_addr);
#endif /* QAK */
- /* Lock indirect block */
- if(NULL == (iblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, &hdr->man_dtable.curr_root_rows, hdr, H5AC_READ)))
+ /* Lock root indirect block */
+ if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, hdr->man_dtable.curr_root_rows, NULL, 0, H5AC_READ)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
/* Check for indirect block row */
@@ -490,7 +657,7 @@ HDfprintf(stderr, "%s: entry = %Zu\n", FUNC, entry);
new_iblock_addr = iblock->ents[entry].addr;
/* Lock new indirect block */
- if(NULL == (new_iblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, new_iblock_addr, &nrows, hdr, H5AC_READ)))
+ if(NULL == (new_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, new_iblock_addr, nrows, iblock, entry, H5AC_READ)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
/* Release the current indirect block */
@@ -525,7 +692,7 @@ HDfprintf(stderr, "%s: entry address = %a\n", FUNC, iblock->ents[entry].addr);
dblock_size = hdr->man_dtable.row_block_size[row];
/* Lock direct block */
- if(NULL == (dblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, &dblock_size, hdr, H5AC_READ)))
+ if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, iblock, entry, H5AC_READ)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap direct block")
/* Unlock indirect block */