use std::collections::BTreeMap;
use std::ops::Bound;
use std::sync::Arc;
use crate::backend::StorageReadView;
use crate::read_view::{ReadLimits, ScanProjection};
use crate::{Op, StorageError, Store};
pub trait DeriveRead {
fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>, StorageError>;
fn range_prefix(&self, prefix: &[u8]) -> Result<Vec<(Vec<u8>, Vec<u8>)>, StorageError>;
fn range(&self, start: &[u8], end: &[u8]) -> Result<Vec<(Vec<u8>, Vec<u8>)>, StorageError>;
}
fn map_range<'a, V: 'a>(
map: &'a BTreeMap<Vec<u8>, V>,
start: &[u8],
end: &[u8],
) -> impl Iterator<Item = (&'a Vec<u8>, &'a V)> {
let upper = if end.is_empty() {
Bound::Unbounded
} else {
Bound::Excluded(end.to_vec())
};
map.range::<Vec<u8>, _>((Bound::Included(start.to_vec()), upper))
}
pub trait Deriver: Send + Sync {
fn derive(
&self,
ci: u64,
base_ops: &[Op],
before: &dyn DeriveRead,
) -> Result<Vec<Op>, StorageError>;
fn is_derived_key(&self, key: &[u8]) -> bool;
fn prefix_reaches_derived(&self, prefix: &[u8]) -> bool;
}
impl DeriveRead for crate::ReadView {
fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>, StorageError> {
crate::ReadView::get(self, key)
}
fn range_prefix(&self, prefix: &[u8]) -> Result<Vec<(Vec<u8>, Vec<u8>)>, StorageError> {
crate::ReadView::range_prefix(self, prefix)
}
fn range(&self, start: &[u8], end: &[u8]) -> Result<Vec<(Vec<u8>, Vec<u8>)>, StorageError> {
crate::ReadView::range(self, start, end)
}
}
pub(crate) struct Layered<'a> {
pub(crate) base: &'a dyn DeriveRead,
pub(crate) buffer: &'a BTreeMap<Vec<u8>, Option<Vec<u8>>>,
}
impl DeriveRead for Layered<'_> {
fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>, StorageError> {
match self.buffer.get(key) {
Some(value) => Ok(value.clone()),
None => self.base.get(key),
}
}
fn range_prefix(&self, prefix: &[u8]) -> Result<Vec<(Vec<u8>, Vec<u8>)>, StorageError> {
let mut merged: BTreeMap<Vec<u8>, Vec<u8>> =
self.base.range_prefix(prefix)?.into_iter().collect();
let upper = crate::prefix_range(prefix).1;
let end = if upper.is_empty() {
Bound::Unbounded
} else {
Bound::Excluded(upper)
};
for (key, value) in self
.buffer
.range::<Vec<u8>, _>((Bound::Included(prefix.to_vec()), end))
{
match value {
Some(value) => {
merged.insert(key.clone(), value.clone());
}
None => {
merged.remove(key);
}
}
}
Ok(merged.into_iter().collect())
}
fn range(&self, start: &[u8], end: &[u8]) -> Result<Vec<(Vec<u8>, Vec<u8>)>, StorageError> {
let mut merged: BTreeMap<Vec<u8>, Vec<u8>> =
self.base.range(start, end)?.into_iter().collect();
for (key, value) in map_range(self.buffer, start, end) {
match value {
Some(value) => {
merged.insert(key.clone(), value.clone());
}
None => {
merged.remove(key);
}
}
}
Ok(merged.into_iter().collect())
}
}
pub(crate) fn fold(buffer: &mut BTreeMap<Vec<u8>, Option<Vec<u8>>>, ops: &[Op]) {
for op in ops {
match op {
Op::Put(key, value) | Op::Set(key, value) => {
buffer.insert(key.clone(), Some(value.clone()));
}
Op::Del(key) | Op::Purge(key) => {
buffer.insert(key.clone(), None);
}
}
}
}
pub(crate) struct BackendRead(pub(crate) Box<dyn StorageReadView>);
impl DeriveRead for BackendRead {
fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>, StorageError> {
self.0.read_value(
key,
u64::MAX,
true,
ReadLimits::default(),
ScanProjection::KeyValue,
)
}
fn range_prefix(&self, prefix: &[u8]) -> Result<Vec<(Vec<u8>, Vec<u8>)>, StorageError> {
let end = crate::prefix_range(prefix).1;
self.0
.current_range(
prefix,
&end,
ReadLimits::default(),
ScanProjection::KeyValue,
)?
.collect()
}
fn range(&self, start: &[u8], end: &[u8]) -> Result<Vec<(Vec<u8>, Vec<u8>)>, StorageError> {
self.0
.current_range(start, end, ReadLimits::default(), ScanProjection::KeyValue)?
.collect()
}
}
pub(crate) struct MapRead<'a>(pub(crate) &'a BTreeMap<Vec<u8>, Vec<u8>>);
impl DeriveRead for MapRead<'_> {
fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>, StorageError> {
Ok(self.0.get(key).cloned())
}
fn range_prefix(&self, prefix: &[u8]) -> Result<Vec<(Vec<u8>, Vec<u8>)>, StorageError> {
Ok(self
.0
.range::<[u8], _>((Bound::Included(prefix), Bound::Unbounded))
.take_while(|(key, _)| key.starts_with(prefix))
.map(|(key, value)| (key.clone(), value.clone()))
.collect())
}
fn range(&self, start: &[u8], end: &[u8]) -> Result<Vec<(Vec<u8>, Vec<u8>)>, StorageError> {
Ok(map_range(self.0, start, end)
.map(|(key, value)| (key.clone(), value.clone()))
.collect())
}
}
pub(crate) struct Empty;
impl DeriveRead for Empty {
fn get(&self, _key: &[u8]) -> Result<Option<Vec<u8>>, StorageError> {
Ok(None)
}
fn range_prefix(&self, _prefix: &[u8]) -> Result<Vec<(Vec<u8>, Vec<u8>)>, StorageError> {
Ok(Vec::new())
}
fn range(&self, _start: &[u8], _end: &[u8]) -> Result<Vec<(Vec<u8>, Vec<u8>)>, StorageError> {
Ok(Vec::new())
}
}
impl Store {
pub fn set_deriver(&self, deriver: Arc<dyn Deriver>) {
if self
.underived_replay
.load(std::sync::atomic::Ordering::SeqCst)
{
self.health.fence();
}
*self.health.cleanup(self.deriver.write()) = Some(deriver);
}
#[doc(hidden)]
pub fn inject_without_derivation<T>(&self, f: impl FnOnce() -> T) -> T {
let saved = self.health.cleanup(self.deriver.write()).take();
let out = f();
*self.health.cleanup(self.deriver.write()) = saved;
out
}
pub(crate) fn deriver(&self) -> Option<Arc<dyn Deriver>> {
self.health.cleanup(self.deriver.read()).clone()
}
pub(crate) fn derive_ops(
deriver: Option<&Arc<dyn Deriver>>,
ci: u64,
base_ops: &[Op],
before: &dyn DeriveRead,
) -> Result<Option<Vec<Op>>, StorageError> {
let Some(deriver) = deriver else {
return Ok(None);
};
let extra = deriver.derive(ci, base_ops, before)?;
if extra.is_empty() {
return Ok(None);
}
let mut all = Vec::with_capacity(base_ops.len() + extra.len());
all.extend_from_slice(base_ops);
all.extend(extra);
Ok(Some(all))
}
}