diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/H5AC.c | 13 | ||||
-rw-r--r-- | src/H5ACprivate.h | 3 | ||||
-rw-r--r-- | src/H5C.c | 6 | ||||
-rw-r--r-- | src/H5Cpkg.h | 2 | ||||
-rw-r--r-- | src/H5Dlayout.c | 6 | ||||
-rw-r--r-- | src/H5Fsuper_cache.c | 5 | ||||
-rw-r--r-- | src/H5Gent.c | 2 | ||||
-rw-r--r-- | src/H5Glink.c | 60 | ||||
-rw-r--r-- | src/H5Gnode.c | 44 | ||||
-rw-r--r-- | src/H5Gpkg.h | 5 | ||||
-rw-r--r-- | src/H5Gstab.c | 39 | ||||
-rw-r--r-- | src/H5Gtest.c | 2 | ||||
-rw-r--r-- | src/H5HL.c | 591 | ||||
-rw-r--r-- | src/H5HLcache.c | 810 | ||||
-rw-r--r-- | src/H5HLdbg.c | 26 | ||||
-rw-r--r-- | src/H5HLint.c | 417 | ||||
-rw-r--r-- | src/H5HLpkg.h | 97 | ||||
-rw-r--r-- | src/H5HLprivate.h | 4 | ||||
-rw-r--r-- | src/H5Oefl.c | 10 | ||||
-rwxr-xr-x | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/Makefile.in | 19 |
21 files changed, 1613 insertions, 550 deletions
@@ -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 */ @@ -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(<able) < 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) @@ -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@ |