summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2008-09-22 15:22:03 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2008-09-22 15:22:03 (GMT)
commit00bd6ae9c27f520b4badbe0698ea1a1e1044f305 (patch)
tree0ca87cd3b1254b3faa9fbcbea2e76d4248f9ffb9
parent0402e025278dbd5ac463ce27805231d5302def1d (diff)
downloadhdf5-00bd6ae9c27f520b4badbe0698ea1a1e1044f305.zip
hdf5-00bd6ae9c27f520b4badbe0698ea1a1e1044f305.tar.gz
hdf5-00bd6ae9c27f520b4badbe0698ea1a1e1044f305.tar.bz2
[svn-r15674] Description:
Add base support for extensible array "data blocks" to code, tests and h5debug. 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
-rw-r--r--MANIFEST1
-rw-r--r--config/gnu-flags2
-rw-r--r--src/H5AC.c1
-rw-r--r--src/H5ACprivate.h1
-rw-r--r--src/H5Cpkg.h2
-rw-r--r--src/H5EA.c145
-rw-r--r--src/H5EAcache.c538
-rw-r--r--src/H5EAdbg.c134
-rw-r--r--src/H5EAdblock.c419
-rw-r--r--src/H5EAhdr.c275
-rw-r--r--src/H5EAiblock.c179
-rw-r--r--src/H5EApkg.h106
-rw-r--r--src/H5EAprivate.h2
-rw-r--r--src/H5EAstat.c6
-rw-r--r--src/H5FDpublic.h4
-rw-r--r--src/H5private.h6
-rwxr-xr-xsrc/Makefile.am4
-rw-r--r--src/Makefile.in5
-rw-r--r--test/earray.c179
-rw-r--r--tools/misc/h5debug.c23
20 files changed, 1854 insertions, 178 deletions
diff --git a/MANIFEST b/MANIFEST
index b997acd..1996eb9 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -501,6 +501,7 @@
./src/H5EA.c
./src/H5EAcache.c
./src/H5EAdbg.c
+./src/H5EAdblock.c
./src/H5EAhdr.c
./src/H5EAiblock.c
./src/H5EAint.c
diff --git a/config/gnu-flags b/config/gnu-flags
index a8e16cb..5fd72f2 100644
--- a/config/gnu-flags
+++ b/config/gnu-flags
@@ -187,7 +187,7 @@ case "$cc_vendor-$cc_version" in
# Closer to the gcc 4.4 release, we should check for additional flags to
# include and break it out into it's own section, like the other versions
# below. -QAK
- gcc-4.3*)
+ gcc-4.[34]*)
# Replace -ansi flag with -std=c99 flag
H5_CFLAGS="`echo $H5_CFLAGS | sed -e 's/-ansi/-std=c99/g'`"
diff --git a/src/H5AC.c b/src/H5AC.c
index 8597a6f..b8c4705 100644
--- a/src/H5AC.c
+++ b/src/H5AC.c
@@ -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
diff --git a/src/H5EA.c b/src/H5EA.c
index 22be79a..d12a0c6 100644
--- a/src/H5EA.c
+++ b/src/H5EA.c
@@ -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@
diff --git a/test/earray.c b/test/earray.c
index d036109..3b33c0a 100644
--- a/test/earray.c
+++ b/test/earray.c
@@ -77,8 +77,10 @@ typedef struct earray_test_param_t {
/* Extensible array state information */
typedef struct earray_state_t {
- hsize_t nsuper_blks; /* # of super blocks */
- hsize_t ndata_blks; /* # of data blocks */
+ 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" */
} earray_state_t;
/* Local variables */
@@ -183,6 +185,10 @@ check_stats(const H5EA_t *ea, const earray_state_t *state)
FAIL_STACK_ERROR
/* Compare information */
+ if(earray_stats.max_idx_set != state->max_idx_set) {
+ HDfprintf(stdout, "earray_stats.max_idx_set = %Hu, state->max_idx_set = %Hu\n", earray_stats.max_idx_set, state->max_idx_set);
+ TEST_ERROR
+ } /* end if */
if(earray_stats.nsuper_blks != state->nsuper_blks) {
HDfprintf(stdout, "earray_stats.nsuper_blks = %Hu, state->nsuper_blks = %Hu\n", earray_stats.nsuper_blks, state->nsuper_blks);
TEST_ERROR
@@ -191,6 +197,10 @@ check_stats(const H5EA_t *ea, const earray_state_t *state)
HDfprintf(stdout, "earray_stats.ndata_blks = %Hu, state->ndata_blks = %Hu\n", earray_stats.ndata_blks, state->ndata_blks);
TEST_ERROR
} /* end if */
+ if(earray_stats.nelmts != state->nelmts) {
+ HDfprintf(stdout, "earray_stats.nelmts = %Hu, state->nelmts = %Hu\n", earray_stats.nelmts, state->nelmts);
+ TEST_ERROR
+ } /* end if */
/* All tests passed */
return(0);
@@ -339,7 +349,7 @@ error:
/*-------------------------------------------------------------------------
- * Function: shutdown_ea
+ * Function: finish
*
* Purpose: Close array, delete array, close file and verify that file
* is empty size
@@ -353,7 +363,7 @@ error:
*-------------------------------------------------------------------------
*/
static int
-shutdown_ea(hid_t file, H5F_t *f, H5EA_t *ea, haddr_t ea_addr)
+finish(hid_t file, H5F_t *f, H5EA_t *ea, haddr_t ea_addr)
{
h5_stat_size_t file_size; /* File size, after deleting array */
@@ -389,7 +399,7 @@ HDsystem("cp earray.h5 earray.h5.save");
error:
return(-1);
-} /* shutdown_ea() */
+} /* finish() */
/*-------------------------------------------------------------------------
@@ -480,6 +490,30 @@ test_create(hid_t fapl, H5EA_create_t *cparam, earray_test_param_t UNUSED *tpara
/* Indicate error */
TEST_ERROR
} /* end if */
+ HDmemcpy(&test_cparam, cparam, sizeof(test_cparam));
+ test_cparam.sup_blk_min_data_ptrs = 1;
+ H5E_BEGIN_TRY {
+ ea = H5EA_create(f, H5P_DATASET_XFER_DEFAULT, &test_cparam);
+ } H5E_END_TRY;
+ if(ea) {
+ /* Close opened extensible array */
+ H5EA_close(ea, H5P_DATASET_XFER_DEFAULT);
+
+ /* Indicate error */
+ TEST_ERROR
+ } /* end if */
+ HDmemcpy(&test_cparam, cparam, sizeof(test_cparam));
+ test_cparam.sup_blk_min_data_ptrs = 6;
+ H5E_BEGIN_TRY {
+ ea = H5EA_create(f, H5P_DATASET_XFER_DEFAULT, &test_cparam);
+ } H5E_END_TRY;
+ if(ea) {
+ /* Close opened extensible array */
+ H5EA_close(ea, H5P_DATASET_XFER_DEFAULT);
+
+ /* Indicate error */
+ TEST_ERROR
+ } /* end if */
/* Set invalid min. # of elements per data block */
HDmemcpy(&test_cparam, cparam, sizeof(test_cparam));
@@ -521,7 +555,7 @@ test_create(hid_t fapl, H5EA_create_t *cparam, earray_test_param_t UNUSED *tpara
TEST_ERROR
/* Close array, delete array, close file & verify file is empty */
- if(shutdown_ea(file, f, ea, ea_addr) < 0)
+ if(finish(file, f, ea, ea_addr) < 0)
TEST_ERROR
/* All tests passed */
@@ -591,7 +625,7 @@ test_reopen(hid_t fapl, H5EA_create_t *cparam, earray_test_param_t *tparam)
TEST_ERROR
/* Close array, delete array, close file & verify file is empty */
- if(shutdown_ea(file, f, ea, ea_addr) < 0)
+ if(finish(file, f, ea, ea_addr) < 0)
TEST_ERROR
/* All tests passed */
@@ -695,7 +729,7 @@ test_open_twice(hid_t fapl, H5EA_create_t *cparam, earray_test_param_t *tparam)
FAIL_STACK_ERROR
/* Close array, delete array, close file & verify file is empty */
- if(shutdown_ea(file2, f2, ea2, ea_addr) < 0)
+ if(finish(file2, f2, ea2, ea_addr) < 0)
TEST_ERROR
/* All tests passed */
@@ -918,6 +952,8 @@ test_set_first(hid_t fapl, H5EA_create_t *cparam, earray_test_param_t *tparam)
/* Verify array state */
HDmemset(&state, 0, sizeof(state));
+ state.max_idx_set = 1;
+ state.nelmts = (hsize_t)cparam->idx_blk_elmts;
if(check_stats(ea, &state))
TEST_ERROR
@@ -931,7 +967,7 @@ test_set_first(hid_t fapl, H5EA_create_t *cparam, earray_test_param_t *tparam)
TEST_ERROR
/* Close array, delete array, close file & verify file is empty */
- if(shutdown_ea(file, f, ea, ea_addr) < 0)
+ if(finish(file, f, ea, ea_addr) < 0)
TEST_ERROR
/* All tests passed */
@@ -1043,6 +1079,8 @@ test_set_iblock(hid_t fapl, H5EA_create_t *cparam, earray_test_param_t *tparam)
/* Verify array state */
HDmemset(&state, 0, sizeof(state));
+ state.max_idx_set = u + 1;
+ state.nelmts = (hsize_t)cparam->idx_blk_elmts;
if(check_stats(ea, &state))
TEST_ERROR
@@ -1057,7 +1095,7 @@ test_set_iblock(hid_t fapl, H5EA_create_t *cparam, earray_test_param_t *tparam)
} /* end for */
/* Close array, delete array, close file & verify file is empty */
- if(shutdown_ea(file, f, ea, ea_addr) < 0)
+ if(finish(file, f, ea, ea_addr) < 0)
TEST_ERROR
/* All tests passed */
@@ -1082,6 +1120,126 @@ error:
/*-------------------------------------------------------------------------
+ * Function: test_set_first_dblock
+ *
+ * Purpose: Set first element in extensible array's first data block
+ *
+ * Return: Success: 0
+ * Failure: 1
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, September 11, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static unsigned
+test_set_first_dblock(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 */
+ hsize_t idx; /* Index value of first element of first data block */
+ haddr_t ea_addr = HADDR_UNDEF; /* Array address in file */
+
+ /*
+ * Display testing message
+ */
+ TESTING("setting first element of array's first data block");
+
+ /* Create file & retrieve pointer to internal file object */
+ if(create_file(fapl, &file, &f) < 0)
+ TEST_ERROR
+
+ /* Create array */
+ if(create_array(f, H5P_DATASET_XFER_DEFAULT, cparam, &ea, &ea_addr) < 0)
+ TEST_ERROR
+
+ /* Verify the creation parameters */
+ if(verify_cparam(ea, cparam) < 0)
+ TEST_ERROR
+
+ /* Check for closing & re-opening the file */
+ 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
+
+ /* Compute index of first element of first data block */
+ idx = cparam->idx_blk_elmts;
+
+ /* Retrieve first element of first data block of array (not set yet) */
+ relmt = (uint64_t)0;
+ if(H5EA_get(ea, H5P_DATASET_XFER_DEFAULT, idx, &relmt) < 0)
+ FAIL_STACK_ERROR
+
+ /* Verify first element is fill value for array */
+ if(relmt != H5EA_TEST_FILL)
+ TEST_ERROR
+
+ /* Set first element of first data block */
+ welmt = (uint64_t)7;
+ if(H5EA_set(ea, H5P_DATASET_XFER_DEFAULT, idx, &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 != (idx + 1))
+ TEST_ERROR
+
+ /* Verify array state */
+ HDmemset(&state, 0, sizeof(state));
+ state.max_idx_set = idx + 1;
+ state.ndata_blks = 1;
+ state.nelmts = (hsize_t)(cparam->idx_blk_elmts + cparam->data_blk_min_elmts);
+ if(check_stats(ea, &state))
+ TEST_ERROR
+
+ /* Retrieve first element of array (set now) */
+ relmt = (uint64_t)0;
+ if(H5EA_get(ea, H5P_DATASET_XFER_DEFAULT, idx, &relmt) < 0)
+ FAIL_STACK_ERROR
+
+ /* Verify first element is value written */
+ if(relmt != welmt)
+ TEST_ERROR
+
+ /* Close array, delete array, close file & verify file is empty */
+ if(finish(file, f, ea, ea_addr) < 0)
+ TEST_ERROR
+
+ /* All tests passed */
+ PASSED()
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ if(ea)
+ H5EA_close(ea, H5P_DATASET_XFER_DEFAULT);
+ H5Fclose(file);
+ } H5E_END_TRY;
+
+ return 1;
+} /* test_set_first_dblock() */
+
+
+/*-------------------------------------------------------------------------
* Function: main
*
* Purpose: Test the extensible array code
@@ -1174,6 +1332,7 @@ main(void)
/* Basic capacity tests */
nerrors += test_set_first(fapl, &cparam, &tparam);
nerrors += test_set_iblock(fapl, &cparam, &tparam);
+ nerrors += test_set_first_dblock(fapl, &cparam, &tparam);
} /* end for */
if(nerrors)
diff --git a/tools/misc/h5debug.c b/tools/misc/h5debug.c
index 95bd345..8ae486d 100644
--- a/tools/misc/h5debug.c
+++ b/tools/misc/h5debug.c
@@ -206,15 +206,15 @@ main(int argc, char *argv[])
/*
* Open the file and get the file descriptor.
*/
- if((dxpl = H5Pcreate (H5P_DATASET_XFER))<0) {
+ if((dxpl = H5Pcreate(H5P_DATASET_XFER)) < 0) {
fprintf(stderr, "cannot create dataset transfer property list\n");
HDexit(1);
} /* end if */
- if((fapl = H5Pcreate (H5P_FILE_ACCESS))<0) {
+ if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0) {
fprintf(stderr, "cannot create file access property list\n");
HDexit(1);
} /* end if */
- if(strchr (argv[1], '%'))
+ if(strchr(argv[1], '%'))
H5Pset_fapl_family (fapl, (hsize_t)0, H5P_DEFAULT);
if((fid = H5Fopen(argv[1], H5F_ACC_RDONLY, fapl)) < 0) {
fprintf(stderr, "cannot open file\n");
@@ -464,6 +464,23 @@ main(int argc, char *argv[])
status = H5EA__iblock_debug(f, H5P_DATASET_XFER_DEFAULT, addr, stdout, 0, VCOL, cls, extra);
+ } else if(!HDmemcmp(sig, H5EA_DBLOCK_MAGIC, (size_t)H5EA_SIZEOF_MAGIC)) {
+ /*
+ * Debug an extensible aray data block.
+ */
+ const H5EA_class_t *cls = get_H5EA_class(sig);
+ HDassert(cls);
+
+ /* Check for enough valid parameters */
+ if(extra == 0 || extra2 == 0) {
+ fprintf(stderr, "ERROR: Need extensible array header address and # of elements in data block in order to dump data block\n");
+ fprintf(stderr, "Extensible array data block usage:\n");
+ fprintf(stderr, "\th5debug <filename> <data block address> <array header address> <# of elements in data block>\n");
+ HDexit(4);
+ } /* end if */
+
+ status = H5EA__dblock_debug(f, H5P_DATASET_XFER_DEFAULT, addr, stdout, 0, VCOL, cls, extra, (size_t)extra2);
+
} else if(!HDmemcmp(sig, H5O_HDR_MAGIC, (size_t)H5O_SIZEOF_MAGIC)) {
/*
* Debug v2 object header (which have signatures).