diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2006-03-04 22:56:44 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2006-03-04 22:56:44 (GMT) |
commit | dfbf976509bea0b4d598716d0dd73be494efacdd (patch) | |
tree | 891886081cf2ed280788eb2a33c609c55dfe2391 | |
parent | 0e708b387c78f5a286ab82eda55214fddf6c2127 (diff) | |
download | hdf5-dfbf976509bea0b4d598716d0dd73be494efacdd.zip hdf5-dfbf976509bea0b4d598716d0dd73be494efacdd.tar.gz hdf5-dfbf976509bea0b4d598716d0dd73be494efacdd.tar.bz2 |
[svn-r12004] Purpose:
New feature & code cleanup
Description:
Update fractal heap to be able to insert objects into a direct block
hanging off the header.
Extract "octal dump" code into separate routine so that both the local
heaps & fractal heaps can use it.
Other code cleanups & support to get this far.
Platforms tested:
FreeBSD 4.11 (sleipnir)
Linux 2.4
-rw-r--r-- | MANIFEST | 1 | ||||
-rw-r--r-- | src/H5AC.c | 1 | ||||
-rw-r--r-- | src/H5ACprivate.h | 1 | ||||
-rw-r--r-- | src/H5Cpkg.h | 2 | ||||
-rw-r--r-- | src/H5FDpublic.h | 4 | ||||
-rw-r--r-- | src/H5Fprivate.h | 87 | ||||
-rw-r--r-- | src/H5HF.c | 21 | ||||
-rw-r--r-- | src/H5HFcache.c | 557 | ||||
-rw-r--r-- | src/H5HFdbg.c | 221 | ||||
-rw-r--r-- | src/H5HFint.c | 569 | ||||
-rw-r--r-- | src/H5HFpkg.h | 145 | ||||
-rw-r--r-- | src/H5HFprivate.h | 17 | ||||
-rw-r--r-- | src/H5HFtest.c | 2 | ||||
-rw-r--r-- | src/H5HLdbg.c | 37 | ||||
-rw-r--r-- | src/H5I.c | 1 | ||||
-rw-r--r-- | src/H5Vprivate.h | 33 | ||||
-rw-r--r-- | src/H5dbg.c | 142 | ||||
-rw-r--r-- | src/H5private.h | 7 | ||||
-rwxr-xr-x | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/Makefile.in | 17 | ||||
-rw-r--r-- | test/fheap.c | 72 | ||||
-rw-r--r-- | tools/misc/h5debug.c | 76 |
22 files changed, 1796 insertions, 219 deletions
@@ -385,6 +385,7 @@ ./src/hdf5-win.lnt _DO_NOT_DISTRIBUTE_ ./src/hdf5-lin.lnt _DO_NOT_DISTRIBUTE_ ./src/H5.c +./src/H5dbg.c ./src/H5api_adpt.h ./src/H5err.txt ./src/H5config.h.in @@ -743,6 +743,7 @@ static const char * H5AC_entry_type_names[H5AC_NTYPES] = "v2 B-tree internal nodes", "v2 B-tree leaf nodes", "fractal heap headers", + "fractal heap direct blocks", "test entry" /* for testing only -- not used for actual files */ }; diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h index 9817a4a..e50c573 100644 --- a/src/H5ACprivate.h +++ b/src/H5ACprivate.h @@ -51,6 +51,7 @@ typedef enum { H5AC_BT2_LEAF_ID, /*v2 B-tree leaf node */ H5AC_TEST_ID, /*test entry -- not used for actual files */ H5AC_FHEAP_HDR_ID, /*fractal heap header */ + H5AC_FHEAP_DBLOCK_ID, /*fractal heap direct block */ H5AC_NTYPES /* Number of types, must be last */ } H5AC_type_t; diff --git a/src/H5Cpkg.h b/src/H5Cpkg.h index 7ee4647..155c7f5 100644 --- a/src/H5Cpkg.h +++ b/src/H5Cpkg.h @@ -609,7 +609,7 @@ ****************************************************************************/ #define H5C__H5C_T_MAGIC 0x005CAC0E -#define H5C__MAX_NUM_TYPE_IDS 10 +#define H5C__MAX_NUM_TYPE_IDS 11 #define H5C__PREFIX_LEN 32 struct H5C_t diff --git a/src/H5FDpublic.h b/src/H5FDpublic.h index 774b3f6..cbfedba 100644 --- a/src/H5FDpublic.h +++ b/src/H5FDpublic.h @@ -56,8 +56,8 @@ typedef enum H5FD_mem_t { * -QAK */ #define H5FD_MEM_FHEAP_HDR H5FD_MEM_OHDR -#define H5FD_MEM_FHEAP_INDIRECT H5FD_MEM_OHDR -#define H5FD_MEM_FHEAP_DIRECT H5FD_MEM_LHEAP +#define H5FD_MEM_FHEAP_IBLOCK H5FD_MEM_OHDR +#define H5FD_MEM_FHEAP_DBLOCK H5FD_MEM_LHEAP /* * A free-list map which maps all types of allocation requests to a single diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index 8b45ef4..ff6717f 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -79,12 +79,10 @@ typedef struct H5F_t H5F_t; int64_t _n = (n); \ size_t _i; \ uint8_t *_p = (uint8_t*)(p); \ - for (_i=0; _i<sizeof(int64_t); _i++, _n>>=8) { \ + for (_i = 0; _i < sizeof(int64_t); _i++, _n >>= 8) \ *_p++ = (uint8_t)(_n & 0xff); \ - } \ - for (/*void*/; _i<8; _i++) { \ - *_p++ = (n)<0 ? 0xff : 0; \ - } \ + for (/*void*/; _i < 8; _i++) \ + *_p++ = (n) < 0 ? 0xff : 0; \ (p) = (uint8_t*)(p)+8; \ } @@ -92,13 +90,23 @@ typedef struct H5F_t H5F_t; uint64_t _n = (n); \ size_t _i; \ uint8_t *_p = (uint8_t*)(p); \ - for (_i=0; _i<sizeof(uint64_t); _i++, _n>>=8) { \ + for (_i = 0; _i < sizeof(uint64_t); _i++, _n >>= 8) \ *_p++ = (uint8_t)(_n & 0xff); \ - } \ - for (/*void*/; _i<8; _i++) { \ + for (/*void*/; _i < 8; _i++) \ *_p++ = 0; \ - } \ - (p) = (uint8_t*)(p)+8; \ + (p) = (uint8_t*)(p) + 8; \ +} + +/* Encode a 64-bit unsigned integer into a variable-sized buffer */ +/* (Assumes that the high bits of the integer are zero) */ +# define UINT64ENCODE_VAR(p, n, l) { \ + uint64_t _n = (n); \ + size_t _i; \ + uint8_t *_p = (uint8_t*)(p); \ + \ + for(_i = 0; _i < l; _i++, _n >>= 8) \ + *_p++ = (uint8_t)(_n & 0xff); \ + (p) = (uint8_t*)(p) + l; \ } /* DECODE converts little endian bytes pointed by p to integer values and store @@ -140,9 +148,8 @@ typedef struct H5F_t H5F_t; size_t _i; \ n = 0; \ (p) += 8; \ - for (_i=0; _i<sizeof(int64_t); _i++) { \ - n = (n<<8) | *(--p); \ - } \ + for (_i = 0; _i < sizeof(int64_t); _i++) \ + n = (n << 8) | *(--p); \ (p) += 8; \ } @@ -151,19 +158,22 @@ typedef struct H5F_t H5F_t; size_t _i; \ n = 0; \ (p) += 8; \ - for (_i=0; _i<sizeof(uint64_t); _i++) { \ - n = (n<<8) | *(--p); \ - } \ + for (_i = 0; _i < sizeof(uint64_t); _i++) \ + n = (n << 8) | *(--p); \ (p) += 8; \ } -#define NBYTEENCODE(d, s, n) do { HDmemcpy(d,s,n); d += n; } while (0) - -/* - * Note: the NBYTEDECODE macro is backwards from the memcpy() routine, in - * the spirit of the other DECODE macros. - */ -#define NBYTEDECODE(s, d, n) do { HDmemcpy(d,s,n); s += n; } while (0) +/* Decode a variable-sized buffer into a 64-bit unsigned integer */ +/* (Assumes that the high bits of the integer will be zero) */ +# define UINT64DECODE_VAR(p, n, l) { \ + size_t _i; \ + \ + n = 0; \ + (p) += l; \ + for (_i = 0; _i < l; _i++) \ + n = (n << 8) | *(--p); \ + (p) += l; \ +} /* Address-related macros */ #define H5F_addr_overflow(X,Z) (HADDR_UNDEF==(X) || \ @@ -237,35 +247,28 @@ typedef struct H5F_t H5F_t; /* Macros to encode/decode offset/length's for storing in the file */ -#ifdef NOT_YET -#define H5F_ENCODE_OFFSET(f,p,o) (H5F_SIZEOF_ADDR(f)==4 ? UINT32ENCODE(p,o) \ - : H5F_SIZEOF_ADDR(f)==8 ? UINT64ENCODE(p,o) \ - : H5F_SIZEOF_ADDR(f)==2 ? UINT16ENCODE(p,o) \ - : H5FPencode_unusual_offset(f,&(p),(uint8_t*)&(o))) -#else /* NOT_YET */ #define H5F_ENCODE_OFFSET(f,p,o) switch(H5F_SIZEOF_ADDR(f)) { \ case 4: UINT32ENCODE(p,o); break; \ case 8: UINT64ENCODE(p,o); break; \ case 2: UINT16ENCODE(p,o); break; \ } -#endif /* NOT_YET */ -#define H5F_DECODE_OFFSET(f,p,o) switch (H5F_SIZEOF_ADDR (f)) { \ - case 4: UINT32DECODE (p, o); break; \ - case 8: UINT64DECODE (p, o); break; \ - case 2: UINT16DECODE (p, o); break; \ +#define H5F_DECODE_OFFSET(f,p,o) switch (H5F_SIZEOF_ADDR (f)) { \ + case 4: UINT32DECODE(p, o); break; \ + case 8: UINT64DECODE(p, o); break; \ + case 2: UINT16DECODE(p, o); break; \ } -#define H5F_ENCODE_LENGTH(f,p,l) switch(H5F_SIZEOF_SIZE(f)) { \ - case 4: UINT32ENCODE(p,l); break; \ - case 8: UINT64ENCODE(p,l); break; \ - case 2: UINT16ENCODE(p,l); break; \ +#define H5F_ENCODE_LENGTH(f,p,l) switch(H5F_SIZEOF_SIZE(f)) { \ + case 4: UINT32ENCODE(p,l); break; \ + case 8: UINT64ENCODE(p,l); break; \ + case 2: UINT16ENCODE(p,l); break; \ } -#define H5F_DECODE_LENGTH(f,p,l) switch(H5F_SIZEOF_SIZE(f)) { \ - case 4: UINT32DECODE(p,l); break; \ - case 8: UINT64DECODE(p,l); break; \ - case 2: UINT16DECODE(p,l); break; \ +#define H5F_DECODE_LENGTH(f,p,l) switch(H5F_SIZEOF_SIZE(f)) { \ + case 4: UINT32DECODE(p,l); break; \ + case 8: UINT64DECODE(p,l); break; \ + case 2: UINT16DECODE(p,l); break; \ } /* @@ -94,7 +94,7 @@ herr_t H5HF_create(H5F_t *f, hid_t dxpl_id, H5HF_create_t *cparam, haddr_t *addr_p) { H5HF_t *fh = NULL; /* The new fractal heap header information */ - herr_t ret_value = SUCCEED; + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5HF_create, FAIL) @@ -102,6 +102,7 @@ H5HF_create(H5F_t *f, hid_t dxpl_id, H5HF_create_t *cparam, haddr_t *addr_p) * Check arguments. */ HDassert(f); + HDassert(cparam); HDassert(addr_p); /* @@ -110,18 +111,18 @@ H5HF_create(H5F_t *f, hid_t dxpl_id, H5HF_create_t *cparam, haddr_t *addr_p) if(NULL == (fh = H5FL_MALLOC(H5HF_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fractal heap header") - /* Assign internal information */ + /* Reset the metadata cache info for the heap header */ HDmemset(&fh->cache_info, 0, sizeof(H5AC_info_t)); - /* Initialize shared fractal heap info */ - if(H5HF_shared_init(fh, cparam) < 0) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create shared fractal heap info") - /* Allocate space for the header on disk */ if(HADDR_UNDEF == (*addr_p = H5MF_alloc(f, H5FD_MEM_FHEAP_HDR, dxpl_id, (hsize_t)H5HF_HEADER_SIZE(f)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap header") - /* Cache the new fractal heap node */ + /* Initialize shared fractal heap info */ + if(H5HF_shared_create(f, fh, *addr_p, cparam) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create shared fractal heap info") + + /* Cache the new fractal heap header */ if(H5AC_set(f, dxpl_id, H5AC_FHEAP_HDR, *addr_p, fh, H5AC__NO_FLAGS_SET) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add fractal heap header to cache") @@ -159,6 +160,7 @@ H5HF_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t size, herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(H5HF_insert, FAIL) +HDfprintf(stderr, "%s: size = %Zu\n", FUNC, size); /* * Check arguments. @@ -181,22 +183,19 @@ H5HF_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t size, /* Check if object is large enough to be standalone */ if(size >= shared->standalone_size) { -HDfprintf(stderr, "%s: size = %Zu\n", FUNC, size); HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "standalone blocks not supported yet") } /* end if */ else { /* Check if we are in "append only" mode, or if there's enough room for the object */ if(shared->write_once) { -HDfprintf(stderr, "%s: size = %Zu\n", FUNC, size); HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "'write once' managed blocks not supported yet") } /* end if */ else if(size <= shared->total_man_free) { -HDfprintf(stderr, "%s: size = %Zu\n", FUNC, size); HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "allocating internal managed blocks not supported yet") } /* end if */ else { /* Allocate space at end of heap */ - if(H5HF_man_alloc_end(shared, size, obj, id) < 0) + if(H5HF_man_alloc_end(fh->shared, dxpl_id, &hdr_flags, size, obj, id) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate space at end of managed blocks") } /* end else */ } /* end else */ diff --git a/src/H5HFcache.c b/src/H5HFcache.c index c20d05d..735037b 100644 --- a/src/H5HFcache.c +++ b/src/H5HFcache.c @@ -35,13 +35,19 @@ #include "H5private.h" /* Generic Functions */ #include "H5HFpkg.h" /* Fractal heaps */ #include "H5Eprivate.h" /* Error handling */ +#include "H5Vprivate.h" /* Vectors and arrays */ /****************/ /* Local Macros */ /****************/ /* Fractal heap format version #'s */ -#define H5HF_HDR_VERSION 0 /* Header */ +#define H5HF_HDR_VERSION 0 /* Header */ +#define H5HF_DBLOCK_VERSION 0 /* Direct block */ + +/* Size of free space description in an absolute managed direct block */ +#define H5HF_MAN_ABS_FREE_NODE_SIZE(d) (2 * (d)->blk_off_size) + /******************/ /* Local Typedefs */ @@ -56,12 +62,20 @@ static H5HF_t *H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const static herr_t H5HF_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_t *fh); static herr_t H5HF_cache_hdr_clear(H5F_t *f, H5HF_t *fh, hbool_t destroy); static herr_t H5HF_cache_hdr_size(const H5F_t *f, const H5HF_t *fh, size_t *size_ptr); +static H5HF_direct_t *H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_type, void *udata); +static herr_t H5HF_cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_direct_t *dblock); +static herr_t H5HF_cache_dblock_clear(H5F_t *f, H5HF_direct_t *dblock, hbool_t destroy); +static herr_t H5HF_cache_dblock_size(const H5F_t *f, const H5HF_direct_t *dblock, size_t *size_ptr); + +/* Local encode/decode routines */ +static herr_t H5HF_dtable_encode(H5F_t *f, uint8_t **pp, const H5HF_dtable_param_t *dt_param); +static herr_t H5HF_dtable_decode(H5F_t *f, const uint8_t **pp, H5HF_dtable_param_t *dt_param); /*********************/ /* Package Variables */ /*********************/ -/* H5HF inherits cache-like properties from H5AC */ +/* H5HF header inherits cache-like properties from H5AC */ const H5AC_class_t H5AC_FHEAP_HDR[1] = {{ H5AC_FHEAP_HDR_ID, (H5AC_load_func_t)H5HF_cache_hdr_load, @@ -71,6 +85,16 @@ const H5AC_class_t H5AC_FHEAP_HDR[1] = {{ (H5AC_size_func_t)H5HF_cache_hdr_size, }}; +/* H5HF direct block inherits cache-like properties from H5AC */ +const H5AC_class_t H5AC_FHEAP_DBLOCK[1] = {{ + H5AC_FHEAP_DBLOCK_ID, + (H5AC_load_func_t)H5HF_cache_dblock_load, + (H5AC_flush_func_t)H5HF_cache_dblock_flush, + (H5AC_dest_func_t)H5HF_cache_dblock_dest, + (H5AC_clear_func_t)H5HF_cache_dblock_clear, + (H5AC_size_func_t)H5HF_cache_dblock_size, +}}; + /*****************************/ /* Library Private Variables */ /*****************************/ @@ -80,9 +104,112 @@ const H5AC_class_t H5AC_FHEAP_HDR[1] = {{ /* Local Variables */ /*******************/ -/* Declare a free list to manage B-tree header data to/from disk */ +/* Declare a free list to manage heap header data to/from disk */ H5FL_BLK_DEFINE_STATIC(header_block); +/* Declare a free list to manage heap direct block data to/from disk */ +H5FL_BLK_DEFINE(direct_block); + + + +/*------------------------------------------------------------------------- + * Function: H5HF_dtable_decode + * + * Purpose: Decodes the metadata for a doubling table + * + * Return: Success: Pointer to a new fractal heap + * + * Failure: NULL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 27 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_dtable_decode(H5F_t *f, const uint8_t **pp, H5HF_dtable_param_t *dt_param) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_dtable_decode) + + /* Check arguments */ + HDassert(f); + HDassert(pp && *pp); + HDassert(dt_param); + + /* Table width */ + UINT16DECODE(*pp, dt_param->cparam.width); + + /* Starting block size */ + H5F_DECODE_LENGTH(f, *pp, dt_param->cparam.start_block_size); + + /* Maximum direct block size */ + H5F_DECODE_LENGTH(f, *pp, dt_param->cparam.max_direct_size); + + /* Maximum heap size (as # of bits) */ + UINT16DECODE(*pp, dt_param->cparam.max_index); + + /* Starting # of rows in root indirect block */ + UINT16DECODE(*pp, dt_param->cparam.start_root_rows); + + /* Address of table */ + H5F_addr_decode(f, pp, &(dt_param->table_addr)); + + /* Current # of rows in root indirect block */ + UINT16DECODE(*pp, dt_param->curr_root_rows); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HF_dtable_decode() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_dtable_encode + * + * Purpose: Encodes the metadata for a doubling table + * + * Return: Success: Pointer to a new fractal heap + * + * Failure: NULL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 27 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_dtable_encode(H5F_t *f, uint8_t **pp, const H5HF_dtable_param_t *dt_param) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_dtable_encode) + + /* Check arguments */ + HDassert(f); + HDassert(pp && *pp); + HDassert(dt_param); + + /* Table width */ + UINT16ENCODE(*pp, dt_param->cparam.width); + + /* Starting block size */ + H5F_ENCODE_LENGTH(f, *pp, dt_param->cparam.start_block_size); + + /* Maximum direct block size */ + H5F_ENCODE_LENGTH(f, *pp, dt_param->cparam.max_direct_size); + + /* Maximum heap size (as # of bits) */ + UINT16ENCODE(*pp, dt_param->cparam.max_index); + + /* Starting # of rows in root indirect block */ + UINT16ENCODE(*pp, dt_param->cparam.start_root_rows); + + /* Address of table */ + H5F_addr_encode(f, pp, dt_param->table_addr); + + /* Current # of rows in root indirect block */ + UINT16ENCODE(*pp, dt_param->curr_root_rows); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HF_dtable_encode() */ /*------------------------------------------------------------------------- @@ -104,10 +231,10 @@ static H5HF_t * H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *udata1, void UNUSED *udata2) { H5HF_t *fh = NULL; /* Fractal heap info */ + H5HF_shared_t *shared = NULL; /* Shared fractal heap information */ size_t size; /* Header size */ uint8_t *buf = NULL; /* Temporary buffer */ - uint8_t *p; /* Pointer into raw data buffer */ - H5HF_create_t cparam; /* Creation parameters for heap */ + const uint8_t *p; /* Pointer into raw data buffer */ uint32_t metadata_chksum; /* Metadata checksum value */ H5HF_t *ret_value; /* Return value */ @@ -122,6 +249,11 @@ H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *ud HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") HDmemset(&fh->cache_info, 0, sizeof(H5AC_info_t)); + /* Allocate & basic initialization for the shared info struct */ + if(NULL == (shared = H5HF_shared_alloc(f))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate space for shared heap info") + shared->heap_addr = addr; + /* Compute the size of the fractal heap header on disk */ size = H5HF_HEADER_SIZE(f); @@ -135,12 +267,12 @@ H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *ud p = buf; - /* magic number */ + /* Magic number */ if(HDmemcmp(p, H5HF_HDR_MAGIC, H5HF_SIZEOF_MAGIC)) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong fractal heap header signature") p += H5HF_SIZEOF_MAGIC; - /* version */ + /* Version */ if(*p++ != H5HF_HDR_VERSION) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong fractal heap header version") @@ -156,21 +288,29 @@ H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *ud HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect metadata checksum for fractal heap header") /* Heap address mapping */ - cparam.addrmap = *p++; + shared->addrmap = *p++; HDassert(H5HF_ABSOLUTE == 0); - if(cparam.addrmap > H5HF_MAPPED) - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect fractal heap type") + if(shared->addrmap > H5HF_MAPPED) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect fractal heap address mapping") /* Min. size of standalone objects */ - UINT32DECODE(p, cparam.standalone_size); + UINT32DECODE(p, shared->standalone_size); + + /* Length of fixed-length objects in heap */ + UINT32DECODE(p, shared->fixed_len_size); - /* Size of fixed-length objects in heap */ - UINT32DECODE(p, cparam.fixed_len_size); + /* Size of ref. count for objects in heap */ + shared->ref_count_size = *p++; + + /* Managed objects' doubling-table info */ + if(H5HF_dtable_decode(shared->f, &p, &(shared->man_dtable_info)) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTENCODE, NULL, "unable to encode managed obj. doubling table info") - /* Initialize shared fractal heap info */ HDassert((size_t)(p - buf) == size); - if(H5HF_shared_init(fh, &cparam) < 0) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't create shared fractal heap info") + + /* Make shared heap info reference counted */ + if(H5HF_shared_own(fh, shared) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't create ref-count wrapper for shared fractal heap info") /* Set return value */ ret_value = fh; @@ -201,6 +341,7 @@ done: static herr_t H5HF_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_t *fh) { + H5HF_shared_t *shared; /* Shared fractal heap information */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5HF_cache_hdr_flush, FAIL) @@ -210,17 +351,16 @@ H5HF_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5H HDassert(H5F_addr_defined(addr)); HDassert(fh); + /* Get the pointer to the shared heap info */ + shared = H5RC_GET_OBJ(fh->shared); + HDassert(shared); + if(fh->cache_info.is_dirty) { - H5HF_shared_t *shared; /* Shared fractal heap information */ uint8_t *buf = NULL; /* Temporary raw data buffer */ uint8_t *p; /* Pointer into raw data buffer */ size_t size; /* Header size on disk */ - /* Get the pointer to the shared B-tree info */ - shared = H5RC_GET_OBJ(fh->shared); - HDassert(shared); - - /* Compute the size of the B-tree header on disk */ + /* Compute the size of the heap header on disk */ size = H5HF_HEADER_SIZE(f); /* Allocate temporary buffer */ @@ -254,7 +394,14 @@ H5HF_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5H /* Size of fixed-length objects in heap */ UINT32ENCODE(p, shared->fixed_len_size); - /* Write the B-tree header. */ + /* Size of ref. count for objects in heap */ + *p++ = shared->ref_count_size; + + /* Managed objects' doubling-table info */ + if(H5HF_dtable_encode(shared->f, &p, &(shared->man_dtable_info)) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTENCODE, FAIL, "unable to encode managed obj. doubling table info") + + /* Write the heap header. */ HDassert((size_t)(p - buf) == size); if(H5F_block_write(f, H5FD_MEM_FHEAP_HDR, addr, size, dxpl_id, buf) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTFLUSH, FAIL, "unable to save fractal heap header to disk") @@ -375,3 +522,367 @@ H5HF_cache_hdr_size(const H5F_t *f, const H5HF_t UNUSED *fh, size_t *size_ptr) FUNC_LEAVE_NOAPI(SUCCEED) } /* H5HF_cache_hdr_size() */ + +/*------------------------------------------------------------------------- + * Function: H5HF_cache_dblock_load + * + * Purpose: Loads a fractal heap direct block from the disk. + * + * Return: Success: Pointer to a new fractal heap direct block + * + * Failure: NULL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 27 2006 + * + *------------------------------------------------------------------------- + */ +static H5HF_direct_t * +H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_size, void *_fh_shared) +{ + const size_t *size = (const size_t *)_size; /* Size of block */ + H5RC_t *fh_shared = (H5RC_t *)_fh_shared; /* Shared heap information */ + H5HF_shared_t *shared = NULL; /* Shared fractal heap information */ + H5HF_direct_t *dblock = NULL; /* Direct block info */ + uint8_t *buf = NULL; /* Temporary buffer */ + const uint8_t *p; /* Pointer into raw data buffer */ + haddr_t heap_addr; /* Address of heap header in the file */ + uint32_t metadata_chksum; /* Metadata checksum value */ + H5HF_direct_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5HF_cache_dblock_load, NULL) + + /* Check arguments */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(fh_shared); + + /* Allocate space for the fractal heap direct block */ + if(NULL == (dblock = H5FL_MALLOC(H5HF_direct_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + HDmemset(&dblock->cache_info, 0, sizeof(H5AC_info_t)); + + /* Share common heap information */ + dblock->shared = fh_shared; + H5RC_INC(dblock->shared); + + /* Get the pointer to the shared heap info */ + shared = H5RC_GET_OBJ(dblock->shared); + HDassert(shared); + + /* Set block's internal information */ + dblock->size = *size; + dblock->blk_off_size = H5HF_SIZEOF_OFFSET_LEN(dblock->size); + dblock->free_list = NULL; + + /* Allocate block buffer */ +/* XXX: Change to using free-list factories */ + if((buf = H5FL_BLK_MALLOC(direct_block, (size_t)dblock->size)) == NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* Read header from disk */ + if(H5F_block_read(f, H5FD_MEM_FHEAP_HDR, addr, (size_t)dblock->size, dxpl_id, buf) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "can't read fractal heap direct block") + + p = buf; + + /* Magic number */ + if(HDmemcmp(p, H5HF_DBLOCK_MAGIC, H5HF_SIZEOF_MAGIC)) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong fractal heap direct block signature") + p += H5HF_SIZEOF_MAGIC; + + /* Version */ + if(*p++ != H5HF_DBLOCK_VERSION) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong fractal heap direct block version") + + /* Metadata flags (unused, currently) */ +/* XXX: Plan out metadata flags (including "read-only duplicate" feature) */ + if(*p++ != 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unknown metadata flag in fractal heap direct block") + + /* Metadata checksum (unused, currently) */ + UINT32DECODE(p, metadata_chksum); +/* XXX: Verify checksum */ + if(metadata_chksum != 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect metadata checksum for fractal heap direct block") + + /* Address of heap that owns this block (skip) */ + H5F_addr_decode(f, &p, &heap_addr); + if(H5F_addr_ne(heap_addr, shared->heap_addr)) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect heap header address for direct block") + + /* Offset of heap within the heap's address space */ + UINT64DECODE_VAR(p, dblock->block_off, shared->heap_off_size); + + /* Total free space in block */ + UINT64DECODE_VAR(p, dblock->blk_free_space, dblock->blk_off_size); + + /* Offset of free list head */ + /* (Defer deserializing the whole free list until we actually need to modify it) */ + UINT64DECODE_VAR(p, dblock->free_list_head, dblock->blk_off_size); + + /* Keep pointer to block buffer */ + dblock->blk = buf; + + /* Set return value */ + ret_value = dblock; + +done: + if(!ret_value && dblock) + (void)H5HF_cache_dblock_dest(f, dblock); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_cache_dblock_load() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_cache_dblock_flush + * + * Purpose: Flushes a dirty fractal heap direct block to disk. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 27 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_direct_t *dblock) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5HF_cache_dblock_flush, FAIL) + + /* check arguments */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(dblock); + + if(dblock->cache_info.is_dirty) { + H5HF_shared_t *shared; /* Shared fractal heap information */ + uint8_t *p; /* Pointer into raw data buffer */ + + /* Get the pointer to the shared heap info */ + shared = H5RC_GET_OBJ(dblock->shared); + HDassert(shared); + + p = dblock->blk; + + /* Magic number */ + HDmemcpy(p, H5HF_DBLOCK_MAGIC, H5HF_SIZEOF_MAGIC); + p += H5HF_SIZEOF_MAGIC; + + /* Version # */ + *p++ = H5HF_DBLOCK_VERSION; + + /* Metadata status flags */ +/* XXX: Set this? */ + *p++ = 0; + + /* Metadata checksum */ +/* XXX: Set this! (After all the metadata is in the buffer) */ + HDmemset(p, 0, 4); + p += 4; + + /* Address of heap header for heap which owns this block */ + H5F_addr_encode(f, &p, shared->heap_addr); + + /* Offset of block in heap */ + UINT64ENCODE_VAR(p, dblock->block_off, shared->heap_off_size); + + /* Check for (currently) unsupported address mapping */ + if(shared->addrmap != H5HF_ABSOLUTE) + HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "encoding mapped direct blocks not supported currently") + + /* Total free space in block */ + UINT64ENCODE_VAR(p, dblock->blk_free_space, dblock->blk_off_size); + + /* Offset of free list head */ + UINT64ENCODE_VAR(p, dblock->free_list_head, dblock->blk_off_size); + + /* Sanity check */ + HDassert((size_t)(p - dblock->blk) == H5HF_MAN_ABS_DIRECT_OVERHEAD_DBLOCK(shared, dblock)); + + /* Check for dirty free list */ + if(dblock->free_list && dblock->free_list->dirty) { + H5HF_direct_free_node_t *node; /* Pointer to free list node for block */ + + /* Loop over all free list blocks, updating their data */ + node = dblock->free_list->first; + while(node) { + /* Find first node which has enough room to describe free space */ + while(node && node->size < H5HF_MAN_ABS_FREE_NODE_SIZE(dblock)) + node = node->next; + + /* Check for free space node to encode */ + if(node) { + H5HF_direct_free_node_t *next_node; /* Pointer to next free list node for block */ + + /* Probe ahead for next node that is large enough to encode free space description */ + next_node = node->next; + while(next_node && next_node->size < H5HF_MAN_ABS_FREE_NODE_SIZE(dblock)) + next_node = next_node->next; + + /* Encode information for this node on free list */ + p = dblock->blk + node->my_offset; + UINT64ENCODE_VAR(p, node->size, dblock->blk_off_size); + UINT64ENCODE_VAR(p, (next_node ? next_node->my_offset : 0), dblock->blk_off_size); + + /* Advance to next node */ + node = node->next; + } /* end if */ + + } /* end while */ + + /* Reset the free list dirty flag */ + dblock->free_list->dirty = FALSE; + } /* end if */ + + /* Write the heap header. */ + if(H5F_block_write(f, H5FD_MEM_FHEAP_HDR, addr, (size_t)dblock->size, dxpl_id, dblock->blk) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFLUSH, FAIL, "unable to save fractal heap direct block to disk") + + dblock->cache_info.is_dirty = FALSE; + } /* end if */ + + if(destroy) + if(H5HF_cache_dblock_dest(f, dblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy fractal heap direct block") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5HF_cache_dblock_flush() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_cache_dblock_dest + * + * Purpose: Destroys a fractal heap direct block in memory. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 27 2006 + * + *------------------------------------------------------------------------- + */ +/* ARGSUSED */ +herr_t +H5HF_cache_dblock_dest(H5F_t UNUSED *f, H5HF_direct_t *dblock) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_cache_dblock_dest) + + /* + * Check arguments. + */ + HDassert(dblock); + + /* Decrement reference count on shared fractal heap info */ + if(dblock->shared) + H5RC_DEC(dblock->shared); + + /* Check for free list & free it, if necessary */ + if(dblock->free_list) { + H5HF_direct_free_node_t *node; /* Pointer to free list node for block */ + + /* Walk through list, freeing the nodes */ + node = dblock->free_list->first; + while(node) { + H5HF_direct_free_node_t *last_node; /* Pointer to last free list node for block */ + + /* Advance to next node */ + last_node = node; + node = node->next; + + /* Release the last node */ + H5FL_FREE(H5HF_direct_free_node_t, last_node); + } /* end while */ + + /* Release the free list head */ + H5FL_FREE(H5HF_direct_free_head_t, dblock->free_list); + } /* end if */ + + /* Free block's buffer */ + H5FL_BLK_FREE(direct_block, dblock->blk); + + /* Free fractal heap direct block info */ + H5FL_FREE(H5HF_direct_t, dblock); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HF_cache_dblock_dest() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_cache_dblock_clear + * + * Purpose: Mark a fractal heap direct block in memory as non-dirty. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 27 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_cache_dblock_clear(H5F_t *f, H5HF_direct_t *dblock, hbool_t destroy) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_cache_dblock_clear) + + /* + * Check arguments. + */ + HDassert(dblock); + + /* Reset the free list dirty flag */ + dblock->free_list->dirty = FALSE; + + /* Reset the dirty flag. */ + dblock->cache_info.is_dirty = FALSE; + + if(destroy) + if(H5HF_cache_dblock_dest(f, dblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy fractal heap direct block") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_cache_dblock_clear() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_cache_block_size + * + * Purpose: Compute the size in bytes of a fractal heap direct block + * on disk, and return it in *size_ptr. On failure, + * the value of *size_ptr is undefined. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 24 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_cache_dblock_size(const H5F_t UNUSED *f, const H5HF_direct_t *dblock, size_t *size_ptr) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_cache_dblock_size) + + /* check arguments */ + HDassert(dblock); + HDassert(size_ptr); + + /* Set size value */ + *size_ptr = dblock->size; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5HF_cache_dblock_size() */ + diff --git a/src/H5HFdbg.c b/src/H5HFdbg.c index 4216e96..2024402 100644 --- a/src/H5HFdbg.c +++ b/src/H5HFdbg.c @@ -33,9 +33,10 @@ /* Headers */ /***********/ #include "H5private.h" /* Generic Functions */ -#include "H5HFpkg.h" /* Fractal heaps */ #include "H5Eprivate.h" /* Error handling */ #include "H5FLprivate.h" /* Free Lists */ +#include "H5HFpkg.h" /* Fractal heaps */ +#include "H5MMprivate.h" /* Memory management */ /****************/ /* Local Macros */ @@ -51,6 +52,9 @@ /* Local Prototypes */ /********************/ +static herr_t H5HF_dtable_debug(H5HF_dtable_param_t *dt_param, FILE *stream, + int indent, int fwidth); + /*********************/ /* Package Variables */ @@ -68,6 +72,61 @@ /*------------------------------------------------------------------------- + * Function: H5HF_dtable_debug + * + * Purpose: Prints debugging info about a doubling table + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 28 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_dtable_debug(H5HF_dtable_param_t *dt_param, FILE *stream, int indent, int fwidth) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_dtable_debug) + + /* + * Check arguments. + */ + HDassert(dt_param); + HDassert(stream); + HDassert(indent >= 0); + HDassert(fwidth >= 0); + + /* + * Print the values. + */ + HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, + "Doubling table width:", + dt_param->cparam.width); + HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth, + "Starting block size:", + dt_param->cparam.start_block_size); + HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth, + "Max. direct block size:", + dt_param->cparam.max_direct_size); + HDfprintf(stream, "%*s%-*s %u (bits)\n", indent, "", fwidth, + "Max. index size:", + dt_param->cparam.max_index); + HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, + "Starting # of rows in root indirect block:", + dt_param->cparam.start_root_rows); + HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth, + "Table's root address:", + dt_param->table_addr); + HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, + "Current # of rows in root indirect block:", + dt_param->curr_root_rows); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HF_dtable_debug() */ + + +/*------------------------------------------------------------------------- * Function: H5HF_hdr_debug * * Purpose: Prints debugging info about a fractal heap header. @@ -102,7 +161,7 @@ H5HF_hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, * Load the fractal heap header. */ if(NULL == (fh = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, addr, NULL, NULL, H5AC_READ))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load fractal heap header") + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap header") /* Get the pointer to the shared fractal heap info */ shared = H5RC_GET_OBJ(fh->shared); @@ -125,11 +184,167 @@ H5HF_hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, HDfprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth, "Fixed length object size:", (unsigned long)shared->fixed_len_size); + HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, + "Ref. count size:", + (unsigned)shared->ref_count_size); + + HDfprintf(stream, "%*sManaged Objects Doubling-Table Info...\n", indent, ""); + H5HF_dtable_debug(&shared->man_dtable_info, stream, indent + 3, MAX(0, fwidth -3)); done: if(fh && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, addr, fh, H5AC__NO_FLAGS_SET) < 0) - HDONE_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release fractal heap header") + HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release fractal heap header") FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_hdr_debug() */ + +/*------------------------------------------------------------------------- + * Function: H5HF_dblock_debug + * + * Purpose: Prints debugging info about a fractal heap direct block. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 28 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_dblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, + int indent, int fwidth, haddr_t hdr_addr, size_t block_size) +{ + H5HF_t *fh = NULL; /* Fractal heap header info */ + H5HF_direct_t *dblock = NULL; /* Fractal heap direct block info */ + H5HF_direct_free_node_t *node; /* Pointer to free list node for block */ + H5HF_shared_t *shared; /* Shared fractal heap information */ + size_t blk_prefix_size; /* Size of prefix for block */ + unsigned node_count = 0; /* Number of free space nodes */ + size_t amount_free = 0; /* Amount of free space in block */ + uint8_t *marker = NULL; /* Track free space for block */ + size_t overlap; /* Number of free space overlaps */ + size_t u, v; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5HF_dblock_debug, FAIL) + + /* + * Check arguments. + */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(stream); + HDassert(indent >= 0); + HDassert(fwidth >= 0); + HDassert(H5F_addr_defined(hdr_addr)); + HDassert(block_size > 0); + + /* + * Load the fractal heap header. + */ + if(NULL == (fh = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, hdr_addr, NULL, NULL, H5AC_READ))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap header") + + /* Get the pointer to the shared fractal heap info */ + shared = H5RC_GET_OBJ(fh->shared); + HDassert(shared); + + /* + * Load the heap direct block + */ + if(NULL == (dblock = H5AC_protect(f, dxpl_id, H5AC_FHEAP_DBLOCK, addr, &block_size, fh->shared, H5AC_READ))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap direct block") + + /* Release the heap header */ + if(H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, hdr_addr, fh, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release fractal heap header") + fh = NULL; + + /* Print opening message */ + HDfprintf(stream, "%*sFractal Heap Direct Block...\n", indent, ""); + + /* + * Print the values. + */ + HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth, + "Address of fractal heap that owns this block:", + shared->heap_addr); + HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth, + "Offset of direct block in heap:", + dblock->block_off); + blk_prefix_size = H5HF_MAN_ABS_DIRECT_OVERHEAD_DBLOCK(shared, dblock); + HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth, + "Size of prefix:", + blk_prefix_size); + HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth, + "Size of block offsets:", + dblock->blk_off_size); + HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth, + "Total free space in block:", + dblock->blk_free_space); + HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth, + "Offset of free list head:", + dblock->free_list_head); + + /* Check for valid free list */ + if(!dblock->free_list) + if(H5HF_man_dblock_build_freelist(dblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDECODE, FAIL, "can't decode free list for block") + HDassert(dblock->free_list); + + /* + * Traverse the free list and check that all free blocks fall within + * the block and that no two free blocks point to the same region of + * the block. */ + if(NULL == (marker = H5MM_calloc(dblock->size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + HDfprintf(stream, "%*sFree Blocks (offset, next offset, size):\n", indent, ""); + node = dblock->free_list->first; + while(node) { + char temp_str[32]; + + sprintf(temp_str, "Block #%u:", node_count); + HDfprintf(stream, "%*s%-*s %8Zu, %8Zu, %8Zu\n", indent + 3, "", MAX(0, fwidth - 9), + temp_str, + node->my_offset, node->next_offset, node->size); + + if (node->my_offset + node->size > dblock->size) + fprintf(stream, "***THAT FREE BLOCK IS OUT OF BOUNDS!\n"); + else { + /* Mark this node's free space & check for overlaps w/other free space */ + for(u = overlap = 0; u < node->size; u++) { + if(marker[node->my_offset + u]) + overlap++; + marker[node->my_offset + u] = 1; + } /* end for */ + + if (overlap) + fprintf(stream, "***THAT FREE BLOCK OVERLAPPED A PREVIOUS ONE!\n"); + else + amount_free += node->size; + } /* end else */ + + /* Avance to next node */ + node = node->next; + node_count++; + } /* end while */ + + HDfprintf(stream, "%*s%-*s %.2f%%\n", indent, "", fwidth, + "Percent of block used:", + (100.0 * (double)(dblock->size - (blk_prefix_size + amount_free)) / (double)dblock->size)); + + /* + * Print the data in a VMS-style octal dump. + */ + H5_buffer_dump(stream, indent, dblock->blk, marker, 0, dblock->size); + +done: + if(dblock && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_DBLOCK, addr, dblock, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release fractal heap direct block") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_dblock_debug() */ + diff --git a/src/H5HFint.c b/src/H5HFint.c index 83bb780..cff06f4 100644 --- a/src/H5HFint.c +++ b/src/H5HFint.c @@ -36,11 +36,17 @@ #include "H5HFpkg.h" /* Fractal heaps */ #include "H5Eprivate.h" /* Error handling */ #include "H5MFprivate.h" /* File memory management */ +#include "H5Vprivate.h" /* Vectors and arrays */ /****************/ /* Local Macros */ /****************/ +/* Limit on the size of the max. direct block size */ +/* (This is limited to 32-bits currently, because I think it's unlikely to + * need to be larger, and the 32-bit limit for H5V_log2(n) - QAK) + */ +#define H5HL_MAX_DIRECT_SIZE_LIMIT ((hsize_t)2 * 1024 * 1024 * 1024) /******************/ /* Local Typedefs */ @@ -52,11 +58,25 @@ /********************/ static herr_t H5HF_shared_free(void *_shared); +static herr_t H5HF_man_dblock_create(H5RC_t *fh_shared, hid_t dxpl_id, + size_t block_size, hsize_t block_off, haddr_t *addr_p); +static herr_t H5HF_man_dblock_insert(H5RC_t *fh_shared, hid_t dxpl_id, + haddr_t block_addr, size_t block_size, size_t obj_size, const void *obj, + void *id); /*********************/ /* Package Variables */ /*********************/ +/* Declare a free list to manage the H5HF_direct_t struct */ +H5FL_DEFINE(H5HF_direct_t); + +/* Declare a free list to manage the H5HF_direct_free_head_t struct */ +H5FL_DEFINE(H5HF_direct_free_head_t); + +/* Declare a free list to manage the H5HF_direct_free_node_t struct */ +H5FL_DEFINE(H5HF_direct_free_node_t); + /*****************************/ /* Library Private Variables */ @@ -73,9 +93,94 @@ H5FL_DEFINE_STATIC(H5HF_shared_t); /*------------------------------------------------------------------------- - * Function: H5HF_shared_init + * Function: H5HF_shared_alloc * - * Purpose: Allocate & initialize shared fractal heap info + * Purpose: Allocate shared fractal heap info + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 27 2006 + * + *------------------------------------------------------------------------- + */ +H5HF_shared_t * +H5HF_shared_alloc(H5F_t *f) +{ + H5HF_shared_t *shared = NULL; /* Shared fractal heap information */ + H5HF_shared_t *ret_value = NULL; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_shared_alloc) + + /* + * Check arguments. + */ + HDassert(f); + + /* Allocate space for the shared information */ + if(NULL == (shared = H5FL_CALLOC(H5HF_shared_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fractal heap shared information") + + /* Set the internal parameters for the heap */ + shared->f = f; + + /* Set the return value */ + ret_value = shared; + +done: + if(!ret_value) + if(shared) + H5HF_shared_free(shared); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_shared_alloc() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_shared_own + * + * Purpose: Have heap take ownership of the shared info + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 27 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_shared_own(H5HF_t *fh, H5HF_shared_t *shared) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_shared_own) + + /* + * Check arguments. + */ + HDassert(fh); + HDassert(shared); + + /* Compute/cache some values */ + shared->fixed_len_obj = (shared->fixed_len_size > 0); + shared->ref_count_obj = (shared->ref_count_size > 0); + shared->heap_off_size = H5HF_SIZEOF_OFFSET_BITS(shared->man_dtable_info.cparam.max_index); + + /* Make shared heap info reference counted */ + if(NULL == (fh->shared = H5RC_create(shared, H5HF_shared_free))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create ref-count wrapper for shared fractal heap info") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_shared_own() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_shared_create + * + * Purpose: Allocate & create shared fractal heap info for new heap * * Return: Non-negative on success/Negative on failure * @@ -86,24 +191,47 @@ H5FL_DEFINE_STATIC(H5HF_shared_t); *------------------------------------------------------------------------- */ herr_t -H5HF_shared_init(H5HF_t *fh, H5HF_create_t *cparam) +H5HF_shared_create(H5F_t *f, H5HF_t *fh, haddr_t fh_addr, H5HF_create_t *cparam) { H5HF_shared_t *shared = NULL; /* Shared fractal heap information */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5HF_shared_init) + FUNC_ENTER_NOAPI_NOINIT(H5HF_shared_create) - /* Allocate space for the shared information */ - if(NULL == (shared = H5FL_CALLOC(H5HF_shared_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fractal heap shared information") + /* + * Check arguments. + */ + HDassert(f); + HDassert(fh); + HDassert(cparam); + +#ifndef NDEBUG + /* Check for valid parameters */ + if(!POWER_OF_TWO(cparam->managed.width) || cparam->managed.width == 0) + HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "width not power of two") + if(!POWER_OF_TWO(cparam->managed.start_block_size) || cparam->managed.start_block_size == 0) + HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "starting block size not power of two") + if(!POWER_OF_TWO(cparam->managed.max_direct_size) || + (cparam->managed.max_direct_size == 0 || cparam->managed.max_direct_size > H5HL_MAX_DIRECT_SIZE_LIMIT)) + HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "max. direct block size not power of two") + if(cparam->managed.max_index > (8 * H5F_SIZEOF_SIZE(f)) || cparam->managed.max_index == 0) + HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "max. direct block size not power of two") +#endif /* NDEBUG */ + + /* Allocate & basic initialization for the shared info struct */ + if(NULL == (shared = H5HF_shared_alloc(f))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate space for shared heap info") /* Set the creation parameters for the heap */ + shared->heap_addr = fh_addr; shared->addrmap = cparam->addrmap; shared->standalone_size = cparam->standalone_size; shared->fixed_len_size = cparam->fixed_len_size; + shared->ref_count_size = cparam->ref_count_size; + HDmemcpy(&(shared->man_dtable_info.cparam), &(cparam->managed), sizeof(H5HF_dtable_cparam_t)); - /* Make shared B-tree info reference counted */ - if(NULL == (fh->shared = H5RC_create(shared, H5HF_shared_free))) + /* Make shared heap info reference counted */ + if(H5HF_shared_own(fh, shared) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create ref-count wrapper for shared fractal heap info") done: @@ -112,7 +240,7 @@ done: H5HF_shared_free(shared); FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_shared_init() */ +} /* end H5HF_shared_create() */ /*------------------------------------------------------------------------- @@ -146,9 +274,9 @@ H5HF_shared_free(void *_shared) /*------------------------------------------------------------------------- - * Function: H5HF_alloc_end + * Function: H5HF_man_alloc_end * - * Purpose: Allocate space for an object at the end of the heap + * Purpose: Allocate space for an object at the end of the managed obj. heap * * Return: Non-negative on success (with heap ID of new object * filled in), negative on failure @@ -160,38 +288,435 @@ H5HF_shared_free(void *_shared) *------------------------------------------------------------------------- */ herr_t -H5HF_man_alloc_end(H5HF_shared_t *shared, size_t size, const void *obj, - void *id/*out*/) +H5HF_man_alloc_end(H5RC_t *fh_shared, hid_t dxpl_id, unsigned *fh_flags_ptr, + size_t size, const void *obj, void *id/*out*/) { + H5HF_shared_t *shared; /* Shared heap information */ herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI_NOINIT(H5HF_man_alloc_end) +HDfprintf(stderr, "%s: size = %Zu\n", FUNC, size); /* * Check arguments. */ - HDassert(shared); + HDassert(fh_shared); + HDassert(fh_flags_ptr); HDassert(size > 0); HDassert(obj); HDassert(id); + /* Get the pointer to the shared heap info */ + shared = H5RC_GET_OBJ(fh_shared); + HDassert(shared); + /* Check if this is the first object in the heap */ if(shared->next_man_block == 0) { - if(size /* + H5HF_DIRECT_OVERHEAD */ <= shared->man_dtable_info.start_block_size) { + /* Check if the object can fit in a direct block of the starting block size */ +#ifdef QAK +HDfprintf(stderr, "%s: H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE = %u\n", FUNC, H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE(shared, shared->man_dtable_info.cparam.start_block_size)); +HDfprintf(stderr, "%s: H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN_SIZE = %u\n", FUNC, H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN_SIZE(shared, shared->man_dtable_info.cparam.start_block_size)); +#endif /* QAK */ + if((size + H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE(shared, shared->man_dtable_info.cparam.start_block_size) + + H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN_SIZE(shared, shared->man_dtable_info.cparam.start_block_size)) + <= shared->man_dtable_info.cparam.start_block_size) { + haddr_t dblock_addr; /* Address of new direct block */ + size_t dblock_size; /* Size of new direct block */ + + /* Allocate initial direct block */ + dblock_size = shared->man_dtable_info.cparam.start_block_size; + if(H5HF_man_dblock_create(fh_shared, dxpl_id, dblock_size, (hsize_t)0, &dblock_addr) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate fractal heap direct block") +HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr); + + /* Point root at new direct block */ + shared->next_man_block = dblock_size; + shared->man_dtable_info.curr_root_rows = 0; + shared->man_dtable_info.table_addr = dblock_addr; + + /* Mark heap header as modified */ + *fh_flags_ptr |= H5AC__DIRTIED_FLAG; + + /* Attempt to insert object into direct block */ + if(H5HF_man_dblock_insert(fh_shared, dxpl_id, dblock_addr, dblock_size, size, obj, id) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't insert object into fractal heap direct block") } /* end if */ else { +HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "first object doesn't fit into starting direct block") } /* end else */ -#ifdef QAK -HDfprintf(stderr, "%s: size = %Zu\n", FUNC, size); -HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "allocating first object not supported yet") -#endif /* QAK */ } /* end if */ else { -HDfprintf(stderr, "%s: size = %Zu\n", FUNC, size); HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "allocating objects at end of heap not supported yet") } /* end else */ done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_alloc_end() */ +} /* end H5HF_man_alloc_end() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_man_dblock_create + * + * Purpose: Allocate & initialize a managed direct block + * + * Return: Pointer to new direct block on success, NULL on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 27 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_man_dblock_create(H5RC_t *fh_shared, hid_t dxpl_id, size_t block_size, + hsize_t block_off, haddr_t *addr_p) +{ + H5HF_direct_free_node_t *node; /* Pointer to free list node for block */ + H5HF_shared_t *shared; /* Pointer to shared heap info */ + H5HF_direct_t *dblock = NULL; /* Pointer to direct block */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_man_dblock_create) + + /* + * Check arguments. + */ + HDassert(fh_shared); + HDassert(block_size > 0); + HDassert(addr_p); + + /* + * Allocate file and memory data structures. + */ + if(NULL == (dblock = H5FL_MALLOC(H5HF_direct_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fractal heap header") + + /* Reset the metadata cache info for the heap header */ + HDmemset(&dblock->cache_info, 0, sizeof(H5AC_info_t)); + + /* Share common heap information */ + dblock->shared = fh_shared; + H5RC_INC(dblock->shared); + + /* Get the pointer to the shared B-tree info */ + shared = H5RC_GET_OBJ(dblock->shared); + HDassert(shared); + + /* Set info for direct block */ +HDfprintf(stderr, "%s: size = %Zu, block_off = %Hu\n", FUNC, block_size, block_off); + dblock->size = block_size; + dblock->block_off = block_off; + dblock->blk_off_size = H5HF_SIZEOF_OFFSET_LEN(block_size); + dblock->free_list_head = H5HF_MAN_ABS_DIRECT_OVERHEAD_DBLOCK(shared, dblock); + dblock->blk_free_space = block_size - dblock->free_list_head; + + /* Allocate buffer for block */ +/* XXX: Change to using free-list factories */ + if((dblock->blk = H5FL_BLK_MALLOC(direct_block, block_size)) == NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") +#ifdef H5_USING_PURIFY +HDmemset(dblock->blk, 0, dblock->size); +#endif /* H5_USING_PURIFY */ + + /* Set up free list head */ + if(NULL == (dblock->free_list = H5FL_MALLOC(H5HF_direct_free_head_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list head") + dblock->free_list->dirty = TRUE; + + /* Set up free list node for all unused space in block */ + if(NULL == (node = H5FL_MALLOC(H5HF_direct_free_node_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list node") + + /* Set node's information */ + node->size = dblock->blk_free_space; + node->my_offset = dblock->free_list_head; + node->next_offset = 0; + node->prev = node->next = NULL; + + /* Attach to free list head */ + dblock->free_list->first = node; + + /* Allocate space for the header on disk */ + if(HADDR_UNDEF == (*addr_p = H5MF_alloc(shared->f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)block_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap header") + + /* Cache the new fractal heap header */ + if(H5AC_set(shared->f, dxpl_id, H5AC_FHEAP_DBLOCK, *addr_p, dblock, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add fractal heap header to cache") + +done: + if(ret_value < 0) + if(dblock) + (void)H5HF_cache_dblock_dest(shared->f, dblock); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_man_dblock_create() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_man_dblock_build_freelist + * + * Purpose: Parse the free list information for a direct block and build + * block's free list + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 28 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_man_dblock_build_freelist(H5HF_direct_t *dblock) +{ + H5HF_direct_free_head_t *head = NULL; /* Pointer to free list head for block */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_man_dblock_build_freelist) + + /* + * Check arguments. + */ + HDassert(dblock); + + /* Allocate head of list */ + if(NULL == (head = H5FL_MALLOC(H5HF_direct_free_head_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list head") + head->dirty = FALSE; + + /* Check for any nodes on free list */ + if(dblock->free_list_head == 0) + head->first = NULL; + else { + H5HF_direct_free_node_t *node = NULL; /* Pointer to free list node for block */ + H5HF_direct_free_node_t *prev_node; /* Pointer to previous free list node for block */ + hsize_t free_len; /* Length of free list info */ + hsize_t next_off; /* Next node offset in block */ + hsize_t prev_off; /* Prev node offset in block */ + uint8_t *p; /* Temporary pointer to free node info */ + + /* Point to first node in free list */ + p = dblock->blk + dblock->free_list_head; + + /* Decode information for first node on free list */ + UINT64DECODE_VAR(p, free_len, dblock->blk_off_size); + UINT64DECODE_VAR(p, next_off, dblock->blk_off_size); + + /* Allocate node on list */ + if(NULL == (node = H5FL_MALLOC(H5HF_direct_free_node_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list node") + + /* Set node's information */ + node->size = free_len; + node->my_offset = dblock->free_list_head; + node->next_offset = next_off; + node->prev = node->next = NULL; + + /* Attach to free list head */ + head->first = node; + + /* Set up trailing node pointer */ + prev_node = node; + prev_off = next_off; + + /* Bring in rest of node on free list */ + while(next_off != 0) { + /* Point to first node in free list */ + p = dblock->blk + next_off; + + /* Decode information for first node on free list */ + UINT64DECODE_VAR(p, free_len, dblock->blk_off_size); + UINT64DECODE_VAR(p, next_off, dblock->blk_off_size); + + /* Allocate node on list */ + if(NULL == (node = H5FL_MALLOC(H5HF_direct_free_node_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list node") + + /* Set node's information */ + node->size = free_len; + node->my_offset = prev_off; + node->next_offset = next_off; + node->prev = prev_node; + node->next = NULL; + + /* Update trailing info */ + prev_node->next = node; + prev_off = next_off; + + /* Advance to next node */ + prev_node = node; + } /* end while */ + } /* end else */ + + /* Assign free list head to block */ + dblock->free_list = head; + +done: +/* XXX: cleanup on failure? */ + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_man_dblock_build_freelist() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_man_dblock_insert + * + * Purpose: Allocate space in a managed direct block + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 28 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_man_dblock_insert(H5RC_t *fh_shared, hid_t dxpl_id, haddr_t block_addr, + size_t block_size, size_t obj_size, const void *obj, void *id) +{ + H5HF_direct_t *dblock = NULL; /* Pointer to direct block to modify */ + H5HF_shared_t *shared; /* Pointer to shared heap info */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_man_dblock_insert) + + /* + * Check arguments. + */ + HDassert(fh_shared); + HDassert(H5F_addr_defined(block_addr)); + HDassert(block_size > 0); + HDassert(obj_size > 0); + HDassert(obj); + HDassert(id); + + /* Get the pointer to the shared heap info */ + shared = H5RC_GET_OBJ(fh_shared); + HDassert(shared); + + /* Lock direct block */ + if(NULL == (dblock = H5AC_protect(shared->f, dxpl_id, H5AC_FHEAP_DBLOCK, block_addr, &block_size, fh_shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load fractal heap direct block") + + /* Check for address mapping type */ + if(shared->addrmap == H5HF_ABSOLUTE) { + H5HF_direct_free_node_t *node; /* Pointer to free list node for block */ + size_t full_obj_size; /* Size of object including metadata */ + size_t obj_off; /* Offset of object within block */ + hbool_t found; /* Flag to indicate we found a node with enough free space */ + + /* Compute full object size, with metadata for object */ + full_obj_size = obj_size + H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN_DBLOCK(shared, dblock); + + /* Sanity check */ + HDassert(dblock->blk_free_space >= full_obj_size); + + /* Check for valid free list */ + if(!dblock->free_list) + if(H5HF_man_dblock_build_freelist(dblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDECODE, FAIL, "can't decode free list for block") + HDassert(dblock->free_list); + + /* Search free list for block large enough to fit object */ + node = dblock->free_list->first; + found = FALSE; + while(node) { + /* Check if this node is large enough to hold object */ + if(node->size >= full_obj_size) { + /* Check for using exact free space available */ + if(node->size == full_obj_size) { + /* Set the offset of the object within the block */ + obj_off = node->my_offset; + + /* Check for allocating from first node in list */ + if(node->prev == NULL) { + /* Make the next node in the free list the list head */ + dblock->free_list->first = node->next; + dblock->free_list_head = node->next_offset; + } /* end if */ + else { + H5HF_direct_free_node_t *prev_node; /* Pointer to previous free list node for block */ + + /* Excise node from list */ + prev_node = node->prev; + prev_node->next = node->next; + if(node->next) { + H5HF_direct_free_node_t *next_node; /* Pointer to next free list node for block */ + + next_node = node->next; + next_node->prev = prev_node; + prev_node->next_offset = next_node->my_offset; + } /* end if */ + else + prev_node->next_offset = 0; + } /* end if */ + + /* Release the memory for the free list node */ + H5FL_FREE(H5HF_direct_free_node_t, node); + } /* end if */ + else { + /* Allocate object from end of free space node */ + /* (so we don't have to play with the other node's info */ + obj_off = (node->my_offset + node->size) - full_obj_size; + node->size -= full_obj_size; + } /* end else */ + + /* Reduce space available in block */ + dblock->blk_free_space -= full_obj_size; + + /* Mark free list as dirty */ + dblock->free_list->dirty = TRUE; + found = TRUE; + } /* end if */ + + /* Avance to next node */ + node = node->next; + } /* end while */ + + /* Encode metadata & copy object into block */ + if(found) { + uint8_t *p; /* Temporary pointer to obj info */ + + /* Point to location for object */ +HDfprintf(stderr, "%s: obj_off = %Zu\n", FUNC, obj_off); +HDfprintf(stderr, "%s: full_obj_size = %Zu\n", FUNC, full_obj_size); + p = dblock->blk + obj_off; + + /* Encode the length, if required */ + if(!shared->fixed_len_obj) + UINT64ENCODE_VAR(p, obj_size, dblock->blk_off_size); + + /* Encode a ref. count (of 1), if required */ + if(shared->ref_count_obj) + UINT64ENCODE_VAR(p, 1, shared->ref_count_size); + + /* Copy the object's data into the heap */ + HDmemcpy(p, obj, obj_size); +#ifndef NDEBUG + p += obj_size; +#endif /* NDEBUG */ + + /* Sanity check */ + HDassert((size_t)(p - (dblock->blk + obj_off)) == full_obj_size); + + /* Set the head ID for the new object */ +HDfprintf(stderr, "%s: dblock->block_off = %Hu\n", FUNC, dblock->block_off); + UINT64ENCODE_VAR(id, (dblock->block_off + obj_off), shared->heap_off_size); + } /* end if */ + else + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "no space for object in block") + + } /* end if */ + else { +HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "inserting within mapped managed blocks not supported yet") + } /* end else */ + +done: + /* Release the direct block (marked as dirty) */ + if(dblock && H5AC_unprotect(shared->f, dxpl_id, H5AC_FHEAP_DBLOCK, block_addr, dblock, H5AC__DIRTIED_FLAG) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_man_dblock_insert() */ diff --git a/src/H5HFpkg.h b/src/H5HFpkg.h index 57671c0..6bb87df 100644 --- a/src/H5HFpkg.h +++ b/src/H5HFpkg.h @@ -44,21 +44,76 @@ /* Fractal heap signatures */ #define H5HF_HDR_MAGIC "FRHP" /* Header */ +#define H5HF_DBLOCK_MAGIC "FHDB" /* Direct block */ -/* Size of the fractal heap header on disk */ -#define H5HF_HEADER_SIZE(f) ( \ - /* General metadata fields */ \ +/* "Standard" size of prefix information for fractal heap metadata */ +#define H5HF_METADATA_PREFIX_SIZE ( \ 4 /* Signature */ \ + 1 /* Version */ \ + 1 /* Metadata flags */ \ + 4 /* Metadata checksum */ \ + ) + +/* Size of doubling-table information */ +#define H5HF_DTABLE_INFO_SIZE(f) ( \ + 2 /* Width of table (i.e. # of columns) */ \ + + H5F_SIZEOF_SIZE(f) /* Starting block size */ \ + + H5F_SIZEOF_SIZE(f) /* Maximum direct block size */ \ + + 2 /* Max. size of heap (log2 of actual value - i.e. the # of bits) */ \ + + 2 /* Starting # of rows in root indirect block */ \ + + H5F_SIZEOF_ADDR(f) /* File address of table managed */ \ + + 2 /* Current # of rows in root indirect block */ \ + ) + +/* Size of the fractal heap header on disk */ +#define H5HF_HEADER_SIZE(f) ( \ + /* General metadata fields */ \ + H5HF_METADATA_PREFIX_SIZE \ \ /* Fractal heap header specific fields */ \ + 1 /* Address mapping */ \ + 4 /* Min. size of standalone object */ \ + 4 /* Length of fixed-size objects */ \ + + 1 /* Size of ref. count for objects */ \ + + H5HF_DTABLE_INFO_SIZE(f) /* Size of managed obj. doubling-table info */ \ ) +/* Size of header for each object in an absolute managed direct block */ +#define H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN_SIZE(s, o) ( \ + ((s)->fixed_len_obj ? 0 : H5HF_SIZEOF_OFFSET_LEN(o)) /* Length of object in block */ \ + + (s)->ref_count_size /* Ref. count of object in block */ \ + ) +#define H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN_DBLOCK(s, d) ( \ + ((s)->fixed_len_obj ? 0 : (d)->blk_off_size) /* Length of object in block */ \ + + (s)->ref_count_size /* Ref. count of object in block */ \ + ) + +/* Size of overhead for a direct block */ +#define H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE(s, o) ( \ + /* General metadata fields */ \ + H5HF_METADATA_PREFIX_SIZE \ + \ + /* Fractal heap managed, absolutely mapped direct block specific fields */ \ + + H5F_SIZEOF_ADDR((s)->f) /* File address of heap owning the block */ \ + + (s)->heap_off_size /* Offset of the block in the heap */ \ + + H5HF_SIZEOF_OFFSET_LEN(o) /* Total free space in a block */ \ + + H5HF_SIZEOF_OFFSET_LEN(o) /* Offset of first descriptor in free list */ \ + ) +#define H5HF_MAN_ABS_DIRECT_OVERHEAD_DBLOCK(s, d) ( \ + /* General metadata fields */ \ + H5HF_METADATA_PREFIX_SIZE \ + \ + /* Fractal heap managed, absolutely mapped direct block specific fields */ \ + + H5F_SIZEOF_ADDR((s)->f) /* File address of heap owning the block */ \ + + (s)->heap_off_size /* Offset of the block in the heap */ \ + + (d)->blk_off_size /* Total free space in a block */ \ + + (d)->blk_off_size /* Offset of first descriptor in free list */ \ + ) + +/* Compute the # of bytes required to store an offset into a given buffer size */ +#define H5HF_SIZEOF_OFFSET_BITS(b) (((b) + 7) / 8) +#define H5HF_SIZEOF_OFFSET_LEN(l) H5HF_SIZEOF_OFFSET_BITS(H5V_log2((unsigned)(l))) + /****************************/ /* Package Private Typedefs */ /****************************/ @@ -66,16 +121,9 @@ /* Doubling-table info */ typedef struct H5HF_dtable_param_t { /* Immutable, pre-set information for table */ - unsigned width; /* Number of columns in the table (must be power of 2) */ - hsize_t start_block_size; /* Starting block size for table (must be power of 2) */ - hsize_t max_direct_size; /* Maximum size of a direct block (must be power of 2) */ - hsize_t max_index; /* Maximum ID/offset for table (must be power of 2) */ - unsigned start_root_rows; /* Starting number of rows for root indirect block */ - /* 0 indicates to create the full indirect block for the root, - * right from the start. Doesn't have to be power of 2 - */ + H5HF_dtable_cparam_t cparam; /* Creation parameters for table */ - /* Derived information that varies during lifetime of table */ + /* Derived information (varies during lifetime of table) */ haddr_t table_addr; /* Address of first block for table */ /* Undefined if no space allocated for table */ unsigned curr_root_rows; /* Current number of rows in the root indirect block */ @@ -89,12 +137,16 @@ typedef struct H5HF_dtable_param_t { * the instances of blocks in that fractal heap. */ typedef struct H5HF_shared_t { - /* Shared internal information */ + /* Shared internal information (varies during lifetime of heap) */ hsize_t next_man_block; /* Offset of next direct managed block */ hsize_t next_std_block; /* Offset of next direct standalone block */ hsize_t total_man_free; /* Total amount of free space in managed blocks */ hsize_t total_std_free; /* Total # of free standalone ID entries */ + /* Cached/computed values */ + haddr_t heap_addr; /* Address of heap header in the file */ + H5F_t *f; /* Pointer to file for heap */ + /* Doubling table information */ /* (Partially set by user, partially derived/updated internally) */ H5HF_dtable_param_t man_dtable_info; /* Doubling-table info for managed objects */ @@ -104,15 +156,17 @@ typedef struct H5HF_shared_t { H5HF_addrmap_t addrmap; /* Type of address mapping */ uint32_t standalone_size; /* Size of object to store standalone */ uint32_t fixed_len_size; /* Size of objects (only for heaps w/fixed-length objects) */ + unsigned char ref_count_size; /* Size of ref. count for objects (only for heaps w/ref. counted objects) */ /* Information derived from user parameters */ hbool_t fixed_len_obj; /* Are objects in the heap fixed length? */ hbool_t ref_count_obj; /* Are objects in the heap ref. counted? */ hbool_t have_io_filter; /* Does the heap have I/O filters for the direct blocks? */ hbool_t write_once; /* Is heap being written in "write once" mode? */ + unsigned char heap_off_size; /* Size of heap offsets (in bytes) */ } H5HF_shared_t; -/* The fractal heap information */ +/* The fractal heap header information */ typedef struct H5HF_t { /* Information for H5AC cache functions, _must_ be first field in structure */ H5AC_info_t cache_info; @@ -121,6 +175,39 @@ typedef struct H5HF_t { H5RC_t *shared; /* Ref-counted shared info */ } H5HF_t; +/* Direct block free list node */ +typedef struct H5HF_direct_free_node_t { + size_t size; /* Size of free space */ + size_t my_offset; /* Offset of free space in block */ + size_t next_offset; /* Offset of next free space in block */ + struct H5HF_direct_free_node_t *prev; /* Previous node in free list */ + struct H5HF_direct_free_node_t *next; /* Next node in free list */ +} H5HF_direct_free_node_t; + +/* Direct block free list header */ +typedef struct H5HF_direct_free_head_t { + H5HF_direct_free_node_t *first; /* First node in free list */ + hbool_t dirty; /* Free list is modified */ +} H5HF_direct_free_head_t; + +/* A fractal heap direct block */ +typedef struct H5HF_direct_t { + /* Information for H5AC cache functions, _must_ be first field in structure */ + H5AC_info_t cache_info; + + /* Internal heap information */ + H5RC_t *shared; /* Ref-counted shared info */ + size_t size; /* Size of direct block */ + size_t blk_off_size; /* Size of offsets in the block */ + H5HF_direct_free_head_t *free_list; /* Pointer to free list for block */ + uint8_t *blk; /* Pointer to buffer containing block data */ + + /* Stored values */ + hsize_t block_off; /* Offset of the block within the heap's address space */ + size_t blk_free_space; /* Total amount of free space in block */ + size_t free_list_head; /* Offset of head of free list in block */ +} H5HF_direct_t; + /*****************************/ /* Package Private Variables */ @@ -129,27 +216,49 @@ typedef struct H5HF_t { /* H5HF header inherits cache-like properties from H5AC */ H5_DLLVAR const H5AC_class_t H5AC_FHEAP_HDR[1]; +/* H5HF direct block inherits cache-like properties from H5AC */ +H5_DLLVAR const H5AC_class_t H5AC_FHEAP_DBLOCK[1]; + /* Declare a free list to manage the H5HF_t struct */ H5FL_EXTERN(H5HF_t); +/* Declare a free list to manage the H5HF_direct_t struct */ +H5FL_EXTERN(H5HF_direct_t); + +/* Declare a free list to manage the H5HF_direct_free_head_t struct */ +H5FL_EXTERN(H5HF_direct_free_head_t); + +/* Declare a free list to manage the H5HF_direct_free_node_t struct */ +H5FL_EXTERN(H5HF_direct_free_node_t); + +/* Declare a free list to manage heap direct block data to/from disk */ +H5FL_BLK_EXTERN(direct_block); + + /******************************/ /* Package Private Prototypes */ /******************************/ /* Routines for managing shared fractal heap info */ -H5_DLL herr_t H5HF_shared_init(H5HF_t *fh, H5HF_create_t *cparam); +H5_DLL H5HF_shared_t * H5HF_shared_alloc(H5F_t *f); +H5_DLL herr_t H5HF_shared_create(H5F_t *f, H5HF_t *fh, haddr_t heap_addr, H5HF_create_t *cparam); +H5_DLL herr_t H5HF_shared_own(H5HF_t *fh, H5HF_shared_t *shared); /* Routines for allocating space */ -herr_t H5HF_man_alloc_end(H5HF_shared_t *shared, size_t size, const void *obj, - void *id/*out*/); +H5_DLL herr_t H5HF_man_alloc_end(H5RC_t *fh_shared, hid_t dxpl_id, unsigned *fh_flags_ptr, + size_t size, const void *obj, void *id/*out*/); +H5_DLL herr_t H5HF_man_dblock_build_freelist(H5HF_direct_t *dblock); /* Metadata cache callbacks */ -H5_DLL herr_t H5HF_cache_hdr_dest(H5F_t *f, H5HF_t *b); +H5_DLL herr_t H5HF_cache_hdr_dest(H5F_t *f, H5HF_t *fh); +H5_DLL herr_t H5HF_cache_dblock_dest(H5F_t *f, H5HF_direct_t *dblock); /* Debugging routines for dumping file structures */ H5_DLL herr_t H5HF_hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int fwidth); +H5_DLL herr_t H5HF_dblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, + FILE *stream, int indent, int fwidth, haddr_t hdr_addr, unsigned nrec); /* Testing routines */ #ifdef H5HF_TESTING diff --git a/src/H5HFprivate.h b/src/H5HFprivate.h index 62334fa..984d717 100644 --- a/src/H5HFprivate.h +++ b/src/H5HFprivate.h @@ -47,13 +47,28 @@ typedef enum { H5HF_MAPPED /* The heap maps internal addresses to allow compaction */ } H5HF_addrmap_t; +/* Creation parameters for doubling-tables */ +typedef struct H5HF_dtable_cparam_t { + unsigned width; /* Number of columns in the table (must be power of 2) */ + size_t start_block_size; /* Starting block size for table (must be power of 2) */ + size_t max_direct_size; /* Maximum size of a direct block (must be power of 2) */ + unsigned max_index; /* Maximum ID/offset for table (integer log2 of actual value, ie. the # of bits required) */ + unsigned start_root_rows; /* Starting number of rows for root indirect block */ + /* 0 indicates to create the full indirect block for the root, + * right from the start. Doesn't have to be power of 2 + */ +} H5HF_dtable_cparam_t; + /* Fractal heap creation parameters */ typedef struct H5HF_create_t { + H5HF_dtable_cparam_t managed;/* Mapped object doubling-table creation parameters */ H5HF_addrmap_t addrmap; /* Type of address mapping for objects in heap */ uint32_t standalone_size; /* Size of object to store standalone */ /* (i.e. max. size of object to manage) */ - uint32_t fixed_len_size; /* Size of objects (0 means variable-sized objects) */ + uint32_t fixed_len_size; /* Size of objects, in bytes (0 means variable-sized objects) */ /* (only for heaps w/fixed-length objects) */ + unsigned char ref_count_size; /* Size of ref. count field for objects, in bytes (0 means no ref. counts for objects) */ + /* (only for heaps w/ref. counted objects) */ } H5HF_create_t; diff --git a/src/H5HFtest.c b/src/H5HFtest.c index ef14b2b..d17f804 100644 --- a/src/H5HFtest.c +++ b/src/H5HFtest.c @@ -103,6 +103,8 @@ H5HF_get_cparam_test(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr, H5HF_create_t *cp cparam->addrmap = shared->addrmap; cparam->standalone_size = shared->standalone_size; cparam->fixed_len_size = shared->fixed_len_size; + cparam->ref_count_size = shared->ref_count_size; + HDmemcpy(&(cparam->managed), &(shared->man_dtable_info.cparam), sizeof(H5HF_dtable_cparam_t)); done: /* Release fractal heap header node */ diff --git a/src/H5HLdbg.c b/src/H5HLdbg.c index 0401f92..1dedaa5 100644 --- a/src/H5HLdbg.c +++ b/src/H5HLdbg.c @@ -125,44 +125,11 @@ H5HL_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent, int "Percent of heap used:", (100.0 * (double)(h->heap_alloc - amount_free) / (double)h->heap_alloc)); } + /* * Print the data in a VMS-style octal dump. */ - fprintf(stream, "%*sData follows (`__' indicates free region)...\n", - indent, ""); - for (i=0; i<(int)(h->heap_alloc); i+=16) { - fprintf(stream, "%*s %8d: ", indent, "", i); - for (j = 0; j < 16; j++) { - if (i+j<(int)(h->heap_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 < (int)(h->heap_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); - } + H5_buffer_dump(stream, indent, h->chunk, marker, H5HL_SIZEOF_HDR(f), h->heap_alloc); done: if (h && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, h, FALSE) != SUCCEED) @@ -72,7 +72,6 @@ * than the ID_MASK constant). */ # define H5I_LOC(a,s) ((hid_t)((size_t)(a)&((s)-1))) -# define POWER_OF_TWO(n) ((((n) - 1) & (n)) == 0 && (n) > 0) #else /* * Map an ID to a hash location. diff --git a/src/H5Vprivate.h b/src/H5Vprivate.h index 52f9d6b..55047cb 100644 --- a/src/H5Vprivate.h +++ b/src/H5Vprivate.h @@ -300,4 +300,35 @@ H5V_vector_inc(int n, hsize_t *v1, const hsize_t *v2) while (n--) *v1++ += *v2++; } -#endif + +/*------------------------------------------------------------------------- + * Function: H5V_power_of_two + * + * Purpose: Determines the log base two of a number (i.e. log2(n)). + * + * Note: N must be a power of two and is limited to 32-bit quantities. + + * This is from the "Bit Twiddling Hacks" at: + * http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn + * + * Return: log2(n) (always - no failure condition) + * + * Programmer: Quincey Koziol + * Monday, Febraury 27, 2006 + * + *------------------------------------------------------------------------- + */ +static H5_inline unsigned +H5V_log2(unsigned n) +{ + static const unsigned MultiplyDeBruijnBitPosition[32] = + { + 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, + 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 + }; + + return(MultiplyDeBruijnBitPosition[(n * 0x077CB531UL) >> 27]); +} /* H5V_log2() */ + +#endif /* H5Vprivate_H */ + diff --git a/src/H5dbg.c b/src/H5dbg.c new file mode 100644 index 0000000..8df83d3 --- /dev/null +++ b/src/H5dbg.c @@ -0,0 +1,142 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5dbg.c + * Mar 4 2006 + * Quincey Koziol <koziol@ncsa.uiuc.edu> + * + * Purpose: Generic debugging routines + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + + +/*------------------------------------------------------------------------- + * Function: H5_buffer_dump + * + * Purpose: Dumps a buffer of memory in an octal dump form + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 4 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5_buffer_dump(FILE *stream, int indent, uint8_t *buf, + uint8_t *marker, size_t buf_offset, size_t buf_size) +{ + size_t u, v; /* Local index variable */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5_buffer_dump) + + /* + * Check arguments. + */ + HDassert(stream); + HDassert(indent >= 0); + HDassert(buf); + HDassert(marker); + HDassert(buf_size > 0); + + /* + * Print the buffer in a VMS-style octal dump. + */ + HDfprintf(stream, "%*sData follows (`__' indicates free region)...\n", + indent, ""); + for(u = 0; u < buf_size; u += 16) { + uint8_t c; + + HDfprintf(stream, "%*s %8d: ", indent, "", u); + + /* Print the hex values */ + for(v = 0; v < 16; v++) { + if(u + v < buf_size) { + if(marker[u + v]) + HDfprintf(stream, "__ "); + else { + c = buf[buf_offset + u + v]; + HDfprintf(stream, "%02x ", c); + } /* end else */ + } /* end if */ + else + fprintf(stream, " "); + if(7 == v) + HDfputc(' ', stream); + } /* end for */ + + /* Print the character values */ + for(v = 0; v < 16; v++) { + if(u + v < buf_size) { + if(marker[u + v]) + HDfputc(' ', stream); + else { + c = buf[buf_offset + u + v]; + if(HDisprint(c)) + HDfputc(c, stream); + else + HDfputc('.', stream); + } /* end else */ + } /* end if */ + } /* end for */ + + HDfputc('\n', stream); + } /* end for */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5_buffer_dump() */ + diff --git a/src/H5private.h b/src/H5private.h index 1b904e3..e7f339b 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -325,6 +325,9 @@ # define SIGN(a) ((a)>0 ? 1 : (a)<0 ? -1 : 0) #endif +/* test for number that is a power of 2 */ +# define POWER_OF_TWO(n) ((((n) - 1) & (n)) == 0 && (n) > 0) + /* * HDF Boolean type. */ @@ -1411,5 +1414,9 @@ H5_DLL int H5S_term_interface(void); H5_DLL int H5T_term_interface(void); H5_DLL int H5Z_term_interface(void); +/* Functions for debugging */ +H5_DLL herr_t H5_buffer_dump(FILE *stream, int indent, uint8_t *buf, + uint8_t *marker, size_t buf_offset, size_t buf_size); + #endif diff --git a/src/Makefile.am b/src/Makefile.am index 0a3abbf..d6ebcfb 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -37,7 +37,7 @@ libhdf5_la_LDFLAGS= -version-info $(LT_VERS_INTERFACE):$(LT_VERS_REVISION):$(LT_ MOSTLYCLEANFILES=H5Tinit.c # library sources -libhdf5_la_SOURCES= H5.c H5A.c H5AC.c H5B.c H5Bcache.c \ +libhdf5_la_SOURCES= H5.c H5dbg.c H5A.c H5AC.c H5B.c H5Bcache.c \ H5B2.c H5B2cache.c H5B2dbg.c H5B2int.c H5B2test.c \ H5C.c \ H5D.c \ diff --git a/src/Makefile.in b/src/Makefile.in index b7914e1..8ef4320 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -82,13 +82,13 @@ am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(settingsdir)" \ libLTLIBRARIES_INSTALL = $(INSTALL) LTLIBRARIES = $(lib_LTLIBRARIES) libhdf5_la_LIBADD = -am_libhdf5_la_OBJECTS = H5.lo H5A.lo H5AC.lo H5B.lo H5Bcache.lo \ - H5B2.lo H5B2cache.lo H5B2dbg.lo H5B2int.lo H5B2test.lo H5C.lo \ - H5D.lo H5Dcompact.lo H5Dcontig.lo H5Defl.lo H5Dio.lo \ - H5Distore.lo H5Dmpio.lo H5Doh.lo H5Dselect.lo H5Dtest.lo \ - H5E.lo H5F.lo H5Fdbg.lo H5Fmount.lo H5Fsfile.lo H5Fsuper.lo \ - H5FD.lo H5FDcore.lo H5FDfamily.lo H5FDfphdf5.lo H5FDlog.lo \ - H5FDmpi.lo H5FDmpio.lo H5FDmpiposix.lo H5FDmulti.lo \ +am_libhdf5_la_OBJECTS = H5.lo H5dbg.lo H5A.lo H5AC.lo H5B.lo \ + H5Bcache.lo H5B2.lo H5B2cache.lo H5B2dbg.lo H5B2int.lo \ + H5B2test.lo H5C.lo H5D.lo H5Dcompact.lo H5Dcontig.lo H5Defl.lo \ + H5Dio.lo H5Distore.lo H5Dmpio.lo H5Doh.lo H5Dselect.lo \ + H5Dtest.lo H5E.lo H5F.lo H5Fdbg.lo H5Fmount.lo H5Fsfile.lo \ + H5Fsuper.lo H5FD.lo H5FDcore.lo H5FDfamily.lo H5FDfphdf5.lo \ + H5FDlog.lo H5FDmpi.lo H5FDmpio.lo H5FDmpiposix.lo H5FDmulti.lo \ H5FDsec2.lo H5FDstdio.lo H5FDstream.lo H5FL.lo H5FO.lo H5FP.lo \ H5FPclient.lo H5FPserver.lo H5FS.lo H5G.lo H5Gent.lo \ H5Glink.lo H5Gloc.lo H5Gname.lo H5Gnode.lo H5Gobj.lo H5Goh.lo \ @@ -389,7 +389,7 @@ libhdf5_la_LDFLAGS = -version-info $(LT_VERS_INTERFACE):$(LT_VERS_REVISION):$(LT MOSTLYCLEANFILES = H5Tinit.c # library sources -libhdf5_la_SOURCES = H5.c H5A.c H5AC.c H5B.c H5Bcache.c \ +libhdf5_la_SOURCES = H5.c H5dbg.c H5A.c H5AC.c H5B.c H5Bcache.c \ H5B2.c H5B2cache.c H5B2dbg.c H5B2int.c H5B2test.c \ H5C.c \ H5D.c \ @@ -702,6 +702,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Zshuffle.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Zszip.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Ztrans.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5dbg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5detect-H5detect.Po@am__quote@ .c.o: diff --git a/test/fheap.c b/test/fheap.c index 1a9f8e9..3aaa7e8 100644 --- a/test/fheap.c +++ b/test/fheap.c @@ -28,6 +28,17 @@ /* Other private headers that this test requires */ #include "H5Iprivate.h" +/* "Standard" creation table parameters */ +#define STD_ADDRMAP H5HF_ABSOLUTE /* Heap address mapping */ +#define STD_STAND_SIZE (64 * 1024) /* Standalone obj. min. size */ +#define STD_FIXED_LEN_SIZE 0 /* Fixed length obj. size */ +#define STD_REF_COUNT_SIZE 0 /* Size of ref. count for obj. */ +#define STD_MAN_WIDTH 32 /* Managed obj. table width */ +#define STD_MAN_START_BLOCK_SIZE 1024 /* Managed obj. starting block size */ +#define STD_MAN_MAX_DIRECT_SIZE (1024 * 1024) /* Managed obj. max. direct block size */ +#define STD_MAN_MAX_INDEX 64 /* Managed obj. # of bits for total heap size */ +#define STD_MAN_START_ROOT_ROWS 1 /* Managed obj. starting # of root indirect block rows */ + const char *FILENAME[] = { "fheap", NULL @@ -35,6 +46,44 @@ const char *FILENAME[] = { /*------------------------------------------------------------------------- + * Function: init_std_cparam + * + * Purpose: Initialize heap creation parameter structure with standard + * settings + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Monday, February 27, 2006 + * + *------------------------------------------------------------------------- + */ +static int +init_std_cparam(H5HF_create_t *cparam) +{ + /* Wipe out background */ + HDmemset(cparam, 0, sizeof(H5HF_create_t)); + + /* General parameters */ + cparam->addrmap = STD_ADDRMAP; + cparam->standalone_size = STD_STAND_SIZE; + cparam->fixed_len_size = STD_FIXED_LEN_SIZE; + cparam->ref_count_size = STD_REF_COUNT_SIZE; + + /* Managed object doubling-table parameters */ + cparam->managed.width = STD_MAN_WIDTH; + cparam->managed.start_block_size = STD_MAN_START_BLOCK_SIZE; + cparam->managed.max_direct_size = STD_MAN_MAX_DIRECT_SIZE; + cparam->managed.max_index = STD_MAN_MAX_INDEX; + cparam->managed.start_root_rows = STD_MAN_START_ROOT_ROWS; + + return(0); +} /* init_std_cparam() */ + + +/*------------------------------------------------------------------------- * Function: test_create * * Purpose: Create fractal heap @@ -72,9 +121,7 @@ test_create(hid_t fapl) * Test fractal heap creation (w/absolute address mapping) */ TESTING("Fractal heap creation (w/absolute address mapping)"); - cparam.addrmap = H5HF_ABSOLUTE; - cparam.standalone_size = 64 * 1024; - cparam.fixed_len_size = 0; + init_std_cparam(&cparam); if(H5HF_create(f, H5P_DATASET_XFER_DEFAULT, &cparam, &fh_addr/*out*/) < 0) FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) @@ -94,9 +141,8 @@ test_create(hid_t fapl) * Test fractal heap creation (w/mapped address mapping) */ TESTING("Fractal heap creation (w/mapped address mapping)"); + init_std_cparam(&cparam); cparam.addrmap = H5HF_MAPPED; - cparam.standalone_size = 64 * 1024; - cparam.fixed_len_size = 0; if(H5HF_create(f, H5P_DATASET_XFER_DEFAULT, &cparam, &fh_addr/*out*/) < 0) FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) @@ -151,7 +197,7 @@ test_abs_insert_first(hid_t fapl) H5HF_create_t cparam; /* Creation parameters for heap */ haddr_t fh_addr; /* Address of fractal heap created */ unsigned char obj[10]; /* Buffer for object to insert */ - haddr_t heap_id; /* Heap ID for object inserted */ + hsize_t heap_id; /* Heap ID for object inserted */ unsigned u; /* Local index variable */ herr_t ret; /* Generic error return value */ @@ -167,14 +213,12 @@ test_abs_insert_first(hid_t fapl) STACK_ERROR /* Create absolute heap */ - cparam.addrmap = H5HF_ABSOLUTE; - cparam.standalone_size = 64 * 1024; - cparam.fixed_len_size = 0; + init_std_cparam(&cparam); if(H5HF_create(f, dxpl, &cparam, &fh_addr/*out*/) < 0) FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR -#ifdef QAK +#ifndef QAK HDfprintf(stdout, "Fractal heap header address = %a\n", fh_addr); #endif /* QAK */ @@ -186,11 +230,11 @@ HDfprintf(stdout, "Fractal heap header address = %a\n", fh_addr); * Test inserting first (small) object into absolute heap */ TESTING("Inserting first (small) object into absolute heap"); - heap_id = HADDR_UNDEF; + heap_id = 0; if(H5HF_insert(f, dxpl, fh_addr, sizeof(obj), obj, &heap_id) < 0) FAIL_STACK_ERROR -#ifdef QAK -HDfprintf(stdout, "heap_id = %a\n", heap_id); +#ifndef QAK +HDfprintf(stdout, "heap_id = %Hu\n", heap_id); #endif /* QAK */ PASSED() @@ -242,7 +286,7 @@ main(void) if(nerrors) goto error; puts("All fractal heap tests passed."); -#ifndef QAK +#ifdef QAK h5_cleanup(FILENAME, fapl); #else /* QAK */ HDfprintf(stderr, "Uncomment cleanup!\n"); diff --git a/tools/misc/h5debug.c b/tools/misc/h5debug.c index b93ec2a..ca26c5d 100644 --- a/tools/misc/h5debug.c +++ b/tools/misc/h5debug.c @@ -74,19 +74,18 @@ main(int argc, char *argv[]) { hid_t fid, fapl, dxpl; H5F_t *f; - haddr_t addr=0, extra=0, extra2=0; + haddr_t addr = 0, extra = 0, extra2 = 0; uint8_t sig[SIGLEN]; - int i; + size_t u; herr_t status = SUCCEED; - if (argc == 1) { - fprintf(stderr, - "Usage: %s filename [signature-addr [extra]]\n", argv[0]); + if(argc == 1) { + fprintf(stderr, "Usage: %s filename [signature-addr [extra]]\n", argv[0]); HDexit(1); } /* Initialize the library */ - if(H5open ()<0) { + if(H5open() < 0) { fprintf(stderr, "cannot initialize the library\n"); HDexit(1); } @@ -102,14 +101,13 @@ main(int argc, char *argv[]) fprintf(stderr, "cannot create file access property list\n"); HDexit(1); } - if (strchr (argv[1], '%')) { + if(strchr (argv[1], '%')) H5Pset_fapl_family (fapl, (hsize_t)0, H5P_DEFAULT); - } - if ((fid = H5Fopen(argv[1], H5F_ACC_RDONLY, fapl)) < 0) { + if((fid = H5Fopen(argv[1], H5F_ACC_RDONLY, fapl)) < 0) { fprintf(stderr, "cannot open file\n"); HDexit(1); } - if (NULL == (f = H5I_object(fid))) { + if(NULL == (f = H5I_object(fid))) { fprintf(stderr, "cannot obtain H5F_t pointer\n"); HDexit(2); } @@ -117,46 +115,46 @@ main(int argc, char *argv[]) /* * Parse command arguments. */ - if (argc > 2) + if(argc > 2) addr = HDstrtoll(argv[2], NULL, 0); - if (argc > 3) + if(argc > 3) extra = HDstrtoll(argv[3], NULL, 0); - if (argc > 4) + if(argc > 4) extra2 = HDstrtoll(argv[4], NULL, 0); /* * Read the signature at the specified file position. */ HDfprintf(stdout, "Reading signature at address %a (rel)\n", addr); - if (H5F_block_read(f, H5FD_MEM_SUPER, addr, sizeof(sig), dxpl, sig)<0) { + if(H5F_block_read(f, H5FD_MEM_SUPER, addr, sizeof(sig), dxpl, sig) < 0) { fprintf(stderr, "cannot read signature\n"); HDexit(3); } - if (!HDmemcmp(sig, H5F_SIGNATURE, H5F_SIGNATURE_LEN)) { + if(!HDmemcmp(sig, H5F_SIGNATURE, H5F_SIGNATURE_LEN)) { /* * Debug the file's super block. */ status = H5F_debug(f, H5P_DATASET_XFER_DEFAULT, stdout, 0, VCOL); - } else if (!HDmemcmp(sig, H5HL_MAGIC, H5HL_SIZEOF_MAGIC)) { + } else if(!HDmemcmp(sig, H5HL_MAGIC, H5HL_SIZEOF_MAGIC)) { /* * Debug a local heap. */ status = H5HL_debug(f, H5P_DATASET_XFER_DEFAULT, addr, stdout, 0, VCOL); - } else if (!HDmemcmp (sig, H5HG_MAGIC, H5HG_SIZEOF_MAGIC)) { + } else if(!HDmemcmp (sig, H5HG_MAGIC, H5HG_SIZEOF_MAGIC)) { /* * Debug a global heap collection. */ status = H5HG_debug (f, H5P_DATASET_XFER_DEFAULT, addr, stdout, 0, VCOL); - } else if (!HDmemcmp(sig, H5G_NODE_MAGIC, H5G_NODE_SIZEOF_MAGIC)) { + } else if(!HDmemcmp(sig, H5G_NODE_MAGIC, H5G_NODE_SIZEOF_MAGIC)) { /* * Debug a symbol table node. */ status = H5G_node_debug(f, H5P_DATASET_XFER_DEFAULT, addr, stdout, 0, VCOL, extra); - } else if (!HDmemcmp(sig, H5B_MAGIC, H5B_SIZEOF_MAGIC)) { + } else if(!HDmemcmp(sig, H5B_MAGIC, H5B_SIZEOF_MAGIC)) { /* * Debug a B-tree. B-trees are debugged through the B-tree * subclass. The subclass identifier is the byte immediately @@ -165,7 +163,7 @@ main(int argc, char *argv[]) H5B_subid_t subtype = (H5B_subid_t)sig[H5B_SIZEOF_MAGIC]; unsigned ndims; - switch (subtype) { + switch(subtype) { case H5B_SNODE_ID: status = H5G_node_debug(f, H5P_DATASET_XFER_DEFAULT, addr, stdout, 0, VCOL, extra); break; @@ -180,7 +178,7 @@ main(int argc, char *argv[]) HDexit(4); } - } else if (!HDmemcmp(sig, H5B2_HDR_MAGIC, H5B2_SIZEOF_MAGIC)) { + } else if(!HDmemcmp(sig, H5B2_HDR_MAGIC, H5B2_SIZEOF_MAGIC)) { /* * Debug a v2 B-tree. B-trees are debugged through the B-tree * subclass. The subclass identifier is two bytes after the @@ -188,7 +186,7 @@ main(int argc, char *argv[]) */ H5B2_subid_t subtype = (H5B2_subid_t)sig[H5B2_SIZEOF_MAGIC+1]; - switch (subtype) { + switch(subtype) { case H5B2_TEST_ID: status = H5B2_hdr_debug(f, H5P_DATASET_XFER_DEFAULT, addr, stdout, 0, VCOL, H5B2_TEST); break; @@ -198,7 +196,7 @@ main(int argc, char *argv[]) HDexit(4); } /* end switch */ - } else if (!HDmemcmp(sig, H5B2_INT_MAGIC, H5B2_SIZEOF_MAGIC)) { + } else if(!HDmemcmp(sig, H5B2_INT_MAGIC, H5B2_SIZEOF_MAGIC)) { /* * Debug a v2 B-tree. B-trees are debugged through the B-tree * subclass. The subclass identifier is two bytes after the @@ -206,7 +204,7 @@ main(int argc, char *argv[]) */ H5B2_subid_t subtype = (H5B2_subid_t)sig[H5B2_SIZEOF_MAGIC+1]; - switch (subtype) { + switch(subtype) { case H5B2_TEST_ID: status = H5B2_int_debug(f, H5P_DATASET_XFER_DEFAULT, addr, stdout, 0, VCOL, H5B2_TEST, extra, (unsigned)extra2); break; @@ -216,7 +214,7 @@ main(int argc, char *argv[]) HDexit(4); } /* end switch */ - } else if (!HDmemcmp(sig, H5B2_LEAF_MAGIC, H5B2_SIZEOF_MAGIC)) { + } else if(!HDmemcmp(sig, H5B2_LEAF_MAGIC, H5B2_SIZEOF_MAGIC)) { /* * Debug a v2 B-tree. B-trees are debugged through the B-tree * subclass. The subclass identifier is two bytes after the @@ -224,7 +222,7 @@ main(int argc, char *argv[]) */ H5B2_subid_t subtype = (H5B2_subid_t)sig[H5B2_SIZEOF_MAGIC+1]; - switch (subtype) { + switch(subtype) { case H5B2_TEST_ID: status = H5B2_leaf_debug(f, H5P_DATASET_XFER_DEFAULT, addr, stdout, 0, VCOL, H5B2_TEST, extra, (unsigned)extra2); break; @@ -234,13 +232,19 @@ main(int argc, char *argv[]) HDexit(4); } /* end switch */ - } else if (!HDmemcmp(sig, H5HF_HDR_MAGIC, H5HF_SIZEOF_MAGIC)) { + } else if(!HDmemcmp(sig, H5HF_HDR_MAGIC, H5HF_SIZEOF_MAGIC)) { /* * Debug a fractal heap header. */ status = H5HF_hdr_debug(f, H5P_DATASET_XFER_DEFAULT, addr, stdout, 0, VCOL); - } else if (sig[0] == H5O_VERSION) { + } else if(!HDmemcmp(sig, H5HF_DBLOCK_MAGIC, H5HF_SIZEOF_MAGIC)) { + /* + * Debug a fractal heap direct block. + */ + status = H5HF_dblock_debug(f, H5P_DATASET_XFER_DEFAULT, addr, stdout, 0, VCOL, extra, (size_t)extra2); + + } else if(sig[0] == H5O_VERSION) { /* * This could be an object header. Since they don't have a signature * it's a somewhat "ify" detection. @@ -252,15 +256,14 @@ main(int argc, char *argv[]) * Got some other unrecognized signature. */ printf("%-*s ", VCOL, "Signature:"); - for (i = 0; i < sizeof(sig); i++) { - if (sig[i] > ' ' && sig[i] <= '~' && '\\' != sig[i]) { - HDputchar(sig[i]); - } else if ('\\' == sig[i]) { + for (u = 0; u < sizeof(sig); u++) { + if (sig[u] > ' ' && sig[u] <= '~' && '\\' != sig[u]) + HDputchar(sig[u]); + else if ('\\' == sig[u]) { HDputchar('\\'); HDputchar('\\'); - } else { - printf("\\%03o", sig[i]); - } + } else + printf("\\%03o", sig[u]); } HDputchar('\n'); @@ -268,11 +271,12 @@ main(int argc, char *argv[]) HDexit(4); } - if (status < 0) { + if(status < 0) { fprintf(stderr, "An error occurred!\n"); H5Eprint(stderr); HDexit(5); } + H5Pclose(dxpl); H5Pclose(fapl); H5Fclose(fid); |