use crate::{Hasher, Key, Value};
use commonware_parallel::Sequential;
use commonware_runtime::{BufferPooler, Clock, Metrics, Storage};
use commonware_storage::{
merkle::{
compact::Config as MerkleConfig,
mmr::{self},
},
qmdb::{
self,
immutable::fixed::{self, CompactConfig},
sync::compact,
},
};
use tracing::error;
pub type Database<E> = fixed::CompactDb<mmr::Family, E, Key, Value, Hasher, Sequential>;
pub type Operation = fixed::Operation<mmr::Family, Key, Value>;
pub fn create_config(_context: &impl BufferPooler) -> CompactConfig<Sequential> {
CompactConfig {
merkle: MerkleConfig {
partition: "compact-immutable".into(),
strategy: Sequential,
},
commit_codec_config: (),
}
}
impl<E> super::ExampleDatabase for Database<E>
where
E: Storage + Clock + Metrics,
{
type Family = mmr::Family;
type Operation = Operation;
fn create_test_operations(count: usize, seed: u64, starting_loc: u64) -> Vec<Self::Operation> {
super::immutable::create_test_operations(count, seed, starting_loc)
}
async fn add_operations(
&mut self,
operations: Vec<Self::Operation>,
) -> Result<(), qmdb::Error<mmr::Family>> {
let Some(last) = operations.last() else {
error!("operations must end with a commit");
return Ok(());
};
if !matches!(last, Operation::Commit(..)) {
error!("operations must end with a commit");
return Ok(());
}
let mut batch = self.new_batch();
for operation in operations {
match operation {
Operation::Set(key, value) => {
batch = batch.set(key, value);
}
Operation::Commit(metadata, floor) => {
let merkleized = batch.merkleize(self, metadata, floor);
self.apply_batch(merkleized)?;
self.commit().await?;
batch = self.new_batch();
}
}
}
Ok(())
}
fn current_floor(&self) -> u64 {
*Self::inactivity_floor_loc(self)
}
fn root(&self) -> Key {
Self::root(self)
}
fn name() -> &'static str {
"compact immutable"
}
}
impl<E> super::CompactSyncable for Database<E>
where
E: Storage + Clock + Metrics,
{
async fn current_target(&self) -> compact::Target<Self::Family, Key> {
Self::current_target(self)
}
}