1use kvdb::{DBTransaction, KeyValueDB};
24use parking_lot::RwLock;
25use std::{collections::HashMap, hash::Hash, ops::Deref};
26
27use rlp;
28
29pub const COL_MISC: u32 = 0;
32pub const COL_BLOCKS: u32 = 1;
34pub const COL_TX_INDEX: u32 = 2;
36pub const COL_EPOCH_NUMBER: u32 = 3;
38pub const COL_BLAMED_HEADER_VERIFIED_ROOTS: u32 = 4;
40pub const COL_BLOCK_TRACES: u32 = 5;
42pub const COL_HASH_BY_BLOCK_NUMBER: u32 = 6;
44pub const COL_REWARD_BY_POS_EPOCH: u32 = 7;
46pub const NUM_COLUMNS: u32 = 8;
48
49#[derive(Clone, Copy)]
51pub enum CacheUpdatePolicy {
52 Overwrite,
54 Invalidate,
56}
57
58pub trait Cache<K, V> {
60 fn insert(&mut self, k: K, v: V) -> Option<V>;
62
63 fn invalidate(&mut self, k: &K) -> Option<V>;
65
66 fn get(&self, k: &K) -> Option<&V>;
68}
69
70impl<K, V> Cache<K, V> for HashMap<K, V>
71where K: Hash + Eq
72{
73 fn insert(&mut self, k: K, v: V) -> Option<V> {
74 HashMap::insert(self, k, v)
75 }
76
77 fn invalidate(&mut self, k: &K) -> Option<V> { HashMap::remove(self, k) }
78
79 fn get(&self, k: &K) -> Option<&V> { HashMap::get(self, k) }
80}
81
82pub trait Key<T> {
84 type Target: Deref<Target = [u8]>;
86
87 fn key(&self) -> Self::Target;
89}
90
91pub trait Writable {
93 fn write<T, R>(
95 &mut self, col: u32, key: &dyn Key<T, Target = R>, value: &T,
96 ) where
97 T: rlp::Encodable,
98 R: Deref<Target = [u8]>;
99
100 fn delete<T, R>(&mut self, col: u32, key: &dyn Key<T, Target = R>)
102 where
103 T: rlp::Encodable,
104 R: Deref<Target = [u8]>;
105
106 fn write_with_cache<K, T, R>(
108 &mut self, col: u32, cache: &mut dyn Cache<K, T>, key: K, value: T,
109 policy: CacheUpdatePolicy,
110 ) where
111 K: Key<T, Target = R> + Hash + Eq,
112 T: rlp::Encodable,
113 R: Deref<Target = [u8]>,
114 {
115 self.write(col, &key, &value);
116 match policy {
117 CacheUpdatePolicy::Overwrite => {
118 cache.insert(key, value);
119 }
120 CacheUpdatePolicy::Invalidate => {
121 cache.invalidate(&key);
122 }
123 }
124 }
125
126 fn extend_with_cache<K, T, R>(
128 &mut self, col: u32, cache: &mut dyn Cache<K, T>,
129 values: HashMap<K, T>, policy: CacheUpdatePolicy,
130 ) where
131 K: Key<T, Target = R> + Hash + Eq,
132 T: rlp::Encodable,
133 R: Deref<Target = [u8]>,
134 {
135 match policy {
136 CacheUpdatePolicy::Overwrite => {
137 for (key, value) in values {
138 self.write(col, &key, &value);
139 cache.insert(key, value);
140 }
141 }
142 CacheUpdatePolicy::Invalidate => {
143 for (key, value) in &values {
144 self.write(col, key, value);
145 cache.invalidate(key);
146 }
147 }
148 }
149 }
150
151 fn extend_with_option_cache<K, T, R>(
153 &mut self, col: u32, cache: &mut dyn Cache<K, Option<T>>,
154 values: HashMap<K, Option<T>>, policy: CacheUpdatePolicy,
155 ) where
156 K: Key<T, Target = R> + Hash + Eq,
157 T: rlp::Encodable,
158 R: Deref<Target = [u8]>,
159 {
160 match policy {
161 CacheUpdatePolicy::Overwrite => {
162 for (key, value) in values {
163 match value {
164 Some(ref v) => self.write(col, &key, v),
165 None => self.delete(col, &key),
166 }
167 cache.insert(key, value);
168 }
169 }
170 CacheUpdatePolicy::Invalidate => {
171 for (key, value) in values {
172 match value {
173 Some(v) => self.write(col, &key, &v),
174 None => self.delete(col, &key),
175 }
176 cache.invalidate(&key);
177 }
178 }
179 }
180 }
181}
182
183pub trait Readable {
185 fn read<T, R>(&self, col: u32, key: &dyn Key<T, Target = R>) -> Option<T>
187 where
188 T: rlp::Decodable,
189 R: Deref<Target = [u8]>;
190
191 fn read_with_cache<K, T, C>(
193 &self, col: u32, cache: &RwLock<C>, key: &K,
194 ) -> Option<T>
195 where
196 K: Key<T> + Eq + Hash + Clone,
197 T: Clone + rlp::Decodable,
198 C: Cache<K, T>,
199 {
200 {
201 let read = cache.read();
202 if let Some(v) = read.get(key) {
203 return Some(v.clone());
204 }
205 }
206
207 self.read(col, key).map(|value: T| {
208 let mut write = cache.write();
209 write.insert(key.clone(), value.clone());
210 value
211 })
212 }
213
214 fn exists<T, R>(&self, col: u32, key: &dyn Key<T, Target = R>) -> bool
216 where R: Deref<Target = [u8]>;
217
218 fn exists_with_cache<K, T, R, C>(
220 &self, col: u32, cache: &RwLock<C>, key: &K,
221 ) -> bool
222 where
223 K: Eq + Hash + Key<T, Target = R>,
224 R: Deref<Target = [u8]>,
225 C: Cache<K, T>,
226 {
227 {
228 let read = cache.read();
229 if read.get(key).is_some() {
230 return true;
231 }
232 }
233
234 self.exists::<T, R>(col, key)
235 }
236}
237
238impl Writable for DBTransaction {
239 fn write<T, R>(&mut self, col: u32, key: &dyn Key<T, Target = R>, value: &T)
240 where
241 T: rlp::Encodable,
242 R: Deref<Target = [u8]>,
243 {
244 self.put(col, &key.key(), &rlp::encode(value));
245 }
246
247 fn delete<T, R>(&mut self, col: u32, key: &dyn Key<T, Target = R>)
248 where
249 T: rlp::Encodable,
250 R: Deref<Target = [u8]>,
251 {
252 self.delete(col, &key.key());
253 }
254}
255
256impl<KVDB: KeyValueDB + ?Sized> Readable for KVDB {
257 fn read<T, R>(&self, col: u32, key: &dyn Key<T, Target = R>) -> Option<T>
258 where
259 T: rlp::Decodable,
260 R: Deref<Target = [u8]>,
261 {
262 self.get(col, &key.key())
263 .unwrap_or_else(|_| {
264 panic!("db get failed, key: {:?}", &key.key() as &[u8])
265 })
266 .map(|v| rlp::decode(&v).expect("decode db value failed"))
267 }
268
269 fn exists<T, R>(&self, col: u32, key: &dyn Key<T, Target = R>) -> bool
270 where R: Deref<Target = [u8]> {
271 let result = self.get(col, &key.key());
272
273 match result {
274 Ok(v) => v.is_some(),
275 Err(err) => {
276 panic!(
277 "db get failed, key: {:?}, err: {:?}",
278 &key.key() as &[u8],
279 err
280 );
281 }
282 }
283 }
284}