signet_libmdbx/tx/
cache.rs1use crate::Database;
18use parking_lot::RwLock;
19use smallvec::SmallVec;
20use std::{
21 cell::RefCell,
22 hash::{Hash, Hasher},
23 sync::Arc,
24};
25
26pub trait Cache: Clone + Default + std::fmt::Debug {
33 fn read_db(&self, name_hash: u64) -> Option<Database>;
35
36 fn write_db(&self, db: CachedDb);
38
39 fn remove_dbi(&self, dbi: ffi::MDBX_dbi);
41}
42
43#[derive(Debug, Clone, Copy)]
48pub struct CachedDb {
49 name_hash: u64,
51 db: Database,
53}
54
55impl CachedDb {
56 pub(crate) fn new(name: Option<&str>, db: Database) -> Self {
58 let name_hash = Self::hash_name(name);
59 Self { name_hash, db }
60 }
61
62 #[inline]
63 pub(crate) fn hash_name(name: Option<&str>) -> u64 {
64 let mut hasher = std::hash::DefaultHasher::new();
65 name.hash(&mut hasher);
66 hasher.finish()
67 }
68}
69
70impl From<CachedDb> for Database {
71 fn from(value: CachedDb) -> Self {
72 value.db
73 }
74}
75
76#[derive(Debug, Default, Clone)]
80#[repr(transparent)]
81pub struct DbCache(SmallVec<[CachedDb; 16]>);
82
83impl DbCache {
84 fn read_db(&self, name_hash: u64) -> Option<Database> {
86 for entry in self.0.iter() {
87 if entry.name_hash == name_hash {
88 return Some(entry.db);
89 }
90 }
91 None
92 }
93
94 fn write_db(&mut self, db: CachedDb) {
96 for entry in self.0.iter() {
97 if entry.name_hash == db.name_hash {
98 return; }
100 }
101 self.0.push(db);
102 }
103
104 fn remove_dbi(&mut self, dbi: ffi::MDBX_dbi) {
106 self.0.retain(|entry| entry.db.dbi() != dbi);
107 }
108}
109
110#[derive(Debug, Clone)]
114pub struct SharedCache {
115 cache: Arc<RwLock<DbCache>>,
116}
117
118impl SharedCache {
119 fn new() -> Self {
121 Self { cache: Arc::new(RwLock::new(DbCache::default())) }
122 }
123
124 fn read(&self) -> parking_lot::RwLockReadGuard<'_, DbCache> {
126 self.cache.read()
127 }
128
129 fn write(&self) -> parking_lot::RwLockWriteGuard<'_, DbCache> {
131 self.cache.write()
132 }
133}
134
135impl Cache for SharedCache {
136 fn read_db(&self, name_hash: u64) -> Option<Database> {
138 let cache = self.read();
139 cache.read_db(name_hash)
140 }
141
142 fn write_db(&self, db: CachedDb) {
144 let mut cache = self.write();
145 cache.write_db(db);
146 }
147
148 fn remove_dbi(&self, dbi: ffi::MDBX_dbi) {
150 let mut cache = self.write();
151 cache.remove_dbi(dbi);
152 }
153}
154
155impl Default for SharedCache {
156 fn default() -> Self {
157 Self::new()
158 }
159}
160
161impl Cache for RefCell<DbCache> {
162 fn read_db(&self, name_hash: u64) -> Option<Database> {
164 let cache = self.borrow();
165 cache.read_db(name_hash)
166 }
167
168 fn write_db(&self, db: CachedDb) {
170 let mut cache = self.borrow_mut();
171 cache.write_db(db);
172 }
173
174 fn remove_dbi(&self, dbi: ffi::MDBX_dbi) {
176 let mut cache = self.borrow_mut();
177 cache.remove_dbi(dbi);
178 }
179}