use std::sync::Arc;
use dashmap::DashMap;
use crate::HashMap;
use super::{
constant::{CacheStoreFactory, CacheStoreTrait},
error::CacheError,
namespace::NamespaceStore,
CacheStoreKey,
};
#[derive(Default)]
pub struct MemoryCacheStore {
cache: DashMap<String, Vec<u8>>,
manifest: DashMap<String, String>,
}
impl MemoryCacheStore {
pub fn new() -> Self {
Default::default()
}
}
impl CacheStoreTrait for MemoryCacheStore {
fn has_cache(&self, name: &str) -> bool {
self.manifest.contains_key(name)
}
fn is_cache_changed(&self, store_key: &CacheStoreKey) -> bool {
!matches!(self.manifest.get(&store_key.name), Some(guard) if guard.value() == &store_key.key)
}
fn write_single_cache(&self, store_key: CacheStoreKey, bytes: Vec<u8>) -> Result<(), CacheError> {
if self.is_cache_changed(&store_key) {
self.manifest.insert(store_key.name, store_key.key.clone());
self.cache.insert(store_key.key, bytes);
}
Ok(())
}
fn write_cache(&self, cache_map: HashMap<CacheStoreKey, Vec<u8>>) {
for (store_key, bytes) in cache_map {
self.write_single_cache(store_key, bytes).unwrap();
}
}
fn read_cache(&self, name: &str) -> Option<Vec<u8>> {
self.read_cache_ref(name).map(|v| v.value().clone())
}
fn read_cache_ref(&self, name: &str) -> Option<super::constant::CacheStoreItemRef<'_>> {
if let Some(key) = self.manifest.get(name) {
return self.cache.get(key.value()).map(|v| v.map(|v| v));
}
None
}
fn remove_cache(&self, name: &str) -> Option<Vec<u8>> {
self.manifest.remove(name);
self.cache.remove(name).map(|(_, v)| v)
}
}
pub struct MemoryCacheFactory {
store: Arc<Box<dyn CacheStoreTrait>>,
}
impl Default for MemoryCacheFactory {
fn default() -> Self {
Self {
store: Arc::new(Box::new(MemoryCacheStore::new())),
}
}
}
impl MemoryCacheFactory {
pub fn new() -> Self {
Default::default()
}
}
impl CacheStoreFactory for MemoryCacheFactory {
fn create_cache_store(&self, name: &str) -> Box<dyn CacheStoreTrait> {
Box::new(NamespaceStore::new(self.store.clone(), name.to_string()))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn t1() {
let store = MemoryCacheStore::new();
let bytes = vec![1, 2, 3];
let name = "namespace".to_string();
store
.write_single_cache(
CacheStoreKey {
name: name.clone(),
key: "hash".to_string(),
},
bytes.clone(),
)
.unwrap();
assert_eq!(store.read_cache(&name), Some(bytes));
}
}