#include "H5B2module.h"
#include "H5private.h"
#include "H5B2pkg.h"
#include "H5Eprivate.h"
#include "H5MMprivate.h"
#include "H5VMprivate.h"
static herr_t H5B2__update_child_flush_depends(H5B2_hdr_t *hdr,
unsigned depth, const H5B2_node_ptr_t *node_ptrs, unsigned start_idx,
unsigned end_idx, void *old_parent, void *new_parent);
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)
{
unsigned lo = 0, hi;
unsigned my_idx = 0;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
*cmp = -1;
hi = nrec;
while(lo < hi && *cmp) {
my_idx = (lo + hi) / 2;
if((type->compare)(udata, native + rec_off[my_idx], cmp) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTCOMPARE, FAIL, "can't compare btree2 records")
if(*cmp < 0)
hi = my_idx;
else
lo = my_idx + 1;
}
*idx = my_idx;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5B2__split1(H5B2_hdr_t *hdr, 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)
{
const H5AC_class_t *child_class;
haddr_t left_addr, right_addr;
void *left_child = NULL, *right_child = NULL;
uint16_t *left_nrec, *right_nrec;
uint8_t *left_native, *right_native;
H5B2_node_ptr_t *left_node_ptrs = NULL, *right_node_ptrs = NULL;
uint16_t mid_record;
uint16_t old_node_nrec;
unsigned left_child_flags = H5AC__NO_FLAGS_SET, right_child_flags = H5AC__NO_FLAGS_SET;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(hdr);
HDassert(internal);
HDassert(internal_flags_ptr);
if(idx < internal->nrec) {
HDmemmove(H5B2_INT_NREC(internal, hdr, idx + 1), H5B2_INT_NREC(internal, hdr, idx), hdr->cls->nrec_size * (internal->nrec - idx));
HDmemmove(&(internal->node_ptrs[idx + 2]), &(internal->node_ptrs[idx + 1]), sizeof(H5B2_node_ptr_t) * (internal->nrec - idx));
}
if(depth > 1) {
H5B2_internal_t *left_int = NULL, *right_int = NULL;
internal->node_ptrs[idx + 1].all_nrec = internal->node_ptrs[idx + 1].node_nrec = 0;
if(H5B2__create_internal(hdr, internal, &(internal->node_ptrs[idx + 1]), (uint16_t)(depth - 1)) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new internal node")
child_class = H5AC_BT2_INT;
if(NULL == (left_int = H5B2__protect_internal(hdr, 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")
left_addr = internal->node_ptrs[idx].addr;
if(NULL == (right_int = H5B2__protect_internal(hdr, 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;
left_child = left_int;
right_child = right_int;
left_nrec = &(left_int->nrec);
right_nrec = &(right_int->nrec);
left_native = left_int->int_native;
right_native = right_int->int_native;
left_node_ptrs = left_int->node_ptrs;
right_node_ptrs = right_int->node_ptrs;
}
else {
H5B2_leaf_t *left_leaf = NULL, *right_leaf = NULL;
internal->node_ptrs[idx + 1].all_nrec = internal->node_ptrs[idx + 1].node_nrec = 0;
if(H5B2__create_leaf(hdr, internal, &(internal->node_ptrs[idx + 1])) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new leaf node")
child_class = H5AC_BT2_LEAF;
if(NULL == (left_leaf = H5B2__protect_leaf(hdr, 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")
left_addr = internal->node_ptrs[idx].addr;
if(NULL == (right_leaf = H5B2__protect_leaf(hdr, 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;
left_child = left_leaf;
right_child = right_leaf;
left_nrec = &(left_leaf->nrec);
right_nrec = &(right_leaf->nrec);
left_native = left_leaf->leaf_native;
right_native = right_leaf->leaf_native;
}
old_node_nrec = internal->node_ptrs[idx].node_nrec;
mid_record = (uint16_t)(old_node_nrec / 2);
H5MM_memcpy(H5B2_NAT_NREC(right_native, hdr, 0),
H5B2_NAT_NREC(left_native, hdr, mid_record + (unsigned)1),
hdr->cls->nrec_size * (old_node_nrec - (mid_record + (unsigned)1)));
if(depth > 1)
H5MM_memcpy(&(right_node_ptrs[0]), &(left_node_ptrs[mid_record + (unsigned)1]),
sizeof(H5B2_node_ptr_t) * (size_t)(old_node_nrec - mid_record));
H5MM_memcpy(H5B2_INT_NREC(internal, hdr, idx), H5B2_NAT_NREC(left_native, hdr, mid_record), hdr->cls->nrec_size);
left_child_flags |= H5AC__DIRTIED_FLAG;
right_child_flags |= H5AC__DIRTIED_FLAG;
internal->node_ptrs[idx].node_nrec = *left_nrec = mid_record;
internal->node_ptrs[idx + 1].node_nrec = *right_nrec = (uint16_t)(old_node_nrec - (mid_record + 1));
if(depth > 1) {
unsigned u;
hsize_t new_left_all_nrec;
hsize_t new_right_all_nrec;
new_left_all_nrec = internal->node_ptrs[idx].node_nrec;
for(u = 0; u < (*left_nrec + (unsigned)1); u++)
new_left_all_nrec += left_node_ptrs[u].all_nrec;
new_right_all_nrec = internal->node_ptrs[idx + 1].node_nrec;
for(u = 0; u < (*right_nrec + (unsigned)1); u++)
new_right_all_nrec += right_node_ptrs[u].all_nrec;
internal->node_ptrs[idx].all_nrec = new_left_all_nrec;
internal->node_ptrs[idx + 1].all_nrec = new_right_all_nrec;
}
else {
internal->node_ptrs[idx].all_nrec = internal->node_ptrs[idx].node_nrec;
internal->node_ptrs[idx + 1].all_nrec = internal->node_ptrs[idx + 1].node_nrec;
}
internal->nrec++;
*internal_flags_ptr |= H5AC__DIRTIED_FLAG;
curr_node_ptr->node_nrec++;
if(parent_cache_info_flags_ptr)
*parent_cache_info_flags_ptr |= H5AC__DIRTIED_FLAG;
if(hdr->swmr_write && depth > 1)
if(H5B2__update_child_flush_depends(hdr, 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) {
H5B2__assert_internal2(internal->node_ptrs[idx].all_nrec, hdr, (H5B2_internal_t *)left_child, (H5B2_internal_t *)right_child);
H5B2__assert_internal2(internal->node_ptrs[idx + 1].all_nrec, hdr, (H5B2_internal_t *)right_child, (H5B2_internal_t *)left_child);
}
else {
H5B2__assert_leaf2(hdr, (H5B2_leaf_t *)left_child, (H5B2_leaf_t *)right_child);
H5B2__assert_leaf(hdr, (H5B2_leaf_t *)right_child);
}
#endif
done:
if(left_child && H5AC_unprotect(hdr->f, child_class, left_addr, left_child, left_child_flags) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree leaf node")
if(right_child && H5AC_unprotect(hdr->f, child_class, right_addr, right_child, right_child_flags) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree leaf node")
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5B2__split_root(H5B2_hdr_t *hdr)
{
H5B2_internal_t *new_root = NULL;
unsigned new_root_flags = H5AC__NO_FLAGS_SET;
H5B2_node_ptr_t old_root_ptr;
size_t sz_max_nrec;
unsigned u_max_nrec_size;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(hdr);
hdr->depth++;
if(NULL == (hdr->node_info = H5FL_SEQ_REALLOC(H5B2_node_info_t, hdr->node_info, (size_t)(hdr->depth + 1))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
sz_max_nrec = H5B2_NUM_INT_REC(hdr, hdr->depth);
H5_CHECKED_ASSIGN(hdr->node_info[hdr->depth].max_nrec, unsigned, sz_max_nrec, size_t)
hdr->node_info[hdr->depth].split_nrec = (hdr->node_info[hdr->depth].max_nrec * hdr->split_percent) / 100;
hdr->node_info[hdr->depth].merge_nrec = (hdr->node_info[hdr->depth].max_nrec * hdr->merge_percent) / 100;
hdr->node_info[hdr->depth].cum_max_nrec = ((hdr->node_info[hdr->depth].max_nrec + 1) *
hdr->node_info[hdr->depth - 1].cum_max_nrec) + hdr->node_info[hdr->depth].max_nrec;
u_max_nrec_size = H5VM_limit_enc_size((uint64_t)hdr->node_info[hdr->depth].cum_max_nrec);
H5_CHECKED_ASSIGN(hdr->node_info[hdr->depth].cum_max_nrec_size, uint8_t, u_max_nrec_size, unsigned)
if(NULL == (hdr->node_info[hdr->depth].nat_rec_fac = H5FL_fac_init(hdr->cls->nrec_size * hdr->node_info[hdr->depth].max_nrec)))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create node native key block factory")
if(NULL == (hdr->node_info[hdr->depth].node_ptr_fac = H5FL_fac_init(sizeof(H5B2_node_ptr_t) * (hdr->node_info[hdr->depth].max_nrec + 1))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create internal 'branch' node node pointer block factory")
old_root_ptr = hdr->root;
hdr->root.node_nrec = 0;
if(H5B2__create_internal(hdr, hdr, &(hdr->root), hdr->depth) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new internal node")
if(NULL == (new_root = H5B2__protect_internal(hdr, hdr, &hdr->root, hdr->depth, FALSE, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
new_root->node_ptrs[0] = old_root_ptr;
if(H5B2__split1(hdr, hdr->depth, &(hdr->root), NULL, new_root, &new_root_flags, 0) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to split old root node")
done:
if(new_root && H5AC_unprotect(hdr->f, H5AC_BT2_INT, hdr->root.addr, new_root, new_root_flags) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree internal node")
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5B2__redistribute2(H5B2_hdr_t *hdr, uint16_t depth, H5B2_internal_t *internal,
unsigned idx)
{
const H5AC_class_t *child_class;
haddr_t left_addr, right_addr;
void *left_child = NULL, *right_child = NULL;
uint16_t *left_nrec, *right_nrec;
uint8_t *left_native, *right_native;
H5B2_node_ptr_t *left_node_ptrs = NULL, *right_node_ptrs = NULL;
hssize_t left_moved_nrec = 0, right_moved_nrec = 0;
unsigned left_child_flags = H5AC__NO_FLAGS_SET, right_child_flags = H5AC__NO_FLAGS_SET;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(hdr);
HDassert(internal);
if(depth > 1) {
H5B2_internal_t *left_internal;
H5B2_internal_t *right_internal;
child_class = H5AC_BT2_INT;
if(NULL == (left_internal = H5B2__protect_internal(hdr, 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")
left_addr = internal->node_ptrs[idx].addr;
if(NULL == (right_internal = H5B2__protect_internal(hdr, 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;
left_child = left_internal;
right_child = right_internal;
left_nrec = &(left_internal->nrec);
right_nrec = &(right_internal->nrec);
left_native = left_internal->int_native;
right_native = right_internal->int_native;
left_node_ptrs = left_internal->node_ptrs;
right_node_ptrs = right_internal->node_ptrs;
}
else {
H5B2_leaf_t *left_leaf;
H5B2_leaf_t *right_leaf;
child_class = H5AC_BT2_LEAF;
if(NULL == (left_leaf = H5B2__protect_leaf(hdr, 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")
left_addr = internal->node_ptrs[idx].addr;
if(NULL == (right_leaf = H5B2__protect_leaf(hdr, 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;
left_child = left_leaf;
right_child = right_leaf;
left_nrec = &(left_leaf->nrec);
right_nrec = &(right_leaf->nrec);
left_native = left_leaf->leaf_native;
right_native = right_leaf->leaf_native;
}
#ifdef H5B2_DEBUG
H5B2__assert_internal((hsize_t)0, hdr, internal);
if(depth > 1) {
H5B2__assert_internal2(internal->node_ptrs[idx].all_nrec, hdr, (H5B2_internal_t *)left_child, (H5B2_internal_t *)right_child);
H5B2__assert_internal2(internal->node_ptrs[idx + 1].all_nrec, hdr, (H5B2_internal_t *)right_child, (H5B2_internal_t *)left_child);
}
else {
H5B2__assert_leaf2(hdr, (H5B2_leaf_t *)left_child, (H5B2_leaf_t *)right_child);
H5B2__assert_leaf(hdr, (H5B2_leaf_t *)right_child);
}
#endif
if(*left_nrec < *right_nrec) {
uint16_t new_right_nrec = (uint16_t)((*left_nrec + *right_nrec) / 2);
uint16_t move_nrec = (uint16_t)(*right_nrec - new_right_nrec);
H5MM_memcpy(H5B2_NAT_NREC(left_native, hdr, *left_nrec), H5B2_INT_NREC(internal, hdr, idx), hdr->cls->nrec_size);
if(move_nrec > 1)
H5MM_memcpy(H5B2_NAT_NREC(left_native, hdr, (*left_nrec + 1)), H5B2_NAT_NREC(right_native, hdr, 0), hdr->cls->nrec_size * (size_t)(move_nrec - 1));
H5MM_memcpy(H5B2_INT_NREC(internal, hdr, idx), H5B2_NAT_NREC(right_native, hdr, (move_nrec - 1)), hdr->cls->nrec_size);
HDmemmove(H5B2_NAT_NREC(right_native, hdr, 0), H5B2_NAT_NREC(right_native, hdr, move_nrec), hdr->cls->nrec_size * new_right_nrec);
if(depth > 1) {
hsize_t moved_nrec = move_nrec;
unsigned u;
for(u = 0; u < move_nrec; u++)
moved_nrec += right_node_ptrs[u].all_nrec;
H5_CHECKED_ASSIGN(left_moved_nrec, hssize_t, moved_nrec, hsize_t)
right_moved_nrec -= (hssize_t)moved_nrec;
H5MM_memcpy(&(left_node_ptrs[*left_nrec + 1]), &(right_node_ptrs[0]), sizeof(H5B2_node_ptr_t) * move_nrec);
HDmemmove(&(right_node_ptrs[0]), &(right_node_ptrs[move_nrec]), sizeof(H5B2_node_ptr_t) * (new_right_nrec + (unsigned)1));
}
if(hdr->swmr_write && depth > 1)
if(H5B2__update_child_flush_depends(hdr, 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")
*left_nrec = (uint16_t)(*left_nrec + move_nrec);
*right_nrec = new_right_nrec;
left_child_flags |= H5AC__DIRTIED_FLAG;
right_child_flags |= H5AC__DIRTIED_FLAG;
}
else {
uint16_t new_left_nrec = (uint16_t)((*left_nrec + *right_nrec) / 2);
uint16_t move_nrec = (uint16_t)(*left_nrec - new_left_nrec);
HDassert(*left_nrec > *right_nrec);
HDmemmove(H5B2_NAT_NREC(right_native, hdr, move_nrec),
H5B2_NAT_NREC(right_native, hdr, 0),
hdr->cls->nrec_size * (*right_nrec));
H5MM_memcpy(H5B2_NAT_NREC(right_native, hdr, (move_nrec - 1)), H5B2_INT_NREC(internal, hdr, idx), hdr->cls->nrec_size);
if(move_nrec > 1)
H5MM_memcpy(H5B2_NAT_NREC(right_native, hdr, 0), H5B2_NAT_NREC(left_native, hdr, ((*left_nrec - move_nrec) + 1)), hdr->cls->nrec_size * (size_t)(move_nrec - 1));
H5MM_memcpy(H5B2_INT_NREC(internal, hdr, idx), H5B2_NAT_NREC(left_native, hdr, (*left_nrec - move_nrec)), hdr->cls->nrec_size);
if(depth > 1) {
hsize_t moved_nrec = move_nrec;
unsigned u;
HDmemmove(&(right_node_ptrs[move_nrec]), &(right_node_ptrs[0]), sizeof(H5B2_node_ptr_t) * (size_t)(*right_nrec + 1));
H5MM_memcpy(&(right_node_ptrs[0]), &(left_node_ptrs[new_left_nrec + 1]), sizeof(H5B2_node_ptr_t) * move_nrec);
for(u = 0; u < move_nrec; u++)
moved_nrec += right_node_ptrs[u].all_nrec;
left_moved_nrec -= (hssize_t)moved_nrec;
H5_CHECKED_ASSIGN(right_moved_nrec, hssize_t, moved_nrec, hsize_t)
}
if(hdr->swmr_write && depth > 1)
if(H5B2__update_child_flush_depends(hdr, 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")
*left_nrec = new_left_nrec;
*right_nrec = (uint16_t)(*right_nrec + move_nrec);
left_child_flags |= H5AC__DIRTIED_FLAG;
right_child_flags |= H5AC__DIRTIED_FLAG;
}
internal->node_ptrs[idx].node_nrec = *left_nrec;
internal->node_ptrs[idx + 1].node_nrec = *right_nrec;
if(depth > 1) {
internal->node_ptrs[idx].all_nrec = (hsize_t)((hssize_t)internal->node_ptrs[idx].all_nrec + left_moved_nrec);
internal->node_ptrs[idx + 1].all_nrec = (hsize_t)((hssize_t)internal->node_ptrs[idx + 1].all_nrec + right_moved_nrec);
}
else {
internal->node_ptrs[idx].all_nrec = internal->node_ptrs[idx].node_nrec;
internal->node_ptrs[idx + 1].all_nrec = internal->node_ptrs[idx + 1].node_nrec;
}
#ifdef H5B2_DEBUG
H5B2__assert_internal((hsize_t)0, hdr, internal);
if(depth > 1) {
H5B2__assert_internal2(internal->node_ptrs[idx].all_nrec, hdr, (H5B2_internal_t *)left_child, (H5B2_internal_t *)right_child);
H5B2__assert_internal2(internal->node_ptrs[idx + 1].all_nrec, hdr, (H5B2_internal_t *)right_child, (H5B2_internal_t *)left_child);
}
else {
H5B2__assert_leaf2(hdr, (H5B2_leaf_t *)left_child, (H5B2_leaf_t *)right_child);
H5B2__assert_leaf(hdr, (H5B2_leaf_t *)right_child);
}
#endif
done:
if(left_child && H5AC_unprotect(hdr->f, child_class, left_addr, left_child, left_child_flags) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
if(right_child && H5AC_unprotect(hdr->f, child_class, right_addr, right_child, right_child_flags) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5B2__redistribute3(H5B2_hdr_t *hdr, uint16_t depth, H5B2_internal_t *internal,
unsigned *internal_flags_ptr, unsigned idx)
{
H5B2_node_ptr_t *left_node_ptrs = NULL, *right_node_ptrs = NULL;
H5B2_node_ptr_t *middle_node_ptrs = NULL;
const H5AC_class_t *child_class;
haddr_t left_addr, right_addr;
haddr_t middle_addr;
void *left_child = NULL, *right_child = NULL;
void *middle_child = NULL;
uint16_t *left_nrec, *right_nrec;
uint16_t *middle_nrec;
uint8_t *left_native, *right_native;
uint8_t *middle_native;
hssize_t left_moved_nrec = 0, right_moved_nrec = 0;
hssize_t middle_moved_nrec = 0;
unsigned left_child_flags = H5AC__NO_FLAGS_SET, right_child_flags = H5AC__NO_FLAGS_SET;
unsigned middle_child_flags = H5AC__NO_FLAGS_SET;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(hdr);
HDassert(internal);
HDassert(internal_flags_ptr);
if(depth > 1) {
H5B2_internal_t *left_internal;
H5B2_internal_t *middle_internal;
H5B2_internal_t *right_internal;
child_class = H5AC_BT2_INT;
if(NULL == (left_internal = H5B2__protect_internal(hdr, 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")
left_addr = internal->node_ptrs[idx - 1].addr;
if(NULL == (middle_internal = H5B2__protect_internal(hdr, 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")
middle_addr = internal->node_ptrs[idx].addr;
if(NULL == (right_internal = H5B2__protect_internal(hdr, 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;
left_child = left_internal;
middle_child = middle_internal;
right_child = right_internal;
left_nrec = &(left_internal->nrec);
middle_nrec = &(middle_internal->nrec);
right_nrec = &(right_internal->nrec);
left_native = left_internal->int_native;
middle_native = middle_internal->int_native;
right_native = right_internal->int_native;
left_node_ptrs = left_internal->node_ptrs;
middle_node_ptrs = middle_internal->node_ptrs;
right_node_ptrs = right_internal->node_ptrs;
}
else {
H5B2_leaf_t *left_leaf;
H5B2_leaf_t *middle_leaf;
H5B2_leaf_t *right_leaf;
child_class = H5AC_BT2_LEAF;
if(NULL == (left_leaf = H5B2__protect_leaf(hdr, 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")
left_addr = internal->node_ptrs[idx - 1].addr;
if(NULL == (middle_leaf = H5B2__protect_leaf(hdr, 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")
middle_addr = internal->node_ptrs[idx].addr;
if(NULL == (right_leaf = H5B2__protect_leaf(hdr, 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;
left_child = left_leaf;
middle_child = middle_leaf;
right_child = right_leaf;
left_nrec = &(left_leaf->nrec);
middle_nrec = &(middle_leaf->nrec);
right_nrec = &(right_leaf->nrec);
left_native = left_leaf->leaf_native;
middle_native = middle_leaf->leaf_native;
right_native = right_leaf->leaf_native;
}
{
unsigned total_nrec = (unsigned)(*left_nrec + *middle_nrec + *right_nrec + 2);
uint16_t new_middle_nrec = (uint16_t)((total_nrec - 2) / 3);
uint16_t new_left_nrec = (uint16_t)(((total_nrec - 2) - new_middle_nrec) / 2);
uint16_t new_right_nrec = (uint16_t)((total_nrec - 2) - (unsigned)(new_left_nrec + new_middle_nrec));
uint16_t curr_middle_nrec = *middle_nrec;
HDassert(new_middle_nrec <= new_left_nrec);
HDassert(new_middle_nrec <= new_right_nrec);
if(new_left_nrec > *left_nrec) {
uint16_t moved_middle_nrec = 0;
H5MM_memcpy(H5B2_NAT_NREC(left_native, hdr, *left_nrec), H5B2_INT_NREC(internal, hdr, idx - 1), hdr->cls->nrec_size);
if((new_left_nrec - 1) > *left_nrec) {
moved_middle_nrec = (uint16_t)(new_left_nrec - (*left_nrec + 1));
H5MM_memcpy(H5B2_NAT_NREC(left_native, hdr, *left_nrec + 1), H5B2_NAT_NREC(middle_native, hdr, 0), hdr->cls->nrec_size * moved_middle_nrec);
}
H5MM_memcpy(H5B2_INT_NREC(internal, hdr, idx - 1), H5B2_NAT_NREC(middle_native, hdr, moved_middle_nrec), hdr->cls->nrec_size);
moved_middle_nrec++;
HDmemmove(H5B2_NAT_NREC(middle_native, hdr, 0), H5B2_NAT_NREC(middle_native, hdr, moved_middle_nrec), hdr->cls->nrec_size * (size_t)(*middle_nrec - moved_middle_nrec));
if(depth > 1) {
hsize_t moved_nrec;
unsigned move_nptrs;
unsigned u;
move_nptrs = (unsigned)(new_left_nrec - *left_nrec);
H5MM_memcpy(&(left_node_ptrs[*left_nrec + 1]), &(middle_node_ptrs[0]), sizeof(H5B2_node_ptr_t)*move_nptrs);
for(u = 0, moved_nrec = 0; u < move_nptrs; u++)
moved_nrec += middle_node_ptrs[u].all_nrec;
left_moved_nrec = (hssize_t)(moved_nrec + move_nptrs);
middle_moved_nrec -= (hssize_t)(moved_nrec + move_nptrs);
HDmemmove(&(middle_node_ptrs[0]), &(middle_node_ptrs[move_nptrs]), sizeof(H5B2_node_ptr_t) * ((*middle_nrec - move_nptrs) + 1));
}
if(hdr->swmr_write && depth > 1)
if(H5B2__update_child_flush_depends(hdr, 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")
curr_middle_nrec = (uint16_t)(curr_middle_nrec - moved_middle_nrec);
left_child_flags |= H5AC__DIRTIED_FLAG;
middle_child_flags |= H5AC__DIRTIED_FLAG;
}
if(new_right_nrec > *right_nrec) {
unsigned right_nrec_move = (unsigned)(new_right_nrec - *right_nrec);
HDmemmove(H5B2_NAT_NREC(right_native, hdr, right_nrec_move), H5B2_NAT_NREC(right_native, hdr, 0), hdr->cls->nrec_size * (*right_nrec));
H5MM_memcpy(H5B2_NAT_NREC(right_native, hdr, right_nrec_move - 1), H5B2_INT_NREC(internal, hdr, idx), hdr->cls->nrec_size);
if(right_nrec_move > 1)
H5MM_memcpy(H5B2_NAT_NREC(right_native, hdr, 0), H5B2_NAT_NREC(middle_native, hdr, ((curr_middle_nrec - right_nrec_move) + 1)), hdr->cls->nrec_size * (right_nrec_move - 1));
H5MM_memcpy(H5B2_INT_NREC(internal, hdr, idx), H5B2_NAT_NREC(middle_native, hdr, (curr_middle_nrec - right_nrec_move)), hdr->cls->nrec_size);
if(depth > 1) {
hsize_t moved_nrec;
unsigned u;
HDmemmove(&(right_node_ptrs[right_nrec_move]), &(right_node_ptrs[0]), sizeof(H5B2_node_ptr_t) * (size_t)(*right_nrec + 1));
H5MM_memcpy(&(right_node_ptrs[0]), &(middle_node_ptrs[(curr_middle_nrec - right_nrec_move) + 1]), sizeof(H5B2_node_ptr_t) * right_nrec_move);
for(u = 0, moved_nrec = 0; u < right_nrec_move; u++)
moved_nrec += right_node_ptrs[u].all_nrec;
right_moved_nrec = (hssize_t)(moved_nrec + right_nrec_move);
middle_moved_nrec -= (hssize_t)(moved_nrec + right_nrec_move);
}
if(hdr->swmr_write && depth > 1)
if(H5B2__update_child_flush_depends(hdr, 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")
curr_middle_nrec = (uint16_t)(curr_middle_nrec - right_nrec_move);
middle_child_flags |= H5AC__DIRTIED_FLAG;
right_child_flags |= H5AC__DIRTIED_FLAG;
}
if(new_left_nrec < *left_nrec) {
unsigned left_nrec_move = (unsigned)(*left_nrec - new_left_nrec);
HDmemmove(H5B2_NAT_NREC(middle_native, hdr, left_nrec_move), H5B2_NAT_NREC(middle_native, hdr, 0), hdr->cls->nrec_size * curr_middle_nrec);
H5MM_memcpy(H5B2_NAT_NREC(middle_native, hdr, left_nrec_move - 1), H5B2_INT_NREC(internal, hdr, idx - 1), hdr->cls->nrec_size);
if(left_nrec_move > 1)
HDmemmove(H5B2_NAT_NREC(middle_native, hdr, 0), H5B2_NAT_NREC(left_native, hdr, new_left_nrec + 1), hdr->cls->nrec_size * (left_nrec_move - 1));
H5MM_memcpy(H5B2_INT_NREC(internal, hdr, idx - 1), H5B2_NAT_NREC(left_native, hdr, new_left_nrec), hdr->cls->nrec_size);
if(depth > 1) {
hsize_t moved_nrec;
unsigned u;
HDmemmove(&(middle_node_ptrs[left_nrec_move]), &(middle_node_ptrs[0]), sizeof(H5B2_node_ptr_t) * (size_t)(curr_middle_nrec + 1));
H5MM_memcpy(&(middle_node_ptrs[0]), &(left_node_ptrs[new_left_nrec + 1]), sizeof(H5B2_node_ptr_t) * left_nrec_move);
for(u = 0, moved_nrec = 0; u < left_nrec_move; u++)
moved_nrec += middle_node_ptrs[u].all_nrec;
left_moved_nrec -= (hssize_t)(moved_nrec + left_nrec_move);
middle_moved_nrec += (hssize_t)(moved_nrec + left_nrec_move);
}
if(hdr->swmr_write && depth > 1)
if(H5B2__update_child_flush_depends(hdr, 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")
curr_middle_nrec = (uint16_t)(curr_middle_nrec + left_nrec_move);
left_child_flags |= H5AC__DIRTIED_FLAG;
middle_child_flags |= H5AC__DIRTIED_FLAG;
}
if(new_right_nrec < *right_nrec) {
unsigned right_nrec_move = (unsigned)(*right_nrec - new_right_nrec);
H5MM_memcpy(H5B2_NAT_NREC(middle_native, hdr, curr_middle_nrec), H5B2_INT_NREC(internal, hdr, idx), hdr->cls->nrec_size);
HDmemmove(H5B2_NAT_NREC(middle_native, hdr, (curr_middle_nrec + 1)), H5B2_NAT_NREC(right_native, hdr, 0), hdr->cls->nrec_size * (right_nrec_move - 1));
H5MM_memcpy(H5B2_INT_NREC(internal, hdr, idx), H5B2_NAT_NREC(right_native, hdr, right_nrec_move - 1), hdr->cls->nrec_size);
HDmemmove(H5B2_NAT_NREC(right_native, hdr, 0), H5B2_NAT_NREC(right_native, hdr, right_nrec_move), hdr->cls->nrec_size * new_right_nrec);
if(depth > 1) {
hsize_t moved_nrec;
unsigned u;
H5MM_memcpy(&(middle_node_ptrs[curr_middle_nrec + 1]), &(right_node_ptrs[0]), sizeof(H5B2_node_ptr_t) * right_nrec_move);
for(u = 0, moved_nrec = 0; u < right_nrec_move; u++)
moved_nrec += right_node_ptrs[u].all_nrec;
right_moved_nrec -= (hssize_t)(moved_nrec + right_nrec_move);
middle_moved_nrec += (hssize_t)(moved_nrec + right_nrec_move);
HDmemmove(&(right_node_ptrs[0]), &(right_node_ptrs[right_nrec_move]), sizeof(H5B2_node_ptr_t) * (size_t)(new_right_nrec + 1));
}
if(hdr->swmr_write && depth > 1)
if(H5B2__update_child_flush_depends(hdr, 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")
middle_child_flags |= H5AC__DIRTIED_FLAG;
right_child_flags |= H5AC__DIRTIED_FLAG;
}
*left_nrec = new_left_nrec;
*middle_nrec = new_middle_nrec;
*right_nrec = new_right_nrec;
}
internal->node_ptrs[idx - 1].node_nrec = *left_nrec;
internal->node_ptrs[idx].node_nrec = *middle_nrec;
internal->node_ptrs[idx + 1].node_nrec = *right_nrec;
if(depth > 1) {
internal->node_ptrs[idx - 1].all_nrec = (hsize_t)((hssize_t)internal->node_ptrs[idx - 1].all_nrec + left_moved_nrec);
internal->node_ptrs[idx].all_nrec = (hsize_t)((hssize_t)internal->node_ptrs[idx].all_nrec + middle_moved_nrec);
internal->node_ptrs[idx + 1].all_nrec = (hsize_t)((hssize_t)internal->node_ptrs[idx + 1].all_nrec + right_moved_nrec);
}
else {
internal->node_ptrs[idx - 1].all_nrec = internal->node_ptrs[idx - 1].node_nrec;
internal->node_ptrs[idx].all_nrec = internal->node_ptrs[idx].node_nrec;
internal->node_ptrs[idx + 1].all_nrec = internal->node_ptrs[idx + 1].node_nrec;
}
*internal_flags_ptr |= H5AC__DIRTIED_FLAG;
#ifdef H5B2_DEBUG
H5B2__assert_internal((hsize_t)0, hdr, internal);
if(depth > 1) {
H5B2__assert_internal2(internal->node_ptrs[idx - 1].all_nrec, hdr, (H5B2_internal_t *)left_child, (H5B2_internal_t *)middle_child);
H5B2__assert_internal2(internal->node_ptrs[idx].all_nrec, hdr, (H5B2_internal_t *)middle_child, (H5B2_internal_t *)left_child);
H5B2__assert_internal2(internal->node_ptrs[idx].all_nrec, hdr, (H5B2_internal_t *)middle_child, (H5B2_internal_t *)right_child);
H5B2__assert_internal2(internal->node_ptrs[idx + 1].all_nrec, hdr, (H5B2_internal_t *)right_child, (H5B2_internal_t *)middle_child);
}
else {
H5B2__assert_leaf2(hdr, (H5B2_leaf_t *)left_child, (H5B2_leaf_t *)middle_child);
H5B2__assert_leaf2(hdr, (H5B2_leaf_t *)middle_child, (H5B2_leaf_t *)right_child);
H5B2__assert_leaf(hdr, (H5B2_leaf_t *)right_child);
}
#endif
done:
if(left_child && H5AC_unprotect(hdr->f, child_class, left_addr, left_child, left_child_flags) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
if(middle_child && H5AC_unprotect(hdr->f, child_class, middle_addr, middle_child, middle_child_flags) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
if(right_child && H5AC_unprotect(hdr->f, child_class, right_addr, right_child, right_child_flags) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5B2__merge2(H5B2_hdr_t *hdr, 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)
{
const H5AC_class_t *child_class;
haddr_t left_addr, right_addr;
void *left_child = NULL, *right_child = NULL;
uint16_t *left_nrec, *right_nrec;
uint8_t *left_native, *right_native;
H5B2_node_ptr_t *left_node_ptrs = NULL, *right_node_ptrs = NULL;
unsigned left_child_flags = H5AC__NO_FLAGS_SET, right_child_flags = H5AC__NO_FLAGS_SET;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(hdr);
HDassert(curr_node_ptr);
HDassert(internal);
HDassert(internal_flags_ptr);
if(depth > 1) {
H5B2_internal_t *left_internal;
H5B2_internal_t *right_internal;
child_class = H5AC_BT2_INT;
if(NULL == (left_internal = H5B2__protect_internal(hdr, 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")
left_addr = internal->node_ptrs[idx].addr;
if(NULL == (right_internal = H5B2__protect_internal(hdr, 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;
left_child = left_internal;
right_child = right_internal;
left_nrec = &(left_internal->nrec);
right_nrec = &(right_internal->nrec);
left_native = left_internal->int_native;
right_native = right_internal->int_native;
left_node_ptrs = left_internal->node_ptrs;
right_node_ptrs = right_internal->node_ptrs;
}
else {
H5B2_leaf_t *left_leaf;
H5B2_leaf_t *right_leaf;
child_class = H5AC_BT2_LEAF;
if(NULL == (left_leaf = H5B2__protect_leaf(hdr, 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")
left_addr = internal->node_ptrs[idx].addr;
if(NULL == (right_leaf = H5B2__protect_leaf(hdr, 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;
left_child = left_leaf;
right_child = right_leaf;
left_nrec = &(left_leaf->nrec);
right_nrec = &(right_leaf->nrec);
left_native = left_leaf->leaf_native;
right_native = right_leaf->leaf_native;
}
{
H5MM_memcpy(H5B2_NAT_NREC(left_native, hdr, *left_nrec), H5B2_INT_NREC(internal, hdr, idx), hdr->cls->nrec_size);
H5MM_memcpy(H5B2_NAT_NREC(left_native, hdr, *left_nrec + 1), H5B2_NAT_NREC(right_native, hdr, 0), hdr->cls->nrec_size * (*right_nrec));
if(depth > 1)
H5MM_memcpy(&(left_node_ptrs[*left_nrec + 1]), &(right_node_ptrs[0]), sizeof(H5B2_node_ptr_t) * (size_t)(*right_nrec + 1));
if(hdr->swmr_write && depth > 1)
if(H5B2__update_child_flush_depends(hdr, 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")
*left_nrec = (uint16_t)(*left_nrec + *right_nrec + 1);
left_child_flags |= H5AC__DIRTIED_FLAG;
right_child_flags |= H5AC__DELETED_FLAG;
if(!(hdr->swmr_write))
right_child_flags |= H5AC__DIRTIED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
}
internal->node_ptrs[idx].node_nrec = *left_nrec;
internal->node_ptrs[idx].all_nrec += internal->node_ptrs[idx + 1].all_nrec + 1;
if((idx + 1) < internal->nrec) {
HDmemmove(H5B2_INT_NREC(internal, hdr, idx), H5B2_INT_NREC(internal, hdr, idx + 1), hdr->cls->nrec_size * (internal->nrec - (idx + 1)));
HDmemmove(&(internal->node_ptrs[idx + 1]), &(internal->node_ptrs[idx + 2]), sizeof(H5B2_node_ptr_t) * (internal->nrec - (idx + 1)));
}
internal->nrec--;
*internal_flags_ptr |= H5AC__DIRTIED_FLAG;
curr_node_ptr->node_nrec--;
if(parent_cache_info_flags_ptr)
*parent_cache_info_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 *)left_child);
else
H5B2__assert_leaf(hdr, (H5B2_leaf_t *)left_child);
#endif
done:
if(left_child && H5AC_unprotect(hdr->f, child_class, left_addr, left_child, left_child_flags) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
if(right_child && H5AC_unprotect(hdr->f, child_class, right_addr, right_child, right_child_flags) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5B2__merge3(H5B2_hdr_t *hdr, 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)
{
const H5AC_class_t *child_class;
haddr_t left_addr, right_addr;
haddr_t middle_addr;
void *left_child = NULL, *right_child = NULL;
void *middle_child = NULL;
uint16_t *left_nrec, *right_nrec;
uint16_t *middle_nrec;
uint8_t *left_native, *right_native;
uint8_t *middle_native;
H5B2_node_ptr_t *left_node_ptrs = NULL, *right_node_ptrs = NULL;
H5B2_node_ptr_t *middle_node_ptrs = NULL;
hsize_t middle_moved_nrec;
unsigned left_child_flags = H5AC__NO_FLAGS_SET, right_child_flags = H5AC__NO_FLAGS_SET;
unsigned middle_child_flags = H5AC__NO_FLAGS_SET;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(hdr);
HDassert(curr_node_ptr);
HDassert(internal);
HDassert(internal_flags_ptr);
if(depth > 1) {
H5B2_internal_t *left_internal;
H5B2_internal_t *middle_internal;
H5B2_internal_t *right_internal;
child_class = H5AC_BT2_INT;
if(NULL == (left_internal = H5B2__protect_internal(hdr, 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")
left_addr = internal->node_ptrs[idx - 1].addr;
if(NULL == (middle_internal = H5B2__protect_internal(hdr, 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")
middle_addr = internal->node_ptrs[idx].addr;
if(NULL == (right_internal = H5B2__protect_internal(hdr, 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;
left_child = left_internal;
middle_child = middle_internal;
right_child = right_internal;
left_nrec = &(left_internal->nrec);
middle_nrec = &(middle_internal->nrec);
right_nrec = &(right_internal->nrec);
left_native = left_internal->int_native;
middle_native = middle_internal->int_native;
right_native = right_internal->int_native;
left_node_ptrs = left_internal->node_ptrs;
middle_node_ptrs = middle_internal->node_ptrs;
right_node_ptrs = right_internal->node_ptrs;
}
else {
H5B2_leaf_t *left_leaf;
H5B2_leaf_t *middle_leaf;
H5B2_leaf_t *right_leaf;
child_class = H5AC_BT2_LEAF;
if(NULL == (left_leaf = H5B2__protect_leaf(hdr, 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")
left_addr = internal->node_ptrs[idx - 1].addr;
if(NULL == (middle_leaf = H5B2__protect_leaf(hdr, 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")
middle_addr = internal->node_ptrs[idx].addr;
if(NULL == (right_leaf = H5B2__protect_leaf(hdr, 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;
left_child = left_leaf;
middle_child = middle_leaf;
right_child = right_leaf;
left_nrec = &(left_leaf->nrec);
middle_nrec = &(middle_leaf->nrec);
right_nrec = &(right_leaf->nrec);
left_native = left_leaf->leaf_native;
middle_native = middle_leaf->leaf_native;
right_native = right_leaf->leaf_native;
}
{
unsigned total_nrec = (unsigned)(*left_nrec + *middle_nrec + *right_nrec + 2);
unsigned middle_nrec_move = ((total_nrec - 1) / 2) - *left_nrec;
middle_moved_nrec = middle_nrec_move;
H5MM_memcpy(H5B2_NAT_NREC(left_native, hdr, *left_nrec), H5B2_INT_NREC(internal, hdr, idx - 1), hdr->cls->nrec_size);
H5MM_memcpy(H5B2_NAT_NREC(left_native, hdr, *left_nrec + 1), H5B2_NAT_NREC(middle_native, hdr, 0), hdr->cls->nrec_size * (middle_nrec_move - 1));
H5MM_memcpy(H5B2_INT_NREC(internal, hdr, idx - 1), H5B2_NAT_NREC(middle_native, hdr, (middle_nrec_move - 1)), hdr->cls->nrec_size);
HDmemmove(H5B2_NAT_NREC(middle_native, hdr, 0), H5B2_NAT_NREC(middle_native, hdr, middle_nrec_move), hdr->cls->nrec_size * (*middle_nrec - middle_nrec_move));
if(depth > 1) {
unsigned u;
H5MM_memcpy(&(left_node_ptrs[*left_nrec + 1]), &(middle_node_ptrs[0]), sizeof(H5B2_node_ptr_t) * middle_nrec_move);
for(u = 0; u < middle_nrec_move; u++)
middle_moved_nrec += middle_node_ptrs[u].all_nrec;
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));
}
if(hdr->swmr_write && depth > 1)
if(H5B2__update_child_flush_depends(hdr, 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")
*left_nrec = (uint16_t)(*left_nrec + middle_nrec_move);
*middle_nrec = (uint16_t)(*middle_nrec - middle_nrec_move);
left_child_flags |= H5AC__DIRTIED_FLAG;
middle_child_flags |= H5AC__DIRTIED_FLAG;
}
{
H5MM_memcpy(H5B2_NAT_NREC(middle_native, hdr, *middle_nrec), H5B2_INT_NREC(internal, hdr, idx), hdr->cls->nrec_size);
H5MM_memcpy(H5B2_NAT_NREC(middle_native, hdr, *middle_nrec + 1), H5B2_NAT_NREC(right_native, hdr, 0), hdr->cls->nrec_size * (*right_nrec));
if(depth > 1)
H5MM_memcpy(&(middle_node_ptrs[*middle_nrec + 1]), &(right_node_ptrs[0]), sizeof(H5B2_node_ptr_t) * (size_t)(*right_nrec + 1));
if(hdr->swmr_write && depth > 1)
if(H5B2__update_child_flush_depends(hdr, 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")
*middle_nrec = (uint16_t)(*middle_nrec + (*right_nrec + 1));
middle_child_flags |= H5AC__DIRTIED_FLAG;
right_child_flags |= H5AC__DELETED_FLAG;
if(!(hdr->swmr_write))
right_child_flags |= H5AC__DIRTIED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
}
internal->node_ptrs[idx - 1].node_nrec = *left_nrec;
internal->node_ptrs[idx].node_nrec = *middle_nrec;
internal->node_ptrs[idx - 1].all_nrec += middle_moved_nrec;
internal->node_ptrs[idx].all_nrec += (internal->node_ptrs[idx + 1].all_nrec + 1) - middle_moved_nrec;
if((idx + 1) < internal->nrec) {
HDmemmove(H5B2_INT_NREC(internal, hdr, idx), H5B2_INT_NREC(internal, hdr, idx + 1), hdr->cls->nrec_size * (internal->nrec - (idx + 1)));
HDmemmove(&(internal->node_ptrs[idx + 1]), &(internal->node_ptrs[idx + 2]), sizeof(H5B2_node_ptr_t) * (internal->nrec - (idx + 1)));
}
internal->nrec--;
*internal_flags_ptr |= H5AC__DIRTIED_FLAG;
curr_node_ptr->node_nrec--;
if(parent_cache_info_flags_ptr)
*parent_cache_info_flags_ptr |= H5AC__DIRTIED_FLAG;
#ifdef H5B2_DEBUG
H5B2__assert_internal((hsize_t)0, hdr, internal);
if(depth > 1) {
H5B2__assert_internal2(internal->node_ptrs[idx - 1].all_nrec, hdr, (H5B2_internal_t *)left_child, (H5B2_internal_t *)middle_child);
H5B2__assert_internal(internal->node_ptrs[idx].all_nrec, hdr, (H5B2_internal_t *)middle_child);
}
else {
H5B2__assert_leaf2(hdr, (H5B2_leaf_t *)left_child, (H5B2_leaf_t *)middle_child);
H5B2__assert_leaf(hdr, (H5B2_leaf_t *)middle_child);
}
#endif
done:
if(left_child && H5AC_unprotect(hdr->f, child_class, left_addr, left_child, left_child_flags) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
if(middle_child && H5AC_unprotect(hdr->f, child_class, middle_addr, middle_child, middle_child_flags) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
if(right_child && H5AC_unprotect(hdr->f, child_class, right_addr, right_child, right_child_flags) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5B2__insert(H5B2_hdr_t *hdr, void *udata)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(hdr);
HDassert(udata);
if(!H5F_addr_defined(hdr->root.addr)) {
if(H5B2__create_leaf(hdr, hdr, &(hdr->root)) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create root node")
}
else if(hdr->root.node_nrec == hdr->node_info[hdr->depth].split_nrec) {
if(H5B2__split_root(hdr) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to split root node")
}
if(hdr->depth > 0) {
if(H5B2__insert_internal(hdr, 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")
}
else {
if(H5B2__insert_leaf(hdr, &hdr->root, H5B2_POS_ROOT, hdr, udata) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into B-tree leaf node")
}
if(H5B2__hdr_dirty(hdr) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTMARKDIRTY, FAIL, "unable to mark B-tree header dirty")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5B2__iterate_node(H5B2_hdr_t *hdr, uint16_t depth, const H5B2_node_ptr_t *curr_node,
void *parent, H5B2_operator_t op, void *op_data)
{
const H5AC_class_t *curr_node_class = NULL;
void *node = NULL;
uint8_t *node_native;
uint8_t *native = NULL;
H5B2_node_ptr_t *node_ptrs = NULL;
hbool_t node_pinned = FALSE;
unsigned u;
herr_t ret_value = H5_ITER_CONT;
FUNC_ENTER_PACKAGE
HDassert(hdr);
HDassert(curr_node);
HDassert(op);
if(depth > 0) {
H5B2_internal_t *internal;
if(NULL == (internal = H5B2__protect_internal(hdr, parent, (H5B2_node_ptr_t *)curr_node, depth, FALSE, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
curr_node_class = H5AC_BT2_INT;
node = internal;
node_native = internal->int_native;
if(NULL == (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")
H5MM_memcpy(node_ptrs, internal->node_ptrs, (sizeof(H5B2_node_ptr_t) * (size_t)(curr_node->node_nrec + 1)));
}
else {
H5B2_leaf_t *leaf;
if(NULL == (leaf = H5B2__protect_leaf(hdr, parent, (H5B2_node_ptr_t *)curr_node, FALSE, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
curr_node_class = H5AC_BT2_LEAF;
node = leaf;
node_native = leaf->leaf_native;
}
if(NULL == (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")
H5MM_memcpy(native, node_native, (hdr->cls->nrec_size * curr_node->node_nrec));
if(H5AC_unprotect(hdr->f, 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")
if(hdr->swmr_write)
node_pinned = TRUE;
else
node = NULL;
for(u = 0; u < curr_node->node_nrec && !ret_value; u++) {
if(depth > 0)
if((ret_value = H5B2__iterate_node(hdr, (uint16_t)(depth - 1), &(node_ptrs[u]), node, op, op_data)) < 0)
HERROR(H5E_BTREE, H5E_CANTLIST, "node iteration failed");
if(!ret_value)
if((ret_value = (op)(H5B2_NAT_NREC(native, hdr, u), op_data)) < 0)
HERROR(H5E_BTREE, H5E_CANTLIST, "iterator function failed");
}
if(!ret_value && depth > 0)
if((ret_value = H5B2__iterate_node(hdr, (uint16_t)(depth - 1), &(node_ptrs[u]), node, op, op_data)) < 0)
HERROR(H5E_BTREE, H5E_CANTLIST, "node iteration failed");
done:
if(node_pinned && H5AC_unpin_entry(node) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTUNPIN, FAIL, "can't unpin node")
if(node_ptrs)
node_ptrs = (H5B2_node_ptr_t *)H5FL_FAC_FREE(hdr->node_info[depth].node_ptr_fac, node_ptrs);
if(native)
native = (uint8_t *)H5FL_FAC_FREE(hdr->node_info[depth].nat_rec_fac, native);
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5B2__delete_node(H5B2_hdr_t *hdr, uint16_t depth, const H5B2_node_ptr_t *curr_node,
void *parent, H5B2_remove_t op, void *op_data)
{
const H5AC_class_t *curr_node_class = NULL;
void *node = NULL;
uint8_t *native;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(hdr);
HDassert(curr_node);
if(depth > 0) {
H5B2_internal_t *internal;
unsigned u;
if(NULL == (internal = H5B2__protect_internal(hdr, parent, (H5B2_node_ptr_t *)curr_node, depth, FALSE, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
curr_node_class = H5AC_BT2_INT;
node = internal;
native = internal->int_native;
for(u = 0; u < internal->nrec + (unsigned)1; u++)
if(H5B2__delete_node(hdr, (uint16_t)(depth - 1), &(internal->node_ptrs[u]), internal, op, op_data) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTLIST, FAIL, "node descent failed")
}
else {
H5B2_leaf_t *leaf;
if(NULL == (leaf = H5B2__protect_leaf(hdr, parent, (H5B2_node_ptr_t *)curr_node, FALSE, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
curr_node_class = H5AC_BT2_LEAF;
node = leaf;
native = leaf->leaf_native;
}
if(op) {
unsigned u;
for(u = 0; u < curr_node->node_nrec; u++) {
if((op)(H5B2_NAT_NREC(native, hdr, u), op_data) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTLIST, FAIL, "iterator function failed")
}
}
done:
if(node && H5AC_unprotect(hdr->f, 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)
}
herr_t
H5B2__node_size(H5B2_hdr_t *hdr, uint16_t depth, const H5B2_node_ptr_t *curr_node,
void *parent, hsize_t *btree_size)
{
H5B2_internal_t *internal = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(hdr);
HDassert(curr_node);
HDassert(btree_size);
HDassert(depth > 0);
if(NULL == (internal = H5B2__protect_internal(hdr, parent, (H5B2_node_ptr_t *)curr_node, depth, FALSE, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
if(depth > 1) {
unsigned u;
for(u = 0; u < internal->nrec + (unsigned)1; u++)
if(H5B2__node_size(hdr, (uint16_t)(depth - 1), &(internal->node_ptrs[u]), internal, btree_size) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTLIST, FAIL, "node iteration failed")
}
else
*btree_size += (hsize_t)(internal->nrec + 1) * hdr->node_size;
*btree_size += hdr->node_size;
done:
if(internal && H5AC_unprotect(hdr->f, H5AC_BT2_INT, curr_node->addr, internal, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5B2__create_flush_depend(H5AC_info_t *parent_entry, H5AC_info_t *child_entry)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT
HDassert(parent_entry);
HDassert(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)
}
herr_t
H5B2__update_flush_depend(H5B2_hdr_t *hdr, unsigned depth,
const H5B2_node_ptr_t *node_ptr, void *old_parent, void *new_parent)
{
const H5AC_class_t *child_class;
void *child = NULL;
unsigned node_status = 0;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(hdr);
HDassert(depth > 0);
HDassert(node_ptr);
HDassert(old_parent);
HDassert(new_parent);
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")
if(node_status & H5AC_ES__IN_CACHE) {
void **parent_ptr;
hbool_t update_deps = FALSE;
if(depth > 1) {
H5B2_internal_t *child_int;
if(NULL == (child_int = H5B2__protect_internal(hdr, new_parent, (H5B2_node_ptr_t *)node_ptr, (uint16_t)(depth - 1), FALSE, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
child_class = H5AC_BT2_INT;
child = child_int;
if(child_int->parent == old_parent) {
parent_ptr = &child_int->parent;
update_deps = TRUE;
}
else
HDassert(child_int->parent == new_parent);
}
else {
H5B2_leaf_t *child_leaf;
if(NULL == (child_leaf = H5B2__protect_leaf(hdr, new_parent, (H5B2_node_ptr_t *)node_ptr, FALSE, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
child_class = H5AC_BT2_LEAF;
child = child_leaf;
if(child_leaf->parent == old_parent) {
parent_ptr = &child_leaf->parent;
update_deps = TRUE;
}
else
HDassert(child_leaf->parent == new_parent);
}
if(update_deps) {
HDassert(parent_ptr);
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")
}
}
done:
if(child)
if(H5AC_unprotect(hdr->f, 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)
}
static herr_t
H5B2__update_child_flush_depends(H5B2_hdr_t *hdr, unsigned depth,
const H5B2_node_ptr_t *node_ptrs, unsigned start_idx, unsigned end_idx,
void *old_parent, void *new_parent)
{
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(hdr);
HDassert(depth > 1);
HDassert(node_ptrs);
HDassert(start_idx <= end_idx);
HDassert(old_parent);
HDassert(new_parent);
for(u = start_idx; u < end_idx; u++)
if(H5B2__update_flush_depend(hdr, 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")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5B2__destroy_flush_depend(H5AC_info_t *parent_entry, H5AC_info_t *child_entry)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT
HDassert(parent_entry);
HDassert(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)
}