use std::path::Path;
use std::time::Duration;
use sva_formula::Hash;
use sva_samples::{FilterTrace, Label};
use super::{Cache, Entry, Expected, Medium, MemoryCache, Pack, Payload, PayloadKind};
pub struct Tiered<M: Medium> {
pub front: MemoryCache,
pub back: Pack<M>,
}
impl<M: Medium> Tiered<M> {
pub fn new(front: MemoryCache, back: Pack<M>) -> Tiered<M> {
Tiered { front, back }
}
}
impl<M: Medium> Cache for Tiered<M> {
fn load(&self, key: Hash, node: &str, expected: Expected) -> Option<Entry> {
if let Some(entry) = self.front.load(key, node, expected) {
return Some(entry);
}
let entry = self.back.load(key, node, expected)?;
self.front
.store(key, &entry.payload, &entry.traces, entry.label.as_ref());
Some(entry)
}
fn peek(&self, key: Hash, node: &str, expected: Expected) -> Option<Entry> {
self.front
.peek(key, node, expected)
.or_else(|| self.back.peek(key, node, expected))
}
fn store(&self, key: Hash, payload: &Payload, traces: &[FilterTrace], label: Option<&Label>) {
self.front.store(key, payload, traces, label);
if self
.back
.worth_storing(Duration::ZERO, payload.bytes(), payload.kind())
{
self.back.store(key, payload, traces, label);
}
}
fn holds(&self, key: Hash) -> bool {
self.front.holds(key) || self.back.holds(key)
}
fn worth_storing(&self, cost: Duration, bytes: usize, kind: PayloadKind) -> bool {
self.front.worth_storing(cost, bytes, kind) || self.back.worth_storing(cost, bytes, kind)
}
fn sweep(&self) {
self.front.sweep();
self.back.sweep();
}
fn held_bytes(&self) -> u64 {
self.front.held_bytes() + self.back.held_bytes()
}
fn evicted_bytes(&self) -> u64 {
self.front.evicted_bytes() + self.back.evicted_bytes()
}
fn faults(&self) -> u64 {
self.front.faults() + self.back.faults()
}
fn max_bytes(&self) -> u64 {
self.front.max_bytes().saturating_add(self.back.max_bytes())
}
fn dir(&self) -> Option<&Path> {
self.back.dir()
}
}