use std::{any::Any, sync::Arc};
use futures::StreamExt;
use parking_lot::RwLock;
use tendermint::abci;
use crate::{
future::{
CacheFuture, StateDeltaNonconsensusPrefixRawStream, StateDeltaNonconsensusRangeRawStream,
StateDeltaPrefixKeysStream, StateDeltaPrefixRawStream,
},
utils, Cache, EscapedByteSlice, StateRead, StateWrite,
};
#[derive(Debug)]
pub struct StateDelta<S: StateRead> {
state: Arc<RwLock<Option<S>>>,
layers: Vec<Arc<RwLock<Option<Cache>>>>,
leaf_cache: Arc<RwLock<Option<Cache>>>,
}
impl<S: StateRead> StateDelta<S> {
pub fn new(state: S) -> Self {
Self {
state: Arc::new(RwLock::new(Some(state))),
layers: Vec::default(),
leaf_cache: Arc::new(RwLock::new(Some(Cache::default()))),
}
}
pub fn fork(&mut self) -> Self {
if self
.leaf_cache
.read()
.as_ref()
.expect("unable to get ref to leaf cache, storage not initialized?")
.is_dirty()
{
let new_layer = std::mem::replace(
&mut self.leaf_cache,
Arc::new(RwLock::new(Some(Cache::default()))),
);
self.layers.push(new_layer);
}
Self {
state: self.state.clone(),
layers: self.layers.clone(),
leaf_cache: Arc::new(RwLock::new(Some(Cache::default()))),
}
}
pub fn flatten(self) -> (S, Cache) {
tracing::trace!("flattening branch");
let state = self
.state
.write()
.take()
.expect("apply must be called only once");
let mut changes = Cache::default();
for layer in self.layers {
let cache = layer
.write()
.take()
.expect("cache must not have already been applied");
changes.merge(cache);
}
changes.merge(
self.leaf_cache
.write()
.take()
.expect("unable to take leaf cache, was it already applied?"),
);
(state, changes)
}
}
impl<S: StateRead + StateWrite> StateDelta<S> {
pub fn apply(self) -> (S, Vec<abci::Event>) {
let (mut state, mut changes) = self.flatten();
let events = changes.take_events();
changes.apply_to(&mut state);
(state, events)
}
}
impl<S: StateRead + StateWrite> StateDelta<Arc<S>> {
pub fn try_apply(self) -> anyhow::Result<(S, Vec<abci::Event>)> {
let (arc_state, mut changes) = self.flatten();
let events = std::mem::take(&mut changes.events);
if let Ok(mut state) = Arc::try_unwrap(arc_state) {
changes.apply_to(&mut state);
Ok((state, events))
} else {
Err(anyhow::anyhow!("did not have unique ownership of Arc<S>"))
}
}
}
impl<S: StateRead> StateRead for StateDelta<S> {
type GetRawFut = CacheFuture<S::GetRawFut>;
type PrefixRawStream = StateDeltaPrefixRawStream<S::PrefixRawStream>;
type PrefixKeysStream = StateDeltaPrefixKeysStream<S::PrefixKeysStream>;
type NonconsensusPrefixRawStream =
StateDeltaNonconsensusPrefixRawStream<S::NonconsensusPrefixRawStream>;
type NonconsensusRangeRawStream =
StateDeltaNonconsensusRangeRawStream<S::NonconsensusRangeRawStream>;
fn get_raw(&self, key: &str) -> Self::GetRawFut {
if let Some(entry) = self
.leaf_cache
.read()
.as_ref()
.expect("delta must not have been applied")
.unwritten_changes
.get(key)
{
return CacheFuture::hit(entry.clone());
}
for layer in self.layers.iter().rev() {
if let Some(entry) = layer
.read()
.as_ref()
.expect("delta must not have been applied")
.unwritten_changes
.get(key)
{
return CacheFuture::hit(entry.clone());
}
}
CacheFuture::miss(
self.state
.read()
.as_ref()
.expect("delta must not have been applied")
.get_raw(key),
)
}
fn nonverifiable_get_raw(&self, key: &[u8]) -> Self::GetRawFut {
if let Some(entry) = self
.leaf_cache
.read()
.as_ref()
.expect("delta must not have been applied")
.nonverifiable_changes
.get(key)
{
return CacheFuture::hit(entry.clone());
}
for layer in self.layers.iter().rev() {
if let Some(entry) = layer
.read()
.as_ref()
.expect("delta must not have been applied")
.nonverifiable_changes
.get(key)
{
return CacheFuture::hit(entry.clone());
}
}
CacheFuture::miss(
self.state
.read()
.as_ref()
.expect("delta must not have been applied")
.nonverifiable_get_raw(key),
)
}
fn object_type(&self, key: &'static str) -> Option<std::any::TypeId> {
if let Some(entry) = self
.leaf_cache
.read()
.as_ref()
.expect("delta must not have been applied")
.ephemeral_objects
.get(key)
{
return entry.as_ref().map(|v| std::any::Any::type_id(&**v));
}
for layer in self.layers.iter().rev() {
if let Some(entry) = layer
.read()
.as_ref()
.expect("delta must not have been applied")
.ephemeral_objects
.get(key)
{
return entry.as_ref().map(|v| std::any::Any::type_id(&**v));
}
}
self.state
.read()
.as_ref()
.expect("delta must not have been applied")
.object_type(key)
}
fn object_get<T: std::any::Any + Send + Sync + Clone>(&self, key: &'static str) -> Option<T> {
if let Some(entry) = self
.leaf_cache
.read()
.as_ref()
.expect("delta must not have been applied")
.ephemeral_objects
.get(key)
{
return entry
.as_ref()
.map(|v| {
v.downcast_ref().unwrap_or_else(|| panic!("unexpected type for key \"{key}\" in `StateDelta::object_get`: expected type {}", std::any::type_name::<T>()))
})
.cloned();
}
for layer in self.layers.iter().rev() {
if let Some(entry) = layer
.read()
.as_ref()
.expect("delta must not have been applied")
.ephemeral_objects
.get(key)
{
return entry
.as_ref()
.map(|v| {
v.downcast_ref().unwrap_or_else(|| panic!("unexpected type for key \"{key}\" in `StateDelta::object_get`: expected type {}", std::any::type_name::<T>()))
}).cloned();
}
}
self.state
.read()
.as_ref()
.expect("delta must not have been applied")
.object_get(key)
}
fn prefix_raw(&self, prefix: &str) -> Self::PrefixRawStream {
let underlying = self
.state
.read()
.as_ref()
.expect("delta must not have been applied")
.prefix_raw(prefix)
.peekable();
StateDeltaPrefixRawStream {
underlying,
layers: self.layers.clone(),
leaf_cache: self.leaf_cache.clone(),
last_key: None,
prefix: prefix.to_owned(),
}
}
fn prefix_keys(&self, prefix: &str) -> Self::PrefixKeysStream {
let underlying = self
.state
.read()
.as_ref()
.expect("delta must not have been applied")
.prefix_keys(prefix)
.peekable();
StateDeltaPrefixKeysStream {
underlying,
layers: self.layers.clone(),
leaf_cache: self.leaf_cache.clone(),
last_key: None,
prefix: prefix.to_owned(),
}
}
fn nonverifiable_prefix_raw(&self, prefix: &[u8]) -> Self::NonconsensusPrefixRawStream {
let underlying = self
.state
.read()
.as_ref()
.expect("delta must not have been applied")
.nonverifiable_prefix_raw(prefix)
.peekable();
StateDeltaNonconsensusPrefixRawStream {
underlying,
layers: self.layers.clone(),
leaf_cache: self.leaf_cache.clone(),
last_key: None,
prefix: prefix.to_vec(),
}
}
fn nonverifiable_range_raw(
&self,
prefix: Option<&[u8]>,
range: impl std::ops::RangeBounds<Vec<u8>>,
) -> anyhow::Result<Self::NonconsensusRangeRawStream> {
let (range, (start, end)) = utils::convert_bounds(range)?;
let underlying = self
.state
.read()
.as_ref()
.expect("delta must not have been applied")
.nonverifiable_range_raw(prefix, range)?
.peekable();
Ok(StateDeltaNonconsensusRangeRawStream {
underlying,
layers: self.layers.clone(),
leaf_cache: self.leaf_cache.clone(),
last_key: None,
prefix: prefix.map(|p| p.to_vec()),
range: (start, end),
})
}
}
impl<S: StateRead> StateWrite for StateDelta<S> {
fn put_raw(&mut self, key: String, value: jmt::OwnedValue) {
self.leaf_cache
.write()
.as_mut()
.expect("delta must not have been applied")
.unwritten_changes
.insert(key, Some(value));
}
fn delete(&mut self, key: String) {
self.leaf_cache
.write()
.as_mut()
.expect("delta must not have been applied")
.unwritten_changes
.insert(key, None);
}
fn nonverifiable_delete(&mut self, key: Vec<u8>) {
tracing::trace!(key = ?EscapedByteSlice(&key), "deleting key");
self.leaf_cache
.write()
.as_mut()
.expect("delta must not have been applied")
.nonverifiable_changes
.insert(key, None);
}
fn nonverifiable_put_raw(&mut self, key: Vec<u8>, value: Vec<u8>) {
tracing::trace!(key = ?EscapedByteSlice(&key), value = ?EscapedByteSlice(&value), "insert nonverifiable change");
self.leaf_cache
.write()
.as_mut()
.expect("delta must not have been applied")
.nonverifiable_changes
.insert(key, Some(value));
}
fn object_put<T: Clone + Any + Send + Sync>(&mut self, key: &'static str, value: T) {
if let Some(previous_type) = self.object_type(key) {
if std::any::TypeId::of::<T>() != previous_type {
panic!(
"unexpected type for key \"{key}\" in `StateDelta::object_put`: expected type {expected}",
expected = std::any::type_name::<T>(),
);
}
}
self.leaf_cache
.write()
.as_mut()
.expect("delta must not have been applied")
.ephemeral_objects
.insert(key, Some(Box::new(value)));
}
fn object_delete(&mut self, key: &'static str) {
self.leaf_cache
.write()
.as_mut()
.expect("delta must not have been applied")
.ephemeral_objects
.insert(key, None);
}
fn object_merge(
&mut self,
objects: std::collections::BTreeMap<&'static str, Option<Box<dyn Any + Send + Sync>>>,
) {
self.leaf_cache
.write()
.as_mut()
.expect("delta must not have been applied")
.ephemeral_objects
.extend(objects);
}
fn record(&mut self, event: abci::Event) {
self.leaf_cache
.write()
.as_mut()
.expect("delta must not have been applied")
.events
.push(event)
}
}
pub trait ArcStateDeltaExt: Sized {
type S: StateRead;
fn try_begin_transaction(&'_ mut self) -> Option<StateDelta<&'_ mut StateDelta<Self::S>>>;
}
impl<S: StateRead> ArcStateDeltaExt for Arc<StateDelta<S>> {
type S = S;
fn try_begin_transaction(&'_ mut self) -> Option<StateDelta<&'_ mut StateDelta<S>>> {
Arc::get_mut(self).map(StateDelta::new)
}
}