use std::cell::RefCell;
use std::collections::HashMap;
use std::path::PathBuf;
use std::sync::{Arc, LazyLock, Mutex, Weak};
use super::error::ChunkCacheError;
use super::{CacheConfig, ChunkCache, DiskCache};
static CACHE_MANAGER: LazyLock<CacheManager> = LazyLock::new(CacheManager::new);
pub fn get_cache(config: &CacheConfig) -> Result<Arc<dyn ChunkCache>, ChunkCacheError> {
CACHE_MANAGER.get(config)
}
struct CacheManager {
vals: Mutex<HashMap<PathBuf, RefCell<Weak<dyn ChunkCache>>>>,
}
impl CacheManager {
fn new() -> Self {
Self {
vals: Mutex::new(HashMap::new()),
}
}
fn get(&self, config: &CacheConfig) -> Result<Arc<dyn ChunkCache>, ChunkCacheError> {
let mut vals = self.vals.lock()?;
if let Some(v) = vals.get_mut(&config.cache_directory) {
let weak = v.borrow().clone();
if let Some(value) = weak.upgrade() {
return Ok(value);
}
let result: Arc<dyn ChunkCache> = Arc::new(DiskCache::initialize(config)?);
v.replace(Arc::downgrade(&result));
Ok(result)
} else {
let result: Arc<dyn ChunkCache> = Arc::new(DiskCache::initialize(config)?);
vals.insert(config.cache_directory.clone(), RefCell::new(Arc::downgrade(&result)));
Ok(result)
}
}
}