diff --git a/Cargo.toml b/Cargo.toml index 6abb5b9..35156bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,10 @@ rand = "0.8.5" criterion = "0.5.1" divan = "0.1.14" +[features] +default = ["vec_store"] +vec_store = [] + [[bench]] name = "vart_bench" path = "benches/vart_bench.rs" diff --git a/src/node.rs b/src/node.rs index ac6aed9..a049438 100644 --- a/src/node.rs +++ b/src/node.rs @@ -1,7 +1,14 @@ use std::slice::from_ref; use std::sync::Arc; -use crate::{art::QueryType, version::BTree, KeyTrait}; +use crate::{ + art::QueryType, + version::{VecStore, VersionStore}, + KeyTrait, +}; + +#[cfg(not(feature = "vec_store"))] +use crate::version::BTreeStore; /* Immutable nodes @@ -22,7 +29,10 @@ pub(crate) trait NodeTrait { pub(crate) struct TwigNode { pub(crate) prefix: K, pub(crate) key: K, - pub(crate) values: BTree, + #[cfg(feature = "vec_store")] + pub(crate) values: VecStore, + #[cfg(not(feature = "vec_store"))] + pub(crate) values: BTreeStore, pub(crate) version: u64, // Version for the twig node } @@ -52,28 +62,20 @@ impl TwigNode { TwigNode { prefix, key, - values: BTree::new(), + values: VersionStore::new(), version: 0, } } pub(crate) fn version(&self) -> u64 { - self.values - .iter() - .map(|value| value.version) - .max() - .unwrap_or(self.version) + self.values.get_max_version().unwrap_or(self.version) } pub(crate) fn insert(&self, value: V, version: u64, ts: u64) -> TwigNode { let mut new_values = self.values.clone(); new_values.insert(value, version, ts); - let new_version = new_values - .iter() - .map(|value| value.version) - .max() - .unwrap_or(self.version); + let new_version = new_values.get_max_version().unwrap_or(self.version); TwigNode { prefix: self.prefix.clone(), diff --git a/src/version.rs b/src/version.rs index 772c5be..e121f76 100644 --- a/src/version.rs +++ b/src/version.rs @@ -15,6 +15,7 @@ pub(crate) struct BNode { is_leaf: bool, } +#[allow(unused)] impl BNode { fn new(is_leaf: bool) -> Self { BNode { @@ -34,6 +35,7 @@ impl BNode { } } +#[allow(unused)] impl BTree { pub fn new() -> Self { BTree { root: None } @@ -241,6 +243,105 @@ impl<'a, V: Clone> DoubleEndedIterator for BNodeIterator<'a, V> { } } +pub(crate) trait VersionStore { + fn new() -> Self; + fn insert(&mut self, value: V, version: u64, ts: u64); + fn clear(&mut self); + fn iter(&self) -> Box>> + '_>; + fn get_max_version(&self) -> Option; +} + +// Implement for Vec +#[cfg(feature = "vec_store")] +#[derive(Clone)] +pub(crate) struct VecStore { + values: Vec>>, +} + +#[cfg(feature = "vec_store")] +impl VersionStore for VecStore { + fn new() -> Self { + Self { values: Vec::new() } + } + + fn insert(&mut self, value: V, version: u64, ts: u64) { + let new_leaf_value = LeafValue::new(value, version, ts); + match self + .values + .binary_search_by(|v| v.version.cmp(&new_leaf_value.version)) + { + Ok(index) => { + if self.values[index].ts == ts { + self.values[index] = Arc::new(new_leaf_value); + } else { + let mut insert_position = index; + if self.values[index].ts < ts { + insert_position += self.values[index..] + .iter() + .take_while(|v| v.ts <= ts) + .count(); + } else { + insert_position -= self.values[..index] + .iter() + .rev() + .take_while(|v| v.ts >= ts) + .count(); + } + self.values + .insert(insert_position, Arc::new(new_leaf_value)); + } + } + Err(index) => { + self.values.insert(index, Arc::new(new_leaf_value)); + } + } + } + + fn clear(&mut self) { + self.values.clear(); + } + + fn iter(&self) -> Box>> + '_> { + Box::new(self.values.iter()) + } + + fn get_max_version(&self) -> Option { + self.values.iter().map(|value| value.version).max() + } +} + +// Implement for BTree +#[cfg(not(feature = "vec_store"))] +#[derive(Clone)] +pub(crate) struct BTreeStore { + values: BTree, +} + +#[cfg(not(feature = "vec_store"))] +impl VersionStore for BTreeStore { + fn new() -> Self { + Self { + values: BTree::new(), + } + } + + fn insert(&mut self, value: V, version: u64, ts: u64) { + self.values.insert(value, version, ts); + } + + fn clear(&mut self) { + self.values.clear(); + } + + fn iter(&self) -> Box>> + '_> { + Box::new(self.values.iter()) + } + + fn get_max_version(&self) -> Option { + self.values.iter().map(|value| value.version).max() + } +} + #[cfg(test)] mod tests { use super::*;