oasis_core_runtime/storage/mkvs/cache/
mod.rs

1mod lru_cache;
2
3pub use lru_cache::LRUCache;
4
5use std::ptr::NonNull;
6
7use anyhow::Result;
8
9use crate::storage::mkvs::{
10    cache::lru_cache::CacheItemBox,
11    sync::{Proof, ReadSync},
12    tree::{Depth, Key, NodeKind, NodePtrRef, NodeRef, Root, Value},
13};
14
15/// Statistics about the contents of the cache.
16#[derive(Debug, Default)]
17#[cfg(test)]
18pub struct CacheStats {
19    /// Count of internal nodes held by the cache.
20    pub internal_node_count: usize,
21    /// Total size of values held by the cache.
22    pub leaf_value_size: usize,
23}
24
25/// Used to fetch proofs from a remote tree via the ReadSyncer interface.
26pub trait ReadSyncFetcher {
27    /// Fetch proof.
28    fn fetch(&self, root: Root, ptr: NodePtrRef, rs: &mut Box<dyn ReadSync>) -> Result<Proof>;
29}
30
31impl<F> ReadSyncFetcher for F
32where
33    F: Fn(Root, NodePtrRef, &mut Box<dyn ReadSync>) -> Result<Proof>,
34{
35    fn fetch(&self, root: Root, ptr: NodePtrRef, rs: &mut Box<dyn ReadSync>) -> Result<Proof> {
36        (*self)(root, ptr, rs)
37    }
38}
39
40/// Cache interface for the in-mmory tree cache.
41pub trait Cache {
42    /// Return statistics about the contents of the cache.
43    #[cfg(test)]
44    fn stats(&self) -> CacheStats;
45
46    /// Get a pointer to the current uncommitted root node.
47    fn get_pending_root(&self) -> NodePtrRef;
48    /// Set the root node for the tree to the given pointer.
49    fn set_pending_root(&mut self, new_root: NodePtrRef);
50    /// Set the root of the tree after committing.
51    fn set_sync_root(&mut self, root: Root);
52
53    /// Get the read syncer backing this cache.
54    #[cfg(test)]
55    fn get_read_syncer(&self) -> &Box<dyn ReadSync>;
56
57    /// Create a new internal node and returns a pointer to it.
58    fn new_internal_node(
59        &mut self,
60        label: &Key,
61        label_bit_length: Depth,
62        leaf_node: NodePtrRef,
63        left: NodePtrRef,
64        right: NodePtrRef,
65    ) -> NodePtrRef;
66    /// Create a new leaf node and returns a pointer to it.
67    fn new_leaf_node(&mut self, key: &Key, value: Value) -> NodePtrRef;
68
69    /// Try removing a node from the cache.
70    fn remove_node(&mut self, ptr: NodePtrRef);
71
72    /// Dereference a node pointer into a concrete node object.
73    ///
74    /// Calling this method may invoke the underlying read syncer.
75    /// Giving a None fetcher forces the dereference to be local-only,
76    /// without invoking the read syncer.
77    fn deref_node_ptr<F: ReadSyncFetcher>(
78        &mut self,
79        ptr: NodePtrRef,
80        fetcher: Option<F>,
81    ) -> Result<Option<NodeRef>>;
82    /// Perform a remote sync with the configured remote syncer.
83    fn remote_sync<F: ReadSyncFetcher>(&mut self, ptr: NodePtrRef, fetcher: F) -> Result<()>;
84
85    /// Mark that a tree node was just used.
86    fn use_node(&mut self, ptr: NodePtrRef) -> bool;
87
88    /// Commit a node into the cache.
89    ///
90    /// This method may evict some nodes in order to make space
91    /// for the one being committed.
92    fn commit_node(&mut self, ptr: NodePtrRef);
93
94    // Mark a tree node as no longer being eligible for eviction
95    // due to it becoming dirty.
96    fn rollback_node(&mut self, ptr: NodePtrRef, kind: NodeKind);
97
98    /// Mark the current LRU queue positions as the ones before any nodes are
99    /// visited. Any new nodes committed into the cache after this is called
100    /// will be inserted after the marked position.
101    ///
102    /// This makes it possible to keep the path from the root to the derefed
103    /// node in the cache instead of evicting it.
104    fn mark_position(&mut self);
105}
106
107/// Shorthand for the type that cacheable items must hold to aid caching.
108pub type CacheExtra<T> = Option<NonNull<CacheItemBox<T>>>;
109
110/// Cacheable objects must implement this trait to enable the cache to cache them.
111pub trait CacheItem<Item = Self>
112where
113    Item: CacheItem + Default,
114{
115    /// Get the item's caching hint.
116    ///
117    /// For e.g. the LRU cache, this may be a used timestamp.
118    fn get_cache_extra(&self) -> CacheExtra<Item>;
119    /// Set the item's caching hint.
120    fn set_cache_extra(&mut self, new_val: CacheExtra<Item>);
121    /// Return the size, in bytes, of the item when cached.
122    fn get_cached_size(&self) -> usize;
123}
124
125/// Callback type used for updating cache items after a commit.
126pub type CacheUpdater<C> = Box<dyn Fn(&mut C)>;
127
128/// A list of cache update callbacks.
129pub struct UpdateList<C: Cache> {
130    updates: Vec<CacheUpdater<C>>,
131}
132
133impl<C: Cache> UpdateList<C> {
134    /// Construct a new UpdateList instance.
135    pub fn new() -> UpdateList<C> {
136        UpdateList {
137            updates: Vec::new(),
138        }
139    }
140
141    /// Push a new callback to the end of the list.
142    pub fn push(&mut self, updater: CacheUpdater<C>) {
143        self.updates.push(updater);
144    }
145
146    /// Commit the update list by calling all callbacks in order and destroying the list.
147    pub fn commit(&mut self, cache: &mut C) {
148        for update in &self.updates {
149            (update)(cache);
150        }
151        self.updates.clear();
152    }
153}