use std::path::PathBuf;
use std::time::Duration;
use crate::config::{CacheEvictorType, GoosefsConfig};
const LOCAL_STORE_OVERHEAD: f64 = 0.05;
#[derive(Debug, Clone)]
pub struct CacheManagerOptions {
pub page_size: u64,
pub dir_capacity: u64,
pub dirs: Vec<PathBuf>,
pub evictor: CacheEvictorType,
pub async_write_enabled: bool,
pub async_write_threads: usize,
pub quota_enabled: bool,
pub ttl: Option<Duration>,
pub uring_enabled: bool,
pub uring_queue_depth: usize,
pub uring_thread_count: usize,
}
impl CacheManagerOptions {
pub fn from_config(config: &GoosefsConfig) -> Self {
let page_size = if config.client_cache_page_size == 0 {
1024 * 1024
} else {
config.client_cache_page_size
};
let dir_capacity = (config.client_cache_size as f64 * (1.0 - LOCAL_STORE_OVERHEAD)) as u64;
let dirs = config.client_cache_dirs.iter().map(PathBuf::from).collect();
let ttl = if config.client_cache_ttl_secs == 0 {
None
} else {
Some(Duration::from_secs(config.client_cache_ttl_secs))
};
Self {
page_size,
dir_capacity,
dirs,
evictor: config.client_cache_evictor,
async_write_enabled: config.client_cache_async_write_enabled,
async_write_threads: config.client_cache_async_write_threads.max(1),
quota_enabled: config.client_cache_quota_enabled,
ttl,
uring_enabled: config.client_cache_uring_enabled,
uring_queue_depth: config.client_cache_uring_queue_depth,
uring_thread_count: config.client_cache_uring_thread_count,
}
}
pub fn pages_per_dir(&self) -> u64 {
if self.page_size == 0 {
0
} else {
self.dir_capacity / self.page_size
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn from_config_defaults() {
let cfg = GoosefsConfig::default();
let opts = CacheManagerOptions::from_config(&cfg);
assert_eq!(opts.page_size, 1024 * 1024);
assert_eq!(
opts.dir_capacity,
(20.0 * 1024.0 * 1024.0 * 1024.0 * 0.95) as u64
);
assert_eq!(opts.dirs.len(), 1);
assert_eq!(opts.evictor, CacheEvictorType::Lfu);
assert!(opts.async_write_enabled);
assert_eq!(opts.async_write_threads, 16);
assert!(!opts.quota_enabled);
assert!(opts.ttl.is_none());
}
#[test]
fn sanitizes_zero_page_size_and_threads() {
let mut cfg = GoosefsConfig::default();
cfg.client_cache_page_size = 0;
cfg.client_cache_async_write_threads = 0;
let opts = CacheManagerOptions::from_config(&cfg);
assert_eq!(opts.page_size, 1024 * 1024);
assert_eq!(opts.async_write_threads, 1);
}
#[test]
fn ttl_zero_is_none() {
let mut cfg = GoosefsConfig::default();
cfg.client_cache_ttl_secs = 0;
assert!(CacheManagerOptions::from_config(&cfg).ttl.is_none());
cfg.client_cache_ttl_secs = 30;
assert_eq!(
CacheManagerOptions::from_config(&cfg).ttl,
Some(Duration::from_secs(30))
);
}
#[test]
fn pages_per_dir_computation() {
let mut cfg = GoosefsConfig::default();
cfg.client_cache_page_size = 1024 * 1024;
cfg.client_cache_size = 10 * 1024 * 1024; let opts = CacheManagerOptions::from_config(&cfg);
assert_eq!(opts.pages_per_dir(), 9);
}
}