use super::node::*;
use crate::internals::lincowcell::LinCowCellCapable;
use std::borrow::Borrow;
use std::fmt::Debug;
use std::mem;
use super::iter::{Iter, KeyIter, RangeIter, ValueIter};
use super::mutiter::RangeMutIter;
use super::states::*;
use std::ops::RangeBounds;
use std::sync::Mutex;
#[derive(Debug)]
pub(crate) struct SuperBlock<K, V>
where
K: Ord + Clone + Debug,
V: Clone,
{
root: *mut Node<K, V>,
size: usize,
txid: u64,
}
unsafe impl<K: Clone + Ord + Debug + Send + 'static, V: Clone + Send + 'static> Send
for SuperBlock<K, V>
{
}
unsafe impl<K: Clone + Ord + Debug + Sync + Send + 'static, V: Clone + Sync + Send + 'static> Sync
for SuperBlock<K, V>
{
}
impl<K: Clone + Ord + Debug, V: Clone> LinCowCellCapable<CursorRead<K, V>, CursorWrite<K, V>>
for SuperBlock<K, V>
{
fn create_reader(&self) -> CursorRead<K, V> {
CursorRead::new(self)
}
fn create_writer(&self) -> CursorWrite<K, V> {
CursorWrite::new(self)
}
fn pre_commit(
&mut self,
mut new: CursorWrite<K, V>,
prev: &CursorRead<K, V>,
) -> CursorRead<K, V> {
let mut prev_last_seen = prev.last_seen.lock().unwrap();
debug_assert!((*prev_last_seen).is_empty());
let new_last_seen = &mut new.last_seen;
std::mem::swap(&mut (*prev_last_seen), &mut (*new_last_seen));
debug_assert!((*new_last_seen).is_empty());
new.first_seen.iter().for_each(|n| {
Node::make_ro_raw(*n);
});
new.first_seen.clear();
self.root = new.root;
self.size = new.length;
self.txid = new.txid;
CursorRead::new(self)
}
}
impl<K: Clone + Ord + Debug, V: Clone> SuperBlock<K, V> {
pub unsafe fn new() -> Self {
let leaf: *mut Leaf<K, V> = Node::new_leaf(1);
SuperBlock {
root: leaf as *mut Node<K, V>,
size: 0,
txid: 1,
}
}
#[cfg(test)]
pub(crate) fn new_test(txid: u64, root: *mut Node<K, V>) -> Self {
assert!(txid < (TXID_MASK >> TXID_SHF));
assert!(txid > 0);
let mut first_seen = Vec::with_capacity(16);
assert!(Node::verify_raw(root));
first_seen.push(root);
Node::sblock_collect_raw(root, &mut first_seen);
first_seen.iter().for_each(|n| {
Node::make_ro_raw(*n);
});
let (length, _) = Node::tree_density_raw(root);
SuperBlock {
txid,
size: length,
root,
}
}
}
#[derive(Debug)]
pub(crate) struct CursorRead<K, V>
where
K: Ord + Clone + Debug,
V: Clone,
{
txid: u64,
length: usize,
root: *mut Node<K, V>,
last_seen: Mutex<Vec<*mut Node<K, V>>>,
}
unsafe impl<K: Clone + Ord + Debug + Send + 'static, V: Clone + Send + 'static> Send
for CursorRead<K, V>
{
}
unsafe impl<K: Clone + Ord + Debug + Sync + Send + 'static, V: Clone + Sync + Send + 'static> Sync
for CursorRead<K, V>
{
}
#[derive(Debug)]
pub(crate) struct CursorWrite<K, V>
where
K: Ord + Clone + Debug,
V: Clone,
{
txid: u64,
length: usize,
root: *mut Node<K, V>,
last_seen: Vec<*mut Node<K, V>>,
first_seen: Vec<*mut Node<K, V>>,
}
unsafe impl<K: Clone + Ord + Debug + Send + 'static, V: Clone + Send + 'static> Send
for CursorWrite<K, V>
{
}
unsafe impl<K: Clone + Ord + Debug + Sync + Send + 'static, V: Clone + Sync + Send + 'static> Sync
for CursorWrite<K, V>
{
}
pub(crate) trait CursorReadOps<K: Clone + Ord + Debug, V: Clone> {
#[allow(unused)]
fn get_root_ref(&self) -> &Node<K, V>;
fn get_root(&self) -> *mut Node<K, V>;
fn len(&self) -> usize;
fn get_txid(&self) -> u64;
#[cfg(test)]
fn get_tree_density(&self) -> (usize, usize) {
let rref = self.get_root();
Node::tree_density_raw(rref)
}
fn search<Q>(&self, k: &Q) -> Option<&V>
where
K: Borrow<Q>,
Q: Ord + ?Sized,
{
let mut node = self.get_root();
for _i in 0..65536 {
if unsafe { (*node).is_leaf() } {
let lref = leaf_ref!(node, K, V);
return lref.get_ref(k).map(|v| unsafe {
let x = v as *const V;
&*x as &V
});
} else {
let bref = branch_ref!(node, K, V);
let idx = bref.locate_node(k);
node = bref.get_idx_unchecked(idx);
}
}
panic!("Tree depth exceeded max limit (65536). This may indicate memory corruption.");
}
fn contains_key<Q>(&self, k: &Q) -> bool
where
K: Borrow<Q>,
Q: Ord + ?Sized,
{
self.search(k).is_some()
}
fn first_key_value(&self) -> Option<(&K, &V)> {
let mut node = self.get_root();
for _i in 0..65536 {
if unsafe { (*node).is_leaf() } {
let lref = leaf_ref!(node, K, V);
return lref.min_value();
} else {
let bref = branch_ref!(node, K, V);
node = bref.min_node();
}
}
panic!("Tree depth exceeded max limit (65536). This may indicate memory corruption.");
}
fn last_key_value(&self) -> Option<(&K, &V)> {
let mut node = self.get_root();
for _i in 0..65536 {
if unsafe { (*node).is_leaf() } {
let lref = leaf_ref!(node, K, V);
return lref.max_value();
} else {
let bref = branch_ref!(node, K, V);
node = bref.max_node();
}
}
panic!("Tree depth exceeded max limit (65536). This may indicate memory corruption.");
}
fn range<'n, R, T>(&'n self, range: R) -> RangeIter<'n, K, V>
where
K: Borrow<T>,
T: Ord + ?Sized,
R: RangeBounds<T>,
{
RangeIter::new(self.get_root(), range, self.len())
}
fn kv_iter<'n>(&'n self) -> Iter<'n, K, V> {
Iter::new(self.get_root(), self.len())
}
fn k_iter<'n>(&'n self) -> KeyIter<'n, K, V> {
KeyIter::new(self.get_root(), self.len())
}
fn v_iter<'n>(&'n self) -> ValueIter<'n, K, V> {
ValueIter::new(self.get_root(), self.len())
}
#[cfg(test)]
fn verify(&self) -> bool {
Node::no_cycles_raw(self.get_root()) && Node::verify_raw(self.get_root()) && {
let (l, _) = self.get_tree_density();
l == self.len()
}
}
}
impl<K: Clone + Ord + Debug, V: Clone> CursorWrite<K, V> {
pub(crate) fn new(sblock: &SuperBlock<K, V>) -> Self {
let txid = sblock.txid + 1;
assert!(txid < (TXID_MASK >> TXID_SHF));
let length = sblock.size;
let root = sblock.root;
let last_seen = Vec::with_capacity(16);
let first_seen = Vec::with_capacity(16);
CursorWrite {
txid,
length,
root,
last_seen,
first_seen,
}
}
pub(crate) fn clear(&mut self) {
self.last_seen.push(self.root);
unsafe { (*self.root).sblock_collect(&mut self.last_seen) };
let nroot: *mut Leaf<K, V> = Node::new_leaf(self.txid);
let mut nroot = nroot as *mut Node<K, V>;
self.first_seen.push(nroot);
mem::swap(&mut self.root, &mut nroot);
self.length = 0;
}
pub(crate) fn insert(&mut self, k: K, v: V) -> Option<V> {
let r = match clone_and_insert(
self.root,
self.txid,
k,
v,
&mut self.last_seen,
&mut self.first_seen,
) {
CRInsertState::NoClone(res) => res,
CRInsertState::Clone(res, mut nnode) => {
mem::swap(&mut self.root, &mut nnode);
res
}
CRInsertState::CloneSplit(lnode, rnode) => {
let mut nroot = Node::new_branch(self.txid, lnode, rnode) as *mut Node<K, V>;
self.first_seen.push(nroot);
mem::swap(&mut self.root, &mut nroot);
None
}
CRInsertState::Split(rnode) => {
let mut nroot = Node::new_branch(self.txid, self.root, rnode) as *mut Node<K, V>;
self.first_seen.push(nroot);
mem::swap(&mut self.root, &mut nroot);
None
}
CRInsertState::RevSplit(lnode) => {
let mut nroot = Node::new_branch(self.txid, lnode, self.root) as *mut Node<K, V>;
self.first_seen.push(nroot);
mem::swap(&mut self.root, &mut nroot);
None
}
CRInsertState::CloneRevSplit(rnode, lnode) => {
let mut nroot = Node::new_branch(self.txid, lnode, rnode) as *mut Node<K, V>;
self.first_seen.push(nroot);
mem::swap(&mut self.root, &mut nroot);
None
}
};
if r.is_none() {
self.length += 1;
}
r
}
pub(crate) fn remove(&mut self, k: &K) -> Option<V> {
let r = match clone_and_remove(
self.root,
self.txid,
k,
&mut self.last_seen,
&mut self.first_seen,
) {
CRRemoveState::NoClone(res) => res,
CRRemoveState::Clone(res, mut nnode) => {
mem::swap(&mut self.root, &mut nnode);
res
}
CRRemoveState::Shrink(res) => {
if self_meta!(self.root).is_leaf() {
res
} else {
self.last_seen.push(self.root);
let rmut = branch_ref!(self.root, K, V);
let mut pnode = rmut.extract_last_node();
mem::swap(&mut self.root, &mut pnode);
res
}
}
CRRemoveState::CloneShrink(res, mut nnode) => {
if self_meta!(nnode).is_leaf() {
mem::swap(&mut self.root, &mut nnode);
res
} else {
self.last_seen.push(nnode);
let rmut = branch_ref!(nnode, K, V);
let mut pnode = rmut.extract_last_node();
mem::swap(&mut self.root, &mut pnode);
res
}
}
};
if r.is_some() {
self.length -= 1;
}
r
}
#[cfg(test)]
pub(crate) fn path_clone(&mut self, k: &K) {
match path_clone(
self.root,
self.txid,
k,
&mut self.last_seen,
&mut self.first_seen,
) {
CRCloneState::Clone(mut nroot) => {
mem::swap(&mut self.root, &mut nroot);
}
CRCloneState::NoClone => {}
};
}
pub(crate) fn get_mut_ref(&mut self, k: &K) -> Option<&mut V> {
match path_clone(
self.root,
self.txid,
k,
&mut self.last_seen,
&mut self.first_seen,
) {
CRCloneState::Clone(mut nroot) => {
mem::swap(&mut self.root, &mut nroot);
}
CRCloneState::NoClone => {}
};
path_get_mut_ref(self.root, k)
}
pub(crate) fn split_off_lt(&mut self, k: &K) {
let mut rmkeys: Vec<K> = Vec::new();
for ki in self.k_iter() {
if ki >= k {
break;
}
rmkeys.push(ki.clone());
}
for kr in rmkeys.into_iter() {
let _ = self.remove(&kr);
}
let newsize = self.kv_iter().count();
self.length = newsize;
}
#[cfg(test)]
pub(crate) fn root_txid(&self) -> u64 {
self.get_root_ref().get_txid()
}
#[cfg(test)]
pub(crate) fn tree_density(&self) -> (usize, usize) {
Node::<K, V>::tree_density_raw(self.get_root())
}
pub(crate) fn range_mut<'n, R, T>(&'n mut self, range: R) -> RangeMutIter<'n, K, V>
where
K: Borrow<T>,
T: Ord + ?Sized,
R: RangeBounds<T>,
{
RangeMutIter::new(self, range)
}
}
impl<K: Clone + Ord + Debug, V: Clone> Extend<(K, V)> for CursorWrite<K, V> {
fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I) {
iter.into_iter().for_each(|(k, v)| {
let _ = self.insert(k, v);
});
}
}
impl<K: Clone + Ord + Debug, V: Clone> Drop for CursorWrite<K, V> {
fn drop(&mut self) {
self.first_seen.iter().for_each(|n| Node::free(*n))
}
}
impl<K: Clone + Ord + Debug, V: Clone> Drop for CursorRead<K, V> {
fn drop(&mut self) {
let last_seen_guard = self
.last_seen
.try_lock()
.expect("Unable to lock, something is horridly wrong!");
last_seen_guard.iter().for_each(|n| Node::free(*n));
std::mem::drop(last_seen_guard);
}
}
impl<K: Clone + Ord + Debug, V: Clone> Drop for SuperBlock<K, V> {
fn drop(&mut self) {
let mut first_seen = Vec::with_capacity(16);
first_seen.push(self.root);
Node::sblock_collect_raw(self.root, &mut first_seen);
first_seen.iter().for_each(|n| Node::free(*n));
}
}
impl<K: Clone + Ord + Debug, V: Clone> CursorRead<K, V> {
pub(crate) fn new(sblock: &SuperBlock<K, V>) -> Self {
CursorRead {
txid: sblock.txid,
length: sblock.size,
root: sblock.root,
last_seen: Mutex::new(Vec::with_capacity(0)),
}
}
}
impl<K: Clone + Ord + Debug, V: Clone> CursorReadOps<K, V> for CursorRead<K, V> {
fn get_root_ref(&self) -> &Node<K, V> {
unsafe { &*(self.root) }
}
fn get_root(&self) -> *mut Node<K, V> {
self.root
}
fn len(&self) -> usize {
self.length
}
fn get_txid(&self) -> u64 {
self.txid
}
}
impl<K: Clone + Ord + Debug, V: Clone> CursorReadOps<K, V> for CursorWrite<K, V> {
fn get_root_ref(&self) -> &Node<K, V> {
unsafe { &*(self.root) }
}
fn get_root(&self) -> *mut Node<K, V> {
self.root
}
fn len(&self) -> usize {
self.length
}
fn get_txid(&self) -> u64 {
self.txid
}
}
fn clone_and_insert<K: Clone + Ord + Debug, V: Clone>(
node: *mut Node<K, V>,
txid: u64,
k: K,
v: V,
last_seen: &mut Vec<*mut Node<K, V>>,
first_seen: &mut Vec<*mut Node<K, V>>,
) -> CRInsertState<K, V> {
if self_meta!(node).is_leaf() {
match leaf_ref!(node, K, V).req_clone(txid) {
Some(cnode) => {
first_seen.push(cnode);
last_seen.push(node);
let mref = leaf_ref!(cnode, K, V);
match mref.insert_or_update(k, v) {
LeafInsertState::Ok(res) => CRInsertState::Clone(res, cnode),
LeafInsertState::Split(rnode) => {
first_seen.push(rnode as *mut Node<K, V>);
CRInsertState::CloneSplit(cnode, rnode as *mut Node<K, V>)
}
LeafInsertState::RevSplit(lnode) => {
first_seen.push(lnode as *mut Node<K, V>);
CRInsertState::CloneRevSplit(cnode, lnode as *mut Node<K, V>)
}
}
}
None => {
let mref = leaf_ref!(node, K, V);
match mref.insert_or_update(k, v) {
LeafInsertState::Ok(res) => CRInsertState::NoClone(res),
LeafInsertState::Split(rnode) => {
first_seen.push(rnode as *mut Node<K, V>);
CRInsertState::Split(rnode as *mut Node<K, V>)
}
LeafInsertState::RevSplit(lnode) => {
first_seen.push(lnode as *mut Node<K, V>);
CRInsertState::RevSplit(lnode as *mut Node<K, V>)
}
}
}
} } else {
match branch_ref!(node, K, V).req_clone(txid) {
Some(cnode) => {
first_seen.push(cnode);
last_seen.push(node);
let nmref = branch_ref!(cnode, K, V);
let anode_idx = nmref.locate_node(&k);
let anode = nmref.get_idx_unchecked(anode_idx);
match clone_and_insert(anode, txid, k, v, last_seen, first_seen) {
CRInsertState::Clone(res, lnode) => {
nmref.replace_by_idx(anode_idx, lnode);
CRInsertState::Clone(res, cnode)
}
CRInsertState::CloneSplit(lnode, rnode) => {
nmref.replace_by_idx(anode_idx, lnode);
match nmref.add_node(rnode) {
BranchInsertState::Ok => CRInsertState::Clone(None, cnode),
BranchInsertState::Split(clnode, crnode) => {
let nrnode = Node::new_branch(txid, clnode, crnode);
first_seen.push(nrnode as *mut Node<K, V>);
CRInsertState::CloneSplit(cnode, nrnode as *mut Node<K, V>)
}
}
}
CRInsertState::CloneRevSplit(nnode, lnode) => {
nmref.replace_by_idx(anode_idx, nnode);
match nmref.add_node_left(lnode, anode_idx) {
BranchInsertState::Ok => CRInsertState::Clone(None, cnode),
BranchInsertState::Split(clnode, crnode) => {
let nrnode = Node::new_branch(txid, clnode, crnode);
first_seen.push(nrnode as *mut Node<K, V>);
CRInsertState::CloneSplit(cnode, nrnode as *mut Node<K, V>)
}
}
}
CRInsertState::NoClone(_res) => {
unreachable!("Should never be possible.");
}
CRInsertState::Split(_rnode) => {
unreachable!("This represents a corrupt tree state");
}
CRInsertState::RevSplit(_lnode) => {
unreachable!("This represents a corrupt tree state");
}
} } None => {
let nmref = branch_ref!(node, K, V);
let anode_idx = nmref.locate_node(&k);
let anode = nmref.get_idx_unchecked(anode_idx);
match clone_and_insert(anode, txid, k, v, last_seen, first_seen) {
CRInsertState::Clone(res, lnode) => {
nmref.replace_by_idx(anode_idx, lnode);
CRInsertState::NoClone(res)
}
CRInsertState::NoClone(res) => {
CRInsertState::NoClone(res)
}
CRInsertState::Split(rnode) => {
match nmref.add_node(rnode) {
BranchInsertState::Ok => CRInsertState::NoClone(None),
BranchInsertState::Split(clnode, crnode) => {
let nrnode = Node::new_branch(txid, clnode, crnode);
first_seen.push(nrnode as *mut Node<K, V>);
CRInsertState::Split(nrnode as *mut Node<K, V>)
}
}
}
CRInsertState::CloneSplit(lnode, rnode) => {
nmref.replace_by_idx(anode_idx, lnode);
match nmref.add_node(rnode) {
BranchInsertState::Ok => CRInsertState::NoClone(None),
BranchInsertState::Split(clnode, crnode) => {
let nrnode = Node::new_branch(txid, clnode, crnode);
first_seen.push(nrnode as *mut Node<K, V>);
CRInsertState::Split(nrnode as *mut Node<K, V>)
}
}
}
CRInsertState::RevSplit(lnode) => match nmref.add_node_left(lnode, anode_idx) {
BranchInsertState::Ok => CRInsertState::NoClone(None),
BranchInsertState::Split(clnode, crnode) => {
let nrnode = Node::new_branch(txid, clnode, crnode);
first_seen.push(nrnode as *mut Node<K, V>);
CRInsertState::Split(nrnode as *mut Node<K, V>)
}
},
CRInsertState::CloneRevSplit(nnode, lnode) => {
nmref.replace_by_idx(anode_idx, nnode);
match nmref.add_node_left(lnode, anode_idx) {
BranchInsertState::Ok => CRInsertState::NoClone(None),
BranchInsertState::Split(clnode, crnode) => {
let nrnode = Node::new_branch(txid, clnode, crnode);
first_seen.push(nrnode as *mut Node<K, V>);
CRInsertState::Split(nrnode as *mut Node<K, V>)
}
}
}
} }
} } }
fn path_clone<K: Clone + Ord + Debug, V: Clone>(
node: *mut Node<K, V>,
txid: u64,
k: &K,
last_seen: &mut Vec<*mut Node<K, V>>,
first_seen: &mut Vec<*mut Node<K, V>>,
) -> CRCloneState<K, V> {
if unsafe { (*node).is_leaf() } {
unsafe {
(*(node as *mut Leaf<K, V>))
.req_clone(txid)
.map(|cnode| {
last_seen.push(node);
first_seen.push(cnode);
CRCloneState::Clone(cnode)
})
.unwrap_or(CRCloneState::NoClone)
}
} else {
let nmref = branch_ref!(node, K, V);
let anode_idx = nmref.locate_node(k);
let anode = nmref.get_idx_unchecked(anode_idx);
match path_clone(anode, txid, k, last_seen, first_seen) {
CRCloneState::Clone(cnode) => {
nmref
.req_clone(txid)
.map(|acnode| {
last_seen.push(node);
first_seen.push(acnode);
let nmref = branch_ref!(acnode, K, V);
nmref.replace_by_idx(anode_idx, cnode);
CRCloneState::Clone(acnode)
})
.unwrap_or_else(|| {
nmref.replace_by_idx(anode_idx, cnode);
CRCloneState::NoClone
})
}
CRCloneState::NoClone => {
CRCloneState::NoClone
}
}
}
}
fn clone_and_remove<K: Clone + Ord + Debug, V: Clone>(
node: *mut Node<K, V>,
txid: u64,
k: &K,
last_seen: &mut Vec<*mut Node<K, V>>,
first_seen: &mut Vec<*mut Node<K, V>>,
) -> CRRemoveState<K, V> {
if self_meta!(node).is_leaf() {
leaf_ref!(node, K, V)
.req_clone(txid)
.map(|cnode| {
first_seen.push(cnode);
last_seen.push(node);
let mref = leaf_ref!(cnode, K, V);
match mref.remove(k) {
LeafRemoveState::Ok(res) => CRRemoveState::Clone(res, cnode),
LeafRemoveState::Shrink(res) => CRRemoveState::CloneShrink(res, cnode),
}
})
.unwrap_or_else(|| {
let mref = leaf_ref!(node, K, V);
match mref.remove(k) {
LeafRemoveState::Ok(res) => CRRemoveState::NoClone(res),
LeafRemoveState::Shrink(res) => CRRemoveState::Shrink(res),
}
})
} else {
branch_ref!(node, K, V)
.req_clone(txid)
.map(|cnode| {
first_seen.push(cnode);
last_seen.push(node);
let nmref = branch_ref!(cnode, K, V);
let anode_idx = nmref.locate_node(k);
let anode = nmref.get_idx_unchecked(anode_idx);
match clone_and_remove(anode, txid, k, last_seen, first_seen) {
CRRemoveState::NoClone(_res) => {
unreachable!("Should never occur");
}
CRRemoveState::Clone(res, lnode) => {
nmref.replace_by_idx(anode_idx, lnode);
CRRemoveState::Clone(res, cnode)
}
CRRemoveState::Shrink(_res) => {
unreachable!("This represents a corrupt tree state");
}
CRRemoveState::CloneShrink(res, nnode) => {
nmref.replace_by_idx(anode_idx, nnode);
let right_idx =
nmref.clone_sibling_idx(txid, anode_idx, last_seen, first_seen);
match nmref.shrink_decision(right_idx) {
BranchShrinkState::Balanced => {
CRRemoveState::Clone(res, cnode)
}
BranchShrinkState::Merge(dnode) => {
debug_assert!(!last_seen.contains(&dnode));
last_seen.push(dnode);
CRRemoveState::Clone(res, cnode)
}
BranchShrinkState::Shrink(dnode) => {
debug_assert!(!last_seen.contains(&dnode));
last_seen.push(dnode);
CRRemoveState::CloneShrink(res, cnode)
}
}
}
}
})
.unwrap_or_else(|| {
let nmref = branch_ref!(node, K, V);
let anode_idx = nmref.locate_node(k);
let anode = nmref.get_idx_unchecked(anode_idx);
match clone_and_remove(anode, txid, k, last_seen, first_seen) {
CRRemoveState::NoClone(res) => CRRemoveState::NoClone(res),
CRRemoveState::Clone(res, lnode) => {
nmref.replace_by_idx(anode_idx, lnode);
CRRemoveState::NoClone(res)
}
CRRemoveState::Shrink(res) => {
let right_idx =
nmref.clone_sibling_idx(txid, anode_idx, last_seen, first_seen);
match nmref.shrink_decision(right_idx) {
BranchShrinkState::Balanced => {
CRRemoveState::NoClone(res)
}
BranchShrinkState::Merge(dnode) => {
debug_assert!(!last_seen.contains(&dnode));
last_seen.push(dnode);
CRRemoveState::NoClone(res)
}
BranchShrinkState::Shrink(dnode) => {
debug_assert!(!last_seen.contains(&dnode));
last_seen.push(dnode);
CRRemoveState::Shrink(res)
}
}
}
CRRemoveState::CloneShrink(res, nnode) => {
nmref.replace_by_idx(anode_idx, nnode);
let right_idx =
nmref.clone_sibling_idx(txid, anode_idx, last_seen, first_seen);
match nmref.shrink_decision(right_idx) {
BranchShrinkState::Balanced => {
CRRemoveState::NoClone(res)
}
BranchShrinkState::Merge(dnode) => {
debug_assert!(!last_seen.contains(&dnode));
last_seen.push(dnode);
CRRemoveState::NoClone(res)
}
BranchShrinkState::Shrink(dnode) => {
debug_assert!(!last_seen.contains(&dnode));
last_seen.push(dnode);
CRRemoveState::Shrink(res)
}
}
}
}
}) }
}
fn path_get_mut_ref<'a, K, V>(node: *mut Node<K, V>, k: &K) -> Option<&'a mut V>
where
K: Clone + Ord + Debug + 'a,
V: Clone,
{
if unsafe { &*node }.meta.is_leaf() {
leaf_ref!(node, K, V).get_mut_ref(k)
} else {
let nmref = branch_ref!(node, K, V);
let anode_idx = nmref.locate_node(k);
let anode = nmref.get_idx_unchecked(anode_idx);
let r: Option<*mut V> = path_get_mut_ref(anode, k).map(|v| v as *mut V);
r.map(|v| unsafe { &mut *v as &mut V })
}
}
#[cfg(test)]
mod tests {
use super::super::node::*;
use super::super::states::*;
use super::SuperBlock;
use super::{CursorRead, CursorReadOps};
use crate::internals::lincowcell::LinCowCellCapable;
use rand::seq::SliceRandom;
use std::mem;
fn create_leaf_node(v: usize) -> *mut Node<usize, usize> {
let node = Node::new_leaf(1);
{
let nmut: &mut Leaf<_, _> = leaf_ref!(node, usize, usize);
nmut.insert_or_update(v, v);
}
node as *mut Node<usize, usize>
}
fn create_leaf_node_full(vbase: usize) -> *mut Node<usize, usize> {
assert!(vbase.is_multiple_of(10));
let node = Node::new_leaf(1);
{
let nmut = leaf_ref!(node, usize, usize);
for idx in 0..L_CAPACITY {
let v = vbase + idx;
nmut.insert_or_update(v, v);
}
}
node as *mut Node<usize, usize>
}
fn create_branch_node_full(vbase: usize) -> *mut Node<usize, usize> {
let l1 = create_leaf_node(vbase);
let l2 = create_leaf_node(vbase + 10);
let lbranch = Node::new_branch(1, l1, l2);
let bref = branch_ref!(lbranch, usize, usize);
for i in 2..BV_CAPACITY {
let l = create_leaf_node(vbase + (10 * i));
let r = bref.add_node(l);
match r {
BranchInsertState::Ok => {}
_ => debug_assert!(false),
}
}
assert!(bref.count() == L_CAPACITY);
lbranch as *mut Node<usize, usize>
}
#[test]
fn test_bptree2_cursor_insert_leaf() {
let node = create_leaf_node(0);
let sb = SuperBlock::new_test(1, node);
let mut wcurs = sb.create_writer();
eprintln!("{:?}", wcurs);
let prev_txid = wcurs.root_txid();
eprintln!("prev_txid {:?}", prev_txid);
let r = wcurs.insert(1, 1);
assert!(r.is_none());
eprintln!("get_root_ref {:?}", wcurs.get_root_ref().meta.get_txid());
let r1_txid = wcurs.root_txid();
assert!(r1_txid == prev_txid + 1);
let r = wcurs.insert(2, 2);
assert!(r.is_none());
let r2_txid = wcurs.root_txid();
assert!(r2_txid == r1_txid);
assert!(wcurs.verify());
}
#[test]
fn test_bptree2_cursor_insert_split_1() {
let node = create_leaf_node_full(10);
let sb = SuperBlock::new_test(1, node);
let mut wcurs = sb.create_writer();
let prev_txid = wcurs.root_txid();
let r = wcurs.insert(1, 1);
assert!(r.is_none());
let r1_txid = wcurs.root_txid();
assert!(r1_txid == prev_txid + 1);
assert!(wcurs.verify());
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_insert_split_2() {
let node = create_leaf_node(0);
let sb = SuperBlock::new_test(1, node);
let mut wcurs = sb.create_writer();
for v in 1..(L_CAPACITY + 1) {
let r = wcurs.insert(v, v);
assert!(r.is_none());
assert!(wcurs.verify());
}
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_insert_split_3() {
let lnode = create_leaf_node_full(10);
let rnode = create_leaf_node_full(20);
let root = Node::new_branch(0, lnode, rnode);
let sb = SuperBlock::new_test(1, root as *mut Node<usize, usize>);
let mut wcurs = sb.create_writer();
assert!(wcurs.verify());
let r = wcurs.insert(19, 19);
assert!(r.is_none());
assert!(wcurs.verify());
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_insert_split_4() {
let lnode = create_leaf_node_full(10);
let rnode = create_leaf_node_full(20);
let root = Node::new_branch(0, lnode, rnode);
let sb = SuperBlock::new_test(1, root as *mut Node<usize, usize>);
let mut wcurs = sb.create_writer();
assert!(wcurs.verify());
let r = wcurs.insert(29, 29);
assert!(r.is_none());
assert!(wcurs.verify());
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_insert_split_5() {
let lnode = create_leaf_node(10);
let rnode = create_leaf_node(20);
let root = Node::new_branch(0, lnode, rnode);
let sb = SuperBlock::new_test(1, root as *mut Node<usize, usize>);
let mut wcurs = sb.create_writer();
assert!(wcurs.verify());
for idx in 0..(L_CAPACITY) {
let v = 10 + 1 + idx;
let r = wcurs.insert(v, v);
assert!(r.is_none());
assert!(wcurs.verify());
}
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_insert_split_6() {
let lnode = create_leaf_node(10);
let rnode = create_leaf_node(20);
let root = Node::new_branch(0, lnode, rnode);
let sb = SuperBlock::new_test(1, root as *mut Node<usize, usize>);
let mut wcurs = sb.create_writer();
assert!(wcurs.verify());
for idx in 0..(L_CAPACITY) {
let v = 20 + 1 + idx;
let r = wcurs.insert(v, v);
assert!(r.is_none());
assert!(wcurs.verify());
}
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_insert_split_7() {
let lnode = create_leaf_node(10);
let rnode = create_leaf_node(20);
let root = Node::new_branch(0, lnode, rnode);
let sb = SuperBlock::new_test(1, root as *mut Node<usize, usize>);
let mut wcurs = sb.create_writer();
assert!(wcurs.verify());
let r = wcurs.insert(11, 11);
assert!(r.is_none());
assert!(wcurs.verify());
let r = wcurs.insert(21, 21);
assert!(r.is_none());
assert!(wcurs.verify());
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_insert_split_8() {
let lnode = create_leaf_node_full(10);
let rnode = create_leaf_node_full(20);
let root = Node::new_branch(0, lnode, rnode);
let sb = SuperBlock::new_test(1, root as *mut Node<usize, usize>);
let mut wcurs = sb.create_writer();
assert!(wcurs.verify());
let r = wcurs.insert(19, 19);
assert!(r.is_none());
assert!(wcurs.verify());
let r = wcurs.insert(29, 29);
assert!(r.is_none());
assert!(wcurs.verify());
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_insert_stress_1() {
let node = create_leaf_node(0);
let sb = SuperBlock::new_test(1, node);
let mut wcurs = sb.create_writer();
for v in 1..(L_CAPACITY << 4) {
let r = wcurs.insert(v, v);
assert!(r.is_none());
assert!(wcurs.verify());
}
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_insert_stress_2() {
let node = create_leaf_node(0);
let sb = SuperBlock::new_test(1, node);
let mut wcurs = sb.create_writer();
for v in (1..(L_CAPACITY << 4)).rev() {
let r = wcurs.insert(v, v);
assert!(r.is_none());
assert!(wcurs.verify());
}
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_insert_stress_3() {
let mut rng = rand::rng();
let mut ins: Vec<usize> = (1..(L_CAPACITY << 4)).collect();
ins.shuffle(&mut rng);
let node = create_leaf_node(0);
let sb = SuperBlock::new_test(1, node);
let mut wcurs = sb.create_writer();
for v in ins.into_iter() {
let r = wcurs.insert(v, v);
assert!(r.is_none());
assert!(wcurs.verify());
}
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_insert_stress_4() {
let mut sb = unsafe { SuperBlock::new() };
let mut rdr = sb.create_reader();
for v in 1..(L_CAPACITY << 4) {
let mut wcurs = sb.create_writer();
let r = wcurs.insert(v, v);
assert!(r.is_none());
assert!(wcurs.verify());
rdr = sb.pre_commit(wcurs, &rdr);
}
mem::drop(rdr);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_insert_stress_5() {
let mut sb = unsafe { SuperBlock::new() };
let mut rdr = sb.create_reader();
for v in (1..(L_CAPACITY << 4)).rev() {
let mut wcurs = sb.create_writer();
let r = wcurs.insert(v, v);
assert!(r.is_none());
assert!(wcurs.verify());
rdr = sb.pre_commit(wcurs, &rdr);
}
mem::drop(rdr);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_insert_stress_6() {
let mut rng = rand::rng();
let mut ins: Vec<usize> = (1..(L_CAPACITY << 4)).collect();
ins.shuffle(&mut rng);
let mut sb = unsafe { SuperBlock::new() };
let mut rdr = sb.create_reader();
for v in ins.into_iter() {
let mut wcurs = sb.create_writer();
let r = wcurs.insert(v, v);
assert!(r.is_none());
assert!(wcurs.verify());
rdr = sb.pre_commit(wcurs, &rdr);
}
mem::drop(rdr);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_search_1() {
let node = create_leaf_node(0);
let sb = SuperBlock::new_test(1, node);
let mut wcurs = sb.create_writer();
for v in 1..(L_CAPACITY << 4) {
let r = wcurs.insert(v, v);
assert!(r.is_none());
let r = wcurs.search(&v);
assert!(r.unwrap() == &v);
}
for v in 1..(L_CAPACITY << 4) {
let r = wcurs.search(&v);
assert!(r.unwrap() == &v);
}
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_length_1() {
let node = create_leaf_node(0);
let sb = SuperBlock::new_test(1, node);
let mut wcurs = sb.create_writer();
for v in 1..(L_CAPACITY << 4) {
let r = wcurs.insert(v, v);
assert!(r.is_none());
}
assert!(wcurs.len() == L_CAPACITY << 4);
}
#[test]
fn test_bptree2_cursor_remove_01_p0() {
let lnode = create_leaf_node_full(0);
let sb = SuperBlock::new_test(1, lnode);
let mut wcurs = sb.create_writer();
for v in 0..L_CAPACITY {
let x = wcurs.remove(&v);
assert!(x == Some(v));
}
for v in 0..L_CAPACITY {
let x = wcurs.remove(&v);
assert!(x.is_none());
}
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_remove_01_p1() {
let node = create_leaf_node(0);
let sb = SuperBlock::new_test(1, node);
let mut wcurs = sb.create_writer();
let _ = wcurs.remove(&0);
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_remove_02() {
let lnode = create_leaf_node(10);
let rnode = create_leaf_node(20);
let znode = create_leaf_node(0);
let root = Node::new_branch(0, znode, lnode);
unsafe { (*root).add_node(rnode) };
let sb = SuperBlock::new_test(1, root as *mut Node<usize, usize>);
let mut wcurs = sb.create_writer();
assert!(wcurs.verify());
wcurs.remove(&20);
assert!(wcurs.verify());
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_remove_03() {
let lnode = create_leaf_node(10);
let rnode = create_leaf_node(20);
let znode = create_leaf_node(30);
let root = Node::new_branch(0, lnode, rnode);
unsafe { (*root).add_node(znode) };
let sb = SuperBlock::new_test(1, root as *mut Node<usize, usize>);
let mut wcurs = sb.create_writer();
assert!(wcurs.verify());
wcurs.remove(&10);
assert!(wcurs.verify());
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_remove_04p0() {
let lnode = create_leaf_node(10);
let rnode = create_leaf_node(20);
let znode = create_leaf_node(0);
let root = Node::new_branch(0, znode, lnode);
unsafe { (*root).add_node(rnode) };
let sb = SuperBlock::new_test(1, root as *mut Node<usize, usize>);
let mut wcurs = sb.create_writer();
assert!(wcurs.verify());
wcurs.path_clone(&10);
assert!(wcurs.verify());
wcurs.remove(&20);
assert!(wcurs.verify());
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_remove_04p1() {
let lnode = create_leaf_node(10);
let rnode = create_leaf_node(20);
let znode = create_leaf_node(0);
let root = Node::new_branch(0, znode, lnode);
unsafe { (*root).add_node(rnode) };
let sb = SuperBlock::new_test(1, root as *mut Node<usize, usize>);
let mut wcurs = sb.create_writer();
assert!(wcurs.verify());
wcurs.path_clone(&20);
assert!(wcurs.verify());
wcurs.remove(&20);
assert!(wcurs.verify());
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_remove_05() {
let lnode = create_leaf_node(10);
let rnode = create_leaf_node(20);
let znode = create_leaf_node(30);
let root = Node::new_branch(0, lnode, rnode);
unsafe { (*root).add_node(znode) };
let sb = SuperBlock::new_test(1, root as *mut Node<usize, usize>);
let mut wcurs = sb.create_writer();
assert!(wcurs.verify());
wcurs.path_clone(&20);
wcurs.remove(&10);
assert!(wcurs.verify());
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_remove_06() {
let l1 = create_leaf_node(0);
let l2 = create_leaf_node(10);
let r1 = create_leaf_node(20);
let r2 = create_leaf_node(30);
let lbranch = Node::new_branch(0, l1, l2);
let rbranch = Node::new_branch(0, r1, r2);
let root: *mut Branch<usize, usize> =
Node::new_branch(0, lbranch as *mut _, rbranch as *mut _);
let sb = SuperBlock::new_test(1, root as *mut Node<usize, usize>);
let mut wcurs = sb.create_writer();
assert!(wcurs.verify());
wcurs.remove(&30);
assert!(wcurs.verify());
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_remove_07() {
let l1 = create_leaf_node(0);
let l2 = create_leaf_node(10);
let r1 = create_leaf_node(20);
let r2 = create_leaf_node(30);
let lbranch = Node::new_branch(0, l1, l2);
let rbranch = Node::new_branch(0, r1, r2);
let root: *mut Branch<usize, usize> =
Node::new_branch(0, lbranch as *mut _, rbranch as *mut _);
let sb = SuperBlock::new_test(1, root as *mut Node<usize, usize>);
let mut wcurs = sb.create_writer();
assert!(wcurs.verify());
wcurs.remove(&10);
assert!(wcurs.verify());
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_remove_08() {
let lbranch = create_branch_node_full(0);
let r1 = create_leaf_node(80);
let r2 = create_leaf_node(90);
let rbranch = Node::new_branch(0, r1, r2);
let root: *mut Branch<usize, usize> =
Node::new_branch(0, lbranch as *mut _, rbranch as *mut _);
let sb = SuperBlock::new_test(1, root as *mut Node<usize, usize>);
let mut wcurs = sb.create_writer();
assert!(wcurs.verify());
wcurs.remove(&80);
assert!(wcurs.verify());
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_remove_09() {
let l1 = create_leaf_node(0);
let l2 = create_leaf_node(10);
let lbranch = Node::new_branch(0, l1, l2);
let rbranch = create_branch_node_full(100);
let root: *mut Branch<usize, usize> =
Node::new_branch(0, lbranch as *mut _, rbranch as *mut _);
let sb = SuperBlock::new_test(1, root as *mut Node<usize, usize>);
let mut wcurs = sb.create_writer();
assert!(wcurs.verify());
wcurs.remove(&10);
assert!(wcurs.verify());
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_remove_10() {
let l1 = create_leaf_node(0);
let l2 = create_leaf_node(10);
let r1 = create_leaf_node(20);
let r2 = create_leaf_node(30);
let lbranch = Node::new_branch(0, l1, l2);
let rbranch = Node::new_branch(0, r1, r2);
let root: *mut Branch<usize, usize> =
Node::new_branch(0, lbranch as *mut _, rbranch as *mut _);
let sb = SuperBlock::new_test(1, root as *mut Node<usize, usize>);
let mut wcurs = sb.create_writer();
assert!(wcurs.verify());
wcurs.path_clone(&0);
wcurs.path_clone(&10);
wcurs.remove(&30);
assert!(wcurs.verify());
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_remove_11() {
let l1 = create_leaf_node(0);
let l2 = create_leaf_node(10);
let r1 = create_leaf_node(20);
let r2 = create_leaf_node(30);
let lbranch = Node::new_branch(0, l1, l2);
let rbranch = Node::new_branch(0, r1, r2);
let root: *mut Branch<usize, usize> =
Node::new_branch(0, lbranch as *mut _, rbranch as *mut _);
let sb = SuperBlock::new_test(1, root as *mut Node<usize, usize>);
let mut wcurs = sb.create_writer();
assert!(wcurs.verify());
wcurs.path_clone(&20);
wcurs.path_clone(&30);
wcurs.remove(&0);
assert!(wcurs.verify());
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_remove_12() {
let lbranch = create_branch_node_full(0);
let r1 = create_leaf_node(80);
let r2 = create_leaf_node(90);
let rbranch = Node::new_branch(0, r1, r2);
let root = Node::new_branch(0, lbranch as *mut _, rbranch as *mut _);
let sb = SuperBlock::new_test(1, root as *mut Node<usize, usize>);
let mut wcurs = sb.create_writer();
assert!(wcurs.verify());
wcurs.path_clone(&0);
wcurs.path_clone(&10);
wcurs.path_clone(&20);
wcurs.remove(&90);
assert!(wcurs.verify());
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_remove_13() {
let l1 = create_leaf_node(0);
let l2 = create_leaf_node(10);
let lbranch = Node::new_branch(0, l1, l2);
let rbranch = create_branch_node_full(100);
let root = Node::new_branch(0, lbranch as *mut _, rbranch as *mut _);
let sb = SuperBlock::new_test(1, root as *mut Node<usize, usize>);
let mut wcurs = sb.create_writer();
assert!(wcurs.verify());
for i in 0..BV_CAPACITY {
let k = 100 + (10 * i);
wcurs.path_clone(&k);
}
assert!(wcurs.verify());
wcurs.remove(&10);
assert!(wcurs.verify());
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_remove_14() {
let lnode = create_leaf_node_full(10);
let rnode = create_leaf_node(20);
let root = Node::new_branch(0, lnode, rnode);
let sb = SuperBlock::new_test(1, root as *mut Node<usize, usize>);
let mut wcurs = sb.create_writer();
assert!(wcurs.verify());
wcurs.remove(&20);
assert!(wcurs.verify());
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_remove_15() {
let lnode = create_leaf_node(10);
let rnode = create_leaf_node_full(20);
let root = Node::new_branch(0, lnode, rnode);
let sb = SuperBlock::new_test(1, root as *mut Node<usize, usize>);
let mut wcurs = sb.create_writer();
assert!(wcurs.verify());
wcurs.remove(&10);
assert!(wcurs.verify());
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
fn tree_create_rand() -> (SuperBlock<usize, usize>, CursorRead<usize, usize>) {
let mut rng = rand::rng();
let mut ins: Vec<usize> = (1..(L_CAPACITY << 4)).collect();
ins.shuffle(&mut rng);
let mut sb = unsafe { SuperBlock::new() };
let rdr = sb.create_reader();
let mut wcurs = sb.create_writer();
for v in ins.into_iter() {
let r = wcurs.insert(v, v);
assert!(r.is_none());
assert!(wcurs.verify());
}
let rdr = sb.pre_commit(wcurs, &rdr);
(sb, rdr)
}
#[test]
fn test_bptree2_cursor_remove_stress_1() {
let (mut sb, rdr) = tree_create_rand();
let mut wcurs = sb.create_writer();
for v in 1..(L_CAPACITY << 4) {
let r = wcurs.remove(&v);
assert!(r == Some(v));
assert!(wcurs.verify());
}
let rdr2 = sb.pre_commit(wcurs, &rdr);
std::mem::drop(rdr2);
std::mem::drop(rdr);
std::mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_remove_stress_2() {
let (mut sb, rdr) = tree_create_rand();
let mut wcurs = sb.create_writer();
for v in (1..(L_CAPACITY << 4)).rev() {
let r = wcurs.remove(&v);
assert!(r == Some(v));
assert!(wcurs.verify());
}
let rdr2 = sb.pre_commit(wcurs, &rdr);
std::mem::drop(rdr2);
std::mem::drop(rdr);
std::mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_remove_stress_3() {
let mut rng = rand::rng();
let mut ins: Vec<usize> = (1..(L_CAPACITY << 4)).collect();
ins.shuffle(&mut rng);
let (mut sb, rdr) = tree_create_rand();
let mut wcurs = sb.create_writer();
for v in ins.into_iter() {
let r = wcurs.remove(&v);
assert!(r == Some(v));
assert!(wcurs.verify());
}
let rdr2 = sb.pre_commit(wcurs, &rdr);
std::mem::drop(rdr2);
std::mem::drop(rdr);
std::mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_remove_stress_4() {
let (mut sb, mut rdr) = tree_create_rand();
for v in 1..(L_CAPACITY << 4) {
let mut wcurs = sb.create_writer();
let r = wcurs.remove(&v);
assert!(r == Some(v));
assert!(wcurs.verify());
rdr = sb.pre_commit(wcurs, &rdr);
}
std::mem::drop(rdr);
std::mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_remove_stress_5() {
let (mut sb, mut rdr) = tree_create_rand();
for v in (1..(L_CAPACITY << 4)).rev() {
let mut wcurs = sb.create_writer();
let r = wcurs.remove(&v);
assert!(r == Some(v));
assert!(wcurs.verify());
rdr = sb.pre_commit(wcurs, &rdr);
}
std::mem::drop(rdr);
std::mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_remove_stress_6() {
let mut rng = rand::rng();
let mut ins: Vec<usize> = (1..(L_CAPACITY << 4)).collect();
ins.shuffle(&mut rng);
let (mut sb, mut rdr) = tree_create_rand();
for v in ins.into_iter() {
let mut wcurs = sb.create_writer();
let r = wcurs.remove(&v);
assert!(r == Some(v));
assert!(wcurs.verify());
rdr = sb.pre_commit(wcurs, &rdr);
}
std::mem::drop(rdr);
std::mem::drop(sb);
assert_released();
}
#[cfg(not(feature = "skinny"))]
fn create_split_off_leaf(base: usize) -> *mut Node<usize, usize> {
let l = Node::new_leaf(0);
let lref = leaf_ref!(l, usize, usize);
lref.insert_or_update(base + 1, base + 1);
lref.insert_or_update(base + 2, base + 2);
l as *mut _
}
#[cfg(not(feature = "skinny"))]
fn create_split_off_branch(base: usize) -> *mut Node<usize, usize> {
let l1 = create_split_off_leaf(base);
let l2 = create_split_off_leaf(base + 10);
let l3 = create_split_off_leaf(base + 20);
let l4 = create_split_off_leaf(base + 30);
let branch = Node::new_branch(0, l1, l2);
let nref = branch_ref!(branch, usize, usize);
nref.add_node(l3);
nref.add_node(l4);
branch as *mut _
}
#[cfg(not(feature = "skinny"))]
fn create_split_off_tree() -> *mut Node<usize, usize> {
let b1 = create_split_off_branch(0);
let b2 = create_split_off_branch(100);
let b3 = create_split_off_branch(200);
let b4 = create_split_off_branch(300);
let root = Node::new_branch(0, b1, b2);
let nref = branch_ref!(root, usize, usize);
nref.add_node(b3);
nref.add_node(b4);
root as *mut _
}
#[test]
fn test_bptree2_cursor_split_off_lt_01() {
let node = create_leaf_node(0);
let sb = SuperBlock::new_test(1, node);
let mut wcurs = sb.create_writer();
wcurs.split_off_lt(&5);
assert!(wcurs.verify());
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_split_off_lt_02() {
let node = create_leaf_node_full(10);
let sb = SuperBlock::new_test(1, node);
let mut wcurs = sb.create_writer();
wcurs.split_off_lt(&11);
assert!(wcurs.verify());
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[test]
fn test_bptree2_cursor_split_off_lt_03() {
let node = create_leaf_node_full(10);
let sb = SuperBlock::new_test(1, node);
let mut wcurs = sb.create_writer();
wcurs.path_clone(&11);
wcurs.split_off_lt(&11);
assert!(wcurs.verify());
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[cfg(not(feature = "skinny"))]
fn run_split_off_test_clone(v: usize, _exp: usize) {
let tree = create_split_off_tree();
let sb = SuperBlock::new_test(1, tree);
let mut wcurs = sb.create_writer();
let outer: [usize; 4] = [0, 100, 200, 300];
let inner: [usize; 4] = [0, 10, 20, 30];
for i in outer.iter() {
for j in inner.iter() {
wcurs.path_clone(&(i + j + 1));
}
}
wcurs.split_off_lt(&v);
assert!(wcurs.verify());
if v > 0 {
assert!(!wcurs.contains_key(&(v - 1)));
}
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[cfg(not(feature = "skinny"))]
fn run_split_off_test(v: usize, _exp: usize) {
let tree = create_split_off_tree();
let sb = SuperBlock::new_test(1, tree);
let mut wcurs = sb.create_writer();
wcurs.split_off_lt(&v);
assert!(wcurs.verify());
if v > 0 {
assert!(!wcurs.contains_key(&(v - 1)));
}
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
#[cfg(not(feature = "skinny"))]
#[test]
fn test_bptree2_cursor_split_off_lt_clone_stress() {
let outer: [usize; 4] = [0, 100, 200, 300];
let inner: [usize; 4] = [0, 10, 20, 30];
for i in outer.iter() {
for j in inner.iter() {
run_split_off_test_clone(i + j, 32);
run_split_off_test_clone(i + j + 1, 32);
run_split_off_test_clone(i + j + 2, 32);
run_split_off_test_clone(i + j + 3, 32);
}
}
}
#[cfg(not(feature = "skinny"))]
#[test]
fn test_bptree2_cursor_split_off_lt_stress() {
let outer: [usize; 4] = [0, 100, 200, 300];
let inner: [usize; 4] = [0, 10, 20, 30];
for i in outer.iter() {
for j in inner.iter() {
run_split_off_test(i + j, 32);
run_split_off_test(i + j + 1, 32);
run_split_off_test(i + j + 2, 32);
run_split_off_test(i + j + 3, 32);
}
}
}
#[test]
#[cfg_attr(miri, ignore)]
fn test_bptree2_cursor_split_off_lt_random_stress() {
let data: Vec<isize> = (0..1024).collect();
for v in data.iter() {
let node: *mut Leaf<isize, isize> = Node::new_leaf(0) as *mut _;
let sb = SuperBlock::new_test(1, node as *mut Node<isize, isize>);
let mut wcurs = sb.create_writer();
wcurs.extend(data.iter().map(|v| (*v, *v)));
if v > &0 {
assert!(wcurs.contains_key(&(v - 1)));
}
wcurs.split_off_lt(v);
assert!(!wcurs.contains_key(&(v - 1)));
if v < &1024 {
assert!(wcurs.contains_key(v));
}
assert!(wcurs.verify());
let contents: Vec<_> = wcurs.k_iter().collect();
assert!(contents[0] == v);
assert!(contents.len() as isize == (1024 - v));
}
}
#[test]
fn test_bptree_cursor_double_extend() {
let node: *mut Leaf<isize, isize> = Node::new_leaf(0) as *mut _;
let sb = SuperBlock::new_test(1, node as *mut Node<isize, isize>);
let mut wcurs = sb.create_writer();
wcurs.extend([(0, 0), (1, 1), (2, 2), (3, 3)]);
assert!(wcurs.len() == 4);
assert!(wcurs.verify());
wcurs.extend([(2, 2), (3, 3), (4, 4), (5, 5)]);
assert!(wcurs.len() == 6);
assert!(wcurs.verify());
mem::drop(wcurs);
mem::drop(sb);
assert_released();
}
}