diff options
Diffstat (limited to 'src')
-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/H5EA.c | 145 | ||||
-rw-r--r-- | src/H5EAcache.c | 538 | ||||
-rw-r--r-- | src/H5EAdbg.c | 134 | ||||
-rw-r--r-- | src/H5EAdblock.c | 419 | ||||
-rw-r--r-- | src/H5EAhdr.c | 275 | ||||
-rw-r--r-- | src/H5EAiblock.c | 179 | ||||
-rw-r--r-- | src/H5EApkg.h | 106 | ||||
-rw-r--r-- | src/H5EAprivate.h | 2 | ||||
-rw-r--r-- | src/H5EAstat.c | 6 | ||||
-rw-r--r-- | src/H5FDpublic.h | 4 | ||||
-rw-r--r-- | src/H5private.h | 6 | ||||
-rwxr-xr-x | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/Makefile.in | 5 |
16 files changed, 1663 insertions, 164 deletions
@@ -493,6 +493,7 @@ static const char * H5AC_entry_type_names[H5AC_NTYPES] = "shared OH message index", "extensible array headers", "extensible array index blocks", + "extensible array data blocks", "test entry" /* for testing only -- not used for actual files */ }; diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h index 9568a79..ea97e17 100644 --- a/src/H5ACprivate.h +++ b/src/H5ACprivate.h @@ -64,6 +64,7 @@ typedef enum { H5AC_SOHM_LIST_ID, /*shared message index stored as a list */ H5AC_EARRAY_HDR_ID, /*extensible array header */ H5AC_EARRAY_IBLOCK_ID, /*extensible array index block */ + H5AC_EARRAY_DBLOCK_ID, /*extensible array index block */ H5AC_TEST_ID, /*test entry -- not used for actual files */ H5AC_NTYPES /* Number of types, must be last */ } H5AC_type_t; diff --git a/src/H5Cpkg.h b/src/H5Cpkg.h index cf3f86b..46181ea 100644 --- a/src/H5Cpkg.h +++ b/src/H5Cpkg.h @@ -802,7 +802,7 @@ ****************************************************************************/ #define H5C__H5C_T_MAGIC 0x005CAC0E -#define H5C__MAX_NUM_TYPE_IDS 18 +#define H5C__MAX_NUM_TYPE_IDS 19 #define H5C__PREFIX_LEN 32 struct H5C_t @@ -47,6 +47,7 @@ #include "H5private.h" /* Generic Functions */ #include "H5Eprivate.h" /* Error handling */ #include "H5EApkg.h" /* Extensible Arrays */ +#include "H5FLprivate.h" /* Free Lists */ /****************/ @@ -263,7 +264,7 @@ HDfprintf(stderr, "%s: Called\n", FUNC); HDassert(nelmts); /* Retrieve the max. index set */ - *nelmts = ea->hdr->max_idx_set; + *nelmts = ea->hdr->stats.max_idx_set; END_FUNC(PRIV) /* end H5EA_get_nelmts() */ @@ -324,6 +325,9 @@ H5EA_set(const H5EA_t *ea, hid_t dxpl_id, hsize_t idx, const void *elmt)) /* Local variables */ H5EA_hdr_t *hdr = ea->hdr; /* Header for EA */ H5EA_iblock_t *iblock = NULL; /* Pointer to index block for EA */ + H5EA_dblock_t *dblock = NULL; /* Pointer to data block for EA */ + unsigned iblock_cache_flags = H5AC__NO_FLAGS_SET; /* Flags to unprotecting index block */ + unsigned dblock_cache_flags = H5AC__NO_FLAGS_SET; /* Flags to unprotecting data block */ hbool_t hdr_dirty = FALSE; /* Whether header information changed */ #ifdef QAK @@ -350,6 +354,9 @@ HDfprintf(stderr, "%s: Index block address not defined!\n", FUNC, idx); if(!H5F_addr_defined(hdr->idx_blk_addr)) H5E_THROW(H5E_CANTCREATE, "unable to create index block") + /* Increment count of elements "realized" */ + hdr->stats.nelmts += hdr->idx_blk_elmts; + /* Mark the header dirty */ hdr_dirty = TRUE; } /* end if */ @@ -361,19 +368,81 @@ HDfprintf(stderr, "%s: Index block address is: %a\n", FUNC, hdr->idx_blk_addr); if(NULL == (iblock = H5EA__iblock_protect(hdr, dxpl_id, H5AC_WRITE))) H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array index block, address = %llu", (unsigned long_long)hdr->idx_blk_addr) - /* Determine where the element to set falls */ + /* Check if element is in index block */ if(idx < hdr->idx_blk_elmts) { /* Set element in index block */ HDmemcpy(((uint8_t *)iblock->elmts) + (hdr->cls->nat_elmt_size * idx), elmt, hdr->cls->nat_elmt_size); + iblock_cache_flags |= H5AC__DIRTIED_FLAG; } /* end if */ else { -HDfprintf(stderr, "%s: Index %Hu not supported yet!\n", FUNC, idx); -HDassert(0 && "Index location not supported!"); + unsigned sblk_idx; /* Which superblock does this index fall in? */ + hsize_t elmt_idx; /* Offset of element in super block */ + + /* Get super block index where element is located */ + sblk_idx = H5EA__dblock_sblk_idx(hdr, idx); + + /* Adjust index to offset in super block */ + elmt_idx = idx - hdr->idx_blk_elmts + hdr->sblk_info[sblk_idx].start_idx; +#ifdef QAK +HDfprintf(stderr, "%s: after adjusting for super block elements, elmt_idx = %Hu\n", FUNC, elmt_idx); +#endif /* QAK */ + + /* Check for data block containing element address in the index block */ + if(sblk_idx < iblock->nsblks) { + size_t dblk_idx; /* Data block index */ + +#ifdef QAK +HDfprintf(stderr, "%s: Element in data block pointed to by address in index block\n", FUNC); +#endif /* QAK */ + /* Compute the data block index in index block */ + dblk_idx = (size_t)(hdr->sblk_info[sblk_idx].start_dblk + (elmt_idx / hdr->sblk_info[sblk_idx].dblk_nelmts)); +#ifdef QAK +HDfprintf(stderr, "%s: dblk_idx = %u\n", FUNC, dblk_idx); +#endif /* QAK */ + HDassert(dblk_idx < iblock->ndblk_addrs); + + /* Check if the data block has been allocated on disk yet */ + if(!H5F_addr_defined(iblock->dblk_addrs[dblk_idx])) { + haddr_t dblk_addr; /* Address of data block created */ + + /* Create data block */ + dblk_addr = H5EA__dblock_create(iblock, dxpl_id, hdr->sblk_info[sblk_idx].dblk_nelmts); + if(!H5F_addr_defined(dblk_addr)) + H5E_THROW(H5E_CANTCREATE, "unable to create extensible array data block") + + /* Set data block address in index block */ + iblock->dblk_addrs[dblk_idx] = dblk_addr; + iblock_cache_flags |= H5AC__DIRTIED_FLAG; + + /* Increment count of elements "realized" and actual data blocks created */ + hdr->stats.ndata_blks++; + hdr->stats.nelmts += hdr->sblk_info[sblk_idx].dblk_nelmts; + hdr_dirty = TRUE; + } /* end if */ + + /* Protect data block */ + if(NULL == (dblock = H5EA__dblock_protect(hdr, dxpl_id, iblock->dblk_addrs[dblk_idx], hdr->sblk_info[sblk_idx].dblk_nelmts, H5AC_WRITE))) + H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array data block, address = %llu", (unsigned long_long)iblock->dblk_addrs[dblk_idx]) + + /* Adjust index to offset in data block */ + elmt_idx %= hdr->sblk_info[sblk_idx].dblk_nelmts; + + /* Set element in data block */ + HDmemcpy(((uint8_t *)dblock->elmts) + (hdr->cls->nat_elmt_size * elmt_idx), elmt, hdr->cls->nat_elmt_size); + dblock_cache_flags |= H5AC__DIRTIED_FLAG; + } /* end if */ + else { +HDfprintf(stderr, "%s: Super block index %Hu not supported yet!\n", FUNC, sblk_idx); +HDassert(0 && "Super block index location not supported!"); + } /* end else */ } /* end else */ /* Update max. element set in array, if appropriate */ - if(idx >= hdr->max_idx_set) { - hdr->max_idx_set = idx + 1; +#ifdef QAK +HDfprintf(stderr, "%s: idx = %Hu, hdr->stats.max_idx_set = %Hu\n", FUNC, idx, hdr->stats.max_idx_set); +#endif /* QAK */ + if(idx >= hdr->stats.max_idx_set) { + hdr->stats.max_idx_set = idx + 1; hdr_dirty = TRUE; } /* end if */ @@ -383,8 +452,11 @@ CATCH if(H5EA__hdr_modified(hdr) < 0) H5E_THROW(H5E_CANTMARKDIRTY, "unable to mark extensible array header as modified") - if(iblock && H5EA__iblock_unprotect(iblock, dxpl_id, H5AC__DIRTIED_FLAG) < 0) + /* Release resources */ + if(iblock && H5EA__iblock_unprotect(iblock, dxpl_id, iblock_cache_flags) < 0) H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array index block") + if(dblock && H5EA__dblock_unprotect(dblock, dxpl_id, dblock_cache_flags) < 0) + H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array data block") END_FUNC(PRIV) /* end H5EA_set() */ @@ -409,6 +481,7 @@ H5EA_get(const H5EA_t *ea, hid_t dxpl_id, hsize_t idx, void *elmt)) /* Local variables */ H5EA_hdr_t *hdr = ea->hdr; /* Header for EA */ H5EA_iblock_t *iblock = NULL; /* Pointer to index block for EA */ + H5EA_dblock_t *dblock = NULL; /* Pointer to data block for EA */ #ifdef QAK HDfprintf(stderr, "%s: Called\n", FUNC); @@ -425,9 +498,9 @@ HDfprintf(stderr, "%s: Index %Hu\n", FUNC, idx); hdr->f = ea->f; /* Check for element beyond max. element in array */ - if(idx >= hdr->max_idx_set) { + if(idx >= hdr->stats.max_idx_set) { #ifdef QAK -HDfprintf(stderr, "%s: Element beyond max. index set\n", FUNC, idx); +HDfprintf(stderr, "%s: Element beyond max. index set, hdr->stats.max_idx_set = %Hu, idx = %Hu\n", FUNC, hdr->stats.max_idx_set, idx); #endif /* QAK */ /* Call the class's 'fill' callback */ if((hdr->cls->fill)(elmt, (size_t)1) < 0) @@ -442,20 +515,68 @@ HDfprintf(stderr, "%s: Index block address is: %a\n", FUNC, hdr->idx_blk_addr); if(NULL == (iblock = H5EA__iblock_protect(hdr, dxpl_id, H5AC_READ))) H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array index block, address = %llu", (unsigned long_long)hdr->idx_blk_addr) - /* Determine where the element to set falls */ + /* Check if element is in index block */ if(idx < hdr->idx_blk_elmts) { /* Get element from index block */ HDmemcpy(elmt, ((uint8_t *)iblock->elmts) + (hdr->cls->nat_elmt_size * idx), hdr->cls->nat_elmt_size); } /* end if */ else { -HDfprintf(stderr, "%s: Index %Hu not supported yet!\n", FUNC, idx); -HDassert(0 && "Index location not supported!"); + unsigned sblk_idx; /* Which superblock does this index fall in? */ + hsize_t elmt_idx; /* Offset of element in super block */ + + /* Get super block index where element is located */ + sblk_idx = H5EA__dblock_sblk_idx(hdr, idx); + + /* Adjust index to offset in super block */ + elmt_idx = idx - hdr->idx_blk_elmts + hdr->sblk_info[sblk_idx].start_idx; +#ifdef QAK +HDfprintf(stderr, "%s: after adjusting for super block elements, elmt_idx = %Hu\n", FUNC, elmt_idx); +#endif /* QAK */ + + /* Check for data block containing element address in the index block */ + if(sblk_idx < iblock->nsblks) { + size_t dblk_idx; /* Data block index */ + +#ifdef QAK +HDfprintf(stderr, "%s: Element in data block pointed to by address in index block\n", FUNC); +#endif /* QAK */ + /* Compute the data block index in index block */ + dblk_idx = (size_t)(hdr->sblk_info[sblk_idx].start_dblk + (elmt_idx / hdr->sblk_info[sblk_idx].dblk_nelmts)); +#ifdef QAK +HDfprintf(stderr, "%s: dblk_idx = %u\n", FUNC, dblk_idx); +#endif /* QAK */ + HDassert(dblk_idx < iblock->ndblk_addrs); + + /* Check if the data block has been allocated on disk yet */ + if(!H5F_addr_defined(iblock->dblk_addrs[dblk_idx])) { + /* Call the class's 'fill' callback */ + if((hdr->cls->fill)(elmt, (size_t)1) < 0) + H5E_THROW(H5E_CANTSET, "can't set element to class's fill value") + } /* end if */ + else { + /* Protect data block */ + if(NULL == (dblock = H5EA__dblock_protect(hdr, dxpl_id, iblock->dblk_addrs[dblk_idx], hdr->sblk_info[sblk_idx].dblk_nelmts, H5AC_READ))) + H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array data block, address = %llu", (unsigned long_long)iblock->dblk_addrs[dblk_idx]) + + /* Adjust index to offset in data block */ + elmt_idx %= hdr->sblk_info[sblk_idx].dblk_nelmts; + + /* Retrieve element from data block */ + HDmemcpy(elmt, ((uint8_t *)dblock->elmts) + (hdr->cls->nat_elmt_size * elmt_idx), hdr->cls->nat_elmt_size); + } /* end else */ + } /* end if */ + else { +HDfprintf(stderr, "%s: Super block index %Hu not supported yet!\n", FUNC, sblk_idx); +HDassert(0 && "Super block index location not supported!"); + } /* end else */ } /* end else */ } /* end else */ CATCH if(iblock && H5EA__iblock_unprotect(iblock, dxpl_id, H5AC__NO_FLAGS_SET) < 0) H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array index block") + if(dblock && H5EA__dblock_unprotect(dblock, dxpl_id, H5AC__NO_FLAGS_SET) < 0) + H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array data block") END_FUNC(PRIV) /* end H5EA_set() */ diff --git a/src/H5EAcache.c b/src/H5EAcache.c index 3a8bba5..d7d57c3 100644 --- a/src/H5EAcache.c +++ b/src/H5EAcache.c @@ -43,6 +43,7 @@ #include "H5Eprivate.h" /* Error handling */ #include "H5EApkg.h" /* Extensible Arrays */ #include "H5MFprivate.h" /* File memory management */ +#include "H5Vprivate.h" /* Vectors and arrays */ #include "H5WBprivate.h" /* Wrapped Buffers */ @@ -53,10 +54,12 @@ /* Fractal heap format version #'s */ #define H5EA_HDR_VERSION 0 /* Header */ #define H5EA_IBLOCK_VERSION 0 /* Index block */ +#define H5EA_DBLOCK_VERSION 0 /* Data block */ /* Size of stack buffer for serialization buffers */ #define H5EA_HDR_BUF_SIZE 512 #define H5EA_IBLOCK_BUF_SIZE 512 +#define H5EA_DBLOCK_BUF_SIZE 512 /******************/ @@ -75,13 +78,20 @@ /* Metadata cache (H5AC) callbacks */ static H5EA_hdr_t *H5EA__cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata, void *udata2); -static herr_t H5EA__cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5EA_hdr_t *hdr, unsigned UNUSED * flags_ptr); +static herr_t H5EA__cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5EA_hdr_t *hdr, unsigned * flags_ptr); static herr_t H5EA__cache_hdr_clear(H5F_t *f, H5EA_hdr_t *hdr, hbool_t destroy); static herr_t H5EA__cache_hdr_size(const H5F_t *f, const H5EA_hdr_t *hdr, size_t *size_ptr); +static herr_t H5EA__cache_hdr_dest(H5F_t *f, H5EA_hdr_t *hdr); static H5EA_iblock_t *H5EA__cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata, void *udata2); -static herr_t H5EA__cache_iblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5EA_iblock_t *iblock, unsigned UNUSED * flags_ptr); +static herr_t H5EA__cache_iblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5EA_iblock_t *iblock, unsigned * flags_ptr); static herr_t H5EA__cache_iblock_clear(H5F_t *f, H5EA_iblock_t *iblock, hbool_t destroy); static herr_t H5EA__cache_iblock_size(const H5F_t *f, const H5EA_iblock_t *iblock, size_t *size_ptr); +static herr_t H5EA__cache_iblock_dest(H5F_t *f, H5EA_iblock_t *iblock); +static H5EA_dblock_t *H5EA__cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata, void *udata2); +static herr_t H5EA__cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5EA_dblock_t *dblock, unsigned * flags_ptr); +static herr_t H5EA__cache_dblock_clear(H5F_t *f, H5EA_dblock_t *dblock, hbool_t destroy); +static herr_t H5EA__cache_dblock_size(const H5F_t *f, const H5EA_dblock_t *dblock, size_t *size_ptr); +static herr_t H5EA__cache_dblock_dest(H5F_t *f, H5EA_dblock_t *dblock); /*********************/ @@ -108,6 +118,16 @@ const H5AC_class_t H5AC_EARRAY_IBLOCK[1] = {{ (H5AC_size_func_t)H5EA__cache_iblock_size, }}; +/* H5EA data block inherits cache-like properties from H5AC */ +const H5AC_class_t H5AC_EARRAY_DBLOCK[1] = {{ + H5AC_EARRAY_DBLOCK_ID, + (H5AC_load_func_t)H5EA__cache_dblock_load, + (H5AC_flush_func_t)H5EA__cache_dblock_flush, + (H5AC_dest_func_t)H5EA__cache_dblock_dest, + (H5AC_clear_func_t)H5EA__cache_dblock_clear, + (H5AC_size_func_t)H5EA__cache_dblock_size, +}}; + /*****************************/ /* Library Private Variables */ @@ -136,7 +156,8 @@ const H5AC_class_t H5AC_EARRAY_IBLOCK[1] = {{ */ BEGIN_FUNC(STATIC, ERR, H5EA_hdr_t *, NULL, NULL, -H5EA__cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_cls, void UNUSED *udata2)) +H5EA__cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_cls, + void UNUSED *udata2)) /* Local variables */ const H5EA_class_t *cls = (const H5EA_class_t *)_cls; /* Extensible array class */ @@ -200,15 +221,15 @@ H5EA__cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_cls, vo /* Internal information */ H5F_addr_decode(f, &p, &hdr->idx_blk_addr); /* Address of index block */ - H5F_DECODE_LENGTH(f, p, hdr->max_idx_set); /* Max. index set (+1) */ + H5F_DECODE_LENGTH(f, p, hdr->stats.max_idx_set); /* Max. index set (+1) */ + H5F_DECODE_LENGTH(f, p, hdr->stats.nsuper_blks); /* Number of super blocks created */ + H5F_DECODE_LENGTH(f, p, hdr->stats.ndata_blks); /* Number of data blocks created */ + H5F_DECODE_LENGTH(f, p, hdr->stats.nelmts); /* Number of elements 'realized' */ /* Sanity check */ /* (allow for checksum not decoded yet) */ HDassert((size_t)(p - buf) == (size - H5EA_SIZEOF_CHKSUM)); - /* Set the array header's size */ - hdr->size = size; - /* Compute checksum on entire header */ /* (including the filter information, if present) */ computed_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0); @@ -217,12 +238,17 @@ H5EA__cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_cls, vo UINT32DECODE(p, stored_chksum); /* Sanity check */ - HDassert((size_t)(p - buf) == hdr->size); + HDassert((size_t)(p - buf) == size); /* Verify checksum */ if(stored_chksum != computed_chksum) H5E_THROW(H5E_BADVALUE, "incorrect metadata checksum for extensible array header") + /* Finish initializing extensible array header */ + if(H5EA__hdr_init(hdr) < 0) + H5E_THROW(H5E_CANTINIT, "initialization failed for extensible array header") + HDassert(hdr->size == size); + /* Set return value */ ret_value = hdr; @@ -253,7 +279,8 @@ END_FUNC(STATIC) /* end H5EA__cache_hdr_load() */ */ BEGIN_FUNC(STATIC, ERR, herr_t, SUCCEED, FAIL, -H5EA__cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5EA_hdr_t *hdr, unsigned UNUSED * flags_ptr)) +H5EA__cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, + H5EA_hdr_t *hdr, unsigned UNUSED * flags_ptr)) H5WB_t *wb = NULL; /* Wrapped buffer for header data */ uint8_t hdr_buf[H5EA_HDR_BUF_SIZE]; /* Buffer for header */ @@ -302,7 +329,10 @@ H5EA__cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5 /* Internal information */ H5F_addr_encode(f, &p, hdr->idx_blk_addr); /* Address of index block */ - H5F_ENCODE_LENGTH(f, p, hdr->max_idx_set); /* Max. index set (+1) */ + H5F_ENCODE_LENGTH(f, p, hdr->stats.max_idx_set); /* Max. index set (+1) */ + H5F_ENCODE_LENGTH(f, p, hdr->stats.nsuper_blks); /* Number of super blocks created */ + H5F_ENCODE_LENGTH(f, p, hdr->stats.ndata_blks); /* Number of data blocks created */ + H5F_ENCODE_LENGTH(f, p, hdr->stats.nelmts); /* Number of elements 'realized' */ /* Compute metadata checksum */ metadata_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0); @@ -332,36 +362,6 @@ END_FUNC(STATIC) /* end H5EA__cache_hdr_flush() */ /*------------------------------------------------------------------------- - * Function: H5EA__cache_hdr_dest - * - * Purpose: Destroys a extensible array header in memory. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@hdfgroup.org - * Aug 26 2008 - * - *------------------------------------------------------------------------- - */ -/* ARGSUSED */ -BEGIN_FUNC(PKG, NOERR, -herr_t, SUCCEED, -, -H5EA__cache_hdr_dest(H5F_t UNUSED *f, H5EA_hdr_t *hdr)) - - /* - * Check arguments. - */ - HDassert(hdr); - HDassert(hdr->rc == 0); - - /* Free the shared info itself */ - (void)H5FL_FREE(H5EA_hdr_t, hdr); - -END_FUNC(PKG) /* end H5EA__cache_hdr_dest() */ - - -/*------------------------------------------------------------------------- * Function: H5EA__cache_hdr_clear * * Purpose: Mark a extensible array header in memory as non-dirty. @@ -378,9 +378,7 @@ BEGIN_FUNC(STATIC, ERR, herr_t, SUCCEED, FAIL, H5EA__cache_hdr_clear(H5F_t *f, H5EA_hdr_t *hdr, hbool_t destroy)) - /* - * Check arguments. - */ + /* Sanity check */ HDassert(hdr); /* Reset the dirty flag. */ @@ -413,9 +411,10 @@ END_FUNC(STATIC) /* end H5EA__cache_hdr_clear() */ /* ARGSUSED */ BEGIN_FUNC(STATIC, NOERR, herr_t, SUCCEED, -, -H5EA__cache_hdr_size(const H5F_t UNUSED *f, const H5EA_hdr_t *hdr, size_t *size_ptr)) +H5EA__cache_hdr_size(const H5F_t UNUSED *f, const H5EA_hdr_t *hdr, + size_t *size_ptr)) - /* check arguments */ + /* Sanity check */ HDassert(f); HDassert(hdr); HDassert(size_ptr); @@ -427,6 +426,36 @@ END_FUNC(STATIC) /* end H5EA__cache_hdr_size() */ /*------------------------------------------------------------------------- + * Function: H5EA__cache_hdr_dest + * + * Purpose: Destroys an extensible array header in memory. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Aug 26 2008 + * + *------------------------------------------------------------------------- + */ +/* ARGSUSED */ +BEGIN_FUNC(STATIC, ERR, +herr_t, SUCCEED, FAIL, +H5EA__cache_hdr_dest(H5F_t UNUSED *f, H5EA_hdr_t *hdr)) + + /* Check arguments */ + HDassert(hdr); + + /* Release the extensible array header */ + if(H5EA__hdr_dest(hdr) < 0) + H5E_THROW(H5E_CANTFREE, "can't free extensible array header") + +CATCH + +END_FUNC(STATIC) /* end H5EA__cache_hdr_dest() */ + + +/*------------------------------------------------------------------------- * Function: H5EA__cache_iblock_load * * Purpose: Loads an extensible array index block from the disk. @@ -442,7 +471,8 @@ END_FUNC(STATIC) /* end H5EA__cache_hdr_size() */ */ BEGIN_FUNC(STATIC, ERR, H5EA_iblock_t *, NULL, NULL, -H5EA__cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *udata1, void *_hdr)) +H5EA__cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, + const void UNUSED *udata1, void *_hdr)) /* Local variables */ H5EA_hdr_t *hdr = (H5EA_hdr_t *)_hdr; /* Shared extensible array information */ @@ -462,12 +492,7 @@ H5EA__cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED /* Allocate the extensible array index block */ if(NULL == (iblock = H5EA__iblock_alloc(hdr))) - H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array shared header") - - /* Share common array information */ - iblock->hdr = hdr; - if(H5EA__hdr_incr(hdr) < 0) - H5E_THROW(H5E_CANTINC, "can't increment reference count on shared array header") + H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array index block") /* Set the extensible array index block's address */ iblock->addr = addr; @@ -477,7 +502,7 @@ H5EA__cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED H5E_THROW(H5E_CANTINIT, "can't wrap buffer") /* Compute the size of the extensible array index block on disk */ - size = H5EA_IBLOCK_SIZE(hdr); + size = H5EA_IBLOCK_SIZE(iblock); /* Get a pointer to a buffer that's large enough for serialized info */ if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size))) @@ -513,6 +538,24 @@ H5EA__cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED p += (hdr->idx_blk_elmts * hdr->raw_elmt_size); } /* end if */ + /* Decode data block addresses in index block */ + if(iblock->ndblk_addrs > 0) { + size_t u; /* Local index variable */ + + /* Decode addresses of data blocks in index block */ + for(u = 0; u < iblock->ndblk_addrs; u++) + H5F_addr_decode(f, &p, &iblock->dblk_addrs[u]); + } /* end if */ + + /* Decode super block addresses in index block */ + if(iblock->nsblk_addrs > 0) { + size_t u; /* Local index variable */ + + /* Decode addresses of super blocks in index block */ + for(u = 0; u < iblock->nsblk_addrs; u++) + H5F_addr_decode(f, &p, &iblock->sblk_addrs[u]); + } /* end if */ + /* Sanity check */ /* (allow for checksum not decoded yet) */ HDassert((size_t)(p - buf) == (size - H5EA_SIZEOF_CHKSUM)); @@ -563,11 +606,12 @@ END_FUNC(STATIC) /* end H5EA__cache_iblock_load() */ */ BEGIN_FUNC(STATIC, ERR, herr_t, SUCCEED, FAIL, -H5EA__cache_iblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5EA_iblock_t *iblock, unsigned UNUSED * flags_ptr)) +H5EA__cache_iblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, + H5EA_iblock_t *iblock, unsigned UNUSED * flags_ptr)) /* Local variables */ H5WB_t *wb = NULL; /* Wrapped buffer for serializing data */ - uint8_t ser_buf[H5EA_HDR_BUF_SIZE]; /* Serialization buffer */ + uint8_t ser_buf[H5EA_IBLOCK_BUF_SIZE]; /* Serialization buffer */ /* Sanity check */ HDassert(f); @@ -615,6 +659,24 @@ H5EA__cache_iblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, p += (iblock->hdr->idx_blk_elmts * iblock->hdr->raw_elmt_size); } /* end if */ + /* Encode data block addresses in index block */ + if(iblock->ndblk_addrs > 0) { + size_t u; /* Local index variable */ + + /* Encode addresses of data blocks in index block */ + for(u = 0; u < iblock->ndblk_addrs; u++) + H5F_addr_encode(f, &p, iblock->dblk_addrs[u]); + } /* end if */ + + /* Encode data block addresses in index block */ + if(iblock->nsblk_addrs > 0) { + size_t u; /* Local index variable */ + + /* Encode addresses of super blocks in index block */ + for(u = 0; u < iblock->nsblk_addrs; u++) + H5F_addr_encode(f, &p, iblock->sblk_addrs[u]); + } /* end if */ + /* Compute metadata checksum */ metadata_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0); @@ -643,9 +705,73 @@ END_FUNC(STATIC) /* end H5EA__cache_iblock_flush() */ /*------------------------------------------------------------------------- + * Function: H5EA__cache_iblock_clear + * + * Purpose: Mark a extensible array index block in memory as non-dirty. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sept 9 2008 + * + *------------------------------------------------------------------------- + */ +BEGIN_FUNC(STATIC, ERR, +herr_t, SUCCEED, FAIL, +H5EA__cache_iblock_clear(H5F_t *f, H5EA_iblock_t *iblock, hbool_t destroy)) + + /* Sanity check */ + HDassert(iblock); + + /* Reset the dirty flag */ + iblock->cache_info.is_dirty = FALSE; + + if(destroy) + if(H5EA__cache_iblock_dest(f, iblock) < 0) + H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array index block") + +CATCH + +END_FUNC(STATIC) /* end H5EA__cache_iblock_clear() */ + + +/*------------------------------------------------------------------------- + * Function: H5EA__cache_iblock_size + * + * Purpose: Compute the size in bytes of a extensible array index 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@hdfgroup.org + * Sept 9 2008 + * + *------------------------------------------------------------------------- + */ +/* ARGSUSED */ +BEGIN_FUNC(STATIC, NOERR, +herr_t, SUCCEED, -, +H5EA__cache_iblock_size(const H5F_t UNUSED *f, const H5EA_iblock_t *iblock, + size_t *size_ptr)) + + /* Sanity check */ + HDassert(f); + HDassert(iblock); + HDassert(size_ptr); + + /* Set size value */ + *size_ptr = iblock->size; + +END_FUNC(STATIC) /* end H5EA__cache_iblock_size() */ + + +/*------------------------------------------------------------------------- * Function: H5EA__cache_iblock_dest * - * Purpose: Destroys a extensible array index block in memory. + * Purpose: Destroys an extensible array index block in memory. * * Return: Non-negative on success/Negative on failure * @@ -655,75 +781,270 @@ END_FUNC(STATIC) /* end H5EA__cache_iblock_flush() */ * *------------------------------------------------------------------------- */ -/* ARGSUSED */ -BEGIN_FUNC(PKG, ERR, +BEGIN_FUNC(STATIC, ERR, herr_t, SUCCEED, FAIL, -H5EA__cache_iblock_dest(H5F_t UNUSED *f, H5EA_iblock_t *iblock)) +H5EA__cache_iblock_dest(H5F_t *f, H5EA_iblock_t *iblock)) /* Sanity check */ HDassert(iblock); - HDassert(iblock->rc == 0); - /* Set the shared array header's file context for this operation */ - iblock->hdr->f = f; + /* Release the index block */ + if(H5EA__iblock_dest(f, iblock) < 0) + H5E_THROW(H5E_CANTFREE, "can't free extensible array index block") - /* Check if we've got elements in the index block */ - if(iblock->hdr->idx_blk_elmts > 0) { - /* Free buffer for index block elements */ - HDassert(iblock->elmts); - (void)H5FL_BLK_FREE(elmt_buf, iblock->elmts); - } /* end if */ +CATCH + +END_FUNC(STATIC) /* end H5EA__cache_iblock_dest() */ + + +/*------------------------------------------------------------------------- + * Function: H5EA__cache_dblock_load + * + * Purpose: Loads an extensible array data block from the disk. + * + * Return: Success: Pointer to a new extensible array data block + * Failure: NULL + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 16 2008 + * + *------------------------------------------------------------------------- + */ +BEGIN_FUNC(STATIC, ERR, +H5EA_dblock_t *, NULL, NULL, +H5EA__cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, + const void *_nelmts, void *_hdr)) - /* Decrement reference count on shared info */ - if(H5EA__hdr_decr(iblock->hdr) < 0) - H5E_THROW(H5E_CANTDEC, "can't decrement reference count on shared array header") + /* Local variables */ + H5EA_hdr_t *hdr = (H5EA_hdr_t *)_hdr; /* Shared extensible array information */ + const size_t *nelmts = (const size_t *)_nelmts; /* Number of elements in data block */ + H5EA_dblock_t *dblock = NULL; /* Data block info */ + size_t size; /* Data block size */ + H5WB_t *wb = NULL; /* Wrapped buffer for data block data */ + uint8_t dblock_buf[H5EA_DBLOCK_BUF_SIZE]; /* Buffer for data block */ + uint8_t *buf; /* Pointer to data block buffer */ + const uint8_t *p; /* Pointer into raw data buffer */ + uint32_t stored_chksum; /* Stored metadata checksum value */ + uint32_t computed_chksum; /* Computed metadata checksum value */ - /* Free the index block itself */ - (void)H5FL_FREE(H5EA_iblock_t, iblock); + /* Sanity check */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(nelmts && *nelmts > 0); + HDassert(hdr); + + /* Allocate the extensible array data block */ + if(NULL == (dblock = H5EA__dblock_alloc(hdr, *nelmts))) + H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array data block") + + /* Set the extensible array data block's information */ + dblock->addr = addr; + + /* Wrap the local buffer for serialized info */ + if(NULL == (wb = H5WB_wrap(dblock_buf, sizeof(dblock_buf)))) + H5E_THROW(H5E_CANTINIT, "can't wrap buffer") + + /* Compute the size of the extensible array data block on disk */ + size = H5EA_DBLOCK_SIZE(dblock); + + /* Get a pointer to a buffer that's large enough for serialized info */ + if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size))) + H5E_THROW(H5E_CANTGET, "can't get actual buffer") + + /* Read data block from disk */ + if(H5F_block_read(f, H5FD_MEM_EARRAY_DBLOCK, addr, size, dxpl_id, buf) < 0) + H5E_THROW(H5E_READERROR, "can't read extensible array data block") + + /* Get temporary pointer to serialized header */ + p = buf; + + /* Magic number */ + if(HDmemcmp(p, H5EA_DBLOCK_MAGIC, (size_t)H5EA_SIZEOF_MAGIC)) + H5E_THROW(H5E_BADVALUE, "wrong extensible array data block signature") + p += H5EA_SIZEOF_MAGIC; + + /* Version */ + if(*p++ != H5EA_DBLOCK_VERSION) + H5E_THROW(H5E_VERSION, "wrong extensible array data block version") + + /* Extensible array type */ + if(*p++ != (uint8_t)hdr->cls->id) + H5E_THROW(H5E_BADTYPE, "incorrect extensible array class") + + /* Internal information */ + + /* Decode elements in data block */ + /* Convert from raw elements on disk into native elements in memory */ + if((hdr->cls->decode)(p, dblock->elmts, *nelmts) < 0) + H5E_THROW(H5E_CANTDECODE, "can't decode extensible array data elements") + p += (*nelmts * hdr->raw_elmt_size); + + /* Sanity check */ + /* (allow for checksum not decoded yet) */ + HDassert((size_t)(p - buf) == (size - H5EA_SIZEOF_CHKSUM)); + + /* Save the data block's size */ + dblock->size = size; + + /* Compute checksum on data block */ + computed_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0); + + /* Metadata checksum */ + UINT32DECODE(p, stored_chksum); + + /* Sanity check */ + HDassert((size_t)(p - buf) == dblock->size); + + /* Verify checksum */ + if(stored_chksum != computed_chksum) + H5E_THROW(H5E_BADVALUE, "incorrect metadata checksum for extensible array data block") + + /* Set return value */ + ret_value = dblock; CATCH -END_FUNC(PKG) /* end H5EA__cache_iblock_dest() */ + /* Release resources */ + if(wb && H5WB_unwrap(wb) < 0) + H5E_THROW(H5E_CLOSEERROR, "can't close wrapped buffer") + if(!ret_value) + if(dblock && H5EA__cache_dblock_dest(f, dblock) < 0) + H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array data block") + +END_FUNC(STATIC) /* end H5EA__cache_dblock_load() */ /*------------------------------------------------------------------------- - * Function: H5EA__cache_iblock_clear + * Function: H5EA__cache_dblock_flush * - * Purpose: Mark a extensible array index block in memory as non-dirty. + * Purpose: Flushes a dirty extensible array data block to disk. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * koziol@hdfgroup.org - * Sept 9 2008 + * Sep 18 2008 * *------------------------------------------------------------------------- */ BEGIN_FUNC(STATIC, ERR, herr_t, SUCCEED, FAIL, -H5EA__cache_iblock_clear(H5F_t *f, H5EA_iblock_t *iblock, hbool_t destroy)) +H5EA__cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, + H5EA_dblock_t *dblock, unsigned UNUSED * flags_ptr)) - /* - * Check arguments. - */ - HDassert(iblock); + /* Local variables */ + H5WB_t *wb = NULL; /* Wrapped buffer for serializing data */ + uint8_t ser_buf[H5EA_DBLOCK_BUF_SIZE]; /* Serialization buffer */ + + /* Sanity check */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(dblock); + HDassert(dblock->hdr); + + if(dblock->cache_info.is_dirty) { + uint8_t *buf; /* Temporary raw data buffer */ + uint8_t *p; /* Pointer into raw data buffer */ + size_t size; /* Index block size on disk */ + uint32_t metadata_chksum; /* Computed metadata checksum value */ + + /* Wrap the local buffer for serialized info */ + if(NULL == (wb = H5WB_wrap(ser_buf, sizeof(ser_buf)))) + H5E_THROW(H5E_CANTINIT, "can't wrap buffer") + + /* Compute the size of the data block on disk */ + size = dblock->size; + + /* Get a pointer to a buffer that's large enough for serialized info */ + if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size))) + H5E_THROW(H5E_CANTGET, "can't get actual buffer") + + /* Get temporary pointer to serialized info */ + p = buf; + + /* Magic number */ + HDmemcpy(p, H5EA_DBLOCK_MAGIC, (size_t)H5EA_SIZEOF_MAGIC); + p += H5EA_SIZEOF_MAGIC; + + /* Version # */ + *p++ = H5EA_DBLOCK_VERSION; + + /* Extensible array type */ + *p++ = dblock->hdr->cls->id; + + /* Internal information */ + + /* Encode elements in data block */ + + /* Convert from native elements in memory into raw elements on disk */ + if((dblock->hdr->cls->encode)(p, dblock->elmts, dblock->nelmts) < 0) + H5E_THROW(H5E_CANTENCODE, "can't encode extensible array data elements") + p += (dblock->nelmts * dblock->hdr->raw_elmt_size); + + /* Compute metadata checksum */ + metadata_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0); + + /* Metadata checksum */ + UINT32ENCODE(p, metadata_chksum); + + /* Write the index block */ + HDassert((size_t)(p - buf) == size); + if(H5F_block_write(f, H5FD_MEM_EARRAY_DBLOCK, addr, size, dxpl_id, buf) < 0) + H5E_THROW(H5E_WRITEERROR, "unable to save extensible array data block to disk") + + dblock->cache_info.is_dirty = FALSE; + } /* end if */ + + if(destroy) + if(H5EA__cache_dblock_dest(f, dblock) < 0) + H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array data block") + +CATCH + + /* Release resources */ + if(wb && H5WB_unwrap(wb) < 0) + H5E_THROW(H5E_CLOSEERROR, "can't close wrapped buffer") + +END_FUNC(STATIC) /* end H5EA__cache_dblock_flush() */ + + +/*------------------------------------------------------------------------- + * Function: H5EA__cache_dblock_clear + * + * Purpose: Mark a extensible array data block in memory as non-dirty. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sept 18 2008 + * + *------------------------------------------------------------------------- + */ +BEGIN_FUNC(STATIC, ERR, +herr_t, SUCCEED, FAIL, +H5EA__cache_dblock_clear(H5F_t *f, H5EA_dblock_t *dblock, hbool_t destroy)) + + /* Sanity check */ + HDassert(dblock); /* Reset the dirty flag */ - iblock->cache_info.is_dirty = FALSE; + dblock->cache_info.is_dirty = FALSE; if(destroy) - if(H5EA__cache_iblock_dest(f, iblock) < 0) - H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array index block") + if(H5EA__cache_dblock_dest(f, dblock) < 0) + H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array data block") CATCH -END_FUNC(STATIC) /* end H5EA__cache_iblock_clear() */ +END_FUNC(STATIC) /* end H5EA__cache_dblock_clear() */ /*------------------------------------------------------------------------- - * Function: H5EA__cache_iblock_size + * Function: H5EA__cache_dblock_size * - * Purpose: Compute the size in bytes of a extensible array index block + * Purpose: Compute the size in bytes of a extensible array data block * on disk, and return it in *size_ptr. On failure, * the value of *size_ptr is undefined. * @@ -731,22 +1052,53 @@ END_FUNC(STATIC) /* end H5EA__cache_iblock_clear() */ * * Programmer: Quincey Koziol * koziol@hdfgroup.org - * Sept 9 2008 + * Sept 18 2008 * *------------------------------------------------------------------------- */ /* ARGSUSED */ BEGIN_FUNC(STATIC, NOERR, herr_t, SUCCEED, -, -H5EA__cache_iblock_size(const H5F_t UNUSED *f, const H5EA_iblock_t *iblock, size_t *size_ptr)) +H5EA__cache_dblock_size(const H5F_t UNUSED *f, const H5EA_dblock_t *dblock, + size_t *size_ptr)) /* Sanity check */ HDassert(f); - HDassert(iblock); + HDassert(dblock); HDassert(size_ptr); /* Set size value */ - *size_ptr = iblock->size; + *size_ptr = dblock->size; -END_FUNC(STATIC) /* end H5EA__cache_iblock_size() */ +END_FUNC(STATIC) /* end H5EA__cache_dblock_size() */ + + +/*------------------------------------------------------------------------- + * Function: H5EA__cache_dblock_dest + * + * Purpose: Destroys an extensible array data block in memory. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 18 2008 + * + *------------------------------------------------------------------------- + */ +/* ARGSUSED */ +BEGIN_FUNC(STATIC, ERR, +herr_t, SUCCEED, FAIL, +H5EA__cache_dblock_dest(H5F_t *f, H5EA_dblock_t *dblock)) + + /* Sanity check */ + HDassert(dblock); + + /* Release the data block */ + if(H5EA__dblock_dest(f, dblock) < 0) + H5E_THROW(H5E_CANTFREE, "can't free extensible array data block") + +CATCH + +END_FUNC(STATIC) /* end H5EA__cache_dblock_dest() */ diff --git a/src/H5EAdbg.c b/src/H5EAdbg.c index c75ced7..26c1070 100644 --- a/src/H5EAdbg.c +++ b/src/H5EAdbg.c @@ -131,7 +131,7 @@ H5EA__hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, "Native Element Size (on this platform):", hdr->cls->nat_elmt_size); HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, - "Log2(Max. # of elements in array):", + "# of elements in index block:", (unsigned)hdr->idx_blk_elmts); HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, "Min. # of elements per data block:", @@ -141,7 +141,16 @@ H5EA__hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, (unsigned)hdr->sup_blk_min_data_ptrs); HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth, "Highest element index stored (+1):", - hdr->max_idx_set); + hdr->stats.max_idx_set); + HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth, + "Number of super blocks created:", + hdr->stats.nsuper_blks); + HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth, + "Number of data blocks created:", + hdr->stats.ndata_blks); + HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth, + "Number of elements 'realized':", + hdr->stats.nelmts); HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth, "Index Block Address:", hdr->idx_blk_addr); @@ -206,27 +215,138 @@ H5EA__iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int inde HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth, "Index Block size:", iblock->size); + HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth, + "# of data block addresses in index block:", + iblock->ndblk_addrs); + HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth, + "# of super block addresses in index block:", + iblock->nsblk_addrs); - /* Check if there are any elements in array */ - if(hdr->max_idx_set > 0) { + /* Check if there are any elements in index block */ + if(hdr->idx_blk_elmts > 0) { unsigned u; /* Local index variable */ /* Print the elements in the index block */ HDfprintf(stream, "%*sElements in Index Block:\n", indent, ""); - for(u = 0; u < MIN(hdr->idx_blk_elmts, hdr->max_idx_set); u++) { + for(u = 0; u < hdr->idx_blk_elmts; u++) { /* Call the class's 'debug' callback */ - if((hdr->cls->debug)(stream, (indent + 6), MAX(0, (fwidth - 6)), + if((hdr->cls->debug)(stream, (indent + 3), MAX(0, (fwidth - 3)), (hsize_t)u, ((uint8_t *)iblock->elmts) + (hdr->cls->nat_elmt_size * u)) < 0) H5E_THROW(H5E_CANTGET, "can't get element for debugging") } /* end for */ } /* end if */ + /* Check if there are any data block addresses in index block */ + if(iblock->ndblk_addrs > 0) { + char temp_str[128]; /* Temporary string, for formatting */ + unsigned u; /* Local index variable */ + + /* Print the data block addresses in the index block */ + HDfprintf(stream, "%*sData Block Addresses in Index Block:\n", indent, ""); + for(u = 0; u < iblock->ndblk_addrs; u++) { + /* Print address */ + sprintf(temp_str, "Address #%u:", u); + HDfprintf(stream, "%*s%-*s %a\n", (indent + 3), "", MAX(0, (fwidth - 3)), + temp_str, + iblock->dblk_addrs[u]); + } /* end for */ + } /* end if */ + + /* Check if there are any super block addresses in index block */ + if(iblock->nsblk_addrs > 0) { + char temp_str[128]; /* Temporary string, for formatting */ + unsigned u; /* Local index variable */ + + /* Print the super block addresses in the index block */ + HDfprintf(stream, "%*sSuper Block Addresses in Index Block:\n", indent, ""); + for(u = 0; u < iblock->nsblk_addrs; u++) { + /* Print address */ + sprintf(temp_str, "Address #%u:", u); + HDfprintf(stream, "%*s%-*s %a\n", (indent + 3), "", MAX(0, (fwidth - 3)), + temp_str, + iblock->sblk_addrs[u]); + } /* end for */ + } /* end if */ + CATCH if(iblock && H5EA__iblock_unprotect(iblock, dxpl_id, H5AC__NO_FLAGS_SET) < 0) H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array index block") if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_EARRAY_HDR, hdr_addr, hdr, H5AC__NO_FLAGS_SET) < 0) H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array header") -END_FUNC(PKG) /* end H5EA__hdr_debug() */ +END_FUNC(PKG) /* end H5EA__iblock_debug() */ + + +/*------------------------------------------------------------------------- + * Function: H5EA__dblock_debug + * + * Purpose: Prints debugging info about a extensible array data block. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 22 2008 + * + *------------------------------------------------------------------------- + */ +BEGIN_FUNC(PKG, ERR, +herr_t, SUCCEED, FAIL, +H5EA__dblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, + int fwidth, const H5EA_class_t *cls, haddr_t hdr_addr, size_t dblk_nelmts)) + + /* Local variables */ + H5EA_hdr_t *hdr = NULL; /* Shared extensible array header */ + H5EA_dblock_t *dblock = NULL; /* Extensible array data block */ + size_t u; /* Local index variable */ + + /* Check arguments */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(stream); + HDassert(indent >= 0); + HDassert(fwidth >= 0); + HDassert(cls); + HDassert(H5F_addr_defined(hdr_addr)); + HDassert(dblk_nelmts > 0); + + /* Load the extensible array header */ + if(NULL == (hdr = (H5EA_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_EARRAY_HDR, hdr_addr, cls, NULL, H5AC_READ))) + H5E_THROW(H5E_CANTPROTECT, "unable to load extensible array header") + + /* Protect data block */ + if(NULL == (dblock = H5EA__dblock_protect(hdr, dxpl_id, addr, (size_t)dblk_nelmts, H5AC_READ))) + H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array data block, address = %llu", (unsigned long_long)addr) + + /* Print opening message */ + HDfprintf(stream, "%*sExtensible Array data Block...\n", indent, ""); + + /* Print the values */ + HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, + "Array class ID:", + (hdr->cls->id == H5EA_CLS_TEST_ID ? "H5EA_CLS_TEST_ID" : + "Unknown!")); + HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth, + "Data Block size:", + dblock->size); + + + /* Print the elements in the index block */ + HDfprintf(stream, "%*sElements:\n", indent, ""); + for(u = 0; u < dblk_nelmts; u++) { + /* Call the class's 'debug' callback */ + if((hdr->cls->debug)(stream, (indent + 3), MAX(0, (fwidth - 3)), + (hsize_t)u, + ((uint8_t *)dblock->elmts) + (hdr->cls->nat_elmt_size * u)) < 0) + H5E_THROW(H5E_CANTGET, "can't get element for debugging") + } /* end for */ + +CATCH + if(dblock && H5EA__dblock_unprotect(dblock, dxpl_id, H5AC__NO_FLAGS_SET) < 0) + H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array data block") + if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_EARRAY_HDR, hdr_addr, hdr, H5AC__NO_FLAGS_SET) < 0) + H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array header") + +END_FUNC(PKG) /* end H5EA__dblock_debug() */ diff --git a/src/H5EAdblock.c b/src/H5EAdblock.c new file mode 100644 index 0000000..e99fb3d --- /dev/null +++ b/src/H5EAdblock.c @@ -0,0 +1,419 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5EAdblock.c + * Sep 11 2008 + * Quincey Koziol <koziol@hdfgroup.org> + * + * Purpose: Data block routines for extensible arrays. + * + *------------------------------------------------------------------------- + */ + +/**********************/ +/* Module Declaration */ +/**********************/ + +#define H5EA_MODULE + + +/***********************/ +/* Other Packages Used */ +/***********************/ + + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5EApkg.h" /* Extensible Arrays */ +#include "H5FLprivate.h" /* Free Lists */ +#include "H5MFprivate.h" /* File memory management */ +#include "H5Vprivate.h" /* Vectors and arrays */ + + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + +/* Declare a free list to manage the H5EA_dblock_t struct */ +H5FL_DEFINE_STATIC(H5EA_dblock_t); + + + +/*------------------------------------------------------------------------- + * Function: H5EA__dblock_alloc + * + * Purpose: Allocate extensible array data block + * + * Return: Non-NULL pointer to data block on success/NULL on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 11 2008 + * + *------------------------------------------------------------------------- + */ +BEGIN_FUNC(PKG, ERR, +H5EA_dblock_t *, NULL, NULL, +H5EA__dblock_alloc(H5EA_hdr_t *hdr, size_t nelmts)) + + /* Local variables */ + H5EA_dblock_t *dblock = NULL; /* Extensible array index block */ + + /* Check arguments */ + HDassert(hdr); + HDassert(nelmts > 0); + + /* Allocate memory for the data block */ + if(NULL == (dblock = H5FL_CALLOC(H5EA_dblock_t))) + H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array data block") + + /* Set non-zero internal fields */ + dblock->nelmts = nelmts; + + /* Allocate buffer for elements in index block */ + if(NULL == (dblock->elmts = H5EA__hdr_alloc_elmts(hdr, nelmts))) + H5E_THROW(H5E_CANTALLOC, "memory allocation failed for data block element buffer") + + /* Share common array information */ + dblock->hdr = hdr; + if(H5EA__hdr_incr(hdr) < 0) + H5E_THROW(H5E_CANTINC, "can't increment reference count on shared array header") + + /* Set the return value */ + ret_value = dblock; + +CATCH + if(!ret_value) + if(dblock && H5EA__dblock_dest(hdr->f, dblock) < 0) + H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array data block") + +END_FUNC(PKG) /* end H5EA__dblock_alloc() */ + + +/*------------------------------------------------------------------------- + * Function: H5EA__dblock_create + * + * Purpose: Creates a new extensible array data block in the file + * + * Return: Valid file address on success/HADDR_UNDEF on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 9 2008 + * + *------------------------------------------------------------------------- + */ +BEGIN_FUNC(PKG, ERR, +haddr_t, HADDR_UNDEF, HADDR_UNDEF, +H5EA__dblock_create(H5EA_iblock_t *iblock, hid_t dxpl_id, size_t nelmts)) + + /* Local variables */ + H5EA_dblock_t *dblock = NULL; /* Extensible array data block */ + +#ifdef QAK +HDfprintf(stderr, "%s: Called\n", FUNC); +#endif /* QAK */ + + /* Sanity check */ + HDassert(iblock); + HDassert(nelmts > 0); + + /* Allocate the data block */ + if(NULL == (dblock = H5EA__dblock_alloc(iblock->hdr, nelmts))) + H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array data block") + + /* Set size of data block on disk */ + dblock->size = H5EA_DBLOCK_SIZE(dblock); +#ifdef QAK +HDfprintf(stderr, "%s: dblock->size = %Zu\n", FUNC, dblock->size); +#endif /* QAK */ + + /* Allocate space for the data block on disk */ + if(HADDR_UNDEF == (dblock->addr = H5MF_alloc(iblock->hdr->f, H5FD_MEM_EARRAY_DBLOCK, dxpl_id, dblock->size))) + H5E_THROW(H5E_CANTALLOC, "file allocation failed for extensible array data block") + + /* Clear any elements in index block to fill value */ + if((iblock->hdr->cls->fill)(dblock->elmts, (size_t)dblock->nelmts) < 0) + H5E_THROW(H5E_CANTSET, "can't set extensible array data block elements to class's fill value") + + /* Cache the new extensible array data block */ + if(H5AC_set(iblock->hdr->f, dxpl_id, H5AC_EARRAY_DBLOCK, dblock->addr, dblock, H5AC__NO_FLAGS_SET) < 0) + H5E_THROW(H5E_CANTINSERT, "can't add extensible array index block to cache") + + /* Set address of index block to return */ + ret_value = dblock->addr; + +CATCH + if(!H5F_addr_defined(ret_value)) + if(dblock) { + /* Release data block's disk space */ + if(H5F_addr_defined(dblock->addr) && H5MF_xfree(iblock->hdr->f, H5FD_MEM_EARRAY_DBLOCK, dxpl_id, dblock->addr, (hsize_t)dblock->size) < 0) + H5E_THROW(H5E_CANTFREE, "unable to release extensible array data block") + + /* Destroy data block */ + if(H5EA__dblock_dest(iblock->hdr->f, dblock) < 0) + H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array data block") + } /* end if */ + +END_FUNC(PKG) /* end H5EA__dblock_create() */ + + +/*------------------------------------------------------------------------- + * Function: H5EA__dblock_sblk_idx + * + * Purpose: Compute the index of the super block where the element is + * located. + * + * Return: Super block index on success/Can't fail + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 11 2008 + * + *------------------------------------------------------------------------- + */ +BEGIN_FUNC(PKG, NOERR, +unsigned, 0, -, +H5EA__dblock_sblk_idx(const H5EA_hdr_t *hdr, hsize_t idx)) + + /* Local variables */ + unsigned sblk_idx; /* Which superblock does this index fall in? */ + + /* Sanity check */ + HDassert(hdr); + HDassert(idx >= hdr->idx_blk_elmts); + +#ifdef QAK +HDfprintf(stderr, "%s: Entering - idx = %Hu\n", FUNC, idx); +#endif /* QAK */ + /* Adjust index for elements in index block */ + idx -= hdr->idx_blk_elmts; +#ifdef QAK +HDfprintf(stderr, "%s: after adjusting for index block elements, idx = %Hu\n", FUNC, idx); +#endif /* QAK */ + + /* Determine the superblock information for the index */ + H5_CHECK_OVERFLOW(idx, /*From:*/hsize_t, /*To:*/uint64_t); +#ifdef QAK +HDfprintf(stderr, "%s: hdr->data_blk_min_elmts = %u\n", FUNC, (unsigned)hdr->data_blk_min_elmts); +#endif /* QAK */ + sblk_idx = H5V_log2_gen((uint64_t)((idx / hdr->data_blk_min_elmts) + 1)); +#ifdef QAK +HDfprintf(stderr, "%s: sblk_idx = %u\n", FUNC, sblk_idx); +HDfprintf(stderr, "%s: hdr->sblk_info[%u] = {%Hu, %Zu, %Hu, %Hu}\n", FUNC, sblk_idx, hdr->sblk_info[sblk_idx].ndblks, hdr->sblk_info[sblk_idx].dblk_nelmts, hdr->sblk_info[sblk_idx].start_idx, hdr->sblk_info[sblk_idx].start_dblk); +#endif /* QAK */ + + /* Set return value */ + ret_value = sblk_idx; + +END_FUNC(PKG) /* end H5EA__dblock_sblk_idx() */ + + +/*------------------------------------------------------------------------- + * Function: H5EA__dblock_protect + * + * Purpose: Convenience wrapper around protecting extensible array data block + * + * Return: Non-NULL pointer to data block on success/NULL on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 18 2008 + * + *------------------------------------------------------------------------- + */ +BEGIN_FUNC(PKG, ERR, +H5EA_dblock_t *, NULL, NULL, +H5EA__dblock_protect(H5EA_hdr_t *hdr, hid_t dxpl_id, haddr_t dblk_addr, + size_t dblk_nelmts, H5AC_protect_t rw)) + + /* Local variables */ + +#ifdef QAK +HDfprintf(stderr, "%s: Called\n", FUNC); +#endif /* QAK */ + + /* Sanity check */ + HDassert(hdr); + HDassert(H5F_addr_defined(dblk_addr)); + HDassert(dblk_nelmts); + + /* Protect the data block */ + if(NULL == (ret_value = (H5EA_dblock_t *)H5AC_protect(hdr->f, dxpl_id, H5AC_EARRAY_DBLOCK, dblk_addr, &dblk_nelmts, hdr, rw))) + H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array data block, address = %llu", (unsigned long_long)dblk_addr) + +CATCH + +END_FUNC(PKG) /* end H5EA__dblock_protect() */ + + +/*------------------------------------------------------------------------- + * Function: H5EA__dblock_unprotect + * + * Purpose: Convenience wrapper around unprotecting extensible array data block + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 11 2008 + * + *------------------------------------------------------------------------- + */ +BEGIN_FUNC(PKG, ERR, +herr_t, SUCCEED, FAIL, +H5EA__dblock_unprotect(H5EA_dblock_t *dblock, hid_t dxpl_id, unsigned cache_flags)) + + /* Local variables */ + +#ifdef QAK +HDfprintf(stderr, "%s: Called\n", FUNC); +#endif /* QAK */ + + /* Sanity check */ + HDassert(dblock); + + /* Unprotect the data block */ + if(H5AC_unprotect(dblock->hdr->f, dxpl_id, H5AC_EARRAY_DBLOCK, dblock->addr, dblock, cache_flags) < 0) + H5E_THROW(H5E_CANTUNPROTECT, "unable to unprotect extensible array data block, address = %llu", (unsigned long_long)dblock->addr) + +CATCH + +END_FUNC(PKG) /* end H5EA__dblock_unprotect() */ + + +/*------------------------------------------------------------------------- + * Function: H5EA__dblock_delete + * + * Purpose: Delete a data block + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 22 2008 + * + *------------------------------------------------------------------------- + */ +BEGIN_FUNC(PKG, ERR, +herr_t, SUCCEED, FAIL, +H5EA__dblock_delete(H5EA_hdr_t *hdr, hid_t dxpl_id, haddr_t dblk_addr, + size_t dblk_nelmts)) + + /* Local variables */ + H5EA_dblock_t *dblock = NULL; /* Pointer to data block */ + +#ifdef QAK +HDfprintf(stderr, "%s: Called\n", FUNC); +#endif /* QAK */ + + /* Sanity check */ + HDassert(hdr); + HDassert(H5F_addr_defined(dblk_addr)); + HDassert(dblk_nelmts > 0); + + /* Protect data block */ + if(NULL == (dblock = H5EA__dblock_protect(hdr, dxpl_id, dblk_addr, dblk_nelmts, H5AC_WRITE))) + H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array data block, address = %llu", (unsigned long_long)dblk_addr) + + /* Release data block's disk space */ + if(H5MF_xfree(hdr->f, H5FD_MEM_EARRAY_DBLOCK, dxpl_id, dblk_addr, (hsize_t)dblock->size) < 0) + H5E_THROW(H5E_CANTFREE, "unable to free extensible array data block") + +CATCH + /* Finished deleting data block in metadata cache */ + if(dblock && H5EA__dblock_unprotect(dblock, dxpl_id, H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG) < 0) + H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array data block") + +END_FUNC(PKG) /* end H5EA__dblock_delete() */ + + +/*------------------------------------------------------------------------- + * Function: H5EA__dblock_dest + * + * Purpose: Destroys an extensible array data block in memory. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 11 2008 + * + *------------------------------------------------------------------------- + */ +/* ARGSUSED */ +BEGIN_FUNC(PKG, ERR, +herr_t, SUCCEED, FAIL, +H5EA__dblock_dest(H5F_t UNUSED *f, H5EA_dblock_t *dblock)) + + /* Sanity check */ + HDassert(dblock); + HDassert(dblock->hdr); + + /* Check if we've got elements in the index block */ + if(dblock->nelmts > 0) { + /* Free buffer for data block elements */ + HDassert(dblock->elmts); + if(H5EA__hdr_free_elmts(dblock->hdr, dblock->nelmts, dblock->elmts) < 0) + H5E_THROW(H5E_CANTFREE, "unable to free extensible array data block element buffer") + dblock->elmts = NULL; + } /* end if */ + + /* Decrement reference count on shared info */ + if(H5EA__hdr_decr(dblock->hdr) < 0) + H5E_THROW(H5E_CANTDEC, "can't decrement reference count on shared array header") + + /* Free the data block itself */ + (void)H5FL_FREE(H5EA_dblock_t, dblock); + +CATCH + +END_FUNC(PKG) /* end H5EA__dblock_dest() */ + diff --git a/src/H5EAhdr.c b/src/H5EAhdr.c index 9ccec62..a49116f 100644 --- a/src/H5EAhdr.c +++ b/src/H5EAhdr.c @@ -43,6 +43,7 @@ #include "H5Eprivate.h" /* Error handling */ #include "H5EApkg.h" /* Extensible Arrays */ #include "H5MFprivate.h" /* File memory management */ +#include "H5Vprivate.h" /* Vectors and arrays */ /****************/ @@ -77,13 +78,22 @@ /* Library Private Variables */ /*****************************/ +/* Alias for pointer to factory, for use when allocating sequences of them */ +typedef H5FL_fac_head_t *H5FL_fac_head_ptr_t; + /*******************/ /* Local Variables */ /*******************/ /* Declare a free list to manage the H5EA_hdr_t struct */ -H5FL_DEFINE(H5EA_hdr_t); +H5FL_DEFINE_STATIC(H5EA_hdr_t); + +/* Declare a free list to manage the H5FL_fac_head_ptr_t sequence information */ +H5FL_SEQ_DEFINE_STATIC(H5FL_fac_head_ptr_t); + +/* Declare a free list to manage the H5EA_sblk_info_t sequence information */ +H5FL_SEQ_DEFINE_STATIC(H5EA_sblk_info_t); @@ -128,13 +138,209 @@ H5EA__hdr_alloc(H5F_t *f, const H5EA_class_t *cls)) CATCH if(!ret_value) - if(hdr && H5EA__cache_hdr_dest(f, hdr) < 0) + if(hdr && H5EA__hdr_dest(hdr) < 0) H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array header") END_FUNC(PKG) /* end H5EA__hdr_alloc() */ /*------------------------------------------------------------------------- + * Function: H5EA__hdr_init + * + * Purpose: Compute useful information for extensible array, based on + * "creation" information. + * + * Notes: The equations for variables below are based on this information: + * + * <sblk idx> <# of dblks> <size of dblks> Range of elements in sblk + * ========== ============ =============== ========================= + * 0 1 1 * <dblk min elmts> 0 * <dblk min elmts> <-> 1 * <dblk min elmts> - 1 + * 1 1 2 * <dblk min elmts> 1 * <dblk min elmts> <-> 3 * <dblk min elmts> - 1 + * 2 2 2 * <dblk min elmts> 3 * <dblk min elmts> <-> 7 * <dblk min elmts> - 1 + * 3 2 4 * <dblk min elmts> 7 * <dblk min elmts> <-> 15 * <dblk min elmts> - 1 + * 4 4 4 * <dblk min elmts> 15 * <dblk min elmts> <-> 31 * <dblk min elmts> - 1 + * 5 4 8 * <dblk min elmts> 31 * <dblk min elmts> <-> 63 * <dblk min elmts> - 1 + * 6 8 8 * <dblk min elmts> 63 * <dblk min elmts> <-> 127 * <dblk min elmts> - 1 + * 7 8 16 * <dblk min elmts> 127 * <dblk min elmts> <-> 255 * <dblk min elmts> - 1 + * . . . * <dblk min elmts> . * <dblk min elmts> <-> . * <dblk min elmts> - 1 + * . . . * <dblk min elmts> . * <dblk min elmts> <-> . * <dblk min elmts> - 1 + * . . . * <dblk min elmts> . * <dblk min elmts> <-> . * <dblk min elmts> - 1 + * + * Therefore: + * <sblk idx>(<elmt idx>) = lg2((<elmt idx> / <dblk min elmts>) + 1) + * <# of dblks>(<sblk idx>) = 2 ^ (<sblk idx> / 2) + * <size of dblk>(<sblk idx>) = 2 ^ ((<sblk idx> + 1) / 2) + * <total # of sblks>(<max. # of elmts>) = 1 + (lg2(<max. # of elmts>) - lg2(<dblk min_elmts>)) + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 18 2008 + * + *------------------------------------------------------------------------- + */ +BEGIN_FUNC(PKG, ERR, +herr_t, SUCCEED, FAIL, +H5EA__hdr_init(H5EA_hdr_t *hdr)) + + /* Local variables */ + hsize_t start_idx; /* First element index for each super block */ + hsize_t start_dblk; /* First data block index for each super block */ + size_t u; /* Local index variable */ + + /* Sanity check */ + HDassert(hdr); + HDassert(hdr->max_nelmts_bits); + HDassert(hdr->data_blk_min_elmts); + HDassert(hdr->sup_blk_min_data_ptrs); + + /* Compute general information */ + hdr->nsblks = 1 + (hdr->max_nelmts_bits - H5V_log2_of2(hdr->data_blk_min_elmts)); +#ifdef QAK +HDfprintf(stderr, "%s: hdr->nsblks = %Zu\n", FUNC, hdr->nsblks); +#endif /* QAK */ + + /* Allocate information for each super block */ + if(NULL == (hdr->sblk_info = H5FL_SEQ_MALLOC(H5EA_sblk_info_t, hdr->nsblks))) + H5E_THROW(H5E_CANTALLOC, "memory allocation failed for super block info array") + + /* Compute information about each super block */ + start_idx = 0; + start_dblk = 0; + for(u = 0; u < hdr->nsblks; u++) { + hdr->sblk_info[u].ndblks = (hsize_t)H5_EXP2(u / 2); + hdr->sblk_info[u].dblk_nelmts = (size_t)H5_EXP2((u + 1) / 2) * hdr->data_blk_min_elmts; + hdr->sblk_info[u].start_idx = start_idx; + hdr->sblk_info[u].start_dblk = start_dblk; +#ifdef QAK +HDfprintf(stderr, "%s: hdr->sblk_info[%Zu] = {%Hu, %Zu, %Hu, %Hu}\n", FUNC, u, hdr->sblk_info[u].ndblks, hdr->sblk_info[u].dblk_nelmts, hdr->sblk_info[u].start_idx, hdr->sblk_info[u].start_dblk); +#endif /* QAK */ + + /* Advance starting indices for next super block */ + start_idx += hdr->sblk_info[u].ndblks * hdr->sblk_info[u].dblk_nelmts; + start_dblk += hdr->sblk_info[u].ndblks; + } /* end for */ + + /* Set size of header on disk */ + hdr->size = H5EA_HEADER_SIZE(hdr); + +CATCH + +END_FUNC(PKG) /* end H5EA__hdr_init() */ + + +/*------------------------------------------------------------------------- + * Function: H5EA__hdr_alloc_elmts + * + * Purpose: Allocate extensible array data block elements + * + * Return: Non-NULL pointer to buffer for elements on success/NULL on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 16 2008 + * + *------------------------------------------------------------------------- + */ +BEGIN_FUNC(PKG, ERR, +void *, NULL, NULL, +H5EA__hdr_alloc_elmts(H5EA_hdr_t *hdr, size_t nelmts)) + + /* Local variables */ + void *elmts = NULL; /* Element buffer allocated */ + unsigned idx; /* Index of element buffer factory in header */ + + /* Check arguments */ + HDassert(hdr); + HDassert(nelmts > 0); + + /* Compute the index of the element buffer factory */ + H5_CHECK_OVERFLOW(nelmts, /*From:*/size_t, /*To:*/uint32_t); + idx = H5V_log2_of2((uint32_t)nelmts) - H5V_log2_of2((uint32_t)hdr->data_blk_min_elmts); +#ifdef QAK +HDfprintf(stderr, "%s: nelmts = %Zu, hdr->data_blk_min_elmts = %u, idx = %u\n", FUNC, nelmts, (unsigned)hdr->data_blk_min_elmts, idx); +#endif /* QAK */ + + /* Check for needing to increase size of array of factories */ + if(idx >= hdr->elmt_fac.nalloc) { + H5FL_fac_head_t **new_fac; /* New array of element factories */ + size_t new_nalloc = MAX(1, (2 * hdr->elmt_fac.nalloc)); /* New number of factories allocated */ + + /* Re-allocate array of element factories */ + if(NULL == (new_fac = H5FL_SEQ_REALLOC(H5FL_fac_head_ptr_t, hdr->elmt_fac.fac, new_nalloc))) + H5E_THROW(H5E_CANTALLOC, "memory allocation failed for data block data element buffer factory array") + + /* Zero out new elements allocated */ + HDmemset(new_fac + hdr->elmt_fac.nalloc, 0, (new_nalloc - hdr->elmt_fac.nalloc) * sizeof(H5FL_fac_head_ptr_t)); + + /* Update information about element factories in header */ + hdr->elmt_fac.nalloc = new_nalloc; + hdr->elmt_fac.fac = new_fac; + } /* end if */ + + /* Check for un-initialized factory at index */ + if(NULL == hdr->elmt_fac.fac[idx]) { + if(NULL == (hdr->elmt_fac.fac[idx] = H5FL_fac_init(nelmts * (size_t)hdr->cls->nat_elmt_size))) + H5E_THROW(H5E_CANTINIT, "can't create data block data element buffer factory") + } /* end if */ + + /* Allocate buffer for elements in index block */ + if(NULL == (elmts = H5FL_FAC_MALLOC(hdr->elmt_fac.fac[idx]))) + H5E_THROW(H5E_CANTALLOC, "memory allocation failed for data block data element buffer") + + /* Set the return value */ + ret_value = elmts; + +CATCH + if(!ret_value) + if(elmts) + (void)H5FL_fac_free(hdr->elmt_fac.fac[idx], elmts); + +END_FUNC(PKG) /* end H5EA__hdr_alloc_elmts() */ + + +/*------------------------------------------------------------------------- + * Function: H5EA__hdr_free_elmts + * + * Purpose: Free extensible array data block elements + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 18 2008 + * + *------------------------------------------------------------------------- + */ +BEGIN_FUNC(PKG, NOERR, +herr_t, SUCCEED, -, +H5EA__hdr_free_elmts(H5EA_hdr_t *hdr, size_t nelmts, void *elmts)) + + /* Local variables */ + unsigned idx; /* Index of element buffer factory in header */ + + /* Check arguments */ + HDassert(hdr); + HDassert(nelmts > 0); + HDassert(elmts); + + /* Compute the index of the element buffer factory */ + H5_CHECK_OVERFLOW(nelmts, /*From:*/size_t, /*To:*/uint32_t); + idx = H5V_log2_of2((uint32_t)nelmts) - H5V_log2_of2((uint32_t)hdr->data_blk_min_elmts); +#ifdef QAK +HDfprintf(stderr, "%s: nelmts = %Zu, hdr->data_blk_min_elmts = %u, idx = %u\n", FUNC, nelmts, (unsigned)hdr->data_blk_min_elmts, idx); +#endif /* QAK */ + + /* Free buffer for elements in index block */ + HDassert(idx < hdr->elmt_fac.nalloc); + HDassert(hdr->elmt_fac.fac[idx]); + (void)H5FL_FAC_FREE(hdr->elmt_fac.fac[idx], elmts); + +END_FUNC(PKG) /* end H5EA__hdr_free_elmts() */ + + +/*------------------------------------------------------------------------- * Function: H5EA__hdr_create * * Purpose: Creates a new extensible array header in the file @@ -155,7 +361,7 @@ H5EA__hdr_create(H5F_t *f, hid_t dxpl_id, const H5EA_create_t *cparam)) H5EA_hdr_t *hdr; /* Extensible array header */ #ifdef QAK -HDfprintf(stderr, "%s: Called\n", __func__); +HDfprintf(stderr, "%s: Called\n", FUNC); #endif /* QAK */ /* Check arguments */ @@ -170,6 +376,8 @@ HDfprintf(stderr, "%s: Called\n", __func__); H5E_THROW(H5E_BADVALUE, "max. # of nelmts bitsmust be greater than zero") if(cparam->max_nelmts_bits > H5EA_MAX_NELMTS_IDX_MAX) H5E_THROW(H5E_BADVALUE, "element size must be <= %u", (unsigned)H5EA_MAX_NELMTS_IDX_MAX) + if(cparam->sup_blk_min_data_ptrs < 2) + H5E_THROW(H5E_BADVALUE, "min # of data block pointers in super block must be >= two") if(!POWER_OF_TWO(cparam->sup_blk_min_data_ptrs)) H5E_THROW(H5E_BADVALUE, "min # of data block pointers in super block not power of two") if(!POWER_OF_TWO(cparam->data_blk_min_elmts)) @@ -190,8 +398,9 @@ HDfprintf(stderr, "%s: Called\n", __func__); hdr->sup_blk_min_data_ptrs = cparam->sup_blk_min_data_ptrs; hdr->data_blk_min_elmts = cparam->data_blk_min_elmts; - /* Set size of header on disk */ - hdr->size = H5EA_HEADER_SIZE(hdr); + /* Finish initializing extensible array header */ + if(H5EA__hdr_init(hdr) < 0) + H5E_THROW(H5E_CANTINIT, "initialization failed for extensible array header") /* Allocate space for the header on disk */ if(HADDR_UNDEF == (hdr->addr = H5MF_alloc(f, H5FD_MEM_EARRAY_HDR, dxpl_id, hdr->size))) @@ -402,7 +611,7 @@ H5EA__hdr_delete(H5EA_hdr_t *hdr, hid_t dxpl_id)) /* Check for index block */ if(H5F_addr_defined(hdr->idx_blk_addr)) { #ifdef QAK -HDfprintf(stderr, "%s: hdr->idx_blk_addr = %a\n", __func__, hdr->idx_blk_addr); +HDfprintf(stderr, "%s: hdr->idx_blk_addr = %a\n", FUNC, hdr->idx_blk_addr); #endif /* QAK */ /* Delete index block */ if(H5EA__iblock_delete(hdr, dxpl_id) < 0) @@ -426,3 +635,57 @@ CATCH END_FUNC(PKG) /* end H5EA__hdr_delete() */ + +/*------------------------------------------------------------------------- + * Function: H5EA__hdr_dest + * + * Purpose: Destroys an extensible array header in memory. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 11 2008 + * + *------------------------------------------------------------------------- + */ +BEGIN_FUNC(PKG, ERR, +herr_t, SUCCEED, FAIL, +H5EA__hdr_dest(H5EA_hdr_t *hdr)) + + /* Check arguments */ + HDassert(hdr); + HDassert(hdr->rc == 0); + + /* Check for data block element buffer factory info to free */ + if(hdr->elmt_fac.fac) { + unsigned u; /* Local index variable */ + + /* Sanity check */ + HDassert(hdr->elmt_fac.nalloc > 0); + + /* Iterate over factories, shutting them down */ + for(u = 0; u < hdr->elmt_fac.nalloc; u++) { + /* Check if this factory has been initialized */ + if(hdr->elmt_fac.fac[u]) { + if(H5FL_fac_term(hdr->elmt_fac.fac[u]) < 0) + H5E_THROW(H5E_CANTRELEASE, "unable to destroy extensible array header factory") + hdr->elmt_fac.fac[u] = NULL; + } /* end if */ + } /* end for */ + + /* Free factory array */ + hdr->elmt_fac.fac = (H5FL_fac_head_t **)H5FL_SEQ_FREE(H5FL_fac_head_ptr_t, hdr->elmt_fac.fac); + } /* end if */ + + /* Free the super block info array */ + if(hdr->sblk_info) + hdr->sblk_info = (H5EA_sblk_info_t *)H5FL_SEQ_FREE(H5EA_sblk_info_t, hdr->sblk_info); + + /* Free the shared info itself */ + (void)H5FL_FREE(H5EA_hdr_t, hdr); + +CATCH + +END_FUNC(PKG) /* end H5EA__hdr_dest() */ + diff --git a/src/H5EAiblock.c b/src/H5EAiblock.c index 2e924a9..bf3fac4 100644 --- a/src/H5EAiblock.c +++ b/src/H5EAiblock.c @@ -42,7 +42,9 @@ #include "H5private.h" /* Generic Functions */ #include "H5Eprivate.h" /* Error handling */ #include "H5EApkg.h" /* Extensible Arrays */ +#include "H5FLprivate.h" /* Free Lists */ #include "H5MFprivate.h" /* File memory management */ +#include "H5Vprivate.h" /* Vectors and arrays */ /****************/ @@ -80,17 +82,20 @@ /*******************/ /* Declare a free list to manage the H5EA_iblock_t struct */ -H5FL_DEFINE(H5EA_iblock_t); +H5FL_DEFINE_STATIC(H5EA_iblock_t); /* Declare a free list to manage the index block elements */ -H5FL_BLK_DEFINE(elmt_buf); +H5FL_BLK_DEFINE_STATIC(idx_blk_elmt_buf); + +/* Declare a free list to manage the haddr_t sequence information */ +H5FL_SEQ_DEFINE_STATIC(haddr_t); /*------------------------------------------------------------------------- * Function: H5EA__iblock_alloc * - * Purpose: Allocate shared extensible array index block + * Purpose: Allocate extensible array index block * * Return: Non-NULL pointer to index block on success/NULL on failure * @@ -117,17 +122,42 @@ H5EA__iblock_alloc(H5EA_hdr_t *hdr)) /* Set non-zero internal fields */ iblock->addr = HADDR_UNDEF; + /* Compute information */ + iblock->nsblks = 2 * H5V_log2_of2((uint32_t)hdr->sup_blk_min_data_ptrs); + iblock->ndblk_addrs = 2 * ((size_t)hdr->sup_blk_min_data_ptrs - 1); + iblock->nsblk_addrs = hdr->nsblks - iblock->nsblks; +#ifdef QAK +HDfprintf(stderr, "%s: iblock->nsblks = %u\n", FUNC, iblock->nsblks); +HDfprintf(stderr, "%s: iblock->ndblk_addrs = %Zu\n", FUNC, iblock->ndblk_addrs); +HDfprintf(stderr, "%s: iblock->nsblk_addrs = %Zu\n", FUNC, iblock->nsblk_addrs); +#endif /* QAK */ + /* Allocate buffer for elements in index block */ if(hdr->idx_blk_elmts > 0) - if(NULL == (iblock->elmts = H5FL_BLK_MALLOC(elmt_buf, (size_t)(hdr->idx_blk_elmts * hdr->cls->nat_elmt_size)))) + if(NULL == (iblock->elmts = H5FL_BLK_MALLOC(idx_blk_elmt_buf, (size_t)(hdr->idx_blk_elmts * hdr->cls->nat_elmt_size)))) H5E_THROW(H5E_CANTALLOC, "memory allocation failed for index block data element buffer") + /* Allocate buffer for data block addresses in index block */ + if(iblock->ndblk_addrs > 0) + if(NULL == (iblock->dblk_addrs = H5FL_SEQ_MALLOC(haddr_t, iblock->ndblk_addrs))) + H5E_THROW(H5E_CANTALLOC, "memory allocation failed for index block data block addresses") + + /* Allocate buffer for super block addresses in index block */ + if(iblock->nsblk_addrs > 0) + if(NULL == (iblock->sblk_addrs = H5FL_SEQ_MALLOC(haddr_t, iblock->nsblk_addrs))) + H5E_THROW(H5E_CANTALLOC, "memory allocation failed for index block super block addresses") + + /* Share common array information */ + iblock->hdr = hdr; + if(H5EA__hdr_incr(hdr) < 0) + H5E_THROW(H5E_CANTINC, "can't increment reference count on shared array header") + /* Set the return value */ ret_value = iblock; CATCH if(!ret_value) - if(iblock && H5EA__cache_iblock_dest(hdr->f, iblock) < 0) + if(iblock && H5EA__iblock_dest(hdr->f, iblock) < 0) H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array index block") END_FUNC(PKG) /* end H5EA__iblock_alloc() */ @@ -154,7 +184,7 @@ H5EA__iblock_create(H5EA_hdr_t *hdr, hid_t dxpl_id)) H5EA_iblock_t *iblock = NULL; /* Extensible array index block */ #ifdef QAK -HDfprintf(stderr, "%s: Called\n", __func__); +HDfprintf(stderr, "%s: Called\n", FUNC); #endif /* QAK */ /* Sanity check */ @@ -164,21 +194,16 @@ HDfprintf(stderr, "%s: Called\n", __func__); if(NULL == (iblock = H5EA__iblock_alloc(hdr))) H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array index block") - /* Set size of header on disk */ - iblock->size = H5EA_IBLOCK_SIZE(hdr); + /* Set size of index block on disk */ + iblock->size = H5EA_IBLOCK_SIZE(iblock); #ifdef QAK -HDfprintf(stderr, "%s: iblock->size = %Zu\n", __func__, iblock->size); +HDfprintf(stderr, "%s: iblock->size = %Zu\n", FUNC, iblock->size); #endif /* QAK */ /* Allocate space for the index block on disk */ if(HADDR_UNDEF == (iblock->addr = H5MF_alloc(hdr->f, H5FD_MEM_EARRAY_IBLOCK, dxpl_id, iblock->size))) H5E_THROW(H5E_CANTALLOC, "file allocation failed for extensible array index block") - /* Share common array information */ - iblock->hdr = hdr; - if(H5EA__hdr_incr(hdr) < 0) - H5E_THROW(H5E_CANTINC, "can't increment reference count on shared array header") - /* Clear any elements in index block to fill value */ if(hdr->idx_blk_elmts > 0) { /* Call the class's 'fill' callback */ @@ -186,6 +211,22 @@ HDfprintf(stderr, "%s: iblock->size = %Zu\n", __func__, iblock->size); H5E_THROW(H5E_CANTSET, "can't set extensible array index block elements to class's fill value") } /* end if */ + /* Reset any data block addresses in the index block */ + if(iblock->ndblk_addrs > 0) { + haddr_t tmp_addr = HADDR_UNDEF; /* Address value to fill data block addresses with */ + + /* Set all the data block addresses to "undefined" address value */ + H5V_array_fill(iblock->dblk_addrs, &tmp_addr, sizeof(haddr_t), iblock->ndblk_addrs); + } /* end if */ + + /* Reset any super block addresses in the index block */ + if(iblock->nsblk_addrs > 0) { + haddr_t tmp_addr = HADDR_UNDEF; /* Address value to fill super block addresses with */ + + /* Set all the super block addresses to "undefined" address value */ + H5V_array_fill(iblock->sblk_addrs, &tmp_addr, sizeof(haddr_t), iblock->nsblk_addrs); + } /* end if */ + /* Cache the new extensible array index block */ if(H5AC_set(hdr->f, dxpl_id, H5AC_EARRAY_IBLOCK, iblock->addr, iblock, H5AC__NO_FLAGS_SET) < 0) H5E_THROW(H5E_CANTINSERT, "can't add extensible array index block to cache") @@ -201,7 +242,7 @@ CATCH H5E_THROW(H5E_CANTFREE, "unable to release extensible array index block") /* Destroy index block */ - if(H5EA__cache_iblock_dest(hdr->f, iblock) < 0) + if(H5EA__iblock_dest(hdr->f, iblock) < 0) H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array index block") } /* end if */ @@ -228,7 +269,7 @@ H5EA__iblock_protect(H5EA_hdr_t *hdr, hid_t dxpl_id, H5AC_protect_t rw)) /* Local variables */ #ifdef QAK -HDfprintf(stderr, "%s: Called\n", __func__); +HDfprintf(stderr, "%s: Called\n", FUNC); #endif /* QAK */ /* Sanity check */ @@ -248,7 +289,7 @@ END_FUNC(PKG) /* end H5EA__iblock_protect() */ * * Purpose: Convenience wrapper around unprotecting extensible array index block * - * Return: SUCCEED/FAIL + * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * koziol@hdfgroup.org @@ -263,7 +304,7 @@ H5EA__iblock_unprotect(H5EA_iblock_t *iblock, hid_t dxpl_id, unsigned cache_flag /* Local variables */ #ifdef QAK -HDfprintf(stderr, "%s: Called\n", __func__); +HDfprintf(stderr, "%s: Called\n", FUNC); #endif /* QAK */ /* Sanity check */ @@ -299,7 +340,7 @@ H5EA__iblock_delete(H5EA_hdr_t *hdr, hid_t dxpl_id)) H5EA_iblock_t *iblock = NULL; /* Pointer to index block */ #ifdef QAK -HDfprintf(stderr, "%s: Called\n", __func__); +HDfprintf(stderr, "%s: Called\n", FUNC); #endif /* QAK */ /* Sanity check */ @@ -310,7 +351,47 @@ HDfprintf(stderr, "%s: Called\n", __func__); if(NULL == (iblock = H5EA__iblock_protect(hdr, dxpl_id, H5AC_WRITE))) H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array index block, address = %llu", (unsigned long_long)hdr->idx_blk_addr) - /* Iterate over data blocks & super blocks (not yet) */ + /* Check for index block having data block pointers */ + if(iblock->ndblk_addrs > 0) { + unsigned sblk_idx; /* Current super block index */ + unsigned dblk_idx; /* Current data block index w/in super block */ + size_t u; /* Local index variable */ + + /* Iterate over data blocks */ + sblk_idx = dblk_idx = 0; + for(u = 0; u < iblock->ndblk_addrs; u++) { + /* Check for data block existing */ + if(H5F_addr_defined(iblock->dblk_addrs[u])) { + /* Delete data block */ + if(H5EA__dblock_delete(hdr, dxpl_id, iblock->dblk_addrs[u], hdr->sblk_info[sblk_idx].dblk_nelmts) < 0) + H5E_THROW(H5E_CANTDELETE, "unable to delete extensible array data block") + iblock->dblk_addrs[u] = HADDR_UNDEF; + } /* end if */ + + /* Advance to next data block w/in super block */ + dblk_idx++; + + /* Check for moving to next super block */ + if(dblk_idx >= hdr->sblk_info[sblk_idx].ndblks) { + sblk_idx++; + dblk_idx = 0; + } /* end if */ + } /* end for */ + } /* end if */ + + /* Check for index block having data block pointers (not yet) */ + if(iblock->nsblk_addrs > 0) { + size_t u; /* Local index variable */ + + /* Iterate over super blocks */ + for(u = 0; u < iblock->nsblk_addrs; u++) { + /* Check for data block existing */ + if(H5F_addr_defined(iblock->sblk_addrs[u])) { +HDfprintf(stderr, "%s: Deleting super blocks not supported yet!\n", FUNC); +HDassert(0 && "Deleting super blocks not supported!"); + } /* end if */ + } /* end for */ + } /* end if */ /* Release index block's disk space */ if(H5MF_xfree(hdr->f, H5FD_MEM_EARRAY_IBLOCK, dxpl_id, hdr->idx_blk_addr, (hsize_t)iblock->size) < 0) @@ -323,3 +404,61 @@ CATCH END_FUNC(PKG) /* end H5EA__iblock_delete() */ + +/*------------------------------------------------------------------------- + * Function: H5EA__iblock_dest + * + * Purpose: Destroys an extensible array index block in memory. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 11 2008 + * + *------------------------------------------------------------------------- + */ +/* ARGSUSED */ +BEGIN_FUNC(PKG, ERR, +herr_t, SUCCEED, FAIL, +H5EA__iblock_dest(H5F_t *f, H5EA_iblock_t *iblock)) + + /* Sanity check */ + HDassert(iblock); + HDassert(iblock->rc == 0); + + /* Set the shared array header's file context for this operation */ + iblock->hdr->f = f; + + /* Check if we've got elements in the index block */ + if(iblock->hdr->idx_blk_elmts > 0) { + /* Free buffer for index block elements */ + HDassert(iblock->elmts); + (void)H5FL_BLK_FREE(idx_blk_elmt_buf, iblock->elmts); + } /* end if */ + + /* Check if we've got data block addresses in the index block */ + if(iblock->ndblk_addrs > 0) { + /* Free buffer for index block data block addresses */ + HDassert(iblock->dblk_addrs); + (void)H5FL_SEQ_FREE(haddr_t, iblock->dblk_addrs); + } /* end if */ + + /* Check if we've got super block addresses in the index block */ + if(iblock->nsblk_addrs > 0) { + /* Free buffer for index block super block addresses */ + HDassert(iblock->sblk_addrs); + (void)H5FL_SEQ_FREE(haddr_t, iblock->sblk_addrs); + } /* end if */ + + /* Decrement reference count on shared info */ + if(H5EA__hdr_decr(iblock->hdr) < 0) + H5E_THROW(H5E_CANTDEC, "can't decrement reference count on shared array header") + + /* Free the index block itself */ + (void)H5FL_FREE(H5EA_iblock_t, iblock); + +CATCH + +END_FUNC(PKG) /* end H5EA__iblock_dest() */ + diff --git a/src/H5EApkg.h b/src/H5EApkg.h index 5f6f10f..f826220 100644 --- a/src/H5EApkg.h +++ b/src/H5EApkg.h @@ -353,6 +353,7 @@ func_init_failed: \ /* Extensible array signatures */ #define H5EA_HDR_MAGIC "EAHD" /* Header */ #define H5EA_IBLOCK_MAGIC "EAIB" /* Index block */ +#define H5EA_DBLOCK_MAGIC "EADB" /* Data block */ /* Size of checksum information (on disk) */ #define H5EA_SIZEOF_CHKSUM 4 @@ -377,18 +378,34 @@ func_init_failed: \ + 1 /* Min. # elements per data block */ \ + 1 /* Min. # of data block pointers for a super block */ \ \ + /* Extensible Array Header statistics fields */ \ + + (h)->sizeof_size /* Max. index set */ \ + + (h)->sizeof_size /* Number of super blocks created */ \ + + (h)->sizeof_size /* Number of data blocks created */ \ + + (h)->sizeof_size /* Number of elements 'realized' */ \ + \ /* Extensible Array Header specific fields */ \ - + (h)->sizeof_addr /* File address of index block */ \ - + (h)->sizeof_size /* Max. index set */ \ + + (h)->sizeof_addr /* File address of index block */ \ ) /* Size of the extensible array index block on disk */ -#define H5EA_IBLOCK_SIZE(h) ( \ +#define H5EA_IBLOCK_SIZE(i) ( \ /* General metadata fields */ \ H5EA_METADATA_PREFIX_SIZE(TRUE) \ \ /* Extensible Array Index Block specific fields */ \ - + (size_t)((h)->idx_blk_elmts * (h)->raw_elmt_size) /* Elements in index block */ \ + + ((size_t)(i)->hdr->idx_blk_elmts * (size_t)(i)->hdr->raw_elmt_size) /* Elements in index block */ \ + + ((i)->ndblk_addrs * (i)->hdr->sizeof_addr) /* Data block addresses in index block */ \ + + ((i)->nsblk_addrs * (i)->hdr->sizeof_addr) /* Super block addresses in index block */ \ + ) + +/* Size of the extensible array data block on disk */ +#define H5EA_DBLOCK_SIZE(d) ( \ + /* General metadata fields */ \ + H5EA_METADATA_PREFIX_SIZE(TRUE) \ + \ + /* Extensible Array Data Block specific fields */ \ + + ((d)->nelmts * (size_t)(d)->hdr->raw_elmt_size) /* Elements in index block */ \ ) @@ -396,6 +413,14 @@ func_init_failed: \ /* Package Private Typedefs */ /****************************/ +/* Information for each super block in extensible array */ +typedef struct H5EA_sblk_info_t { + hsize_t ndblks; /* Number of data blocks for a super block */ + size_t dblk_nelmts; /* Number of elements in each data block for super block */ + hsize_t start_idx; /* Index of first element in super block */ + hsize_t start_dblk; /* Index of first data block in super block */ +} H5EA_sblk_info_t; + /* The extensible array header information */ /* (Each extensible array header has certain information that is shared across * all the blocks in that extensible array) @@ -415,9 +440,15 @@ typedef struct H5EA_hdr_t { haddr_t idx_blk_addr; /* Address of index block in header */ /* Statistics for array (stored in header) */ - hsize_t max_idx_set; /* Highest element index stored (+1 - i.e. if element 0 has been set, this value with be '1', if no elements have been stored, this value will be '0') */ + H5EA_stat_t stats; /* Statistics for extensible array */ + + /* Data block element buffer factory info (not stored in header) */ + struct { + size_t nalloc; /* Number of factories allocated */ + H5FL_fac_head_t **fac; /* Array of factories for data block element buffers */ + } elmt_fac; - /* Computed/cached values */ + /* Computed/cached values (not stored in header) */ size_t rc; /* Reference count of heap's components using heap header */ haddr_t addr; /* Address of header in file */ size_t size; /* Size of header in file */ @@ -427,6 +458,10 @@ typedef struct H5EA_hdr_t { size_t sizeof_addr; /* Size of file addresses */ size_t sizeof_size; /* Size of file sizes */ + /* Super block information (not stored) */ + size_t nsblks; /* Number of superblocks needed for array */ + H5EA_sblk_info_t *sblk_info; /* Array of information for each super block */ + /* Memory data structures (not stored directly) */ const H5EA_class_t *cls; /* Pointer to class for array */ } H5EA_hdr_t; @@ -438,14 +473,38 @@ typedef struct H5EA_iblock_t { /* Extensible array information (stored) */ void *elmts; /* Buffer for elements stored in index block */ + haddr_t *dblk_addrs; /* Buffer for addresses of data blocks in index block */ + haddr_t *sblk_addrs; /* Buffer for addresses of super blocks in index block */ /* Internal array information (not stored) */ size_t rc; /* Reference count of objects using this block */ H5EA_hdr_t *hdr; /* Shared array header info */ haddr_t addr; /* Address of this index block on disk */ size_t size; /* Size of index block on disk */ + + /* Computed/cached values (not stored) */ + size_t nsblks; /* # of super blocks whose data block addresses are in index block */ + size_t ndblk_addrs; /* Number of pointers to data blocks in index block */ + size_t nsblk_addrs; /* Number of pointers to super blocks in index block */ } H5EA_iblock_t; +/* The extensible array data block information */ +typedef struct H5EA_dblock_t { + /* Information for H5AC cache functions, _must_ be first field in structure */ + H5AC_info_t cache_info; + + /* Extensible array information (stored) */ + void *elmts; /* Buffer for elements stored in data block */ + + /* Internal array information (not stored) */ + H5EA_hdr_t *hdr; /* Shared array header info */ + haddr_t addr; /* Address of this data block on disk */ + size_t size; /* Size of data block on disk */ + + /* Computed/cached values (not stored) */ + size_t nelmts; /* Number of elements in block */ +} H5EA_dblock_t; + /* Extensible array */ struct H5EA_t { H5EA_hdr_t *hdr; /* Pointer to internal extensible array header info */ @@ -463,14 +522,8 @@ H5_DLLVAR const H5AC_class_t H5AC_EARRAY_HDR[1]; /* H5EA index block inherits cache-like properties from H5AC */ H5_DLLVAR const H5AC_class_t H5AC_EARRAY_IBLOCK[1]; -/* Declare a free list to manage the H5EA_hdr_t struct */ -H5FL_EXTERN(H5EA_hdr_t); - -/* Declare a free list to manage the H5EA_iblock_t struct */ -H5FL_EXTERN(H5EA_iblock_t); - -/* Declare a free list to manage the index block elements */ -H5FL_BLK_EXTERN(elmt_buf); +/* H5EA data block inherits cache-like properties from H5AC */ +H5_DLLVAR const H5AC_class_t H5AC_EARRAY_DBLOCK[1]; /* Internal extensible array testing class */ #ifdef H5EA_TESTING @@ -484,13 +537,17 @@ H5_DLLVAR const H5EA_class_t H5EA_CLS_TEST[1]; /* Header routines */ H5_DLL H5EA_hdr_t *H5EA__hdr_alloc(H5F_t *f, const H5EA_class_t *cls); +H5_DLL herr_t H5EA__hdr_init(H5EA_hdr_t *hdr); H5_DLL haddr_t H5EA__hdr_create(H5F_t *f, hid_t dxpl_id, const H5EA_create_t *cparam); +H5_DLL void *H5EA__hdr_alloc_elmts(H5EA_hdr_t *hdr, size_t nelmts); +H5_DLL herr_t H5EA__hdr_free_elmts(H5EA_hdr_t *hdr, size_t nelmts, void *elmts); H5_DLL herr_t H5EA__hdr_incr(H5EA_hdr_t *hdr); H5_DLL herr_t H5EA__hdr_decr(H5EA_hdr_t *hdr); H5_DLL herr_t H5EA__hdr_fuse_incr(H5EA_hdr_t *hdr); H5_DLL size_t H5EA__hdr_fuse_decr(H5EA_hdr_t *hdr); H5_DLL herr_t H5EA__hdr_modified(H5EA_hdr_t *hdr); H5_DLL herr_t H5EA__hdr_delete(H5EA_hdr_t *hdr, hid_t dxpl_id); +H5_DLL herr_t H5EA__hdr_dest(H5EA_hdr_t *hdr); /* Index block routines */ H5_DLL H5EA_iblock_t *H5EA__iblock_alloc(H5EA_hdr_t *hdr); @@ -500,10 +557,20 @@ H5_DLL H5EA_iblock_t *H5EA__iblock_protect(H5EA_hdr_t *hdr, hid_t dxpl_id, H5_DLL herr_t H5EA__iblock_unprotect(H5EA_iblock_t *iblock, hid_t dxpl_id, unsigned cache_flags); H5_DLL herr_t H5EA__iblock_delete(H5EA_hdr_t *hdr, hid_t dxpl_id); - -/* Metadata cache callbacks */ -H5_DLL herr_t H5EA__cache_hdr_dest(H5F_t *f, H5EA_hdr_t *hdr); -H5_DLL herr_t H5EA__cache_iblock_dest(H5F_t *f, H5EA_iblock_t *iblock); +H5_DLL herr_t H5EA__iblock_dest(H5F_t *f, H5EA_iblock_t *iblock); + +/* Data block routines */ +H5_DLL H5EA_dblock_t *H5EA__dblock_alloc(H5EA_hdr_t *hdr, size_t nelmts); +H5_DLL haddr_t H5EA__dblock_create(H5EA_iblock_t *iblock, hid_t dxpl_id, + size_t nelmts); +H5_DLL unsigned H5EA__dblock_sblk_idx(const H5EA_hdr_t *hdr, hsize_t idx); +H5_DLL H5EA_dblock_t *H5EA__dblock_protect(H5EA_hdr_t *hdr, hid_t dxpl_id, + haddr_t dblk_addr, size_t dblk_nelmts, H5AC_protect_t rw); +H5_DLL herr_t H5EA__dblock_unprotect(H5EA_dblock_t *dblock, hid_t dxpl_id, + unsigned cache_flags); +H5_DLL herr_t H5EA__dblock_delete(H5EA_hdr_t *hdr, hid_t dxpl_id, + haddr_t dblk_addr, size_t dblk_nelmts); +H5_DLL herr_t H5EA__dblock_dest(H5F_t *f, H5EA_dblock_t *dblock); /* Debugging routines for dumping file structures */ H5_DLL herr_t H5EA__hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, @@ -511,6 +578,9 @@ H5_DLL herr_t H5EA__hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, H5_DLL herr_t H5EA__iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int fwidth, const H5EA_class_t *cls, haddr_t hdr_addr); +H5_DLL herr_t H5EA__dblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, + FILE *stream, int indent, int fwidth, const H5EA_class_t *cls, + haddr_t hdr_addr, size_t dblk_nelmts); /* Testing routines */ #ifdef H5EA_TESTING diff --git a/src/H5EAprivate.h b/src/H5EAprivate.h index b104fc2..f70a734 100644 --- a/src/H5EAprivate.h +++ b/src/H5EAprivate.h @@ -80,8 +80,10 @@ typedef struct H5EA_create_t { /* Extensible array metadata statistics info */ typedef struct H5EA_stat_t { + hsize_t max_idx_set; /* Highest element index stored (+1 - i.e. if element 0 has been set, this value with be '1', if no elements have been stored, this value will be '0') */ hsize_t nsuper_blks; /* # of super blocks */ hsize_t ndata_blks; /* # of data blocks */ + hsize_t nelmts; /* # of elements "realized" */ } H5EA_stat_t; /* Extensible array info (forward decl - defined in H5EApkg.h) */ diff --git a/src/H5EAstat.c b/src/H5EAstat.c index 33a8d4b..8a26e34 100644 --- a/src/H5EAstat.c +++ b/src/H5EAstat.c @@ -100,7 +100,7 @@ H5EA_get_stats(const H5EA_t *ea, H5EA_stat_t *stats)) /* Local variables */ #ifdef QAK -HDfprintf(stderr, "%s: Called\n", __func__); +HDfprintf(stderr, "%s: Called\n", FUNC); #endif /* QAK */ /* @@ -109,8 +109,8 @@ HDfprintf(stderr, "%s: Called\n", __func__); HDassert(ea); HDassert(stats); - /* Placeholder value */ - HDmemset(stats, 0, sizeof(*stats)); + /* Copy extensible array statistics */ + HDmemcpy(stats, &ea->hdr->stats, sizeof(ea->hdr->stats)); END_FUNC(PRIV) /* end H5EA_get_stats() */ diff --git a/src/H5FDpublic.h b/src/H5FDpublic.h index f83d8fe..1d5e3ae 100644 --- a/src/H5FDpublic.h +++ b/src/H5FDpublic.h @@ -96,10 +96,14 @@ typedef enum H5FD_mem_t { * Map "extensible array" index blocks to 'ohdr' type file memory, since they * are similar to extensible array header blocks. * + * Map "extensible array" data blocks to 'lheap' type file memory, since they + * are similar enough to B-tree nodes. + * * -QAK */ #define H5FD_MEM_EARRAY_HDR H5FD_MEM_OHDR #define H5FD_MEM_EARRAY_IBLOCK H5FD_MEM_OHDR +#define H5FD_MEM_EARRAY_DBLOCK H5FD_MEM_BTREE /* * A free-list map which maps all types of allocation requests to a single diff --git a/src/H5private.h b/src/H5private.h index f919491..cc9274f 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -313,6 +313,9 @@ /* (from: http://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2) */ # define POWER_OF_TWO(n) (!(n & (n - 1)) && n) +/* Raise an integer to a power of 2 */ +# define H5_EXP2(n) (1 << (n)) + /* * HDF Boolean type. */ @@ -645,6 +648,9 @@ typedef struct { #ifndef HDexp #define HDexp(X) exp(X) #endif /* HDexp */ +#ifndef HDexp2 + #define HDexp2(X) exp2(X) +#endif /* HDexp2 */ #ifndef HDfabs #define HDfabs(X) fabs(X) #endif /* HDfabs */ diff --git a/src/Makefile.am b/src/Makefile.am index a6245b7..cd8f6ac 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -51,8 +51,8 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \ H5Dio.c \ H5Distore.c H5Dmpio.c H5Doh.c H5Dscatgath.c H5Dselect.c H5Dtest.c \ H5E.c H5Edeprec.c H5Eint.c \ - H5EA.c H5EAcache.c H5EAdbg.c H5EAhdr.c H5EAiblock.c H5EAint.c \ - H5EAstat.c H5EAtest.c \ + H5EA.c H5EAcache.c H5EAdbg.c H5EAdblock.c H5EAhdr.c H5EAiblock.c \ + H5EAint.c H5EAstat.c H5EAtest.c \ H5F.c H5Fdbg.c H5Ffake.c H5Fmount.c H5Fsfile.c H5Fsuper.c H5Ftest.c \ H5FD.c H5FDcore.c \ H5FDdirect.c H5FDfamily.c H5FDlog.c H5FDmpi.c H5FDmpio.c \ diff --git a/src/Makefile.in b/src/Makefile.in index 68ff604..0856523 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -86,7 +86,7 @@ am_libhdf5_la_OBJECTS = H5.lo H5checksum.lo H5dbg.lo H5system.lo \ H5Dcontig.lo H5Ddbg.lo H5Ddeprec.lo H5Defl.lo H5Dfill.lo \ H5Dint.lo H5Dio.lo H5Distore.lo H5Dmpio.lo H5Doh.lo \ H5Dscatgath.lo H5Dselect.lo H5Dtest.lo H5E.lo H5Edeprec.lo \ - H5Eint.lo H5EA.lo H5EAcache.lo H5EAdbg.lo H5EAhdr.lo \ + H5Eint.lo H5EA.lo H5EAcache.lo H5EAdbg.lo H5EAdblock.lo H5EAhdr.lo \ H5EAiblock.lo H5EAint.lo H5EAstat.lo H5EAtest.lo H5F.lo \ H5Fdbg.lo H5Ffake.lo H5Fmount.lo H5Fsfile.lo H5Fsuper.lo \ H5Ftest.lo H5FD.lo H5FDcore.lo H5FDdirect.lo H5FDfamily.lo \ @@ -431,7 +431,7 @@ libhdf5_la_SOURCES = H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \ H5Dio.c \ H5Distore.c H5Dmpio.c H5Doh.c H5Dscatgath.c H5Dselect.c H5Dtest.c \ H5E.c H5Edeprec.c H5Eint.c \ - H5EA.c H5EAcache.c H5EAdbg.c H5EAhdr.c H5EAiblock.c H5EAint.c \ + H5EA.c H5EAcache.c H5EAdbg.c H5EAdblock.c H5EAhdr.c H5EAiblock.c H5EAint.c \ H5EAstat.c H5EAtest.c \ H5F.c H5Fdbg.c H5Ffake.c H5Fmount.c H5Fsfile.c H5Fsuper.c H5Ftest.c \ H5FD.c H5FDcore.c \ @@ -645,6 +645,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5EA.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5EAcache.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5EAdbg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5EAdblock.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5EAhdr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5EAiblock.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5EAint.Plo@am__quote@ |