summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MANIFEST1
-rw-r--r--src/H5AC.c1
-rw-r--r--src/H5ACprivate.h5
-rw-r--r--src/H5B2.c1007
-rw-r--r--src/H5B2cache.c1003
-rw-r--r--src/H5B2dbg.c3
-rw-r--r--src/H5B2pkg.h69
-rw-r--r--src/H5B2private.h7
-rw-r--r--src/H5FLprivate.h32
-rwxr-xr-xsrc/Makefile.am7
-rw-r--r--src/Makefile.in56
-rw-r--r--test/btree2.c155
12 files changed, 1590 insertions, 756 deletions
diff --git a/MANIFEST b/MANIFEST
index 3cc951a..946a797 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -775,6 +775,7 @@
./src/H5Bprivate.h
./src/H5Bpublic.h
./src/H5B2.c
+./src/H5B2cache.c
./src/H5B2dbg.c
./src/H5B2pkg.h
./src/H5B2private.h
diff --git a/src/H5AC.c b/src/H5AC.c
index e1a88a4..2f717ad 100644
--- a/src/H5AC.c
+++ b/src/H5AC.c
@@ -345,6 +345,7 @@ static const char * H5AC_entry_type_names[H5AC_NTYPES] =
"global heaps",
"object headers",
"v2 B-tree headers",
+ "v2 B-tree internal nodes",
"v2 B-tree leaf nodes"
};
diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h
index 51f5b5a..44bd862 100644
--- a/src/H5ACprivate.h
+++ b/src/H5ACprivate.h
@@ -45,8 +45,9 @@
#define H5AC_GHEAP_ID 3 /*global heap */
#define H5AC_OHDR_ID 4 /*object header */
#define H5AC_BT2_HDR_ID 5 /*v2 B-tree header */
-#define H5AC_BT2_LEAF_ID 6 /*v2 B-tree leaf */
-#define H5AC_NTYPES 7
+#define H5AC_BT2_INT_ID 6 /*v2 B-tree internal node */
+#define H5AC_BT2_LEAF_ID 7 /*v2 B-tree leaf node */
+#define H5AC_NTYPES 8
/* H5AC_DUMP_STATS_ON_CLOSE should always be FALSE when
* H5C_COLLECT_CACHE_STATS is FALSE.
diff --git a/src/H5B2.c b/src/H5B2.c
index 1307c07..99f43c4 100644
--- a/src/H5B2.c
+++ b/src/H5B2.c
@@ -38,16 +38,6 @@
/* Local macros */
-/* B-tree version #'s */
-#define H5B2_HDR_VERSION 0 /* Header */
-#define H5B2_LEAF_VERSION 0 /* Leaf node */
-
-/* Size of storage for number of records per node (on disk) */
-#define H5B2_SIZEOF_RECORDS_PER_NODE 2
-
-/* Size of a "node pointer" (on disk) */
-#define H5B2_NODE_POINTER_SIZE(f) (H5F_SIZEOF_ADDR(f)+H5B2_SIZEOF_RECORDS_PER_NODE+H5F_SIZEOF_SIZE(f))
-
/* Format overhead for each node (on disk) */
#define H5B2_OVERHEAD_SIZE (H5B2_SIZEOF_MAGIC+1) /* Signature + version # */
@@ -57,21 +47,9 @@
/* Number of records that fit into leaf node */
#define H5B2_NUM_LEAF_REC(n,r) (((n)-H5B2_OVERHEAD_SIZE)/(r))
-/* Size of the B-tree header on disk */
-#define H5B2_HEADER_SIZE(f) ( \
- 4 + /* Signature */ \
- 1 + /* Version */ \
- 1 + /* Tree type */ \
- 4 + /* Node size, in bytes */ \
- 2 + /* Key size, in bytes */ \
- 2 + /* Depth of tree */ \
- 2 + /* Split % of full (as integer, ie. "98" means 98%) */ \
- 2 + /* Merge % of full (as integer, ie. "98" means 98%) */ \
- H5B2_NODE_POINTER_SIZE(f)) /* Node pointer to root node in tree */
-
/* Macro to retrieve pointer to i'th native key for leaf node */
-#define H5B2_INT_NKEY(i,shared,idx) ((i)->int_native+(shared)->int_nat_off[(idx)])
-#define H5B2_LEAF_NKEY(l,shared,idx) ((l)->leaf_native+(shared)->leaf_nat_off[(idx)])
+#define H5B2_INT_NKEY(i,shared,idx) ((i)->int_native+(shared)->nat_off[(idx)])
+#define H5B2_LEAF_NKEY(l,shared,idx) ((l)->leaf_native+(shared)->nat_off[(idx)])
/* Local typedefs */
@@ -79,69 +57,39 @@
/* Local prototypes */
/* Helper functions */
-static herr_t H5B2_shared_free (void *_shared);
-static herr_t H5B2_shared_init (H5F_t *f, H5B2_t *bt2, const H5B2_class_t *type,
- size_t node_size, size_t rkey_size, unsigned split_percent, unsigned merge_percent);
static herr_t H5B2_create_leaf(H5F_t *f, hid_t dxpl_id, H5B2_t *bt2, H5B2_node_ptr_t *node_ptr);
static int H5B2_locate_record(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type,
unsigned nrec, size_t *rec_off, const uint8_t *native,
const void *udata);
+static herr_t H5B2_split_root(H5F_t *f, hid_t dxpl_id, H5B2_t *bt2,
+ const H5B2_shared_t *shared);
+static herr_t H5B2_create_internal(H5F_t *f, hid_t dxpl_id, H5B2_t *bt2,
+ H5B2_node_ptr_t *node_ptr);
-/* Metadata cache callbacks */
-static H5B2_t *H5B2_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_type, void *udata);
-static herr_t H5B2_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_t *b);
-static herr_t H5B2_cache_hdr_dest(H5F_t *f, H5B2_t *b);
-static herr_t H5B2_cache_hdr_clear(H5F_t *f, H5B2_t *b, hbool_t destroy);
-static herr_t H5B2_cache_hdr_size(const H5F_t *f, const H5B2_t *bt, size_t *size_ptr);
-static H5B2_leaf_t *H5B2_cache_leaf_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_type, void *udata);
-static herr_t H5B2_cache_leaf_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_leaf_t *l);
-static herr_t H5B2_cache_leaf_dest(H5F_t *f, H5B2_leaf_t *l);
-static herr_t H5B2_cache_leaf_clear(H5F_t *f, H5B2_leaf_t *l, hbool_t destroy);
-static herr_t H5B2_cache_leaf_size(const H5F_t *f, const H5B2_leaf_t *l, size_t *size_ptr);
-/* Static variables */
+/* Package variables */
+
+/* Declare a free list to manage the H5B2_t struct */
+H5FL_DEFINE(H5B2_t);
+
+/* Declare a free list to manage the H5B2_internal_t struct */
+H5FL_DEFINE(H5B2_internal_t);
+
+/* Declare a free list to manage the H5B2_leaf_t struct */
+H5FL_DEFINE(H5B2_leaf_t);
+
-/* H5B2 inherits cache-like properties from H5AC */
-const H5AC_class_t H5AC_BT2_HDR[1] = {{
- H5AC_BT2_HDR_ID,
- (H5AC_load_func_t)H5B2_cache_hdr_load,
- (H5AC_flush_func_t)H5B2_cache_hdr_flush,
- (H5AC_dest_func_t)H5B2_cache_hdr_dest,
- (H5AC_clear_func_t)H5B2_cache_hdr_clear,
- (H5AC_size_func_t)H5B2_cache_hdr_size,
-}};
-
-/* H5B2 inherits cache-like properties from H5AC */
-static const H5AC_class_t H5AC_BT2_LEAF[1] = {{
- H5AC_BT2_LEAF_ID,
- (H5AC_load_func_t)H5B2_cache_leaf_load,
- (H5AC_flush_func_t)H5B2_cache_leaf_flush,
- (H5AC_dest_func_t)H5B2_cache_leaf_dest,
- (H5AC_clear_func_t)H5B2_cache_leaf_clear,
- (H5AC_size_func_t)H5B2_cache_leaf_size,
-}};
-
-
-/* Declare a free list to manage B-tree header data to/from disk */
-H5FL_BLK_DEFINE_STATIC(header_block);
+/* Static variables */
/* Declare a free list to manage B-tree node pages to/from disk */
H5FL_BLK_DEFINE_STATIC(node_page);
-/* Declare a free list to manage the 'H5B2_node_ptr_t' sequence information */
-H5FL_SEQ_DEFINE_STATIC(H5B2_node_ptr_t);
-
/* Declare a free list to manage the 'size_t' sequence information */
H5FL_SEQ_DEFINE_STATIC(size_t);
-/* Declare a free list to manage the H5B2_t struct */
-H5FL_DEFINE_STATIC(H5B2_t);
-
/* Declare a free list to manage the H5B2_shared_t struct */
H5FL_DEFINE_STATIC(H5B2_shared_t);
-/* Declare a free list to manage the H5B2_leaf_t struct */
-H5FL_DEFINE_STATIC(H5B2_leaf_t);
/*-------------------------------------------------------------------------
@@ -157,7 +105,7 @@ H5FL_DEFINE_STATIC(H5B2_leaf_t);
*
*-------------------------------------------------------------------------
*/
-static herr_t
+herr_t
H5B2_shared_init (H5F_t *f, H5B2_t *bt2, const H5B2_class_t *type,
size_t node_size, size_t rkey_size,
unsigned split_percent, unsigned merge_percent)
@@ -207,28 +155,12 @@ H5B2_shared_init (H5F_t *f, H5B2_t *bt2, const H5B2_class_t *type,
HGOTO_ERROR (H5E_RESOURCE, H5E_CANTINIT, NULL, "can't create internal node node pointer block factory")
/* Allocate array of pointers to internal node native keys */
- if((shared->int_nat_off=H5FL_SEQ_MALLOC(size_t,shared->internal_nrec))==NULL)
+ if((shared->nat_off=H5FL_SEQ_MALLOC(size_t,MAX(shared->internal_nrec,shared->leaf_nrec)))==NULL)
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
- /* Allocate array of pointers to leaf node native keys */
- if((shared->leaf_nat_off=H5FL_SEQ_MALLOC(size_t,shared->leaf_nrec))==NULL)
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
-
- /* Allocate array of pointers to internal node node pointers */
- if((shared->node_ptr_off=H5FL_SEQ_MALLOC(H5B2_node_ptr_t,(shared->internal_nrec+1)))==NULL)
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
-
- /* Initialize offsets in internal node native key block */
- for(u=0; u<shared->internal_nrec; u++)
- shared->int_nat_off[u]=type->nkey_size*u;
-
- /* Initialize offsets in leaf node native key block */
- for(u=0; u<shared->leaf_nrec; u++)
- shared->leaf_nat_off[u]=type->nkey_size*u;
-
- /* Initialize offsets in internal node node pointer block */
- for(u=0; u<(shared->internal_nrec+1); u++)
- shared->node_ptr_off[u]=sizeof(H5B2_node_ptr_t)*u;
+ /* Initialize offsets in native key block */
+ for(u=0; u<MAX(shared->internal_nrec,shared->leaf_nrec); u++)
+ shared->nat_off[u]=type->nkey_size*u;
/* Make shared B-tree info reference counted */
if(NULL==(bt2->shared=H5RC_create(shared,H5B2_shared_free)))
@@ -256,7 +188,7 @@ done:
*
*-------------------------------------------------------------------------
*/
-static herr_t
+herr_t
H5B2_shared_free (void *_shared)
{
H5B2_shared_t *shared = (H5B2_shared_t *)_shared;
@@ -286,17 +218,9 @@ H5B2_shared_free (void *_shared)
if(H5FL_fac_term(shared->node_ptr_fac)<0)
HGOTO_ERROR (H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't destroy internal node node pointer block factory")
- /* Free the array of offsets into the internal node native key block */
- if(shared->int_nat_off)
- H5FL_SEQ_FREE(size_t,shared->int_nat_off);
-
- /* Free the array of offsets into the leaf node native key block */
- if(shared->leaf_nat_off)
- H5FL_SEQ_FREE(size_t,shared->leaf_nat_off);
-
- /* Free the array of offsets into the internal node node pointer block */
- if(shared->node_ptr_off)
- H5FL_SEQ_FREE(H5B2_node_ptr_t,shared->node_ptr_off);
+ /* Free the array of offsets into the native key block */
+ if(shared->nat_off)
+ H5FL_SEQ_FREE(size_t,shared->nat_off);
/* Free the shared B-tree info itself */
H5FL_FREE(H5B2_shared_t,shared);
@@ -378,340 +302,158 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5B2_cache_hdr_load
+ * Function: H5B2_locate_record
*
- * Purpose: Loads a B-tree header from the disk.
+ * Purpose: Performs a binary search to locate a record in a sorted
+ * array of records.
*
- * Return: Success: Pointer to a new B-tree.
+ * Return: Success: Non-negative array index where new record
+ * should be inserted
*
- * Failure: NULL
+ * Failure: Negative, if record already is in array of
+ * records.
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
- * Feb 1 2005
+ * Feb 3 2005
*
*-------------------------------------------------------------------------
*/
-static H5B2_t *
-H5B2_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_type, void UNUSED *udata)
+static int
+H5B2_locate_record(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type,
+ unsigned nrec, size_t *rec_off, const uint8_t *native,
+ const void *udata)
{
- const H5B2_class_t *type = (const H5B2_class_t *) _type;
- size_t node_size, rkey_size; /* Size info for B-tree */
- unsigned split_percent, merge_percent; /* Split & merge info for B-tree */
- H5B2_t *bt2 = NULL;
- size_t size;
- uint8_t *buf = NULL;
- uint8_t *p; /* Pointer into raw data buffer */
- H5B2_t *ret_value;
-
- FUNC_ENTER_NOAPI(H5B2_cache_hdr_load, NULL)
-
- /* Check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
- HDassert(type);
-
- if (NULL==(bt2 = H5FL_MALLOC(H5B2_t)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- HDmemset(&bt2->cache_info,0,sizeof(H5AC_info_t));
-
- /* Compute the size of the B-tree header on disk */
- size = H5B2_HEADER_SIZE(f);
-
- /* Allocate temporary buffer */
- if ((buf=H5FL_BLK_MALLOC(header_block,size))==NULL)
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
-
- /* Read header from disk */
- if (H5F_block_read(f, H5FD_MEM_BTREE, addr, size, dxpl_id, buf)<0)
- HGOTO_ERROR(H5E_BTREE, H5E_READERROR, NULL, "can't read B-tree header")
-
- p = buf;
-
- /* magic number */
- if (HDmemcmp(p, H5B2_HDR_MAGIC, H5B2_SIZEOF_MAGIC))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree header signature")
- p += H5B2_SIZEOF_MAGIC;
-
- /* version */
- if (*p++ != H5B2_HDR_VERSION)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree header version")
-
- /* B-tree type */
- if (*p++ != (uint8_t)type->id)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "incorrect B-tree type")
-
- /* node size (in bytes) */
- UINT32DECODE(p, node_size);
-
- /* raw key size (in bytes) */
- UINT16DECODE(p, rkey_size);
-
- /* depth of tree */
- UINT16DECODE(p, bt2->depth);
-
- /* split & merge %s */
- UINT16DECODE(p, split_percent);
- UINT16DECODE(p, merge_percent);
-
- /* root node pointer */
- H5F_addr_decode(f, (const uint8_t **)&p, &(bt2->root.addr));
- UINT16DECODE(p, bt2->root.node_nrec);
- H5F_DECODE_LENGTH(f, p, bt2->root.all_nrec);
+ unsigned lo = 0, hi; /* Low & high index values */
+ int idx = 0; /* Final index value */
+ int cmp = -1; /* Key comparison value */
- /* Initialize shared B-tree info */
- if(H5B2_shared_init(f, bt2, type, node_size, rkey_size, split_percent, merge_percent)<0)
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "can't create shared B-tree info")
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5B2_locate_record)
- /* Set return value */
- ret_value = bt2;
+ hi = nrec;
+ while (lo < hi && cmp) {
+ idx = (lo + hi) / 2;
+ if ((cmp = (type->compare)(f, dxpl_id, udata, native+rec_off[idx])) < 0)
+ hi = idx;
+ else
+ lo = idx + 1;
+ }
+ if(cmp==0)
+ idx=(-1);
+ else if(cmp>0)
+ idx++;
-done:
- if(buf)
- H5FL_BLK_FREE(header_block,buf);
- if (!ret_value && bt2)
- (void)H5B2_cache_hdr_dest(f,bt2);
- FUNC_LEAVE_NOAPI(ret_value)
-} /*lint !e818 Can't make udata a pointer to const */
+ FUNC_LEAVE_NOAPI(idx);
+} /* end H5B2_locate_record */
/*-------------------------------------------------------------------------
- * Function: H5B2_cache_hdr_flush
+ * Function: H5B2_split_root
*
- * Purpose: Flushes a dirty B-tree header to disk.
+ * Purpose: Split the root node
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: Non-negative
+ *
+ * Failure: Negative
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
- * Feb 1 2005
+ * Feb 3 2005
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5B2_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_t *bt2)
+H5B2_split_root(H5F_t *f, hid_t dxpl_id, H5B2_t *bt2, const H5B2_shared_t *shared)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5B2_cache_hdr_flush, FAIL)
+ FUNC_ENTER_NOAPI_NOINIT(H5B2_split_root)
- /* check arguments */
HDassert(f);
- HDassert(H5F_addr_defined(addr));
HDassert(bt2);
+ HDassert(shared);
- if (bt2->cache_info.is_dirty) {
- H5B2_shared_t *shared; /* Shared B-tree information */
- uint8_t *buf = NULL;
- uint8_t *p; /* Pointer into raw data buffer */
- size_t size;
-
- /* Get the pointer to the shared B-tree info */
- shared=H5RC_GET_OBJ(bt2->shared);
- HDassert(shared);
-
- /* Compute the size of the B-tree header on disk */
- size = H5B2_HEADER_SIZE(f);
-
- /* Allocate temporary buffer */
- if ((buf=H5FL_BLK_MALLOC(header_block,size))==NULL)
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
-
- p = buf;
-
- /* magic number */
- HDmemcpy(p, H5B2_HDR_MAGIC, H5B2_SIZEOF_MAGIC);
- p += H5B2_SIZEOF_MAGIC;
-
- /* version # */
- *p++ = H5B2_HDR_VERSION;
-
- /* b-tree type */
- *p++ = shared->type->id;
-
- /* node size (in bytes) */
- UINT32ENCODE(p, shared->node_size);
-
- /* raw key size (in bytes) */
- UINT16ENCODE(p, shared->rkey_size);
+ if(bt2->depth==0) {
+ H5B2_internal_t *new_int=NULL; /* Pointer to new internal node */
+ H5B2_leaf_t *old_leaf=NULL, *new_leaf=NULL; /* Pointers to old & new leaf nodes */
+ H5B2_node_ptr_t new_int_ptr; /* Node pointer to manage new internal node */
+ H5B2_node_ptr_t new_leaf_ptr; /* Node pointer to manage new leaf node */
+ unsigned mid_record; /* Index of "middle" record in current node */
- /* depth of tree */
- UINT16ENCODE(p, bt2->depth);
+ /* Create new leaf node */
+ new_leaf_ptr.all_nrec=new_leaf_ptr.node_nrec=0;
+ if(H5B2_create_leaf(f, dxpl_id, bt2, &new_leaf_ptr)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new leaf node")
- /* split & merge %s */
- UINT16ENCODE(p, shared->split_percent);
- UINT16ENCODE(p, shared->merge_percent);
+ /* Determine "middle" record to promote to new root */
+ mid_record = shared->split_leaf_nrec/2;
- /* root node pointer */
- H5F_addr_encode(f, &p, bt2->root.addr);
- UINT16ENCODE(p, bt2->root.node_nrec);
- H5F_ENCODE_LENGTH(f, p, bt2->root.all_nrec);
+ /* Protect both leafs */
+ if (NULL == (old_leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, bt2->root.addr, shared->type, &(bt2->root), H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load B-tree leaf node")
+ if (NULL == (new_leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, new_leaf_ptr.addr, shared->type, &new_leaf_ptr, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load B-tree leaf node")
- /* Write the B-tree header. */
- if (H5F_block_write(f, H5FD_MEM_BTREE, addr, size, dxpl_id, buf) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFLUSH, FAIL, "unable to save B-tree header to disk")
+ /* Copy "upper half" of records to new leaf */
+ HDmemcpy(new_leaf->leaf_native,H5B2_LEAF_NKEY(old_leaf,shared,mid_record+1),shared->type->nkey_size*(shared->split_leaf_nrec-(mid_record+1)));
- H5FL_BLK_FREE(header_block,buf);
+ /* Create new internal node */
+ new_int_ptr.all_nrec=new_int_ptr.node_nrec=0;
+ if(H5B2_create_internal(f, dxpl_id, bt2, &new_int_ptr)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new internal node")
- bt2->cache_info.is_dirty = FALSE;
- } /* end if */
+ /* Protect new internal node */
+ if (NULL == (new_int = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, new_int_ptr.addr, shared->type, &new_int_ptr, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load B-tree internal node")
- if (destroy)
- if (H5B2_cache_hdr_dest(f,bt2) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree header")
+ /* Copy "middle" record to new internal node */
+ HDmemcpy(new_int->int_native,H5B2_LEAF_NKEY(old_leaf,shared,mid_record),shared->type->nkey_size);
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5B2_cache_hdr_flush() */
+ /* Update record counts in leaf nodes */
+ bt2->root.all_nrec=bt2->root.node_nrec=old_leaf->nrec=mid_record;
+ new_leaf_ptr.all_nrec=new_leaf_ptr.node_nrec=new_leaf->nrec=shared->split_leaf_nrec-(mid_record+1);
-
-/*-------------------------------------------------------------------------
- * Function: H5B_cache_hdr_dest
- *
- * Purpose: Destroys a B-tree header in memory.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 1 2005
- *
- *-------------------------------------------------------------------------
- */
-/* ARGSUSED */
-static herr_t
-H5B2_cache_hdr_dest(H5F_t UNUSED *f, H5B2_t *bt2)
-{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5B2_cache_hdr_dest)
+ /* Mark leaf nodes as dirty */
+ old_leaf->cache_info.is_dirty = TRUE;
+ new_leaf->cache_info.is_dirty = TRUE;
- /*
- * Check arguments.
- */
- HDassert(bt2);
+ /* Release leaf nodes */
+ if (H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, bt2->root.addr, old_leaf, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release B-tree leaf node")
+ if (H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, new_leaf_ptr.addr, new_leaf, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release B-tree leaf node")
- /* Decrement reference count on shared B-tree info */
- if(bt2->shared)
- H5RC_DEC(bt2->shared);
+ /* Set internal node pointers to leaf nodes */
+ new_int->node_ptrs[0]=bt2->root;
+ new_int->node_ptrs[1]=new_leaf_ptr;
- /* Free B-tree header info */
- H5FL_FREE(H5B2_t,bt2);
+ /* Update record count in new internal node */
+ new_int->nrec = 1;
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5B2_cache_hdr_dest() */
+ /* Mark new internal node as dirty */
+ new_int->cache_info.is_dirty = TRUE;
-
-/*-------------------------------------------------------------------------
- * Function: H5B2_cache_hdr_clear
- *
- * Purpose: Mark a B-tree header in memory as non-dirty.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 1 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B2_cache_hdr_clear(H5F_t *f, H5B2_t *bt2, hbool_t destroy)
-{
- herr_t ret_value = SUCCEED;
+ /* Release new internal node */
+ if (H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, new_int_ptr.addr, new_int, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release B-tree internal node")
- FUNC_ENTER_NOAPI_NOINIT(H5B2_cache_hdr_clear)
+ /* Update depth of B-tree */
+ bt2->depth++;
- /*
- * Check arguments.
- */
- HDassert(bt2);
+ /* Update pointer to B-tree's root node to pointer to new internal node */
+ bt2->root = new_int_ptr;
- /* Reset the dirty flag. */
- bt2->cache_info.is_dirty = FALSE;
-
- if (destroy)
- if (H5B2_cache_hdr_dest(f, bt2) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree header")
+ /* Mark B-tree header as dirty */
+ bt2->cache_info.is_dirty = TRUE;
+ } /* end if */
+ else {
+HDfprintf(stderr,"%s: Need to split internal root! shared->split_int_nrec=%Zu\n",FUNC,shared->split_int_nrec);
+HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to split internal root node yet")
+ } /* end else */
done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5B2_cache_hdr_clear() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5B2_cache_hdr_size
- *
- * Purpose: Compute the size in bytes of a B-tree header
- * on disk, and return it in *size_ptr. On failure,
- * the value of *size_ptr is undefined.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 1 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B2_cache_hdr_size(const H5F_t *f, const H5B2_t UNUSED *bt2, size_t *size_ptr)
-{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5B2_cache_hdr_size)
-
- /* check arguments */
- HDassert(f);
- HDassert(size_ptr);
-
- /* Set size value */
- *size_ptr = H5B2_HEADER_SIZE(f);
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5B2_cache_hdr_size() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5B2_locate_record
- *
- * Purpose: Performs a binary search to locate a record in a sorted
- * array of records.
- *
- * Return: Success: Non-negative array index where new record
- * should be inserted
- *
- * Failure: Negative, if record already is in array of
- * records.
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 3 2005
- *
- *-------------------------------------------------------------------------
- */
-static int
-H5B2_locate_record(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type,
- unsigned nrec, size_t *rec_off, const uint8_t *native,
- const void *udata)
-{
- unsigned lo = 0, hi; /* Low & high index values */
- int idx = 0; /* Final index value */
- int cmp = -1; /* Key comparison value */
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5B2_locate_record)
-
- hi = nrec;
- while (lo < hi && cmp) {
- idx = (lo + hi) / 2;
- if ((cmp = (type->compare)(f, dxpl_id, udata, native+rec_off[idx])) < 0)
- hi = idx;
- else
- lo = idx + 1;
- }
- if(cmp==0)
- idx=(-1);
- else if(cmp>0)
- idx++;
-
- FUNC_LEAVE_NOAPI(idx);
-} /* end H5B2_locate_record */
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5B2_split_root */
/*-------------------------------------------------------------------------
@@ -733,11 +475,11 @@ herr_t
H5B2_insert(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr,
void *udata)
{
- H5AC_info_t *cache_info; /* Parent node's cache info */
H5B2_t *bt2=NULL; /* Pointer to the B-tree header */
H5B2_shared_t *shared; /* Pointer to B-tree's shared information */
- H5B2_node_ptr_t *node_ptr; /* Pointer to node pointer info for current node */
- unsigned depth; /* Current depth of node */
+ H5B2_node_ptr_t leaf_ptr; /* Node pointer info for leaf node */
+ H5B2_leaf_t *leaf=NULL; /* Pointer to leaf node */
+ int idx; /* Location of record which matches key */
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(H5B2_insert, FAIL)
@@ -764,71 +506,174 @@ H5B2_insert(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr,
/* Mark B-tree header as dirty, since we updated the address of the root node */
bt2->cache_info.is_dirty = TRUE;
} /* end if */
-depth=bt2->depth;
-node_ptr=&(bt2->root);
-cache_info=&(bt2->cache_info);
+ /* Check if we need to split the root node */
+ else if((bt2->depth==0 && bt2->root.node_nrec==shared->split_leaf_nrec) ||
+ (bt2->depth>0 && bt2->root.node_nrec==shared->split_int_nrec)) {
+ /* Split root node */
+ if(H5B2_split_root(f, dxpl_id, bt2, shared)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to split root node")
+ } /* end if */
+
+ /* Check for non-trivial B-tree */
+ if(bt2->depth>0) {
+ H5B2_internal_t *internal; /* Pointer to internal node in B-tree */
+ H5AC_info_t *parent_cache_info; /* Parent node's cache info */
+ haddr_t parent_addr; /* Address of parent which contain's node pointer to current node */
+ void *parent_ptr; /* Pointer to parent structure in memory */
+ H5AC_info_t *curr_cache_info=NULL; /* Current node's cache info */
+ H5B2_node_ptr_t *curr_node_ptr; /* Pointer to node pointer info for current node (in parent node) */
+ haddr_t curr_addr=HADDR_UNDEF; /* Address of current node */
+ void *curr_ptr=NULL; /* Pointer to current structure in memory */
+ H5B2_node_ptr_t *child_node_ptr=NULL; /* Pointer to node pointer info for child node */
+ unsigned depth; /* Depth of current node */
+
+ /* Track the depth of current node (leaves are depth 0) */
+ depth=bt2->depth;
+
+ /* Set initial "parent" information to the B-tree header */
+ parent_cache_info=&(bt2->cache_info);
+ parent_addr=addr;
+ parent_ptr=bt2;
+
+ /* Set initial node pointer for "current" node */
+ curr_node_ptr=&(bt2->root);
+
+ /* Find correct leaf to insert node into */
+ while(depth>0) {
+ /* Lock B-tree current node */
+ if (NULL == (internal = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr->addr, shared->type, curr_node_ptr, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load B-tree internal node")
+
+ /* Set information for current (root) node */
+ curr_cache_info=&(internal->cache_info);
+ curr_addr=curr_node_ptr->addr;
+ curr_ptr=internal;
+
+ /* Locate node pointer for child */
+ if((idx=H5B2_locate_record(f,dxpl_id,shared->type,internal->nrec,shared->nat_off,internal->int_native,udata))<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_EXISTS, FAIL, "record is already in B-tree")
- /* Check if we are inserting in internal or leaf node */
- if(depth==0) {
- H5B2_leaf_t *leaf=NULL; /* Pointer to leaf node */
- int idx; /* Location of record which matches key */
+ /* Get node pointer for child */
+ child_node_ptr=&(internal->node_ptrs[idx]);
+
+ /* Preemptively split/redistribute a node we will enter */
+ if((depth==1 && child_node_ptr->node_nrec==shared->split_leaf_nrec) ||
+ (depth>1 && child_node_ptr->node_nrec==shared->split_int_nrec)) {
+HDfprintf(stderr,"%s: need to split child node!, depth=%u\n",FUNC,depth);
+HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to split child node")
+ /* Attempt to redistribute records among children */
+ /* Split children, if can't redistribute */
+ /* Update record count info for current node to reflect new # of records (in parent) */
+ /* Update child_node_ptr (to reflect change in location from split/redistribution) */
+ } /* end if */
- /* Look up the B-tree leaf node */
- if (NULL == (leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, node_ptr->addr, shared->type, node_ptr, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load B-tree leaf node")
+ /* Update record count (in parent) */
+ curr_node_ptr->all_nrec++;
- /* Check for inserting into empty leaf */
- if(node_ptr->node_nrec==0)
- idx=0;
- else {
- /* Find correct location to insert this record and make room for it */
- if((idx=H5B2_locate_record(f,dxpl_id,shared->type,leaf->nrec,shared->leaf_nat_off,leaf->leaf_native,udata))<0) {
- /* Release the B-tree leaf node */
- if (H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, node_ptr->addr, leaf, H5AC__NO_FLAGS_SET) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release B-tree leaf node")
+ /* Mark parent node as dirty */
+ parent_cache_info->is_dirty = TRUE;
- HGOTO_ERROR(H5E_BTREE, H5E_EXISTS, FAIL, "record is already in B-tree")
- } /* end if */
+ /* Unlock parent node (possibly the B-tree header) */
+ if (H5AC_unprotect(f, dxpl_id, parent_cache_info->type, parent_addr, parent_ptr, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release B-tree info")
- /* Make room for new record */
- if((unsigned)idx<leaf->nrec)
- HDmemmove(H5B2_LEAF_NKEY(leaf,shared,idx+1),H5B2_LEAF_NKEY(leaf,shared,idx),shared->type->nkey_size*(leaf->nrec-idx));
- } /* end else */
+ /* Transition "current" info into "parent" info */
+ parent_cache_info = curr_cache_info;
+ parent_addr = curr_addr;
+ parent_ptr = curr_ptr;
- /* Make callback to store record in native form */
- if((shared->type->store)(f,dxpl_id,udata,H5B2_LEAF_NKEY(leaf,shared,idx))<0) {
- /* Release the B-tree leaf node */
- if (H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, node_ptr->addr, leaf, H5AC__NO_FLAGS_SET) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release B-tree leaf node")
+ /* Transition "child" node pointer to "current" node pointer */
+ curr_node_ptr = child_node_ptr;
- HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into leaf node")
- } /* end if */
+ /* Decrement depth of current node */
+ depth--;
+ } /* end while */
+
+ /* Update record count for leaf (in current node) */
+ HDassert(curr_node_ptr);
+ curr_node_ptr->all_nrec++;
+ curr_node_ptr->node_nrec++;
+
+ /* Mark parent node as dirty */
+ curr_cache_info->is_dirty = TRUE;
+
+ /* Copy node pointer info for leaf */
+ leaf_ptr = *curr_node_ptr;
+
+ /* Release current node */
+ if (H5AC_unprotect(f, dxpl_id, curr_cache_info->type, curr_addr, curr_ptr, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release B-tree node")
+ } /* end if */
+ else {
+ /* Update record count for root node */
+ bt2->root.all_nrec++;
+ bt2->root.node_nrec++;
+
+ /* Mark parent node as dirty */
+ bt2->cache_info.is_dirty = TRUE;
+
+ /* Copy node pointer info for leaf */
+ leaf_ptr = bt2->root;
- /* Update record # info in node pointer */
- node_ptr->all_nrec++;
- node_ptr->node_nrec++;
+ /* Release parent node */
+ if (H5AC_unprotect(f, dxpl_id, H5AC_BT2_HDR, addr, bt2, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release B-tree header info")
+ bt2=NULL;
+ } /* end else */
+
+ /* Must have a leaf node with enough space to insert a record now */
+ HDassert(H5F_addr_defined(leaf_ptr.addr));
+ HDassert((leaf_ptr.node_nrec-1)<shared->split_leaf_nrec); /* node pointer to leaf has already been incremented */
+
+ /* Look up the B-tree leaf node */
+ if (NULL == (leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, leaf_ptr.addr, shared->type, &leaf_ptr, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load B-tree leaf node")
+
+ /* Sanity check number of records */
+ HDassert(leaf_ptr.all_nrec==leaf_ptr.node_nrec);
+ HDassert(leaf->nrec==(leaf_ptr.node_nrec-1)); /* node pointer to leaf has already been incremented */
+
+ /* Check for inserting into empty leaf */
+ if(leaf->nrec==0)
+ idx=0;
+ else {
+ /* Sanity check for the leaf node being full */
+ HDassert(leaf->nrec!=shared->split_leaf_nrec);
- /* Update number of records in node */
- leaf->nrec++;
- HDassert(node_ptr->node_nrec==leaf->nrec);
+ /* Find correct location to insert this record and make room for it */
+ if((idx=H5B2_locate_record(f,dxpl_id,shared->type,leaf->nrec,shared->nat_off,leaf->leaf_native,udata))<0) {
+ /* Release the B-tree leaf node */
+ if (H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, leaf_ptr.addr, leaf, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release B-tree leaf node")
- /* Mark parent's node as dirty now */
- cache_info->is_dirty = TRUE;
+ HGOTO_ERROR(H5E_BTREE, H5E_EXISTS, FAIL, "record is already in B-tree")
+ } /* end if */
- /* Mark leaf node as dirty also */
- leaf->cache_info.is_dirty = TRUE;
+ /* Make room for new record */
+ if((unsigned)idx<leaf->nrec)
+ HDmemmove(H5B2_LEAF_NKEY(leaf,shared,idx+1),H5B2_LEAF_NKEY(leaf,shared,idx),shared->type->nkey_size*(leaf->nrec-idx));
+ } /* end else */
+ /* Make callback to store record in native form */
+ if((shared->type->store)(f,dxpl_id,udata,H5B2_LEAF_NKEY(leaf,shared,idx))<0) {
/* Release the B-tree leaf node */
- if (H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, node_ptr->addr, leaf, H5AC__NO_FLAGS_SET) < 0)
+ if (H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, leaf_ptr.addr, leaf, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release B-tree leaf node")
+
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into leaf node")
} /* end if */
- else {
- } /* end else */
-done:
- if (bt2 && H5AC_unprotect(f, dxpl_id, H5AC_BT2_HDR, addr, bt2, H5AC__NO_FLAGS_SET) < 0)
- HDONE_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release B-tree header")
+ /* Update number of records in node */
+ leaf->nrec++;
+
+ /* Mark leaf node as dirty also */
+ leaf->cache_info.is_dirty = TRUE;
+
+ /* Release the B-tree leaf node */
+ if (H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, leaf_ptr.addr, leaf, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release B-tree leaf node")
+done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5B2_insert() */
@@ -847,7 +692,7 @@ done:
*
*-------------------------------------------------------------------------
*/
-herr_t
+static herr_t
H5B2_create_leaf(H5F_t *f, hid_t dxpl_id, H5B2_t *bt2, H5B2_node_ptr_t *node_ptr)
{
H5B2_leaf_t *leaf=NULL; /* Pointer to new leaf node created */
@@ -886,7 +731,7 @@ H5B2_create_leaf(H5F_t *f, hid_t dxpl_id, H5B2_t *bt2, H5B2_node_ptr_t *node_ptr
/* Allocate space on disk for the leaf */
if (HADDR_UNDEF==(node_ptr->addr=H5MF_alloc(f, H5FD_MEM_BTREE, dxpl_id, (hsize_t)shared->node_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for B-tree header")
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for B-tree leaf node")
/* Cache the new B-tree node */
if (H5AC_set(f, dxpl_id, H5AC_BT2_LEAF, node_ptr->addr, leaf, H5AC__NO_FLAGS_SET) < 0)
@@ -903,274 +748,74 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5B2_cache_leaf_load
+ * Function: H5B2_create_internal
*
- * Purpose: Loads a B-tree leaf from the disk.
- *
- * Return: Success: Pointer to a new B-tree leaf node.
+ * Purpose: Creates empty internal node of a B-tree and update node pointer
+ * to point to it.
*
- * Failure: NULL
+ * Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
- * Feb 2 2005
+ * Feb 3 2005
*
*-------------------------------------------------------------------------
*/
-static H5B2_leaf_t *
-H5B2_cache_leaf_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_bt2, void *_node_ptr)
+static herr_t
+H5B2_create_internal(H5F_t *f, hid_t dxpl_id, H5B2_t *bt2, H5B2_node_ptr_t *node_ptr)
{
- const H5B2_t *bt2 = (const H5B2_t *)_bt2;
- H5B2_node_ptr_t *node_ptr = (H5B2_node_ptr_t *)_node_ptr;
- H5B2_leaf_t *leaf = NULL;
- H5B2_shared_t *shared; /* Shared B-tree information */
- uint8_t *p; /* Pointer into raw data buffer */
- H5B2_leaf_t *ret_value;
+ H5B2_internal_t *internal=NULL; /* Pointer to new internal node created */
+ H5B2_shared_t *shared; /* Shared B-tree information */
+ herr_t ret_value = SUCCEED;
- FUNC_ENTER_NOAPI(H5B2_cache_leaf_load, NULL)
+ FUNC_ENTER_NOAPI(H5B2_create_internal, FAIL)
- /* Check arguments */
+ /* Check arguments. */
HDassert(f);
- HDassert(H5F_addr_defined(addr));
HDassert(bt2);
+ HDassert(node_ptr);
- if (NULL==(leaf = H5FL_MALLOC(H5B2_leaf_t)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- HDmemset(&leaf->cache_info,0,sizeof(H5AC_info_t));
+ /* Allocate memory for internal node information */
+ if (NULL==(internal = H5FL_MALLOC(H5B2_internal_t)))
+ HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree internal info")
+
+ /* Set metadata cache info */
+ HDmemset(&internal->cache_info,0,sizeof(H5AC_info_t));
+ internal->cache_info.is_dirty = TRUE;
/* Share common B-tree information */
- leaf->shared = bt2->shared;
- H5RC_INC(leaf->shared);
+ internal->shared = bt2->shared;
+ H5RC_INC(internal->shared);
/* Get the pointer to the shared B-tree info */
- shared=H5RC_GET_OBJ(leaf->shared);
+ shared=H5RC_GET_OBJ(internal->shared);
HDassert(shared);
- /* Read header from disk */
- if (H5F_block_read(f, H5FD_MEM_BTREE, addr, shared->node_size, dxpl_id, shared->page)<0)
- HGOTO_ERROR(H5E_BTREE, H5E_READERROR, NULL, "can't read B-tree leaf node")
-
- p = shared->page;
-
- /* magic number */
- if (HDmemcmp(p, H5B2_LEAF_MAGIC, H5B2_SIZEOF_MAGIC))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree leaf node signature")
- p += H5B2_SIZEOF_MAGIC;
-
- /* version */
- if (*p++ != H5B2_LEAF_VERSION)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree header version")
-
- /* B-tree type */
- if (*p++ != (uint8_t)shared->type->id)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "incorrect B-tree type")
-
/* Allocate space for the native keys in memory */
- if((leaf->leaf_native=H5FL_FAC_MALLOC(shared->leaf_fac))==NULL)
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for B-tree leaf native keys")
-
-HDfprintf(stderr,"%s: Deserialize leaf node records here!, node_ptr->node_nrec=%u\n",FUNC,node_ptr->node_nrec);
-
- /* Set return value */
- ret_value = leaf;
-
-done:
- if (!ret_value && leaf)
- (void)H5B2_cache_leaf_dest(f,leaf);
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5B2_cache_leaf_load() */ /*lint !e818 Can't make udata a pointer to const */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5B2_cache_leaf_flush
- *
- * Purpose: Flushes a dirty B-tree leaf node to disk.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 2 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B2_cache_leaf_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_leaf_t *leaf)
-{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5B2_cache_leaf_flush, FAIL)
-
- /* check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
- HDassert(leaf);
-
- if (leaf->cache_info.is_dirty) {
- H5B2_shared_t *shared; /* Shared B-tree information */
- uint8_t *p; /* Pointer into raw data buffer */
- uint8_t *native; /* Pointer to native keys */
- unsigned u; /* Local index variable */
-
- /* Get the pointer to the shared B-tree info */
- shared=H5RC_GET_OBJ(leaf->shared);
- HDassert(shared);
-
- p = shared->page;
-
- /* magic number */
- HDmemcpy(p, H5B2_HDR_MAGIC, H5B2_SIZEOF_MAGIC);
- p += H5B2_SIZEOF_MAGIC;
+ if((internal->int_native=H5FL_FAC_MALLOC(shared->int_fac))==NULL)
+ HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree internal native keys")
- /* version # */
- *p++ = H5B2_LEAF_VERSION;
+ /* Allocate space for the node pointers in memory */
+ if((internal->node_ptrs=H5FL_FAC_MALLOC(shared->node_ptr_fac))==NULL)
+ HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree internal node pointers")
- /* b-tree type */
- *p++ = shared->type->id;
-
- /* Serialize records for leaf node */
- native=leaf->leaf_native;
- for(u=0; u<leaf->nrec; u++) {
- /* Encode record */
- if((shared->type->encode)(f,p,native)<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTENCODE, FAIL, "enable to encode B-tree record");
-
- /* Move to next record */
- p += shared->rkey_size;
- native += shared->type->nkey_size;
- } /* end for */
-
- /* Write the B-tree leaf node */
- if (H5F_block_write(f, H5FD_MEM_BTREE, addr, shared->node_size, dxpl_id, shared->page) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFLUSH, FAIL, "unable to save B-tree leaf node to disk")
+ /* Set number of records */
+ internal->nrec=0;
- leaf->cache_info.is_dirty = FALSE;
- } /* end if */
+ /* Allocate space on disk for the internal node */
+ if (HADDR_UNDEF==(node_ptr->addr=H5MF_alloc(f, H5FD_MEM_BTREE, dxpl_id, (hsize_t)shared->node_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for B-tree internal node")
- if (destroy)
- if (H5B2_cache_leaf_dest(f,leaf) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree leaf node")
+ /* Cache the new B-tree node */
+ if (H5AC_set(f, dxpl_id, H5AC_BT2_INT, node_ptr->addr, internal, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "can't add B-tree internal node to cache")
done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5B2_cache_leaf_flush() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5B_cache_leaf_dest
- *
- * Purpose: Destroys a B-tree leaf node in memory.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 2 2005
- *
- *-------------------------------------------------------------------------
- */
-/* ARGSUSED */
-static herr_t
-H5B2_cache_leaf_dest(H5F_t UNUSED *f, H5B2_leaf_t *leaf)
-{
- H5B2_shared_t *shared; /* Shared B-tree information */
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5B2_cache_leaf_dest)
-
- /*
- * Check arguments.
- */
- HDassert(leaf);
-
- /* Get the pointer to the shared B-tree info */
- shared=H5RC_GET_OBJ(leaf->shared);
- HDassert(shared);
-
- /* Release leaf's native key buffer */
- if(leaf->leaf_native)
- H5FL_FAC_FREE(shared->leaf_fac,leaf->leaf_native);
-
- /* Decrement reference count on shared B-tree info */
- if(leaf->shared)
- H5RC_DEC(leaf->shared);
-
- /* Free B-tree leaf node info */
- H5FL_FREE(H5B2_leaf_t,leaf);
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5B2_cache_leaf_dest() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5B2_cache_leaf_clear
- *
- * Purpose: Mark a B-tree leaf node in memory as non-dirty.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 2 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B2_cache_leaf_clear(H5F_t *f, H5B2_leaf_t *leaf, hbool_t destroy)
-{
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT(H5B2_cache_leaf_clear)
-
- /*
- * Check arguments.
- */
- HDassert(leaf);
-
- /* Reset the dirty flag. */
- leaf->cache_info.is_dirty = FALSE;
-
- if (destroy)
- if (H5B2_cache_leaf_dest(f, leaf) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree leaf node")
+ if (ret_value<0) {
+ if (internal)
+ (void)H5B2_cache_internal_dest(f,internal);
+ } /* end if */
-done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5B2_cache_leaf_clear() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5B2_cache_leaf_size
- *
- * Purpose: Compute the size in bytes of a B-tree leaf node
- * on disk, and return it in *size_ptr. On failure,
- * the value of *size_ptr is undefined.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 2 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B2_cache_leaf_size(const H5F_t UNUSED *f, const H5B2_leaf_t *leaf, size_t *size_ptr)
-{
- H5B2_shared_t *shared; /* Shared B-tree information */
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5B2_cache_leaf_size)
-
- /* check arguments */
- HDassert(leaf);
- HDassert(size_ptr);
-
- /* Get the pointer to the shared B-tree info */
- shared=H5RC_GET_OBJ(leaf->shared);
- HDassert(shared);
-
- /* Set size value */
- *size_ptr = shared->node_size;
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5B2_cache_leaf_size() */
+} /* H5B2_create_internal() */
diff --git a/src/H5B2cache.c b/src/H5B2cache.c
new file mode 100644
index 0000000..fa9538d
--- /dev/null
+++ b/src/H5B2cache.c
@@ -0,0 +1,1003 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5B2.c
+ * Jan 31 2005
+ * Quincey Koziol <koziol@ncsa.uiuc.edu>
+ *
+ * Purpose: Implements a B-tree, with several modifications from
+ * the "standard" methods.
+ *
+ * Please see the documentation in:
+ * doc/html/TechNotes/Btrees.html for a full description
+ * of how they work, etc.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#define H5B2_PACKAGE /*suppress error about including H5B2pkg */
+
+/* Private headers */
+#include "H5private.h" /* Generic Functions */
+#include "H5B2pkg.h" /* B-trees */
+#include "H5Eprivate.h" /* Error handling */
+
+/* Local macros */
+
+/* B-tree format version #'s */
+#define H5B2_HDR_VERSION 0 /* Header */
+#define H5B2_INT_VERSION 0 /* Internal node */
+#define H5B2_LEAF_VERSION 0 /* Leaf node */
+
+
+/* Local typedefs */
+
+/* Local prototypes */
+
+/* Metadata cache callbacks */
+static H5B2_t *H5B2_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_type, void *udata);
+static herr_t H5B2_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_t *b);
+static herr_t H5B2_cache_hdr_clear(H5F_t *f, H5B2_t *b, hbool_t destroy);
+static herr_t H5B2_cache_hdr_size(const H5F_t *f, const H5B2_t *bt, size_t *size_ptr);
+static H5B2_leaf_t *H5B2_cache_leaf_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_type, void *udata);
+static herr_t H5B2_cache_leaf_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_leaf_t *l);
+static herr_t H5B2_cache_leaf_clear(H5F_t *f, H5B2_leaf_t *l, hbool_t destroy);
+static herr_t H5B2_cache_leaf_size(const H5F_t *f, const H5B2_leaf_t *l, size_t *size_ptr);
+static H5B2_internal_t *H5B2_cache_internal_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_type, void *udata);
+static herr_t H5B2_cache_internal_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_internal_t *i);
+static herr_t H5B2_cache_internal_clear(H5F_t *f, H5B2_internal_t *i, hbool_t destroy);
+static herr_t H5B2_cache_internal_size(const H5F_t *f, const H5B2_internal_t *i, size_t *size_ptr);
+
+/* Package variables */
+
+/* H5B2 inherits cache-like properties from H5AC */
+const H5AC_class_t H5AC_BT2_HDR[1] = {{
+ H5AC_BT2_HDR_ID,
+ (H5AC_load_func_t)H5B2_cache_hdr_load,
+ (H5AC_flush_func_t)H5B2_cache_hdr_flush,
+ (H5AC_dest_func_t)H5B2_cache_hdr_dest,
+ (H5AC_clear_func_t)H5B2_cache_hdr_clear,
+ (H5AC_size_func_t)H5B2_cache_hdr_size,
+}};
+
+/* H5B2 inherits cache-like properties from H5AC */
+const H5AC_class_t H5AC_BT2_LEAF[1] = {{
+ H5AC_BT2_LEAF_ID,
+ (H5AC_load_func_t)H5B2_cache_leaf_load,
+ (H5AC_flush_func_t)H5B2_cache_leaf_flush,
+ (H5AC_dest_func_t)H5B2_cache_leaf_dest,
+ (H5AC_clear_func_t)H5B2_cache_leaf_clear,
+ (H5AC_size_func_t)H5B2_cache_leaf_size,
+}};
+
+/* H5B2 inherits cache-like properties from H5AC */
+const H5AC_class_t H5AC_BT2_INT[1] = {{
+ H5AC_BT2_INT_ID,
+ (H5AC_load_func_t)H5B2_cache_internal_load,
+ (H5AC_flush_func_t)H5B2_cache_internal_flush,
+ (H5AC_dest_func_t)H5B2_cache_internal_dest,
+ (H5AC_clear_func_t)H5B2_cache_internal_clear,
+ (H5AC_size_func_t)H5B2_cache_internal_size,
+}};
+
+/* Static variables */
+
+/* Declare a free list to manage B-tree header data to/from disk */
+H5FL_BLK_DEFINE_STATIC(header_block);
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_cache_hdr_load
+ *
+ * Purpose: Loads a B-tree header from the disk.
+ *
+ * Return: Success: Pointer to a new B-tree.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 1 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5B2_t *
+H5B2_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_type, void UNUSED *udata)
+{
+ const H5B2_class_t *type = (const H5B2_class_t *) _type;
+ size_t node_size, rkey_size; /* Size info for B-tree */
+ unsigned split_percent, merge_percent; /* Split & merge info for B-tree */
+ H5B2_t *bt2 = NULL;
+ size_t size;
+ uint8_t *buf = NULL;
+ uint8_t *p; /* Pointer into raw data buffer */
+ H5B2_t *ret_value;
+
+ FUNC_ENTER_NOAPI(H5B2_cache_hdr_load, NULL)
+
+ /* Check arguments */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(type);
+
+ if (NULL==(bt2 = H5FL_MALLOC(H5B2_t)))
+ HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ HDmemset(&bt2->cache_info,0,sizeof(H5AC_info_t));
+
+ /* Compute the size of the B-tree header on disk */
+ size = H5B2_HEADER_SIZE(f);
+
+ /* Allocate temporary buffer */
+ if ((buf=H5FL_BLK_MALLOC(header_block,size))==NULL)
+ HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
+
+ /* Read header from disk */
+ if (H5F_block_read(f, H5FD_MEM_BTREE, addr, size, dxpl_id, buf)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_READERROR, NULL, "can't read B-tree header")
+
+ p = buf;
+
+ /* magic number */
+ if (HDmemcmp(p, H5B2_HDR_MAGIC, H5B2_SIZEOF_MAGIC))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree header signature")
+ p += H5B2_SIZEOF_MAGIC;
+
+ /* version */
+ if (*p++ != H5B2_HDR_VERSION)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree header version")
+
+ /* B-tree type */
+ if (*p++ != (uint8_t)type->id)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "incorrect B-tree type")
+
+ /* node size (in bytes) */
+ UINT32DECODE(p, node_size);
+
+ /* raw key size (in bytes) */
+ UINT16DECODE(p, rkey_size);
+
+ /* depth of tree */
+ UINT16DECODE(p, bt2->depth);
+
+ /* split & merge %s */
+ UINT16DECODE(p, split_percent);
+ UINT16DECODE(p, merge_percent);
+
+ /* root node pointer */
+ H5F_addr_decode(f, (const uint8_t **)&p, &(bt2->root.addr));
+ UINT16DECODE(p, bt2->root.node_nrec);
+ H5F_DECODE_LENGTH(f, p, bt2->root.all_nrec);
+
+ /* Initialize shared B-tree info */
+ if(H5B2_shared_init(f, bt2, type, node_size, rkey_size, split_percent, merge_percent)<0)
+ HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "can't create shared B-tree info")
+
+ /* Set return value */
+ ret_value = bt2;
+
+done:
+ if(buf)
+ H5FL_BLK_FREE(header_block,buf);
+ if (!ret_value && bt2)
+ (void)H5B2_cache_hdr_dest(f,bt2);
+ FUNC_LEAVE_NOAPI(ret_value)
+} /*lint !e818 Can't make udata a pointer to const */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_cache_hdr_flush
+ *
+ * Purpose: Flushes a dirty B-tree header to disk.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 1 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B2_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_t *bt2)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5B2_cache_hdr_flush, FAIL)
+
+ /* check arguments */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(bt2);
+
+ if (bt2->cache_info.is_dirty) {
+ H5B2_shared_t *shared; /* Shared B-tree information */
+ uint8_t *buf = NULL;
+ uint8_t *p; /* Pointer into raw data buffer */
+ size_t size;
+
+ /* Get the pointer to the shared B-tree info */
+ shared=H5RC_GET_OBJ(bt2->shared);
+ HDassert(shared);
+
+ /* Compute the size of the B-tree header on disk */
+ size = H5B2_HEADER_SIZE(f);
+
+ /* Allocate temporary buffer */
+ if ((buf=H5FL_BLK_MALLOC(header_block,size))==NULL)
+ HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
+
+ p = buf;
+
+ /* magic number */
+ HDmemcpy(p, H5B2_HDR_MAGIC, H5B2_SIZEOF_MAGIC);
+ p += H5B2_SIZEOF_MAGIC;
+
+ /* version # */
+ *p++ = H5B2_HDR_VERSION;
+
+ /* b-tree type */
+ *p++ = shared->type->id;
+
+ /* node size (in bytes) */
+ UINT32ENCODE(p, shared->node_size);
+
+ /* raw key size (in bytes) */
+ UINT16ENCODE(p, shared->rkey_size);
+
+ /* depth of tree */
+ UINT16ENCODE(p, bt2->depth);
+
+ /* split & merge %s */
+ UINT16ENCODE(p, shared->split_percent);
+ UINT16ENCODE(p, shared->merge_percent);
+
+ /* root node pointer */
+ H5F_addr_encode(f, &p, bt2->root.addr);
+ UINT16ENCODE(p, bt2->root.node_nrec);
+ H5F_ENCODE_LENGTH(f, p, bt2->root.all_nrec);
+
+ /* Write the B-tree header. */
+ if (H5F_block_write(f, H5FD_MEM_BTREE, addr, size, dxpl_id, buf) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTFLUSH, FAIL, "unable to save B-tree header to disk")
+
+ H5FL_BLK_FREE(header_block,buf);
+
+ bt2->cache_info.is_dirty = FALSE;
+ } /* end if */
+
+ if (destroy)
+ if (H5B2_cache_hdr_dest(f,bt2) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree header")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5B2_cache_hdr_flush() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B_cache_hdr_dest
+ *
+ * Purpose: Destroys a B-tree header in memory.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 1 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+herr_t
+H5B2_cache_hdr_dest(H5F_t UNUSED *f, H5B2_t *bt2)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5B2_cache_hdr_dest)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(bt2);
+
+ /* Decrement reference count on shared B-tree info */
+ if(bt2->shared)
+ H5RC_DEC(bt2->shared);
+
+ /* Free B-tree header info */
+ H5FL_FREE(H5B2_t,bt2);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5B2_cache_hdr_dest() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_cache_hdr_clear
+ *
+ * Purpose: Mark a B-tree header in memory as non-dirty.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 1 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B2_cache_hdr_clear(H5F_t *f, H5B2_t *bt2, hbool_t destroy)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT(H5B2_cache_hdr_clear)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(bt2);
+
+ /* Reset the dirty flag. */
+ bt2->cache_info.is_dirty = FALSE;
+
+ if (destroy)
+ if (H5B2_cache_hdr_dest(f, bt2) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree header")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5B2_cache_hdr_clear() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_cache_hdr_size
+ *
+ * Purpose: Compute the size in bytes of a B-tree header
+ * on disk, and return it in *size_ptr. On failure,
+ * the value of *size_ptr is undefined.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 1 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B2_cache_hdr_size(const H5F_t *f, const H5B2_t UNUSED *bt2, size_t *size_ptr)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5B2_cache_hdr_size)
+
+ /* check arguments */
+ HDassert(f);
+ HDassert(size_ptr);
+
+ /* Set size value */
+ *size_ptr = H5B2_HEADER_SIZE(f);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5B2_cache_hdr_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_cache_leaf_load
+ *
+ * Purpose: Loads a B-tree leaf from the disk.
+ *
+ * Return: Success: Pointer to a new B-tree leaf node.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 2 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5B2_leaf_t *
+H5B2_cache_leaf_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_bt2, void *_node_ptr)
+{
+ const H5B2_t *bt2 = (const H5B2_t *)_bt2;
+ H5B2_node_ptr_t *node_ptr = (H5B2_node_ptr_t *)_node_ptr;
+ H5B2_leaf_t *leaf = NULL;
+ H5B2_shared_t *shared; /* Shared B-tree information */
+ uint8_t *p; /* Pointer into raw data buffer */
+ uint8_t *native; /* Pointer to native keys */
+ unsigned u; /* Local index variable */
+ H5B2_leaf_t *ret_value;
+
+ FUNC_ENTER_NOAPI(H5B2_cache_leaf_load, NULL)
+
+ /* Check arguments */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(bt2);
+
+ if (NULL==(leaf = H5FL_MALLOC(H5B2_leaf_t)))
+ HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ HDmemset(&leaf->cache_info,0,sizeof(H5AC_info_t));
+
+ /* Share common B-tree information */
+ leaf->shared = bt2->shared;
+ H5RC_INC(leaf->shared);
+
+ /* Get the pointer to the shared B-tree info */
+ shared=H5RC_GET_OBJ(leaf->shared);
+ HDassert(shared);
+
+ /* Read header from disk */
+ if (H5F_block_read(f, H5FD_MEM_BTREE, addr, shared->node_size, dxpl_id, shared->page)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_READERROR, NULL, "can't read B-tree leaf node")
+
+ p = shared->page;
+
+ /* magic number */
+ if (HDmemcmp(p, H5B2_LEAF_MAGIC, H5B2_SIZEOF_MAGIC))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree leaf node signature")
+ p += H5B2_SIZEOF_MAGIC;
+
+ /* version */
+ if (*p++ != H5B2_LEAF_VERSION)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree leaf node version")
+
+ /* B-tree type */
+ if (*p++ != (uint8_t)shared->type->id)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "incorrect B-tree type")
+
+ /* Allocate space for the native keys in memory */
+ if((leaf->leaf_native=H5FL_FAC_MALLOC(shared->leaf_fac))==NULL)
+ HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for B-tree leaf native keys")
+
+ /* Set the number of records in the leaf */
+ leaf->nrec = node_ptr->node_nrec;
+
+ /* Deserialize records for leaf node */
+ native=leaf->leaf_native;
+ for(u=0; u<leaf->nrec; u++) {
+ /* Decode record */
+ if((shared->type->decode)(f,p,native)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTENCODE, NULL, "unable to decode B-tree record");
+
+ /* Move to next record */
+ p += shared->rkey_size;
+ native += shared->type->nkey_size;
+ } /* end for */
+
+ /* Set return value */
+ ret_value = leaf;
+
+done:
+ if (!ret_value && leaf)
+ (void)H5B2_cache_leaf_dest(f,leaf);
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5B2_cache_leaf_load() */ /*lint !e818 Can't make udata a pointer to const */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_cache_leaf_flush
+ *
+ * Purpose: Flushes a dirty B-tree leaf node to disk.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 2 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B2_cache_leaf_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_leaf_t *leaf)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5B2_cache_leaf_flush, FAIL)
+
+ /* check arguments */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(leaf);
+
+ if (leaf->cache_info.is_dirty) {
+ H5B2_shared_t *shared; /* Shared B-tree information */
+ uint8_t *p; /* Pointer into raw data buffer */
+ uint8_t *native; /* Pointer to native keys */
+ unsigned u; /* Local index variable */
+
+ /* Get the pointer to the shared B-tree info */
+ shared=H5RC_GET_OBJ(leaf->shared);
+ HDassert(shared);
+
+ p = shared->page;
+
+ /* magic number */
+ HDmemcpy(p, H5B2_LEAF_MAGIC, H5B2_SIZEOF_MAGIC);
+ p += H5B2_SIZEOF_MAGIC;
+
+ /* version # */
+ *p++ = H5B2_LEAF_VERSION;
+
+ /* b-tree type */
+ *p++ = shared->type->id;
+
+ /* Serialize records for leaf node */
+ native=leaf->leaf_native;
+ for(u=0; u<leaf->nrec; u++) {
+ /* Encode record */
+ if((shared->type->encode)(f,p,native)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTENCODE, FAIL, "unable to encode B-tree record");
+
+ /* Move to next record */
+ p += shared->rkey_size;
+ native += shared->type->nkey_size;
+ } /* end for */
+
+ /* Write the B-tree leaf node */
+ if (H5F_block_write(f, H5FD_MEM_BTREE, addr, shared->node_size, dxpl_id, shared->page) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTFLUSH, FAIL, "unable to save B-tree leaf node to disk")
+
+ leaf->cache_info.is_dirty = FALSE;
+ } /* end if */
+
+ if (destroy)
+ if (H5B2_cache_leaf_dest(f,leaf) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree leaf node")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5B2_cache_leaf_flush() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B_cache_leaf_dest
+ *
+ * Purpose: Destroys a B-tree leaf node in memory.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 2 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+herr_t
+H5B2_cache_leaf_dest(H5F_t UNUSED *f, H5B2_leaf_t *leaf)
+{
+ H5B2_shared_t *shared; /* Shared B-tree information */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5B2_cache_leaf_dest)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(leaf);
+
+ /* Get the pointer to the shared B-tree info */
+ shared=H5RC_GET_OBJ(leaf->shared);
+ HDassert(shared);
+
+ /* Release leaf's native key buffer */
+ if(leaf->leaf_native)
+ H5FL_FAC_FREE(shared->leaf_fac,leaf->leaf_native);
+
+ /* Decrement reference count on shared B-tree info */
+ if(leaf->shared)
+ H5RC_DEC(leaf->shared);
+
+ /* Free B-tree leaf node info */
+ H5FL_FREE(H5B2_leaf_t,leaf);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5B2_cache_leaf_dest() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_cache_leaf_clear
+ *
+ * Purpose: Mark a B-tree leaf node in memory as non-dirty.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 2 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B2_cache_leaf_clear(H5F_t *f, H5B2_leaf_t *leaf, hbool_t destroy)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT(H5B2_cache_leaf_clear)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(leaf);
+
+ /* Reset the dirty flag. */
+ leaf->cache_info.is_dirty = FALSE;
+
+ if (destroy)
+ if (H5B2_cache_leaf_dest(f, leaf) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree leaf node")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5B2_cache_leaf_clear() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_cache_leaf_size
+ *
+ * Purpose: Compute the size in bytes of a B-tree leaf node
+ * on disk, and return it in *size_ptr. On failure,
+ * the value of *size_ptr is undefined.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 2 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B2_cache_leaf_size(const H5F_t UNUSED *f, const H5B2_leaf_t *leaf, size_t *size_ptr)
+{
+ H5B2_shared_t *shared; /* Shared B-tree information */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5B2_cache_leaf_size)
+
+ /* check arguments */
+ HDassert(leaf);
+ HDassert(size_ptr);
+
+ /* Get the pointer to the shared B-tree info */
+ shared=H5RC_GET_OBJ(leaf->shared);
+ HDassert(shared);
+
+ /* Set size value */
+ *size_ptr = shared->node_size;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5B2_cache_leaf_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_cache_internal_load
+ *
+ * Purpose: Loads a B-tree internal node from the disk.
+ *
+ * Return: Success: Pointer to a new B-tree internal node.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 2 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5B2_internal_t *
+H5B2_cache_internal_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_bt2, void *_node_ptr)
+{
+ const H5B2_t *bt2 = (const H5B2_t *)_bt2;
+ H5B2_node_ptr_t *node_ptr = (H5B2_node_ptr_t *)_node_ptr;
+ H5B2_internal_t *internal = NULL;
+ H5B2_shared_t *shared; /* Shared B-tree information */
+ uint8_t *p; /* Pointer into raw data buffer */
+ uint8_t *native; /* Pointer to native record info */
+ H5B2_node_ptr_t *int_node_ptr; /* Pointer to node pointer info */
+ unsigned u; /* Local index variable */
+ H5B2_internal_t *ret_value;
+
+ FUNC_ENTER_NOAPI(H5B2_cache_internal_load, NULL)
+
+ /* Check arguments */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(bt2);
+
+ if (NULL==(internal = H5FL_MALLOC(H5B2_internal_t)))
+ HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ HDmemset(&internal->cache_info,0,sizeof(H5AC_info_t));
+
+ /* Share common B-tree information */
+ internal->shared = bt2->shared;
+ H5RC_INC(internal->shared);
+
+ /* Get the pointer to the shared B-tree info */
+ shared=H5RC_GET_OBJ(internal->shared);
+ HDassert(shared);
+
+ /* Read header from disk */
+ if (H5F_block_read(f, H5FD_MEM_BTREE, addr, shared->node_size, dxpl_id, shared->page)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_READERROR, NULL, "can't read B-tree internal node")
+
+ p = shared->page;
+
+ /* magic number */
+ if (HDmemcmp(p, H5B2_INT_MAGIC, H5B2_SIZEOF_MAGIC))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree internal node signature")
+ p += H5B2_SIZEOF_MAGIC;
+
+ /* version */
+ if (*p++ != H5B2_INT_VERSION)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree internal node version")
+
+ /* B-tree type */
+ if (*p++ != (uint8_t)shared->type->id)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "incorrect B-tree type")
+
+ /* Allocate space for the native keys in memory */
+ if((internal->int_native=H5FL_FAC_MALLOC(shared->int_fac))==NULL)
+ HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for B-tree internal native keys")
+
+ /* Allocate space for the node pointers in memory */
+ if((internal->node_ptrs=H5FL_FAC_MALLOC(shared->node_ptr_fac))==NULL)
+ HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for B-tree internal node pointers")
+
+ /* Set the number of records in the leaf */
+ internal->nrec = node_ptr->node_nrec;
+
+ /* Deserialize records for internal node */
+ native=internal->int_native;
+ for(u=0; u<internal->nrec; u++) {
+ /* Decode record */
+ if((shared->type->decode)(f,p,native)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTENCODE, NULL, "unable to decode B-tree record");
+
+ /* Move to next record */
+ p += shared->rkey_size;
+ native += shared->type->nkey_size;
+ } /* end for */
+
+ /* Serialize node pointers for internal node */
+ int_node_ptr=internal->node_ptrs;
+ for(u=0; u<internal->nrec+1; u++) {
+ /* Decode node pointer */
+ H5F_addr_decode(f, (const uint8_t **)&p, &(int_node_ptr->addr));
+ UINT16DECODE(p, int_node_ptr->node_nrec);
+ H5F_DECODE_LENGTH(f, p, int_node_ptr->all_nrec);
+
+ /* Move to next node pointer */
+ int_node_ptr++;
+ } /* end for */
+
+ /* Set return value */
+ ret_value = internal;
+
+done:
+ if (!ret_value && internal)
+ (void)H5B2_cache_internal_dest(f,internal);
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5B2_cache_internal_load() */ /*lint !e818 Can't make udata a pointer to const */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_cache_internal_flush
+ *
+ * Purpose: Flushes a dirty B-tree internal node to disk.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 3 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B2_cache_internal_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_internal_t *internal)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5B2_cache_internal_flush, FAIL)
+
+ /* check arguments */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(internal);
+
+ if (internal->cache_info.is_dirty) {
+ H5B2_shared_t *shared; /* Shared B-tree information */
+ uint8_t *p; /* Pointer into raw data buffer */
+ uint8_t *native; /* Pointer to native record info */
+ H5B2_node_ptr_t *int_node_ptr; /* Pointer to node pointer info */
+ unsigned u; /* Local index variable */
+
+ /* Get the pointer to the shared B-tree info */
+ shared=H5RC_GET_OBJ(internal->shared);
+ HDassert(shared);
+
+ p = shared->page;
+
+ /* magic number */
+ HDmemcpy(p, H5B2_INT_MAGIC, H5B2_SIZEOF_MAGIC);
+ p += H5B2_SIZEOF_MAGIC;
+
+ /* version # */
+ *p++ = H5B2_INT_VERSION;
+
+ /* b-tree type */
+ *p++ = shared->type->id;
+
+ /* Serialize records for internal node */
+ native=internal->int_native;
+ for(u=0; u<internal->nrec; u++) {
+ /* Encode record */
+ if((shared->type->encode)(f,p,native)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTENCODE, FAIL, "unable to encode B-tree record");
+
+ /* Move to next record */
+ p += shared->rkey_size;
+ native += shared->type->nkey_size;
+ } /* end for */
+
+ /* Serialize node pointers for internal node */
+ int_node_ptr=internal->node_ptrs;
+ for(u=0; u<internal->nrec+1; u++) {
+ /* Encode node pointer */
+ H5F_addr_encode(f, &p, int_node_ptr->addr);
+ UINT16ENCODE(p, int_node_ptr->node_nrec);
+ H5F_ENCODE_LENGTH(f, p, int_node_ptr->all_nrec);
+
+ /* Move to next node pointer */
+ int_node_ptr++;
+ } /* end for */
+
+ /* Write the B-tree internal node */
+ if (H5F_block_write(f, H5FD_MEM_BTREE, addr, shared->node_size, dxpl_id, shared->page) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTFLUSH, FAIL, "unable to save B-tree internal node to disk")
+
+ internal->cache_info.is_dirty = FALSE;
+ } /* end if */
+
+ if (destroy)
+ if (H5B2_cache_internal_dest(f,internal) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree internal node")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5B2_cache_internal_flush() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B_cache_internal_dest
+ *
+ * Purpose: Destroys a B-tree internal node in memory.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 2 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+herr_t
+H5B2_cache_internal_dest(H5F_t UNUSED *f, H5B2_internal_t *internal)
+{
+ H5B2_shared_t *shared; /* Shared B-tree information */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5B2_cache_internal_dest)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(internal);
+
+ /* Get the pointer to the shared B-tree info */
+ shared=H5RC_GET_OBJ(internal->shared);
+ HDassert(shared);
+
+ /* Release internal node's native key buffer */
+ if(internal->int_native)
+ H5FL_FAC_FREE(shared->int_fac,internal->int_native);
+
+ /* Release internal node's node pointer buffer */
+ if(internal->node_ptrs)
+ H5FL_FAC_FREE(shared->node_ptr_fac,internal->node_ptrs);
+
+ /* Decrement reference count on shared B-tree info */
+ if(internal->shared)
+ H5RC_DEC(internal->shared);
+
+ /* Free B-tree internal node info */
+ H5FL_FREE(H5B2_internal_t,internal);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5B2_cache_internal_dest() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_cache_internal_clear
+ *
+ * Purpose: Mark a B-tree internal node in memory as non-dirty.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 2 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B2_cache_internal_clear(H5F_t *f, H5B2_internal_t *internal, hbool_t destroy)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT(H5B2_cache_internal_clear)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(internal);
+
+ /* Reset the dirty flag. */
+ internal->cache_info.is_dirty = FALSE;
+
+ if (destroy)
+ if (H5B2_cache_internal_dest(f, internal) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree internal node")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5B2_cache_internal_clear() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_cache_internal_size
+ *
+ * Purpose: Compute the size in bytes of a B-tree internal node
+ * on disk, and return it in *size_ptr. On failure,
+ * the value of *size_ptr is undefined.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 2 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B2_cache_internal_size(const H5F_t UNUSED *f, const H5B2_internal_t *internal, size_t *size_ptr)
+{
+ H5B2_shared_t *shared; /* Shared B-tree information */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5B2_cache_internal_size)
+
+ /* check arguments */
+ HDassert(internal);
+ HDassert(size_ptr);
+
+ /* Get the pointer to the shared B-tree info */
+ shared=H5RC_GET_OBJ(internal->shared);
+ HDassert(shared);
+
+ /* Set size value */
+ *size_ptr = shared->node_size;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5B2_cache_internal_size() */
+
+
diff --git a/src/H5B2dbg.c b/src/H5B2dbg.c
index 6e8af60..bd18582 100644
--- a/src/H5B2dbg.c
+++ b/src/H5B2dbg.c
@@ -31,9 +31,6 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5FLprivate.h" /* Free Lists */
-/* H5B2 inherits cache-like properties from H5AC */
-extern const H5AC_class_t H5AC_BT2_HDR[1];
-
/*-------------------------------------------------------------------------
* Function: H5B2_hdr_debug
diff --git a/src/H5B2pkg.h b/src/H5B2pkg.h
index 1f98cac..001d0ca 100644
--- a/src/H5B2pkg.h
+++ b/src/H5B2pkg.h
@@ -44,8 +44,27 @@
/* B-tree signatures */
#define H5B2_HDR_MAGIC "BTHD" /* Header */
+#define H5B2_INT_MAGIC "BTND" /* Internal node */
#define H5B2_LEAF_MAGIC "BTLF" /* Leaf node */
+/* Size of storage for number of records per node (on disk) */
+#define H5B2_SIZEOF_RECORDS_PER_NODE 2
+
+/* Size of a "node pointer" (on disk) */
+#define H5B2_NODE_POINTER_SIZE(f) (H5F_SIZEOF_ADDR(f)+H5B2_SIZEOF_RECORDS_PER_NODE+H5F_SIZEOF_SIZE(f))
+
+/* Size of the B-tree header on disk */
+#define H5B2_HEADER_SIZE(f) ( \
+ 4 + /* Signature */ \
+ 1 + /* Version */ \
+ 1 + /* Tree type */ \
+ 4 + /* Node size, in bytes */ \
+ 2 + /* Key size, in bytes */ \
+ 2 + /* Depth of tree */ \
+ 2 + /* Split % of full (as integer, ie. "98" means 98%) */ \
+ 2 + /* Merge % of full (as integer, ie. "98" means 98%) */ \
+ H5B2_NODE_POINTER_SIZE(f)) /* Node pointer to root node in tree */
+
/****************************/
/* Package Private Typedefs */
/****************************/
@@ -67,9 +86,7 @@ typedef struct H5B2_shared_t {
H5FL_fac_head_t *int_fac; /* Factory for internal node native key blocks */
H5FL_fac_head_t *leaf_fac; /* Factory for leaf node native key blocks */
H5FL_fac_head_t *node_ptr_fac; /* Factory for internal node node pointer blocks */
- size_t *int_nat_off; /* Array of offsets of native keys in internal node block */
- size_t *leaf_nat_off; /* Array of offsets of native keys in leaf node block */
- size_t *node_ptr_off; /* Array of offsets of node pointers in internal node block */
+ size_t *nat_off; /* Array of offsets of native keys */
/* Information set by user */
unsigned split_percent; /* Percent full at which to split the node, when inserting */
@@ -97,7 +114,7 @@ typedef struct H5B2_t {
H5RC_t *shared; /* Ref-counted shared info */
} H5B2_t;
-/* B-tree leaf information */
+/* B-tree leaf node information */
typedef struct H5B2_leaf_t {
/* Information for H5AC cache functions, _must_ be first field in structure */
H5AC_info_t cache_info;
@@ -105,12 +122,54 @@ typedef struct H5B2_leaf_t {
/* Internal B-tree information */
H5RC_t *shared; /* Ref-counted shared info */
uint8_t *leaf_native; /* Pointer to native keys */
- unsigned nrec; /* Number of records in leaf node */
+ unsigned nrec; /* Number of records in node */
} H5B2_leaf_t;
+/* B-tree internal node information */
+typedef struct H5B2_internal_t {
+ /* Information for H5AC cache functions, _must_ be first field in structure */
+ H5AC_info_t cache_info;
+
+ /* Internal B-tree information */
+ H5RC_t *shared; /* Ref-counted shared info */
+ uint8_t *int_native; /* Pointer to native keys */
+ H5B2_node_ptr_t *node_ptrs; /* Pointer to node pointers */
+ unsigned nrec; /* Number of records in node */
+} H5B2_internal_t;
+
+
+/*****************************/
+/* Package Private Variables */
+/*****************************/
+
+/* H5B2 header inherits cache-like properties from H5AC */
+H5_DLLVAR const H5AC_class_t H5AC_BT2_HDR[1];
+
+/* H5B2 internal node inherits cache-like properties from H5AC */
+H5_DLLVAR const H5AC_class_t H5AC_BT2_INT[1];
+
+/* H5B2 leaf node inherits cache-like properties from H5AC */
+H5_DLLVAR const H5AC_class_t H5AC_BT2_LEAF[1];
+
+/* Declare a free list to manage the H5B2_t struct */
+H5FL_EXTERN(H5B2_t);
+
+/* Declare a free list to manage the H5B2_internal_t struct */
+H5FL_EXTERN(H5B2_internal_t);
+
+/* Declare a free list to manage the H5B2_leaf_t struct */
+H5FL_EXTERN(H5B2_leaf_t);
+
+
/******************************/
/* Package Private Prototypes */
/******************************/
+H5_DLL herr_t H5B2_shared_free (void *_shared);
+H5_DLL herr_t H5B2_shared_init (H5F_t *f, H5B2_t *bt2, const H5B2_class_t *type,
+ size_t node_size, size_t rkey_size, unsigned split_percent, unsigned merge_percent);
+H5_DLL herr_t H5B2_cache_hdr_dest(H5F_t *f, H5B2_t *b);
+H5_DLL herr_t H5B2_cache_leaf_dest(H5F_t *f, H5B2_leaf_t *l);
+H5_DLL herr_t H5B2_cache_internal_dest(H5F_t *f, H5B2_internal_t *i);
H5_DLL herr_t H5B2_hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr,
FILE *stream, int indent, int fwidth, const H5B2_class_t *type);
diff --git a/src/H5B2private.h b/src/H5B2private.h
index 5d8d42a..bd1515a 100644
--- a/src/H5B2private.h
+++ b/src/H5B2private.h
@@ -72,8 +72,11 @@ typedef struct H5B2_class_t {
/* Compare records, according to a key */
herr_t (*compare)(const H5F_t *f, hid_t dxpl_id, const void *rec1, const void *rec2); /* Compare two native records */
- /* Encode, decode, debug record values */
- herr_t (*encode)(const H5F_t *f, uint8_t *raw, const void *record); /* Store record in native key table */
+ /* Encode & decode record values */
+ herr_t (*encode)(const H5F_t *f, uint8_t *raw, const void *record); /* Encode record from native form to disk storage form */
+ herr_t (*decode)(const H5F_t *f, const uint8_t *raw, void *record); /* Decode record from disk storage form to native form */
+
+ /* Debug record values */
} H5B2_class_t;
diff --git a/src/H5FLprivate.h b/src/H5FLprivate.h
index cc19d99..1ced06a 100644
--- a/src/H5FLprivate.h
+++ b/src/H5FLprivate.h
@@ -73,10 +73,10 @@ typedef struct H5FL_reg_head_t {
#define H5FL_DEFINE_COMMON(t) H5FL_reg_head_t H5FL_REG_NAME(t)={0,0,0,0,#t,sizeof(t),NULL}
/* Declare a free list to manage objects of type 't' */
-#define H5FL_DEFINE(t) H5_DLL H5FL_DEFINE_COMMON(t)
+#define H5FL_DEFINE(t) H5FL_DEFINE_COMMON(t)
/* Reference a free list for type 't' defined in another file */
-#define H5FL_EXTERN(t) extern H5_DLL H5FL_reg_head_t H5FL_REG_NAME(t)
+#define H5FL_EXTERN(t) H5_DLLVAR H5FL_reg_head_t H5FL_REG_NAME(t)
/* Declare a static free list to manage objects of type 't' */
#define H5FL_DEFINE_STATIC(t) static H5FL_DEFINE_COMMON(t)
@@ -99,8 +99,8 @@ typedef struct H5FL_reg_head_t {
/* Common macro for H5FL_DEFINE & H5FL_DEFINE_STATIC */
#define H5FL_DEFINE_COMMON(t) int H5FL_REG_NAME(t)
-#define H5FL_DEFINE(t) H5_DLL H5FL_DEFINE_COMMON(t)
-#define H5FL_EXTERN(t) extern H5_DLL int H5FL_REG_NAME(t)
+#define H5FL_DEFINE(t) H5FL_DEFINE_COMMON(t)
+#define H5FL_EXTERN(t) H5_DLLVAR int H5FL_REG_NAME(t)
#define H5FL_DEFINE_STATIC(t) static H5FL_DEFINE_COMMON(t)
#define H5FL_MALLOC(t) H5MM_malloc(sizeof(t))
#define H5FL_CALLOC(t) H5MM_calloc(sizeof(t))
@@ -142,10 +142,10 @@ typedef struct H5FL_blk_head_t {
#define H5FL_BLK_DEFINE_COMMON(t) H5FL_blk_head_t H5FL_BLK_NAME(t)={0,0,0,0,#t"_blk",NULL}
/* Declare a free list to manage objects of type 't' */
-#define H5FL_BLK_DEFINE(t) H5_DLL H5FL_BLK_DEFINE_COMMON(t)
+#define H5FL_BLK_DEFINE(t) H5FL_BLK_DEFINE_COMMON(t)
/* Reference a free list for type 't' defined in another file */
-#define H5FL_BLK_EXTERN(t) extern H5_DLL H5FL_blk_head_t H5FL_BLK_NAME(t)
+#define H5FL_BLK_EXTERN(t) H5_DLLVAR H5FL_blk_head_t H5FL_BLK_NAME(t)
/* Declare a static free list to manage objects of type 't' */
#define H5FL_BLK_DEFINE_STATIC(t) static H5FL_BLK_DEFINE_COMMON(t)
@@ -169,8 +169,8 @@ typedef struct H5FL_blk_head_t {
/* Common macro for H5FL_BLK_DEFINE & H5FL_BLK_DEFINE_STATIC */
#define H5FL_BLK_DEFINE_COMMON(t) int H5FL_BLK_NAME(t)
-#define H5FL_BLK_DEFINE(t) H5_DLL H5FL_BLK_DEFINE_COMMON(t)
-#define H5FL_BLK_EXTERN(t) extern H5_DLL int H5FL_BLK_NAME(t)
+#define H5FL_BLK_DEFINE(t) H5FL_BLK_DEFINE_COMMON(t)
+#define H5FL_BLK_EXTERN(t) H5_DLLVAR int H5FL_BLK_NAME(t)
#define H5FL_BLK_DEFINE_STATIC(t) static H5FL_BLK_DEFINE_COMMON(t)
#define H5FL_BLK_MALLOC(t,size) H5MM_malloc(size)
#define H5FL_BLK_CALLOC(t,size) H5MM_calloc(size)
@@ -214,10 +214,10 @@ typedef struct H5FL_arr_head_t {
#define H5FL_ARR_DEFINE_COMMON(t,m) H5FL_arr_head_t H5FL_ARR_NAME(t)={0,0,0,#t"_arr",m+1,sizeof(t),NULL}
/* Declare a free list to manage arrays of type 't' */
-#define H5FL_ARR_DEFINE(t,m) H5_DLL H5FL_ARR_DEFINE_COMMON(t,m)
+#define H5FL_ARR_DEFINE(t,m) H5FL_ARR_DEFINE_COMMON(t,m)
/* Reference a free list for arrays of type 't' defined in another file */
-#define H5FL_ARR_EXTERN(t) extern H5_DLL H5FL_arr_head_t H5FL_ARR_NAME(t)
+#define H5FL_ARR_EXTERN(t) H5_DLLVAR H5FL_arr_head_t H5FL_ARR_NAME(t)
/* Declare a static free list to manage arrays of type 't' */
#define H5FL_ARR_DEFINE_STATIC(t,m) static H5FL_ARR_DEFINE_COMMON(t,m)
@@ -238,8 +238,8 @@ typedef struct H5FL_arr_head_t {
/* Common macro for H5FL_ARR_DEFINE & H5FL_ARR_DEFINE_STATIC */
#define H5FL_ARR_DEFINE_COMMON(t,m) int H5FL_ARR_NAME(t)
-#define H5FL_ARR_DEFINE(t,m) H5_DLL H5FL_ARR_DEFINE_COMMON(t,m)
-#define H5FL_ARR_EXTERN(t) extern H5_DLL int H5FL_ARR_NAME(t)
+#define H5FL_ARR_DEFINE(t,m) H5FL_ARR_DEFINE_COMMON(t,m)
+#define H5FL_ARR_EXTERN(t) H5_DLLVAR int H5FL_ARR_NAME(t)
#define H5FL_ARR_DEFINE_STATIC(t,m) static H5FL_ARR_DEFINE_COMMON(t,m)
#define H5FL_ARR_MALLOC(t,elem) H5MM_malloc((elem)*sizeof(t))
#define H5FL_ARR_CALLOC(t,elem) H5MM_calloc((elem)*sizeof(t))
@@ -265,10 +265,10 @@ typedef struct H5FL_seq_head_t {
#define H5FL_SEQ_DEFINE_COMMON(t) H5FL_seq_head_t H5FL_SEQ_NAME(t)={{0,0,0,0,#t"_seq",NULL},sizeof(t)}
/* Declare a free list to manage sequences of type 't' */
-#define H5FL_SEQ_DEFINE(t) H5_DLL H5FL_SEQ_DEFINE_COMMON(t)
+#define H5FL_SEQ_DEFINE(t) H5FL_SEQ_DEFINE_COMMON(t)
/* Reference a free list for sequences of type 't' defined in another file */
-#define H5FL_SEQ_EXTERN(t) extern H5_DLL H5FL_seq_head_t H5FL_SEQ_NAME(t)
+#define H5FL_SEQ_EXTERN(t) H5_DLLVAR H5FL_seq_head_t H5FL_SEQ_NAME(t)
/* Declare a static free list to manage sequences of type 't' */
#define H5FL_SEQ_DEFINE_STATIC(t) static H5FL_SEQ_DEFINE_COMMON(t)
@@ -289,8 +289,8 @@ typedef struct H5FL_seq_head_t {
/* Common macro for H5FL_BLK_DEFINE & H5FL_BLK_DEFINE_STATIC */
#define H5FL_SEQ_DEFINE_COMMON(t) int H5FL_SEQ_NAME(t)
-#define H5FL_SEQ_DEFINE(t) H5_DLL H5FL_SEQ_DEFINE_COMMON(t)
-#define H5FL_SEQ_EXTERN(t) extern H5_DLL int H5FL_SEQ_NAME(t)
+#define H5FL_SEQ_DEFINE(t) H5FL_SEQ_DEFINE_COMMON(t)
+#define H5FL_SEQ_EXTERN(t) H5_DLLVAR int H5FL_SEQ_NAME(t)
#define H5FL_SEQ_DEFINE_STATIC(t) static H5FL_SEQ_DEFINE_COMMON(t)
#define H5FL_SEQ_MALLOC(t,elem) H5MM_malloc((elem)*sizeof(t))
#define H5FL_SEQ_CALLOC(t,elem) H5MM_calloc((elem)*sizeof(t))
diff --git a/src/Makefile.am b/src/Makefile.am
index 112b9e9..d3a9fba 100755
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -39,12 +39,13 @@ MOSTLYCLEANFILES=H5detect.o H5detect.lo H5detect H5Tinit.o H5Tinit.lo H5Tinit.c
DISTCLEAN=libhdf5.settings
# library sources
-libhdf5_la_SOURCES= H5.c H5A.c H5AC.c H5B.c H5B2.c H5B2dbg.c H5C.c H5D.c \
+libhdf5_la_SOURCES= H5.c H5A.c H5AC.c H5B.c H5B2.c H5B2cache.c H5B2dbg.c H5C.c \
+ H5D.c \
H5Dcontig.c \
H5Dcompact.c \
H5Defl.c H5Dio.c H5Distore.c H5Dmpio.c H5Dselect.c H5Dtest.c H5E.c H5F.c \
H5Fdbg.c H5FD.c H5FDcore.c \
- H5FDfamily.c H5FDfphdf5.c H5FDgass.c H5FDlog.c H5FDmpi.c H5FDmpio.c \
+ H5FDfamily.c H5FDfphdf5.c H5FDgass.c H5FDlog.c H5FDmpi.c H5FDmpio.c \
H5FDmpiposix.c H5FDmulti.c H5FDsec2.c H5FDsrb.c H5FDstdio.c \
H5FDstream.c H5FL.c H5FO.c H5FP.c H5FPclient.c H5FPserver.c H5FS.c \
H5G.c H5Gent.c H5Gnode.c H5Gstab.c \
@@ -54,7 +55,7 @@ libhdf5_la_SOURCES= H5.c H5A.c H5AC.c H5B.c H5B2.c H5B2dbg.c H5C.c H5D.c \
H5Oname.c H5Onull.c H5Opline.c H5Osdspace.c H5Oshared.c H5Ostab.c \
H5P.c H5Pdcpl.c H5Pdxpl.c H5Pfapl.c H5Pfcpl.c H5Ptest.c H5R.c H5RC.c \
H5RS.c H5S.c H5Sall.c H5Shyper.c H5Smpio.c H5Snone.c H5Spoint.c \
- H5Sselect.c H5Stest.c H5SL.c H5ST.c H5T.c H5Tarray.c H5Tbit.c H5Tcommit.c \
+ H5Sselect.c H5Stest.c H5SL.c H5ST.c H5T.c H5Tarray.c H5Tbit.c H5Tcommit.c \
H5Tcompound.c H5Tconv.c H5Tcset.c H5Tenum.c H5Tfields.c H5Tfixed.c \
H5Tfloat.c H5Tinit.c H5Tnative.c H5Toffset.c H5Topaque.c H5Torder.c \
H5Tpad.c H5Tprecis.c H5Tstrpad.c H5Tvlen.c H5TS.c H5V.c H5Z.c \
diff --git a/src/Makefile.in b/src/Makefile.in
index 0d69855..3299112 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -219,12 +219,13 @@ MOSTLYCLEANFILES = H5detect.o H5detect.lo H5detect H5Tinit.o H5Tinit.lo H5Tinit.
DISTCLEAN = libhdf5.settings
# library sources
-libhdf5_la_SOURCES = H5.c H5A.c H5AC.c H5B.c H5B2.c H5B2dbg.c H5C.c H5D.c \
+libhdf5_la_SOURCES = H5.c H5A.c H5AC.c H5B.c H5B2.c H5B2cache.c H5B2dbg.c H5C.c \
+ H5D.c \
H5Dcontig.c \
H5Dcompact.c \
H5Defl.c H5Dio.c H5Distore.c H5Dmpio.c H5Dselect.c H5Dtest.c H5E.c H5F.c \
H5Fdbg.c H5FD.c H5FDcore.c \
- H5FDfamily.c H5FDfphdf5.c H5FDgass.c H5FDlog.c H5FDmpi.c H5FDmpio.c \
+ H5FDfamily.c H5FDfphdf5.c H5FDgass.c H5FDlog.c H5FDmpi.c H5FDmpio.c \
H5FDmpiposix.c H5FDmulti.c H5FDsec2.c H5FDsrb.c H5FDstdio.c \
H5FDstream.c H5FL.c H5FO.c H5FP.c H5FPclient.c H5FPserver.c H5FS.c \
H5G.c H5Gent.c H5Gnode.c H5Gstab.c \
@@ -234,7 +235,7 @@ libhdf5_la_SOURCES = H5.c H5A.c H5AC.c H5B.c H5B2.c H5B2dbg.c H5C.c H5D.c \
H5Oname.c H5Onull.c H5Opline.c H5Osdspace.c H5Oshared.c H5Ostab.c \
H5P.c H5Pdcpl.c H5Pdxpl.c H5Pfapl.c H5Pfcpl.c H5Ptest.c H5R.c H5RC.c \
H5RS.c H5S.c H5Sall.c H5Shyper.c H5Smpio.c H5Snone.c H5Spoint.c \
- H5Sselect.c H5Stest.c H5SL.c H5ST.c H5T.c H5Tarray.c H5Tbit.c H5Tcommit.c \
+ H5Sselect.c H5Stest.c H5SL.c H5ST.c H5T.c H5Tarray.c H5Tbit.c H5Tcommit.c \
H5Tcompound.c H5Tconv.c H5Tcset.c H5Tenum.c H5Tfields.c H5Tfixed.c \
H5Tfloat.c H5Tinit.c H5Tnative.c H5Toffset.c H5Topaque.c H5Torder.c \
H5Tpad.c H5Tprecis.c H5Tstrpad.c H5Tvlen.c H5TS.c H5V.c H5Z.c \
@@ -288,27 +289,27 @@ LTLIBRARIES = $(lib_LTLIBRARIES)
libhdf5_la_LDFLAGS =
libhdf5_la_LIBADD =
-am_libhdf5_la_OBJECTS = H5.lo H5A.lo H5AC.lo H5B.lo H5B2.lo H5B2dbg.lo \
- H5C.lo H5D.lo H5Dcontig.lo H5Dcompact.lo H5Defl.lo H5Dio.lo \
- H5Distore.lo H5Dmpio.lo H5Dselect.lo H5Dtest.lo H5E.lo H5F.lo \
- H5Fdbg.lo H5FD.lo H5FDcore.lo H5FDfamily.lo H5FDfphdf5.lo \
- H5FDgass.lo H5FDlog.lo H5FDmpi.lo H5FDmpio.lo H5FDmpiposix.lo \
- H5FDmulti.lo H5FDsec2.lo H5FDsrb.lo H5FDstdio.lo H5FDstream.lo \
- H5FL.lo H5FO.lo H5FP.lo H5FPclient.lo H5FPserver.lo H5FS.lo \
- H5G.lo H5Gent.lo H5Gnode.lo H5Gstab.lo H5HG.lo H5HGdbg.lo \
- H5HL.lo H5HLdbg.lo H5HP.lo H5I.lo H5MF.lo H5MM.lo H5O.lo \
- H5Oattr.lo H5Obogus.lo H5Ocont.lo H5Odtype.lo H5Oefl.lo \
- H5Ofill.lo H5Olayout.lo H5Omtime.lo H5Oname.lo H5Onull.lo \
- H5Opline.lo H5Osdspace.lo H5Oshared.lo H5Ostab.lo H5P.lo \
- H5Pdcpl.lo H5Pdxpl.lo H5Pfapl.lo H5Pfcpl.lo H5Ptest.lo H5R.lo \
- H5RC.lo H5RS.lo H5S.lo H5Sall.lo H5Shyper.lo H5Smpio.lo \
- H5Snone.lo H5Spoint.lo H5Sselect.lo H5Stest.lo H5SL.lo H5ST.lo \
- H5T.lo H5Tarray.lo H5Tbit.lo H5Tcommit.lo H5Tcompound.lo \
- H5Tconv.lo H5Tcset.lo H5Tenum.lo H5Tfields.lo H5Tfixed.lo \
- H5Tfloat.lo H5Tinit.lo H5Tnative.lo H5Toffset.lo H5Topaque.lo \
- H5Torder.lo H5Tpad.lo H5Tprecis.lo H5Tstrpad.lo H5Tvlen.lo \
- H5TS.lo H5V.lo H5Z.lo H5Zdeflate.lo H5Zfletcher32.lo H5Znbit.lo \
- H5Zshuffle.lo H5Zszip.lo H5Ztrans.lo
+am_libhdf5_la_OBJECTS = H5.lo H5A.lo H5AC.lo H5B.lo H5B2.lo H5B2cache.lo \
+ H5B2dbg.lo H5C.lo H5D.lo H5Dcontig.lo H5Dcompact.lo H5Defl.lo \
+ H5Dio.lo H5Distore.lo H5Dmpio.lo H5Dselect.lo H5Dtest.lo H5E.lo \
+ H5F.lo H5Fdbg.lo H5FD.lo H5FDcore.lo H5FDfamily.lo \
+ H5FDfphdf5.lo H5FDgass.lo H5FDlog.lo H5FDmpi.lo H5FDmpio.lo \
+ H5FDmpiposix.lo H5FDmulti.lo H5FDsec2.lo H5FDsrb.lo \
+ H5FDstdio.lo H5FDstream.lo H5FL.lo H5FO.lo H5FP.lo \
+ H5FPclient.lo H5FPserver.lo H5FS.lo H5G.lo H5Gent.lo H5Gnode.lo \
+ H5Gstab.lo H5HG.lo H5HGdbg.lo H5HL.lo H5HLdbg.lo H5HP.lo H5I.lo \
+ H5MF.lo H5MM.lo H5O.lo H5Oattr.lo H5Obogus.lo H5Ocont.lo \
+ H5Odtype.lo H5Oefl.lo H5Ofill.lo H5Olayout.lo H5Omtime.lo \
+ H5Oname.lo H5Onull.lo H5Opline.lo H5Osdspace.lo H5Oshared.lo \
+ H5Ostab.lo H5P.lo H5Pdcpl.lo H5Pdxpl.lo H5Pfapl.lo H5Pfcpl.lo \
+ H5Ptest.lo H5R.lo H5RC.lo H5RS.lo H5S.lo H5Sall.lo H5Shyper.lo \
+ H5Smpio.lo H5Snone.lo H5Spoint.lo H5Sselect.lo H5Stest.lo \
+ H5SL.lo H5ST.lo H5T.lo H5Tarray.lo H5Tbit.lo H5Tcommit.lo \
+ H5Tcompound.lo H5Tconv.lo H5Tcset.lo H5Tenum.lo H5Tfields.lo \
+ H5Tfixed.lo H5Tfloat.lo H5Tinit.lo H5Tnative.lo H5Toffset.lo \
+ H5Topaque.lo H5Torder.lo H5Tpad.lo H5Tprecis.lo H5Tstrpad.lo \
+ H5Tvlen.lo H5TS.lo H5V.lo H5Z.lo H5Zdeflate.lo H5Zfletcher32.lo \
+ H5Znbit.lo H5Zshuffle.lo H5Zszip.lo H5Ztrans.lo
libhdf5_la_OBJECTS = $(am_libhdf5_la_OBJECTS)
noinst_PROGRAMS = H5detect$(EXEEXT)
PROGRAMS = $(noinst_PROGRAMS)
@@ -327,9 +328,9 @@ depcomp = $(SHELL) $(top_srcdir)/bin/depcomp
am__depfiles_maybe = depfiles
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/H5.Plo ./$(DEPDIR)/H5A.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/H5AC.Plo ./$(DEPDIR)/H5B.Plo \
-@AMDEP_TRUE@ ./$(DEPDIR)/H5B2.Plo ./$(DEPDIR)/H5B2dbg.Plo \
-@AMDEP_TRUE@ ./$(DEPDIR)/H5C.Plo ./$(DEPDIR)/H5D.Plo \
-@AMDEP_TRUE@ ./$(DEPDIR)/H5Dcompact.Plo \
+@AMDEP_TRUE@ ./$(DEPDIR)/H5B2.Plo ./$(DEPDIR)/H5B2cache.Plo \
+@AMDEP_TRUE@ ./$(DEPDIR)/H5B2dbg.Plo ./$(DEPDIR)/H5C.Plo \
+@AMDEP_TRUE@ ./$(DEPDIR)/H5D.Plo ./$(DEPDIR)/H5Dcompact.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/H5Dcontig.Plo ./$(DEPDIR)/H5Defl.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/H5Dio.Plo ./$(DEPDIR)/H5Distore.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/H5Dmpio.Plo ./$(DEPDIR)/H5Dselect.Plo \
@@ -484,6 +485,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5AC.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5B.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5B2.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5B2cache.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5B2dbg.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5C.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5D.Plo@am__quote@
diff --git a/test/btree2.c b/test/btree2.c
index 182c4fa..312f149 100644
--- a/test/btree2.c
+++ b/test/btree2.c
@@ -31,6 +31,8 @@ const char *FILENAME[] = {
NULL
};
+#define INSERT_SPLIT_ROOT_NREC 80
+
/*-------------------------------------------------------------------------
* Function: store
@@ -115,7 +117,44 @@ HDfprintf(stderr,"encode: data=%Hu\n",*(const hsize_t *)nrecord);
/*-------------------------------------------------------------------------
- * Function: test_basic
+ * Function: decode
+ *
+ * Purpose: Decode raw disk form of record into native form
+ *
+ * Return: Success: non-negative
+ *
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Friday, February 4, 2005
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+decode(const H5F_t *f, const uint8_t *raw, void *nrecord)
+{
+ H5F_DECODE_LENGTH(f, raw, *(hsize_t *)nrecord);
+
+#ifdef QAK
+HDfprintf(stderr,"encode: data=%Hu\n",*(const hsize_t *)nrecord);
+#endif /* QAK */
+ return(SUCCEED);
+}
+
+H5B2_class_t type={ /* B-tree class information */
+ 0, /* Type of B-tree */
+ sizeof(hsize_t), /* Size of native key */
+ store, /* Record storage callback */
+ compare, /* Record comparison callback */
+ encode, /* Record encoding callback */
+ decode /* Record decoding callback */
+};
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_insert_basic
*
* Purpose: Basic tests for the B-tree v2 code
*
@@ -131,18 +170,11 @@ HDfprintf(stderr,"encode: data=%Hu\n",*(const hsize_t *)nrecord);
*-------------------------------------------------------------------------
*/
static int
-test_basic_insert(hid_t fapl)
+test_insert_basic(hid_t fapl)
{
hid_t file=-1;
char filename[1024];
H5F_t *f=NULL;
- H5B2_class_t type={ /* B-tree class information */
- 0, /* Type of B-tree */
- sizeof(hsize_t), /* Size of native key */
- store, /* Record storage callback */
- compare, /* Record comparison callback */
- encode /* Record encoding callback */
- };
hsize_t record; /* Record to insert into tree */
haddr_t bt2_addr; /* Address of B-tree created */
@@ -164,7 +196,7 @@ test_basic_insert(hid_t fapl)
if (H5B2_create(f, H5P_DATASET_XFER_DEFAULT, &type, 512, 8, 100, 40, &bt2_addr/*out*/)<0) {
H5_FAILED();
H5Eprint_stack(H5E_DEFAULT, stdout);
- TEST_ERROR;
+ goto error;
}
PASSED();
@@ -176,7 +208,7 @@ test_basic_insert(hid_t fapl)
if (H5B2_insert(f, H5P_DATASET_XFER_DEFAULT, &type, bt2_addr, &record)<0) {
H5_FAILED();
H5Eprint_stack(H5E_DEFAULT, stdout);
- TEST_ERROR;
+ goto error;
}
/*
@@ -186,7 +218,7 @@ test_basic_insert(hid_t fapl)
if (H5B2_insert(f, H5P_DATASET_XFER_DEFAULT, &type, bt2_addr, &record)<0) {
H5_FAILED();
H5Eprint_stack(H5E_DEFAULT, stdout);
- TEST_ERROR;
+ goto error;
}
/*
@@ -196,7 +228,7 @@ test_basic_insert(hid_t fapl)
if (H5B2_insert(f, H5P_DATASET_XFER_DEFAULT, &type, bt2_addr, &record)<0) {
H5_FAILED();
H5Eprint_stack(H5E_DEFAULT, stdout);
- TEST_ERROR;
+ goto error;
}
/*
@@ -206,7 +238,7 @@ test_basic_insert(hid_t fapl)
if (H5B2_insert(f, H5P_DATASET_XFER_DEFAULT, &type, bt2_addr, &record)<0) {
H5_FAILED();
H5Eprint_stack(H5E_DEFAULT, stdout);
- TEST_ERROR;
+ goto error;
}
PASSED();
@@ -219,7 +251,96 @@ error:
H5Fclose(file);
} H5E_END_TRY;
return 1;
-}
+} /* test_insert_basic() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_insert_split_root
+ *
+ * Purpose: Basic tests for the B-tree v2 code. This test inserts enough
+ * records to split the root node and force the tree to depth 1.
+ * It also continues to add a few more records to each of the
+ * left and right leaf nodes after the split
+ *
+ * Return: Success: 0
+ *
+ * Failure: 1
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, February 3, 2005
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_insert_split_root(hid_t fapl)
+{
+ hid_t file=-1;
+ char filename[1024];
+ H5F_t *f=NULL;
+ hsize_t record; /* Record to insert into tree */
+ haddr_t bt2_addr; /* Address of B-tree created */
+ unsigned u; /* Local index variable */
+
+ h5_fixname(FILENAME[0], fapl, filename, sizeof filename);
+
+ /* Create the file to work on */
+ if ((file=H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR;
+
+ /* Get a pointer to the internal file object */
+ if (NULL==(f=H5I_object(file))) {
+ H5Eprint_stack(H5E_DEFAULT, stdout);
+ goto error;
+ }
+
+ /*
+ * Test v2 B-tree creation
+ */
+ if (H5B2_create(f, H5P_DATASET_XFER_DEFAULT, &type, 512, 8, 100, 40, &bt2_addr/*out*/)<0) {
+ H5_FAILED();
+ H5Eprint_stack(H5E_DEFAULT, stdout);
+ goto error;
+ }
+
+ /*
+ * Test inserting many records into v2 B-tree
+ */
+ TESTING("B-tree many - split root");
+
+ for(u=0; u<INSERT_SPLIT_ROOT_NREC; u++) {
+ record=u+10;
+ if (H5B2_insert(f, H5P_DATASET_XFER_DEFAULT, &type, bt2_addr, &record)<0) {
+ H5_FAILED();
+ H5Eprint_stack(H5E_DEFAULT, stdout);
+ goto error;
+ }
+ }
+ record=0;
+ if (H5B2_insert(f, H5P_DATASET_XFER_DEFAULT, &type, bt2_addr, &record)<0) {
+ H5_FAILED();
+ H5Eprint_stack(H5E_DEFAULT, stdout);
+ goto error;
+ }
+ record=1;
+ if (H5B2_insert(f, H5P_DATASET_XFER_DEFAULT, &type, bt2_addr, &record)<0) {
+ H5_FAILED();
+ H5Eprint_stack(H5E_DEFAULT, stdout);
+ goto error;
+ }
+
+ PASSED();
+
+ if (H5Fclose(file)<0) TEST_ERROR;
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Fclose(file);
+ } H5E_END_TRY;
+ return 1;
+} /* test_insert_split_root() */
/*-------------------------------------------------------------------------
@@ -249,8 +370,8 @@ main(void)
fapl = h5_fileaccess();
/* Test basic B-tree insertion */
- nerrors += test_basic_insert(fapl);
-/* nerrors += test_many_insert(fapl); */
+ nerrors += test_insert_basic(fapl);
+ nerrors += test_insert_split_root(fapl);
if (nerrors) goto error;
puts("All v2 B-tree tests passed.");