use std::{collections::HashSet, marker::PhantomData, sync::Arc};
use foyer_common::code::{StorageKey, StorageValue};
use parking_lot::Mutex;
use crate::{
admission::{AdmissionContext, AdmissionPolicy},
reinsertion::{ReinsertionContext, ReinsertionPolicy},
};
#[derive(Debug)]
pub enum Record<K> {
Admit(Arc<K>),
Evict(Arc<K>),
}
impl<K> Clone for Record<K> {
fn clone(&self) -> Self {
match self {
Self::Admit(key) => Self::Admit(key.clone()),
Self::Evict(key) => Self::Evict(key.clone()),
}
}
}
#[derive(Debug)]
pub struct JudgeRecorder<K, V>
where
K: StorageKey,
V: StorageValue,
{
records: Mutex<Vec<Record<K>>>,
_marker: PhantomData<V>,
}
impl<K, V> JudgeRecorder<K, V>
where
K: StorageKey,
V: StorageValue,
{
pub fn dump(&self) -> Vec<Record<K>> {
self.records.lock().clone()
}
pub fn remains(&self) -> HashSet<Arc<K>> {
let records = self.dump();
let mut res = HashSet::default();
for record in records {
match record {
Record::Admit(key) => {
res.insert(key);
}
Record::Evict(key) => {
res.remove(&key);
}
}
}
res
}
}
impl<K, V> Default for JudgeRecorder<K, V>
where
K: StorageKey,
V: StorageValue,
{
fn default() -> Self {
Self {
records: Mutex::new(Vec::default()),
_marker: PhantomData,
}
}
}
impl<K, V> AdmissionPolicy for JudgeRecorder<K, V>
where
K: StorageKey,
V: StorageValue,
{
type Key = K;
type Value = V;
fn init(&self, _: AdmissionContext<Self::Key, Self::Value>) {}
fn judge(&self, key: &Arc<K>) -> bool {
self.records.lock().push(Record::Admit(key.clone()));
true
}
}
impl<K, V> ReinsertionPolicy for JudgeRecorder<K, V>
where
K: StorageKey,
V: StorageValue,
{
type Key = K;
type Value = V;
fn init(&self, _: ReinsertionContext<Self::Key, Self::Value>) {}
fn judge(&self, key: &Arc<K>) -> bool {
self.records.lock().push(Record::Evict(key.clone()));
false
}
}