use super::states::*;
use crate::utils::*;
use crossbeam::utils::CachePadded;
use std::borrow::Borrow;
use std::fmt::{self, Debug, Error};
use std::marker::PhantomData;
use std::mem::MaybeUninit;
use std::ptr;
use std::slice;
#[cfg(test)]
use std::collections::BTreeSet;
#[cfg(test)]
use std::sync::atomic::{AtomicUsize, Ordering};
#[cfg(test)]
use std::sync::Mutex;
pub(crate) const TXID_MASK: u64 = 0x0fff_ffff_ffff_fff0;
const FLAG_MASK: u64 = 0xf000_0000_0000_0000;
const COUNT_MASK: u64 = 0x0000_0000_0000_000f;
pub(crate) const TXID_SHF: usize = 4;
const FLAG_BRANCH: u64 = 0x1000_0000_0000_0000;
const FLAG_LEAF: u64 = 0x2000_0000_0000_0000;
const FLAG_DROPPED: u64 = 0xaaaa_bbbb_cccc_dddd;
#[cfg(feature = "skinny")]
pub(crate) const L_CAPACITY: usize = 3;
#[cfg(feature = "skinny")]
const L_CAPACITY_N1: usize = L_CAPACITY - 1;
#[cfg(feature = "skinny")]
pub(crate) const BV_CAPACITY: usize = L_CAPACITY + 1;
#[cfg(not(feature = "skinny"))]
pub(crate) const L_CAPACITY: usize = 7;
#[cfg(not(feature = "skinny"))]
const L_CAPACITY_N1: usize = L_CAPACITY - 1;
#[cfg(not(feature = "skinny"))]
pub(crate) const BV_CAPACITY: usize = L_CAPACITY + 1;
#[cfg(test)]
thread_local!(static NODE_COUNTER: AtomicUsize = AtomicUsize::new(1));
#[cfg(all(test, not(miri)))]
thread_local!(static ALLOC_LIST: Mutex<BTreeSet<usize>> = Mutex::new(BTreeSet::new()));
#[cfg(test)]
fn alloc_nid() -> usize {
let nid: usize = NODE_COUNTER.with(|nc| nc.fetch_add(1, Ordering::AcqRel));
#[cfg(all(test, not(miri)))]
{
ALLOC_LIST.with(|llist| llist.lock().unwrap().insert(nid));
}
nid
}
#[cfg(all(test, not(miri)))]
fn release_nid(nid: usize) {
let r = ALLOC_LIST.with(|llist| llist.lock().unwrap().remove(&nid));
assert!(r == true);
}
#[cfg(test)]
pub(crate) fn assert_released() {
#[cfg(not(miri))]
{
let is_empt = ALLOC_LIST.with(|llist| {
let x = llist.lock().unwrap();
x.is_empty()
});
assert!(is_empt);
}
}
#[repr(C)]
pub(crate) struct Meta(u64);
#[repr(C)]
pub(crate) struct Branch<K, V>
where
K: Ord + Clone + Debug,
V: Clone,
{
pub(crate) meta: Meta,
key: [MaybeUninit<K>; L_CAPACITY],
nodes: [*mut Node<K, V>; BV_CAPACITY],
#[cfg(all(test, not(miri)))]
pub(crate) nid: usize,
}
#[repr(C)]
pub(crate) struct Leaf<K, V>
where
K: Ord + Clone + Debug,
V: Clone,
{
pub(crate) meta: Meta,
key: [MaybeUninit<K>; L_CAPACITY],
values: [MaybeUninit<V>; L_CAPACITY],
#[cfg(all(test, not(miri)))]
pub(crate) nid: usize,
}
#[repr(C)]
pub(crate) struct Node<K, V> {
pub(crate) meta: Meta,
k: PhantomData<K>,
v: PhantomData<V>,
}
impl<K: Clone + Ord + Debug, V: Clone> Node<K, V> {
pub(crate) fn new_leaf(txid: u64) -> *mut Leaf<K, V> {
debug_assert!(txid < (TXID_MASK >> TXID_SHF));
let x: Box<CachePadded<Leaf<K, V>>> = Box::new(CachePadded::new(Leaf {
meta: Meta((txid << TXID_SHF) | FLAG_LEAF),
key: unsafe { MaybeUninit::uninit().assume_init() },
values: unsafe { MaybeUninit::uninit().assume_init() },
#[cfg(all(test, not(miri)))]
nid: alloc_nid(),
}));
Box::into_raw(x) as *mut Leaf<K, V>
}
fn new_leaf_ins(flags: u64, k: K, v: V) -> *mut Leaf<K, V> {
debug_assert!((flags & FLAG_MASK) == FLAG_LEAF);
let txid = flags & (TXID_MASK | FLAG_MASK | 1);
let x: Box<CachePadded<Leaf<K, V>>> = Box::new(CachePadded::new(Leaf {
meta: Meta(txid),
#[cfg(feature = "skinny")]
key: [
MaybeUninit::new(k),
MaybeUninit::uninit(),
MaybeUninit::uninit(),
],
#[cfg(not(feature = "skinny"))]
key: [
MaybeUninit::new(k),
MaybeUninit::uninit(),
MaybeUninit::uninit(),
MaybeUninit::uninit(),
MaybeUninit::uninit(),
MaybeUninit::uninit(),
MaybeUninit::uninit(),
],
#[cfg(feature = "skinny")]
values: [
MaybeUninit::new(v),
MaybeUninit::uninit(),
MaybeUninit::uninit(),
],
#[cfg(not(feature = "skinny"))]
values: [
MaybeUninit::new(v),
MaybeUninit::uninit(),
MaybeUninit::uninit(),
MaybeUninit::uninit(),
MaybeUninit::uninit(),
MaybeUninit::uninit(),
MaybeUninit::uninit(),
],
#[cfg(all(test, not(miri)))]
nid: alloc_nid(),
}));
let nnode = Box::into_raw(x) as *mut Leaf<K, V>;
nnode
}
pub(crate) fn new_branch(
txid: u64,
l: *mut Node<K, V>,
r: *mut Node<K, V>,
) -> *mut Branch<K, V> {
debug_assert!(!l.is_null());
debug_assert!(!r.is_null());
debug_assert!(unsafe { (*l).verify() });
debug_assert!(unsafe { (*r).verify() });
debug_assert!(txid < (TXID_MASK >> TXID_SHF));
let x: Box<CachePadded<Branch<K, V>>> = Box::new(CachePadded::new(Branch {
meta: Meta((txid << TXID_SHF) | FLAG_BRANCH | 1),
#[cfg(feature = "skinny")]
key: [
MaybeUninit::new(unsafe { (*r).min().clone() }),
MaybeUninit::uninit(),
MaybeUninit::uninit(),
],
#[cfg(not(feature = "skinny"))]
key: [
MaybeUninit::new(unsafe { (*r).min().clone() }),
MaybeUninit::uninit(),
MaybeUninit::uninit(),
MaybeUninit::uninit(),
MaybeUninit::uninit(),
MaybeUninit::uninit(),
MaybeUninit::uninit(),
],
#[cfg(feature = "skinny")]
nodes: [l, r, ptr::null_mut(), ptr::null_mut()],
#[cfg(not(feature = "skinny"))]
nodes: [
l,
r,
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
],
#[cfg(all(test, not(miri)))]
nid: alloc_nid(),
}));
debug_assert!(x.verify());
Box::into_raw(x) as *mut Branch<K, V>
}
#[inline(always)]
pub(crate) fn make_ro(&self) {
match self.meta.0 & FLAG_MASK {
FLAG_LEAF => {
let lref = unsafe { &*(self as *const _ as *const Leaf<K, V>) };
lref.make_ro()
}
FLAG_BRANCH => {
let bref = unsafe { &*(self as *const _ as *const Branch<K, V>) };
bref.make_ro()
}
_ => unreachable!(),
}
}
#[inline(always)]
pub(crate) fn get_txid(&self) -> u64 {
self.meta.get_txid()
}
#[inline(always)]
pub(crate) fn is_leaf(&self) -> bool {
self.meta.is_leaf()
}
#[inline(always)]
pub(crate) fn is_branch(&self) -> bool {
self.meta.is_branch()
}
pub(crate) fn tree_density(&self) -> (usize, usize) {
match self.meta.0 & FLAG_MASK {
FLAG_LEAF => {
let lref = unsafe { &*(self as *const _ as *const Leaf<K, V>) };
(lref.count(), L_CAPACITY)
}
FLAG_BRANCH => {
let bref = unsafe { &*(self as *const _ as *const Branch<K, V>) };
let mut lcount = 0;
let mut mcount = 0;
for idx in 0..(bref.count() + 1) {
let n = bref.nodes[idx] as *mut Node<K, V>;
let (l, m) = unsafe { (*n).tree_density() };
lcount += l;
mcount += m;
}
(lcount, mcount)
}
_ => unreachable!(),
}
}
pub(crate) fn leaf_count(&self) -> usize {
match self.meta.0 & FLAG_MASK {
FLAG_LEAF => 1,
FLAG_BRANCH => {
let bref = unsafe { &*(self as *const _ as *const Branch<K, V>) };
let mut lcount = 0;
for idx in 0..(bref.count() + 1) {
let n = bref.nodes[idx] as *mut Node<K, V>;
lcount += unsafe { (*n).leaf_count() };
}
lcount
}
_ => unreachable!(),
}
}
#[inline(always)]
pub(crate) fn get_ref<Q: ?Sized>(&self, k: &Q) -> Option<&V>
where
K: Borrow<Q>,
Q: Ord,
{
match self.meta.0 & FLAG_MASK {
FLAG_LEAF => {
let lref = unsafe { &*(self as *const _ as *const Leaf<K, V>) };
lref.get_ref(k)
}
FLAG_BRANCH => {
let bref = unsafe { &*(self as *const _ as *const Branch<K, V>) };
bref.get_ref(k)
}
_ => {
unreachable!()
}
}
}
#[inline(always)]
pub(crate) fn min(&self) -> &K {
match self.meta.0 & FLAG_MASK {
FLAG_LEAF => {
let lref = unsafe { &*(self as *const _ as *const Leaf<K, V>) };
lref.min()
}
FLAG_BRANCH => {
let bref = unsafe { &*(self as *const _ as *const Branch<K, V>) };
bref.min()
}
_ => unreachable!(),
}
}
#[inline(always)]
pub(crate) fn max(&self) -> &K {
match self.meta.0 & FLAG_MASK {
FLAG_LEAF => {
let lref = unsafe { &*(self as *const _ as *const Leaf<K, V>) };
lref.max()
}
FLAG_BRANCH => {
let bref = unsafe { &*(self as *const _ as *const Branch<K, V>) };
bref.max()
}
_ => unreachable!(),
}
}
#[inline(always)]
pub(crate) fn verify(&self) -> bool {
match self.meta.0 & FLAG_MASK {
FLAG_LEAF => {
let lref = unsafe { &*(self as *const _ as *const Leaf<K, V>) };
lref.verify()
}
FLAG_BRANCH => {
let bref = unsafe { &*(self as *const _ as *const Branch<K, V>) };
bref.verify()
}
_ => unreachable!(),
}
}
#[cfg(test)]
fn no_cycles_inner(&self, track: &mut BTreeSet<*const Self>) -> bool {
match self.meta.0 & FLAG_MASK {
FLAG_LEAF => {
track.insert(self as *const Self)
}
FLAG_BRANCH => {
if track.insert(self as *const Self) {
let bref = unsafe { &*(self as *const _ as *const Branch<K, V>) };
for i in 0..(bref.count() + 1) {
let n = bref.nodes[i];
let r = unsafe { (*n).no_cycles_inner(track) };
if r == false {
return false;
}
}
true
} else {
false
}
}
_ => {
unreachable!()
}
}
}
#[cfg(test)]
pub(crate) fn no_cycles(&self) -> bool {
let mut track = BTreeSet::new();
self.no_cycles_inner(&mut track)
}
pub(crate) fn sblock_collect(&mut self, alloc: &mut Vec<*mut Node<K, V>>) {
if (self.meta.0 & FLAG_MASK) == FLAG_BRANCH {
let bref = unsafe { &*(self as *const _ as *const Branch<K, V>) };
for idx in 0..(bref.count() + 1) {
alloc.push(bref.nodes[idx]);
let n = bref.nodes[idx] as *mut Node<K, V>;
unsafe { (*n).sblock_collect(alloc) };
}
}
}
pub(crate) fn free(node: *mut Node<K, V>) {
let self_meta = self_meta!(node);
match self_meta.0 & FLAG_MASK {
FLAG_LEAF => Leaf::free(node as *mut Leaf<K, V>),
FLAG_BRANCH => Branch::free(node as *mut Branch<K, V>),
_ => unreachable!(),
}
}
}
impl Meta {
#[inline(always)]
fn set_count(&mut self, c: usize) {
debug_assert!(c < 16);
self.0 &= FLAG_MASK | TXID_MASK;
self.0 |= c as u8 as u64;
}
#[inline(always)]
pub(crate) fn count(&self) -> usize {
(self.0 & COUNT_MASK) as usize
}
#[inline(always)]
fn add_count(&mut self, x: usize) {
self.set_count(self.count() + x);
}
#[inline(always)]
fn inc_count(&mut self) {
debug_assert!(self.count() < 15);
self.0 += 1;
}
#[inline(always)]
fn dec_count(&mut self) {
debug_assert!(self.count() > 0);
self.0 -= 1;
}
#[inline(always)]
pub(crate) fn get_txid(&self) -> u64 {
(self.0 & TXID_MASK) >> TXID_SHF
}
#[inline(always)]
pub(crate) fn is_leaf(&self) -> bool {
(self.0 & FLAG_MASK) == FLAG_LEAF
}
#[inline(always)]
pub(crate) fn is_branch(&self) -> bool {
(self.0 & FLAG_MASK) == FLAG_BRANCH
}
}
impl<K: Ord + Clone + Debug, V: Clone> Leaf<K, V> {
#[inline(always)]
fn set_count(&mut self, c: usize) {
debug_assert_leaf!(self);
self.meta.set_count(c)
}
#[inline(always)]
pub(crate) fn count(&self) -> usize {
debug_assert_leaf!(self);
self.meta.count()
}
#[inline(always)]
fn inc_count(&mut self) {
debug_assert_leaf!(self);
self.meta.inc_count()
}
#[inline(always)]
fn dec_count(&mut self) {
debug_assert_leaf!(self);
self.meta.dec_count()
}
#[inline(always)]
pub(crate) fn get_txid(&self) -> u64 {
debug_assert_leaf!(self);
self.meta.get_txid()
}
pub(crate) fn get_ref<Q: ?Sized>(&self, k: &Q) -> Option<&V>
where
K: Borrow<Q>,
Q: Ord,
{
debug_assert_leaf!(self);
key_search!(self, k)
.ok()
.map(|idx| unsafe { &*self.values[idx].as_ptr() })
}
pub(crate) fn get_mut_ref<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
where
K: Borrow<Q>,
Q: Ord,
{
debug_assert_leaf!(self);
key_search!(self, k)
.ok()
.map(|idx| unsafe { &mut *self.values[idx].as_mut_ptr() })
}
#[inline(always)]
pub(crate) fn get_kv_idx_checked(&self, idx: usize) -> Option<(&K, &V)> {
debug_assert_leaf!(self);
if idx < self.count() {
Some((unsafe { &*self.key[idx].as_ptr() }, unsafe {
&*self.values[idx].as_ptr()
}))
} else {
None
}
}
pub(crate) fn min(&self) -> &K {
debug_assert!(self.count() > 0);
unsafe { &*self.key[0].as_ptr() }
}
pub(crate) fn max(&self) -> &K {
debug_assert!(self.count() > 0);
unsafe { &*self.key[self.count() - 1].as_ptr() }
}
pub(crate) fn req_clone(&self, txid: u64) -> Option<*mut Node<K, V>> {
debug_assert_leaf!(self);
debug_assert!(txid < (TXID_MASK >> TXID_SHF));
if self.get_txid() == txid {
None
} else {
let new_txid = (self.meta.0 & (FLAG_MASK | COUNT_MASK)) | (txid << TXID_SHF);
let mut x: Box<CachePadded<Leaf<K, V>>> = Box::new(CachePadded::new(Leaf {
meta: Meta(new_txid),
key: unsafe { MaybeUninit::uninit().assume_init() },
values: unsafe { MaybeUninit::uninit().assume_init() },
#[cfg(all(test, not(miri)))]
nid: alloc_nid(),
}));
for idx in 0..self.count() {
unsafe {
let lkey = (*self.key[idx].as_ptr()).clone();
x.key[idx].as_mut_ptr().write(lkey);
let lvalue = (*self.values[idx].as_ptr()).clone();
x.values[idx].as_mut_ptr().write(lvalue);
}
}
Some(Box::into_raw(x) as *mut Node<K, V>)
}
}
pub(crate) fn insert_or_update(&mut self, k: K, v: V) -> LeafInsertState<K, V> {
debug_assert_leaf!(self);
let r = key_search!(self, &k);
match r {
Ok(idx) => {
let prev = unsafe { self.values[idx].as_mut_ptr().replace(v) };
LeafInsertState::Ok(Some(prev))
}
Err(idx) => {
if self.count() >= L_CAPACITY {
if idx >= self.count() {
let rnode = Node::new_leaf_ins(self.meta.0, k, v);
LeafInsertState::Split(rnode)
} else if idx == 0 {
let lnode = Node::new_leaf_ins(self.meta.0, k, v);
LeafInsertState::RevSplit(lnode)
} else {
let pk =
unsafe { slice_remove(&mut self.key, L_CAPACITY - 1).assume_init() };
let pv =
unsafe { slice_remove(&mut self.values, L_CAPACITY - 1).assume_init() };
unsafe {
slice_insert(&mut self.key, MaybeUninit::new(k), idx);
slice_insert(&mut self.values, MaybeUninit::new(v), idx);
}
let rnode = Node::new_leaf_ins(self.meta.0, pk, pv);
LeafInsertState::Split(rnode)
}
} else {
unsafe {
slice_insert(&mut self.key, MaybeUninit::new(k), idx);
slice_insert(&mut self.values, MaybeUninit::new(v), idx);
}
self.inc_count();
LeafInsertState::Ok(None)
}
}
}
}
pub(crate) fn remove<Q: ?Sized>(&mut self, k: &Q) -> LeafRemoveState<V>
where
K: Borrow<Q>,
Q: Ord,
{
debug_assert_leaf!(self);
if self.count() == 0 {
return LeafRemoveState::Shrink(None);
}
match key_search!(self, k).ok() {
None => LeafRemoveState::Ok(None),
Some(idx) => {
let _pk = unsafe { slice_remove(&mut self.key, idx).assume_init() };
let pv = unsafe { slice_remove(&mut self.values, idx).assume_init() };
self.dec_count();
if self.count() == 0 {
LeafRemoveState::Shrink(Some(pv))
} else {
LeafRemoveState::Ok(Some(pv))
}
}
}
}
pub(crate) fn take_from_l_to_r(&mut self, right: &mut Self) {
debug_assert!(right.count() == 0);
let count = self.count() / 2;
let start_idx = self.count() - count;
unsafe {
slice_move(&mut right.key, 0, &mut self.key, start_idx, count);
slice_move(&mut right.values, 0, &mut self.values, start_idx, count);
}
self.meta.set_count(start_idx);
right.meta.set_count(count);
}
pub(crate) fn take_from_r_to_l(&mut self, right: &mut Self) {
debug_assert!(self.count() == 0);
let count = right.count() / 2;
let start_idx = right.count() - count;
unsafe {
slice_move(&mut self.key, 0, &mut right.key, 0, count);
slice_move(&mut self.values, 0, &mut right.values, 0, count);
}
unsafe {
ptr::copy(
right.key.as_ptr().add(count),
right.key.as_mut_ptr(),
start_idx,
);
ptr::copy(
right.values.as_ptr().add(count),
right.values.as_mut_ptr(),
start_idx,
);
}
self.meta.set_count(count);
right.meta.set_count(start_idx);
}
#[inline(always)]
pub(crate) fn make_ro(&self) {
debug_assert_leaf!(self);
}
#[inline(always)]
pub(crate) fn merge(&mut self, right: &mut Self) {
debug_assert_leaf!(self);
debug_assert_leaf!(right);
let sc = self.count();
let rc = right.count();
unsafe {
slice_merge(&mut self.key, sc, &mut right.key, rc);
slice_merge(&mut self.values, sc, &mut right.values, rc);
}
self.meta.add_count(right.count());
right.meta.set_count(0);
}
pub(crate) fn verify(&self) -> bool {
debug_assert_leaf!(self);
if self.meta.count() == 0 {
return true;
}
let mut lk: &K = unsafe { &*self.key[0].as_ptr() };
for work_idx in 1..self.meta.count() {
let rk: &K = unsafe { &*self.key[work_idx].as_ptr() };
if lk >= rk {
if cfg!(test) {
return false;
} else {
debug_assert!(false);
}
}
lk = rk;
}
true
}
fn free(node: *mut Self) {
unsafe {
let _x: Box<Leaf<K, V>> = Box::from_raw(node as *mut Leaf<K, V>);
}
}
}
impl<K: Ord + Clone + Debug, V: Clone> Debug for Leaf<K, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), Error> {
debug_assert_leaf!(self);
write!(f, "Leaf -> {}", self.count())?;
#[cfg(all(test, not(miri)))]
write!(f, " nid: {}", self.nid)?;
write!(f, " \\-> [ ")?;
for idx in 0..self.count() {
write!(f, "{:?}, ", unsafe { &*self.key[idx].as_ptr() })?;
}
write!(f, " ]")
}
}
impl<K: Ord + Clone + Debug, V: Clone> Drop for Leaf<K, V> {
fn drop(&mut self) {
debug_assert_leaf!(self);
#[cfg(all(test, not(miri)))]
release_nid(self.nid);
unsafe {
for idx in 0..self.count() {
ptr::drop_in_place(self.key[idx].as_mut_ptr());
ptr::drop_in_place(self.values[idx].as_mut_ptr());
}
}
self.meta.0 = FLAG_DROPPED;
debug_assert!(self.meta.0 & FLAG_MASK != FLAG_LEAF);
}
}
impl<K: Ord + Clone + Debug, V: Clone> Branch<K, V> {
#[inline(always)]
fn set_count(&mut self, c: usize) {
debug_assert_branch!(self);
self.meta.set_count(c)
}
#[inline(always)]
pub(crate) fn count(&self) -> usize {
debug_assert_branch!(self);
self.meta.count()
}
#[inline(always)]
fn inc_count(&mut self) {
debug_assert_branch!(self);
self.meta.inc_count()
}
#[inline(always)]
fn dec_count(&mut self) {
debug_assert_branch!(self);
self.meta.dec_count()
}
#[inline(always)]
pub(crate) fn get_txid(&self) -> u64 {
debug_assert_branch!(self);
self.meta.get_txid()
}
pub(crate) fn min(&self) -> &K {
debug_assert_branch!(self);
unsafe { (*self.nodes[0]).min() }
}
pub(crate) fn max(&self) -> &K {
debug_assert_branch!(self);
unsafe { (*self.nodes[self.count()]).max() }
}
pub(crate) fn req_clone(&self, txid: u64) -> Option<*mut Node<K, V>> {
debug_assert_branch!(self);
if self.get_txid() == txid {
None
} else {
let new_txid = (self.meta.0 & (FLAG_MASK | COUNT_MASK)) | (txid << TXID_SHF);
let mut x: Box<CachePadded<Branch<K, V>>> = Box::new(CachePadded::new(Branch {
meta: Meta(new_txid),
key: unsafe { MaybeUninit::uninit().assume_init() },
nodes: self.nodes.clone(),
#[cfg(all(test, not(miri)))]
nid: alloc_nid(),
}));
for idx in 0..self.count() {
unsafe {
let lkey = (*self.key[idx].as_ptr()).clone();
x.key[idx].as_mut_ptr().write(lkey);
}
}
Some(Box::into_raw(x) as *mut Node<K, V>)
}
}
#[inline(always)]
pub(crate) fn locate_node<Q: ?Sized>(&self, k: &Q) -> usize
where
K: Borrow<Q>,
Q: Ord,
{
debug_assert_branch!(self);
match key_search!(self, k) {
Err(idx) => idx,
Ok(idx) => idx + 1,
}
}
#[inline(always)]
pub(crate) fn get_idx_unchecked(&self, idx: usize) -> *mut Node<K, V> {
debug_assert_branch!(self);
debug_assert!(idx <= self.count());
debug_assert!(!self.nodes[idx].is_null());
self.nodes[idx]
}
#[inline(always)]
pub(crate) fn get_idx_checked(&self, idx: usize) -> Option<*mut Node<K, V>> {
debug_assert_branch!(self);
if idx <= self.count() {
debug_assert!(!self.nodes[idx].is_null());
Some(self.nodes[idx])
} else {
None
}
}
pub(crate) fn get_ref<Q: ?Sized>(&self, k: &Q) -> Option<&V>
where
K: Borrow<Q>,
Q: Ord,
{
debug_assert_branch!(self);
let idx = self.locate_node(k);
unsafe { (*self.nodes[idx]).get_ref(k) }
}
pub(crate) fn add_node(&mut self, node: *mut Node<K, V>) -> BranchInsertState<K, V> {
debug_assert_branch!(self);
if self.count() == L_CAPACITY {
let kr = unsafe { (*node).min() };
let r = key_search!(self, kr);
let ins_idx = r.unwrap_err();
let max = unsafe { *(self.nodes.get_unchecked(BV_CAPACITY - 1)) };
let res = match ins_idx {
L_CAPACITY => {
let _kdrop =
unsafe { ptr::read(self.key.get_unchecked(L_CAPACITY - 1)).assume_init() };
BranchInsertState::Split(max, node)
}
L_CAPACITY_N1 => {
let _kdrop =
unsafe { ptr::read(self.key.get_unchecked(L_CAPACITY - 1)).assume_init() };
BranchInsertState::Split(node, max)
}
ins_idx => {
let maxn1 = unsafe { *(self.nodes.get_unchecked(BV_CAPACITY - 2)) };
let _kdrop =
unsafe { ptr::read(self.key.get_unchecked(L_CAPACITY - 1)).assume_init() };
let _kdrop =
unsafe { ptr::read(self.key.get_unchecked(L_CAPACITY - 2)).assume_init() };
let k: K = kr.clone();
let leaf_ins_idx = ins_idx + 1;
unsafe {
slice_insert(&mut self.key, MaybeUninit::new(k), ins_idx);
slice_insert(&mut self.nodes, node, leaf_ins_idx);
}
BranchInsertState::Split(maxn1, max)
}
};
self.dec_count();
res
} else {
let k: K = unsafe { (*node).min().clone() };
let r = key_search!(self, &k);
let ins_idx = r.unwrap_err();
let leaf_ins_idx = ins_idx + 1;
unsafe {
slice_insert(&mut self.key, MaybeUninit::new(k), ins_idx);
slice_insert(&mut self.nodes, node, leaf_ins_idx);
}
self.inc_count();
BranchInsertState::Ok
}
}
pub(crate) fn add_node_left(
&mut self,
lnode: *mut Node<K, V>,
sibidx: usize,
) -> BranchInsertState<K, V> {
debug_assert_branch!(self);
if self.count() == L_CAPACITY {
if sibidx == self.count() {
let max = self.nodes[BV_CAPACITY - 1];
let _kdrop =
unsafe { ptr::read(self.key.get_unchecked(L_CAPACITY - 1)).assume_init() };
self.dec_count();
BranchInsertState::Split(lnode, max)
} else if sibidx == (self.count() - 1) {
let maxn1 = self.nodes[BV_CAPACITY - 2];
let max = self.nodes[BV_CAPACITY - 1];
let _kdrop =
unsafe { ptr::read(self.key.get_unchecked(L_CAPACITY - 1)).assume_init() };
let _kdrop =
unsafe { ptr::read(self.key.get_unchecked(L_CAPACITY - 2)).assume_init() };
self.dec_count();
self.dec_count();
let k: K = unsafe { (*lnode).min().clone() };
unsafe {
slice_insert(&mut self.key, MaybeUninit::new(k), sibidx - 1);
slice_insert(&mut self.nodes, lnode, sibidx);
}
self.inc_count();
BranchInsertState::Split(maxn1, max)
} else {
let maxn1 = self.nodes[BV_CAPACITY - 2];
let max = self.nodes[BV_CAPACITY - 1];
let _kdrop =
unsafe { ptr::read(self.key.get_unchecked(L_CAPACITY - 1)).assume_init() };
let _kdrop =
unsafe { ptr::read(self.key.get_unchecked(L_CAPACITY - 2)).assume_init() };
self.dec_count();
self.dec_count();
let sibnode = self.nodes[sibidx];
let nkey: K = unsafe { (*sibnode).min().clone() };
unsafe {
slice_insert(&mut self.key, MaybeUninit::new(nkey), sibidx);
slice_insert(&mut self.nodes, lnode, sibidx);
}
self.inc_count();
BranchInsertState::Split(maxn1, max)
}
} else {
let sibnode = self.nodes[sibidx];
let nkey: K = unsafe { (*sibnode).min().clone() };
unsafe {
slice_insert(&mut self.nodes, lnode, sibidx);
slice_insert(&mut self.key, MaybeUninit::new(nkey), sibidx);
}
self.inc_count();
BranchInsertState::Ok
}
}
fn remove_by_idx(&mut self, idx: usize) -> *mut Node<K, V> {
debug_assert_branch!(self);
debug_assert!(idx <= self.count());
debug_assert!(idx > 0);
let _pk = unsafe { slice_remove(&mut self.key, idx - 1).assume_init() };
let pn = unsafe { slice_remove(&mut self.nodes, idx) };
self.dec_count();
pn
}
pub(crate) fn shrink_decision(&mut self, ridx: usize) -> BranchShrinkState<K, V> {
debug_assert_branch!(self);
debug_assert!(ridx > 0 && ridx <= self.count());
let left = self.nodes[ridx - 1];
let right = self.nodes[ridx];
debug_assert!(!left.is_null());
debug_assert!(!right.is_null());
match unsafe { (*left).meta.0 & FLAG_MASK } {
FLAG_LEAF => {
let lmut = leaf_ref!(left, K, V);
let rmut = leaf_ref!(right, K, V);
if lmut.count() + rmut.count() <= L_CAPACITY {
lmut.merge(rmut);
let dnode = self.remove_by_idx(ridx);
debug_assert!(dnode == right);
if self.count() == 0 {
BranchShrinkState::Shrink(dnode)
} else {
BranchShrinkState::Merge(dnode)
}
} else if rmut.count() > (L_CAPACITY / 2) {
lmut.take_from_r_to_l(rmut);
self.rekey_by_idx(ridx);
BranchShrinkState::Balanced
} else if lmut.count() > (L_CAPACITY / 2) {
lmut.take_from_l_to_r(rmut);
self.rekey_by_idx(ridx);
BranchShrinkState::Balanced
} else {
BranchShrinkState::Balanced
}
}
FLAG_BRANCH => {
let lmut = branch_ref!(left, K, V);
let rmut = branch_ref!(right, K, V);
debug_assert!(rmut.count() == 0 || lmut.count() == 0);
debug_assert!(rmut.count() <= L_CAPACITY || lmut.count() <= L_CAPACITY);
if lmut.count() == L_CAPACITY {
lmut.take_from_l_to_r(rmut);
self.rekey_by_idx(ridx);
BranchShrinkState::Balanced
} else if rmut.count() == L_CAPACITY {
lmut.take_from_r_to_l(rmut);
self.rekey_by_idx(ridx);
BranchShrinkState::Balanced
} else {
lmut.merge(rmut);
let dnode = self.remove_by_idx(ridx);
debug_assert!(dnode == right);
if self.count() == 0 {
BranchShrinkState::Shrink(dnode)
} else {
BranchShrinkState::Merge(dnode)
}
}
}
_ => unreachable!(),
}
}
#[inline(always)]
pub(crate) fn extract_last_node(&self) -> *mut Node<K, V> {
debug_assert_branch!(self);
self.nodes[0]
}
pub(crate) fn rekey_by_idx(&mut self, idx: usize) {
debug_assert_branch!(self);
debug_assert!(idx <= self.count());
debug_assert!(idx > 0);
let nref = self.nodes[idx];
let nkey = unsafe { ((*nref).min()).clone() };
unsafe {
self.key[idx - 1].as_mut_ptr().write(nkey);
}
}
#[inline(always)]
pub(crate) fn merge(&mut self, right: &mut Self) {
debug_assert_branch!(self);
debug_assert_branch!(right);
let sc = self.count();
let rc = right.count();
if rc == 0 {
let node = right.nodes[0];
debug_assert!(!node.is_null());
let k: K = unsafe { (*node).min().clone() };
let ins_idx = self.count();
let leaf_ins_idx = ins_idx + 1;
unsafe {
slice_insert(&mut self.key, MaybeUninit::new(k), ins_idx);
slice_insert(&mut self.nodes, node, leaf_ins_idx);
}
self.inc_count();
} else {
debug_assert!(sc == 0);
unsafe {
slice_merge(&mut self.nodes, 1, &mut right.nodes, rc + 1);
slice_merge(&mut self.key, 1, &mut right.key, rc);
}
self.meta.set_count(rc + 1);
right.meta.set_count(0);
unsafe {
let nptr = self.nodes[1];
let k: K = (*nptr).min().clone();
self.key[0].as_mut_ptr().write(k);
}
}
}
pub(crate) fn take_from_l_to_r(&mut self, right: &mut Self) {
debug_assert_branch!(self);
debug_assert_branch!(right);
debug_assert!(self.count() > right.count());
let count = (self.count() + right.count()) / 2;
let start_idx = self.count() - count;
unsafe {
ptr::swap(
right.nodes.get_unchecked_mut(0),
right.nodes.get_unchecked_mut(count),
)
}
unsafe {
slice_move(&mut right.nodes, 0, &mut self.nodes, start_idx + 1, count);
}
for kidx in (start_idx - 1)..L_CAPACITY {
let _pk = unsafe { ptr::read(self.key.get_unchecked(kidx)).assume_init() };
}
right.meta.set_count(count);
self.meta.set_count(start_idx);
for kidx in 1..(count + 1) {
right.rekey_by_idx(kidx);
}
}
pub(crate) fn take_from_r_to_l(&mut self, right: &mut Self) {
debug_assert_branch!(self);
debug_assert_branch!(right);
debug_assert!(right.count() >= self.count());
let count = (self.count() + right.count()) / 2;
let start_idx = right.count() - count;
unsafe {
slice_move(&mut self.nodes, 1, &mut right.nodes, 0, count);
}
for kidx in 0..count {
let _pk = unsafe { ptr::read(right.key.get_unchecked(kidx)).assume_init() };
}
unsafe {
ptr::copy(
right.key.as_ptr().add(count),
right.key.as_mut_ptr(),
start_idx,
);
}
unsafe {
ptr::copy(
right.nodes.as_ptr().add(count),
right.nodes.as_mut_ptr(),
start_idx + 1,
);
}
right.meta.set_count(start_idx);
self.meta.set_count(count);
for kidx in 1..(count + 1) {
self.rekey_by_idx(kidx);
}
}
#[inline(always)]
pub(crate) fn replace_by_idx(&mut self, idx: usize, node: *mut Node<K, V>) {
debug_assert_branch!(self);
debug_assert!(idx <= self.count());
debug_assert!(!self.nodes[idx].is_null());
self.nodes[idx] = node;
}
pub(crate) fn clone_sibling_idx(
&mut self,
txid: u64,
idx: usize,
last_seen: &mut Vec<*mut Node<K, V>>,
first_seen: &mut Vec<*mut Node<K, V>>,
) -> usize {
debug_assert_branch!(self);
let (ridx, idx) = if idx == 0 {
(1, 1)
} else {
(idx, idx - 1)
};
debug_assert!(idx <= self.count());
let sib_ptr = self.nodes[idx];
debug_assert!(!sib_ptr.is_null());
let res = match unsafe { (*sib_ptr).meta.0 & FLAG_MASK } {
FLAG_LEAF => {
let lref = unsafe { &*(sib_ptr as *const _ as *const Leaf<K, V>) };
lref.req_clone(txid)
}
FLAG_BRANCH => {
let bref = unsafe { &*(sib_ptr as *const _ as *const Branch<K, V>) };
bref.req_clone(txid)
}
_ => unreachable!(),
};
res.map(|n_ptr| {
first_seen.push(n_ptr);
last_seen.push(sib_ptr);
self.nodes[idx] = n_ptr;
});
ridx
}
#[inline(always)]
pub(crate) fn make_ro(&self) {
debug_assert_branch!(self);
}
pub(crate) fn verify(&self) -> bool {
debug_assert_branch!(self);
if self.count() == 0 {
debug_assert!(false);
return false;
}
let mut lk: &K = unsafe { &*self.key[0].as_ptr() };
for work_idx in 1..self.count() {
let rk: &K = unsafe { &*self.key[work_idx].as_ptr() };
if lk >= rk {
debug_assert!(false);
return false;
}
lk = rk;
}
for work_idx in 0..self.count() {
let node = unsafe { &*self.nodes[work_idx] };
if !node.verify() {
for work_idx in 0..(self.count() + 1) {
let nref = unsafe { &*self.nodes[work_idx] };
if !nref.verify() {
debug_assert!(false);
return false;
}
}
}
}
for work_idx in 0..self.count() {
let lnode = unsafe { &*self.nodes[work_idx] };
let rnode = unsafe { &*self.nodes[work_idx + 1] };
let pkey = unsafe { &*self.key[work_idx].as_ptr() };
let lkey = lnode.max();
let rkey = rnode.min();
if lkey >= pkey || pkey > rkey {
debug_assert!(false);
return false;
}
}
true
}
fn free(node: *mut Self) {
unsafe {
let mut _x: Box<Branch<K, V>> = Box::from_raw(node as *mut Branch<K, V>);
}
}
}
impl<K: Ord + Clone + Debug, V: Clone> Debug for Branch<K, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), Error> {
debug_assert_branch!(self);
write!(f, "Branch -> {}", self.count())?;
#[cfg(all(test, not(miri)))]
write!(f, " nid: {}", self.nid)?;
write!(f, " \\-> [ ")?;
for idx in 0..self.count() {
write!(f, "{:?}, ", unsafe { &*self.key[idx].as_ptr() })?;
}
write!(f, " ]")
}
}
impl<K: Ord + Clone + Debug, V: Clone> Drop for Branch<K, V> {
fn drop(&mut self) {
debug_assert_branch!(self);
#[cfg(all(test, not(miri)))]
release_nid(self.nid);
unsafe {
for idx in 0..self.count() {
ptr::drop_in_place(self.key[idx].as_mut_ptr());
}
}
self.meta.0 = FLAG_DROPPED;
debug_assert!(self.meta.0 & FLAG_MASK != FLAG_BRANCH);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_bptree2_node_cache_size() {
let ls = std::mem::size_of::<Leaf<u64, u64>>() - std::mem::size_of::<usize>();
let bs = std::mem::size_of::<Branch<u64, u64>>() - std::mem::size_of::<usize>();
#[cfg(feature = "skinny")]
{
assert!(ls <= 64);
assert!(bs <= 64);
}
#[cfg(not(feature = "skinny"))]
{
assert!(ls <= 128);
assert!(bs <= 128);
}
}
#[test]
fn test_bptree2_node_test_weird_basics() {
let leaf: *mut Leaf<u64, u64> = Node::new_leaf(1);
let leaf = unsafe { &mut *leaf };
assert!(leaf.get_txid() == 1);
leaf.set_count(1);
assert!(leaf.count() == 1);
leaf.set_count(0);
assert!(leaf.count() == 0);
leaf.inc_count();
leaf.inc_count();
leaf.inc_count();
assert!(leaf.count() == 3);
leaf.dec_count();
leaf.dec_count();
leaf.dec_count();
assert!(leaf.count() == 0);
Leaf::free(leaf as *mut _);
assert_released();
}
#[test]
fn test_bptree2_node_leaf_in_order() {
let leaf: *mut Leaf<usize, usize> = Node::new_leaf(1);
let leaf = unsafe { &mut *leaf };
assert!(leaf.get_txid() == 1);
for kv in 0..L_CAPACITY {
let r = leaf.insert_or_update(kv, kv);
if let LeafInsertState::Ok(None) = r {
assert!(leaf.get_ref(&kv) == Some(&kv));
} else {
assert!(false);
}
}
assert!(leaf.verify());
for kv in 0..L_CAPACITY {
let r = leaf.insert_or_update(kv, kv);
if let LeafInsertState::Ok(Some(pkv)) = r {
assert!(pkv == kv);
assert!(leaf.get_ref(&kv) == Some(&kv));
} else {
assert!(false);
}
}
assert!(leaf.verify());
Leaf::free(leaf as *mut _);
assert_released();
}
#[test]
fn test_bptree2_node_leaf_out_of_order() {
let leaf: *mut Leaf<usize, usize> = Node::new_leaf(1);
let leaf = unsafe { &mut *leaf };
assert!(L_CAPACITY <= 8);
let kvs = [7, 5, 1, 6, 2, 3, 0, 8];
assert!(leaf.get_txid() == 1);
for idx in 0..L_CAPACITY {
let kv = kvs[idx];
let r = leaf.insert_or_update(kv, kv);
if let LeafInsertState::Ok(None) = r {
assert!(leaf.get_ref(&kv) == Some(&kv));
} else {
assert!(false);
}
}
assert!(leaf.verify());
assert!(leaf.count() == L_CAPACITY);
for idx in 0..L_CAPACITY {
let kv = kvs[idx];
let r = leaf.insert_or_update(kv, kv);
if let LeafInsertState::Ok(Some(pkv)) = r {
assert!(pkv == kv);
assert!(leaf.get_ref(&kv) == Some(&kv));
} else {
assert!(false);
}
}
assert!(leaf.verify());
assert!(leaf.count() == L_CAPACITY);
Leaf::free(leaf as *mut _);
assert_released();
}
#[test]
fn test_bptree2_node_leaf_min() {
let leaf: *mut Leaf<usize, usize> = Node::new_leaf(1);
let leaf = unsafe { &mut *leaf };
assert!(L_CAPACITY <= 8);
let kvs = [3, 2, 6, 4, 5, 1, 9, 0];
let min = [3, 2, 2, 2, 2, 1, 1, 0];
for idx in 0..L_CAPACITY {
let kv = kvs[idx];
let r = leaf.insert_or_update(kv, kv);
if let LeafInsertState::Ok(None) = r {
assert!(leaf.get_ref(&kv) == Some(&kv));
assert!(leaf.min() == &min[idx]);
} else {
assert!(false);
}
}
assert!(leaf.verify());
assert!(leaf.count() == L_CAPACITY);
Leaf::free(leaf as *mut _);
assert_released();
}
#[test]
fn test_bptree2_node_leaf_max() {
let leaf: *mut Leaf<usize, usize> = Node::new_leaf(1);
let leaf = unsafe { &mut *leaf };
assert!(L_CAPACITY <= 8);
let kvs = [1, 3, 2, 6, 4, 5, 9, 0];
let max: [usize; 8] = [1, 3, 3, 6, 6, 6, 9, 9];
for idx in 0..L_CAPACITY {
let kv = kvs[idx];
let r = leaf.insert_or_update(kv, kv);
if let LeafInsertState::Ok(None) = r {
assert!(leaf.get_ref(&kv) == Some(&kv));
assert!(leaf.max() == &max[idx]);
} else {
assert!(false);
}
}
assert!(leaf.verify());
assert!(leaf.count() == L_CAPACITY);
Leaf::free(leaf as *mut _);
assert_released();
}
#[test]
fn test_bptree2_node_leaf_remove_order() {
let leaf: *mut Leaf<usize, usize> = Node::new_leaf(1);
let leaf = unsafe { &mut *leaf };
for kv in 0..L_CAPACITY {
leaf.insert_or_update(kv, kv);
}
for kv in 0..(L_CAPACITY - 1) {
let r = leaf.remove(&kv);
if let LeafRemoveState::Ok(Some(rkv)) = r {
assert!(rkv == kv);
} else {
assert!(false);
}
}
assert!(leaf.count() == 1);
assert!(leaf.max() == &(L_CAPACITY - 1));
let r = leaf.remove(&(L_CAPACITY + 20));
if let LeafRemoveState::Ok(None) = r {
} else {
assert!(false);
}
let kv = L_CAPACITY - 1;
let r = leaf.remove(&kv);
if let LeafRemoveState::Shrink(Some(rkv)) = r {
assert!(rkv == kv);
} else {
assert!(false);
}
assert!(leaf.count() == 0);
let r = leaf.remove(&0);
if let LeafRemoveState::Shrink(None) = r {
} else {
assert!(false);
}
assert!(leaf.count() == 0);
assert!(leaf.verify());
Leaf::free(leaf as *mut _);
assert_released();
}
#[test]
fn test_bptree2_node_leaf_remove_out_of_order() {
let leaf: *mut Leaf<usize, usize> = Node::new_leaf(1);
let leaf = unsafe { &mut *leaf };
for kv in 0..L_CAPACITY {
leaf.insert_or_update(kv, kv);
}
let mid = L_CAPACITY / 2;
for kv in mid..(L_CAPACITY - 1) {
let r = leaf.remove(&kv);
match r {
LeafRemoveState::Ok(_) => {}
_ => panic!(),
}
}
for kv in 0..(L_CAPACITY / 2) {
let r = leaf.remove(&kv);
match r {
LeafRemoveState::Ok(_) => {}
_ => panic!(),
}
}
assert!(leaf.count() == 1);
assert!(leaf.verify());
Leaf::free(leaf as *mut _);
assert_released();
}
#[test]
fn test_bptree2_node_leaf_insert_split() {
let leaf: *mut Leaf<usize, usize> = Node::new_leaf(1);
let leaf = unsafe { &mut *leaf };
for kv in 0..L_CAPACITY {
leaf.insert_or_update(kv + 10, kv + 10);
}
let r = leaf.insert_or_update(L_CAPACITY + 10, L_CAPACITY + 10);
if let LeafInsertState::Split(rleaf) = r {
unsafe {
assert!((&*rleaf).count() == 1);
}
Leaf::free(rleaf);
} else {
panic!();
}
let r = leaf.insert_or_update(0, 0);
if let LeafInsertState::RevSplit(lleaf) = r {
unsafe {
assert!((&*lleaf).count() == 1);
}
Leaf::free(lleaf);
} else {
panic!();
}
assert!(leaf.count() == L_CAPACITY);
assert!(leaf.verify());
Leaf::free(leaf as *mut _);
assert_released();
}
#[test]
fn test_bptree2_node_branch_new() {
let left: *mut Leaf<usize, usize> = Node::new_leaf(1);
let left_ref = unsafe { &mut *left };
let right: *mut Leaf<usize, usize> = Node::new_leaf(1);
let right_ref = unsafe { &mut *right };
for kv in 0..L_CAPACITY {
left_ref.insert_or_update(kv + 10, kv + 10);
right_ref.insert_or_update(kv + 20, kv + 20);
}
let branch: *mut Branch<usize, usize> = Node::new_branch(
1,
left as *mut Node<usize, usize>,
right as *mut Node<usize, usize>,
);
let branch_ref = unsafe { &mut *branch };
assert!(branch_ref.verify());
assert!(branch_ref.min() == &10);
assert!(branch_ref.max() == &(20 + L_CAPACITY - 1));
assert!(branch_ref.get_ref(&11) == Some(&11));
assert!(branch_ref.get_ref(&21) == Some(&21));
assert!(branch_ref.get_ref(&1) == None);
assert!(branch_ref.get_ref(&100) == None);
Leaf::free(left as *mut _);
Leaf::free(right as *mut _);
Branch::free(branch as *mut _);
assert_released();
}
macro_rules! test_3_leaf {
($fun:expr) => {{
let a: *mut Leaf<usize, usize> = Node::new_leaf(1);
let b: *mut Leaf<usize, usize> = Node::new_leaf(1);
let c: *mut Leaf<usize, usize> = Node::new_leaf(1);
unsafe {
(*a).insert_or_update(10, 10);
(*b).insert_or_update(20, 20);
(*c).insert_or_update(30, 30);
}
$fun(a, b, c);
Leaf::free(a as *mut _);
Leaf::free(b as *mut _);
Leaf::free(c as *mut _);
assert_released();
}};
}
#[test]
fn test_bptree2_node_branch_add_min() {
test_3_leaf!(|a, b, c| {
let branch: *mut Branch<usize, usize> = Node::new_branch(
1,
b as *mut Node<usize, usize>,
c as *mut Node<usize, usize>,
);
let branch_ref = unsafe { &mut *branch };
assert!(branch_ref.verify());
let r = branch_ref.add_node_left(a as *mut Node<usize, usize>, 0);
match r {
BranchInsertState::Ok => {}
_ => debug_assert!(false),
};
assert!(branch_ref.verify());
Branch::free(branch as *mut _);
})
}
#[test]
fn test_bptree2_node_branch_add_mid() {
test_3_leaf!(|a, b, c| {
let branch: *mut Branch<usize, usize> = Node::new_branch(
1,
a as *mut Node<usize, usize>,
c as *mut Node<usize, usize>,
);
let branch_ref = unsafe { &mut *branch };
assert!(branch_ref.verify());
let r = branch_ref.add_node(b as *mut Node<usize, usize>);
match r {
BranchInsertState::Ok => {}
_ => debug_assert!(false),
};
assert!(branch_ref.verify());
Branch::free(branch as *mut _);
})
}
#[test]
fn test_bptree2_node_branch_add_max() {
test_3_leaf!(|a, b, c| {
let branch: *mut Branch<usize, usize> = Node::new_branch(
1,
a as *mut Node<usize, usize>,
b as *mut Node<usize, usize>,
);
let branch_ref = unsafe { &mut *branch };
assert!(branch_ref.verify());
let r = branch_ref.add_node(c as *mut Node<usize, usize>);
match r {
BranchInsertState::Ok => {}
_ => debug_assert!(false),
};
assert!(branch_ref.verify());
Branch::free(branch as *mut _);
})
}
macro_rules! test_max_leaf {
($fun:expr) => {{
let a: *mut Leaf<usize, usize> = Node::new_leaf(1);
let b: *mut Leaf<usize, usize> = Node::new_leaf(1);
let c: *mut Leaf<usize, usize> = Node::new_leaf(1);
let d: *mut Leaf<usize, usize> = Node::new_leaf(1);
#[cfg(not(feature = "skinny"))]
let e: *mut Leaf<usize, usize> = Node::new_leaf(1);
#[cfg(not(feature = "skinny"))]
let f: *mut Leaf<usize, usize> = Node::new_leaf(1);
#[cfg(not(feature = "skinny"))]
let g: *mut Leaf<usize, usize> = Node::new_leaf(1);
#[cfg(not(feature = "skinny"))]
let h: *mut Leaf<usize, usize> = Node::new_leaf(1);
unsafe {
(*a).insert_or_update(10, 10);
(*b).insert_or_update(20, 20);
(*c).insert_or_update(30, 30);
(*d).insert_or_update(40, 40);
#[cfg(not(feature = "skinny"))]
{
(*e).insert_or_update(50, 50);
(*f).insert_or_update(60, 60);
(*g).insert_or_update(70, 70);
(*h).insert_or_update(80, 80);
}
}
let branch: *mut Branch<usize, usize> = Node::new_branch(
1,
a as *mut Node<usize, usize>,
b as *mut Node<usize, usize>,
);
let branch_ref = unsafe { &mut *branch };
branch_ref.add_node(c as *mut Node<usize, usize>);
branch_ref.add_node(d as *mut Node<usize, usize>);
#[cfg(not(feature = "skinny"))]
{
branch_ref.add_node(e as *mut Node<usize, usize>);
branch_ref.add_node(f as *mut Node<usize, usize>);
branch_ref.add_node(g as *mut Node<usize, usize>);
branch_ref.add_node(h as *mut Node<usize, usize>);
}
assert!(branch_ref.count() == L_CAPACITY);
#[cfg(feature = "skinny")]
$fun(branch_ref, 40);
#[cfg(not(feature = "skinny"))]
$fun(branch_ref, 80);
Branch::free(branch as *mut _);
Leaf::free(a as *mut _);
Leaf::free(b as *mut _);
Leaf::free(c as *mut _);
Leaf::free(d as *mut _);
#[cfg(not(feature = "skinny"))]
{
Leaf::free(e as *mut _);
Leaf::free(f as *mut _);
Leaf::free(g as *mut _);
Leaf::free(h as *mut _);
}
assert_released();
}};
}
#[test]
fn test_bptree2_node_branch_add_split_min() {
}
#[test]
fn test_bptree2_node_branch_add_split_mid() {
test_max_leaf!(|branch_ref: &mut Branch<usize, usize>, max: usize| {
let node: *mut Leaf<usize, usize> = Node::new_leaf(1);
unsafe {
(*node).insert_or_update(15, 15);
};
let r = branch_ref.add_node(node as *mut _);
match r {
BranchInsertState::Split(x, y) => {
unsafe {
assert!((*x).min() == &(max - 10));
assert!((*y).min() == &max);
}
}
_ => debug_assert!(false),
};
assert!(branch_ref.verify());
Leaf::free(node as *mut _);
})
}
#[test]
fn test_bptree2_node_branch_add_split_max() {
test_max_leaf!(|branch_ref: &mut Branch<usize, usize>, max: usize| {
let node: *mut Leaf<usize, usize> = Node::new_leaf(1);
unsafe {
(*node).insert_or_update(200, 200);
};
let r = branch_ref.add_node(node as *mut _);
match r {
BranchInsertState::Split(y, mynode) => {
unsafe {
assert!((*y).min() == &max);
assert!((*mynode).min() == &200);
}
}
_ => debug_assert!(false),
};
assert!(branch_ref.verify());
Leaf::free(node as *mut _);
})
}
#[test]
fn test_bptree2_node_branch_add_split_n1max() {
test_max_leaf!(|branch_ref: &mut Branch<usize, usize>, max: usize| {
let node: *mut Leaf<usize, usize> = Node::new_leaf(1);
unsafe {
(*node).insert_or_update(max - 5, max - 5);
};
let r = branch_ref.add_node(node as *mut _);
match r {
BranchInsertState::Split(mynode, y) => {
unsafe {
assert!((*mynode).min() == &(max - 5));
assert!((*y).min() == &max);
}
}
_ => debug_assert!(false),
};
assert!(branch_ref.verify());
Leaf::free(node as *mut _);
})
}
}