diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2016-12-02 16:07:04 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2016-12-02 16:07:04 (GMT) |
commit | 64a339183f0e4532597744351548308203e993c8 (patch) | |
tree | ddfff2f15c0f3a01782f191a847665c6eceadd42 /src/H5B2int.c | |
parent | 5d7d029b97b36d1c380cef82d637342921bf3a1d (diff) | |
download | hdf5-64a339183f0e4532597744351548308203e993c8.zip hdf5-64a339183f0e4532597744351548308203e993c8.tar.gz hdf5-64a339183f0e4532597744351548308203e993c8.tar.bz2 |
Bring SWMR support in to the main development branch. (Finally!) More tests
and the tool and API wrappers will be coming in over the weekend.
Diffstat (limited to 'src/H5B2int.c')
-rw-r--r-- | src/H5B2int.c | 2423 |
1 files changed, 321 insertions, 2102 deletions
diff --git a/src/H5B2int.c b/src/H5B2int.c index a8fa59f..47100fd 100644 --- a/src/H5B2int.c +++ b/src/H5B2int.c @@ -37,16 +37,13 @@ #include "H5private.h" /* Generic Functions */ #include "H5B2pkg.h" /* v2 B-trees */ #include "H5Eprivate.h" /* Error handling */ -#include "H5MFprivate.h" /* File memory management */ -#include "H5MMprivate.h" /* Memory management */ #include "H5VMprivate.h" /* Vectors and arrays */ + /****************/ /* Local Macros */ /****************/ -/* Uncomment this macro to enable extra sanity checking */ -/* #define H5B2_DEBUG */ /******************/ /* Local Typedefs */ @@ -61,44 +58,15 @@ /********************/ /* Local Prototypes */ /********************/ +static herr_t H5B2__update_child_flush_depends(H5B2_hdr_t *hdr, hid_t dxpl_id, + unsigned depth, const H5B2_node_ptr_t *node_ptrs, unsigned start_idx, + unsigned end_idx, void *old_parent, void *new_parent); -/* Helper functions */ -static herr_t H5B2__split1(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t 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__redistribute2(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, - H5B2_internal_t *internal, unsigned idx); -static herr_t H5B2__redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, - H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx); -static herr_t H5B2__merge2(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t 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(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t 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(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, - H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx, - void *swap_loc); -static herr_t H5B2__create_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, - H5B2_node_ptr_t *node_ptr, uint16_t depth); -#ifdef H5B2_DEBUG -/* Don't label these with H5_ATTR_PURE or you'll get even more warnings... */ -static herr_t H5B2__assert_leaf(const H5B2_hdr_t *hdr, const H5B2_leaf_t *leaf); -static herr_t H5B2__assert_leaf2(const H5B2_hdr_t *hdr, const H5B2_leaf_t *leaf, const H5B2_leaf_t *leaf2); -static herr_t H5B2__assert_internal(hsize_t parent_all_nrec, const H5B2_hdr_t *hdr, const H5B2_internal_t *internal); -static herr_t H5B2__assert_internal2(hsize_t parent_all_nrec, const H5B2_hdr_t *hdr, const H5B2_internal_t *internal, const 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 */ @@ -137,7 +105,7 @@ H5FL_SEQ_EXTERN(H5B2_node_info_t); */ herr_t H5B2__locate_record(const H5B2_class_t *type, unsigned nrec, size_t *rec_off, - const uint8_t *native, const void *udata, unsigned *idx, int *cmp) + const uint8_t *native, const void *udata, unsigned *idx, int *cmp) { unsigned lo = 0, hi; /* Low & high index values */ unsigned my_idx = 0; /* Final index value */ @@ -179,7 +147,7 @@ done: * *------------------------------------------------------------------------- */ -static herr_t +herr_t H5B2__split1(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, H5B2_node_ptr_t *curr_node_ptr, unsigned *parent_cache_info_flags_ptr, H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx) @@ -195,7 +163,7 @@ H5B2__split1(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, unsigned left_child_flags = H5AC__NO_FLAGS_SET, right_child_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting child nodes */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_STATIC + FUNC_ENTER_PACKAGE /* Check arguments. */ HDassert(hdr); @@ -214,19 +182,20 @@ H5B2__split1(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, /* Create new internal node */ internal->node_ptrs[idx + 1].all_nrec = internal->node_ptrs[idx + 1].node_nrec = 0; - if(H5B2__create_internal(hdr, dxpl_id, &(internal->node_ptrs[idx + 1]), (uint16_t)(depth - 1)) < 0) + if(H5B2__create_internal(hdr, dxpl_id, internal, &(internal->node_ptrs[idx + 1]), (uint16_t)(depth - 1)) < 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 = internal->node_ptrs[idx].addr; - right_addr = internal->node_ptrs[idx + 1].addr; /* Protect both leaves */ - if(NULL == (left_int = H5B2__protect_internal(hdr, dxpl_id, left_addr, internal->node_ptrs[idx].node_nrec, (uint16_t)(depth - 1), H5AC__NO_FLAGS_SET))) + /* (Shadow left node if doing SWMR writes) */ + if(NULL == (left_int = H5B2__protect_internal(hdr, dxpl_id, internal, &internal->node_ptrs[idx], (uint16_t)(depth - 1), hdr->swmr_write, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node") - if(NULL == (right_int = H5B2__protect_internal(hdr, dxpl_id, right_addr, internal->node_ptrs[idx + 1].node_nrec, (uint16_t)(depth - 1), H5AC__NO_FLAGS_SET))) + left_addr = internal->node_ptrs[idx].addr; + if(NULL == (right_int = H5B2__protect_internal(hdr, dxpl_id, internal, &internal->node_ptrs[idx + 1], (uint16_t)(depth - 1), FALSE, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node") + right_addr = internal->node_ptrs[idx + 1].addr; /* More setup for child nodes */ left_child = left_int; @@ -243,19 +212,20 @@ H5B2__split1(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, /* Create new leaf node */ internal->node_ptrs[idx + 1].all_nrec = internal->node_ptrs[idx + 1].node_nrec = 0; - if(H5B2__create_leaf(hdr, dxpl_id, &(internal->node_ptrs[idx + 1])) < 0) + if(H5B2__create_leaf(hdr, dxpl_id, internal, &(internal->node_ptrs[idx + 1])) < 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 = internal->node_ptrs[idx].addr; - right_addr = internal->node_ptrs[idx + 1].addr; /* Protect both leaves */ - if(NULL == (left_leaf = H5B2__protect_leaf(hdr, dxpl_id, left_addr, internal->node_ptrs[idx].node_nrec, H5AC__NO_FLAGS_SET))) + /* (Shadow the left node if doing SWMR writes) */ + if(NULL == (left_leaf = H5B2__protect_leaf(hdr, dxpl_id, internal, &internal->node_ptrs[idx], hdr->swmr_write, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node") - if(NULL == (right_leaf = H5B2__protect_leaf(hdr, dxpl_id, right_addr, internal->node_ptrs[idx + 1].node_nrec, H5AC__NO_FLAGS_SET))) + left_addr = internal->node_ptrs[idx].addr; + if(NULL == (right_leaf = H5B2__protect_leaf(hdr, dxpl_id, internal, &internal->node_ptrs[idx + 1], FALSE, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node") + right_addr = internal->node_ptrs[idx + 1].addr; /* More setup for child nodes */ left_child = left_leaf; @@ -295,7 +265,7 @@ H5B2__split1(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, /* Determine total number of records in new child nodes */ if(depth > 1) { - unsigned u; /* Local index variable */ + 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 */ @@ -329,6 +299,12 @@ H5B2__split1(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, if(parent_cache_info_flags_ptr) *parent_cache_info_flags_ptr |= H5AC__DIRTIED_FLAG; + /* Update flush dependencies for grandchildren, if using SWMR */ + if(hdr->swmr_write && depth > 1) + if(H5B2__update_child_flush_depends(hdr, dxpl_id, depth, right_node_ptrs, + 0, (unsigned)(*right_nrec + 1), left_child, right_child) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUPDATE, FAIL, "unable to update child nodes to new parent") + #ifdef H5B2_DEBUG H5B2__assert_internal((hsize_t)0, hdr, internal); if(depth > 1) { @@ -407,11 +383,11 @@ H5B2__split_root(H5B2_hdr_t *hdr, hid_t dxpl_id) /* Create new internal node to use as root */ hdr->root.node_nrec = 0; - if(H5B2__create_internal(hdr, dxpl_id, &(hdr->root), hdr->depth) < 0) + if(H5B2__create_internal(hdr, dxpl_id, hdr, &(hdr->root), hdr->depth) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new internal node") /* Protect new root node */ - if(NULL == (new_root = H5B2__protect_internal(hdr, dxpl_id, hdr->root.addr, hdr->root.node_nrec, hdr->depth, H5AC__NO_FLAGS_SET))) + if(NULL == (new_root = H5B2__protect_internal(hdr, dxpl_id, hdr, &hdr->root, hdr->depth, FALSE, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node") /* Set first node pointer in root node to old root node pointer info */ @@ -444,7 +420,7 @@ done: * *------------------------------------------------------------------------- */ -static herr_t +herr_t H5B2__redistribute2(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, H5B2_internal_t *internal, unsigned idx) { @@ -458,7 +434,7 @@ H5B2__redistribute2(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, unsigned left_child_flags = H5AC__NO_FLAGS_SET, right_child_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting child nodes */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_STATIC + FUNC_ENTER_PACKAGE /* Check arguments. */ HDassert(hdr); @@ -471,14 +447,15 @@ H5B2__redistribute2(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, /* 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 = H5B2__protect_internal(hdr, dxpl_id, left_addr, internal->node_ptrs[idx].node_nrec, (uint16_t)(depth - 1), H5AC__NO_FLAGS_SET))) + /* (Shadow both nodes if doing SWMR writes) */ + if(NULL == (left_internal = H5B2__protect_internal(hdr, dxpl_id, internal, &internal->node_ptrs[idx], (uint16_t)(depth - 1), hdr->swmr_write, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node") - if(NULL == (right_internal = H5B2__protect_internal(hdr, dxpl_id, right_addr, internal->node_ptrs[idx + 1].node_nrec, (uint16_t)(depth - 1), H5AC__NO_FLAGS_SET))) + left_addr = internal->node_ptrs[idx].addr; + if(NULL == (right_internal = H5B2__protect_internal(hdr, dxpl_id, internal, &internal->node_ptrs[idx + 1], (uint16_t)(depth - 1), hdr->swmr_write, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node") + right_addr = internal->node_ptrs[idx + 1].addr; /* More setup for child nodes */ left_child = left_internal; @@ -496,14 +473,15 @@ H5B2__redistribute2(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, /* 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 = H5B2__protect_leaf(hdr, dxpl_id, left_addr, internal->node_ptrs[idx].node_nrec, H5AC__NO_FLAGS_SET))) + /* (Shadow both nodes if doing SWMR writes) */ + if(NULL == (left_leaf = H5B2__protect_leaf(hdr, dxpl_id, internal, &internal->node_ptrs[idx], hdr->swmr_write, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node") - if(NULL == (right_leaf = H5B2__protect_leaf(hdr, dxpl_id, right_addr, internal->node_ptrs[idx + 1].node_nrec, H5AC__NO_FLAGS_SET))) + left_addr = internal->node_ptrs[idx].addr; + if(NULL == (right_leaf = H5B2__protect_leaf(hdr, dxpl_id, internal, &internal->node_ptrs[idx + 1], hdr->swmr_write, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node") + right_addr = internal->node_ptrs[idx + 1].addr; /* More setup for child nodes */ left_child = left_leaf; @@ -549,7 +527,7 @@ H5B2__redistribute2(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, /* 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 */ + unsigned u; /* Local index variable */ /* Count the number of records being moved */ for(u = 0; u < move_nrec; u++) @@ -564,6 +542,12 @@ H5B2__redistribute2(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, HDmemmove(&(right_node_ptrs[0]), &(right_node_ptrs[move_nrec]), sizeof(H5B2_node_ptr_t) * (new_right_nrec + (unsigned)1)); } /* end if */ + /* Update flush dependencies for grandchildren, if using SWMR */ + if(hdr->swmr_write && depth > 1) + if(H5B2__update_child_flush_depends(hdr, dxpl_id, depth, left_node_ptrs, + (unsigned)(*left_nrec + 1), (unsigned)(*left_nrec + move_nrec + 1), right_child, left_child) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUPDATE, FAIL, "unable to update child nodes to new parent") + /* Update number of records in child nodes */ *left_nrec = (uint16_t)(*left_nrec + move_nrec); *right_nrec = new_right_nrec; @@ -599,7 +583,7 @@ H5B2__redistribute2(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, /* 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 */ + 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) * (size_t)(*right_nrec + 1)); @@ -614,6 +598,12 @@ H5B2__redistribute2(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, H5_CHECKED_ASSIGN(right_moved_nrec, hssize_t, moved_nrec, hsize_t) } /* end if */ + /* Update flush dependencies for grandchildren, if using SWMR */ + if(hdr->swmr_write && depth > 1) + if(H5B2__update_child_flush_depends(hdr, dxpl_id, depth, right_node_ptrs, + 0, (unsigned)move_nrec, left_child, right_child) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUPDATE, FAIL, "unable to update child nodes to new parent") + /* Update number of records in child nodes */ *left_nrec = new_left_nrec; *right_nrec = (uint16_t)(*right_nrec + move_nrec); @@ -674,7 +664,7 @@ done: * *------------------------------------------------------------------------- */ -static herr_t +herr_t H5B2__redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx) { @@ -695,7 +685,7 @@ H5B2__redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, unsigned middle_child_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting child nodes */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_STATIC + FUNC_ENTER_PACKAGE /* Check arguments. */ HDassert(hdr); @@ -710,17 +700,18 @@ H5B2__redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, /* 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 = H5B2__protect_internal(hdr, dxpl_id, left_addr, internal->node_ptrs[idx - 1].node_nrec, (uint16_t)(depth - 1), H5AC__NO_FLAGS_SET))) + /* (Shadow all nodes if doing SWMR writes) */ + if(NULL == (left_internal = H5B2__protect_internal(hdr, dxpl_id, internal, &internal->node_ptrs[idx - 1], (uint16_t)(depth - 1), hdr->swmr_write, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node") - if(NULL == (middle_internal = H5B2__protect_internal(hdr, dxpl_id, middle_addr, internal->node_ptrs[idx].node_nrec, (uint16_t)(depth - 1), H5AC__NO_FLAGS_SET))) + left_addr = internal->node_ptrs[idx - 1].addr; + if(NULL == (middle_internal = H5B2__protect_internal(hdr, dxpl_id, internal, &internal->node_ptrs[idx], (uint16_t)(depth - 1), hdr->swmr_write, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node") - if(NULL == (right_internal = H5B2__protect_internal(hdr, dxpl_id, right_addr, internal->node_ptrs[idx + 1].node_nrec, (uint16_t)(depth - 1), H5AC__NO_FLAGS_SET))) + middle_addr = internal->node_ptrs[idx].addr; + if(NULL == (right_internal = H5B2__protect_internal(hdr, dxpl_id, internal, &internal->node_ptrs[idx + 1], (uint16_t)(depth - 1), hdr->swmr_write, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node") + right_addr = internal->node_ptrs[idx + 1].addr; /* More setup for child nodes */ left_child = left_internal; @@ -743,17 +734,18 @@ H5B2__redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, /* 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 = H5B2__protect_leaf(hdr, dxpl_id, left_addr, internal->node_ptrs[idx - 1].node_nrec, H5AC__NO_FLAGS_SET))) + /* (Shadow all nodes if doing SWMR writes) */ + if(NULL == (left_leaf = H5B2__protect_leaf(hdr, dxpl_id, internal, &internal->node_ptrs[idx - 1], hdr->swmr_write, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node") - if(NULL == (middle_leaf = H5B2__protect_leaf(hdr, dxpl_id, middle_addr, internal->node_ptrs[idx].node_nrec, H5AC__NO_FLAGS_SET))) + left_addr = internal->node_ptrs[idx - 1].addr; + if(NULL == (middle_leaf = H5B2__protect_leaf(hdr, dxpl_id, internal, &internal->node_ptrs[idx], hdr->swmr_write, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node") - if(NULL == (right_leaf = H5B2__protect_leaf(hdr, dxpl_id, right_addr, internal->node_ptrs[idx + 1].node_nrec, H5AC__NO_FLAGS_SET))) + middle_addr = internal->node_ptrs[idx].addr; + if(NULL == (right_leaf = H5B2__protect_leaf(hdr, dxpl_id, internal, &internal->node_ptrs[idx + 1], hdr->swmr_write, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node") + right_addr = internal->node_ptrs[idx + 1].addr; /* More setup for child nodes */ left_child = left_leaf; @@ -802,7 +794,7 @@ H5B2__redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, /* 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 */ + 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 */ @@ -820,6 +812,12 @@ H5B2__redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, HDmemmove(&(middle_node_ptrs[0]), &(middle_node_ptrs[move_nptrs]), sizeof(H5B2_node_ptr_t) * ((*middle_nrec - move_nptrs) + 1)); } /* end if */ + /* Update flush dependencies for grandchildren, if using SWMR */ + if(hdr->swmr_write && depth > 1) + if(H5B2__update_child_flush_depends(hdr, dxpl_id, depth, left_node_ptrs, + (unsigned)(*left_nrec + 1), (unsigned)(*left_nrec + moved_middle_nrec + 1), middle_child, left_child) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUPDATE, FAIL, "unable to update child nodes to new parent") + /* Update the current number of records in middle node */ curr_middle_nrec = (uint16_t)(curr_middle_nrec - moved_middle_nrec); @@ -847,7 +845,7 @@ H5B2__redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, /* 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 */ + 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 */ @@ -863,6 +861,12 @@ H5B2__redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, middle_moved_nrec -= (hssize_t)(moved_nrec + right_nrec_move); } /* end if */ + /* Update flush dependencies for grandchildren, if using SWMR */ + if(hdr->swmr_write && depth > 1) + if(H5B2__update_child_flush_depends(hdr, dxpl_id, depth, right_node_ptrs, + 0, (unsigned)right_nrec_move, middle_child, right_child) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUPDATE, FAIL, "unable to update child nodes to new parent") + /* Update the current number of records in middle node */ curr_middle_nrec = (uint16_t)(curr_middle_nrec - right_nrec_move); @@ -890,7 +894,7 @@ H5B2__redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, /* 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 */ + 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 */ @@ -906,6 +910,12 @@ H5B2__redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, middle_moved_nrec += (hssize_t)(moved_nrec + left_nrec_move); } /* end if */ + /* Update flush dependencies for grandchildren, if using SWMR */ + if(hdr->swmr_write && depth > 1) + if(H5B2__update_child_flush_depends(hdr, dxpl_id, depth, middle_node_ptrs, + 0, (unsigned)left_nrec_move, left_child, middle_child) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUPDATE, FAIL, "unable to update child nodes to new parent") + /* Update the current number of records in middle node */ curr_middle_nrec = (uint16_t)(curr_middle_nrec + left_nrec_move); @@ -932,7 +942,7 @@ H5B2__redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, /* 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 */ + hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */ unsigned u; /* Local index variable */ /* Move right node pointers into middle node */ @@ -948,6 +958,12 @@ H5B2__redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, HDmemmove(&(right_node_ptrs[0]), &(right_node_ptrs[right_nrec_move]), sizeof(H5B2_node_ptr_t) * (size_t)(new_right_nrec + 1)); } /* end if */ + /* Update flush dependencies for grandchildren, if using SWMR */ + if(hdr->swmr_write && depth > 1) + if(H5B2__update_child_flush_depends(hdr, dxpl_id, depth, middle_node_ptrs, + (unsigned)(curr_middle_nrec + 1), (unsigned)(curr_middle_nrec + right_nrec_move + 1), right_child, middle_child) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUPDATE, FAIL, "unable to update child nodes to new parent") + /* Mark nodes as dirty */ middle_child_flags |= H5AC__DIRTIED_FLAG; right_child_flags |= H5AC__DIRTIED_FLAG; @@ -979,46 +995,6 @@ H5B2__redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, /* 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); - (hdr->cls->debug)(stderr, hdr->f, dxpl_id, 3, 4, H5B2_INT_NREC(internal, hdr, 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); - (hdr->cls->debug)(stderr, hdr->f, dxpl_id, 3, 4, H5B2_NAT_NREC(left_native, hdr, 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); - (hdr->cls->debug)(stderr, hdr->f, dxpl_id, 3, 4, H5B2_NAT_NREC(middle_native, hdr, 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); - (hdr->cls->debug)(stderr, hdr->f, dxpl_id, 3, 4, H5B2_NAT_NREC(right_native, hdr, 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, hdr, internal); if(depth > 1) { @@ -1062,7 +1038,7 @@ done: * *------------------------------------------------------------------------- */ -static herr_t +herr_t H5B2__merge2(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, H5B2_node_ptr_t *curr_node_ptr, unsigned *parent_cache_info_flags_ptr, H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx) @@ -1076,7 +1052,7 @@ H5B2__merge2(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, unsigned left_child_flags = H5AC__NO_FLAGS_SET, right_child_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting child nodes */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_STATIC + FUNC_ENTER_PACKAGE /* Check arguments. */ HDassert(hdr); @@ -1091,14 +1067,15 @@ H5B2__merge2(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, /* 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 = H5B2__protect_internal(hdr, dxpl_id, left_addr, internal->node_ptrs[idx].node_nrec, (uint16_t)(depth - 1), H5AC__NO_FLAGS_SET))) + /* (Shadow the left node if doing SWMR writes) */ + if(NULL == (left_internal = H5B2__protect_internal(hdr, dxpl_id, internal, &internal->node_ptrs[idx], (uint16_t)(depth - 1), hdr->swmr_write, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node") - if(NULL == (right_internal = H5B2__protect_internal(hdr, dxpl_id, right_addr, internal->node_ptrs[idx + 1].node_nrec, (uint16_t)(depth - 1), H5AC__NO_FLAGS_SET))) + left_addr = internal->node_ptrs[idx].addr; + if(NULL == (right_internal = H5B2__protect_internal(hdr, dxpl_id, internal, &internal->node_ptrs[idx + 1], (uint16_t)(depth - 1), FALSE, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node") + right_addr = internal->node_ptrs[idx + 1].addr; /* More setup for accessing child node information */ left_child = left_internal; @@ -1116,14 +1093,15 @@ H5B2__merge2(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, /* 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 = H5B2__protect_leaf(hdr, dxpl_id, left_addr, internal->node_ptrs[idx].node_nrec, H5AC__NO_FLAGS_SET))) + /* (Shadow the left node if doing SWMR writes) */ + if(NULL == (left_leaf = H5B2__protect_leaf(hdr, dxpl_id, internal, &internal->node_ptrs[idx], hdr->swmr_write, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node") - if(NULL == (right_leaf = H5B2__protect_leaf(hdr, dxpl_id, right_addr, internal->node_ptrs[idx + 1].node_nrec, H5AC__NO_FLAGS_SET))) + left_addr = internal->node_ptrs[idx].addr; + if(NULL == (right_leaf = H5B2__protect_leaf(hdr, dxpl_id, internal, &internal->node_ptrs[idx + 1], FALSE, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node") + right_addr = internal->node_ptrs[idx + 1].addr; /* More setup for accessing child node information */ left_child = left_leaf; @@ -1146,12 +1124,20 @@ H5B2__merge2(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, if(depth > 1) HDmemcpy(&(left_node_ptrs[*left_nrec + 1]), &(right_node_ptrs[0]), sizeof(H5B2_node_ptr_t) * (size_t)(*right_nrec + 1)); + /* Update flush dependencies for grandchildren, if using SWMR */ + if(hdr->swmr_write && depth > 1) + if(H5B2__update_child_flush_depends(hdr, dxpl_id, depth, left_node_ptrs, + (unsigned)(*left_nrec + 1), (unsigned)(*left_nrec + *right_nrec + 2), right_child, left_child) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUPDATE, FAIL, "unable to update child nodes to new parent") + /* Update # of records in left node */ *left_nrec = (uint16_t)(*left_nrec + *right_nrec + 1); /* Mark nodes as dirty */ left_child_flags |= H5AC__DIRTIED_FLAG; - right_child_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG; + right_child_flags |= H5AC__DELETED_FLAG; + if(!(hdr->swmr_write)) + right_child_flags |= H5AC__DIRTIED_FLAG | H5AC__FREE_FILE_SPACE_FLAG; } /* end block */ /* Update # of records in child nodes */ @@ -1215,7 +1201,7 @@ done: * *------------------------------------------------------------------------- */ -static herr_t +herr_t H5B2__merge3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, H5B2_node_ptr_t *curr_node_ptr, unsigned *parent_cache_info_flags_ptr, H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx) @@ -1236,7 +1222,7 @@ H5B2__merge3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, unsigned middle_child_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting child nodes */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_STATIC + FUNC_ENTER_PACKAGE /* Check arguments. */ HDassert(hdr); @@ -1252,17 +1238,18 @@ H5B2__merge3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, /* 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 = H5B2__protect_internal(hdr, dxpl_id, left_addr, internal->node_ptrs[idx - 1].node_nrec, (uint16_t)(depth - 1), H5AC__NO_FLAGS_SET))) + /* (Shadow left and middle nodes if doing SWMR writes) */ + if(NULL == (left_internal = H5B2__protect_internal(hdr, dxpl_id, internal, &internal->node_ptrs[idx - 1], (uint16_t)(depth - 1), hdr->swmr_write, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node") - if(NULL == (middle_internal = H5B2__protect_internal(hdr, dxpl_id, middle_addr, internal->node_ptrs[idx].node_nrec, (uint16_t)(depth - 1), H5AC__NO_FLAGS_SET))) + left_addr = internal->node_ptrs[idx - 1].addr; + if(NULL == (middle_internal = H5B2__protect_internal(hdr, dxpl_id, internal, &internal->node_ptrs[idx], (uint16_t)(depth - 1), hdr->swmr_write, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node") - if(NULL == (right_internal = H5B2__protect_internal(hdr, dxpl_id, right_addr, internal->node_ptrs[idx + 1].node_nrec, (uint16_t)(depth - 1), H5AC__NO_FLAGS_SET))) + middle_addr = internal->node_ptrs[idx].addr; + if(NULL == (right_internal = H5B2__protect_internal(hdr, dxpl_id, internal, &internal->node_ptrs[idx + 1], (uint16_t)(depth - 1), FALSE, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node") + right_addr = internal->node_ptrs[idx + 1].addr; /* More setup for accessing child node information */ left_child = left_internal; @@ -1285,17 +1272,18 @@ H5B2__merge3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, /* 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 = H5B2__protect_leaf(hdr, dxpl_id, left_addr, internal->node_ptrs[idx - 1].node_nrec, H5AC__NO_FLAGS_SET))) + /* (Shadow left and middle nodes if doing SWMR writes) */ + if(NULL == (left_leaf = H5B2__protect_leaf(hdr, dxpl_id, internal, &internal->node_ptrs[idx - 1], hdr->swmr_write, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node") - if(NULL == (middle_leaf = H5B2__protect_leaf(hdr, dxpl_id, middle_addr, internal->node_ptrs[idx].node_nrec, H5AC__NO_FLAGS_SET))) + left_addr = internal->node_ptrs[idx - 1].addr; + if(NULL == (middle_leaf = H5B2__protect_leaf(hdr, dxpl_id, internal, &internal->node_ptrs[idx], hdr->swmr_write, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node") - if(NULL == (right_leaf = H5B2__protect_leaf(hdr, dxpl_id, right_addr, internal->node_ptrs[idx + 1].node_nrec, H5AC__NO_FLAGS_SET))) + middle_addr = internal->node_ptrs[idx].addr; + if(NULL == (right_leaf = H5B2__protect_leaf(hdr, dxpl_id, internal, &internal->node_ptrs[idx + 1], FALSE, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node") + right_addr = internal->node_ptrs[idx + 1].addr; /* More setup for accessing child node information */ left_child = left_leaf; @@ -1344,6 +1332,12 @@ H5B2__merge3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, HDmemmove(&(middle_node_ptrs[0]), &(middle_node_ptrs[middle_nrec_move]), sizeof(H5B2_node_ptr_t) * (size_t)((unsigned)(*middle_nrec + 1) - middle_nrec_move)); } /* end if */ + /* Update flush dependencies for grandchildren, if using SWMR */ + if(hdr->swmr_write && depth > 1) + if(H5B2__update_child_flush_depends(hdr, dxpl_id, depth, left_node_ptrs, + (unsigned)(*left_nrec + 1), (unsigned)(*left_nrec + middle_nrec_move + 1), middle_child, left_child) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUPDATE, FAIL, "unable to update child nodes to new parent") + /* Update # of records in left & middle nodes */ *left_nrec = (uint16_t)(*left_nrec + middle_nrec_move); *middle_nrec = (uint16_t)(*middle_nrec - middle_nrec_move); @@ -1366,12 +1360,20 @@ H5B2__merge3(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, /* Copy node pointers from right node into middle node */ HDmemcpy(&(middle_node_ptrs[*middle_nrec + 1]), &(right_node_ptrs[0]), sizeof(H5B2_node_ptr_t) * (size_t)(*right_nrec + 1)); + /* Update flush dependencies for grandchildren, if using SWMR */ + if(hdr->swmr_write && depth > 1) + if(H5B2__update_child_flush_depends(hdr, dxpl_id, depth, middle_node_ptrs, + (unsigned)(*middle_nrec + 1), (unsigned)(*middle_nrec + *right_nrec + 2), right_child, middle_child) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUPDATE, FAIL, "unable to update child nodes to new parent") + /* Update # of records in middle node */ *middle_nrec = (uint16_t)(*middle_nrec + (*right_nrec + 1)); /* Mark nodes as dirty */ middle_child_flags |= H5AC__DIRTIED_FLAG; - right_child_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG; + right_child_flags |= H5AC__DELETED_FLAG; + if(!(hdr->swmr_write)) + right_child_flags |= H5AC__DIRTIED_FLAG | H5AC__FREE_FILE_SPACE_FLAG; } /* end block */ /* Update # of records in child nodes */ @@ -1429,98 +1431,7 @@ done: /*------------------------------------------------------------------------- - * 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(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t 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 = NULL; /* Pointer to child node */ - uint8_t *child_native; /* Pointer to child's native records */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_STATIC - - /* Check arguments. */ - HDassert(hdr); - HDassert(internal); - HDassert(internal_flags_ptr); - HDassert(idx <= internal->nrec); - - /* 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 = H5B2__protect_internal(hdr, dxpl_id, child_addr, internal->node_ptrs[idx].node_nrec, (uint16_t)(depth - 1), H5AC__NO_FLAGS_SET))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect 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 = H5B2__protect_leaf(hdr, dxpl_id, child_addr, internal->node_ptrs[idx].node_nrec, H5AC__NO_FLAGS_SET))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect 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(hdr->page, H5B2_NAT_NREC(child_native, hdr, 0), hdr->cls->nrec_size); - HDmemcpy(H5B2_NAT_NREC(child_native, hdr, 0), swap_loc, hdr->cls->nrec_size); - HDmemcpy(swap_loc, hdr->page, hdr->cls->nrec_size); - - /* Mark parent as dirty */ - *internal_flags_ptr |= H5AC__DIRTIED_FLAG; - -#ifdef H5B2_DEBUG - H5B2__assert_internal((hsize_t)0, hdr, internal); - if(depth > 1) - H5B2__assert_internal(internal->node_ptrs[idx].all_nrec, hdr, (H5B2_internal_t *)child); - else - H5B2__assert_leaf(hdr, (H5B2_leaf_t *)child); -#endif /* H5B2_DEBUG */ - -done: - /* Unlock child node */ - if(child && H5AC_unprotect(hdr->f, dxpl_id, child_class, child_addr, child, H5AC__DIRTIED_FLAG) < 0) - HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") - - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5B2__swap_leaf() */ - - -/*------------------------------------------------------------------------- - * Function: H5B2__insert_hdr + * Function: H5B2__insert * * Purpose: Adds a new record to the B-tree. * @@ -1533,7 +1444,7 @@ done: *------------------------------------------------------------------------- */ herr_t -H5B2__insert_hdr(H5B2_hdr_t *hdr, hid_t dxpl_id, void *udata) +H5B2__insert(H5B2_hdr_t *hdr, hid_t dxpl_id, void *udata) { herr_t ret_value = SUCCEED; /* Return value */ @@ -1546,7 +1457,7 @@ H5B2__insert_hdr(H5B2_hdr_t *hdr, hid_t dxpl_id, void *udata) /* Check if the root node is allocated yet */ if(!H5F_addr_defined(hdr->root.addr)) { /* Create root node as leaf node in B-tree */ - if(H5B2__create_leaf(hdr, dxpl_id, &(hdr->root)) < 0) + if(H5B2__create_leaf(hdr, dxpl_id, hdr, &(hdr->root)) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create root node") } /* end if */ /* Check if we need to split the root node (equiv. to a 1->2 node split) */ @@ -1558,11 +1469,11 @@ H5B2__insert_hdr(H5B2_hdr_t *hdr, hid_t dxpl_id, void *udata) /* Attempt to insert record into B-tree */ if(hdr->depth > 0) { - if(H5B2__insert_internal(hdr, dxpl_id, hdr->depth, NULL, &hdr->root, H5B2_POS_ROOT, udata) < 0) + if(H5B2__insert_internal(hdr, dxpl_id, hdr->depth, NULL, &hdr->root, H5B2_POS_ROOT, hdr, 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(hdr, dxpl_id, &hdr->root, H5B2_POS_ROOT, udata) < 0) + if(H5B2__insert_leaf(hdr, dxpl_id, &hdr->root, H5B2_POS_ROOT, hdr, udata) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into B-tree leaf node") } /* end else */ @@ -1572,834 +1483,7 @@ H5B2__insert_hdr(H5B2_hdr_t *hdr, hid_t dxpl_id, void *udata) done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5B2__insert_hdr() */ - - -/*------------------------------------------------------------------------- - * 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(H5B2_hdr_t *hdr, hid_t dxpl_id, H5B2_node_ptr_t *curr_node_ptr, - H5B2_nodepos_t curr_pos, void *udata) -{ - H5B2_leaf_t *leaf; /* Pointer to leaf node */ - int cmp; /* Comparison value of records */ - unsigned idx; /* Location of record which matches key */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_PACKAGE - - /* Check arguments. */ - HDassert(hdr); - HDassert(curr_node_ptr); - HDassert(H5F_addr_defined(curr_node_ptr->addr)); - - /* Lock current B-tree node */ - if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, curr_node_ptr->addr, curr_node_ptr->node_nrec, H5AC__NO_FLAGS_SET))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node") - - /* Must have a leaf node with enough space to insert a record now */ - HDassert(curr_node_ptr->node_nrec < hdr->node_info[0].max_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(H5B2__locate_record(hdr->cls, leaf->nrec, hdr->nat_off, leaf->leaf_native, udata, &idx, &cmp) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTCOMPARE, FAIL, "can't compare btree2 records") - if(cmp == 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, hdr, idx + 1), H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size * (leaf->nrec - idx)); - } /* end else */ - - /* Make callback to store record in native form */ - if((hdr->cls->store)(H5B2_LEAF_NREC(leaf, hdr, 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++; - - /* Check for new record being the min or max for the tree */ - /* (Don't use 'else' for the idx check, to allow for root leaf node) */ - if(H5B2_POS_MIDDLE != curr_pos) { - if(idx == 0) { - if(H5B2_POS_LEFT == curr_pos || H5B2_POS_ROOT == curr_pos) { - if(hdr->min_native_rec == NULL) - if(NULL == (hdr->min_native_rec = H5MM_malloc(hdr->cls->nrec_size))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL, "memory allocation failed for v2 B-tree min record info") - HDmemcpy(hdr->min_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size); - } /* end if */ - } /* end if */ - if(idx == (unsigned)(leaf->nrec - 1)) { - if(H5B2_POS_RIGHT == curr_pos || H5B2_POS_ROOT == curr_pos) { - if(hdr->max_native_rec == NULL) - if(NULL == (hdr->max_native_rec = H5MM_malloc(hdr->cls->nrec_size))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL, "memory allocation failed for v2 B-tree max record info") - HDmemcpy(hdr->max_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size); - } /* end if */ - } /* end if */ - } /* end if */ - -done: - /* Release the B-tree leaf node (marked as dirty) */ - if(leaf && H5AC_unprotect(hdr->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(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, - unsigned *parent_cache_info_flags_ptr, H5B2_node_ptr_t *curr_node_ptr, - H5B2_nodepos_t curr_pos, void *udata) -{ - H5B2_internal_t *internal = NULL; /* Pointer to internal node */ - unsigned internal_flags = H5AC__NO_FLAGS_SET; - unsigned idx; /* Location of record which matches key */ - H5B2_nodepos_t next_pos = H5B2_POS_MIDDLE; /* Position of node */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_PACKAGE - - /* Check arguments. */ - HDassert(hdr); - HDassert(depth > 0); - HDassert(curr_node_ptr); - HDassert(H5F_addr_defined(curr_node_ptr->addr)); - - /* Lock current B-tree node */ - if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, curr_node_ptr->addr, curr_node_ptr->node_nrec, depth, H5AC__NO_FLAGS_SET))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node") - - /* Sanity check number of records */ - HDassert(internal->nrec == curr_node_ptr->node_nrec); - - /* 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(H5B2__locate_record(hdr->cls, internal->nrec, hdr->nat_off, internal->int_native, - udata, &idx, &cmp) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTCOMPARE, FAIL, "can't compare btree2 records") - if(cmp == 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 child node at */ - split_nrec = hdr->node_info[depth - 1].split_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(hdr, dxpl_id, depth, internal, idx) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records") - } /* end if */ - else { - if(H5B2__split1(hdr, 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(hdr, 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__split1(hdr, 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 { /* 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(hdr, 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__split1(hdr, 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(H5B2__locate_record(hdr->cls, internal->nrec, hdr->nat_off, internal->int_native, - udata, &idx, &cmp) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTCOMPARE, FAIL, "can't compare btree2 records") - if(cmp == 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 */ - - /* Check if this node is left/right-most */ - if(H5B2_POS_MIDDLE != curr_pos) { - if(idx == 0) { - if(H5B2_POS_LEFT == curr_pos || H5B2_POS_ROOT == curr_pos) - next_pos = H5B2_POS_LEFT; - } /* end if */ - else if(idx == internal->nrec) { - if(H5B2_POS_RIGHT == curr_pos || H5B2_POS_ROOT == curr_pos) - next_pos = H5B2_POS_RIGHT; - } /* end else */ - } /* end if */ - - /* Attempt to insert node */ - if(depth > 1) { - if(H5B2__insert_internal(hdr, dxpl_id, (uint16_t)(depth - 1), &internal_flags, &internal->node_ptrs[idx], next_pos, 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(hdr, dxpl_id, &internal->node_ptrs[idx], next_pos, 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(hdr->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__update_leaf - * - * Purpose: Insert or modify a record in a B-tree leaf node. - * If the record exists already, it is modified as if H5B2_modify - * was called). If it doesn't exist, it is inserted as if - * H5B2_insert was called. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@hdfgroup.org - * Dec 23 2015 - * - *------------------------------------------------------------------------- - */ -herr_t -H5B2__update_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, H5B2_node_ptr_t *curr_node_ptr, - H5B2_update_status_t *status, H5B2_nodepos_t curr_pos, void *udata, - H5B2_modify_t op, void *op_data) -{ - H5B2_leaf_t *leaf; /* Pointer to leaf node */ - unsigned leaf_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting the leaf node */ - int cmp = -1; /* Comparison value of records */ - unsigned idx; /* Location of record which matches key */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_PACKAGE - - /* Check arguments. */ - HDassert(hdr); - HDassert(curr_node_ptr); - HDassert(H5F_addr_defined(curr_node_ptr->addr)); - - /* Lock current B-tree node */ - if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, curr_node_ptr->addr, curr_node_ptr->node_nrec, H5AC__NO_FLAGS_SET))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect 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); - - /* Check for inserting into empty leaf */ - if(leaf->nrec == 0) - idx = 0; - else { - /* Find correct location to insert this record */ - if(H5B2__locate_record(hdr->cls, leaf->nrec, hdr->nat_off, leaf->leaf_native, udata, &idx, &cmp) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTCOMPARE, FAIL, "can't compare btree2 records") - - /* Check for inserting a record */ - if(0 != cmp) { - /* Check if the leaf node is full */ - if(curr_node_ptr->node_nrec == hdr->node_info[0].split_nrec) { - /* Indicate that the leaf is full, but we need to insert */ - *status = H5B2_UPDATE_INSERT_CHILD_FULL; - - /* Let calling routine handle insertion */ - HGOTO_DONE(SUCCEED) - } /* end if */ - - /* Adjust index to leave room for record to insert */ - if(cmp > 0) - idx++; - - /* Make room for new record */ - if(idx < leaf->nrec) - HDmemmove(H5B2_LEAF_NREC(leaf, hdr, idx + 1), H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size * (leaf->nrec - idx)); - } /* end if */ - } /* end else */ - - /* Check for modifying existing record */ - if(0 == cmp) { - hbool_t changed = FALSE; /* Whether the 'modify' callback changed the record */ - - /* Make callback for current record */ - if((op)(H5B2_LEAF_NREC(leaf, hdr, idx), op_data, &changed) < 0) { - /* Make certain that the callback didn't modify the value if it failed */ - HDassert(changed == FALSE); - - HGOTO_ERROR(H5E_BTREE, H5E_CANTMODIFY, FAIL, "'modify' callback failed for B-tree update operation") - } /* end if */ - - /* Mark the node as dirty if it changed */ - leaf_flags |= (changed ? H5AC__DIRTIED_FLAG : 0); - - /* Indicate that the record was modified */ - *status = H5B2_UPDATE_MODIFY_DONE; - } /* end if */ - else { - /* Must have a leaf node with enough space to insert a record now */ - HDassert(curr_node_ptr->node_nrec < hdr->node_info[0].max_nrec); - - /* Make callback to store record in native form */ - if((hdr->cls->store)(H5B2_LEAF_NREC(leaf, hdr, idx), udata) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into leaf node") - - /* Mark the node as dirty */ - leaf_flags |= H5AC__DIRTIED_FLAG; - - /* Indicate that the record was inserted */ - *status = H5B2_UPDATE_INSERT_DONE; - - /* 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++; - } /* end else */ - - /* Check for new record being the min or max for the tree */ - /* (Don't use 'else' for the idx check, to allow for root leaf node) */ - if(H5B2_POS_MIDDLE != curr_pos) { - if(idx == 0) { - if(H5B2_POS_LEFT == curr_pos || H5B2_POS_ROOT == curr_pos) { - if(hdr->min_native_rec == NULL) - if(NULL == (hdr->min_native_rec = H5MM_malloc(hdr->cls->nrec_size))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL, "memory allocation failed for v2 B-tree min record info") - HDmemcpy(hdr->min_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size); - } /* end if */ - } /* end if */ - if(idx == (unsigned)(leaf->nrec - 1)) { - if(H5B2_POS_RIGHT == curr_pos || H5B2_POS_ROOT == curr_pos) { - if(hdr->max_native_rec == NULL) - if(NULL == (hdr->max_native_rec = H5MM_malloc(hdr->cls->nrec_size))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL, "memory allocation failed for v2 B-tree max record info") - HDmemcpy(hdr->max_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size); - } /* end if */ - } /* end if */ - } /* end if */ - -done: - /* Release the B-tree leaf node */ - if(leaf && H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr->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__update_leaf() */ - - -/*------------------------------------------------------------------------- - * Function: H5B2__update_internal - * - * Purpose: Insert or modify a record in a B-tree leaf node. - * If the record exists already, it is modified as if H5B2_modify - * was called). If it doesn't exist, it is inserted as if - * H5B2_insert was called. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@hdfgroup.org - * Dec 24 2015 - * - *------------------------------------------------------------------------- - */ -herr_t -H5B2__update_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, - unsigned *parent_cache_info_flags_ptr, H5B2_node_ptr_t *curr_node_ptr, - H5B2_update_status_t *status, H5B2_nodepos_t curr_pos, void *udata, - H5B2_modify_t op, void *op_data) -{ - H5B2_internal_t *internal = NULL; /* Pointer to internal node */ - unsigned internal_flags = H5AC__NO_FLAGS_SET; - int cmp; /* Comparison value of records */ - unsigned idx; /* Location of record which matches key */ - H5B2_nodepos_t next_pos = H5B2_POS_MIDDLE; /* Position of node */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_PACKAGE - - /* Check arguments. */ - HDassert(hdr); - HDassert(depth > 0); - HDassert(curr_node_ptr); - HDassert(H5F_addr_defined(curr_node_ptr->addr)); - - /* Lock current B-tree node */ - if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, curr_node_ptr->addr, curr_node_ptr->node_nrec, depth, H5AC__NO_FLAGS_SET))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node") - - /* Sanity check number of records */ - HDassert(internal->nrec == curr_node_ptr->node_nrec); - - /* Locate node pointer for child */ - if(H5B2__locate_record(hdr->cls, internal->nrec, hdr->nat_off, internal->int_native, udata, &idx, &cmp) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTCOMPARE, FAIL, "can't compare btree2 records") - - /* Check for modifying existing record */ - if(0 == cmp) { - hbool_t changed = FALSE; /* Whether the 'modify' callback changed the record */ - - /* Make callback for current record */ - if((op)(H5B2_INT_NREC(internal, hdr, idx), op_data, &changed) < 0) { - /* Make certain that the callback didn't modify the value if it failed */ - HDassert(changed == FALSE); - - HGOTO_ERROR(H5E_BTREE, H5E_CANTMODIFY, FAIL, "'modify' callback failed for B-tree update operation") - } /* end if */ - - /* Mark the node as dirty if it changed */ - internal_flags |= (changed ? H5AC__DIRTIED_FLAG : 0); - - /* Indicate that the record was modified */ - *status = H5B2_UPDATE_MODIFY_DONE; - } /* end if */ - else { - /* Adjust index to leave room for node to insert */ - if(cmp > 0) - idx++; - - /* Check if this node is left/right-most */ - if(H5B2_POS_MIDDLE != curr_pos) { - if(idx == 0) { - if(H5B2_POS_LEFT == curr_pos || H5B2_POS_ROOT == curr_pos) - next_pos = H5B2_POS_LEFT; - } /* end if */ - else if(idx == internal->nrec) { - if(H5B2_POS_RIGHT == curr_pos || H5B2_POS_ROOT == curr_pos) - next_pos = H5B2_POS_RIGHT; - } /* end else */ - } /* end if */ - - /* Attempt to update record in child */ - if(depth > 1) { - if(H5B2__update_internal(hdr, dxpl_id, (uint16_t)(depth - 1), &internal_flags, &internal->node_ptrs[idx], status, next_pos, udata, op, op_data) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTUPDATE, FAIL, "unable to update record in internal B-tree node") - } /* end if */ - else { - if(H5B2__update_leaf(hdr, dxpl_id, &internal->node_ptrs[idx], status, next_pos, udata, op, op_data) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTUPDATE, FAIL, "unable to update record in leaf B-tree node") - } /* end else */ - - /* Take actions based on child's status report */ - switch(*status) { - case H5B2_UPDATE_MODIFY_DONE: - /* No action */ - break; - - case H5B2_UPDATE_INSERT_DONE: - /* Mark node as dirty */ - internal_flags |= H5AC__DIRTIED_FLAG; - - /* Update total record count for node pointer to current node */ - curr_node_ptr->all_nrec++; - break; - - case H5B2_UPDATE_INSERT_CHILD_FULL: - /* Split/redistribute this node */ - if(internal->nrec == hdr->node_info[depth].split_nrec) { - hbool_t could_split = FALSE; /* Whether the child node could split */ - -#ifdef QAK -HDfprintf(stderr, "%s: idx = %u, internal->nrec = %u\n", FUNC, idx, internal->nrec); -HDfprintf(stderr, "%s: hdr->node_info[%u].split_nrec = %u\n", FUNC, (unsigned)depth, (unsigned)hdr->node_info[depth].split_nrec); -HDfprintf(stderr, "%s: hdr->node_info[%u].split_nrec = %u\n", FUNC, (unsigned)(depth - 1), (unsigned)hdr->node_info[depth - 1].split_nrec); -#endif /* QAK */ - if(idx == 0) { /* Left-most child */ -#ifdef QAK -HDfprintf(stderr, "%s: Left-most child\n", FUNC); -HDfprintf(stderr, "%s: internal->node_ptrs[%u].node_nrec = %u\n", FUNC, (unsigned)idx, (unsigned)internal->node_ptrs[idx].node_nrec); -HDfprintf(stderr, "%s: internal->node_ptrs[%u].node_nrec = %u\n", FUNC, (unsigned)(idx + 1), (unsigned)internal->node_ptrs[idx + 1].node_nrec); -#endif /* QAK */ - /* Check for left-most child and its neighbor being close to full */ - if((internal->node_ptrs[idx].node_nrec + internal->node_ptrs[idx + 1].node_nrec) - >= ((hdr->node_info[depth - 1].split_nrec * 2) - 1)) - could_split = TRUE; - } /* end if */ - else if(idx == internal->nrec) { /* Right-most child */ -#ifdef QAK -HDfprintf(stderr, "%s: Right-most child\n", FUNC); -HDfprintf(stderr, "%s: internal->node_ptrs[%u].node_nrec = %u\n", FUNC, (unsigned)(idx - 1), (unsigned)internal->node_ptrs[idx - 1].node_nrec); -HDfprintf(stderr, "%s: internal->node_ptrs[%u].node_nrec = %u\n", FUNC, (unsigned)idx, (unsigned)internal->node_ptrs[idx].node_nrec); -#endif /* QAK */ - /* Check for right-most child and its neighbor being close to full */ - if((internal->node_ptrs[idx - 1].node_nrec + internal->node_ptrs[idx].node_nrec) - >= ((hdr->node_info[depth - 1].split_nrec * 2) - 1)) - could_split = TRUE; - } /* end else-if */ - else { /* Middle child */ -#ifdef QAK -HDfprintf(stderr, "%s: Middle child\n", FUNC); -HDfprintf(stderr, "%s: internal->node_ptrs[%u].node_nrec = %u\n", FUNC, (unsigned)(idx - 1), (unsigned)internal->node_ptrs[idx - 1].node_nrec); -HDfprintf(stderr, "%s: internal->node_ptrs[%u].node_nrec = %u\n", FUNC, (unsigned)idx, (unsigned)internal->node_ptrs[idx].node_nrec); -HDfprintf(stderr, "%s: internal->node_ptrs[%u].node_nrec = %u\n", FUNC, (unsigned)(idx + 1), (unsigned)internal->node_ptrs[idx + 1].node_nrec); -#endif /* QAK */ - /* Check for middle child and its left neighbor being close to full */ - if((internal->node_ptrs[idx - 1].node_nrec + internal->node_ptrs[idx].node_nrec) - >= ((hdr->node_info[depth - 1].split_nrec * 2) - 1)) - could_split = TRUE; - /* Check for middle child and its right neighbor being close to full */ - else if((internal->node_ptrs[idx].node_nrec + internal->node_ptrs[idx + 1].node_nrec) - >= ((hdr->node_info[depth - 1].split_nrec * 2) - 1)) - could_split = TRUE; - } /* end if */ - - /* If this node is full and the child node insertion could - * cause a split, punt back up to caller, leaving the - * "insert child full" status. - */ - if(could_split) { - /* Release the internal B-tree node */ - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_INT, curr_node_ptr->addr, internal, internal_flags) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release internal B-tree node") - internal = NULL; - -#ifdef QAK -HDfprintf(stderr, "%s: Punting back to caller\n", FUNC); -#endif /* QAK */ - /* Punt back to caller */ - HGOTO_DONE(SUCCEED); - } /* end if */ - } /* end if */ - - /* Release the internal B-tree node */ - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_INT, curr_node_ptr->addr, internal, internal_flags) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release internal B-tree node") - internal = NULL; - - /* Indicate that the record was inserted */ - *status = H5B2_UPDATE_INSERT_DONE; - - /* Dodge sideways into inserting a record into this node */ - if(H5B2__insert_internal(hdr, dxpl_id, depth, parent_cache_info_flags_ptr, curr_node_ptr, curr_pos, udata) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into internal B-tree node") - break; - - case H5B2_UPDATE_UNKNOWN: - default: - HDassert(0 && "Invalid update status"); - HGOTO_ERROR(H5E_BTREE, H5E_CANTUPDATE, FAIL, "invalid update status") - } /* end switch */ - } /* end else */ - -done: - /* Release the internal B-tree node */ - if(internal && H5AC_unprotect(hdr->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__update_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(H5B2_hdr_t *hdr, hid_t dxpl_id, H5B2_node_ptr_t *node_ptr) -{ - H5B2_leaf_t *leaf = NULL; /* Pointer to new leaf node created */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_PACKAGE - - /* Check arguments. */ - HDassert(hdr); - 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)); - - /* Increment ref. count on B-tree header */ - if(H5B2__hdr_incr(hdr) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTINC, FAIL, "can't increment ref. count on B-tree header") - - /* Share B-tree header information */ - leaf->hdr = hdr; - - /* Allocate space for the native keys in memory */ - if(NULL == (leaf->leaf_native = (uint8_t *)H5FL_FAC_MALLOC(hdr->node_info[0].nat_rec_fac))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree leaf native keys") - HDmemset(leaf->leaf_native, 0, hdr->cls->nrec_size * hdr->node_info[0].max_nrec); - - /* Set number of records */ - leaf->nrec = 0; - - /* Allocate space on disk for the leaf */ - if(HADDR_UNDEF == (node_ptr->addr = H5MF_alloc(hdr->f, H5FD_MEM_BTREE, dxpl_id, (hsize_t)hdr->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_insert_entry(hdr->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) - if(H5B2__leaf_free(leaf) < 0) - HDONE_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to release v2 B-tree leaf node") - } /* end if */ - - FUNC_LEAVE_NOAPI(ret_value) -} /* H5B2__create_leaf() */ - - -/*------------------------------------------------------------------------- - * Function: H5B2__protect_leaf - * - * Purpose: "Protect" an leaf node in the metadata cache - * - * Return: Pointer to leaf node on success/NULL on failure - * - * Programmer: Quincey Koziol - * koziol@hdfgroup.org - * May 5 2010 - * - *------------------------------------------------------------------------- - */ -H5B2_leaf_t * -H5B2__protect_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, haddr_t addr, uint16_t nrec, - unsigned flags) -{ - H5B2_leaf_cache_ud_t udata; /* User-data for callback */ - H5B2_leaf_t *ret_value = NULL; /* Return value */ - - FUNC_ENTER_PACKAGE - - /* Check arguments. */ - HDassert(hdr); - HDassert(H5F_addr_defined(addr)); - - /* only H5AC__READ_ONLY_FLAG may appear in flags */ - HDassert((flags & (unsigned)(~H5AC__READ_ONLY_FLAG)) == 0); - - /* Set up user data for callback */ - udata.f = hdr->f; - udata.hdr = hdr; - H5_CHECKED_ASSIGN(udata.nrec, uint16_t, nrec, unsigned) - - /* Protect the leaf node */ - if(NULL == (ret_value = (H5B2_leaf_t *)H5AC_protect(hdr->f, dxpl_id, H5AC_BT2_LEAF, addr, &udata, flags))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, NULL, "unable to protect B-tree leaf node") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5B2__protect_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(H5B2_hdr_t *hdr, hid_t dxpl_id, H5B2_node_ptr_t *node_ptr, - uint16_t depth) -{ - H5B2_internal_t *internal = NULL; /* Pointer to new internal node created */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_STATIC - - /* Check arguments. */ - HDassert(hdr); - HDassert(node_ptr); - HDassert(depth > 0); - - /* 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)); - - /* Increment ref. count on B-tree header */ - if(H5B2__hdr_incr(hdr) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTINC, FAIL, "can't increment ref. count on B-tree header") - - /* Share B-tree header information */ - internal->hdr = hdr; - - /* Allocate space for the native keys in memory */ - if(NULL == (internal->int_native = (uint8_t *)H5FL_FAC_MALLOC(hdr->node_info[depth].nat_rec_fac))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree internal native keys") - HDmemset(internal->int_native, 0, hdr->cls->nrec_size * hdr->node_info[depth].max_nrec); - - /* Allocate space for the node pointers in memory */ - if(NULL == (internal->node_ptrs = (H5B2_node_ptr_t *)H5FL_FAC_MALLOC(hdr->node_info[depth].node_ptr_fac))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree internal node pointers") - HDmemset(internal->node_ptrs, 0, sizeof(H5B2_node_ptr_t) * (hdr->node_info[depth].max_nrec + 1)); - - /* Set number of records & depth of the node */ - internal->nrec = 0; - internal->depth = depth; - - /* Allocate space on disk for the internal node */ - if(HADDR_UNDEF == (node_ptr->addr = H5MF_alloc(hdr->f, H5FD_MEM_BTREE, dxpl_id, (hsize_t)hdr->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_insert_entry(hdr->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) - if(H5B2__internal_free(internal) < 0) - HDONE_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to release v2 B-tree internal node") - } /* end if */ - - FUNC_LEAVE_NOAPI(ret_value) -} /* H5B2__create_internal() */ - - -/*------------------------------------------------------------------------- - * Function: H5B2__protect_internal - * - * Purpose: "Protect" an internal node in the metadata cache - * - * Return: Pointer to internal node on success/NULL on failure - * - * Programmer: Quincey Koziol - * koziol@hdfgroup.org - * Aug 25 2006 - * - *------------------------------------------------------------------------- - */ -H5B2_internal_t * -H5B2__protect_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, haddr_t addr, - uint16_t nrec, uint16_t depth, unsigned flags) -{ - H5B2_internal_cache_ud_t udata; /* User data to pass through to cache 'deserialize' callback */ - H5B2_internal_t *ret_value = NULL; /* Return value */ - - FUNC_ENTER_PACKAGE - - /* Check arguments. */ - HDassert(hdr); - HDassert(H5F_addr_defined(addr)); - HDassert(depth > 0); - - /* only H5AC__READ_ONLY_FLAG may appear in flags */ - HDassert((flags & (unsigned)(~H5AC__READ_ONLY_FLAG)) == 0); - - /* Set up user data for callback */ - udata.f = hdr->f; - udata.hdr = hdr; - udata.nrec = nrec; - udata.depth = depth; - - /* Protect the internal node */ - if(NULL == (ret_value = (H5B2_internal_t *)H5AC_protect(hdr->f, dxpl_id, H5AC_BT2_INT, addr, &udata, flags))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, NULL, "unable to protect B-tree internal node") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5B2__protect_internal() */ +} /* H5B2__insert() */ /*------------------------------------------------------------------------- @@ -2421,13 +1505,15 @@ done: */ herr_t H5B2__iterate_node(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, - const H5B2_node_ptr_t *curr_node, H5B2_operator_t op, void *op_data) + const H5B2_node_ptr_t *curr_node, void *parent, H5B2_operator_t op, + void *op_data) { const H5AC_class_t *curr_node_class = NULL; /* Pointer to current node's class info */ void *node = NULL; /* Pointers to current node */ uint8_t *node_native; /* Pointers to node's native records */ uint8_t *native = NULL; /* Pointers to copy of node's native records */ H5B2_node_ptr_t *node_ptrs = NULL; /* Pointers to node's node pointers */ + hbool_t node_pinned = FALSE; /* Whether node is pinned */ unsigned u; /* Local index */ herr_t ret_value = H5_ITER_CONT; /* Iterator return value */ @@ -2443,7 +1529,7 @@ H5B2__iterate_node(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, H5B2_internal_t *internal; /* Pointer to internal node */ /* Lock the current B-tree node */ - if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, curr_node->addr, curr_node->node_nrec, depth, H5AC__READ_ONLY_FLAG))) + if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, parent, (H5B2_node_ptr_t *)curr_node, depth, FALSE, H5AC__READ_ONLY_FLAG))) /* Casting away const OK -QAK */ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node") /* Set up information about current node */ @@ -2462,7 +1548,7 @@ H5B2__iterate_node(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, H5B2_leaf_t *leaf; /* Pointer to leaf node */ /* Lock the current B-tree node */ - if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, curr_node->addr, curr_node->node_nrec, H5AC__READ_ONLY_FLAG))) + if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, parent, (H5B2_node_ptr_t *)curr_node, FALSE, H5AC__READ_ONLY_FLAG))) /* Casting away const OK -QAK */ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node") /* Set up information about current node */ @@ -2479,15 +1565,18 @@ H5B2__iterate_node(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, HDmemcpy(native, node_native, (hdr->cls->nrec_size * curr_node->node_nrec)); /* Unlock the node */ - if(H5AC_unprotect(hdr->f, dxpl_id, curr_node_class, curr_node->addr, node, H5AC__NO_FLAGS_SET) < 0) + if(H5AC_unprotect(hdr->f, dxpl_id, curr_node_class, curr_node->addr, node, (unsigned)(hdr->swmr_write ? H5AC__PIN_ENTRY_FLAG : H5AC__NO_FLAGS_SET)) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node") - node = NULL; + if(hdr->swmr_write) + node_pinned = TRUE; + else + node = NULL; /* Iterate through records, in order */ 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(hdr, dxpl_id, (uint16_t)(depth - 1), &(node_ptrs[u]), op, op_data)) < 0) + if((ret_value = H5B2__iterate_node(hdr, dxpl_id, (uint16_t)(depth - 1), &(node_ptrs[u]), node, op, op_data)) < 0) HERROR(H5E_BTREE, H5E_CANTLIST, "node iteration failed"); } /* end if */ @@ -2500,11 +1589,15 @@ H5B2__iterate_node(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, /* Descend into last child node, if current node is an internal node */ if(!ret_value && depth > 0) { - if((ret_value = H5B2__iterate_node(hdr, dxpl_id, (uint16_t)(depth - 1), &(node_ptrs[u]), op, op_data)) < 0) + if((ret_value = H5B2__iterate_node(hdr, dxpl_id, (uint16_t)(depth - 1), &(node_ptrs[u]), node, op, op_data)) < 0) HERROR(H5E_BTREE, H5E_CANTLIST, "node iteration failed"); } /* end if */ done: + /* Unpin the node if it was pinned */ + if(node_pinned && H5AC_unpin_entry(node) < 0) + HDONE_ERROR(H5E_BTREE, H5E_CANTUNPIN, FAIL, "can't unpin node") + /* Release the node pointers & native records, if they were copied */ if(node_ptrs) node_ptrs = (H5B2_node_ptr_t *)H5FL_FAC_FREE(hdr->node_info[depth].node_ptr_fac, node_ptrs); @@ -2516,867 +1609,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 - * - *------------------------------------------------------------------------- - */ -herr_t -H5B2__remove_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, H5B2_node_ptr_t *curr_node_ptr, - H5B2_nodepos_t curr_pos, void *udata, H5B2_remove_t op, void *op_data) -{ - 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 */ - unsigned idx; /* Location of record which matches key */ - int cmp; /* Comparison value of records */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_PACKAGE - - /* Check arguments. */ - HDassert(hdr); - 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 = H5B2__protect_leaf(hdr, dxpl_id, leaf_addr, curr_node_ptr->node_nrec, H5AC__NO_FLAGS_SET))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect 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 remove this record */ - if(H5B2__locate_record(hdr->cls, leaf->nrec, hdr->nat_off, leaf->leaf_native, udata, &idx, &cmp) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTCOMPARE, FAIL, "can't compare btree2 records") - if(cmp != 0) - HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "record is not in B-tree") - - /* Check for invalidating the min/max record for the tree */ - if(H5B2_POS_MIDDLE != curr_pos) { - /* (Don't use 'else' for the idx check, to allow for root leaf node) */ - if(idx == 0) { - if(H5B2_POS_LEFT == curr_pos || H5B2_POS_ROOT == curr_pos) { - if(hdr->min_native_rec) - hdr->min_native_rec = H5MM_xfree(hdr->min_native_rec); - } /* end if */ - } /* end if */ - if(idx == (unsigned)(leaf->nrec - 1)) { - if(H5B2_POS_RIGHT == curr_pos || H5B2_POS_ROOT == curr_pos) { - if(hdr->max_native_rec) - hdr->max_native_rec = H5MM_xfree(hdr->max_native_rec); - } /* end if */ - } /* end if */ - } /* end if */ - - /* Make 'remove' callback if there is one */ - if(op) - if((op)(H5B2_LEAF_NREC(leaf, hdr, idx), op_data) < 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, hdr, idx), H5B2_LEAF_NREC(leaf, hdr, (idx + 1)), hdr->cls->nrec_size * (leaf->nrec - idx)); - } /* end if */ - else { - /* Let the cache know that the object is deleted */ - leaf_flags |= H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_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(hdr->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(H5B2_hdr_t *hdr, hid_t dxpl_id, hbool_t *depth_decreased, - void *swap_loc, uint16_t depth, H5AC_info_t *parent_cache_info, - unsigned *parent_cache_info_flags_ptr, H5B2_nodepos_t curr_pos, - H5B2_node_ptr_t *curr_node_ptr, void *udata, H5B2_remove_t op, void *op_data) -{ - 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 */ - H5B2_nodepos_t next_pos = H5B2_POS_MIDDLE; /* Position of next node */ - unsigned internal_flags = H5AC__NO_FLAGS_SET; - haddr_t internal_addr; /* Address of internal node */ - 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; /* Return value */ - - FUNC_ENTER_PACKAGE - - /* Check arguments. */ - HDassert(hdr); - HDassert(depth > 0); - HDassert(parent_cache_info); - 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 = H5B2__protect_internal(hdr, dxpl_id, internal_addr, curr_node_ptr->node_nrec, depth, H5AC__NO_FLAGS_SET))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node") - - /* Determine the correct number of records to merge at */ - merge_nrec = hdr->node_info[depth - 1].merge_nrec; - - /* Check for needing to collapse the root node */ - /* (The root node is the only internal 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(hdr, 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") - - /* Let the cache know that the object is deleted */ - internal_flags |= H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG; - - /* Reset information in header's root 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; - - /* Indicate position of next node */ - next_pos = H5B2_POS_ROOT; - } /* end if */ - /* Merge or redistribute child node pointers, if necessary */ - else { - unsigned idx; /* Location of record which matches key */ - 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 { - if(H5B2__locate_record(hdr->cls, internal->nrec, hdr->nat_off, internal->int_native, - udata, &idx, &cmp) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTCOMPARE, FAIL, "can't compare btree2 records") - 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 */ - /* (NOTE: These 2-node redistributions should actually get the - * record to promote from the node with more records. - QAK) - */ - /* (NOTE: This code is the same in both H5B2__remove_internal() and - * H5B2__remove_internal_by_idx(), fix bugs in both places! - QAK) - */ - if(idx == 0) { /* Left-most child */ - if(retries > 0 && (internal->node_ptrs[idx + 1].node_nrec > merge_nrec)) { - if(H5B2__redistribute2(hdr, 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(hdr, 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(hdr, 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(hdr, 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(hdr, 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(hdr, 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 */ - if(H5B2__locate_record(hdr->cls, internal->nrec, hdr->nat_off, internal->int_native, udata, &idx, &cmp) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTCOMPARE, FAIL, "can't compare btree2 records") - 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, hdr, 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(hdr, 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]; - - /* Indicate position of next node */ - if(H5B2_POS_MIDDLE != curr_pos) { - if(idx == 0) { - if(H5B2_POS_LEFT == curr_pos || H5B2_POS_ROOT == curr_pos) - next_pos = H5B2_POS_LEFT; - } /* end if */ - else if(idx == internal->nrec) { - if(H5B2_POS_RIGHT == curr_pos || H5B2_POS_ROOT == curr_pos) - next_pos = H5B2_POS_RIGHT; - } /* end if */ - } /* end if */ - } /* end else */ - - /* Attempt to remove record from child node */ - if(depth > 1) { - if(H5B2__remove_internal(hdr, dxpl_id, depth_decreased, swap_loc, (uint16_t)(depth - 1), - new_cache_info, new_cache_info_flags_ptr, next_pos, new_node_ptr, udata, op, op_data) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to remove record from B-tree internal node") - } /* end if */ - else { - if(H5B2__remove_leaf(hdr, dxpl_id, new_node_ptr, next_pos, udata, op, op_data) < 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), hdr, internal); -#endif /* H5B2_DEBUG */ - -done: - /* Release the B-tree internal node */ - if(internal && H5AC_unprotect(hdr->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_leaf_by_idx - * - * Purpose: Removes a record from a B-tree leaf node, according to the - * offset in the B-tree records. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@hdfgroup.org - * Nov 14 2006 - * - *------------------------------------------------------------------------- - */ -herr_t -H5B2__remove_leaf_by_idx(H5B2_hdr_t *hdr, hid_t dxpl_id, - H5B2_node_ptr_t *curr_node_ptr, H5B2_nodepos_t curr_pos, - unsigned idx, H5B2_remove_t op, void *op_data) -{ - 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 */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_PACKAGE - - /* Check arguments. */ - HDassert(hdr); - HDassert(curr_node_ptr); - HDassert(H5F_addr_defined(curr_node_ptr->addr)); - - /* Lock B-tree leaf node */ - leaf_addr = curr_node_ptr->addr; - if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, leaf_addr, curr_node_ptr->node_nrec, H5AC__NO_FLAGS_SET))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect 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); - HDassert(idx < leaf->nrec); - - /* Check for invalidating the min/max record for the tree */ - if(H5B2_POS_MIDDLE != curr_pos) { - /* (Don't use 'else' for the idx check, to allow for root leaf node) */ - if(idx == 0) { - if(H5B2_POS_LEFT == curr_pos || H5B2_POS_ROOT == curr_pos) { - if(hdr->min_native_rec) - hdr->min_native_rec = H5MM_xfree(hdr->min_native_rec); - } /* end if */ - } /* end if */ - if(idx == (unsigned)(leaf->nrec - 1)) { - if(H5B2_POS_RIGHT == curr_pos || H5B2_POS_ROOT == curr_pos) { - if(hdr->max_native_rec) - hdr->max_native_rec = H5MM_xfree(hdr->max_native_rec); - } /* end if */ - } /* end if */ - } /* end if */ - - /* Make 'remove' callback if there is one */ - if(op) - if((op)(H5B2_LEAF_NREC(leaf, hdr, idx), op_data) < 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, hdr, idx), H5B2_LEAF_NREC(leaf, hdr, (idx + 1)), hdr->cls->nrec_size * (leaf->nrec - idx)); - } /* end if */ - else { - /* Let the cache know that the object is deleted */ - leaf_flags |= H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_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(hdr->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_by_idx() */ - - -/*------------------------------------------------------------------------- - * Function: H5B2__remove_internal_by_idx - * - * Purpose: Removes a record from a B-tree node, according to the offset - * in the B-tree records - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@hdfgroup.org - * Nov 14 2006 - * - *------------------------------------------------------------------------- - */ -herr_t -H5B2__remove_internal_by_idx(H5B2_hdr_t *hdr, hid_t dxpl_id, - hbool_t *depth_decreased, void *swap_loc, uint16_t depth, - H5AC_info_t *parent_cache_info, unsigned *parent_cache_info_flags_ptr, - H5B2_node_ptr_t *curr_node_ptr, H5B2_nodepos_t curr_pos, hsize_t n, - H5B2_remove_t op, void *op_data) -{ - 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 */ - H5B2_nodepos_t next_pos = H5B2_POS_MIDDLE; /* Position of next node */ - unsigned internal_flags = H5AC__NO_FLAGS_SET; - haddr_t internal_addr; /* Address of internal node */ - 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; /* Return value */ - - FUNC_ENTER_PACKAGE - - /* Check arguments. */ - HDassert(hdr); - HDassert(depth > 0); - HDassert(parent_cache_info); - 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 = H5B2__protect_internal(hdr, dxpl_id, internal_addr, curr_node_ptr->node_nrec, depth, H5AC__NO_FLAGS_SET))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node") - HDassert(internal->nrec == curr_node_ptr->node_nrec); - HDassert(depth == hdr->depth || internal->nrec > 1); - - /* Determine the correct number of records to merge at */ - merge_nrec = hdr->node_info[depth - 1].merge_nrec; - - /* Check for needing to collapse the root node */ - /* (The root node is the only internal 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))) { - HDassert(depth == hdr->depth); - - /* Merge children of root node */ - if(H5B2__merge2(hdr, 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") - - /* Let the cache know that the object is deleted */ - internal_flags |= H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG; - - /* Reset information in header's root 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; - - /* Indicate position of next node */ - next_pos = H5B2_POS_ROOT; - } /* end if */ - /* Merge or redistribute child node pointers, if necessary */ - else { - hsize_t orig_n = n; /* Original index looked for */ - unsigned idx; /* Location of record which matches key */ - hbool_t found = FALSE; /* Comparison value of records */ - unsigned retries; /* Number of times to attempt redistribution */ - - /* Locate node pointer for child */ - if(swap_loc) - idx = 0; - else { - /* Search for record with correct index */ - for(idx = 0; idx < internal->nrec; idx++) { - /* Check which child node contains indexed record */ - if(internal->node_ptrs[idx].all_nrec >= n) { - /* Check if record is in this node */ - if(internal->node_ptrs[idx].all_nrec == n) { - /* Indicate the record was found and that the index - * in child nodes is zero from now on - */ - found = TRUE; - n = 0; - - /* Increment to next record */ - idx++; - } /* end if */ - - /* Break out of loop early */ - break; - } /* end if */ - - /* Decrement index we are looking for to account for the node we - * just advanced past. - */ - n -= (internal->node_ptrs[idx].all_nrec + 1); - } /* end for */ - } /* 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 */ - /* (NOTE: These 2-node redistributions should actually get the - * record to promote from the node with more records. - QAK) - */ - /* (NOTE: This code is the same in both H5B2__remove_internal() and - * H5B2__remove_internal_by_idx(), fix bugs in both places! - QAK) - */ - if(idx == 0) { /* Left-most child */ - if(retries > 0 && (internal->node_ptrs[idx + 1].node_nrec > merge_nrec)) { - if(H5B2__redistribute2(hdr, 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(hdr, 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(hdr, 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(hdr, 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(hdr, 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(hdr, 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 { - /* Count from the orginal index value again */ - n = orig_n; - - /* Reset "found" flag - the record may have shifted during the - * redistribute/merge - */ - found = FALSE; - - /* Search for record with correct index */ - for(idx = 0; idx < internal->nrec; idx++) { - /* Check which child node contains indexed record */ - if(internal->node_ptrs[idx].all_nrec >= n) { - /* Check if record is in this node */ - if(internal->node_ptrs[idx].all_nrec == n) { - /* Indicate the record was found and that the index - * in child nodes is zero from now on - */ - found = TRUE; - n = 0; - - /* Increment to next record */ - idx++; - } /* end if */ - - /* Break out of loop early */ - break; - } /* end if */ - - /* Decrement index we are looking for to account for the node we - * just advanced past. - */ - n -= (internal->node_ptrs[idx].all_nrec + 1); - } /* end for */ - } /* end else */ - - /* Decrement the number of redistribution retries left */ - retries--; - } /* end while */ - - /* Handle deleting a record from an internal node */ - if(!swap_loc && found) - swap_loc = H5B2_INT_NREC(internal, hdr, 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(hdr, 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]; - - /* Indicate position of next node */ - if(H5B2_POS_MIDDLE != curr_pos) { - if(idx == 0) { - if(H5B2_POS_LEFT == curr_pos || H5B2_POS_ROOT == curr_pos) - next_pos = H5B2_POS_LEFT; - } /* end if */ - else if(idx == internal->nrec) { - if(H5B2_POS_RIGHT == curr_pos || H5B2_POS_ROOT == curr_pos) - next_pos = H5B2_POS_RIGHT; - } /* end if */ - } /* end if */ - } /* end else */ - - /* Attempt to remove record from child node */ - if(depth > 1) { - if(H5B2__remove_internal_by_idx(hdr, dxpl_id, depth_decreased, swap_loc, (uint16_t)(depth - 1), - new_cache_info, new_cache_info_flags_ptr, new_node_ptr, next_pos, n, op, op_data) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to remove record from B-tree internal node") - } /* end if */ - else { - if(H5B2__remove_leaf_by_idx(hdr, dxpl_id, new_node_ptr, next_pos, (unsigned)n, op, op_data) < 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 child 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), hdr, internal); -#endif /* H5B2_DEBUG */ - -done: - /* Release the B-tree internal node */ - if(internal && H5AC_unprotect(hdr->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_by_idx() */ - - -/*------------------------------------------------------------------------- - * 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(H5B2_hdr_t *hdr, hid_t dxpl_id, 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 */ - unsigned idx; /* Location of record which matches key */ - int cmp = 0; /* Comparison value of records */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_PACKAGE - - /* Check arguments. */ - HDassert(hdr); - HDassert(curr_node_ptr); - HDassert(H5F_addr_defined(curr_node_ptr->addr)); - HDassert(op); - - /* Lock current B-tree node */ - if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, curr_node_ptr->addr, curr_node_ptr->node_nrec, H5AC__READ_ONLY_FLAG))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node") - - /* Locate node pointer for child */ - if(H5B2__locate_record(hdr->cls, leaf->nrec, hdr->nat_off, leaf->leaf_native, udata, &idx, &cmp) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTCOMPARE, FAIL, "can't compare btree2 records") - 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, hdr, idx - 1); - } /* end if */ - else { - HDassert(comp == H5B2_COMPARE_GREATER); - - if(idx < leaf->nrec) - neighbor_loc = H5B2_LEAF_NREC(leaf, hdr, 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(hdr->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(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t 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 */ - unsigned idx; /* Location of record which matches key */ - int cmp = 0; /* Comparison value of records */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_PACKAGE - - /* Check arguments. */ - HDassert(hdr); - 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 = H5B2__protect_internal(hdr, dxpl_id, curr_node_ptr->addr, curr_node_ptr->node_nrec, depth, H5AC__READ_ONLY_FLAG))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node") - - /* Locate node pointer for child */ - if(H5B2__locate_record(hdr->cls, internal->nrec, hdr->nat_off, internal->int_native, - udata, &idx, &cmp) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTCOMPARE, FAIL, "can't compare btree2 records") - if(cmp > 0) - idx++; - - /* Set the neighbor location, if appropriate */ - if(comp == H5B2_COMPARE_LESS) { - if(idx > 0) - neighbor_loc = H5B2_INT_NREC(internal, hdr, idx - 1); - } /* end if */ - else { - HDassert(comp == H5B2_COMPARE_GREATER); - - if(idx < internal->nrec) - neighbor_loc = H5B2_INT_NREC(internal, hdr, idx); - } /* end else */ - - /* Attempt to find neighboring record */ - if(depth > 1) { - if(H5B2__neighbor_internal(hdr, dxpl_id, (uint16_t)(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(hdr, dxpl_id, &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(hdr->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 @@ -3392,7 +1624,8 @@ done: */ herr_t H5B2__delete_node(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, - const H5B2_node_ptr_t *curr_node, H5B2_remove_t op, void *op_data) + const H5B2_node_ptr_t *curr_node, void *parent, H5B2_remove_t op, + void *op_data) { const H5AC_class_t *curr_node_class = NULL; /* Pointer to current node's class info */ void *node = NULL; /* Pointers to current node */ @@ -3410,7 +1643,7 @@ H5B2__delete_node(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, unsigned u; /* Local index */ /* Lock the current B-tree node */ - if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, curr_node->addr, curr_node->node_nrec, depth, H5AC__NO_FLAGS_SET))) + if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, parent, (H5B2_node_ptr_t *)curr_node, depth, FALSE, H5AC__NO_FLAGS_SET))) /* Casting away const OK -QAK */ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node") /* Set up information about current node */ @@ -3420,14 +1653,14 @@ H5B2__delete_node(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, /* Descend into children */ for(u = 0; u < internal->nrec + (unsigned)1; u++) - if(H5B2__delete_node(hdr, dxpl_id, (uint16_t)(depth - 1), &(internal->node_ptrs[u]), op, op_data) < 0) + if(H5B2__delete_node(hdr, dxpl_id, (uint16_t)(depth - 1), &(internal->node_ptrs[u]), internal, op, op_data) < 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 = H5B2__protect_leaf(hdr, dxpl_id, curr_node->addr, curr_node->node_nrec, H5AC__NO_FLAGS_SET))) + if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, parent, (H5B2_node_ptr_t *)curr_node, FALSE, H5AC__NO_FLAGS_SET))) /* Casting away const OK -QAK */ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node") /* Set up information about current node */ @@ -3450,7 +1683,7 @@ H5B2__delete_node(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, done: /* Unlock & delete current node */ - if(node && H5AC_unprotect(hdr->f, dxpl_id, curr_node_class, curr_node->addr, node, H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0) + if(node && H5AC_unprotect(hdr->f, dxpl_id, curr_node_class, curr_node->addr, node, (unsigned)(H5AC__DELETED_FLAG | (hdr->swmr_write ? 0 : H5AC__FREE_FILE_SPACE_FLAG))) < 0) HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node") FUNC_LEAVE_NOAPI(ret_value) @@ -3472,7 +1705,7 @@ done: */ herr_t H5B2__node_size(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, - const H5B2_node_ptr_t *curr_node, hsize_t *btree_size) + const H5B2_node_ptr_t *curr_node, void *parent, hsize_t *btree_size) { H5B2_internal_t *internal = NULL; /* Pointer to internal node */ herr_t ret_value = SUCCEED; /* Iterator return value */ @@ -3486,7 +1719,7 @@ H5B2__node_size(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, HDassert(depth > 0); /* Lock the current B-tree node */ - if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, curr_node->addr, curr_node->node_nrec, depth, H5AC__READ_ONLY_FLAG))) + if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, parent, (H5B2_node_ptr_t *)curr_node, depth, FALSE, H5AC__READ_ONLY_FLAG))) /* Casting away const OK -QAK */ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node") /* Recursively descend into child nodes, if we are above the "twig" level in the B-tree */ @@ -3495,7 +1728,7 @@ H5B2__node_size(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, /* Descend into children */ for(u = 0; u < internal->nrec + (unsigned)1; u++) - if(H5B2__node_size(hdr, dxpl_id, (uint16_t)(depth - 1), &(internal->node_ptrs[u]), btree_size) < 0) + if(H5B2__node_size(hdr, dxpl_id, (uint16_t)(depth - 1), &(internal->node_ptrs[u]), internal, btree_size) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTLIST, FAIL, "node iteration failed") } /* end if */ else /* depth is 1: count all the leaf nodes from this node */ @@ -3513,219 +1746,205 @@ done: /*------------------------------------------------------------------------- - * Function: H5B2__internal_free + * Function: H5B2__create_flush_depend * - * Purpose: Destroys a B-tree internal node in memory. + * Purpose: Create a flush dependency between two data structure components * - * Return: Non-negative on success/Negative on failure + * Return: SUCCEED/FAIL * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Feb 2 2005 + * Programmer: Dana Robinson + * Fall 2012 * *------------------------------------------------------------------------- */ herr_t -H5B2__internal_free(H5B2_internal_t *internal) +H5B2__create_flush_depend(H5AC_info_t *parent_entry, H5AC_info_t *child_entry) { herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_PACKAGE - - /* - * Check arguments. - */ - HDassert(internal); - - /* Release internal node's native key buffer */ - if(internal->int_native) - internal->int_native = (uint8_t *)H5FL_FAC_FREE(internal->hdr->node_info[internal->depth].nat_rec_fac, internal->int_native); - - /* Release internal node's node pointer buffer */ - if(internal->node_ptrs) - internal->node_ptrs = (H5B2_node_ptr_t *)H5FL_FAC_FREE(internal->hdr->node_info[internal->depth].node_ptr_fac, internal->node_ptrs); - - /* Decrement ref. count on B-tree header */ - if(H5B2__hdr_decr(internal->hdr) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTDEC, FAIL, "can't decrement ref. count on B-tree header") + FUNC_ENTER_NOAPI_NOINIT + + /* Sanity check */ + HDassert(parent_entry); + HDassert(child_entry); - /* Free B-tree internal node info */ - internal = H5FL_FREE(H5B2_internal_t, internal); + /* Create a flush dependency between parent and child entry */ + if(H5AC_create_flush_dependency(parent_entry, child_entry) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to create flush dependency") done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5B2__internal_free() */ +} /* end H5B2__create_flush_depend() */ /*------------------------------------------------------------------------- - * Function: H5B2__leaf_free + * Function: H5B2__update_flush_depend * - * Purpose: Destroys a B-tree leaf node in memory. + * Purpose: Update flush dependencies for children of a node * - * Return: Non-negative on success/Negative on failure + * Return: SUCCEED/FAIL * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Feb 2 2005 + * Programmer: Quincey Koziol + * koziol@lbl.gov + * Dec 1 2016 * *------------------------------------------------------------------------- */ herr_t -H5B2__leaf_free(H5B2_leaf_t *leaf) +H5B2__update_flush_depend(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth, + const H5B2_node_ptr_t *node_ptr, void *old_parent, void *new_parent) { + const H5AC_class_t *child_class; /* Pointer to child node's class info */ + void *child = NULL; /* Pointer to child node */ + unsigned node_status = 0; /* Node's status in the metadata cache */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE + + /* Sanity checks */ + HDassert(hdr); + HDassert(depth > 0); + HDassert(node_ptr); + HDassert(old_parent); + HDassert(new_parent); - /* - * Check arguments. - */ - HDassert(leaf); + /* Check the node's entry status in the metadata cache */ + if(H5AC_get_entry_status(hdr->f, node_ptr->addr, &node_status) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTGET, FAIL, "unable to check status of B-tree node") - /* Release leaf's native key buffer */ - if(leaf->leaf_native) - leaf->leaf_native = (uint8_t *)H5FL_FAC_FREE(leaf->hdr->node_info[0].nat_rec_fac, leaf->leaf_native); + /* If the node is in the cache, check for retargeting its parent */ + if(node_status & H5AC_ES__IN_CACHE) { + void **parent_ptr; /* Pointer to child node's parent */ + hbool_t update_deps = FALSE; /* Whether to update flush dependencies */ - /* Decrement ref. count on B-tree header */ - if(H5B2__hdr_decr(leaf->hdr) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTDEC, FAIL, "can't decrement ref. count on B-tree header") + /* Get child node pointer */ + if(depth > 1) { + H5B2_internal_t *child_int; - /* Free B-tree leaf node info */ - leaf = H5FL_FREE(H5B2_leaf_t, leaf); + /* Protect child */ + if(NULL == (child_int = H5B2__protect_internal(hdr, dxpl_id, new_parent, (H5B2_node_ptr_t *)node_ptr, (uint16_t)(depth - 1), FALSE, H5AC__NO_FLAGS_SET))) /* Casting away const OK -QAK */ + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node") + child_class = H5AC_BT2_INT; + child = child_int; -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5B2__leaf_free() */ + if(child_int->parent == old_parent) { + parent_ptr = &child_int->parent; + update_deps = TRUE; + } /* end if */ + else + HDassert(child_int->parent == new_parent); + } /* end if */ + else { + H5B2_leaf_t *child_leaf; -#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 - * - *------------------------------------------------------------------------- - */ -H5_ATTR_PURE static herr_t -H5B2__assert_leaf(const H5B2_hdr_t *hdr, const H5B2_leaf_t *leaf) -{ - /* General sanity checking on node */ - HDassert(leaf->nrec <= hdr->node_info->split_nrec); + /* Protect child */ + if(NULL == (child_leaf = H5B2__protect_leaf(hdr, dxpl_id, new_parent, (H5B2_node_ptr_t *)node_ptr, FALSE, H5AC__NO_FLAGS_SET))) /* Casting away const OK -QAK */ + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node") + child_class = H5AC_BT2_LEAF; + child = child_leaf; - return(0); -} /* end H5B2__assert_leaf() */ + if(child_leaf->parent == old_parent) { + parent_ptr = &child_leaf->parent; + update_deps = TRUE; + } /* end if */ + else + HDassert(child_leaf->parent == new_parent); + } /* end else */ - -/*------------------------------------------------------------------------- - * 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 - * - *------------------------------------------------------------------------- - */ -H5_ATTR_PURE static herr_t -H5B2__assert_leaf2(const H5B2_hdr_t *hdr, const H5B2_leaf_t *leaf, const H5B2_leaf_t H5_ATTR_UNUSED *leaf2) -{ - /* General sanity checking on node */ - HDassert(leaf->nrec <= hdr->node_info->split_nrec); + /* Update flush dependencies if necessary */ + if(update_deps) { + /* Sanity check */ + HDassert(parent_ptr); + + /* Switch the flush dependency for the node */ + if(H5B2__destroy_flush_depend((H5AC_info_t *)old_parent, (H5AC_info_t *)child) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency") + *parent_ptr = new_parent; + if(H5B2__create_flush_depend((H5AC_info_t *)new_parent, (H5AC_info_t *)child) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to create flush dependency") + } /* end if */ + } /* end if */ - return(0); -} /* end H5B2__assert_leaf2() */ +done: + /* Unprotect the child */ + if(child) + if(H5AC_unprotect(hdr->f, dxpl_id, child_class, node_ptr->addr, child, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5B2__update_flush_depend() */ /*------------------------------------------------------------------------- - * Function: H5B2__assert_internal + * Function: H5B2__update_child_flush_depends * - * Purpose: Verify than an internal node is mostly sane + * Purpose: Update flush dependencies for children of a node * - * Return: Non-negative on success, negative on failure + * Return: SUCCEED/FAIL * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Feb 19 2005 + * Programmer: Quincey Koziol + * koziol@lbl.gov + * Dec 1 2016 * *------------------------------------------------------------------------- */ -H5_ATTR_PURE static herr_t -H5B2__assert_internal(hsize_t parent_all_nrec, const H5B2_hdr_t *hdr, const H5B2_internal_t *internal) +static herr_t +H5B2__update_child_flush_depends(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth, + const H5B2_node_ptr_t *node_ptrs, unsigned start_idx, unsigned end_idx, + void *old_parent, void *new_parent) { - hsize_t tot_all_nrec; /* Total number of records at or below this node */ - uint16_t u, v; /* Local index variables */ - - /* General sanity checking on node */ - HDassert(internal->nrec <= hdr->node_info->split_nrec); - - /* 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 */ + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ - /* Sanity check all_nrec total in parent */ - if(parent_all_nrec > 0) - HDassert(tot_all_nrec == parent_all_nrec); + FUNC_ENTER_STATIC + + /* Sanity checks */ + HDassert(hdr); + HDassert(depth > 1); + HDassert(node_ptrs); + HDassert(start_idx <= end_idx); + HDassert(old_parent); + HDassert(new_parent); + + /* Loop over children */ + for(u = start_idx; u < end_idx; u++) + /* Update parent for children */ + if(H5B2__update_flush_depend(hdr, dxpl_id, depth - 1, &node_ptrs[u], old_parent, new_parent) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUPDATE, FAIL, "unable to update child node to new parent") - return(0); -} /* end H5B2__assert_internal() */ +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5B2__update_child_flush_depends() */ /*------------------------------------------------------------------------- - * Function: H5B2__assert_internal2 + * Function: H5B2__destroy_flush_depend * - * Purpose: Verify than internal nodes are mostly sane + * Purpose: Destroy a flush dependency between two data structure components * - * Return: Non-negative on success, negative on failure + * Return: SUCCEED/FAIL * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Feb 19 2005 + * Programmer: Dana Robinson + * Fall 2012 * *------------------------------------------------------------------------- */ -H5_ATTR_PURE static herr_t -H5B2__assert_internal2(hsize_t parent_all_nrec, const H5B2_hdr_t *hdr, const H5B2_internal_t *internal, const H5B2_internal_t *internal2) +herr_t +H5B2__destroy_flush_depend(H5AC_info_t *parent_entry, H5AC_info_t *child_entry) { - hsize_t tot_all_nrec; /* Total number of records at or below this node */ - uint16_t u, v; /* Local index variables */ - - /* General sanity checking on node */ - HDassert(internal->nrec <= hdr->node_info->split_nrec); - - /* 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 */ + herr_t ret_value = SUCCEED; /* Return value */ - /* Sanity check all_nrec total in parent */ - if(parent_all_nrec > 0) - HDassert(tot_all_nrec == parent_all_nrec); + FUNC_ENTER_NOAPI_NOINIT + + /* Sanity check */ + HDassert(parent_entry); + HDassert(child_entry); - return(0); -} /* end H5B2__assert_internal2() */ -#endif /* H5B2_DEBUG */ + /* Destroy a flush dependency between parent and child entry */ + if(H5AC_destroy_flush_dependency(parent_entry, child_entry) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5B2__destroy_flush_depend() */ |