mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-08-12 02:03:09 -07:00
180 lines
4.9 KiB
Rust
180 lines
4.9 KiB
Rust
//! Rollback of stamps that included a `truncate_if_needed_at` shrink.
|
|
//! (The `rollback_with_truncation` test in `tests/rollback.rs` is misnamed —
|
|
//! it never actually calls `truncate_if_needed_at`.)
|
|
|
|
use rawdb::Database;
|
|
use tempfile::TempDir;
|
|
use vecdb::{ImportOptions, Result, Stamp, StoredVec, Version};
|
|
|
|
fn setup_db() -> Result<(Database, TempDir)> {
|
|
let temp = TempDir::new()?;
|
|
let db = Database::open(temp.path())?;
|
|
Ok((db, temp))
|
|
}
|
|
|
|
fn import_with_changes<V>(db: &Database, name: &str, changes: u16) -> Result<V>
|
|
where
|
|
V: StoredVec<I = usize, T = u32>,
|
|
{
|
|
let mut options: ImportOptions = (db, name, Version::TWO).into();
|
|
options = options.with_saved_stamped_changes(changes);
|
|
V::forced_import_with(options)
|
|
}
|
|
|
|
fn run_rollback_after_pure_truncate<V>() -> Result<()>
|
|
where
|
|
V: StoredVec<I = usize, T = u32>,
|
|
{
|
|
let (db, _temp) = setup_db()?;
|
|
let mut vec = import_with_changes::<V>(&db, "pure_truncate", 10)?;
|
|
|
|
for i in 0..8 {
|
|
vec.push(i);
|
|
}
|
|
vec.stamped_write_with_changes(Stamp::new(1))?;
|
|
assert_eq!(vec.len(), 8);
|
|
assert_eq!(vec.collect(), (0..8).collect::<Vec<u32>>());
|
|
|
|
vec.truncate_if_needed_at(5)?;
|
|
vec.stamped_write_with_changes(Stamp::new(2))?;
|
|
assert_eq!(vec.len(), 5);
|
|
assert_eq!(vec.collect(), (0..5).collect::<Vec<u32>>());
|
|
|
|
vec.rollback()?;
|
|
assert_eq!(vec.len(), 8, "len mismatch after rollback of truncation");
|
|
assert_eq!(
|
|
vec.collect(),
|
|
(0..8).collect::<Vec<u32>>(),
|
|
"data mismatch after rollback of truncation"
|
|
);
|
|
assert_eq!(vec.stamp(), Stamp::new(1));
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn run_rollback_after_truncate_and_push<V>() -> Result<()>
|
|
where
|
|
V: StoredVec<I = usize, T = u32>,
|
|
{
|
|
let (db, _temp) = setup_db()?;
|
|
let mut vec = import_with_changes::<V>(&db, "truncate_push", 10)?;
|
|
|
|
for i in 0..5 {
|
|
vec.push(i);
|
|
}
|
|
vec.stamped_write_with_changes(Stamp::new(1))?;
|
|
|
|
vec.truncate_if_needed_at(3)?;
|
|
vec.push(100);
|
|
vec.push(200);
|
|
vec.stamped_write_with_changes(Stamp::new(2))?;
|
|
assert_eq!(vec.len(), 5);
|
|
assert_eq!(vec.collect(), vec![0, 1, 2, 100, 200]);
|
|
|
|
vec.rollback()?;
|
|
assert_eq!(vec.len(), 5, "len mismatch after rollback");
|
|
assert_eq!(
|
|
vec.collect(),
|
|
vec![0, 1, 2, 3, 4],
|
|
"data mismatch after rollback"
|
|
);
|
|
assert_eq!(vec.stamp(), Stamp::new(1));
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn run_rollback_truncate_then_reflush<V>() -> Result<()>
|
|
where
|
|
V: StoredVec<I = usize, T = u32>,
|
|
{
|
|
let (db, _temp) = setup_db()?;
|
|
let mut vec = import_with_changes::<V>(&db, "truncate_reflush", 10)?;
|
|
|
|
for i in 0..10 {
|
|
vec.push(i);
|
|
}
|
|
vec.stamped_write_with_changes(Stamp::new(1))?;
|
|
|
|
vec.truncate_if_needed_at(4)?;
|
|
vec.stamped_write_with_changes(Stamp::new(2))?;
|
|
assert_eq!(vec.len(), 4);
|
|
|
|
vec.rollback()?;
|
|
assert_eq!(vec.len(), 10);
|
|
assert_eq!(vec.collect(), (0..10).collect::<Vec<u32>>());
|
|
|
|
vec.stamped_write_with_changes(Stamp::new(2))?;
|
|
assert_eq!(vec.len(), 10);
|
|
assert_eq!(vec.stored_len(), 10);
|
|
assert_eq!(vec.collect(), (0..10).collect::<Vec<u32>>());
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn run_rollback_truncate_persistence<V>() -> Result<()>
|
|
where
|
|
V: StoredVec<I = usize, T = u32>,
|
|
{
|
|
let (db, _temp) = setup_db()?;
|
|
{
|
|
let mut vec = import_with_changes::<V>(&db, "persist", 10)?;
|
|
for i in 0..7 {
|
|
vec.push(i);
|
|
}
|
|
vec.stamped_write_with_changes(Stamp::new(1))?;
|
|
|
|
vec.truncate_if_needed_at(2)?;
|
|
vec.stamped_write_with_changes(Stamp::new(2))?;
|
|
|
|
vec.rollback()?;
|
|
vec.stamped_write_with_changes(Stamp::new(1))?;
|
|
}
|
|
{
|
|
let vec = import_with_changes::<V>(&db, "persist", 10)?;
|
|
assert_eq!(vec.len(), 7);
|
|
assert_eq!(vec.collect(), (0..7).collect::<Vec<u32>>());
|
|
assert_eq!(vec.stamp(), Stamp::new(1));
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
macro_rules! instantiate_for {
|
|
($mod:ident, $ty:ty) => {
|
|
mod $mod {
|
|
use super::*;
|
|
type V = $ty;
|
|
|
|
#[test]
|
|
fn rollback_after_pure_truncate() -> Result<()> {
|
|
run_rollback_after_pure_truncate::<V>()
|
|
}
|
|
#[test]
|
|
fn rollback_after_truncate_and_push() -> Result<()> {
|
|
run_rollback_after_truncate_and_push::<V>()
|
|
}
|
|
#[test]
|
|
fn rollback_truncate_then_reflush() -> Result<()> {
|
|
run_rollback_truncate_then_reflush::<V>()
|
|
}
|
|
#[test]
|
|
fn rollback_truncate_persistence() -> Result<()> {
|
|
run_rollback_truncate_persistence::<V>()
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
instantiate_for!(bytes, vecdb::BytesVec<usize, u32>);
|
|
|
|
#[cfg(feature = "zerocopy")]
|
|
instantiate_for!(zerocopy, vecdb::ZeroCopyVec<usize, u32>);
|
|
|
|
#[cfg(feature = "pco")]
|
|
instantiate_for!(pco, vecdb::PcoVec<usize, u32>);
|
|
|
|
#[cfg(feature = "lz4")]
|
|
instantiate_for!(lz4, vecdb::LZ4Vec<usize, u32>);
|
|
|
|
#[cfg(feature = "zstd")]
|
|
instantiate_for!(zstd, vecdb::ZstdVec<usize, u32>);
|