use std::sync::atomic::{AtomicPtr, Ordering as AtomicOrdering};
use crate::TreeAllocator;
use crate::internode::InternodeNode;
use crate::leaf15::LeafNode15;
use crate::policy::LeafPolicy;
pub struct RootCreation;
impl RootCreation {
pub fn create_root_from_leaves<P, A>(
root_ptr: &AtomicPtr<u8>,
allocator: &A,
left_leaf_ptr: *mut LeafNode15<P>,
right_leaf_ptr: *mut LeafNode15<P>,
split_ikey: u64,
) -> *mut InternodeNode
where
P: LeafPolicy,
A: TreeAllocator<P>,
{
let new_root_ptr: *mut u8 = allocator.alloc_internode_direct_root(0);
let new_root: &InternodeNode = unsafe { &*new_root_ptr.cast::<InternodeNode>() };
new_root.set_child(0, left_leaf_ptr.cast());
new_root.set_ikey(0, split_ikey);
new_root.set_child(1, right_leaf_ptr.cast());
new_root.set_nkeys(1);
root_ptr.store(new_root_ptr, AtomicOrdering::Release);
unsafe {
(*left_leaf_ptr).set_parent(new_root_ptr);
(*right_leaf_ptr).set_parent(new_root_ptr);
(*left_leaf_ptr).version().mark_nonroot();
}
new_root_ptr.cast()
}
pub fn create_root_from_internodes<P, A>(
root_ptr: &AtomicPtr<u8>,
allocator: &A,
left_inode_ptr: *mut InternodeNode,
right_inode_ptr: *mut InternodeNode,
split_ikey: u64,
) -> *mut InternodeNode
where
P: LeafPolicy,
A: TreeAllocator<P>,
{
let left: &InternodeNode = unsafe { &*left_inode_ptr };
let new_root_ptr: *mut u8 = allocator.alloc_internode_direct_root(left.height() + 1);
let new_root: &InternodeNode = unsafe { &*new_root_ptr.cast::<InternodeNode>() };
new_root.set_child(0, left_inode_ptr.cast());
new_root.set_ikey(0, split_ikey);
new_root.set_child(1, right_inode_ptr.cast());
new_root.set_nkeys(1);
root_ptr.store(new_root_ptr, AtomicOrdering::Release);
unsafe {
(*left_inode_ptr).set_parent(new_root_ptr);
(*right_inode_ptr).set_parent(new_root_ptr);
(*left_inode_ptr).version().mark_nonroot();
}
new_root_ptr.cast()
}
pub fn promote_layer_root_leaves<P, A>(
allocator: &A,
left_leaf_ptr: *mut LeafNode15<P>,
right_leaf_ptr: *mut LeafNode15<P>,
split_ikey: u64,
) -> *mut InternodeNode
where
P: LeafPolicy,
A: TreeAllocator<P>,
{
let new_inode_ptr: *mut u8 = allocator.alloc_internode_direct_root(0);
let new_inode: &InternodeNode = unsafe { &*new_inode_ptr.cast::<InternodeNode>() };
new_inode.set_child(0, left_leaf_ptr.cast());
new_inode.set_ikey(0, split_ikey);
new_inode.set_child(1, right_leaf_ptr.cast());
new_inode.set_nkeys(1);
unsafe {
(*left_leaf_ptr).set_parent(new_inode_ptr);
(*right_leaf_ptr).set_parent(new_inode_ptr);
(*left_leaf_ptr).version().mark_nonroot();
(*right_leaf_ptr).version().mark_nonroot();
}
new_inode_ptr.cast()
}
pub fn promote_layer_root_internodes<P, A>(
allocator: &A,
left_inode_ptr: *mut InternodeNode,
right_inode_ptr: *mut InternodeNode,
split_ikey: u64,
) -> *mut InternodeNode
where
P: LeafPolicy,
A: TreeAllocator<P>,
{
let left: &InternodeNode = unsafe { &*left_inode_ptr };
let new_inode_ptr: *mut u8 = allocator.alloc_internode_direct_root(left.height() + 1);
let new_inode: &InternodeNode = unsafe { &*new_inode_ptr.cast::<InternodeNode>() };
new_inode.set_child(0, left_inode_ptr.cast());
new_inode.set_ikey(0, split_ikey);
new_inode.set_child(1, right_inode_ptr.cast());
new_inode.set_nkeys(1);
unsafe {
(*left_inode_ptr).set_parent(new_inode_ptr);
(*right_inode_ptr).set_parent(new_inode_ptr);
(*left_inode_ptr).version().mark_nonroot();
}
new_inode_ptr.cast()
}
}