summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2005-03-04 22:22:34 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2005-03-04 22:22:34 (GMT)
commitc153ca4d5e5bb7c3bff99b44494f632b4cbf2759 (patch)
treef42404064ea674a1fa6a1d9cb35e2373e48190d4
parent831be556f4cca3b5f9380757ce4f09b40f13dd4b (diff)
downloadhdf5-c153ca4d5e5bb7c3bff99b44494f632b4cbf2759.zip
hdf5-c153ca4d5e5bb7c3bff99b44494f632b4cbf2759.tar.gz
hdf5-c153ca4d5e5bb7c3bff99b44494f632b4cbf2759.tar.bz2
[svn-r10149] Purpose:
Bug fix & new feature Description: Fix a couple of off-by-one errors in assertions (code was actually correct) for 3 node redistributions. Remove "old" node removal code that is unused now. Add more tests that verify that 2-node and 3-node redistributions are working correctly for removals. Platforms tested: FreeBSD 4.11 (sleipnir) Solaris 2.9 (shanti)
-rw-r--r--src/H5B2.c298
-rw-r--r--test/btree2.c170
2 files changed, 172 insertions, 296 deletions
diff --git a/src/H5B2.c b/src/H5B2.c
index 04109ad..b185fa8 100644
--- a/src/H5B2.c
+++ b/src/H5B2.c
@@ -1295,7 +1295,7 @@ H5B2_redistribute3(H5F_t *f, hid_t dxpl_id, unsigned depth, H5B2_internal_t *int
unsigned left_nrec_move = *left_nrec-new_left_nrec; /* Number of records to move out of left node */
/* Sanity check */
- HDassert(new_right_nrec>*right_nrec);
+ HDassert(new_right_nrec >= *right_nrec);
/* 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);
@@ -1334,7 +1334,7 @@ H5B2_redistribute3(H5F_t *f, hid_t dxpl_id, unsigned depth, H5B2_internal_t *int
unsigned right_nrec_move = *right_nrec-new_right_nrec; /* Number of records to move out of right node */
/* Sanity check */
- HDassert(new_left_nrec>*left_nrec);
+ HDassert(new_left_nrec >= *left_nrec);
/* 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);
@@ -2763,296 +2763,6 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5B2_index() */
-#ifdef OLD_WAY
-
-/*-------------------------------------------------------------------------
- * Function: H5B2_remove
- *
- * Purpose: Removes a record from a B-tree.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 25 2005
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5B2_remove(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr,
- void *udata)
-{
- H5B2_t *bt2=NULL; /* Pointer to the B-tree header */
- H5RC_t *bt2_shared=NULL; /* Pointer to ref-counter for shared B-tree info */
- H5B2_shared_t *shared; /* Pointer to B-tree's shared information */
- hbool_t incr_rc=FALSE; /* Flag to indicate that we've incremented the B-tree's shared info reference count */
- H5AC_info_t *parent_cache_info=NULL;/* Parent node's cache info */
- haddr_t parent_addr=HADDR_UNDEF;/* Address of parent which contain's node pointer to current node */
- void *parent_ptr=NULL; /* Pointer to parent structure in memory */
- H5B2_node_ptr_t *curr_node_ptr=NULL;/* Pointer to node pointer info for current node (in parent node) */
- H5B2_leaf_t *leaf=NULL; /* Pointer to leaf node */
- haddr_t leaf_addr=HADDR_UNDEF; /* Leaf address on disk */
- unsigned leaf_unprotect_flags=H5C__NO_FLAGS_SET; /* Flags for unprotecting leaf node */
- unsigned depth; /* Depth of B-tree */
- int cmp; /* Comparison value of records */
- unsigned idx; /* Location of record which matches key */
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI(H5B2_remove, FAIL)
-
- /* Check arguments. */
- HDassert(f);
- HDassert(type);
- HDassert(H5F_addr_defined(addr));
-
- /* Look up the B-tree header */
- if (NULL == (bt2 = H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, addr, type, NULL, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree header")
-
- /* Safely grab pointer to reference counted shared B-tree info, so we can release the B-tree header if necessary */
- bt2_shared=bt2->shared;
- H5RC_INC(bt2_shared);
- incr_rc=TRUE;
-
- /* Get the pointer to the shared B-tree info */
- shared=H5RC_GET_OBJ(bt2_shared);
- HDassert(shared);
-
- /* Get B-tree depth */
- depth = bt2->depth;
-
- /* Check for empty B-tree */
- if(bt2->root.all_nrec==0) {
- /* Release B-tree header node */
- if (H5AC_unprotect(f, dxpl_id, H5AC_BT2_HDR, addr, bt2, H5AC__NO_FLAGS_SET) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree header info")
- bt2=NULL;
-
- /* Indicate error */
- HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "record is not in B-tree")
- } /* end if */
-
- /* Set initial "parent" information to the B-tree header */
- parent_cache_info=&(bt2->cache_info);
- parent_addr=addr;
- parent_ptr=bt2;
-
- /* Set initial node pointer for "current" node */
- curr_node_ptr=&(bt2->root);
-
- /* Check for non-trivial B-tree */
- if(depth>0) {
- H5B2_internal_t *internal; /* Pointer to internal node in B-tree */
- H5AC_info_t *curr_cache_info=NULL; /* Current node's cache info */
- haddr_t curr_addr=HADDR_UNDEF; /* Address of current node */
- void *curr_ptr=NULL; /* Pointer to current structure in memory */
- H5B2_node_ptr_t *child_node_ptr=NULL; /* Pointer to node pointer info for child node */
-
- /* Find correct leaf to remove node from */
- while(depth>0) {
- unsigned retries; /* Number of times to attempt redistribution */
-
- /* Lock B-tree current 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")
-
-#ifdef H5B2_DEBUG
- H5B2_assert_internal((hsize_t)0,shared,internal);
-#endif /* H5B2_DEBUG */
-
- /* Set information for current (root) node */
- curr_cache_info=&(internal->cache_info);
- curr_addr=curr_node_ptr->addr;
- curr_ptr=internal;
-
- /* Locate node pointer for child */
- cmp=H5B2_locate_record(shared->type,internal->nrec,shared->nat_off,internal->int_native,udata,&idx);
- if(cmp>0)
- idx++;
-
- /* Handle deleting a record from an internal node */
- if(cmp==0) {
-HDfprintf(stderr,"%s: Deleting record in internal node of non-trival B-tree!\n",FUNC);
-HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "Can't delete record in B-tree")
- } /* end if */
-
- /* Get node pointer for child */
- child_node_ptr=&(internal->node_ptrs[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 merge */
- retries = 2;
-
- /* Preemptively merge/redistribute a node we will enter */
- while((depth==1 && child_node_ptr->node_nrec==shared->merge_leaf_nrec) ||
- (depth>1 && child_node_ptr->node_nrec==shared->merge_int_nrec)) {
- /* Attempt to redistribute records among children */
- if(idx==0) { /* Left-most child */
- if(retries>0 && ((depth==1 && internal->node_ptrs[idx+1].node_nrec>shared->merge_leaf_nrec) ||
- (depth>1 && internal->node_ptrs[idx+1].node_nrec>shared->merge_int_nrec))) {
-HDfprintf(stderr,"%s: Performing 2 node redistribution in B-tree!\n",FUNC);
- if(H5B2_redistribute2(f,dxpl_id,depth,internal,(unsigned)idx)<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records")
- } /* end if */
- else {
-HDfprintf(stderr,"%s: Need to perform 2->1 node merge in B-tree!\n",FUNC);
-HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "Can't delete record in B-tree")
- } /* end else */
- } /* end if */
- else if((unsigned)idx==internal->nrec) { /* Right-most child */
- if(retries>0 && ((depth==1 && internal->node_ptrs[idx-1].node_nrec>shared->merge_leaf_nrec) ||
- (depth>1 && internal->node_ptrs[idx-1].node_nrec>shared->merge_int_nrec))) {
-HDfprintf(stderr,"%s: Performing 2 node redistribution in B-tree!\n",FUNC);
- if(H5B2_redistribute2(f,dxpl_id,depth,internal,(unsigned)(idx-1))<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records")
- } /* end if */
- else {
-HDfprintf(stderr,"%s: Need to perform 2->1 node merge in B-tree!\n",FUNC);
-HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "Can't delete record in B-tree")
- } /* end else */
- } /* end if */
- else { /* Middle child */
- if(retries>0 && ((depth==1 &&
- ((internal->node_ptrs[idx+1].node_nrec>shared->merge_leaf_nrec) ||
- (internal->node_ptrs[idx-1].node_nrec>shared->merge_leaf_nrec))) ||
- (depth>1 &&
- ((internal->node_ptrs[idx+1].node_nrec>shared->merge_int_nrec) ||
- (internal->node_ptrs[idx-1].node_nrec>shared->merge_int_nrec))))) {
-HDfprintf(stderr,"%s: Performing 3 node redistribution in B-tree!\n",FUNC);
- if(H5B2_redistribute3(f,dxpl_id,depth,internal,(unsigned)idx)<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records")
- } /* end if */
- else {
-HDfprintf(stderr,"%s: Need to perform 3->2 node merge in B-tree!\n",FUNC);
-HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "Can't delete record in B-tree")
- } /* end else */
- } /* end else */
-
- /* Locate node pointer for child (after merge/redistribute) */
-/* 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++;
-
- /* Update child_node_ptr (to reflect change in location from merge/redistribution) */
- child_node_ptr=&(internal->node_ptrs[idx]);
-
- /* Decrement the number of redistribution retries left */
- retries--;
- } /* end while */
-
- /* Update record count (in parent) */
- curr_node_ptr->all_nrec--;
-
- /* Mark parent node as dirty */
- parent_cache_info->is_dirty = TRUE;
-
-#ifdef H5B2_DEBUG
- if(parent_cache_info->type==H5AC_BT2_INT)
- H5B2_assert_internal((hsize_t)0,shared,parent_ptr);
-#endif /* H5B2_DEBUG */
-
- /* Unlock parent node (possibly the B-tree header) */
- if (H5AC_unprotect(f, dxpl_id, parent_cache_info->type, parent_addr, parent_ptr, H5AC__NO_FLAGS_SET) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree info")
-
- /* Transition "current" info into "parent" info */
- parent_cache_info = curr_cache_info;
- parent_addr = curr_addr;
- parent_ptr = curr_ptr;
-
- /* Transition "child" node pointer to "current" node pointer */
- curr_node_ptr = child_node_ptr;
-
- /* Decrement depth of current node */
- depth--;
- } /* end while */
- } /* end if */
-
- /* Must have a leaf node with enough space to insert a record now */
- HDassert(H5F_addr_defined(curr_node_ptr->addr));
- /* "Root only" B-tree allowed to have less records in it's node */
- if(depth>0)
- HDassert(curr_node_ptr->node_nrec > shared->merge_leaf_nrec);
-
- /* Look up the B-tree leaf 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")
-
- /* 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 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_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->cache_info.is_dirty = TRUE;
-
- if(leaf->nrec>0) {
- /* Pack record out of leaf */
- HDmemmove(H5B2_LEAF_NREC(leaf,shared,idx),H5B2_LEAF_NREC(leaf,shared,idx+1),shared->type->nrec_size*(leaf->nrec-idx));
- } /* end if */
- else {
- /* Sanity check - we are only allowed to delete a leaf when it's the root node */
- HDassert(depth == 0);
- HDassert(parent_cache_info->type == H5AC_BT2_HDR);
-
- /* 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_unprotect_flags = H5C__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->all_nrec--;
- curr_node_ptr->node_nrec--;
-
- /* Mark parent node as dirty */
- parent_cache_info->is_dirty = TRUE;
-
-done:
- /* Release parent of leaf node */
- if(parent_ptr) {
- /* Unlock parent node (possibly the B-tree header) */
- if (H5AC_unprotect(f, dxpl_id, parent_cache_info->type, parent_addr, parent_ptr, H5AC__NO_FLAGS_SET) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree info")
- } /* end if */
-
- /* Release the B-tree leaf node */
- if (leaf) {
-#ifdef H5B2_DEBUG
-H5B2_assert_leaf(shared,leaf);
-#endif /* H5B2_DEBUG */
- if(H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, leaf_addr, leaf, leaf_unprotect_flags) < 0)
- HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree leaf node")
- } /* end if */
-
- /* Check if we need to decrement the reference count for the B-tree's shared info */
- if(incr_rc)
- H5RC_DEC(bt2_shared);
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5B2_remove() */
-#else /* OLD_WAY */
/*-------------------------------------------------------------------------
* Function: H5B2_remove_leaf
@@ -3216,7 +2926,6 @@ HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "Can't delete record in B-tree")
if(idx==0) { /* Left-most child */
if(retries>0 && ((depth==1 && internal->node_ptrs[idx+1].node_nrec>shared->merge_leaf_nrec) ||
(depth>1 && internal->node_ptrs[idx+1].node_nrec>shared->merge_int_nrec))) {
-HDfprintf(stderr,"%s: Performing 2 node redistribution in B-tree!\n",FUNC);
if(H5B2_redistribute2(f,dxpl_id,depth,internal,(unsigned)idx)<0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records")
} /* end if */
@@ -3228,7 +2937,6 @@ HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "Can't delete record in B-tree")
else if((unsigned)idx==internal->nrec) { /* Right-most child */
if(retries>0 && ((depth==1 && internal->node_ptrs[idx-1].node_nrec>shared->merge_leaf_nrec) ||
(depth>1 && internal->node_ptrs[idx-1].node_nrec>shared->merge_int_nrec))) {
-HDfprintf(stderr,"%s: Performing 2 node redistribution in B-tree!\n",FUNC);
if(H5B2_redistribute2(f,dxpl_id,depth,internal,(unsigned)(idx-1))<0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records")
} /* end if */
@@ -3244,7 +2952,6 @@ HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "Can't delete record in B-tree")
(depth>1 &&
((internal->node_ptrs[idx+1].node_nrec>shared->merge_int_nrec) ||
(internal->node_ptrs[idx-1].node_nrec>shared->merge_int_nrec))))) {
-HDfprintf(stderr,"%s: Performing 3 node redistribution in B-tree!\n",FUNC);
if(H5B2_redistribute3(f,dxpl_id,depth,internal,(unsigned)idx)<0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records")
} /* end if */
@@ -3350,7 +3057,6 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5B2_remove() */
-#endif /* OLD_WAY */
/*-------------------------------------------------------------------------
diff --git a/test/btree2.c b/test/btree2.c
index b9f28f9..6c6486a 100644
--- a/test/btree2.c
+++ b/test/btree2.c
@@ -2385,6 +2385,175 @@ error:
/*-------------------------------------------------------------------------
+ * Function: test_remove_level1_redistrib
+ *
+ * Purpose: Basic tests for the B-tree v2 code
+ *
+ * Return: Success: 0
+ *
+ * Failure: 1
+ *
+ * Programmer: Quincey Koziol
+ * Friday, March 4, 2005
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_remove_level1_redistrib(hid_t fapl)
+{
+ hid_t file=-1;
+ char filename[1024];
+ H5F_t *f=NULL;
+ hsize_t record; /* Record to insert into tree */
+ hsize_t nrec; /* Number of records in B-tree */
+ haddr_t bt2_addr; /* Address of B-tree created */
+ haddr_t root_addr; /* Address of root of B-tree created */
+ unsigned u; /* Local index variable */
+ herr_t ret; /* Generic error return value */
+
+ h5_fixname(FILENAME[0], fapl, filename, sizeof filename);
+
+ /* Create the file to work on */
+ if ((file=H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR;
+
+ /* Get a pointer to the internal file object */
+ if (NULL==(f=H5I_object(file))) {
+ H5Eprint_stack(H5E_DEFAULT, stdout);
+ TEST_ERROR;
+ }
+
+ /*
+ * Test v2 B-tree creation
+ */
+ if (H5B2_create(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, 512, 8, 100, 40, &bt2_addr/*out*/)<0) {
+ H5_FAILED();
+ H5Eprint_stack(H5E_DEFAULT, stdout);
+ goto error;
+ }
+
+ /* Create level-1 B-tree with 3 leaves */
+ for(u=0; u<INSERT_SPLIT_ROOT_NREC*2; u++) {
+ record=u;
+ if (H5B2_insert(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &record)<0) {
+ H5_FAILED();
+ H5Eprint_stack(H5E_DEFAULT, stdout);
+ goto error;
+ }
+ }
+
+ /* Query the number of records in the B-tree */
+ if (H5B2_get_nrec(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &nrec)<0) {
+ H5_FAILED();
+ H5Eprint_stack(H5E_DEFAULT, stdout);
+ goto error;
+ } /* end if */
+
+ /* Make certain that the # of records is correct */
+ if(nrec != (INSERT_SPLIT_ROOT_NREC*2)) TEST_ERROR;
+
+ /* Query the address of the root node in the B-tree */
+ if (H5B2_get_root_addr(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &root_addr)<0) {
+ H5_FAILED();
+ H5Eprint_stack(H5E_DEFAULT, stdout);
+ goto error;
+ } /* end if */
+
+ /* Make certain that the address of the root node is defined */
+ if(!H5F_addr_defined(root_addr)) TEST_ERROR;
+
+ /* Attempt to remove enough records from right leaf of a level-1 B-tree to force redistribution */
+ TESTING("B-tree remove: redistribute 2 leaves in level-1 B-tree (r->l)");
+ for(u=0; u < (INSERT_SPLIT_ROOT_NREC/2); u++) {
+ record = (INSERT_SPLIT_ROOT_NREC*2)-(u+1);
+ if(H5B2_remove(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &record)<0) {
+ H5_FAILED();
+ H5Eprint_stack(H5E_DEFAULT, stdout);
+ goto error;
+ } /* end if */
+
+ /* Make certain that the record value is correct */
+ if(record != ((INSERT_SPLIT_ROOT_NREC*2)-(u+1))) TEST_ERROR;
+
+ /* Query the number of records in the B-tree */
+ if (H5B2_get_nrec(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &nrec)<0) {
+ H5_FAILED();
+ H5Eprint_stack(H5E_DEFAULT, stdout);
+ goto error;
+ } /* end if */
+
+ /* Make certain that the # of records is correct */
+ if(nrec != ((INSERT_SPLIT_ROOT_NREC*2)-(u+1))) TEST_ERROR;
+ } /* end for */
+
+ PASSED();
+
+ /* Attempt to remove enough records from left leaf of a level-1 B-tree to force redistribution */
+ TESTING("B-tree remove: redistribute 2 leaves in level-1 B-tree (l->r)");
+ for(u=0; u < (INSERT_SPLIT_ROOT_NREC/4); u++) {
+ record = u;
+ if(H5B2_remove(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &record)<0) {
+ H5_FAILED();
+ H5Eprint_stack(H5E_DEFAULT, stdout);
+ goto error;
+ } /* end if */
+
+ /* Make certain that the record value is correct */
+ if(record != u) TEST_ERROR;
+
+ /* Query the number of records in the B-tree */
+ if (H5B2_get_nrec(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &nrec)<0) {
+ H5_FAILED();
+ H5Eprint_stack(H5E_DEFAULT, stdout);
+ goto error;
+ } /* end if */
+
+ /* Make certain that the # of records is correct */
+ if(nrec != (((INSERT_SPLIT_ROOT_NREC*2)-(INSERT_SPLIT_ROOT_NREC/2))-(u+1))) TEST_ERROR;
+ } /* end for */
+
+ PASSED();
+
+ /* Attempt to remove enough records from middle leaf of a level-1 B-tree to force redistribution */
+ TESTING("B-tree remove: redistribute 3 leaves in level-1 B-tree");
+ for(u=0; u < (INSERT_SPLIT_ROOT_NREC/8); u++) {
+ record = ((INSERT_SPLIT_ROOT_NREC/4)*3) + u;
+ if(H5B2_remove(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &record)<0) {
+ H5_FAILED();
+ H5Eprint_stack(H5E_DEFAULT, stdout);
+ goto error;
+ } /* end if */
+
+ /* Make certain that the record value is correct */
+ if(record != (((INSERT_SPLIT_ROOT_NREC/4)*3) + u)) TEST_ERROR;
+
+ /* Query the number of records in the B-tree */
+ if (H5B2_get_nrec(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &nrec)<0) {
+ H5_FAILED();
+ H5Eprint_stack(H5E_DEFAULT, stdout);
+ goto error;
+ } /* end if */
+
+ /* Make certain that the # of records is correct */
+ if(nrec != (((INSERT_SPLIT_ROOT_NREC*2)-(3*(INSERT_SPLIT_ROOT_NREC/4)))-(u+1))) TEST_ERROR;
+ } /* end for */
+
+ PASSED();
+
+ if (H5Fclose(file)<0) TEST_ERROR;
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Fclose(file);
+ } H5E_END_TRY;
+ return 1;
+} /* test_remove_level1_noredistrib() */
+
+
+/*-------------------------------------------------------------------------
* Function: main
*
* Purpose: Test the B-tree v2 code
@@ -2436,6 +2605,7 @@ HDfprintf(stderr,"Uncomment tests!\n");
/* Querying the number of records routine also tested in these routines as well */
nerrors += test_remove_basic(fapl);
nerrors += test_remove_level1_noredistrib(fapl);
+ nerrors += test_remove_level1_redistrib(fapl);
#else /* QAK */
HDfprintf(stderr,"Uncomment tests!\n");
#endif /* QAK */