commonware_storage/qmdb/immutable/sync/
mod.rs1use crate::{
2 Context,
3 journal::{authenticated, contiguous::Mutable},
4 merkle::{
5 Family, Location,
6 full::{self, Merkle},
7 },
8 qmdb::{
9 self, Error,
10 any::ValueEncoding,
11 immutable::{self, CompactDb, Metrics, Operation},
12 operation::Key,
13 sync,
14 },
15 translator::Translator,
16};
17use commonware_codec::{EncodeShared, Read};
18use commonware_cryptography::Hasher;
19use commonware_parallel::Strategy;
20use commonware_utils::range::NonEmptyRange;
21use std::num::NonZeroU64;
22
23impl<F, E, K, V, C, H, T, S> sync::Database for immutable::Immutable<F, E, K, V, C, H, T, S>
24where
25 F: Family,
26 E: Context,
27 K: Key,
28 V: ValueEncoding,
29 C: Mutable<Item = Operation<F, K, V>> + sync::Journal<F, Context = E, Op = Operation<F, K, V>>,
30 C::Item: EncodeShared,
31 H: Hasher,
32 T: Translator,
33 S: Strategy,
34{
35 type Family = F;
36 type Op = Operation<F, K, V>;
37 type Journal = C;
38 type Hasher = H;
39 type Config = immutable::Config<T, C::Config, S>;
40 type Digest = H::Digest;
41 type Context = E;
42
43 async fn from_sync_result(
61 context: Self::Context,
62 db_config: Self::Config,
63 log: Self::Journal,
64 pinned_nodes: Option<Vec<Self::Digest>>,
65 range: NonEmptyRange<Location<F>>,
66 apply_batch_size: NonZeroU64,
67 ) -> Result<Self, Error<F>> {
68 let hasher = qmdb::hasher::<H>();
69
70 let merkle = Merkle::<F, _, _, S>::init_sync(
72 context.child("merkle"),
73 full::SyncConfig {
74 config: db_config.merkle_config,
75 range: range.clone(),
76 pinned_nodes,
77 },
78 )
79 .await?;
80
81 let journal = authenticated::Journal::<_, _, _, _, S>::from_components(
82 merkle,
83 log,
84 hasher,
85 apply_batch_size,
86 )
87 .await?;
88
89 let size = journal.size();
92 if size == 0 {
93 return Err(Error::HistoricalFloorPruned(size));
94 }
95 let inactivity_floor_loc =
96 crate::qmdb::find_inactivity_floor_at::<F, _>(&journal.journal, size).await?;
97
98 let snapshot = immutable::build_snapshot(
100 context.child("snapshot"),
101 db_config.translator,
102 inactivity_floor_loc,
103 &journal.journal,
104 db_config.init_buffer,
105 )
106 .await?;
107 let inactive_peaks = F::inactive_peaks(size, inactivity_floor_loc);
108 let root = journal.root(inactive_peaks)?;
109
110 let metrics = Metrics::new(context);
111 let db = Self {
112 journal,
113 root,
114 snapshot,
115 inactivity_floor_loc,
116 metrics,
117 };
118 db.update_metrics();
119
120 db.sync().await
121 }
122
123 async fn persist_sync_result(self) -> Result<Self, Error<F>> {
124 Ok(self)
125 }
126
127 async fn local_pinned_nodes(
128 context: Self::Context,
129 config: &Self::Config,
130 target: &sync::Target<F, Self::Digest>,
131 journal: &Self::Journal,
132 ) -> Result<Option<Vec<Self::Digest>>, Error<F>> {
133 if target.range.start() == Location::new(0)
134 || !sync::journal_covers_range(journal.bounds(), &target.range)
135 {
136 return Ok(None);
137 }
138
139 let inactivity_floor =
142 qmdb::find_inactivity_floor_at::<F, _>(journal, target.range.end()).await?;
143
144 sync::local_pinned_nodes::<F, _, H, S>(
145 context,
146 config.merkle_config.clone(),
147 target,
148 inactivity_floor,
149 )
150 .await
151 }
152
153 fn root(&self) -> Self::Digest {
154 self.root()
155 }
156}
157
158impl<F, E, K, V, H, S> sync::Database for CompactDb<F, E, K, V, H, S>
159where
160 F: Family,
161 E: Context,
162 K: Key,
163 V: ValueEncoding,
164 H: Hasher,
165 S: Strategy,
166 Operation<F, K, V>: EncodeShared,
167 Operation<F, K, V>: Read,
168{
169 type Family = F;
170 type Op = Operation<F, K, V>;
171 type Journal = sync::journal::Memory<F, E, Operation<F, K, V>>;
172 type Config = immutable::CompactConfig<<Operation<F, K, V> as Read>::Cfg, S>;
173 type Digest = H::Digest;
174 type Context = E;
175 type Hasher = H;
176
177 async fn from_sync_result(
178 context: Self::Context,
179 config: Self::Config,
180 log: Self::Journal,
181 pinned_nodes: Option<Vec<Self::Digest>>,
182 range: NonEmptyRange<Location<F>>,
183 _apply_batch_size: NonZeroU64,
184 ) -> Result<Self, Error<F>> {
185 crate::qmdb::compact::from_sync_result(
186 context,
187 config,
188 log,
189 pinned_nodes,
190 range,
191 Self::init_from_sync,
192 )
193 .await
194 }
195
196 async fn persist_sync_result(self) -> Result<Self, Error<F>> {
197 self.sync().await
198 }
199
200 async fn local_pinned_nodes(
201 _context: Self::Context,
202 _config: &Self::Config,
203 _target: &sync::Target<F, Self::Digest>,
204 _journal: &Self::Journal,
205 ) -> Result<Option<Vec<Self::Digest>>, Error<F>> {
206 Ok(None)
207 }
208
209 fn root(&self) -> Self::Digest {
210 self.root()
211 }
212}
213
214#[cfg(test)]
215mod tests;