use std::{collections::BTreeMap, sync::RwLock};
use crate::LogFsError;
use super::Path;
pub type DataOffset = u64;
#[derive(Clone, Debug)]
pub struct KeyPointer {
pub sequence_id: u64,
pub file_offset: DataOffset,
pub size: u64,
pub chunk_size: Option<u32>,
}
pub struct State {
pub(crate) tree: BTreeMap<Path, KeyPointer>,
redundant_data_bytes_estimate: Option<u128>,
pub(crate) write_counter: u64,
}
pub type SharedTree = std::sync::Arc<RwLock<State>>;
impl State {
pub fn new() -> Self {
Self {
tree: BTreeMap::new(),
redundant_data_bytes_estimate: Some(0),
write_counter: 0,
}
}
pub(crate) fn set_tree(&mut self, tree: BTreeMap<Path, KeyPointer>) {
self.tree = tree;
self.redundant_data_bytes_estimate = None;
}
pub fn get_key(&self, path: &str) -> Option<&KeyPointer> {
self.tree.get(path)
}
pub fn paths_range<R>(&self, range: R) -> Vec<Path>
where
R: std::ops::RangeBounds<String>,
{
self.tree.range(range).map(|x| x.0).cloned().collect()
}
pub fn paths_offset(&self, offset: usize, max: usize) -> Vec<Path> {
self.tree
.iter()
.skip(offset)
.take(max)
.map(|x| x.0)
.cloned()
.collect()
}
pub fn paths_prefix(&self, prefix: &str) -> Vec<Path> {
self.tree
.range(prefix.to_string()..)
.take_while(|(path, _v)| path.starts_with(prefix))
.map(|x| x.0)
.cloned()
.collect()
}
pub fn add_key(&mut self, path: Path, pointer: KeyPointer) {
self.tree.insert(path, pointer);
self.write_counter += 1;
}
pub fn remove_key(&mut self, path: &str) -> Option<KeyPointer> {
if let Some(pointer) = self.tree.remove(path) {
let old = self.redundant_data_bytes_estimate.unwrap_or_default();
self.redundant_data_bytes_estimate = Some(old + pointer.size as u128);
self.write_counter += 1;
Some(pointer)
} else {
None
}
}
pub fn rename_key(&mut self, old_path: &Path, new_path: Path) -> Result<(), LogFsError> {
if let Some(old) = self.tree.remove(old_path) {
self.tree.insert(new_path, old);
self.write_counter += 1;
Ok(())
} else {
Err(LogFsError::NotFound {
path: old_path.clone(),
})
}
}
pub fn redundant_data_bytes_estimate(&self) -> Option<u128> {
self.redundant_data_bytes_estimate
}
}
impl Default for State {
fn default() -> Self {
Self::new()
}
}