use crate::{
error::{GenericError, PERes, PIRes, ReadError},
id::{IndexId, SegmentId},
index::{
config::{IndexTypeInternal, ValueMode},
serialization::{deserialize, reuse_deserialize},
tree::nodes::{Node, TreeNode, TreeNodeRef},
},
persy::PersyImpl,
snapshots::SnapshotRef,
};
pub(crate) struct IndexLimits {
bottom: usize,
top: usize,
}
impl IndexLimits {
pub(crate) fn new(bottom: usize, top: usize) -> Self {
Self { bottom, top }
}
pub(crate) fn bottom(&self) -> usize {
self.bottom
}
pub(crate) fn top(&self) -> usize {
self.top
}
}
pub trait IndexKeeper<K, V> {
fn load(&self, node: &TreeNodeRef) -> PERes<TreeNode<K, V>> {
Ok(self.failable_load(node)?.unwrap())
}
fn failable_load(&self, node: &TreeNodeRef) -> PERes<Option<TreeNode<K, V>>>;
fn load_with(&self, node: &TreeNodeRef, reuse: Option<Node<K>>) -> PERes<TreeNode<K, V>>;
fn get_root(&self) -> PERes<Option<TreeNodeRef>>;
fn value_mode(&self) -> ValueMode;
fn index_name(&self) -> &String;
}
pub(crate) trait IndexModify<K, V>: IndexKeeper<K, V> {
fn load_from_node<R, C>(&self, node_ref: &TreeNodeRef, loader: C) -> PIRes<Option<R>>
where
C: FnOnce(&TreeNode<K, V>, u16) -> R;
fn lock(&mut self, node: &TreeNodeRef, version: u16) -> PIRes<bool>;
fn is_locked(&mut self, node: &TreeNodeRef) -> bool;
fn unlock(&mut self, node: &TreeNodeRef) -> bool;
fn get_root_refresh(&mut self) -> PIRes<Option<TreeNodeRef>>;
fn lock_config(&mut self) -> PIRes<bool>;
fn insert(&mut self, node: TreeNode<K, V>) -> PIRes<TreeNodeRef>;
fn update_with<R, C>(&mut self, node_ref: &TreeNodeRef, updater: C) -> PIRes<R>
where
C: FnOnce(&mut TreeNode<K, V>) -> (bool, R);
fn delete(&mut self, node: &TreeNodeRef, version: u16) -> PIRes<()>;
fn delete_to_own(&mut self, node: &TreeNodeRef) -> PIRes<TreeNode<K, V>>;
fn set_root(&mut self, root: Option<TreeNodeRef>) -> PIRes<()>;
fn limits(&self) -> &IndexLimits;
}
pub struct IndexSegmentKeeper<'a> {
name: String,
segment: SegmentId,
root: Option<TreeNodeRef>,
store: &'a PersyImpl,
snapshot: SnapshotRef,
value_mode: ValueMode,
}
impl<'a> IndexSegmentKeeper<'a> {
pub fn new(
name: &str,
index_id: &IndexId,
root: Option<TreeNodeRef>,
store: &'a PersyImpl,
snapshot: &SnapshotRef,
value_mode: ValueMode,
) -> IndexSegmentKeeper<'a> {
IndexSegmentKeeper {
name: name.to_string(),
segment: index_id.get_data_id(),
root,
store,
snapshot: snapshot.clone(),
value_mode,
}
}
}
impl<K: IndexTypeInternal, V: IndexTypeInternal> IndexKeeper<K, V> for IndexSegmentKeeper<'_> {
fn failable_load(&self, node: &TreeNodeRef) -> PERes<Option<TreeNode<K, V>>> {
self.store
.read_snap_fn(self.segment, node, &self.snapshot, deserialize)
.map_err(map_read_err)
}
fn load_with(&self, node: &TreeNodeRef, reuse: Option<Node<K>>) -> PERes<TreeNode<K, V>> {
let rec = self
.store
.read_snap_fn(self.segment, node, &self.snapshot, |e| reuse_deserialize(e, reuse))
.map_err(map_read_err)?
.unwrap();
Ok(rec)
}
fn get_root(&self) -> PERes<Option<TreeNodeRef>> {
Ok(self.root)
}
fn value_mode(&self) -> ValueMode {
self.value_mode.clone()
}
fn index_name(&self) -> &String {
&self.name
}
}
pub(crate) fn map_read_err(r: ReadError) -> GenericError {
match r {
ReadError::SegmentNotFound => panic!("The segment should be already checked"),
ReadError::InvalidPersyId(_) => panic!("The Internal id should be everytime valid"),
ReadError::Generic(g) => g,
}
}