2024-01-21 15:26:22 +08:00
|
|
|
use std::{path::Path, sync::Arc};
|
|
|
|
|
|
2024-01-21 11:56:09 +08:00
|
|
|
use anyhow::{bail, Result};
|
|
|
|
|
use bytes::Bytes;
|
|
|
|
|
|
2024-01-21 15:26:22 +08:00
|
|
|
use crate::{
|
|
|
|
|
iterators::StorageIterator,
|
2024-01-25 10:59:08 +08:00
|
|
|
key::KeySlice,
|
2024-01-23 13:44:48 +08:00
|
|
|
lsm_storage::{BlockCache, LsmStorageInner},
|
2024-01-21 15:26:22 +08:00
|
|
|
table::{SsTable, SsTableBuilder},
|
|
|
|
|
};
|
2024-01-21 11:56:09 +08:00
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub struct MockIterator {
|
|
|
|
|
pub data: Vec<(Bytes, Bytes)>,
|
|
|
|
|
pub error_when: Option<usize>,
|
|
|
|
|
pub index: usize,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl MockIterator {
|
|
|
|
|
pub fn new(data: Vec<(Bytes, Bytes)>) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
data,
|
|
|
|
|
index: 0,
|
|
|
|
|
error_when: None,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn new_with_error(data: Vec<(Bytes, Bytes)>, error_when: usize) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
data,
|
|
|
|
|
index: 0,
|
|
|
|
|
error_when: Some(error_when),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl StorageIterator for MockIterator {
|
2024-01-25 10:59:08 +08:00
|
|
|
type KeyType<'a> = KeySlice<'a>;
|
|
|
|
|
|
2024-01-21 11:56:09 +08:00
|
|
|
fn next(&mut self) -> Result<()> {
|
|
|
|
|
if self.index < self.data.len() {
|
|
|
|
|
self.index += 1;
|
|
|
|
|
}
|
|
|
|
|
if let Some(error_when) = self.error_when {
|
|
|
|
|
if self.index == error_when {
|
|
|
|
|
bail!("fake error!");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-25 10:59:08 +08:00
|
|
|
fn key(&self) -> KeySlice {
|
2024-01-21 11:56:09 +08:00
|
|
|
if let Some(error_when) = self.error_when {
|
|
|
|
|
if self.index >= error_when {
|
|
|
|
|
panic!("invalid access after next returns an error!");
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-01-25 10:59:08 +08:00
|
|
|
KeySlice::for_testing_from_slice_no_ts(self.data[self.index].0.as_ref())
|
2024-01-21 11:56:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn value(&self) -> &[u8] {
|
|
|
|
|
if let Some(error_when) = self.error_when {
|
|
|
|
|
if self.index >= error_when {
|
|
|
|
|
panic!("invalid access after next returns an error!");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
self.data[self.index].1.as_ref()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn is_valid(&self) -> bool {
|
|
|
|
|
if let Some(error_when) = self.error_when {
|
|
|
|
|
if self.index >= error_when {
|
|
|
|
|
panic!("invalid access after next returns an error!");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
self.index < self.data.len()
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-01-21 15:26:22 +08:00
|
|
|
|
|
|
|
|
pub fn as_bytes(x: &[u8]) -> Bytes {
|
|
|
|
|
Bytes::copy_from_slice(x)
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-25 10:59:08 +08:00
|
|
|
pub fn check_iter_result_by_key<I>(iter: &mut I, expected: Vec<(Bytes, Bytes)>)
|
|
|
|
|
where
|
|
|
|
|
I: for<'a> StorageIterator<KeyType<'a> = KeySlice<'a>>,
|
|
|
|
|
{
|
|
|
|
|
for (k, v) in expected {
|
|
|
|
|
assert!(iter.is_valid());
|
|
|
|
|
assert_eq!(
|
|
|
|
|
k,
|
|
|
|
|
iter.key().for_testing_key_ref(),
|
|
|
|
|
"expected key: {:?}, actual key: {:?}",
|
|
|
|
|
k,
|
|
|
|
|
as_bytes(iter.key().for_testing_key_ref()),
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
v,
|
|
|
|
|
iter.value(),
|
|
|
|
|
"expected value: {:?}, actual value: {:?}",
|
|
|
|
|
v,
|
|
|
|
|
as_bytes(iter.value()),
|
|
|
|
|
);
|
|
|
|
|
iter.next().unwrap();
|
|
|
|
|
}
|
|
|
|
|
assert!(!iter.is_valid());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn check_lsm_iter_result_by_key<I>(iter: &mut I, expected: Vec<(Bytes, Bytes)>)
|
|
|
|
|
where
|
|
|
|
|
I: for<'a> StorageIterator<KeyType<'a> = &'a [u8]>,
|
|
|
|
|
{
|
2024-01-21 15:26:22 +08:00
|
|
|
for (k, v) in expected {
|
|
|
|
|
assert!(iter.is_valid());
|
|
|
|
|
assert_eq!(
|
|
|
|
|
k,
|
|
|
|
|
iter.key(),
|
|
|
|
|
"expected key: {:?}, actual key: {:?}",
|
|
|
|
|
k,
|
|
|
|
|
as_bytes(iter.key()),
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
v,
|
|
|
|
|
iter.value(),
|
|
|
|
|
"expected value: {:?}, actual value: {:?}",
|
|
|
|
|
v,
|
|
|
|
|
as_bytes(iter.value()),
|
|
|
|
|
);
|
|
|
|
|
iter.next().unwrap();
|
|
|
|
|
}
|
|
|
|
|
assert!(!iter.is_valid());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn expect_iter_error(mut iter: impl StorageIterator) {
|
|
|
|
|
loop {
|
|
|
|
|
match iter.next() {
|
|
|
|
|
Ok(_) if iter.is_valid() => continue,
|
|
|
|
|
Ok(_) => panic!("expect an error"),
|
|
|
|
|
Err(_) => break,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn generate_sst(
|
|
|
|
|
id: usize,
|
|
|
|
|
path: impl AsRef<Path>,
|
|
|
|
|
data: Vec<(Bytes, Bytes)>,
|
|
|
|
|
block_cache: Option<Arc<BlockCache>>,
|
|
|
|
|
) -> SsTable {
|
|
|
|
|
let mut builder = SsTableBuilder::new(128);
|
|
|
|
|
for (key, value) in data {
|
2024-01-25 10:59:08 +08:00
|
|
|
builder.add(KeySlice::for_testing_from_slice_no_ts(&key[..]), &value[..]);
|
2024-01-21 15:26:22 +08:00
|
|
|
}
|
|
|
|
|
builder.build(id, block_cache, path.as_ref()).unwrap()
|
|
|
|
|
}
|
2024-01-23 13:44:48 +08:00
|
|
|
|
|
|
|
|
pub fn sync(storage: &LsmStorageInner) {
|
|
|
|
|
storage
|
|
|
|
|
.force_freeze_memtable(&storage.state_lock.lock())
|
|
|
|
|
.unwrap();
|
|
|
|
|
storage.force_flush_next_imm_memtable().unwrap();
|
2024-01-24 14:32:13 +08:00
|
|
|
}
|