mod cache;
mod persistence;
mod storage;
mod traversal;
use std::{
any::Any,
collections::{HashMap, HashSet},
path::Path,
sync::RwLock,
};
use ed25519_dalek::SigningKey;
use serde::{Deserialize, Serialize};
use crate::{
Result,
backend::{BackendImpl, VerificationStatus, errors::BackendError},
entry::{Entry, ID},
};
pub(crate) type TreeHeightsCache = HashMap<ID, (usize, HashMap<String, usize>)>;
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub(crate) struct TreeTipsCache {
pub(crate) tree_tips: HashSet<ID>,
pub(crate) subtree_tips: HashMap<String, HashSet<ID>>,
}
#[derive(Debug)]
pub struct InMemory {
pub(crate) entries: RwLock<HashMap<ID, Entry>>,
pub(crate) verification_status: RwLock<HashMap<ID, VerificationStatus>>,
pub(crate) private_keys: RwLock<HashMap<String, SigningKey>>,
pub(crate) cache: RwLock<HashMap<String, String>>,
pub(crate) heights: RwLock<HashMap<ID, TreeHeightsCache>>,
pub(crate) tips: RwLock<HashMap<ID, TreeTipsCache>>,
}
impl InMemory {
pub fn new() -> Self {
Self {
entries: RwLock::new(HashMap::new()),
verification_status: RwLock::new(HashMap::new()),
private_keys: RwLock::new(HashMap::new()),
cache: RwLock::new(HashMap::new()),
heights: RwLock::new(HashMap::new()),
tips: RwLock::new(HashMap::new()),
}
}
pub fn all_ids(&self) -> Vec<ID> {
let entries = self.entries.read().unwrap();
entries.keys().cloned().collect()
}
pub fn save_to_file<P: AsRef<Path>>(&self, path: P) -> Result<()> {
persistence::save_to_file(self, path)
}
pub fn load_from_file<P: AsRef<Path>>(path: P) -> Result<Self> {
persistence::load_from_file(path)
}
pub fn calculate_heights(
&self,
tree: &ID,
subtree: Option<&str>,
) -> Result<std::collections::HashMap<ID, usize>> {
cache::calculate_heights(self, tree, subtree)
}
pub fn sort_entries_by_height(&self, tree: &ID, entries: &mut [Entry]) -> Result<()> {
cache::sort_entries_by_height(self, tree, entries)
}
pub fn sort_entries_by_subtree_height(
&self,
tree: &ID,
subtree: &str,
entries: &mut [Entry],
) -> Result<()> {
cache::sort_entries_by_subtree_height(self, tree, subtree, entries)
}
pub fn is_tip(&self, tree: &ID, entry_id: &ID) -> bool {
storage::is_tip(self, tree, entry_id)
}
}
impl Default for InMemory {
fn default() -> Self {
Self::new()
}
}
impl BackendImpl for InMemory {
fn get(&self, id: &ID) -> Result<Entry> {
let entries = self.entries.read().unwrap();
entries
.get(id)
.cloned()
.ok_or_else(|| BackendError::EntryNotFound { id: id.clone() }.into())
}
fn get_verification_status(&self, id: &ID) -> Result<VerificationStatus> {
let verification_status_map = self.verification_status.read().unwrap();
verification_status_map
.get(id)
.copied()
.ok_or_else(|| BackendError::VerificationStatusNotFound { id: id.clone() }.into())
}
fn put(&self, verification_status: VerificationStatus, entry: Entry) -> Result<()> {
storage::put(self, verification_status, entry)
}
fn update_verification_status(
&self,
id: &ID,
verification_status: VerificationStatus,
) -> Result<()> {
let mut verification_status_map = self.verification_status.write().unwrap();
if verification_status_map.contains_key(id) {
verification_status_map.insert(id.clone(), verification_status);
Ok(())
} else {
Err(BackendError::EntryNotFound { id: id.clone() }.into())
}
}
fn get_entries_by_verification_status(&self, status: VerificationStatus) -> Result<Vec<ID>> {
let verification_status_map = self.verification_status.read().unwrap();
let ids = verification_status_map
.iter()
.filter(|&(_, entry_status)| *entry_status == status)
.map(|(id, _)| id.clone())
.collect();
Ok(ids)
}
fn get_tips(&self, tree: &ID) -> Result<Vec<ID>> {
traversal::get_tips(self, tree)
}
fn get_store_tips(&self, tree: &ID, subtree: &str) -> Result<Vec<ID>> {
traversal::get_store_tips(self, tree, subtree)
}
fn get_store_tips_up_to_entries(
&self,
tree: &ID,
subtree: &str,
main_entries: &[ID],
) -> Result<Vec<ID>> {
traversal::get_store_tips_up_to_entries(self, tree, subtree, main_entries)
}
fn all_roots(&self) -> Result<Vec<ID>> {
let entries = self.entries.read().unwrap();
let roots: Vec<ID> = entries
.values()
.filter(|entry| entry.is_root())
.map(|entry| entry.id())
.collect();
Ok(roots)
}
fn find_lca(&self, tree: &ID, subtree: &str, entry_ids: &[ID]) -> Result<ID> {
traversal::find_lca(self, tree, subtree, entry_ids)
}
fn collect_root_to_target(
&self,
tree: &ID,
subtree: &str,
target_entry: &ID,
) -> Result<Vec<ID>> {
traversal::collect_root_to_target(self, tree, subtree, target_entry)
}
fn as_any(&self) -> &dyn Any {
self
}
fn get_tree(&self, tree: &ID) -> Result<Vec<Entry>> {
storage::get_tree(self, tree)
}
fn get_store(&self, tree: &ID, subtree: &str) -> Result<Vec<Entry>> {
storage::get_store(self, tree, subtree)
}
fn get_tree_from_tips(&self, tree: &ID, tips: &[ID]) -> Result<Vec<Entry>> {
storage::get_tree_from_tips(self, tree, tips)
}
fn get_store_from_tips(&self, tree: &ID, subtree: &str, tips: &[ID]) -> Result<Vec<Entry>> {
storage::get_store_from_tips(self, tree, subtree, tips)
}
fn store_private_key(&self, key_name: &str, private_key: SigningKey) -> Result<()> {
let mut private_keys = self.private_keys.write().unwrap();
private_keys.insert(key_name.to_string(), private_key);
Ok(())
}
fn get_private_key(&self, key_name: &str) -> Result<Option<SigningKey>> {
let private_keys = self.private_keys.read().unwrap();
Ok(private_keys.get(key_name).cloned())
}
fn list_private_keys(&self) -> Result<Vec<String>> {
let private_keys = self.private_keys.read().unwrap();
Ok(private_keys.keys().cloned().collect())
}
fn remove_private_key(&self, key_name: &str) -> Result<()> {
let mut private_keys = self.private_keys.write().unwrap();
private_keys.remove(key_name);
Ok(())
}
fn get_cached_crdt_state(&self, entry_id: &ID, subtree: &str) -> Result<Option<String>> {
cache::get_cached_crdt_state(self, entry_id, subtree)
}
fn cache_crdt_state(&self, entry_id: &ID, subtree: &str, state: String) -> Result<()> {
cache::cache_crdt_state(self, entry_id, subtree, state)
}
fn clear_crdt_cache(&self) -> Result<()> {
cache::clear_crdt_cache(self)
}
fn get_sorted_store_parents(
&self,
tree_id: &ID,
entry_id: &ID,
subtree: &str,
) -> Result<Vec<ID>> {
traversal::get_sorted_store_parents(self, tree_id, entry_id, subtree)
}
fn get_path_from_to(
&self,
tree_id: &ID,
subtree: &str,
from_id: &ID,
to_ids: &[ID],
) -> Result<Vec<ID>> {
traversal::get_path_from_to(self, tree_id, subtree, from_id, to_ids)
}
}