summaryrefslogtreecommitdiffstats
path: root/src/H5HFdblock.c
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2006-04-30 13:32:41 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2006-04-30 13:32:41 (GMT)
commit4965bf1839b4219c3063e27d37bc59a777cc1fb5 (patch)
tree925c87307aa9c13c66c301b0d3ca9283e9b20d32 /src/H5HFdblock.c
parenteb96132022da938d4b54ae4dd482919a178c4ee5 (diff)
downloadhdf5-4965bf1839b4219c3063e27d37bc59a777cc1fb5.zip
hdf5-4965bf1839b4219c3063e27d37bc59a777cc1fb5.tar.gz
hdf5-4965bf1839b4219c3063e27d37bc59a777cc1fb5.tar.bz2
[svn-r12317] Purpose:
Code checkpoint Description: More progress on fractal heap, can now re-open an existing heap, although the free space algorithm still needs work. Also, use the new "pinned entry" metadata cache code. Platforms tested: FreeBSD 4.11 (sleipnir) Linux 2.4 (heping) Solaris 9 (shanti) Linux 2.4/64 (mir)
Diffstat (limited to 'src/H5HFdblock.c')
-rw-r--r--src/H5HFdblock.c269
1 files changed, 238 insertions, 31 deletions
diff --git a/src/H5HFdblock.c b/src/H5HFdblock.c
index dcb704c..8ac411b 100644
--- a/src/H5HFdblock.c
+++ b/src/H5HFdblock.c
@@ -56,6 +56,8 @@
/********************/
/* Local Prototypes */
/********************/
+static herr_t H5HF_man_dblock_regen_freelist(H5HF_direct_t *dblock,
+ haddr_t dblock_addr);
/*********************/
@@ -97,7 +99,7 @@ H5FL_DEFINE(H5HF_direct_free_node_t);
*-------------------------------------------------------------------------
*/
herr_t
-H5HF_man_dblock_create(hid_t dxpl_id, H5HF_t *hdr, H5HF_indirect_t *par_iblock,
+H5HF_man_dblock_create(hid_t dxpl_id, H5HF_hdr_t *hdr, H5HF_indirect_t *par_iblock,
unsigned par_entry, size_t block_size, hsize_t block_off, haddr_t *addr_p,
H5HF_free_section_t **ret_sec_node)
{
@@ -126,7 +128,7 @@ H5HF_man_dblock_create(hid_t dxpl_id, H5HF_t *hdr, H5HF_indirect_t *par_iblock,
HDmemset(&dblock->cache_info, 0, sizeof(H5AC_info_t));
/* Share common heap information */
- dblock->shared = hdr;
+ dblock->hdr = hdr;
if(H5HF_hdr_incr(hdr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared heap header")
@@ -138,17 +140,12 @@ HDfprintf(stderr, "%s: size = %Zu, block_off = %Hu\n", FUNC, block_size, block_o
if(dblock->parent) {
if(H5HF_iblock_incr(par_iblock) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block")
- dblock->par_addr = par_iblock->addr;
- dblock->par_nrows = par_iblock->nrows;
} /* end if */
- else {
- dblock->par_addr = HADDR_UNDEF;
- dblock->par_nrows = 0;
- } /* end else */
dblock->par_entry = par_entry;
dblock->size = block_size;
dblock->block_off = block_off;
dblock->blk_off_size = H5HF_SIZEOF_OFFSET_LEN(block_size);
+ dblock->fl_gen = hdr->fl_gen; /* New blocks have their free list generation set up correctly */
dblock->free_list_head = H5HF_MAN_ABS_DIRECT_OVERHEAD_DBLOCK(hdr, dblock);
dblock->blk_free_space = block_size -
(H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE(hdr, block_size) + H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr));
@@ -194,6 +191,12 @@ HDmemset(dblock->blk, 0, dblock->size);
/* (section size is "object size", without the metadata overhead) */
sec_node->sect_size = node->size - H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr);
sec_node->type = H5HF_SECT_SINGLE;
+ sec_node->u.single.parent = dblock->parent;
+ if(dblock->parent) {
+ if(H5HF_iblock_incr(dblock->parent) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block")
+ } /* end if */
+ sec_node->u.single.par_entry = dblock->par_entry;
sec_node->u.single.dblock_addr = *addr_p;
sec_node->u.single.dblock_size = block_size;
@@ -256,7 +259,7 @@ H5HF_man_dblock_build_freelist(H5HF_direct_t *dblock, haddr_t dblock_addr)
if(dblock->free_list_head == 0)
head->first = NULL;
else {
- H5HF_t *hdr; /* Pointer to shared heap header */
+ H5HF_hdr_t *hdr; /* Pointer to shared heap header */
H5HF_free_section_t *sec_node; /* Pointer to free list section for block */
H5HF_direct_free_node_t *node = NULL; /* Pointer to free list node for block */
H5HF_direct_free_node_t *prev_node; /* Pointer to previous free list node for block */
@@ -266,7 +269,7 @@ H5HF_man_dblock_build_freelist(H5HF_direct_t *dblock, haddr_t dblock_addr)
uint8_t *p; /* Temporary pointer to free node info */
/* Get the pointer to the shared heap info */
- hdr = dblock->shared;
+ hdr = dblock->hdr;
/* Point to first node in free list */
p = dblock->blk + dblock->free_list_head;
@@ -300,6 +303,12 @@ H5HF_man_dblock_build_freelist(H5HF_direct_t *dblock, haddr_t dblock_addr)
/* (section size is "object size", without the metadata overhead) */
sec_node->sect_size = node->size - H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr);
sec_node->type = H5HF_SECT_SINGLE;
+ sec_node->u.single.parent = dblock->parent;
+ if(dblock->parent) {
+ if(H5HF_iblock_incr(dblock->parent) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block")
+ } /* end if */
+ sec_node->u.single.par_entry = dblock->par_entry;
sec_node->u.single.dblock_addr = dblock_addr;
sec_node->u.single.dblock_size = dblock->size;
@@ -343,6 +352,12 @@ H5HF_man_dblock_build_freelist(H5HF_direct_t *dblock, haddr_t dblock_addr)
/* (section size is "object size", without the metadata overhead) */
sec_node->sect_size = node->size - H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr);
sec_node->type = H5HF_SECT_SINGLE;
+ sec_node->u.single.parent = dblock->parent;
+ if(dblock->parent) {
+ if(H5HF_iblock_incr(dblock->parent) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block")
+ } /* end if */
+ sec_node->u.single.par_entry = dblock->par_entry;
sec_node->u.single.dblock_addr = dblock_addr;
sec_node->u.single.dblock_size = dblock->size;
@@ -369,6 +384,123 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5HF_man_dblock_regen_freelist
+ *
+ * Purpose: Regenerate the free section information for the free space
+ * in a direct block's free list.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Apr 25 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_man_dblock_regen_freelist(H5HF_direct_t *dblock, haddr_t dblock_addr)
+{
+ H5HF_hdr_t *hdr; /* Pointer to shared heap header */
+ H5HF_free_section_t *sec_node; /* Pointer to free list section for block */
+ H5HF_direct_free_node_t *node; /* First node in free list */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_dblock_regen_freelist)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(dblock);
+ HDassert(dblock->free_list);
+
+ /* Get the pointer to the shared heap info */
+ hdr = dblock->hdr;
+
+ /* Iterate through nodes on block's free list */
+ node = dblock->free_list->first;
+ while(node) {
+ /* Create free list section node */
+ if(NULL == (sec_node = H5FL_MALLOC(H5HF_free_section_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section")
+
+ /* Set section's information */
+ sec_node->sect_addr = dblock->block_off + node->my_offset;
+ /* (section size is "object size", without the metadata overhead) */
+ sec_node->sect_size = node->size - H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr);
+ sec_node->type = H5HF_SECT_SINGLE;
+ sec_node->u.single.parent = dblock->parent;
+ if(dblock->parent) {
+ if(H5HF_iblock_incr(dblock->parent) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block")
+ } /* end if */
+ sec_node->u.single.par_entry = dblock->par_entry;
+ sec_node->u.single.dblock_addr = dblock_addr;
+ sec_node->u.single.dblock_size = dblock->size;
+
+ /* Add new free space to the global list of space */
+ if(H5HF_flist_add(hdr->flist, sec_node, &sec_node->sect_size, &sec_node->sect_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add direct block free space to global list")
+
+ /* Advance to next node */
+ node = node->next;
+ } /* end while */
+
+done:
+/* XXX: cleanup on failure? */
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_man_dblock_regen_freelist() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_man_dblock_destroy_freelist
+ *
+ * Purpose: Destroy the free list information for a direct block
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Apr 22 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_man_dblock_destroy_freelist(H5HF_direct_t *dblock)
+{
+ H5HF_direct_free_node_t *node; /* Pointer to free list node for block */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_man_dblock_destroy_freelist)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(dblock);
+ HDassert(dblock->free_list);
+
+ /* Walk through list, freeing the nodes */
+ node = dblock->free_list->first;
+ while(node) {
+ H5HF_direct_free_node_t *last_node; /* Pointer to last free list node for block */
+
+ /* Advance to next node */
+ last_node = node;
+ node = node->next;
+
+ /* Release the last node */
+ H5FL_FREE(H5HF_direct_free_node_t, last_node);
+ } /* end while */
+
+ /* Release the free list head */
+ H5FL_FREE(H5HF_direct_free_head_t, dblock->free_list);
+
+ /* Reset the free list head */
+ dblock->free_list = NULL;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5HF_man_dblock_destroy_freelist() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5HF_man_dblock_adj_free
*
* Purpose: Adjust the free space for a direct block, and it's parents
@@ -382,9 +514,9 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5HF_man_dblock_adj_free(hid_t dxpl_id, H5HF_direct_t *dblock, ssize_t amt)
+H5HF_man_dblock_adj_free(H5HF_direct_t *dblock, ssize_t amt)
{
- H5HF_t *hdr; /* Shared heap information */
+ H5HF_hdr_t *hdr; /* Shared heap information */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_man_dblock_adj_free)
@@ -398,7 +530,7 @@ HDfprintf(stderr, "%s: amt = %Zd\n", FUNC, amt);
HDassert(dblock);
/* Get the pointer to the shared heap header */
- hdr = dblock->shared;
+ hdr = dblock->hdr;
/* Adjust space available in block */
HDassert(amt > 0 || dblock->blk_free_space >= (size_t)-amt);
@@ -424,7 +556,7 @@ HDfprintf(stderr, "%s: iblock->ents[dblock->par_entry].free_space = %Hu\n", FUNC
iblock->child_free_space += amt;
/* Mark indirect block as dirty */
- if(H5HF_iblock_dirty(dxpl_id, iblock) < 0)
+ if(H5HF_iblock_dirty(iblock) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty")
/* Modify the free space in parent block(s) */
@@ -443,7 +575,7 @@ HDfprintf(stderr, "%s: iblock->ents[dblock->par_entry].free_space = %Hu\n", FUNC
iblock->child_free_space += amt;
/* Mark indirect block as dirty */
- if(H5HF_iblock_dirty(dxpl_id, iblock) < 0)
+ if(H5HF_iblock_dirty(iblock) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty")
} /* end while */
} /* end if */
@@ -456,7 +588,7 @@ HDfprintf(stderr, "%s: hdr->total_man_free = %Hu\n", FUNC, hdr->total_man_free);
#endif /* QAK */
/* 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:
@@ -479,12 +611,13 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5HF_man_dblock_new(H5HF_t *hdr, hid_t dxpl_id, size_t request)
+H5HF_man_dblock_new(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t request)
{
- haddr_t dblock_addr; /* Address of new direct block */
- size_t dblock_size; /* Size of new direct block */
- size_t min_dblock_size; /* Min. size of direct block to allocate */
- herr_t ret_value = SUCCEED; /* Return value */
+ haddr_t dblock_addr; /* Address of new direct block */
+ hsize_t dblock_off; /* Direct block offset in heap address space */
+ size_t dblock_size; /* Size of new direct block */
+ size_t min_dblock_size; /* Min. size of direct block to allocate */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_man_dblock_new)
#ifdef QAK
@@ -523,7 +656,8 @@ HDfprintf(stderr, "%s: Check 2 - min_dblock_size = %Zu\n", FUNC, min_dblock_size
min_dblock_size == hdr->man_dtable.cparam.start_block_size) {
/* Create new direct block at starting offset */
dblock_size = hdr->man_dtable.cparam.start_block_size;
- if(H5HF_man_dblock_create(dxpl_id, hdr, NULL, 0, dblock_size, (hsize_t)0, &dblock_addr, NULL) < 0)
+ dblock_off = 0;
+ if(H5HF_man_dblock_create(dxpl_id, hdr, NULL, 0, dblock_size, dblock_off, &dblock_addr, NULL) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap direct block")
#ifdef QAK
@@ -541,15 +675,14 @@ HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr);
/* Root entry already exists, go get indirect block for new direct block */
else {
H5HF_indirect_t *iblock; /* Pointer to indirect block to create */
- haddr_t iblock_addr; /* Indirect block's address */
size_t dblock_entry; /* Direct entry for new direct block */
- hsize_t dblock_off; /* Direct block offset in heap address space */
/* Find indirect block with room for block of correct size */
- if(NULL == (iblock = H5HF_man_iblock_place_dblock(hdr, dxpl_id, min_dblock_size, &iblock_addr, &dblock_entry, &dblock_size)))
+ if(NULL == (iblock = H5HF_man_iblock_place_dblock(hdr, dxpl_id, min_dblock_size, &dblock_entry, &dblock_size)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to locate indirect block with space for direct block")
#ifdef QAK
-HDfprintf(stderr, "%s: iblock_addr = %a\n", FUNC, iblock_addr);
+HDfprintf(stderr, "%s: iblock = %p\n", FUNC, iblock);
+HDfprintf(stderr, "%s: iblock->addr = %a\n", FUNC, iblock->addr);
HDfprintf(stderr, "%s: dblock_entry = %Zu\n", FUNC, dblock_entry);
HDfprintf(stderr, "%s: dblock_size = %Zu\n", FUNC, dblock_size);
#endif /* QAK */
@@ -571,15 +704,89 @@ HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr);
iblock->ents[dblock_entry].addr = dblock_addr;
/* Mark indirect block as modified */
- if(H5HF_iblock_dirty(dxpl_id, iblock) < 0)
+ if(H5HF_iblock_dirty(iblock) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty")
-
- /* Release the indirect block (marked as dirty) */
- if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, iblock, H5AC__DIRTIED_FLAG) < 0)
- HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
} /* end else */
+ /* Advance the allocated heap size/new block iterator */
+ if(H5HF_hdr_inc_alloc(hdr, dblock_off + dblock_size, 1) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't increase allocated heap size")
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_man_dblock_new() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_man_dblock_protect
+ *
+ * Purpose: Convenience wrapper around H5AC_protect on a direct block
+ * (Use H5AC_unprotect to unprotect it for now)
+ *
+ * Return: Pointer to direct block on success, NULL on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Apr 17 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+H5HF_direct_t *
+H5HF_man_dblock_protect(H5HF_hdr_t *hdr, hid_t dxpl_id, haddr_t dblock_addr,
+ size_t dblock_size, H5HF_indirect_t *par_iblock, unsigned par_entry,
+ H5AC_protect_t rw)
+{
+ H5HF_parent_t par_info; /* Parent info for loading block */
+ H5HF_direct_t *dblock; /* Direct block from cache */
+ H5HF_direct_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_dblock_protect)
+#ifdef QAK
+HDfprintf(stderr, "%s: dblock_addr = %a, dblock_size = %Zu\n", FUNC, dblock_addr, dblock_size);
+#endif /* QAK */
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+ HDassert(H5F_addr_defined(dblock_addr));
+ HDassert(dblock_size > 0);
+
+ /* Set up parent info */
+ par_info.hdr = hdr;
+ par_info.iblock = par_iblock;
+ par_info.entry = par_entry;
+
+ /* Protect the direct block */
+ if(NULL == (dblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, &dblock_size, &par_info, rw)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap direct block")
+
+ /* Regenerate the free list information for this block, if necessary */
+ /* (Only create free list information if write access is requested) */
+ if(rw == H5AC_WRITE && hdr->fl_gen != dblock->fl_gen) {
+#ifdef QAK
+HDfprintf(stderr, "%s: building free list for direct block\n", FUNC);
+#endif /* QAK */
+ /* If the block has a free list from a previous generation, get rid of it */
+ if(dblock->free_list) {
+ if(H5HF_man_dblock_regen_freelist(dblock, dblock_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, NULL, "can't regenerate free list for direct block")
+ } /* end if */
+ else {
+ /* Build the free list for the block */
+ if(H5HF_man_dblock_build_freelist(dblock, dblock_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDECODE, NULL, "can't decode free list for block")
+ } /* end else */
+ HDassert(dblock->free_list);
+
+ /* Mark the block's free list generation as up to date now */
+ dblock->fl_gen = hdr->fl_gen;
+ } /* end if */
+
+ /* Set the return value */
+ ret_value = dblock;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_man_dblock_protect() */
+