use super::*;
use crate::async_lru_cache::AsyncLruCacheBackend;
use tracing::trace;
pub(super) struct L2CacheBackend<S: Storage> {
file: Arc<S>,
header: Arc<Header>,
}
pub(super) struct RefBlockCacheBackend<S: Storage> {
file: Arc<S>,
header: Arc<Header>,
}
impl<S: Storage> L2CacheBackend<S> {
pub fn new(file: Arc<S>, header: Arc<Header>) -> Self {
L2CacheBackend { file, header }
}
}
impl<S: Storage> AsyncLruCacheBackend for L2CacheBackend<S> {
type Key = HostCluster;
type Value = L2Table;
async fn load(&self, l2_cluster: HostCluster) -> io::Result<L2Table> {
trace!("Loading L2 table");
L2Table::load(
self.file.as_ref(),
&self.header,
l2_cluster,
self.header.l2_entries(),
)
.await
}
async fn flush(&self, l2_cluster: HostCluster, l2_table: Arc<L2Table>) -> io::Result<()> {
trace!("Flushing L2 table");
if l2_table.is_modified() {
assert!(l2_table.get_cluster().unwrap() == l2_cluster);
l2_table.write(self.file.as_ref()).await?;
}
Ok(())
}
unsafe fn evict(&self, _l2_cluster: HostCluster, l2_table: L2Table) {
trace!(
"Evicting L2 table {}",
l2_table.get_offset().unwrap_or(HostOffset(0))
);
l2_table.clear_modified();
}
}
impl<S: Storage> RefBlockCacheBackend<S> {
pub fn new(file: Arc<S>, header: Arc<Header>) -> Self {
RefBlockCacheBackend { file, header }
}
}
impl<S: Storage> AsyncLruCacheBackend for RefBlockCacheBackend<S> {
type Key = HostCluster;
type Value = RefBlock;
async fn load(&self, rb_cluster: HostCluster) -> io::Result<RefBlock> {
RefBlock::load(self.file.as_ref(), &self.header, rb_cluster).await
}
async fn flush(&self, rb_cluster: HostCluster, refblock: Arc<RefBlock>) -> io::Result<()> {
if refblock.is_modified() {
assert!(refblock.get_cluster().unwrap() == rb_cluster);
refblock.write(self.file.as_ref()).await?;
}
Ok(())
}
unsafe fn evict(&self, _rb_cluster: HostCluster, refblock: RefBlock) {
refblock.clear_modified();
}
}