use std::{any::Any, fmt::Debug, sync::Arc};
use foyer_common::{
code::{StorageKey, StorageValue},
error::Result,
metrics::Metrics,
properties::{Age, Properties},
spawn::Spawner,
};
use foyer_memory::Piece;
use futures_core::future::BoxFuture;
use crate::{filter::StorageFilterResult, io::engine::IoEngine, keeper::PieceRef, Device};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Populated {
pub age: Age,
}
pub enum Load<K, V, P> {
Entry {
key: K,
value: V,
populated: Populated,
},
Piece {
piece: Piece<K, V, P>,
populated: Populated,
},
Throttled,
Miss,
}
impl<K, V, P> Debug for Load<K, V, P> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Load::Entry { populated, .. } => f.debug_struct("Load::Entry").field("populated", populated).finish(),
Load::Piece { piece, populated } => f
.debug_struct("Load::Piece")
.field("piece", piece)
.field("populated", populated)
.finish(),
Load::Throttled => f.debug_struct("Load::Throttled").finish(),
Load::Miss => f.debug_struct("Load::Miss").finish(),
}
}
}
impl<K, V, P> Load<K, V, P> {
pub fn entry(self) -> Option<(K, V, Populated)> {
match self {
Load::Entry { key, value, populated } => Some((key, value, populated)),
_ => None,
}
}
pub fn kv(self) -> Option<(K, V)> {
match self {
Load::Entry { key, value, .. } => Some((key, value)),
_ => None,
}
}
pub fn is_miss(&self) -> bool {
matches!(self, Load::Miss)
}
pub fn is_throttled(&self) -> bool {
matches!(self, Load::Throttled)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
pub enum RecoverMode {
None,
#[default]
Quiet,
Strict,
}
pub struct EngineBuildContext {
pub io_engine: Arc<dyn IoEngine>,
pub metrics: Arc<Metrics>,
pub spawner: Spawner,
pub recover_mode: RecoverMode,
}
#[expect(clippy::type_complexity)]
pub trait EngineConfig<K, V, P>: Send + Sync + 'static + Debug
where
K: StorageKey,
V: StorageValue,
P: Properties,
{
fn build(self: Box<Self>, ctx: EngineBuildContext) -> BoxFuture<'static, Result<Arc<dyn Engine<K, V, P>>>>;
fn boxed(self) -> Box<Self>
where
Self: Sized,
{
Box::new(self)
}
}
pub trait Engine<K, V, P>: Send + Sync + 'static + Debug + Any
where
K: StorageKey,
V: StorageValue,
P: Properties,
{
fn device(&self) -> &Arc<dyn Device>;
fn filter(&self, hash: u64, estimated_size: usize) -> StorageFilterResult;
fn enqueue(&self, piece: PieceRef<K, V, P>, estimated_size: usize);
fn load(&self, hash: u64) -> BoxFuture<'static, Result<Load<K, V, P>>>;
fn delete(&self, hash: u64);
fn may_contains(&self, hash: u64) -> bool;
fn destroy(&self) -> BoxFuture<'static, Result<()>>;
fn wait(&self) -> BoxFuture<'static, ()>;
fn close(&self) -> BoxFuture<'static, Result<()>>;
}
pub mod block;
pub mod noop;