use super::types::{StorageResult, StorageType};
use std::collections::HashMap;
use std::path::Path;
pub trait StorageTree: Send + Sync {
fn insert(&self, key: &[u8], value: &[u8]) -> StorageResult<()>;
fn get(&self, key: &[u8]) -> StorageResult<Option<Vec<u8>>>;
fn remove(&self, key: &[u8]) -> StorageResult<()>;
fn contains_key(&self, key: &[u8]) -> StorageResult<bool>;
fn clear(&self) -> StorageResult<()>;
fn is_empty(&self) -> StorageResult<bool>;
fn iter(
&self,
) -> StorageResult<Box<dyn Iterator<Item = StorageResult<(Vec<u8>, Vec<u8>)>> + '_>>;
fn scan_prefix(
&self,
prefix: &[u8],
) -> StorageResult<Box<dyn Iterator<Item = StorageResult<(Vec<u8>, Vec<u8>)>> + '_>>;
fn batch_get(&self, keys: &[&[u8]]) -> StorageResult<Vec<Option<Vec<u8>>>>;
fn batch_insert(&self, entries: &[(&[u8], &[u8])]) -> StorageResult<()>;
fn batch_remove(&self, keys: &[&[u8]]) -> StorageResult<()>;
fn flush(&self) -> StorageResult<()>;
}
pub trait StorageDriver: Send + Sync {
type Tree: StorageTree;
fn open<P: AsRef<Path>>(path: P) -> StorageResult<Self>
where
Self: Sized;
fn open_tree(&self, name: &str) -> StorageResult<Self::Tree>;
fn list_trees(&self) -> StorageResult<Vec<String>>;
fn flush(&self) -> StorageResult<()>;
fn storage_type(&self) -> StorageType;
fn open_index_tree(
&self,
name: &str,
index_options: IndexTreeOptions,
) -> StorageResult<Self::Tree>;
fn list_indexes(&self) -> StorageResult<Vec<String>>;
fn drop_index(&self, name: &str) -> StorageResult<()>;
fn tree_stats(&self, name: &str) -> StorageResult<Option<TreeStatistics>>;
fn shutdown(&mut self) -> StorageResult<()> {
self.flush()
}
}
impl StorageTree for Box<dyn StorageTree> {
fn insert(&self, key: &[u8], value: &[u8]) -> StorageResult<()> {
(**self).insert(key, value)
}
fn get(&self, key: &[u8]) -> StorageResult<Option<Vec<u8>>> {
(**self).get(key)
}
fn remove(&self, key: &[u8]) -> StorageResult<()> {
(**self).remove(key)
}
fn contains_key(&self, key: &[u8]) -> StorageResult<bool> {
(**self).contains_key(key)
}
fn clear(&self) -> StorageResult<()> {
(**self).clear()
}
fn is_empty(&self) -> StorageResult<bool> {
(**self).is_empty()
}
fn iter(
&self,
) -> StorageResult<Box<dyn Iterator<Item = StorageResult<(Vec<u8>, Vec<u8>)>> + '_>> {
(**self).iter()
}
fn flush(&self) -> StorageResult<()> {
(**self).flush()
}
fn scan_prefix(
&self,
prefix: &[u8],
) -> StorageResult<Box<dyn Iterator<Item = StorageResult<(Vec<u8>, Vec<u8>)>> + '_>> {
(**self).scan_prefix(prefix)
}
fn batch_get(&self, keys: &[&[u8]]) -> StorageResult<Vec<Option<Vec<u8>>>> {
(**self).batch_get(keys)
}
fn batch_insert(&self, entries: &[(&[u8], &[u8])]) -> StorageResult<()> {
(**self).batch_insert(entries)
}
fn batch_remove(&self, keys: &[&[u8]]) -> StorageResult<()> {
(**self).batch_remove(keys)
}
}
#[derive(Debug, Clone)]
pub struct IndexTreeOptions {
pub index_type: String,
pub compression: bool,
pub block_cache_size: Option<usize>,
pub write_buffer_size: Option<usize>,
pub bloom_filter_bits: Option<u32>,
pub custom_options: HashMap<String, String>,
}
impl Default for IndexTreeOptions {
fn default() -> Self {
Self {
index_type: "generic".to_string(),
compression: true,
block_cache_size: Some(64 * 1024 * 1024), write_buffer_size: Some(16 * 1024 * 1024), bloom_filter_bits: Some(10),
custom_options: HashMap::new(),
}
}
}
impl IndexTreeOptions {
pub fn for_graph_index() -> Self {
Self {
index_type: "graph".to_string(),
compression: false, block_cache_size: Some(64 * 1024 * 1024), write_buffer_size: Some(16 * 1024 * 1024), bloom_filter_bits: Some(12),
custom_options: HashMap::new(),
}
}
}
#[derive(Debug, Clone)]
pub struct TreeStatistics {
pub entry_count: u64,
pub size_bytes: u64,
pub memory_bytes: u64,
pub levels: Option<u32>,
pub compaction_stats: Option<CompactionStats>,
}
#[derive(Debug, Clone)]
pub struct CompactionStats {
pub compaction_count: u64,
pub last_compaction: Option<chrono::DateTime<chrono::Utc>>,
pub bytes_written: u64,
pub bytes_read: u64,
}