use std::collections::HashMap;
use crate::snapshot::SnapshotIterator;
use crate::vlog::ValueLocation;
use crate::{InternalKey, Key, LSMIterator, Result, Value};
#[cfg(test)]
pub mod batch_tests;
#[cfg(test)]
pub mod block_tests;
#[cfg(test)]
pub mod compaction_tests;
#[cfg(test)]
pub mod compression_tests;
#[cfg(test)]
pub mod index_block_tests;
#[cfg(test)]
pub mod iterator_tests;
#[cfg(test)]
pub mod level_tests;
#[cfg(test)]
pub mod lsm_tests;
#[cfg(test)]
pub mod manifest_tests;
#[cfg(test)]
pub mod memtable_tests;
#[cfg(test)]
pub mod recovery_integration_tests;
#[cfg(test)]
pub mod recovery_test_helpers;
#[cfg(test)]
pub mod recovery_tests;
#[cfg(test)]
pub mod snapshot_tests;
#[cfg(test)]
pub mod sstable_tests;
#[cfg(test)]
pub mod stall_tests;
#[cfg(test)]
pub mod transaction_tests;
#[cfg(test)]
pub mod version_iterator_tests;
#[cfg(test)]
pub mod vlog_tests;
#[cfg(test)]
pub mod wal_tests;
fn collect_iter(iter: &mut impl LSMIterator) -> Vec<(InternalKey, Vec<u8>)> {
let mut result = Vec::new();
while iter.valid() {
result.push((iter.key().to_owned(), iter.value_encoded().unwrap().to_vec()));
if !iter.next().unwrap_or(false) {
break;
}
}
result
}
fn collect_all(iter: &mut impl LSMIterator) -> Result<Vec<(InternalKey, Vec<u8>)>> {
iter.seek_first()?;
Ok(collect_iter(iter))
}
fn count_iter(iter: &mut impl LSMIterator) -> Result<usize> {
iter.seek_first()?;
let mut count = 0;
while iter.valid() {
count += 1;
if !iter.next()? {
break;
}
}
Ok(count)
}
fn collect_transaction_iter(iter: &mut impl LSMIterator) -> Result<Vec<(Vec<u8>, Vec<u8>)>> {
let mut result = Vec::new();
while iter.valid() {
let key = iter.key().user_key().to_vec();
let value = iter.value()?;
result.push((key, value));
iter.next()?;
}
Ok(result)
}
fn collect_transaction_all(iter: &mut impl LSMIterator) -> Result<Vec<(Vec<u8>, Vec<u8>)>> {
iter.seek_first()?;
collect_transaction_iter(iter)
}
fn collect_transaction_reverse(iter: &mut impl LSMIterator) -> Result<Vec<(Vec<u8>, Vec<u8>)>> {
iter.seek_last()?;
let mut result = Vec::new();
while iter.valid() {
let key = iter.key().user_key().to_vec();
let value = iter.value()?;
result.push((key, value));
if !iter.prev()? {
break;
}
}
Ok(result)
}
fn collect_snapshot_iter(iter: &mut SnapshotIterator) -> Result<Vec<(InternalKey, Vec<u8>)>> {
iter.seek_first()?;
let mut result = Vec::new();
while iter.valid() {
let encoded_value = iter.value_encoded()?;
let decoded_value = ValueLocation::decode(encoded_value)?.value;
result.push((iter.key().to_owned(), decoded_value));
if !iter.next()? {
break;
}
}
Ok(result)
}
fn collect_snapshot_reverse(iter: &mut SnapshotIterator) -> Result<Vec<(InternalKey, Vec<u8>)>> {
iter.seek_last()?;
let mut result = Vec::new();
while iter.valid() {
let encoded_value = iter.value_encoded()?;
let decoded_value = ValueLocation::decode(encoded_value)?.value;
result.push((iter.key().to_owned(), decoded_value));
if !iter.prev()? {
break;
}
}
Ok(result)
}
#[allow(dead_code)]
type KeyVersionsMap = HashMap<Key, Vec<(Vec<u8>, u64, bool)>>;
#[allow(dead_code)]
fn collect_history_all(iter: &mut impl LSMIterator) -> crate::Result<Vec<(Key, Value, u64, bool)>> {
iter.seek_first()?;
let mut result = Vec::new();
while iter.valid() {
let key_ref = iter.key();
let is_tombstone = key_ref.is_tombstone();
let value = if is_tombstone {
Vec::new()
} else {
iter.value()?
};
result.push((key_ref.user_key().to_vec(), value, key_ref.timestamp(), is_tombstone));
iter.next()?;
}
Ok(result)
}
#[allow(dead_code)]
fn point_in_time_from_history(
iter: &mut impl LSMIterator,
timestamp: u64,
) -> crate::Result<Vec<(Key, Value)>> {
use std::collections::BTreeMap;
iter.seek_first()?;
let mut latest_entries: BTreeMap<Key, (Option<Value>, u64, bool)> = BTreeMap::new();
while iter.valid() {
let key_ref = iter.key();
let ts = key_ref.timestamp();
let key = key_ref.user_key().to_vec();
let is_tombstone = key_ref.is_tombstone();
if ts <= timestamp {
let should_update = match latest_entries.get(&key) {
None => true,
Some((_, existing_ts, _)) => ts > *existing_ts,
};
if should_update {
let value = if is_tombstone {
None
} else {
Some(iter.value()?)
};
latest_entries.insert(key.clone(), (value, ts, is_tombstone));
}
}
iter.next()?;
}
Ok(latest_entries
.into_iter()
.filter_map(|(k, (v, _, is_tombstone))| {
if is_tombstone {
None
} else {
Some((k, v.unwrap()))
}
})
.collect())
}