summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MANIFEST2
-rw-r--r--src/H5B2.c3321
-rw-r--r--src/H5B2cache.c150
-rw-r--r--src/H5B2int.c3357
-rw-r--r--src/H5B2pkg.h39
-rw-r--r--src/H5HF.c101
-rw-r--r--src/H5HFcache.c27
-rw-r--r--src/H5HFdbg.c12
-rw-r--r--src/H5HFint.c197
-rw-r--r--src/H5HFpkg.h20
-rw-r--r--src/H5HFprivate.h13
-rw-r--r--src/H5HFtest.c18
-rwxr-xr-xsrc/Makefile.am7
-rw-r--r--src/Makefile.in13
-rw-r--r--test/fheap.c32
15 files changed, 3791 insertions, 3518 deletions
diff --git a/MANIFEST b/MANIFEST
index a517fdb..7e69b71 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -406,6 +406,7 @@
./src/H5B2.c
./src/H5B2cache.c
./src/H5B2dbg.c
+./src/H5B2int.c
./src/H5B2pkg.h
./src/H5B2private.h
./src/H5B2public.h
@@ -495,6 +496,7 @@
./src/H5HF.c
./src/H5HFcache.c
./src/H5HFdbg.c
+./src/H5HFint.c
./src/H5HFpkg.h
./src/H5HFprivate.h
./src/H5HFpublic.h
diff --git a/src/H5B2.c b/src/H5B2.c
index f1fd069..57ba36c 100644
--- a/src/H5B2.c
+++ b/src/H5B2.c
@@ -46,84 +46,16 @@
/* Local Macros */
/****************/
-/* Format overhead for each node (on disk) */
-#define H5B2_OVERHEAD_SIZE (H5B2_SIZEOF_MAGIC+1) /* Signature + version # */
-
-/* Number of records that fit into internal node */
-#define H5B2_NUM_INT_REC(f,n,r) (((n)-(H5B2_OVERHEAD_SIZE+H5B2_NODE_POINTER_SIZE(f)))/((r)+H5B2_NODE_POINTER_SIZE(f)))
-
-/* Number of records that fit into leaf node */
-#define H5B2_NUM_LEAF_REC(n,r) (((n)-H5B2_OVERHEAD_SIZE)/(r))
-
-/* Uncomment this macro to enable extra sanity checking */
-/* #define H5B2_DEBUG */
-
/******************/
/* Local Typedefs */
/******************/
+
/********************/
/* Local Prototypes */
/********************/
-/* Helper functions */
-static herr_t H5B2_shared_free(void *_shared);
-static herr_t H5B2_create_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
- H5B2_node_ptr_t *node_ptr);
-static herr_t H5B2_create_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
- H5B2_node_ptr_t *node_ptr);
-static int H5B2_locate_record(const H5B2_class_t *type, unsigned nrec,
- size_t *rec_off, const uint8_t *native, const void *udata, unsigned *idx);
-static herr_t H5B2_split_root(H5F_t *f, hid_t dxpl_id, H5B2_t *bt2,
- unsigned *bt2_flags_ptr, H5RC_t *bt2_shared);
-static herr_t H5B2_redistribute2(H5F_t *f, hid_t dxpl_id, unsigned depth,
- H5B2_internal_t *internal, unsigned idx);
-static herr_t H5B2_split2(H5F_t *f, hid_t dxpl_id, unsigned depth,
- H5B2_node_ptr_t *curr_node_ptr, unsigned * parent_cache_info_flags_ptr,
- H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx);
-static herr_t H5B2_split3(H5F_t *f, hid_t dxpl_id, unsigned depth,
- H5B2_node_ptr_t *curr_node_ptr, unsigned *parent_cache_info_flags,
- H5B2_internal_t *internal, unsigned *internal_flags, unsigned idx);
-static herr_t H5B2_redistribute3(H5F_t *f, hid_t dxpl_id, unsigned depth,
- H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx);
-static herr_t H5B2_merge2(H5F_t *f, hid_t dxpl_id, unsigned depth,
- H5B2_node_ptr_t *curr_node_ptr, unsigned *parent_cache_info_flags_ptr,
- H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx);
-static herr_t H5B2_merge3(H5F_t *f, hid_t dxpl_id, unsigned depth,
- H5B2_node_ptr_t *curr_node_ptr, unsigned *parent_cache_info_flags_ptr,
- H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx);
-static herr_t H5B2_swap_leaf(H5F_t *f, hid_t dxpl_id, unsigned depth,
- H5B2_internal_t *internal, unsigned *internal_flags_ptr,
- unsigned idx, void *swap_loc);
-static herr_t H5B2_insert_internal(H5F_t *f, hid_t dxpl_id,
- H5RC_t *bt2_shared, unsigned depth, unsigned *parent_cache_info_flags_ptr,
- H5B2_node_ptr_t *curr_node_ptr, void *udata);
-static herr_t H5B2_insert_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
- H5B2_node_ptr_t *curr_node_ptr, void *udata);
-static herr_t H5B2_remove_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
- hbool_t *depth_decreased, void *swap_loc, unsigned depth, H5AC_info_t *parent_cache_info,
- hbool_t * parent_cache_info_dirtied_ptr, H5B2_node_ptr_t *curr_node_ptr, void *udata);
-static herr_t H5B2_remove_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
- H5B2_node_ptr_t *curr_node_ptr, void *udata);
-static herr_t H5B2_iterate_node(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
- unsigned depth, const H5B2_node_ptr_t *curr_node, H5B2_operator_t op,
- void *op_data);
-static herr_t H5B2_neighbor_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
- H5B2_node_ptr_t *curr_node_ptr, void *neighbor_loc,
- H5B2_compare_t comp, void *udata, H5B2_found_t op, void *op_data);
-static herr_t H5B2_neighbor_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
- unsigned depth, H5B2_node_ptr_t *curr_node_ptr, void *neighbor_loc,
- H5B2_compare_t comp, void *udata, H5B2_found_t op, void *op_data);
-static herr_t H5B2_delete_node(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
- unsigned depth, const H5B2_node_ptr_t *curr_node);
-#ifdef H5B2_DEBUG
-static herr_t H5B2_assert_leaf(H5B2_shared_t *shared, H5B2_leaf_t *leaf);
-static herr_t H5B2_assert_leaf2(H5B2_shared_t *shared, H5B2_leaf_t *leaf, H5B2_leaf_t *leaf2);
-static herr_t H5B2_assert_internal(hsize_t parent_all_nrec, H5B2_shared_t *shared, H5B2_internal_t *internal);
-static herr_t H5B2_assert_internal2(hsize_t parent_all_nrec, H5B2_shared_t *shared, H5B2_internal_t *internal, H5B2_internal_t *internal2);
-#endif /* H5B2_DEBUG */
-
/*********************/
/* Package Variables */
@@ -132,171 +64,15 @@ static herr_t H5B2_assert_internal2(hsize_t parent_all_nrec, H5B2_shared_t *shar
/* 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);
-
/*****************************/
/* Library Private Variables */
/*****************************/
+
/*******************/
/* Local 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 'size_t' sequence information */
-H5FL_SEQ_DEFINE_STATIC(size_t);
-
-/* Declare a free list to manage the H5B2_shared_t struct */
-H5FL_DEFINE_STATIC(H5B2_shared_t);
-
-
-
-/*-------------------------------------------------------------------------
- * Function: H5B2_shared_init
- *
- * Purpose: Allocate & initialize shared B-tree info
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 2 2005
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5B2_shared_init (H5F_t *f, H5B2_t *bt2, const H5B2_class_t *type,
- size_t node_size, size_t rrec_size,
- unsigned split_percent, unsigned merge_percent)
-{
- H5B2_shared_t *shared = NULL; /* Shared B-tree information */
- unsigned u; /* Local index variable */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5B2_shared_init)
-
- /* Allocate space for the shared information */
- if(NULL == (shared = H5FL_CALLOC(H5B2_shared_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree shared information")
-
- /* Assign user's information */
- shared->split_percent = split_percent;
- shared->merge_percent = merge_percent;
- shared->node_size = node_size;
- shared->rrec_size = rrec_size;
-
- /* Compute derived information */
- shared->internal_nrec = H5B2_NUM_INT_REC(f, shared->node_size, shared->rrec_size);
- shared->split_int_nrec = (shared->internal_nrec * shared->split_percent) / 100;
- shared->merge_int_nrec = (shared->internal_nrec * shared->merge_percent) / 100;
-
- shared->leaf_nrec = H5B2_NUM_LEAF_REC(shared->node_size, shared->rrec_size);
- shared->split_leaf_nrec = (shared->leaf_nrec * shared->split_percent) / 100;
- shared->merge_leaf_nrec = (shared->leaf_nrec * shared->merge_percent) / 100;
-
- /* Assign common type information */
- shared->type = type;
-
- /* Allocate "page" for node I/O */
- if((shared->page = H5FL_BLK_MALLOC(node_page, shared->node_size)) == NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
-#ifdef H5_USING_PURIFY
-HDmemset(shared->page,0,shared->node_size);
-#endif /* H5_USING_PURIFY */
-
- /* Create factory for internal node native record storage */
- if((shared->int_fac = H5FL_fac_init(type->nrec_size * shared->internal_nrec)) == NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create internal node native key block factory")
-
- /* Create factory for leaf node native record storage */
- if((shared->leaf_fac = H5FL_fac_init(type->nrec_size * shared->leaf_nrec)) == NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create leaf node native key block factory")
-
- /* Create factory for internal node node pointer storage */
- if((shared->node_ptr_fac = H5FL_fac_init(sizeof(H5B2_node_ptr_t) * (shared->internal_nrec + 1))) == NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create internal node node pointer block factory")
-
- /* Allocate array of pointers to internal node native keys */
- if((shared->nat_off = H5FL_SEQ_MALLOC(size_t, MAX(shared->internal_nrec, shared->leaf_nrec))) == NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
-
- /* Initialize offsets in native key block */
- for(u = 0; u < MAX(shared->internal_nrec, shared->leaf_nrec); u++)
- shared->nat_off[u]=type->nrec_size*u;
-
- /* Make shared B-tree info reference counted */
- if(NULL == (bt2->shared = H5RC_create(shared, H5B2_shared_free)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create ref-count wrapper for shared B-tree info")
-
-done:
- if(ret_value < 0)
- if(shared)
- H5B2_shared_free(shared);
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5B2_shared_init() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5B2_shared_free
- *
- * Purpose: Free shared B-tree info
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 2 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B2_shared_free(void *_shared)
-{
- H5B2_shared_t *shared = (H5B2_shared_t *)_shared;
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT(H5B2_shared_free)
-
- /* Sanity check */
- HDassert(shared);
-
- /* Free the B-tree node buffer */
- if(shared->page)
- H5FL_BLK_FREE(node_page, shared->page);
-
- /* Destroy factory for internal node native record storage */
- if(shared->int_fac)
- if(H5FL_fac_term(shared->int_fac) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't destroy internal node native key block factory")
-
- /* Destroy factory for leaf node native record storage */
- if(shared->leaf_fac)
- if(H5FL_fac_term(shared->leaf_fac) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't destroy leaf node native key block factory")
-
- /* Destroy factory for internal node node pointer storage */
- if(shared->node_ptr_fac)
- 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 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);
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5B2_shared_free() */
-
/*-------------------------------------------------------------------------
* Function: H5B2_create
@@ -370,2138 +146,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5B2_locate_record
- *
- * Purpose: Performs a binary search to locate a record in a sorted
- * array of records.
- *
- * Sets *IDX to location of record greater than or equal to
- * record to locate.
- *
- * Return: Comparison value for insertion location. Negative for record
- * to locate being less than value in *IDX. Zero for record to
- * locate equal to value in *IDX. Positive for record to locate
- * being greater than value in *IDX (which should only happen when
- * record to locate is greater than all records to search).
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 3 2005
- *
- *-------------------------------------------------------------------------
- */
-static int
-H5B2_locate_record(const H5B2_class_t *type, unsigned nrec, size_t *rec_off,
- const uint8_t *native, const void *udata, unsigned *idx)
-{
- unsigned lo = 0, hi; /* Low & high index values */
- unsigned my_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) {
- my_idx = (lo + hi) / 2;
- if ((cmp = (type->compare)(udata, native+rec_off[my_idx])) < 0)
- hi = my_idx;
- else
- lo = my_idx + 1;
- }
-
- *idx = my_idx;
-
- FUNC_LEAVE_NOAPI(cmp);
-} /* end H5B2_locate_record */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5B2_split_root
- *
- * Purpose: Split the root node
- *
- * Return: Success: Non-negative
- *
- * Failure: Negative
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 3 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B2_split_root(H5F_t *f, hid_t dxpl_id, H5B2_t *bt2, unsigned *bt2_flags_ptr,
- H5RC_t *bt2_shared)
-{
- const H5AC_class_t *child_class; /* Pointer to child node's class info */
- H5B2_internal_t *new_root; /* Pointer to new root node */
- haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */
- void *left_child, *right_child; /* Pointers to child nodes */
- unsigned *left_nrec, *right_nrec; /* Pointers to child # of records */
- uint8_t *left_native, *right_native;/* Pointers to childs' native records */
- H5B2_node_ptr_t *left_node_ptrs=NULL, *right_node_ptrs=NULL;/* Pointers to childs' node pointer info */
- H5B2_shared_t *shared; /* B-tree's shared info */
- unsigned mid_record; /* Index of "middle" record in current node */
- unsigned old_root_nrec; /* Number of records in root node */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5B2_split_root)
-
- HDassert(f);
- HDassert(bt2);
- HDassert(bt2_flags_ptr);
- HDassert(bt2_shared);
-
- /* Get the pointer to the shared B-tree info */
- shared=H5RC_GET_OBJ(bt2_shared);
- HDassert(shared);
-
- if(bt2->depth>0) {
- H5B2_internal_t *old_int=NULL, *new_int=NULL; /* Pointers to old & new internal nodes */
- H5B2_node_ptr_t new_int_ptr; /* Node pointer to manage new internal node */
-
- /* Create new internal node */
- new_int_ptr.all_nrec=new_int_ptr.node_nrec=0;
- if(H5B2_create_internal(f, dxpl_id, bt2_shared, &new_int_ptr)<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new internal node")
-
- /* Setup information for unlocking child nodes */
- child_class = H5AC_BT2_INT;
- left_addr = bt2->root.addr;
- right_addr = new_int_ptr.addr;
-
- /* Protect both leafs */
- if (NULL == (old_int = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, left_addr, &(bt2->root.node_nrec), bt2_shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
- if (NULL == (new_int = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, right_addr, &(new_int_ptr.node_nrec), bt2_shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
-
- /* More setup for child nodes */
- left_child = old_int;
- right_child = new_int;
- left_nrec = &(old_int->nrec);
- right_nrec = &(new_int->nrec);
- left_native = old_int->int_native;
- right_native = new_int->int_native;
- left_node_ptrs = old_int->node_ptrs;
- right_node_ptrs = new_int->node_ptrs;
- } /* end if */
- else {
- H5B2_leaf_t *old_leaf=NULL, *new_leaf=NULL; /* Pointers to old & new leaf nodes */
- H5B2_node_ptr_t new_leaf_ptr; /* Node pointer to manage new leaf node */
-
- /* Create new leaf node */
- new_leaf_ptr.all_nrec=new_leaf_ptr.node_nrec=0;
- if(H5B2_create_leaf(f, dxpl_id, bt2_shared, &new_leaf_ptr)<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new leaf node")
-
- /* Setup information for unlocking child nodes */
- child_class = H5AC_BT2_LEAF;
- left_addr = bt2->root.addr;
- right_addr = new_leaf_ptr.addr;
-
- /* Protect both leafs */
- if (NULL == (old_leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, left_addr, &(bt2->root.node_nrec), bt2_shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
- if (NULL == (new_leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, right_addr, &(new_leaf_ptr.node_nrec), bt2_shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
-
- /* More setup for child nodes */
- left_child = old_leaf;
- right_child = new_leaf;
- left_nrec = &(old_leaf->nrec);
- right_nrec = &(new_leaf->nrec);
- left_native = old_leaf->leaf_native;
- right_native = new_leaf->leaf_native;
- } /* end if */
-
- /* Set the old number of records in root node */
- old_root_nrec = bt2->root.node_nrec;
-
- /* Determine "middle" record to promote to new root */
- mid_record = old_root_nrec/2;
-
- /* Copy "upper half" of records to new child */
- HDmemcpy(H5B2_NAT_NREC(right_native,shared,0),H5B2_NAT_NREC(left_native,shared,mid_record+1),shared->type->nrec_size*(old_root_nrec-(mid_record+1)));
-
- /* Copy "upper half" of format root's node pointers, if the children of the root are internal nodes */
- if(bt2->depth>0)
- HDmemcpy(&(right_node_ptrs[0]),&(left_node_ptrs[mid_record+1]),sizeof(H5B2_node_ptr_t)*(old_root_nrec-mid_record));
-
- /* Create new internal node to use as root */
- if(H5B2_create_internal(f, dxpl_id, bt2_shared, &(bt2->root))<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new internal node")
-
- /* Protect new internal node */
- if (NULL == (new_root = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, bt2->root.addr, &(bt2->root.node_nrec), bt2_shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
-
- /* Copy "middle" record to new internal node */
- HDmemcpy(H5B2_INT_NREC(new_root,shared,0),H5B2_NAT_NREC(left_native,shared,mid_record),shared->type->nrec_size);
-
- /* Set internal node pointers to child nodes */
- new_root->node_ptrs[0].addr = left_addr;
- new_root->node_ptrs[1].addr = right_addr;
-
- /* Update record counts in child nodes */
- new_root->node_ptrs[0].node_nrec = *left_nrec = mid_record;
- new_root->node_ptrs[1].node_nrec = *right_nrec = old_root_nrec-(mid_record+1);
-
- /* Determine total number of records in new child nodes */
- if(bt2->depth>0) {
- unsigned u; /* Local index variable */
- hsize_t new_left_all_nrec; /* New total number of records in left child */
- hsize_t new_right_all_nrec; /* New total number of records in right child */
-
- /* Compute total of all records in each child node */
- new_left_all_nrec = new_root->node_ptrs[0].node_nrec;
- for(u=0; u<(*left_nrec+1); u++)
- new_left_all_nrec += left_node_ptrs[u].all_nrec;
-
- new_right_all_nrec = new_root->node_ptrs[1].node_nrec;
- for(u=0; u<(*right_nrec+1); u++)
- new_right_all_nrec += right_node_ptrs[u].all_nrec;
-
- new_root->node_ptrs[0].all_nrec = new_left_all_nrec;
- new_root->node_ptrs[1].all_nrec = new_right_all_nrec;
- } /* end if */
- else {
- new_root->node_ptrs[0].all_nrec = new_root->node_ptrs[0].node_nrec;
- new_root->node_ptrs[1].all_nrec = new_root->node_ptrs[1].node_nrec;
- } /* end else */
-
- /* Update record count in new internal node */
- new_root->nrec = 1;
-
-#ifdef H5B2_DEBUG
- H5B2_assert_internal(bt2->root.all_nrec,shared,new_root);
- if(bt2->depth>0) {
- H5B2_assert_internal2(new_root->node_ptrs[0].all_nrec,shared,left_child,right_child);
- H5B2_assert_internal2(new_root->node_ptrs[1].all_nrec,shared,right_child,left_child);
- } /* end if */
- else {
- H5B2_assert_leaf2(shared,left_child,right_child);
- H5B2_assert_leaf(shared,right_child);
- } /* end else */
-#endif /* H5B2_DEBUG */
- /* Release new internal node (marked as dirty) */
- if (H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, bt2->root.addr, new_root, H5AC__DIRTIED_FLAG) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree internal node")
-
- /* Release child nodes (marked as dirty) */
- if (H5AC_unprotect(f, dxpl_id, child_class, left_addr, left_child, H5AC__DIRTIED_FLAG) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree leaf node")
- if (H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree leaf node")
-
- /* Update depth of B-tree */
- bt2->depth++;
-
- /* Update pointer to B-tree's root node to pointer to new internal node */
- bt2->root.node_nrec = 1;
-
- /* Mark B-tree header as dirty */
- *bt2_flags_ptr |= H5AC__DIRTIED_FLAG;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5B2_split_root */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5B2_redistribute2
- *
- * Purpose: Redistribute records between two nodes
- *
- * Return: Success: Non-negative
- *
- * Failure: Negative
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 9 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B2_redistribute2(H5F_t *f, hid_t dxpl_id, unsigned depth, H5B2_internal_t *internal, unsigned idx)
-{
- const H5AC_class_t *child_class; /* Pointer to child node's class info */
- haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */
- void *left_child, *right_child; /* Pointers to child nodes */
- unsigned *left_nrec, *right_nrec; /* Pointers to child # of records */
- uint8_t *left_native, *right_native; /* Pointers to childs' native records */
- H5B2_node_ptr_t *left_node_ptrs=NULL, *right_node_ptrs=NULL;/* Pointers to childs' node pointer info */
- H5B2_shared_t *shared; /* B-tree's shared info */
- hssize_t left_moved_nrec=0, right_moved_nrec=0; /* Number of records moved, for internal redistrib */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5B2_redistribute2)
-
- HDassert(f);
- HDassert(internal);
-
- /* Get the pointer to the shared B-tree info */
- shared=H5RC_GET_OBJ(internal->shared);
- HDassert(shared);
-
- /* Check for the kind of B-tree node to redistribute */
- if(depth>1) {
- H5B2_internal_t *left_internal; /* Pointer to left internal node */
- H5B2_internal_t *right_internal; /* Pointer to right internal node */
-
- /* Setup information for unlocking child nodes */
- child_class = H5AC_BT2_INT;
- left_addr = internal->node_ptrs[idx].addr;
- right_addr = internal->node_ptrs[idx+1].addr;
-
- /* Lock left & right B-tree child nodes */
- if (NULL == (left_internal = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
- if (NULL == (right_internal = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
-
- /* More setup for child nodes */
- left_child = left_internal;
- right_child = right_internal;
- left_nrec = &(left_internal->nrec);
- right_nrec = &(right_internal->nrec);
- left_native = left_internal->int_native;
- right_native = right_internal->int_native;
- left_node_ptrs = left_internal->node_ptrs;
- right_node_ptrs = right_internal->node_ptrs;
- } /* end if */
- else {
- H5B2_leaf_t *left_leaf; /* Pointer to left leaf node */
- H5B2_leaf_t *right_leaf; /* Pointer to right leaf node */
-
- /* Setup information for unlocking child nodes */
- child_class = H5AC_BT2_LEAF;
- left_addr = internal->node_ptrs[idx].addr;
- right_addr = internal->node_ptrs[idx+1].addr;
-
- /* Lock left & right B-tree child nodes */
- if (NULL == (left_leaf = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
- if (NULL == (right_leaf = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
-
- /* More setup for child nodes */
- left_child = left_leaf;
- right_child = right_leaf;
- left_nrec = &(left_leaf->nrec);
- right_nrec = &(right_leaf->nrec);
- left_native = left_leaf->leaf_native;
- right_native = right_leaf->leaf_native;
- } /* end else */
-
-#ifdef H5B2_DEBUG
- H5B2_assert_internal((hsize_t)0,shared,internal);
- if(depth>1) {
- H5B2_assert_internal2(internal->node_ptrs[idx].all_nrec,shared,left_child,right_child);
- H5B2_assert_internal2(internal->node_ptrs[idx+1].all_nrec,shared,right_child,left_child);
- } /* end if */
- else {
- H5B2_assert_leaf2(shared,left_child,right_child);
- H5B2_assert_leaf(shared,right_child);
- } /* end else */
-#endif /* H5B2_DEBUG */
-
- /* Determine whether to shuffle records left or right */
- if(*left_nrec<*right_nrec) {
- /* Moving record from right node to left */
-
- unsigned new_right_nrec = (*left_nrec+*right_nrec)/2; /* New number of records for right child */
- unsigned move_nrec = *right_nrec - new_right_nrec; /* Number of records to move from right node to left */
-
- /* Copy record from parent node down into left child */
- HDmemcpy(H5B2_NAT_NREC(left_native,shared,*left_nrec),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size);
-
- /* See if we need to move records from right node */
- if(move_nrec>1)
- HDmemcpy(H5B2_NAT_NREC(left_native,shared,(*left_nrec+1)),H5B2_NAT_NREC(right_native,shared,0),shared->type->nrec_size*(move_nrec-1));
-
- /* Move record from right node into parent node */
- HDmemcpy(H5B2_INT_NREC(internal,shared,idx),H5B2_NAT_NREC(right_native,shared,(move_nrec-1)),shared->type->nrec_size);
-
- /* Slide records in right node down */
- HDmemmove(H5B2_NAT_NREC(right_native,shared,0),H5B2_NAT_NREC(right_native,shared,move_nrec),shared->type->nrec_size*new_right_nrec);
-
- /* Handle node pointers, if we have an internal node */
- if(depth>1) {
- hsize_t moved_nrec=move_nrec; /* Total number of records moved, for internal redistrib */
- unsigned u; /* Local index variable */
-
- /* Count the number of records being moved */
- for(u=0; u<move_nrec; u++)
- moved_nrec += right_node_ptrs[u].all_nrec;
- left_moved_nrec = moved_nrec;
- right_moved_nrec -= moved_nrec;
-
- /* Copy node pointers from right node to left */
- HDmemcpy(&(left_node_ptrs[*left_nrec+1]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*move_nrec);
-
- /* Slide node pointers in right node down */
- HDmemmove(&(right_node_ptrs[0]),&(right_node_ptrs[move_nrec]),sizeof(H5B2_node_ptr_t)*(new_right_nrec+1));
- } /* end if */
-
- /* Update number of records in child nodes */
- *left_nrec += move_nrec;
- *right_nrec = new_right_nrec;
- } /* end if */
- else {
- /* Moving record from left node to right */
-
- unsigned new_left_nrec = (*left_nrec+*right_nrec)/2; /* New number of records for left child */
- unsigned move_nrec = *left_nrec - new_left_nrec; /* Number of records to move from left node to right */
-
- /* Slide records in right node up */
- HDmemmove(H5B2_NAT_NREC(right_native,shared,move_nrec),
- H5B2_NAT_NREC(right_native,shared,0),
- shared->type->nrec_size*(*right_nrec));
-
- /* Copy record from parent node down into right child */
- HDmemcpy(H5B2_NAT_NREC(right_native,shared,(move_nrec-1)),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size);
-
- /* See if we need to move records from left node */
- if(move_nrec>1)
- HDmemcpy(H5B2_NAT_NREC(right_native,shared,0),H5B2_NAT_NREC(left_native,shared,((*left_nrec-move_nrec)+1)),shared->type->nrec_size*(move_nrec-1));
-
- /* Move record from left node into parent node */
- HDmemcpy(H5B2_INT_NREC(internal,shared,idx),H5B2_NAT_NREC(left_native,shared,(*left_nrec-move_nrec)),shared->type->nrec_size);
-
- /* Handle node pointers, if we have an internal node */
- if(depth>1) {
- hsize_t moved_nrec=move_nrec; /* Total number of records moved, for internal redistrib */
- unsigned u; /* Local index variable */
-
- /* Slide node pointers in right node up */
- HDmemmove(&(right_node_ptrs[move_nrec]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*(*right_nrec+1));
-
- /* Copy node pointers from left node to right */
- HDmemcpy(&(right_node_ptrs[0]),&(left_node_ptrs[new_left_nrec+1]),sizeof(H5B2_node_ptr_t)*move_nrec);
-
- /* Count the number of records being moved */
- for(u=0; u<move_nrec; u++)
- moved_nrec += right_node_ptrs[u].all_nrec;
- left_moved_nrec -= moved_nrec;
- right_moved_nrec = moved_nrec;
- } /* end if */
-
- /* Update number of records in child nodes */
- *left_nrec = new_left_nrec;
- *right_nrec += move_nrec;
- } /* end else */
-
- /* Update # of records in child nodes */
- internal->node_ptrs[idx].node_nrec = *left_nrec;
- internal->node_ptrs[idx+1].node_nrec = *right_nrec;
-
- /* Update total # of records in child B-trees */
- if(depth>1) {
- internal->node_ptrs[idx].all_nrec += left_moved_nrec;
- internal->node_ptrs[idx+1].all_nrec += right_moved_nrec;
- } /* end if */
- else {
- internal->node_ptrs[idx].all_nrec = internal->node_ptrs[idx].node_nrec;
- internal->node_ptrs[idx+1].all_nrec = internal->node_ptrs[idx+1].node_nrec;
- } /* end else */
-
-#ifdef H5B2_DEBUG
- H5B2_assert_internal((hsize_t)0,shared,internal);
- if(depth>1) {
- H5B2_assert_internal2(internal->node_ptrs[idx].all_nrec,shared,left_child,right_child);
- H5B2_assert_internal2(internal->node_ptrs[idx+1].all_nrec,shared,right_child,left_child);
- } /* end if */
- else {
- H5B2_assert_leaf2(shared,left_child,right_child);
- H5B2_assert_leaf(shared,right_child);
- } /* end else */
-#endif /* H5B2_DEBUG */
-
- /* Release child nodes (marked as dirty) */
- if (H5AC_unprotect(f, dxpl_id, child_class, left_addr, left_child, H5AC__DIRTIED_FLAG) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
- if (H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5B2_redistribute2 */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5B2_split2
- *
- * Purpose: Perform a 2->3 node split
- *
- * Return: Success: Non-negative
- *
- * Failure: Negative
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 9 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B2_split2(H5F_t *f, hid_t dxpl_id, unsigned depth, H5B2_node_ptr_t *curr_node_ptr,
- unsigned *parent_cache_info_flags_ptr, H5B2_internal_t *internal,
- unsigned *internal_flags_ptr, unsigned idx)
-{
- const H5AC_class_t *child_class; /* Pointer to child node's class info */
- haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */
- haddr_t middle_addr; /* Address of middle child node */
- void *left_child, *right_child; /* Pointers to left & right child nodes */
- void *middle_child; /* Pointer to middle child node */
- unsigned *left_nrec, *right_nrec; /* Pointers to left & right child # of records */
- unsigned *middle_nrec; /* Pointer to middle child # of records */
- uint8_t *left_native, *right_native; /* Pointers to left & right children's native records */
- uint8_t *middle_native; /* Pointer to middle child's native records */
- H5B2_node_ptr_t *left_node_ptrs=NULL, *right_node_ptrs=NULL;/* Pointers to childs' node pointer info */
- H5B2_node_ptr_t *middle_node_ptrs=NULL;/* Pointers to childs' node pointer info */
- H5B2_shared_t *shared; /* B-tree's shared info */
- hssize_t left_moved_nrec=0, right_moved_nrec=0; /* Number of records moved, for internal split */
- hsize_t middle_moved_nrec=0; /* Number of records moved, for internal split */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5B2_split2)
-
- HDassert(f);
- HDassert(parent_cache_info_flags_ptr);
- HDassert(internal);
- HDassert(internal_flags_ptr);
-
- /* Get the pointer to the shared B-tree info */
- shared=H5RC_GET_OBJ(internal->shared);
- HDassert(shared);
-
- /* Slide records in parent node up one space, to make room for promoted record */
- HDmemmove(H5B2_INT_NREC(internal,shared,idx+2),H5B2_INT_NREC(internal,shared,idx+1),shared->type->nrec_size*(internal->nrec-(idx+1)));
- HDmemmove(&(internal->node_ptrs[idx+2]),&(internal->node_ptrs[idx+1]),sizeof(H5B2_node_ptr_t)*(internal->nrec-idx));
-
- /* Check for the kind of B-tree node to split */
- if(depth>1) {
- H5B2_internal_t *left_internal; /* Pointer to left internal node */
- H5B2_internal_t *middle_internal; /* Pointer to middle internal node */
- H5B2_internal_t *right_internal; /* Pointer to right internal node */
-
- /* Setup information for unlocking child nodes */
- child_class = H5AC_BT2_INT;
- left_addr = internal->node_ptrs[idx].addr;
- right_addr = internal->node_ptrs[idx+2].addr;
-
- /* Lock left & right B-tree child nodes */
- if (NULL == (left_internal = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
- if (NULL == (right_internal = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+2].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
-
- /* Create new empty "middle" internal node */
- internal->node_ptrs[idx+1].all_nrec=internal->node_ptrs[idx+1].node_nrec=0;
- if(H5B2_create_internal(f, dxpl_id, internal->shared, &(internal->node_ptrs[idx+1]))<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new internal node")
-
- /* Setup information for unlocking middle child node */
- middle_addr = internal->node_ptrs[idx+1].addr;
-
- /* Lock "middle" internal node */
- if (NULL == (middle_internal = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
-
- /* More setup for accessing child node information */
- left_child = left_internal;
- middle_child = middle_internal;
- right_child = right_internal;
- left_nrec = &(left_internal->nrec);
- middle_nrec = &(middle_internal->nrec);
- right_nrec = &(right_internal->nrec);
- left_native = left_internal->int_native;
- middle_native = middle_internal->int_native;
- right_native = right_internal->int_native;
- left_node_ptrs = left_internal->node_ptrs;
- middle_node_ptrs = middle_internal->node_ptrs;
- right_node_ptrs = right_internal->node_ptrs;
- } /* end if */
- else {
- H5B2_leaf_t *left_leaf; /* Pointer to left leaf node */
- H5B2_leaf_t *middle_leaf; /* Pointer to middle leaf node */
- H5B2_leaf_t *right_leaf; /* Pointer to right leaf node */
-
- /* Setup information for unlocking child nodes */
- child_class = H5AC_BT2_LEAF;
- left_addr = internal->node_ptrs[idx].addr;
- right_addr = internal->node_ptrs[idx+2].addr;
-
- /* Lock left & right B-tree child nodes */
- if (NULL == (left_leaf = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
- if (NULL == (right_leaf = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+2].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
-
- /* Create new empty "middle" leaf node */
- internal->node_ptrs[idx+1].all_nrec=internal->node_ptrs[idx+1].node_nrec=0;
- if(H5B2_create_leaf(f, dxpl_id, internal->shared, &(internal->node_ptrs[idx+1]))<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new leaf node")
-
- /* Setup information for unlocking middle child node */
- middle_addr = internal->node_ptrs[idx+1].addr;
-
- /* Lock "middle" leaf node */
- if (NULL == (middle_leaf = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
-
- /* More setup for accessing child node information */
- left_child = left_leaf;
- middle_child = middle_leaf;
- right_child = right_leaf;
- left_nrec = &(left_leaf->nrec);
- middle_nrec = &(middle_leaf->nrec);
- right_nrec = &(right_leaf->nrec);
- left_native = left_leaf->leaf_native;
- middle_native = middle_leaf->leaf_native;
- right_native = right_leaf->leaf_native;
- } /* end else */
-
- /* Redistribute records */
- {
- /* Compute new # of records in each node */
- unsigned total_nrec = *left_nrec + *right_nrec + 1;
- unsigned new_middle_nrec = (total_nrec-2)/3;
- unsigned new_left_nrec = ((total_nrec-2)-new_middle_nrec)/2;
- unsigned new_right_nrec = (total_nrec-2)-(new_left_nrec+new_middle_nrec);
-
- /* Fill new middle node */
- {
- unsigned curr_middle_idx=0;
-
- /* Copy record(s) from left node to proper location */
- if(new_left_nrec<(*left_nrec-1)) {
- curr_middle_idx=*left_nrec-(new_left_nrec+1);
- HDmemcpy(H5B2_NAT_NREC(middle_native,shared,0),H5B2_NAT_NREC(left_native,shared,(new_left_nrec+1)),shared->type->nrec_size*curr_middle_idx);
- } /* end if */
-
- /* Copy record from parent node to proper location */
- HDmemcpy(H5B2_NAT_NREC(middle_native,shared,curr_middle_idx),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size);
- curr_middle_idx++;
-
- /* Copy record(s) from right node to proper location */
- if(new_right_nrec<(*right_nrec-1))
- HDmemcpy(H5B2_NAT_NREC(middle_native,shared,curr_middle_idx),H5B2_NAT_NREC(right_native,shared,0),shared->type->nrec_size*(*right_nrec-(new_right_nrec+1)));
-
- /* Copy node pointers from left and right nodes into middle node */
- if(depth>1) {
- hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */
- unsigned move_nptrs; /* Number of node pointers to move */
- unsigned u; /* Local index variable */
-
- /* Start tracking the total number of records in middle node */
- middle_moved_nrec = new_middle_nrec;
-
- /* Copy node pointers from left node */
- move_nptrs = (*left_nrec-new_left_nrec);
- HDmemcpy(&(middle_node_ptrs[0]),&(left_node_ptrs[new_left_nrec+1]),sizeof(H5B2_node_ptr_t)*move_nptrs);
-
- /* Count the number of records being moved from the left node */
- for(u=0, moved_nrec=0; u<move_nptrs; u++)
- moved_nrec += middle_node_ptrs[u].all_nrec;
- left_moved_nrec -= (moved_nrec+(*left_nrec-new_left_nrec));
- middle_moved_nrec += moved_nrec;
-
- /* Copy node pointers from right node */
- move_nptrs = (*right_nrec-new_right_nrec);
- HDmemcpy(&(middle_node_ptrs[(*left_nrec-new_left_nrec)]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*move_nptrs);
-
- /* Count the number of records being moved from the right node */
- for(u=0, moved_nrec=0; u<move_nptrs; u++)
- moved_nrec += right_node_ptrs[u].all_nrec;
- right_moved_nrec -= (moved_nrec+(*right_nrec-new_right_nrec));
- middle_moved_nrec += moved_nrec;
-
- /* Slide node pointers in right node down */
- HDmemmove(&(right_node_ptrs[0]),&(right_node_ptrs[move_nptrs]),sizeof(H5B2_node_ptr_t)*(new_right_nrec+1));
- } /* end if */
-
- } /* end block */
-
- /* Update # of records in middle node */
- *middle_nrec=new_middle_nrec;
-
- /* Promote records to parent node from left & right nodes */
- HDmemcpy(H5B2_INT_NREC(internal,shared,idx),H5B2_NAT_NREC(left_native,shared,new_left_nrec),shared->type->nrec_size);
- HDmemcpy(H5B2_INT_NREC(internal,shared,idx+1),H5B2_NAT_NREC(right_native,shared,(*right_nrec-(new_right_nrec+1))),shared->type->nrec_size);
-
- /* Update # of records in left node */
- *left_nrec = new_left_nrec;
-
- /* Slide records in right node to proper position */
- HDmemmove(H5B2_NAT_NREC(right_native,shared,0),H5B2_NAT_NREC(right_native,shared,(*right_nrec-new_right_nrec)),shared->type->nrec_size*new_right_nrec);
-
- /* Update # of records in right node */
- *right_nrec = new_right_nrec;
- } /* end block */
-
- /* Update # of records in child nodes */
- internal->node_ptrs[idx].node_nrec = *left_nrec;
- internal->node_ptrs[idx+1].node_nrec = *middle_nrec;
- internal->node_ptrs[idx+2].node_nrec = *right_nrec;
-
- /* Update total # of records in child B-trees */
- if(depth>1) {
- internal->node_ptrs[idx].all_nrec += left_moved_nrec;
- internal->node_ptrs[idx+1].all_nrec = middle_moved_nrec;
- internal->node_ptrs[idx+2].all_nrec += right_moved_nrec;
- } /* end if */
- else {
- internal->node_ptrs[idx].all_nrec = internal->node_ptrs[idx].node_nrec;
- internal->node_ptrs[idx+1].all_nrec = internal->node_ptrs[idx+1].node_nrec;
- internal->node_ptrs[idx+2].all_nrec = internal->node_ptrs[idx+2].node_nrec;
- } /* end else */
-
-
- /* Update # of records in parent node */
- internal->nrec++;
-
- /* Mark parent as dirty */
- *internal_flags_ptr |= H5AC__DIRTIED_FLAG;
-
- /* Update grandparent info */
- curr_node_ptr->node_nrec++;
-
- /* Mark grandparent as dirty */
- *parent_cache_info_flags_ptr |= H5AC__DIRTIED_FLAG;
-
-#ifdef H5B2_DEBUG
- H5B2_assert_internal((hsize_t)0,shared,internal);
- if(depth>1) {
- H5B2_assert_internal2(internal->node_ptrs[idx].all_nrec,shared,left_child,middle_child);
- H5B2_assert_internal2(internal->node_ptrs[idx+1].all_nrec,shared,middle_child,left_child);
- H5B2_assert_internal2(internal->node_ptrs[idx+1].all_nrec,shared,middle_child,right_child);
- H5B2_assert_internal2(internal->node_ptrs[idx+2].all_nrec,shared,right_child,middle_child);
- } /* end if */
- else {
- H5B2_assert_leaf2(shared,left_child,middle_child);
- H5B2_assert_leaf2(shared,middle_child,right_child);
- H5B2_assert_leaf(shared,right_child);
- } /* end else */
-#endif /* H5B2_DEBUG */
-
- /* Unlock child nodes (marked as dirty) */
- if (H5AC_unprotect(f, dxpl_id, child_class, left_addr, left_child, H5AC__DIRTIED_FLAG) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
- if (H5AC_unprotect(f, dxpl_id, child_class, middle_addr, middle_child, H5AC__DIRTIED_FLAG) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
- if (H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5B2_split2 */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5B2_redistribute3
- *
- * Purpose: Redistribute records between three nodes
- *
- * Return: Success: Non-negative
- *
- * Failure: Negative
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 9 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B2_redistribute3(H5F_t *f, hid_t dxpl_id, unsigned depth,
- H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx)
-{
- const H5AC_class_t *child_class; /* Pointer to child node's class info */
- haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */
- haddr_t middle_addr; /* Address of middle child node */
- void *left_child, *right_child; /* Pointers to child nodes */
- void *middle_child; /* Pointers to middle child node */
- unsigned *left_nrec, *right_nrec; /* Pointers to child # of records */
- unsigned *middle_nrec; /* Pointers to middle child # of records */
- uint8_t *left_native, *right_native; /* Pointers to childs' native records */
- uint8_t *middle_native; /* Pointers to middle child's native records */
- H5B2_shared_t *shared; /* B-tree's shared info */
- H5B2_node_ptr_t *left_node_ptrs=NULL, *right_node_ptrs=NULL;/* Pointers to childs' node pointer info */
- H5B2_node_ptr_t *middle_node_ptrs=NULL;/* Pointers to childs' node pointer info */
- hssize_t left_moved_nrec=0, right_moved_nrec=0; /* Number of records moved, for internal split */
- hssize_t middle_moved_nrec=0; /* Number of records moved, for internal split */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5B2_redistribute3)
-
- HDassert(f);
- HDassert(internal);
- HDassert(internal_flags_ptr);
-
- /* Get the pointer to the shared B-tree info */
- shared=H5RC_GET_OBJ(internal->shared);
- HDassert(shared);
-
- /* Check for the kind of B-tree node to redistribute */
- if(depth>1) {
- H5B2_internal_t *left_internal; /* Pointer to left internal node */
- H5B2_internal_t *middle_internal; /* Pointer to middle internal node */
- H5B2_internal_t *right_internal; /* Pointer to right internal node */
-
- /* Setup information for unlocking child nodes */
- child_class = H5AC_BT2_INT;
- left_addr = internal->node_ptrs[idx-1].addr;
- middle_addr = internal->node_ptrs[idx].addr;
- right_addr = internal->node_ptrs[idx+1].addr;
-
- /* Lock B-tree child nodes */
- if (NULL == (left_internal = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx-1].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
- if (NULL == (middle_internal = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
- if (NULL == (right_internal = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
-
- /* More setup for child nodes */
- left_child = left_internal;
- middle_child = middle_internal;
- right_child = right_internal;
- left_nrec = &(left_internal->nrec);
- middle_nrec = &(middle_internal->nrec);
- right_nrec = &(right_internal->nrec);
- left_native = left_internal->int_native;
- middle_native = middle_internal->int_native;
- right_native = right_internal->int_native;
- left_node_ptrs = left_internal->node_ptrs;
- middle_node_ptrs = middle_internal->node_ptrs;
- right_node_ptrs = right_internal->node_ptrs;
- } /* end if */
- else {
- H5B2_leaf_t *left_leaf; /* Pointer to left leaf node */
- H5B2_leaf_t *middle_leaf; /* Pointer to middle leaf node */
- H5B2_leaf_t *right_leaf; /* Pointer to right leaf node */
-
- /* Setup information for unlocking child nodes */
- child_class = H5AC_BT2_LEAF;
- left_addr = internal->node_ptrs[idx-1].addr;
- middle_addr = internal->node_ptrs[idx].addr;
- right_addr = internal->node_ptrs[idx+1].addr;
-
- /* Lock B-tree child nodes */
- if (NULL == (left_leaf = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx-1].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
- if (NULL == (middle_leaf = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
- if (NULL == (right_leaf = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
-
- /* More setup for child nodes */
- left_child = left_leaf;
- middle_child = middle_leaf;
- right_child = right_leaf;
- left_nrec = &(left_leaf->nrec);
- middle_nrec = &(middle_leaf->nrec);
- right_nrec = &(right_leaf->nrec);
- left_native = left_leaf->leaf_native;
- middle_native = middle_leaf->leaf_native;
- right_native = right_leaf->leaf_native;
- } /* end else */
-
- /* Redistribute records */
- {
- /* Compute new # of records in each node */
- unsigned total_nrec = *left_nrec + *middle_nrec + *right_nrec + 2;
- unsigned new_middle_nrec = (total_nrec-2)/3;
- unsigned new_left_nrec = ((total_nrec-2)-new_middle_nrec)/2;
- unsigned new_right_nrec = (total_nrec-2)-(new_left_nrec+new_middle_nrec);
- unsigned curr_middle_nrec = *middle_nrec;
-
- /* Move records into left node */
- if(new_left_nrec>*left_nrec) {
- unsigned moved_middle_nrec=0; /* Number of records moved into left node */
-
- /* Move left parent record down to left node */
- HDmemcpy(H5B2_NAT_NREC(left_native,shared,*left_nrec),H5B2_INT_NREC(internal,shared,idx-1),shared->type->nrec_size);
-
- /* Move records from middle node into left node */
- if((new_left_nrec-1)>*left_nrec) {
- moved_middle_nrec = new_left_nrec-(*left_nrec+1);
- HDmemcpy(H5B2_NAT_NREC(left_native,shared,*left_nrec+1),H5B2_NAT_NREC(middle_native,shared,0),shared->type->nrec_size*moved_middle_nrec);
- } /* end if */
-
- /* Move record from middle node up to parent node */
- HDmemcpy(H5B2_INT_NREC(internal,shared,idx-1),H5B2_NAT_NREC(middle_native,shared,moved_middle_nrec),shared->type->nrec_size);
- moved_middle_nrec++;
-
- /* Slide records in middle node down */
- HDmemmove(H5B2_NAT_NREC(middle_native,shared,0),H5B2_NAT_NREC(middle_native,shared,moved_middle_nrec),shared->type->nrec_size*(*middle_nrec-moved_middle_nrec));
-
- /* Move node pointers also if this is an internal node */
- if(depth>1) {
- hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */
- unsigned move_nptrs; /* Number of node pointers to move */
- unsigned u; /* Local index variable */
-
- /* Move middle node pointers into left node */
- move_nptrs = new_left_nrec - *left_nrec;
- HDmemcpy(&(left_node_ptrs[*left_nrec+1]),&(middle_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*move_nptrs);
-
- /* Count the number of records being moved into the left node */
- for(u=0, moved_nrec=0; u<move_nptrs; u++)
- moved_nrec += middle_node_ptrs[u].all_nrec;
- left_moved_nrec = moved_nrec+move_nptrs;
- middle_moved_nrec -= moved_nrec+move_nptrs;
-
- /* Slide the node pointers in middle node down */
- HDmemmove(&(middle_node_ptrs[0]),&(middle_node_ptrs[move_nptrs]),sizeof(H5B2_node_ptr_t)*((*middle_nrec-move_nptrs)+1));
- } /* end if */
-
- /* Update the current number of records in middle node */
- curr_middle_nrec -= moved_middle_nrec;
- } /* end if */
-
- /* Move records into right node */
- if(new_right_nrec>*right_nrec) {
- unsigned right_nrec_move = new_right_nrec-*right_nrec; /* Number of records to move out of right node */
-
- /* Slide records in right node up */
- HDmemmove(H5B2_NAT_NREC(right_native,shared,right_nrec_move),H5B2_NAT_NREC(right_native,shared,0),shared->type->nrec_size*(*right_nrec));
-
- /* Move right parent record down to right node */
- HDmemcpy(H5B2_NAT_NREC(right_native,shared,right_nrec_move-1),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size);
-
- /* Move records from middle node into right node */
- if(right_nrec_move>1)
- HDmemcpy(H5B2_NAT_NREC(right_native,shared,0),H5B2_NAT_NREC(middle_native,shared,((curr_middle_nrec-right_nrec_move)+1)),shared->type->nrec_size*(right_nrec_move-1));
-
- /* Move record from middle node up to parent node */
- HDmemcpy(H5B2_INT_NREC(internal,shared,idx),H5B2_NAT_NREC(middle_native,shared,(curr_middle_nrec-right_nrec_move)),shared->type->nrec_size);
-
- /* Move node pointers also if this is an internal node */
- if(depth>1) {
- hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */
- unsigned u; /* Local index variable */
-
- /* Slide the node pointers in right node up */
- HDmemmove(&(right_node_ptrs[right_nrec_move]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*(*right_nrec+1));
-
- /* Move middle node pointers into right node */
- HDmemcpy(&(right_node_ptrs[0]),&(middle_node_ptrs[(curr_middle_nrec-right_nrec_move)+1]),sizeof(H5B2_node_ptr_t)*right_nrec_move);
-
- /* Count the number of records being moved into the right node */
- for(u=0, moved_nrec=0; u<right_nrec_move; u++)
- moved_nrec += right_node_ptrs[u].all_nrec;
- right_moved_nrec = moved_nrec+right_nrec_move;
- middle_moved_nrec -= moved_nrec+right_nrec_move;
- } /* end if */
-
- /* Update the current number of records in middle node */
- curr_middle_nrec -= right_nrec_move;
- } /* end if */
-
- /* Move records out of left node */
- if(new_left_nrec<*left_nrec) {
- unsigned left_nrec_move = *left_nrec-new_left_nrec; /* Number of records to move out of left node */
-
- /* Slide middle records up */
- HDmemmove(H5B2_NAT_NREC(middle_native,shared,left_nrec_move),H5B2_NAT_NREC(middle_native,shared,0),shared->type->nrec_size*curr_middle_nrec);
-
- /* Move left parent record down to middle node */
- HDmemcpy(H5B2_NAT_NREC(middle_native,shared,left_nrec_move-1),H5B2_INT_NREC(internal,shared,idx-1),shared->type->nrec_size);
-
- /* Move left records to middle node */
- if(left_nrec_move>1)
- HDmemmove(H5B2_NAT_NREC(middle_native,shared,0),H5B2_NAT_NREC(left_native,shared,new_left_nrec+1),shared->type->nrec_size*(left_nrec_move-1));
-
- /* Move left parent record up from left node */
- HDmemcpy(H5B2_INT_NREC(internal,shared,idx-1),H5B2_NAT_NREC(left_native,shared,new_left_nrec),shared->type->nrec_size);
-
- /* Move node pointers also if this is an internal node */
- if(depth>1) {
- hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */
- unsigned u; /* Local index variable */
-
- /* Slide the node pointers in middle node up */
- HDmemmove(&(middle_node_ptrs[left_nrec_move]),&(middle_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*(curr_middle_nrec+1));
-
- /* Move left node pointers into middle node */
- HDmemcpy(&(middle_node_ptrs[0]),&(left_node_ptrs[new_left_nrec+1]),sizeof(H5B2_node_ptr_t)*left_nrec_move);
-
- /* Count the number of records being moved into the left node */
- for(u=0, moved_nrec=0; u<left_nrec_move; u++)
- moved_nrec += middle_node_ptrs[u].all_nrec;
- left_moved_nrec -= moved_nrec+left_nrec_move;
- middle_moved_nrec += moved_nrec+left_nrec_move;
- } /* end if */
-
- /* Update the current number of records in middle node */
- curr_middle_nrec += left_nrec_move;
- } /* end if */
-
- /* Move records out of right node */
- if(new_right_nrec<*right_nrec) {
- unsigned right_nrec_move = *right_nrec-new_right_nrec; /* Number of records to move out of right node */
-
- /* Move right parent record down to middle node */
- HDmemcpy(H5B2_NAT_NREC(middle_native,shared,curr_middle_nrec),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size);
-
- /* Move right records to middle node */
- HDmemmove(H5B2_NAT_NREC(middle_native,shared,(curr_middle_nrec+1)),H5B2_NAT_NREC(right_native,shared,0),shared->type->nrec_size*(right_nrec_move-1));
-
- /* Move right parent record up from right node */
- HDmemcpy(H5B2_INT_NREC(internal,shared,idx),H5B2_NAT_NREC(right_native,shared,right_nrec_move-1),shared->type->nrec_size);
-
- /* Slide right records down */
- HDmemmove(H5B2_NAT_NREC(right_native,shared,0),H5B2_NAT_NREC(right_native,shared,right_nrec_move),shared->type->nrec_size*new_right_nrec);
-
- /* Move node pointers also if this is an internal node */
- if(depth>1) {
- hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */
- unsigned u; /* Local index variable */
-
- /* Move right node pointers into middle node */
- HDmemcpy(&(middle_node_ptrs[curr_middle_nrec+1]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*right_nrec_move);
-
- /* Count the number of records being moved into the right node */
- for(u=0, moved_nrec=0; u<right_nrec_move; u++)
- moved_nrec += right_node_ptrs[u].all_nrec;
- right_moved_nrec -= moved_nrec+right_nrec_move;
- middle_moved_nrec += moved_nrec+right_nrec_move;
-
- /* Slide the node pointers in right node down */
- HDmemmove(&(right_node_ptrs[0]),&(right_node_ptrs[right_nrec_move]),sizeof(H5B2_node_ptr_t)*(new_right_nrec+1));
- } /* end if */
- } /* end if */
-
- /* Update # of records in nodes */
- *left_nrec = new_left_nrec;
- *middle_nrec = new_middle_nrec;
- *right_nrec = new_right_nrec;
- } /* end block */
-
- /* Update # of records in child nodes */
- internal->node_ptrs[idx-1].node_nrec = *left_nrec;
- internal->node_ptrs[idx].node_nrec = *middle_nrec;
- internal->node_ptrs[idx+1].node_nrec = *right_nrec;
-
- /* Update total # of records in child B-trees */
- if(depth>1) {
- internal->node_ptrs[idx-1].all_nrec += left_moved_nrec;
- internal->node_ptrs[idx].all_nrec += middle_moved_nrec;
- internal->node_ptrs[idx+1].all_nrec += right_moved_nrec;
- } /* end if */
- else {
- internal->node_ptrs[idx-1].all_nrec = internal->node_ptrs[idx-1].node_nrec;
- internal->node_ptrs[idx].all_nrec = internal->node_ptrs[idx].node_nrec;
- internal->node_ptrs[idx+1].all_nrec = internal->node_ptrs[idx+1].node_nrec;
- } /* end else */
-
- /* Mark parent as dirty */
- *internal_flags_ptr |= H5AC__DIRTIED_FLAG;
-
-#ifdef QAK
-{
- unsigned u;
-
- HDfprintf(stderr,"%s: Internal records:\n",FUNC);
- for(u=0; u<internal->nrec; u++) {
- HDfprintf(stderr,"%s: u=%u\n",FUNC,u);
- (shared->type->debug)(stderr,f,dxpl_id,3,4,H5B2_INT_NREC(internal,shared,u),NULL);
- } /* end for */
-
- HDfprintf(stderr,"%s: Left Child records:\n",FUNC);
- for(u=0; u<*left_nrec; u++) {
- HDfprintf(stderr,"%s: u=%u\n",FUNC,u);
- (shared->type->debug)(stderr,f,dxpl_id,3,4,H5B2_NAT_NREC(left_native,shared,u),NULL);
- } /* end for */
-
- HDfprintf(stderr,"%s: Middle Child records:\n",FUNC);
- for(u=0; u<*middle_nrec; u++) {
- HDfprintf(stderr,"%s: u=%u\n",FUNC,u);
- (shared->type->debug)(stderr,f,dxpl_id,3,4,H5B2_NAT_NREC(middle_native,shared,u),NULL);
- } /* end for */
-
- HDfprintf(stderr,"%s: Right Child records:\n",FUNC);
- for(u=0; u<*right_nrec; u++) {
- HDfprintf(stderr,"%s: u=%u\n",FUNC,u);
- (shared->type->debug)(stderr,f,dxpl_id,3,4,H5B2_NAT_NREC(right_native,shared,u),NULL);
- } /* end for */
-
- for(u=0; u<internal->nrec+1; u++)
- HDfprintf(stderr,"%s: internal->node_ptrs[%u]=(%Hu/%u/%a)\n",FUNC,u,internal->node_ptrs[u].all_nrec,internal->node_ptrs[u].node_nrec,internal->node_ptrs[u].addr);
- if(depth>1) {
- for(u=0; u<*left_nrec+1; u++)
- HDfprintf(stderr,"%s: left_node_ptr[%u]=(%Hu/%u/%a)\n",FUNC,u,left_node_ptrs[u].all_nrec,left_node_ptrs[u].node_nrec,left_node_ptrs[u].addr);
- for(u=0; u<*middle_nrec+1; u++)
- HDfprintf(stderr,"%s: middle_node_ptr[%u]=(%Hu/%u/%a)\n",FUNC,u,middle_node_ptrs[u].all_nrec,middle_node_ptrs[u].node_nrec,middle_node_ptrs[u].addr);
- for(u=0; u<*right_nrec+1; u++)
- HDfprintf(stderr,"%s: right_node_ptr[%u]=(%Hu/%u/%a)\n",FUNC,u,right_node_ptrs[u].all_nrec,right_node_ptrs[u].node_nrec,right_node_ptrs[u].addr);
- } /* end if */
-}
-#endif /* QAK */
-#ifdef H5B2_DEBUG
- H5B2_assert_internal((hsize_t)0,shared,internal);
- if(depth>1) {
- H5B2_assert_internal2(internal->node_ptrs[idx-1].all_nrec,shared,left_child,middle_child);
- H5B2_assert_internal2(internal->node_ptrs[idx].all_nrec,shared,middle_child,left_child);
- H5B2_assert_internal2(internal->node_ptrs[idx].all_nrec,shared,middle_child,right_child);
- H5B2_assert_internal2(internal->node_ptrs[idx+1].all_nrec,shared,right_child,middle_child);
- } /* end if */
- else {
- H5B2_assert_leaf2(shared,left_child,middle_child);
- H5B2_assert_leaf2(shared,middle_child,right_child);
- H5B2_assert_leaf(shared,right_child);
- } /* end else */
-#endif /* H5B2_DEBUG */
-
- /* Unlock child nodes (marked as dirty) */
- if (H5AC_unprotect(f, dxpl_id, child_class, left_addr, left_child, H5AC__DIRTIED_FLAG) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
- if (H5AC_unprotect(f, dxpl_id, child_class, middle_addr, middle_child, H5AC__DIRTIED_FLAG) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
- if (H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5B2_redistribute3 */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5B2_split3
- *
- * Purpose: Perform a 3->4 node split
- *
- * Return: Success: Non-negative
- *
- * Failure: Negative
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 10 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B2_split3(H5F_t *f, hid_t dxpl_id, unsigned depth,
- H5B2_node_ptr_t *curr_node_ptr,
- unsigned *parent_cache_info_flags_ptr, H5B2_internal_t *internal,
- unsigned *internal_flags_ptr, unsigned idx)
-{
- const H5AC_class_t *child_class; /* Pointer to child node's class info */
- haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */
- haddr_t middle_addr; /* Address of middle child node */
- haddr_t new_addr; /* Address of new child node */
- void *left_child, *right_child; /* Pointers to left & right child nodes */
- void *middle_child; /* Pointer to middle child node */
- void *new_child; /* Pointer to new child node */
- unsigned *left_nrec, *right_nrec; /* Pointers to left & right child # of records */
- unsigned *middle_nrec; /* Pointer to middle child # of records */
- unsigned *new_nrec; /* Pointer to new child # of records */
- uint8_t *left_native, *right_native; /* Pointers to left & right children's native records */
- uint8_t *middle_native; /* Pointer to middle child's native records */
- uint8_t *new_native; /* Pointer to new child's native records */
- H5B2_shared_t *shared; /* B-tree's shared info */
- H5B2_node_ptr_t *left_node_ptrs=NULL, *right_node_ptrs=NULL;/* Pointers to childs' node pointer info */
- H5B2_node_ptr_t *middle_node_ptrs=NULL;/* Pointers to childs' node pointer info */
- H5B2_node_ptr_t *new_node_ptrs=NULL;/* Pointers to childs' node pointer info */
- hssize_t left_moved_nrec=0, right_moved_nrec=0; /* Number of records moved, for internal split */
- hssize_t middle_moved_nrec=0; /* Number of records moved, for internal split */
- hsize_t new_moved_nrec=0; /* Number of records moved, for internal split */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5B2_split3)
-
- HDassert(f);
- HDassert(internal);
-
- /* Get the pointer to the shared B-tree info */
- shared=H5RC_GET_OBJ(internal->shared);
- HDassert(shared);
-
- /* Slide records in parent node up one space, to make room for promoted record */
- HDmemmove(H5B2_INT_NREC(internal,shared,idx+2),H5B2_INT_NREC(internal,shared,idx+1),shared->type->nrec_size*(internal->nrec-(idx+1)));
- HDmemmove(&(internal->node_ptrs[idx+2]),&(internal->node_ptrs[idx+1]),sizeof(H5B2_node_ptr_t)*(internal->nrec-idx));
-
- /* Check for the kind of B-tree node to split */
- if(depth>1) {
- H5B2_internal_t *left_internal; /* Pointer to left internal node */
- H5B2_internal_t *right_internal; /* Pointer to right internal node */
- H5B2_internal_t *middle_internal; /* Pointer to middle internal node */
- H5B2_internal_t *new_internal; /* Pointer to new internal node */
-
- /* Setup information for unlocking child nodes */
- child_class = H5AC_BT2_INT;
- left_addr = internal->node_ptrs[idx-1].addr;
- middle_addr = internal->node_ptrs[idx].addr;
- right_addr = internal->node_ptrs[idx+2].addr;
-
- /* Lock left & right B-tree child nodes */
- if (NULL == (left_internal = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx-1].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
- if (NULL == (middle_internal = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
- if (NULL == (right_internal = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+2].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
-
- /* Create new empty internal node */
- internal->node_ptrs[idx+1].all_nrec=internal->node_ptrs[idx+1].node_nrec=0;
- if(H5B2_create_internal(f, dxpl_id, internal->shared, &(internal->node_ptrs[idx+1]))<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new internal node")
-
- /* Setup information for unlocking middle child node */
- new_addr = internal->node_ptrs[idx+1].addr;
-
- /* Lock "new" internal node */
- if (NULL == (new_internal = H5AC_protect(f, dxpl_id, child_class, new_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
-
- /* More setup for accessing child node information */
- left_child = left_internal;
- middle_child = middle_internal;
- new_child = new_internal;
- right_child = right_internal;
- left_nrec = &(left_internal->nrec);
- middle_nrec = &(middle_internal->nrec);
- new_nrec = &(new_internal->nrec);
- right_nrec = &(right_internal->nrec);
- left_native = left_internal->int_native;
- middle_native = middle_internal->int_native;
- new_native = new_internal->int_native;
- right_native = right_internal->int_native;
- left_node_ptrs = left_internal->node_ptrs;
- middle_node_ptrs = middle_internal->node_ptrs;
- right_node_ptrs = right_internal->node_ptrs;
- new_node_ptrs = new_internal->node_ptrs;
- } /* end if */
- else {
- H5B2_leaf_t *left_leaf; /* Pointer to left leaf node */
- H5B2_leaf_t *right_leaf; /* Pointer to right leaf node */
- H5B2_leaf_t *middle_leaf; /* Pointer to middle leaf node */
- H5B2_leaf_t *new_leaf; /* Pointer to new leaf node */
-
- /* Setup information for unlocking child nodes */
- child_class = H5AC_BT2_LEAF;
- left_addr = internal->node_ptrs[idx-1].addr;
- middle_addr = internal->node_ptrs[idx].addr;
- right_addr = internal->node_ptrs[idx+2].addr;
-
- /* Lock left & right B-tree child nodes */
- if (NULL == (left_leaf = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx-1].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
- if (NULL == (middle_leaf = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
- if (NULL == (right_leaf = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+2].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
-
- /* Create new empty leaf node */
- internal->node_ptrs[idx+1].all_nrec=internal->node_ptrs[idx+1].node_nrec=0;
- if(H5B2_create_leaf(f, dxpl_id, internal->shared, &(internal->node_ptrs[idx+1]))<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new leaf node")
-
- /* Setup information for unlocking middle child node */
- new_addr = internal->node_ptrs[idx+1].addr;
-
- /* Lock "new" leaf node */
- if (NULL == (new_leaf = H5AC_protect(f, dxpl_id, child_class, new_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
-
- /* More setup for accessing child node information */
- left_child = left_leaf;
- middle_child = middle_leaf;
- new_child = new_leaf;
- right_child = right_leaf;
- left_nrec = &(left_leaf->nrec);
- middle_nrec = &(middle_leaf->nrec);
- new_nrec = &(new_leaf->nrec);
- right_nrec = &(right_leaf->nrec);
- left_native = left_leaf->leaf_native;
- middle_native = middle_leaf->leaf_native;
- new_native = new_leaf->leaf_native;
- right_native = right_leaf->leaf_native;
- } /* end else */
-
- /* Redistribute records */
- {
- /* Compute new # of records in each node */
- unsigned total_nrec = *left_nrec + *middle_nrec + *right_nrec + 2;
- unsigned new_new_nrec = (total_nrec-3)/4;
- unsigned new_middle_nrec = ((total_nrec-3)-new_new_nrec)/3;
- unsigned new_left_nrec = ((total_nrec-3)-(new_middle_nrec+new_new_nrec))/2;
- unsigned new_right_nrec = (total_nrec-3)-(new_left_nrec+new_middle_nrec+new_new_nrec);
-
- /* Partially fill new node from right node */
- {
- unsigned right_nrec_move = *right_nrec-new_right_nrec;
-
- /* Move right record down from parent into new node */
- HDmemcpy(H5B2_NAT_NREC(new_native,shared,(new_new_nrec-right_nrec_move)),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size);
-
- /* Move records from right node to new node */
- HDmemcpy(H5B2_NAT_NREC(new_native,shared,((new_new_nrec-right_nrec_move)+1)),H5B2_NAT_NREC(right_native,shared,0),shared->type->nrec_size*(right_nrec_move-1));
-
- /* Move record from right node up to parent node */
- HDmemcpy(H5B2_INT_NREC(internal,shared,idx+1),H5B2_NAT_NREC(right_native,shared,(right_nrec_move-1)),shared->type->nrec_size);
-
- /* Slide records in right node down */
- HDmemmove(H5B2_NAT_NREC(right_native,shared,0),H5B2_NAT_NREC(right_native,shared,right_nrec_move),shared->type->nrec_size*new_right_nrec);
-
- /* Move node pointers also if this is an internal node */
- if(depth>1) {
- hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */
- unsigned u; /* Local index variable */
-
- /* Move right node pointers into new node */
- HDmemcpy(&(new_node_ptrs[(new_new_nrec-right_nrec_move)+1]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*right_nrec_move);
-
- /* Count the number of records being moved into the new node */
- for(u=0, moved_nrec=0; u<right_nrec_move; u++)
- moved_nrec += right_node_ptrs[u].all_nrec;
- right_moved_nrec -= (moved_nrec+right_nrec_move);
- new_moved_nrec += (moved_nrec+right_nrec_move);
-
- /* Slide the node pointers in right node down */
- HDmemmove(&(right_node_ptrs[0]),&(right_node_ptrs[right_nrec_move]),sizeof(H5B2_node_ptr_t)*(new_right_nrec+1));
- } /* end if */
- } /* end block */
-
- /* Finish filling new node from middle node */
- {
- unsigned new_nrec_move = new_new_nrec-(*right_nrec-new_right_nrec);
-
- /* Move records from middle node to new node */
- HDmemcpy(H5B2_NAT_NREC(new_native,shared,0),H5B2_NAT_NREC(middle_native,shared,(*middle_nrec-new_nrec_move)),shared->type->nrec_size*new_nrec_move);
-
- /* Move record from middle node up to parent node */
- HDmemcpy(H5B2_INT_NREC(internal,shared,idx),H5B2_NAT_NREC(middle_native,shared,((*middle_nrec-new_nrec_move)-1)),shared->type->nrec_size);
-
- /* Slide records in middle node up */
- HDmemmove(H5B2_NAT_NREC(middle_native,shared,(new_middle_nrec-((*middle_nrec-new_nrec_move)-1))),H5B2_NAT_NREC(middle_native,shared,0),shared->type->nrec_size*(*middle_nrec-(new_nrec_move+1)));
-
- /* Move node pointers also if this is an internal node */
- if(depth>1) {
- hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */
- unsigned u; /* Local index variable */
-
- /* Move middle node pointers into new node */
- HDmemcpy(&(new_node_ptrs[0]),&(middle_node_ptrs[(*middle_nrec-new_nrec_move)]),sizeof(H5B2_node_ptr_t)*(new_nrec_move+1));
-
- /* Count the number of records being moved into the new node */
- for(u=0, moved_nrec=0; u<new_nrec_move+1; u++)
- moved_nrec += new_node_ptrs[u].all_nrec;
- middle_moved_nrec -= (moved_nrec+new_nrec_move+1);
- new_moved_nrec += (moved_nrec+new_nrec_move);
-
- /* Slide the node pointers in middle node up */
- HDmemmove(&(middle_node_ptrs[(new_middle_nrec-((*middle_nrec-new_nrec_move)-1))]),&(middle_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*(*middle_nrec-new_nrec_move));
- } /* end if */
- } /* end block */
-
- /* Fill middle node from left node */
- {
- unsigned left_nrec_move = *left_nrec - new_left_nrec;
-
- /* Move record from parent node down to middle node */
- HDmemcpy(H5B2_NAT_NREC(middle_native,shared,(left_nrec_move-1)),H5B2_INT_NREC(internal,shared,idx-1),shared->type->nrec_size);
-
- /* Move records from left node to middle node */
- HDmemcpy(H5B2_NAT_NREC(middle_native,shared,0),H5B2_NAT_NREC(left_native,shared,(new_left_nrec+1)),shared->type->nrec_size*(left_nrec_move-1));
-
- /* Move node pointers also if this is an internal node */
- if(depth>1) {
- hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */
- unsigned u; /* Local index variable */
-
- /* Move left node pointers into middle node */
- HDmemcpy(&(middle_node_ptrs[0]),&(left_node_ptrs[new_left_nrec+1]),sizeof(H5B2_node_ptr_t)*left_nrec_move);
-
- /* Count the number of records being moved into the middle node */
- for(u=0, moved_nrec=0; u<left_nrec_move; u++)
- moved_nrec += middle_node_ptrs[u].all_nrec;
- left_moved_nrec -= (moved_nrec+left_nrec_move);
- middle_moved_nrec += (moved_nrec+left_nrec_move);
- } /* end if */
- }
-
- /* Move record from left node to parent node */
- HDmemcpy(H5B2_INT_NREC(internal,shared,idx-1),H5B2_NAT_NREC(left_native,shared,new_left_nrec),shared->type->nrec_size);
-
- /* Update # of records in nodes */
- *left_nrec = new_left_nrec;
- *middle_nrec = new_middle_nrec;
- *new_nrec = new_new_nrec;
- *right_nrec = new_right_nrec;
- } /* end block */
-
- /* Update # of records in child nodes */
- internal->node_ptrs[idx-1].node_nrec = *left_nrec;
- internal->node_ptrs[idx].node_nrec = *middle_nrec;
- internal->node_ptrs[idx+1].node_nrec = *new_nrec;
- internal->node_ptrs[idx+2].node_nrec = *right_nrec;
-
- /* Update total # of records in child B-trees */
- if(depth>1) {
- internal->node_ptrs[idx-1].all_nrec += left_moved_nrec;
- internal->node_ptrs[idx].all_nrec += middle_moved_nrec;
- internal->node_ptrs[idx+1].all_nrec = new_moved_nrec;
- internal->node_ptrs[idx+2].all_nrec += right_moved_nrec;
- } /* end if */
- else {
- internal->node_ptrs[idx-1].all_nrec = internal->node_ptrs[idx-1].node_nrec;
- internal->node_ptrs[idx].all_nrec = internal->node_ptrs[idx].node_nrec;
- internal->node_ptrs[idx+1].all_nrec = internal->node_ptrs[idx+1].node_nrec;
- internal->node_ptrs[idx+2].all_nrec = internal->node_ptrs[idx+2].node_nrec;
- } /* end else */
-
- /* Update # of records in parent node */
- internal->nrec++;
-
- /* Mark parent as dirty */
- *internal_flags_ptr |= H5AC__DIRTIED_FLAG;
-
- /* Update grandparent info */
- curr_node_ptr->node_nrec++;
-
- /* Mark grandparent as dirty */
- *parent_cache_info_flags_ptr |= H5AC__DIRTIED_FLAG;
-
-#ifdef H5B2_DEBUG
- H5B2_assert_internal((hsize_t)0,shared,internal);
- if(depth>1) {
- H5B2_assert_internal2(internal->node_ptrs[idx-1].all_nrec,shared,left_child,middle_child);
- H5B2_assert_internal2(internal->node_ptrs[idx].all_nrec,shared,middle_child,left_child);
- H5B2_assert_internal2(internal->node_ptrs[idx].all_nrec,shared,middle_child,new_child);
- H5B2_assert_internal2(internal->node_ptrs[idx+1].all_nrec,shared,new_child,middle_child);
- H5B2_assert_internal2(internal->node_ptrs[idx+1].all_nrec,shared,new_child,right_child);
- H5B2_assert_internal2(internal->node_ptrs[idx+2].all_nrec,shared,right_child,new_child);
- } /* end if */
- else {
- H5B2_assert_leaf2(shared,left_child,middle_child);
- H5B2_assert_leaf2(shared,middle_child,new_child);
- H5B2_assert_leaf2(shared,new_child,right_child);
- H5B2_assert_leaf(shared,right_child);
- } /* end else */
-#endif /* H5B2_DEBUG */
-
- /* Unlock child nodes (mark as dirty) */
- if (H5AC_unprotect(f, dxpl_id, child_class, left_addr, left_child, H5AC__DIRTIED_FLAG) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
- if (H5AC_unprotect(f, dxpl_id, child_class, middle_addr, middle_child, H5AC__DIRTIED_FLAG) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
- if (H5AC_unprotect(f, dxpl_id, child_class, new_addr, new_child, H5AC__DIRTIED_FLAG) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
- if (H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5B2_split3 */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5B2_merge2
- *
- * Purpose: Perform a 2->1 node merge
- *
- * Return: Success: Non-negative
- *
- * Failure: Negative
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Mar 4 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B2_merge2(H5F_t *f, hid_t dxpl_id, unsigned depth,
- H5B2_node_ptr_t *curr_node_ptr, unsigned *parent_cache_info_flags_ptr,
- H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx)
-{
- const H5AC_class_t *child_class; /* Pointer to child node's class info */
- haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */
- void *left_child, *right_child; /* Pointers to left & right child nodes */
- unsigned *left_nrec, *right_nrec; /* Pointers to left & right child # of records */
- uint8_t *left_native, *right_native; /* Pointers to left & right children's native records */
- H5B2_node_ptr_t *left_node_ptrs=NULL, *right_node_ptrs=NULL;/* Pointers to childs' node pointer info */
- H5B2_shared_t *shared; /* B-tree's shared info */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5B2_merge2)
-
- HDassert(f);
- HDassert(curr_node_ptr);
- HDassert(parent_cache_info_flags_ptr);
- HDassert(internal);
- HDassert(internal_flags_ptr);
-
- /* Get the pointer to the shared B-tree info */
- shared=H5RC_GET_OBJ(internal->shared);
- HDassert(shared);
-
- /* Check for the kind of B-tree node to split */
- if(depth>1) {
- H5B2_internal_t *left_internal; /* Pointer to left internal node */
- H5B2_internal_t *right_internal; /* Pointer to right internal node */
-
- /* Setup information for unlocking child nodes */
- child_class = H5AC_BT2_INT;
- left_addr = internal->node_ptrs[idx].addr;
- right_addr = internal->node_ptrs[idx+1].addr;
-
- /* Lock left & right B-tree child nodes */
- if (NULL == (left_internal = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
- if (NULL == (right_internal = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
-
- /* More setup for accessing child node information */
- left_child = left_internal;
- right_child = right_internal;
- left_nrec = &(left_internal->nrec);
- right_nrec = &(right_internal->nrec);
- left_native = left_internal->int_native;
- right_native = right_internal->int_native;
- left_node_ptrs = left_internal->node_ptrs;
- right_node_ptrs = right_internal->node_ptrs;
- } /* end if */
- else {
- H5B2_leaf_t *left_leaf; /* Pointer to left leaf node */
- H5B2_leaf_t *right_leaf; /* Pointer to right leaf node */
-
- /* Setup information for unlocking child nodes */
- child_class = H5AC_BT2_LEAF;
- left_addr = internal->node_ptrs[idx].addr;
- right_addr = internal->node_ptrs[idx+1].addr;
-
- /* Lock left & right B-tree child nodes */
- if (NULL == (left_leaf = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
- if (NULL == (right_leaf = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
-
- /* More setup for accessing child node information */
- left_child = left_leaf;
- right_child = right_leaf;
- left_nrec = &(left_leaf->nrec);
- right_nrec = &(right_leaf->nrec);
- left_native = left_leaf->leaf_native;
- right_native = right_leaf->leaf_native;
- } /* end else */
-
- /* Redistribute records into left node */
- {
- /* Copy record from parent node to proper location */
- HDmemcpy(H5B2_NAT_NREC(left_native,shared,*left_nrec),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size);
-
- /* Copy records from right node to left node */
- HDmemcpy(H5B2_NAT_NREC(left_native,shared,*left_nrec+1),H5B2_NAT_NREC(right_native,shared,0),shared->type->nrec_size*(*right_nrec));
-
- /* Copy node pointers from right node into left node */
- if(depth>1)
- HDmemcpy(&(left_node_ptrs[*left_nrec+1]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*(*right_nrec+1));
-
- /* Update # of records in left node */
- *left_nrec += *right_nrec + 1;
- } /* end block */
-
- /* Update # of records in child nodes */
- internal->node_ptrs[idx].node_nrec = *left_nrec;
-
- /* Update total # of records in child B-trees */
- internal->node_ptrs[idx].all_nrec += internal->node_ptrs[idx+1].all_nrec + 1;
-
- /* Slide records in parent node down, to eliminate demoted record */
- if((idx+1) < internal->nrec) {
- HDmemmove(H5B2_INT_NREC(internal,shared,idx),H5B2_INT_NREC(internal,shared,idx+1),shared->type->nrec_size*(internal->nrec-(idx+1)));
- HDmemmove(&(internal->node_ptrs[idx+1]),&(internal->node_ptrs[idx+2]),sizeof(H5B2_node_ptr_t)*(internal->nrec-(idx+1)));
- } /* end if */
-
- /* Update # of records in parent node */
- internal->nrec--;
-
- /* Mark parent as dirty */
- *internal_flags_ptr |= H5AC__DIRTIED_FLAG;
-
- /* Update grandparent info */
- curr_node_ptr->node_nrec--;
-
- /* Mark grandparent as dirty */
- *parent_cache_info_flags_ptr |= H5AC__DIRTIED_FLAG;
-
-#ifdef H5B2_DEBUG
- H5B2_assert_internal((hsize_t)0,shared,internal);
- if(depth>1) {
- H5B2_assert_internal(internal->node_ptrs[idx].all_nrec,shared,left_child);
- } /* end if */
- else {
- H5B2_assert_leaf(shared,left_child);
- } /* end else */
-#endif /* H5B2_DEBUG */
-
- /* Unlock left node (marked as dirty) */
- if (H5AC_unprotect(f, dxpl_id, child_class, left_addr, left_child, H5AC__DIRTIED_FLAG) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
-
- /* Delete right node & remove from cache (marked as dirty) */
- if (H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, right_addr, (hsize_t)shared->node_size)<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node")
- if (H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5B2_merge2 */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5B2_merge3
- *
- * Purpose: Perform a 3->2 node merge
- *
- * Return: Success: Non-negative
- *
- * Failure: Negative
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Mar 4 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B2_merge3(H5F_t *f, hid_t dxpl_id, unsigned depth,
- H5B2_node_ptr_t *curr_node_ptr, unsigned *parent_cache_info_flags_ptr,
- H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx)
-{
- const H5AC_class_t *child_class; /* Pointer to child node's class info */
- haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */
- haddr_t middle_addr; /* Address of middle child node */
- void *left_child, *right_child; /* Pointers to left & right child nodes */
- void *middle_child; /* Pointer to middle child node */
- unsigned *left_nrec, *right_nrec; /* Pointers to left & right child # of records */
- unsigned *middle_nrec; /* Pointer to middle child # of records */
- uint8_t *left_native, *right_native; /* Pointers to left & right children's native records */
- uint8_t *middle_native; /* Pointer to middle child's native records */
- H5B2_node_ptr_t *left_node_ptrs=NULL, *right_node_ptrs=NULL;/* Pointers to childs' node pointer info */
- H5B2_node_ptr_t *middle_node_ptrs=NULL;/* Pointer to child's node pointer info */
- H5B2_shared_t *shared; /* B-tree's shared info */
- hsize_t middle_moved_nrec; /* Number of records moved, for internal split */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5B2_merge3)
-
- HDassert(f);
- HDassert(curr_node_ptr);
- HDassert(parent_cache_info_flags_ptr);
- HDassert(internal);
- HDassert(internal_flags_ptr);
-
- /* Get the pointer to the shared B-tree info */
- shared=H5RC_GET_OBJ(internal->shared);
- HDassert(shared);
-
- /* Check for the kind of B-tree node to split */
- if(depth>1) {
- H5B2_internal_t *left_internal; /* Pointer to left internal node */
- H5B2_internal_t *middle_internal; /* Pointer to middle internal node */
- H5B2_internal_t *right_internal; /* Pointer to right internal node */
-
- /* Setup information for unlocking child nodes */
- child_class = H5AC_BT2_INT;
- left_addr = internal->node_ptrs[idx-1].addr;
- middle_addr = internal->node_ptrs[idx].addr;
- right_addr = internal->node_ptrs[idx+1].addr;
-
- /* Lock B-tree child nodes */
- if (NULL == (left_internal = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx-1].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
- if (NULL == (middle_internal = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
- if (NULL == (right_internal = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
-
- /* More setup for accessing child node information */
- left_child = left_internal;
- middle_child = middle_internal;
- right_child = right_internal;
- left_nrec = &(left_internal->nrec);
- middle_nrec = &(middle_internal->nrec);
- right_nrec = &(right_internal->nrec);
- left_native = left_internal->int_native;
- middle_native = middle_internal->int_native;
- right_native = right_internal->int_native;
- left_node_ptrs = left_internal->node_ptrs;
- middle_node_ptrs = middle_internal->node_ptrs;
- right_node_ptrs = right_internal->node_ptrs;
- } /* end if */
- else {
- H5B2_leaf_t *left_leaf; /* Pointer to left leaf node */
- H5B2_leaf_t *middle_leaf; /* Pointer to middle leaf node */
- H5B2_leaf_t *right_leaf; /* Pointer to right leaf node */
-
- /* Setup information for unlocking child nodes */
- child_class = H5AC_BT2_LEAF;
- left_addr = internal->node_ptrs[idx-1].addr;
- middle_addr = internal->node_ptrs[idx].addr;
- right_addr = internal->node_ptrs[idx+1].addr;
-
- /* Lock B-tree child nodes */
- if (NULL == (left_leaf = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx-1].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
- if (NULL == (middle_leaf = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
- if (NULL == (right_leaf = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
-
- /* More setup for accessing child node information */
- left_child = left_leaf;
- middle_child = middle_leaf;
- right_child = right_leaf;
- left_nrec = &(left_leaf->nrec);
- middle_nrec = &(middle_leaf->nrec);
- right_nrec = &(right_leaf->nrec);
- left_native = left_leaf->leaf_native;
- middle_native = middle_leaf->leaf_native;
- right_native = right_leaf->leaf_native;
- } /* end else */
-
- /* Redistribute records into left node */
- {
- unsigned total_nrec = *left_nrec + *middle_nrec + *right_nrec + 2;
- unsigned middle_nrec_move = ((total_nrec - 1) / 2) - *left_nrec;
-
- /* Set the base number of records moved from middle node */
- middle_moved_nrec = middle_nrec_move;
-
- /* Copy record from parent node to proper location in left node */
- HDmemcpy(H5B2_NAT_NREC(left_native,shared,*left_nrec),H5B2_INT_NREC(internal,shared,idx-1),shared->type->nrec_size);
-
- /* Copy records from middle node to left node */
- HDmemcpy(H5B2_NAT_NREC(left_native,shared,*left_nrec+1),H5B2_NAT_NREC(middle_native,shared,0),shared->type->nrec_size*(middle_nrec_move-1));
-
- /* Copy record from middle node to proper location in parent node */
- HDmemcpy(H5B2_INT_NREC(internal,shared,idx-1),H5B2_NAT_NREC(middle_native,shared,(middle_nrec_move-1)),shared->type->nrec_size);
-
- /* Slide records in middle node down */
- HDmemmove(H5B2_NAT_NREC(middle_native,shared,0),H5B2_NAT_NREC(middle_native,shared,middle_nrec_move),shared->type->nrec_size*(*middle_nrec-middle_nrec_move));
-
- /* Move node pointers also if this is an internal node */
- if(depth>1) {
- unsigned u; /* Local index variable */
-
- /* Copy node pointers from middle node into left node */
- HDmemcpy(&(left_node_ptrs[*left_nrec+1]),&(middle_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*middle_nrec_move);
-
- /* Count the number of records being moved into the left node */
- for(u=0; u<middle_nrec_move; u++)
- middle_moved_nrec += middle_node_ptrs[u].all_nrec;
-
- /* Slide the node pointers in right node down */
- HDmemmove(&(middle_node_ptrs[0]),&(middle_node_ptrs[middle_nrec_move]),sizeof(H5B2_node_ptr_t)*((*middle_nrec+1)-middle_nrec_move));
- } /* end if */
-
- /* Update # of records in left & middle nodes */
- *left_nrec += middle_nrec_move;
- *middle_nrec -= middle_nrec_move;
- } /* end block */
-
- /* Redistribute records into middle node */
- {
- /* Copy record from parent node to proper location in middle node */
- HDmemcpy(H5B2_NAT_NREC(middle_native,shared,*middle_nrec),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size);
-
- /* Copy records from right node to middle node */
- HDmemcpy(H5B2_NAT_NREC(middle_native,shared,*middle_nrec+1),H5B2_NAT_NREC(right_native,shared,0),shared->type->nrec_size*(*right_nrec));
-
- /* Move node pointers also if this is an internal node */
- if(depth>1)
- /* Copy node pointers from middle node into left node */
- HDmemcpy(&(middle_node_ptrs[*middle_nrec+1]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*(*right_nrec+1));
-
- /* Update # of records in middle node */
- *middle_nrec += *right_nrec + 1;
- } /* end block */
-
- /* Update # of records in child nodes */
- internal->node_ptrs[idx-1].node_nrec = *left_nrec;
- internal->node_ptrs[idx].node_nrec = *middle_nrec;
-
- /* Update total # of records in child B-trees */
- internal->node_ptrs[idx-1].all_nrec += middle_moved_nrec;
- internal->node_ptrs[idx].all_nrec += (internal->node_ptrs[idx+1].all_nrec + 1) - middle_moved_nrec;
-
- /* Slide records in parent node down, to eliminate demoted record */
- if((idx+1) < internal->nrec) {
- HDmemmove(H5B2_INT_NREC(internal,shared,idx),H5B2_INT_NREC(internal,shared,idx+1),shared->type->nrec_size*(internal->nrec-(idx+1)));
- HDmemmove(&(internal->node_ptrs[idx+1]),&(internal->node_ptrs[idx+2]),sizeof(H5B2_node_ptr_t)*(internal->nrec-(idx+1)));
- } /* end if */
-
- /* Update # of records in parent node */
- internal->nrec--;
-
- /* Mark parent as dirty */
- *internal_flags_ptr |= H5AC__DIRTIED_FLAG;
-
- /* Update grandparent info */
- curr_node_ptr->node_nrec--;
-
- /* Mark grandparent as dirty */
- *parent_cache_info_flags_ptr |= H5AC__DIRTIED_FLAG;
-
-#ifdef H5B2_DEBUG
- H5B2_assert_internal((hsize_t)0,shared,internal);
- if(depth>1) {
- H5B2_assert_internal2(internal->node_ptrs[idx-1].all_nrec,shared,left_child,middle_child);
- H5B2_assert_internal(internal->node_ptrs[idx].all_nrec,shared,middle_child);
- } /* end if */
- else {
- H5B2_assert_leaf2(shared,left_child,middle_child);
- H5B2_assert_leaf(shared,middle_child);
- } /* end else */
-#endif /* H5B2_DEBUG */
-
- /* Unlock left & middle nodes (marked as dirty) */
- if (H5AC_unprotect(f, dxpl_id, child_class, left_addr, left_child, H5AC__DIRTIED_FLAG) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
- if (H5AC_unprotect(f, dxpl_id, child_class, middle_addr, middle_child, H5AC__DIRTIED_FLAG) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
-
- /* Delete right node & remove from cache (marked as dirty) */
- if (H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, right_addr, (hsize_t)shared->node_size)<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node")
- if (H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5B2_merge3 */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5B2_swap_leaf
- *
- * Purpose: Swap a record in a node with a record in a leaf node
- *
- * Return: Success: Non-negative
- *
- * Failure: Negative
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Mar 4 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B2_swap_leaf(H5F_t *f, hid_t dxpl_id, unsigned depth,
- H5B2_internal_t *internal, unsigned *internal_flags_ptr,
- unsigned idx, void *swap_loc)
-{
- const H5AC_class_t *child_class; /* Pointer to child node's class info */
- haddr_t child_addr; /* Address of child node */
- void *child; /* Pointer to child node */
- uint8_t *child_native; /* Pointer to child's native records */
- H5B2_shared_t *shared; /* B-tree's shared info */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5B2_swap_leaf)
-
- HDassert(f);
- HDassert(internal);
- HDassert(internal_flags_ptr);
- HDassert(idx <= internal->nrec);
-
- /* Get the pointer to the shared B-tree info */
- shared=H5RC_GET_OBJ(internal->shared);
- HDassert(shared);
-
- /* Check for the kind of B-tree node to swap */
- if(depth>1) {
- H5B2_internal_t *child_internal; /* Pointer to internal node */
-
- /* Setup information for unlocking child node */
- child_class = H5AC_BT2_INT;
- child_addr = internal->node_ptrs[idx].addr;
-
- /* Lock B-tree child nodes */
- if (NULL == (child_internal = H5AC_protect(f, dxpl_id, child_class, child_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
-
- /* More setup for accessing child node information */
- child = child_internal;
- child_native = child_internal->int_native;
- } /* end if */
- else {
- H5B2_leaf_t *child_leaf; /* Pointer to leaf node */
-
- /* Setup information for unlocking child nodes */
- child_class = H5AC_BT2_LEAF;
- child_addr = internal->node_ptrs[idx].addr;
-
- /* Lock B-tree child node */
- if (NULL == (child_leaf = H5AC_protect(f, dxpl_id, child_class, child_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
-
- /* More setup for accessing child node information */
- child = child_leaf;
- child_native = child_leaf->leaf_native;
- } /* end else */
-
- /* Swap records (use disk page as temporary buffer) */
- HDmemcpy(shared->page, H5B2_NAT_NREC(child_native,shared,0), shared->type->nrec_size);
- HDmemcpy(H5B2_NAT_NREC(child_native,shared,0), swap_loc, shared->type->nrec_size);
- HDmemcpy(swap_loc, shared->page, shared->type->nrec_size);
-
- /* Mark parent as dirty */
- *internal_flags_ptr |= H5AC__DIRTIED_FLAG;
-
-#ifdef H5B2_DEBUG
- H5B2_assert_internal((hsize_t)0,shared,internal);
- if(depth>1)
- H5B2_assert_internal(internal->node_ptrs[idx].all_nrec,shared,child);
- else
- H5B2_assert_leaf(shared,child);
-#endif /* H5B2_DEBUG */
-
- /* Unlock child node */
- if (H5AC_unprotect(f, dxpl_id, child_class, child_addr, child, H5AC__DIRTIED_FLAG) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5B2_swap_leaf */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5B2_insert_leaf
- *
- * Purpose: Adds a new record to a B-tree leaf node.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Mar 3 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B2_insert_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
- H5B2_node_ptr_t *curr_node_ptr, void *udata)
-{
- H5B2_leaf_t *leaf; /* Pointer to leaf node */
- H5B2_shared_t *shared; /* Pointer to B-tree's shared information */
- int cmp; /* Comparison value of records */
- unsigned idx; /* Location of record which matches key */
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT(H5B2_insert_leaf)
-
- /* Check arguments. */
- HDassert(f);
- HDassert(bt2_shared);
- HDassert(curr_node_ptr);
- HDassert(H5F_addr_defined(curr_node_ptr->addr));
-
- /* Lock current B-tree node */
- if (NULL == (leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr->addr, &(curr_node_ptr->node_nrec), bt2_shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
-
- /* Get the pointer to the shared B-tree info */
- shared=H5RC_GET_OBJ(bt2_shared);
- HDassert(shared);
-
- /* Must have a leaf node with enough space to insert a record now */
- HDassert(curr_node_ptr->node_nrec < shared->split_leaf_nrec);
-
- /* Sanity check number of records */
- HDassert(curr_node_ptr->all_nrec == curr_node_ptr->node_nrec);
- HDassert(leaf->nrec == curr_node_ptr->node_nrec);
-
- /* Check for inserting into empty leaf */
- if(leaf->nrec==0)
- idx=0;
- else {
- /* Find correct location to insert this record */
- if((cmp = H5B2_locate_record(shared->type,leaf->nrec,shared->nat_off,leaf->leaf_native,udata,&idx)) == 0)
- HGOTO_ERROR(H5E_BTREE, H5E_EXISTS, FAIL, "record is already in B-tree")
- if(cmp > 0)
- idx++;
-
- /* Make room for new record */
- if(idx<leaf->nrec)
- HDmemmove(H5B2_LEAF_NREC(leaf,shared,idx+1),H5B2_LEAF_NREC(leaf,shared,idx),shared->type->nrec_size*(leaf->nrec-idx));
- } /* end else */
-
- /* Make callback to store record in native form */
- if((shared->type->store)(H5B2_LEAF_NREC(leaf,shared,idx),udata)<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into leaf node")
-
- /* Update record count for node pointer to current node */
- curr_node_ptr->all_nrec++;
- curr_node_ptr->node_nrec++;
-
- /* Update record count for current node */
- leaf->nrec++;
-
-done:
- /* Release the B-tree leaf node (marked as dirty) */
- if (leaf && H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr->addr, leaf, H5AC__DIRTIED_FLAG) < 0)
- HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release leaf B-tree node")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5B2_insert_leaf() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5B2_insert_internal
- *
- * Purpose: Adds a new record to a B-tree node.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Mar 2 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B2_insert_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
- unsigned depth, unsigned *parent_cache_info_flags_ptr,
- H5B2_node_ptr_t *curr_node_ptr, void *udata)
-{
- H5B2_internal_t *internal; /* Pointer to internal node */
- unsigned internal_flags = H5AC__NO_FLAGS_SET;
- H5B2_shared_t *shared; /* Pointer to B-tree's shared information */
- unsigned idx; /* Location of record which matches key */
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT(H5B2_insert_internal)
-
- /* Check arguments. */
- HDassert(f);
- HDassert(bt2_shared);
- HDassert(depth>0);
- HDassert(parent_cache_info_flags_ptr);
- HDassert(curr_node_ptr);
- HDassert(H5F_addr_defined(curr_node_ptr->addr));
-
- /* Lock current B-tree node */
- if (NULL == (internal = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr->addr, &(curr_node_ptr->node_nrec), bt2_shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
-
- /* Get the pointer to the shared B-tree info */
- shared=H5RC_GET_OBJ(bt2_shared);
- HDassert(shared);
-
-/* Split or redistribute child node pointers, if necessary */
- {
- int cmp; /* Comparison value of records */
- unsigned retries; /* Number of times to attempt redistribution */
- size_t split_nrec; /* Number of records to split node at */
-
- /* Locate node pointer for child */
- if((cmp=H5B2_locate_record(shared->type,internal->nrec,shared->nat_off,internal->int_native,udata,&idx)) == 0)
- HGOTO_ERROR(H5E_BTREE, H5E_EXISTS, FAIL, "record is already in B-tree")
- if(cmp>0)
- idx++;
-
- /* Set the number of redistribution retries */
- /* This takes care of the case where a B-tree node needs to be
- * redistributed, but redistributing the node causes the index
- * for insertion to move to another node, which also needs to be
- * redistributed. Now, we loop trying to redistribute and then
- * eventually force a split */
- retries = 2;
-
- /* Determine the correct number of records to split at */
- if(depth==1)
- split_nrec = shared->split_leaf_nrec;
- else
- split_nrec = shared->split_int_nrec;
-
- /* Preemptively split/redistribute a node we will enter */
- while(internal->node_ptrs[idx].node_nrec == split_nrec) {
- /* Attempt to redistribute records among children */
- if(idx==0) { /* Left-most child */
- if(retries>0 && (internal->node_ptrs[idx+1].node_nrec < split_nrec)) {
- if(H5B2_redistribute2(f,dxpl_id,depth,internal,idx)<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records")
- } /* end if */
- else {
- if(H5B2_split2(f,dxpl_id,depth,curr_node_ptr,
- parent_cache_info_flags_ptr, internal,&internal_flags,idx)<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to split child node")
- } /* end else */
- } /* end if */
- else if(idx==internal->nrec) { /* Right-most child */
- if(retries>0 && (internal->node_ptrs[idx-1].node_nrec < split_nrec)) {
- if(H5B2_redistribute2(f,dxpl_id,depth,internal,(idx-1))<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records")
- } /* end if */
- else {
- if(H5B2_split2(f,dxpl_id,depth,curr_node_ptr,
- parent_cache_info_flags_ptr, internal,&internal_flags,(idx-1))<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to split child node")
- } /* end else */
- } /* end if */
- else { /* Middle child */
- if(retries>0 && ((internal->node_ptrs[idx+1].node_nrec < split_nrec) ||
- (internal->node_ptrs[idx-1].node_nrec < split_nrec))) {
- if(H5B2_redistribute3(f,dxpl_id,depth,internal,&internal_flags,idx)<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records")
- } /* end if */
- else {
- if(H5B2_split3(f,dxpl_id,depth,curr_node_ptr,
- parent_cache_info_flags_ptr, internal,&internal_flags,idx)<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to split child node")
- } /* end else */
- } /* end else */
-
- /* Locate node pointer for child (after split/redistribute) */
-/* Actually, this can be easily updated (for 2-node redistrib.) and shouldn't require re-searching */
- if((cmp=H5B2_locate_record(shared->type,internal->nrec,shared->nat_off,internal->int_native,udata,&idx)) == 0)
- HGOTO_ERROR(H5E_BTREE, H5E_EXISTS, FAIL, "record is already in B-tree")
- if(cmp > 0)
- idx++;
-
- /* Decrement the number of redistribution retries left */
- retries--;
- } /* end while */
- } /* end block */
-
- /* Attempt to insert node */
- if(depth>1) {
- if(H5B2_insert_internal(f, dxpl_id, bt2_shared, depth-1, &internal_flags, &internal->node_ptrs[idx], udata) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into B-tree internal node")
- } /* end if */
- else {
- if(H5B2_insert_leaf(f,dxpl_id,bt2_shared,&internal->node_ptrs[idx],udata)<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into B-tree leaf node")
- } /* end else */
-
- /* Update record count for node pointer to current node */
- curr_node_ptr->all_nrec++;
-
- /* Mark node as dirty */
- internal_flags |= H5AC__DIRTIED_FLAG;
-
-done:
- /* Release the B-tree internal node */
- if (internal && H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr->addr, internal, internal_flags) < 0)
- HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release internal B-tree node")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5B2_insert_internal() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5B2_insert
*
* Purpose: Adds a new record to the B-tree.
@@ -2578,251 +222,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5B2_create_leaf
- *
- * Purpose: Creates empty leaf node of a B-tree and update node pointer
- * to point to it.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 2 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B2_create_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, H5B2_node_ptr_t *node_ptr)
-{
- H5B2_leaf_t *leaf=NULL; /* Pointer to new leaf node created */
- H5B2_shared_t *shared; /* Shared B-tree information */
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI(H5B2_create_leaf, FAIL)
-
- /* Check arguments. */
- HDassert(f);
- HDassert(bt2_shared);
- HDassert(node_ptr);
-
- /* Allocate memory for leaf information */
- if (NULL==(leaf = H5FL_MALLOC(H5B2_leaf_t)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree leaf info")
-
- /* Set metadata cache info */
- 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);
-
- /* 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, FAIL, "memory allocation failed for B-tree leaf native keys")
-#ifdef H5_USING_PURIFY
-HDmemset(leaf->leaf_native,0,shared->type->nrec_size*shared->leaf_nrec);
-#endif /* H5_USING_PURIFY */
-
- /* Set number of records */
- leaf->nrec=0;
-
- /* 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 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)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "can't add B-tree leaf to cache")
-
-done:
- if (ret_value<0) {
- if (leaf)
- (void)H5B2_cache_leaf_dest(f,leaf);
- } /* end if */
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5B2_create_leaf() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5B2_create_internal
- *
- * Purpose: Creates empty internal node of a B-tree and update node pointer
- * to point to it.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 3 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B2_create_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, H5B2_node_ptr_t *node_ptr)
-{
- 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_create_internal, FAIL)
-
- /* Check arguments. */
- HDassert(f);
- HDassert(bt2_shared);
- HDassert(node_ptr);
-
- /* 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));
-
- /* 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);
-
- /* 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, FAIL, "memory allocation failed for B-tree internal native keys")
-#ifdef H5_USING_PURIFY
-HDmemset(internal->int_native,0,shared->type->nrec_size*shared->internal_nrec);
-#endif /* H5_USING_PURIFY */
-
- /* 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")
-#ifdef H5_USING_PURIFY
-HDmemset(internal->node_ptrs,0,sizeof(H5B2_node_ptr_t)*(shared->internal_nrec+1));
-#endif /* H5_USING_PURIFY */
-
- /* Set number of records */
- internal->nrec=0;
-
- /* 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")
-
- /* 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:
- if (ret_value<0) {
- if (internal)
- (void)H5B2_cache_internal_dest(f,internal);
- } /* end if */
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5B2_create_internal() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5B2_iterate_node
- *
- * Purpose: Iterate over all the records from a B-tree node, in "in-order"
- * order, making a callback for each record.
- *
- * If the callback returns non-zero, the iteration breaks out
- * without finishing all the records.
- *
- * Return: Value from callback, non-negative on success, negative on error
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 11 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B2_iterate_node(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, unsigned depth,
- const H5B2_node_ptr_t *curr_node, H5B2_operator_t op, void *op_data)
-{
- H5B2_shared_t *shared; /* Pointer to B-tree's shared information */
- const H5AC_class_t *curr_node_class=NULL; /* Pointer to current node's class info */
- void *node=NULL; /* Pointers to current node */
- uint8_t *native; /* Pointers to node's native records */
- H5B2_node_ptr_t *node_ptrs=NULL; /* Pointers to node's node pointers */
- unsigned u; /* Local index */
- herr_t ret_value = H5B2_ITER_CONT;
-
- FUNC_ENTER_NOAPI(H5B2_iterate_node, FAIL)
-
- /* Check arguments. */
- HDassert(f);
- HDassert(bt2_shared);
- HDassert(curr_node);
- HDassert(op);
-
- /* Get the pointer to the shared B-tree info */
- shared=H5RC_GET_OBJ(bt2_shared);
- HDassert(shared);
-
- if(depth>0) {
- H5B2_internal_t *internal; /* Pointer to internal node */
-
- /* Lock the current B-tree node */
- if (NULL == (internal = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, curr_node->addr, &(curr_node->node_nrec), bt2_shared, H5AC_READ)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
-
- /* Set up information about current node */
- curr_node_class = H5AC_BT2_INT;
- node = internal;
- native = internal->int_native;
- node_ptrs = internal->node_ptrs;
- } /* end if */
- else {
- H5B2_leaf_t *leaf; /* Pointer to leaf node */
-
- /* Lock the current B-tree node */
- if (NULL == (leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, curr_node->addr, &(curr_node->node_nrec), bt2_shared, H5AC_READ)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
-
- /* Set up information about current node */
- curr_node_class = H5AC_BT2_LEAF;
- node = leaf;
- native = leaf->leaf_native;
- } /* end else */
-
- /* Iterate through records */
- for(u=0; u<curr_node->node_nrec && !ret_value; u++) {
- /* Descend into child node, if current node is an internal node */
- if(depth>0) {
- if((ret_value = H5B2_iterate_node(f,dxpl_id,bt2_shared,depth-1,&(node_ptrs[u]),op,op_data))<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTLIST, FAIL, "node iteration failed")
- } /* end if */
-
- /* Make callback for current record */
- if ((ret_value = (op)(H5B2_NAT_NREC(native,shared,u), op_data)) <0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTLIST, FAIL, "iterator function failed")
- } /* end for */
-
- /* Descend into last child node, if current node is an internal node */
- if(!ret_value && depth>0) {
- if((ret_value = H5B2_iterate_node(f,dxpl_id,bt2_shared,depth-1,&(node_ptrs[u]),op,op_data))<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTLIST, FAIL, "node iteration failed")
- } /* end if */
-
-done:
- /* Unlock current node */
- if(node)
- if (H5AC_unprotect(f, dxpl_id, curr_node_class, curr_node->addr, node, H5AC__NO_FLAGS_SET) < 0)
- HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5B2_iterate_node() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5B2_iterate
*
* Purpose: Iterate over all the records in the B-tree, in "in-order"
@@ -3242,303 +641,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5B2_remove_leaf
- *
- * Purpose: Removes a record from a B-tree leaf node.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Mar 3 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B2_remove_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
- H5B2_node_ptr_t *curr_node_ptr, void *udata)
-{
- H5B2_leaf_t *leaf; /* Pointer to leaf node */
- haddr_t leaf_addr=HADDR_UNDEF; /* Leaf address on disk */
- unsigned leaf_flags=H5AC__NO_FLAGS_SET; /* Flags for unprotecting leaf node */
- H5B2_shared_t *shared; /* Pointer to B-tree's shared information */
- unsigned idx; /* Location of record which matches key */
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT(H5B2_remove_leaf)
-
- /* Check arguments. */
- HDassert(f);
- HDassert(bt2_shared);
- HDassert(curr_node_ptr);
- HDassert(H5F_addr_defined(curr_node_ptr->addr));
-
- /* Lock current B-tree node */
- leaf_addr = curr_node_ptr->addr;
- if (NULL == (leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, leaf_addr, &(curr_node_ptr->node_nrec), bt2_shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
-
- /* Get the pointer to the shared B-tree info */
- shared=H5RC_GET_OBJ(bt2_shared);
- HDassert(shared);
-
- /* Sanity check number of records */
- HDassert(curr_node_ptr->all_nrec == curr_node_ptr->node_nrec);
- HDassert(leaf->nrec == curr_node_ptr->node_nrec);
-
- /* Find correct location to remove this record */
- if(H5B2_locate_record(shared->type,leaf->nrec,shared->nat_off,leaf->leaf_native,udata,&idx) != 0)
- HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "record is not in B-tree")
-
- /* Make callback to retrieve record in native form */
- if((shared->type->retrieve)(udata,H5B2_LEAF_NREC(leaf,shared,idx))<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to remove record into leaf node")
-
- /* Update number of records in node */
- leaf->nrec--;
-
- /* Mark leaf node as dirty also */
- leaf_flags |= H5AC__DIRTIED_FLAG;
-
- if(leaf->nrec > 0) {
- /* Pack record out of leaf */
- if(idx<leaf->nrec)
- HDmemmove(H5B2_LEAF_NREC(leaf,shared,idx),H5B2_LEAF_NREC(leaf,shared,idx+1),shared->type->nrec_size*(leaf->nrec-idx));
- } /* end if */
- else {
- /* Release space for B-tree node on disk */
- if (H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, leaf_addr, (hsize_t)shared->node_size)<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node")
-
- /* Let the cache know that the object is deleted */
- leaf_flags |= H5AC__DELETED_FLAG;
-
- /* Reset address of parent node pointer */
- curr_node_ptr->addr = HADDR_UNDEF;
- } /* end else */
-
- /* Update record count for parent of leaf node */
- curr_node_ptr->node_nrec--;
-
-done:
- /* Release the B-tree leaf node */
- if (leaf && H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, leaf_addr, leaf, leaf_flags) < 0)
- HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release leaf B-tree node")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5B2_remove_leaf() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5B2_remove_internal
- *
- * Purpose: Removes a record from a B-tree node.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Mar 3 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B2_remove_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
- hbool_t *depth_decreased, void *swap_loc, unsigned depth,
- H5AC_info_t *parent_cache_info, unsigned *parent_cache_info_flags_ptr,
- H5B2_node_ptr_t *curr_node_ptr, void *udata)
-{
- H5AC_info_t *new_cache_info; /* Pointer to new cache info */
- unsigned *new_cache_info_flags_ptr = NULL;
- H5B2_node_ptr_t *new_node_ptr; /* Pointer to new node pointer */
- H5B2_internal_t *internal; /* Pointer to internal node */
- unsigned internal_flags = H5AC__NO_FLAGS_SET;
- haddr_t internal_addr; /* Address of internal node */
- H5B2_shared_t *shared; /* Pointer to B-tree's shared information */
- unsigned idx; /* Location of record which matches key */
- size_t merge_nrec; /* Number of records to merge node at */
- hbool_t collapsed_root = FALSE; /* Whether the root was collapsed */
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT(H5B2_remove_internal)
-
- /* Check arguments. */
- HDassert(f);
- HDassert(bt2_shared);
- HDassert(depth>0);
- HDassert(parent_cache_info);
- HDassert(parent_cache_info_flags_ptr);
- HDassert(curr_node_ptr);
- HDassert(H5F_addr_defined(curr_node_ptr->addr));
-
- /* Lock current B-tree node */
- internal_addr = curr_node_ptr->addr;
- if (NULL == (internal = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, internal_addr, &(curr_node_ptr->node_nrec), bt2_shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
-
- /* Get the pointer to the shared B-tree info */
- shared=H5RC_GET_OBJ(bt2_shared);
- HDassert(shared);
-
- /* Determine the correct number of records to merge at */
- if(depth==1)
- merge_nrec = shared->merge_leaf_nrec;
- else
- merge_nrec = shared->merge_int_nrec;
-
- /* Check for needing to collapse the root node */
- /* (The root node is the only node allowed to have 1 record) */
- if(internal->nrec == 1 &&
- ((internal->node_ptrs[0].node_nrec + internal->node_ptrs[1].node_nrec) <= ((merge_nrec * 2) + 1))) {
-
- /* Merge children of root node */
- if(H5B2_merge2(f,dxpl_id,depth,curr_node_ptr,
- parent_cache_info_flags_ptr, internal,&internal_flags,0)<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to merge child node")
-
- /* Release space for root B-tree node on disk */
- if (H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, internal_addr, (hsize_t)shared->node_size)<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node")
-
- /* Let the cache know that the object is deleted */
- internal_flags |= H5AC__DELETED_FLAG;
-
- /* Reset information in parent node pointer */
- curr_node_ptr->addr = internal->node_ptrs[0].addr;
- curr_node_ptr->node_nrec = internal->node_ptrs[0].node_nrec;
-
- /* Indicate that the level of the B-tree decreased */
- *depth_decreased = TRUE;
-
- /* Set pointers for advancing to child node */
- new_cache_info = parent_cache_info;
- new_cache_info_flags_ptr = parent_cache_info_flags_ptr;
- new_node_ptr = curr_node_ptr;
-
- /* Set flag to indicate root was collapsed */
- collapsed_root = TRUE;
- } /* end if */
- /* Merge or redistribute child node pointers, if necessary */
- else {
- int cmp=0; /* Comparison value of records */
- unsigned retries; /* Number of times to attempt redistribution */
-
- /* Locate node pointer for child */
- if(swap_loc)
- idx = 0;
- else {
- cmp=H5B2_locate_record(shared->type,internal->nrec,shared->nat_off,internal->int_native,udata,&idx);
- if(cmp >= 0)
- idx++;
- } /* end else */
-
- /* Set the number of redistribution retries */
- /* This takes care of the case where a B-tree node needs to be
- * redistributed, but redistributing the node causes the index
- * for removal to move to another node, which also needs to be
- * redistributed. Now, we loop trying to redistribute and then
- * eventually force a merge */
- retries = 2;
-
- /* Preemptively merge/redistribute a node we will enter */
- while(internal->node_ptrs[idx].node_nrec==merge_nrec) {
- /* Attempt to redistribute records among children */
- if(idx==0) { /* Left-most child */
- if(retries>0 && (internal->node_ptrs[idx+1].node_nrec > merge_nrec)) {
- if(H5B2_redistribute2(f,dxpl_id,depth,internal,idx)<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records")
- } /* end if */
- else {
- if(H5B2_merge2(f,dxpl_id,depth,curr_node_ptr,
- parent_cache_info_flags_ptr, internal,&internal_flags,idx)<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to merge child node")
- } /* end else */
- } /* end if */
- else if(idx==internal->nrec) { /* Right-most child */
- if(retries>0 && (internal->node_ptrs[idx-1].node_nrec > merge_nrec)) {
- if(H5B2_redistribute2(f,dxpl_id,depth,internal,(idx-1))<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records")
- } /* end if */
- else {
- if(H5B2_merge2(f,dxpl_id,depth,curr_node_ptr,
- parent_cache_info_flags_ptr, internal,&internal_flags,(idx-1))<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to merge child node")
- } /* end else */
- } /* end if */
- else { /* Middle child */
- if(retries>0 && ((internal->node_ptrs[idx+1].node_nrec > merge_nrec) ||
- (internal->node_ptrs[idx-1].node_nrec > merge_nrec))) {
- if(H5B2_redistribute3(f,dxpl_id,depth,internal,&internal_flags,idx)<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records")
- } /* end if */
- else {
- if(H5B2_merge3(f,dxpl_id,depth,curr_node_ptr,
- parent_cache_info_flags_ptr,internal, &internal_flags,idx)<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to merge child node")
- } /* end else */
- } /* end else */
-
- /* Locate node pointer for child (after merge/redistribute) */
- if(swap_loc)
- idx = 0;
- else {
-/* Actually, this can be easily updated (for 2-node redistrib.) and shouldn't require re-searching */
- cmp=H5B2_locate_record(shared->type,internal->nrec,shared->nat_off,internal->int_native,udata,&idx);
- if(cmp >= 0)
- idx++;
- } /* end else */
-
- /* Decrement the number of redistribution retries left */
- retries--;
- } /* end while */
-
- /* Handle deleting a record from an internal node */
- if(!swap_loc && cmp==0)
- swap_loc = H5B2_INT_NREC(internal,shared,idx-1);
-
- /* Swap record to delete with record from leaf, if we are the last internal node */
- if(swap_loc && depth==1)
- if(H5B2_swap_leaf(f,dxpl_id,depth,internal,&internal_flags,idx,swap_loc) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTSWAP, FAIL, "Can't swap records in B-tree")
-
- /* Set pointers for advancing to child node */
- new_cache_info_flags_ptr = &internal_flags;
- new_cache_info = &internal->cache_info;
- new_node_ptr = &internal->node_ptrs[idx];
- } /* end else */
-
- /* Attempt to remove node */
- if(depth>1) {
- if(H5B2_remove_internal(f,dxpl_id,bt2_shared,depth_decreased, swap_loc, depth-1,
- new_cache_info,new_cache_info_flags_ptr,new_node_ptr,udata)<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to remove record from B-tree internal node")
- } /* end if */
- else {
- if(H5B2_remove_leaf(f,dxpl_id,bt2_shared,new_node_ptr,udata)<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to remove record from B-tree leaf node")
- } /* end else */
-
- /* Update record count for node pointer to current node */
- if(!collapsed_root)
- new_node_ptr->all_nrec--;
-
- /* Mark node as dirty */
- internal_flags |= H5AC__DIRTIED_FLAG;
-
-#ifdef H5B2_DEBUG
- H5B2_assert_internal((!collapsed_root ? (curr_node_ptr->all_nrec-1) : new_node_ptr->all_nrec),shared,internal);
-#endif /* H5B2_DEBUG */
-
-done:
- /* Release the B-tree internal node */
- if (internal && H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, internal_addr, internal, internal_flags) < 0)
- HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release internal B-tree node")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5B2_remove_internal() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5B2_remove
*
* Purpose: Removes a record from a B-tree.
@@ -3654,190 +756,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5B2_neighbor_leaf
- *
- * Purpose: Locate a record relative to the specified information in a
- * B-tree leaf node and return that information by filling in
- * fields of the
- * caller-supplied UDATA pointer depending on the type of leaf node
- * requested. The UDATA can point to additional data passed
- * to the key comparison function.
- *
- * The 'OP' routine is called with the record found and the
- * OP_DATA pointer, to allow caller to return information about
- * the record.
- *
- * The RANGE indicates whether to search for records less than or
- * equal to, or greater than or equal to the information passed
- * in with UDATA.
- *
- * Return: Non-negative on success, negative on failure.
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Mar 9 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B2_neighbor_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
- H5B2_node_ptr_t *curr_node_ptr, void *neighbor_loc,
- H5B2_compare_t comp, void *udata, H5B2_found_t op, void *op_data)
-{
- H5B2_leaf_t *leaf; /* Pointer to leaf node */
- H5B2_shared_t *shared; /* Pointer to B-tree's shared information */
- unsigned idx; /* Location of record which matches key */
- int cmp=0; /* Comparison value of records */
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT(H5B2_neighbor_leaf)
-
- /* Check arguments. */
- HDassert(f);
- HDassert(bt2_shared);
- HDassert(curr_node_ptr);
- HDassert(H5F_addr_defined(curr_node_ptr->addr));
- HDassert(op);
-
- /* Lock current B-tree node */
- if (NULL == (leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr->addr, &(curr_node_ptr->node_nrec), bt2_shared, H5AC_READ)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
-
- /* Get the pointer to the shared B-tree info */
- shared=H5RC_GET_OBJ(bt2_shared);
- HDassert(shared);
-
-
- /* Locate node pointer for child */
- cmp = H5B2_locate_record(shared->type, leaf->nrec, shared->nat_off, leaf->leaf_native, udata, &idx);
- if(cmp > 0)
- idx++;
- else
- if(cmp == 0 && comp == H5B2_COMPARE_GREATER)
- idx++;
-
- /* Set the neighbor location, if appropriate */
- if(comp == H5B2_COMPARE_LESS) {
- if(idx > 0)
- neighbor_loc = H5B2_LEAF_NREC(leaf,shared,idx-1);
- } /* end if */
- else {
- HDassert(comp == H5B2_COMPARE_GREATER);
-
- if(idx < leaf->nrec)
- neighbor_loc = H5B2_LEAF_NREC(leaf,shared,idx);
- } /* end else */
-
- /* Make callback if neighbor record has been found */
- if(neighbor_loc) {
- /* Make callback for current record */
- if ((op)(neighbor_loc, op_data) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "'found' callback failed for B-tree neighbor operation")
- } /* end if */
- else
- HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "unable to find neighbor record in B-tree")
-
-done:
- /* Release the B-tree internal node */
- if (leaf && H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr->addr, leaf, H5AC__NO_FLAGS_SET) < 0)
- HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree leaf node")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5B2_neighbor_leaf() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5B2_neighbor_internal
- *
- * Purpose: Locate a record relative to the specified information in a
- * B-tree internal node and return that information by filling in
- * fields of the
- * caller-supplied UDATA pointer depending on the type of leaf node
- * requested. The UDATA can point to additional data passed
- * to the key comparison function.
- *
- * The 'OP' routine is called with the record found and the
- * OP_DATA pointer, to allow caller to return information about
- * the record.
- *
- * The RANGE indicates whether to search for records less than or
- * equal to, or greater than or equal to the information passed
- * in with UDATA.
- *
- * Return: Non-negative on success, negative on failure.
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Mar 9 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B2_neighbor_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
- unsigned depth, H5B2_node_ptr_t *curr_node_ptr, void *neighbor_loc,
- H5B2_compare_t comp, void *udata, H5B2_found_t op, void *op_data)
-{
- H5B2_internal_t *internal; /* Pointer to internal node */
- H5B2_shared_t *shared; /* Pointer to B-tree's shared information */
- unsigned idx; /* Location of record which matches key */
- int cmp=0; /* Comparison value of records */
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT(H5B2_neighbor_internal)
-
- /* Check arguments. */
- HDassert(f);
- HDassert(bt2_shared);
- HDassert(depth>0);
- HDassert(curr_node_ptr);
- HDassert(H5F_addr_defined(curr_node_ptr->addr));
- HDassert(op);
-
- /* Lock current B-tree node */
- if (NULL == (internal = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr->addr, &(curr_node_ptr->node_nrec), bt2_shared, H5AC_READ)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
-
- /* Get the pointer to the shared B-tree info */
- shared=H5RC_GET_OBJ(bt2_shared);
- HDassert(shared);
-
- /* Locate node pointer for child */
- cmp = H5B2_locate_record(shared->type,internal->nrec,shared->nat_off,internal->int_native,udata,&idx);
- if(cmp > 0)
- idx++;
-
- /* Set the neighbor location, if appropriate */
- if(comp == H5B2_COMPARE_LESS) {
- if(idx > 0)
- neighbor_loc = H5B2_INT_NREC(internal,shared,idx-1);
- } /* end if */
- else {
- HDassert(comp == H5B2_COMPARE_GREATER);
-
- if(idx < internal->nrec)
- neighbor_loc = H5B2_INT_NREC(internal,shared,idx);
- } /* end else */
-
- /* Attempt to find neighboring record */
- if(depth>1) {
- if(H5B2_neighbor_internal(f, dxpl_id, bt2_shared, depth-1, &internal->node_ptrs[idx], neighbor_loc, comp, udata, op, op_data)<0)
- HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "unable to find neighbor record in B-tree internal node")
- } /* end if */
- else {
- if(H5B2_neighbor_leaf(f, dxpl_id, bt2_shared, &internal->node_ptrs[idx], neighbor_loc, comp, udata, op, op_data)<0)
- HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "unable to find neighbor record in B-tree leaf node")
- } /* end else */
-
-done:
- /* Release the B-tree internal node */
- if (internal && H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr->addr, internal, H5AC__NO_FLAGS_SET) < 0)
- HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release internal B-tree node")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5B2_neighbor_internal() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5B2_neighbor
*
* Purpose: Locate a record relative to the specified information in a
@@ -3905,83 +823,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5B2_delete_node
- *
- * Purpose: Iterate over all the nodes in a B-tree node deleting them
- * after they no longer have any children
- *
- * Return: Value from callback, non-negative on success, negative on error
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Mar 9 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B2_delete_node(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, unsigned depth,
- const H5B2_node_ptr_t *curr_node)
-{
- H5B2_shared_t *shared; /* Pointer to B-tree's shared information */
- const H5AC_class_t *curr_node_class=NULL; /* Pointer to current node's class info */
- void *node=NULL; /* Pointers to current node */
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI(H5B2_delete_node, FAIL)
-
- /* Check arguments. */
- HDassert(f);
- HDassert(bt2_shared);
- HDassert(curr_node);
-
- /* Get the pointer to the shared B-tree info */
- shared=H5RC_GET_OBJ(bt2_shared);
- HDassert(shared);
-
- if(depth>0) {
- H5B2_internal_t *internal; /* Pointer to internal node */
- unsigned u; /* Local index */
-
- /* Lock the current B-tree node */
- if (NULL == (internal = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, curr_node->addr, &(curr_node->node_nrec), bt2_shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
-
- /* Set up information about current node */
- curr_node_class = H5AC_BT2_INT;
- node = internal;
-
- /* Descend into children */
- for(u=0; u<internal->nrec+1; u++)
- if(H5B2_delete_node(f, dxpl_id, bt2_shared, depth-1, &(internal->node_ptrs[u]))<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTLIST, FAIL, "node descent failed")
- } /* end if */
- else {
- H5B2_leaf_t *leaf; /* Pointer to leaf node */
-
- /* Lock the current B-tree node */
- if (NULL == (leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, curr_node->addr, &(curr_node->node_nrec), bt2_shared, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
-
- /* Set up information about current node */
- curr_node_class = H5AC_BT2_LEAF;
- node = leaf;
- } /* end else */
-
- /* Release space for current B-tree node on disk */
- if (H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, curr_node->addr, (hsize_t)shared->node_size)<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree node")
-
-done:
- /* Unlock & delete current node */
- if(node)
- if (H5AC_unprotect(f, dxpl_id, curr_node_class, curr_node->addr, node, H5AC__DELETED_FLAG) < 0)
- HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5B2_delete_node() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5B2_delete
*
* Purpose: Delete an entire B-tree from a file.
@@ -4211,161 +1052,3 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5B2_modify() */
-#ifdef H5B2_DEBUG
-
-/*-------------------------------------------------------------------------
- * Function: H5B2_assert_leaf
- *
- * Purpose: Verify than a leaf node is mostly sane
- *
- * Return: Non-negative on success, negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 19 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B2_assert_leaf(H5B2_shared_t *shared, H5B2_leaf_t *leaf)
-{
- unsigned u,v; /* Local index variables */
-
- /* General sanity checking on node */
- HDassert(leaf->nrec<=shared->split_leaf_nrec);
-
- /* Sanity checking on records */
- for(u=0; u<leaf->nrec; u++)
- for(v=0; v<u; v++)
- HDassert((shared->type->compare)(H5B2_LEAF_NREC(leaf,shared,u), H5B2_LEAF_NREC(leaf,shared,v))>0);
-
- return(0);
-} /* end H5B2_assert_leaf() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5B2_assert_leaf2
- *
- * Purpose: Verify than a leaf node is mostly sane
- *
- * Return: Non-negative on success, negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 19 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B2_assert_leaf2(H5B2_shared_t *shared, H5B2_leaf_t *leaf, H5B2_leaf_t *leaf2)
-{
- unsigned u,v; /* Local index variables */
-
- /* General sanity checking on node */
- HDassert(leaf->nrec<=shared->split_leaf_nrec);
-
- /* Sanity checking on records */
- for(u=0; u<leaf->nrec; u++) {
- HDassert((shared->type->compare)(H5B2_LEAF_NREC(leaf2,shared,0), H5B2_LEAF_NREC(leaf,shared,u))>0);
- for(v=0; v<u; v++)
- HDassert((shared->type->compare)(H5B2_LEAF_NREC(leaf,shared,u), H5B2_LEAF_NREC(leaf,shared,v))>0);
- } /* end for */
-
- return(0);
-} /* end H5B2_assert_leaf() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5B2_assert_internal
- *
- * Purpose: Verify than an internal node is mostly sane
- *
- * Return: Non-negative on success, negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 19 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B2_assert_internal(hsize_t parent_all_nrec, H5B2_shared_t *shared, H5B2_internal_t *internal)
-{
- hsize_t tot_all_nrec; /* Total number of records at or below this node */
- unsigned u,v; /* Local index variables */
-
- /* General sanity checking on node */
- HDassert(internal->nrec<=shared->split_int_nrec);
-
- /* Sanity checking on records */
- for(u=0; u<internal->nrec; u++)
- for(v=0; v<u; v++)
- HDassert((shared->type->compare)(H5B2_INT_NREC(internal,shared,u), H5B2_INT_NREC(internal,shared,v))>0);
-
- /* Sanity checking on node pointers */
- tot_all_nrec=internal->nrec;
- for(u=0; u<internal->nrec+1; u++) {
- tot_all_nrec += internal->node_ptrs[u].all_nrec;
-
- HDassert(H5F_addr_defined(internal->node_ptrs[u].addr));
- HDassert(internal->node_ptrs[u].addr>0);
- for(v=0; v<u; v++)
- HDassert(internal->node_ptrs[u].addr!=internal->node_ptrs[v].addr);
- } /* end for */
-
- /* Sanity check all_nrec total in parent */
- if(parent_all_nrec>0)
- HDassert(tot_all_nrec == parent_all_nrec);
-
- return(0);
-} /* end H5B2_assert_internal() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5B2_assert_internal2
- *
- * Purpose: Verify than internal nodes are mostly sane
- *
- * Return: Non-negative on success, negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 19 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5B2_assert_internal2(hsize_t parent_all_nrec, H5B2_shared_t *shared, H5B2_internal_t *internal, H5B2_internal_t *internal2)
-{
- hsize_t tot_all_nrec; /* Total number of records at or below this node */
- unsigned u,v; /* Local index variables */
-
- /* General sanity checking on node */
- HDassert(internal->nrec<=shared->split_int_nrec);
-
- /* Sanity checking on records */
- for(u=0; u<internal->nrec; u++)
- for(v=0; v<u; v++)
- HDassert((shared->type->compare)(H5B2_INT_NREC(internal,shared,u), H5B2_INT_NREC(internal,shared,v))>0);
-
- /* Sanity checking on node pointers */
- tot_all_nrec=internal->nrec;
- for(u=0; u<internal->nrec+1; u++) {
- tot_all_nrec += internal->node_ptrs[u].all_nrec;
-
- HDassert(H5F_addr_defined(internal->node_ptrs[u].addr));
- HDassert(internal->node_ptrs[u].addr>0);
- for(v=0; v<u; v++)
- HDassert(internal->node_ptrs[u].addr!=internal->node_ptrs[v].addr);
- for(v=0; v<internal2->nrec+1; v++)
- HDassert(internal->node_ptrs[u].addr!=internal2->node_ptrs[v].addr);
- } /* end for */
-
- /* Sanity check all_nrec total in parent */
- if(parent_all_nrec>0)
- HDassert(tot_all_nrec == parent_all_nrec);
-
- return(0);
-} /* end H5B2_assert_internal2() */
-#endif /* H5B2_DEBUG */
-
diff --git a/src/H5B2cache.c b/src/H5B2cache.c
index 0ad3242..cad430e 100644
--- a/src/H5B2cache.c
+++ b/src/H5B2cache.c
@@ -202,6 +202,7 @@ H5B2_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_type, vo
H5F_DECODE_LENGTH(f, p, bt2->root.all_nrec);
/* Initialize shared B-tree info */
+ HDassert((size_t)(p - buf) == size);
if(H5B2_shared_init(f, bt2, type, node_size, rrec_size, split_percent, merge_percent) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't create shared B-tree info")
@@ -291,7 +292,7 @@ H5B2_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B
H5F_ENCODE_LENGTH(f, p, bt2->root.all_nrec);
/* Write the B-tree header. */
- HDassert((p - buf) == size);
+ HDassert((size_t)(p - buf) == size);
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")
@@ -431,13 +432,13 @@ static H5B2_leaf_t *
H5B2_cache_leaf_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nrec, void *_bt2_shared)
{
const unsigned *nrec = (const unsigned *)_nrec;
- H5RC_t *bt2_shared=(H5RC_t *)_bt2_shared; /* Shared B-tree information */
+ H5RC_t *bt2_shared = (H5RC_t *)_bt2_shared; /* Shared B-tree information */
H5B2_shared_t *shared; /* Shared B-tree information */
- H5B2_leaf_t *leaf = NULL;
+ H5B2_leaf_t *leaf = NULL; /* Pointer to lead node loaded */
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;
+ H5B2_leaf_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5B2_cache_leaf_load, NULL)
@@ -446,49 +447,51 @@ H5B2_cache_leaf_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nrec, v
HDassert(H5F_addr_defined(addr));
HDassert(bt2_shared);
- if (NULL==(leaf = H5FL_MALLOC(H5B2_leaf_t)))
+ 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));
+ 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);
+ 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)
+ 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))
+ /* 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)
+ /* Version */
+ if(*p++ != H5B2_LEAF_VERSION)
HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree leaf node version")
+/* XXX: Add metadata flags & checksum to v2 B-tree metadata (like fractal heap) */
+
/* B-tree type */
- if (*p++ != (uint8_t)shared->type->id)
+ 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)
+ 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 = *nrec;
/* Deserialize records for leaf node */
- native=leaf->leaf_native;
- for(u=0; u<leaf->nrec; u++) {
+ native = leaf->leaf_native;
+ for(u = 0; u < leaf->nrec; u++) {
/* Decode record */
- if((shared->type->decode)(f,p,native)<0)
+ 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 */
@@ -496,11 +499,14 @@ H5B2_cache_leaf_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nrec, v
native += shared->type->nrec_size;
} /* end for */
+ /* Sanity check parsing */
+ HDassert((size_t)(p - shared->page) <= shared->node_size);
+
/* Set return value */
ret_value = leaf;
done:
- if (!ret_value && leaf)
+ 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 */
@@ -531,14 +537,14 @@ H5B2_cache_leaf_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5
HDassert(H5F_addr_defined(addr));
HDassert(leaf);
- if (leaf->cache_info.is_dirty) {
+ 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);
+ shared = H5RC_GET_OBJ(leaf->shared);
HDassert(shared);
p = shared->page;
@@ -554,10 +560,10 @@ H5B2_cache_leaf_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5
*p++ = shared->type->id;
/* Serialize records for leaf node */
- native=leaf->leaf_native;
- for(u=0; u<leaf->nrec; u++) {
+ native = leaf->leaf_native;
+ for(u = 0; u < leaf->nrec; u++) {
/* Encode record */
- if((shared->type->encode)(f,p,native)<0)
+ 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 */
@@ -566,14 +572,15 @@ H5B2_cache_leaf_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5
} /* 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)
+ HDassert((size_t)(p - shared->page) <= shared->node_size);
+ 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)
+ 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:
@@ -608,7 +615,7 @@ H5B2_cache_leaf_dest(H5F_t UNUSED *f, H5B2_leaf_t *leaf)
HDassert(leaf);
/* Get the pointer to the shared B-tree info */
- shared=H5RC_GET_OBJ(leaf->shared);
+ shared = H5RC_GET_OBJ(leaf->shared);
HDassert(shared);
/* Release leaf's native key buffer */
@@ -654,8 +661,8 @@ H5B2_cache_leaf_clear(H5F_t *f, H5B2_leaf_t *leaf, hbool_t destroy)
/* Reset the dirty flag. */
leaf->cache_info.is_dirty = FALSE;
- if (destroy)
- if (H5B2_cache_leaf_dest(f, leaf) < 0)
+ 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:
@@ -690,7 +697,7 @@ H5B2_cache_leaf_size(const H5F_t UNUSED *f, const H5B2_leaf_t *leaf, size_t *siz
HDassert(size_ptr);
/* Get the pointer to the shared B-tree info */
- shared=H5RC_GET_OBJ(leaf->shared);
+ shared = H5RC_GET_OBJ(leaf->shared);
HDassert(shared);
/* Set size value */
@@ -721,12 +728,12 @@ H5B2_cache_internal_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nre
const unsigned *nrec = (const unsigned *)_nrec;
H5RC_t *bt2_shared = (H5RC_t *)_bt2_shared; /* Ref counter for shared B-tree info */
H5B2_shared_t *shared; /* Shared B-tree information */
- H5B2_internal_t *internal = NULL;
+ H5B2_internal_t *internal = NULL; /* Internal node read */
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;
+ H5B2_internal_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5B2_cache_internal_load, NULL)
@@ -735,9 +742,9 @@ H5B2_cache_internal_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nre
HDassert(H5F_addr_defined(addr));
HDassert(bt2_shared);
- if (NULL==(internal = H5FL_MALLOC(H5B2_internal_t)))
+ 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));
+ HDmemset(&internal->cache_info, 0, sizeof(H5AC_info_t));
/* Share common B-tree information */
internal->shared = bt2_shared;
@@ -748,40 +755,42 @@ H5B2_cache_internal_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nre
HDassert(shared);
/* Read header from disk */
- if (H5F_block_read(f, H5FD_MEM_BTREE, addr, shared->node_size, dxpl_id, shared->page)<0)
+ 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))
+ /* 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)
+ /* Version */
+ if(*p++ != H5B2_INT_VERSION)
HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree internal node version")
+/* XXX: Add metadata flags & checksum to v2 B-tree metadata (like fractal heap) */
+
/* 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)
+ 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)
+ 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 = *nrec;
/* Deserialize records for internal node */
- native=internal->int_native;
- for(u=0; u<internal->nrec; u++) {
+ native = internal->int_native;
+ for(u = 0; u < internal->nrec; u++) {
/* Decode record */
- if((shared->type->decode)(f,p,native)<0)
+ 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 */
@@ -790,8 +799,8 @@ H5B2_cache_internal_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nre
} /* end for */
/* Deserialize node pointers for internal node */
- int_node_ptr=internal->node_ptrs;
- for(u=0; u<internal->nrec+1; u++) {
+ 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);
@@ -801,12 +810,15 @@ H5B2_cache_internal_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nre
int_node_ptr++;
} /* end for */
+ /* Sanity check parsing */
+ HDassert((size_t)(p - shared->page) <= shared->node_size);
+
/* Set return value */
ret_value = internal;
done:
- if (!ret_value && internal)
- (void)H5B2_cache_internal_dest(f,internal);
+ 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 */
@@ -836,7 +848,7 @@ H5B2_cache_internal_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr
HDassert(H5F_addr_defined(addr));
HDassert(internal);
- if (internal->cache_info.is_dirty) {
+ 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 */
@@ -844,26 +856,26 @@ H5B2_cache_internal_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr
unsigned u; /* Local index variable */
/* Get the pointer to the shared B-tree info */
- shared=H5RC_GET_OBJ(internal->shared);
+ shared = H5RC_GET_OBJ(internal->shared);
HDassert(shared);
p = shared->page;
- /* magic number */
+ /* Magic number */
HDmemcpy(p, H5B2_INT_MAGIC, H5B2_SIZEOF_MAGIC);
p += H5B2_SIZEOF_MAGIC;
- /* version # */
+ /* Version # */
*p++ = H5B2_INT_VERSION;
- /* b-tree type */
+ /* B-tree type */
*p++ = shared->type->id;
/* Serialize records for internal node */
- native=internal->int_native;
- for(u=0; u<internal->nrec; u++) {
+ native = internal->int_native;
+ for(u = 0; u < internal->nrec; u++) {
/* Encode record */
- if((shared->type->encode)(f,p,native)<0)
+ 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 */
@@ -872,8 +884,8 @@ H5B2_cache_internal_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr
} /* end for */
/* Serialize node pointers for internal node */
- int_node_ptr=internal->node_ptrs;
- for(u=0; u<internal->nrec+1; u++) {
+ 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);
@@ -884,14 +896,15 @@ H5B2_cache_internal_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr
} /* 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)
+ HDassert((size_t)(p - shared->page) <= shared->node_size);
+ 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)
+ 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:
@@ -926,23 +939,23 @@ H5B2_cache_internal_dest(H5F_t UNUSED *f, H5B2_internal_t *internal)
HDassert(internal);
/* Get the pointer to the shared B-tree info */
- shared=H5RC_GET_OBJ(internal->shared);
+ 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);
+ 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);
+ 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);
+ H5FL_FREE(H5B2_internal_t, internal);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5B2_cache_internal_dest() */
@@ -976,8 +989,8 @@ H5B2_cache_internal_clear(H5F_t *f, H5B2_internal_t *internal, hbool_t destroy)
/* Reset the dirty flag. */
internal->cache_info.is_dirty = FALSE;
- if (destroy)
- if (H5B2_cache_internal_dest(f, internal) < 0)
+ 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:
@@ -1012,7 +1025,7 @@ H5B2_cache_internal_size(const H5F_t UNUSED *f, const H5B2_internal_t *internal,
HDassert(size_ptr);
/* Get the pointer to the shared B-tree info */
- shared=H5RC_GET_OBJ(internal->shared);
+ shared = H5RC_GET_OBJ(internal->shared);
HDassert(shared);
/* Set size value */
@@ -1021,4 +1034,3 @@ H5B2_cache_internal_size(const H5F_t UNUSED *f, const H5B2_internal_t *internal,
FUNC_LEAVE_NOAPI(SUCCEED)
} /* H5B2_cache_internal_size() */
-
diff --git a/src/H5B2int.c b/src/H5B2int.c
new file mode 100644
index 0000000..9b4b8db
--- /dev/null
+++ b/src/H5B2int.c
@@ -0,0 +1,3357 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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: H5B2int.c
+ * Feb 27 2006
+ * Quincey Koziol <koziol@ncsa.uiuc.edu>
+ *
+ * Purpose: Internal routines for managing v2 B-trees.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5B2_PACKAGE /*suppress error about including H5B2pkg */
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5B2pkg.h" /* v2 B-trees */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5MFprivate.h" /* File memory management */
+
+/****************/
+/* Local Macros */
+/****************/
+
+/* Format overhead for each node (on disk) */
+#define H5B2_OVERHEAD_SIZE (H5B2_SIZEOF_MAGIC+1) /* Signature + version # */
+
+/* Number of records that fit into internal node */
+#define H5B2_NUM_INT_REC(f,n,r) (((n)-(H5B2_OVERHEAD_SIZE+H5B2_NODE_POINTER_SIZE(f)))/((r)+H5B2_NODE_POINTER_SIZE(f)))
+
+/* Number of records that fit into leaf node */
+#define H5B2_NUM_LEAF_REC(n,r) (((n)-H5B2_OVERHEAD_SIZE)/(r))
+
+/* Uncomment this macro to enable extra sanity checking */
+/* #define H5B2_DEBUG */
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+/* Helper functions */
+static herr_t H5B2_shared_free(void *_shared);
+static herr_t H5B2_create_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
+ H5B2_node_ptr_t *node_ptr);
+static herr_t H5B2_redistribute2(H5F_t *f, hid_t dxpl_id, unsigned depth,
+ H5B2_internal_t *internal, unsigned idx);
+static herr_t H5B2_split2(H5F_t *f, hid_t dxpl_id, unsigned depth,
+ H5B2_node_ptr_t *curr_node_ptr, unsigned * parent_cache_info_flags_ptr,
+ H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx);
+static herr_t H5B2_split3(H5F_t *f, hid_t dxpl_id, unsigned depth,
+ H5B2_node_ptr_t *curr_node_ptr, unsigned *parent_cache_info_flags,
+ H5B2_internal_t *internal, unsigned *internal_flags, unsigned idx);
+static herr_t H5B2_redistribute3(H5F_t *f, hid_t dxpl_id, unsigned depth,
+ H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx);
+static herr_t H5B2_merge2(H5F_t *f, hid_t dxpl_id, unsigned depth,
+ H5B2_node_ptr_t *curr_node_ptr, unsigned *parent_cache_info_flags_ptr,
+ H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx);
+static herr_t H5B2_merge3(H5F_t *f, hid_t dxpl_id, unsigned depth,
+ H5B2_node_ptr_t *curr_node_ptr, unsigned *parent_cache_info_flags_ptr,
+ H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx);
+static herr_t H5B2_swap_leaf(H5F_t *f, hid_t dxpl_id, unsigned depth,
+ H5B2_internal_t *internal, unsigned *internal_flags_ptr,
+ unsigned idx, void *swap_loc);
+#ifdef H5B2_DEBUG
+static herr_t H5B2_assert_leaf(H5B2_shared_t *shared, H5B2_leaf_t *leaf);
+static herr_t H5B2_assert_leaf2(H5B2_shared_t *shared, H5B2_leaf_t *leaf, H5B2_leaf_t *leaf2);
+static herr_t H5B2_assert_internal(hsize_t parent_all_nrec, H5B2_shared_t *shared, H5B2_internal_t *internal);
+static herr_t H5B2_assert_internal2(hsize_t parent_all_nrec, H5B2_shared_t *shared, H5B2_internal_t *internal, H5B2_internal_t *internal2);
+#endif /* H5B2_DEBUG */
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+/* 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);
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local 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 'size_t' sequence information */
+H5FL_SEQ_DEFINE_STATIC(size_t);
+
+/* Declare a free list to manage the H5B2_shared_t struct */
+H5FL_DEFINE_STATIC(H5B2_shared_t);
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_shared_init
+ *
+ * Purpose: Allocate & initialize shared B-tree info
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 2 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5B2_shared_init (H5F_t *f, H5B2_t *bt2, const H5B2_class_t *type,
+ size_t node_size, size_t rrec_size,
+ unsigned split_percent, unsigned merge_percent)
+{
+ H5B2_shared_t *shared = NULL; /* Shared B-tree information */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5B2_shared_init)
+
+ /* Allocate space for the shared information */
+ if(NULL == (shared = H5FL_CALLOC(H5B2_shared_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree shared information")
+
+ /* Assign user's information */
+ shared->split_percent = split_percent;
+ shared->merge_percent = merge_percent;
+ shared->node_size = node_size;
+ shared->rrec_size = rrec_size;
+
+ /* Compute derived information */
+ shared->internal_nrec = H5B2_NUM_INT_REC(f, shared->node_size, shared->rrec_size);
+ shared->split_int_nrec = (shared->internal_nrec * shared->split_percent) / 100;
+ shared->merge_int_nrec = (shared->internal_nrec * shared->merge_percent) / 100;
+
+ shared->leaf_nrec = H5B2_NUM_LEAF_REC(shared->node_size, shared->rrec_size);
+ shared->split_leaf_nrec = (shared->leaf_nrec * shared->split_percent) / 100;
+ shared->merge_leaf_nrec = (shared->leaf_nrec * shared->merge_percent) / 100;
+
+ /* Assign common type information */
+ shared->type = type;
+
+ /* Allocate "page" for node I/O */
+ if((shared->page = H5FL_BLK_MALLOC(node_page, shared->node_size)) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+#ifdef H5_USING_PURIFY
+HDmemset(shared->page,0,shared->node_size);
+#endif /* H5_USING_PURIFY */
+
+ /* Create factory for internal node native record storage */
+ if((shared->int_fac = H5FL_fac_init(type->nrec_size * shared->internal_nrec)) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create internal node native key block factory")
+
+ /* Create factory for leaf node native record storage */
+ if((shared->leaf_fac = H5FL_fac_init(type->nrec_size * shared->leaf_nrec)) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create leaf node native key block factory")
+
+ /* Create factory for internal node node pointer storage */
+ if((shared->node_ptr_fac = H5FL_fac_init(sizeof(H5B2_node_ptr_t) * (shared->internal_nrec + 1))) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create internal node node pointer block factory")
+
+ /* Allocate array of pointers to internal node native keys */
+ if((shared->nat_off = H5FL_SEQ_MALLOC(size_t, MAX(shared->internal_nrec, shared->leaf_nrec))) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Initialize offsets in native key block */
+ for(u = 0; u < MAX(shared->internal_nrec, shared->leaf_nrec); u++)
+ shared->nat_off[u]=type->nrec_size*u;
+
+ /* Make shared B-tree info reference counted */
+ if(NULL == (bt2->shared = H5RC_create(shared, H5B2_shared_free)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create ref-count wrapper for shared B-tree info")
+
+done:
+ if(ret_value < 0)
+ if(shared)
+ H5B2_shared_free(shared);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5B2_shared_init() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_shared_free
+ *
+ * Purpose: Free shared B-tree info
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 2 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B2_shared_free(void *_shared)
+{
+ H5B2_shared_t *shared = (H5B2_shared_t *)_shared;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT(H5B2_shared_free)
+
+ /* Sanity check */
+ HDassert(shared);
+
+ /* Free the B-tree node buffer */
+ if(shared->page)
+ H5FL_BLK_FREE(node_page, shared->page);
+
+ /* Destroy factory for internal node native record storage */
+ if(shared->int_fac)
+ if(H5FL_fac_term(shared->int_fac) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't destroy internal node native key block factory")
+
+ /* Destroy factory for leaf node native record storage */
+ if(shared->leaf_fac)
+ if(H5FL_fac_term(shared->leaf_fac) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't destroy leaf node native key block factory")
+
+ /* Destroy factory for internal node node pointer storage */
+ if(shared->node_ptr_fac)
+ 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 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);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5B2_shared_free() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_locate_record
+ *
+ * Purpose: Performs a binary search to locate a record in a sorted
+ * array of records.
+ *
+ * Sets *IDX to location of record greater than or equal to
+ * record to locate.
+ *
+ * Return: Comparison value for insertion location. Negative for record
+ * to locate being less than value in *IDX. Zero for record to
+ * locate equal to value in *IDX. Positive for record to locate
+ * being greater than value in *IDX (which should only happen when
+ * record to locate is greater than all records to search).
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 3 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+H5B2_locate_record(const H5B2_class_t *type, unsigned nrec, size_t *rec_off,
+ const uint8_t *native, const void *udata, unsigned *idx)
+{
+ unsigned lo = 0, hi; /* Low & high index values */
+ unsigned my_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) {
+ my_idx = (lo + hi) / 2;
+ if ((cmp = (type->compare)(udata, native+rec_off[my_idx])) < 0)
+ hi = my_idx;
+ else
+ lo = my_idx + 1;
+ }
+
+ *idx = my_idx;
+
+ FUNC_LEAVE_NOAPI(cmp);
+} /* end H5B2_locate_record */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_split_root
+ *
+ * Purpose: Split the root node
+ *
+ * Return: Success: Non-negative
+ *
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 3 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5B2_split_root(H5F_t *f, hid_t dxpl_id, H5B2_t *bt2, unsigned *bt2_flags_ptr,
+ H5RC_t *bt2_shared)
+{
+ const H5AC_class_t *child_class; /* Pointer to child node's class info */
+ H5B2_internal_t *new_root; /* Pointer to new root node */
+ haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */
+ void *left_child, *right_child; /* Pointers to child nodes */
+ unsigned *left_nrec, *right_nrec; /* Pointers to child # of records */
+ uint8_t *left_native, *right_native;/* Pointers to childs' native records */
+ H5B2_node_ptr_t *left_node_ptrs=NULL, *right_node_ptrs=NULL;/* Pointers to childs' node pointer info */
+ H5B2_shared_t *shared; /* B-tree's shared info */
+ unsigned mid_record; /* Index of "middle" record in current node */
+ unsigned old_root_nrec; /* Number of records in root node */
+ herr_t ret_value=SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5B2_split_root)
+
+ HDassert(f);
+ HDassert(bt2);
+ HDassert(bt2_flags_ptr);
+ HDassert(bt2_shared);
+
+ /* Get the pointer to the shared B-tree info */
+ shared=H5RC_GET_OBJ(bt2_shared);
+ HDassert(shared);
+
+ if(bt2->depth>0) {
+ H5B2_internal_t *old_int=NULL, *new_int=NULL; /* Pointers to old & new internal nodes */
+ H5B2_node_ptr_t new_int_ptr; /* Node pointer to manage new internal node */
+
+ /* Create new internal node */
+ new_int_ptr.all_nrec=new_int_ptr.node_nrec=0;
+ if(H5B2_create_internal(f, dxpl_id, bt2_shared, &new_int_ptr)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new internal node")
+
+ /* Setup information for unlocking child nodes */
+ child_class = H5AC_BT2_INT;
+ left_addr = bt2->root.addr;
+ right_addr = new_int_ptr.addr;
+
+ /* Protect both leafs */
+ if (NULL == (old_int = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, left_addr, &(bt2->root.node_nrec), bt2_shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
+ if (NULL == (new_int = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, right_addr, &(new_int_ptr.node_nrec), bt2_shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
+
+ /* More setup for child nodes */
+ left_child = old_int;
+ right_child = new_int;
+ left_nrec = &(old_int->nrec);
+ right_nrec = &(new_int->nrec);
+ left_native = old_int->int_native;
+ right_native = new_int->int_native;
+ left_node_ptrs = old_int->node_ptrs;
+ right_node_ptrs = new_int->node_ptrs;
+ } /* end if */
+ else {
+ H5B2_leaf_t *old_leaf=NULL, *new_leaf=NULL; /* Pointers to old & new leaf nodes */
+ H5B2_node_ptr_t new_leaf_ptr; /* Node pointer to manage new leaf node */
+
+ /* Create new leaf node */
+ new_leaf_ptr.all_nrec=new_leaf_ptr.node_nrec=0;
+ if(H5B2_create_leaf(f, dxpl_id, bt2_shared, &new_leaf_ptr)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new leaf node")
+
+ /* Setup information for unlocking child nodes */
+ child_class = H5AC_BT2_LEAF;
+ left_addr = bt2->root.addr;
+ right_addr = new_leaf_ptr.addr;
+
+ /* Protect both leafs */
+ if (NULL == (old_leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, left_addr, &(bt2->root.node_nrec), bt2_shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
+ if (NULL == (new_leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, right_addr, &(new_leaf_ptr.node_nrec), bt2_shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
+
+ /* More setup for child nodes */
+ left_child = old_leaf;
+ right_child = new_leaf;
+ left_nrec = &(old_leaf->nrec);
+ right_nrec = &(new_leaf->nrec);
+ left_native = old_leaf->leaf_native;
+ right_native = new_leaf->leaf_native;
+ } /* end if */
+
+ /* Set the old number of records in root node */
+ old_root_nrec = bt2->root.node_nrec;
+
+ /* Determine "middle" record to promote to new root */
+ mid_record = old_root_nrec/2;
+
+ /* Copy "upper half" of records to new child */
+ HDmemcpy(H5B2_NAT_NREC(right_native,shared,0),H5B2_NAT_NREC(left_native,shared,mid_record+1),shared->type->nrec_size*(old_root_nrec-(mid_record+1)));
+
+ /* Copy "upper half" of format root's node pointers, if the children of the root are internal nodes */
+ if(bt2->depth>0)
+ HDmemcpy(&(right_node_ptrs[0]),&(left_node_ptrs[mid_record+1]),sizeof(H5B2_node_ptr_t)*(old_root_nrec-mid_record));
+
+ /* Create new internal node to use as root */
+ if(H5B2_create_internal(f, dxpl_id, bt2_shared, &(bt2->root))<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new internal node")
+
+ /* Protect new internal node */
+ if (NULL == (new_root = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, bt2->root.addr, &(bt2->root.node_nrec), bt2_shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
+
+ /* Copy "middle" record to new internal node */
+ HDmemcpy(H5B2_INT_NREC(new_root,shared,0),H5B2_NAT_NREC(left_native,shared,mid_record),shared->type->nrec_size);
+
+ /* Set internal node pointers to child nodes */
+ new_root->node_ptrs[0].addr = left_addr;
+ new_root->node_ptrs[1].addr = right_addr;
+
+ /* Update record counts in child nodes */
+ new_root->node_ptrs[0].node_nrec = *left_nrec = mid_record;
+ new_root->node_ptrs[1].node_nrec = *right_nrec = old_root_nrec-(mid_record+1);
+
+ /* Determine total number of records in new child nodes */
+ if(bt2->depth>0) {
+ unsigned u; /* Local index variable */
+ hsize_t new_left_all_nrec; /* New total number of records in left child */
+ hsize_t new_right_all_nrec; /* New total number of records in right child */
+
+ /* Compute total of all records in each child node */
+ new_left_all_nrec = new_root->node_ptrs[0].node_nrec;
+ for(u=0; u<(*left_nrec+1); u++)
+ new_left_all_nrec += left_node_ptrs[u].all_nrec;
+
+ new_right_all_nrec = new_root->node_ptrs[1].node_nrec;
+ for(u=0; u<(*right_nrec+1); u++)
+ new_right_all_nrec += right_node_ptrs[u].all_nrec;
+
+ new_root->node_ptrs[0].all_nrec = new_left_all_nrec;
+ new_root->node_ptrs[1].all_nrec = new_right_all_nrec;
+ } /* end if */
+ else {
+ new_root->node_ptrs[0].all_nrec = new_root->node_ptrs[0].node_nrec;
+ new_root->node_ptrs[1].all_nrec = new_root->node_ptrs[1].node_nrec;
+ } /* end else */
+
+ /* Update record count in new internal node */
+ new_root->nrec = 1;
+
+#ifdef H5B2_DEBUG
+ H5B2_assert_internal(bt2->root.all_nrec,shared,new_root);
+ if(bt2->depth>0) {
+ H5B2_assert_internal2(new_root->node_ptrs[0].all_nrec,shared,left_child,right_child);
+ H5B2_assert_internal2(new_root->node_ptrs[1].all_nrec,shared,right_child,left_child);
+ } /* end if */
+ else {
+ H5B2_assert_leaf2(shared,left_child,right_child);
+ H5B2_assert_leaf(shared,right_child);
+ } /* end else */
+#endif /* H5B2_DEBUG */
+ /* Release new internal node (marked as dirty) */
+ if (H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, bt2->root.addr, new_root, H5AC__DIRTIED_FLAG) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree internal node")
+
+ /* Release child nodes (marked as dirty) */
+ if (H5AC_unprotect(f, dxpl_id, child_class, left_addr, left_child, H5AC__DIRTIED_FLAG) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree leaf node")
+ if (H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree leaf node")
+
+ /* Update depth of B-tree */
+ bt2->depth++;
+
+ /* Update pointer to B-tree's root node to pointer to new internal node */
+ bt2->root.node_nrec = 1;
+
+ /* Mark B-tree header as dirty */
+ *bt2_flags_ptr |= H5AC__DIRTIED_FLAG;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5B2_split_root */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_redistribute2
+ *
+ * Purpose: Redistribute records between two nodes
+ *
+ * Return: Success: Non-negative
+ *
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 9 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B2_redistribute2(H5F_t *f, hid_t dxpl_id, unsigned depth, H5B2_internal_t *internal, unsigned idx)
+{
+ const H5AC_class_t *child_class; /* Pointer to child node's class info */
+ haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */
+ void *left_child, *right_child; /* Pointers to child nodes */
+ unsigned *left_nrec, *right_nrec; /* Pointers to child # of records */
+ uint8_t *left_native, *right_native; /* Pointers to childs' native records */
+ H5B2_node_ptr_t *left_node_ptrs=NULL, *right_node_ptrs=NULL;/* Pointers to childs' node pointer info */
+ H5B2_shared_t *shared; /* B-tree's shared info */
+ hssize_t left_moved_nrec=0, right_moved_nrec=0; /* Number of records moved, for internal redistrib */
+ herr_t ret_value=SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5B2_redistribute2)
+
+ HDassert(f);
+ HDassert(internal);
+
+ /* Get the pointer to the shared B-tree info */
+ shared=H5RC_GET_OBJ(internal->shared);
+ HDassert(shared);
+
+ /* Check for the kind of B-tree node to redistribute */
+ if(depth>1) {
+ H5B2_internal_t *left_internal; /* Pointer to left internal node */
+ H5B2_internal_t *right_internal; /* Pointer to right internal node */
+
+ /* Setup information for unlocking child nodes */
+ child_class = H5AC_BT2_INT;
+ left_addr = internal->node_ptrs[idx].addr;
+ right_addr = internal->node_ptrs[idx+1].addr;
+
+ /* Lock left & right B-tree child nodes */
+ if (NULL == (left_internal = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
+ if (NULL == (right_internal = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
+
+ /* More setup for child nodes */
+ left_child = left_internal;
+ right_child = right_internal;
+ left_nrec = &(left_internal->nrec);
+ right_nrec = &(right_internal->nrec);
+ left_native = left_internal->int_native;
+ right_native = right_internal->int_native;
+ left_node_ptrs = left_internal->node_ptrs;
+ right_node_ptrs = right_internal->node_ptrs;
+ } /* end if */
+ else {
+ H5B2_leaf_t *left_leaf; /* Pointer to left leaf node */
+ H5B2_leaf_t *right_leaf; /* Pointer to right leaf node */
+
+ /* Setup information for unlocking child nodes */
+ child_class = H5AC_BT2_LEAF;
+ left_addr = internal->node_ptrs[idx].addr;
+ right_addr = internal->node_ptrs[idx+1].addr;
+
+ /* Lock left & right B-tree child nodes */
+ if (NULL == (left_leaf = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
+ if (NULL == (right_leaf = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
+
+ /* More setup for child nodes */
+ left_child = left_leaf;
+ right_child = right_leaf;
+ left_nrec = &(left_leaf->nrec);
+ right_nrec = &(right_leaf->nrec);
+ left_native = left_leaf->leaf_native;
+ right_native = right_leaf->leaf_native;
+ } /* end else */
+
+#ifdef H5B2_DEBUG
+ H5B2_assert_internal((hsize_t)0,shared,internal);
+ if(depth>1) {
+ H5B2_assert_internal2(internal->node_ptrs[idx].all_nrec,shared,left_child,right_child);
+ H5B2_assert_internal2(internal->node_ptrs[idx+1].all_nrec,shared,right_child,left_child);
+ } /* end if */
+ else {
+ H5B2_assert_leaf2(shared,left_child,right_child);
+ H5B2_assert_leaf(shared,right_child);
+ } /* end else */
+#endif /* H5B2_DEBUG */
+
+ /* Determine whether to shuffle records left or right */
+ if(*left_nrec<*right_nrec) {
+ /* Moving record from right node to left */
+
+ unsigned new_right_nrec = (*left_nrec+*right_nrec)/2; /* New number of records for right child */
+ unsigned move_nrec = *right_nrec - new_right_nrec; /* Number of records to move from right node to left */
+
+ /* Copy record from parent node down into left child */
+ HDmemcpy(H5B2_NAT_NREC(left_native,shared,*left_nrec),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size);
+
+ /* See if we need to move records from right node */
+ if(move_nrec>1)
+ HDmemcpy(H5B2_NAT_NREC(left_native,shared,(*left_nrec+1)),H5B2_NAT_NREC(right_native,shared,0),shared->type->nrec_size*(move_nrec-1));
+
+ /* Move record from right node into parent node */
+ HDmemcpy(H5B2_INT_NREC(internal,shared,idx),H5B2_NAT_NREC(right_native,shared,(move_nrec-1)),shared->type->nrec_size);
+
+ /* Slide records in right node down */
+ HDmemmove(H5B2_NAT_NREC(right_native,shared,0),H5B2_NAT_NREC(right_native,shared,move_nrec),shared->type->nrec_size*new_right_nrec);
+
+ /* Handle node pointers, if we have an internal node */
+ if(depth>1) {
+ hsize_t moved_nrec=move_nrec; /* Total number of records moved, for internal redistrib */
+ unsigned u; /* Local index variable */
+
+ /* Count the number of records being moved */
+ for(u=0; u<move_nrec; u++)
+ moved_nrec += right_node_ptrs[u].all_nrec;
+ left_moved_nrec = moved_nrec;
+ right_moved_nrec -= moved_nrec;
+
+ /* Copy node pointers from right node to left */
+ HDmemcpy(&(left_node_ptrs[*left_nrec+1]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*move_nrec);
+
+ /* Slide node pointers in right node down */
+ HDmemmove(&(right_node_ptrs[0]),&(right_node_ptrs[move_nrec]),sizeof(H5B2_node_ptr_t)*(new_right_nrec+1));
+ } /* end if */
+
+ /* Update number of records in child nodes */
+ *left_nrec += move_nrec;
+ *right_nrec = new_right_nrec;
+ } /* end if */
+ else {
+ /* Moving record from left node to right */
+
+ unsigned new_left_nrec = (*left_nrec+*right_nrec)/2; /* New number of records for left child */
+ unsigned move_nrec = *left_nrec - new_left_nrec; /* Number of records to move from left node to right */
+
+ /* Slide records in right node up */
+ HDmemmove(H5B2_NAT_NREC(right_native,shared,move_nrec),
+ H5B2_NAT_NREC(right_native,shared,0),
+ shared->type->nrec_size*(*right_nrec));
+
+ /* Copy record from parent node down into right child */
+ HDmemcpy(H5B2_NAT_NREC(right_native,shared,(move_nrec-1)),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size);
+
+ /* See if we need to move records from left node */
+ if(move_nrec>1)
+ HDmemcpy(H5B2_NAT_NREC(right_native,shared,0),H5B2_NAT_NREC(left_native,shared,((*left_nrec-move_nrec)+1)),shared->type->nrec_size*(move_nrec-1));
+
+ /* Move record from left node into parent node */
+ HDmemcpy(H5B2_INT_NREC(internal,shared,idx),H5B2_NAT_NREC(left_native,shared,(*left_nrec-move_nrec)),shared->type->nrec_size);
+
+ /* Handle node pointers, if we have an internal node */
+ if(depth>1) {
+ hsize_t moved_nrec=move_nrec; /* Total number of records moved, for internal redistrib */
+ unsigned u; /* Local index variable */
+
+ /* Slide node pointers in right node up */
+ HDmemmove(&(right_node_ptrs[move_nrec]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*(*right_nrec+1));
+
+ /* Copy node pointers from left node to right */
+ HDmemcpy(&(right_node_ptrs[0]),&(left_node_ptrs[new_left_nrec+1]),sizeof(H5B2_node_ptr_t)*move_nrec);
+
+ /* Count the number of records being moved */
+ for(u=0; u<move_nrec; u++)
+ moved_nrec += right_node_ptrs[u].all_nrec;
+ left_moved_nrec -= moved_nrec;
+ right_moved_nrec = moved_nrec;
+ } /* end if */
+
+ /* Update number of records in child nodes */
+ *left_nrec = new_left_nrec;
+ *right_nrec += move_nrec;
+ } /* end else */
+
+ /* Update # of records in child nodes */
+ internal->node_ptrs[idx].node_nrec = *left_nrec;
+ internal->node_ptrs[idx+1].node_nrec = *right_nrec;
+
+ /* Update total # of records in child B-trees */
+ if(depth>1) {
+ internal->node_ptrs[idx].all_nrec += left_moved_nrec;
+ internal->node_ptrs[idx+1].all_nrec += right_moved_nrec;
+ } /* end if */
+ else {
+ internal->node_ptrs[idx].all_nrec = internal->node_ptrs[idx].node_nrec;
+ internal->node_ptrs[idx+1].all_nrec = internal->node_ptrs[idx+1].node_nrec;
+ } /* end else */
+
+#ifdef H5B2_DEBUG
+ H5B2_assert_internal((hsize_t)0,shared,internal);
+ if(depth>1) {
+ H5B2_assert_internal2(internal->node_ptrs[idx].all_nrec,shared,left_child,right_child);
+ H5B2_assert_internal2(internal->node_ptrs[idx+1].all_nrec,shared,right_child,left_child);
+ } /* end if */
+ else {
+ H5B2_assert_leaf2(shared,left_child,right_child);
+ H5B2_assert_leaf(shared,right_child);
+ } /* end else */
+#endif /* H5B2_DEBUG */
+
+ /* Release child nodes (marked as dirty) */
+ if (H5AC_unprotect(f, dxpl_id, child_class, left_addr, left_child, H5AC__DIRTIED_FLAG) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
+ if (H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5B2_redistribute2 */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_split2
+ *
+ * Purpose: Perform a 2->3 node split
+ *
+ * Return: Success: Non-negative
+ *
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 9 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B2_split2(H5F_t *f, hid_t dxpl_id, unsigned depth, H5B2_node_ptr_t *curr_node_ptr,
+ unsigned *parent_cache_info_flags_ptr, H5B2_internal_t *internal,
+ unsigned *internal_flags_ptr, unsigned idx)
+{
+ const H5AC_class_t *child_class; /* Pointer to child node's class info */
+ haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */
+ haddr_t middle_addr; /* Address of middle child node */
+ void *left_child, *right_child; /* Pointers to left & right child nodes */
+ void *middle_child; /* Pointer to middle child node */
+ unsigned *left_nrec, *right_nrec; /* Pointers to left & right child # of records */
+ unsigned *middle_nrec; /* Pointer to middle child # of records */
+ uint8_t *left_native, *right_native; /* Pointers to left & right children's native records */
+ uint8_t *middle_native; /* Pointer to middle child's native records */
+ H5B2_node_ptr_t *left_node_ptrs=NULL, *right_node_ptrs=NULL;/* Pointers to childs' node pointer info */
+ H5B2_node_ptr_t *middle_node_ptrs=NULL;/* Pointers to childs' node pointer info */
+ H5B2_shared_t *shared; /* B-tree's shared info */
+ hssize_t left_moved_nrec=0, right_moved_nrec=0; /* Number of records moved, for internal split */
+ hsize_t middle_moved_nrec=0; /* Number of records moved, for internal split */
+ herr_t ret_value=SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5B2_split2)
+
+ HDassert(f);
+ HDassert(parent_cache_info_flags_ptr);
+ HDassert(internal);
+ HDassert(internal_flags_ptr);
+
+ /* Get the pointer to the shared B-tree info */
+ shared=H5RC_GET_OBJ(internal->shared);
+ HDassert(shared);
+
+ /* Slide records in parent node up one space, to make room for promoted record */
+ HDmemmove(H5B2_INT_NREC(internal,shared,idx+2),H5B2_INT_NREC(internal,shared,idx+1),shared->type->nrec_size*(internal->nrec-(idx+1)));
+ HDmemmove(&(internal->node_ptrs[idx+2]),&(internal->node_ptrs[idx+1]),sizeof(H5B2_node_ptr_t)*(internal->nrec-idx));
+
+ /* Check for the kind of B-tree node to split */
+ if(depth>1) {
+ H5B2_internal_t *left_internal; /* Pointer to left internal node */
+ H5B2_internal_t *middle_internal; /* Pointer to middle internal node */
+ H5B2_internal_t *right_internal; /* Pointer to right internal node */
+
+ /* Setup information for unlocking child nodes */
+ child_class = H5AC_BT2_INT;
+ left_addr = internal->node_ptrs[idx].addr;
+ right_addr = internal->node_ptrs[idx+2].addr;
+
+ /* Lock left & right B-tree child nodes */
+ if (NULL == (left_internal = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
+ if (NULL == (right_internal = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+2].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
+
+ /* Create new empty "middle" internal node */
+ internal->node_ptrs[idx+1].all_nrec=internal->node_ptrs[idx+1].node_nrec=0;
+ if(H5B2_create_internal(f, dxpl_id, internal->shared, &(internal->node_ptrs[idx+1]))<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new internal node")
+
+ /* Setup information for unlocking middle child node */
+ middle_addr = internal->node_ptrs[idx+1].addr;
+
+ /* Lock "middle" internal node */
+ if (NULL == (middle_internal = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
+
+ /* More setup for accessing child node information */
+ left_child = left_internal;
+ middle_child = middle_internal;
+ right_child = right_internal;
+ left_nrec = &(left_internal->nrec);
+ middle_nrec = &(middle_internal->nrec);
+ right_nrec = &(right_internal->nrec);
+ left_native = left_internal->int_native;
+ middle_native = middle_internal->int_native;
+ right_native = right_internal->int_native;
+ left_node_ptrs = left_internal->node_ptrs;
+ middle_node_ptrs = middle_internal->node_ptrs;
+ right_node_ptrs = right_internal->node_ptrs;
+ } /* end if */
+ else {
+ H5B2_leaf_t *left_leaf; /* Pointer to left leaf node */
+ H5B2_leaf_t *middle_leaf; /* Pointer to middle leaf node */
+ H5B2_leaf_t *right_leaf; /* Pointer to right leaf node */
+
+ /* Setup information for unlocking child nodes */
+ child_class = H5AC_BT2_LEAF;
+ left_addr = internal->node_ptrs[idx].addr;
+ right_addr = internal->node_ptrs[idx+2].addr;
+
+ /* Lock left & right B-tree child nodes */
+ if (NULL == (left_leaf = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
+ if (NULL == (right_leaf = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+2].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
+
+ /* Create new empty "middle" leaf node */
+ internal->node_ptrs[idx+1].all_nrec=internal->node_ptrs[idx+1].node_nrec=0;
+ if(H5B2_create_leaf(f, dxpl_id, internal->shared, &(internal->node_ptrs[idx+1]))<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new leaf node")
+
+ /* Setup information for unlocking middle child node */
+ middle_addr = internal->node_ptrs[idx+1].addr;
+
+ /* Lock "middle" leaf node */
+ if (NULL == (middle_leaf = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
+
+ /* More setup for accessing child node information */
+ left_child = left_leaf;
+ middle_child = middle_leaf;
+ right_child = right_leaf;
+ left_nrec = &(left_leaf->nrec);
+ middle_nrec = &(middle_leaf->nrec);
+ right_nrec = &(right_leaf->nrec);
+ left_native = left_leaf->leaf_native;
+ middle_native = middle_leaf->leaf_native;
+ right_native = right_leaf->leaf_native;
+ } /* end else */
+
+ /* Redistribute records */
+ {
+ /* Compute new # of records in each node */
+ unsigned total_nrec = *left_nrec + *right_nrec + 1;
+ unsigned new_middle_nrec = (total_nrec-2)/3;
+ unsigned new_left_nrec = ((total_nrec-2)-new_middle_nrec)/2;
+ unsigned new_right_nrec = (total_nrec-2)-(new_left_nrec+new_middle_nrec);
+
+ /* Fill new middle node */
+ {
+ unsigned curr_middle_idx=0;
+
+ /* Copy record(s) from left node to proper location */
+ if(new_left_nrec<(*left_nrec-1)) {
+ curr_middle_idx=*left_nrec-(new_left_nrec+1);
+ HDmemcpy(H5B2_NAT_NREC(middle_native,shared,0),H5B2_NAT_NREC(left_native,shared,(new_left_nrec+1)),shared->type->nrec_size*curr_middle_idx);
+ } /* end if */
+
+ /* Copy record from parent node to proper location */
+ HDmemcpy(H5B2_NAT_NREC(middle_native,shared,curr_middle_idx),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size);
+ curr_middle_idx++;
+
+ /* Copy record(s) from right node to proper location */
+ if(new_right_nrec<(*right_nrec-1))
+ HDmemcpy(H5B2_NAT_NREC(middle_native,shared,curr_middle_idx),H5B2_NAT_NREC(right_native,shared,0),shared->type->nrec_size*(*right_nrec-(new_right_nrec+1)));
+
+ /* Copy node pointers from left and right nodes into middle node */
+ if(depth>1) {
+ hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */
+ unsigned move_nptrs; /* Number of node pointers to move */
+ unsigned u; /* Local index variable */
+
+ /* Start tracking the total number of records in middle node */
+ middle_moved_nrec = new_middle_nrec;
+
+ /* Copy node pointers from left node */
+ move_nptrs = (*left_nrec-new_left_nrec);
+ HDmemcpy(&(middle_node_ptrs[0]),&(left_node_ptrs[new_left_nrec+1]),sizeof(H5B2_node_ptr_t)*move_nptrs);
+
+ /* Count the number of records being moved from the left node */
+ for(u=0, moved_nrec=0; u<move_nptrs; u++)
+ moved_nrec += middle_node_ptrs[u].all_nrec;
+ left_moved_nrec -= (moved_nrec+(*left_nrec-new_left_nrec));
+ middle_moved_nrec += moved_nrec;
+
+ /* Copy node pointers from right node */
+ move_nptrs = (*right_nrec-new_right_nrec);
+ HDmemcpy(&(middle_node_ptrs[(*left_nrec-new_left_nrec)]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*move_nptrs);
+
+ /* Count the number of records being moved from the right node */
+ for(u=0, moved_nrec=0; u<move_nptrs; u++)
+ moved_nrec += right_node_ptrs[u].all_nrec;
+ right_moved_nrec -= (moved_nrec+(*right_nrec-new_right_nrec));
+ middle_moved_nrec += moved_nrec;
+
+ /* Slide node pointers in right node down */
+ HDmemmove(&(right_node_ptrs[0]),&(right_node_ptrs[move_nptrs]),sizeof(H5B2_node_ptr_t)*(new_right_nrec+1));
+ } /* end if */
+
+ } /* end block */
+
+ /* Update # of records in middle node */
+ *middle_nrec=new_middle_nrec;
+
+ /* Promote records to parent node from left & right nodes */
+ HDmemcpy(H5B2_INT_NREC(internal,shared,idx),H5B2_NAT_NREC(left_native,shared,new_left_nrec),shared->type->nrec_size);
+ HDmemcpy(H5B2_INT_NREC(internal,shared,idx+1),H5B2_NAT_NREC(right_native,shared,(*right_nrec-(new_right_nrec+1))),shared->type->nrec_size);
+
+ /* Update # of records in left node */
+ *left_nrec = new_left_nrec;
+
+ /* Slide records in right node to proper position */
+ HDmemmove(H5B2_NAT_NREC(right_native,shared,0),H5B2_NAT_NREC(right_native,shared,(*right_nrec-new_right_nrec)),shared->type->nrec_size*new_right_nrec);
+
+ /* Update # of records in right node */
+ *right_nrec = new_right_nrec;
+ } /* end block */
+
+ /* Update # of records in child nodes */
+ internal->node_ptrs[idx].node_nrec = *left_nrec;
+ internal->node_ptrs[idx+1].node_nrec = *middle_nrec;
+ internal->node_ptrs[idx+2].node_nrec = *right_nrec;
+
+ /* Update total # of records in child B-trees */
+ if(depth>1) {
+ internal->node_ptrs[idx].all_nrec += left_moved_nrec;
+ internal->node_ptrs[idx+1].all_nrec = middle_moved_nrec;
+ internal->node_ptrs[idx+2].all_nrec += right_moved_nrec;
+ } /* end if */
+ else {
+ internal->node_ptrs[idx].all_nrec = internal->node_ptrs[idx].node_nrec;
+ internal->node_ptrs[idx+1].all_nrec = internal->node_ptrs[idx+1].node_nrec;
+ internal->node_ptrs[idx+2].all_nrec = internal->node_ptrs[idx+2].node_nrec;
+ } /* end else */
+
+
+ /* Update # of records in parent node */
+ internal->nrec++;
+
+ /* Mark parent as dirty */
+ *internal_flags_ptr |= H5AC__DIRTIED_FLAG;
+
+ /* Update grandparent info */
+ curr_node_ptr->node_nrec++;
+
+ /* Mark grandparent as dirty */
+ *parent_cache_info_flags_ptr |= H5AC__DIRTIED_FLAG;
+
+#ifdef H5B2_DEBUG
+ H5B2_assert_internal((hsize_t)0,shared,internal);
+ if(depth>1) {
+ H5B2_assert_internal2(internal->node_ptrs[idx].all_nrec,shared,left_child,middle_child);
+ H5B2_assert_internal2(internal->node_ptrs[idx+1].all_nrec,shared,middle_child,left_child);
+ H5B2_assert_internal2(internal->node_ptrs[idx+1].all_nrec,shared,middle_child,right_child);
+ H5B2_assert_internal2(internal->node_ptrs[idx+2].all_nrec,shared,right_child,middle_child);
+ } /* end if */
+ else {
+ H5B2_assert_leaf2(shared,left_child,middle_child);
+ H5B2_assert_leaf2(shared,middle_child,right_child);
+ H5B2_assert_leaf(shared,right_child);
+ } /* end else */
+#endif /* H5B2_DEBUG */
+
+ /* Unlock child nodes (marked as dirty) */
+ if (H5AC_unprotect(f, dxpl_id, child_class, left_addr, left_child, H5AC__DIRTIED_FLAG) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
+ if (H5AC_unprotect(f, dxpl_id, child_class, middle_addr, middle_child, H5AC__DIRTIED_FLAG) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
+ if (H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5B2_split2 */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_redistribute3
+ *
+ * Purpose: Redistribute records between three nodes
+ *
+ * Return: Success: Non-negative
+ *
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 9 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B2_redistribute3(H5F_t *f, hid_t dxpl_id, unsigned depth,
+ H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx)
+{
+ const H5AC_class_t *child_class; /* Pointer to child node's class info */
+ haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */
+ haddr_t middle_addr; /* Address of middle child node */
+ void *left_child, *right_child; /* Pointers to child nodes */
+ void *middle_child; /* Pointers to middle child node */
+ unsigned *left_nrec, *right_nrec; /* Pointers to child # of records */
+ unsigned *middle_nrec; /* Pointers to middle child # of records */
+ uint8_t *left_native, *right_native; /* Pointers to childs' native records */
+ uint8_t *middle_native; /* Pointers to middle child's native records */
+ H5B2_shared_t *shared; /* B-tree's shared info */
+ H5B2_node_ptr_t *left_node_ptrs=NULL, *right_node_ptrs=NULL;/* Pointers to childs' node pointer info */
+ H5B2_node_ptr_t *middle_node_ptrs=NULL;/* Pointers to childs' node pointer info */
+ hssize_t left_moved_nrec=0, right_moved_nrec=0; /* Number of records moved, for internal split */
+ hssize_t middle_moved_nrec=0; /* Number of records moved, for internal split */
+ herr_t ret_value=SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5B2_redistribute3)
+
+ HDassert(f);
+ HDassert(internal);
+ HDassert(internal_flags_ptr);
+
+ /* Get the pointer to the shared B-tree info */
+ shared=H5RC_GET_OBJ(internal->shared);
+ HDassert(shared);
+
+ /* Check for the kind of B-tree node to redistribute */
+ if(depth>1) {
+ H5B2_internal_t *left_internal; /* Pointer to left internal node */
+ H5B2_internal_t *middle_internal; /* Pointer to middle internal node */
+ H5B2_internal_t *right_internal; /* Pointer to right internal node */
+
+ /* Setup information for unlocking child nodes */
+ child_class = H5AC_BT2_INT;
+ left_addr = internal->node_ptrs[idx-1].addr;
+ middle_addr = internal->node_ptrs[idx].addr;
+ right_addr = internal->node_ptrs[idx+1].addr;
+
+ /* Lock B-tree child nodes */
+ if (NULL == (left_internal = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx-1].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
+ if (NULL == (middle_internal = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
+ if (NULL == (right_internal = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
+
+ /* More setup for child nodes */
+ left_child = left_internal;
+ middle_child = middle_internal;
+ right_child = right_internal;
+ left_nrec = &(left_internal->nrec);
+ middle_nrec = &(middle_internal->nrec);
+ right_nrec = &(right_internal->nrec);
+ left_native = left_internal->int_native;
+ middle_native = middle_internal->int_native;
+ right_native = right_internal->int_native;
+ left_node_ptrs = left_internal->node_ptrs;
+ middle_node_ptrs = middle_internal->node_ptrs;
+ right_node_ptrs = right_internal->node_ptrs;
+ } /* end if */
+ else {
+ H5B2_leaf_t *left_leaf; /* Pointer to left leaf node */
+ H5B2_leaf_t *middle_leaf; /* Pointer to middle leaf node */
+ H5B2_leaf_t *right_leaf; /* Pointer to right leaf node */
+
+ /* Setup information for unlocking child nodes */
+ child_class = H5AC_BT2_LEAF;
+ left_addr = internal->node_ptrs[idx-1].addr;
+ middle_addr = internal->node_ptrs[idx].addr;
+ right_addr = internal->node_ptrs[idx+1].addr;
+
+ /* Lock B-tree child nodes */
+ if (NULL == (left_leaf = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx-1].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
+ if (NULL == (middle_leaf = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
+ if (NULL == (right_leaf = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
+
+ /* More setup for child nodes */
+ left_child = left_leaf;
+ middle_child = middle_leaf;
+ right_child = right_leaf;
+ left_nrec = &(left_leaf->nrec);
+ middle_nrec = &(middle_leaf->nrec);
+ right_nrec = &(right_leaf->nrec);
+ left_native = left_leaf->leaf_native;
+ middle_native = middle_leaf->leaf_native;
+ right_native = right_leaf->leaf_native;
+ } /* end else */
+
+ /* Redistribute records */
+ {
+ /* Compute new # of records in each node */
+ unsigned total_nrec = *left_nrec + *middle_nrec + *right_nrec + 2;
+ unsigned new_middle_nrec = (total_nrec-2)/3;
+ unsigned new_left_nrec = ((total_nrec-2)-new_middle_nrec)/2;
+ unsigned new_right_nrec = (total_nrec-2)-(new_left_nrec+new_middle_nrec);
+ unsigned curr_middle_nrec = *middle_nrec;
+
+ /* Move records into left node */
+ if(new_left_nrec>*left_nrec) {
+ unsigned moved_middle_nrec=0; /* Number of records moved into left node */
+
+ /* Move left parent record down to left node */
+ HDmemcpy(H5B2_NAT_NREC(left_native,shared,*left_nrec),H5B2_INT_NREC(internal,shared,idx-1),shared->type->nrec_size);
+
+ /* Move records from middle node into left node */
+ if((new_left_nrec-1)>*left_nrec) {
+ moved_middle_nrec = new_left_nrec-(*left_nrec+1);
+ HDmemcpy(H5B2_NAT_NREC(left_native,shared,*left_nrec+1),H5B2_NAT_NREC(middle_native,shared,0),shared->type->nrec_size*moved_middle_nrec);
+ } /* end if */
+
+ /* Move record from middle node up to parent node */
+ HDmemcpy(H5B2_INT_NREC(internal,shared,idx-1),H5B2_NAT_NREC(middle_native,shared,moved_middle_nrec),shared->type->nrec_size);
+ moved_middle_nrec++;
+
+ /* Slide records in middle node down */
+ HDmemmove(H5B2_NAT_NREC(middle_native,shared,0),H5B2_NAT_NREC(middle_native,shared,moved_middle_nrec),shared->type->nrec_size*(*middle_nrec-moved_middle_nrec));
+
+ /* Move node pointers also if this is an internal node */
+ if(depth>1) {
+ hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */
+ unsigned move_nptrs; /* Number of node pointers to move */
+ unsigned u; /* Local index variable */
+
+ /* Move middle node pointers into left node */
+ move_nptrs = new_left_nrec - *left_nrec;
+ HDmemcpy(&(left_node_ptrs[*left_nrec+1]),&(middle_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*move_nptrs);
+
+ /* Count the number of records being moved into the left node */
+ for(u=0, moved_nrec=0; u<move_nptrs; u++)
+ moved_nrec += middle_node_ptrs[u].all_nrec;
+ left_moved_nrec = moved_nrec+move_nptrs;
+ middle_moved_nrec -= moved_nrec+move_nptrs;
+
+ /* Slide the node pointers in middle node down */
+ HDmemmove(&(middle_node_ptrs[0]),&(middle_node_ptrs[move_nptrs]),sizeof(H5B2_node_ptr_t)*((*middle_nrec-move_nptrs)+1));
+ } /* end if */
+
+ /* Update the current number of records in middle node */
+ curr_middle_nrec -= moved_middle_nrec;
+ } /* end if */
+
+ /* Move records into right node */
+ if(new_right_nrec>*right_nrec) {
+ unsigned right_nrec_move = new_right_nrec-*right_nrec; /* Number of records to move out of right node */
+
+ /* Slide records in right node up */
+ HDmemmove(H5B2_NAT_NREC(right_native,shared,right_nrec_move),H5B2_NAT_NREC(right_native,shared,0),shared->type->nrec_size*(*right_nrec));
+
+ /* Move right parent record down to right node */
+ HDmemcpy(H5B2_NAT_NREC(right_native,shared,right_nrec_move-1),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size);
+
+ /* Move records from middle node into right node */
+ if(right_nrec_move>1)
+ HDmemcpy(H5B2_NAT_NREC(right_native,shared,0),H5B2_NAT_NREC(middle_native,shared,((curr_middle_nrec-right_nrec_move)+1)),shared->type->nrec_size*(right_nrec_move-1));
+
+ /* Move record from middle node up to parent node */
+ HDmemcpy(H5B2_INT_NREC(internal,shared,idx),H5B2_NAT_NREC(middle_native,shared,(curr_middle_nrec-right_nrec_move)),shared->type->nrec_size);
+
+ /* Move node pointers also if this is an internal node */
+ if(depth>1) {
+ hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */
+ unsigned u; /* Local index variable */
+
+ /* Slide the node pointers in right node up */
+ HDmemmove(&(right_node_ptrs[right_nrec_move]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*(*right_nrec+1));
+
+ /* Move middle node pointers into right node */
+ HDmemcpy(&(right_node_ptrs[0]),&(middle_node_ptrs[(curr_middle_nrec-right_nrec_move)+1]),sizeof(H5B2_node_ptr_t)*right_nrec_move);
+
+ /* Count the number of records being moved into the right node */
+ for(u=0, moved_nrec=0; u<right_nrec_move; u++)
+ moved_nrec += right_node_ptrs[u].all_nrec;
+ right_moved_nrec = moved_nrec+right_nrec_move;
+ middle_moved_nrec -= moved_nrec+right_nrec_move;
+ } /* end if */
+
+ /* Update the current number of records in middle node */
+ curr_middle_nrec -= right_nrec_move;
+ } /* end if */
+
+ /* Move records out of left node */
+ if(new_left_nrec<*left_nrec) {
+ unsigned left_nrec_move = *left_nrec-new_left_nrec; /* Number of records to move out of left node */
+
+ /* Slide middle records up */
+ HDmemmove(H5B2_NAT_NREC(middle_native,shared,left_nrec_move),H5B2_NAT_NREC(middle_native,shared,0),shared->type->nrec_size*curr_middle_nrec);
+
+ /* Move left parent record down to middle node */
+ HDmemcpy(H5B2_NAT_NREC(middle_native,shared,left_nrec_move-1),H5B2_INT_NREC(internal,shared,idx-1),shared->type->nrec_size);
+
+ /* Move left records to middle node */
+ if(left_nrec_move>1)
+ HDmemmove(H5B2_NAT_NREC(middle_native,shared,0),H5B2_NAT_NREC(left_native,shared,new_left_nrec+1),shared->type->nrec_size*(left_nrec_move-1));
+
+ /* Move left parent record up from left node */
+ HDmemcpy(H5B2_INT_NREC(internal,shared,idx-1),H5B2_NAT_NREC(left_native,shared,new_left_nrec),shared->type->nrec_size);
+
+ /* Move node pointers also if this is an internal node */
+ if(depth>1) {
+ hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */
+ unsigned u; /* Local index variable */
+
+ /* Slide the node pointers in middle node up */
+ HDmemmove(&(middle_node_ptrs[left_nrec_move]),&(middle_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*(curr_middle_nrec+1));
+
+ /* Move left node pointers into middle node */
+ HDmemcpy(&(middle_node_ptrs[0]),&(left_node_ptrs[new_left_nrec+1]),sizeof(H5B2_node_ptr_t)*left_nrec_move);
+
+ /* Count the number of records being moved into the left node */
+ for(u=0, moved_nrec=0; u<left_nrec_move; u++)
+ moved_nrec += middle_node_ptrs[u].all_nrec;
+ left_moved_nrec -= moved_nrec+left_nrec_move;
+ middle_moved_nrec += moved_nrec+left_nrec_move;
+ } /* end if */
+
+ /* Update the current number of records in middle node */
+ curr_middle_nrec += left_nrec_move;
+ } /* end if */
+
+ /* Move records out of right node */
+ if(new_right_nrec<*right_nrec) {
+ unsigned right_nrec_move = *right_nrec-new_right_nrec; /* Number of records to move out of right node */
+
+ /* Move right parent record down to middle node */
+ HDmemcpy(H5B2_NAT_NREC(middle_native,shared,curr_middle_nrec),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size);
+
+ /* Move right records to middle node */
+ HDmemmove(H5B2_NAT_NREC(middle_native,shared,(curr_middle_nrec+1)),H5B2_NAT_NREC(right_native,shared,0),shared->type->nrec_size*(right_nrec_move-1));
+
+ /* Move right parent record up from right node */
+ HDmemcpy(H5B2_INT_NREC(internal,shared,idx),H5B2_NAT_NREC(right_native,shared,right_nrec_move-1),shared->type->nrec_size);
+
+ /* Slide right records down */
+ HDmemmove(H5B2_NAT_NREC(right_native,shared,0),H5B2_NAT_NREC(right_native,shared,right_nrec_move),shared->type->nrec_size*new_right_nrec);
+
+ /* Move node pointers also if this is an internal node */
+ if(depth>1) {
+ hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */
+ unsigned u; /* Local index variable */
+
+ /* Move right node pointers into middle node */
+ HDmemcpy(&(middle_node_ptrs[curr_middle_nrec+1]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*right_nrec_move);
+
+ /* Count the number of records being moved into the right node */
+ for(u=0, moved_nrec=0; u<right_nrec_move; u++)
+ moved_nrec += right_node_ptrs[u].all_nrec;
+ right_moved_nrec -= moved_nrec+right_nrec_move;
+ middle_moved_nrec += moved_nrec+right_nrec_move;
+
+ /* Slide the node pointers in right node down */
+ HDmemmove(&(right_node_ptrs[0]),&(right_node_ptrs[right_nrec_move]),sizeof(H5B2_node_ptr_t)*(new_right_nrec+1));
+ } /* end if */
+ } /* end if */
+
+ /* Update # of records in nodes */
+ *left_nrec = new_left_nrec;
+ *middle_nrec = new_middle_nrec;
+ *right_nrec = new_right_nrec;
+ } /* end block */
+
+ /* Update # of records in child nodes */
+ internal->node_ptrs[idx-1].node_nrec = *left_nrec;
+ internal->node_ptrs[idx].node_nrec = *middle_nrec;
+ internal->node_ptrs[idx+1].node_nrec = *right_nrec;
+
+ /* Update total # of records in child B-trees */
+ if(depth>1) {
+ internal->node_ptrs[idx-1].all_nrec += left_moved_nrec;
+ internal->node_ptrs[idx].all_nrec += middle_moved_nrec;
+ internal->node_ptrs[idx+1].all_nrec += right_moved_nrec;
+ } /* end if */
+ else {
+ internal->node_ptrs[idx-1].all_nrec = internal->node_ptrs[idx-1].node_nrec;
+ internal->node_ptrs[idx].all_nrec = internal->node_ptrs[idx].node_nrec;
+ internal->node_ptrs[idx+1].all_nrec = internal->node_ptrs[idx+1].node_nrec;
+ } /* end else */
+
+ /* Mark parent as dirty */
+ *internal_flags_ptr |= H5AC__DIRTIED_FLAG;
+
+#ifdef QAK
+{
+ unsigned u;
+
+ HDfprintf(stderr,"%s: Internal records:\n",FUNC);
+ for(u=0; u<internal->nrec; u++) {
+ HDfprintf(stderr,"%s: u=%u\n",FUNC,u);
+ (shared->type->debug)(stderr,f,dxpl_id,3,4,H5B2_INT_NREC(internal,shared,u),NULL);
+ } /* end for */
+
+ HDfprintf(stderr,"%s: Left Child records:\n",FUNC);
+ for(u=0; u<*left_nrec; u++) {
+ HDfprintf(stderr,"%s: u=%u\n",FUNC,u);
+ (shared->type->debug)(stderr,f,dxpl_id,3,4,H5B2_NAT_NREC(left_native,shared,u),NULL);
+ } /* end for */
+
+ HDfprintf(stderr,"%s: Middle Child records:\n",FUNC);
+ for(u=0; u<*middle_nrec; u++) {
+ HDfprintf(stderr,"%s: u=%u\n",FUNC,u);
+ (shared->type->debug)(stderr,f,dxpl_id,3,4,H5B2_NAT_NREC(middle_native,shared,u),NULL);
+ } /* end for */
+
+ HDfprintf(stderr,"%s: Right Child records:\n",FUNC);
+ for(u=0; u<*right_nrec; u++) {
+ HDfprintf(stderr,"%s: u=%u\n",FUNC,u);
+ (shared->type->debug)(stderr,f,dxpl_id,3,4,H5B2_NAT_NREC(right_native,shared,u),NULL);
+ } /* end for */
+
+ for(u=0; u<internal->nrec+1; u++)
+ HDfprintf(stderr,"%s: internal->node_ptrs[%u]=(%Hu/%u/%a)\n",FUNC,u,internal->node_ptrs[u].all_nrec,internal->node_ptrs[u].node_nrec,internal->node_ptrs[u].addr);
+ if(depth>1) {
+ for(u=0; u<*left_nrec+1; u++)
+ HDfprintf(stderr,"%s: left_node_ptr[%u]=(%Hu/%u/%a)\n",FUNC,u,left_node_ptrs[u].all_nrec,left_node_ptrs[u].node_nrec,left_node_ptrs[u].addr);
+ for(u=0; u<*middle_nrec+1; u++)
+ HDfprintf(stderr,"%s: middle_node_ptr[%u]=(%Hu/%u/%a)\n",FUNC,u,middle_node_ptrs[u].all_nrec,middle_node_ptrs[u].node_nrec,middle_node_ptrs[u].addr);
+ for(u=0; u<*right_nrec+1; u++)
+ HDfprintf(stderr,"%s: right_node_ptr[%u]=(%Hu/%u/%a)\n",FUNC,u,right_node_ptrs[u].all_nrec,right_node_ptrs[u].node_nrec,right_node_ptrs[u].addr);
+ } /* end if */
+}
+#endif /* QAK */
+#ifdef H5B2_DEBUG
+ H5B2_assert_internal((hsize_t)0,shared,internal);
+ if(depth>1) {
+ H5B2_assert_internal2(internal->node_ptrs[idx-1].all_nrec,shared,left_child,middle_child);
+ H5B2_assert_internal2(internal->node_ptrs[idx].all_nrec,shared,middle_child,left_child);
+ H5B2_assert_internal2(internal->node_ptrs[idx].all_nrec,shared,middle_child,right_child);
+ H5B2_assert_internal2(internal->node_ptrs[idx+1].all_nrec,shared,right_child,middle_child);
+ } /* end if */
+ else {
+ H5B2_assert_leaf2(shared,left_child,middle_child);
+ H5B2_assert_leaf2(shared,middle_child,right_child);
+ H5B2_assert_leaf(shared,right_child);
+ } /* end else */
+#endif /* H5B2_DEBUG */
+
+ /* Unlock child nodes (marked as dirty) */
+ if (H5AC_unprotect(f, dxpl_id, child_class, left_addr, left_child, H5AC__DIRTIED_FLAG) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
+ if (H5AC_unprotect(f, dxpl_id, child_class, middle_addr, middle_child, H5AC__DIRTIED_FLAG) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
+ if (H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5B2_redistribute3 */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_split3
+ *
+ * Purpose: Perform a 3->4 node split
+ *
+ * Return: Success: Non-negative
+ *
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 10 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B2_split3(H5F_t *f, hid_t dxpl_id, unsigned depth,
+ H5B2_node_ptr_t *curr_node_ptr,
+ unsigned *parent_cache_info_flags_ptr, H5B2_internal_t *internal,
+ unsigned *internal_flags_ptr, unsigned idx)
+{
+ const H5AC_class_t *child_class; /* Pointer to child node's class info */
+ haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */
+ haddr_t middle_addr; /* Address of middle child node */
+ haddr_t new_addr; /* Address of new child node */
+ void *left_child, *right_child; /* Pointers to left & right child nodes */
+ void *middle_child; /* Pointer to middle child node */
+ void *new_child; /* Pointer to new child node */
+ unsigned *left_nrec, *right_nrec; /* Pointers to left & right child # of records */
+ unsigned *middle_nrec; /* Pointer to middle child # of records */
+ unsigned *new_nrec; /* Pointer to new child # of records */
+ uint8_t *left_native, *right_native; /* Pointers to left & right children's native records */
+ uint8_t *middle_native; /* Pointer to middle child's native records */
+ uint8_t *new_native; /* Pointer to new child's native records */
+ H5B2_shared_t *shared; /* B-tree's shared info */
+ H5B2_node_ptr_t *left_node_ptrs=NULL, *right_node_ptrs=NULL;/* Pointers to childs' node pointer info */
+ H5B2_node_ptr_t *middle_node_ptrs=NULL;/* Pointers to childs' node pointer info */
+ H5B2_node_ptr_t *new_node_ptrs=NULL;/* Pointers to childs' node pointer info */
+ hssize_t left_moved_nrec=0, right_moved_nrec=0; /* Number of records moved, for internal split */
+ hssize_t middle_moved_nrec=0; /* Number of records moved, for internal split */
+ hsize_t new_moved_nrec=0; /* Number of records moved, for internal split */
+ herr_t ret_value=SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5B2_split3)
+
+ HDassert(f);
+ HDassert(internal);
+
+ /* Get the pointer to the shared B-tree info */
+ shared=H5RC_GET_OBJ(internal->shared);
+ HDassert(shared);
+
+ /* Slide records in parent node up one space, to make room for promoted record */
+ HDmemmove(H5B2_INT_NREC(internal,shared,idx+2),H5B2_INT_NREC(internal,shared,idx+1),shared->type->nrec_size*(internal->nrec-(idx+1)));
+ HDmemmove(&(internal->node_ptrs[idx+2]),&(internal->node_ptrs[idx+1]),sizeof(H5B2_node_ptr_t)*(internal->nrec-idx));
+
+ /* Check for the kind of B-tree node to split */
+ if(depth>1) {
+ H5B2_internal_t *left_internal; /* Pointer to left internal node */
+ H5B2_internal_t *right_internal; /* Pointer to right internal node */
+ H5B2_internal_t *middle_internal; /* Pointer to middle internal node */
+ H5B2_internal_t *new_internal; /* Pointer to new internal node */
+
+ /* Setup information for unlocking child nodes */
+ child_class = H5AC_BT2_INT;
+ left_addr = internal->node_ptrs[idx-1].addr;
+ middle_addr = internal->node_ptrs[idx].addr;
+ right_addr = internal->node_ptrs[idx+2].addr;
+
+ /* Lock left & right B-tree child nodes */
+ if (NULL == (left_internal = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx-1].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
+ if (NULL == (middle_internal = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
+ if (NULL == (right_internal = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+2].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
+
+ /* Create new empty internal node */
+ internal->node_ptrs[idx+1].all_nrec=internal->node_ptrs[idx+1].node_nrec=0;
+ if(H5B2_create_internal(f, dxpl_id, internal->shared, &(internal->node_ptrs[idx+1]))<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new internal node")
+
+ /* Setup information for unlocking middle child node */
+ new_addr = internal->node_ptrs[idx+1].addr;
+
+ /* Lock "new" internal node */
+ if (NULL == (new_internal = H5AC_protect(f, dxpl_id, child_class, new_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
+
+ /* More setup for accessing child node information */
+ left_child = left_internal;
+ middle_child = middle_internal;
+ new_child = new_internal;
+ right_child = right_internal;
+ left_nrec = &(left_internal->nrec);
+ middle_nrec = &(middle_internal->nrec);
+ new_nrec = &(new_internal->nrec);
+ right_nrec = &(right_internal->nrec);
+ left_native = left_internal->int_native;
+ middle_native = middle_internal->int_native;
+ new_native = new_internal->int_native;
+ right_native = right_internal->int_native;
+ left_node_ptrs = left_internal->node_ptrs;
+ middle_node_ptrs = middle_internal->node_ptrs;
+ right_node_ptrs = right_internal->node_ptrs;
+ new_node_ptrs = new_internal->node_ptrs;
+ } /* end if */
+ else {
+ H5B2_leaf_t *left_leaf; /* Pointer to left leaf node */
+ H5B2_leaf_t *right_leaf; /* Pointer to right leaf node */
+ H5B2_leaf_t *middle_leaf; /* Pointer to middle leaf node */
+ H5B2_leaf_t *new_leaf; /* Pointer to new leaf node */
+
+ /* Setup information for unlocking child nodes */
+ child_class = H5AC_BT2_LEAF;
+ left_addr = internal->node_ptrs[idx-1].addr;
+ middle_addr = internal->node_ptrs[idx].addr;
+ right_addr = internal->node_ptrs[idx+2].addr;
+
+ /* Lock left & right B-tree child nodes */
+ if (NULL == (left_leaf = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx-1].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
+ if (NULL == (middle_leaf = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
+ if (NULL == (right_leaf = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+2].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
+
+ /* Create new empty leaf node */
+ internal->node_ptrs[idx+1].all_nrec=internal->node_ptrs[idx+1].node_nrec=0;
+ if(H5B2_create_leaf(f, dxpl_id, internal->shared, &(internal->node_ptrs[idx+1]))<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new leaf node")
+
+ /* Setup information for unlocking middle child node */
+ new_addr = internal->node_ptrs[idx+1].addr;
+
+ /* Lock "new" leaf node */
+ if (NULL == (new_leaf = H5AC_protect(f, dxpl_id, child_class, new_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
+
+ /* More setup for accessing child node information */
+ left_child = left_leaf;
+ middle_child = middle_leaf;
+ new_child = new_leaf;
+ right_child = right_leaf;
+ left_nrec = &(left_leaf->nrec);
+ middle_nrec = &(middle_leaf->nrec);
+ new_nrec = &(new_leaf->nrec);
+ right_nrec = &(right_leaf->nrec);
+ left_native = left_leaf->leaf_native;
+ middle_native = middle_leaf->leaf_native;
+ new_native = new_leaf->leaf_native;
+ right_native = right_leaf->leaf_native;
+ } /* end else */
+
+ /* Redistribute records */
+ {
+ /* Compute new # of records in each node */
+ unsigned total_nrec = *left_nrec + *middle_nrec + *right_nrec + 2;
+ unsigned new_new_nrec = (total_nrec-3)/4;
+ unsigned new_middle_nrec = ((total_nrec-3)-new_new_nrec)/3;
+ unsigned new_left_nrec = ((total_nrec-3)-(new_middle_nrec+new_new_nrec))/2;
+ unsigned new_right_nrec = (total_nrec-3)-(new_left_nrec+new_middle_nrec+new_new_nrec);
+
+ /* Partially fill new node from right node */
+ {
+ unsigned right_nrec_move = *right_nrec-new_right_nrec;
+
+ /* Move right record down from parent into new node */
+ HDmemcpy(H5B2_NAT_NREC(new_native,shared,(new_new_nrec-right_nrec_move)),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size);
+
+ /* Move records from right node to new node */
+ HDmemcpy(H5B2_NAT_NREC(new_native,shared,((new_new_nrec-right_nrec_move)+1)),H5B2_NAT_NREC(right_native,shared,0),shared->type->nrec_size*(right_nrec_move-1));
+
+ /* Move record from right node up to parent node */
+ HDmemcpy(H5B2_INT_NREC(internal,shared,idx+1),H5B2_NAT_NREC(right_native,shared,(right_nrec_move-1)),shared->type->nrec_size);
+
+ /* Slide records in right node down */
+ HDmemmove(H5B2_NAT_NREC(right_native,shared,0),H5B2_NAT_NREC(right_native,shared,right_nrec_move),shared->type->nrec_size*new_right_nrec);
+
+ /* Move node pointers also if this is an internal node */
+ if(depth>1) {
+ hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */
+ unsigned u; /* Local index variable */
+
+ /* Move right node pointers into new node */
+ HDmemcpy(&(new_node_ptrs[(new_new_nrec-right_nrec_move)+1]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*right_nrec_move);
+
+ /* Count the number of records being moved into the new node */
+ for(u=0, moved_nrec=0; u<right_nrec_move; u++)
+ moved_nrec += right_node_ptrs[u].all_nrec;
+ right_moved_nrec -= (moved_nrec+right_nrec_move);
+ new_moved_nrec += (moved_nrec+right_nrec_move);
+
+ /* Slide the node pointers in right node down */
+ HDmemmove(&(right_node_ptrs[0]),&(right_node_ptrs[right_nrec_move]),sizeof(H5B2_node_ptr_t)*(new_right_nrec+1));
+ } /* end if */
+ } /* end block */
+
+ /* Finish filling new node from middle node */
+ {
+ unsigned new_nrec_move = new_new_nrec-(*right_nrec-new_right_nrec);
+
+ /* Move records from middle node to new node */
+ HDmemcpy(H5B2_NAT_NREC(new_native,shared,0),H5B2_NAT_NREC(middle_native,shared,(*middle_nrec-new_nrec_move)),shared->type->nrec_size*new_nrec_move);
+
+ /* Move record from middle node up to parent node */
+ HDmemcpy(H5B2_INT_NREC(internal,shared,idx),H5B2_NAT_NREC(middle_native,shared,((*middle_nrec-new_nrec_move)-1)),shared->type->nrec_size);
+
+ /* Slide records in middle node up */
+ HDmemmove(H5B2_NAT_NREC(middle_native,shared,(new_middle_nrec-((*middle_nrec-new_nrec_move)-1))),H5B2_NAT_NREC(middle_native,shared,0),shared->type->nrec_size*(*middle_nrec-(new_nrec_move+1)));
+
+ /* Move node pointers also if this is an internal node */
+ if(depth>1) {
+ hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */
+ unsigned u; /* Local index variable */
+
+ /* Move middle node pointers into new node */
+ HDmemcpy(&(new_node_ptrs[0]),&(middle_node_ptrs[(*middle_nrec-new_nrec_move)]),sizeof(H5B2_node_ptr_t)*(new_nrec_move+1));
+
+ /* Count the number of records being moved into the new node */
+ for(u=0, moved_nrec=0; u<new_nrec_move+1; u++)
+ moved_nrec += new_node_ptrs[u].all_nrec;
+ middle_moved_nrec -= (moved_nrec+new_nrec_move+1);
+ new_moved_nrec += (moved_nrec+new_nrec_move);
+
+ /* Slide the node pointers in middle node up */
+ HDmemmove(&(middle_node_ptrs[(new_middle_nrec-((*middle_nrec-new_nrec_move)-1))]),&(middle_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*(*middle_nrec-new_nrec_move));
+ } /* end if */
+ } /* end block */
+
+ /* Fill middle node from left node */
+ {
+ unsigned left_nrec_move = *left_nrec - new_left_nrec;
+
+ /* Move record from parent node down to middle node */
+ HDmemcpy(H5B2_NAT_NREC(middle_native,shared,(left_nrec_move-1)),H5B2_INT_NREC(internal,shared,idx-1),shared->type->nrec_size);
+
+ /* Move records from left node to middle node */
+ HDmemcpy(H5B2_NAT_NREC(middle_native,shared,0),H5B2_NAT_NREC(left_native,shared,(new_left_nrec+1)),shared->type->nrec_size*(left_nrec_move-1));
+
+ /* Move node pointers also if this is an internal node */
+ if(depth>1) {
+ hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */
+ unsigned u; /* Local index variable */
+
+ /* Move left node pointers into middle node */
+ HDmemcpy(&(middle_node_ptrs[0]),&(left_node_ptrs[new_left_nrec+1]),sizeof(H5B2_node_ptr_t)*left_nrec_move);
+
+ /* Count the number of records being moved into the middle node */
+ for(u=0, moved_nrec=0; u<left_nrec_move; u++)
+ moved_nrec += middle_node_ptrs[u].all_nrec;
+ left_moved_nrec -= (moved_nrec+left_nrec_move);
+ middle_moved_nrec += (moved_nrec+left_nrec_move);
+ } /* end if */
+ }
+
+ /* Move record from left node to parent node */
+ HDmemcpy(H5B2_INT_NREC(internal,shared,idx-1),H5B2_NAT_NREC(left_native,shared,new_left_nrec),shared->type->nrec_size);
+
+ /* Update # of records in nodes */
+ *left_nrec = new_left_nrec;
+ *middle_nrec = new_middle_nrec;
+ *new_nrec = new_new_nrec;
+ *right_nrec = new_right_nrec;
+ } /* end block */
+
+ /* Update # of records in child nodes */
+ internal->node_ptrs[idx-1].node_nrec = *left_nrec;
+ internal->node_ptrs[idx].node_nrec = *middle_nrec;
+ internal->node_ptrs[idx+1].node_nrec = *new_nrec;
+ internal->node_ptrs[idx+2].node_nrec = *right_nrec;
+
+ /* Update total # of records in child B-trees */
+ if(depth>1) {
+ internal->node_ptrs[idx-1].all_nrec += left_moved_nrec;
+ internal->node_ptrs[idx].all_nrec += middle_moved_nrec;
+ internal->node_ptrs[idx+1].all_nrec = new_moved_nrec;
+ internal->node_ptrs[idx+2].all_nrec += right_moved_nrec;
+ } /* end if */
+ else {
+ internal->node_ptrs[idx-1].all_nrec = internal->node_ptrs[idx-1].node_nrec;
+ internal->node_ptrs[idx].all_nrec = internal->node_ptrs[idx].node_nrec;
+ internal->node_ptrs[idx+1].all_nrec = internal->node_ptrs[idx+1].node_nrec;
+ internal->node_ptrs[idx+2].all_nrec = internal->node_ptrs[idx+2].node_nrec;
+ } /* end else */
+
+ /* Update # of records in parent node */
+ internal->nrec++;
+
+ /* Mark parent as dirty */
+ *internal_flags_ptr |= H5AC__DIRTIED_FLAG;
+
+ /* Update grandparent info */
+ curr_node_ptr->node_nrec++;
+
+ /* Mark grandparent as dirty */
+ *parent_cache_info_flags_ptr |= H5AC__DIRTIED_FLAG;
+
+#ifdef H5B2_DEBUG
+ H5B2_assert_internal((hsize_t)0,shared,internal);
+ if(depth>1) {
+ H5B2_assert_internal2(internal->node_ptrs[idx-1].all_nrec,shared,left_child,middle_child);
+ H5B2_assert_internal2(internal->node_ptrs[idx].all_nrec,shared,middle_child,left_child);
+ H5B2_assert_internal2(internal->node_ptrs[idx].all_nrec,shared,middle_child,new_child);
+ H5B2_assert_internal2(internal->node_ptrs[idx+1].all_nrec,shared,new_child,middle_child);
+ H5B2_assert_internal2(internal->node_ptrs[idx+1].all_nrec,shared,new_child,right_child);
+ H5B2_assert_internal2(internal->node_ptrs[idx+2].all_nrec,shared,right_child,new_child);
+ } /* end if */
+ else {
+ H5B2_assert_leaf2(shared,left_child,middle_child);
+ H5B2_assert_leaf2(shared,middle_child,new_child);
+ H5B2_assert_leaf2(shared,new_child,right_child);
+ H5B2_assert_leaf(shared,right_child);
+ } /* end else */
+#endif /* H5B2_DEBUG */
+
+ /* Unlock child nodes (mark as dirty) */
+ if (H5AC_unprotect(f, dxpl_id, child_class, left_addr, left_child, H5AC__DIRTIED_FLAG) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
+ if (H5AC_unprotect(f, dxpl_id, child_class, middle_addr, middle_child, H5AC__DIRTIED_FLAG) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
+ if (H5AC_unprotect(f, dxpl_id, child_class, new_addr, new_child, H5AC__DIRTIED_FLAG) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
+ if (H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5B2_split3 */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_merge2
+ *
+ * Purpose: Perform a 2->1 node merge
+ *
+ * Return: Success: Non-negative
+ *
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Mar 4 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B2_merge2(H5F_t *f, hid_t dxpl_id, unsigned depth,
+ H5B2_node_ptr_t *curr_node_ptr, unsigned *parent_cache_info_flags_ptr,
+ H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx)
+{
+ const H5AC_class_t *child_class; /* Pointer to child node's class info */
+ haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */
+ void *left_child, *right_child; /* Pointers to left & right child nodes */
+ unsigned *left_nrec, *right_nrec; /* Pointers to left & right child # of records */
+ uint8_t *left_native, *right_native; /* Pointers to left & right children's native records */
+ H5B2_node_ptr_t *left_node_ptrs=NULL, *right_node_ptrs=NULL;/* Pointers to childs' node pointer info */
+ H5B2_shared_t *shared; /* B-tree's shared info */
+ herr_t ret_value=SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5B2_merge2)
+
+ HDassert(f);
+ HDassert(curr_node_ptr);
+ HDassert(parent_cache_info_flags_ptr);
+ HDassert(internal);
+ HDassert(internal_flags_ptr);
+
+ /* Get the pointer to the shared B-tree info */
+ shared=H5RC_GET_OBJ(internal->shared);
+ HDassert(shared);
+
+ /* Check for the kind of B-tree node to split */
+ if(depth>1) {
+ H5B2_internal_t *left_internal; /* Pointer to left internal node */
+ H5B2_internal_t *right_internal; /* Pointer to right internal node */
+
+ /* Setup information for unlocking child nodes */
+ child_class = H5AC_BT2_INT;
+ left_addr = internal->node_ptrs[idx].addr;
+ right_addr = internal->node_ptrs[idx+1].addr;
+
+ /* Lock left & right B-tree child nodes */
+ if (NULL == (left_internal = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
+ if (NULL == (right_internal = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
+
+ /* More setup for accessing child node information */
+ left_child = left_internal;
+ right_child = right_internal;
+ left_nrec = &(left_internal->nrec);
+ right_nrec = &(right_internal->nrec);
+ left_native = left_internal->int_native;
+ right_native = right_internal->int_native;
+ left_node_ptrs = left_internal->node_ptrs;
+ right_node_ptrs = right_internal->node_ptrs;
+ } /* end if */
+ else {
+ H5B2_leaf_t *left_leaf; /* Pointer to left leaf node */
+ H5B2_leaf_t *right_leaf; /* Pointer to right leaf node */
+
+ /* Setup information for unlocking child nodes */
+ child_class = H5AC_BT2_LEAF;
+ left_addr = internal->node_ptrs[idx].addr;
+ right_addr = internal->node_ptrs[idx+1].addr;
+
+ /* Lock left & right B-tree child nodes */
+ if (NULL == (left_leaf = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
+ if (NULL == (right_leaf = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
+
+ /* More setup for accessing child node information */
+ left_child = left_leaf;
+ right_child = right_leaf;
+ left_nrec = &(left_leaf->nrec);
+ right_nrec = &(right_leaf->nrec);
+ left_native = left_leaf->leaf_native;
+ right_native = right_leaf->leaf_native;
+ } /* end else */
+
+ /* Redistribute records into left node */
+ {
+ /* Copy record from parent node to proper location */
+ HDmemcpy(H5B2_NAT_NREC(left_native,shared,*left_nrec),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size);
+
+ /* Copy records from right node to left node */
+ HDmemcpy(H5B2_NAT_NREC(left_native,shared,*left_nrec+1),H5B2_NAT_NREC(right_native,shared,0),shared->type->nrec_size*(*right_nrec));
+
+ /* Copy node pointers from right node into left node */
+ if(depth>1)
+ HDmemcpy(&(left_node_ptrs[*left_nrec+1]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*(*right_nrec+1));
+
+ /* Update # of records in left node */
+ *left_nrec += *right_nrec + 1;
+ } /* end block */
+
+ /* Update # of records in child nodes */
+ internal->node_ptrs[idx].node_nrec = *left_nrec;
+
+ /* Update total # of records in child B-trees */
+ internal->node_ptrs[idx].all_nrec += internal->node_ptrs[idx+1].all_nrec + 1;
+
+ /* Slide records in parent node down, to eliminate demoted record */
+ if((idx+1) < internal->nrec) {
+ HDmemmove(H5B2_INT_NREC(internal,shared,idx),H5B2_INT_NREC(internal,shared,idx+1),shared->type->nrec_size*(internal->nrec-(idx+1)));
+ HDmemmove(&(internal->node_ptrs[idx+1]),&(internal->node_ptrs[idx+2]),sizeof(H5B2_node_ptr_t)*(internal->nrec-(idx+1)));
+ } /* end if */
+
+ /* Update # of records in parent node */
+ internal->nrec--;
+
+ /* Mark parent as dirty */
+ *internal_flags_ptr |= H5AC__DIRTIED_FLAG;
+
+ /* Update grandparent info */
+ curr_node_ptr->node_nrec--;
+
+ /* Mark grandparent as dirty */
+ *parent_cache_info_flags_ptr |= H5AC__DIRTIED_FLAG;
+
+#ifdef H5B2_DEBUG
+ H5B2_assert_internal((hsize_t)0,shared,internal);
+ if(depth>1) {
+ H5B2_assert_internal(internal->node_ptrs[idx].all_nrec,shared,left_child);
+ } /* end if */
+ else {
+ H5B2_assert_leaf(shared,left_child);
+ } /* end else */
+#endif /* H5B2_DEBUG */
+
+ /* Unlock left node (marked as dirty) */
+ if (H5AC_unprotect(f, dxpl_id, child_class, left_addr, left_child, H5AC__DIRTIED_FLAG) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
+
+ /* Delete right node & remove from cache (marked as dirty) */
+ if (H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, right_addr, (hsize_t)shared->node_size)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node")
+ if (H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5B2_merge2 */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_merge3
+ *
+ * Purpose: Perform a 3->2 node merge
+ *
+ * Return: Success: Non-negative
+ *
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Mar 4 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B2_merge3(H5F_t *f, hid_t dxpl_id, unsigned depth,
+ H5B2_node_ptr_t *curr_node_ptr, unsigned *parent_cache_info_flags_ptr,
+ H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx)
+{
+ const H5AC_class_t *child_class; /* Pointer to child node's class info */
+ haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */
+ haddr_t middle_addr; /* Address of middle child node */
+ void *left_child, *right_child; /* Pointers to left & right child nodes */
+ void *middle_child; /* Pointer to middle child node */
+ unsigned *left_nrec, *right_nrec; /* Pointers to left & right child # of records */
+ unsigned *middle_nrec; /* Pointer to middle child # of records */
+ uint8_t *left_native, *right_native; /* Pointers to left & right children's native records */
+ uint8_t *middle_native; /* Pointer to middle child's native records */
+ H5B2_node_ptr_t *left_node_ptrs=NULL, *right_node_ptrs=NULL;/* Pointers to childs' node pointer info */
+ H5B2_node_ptr_t *middle_node_ptrs=NULL;/* Pointer to child's node pointer info */
+ H5B2_shared_t *shared; /* B-tree's shared info */
+ hsize_t middle_moved_nrec; /* Number of records moved, for internal split */
+ herr_t ret_value=SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5B2_merge3)
+
+ HDassert(f);
+ HDassert(curr_node_ptr);
+ HDassert(parent_cache_info_flags_ptr);
+ HDassert(internal);
+ HDassert(internal_flags_ptr);
+
+ /* Get the pointer to the shared B-tree info */
+ shared=H5RC_GET_OBJ(internal->shared);
+ HDassert(shared);
+
+ /* Check for the kind of B-tree node to split */
+ if(depth>1) {
+ H5B2_internal_t *left_internal; /* Pointer to left internal node */
+ H5B2_internal_t *middle_internal; /* Pointer to middle internal node */
+ H5B2_internal_t *right_internal; /* Pointer to right internal node */
+
+ /* Setup information for unlocking child nodes */
+ child_class = H5AC_BT2_INT;
+ left_addr = internal->node_ptrs[idx-1].addr;
+ middle_addr = internal->node_ptrs[idx].addr;
+ right_addr = internal->node_ptrs[idx+1].addr;
+
+ /* Lock B-tree child nodes */
+ if (NULL == (left_internal = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx-1].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
+ if (NULL == (middle_internal = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
+ if (NULL == (right_internal = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
+
+ /* More setup for accessing child node information */
+ left_child = left_internal;
+ middle_child = middle_internal;
+ right_child = right_internal;
+ left_nrec = &(left_internal->nrec);
+ middle_nrec = &(middle_internal->nrec);
+ right_nrec = &(right_internal->nrec);
+ left_native = left_internal->int_native;
+ middle_native = middle_internal->int_native;
+ right_native = right_internal->int_native;
+ left_node_ptrs = left_internal->node_ptrs;
+ middle_node_ptrs = middle_internal->node_ptrs;
+ right_node_ptrs = right_internal->node_ptrs;
+ } /* end if */
+ else {
+ H5B2_leaf_t *left_leaf; /* Pointer to left leaf node */
+ H5B2_leaf_t *middle_leaf; /* Pointer to middle leaf node */
+ H5B2_leaf_t *right_leaf; /* Pointer to right leaf node */
+
+ /* Setup information for unlocking child nodes */
+ child_class = H5AC_BT2_LEAF;
+ left_addr = internal->node_ptrs[idx-1].addr;
+ middle_addr = internal->node_ptrs[idx].addr;
+ right_addr = internal->node_ptrs[idx+1].addr;
+
+ /* Lock B-tree child nodes */
+ if (NULL == (left_leaf = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx-1].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
+ if (NULL == (middle_leaf = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
+ if (NULL == (right_leaf = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
+
+ /* More setup for accessing child node information */
+ left_child = left_leaf;
+ middle_child = middle_leaf;
+ right_child = right_leaf;
+ left_nrec = &(left_leaf->nrec);
+ middle_nrec = &(middle_leaf->nrec);
+ right_nrec = &(right_leaf->nrec);
+ left_native = left_leaf->leaf_native;
+ middle_native = middle_leaf->leaf_native;
+ right_native = right_leaf->leaf_native;
+ } /* end else */
+
+ /* Redistribute records into left node */
+ {
+ unsigned total_nrec = *left_nrec + *middle_nrec + *right_nrec + 2;
+ unsigned middle_nrec_move = ((total_nrec - 1) / 2) - *left_nrec;
+
+ /* Set the base number of records moved from middle node */
+ middle_moved_nrec = middle_nrec_move;
+
+ /* Copy record from parent node to proper location in left node */
+ HDmemcpy(H5B2_NAT_NREC(left_native,shared,*left_nrec),H5B2_INT_NREC(internal,shared,idx-1),shared->type->nrec_size);
+
+ /* Copy records from middle node to left node */
+ HDmemcpy(H5B2_NAT_NREC(left_native,shared,*left_nrec+1),H5B2_NAT_NREC(middle_native,shared,0),shared->type->nrec_size*(middle_nrec_move-1));
+
+ /* Copy record from middle node to proper location in parent node */
+ HDmemcpy(H5B2_INT_NREC(internal,shared,idx-1),H5B2_NAT_NREC(middle_native,shared,(middle_nrec_move-1)),shared->type->nrec_size);
+
+ /* Slide records in middle node down */
+ HDmemmove(H5B2_NAT_NREC(middle_native,shared,0),H5B2_NAT_NREC(middle_native,shared,middle_nrec_move),shared->type->nrec_size*(*middle_nrec-middle_nrec_move));
+
+ /* Move node pointers also if this is an internal node */
+ if(depth>1) {
+ unsigned u; /* Local index variable */
+
+ /* Copy node pointers from middle node into left node */
+ HDmemcpy(&(left_node_ptrs[*left_nrec+1]),&(middle_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*middle_nrec_move);
+
+ /* Count the number of records being moved into the left node */
+ for(u=0; u<middle_nrec_move; u++)
+ middle_moved_nrec += middle_node_ptrs[u].all_nrec;
+
+ /* Slide the node pointers in right node down */
+ HDmemmove(&(middle_node_ptrs[0]),&(middle_node_ptrs[middle_nrec_move]),sizeof(H5B2_node_ptr_t)*((*middle_nrec+1)-middle_nrec_move));
+ } /* end if */
+
+ /* Update # of records in left & middle nodes */
+ *left_nrec += middle_nrec_move;
+ *middle_nrec -= middle_nrec_move;
+ } /* end block */
+
+ /* Redistribute records into middle node */
+ {
+ /* Copy record from parent node to proper location in middle node */
+ HDmemcpy(H5B2_NAT_NREC(middle_native,shared,*middle_nrec),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size);
+
+ /* Copy records from right node to middle node */
+ HDmemcpy(H5B2_NAT_NREC(middle_native,shared,*middle_nrec+1),H5B2_NAT_NREC(right_native,shared,0),shared->type->nrec_size*(*right_nrec));
+
+ /* Move node pointers also if this is an internal node */
+ if(depth>1)
+ /* Copy node pointers from middle node into left node */
+ HDmemcpy(&(middle_node_ptrs[*middle_nrec+1]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*(*right_nrec+1));
+
+ /* Update # of records in middle node */
+ *middle_nrec += *right_nrec + 1;
+ } /* end block */
+
+ /* Update # of records in child nodes */
+ internal->node_ptrs[idx-1].node_nrec = *left_nrec;
+ internal->node_ptrs[idx].node_nrec = *middle_nrec;
+
+ /* Update total # of records in child B-trees */
+ internal->node_ptrs[idx-1].all_nrec += middle_moved_nrec;
+ internal->node_ptrs[idx].all_nrec += (internal->node_ptrs[idx+1].all_nrec + 1) - middle_moved_nrec;
+
+ /* Slide records in parent node down, to eliminate demoted record */
+ if((idx+1) < internal->nrec) {
+ HDmemmove(H5B2_INT_NREC(internal,shared,idx),H5B2_INT_NREC(internal,shared,idx+1),shared->type->nrec_size*(internal->nrec-(idx+1)));
+ HDmemmove(&(internal->node_ptrs[idx+1]),&(internal->node_ptrs[idx+2]),sizeof(H5B2_node_ptr_t)*(internal->nrec-(idx+1)));
+ } /* end if */
+
+ /* Update # of records in parent node */
+ internal->nrec--;
+
+ /* Mark parent as dirty */
+ *internal_flags_ptr |= H5AC__DIRTIED_FLAG;
+
+ /* Update grandparent info */
+ curr_node_ptr->node_nrec--;
+
+ /* Mark grandparent as dirty */
+ *parent_cache_info_flags_ptr |= H5AC__DIRTIED_FLAG;
+
+#ifdef H5B2_DEBUG
+ H5B2_assert_internal((hsize_t)0,shared,internal);
+ if(depth>1) {
+ H5B2_assert_internal2(internal->node_ptrs[idx-1].all_nrec,shared,left_child,middle_child);
+ H5B2_assert_internal(internal->node_ptrs[idx].all_nrec,shared,middle_child);
+ } /* end if */
+ else {
+ H5B2_assert_leaf2(shared,left_child,middle_child);
+ H5B2_assert_leaf(shared,middle_child);
+ } /* end else */
+#endif /* H5B2_DEBUG */
+
+ /* Unlock left & middle nodes (marked as dirty) */
+ if (H5AC_unprotect(f, dxpl_id, child_class, left_addr, left_child, H5AC__DIRTIED_FLAG) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
+ if (H5AC_unprotect(f, dxpl_id, child_class, middle_addr, middle_child, H5AC__DIRTIED_FLAG) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
+
+ /* Delete right node & remove from cache (marked as dirty) */
+ if (H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, right_addr, (hsize_t)shared->node_size)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node")
+ if (H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5B2_merge3 */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_swap_leaf
+ *
+ * Purpose: Swap a record in a node with a record in a leaf node
+ *
+ * Return: Success: Non-negative
+ *
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Mar 4 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B2_swap_leaf(H5F_t *f, hid_t dxpl_id, unsigned depth,
+ H5B2_internal_t *internal, unsigned *internal_flags_ptr,
+ unsigned idx, void *swap_loc)
+{
+ const H5AC_class_t *child_class; /* Pointer to child node's class info */
+ haddr_t child_addr; /* Address of child node */
+ void *child; /* Pointer to child node */
+ uint8_t *child_native; /* Pointer to child's native records */
+ H5B2_shared_t *shared; /* B-tree's shared info */
+ herr_t ret_value=SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5B2_swap_leaf)
+
+ HDassert(f);
+ HDassert(internal);
+ HDassert(internal_flags_ptr);
+ HDassert(idx <= internal->nrec);
+
+ /* Get the pointer to the shared B-tree info */
+ shared=H5RC_GET_OBJ(internal->shared);
+ HDassert(shared);
+
+ /* Check for the kind of B-tree node to swap */
+ if(depth>1) {
+ H5B2_internal_t *child_internal; /* Pointer to internal node */
+
+ /* Setup information for unlocking child node */
+ child_class = H5AC_BT2_INT;
+ child_addr = internal->node_ptrs[idx].addr;
+
+ /* Lock B-tree child nodes */
+ if (NULL == (child_internal = H5AC_protect(f, dxpl_id, child_class, child_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
+
+ /* More setup for accessing child node information */
+ child = child_internal;
+ child_native = child_internal->int_native;
+ } /* end if */
+ else {
+ H5B2_leaf_t *child_leaf; /* Pointer to leaf node */
+
+ /* Setup information for unlocking child nodes */
+ child_class = H5AC_BT2_LEAF;
+ child_addr = internal->node_ptrs[idx].addr;
+
+ /* Lock B-tree child node */
+ if (NULL == (child_leaf = H5AC_protect(f, dxpl_id, child_class, child_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
+
+ /* More setup for accessing child node information */
+ child = child_leaf;
+ child_native = child_leaf->leaf_native;
+ } /* end else */
+
+ /* Swap records (use disk page as temporary buffer) */
+ HDmemcpy(shared->page, H5B2_NAT_NREC(child_native,shared,0), shared->type->nrec_size);
+ HDmemcpy(H5B2_NAT_NREC(child_native,shared,0), swap_loc, shared->type->nrec_size);
+ HDmemcpy(swap_loc, shared->page, shared->type->nrec_size);
+
+ /* Mark parent as dirty */
+ *internal_flags_ptr |= H5AC__DIRTIED_FLAG;
+
+#ifdef H5B2_DEBUG
+ H5B2_assert_internal((hsize_t)0,shared,internal);
+ if(depth>1)
+ H5B2_assert_internal(internal->node_ptrs[idx].all_nrec,shared,child);
+ else
+ H5B2_assert_leaf(shared,child);
+#endif /* H5B2_DEBUG */
+
+ /* Unlock child node */
+ if (H5AC_unprotect(f, dxpl_id, child_class, child_addr, child, H5AC__DIRTIED_FLAG) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5B2_swap_leaf */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_insert_leaf
+ *
+ * Purpose: Adds a new record to a B-tree leaf node.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Mar 3 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5B2_insert_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
+ H5B2_node_ptr_t *curr_node_ptr, void *udata)
+{
+ H5B2_leaf_t *leaf; /* Pointer to leaf node */
+ H5B2_shared_t *shared; /* Pointer to B-tree's shared information */
+ int cmp; /* Comparison value of records */
+ unsigned idx; /* Location of record which matches key */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT(H5B2_insert_leaf)
+
+ /* Check arguments. */
+ HDassert(f);
+ HDassert(bt2_shared);
+ HDassert(curr_node_ptr);
+ HDassert(H5F_addr_defined(curr_node_ptr->addr));
+
+ /* Lock current B-tree node */
+ if (NULL == (leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr->addr, &(curr_node_ptr->node_nrec), bt2_shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
+
+ /* Get the pointer to the shared B-tree info */
+ shared=H5RC_GET_OBJ(bt2_shared);
+ HDassert(shared);
+
+ /* Must have a leaf node with enough space to insert a record now */
+ HDassert(curr_node_ptr->node_nrec < shared->split_leaf_nrec);
+
+ /* Sanity check number of records */
+ HDassert(curr_node_ptr->all_nrec == curr_node_ptr->node_nrec);
+ HDassert(leaf->nrec == curr_node_ptr->node_nrec);
+
+ /* Check for inserting into empty leaf */
+ if(leaf->nrec==0)
+ idx=0;
+ else {
+ /* Find correct location to insert this record */
+ if((cmp = H5B2_locate_record(shared->type,leaf->nrec,shared->nat_off,leaf->leaf_native,udata,&idx)) == 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_EXISTS, FAIL, "record is already in B-tree")
+ if(cmp > 0)
+ idx++;
+
+ /* Make room for new record */
+ if(idx<leaf->nrec)
+ HDmemmove(H5B2_LEAF_NREC(leaf,shared,idx+1),H5B2_LEAF_NREC(leaf,shared,idx),shared->type->nrec_size*(leaf->nrec-idx));
+ } /* end else */
+
+ /* Make callback to store record in native form */
+ if((shared->type->store)(H5B2_LEAF_NREC(leaf,shared,idx),udata)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into leaf node")
+
+ /* Update record count for node pointer to current node */
+ curr_node_ptr->all_nrec++;
+ curr_node_ptr->node_nrec++;
+
+ /* Update record count for current node */
+ leaf->nrec++;
+
+done:
+ /* Release the B-tree leaf node (marked as dirty) */
+ if (leaf && H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr->addr, leaf, H5AC__DIRTIED_FLAG) < 0)
+ HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release leaf B-tree node")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5B2_insert_leaf() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_insert_internal
+ *
+ * Purpose: Adds a new record to a B-tree node.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Mar 2 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5B2_insert_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
+ unsigned depth, unsigned *parent_cache_info_flags_ptr,
+ H5B2_node_ptr_t *curr_node_ptr, void *udata)
+{
+ H5B2_internal_t *internal; /* Pointer to internal node */
+ unsigned internal_flags = H5AC__NO_FLAGS_SET;
+ H5B2_shared_t *shared; /* Pointer to B-tree's shared information */
+ unsigned idx; /* Location of record which matches key */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT(H5B2_insert_internal)
+
+ /* Check arguments. */
+ HDassert(f);
+ HDassert(bt2_shared);
+ HDassert(depth>0);
+ HDassert(parent_cache_info_flags_ptr);
+ HDassert(curr_node_ptr);
+ HDassert(H5F_addr_defined(curr_node_ptr->addr));
+
+ /* Lock current B-tree node */
+ if (NULL == (internal = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr->addr, &(curr_node_ptr->node_nrec), bt2_shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
+
+ /* Get the pointer to the shared B-tree info */
+ shared=H5RC_GET_OBJ(bt2_shared);
+ HDassert(shared);
+
+/* Split or redistribute child node pointers, if necessary */
+ {
+ int cmp; /* Comparison value of records */
+ unsigned retries; /* Number of times to attempt redistribution */
+ size_t split_nrec; /* Number of records to split node at */
+
+ /* Locate node pointer for child */
+ if((cmp=H5B2_locate_record(shared->type,internal->nrec,shared->nat_off,internal->int_native,udata,&idx)) == 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_EXISTS, FAIL, "record is already in B-tree")
+ if(cmp>0)
+ idx++;
+
+ /* Set the number of redistribution retries */
+ /* This takes care of the case where a B-tree node needs to be
+ * redistributed, but redistributing the node causes the index
+ * for insertion to move to another node, which also needs to be
+ * redistributed. Now, we loop trying to redistribute and then
+ * eventually force a split */
+ retries = 2;
+
+ /* Determine the correct number of records to split at */
+ if(depth==1)
+ split_nrec = shared->split_leaf_nrec;
+ else
+ split_nrec = shared->split_int_nrec;
+
+ /* Preemptively split/redistribute a node we will enter */
+ while(internal->node_ptrs[idx].node_nrec == split_nrec) {
+ /* Attempt to redistribute records among children */
+ if(idx==0) { /* Left-most child */
+ if(retries>0 && (internal->node_ptrs[idx+1].node_nrec < split_nrec)) {
+ if(H5B2_redistribute2(f,dxpl_id,depth,internal,idx)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records")
+ } /* end if */
+ else {
+ if(H5B2_split2(f,dxpl_id,depth,curr_node_ptr,
+ parent_cache_info_flags_ptr, internal,&internal_flags,idx)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to split child node")
+ } /* end else */
+ } /* end if */
+ else if(idx==internal->nrec) { /* Right-most child */
+ if(retries>0 && (internal->node_ptrs[idx-1].node_nrec < split_nrec)) {
+ if(H5B2_redistribute2(f,dxpl_id,depth,internal,(idx-1))<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records")
+ } /* end if */
+ else {
+ if(H5B2_split2(f,dxpl_id,depth,curr_node_ptr,
+ parent_cache_info_flags_ptr, internal,&internal_flags,(idx-1))<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to split child node")
+ } /* end else */
+ } /* end if */
+ else { /* Middle child */
+ if(retries>0 && ((internal->node_ptrs[idx+1].node_nrec < split_nrec) ||
+ (internal->node_ptrs[idx-1].node_nrec < split_nrec))) {
+ if(H5B2_redistribute3(f,dxpl_id,depth,internal,&internal_flags,idx)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records")
+ } /* end if */
+ else {
+ if(H5B2_split3(f,dxpl_id,depth,curr_node_ptr,
+ parent_cache_info_flags_ptr, internal,&internal_flags,idx)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to split child node")
+ } /* end else */
+ } /* end else */
+
+ /* Locate node pointer for child (after split/redistribute) */
+/* Actually, this can be easily updated (for 2-node redistrib.) and shouldn't require re-searching */
+ if((cmp=H5B2_locate_record(shared->type,internal->nrec,shared->nat_off,internal->int_native,udata,&idx)) == 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_EXISTS, FAIL, "record is already in B-tree")
+ if(cmp > 0)
+ idx++;
+
+ /* Decrement the number of redistribution retries left */
+ retries--;
+ } /* end while */
+ } /* end block */
+
+ /* Attempt to insert node */
+ if(depth>1) {
+ if(H5B2_insert_internal(f, dxpl_id, bt2_shared, depth-1, &internal_flags, &internal->node_ptrs[idx], udata) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into B-tree internal node")
+ } /* end if */
+ else {
+ if(H5B2_insert_leaf(f,dxpl_id,bt2_shared,&internal->node_ptrs[idx],udata)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into B-tree leaf node")
+ } /* end else */
+
+ /* Update record count for node pointer to current node */
+ curr_node_ptr->all_nrec++;
+
+ /* Mark node as dirty */
+ internal_flags |= H5AC__DIRTIED_FLAG;
+
+done:
+ /* Release the B-tree internal node */
+ if (internal && H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr->addr, internal, internal_flags) < 0)
+ HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release internal B-tree node")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5B2_insert_internal() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_create_leaf
+ *
+ * Purpose: Creates empty leaf node of a B-tree and update node pointer
+ * to point to it.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 2 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5B2_create_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, H5B2_node_ptr_t *node_ptr)
+{
+ H5B2_leaf_t *leaf = NULL; /* Pointer to new leaf node created */
+ H5B2_shared_t *shared; /* Shared B-tree information */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT(H5B2_create_leaf)
+
+ /* Check arguments. */
+ HDassert(f);
+ HDassert(bt2_shared);
+ HDassert(node_ptr);
+
+ /* Allocate memory for leaf information */
+ if (NULL==(leaf = H5FL_MALLOC(H5B2_leaf_t)))
+ HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree leaf info")
+
+ /* Set metadata cache info */
+ 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);
+
+ /* 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, FAIL, "memory allocation failed for B-tree leaf native keys")
+#ifdef H5_USING_PURIFY
+HDmemset(leaf->leaf_native,0,shared->type->nrec_size*shared->leaf_nrec);
+#endif /* H5_USING_PURIFY */
+
+ /* Set number of records */
+ leaf->nrec=0;
+
+ /* 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 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)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "can't add B-tree leaf to cache")
+
+done:
+ if (ret_value<0) {
+ if (leaf)
+ (void)H5B2_cache_leaf_dest(f,leaf);
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5B2_create_leaf() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_create_internal
+ *
+ * Purpose: Creates empty internal node of a B-tree and update node pointer
+ * to point to it.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 3 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B2_create_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, H5B2_node_ptr_t *node_ptr)
+{
+ 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_NOINIT(H5B2_create_internal)
+
+ /* Check arguments. */
+ HDassert(f);
+ HDassert(bt2_shared);
+ HDassert(node_ptr);
+
+ /* 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));
+
+ /* 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);
+
+ /* 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, FAIL, "memory allocation failed for B-tree internal native keys")
+#ifdef H5_USING_PURIFY
+HDmemset(internal->int_native,0,shared->type->nrec_size*shared->internal_nrec);
+#endif /* H5_USING_PURIFY */
+
+ /* 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")
+#ifdef H5_USING_PURIFY
+HDmemset(internal->node_ptrs,0,sizeof(H5B2_node_ptr_t)*(shared->internal_nrec+1));
+#endif /* H5_USING_PURIFY */
+
+ /* Set number of records */
+ internal->nrec=0;
+
+ /* 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")
+
+ /* 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:
+ if (ret_value<0) {
+ if (internal)
+ (void)H5B2_cache_internal_dest(f,internal);
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5B2_create_internal() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_iterate_node
+ *
+ * Purpose: Iterate over all the records from a B-tree node, in "in-order"
+ * order, making a callback for each record.
+ *
+ * If the callback returns non-zero, the iteration breaks out
+ * without finishing all the records.
+ *
+ * Return: Value from callback, non-negative on success, negative on error
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 11 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5B2_iterate_node(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, unsigned depth,
+ const H5B2_node_ptr_t *curr_node, H5B2_operator_t op, void *op_data)
+{
+ H5B2_shared_t *shared; /* Pointer to B-tree's shared information */
+ const H5AC_class_t *curr_node_class=NULL; /* Pointer to current node's class info */
+ void *node=NULL; /* Pointers to current node */
+ uint8_t *native; /* Pointers to node's native records */
+ H5B2_node_ptr_t *node_ptrs=NULL; /* Pointers to node's node pointers */
+ unsigned u; /* Local index */
+ herr_t ret_value = H5B2_ITER_CONT;
+
+ FUNC_ENTER_NOAPI_NOINIT(H5B2_iterate_node)
+
+ /* Check arguments. */
+ HDassert(f);
+ HDassert(bt2_shared);
+ HDassert(curr_node);
+ HDassert(op);
+
+ /* Get the pointer to the shared B-tree info */
+ shared=H5RC_GET_OBJ(bt2_shared);
+ HDassert(shared);
+
+ if(depth>0) {
+ H5B2_internal_t *internal; /* Pointer to internal node */
+
+ /* Lock the current B-tree node */
+ if (NULL == (internal = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, curr_node->addr, &(curr_node->node_nrec), bt2_shared, H5AC_READ)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
+
+ /* Set up information about current node */
+ curr_node_class = H5AC_BT2_INT;
+ node = internal;
+ native = internal->int_native;
+ node_ptrs = internal->node_ptrs;
+ } /* end if */
+ else {
+ H5B2_leaf_t *leaf; /* Pointer to leaf node */
+
+ /* Lock the current B-tree node */
+ if (NULL == (leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, curr_node->addr, &(curr_node->node_nrec), bt2_shared, H5AC_READ)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
+
+ /* Set up information about current node */
+ curr_node_class = H5AC_BT2_LEAF;
+ node = leaf;
+ native = leaf->leaf_native;
+ } /* end else */
+
+ /* Iterate through records */
+ for(u=0; u<curr_node->node_nrec && !ret_value; u++) {
+ /* Descend into child node, if current node is an internal node */
+ if(depth>0) {
+ if((ret_value = H5B2_iterate_node(f,dxpl_id,bt2_shared,depth-1,&(node_ptrs[u]),op,op_data))<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTLIST, FAIL, "node iteration failed")
+ } /* end if */
+
+ /* Make callback for current record */
+ if ((ret_value = (op)(H5B2_NAT_NREC(native,shared,u), op_data)) <0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTLIST, FAIL, "iterator function failed")
+ } /* end for */
+
+ /* Descend into last child node, if current node is an internal node */
+ if(!ret_value && depth>0) {
+ if((ret_value = H5B2_iterate_node(f,dxpl_id,bt2_shared,depth-1,&(node_ptrs[u]),op,op_data))<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTLIST, FAIL, "node iteration failed")
+ } /* end if */
+
+done:
+ /* Unlock current node */
+ if(node)
+ if (H5AC_unprotect(f, dxpl_id, curr_node_class, curr_node->addr, node, H5AC__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5B2_iterate_node() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_remove_leaf
+ *
+ * Purpose: Removes a record from a B-tree leaf node.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Mar 3 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5B2_remove_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
+ H5B2_node_ptr_t *curr_node_ptr, void *udata)
+{
+ H5B2_leaf_t *leaf; /* Pointer to leaf node */
+ haddr_t leaf_addr=HADDR_UNDEF; /* Leaf address on disk */
+ unsigned leaf_flags=H5AC__NO_FLAGS_SET; /* Flags for unprotecting leaf node */
+ H5B2_shared_t *shared; /* Pointer to B-tree's shared information */
+ unsigned idx; /* Location of record which matches key */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT(H5B2_remove_leaf)
+
+ /* Check arguments. */
+ HDassert(f);
+ HDassert(bt2_shared);
+ HDassert(curr_node_ptr);
+ HDassert(H5F_addr_defined(curr_node_ptr->addr));
+
+ /* Lock current B-tree node */
+ leaf_addr = curr_node_ptr->addr;
+ if (NULL == (leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, leaf_addr, &(curr_node_ptr->node_nrec), bt2_shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
+
+ /* Get the pointer to the shared B-tree info */
+ shared=H5RC_GET_OBJ(bt2_shared);
+ HDassert(shared);
+
+ /* Sanity check number of records */
+ HDassert(curr_node_ptr->all_nrec == curr_node_ptr->node_nrec);
+ HDassert(leaf->nrec == curr_node_ptr->node_nrec);
+
+ /* Find correct location to remove this record */
+ if(H5B2_locate_record(shared->type,leaf->nrec,shared->nat_off,leaf->leaf_native,udata,&idx) != 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "record is not in B-tree")
+
+ /* Make callback to retrieve record in native form */
+ if((shared->type->retrieve)(udata,H5B2_LEAF_NREC(leaf,shared,idx))<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to remove record into leaf node")
+
+ /* Update number of records in node */
+ leaf->nrec--;
+
+ /* Mark leaf node as dirty also */
+ leaf_flags |= H5AC__DIRTIED_FLAG;
+
+ if(leaf->nrec > 0) {
+ /* Pack record out of leaf */
+ if(idx<leaf->nrec)
+ HDmemmove(H5B2_LEAF_NREC(leaf,shared,idx),H5B2_LEAF_NREC(leaf,shared,idx+1),shared->type->nrec_size*(leaf->nrec-idx));
+ } /* end if */
+ else {
+ /* Release space for B-tree node on disk */
+ if (H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, leaf_addr, (hsize_t)shared->node_size)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node")
+
+ /* Let the cache know that the object is deleted */
+ leaf_flags |= H5AC__DELETED_FLAG;
+
+ /* Reset address of parent node pointer */
+ curr_node_ptr->addr = HADDR_UNDEF;
+ } /* end else */
+
+ /* Update record count for parent of leaf node */
+ curr_node_ptr->node_nrec--;
+
+done:
+ /* Release the B-tree leaf node */
+ if (leaf && H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, leaf_addr, leaf, leaf_flags) < 0)
+ HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release leaf B-tree node")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5B2_remove_leaf() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_remove_internal
+ *
+ * Purpose: Removes a record from a B-tree node.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Mar 3 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5B2_remove_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
+ hbool_t *depth_decreased, void *swap_loc, unsigned depth,
+ H5AC_info_t *parent_cache_info, unsigned *parent_cache_info_flags_ptr,
+ H5B2_node_ptr_t *curr_node_ptr, void *udata)
+{
+ H5AC_info_t *new_cache_info; /* Pointer to new cache info */
+ unsigned *new_cache_info_flags_ptr = NULL;
+ H5B2_node_ptr_t *new_node_ptr; /* Pointer to new node pointer */
+ H5B2_internal_t *internal; /* Pointer to internal node */
+ unsigned internal_flags = H5AC__NO_FLAGS_SET;
+ haddr_t internal_addr; /* Address of internal node */
+ H5B2_shared_t *shared; /* Pointer to B-tree's shared information */
+ unsigned idx; /* Location of record which matches key */
+ size_t merge_nrec; /* Number of records to merge node at */
+ hbool_t collapsed_root = FALSE; /* Whether the root was collapsed */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT(H5B2_remove_internal)
+
+ /* Check arguments. */
+ HDassert(f);
+ HDassert(bt2_shared);
+ HDassert(depth>0);
+ HDassert(parent_cache_info);
+ HDassert(parent_cache_info_flags_ptr);
+ HDassert(curr_node_ptr);
+ HDassert(H5F_addr_defined(curr_node_ptr->addr));
+
+ /* Lock current B-tree node */
+ internal_addr = curr_node_ptr->addr;
+ if (NULL == (internal = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, internal_addr, &(curr_node_ptr->node_nrec), bt2_shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
+
+ /* Get the pointer to the shared B-tree info */
+ shared=H5RC_GET_OBJ(bt2_shared);
+ HDassert(shared);
+
+ /* Determine the correct number of records to merge at */
+ if(depth==1)
+ merge_nrec = shared->merge_leaf_nrec;
+ else
+ merge_nrec = shared->merge_int_nrec;
+
+ /* Check for needing to collapse the root node */
+ /* (The root node is the only node allowed to have 1 record) */
+ if(internal->nrec == 1 &&
+ ((internal->node_ptrs[0].node_nrec + internal->node_ptrs[1].node_nrec) <= ((merge_nrec * 2) + 1))) {
+
+ /* Merge children of root node */
+ if(H5B2_merge2(f,dxpl_id,depth,curr_node_ptr,
+ parent_cache_info_flags_ptr, internal,&internal_flags,0)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to merge child node")
+
+ /* Release space for root B-tree node on disk */
+ if (H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, internal_addr, (hsize_t)shared->node_size)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node")
+
+ /* Let the cache know that the object is deleted */
+ internal_flags |= H5AC__DELETED_FLAG;
+
+ /* Reset information in parent node pointer */
+ curr_node_ptr->addr = internal->node_ptrs[0].addr;
+ curr_node_ptr->node_nrec = internal->node_ptrs[0].node_nrec;
+
+ /* Indicate that the level of the B-tree decreased */
+ *depth_decreased = TRUE;
+
+ /* Set pointers for advancing to child node */
+ new_cache_info = parent_cache_info;
+ new_cache_info_flags_ptr = parent_cache_info_flags_ptr;
+ new_node_ptr = curr_node_ptr;
+
+ /* Set flag to indicate root was collapsed */
+ collapsed_root = TRUE;
+ } /* end if */
+ /* Merge or redistribute child node pointers, if necessary */
+ else {
+ int cmp=0; /* Comparison value of records */
+ unsigned retries; /* Number of times to attempt redistribution */
+
+ /* Locate node pointer for child */
+ if(swap_loc)
+ idx = 0;
+ else {
+ cmp=H5B2_locate_record(shared->type,internal->nrec,shared->nat_off,internal->int_native,udata,&idx);
+ if(cmp >= 0)
+ idx++;
+ } /* end else */
+
+ /* Set the number of redistribution retries */
+ /* This takes care of the case where a B-tree node needs to be
+ * redistributed, but redistributing the node causes the index
+ * for removal to move to another node, which also needs to be
+ * redistributed. Now, we loop trying to redistribute and then
+ * eventually force a merge */
+ retries = 2;
+
+ /* Preemptively merge/redistribute a node we will enter */
+ while(internal->node_ptrs[idx].node_nrec==merge_nrec) {
+ /* Attempt to redistribute records among children */
+ if(idx==0) { /* Left-most child */
+ if(retries>0 && (internal->node_ptrs[idx+1].node_nrec > merge_nrec)) {
+ if(H5B2_redistribute2(f,dxpl_id,depth,internal,idx)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records")
+ } /* end if */
+ else {
+ if(H5B2_merge2(f,dxpl_id,depth,curr_node_ptr,
+ parent_cache_info_flags_ptr, internal,&internal_flags,idx)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to merge child node")
+ } /* end else */
+ } /* end if */
+ else if(idx==internal->nrec) { /* Right-most child */
+ if(retries>0 && (internal->node_ptrs[idx-1].node_nrec > merge_nrec)) {
+ if(H5B2_redistribute2(f,dxpl_id,depth,internal,(idx-1))<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records")
+ } /* end if */
+ else {
+ if(H5B2_merge2(f,dxpl_id,depth,curr_node_ptr,
+ parent_cache_info_flags_ptr, internal,&internal_flags,(idx-1))<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to merge child node")
+ } /* end else */
+ } /* end if */
+ else { /* Middle child */
+ if(retries>0 && ((internal->node_ptrs[idx+1].node_nrec > merge_nrec) ||
+ (internal->node_ptrs[idx-1].node_nrec > merge_nrec))) {
+ if(H5B2_redistribute3(f,dxpl_id,depth,internal,&internal_flags,idx)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records")
+ } /* end if */
+ else {
+ if(H5B2_merge3(f,dxpl_id,depth,curr_node_ptr,
+ parent_cache_info_flags_ptr,internal, &internal_flags,idx)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to merge child node")
+ } /* end else */
+ } /* end else */
+
+ /* Locate node pointer for child (after merge/redistribute) */
+ if(swap_loc)
+ idx = 0;
+ else {
+/* Actually, this can be easily updated (for 2-node redistrib.) and shouldn't require re-searching */
+ cmp=H5B2_locate_record(shared->type,internal->nrec,shared->nat_off,internal->int_native,udata,&idx);
+ if(cmp >= 0)
+ idx++;
+ } /* end else */
+
+ /* Decrement the number of redistribution retries left */
+ retries--;
+ } /* end while */
+
+ /* Handle deleting a record from an internal node */
+ if(!swap_loc && cmp==0)
+ swap_loc = H5B2_INT_NREC(internal,shared,idx-1);
+
+ /* Swap record to delete with record from leaf, if we are the last internal node */
+ if(swap_loc && depth==1)
+ if(H5B2_swap_leaf(f,dxpl_id,depth,internal,&internal_flags,idx,swap_loc) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTSWAP, FAIL, "Can't swap records in B-tree")
+
+ /* Set pointers for advancing to child node */
+ new_cache_info_flags_ptr = &internal_flags;
+ new_cache_info = &internal->cache_info;
+ new_node_ptr = &internal->node_ptrs[idx];
+ } /* end else */
+
+ /* Attempt to remove node */
+ if(depth>1) {
+ if(H5B2_remove_internal(f,dxpl_id,bt2_shared,depth_decreased, swap_loc, depth-1,
+ new_cache_info,new_cache_info_flags_ptr,new_node_ptr,udata)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to remove record from B-tree internal node")
+ } /* end if */
+ else {
+ if(H5B2_remove_leaf(f,dxpl_id,bt2_shared,new_node_ptr,udata)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to remove record from B-tree leaf node")
+ } /* end else */
+
+ /* Update record count for node pointer to current node */
+ if(!collapsed_root)
+ new_node_ptr->all_nrec--;
+
+ /* Mark node as dirty */
+ internal_flags |= H5AC__DIRTIED_FLAG;
+
+#ifdef H5B2_DEBUG
+ H5B2_assert_internal((!collapsed_root ? (curr_node_ptr->all_nrec-1) : new_node_ptr->all_nrec),shared,internal);
+#endif /* H5B2_DEBUG */
+
+done:
+ /* Release the B-tree internal node */
+ if (internal && H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, internal_addr, internal, internal_flags) < 0)
+ HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release internal B-tree node")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5B2_remove_internal() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_neighbor_leaf
+ *
+ * Purpose: Locate a record relative to the specified information in a
+ * B-tree leaf node and return that information by filling in
+ * fields of the
+ * caller-supplied UDATA pointer depending on the type of leaf node
+ * requested. The UDATA can point to additional data passed
+ * to the key comparison function.
+ *
+ * The 'OP' routine is called with the record found and the
+ * OP_DATA pointer, to allow caller to return information about
+ * the record.
+ *
+ * The RANGE indicates whether to search for records less than or
+ * equal to, or greater than or equal to the information passed
+ * in with UDATA.
+ *
+ * Return: Non-negative on success, negative on failure.
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Mar 9 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5B2_neighbor_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
+ H5B2_node_ptr_t *curr_node_ptr, void *neighbor_loc,
+ H5B2_compare_t comp, void *udata, H5B2_found_t op, void *op_data)
+{
+ H5B2_leaf_t *leaf; /* Pointer to leaf node */
+ H5B2_shared_t *shared; /* Pointer to B-tree's shared information */
+ unsigned idx; /* Location of record which matches key */
+ int cmp=0; /* Comparison value of records */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT(H5B2_neighbor_leaf)
+
+ /* Check arguments. */
+ HDassert(f);
+ HDassert(bt2_shared);
+ HDassert(curr_node_ptr);
+ HDassert(H5F_addr_defined(curr_node_ptr->addr));
+ HDassert(op);
+
+ /* Lock current B-tree node */
+ if (NULL == (leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr->addr, &(curr_node_ptr->node_nrec), bt2_shared, H5AC_READ)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
+
+ /* Get the pointer to the shared B-tree info */
+ shared=H5RC_GET_OBJ(bt2_shared);
+ HDassert(shared);
+
+
+ /* Locate node pointer for child */
+ cmp = H5B2_locate_record(shared->type, leaf->nrec, shared->nat_off, leaf->leaf_native, udata, &idx);
+ if(cmp > 0)
+ idx++;
+ else
+ if(cmp == 0 && comp == H5B2_COMPARE_GREATER)
+ idx++;
+
+ /* Set the neighbor location, if appropriate */
+ if(comp == H5B2_COMPARE_LESS) {
+ if(idx > 0)
+ neighbor_loc = H5B2_LEAF_NREC(leaf,shared,idx-1);
+ } /* end if */
+ else {
+ HDassert(comp == H5B2_COMPARE_GREATER);
+
+ if(idx < leaf->nrec)
+ neighbor_loc = H5B2_LEAF_NREC(leaf,shared,idx);
+ } /* end else */
+
+ /* Make callback if neighbor record has been found */
+ if(neighbor_loc) {
+ /* Make callback for current record */
+ if ((op)(neighbor_loc, op_data) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "'found' callback failed for B-tree neighbor operation")
+ } /* end if */
+ else
+ HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "unable to find neighbor record in B-tree")
+
+done:
+ /* Release the B-tree internal node */
+ if (leaf && H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr->addr, leaf, H5AC__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree leaf node")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5B2_neighbor_leaf() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_neighbor_internal
+ *
+ * Purpose: Locate a record relative to the specified information in a
+ * B-tree internal node and return that information by filling in
+ * fields of the
+ * caller-supplied UDATA pointer depending on the type of leaf node
+ * requested. The UDATA can point to additional data passed
+ * to the key comparison function.
+ *
+ * The 'OP' routine is called with the record found and the
+ * OP_DATA pointer, to allow caller to return information about
+ * the record.
+ *
+ * The RANGE indicates whether to search for records less than or
+ * equal to, or greater than or equal to the information passed
+ * in with UDATA.
+ *
+ * Return: Non-negative on success, negative on failure.
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Mar 9 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5B2_neighbor_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
+ unsigned depth, H5B2_node_ptr_t *curr_node_ptr, void *neighbor_loc,
+ H5B2_compare_t comp, void *udata, H5B2_found_t op, void *op_data)
+{
+ H5B2_internal_t *internal; /* Pointer to internal node */
+ H5B2_shared_t *shared; /* Pointer to B-tree's shared information */
+ unsigned idx; /* Location of record which matches key */
+ int cmp=0; /* Comparison value of records */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT(H5B2_neighbor_internal)
+
+ /* Check arguments. */
+ HDassert(f);
+ HDassert(bt2_shared);
+ HDassert(depth>0);
+ HDassert(curr_node_ptr);
+ HDassert(H5F_addr_defined(curr_node_ptr->addr));
+ HDassert(op);
+
+ /* Lock current B-tree node */
+ if (NULL == (internal = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr->addr, &(curr_node_ptr->node_nrec), bt2_shared, H5AC_READ)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
+
+ /* Get the pointer to the shared B-tree info */
+ shared=H5RC_GET_OBJ(bt2_shared);
+ HDassert(shared);
+
+ /* Locate node pointer for child */
+ cmp = H5B2_locate_record(shared->type,internal->nrec,shared->nat_off,internal->int_native,udata,&idx);
+ if(cmp > 0)
+ idx++;
+
+ /* Set the neighbor location, if appropriate */
+ if(comp == H5B2_COMPARE_LESS) {
+ if(idx > 0)
+ neighbor_loc = H5B2_INT_NREC(internal,shared,idx-1);
+ } /* end if */
+ else {
+ HDassert(comp == H5B2_COMPARE_GREATER);
+
+ if(idx < internal->nrec)
+ neighbor_loc = H5B2_INT_NREC(internal,shared,idx);
+ } /* end else */
+
+ /* Attempt to find neighboring record */
+ if(depth>1) {
+ if(H5B2_neighbor_internal(f, dxpl_id, bt2_shared, depth-1, &internal->node_ptrs[idx], neighbor_loc, comp, udata, op, op_data)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "unable to find neighbor record in B-tree internal node")
+ } /* end if */
+ else {
+ if(H5B2_neighbor_leaf(f, dxpl_id, bt2_shared, &internal->node_ptrs[idx], neighbor_loc, comp, udata, op, op_data)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "unable to find neighbor record in B-tree leaf node")
+ } /* end else */
+
+done:
+ /* Release the B-tree internal node */
+ if (internal && H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr->addr, internal, H5AC__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release internal B-tree node")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5B2_neighbor_internal() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_delete_node
+ *
+ * Purpose: Iterate over all the nodes in a B-tree node deleting them
+ * after they no longer have any children
+ *
+ * Return: Value from callback, non-negative on success, negative on error
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Mar 9 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5B2_delete_node(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, unsigned depth,
+ const H5B2_node_ptr_t *curr_node)
+{
+ H5B2_shared_t *shared; /* Pointer to B-tree's shared information */
+ const H5AC_class_t *curr_node_class=NULL; /* Pointer to current node's class info */
+ void *node=NULL; /* Pointers to current node */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT(H5B2_delete_node)
+
+ /* Check arguments. */
+ HDassert(f);
+ HDassert(bt2_shared);
+ HDassert(curr_node);
+
+ /* Get the pointer to the shared B-tree info */
+ shared=H5RC_GET_OBJ(bt2_shared);
+ HDassert(shared);
+
+ if(depth>0) {
+ H5B2_internal_t *internal; /* Pointer to internal node */
+ unsigned u; /* Local index */
+
+ /* Lock the current B-tree node */
+ if (NULL == (internal = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, curr_node->addr, &(curr_node->node_nrec), bt2_shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
+
+ /* Set up information about current node */
+ curr_node_class = H5AC_BT2_INT;
+ node = internal;
+
+ /* Descend into children */
+ for(u=0; u<internal->nrec+1; u++)
+ if(H5B2_delete_node(f, dxpl_id, bt2_shared, depth-1, &(internal->node_ptrs[u]))<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTLIST, FAIL, "node descent failed")
+ } /* end if */
+ else {
+ H5B2_leaf_t *leaf; /* Pointer to leaf node */
+
+ /* Lock the current B-tree node */
+ if (NULL == (leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, curr_node->addr, &(curr_node->node_nrec), bt2_shared, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node")
+
+ /* Set up information about current node */
+ curr_node_class = H5AC_BT2_LEAF;
+ node = leaf;
+ } /* end else */
+
+ /* Release space for current B-tree node on disk */
+ if (H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, curr_node->addr, (hsize_t)shared->node_size)<0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree node")
+
+done:
+ /* Unlock & delete current node */
+ if(node)
+ if (H5AC_unprotect(f, dxpl_id, curr_node_class, curr_node->addr, node, H5AC__DELETED_FLAG) < 0)
+ HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5B2_delete_node() */
+
+#ifdef H5B2_DEBUG
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_assert_leaf
+ *
+ * Purpose: Verify than a leaf node is mostly sane
+ *
+ * Return: Non-negative on success, negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 19 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B2_assert_leaf(H5B2_shared_t *shared, H5B2_leaf_t *leaf)
+{
+ unsigned u,v; /* Local index variables */
+
+ /* General sanity checking on node */
+ HDassert(leaf->nrec<=shared->split_leaf_nrec);
+
+ /* Sanity checking on records */
+ for(u=0; u<leaf->nrec; u++)
+ for(v=0; v<u; v++)
+ HDassert((shared->type->compare)(H5B2_LEAF_NREC(leaf,shared,u), H5B2_LEAF_NREC(leaf,shared,v))>0);
+
+ return(0);
+} /* end H5B2_assert_leaf() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_assert_leaf2
+ *
+ * Purpose: Verify than a leaf node is mostly sane
+ *
+ * Return: Non-negative on success, negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 19 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B2_assert_leaf2(H5B2_shared_t *shared, H5B2_leaf_t *leaf, H5B2_leaf_t *leaf2)
+{
+ unsigned u,v; /* Local index variables */
+
+ /* General sanity checking on node */
+ HDassert(leaf->nrec<=shared->split_leaf_nrec);
+
+ /* Sanity checking on records */
+ for(u=0; u<leaf->nrec; u++) {
+ HDassert((shared->type->compare)(H5B2_LEAF_NREC(leaf2,shared,0), H5B2_LEAF_NREC(leaf,shared,u))>0);
+ for(v=0; v<u; v++)
+ HDassert((shared->type->compare)(H5B2_LEAF_NREC(leaf,shared,u), H5B2_LEAF_NREC(leaf,shared,v))>0);
+ } /* end for */
+
+ return(0);
+} /* end H5B2_assert_leaf() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_assert_internal
+ *
+ * Purpose: Verify than an internal node is mostly sane
+ *
+ * Return: Non-negative on success, negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 19 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B2_assert_internal(hsize_t parent_all_nrec, H5B2_shared_t *shared, H5B2_internal_t *internal)
+{
+ hsize_t tot_all_nrec; /* Total number of records at or below this node */
+ unsigned u,v; /* Local index variables */
+
+ /* General sanity checking on node */
+ HDassert(internal->nrec<=shared->split_int_nrec);
+
+ /* Sanity checking on records */
+ for(u=0; u<internal->nrec; u++)
+ for(v=0; v<u; v++)
+ HDassert((shared->type->compare)(H5B2_INT_NREC(internal,shared,u), H5B2_INT_NREC(internal,shared,v))>0);
+
+ /* Sanity checking on node pointers */
+ tot_all_nrec=internal->nrec;
+ for(u=0; u<internal->nrec+1; u++) {
+ tot_all_nrec += internal->node_ptrs[u].all_nrec;
+
+ HDassert(H5F_addr_defined(internal->node_ptrs[u].addr));
+ HDassert(internal->node_ptrs[u].addr>0);
+ for(v=0; v<u; v++)
+ HDassert(internal->node_ptrs[u].addr!=internal->node_ptrs[v].addr);
+ } /* end for */
+
+ /* Sanity check all_nrec total in parent */
+ if(parent_all_nrec>0)
+ HDassert(tot_all_nrec == parent_all_nrec);
+
+ return(0);
+} /* end H5B2_assert_internal() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_assert_internal2
+ *
+ * Purpose: Verify than internal nodes are mostly sane
+ *
+ * Return: Non-negative on success, negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 19 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B2_assert_internal2(hsize_t parent_all_nrec, H5B2_shared_t *shared, H5B2_internal_t *internal, H5B2_internal_t *internal2)
+{
+ hsize_t tot_all_nrec; /* Total number of records at or below this node */
+ unsigned u,v; /* Local index variables */
+
+ /* General sanity checking on node */
+ HDassert(internal->nrec<=shared->split_int_nrec);
+
+ /* Sanity checking on records */
+ for(u=0; u<internal->nrec; u++)
+ for(v=0; v<u; v++)
+ HDassert((shared->type->compare)(H5B2_INT_NREC(internal,shared,u), H5B2_INT_NREC(internal,shared,v))>0);
+
+ /* Sanity checking on node pointers */
+ tot_all_nrec=internal->nrec;
+ for(u=0; u<internal->nrec+1; u++) {
+ tot_all_nrec += internal->node_ptrs[u].all_nrec;
+
+ HDassert(H5F_addr_defined(internal->node_ptrs[u].addr));
+ HDassert(internal->node_ptrs[u].addr>0);
+ for(v=0; v<u; v++)
+ HDassert(internal->node_ptrs[u].addr!=internal->node_ptrs[v].addr);
+ for(v=0; v<internal2->nrec+1; v++)
+ HDassert(internal->node_ptrs[u].addr!=internal2->node_ptrs[v].addr);
+ } /* end for */
+
+ /* Sanity check all_nrec total in parent */
+ if(parent_all_nrec>0)
+ HDassert(tot_all_nrec == parent_all_nrec);
+
+ return(0);
+} /* end H5B2_assert_internal2() */
+#endif /* H5B2_DEBUG */
+
diff --git a/src/H5B2pkg.h b/src/H5B2pkg.h
index 4abf5aa..784b1e5 100644
--- a/src/H5B2pkg.h
+++ b/src/H5B2pkg.h
@@ -184,6 +184,45 @@ H5_DLLVAR const H5B2_class_t H5B2_TEST[1];
H5_DLL herr_t H5B2_shared_init(H5F_t *f, H5B2_t *bt2, const H5B2_class_t *type,
size_t node_size, size_t rrec_size, unsigned split_percent, unsigned merge_percent);
+/* Routines for allocating nodes */
+H5_DLL herr_t H5B2_split_root(H5F_t *f, hid_t dxpl_id, H5B2_t *bt2,
+ unsigned *bt2_flags_ptr, H5RC_t *bt2_shared);
+H5_DLL herr_t H5B2_create_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
+ H5B2_node_ptr_t *node_ptr);
+
+/* Routines for inserting records */
+H5_DLL herr_t H5B2_insert_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
+ unsigned depth, unsigned *parent_cache_info_flags_ptr,
+ H5B2_node_ptr_t *curr_node_ptr, void *udata);
+H5_DLL herr_t H5B2_insert_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
+ H5B2_node_ptr_t *curr_node_ptr, void *udata);
+
+/* Routines for iterating over nodes/records */
+H5_DLL herr_t H5B2_iterate_node(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
+ unsigned depth, const H5B2_node_ptr_t *curr_node, H5B2_operator_t op,
+ void *op_data);
+
+/* Routines for locating records */
+H5_DLL int H5B2_locate_record(const H5B2_class_t *type, unsigned nrec,
+ size_t *rec_off, const uint8_t *native, const void *udata, unsigned *idx);
+H5_DLL herr_t H5B2_neighbor_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
+ unsigned depth, H5B2_node_ptr_t *curr_node_ptr, void *neighbor_loc,
+ H5B2_compare_t comp, void *udata, H5B2_found_t op, void *op_data);
+H5_DLL herr_t H5B2_neighbor_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
+ H5B2_node_ptr_t *curr_node_ptr, void *neighbor_loc,
+ H5B2_compare_t comp, void *udata, H5B2_found_t op, void *op_data);
+
+/* Routines for removing records */
+H5_DLL herr_t H5B2_remove_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
+ hbool_t *depth_decreased, void *swap_loc, unsigned depth, H5AC_info_t *parent_cache_info,
+ hbool_t * parent_cache_info_dirtied_ptr, H5B2_node_ptr_t *curr_node_ptr, void *udata);
+H5_DLL herr_t H5B2_remove_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
+ H5B2_node_ptr_t *curr_node_ptr, void *udata);
+
+/* Routines for deleting nodes */
+H5_DLL herr_t H5B2_delete_node(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
+ unsigned depth, const H5B2_node_ptr_t *curr_node);
+
/* Metadata cache callbacks */
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);
diff --git a/src/H5HF.c b/src/H5HF.c
index 1fe38cb..bdc9e00 100644
--- a/src/H5HF.c
+++ b/src/H5HF.c
@@ -56,7 +56,6 @@
/* Local Prototypes */
/********************/
-static herr_t H5HF_shared_free(void *_shared);
/*********************/
/* Package Variables */
@@ -75,82 +74,6 @@ H5FL_DEFINE(H5HF_t);
/* Local Variables */
/*******************/
-/* Declare a free list to manage the H5HF_shared_t struct */
-H5FL_DEFINE_STATIC(H5HF_shared_t);
-
-
-
-/*-------------------------------------------------------------------------
- * Function: H5HF_shared_init
- *
- * Purpose: Allocate & initialize shared fractal heap info
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 24 2006
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5HF_shared_init(H5F_t *f, H5HF_t *fh, H5HF_type_t type)
-{
- H5HF_shared_t *shared = NULL; /* Shared fractal heap information */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5HF_shared_init)
-
- /* Allocate space for the shared information */
- if(NULL == (shared = H5FL_CALLOC(H5HF_shared_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fractal heap shared information")
-
- /* Set the type of heap address mapping */
- shared->type = type;
-
- /* Make shared B-tree info reference counted */
- if(NULL == (fh->shared = H5RC_create(shared, H5HF_shared_free)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create ref-count wrapper for shared fractal heap info")
-
-done:
- if(ret_value < 0)
- if(shared)
- H5HF_shared_free(shared);
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_shared_init() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5HF_shared_free
- *
- * Purpose: Free shared fractal heap info
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 24 2006
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HF_shared_free(void *_shared)
-{
- H5HF_shared_t *shared = (H5HF_shared_t *)_shared;
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT(H5HF_shared_free)
-
- /* Sanity check */
- HDassert(shared);
-
- /* Free the shared info itself */
- H5FL_FREE(H5HF_shared_t, shared);
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_shared_free() */
/*-------------------------------------------------------------------------
@@ -168,7 +91,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5HF_create(H5F_t *f, hid_t dxpl_id, H5HF_type_t type, haddr_t *addr_p)
+H5HF_create(H5F_t *f, hid_t dxpl_id, H5HF_create_t *cparam, haddr_t *addr_p)
{
H5HF_t *fh = NULL; /* The new fractal heap header information */
herr_t ret_value = SUCCEED;
@@ -191,7 +114,7 @@ H5HF_create(H5F_t *f, hid_t dxpl_id, H5HF_type_t type, haddr_t *addr_p)
HDmemset(&fh->cache_info, 0, sizeof(H5AC_info_t));
/* Initialize shared fractal heap info */
- if(H5HF_shared_init(f, fh, type) < 0)
+ if(H5HF_shared_init(fh, cparam) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create shared fractal heap info")
/* Allocate space for the header on disk */
@@ -250,7 +173,7 @@ H5HF_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t size,
* Load the fractal heap header.
*/
if(NULL == (fh = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, addr, NULL, NULL, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load fractal heap header")
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap header")
/* Get the pointer to the shared fractal heap info */
shared = H5RC_GET_OBJ(fh->shared);
@@ -258,13 +181,29 @@ H5HF_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t size,
/* Check if object is large enough to be standalone */
if(size >= shared->standalone_size) {
+HDfprintf(stderr, "%s: size = %Zu\n", FUNC, size);
+HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "standalone blocks not supported yet")
} /* end if */
else {
+ /* Check if we are in "append only" mode, or if there's enough room for the object */
+ if(shared->write_once) {
+HDfprintf(stderr, "%s: size = %Zu\n", FUNC, size);
+HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "'write once' managed blocks not supported yet")
+ } /* end if */
+ else if(size <= shared->total_man_free) {
+HDfprintf(stderr, "%s: size = %Zu\n", FUNC, size);
+HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "allocating internal managed blocks not supported yet")
+ } /* end if */
+ else {
+ /* Allocate space at end of heap */
+ if(H5HF_man_alloc_end(shared, size, obj, id) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate space at end of managed blocks")
+ } /* end else */
} /* end else */
done:
if(fh && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, addr, fh, hdr_flags) < 0)
- HDONE_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release fractal heap header")
+ HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release fractal heap header")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_insert() */
diff --git a/src/H5HFcache.c b/src/H5HFcache.c
index 9544242..c20d05d 100644
--- a/src/H5HFcache.c
+++ b/src/H5HFcache.c
@@ -107,7 +107,7 @@ H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *ud
size_t size; /* Header size */
uint8_t *buf = NULL; /* Temporary buffer */
uint8_t *p; /* Pointer into raw data buffer */
- H5HF_type_t heap_type; /* Type of heap */
+ H5HF_create_t cparam; /* Creation parameters for heap */
uint32_t metadata_chksum; /* Metadata checksum value */
H5HF_t *ret_value; /* Return value */
@@ -155,14 +155,21 @@ H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *ud
if(metadata_chksum != 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect metadata checksum for fractal heap header")
- /* Fractal heap type */
- heap_type = *p++;
+ /* Heap address mapping */
+ cparam.addrmap = *p++;
HDassert(H5HF_ABSOLUTE == 0);
- if(heap_type > H5HF_MAPPED)
+ if(cparam.addrmap > H5HF_MAPPED)
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect fractal heap type")
+ /* Min. size of standalone objects */
+ UINT32DECODE(p, cparam.standalone_size);
+
+ /* Size of fixed-length objects in heap */
+ UINT32DECODE(p, cparam.fixed_len_size);
+
/* Initialize shared fractal heap info */
- if(H5HF_shared_init(f, fh, heap_type) < 0)
+ HDassert((size_t)(p - buf) == size);
+ if(H5HF_shared_init(fh, &cparam) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't create shared fractal heap info")
/* Set return value */
@@ -238,8 +245,14 @@ H5HF_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5H
HDmemset(p, 0, 4);
p += 4;
- /* Fractal heap type */
- *p++ = shared->type;
+ /* Heap address mapping */
+ *p++ = shared->addrmap;
+
+ /* Min. size of standalone objects */
+ UINT32ENCODE(p, shared->standalone_size);
+
+ /* Size of fixed-length objects in heap */
+ UINT32ENCODE(p, shared->fixed_len_size);
/* Write the B-tree header. */
HDassert((size_t)(p - buf) == size);
diff --git a/src/H5HFdbg.c b/src/H5HFdbg.c
index cb6476c..4216e96 100644
--- a/src/H5HFdbg.c
+++ b/src/H5HFdbg.c
@@ -115,10 +115,16 @@ H5HF_hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent,
* Print the values.
*/
HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
- "Heap addressing method:",
- ((shared->type) == H5HF_ABSOLUTE ? "Absolute" :
- ((shared->type) == H5HF_MAPPED ? "Mapped" :
+ "Heap address mapping method:",
+ ((shared->addrmap) == H5HF_ABSOLUTE ? "Absolute" :
+ ((shared->addrmap) == H5HF_MAPPED ? "Mapped" :
"Unknown!")));
+ HDfprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth,
+ "Min. size of standalone object:",
+ (unsigned long)shared->standalone_size);
+ HDfprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth,
+ "Fixed length object size:",
+ (unsigned long)shared->fixed_len_size);
done:
if(fh && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, addr, fh, H5AC__NO_FLAGS_SET) < 0)
diff --git a/src/H5HFint.c b/src/H5HFint.c
new file mode 100644
index 0000000..83bb780
--- /dev/null
+++ b/src/H5HFint.c
@@ -0,0 +1,197 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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: H5HFint.c
+ * Feb 24 2006
+ * Quincey Koziol <koziol@ncsa.uiuc.edu>
+ *
+ * Purpose: "Internal" routines for fractal heaps.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5HF_PACKAGE /*suppress error about including H5HFpkg */
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5HFpkg.h" /* Fractal heaps */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5MFprivate.h" /* File memory management */
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+static herr_t H5HF_shared_free(void *_shared);
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* Declare a free list to manage the H5HF_shared_t struct */
+H5FL_DEFINE_STATIC(H5HF_shared_t);
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_shared_init
+ *
+ * Purpose: Allocate & initialize shared fractal heap info
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 24 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_shared_init(H5HF_t *fh, H5HF_create_t *cparam)
+{
+ H5HF_shared_t *shared = NULL; /* Shared fractal heap information */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_shared_init)
+
+ /* Allocate space for the shared information */
+ if(NULL == (shared = H5FL_CALLOC(H5HF_shared_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fractal heap shared information")
+
+ /* Set the creation parameters for the heap */
+ shared->addrmap = cparam->addrmap;
+ shared->standalone_size = cparam->standalone_size;
+ shared->fixed_len_size = cparam->fixed_len_size;
+
+ /* Make shared B-tree info reference counted */
+ if(NULL == (fh->shared = H5RC_create(shared, H5HF_shared_free)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create ref-count wrapper for shared fractal heap info")
+
+done:
+ if(ret_value < 0)
+ if(shared)
+ H5HF_shared_free(shared);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_shared_init() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_shared_free
+ *
+ * Purpose: Free shared fractal heap info
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 24 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_shared_free(void *_shared)
+{
+ H5HF_shared_t *shared = (H5HF_shared_t *)_shared;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_shared_free)
+
+ /* Sanity check */
+ HDassert(shared);
+
+ /* Free the shared info itself */
+ H5FL_FREE(H5HF_shared_t, shared);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5HF_shared_free() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_alloc_end
+ *
+ * Purpose: Allocate space for an object at the end of the heap
+ *
+ * Return: Non-negative on success (with heap ID of new object
+ * filled in), negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 27 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_man_alloc_end(H5HF_shared_t *shared, size_t size, const void *obj,
+ void *id/*out*/)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_alloc_end)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(shared);
+ HDassert(size > 0);
+ HDassert(obj);
+ HDassert(id);
+
+ /* Check if this is the first object in the heap */
+ if(shared->next_man_block == 0) {
+ if(size /* + H5HF_DIRECT_OVERHEAD */ <= shared->man_dtable_info.start_block_size) {
+ } /* end if */
+ else {
+ } /* end else */
+#ifdef QAK
+HDfprintf(stderr, "%s: size = %Zu\n", FUNC, size);
+HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "allocating first object not supported yet")
+#endif /* QAK */
+ } /* end if */
+ else {
+HDfprintf(stderr, "%s: size = %Zu\n", FUNC, size);
+HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "allocating objects at end of heap not supported yet")
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_alloc_end() */
+
diff --git a/src/H5HFpkg.h b/src/H5HFpkg.h
index d311aff..57671c0 100644
--- a/src/H5HFpkg.h
+++ b/src/H5HFpkg.h
@@ -54,7 +54,9 @@
+ 4 /* Metadata checksum */ \
\
/* Fractal heap header specific fields */ \
- + 1 /* Heap type */ \
+ + 1 /* Address mapping */ \
+ + 4 /* Min. size of standalone object */ \
+ + 4 /* Length of fixed-size objects */ \
)
/****************************/
@@ -99,9 +101,9 @@ typedef struct H5HF_shared_t {
H5HF_dtable_param_t std_dtable_info; /* Doubling-table info for standalone objects */
/* Information set by user */
- H5HF_type_t type; /* Type of address mapping */
- size_t standalone_size; /* Size of object to store standalone */
- size_t fixed_len_size; /* Size of objects (only for heaps w/fixed-length objects) */
+ H5HF_addrmap_t addrmap; /* Type of address mapping */
+ uint32_t standalone_size; /* Size of object to store standalone */
+ uint32_t fixed_len_size; /* Size of objects (only for heaps w/fixed-length objects) */
/* Information derived from user parameters */
hbool_t fixed_len_obj; /* Are objects in the heap fixed length? */
@@ -136,7 +138,11 @@ H5FL_EXTERN(H5HF_t);
/******************************/
/* Routines for managing shared fractal heap info */
-H5_DLL herr_t H5HF_shared_init(H5F_t *f, H5HF_t *fh, H5HF_type_t type);
+H5_DLL herr_t H5HF_shared_init(H5HF_t *fh, H5HF_create_t *cparam);
+
+/* Routines for allocating space */
+herr_t H5HF_man_alloc_end(H5HF_shared_t *shared, size_t size, const void *obj,
+ void *id/*out*/);
/* Metadata cache callbacks */
H5_DLL herr_t H5HF_cache_hdr_dest(H5F_t *f, H5HF_t *b);
@@ -147,8 +153,8 @@ H5_DLL herr_t H5HF_hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr,
/* Testing routines */
#ifdef H5HF_TESTING
-H5_DLL herr_t H5HF_get_addrmap_test(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr,
- H5HF_type_t *heap_type);
+H5_DLL herr_t H5HF_get_cparam_test(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr,
+ H5HF_create_t *cparam);
#endif /* H5HF_TESTING */
#endif /* _H5HFpkg_H */
diff --git a/src/H5HFprivate.h b/src/H5HFprivate.h
index 49c11c9..62334fa 100644
--- a/src/H5HFprivate.h
+++ b/src/H5HFprivate.h
@@ -45,7 +45,16 @@
typedef enum {
H5HF_ABSOLUTE, /* The heap uses absolute internal addressing */
H5HF_MAPPED /* The heap maps internal addresses to allow compaction */
-} H5HF_type_t;
+} H5HF_addrmap_t;
+
+/* Fractal heap creation parameters */
+typedef struct H5HF_create_t {
+ H5HF_addrmap_t addrmap; /* Type of address mapping for objects in heap */
+ uint32_t standalone_size; /* Size of object to store standalone */
+ /* (i.e. max. size of object to manage) */
+ uint32_t fixed_len_size; /* Size of objects (0 means variable-sized objects) */
+ /* (only for heaps w/fixed-length objects) */
+} H5HF_create_t;
/*****************************/
@@ -55,7 +64,7 @@ typedef enum {
/***************************************/
/* Library-private Function Prototypes */
/***************************************/
-H5_DLL herr_t H5HF_create(H5F_t *f, hid_t dxpl_id, H5HF_type_t type,
+H5_DLL herr_t H5HF_create(H5F_t *f, hid_t dxpl_id, H5HF_create_t *cparam,
haddr_t *addr_p);
H5_DLL herr_t H5HF_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t size,
const void *obj, void *id/*out*/);
diff --git a/src/H5HFtest.c b/src/H5HFtest.c
index e9a3eeb..ef14b2b 100644
--- a/src/H5HFtest.c
+++ b/src/H5HFtest.c
@@ -64,9 +64,9 @@
/*-------------------------------------------------------------------------
- * Function: H5HF_get_addrmap_test
+ * Function: H5HF_get_cparam_test
*
- * Purpose: Retrieve the address mapping type
+ * Purpose: Retrieve the parameters used to create the fractal heap
*
* Return: Success: non-negative
*
@@ -78,18 +78,18 @@
*-------------------------------------------------------------------------
*/
herr_t
-H5HF_get_addrmap_test(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr, H5HF_type_t *heap_type)
+H5HF_get_cparam_test(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr, H5HF_create_t *cparam)
{
H5HF_t *fh = NULL; /* Pointer to the B-tree header */
H5HF_shared_t *shared; /* Shared fractal heap information */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5HF_get_addrmap_test)
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_get_cparam_test)
/* Check arguments. */
HDassert(f);
HDassert(H5F_addr_defined(fh_addr));
- HDassert(heap_type);
+ HDassert(cparam);
/* Look up the fractal heap header */
if(NULL == (fh = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, fh_addr, NULL, NULL, H5AC_READ)))
@@ -99,8 +99,10 @@ H5HF_get_addrmap_test(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr, H5HF_type_t *hea
shared = H5RC_GET_OBJ(fh->shared);
HDassert(shared);
- /* Get fractal heap address mapping */
- *heap_type = shared->type;
+ /* Get fractal heap creation parameters */
+ cparam->addrmap = shared->addrmap;
+ cparam->standalone_size = shared->standalone_size;
+ cparam->fixed_len_size = shared->fixed_len_size;
done:
/* Release fractal heap header node */
@@ -108,5 +110,5 @@ done:
HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap header info")
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5HF_get_addrmap_test() */
+} /* H5HF_get_cparam_test() */
diff --git a/src/Makefile.am b/src/Makefile.am
index dc3629a..0a3abbf 100755
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -37,9 +37,8 @@ libhdf5_la_LDFLAGS= -version-info $(LT_VERS_INTERFACE):$(LT_VERS_REVISION):$(LT_
MOSTLYCLEANFILES=H5Tinit.c
# library sources
-libhdf5_la_SOURCES= H5.c H5A.c H5AC.c H5B.c H5Bcache.c H5B2.c H5B2cache.c \
- H5B2dbg.c \
- H5B2test.c \
+libhdf5_la_SOURCES= H5.c H5A.c H5AC.c H5B.c H5Bcache.c \
+ H5B2.c H5B2cache.c H5B2dbg.c H5B2int.c H5B2test.c \
H5C.c \
H5D.c \
H5Dcompact.c \
@@ -55,7 +54,7 @@ libhdf5_la_SOURCES= H5.c H5A.c H5AC.c H5B.c H5Bcache.c H5B2.c H5B2cache.c \
H5Gstab.c \
H5Gtest.c \
H5Gtraverse.c \
- H5HF.c H5HFcache.c H5HFdbg.c H5HFtest.c \
+ H5HF.c H5HFcache.c H5HFdbg.c H5HFint.c H5HFtest.c \
H5HG.c H5HGdbg.c H5HL.c H5HLdbg.c H5HP.c H5I.c H5MF.c H5MM.c \
H5MP.c H5MPtest.c \
H5O.c \
diff --git a/src/Makefile.in b/src/Makefile.in
index 1b5ea41..dd8ec8b 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -83,7 +83,7 @@ libLTLIBRARIES_INSTALL = $(INSTALL)
LTLIBRARIES = $(lib_LTLIBRARIES)
libhdf5_la_LIBADD =
am_libhdf5_la_OBJECTS = H5.lo H5A.lo H5AC.lo H5B.lo H5Bcache.lo \
- H5B2.lo H5B2cache.lo H5B2dbg.lo H5B2test.lo H5C.lo H5D.lo \
+ H5B2.lo H5B2cache.lo H5B2dbg.lo H5B2int.lo H5B2test.lo H5C.lo H5D.lo \
H5Dcompact.lo H5Dcontig.lo H5Defl.lo H5Dio.lo H5Distore.lo \
H5Dmpio.lo H5Doh.lo H5Dselect.lo H5Dtest.lo H5E.lo H5F.lo \
H5Fdbg.lo H5Fmount.lo H5Fsfile.lo H5Fsuper.lo H5FD.lo \
@@ -93,7 +93,7 @@ am_libhdf5_la_OBJECTS = H5.lo H5A.lo H5AC.lo H5B.lo H5Bcache.lo \
H5FPclient.lo H5FPserver.lo H5FS.lo H5G.lo H5Gent.lo \
H5Glink.lo H5Gloc.lo H5Gname.lo H5Gnode.lo H5Gobj.lo H5Goh.lo \
H5Gstab.lo H5Gtest.lo H5Gtraverse.lo H5HF.lo H5HFcache.lo \
- H5HFdbg.lo H5HFtest.lo H5HG.lo H5HGdbg.lo H5HL.lo H5HLdbg.lo \
+ H5HFdbg.lo H5HFint.lo H5HFtest.lo H5HG.lo H5HGdbg.lo H5HL.lo H5HLdbg.lo \
H5HP.lo H5I.lo H5MF.lo H5MM.lo H5MP.lo H5MPtest.lo H5O.lo \
H5Oattr.lo H5Obogus.lo H5Ocache.lo H5Ocont.lo H5Odtype.lo \
H5Oefl.lo H5Ofill.lo H5Oginfo.lo H5Olayout.lo H5Olinfo.lo \
@@ -389,9 +389,8 @@ libhdf5_la_LDFLAGS = -version-info $(LT_VERS_INTERFACE):$(LT_VERS_REVISION):$(LT
MOSTLYCLEANFILES = H5Tinit.c
# library sources
-libhdf5_la_SOURCES = H5.c H5A.c H5AC.c H5B.c H5Bcache.c H5B2.c H5B2cache.c \
- H5B2dbg.c \
- H5B2test.c \
+libhdf5_la_SOURCES = H5.c H5A.c H5AC.c H5B.c H5Bcache.c \
+ H5B2.c H5B2cache.c H5B2dbg.c H5B2int.c H5B2test.c \
H5C.c \
H5D.c \
H5Dcompact.c \
@@ -407,7 +406,7 @@ libhdf5_la_SOURCES = H5.c H5A.c H5AC.c H5B.c H5Bcache.c H5B2.c H5B2cache.c \
H5Gstab.c \
H5Gtest.c \
H5Gtraverse.c \
- H5HF.c H5HFcache.c H5HFdbg.c H5HFtest.c \
+ H5HF.c H5HFcache.c H5HFdbg.c H5HFint.c H5HFtest.c \
H5HG.c H5HGdbg.c H5HL.c H5HLdbg.c H5HP.c H5I.c H5MF.c H5MM.c \
H5MP.c H5MPtest.c \
H5O.c \
@@ -567,6 +566,7 @@ distclean-compile:
@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)/H5B2int.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5B2test.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Bcache.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5C.Plo@am__quote@
@@ -618,6 +618,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HF.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFcache.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFdbg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFint.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFtest.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HG.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HGdbg.Plo@am__quote@
diff --git a/test/fheap.c b/test/fheap.c
index b1fce69..1a9f8e9 100644
--- a/test/fheap.c
+++ b/test/fheap.c
@@ -54,7 +54,7 @@ test_create(hid_t fapl)
hid_t file = -1; /* File ID */
char filename[1024]; /* Filename to use */
H5F_t *f = NULL; /* Internal file object pointer */
- H5HF_type_t heap_type, test_heap_type; /* Type of address mapping for fractal heap */
+ H5HF_create_t cparam, test_cparam; /* Creation parameters for heap */
haddr_t fh_addr; /* Address of fractal heap created */
/* Set the filename to use for this test (dependent on fapl) */
@@ -72,8 +72,10 @@ test_create(hid_t fapl)
* Test fractal heap creation (w/absolute address mapping)
*/
TESTING("Fractal heap creation (w/absolute address mapping)");
- heap_type = H5HF_ABSOLUTE;
- if(H5HF_create(f, H5P_DATASET_XFER_DEFAULT, heap_type, &fh_addr/*out*/) < 0)
+ cparam.addrmap = H5HF_ABSOLUTE;
+ cparam.standalone_size = 64 * 1024;
+ cparam.fixed_len_size = 0;
+ if(H5HF_create(f, H5P_DATASET_XFER_DEFAULT, &cparam, &fh_addr/*out*/) < 0)
FAIL_STACK_ERROR
if(!H5F_addr_defined(fh_addr))
FAIL_STACK_ERROR
@@ -81,10 +83,10 @@ test_create(hid_t fapl)
/* Query the type of address mapping */
TESTING("Query absolute address mapping setting");
- test_heap_type = H5HF_MAPPED;
- if(H5HF_get_addrmap_test(f, H5P_DATASET_XFER_DEFAULT, fh_addr, &test_heap_type) < 0)
+ HDmemset(&test_cparam, 0, sizeof(H5HF_create_t));
+ if(H5HF_get_cparam_test(f, H5P_DATASET_XFER_DEFAULT, fh_addr, &test_cparam) < 0)
FAIL_STACK_ERROR
- if(test_heap_type != heap_type)
+ if(HDmemcmp(&cparam, &test_cparam, sizeof(H5HF_create_t)))
FAIL_STACK_ERROR
PASSED()
@@ -92,8 +94,10 @@ test_create(hid_t fapl)
* Test fractal heap creation (w/mapped address mapping)
*/
TESTING("Fractal heap creation (w/mapped address mapping)");
- heap_type = H5HF_MAPPED;
- if(H5HF_create(f, H5P_DATASET_XFER_DEFAULT, heap_type, &fh_addr/*out*/) < 0)
+ cparam.addrmap = H5HF_MAPPED;
+ cparam.standalone_size = 64 * 1024;
+ cparam.fixed_len_size = 0;
+ if(H5HF_create(f, H5P_DATASET_XFER_DEFAULT, &cparam, &fh_addr/*out*/) < 0)
FAIL_STACK_ERROR
if(!H5F_addr_defined(fh_addr))
FAIL_STACK_ERROR
@@ -101,10 +105,10 @@ test_create(hid_t fapl)
/* Query the type of address mapping */
TESTING("Query mapped address mapping setting");
- test_heap_type = H5HF_ABSOLUTE;
- if(H5HF_get_addrmap_test(f, H5P_DATASET_XFER_DEFAULT, fh_addr, &test_heap_type) < 0)
+ HDmemset(&test_cparam, 0, sizeof(H5HF_create_t));
+ if(H5HF_get_cparam_test(f, H5P_DATASET_XFER_DEFAULT, fh_addr, &test_cparam) < 0)
FAIL_STACK_ERROR
- if(test_heap_type != heap_type)
+ if(HDmemcmp(&cparam, &test_cparam, sizeof(H5HF_create_t)))
FAIL_STACK_ERROR
PASSED()
@@ -144,6 +148,7 @@ test_abs_insert_first(hid_t fapl)
hid_t dxpl = H5P_DATASET_XFER_DEFAULT; /* DXPL to use */
char filename[1024]; /* Filename to use */
H5F_t *f = NULL; /* Internal file object pointer */
+ H5HF_create_t cparam; /* Creation parameters for heap */
haddr_t fh_addr; /* Address of fractal heap created */
unsigned char obj[10]; /* Buffer for object to insert */
haddr_t heap_id; /* Heap ID for object inserted */
@@ -162,7 +167,10 @@ test_abs_insert_first(hid_t fapl)
STACK_ERROR
/* Create absolute heap */
- if(H5HF_create(f, dxpl, H5HF_ABSOLUTE, &fh_addr/*out*/) < 0)
+ cparam.addrmap = H5HF_ABSOLUTE;
+ cparam.standalone_size = 64 * 1024;
+ cparam.fixed_len_size = 0;
+ if(H5HF_create(f, dxpl, &cparam, &fh_addr/*out*/) < 0)
FAIL_STACK_ERROR
if(!H5F_addr_defined(fh_addr))
FAIL_STACK_ERROR