commonware_storage/qmdb/any/
mod.rs1use crate::{
6 journal::{
7 authenticated,
8 contiguous::fixed::{Config as JConfig, Journal},
9 },
10 mmr::{journaled::Config as MmrConfig, mem::Clean, Location},
11 qmdb::{
12 operation::Committable,
13 store::{CleanStore, DirtyStore},
14 Error,
15 },
16 translator::Translator,
17};
18use commonware_codec::CodecFixed;
19use commonware_cryptography::{DigestOf, Hasher};
20use commonware_runtime::{buffer::PoolRef, Clock, Metrics, Storage, ThreadPool};
21use commonware_utils::Array;
22use std::{
23 future::Future,
24 num::{NonZeroU64, NonZeroUsize},
25 ops::Range,
26};
27
28pub(crate) mod db;
29mod operation;
30
31mod value;
32pub(crate) use value::{FixedValue, ValueEncoding, VariableValue};
33
34mod ext;
35pub mod ordered;
36pub mod unordered;
37
38pub use ext::AnyExt;
39
40pub trait CleanAny:
42 CleanStore<Dirty: DirtyAny<Key = Self::Key, Value = Self::Value, Clean = Self>>
43{
44 type Key: Array;
46
47 fn get(&self, key: &Self::Key) -> impl Future<Output = Result<Option<Self::Value>, Error>>;
49
50 fn commit(
53 &mut self,
54 metadata: Option<Self::Value>,
55 ) -> impl Future<Output = Result<Range<Location>, Error>>;
56
57 fn sync(&mut self) -> impl Future<Output = Result<(), Error>>;
59
60 fn prune(&mut self, prune_loc: Location) -> impl Future<Output = Result<(), Error>>;
62
63 fn close(self) -> impl Future<Output = Result<(), Error>>;
65
66 fn destroy(self) -> impl Future<Output = Result<(), Error>>;
68}
69
70pub trait DirtyAny: DirtyStore {
72 type Key: Array;
74
75 fn get(&self, key: &Self::Key) -> impl Future<Output = Result<Option<Self::Value>, Error>>;
77
78 fn update(
80 &mut self,
81 key: Self::Key,
82 value: Self::Value,
83 ) -> impl Future<Output = Result<(), Error>>;
84
85 fn create(
88 &mut self,
89 key: Self::Key,
90 value: Self::Value,
91 ) -> impl Future<Output = Result<bool, Error>>;
92
93 fn delete(&mut self, key: Self::Key) -> impl Future<Output = Result<bool, Error>>;
96}
97
98#[derive(Clone)]
100pub struct FixedConfig<T: Translator> {
101 pub mmr_journal_partition: String,
103
104 pub mmr_items_per_blob: NonZeroU64,
106
107 pub mmr_write_buffer: NonZeroUsize,
109
110 pub mmr_metadata_partition: String,
112
113 pub log_journal_partition: String,
115
116 pub log_items_per_blob: NonZeroU64,
118
119 pub log_write_buffer: NonZeroUsize,
121
122 pub translator: T,
124
125 pub thread_pool: Option<ThreadPool>,
127
128 pub buffer_pool: PoolRef,
130}
131
132#[derive(Clone)]
134pub struct VariableConfig<T: Translator, C> {
135 pub mmr_journal_partition: String,
137
138 pub mmr_items_per_blob: NonZeroU64,
140
141 pub mmr_write_buffer: NonZeroUsize,
143
144 pub mmr_metadata_partition: String,
146
147 pub log_partition: String,
149
150 pub log_write_buffer: NonZeroUsize,
152
153 pub log_compression: Option<u8>,
155
156 pub log_codec_config: C,
158
159 pub log_items_per_blob: NonZeroU64,
161
162 pub translator: T,
164
165 pub thread_pool: Option<ThreadPool>,
167
168 pub buffer_pool: PoolRef,
170}
171
172type AuthenticatedLog<E, O, H, S = Clean<DigestOf<H>>> =
173 authenticated::Journal<E, Journal<E, O>, H, S>;
174
175pub(crate) async fn init_fixed_authenticated_log<
178 E: Storage + Clock + Metrics,
179 O: Committable + CodecFixed<Cfg = ()>,
180 H: Hasher,
181 T: Translator,
182>(
183 context: E,
184 cfg: FixedConfig<T>,
185) -> Result<AuthenticatedLog<E, O, H>, Error> {
186 let mmr_config = MmrConfig {
187 journal_partition: cfg.mmr_journal_partition,
188 metadata_partition: cfg.mmr_metadata_partition,
189 items_per_blob: cfg.mmr_items_per_blob,
190 write_buffer: cfg.mmr_write_buffer,
191 thread_pool: cfg.thread_pool,
192 buffer_pool: cfg.buffer_pool.clone(),
193 };
194
195 let journal_config = JConfig {
196 partition: cfg.log_journal_partition,
197 items_per_blob: cfg.log_items_per_blob,
198 write_buffer: cfg.log_write_buffer,
199 buffer_pool: cfg.buffer_pool,
200 };
201
202 let log = AuthenticatedLog::new(
203 context.with_label("log"),
204 mmr_config,
205 journal_config,
206 O::is_commit,
207 )
208 .await?;
209
210 Ok(log)
211}
212
213#[cfg(test)]
214mod test {
215 use super::*;
216 use crate::{
217 qmdb::any::{FixedConfig, VariableConfig},
218 translator::TwoCap,
219 };
220 use commonware_utils::{NZUsize, NZU64};
221
222 const PAGE_SIZE: usize = 101;
224 const PAGE_CACHE_SIZE: usize = 11;
225
226 pub(super) fn fixed_db_config(suffix: &str) -> FixedConfig<TwoCap> {
227 FixedConfig {
228 mmr_journal_partition: format!("journal_{suffix}"),
229 mmr_metadata_partition: format!("metadata_{suffix}"),
230 mmr_items_per_blob: NZU64!(11),
231 mmr_write_buffer: NZUsize!(1024),
232 log_journal_partition: format!("log_journal_{suffix}"),
233 log_items_per_blob: NZU64!(7),
234 log_write_buffer: NZUsize!(1024),
235 translator: TwoCap,
236 thread_pool: None,
237 buffer_pool: PoolRef::new(NZUsize!(PAGE_SIZE), NZUsize!(PAGE_CACHE_SIZE)),
238 }
239 }
240
241 pub(super) fn variable_db_config(suffix: &str) -> VariableConfig<TwoCap, ()> {
242 VariableConfig {
243 mmr_journal_partition: format!("journal_{suffix}"),
244 mmr_metadata_partition: format!("metadata_{suffix}"),
245 mmr_items_per_blob: NZU64!(11),
246 mmr_write_buffer: NZUsize!(1024),
247 log_partition: format!("log_journal_{suffix}"),
248 log_items_per_blob: NZU64!(7),
249 log_write_buffer: NZUsize!(1024),
250 log_compression: None,
251 log_codec_config: (),
252 translator: TwoCap,
253 thread_pool: None,
254 buffer_pool: PoolRef::new(NZUsize!(PAGE_SIZE), NZUsize!(PAGE_CACHE_SIZE)),
255 }
256 }
257}