mod storage;
use commonware_runtime::buffer::paged::CacheRef;
use std::num::{NonZeroU64, NonZeroUsize};
pub use storage::Archive;
#[derive(Clone)]
pub struct Config<C> {
pub metadata_partition: String,
pub freezer_table_partition: String,
pub freezer_table_initial_size: u32,
pub freezer_table_resize_frequency: u8,
pub freezer_table_resize_chunk_size: u32,
pub freezer_key_partition: String,
pub freezer_key_page_cache: CacheRef,
pub freezer_value_partition: String,
pub freezer_value_target_size: u64,
pub freezer_value_compression: Option<u8>,
pub ordinal_partition: String,
pub items_per_section: NonZeroU64,
pub freezer_key_write_buffer: NonZeroUsize,
pub freezer_value_write_buffer: NonZeroUsize,
pub ordinal_write_buffer: NonZeroUsize,
pub replay_buffer: NonZeroUsize,
pub codec_config: C,
}
#[cfg(test)]
mod tests {
use super::*;
use crate::archive::Archive as ArchiveTrait;
use commonware_cryptography::{sha256::Digest, Hasher, Sha256};
use commonware_runtime::{buffer::paged::CacheRef, deterministic, Metrics, Runner};
use commonware_utils::{NZUsize, NZU16, NZU64};
use std::num::NonZeroU16;
const PAGE_SIZE: NonZeroU16 = NZU16!(1024);
const PAGE_CACHE_SIZE: NonZeroUsize = NZUsize!(10);
#[test]
fn test_unclean_shutdown() {
let executor = deterministic::Runner::default();
executor.start(|context| async move {
let cfg = Config {
metadata_partition: "test-metadata2".into(),
freezer_table_partition: "test-table2".into(),
freezer_table_initial_size: 8192, freezer_table_resize_frequency: 4,
freezer_table_resize_chunk_size: 8192,
freezer_key_partition: "test-key2".into(),
freezer_key_page_cache: CacheRef::from_pooler(&context, PAGE_SIZE, PAGE_CACHE_SIZE),
freezer_value_partition: "test-value2".into(),
freezer_value_target_size: 1024 * 1024,
freezer_value_compression: Some(3),
ordinal_partition: "test-ordinal2".into(),
items_per_section: NZU64!(512),
freezer_key_write_buffer: NZUsize!(1024),
freezer_value_write_buffer: NZUsize!(1024),
ordinal_write_buffer: NZUsize!(1024),
replay_buffer: NZUsize!(1024),
codec_config: (),
};
let archive: Archive<_, Digest, i32> =
Archive::init(context.with_label("first"), cfg.clone())
.await
.unwrap();
drop(archive);
let mut archive = Archive::init(context.with_label("second"), cfg.clone())
.await
.unwrap();
let key1 = Sha256::hash(b"key1");
let key2 = Sha256::hash(b"key2");
archive.put(1, key1, 2000).await.unwrap();
archive.put(2, key2, 2001).await.unwrap();
archive.sync().await.unwrap();
drop(archive);
let archive = Archive::init(context.with_label("third"), cfg)
.await
.unwrap();
assert_eq!(
archive
.get(crate::archive::Identifier::Key(&key1))
.await
.unwrap(),
Some(2000)
);
assert_eq!(
archive
.get(crate::archive::Identifier::Key(&key2))
.await
.unwrap(),
Some(2001)
);
});
}
#[test]
fn test_sync_empty_archive_then_restart() {
let executor = deterministic::Runner::default();
executor.start(|context| async move {
let cfg = Config {
metadata_partition: "empty-metadata".into(),
freezer_table_partition: "empty-table".into(),
freezer_table_initial_size: 8192,
freezer_table_resize_frequency: 4,
freezer_table_resize_chunk_size: 8192,
freezer_key_partition: "empty-key".into(),
freezer_key_page_cache: CacheRef::from_pooler(&context, PAGE_SIZE, PAGE_CACHE_SIZE),
freezer_value_partition: "empty-value".into(),
freezer_value_target_size: 1024 * 1024,
freezer_value_compression: Some(3),
ordinal_partition: "empty-ordinal".into(),
items_per_section: NZU64!(512),
freezer_key_write_buffer: NZUsize!(1024),
freezer_value_write_buffer: NZUsize!(1024),
ordinal_write_buffer: NZUsize!(1024),
replay_buffer: NZUsize!(1024),
codec_config: (),
};
let mut archive: Archive<_, Digest, i32> =
Archive::init(context.with_label("first"), cfg.clone())
.await
.unwrap();
archive.sync().await.unwrap();
drop(archive);
let mut archive: Archive<_, Digest, i32> =
Archive::init(context.with_label("second"), cfg.clone())
.await
.unwrap();
let key = Sha256::hash(b"after-restart");
archive.put(0, key, 42).await.unwrap();
archive.sync().await.unwrap();
drop(archive);
let archive: Archive<_, Digest, i32> = Archive::init(context.with_label("third"), cfg)
.await
.unwrap();
assert_eq!(
archive
.get(crate::archive::Identifier::Key(&key))
.await
.unwrap(),
Some(42)
);
});
}
}