#[cfg(any(test, feature = "test-traits"))] use crate::qmdb::any::traits::PersistableMutableLog; use crate::{ index::Unordered as Index, journal::contiguous::{Contiguous, Mutable, Reader}, merkle::{Family, Location}, qmdb::{ any::{ db::{AuthenticatedLog, Db}, ValueEncoding, }, build_snapshot_from_log, operation::{Committable, Key, Operation as OperationTrait}, }, Context, }; use commonware_codec::Codec; use commonware_cryptography::Hasher; pub mod fixed; pub mod variable; pub use crate::qmdb::any::operation::{update::Unordered as Update, Unordered as Operation}; impl< F: Family, E: Context, K: Key, V: ValueEncoding, C: Contiguous>, I: Index>, H: Hasher, > Db> where Operation: Codec, { /// Returns the value for `key` and its location, or None if the key is not active. pub(crate) async fn get_with_loc( &self, key: &K, ) -> Result)>, crate::qmdb::Error> { // Collect to avoid holding a borrow across await points (rust-lang/rust#100013). let locs: Vec> = self.snapshot.get(key).copied().collect(); let reader = self.log.reader().await; for loc in locs { let op = reader.read(*loc).await?; match &op { Operation::Update(Update(k, value)) => { if k == key { return Ok(Some((value.clone(), loc))); } } _ => unreachable!("location {loc} does not reference update operation"), } } Ok(None) } } impl< F: Family, E: Context, C: Mutable, O: OperationTrait + Codec + Committable + Send + Sync, I: Index>, H: Hasher, U: Send + Sync, > Db { /// Returns an [Db] initialized directly from the given components. The log is /// replayed from `inactivity_floor_loc` to build the snapshot, and that value is used as the /// inactivity floor. The last operation is assumed to be a commit. pub(crate) async fn from_components( inactivity_floor_loc: Location, log: AuthenticatedLog, mut snapshot: I, ) -> Result> { let (active_keys, last_commit_loc) = { let reader = log.reader().await; let active_keys = build_snapshot_from_log(inactivity_floor_loc, &reader, &mut snapshot, |_, _| {}) .await?; let last_commit_loc = Location::new( reader .bounds() .end .checked_sub(1) .expect("commit should exist"), ); assert!(reader.read(*last_commit_loc).await?.is_commit()); (active_keys, last_commit_loc) }; Ok(Self { log, inactivity_floor_loc, snapshot, last_commit_loc, active_keys, _update: core::marker::PhantomData, }) } } #[cfg(any(test, feature = "test-traits"))] crate::qmdb::any::traits::impl_db_any! { [E, K, V, C, I, H] Db> where { E: Context, K: Key, V: ValueEncoding + 'static, C: PersistableMutableLog>, I: Index + Send + Sync + 'static, H: Hasher, Operation: Codec, V::Value: Send + Sync, } Family = crate::merkle::mmr::Family, Key = K, Value = V::Value, Digest = H::Digest } #[cfg(any(test, feature = "test-traits"))] crate::qmdb::any::traits::impl_provable! { [E, K, V, C, I, H] Db> where { E: Context, K: Key, V: ValueEncoding + 'static, C: PersistableMutableLog>, I: Index + Send + Sync + 'static, H: Hasher, Operation: Codec, V::Value: Send + Sync, } Family = crate::merkle::mmr::Family, Operation = Operation } #[cfg(any(test, feature = "test-traits"))] crate::qmdb::any::traits::impl_db_any! { [E, K, V, C, I, H] Db> where { E: Context, K: Key, V: ValueEncoding + 'static, C: PersistableMutableLog>, I: Index> + Send + Sync + 'static, H: Hasher, Operation: Codec, V::Value: Send + Sync, } Family = crate::merkle::mmb::Family, Key = K, Value = V::Value, Digest = H::Digest } #[cfg(any(test, feature = "test-traits"))] crate::qmdb::any::traits::impl_provable! { [E, K, V, C, I, H] Db> where { E: Context, K: Key, V: ValueEncoding + 'static, C: PersistableMutableLog>, I: Index> + Send + Sync + 'static, H: Hasher, Operation: Codec, V::Value: Send + Sync, } Family = crate::merkle::mmb::Family, Operation = Operation }