From 78c1574378256975b39d4b65a011307a631dc667 Mon Sep 17 00:00:00 2001 From: Robb Matzke Date: Mon, 30 Mar 1998 14:24:08 -0500 Subject: [svn-r333] Changes since 19980324 ---------------------- ./MANIFEST ./src/H5HG.c [new] ./src/H5HGprivate.h [new] ./src/H5HGpublic.h [new] ./src/Makefile.in Added global heaps, H5HG. This compiles but is untested. ./src/H5D.c ./src/H5G.c ./src/H5Gnode.c ./src/H5Gstab.c ./src/H5HL.c [renamed from H5H.c] ./src/H5HLprivate.h [renamed from H5Hprivate.h] ./src/H5HLpublic.h [renamed from H5Hpublic.h] ./src/H5Oefl.c ./src/Makefile.in ./src/hdf5.h ./test/theap.c Renamed local heaps from H5H to H5HL. ./src/H5AC.c ./src/H5ACprivate.h ./src/debug.c Added debugging support for global heap collections. ./html/H5.format.html Ripped out the old small object heap documentation and added documentation for the new global heap. ./html/H5.api.html ./src/H5P.c ./src/H5Ppublic.h ./src/H5F.c ./src/H5Fprivate.h ./src/H5private.h The H5Pget_version() function no longer returns a small object heap version number. Instead, each collection of the global heap has its own version number instead of a single number in the file boot block. ./bin/release Omit files marked for removal by CVS even though the removal hasn't been committed yet. ./test/iopipe.c Removed warnings about casting unsigned int to double on Irix64. ./MANIFEST Removed ./test/testpar/phdf5sup.c --- MANIFEST | 10 +- bin/release | 3 +- src/H5AC.c | 7 +- src/H5ACprivate.h | 11 +- src/H5D.c | 10 +- src/H5F.c | 21 +- src/H5Fprivate.h | 4 +- src/H5G.c | 2 +- src/H5Gnode.c | 20 +- src/H5Gstab.c | 8 +- src/H5H.c | 1004 ----------------------------------------------------- src/H5HG.c | 887 ++++++++++++++++++++++++++++++++++++++++++++++ src/H5HGprivate.h | 78 +++++ src/H5HGpublic.h | 21 ++ src/H5HL.c | 972 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/H5HLprivate.h | 56 +++ src/H5HLpublic.h | 30 ++ src/H5Hprivate.h | 62 ---- src/H5Hpublic.h | 30 -- src/H5Oefl.c | 12 +- src/H5P.c | 18 +- src/H5Ppublic.h | 5 +- src/H5private.h | 1 - src/Makefile.in | 14 +- src/debug.c | 15 +- src/hdf5.h | 2 +- test/.distdep | 12 +- test/iopipe.c | 23 +- test/theap.c | 10 +- 29 files changed, 2146 insertions(+), 1202 deletions(-) delete mode 100644 src/H5H.c create mode 100644 src/H5HG.c create mode 100644 src/H5HGprivate.h create mode 100644 src/H5HGpublic.h create mode 100644 src/H5HL.c create mode 100644 src/H5HLprivate.h create mode 100644 src/H5HLpublic.h delete mode 100644 src/H5Hprivate.h delete mode 100644 src/H5Hpublic.h diff --git a/MANIFEST b/MANIFEST index fc11d73..e3a7e89 100644 --- a/MANIFEST +++ b/MANIFEST @@ -133,9 +133,12 @@ ./src/H5Gprivate.h ./src/H5Gpublic.h ./src/H5Gstab.c -./src/H5H.c -./src/H5Hprivate.h -./src/H5Hpublic.h +./src/H5HG.c +./src/H5HGprivate.h +./src/H5HGpublic.h +./src/H5HL.c +./src/H5HLprivate.h +./src/H5HLpublic.h ./src/H5I.c ./src/H5Iprivate.h ./src/H5Ipublic.h @@ -199,7 +202,6 @@ ./test/tstab.c ./testpar/Makefile.irix64 ./testpar/README -./testpar/phdf5sup.c ./testpar/testphdf5.c ./tgif/APIGrammar.obj ./tgif/FileGrammar.obj diff --git a/bin/release b/bin/release index dc48b59..010acbb 100755 --- a/bin/release +++ b/bin/release @@ -84,7 +84,8 @@ sub manifest () { my ($dir) = $fname =~ m%(.*)/CVS/Entries%; open ENTRIES, $fname or die "unable to open $fname"; while () { - my ($ename) = m%^/(.*?)/%; + my ($ename); + next unless ($ename) = m%^/([^/]+)/[^-]%; $ename = "$dir/" . $ename; if (exists $manifest{$ename}) { delete $manifest{$ename}; diff --git a/src/H5AC.c b/src/H5AC.c index 4f35a25..23e86e4 100644 --- a/src/H5AC.c +++ b/src/H5AC.c @@ -851,9 +851,12 @@ H5AC_debug(H5F_t *f) case H5AC_SNODE_ID: strcpy(s, "symbol table nodes"); break; - case H5AC_HEAP_ID: - strcpy(s, "heaps"); + case H5AC_LHEAP_ID: + strcpy (s, "local heaps"); break; + case H5AC_GHEAP_ID: + strcpy (s, "global heaps"); + break; case H5AC_OHDR_ID: strcpy(s, "object headers"); break; diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h index ba5be6d..b17bf33 100644 --- a/src/H5ACprivate.h +++ b/src/H5ACprivate.h @@ -50,11 +50,12 @@ * by the LOAD method if the DEST argument is non-zero. */ typedef enum H5AC_subid_t { - H5AC_BT_ID = 0, /*B-tree nodes */ - H5AC_SNODE_ID = 1, /*symbol table nodes */ - H5AC_HEAP_ID = 2, /*object or name heap */ - H5AC_OHDR_ID = 3, /*object header */ - H5AC_NTYPES = 4 /*THIS MUST BE LAST! */ + H5AC_BT_ID = 0, /*B-tree nodes */ + H5AC_SNODE_ID = 1, /*symbol table nodes */ + H5AC_LHEAP_ID = 2, /*local heap */ + H5AC_GHEAP_ID = 3, /*global heap */ + H5AC_OHDR_ID = 4, /*object header */ + H5AC_NTYPES = 5 /*THIS MUST BE LAST! */ } H5AC_subid_t; typedef struct H5AC_class_t { diff --git a/src/H5D.c b/src/H5D.c index b4f8766..8a527cd 100644 --- a/src/H5D.c +++ b/src/H5D.c @@ -22,7 +22,7 @@ static char RcsId[] = "@(#)$Revision$"; #include /* Dataset functions */ #include /* Error handling */ #include /* Group headers */ -#include /* Name heap */ +#include /* Name heap */ #include /* File space allocation header */ #include /* Memory management */ #include /* Object headers */ @@ -850,12 +850,12 @@ H5D_create(H5G_t *loc, const char *name, const H5T_t *type, const H5S_t *space, /* Update external storage message */ if (efl->nused>0) { - size_t heap_size = H5H_ALIGN (1); + size_t heap_size = H5HL_ALIGN (1); for (i=0; inused; i++) { - heap_size += H5H_ALIGN (strlen (efl->slot[i].name)+1); + heap_size += H5HL_ALIGN (strlen (efl->slot[i].name)+1); } - if (H5H_create (f, H5H_LOCAL, heap_size, &(efl->heap_addr))<0 || - (size_t)(-1)==H5H_insert (f, &(efl->heap_addr), 1, "")) { + if (H5HL_create (f, heap_size, &(efl->heap_addr))<0 || + (size_t)(-1)==H5HL_insert (f, &(efl->heap_addr), 1, "")) { HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, NULL, "unable to create external file list name heap"); } diff --git a/src/H5F.c b/src/H5F.c index 6acdf81..4bec710 100644 --- a/src/H5F.c +++ b/src/H5F.c @@ -79,7 +79,6 @@ const H5F_create_t H5F_create_dflt = { sizeof(size_t), /* Default offset size */ sizeof(size_t), /* Default length size */ HDF5_BOOTBLOCK_VERSION, /* Current Boot-Block version # */ - HDF5_SMALLOBJECT_VERSION, /* Current Small-Object heap version # */ HDF5_FREESPACE_VERSION, /* Current Free-Space info version # */ HDF5_OBJECTDIR_VERSION, /* Current Object Directory info version # */ HDF5_SHAREDHEADER_VERSION, /* Current Shared-Header format version # */ @@ -497,7 +496,6 @@ H5F_new(H5F_file_t *shared) f->shared = H5MM_xcalloc(1, sizeof(H5F_file_t)); H5F_addr_undef(&(f->shared->boot_addr)); H5F_addr_undef(&(f->shared->base_addr)); - H5F_addr_undef(&(f->shared->smallobj_addr)); H5F_addr_undef(&(f->shared->freespace_addr)); H5F_addr_undef(&(f->shared->hdf5_eof)); @@ -859,11 +857,6 @@ H5F_open(const char *name, uintn flags, HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "bad boot block version number"); } - cp->smallobject_ver = *p++; - if (cp->smallobject_ver != HDF5_SMALLOBJECT_VERSION) { - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, - "bad small object heap version number"); - } cp->freespace_ver = *p++; if (cp->freespace_ver != HDF5_FREESPACE_VERSION) { HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, @@ -874,6 +867,7 @@ H5F_open(const char *name, uintn flags, HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "bad object dir version number"); } + p++; /*reserved*/ cp->sharedheader_ver = *p++; if (cp->sharedheader_ver != HDF5_SHAREDHEADER_VERSION) { HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, @@ -919,7 +913,6 @@ H5F_open(const char *name, uintn flags, /* Read the variable length part of the boot block... */ variable_size = H5F_SIZEOF_ADDR(f) + /*base address */ - H5F_SIZEOF_ADDR(f) + /*global small obj heap */ H5F_SIZEOF_ADDR(f) + /*global free list addr */ H5F_SIZEOF_ADDR(f) + /*logical file size */ H5G_SIZEOF_ENTRY(f); @@ -933,7 +926,6 @@ H5F_open(const char *name, uintn flags, } p = buf; H5F_addr_decode(f, &p, &(f->shared->base_addr)); - H5F_addr_decode(f, &p, &(f->shared->smallobj_addr)); H5F_addr_decode(f, &p, &(f->shared->freespace_addr)); H5F_addr_decode(f, &p, &(f->shared->hdf5_eof)); if (H5G_ent_decode(f, &p, &root_ent) < 0) { @@ -1258,9 +1250,9 @@ H5F_flush(H5F_t *f, hbool_t invalidate) p += H5F_SIGNATURE_LEN; *p++ = f->shared->create_parms.bootblock_ver; - *p++ = f->shared->create_parms.smallobject_ver; *p++ = f->shared->create_parms.freespace_ver; *p++ = f->shared->create_parms.objectdir_ver; + *p++ = 0; /*reserved*/ *p++ = f->shared->create_parms.sharedheader_ver; assert (H5F_SIZEOF_ADDR(f)<=255); *p++ = (uint8)H5F_SIZEOF_ADDR(f); @@ -1271,7 +1263,6 @@ H5F_flush(H5F_t *f, hbool_t invalidate) UINT16ENCODE(p, f->shared->create_parms.btree_k[H5B_SNODE_ID]); UINT32ENCODE(p, f->shared->consist_flags); H5F_addr_encode(f, &p, &(f->shared->base_addr)); - H5F_addr_encode(f, &p, &(f->shared->smallobj_addr)); H5F_addr_encode(f, &p, &(f->shared->freespace_addr)); H5F_addr_encode(f, &p, &(f->shared->hdf5_eof)); H5G_ent_encode(f, &p, H5G_entof(f->shared->root_grp)); @@ -1570,11 +1561,6 @@ H5F_debug(H5F_t *f, const haddr_t *addr, FILE * stream, intn indent, fprintf(stream, " (abs)\n"); fprintf(stream, "%*s%-*s ", indent, "", fwidth, - "Small object heap address:"); - H5F_addr_print(stream, &(f->shared->smallobj_addr)); - fprintf(stream, " (rel)\n"); - - fprintf(stream, "%*s%-*s ", indent, "", fwidth, "Free list address:"); H5F_addr_print(stream, &(f->shared->freespace_addr)); fprintf(stream, " (rel)\n"); @@ -1603,9 +1589,6 @@ H5F_debug(H5F_t *f, const haddr_t *addr, FILE * stream, intn indent, "Boot block version number:", (unsigned) (f->shared->create_parms.bootblock_ver)); fprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, - "Small object heap version number:", - (unsigned) (f->shared->create_parms.smallobject_ver)); - fprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, "Free list version number:", (unsigned) (f->shared->create_parms.freespace_ver)); fprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index 9b7192a..c4e1fc0 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -229,7 +229,6 @@ typedef struct H5F_create_t { size_t sizeof_addr; /* Number of bytes in an address */ size_t sizeof_size; /* Number of bytes for obj sizes */ intn bootblock_ver; /* Version # of the bootblock */ - intn smallobject_ver;/* Version # of the small-object heap */ intn freespace_ver; /* Version # of the free-space information*/ intn objectdir_ver; /* Version # of the object directory format*/ intn sharedheader_ver;/* Version # of the shared header format */ @@ -398,13 +397,14 @@ typedef struct H5F_file_t { uint32 consist_flags; /* File Consistency Flags */ haddr_t boot_addr; /* Absolute address of boot block */ haddr_t base_addr; /* Absolute base address for rel.addrs. */ - haddr_t smallobj_addr; /* Relative address of small-obj heap */ haddr_t freespace_addr; /* Relative address of free-space info */ haddr_t hdf5_eof; /* Relative addr of end of all hdf5 data*/ struct H5AC_t *cache; /* The object cache */ H5F_create_t create_parms; /* File-creation property list */ H5F_access_t access_parms; /* File-access property list */ struct H5G_t *root_grp; /* Open root group */ + intn ncwfs; /* Num entries on cwfs list */ + struct H5HG_heap_t **cwfs; /* Global heap cache */ } H5F_file_t; /* diff --git a/src/H5G.c b/src/H5G.c index f5162e0..293e3ab 100644 --- a/src/H5G.c +++ b/src/H5G.c @@ -79,7 +79,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/H5Gnode.c b/src/H5Gnode.c index 79b016a..e447742 100644 --- a/src/H5Gnode.c +++ b/src/H5Gnode.c @@ -25,7 +25,7 @@ #include /*B-link trees */ #include /*error handling */ #include /*me */ -#include /*heap */ +#include /*heap */ #include /*file memory management */ #include /*core memory management */ #include /*header messages */ @@ -486,11 +486,11 @@ H5G_node_cmp2(H5F_t *f, void *_lt_key, void *_udata, void *_rt_key) assert(lt_key); assert(rt_key); - if (NULL == (s1 = H5H_peek(f, &(udata->heap_addr), lt_key->offset))) { + if (NULL == (s1 = H5HL_peek(f, &(udata->heap_addr), lt_key->offset))) { HRETURN_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to read symbol name"); } - if (NULL == (s2 = H5H_peek(f, &(udata->heap_addr), rt_key->offset))) { + if (NULL == (s2 = H5HL_peek(f, &(udata->heap_addr), rt_key->offset))) { HRETURN_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to read symbol name"); } @@ -538,7 +538,7 @@ H5G_node_cmp3(H5F_t *f, void *_lt_key, void *_udata, void *_rt_key) FUNC_ENTER(H5G_node_cmp3, FAIL); /* left side */ - if (NULL == (s = H5H_peek(f, &(udata->heap_addr), lt_key->offset))) { + if (NULL == (s = H5HL_peek(f, &(udata->heap_addr), lt_key->offset))) { HRETURN_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to read symbol name"); } @@ -546,7 +546,7 @@ H5G_node_cmp3(H5F_t *f, void *_lt_key, void *_udata, void *_rt_key) HRETURN(-1); /* right side */ - if (NULL == (s = H5H_peek(f, &(udata->heap_addr), rt_key->offset))) { + if (NULL == (s = H5HL_peek(f, &(udata->heap_addr), rt_key->offset))) { HRETURN_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to read symbol name"); } @@ -618,7 +618,7 @@ H5G_node_found(H5F_t *f, const haddr_t *addr, const void *_lt_key, rt = sn->nsyms; while (lt < rt && cmp) { idx = (lt + rt) / 2; - if (NULL == (s = H5H_peek(f, &(bt_udata->heap_addr), + if (NULL == (s = H5HL_peek(f, &(bt_udata->heap_addr), sn->entry[idx].name_off))) { HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to read symbol name"); @@ -739,7 +739,7 @@ H5G_node_insert(H5F_t *f, const haddr_t *addr, rt = sn->nsyms; while (lt < rt) { idx = (lt + rt) / 2; - if (NULL == (s = H5H_peek(f, &(bt_udata->heap_addr), + if (NULL == (s = H5HL_peek(f, &(bt_udata->heap_addr), sn->entry[idx].name_off))) { HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5B_INS_ERROR, "unable to read symbol name"); @@ -760,7 +760,7 @@ H5G_node_insert(H5F_t *f, const haddr_t *addr, /* * Add the new name to the heap. */ - offset = H5H_insert(f, &(bt_udata->heap_addr), HDstrlen(bt_udata->name)+1, + offset = H5HL_insert(f, &(bt_udata->heap_addr), HDstrlen(bt_udata->name)+1, bt_udata->name); bt_udata->ent.name_off = offset; if (0==offset || (size_t)(-1)==offset) { @@ -898,7 +898,7 @@ H5G_node_iterate (H5F_t *f, const haddr_t *addr, void *_udata) if (bt_udata->skip>0) { --bt_udata->skip; } else { - name = H5H_peek (f, &(bt_udata->group->ent.cache.stab.heap_addr), + name = H5HL_peek (f, &(bt_udata->group->ent.cache.stab.heap_addr), name_off[i]); assert (name); n = strlen (name); @@ -983,7 +983,7 @@ H5G_node_debug(H5F_t *f, const haddr_t *addr, FILE * stream, intn indent, for (i = 0; i < sn->nsyms; i++) { fprintf(stream, "%*sSymbol %d:\n", indent - 3, "", i); if (H5F_addr_defined(heap) && - (s = H5H_peek(f, heap, sn->entry[i].name_off))) { + (s = H5HL_peek(f, heap, sn->entry[i].name_off))) { fprintf(stream, "%*s%-*s `%s'\n", indent, "", fwidth, "Name:", s); diff --git a/src/H5Gstab.c b/src/H5Gstab.c index db12c05..be43215 100644 --- a/src/H5Gstab.c +++ b/src/H5Gstab.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include @@ -59,13 +59,13 @@ H5G_stab_create(H5F_t *f, size_t init, H5G_entry_t *self/*out*/) */ assert(f); assert(self); - init = MAX(init, H5H_SIZEOF_FREE(f) + 2); + init = MAX(init, H5HL_SIZEOF_FREE(f) + 2); /* Create symbol table private heap */ - if (H5H_create(f, H5H_LOCAL, init, &(stab.heap_addr) /*out */ ) < 0) { + if (H5HL_create(f, init, &(stab.heap_addr)/*out*/)<0) { HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create heap"); } - name = H5H_insert(f, &(stab.heap_addr), 1, ""); + name = H5HL_insert(f, &(stab.heap_addr), 1, ""); if ((size_t)(-1)==name) { HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't initialize heap"); } diff --git a/src/H5H.c b/src/H5H.c deleted file mode 100644 index 54e537a..0000000 --- a/src/H5H.c +++ /dev/null @@ -1,1004 +0,0 @@ -/*------------------------------------------------------------------------- - * Copyright (C) 1997 National Center for Supercomputing Applications. - * All rights reserved. - * - *------------------------------------------------------------------------- - * - * Created: H5H.c - * Jul 16 1997 - * Robb Matzke - * - * Purpose: Heap functions for the global small object heap - * and for local symbol table name heaps. - * - * Modifications: - * - * Robb Matzke, 5 Aug 1997 - * Added calls to H5E. - * - *------------------------------------------------------------------------- - */ -#include /*library */ -#include /*cache */ -#include /*error handling */ -#include /*self */ -#include /*file memory management */ -#include /*core memory management */ - -#define H5H_FREE_NULL 1 /*end of free list on disk */ -#define PABLO_MASK H5H_mask - -typedef struct H5H_free_t { - size_t offset; /*offset of free block */ - size_t size; /*size of free block */ - struct H5H_free_t *prev; /*previous entry in free list */ - struct H5H_free_t *next; /*next entry in free list */ -} H5H_free_t; - -typedef struct H5H_t { - intn dirty; - haddr_t addr; /*address of data */ - size_t disk_alloc; /*data bytes allocated on disk */ - size_t mem_alloc; /*data bytes allocated in mem */ - uint8 *chunk; /*the chunk, including header */ - H5H_free_t *freelist; /*the free list */ -} H5H_t; - -/* PRIVATE PROTOTYPES */ -static H5H_t *H5H_load(H5F_t *f, const haddr_t *addr, const void *udata1, - void *udata2); -static herr_t H5H_flush(H5F_t *f, hbool_t dest, const haddr_t *addr, - H5H_t *heap); - -/* - * H5H inherits cache-like properties from H5AC - */ -static const H5AC_class_t H5AC_HEAP[1] = {{ - H5AC_HEAP_ID, - (void *(*)(H5F_t *, const haddr_t *, const void *, void *)) H5H_load, - (herr_t (*)(H5F_t *, hbool_t, const haddr_t *, void *)) H5H_flush, -}}; - -/* Interface initialization */ -static intn interface_initialize_g = FALSE; -#define INTERFACE_INIT NULL - - -/*------------------------------------------------------------------------- - * Function: H5H_create - * - * Purpose: Creates a new heap data structure on disk and caches it - * in memory. SIZE_HINT is a hint for the initial size of the - * data area of the heap. If size hint is invalid then a - * reasonable (but probably not optimal) size will be chosen. - * If the heap ever has to grow, then REALLOC_HINT is the - * minimum amount by which the heap will grow. - * - * Return: Success: SUCCEED. The file address of new heap is - * returned through the ADDR argument. - * - * Failure: FAIL - * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jul 16 1997 - * - * Modifications: - * - * Robb Matzke, 5 Aug 1997 - * Takes a flag that determines the type of heap that is - * created. - * - *------------------------------------------------------------------------- - */ -herr_t -H5H_create(H5F_t *f, H5H_type_t heap_type, size_t size_hint, - haddr_t *addr/*out*/) -{ - H5H_t *heap = NULL; - size_t total_size; /*total heap size on disk */ - - FUNC_ENTER(H5H_create, FAIL); - - /* check arguments */ - assert(f); - assert(addr); -#ifndef NDEBUG - if (H5H_GLOBAL == heap_type) { - fprintf(stderr, "H5H_create: a local heap is used as the global " - "heap\n"); - } -#endif - - if (size_hint && size_hint < H5H_SIZEOF_FREE(f)) { - size_hint = H5H_SIZEOF_FREE(f); - } - size_hint = H5H_ALIGN(size_hint); - - /* allocate file version */ - total_size = H5H_SIZEOF_HDR(f) + size_hint; - if (H5MF_alloc(f, H5MF_META, total_size, addr/*out*/) < 0) { - HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, - "unable to allocate file memory"); - } - - /* allocate memory version */ - heap = H5MM_xcalloc(1, sizeof(H5H_t)); - heap->addr = *addr; - H5F_addr_inc(&(heap->addr), H5H_SIZEOF_HDR(f)); - heap->disk_alloc = size_hint; - heap->mem_alloc = size_hint; - heap->chunk = H5MM_xcalloc(1, H5H_SIZEOF_HDR(f) + size_hint); - - /* free list */ - if (size_hint) { - heap->freelist = H5MM_xmalloc(sizeof(H5H_free_t)); - heap->freelist->offset = 0; - heap->freelist->size = size_hint; - heap->freelist->prev = heap->freelist->next = NULL; - } else { - heap->freelist = NULL; - } - - /* add to cache */ - heap->dirty = 1; - if (H5AC_set(f, H5AC_HEAP, addr, heap) < 0) { - heap->chunk = H5MM_xfree(heap->chunk); - heap->freelist = H5MM_xfree(heap->freelist); - HRETURN_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, - "unable to cache heap"); - } - FUNC_LEAVE(SUCCEED); -} - -/*------------------------------------------------------------------------- - * Function: H5H_load - * - * Purpose: Loads a heap from disk. - * - * Return: Success: Ptr to heap memory data structure. - * - * Failure: NULL - * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jul 17 1997 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static H5H_t * -H5H_load(H5F_t *f, const haddr_t *addr, const void *udata1, void *udata2) -{ - uint8 hdr[52]; - const uint8 *p = NULL; - H5H_t *heap = NULL; - H5H_free_t *fl = NULL, *tail = NULL; - size_t free_block = H5H_FREE_NULL; - H5H_t *ret_value = NULL; - - FUNC_ENTER(H5H_load, NULL); - - /* check arguments */ - assert(f); - assert(addr && H5F_addr_defined(addr)); - assert(H5H_SIZEOF_HDR(f) <= sizeof hdr); - assert(!udata1); - assert(!udata2); - - if (H5F_block_read(f, addr, H5H_SIZEOF_HDR(f), hdr) < 0) { - HRETURN_ERROR(H5E_HEAP, H5E_READERROR, NULL, - "unable to read heap header"); - } - p = hdr; - heap = H5MM_xcalloc(1, sizeof(H5H_t)); - - /* magic number */ - if (HDmemcmp(hdr, H5H_MAGIC, H5H_SIZEOF_MAGIC)) { - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, - "bad heap signature"); - } - p += H5H_SIZEOF_MAGIC; - - /* Reserved */ - p += 4; - - /* heap data size */ - H5F_decode_length(f, p, heap->disk_alloc); - heap->mem_alloc = heap->disk_alloc; - - /* free list head */ - H5F_decode_length(f, p, free_block); - if (free_block != H5H_FREE_NULL && free_block >= heap->disk_alloc) { - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, - "bad heap free list"); - } - - /* data */ - H5F_addr_decode(f, &p, &(heap->addr)); - heap->chunk = H5MM_xcalloc(1, H5H_SIZEOF_HDR(f) + heap->mem_alloc); - if (heap->disk_alloc && - H5F_block_read(f, &(heap->addr), heap->disk_alloc, - heap->chunk + H5H_SIZEOF_HDR(f)) < 0) { - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, - "unable to read heap data"); - } - - /* free list */ - while (H5H_FREE_NULL != free_block) { - if (free_block >= heap->disk_alloc) { - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, - "bad heap free list"); - } - fl = H5MM_xmalloc(sizeof(H5H_free_t)); - 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 + H5H_SIZEOF_HDR(f) + free_block; - H5F_decode_length(f, p, free_block); - H5F_decode_length(f, p, fl->size); - - if (fl->offset + fl->size > heap->disk_alloc) { - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, - "bad heap free list"); - } - } - - ret_value = heap; - - done: - if (!ret_value && heap) { - heap->chunk = H5MM_xfree(heap->chunk); - H5MM_xfree(heap); - for (fl = heap->freelist; fl; fl = tail) { - tail = fl->next; - H5MM_xfree(fl); - } - } - FUNC_LEAVE(ret_value); -} - -/*------------------------------------------------------------------------- - * Function: H5H_flush - * - * Purpose: Flushes a heap from memory to disk if it's dirty. Optionally - * deletes the heap from memory. - * - * Return: Success: SUCCEED - * - * Failure: FAIL - * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jul 17 1997 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5H_flush(H5F_t *f, hbool_t destroy, const haddr_t *addr, H5H_t *heap) -{ - uint8 *p = heap->chunk; - H5H_free_t *fl = heap->freelist; - haddr_t hdr_end_addr; - - FUNC_ENTER(H5H_flush, FAIL); - - /* check arguments */ - assert(f); - assert(addr && H5F_addr_defined(addr)); - assert(heap); - - if (heap->dirty) { - /* - * If the heap grew larger than disk storage then move the - * data segment of the heap to a larger contiguous block of - * disk storage. - */ - if (heap->mem_alloc > heap->disk_alloc) { - haddr_t old_addr = heap->addr, new_addr; - if (H5MF_alloc(f, H5MF_META, heap->mem_alloc, - &new_addr/*out*/)<0) { - HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, - "unable to allocate file space for heap"); - } - heap->addr = new_addr; - H5MF_free(f, &old_addr, heap->disk_alloc); - H5E_clear(); /*don't really care if the free failed */ - heap->disk_alloc = heap->mem_alloc; - } - - /* - * Write the header. - */ - HDmemcpy(p, H5H_MAGIC, H5H_SIZEOF_MAGIC); - p += H5H_SIZEOF_MAGIC; - *p++ = 0; /*reserved*/ - *p++ = 0; /*reserved*/ - *p++ = 0; /*reserved*/ - *p++ = 0; /*reserved*/ - H5F_encode_length(f, p, heap->mem_alloc); - H5F_encode_length(f, p, fl ? fl->offset : H5H_FREE_NULL); - H5F_addr_encode(f, &p, &(heap->addr)); - - /* - * Write the free list. - */ - while (fl) { - assert (fl->offset == H5H_ALIGN (fl->offset)); - p = heap->chunk + H5H_SIZEOF_HDR(f) + fl->offset; - if (fl->next) { - H5F_encode_length(f, p, fl->next->offset); - } else { - H5F_encode_length(f, p, H5H_FREE_NULL); - } - H5F_encode_length(f, p, fl->size); - fl = fl->next; - } - - /* - * Copy buffer to disk. - */ - hdr_end_addr = *addr; - H5F_addr_inc(&hdr_end_addr, H5H_SIZEOF_HDR(f)); - if (H5F_addr_eq(&(heap->addr), &hdr_end_addr)) { - /* The header and data are contiguous */ - if (H5F_block_write(f, addr, H5H_SIZEOF_HDR(f) + heap->disk_alloc, - heap->chunk) < 0) { - HRETURN_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, - "unable to write heap header and data to disk"); - } - } else { - if (H5F_block_write(f, addr, H5H_SIZEOF_HDR(f), heap->chunk) < 0) { - HRETURN_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, - "unable to write heap header to disk"); - } - if (H5F_block_write(f, &(heap->addr), heap->disk_alloc, - heap->chunk + H5H_SIZEOF_HDR(f)) < 0) { - HRETURN_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, - "unable to write heap data to disk"); - } - } - - heap->dirty = 0; - } - - /* - * Should we destroy the memory version? - */ - if (destroy) { - heap->chunk = H5MM_xfree(heap->chunk); - while (heap->freelist) { - fl = heap->freelist; - heap->freelist = fl->next; - H5MM_xfree(fl); - } - H5MM_xfree(heap); - } - FUNC_LEAVE(SUCCEED); -} - -/*------------------------------------------------------------------------- - * Function: H5H_read - * - * Purpose: Reads some object (or part of an object) from the heap - * whose address is ADDR in file F. OFFSET is the byte offset - * from the beginning of the heap at which to begin reading - * and SIZE is the number of bytes to read. - * - * If BUF is the null pointer then a buffer is allocated by - * this function. - * - * Attempting to read past the end of an object may cause this - * function to fail. - * - * If the heap address ADDR is the the null pointer then the - * address comes from the H5F_t global heap field. - * - * Return: Success: BUF (or the allocated buffer) - * - * Failure: NULL - * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jul 16 1997 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -void * -H5H_read(H5F_t *f, const haddr_t *addr, size_t offset, size_t size, void *buf) -{ - H5H_t *heap = NULL; - - FUNC_ENTER(H5H_read, NULL); - - /* check arguments */ - assert(f); - if (!addr) addr = &(f->shared->smallobj_addr); - assert(H5F_addr_defined(addr)); - - if (NULL == (heap = H5AC_find(f, H5AC_HEAP, addr, NULL, NULL))) { - HRETURN_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, - "unable to load heap"); - } - assert(offset < heap->mem_alloc); - assert(offset + size <= heap->mem_alloc); - - if (!buf) buf = H5MM_xmalloc(size); - HDmemcpy(buf, heap->chunk + H5H_SIZEOF_HDR(f) + offset, size); - - FUNC_LEAVE(buf); -} - -/*------------------------------------------------------------------------- - * Function: H5H_peek - * - * Purpose: This function is a more efficient version of H5H_read. - * Instead of copying a heap object into a caller-supplied - * buffer, this function returns a pointer directly into the - * cache where the heap is being held. Thus, the return pointer - * is valid only until the next call to the cache. - * - * The address of the heap is ADDR in file F. OFFSET is the - * byte offset of the object from the beginning of the heap and - * may include an offset into the interior of the object. - * - * If the heap address ADDR is the null pointer then - * the address comes from the H5F_t global heap field. - * - * 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. - * - * Failure: NULL - * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jul 16 1997 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -const void * -H5H_peek(H5F_t *f, const haddr_t *addr, size_t offset) -{ - H5H_t *heap = NULL; - const void *retval = NULL; - - FUNC_ENTER(H5H_peek, NULL); - - /* check arguments */ - assert(f); - if (!addr) addr = &(f->shared->smallobj_addr); - assert(H5F_addr_defined(addr)); - - if (NULL == (heap = H5AC_find(f, H5AC_HEAP, addr, NULL, NULL))) { - HRETURN_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, - "unable to load heap"); - } - assert(offset < heap->mem_alloc); - - retval = heap->chunk + H5H_SIZEOF_HDR(f) + offset; - FUNC_LEAVE(retval); -} - -/*------------------------------------------------------------------------- - * Function: H5H_remove_free - * - * Purpose: Removes free list element FL from the specified heap and - * frees it. - * - * Return: NULL - * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jul 17 1997 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static H5H_free_t * -H5H_remove_free(H5H_t *heap, H5H_free_t *fl) -{ - if (fl->prev) fl->prev->next = fl->next; - if (fl->next) fl->next->prev = fl->prev; - - if (!fl->prev) heap->freelist = fl->next; - return H5MM_xfree(fl); -} - -/*------------------------------------------------------------------------- - * Function: H5H_insert - * - * Purpose: Inserts a new item into the heap. - * - * If the heap address ADDR is the null pointer then - * the address comes from the H5F_t global heap field. - * - * Return: Success: Offset of new item within heap. - * - * Failure: (size_t)(-1) - * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jul 17 1997 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -size_t -H5H_insert(H5F_t *f, const haddr_t *addr, size_t buf_size, const void *buf) -{ - H5H_t *heap = NULL; - H5H_free_t *fl = NULL, *max_fl = NULL; - size_t offset = 0; - size_t need_size, old_size, need_more; - hbool_t found; -#ifndef NDEBUG - static int nmessages = 0; -#endif - - FUNC_ENTER(H5H_insert, (size_t)(-1)); - - /* check arguments */ - assert(f); - if (!addr) addr = &(f->shared->smallobj_addr); - assert(H5F_addr_defined(addr)); - assert(buf_size > 0); - assert(buf); - - if (NULL == (heap = H5AC_find(f, H5AC_HEAP, addr, NULL, NULL))) { - HRETURN_ERROR(H5E_HEAP, H5E_CANTLOAD, (size_t)(-1), - "unable to load heap"); - } - heap->dirty += 1; - - /* - * 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 - * a word. - */ - need_size = H5H_ALIGN(buf_size); - - /* - * Look for a free slot large enough for this object and which would - * leave zero or at least H5G_SIZEOF_FREE bytes left over. - */ - for (fl=heap->freelist, found=FALSE; fl; fl=fl->next) { - if (fl->size > need_size && - fl->size - need_size >= H5H_SIZEOF_FREE(f)) { - /* a bigger free block was found */ - offset = fl->offset; - fl->offset += need_size; - fl->size -= need_size; - assert (fl->offset==H5H_ALIGN (fl->offset)); - assert (fl->size==H5H_ALIGN (fl->size)); - found = TRUE; - break; - } else if (fl->size == need_size) { - /* free block of exact size found */ - offset = fl->offset; - fl = H5H_remove_free(heap, fl); - found = TRUE; - break; - } else if (!max_fl || max_fl->offset < fl->offset) { - /* use worst fit */ - max_fl = fl; - } - } - - /* - * If no free chunk was large enough, then allocate more space and - * add it to the free list. If the heap ends with a free chunk, we - * can extend that free chunk. Otherwise we'll have to make another - * free chunk. If the heap must expand, we double its size. - */ - if (found==FALSE) { - need_more = MAX3(need_size, heap->mem_alloc, H5H_SIZEOF_FREE(f)); - - if (max_fl && max_fl->offset + max_fl->size == heap->mem_alloc) { - /* - * Increase the size of the maximum free block. - */ - offset = max_fl->offset; - max_fl->offset += need_size; - max_fl->size += need_more - need_size; - assert (max_fl->offset==H5H_ALIGN (max_fl->offset)); - assert (max_fl->size==H5H_ALIGN (max_fl->size)); - - if (max_fl->size < H5H_SIZEOF_FREE(f)) { -#ifndef NDEBUG - if (max_fl->size) { - fprintf(stderr, "H5H_insert: lost %lu bytes at line %d\n", - (unsigned long) (max_fl->size), __LINE__); - if (0 == nmessages++) { - fprintf(stderr, "Messages from H5H_insert() will go " - "away when assertions are turned off.\n"); - } - } -#endif - max_fl = H5H_remove_free(heap, max_fl); - } - } else { - /* - * Create a new free list element large enough that we can - * take some space out of it right away. - */ - offset = heap->mem_alloc; - if (need_more - need_size >= H5H_SIZEOF_FREE(f)) { - fl = H5MM_xmalloc(sizeof(H5H_free_t)); - fl->offset = heap->mem_alloc + need_size; - fl->size = need_more - need_size; - assert (fl->offset==H5H_ALIGN (fl->offset)); - assert (fl->size==H5H_ALIGN (fl->size)); - fl->prev = NULL; - fl->next = heap->freelist; - if (heap->freelist) heap->freelist->prev = fl; - heap->freelist = fl; -#ifndef NDEBUG - } else if (need_more > need_size) { - fprintf(stderr, "H5H_insert: lost %lu bytes at line %d\n", - (unsigned long) (need_more - need_size), __LINE__); - if (0 == nmessages++) { - fprintf(stderr, "Messages from H5H_insert() will go away " - "when assertions are turned off.\n"); - } -#endif - } - } - -#ifndef NDEBUG - fprintf(stderr, "H5H_insert: resize mem buf from %lu to %lu bytes\n", - (unsigned long) (heap->mem_alloc), - (unsigned long) (heap->mem_alloc + need_more)); - if (0 == nmessages++) { - fprintf(stderr, "Messages from H5H_insert() will go away " - "when assertions are turned off.\n"); - } -#endif - old_size = heap->mem_alloc; - heap->mem_alloc += need_more; - heap->chunk = H5MM_xrealloc(heap->chunk, - H5H_SIZEOF_HDR(f) + heap->mem_alloc); - - /* clear new section so junk doesn't appear in the file */ - HDmemset(heap->chunk + H5H_SIZEOF_HDR(f) + old_size, 0, need_more); - } - /* - * Copy the data into the heap - */ - HDmemcpy(heap->chunk + H5H_SIZEOF_HDR(f) + offset, buf, buf_size); - FUNC_LEAVE(offset); -} - -/*------------------------------------------------------------------------- - * Function: H5H_write - * - * Purpose: Writes (overwrites) the object (or part of object) stored - * in BUF to the heap at file address ADDR in file F. The - * writing begins at byte offset OFFSET from the beginning of - * the heap and continues for SIZE bytes. - * - * Do not partially write an object to create it; the first - * write for an object must be for the entire object. - * - * If the heap address ADDR is the null pointer then - * the address comes from the H5F_t global heap field. - * - * Return: Success: SUCCEED - * - * Failure: FAIL - * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jul 16 1997 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5H_write(H5F_t *f, const haddr_t *addr, size_t offset, size_t size, - const void *buf) -{ - H5H_t *heap = NULL; - - FUNC_ENTER(H5H_write, FAIL); - - /* check arguments */ - assert(f); - if (!addr) addr = &(f->shared->smallobj_addr); - assert(H5F_addr_defined(addr)); - assert(buf); - assert (offset==H5H_ALIGN (offset)); - - if (NULL == (heap = H5AC_find(f, H5AC_HEAP, addr, NULL, NULL))) { - HRETURN_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, - "unable to load heap"); - } - assert(offset < heap->mem_alloc); - assert(offset + size <= heap->mem_alloc); - - heap->dirty += 1; - HDmemcpy(heap->chunk + H5H_SIZEOF_HDR(f) + offset, buf, size); - - FUNC_LEAVE(SUCCEED); -} - -/*------------------------------------------------------------------------- - * Function: H5H_remove - * - * Purpose: Removes an object or part of an object from the heap at - * address ADDR of file F. The object (or part) to remove - * begins at byte OFFSET from the beginning of the heap and - * continues for SIZE bytes. - * - * Once part of an object is removed, one must not attempt - * to access that part. Removing the beginning of an object - * results in the object OFFSET increasing by the amount - * truncated. Removing the end of an object results in - * object truncation. Removing the middle of an object results - * in two separate objects, one at the original offset and - * one at the first offset past the removed portion. - * - * If the heap address ADDR is the null pointer then - * the address comes from the H5F_t global heap field. - * - * Return: Success: SUCCEED - * - * Failure: FAIL - * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jul 16 1997 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5H_remove(H5F_t *f, const haddr_t *addr, size_t offset, size_t size) -{ - H5H_t *heap = NULL; - H5H_free_t *fl = heap->freelist, *fl2 = NULL; -#ifndef NDEBUG - static int nmessages = 0; -#endif - - FUNC_ENTER(H5H_remove, FAIL); - - /* check arguments */ - assert(f); - if (!addr) addr = &(f->shared->smallobj_addr); - assert(H5F_addr_defined(addr)); - assert(size > 0); - assert (offset==H5H_ALIGN (offset)); - size = H5H_ALIGN (size); - - if (NULL == (heap = H5AC_find(f, H5AC_HEAP, addr, NULL, NULL))) { - HRETURN_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, - "unable to load heap"); - } - assert(offset < heap->mem_alloc); - assert(offset + size <= heap->mem_alloc); - - heap->dirty += 1; - - /* - * Check if this chunk can be prepended or appended to an already - * free chunk. It might also fall between two chunks in such a way - * that all three chunks can be combined into one. - */ - while (fl) { - if (offset + size == fl->offset) { - fl->offset = offset; - fl->size += size; - assert (fl->offset==H5H_ALIGN (fl->offset)); - assert (fl->size==H5H_ALIGN (fl->size)); - fl2 = fl->next; - while (fl2) { - if (fl2->offset + fl2->size == fl->offset) { - fl->offset = fl2->offset; - fl->size += fl2->size; - assert (fl->offset==H5H_ALIGN (fl->offset)); - assert (fl->size==H5H_ALIGN (fl->size)); - fl2 = H5H_remove_free(heap, fl2); - HRETURN(SUCCEED); - } - } - HRETURN(SUCCEED); - - } else if (fl->offset + fl->size == offset) { - fl->size += size; - fl2 = fl->next; - assert (fl->size==H5H_ALIGN (fl->size)); - while (fl2) { - if (fl->offset + fl->size == fl2->offset) { - fl->size += fl2->size; - assert (fl->size==H5H_ALIGN (fl->size)); - fl2 = H5H_remove_free(heap, fl2); - HRETURN(SUCCEED); - } - } - HRETURN(SUCCEED); - } - fl = fl->next; - } - - /* - * The amount which is being removed must be large enough to - * hold the free list data. If not, the freed chunk is forever - * lost. - */ - if (size < H5H_SIZEOF_FREE(f)) { -#ifndef NDEBUG - fprintf(stderr, "H5H_remove: lost %lu bytes\n", (unsigned long) size); - if (0 == nmessages++) { - fprintf(stderr, "Messages from H5H_remove() will go away " - "when assertions are turned off.\n"); - } -#endif - HRETURN(SUCCEED); - } - /* - * Add an entry to the free list. - */ - fl = H5MM_xmalloc(sizeof(H5H_free_t)); - fl->offset = offset; - fl->size = size; - assert (fl->offset==H5H_ALIGN (fl->offset)); - assert (fl->size==H5H_ALIGN (fl->size)); - fl->prev = NULL; - fl->next = heap->freelist; - if (heap->freelist) heap->freelist->prev = fl; - heap->freelist = fl; - - FUNC_LEAVE(SUCCEED); -} - -/*------------------------------------------------------------------------- - * Function: H5H_debug - * - * Purpose: Prints debugging information about a heap. - * - * If the heap address ADDR is the null pointer then - * the address comes from the H5F_t global heap field. - * - * Return: Success: SUCCEED - * - * Failure: FAIL - * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Aug 1 1997 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5H_debug(H5F_t *f, const haddr_t *addr, FILE * stream, intn indent, - intn fwidth) -{ - H5H_t *h = NULL; - int i, j, overlap; - uint8 c; - H5H_free_t *freelist = NULL; - uint8 *marker = NULL; - size_t amount_free = 0; - - FUNC_ENTER(H5H_debug, FAIL); - - /* check arguments */ - assert(f); - if (!addr) - addr = &(f->shared->smallobj_addr); - assert(H5F_addr_defined(addr)); - assert(stream); - assert(indent >= 0); - assert(fwidth >= 0); - - if (NULL == (h = H5AC_find(f, H5AC_HEAP, addr, NULL, NULL))) { - HRETURN_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, - "unable to load heap"); - } - fprintf(stream, "%*sHeap...\n", indent, ""); - fprintf(stream, "%*s%-*s %d\n", indent, "", fwidth, - "Dirty:", - (int) (h->dirty)); - fprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth, - "Data bytes allocated on disk:", - (unsigned long) (h->disk_alloc)); - fprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth, - "Data bytes allocated in core:", - (unsigned long) (h->mem_alloc)); - - /* - * 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. - */ - marker = H5MM_xcalloc(h->mem_alloc, 1); - for (freelist = h->freelist; freelist; freelist = freelist->next) { - fprintf(stream, "%*s%-*s %8lu, %8lu\n", indent, "", fwidth, - "Free Block (offset,size):", - (unsigned long) (freelist->offset), - (unsigned long) (freelist->size)); - if (freelist->offset + freelist->size > h->mem_alloc) { - fprintf(stream, "***THAT FREE BLOCK IS OUT OF BOUNDS!\n"); - } else { - for (i = overlap = 0; i < freelist->size; i++) { - if (marker[freelist->offset + i]) - overlap++; - marker[freelist->offset + i] = 1; - } - if (overlap) { - fprintf(stream, "***THAT FREE BLOCK OVERLAPPED A PREVIOUS ONE!\n"); - } else { - amount_free += freelist->size; - } - } - } - - if (h->mem_alloc) { - fprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth, - "Percent of heap used:", - (unsigned long) (100 * (h->mem_alloc - amount_free) / - h->mem_alloc)); - } - /* - * Print the data in a VMS-style octal dump. - */ - fprintf(stream, "%*sData follows (`__' indicates free region)...\n", - indent, ""); - for (i = 0; i < h->disk_alloc; i += 16) { - fprintf(stream, "%*s %8d: ", indent, "", i); - for (j = 0; j < 16; j++) { - if (i + j < h->disk_alloc) { - if (marker[i + j]) { - fprintf(stream, "__ "); - } else { - c = h->chunk[H5H_SIZEOF_HDR(f) + i + j]; - fprintf(stream, "%02x ", c); - } - } else { - fprintf(stream, " "); - } - if (7 == j) - HDfputc(' ', stream); - } - - for (j = 0; j < 16; j++) { - if (i + j < h->disk_alloc) { - if (marker[i + j]) { - HDfputc(' ', stream); - } else { - c = h->chunk[H5H_SIZEOF_HDR(f) + i + j]; - if (c > ' ' && c < '~') - HDfputc(c, stream); - else - HDfputc('.', stream); - } - } - } - - HDfputc('\n', stream); - } - - H5MM_xfree(marker); - FUNC_LEAVE(SUCCEED); -} diff --git a/src/H5HG.c b/src/H5HG.c new file mode 100644 index 0000000..63b41a3 --- /dev/null +++ b/src/H5HG.c @@ -0,0 +1,887 @@ +/* + * Copyright (C) 1998 NCSA + * All rights reserved. + * + * Programmer: Robb Matzke + * Friday, March 27, 1998 + * + * Purpose: Operations on the global heap. The global heap is the set of + * all collections and each collection contains one or more + * global heap objects. An object belongs to exactly one + * collection. A collection is treated as an atomic entity for + * the purposes of I/O and caching. + * + * Each file has a small cache of global heap collections called + * the CWFS list and recently accessed collections with free + * space appear on this list. As collections are accessed the + * collection is moved toward the front of the list. New + * collections are added to the front of the list while old + * collections are added to the end of the list. + * + * The collection model reduces the overhead which would be + * incurred if the global heap were a single object, and the + * CWFS list allows the library to cheaply choose a collection + * for a new object based on object size, amount of free space + * in the collection, and temporal locality. + */ +#include /*library */ +#include /*caching */ +#include /*error handling */ +#include /*global heaps */ +#include /*file memory management */ +#include /*memory management */ + +#define PABLO_MASK H5HG_mask + +struct H5HG_t { + haddr_t addr; /*address of collection */ + intn idx; /*object ID within collection */ +}; + +typedef struct H5HG_obj_t { + intn nrefs; /*reference count */ + size_t size; /*total size of object */ + uint8 *begin; /*ptr to object into heap->chunk*/ +} H5HG_obj_t; + +typedef struct H5HG_heap_t { + haddr_t addr; /*collection address */ + hbool_t dirty; /*does heap need to be saved? */ + size_t size; /*total size of collection */ + uint8 *chunk; /*the collection, incl. header */ + intn nalloc; /*numb object slots allocated */ + H5HG_obj_t *obj; /*array of object descriptions */ +} H5HG_heap_t; + +/* PRIVATE PROTOTYPES */ +static H5HG_heap_t *H5HG_load(H5F_t *f, const haddr_t *addr, + const void *udata1, void *udata2); +static herr_t H5HG_flush(H5F_t *f, hbool_t dest, const haddr_t *addr, + H5HG_heap_t *heap); + +/* + * H5HG inherits cache-like properties from H5AC + */ +static const H5AC_class_t H5AC_GHEAP[1] = {{ + H5AC_GHEAP_ID, + (void *(*)(H5F_t*, const haddr_t*, const void*, void*))H5HG_load, + (herr_t (*)(H5F_t*, hbool_t, const haddr_t*, void*))H5HG_flush, +}}; + +/* Interface initialization */ +static intn interface_initialize_g = FALSE; +#define INTERFACE_INIT NULL + + +/*------------------------------------------------------------------------- + * Function: H5HG_create + * + * Purpose: Creates a global heap collection of the specified size. If + * SIZE is less than some minimum it will be readjusted. The + * new collection is allocated in the file and added to the + * beginning of the CWFS list. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Friday, March 27, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5HG_create (H5F_t *f, size_t size) +{ + H5HG_heap_t *heap = NULL; + herr_t ret_value = FAIL; + uint8 *p = NULL; + haddr_t addr; + + FUNC_ENTER (H5HG_create, FAIL); + + /* Check args */ + assert (f); + if (sizeaddr = addr; + heap->size = size; + heap->dirty = TRUE; + heap->chunk = H5MM_xmalloc (size); + heap->nalloc = H5HG_NOBJS (f, size); + heap->obj = H5MM_xcalloc (heap->nalloc, sizeof(H5HG_obj_t)); + + /* Initialize the header */ + HDmemcpy (heap->chunk, H5HG_MAGIC, H5HG_SIZEOF_MAGIC); + p = heap->chunk + H5HG_SIZEOF_MAGIC; + *p++ = H5HG_VERSION; + p += 3; /*reserved*/ + H5F_encode_length (f, p, size); + + /* The freespace object */ + heap->obj[0].size = size - H5HG_SIZEOF_HDR (f); + heap->obj[0].begin = p; + UINT16ENCODE (p, 0); /*object ID*/ + UINT16ENCODE (p, 0); /*reference count*/ + H5F_encode_length (f, p, heap->obj[0].size); + HDmemset (p, 0, (heap->chunk+heap->nalloc) - p); + + /* Add the heap to the cache */ + if (H5AC_set (f, H5AC_GHEAP, &addr, heap)<0) { + HGOTO_ERROR (H5E_HEAP, H5E_CANTINIT, FAIL, + "unable to cache global heap collection"); + } + + /* Add this heap to the beginning of the CWFS list */ + if (NULL==f->shared->cwfs) { + f->shared->cwfs = H5MM_xmalloc (H5HG_NCWFS * sizeof(H5HG_heap_t*)); + f->shared->cwfs[0] = heap; + f->shared->ncwfs = 1; + } else { + HDmemmove (f->shared->cwfs+1, f->shared->cwfs, + MIN (f->shared->ncwfs, H5HG_NCWFS-1)*sizeof(H5HG_heap_t*)); + f->shared->cwfs[0] = heap; + f->shared->ncwfs = MIN (H5HG_NCWFS, f->shared->ncwfs+1); + } + + ret_value = SUCCEED; + + done: + if (ret_value<0 && heap) { + H5MM_xfree (heap->chunk); + H5MM_xfree (heap->obj); + H5MM_xfree (heap); + } + FUNC_LEAVE (ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5HG_load + * + * Purpose: Loads a global heap collection from disk. + * + * Return: Success: Ptr to a global heap collection. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * Friday, March 27, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static H5HG_heap_t * +H5HG_load (H5F_t *f, const haddr_t *addr, const void *udata1, void *udata2) +{ + H5HG_heap_t *heap = NULL; + H5HG_heap_t *ret_value = NULL; + uint8 *p = NULL; + intn i; + + FUNC_ENTER (H5HG_load, NULL); + + /* check arguments */ + assert (f); + assert (addr && H5F_addr_defined (addr)); + assert (!udata1); + assert (!udata2); + + /* Read the initial 4k page */ + heap = H5MM_xcalloc (1, sizeof(H5HG_heap_t)); + heap->addr = *addr; + heap->chunk = H5MM_xmalloc (H5HG_MINSIZE); + if (H5F_block_read (f, addr, H5HG_MINSIZE, heap->chunk)<0) { + HGOTO_ERROR (H5E_HEAP, H5E_READERROR, NULL, + "unable to read global heap collection"); + } + + /* Magic number */ + if (HDmemcmp (heap->chunk, H5HG_MAGIC, H5HG_SIZEOF_MAGIC)) { + HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL, + "bad global heap collection signature"); + } + p = heap->chunk + H5HG_SIZEOF_MAGIC; + + /* Version */ + if (H5HG_VERSION!=*p++) { + HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL, + "wrong version number in global heap"); + } + + /* Reserved */ + p += 3; + + /* Size */ + H5F_decode_length (f, p, heap->size); + assert (heap->size>=H5HG_MINSIZE); + + /* + * If we didn't read enough in the first try, then read the rest of the + * collection now. + */ + if (heap->size > H5HG_MINSIZE) { + haddr_t next_addr = *addr; + H5F_addr_inc (&next_addr, H5HG_MINSIZE); + heap->chunk = H5MM_xrealloc (heap->chunk, heap->size); + if (H5F_block_read (f, &next_addr, heap->size-H5HG_MINSIZE, + heap->chunk+H5HG_MINSIZE)<0) { + HGOTO_ERROR (H5E_HEAP, H5E_READERROR, NULL, + "unable to read global heap collection"); + } + } + + /* Decode each object */ + p = heap->chunk + H5HG_SIZEOF_HDR (f); + heap->nalloc = H5HG_NOBJS (f, heap->size); + heap->obj = H5MM_xcalloc (heap->nalloc, sizeof(H5HG_obj_t)); + while (pchunk+heap->size) { + if (p+H5HG_SIZEOF_OBJHDR(f)>heap->chunk+heap->size) { + /* + * The last bit of space is too tiny for an object header, so we + * assume that it's free space. + */ + assert (NULL==heap->obj[0].begin); + heap->obj[0].size = (heap->chunk+heap->size) - p; + heap->obj[0].begin = p; + p += heap->obj[0].size; + } else { + intn idx; + uint8 *begin = p; + UINT16DECODE (p, idx); + assert (idxnalloc); + assert (NULL==heap->obj[idx].begin); + UINT16DECODE (p, heap->obj[idx].nrefs); + H5F_decode_length (f, p, heap->obj[idx].size); + heap->obj[idx].begin = begin; + p += heap->obj[idx].size; + } + } + assert (p==heap->chunk+heap->size); + + /* + * Add the new heap to the CWFS list, removing some other entry if + * necessary to make room. We remove the right-most entry that has less + * free space than this heap. + */ + if (heap->obj[0].size>0) { + if (!f->shared->cwfs) { + f->shared->cwfs = H5MM_xmalloc (H5HG_NCWFS*sizeof(H5HG_heap_t*)); + f->shared->ncwfs = 1; + f->shared->cwfs[0] = heap; + } else if (H5HG_NCWFS==f->shared->ncwfs) { + for (i=H5HG_NCWFS-1; i>=0; --i) { + if (f->shared->cwfs[i]->obj[0].size < heap->obj[0].size) { + HDmemcpy (f->shared->cwfs+1, f->shared->cwfs, + i * sizeof(H5HG_heap_t*)); + f->shared->cwfs[0] = heap; + break; + } + } + } else { + HDmemcpy (f->shared->cwfs+1, f->shared->cwfs, + f->shared->ncwfs*sizeof(H5HG_heap_t*)); + f->shared->ncwfs += 1; + f->shared->cwfs[0] = heap; + } + } + + ret_value = heap; + + done: + if (!ret_value && heap) { + H5MM_xfree (heap->chunk); + H5MM_xfree (heap->obj); + H5MM_xfree (heap); + } + FUNC_LEAVE (ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5HG_flush + * + * Purpose: Flushes a global heap collection from memory to disk if it's + * dirty. Optionally deletes teh heap from memory. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Friday, March 27, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HG_flush (H5F_t *f, hbool_t destroy, const haddr_t *addr, H5HG_heap_t *heap) +{ + int i; + + FUNC_ENTER (H5HG_flush, FAIL); + + /* Check arguments */ + assert (f); + assert (addr && H5F_addr_defined (addr)); + assert (H5F_addr_eq (addr, &(heap->addr))); + assert (heap); + + if (heap->dirty) { + if (H5F_block_write (f, addr, heap->size, heap->chunk)<0) { + HRETURN_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL, + "unable to write global heap collection to file"); + } + heap->dirty = 0; + } + + if (destroy) { + for (i=0; ishared->ncwfs; i++) { + if (f->shared->cwfs[i]==heap) { + f->shared->ncwfs -= 1; + HDmemmove (f->shared->cwfs+i, f->shared->cwfs+i+1, + (f->shared->ncwfs-i) * sizeof(H5HG_heap_t*)); + break; + } + } + heap->chunk = H5MM_xfree (heap->chunk); + heap->obj = H5MM_xfree (heap->obj); + H5MM_xfree (heap); + } + + FUNC_LEAVE (SUCCEED); +} + + +/*------------------------------------------------------------------------- + * Function: H5HG_alloc + * + * Purpose: Given a heap with enough free space, this function will split + * the free space to make a new empty heap object and initialize + * the header. + * + * Return: Success: The heap object ID of the new object. + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Friday, March 27, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static intn +H5HG_alloc (H5F_t *f, H5HG_heap_t *heap, int cwfsno, size_t size) +{ + int idx; + uint8 *p = NULL; + + FUNC_ENTER (H5HG_alloc, FAIL); + + /* Check args */ + assert (heap); + assert (heap->obj[0].size>=size); + + /* + * Find an ID for the new object. ID zero is reserved for the free space + * object. + */ + for (idx=1; idxnalloc; idx++) { + if (NULL==heap->obj[idx].begin) break; + } + assert (idx < heap->nalloc); + + /* Initialize the new object */ + heap->obj[idx].nrefs = 0; + heap->obj[idx].size = size; + heap->obj[idx].begin = heap->obj[0].begin; + p = heap->obj[idx].begin; + UINT16ENCODE (p, idx); + UINT16ENCODE (p, 0); /*nrefs*/ + H5F_encode_length (f, p, size); + + /* Fix the free space object */ + if (size==heap->obj[0].size) { + /* + * All free space has been exhausted from this collection. Remove the + * heap from the CWFS list. + */ + heap->obj[0].size = 0; + heap->obj[0].begin = NULL; + if (cwfsno>=0) { + f->shared->ncwfs -= 1; + HDmemmove (f->shared->cwfs+cwfsno, f->shared->cwfs+cwfsno+1, + (f->shared->ncwfs-cwfsno)*sizeof(H5HG_heap_t*)); + } + + } else if (heap->obj[0].size-size >= H5HG_SIZEOF_OBJHDR (f)) { + /* + * Some free space remains and it's larger than a heap object header, + * so write the new free heap object header to the heap. + */ + heap->obj[0].size -= size; + heap->obj[0].begin += size; + p = heap->obj[0].begin; + UINT16ENCODE (p, 0); /*id*/ + UINT16ENCODE (p, 0); /*nrefs*/ + H5F_encode_length (f, p, heap->obj[0].size); + + } else { + /* + * Some free space remains but it's smaller than a heap object header, + * so we don't write the header. + */ + heap->obj[0].size -= size; + heap->obj[0].begin += size; + } + + heap->dirty = 1; + FUNC_LEAVE (idx); +} + + +/*------------------------------------------------------------------------- + * Function: H5HG_insert + * + * Purpose: A new object is inserted into the global heap. It will be + * placed in the first collection on the CWFS list which has + * enough free space and that collection will be advanced one + * position in the list. If no collection on the CWFS list has + * enough space then a new collection will be created. + * + * It is legal to push a zero-byte object onto the heap to get + * the reference count features of heap objects. + * + * Return: Success: SUCCEED, and a heap object handle returned + * through the HOBJ pointer. + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Friday, March 27, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5HG_insert (H5F_t *f, size_t size, void *obj, H5HG_t *hobj/*out*/) +{ + size_t need; /*total space needed for object */ + intn cwfsno, idx; + H5HG_heap_t *heap = NULL; + + FUNC_ENTER (H5HG_insert, FAIL); + + /* Check args */ + assert (f); + assert (0==size || obj); + assert (hobj); + + /* Find a large enough collection on the CWFS list */ + need = size + H5HG_SIZEOF_OBJHDR (f); + for (cwfsno=0; cwfsnoshared->ncwfs; cwfsno++) { + if (f->shared->cwfs[cwfsno]->obj[0].size>=need) { + /* + * Found. Move the collection forward in the CWFS list. + */ + heap = f->shared->cwfs[cwfsno]; + if (cwfsno>0) { + H5HG_heap_t *tmp = f->shared->cwfs[cwfsno]; + f->shared->cwfs[cwfsno] = f->shared->cwfs[cwfsno-1]; + f->shared->cwfs[cwfsno-1] = tmp; + --cwfsno; + break; + } + } + } + + /* + * If we didn't find any collection with enough free space then allocate a + * new collection large enough for the message plus the collection header. + */ + if (cwfsno>=f->shared->ncwfs) { + if (H5HG_create (f, need+H5HG_SIZEOF_HDR (f))<0) { + HRETURN_ERROR (H5E_HEAP, H5E_CANTINIT, FAIL, + "unable to allocate a global heap collection"); + } + assert (f->shared->ncwfs>0); + assert (f->shared->cwfs[0]->obj[0].size >= need+H5HG_SIZEOF_HDR(f)); + cwfsno = 0; + } + + /* Split the free space to make room for the new object */ + idx = H5HG_alloc (f, heap, cwfsno, need); + assert (idx>0); + + /* Copy data into the heap */ + HDmemcpy (heap->obj[idx].begin+H5HG_SIZEOF_OBJHDR(f), obj, size); + heap->dirty = TRUE; + + /* Return value */ + hobj->addr = heap->addr; + hobj->idx = idx; + FUNC_LEAVE (SUCCEED); +} + + +/*------------------------------------------------------------------------- + * Function: H5HG_peek + * + * Purpose: Given an ID for a global heap object return a pointer to the + * beginning of that object. This is intended for quick and + * dirty access to the object; otherwise use H5HG_read(). + * + * Return: Success: Ptr directly into the H5AC layer for the + * specified object of the global heap. The + * pointer is guaranteed to be valid only until + * some other hdf5 library function is called. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * Monday, March 30, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void * +H5HG_peek (H5F_t *f, H5HG_t *hobj) +{ + H5HG_heap_t *heap = NULL; + void *retval = NULL; + intn i; + + FUNC_ENTER (H5HG_peek, NULL); + + /* Check args */ + assert (f); + assert (hobj); + + /* Load the heap and return a pointer to the object */ + if (NULL==(heap=H5AC_find (f, H5AC_GHEAP, &(hobj->addr), NULL, NULL))) { + HRETURN_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL, "unable to load heap"); + } + assert (hobj->idx>0 && hobj->idxnalloc); + retval = heap->obj[hobj->idx].begin + H5HG_SIZEOF_OBJHDR (f); + assert (retval); + + /* + * Advance the heap in the CWFS list. We might have done this already + * with the H5AC_find(), but it won't hurt to do it twice. + */ + if (heap->obj[0].begin) { + for (i=0; ishared->ncwfs; i++) { + if (f->shared->cwfs[i]==heap) { + if (i) { + f->shared->cwfs[i] = f->shared->cwfs[i-1]; + f->shared->cwfs[i-1] = heap; + } + break; + } + } + } + + FUNC_LEAVE (retval); +} + + +/*------------------------------------------------------------------------- + * Function: H5HG_read + * + * Purpose: Reads the specified global heap object into the buffer OBJECT + * supplied by the caller. If the caller doesn't supply a + * buffer then one will be allocated. The buffer should be + * large enough to hold the result. + * + * Return: Success: The buffer containing the result. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * Monday, March 30, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void * +H5HG_read (H5F_t *f, H5HG_t *hobj, void *object/*out*/) +{ + H5HG_heap_t *heap = NULL; + intn i; + size_t size; + uint8 *p = NULL; + + FUNC_ENTER (H5HG_read, NULL); + + /* Check args */ + assert (f); + assert (hobj); + + /* Load the heap */ + if (NULL==(heap=H5AC_find (f, H5AC_GHEAP, &(hobj->addr), NULL, NULL))) { + HRETURN_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL, "unable to load heap"); + } + assert (hobj->idx>0 && hobj->idxnalloc); + assert (heap->obj[hobj->idx].begin); + size = heap->obj[hobj->idx].size - H5HG_SIZEOF_OBJHDR (f); + p = heap->obj[hobj->idx].begin + H5HG_SIZEOF_OBJHDR (f); + if (!object) object = H5MM_xmalloc (size); + HDmemcpy (object, p, size); + + /* + * Advance the heap in the CWFS list. We might have done this already + * with the H5AC_find(), but it won't hurt to do it twice. + */ + if (heap->obj[0].begin) { + for (i=0; ishared->ncwfs; i++) { + if (f->shared->cwfs[i]==heap) { + if (i) { + f->shared->cwfs[i] = f->shared->cwfs[i-1]; + f->shared->cwfs[i-1] = heap; + } + break; + } + } + } + + FUNC_LEAVE (object); +} + + +/*------------------------------------------------------------------------- + * Function: H5HG_link + * + * Purpose: Adjusts the link count for a global heap object by adding + * ADJUST to the current value. This function will fail if the + * new link count would overflow. Nothing special happens when + * the link count reaches zero; in order for a heap object to be + * removed one must call H5HG_remove(). + * + * Return: Success: Number of links present after the adjustment. + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Monday, March 30, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +intn +H5HG_link (H5F_t *f, H5HG_t *hobj, intn adjust) +{ + H5HG_heap_t *heap = NULL; + + FUNC_ENTER (H5HG_link, FAIL); + + /* Check args */ + assert (f); + assert (hobj); + + /* Load the heap */ + if (NULL==(heap=H5AC_find (f, H5AC_GHEAP, &(hobj->addr), NULL, NULL))) { + HRETURN_ERROR (H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap"); + } + assert (hobj->idx>0 && hobj->idxnalloc); + assert (heap->obj[hobj->idx].begin); + if (heap->obj[hobj->idx].nrefs+adjust<0) { + HRETURN_ERROR (H5E_HEAP, H5E_BADRANGE, FAIL, + "new link count would be out of range"); + } + if (heap->obj[hobj->idx].nrefs+adjust>H5HG_MAXLINK) { + HRETURN_ERROR (H5E_HEAP, H5E_BADVALUE, FAIL, + "new link count would be out of range"); + } + heap->obj[hobj->idx].nrefs += adjust; + if (adjust) heap->dirty = TRUE; + + FUNC_LEAVE (heap->obj[hobj->idx].nrefs); +} + + +/*------------------------------------------------------------------------- + * Function: H5HG_remove + * + * Purpose: Removes the specified object from the global heap. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Monday, March 30, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5HG_remove (H5F_t *f, H5HG_t *hobj) +{ + uint8 *p=NULL, *obj_start=NULL; + H5HG_heap_t *heap = NULL; + size_t size; + intn i; + + FUNC_ENTER (H5HG_remove, FAIL); + + /* Check args */ + assert (f); + assert (hobj); + + /* Load the heap */ + if (NULL==(heap=H5AC_find (f, H5AC_GHEAP, &(hobj->addr), NULL, NULL))) { + HRETURN_ERROR (H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap"); + } + assert (hobj->idx>0 && hobj->idxnalloc); + assert (heap->obj[hobj->idx].begin); + obj_start = heap->obj[hobj->idx].begin; + size = heap->obj[hobj->idx].size; + + /* Move the new free space to the end of the heap */ + for (i=0; inalloc; i++) { + if (heap->obj[i].begin > heap->obj[hobj->idx].begin) { + heap->obj[i].begin -= size; + } + } + if (NULL==heap->obj[0].begin) { + heap->obj[0].begin = heap->chunk + (heap->size-size); + heap->obj[0].size = size; + heap->obj[0].nrefs = 0; + } + HDmemmove (obj_start, obj_start+size, + heap->size-((obj_start+size)-heap->chunk)); + if (heap->obj[0].size>=H5HG_SIZEOF_OBJHDR (f)) { + p = heap->obj[0].begin; + UINT32ENCODE (p, 0); /*id*/ + UINT32ENCODE (p, 0); /*nrefs*/ + H5F_encode_length (f, p, size); + } + HDmemset (heap->obj+hobj->idx, 0, sizeof(H5HG_obj_t)); + heap->dirty = 1; + + if (heap->obj[0].size+H5HG_SIZEOF_HDR(f)==heap->size) { + /* + * The collection is empty. Remove it from the CWFS list and return it + * to the file free list. + */ + heap->dirty = FALSE; + H5MF_free (f, &(heap->addr), heap->size); + H5AC_flush (f, H5AC_GHEAP, &(heap->addr), TRUE); + heap = NULL; + } else { + /* + * If the heap is in the CWFS list then advance it one position. The + * H5AC_find() might have done that too, but that's okay. If the + * heap isn't on the CWFS list then add it to the end. + */ + for (i=0; ishared->ncwfs; i++) { + if (f->shared->cwfs[i]==heap) { + if (i) { + f->shared->cwfs[i] = f->shared->cwfs[i-1]; + f->shared->cwfs[i-1] = heap; + } + break; + } + } + if (i>=f->shared->ncwfs) { + f->shared->ncwfs = MIN (f->shared->ncwfs+1, H5HG_NCWFS); + f->shared->cwfs[f->shared->ncwfs-1] = heap; + } + } + + FUNC_LEAVE (SUCCEED); +} + + +/*------------------------------------------------------------------------- + * Function: H5HG_debug + * + * Purpose: Prints debugging information about a global heap collection. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Mar 27, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5HG_debug(H5F_t *f, const haddr_t *addr, FILE *stream, intn indent, + intn fwidth) +{ + int i, nused, maxobj; + H5HG_heap_t *h = NULL; + char buf[64]; + + FUNC_ENTER(H5HG_debug, FAIL); + + /* check arguments */ + assert(f); + if (addr && H5F_addr_defined (addr)); + assert(stream); + assert(indent >= 0); + assert(fwidth >= 0); + + if (NULL == (h = H5AC_find(f, H5AC_GHEAP, addr, NULL, NULL))) { + HRETURN_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, + "unable to load global heap collection"); + } + fprintf(stream, "%*sGlobal Heap Collection...\n", indent, ""); + fprintf(stream, "%*s%-*s %d\n", indent, "", fwidth, + "Dirty:", + (int)(h->dirty)); + fprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth, + "Total collection size in file:", + (unsigned long)(h->size)); + + for (i=1, nused=0, maxobj=-1; inalloc; i++) { + if (h->obj[i].begin) { + nused++; + if (i>maxobj) maxobj = i; + } + } + fprintf (stream, "%*s%-*s %d/%d/", indent, "", fwidth, + "Objects defined/allocated/max:", + nused, h->nalloc); + fprintf (stream, nused?"%d\n":"NA\n", maxobj); + + fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth, + "Free space:", + (unsigned long)(h->obj[0].size)); + + for (i=1; inalloc; i++) { + if (h->obj[i].begin) { + sprintf (buf, "Object %d", i); + fprintf (stream, "%*s%-*s:\n", indent, "", fwidth, buf); + fprintf (stream, "%*s%-*s %d\n", indent+3, "", MIN(fwidth-3, 0), + "Reference count:", + h->obj[i].nrefs); + fprintf (stream, "%*s%-*s %lu\n", indent+3, "", MIN(fwidth-3, 0), + "Size of object body:", + (unsigned long)(h->obj[i].size)); + } + } + + FUNC_LEAVE(SUCCEED); +} diff --git a/src/H5HGprivate.h b/src/H5HGprivate.h new file mode 100644 index 0000000..aebb3f8 --- /dev/null +++ b/src/H5HGprivate.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 1998 NCSA + * All rights reserved. + * + * Programmer: Robb Matzke + * Friday, March 27, 1998 + */ +#ifndef _H5HGprivate_H +#define _H5HGprivate_H + +#include + +/* + * Each collection has a magic number for some redundancy. + */ +#define H5HG_MAGIC "GCOL" +#define H5HG_SIZEOF_MAGIC 4 + +/* + * Global heap collection version. + */ +#define H5HG_VERSION 1 + +/* + * All global heap collections are at least this big. This allows us to read + * most collections with a single read() since we don't have to read a few + * bytes of header to figure out the size. If the heap is larger than this + * then a second read gets the rest after we've decoded the header. + */ +#define H5HG_MINSIZE 4096 + +/* + * Maximum length of the CWFS list, the list of remembered collections that + * have free space. + */ +#define H5HG_NCWFS 16 + +/* + * The maximum number of links allowed to a global heap object. + */ +#define H5HG_MAXLINK 65535 + +/* + * The size of the collection header. + */ +#define H5HG_SIZEOF_HDR(f) (4 + /*magic number */ \ + 1 + /*version number */ \ + 3 + /*reserved */ \ + H5F_SIZEOF_SIZE(f)) /*collection size */ + +/* + * The overhead associated with each object in the heap. + */ +#define H5HG_SIZEOF_OBJHDR(f) (2 + /*reference count */ \ + 2 + /*reserved */ \ + H5F_SIZEOF_SIZE(f)) /*object data size */ + +/* + * The initial guess for the number of messages in a collection. We assume + * that all objects in that collection are zero length, giving the maximum + * possible number of objects in the collection. The collection itself has + * some overhead and each message has some overhead. + */ +#define H5HG_NOBJS(f,z) (int)((((z)-H5HG_SIZEOF_HDR(f))/ \ + H5HG_SIZEOF_OBJHDR(f)+1)) + +typedef struct H5HG_t H5HG_t; + +herr_t H5HG_create (H5F_t *f, size_t size); +herr_t H5HG_insert (H5F_t *f, size_t size, void *obj, H5HG_t *hobj/*out*/); +void *H5HG_peek (H5F_t *f, H5HG_t *hobj); +void *H5HG_read (H5F_t *f, H5HG_t *hobj, void *object); +intn H5HG_link (H5F_t *f, H5HG_t *hobj, intn adjust); +herr_t H5HG_remove (H5F_t *f, H5HG_t *hobj); +herr_t H5HG_debug(H5F_t *f, const haddr_t *addr, FILE *stream, intn indent, + intn fwidth); + +#endif diff --git a/src/H5HGpublic.h b/src/H5HGpublic.h new file mode 100644 index 0000000..0c561e3 --- /dev/null +++ b/src/H5HGpublic.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) 1998 NCSA + * All rights reserved. + * + * Programmer: Robb Matzke + * Friday, March 27, 1998 + */ +#ifndef _H5HGpublic_H +#define _H5HGpublic_H + +/* Public headers needed by this file */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/H5HL.c b/src/H5HL.c new file mode 100644 index 0000000..f6fa4f0 --- /dev/null +++ b/src/H5HL.c @@ -0,0 +1,972 @@ +/*------------------------------------------------------------------------- + * Copyright (C) 1997 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + * + * Created: H5HL.c + * Jul 16 1997 + * Robb Matzke + * + * Purpose: Heap functions for the local heaps used by symbol + * tables to store names (among other things). + * + * Modifications: + * + * Robb Matzke, 5 Aug 1997 + * Added calls to H5E. + * + *------------------------------------------------------------------------- + */ +#include /*library */ +#include /*cache */ +#include /*error handling */ +#include /*self */ +#include /*file memory management */ +#include /*core memory management */ + +#define H5HL_FREE_NULL 1 /*end of free list on disk */ +#define PABLO_MASK H5HL_mask + +typedef struct H5HL_free_t { + size_t offset; /*offset of free block */ + size_t size; /*size of free block */ + struct H5HL_free_t *prev; /*previous entry in free list */ + struct H5HL_free_t *next; /*next entry in free list */ +} H5HL_free_t; + +typedef struct H5HL_t { + intn dirty; + haddr_t addr; /*address of data */ + size_t disk_alloc; /*data bytes allocated on disk */ + size_t mem_alloc; /*data bytes allocated in mem */ + uint8 *chunk; /*the chunk, including header */ + H5HL_free_t *freelist; /*the free list */ +} H5HL_t; + +/* PRIVATE PROTOTYPES */ +static H5HL_t *H5HL_load(H5F_t *f, const haddr_t *addr, const void *udata1, + void *udata2); +static herr_t H5HL_flush(H5F_t *f, hbool_t dest, const haddr_t *addr, + H5HL_t *heap); + +/* + * H5HL inherits cache-like properties from H5AC + */ +static const H5AC_class_t H5AC_LHEAP[1] = {{ + H5AC_LHEAP_ID, + (void *(*)(H5F_t*, const haddr_t*, const void*, void*))H5HL_load, + (herr_t (*)(H5F_t*, hbool_t, const haddr_t*, void*))H5HL_flush, +}}; + +/* Interface initialization */ +static intn interface_initialize_g = FALSE; +#define INTERFACE_INIT NULL + + +/*------------------------------------------------------------------------- + * Function: H5HL_create + * + * Purpose: Creates a new heap data structure on disk and caches it + * in memory. SIZE_HINT is a hint for the initial size of the + * data area of the heap. If size hint is invalid then a + * reasonable (but probably not optimal) size will be chosen. + * If the heap ever has to grow, then REALLOC_HINT is the + * minimum amount by which the heap will grow. + * + * Return: Success: SUCCEED. The file address of new heap is + * returned through the ADDR argument. + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jul 16 1997 + * + * Modifications: + * + * Robb Matzke, 5 Aug 1997 + * Takes a flag that determines the type of heap that is + * created. + * + *------------------------------------------------------------------------- + */ +herr_t +H5HL_create(H5F_t *f, size_t size_hint, haddr_t *addr/*out*/) +{ + H5HL_t *heap = NULL; + size_t total_size; /*total heap size on disk */ + + FUNC_ENTER(H5HL_create, FAIL); + + /* check arguments */ + assert(f); + assert(addr); + + if (size_hint && size_hint < H5HL_SIZEOF_FREE(f)) { + size_hint = H5HL_SIZEOF_FREE(f); + } + size_hint = H5HL_ALIGN(size_hint); + + /* allocate file version */ + total_size = H5HL_SIZEOF_HDR(f) + size_hint; + if (H5MF_alloc(f, H5MF_META, total_size, addr/*out*/) < 0) { + HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, + "unable to allocate file memory"); + } + + /* allocate memory version */ + heap = H5MM_xcalloc(1, sizeof(H5HL_t)); + heap->addr = *addr; + H5F_addr_inc(&(heap->addr), H5HL_SIZEOF_HDR(f)); + heap->disk_alloc = size_hint; + heap->mem_alloc = size_hint; + heap->chunk = H5MM_xcalloc(1, H5HL_SIZEOF_HDR(f) + size_hint); + + /* free list */ + if (size_hint) { + heap->freelist = H5MM_xmalloc(sizeof(H5HL_free_t)); + heap->freelist->offset = 0; + heap->freelist->size = size_hint; + heap->freelist->prev = heap->freelist->next = NULL; + } else { + heap->freelist = NULL; + } + + /* add to cache */ + heap->dirty = 1; + if (H5AC_set(f, H5AC_LHEAP, addr, heap) < 0) { + heap->chunk = H5MM_xfree(heap->chunk); + heap->freelist = H5MM_xfree(heap->freelist); + HRETURN_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, + "unable to cache heap"); + } + FUNC_LEAVE(SUCCEED); +} + +/*------------------------------------------------------------------------- + * Function: H5HL_load + * + * Purpose: Loads a heap from disk. + * + * Return: Success: Ptr to a local heap memory data structure. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jul 17 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static H5HL_t * +H5HL_load(H5F_t *f, const haddr_t *addr, const void *udata1, void *udata2) +{ + uint8 hdr[52]; + const uint8 *p = NULL; + H5HL_t *heap = NULL; + H5HL_free_t *fl = NULL, *tail = NULL; + size_t free_block = H5HL_FREE_NULL; + H5HL_t *ret_value = NULL; + + FUNC_ENTER(H5HL_load, NULL); + + /* check arguments */ + assert(f); + assert(addr && H5F_addr_defined(addr)); + assert(H5HL_SIZEOF_HDR(f) <= sizeof hdr); + assert(!udata1); + assert(!udata2); + + if (H5F_block_read(f, addr, H5HL_SIZEOF_HDR(f), hdr) < 0) { + HRETURN_ERROR(H5E_HEAP, H5E_READERROR, NULL, + "unable to read heap header"); + } + p = hdr; + heap = H5MM_xcalloc(1, sizeof(H5HL_t)); + + /* magic number */ + if (HDmemcmp(hdr, H5HL_MAGIC, H5HL_SIZEOF_MAGIC)) { + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, + "bad heap signature"); + } + p += H5HL_SIZEOF_MAGIC; + + /* Reserved */ + p += 4; + + /* heap data size */ + H5F_decode_length(f, p, heap->disk_alloc); + heap->mem_alloc = heap->disk_alloc; + + /* free list head */ + H5F_decode_length(f, p, free_block); + if (free_block != H5HL_FREE_NULL && free_block >= heap->disk_alloc) { + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, + "bad heap free list"); + } + + /* data */ + H5F_addr_decode(f, &p, &(heap->addr)); + heap->chunk = H5MM_xcalloc(1, H5HL_SIZEOF_HDR(f) + heap->mem_alloc); + if (heap->disk_alloc && + H5F_block_read(f, &(heap->addr), heap->disk_alloc, + heap->chunk + H5HL_SIZEOF_HDR(f)) < 0) { + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, + "unable to read heap data"); + } + + /* free list */ + while (H5HL_FREE_NULL != free_block) { + if (free_block >= heap->disk_alloc) { + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, + "bad heap free list"); + } + fl = H5MM_xmalloc(sizeof(H5HL_free_t)); + 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 + H5HL_SIZEOF_HDR(f) + free_block; + H5F_decode_length(f, p, free_block); + H5F_decode_length(f, p, fl->size); + + if (fl->offset + fl->size > heap->disk_alloc) { + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, + "bad heap free list"); + } + } + + ret_value = heap; + + done: + if (!ret_value && heap) { + heap->chunk = H5MM_xfree(heap->chunk); + H5MM_xfree(heap); + for (fl = heap->freelist; fl; fl = tail) { + tail = fl->next; + H5MM_xfree(fl); + } + } + FUNC_LEAVE(ret_value); +} + +/*------------------------------------------------------------------------- + * Function: H5HL_flush + * + * Purpose: Flushes a heap from memory to disk if it's dirty. Optionally + * deletes the heap from memory. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jul 17 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HL_flush(H5F_t *f, hbool_t destroy, const haddr_t *addr, H5HL_t *heap) +{ + uint8 *p = heap->chunk; + H5HL_free_t *fl = heap->freelist; + haddr_t hdr_end_addr; + + FUNC_ENTER(H5HL_flush, FAIL); + + /* check arguments */ + assert(f); + assert(addr && H5F_addr_defined(addr)); + assert(heap); + + if (heap->dirty) { + /* + * If the heap grew larger than disk storage then move the + * data segment of the heap to a larger contiguous block of + * disk storage. + */ + if (heap->mem_alloc > heap->disk_alloc) { + haddr_t old_addr = heap->addr, new_addr; + if (H5MF_alloc(f, H5MF_META, heap->mem_alloc, + &new_addr/*out*/)<0) { + HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, + "unable to allocate file space for heap"); + } + heap->addr = new_addr; + H5MF_free(f, &old_addr, heap->disk_alloc); + H5E_clear(); /*don't really care if the free failed */ + heap->disk_alloc = heap->mem_alloc; + } + + /* + * Write the header. + */ + HDmemcpy(p, H5HL_MAGIC, H5HL_SIZEOF_MAGIC); + p += H5HL_SIZEOF_MAGIC; + *p++ = 0; /*reserved*/ + *p++ = 0; /*reserved*/ + *p++ = 0; /*reserved*/ + *p++ = 0; /*reserved*/ + H5F_encode_length(f, p, heap->mem_alloc); + H5F_encode_length(f, p, fl ? fl->offset : H5HL_FREE_NULL); + H5F_addr_encode(f, &p, &(heap->addr)); + + /* + * Write the free list. + */ + while (fl) { + 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); + fl = fl->next; + } + + /* + * Copy buffer to disk. + */ + hdr_end_addr = *addr; + H5F_addr_inc(&hdr_end_addr, H5HL_SIZEOF_HDR(f)); + if (H5F_addr_eq(&(heap->addr), &hdr_end_addr)) { + /* The header and data are contiguous */ + if (H5F_block_write(f, addr, H5HL_SIZEOF_HDR(f) + heap->disk_alloc, + heap->chunk) < 0) { + HRETURN_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, + "unable to write heap header and data to file"); + } + } else { + if (H5F_block_write(f, addr, H5HL_SIZEOF_HDR(f), heap->chunk)<0) { + HRETURN_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, + "unable to write heap header to file"); + } + if (H5F_block_write(f, &(heap->addr), heap->disk_alloc, + heap->chunk + H5HL_SIZEOF_HDR(f)) < 0) { + HRETURN_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, + "unable to write heap data to file"); + } + } + + heap->dirty = 0; + } + + /* + * Should we destroy the memory version? + */ + if (destroy) { + heap->chunk = H5MM_xfree(heap->chunk); + while (heap->freelist) { + fl = heap->freelist; + heap->freelist = fl->next; + H5MM_xfree(fl); + } + H5MM_xfree(heap); + } + FUNC_LEAVE(SUCCEED); +} + +/*------------------------------------------------------------------------- + * Function: H5HL_read + * + * Purpose: Reads some object (or part of an object) from the heap + * whose address is ADDR in file F. OFFSET is the byte offset + * from the beginning of the heap at which to begin reading + * and SIZE is the number of bytes to read. + * + * If BUF is the null pointer then a buffer is allocated by + * this function. + * + * Attempting to read past the end of an object may cause this + * function to fail. + * + * Return: Success: BUF (or the allocated buffer) + * + * Failure: NULL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jul 16 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void * +H5HL_read(H5F_t *f, const haddr_t *addr, size_t offset, size_t size, void *buf) +{ + H5HL_t *heap = NULL; + + FUNC_ENTER(H5HL_read, NULL); + + /* check arguments */ + assert(f); + assert (addr && H5F_addr_defined(addr)); + + if (NULL == (heap = H5AC_find(f, H5AC_LHEAP, addr, NULL, NULL))) { + HRETURN_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, + "unable to load heap"); + } + assert(offset < heap->mem_alloc); + assert(offset + size <= heap->mem_alloc); + + if (!buf) buf = H5MM_xmalloc(size); + HDmemcpy(buf, heap->chunk + H5HL_SIZEOF_HDR(f) + offset, size); + + FUNC_LEAVE(buf); +} + +/*------------------------------------------------------------------------- + * Function: H5HL_peek + * + * Purpose: This function is a more efficient version of H5HL_read. + * Instead of copying a heap object into a caller-supplied + * buffer, this function returns a pointer directly into the + * cache where the heap is being held. Thus, the return pointer + * is valid only until the next call to the cache. + * + * The address of the heap is ADDR in file F. OFFSET is the + * byte offset of the object from the beginning of the heap and + * may include an offset into the interior of the object. + * + * 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. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jul 16 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +const void * +H5HL_peek(H5F_t *f, const haddr_t *addr, size_t offset) +{ + H5HL_t *heap = NULL; + const void *retval = NULL; + + FUNC_ENTER(H5HL_peek, NULL); + + /* check arguments */ + assert(f); + assert(addr && H5F_addr_defined(addr)); + + if (NULL == (heap = H5AC_find(f, H5AC_LHEAP, addr, NULL, NULL))) { + HRETURN_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unable to load heap"); + } + assert(offset < heap->mem_alloc); + + retval = heap->chunk + H5HL_SIZEOF_HDR(f) + offset; + FUNC_LEAVE(retval); +} + +/*------------------------------------------------------------------------- + * Function: H5HL_remove_free + * + * Purpose: Removes free list element FL from the specified heap and + * frees it. + * + * Return: NULL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jul 17 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static H5HL_free_t * +H5HL_remove_free(H5HL_t *heap, H5HL_free_t *fl) +{ + if (fl->prev) fl->prev->next = fl->next; + if (fl->next) fl->next->prev = fl->prev; + + if (!fl->prev) heap->freelist = fl->next; + return H5MM_xfree(fl); +} + +/*------------------------------------------------------------------------- + * Function: H5HL_insert + * + * Purpose: Inserts a new item into the heap. + * + * Return: Success: Offset of new item within heap. + * + * Failure: (size_t)(-1) + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jul 17 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +size_t +H5HL_insert(H5F_t *f, const haddr_t *addr, size_t buf_size, const void *buf) +{ + H5HL_t *heap = NULL; + H5HL_free_t *fl = NULL, *max_fl = NULL; + size_t offset = 0; + size_t need_size, old_size, need_more; + hbool_t found; +#ifndef NDEBUG + static int nmessages = 0; +#endif + + FUNC_ENTER(H5HL_insert, (size_t)(-1)); + + /* check arguments */ + assert(f); + assert(addr && H5F_addr_defined(addr)); + assert(buf_size > 0); + assert(buf); + + if (NULL == (heap = H5AC_find(f, H5AC_LHEAP, addr, NULL, NULL))) { + HRETURN_ERROR(H5E_HEAP, H5E_CANTLOAD, (size_t)(-1), + "unable to load heap"); + } + heap->dirty += 1; + + /* + * 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 + * a word. + */ + need_size = H5HL_ALIGN(buf_size); + + /* + * Look for a free slot large enough for this object and which would + * leave zero or at least H5G_SIZEOF_FREE bytes left over. + */ + for (fl=heap->freelist, found=FALSE; fl; fl=fl->next) { + if (fl->size > need_size && + fl->size - need_size >= H5HL_SIZEOF_FREE(f)) { + /* a bigger free block was found */ + offset = fl->offset; + fl->offset += need_size; + fl->size -= need_size; + assert (fl->offset==H5HL_ALIGN (fl->offset)); + assert (fl->size==H5HL_ALIGN (fl->size)); + found = TRUE; + break; + } else if (fl->size == need_size) { + /* free block of exact size found */ + offset = fl->offset; + fl = H5HL_remove_free(heap, fl); + found = TRUE; + break; + } else if (!max_fl || max_fl->offset < fl->offset) { + /* use worst fit */ + max_fl = fl; + } + } + + /* + * If no free chunk was large enough, then allocate more space and + * add it to the free list. If the heap ends with a free chunk, we + * can extend that free chunk. Otherwise we'll have to make another + * free chunk. If the heap must expand, we double its size. + */ + if (found==FALSE) { + need_more = MAX3(need_size, heap->mem_alloc, H5HL_SIZEOF_FREE(f)); + + if (max_fl && max_fl->offset + max_fl->size == heap->mem_alloc) { + /* + * Increase the size of the maximum free block. + */ + offset = max_fl->offset; + max_fl->offset += need_size; + max_fl->size += need_more - need_size; + assert (max_fl->offset==H5HL_ALIGN (max_fl->offset)); + assert (max_fl->size==H5HL_ALIGN (max_fl->size)); + + if (max_fl->size < H5HL_SIZEOF_FREE(f)) { +#ifndef NDEBUG + if (max_fl->size) { + fprintf(stderr, "H5HL_insert: lost %lu bytes at line %d\n", + (unsigned long) (max_fl->size), __LINE__); + if (0 == nmessages++) { + fprintf(stderr, "Messages from H5HL_insert() will go " + "away when assertions are turned off.\n"); + } + } +#endif + max_fl = H5HL_remove_free(heap, max_fl); + } + } else { + /* + * Create a new free list element large enough that we can + * take some space out of it right away. + */ + offset = heap->mem_alloc; + if (need_more - need_size >= H5HL_SIZEOF_FREE(f)) { + fl = H5MM_xmalloc(sizeof(H5HL_free_t)); + fl->offset = heap->mem_alloc + need_size; + fl->size = need_more - need_size; + assert (fl->offset==H5HL_ALIGN (fl->offset)); + assert (fl->size==H5HL_ALIGN (fl->size)); + fl->prev = NULL; + fl->next = heap->freelist; + if (heap->freelist) heap->freelist->prev = fl; + heap->freelist = fl; +#ifndef NDEBUG + } else if (need_more > need_size) { + fprintf(stderr, "H5HL_insert: lost %lu bytes at line %d\n", + (unsigned long) (need_more - need_size), __LINE__); + if (0 == nmessages++) { + fprintf(stderr, "Messages from H5HL_insert() will go away " + "when assertions are turned off.\n"); + } +#endif + } + } + +#ifndef NDEBUG + fprintf(stderr, "H5HL_insert: resize mem buf from %lu to %lu bytes\n", + (unsigned long) (heap->mem_alloc), + (unsigned long) (heap->mem_alloc + need_more)); + if (0 == nmessages++) { + fprintf(stderr, "Messages from H5HL_insert() will go away " + "when assertions are turned off.\n"); + } +#endif + old_size = heap->mem_alloc; + heap->mem_alloc += need_more; + heap->chunk = H5MM_xrealloc(heap->chunk, + H5HL_SIZEOF_HDR(f) + heap->mem_alloc); + + /* clear new section so junk doesn't appear in the file */ + HDmemset(heap->chunk + H5HL_SIZEOF_HDR(f) + old_size, 0, need_more); + } + /* + * Copy the data into the heap + */ + HDmemcpy(heap->chunk + H5HL_SIZEOF_HDR(f) + offset, buf, buf_size); + FUNC_LEAVE(offset); +} + +/*------------------------------------------------------------------------- + * Function: H5HL_write + * + * Purpose: Writes (overwrites) the object (or part of object) stored + * in BUF to the heap at file address ADDR in file F. The + * writing begins at byte offset OFFSET from the beginning of + * the heap and continues for SIZE bytes. + * + * Do not partially write an object to create it; the first + * write for an object must be for the entire object. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jul 16 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5HL_write(H5F_t *f, const haddr_t *addr, size_t offset, size_t size, + const void *buf) +{ + H5HL_t *heap = NULL; + + FUNC_ENTER(H5HL_write, FAIL); + + /* check arguments */ + assert(f); + assert(addr && H5F_addr_defined(addr)); + assert(buf); + assert (offset==H5HL_ALIGN (offset)); + + if (NULL == (heap = H5AC_find(f, H5AC_LHEAP, addr, NULL, NULL))) { + HRETURN_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, + "unable to load heap"); + } + assert(offset < heap->mem_alloc); + assert(offset + size <= heap->mem_alloc); + + heap->dirty += 1; + HDmemcpy(heap->chunk + H5HL_SIZEOF_HDR(f) + offset, buf, size); + + FUNC_LEAVE(SUCCEED); +} + +/*------------------------------------------------------------------------- + * Function: H5HL_remove + * + * Purpose: Removes an object or part of an object from the heap at + * address ADDR of file F. The object (or part) to remove + * begins at byte OFFSET from the beginning of the heap and + * continues for SIZE bytes. + * + * Once part of an object is removed, one must not attempt + * to access that part. Removing the beginning of an object + * results in the object OFFSET increasing by the amount + * truncated. Removing the end of an object results in + * object truncation. Removing the middle of an object results + * in two separate objects, one at the original offset and + * one at the first offset past the removed portion. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jul 16 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5HL_remove(H5F_t *f, const haddr_t *addr, size_t offset, size_t size) +{ + H5HL_t *heap = NULL; + H5HL_free_t *fl = heap->freelist, *fl2 = NULL; +#ifndef NDEBUG + static int nmessages = 0; +#endif + + FUNC_ENTER(H5HL_remove, FAIL); + + /* check arguments */ + assert(f); + assert(addr && H5F_addr_defined(addr)); + assert(size > 0); + assert (offset==H5HL_ALIGN (offset)); + size = H5HL_ALIGN (size); + + if (NULL == (heap = H5AC_find(f, H5AC_LHEAP, addr, NULL, NULL))) { + HRETURN_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, + "unable to load heap"); + } + assert(offset < heap->mem_alloc); + assert(offset + size <= heap->mem_alloc); + + heap->dirty += 1; + + /* + * Check if this chunk can be prepended or appended to an already + * free chunk. It might also fall between two chunks in such a way + * that all three chunks can be combined into one. + */ + while (fl) { + if (offset + size == fl->offset) { + fl->offset = offset; + fl->size += size; + assert (fl->offset==H5HL_ALIGN (fl->offset)); + assert (fl->size==H5HL_ALIGN (fl->size)); + fl2 = fl->next; + while (fl2) { + if (fl2->offset + fl2->size == fl->offset) { + fl->offset = fl2->offset; + fl->size += fl2->size; + assert (fl->offset==H5HL_ALIGN (fl->offset)); + assert (fl->size==H5HL_ALIGN (fl->size)); + fl2 = H5HL_remove_free(heap, fl2); + HRETURN(SUCCEED); + } + } + HRETURN(SUCCEED); + + } else if (fl->offset + fl->size == offset) { + fl->size += size; + fl2 = fl->next; + assert (fl->size==H5HL_ALIGN (fl->size)); + while (fl2) { + if (fl->offset + fl->size == fl2->offset) { + fl->size += fl2->size; + assert (fl->size==H5HL_ALIGN (fl->size)); + fl2 = H5HL_remove_free(heap, fl2); + HRETURN(SUCCEED); + } + } + HRETURN(SUCCEED); + } + fl = fl->next; + } + + /* + * The amount which is being removed must be large enough to + * hold the free list data. If not, the freed chunk is forever + * lost. + */ + if (size < H5HL_SIZEOF_FREE(f)) { +#ifndef NDEBUG + fprintf(stderr, "H5HL_remove: lost %lu bytes\n", (unsigned long) size); + if (0 == nmessages++) { + fprintf(stderr, "Messages from H5HL_remove() will go away " + "when assertions are turned off.\n"); + } +#endif + HRETURN(SUCCEED); + } + /* + * Add an entry to the free list. + */ + fl = H5MM_xmalloc(sizeof(H5HL_free_t)); + fl->offset = offset; + fl->size = size; + assert (fl->offset==H5HL_ALIGN (fl->offset)); + assert (fl->size==H5HL_ALIGN (fl->size)); + fl->prev = NULL; + fl->next = heap->freelist; + if (heap->freelist) heap->freelist->prev = fl; + heap->freelist = fl; + + FUNC_LEAVE(SUCCEED); +} + +/*------------------------------------------------------------------------- + * Function: H5HL_debug + * + * Purpose: Prints debugging information about a heap. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 1 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5HL_debug(H5F_t *f, const haddr_t *addr, FILE * stream, intn indent, + intn fwidth) +{ + H5HL_t *h = NULL; + int i, j, overlap; + uint8 c; + H5HL_free_t *freelist = NULL; + uint8 *marker = NULL; + size_t amount_free = 0; + + FUNC_ENTER(H5HL_debug, FAIL); + + /* check arguments */ + assert(f); + assert(addr && H5F_addr_defined(addr)); + assert(stream); + assert(indent >= 0); + assert(fwidth >= 0); + + if (NULL == (h = H5AC_find(f, H5AC_LHEAP, addr, NULL, NULL))) { + HRETURN_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, + "unable to load heap"); + } + fprintf(stream, "%*sHeap...\n", indent, ""); + fprintf(stream, "%*s%-*s %d\n", indent, "", fwidth, + "Dirty:", + (int) (h->dirty)); + fprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth, + "Data bytes allocated on disk:", + (unsigned long) (h->disk_alloc)); + fprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth, + "Data bytes allocated in core:", + (unsigned long) (h->mem_alloc)); + + /* + * 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. + */ + marker = H5MM_xcalloc(h->mem_alloc, 1); + for (freelist = h->freelist; freelist; freelist = freelist->next) { + fprintf(stream, "%*s%-*s %8lu, %8lu\n", indent, "", fwidth, + "Free Block (offset,size):", + (unsigned long) (freelist->offset), + (unsigned long) (freelist->size)); + if (freelist->offset + freelist->size > h->mem_alloc) { + fprintf(stream, "***THAT FREE BLOCK IS OUT OF BOUNDS!\n"); + } else { + for (i = overlap = 0; i < freelist->size; i++) { + if (marker[freelist->offset + i]) + overlap++; + marker[freelist->offset + i] = 1; + } + if (overlap) { + fprintf(stream, "***THAT FREE BLOCK OVERLAPPED A PREVIOUS " + "ONE!\n"); + } else { + amount_free += freelist->size; + } + } + } + + if (h->mem_alloc) { + fprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth, + "Percent of heap used:", + (unsigned long) (100 * (h->mem_alloc - amount_free) / + h->mem_alloc)); + } + /* + * Print the data in a VMS-style octal dump. + */ + fprintf(stream, "%*sData follows (`__' indicates free region)...\n", + indent, ""); + for (i = 0; i < h->disk_alloc; i += 16) { + fprintf(stream, "%*s %8d: ", indent, "", i); + for (j = 0; j < 16; j++) { + if (i + j < h->disk_alloc) { + if (marker[i + j]) { + fprintf(stream, "__ "); + } else { + c = h->chunk[H5HL_SIZEOF_HDR(f) + i + j]; + fprintf(stream, "%02x ", c); + } + } else { + fprintf(stream, " "); + } + if (7 == j) + HDfputc(' ', stream); + } + + for (j = 0; j < 16; j++) { + if (i + j < h->disk_alloc) { + if (marker[i + j]) { + HDfputc(' ', stream); + } else { + c = h->chunk[H5HL_SIZEOF_HDR(f) + i + j]; + if (c > ' ' && c < '~') + HDfputc(c, stream); + else + HDfputc('.', stream); + } + } + } + + HDfputc('\n', stream); + } + + H5MM_xfree(marker); + FUNC_LEAVE(SUCCEED); +} diff --git a/src/H5HLprivate.h b/src/H5HLprivate.h new file mode 100644 index 0000000..8ccc2ed --- /dev/null +++ b/src/H5HLprivate.h @@ -0,0 +1,56 @@ +/*------------------------------------------------------------------------- + * Copyright (C) 1997 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + * + * Created: H5HLprivate.h + * Jul 16 1997 + * Robb Matzke + * + * Purpose: + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#ifndef _H5HLprivate_H +#define _H5HLprivate_H + +#include + +/* Private headers needed by this file. */ +#include +#include + +#define H5HL_MAGIC "HEAP" /*heap magic number */ +#define H5HL_SIZEOF_MAGIC 4 + +#define H5HL_ALIGN(X) (((X)+7)&~0x07) /*align on 8-byte boundary */ + +#define H5HL_SIZEOF_HDR(F) \ + H5HL_ALIGN(H5HL_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 */ + +#define H5HL_SIZEOF_FREE(F) \ + H5HL_ALIGN(H5F_SIZEOF_SIZE (F) + /*ptr to next free block */ \ + H5F_SIZEOF_SIZE (F)) /*size of this free block */ + +/* + * Library prototypes... + */ +herr_t H5HL_create (H5F_t *f, size_t size_hint, haddr_t *addr/*out*/); +void *H5HL_read (H5F_t *f, const haddr_t *addr, size_t offset, size_t size, + void *buf); +const void *H5HL_peek (H5F_t *f, const haddr_t *addr, size_t offset); +size_t H5HL_insert (H5F_t *f, const haddr_t *addr, size_t size, + const void *buf); +herr_t H5HL_write (H5F_t *f, const haddr_t *addr, size_t offset, size_t size, + const void *buf); +herr_t H5HL_remove (H5F_t *f, const haddr_t *addr, size_t offset, size_t size); +herr_t H5HL_debug (H5F_t *f, const haddr_t *addr, FILE * stream, intn indent, + intn fwidth); +#endif diff --git a/src/H5HLpublic.h b/src/H5HLpublic.h new file mode 100644 index 0000000..30b5a15 --- /dev/null +++ b/src/H5HLpublic.h @@ -0,0 +1,30 @@ +/*------------------------------------------------------------------------- + * Copyright (C) 1997 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + * + * Created: H5HLpublic.h + * Jul 16 1997 + * Robb Matzke + * + * Purpose: Public declarations for the H5HL (local heap) package. + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#ifndef _H5HLpublic_H +#define _H5HLpublic_H + +/* Public headers needed by this file */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/H5Hprivate.h b/src/H5Hprivate.h deleted file mode 100644 index c852e6d..0000000 --- a/src/H5Hprivate.h +++ /dev/null @@ -1,62 +0,0 @@ -/*------------------------------------------------------------------------- - * Copyright (C) 1997 National Center for Supercomputing Applications. - * All rights reserved. - * - *------------------------------------------------------------------------- - * - * Created: H5Hprivate.h - * Jul 16 1997 - * Robb Matzke - * - * Purpose: - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -#ifndef _H5Hprivate_H -#define _H5Hprivate_H - -#include - -/* Private headers needed by this file. */ -#include -#include - -#define H5H_MAGIC "HEAP" /*heap magic number */ -#define H5H_SIZEOF_MAGIC 4 - -#define H5H_ALIGN(X) (((X)+7)&~0x07) /*align on 8-byte boundary */ - -#define H5H_SIZEOF_HDR(F) \ - H5H_ALIGN(H5H_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 */ - -#define H5H_SIZEOF_FREE(F) \ - H5H_ALIGN(H5F_SIZEOF_SIZE (F) + /*ptr to next free block */ \ - H5F_SIZEOF_SIZE (F)) /*size of this free block */ - -typedef enum H5H_type_t { - H5H_LOCAL = 0, /*local symtab name heap */ - H5H_GLOBAL = 1 /*global small object heap */ -} H5H_type_t; - -/* - * Library prototypes... - */ -herr_t H5H_create (H5F_t *f, H5H_type_t type, size_t size_hint, - haddr_t *addr/*out*/); -void *H5H_read (H5F_t *f, const haddr_t *addr, size_t offset, size_t size, - void *buf); -const void *H5H_peek (H5F_t *f, const haddr_t *addr, size_t offset); -size_t H5H_insert (H5F_t *f, const haddr_t *addr, size_t size, - const void *buf); -herr_t H5H_write (H5F_t *f, const haddr_t *addr, size_t offset, size_t size, - const void *buf); -herr_t H5H_remove (H5F_t *f, const haddr_t *addr, size_t offset, size_t size); -herr_t H5H_debug (H5F_t *f, const haddr_t *addr, FILE * stream, intn indent, - intn fwidth); -#endif diff --git a/src/H5Hpublic.h b/src/H5Hpublic.h deleted file mode 100644 index 82c85e0..0000000 --- a/src/H5Hpublic.h +++ /dev/null @@ -1,30 +0,0 @@ -/*------------------------------------------------------------------------- - * Copyright (C) 1997 National Center for Supercomputing Applications. - * All rights reserved. - * - *------------------------------------------------------------------------- - * - * Created: H5Hproto.h - * Jul 16 1997 - * Robb Matzke - * - * Purpose: Public declarations for the H5H (heap) package. - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -#ifndef _H5Hpublic_H -#define _H5Hpublic_H - -/* Public headers needed by this file */ -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __cplusplus -} -#endif -#endif diff --git a/src/H5Oefl.c b/src/H5Oefl.c index e1f3247..b4bdf19 100644 --- a/src/H5Oefl.c +++ b/src/H5Oefl.c @@ -7,7 +7,7 @@ */ #include #include -#include +#include #include #include @@ -76,7 +76,7 @@ H5O_efl_decode(H5F_t *f, size_t raw_size, const uint8 *p) H5F_addr_decode(f, &p, &(mesg->heap_addr)); #ifndef NDEBUG assert (H5F_addr_defined (&(mesg->heap_addr))); - s = H5H_peek (f, &(mesg->heap_addr), 0); + s = H5HL_peek (f, &(mesg->heap_addr), 0); assert (s && !*s); #endif UINT16DECODE(p, mesg->nalloc); @@ -90,7 +90,7 @@ H5O_efl_decode(H5F_t *f, size_t raw_size, const uint8 *p) for (i=0; inused; i++) { /* Name */ H5F_decode_length (f, p, mesg->slot[i].name_offset); - s = H5H_peek (f, &(mesg->heap_addr), mesg->slot[i].name_offset); + s = H5HL_peek (f, &(mesg->heap_addr), mesg->slot[i].name_offset); assert (s && *s); mesg->slot[i].name = H5MM_xstrdup (s); @@ -155,9 +155,9 @@ H5O_efl_encode(H5F_t *f, size_t raw_size, uint8 *p, const void *_mesg) * If the name has not been added to the heap yet then do so now. */ if (0==mesg->slot[i].name_offset) { - offset = H5H_insert (f, &(mesg->heap_addr), - strlen (mesg->slot[i].name)+1, - mesg->slot[i].name); + offset = H5HL_insert (f, &(mesg->heap_addr), + strlen (mesg->slot[i].name)+1, + mesg->slot[i].name); if ((size_t)(-1)==offset) { HRETURN_ERROR (H5E_EFL, H5E_CANTINIT, FAIL, "unable to insert URL into name heap"); diff --git a/src/H5P.c b/src/H5P.c index 7fbf55a..04020a5 100644 --- a/src/H5P.c +++ b/src/H5P.c @@ -408,8 +408,8 @@ H5Pget_class(hid_t tid) *------------------------------------------------------------------------- */ herr_t -H5Pget_version(hid_t tid, int *boot /*out */ , int *heap /*out */ , - int *freelist /*out */ , int *stab /*out */ , int *shhdr /*out */ ) +H5Pget_version(hid_t tid, int *boot/*out*/, int *freelist/*out*/, + int *stab/*out*/, int *shhdr/*out*/) { H5F_create_t *tmpl = NULL; @@ -422,16 +422,10 @@ H5Pget_version(hid_t tid, int *boot /*out */ , int *heap /*out */ , "not a file creation template"); } /* Get values */ - if (boot) - *boot = tmpl->bootblock_ver; - if (heap) - *heap = tmpl->smallobject_ver; - if (freelist) - *freelist = tmpl->freespace_ver; - if (stab) - *stab = tmpl->objectdir_ver; - if (shhdr) - *shhdr = tmpl->sharedheader_ver; + if (boot) *boot = tmpl->bootblock_ver; + if (freelist) *freelist = tmpl->freespace_ver; + if (stab) *stab = tmpl->objectdir_ver; + if (shhdr) *shhdr = tmpl->sharedheader_ver; FUNC_LEAVE(SUCCEED); } diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h index ea3c0d2..714782f 100644 --- a/src/H5Ppublic.h +++ b/src/H5Ppublic.h @@ -46,9 +46,8 @@ hid_t H5Pcreate (H5P_class_t type); herr_t H5Pclose (hid_t tid); hid_t H5Pcopy (hid_t tid); H5P_class_t H5Pget_class (hid_t tid); -herr_t H5Pget_version (hid_t tid, int *boot/*out*/, int *heap/*out*/, - int *freelist/*out*/, int *stab/*out*/, - int *shhdr/*out*/); +herr_t H5Pget_version (hid_t tid, int *boot/*out*/, int *freelist/*out*/, + int *stab/*out*/, int *shhdr/*out*/); herr_t H5Pset_userblock (hid_t tid, size_t size); herr_t H5Pget_userblock (hid_t tid, size_t *size); herr_t H5Pset_sizes (hid_t tid, size_t sizeof_addr, size_t sizeof_size); diff --git a/src/H5private.h b/src/H5private.h index 10f5161..8d319bb 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -29,7 +29,6 @@ /* Version #'s of the major components of the file format */ #define HDF5_BOOTBLOCK_VERSION 0 /* of the boot block format */ -#define HDF5_SMALLOBJECT_VERSION 0 /* of the Small-Object Heap */ #define HDF5_FREESPACE_VERSION 0 /* of the Free-Space Info */ #define HDF5_OBJECTDIR_VERSION 0 /* of the Object Directory format */ #define HDF5_SHAREDHEADER_VERSION 0 /* of the Shared-Header Info */ diff --git a/src/Makefile.in b/src/Makefile.in index 66a3949..7c5a8a5 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -18,7 +18,7 @@ PARALLEL_SRC=H5Fmpio.c LIB_SRC=H5.c H5AC.c H5B.c H5D.c H5E.c H5F.c H5Farray.c H5Fcore.c H5Ffamily.c \ H5Fistore.c H5Flow.c H5Fsec2.c H5Fsplit.c H5Fstdio.c H5G.c H5Gent.c \ - H5Gnode.c H5Gstab.c H5H.c H5I.c H5MF.c H5MM.c H5O.c H5Ocont.c \ + H5Gnode.c H5Gstab.c H5HG.c H5HL.c H5I.c H5MF.c H5MM.c H5O.c H5Ocont.c \ H5Odtype.c H5Oefl.c H5Olayout.c H5Oname.c H5Onull.c H5Osdspace.c \ H5Ostab.c H5P.c H5S.c H5Ssimp.c H5T.c H5Tconv.c H5Tinit.c \ H5V.c @PARALLEL_SRC@ @@ -34,15 +34,15 @@ PROG_OBJ=$(PROG_SRC:.c=.o) # Public header files (to be installed)... PUB_HDR=H5public.h H5ACpublic.h H5Bpublic.h H5Ppublic.h H5Dpublic.h \ - H5Epublic.h H5Fpublic.h H5Gpublic.h H5Hpublic.h H5Ipublic.h \ - H5MFpublic.h H5MMpublic.h H5Opublic.h H5Spublic.h H5Tpublic.h \ - H5config.h hdf5.h + H5Epublic.h H5Fpublic.h H5Gpublic.h H5HGpublic.h H5HLpublic.h \ + H5Ipublic.h H5MFpublic.h H5MMpublic.h H5Opublic.h H5Spublic.h \ + H5Tpublic.h H5config.h hdf5.h # Other header files (not to be installed)... PRIVATE_HDR=H5private.h H5ACprivate.h H5Bprivate.h H5Pprivate.h H5Dprivate.h \ - H5Eprivate.h H5Fprivate.h H5Gprivate.h H5Gpkg.h H5Hprivate.h \ - H5Iprivate.h H5MFprivate.h H5MMprivate.h H5Oprivate.h H5Sprivate.h \ - H5Tprivate.h H5Tpkg.h H5Vprivate.h + H5Eprivate.h H5Fprivate.h H5Gprivate.h H5Gpkg.h H5HGprivate.h \ + H5HLprivate.h H5Iprivate.h H5MFprivate.h H5MMprivate.h H5Oprivate.h \ + H5Sprivate.h H5Tprivate.h H5Tpkg.h H5Vprivate.h # Number format detection H5Tinit.c: H5detect diff --git a/src/debug.c b/src/debug.c index 7757afd..a15362c 100644 --- a/src/debug.c +++ b/src/debug.c @@ -20,7 +20,8 @@ #include #include #include -#include +#include +#include #include #define INDENT 3 @@ -93,11 +94,17 @@ main(int argc, char *argv[]) */ status = H5F_debug(f, &addr, stdout, 0, VCOL); - } else if (!HDmemcmp(sig, H5H_MAGIC, H5H_SIZEOF_MAGIC)) { + } else if (!HDmemcmp(sig, H5HL_MAGIC, H5HL_SIZEOF_MAGIC)) { /* - * Debug a heap. + * Debug a local heap. */ - status = H5H_debug(f, &addr, stdout, 0, VCOL); + status = H5HL_debug(f, &addr, stdout, 0, VCOL); + + } else if (!HDmemcmp (sig, H5HG_MAGIC, H5HG_SIZEOF_MAGIC)) { + /* + * Debug a global heap collection. + */ + status = H5HG_debug (f, &addr, stdout, 0, VCOL); } else if (!HDmemcmp(sig, H5G_NODE_MAGIC, H5G_NODE_SIZEOF_MAGIC)) { /* diff --git a/src/hdf5.h b/src/hdf5.h index ae82b77..73f269b 100644 --- a/src/hdf5.h +++ b/src/hdf5.h @@ -25,7 +25,7 @@ #include /* Errors */ #include /* Files */ #include /* Groups */ -#include +#include #include /* IDs */ #include #include diff --git a/test/.distdep b/test/.distdep index cb9225b..03ec460 100644 --- a/test/.distdep +++ b/test/.distdep @@ -130,7 +130,7 @@ dtypes.o: \ ../src/H5Epublic.h \ ../src/H5Fpublic.h \ ../src/H5Gpublic.h \ - ../src/H5Hpublic.h \ + ../src/H5HLpublic.h \ ../src/H5MFpublic.h \ ../src/H5MMpublic.h \ ../src/H5Opublic.h \ @@ -183,7 +183,7 @@ dsets.o: \ ../src/H5Epublic.h \ ../src/H5Fpublic.h \ ../src/H5Gpublic.h \ - ../src/H5Hpublic.h \ + ../src/H5HLpublic.h \ ../src/H5MFpublic.h \ ../src/H5MMpublic.h \ ../src/H5Opublic.h \ @@ -202,7 +202,7 @@ cmpd_dset.o: \ ../src/H5Epublic.h \ ../src/H5Fpublic.h \ ../src/H5Gpublic.h \ - ../src/H5Hpublic.h \ + ../src/H5HLpublic.h \ ../src/H5MFpublic.h \ ../src/H5MMpublic.h \ ../src/H5Opublic.h \ @@ -220,7 +220,7 @@ extend.o: \ ../src/H5Epublic.h \ ../src/H5Fpublic.h \ ../src/H5Gpublic.h \ - ../src/H5Hpublic.h \ + ../src/H5HLpublic.h \ ../src/H5MFpublic.h \ ../src/H5MMpublic.h \ ../src/H5Opublic.h @@ -236,7 +236,7 @@ external.o: \ ../src/H5Epublic.h \ ../src/H5Fpublic.h \ ../src/H5Gpublic.h \ - ../src/H5Hpublic.h \ + ../src/H5HLpublic.h \ ../src/H5MFpublic.h \ ../src/H5MMpublic.h \ ../src/H5Opublic.h \ @@ -255,7 +255,7 @@ iopipe.o: \ ../src/H5Epublic.h \ ../src/H5Fpublic.h \ ../src/H5Gpublic.h \ - ../src/H5Hpublic.h \ + ../src/H5HLpublic.h \ ../src/H5MFpublic.h \ ../src/H5MMpublic.h \ ../src/H5Opublic.h \ diff --git a/test/iopipe.c b/test/iopipe.c index f185aad..4d856b9 100644 --- a/test/iopipe.c +++ b/test/iopipe.c @@ -59,16 +59,22 @@ print_stats (const char *prefix, { double u_time, s_time, e_time, bw; - u_time = (r_stop->ru_utime.tv_sec+r_stop->ru_utime.tv_usec/1000000.0) - - (r_start->ru_utime.tv_sec+r_start->ru_utime.tv_usec/1000000.0); + u_time = ((double)(r_stop->ru_utime.tv_sec)+ + (double)(r_stop->ru_utime.tv_usec)/1000000.0) - + ((double)(r_start->ru_utime.tv_sec)+ + (double)(r_start->ru_utime.tv_usec)/1000000.0); - s_time = (r_stop->ru_stime.tv_sec+r_stop->ru_stime.tv_usec/1000000.0) - - (r_start->ru_stime.tv_sec+r_start->ru_stime.tv_usec/1000000.0); + s_time = ((double)(r_stop->ru_stime.tv_sec)+ + (double)(r_stop->ru_stime.tv_usec)/1000000.0) - + ((double)(r_start->ru_stime.tv_sec)+ + (double)(r_start->ru_stime.tv_usec)/1000000.0); - e_time = (t_stop->tv_sec+t_stop->tv_usec/1000000.0) - - (t_start->tv_sec+t_start->tv_usec/1000000.0); + e_time = ((double)(t_stop->tv_sec)+ + (double)(t_stop->tv_usec)/1000000.0) - + ((double)(t_start->tv_sec)+ + (double)(t_start->tv_usec)/1000000.0); - bw = nbytes / e_time; + bw = (double)nbytes / e_time; printf (HEADING "%1.2fuser %1.2fsystem %1.2felapsed %1.2fMB/s\n", prefix, u_time, s_time, e_time, bw/(1024*1024)); @@ -141,7 +147,8 @@ main (void) int start[2]; size_t count[2]; - printf ("I/O request size is %1.1fMB\n", (size[0]*size[1])/(1024.0*1024)); + printf ("I/O request size is %1.1fMB\n", + ((double)(size[0])*(double)(size[1]))/(1024.0*1024)); /* Open the files */ diff --git a/test/theap.c b/test/theap.c index 4ffc892..e355ded 100644 --- a/test/theap.c +++ b/test/theap.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #define NOBJS 40 @@ -61,8 +61,8 @@ test_heap(void) CHECK(f, NULL, "H5I_object"); /* Create a new heap */ - status = H5H_create(f, H5H_LOCAL, 0, &heap_addr /*out */ ); - CHECK_I(status, "H5H_new"); + status = H5HL_create(f, 0, &heap_addr /*out */ ); + CHECK_I(status, "H5HL_create"); /* Add stuff to the heap */ for (i = 0; i < NOBJS; i++) { @@ -72,7 +72,7 @@ test_heap(void) if (j > 4) buf[j] = '\0'; - obj[i] = H5H_insert(f, &heap_addr, strlen(buf) + 1, buf); + obj[i] = H5HL_insert(f, &heap_addr, strlen(buf) + 1, buf); assert ((size_t)(-1)!=obj[i]); } @@ -81,7 +81,7 @@ test_heap(void) /* Read the objects back out */ for (i = 0; i < NOBJS; i++) { - s = H5H_peek(f, &heap_addr, obj[i]); + s = H5HL_peek(f, &heap_addr, obj[i]); MESSAGE(8, ("object is `%s'\n", s)); } -- cgit v0.12