sov_state/
internal_cache.rs

1use sov_first_read_last_write_cache::cache::{self, CacheLog, ValueExists};
2use sov_first_read_last_write_cache::{CacheKey, CacheValue};
3
4use crate::storage::{Storage, StorageKey, StorageValue};
5
6/// Caches reads and writes for a (key, value) pair. On the first read the value is fetched
7/// from an external source represented by the `ValueReader` trait. On following reads,
8/// the cache checks if the value we read was inserted before.
9#[derive(Default)]
10pub struct StorageInternalCache {
11    /// Transaction cache.
12    pub tx_cache: CacheLog,
13    /// Ordered reads and writes.
14    pub ordered_db_reads: Vec<(CacheKey, Option<CacheValue>)>,
15}
16
17/// A struct that contains the values read from the DB and the values to be written, both in
18/// deterministic order.
19#[derive(Debug, Default)]
20pub struct OrderedReadsAndWrites {
21    /// Ordered reads.
22    pub ordered_reads: Vec<(CacheKey, Option<CacheValue>)>,
23    /// Ordered writes.
24    pub ordered_writes: Vec<(CacheKey, Option<CacheValue>)>,
25}
26
27impl From<StorageInternalCache> for OrderedReadsAndWrites {
28    fn from(val: StorageInternalCache) -> Self {
29        let mut writes = val.tx_cache.take_writes();
30        // TODO: Make this more efficient
31        writes.sort_by(|(k1, _), (k2, _)| k1.cmp(k2));
32        Self {
33            ordered_reads: val.ordered_db_reads,
34            ordered_writes: writes,
35        }
36    }
37}
38
39impl From<StorageInternalCache> for CacheLog {
40    fn from(val: StorageInternalCache) -> Self {
41        val.tx_cache
42    }
43}
44
45impl StorageInternalCache {
46    /// Gets a value from the cache or reads it from the provided `ValueReader`.
47    pub fn get_or_fetch<S: Storage>(
48        &mut self,
49        key: &StorageKey,
50        value_reader: &S,
51        witness: &S::Witness,
52    ) -> Option<StorageValue> {
53        let cache_key = key.to_cache_key();
54        let cache_value = self.get_value_from_cache(&cache_key);
55
56        match cache_value {
57            cache::ValueExists::Yes(cache_value_exists) => cache_value_exists.map(Into::into),
58            // If the value does not exist in the cache, then fetch it from an external source.
59            cache::ValueExists::No => {
60                let storage_value = value_reader.get(key, witness);
61                let cache_value = storage_value.as_ref().map(|v| v.clone().into_cache_value());
62
63                self.add_read(cache_key, cache_value);
64                storage_value
65            }
66        }
67    }
68
69    /// Gets a keyed value from the cache, returning a wrapper on whether it exists.
70    pub fn try_get(&self, key: &StorageKey) -> ValueExists {
71        let cache_key = key.to_cache_key();
72        self.get_value_from_cache(&cache_key)
73    }
74
75    /// Replaces the keyed value on the storage.
76    pub fn set(&mut self, key: &StorageKey, value: StorageValue) {
77        let cache_key = key.to_cache_key();
78        let cache_value = value.into_cache_value();
79        self.tx_cache.add_write(cache_key, Some(cache_value));
80    }
81
82    /// Deletes a keyed value from the cache.
83    pub fn delete(&mut self, key: &StorageKey) {
84        let cache_key = key.to_cache_key();
85        self.tx_cache.add_write(cache_key, None);
86    }
87
88    fn get_value_from_cache(&self, cache_key: &CacheKey) -> cache::ValueExists {
89        self.tx_cache.get_value(cache_key)
90    }
91
92    /// Merges the provided `StorageInternalCache` into this one.
93    pub fn merge_left(
94        &mut self,
95        rhs: Self,
96    ) -> Result<(), sov_first_read_last_write_cache::MergeError> {
97        self.tx_cache.merge_left(rhs.tx_cache)
98    }
99
100    /// Merges the reads of the provided `StorageInternalCache` into this one.
101    pub fn merge_reads_left(
102        &mut self,
103        rhs: Self,
104    ) -> Result<(), sov_first_read_last_write_cache::MergeError> {
105        self.tx_cache.merge_reads_left(rhs.tx_cache)
106    }
107
108    /// Merges the writes of the provided `StorageInternalCache` into this one.
109    pub fn merge_writes_left(
110        &mut self,
111        rhs: Self,
112    ) -> Result<(), sov_first_read_last_write_cache::MergeError> {
113        self.tx_cache.merge_writes_left(rhs.tx_cache)
114    }
115
116    fn add_read(&mut self, key: CacheKey, value: Option<CacheValue>) {
117        self.tx_cache
118            .add_read(key.clone(), value.clone())
119            // It is ok to panic here, we must guarantee that the cache is consistent.
120            .unwrap_or_else(|e| panic!("Inconsistent read from the cache: {e:?}"));
121        self.ordered_db_reads.push((key, value))
122    }
123}