mod any;
pub mod forest;
mod many;
pub mod plain;
pub use any::AnyCar;
pub use forest::ForestCar;
pub use many::ManyCar;
pub use plain::PlainCar;
use ahash::HashMap;
use cid::Cid;
use lru::LruCache;
use positioned_io::{ReadAt, Size};
pub trait RandomAccessFileReader: ReadAt + Size + Send + Sync + 'static {}
impl<X: ReadAt + Size + Send + Sync + 'static> RandomAccessFileReader for X {}
pub type CacheKey = u64;
type FrameOffset = u64;
pub struct ZstdFrameCache {
pub max_size: usize,
current_size: usize,
lru: LruCache<(FrameOffset, CacheKey), HashMap<Cid, Vec<u8>>>,
}
impl Default for ZstdFrameCache {
fn default() -> Self {
ZstdFrameCache::new(ZstdFrameCache::DEFAULT_SIZE)
}
}
impl ZstdFrameCache {
pub const DEFAULT_SIZE: usize = 1024 * 1024 * 1024;
pub fn new(max_size: usize) -> Self {
ZstdFrameCache {
max_size,
current_size: 0,
lru: LruCache::unbounded(),
}
}
pub fn get(&mut self, offset: FrameOffset, key: CacheKey, cid: Cid) -> Option<Option<Vec<u8>>> {
self.lru
.get(&(offset, key))
.map(|index| index.get(&cid).cloned())
}
pub fn put(&mut self, offset: FrameOffset, key: CacheKey, index: HashMap<Cid, Vec<u8>>) {
fn size_of_entry(entry: &HashMap<Cid, Vec<u8>>) -> usize {
entry.values().map(Vec::len).sum::<usize>()
}
self.current_size += size_of_entry(&index);
if let Some(prev_entry) = self.lru.put((offset, key), index) {
self.current_size -= size_of_entry(&prev_entry);
}
while self.current_size > self.max_size {
if let Some((_, entry)) = self.lru.pop_lru() {
self.current_size -= size_of_entry(&entry)
} else {
break;
}
}
}
}