From a7b48fec30b180f5c96cf9601a29ce3f7729f6bb Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Sat, 19 Dec 2009 02:22:53 -0500 Subject: [svn-r18041] Description: Move local & global heap metadata cache callback routines to their own source module, as they are in later revisions of the trunk and on the metadata journaling branch, in order to make the convergence of the trunk and the metadata journaling branch easier. Tested on: Mac OS X/32 10.6.2 (amazon) w/debug (h5committest not required on this branch) --- MANIFEST | 2 + src/H5B.c | 2 +- src/H5HG.c | 742 +++++++++++++------------------------------------------- src/H5HGcache.c | 439 +++++++++++++++++++++++++++++++++ src/H5HGdbg.c | 9 +- src/H5HGpkg.h | 56 ++++- src/H5HL.c | 418 ++----------------------------- src/H5HLcache.c | 444 +++++++++++++++++++++++++++++++++ src/H5HLpkg.h | 19 +- src/Makefile.am | 2 +- src/Makefile.in | 6 +- 11 files changed, 1168 insertions(+), 971 deletions(-) create mode 100644 src/H5HGcache.c create mode 100644 src/H5HLcache.c diff --git a/MANIFEST b/MANIFEST index 63e4b87..6406211 100644 --- a/MANIFEST +++ b/MANIFEST @@ -580,11 +580,13 @@ ./src/H5HFtest.c ./src/H5HFtiny.c ./src/H5HG.c +./src/H5HGcache.c ./src/H5HGdbg.c ./src/H5HGpkg.h ./src/H5HGprivate.h ./src/H5HGpublic.h ./src/H5HL.c +./src/H5HLcache.c ./src/H5HLdbg.c ./src/H5HLpkg.h ./src/H5HLprivate.h diff --git a/src/H5B.c b/src/H5B.c index 3a755e2..d29d57b 100644 --- a/src/H5B.c +++ b/src/H5B.c @@ -1676,7 +1676,7 @@ H5B_shared_new(const H5F_t *f, const H5B_class_t *type, size_t sizeof_rkey) HDassert(type); /* Allocate space for the shared structure */ - if(NULL == (shared = H5FL_MALLOC(H5B_shared_t))) + if(NULL == (shared = H5FL_CALLOC(H5B_shared_t))) HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, NULL, "memory allocation failed for shared B-tree info") /* Set up the "global" information for this file's groups */ diff --git a/src/H5HG.c b/src/H5HG.c index 2440166..83e02ac 100644 --- a/src/H5HG.c +++ b/src/H5HG.c @@ -37,33 +37,28 @@ * in the collection, and temporal locality. */ +/****************/ +/* Module Setup */ +/****************/ + #define H5F_PACKAGE /*suppress error about including H5Fpkg */ #define H5HG_PACKAGE /*suppress error about including H5HGpkg */ +/***********/ +/* Headers */ +/***********/ #include "H5private.h" /* Generic Functions */ -#include "H5ACprivate.h" /* Metadata cache */ #include "H5Eprivate.h" /* Error handling */ #include "H5Fpkg.h" /* File access */ -#include "H5FLprivate.h" /* Free lists */ #include "H5HGpkg.h" /* Global heaps */ #include "H5MFprivate.h" /* File memory management */ #include "H5MMprivate.h" /* Memory management */ -/* Private macros */ - -/* - * 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 +/****************/ +/* Local Macros */ +/****************/ /* * Limit global heap collections to the some reasonable size. This is @@ -73,12 +68,6 @@ #define H5HG_MAXSIZE 65536 /* - * 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 @@ -88,70 +77,47 @@ */ #define H5HG_MAXIDX 65535 -/* - * The size of the collection header, always a multiple of the alignment so - * that the stuff that follows the header is aligned. - */ -#define H5HG_SIZEOF_HDR(f) \ - H5HG_ALIGN(4 + /*magic number */ \ - 1 + /*version number */ \ - 3 + /*reserved */ \ - H5F_SIZEOF_SIZE(f)) /*collection 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. The `+2' accounts for - * rounding and for the free space object. - */ -#define H5HG_NOBJS(f,z) (int)((((z)-H5HG_SIZEOF_HDR(f))/ \ - H5HG_SIZEOF_OBJHDR(f)+2)) +/******************/ +/* Local Typedefs */ +/******************/ -/* - * Makes a global heap object pointer undefined, or checks whether one is - * defined. - */ -#define H5HG_undef(HGP) ((HGP)->idx=0) -#define H5HG_defined(HGP) ((HGP)->idx!=0) -/* Private typedefs */ +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ -/* PRIVATE PROTOTYPES */ static haddr_t H5HG_create(H5F_t *f, hid_t dxpl_id, size_t size); -#ifdef NOT_YET -static void *H5HG_peek(H5F_t *f, hid_t dxpl_id, H5HG_t *hobj); -#endif /* NOT_YET */ - -/* Metadata cache callbacks */ -static H5HG_heap_t *H5HG_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1, - void *udata2); -static herr_t H5HG_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, - H5HG_heap_t *heap, unsigned UNUSED * flags_ptr); -static herr_t H5HG_dest(H5F_t *f, H5HG_heap_t *heap); -static herr_t H5HG_clear(H5F_t *f, H5HG_heap_t *heap, hbool_t destroy); -static herr_t H5HG_compute_size(const H5F_t *f, const H5HG_heap_t *heap, size_t *size_ptr); -/* - * H5HG inherits cache-like properties from H5AC - */ -const H5AC_class_t H5AC_GHEAP[1] = {{ - H5AC_GHEAP_ID, - (H5AC_load_func_t)H5HG_load, - (H5AC_flush_func_t)H5HG_flush, - (H5AC_dest_func_t)H5HG_dest, - (H5AC_clear_func_t)H5HG_clear, - (H5AC_size_func_t)H5HG_compute_size, -}}; + +/*********************/ +/* Package Variables */ +/*********************/ /* Declare a free list to manage the H5HG_t struct */ -H5FL_DEFINE_STATIC(H5HG_heap_t); +H5FL_DEFINE(H5HG_heap_t); /* Declare a free list to manage sequences of H5HG_obj_t's */ -H5FL_SEQ_DEFINE_STATIC(H5HG_obj_t); +H5FL_SEQ_DEFINE(H5HG_obj_t); /* Declare a PQ free list to manage heap chunks */ -H5FL_BLK_DEFINE_STATIC(heap_chunk); +H5FL_BLK_DEFINE(gheap_chunk); + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + /*------------------------------------------------------------------------- @@ -202,20 +168,18 @@ H5HG_create (H5F_t *f, hid_t dxpl_id, size_t size) heap->addr = addr; heap->size = size; - if (NULL==(heap->chunk = H5FL_BLK_MALLOC (heap_chunk,size))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, \ - "memory allocation failed"); + if(NULL == (heap->chunk = H5FL_BLK_MALLOC(gheap_chunk, size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, "memory allocation failed") #ifdef H5_CLEAR_MEMORY HDmemset(heap->chunk, 0, size); #endif /* H5_CLEAR_MEMORY */ - heap->nalloc = H5HG_NOBJS (f, size); + heap->nalloc = H5HG_NOBJS(f, size); heap->nused = 1; /* account for index 0, which is used for the free object */ - if (NULL==(heap->obj = H5FL_SEQ_MALLOC (H5HG_obj_t,heap->nalloc))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, \ - "memory allocation failed"); + if(NULL == (heap->obj = H5FL_SEQ_MALLOC(H5HG_obj_t, heap->nalloc))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, "memory allocation failed") /* Initialize the header */ - HDmemcpy (heap->chunk, H5HG_MAGIC, (size_t)H5HG_SIZEOF_MAGIC); + HDmemcpy(heap->chunk, H5HG_MAGIC, (size_t)H5HG_SIZEOF_MAGIC); p = heap->chunk + H5HG_SIZEOF_MAGIC; *p++ = H5HG_VERSION; *p++ = 0; /*reserved*/ @@ -250,22 +214,22 @@ HDmemset(heap->chunk, 0, size); #endif /* OLD_WAY */ /* Add this heap to the beginning of the CWFS list */ - if (NULL==f->shared->cwfs) { - f->shared->cwfs = H5MM_malloc (H5HG_NCWFS * sizeof(H5HG_heap_t*)); - if (NULL==(f->shared->cwfs)) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, \ - "memory allocation failed"); + if(NULL == f->shared->cwfs) { + f->shared->cwfs = (H5HG_heap_t **)H5MM_malloc(H5HG_NCWFS * sizeof(H5HG_heap_t *)); + if(NULL == (f->shared->cwfs)) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, "memory allocation failed") 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*)); + } /* end if */ + 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); + f->shared->ncwfs = MIN(H5HG_NCWFS, f->shared->ncwfs+1); } /* Add the heap to the cache */ - if(H5AC_set(f, dxpl_id, H5AC_GHEAP, addr, heap, H5AC__NO_FLAGS_SET)<0) + if(H5AC_set(f, dxpl_id, H5AC_GHEAP, addr, heap, H5AC__NO_FLAGS_SET) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, HADDR_UNDEF, "unable to cache global heap collection") ret_value = addr; @@ -280,361 +244,6 @@ done: /*------------------------------------------------------------------------- - * 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: - * Robb Matzke, 1999-07-28 - * The ADDR argument is passed by value. - * - * Quincey Koziol, 2002-7-180 - * Added dxpl parameter to allow more control over I/O from metadata - * cache. - *------------------------------------------------------------------------- - */ -static H5HG_heap_t * -H5HG_load (H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * udata1, - void UNUSED * udata2) -{ - H5HG_heap_t *heap = NULL; - uint8_t *p = NULL; - int i; - size_t nalloc, need; - size_t max_idx=0; /* The maximum index seen */ - H5HG_heap_t *ret_value = NULL; /* Return value */ - - FUNC_ENTER_NOAPI(H5HG_load, NULL); - - /* check arguments */ - assert (f); - assert (H5F_addr_defined (addr)); - assert (!udata1); - assert (!udata2); - - /* Read the initial 4k page */ - if(NULL == (heap = H5FL_CALLOC (H5HG_heap_t))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - heap->addr = addr; - if(NULL == (heap->chunk = H5FL_BLK_MALLOC(heap_chunk, (size_t)H5HG_MINSIZE))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - if(H5F_block_read(f, H5FD_MEM_GHEAP, addr, (size_t)H5HG_MINSIZE, dxpl_id, heap->chunk)<0) - HGOTO_ERROR (H5E_HEAP, H5E_READERROR, NULL, "unable to read global heap collection"); - - /* Magic number */ - if(HDmemcmp(heap->chunk, H5HG_MAGIC, (size_t)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 + (hsize_t)H5HG_MINSIZE; - if (NULL==(heap->chunk = H5FL_BLK_REALLOC (heap_chunk, heap->chunk, heap->size))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - if (H5F_block_read (f, H5FD_MEM_GHEAP, next_addr, (heap->size-H5HG_MINSIZE), dxpl_id, 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); - nalloc = H5HG_NOBJS (f, heap->size); - if (NULL==(heap->obj = H5FL_SEQ_MALLOC (H5HG_obj_t,nalloc))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - heap->obj[0].size=heap->obj[0].nrefs=0; - heap->obj[0].begin=NULL; - - heap->nalloc = nalloc; - 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 { - unsigned idx; - uint8_t *begin = p; - - UINT16DECODE (p, idx); - - /* Check if we need more room to store heap objects */ - if(idx>=heap->nalloc) { - size_t new_alloc; /* New allocation number */ - H5HG_obj_t *new_obj; /* New array of object descriptions */ - - /* Determine the new number of objects to index */ - new_alloc=MAX(heap->nalloc*2,(idx+1)); - - /* Reallocate array of objects */ - if (NULL==(new_obj = H5FL_SEQ_REALLOC (H5HG_obj_t, heap->obj, new_alloc))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - - /* Update heap information */ - heap->nalloc=new_alloc; - heap->obj=new_obj; - } /* end if */ - - UINT16DECODE (p, heap->obj[idx].nrefs); - p += 4; /*reserved*/ - H5F_DECODE_LENGTH (f, p, heap->obj[idx].size); - heap->obj[idx].begin = begin; - /* - * The total storage size includes the size of the object header - * and is zero padded so the next object header is properly - * aligned. The last bit of space is the free space object whose - * size is never padded and already includes the object header. - */ - if (idx>0) { - need = H5HG_SIZEOF_OBJHDR(f) + H5HG_ALIGN(heap->obj[idx].size); - - /* Check for "gap" in index numbers (caused by deletions) and fill in heap object values */ - if(idx>(max_idx+1)) - HDmemset(&heap->obj[max_idx+1],0,sizeof(H5HG_obj_t)*(idx-(max_idx+1))); - max_idx=idx; - } else { - need = heap->obj[idx].size; - } - p = begin + need; - } - } - assert(p==heap->chunk+heap->size); - assert(H5HG_ISALIGNED(heap->obj[0].size)); - - /* Set the next index value to use */ - if(max_idx>0) - heap->nused=max_idx+1; - else - heap->nused=1; - - /* - * 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 (!f->shared->cwfs) { - f->shared->cwfs = H5MM_malloc (H5HG_NCWFS*sizeof(H5HG_heap_t*)); - if (NULL==f->shared->cwfs) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - 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) { - HDmemmove (f->shared->cwfs+1, f->shared->cwfs, i * sizeof(H5HG_heap_t*)); - f->shared->cwfs[0] = heap; - break; - } - } - } else { - HDmemmove (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) { - if(H5HG_dest(f,heap)<0) - HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, NULL, "unable to destroy global heap collection"); - } - FUNC_LEAVE_NOAPI(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: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Friday, March 27, 1998 - * - * Modifications: - * Robb Matzke, 1999-07-28 - * The ADDR argument is passed by value. - * - * Quincey Koziol, 2002-7-180 - * Added dxpl parameter to allow more control over I/O from metadata - * cache. - * - * JRM -- 8/21/06 - * Added the flags_ptr parameter. This parameter exists to - * allow the flush routine to report to the cache if the - * entry is resized or renamed as a result of the flush. - * *flags_ptr is set to H5C_CALLBACK__NO_FLAGS_SET on entry. - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HG_flush (H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HG_heap_t *heap, unsigned UNUSED * flags_ptr) -{ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5HG_flush, FAIL); - - /* Check arguments */ - assert (f); - assert (H5F_addr_defined (addr)); - assert (H5F_addr_eq (addr, heap->addr)); - assert (heap); - - if (heap->cache_info.is_dirty) { - if (H5F_block_write (f, H5FD_MEM_GHEAP, addr, heap->size, dxpl_id, heap->chunk)<0) - HGOTO_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write global heap collection to file"); - heap->cache_info.is_dirty = FALSE; - } - - if (destroy) { - if(H5HG_dest(f,heap)<0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy global heap collection"); - } - -done: - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5HG_dest - * - * Purpose: Destroys a global heap collection in memory - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * Wednesday, January 15, 2003 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HG_dest (H5F_t *f, H5HG_heap_t *heap) -{ - int i; - - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HG_dest); - - /* Check arguments */ - assert (heap); - - /* Verify that node is clean */ - assert (heap->cache_info.is_dirty==FALSE); - - 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; - } - } - - if(heap->chunk) - heap->chunk = H5FL_BLK_FREE(heap_chunk,heap->chunk); - if(heap->obj) - heap->obj = H5FL_SEQ_FREE(H5HG_obj_t,heap->obj); - H5FL_FREE (H5HG_heap_t,heap); - - FUNC_LEAVE_NOAPI(SUCCEED); -} /* H5HG_dest() */ - - -/*------------------------------------------------------------------------- - * Function: H5HG_clear - * - * Purpose: Mark a global heap in memory as non-dirty. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * Thursday, March 20, 2003 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HG_clear(H5F_t *f, H5HG_heap_t *heap, hbool_t destroy) -{ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI_NOINIT(H5HG_clear); - - /* Check arguments */ - assert (heap); - - /* Mark heap as clean */ - heap->cache_info.is_dirty = FALSE; - - if (destroy) - if (H5HG_dest(f, heap) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy global heap collection"); - -done: - FUNC_LEAVE_NOAPI(ret_value); -} /* H5HG_clear() */ - - -/*------------------------------------------------------------------------- - * Function: H5HG_compute_size - * - * Purpose: Compute the size in bytes of the specified instance of - * H5HG_heap_t on disk, and return it in *len_ptr. On failure, - * the value of *len_ptr is undefined. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: John Mainzer - * 5/13/04 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HG_compute_size(const H5F_t UNUSED *f, const H5HG_heap_t *heap, size_t *size_ptr) -{ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HG_compute_size); - - /* Check arguments */ - HDassert(heap); - HDassert(size_ptr); - - *size_ptr = heap->size; - - FUNC_LEAVE_NOAPI(SUCCEED); -} /* H5HG_compute_size() */ - - -/*------------------------------------------------------------------------- * Function: H5HG_alloc * * Purpose: Given a heap with enough free space, this function will split @@ -671,7 +280,7 @@ H5HG_alloc (H5F_t *f, H5HG_heap_t *heap, size_t size, unsigned * heap_flags_ptr) * Find an ID for the new object. ID zero is reserved for the free space * object. */ - if(heap->nusednused<=H5HG_MAXIDX) idx=heap->nused++; else { for (idx=1; idxnused; idx++) @@ -679,23 +288,29 @@ H5HG_alloc (H5F_t *f, H5HG_heap_t *heap, size_t size, unsigned * heap_flags_ptr) break; } /* end else */ + HDassert(idx < heap->nused); + /* Check if we need more room to store heap objects */ if(idx>=heap->nalloc) { size_t new_alloc; /* New allocation number */ H5HG_obj_t *new_obj; /* New array of object descriptions */ /* Determine the new number of objects to index */ - new_alloc=MAX(heap->nalloc*2,(idx+1)); - assert(new_alloc<=(H5HG_MAXIDX+1)); + /* nalloc is *not* guaranteed to be a power of 2! - NAF 10/26/09 */ + new_alloc = MIN(MAX(heap->nalloc * 2, (idx + 1)), (H5HG_MAXIDX + 1)); + HDassert(idx < new_alloc); /* Reallocate array of objects */ if (NULL==(new_obj = H5FL_SEQ_REALLOC (H5HG_obj_t, heap->obj, new_alloc))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, 0, "memory allocation failed"); + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "memory allocation failed") + + /* Clear newly allocated space */ + HDmemset(&new_obj[heap->nalloc], 0, (new_alloc - heap->nalloc) * sizeof(heap->obj[0])); /* Update heap information */ heap->nalloc=new_alloc; heap->obj=new_obj; - assert(heap->nalloc>heap->nused); + HDassert(heap->nalloc>heap->nused); } /* end if */ /* Initialize the new object */ @@ -779,75 +394,75 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5HG_extend (H5F_t *f, H5HG_heap_t *heap, size_t size, unsigned * heap_flags_ptr) +H5HG_extend(H5F_t *f, H5HG_heap_t *heap, size_t size, unsigned *heap_flags_ptr) { size_t need; /* Actual space needed to store object */ size_t old_size; /* Previous size of the heap's chunk */ - uint8_t *new_chunk=NULL; /* Pointer to new chunk information */ + uint8_t *new_chunk = NULL; /* Pointer to new chunk information */ uint8_t *p = NULL; /* Pointer to raw heap info */ unsigned u; /* Local index variable */ - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5HG_extend); + FUNC_ENTER_NOAPI_NOINIT(H5HG_extend) /* Check args */ - assert (f); - assert (heap); - assert (heap_flags_ptr); + HDassert(f); + HDassert(heap); + HDassert(heap_flags_ptr); /* Compute total space need to add to this heap */ need = H5HG_SIZEOF_OBJHDR(f) + H5HG_ALIGN(size); /* Decrement the amount needed in the heap by the amount of free space available */ - assert(need>heap->obj[0].size); + HDassert(need > heap->obj[0].size); need -= heap->obj[0].size; /* Don't do anything less than double the size of the heap */ - need = MAX(heap->size,need); + need = MAX(heap->size, need); /* Extend the space allocated for this heap on disk */ - if(H5MF_extend(f,H5FD_MEM_GHEAP,heap->addr,(hsize_t)heap->size,(hsize_t)need)<0) - HGOTO_ERROR (H5E_HEAP, H5E_NOSPACE, FAIL, "can't extend heap on disk"); + if(H5MF_extend(f, H5FD_MEM_GHEAP, heap->addr, (hsize_t)heap->size, (hsize_t)need) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "can't extend heap on disk") /* Re-allocate the heap information in memory */ - if (NULL==(new_chunk = H5FL_BLK_REALLOC (heap_chunk, heap->chunk, heap->size+need))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "new heap allocation failed"); + if(NULL == (new_chunk = H5FL_BLK_REALLOC(gheap_chunk, heap->chunk, (heap->size + need)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "new heap allocation failed") #ifdef H5_CLEAR_MEMORY HDmemset(new_chunk + heap->size, 0, need); #endif /* H5_CLEAR_MEMORY */ /* Adjust the size of the heap */ - old_size=heap->size; - heap->size+=need; + old_size = heap->size; + heap->size += need; /* Encode the new size of the heap */ p = new_chunk + H5HG_SIZEOF_MAGIC + 1 /* version */ + 3 /* reserved */; - H5F_ENCODE_LENGTH (f, p, heap->size); + H5F_ENCODE_LENGTH(f, p, heap->size); /* Move the pointers to the existing objects to their new locations */ - for (u=0; unused; u++) + for(u = 0; u < heap->nused; u++) if(heap->obj[u].begin) heap->obj[u].begin = new_chunk + (heap->obj[u].begin - heap->chunk); /* Update the heap chunk pointer now */ - heap->chunk=new_chunk; + heap->chunk = new_chunk; /* Update the free space information for the heap */ - heap->obj[0].size+=need; - if(heap->obj[0].begin==NULL) - heap->obj[0].begin=heap->chunk+old_size; + heap->obj[0].size += need; + if(heap->obj[0].begin == NULL) + heap->obj[0].begin = heap->chunk+old_size; p = heap->obj[0].begin; UINT16ENCODE(p, 0); /*id*/ UINT16ENCODE(p, 0); /*nrefs*/ UINT32ENCODE(p, 0); /*reserved*/ - H5F_ENCODE_LENGTH (f, p, heap->obj[0].size); + H5F_ENCODE_LENGTH(f, p, heap->obj[0].size); assert(H5HG_ISALIGNED(heap->obj[0].size)); /* Mark the heap as dirty */ *heap_flags_ptr |= H5AC__DIRTIED_FLAG; done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5HG_extend() */ @@ -874,26 +489,26 @@ done: *------------------------------------------------------------------------- */ herr_t -H5HG_insert (H5F_t *f, hid_t dxpl_id, size_t size, void *obj, H5HG_t *hobj/*out*/) +H5HG_insert(H5F_t *f, hid_t dxpl_id, size_t size, void *obj, H5HG_t *hobj/*out*/) { size_t need; /*total space needed for object */ - int cwfsno; + int cwfsno; size_t idx; haddr_t addr = HADDR_UNDEF; H5HG_heap_t *heap = NULL; unsigned heap_flags = H5AC__NO_FLAGS_SET; - hbool_t found=0; /* Flag to indicate a heap with enough space was found */ - herr_t ret_value=SUCCEED; /* Return value */ + hbool_t found = FALSE; /* Flag to indicate a heap with enough space was found */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5HG_insert, FAIL); + FUNC_ENTER_NOAPI(H5HG_insert, FAIL) /* Check args */ - assert (f); - assert (0==size || obj); - assert (hobj); + HDassert(f); + HDassert(0 == size || obj); + HDassert(hobj); - if (0==(f->intent & H5F_ACC_RDWR)) - HGOTO_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file"); + if(0 == (f->intent & H5F_ACC_RDWR)) + HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file") /* Find a large enough collection on the CWFS list */ need = H5HG_SIZEOF_OBJHDR(f) + H5HG_ALIGN(size); @@ -922,20 +537,18 @@ H5HG_insert (H5F_t *f, hid_t dxpl_id, size_t size, void *obj, H5HG_t *hobj/*out* * take any of it as gospel. * JRM - 5/24/04 */ - - for (cwfsno=0; cwfsnoshared->ncwfs; cwfsno++) { - if (f->shared->cwfs[cwfsno]->obj[0].size>=need) { + for(cwfsno = 0; cwfsno < f->shared->ncwfs; cwfsno++) + if(f->shared->cwfs[cwfsno]->obj[0].size >= need) { addr = f->shared->cwfs[cwfsno]->addr; - found=1; + found = TRUE; break; } /* end if */ - } /* end for */ /* * If we didn't find any collection with enough free space the check if * we can extend any of the collections to make enough room. */ - if (!found) { + if(!found) { size_t new_need; for (cwfsno=0; cwfsnoshared->ncwfs; cwfsno++) { @@ -943,11 +556,11 @@ H5HG_insert (H5F_t *f, hid_t dxpl_id, size_t size, void *obj, H5HG_t *hobj/*out* new_need -= f->shared->cwfs[cwfsno]->obj[0].size; new_need = MAX(f->shared->cwfs[cwfsno]->size, new_need); - if((f->shared->cwfs[cwfsno]->size+new_need)<=H5HG_MAXSIZE && H5MF_can_extend(f,H5FD_MEM_GHEAP,f->shared->cwfs[cwfsno]->addr,(hsize_t)f->shared->cwfs[cwfsno]->size,(hsize_t)new_need)) { - if(H5HG_extend(f,f->shared->cwfs[cwfsno],size, &heap_flags)<0) - HGOTO_ERROR (H5E_HEAP, H5E_CANTINIT, FAIL, "unable to extend global heap collection"); + if((f->shared->cwfs[cwfsno]->size + new_need) <= H5HG_MAXSIZE && H5MF_can_extend(f, H5FD_MEM_GHEAP, f->shared->cwfs[cwfsno]->addr, (hsize_t)f->shared->cwfs[cwfsno]->size, (hsize_t)new_need)) { + if(H5HG_extend(f, f->shared->cwfs[cwfsno], size, &heap_flags) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to extend global heap collection") addr = f->shared->cwfs[cwfsno]->addr; - found=1; + found = TRUE; break; } /* end if */ } /* end for */ @@ -957,42 +570,39 @@ H5HG_insert (H5F_t *f, hid_t dxpl_id, size_t size, void *obj, H5HG_t *hobj/*out* * 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 (!found) { - + if(!found) { addr = H5HG_create(f, dxpl_id, need+H5HG_SIZEOF_HDR (f)); - if ( ! H5F_addr_defined(addr) ) - HGOTO_ERROR (H5E_HEAP, H5E_CANTINIT, FAIL, \ - "unable to allocate a global heap collection"); + if(!H5F_addr_defined(addr)) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to allocate a global heap collection") cwfsno = 0; } /* end if */ else { - /* Move the collection forward in the CWFS list, if it's not * already at the front */ - if (cwfsno>0) { + 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; + + f->shared->cwfs[cwfsno] = f->shared->cwfs[cwfsno - 1]; + f->shared->cwfs[cwfsno - 1] = tmp; --cwfsno; } /* end if */ } /* end else */ HDassert(H5F_addr_defined(addr)); - - if(NULL == (heap = H5AC_protect(f, dxpl_id, H5AC_GHEAP, addr, NULL, NULL, H5AC_WRITE))) + if(NULL == (heap = (H5HG_heap_t *)H5AC_protect(f, dxpl_id, H5AC_GHEAP, addr, NULL, NULL, H5AC_WRITE))) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap") /* Split the free space to make room for the new object */ - idx = H5HG_alloc (f, heap, size, &heap_flags); + idx = H5HG_alloc(f, heap, size, &heap_flags); /* Copy data into the heap */ - if(size>0) { - HDmemcpy(heap->obj[idx].begin+H5HG_SIZEOF_OBJHDR(f), obj, size); + if(size > 0) { + HDmemcpy(heap->obj[idx].begin + H5HG_SIZEOF_OBJHDR(f), obj, size); #ifdef OLD_WAY /* Don't bother zeroing out the rest of the info in the heap -QAK */ - HDmemset(heap->obj[idx].begin+H5HG_SIZEOF_OBJHDR(f)+size, 0, - need-(H5HG_SIZEOF_OBJHDR(f)+size)); + HDmemset(heap->obj[idx].begin + H5HG_SIZEOF_OBJHDR(f) + size, 0, + need - (H5HG_SIZEOF_OBJHDR(f) + size)); #endif /* OLD_WAY */ } /* end if */ heap_flags |= H5AC__DIRTIED_FLAG; @@ -1005,7 +615,7 @@ done: if(heap && H5AC_unprotect(f, dxpl_id, H5AC_GHEAP, heap->addr, heap, heap_flags) < 0) HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to unprotect heap.") - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5HG_insert() */ @@ -1024,13 +634,6 @@ done: * Programmer: Robb Matzke * Monday, March 30, 1998 * - * Modifications: - * - * John Mainzer, 6/8/05 - * Modified the function to use the new dirtied parameter of - * of H5AC_unprotect() instead of modifying the is_dirty - * field of the cache info. - * *------------------------------------------------------------------------- */ void * @@ -1049,7 +652,7 @@ H5HG_read(H5F_t *f, hid_t dxpl_id, H5HG_t *hobj, void *object/*out*/, HDassert(hobj); /* Load the heap */ - if(NULL == (heap = H5AC_protect(f, dxpl_id, H5AC_GHEAP, hobj->addr, NULL, NULL, H5AC_READ))) + if(NULL == (heap = (H5HG_heap_t *)H5AC_protect(f, dxpl_id, H5AC_GHEAP, hobj->addr, NULL, NULL, H5AC_READ))) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unable to load heap") HDassert(hobj->idx < heap->nused); @@ -1131,19 +734,19 @@ H5HG_link (H5F_t *f, hid_t dxpl_id, const H5HG_t *hobj, int adjust) assert (f); assert (hobj); if (0==(f->intent & H5F_ACC_RDWR)) - HGOTO_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file"); + HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file") if(adjust!=0) { /* Load the heap */ - if (NULL == (heap = H5AC_protect(f, dxpl_id, H5AC_GHEAP, hobj->addr, NULL, NULL, H5AC_WRITE))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap"); + if (NULL == (heap = (H5HG_heap_t *)H5AC_protect(f, dxpl_id, H5AC_GHEAP, hobj->addr, NULL, NULL, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap") assert (hobj->idxnused); assert (heap->obj[hobj->idx].begin); if (heap->obj[hobj->idx].nrefs+adjust<0) - HGOTO_ERROR (H5E_HEAP, H5E_BADRANGE, FAIL, "new link count would be out of range"); + HGOTO_ERROR (H5E_HEAP, H5E_BADRANGE, FAIL, "new link count would be out of range") if (heap->obj[hobj->idx].nrefs+adjust>H5HG_MAXLINK) - HGOTO_ERROR (H5E_HEAP, H5E_BADVALUE, FAIL, "new link count would be out of range"); + HGOTO_ERROR (H5E_HEAP, H5E_BADVALUE, FAIL, "new link count would be out of range") heap->obj[hobj->idx].nrefs += adjust; heap_flags |= H5AC__DIRTIED_FLAG; } /* end if */ @@ -1153,7 +756,7 @@ H5HG_link (H5F_t *f, hid_t dxpl_id, const H5HG_t *hobj, int adjust) done: if(heap && H5AC_unprotect(f, dxpl_id, H5AC_GHEAP, hobj->addr, heap, heap_flags) < 0) - HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release object header"); + HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release object header") FUNC_LEAVE_NOAPI(ret_value); } @@ -1181,88 +784,89 @@ done: herr_t H5HG_remove (H5F_t *f, hid_t dxpl_id, H5HG_t *hobj) { - uint8_t *p=NULL, *obj_start=NULL; H5HG_heap_t *heap = NULL; + uint8_t *p = NULL, *obj_start = NULL; size_t need; - int i; unsigned u; - unsigned flags=H5AC__NO_FLAGS_SET;/* Whether the heap gets deleted */ - herr_t ret_value=SUCCEED; /* Return value */ + unsigned flags = H5AC__NO_FLAGS_SET;/* Whether the heap gets deleted */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5HG_remove, FAIL); /* Check args */ - assert (f); - assert (hobj); - if (0==(f->intent & H5F_ACC_RDWR)) - HGOTO_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file"); + HDassert(f); + HDassert(hobj); + if(0 == (f->intent & H5F_ACC_RDWR)) + HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file") /* Load the heap */ - if (NULL == (heap = H5AC_protect(f, dxpl_id, H5AC_GHEAP, hobj->addr, NULL, NULL, H5AC_WRITE))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap"); + if(NULL == (heap = (H5HG_heap_t *)H5AC_protect(f, dxpl_id, H5AC_GHEAP, hobj->addr, NULL, NULL, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap") - assert (hobj->idxnused); - assert (heap->obj[hobj->idx].begin); + HDassert(hobj->idx < heap->nused); + HDassert(heap->obj[hobj->idx].begin); obj_start = heap->obj[hobj->idx].begin; /* Include object header size */ - need = H5HG_ALIGN(heap->obj[hobj->idx].size)+H5HG_SIZEOF_OBJHDR(f); + need = H5HG_ALIGN(heap->obj[hobj->idx].size) + H5HG_SIZEOF_OBJHDR(f); /* Move the new free space to the end of the heap */ - for (u=0; unused; u++) { - if (heap->obj[u].begin > heap->obj[hobj->idx].begin) + for(u = 0; u < heap->nused; u++) + if(heap->obj[u].begin > heap->obj[hobj->idx].begin) heap->obj[u].begin -= need; - } - if (NULL==heap->obj[0].begin) { - heap->obj[0].begin = heap->chunk + (heap->size-need); + if(NULL == heap->obj[0].begin) { + heap->obj[0].begin = heap->chunk + (heap->size - need); heap->obj[0].size = need; heap->obj[0].nrefs = 0; - } else { + } /* end if */ + else heap->obj[0].size += need; - } - HDmemmove (obj_start, obj_start+need, - heap->size-((obj_start+need)-heap->chunk)); - if (heap->obj[0].size>=H5HG_SIZEOF_OBJHDR (f)) { + HDmemmove(obj_start, obj_start + need, + heap->size - ((obj_start + need) - heap->chunk)); + if(heap->obj[0].size >= H5HG_SIZEOF_OBJHDR(f)) { p = heap->obj[0].begin; UINT16ENCODE(p, 0); /*id*/ UINT16ENCODE(p, 0); /*nrefs*/ UINT32ENCODE(p, 0); /*reserved*/ H5F_ENCODE_LENGTH (f, p, heap->obj[0].size); - } - HDmemset (heap->obj+hobj->idx, 0, sizeof(H5HG_obj_t)); + } /* end if */ + HDmemset(heap->obj + hobj->idx, 0, sizeof(H5HG_obj_t)); flags |= H5AC__DIRTIED_FLAG; - if (heap->obj[0].size+H5HG_SIZEOF_HDR(f)==heap->size) { + 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. */ - H5_CHECK_OVERFLOW(heap->size,size_t,hsize_t); + H5_CHECK_OVERFLOW(heap->size, size_t, hsize_t); H5MF_xfree(f, H5FD_MEM_GHEAP, dxpl_id, heap->addr, (hsize_t)heap->size); flags |= H5C__DELETED_FLAG; /* Indicate that the object was deleted, for the unprotect call */ - } else { + } /* end if */ + else { + int i; /* Local index variable */ + /* * If the heap is in the CWFS list then advance it one position. The * H5AC_protect() 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; - } + for(i = 0; i < f->shared->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; + } /* end if */ break; - } - } - if (i>=f->shared->ncwfs) { - f->shared->ncwfs = MIN (f->shared->ncwfs+1, H5HG_NCWFS); - f->shared->cwfs[f->shared->ncwfs-1] = heap; - } - } + } /* end if */ + if(i >= f->shared->ncwfs) { + f->shared->ncwfs = MIN(f->shared->ncwfs + 1, H5HG_NCWFS); + f->shared->cwfs[f->shared->ncwfs - 1] = heap; + } /* end if */ + } /* end else */ done: - if (heap && H5AC_unprotect(f, dxpl_id, H5AC_GHEAP, hobj->addr, heap, flags) != SUCCEED) - HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release object header"); + if(heap && H5AC_unprotect(f, dxpl_id, H5AC_GHEAP, hobj->addr, heap, flags) < 0) + HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release object header") FUNC_LEAVE_NOAPI(ret_value); -} +} /* end H5HG_remove() */ + diff --git a/src/H5HGcache.c b/src/H5HGcache.c new file mode 100644 index 0000000..64a63b5 --- /dev/null +++ b/src/H5HGcache.c @@ -0,0 +1,439 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5HGcache.c + * October 6, 2008 + * Mike McGreevy + * + * Purpose: Implement gloabl heap metadata cache methods. + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5F_PACKAGE /*suppress error about including H5Fpkg */ +#define H5HG_PACKAGE /*suppress error about including H5HGpkg */ + + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Fpkg.h" /* File access */ +#include "H5HGpkg.h" /* Global heaps */ +#include "H5MMprivate.h" /* Memory management */ + + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + +/* Metadata cache callbacks */ +static H5HG_heap_t *H5HG_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1, + void *udata2); +static herr_t H5HG_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, + H5HG_heap_t *heap, unsigned UNUSED * flags_ptr); +static herr_t H5HG_clear(H5F_t *f, H5HG_heap_t *heap, hbool_t destroy); +static herr_t H5HG_size(const H5F_t *f, const H5HG_heap_t *heap, size_t *size_ptr); + + +/*********************/ +/* Package Variables */ +/*********************/ + +/* + * H5HG inherits cache-like properties from H5AC2 + */ +const H5AC_class_t H5AC_GHEAP[1] = {{ + H5AC_GHEAP_ID, + (H5AC_load_func_t)H5HG_load, + (H5AC_flush_func_t)H5HG_flush, + (H5AC_dest_func_t)H5HG_dest, + (H5AC_clear_func_t)H5HG_clear, + (H5AC_size_func_t)H5HG_size, +}}; + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + + +/*------------------------------------------------------------------------- + * 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 + * + *------------------------------------------------------------------------- + */ +static H5HG_heap_t * +H5HG_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * udata1, + void UNUSED * udata2) +{ + H5HG_heap_t *heap = NULL; + uint8_t *p = NULL; + size_t nalloc, need; + size_t max_idx = 0; /* The maximum index seen */ + H5HG_heap_t *ret_value = NULL; /* Return value */ + + FUNC_ENTER_NOAPI(H5HG_load, NULL) + + /* check arguments */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(!udata1); + HDassert(!udata2); + + /* Read the initial 4k page */ + if(NULL == (heap = H5FL_CALLOC(H5HG_heap_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + heap->addr = addr; + if(NULL == (heap->chunk = H5FL_BLK_MALLOC(gheap_chunk, (size_t)H5HG_MINSIZE))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + if(H5F_block_read(f, H5FD_MEM_GHEAP, addr, (size_t)H5HG_MINSIZE, dxpl_id, heap->chunk) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read global heap collection") + + /* Magic number */ + if(HDmemcmp(heap->chunk, H5HG_MAGIC, (size_t)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); + HDassert(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 + (hsize_t)H5HG_MINSIZE; + + if(NULL == (heap->chunk = H5FL_BLK_REALLOC(gheap_chunk, heap->chunk, heap->size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + if(H5F_block_read(f, H5FD_MEM_GHEAP, next_addr, (heap->size - H5HG_MINSIZE), dxpl_id, heap->chunk + H5HG_MINSIZE) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read global heap collection") + } /* end if */ + + /* Decode each object */ + p = heap->chunk + H5HG_SIZEOF_HDR(f); + nalloc = H5HG_NOBJS(f, heap->size); + + /* Calloc the obj array because the file format spec makes no guarantee + * about the order of the objects, and unused slots must be set to zero. + */ + if(NULL == (heap->obj = H5FL_SEQ_CALLOC(H5HG_obj_t, nalloc))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + heap->nalloc = nalloc; + while(p < (heap->chunk + 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. + */ + HDassert(NULL == heap->obj[0].begin); + heap->obj[0].size = (heap->chunk + heap->size) - p; + heap->obj[0].begin = p; + p += heap->obj[0].size; + } /* end if */ + else { + unsigned idx; + uint8_t *begin = p; + + UINT16DECODE(p, idx); + + /* Check if we need more room to store heap objects */ + if(idx >= heap->nalloc) { + size_t new_alloc; /* New allocation number */ + H5HG_obj_t *new_obj; /* New array of object descriptions */ + + /* Determine the new number of objects to index */ + new_alloc = MAX(heap->nalloc * 2, (idx + 1)); + HDassert(idx < new_alloc); + + /* Reallocate array of objects */ + if(NULL == (new_obj = H5FL_SEQ_REALLOC(H5HG_obj_t, heap->obj, new_alloc))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* Clear newly allocated space */ + HDmemset(&new_obj[heap->nalloc], 0, (new_alloc - heap->nalloc) * sizeof(heap->obj[0])); + + /* Update heap information */ + heap->nalloc = new_alloc; + heap->obj = new_obj; + HDassert(heap->nalloc>heap->nused); + } /* end if */ + + UINT16DECODE(p, heap->obj[idx].nrefs); + p += 4; /*reserved*/ + H5F_DECODE_LENGTH(f, p, heap->obj[idx].size); + heap->obj[idx].begin = begin; + + /* + * The total storage size includes the size of the object header + * and is zero padded so the next object header is properly + * aligned. The entire obj array was calloc'ed, so no need to zero + * the space here. The last bit of space is the free space object + * whose size is never padded and already includes the object + * header. + */ + if(idx > 0) { + need = H5HG_SIZEOF_OBJHDR(f) + H5HG_ALIGN(heap->obj[idx].size); + + if(idx > max_idx) + max_idx = idx; + } /* end if */ + else + need = heap->obj[idx].size; + p = begin + need; + } /* end else */ + } /* end while */ + HDassert(p == heap->chunk + heap->size); + HDassert(H5HG_ISALIGNED(heap->obj[0].size)); + + /* Set the next index value to use */ + if(max_idx > 0) + heap->nused = max_idx + 1; + else + heap->nused = 1; + + HDassert(max_idx < heap->nused); + + /* + * 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(!f->shared->cwfs) { + f->shared->cwfs = (H5HG_heap_t **)H5MM_malloc(H5HG_NCWFS * sizeof(H5HG_heap_t *)); + if(NULL == f->shared->cwfs) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + f->shared->ncwfs = 1; + f->shared->cwfs[0] = heap; + } else if(H5HG_NCWFS == f->shared->ncwfs) { + int i; /* Local index variable */ + + for(i = H5HG_NCWFS - 1; i >= 0; --i) + if(f->shared->cwfs[i]->obj[0].size < heap->obj[0].size) { + HDmemmove(f->shared->cwfs + 1, f->shared->cwfs, i * sizeof(H5HG_heap_t *)); + f->shared->cwfs[0] = heap; + break; + } /* end if */ + } else { + HDmemmove(f->shared->cwfs + 1, f->shared->cwfs, f->shared->ncwfs * sizeof(H5HG_heap_t *)); + f->shared->ncwfs += 1; + f->shared->cwfs[0] = heap; + } /* end else */ + + ret_value = heap; + +done: + if(!ret_value && heap) + if(H5HG_dest(f, heap) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, NULL, "unable to destroy global heap collection") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HG_load() */ + + +/*------------------------------------------------------------------------- + * Function: H5HG_flush + * + * Purpose: Flushes a global heap collection from memory to disk if it's + * dirty. Optionally deletes teh heap from memory. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Friday, March 27, 1998 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HG_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HG_heap_t *heap, unsigned UNUSED * flags_ptr) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5HG_flush, FAIL) + + /* Check arguments */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(H5F_addr_eq(addr, heap->addr)); + HDassert(heap); + + if(heap->cache_info.is_dirty) { + if(H5F_block_write(f, H5FD_MEM_GHEAP, addr, heap->size, dxpl_id, heap->chunk) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write global heap collection to file") + heap->cache_info.is_dirty = FALSE; + } /* end if */ + + if(destroy) + if(H5HG_dest(f, heap) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy global heap collection") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HG_flush() */ + + +/*------------------------------------------------------------------------- + * Function: H5HG_dest + * + * Purpose: Destroys a global heap collection in memory + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Wednesday, January 15, 2003 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HG_dest(H5F_t *f, H5HG_heap_t *heap) +{ + int i; /* Local index variable */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HG_dest) + + /* Check arguments */ + HDassert(heap); + + /* Verify that node is clean */ + HDassert(heap->cache_info.is_dirty == FALSE); + + /* Remove heap from NCWFS array, if it's present */ + for(i = 0; i < f->shared->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; + } /* end if */ + + /* Release resources */ + if(heap->chunk) + heap->chunk = H5FL_BLK_FREE(gheap_chunk, heap->chunk); + if(heap->obj) + heap->obj = H5FL_SEQ_FREE(H5HG_obj_t, heap->obj); + heap = H5FL_FREE(H5HG_heap_t, heap); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5HG_dest() */ + + +/*------------------------------------------------------------------------- + * Function: H5HG_clear + * + * Purpose: Mark a global heap in memory as non-dirty. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Thursday, March 20, 2003 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HG_clear(H5F_t *f, H5HG_heap_t *heap, hbool_t destroy) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT(H5HG_clear) + + /* Check arguments */ + HDassert(heap); + + /* Mark heap as clean */ + heap->cache_info.is_dirty = FALSE; + + if(destroy) + if(H5HG_dest(f, heap) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy global heap collection") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5HG_clear() */ + + +/*------------------------------------------------------------------------- + * Function: H5HG_size + * + * Purpose: Compute the size in bytes of the specified instance of + * H5HG_heap_t on disk, and return it in *len_ptr. On failure, + * the value of *len_ptr is undefined. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: John Mainzer + * 5/13/04 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HG_size(const H5F_t UNUSED *f, const H5HG_heap_t *heap, size_t *size_ptr) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HG_size) + + /* Check arguments */ + HDassert(heap); + HDassert(size_ptr); + + *size_ptr = heap->size; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5HG_size() */ + diff --git a/src/H5HGdbg.c b/src/H5HGdbg.c index 0e5aff8..bda9832 100644 --- a/src/H5HGdbg.c +++ b/src/H5HGdbg.c @@ -73,7 +73,7 @@ H5HG_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, assert(indent >= 0); assert(fwidth >= 0); - if (NULL == (h = H5AC_protect(f, dxpl_id, H5AC_GHEAP, addr, NULL, NULL, H5AC_READ))) + if (NULL == (h = (H5HG_heap_t *)H5AC_protect(f, dxpl_id, H5AC_GHEAP, addr, NULL, NULL, H5AC_READ))) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load global heap collection"); fprintf(stream, "%*sGlobal Heap Collection...\n", indent, ""); @@ -93,7 +93,10 @@ H5HG_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, fprintf (stream, "%*s%-*s %u/%lu/", indent, "", fwidth, "Objects defined/allocated/max:", nused, (unsigned long)h->nalloc); - fprintf (stream, nused ? "%u\n": "NA\n", maxobj); + if(nused) + fprintf(stream, "%u\n", maxobj); + else + fprintf(stream, "NA\n"); fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth, "Free space:", @@ -113,7 +116,7 @@ H5HG_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, (unsigned long)H5HG_ALIGN(h->obj[u].size)); p = h->obj[u].begin + H5HG_SIZEOF_OBJHDR (f); for (j=0; jobj[u].size; j+=16) { - fprintf (stream, "%*s%04d: ", indent+6, "", j); + fprintf (stream, "%*s%04u: ", indent+6, "", j); for (k=0; k<16; k++) { if (8==k) fprintf (stream, " "); if (j+kobj[u].size) { diff --git a/src/H5HGpkg.h b/src/H5HGpkg.h index e814367..96be009 100644 --- a/src/H5HGpkg.h +++ b/src/H5HGpkg.h @@ -32,6 +32,9 @@ #include "H5HGprivate.h" /* Other private headers needed by this file */ +#include "H5ACprivate.h" /* Metadata cache */ +#include "H5FLprivate.h" /* Free lists */ + /*****************************/ /* Package Private Variables */ @@ -40,11 +43,40 @@ /* The cache subclass */ H5_DLLVAR const H5AC_class_t H5AC_GHEAP[1]; +/* Declare extern the free list to manage the H5HG_t struct */ +H5FL_EXTERN(H5HG_heap_t); + +/* Declare extern the free list to manage sequences of H5HG_obj_t's */ +H5FL_SEQ_EXTERN(H5HG_obj_t); + +/* Declare extern the PQ free list to manage heap chunks */ +H5FL_BLK_EXTERN(gheap_chunk); + + /**************************/ /* Package Private Macros */ /**************************/ /* + * 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 + +/* * Pad all global heap messages to a multiple of eight bytes so we can load * the entire collection into memory and operate on it there. Eight should * be sufficient for machines that have alignment constraints because our @@ -56,6 +88,16 @@ H5_DLLVAR const H5AC_class_t H5AC_GHEAP[1]; #define H5HG_ISALIGNED(X) ((X)==H5HG_ALIGN(X)) /* + * The size of the collection header, always a multiple of the alignment so + * that the stuff that follows the header is aligned. + */ +#define H5HG_SIZEOF_HDR(f) \ + H5HG_ALIGN(4 + /*magic number */ \ + 1 + /*version number */ \ + 3 + /*reserved */ \ + H5F_SIZEOF_SIZE(f)) /*collection size */ + +/* * The overhead associated with each object in the heap, always a multiple of * the alignment so that the stuff that follows the header is aligned. */ @@ -65,6 +107,17 @@ H5_DLLVAR const H5AC_class_t H5AC_GHEAP[1]; 4 + /*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. The `+2' accounts for + * rounding and for the free space object. + */ +#define H5HG_NOBJS(f,z) (int)((((z)-H5HG_SIZEOF_HDR(f))/ \ + H5HG_SIZEOF_OBJHDR(f)+2)) + + /****************************/ /* Package Private Typedefs */ /****************************/ @@ -92,6 +145,7 @@ struct H5HG_heap_t { /******************************/ /* Package Private Prototypes */ /******************************/ +H5_DLL herr_t H5HG_dest(H5F_t *f, H5HG_heap_t *heap); -#endif +#endif /* _H5HGpkg_H */ diff --git a/src/H5HL.c b/src/H5HL.c index f31c47e..9e09217 100644 --- a/src/H5HL.c +++ b/src/H5HL.c @@ -28,6 +28,7 @@ /****************/ /* Module Setup */ /****************/ + #define H5F_PACKAGE /* Suppress error about including H5Fpkg */ #define H5HL_PACKAGE /* Suppress error about including H5HLpkg */ @@ -36,10 +37,8 @@ /* Headers */ /***********/ #include "H5private.h" /* Generic Functions */ -#include "H5ACprivate.h" /* Metadata cache */ #include "H5Eprivate.h" /* Error handling */ #include "H5Fpkg.h" /* File access */ -#include "H5FLprivate.h" /* Free lists */ #include "H5HLpkg.h" /* Local Heaps */ #include "H5MFprivate.h" /* File memory management */ @@ -48,13 +47,8 @@ /* Local Macros */ /****************/ -#define H5HL_FREE_NULL 1 /*end of free list on disk */ #define H5HL_MIN_HEAP 128 /* Minimum size to reduce heap buffer to */ -/* - * Local heap collection version. - */ -#define H5HL_VERSION 0 /******************/ /* Local Typedefs */ @@ -69,42 +63,23 @@ /********************/ /* Local Prototypes */ /********************/ -static herr_t H5HL_serialize(H5F_t *f, H5HL_t *heap, uint8_t *buf); + static H5HL_free_t *H5HL_remove_free(H5HL_t *heap, H5HL_free_t *fl); static herr_t H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap); -/* Metadata cache callbacks */ -static H5HL_t *H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1, - void *udata2); -static herr_t H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, H5HL_t *heap, unsigned UNUSED * flags_ptr); -static herr_t H5HL_dest(H5F_t *f, H5HL_t *heap); -static herr_t H5HL_clear(H5F_t *f, H5HL_t *heap, hbool_t destroy); -static herr_t H5HL_size(const H5F_t *f, const H5HL_t *heap, size_t *size_ptr); - -/* - * H5HL inherits cache-like properties from H5AC - */ -const H5AC_class_t H5AC_LHEAP[1] = {{ - H5AC_LHEAP_ID, - (H5AC_load_func_t)H5HL_load, - (H5AC_flush_func_t)H5HL_flush, - (H5AC_dest_func_t)H5HL_dest, - (H5AC_clear_func_t)H5HL_clear, - (H5AC_size_func_t)H5HL_size, -}}; /*********************/ /* Package Variables */ /*********************/ /* Declare a free list to manage the H5HL_free_t struct */ -H5FL_DEFINE_STATIC(H5HL_free_t); +H5FL_DEFINE(H5HL_free_t); /* Declare a free list to manage the H5HL_t struct */ -H5FL_DEFINE_STATIC(H5HL_t); +H5FL_DEFINE(H5HL_t); /* Declare a PQ free list to manage the heap chunk information */ -H5FL_BLK_DEFINE_STATIC(heap_chunk); +H5FL_BLK_DEFINE(lheap_chunk); /*****************************/ @@ -164,14 +139,14 @@ H5HL_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, haddr_t *addr_p/*out*/) /* Allocate file version */ total_size = sizeof_hdr + size_hint; if(HADDR_UNDEF == (*addr_p = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, total_size))) - HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "unable to allocate file memory") + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "unable to allocate file memory") /* allocate memory version */ if(NULL == (heap = H5FL_CALLOC(H5HL_t))) - HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "memory allocation failed") + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed") heap->addr = *addr_p + (hsize_t)sizeof_hdr; heap->heap_alloc = size_hint; - if(NULL == (heap->chunk = H5FL_BLK_CALLOC(heap_chunk,(sizeof_hdr + size_hint)))) + if(NULL == (heap->chunk = H5FL_BLK_CALLOC(lheap_chunk, (sizeof_hdr + size_hint)))) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed") /* free list */ @@ -193,10 +168,9 @@ done: if(ret_value < 0) { if(H5F_addr_defined(*addr_p)) H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, *addr_p, total_size); - if(heap) { + if(heap) if(H5HL_dest(f, heap) < 0) HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap") - } /* end if */ } /* end if */ FUNC_LEAVE_NOAPI(ret_value) @@ -204,120 +178,6 @@ done: /*------------------------------------------------------------------------- - * 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 - * - *------------------------------------------------------------------------- - */ -static H5HL_t * -H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * udata1, - void UNUSED * udata2) -{ - uint8_t hdr[52]; - size_t sizeof_hdr; /* Cache H5HL header size for file */ - const uint8_t *p = NULL; - H5HL_t *heap = NULL; - H5HL_free_t *fl = NULL, *tail = NULL; - size_t free_block = H5HL_FREE_NULL; - H5HL_t *ret_value; - - FUNC_ENTER_NOAPI(H5HL_load, NULL) - - /* check arguments */ - HDassert(f); - HDassert(H5F_addr_defined(addr)); - HDassert(!udata1); - HDassert(!udata2); - - /* Cache this for later */ - sizeof_hdr = H5HL_SIZEOF_HDR(f); - HDassert(sizeof_hdr <= sizeof(hdr)); - - /* Get the local heap's header */ - if(H5F_block_read(f, H5FD_MEM_LHEAP, addr, sizeof_hdr, dxpl_id, hdr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read heap header") - p = hdr; - - /* Check magic number */ - if(HDmemcmp(hdr, H5HL_MAGIC, (size_t)H5HL_SIZEOF_MAGIC)) - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap signature") - p += H5HL_SIZEOF_MAGIC; - - /* Version */ - if(H5HL_VERSION != *p++) - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong version number in global heap") - - /* Reserved */ - p += 3; - - /* Allocate space in memory for the heap */ - if(NULL == (heap = H5FL_CALLOC(H5HL_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - - /* heap data size */ - H5F_DECODE_LENGTH(f, p, heap->heap_alloc); - - /* free list head */ - H5F_DECODE_LENGTH(f, p, free_block); - if(free_block != H5HL_FREE_NULL && free_block >= heap->heap_alloc) - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list") - - /* data */ - H5F_addr_decode(f, &p, &(heap->addr)); - if(NULL == (heap->chunk = H5FL_BLK_CALLOC(heap_chunk, (sizeof_hdr + heap->heap_alloc)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - if(heap->heap_alloc && - H5F_block_read(f, H5FD_MEM_LHEAP, heap->addr, heap->heap_alloc, dxpl_id, heap->chunk + sizeof_hdr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unable to read heap data") - - /* Build free list */ - while(H5HL_FREE_NULL != free_block) { - if(free_block >= heap->heap_alloc) - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list") - if(NULL == (fl = H5FL_MALLOC(H5HL_free_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - fl->offset = free_block; - fl->prev = tail; - fl->next = NULL; - if(tail) - tail->next = fl; - tail = fl; - if(!heap->freelist) - heap->freelist = fl; - - p = heap->chunk + sizeof_hdr + free_block; - - H5F_DECODE_LENGTH(f, p, free_block); - if(free_block == 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "free block size is zero?") - - H5F_DECODE_LENGTH(f, p, fl->size); - if (fl->offset + fl->size > heap->heap_alloc) - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list") - } /* end while */ - - /* Set return value */ - ret_value = heap; - -done: - if(!ret_value && heap) - if(H5HL_dest(f,heap) < 0) - HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, NULL, "unable to destroy local heap collection") - - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HL_load() */ - - -/*------------------------------------------------------------------------- * Function: H5HL_minimize_heap_space * * Purpose: Go through the heap's freelist and determine if we can @@ -432,14 +292,14 @@ H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap) HDassert(new_heap_size < heap->heap_alloc); /* Resize the memory buffer */ - if(NULL == (heap->chunk = H5FL_BLK_REALLOC(heap_chunk, heap->chunk, (sizeof_hdr + new_heap_size)))) + if(NULL == (heap->chunk = H5FL_BLK_REALLOC(lheap_chunk, heap->chunk, (sizeof_hdr + new_heap_size)))) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed") /* Release old space on disk */ /* (Should be safe to free old heap space first, since it's shrinking -QAK) */ H5_CHECK_OVERFLOW(heap->heap_alloc, size_t, hsize_t); - H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, old_addr, (hsize_t)heap->heap_alloc); - H5E_clear_stack(NULL); /* don't really care if the free failed */ + if(H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, old_addr, (hsize_t)heap->heap_alloc) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap") /* Allocate new space on disk */ H5_CHECK_OVERFLOW(new_heap_size, size_t, hsize_t); @@ -457,235 +317,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5HL_serialize - * - * Purpose: Serialize the heap. This function will eliminate free - * blocks at the tail of the heap and also split the block - * if it needs to be split for the file. This is so that we - * can serialize it correctly. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Bill Wendling - * wendling@ncsa.uiuc.edu - * Sept. 16, 2003 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HL_serialize(H5F_t *f, H5HL_t *heap, uint8_t *buf) -{ - H5HL_free_t *fl; - uint8_t *p; - herr_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_serialize) - - /* check args */ - assert(buf); - assert(heap); - - /* serialize the header */ - p = buf; - fl = heap->freelist; - HDmemcpy(p, H5HL_MAGIC, (size_t)H5HL_SIZEOF_MAGIC); - p += H5HL_SIZEOF_MAGIC; - *p++ = H5HL_VERSION; - *p++ = 0; /*reserved*/ - *p++ = 0; /*reserved*/ - *p++ = 0; /*reserved*/ - H5F_ENCODE_LENGTH(f, p, heap->heap_alloc); - H5F_ENCODE_LENGTH(f, p, fl ? fl->offset : H5HL_FREE_NULL); - H5F_addr_encode(f, &p, heap->addr); - - /* serialize the free list */ - for (; fl; fl = fl->next) { - assert (fl->offset == H5HL_ALIGN (fl->offset)); - p = heap->chunk + H5HL_SIZEOF_HDR(f) + fl->offset; - - if (fl->next) { - H5F_ENCODE_LENGTH(f, p, fl->next->offset); - } else { - H5F_ENCODE_LENGTH(f, p, H5HL_FREE_NULL); - } - - H5F_ENCODE_LENGTH(f, p, fl->size); - } - - FUNC_LEAVE_NOAPI(ret_value) -} - - -/*------------------------------------------------------------------------- - * Function: H5HL_flush - * - * Purpose: Flushes a heap from memory to disk if it's dirty. Optionally - * deletes the heap from memory. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jul 17 1997 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HL_t *heap, unsigned UNUSED * flags_ptr) -{ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5HL_flush, FAIL); - - /* check arguments */ - HDassert( f ); - HDassert( H5F_addr_defined(addr) ); - HDassert( heap ); - - if (heap->cache_info.is_dirty) { - haddr_t hdr_end_addr; - size_t sizeof_hdr = H5HL_SIZEOF_HDR(f); /* cache H5HL header size for file */ - - /* Write the header */ - if (H5HL_serialize(f, heap, heap->chunk) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTSERIALIZE, FAIL, "unable to serialize local heap") - - /* Copy buffer to disk */ - hdr_end_addr = addr + (hsize_t)sizeof_hdr; - - if (H5F_addr_eq(heap->addr, hdr_end_addr)) { - /* The header and data are contiguous */ - if (H5F_block_write(f, H5FD_MEM_LHEAP, addr, (sizeof_hdr + heap->heap_alloc), - dxpl_id, heap->chunk) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header and data to file") - } else { - if (H5F_block_write(f, H5FD_MEM_LHEAP, addr, sizeof_hdr, dxpl_id, heap->chunk) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header to file") - - if (H5F_block_write(f, H5FD_MEM_LHEAP, heap->addr, heap->heap_alloc, - dxpl_id, heap->chunk + sizeof_hdr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap data to file") - } - - heap->cache_info.is_dirty = FALSE; - } - - /* Should we destroy the memory version? */ - if (destroy) { - if (H5HL_dest(f,heap) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap collection") - } - -done: - FUNC_LEAVE_NOAPI(ret_value) -} - - -/*------------------------------------------------------------------------- - * Function: H5HL_dest - * - * Purpose: Destroys a heap in memory. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Jan 15 2003 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HL_dest(H5F_t UNUSED *f, H5HL_t *heap) -{ - H5HL_free_t *fl; - - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_dest); - - /* check arguments */ - assert(heap); - - /* Verify that node is clean */ - assert (heap->cache_info.is_dirty==FALSE); - - if(heap->chunk) - heap->chunk = H5FL_BLK_FREE(heap_chunk,heap->chunk); - while (heap->freelist) { - fl = heap->freelist; - heap->freelist = fl->next; - H5FL_FREE(H5HL_free_t,fl); - } - H5FL_FREE(H5HL_t,heap); - - FUNC_LEAVE_NOAPI(SUCCEED); -} /* end H5HL_dest() */ - - -/*------------------------------------------------------------------------- - * Function: H5HL_clear - * - * Purpose: Mark a local heap in memory as non-dirty. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 20 2003 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HL_clear(H5F_t *f, H5HL_t *heap, hbool_t destroy) -{ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI_NOINIT(H5HL_clear); - - /* check arguments */ - assert(heap); - - /* Mark heap as clean */ - heap->cache_info.is_dirty = FALSE; - - if (destroy) - if (H5HL_dest(f, heap) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap collection"); - -done: - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5HL_clear() */ - - -/*------------------------------------------------------------------------- - * Function: H5HL_size - * - * Purpose: Compute the size in bytes of the specified instance of - * H5HL_t on disk, and return it in *len_ptr. On failure, - * the value of *len_ptr is undefined. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: John Mainzer - * 5/13/04 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HL_size(const H5F_t *f, const H5HL_t *heap, size_t *size_ptr) -{ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_size); - - /* check arguments */ - HDassert(f); - HDassert(heap); - HDassert(size_ptr); - - *size_ptr = H5HL_SIZEOF_HDR(f) + heap->heap_alloc; - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5HL_size() */ - - -/*------------------------------------------------------------------------- * Function: H5HL_protect * * Purpose: This function is a wrapper for the H5AC_protect call. The @@ -727,8 +358,8 @@ H5HL_protect(H5F_t *f, hid_t dxpl_id, haddr_t addr, H5AC_protect_t rw) HDassert(f); HDassert(H5F_addr_defined(addr)); - if(NULL == (ret_value = H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, rw))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unable to load heap") + if(NULL == (ret_value = (H5HL_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, rw))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to load heap") done: FUNC_LEAVE_NOAPI(ret_value) @@ -762,6 +393,7 @@ H5HL_offset_into(H5F_t *f, const H5HL_t *heap, size_t offset) HDassert(f); HDassert(heap); HDassert(offset < heap->heap_alloc); + FUNC_LEAVE_NOAPI(heap->chunk + H5HL_SIZEOF_HDR(f) + offset) } /* end H5HL_offset_into() */ @@ -827,7 +459,7 @@ H5HL_remove_free(H5HL_t *heap, H5HL_free_t *fl) if(!fl->prev) heap->freelist = fl->next; - FUNC_LEAVE_NOAPI(H5FL_FREE(H5HL_free_t, fl)) + FUNC_LEAVE_NOAPI((H5HL_free_t *)H5FL_FREE(H5HL_free_t, fl)) } /* end H5HL_remove_free() */ @@ -943,13 +575,13 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t buf_size, const void * /* Check if current heap is extendible */ can_extend = H5MF_can_extend(f, H5FD_MEM_LHEAP, heap->addr, (hsize_t)(heap->heap_alloc), (hsize_t)need_more); if(can_extend < 0) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, "unable to check whether heap can be extended") + HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, UFAIL, "unable to check whether heap can be extended") /* Check if we can extend heap in file */ if(can_extend == TRUE) { /* Extend file space allocation */ if(H5MF_extend(f, H5FD_MEM_LHEAP, heap->addr, (hsize_t)(heap->heap_alloc), (hsize_t)need_more) < 0) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, "can't extend heap on disk") + HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, UFAIL, "can't extend heap on disk") } /* end if */ else { /* ...if we can't, allocate a new chunk & release the old */ haddr_t new_addr; @@ -1027,8 +659,8 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t buf_size, const void * } #endif heap->heap_alloc = new_heap_alloc; - if(NULL == (heap->chunk = H5FL_BLK_REALLOC(heap_chunk, heap->chunk, (sizeof_hdr + heap->heap_alloc)))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, UFAIL, "memory allocation failed") + if(NULL == (heap->chunk = H5FL_BLK_REALLOC(lheap_chunk, heap->chunk, (sizeof_hdr + heap->heap_alloc)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, "memory allocation failed") /* Clear new section so junk doesn't appear in the file */ /* (Avoid clearing section which will be overwritten with newly inserted data) */ @@ -1234,8 +866,8 @@ H5HL_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr) sizeof_hdr= H5HL_SIZEOF_HDR(f); /* Get heap pointer */ - if(NULL == (heap = H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_WRITE))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap") + if(NULL == (heap = (H5HL_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load heap") /* Check if the heap is contiguous on disk */ assert(!H5F_addr_overflow(addr,sizeof_hdr)); @@ -1299,8 +931,8 @@ H5HL_get_size(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t *size) HDassert(size); /* Get heap pointer */ - if(NULL == (heap = H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_READ))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap") + if(NULL == (heap = (H5HL_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_READ))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load heap") /* Set the size to return */ *size = heap->heap_alloc; @@ -1341,7 +973,7 @@ H5HL_heapsize(H5F_t *f, hid_t dxpl_id, haddr_t addr, hsize_t *heap_size) HDassert(heap_size); /* Get heap pointer */ - if(NULL == (heap = H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_READ))) + if(NULL == (heap = (H5HL_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_READ))) HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load heap") /* Get the total size of the local heap */ diff --git a/src/H5HLcache.c b/src/H5HLcache.c new file mode 100644 index 0000000..6d17398 --- /dev/null +++ b/src/H5HLcache.c @@ -0,0 +1,444 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5HLcache.c + * Jul 23 2008 + * Quincey Koziol + * + * Purpose: Local heap metadata cache callbacks. + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5HL_PACKAGE /* Suppress error about including H5HLpkg */ + + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5HLpkg.h" /* Local Heaps */ + + +/****************/ +/* Local Macros */ +/****************/ + +/* Local heap format version */ +#define H5HL_VERSION 0 + +/* Value indicating end of free list on disk */ +#define H5HL_FREE_NULL 1 + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + +/* Local encode/decode routines */ +static herr_t H5HL_serialize(H5F_t *f, H5HL_t *heap, uint8_t *buf); + +/* Metadata cache callbacks */ +static H5HL_t *H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1, + void *udata2); +static herr_t H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, H5HL_t *heap, unsigned UNUSED * flags_ptr); +static herr_t H5HL_clear(H5F_t *f, H5HL_t *heap, hbool_t destroy); + + +/*********************/ +/* Package Variables */ +/*********************/ + +/* + * H5HL inherits cache-like properties from H5AC + */ +const H5AC_class_t H5AC_LHEAP[1] = {{ + H5AC_LHEAP_ID, + (H5AC_load_func_t)H5HL_load, + (H5AC_flush_func_t)H5HL_flush, + (H5AC_dest_func_t)H5HL_dest, + (H5AC_clear_func_t)H5HL_clear, + (H5AC_size_func_t)H5HL_size, +}}; + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + + +/*------------------------------------------------------------------------- + * Function: H5HL_serialize + * + * Purpose: Serialize the heap. This function will eliminate free + * blocks at the tail of the heap and also split the block + * if it needs to be split for the file. This is so that we + * can serialize it correctly. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Bill Wendling + * wendling@ncsa.uiuc.edu + * Sept. 16, 2003 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HL_serialize(H5F_t *f, H5HL_t *heap, uint8_t *buf) +{ + H5HL_free_t *fl; + uint8_t *p; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_serialize) + + /* check args */ + assert(buf); + assert(heap); + + /* serialize the header */ + p = buf; + fl = heap->freelist; + HDmemcpy(p, H5HL_MAGIC, (size_t)H5HL_SIZEOF_MAGIC); + p += H5HL_SIZEOF_MAGIC; + *p++ = H5HL_VERSION; + *p++ = 0; /*reserved*/ + *p++ = 0; /*reserved*/ + *p++ = 0; /*reserved*/ + H5F_ENCODE_LENGTH(f, p, heap->heap_alloc); + H5F_ENCODE_LENGTH(f, p, fl ? fl->offset : H5HL_FREE_NULL); + H5F_addr_encode(f, &p, heap->addr); + + /* serialize the free list */ + for (; fl; fl = fl->next) { + assert (fl->offset == H5HL_ALIGN (fl->offset)); + p = heap->chunk + H5HL_SIZEOF_HDR(f) + fl->offset; + + if (fl->next) { + H5F_ENCODE_LENGTH(f, p, fl->next->offset); + } else { + H5F_ENCODE_LENGTH(f, p, H5HL_FREE_NULL); + } + + H5F_ENCODE_LENGTH(f, p, fl->size); + } + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HL_serialize() */ + + +/*------------------------------------------------------------------------- + * 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 + * + *------------------------------------------------------------------------- + */ +static H5HL_t * +H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * udata1, + void UNUSED * udata2) +{ + uint8_t hdr[52]; + size_t sizeof_hdr; /* Cache H5HL header size for file */ + const uint8_t *p = NULL; + H5HL_t *heap = NULL; + H5HL_free_t *fl = NULL, *tail = NULL; + size_t free_block = H5HL_FREE_NULL; + H5HL_t *ret_value; + + FUNC_ENTER_NOAPI(H5HL_load, NULL) + + /* check arguments */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(!udata1); + HDassert(!udata2); + + /* Cache this for later */ + sizeof_hdr = H5HL_SIZEOF_HDR(f); + HDassert(sizeof_hdr <= sizeof(hdr)); + + /* Get the local heap's header */ + if(H5F_block_read(f, H5FD_MEM_LHEAP, addr, sizeof_hdr, dxpl_id, hdr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read heap header") + p = hdr; + + /* Check magic number */ + if(HDmemcmp(hdr, H5HL_MAGIC, (size_t)H5HL_SIZEOF_MAGIC)) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap signature") + p += H5HL_SIZEOF_MAGIC; + + /* Version */ + if(H5HL_VERSION != *p++) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong version number in global heap") + + /* Reserved */ + p += 3; + + /* Allocate space in memory for the heap */ + if(NULL == (heap = H5FL_CALLOC(H5HL_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* heap data size */ + H5F_DECODE_LENGTH(f, p, heap->heap_alloc); + + /* free list head */ + H5F_DECODE_LENGTH(f, p, free_block); + if(free_block != H5HL_FREE_NULL && free_block >= heap->heap_alloc) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list") + + /* data */ + H5F_addr_decode(f, &p, &(heap->addr)); + if(NULL == (heap->chunk = H5FL_BLK_CALLOC(lheap_chunk, (sizeof_hdr + heap->heap_alloc)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + if(heap->heap_alloc && + H5F_block_read(f, H5FD_MEM_LHEAP, heap->addr, heap->heap_alloc, dxpl_id, heap->chunk + sizeof_hdr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unable to read heap data") + + /* Build free list */ + while(H5HL_FREE_NULL != free_block) { + if(free_block >= heap->heap_alloc) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list") + if(NULL == (fl = H5FL_MALLOC(H5HL_free_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + fl->offset = free_block; + fl->prev = tail; + fl->next = NULL; + if(tail) + tail->next = fl; + tail = fl; + if(!heap->freelist) + heap->freelist = fl; + + p = heap->chunk + sizeof_hdr + free_block; + + H5F_DECODE_LENGTH(f, p, free_block); + if(free_block == 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "free block size is zero?") + + H5F_DECODE_LENGTH(f, p, fl->size); + if(fl->offset + fl->size > heap->heap_alloc) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list") + } /* end while */ + + /* Set return value */ + ret_value = heap; + +done: + if(!ret_value && heap) + if(H5HL_dest(f,heap) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, NULL, "unable to destroy local heap collection") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HL_load() */ + + +/*------------------------------------------------------------------------- + * Function: H5HL_flush + * + * Purpose: Flushes a heap from memory to disk if it's dirty. Optionally + * deletes the heap from memory. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jul 17 1997 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HL_t *heap, unsigned UNUSED * flags_ptr) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5HL_flush, FAIL) + + /* check arguments */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(heap); + + if(heap->cache_info.is_dirty) { + haddr_t hdr_end_addr; + size_t sizeof_hdr = H5HL_SIZEOF_HDR(f); /* cache H5HL header size for file */ + + /* Write the header */ + if(H5HL_serialize(f, heap, heap->chunk) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTSERIALIZE, FAIL, "unable to serialize local heap") + + /* Copy buffer to disk */ + hdr_end_addr = addr + (hsize_t)sizeof_hdr; + + if(H5F_addr_eq(heap->addr, hdr_end_addr)) { + /* The header and data are contiguous */ + if(H5F_block_write(f, H5FD_MEM_LHEAP, addr, (sizeof_hdr + heap->heap_alloc), dxpl_id, heap->chunk) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header and data to file") + } /* end if */ + else { + if(H5F_block_write(f, H5FD_MEM_LHEAP, addr, sizeof_hdr, dxpl_id, heap->chunk) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header to file") + + if(H5F_block_write(f, H5FD_MEM_LHEAP, heap->addr, heap->heap_alloc, dxpl_id, heap->chunk + sizeof_hdr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap data to file") + } /* end else */ + + heap->cache_info.is_dirty = FALSE; + } /* end if */ + + /* Should we destroy the memory version? */ + if(destroy) + if(H5HL_dest(f, heap) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap collection") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HL_flush() */ + + +/*------------------------------------------------------------------------- + * Function: H5HL_dest + * + * Purpose: Destroys a heap in memory. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Jan 15 2003 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HL_dest(H5F_t UNUSED *f, H5HL_t *heap) +{ + H5HL_free_t *fl; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_dest) + + /* check arguments */ + HDassert(heap); + + /* Verify that node is clean */ + HDassert(heap->cache_info.is_dirty == FALSE); + + if(heap->chunk) + heap->chunk = H5FL_BLK_FREE(lheap_chunk, heap->chunk); + while(heap->freelist) { + fl = heap->freelist; + heap->freelist = fl->next; + fl = H5FL_FREE(H5HL_free_t, fl); + } /* end while */ + heap = H5FL_FREE(H5HL_t, heap); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HL_dest() */ + + +/*------------------------------------------------------------------------- + * Function: H5HL_clear + * + * Purpose: Mark a local heap in memory as non-dirty. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 20 2003 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HL_clear(H5F_t *f, H5HL_t *heap, hbool_t destroy) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HL_clear) + + /* check arguments */ + HDassert(heap); + + /* Mark heap as clean */ + heap->cache_info.is_dirty = FALSE; + + if(destroy) + if(H5HL_dest(f, heap) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap collection") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HL_clear() */ + + +/*------------------------------------------------------------------------- + * Function: H5HL_size + * + * Purpose: Compute the size in bytes of the specified instance of + * H5HL_t on disk, and return it in *len_ptr. On failure, + * the value of *len_ptr is undefined. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: John Mainzer + * 5/13/04 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HL_size(const H5F_t *f, const H5HL_t *heap, size_t *size_ptr) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_size) + + /* check arguments */ + HDassert(f); + HDassert(heap); + HDassert(size_ptr); + + *size_ptr = H5HL_SIZEOF_HDR(f) + heap->heap_alloc; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5HL_size() */ + diff --git a/src/H5HLpkg.h b/src/H5HLpkg.h index fe6f107..856010c 100644 --- a/src/H5HLpkg.h +++ b/src/H5HLpkg.h @@ -32,6 +32,9 @@ #include "H5HLprivate.h" /* Other private headers needed by this file */ +#include "H5ACprivate.h" /* Metadata cache */ +#include "H5FLprivate.h" /* Free lists */ + /*****************************/ /* Package Private Variables */ @@ -40,6 +43,16 @@ /* The cache subclass */ H5_DLLVAR const H5AC_class_t H5AC_LHEAP[1]; +/* Declare extern the free list to manage the H5HL_free_t struct */ +H5FL_EXTERN(H5HL_free_t); + +/* Declare extern the free list to manage the H5HL_t struct */ +H5FL_EXTERN(H5HL_t); + +/* Declare extern the PQ free list to manage the heap chunk information */ +H5FL_BLK_EXTERN(lheap_chunk); + + /**************************/ /* Package Private Macros */ /**************************/ @@ -51,6 +64,7 @@ H5_DLLVAR const H5AC_class_t H5AC_LHEAP[1]; H5F_SIZEOF_SIZE (F) + /*free list head */ \ H5F_SIZEOF_ADDR (F)) /*data address */ + /****************************/ /* Package Private Typedefs */ /****************************/ @@ -71,10 +85,13 @@ struct H5HL_t { H5HL_free_t *freelist; /*the free list */ }; + /******************************/ /* Package Private Prototypes */ /******************************/ -#endif +H5_DLL herr_t H5HL_dest(H5F_t *f, H5HL_t *heap); +H5_DLL herr_t H5HL_size(const H5F_t *f, const H5HL_t *heap, size_t *size_ptr); +#endif /* _H5HLpkg_H */ diff --git a/src/Makefile.am b/src/Makefile.am index fcb47e2..0b4c423 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -63,7 +63,7 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \ H5HF.c H5HFbtree2.c H5HFcache.c H5HFdbg.c H5HFdblock.c H5HFdtable.c \ H5HFhdr.c H5HFhuge.c H5HFiblock.c H5HFiter.c H5HFman.c H5HFsection.c \ H5HFspace.c H5HFstat.c H5HFtest.c H5HFtiny.c \ - H5HG.c H5HGdbg.c H5HL.c H5HLdbg.c H5HP.c H5I.c H5L.c H5Lexternal.c \ + H5HG.c H5HGcache.c H5HGdbg.c H5HL.c H5HLcache.c H5HLdbg.c H5HP.c H5I.c H5L.c H5Lexternal.c \ H5MF.c H5MM.c H5MP.c H5MPtest.c \ H5O.c H5Oainfo.c H5Oalloc.c H5Oattr.c \ H5Oattribute.c H5Obogus.c H5Obtreek.c H5Ocache.c \ diff --git a/src/Makefile.in b/src/Makefile.in index bad04f1..4c62a1c 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -98,7 +98,7 @@ am_libhdf5_la_OBJECTS = H5.lo H5checksum.lo H5dbg.lo H5system.lo \ H5HFdblock.lo H5HFdtable.lo H5HFhdr.lo H5HFhuge.lo \ H5HFiblock.lo H5HFiter.lo H5HFman.lo H5HFsection.lo \ H5HFspace.lo H5HFstat.lo H5HFtest.lo H5HFtiny.lo H5HG.lo \ - H5HGdbg.lo H5HL.lo H5HLdbg.lo H5HP.lo H5I.lo H5L.lo \ + H5HGcache.lo H5HGdbg.lo H5HL.lo H5HLcache.lo H5HLdbg.lo H5HP.lo H5I.lo H5L.lo \ H5Lexternal.lo H5MF.lo H5MM.lo H5MP.lo H5MPtest.lo H5O.lo \ H5Oainfo.lo H5Oalloc.lo H5Oattr.lo H5Oattribute.lo H5Obogus.lo \ H5Obtreek.lo H5Ocache.lo H5Ocont.lo H5Ocopy.lo H5Odbg.lo \ @@ -441,7 +441,7 @@ libhdf5_la_SOURCES = H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \ H5HF.c H5HFbtree2.c H5HFcache.c H5HFdbg.c H5HFdblock.c H5HFdtable.c \ H5HFhdr.c H5HFhuge.c H5HFiblock.c H5HFiter.c H5HFman.c H5HFsection.c \ H5HFspace.c H5HFstat.c H5HFtest.c H5HFtiny.c \ - H5HG.c H5HGdbg.c H5HL.c H5HLdbg.c H5HP.c H5I.c H5L.c H5Lexternal.c \ + H5HG.c H5HGcache.c H5HGdbg.c H5HL.c H5HLcache.c H5HLdbg.c H5HP.c H5I.c H5L.c H5Lexternal.c \ H5MF.c H5MM.c H5MP.c H5MPtest.c \ H5O.c H5Oainfo.c H5Oalloc.c H5Oattr.c \ H5Oattribute.c H5Obogus.c H5Obtreek.c H5Ocache.c \ @@ -698,8 +698,10 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFtest.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFtiny.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HG.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HGcache.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HGdbg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HL.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HLcache.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HLdbg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HP.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5I.Plo@am__quote@ -- cgit v0.12