summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/H5AC.c13
-rw-r--r--src/H5ACprivate.h3
-rw-r--r--src/H5C.c6
-rw-r--r--src/H5Cpkg.h2
-rw-r--r--src/H5Dlayout.c6
-rw-r--r--src/H5Fsuper_cache.c5
-rw-r--r--src/H5Gent.c2
-rw-r--r--src/H5Glink.c60
-rw-r--r--src/H5Gnode.c44
-rw-r--r--src/H5Gpkg.h5
-rw-r--r--src/H5Gstab.c39
-rw-r--r--src/H5Gtest.c2
-rw-r--r--src/H5HL.c591
-rw-r--r--src/H5HLcache.c810
-rw-r--r--src/H5HLdbg.c26
-rw-r--r--src/H5HLint.c417
-rw-r--r--src/H5HLpkg.h97
-rw-r--r--src/H5HLprivate.h4
-rw-r--r--src/H5Oefl.c10
-rwxr-xr-xsrc/Makefile.am2
-rw-r--r--src/Makefile.in19
21 files changed, 1613 insertions, 550 deletions
diff --git a/src/H5AC.c b/src/H5AC.c
index cbe4dd0..e2e0364 100644
--- a/src/H5AC.c
+++ b/src/H5AC.c
@@ -480,7 +480,8 @@ static const char * H5AC_entry_type_names[H5AC_NTYPES] =
{
"B-tree nodes",
"symbol table nodes",
- "local heaps",
+ "local heap prefixes",
+ "local heap data blocks",
"global heaps",
"object headers",
"v2 B-tree headers",
@@ -521,11 +522,11 @@ H5AC_create(const H5F_t *f,
FUNC_ENTER_NOAPI(H5AC_create, FAIL)
- HDassert ( f );
- HDassert ( NULL == f->shared->cache );
- HDassert ( config_ptr != NULL ) ;
- HDassert ( NELMTS(H5AC_entry_type_names) == H5AC_NTYPES);
- HDassert ( H5C__MAX_NUM_TYPE_IDS == H5AC_NTYPES);
+ HDassert(f);
+ HDassert(NULL == f->shared->cache);
+ HDassert(config_ptr != NULL) ;
+ HDcompile_assert(NELMTS(H5AC_entry_type_names) == H5AC_NTYPES);
+ HDcompile_assert(H5C__MAX_NUM_TYPE_IDS == H5AC_NTYPES);
result = H5AC_validate_config(config_ptr);
diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h
index d36069a..cdb547e 100644
--- a/src/H5ACprivate.h
+++ b/src/H5ACprivate.h
@@ -49,7 +49,8 @@
typedef enum {
H5AC_BT_ID = 0, /*B-tree nodes */
H5AC_SNODE_ID, /*symbol table nodes */
- H5AC_LHEAP_ID, /*local heap */
+ H5AC_LHEAP_PRFX_ID, /*local heap prefix */
+ H5AC_LHEAP_DBLK_ID, /*local heap data block */
H5AC_GHEAP_ID, /*global heap */
H5AC_OHDR_ID, /*object header */
H5AC_BT2_HDR_ID, /*v2 B-tree header */
diff --git a/src/H5C.c b/src/H5C.c
index ef58012..d40cd62 100644
--- a/src/H5C.c
+++ b/src/H5C.c
@@ -11477,9 +11477,9 @@ H5C_load_entry(H5F_t * f,
*
* with:
*
- * HDassert( ( entry_ptr->is_dirty == FALSE ) || ( type->id == 4 ) );
+ * HDassert( ( entry_ptr->is_dirty == FALSE ) || ( type->id == 5 ) );
*
- * Note that type id 4 is associated with object headers in the metadata
+ * Note that type id 5 is associated with object headers in the metadata
* cache.
*
* When we get to using H5C for other purposes, we may wish to
@@ -11487,7 +11487,7 @@ H5C_load_entry(H5F_t * f,
* metadata cache.
*/
- HDassert( ( entry_ptr->is_dirty == FALSE ) || ( type->id == 4 ) );
+ HDassert( ( entry_ptr->is_dirty == FALSE ) || ( type->id == 5 ) );
#ifndef NDEBUG
entry_ptr->magic = H5C__H5C_CACHE_ENTRY_T_MAGIC;
#endif /* NDEBUG */
diff --git a/src/H5Cpkg.h b/src/H5Cpkg.h
index 4bc105d..719dec9 100644
--- a/src/H5Cpkg.h
+++ b/src/H5Cpkg.h
@@ -857,7 +857,7 @@
****************************************************************************/
#define H5C__H5C_T_MAGIC 0x005CAC0E
-#define H5C__MAX_NUM_TYPE_IDS 25
+#define H5C__MAX_NUM_TYPE_IDS 26
#define H5C__PREFIX_LEN 32
struct H5C_t
diff --git a/src/H5Dlayout.c b/src/H5Dlayout.c
index d6b7619..5a5a9f6 100644
--- a/src/H5Dlayout.c
+++ b/src/H5Dlayout.c
@@ -254,7 +254,7 @@ H5D_layout_oh_create(H5F_t *file, hid_t dxpl_id, H5O_t *oh, H5D_t *dset,
/* Insert "empty" name first */
if((size_t)(-1) == H5HL_insert(file, dxpl_id, heap, (size_t)1, "")) {
- H5HL_unprotect(file, dxpl_id, heap, efl->heap_addr);
+ H5HL_unprotect(file, heap);
HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert file name into heap")
} /* end if */
@@ -264,7 +264,7 @@ H5D_layout_oh_create(H5F_t *file, hid_t dxpl_id, H5O_t *oh, H5D_t *dset,
/* Insert file name into heap */
if((size_t)(-1) == (offset = H5HL_insert(file, dxpl_id, heap,
HDstrlen(efl->slot[u].name) + 1, efl->slot[u].name))) {
- H5HL_unprotect(file, dxpl_id, heap, efl->heap_addr);
+ H5HL_unprotect(file, heap);
HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert file name into heap")
} /* end if */
@@ -274,7 +274,7 @@ H5D_layout_oh_create(H5F_t *file, hid_t dxpl_id, H5O_t *oh, H5D_t *dset,
} /* end for */
/* Release the heap */
- if(H5HL_unprotect(file, dxpl_id, heap, efl->heap_addr) < 0)
+ if(H5HL_unprotect(file, heap) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTUNPROTECT, FAIL, "unable to unprotect EFL file name heap")
heap = NULL;
diff --git a/src/H5Fsuper_cache.c b/src/H5Fsuper_cache.c
index d2aaef8..3057d09 100644
--- a/src/H5Fsuper_cache.c
+++ b/src/H5Fsuper_cache.c
@@ -155,7 +155,8 @@ H5F_sblock_load(H5F_t *f, hid_t dxpl_id, haddr_t UNUSED addr, const void UNUSED
/* Read fixed-size portion of the superblock */
p = sbuf;
- if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, fixed_size) < 0)
+ H5_CHECK_OVERFLOW(fixed_size, size_t, haddr_t);
+ if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, (haddr_t)fixed_size) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "set end of space allocation request failed")
if(H5FD_read(lf, dxpl_id, H5FD_MEM_SUPER, (haddr_t)0, fixed_size, p) < 0)
HGOTO_ERROR(H5E_FILE, H5E_READERROR, NULL, "unable to read superblock")
@@ -182,7 +183,7 @@ H5F_sblock_load(H5F_t *f, hid_t dxpl_id, haddr_t UNUSED addr, const void UNUSED
HDassert(fixed_size + variable_size <= sizeof(sbuf));
/* Read in variable-sized portion of superblock */
- if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, fixed_size + variable_size) < 0)
+ if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, (haddr_t)fixed_size + variable_size) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "set end of space allocation request failed")
if(H5FD_read(lf, dxpl_id, H5FD_MEM_SUPER, (haddr_t)fixed_size, variable_size, p) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to read superblock")
diff --git a/src/H5Gent.c b/src/H5Gent.c
index 2b499fe..18883ac 100644
--- a/src/H5Gent.c
+++ b/src/H5Gent.c
@@ -471,7 +471,7 @@ H5G_ent_debug(const H5G_entry_t *ent, FILE *stream, int indent, int fwidth,
"Link value offset:",
(unsigned long)(ent->cache.slink.lval_offset));
if(heap) {
- lval = (const char *)H5HL_offset_into(ent->file, heap, ent->cache.slink.lval_offset);
+ lval = (const char *)H5HL_offset_into(heap, ent->cache.slink.lval_offset);
HDfprintf(stream, "%*s%-*s %s\n", nested_indent, "", nested_fwidth,
"Link value:",
lval);
diff --git a/src/H5Glink.c b/src/H5Glink.c
index 488c05b..f5ad7d9 100644
--- a/src/H5Glink.c
+++ b/src/H5Glink.c
@@ -218,13 +218,12 @@ H5G_link_cmp_corder_dec(const void *lnk1, const void *lnk2)
*-------------------------------------------------------------------------
*/
herr_t
-H5G_ent_to_link(H5F_t *f, H5O_link_t *lnk, const H5HL_t *heap,
+H5G_ent_to_link(H5O_link_t *lnk, const H5HL_t *heap,
const H5G_entry_t *ent, const char *name)
{
FUNC_ENTER_NOAPI_NOFUNC(H5G_ent_to_link)
/* check arguments */
- HDassert(f);
HDassert(lnk);
HDassert(heap);
HDassert(ent);
@@ -241,7 +240,7 @@ H5G_ent_to_link(H5F_t *f, H5O_link_t *lnk, const H5HL_t *heap,
if(ent->type == H5G_CACHED_SLINK) {
const char *s; /* Pointer to link value */
- s = (const char *)H5HL_offset_into(f, heap, ent->cache.slink.lval_offset);
+ s = (const char *)H5HL_offset_into(heap, ent->cache.slink.lval_offset);
HDassert(s);
/* Copy the link value */
@@ -263,61 +262,6 @@ H5G_ent_to_link(H5F_t *f, H5O_link_t *lnk, const H5HL_t *heap,
/*-------------------------------------------------------------------------
- * Function: H5G_ent_to_info
- *
- * Purpose: Make link info for a symbol table entry
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Nov 16 2006
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5G_ent_to_info(H5F_t *f, H5L_info_t *info, const H5HL_t *heap,
- const H5G_entry_t *ent)
-{
- FUNC_ENTER_NOAPI_NOFUNC(H5G_ent_to_info)
-
- /* check arguments */
- HDassert(f);
- HDassert(info);
- HDassert(heap);
- HDassert(ent);
-
- /* Set (default) common info for info */
- info->cset = H5F_DEFAULT_CSET;
- info->corder = 0;
- info->corder_valid = FALSE; /* Creation order not valid for this link */
-
- /* Object is a symbolic or hard link */
- if(ent->type == H5G_CACHED_SLINK) {
- const char *s; /* Pointer to link value */
-
- s = (const char *)H5HL_offset_into(f, heap, ent->cache.slink.lval_offset);
- HDassert(s);
-
- /* Get the link value size */
- info->u.val_size = HDstrlen(s) + 1;
-
- /* Set link type */
- info->type = H5L_TYPE_SOFT;
- } /* end if */
- else {
- /* Set address of object */
- info->u.address = ent->header;
-
- /* Set link type */
- info->type = H5L_TYPE_HARD;
- } /* end else */
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5G_ent_to_info() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5G_link_to_info
*
* Purpose: Retrieve information from a link object
diff --git a/src/H5Gnode.c b/src/H5Gnode.c
index ce41727..ca6cb6c 100644
--- a/src/H5Gnode.c
+++ b/src/H5Gnode.c
@@ -218,8 +218,8 @@ H5G_node_encode_key(const H5F_t *f, const H5B_t UNUSED *bt, uint8_t *raw, void *
*-------------------------------------------------------------------------
*/
static herr_t
-H5G_node_debug_key(FILE *stream, H5F_t *f, hid_t UNUSED dxpl_id, int indent,
- int fwidth, const void *_key, const void *_udata)
+H5G_node_debug_key(FILE *stream, H5F_t UNUSED *f, hid_t UNUSED dxpl_id,
+ int indent, int fwidth, const void *_key, const void *_udata)
{
const H5G_node_key_t *key = (const H5G_node_key_t *) _key;
const H5G_bt_common_t *udata = (const H5G_bt_common_t *) _udata;
@@ -236,7 +236,7 @@ H5G_node_debug_key(FILE *stream, H5F_t *f, hid_t UNUSED dxpl_id, int indent,
HDfprintf(stream, "%*s%-*s ", indent, "", fwidth, "Name:");
- s = (const char *)H5HL_offset_into(f, udata->heap, key->offset);
+ s = (const char *)H5HL_offset_into(udata->heap, key->offset);
HDfprintf(stream, "%s\n", s);
} /* end if */
else
@@ -367,7 +367,7 @@ done:
*-------------------------------------------------------------------------
*/
static int
-H5G_node_cmp2(H5F_t *f, hid_t UNUSED dxpl_id, void *_lt_key, void *_udata,
+H5G_node_cmp2(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, void *_lt_key, void *_udata,
void *_rt_key)
{
H5G_bt_common_t *udata = (H5G_bt_common_t *) _udata;
@@ -385,7 +385,7 @@ H5G_node_cmp2(H5F_t *f, hid_t UNUSED dxpl_id, void *_lt_key, void *_udata,
HDassert(rt_key);
/* Get base address of heap */
- base = (const char *)H5HL_offset_into(f, udata->heap, (size_t)0);
+ base = (const char *)H5HL_offset_into(udata->heap, (size_t)0);
HDassert(base);
/* Get pointers to string names */
@@ -427,7 +427,7 @@ H5G_node_cmp2(H5F_t *f, hid_t UNUSED dxpl_id, void *_lt_key, void *_udata,
*-------------------------------------------------------------------------
*/
static int
-H5G_node_cmp3(H5F_t *f, hid_t UNUSED dxpl_id, void *_lt_key, void *_udata,
+H5G_node_cmp3(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, void *_lt_key, void *_udata,
void *_rt_key)
{
H5G_bt_common_t *udata = (H5G_bt_common_t *) _udata;
@@ -445,7 +445,7 @@ H5G_node_cmp3(H5F_t *f, hid_t UNUSED dxpl_id, void *_lt_key, void *_udata,
HDassert(rt_key);
/* Get base address of heap */
- base = (const char *)H5HL_offset_into(f, udata->heap, (size_t)0);
+ base = (const char *)H5HL_offset_into(udata->heap, (size_t)0);
HDassert(base);
/* left side */
@@ -517,7 +517,7 @@ H5G_node_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *_lt_key
HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, FAIL, "unable to protect symbol table node")
/* Get base address of heap */
- base = (const char *)H5HL_offset_into(f, udata->common.heap, (size_t)0);
+ base = (const char *)H5HL_offset_into(udata->common.heap, (size_t)0);
HDassert(base);
/*
@@ -623,7 +623,7 @@ H5G_node_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr,
HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR, "unable to protect symbol table node")
/* Get base address of heap */
- base = (const char *)H5HL_offset_into(f, udata->common.heap, (size_t)0);
+ base = (const char *)H5HL_offset_into(udata->common.heap, (size_t)0);
HDassert(base);
/*
@@ -791,7 +791,7 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/,
const char *base; /* Base of heap */
/* Get base address of heap */
- base = (const char *)H5HL_offset_into(f, udata->common.heap, (size_t)0);
+ base = (const char *)H5HL_offset_into(udata->common.heap, (size_t)0);
/* Find the name with a binary search */
rt = sn->nsyms;
@@ -811,7 +811,7 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/,
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5B_INS_ERROR, "name not found")
/* Get a pointer to the name of the link */
- if(NULL == (lnk.name = (char *)H5HL_offset_into(f, udata->common.heap, sn->entry[idx].name_off)))
+ if(NULL == (lnk.name = (char *)H5HL_offset_into(udata->common.heap, sn->entry[idx].name_off)))
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5B_INS_ERROR, "unable to get link name")
/* Set up rest of link structure */
@@ -820,7 +820,7 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/,
lnk.cset = H5T_CSET_ASCII;
if(sn->entry[idx].type == H5G_CACHED_SLINK) {
lnk.type = H5L_TYPE_SOFT;
- lnk.u.soft.name = (char *)H5HL_offset_into(f, udata->common.heap, sn->entry[idx].cache.slink.lval_offset);
+ lnk.u.soft.name = (char *)H5HL_offset_into(udata->common.heap, sn->entry[idx].cache.slink.lval_offset);
} /* end if */
else {
lnk.type = H5L_TYPE_HARD;
@@ -992,11 +992,11 @@ H5G_node_iterate(H5F_t *f, hid_t dxpl_id, const void UNUSED *_lt_key, haddr_t ad
const char *name; /* Pointer to link name in heap */
/* Get the pointer to the name of the link in the heap */
- name = (const char *)H5HL_offset_into(f, udata->heap, ents[u].name_off);
+ name = (const char *)H5HL_offset_into(udata->heap, ents[u].name_off);
HDassert(name);
/* Convert the entry to a link */
- if(H5G_ent_to_link(f, &lnk, udata->heap, &ents[u], name) < 0)
+ if(H5G_ent_to_link(&lnk, udata->heap, &ents[u], name) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTCONVERT, H5_ITER_ERROR, "unable to convert symbol table entry to link")
/* Make the callback */
@@ -1268,7 +1268,7 @@ H5G_node_copy(H5F_t *f, hid_t dxpl_id, const void UNUSED *_lt_key, haddr_t addr,
grp_loc.oloc = (H5O_loc_t *)src_oloc;
/* Get pointer to link value in local heap */
- link_name = (char *)H5HL_offset_into(f, heap, tmp_src_ent.cache.slink.lval_offset);
+ link_name = (char *)H5HL_offset_into(heap, tmp_src_ent.cache.slink.lval_offset);
/* Check if the object pointed by the soft link exists in the source file */
if(H5G_loc_info(&grp_loc, link_name, FALSE, &oinfo, H5P_DEFAULT, dxpl_id) >= 0) {
@@ -1306,7 +1306,7 @@ H5G_node_copy(H5F_t *f, hid_t dxpl_id, const void UNUSED *_lt_key, haddr_t addr,
/* Construct link information for eventual insertion */
lnk.type = H5L_TYPE_SOFT;
- lnk.u.soft.name = (char *)H5HL_offset_into(f, heap, src_ent->cache.slink.lval_offset);
+ lnk.u.soft.name = (char *)H5HL_offset_into(heap, src_ent->cache.slink.lval_offset);
} /* else if */
else
HDassert(0 && "Unknown entry type");
@@ -1318,7 +1318,7 @@ H5G_node_copy(H5F_t *f, hid_t dxpl_id, const void UNUSED *_lt_key, haddr_t addr,
/* lnk.name = name; */ /* This will be set in callback */
/* Determine name of source object */
- name = (const char *)H5HL_offset_into(f, heap, src_ent->name_off);
+ name = (const char *)H5HL_offset_into(heap, src_ent->name_off);
HDassert(name);
/* Insert the new object in the destination file's group */
@@ -1328,7 +1328,7 @@ H5G_node_copy(H5F_t *f, hid_t dxpl_id, const void UNUSED *_lt_key, haddr_t addr,
} /* end of for (i=0; i<sn->nsyms; i++) */
done:
- if(heap && H5HL_unprotect(f, dxpl_id, heap, udata->src_heap_addr) < 0)
+ if(heap && H5HL_unprotect(f, heap) < 0)
HDONE_ERROR(H5E_SYM, H5E_PROTECT, H5_ITER_ERROR, "unable to unprotect symbol name")
if(sn && H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, H5AC__NO_FLAGS_SET) < 0)
@@ -1393,14 +1393,14 @@ H5G_node_build_table(H5F_t *f, hid_t dxpl_id, const void UNUSED *_lt_key, haddr_
unsigned linkno; /* Link allocated */
/* Get pointer to link's name in the heap */
- name = (const char *)H5HL_offset_into(f, udata->heap, sn->entry[u].name_off);
+ name = (const char *)H5HL_offset_into(udata->heap, sn->entry[u].name_off);
HDassert(name);
/* Determine the link to operate on in the table */
linkno = udata->ltable->nlinks++;
/* Convert the entry to a link */
- if(H5G_ent_to_link(f, &udata->ltable->lnks[linkno], udata->heap, &sn->entry[u], name) < 0)
+ if(H5G_ent_to_link(&udata->ltable->lnks[linkno], udata->heap, &sn->entry[u], name) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTCONVERT, H5_ITER_ERROR, "unable to convert symbol table entry to link")
} /* end for */
@@ -1512,7 +1512,7 @@ H5G_node_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent,
fprintf(stream, "%*sSymbol %u:\n", indent - 3, "", u);
if(heap) {
- const char *s = (const char *)H5HL_offset_into(f, heap, sn->entry[u].name_off);
+ const char *s = (const char *)H5HL_offset_into(heap, sn->entry[u].name_off);
if(s)
fprintf(stream, "%*s%-*s `%s'\n", indent, "", fwidth, "Name:", s);
@@ -1527,7 +1527,7 @@ H5G_node_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent,
done:
if(sn && H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to release symbol table node")
- if(heap && H5HL_unprotect(f, dxpl_id, heap, heap_addr) < 0)
+ if(heap && H5HL_unprotect(f, heap) < 0)
HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap")
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h
index 355b5fd..33ec680 100644
--- a/src/H5Gpkg.h
+++ b/src/H5Gpkg.h
@@ -244,7 +244,6 @@ typedef struct H5G_bt_it_cpy_t {
/* Common information for "by index" lookups in symbol tables */
typedef struct H5G_bt_it_idx_common_t {
/* downward */
- H5F_t *f; /* Pointer to file that symbol table is in */
hsize_t idx; /* Index of group member to be queried */
hsize_t num_objs; /* The number of objects having been traversed */
H5G_bt_find_op_t op; /* Operator to call when correct entry is found */
@@ -456,10 +455,8 @@ H5_DLL int H5G_link_cmp_name_inc(const void *lnk1, const void *lnk2);
H5_DLL int H5G_link_cmp_name_dec(const void *lnk1, const void *lnk2);
H5_DLL int H5G_link_cmp_corder_inc(const void *lnk1, const void *lnk2);
H5_DLL int H5G_link_cmp_corder_dec(const void *lnk1, const void *lnk2);
-H5_DLL herr_t H5G_ent_to_link(H5F_t *f, H5O_link_t *lnk, const H5HL_t *heap,
+H5_DLL herr_t H5G_ent_to_link(H5O_link_t *lnk, const H5HL_t *heap,
const H5G_entry_t *ent, const char *name);
-H5_DLL herr_t H5G_ent_to_info(H5F_t *f, H5L_info_t *info, const H5HL_t *heap,
- const H5G_entry_t *ent);
H5_DLL herr_t H5G_link_to_info(const H5O_link_t *lnk, H5L_info_t *linfo);
H5_DLL herr_t H5G_link_to_loc(const H5G_loc_t *grp_loc, const H5O_link_t *lnk,
H5G_loc_t *obj_loc);
diff --git a/src/H5Gstab.c b/src/H5Gstab.c
index ab40fad..7dfb5ae 100644
--- a/src/H5Gstab.c
+++ b/src/H5Gstab.c
@@ -33,7 +33,6 @@
/* User data for finding link information from B-tree */
typedef struct {
/* downward */
- H5F_t *file; /* Pointer to file for query */
const char *name; /* Name to search for */
H5HL_t *heap; /* Local heap for group */
@@ -56,6 +55,7 @@ typedef struct H5G_bt_it_gnbi_t {
typedef struct H5G_bt_it_gtbi_t {
/* downward */
H5G_bt_it_idx_common_t common; /* Common information for "by index" lookup */
+ H5F_t *f; /* Pointer to file that symbol table is in */
hid_t dxpl_id; /* DXPL for operation */
/* upward */
@@ -136,7 +136,7 @@ H5G_stab_create_components(H5F_t *f, H5O_stab_t *stab, size_t size_hint, hid_t d
done:
/* Release resources */
- if(heap && H5HL_unprotect(f, dxpl_id, heap, stab->heap_addr) < 0)
+ if(heap && H5HL_unprotect(f, heap) < 0)
HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap")
FUNC_LEAVE_NOAPI(ret_value)
@@ -250,7 +250,7 @@ H5G_stab_insert_real(H5F_t *f, H5O_stab_t *stab, const char *name,
done:
/* Release resources */
- if(heap && H5HL_unprotect(f, dxpl_id, heap, stab->heap_addr) < 0)
+ if(heap && H5HL_unprotect(f, heap) < 0)
HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap")
FUNC_LEAVE_NOAPI(ret_value)
@@ -343,7 +343,7 @@ H5G_stab_remove(H5O_loc_t *loc, hid_t dxpl_id, H5RS_str_t *grp_full_path_r,
done:
/* Release resources */
- if(heap && H5HL_unprotect(loc->file, dxpl_id, heap, stab.heap_addr) < 0)
+ if(heap && H5HL_unprotect(loc->file, heap) < 0)
HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap")
FUNC_LEAVE_NOAPI(ret_value)
@@ -401,7 +401,7 @@ H5G_stab_remove_by_idx(H5O_loc_t *grp_oloc, hid_t dxpl_id, H5RS_str_t *grp_full_
done:
/* Release resources */
- if(heap && H5HL_unprotect(grp_oloc->file, dxpl_id, heap, stab.heap_addr) < 0)
+ if(heap && H5HL_unprotect(grp_oloc->file, heap) < 0)
HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap")
/* Reset the link information, if we have a copy */
@@ -453,7 +453,7 @@ H5G_stab_delete(H5F_t *f, hid_t dxpl_id, const H5O_stab_t *stab)
HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete symbol table B-tree")
/* Release resources */
- if(H5HL_unprotect(f, dxpl_id, heap, stab->heap_addr) < 0)
+ if(H5HL_unprotect(f, heap) < 0)
HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap")
heap = NULL;
@@ -463,7 +463,7 @@ H5G_stab_delete(H5F_t *f, hid_t dxpl_id, const H5O_stab_t *stab)
done:
/* Release resources */
- if(heap && H5HL_unprotect(f, dxpl_id, heap, stab->heap_addr) < 0)
+ if(heap && H5HL_unprotect(f, heap) < 0)
HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap")
FUNC_LEAVE_NOAPI(ret_value)
@@ -553,7 +553,7 @@ H5G_stab_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, H5_iter_order_t order,
done:
/* Release resources */
- if(heap && H5HL_unprotect(oloc->file, dxpl_id, heap, stab.heap_addr) < 0)
+ if(heap && H5HL_unprotect(oloc->file, heap) < 0)
HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap")
if(ltable.lnks && H5G_link_release_table(&ltable) < 0)
HDONE_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to release link table")
@@ -677,7 +677,7 @@ H5G_stab_get_name_by_idx_cb(const H5G_entry_t *ent, void *_udata)
/* Get name offset in heap */
name_off = ent->name_off;
- name = (const char *)H5HL_offset_into(udata->common.f, udata->heap, name_off);
+ name = (const char *)H5HL_offset_into(udata->heap, name_off);
HDassert(name);
udata->name = H5MM_strdup(name);
HDassert(udata->name);
@@ -734,7 +734,6 @@ H5G_stab_get_name_by_idx(H5O_loc_t *oloc, H5_iter_order_t order, hsize_t n,
} /* end if */
/* Set iteration information */
- udata.common.f = oloc->file;
udata.common.idx = n;
udata.common.num_objs = 0;
udata.common.op = H5G_stab_get_name_by_idx_cb;
@@ -761,7 +760,7 @@ H5G_stab_get_name_by_idx(H5O_loc_t *oloc, H5_iter_order_t order, hsize_t n,
done:
/* Release resources */
- if(heap && H5HL_unprotect(oloc->file, dxpl_id, heap, stab.heap_addr) < 0)
+ if(heap && H5HL_unprotect(oloc->file, heap) < 0)
HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap")
/* Free the duplicated name */
@@ -797,7 +796,7 @@ H5G_stab_lookup_cb(const H5G_entry_t *ent, void *_udata)
/* Check for setting link info */
if(udata->lnk)
/* Convert the entry to a link */
- if(H5G_ent_to_link(udata->file, udata->lnk, udata->heap, ent, udata->name) < 0)
+ if(H5G_ent_to_link(udata->lnk, udata->heap, ent, udata->name) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTCONVERT, FAIL, "unable to convert symbol table entry to link")
done:
@@ -844,7 +843,6 @@ H5G_stab_lookup(H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk,
HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to protect symbol table heap")
/* Set up user data to pass to 'find' operation callback */
- udata.file = grp_oloc->file;
udata.name = name;
udata.lnk = lnk;
udata.heap = heap;
@@ -861,7 +859,7 @@ H5G_stab_lookup(H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk,
done:
/* Release resources */
- if(heap && H5HL_unprotect(grp_oloc->file, dxpl_id, heap, stab.heap_addr) < 0)
+ if(heap && H5HL_unprotect(grp_oloc->file, heap) < 0)
HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap")
FUNC_LEAVE_NOAPI(ret_value)
@@ -896,11 +894,11 @@ H5G_stab_lookup_by_idx_cb(const H5G_entry_t *ent, void *_udata)
HDassert(udata && udata->heap);
/* Get a pointer to the link name */
- name = (const char *)H5HL_offset_into(udata->common.f, udata->heap, ent->name_off);
+ name = (const char *)H5HL_offset_into(udata->heap, ent->name_off);
HDassert(name);
/* Convert the entry to a link */
- if(H5G_ent_to_link(udata->common.f, udata->lnk, udata->heap, ent, name) < 0)
+ if(H5G_ent_to_link(udata->lnk, udata->heap, ent, name) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTCONVERT, FAIL, "unable to convert symbol table entry to link")
udata->found = TRUE;
@@ -958,7 +956,6 @@ H5G_stab_lookup_by_idx(H5O_loc_t *grp_oloc, H5_iter_order_t order, hsize_t n,
} /* end if */
/* Set iteration information */
- udata.common.f = grp_oloc->file;
udata.common.idx = n;
udata.common.num_objs = 0;
udata.common.op = H5G_stab_lookup_by_idx_cb;
@@ -976,7 +973,7 @@ H5G_stab_lookup_by_idx(H5O_loc_t *grp_oloc, H5_iter_order_t order, hsize_t n,
done:
/* Release resources */
- if(heap && H5HL_unprotect(grp_oloc->file, dxpl_id, heap, stab.heap_addr) < 0)
+ if(heap && H5HL_unprotect(grp_oloc->file, heap) < 0)
HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap")
FUNC_LEAVE_NOAPI(ret_value)
@@ -1051,7 +1048,7 @@ H5G_stab_valid(H5O_loc_t *grp_oloc, hid_t dxpl_id, H5O_stab_t *alt_stab)
done:
/* Release resources */
- if(heap && H5HL_unprotect(grp_oloc->file, dxpl_id, heap, stab.heap_addr) < 0)
+ if(heap && H5HL_unprotect(grp_oloc->file, heap) < 0)
HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap")
FUNC_LEAVE_NOAPI(ret_value)
@@ -1098,7 +1095,7 @@ H5G_stab_get_type_by_idx_cb(const H5G_entry_t *ent, void *_udata)
H5O_type_t obj_type; /* Type of object at location */
/* Build temporary object location */
- tmp_oloc.file = udata->common.f;
+ tmp_oloc.file = udata->f;
HDassert(H5F_addr_defined(ent->header));
tmp_oloc.addr = ent->header;
@@ -1147,10 +1144,10 @@ H5G_stab_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx, hid_t dxpl_id)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5G_UNKNOWN, "unable to determine local heap address")
/* Set iteration information */
- udata.common.f = oloc->file;
udata.common.idx = idx;
udata.common.num_objs = 0;
udata.common.op = H5G_stab_get_type_by_idx_cb;
+ udata.f = oloc->file;
udata.dxpl_id = dxpl_id;
udata.type = H5G_UNKNOWN;
diff --git a/src/H5Gtest.c b/src/H5Gtest.c
index 26de267..44105cd 100644
--- a/src/H5Gtest.c
+++ b/src/H5Gtest.c
@@ -616,7 +616,7 @@ H5G_verify_cached_stab_test(H5O_loc_t *grp_oloc, H5G_entry_t *ent)
done:
/* Release resources */
- if(heap && H5HL_unprotect(grp_oloc->file, H5AC_ind_dxpl_id, heap, stab.heap_addr) < 0)
+ if(heap && H5HL_unprotect(grp_oloc->file, heap) < 0)
HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap")
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5HL.c b/src/H5HL.c
index 5951509..aa187ad 100644
--- a/src/H5HL.c
+++ b/src/H5HL.c
@@ -75,9 +75,6 @@ static herr_t H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap);
/* Declare a free list to manage the H5HL_free_t struct */
H5FL_DEFINE(H5HL_free_t);
-/* Declare a free list to manage the H5HL_t struct */
-H5FL_DEFINE(H5HL_t);
-
/* Declare a PQ free list to manage the heap chunk information */
H5FL_BLK_DEFINE(lheap_chunk);
@@ -118,8 +115,8 @@ herr_t
H5HL_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, haddr_t *addr_p/*out*/)
{
H5HL_t *heap = NULL; /* Heap created */
+ H5HL_prfx_t *prfx = NULL; /* Heap prefix */
hsize_t total_size; /* Total heap size on disk */
- size_t sizeof_hdr; /* Cache H5HL header size for file */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5HL_create, FAIL)
@@ -133,21 +130,22 @@ H5HL_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, haddr_t *addr_p/*out*/)
size_hint = H5HL_SIZEOF_FREE(f);
size_hint = H5HL_ALIGN(size_hint);
- /* Cache this for later */
- sizeof_hdr = H5HL_SIZEOF_HDR(f);
+ /* Allocate memory structure */
+ if(NULL == (heap = H5HL_new(H5F_SIZEOF_SIZE(f), H5F_SIZEOF_ADDR(f), H5HL_SIZEOF_HDR(f))))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed")
- /* Allocate file version */
- total_size = sizeof_hdr + size_hint;
- if(HADDR_UNDEF == (*addr_p = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, total_size)))
+ /* Allocate file space */
+ total_size = heap->prfx_size + size_hint;
+ if(HADDR_UNDEF == (heap->prfx_addr = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, total_size)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "unable to allocate file memory")
- /* allocate memory version */
- if(NULL == (heap = H5FL_CALLOC(H5HL_t)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed")
- heap->addr = *addr_p + (hsize_t)sizeof_hdr;
- heap->heap_alloc = size_hint;
- if(NULL == (heap->chunk = H5FL_BLK_CALLOC(lheap_chunk, (sizeof_hdr + size_hint))))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed")
+ /* Initialize info */
+ heap->single_cache_obj = TRUE;
+ heap->dblk_addr = heap->prfx_addr + (hsize_t)heap->prfx_size;
+ heap->dblk_size = size_hint;
+ if(size_hint)
+ if(NULL == (heap->dblk_image = H5FL_BLK_CALLOC(lheap_chunk, size_hint)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed")
/* free list */
if(size_hint) {
@@ -160,17 +158,32 @@ H5HL_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, haddr_t *addr_p/*out*/)
else
heap->freelist = NULL;
+ /* Allocate the heap prefix */
+ if(NULL == (prfx = H5HL_prfx_new(heap)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed")
+
/* Add to cache */
- if(H5AC_set(f, dxpl_id, H5AC_LHEAP, *addr_p, heap, H5AC__NO_FLAGS_SET) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to cache heap")
+ if(H5AC_set(f, dxpl_id, H5AC_LHEAP_PRFX, heap->prfx_addr, prfx, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to cache local heap prefix")
+
+ /* Set address to return */
+ *addr_p = heap->prfx_addr;
done:
if(ret_value < 0) {
- if(H5F_addr_defined(*addr_p))
- H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, *addr_p, total_size);
- if(heap)
- if(H5HL_dest(f, heap) < 0)
- HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap")
+ if(prfx) {
+ if(H5HL_prfx_dest(prfx) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap prefix")
+ } /* end if */
+ else {
+ if(heap) {
+ if(H5F_addr_defined(heap->prfx_addr))
+ if(H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, heap->prfx_addr, total_size) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "can't release heap data?")
+ if(H5HL_dest(heap) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap")
+ } /* end if */
+ } /* end else */
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
@@ -178,6 +191,110 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5HL_dblk_realloc
+ *
+ * Purpose: Reallocate data block for heap
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Oct 12 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HL_dblk_realloc(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t new_heap_size)
+{
+ H5HL_dblk_t *dblk; /* Local heap data block */
+ haddr_t old_addr; /* Old location of heap data block */
+ haddr_t new_addr; /* New location of heap data block */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HL_dblk_realloc)
+
+ /* check arguments */
+ HDassert(heap);
+ HDassert(new_heap_size > 0);
+
+ /* Release old space on disk */
+ old_addr = heap->dblk_addr;
+ H5_CHECK_OVERFLOW(heap->dblk_size, size_t, hsize_t);
+ if(H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, old_addr, (hsize_t)heap->dblk_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "can't release old heap data?")
+
+ /* Allocate new space on disk */
+ H5_CHECK_OVERFLOW(new_heap_size, size_t, hsize_t);
+ if(HADDR_UNDEF == (new_addr = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, (hsize_t)new_heap_size)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "unable to allocate file space for heap")
+
+ /* Check if heap data block actually moved in the file */
+ if(H5F_addr_eq(old_addr, new_addr)) {
+ /* Check if heap data block is contiguous w/prefix */
+ if(heap->single_cache_obj) {
+ /* Sanity check */
+ HDassert(H5F_addr_eq(heap->prfx_addr + heap->prfx_size, heap->dblk_addr));
+ HDassert(heap->prfx);
+
+ /* Resize the heap prefix in the cache */
+ if(H5AC_resize_pinned_entry(f, heap->prfx, (size_t)(heap->prfx_size + new_heap_size)) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, FAIL, "unable to resize heap in cache")
+ } /* end if */
+ else {
+ /* Sanity check */
+ HDassert(H5F_addr_ne(heap->prfx_addr + heap->prfx_size, heap->dblk_addr));
+ HDassert(heap->dblk);
+
+ /* Resize the heap data block in the cache */
+ if(H5AC_resize_pinned_entry(f, heap->dblk, (size_t)new_heap_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, FAIL, "unable to resize heap in cache")
+ } /* end else */
+ } /* end if */
+ else {
+ /* Check if heap data block was contiguous w/prefix previously */
+ if(heap->single_cache_obj) {
+ /* Create new heap data block */
+ if(NULL == (dblk = H5HL_dblk_new(heap)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "unable to allocate local heap data block")
+
+ /* Resize current heap prefix */
+ heap->prfx_size = H5HL_SIZEOF_HDR(f);
+ if(H5AC_resize_pinned_entry(f, heap->prfx, (size_t)heap->prfx_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, FAIL, "unable to resize heap prefix in cache")
+
+ /* Insert data block into cache (pinned) */
+ if(H5AC_set(f, dxpl_id, H5AC_LHEAP_DBLK, new_addr, dblk, H5AC__PIN_ENTRY_FLAG) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to cache local heap data block")
+ dblk = NULL;
+
+ /* Reset 'single cache object' flag */
+ heap->single_cache_obj = FALSE;
+ } /* end if */
+ else {
+ /* Resize the heap data block in the cache */
+ /* (ignore [unlikely] case where heap data block ends up
+ * contiguous w/heap prefix again.
+ */
+ if(H5AC_resize_pinned_entry(f, heap->dblk, (size_t)new_heap_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, FAIL, "unable to resize heap data block in cache")
+
+ /* Relocate the heap data block in the cache */
+ if(H5AC_rename(f, H5AC_LHEAP_DBLK, old_addr, new_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRENAME, FAIL, "unable to move heap data block in cache")
+ } /* end else */
+ } /* end else */
+
+ /* Update heap info*/
+ heap->dblk_addr = new_addr;
+ heap->dblk_size = new_heap_size;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HL_dblk_realloc() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5HL_minimize_heap_space
*
* Purpose: Go through the heap's freelist and determine if we can
@@ -195,8 +312,7 @@ done:
static herr_t
H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap)
{
- size_t new_heap_size = heap->heap_alloc; /* New size of heap */
- size_t sizeof_hdr;
+ size_t new_heap_size = heap->dblk_size; /* New size of heap */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5HL_minimize_heap_space, FAIL)
@@ -205,8 +321,6 @@ H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap)
HDassert(f);
HDassert(heap);
- sizeof_hdr = H5HL_SIZEOF_HDR(f); /* cache H5HL header size for file */
-
/*
* Check to see if we can reduce the size of the heap in memory by
* eliminating free blocks at the tail of the buffer before flushing the
@@ -219,7 +333,7 @@ H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap)
/* Search for a free block at the end of the buffer */
for(tmp_fl = heap->freelist; tmp_fl; tmp_fl = tmp_fl->next)
/* Check if the end of this free block is at the end of the buffer */
- if(tmp_fl->offset + tmp_fl->size == heap->heap_alloc) {
+ if(tmp_fl->offset + tmp_fl->size == heap->dblk_size) {
last_fl = tmp_fl;
break;
} /* end if */
@@ -234,7 +348,7 @@ H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap)
* buffer size (and the memory buffer is larger than the
* minimum size), reduce or eliminate it.
*/
- if(last_fl->size >= (heap->heap_alloc / 2) && heap->heap_alloc > H5HL_MIN_HEAP) {
+ if(last_fl->size >= (heap->dblk_size / 2) && heap->dblk_size > H5HL_MIN_HEAP) {
/*
* Reduce size of buffer until it's too small or would
* eliminate the free block
@@ -285,30 +399,16 @@ H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap)
* data segment of the heap to another contiguous block of disk
* storage.
*/
- if(new_heap_size != heap->heap_alloc) {
- haddr_t old_addr = heap->addr,
- new_addr;
-
- HDassert(new_heap_size < heap->heap_alloc);
+ if(new_heap_size != heap->dblk_size) {
+ HDassert(new_heap_size < heap->dblk_size);
/* Resize the memory buffer */
- if(NULL == (heap->chunk = H5FL_BLK_REALLOC(lheap_chunk, heap->chunk, (sizeof_hdr + new_heap_size))))
+ if(NULL == (heap->dblk_image = H5FL_BLK_REALLOC(lheap_chunk, heap->dblk_image, new_heap_size)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed")
- /* Release old space on disk */
- /* (Should be safe to free old heap space first, since it's shrinking -QAK) */
- H5_CHECK_OVERFLOW(heap->heap_alloc, size_t, hsize_t);
- if(H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, old_addr, (hsize_t)heap->heap_alloc) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap")
-
- /* Allocate new space on disk */
- H5_CHECK_OVERFLOW(new_heap_size, size_t, hsize_t);
- if(HADDR_UNDEF == (new_addr = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, (hsize_t)new_heap_size)))
+ /* Reallocate data block in file */
+ if(H5HL_dblk_realloc(f, dxpl_id, heap, new_heap_size) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, FAIL, "reallocating data block failed")
-
- /* Update heap info*/
- heap->addr = new_addr;
- heap->heap_alloc = new_heap_size;
} /* end if */
done:
@@ -319,26 +419,9 @@ done:
/*-------------------------------------------------------------------------
* Function: H5HL_protect
*
- * Purpose: This function is a wrapper for the H5AC_protect call. The
- * old H5HL_peek call (which this once was) wasn't "safe"
- * for FPHDF5. (It'd get a read lock on an object but once
- * it got that object, it'd release it keeping the old
- * pointer value, which is no longer valid. This won't work
- * since the pointer into some metdata block can become
- * invalid.)
- *
- * N.B.: This function is always called in conjunction with
- * the H5HL_offset_into function. The return from that
- * function is the proper pointer to the heap's object. This
- * is done so that the return from this function can be sent
- * to H5HL_unprotect.
- *
- * Return: Success: Ptr to the object. The pointer points to a
- * chunk of memory large enough to hold the
- * object from the specified offset (usually the
- * beginning of the object) to the end of the
- * object. Do not attempt to read past the end
- * of the object.
+ * Purpose: This function is a wrapper for the H5AC_protect call.
+ *
+ * Return: Success: Non-NULL pointer to the local heap prefix.
* Failure: NULL
*
* Programmer: Bill Wendling
@@ -350,7 +433,13 @@ done:
H5HL_t *
H5HL_protect(H5F_t *f, hid_t dxpl_id, haddr_t addr, H5AC_protect_t rw)
{
- H5HL_t *ret_value;
+ H5HL_cache_prfx_ud_t prfx_udata; /* User data for protecting local heap prefix */
+ H5HL_prfx_t *prfx = NULL; /* Local heap prefix */
+ H5HL_dblk_t *dblk = NULL; /* Local heap data block */
+ H5HL_t *heap; /* Heap data structure */
+ unsigned prfx_cache_flags = H5AC__NO_FLAGS_SET; /* Cache flags for unprotecting prefix entry */
+ unsigned dblk_cache_flags = H5AC__NO_FLAGS_SET; /* Cache flags for unprotecting data block entry */
+ H5HL_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5HL_protect, NULL)
@@ -358,10 +447,65 @@ H5HL_protect(H5F_t *f, hid_t dxpl_id, haddr_t addr, H5AC_protect_t rw)
HDassert(f);
HDassert(H5F_addr_defined(addr));
- if(NULL == (ret_value = (H5HL_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, rw)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to load heap")
+ /* Construct the user data for protect callback */
+ prfx_udata.sizeof_size = H5F_SIZEOF_SIZE(f);
+ prfx_udata.sizeof_addr = H5F_SIZEOF_ADDR(f);
+ prfx_udata.sizeof_prfx = H5HL_SIZEOF_HDR(f);
+ prfx_udata.loaded = FALSE;
+ prfx_udata.free_block = H5HL_FREE_NULL;
+
+ /* Protect the local heap prefix */
+ if(NULL == (prfx = (H5HL_prfx_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP_PRFX, addr, NULL, &prfx_udata, rw)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to load heap prefix")
+
+ /* Get the pointer to the heap */
+ heap = prfx->heap;
+
+ /* Check if the heap is already pinned in memory */
+ /* (for re-entrant situation) */
+ if(heap->prots == 0) {
+ /* Check if heap has separate data block */
+ if(heap->single_cache_obj) {
+ /* Set the flag for pinning the prefix when unprotecting it */
+ prfx_cache_flags |= H5AC__PIN_ENTRY_FLAG;
+ } /* end if */
+ else {
+ H5HL_cache_dblk_ud_t dblk_udata; /* User data for protecting local heap data block */
+
+ /* Construct the user data for protect callback */
+ dblk_udata.heap = heap;
+ dblk_udata.free_block = prfx_udata.loaded ? prfx_udata.free_block :
+ (heap->freelist ? heap->freelist->offset : H5HL_FREE_NULL);
+ dblk_udata.loaded = FALSE;
+
+ /* Protect the local heap data block */
+ if(NULL == (dblk = (H5HL_dblk_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP_DBLK, heap->dblk_addr, NULL, &dblk_udata, rw)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to load heap data block")
+
+ /* Pin the prefix, if the data block was loaded from file */
+ if(dblk_udata.loaded)
+ prfx_cache_flags |= H5AC__PIN_ENTRY_FLAG;
+
+ /* Set the flag for pinning the data block when unprotecting it */
+ dblk_cache_flags |= H5AC__PIN_ENTRY_FLAG;
+ } /* end if */
+ } /* end if */
+
+ /* Increment # of times heap is protected */
+ heap->prots++;
+
+ /* Set return value */
+ ret_value = heap;
done:
+ /* Release the prefix from the cache, now pinned */
+ if(prfx && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP_PRFX, heap->prfx_addr, prfx, prfx_cache_flags) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, NULL, "unable to release local heap prefix")
+
+ /* Release the data block from the cache, now pinned */
+ if(dblk && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP_DBLK, heap->dblk_addr, dblk, dblk_cache_flags) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, NULL, "unable to release local heap data block")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HL_protect() */
@@ -382,7 +526,7 @@ done:
*-------------------------------------------------------------------------
*/
void *
-H5HL_offset_into(H5F_t *f, const H5HL_t *heap, size_t offset)
+H5HL_offset_into(const H5HL_t *heap, size_t offset)
{
/*
* We need to have called some other function before this to get a
@@ -390,11 +534,11 @@ H5HL_offset_into(H5F_t *f, const H5HL_t *heap, size_t offset)
*/
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_offset_into)
- HDassert(f);
+ /* Sanity check */
HDassert(heap);
- HDassert(offset < heap->heap_alloc);
+ HDassert(offset < heap->dblk_size);
- FUNC_LEAVE_NOAPI(heap->chunk + H5HL_SIZEOF_HDR(f) + offset)
+ FUNC_LEAVE_NOAPI(heap->dblk_image + offset)
} /* end H5HL_offset_into() */
@@ -413,7 +557,7 @@ H5HL_offset_into(H5F_t *f, const H5HL_t *heap, size_t offset)
*-------------------------------------------------------------------------
*/
herr_t
-H5HL_unprotect(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, haddr_t addr)
+H5HL_unprotect(H5F_t *f, H5HL_t *heap)
{
herr_t ret_value = SUCCEED;
@@ -422,10 +566,28 @@ H5HL_unprotect(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, haddr_t addr)
/* check arguments */
HDassert(f);
HDassert(heap);
- HDassert(H5F_addr_defined(addr));
- if(H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, (void *)heap, H5AC__NO_FLAGS_SET) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release local heap")
+ /* Decrement # of times heap is protected */
+ heap->prots--;
+
+ /* Check for last unprotection of heap */
+ if(heap->prots == 0) {
+ /* Check for separate heap data block */
+ if(heap->single_cache_obj) {
+ /* Mark local heap prefix as evictable again */
+ if(H5AC_unpin_entry(f, heap->prfx) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPIN, FAIL, "unable to unpin local heap data block")
+ } /* end if */
+ else {
+ /* Sanity check */
+ HDassert(heap->dblk);
+
+ /* Mark local heap data block as evictable again */
+ /* (data block still pins prefix) */
+ if(H5AC_unpin_entry(f, heap->dblk) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPIN, FAIL, "unable to unpin local heap data block")
+ } /* end else */
+ } /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -464,12 +626,55 @@ H5HL_remove_free(H5HL_t *heap, H5HL_free_t *fl)
/*-------------------------------------------------------------------------
+ * Function: H5HL_dirty
+ *
+ * Purpose: Mark heap as dirty
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Oct 12 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HL_dirty(H5F_t *f, H5HL_t *heap)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HL_dirty)
+
+ /* check arguments */
+ HDassert(f);
+ HDassert(heap);
+ HDassert(heap->prfx);
+
+ /* Mark heap data block as dirty, if there is one */
+ if(!heap->single_cache_obj) {
+ /* Sanity check */
+ HDassert(heap->dblk);
+
+ if(H5AC_mark_pinned_or_protected_entry_dirty(f, heap->dblk) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTMARKDIRTY, FAIL, "unable to mark heap data block as dirty")
+ } /* end if */
+
+ /* Mark heap prefix as dirty */
+ if(H5AC_mark_pinned_or_protected_entry_dirty(f, heap->prfx) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTMARKDIRTY, FAIL, "unable to mark heap prefix as dirty")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HL_dirty() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5HL_insert
*
* Purpose: Inserts a new item into the heap.
*
* Return: Success: Offset of new item within heap.
- *
* Failure: UFAIL
*
* Programmer: Robb Matzke
@@ -485,7 +690,6 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t buf_size, const void *
size_t offset = 0;
size_t need_size;
hbool_t found;
- size_t sizeof_hdr; /* Cache H5HL header size for file */
size_t ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5HL_insert, UFAIL)
@@ -502,12 +706,9 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t buf_size, const void *
* so we just accept that an extra flush of the heap info could occur
* if an error occurs -QAK)
*/
- if(H5AC_mark_pinned_or_protected_entry_dirty(f, heap) < 0)
+ if(H5HL_dirty(f, heap) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTMARKDIRTY, UFAIL, "unable to mark heap as dirty")
- /* Cache this for later */
- sizeof_hdr = H5HL_SIZEOF_HDR(f);
-
/*
* In order to keep the free list descriptors aligned on word boundaries,
* whatever that might mean, we round the size up to the next multiple of
@@ -550,12 +751,13 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t buf_size, const void *
*/
if(found == FALSE) {
size_t need_more; /* How much more space we need */
- size_t new_heap_alloc; /* Final size of space allocated for heap */
+ size_t new_dblk_size; /* Final size of space allocated for heap data block */
+ size_t old_dblk_size; /* Previous size of space allocated for heap data block */
htri_t extended; /* Whether the local heap's data segment on disk was extended */
/* At least double the heap's size, making certain there's enough room
* for the new object */
- need_more = MAX(need_size, heap->heap_alloc);
+ need_more = MAX(need_size, heap->dblk_size);
/* If there is no last free block or it's not at the end of the heap,
* and the amount of space to allocate is not big enough to include at
@@ -563,33 +765,46 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t buf_size, const void *
* space requested to just the amount of space needed. (Generally
* speaking, this only occurs when the heap is small -QAK)
*/
- if(!(last_fl && last_fl->offset + last_fl->size == heap->heap_alloc)
+ if(!(last_fl && last_fl->offset + last_fl->size == heap->dblk_size)
&& (need_more < (need_size + H5HL_SIZEOF_FREE(f))))
need_more = need_size;
- new_heap_alloc = heap->heap_alloc + need_more;
- HDassert(heap->heap_alloc < new_heap_alloc);
- H5_CHECK_OVERFLOW(heap->heap_alloc, size_t, hsize_t);
- H5_CHECK_OVERFLOW(new_heap_alloc, size_t, hsize_t);
+ new_dblk_size = heap->dblk_size + need_more;
+ HDassert(heap->dblk_size < new_dblk_size);
+ old_dblk_size = heap->dblk_size;
+ H5_CHECK_OVERFLOW(heap->dblk_size, size_t, hsize_t);
+ H5_CHECK_OVERFLOW(new_dblk_size, size_t, hsize_t);
/* Extend current heap if possible */
- extended = H5MF_try_extend(f, dxpl_id, H5FD_MEM_LHEAP, heap->addr, (hsize_t)(heap->heap_alloc), (hsize_t)need_more);
+ extended = H5MF_try_extend(f, dxpl_id, H5FD_MEM_LHEAP, heap->dblk_addr, (hsize_t)(heap->dblk_size), (hsize_t)need_more);
if(extended < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, UFAIL, "error trying to extend heap")
- /* If we couldn't extend the heap, release old chunk and allocate a new one */
- if(extended == FALSE) {
- /* Release old space on disk */
- if(H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, heap->addr, (hsize_t)heap->heap_alloc) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, UFAIL, "unable to free local heap")
-
- /* allocate new disk space for the heap */
- if((heap->addr = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, (hsize_t)new_heap_alloc)) == HADDR_UNDEF)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, UFAIL, "unable to allocate file space for heap")
+ /* Check if we extended the heap data block in file */
+ if(extended == TRUE) {
+ /* Check for prefix & data block contiguous */
+ if(heap->single_cache_obj) {
+ /* Resize prefix+data block */
+ if(H5AC_resize_pinned_entry(f, heap->prfx, (size_t)(heap->prfx_size + new_dblk_size)) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, UFAIL, "unable to resize heap prefix in cache")
+ } /* end if */
+ else {
+ /* Resize 'standalone' data block */
+ if(H5AC_resize_pinned_entry(f, heap->dblk, (size_t)new_dblk_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, UFAIL, "unable to resize heap data block in cache")
+ } /* end else */
+
+ /* Note new size */
+ heap->dblk_size = new_dblk_size;
+ } /* end if */
+ else { /* ...if we can't, allocate a new chunk & release the old */
+ /* Reallocate data block in file */
+ if(H5HL_dblk_realloc(f, dxpl_id, heap, new_dblk_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, UFAIL, "reallocating data block failed")
} /* end if */
/* If the last free list in the heap is at the end of the heap, extend it */
- if(last_fl && last_fl->offset + last_fl->size == heap->heap_alloc) {
+ if(last_fl && last_fl->offset + last_fl->size == old_dblk_size) {
/*
* Increase the size of the last free block.
*/
@@ -614,11 +829,11 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t buf_size, const void *
* Create a new free list element large enough that we can
* take some space out of it right away.
*/
- offset = heap->heap_alloc;
+ offset = old_dblk_size;
if(need_more - need_size >= H5HL_SIZEOF_FREE(f)) {
if(NULL == (fl = H5FL_MALLOC(H5HL_free_t)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, UFAIL, "memory allocation failed")
- fl->offset = heap->heap_alloc + need_size;
+ fl->offset = old_dblk_size + need_size;
fl->size = need_more - need_size;
HDassert(fl->offset == H5HL_ALIGN(fl->offset));
HDassert(fl->size == H5HL_ALIGN(fl->size));
@@ -640,21 +855,20 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t buf_size, const void *
if (H5DEBUG(HL)) {
fprintf(H5DEBUG(HL),
"H5HL: resize mem buf from %lu to %lu bytes\n",
- (unsigned long)(heap->heap_alloc),
- (unsigned long)(heap->heap_alloc + need_more));
+ (unsigned long)(old_dblk_size),
+ (unsigned long)(old_dblk_size + need_more));
}
#endif
- heap->heap_alloc = new_heap_alloc;
- if(NULL == (heap->chunk = H5FL_BLK_REALLOC(lheap_chunk, heap->chunk, (sizeof_hdr + heap->heap_alloc))))
+ if(NULL == (heap->dblk_image = H5FL_BLK_REALLOC(lheap_chunk, heap->dblk_image, heap->dblk_size)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, UFAIL, "memory allocation failed")
/* Clear new section so junk doesn't appear in the file */
/* (Avoid clearing section which will be overwritten with newly inserted data) */
- HDmemset(heap->chunk + sizeof_hdr + offset + buf_size, 0, (new_heap_alloc - (offset + buf_size)));
+ HDmemset(heap->dblk_image + offset + buf_size, 0, (new_dblk_size - (offset + buf_size)));
} /* end if */
/* Copy the data into the heap */
- HDmemcpy(heap->chunk + sizeof_hdr + offset, buf, buf_size);
+ HDmemcpy(heap->dblk_image + offset, buf, buf_size);
/* Set return value */
ret_value = offset;
@@ -704,8 +918,8 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size)
size = H5HL_ALIGN(size);
- HDassert(offset < heap->heap_alloc);
- HDassert(offset + size <= heap->heap_alloc);
+ HDassert(offset < heap->dblk_size);
+ HDassert(offset + size <= heap->dblk_size);
/* Mark heap as dirty in cache */
/* (A bit early in the process, but it's difficult to determine in the
@@ -713,7 +927,7 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size)
* so we just accept that an extra flush of the heap info could occur
* if an error occurs -QAK)
*/
- if(H5AC_mark_pinned_or_protected_entry_dirty(f, heap) < 0)
+ if(H5HL_dirty(f, heap) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTMARKDIRTY, FAIL, "unable to mark heap as dirty")
/*
@@ -738,8 +952,8 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size)
HDassert(fl->offset == H5HL_ALIGN(fl->offset));
HDassert(fl->size == H5HL_ALIGN(fl->size));
fl2 = H5HL_remove_free(heap, fl2);
- if(((fl->offset + fl->size) == heap->heap_alloc ) &&
- ((2 * fl->size) > heap->heap_alloc )) {
+ if(((fl->offset + fl->size) == heap->dblk_size) &&
+ ((2 * fl->size) > heap->dblk_size)) {
if(H5HL_minimize_heap_space(f, dxpl_id, heap) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "heap size minimization failed")
}
@@ -747,8 +961,8 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size)
}
fl2 = fl2->next;
}
- if(((fl->offset + fl->size) == heap->heap_alloc) &&
- ((2 * fl->size) > heap->heap_alloc)) {
+ if(((fl->offset + fl->size) == heap->dblk_size) &&
+ ((2 * fl->size) > heap->dblk_size)) {
if(H5HL_minimize_heap_space(f, dxpl_id, heap) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "heap size minimization failed")
}
@@ -762,8 +976,8 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size)
fl->size += fl2->size;
HDassert(fl->size == H5HL_ALIGN(fl->size));
fl2 = H5HL_remove_free(heap, fl2);
- if(((fl->offset + fl->size) == heap->heap_alloc) &&
- ((2 * fl->size) > heap->heap_alloc)) {
+ if(((fl->offset + fl->size) == heap->dblk_size) &&
+ ((2 * fl->size) > heap->dblk_size)) {
if(H5HL_minimize_heap_space(f, dxpl_id, heap) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "heap size minimization failed")
} /* end if */
@@ -771,8 +985,8 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size)
} /* end if */
fl2 = fl2->next;
} /* end while */
- if(((fl->offset + fl->size) == heap->heap_alloc) &&
- ((2 * fl->size) > heap->heap_alloc)) {
+ if(((fl->offset + fl->size) == heap->dblk_size) &&
+ ((2 * fl->size) > heap->dblk_size)) {
if(H5HL_minimize_heap_space(f, dxpl_id, heap) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "heap size minimization failed")
} /* end if */
@@ -811,8 +1025,8 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size)
heap->freelist->prev = fl;
heap->freelist = fl;
- if(((fl->offset + fl->size) == heap->heap_alloc) &&
- ((2 * fl->size) > heap->heap_alloc)) {
+ if(((fl->offset + fl->size) == heap->dblk_size) &&
+ ((2 * fl->size) > heap->dblk_size)) {
if(H5HL_minimize_heap_space(f, dxpl_id, heap) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "heap size minimization failed")
} /* end if */
@@ -838,9 +1052,12 @@ done:
herr_t
H5HL_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr)
{
- H5HL_t *heap = NULL; /* Local heap to delete */
+ H5HL_t *heap; /* Local heap to delete */
+ H5HL_cache_prfx_ud_t prfx_udata; /* User data for protecting local heap prefix */
+ H5HL_prfx_t *prfx = NULL; /* Local heap prefix */
+ H5HL_dblk_t *dblk = NULL; /* Local heap data block */
unsigned cache_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting heap */
- herr_t ret_value = SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5HL_delete, FAIL)
@@ -848,16 +1065,71 @@ H5HL_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr)
HDassert(f);
HDassert(H5F_addr_defined(addr));
- /* Get heap pointer */
- if(NULL == (heap = (H5HL_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_WRITE)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load heap")
+ /* Construct the user data for protect callback */
+ prfx_udata.sizeof_size = H5F_SIZEOF_SIZE(f);
+ prfx_udata.sizeof_addr = H5F_SIZEOF_ADDR(f);
+ prfx_udata.sizeof_prfx = H5HL_SIZEOF_HDR(f);
+ prfx_udata.loaded = FALSE;
+ prfx_udata.free_block = H5HL_FREE_NULL;
+
+ /* Protect the local heap prefix */
+ if(NULL == (prfx = (H5HL_prfx_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP_PRFX, addr, NULL, &prfx_udata, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load heap prefix")
+
+ /* Get the pointer to the heap */
+ heap = prfx->heap;
+
+ /* Check if heap has separate data block */
+ if(!heap->single_cache_obj) {
+ H5HL_cache_dblk_ud_t dblk_udata; /* User data for protecting local heap data block */
+
+ /* Construct the user data for protect callback */
+ dblk_udata.heap = heap;
+ dblk_udata.free_block = prfx_udata.loaded ? prfx_udata.free_block :
+ (heap->freelist ? heap->freelist->offset : H5HL_FREE_NULL);
+ dblk_udata.loaded = FALSE;
+
+ /* Protect the local heap data block */
+ if(NULL == (dblk = (H5HL_dblk_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP_DBLK, heap->dblk_addr, NULL, &dblk_udata, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load heap data block")
+
+ /* Pin the prefix, if the data block was loaded from file */
+ if(dblk_udata.loaded) {
+ if(H5AC_pin_protected_entry(f, prfx) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPIN, FAIL, "unable to pin local heap prefix")
+ } /* end if */
+ } /* end if */
- /* Set the cache flags to delete the heap & free its file space */
+ /* Check if the heap is contiguous on disk */
+ if(heap->single_cache_obj) {
+ /* Free the contiguous local heap in one call */
+ H5_CHECK_OVERFLOW(heap->prfx_size + heap->dblk_size, size_t, hsize_t);
+ if(H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, addr, (hsize_t)(heap->prfx_size + heap->dblk_size)) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free contiguous local heap")
+ } /* end if */
+ else {
+ /* Free the local heap's prefix */
+ H5_CHECK_OVERFLOW(heap->prfx_size, size_t, hsize_t);
+ if(H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, heap->prfx_addr, (hsize_t)heap->prfx_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap header")
+
+ /* Free the local heap's data block */
+ H5_CHECK_OVERFLOW(heap->dblk_size, size_t, hsize_t);
+ if(H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, heap->dblk_addr, (hsize_t)heap->dblk_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap data")
+ } /* end else */
+
+ /* Set the flags for releasing the prefix and data block */
cache_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
done:
- if(heap && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, heap, cache_flags) < 0)
- HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release local heap")
+ /* Release the data block from the cache, now deleted */
+ if(dblk && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP_DBLK, heap->dblk_addr, dblk, cache_flags) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release local heap data block")
+
+ /* Release the prefix from the cache, now deleted */
+ if(prfx && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP_PRFX, heap->prfx_addr, prfx, cache_flags) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release local heap prefix")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HL_delete() */
@@ -879,7 +1151,9 @@ done:
herr_t
H5HL_get_size(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t *size)
{
- H5HL_t *heap = NULL; /* Heap to query */
+ H5HL_cache_prfx_ud_t prfx_udata; /* User data for protecting local heap prefix */
+ H5HL_prfx_t *prfx = NULL; /* Local heap prefix */
+ H5HL_t *heap; /* Heap data structure */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5HL_get_size, FAIL)
@@ -889,16 +1163,26 @@ H5HL_get_size(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t *size)
HDassert(H5F_addr_defined(addr));
HDassert(size);
- /* Get heap pointer */
- if(NULL == (heap = (H5HL_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_READ)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load heap")
+ /* Construct the user data for protect callback */
+ prfx_udata.sizeof_size = H5F_SIZEOF_SIZE(f);
+ prfx_udata.sizeof_addr = H5F_SIZEOF_ADDR(f);
+ prfx_udata.sizeof_prfx = H5HL_SIZEOF_HDR(f);
+ prfx_udata.loaded = FALSE;
+ prfx_udata.free_block = H5HL_FREE_NULL;
+
+ /* Protect the local heap prefix */
+ if(NULL == (prfx = (H5HL_prfx_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP_PRFX, addr, NULL, &prfx_udata, H5AC_READ)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load heap prefix")
+
+ /* Get the pointer to the heap */
+ heap = prfx->heap;
/* Set the size to return */
- *size = heap->heap_alloc;
+ *size = heap->dblk_size;
done:
- if(heap && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, heap, H5AC__NO_FLAGS_SET) < 0)
- HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release local heap")
+ if(prfx && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP_PRFX, heap->prfx_addr, prfx, H5AC__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release local heap prefix")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HL_get_size() */
@@ -920,8 +1204,9 @@ done:
herr_t
H5HL_heapsize(H5F_t *f, hid_t dxpl_id, haddr_t addr, hsize_t *heap_size)
{
- H5HL_t *heap = NULL; /* Heap to query */
- size_t local_heap_size = 0;
+ H5HL_cache_prfx_ud_t prfx_udata; /* User data for protecting local heap prefix */
+ H5HL_prfx_t *prfx = NULL; /* Local heap prefix */
+ H5HL_t *heap; /* Heap data structure */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5HL_heapsize, FAIL)
@@ -931,20 +1216,26 @@ H5HL_heapsize(H5F_t *f, hid_t dxpl_id, haddr_t addr, hsize_t *heap_size)
HDassert(H5F_addr_defined(addr));
HDassert(heap_size);
- /* Get heap pointer */
- if(NULL == (heap = (H5HL_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_READ)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load heap")
+ /* Construct the user data for protect callback */
+ prfx_udata.sizeof_size = H5F_SIZEOF_SIZE(f);
+ prfx_udata.sizeof_addr = H5F_SIZEOF_ADDR(f);
+ prfx_udata.sizeof_prfx = H5HL_SIZEOF_HDR(f);
+ prfx_udata.loaded = FALSE;
+ prfx_udata.free_block = H5HL_FREE_NULL;
+
+ /* Protect the local heap prefix */
+ if(NULL == (prfx = (H5HL_prfx_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP_PRFX, addr, NULL, &prfx_udata, H5AC_READ)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load heap prefix")
- /* Get the total size of the local heap */
- if(H5HL_size(f, heap, &local_heap_size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to compute size of local heap")
+ /* Get the pointer to the heap */
+ heap = prfx->heap;
/* Accumulate the size of the local heap */
- *heap_size += (hsize_t)local_heap_size;
+ *heap_size += (hsize_t)(heap->prfx_size + heap->dblk_size);
done:
- if(heap && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, heap, H5AC__NO_FLAGS_SET) < 0)
- HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release local heap")
+ if(prfx && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP_PRFX, heap->prfx_addr, prfx, H5AC__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release local heap prefix")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HL_heapsize() */
diff --git a/src/H5HLcache.c b/src/H5HLcache.c
index 8f617f7..a26477a 100644
--- a/src/H5HLcache.c
+++ b/src/H5HLcache.c
@@ -38,6 +38,7 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5HLpkg.h" /* Local Heaps */
#include "H5MFprivate.h" /* File memory management */
+#include "H5WBprivate.h" /* Wrapped Buffers */
/****************/
@@ -45,7 +46,12 @@
/****************/
#define H5HL_VERSION 0 /* Local heap collection version */
-#define H5HL_FREE_NULL 1 /* End of free list on disk */
+
+/* Set the local heap size to speculatively read in */
+/* (needs to be more than the local heap prefix size to work at all and
+ * should be larger than the default local heap size to save the
+ * extra I/O operations) */
+#define H5HL_SPEC_READ_SIZE 512
/******************/
@@ -62,14 +68,21 @@
/* Local Prototypes */
/********************/
-/* Local encode/decode routines */
-static herr_t H5HL_serialize(H5F_t *f, H5HL_t *heap, uint8_t *buf);
-
/* Metadata cache callbacks */
-static H5HL_t *H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1,
- void *udata2);
-static herr_t H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, H5HL_t *heap, unsigned UNUSED * flags_ptr);
-static herr_t H5HL_clear(H5F_t *f, H5HL_t *heap, hbool_t destroy);
+static void *H5HL_prefix_load(H5F_t *f, hid_t dxpl_id, haddr_t addr,
+ const void *udata1, void *udata2);
+static herr_t H5HL_prefix_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr,
+ void *thing, unsigned *flags_ptr);
+static herr_t H5HL_prefix_dest(H5F_t *f, void *thing);
+static herr_t H5HL_prefix_clear(H5F_t *f, void *thing, hbool_t destroy);
+static herr_t H5HL_prefix_size(const H5F_t *f, const void *thing, size_t *size_ptr);
+static void *H5HL_datablock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr,
+ const void *udata1, void *udata2);
+static herr_t H5HL_datablock_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr,
+ void *thing, unsigned *flags_ptr);
+static herr_t H5HL_datablock_dest(H5F_t *f, void *thing);
+static herr_t H5HL_datablock_clear(H5F_t *f, void *thing, hbool_t destroy);
+static herr_t H5HL_datablock_size(const H5F_t *f, const void *thing, size_t *size_ptr);
/*********************/
@@ -77,14 +90,24 @@ static herr_t H5HL_clear(H5F_t *f, H5HL_t *heap, hbool_t destroy);
/*********************/
/* H5HL inherits cache-like properties from H5AC */
-const H5AC_class_t H5AC_LHEAP[1] = {{
- H5AC_LHEAP_ID,
- (H5AC_load_func_t)H5HL_load,
- (H5AC_flush_func_t)H5HL_flush,
- (H5AC_dest_func_t)H5HL_dest,
- (H5AC_clear_func_t)H5HL_clear,
- (H5AC_notify_func_t)NULL,
- (H5AC_size_func_t)H5HL_size,
+const H5AC_class_t H5AC_LHEAP_PRFX[1] = {{
+ H5AC_LHEAP_PRFX_ID,
+ H5HL_prefix_load,
+ H5HL_prefix_flush,
+ H5HL_prefix_dest,
+ H5HL_prefix_clear,
+ NULL,
+ H5HL_prefix_size,
+}};
+
+const H5AC_class_t H5AC_LHEAP_DBLK[1] = {{
+ H5AC_LHEAP_DBLK_ID,
+ H5HL_datablock_load,
+ H5HL_datablock_flush,
+ H5HL_datablock_dest,
+ H5HL_datablock_clear,
+ NULL,
+ H5HL_datablock_size,
}};
@@ -100,72 +123,117 @@ const H5AC_class_t H5AC_LHEAP[1] = {{
/*-------------------------------------------------------------------------
- * Function: H5HL_serialize
+ * Function: H5HL_fl_deserialize
*
- * Purpose: Serialize the heap. This function will eliminate free
- * blocks at the tail of the heap and also split the block
- * if it needs to be split for the file. This is so that we
- * can serialize it correctly.
+ * Purpose: Deserialize the free list for a heap data block
*
* Return: Non-negative on success/Negative on failure
*
- * Programmer: Bill Wendling
- * wendling@ncsa.uiuc.edu
- * Sept. 16, 2003
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Oct 12 2008
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5HL_serialize(H5F_t *f, H5HL_t *heap, uint8_t *buf)
+H5HL_fl_deserialize(H5HL_t *heap, hsize_t free_block)
{
- H5HL_free_t *fl;
- uint8_t *p;
- herr_t ret_value = SUCCEED;
+ H5HL_free_t *fl, *tail = NULL; /* Heap free block nodes */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HL_fl_deserialize)
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_serialize)
+ /* check arguments */
+ HDassert(heap);
- /* check args */
- assert(buf);
- assert(heap);
+ /* Build free list */
+ while(H5HL_FREE_NULL != free_block) {
+ const uint8_t *p; /* Pointer into image buffer */
- /* serialize the header */
- p = buf;
- fl = heap->freelist;
- HDmemcpy(p, H5HL_MAGIC, (size_t)H5_SIZEOF_MAGIC);
- p += H5_SIZEOF_MAGIC;
- *p++ = H5HL_VERSION;
- *p++ = 0; /*reserved*/
- *p++ = 0; /*reserved*/
- *p++ = 0; /*reserved*/
- H5F_ENCODE_LENGTH(f, p, heap->heap_alloc);
- H5F_ENCODE_LENGTH(f, p, fl ? fl->offset : H5HL_FREE_NULL);
- H5F_addr_encode(f, &p, heap->addr);
-
- /* serialize the free list */
- for (; fl; fl = fl->next) {
- assert (fl->offset == H5HL_ALIGN (fl->offset));
- p = heap->chunk + H5HL_SIZEOF_HDR(f) + fl->offset;
-
- if (fl->next) {
- H5F_ENCODE_LENGTH(f, p, fl->next->offset);
- } else {
- H5F_ENCODE_LENGTH(f, p, H5HL_FREE_NULL);
- }
-
- H5F_ENCODE_LENGTH(f, p, fl->size);
- }
+ /* Sanity check */
+ if(free_block >= heap->dblk_size)
+ HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "bad heap free list")
+
+ /* Allocate & initialize free list node */
+ if(NULL == (fl = H5FL_MALLOC(H5HL_free_t)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed")
+ fl->offset = (size_t)free_block;
+ fl->prev = tail;
+ fl->next = NULL;
+ /* Insert node into list */
+ if(tail)
+ tail->next = fl;
+ tail = fl;
+ if(!heap->freelist)
+ heap->freelist = fl;
+
+ /* Decode offset of next free block */
+ p = heap->dblk_image + free_block;
+ H5F_DECODE_LENGTH_LEN(p, free_block, heap->sizeof_size);
+ if(free_block == 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "free block size is zero?")
+
+ /* Decode length of this free block */
+ H5F_DECODE_LENGTH_LEN(p, fl->size, heap->sizeof_size);
+ if(fl->offset + fl->size > heap->dblk_size)
+ HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "bad heap free list")
+ } /* end while */
+
+done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HL_serialize() */
+} /* end H5HL_fl_deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5HL_load
+ * Function: H5HL_fl_serialize
*
- * Purpose: Loads a heap from disk.
+ * Purpose: Serialize the free list for a heap data block
*
- * Return: Success: Ptr to a local heap memory data structure.
+ * Return: Success: SUCCESS
+ * Failure: FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Oct 12 2008
*
+ *-------------------------------------------------------------------------
+ */
+static void
+H5HL_fl_serialize(const H5HL_t *heap)
+{
+ H5HL_free_t *fl; /* Pointer to heap free list node */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_fl_serialize)
+
+ /* check arguments */
+ HDassert(heap);
+
+ /* Serialize the free list into the heap data's image */
+ for(fl = heap->freelist; fl; fl = fl->next) {
+ uint8_t *p; /* Pointer into raw data buffer */
+
+ HDassert(fl->offset == H5HL_ALIGN(fl->offset));
+ p = heap->dblk_image + fl->offset;
+
+ if(fl->next)
+ H5F_ENCODE_LENGTH_LEN(p, fl->next->offset, heap->sizeof_size)
+ else
+ H5F_ENCODE_LENGTH_LEN(p, H5HL_FREE_NULL, heap->sizeof_size)
+
+ H5F_ENCODE_LENGTH_LEN(p, fl->size, heap->sizeof_size)
+ } /* end for */
+
+ FUNC_LEAVE_NOAPI_VOID
+} /* end H5HL_fl_serialize() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HL_prefix_load
+ *
+ * Purpose: Loads a local heap prefix from disk.
+ *
+ * Return: Success: Ptr to a local heap memory data structure.
* Failure: NULL
*
* Programmer: Robb Matzke
@@ -174,38 +242,47 @@ H5HL_serialize(H5F_t *f, H5HL_t *heap, uint8_t *buf)
*
*-------------------------------------------------------------------------
*/
-static H5HL_t *
-H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * udata1,
- void UNUSED * udata2)
+static void *
+H5HL_prefix_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1,
+ void *_udata)
{
- uint8_t hdr[52];
- size_t sizeof_hdr; /* Cache H5HL header size for file */
- const uint8_t *p = NULL;
- H5HL_t *heap = NULL;
- H5HL_free_t *fl = NULL, *tail = NULL;
- size_t free_block = H5HL_FREE_NULL;
- H5HL_t *ret_value;
+ H5HL_t *heap = NULL; /* Local heap */
+ H5HL_prfx_t *prfx = NULL; /* Heap prefix deserialized */
+ H5HL_cache_prfx_ud_t *udata = (H5HL_cache_prfx_ud_t *)_udata; /* User data for protecting local heap prefix */
+ uint8_t buf[H5HL_SPEC_READ_SIZE]; /* Buffer for decoding */
+ size_t spec_read_size; /* Size of buffer to speculatively read in */
+ const uint8_t *p; /* Pointer into decoding buffer */
+ haddr_t eoa; /* Relative end of file address */
+ void *ret_value; /* Return value */
- FUNC_ENTER_NOAPI(H5HL_load, NULL)
+ FUNC_ENTER_NOAPI_NOINIT(H5HL_prefix_load)
/* check arguments */
HDassert(f);
HDassert(H5F_addr_defined(addr));
HDassert(!udata1);
- HDassert(!udata2);
-
- /* Cache this for later */
- sizeof_hdr = H5HL_SIZEOF_HDR(f);
- HDassert(sizeof_hdr <= sizeof(hdr));
-
- /* Get the local heap's header */
- if(H5F_block_read(f, H5FD_MEM_LHEAP, addr, sizeof_hdr, dxpl_id, hdr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read heap header")
- p = hdr;
+ HDassert(udata);
+ HDassert(udata->sizeof_size > 0);
+ HDassert(udata->sizeof_addr > 0);
+ HDassert(udata->sizeof_prfx > 0);
+ HDassert(udata->sizeof_prfx <= sizeof(buf));
+
+ /* Make certain we don't speculatively read off the end of the file */
+ if(HADDR_UNDEF == (eoa = H5F_get_eoa(f, H5FD_MEM_LHEAP)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, NULL, "unable to determine file size")
+
+ /* Compute the size of the speculative local heap prefix buffer */
+ H5_ASSIGN_OVERFLOW(spec_read_size, MIN(eoa - addr, H5HL_SPEC_READ_SIZE), /* From: */ hsize_t, /* To: */ size_t);
+ HDassert(spec_read_size >= udata->sizeof_prfx);
+
+ /* Attempt to speculatively read both local heap prefix and heap data */
+ if(H5F_block_read(f, H5FD_MEM_LHEAP, addr, spec_read_size, dxpl_id, buf) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read local heap prefix")
+ p = buf;
/* Check magic number */
- if(HDmemcmp(hdr, H5HL_MAGIC, (size_t)H5_SIZEOF_MAGIC))
- HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "bad heap signature")
+ if(HDmemcmp(p, H5HL_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "bad local heap signature")
p += H5_SIZEOF_MAGIC;
/* Version */
@@ -216,65 +293,84 @@ H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * udata1,
p += 3;
/* Allocate space in memory for the heap */
- if(NULL == (heap = H5FL_CALLOC(H5HL_t)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "memory allocation failed")
+ if(NULL == (heap = H5HL_new(udata->sizeof_size, udata->sizeof_addr, udata->sizeof_prfx)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "can't allocate local heap structure")
- /* heap data size */
- H5F_DECODE_LENGTH(f, p, heap->heap_alloc);
+ /* Allocate the heap prefix */
+ if(NULL == (prfx = H5HL_prfx_new(heap)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "can't allocate local heap prefix")
- /* free list head */
- H5F_DECODE_LENGTH(f, p, free_block);
- if(free_block != H5HL_FREE_NULL && free_block >= heap->heap_alloc)
- HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "bad heap free list")
+ /* Store the prefix's address & length */
+ heap->prfx_addr = addr;
+ heap->prfx_size = udata->sizeof_prfx;
- /* data */
- H5F_addr_decode(f, &p, &(heap->addr));
- if(NULL == (heap->chunk = H5FL_BLK_CALLOC(lheap_chunk, (sizeof_hdr + heap->heap_alloc))))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "memory allocation failed")
- if(heap->heap_alloc &&
- H5F_block_read(f, H5FD_MEM_LHEAP, heap->addr, heap->heap_alloc, dxpl_id, heap->chunk + sizeof_hdr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read heap data")
+ /* Heap data size */
+ H5F_DECODE_LENGTH_LEN(p, heap->dblk_size, udata->sizeof_size);
- /* Build free list */
- while(H5HL_FREE_NULL != free_block) {
- if(free_block >= heap->heap_alloc)
- HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, NULL, "bad heap free list")
- if(NULL == (fl = H5FL_MALLOC(H5HL_free_t)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "memory allocation failed")
- fl->offset = free_block;
- fl->prev = tail;
- fl->next = NULL;
- if(tail)
- tail->next = fl;
- tail = fl;
- if(!heap->freelist)
- heap->freelist = fl;
-
- p = heap->chunk + sizeof_hdr + free_block;
+ /* Free list head */
+ H5F_DECODE_LENGTH_LEN(p, udata->free_block, udata->sizeof_size);
+ if(udata->free_block != H5HL_FREE_NULL && udata->free_block >= heap->dblk_size)
+ HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "bad heap free list")
- H5F_DECODE_LENGTH(f, p, free_block);
- if(free_block == 0)
- HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "free block size is zero?")
+ /* Heap data address */
+ H5F_addr_decode_len(udata->sizeof_addr, &p, &(heap->dblk_addr));
+
+ /* Check if heap block exists */
+ if(heap->dblk_size) {
+ /* Check if heap data block is contiguous with header */
+ if(H5F_addr_eq((heap->prfx_addr + heap->prfx_size), heap->dblk_addr)) {
+ /* Note that the heap should be a single object in the cache */
+ heap->single_cache_obj = TRUE;
+
+ /* Allocate space for the heap data image */
+ if(NULL == (heap->dblk_image = H5FL_BLK_MALLOC(lheap_chunk, heap->dblk_size)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "memory allocation failed")
+
+ /* Check if the current buffer from the speculative read already has the heap data */
+ if(spec_read_size >= (heap->prfx_size + heap->dblk_size)) {
+ /* Copy the heap data from the speculative read buffer */
+ HDmemcpy(heap->dblk_image, p, heap->dblk_size);
+ } /* end if */
+ else {
+ /* Read the local heap data block directly into buffer */
+ if(H5F_block_read(f, H5FD_MEM_LHEAP, heap->dblk_addr, heap->dblk_size, dxpl_id, heap->dblk_image) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read heap data")
+ } /* end else */
+
+ /* Build free list */
+ if(H5HL_fl_deserialize(heap, udata->free_block) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't initialize free list")
+ } /* end if */
+ else
+ /* Note that the heap should _NOT_ be a single object in the cache */
+ heap->single_cache_obj = FALSE;
+ } /* end if */
- H5F_DECODE_LENGTH(f, p, fl->size);
- if(fl->offset + fl->size > heap->heap_alloc)
- HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, NULL, "bad heap free list")
- } /* end while */
+ /* Set flag to indicate prefix from loaded from file */
+ udata->loaded = TRUE;
/* Set return value */
- ret_value = heap;
+ ret_value = prfx;
done:
- if(!ret_value && heap)
- if(H5HL_dest(f,heap) < 0)
- HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, NULL, "unable to destroy local heap collection")
+ /* Release the [possibly partially initialized] local heap on errors */
+ if(!ret_value) {
+ if(prfx) {
+ if(H5HL_prfx_dest(prfx) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTRELEASE, NULL, "unable to destroy local heap prefix")
+ } /* end if */
+ else {
+ if(heap && H5HL_dest(heap) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTRELEASE, NULL, "unable to destroy local heap")
+ } /* end else */
+ } /* end if */
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HL_load() */
+} /* end H5HL_prefix_load() */
/*-------------------------------------------------------------------------
- * Function: H5HL_flush
+ * Function: H5HL_prefix_flush
*
* Purpose: Flushes a heap from memory to disk if it's dirty. Optionally
* deletes the heap from memory.
@@ -288,58 +384,336 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HL_t *heap, unsigned UNUSED * flags_ptr)
+H5HL_prefix_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
+ void *thing, unsigned UNUSED *flags_ptr)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5HL_prfx_t *prfx = (H5HL_prfx_t *)thing; /* Local heap prefix to flush */
+ H5WB_t *wb = NULL; /* Wrapped buffer for heap data */
+ uint8_t heap_buf[H5HL_SPEC_READ_SIZE]; /* Buffer for heap */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5HL_flush, FAIL)
+ FUNC_ENTER_NOAPI_NOINIT(H5HL_prefix_flush)
/* check arguments */
HDassert(f);
HDassert(H5F_addr_defined(addr));
- HDassert(heap);
+ HDassert(prfx);
+
+ if(prfx->cache_info.is_dirty) {
+ H5HL_t *heap = prfx->heap; /* Pointer to the local heap */
+ H5HL_free_t *fl = heap->freelist; /* Pointer to heap's free list */
+ uint8_t *buf; /* Pointer to heap buffer */
+ size_t buf_size; /* Size of buffer for encoding & writing heap info */
+ uint8_t *p; /* Pointer into raw data buffer */
+
+ /* Wrap the local buffer for serialized heap info */
+ if(NULL == (wb = H5WB_wrap(heap_buf, sizeof(heap_buf))))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't wrap buffer")
+
+ /* Compute the size of the buffer to encode & write */
+ buf_size = heap->prfx_size;
+ if(heap->single_cache_obj)
+ buf_size += heap->dblk_size;
+
+ /* Get a pointer to a buffer that's large enough for serialized heap */
+ if(NULL == (buf = (uint8_t *)H5WB_actual(wb, buf_size)))
+ HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "can't get actual buffer")
+
+ /* Serialize the heap prefix */
+ p = buf;
+ HDmemcpy(p, H5HL_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ p += H5_SIZEOF_MAGIC;
+ *p++ = H5HL_VERSION;
+ *p++ = 0; /*reserved*/
+ *p++ = 0; /*reserved*/
+ *p++ = 0; /*reserved*/
+ H5F_ENCODE_LENGTH_LEN(p, heap->dblk_size, heap->sizeof_size);
+ H5F_ENCODE_LENGTH_LEN(p, fl ? fl->offset : H5HL_FREE_NULL, heap->sizeof_size);
+ H5F_addr_encode_len(heap->sizeof_addr, &p, heap->dblk_addr);
+
+ /* Check if the local heap is a single object in cache */
+ if(heap->single_cache_obj) {
+ /* Serialize the free list into the heap data's image */
+ H5HL_fl_serialize(heap);
+
+ /* Copy the heap data block into the cache image */
+ HDmemcpy(p, heap->dblk_image, heap->dblk_size);
+ } /* end if */
- if(heap->cache_info.is_dirty) {
- haddr_t hdr_end_addr;
- size_t sizeof_hdr = H5HL_SIZEOF_HDR(f); /* cache H5HL header size for file */
+ /* Write the prefix [and possibly the data block] to the file */
+ if(H5F_block_write(f, H5FD_MEM_LHEAP, addr, buf_size, dxpl_id, buf) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header and data to file")
- /* Write the header */
- if(H5HL_serialize(f, heap, heap->chunk) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTSERIALIZE, FAIL, "unable to serialize local heap")
+ prfx->cache_info.is_dirty = FALSE;
+ } /* end if */
- /* Copy buffer to disk */
- hdr_end_addr = addr + (hsize_t)sizeof_hdr;
+ /* Should we destroy the memory version? */
+ if(destroy)
+ if(H5HL_prfx_dest(prfx) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap prefix")
- if(H5F_addr_eq(heap->addr, hdr_end_addr)) {
- /* The header and data are contiguous */
- if(H5F_block_write(f, H5FD_MEM_LHEAP, addr, (sizeof_hdr + heap->heap_alloc), dxpl_id, heap->chunk) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header and data to file")
- } /* end if */
- else {
- if(H5F_block_write(f, H5FD_MEM_LHEAP, addr, sizeof_hdr, dxpl_id, heap->chunk) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header to file")
+done:
+ /* Release resources */
+ if(wb && H5WB_unwrap(wb) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CLOSEERROR, FAIL, "can't close wrapped buffer")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HL_prefix_flush() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HL_prefix_dest
+ *
+ * Purpose: Destroys a heap prefix in memory.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Jan 15 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HL_prefix_dest(H5F_t UNUSED *f, void *thing)
+{
+ H5HL_prfx_t *prfx = (H5HL_prfx_t *)thing; /* Local heap prefix to destroy */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HL_prefix_dest)
- if(H5F_block_write(f, H5FD_MEM_LHEAP, heap->addr, heap->heap_alloc, dxpl_id, heap->chunk + sizeof_hdr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap data to file")
- } /* end else */
+ /* check arguments */
+ HDassert(prfx);
+ HDassert(prfx->heap);
+ HDassert(H5F_addr_eq(prfx->cache_info.addr, prfx->heap->prfx_addr));
+
+ /* Verify that entry is clean */
+ HDassert(prfx->cache_info.is_dirty == FALSE);
+
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!prfx->cache_info.free_file_space_on_destroy || H5F_addr_defined(prfx->cache_info.addr));
- heap->cache_info.is_dirty = FALSE;
+ /* Check for freeing file space for local heap prefix */
+ if(prfx->cache_info.free_file_space_on_destroy) {
+ hsize_t free_size; /* Size of region to free in file */
+
+ /* Compute size to free for later */
+ free_size = prfx->heap->prfx_size;
+ if(prfx->heap->single_cache_obj)
+ free_size += prfx->heap->dblk_size;
+
+ /* Free the local heap prefix [and possible the data block] on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_LHEAP, H5AC_dxpl_id, prfx->cache_info.addr, free_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap prefix")
+ } /* end if */
+
+ /* Destroy local heap prefix */
+ if(H5HL_prfx_dest(prfx) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't destroy local heap prefix")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HL_prefix_dest() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HL_prefix_clear
+ *
+ * Purpose: Mark a local heap prefix in memory as non-dirty.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Mar 20 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HL_prefix_clear(H5F_t UNUSED *f, void *thing, hbool_t destroy)
+{
+ H5HL_prfx_t *prfx = (H5HL_prfx_t *)thing; /* The local heap prefix to operate on */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HL_prefix_clear)
+
+ /* check arguments */
+ HDassert(prfx);
+
+ /* Mark heap prefix as clean */
+ prfx->cache_info.is_dirty = FALSE;
+
+ if(destroy)
+ if(H5HL_prfx_dest(prfx) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap prefix")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HL_prefix_clear() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HL_prefix_size
+ *
+ * Purpose: Compute the size in bytes of the heap prefix on disk,
+ * and return it in *len_ptr. On failure, the value of *len_ptr
+ * is undefined.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 5/13/04
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HL_prefix_size(const H5F_t UNUSED *f, const void *thing, size_t *size_ptr)
+{
+ const H5HL_prfx_t *prfx = (const H5HL_prfx_t *)thing; /* Pointer to local heap prefix to query */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_prefix_size)
+
+ /* check arguments */
+ HDassert(prfx);
+ HDassert(prfx->heap);
+ HDassert(size_ptr);
+
+ /* Calculate size of prefix in cache */
+ *size_ptr = prfx->heap->prfx_size;
+
+ /* If the heap is stored as a single object, add in the data block size also */
+ if(prfx->heap->single_cache_obj)
+ *size_ptr += prfx->heap->dblk_size;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5HL_prefix_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HL_datablock_load
+ *
+ * Purpose: Loads a local heap data block from disk.
+ *
+ * Return: Success: Ptr to a local heap data block memory data structure.
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jan 5 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5HL_datablock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1,
+ void *_udata)
+{
+ H5HL_dblk_t *dblk = NULL; /* Heap data block deserialized */
+ H5HL_cache_dblk_ud_t *udata = (H5HL_cache_dblk_ud_t *)_udata; /* User data for protecting local heap data block */
+ void *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HL_datablock_load)
+
+ /* check arguments */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(!udata1);
+ HDassert(udata);
+ HDassert(udata->heap);
+ HDassert(!udata->heap->single_cache_obj);
+
+ /* Allocate space in memory for the heap data block */
+ if(NULL == (dblk = H5HL_dblk_new(udata->heap)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "memory allocation failed")
+
+ /* Check for heap still retaining image */
+ if(NULL == udata->heap->dblk_image) {
+ /* Allocate space for the heap data image */
+ if(NULL == (udata->heap->dblk_image = H5FL_BLK_MALLOC(lheap_chunk, udata->heap->dblk_size)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "can't allocate data block image buffer")
+
+ /* Read local heap data block */
+ if(H5F_block_read(f, H5FD_MEM_LHEAP, udata->heap->dblk_addr, udata->heap->dblk_size, dxpl_id, udata->heap->dblk_image) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read local heap data block")
+
+ /* Build free list */
+ if(H5HL_fl_deserialize(udata->heap, udata->free_block) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't initialize free list")
+ } /* end if */
+
+ /* Set flag to indicate data block from loaded from file */
+ udata->loaded = TRUE;
+
+ /* Set return value */
+ ret_value = dblk;
+
+done:
+ /* Release the [possibly partially initialized] local heap on errors */
+ if(!ret_value && dblk)
+ if(H5HL_dblk_dest(f, dblk) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTRELEASE, NULL, "unable to destroy local heap data block")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HL_datablock_load() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HL_datablock_flush
+ *
+ * Purpose: Flushes a heap's data block from memory to disk if it's dirty.
+ * Optionally deletes the heap data block from memory.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Jul 17 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HL_datablock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
+ void *_thing, unsigned UNUSED * flags_ptr)
+{
+ H5HL_dblk_t *dblk = (H5HL_dblk_t *)_thing; /* Pointer to the local heap data block */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HL_datablock_flush)
+
+ /* check arguments */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(dblk);
+ HDassert(dblk->heap);
+ HDassert(!dblk->heap->single_cache_obj);
+
+ if(dblk->cache_info.is_dirty) {
+ H5HL_t *heap = dblk->heap; /* Pointer to the local heap */
+
+ /* Serialize the free list into the heap data's image */
+ H5HL_fl_serialize(heap);
+
+ /* Write the data block to the file */
+ if(H5F_block_write(f, H5FD_MEM_LHEAP, heap->dblk_addr, heap->dblk_size, dxpl_id, heap->dblk_image) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap data block to file")
+
+ dblk->cache_info.is_dirty = FALSE;
} /* end if */
/* Should we destroy the memory version? */
if(destroy)
- if(H5HL_dest(f, heap) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap collection")
+ if(H5HL_dblk_dest(f, dblk) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap data block")
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HL_flush() */
+} /* end H5HL_datablock_flush() */
/*-------------------------------------------------------------------------
- * Function: H5HL_dest
+ * Function: H5HL_datablock_dest
*
- * Purpose: Destroys a heap in memory.
+ * Purpose: Destroys a local heap data block in memory.
*
* Return: Non-negative on success/Negative on failure
*
@@ -349,75 +723,48 @@ done:
*
*-------------------------------------------------------------------------
*/
-herr_t
-H5HL_dest(H5F_t *f, H5HL_t *heap)
+static herr_t
+H5HL_datablock_dest(H5F_t *f, void *_thing)
{
- H5HL_free_t *fl; /* Heap object free list */
+ H5HL_dblk_t *dblk = (H5HL_dblk_t *)_thing; /* Pointer to the local heap data block */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5HL_dest)
+ FUNC_ENTER_NOAPI_NOINIT(H5HL_datablock_dest)
/* check arguments */
- HDassert(heap);
+ HDassert(f);
+ HDassert(dblk);
+ HDassert(dblk->heap);
+ HDassert(!dblk->heap->single_cache_obj);
+ HDassert(H5F_addr_eq(dblk->cache_info.addr, dblk->heap->dblk_addr));
- /* Verify that node is clean */
- HDassert(heap->cache_info.is_dirty == FALSE);
+ /* Verify that entry is clean */
+ HDassert(dblk->cache_info.is_dirty == FALSE);
/* If we're going to free the space on disk, the address must be valid */
- HDassert(!heap->cache_info.free_file_space_on_destroy || H5F_addr_defined(heap->cache_info.addr));
-
- /* Check for freeing file space for local heap */
- if(heap->cache_info.free_file_space_on_destroy) {
- size_t sizeof_hdr; /* H5HL header size for file */
- haddr_t hdr_addr; /* Address of heap header in file */
-
- /* Compute this for later */
- sizeof_hdr = H5HL_SIZEOF_HDR(f);
- hdr_addr = heap->cache_info.addr;
-
- /* Check if the heap is contiguous on disk */
- HDassert(!H5F_addr_overflow(hdr_addr, sizeof_hdr));
- if(H5F_addr_eq(heap->addr, hdr_addr + sizeof_hdr)) {
- /* Free the contiguous local heap in one call */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- H5_CHECK_OVERFLOW(sizeof_hdr + heap->heap_alloc, size_t, hsize_t);
- if(H5MF_xfree(f, H5FD_MEM_LHEAP, H5AC_dxpl_id, hdr_addr, (hsize_t)(sizeof_hdr + heap->heap_alloc)) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free contiguous local heap")
- } /* end if */
- else {
- /* Free the local heap's header */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- H5_CHECK_OVERFLOW(sizeof_hdr, size_t, hsize_t);
- if(H5MF_xfree(f, H5FD_MEM_LHEAP, H5AC_dxpl_id, hdr_addr, (hsize_t)sizeof_hdr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap header")
-
- /* Free the local heap's data */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- H5_CHECK_OVERFLOW(heap->heap_alloc, size_t, hsize_t);
- if(H5MF_xfree(f, H5FD_MEM_LHEAP, H5AC_dxpl_id, heap->addr, (hsize_t)heap->heap_alloc) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap data")
- } /* end else */
+ HDassert(!dblk->cache_info.free_file_space_on_destroy || H5F_addr_defined(dblk->cache_info.addr));
+
+ /* Check for freeing file space for local heap data block */
+ if(dblk->cache_info.free_file_space_on_destroy) {
+ /* Free the local heap data block on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_LHEAP, H5AC_dxpl_id, dblk->cache_info.addr, (hsize_t)dblk->heap->dblk_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap data block")
} /* end if */
- /* Release resources */
- if(heap->chunk)
- heap->chunk = H5FL_BLK_FREE(lheap_chunk, heap->chunk);
- while(heap->freelist) {
- fl = heap->freelist;
- heap->freelist = fl->next;
- fl = H5FL_FREE(H5HL_free_t, fl);
- } /* end while */
- heap = H5FL_FREE(H5HL_t, heap);
+ /* Destroy local heap data block */
+ if(H5HL_dblk_dest(f, dblk) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't destroy local heap data block")
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HL_dest() */
+} /* end H5HL_datablock_dest() */
/*-------------------------------------------------------------------------
- * Function: H5HL_clear
+ * Function: H5HL_datablock_clear
*
- * Purpose: Mark a local heap in memory as non-dirty.
+ * Purpose: Mark a local heap data block in memory as non-dirty.
*
* Return: Non-negative on success/Negative on failure
*
@@ -428,33 +775,35 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5HL_clear(H5F_t *f, H5HL_t *heap, hbool_t destroy)
+H5HL_datablock_clear(H5F_t *f, void *_thing, hbool_t destroy)
{
+ H5HL_dblk_t *dblk = (H5HL_dblk_t *)_thing; /* Pointer to the local heap data block */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5HL_clear)
+ FUNC_ENTER_NOAPI_NOINIT(H5HL_datablock_clear)
/* check arguments */
- HDassert(heap);
+ HDassert(f);
+ HDassert(dblk);
- /* Mark heap as clean */
- heap->cache_info.is_dirty = FALSE;
+ /* Mark local heap data block as clean */
+ dblk->cache_info.is_dirty = FALSE;
if(destroy)
- if(H5HL_dest(f, heap) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap collection")
+ if(H5HL_dblk_dest(f, dblk) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap data block")
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HL_clear() */
+} /* end H5HL_datablock_clear() */
/*-------------------------------------------------------------------------
- * Function: H5HL_size
+ * Function: H5HL_datablock_size
*
- * Purpose: Compute the size in bytes of the specified instance of
- * H5HL_t on disk, and return it in *len_ptr. On failure,
- * the value of *len_ptr is undefined.
+ * Purpose: Compute the size in bytes of the local heap data block on disk,
+ * and return it in *len_ptr. On failure, the value of *len_ptr
+ * is undefined.
*
* Return: Non-negative on success/Negative on failure
*
@@ -463,18 +812,21 @@ done:
*
*-------------------------------------------------------------------------
*/
-herr_t
-H5HL_size(const H5F_t *f, const H5HL_t *heap, size_t *size_ptr)
+static herr_t
+H5HL_datablock_size(const H5F_t UNUSED *f, const void *_thing, size_t *size_ptr)
{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_size)
+ const H5HL_dblk_t *dblk = (const H5HL_dblk_t *)_thing; /* Pointer to the local heap data block */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_datablock_size)
/* check arguments */
- HDassert(f);
- HDassert(heap);
+ HDassert(dblk);
+ HDassert(dblk->heap);
HDassert(size_ptr);
- *size_ptr = H5HL_SIZEOF_HDR(f) + heap->heap_alloc;
+ /* Set size of data block in cache */
+ *size_ptr = dblk->heap->dblk_size;
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5HL_size() */
+} /* H5HL_datablock_size() */
diff --git a/src/H5HLdbg.c b/src/H5HLdbg.c
index 6bf35ad..8107164 100644
--- a/src/H5HLdbg.c
+++ b/src/H5HLdbg.c
@@ -69,28 +69,25 @@ H5HL_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent, int
HDassert(indent >= 0);
HDassert(fwidth >= 0);
- if(NULL == (h = (H5HL_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (h = (H5HL_t *)H5HL_protect(f, dxpl_id, addr, H5AC_READ)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap")
fprintf(stream, "%*sLocal Heap...\n", indent, "");
- fprintf(stream, "%*s%-*s %d\n", indent, "", fwidth,
- "Dirty:",
- (int) (h->cache_info.is_dirty));
fprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth,
"Header size (in bytes):",
- (unsigned long) H5HL_SIZEOF_HDR(f));
+ (unsigned long)h->prfx_size);
HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
"Address of heap data:",
- h->addr);
+ h->dblk_addr);
HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth,
"Data bytes allocated for heap:",
- h->heap_alloc);
+ h->dblk_size);
/*
* Traverse the free list and check that all free blocks fall within
* the heap and that no two free blocks point to the same region of
* the heap. */
- if(NULL == (marker = (uint8_t *)H5MM_calloc(h->heap_alloc)))
+ if(NULL == (marker = (uint8_t *)H5MM_calloc(h->dblk_size)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed")
fprintf(stream, "%*sFree Blocks (offset, size):\n", indent, "");
@@ -102,7 +99,7 @@ H5HL_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent, int
HDfprintf(stream, "%*s%-*s %8Zu, %8Zu\n", indent+3, "", MAX(0,fwidth-9),
temp_str,
freelist->offset, freelist->size);
- if(freelist->offset + freelist->size > h->heap_alloc)
+ if((freelist->offset + freelist->size) > h->dblk_size)
fprintf(stream, "***THAT FREE BLOCK IS OUT OF BOUNDS!\n");
else {
for(i = overlap = 0; i < (int)(freelist->size); i++) {
@@ -111,25 +108,24 @@ H5HL_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent, int
marker[freelist->offset + i] = 1;
} /* end for */
if(overlap)
- fprintf(stream, "***THAT FREE BLOCK OVERLAPPED A PREVIOUS "
- "ONE!\n");
+ fprintf(stream, "***THAT FREE BLOCK OVERLAPPED A PREVIOUS ONE!\n");
else
amount_free += freelist->size;
} /* end for */
} /* end for */
- if(h->heap_alloc)
+ if(h->dblk_size)
fprintf(stream, "%*s%-*s %.2f%%\n", indent, "", fwidth,
"Percent of heap used:",
- (100.0 * (double)(h->heap_alloc - amount_free) / (double)h->heap_alloc));
+ (100.0 * (double)(h->dblk_size - amount_free) / (double)h->dblk_size));
/*
* Print the data in a VMS-style octal dump.
*/
- H5_buffer_dump(stream, indent, h->chunk, marker, H5HL_SIZEOF_HDR(f), h->heap_alloc);
+ H5_buffer_dump(stream, indent, h->dblk_image, marker, (size_t)0, h->dblk_size);
done:
- if(h && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, h, FALSE) < 0)
+ if(h && H5HL_unprotect(f, h) < 0)
HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header")
H5MM_xfree(marker);
diff --git a/src/H5HLint.c b/src/H5HLint.c
new file mode 100644
index 0000000..23ffe00
--- /dev/null
+++ b/src/H5HLint.c
@@ -0,0 +1,417 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5HLint.c
+ * Oct 12 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: Local heap internal routines.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5HL_PACKAGE /* Suppress error about including H5HLpkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5HLpkg.h" /* Local Heaps */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* Declare a free list to manage the H5HL_t struct */
+H5FL_DEFINE_STATIC(H5HL_t);
+
+/* Declare a free list to manage the H5HL_dblk_t struct */
+H5FL_DEFINE_STATIC(H5HL_dblk_t);
+
+/* Declare a free list to manage the H5HL_prfx_t struct */
+H5FL_DEFINE_STATIC(H5HL_prfx_t);
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HL_new
+ *
+ * Purpose: Create a new local heap object
+ *
+ * Return: Success: non-NULL pointer to new local heap
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jan 5 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+H5HL_t *
+H5HL_new(size_t sizeof_size, size_t sizeof_addr, size_t prfx_size)
+{
+ H5HL_t *heap = NULL; /* New local heap */
+ H5HL_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5HL_new, NULL)
+
+ /* check arguments */
+ HDassert(sizeof_size > 0);
+ HDassert(sizeof_addr > 0);
+ HDassert(prfx_size > 0);
+
+ /* Allocate new local heap structure */
+ if(NULL == (heap = H5FL_CALLOC(H5HL_t)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "memory allocation failed")
+
+ /* Initialize non-zero fields */
+ heap->sizeof_size = sizeof_size;
+ heap->sizeof_addr = sizeof_addr;
+ heap->prfx_size = prfx_size;
+
+ /* Set the return value */
+ ret_value = heap;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HL_new() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HL_inc_rc
+ *
+ * Purpose: Increment ref. count on heap
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Oct 12 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HL_inc_rc(H5HL_t *heap)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_inc_rc)
+
+ /* check arguments */
+ HDassert(heap);
+
+ /* Increment heap's ref. count */
+ heap->rc++;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5HL_inc_rc() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HL_dec_rc
+ *
+ * Purpose: Decrement ref. count on heap
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Oct 12 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HL_dec_rc(H5HL_t *heap)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_dec_rc)
+
+ /* check arguments */
+ HDassert(heap);
+
+ /* Decrement heap's ref. count */
+ heap->rc--;
+
+ /* Check if we should destroy the heap */
+ if(heap->rc == 0)
+ H5HL_dest(heap);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5HL_dec_rc() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HL_dest
+ *
+ * Purpose: Destroys a heap in memory.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Jan 15 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HL_dest(H5HL_t *heap)
+{
+ FUNC_ENTER_NOAPI_NOFUNC(H5HL_dest)
+
+ /* check arguments */
+ HDassert(heap);
+
+ /* Verify that node is unused */
+ HDassert(heap->prots == 0);
+ HDassert(heap->rc == 0);
+ HDassert(heap->prfx == NULL);
+ HDassert(heap->dblk == NULL);
+
+ if(heap->dblk_image)
+ heap->dblk_image = H5FL_BLK_FREE(lheap_chunk, heap->dblk_image);
+ while(heap->freelist) {
+ H5HL_free_t *fl;
+
+ fl = heap->freelist;
+ heap->freelist = fl->next;
+ fl = H5FL_FREE(H5HL_free_t, fl);
+ } /* end while */
+ heap = H5FL_FREE(H5HL_t, heap);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5HL_dest() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HL_prfx_new
+ *
+ * Purpose: Create a new local heap prefix object
+ *
+ * Return: Success: non-NULL pointer to new local heap prefix
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Oct 12 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+H5HL_prfx_t *
+H5HL_prfx_new(H5HL_t *heap)
+{
+ H5HL_prfx_t *prfx = NULL; /* New local heap prefix */
+ H5HL_prfx_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5HL_prfx_new, NULL)
+
+ /* check arguments */
+ HDassert(heap);
+
+ /* Allocate new local heap prefix */
+ if(NULL == (prfx = H5FL_CALLOC(H5HL_prfx_t)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "memory allocation failed")
+
+ /* Increment ref. count on heap data structure */
+ if(H5HL_inc_rc(heap) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment heap ref. count")
+
+ /* Link the heap & the prefix */
+ prfx->heap = heap;
+ heap->prfx = prfx;
+
+ /* Set the return value */
+ ret_value = prfx;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HL_prfx_new() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HL_prfx_dest
+ *
+ * Purpose: Destroy a local heap prefix object
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Oct 12 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HL_prfx_dest(H5HL_prfx_t *prfx)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5HL_prfx_dest, FAIL)
+
+ /* check arguments */
+ HDassert(prfx);
+
+ /* Check if prefix was initialized */
+ if(prfx->heap) {
+ /* Unlink prefix from heap */
+ prfx->heap->prfx = NULL;
+
+ /* Decrement ref. count on heap data structure */
+ if(H5HL_dec_rc(prfx->heap) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement heap ref. count")
+
+ /* Unlink heap from prefix */
+ prfx->heap = NULL;
+ } /* end if */
+
+ /* Free local heap prefix */
+ prfx = H5FL_FREE(H5HL_prfx_t, prfx);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HL_prfx_dest() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HL_dblk_new
+ *
+ * Purpose: Create a new local heap data block object
+ *
+ * Return: Success: non-NULL pointer to new local heap data block
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Oct 12 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+H5HL_dblk_t *
+H5HL_dblk_new(H5HL_t *heap)
+{
+ H5HL_dblk_t *dblk = NULL; /* New local heap data block */
+ H5HL_dblk_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5HL_dblk_new, NULL)
+
+ /* check arguments */
+ HDassert(heap);
+
+ /* Allocate new local heap data block */
+ if(NULL == (dblk = H5FL_CALLOC(H5HL_dblk_t)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "memory allocation failed")
+
+ /* Increment ref. count on heap data structure */
+ if(H5HL_inc_rc(heap) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment heap ref. count")
+
+ /* Link the heap & the data block */
+ dblk->heap = heap;
+ heap->dblk = dblk;
+
+ /* Set the return value */
+ ret_value = dblk;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HL_dblk_new() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HL_dblk_dest
+ *
+ * Purpose: Destroy a local heap data block object
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Oct 12 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HL_dblk_dest(H5F_t *f, H5HL_dblk_t *dblk)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5HL_dblk_dest, FAIL)
+
+ /* check arguments */
+ HDassert(dblk);
+
+ /* Check if data block was initialized */
+ if(dblk->heap) {
+ /* Unlink data block from heap */
+ dblk->heap->dblk = NULL;
+
+ /* Unpin the local heap prefix */
+ if(H5AC_unpin_entry(f, dblk->heap->prfx) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPIN, FAIL, "can't unpin local heap prefix")
+
+ /* Decrement ref. count on heap data structure */
+ if(H5HL_dec_rc(dblk->heap) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement heap ref. count")
+
+ /* Unlink heap from data block */
+ dblk->heap = NULL;
+ } /* end if */
+
+ /* Free local heap data block */
+ dblk = H5FL_FREE(H5HL_dblk_t, dblk);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HL_dblk_dest() */
+
diff --git a/src/H5HLpkg.h b/src/H5HLpkg.h
index 50cb4ed..8052eb1 100644
--- a/src/H5HLpkg.h
+++ b/src/H5HLpkg.h
@@ -39,15 +39,15 @@
/* Package Private Variables */
/*****************************/
-/* The cache subclass */
-H5_DLLVAR const H5AC_class_t H5AC_LHEAP[1];
+/* The local heap prefix cache subclass */
+H5_DLLVAR const H5AC_class_t H5AC_LHEAP_PRFX[1];
+
+/* The local heap data block cache subclass */
+H5_DLLVAR const H5AC_class_t H5AC_LHEAP_DBLK[1];
/* Declare extern the free list to manage the H5HL_free_t struct */
H5FL_EXTERN(H5HL_free_t);
-/* Declare extern the free list to manage the H5HL_t struct */
-H5FL_EXTERN(H5HL_t);
-
/* Declare extern the PQ free list to manage the heap chunk information */
H5FL_BLK_EXTERN(lheap_chunk);
@@ -58,10 +58,14 @@ H5FL_BLK_EXTERN(lheap_chunk);
#define H5HL_SIZEOF_HDR(F) \
H5HL_ALIGN(H5_SIZEOF_MAGIC + /*heap signature */ \
- 4 + /*reserved */ \
- H5F_SIZEOF_SIZE (F) + /*data size */ \
- H5F_SIZEOF_SIZE (F) + /*free list head */ \
- H5F_SIZEOF_ADDR (F)) /*data address */
+ 1 + /*version */ \
+ 3 + /*reserved */ \
+ H5F_SIZEOF_SIZE(F) + /*data size */ \
+ H5F_SIZEOF_SIZE(F) + /*free list head */ \
+ H5F_SIZEOF_ADDR(F)) /*data address */
+
+/* Value indicating end of free list on disk */
+#define H5HL_FREE_NULL 1
/****************************/
@@ -75,22 +79,83 @@ typedef struct H5HL_free_t {
struct H5HL_free_t *next; /*next entry in free list */
} H5HL_free_t;
+/* Forward declarations */
+typedef struct H5HL_dblk_t H5HL_dblk_t;
+typedef struct H5HL_prfx_t H5HL_prfx_t;
+
struct H5HL_t {
- H5AC_info_t cache_info; /* Information for H5AC cache functions, _must_ be */
- /* first field in structure */
- haddr_t addr; /*address of data */
- size_t heap_alloc; /*size of heap on disk and in mem */
- uint8_t *chunk; /*the chunk, including header */
+ /* General heap-management fields */
+ size_t rc; /* Ref. count for prefix & data block using this struct */
+ size_t prots; /* # of times the heap has been protected */
+ size_t sizeof_size; /* Size of file sizes */
+ size_t sizeof_addr; /* Size of file addresses */
+ hbool_t single_cache_obj; /* Indicate if the heap is a single object in the cache */
+
+ /* Prefix-specific fields */
+ H5HL_prfx_t *prfx; /* The prefix object for the heap */
+ haddr_t prfx_addr; /* address of heap prefix */
+ size_t prfx_size; /* size of heap prefix */
+
+ /* Data block-specific fields */
+ H5HL_dblk_t *dblk; /* The data block object for the heap */
+ haddr_t dblk_addr; /* address of data block */
+ size_t dblk_size; /* size of heap data block on disk and in mem */
+ uint8_t *dblk_image; /* The data block image */
H5HL_free_t *freelist; /*the free list */
};
+/* Struct for heap data block */
+struct H5HL_dblk_t {
+ H5AC_info_t cache_info; /* Information for H5AC cache functions, _must_ be */
+ /* first field in structure */
+ H5HL_t *heap; /* Pointer to heap for data block */
+};
+
+/* Struct for heap prefix */
+struct H5HL_prfx_t {
+ H5AC_info_t cache_info; /* Information for H5AC cache functions, _must_ be */
+ /* first field in structure */
+ H5HL_t *heap; /* Pointer to heap for prefix */
+};
+
+/* Callback information for loading local heap prefix from disk */
+typedef struct H5HL_cache_prfx_ud_t {
+ /* Downwards */
+ size_t sizeof_size; /* Size of file sizes */
+ size_t sizeof_addr; /* Size of file addresses */
+ size_t sizeof_prfx; /* Size of heap prefix */
+
+ /* Upwards */
+ hbool_t loaded; /* Whether prefix was loaded from file */
+ hsize_t free_block; /* First free block in heap */
+} H5HL_cache_prfx_ud_t;
+
+/* Callback information for loading local heap data block from disk */
+typedef struct H5HL_cache_dblk_ud_t {
+ /* Downwards */
+ H5HL_t *heap; /* Local heap */
+ hsize_t free_block; /* First free block in heap */
+
+ /* Upwards */
+ hbool_t loaded; /* Whether data block was loaded from file */
+} H5HL_cache_dblk_ud_t;
+
/******************************/
/* Package Private Prototypes */
/******************************/
-H5_DLL herr_t H5HL_dest(H5F_t *f, H5HL_t *heap);
-H5_DLL herr_t H5HL_size(const H5F_t *f, const H5HL_t *heap, size_t *size_ptr);
+/* Heap routines */
+H5_DLL H5HL_t *H5HL_new(size_t sizeof_size, size_t sizeof_addr, size_t prfx_size);
+H5_DLL herr_t H5HL_dest(H5HL_t *heap);
+
+/* Heap prefix routines */
+H5_DLL H5HL_prfx_t *H5HL_prfx_new(H5HL_t *heap);
+H5_DLL herr_t H5HL_prfx_dest(H5HL_prfx_t *prfx);
+
+/* Heap data block routines */
+H5_DLL H5HL_dblk_t *H5HL_dblk_new(H5HL_t *heap);
+H5_DLL herr_t H5HL_dblk_dest(H5F_t *f, H5HL_dblk_t *dblk);
#endif /* _H5HLpkg_H */
diff --git a/src/H5HLprivate.h b/src/H5HLprivate.h
index 2a3e2df..df2ec62 100644
--- a/src/H5HLprivate.h
+++ b/src/H5HLprivate.h
@@ -62,10 +62,10 @@ typedef struct H5HL_t H5HL_t;
*/
H5_DLL herr_t H5HL_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, haddr_t *addr/*out*/);
H5_DLL H5HL_t *H5HL_protect(H5F_t *f, hid_t dxpl_id, haddr_t addr, H5AC_protect_t rw);
-H5_DLL void *H5HL_offset_into(H5F_t *f, const H5HL_t *heap, size_t offset);
+H5_DLL void *H5HL_offset_into(const H5HL_t *heap, size_t offset);
H5_DLL herr_t H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset,
size_t size);
-H5_DLL herr_t H5HL_unprotect(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, haddr_t addr);
+H5_DLL herr_t H5HL_unprotect(H5F_t *f, H5HL_t *heap);
H5_DLL size_t H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t size,
const void *buf);
H5_DLL herr_t H5HL_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr);
diff --git a/src/H5Oefl.c b/src/H5Oefl.c
index 5702b34..b16f415 100644
--- a/src/H5Oefl.c
+++ b/src/H5Oefl.c
@@ -126,11 +126,11 @@ H5O_efl_decode(H5F_t *f, hid_t dxpl_id, H5O_t UNUSED *open_oh,
if(NULL == (heap = H5HL_protect(f, dxpl_id, mesg->heap_addr, H5AC_READ)))
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, NULL, "unable to read protect link value")
- s = (const char *)H5HL_offset_into(f, heap, 0);
+ s = (const char *)H5HL_offset_into(heap, 0);
HDassert(s && !*s);
- if(H5HL_unprotect(f, dxpl_id, heap, mesg->heap_addr) < 0)
+ if(H5HL_unprotect(f, heap) < 0)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, NULL, "unable to read unprotect link value")
heap = NULL;
#endif
@@ -146,7 +146,7 @@ H5O_efl_decode(H5F_t *f, hid_t dxpl_id, H5O_t UNUSED *open_oh,
/* Name */
H5F_DECODE_LENGTH (f, p, mesg->slot[u].name_offset);
- s = (const char *)H5HL_offset_into(f, heap, mesg->slot[u].name_offset);
+ s = (const char *)H5HL_offset_into(heap, mesg->slot[u].name_offset);
HDassert(s && *s);
mesg->slot[u].name = H5MM_xstrdup (s);
HDassert(mesg->slot[u].name);
@@ -159,7 +159,7 @@ H5O_efl_decode(H5F_t *f, hid_t dxpl_id, H5O_t UNUSED *open_oh,
HDassert(mesg->slot[u].size > 0);
} /* end for */
- if(H5HL_unprotect(f, dxpl_id, heap, mesg->heap_addr) < 0)
+ if(H5HL_unprotect(f, heap) < 0)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, NULL, "unable to read unprotect link value")
heap = NULL;
@@ -482,7 +482,7 @@ H5O_efl_copy_file(H5F_t UNUSED *file_src, void *mesg_src, H5F_t *file_dst,
done:
/* Release resources */
- if(heap && H5HL_unprotect(file_dst, dxpl_id, heap, efl_dst->heap_addr) < 0)
+ if(heap && H5HL_unprotect(file_dst, heap) < 0)
HDONE_ERROR(H5E_EFL, H5E_PROTECT, NULL, "unable to unprotect EFL file name heap")
if(!ret_value)
if(efl_dst)
diff --git a/src/Makefile.am b/src/Makefile.am
index b71033e..494f370 100755
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -71,7 +71,7 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
H5HFhdr.c H5HFhuge.c H5HFiblock.c H5HFiter.c H5HFman.c H5HFsection.c \
H5HFspace.c H5HFstat.c H5HFtest.c H5HFtiny.c \
H5HG.c H5HGcache.c H5HGdbg.c \
- H5HL.c H5HLcache.c H5HLdbg.c \
+ H5HL.c H5HLcache.c H5HLdbg.c H5HLint.c \
H5HP.c H5I.c H5L.c H5Lexternal.c \
H5MF.c H5MFaggr.c H5MFdbg.c H5MFsection.c \
H5MM.c H5MP.c H5MPtest.c \
diff --git a/src/Makefile.in b/src/Makefile.in
index d6f6dae..b650260 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -122,14 +122,14 @@ am_libhdf5_la_OBJECTS = H5.lo H5checksum.lo H5dbg.lo H5system.lo \
H5HFdtable.lo H5HFhdr.lo H5HFhuge.lo H5HFiblock.lo H5HFiter.lo \
H5HFman.lo H5HFsection.lo H5HFspace.lo H5HFstat.lo H5HFtest.lo \
H5HFtiny.lo H5HG.lo H5HGcache.lo H5HGdbg.lo H5HL.lo \
- H5HLcache.lo H5HLdbg.lo H5HP.lo H5I.lo H5L.lo H5Lexternal.lo \
- H5MF.lo H5MFaggr.lo H5MFdbg.lo H5MFsection.lo H5MM.lo H5MP.lo \
- H5MPtest.lo H5O.lo H5Oainfo.lo H5Oalloc.lo H5Oattr.lo \
- H5Oattribute.lo H5Obogus.lo H5Obtreek.lo H5Ocache.lo \
- H5Ocont.lo H5Ocopy.lo H5Odbg.lo H5Odrvinfo.lo H5Odtype.lo \
- H5Oefl.lo H5Ofill.lo H5Ofsinfo.lo H5Oginfo.lo H5Olayout.lo \
- H5Olinfo.lo H5Olink.lo H5Omessage.lo H5Omtime.lo H5Oname.lo \
- H5Onull.lo H5Opline.lo H5Orefcount.lo H5Osdspace.lo \
+ H5HLcache.lo H5HLdbg.lo H5HLint.lo H5HP.lo H5I.lo H5L.lo \
+ H5Lexternal.lo H5MF.lo H5MFaggr.lo H5MFdbg.lo H5MFsection.lo \
+ H5MM.lo H5MP.lo H5MPtest.lo H5O.lo H5Oainfo.lo H5Oalloc.lo \
+ H5Oattr.lo H5Oattribute.lo H5Obogus.lo H5Obtreek.lo \
+ H5Ocache.lo H5Ocont.lo H5Ocopy.lo H5Odbg.lo H5Odrvinfo.lo \
+ H5Odtype.lo H5Oefl.lo H5Ofill.lo H5Ofsinfo.lo H5Oginfo.lo \
+ H5Olayout.lo H5Olinfo.lo H5Olink.lo H5Omessage.lo H5Omtime.lo \
+ H5Oname.lo H5Onull.lo H5Opline.lo H5Orefcount.lo H5Osdspace.lo \
H5Oshared.lo H5Ostab.lo H5Oshmesg.lo H5Otest.lo H5Ounknown.lo \
H5P.lo H5Pacpl.lo H5Pdapl.lo H5Pdcpl.lo H5Pdeprec.lo \
H5Pdxpl.lo H5Pfapl.lo H5Pfcpl.lo H5Pfmpl.lo H5Pgcpl.lo \
@@ -486,7 +486,7 @@ libhdf5_la_SOURCES = H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
H5HFhdr.c H5HFhuge.c H5HFiblock.c H5HFiter.c H5HFman.c H5HFsection.c \
H5HFspace.c H5HFstat.c H5HFtest.c H5HFtiny.c \
H5HG.c H5HGcache.c H5HGdbg.c \
- H5HL.c H5HLcache.c H5HLdbg.c \
+ H5HL.c H5HLcache.c H5HLdbg.c H5HLint.c \
H5HP.c H5I.c H5L.c H5Lexternal.c \
H5MF.c H5MFaggr.c H5MFdbg.c H5MFsection.c \
H5MM.c H5MP.c H5MPtest.c \
@@ -792,6 +792,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HL.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HLcache.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HLdbg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HLint.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HP.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5I.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5L.Plo@am__quote@