use crate::compaction::{Choice, CompactionStrategy, Input, state::CompactionState};
use crate::version::Version;
use crate::{AbstractTree, AnyTree, Config, SeqNo, SequenceNumberCounter, TableId};
use std::sync::Arc;
use test_log::test;
struct Merge(Vec<TableId>, u8);
impl CompactionStrategy for Merge {
fn get_name(&self) -> &'static str {
"MergeTest"
}
fn choose(&self, _: &Version, _: &Config, _: &CompactionState) -> Choice {
Choice::Merge(Input {
table_ids: self.0.iter().copied().collect(),
dest_level: self.1,
canonical_level: self.1,
target_size: u64::MAX,
})
}
}
struct Place(Vec<TableId>, u8);
impl CompactionStrategy for Place {
fn get_name(&self) -> &'static str {
"PlaceTest"
}
fn choose(&self, _: &Version, _: &Config, _: &CompactionState) -> Choice {
Choice::Move(Input {
table_ids: self.0.iter().copied().collect(),
dest_level: self.1,
canonical_level: self.1,
target_size: u64::MAX,
})
}
}
fn level_ids(tree: &AnyTree, level: usize) -> Vec<TableId> {
tree.current_version()
.level(level)
.into_iter()
.flat_map(|level| level.iter())
.flat_map(|run| run.iter())
.map(crate::Table::id)
.collect()
}
#[test]
fn a_move_of_overlapping_runs_keeps_the_newer_version_in_front() -> crate::Result<()> {
let folder = tempfile::tempdir()?;
let tree = Config::new(
folder.path(),
SequenceNumberCounter::default(),
SequenceNumberCounter::default(),
)
.open()?;
tree.insert("a", "a", 1);
tree.insert("k", "old", 2);
tree.flush_active_memtable(0)?;
tree.compact(Arc::new(Merge(level_ids(&tree, 0), 1)), 0)?;
tree.insert("k", "new", 3);
tree.insert("z", "z", 4);
tree.flush_active_memtable(0)?;
tree.compact(Arc::new(Merge(level_ids(&tree, 0), 1)), 0)?;
assert_eq!(
tree.current_version().level(1).expect("L1").run_count(),
2,
"two overlapping runs in L1"
);
assert_eq!(&*tree.get("k", SeqNo::MAX)?.expect("k"), b"new");
tree.compact(Arc::new(Place(level_ids(&tree, 1), 2)), 0)?;
let l2 = tree.current_version();
assert_eq!(l2.level(2).expect("L2").run_count(), 2, "kept apart");
assert_eq!(
&*tree.get("k", SeqNo::MAX)?.expect("k"),
b"new",
"the newer run stays in front"
);
assert_eq!(&*tree.get("a", SeqNo::MAX)?.expect("a"), b"a");
assert_eq!(&*tree.get("z", SeqNo::MAX)?.expect("z"), b"z");
Ok(())
}