chunk_cache_bench/src/sccache.rs (23 lines of code) (raw):

use std::ffi::{OsStr, OsString}; use std::io::Write; use std::os::unix::ffi::OsStringExt; use std::path::PathBuf; use std::sync::{Arc, Mutex}; use base64::Engine; use cas_types::{ChunkRange, Key}; use chunk_cache::error::ChunkCacheError; use chunk_cache::{CacheRange, ChunkCache}; use sccache::lru_disk_cache::LruDiskCache; use crate::ChunkCacheExt; #[derive(Clone)] pub struct SCCache { cache: Arc<Mutex<LruDiskCache>>, } impl ChunkCacheExt for SCCache { fn _initialize(cache_root: PathBuf, capacity: u64) -> Result<Self, ChunkCacheError> { let cache = LruDiskCache::new(cache_root, capacity).map_err(ChunkCacheError::general)?; Ok(Self { cache: Arc::new(Mutex::new(cache)), }) } fn name() -> &'static str { "sccache" } } #[async_trait::async_trait] impl ChunkCache for SCCache { async fn get( &self, key: &cas_types::Key, range: &cas_types::ChunkRange, ) -> Result<Option<CacheRange>, ChunkCacheError> { let cache_key = CacheKey::new(key, range)?; let mut file = if let Ok(file) = self.cache.lock()?.get(&cache_key) { file } else { return Ok(None); }; let mut res = Vec::new(); file.read_to_end(&mut res)?; Ok(Some(CacheRange { offsets: (range.start..=range.end).collect::<Vec<_>>().into(), data: res.into(), range: range.clone(), })) } async fn put( &self, key: &cas_types::Key, range: &cas_types::ChunkRange, _chunk_byte_indices: &[u32], data: &[u8], ) -> Result<(), ChunkCacheError> { let mut cache = self.cache.lock()?; let cache_key = CacheKey::new(key, range)?; if cache.get(&cache_key).is_ok() { return Ok(()); } cache.insert_bytes(cache_key, data).map_err(ChunkCacheError::general)?; Ok(()) } } #[derive(Debug)] struct CacheKey(OsString); impl CacheKey { fn new(key: &Key, range: &ChunkRange) -> Result<Self, ChunkCacheError> { let mut buf = Vec::new(); buf.write_all(key.hash.as_bytes())?; buf.write_all(key.prefix.as_bytes())?; buf.write_all(format!("{}_{}", range.start, range.end).as_bytes())?; let result = base64::engine::general_purpose::URL_SAFE.encode(buf).as_bytes().to_vec(); Ok(CacheKey(OsString::from_vec(result))) } } impl AsRef<OsStr> for CacheKey { fn as_ref(&self) -> &OsStr { &self.0 } }