From 86d40d2265865e2c601204ca50f9528543b96caa Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Thu, 7 Jan 2010 17:45:21 -0500 Subject: [svn-r18072] Description: Bring r18071 from metadata journaling merge branch: Refactor local heap routines with changes from metadata journaling branch, along with other misc. changes as the changes on the metadata journaling branch are being converged with the current state of the trunk. Tested on: FreeBSD/32 6.3 (duty) in debug mode FreeBSD/64 6.3 (liberty) w/C++ & FORTRAN, in debug mode Linux/32 2.6 (jam) w/PGI compilers, w/default API=1.8.x, w/C++ & FORTRAN, w/threadsafe, in debug mode Linux/64-amd64 2.6 (amani) w/Intel compilers, w/default API=1.6.x, w/C++ & FORTRAN, in production mode Solaris/32 2.10 (linew) w/deprecated symbols disabled, w/C++ & FORTRAN, w/szip filter, in production mode Linux/64-ia64 2.6 (cobalt) w/Intel compilers, w/C++ & FORTRAN, in production mode Linux/64-ia64 2.4 (tg-login3) w/parallel, w/FORTRAN, in debug mode Linux/64-amd64 2.6 (abe) w/parallel, w/FORTRAN, in production mode Mac OS X/32 10.6.2 (amazon) in debug mode Mac OS X/32 10.6.2 (amazon) w/C++ & FORTRAN, w/threadsafe, in production mode --- MANIFEST | 1 + configure | 2 +- src/H5AC.c | 13 +- src/H5ACprivate.h | 3 +- src/H5C.c | 6 +- src/H5Cpkg.h | 2 +- src/H5Dlayout.c | 6 +- src/H5Fsuper_cache.c | 5 +- src/H5Gent.c | 2 +- src/H5Glink.c | 60 +--- src/H5Gnode.c | 44 +-- src/H5Gpkg.h | 5 +- src/H5Gstab.c | 39 ++- src/H5Gtest.c | 2 +- src/H5HL.c | 591 +++++++++++++++++++++++++++---------- src/H5HLcache.c | 810 ++++++++++++++++++++++++++++++++++++--------------- src/H5HLdbg.c | 26 +- src/H5HLint.c | 417 ++++++++++++++++++++++++++ src/H5HLpkg.h | 97 +++++- src/H5HLprivate.h | 4 +- src/H5Oefl.c | 10 +- src/Makefile.am | 2 +- src/Makefile.in | 19 +- test/lheap.c | 6 +- 24 files changed, 1618 insertions(+), 554 deletions(-) create mode 100644 src/H5HLint.c diff --git a/MANIFEST b/MANIFEST index 718c91f..62c3aaa 100644 --- a/MANIFEST +++ b/MANIFEST @@ -620,6 +620,7 @@ ./src/H5HL.c ./src/H5HLcache.c ./src/H5HLdbg.c +./src/H5HLint.c ./src/H5HLpkg.h ./src/H5HLprivate.h ./src/H5HLpublic.h diff --git a/configure b/configure index d34155c..c255150 100755 --- a/configure +++ b/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Id: configure.in 18047 2009-12-20 13:32:29Z hdftest . +# From configure.in Id: configure.in 18059 2010-01-03 13:39:26Z hdftest . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.64 for HDF5 1.9.57. # diff --git a/src/H5AC.c b/src/H5AC.c index cbe4dd0..e2e0364 100644 --- a/src/H5AC.c +++ b/src/H5AC.c @@ -480,7 +480,8 @@ static const char * H5AC_entry_type_names[H5AC_NTYPES] = { "B-tree nodes", "symbol table nodes", - "local heaps", + "local heap prefixes", + "local heap data blocks", "global heaps", "object headers", "v2 B-tree headers", @@ -521,11 +522,11 @@ H5AC_create(const H5F_t *f, FUNC_ENTER_NOAPI(H5AC_create, FAIL) - HDassert ( f ); - HDassert ( NULL == f->shared->cache ); - HDassert ( config_ptr != NULL ) ; - HDassert ( NELMTS(H5AC_entry_type_names) == H5AC_NTYPES); - HDassert ( H5C__MAX_NUM_TYPE_IDS == H5AC_NTYPES); + HDassert(f); + HDassert(NULL == f->shared->cache); + HDassert(config_ptr != NULL) ; + HDcompile_assert(NELMTS(H5AC_entry_type_names) == H5AC_NTYPES); + HDcompile_assert(H5C__MAX_NUM_TYPE_IDS == H5AC_NTYPES); result = H5AC_validate_config(config_ptr); diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h index d36069a..cdb547e 100644 --- a/src/H5ACprivate.h +++ b/src/H5ACprivate.h @@ -49,7 +49,8 @@ typedef enum { H5AC_BT_ID = 0, /*B-tree nodes */ H5AC_SNODE_ID, /*symbol table nodes */ - H5AC_LHEAP_ID, /*local heap */ + H5AC_LHEAP_PRFX_ID, /*local heap prefix */ + H5AC_LHEAP_DBLK_ID, /*local heap data block */ H5AC_GHEAP_ID, /*global heap */ H5AC_OHDR_ID, /*object header */ H5AC_BT2_HDR_ID, /*v2 B-tree header */ diff --git a/src/H5C.c b/src/H5C.c index ef58012..d40cd62 100644 --- a/src/H5C.c +++ b/src/H5C.c @@ -11477,9 +11477,9 @@ H5C_load_entry(H5F_t * f, * * with: * - * HDassert( ( entry_ptr->is_dirty == FALSE ) || ( type->id == 4 ) ); + * HDassert( ( entry_ptr->is_dirty == FALSE ) || ( type->id == 5 ) ); * - * Note that type id 4 is associated with object headers in the metadata + * Note that type id 5 is associated with object headers in the metadata * cache. * * When we get to using H5C for other purposes, we may wish to @@ -11487,7 +11487,7 @@ H5C_load_entry(H5F_t * f, * metadata cache. */ - HDassert( ( entry_ptr->is_dirty == FALSE ) || ( type->id == 4 ) ); + HDassert( ( entry_ptr->is_dirty == FALSE ) || ( type->id == 5 ) ); #ifndef NDEBUG entry_ptr->magic = H5C__H5C_CACHE_ENTRY_T_MAGIC; #endif /* NDEBUG */ diff --git a/src/H5Cpkg.h b/src/H5Cpkg.h index 4bc105d..719dec9 100644 --- a/src/H5Cpkg.h +++ b/src/H5Cpkg.h @@ -857,7 +857,7 @@ ****************************************************************************/ #define H5C__H5C_T_MAGIC 0x005CAC0E -#define H5C__MAX_NUM_TYPE_IDS 25 +#define H5C__MAX_NUM_TYPE_IDS 26 #define H5C__PREFIX_LEN 32 struct H5C_t diff --git a/src/H5Dlayout.c b/src/H5Dlayout.c index d6b7619..5a5a9f6 100644 --- a/src/H5Dlayout.c +++ b/src/H5Dlayout.c @@ -254,7 +254,7 @@ H5D_layout_oh_create(H5F_t *file, hid_t dxpl_id, H5O_t *oh, H5D_t *dset, /* Insert "empty" name first */ if((size_t)(-1) == H5HL_insert(file, dxpl_id, heap, (size_t)1, "")) { - H5HL_unprotect(file, dxpl_id, heap, efl->heap_addr); + H5HL_unprotect(file, heap); HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert file name into heap") } /* end if */ @@ -264,7 +264,7 @@ H5D_layout_oh_create(H5F_t *file, hid_t dxpl_id, H5O_t *oh, H5D_t *dset, /* Insert file name into heap */ if((size_t)(-1) == (offset = H5HL_insert(file, dxpl_id, heap, HDstrlen(efl->slot[u].name) + 1, efl->slot[u].name))) { - H5HL_unprotect(file, dxpl_id, heap, efl->heap_addr); + H5HL_unprotect(file, heap); HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert file name into heap") } /* end if */ @@ -274,7 +274,7 @@ H5D_layout_oh_create(H5F_t *file, hid_t dxpl_id, H5O_t *oh, H5D_t *dset, } /* end for */ /* Release the heap */ - if(H5HL_unprotect(file, dxpl_id, heap, efl->heap_addr) < 0) + if(H5HL_unprotect(file, heap) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTUNPROTECT, FAIL, "unable to unprotect EFL file name heap") heap = NULL; diff --git a/src/H5Fsuper_cache.c b/src/H5Fsuper_cache.c index d2aaef8..3057d09 100644 --- a/src/H5Fsuper_cache.c +++ b/src/H5Fsuper_cache.c @@ -155,7 +155,8 @@ H5F_sblock_load(H5F_t *f, hid_t dxpl_id, haddr_t UNUSED addr, const void UNUSED /* Read fixed-size portion of the superblock */ p = sbuf; - if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, fixed_size) < 0) + H5_CHECK_OVERFLOW(fixed_size, size_t, haddr_t); + if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, (haddr_t)fixed_size) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "set end of space allocation request failed") if(H5FD_read(lf, dxpl_id, H5FD_MEM_SUPER, (haddr_t)0, fixed_size, p) < 0) HGOTO_ERROR(H5E_FILE, H5E_READERROR, NULL, "unable to read superblock") @@ -182,7 +183,7 @@ H5F_sblock_load(H5F_t *f, hid_t dxpl_id, haddr_t UNUSED addr, const void UNUSED HDassert(fixed_size + variable_size <= sizeof(sbuf)); /* Read in variable-sized portion of superblock */ - if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, fixed_size + variable_size) < 0) + if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, (haddr_t)fixed_size + variable_size) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "set end of space allocation request failed") if(H5FD_read(lf, dxpl_id, H5FD_MEM_SUPER, (haddr_t)fixed_size, variable_size, p) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to read superblock") diff --git a/src/H5Gent.c b/src/H5Gent.c index 2b499fe..18883ac 100644 --- a/src/H5Gent.c +++ b/src/H5Gent.c @@ -471,7 +471,7 @@ H5G_ent_debug(const H5G_entry_t *ent, FILE *stream, int indent, int fwidth, "Link value offset:", (unsigned long)(ent->cache.slink.lval_offset)); if(heap) { - lval = (const char *)H5HL_offset_into(ent->file, heap, ent->cache.slink.lval_offset); + lval = (const char *)H5HL_offset_into(heap, ent->cache.slink.lval_offset); HDfprintf(stream, "%*s%-*s %s\n", nested_indent, "", nested_fwidth, "Link value:", lval); diff --git a/src/H5Glink.c b/src/H5Glink.c index 488c05b..f5ad7d9 100644 --- a/src/H5Glink.c +++ b/src/H5Glink.c @@ -218,13 +218,12 @@ H5G_link_cmp_corder_dec(const void *lnk1, const void *lnk2) *------------------------------------------------------------------------- */ herr_t -H5G_ent_to_link(H5F_t *f, H5O_link_t *lnk, const H5HL_t *heap, +H5G_ent_to_link(H5O_link_t *lnk, const H5HL_t *heap, const H5G_entry_t *ent, const char *name) { FUNC_ENTER_NOAPI_NOFUNC(H5G_ent_to_link) /* check arguments */ - HDassert(f); HDassert(lnk); HDassert(heap); HDassert(ent); @@ -241,7 +240,7 @@ H5G_ent_to_link(H5F_t *f, H5O_link_t *lnk, const H5HL_t *heap, if(ent->type == H5G_CACHED_SLINK) { const char *s; /* Pointer to link value */ - s = (const char *)H5HL_offset_into(f, heap, ent->cache.slink.lval_offset); + s = (const char *)H5HL_offset_into(heap, ent->cache.slink.lval_offset); HDassert(s); /* Copy the link value */ @@ -263,61 +262,6 @@ H5G_ent_to_link(H5F_t *f, H5O_link_t *lnk, const H5HL_t *heap, /*------------------------------------------------------------------------- - * Function: H5G_ent_to_info - * - * Purpose: Make link info for a symbol table entry - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@hdfgroup.org - * Nov 16 2006 - * - *------------------------------------------------------------------------- - */ -herr_t -H5G_ent_to_info(H5F_t *f, H5L_info_t *info, const H5HL_t *heap, - const H5G_entry_t *ent) -{ - FUNC_ENTER_NOAPI_NOFUNC(H5G_ent_to_info) - - /* check arguments */ - HDassert(f); - HDassert(info); - HDassert(heap); - HDassert(ent); - - /* Set (default) common info for info */ - info->cset = H5F_DEFAULT_CSET; - info->corder = 0; - info->corder_valid = FALSE; /* Creation order not valid for this link */ - - /* Object is a symbolic or hard link */ - if(ent->type == H5G_CACHED_SLINK) { - const char *s; /* Pointer to link value */ - - s = (const char *)H5HL_offset_into(f, heap, ent->cache.slink.lval_offset); - HDassert(s); - - /* Get the link value size */ - info->u.val_size = HDstrlen(s) + 1; - - /* Set link type */ - info->type = H5L_TYPE_SOFT; - } /* end if */ - else { - /* Set address of object */ - info->u.address = ent->header; - - /* Set link type */ - info->type = H5L_TYPE_HARD; - } /* end else */ - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5G_ent_to_info() */ - - -/*------------------------------------------------------------------------- * Function: H5G_link_to_info * * Purpose: Retrieve information from a link object diff --git a/src/H5Gnode.c b/src/H5Gnode.c index ce41727..ca6cb6c 100644 --- a/src/H5Gnode.c +++ b/src/H5Gnode.c @@ -218,8 +218,8 @@ H5G_node_encode_key(const H5F_t *f, const H5B_t UNUSED *bt, uint8_t *raw, void * *------------------------------------------------------------------------- */ static herr_t -H5G_node_debug_key(FILE *stream, H5F_t *f, hid_t UNUSED dxpl_id, int indent, - int fwidth, const void *_key, const void *_udata) +H5G_node_debug_key(FILE *stream, H5F_t UNUSED *f, hid_t UNUSED dxpl_id, + int indent, int fwidth, const void *_key, const void *_udata) { const H5G_node_key_t *key = (const H5G_node_key_t *) _key; const H5G_bt_common_t *udata = (const H5G_bt_common_t *) _udata; @@ -236,7 +236,7 @@ H5G_node_debug_key(FILE *stream, H5F_t *f, hid_t UNUSED dxpl_id, int indent, HDfprintf(stream, "%*s%-*s ", indent, "", fwidth, "Name:"); - s = (const char *)H5HL_offset_into(f, udata->heap, key->offset); + s = (const char *)H5HL_offset_into(udata->heap, key->offset); HDfprintf(stream, "%s\n", s); } /* end if */ else @@ -367,7 +367,7 @@ done: *------------------------------------------------------------------------- */ static int -H5G_node_cmp2(H5F_t *f, hid_t UNUSED dxpl_id, void *_lt_key, void *_udata, +H5G_node_cmp2(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, void *_lt_key, void *_udata, void *_rt_key) { H5G_bt_common_t *udata = (H5G_bt_common_t *) _udata; @@ -385,7 +385,7 @@ H5G_node_cmp2(H5F_t *f, hid_t UNUSED dxpl_id, void *_lt_key, void *_udata, HDassert(rt_key); /* Get base address of heap */ - base = (const char *)H5HL_offset_into(f, udata->heap, (size_t)0); + base = (const char *)H5HL_offset_into(udata->heap, (size_t)0); HDassert(base); /* Get pointers to string names */ @@ -427,7 +427,7 @@ H5G_node_cmp2(H5F_t *f, hid_t UNUSED dxpl_id, void *_lt_key, void *_udata, *------------------------------------------------------------------------- */ static int -H5G_node_cmp3(H5F_t *f, hid_t UNUSED dxpl_id, void *_lt_key, void *_udata, +H5G_node_cmp3(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, void *_lt_key, void *_udata, void *_rt_key) { H5G_bt_common_t *udata = (H5G_bt_common_t *) _udata; @@ -445,7 +445,7 @@ H5G_node_cmp3(H5F_t *f, hid_t UNUSED dxpl_id, void *_lt_key, void *_udata, HDassert(rt_key); /* Get base address of heap */ - base = (const char *)H5HL_offset_into(f, udata->heap, (size_t)0); + base = (const char *)H5HL_offset_into(udata->heap, (size_t)0); HDassert(base); /* left side */ @@ -517,7 +517,7 @@ H5G_node_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *_lt_key HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, FAIL, "unable to protect symbol table node") /* Get base address of heap */ - base = (const char *)H5HL_offset_into(f, udata->common.heap, (size_t)0); + base = (const char *)H5HL_offset_into(udata->common.heap, (size_t)0); HDassert(base); /* @@ -623,7 +623,7 @@ H5G_node_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR, "unable to protect symbol table node") /* Get base address of heap */ - base = (const char *)H5HL_offset_into(f, udata->common.heap, (size_t)0); + base = (const char *)H5HL_offset_into(udata->common.heap, (size_t)0); HDassert(base); /* @@ -791,7 +791,7 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/, const char *base; /* Base of heap */ /* Get base address of heap */ - base = (const char *)H5HL_offset_into(f, udata->common.heap, (size_t)0); + base = (const char *)H5HL_offset_into(udata->common.heap, (size_t)0); /* Find the name with a binary search */ rt = sn->nsyms; @@ -811,7 +811,7 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/, HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5B_INS_ERROR, "name not found") /* Get a pointer to the name of the link */ - if(NULL == (lnk.name = (char *)H5HL_offset_into(f, udata->common.heap, sn->entry[idx].name_off))) + if(NULL == (lnk.name = (char *)H5HL_offset_into(udata->common.heap, sn->entry[idx].name_off))) HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5B_INS_ERROR, "unable to get link name") /* Set up rest of link structure */ @@ -820,7 +820,7 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/, lnk.cset = H5T_CSET_ASCII; if(sn->entry[idx].type == H5G_CACHED_SLINK) { lnk.type = H5L_TYPE_SOFT; - lnk.u.soft.name = (char *)H5HL_offset_into(f, udata->common.heap, sn->entry[idx].cache.slink.lval_offset); + lnk.u.soft.name = (char *)H5HL_offset_into(udata->common.heap, sn->entry[idx].cache.slink.lval_offset); } /* end if */ else { lnk.type = H5L_TYPE_HARD; @@ -992,11 +992,11 @@ H5G_node_iterate(H5F_t *f, hid_t dxpl_id, const void UNUSED *_lt_key, haddr_t ad const char *name; /* Pointer to link name in heap */ /* Get the pointer to the name of the link in the heap */ - name = (const char *)H5HL_offset_into(f, udata->heap, ents[u].name_off); + name = (const char *)H5HL_offset_into(udata->heap, ents[u].name_off); HDassert(name); /* Convert the entry to a link */ - if(H5G_ent_to_link(f, &lnk, udata->heap, &ents[u], name) < 0) + if(H5G_ent_to_link(&lnk, udata->heap, &ents[u], name) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTCONVERT, H5_ITER_ERROR, "unable to convert symbol table entry to link") /* Make the callback */ @@ -1268,7 +1268,7 @@ H5G_node_copy(H5F_t *f, hid_t dxpl_id, const void UNUSED *_lt_key, haddr_t addr, grp_loc.oloc = (H5O_loc_t *)src_oloc; /* Get pointer to link value in local heap */ - link_name = (char *)H5HL_offset_into(f, heap, tmp_src_ent.cache.slink.lval_offset); + link_name = (char *)H5HL_offset_into(heap, tmp_src_ent.cache.slink.lval_offset); /* Check if the object pointed by the soft link exists in the source file */ if(H5G_loc_info(&grp_loc, link_name, FALSE, &oinfo, H5P_DEFAULT, dxpl_id) >= 0) { @@ -1306,7 +1306,7 @@ H5G_node_copy(H5F_t *f, hid_t dxpl_id, const void UNUSED *_lt_key, haddr_t addr, /* Construct link information for eventual insertion */ lnk.type = H5L_TYPE_SOFT; - lnk.u.soft.name = (char *)H5HL_offset_into(f, heap, src_ent->cache.slink.lval_offset); + lnk.u.soft.name = (char *)H5HL_offset_into(heap, src_ent->cache.slink.lval_offset); } /* else if */ else HDassert(0 && "Unknown entry type"); @@ -1318,7 +1318,7 @@ H5G_node_copy(H5F_t *f, hid_t dxpl_id, const void UNUSED *_lt_key, haddr_t addr, /* lnk.name = name; */ /* This will be set in callback */ /* Determine name of source object */ - name = (const char *)H5HL_offset_into(f, heap, src_ent->name_off); + name = (const char *)H5HL_offset_into(heap, src_ent->name_off); HDassert(name); /* Insert the new object in the destination file's group */ @@ -1328,7 +1328,7 @@ H5G_node_copy(H5F_t *f, hid_t dxpl_id, const void UNUSED *_lt_key, haddr_t addr, } /* end of for (i=0; insyms; 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) diff --git a/src/H5HL.c b/src/H5HL.c index 5951509..aa187ad 100644 --- a/src/H5HL.c +++ b/src/H5HL.c @@ -75,9 +75,6 @@ static herr_t H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap); /* Declare a free list to manage the H5HL_free_t struct */ H5FL_DEFINE(H5HL_free_t); -/* Declare a free list to manage the H5HL_t struct */ -H5FL_DEFINE(H5HL_t); - /* Declare a PQ free list to manage the heap chunk information */ H5FL_BLK_DEFINE(lheap_chunk); @@ -118,8 +115,8 @@ herr_t H5HL_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, haddr_t *addr_p/*out*/) { H5HL_t *heap = NULL; /* Heap created */ + H5HL_prfx_t *prfx = NULL; /* Heap prefix */ hsize_t total_size; /* Total heap size on disk */ - size_t sizeof_hdr; /* Cache H5HL header size for file */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5HL_create, FAIL) @@ -133,21 +130,22 @@ H5HL_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, haddr_t *addr_p/*out*/) size_hint = H5HL_SIZEOF_FREE(f); size_hint = H5HL_ALIGN(size_hint); - /* Cache this for later */ - sizeof_hdr = H5HL_SIZEOF_HDR(f); + /* Allocate memory structure */ + if(NULL == (heap = H5HL_new(H5F_SIZEOF_SIZE(f), H5F_SIZEOF_ADDR(f), H5HL_SIZEOF_HDR(f)))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed") - /* Allocate file version */ - total_size = sizeof_hdr + size_hint; - if(HADDR_UNDEF == (*addr_p = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, total_size))) + /* Allocate file space */ + total_size = heap->prfx_size + size_hint; + if(HADDR_UNDEF == (heap->prfx_addr = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, total_size))) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "unable to allocate file memory") - /* allocate memory version */ - if(NULL == (heap = H5FL_CALLOC(H5HL_t))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed") - heap->addr = *addr_p + (hsize_t)sizeof_hdr; - heap->heap_alloc = size_hint; - if(NULL == (heap->chunk = H5FL_BLK_CALLOC(lheap_chunk, (sizeof_hdr + size_hint)))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed") + /* Initialize info */ + heap->single_cache_obj = TRUE; + heap->dblk_addr = heap->prfx_addr + (hsize_t)heap->prfx_size; + heap->dblk_size = size_hint; + if(size_hint) + if(NULL == (heap->dblk_image = H5FL_BLK_CALLOC(lheap_chunk, size_hint))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed") /* free list */ if(size_hint) { @@ -160,17 +158,32 @@ H5HL_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, haddr_t *addr_p/*out*/) else heap->freelist = NULL; + /* Allocate the heap prefix */ + if(NULL == (prfx = H5HL_prfx_new(heap))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed") + /* Add to cache */ - if(H5AC_set(f, dxpl_id, H5AC_LHEAP, *addr_p, heap, H5AC__NO_FLAGS_SET) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to cache heap") + if(H5AC_set(f, dxpl_id, H5AC_LHEAP_PRFX, heap->prfx_addr, prfx, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to cache local heap prefix") + + /* Set address to return */ + *addr_p = heap->prfx_addr; done: if(ret_value < 0) { - if(H5F_addr_defined(*addr_p)) - H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, *addr_p, total_size); - if(heap) - if(H5HL_dest(f, heap) < 0) - HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap") + if(prfx) { + if(H5HL_prfx_dest(prfx) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap prefix") + } /* end if */ + else { + if(heap) { + if(H5F_addr_defined(heap->prfx_addr)) + if(H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, heap->prfx_addr, total_size) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "can't release heap data?") + if(H5HL_dest(heap) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap") + } /* end if */ + } /* end else */ } /* end if */ FUNC_LEAVE_NOAPI(ret_value) @@ -178,6 +191,110 @@ done: /*------------------------------------------------------------------------- + * Function: H5HL_dblk_realloc + * + * Purpose: Reallocate data block for heap + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Oct 12 2008 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HL_dblk_realloc(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t new_heap_size) +{ + H5HL_dblk_t *dblk; /* Local heap data block */ + haddr_t old_addr; /* Old location of heap data block */ + haddr_t new_addr; /* New location of heap data block */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HL_dblk_realloc) + + /* check arguments */ + HDassert(heap); + HDassert(new_heap_size > 0); + + /* Release old space on disk */ + old_addr = heap->dblk_addr; + H5_CHECK_OVERFLOW(heap->dblk_size, size_t, hsize_t); + if(H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, old_addr, (hsize_t)heap->dblk_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "can't release old heap data?") + + /* Allocate new space on disk */ + H5_CHECK_OVERFLOW(new_heap_size, size_t, hsize_t); + if(HADDR_UNDEF == (new_addr = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, (hsize_t)new_heap_size))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "unable to allocate file space for heap") + + /* Check if heap data block actually moved in the file */ + if(H5F_addr_eq(old_addr, new_addr)) { + /* Check if heap data block is contiguous w/prefix */ + if(heap->single_cache_obj) { + /* Sanity check */ + HDassert(H5F_addr_eq(heap->prfx_addr + heap->prfx_size, heap->dblk_addr)); + HDassert(heap->prfx); + + /* Resize the heap prefix in the cache */ + if(H5AC_resize_pinned_entry(f, heap->prfx, (size_t)(heap->prfx_size + new_heap_size)) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, FAIL, "unable to resize heap in cache") + } /* end if */ + else { + /* Sanity check */ + HDassert(H5F_addr_ne(heap->prfx_addr + heap->prfx_size, heap->dblk_addr)); + HDassert(heap->dblk); + + /* Resize the heap data block in the cache */ + if(H5AC_resize_pinned_entry(f, heap->dblk, (size_t)new_heap_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, FAIL, "unable to resize heap in cache") + } /* end else */ + } /* end if */ + else { + /* Check if heap data block was contiguous w/prefix previously */ + if(heap->single_cache_obj) { + /* Create new heap data block */ + if(NULL == (dblk = H5HL_dblk_new(heap))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "unable to allocate local heap data block") + + /* Resize current heap prefix */ + heap->prfx_size = H5HL_SIZEOF_HDR(f); + if(H5AC_resize_pinned_entry(f, heap->prfx, (size_t)heap->prfx_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, FAIL, "unable to resize heap prefix in cache") + + /* Insert data block into cache (pinned) */ + if(H5AC_set(f, dxpl_id, H5AC_LHEAP_DBLK, new_addr, dblk, H5AC__PIN_ENTRY_FLAG) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to cache local heap data block") + dblk = NULL; + + /* Reset 'single cache object' flag */ + heap->single_cache_obj = FALSE; + } /* end if */ + else { + /* Resize the heap data block in the cache */ + /* (ignore [unlikely] case where heap data block ends up + * contiguous w/heap prefix again. + */ + if(H5AC_resize_pinned_entry(f, heap->dblk, (size_t)new_heap_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, FAIL, "unable to resize heap data block in cache") + + /* Relocate the heap data block in the cache */ + if(H5AC_rename(f, H5AC_LHEAP_DBLK, old_addr, new_addr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRENAME, FAIL, "unable to move heap data block in cache") + } /* end else */ + } /* end else */ + + /* Update heap info*/ + heap->dblk_addr = new_addr; + heap->dblk_size = new_heap_size; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HL_dblk_realloc() */ + + +/*------------------------------------------------------------------------- * Function: H5HL_minimize_heap_space * * Purpose: Go through the heap's freelist and determine if we can @@ -195,8 +312,7 @@ done: static herr_t H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap) { - size_t new_heap_size = heap->heap_alloc; /* New size of heap */ - size_t sizeof_hdr; + size_t new_heap_size = heap->dblk_size; /* New size of heap */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5HL_minimize_heap_space, FAIL) @@ -205,8 +321,6 @@ H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap) HDassert(f); HDassert(heap); - sizeof_hdr = H5HL_SIZEOF_HDR(f); /* cache H5HL header size for file */ - /* * Check to see if we can reduce the size of the heap in memory by * eliminating free blocks at the tail of the buffer before flushing the @@ -219,7 +333,7 @@ H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap) /* Search for a free block at the end of the buffer */ for(tmp_fl = heap->freelist; tmp_fl; tmp_fl = tmp_fl->next) /* Check if the end of this free block is at the end of the buffer */ - if(tmp_fl->offset + tmp_fl->size == heap->heap_alloc) { + if(tmp_fl->offset + tmp_fl->size == heap->dblk_size) { last_fl = tmp_fl; break; } /* end if */ @@ -234,7 +348,7 @@ H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap) * buffer size (and the memory buffer is larger than the * minimum size), reduce or eliminate it. */ - if(last_fl->size >= (heap->heap_alloc / 2) && heap->heap_alloc > H5HL_MIN_HEAP) { + if(last_fl->size >= (heap->dblk_size / 2) && heap->dblk_size > H5HL_MIN_HEAP) { /* * Reduce size of buffer until it's too small or would * eliminate the free block @@ -285,30 +399,16 @@ H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap) * data segment of the heap to another contiguous block of disk * storage. */ - if(new_heap_size != heap->heap_alloc) { - haddr_t old_addr = heap->addr, - new_addr; - - HDassert(new_heap_size < heap->heap_alloc); + if(new_heap_size != heap->dblk_size) { + HDassert(new_heap_size < heap->dblk_size); /* Resize the memory buffer */ - if(NULL == (heap->chunk = H5FL_BLK_REALLOC(lheap_chunk, heap->chunk, (sizeof_hdr + new_heap_size)))) + if(NULL == (heap->dblk_image = H5FL_BLK_REALLOC(lheap_chunk, heap->dblk_image, new_heap_size))) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed") - /* Release old space on disk */ - /* (Should be safe to free old heap space first, since it's shrinking -QAK) */ - H5_CHECK_OVERFLOW(heap->heap_alloc, size_t, hsize_t); - if(H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, old_addr, (hsize_t)heap->heap_alloc) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap") - - /* Allocate new space on disk */ - H5_CHECK_OVERFLOW(new_heap_size, size_t, hsize_t); - if(HADDR_UNDEF == (new_addr = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, (hsize_t)new_heap_size))) + /* Reallocate data block in file */ + if(H5HL_dblk_realloc(f, dxpl_id, heap, new_heap_size) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, FAIL, "reallocating data block failed") - - /* Update heap info*/ - heap->addr = new_addr; - heap->heap_alloc = new_heap_size; } /* end if */ done: @@ -319,26 +419,9 @@ done: /*------------------------------------------------------------------------- * Function: H5HL_protect * - * Purpose: This function is a wrapper for the H5AC_protect call. The - * old H5HL_peek call (which this once was) wasn't "safe" - * for FPHDF5. (It'd get a read lock on an object but once - * it got that object, it'd release it keeping the old - * pointer value, which is no longer valid. This won't work - * since the pointer into some metdata block can become - * invalid.) - * - * N.B.: This function is always called in conjunction with - * the H5HL_offset_into function. The return from that - * function is the proper pointer to the heap's object. This - * is done so that the return from this function can be sent - * to H5HL_unprotect. - * - * Return: Success: Ptr to the object. The pointer points to a - * chunk of memory large enough to hold the - * object from the specified offset (usually the - * beginning of the object) to the end of the - * object. Do not attempt to read past the end - * of the object. + * Purpose: This function is a wrapper for the H5AC_protect call. + * + * Return: Success: Non-NULL pointer to the local heap prefix. * Failure: NULL * * Programmer: Bill Wendling @@ -350,7 +433,13 @@ done: H5HL_t * H5HL_protect(H5F_t *f, hid_t dxpl_id, haddr_t addr, H5AC_protect_t rw) { - H5HL_t *ret_value; + H5HL_cache_prfx_ud_t prfx_udata; /* User data for protecting local heap prefix */ + H5HL_prfx_t *prfx = NULL; /* Local heap prefix */ + H5HL_dblk_t *dblk = NULL; /* Local heap data block */ + H5HL_t *heap; /* Heap data structure */ + unsigned prfx_cache_flags = H5AC__NO_FLAGS_SET; /* Cache flags for unprotecting prefix entry */ + unsigned dblk_cache_flags = H5AC__NO_FLAGS_SET; /* Cache flags for unprotecting data block entry */ + H5HL_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5HL_protect, NULL) @@ -358,10 +447,65 @@ H5HL_protect(H5F_t *f, hid_t dxpl_id, haddr_t addr, H5AC_protect_t rw) HDassert(f); HDassert(H5F_addr_defined(addr)); - if(NULL == (ret_value = (H5HL_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, rw))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to load heap") + /* Construct the user data for protect callback */ + prfx_udata.sizeof_size = H5F_SIZEOF_SIZE(f); + prfx_udata.sizeof_addr = H5F_SIZEOF_ADDR(f); + prfx_udata.sizeof_prfx = H5HL_SIZEOF_HDR(f); + prfx_udata.loaded = FALSE; + prfx_udata.free_block = H5HL_FREE_NULL; + + /* Protect the local heap prefix */ + if(NULL == (prfx = (H5HL_prfx_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP_PRFX, addr, NULL, &prfx_udata, rw))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to load heap prefix") + + /* Get the pointer to the heap */ + heap = prfx->heap; + + /* Check if the heap is already pinned in memory */ + /* (for re-entrant situation) */ + if(heap->prots == 0) { + /* Check if heap has separate data block */ + if(heap->single_cache_obj) { + /* Set the flag for pinning the prefix when unprotecting it */ + prfx_cache_flags |= H5AC__PIN_ENTRY_FLAG; + } /* end if */ + else { + H5HL_cache_dblk_ud_t dblk_udata; /* User data for protecting local heap data block */ + + /* Construct the user data for protect callback */ + dblk_udata.heap = heap; + dblk_udata.free_block = prfx_udata.loaded ? prfx_udata.free_block : + (heap->freelist ? heap->freelist->offset : H5HL_FREE_NULL); + dblk_udata.loaded = FALSE; + + /* Protect the local heap data block */ + if(NULL == (dblk = (H5HL_dblk_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP_DBLK, heap->dblk_addr, NULL, &dblk_udata, rw))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to load heap data block") + + /* Pin the prefix, if the data block was loaded from file */ + if(dblk_udata.loaded) + prfx_cache_flags |= H5AC__PIN_ENTRY_FLAG; + + /* Set the flag for pinning the data block when unprotecting it */ + dblk_cache_flags |= H5AC__PIN_ENTRY_FLAG; + } /* end if */ + } /* end if */ + + /* Increment # of times heap is protected */ + heap->prots++; + + /* Set return value */ + ret_value = heap; done: + /* Release the prefix from the cache, now pinned */ + if(prfx && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP_PRFX, heap->prfx_addr, prfx, prfx_cache_flags) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, NULL, "unable to release local heap prefix") + + /* Release the data block from the cache, now pinned */ + if(dblk && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP_DBLK, heap->dblk_addr, dblk, dblk_cache_flags) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, NULL, "unable to release local heap data block") + FUNC_LEAVE_NOAPI(ret_value) } /* end H5HL_protect() */ @@ -382,7 +526,7 @@ done: *------------------------------------------------------------------------- */ void * -H5HL_offset_into(H5F_t *f, const H5HL_t *heap, size_t offset) +H5HL_offset_into(const H5HL_t *heap, size_t offset) { /* * We need to have called some other function before this to get a @@ -390,11 +534,11 @@ H5HL_offset_into(H5F_t *f, const H5HL_t *heap, size_t offset) */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_offset_into) - HDassert(f); + /* Sanity check */ HDassert(heap); - HDassert(offset < heap->heap_alloc); + HDassert(offset < heap->dblk_size); - FUNC_LEAVE_NOAPI(heap->chunk + H5HL_SIZEOF_HDR(f) + offset) + FUNC_LEAVE_NOAPI(heap->dblk_image + offset) } /* end H5HL_offset_into() */ @@ -413,7 +557,7 @@ H5HL_offset_into(H5F_t *f, const H5HL_t *heap, size_t offset) *------------------------------------------------------------------------- */ herr_t -H5HL_unprotect(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, haddr_t addr) +H5HL_unprotect(H5F_t *f, H5HL_t *heap) { herr_t ret_value = SUCCEED; @@ -422,10 +566,28 @@ H5HL_unprotect(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, haddr_t addr) /* check arguments */ HDassert(f); HDassert(heap); - HDassert(H5F_addr_defined(addr)); - if(H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, (void *)heap, H5AC__NO_FLAGS_SET) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release local heap") + /* Decrement # of times heap is protected */ + heap->prots--; + + /* Check for last unprotection of heap */ + if(heap->prots == 0) { + /* Check for separate heap data block */ + if(heap->single_cache_obj) { + /* Mark local heap prefix as evictable again */ + if(H5AC_unpin_entry(f, heap->prfx) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPIN, FAIL, "unable to unpin local heap data block") + } /* end if */ + else { + /* Sanity check */ + HDassert(heap->dblk); + + /* Mark local heap data block as evictable again */ + /* (data block still pins prefix) */ + if(H5AC_unpin_entry(f, heap->dblk) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPIN, FAIL, "unable to unpin local heap data block") + } /* end else */ + } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) @@ -464,12 +626,55 @@ H5HL_remove_free(H5HL_t *heap, H5HL_free_t *fl) /*------------------------------------------------------------------------- + * Function: H5HL_dirty + * + * Purpose: Mark heap as dirty + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Oct 12 2008 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HL_dirty(H5F_t *f, H5HL_t *heap) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HL_dirty) + + /* check arguments */ + HDassert(f); + HDassert(heap); + HDassert(heap->prfx); + + /* Mark heap data block as dirty, if there is one */ + if(!heap->single_cache_obj) { + /* Sanity check */ + HDassert(heap->dblk); + + if(H5AC_mark_pinned_or_protected_entry_dirty(f, heap->dblk) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTMARKDIRTY, FAIL, "unable to mark heap data block as dirty") + } /* end if */ + + /* Mark heap prefix as dirty */ + if(H5AC_mark_pinned_or_protected_entry_dirty(f, heap->prfx) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTMARKDIRTY, FAIL, "unable to mark heap prefix as dirty") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HL_dirty() */ + + +/*------------------------------------------------------------------------- * Function: H5HL_insert * * Purpose: Inserts a new item into the heap. * * Return: Success: Offset of new item within heap. - * * Failure: UFAIL * * Programmer: Robb Matzke @@ -485,7 +690,6 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t buf_size, const void * size_t offset = 0; size_t need_size; hbool_t found; - size_t sizeof_hdr; /* Cache H5HL header size for file */ size_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5HL_insert, UFAIL) @@ -502,12 +706,9 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t buf_size, const void * * so we just accept that an extra flush of the heap info could occur * if an error occurs -QAK) */ - if(H5AC_mark_pinned_or_protected_entry_dirty(f, heap) < 0) + if(H5HL_dirty(f, heap) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTMARKDIRTY, UFAIL, "unable to mark heap as dirty") - /* Cache this for later */ - sizeof_hdr = H5HL_SIZEOF_HDR(f); - /* * In order to keep the free list descriptors aligned on word boundaries, * whatever that might mean, we round the size up to the next multiple of @@ -550,12 +751,13 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t buf_size, const void * */ if(found == FALSE) { size_t need_more; /* How much more space we need */ - size_t new_heap_alloc; /* Final size of space allocated for heap */ + size_t new_dblk_size; /* Final size of space allocated for heap data block */ + size_t old_dblk_size; /* Previous size of space allocated for heap data block */ htri_t extended; /* Whether the local heap's data segment on disk was extended */ /* At least double the heap's size, making certain there's enough room * for the new object */ - need_more = MAX(need_size, heap->heap_alloc); + need_more = MAX(need_size, heap->dblk_size); /* If there is no last free block or it's not at the end of the heap, * and the amount of space to allocate is not big enough to include at @@ -563,33 +765,46 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t buf_size, const void * * space requested to just the amount of space needed. (Generally * speaking, this only occurs when the heap is small -QAK) */ - if(!(last_fl && last_fl->offset + last_fl->size == heap->heap_alloc) + if(!(last_fl && last_fl->offset + last_fl->size == heap->dblk_size) && (need_more < (need_size + H5HL_SIZEOF_FREE(f)))) need_more = need_size; - new_heap_alloc = heap->heap_alloc + need_more; - HDassert(heap->heap_alloc < new_heap_alloc); - H5_CHECK_OVERFLOW(heap->heap_alloc, size_t, hsize_t); - H5_CHECK_OVERFLOW(new_heap_alloc, size_t, hsize_t); + new_dblk_size = heap->dblk_size + need_more; + HDassert(heap->dblk_size < new_dblk_size); + old_dblk_size = heap->dblk_size; + H5_CHECK_OVERFLOW(heap->dblk_size, size_t, hsize_t); + H5_CHECK_OVERFLOW(new_dblk_size, size_t, hsize_t); /* Extend current heap if possible */ - extended = H5MF_try_extend(f, dxpl_id, H5FD_MEM_LHEAP, heap->addr, (hsize_t)(heap->heap_alloc), (hsize_t)need_more); + extended = H5MF_try_extend(f, dxpl_id, H5FD_MEM_LHEAP, heap->dblk_addr, (hsize_t)(heap->dblk_size), (hsize_t)need_more); if(extended < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, UFAIL, "error trying to extend heap") - /* If we couldn't extend the heap, release old chunk and allocate a new one */ - if(extended == FALSE) { - /* Release old space on disk */ - if(H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, heap->addr, (hsize_t)heap->heap_alloc) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, UFAIL, "unable to free local heap") - - /* allocate new disk space for the heap */ - if((heap->addr = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, (hsize_t)new_heap_alloc)) == HADDR_UNDEF) - HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, UFAIL, "unable to allocate file space for heap") + /* Check if we extended the heap data block in file */ + if(extended == TRUE) { + /* Check for prefix & data block contiguous */ + if(heap->single_cache_obj) { + /* Resize prefix+data block */ + if(H5AC_resize_pinned_entry(f, heap->prfx, (size_t)(heap->prfx_size + new_dblk_size)) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, UFAIL, "unable to resize heap prefix in cache") + } /* end if */ + else { + /* Resize 'standalone' data block */ + if(H5AC_resize_pinned_entry(f, heap->dblk, (size_t)new_dblk_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, UFAIL, "unable to resize heap data block in cache") + } /* end else */ + + /* Note new size */ + heap->dblk_size = new_dblk_size; + } /* end if */ + else { /* ...if we can't, allocate a new chunk & release the old */ + /* Reallocate data block in file */ + if(H5HL_dblk_realloc(f, dxpl_id, heap, new_dblk_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, UFAIL, "reallocating data block failed") } /* end if */ /* If the last free list in the heap is at the end of the heap, extend it */ - if(last_fl && last_fl->offset + last_fl->size == heap->heap_alloc) { + if(last_fl && last_fl->offset + last_fl->size == old_dblk_size) { /* * Increase the size of the last free block. */ @@ -614,11 +829,11 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t buf_size, const void * * Create a new free list element large enough that we can * take some space out of it right away. */ - offset = heap->heap_alloc; + offset = old_dblk_size; if(need_more - need_size >= H5HL_SIZEOF_FREE(f)) { if(NULL == (fl = H5FL_MALLOC(H5HL_free_t))) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, UFAIL, "memory allocation failed") - fl->offset = heap->heap_alloc + need_size; + fl->offset = old_dblk_size + need_size; fl->size = need_more - need_size; HDassert(fl->offset == H5HL_ALIGN(fl->offset)); HDassert(fl->size == H5HL_ALIGN(fl->size)); @@ -640,21 +855,20 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t buf_size, const void * if (H5DEBUG(HL)) { fprintf(H5DEBUG(HL), "H5HL: resize mem buf from %lu to %lu bytes\n", - (unsigned long)(heap->heap_alloc), - (unsigned long)(heap->heap_alloc + need_more)); + (unsigned long)(old_dblk_size), + (unsigned long)(old_dblk_size + need_more)); } #endif - heap->heap_alloc = new_heap_alloc; - if(NULL == (heap->chunk = H5FL_BLK_REALLOC(lheap_chunk, heap->chunk, (sizeof_hdr + heap->heap_alloc)))) + if(NULL == (heap->dblk_image = H5FL_BLK_REALLOC(lheap_chunk, heap->dblk_image, heap->dblk_size))) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, UFAIL, "memory allocation failed") /* Clear new section so junk doesn't appear in the file */ /* (Avoid clearing section which will be overwritten with newly inserted data) */ - HDmemset(heap->chunk + sizeof_hdr + offset + buf_size, 0, (new_heap_alloc - (offset + buf_size))); + HDmemset(heap->dblk_image + offset + buf_size, 0, (new_dblk_size - (offset + buf_size))); } /* end if */ /* Copy the data into the heap */ - HDmemcpy(heap->chunk + sizeof_hdr + offset, buf, buf_size); + HDmemcpy(heap->dblk_image + offset, buf, buf_size); /* Set return value */ ret_value = offset; @@ -704,8 +918,8 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size) size = H5HL_ALIGN(size); - HDassert(offset < heap->heap_alloc); - HDassert(offset + size <= heap->heap_alloc); + HDassert(offset < heap->dblk_size); + HDassert(offset + size <= heap->dblk_size); /* Mark heap as dirty in cache */ /* (A bit early in the process, but it's difficult to determine in the @@ -713,7 +927,7 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size) * so we just accept that an extra flush of the heap info could occur * if an error occurs -QAK) */ - if(H5AC_mark_pinned_or_protected_entry_dirty(f, heap) < 0) + if(H5HL_dirty(f, heap) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTMARKDIRTY, FAIL, "unable to mark heap as dirty") /* @@ -738,8 +952,8 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size) HDassert(fl->offset == H5HL_ALIGN(fl->offset)); HDassert(fl->size == H5HL_ALIGN(fl->size)); fl2 = H5HL_remove_free(heap, fl2); - if(((fl->offset + fl->size) == heap->heap_alloc ) && - ((2 * fl->size) > heap->heap_alloc )) { + if(((fl->offset + fl->size) == heap->dblk_size) && + ((2 * fl->size) > heap->dblk_size)) { if(H5HL_minimize_heap_space(f, dxpl_id, heap) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "heap size minimization failed") } @@ -747,8 +961,8 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size) } fl2 = fl2->next; } - if(((fl->offset + fl->size) == heap->heap_alloc) && - ((2 * fl->size) > heap->heap_alloc)) { + if(((fl->offset + fl->size) == heap->dblk_size) && + ((2 * fl->size) > heap->dblk_size)) { if(H5HL_minimize_heap_space(f, dxpl_id, heap) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "heap size minimization failed") } @@ -762,8 +976,8 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size) fl->size += fl2->size; HDassert(fl->size == H5HL_ALIGN(fl->size)); fl2 = H5HL_remove_free(heap, fl2); - if(((fl->offset + fl->size) == heap->heap_alloc) && - ((2 * fl->size) > heap->heap_alloc)) { + if(((fl->offset + fl->size) == heap->dblk_size) && + ((2 * fl->size) > heap->dblk_size)) { if(H5HL_minimize_heap_space(f, dxpl_id, heap) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "heap size minimization failed") } /* end if */ @@ -771,8 +985,8 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size) } /* end if */ fl2 = fl2->next; } /* end while */ - if(((fl->offset + fl->size) == heap->heap_alloc) && - ((2 * fl->size) > heap->heap_alloc)) { + if(((fl->offset + fl->size) == heap->dblk_size) && + ((2 * fl->size) > heap->dblk_size)) { if(H5HL_minimize_heap_space(f, dxpl_id, heap) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "heap size minimization failed") } /* end if */ @@ -811,8 +1025,8 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size) heap->freelist->prev = fl; heap->freelist = fl; - if(((fl->offset + fl->size) == heap->heap_alloc) && - ((2 * fl->size) > heap->heap_alloc)) { + if(((fl->offset + fl->size) == heap->dblk_size) && + ((2 * fl->size) > heap->dblk_size)) { if(H5HL_minimize_heap_space(f, dxpl_id, heap) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "heap size minimization failed") } /* end if */ @@ -838,9 +1052,12 @@ done: herr_t H5HL_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr) { - H5HL_t *heap = NULL; /* Local heap to delete */ + H5HL_t *heap; /* Local heap to delete */ + H5HL_cache_prfx_ud_t prfx_udata; /* User data for protecting local heap prefix */ + H5HL_prfx_t *prfx = NULL; /* Local heap prefix */ + H5HL_dblk_t *dblk = NULL; /* Local heap data block */ unsigned cache_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting heap */ - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5HL_delete, FAIL) @@ -848,16 +1065,71 @@ H5HL_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr) HDassert(f); HDassert(H5F_addr_defined(addr)); - /* Get heap pointer */ - if(NULL == (heap = (H5HL_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_WRITE))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load heap") + /* Construct the user data for protect callback */ + prfx_udata.sizeof_size = H5F_SIZEOF_SIZE(f); + prfx_udata.sizeof_addr = H5F_SIZEOF_ADDR(f); + prfx_udata.sizeof_prfx = H5HL_SIZEOF_HDR(f); + prfx_udata.loaded = FALSE; + prfx_udata.free_block = H5HL_FREE_NULL; + + /* Protect the local heap prefix */ + if(NULL == (prfx = (H5HL_prfx_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP_PRFX, addr, NULL, &prfx_udata, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load heap prefix") + + /* Get the pointer to the heap */ + heap = prfx->heap; + + /* Check if heap has separate data block */ + if(!heap->single_cache_obj) { + H5HL_cache_dblk_ud_t dblk_udata; /* User data for protecting local heap data block */ + + /* Construct the user data for protect callback */ + dblk_udata.heap = heap; + dblk_udata.free_block = prfx_udata.loaded ? prfx_udata.free_block : + (heap->freelist ? heap->freelist->offset : H5HL_FREE_NULL); + dblk_udata.loaded = FALSE; + + /* Protect the local heap data block */ + if(NULL == (dblk = (H5HL_dblk_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP_DBLK, heap->dblk_addr, NULL, &dblk_udata, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load heap data block") + + /* Pin the prefix, if the data block was loaded from file */ + if(dblk_udata.loaded) { + if(H5AC_pin_protected_entry(f, prfx) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPIN, FAIL, "unable to pin local heap prefix") + } /* end if */ + } /* end if */ - /* Set the cache flags to delete the heap & free its file space */ + /* Check if the heap is contiguous on disk */ + if(heap->single_cache_obj) { + /* Free the contiguous local heap in one call */ + H5_CHECK_OVERFLOW(heap->prfx_size + heap->dblk_size, size_t, hsize_t); + if(H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, addr, (hsize_t)(heap->prfx_size + heap->dblk_size)) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free contiguous local heap") + } /* end if */ + else { + /* Free the local heap's prefix */ + H5_CHECK_OVERFLOW(heap->prfx_size, size_t, hsize_t); + if(H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, heap->prfx_addr, (hsize_t)heap->prfx_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap header") + + /* Free the local heap's data block */ + H5_CHECK_OVERFLOW(heap->dblk_size, size_t, hsize_t); + if(H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, heap->dblk_addr, (hsize_t)heap->dblk_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap data") + } /* end else */ + + /* Set the flags for releasing the prefix and data block */ cache_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG; done: - if(heap && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, heap, cache_flags) < 0) - HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release local heap") + /* Release the data block from the cache, now deleted */ + if(dblk && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP_DBLK, heap->dblk_addr, dblk, cache_flags) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release local heap data block") + + /* Release the prefix from the cache, now deleted */ + if(prfx && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP_PRFX, heap->prfx_addr, prfx, cache_flags) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release local heap prefix") FUNC_LEAVE_NOAPI(ret_value) } /* end H5HL_delete() */ @@ -879,7 +1151,9 @@ done: herr_t H5HL_get_size(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t *size) { - H5HL_t *heap = NULL; /* Heap to query */ + H5HL_cache_prfx_ud_t prfx_udata; /* User data for protecting local heap prefix */ + H5HL_prfx_t *prfx = NULL; /* Local heap prefix */ + H5HL_t *heap; /* Heap data structure */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5HL_get_size, FAIL) @@ -889,16 +1163,26 @@ H5HL_get_size(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t *size) HDassert(H5F_addr_defined(addr)); HDassert(size); - /* Get heap pointer */ - if(NULL == (heap = (H5HL_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_READ))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load heap") + /* Construct the user data for protect callback */ + prfx_udata.sizeof_size = H5F_SIZEOF_SIZE(f); + prfx_udata.sizeof_addr = H5F_SIZEOF_ADDR(f); + prfx_udata.sizeof_prfx = H5HL_SIZEOF_HDR(f); + prfx_udata.loaded = FALSE; + prfx_udata.free_block = H5HL_FREE_NULL; + + /* Protect the local heap prefix */ + if(NULL == (prfx = (H5HL_prfx_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP_PRFX, addr, NULL, &prfx_udata, H5AC_READ))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load heap prefix") + + /* Get the pointer to the heap */ + heap = prfx->heap; /* Set the size to return */ - *size = heap->heap_alloc; + *size = heap->dblk_size; done: - if(heap && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, heap, H5AC__NO_FLAGS_SET) < 0) - HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release local heap") + if(prfx && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP_PRFX, heap->prfx_addr, prfx, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release local heap prefix") FUNC_LEAVE_NOAPI(ret_value) } /* end H5HL_get_size() */ @@ -920,8 +1204,9 @@ done: herr_t H5HL_heapsize(H5F_t *f, hid_t dxpl_id, haddr_t addr, hsize_t *heap_size) { - H5HL_t *heap = NULL; /* Heap to query */ - size_t local_heap_size = 0; + H5HL_cache_prfx_ud_t prfx_udata; /* User data for protecting local heap prefix */ + H5HL_prfx_t *prfx = NULL; /* Local heap prefix */ + H5HL_t *heap; /* Heap data structure */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5HL_heapsize, FAIL) @@ -931,20 +1216,26 @@ H5HL_heapsize(H5F_t *f, hid_t dxpl_id, haddr_t addr, hsize_t *heap_size) HDassert(H5F_addr_defined(addr)); HDassert(heap_size); - /* Get heap pointer */ - if(NULL == (heap = (H5HL_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_READ))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load heap") + /* Construct the user data for protect callback */ + prfx_udata.sizeof_size = H5F_SIZEOF_SIZE(f); + prfx_udata.sizeof_addr = H5F_SIZEOF_ADDR(f); + prfx_udata.sizeof_prfx = H5HL_SIZEOF_HDR(f); + prfx_udata.loaded = FALSE; + prfx_udata.free_block = H5HL_FREE_NULL; + + /* Protect the local heap prefix */ + if(NULL == (prfx = (H5HL_prfx_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP_PRFX, addr, NULL, &prfx_udata, H5AC_READ))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load heap prefix") - /* Get the total size of the local heap */ - if(H5HL_size(f, heap, &local_heap_size) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to compute size of local heap") + /* Get the pointer to the heap */ + heap = prfx->heap; /* Accumulate the size of the local heap */ - *heap_size += (hsize_t)local_heap_size; + *heap_size += (hsize_t)(heap->prfx_size + heap->dblk_size); done: - if(heap && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, heap, H5AC__NO_FLAGS_SET) < 0) - HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release local heap") + if(prfx && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP_PRFX, heap->prfx_addr, prfx, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release local heap prefix") FUNC_LEAVE_NOAPI(ret_value) } /* end H5HL_heapsize() */ diff --git a/src/H5HLcache.c b/src/H5HLcache.c index 8f617f7..a26477a 100644 --- a/src/H5HLcache.c +++ b/src/H5HLcache.c @@ -38,6 +38,7 @@ #include "H5Eprivate.h" /* Error handling */ #include "H5HLpkg.h" /* Local Heaps */ #include "H5MFprivate.h" /* File memory management */ +#include "H5WBprivate.h" /* Wrapped Buffers */ /****************/ @@ -45,7 +46,12 @@ /****************/ #define H5HL_VERSION 0 /* Local heap collection version */ -#define H5HL_FREE_NULL 1 /* End of free list on disk */ + +/* Set the local heap size to speculatively read in */ +/* (needs to be more than the local heap prefix size to work at all and + * should be larger than the default local heap size to save the + * extra I/O operations) */ +#define H5HL_SPEC_READ_SIZE 512 /******************/ @@ -62,14 +68,21 @@ /* Local Prototypes */ /********************/ -/* Local encode/decode routines */ -static herr_t H5HL_serialize(H5F_t *f, H5HL_t *heap, uint8_t *buf); - /* Metadata cache callbacks */ -static H5HL_t *H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1, - void *udata2); -static herr_t H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, H5HL_t *heap, unsigned UNUSED * flags_ptr); -static herr_t H5HL_clear(H5F_t *f, H5HL_t *heap, hbool_t destroy); +static void *H5HL_prefix_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, + const void *udata1, void *udata2); +static herr_t H5HL_prefix_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, + void *thing, unsigned *flags_ptr); +static herr_t H5HL_prefix_dest(H5F_t *f, void *thing); +static herr_t H5HL_prefix_clear(H5F_t *f, void *thing, hbool_t destroy); +static herr_t H5HL_prefix_size(const H5F_t *f, const void *thing, size_t *size_ptr); +static void *H5HL_datablock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, + const void *udata1, void *udata2); +static herr_t H5HL_datablock_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, + void *thing, unsigned *flags_ptr); +static herr_t H5HL_datablock_dest(H5F_t *f, void *thing); +static herr_t H5HL_datablock_clear(H5F_t *f, void *thing, hbool_t destroy); +static herr_t H5HL_datablock_size(const H5F_t *f, const void *thing, size_t *size_ptr); /*********************/ @@ -77,14 +90,24 @@ static herr_t H5HL_clear(H5F_t *f, H5HL_t *heap, hbool_t destroy); /*********************/ /* H5HL inherits cache-like properties from H5AC */ -const H5AC_class_t H5AC_LHEAP[1] = {{ - H5AC_LHEAP_ID, - (H5AC_load_func_t)H5HL_load, - (H5AC_flush_func_t)H5HL_flush, - (H5AC_dest_func_t)H5HL_dest, - (H5AC_clear_func_t)H5HL_clear, - (H5AC_notify_func_t)NULL, - (H5AC_size_func_t)H5HL_size, +const H5AC_class_t H5AC_LHEAP_PRFX[1] = {{ + H5AC_LHEAP_PRFX_ID, + H5HL_prefix_load, + H5HL_prefix_flush, + H5HL_prefix_dest, + H5HL_prefix_clear, + NULL, + H5HL_prefix_size, +}}; + +const H5AC_class_t H5AC_LHEAP_DBLK[1] = {{ + H5AC_LHEAP_DBLK_ID, + H5HL_datablock_load, + H5HL_datablock_flush, + H5HL_datablock_dest, + H5HL_datablock_clear, + NULL, + H5HL_datablock_size, }}; @@ -100,72 +123,117 @@ const H5AC_class_t H5AC_LHEAP[1] = {{ /*------------------------------------------------------------------------- - * Function: H5HL_serialize + * Function: H5HL_fl_deserialize * - * Purpose: Serialize the heap. This function will eliminate free - * blocks at the tail of the heap and also split the block - * if it needs to be split for the file. This is so that we - * can serialize it correctly. + * Purpose: Deserialize the free list for a heap data block * * Return: Non-negative on success/Negative on failure * - * Programmer: Bill Wendling - * wendling@ncsa.uiuc.edu - * Sept. 16, 2003 + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Oct 12 2008 * *------------------------------------------------------------------------- */ static herr_t -H5HL_serialize(H5F_t *f, H5HL_t *heap, uint8_t *buf) +H5HL_fl_deserialize(H5HL_t *heap, hsize_t free_block) { - H5HL_free_t *fl; - uint8_t *p; - herr_t ret_value = SUCCEED; + H5HL_free_t *fl, *tail = NULL; /* Heap free block nodes */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HL_fl_deserialize) - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_serialize) + /* check arguments */ + HDassert(heap); - /* check args */ - assert(buf); - assert(heap); + /* Build free list */ + while(H5HL_FREE_NULL != free_block) { + const uint8_t *p; /* Pointer into image buffer */ - /* serialize the header */ - p = buf; - fl = heap->freelist; - HDmemcpy(p, H5HL_MAGIC, (size_t)H5_SIZEOF_MAGIC); - p += H5_SIZEOF_MAGIC; - *p++ = H5HL_VERSION; - *p++ = 0; /*reserved*/ - *p++ = 0; /*reserved*/ - *p++ = 0; /*reserved*/ - H5F_ENCODE_LENGTH(f, p, heap->heap_alloc); - H5F_ENCODE_LENGTH(f, p, fl ? fl->offset : H5HL_FREE_NULL); - H5F_addr_encode(f, &p, heap->addr); - - /* serialize the free list */ - for (; fl; fl = fl->next) { - assert (fl->offset == H5HL_ALIGN (fl->offset)); - p = heap->chunk + H5HL_SIZEOF_HDR(f) + fl->offset; - - if (fl->next) { - H5F_ENCODE_LENGTH(f, p, fl->next->offset); - } else { - H5F_ENCODE_LENGTH(f, p, H5HL_FREE_NULL); - } - - H5F_ENCODE_LENGTH(f, p, fl->size); - } + /* Sanity check */ + if(free_block >= heap->dblk_size) + HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "bad heap free list") + + /* Allocate & initialize free list node */ + if(NULL == (fl = H5FL_MALLOC(H5HL_free_t))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed") + fl->offset = (size_t)free_block; + fl->prev = tail; + fl->next = NULL; + /* Insert node into list */ + if(tail) + tail->next = fl; + tail = fl; + if(!heap->freelist) + heap->freelist = fl; + + /* Decode offset of next free block */ + p = heap->dblk_image + free_block; + H5F_DECODE_LENGTH_LEN(p, free_block, heap->sizeof_size); + if(free_block == 0) + HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "free block size is zero?") + + /* Decode length of this free block */ + H5F_DECODE_LENGTH_LEN(p, fl->size, heap->sizeof_size); + if(fl->offset + fl->size > heap->dblk_size) + HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "bad heap free list") + } /* end while */ + +done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HL_serialize() */ +} /* end H5HL_fl_deserialize() */ /*------------------------------------------------------------------------- - * Function: H5HL_load + * Function: H5HL_fl_serialize * - * Purpose: Loads a heap from disk. + * Purpose: Serialize the free list for a heap data block * - * Return: Success: Ptr to a local heap memory data structure. + * Return: Success: SUCCESS + * Failure: FAIL + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Oct 12 2008 * + *------------------------------------------------------------------------- + */ +static void +H5HL_fl_serialize(const H5HL_t *heap) +{ + H5HL_free_t *fl; /* Pointer to heap free list node */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_fl_serialize) + + /* check arguments */ + HDassert(heap); + + /* Serialize the free list into the heap data's image */ + for(fl = heap->freelist; fl; fl = fl->next) { + uint8_t *p; /* Pointer into raw data buffer */ + + HDassert(fl->offset == H5HL_ALIGN(fl->offset)); + p = heap->dblk_image + fl->offset; + + if(fl->next) + H5F_ENCODE_LENGTH_LEN(p, fl->next->offset, heap->sizeof_size) + else + H5F_ENCODE_LENGTH_LEN(p, H5HL_FREE_NULL, heap->sizeof_size) + + H5F_ENCODE_LENGTH_LEN(p, fl->size, heap->sizeof_size) + } /* end for */ + + FUNC_LEAVE_NOAPI_VOID +} /* end H5HL_fl_serialize() */ + + +/*------------------------------------------------------------------------- + * Function: H5HL_prefix_load + * + * Purpose: Loads a local heap prefix from disk. + * + * Return: Success: Ptr to a local heap memory data structure. * Failure: NULL * * Programmer: Robb Matzke @@ -174,38 +242,47 @@ H5HL_serialize(H5F_t *f, H5HL_t *heap, uint8_t *buf) * *------------------------------------------------------------------------- */ -static H5HL_t * -H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * udata1, - void UNUSED * udata2) +static void * +H5HL_prefix_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1, + void *_udata) { - uint8_t hdr[52]; - size_t sizeof_hdr; /* Cache H5HL header size for file */ - const uint8_t *p = NULL; - H5HL_t *heap = NULL; - H5HL_free_t *fl = NULL, *tail = NULL; - size_t free_block = H5HL_FREE_NULL; - H5HL_t *ret_value; + H5HL_t *heap = NULL; /* Local heap */ + H5HL_prfx_t *prfx = NULL; /* Heap prefix deserialized */ + H5HL_cache_prfx_ud_t *udata = (H5HL_cache_prfx_ud_t *)_udata; /* User data for protecting local heap prefix */ + uint8_t buf[H5HL_SPEC_READ_SIZE]; /* Buffer for decoding */ + size_t spec_read_size; /* Size of buffer to speculatively read in */ + const uint8_t *p; /* Pointer into decoding buffer */ + haddr_t eoa; /* Relative end of file address */ + void *ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5HL_load, NULL) + FUNC_ENTER_NOAPI_NOINIT(H5HL_prefix_load) /* check arguments */ HDassert(f); HDassert(H5F_addr_defined(addr)); HDassert(!udata1); - HDassert(!udata2); - - /* Cache this for later */ - sizeof_hdr = H5HL_SIZEOF_HDR(f); - HDassert(sizeof_hdr <= sizeof(hdr)); - - /* Get the local heap's header */ - if(H5F_block_read(f, H5FD_MEM_LHEAP, addr, sizeof_hdr, dxpl_id, hdr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read heap header") - p = hdr; + HDassert(udata); + HDassert(udata->sizeof_size > 0); + HDassert(udata->sizeof_addr > 0); + HDassert(udata->sizeof_prfx > 0); + HDassert(udata->sizeof_prfx <= sizeof(buf)); + + /* Make certain we don't speculatively read off the end of the file */ + if(HADDR_UNDEF == (eoa = H5F_get_eoa(f, H5FD_MEM_LHEAP))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, NULL, "unable to determine file size") + + /* Compute the size of the speculative local heap prefix buffer */ + H5_ASSIGN_OVERFLOW(spec_read_size, MIN(eoa - addr, H5HL_SPEC_READ_SIZE), /* From: */ hsize_t, /* To: */ size_t); + HDassert(spec_read_size >= udata->sizeof_prfx); + + /* Attempt to speculatively read both local heap prefix and heap data */ + if(H5F_block_read(f, H5FD_MEM_LHEAP, addr, spec_read_size, dxpl_id, buf) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read local heap prefix") + p = buf; /* Check magic number */ - if(HDmemcmp(hdr, H5HL_MAGIC, (size_t)H5_SIZEOF_MAGIC)) - HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "bad heap signature") + if(HDmemcmp(p, H5HL_MAGIC, (size_t)H5_SIZEOF_MAGIC)) + HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "bad local heap signature") p += H5_SIZEOF_MAGIC; /* Version */ @@ -216,65 +293,84 @@ H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * udata1, p += 3; /* Allocate space in memory for the heap */ - if(NULL == (heap = H5FL_CALLOC(H5HL_t))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "memory allocation failed") + if(NULL == (heap = H5HL_new(udata->sizeof_size, udata->sizeof_addr, udata->sizeof_prfx))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "can't allocate local heap structure") - /* heap data size */ - H5F_DECODE_LENGTH(f, p, heap->heap_alloc); + /* Allocate the heap prefix */ + if(NULL == (prfx = H5HL_prfx_new(heap))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "can't allocate local heap prefix") - /* free list head */ - H5F_DECODE_LENGTH(f, p, free_block); - if(free_block != H5HL_FREE_NULL && free_block >= heap->heap_alloc) - HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "bad heap free list") + /* Store the prefix's address & length */ + heap->prfx_addr = addr; + heap->prfx_size = udata->sizeof_prfx; - /* data */ - H5F_addr_decode(f, &p, &(heap->addr)); - if(NULL == (heap->chunk = H5FL_BLK_CALLOC(lheap_chunk, (sizeof_hdr + heap->heap_alloc)))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "memory allocation failed") - if(heap->heap_alloc && - H5F_block_read(f, H5FD_MEM_LHEAP, heap->addr, heap->heap_alloc, dxpl_id, heap->chunk + sizeof_hdr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read heap data") + /* Heap data size */ + H5F_DECODE_LENGTH_LEN(p, heap->dblk_size, udata->sizeof_size); - /* Build free list */ - while(H5HL_FREE_NULL != free_block) { - if(free_block >= heap->heap_alloc) - HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, NULL, "bad heap free list") - if(NULL == (fl = H5FL_MALLOC(H5HL_free_t))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "memory allocation failed") - fl->offset = free_block; - fl->prev = tail; - fl->next = NULL; - if(tail) - tail->next = fl; - tail = fl; - if(!heap->freelist) - heap->freelist = fl; - - p = heap->chunk + sizeof_hdr + free_block; + /* Free list head */ + H5F_DECODE_LENGTH_LEN(p, udata->free_block, udata->sizeof_size); + if(udata->free_block != H5HL_FREE_NULL && udata->free_block >= heap->dblk_size) + HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "bad heap free list") - H5F_DECODE_LENGTH(f, p, free_block); - if(free_block == 0) - HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "free block size is zero?") + /* Heap data address */ + H5F_addr_decode_len(udata->sizeof_addr, &p, &(heap->dblk_addr)); + + /* Check if heap block exists */ + if(heap->dblk_size) { + /* Check if heap data block is contiguous with header */ + if(H5F_addr_eq((heap->prfx_addr + heap->prfx_size), heap->dblk_addr)) { + /* Note that the heap should be a single object in the cache */ + heap->single_cache_obj = TRUE; + + /* Allocate space for the heap data image */ + if(NULL == (heap->dblk_image = H5FL_BLK_MALLOC(lheap_chunk, heap->dblk_size))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "memory allocation failed") + + /* Check if the current buffer from the speculative read already has the heap data */ + if(spec_read_size >= (heap->prfx_size + heap->dblk_size)) { + /* Copy the heap data from the speculative read buffer */ + HDmemcpy(heap->dblk_image, p, heap->dblk_size); + } /* end if */ + else { + /* Read the local heap data block directly into buffer */ + if(H5F_block_read(f, H5FD_MEM_LHEAP, heap->dblk_addr, heap->dblk_size, dxpl_id, heap->dblk_image) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read heap data") + } /* end else */ + + /* Build free list */ + if(H5HL_fl_deserialize(heap, udata->free_block) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't initialize free list") + } /* end if */ + else + /* Note that the heap should _NOT_ be a single object in the cache */ + heap->single_cache_obj = FALSE; + } /* end if */ - H5F_DECODE_LENGTH(f, p, fl->size); - if(fl->offset + fl->size > heap->heap_alloc) - HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, NULL, "bad heap free list") - } /* end while */ + /* Set flag to indicate prefix from loaded from file */ + udata->loaded = TRUE; /* Set return value */ - ret_value = heap; + ret_value = prfx; done: - if(!ret_value && heap) - if(H5HL_dest(f,heap) < 0) - HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, NULL, "unable to destroy local heap collection") + /* Release the [possibly partially initialized] local heap on errors */ + if(!ret_value) { + if(prfx) { + if(H5HL_prfx_dest(prfx) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTRELEASE, NULL, "unable to destroy local heap prefix") + } /* end if */ + else { + if(heap && H5HL_dest(heap) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTRELEASE, NULL, "unable to destroy local heap") + } /* end else */ + } /* end if */ FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HL_load() */ +} /* end H5HL_prefix_load() */ /*------------------------------------------------------------------------- - * Function: H5HL_flush + * Function: H5HL_prefix_flush * * Purpose: Flushes a heap from memory to disk if it's dirty. Optionally * deletes the heap from memory. @@ -288,58 +384,336 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HL_t *heap, unsigned UNUSED * flags_ptr) +H5HL_prefix_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, + void *thing, unsigned UNUSED *flags_ptr) { - herr_t ret_value = SUCCEED; /* Return value */ + H5HL_prfx_t *prfx = (H5HL_prfx_t *)thing; /* Local heap prefix to flush */ + H5WB_t *wb = NULL; /* Wrapped buffer for heap data */ + uint8_t heap_buf[H5HL_SPEC_READ_SIZE]; /* Buffer for heap */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5HL_flush, FAIL) + FUNC_ENTER_NOAPI_NOINIT(H5HL_prefix_flush) /* check arguments */ HDassert(f); HDassert(H5F_addr_defined(addr)); - HDassert(heap); + HDassert(prfx); + + if(prfx->cache_info.is_dirty) { + H5HL_t *heap = prfx->heap; /* Pointer to the local heap */ + H5HL_free_t *fl = heap->freelist; /* Pointer to heap's free list */ + uint8_t *buf; /* Pointer to heap buffer */ + size_t buf_size; /* Size of buffer for encoding & writing heap info */ + uint8_t *p; /* Pointer into raw data buffer */ + + /* Wrap the local buffer for serialized heap info */ + if(NULL == (wb = H5WB_wrap(heap_buf, sizeof(heap_buf)))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't wrap buffer") + + /* Compute the size of the buffer to encode & write */ + buf_size = heap->prfx_size; + if(heap->single_cache_obj) + buf_size += heap->dblk_size; + + /* Get a pointer to a buffer that's large enough for serialized heap */ + if(NULL == (buf = (uint8_t *)H5WB_actual(wb, buf_size))) + HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "can't get actual buffer") + + /* Serialize the heap prefix */ + p = buf; + HDmemcpy(p, H5HL_MAGIC, (size_t)H5_SIZEOF_MAGIC); + p += H5_SIZEOF_MAGIC; + *p++ = H5HL_VERSION; + *p++ = 0; /*reserved*/ + *p++ = 0; /*reserved*/ + *p++ = 0; /*reserved*/ + H5F_ENCODE_LENGTH_LEN(p, heap->dblk_size, heap->sizeof_size); + H5F_ENCODE_LENGTH_LEN(p, fl ? fl->offset : H5HL_FREE_NULL, heap->sizeof_size); + H5F_addr_encode_len(heap->sizeof_addr, &p, heap->dblk_addr); + + /* Check if the local heap is a single object in cache */ + if(heap->single_cache_obj) { + /* Serialize the free list into the heap data's image */ + H5HL_fl_serialize(heap); + + /* Copy the heap data block into the cache image */ + HDmemcpy(p, heap->dblk_image, heap->dblk_size); + } /* end if */ - if(heap->cache_info.is_dirty) { - haddr_t hdr_end_addr; - size_t sizeof_hdr = H5HL_SIZEOF_HDR(f); /* cache H5HL header size for file */ + /* Write the prefix [and possibly the data block] to the file */ + if(H5F_block_write(f, H5FD_MEM_LHEAP, addr, buf_size, dxpl_id, buf) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header and data to file") - /* Write the header */ - if(H5HL_serialize(f, heap, heap->chunk) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTSERIALIZE, FAIL, "unable to serialize local heap") + prfx->cache_info.is_dirty = FALSE; + } /* end if */ - /* Copy buffer to disk */ - hdr_end_addr = addr + (hsize_t)sizeof_hdr; + /* Should we destroy the memory version? */ + if(destroy) + if(H5HL_prfx_dest(prfx) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap prefix") - if(H5F_addr_eq(heap->addr, hdr_end_addr)) { - /* The header and data are contiguous */ - if(H5F_block_write(f, H5FD_MEM_LHEAP, addr, (sizeof_hdr + heap->heap_alloc), dxpl_id, heap->chunk) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header and data to file") - } /* end if */ - else { - if(H5F_block_write(f, H5FD_MEM_LHEAP, addr, sizeof_hdr, dxpl_id, heap->chunk) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header to file") +done: + /* Release resources */ + if(wb && H5WB_unwrap(wb) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CLOSEERROR, FAIL, "can't close wrapped buffer") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HL_prefix_flush() */ + + +/*------------------------------------------------------------------------- + * Function: H5HL_prefix_dest + * + * Purpose: Destroys a heap prefix in memory. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Jan 15 2003 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HL_prefix_dest(H5F_t UNUSED *f, void *thing) +{ + H5HL_prfx_t *prfx = (H5HL_prfx_t *)thing; /* Local heap prefix to destroy */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HL_prefix_dest) - if(H5F_block_write(f, H5FD_MEM_LHEAP, heap->addr, heap->heap_alloc, dxpl_id, heap->chunk + sizeof_hdr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap data to file") - } /* end else */ + /* check arguments */ + HDassert(prfx); + HDassert(prfx->heap); + HDassert(H5F_addr_eq(prfx->cache_info.addr, prfx->heap->prfx_addr)); + + /* Verify that entry is clean */ + HDassert(prfx->cache_info.is_dirty == FALSE); + + /* If we're going to free the space on disk, the address must be valid */ + HDassert(!prfx->cache_info.free_file_space_on_destroy || H5F_addr_defined(prfx->cache_info.addr)); - heap->cache_info.is_dirty = FALSE; + /* Check for freeing file space for local heap prefix */ + if(prfx->cache_info.free_file_space_on_destroy) { + hsize_t free_size; /* Size of region to free in file */ + + /* Compute size to free for later */ + free_size = prfx->heap->prfx_size; + if(prfx->heap->single_cache_obj) + free_size += prfx->heap->dblk_size; + + /* Free the local heap prefix [and possible the data block] on disk */ + /* (XXX: Nasty usage of internal DXPL value! -QAK) */ + if(H5MF_xfree(f, H5FD_MEM_LHEAP, H5AC_dxpl_id, prfx->cache_info.addr, free_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap prefix") + } /* end if */ + + /* Destroy local heap prefix */ + if(H5HL_prfx_dest(prfx) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't destroy local heap prefix") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HL_prefix_dest() */ + + +/*------------------------------------------------------------------------- + * Function: H5HL_prefix_clear + * + * Purpose: Mark a local heap prefix in memory as non-dirty. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 20 2003 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HL_prefix_clear(H5F_t UNUSED *f, void *thing, hbool_t destroy) +{ + H5HL_prfx_t *prfx = (H5HL_prfx_t *)thing; /* The local heap prefix to operate on */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HL_prefix_clear) + + /* check arguments */ + HDassert(prfx); + + /* Mark heap prefix as clean */ + prfx->cache_info.is_dirty = FALSE; + + if(destroy) + if(H5HL_prfx_dest(prfx) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap prefix") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HL_prefix_clear() */ + + +/*------------------------------------------------------------------------- + * Function: H5HL_prefix_size + * + * Purpose: Compute the size in bytes of the heap prefix on disk, + * and return it in *len_ptr. On failure, the value of *len_ptr + * is undefined. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: John Mainzer + * 5/13/04 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HL_prefix_size(const H5F_t UNUSED *f, const void *thing, size_t *size_ptr) +{ + const H5HL_prfx_t *prfx = (const H5HL_prfx_t *)thing; /* Pointer to local heap prefix to query */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_prefix_size) + + /* check arguments */ + HDassert(prfx); + HDassert(prfx->heap); + HDassert(size_ptr); + + /* Calculate size of prefix in cache */ + *size_ptr = prfx->heap->prfx_size; + + /* If the heap is stored as a single object, add in the data block size also */ + if(prfx->heap->single_cache_obj) + *size_ptr += prfx->heap->dblk_size; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5HL_prefix_size() */ + + +/*------------------------------------------------------------------------- + * Function: H5HL_datablock_load + * + * Purpose: Loads a local heap data block from disk. + * + * Return: Success: Ptr to a local heap data block memory data structure. + * Failure: NULL + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Jan 5 2010 + * + *------------------------------------------------------------------------- + */ +static void * +H5HL_datablock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1, + void *_udata) +{ + H5HL_dblk_t *dblk = NULL; /* Heap data block deserialized */ + H5HL_cache_dblk_ud_t *udata = (H5HL_cache_dblk_ud_t *)_udata; /* User data for protecting local heap data block */ + void *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HL_datablock_load) + + /* check arguments */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(!udata1); + HDassert(udata); + HDassert(udata->heap); + HDassert(!udata->heap->single_cache_obj); + + /* Allocate space in memory for the heap data block */ + if(NULL == (dblk = H5HL_dblk_new(udata->heap))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "memory allocation failed") + + /* Check for heap still retaining image */ + if(NULL == udata->heap->dblk_image) { + /* Allocate space for the heap data image */ + if(NULL == (udata->heap->dblk_image = H5FL_BLK_MALLOC(lheap_chunk, udata->heap->dblk_size))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "can't allocate data block image buffer") + + /* Read local heap data block */ + if(H5F_block_read(f, H5FD_MEM_LHEAP, udata->heap->dblk_addr, udata->heap->dblk_size, dxpl_id, udata->heap->dblk_image) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read local heap data block") + + /* Build free list */ + if(H5HL_fl_deserialize(udata->heap, udata->free_block) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't initialize free list") + } /* end if */ + + /* Set flag to indicate data block from loaded from file */ + udata->loaded = TRUE; + + /* Set return value */ + ret_value = dblk; + +done: + /* Release the [possibly partially initialized] local heap on errors */ + if(!ret_value && dblk) + if(H5HL_dblk_dest(f, dblk) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTRELEASE, NULL, "unable to destroy local heap data block") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HL_datablock_load() */ + + +/*------------------------------------------------------------------------- + * Function: H5HL_datablock_flush + * + * Purpose: Flushes a heap's data block from memory to disk if it's dirty. + * Optionally deletes the heap data block from memory. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jul 17 1997 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HL_datablock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, + void *_thing, unsigned UNUSED * flags_ptr) +{ + H5HL_dblk_t *dblk = (H5HL_dblk_t *)_thing; /* Pointer to the local heap data block */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HL_datablock_flush) + + /* check arguments */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(dblk); + HDassert(dblk->heap); + HDassert(!dblk->heap->single_cache_obj); + + if(dblk->cache_info.is_dirty) { + H5HL_t *heap = dblk->heap; /* Pointer to the local heap */ + + /* Serialize the free list into the heap data's image */ + H5HL_fl_serialize(heap); + + /* Write the data block to the file */ + if(H5F_block_write(f, H5FD_MEM_LHEAP, heap->dblk_addr, heap->dblk_size, dxpl_id, heap->dblk_image) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap data block to file") + + dblk->cache_info.is_dirty = FALSE; } /* end if */ /* Should we destroy the memory version? */ if(destroy) - if(H5HL_dest(f, heap) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap collection") + if(H5HL_dblk_dest(f, dblk) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap data block") done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HL_flush() */ +} /* end H5HL_datablock_flush() */ /*------------------------------------------------------------------------- - * Function: H5HL_dest + * Function: H5HL_datablock_dest * - * Purpose: Destroys a heap in memory. + * Purpose: Destroys a local heap data block in memory. * * Return: Non-negative on success/Negative on failure * @@ -349,75 +723,48 @@ done: * *------------------------------------------------------------------------- */ -herr_t -H5HL_dest(H5F_t *f, H5HL_t *heap) +static herr_t +H5HL_datablock_dest(H5F_t *f, void *_thing) { - H5HL_free_t *fl; /* Heap object free list */ + H5HL_dblk_t *dblk = (H5HL_dblk_t *)_thing; /* Pointer to the local heap data block */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5HL_dest) + FUNC_ENTER_NOAPI_NOINIT(H5HL_datablock_dest) /* check arguments */ - HDassert(heap); + HDassert(f); + HDassert(dblk); + HDassert(dblk->heap); + HDassert(!dblk->heap->single_cache_obj); + HDassert(H5F_addr_eq(dblk->cache_info.addr, dblk->heap->dblk_addr)); - /* Verify that node is clean */ - HDassert(heap->cache_info.is_dirty == FALSE); + /* Verify that entry is clean */ + HDassert(dblk->cache_info.is_dirty == FALSE); /* If we're going to free the space on disk, the address must be valid */ - HDassert(!heap->cache_info.free_file_space_on_destroy || H5F_addr_defined(heap->cache_info.addr)); - - /* Check for freeing file space for local heap */ - if(heap->cache_info.free_file_space_on_destroy) { - size_t sizeof_hdr; /* H5HL header size for file */ - haddr_t hdr_addr; /* Address of heap header in file */ - - /* Compute this for later */ - sizeof_hdr = H5HL_SIZEOF_HDR(f); - hdr_addr = heap->cache_info.addr; - - /* Check if the heap is contiguous on disk */ - HDassert(!H5F_addr_overflow(hdr_addr, sizeof_hdr)); - if(H5F_addr_eq(heap->addr, hdr_addr + sizeof_hdr)) { - /* Free the contiguous local heap in one call */ - /* (XXX: Nasty usage of internal DXPL value! -QAK) */ - H5_CHECK_OVERFLOW(sizeof_hdr + heap->heap_alloc, size_t, hsize_t); - if(H5MF_xfree(f, H5FD_MEM_LHEAP, H5AC_dxpl_id, hdr_addr, (hsize_t)(sizeof_hdr + heap->heap_alloc)) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free contiguous local heap") - } /* end if */ - else { - /* Free the local heap's header */ - /* (XXX: Nasty usage of internal DXPL value! -QAK) */ - H5_CHECK_OVERFLOW(sizeof_hdr, size_t, hsize_t); - if(H5MF_xfree(f, H5FD_MEM_LHEAP, H5AC_dxpl_id, hdr_addr, (hsize_t)sizeof_hdr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap header") - - /* Free the local heap's data */ - /* (XXX: Nasty usage of internal DXPL value! -QAK) */ - H5_CHECK_OVERFLOW(heap->heap_alloc, size_t, hsize_t); - if(H5MF_xfree(f, H5FD_MEM_LHEAP, H5AC_dxpl_id, heap->addr, (hsize_t)heap->heap_alloc) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap data") - } /* end else */ + HDassert(!dblk->cache_info.free_file_space_on_destroy || H5F_addr_defined(dblk->cache_info.addr)); + + /* Check for freeing file space for local heap data block */ + if(dblk->cache_info.free_file_space_on_destroy) { + /* Free the local heap data block on disk */ + /* (XXX: Nasty usage of internal DXPL value! -QAK) */ + if(H5MF_xfree(f, H5FD_MEM_LHEAP, H5AC_dxpl_id, dblk->cache_info.addr, (hsize_t)dblk->heap->dblk_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap data block") } /* end if */ - /* Release resources */ - if(heap->chunk) - heap->chunk = H5FL_BLK_FREE(lheap_chunk, heap->chunk); - while(heap->freelist) { - fl = heap->freelist; - heap->freelist = fl->next; - fl = H5FL_FREE(H5HL_free_t, fl); - } /* end while */ - heap = H5FL_FREE(H5HL_t, heap); + /* Destroy local heap data block */ + if(H5HL_dblk_dest(f, dblk) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't destroy local heap data block") done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HL_dest() */ +} /* end H5HL_datablock_dest() */ /*------------------------------------------------------------------------- - * Function: H5HL_clear + * Function: H5HL_datablock_clear * - * Purpose: Mark a local heap in memory as non-dirty. + * Purpose: Mark a local heap data block in memory as non-dirty. * * Return: Non-negative on success/Negative on failure * @@ -428,33 +775,35 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5HL_clear(H5F_t *f, H5HL_t *heap, hbool_t destroy) +H5HL_datablock_clear(H5F_t *f, void *_thing, hbool_t destroy) { + H5HL_dblk_t *dblk = (H5HL_dblk_t *)_thing; /* Pointer to the local heap data block */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5HL_clear) + FUNC_ENTER_NOAPI_NOINIT(H5HL_datablock_clear) /* check arguments */ - HDassert(heap); + HDassert(f); + HDassert(dblk); - /* Mark heap as clean */ - heap->cache_info.is_dirty = FALSE; + /* Mark local heap data block as clean */ + dblk->cache_info.is_dirty = FALSE; if(destroy) - if(H5HL_dest(f, heap) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap collection") + if(H5HL_dblk_dest(f, dblk) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap data block") done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HL_clear() */ +} /* end H5HL_datablock_clear() */ /*------------------------------------------------------------------------- - * Function: H5HL_size + * Function: H5HL_datablock_size * - * Purpose: Compute the size in bytes of the specified instance of - * H5HL_t on disk, and return it in *len_ptr. On failure, - * the value of *len_ptr is undefined. + * Purpose: Compute the size in bytes of the local heap data block on disk, + * and return it in *len_ptr. On failure, the value of *len_ptr + * is undefined. * * Return: Non-negative on success/Negative on failure * @@ -463,18 +812,21 @@ done: * *------------------------------------------------------------------------- */ -herr_t -H5HL_size(const H5F_t *f, const H5HL_t *heap, size_t *size_ptr) +static herr_t +H5HL_datablock_size(const H5F_t UNUSED *f, const void *_thing, size_t *size_ptr) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_size) + const H5HL_dblk_t *dblk = (const H5HL_dblk_t *)_thing; /* Pointer to the local heap data block */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_datablock_size) /* check arguments */ - HDassert(f); - HDassert(heap); + HDassert(dblk); + HDassert(dblk->heap); HDassert(size_ptr); - *size_ptr = H5HL_SIZEOF_HDR(f) + heap->heap_alloc; + /* Set size of data block in cache */ + *size_ptr = dblk->heap->dblk_size; FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5HL_size() */ +} /* H5HL_datablock_size() */ diff --git a/src/H5HLdbg.c b/src/H5HLdbg.c index 6bf35ad..8107164 100644 --- a/src/H5HLdbg.c +++ b/src/H5HLdbg.c @@ -69,28 +69,25 @@ H5HL_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent, int HDassert(indent >= 0); HDassert(fwidth >= 0); - if(NULL == (h = (H5HL_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_READ))) + if(NULL == (h = (H5HL_t *)H5HL_protect(f, dxpl_id, addr, H5AC_READ))) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap") fprintf(stream, "%*sLocal Heap...\n", indent, ""); - fprintf(stream, "%*s%-*s %d\n", indent, "", fwidth, - "Dirty:", - (int) (h->cache_info.is_dirty)); fprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth, "Header size (in bytes):", - (unsigned long) H5HL_SIZEOF_HDR(f)); + (unsigned long)h->prfx_size); HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth, "Address of heap data:", - h->addr); + h->dblk_addr); HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth, "Data bytes allocated for heap:", - h->heap_alloc); + h->dblk_size); /* * Traverse the free list and check that all free blocks fall within * the heap and that no two free blocks point to the same region of * the heap. */ - if(NULL == (marker = (uint8_t *)H5MM_calloc(h->heap_alloc))) + if(NULL == (marker = (uint8_t *)H5MM_calloc(h->dblk_size))) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed") fprintf(stream, "%*sFree Blocks (offset, size):\n", indent, ""); @@ -102,7 +99,7 @@ H5HL_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent, int HDfprintf(stream, "%*s%-*s %8Zu, %8Zu\n", indent+3, "", MAX(0,fwidth-9), temp_str, freelist->offset, freelist->size); - if(freelist->offset + freelist->size > h->heap_alloc) + if((freelist->offset + freelist->size) > h->dblk_size) fprintf(stream, "***THAT FREE BLOCK IS OUT OF BOUNDS!\n"); else { for(i = overlap = 0; i < (int)(freelist->size); i++) { @@ -111,25 +108,24 @@ H5HL_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent, int marker[freelist->offset + i] = 1; } /* end for */ if(overlap) - fprintf(stream, "***THAT FREE BLOCK OVERLAPPED A PREVIOUS " - "ONE!\n"); + fprintf(stream, "***THAT FREE BLOCK OVERLAPPED A PREVIOUS ONE!\n"); else amount_free += freelist->size; } /* end for */ } /* end for */ - if(h->heap_alloc) + if(h->dblk_size) fprintf(stream, "%*s%-*s %.2f%%\n", indent, "", fwidth, "Percent of heap used:", - (100.0 * (double)(h->heap_alloc - amount_free) / (double)h->heap_alloc)); + (100.0 * (double)(h->dblk_size - amount_free) / (double)h->dblk_size)); /* * Print the data in a VMS-style octal dump. */ - H5_buffer_dump(stream, indent, h->chunk, marker, H5HL_SIZEOF_HDR(f), h->heap_alloc); + H5_buffer_dump(stream, indent, h->dblk_image, marker, (size_t)0, h->dblk_size); done: - if(h && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, h, FALSE) < 0) + if(h && H5HL_unprotect(f, h) < 0) HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header") H5MM_xfree(marker); diff --git a/src/H5HLint.c b/src/H5HLint.c new file mode 100644 index 0000000..23ffe00 --- /dev/null +++ b/src/H5HLint.c @@ -0,0 +1,417 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5HLint.c + * Oct 12 2008 + * Quincey Koziol + * + * 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@ diff --git a/test/lheap.c b/test/lheap.c index b6591ef..df41315 100644 --- a/test/lheap.c +++ b/test/lheap.c @@ -104,7 +104,7 @@ main(void) goto error; } } - if(H5HL_unprotect(f, H5P_DATASET_XFER_DEFAULT, heap, heap_addr) < 0) { + if(H5HL_unprotect(f, heap) < 0) { H5_FAILED(); H5Eprint2(H5E_DEFAULT, stdout); goto error; @@ -137,7 +137,7 @@ main(void) goto error; } - if (NULL == (s = (const char *)H5HL_offset_into(f, heap, obj[i]))) { + if (NULL == (s = (const char *)H5HL_offset_into(heap, obj[i]))) { H5_FAILED(); H5Eprint2(H5E_DEFAULT, stdout); goto error; @@ -151,7 +151,7 @@ main(void) goto error; } - if(H5HL_unprotect(f, H5P_DATASET_XFER_DEFAULT, heap, heap_addr) < 0) { + if(H5HL_unprotect(f, heap) < 0) { H5_FAILED(); H5Eprint2(H5E_DEFAULT, stdout); goto error; -- cgit v0.12