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}