From f1d22675ffc09e604c8715b2a6a010ec21acb771 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Thu, 11 Sep 2008 09:03:23 -0500 Subject: [svn-r15614] Description: More extensible array features: add support for setting/getting elements in the array's index block. Tested on: Mac OS X/32 10.5.4 (amazon) in debug mode Mac OS X/32 10.5.4 (amazon) w/C++ & FORTRAN, w/threadsafe, in production mode FreeBSD/32 6.3 (duty) in debug mode FreeBSD/64 6.3 (liberty) w/C++ & FORTRAN, in debug mode Linux/32 2.6 (kagiso) w/PGI compilers, w/C++ & FORTRAN, w/threadsafe, in debug mode Linux/64-amd64 2.6 (smirom) w/Intel compilers w/default API=1.6.x, w/C++ & FORTRAN, in production mode Solaris/32 2.10 (linew) w/deprecated symbols disabled, w/C++ & FORTRAN, w/szip filter, in production mode Linux/64-ia64 2.6 (cobalt) w/Intel compilers, w/C++ & FORTRAN, in production mode Linux/64-ia64 2.4 (tg-login3) w/parallel, w/FORTRAN, in production mode Linux/64-amd64 2.6 (abe) w/parallel, w/FORTRAN, in production mode --- MANIFEST | 2 + src/H5AC.c | 1 + src/H5ACprivate.h | 1 + src/H5Cpkg.h | 2 +- src/H5EA.c | 218 +++++++++++++++++++++++++-------- src/H5EAcache.c | 360 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/H5EAhdr.c | 108 ++++++++-------- src/H5EAiblock.c | 325 ++++++++++++++++++++++++++++++++++++++++++++++++ src/H5EApkg.h | 71 ++++++++++- src/H5EAprivate.h | 13 +- src/H5EAstat.c | 116 ++++++++++++++++++ src/H5EAtest.c | 85 +++++++++---- src/H5FDpublic.h | 4 + src/Makefile.am | 3 +- src/Makefile.in | 8 +- test/earray.c | 80 +++++++++--- 16 files changed, 1238 insertions(+), 159 deletions(-) create mode 100644 src/H5EAiblock.c create mode 100644 src/H5EAstat.c diff --git a/MANIFEST b/MANIFEST index af9e64e..d36607e 100644 --- a/MANIFEST +++ b/MANIFEST @@ -501,9 +501,11 @@ ./src/H5EA.c ./src/H5EAcache.c ./src/H5EAhdr.c +./src/H5EAiblock.c ./src/H5EAint.c ./src/H5EApkg.h ./src/H5EAprivate.h +./src/H5EAstat.c ./src/H5EAtest.c ./src/H5F.c ./src/H5Fdbg.c diff --git a/src/H5AC.c b/src/H5AC.c index 83ab0a4..406dad3 100644 --- a/src/H5AC.c +++ b/src/H5AC.c @@ -492,6 +492,7 @@ static const char * H5AC_entry_type_names[H5AC_NTYPES] = "shared OH message master table", "shared OH message index", "extensible array headers", + "extensible array index blocks", "test entry" /* for testing only -- not used for actual files */ }; diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h index da18cd5..9568a79 100644 --- a/src/H5ACprivate.h +++ b/src/H5ACprivate.h @@ -63,6 +63,7 @@ typedef enum { H5AC_SOHM_TABLE_ID, /*shared object header message master table */ 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_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 c82443b..a2dadf1 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 17 +#define H5C__MAX_NUM_TYPE_IDS 18 #define H5C__PREFIX_LEN 32 struct H5C_t diff --git a/src/H5EA.c b/src/H5EA.c index 06a11d2..fa8cd32 100644 --- a/src/H5EA.c +++ b/src/H5EA.c @@ -116,7 +116,7 @@ H5EA_create(H5F_t *f, hid_t dxpl_id, const H5EA_create_t *cparam)) haddr_t ea_addr; /* Array header address */ #ifdef QAK -HDfprintf(stderr, "%s: Called\n", FUNC); +HDfprintf(stderr, "%s: Called\n", __func__); #endif /* QAK */ /* @@ -134,7 +134,7 @@ HDfprintf(stderr, "%s: Called\n", FUNC); H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array info") /* Lock the array header into memory */ - if(NULL == (hdr = (H5EA_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_EARRAY_HDR, ea_addr, NULL, NULL, H5AC_WRITE))) + if(NULL == (hdr = (H5EA_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_EARRAY_HDR, ea_addr, cparam->cls, NULL, H5AC_WRITE))) H5E_THROW(H5E_CANTPROTECT, "unable to load extensible array header") /* Point extensible array wrapper at header and bump it's ref count */ @@ -179,7 +179,7 @@ END_FUNC(PRIV) /* end H5EA_create() */ */ BEGIN_FUNC(PRIV, ERR, H5EA_t *, NULL, NULL, -H5EA_open(H5F_t *f, hid_t dxpl_id, haddr_t ea_addr)) +H5EA_open(H5F_t *f, hid_t dxpl_id, haddr_t ea_addr, const H5EA_class_t *cls)) /* Local variables */ H5EA_t *ea = NULL; /* Pointer to new extensible array wrapper */ @@ -190,12 +190,13 @@ H5EA_open(H5F_t *f, hid_t dxpl_id, haddr_t ea_addr)) */ HDassert(f); HDassert(H5F_addr_defined(ea_addr)); + HDassert(cls); /* Load the array header into memory */ #ifdef QAK -HDfprintf(stderr, "%s: ea_addr = %a\n", FUNC, ea_addr); +HDfprintf(stderr, "%s: ea_addr = %a\n", __func__, ea_addr); #endif /* QAK */ - if(NULL == (hdr = (H5EA_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_EARRAY_HDR, ea_addr, NULL, NULL, H5AC_READ))) + if(NULL == (hdr = (H5EA_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_EARRAY_HDR, ea_addr, cls, NULL, H5AC_READ))) H5E_THROW(H5E_CANTPROTECT, "unable to load extensible array header, address = %llu", (unsigned long_long)ea_addr) /* Check for pending array deletion */ @@ -252,7 +253,7 @@ H5EA_get_nelmts(const H5EA_t *ea, hsize_t *nelmts)) /* Local variables */ #ifdef QAK -HDfprintf(stderr, "%s: Called\n", FUNC); +HDfprintf(stderr, "%s: Called\n", __func__); #endif /* QAK */ /* @@ -261,8 +262,8 @@ HDfprintf(stderr, "%s: Called\n", FUNC); HDassert(ea); HDassert(nelmts); - /* Placeholder value */ - *nelmts = 0; + /* Retrieve the max. index set */ + *nelmts = ea->hdr->max_idx_set; END_FUNC(PRIV) /* end H5EA_get_nelmts() */ @@ -287,7 +288,7 @@ H5EA_get_addr(const H5EA_t *ea, haddr_t *addr)) /* Local variables */ #ifdef QAK -HDfprintf(stderr, "%s: Called\n", FUNC); +HDfprintf(stderr, "%s: Called\n", __func__); #endif /* QAK */ /* @@ -304,93 +305,159 @@ END_FUNC(PRIV) /* end H5EA_get_addr() */ /*------------------------------------------------------------------------- - * Function: H5EA_get_stats + * Function: H5EA_set * - * Purpose: Query the metadata stats of an array + * Purpose: Set an element of an extensible array * * Return: SUCCEED/FAIL * * Programmer: Quincey Koziol * koziol@hdfgroup.org - * Aug 21 2008 + * Sep 9 2008 * *------------------------------------------------------------------------- */ -BEGIN_FUNC(PRIV, NOERR, -herr_t, SUCCEED, -, -H5EA_get_stats(const H5EA_t *ea, H5EA_stat_t *stats)) +BEGIN_FUNC(PRIV, ERR, +herr_t, SUCCEED, FAIL, +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 */ + hbool_t hdr_dirty = FALSE; /* Whether header information changed */ #ifdef QAK -HDfprintf(stderr, "%s: Called\n", FUNC); +HDfprintf(stderr, "%s: Called\n", __func__); +HDfprintf(stderr, "%s: Index %Hu\n", __func__, idx); #endif /* QAK */ /* * Check arguments. */ HDassert(ea); - HDassert(stats); + HDassert(ea->hdr); - /* Placeholder value */ - HDmemset(stats, 0, sizeof(*stats)); + /* Set the shared array header's file context for this operation */ + hdr->f = ea->f; -END_FUNC(PRIV) /* end H5EA_get_stats() */ + /* Check if we should create the index block */ + if(!H5F_addr_defined(hdr->idx_blk_addr)) { +#ifdef QAK +HDfprintf(stderr, "%s: Index block address not defined!\n", __func__, idx); +#endif /* QAK */ + /* Create the index block */ + hdr->idx_blk_addr = H5EA__iblock_create(hdr, dxpl_id); + if(!H5F_addr_defined(hdr->idx_blk_addr)) + H5E_THROW(H5E_CANTCREATE, "unable to create index block") + + /* Mark the header dirty */ + hdr_dirty = TRUE; + } /* end if */ +#ifdef QAK +HDfprintf(stderr, "%s: Index block address is: %a\n", __func__, hdr->idx_blk_addr); +#endif /* QAK */ + + /* Protect index block */ + 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 */ + 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); + } /* end if */ + else { +HDfprintf(stderr, "%s: Index %Hu not supported yet!\n", __func__, idx); +HDassert(0 && "Index location not supported!"); + } /* end else */ + + /* Update max. element set in array, if appropriate */ + if(idx >= hdr->max_idx_set) { + hdr->max_idx_set = idx + 1; + hdr_dirty = TRUE; + } /* end if */ + +CATCH + /* Check for header modified */ + if(hdr_dirty) + 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) + H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array index block") + +END_FUNC(PRIV) /* end H5EA_set() */ /*------------------------------------------------------------------------- - * Function: H5EA_delete + * Function: H5EA_get * - * Purpose: Delete an extensible array + * Purpose: Get an element of an extensible array * * Return: SUCCEED/FAIL * * Programmer: Quincey Koziol * koziol@hdfgroup.org - * Aug 28 2008 + * Sep 11 2008 * *------------------------------------------------------------------------- */ BEGIN_FUNC(PRIV, ERR, herr_t, SUCCEED, FAIL, -H5EA_delete(H5F_t *f, hid_t dxpl_id, haddr_t ea_addr)) +H5EA_get(const H5EA_t *ea, hid_t dxpl_id, hsize_t idx, void *elmt)) /* Local variables */ - H5EA_hdr_t *hdr = NULL; /* The fractal heap header information */ + H5EA_hdr_t *hdr = ea->hdr; /* Header for EA */ + H5EA_iblock_t *iblock = NULL; /* Pointer to index block for EA */ + +#ifdef QAK +HDfprintf(stderr, "%s: Called\n", __func__); +HDfprintf(stderr, "%s: Index %Hu\n", __func__, idx); +#endif /* QAK */ /* * Check arguments. */ - HDassert(f); - HDassert(H5F_addr_defined(ea_addr)); + HDassert(ea); + HDassert(ea->hdr); - /* Lock the array header into memory */ + /* Set the shared array header's file context for this operation */ + hdr->f = ea->f; + + /* Check for element beyond max. element in array */ + if(idx >= hdr->max_idx_set) { #ifdef QAK -HDfprintf(stderr, "%s: ea_addr = %a\n", FUNC, ea_addr); +HDfprintf(stderr, "%s: Element beyond max. index set\n", __func__, idx); #endif /* QAK */ - if(NULL == (hdr = (H5EA_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_EARRAY_HDR, ea_addr, NULL, NULL, H5AC_WRITE))) - H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array header, address = %llu", (unsigned long_long)ea_addr) - - /* Check for files using shared array header */ - if(hdr->file_rc) - hdr->pending_delete = TRUE; + /* 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 { - /* Set the shared array header's file context for this operation */ - hdr->f = f; +#ifdef QAK +HDfprintf(stderr, "%s: Index block address is: %a\n", __func__, hdr->idx_blk_addr); +#endif /* QAK */ - /* Delete array now, starting with header (unprotects header) */ - if(H5EA__hdr_delete(hdr, dxpl_id) < 0) - H5E_THROW(H5E_CANTDELETE, "unable to delete extensible array") - hdr = NULL; - } /* end if */ + /* Protect index block */ + 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) -CATCH + /* Determine where the element to set falls */ + 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!"); + } /* end else */ + } /* end else */ - /* Unprotect the header, if an error occurred */ - if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_EARRAY_HDR, ea_addr, hdr, H5AC__NO_FLAGS_SET) < 0) - H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array header") +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") -END_FUNC(PRIV) /* end H5EA_delete() */ +END_FUNC(PRIV) /* end H5EA_set() */ /*------------------------------------------------------------------------- @@ -415,7 +482,7 @@ H5EA_close(H5EA_t *ea, hid_t dxpl_id)) haddr_t ea_addr = HADDR_UNDEF; /* Address of array (for deletion) */ #ifdef QAK -HDfprintf(stderr, "%s: Called\n", FUNC); +HDfprintf(stderr, "%s: Called\n", __func__); #endif /* QAK */ /* @@ -470,3 +537,58 @@ CATCH END_FUNC(PRIV) /* end H5EA_close() */ + +/*------------------------------------------------------------------------- + * Function: H5EA_delete + * + * Purpose: Delete an extensible array + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Aug 28 2008 + * + *------------------------------------------------------------------------- + */ +BEGIN_FUNC(PRIV, ERR, +herr_t, SUCCEED, FAIL, +H5EA_delete(H5F_t *f, hid_t dxpl_id, haddr_t ea_addr)) + + /* Local variables */ + H5EA_hdr_t *hdr = NULL; /* The fractal heap header information */ + + /* + * Check arguments. + */ + HDassert(f); + HDassert(H5F_addr_defined(ea_addr)); + + /* Lock the array header into memory */ +#ifdef QAK +HDfprintf(stderr, "%s: ea_addr = %a\n", __func__, ea_addr); +#endif /* QAK */ + if(NULL == (hdr = (H5EA_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_EARRAY_HDR, ea_addr, NULL, NULL, H5AC_WRITE))) + H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array header, address = %llu", (unsigned long_long)ea_addr) + + /* Check for files using shared array header */ + if(hdr->file_rc) + hdr->pending_delete = TRUE; + else { + /* Set the shared array header's file context for this operation */ + hdr->f = f; + + /* Delete array now, starting with header (unprotects header) */ + if(H5EA__hdr_delete(hdr, dxpl_id) < 0) + H5E_THROW(H5E_CANTDELETE, "unable to delete extensible array") + hdr = NULL; + } /* end if */ + +CATCH + + /* Unprotect the header, if an error occurred */ + if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_EARRAY_HDR, ea_addr, hdr, H5AC__NO_FLAGS_SET) < 0) + H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array header") + +END_FUNC(PRIV) /* end H5EA_delete() */ + diff --git a/src/H5EAcache.c b/src/H5EAcache.c index a6e8178..6e141e9 100644 --- a/src/H5EAcache.c +++ b/src/H5EAcache.c @@ -52,9 +52,11 @@ /* Fractal heap format version #'s */ #define H5EA_HDR_VERSION 0 /* Header */ +#define H5EA_IBLOCK_VERSION 0 /* Index block */ -/* Size of stack buffer for serialized headers */ +/* Size of stack buffer for serialization buffers */ #define H5EA_HDR_BUF_SIZE 512 +#define H5EA_IBLOCK_BUF_SIZE 512 /******************/ @@ -76,6 +78,10 @@ static H5EA_hdr_t *H5EA__cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, c 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_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 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_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); /*********************/ @@ -92,6 +98,16 @@ const H5AC_class_t H5AC_EARRAY_HDR[1] = {{ (H5AC_size_func_t)H5EA__cache_hdr_size, }}; +/* H5EA index block inherits cache-like properties from H5AC */ +const H5AC_class_t H5AC_EARRAY_IBLOCK[1] = {{ + H5AC_EARRAY_IBLOCK_ID, + (H5AC_load_func_t)H5EA__cache_iblock_load, + (H5AC_flush_func_t)H5EA__cache_iblock_flush, + (H5AC_dest_func_t)H5EA__cache_iblock_dest, + (H5AC_clear_func_t)H5EA__cache_iblock_clear, + (H5AC_size_func_t)H5EA__cache_iblock_size, +}}; + /*****************************/ /* Library Private Variables */ @@ -105,7 +121,7 @@ const H5AC_class_t H5AC_EARRAY_HDR[1] = {{ /*------------------------------------------------------------------------- - * Function: H5EA_cache_hdr_load + * Function: H5EA__cache_hdr_load * * Purpose: Loads an extensible array header from the disk. * @@ -120,9 +136,11 @@ const H5AC_class_t H5AC_EARRAY_HDR[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 UNUSED *udata1, void UNUSED *udata2)) +H5EA__cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_cls, void UNUSED *udata2)) - H5EA_hdr_t *hdr = NULL; /* Fractal heap info */ + /* Local variables */ + const H5EA_class_t *cls = (const H5EA_class_t *)_cls; /* Extensible array class */ + H5EA_hdr_t *hdr = NULL; /* Extensible array info */ size_t size; /* Header size */ H5WB_t *wb = NULL; /* Wrapped buffer for header data */ uint8_t hdr_buf[H5EA_HDR_BUF_SIZE]; /* Buffer for header */ @@ -136,17 +154,17 @@ H5EA__cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *u HDassert(H5F_addr_defined(addr)); /* Allocate space for the extensible array data structure */ - if(NULL == (hdr = H5EA__hdr_alloc(f))) + if(NULL == (hdr = H5EA__hdr_alloc(f, cls))) H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array shared header") /* Set the extensible array header's address */ hdr->addr = addr; - /* Wrap the local buffer for serialized header info */ + /* Wrap the local buffer for serialized info */ if(NULL == (wb = H5WB_wrap(hdr_buf, sizeof(hdr_buf)))) H5E_THROW(H5E_CANTINIT, "can't wrap buffer") - /* Compute the 'base' size of the fractal heap header on disk */ + /* Compute the 'base' size of the extensible array header on disk */ size = H5EA_HEADER_SIZE(hdr); /* Get a pointer to a buffer that's large enough for serialized header */ @@ -176,6 +194,10 @@ H5EA__cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *u hdr->data_blk_min_elmts = *p++; /* Min. # of elements per data block */ hdr->sup_blk_min_data_ptrs = *p++; /* Min. # of data block pointers for a super block */ + /* 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) */ + /* Sanity check */ /* (allow for checksum not decoded yet) */ HDassert((size_t)(p - buf) == (size - H5EA_SIZEOF_CHKSUM)); @@ -247,7 +269,7 @@ H5EA__cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5 if(NULL == (wb = H5WB_wrap(hdr_buf, sizeof(hdr_buf)))) H5E_THROW(H5E_CANTINIT, "can't wrap buffer") - /* Compute the size of the heap header on disk */ + /* Compute the size of the array header on disk */ size = hdr->size; /* Get a pointer to a buffer that's large enough for serialized header */ @@ -271,6 +293,10 @@ H5EA__cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5 *p++ = hdr->data_blk_min_elmts; /* Min. # of elements per data block */ *p++ = hdr->sup_blk_min_data_ptrs; /* Min. # of data block pointers for a super block */ + /* 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) */ + /* Compute metadata checksum */ metadata_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0); @@ -392,3 +418,321 @@ H5EA__cache_hdr_size(const H5F_t UNUSED *f, const H5EA_hdr_t *hdr, size_t *size_ END_FUNC(STATIC) /* end H5EA__cache_hdr_size() */ + +/*------------------------------------------------------------------------- + * Function: H5EA__cache_iblock_load + * + * Purpose: Loads an extensible array index block from the disk. + * + * Return: Success: Pointer to a new extensible array index block + * Failure: NULL + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 9 2008 + * + *------------------------------------------------------------------------- + */ +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)) + + /* Local variables */ + H5EA_hdr_t *hdr = (H5EA_hdr_t *)_hdr; /* Shared extensible array information */ + H5EA_iblock_t *iblock = NULL; /* Index block info */ + size_t size; /* Index block size */ + H5WB_t *wb = NULL; /* Wrapped buffer for index block data */ + uint8_t iblock_buf[H5EA_IBLOCK_BUF_SIZE]; /* Buffer for index block */ + uint8_t *buf; /* Pointer to index 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 */ + + /* Sanity check */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(hdr); + + /* 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") + + /* Set the extensible array index block's address */ + iblock->addr = addr; + + /* Wrap the local buffer for serialized info */ + if(NULL == (wb = H5WB_wrap(iblock_buf, sizeof(iblock_buf)))) + H5E_THROW(H5E_CANTINIT, "can't wrap buffer") + + /* Compute the size of the extensible array index block on disk */ + size = H5EA_IBLOCK_SIZE(hdr); + + /* 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 index block from disk */ + if(H5F_block_read(f, H5FD_MEM_EARRAY_IBLOCK, addr, size, dxpl_id, buf) < 0) + H5E_THROW(H5E_READERROR, "can't read extensible array index block") + + /* Get temporary pointer to serialized header */ + p = buf; + + /* Magic number */ + if(HDmemcmp(p, H5EA_IBLOCK_MAGIC, (size_t)H5EA_SIZEOF_MAGIC)) + H5E_THROW(H5E_BADVALUE, "wrong extensible array index block signature") + p += H5EA_SIZEOF_MAGIC; + + /* Version */ + if(*p++ != H5EA_IBLOCK_VERSION) + H5E_THROW(H5E_VERSION, "wrong extensible array index block version") + + /* Internal information */ + + /* Decode elements in index block */ + if(hdr->idx_blk_elmts > 0) { + /* Convert from raw elements on disk into native elements in memory */ + if((hdr->cls->decode)(p, iblock->elmts, (size_t)hdr->idx_blk_elmts) < 0) + H5E_THROW(H5E_CANTDECODE, "can't decode extensible array index elements") + p += (hdr->idx_blk_elmts * hdr->raw_elmt_size); + } /* end if */ + + /* Sanity check */ + /* (allow for checksum not decoded yet) */ + HDassert((size_t)(p - buf) == (size - H5EA_SIZEOF_CHKSUM)); + + /* Save the index block's size */ + iblock->size = size; + + /* Compute checksum on index 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) == iblock->size); + + /* Verify checksum */ + if(stored_chksum != computed_chksum) + H5E_THROW(H5E_BADVALUE, "incorrect metadata checksum for extensible array index block") + + /* Set return value */ + ret_value = iblock; + +CATCH + + /* Release resources */ + if(wb && H5WB_unwrap(wb) < 0) + H5E_THROW(H5E_CLOSEERROR, "can't close wrapped buffer") + if(!ret_value) + if(iblock && H5EA__cache_iblock_dest(f, iblock) < 0) + H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array index block") + +END_FUNC(STATIC) /* end H5EA__cache_iblock_load() */ + + +/*------------------------------------------------------------------------- + * Function: H5EA__cache_iblock_flush + * + * Purpose: Flushes a dirty extensible array index block to disk. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 9 2008 + * + *------------------------------------------------------------------------- + */ +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)) + + /* Local variables */ + H5WB_t *wb = NULL; /* Wrapped buffer for serializing data */ + uint8_t ser_buf[H5EA_HDR_BUF_SIZE]; /* Serialization buffer */ + + /* Sanity check */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(iblock); + HDassert(iblock->hdr); + + if(iblock->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 index block on disk */ + size = iblock->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_IBLOCK_MAGIC, (size_t)H5EA_SIZEOF_MAGIC); + p += H5EA_SIZEOF_MAGIC; + + /* Version # */ + *p++ = H5EA_IBLOCK_VERSION; + + /* Internal information */ + + /* Encode elements in index block */ + if(iblock->hdr->idx_blk_elmts > 0) { + /* Convert from native elements in memory into raw elements on disk */ + if((iblock->hdr->cls->encode)(p, iblock->elmts, (size_t)iblock->hdr->idx_blk_elmts) < 0) + H5E_THROW(H5E_CANTENCODE, "can't encode extensible array index elements") + p += (iblock->hdr->idx_blk_elmts * iblock->hdr->raw_elmt_size); + } /* end if */ + + /* 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_IBLOCK, addr, size, dxpl_id, buf) < 0) + H5E_THROW(H5E_WRITEERROR, "unable to save extensible array index block to disk") + + iblock->cache_info.is_dirty = FALSE; + } /* end if */ + + if(destroy) + if(H5EA__cache_iblock_dest(f, iblock) < 0) + H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array index 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_iblock_flush() */ + + +/*------------------------------------------------------------------------- + * Function: H5EA__cache_iblock_dest + * + * Purpose: Destroys a extensible array index block in memory. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 9 2008 + * + *------------------------------------------------------------------------- + */ +/* ARGSUSED */ +BEGIN_FUNC(PKG, ERR, +herr_t, SUCCEED, FAIL, +H5EA__cache_iblock_dest(H5F_t UNUSED *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(elmt_buf, iblock->elmts); + } /* 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__cache_iblock_dest() */ + + +/*------------------------------------------------------------------------- + * 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)) + + /* + * Check arguments. + */ + 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() */ + diff --git a/src/H5EAhdr.c b/src/H5EAhdr.c index 5fbcaf9..9ccec62 100644 --- a/src/H5EAhdr.c +++ b/src/H5EAhdr.c @@ -52,6 +52,7 @@ /* Max. # of bits for max. nelmts index */ #define H5EA_MAX_NELMTS_IDX_MAX 64 + /******************/ /* Local Typedefs */ /******************/ @@ -101,14 +102,14 @@ H5FL_DEFINE(H5EA_hdr_t); */ BEGIN_FUNC(PKG, ERR, H5EA_hdr_t *, NULL, NULL, -H5EA__hdr_alloc(H5F_t *f)) +H5EA__hdr_alloc(H5F_t *f, const H5EA_class_t *cls)) - H5EA_hdr_t *hdr = NULL; /* Shared fractal heap header */ + /* Local variables */ + H5EA_hdr_t *hdr = NULL; /* Shared extensible array header */ - /* - * Check arguments. - */ + /* Check arguments */ HDassert(f); + HDassert(cls); /* Allocate space for the shared information */ if(NULL == (hdr = H5FL_CALLOC(H5EA_hdr_t))) @@ -116,6 +117,11 @@ H5EA__hdr_alloc(H5F_t *f)) /* Set the internal parameters for the array */ hdr->f = f; + hdr->sizeof_addr = H5F_SIZEOF_ADDR(f); + hdr->sizeof_size = H5F_SIZEOF_SIZE(f); + + /* Set the class of the array */ + hdr->cls = cls; /* Set the return value */ ret_value = hdr; @@ -129,7 +135,7 @@ END_FUNC(PKG) /* end H5EA__hdr_alloc() */ /*------------------------------------------------------------------------- - * Function: H5EA_hdr_create + * Function: H5EA__hdr_create * * Purpose: Creates a new extensible array header in the file * @@ -145,15 +151,14 @@ BEGIN_FUNC(PKG, ERR, haddr_t, HADDR_UNDEF, HADDR_UNDEF, H5EA__hdr_create(H5F_t *f, hid_t dxpl_id, const H5EA_create_t *cparam)) + /* Local variables */ 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. - */ + /* Check arguments */ HDassert(f); HDassert(cparam); @@ -172,10 +177,11 @@ HDfprintf(stderr, "%s: Called\n", FUNC); #endif /* NDEBUG */ /* Allocate space for the shared information */ - if(NULL == (hdr = H5EA__hdr_alloc(f))) + if(NULL == (hdr = H5EA__hdr_alloc(f, cparam->cls))) H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array shared header") /* Set the internal parameters for the array */ + hdr->idx_blk_addr = HADDR_UNDEF; /* Set the creation parameters for the array */ hdr->raw_elmt_size = cparam->raw_elmt_size; @@ -198,14 +204,13 @@ HDfprintf(stderr, "%s: Called\n", FUNC); /* Set address of array header to return */ ret_value = hdr->addr; - CATCH END_FUNC(PKG) /* end H5EA__hdr_create() */ /*------------------------------------------------------------------------- - * Function: H5EA_hdr_incr + * Function: H5EA__hdr_incr * * Purpose: Increment component reference count on shared array header * @@ -238,7 +243,7 @@ END_FUNC(PKG) /* end H5EA__hdr_incr() */ /*------------------------------------------------------------------------- - * Function: H5EA_hdr_decr + * Function: H5EA__hdr_decr * * Purpose: Decrement component reference count on shared array header * @@ -274,7 +279,7 @@ END_FUNC(PKG) /* end H5EA__hdr_decr() */ /*------------------------------------------------------------------------- - * Function: H5EA_hdr_fuse_incr + * Function: H5EA__hdr_fuse_incr * * Purpose: Increment file reference count on shared array header * @@ -300,7 +305,7 @@ END_FUNC(PKG) /* end H5EA__hdr_fuse_incr() */ /*------------------------------------------------------------------------- - * Function: H5EA_hdr_fuse_decr + * Function: H5EA__hdr_fuse_decr * * Purpose: Decrement file reference count on shared array header * @@ -330,6 +335,36 @@ END_FUNC(PKG) /* end H5EA__hdr_fuse_decr() */ /*------------------------------------------------------------------------- + * Function: H5EA__hdr_modified + * + * Purpose: Mark an extensible array as modified + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 9 2008 + * + *------------------------------------------------------------------------- + */ +BEGIN_FUNC(PKG, ERR, +herr_t, SUCCEED, FAIL, +H5EA__hdr_modified(H5EA_hdr_t *hdr)) + + /* Sanity check */ + HDassert(hdr); + HDassert(hdr->f); + + /* Mark header as dirty in cache */ + if(H5AC_mark_pinned_or_protected_entry_dirty(hdr->f, hdr) < 0) + H5E_THROW(H5E_CANTMARKDIRTY, "unable to mark extensible array header as dirty") + +CATCH + +END_FUNC(PKG) /* end H5EA__hdr_modified() */ + + +/*------------------------------------------------------------------------- * Function: H5EA__hdr_delete * * Purpose: Delete an extensible array, starting with the header @@ -346,9 +381,7 @@ BEGIN_FUNC(PKG, ERR, herr_t, SUCCEED, FAIL, H5EA__hdr_delete(H5EA_hdr_t *hdr, hid_t dxpl_id)) - /* - * Check arguments. - */ + /* Sanity check */ HDassert(hdr); HDassert(!hdr->file_rc); @@ -366,40 +399,15 @@ H5EA__hdr_delete(H5EA_hdr_t *hdr, hid_t dxpl_id)) } /* end block */ #endif /* NDEBUG */ -#ifdef LATER - /* Check for root direct/indirect block */ - if(H5F_addr_defined(hdr->man_dtable.table_addr)) { + /* Check for index block */ + if(H5F_addr_defined(hdr->idx_blk_addr)) { #ifdef QAK -HDfprintf(stderr, "%s: hdr->man_dtable.table_addr = %a\n", FUNC, hdr->man_dtable.table_addr); +HDfprintf(stderr, "%s: hdr->idx_blk_addr = %a\n", __func__, hdr->idx_blk_addr); #endif /* QAK */ - if(hdr->man_dtable.curr_root_rows == 0) { - hsize_t dblock_size; /* Size of direct block */ - - /* Check for I/O filters on this heap */ - if(hdr->filter_len > 0) { - dblock_size = (hsize_t)hdr->pline_root_direct_size; -#ifdef QAK -HDfprintf(stderr, "%s: hdr->pline_root_direct_size = %Zu\n", FUNC, hdr->pline_root_direct_size); -#endif /* QAK */ - - /* Reset the header's pipeline information */ - hdr->pline_root_direct_size = 0; - hdr->pline_root_direct_filter_mask = 0; - } /* end else */ - else - dblock_size = (hsize_t)hdr->man_dtable.cparam.start_block_size; - - /* Delete root direct block */ - if(H5HF_man_dblock_delete(hdr->f, dxpl_id, hdr->man_dtable.table_addr, dblock_size) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to release fractal heap root direct block") - } /* end if */ - else { - /* Delete root indirect block */ - if(H5HF_man_iblock_delete(hdr, dxpl_id, hdr->man_dtable.table_addr, hdr->man_dtable.curr_root_rows, NULL, 0) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to release fractal heap root indirect block") - } /* end else */ + /* Delete index block */ + if(H5EA__iblock_delete(hdr, dxpl_id) < 0) + H5E_THROW(H5E_CANTDELETE, "unable to delete extensible array index block") } /* end if */ -#endif /* LATER */ /* Release header's disk space */ if(H5MF_xfree(hdr->f, H5FD_MEM_EARRAY_HDR, dxpl_id, hdr->addr, (hsize_t)hdr->size) < 0) diff --git a/src/H5EAiblock.c b/src/H5EAiblock.c new file mode 100644 index 0000000..2e924a9 --- /dev/null +++ b/src/H5EAiblock.c @@ -0,0 +1,325 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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: H5EAiblock.c + * Sep 9 2008 + * Quincey Koziol + * + * Purpose: Index 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 "H5MFprivate.h" /* File memory management */ + + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + +/* Declare a free list to manage the H5EA_iblock_t struct */ +H5FL_DEFINE(H5EA_iblock_t); + +/* Declare a free list to manage the index block elements */ +H5FL_BLK_DEFINE(elmt_buf); + + + +/*------------------------------------------------------------------------- + * Function: H5EA__iblock_alloc + * + * Purpose: Allocate shared extensible array index block + * + * Return: Non-NULL pointer to index block on success/NULL on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 9 2008 + * + *------------------------------------------------------------------------- + */ +BEGIN_FUNC(PKG, ERR, +H5EA_iblock_t *, NULL, NULL, +H5EA__iblock_alloc(H5EA_hdr_t *hdr)) + + /* Local variables */ + H5EA_iblock_t *iblock = NULL; /* Extensible array index block */ + + /* Check arguments */ + HDassert(hdr); + + /* Allocate memory for the index block */ + if(NULL == (iblock = H5FL_CALLOC(H5EA_iblock_t))) + H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array index block") + + /* Set non-zero internal fields */ + iblock->addr = HADDR_UNDEF; + + /* 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)))) + H5E_THROW(H5E_CANTALLOC, "memory allocation failed for index block data element buffer") + + /* Set the return value */ + ret_value = iblock; + +CATCH + if(!ret_value) + if(iblock && H5EA__cache_iblock_dest(hdr->f, iblock) < 0) + H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array index block") + +END_FUNC(PKG) /* end H5EA__iblock_alloc() */ + + +/*------------------------------------------------------------------------- + * Function: H5EA__iblock_create + * + * Purpose: Creates a new extensible array index 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__iblock_create(H5EA_hdr_t *hdr, hid_t dxpl_id)) + + /* Local variables */ + H5EA_iblock_t *iblock = NULL; /* Extensible array index block */ + +#ifdef QAK +HDfprintf(stderr, "%s: Called\n", __func__); +#endif /* QAK */ + + /* Sanity check */ + HDassert(hdr); + + /* Allocate the index block */ + 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); +#ifdef QAK +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 */ + if((hdr->cls->fill)(iblock->elmts, (size_t)hdr->idx_blk_elmts) < 0) + H5E_THROW(H5E_CANTSET, "can't set extensible array index block elements to class's fill value") + } /* 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") + + /* Set address of index block to return */ + ret_value = iblock->addr; + +CATCH + if(!H5F_addr_defined(ret_value)) + if(iblock) { + /* Release index block's disk space */ + if(H5F_addr_defined(iblock->addr) && H5MF_xfree(hdr->f, H5FD_MEM_EARRAY_IBLOCK, dxpl_id, iblock->addr, (hsize_t)iblock->size) < 0) + H5E_THROW(H5E_CANTFREE, "unable to release extensible array index block") + + /* Destroy index block */ + if(H5EA__cache_iblock_dest(hdr->f, iblock) < 0) + H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array index block") + } /* end if */ + +END_FUNC(PKG) /* end H5EA__iblock_create() */ + + +/*------------------------------------------------------------------------- + * Function: H5EA__iblock_protect + * + * Purpose: Convenience wrapper around protecting extensible array index block + * + * Return: Non-NULL pointer to index block on success/NULL on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 9 2008 + * + *------------------------------------------------------------------------- + */ +BEGIN_FUNC(PKG, ERR, +H5EA_iblock_t *, NULL, NULL, +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__); +#endif /* QAK */ + + /* Sanity check */ + HDassert(hdr); + + /* Protect the index block */ + if(NULL == (ret_value = (H5EA_iblock_t *)H5AC_protect(hdr->f, dxpl_id, H5AC_EARRAY_IBLOCK, hdr->idx_blk_addr, NULL, hdr, rw))) + H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array index block, address = %llu", (unsigned long_long)hdr->idx_blk_addr) + +CATCH + +END_FUNC(PKG) /* end H5EA__iblock_protect() */ + + +/*------------------------------------------------------------------------- + * Function: H5EA__iblock_unprotect + * + * Purpose: Convenience wrapper around unprotecting extensible array index block + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 9 2008 + * + *------------------------------------------------------------------------- + */ +BEGIN_FUNC(PKG, ERR, +herr_t, SUCCEED, FAIL, +H5EA__iblock_unprotect(H5EA_iblock_t *iblock, hid_t dxpl_id, unsigned cache_flags)) + + /* Local variables */ + +#ifdef QAK +HDfprintf(stderr, "%s: Called\n", __func__); +#endif /* QAK */ + + /* Sanity check */ + HDassert(iblock); + + /* Unprotect the index block */ + if(H5AC_unprotect(iblock->hdr->f, dxpl_id, H5AC_EARRAY_IBLOCK, iblock->addr, iblock, cache_flags) < 0) + H5E_THROW(H5E_CANTUNPROTECT, "unable to unprotect extensible array index block, address = %llu", (unsigned long_long)iblock->addr) + +CATCH + +END_FUNC(PKG) /* end H5EA__iblock_unprotect() */ + + +/*------------------------------------------------------------------------- + * Function: H5EA__iblock_delete + * + * Purpose: Delete index block + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 9 2008 + * + *------------------------------------------------------------------------- + */ +BEGIN_FUNC(PKG, ERR, +herr_t, SUCCEED, FAIL, +H5EA__iblock_delete(H5EA_hdr_t *hdr, hid_t dxpl_id)) + + /* Local variables */ + H5EA_iblock_t *iblock = NULL; /* Pointer to index block */ + +#ifdef QAK +HDfprintf(stderr, "%s: Called\n", __func__); +#endif /* QAK */ + + /* Sanity check */ + HDassert(hdr); + HDassert(H5F_addr_defined(hdr->idx_blk_addr)); + + /* Protect index block */ + 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) */ + + /* 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) + H5E_THROW(H5E_CANTFREE, "unable to free extensible array index block") + +CATCH + /* Finished deleting index block in metadata cache */ + if(iblock && H5EA__iblock_unprotect(iblock, dxpl_id, H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG) < 0) + H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array index block") + +END_FUNC(PKG) /* end H5EA__iblock_delete() */ + diff --git a/src/H5EApkg.h b/src/H5EApkg.h index 33131bd..b0f351f 100644 --- a/src/H5EApkg.h +++ b/src/H5EApkg.h @@ -341,8 +341,14 @@ func_init_failed: \ /* Size of signature information (on disk) */ #define H5EA_SIZEOF_MAGIC 4 -/* Fractal heap signatures */ +/* Fill value for extensible array test class */ +#ifdef H5EA_TESTING +#define H5EA_TEST_FILL ((uint64_t)ULLONG_MAX) +#endif /* H5EA_TESTING */ + +/* Extensible array signatures */ #define H5EA_HDR_MAGIC "EAHD" /* Header */ +#define H5EA_IBLOCK_MAGIC "EAIB" /* Index block */ /* Size of checksum information (on disk) */ #define H5EA_SIZEOF_CHKSUM 4 @@ -359,14 +365,25 @@ func_init_failed: \ /* General metadata fields */ \ H5EA_METADATA_PREFIX_SIZE(TRUE) \ \ - /* Extensible Array Header specific fields */ \ - \ /* General heap information */ \ + 1 /* Element Size */ \ + 1 /* Max. # of elements bits */ \ + 1 /* # of elements to store in index block */ \ + 1 /* Min. # elements per data block */ \ + 1 /* Min. # of data block pointers for a super block */ \ + \ + /* Extensible Array Header specific fields */ \ + + (h)->sizeof_addr /* File address of index block */ \ + + (h)->sizeof_size /* Max. index set */ \ + ) + +/* Size of the extensible array index block on disk */ +#define H5EA_IBLOCK_SIZE(h) ( \ + /* 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 */ \ ) @@ -389,6 +406,12 @@ typedef struct H5EA_hdr_t { uint8_t data_blk_min_elmts; /* Min. # of elements per data block */ uint8_t sup_blk_min_data_ptrs; /* Min. # of data block pointers for a super block */ + /* Index block information (stored in header) */ + 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') */ + /* Computed/cached values */ size_t rc; /* Reference count of heap's components using heap header */ haddr_t addr; /* Address of header in file */ @@ -396,8 +419,28 @@ typedef struct H5EA_hdr_t { H5F_t *f; /* Pointer to file for extensible array */ size_t file_rc; /* Reference count of files using array header */ hbool_t pending_delete; /* Array is pending deletion */ + size_t sizeof_addr; /* Size of file addresses */ + size_t sizeof_size; /* Size of file sizes */ + + /* Memory data structures (not stored directly) */ + const H5EA_class_t *cls; /* Pointer to class for array */ } H5EA_hdr_t; +/* The extensible array index block information */ +typedef struct H5EA_iblock_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 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 */ +} H5EA_iblock_t; + /* Extensible array */ struct H5EA_t { H5EA_hdr_t *hdr; /* Pointer to internal extensible array header info */ @@ -412,9 +455,18 @@ struct H5EA_t { /* H5EA header inherits cache-like properties from H5AC */ 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); + /* Internal extensible array testing class */ #ifdef H5EA_TESTING H5_DLLVAR const H5EA_class_t H5EA_CLS_TEST[1]; @@ -426,16 +478,27 @@ H5_DLLVAR const H5EA_class_t H5EA_CLS_TEST[1]; /******************************/ /* Header routines */ -H5_DLL H5EA_hdr_t *H5EA__hdr_alloc(H5F_t *f); +H5_DLL H5EA_hdr_t *H5EA__hdr_alloc(H5F_t *f, const H5EA_class_t *cls); H5_DLL haddr_t H5EA__hdr_create(H5F_t *f, hid_t dxpl_id, const H5EA_create_t *cparam); 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); +/* Index block routines */ +H5_DLL H5EA_iblock_t *H5EA__iblock_alloc(H5EA_hdr_t *hdr); +H5_DLL haddr_t H5EA__iblock_create(H5EA_hdr_t *hdr, hid_t dxpl_id); +H5_DLL H5EA_iblock_t *H5EA__iblock_protect(H5EA_hdr_t *hdr, hid_t dxpl_id, + H5AC_protect_t rw); +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); /* Testing routines */ #ifdef H5EA_TESTING diff --git a/src/H5EAprivate.h b/src/H5EAprivate.h index e39cefe..5893ebb 100644 --- a/src/H5EAprivate.h +++ b/src/H5EAprivate.h @@ -62,9 +62,9 @@ typedef struct H5EA_class_t { size_t nat_elmt_size; /* Size of native (memory) element */ /* Extensible array client callback methods */ - herr_t (*fill)(uint8_t *raw_blk, size_t nelmts); /* Fill array of elements with encoded form of "missing element" value */ - herr_t (*encode)(uint8_t *raw, const void *elmt); /* Encode element from native form to disk storage form */ - herr_t (*decode)(const uint8_t *raw, void *elmt); /* Decode element from disk storage form to native form */ + herr_t (*fill)(void *nat_blk, size_t nelmts); /* Fill array of elements with encoded form of "missing element" value */ + herr_t (*encode)(void *raw, const void *elmt, size_t nelmts); /* Encode elements from native form to disk storage form */ + herr_t (*decode)(const void *raw, void *elmt, size_t nelmts); /* Decode elements from disk storage form to native form */ herr_t (*debug)(FILE *stream, int indent, int fwidth, const void *elmt); /* Print an element for debugging */ } H5EA_class_t; @@ -99,11 +99,14 @@ typedef struct H5EA_t H5EA_t; /* General routines */ H5_DLL H5EA_t *H5EA_create(H5F_t *f, hid_t dxpl_id, const H5EA_create_t *cparam); -H5_DLL H5EA_t *H5EA_open(H5F_t *f, hid_t dxpl_id, haddr_t ea_addr); +H5_DLL H5EA_t *H5EA_open(H5F_t *f, hid_t dxpl_id, haddr_t ea_addr, + const H5EA_class_t *cls); H5_DLL herr_t H5EA_get_nelmts(const H5EA_t *ea, hsize_t *nelmts); H5_DLL herr_t H5EA_get_addr(const H5EA_t *ea, haddr_t *addr); -H5_DLL herr_t H5EA_delete(H5F_t *f, hid_t dxpl_id, haddr_t ea_addr); +H5_DLL herr_t H5EA_set(const H5EA_t *ea, hid_t dxpl_id, hsize_t idx, const void *elmt); +herr_t H5EA_get(const H5EA_t *ea, hid_t dxpl_id, hsize_t idx, void *elmt); H5_DLL herr_t H5EA_close(H5EA_t *ea, hid_t dxpl_id); +H5_DLL herr_t H5EA_delete(H5F_t *f, hid_t dxpl_id, haddr_t ea_addr); /* Statistics routines */ H5_DLL herr_t H5EA_get_stats(const H5EA_t *ea, H5EA_stat_t *stats); diff --git a/src/H5EAstat.c b/src/H5EAstat.c new file mode 100644 index 0000000..8b0460c --- /dev/null +++ b/src/H5EAstat.c @@ -0,0 +1,116 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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: H5EAstat.c + * Sep 11 2009 + * Quincey Koziol + * + * Purpose: Extensible array metadata statistics functions. + * + *------------------------------------------------------------------------- + */ + +/**********************/ +/* Module Declaration */ +/**********************/ + +#define H5EA_MODULE + + +/***********************/ +/* Other Packages Used */ +/***********************/ + + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5EApkg.h" /* Extensible Arrays */ + + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + + +/*------------------------------------------------------------------------- + * Function: H5EA_get_stats + * + * Purpose: Query the metadata stats of an array + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Aug 21 2008 + * + *------------------------------------------------------------------------- + */ +BEGIN_FUNC(PRIV, NOERR, +herr_t, SUCCEED, -, +H5EA_get_stats(const H5EA_t *ea, H5EA_stat_t *stats)) + + /* Local variables */ + +#ifdef QAK +HDfprintf(stderr, "%s: Called\n", __func__); +#endif /* QAK */ + + /* + * Check arguments. + */ + HDassert(ea); + HDassert(stats); + + /* Placeholder value */ + HDmemset(stats, 0, sizeof(*stats)); + +END_FUNC(PRIV) /* end H5EA_get_stats() */ + diff --git a/src/H5EAtest.c b/src/H5EAtest.c index 0096d9c..8f2e038 100644 --- a/src/H5EAtest.c +++ b/src/H5EAtest.c @@ -39,6 +39,7 @@ #include "H5private.h" /* Generic Functions */ #include "H5Eprivate.h" /* Error handling */ #include "H5EApkg.h" /* Extensible Arrays */ +#include "H5Vprivate.h" /* Vector functions */ /****************/ @@ -61,10 +62,10 @@ /********************/ /* Extensible array class callbacks */ -static herr_t H5EA_test_fill(uint8_t *raw_blk, size_t nelmts); -static herr_t H5EA_test_encode(uint8_t *raw, const void *elmt); -static herr_t H5EA_test_decode(const uint8_t *raw, void *elmt); -static herr_t H5EA_test_debug(FILE *stream, int indent, int fwidth, const void *elmt); +static herr_t H5EA__test_fill(void *nat_blk, size_t nelmts); +static herr_t H5EA__test_encode(void *raw, const void *elmt, size_t nelmts); +static herr_t H5EA__test_decode(const void *raw, void *elmt, size_t nelmts); +static herr_t H5EA__test_debug(FILE *stream, int indent, int fwidth, const void *elmt); /*********************/ @@ -74,11 +75,11 @@ static herr_t H5EA_test_debug(FILE *stream, int indent, int fwidth, const void * /* Extensible array testing class information */ const H5EA_class_t H5EA_CLS_TEST[1]={{ H5EA_CLS_TEST_ID, /* Type of Extensible array */ - sizeof(haddr_t), /* Size of native record */ - H5EA_test_fill, /* Fill block of missing elements callback */ - H5EA_test_encode, /* Element encoding callback */ - H5EA_test_decode, /* Element decoding callback */ - H5EA_test_debug /* Element debugging callback */ + sizeof(uint64_t), /* Size of native element */ + H5EA__test_fill, /* Fill block of missing elements callback */ + H5EA__test_encode, /* Element encoding callback */ + H5EA__test_decode, /* Element decoding callback */ + H5EA__test_debug /* Element debugging callback */ }}; @@ -94,7 +95,7 @@ const H5EA_class_t H5EA_CLS_TEST[1]={{ /*------------------------------------------------------------------------- - * Function: H5EA_test_fill + * Function: H5EA__test_fill * * Purpose: Fill "missing elements" in block of elements * @@ -108,17 +109,22 @@ const H5EA_class_t H5EA_CLS_TEST[1]={{ */ BEGIN_FUNC(STATIC, NOERR, herr_t, SUCCEED, -, -H5EA_test_fill(uint8_t *raw_blk, size_t nelmts)) +H5EA__test_fill(void *nat_blk, size_t nelmts)) + + /* Local variables */ + uint64_t fill_val = H5EA_TEST_FILL; /* Value to fill elements with */ /* Sanity checks */ - HDassert(raw_blk); + HDassert(nat_blk); HDassert(nelmts); -END_FUNC(STATIC) /* end H5EA_test_fill() */ + H5V_array_fill(nat_blk, &fill_val, sizeof(uint64_t), nelmts); + +END_FUNC(STATIC) /* end H5EA__test_fill() */ /*------------------------------------------------------------------------- - * Function: H5EA_test_encode + * Function: H5EA__test_encode * * Purpose: Encode an element from "native" to "raw" form * @@ -132,17 +138,34 @@ END_FUNC(STATIC) /* end H5EA_test_fill() */ */ BEGIN_FUNC(STATIC, NOERR, herr_t, SUCCEED, -, -H5EA_test_encode(uint8_t *raw, const void *elmt)) +H5EA__test_encode(void *raw, const void *_elmt, size_t nelmts)) + + /* Local variables */ + const uint64_t *elmt = (const uint64_t *)_elmt; /* Convenience pointer to native elements */ /* Sanity checks */ HDassert(raw); HDassert(elmt); + HDassert(nelmts); + + /* Encode native elements into raw elements */ + while(nelmts) { + /* Encode element */ + /* (advances 'raw' pointer */ + UINT64ENCODE(raw, *elmt); + + /* Advance native element pointer */ + elmt++; -END_FUNC(STATIC) /* end H5EA_test_encode() */ + /* Decrement # of elements to encode */ + nelmts--; + } /* end while */ + +END_FUNC(STATIC) /* end H5EA__test_encode() */ /*------------------------------------------------------------------------- - * Function: H5EA_test_decode + * Function: H5EA__test_decode * * Purpose: Decode an element from "raw" to "native" form * @@ -156,17 +179,35 @@ END_FUNC(STATIC) /* end H5EA_test_encode() */ */ BEGIN_FUNC(STATIC, NOERR, herr_t, SUCCEED, -, -H5EA_test_decode(const uint8_t *raw, void *elmt)) +H5EA__test_decode(const void *_raw, void *_elmt, size_t nelmts)) + + /* Local variables */ + uint64_t *elmt = (uint64_t *)_elmt; /* Convenience pointer to native elements */ + const uint8_t *raw = (const uint8_t *)_raw; /* Convenience pointer to raw elements */ /* Sanity checks */ HDassert(raw); HDassert(elmt); + HDassert(nelmts); + + /* Decode raw elements into native elements */ + while(nelmts) { + /* Decode element */ + /* (advances 'raw' pointer */ + UINT64DECODE(raw, *elmt); + + /* Advance native element pointer */ + elmt++; + + /* Decrement # of elements to decode */ + nelmts--; + } /* end while */ -END_FUNC(STATIC) /* end H5EA_test_decode() */ +END_FUNC(STATIC) /* end H5EA__test_decode() */ /*------------------------------------------------------------------------- - * Function: H5EA_test_debug + * Function: H5EA__test_debug * * Purpose: Display an element for debugging * @@ -180,13 +221,13 @@ END_FUNC(STATIC) /* end H5EA_test_decode() */ */ BEGIN_FUNC(STATIC, NOERR, herr_t, SUCCEED, -, -H5EA_test_debug(FILE *stream, int indent, int fwidth, const void *elmt)) +H5EA__test_debug(FILE *stream, int indent, int fwidth, const void *elmt)) /* Sanity checks */ HDassert(stream); HDassert(elmt); -END_FUNC(STATIC) /* end H5EA_test_debug() */ +END_FUNC(STATIC) /* end H5EA__test_debug() */ /*------------------------------------------------------------------------- diff --git a/src/H5FDpublic.h b/src/H5FDpublic.h index 984edb6..f83d8fe 100644 --- a/src/H5FDpublic.h +++ b/src/H5FDpublic.h @@ -93,9 +93,13 @@ typedef enum H5FD_mem_t { * a fair amount of work to add a new kind of file memory and they are similar * enough to object headers and probably too minor to deserve their own type. * + * Map "extensible array" index blocks to 'ohdr' type file memory, since they + * are similar to extensible array header blocks. + * * -QAK */ #define H5FD_MEM_EARRAY_HDR H5FD_MEM_OHDR +#define H5FD_MEM_EARRAY_IBLOCK H5FD_MEM_OHDR /* * A free-list map which maps all types of allocation requests to a single diff --git a/src/Makefile.am b/src/Makefile.am index 161af23..6111ed0 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -51,7 +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 H5EAhdr.c H5EAint.c H5EAtest.c \ + H5EA.c H5EAcache.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 786ffff..b4900dc 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -86,8 +86,8 @@ 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 H5EAhdr.lo H5EAint.lo \ - H5EAtest.lo H5F.lo H5Fdbg.lo H5Ffake.lo H5Fmount.lo \ + H5Eint.lo H5EA.lo H5EAcache.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 H5FDlog.lo H5FDmpi.lo H5FDmpio.lo \ H5FDmpiposix.lo H5FDmulti.lo H5FDsec2.lo H5FDspace.lo \ @@ -430,7 +430,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 H5EAhdr.c H5EAint.c H5EAtest.c \ + H5EA.c H5EAcache.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 \ @@ -643,7 +643,9 @@ 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)/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@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5EAstat.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5EAtest.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Edeprec.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Eint.Plo@am__quote@ diff --git a/test/earray.c b/test/earray.c index 32b58bb..868a7ba 100644 --- a/test/earray.c +++ b/test/earray.c @@ -36,7 +36,7 @@ #define EARRAY_FILENAME_LEN 1024 /* Extensible array creation values */ -#define ELMT_SIZE sizeof(haddr_t) +#define ELMT_SIZE sizeof(uint64_t) #define MAX_NELMTS_BITS 32 #define IDX_BLK_ELMTS 4 #define SUP_BLK_MIN_DATA_PTRS 4 @@ -215,7 +215,8 @@ error: */ static int reopen_file(hid_t *file, H5F_t **f, hid_t fapl, hid_t dxpl, - H5EA_t **ea, haddr_t ea_addr, const earray_test_param_t *tparam) + H5EA_t **ea, haddr_t ea_addr, const H5EA_class_t *ea_cls, + const earray_test_param_t *tparam) { /* Check for closing & re-opening the array */ /* (actually will close & re-open the file as well) */ @@ -243,7 +244,7 @@ reopen_file(hid_t *file, H5F_t **f, hid_t fapl, hid_t dxpl, /* Re-open array, if given */ if(ea) { - if(NULL == (*ea = H5EA_open(*f, dxpl, ea_addr))) + if(NULL == (*ea = H5EA_open(*f, dxpl, ea_addr, ea_cls))) FAIL_STACK_ERROR } /* end if */ } /* end if */ @@ -281,7 +282,7 @@ create_array(H5F_t *f, hid_t dxpl, const H5EA_create_t *cparam, FAIL_STACK_ERROR /* Check status of array */ - nelmts = 0; + nelmts = (hsize_t)ULLONG_MAX; if(H5EA_get_nelmts(*ea, &nelmts) < 0) FAIL_STACK_ERROR if(nelmts > 0) @@ -572,11 +573,11 @@ test_reopen(hid_t fapl, H5EA_create_t *cparam, earray_test_param_t *tparam) FAIL_STACK_ERROR /* Check for closing & re-opening the file */ - if(reopen_file(&file, &f, fapl, H5P_DATASET_XFER_DEFAULT, NULL, HADDR_UNDEF, tparam) < 0) + if(reopen_file(&file, &f, fapl, H5P_DATASET_XFER_DEFAULT, NULL, HADDR_UNDEF, NULL, tparam) < 0) TEST_ERROR /* Re-open the array */ - if(NULL == (ea = H5EA_open(f, H5P_DATASET_XFER_DEFAULT, ea_addr))) + if(NULL == (ea = H5EA_open(f, H5P_DATASET_XFER_DEFAULT, ea_addr, cparam->cls))) FAIL_STACK_ERROR /* Verify the creation parameters */ @@ -641,7 +642,7 @@ test_open_twice(hid_t fapl, H5EA_create_t *cparam, earray_test_param_t *tparam) TEST_ERROR /* Open the array again, through the first file handle */ - if(NULL == (ea2 = H5EA_open(f, H5P_DATASET_XFER_DEFAULT, ea_addr))) + if(NULL == (ea2 = H5EA_open(f, H5P_DATASET_XFER_DEFAULT, ea_addr, cparam->cls))) FAIL_STACK_ERROR /* Verify the creation parameters */ @@ -656,7 +657,7 @@ test_open_twice(hid_t fapl, H5EA_create_t *cparam, earray_test_param_t *tparam) ea2 = NULL; /* Check for closing & re-opening the file */ - if(reopen_file(&file, &f, fapl, H5P_DATASET_XFER_DEFAULT, &ea, ea_addr, tparam) < 0) + if(reopen_file(&file, &f, fapl, H5P_DATASET_XFER_DEFAULT, &ea, ea_addr, cparam->cls, tparam) < 0) TEST_ERROR /* Re-open the file */ @@ -668,7 +669,7 @@ test_open_twice(hid_t fapl, H5EA_create_t *cparam, earray_test_param_t *tparam) FAIL_STACK_ERROR /* Open the extensible array through the second file handle */ - if(NULL == (ea2 = H5EA_open(f2, H5P_DATASET_XFER_DEFAULT, ea_addr))) + if(NULL == (ea2 = H5EA_open(f2, H5P_DATASET_XFER_DEFAULT, ea_addr, cparam->cls))) FAIL_STACK_ERROR /* Verify the creation parameters */ @@ -747,7 +748,7 @@ test_delete_open(hid_t fapl, H5EA_create_t *cparam, earray_test_param_t *tparam) TEST_ERROR /* Open the array again */ - if(NULL == (ea2 = H5EA_open(f, H5P_DATASET_XFER_DEFAULT, ea_addr))) + if(NULL == (ea2 = H5EA_open(f, H5P_DATASET_XFER_DEFAULT, ea_addr, cparam->cls))) FAIL_STACK_ERROR /* Request that the array be deleted */ @@ -767,7 +768,7 @@ test_delete_open(hid_t fapl, H5EA_create_t *cparam, earray_test_param_t *tparam) /* Try re-opening the array again (should fail, as array will be deleted) */ H5E_BEGIN_TRY { - ea2 = H5EA_open(f, H5P_DATASET_XFER_DEFAULT, ea_addr); + ea2 = H5EA_open(f, H5P_DATASET_XFER_DEFAULT, ea_addr, cparam->cls); } H5E_END_TRY; if(ea2) { /* Close opened array */ @@ -783,12 +784,12 @@ test_delete_open(hid_t fapl, H5EA_create_t *cparam, earray_test_param_t *tparam) ea = NULL; /* Check for closing & re-opening the file */ - if(reopen_file(&file, &f, fapl, H5P_DATASET_XFER_DEFAULT, NULL, HADDR_UNDEF, tparam) < 0) + if(reopen_file(&file, &f, fapl, H5P_DATASET_XFER_DEFAULT, NULL, HADDR_UNDEF, NULL, tparam) < 0) TEST_ERROR /* Try re-opening the array again (should fail, as array is now deleted) */ H5E_BEGIN_TRY { - ea = H5EA_open(f, H5P_DATASET_XFER_DEFAULT, ea_addr); + ea = H5EA_open(f, H5P_DATASET_XFER_DEFAULT, ea_addr, cparam->cls); } H5E_END_TRY; if(ea) { /* Close opened array */ @@ -847,6 +848,10 @@ test_set_first(hid_t fapl, H5EA_create_t *cparam, earray_test_param_t *tparam) hid_t file = -1; /* File ID */ H5F_t *f = NULL; /* Internal file object pointer */ H5EA_t *ea = NULL; /* Extensible array wrapper */ + earray_state_t state; /* State of extensible array */ + uint64_t welmt; /* Element to write */ + uint64_t relmt; /* Element to read */ + hsize_t nelmts; /* Highest element written in array */ haddr_t ea_addr = HADDR_UNDEF; /* Array address in file */ /* Create file & retrieve pointer to internal file object */ @@ -867,14 +872,55 @@ test_set_first(hid_t fapl, H5EA_create_t *cparam, earray_test_param_t *tparam) TEST_ERROR /* Check for closing & re-opening the file */ - if(reopen_file(&file, &f, fapl, H5P_DATASET_XFER_DEFAULT, &ea, ea_addr, tparam) < 0) + if(reopen_file(&file, &f, fapl, H5P_DATASET_XFER_DEFAULT, &ea, ea_addr, cparam->cls, tparam) < 0) + TEST_ERROR + + /* Verify high-water # of elements written */ + nelmts = (hsize_t)ULLONG_MAX; + if(H5EA_get_nelmts(ea, &nelmts) < 0) + FAIL_STACK_ERROR + if(nelmts != 0) + TEST_ERROR + + /* Verify array state */ + HDmemset(&state, 0, sizeof(state)); + if(check_stats(ea, &state)) + TEST_ERROR + + /* Retrieve first element of array (not set yet) */ + relmt = (uint64_t)0; + if(H5EA_get(ea, H5P_DATASET_XFER_DEFAULT, 0, &relmt) < 0) + FAIL_STACK_ERROR + + /* Verify first element is fill value for array */ + if(relmt != H5EA_TEST_FILL) + TEST_ERROR + + /* Set first element of array */ + welmt = (uint64_t)7; + if(H5EA_set(ea, H5P_DATASET_XFER_DEFAULT, 0, &welmt) < 0) + FAIL_STACK_ERROR + + /* Verify high-water # of elements written */ + nelmts = (hsize_t)ULLONG_MAX; + if(H5EA_get_nelmts(ea, &nelmts) < 0) + FAIL_STACK_ERROR + if(nelmts != 1) TEST_ERROR -/* Set first element of array */ + /* Verify array state */ + HDmemset(&state, 0, sizeof(state)); + if(check_stats(ea, &state)) + TEST_ERROR -/* Verify # of elements */ + /* Retrieve first element of array (set now) */ + relmt = (uint64_t)0; + if(H5EA_get(ea, H5P_DATASET_XFER_DEFAULT, 0, &relmt) < 0) + FAIL_STACK_ERROR -/* Verify array state */ + /* Verify first element is value written */ + if(relmt != welmt) + TEST_ERROR /* Close array, delete array, close file & verify file is empty */ if(shutdown(file, f, ea, ea_addr) < 0) -- cgit v0.12