commonware_storage/qmdb/any/
mod.rs1use crate::{
13 journal::{
14 authenticated,
15 contiguous::fixed::{Config as JConfig, Journal},
16 },
17 mmr::journaled::Config as MmrConfig,
18 qmdb::{operation::Committable, Error, Merkleized},
19 translator::Translator,
20};
21use commonware_codec::CodecFixedShared;
22use commonware_cryptography::Hasher;
23use commonware_parallel::ThreadPool;
24use commonware_runtime::{buffer::paged::CacheRef, Clock, Metrics, Storage};
25use std::num::{NonZeroU64, NonZeroUsize};
26
27pub(crate) mod db;
28pub(crate) mod operation;
29#[cfg(any(test, feature = "test-traits"))]
30pub mod states;
31pub(crate) mod value;
32pub(crate) use value::{FixedValue, ValueEncoding, VariableValue};
33pub mod ordered;
34pub(crate) mod sync;
35pub mod unordered;
36
37#[derive(Clone)]
39pub struct FixedConfig<T: Translator> {
40 pub mmr_journal_partition: String,
42
43 pub mmr_items_per_blob: NonZeroU64,
45
46 pub mmr_write_buffer: NonZeroUsize,
48
49 pub mmr_metadata_partition: String,
51
52 pub log_journal_partition: String,
54
55 pub log_items_per_blob: NonZeroU64,
57
58 pub log_write_buffer: NonZeroUsize,
60
61 pub translator: T,
63
64 pub thread_pool: Option<ThreadPool>,
66
67 pub page_cache: CacheRef,
69}
70
71#[derive(Clone)]
73pub struct VariableConfig<T: Translator, C> {
74 pub mmr_journal_partition: String,
76
77 pub mmr_items_per_blob: NonZeroU64,
79
80 pub mmr_write_buffer: NonZeroUsize,
82
83 pub mmr_metadata_partition: String,
85
86 pub log_partition: String,
88
89 pub log_write_buffer: NonZeroUsize,
91
92 pub log_compression: Option<u8>,
94
95 pub log_codec_config: C,
97
98 pub log_items_per_blob: NonZeroU64,
100
101 pub translator: T,
103
104 pub thread_pool: Option<ThreadPool>,
106
107 pub page_cache: CacheRef,
109}
110
111type AuthenticatedLog<E, O, H, S = Merkleized<H>> = authenticated::Journal<E, Journal<E, O>, H, S>;
112
113pub(crate) async fn init_fixed_authenticated_log<
116 E: Storage + Clock + Metrics,
117 O: Committable + CodecFixedShared,
118 H: Hasher,
119 T: Translator,
120>(
121 context: E,
122 cfg: FixedConfig<T>,
123) -> Result<AuthenticatedLog<E, O, H>, Error> {
124 let mmr_config = MmrConfig {
125 journal_partition: cfg.mmr_journal_partition,
126 metadata_partition: cfg.mmr_metadata_partition,
127 items_per_blob: cfg.mmr_items_per_blob,
128 write_buffer: cfg.mmr_write_buffer,
129 thread_pool: cfg.thread_pool,
130 page_cache: cfg.page_cache.clone(),
131 };
132
133 let journal_config = JConfig {
134 partition: cfg.log_journal_partition,
135 items_per_blob: cfg.log_items_per_blob,
136 write_buffer: cfg.log_write_buffer,
137 page_cache: cfg.page_cache,
138 };
139
140 let log = AuthenticatedLog::new(
141 context.with_label("log"),
142 mmr_config,
143 journal_config,
144 O::is_commit,
145 )
146 .await?;
147
148 Ok(log)
149}
150
151#[cfg(test)]
152pub(crate) mod test {
154 use super::*;
155 use crate::{
156 qmdb::any::{FixedConfig, VariableConfig},
157 translator::TwoCap,
158 };
159 use commonware_utils::{NZUsize, NZU16, NZU64};
160 use std::num::NonZeroU16;
161
162 const PAGE_SIZE: NonZeroU16 = NZU16!(101);
164 const PAGE_CACHE_SIZE: NonZeroUsize = NZUsize!(11);
165
166 pub(super) fn fixed_db_config(suffix: &str) -> FixedConfig<TwoCap> {
167 FixedConfig {
168 mmr_journal_partition: format!("journal_{suffix}"),
169 mmr_metadata_partition: format!("metadata_{suffix}"),
170 mmr_items_per_blob: NZU64!(11),
171 mmr_write_buffer: NZUsize!(1024),
172 log_journal_partition: format!("log_journal_{suffix}"),
173 log_items_per_blob: NZU64!(7),
174 log_write_buffer: NZUsize!(1024),
175 translator: TwoCap,
176 thread_pool: None,
177 page_cache: CacheRef::new(PAGE_SIZE, PAGE_CACHE_SIZE),
178 }
179 }
180
181 pub(super) fn variable_db_config(suffix: &str) -> VariableConfig<TwoCap, ()> {
182 VariableConfig {
183 mmr_journal_partition: format!("journal_{suffix}"),
184 mmr_metadata_partition: format!("metadata_{suffix}"),
185 mmr_items_per_blob: NZU64!(11),
186 mmr_write_buffer: NZUsize!(1024),
187 log_partition: format!("log_journal_{suffix}"),
188 log_items_per_blob: NZU64!(7),
189 log_write_buffer: NZUsize!(1024),
190 log_compression: None,
191 log_codec_config: (),
192 translator: TwoCap,
193 thread_pool: None,
194 page_cache: CacheRef::new(PAGE_SIZE, PAGE_CACHE_SIZE),
195 }
196 }
197
198 use crate::{
199 kv::Updatable,
200 qmdb::{
201 any::states::{CleanAny, MerkleizedNonDurableAny, MutableAny, UnmerkleizedDurableAny},
202 store::MerkleizedStore,
203 },
204 Persistable,
205 };
206 use commonware_cryptography::{sha256::Digest, Sha256};
207
208 pub(crate) async fn test_any_db_steps_not_reset<D>(db: D)
210 where
211 D: CleanAny<Key = Digest> + MerkleizedStore<Value = Digest, Digest = Digest>,
212 D::Mutable: Updatable<Key = Digest, Value = Digest, Error = crate::qmdb::Error>,
213 {
214 let mut db = db.into_mutable();
216
217 assert!(db
218 .create(Sha256::fill(1u8), Sha256::fill(2u8))
219 .await
220 .unwrap());
221 assert!(db
222 .create(Sha256::fill(3u8), Sha256::fill(4u8))
223 .await
224 .unwrap());
225 let (clean_db, _) = db.commit(None).await.unwrap();
226 let mut db = clean_db.into_mutable();
227
228 db.update(Sha256::fill(1u8), Sha256::fill(5u8))
230 .await
231 .unwrap();
232 let steps = db.steps();
233 assert_ne!(steps, 0);
234
235 let db = db.into_merkleized().await.unwrap();
237 let db = db.into_mutable();
238 assert_eq!(db.steps(), steps);
239
240 let (db, _) = db.commit(None).await.unwrap();
242 let db = db.into_merkleized().await.unwrap();
243 db.destroy().await.unwrap();
244 }
245}