@@ -1,10 +1,9 @@
|
||||
use std::ops::Bound;
|
||||
|
||||
use self::harness::generate_sst;
|
||||
use self::harness::{check_iter_result, MockIterator};
|
||||
use bytes::Bytes;
|
||||
use tempfile::tempdir;
|
||||
use week1_day5::harness::generate_sst;
|
||||
|
||||
use self::harness::{check_iter_result, MockIterator};
|
||||
|
||||
use super::*;
|
||||
use crate::{
|
||||
|
||||
201
mini-lsm/src/tests/week1_day6.rs
Normal file
201
mini-lsm/src/tests/week1_day6.rs
Normal file
@@ -0,0 +1,201 @@
|
||||
use std::{ops::Bound, time::Duration};
|
||||
|
||||
use bytes::Bytes;
|
||||
use tempfile::tempdir;
|
||||
|
||||
use self::harness::check_iter_result;
|
||||
|
||||
use super::*;
|
||||
use crate::{
|
||||
iterators::StorageIterator,
|
||||
lsm_storage::{LsmStorageInner, LsmStorageOptions, MiniLsm},
|
||||
};
|
||||
|
||||
fn sync(storage: &LsmStorageInner) {
|
||||
storage
|
||||
.force_freeze_memtable(&storage.state_lock.lock())
|
||||
.unwrap();
|
||||
storage.force_flush_next_imm_memtable().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_task1_storage_scan() {
|
||||
let dir = tempdir().unwrap();
|
||||
let storage = LsmStorageInner::open(&dir, LsmStorageOptions::default_for_week1_test()).unwrap();
|
||||
storage.put(b"0", b"2333333").unwrap();
|
||||
storage.put(b"00", b"2333333").unwrap();
|
||||
storage.put(b"4", b"23").unwrap();
|
||||
sync(&storage);
|
||||
|
||||
storage.delete(b"4").unwrap();
|
||||
sync(&storage);
|
||||
|
||||
storage.put(b"1", b"233").unwrap();
|
||||
storage.put(b"2", b"2333").unwrap();
|
||||
storage
|
||||
.force_freeze_memtable(&storage.state_lock.lock())
|
||||
.unwrap();
|
||||
storage.put(b"00", b"2333").unwrap();
|
||||
storage
|
||||
.force_freeze_memtable(&storage.state_lock.lock())
|
||||
.unwrap();
|
||||
storage.put(b"3", b"23333").unwrap();
|
||||
storage.delete(b"1").unwrap();
|
||||
|
||||
{
|
||||
let state = storage.state.read();
|
||||
assert_eq!(state.l0_sstables.len(), 2);
|
||||
assert_eq!(state.imm_memtables.len(), 2);
|
||||
}
|
||||
|
||||
check_iter_result(
|
||||
&mut storage.scan(Bound::Unbounded, Bound::Unbounded).unwrap(),
|
||||
vec![
|
||||
(Bytes::from("0"), Bytes::from("2333333")),
|
||||
(Bytes::from("00"), Bytes::from("2333")),
|
||||
(Bytes::from("2"), Bytes::from("2333")),
|
||||
(Bytes::from("3"), Bytes::from("23333")),
|
||||
],
|
||||
);
|
||||
check_iter_result(
|
||||
&mut storage
|
||||
.scan(Bound::Included(b"1"), Bound::Included(b"2"))
|
||||
.unwrap(),
|
||||
vec![(Bytes::from("2"), Bytes::from("2333"))],
|
||||
);
|
||||
check_iter_result(
|
||||
&mut storage
|
||||
.scan(Bound::Excluded(b"1"), Bound::Excluded(b"3"))
|
||||
.unwrap(),
|
||||
vec![(Bytes::from("2"), Bytes::from("2333"))],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_task1_storage_get() {
|
||||
let dir = tempdir().unwrap();
|
||||
let storage = LsmStorageInner::open(&dir, LsmStorageOptions::default_for_week1_test()).unwrap();
|
||||
storage.put(b"0", b"2333333").unwrap();
|
||||
storage.put(b"00", b"2333333").unwrap();
|
||||
storage.put(b"4", b"23").unwrap();
|
||||
sync(&storage);
|
||||
|
||||
storage.delete(b"4").unwrap();
|
||||
sync(&storage);
|
||||
|
||||
storage.put(b"1", b"233").unwrap();
|
||||
storage.put(b"2", b"2333").unwrap();
|
||||
storage
|
||||
.force_freeze_memtable(&storage.state_lock.lock())
|
||||
.unwrap();
|
||||
storage.put(b"00", b"2333").unwrap();
|
||||
storage
|
||||
.force_freeze_memtable(&storage.state_lock.lock())
|
||||
.unwrap();
|
||||
storage.put(b"3", b"23333").unwrap();
|
||||
storage.delete(b"1").unwrap();
|
||||
|
||||
{
|
||||
let state = storage.state.read();
|
||||
assert_eq!(state.l0_sstables.len(), 2);
|
||||
assert_eq!(state.imm_memtables.len(), 2);
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
storage.get(b"0").unwrap(),
|
||||
Some(Bytes::from_static(b"2333333"))
|
||||
);
|
||||
assert_eq!(
|
||||
storage.get(b"00").unwrap(),
|
||||
Some(Bytes::from_static(b"2333"))
|
||||
);
|
||||
assert_eq!(
|
||||
storage.get(b"2").unwrap(),
|
||||
Some(Bytes::from_static(b"2333"))
|
||||
);
|
||||
assert_eq!(
|
||||
storage.get(b"3").unwrap(),
|
||||
Some(Bytes::from_static(b"23333"))
|
||||
);
|
||||
assert_eq!(storage.get(b"4").unwrap(), None);
|
||||
assert_eq!(storage.get(b"--").unwrap(), None);
|
||||
assert_eq!(storage.get(b"555").unwrap(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_task2_auto_flush() {
|
||||
let dir = tempdir().unwrap();
|
||||
let storage = MiniLsm::open(&dir, LsmStorageOptions::default_for_week1_day6_test()).unwrap();
|
||||
|
||||
let value = "1".repeat(1024); // 1KB
|
||||
|
||||
// approximately 6MB
|
||||
for i in 0..6000 {
|
||||
storage
|
||||
.put(format!("{i}").as_bytes(), value.as_bytes())
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
std::thread::sleep(Duration::from_millis(500));
|
||||
|
||||
assert!(!storage.inner.state.read().l0_sstables.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_task3_sst_filter() {
|
||||
let dir = tempdir().unwrap();
|
||||
let storage = LsmStorageInner::open(&dir, LsmStorageOptions::default_for_week1_test()).unwrap();
|
||||
|
||||
for i in 1..=10000 {
|
||||
if i % 1000 == 0 {
|
||||
sync(&storage);
|
||||
}
|
||||
storage
|
||||
.put(format!("{:05}", i).as_bytes(), b"2333333")
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
let iter = storage.scan(Bound::Unbounded, Bound::Unbounded).unwrap();
|
||||
assert!(
|
||||
iter.num_active_iterators() >= 10,
|
||||
"did you implement num_active_iterators? current active iterators = {}",
|
||||
iter.num_active_iterators()
|
||||
);
|
||||
let max_num = iter.num_active_iterators();
|
||||
let iter = storage
|
||||
.scan(
|
||||
Bound::Excluded(format!("{:05}", 10000).as_bytes()),
|
||||
Bound::Unbounded,
|
||||
)
|
||||
.unwrap();
|
||||
assert!(iter.num_active_iterators() < max_num);
|
||||
let min_num = iter.num_active_iterators();
|
||||
let iter = storage
|
||||
.scan(
|
||||
Bound::Unbounded,
|
||||
Bound::Excluded(format!("{:05}", 1).as_bytes()),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(iter.num_active_iterators(), min_num);
|
||||
let iter = storage
|
||||
.scan(
|
||||
Bound::Unbounded,
|
||||
Bound::Included(format!("{:05}", 0).as_bytes()),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(iter.num_active_iterators(), min_num);
|
||||
let iter = storage
|
||||
.scan(
|
||||
Bound::Included(format!("{:05}", 10001).as_bytes()),
|
||||
Bound::Unbounded,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(iter.num_active_iterators(), min_num);
|
||||
let iter = storage
|
||||
.scan(
|
||||
Bound::Included(format!("{:05}", 5000).as_bytes()),
|
||||
Bound::Excluded(format!("{:05}", 6000).as_bytes()),
|
||||
)
|
||||
.unwrap();
|
||||
assert!(min_num < iter.num_active_iterators() && iter.num_active_iterators() < max_num);
|
||||
}
|
||||
Reference in New Issue
Block a user