refactor: move iterator trait to parent mod
Signed-off-by: Alex Chi <iskyzh@gmail.com>
This commit is contained in:
@@ -1 +1,25 @@
|
|||||||
# Storage Engine and Block Cache
|
# Storage Engine and Block Cache
|
||||||
|
|
||||||
|
|
||||||
|
<!-- toc -->
|
||||||
|
|
||||||
|
In this part, you will need to modify:
|
||||||
|
|
||||||
|
* `src/lsm_iterator.rs`
|
||||||
|
* `src/lsm_storage.rs`
|
||||||
|
* Other parts that use `SsTable::read_block`
|
||||||
|
|
||||||
|
You can use `cargo x copy-test day4` to copy our provided test cases to the starter code directory. After you have
|
||||||
|
finished this part, use `cargo x scheck` to check the style and run all test cases. If you want to write your own
|
||||||
|
test cases, write a new module `#[cfg(test)] mod user_tests { /* your test cases */ }` in `table.rs`. Remember to remove
|
||||||
|
`#![allow(...)]` at the top of the modules you modified so that cargo clippy can actually check the styles.
|
||||||
|
|
||||||
|
## Task 1 - Put and Delete
|
||||||
|
|
||||||
|
## Task 2 - Get
|
||||||
|
|
||||||
|
## Task 3 - Scan
|
||||||
|
|
||||||
|
## Task 4 - Sync
|
||||||
|
|
||||||
|
## Task 5 - Block Cache
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
|
|
||||||
- [Store key-value pairs in little blocks](./01-block.md)
|
- [Store key-value pairs in little blocks](./01-block.md)
|
||||||
- [And make them into an SST](./02-sst.md)
|
- [And make them into an SST](./02-sst.md)
|
||||||
- [Now it's time for merging everything](./03-memtable.md)
|
- [Now it's time to merge everything](./03-memtable.md)
|
||||||
- [Block cache, the good way](./04-engine.md)
|
- [The engine starts](./04-engine.md)
|
||||||
- [Let's do something in the background](./05-compaction.md)
|
- [Let's do something in the background](./05-compaction.md)
|
||||||
- [Be careful when the system crashes](./06-recovery.md)
|
- [Be careful when the system crashes](./06-recovery.md)
|
||||||
- [A good bloom filter makes life easier](./07-bloom-filter.md)
|
- [A good bloom filter makes life easier](./07-bloom-filter.md)
|
||||||
|
|||||||
@@ -1,6 +1,19 @@
|
|||||||
pub mod impls;
|
|
||||||
pub mod merge_iterator;
|
pub mod merge_iterator;
|
||||||
pub mod two_merge_iterator;
|
pub mod two_merge_iterator;
|
||||||
|
|
||||||
|
pub trait StorageIterator {
|
||||||
|
/// Get the current value.
|
||||||
|
fn value(&self) -> &[u8];
|
||||||
|
|
||||||
|
/// Get the current key.
|
||||||
|
fn key(&self) -> &[u8];
|
||||||
|
|
||||||
|
/// Check if the current iterator is valid.
|
||||||
|
fn is_valid(&self) -> bool;
|
||||||
|
|
||||||
|
/// Move to the next position.
|
||||||
|
fn next(&mut self) -> anyhow::Result<()>;
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
use anyhow::Result;
|
|
||||||
|
|
||||||
pub trait StorageIterator {
|
|
||||||
/// Get the current value.
|
|
||||||
fn value(&self) -> &[u8];
|
|
||||||
|
|
||||||
/// Get the current key.
|
|
||||||
fn key(&self) -> &[u8];
|
|
||||||
|
|
||||||
/// Check if the current iterator is valid.
|
|
||||||
fn is_valid(&self) -> bool;
|
|
||||||
|
|
||||||
/// Move to the next position.
|
|
||||||
fn next(&mut self) -> Result<()>;
|
|
||||||
}
|
|
||||||
@@ -6,7 +6,7 @@ use std::collections::BinaryHeap;
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
use super::impls::StorageIterator;
|
use super::StorageIterator;
|
||||||
|
|
||||||
struct HeapWrapper<I: StorageIterator>(pub usize, pub Box<I>);
|
struct HeapWrapper<I: StorageIterator>(pub usize, pub Box<I>);
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
use super::impls::StorageIterator;
|
use super::StorageIterator;
|
||||||
|
|
||||||
/// Merges two iterators of different types into one. If the two iterators have the same key, only
|
/// Merges two iterators of different types into one. If the two iterators have the same key, only
|
||||||
/// produce the key once and prefer the entry from A.
|
/// produce the key once and prefer the entry from A.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
use crate::iterators::impls::StorageIterator;
|
use crate::iterators::StorageIterator;
|
||||||
|
|
||||||
pub struct LsmIterator {}
|
pub struct LsmIterator {}
|
||||||
|
|
||||||
|
|||||||
@@ -45,24 +45,32 @@ impl LsmStorage {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get a key from the storage. In day 7, this can be further optimized by using a bloom filter.
|
||||||
pub fn get(&self, key: &[u8]) -> Result<Option<Bytes>> {
|
pub fn get(&self, key: &[u8]) -> Result<Option<Bytes>> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Put a key-value pair into the storage by writing into the current memtable.
|
||||||
pub fn put(&self, key: &[u8], value: &[u8]) -> Result<()> {
|
pub fn put(&self, key: &[u8], value: &[u8]) -> Result<()> {
|
||||||
assert!(!value.is_empty(), "value cannot be empty");
|
assert!(!value.is_empty(), "value cannot be empty");
|
||||||
assert!(!key.is_empty(), "key cannot be empty");
|
assert!(!key.is_empty(), "key cannot be empty");
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Remove a key from the storage by writing an empty value.
|
||||||
pub fn delete(&self, _key: &[u8]) -> Result<()> {
|
pub fn delete(&self, _key: &[u8]) -> Result<()> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Persist data to disk.
|
||||||
|
///
|
||||||
|
/// In day 3: flush the current memtable to disk as L0 SST.
|
||||||
|
/// In day 6: call `fsync` on WAL.
|
||||||
pub fn sync(&self) -> Result<()> {
|
pub fn sync(&self) -> Result<()> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create an iterator over a range of keys.
|
||||||
pub fn scan(
|
pub fn scan(
|
||||||
&self,
|
&self,
|
||||||
_lower: Bound<&[u8]>,
|
_lower: Bound<&[u8]>,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use bytes::Bytes;
|
|||||||
use crossbeam_skiplist::SkipMap;
|
use crossbeam_skiplist::SkipMap;
|
||||||
use ouroboros::self_referencing;
|
use ouroboros::self_referencing;
|
||||||
|
|
||||||
use crate::iterators::impls::StorageIterator;
|
use crate::iterators::StorageIterator;
|
||||||
use crate::table::SsTableBuilder;
|
use crate::table::SsTableBuilder;
|
||||||
|
|
||||||
/// A basic mem-table based on crossbeam-skiplist
|
/// A basic mem-table based on crossbeam-skiplist
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use std::sync::Arc;
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
use super::SsTable;
|
use super::SsTable;
|
||||||
use crate::iterators::impls::StorageIterator;
|
use crate::iterators::StorageIterator;
|
||||||
|
|
||||||
/// An iterator over the contents of an SSTable.
|
/// An iterator over the contents of an SSTable.
|
||||||
pub struct SsTableIterator {}
|
pub struct SsTableIterator {}
|
||||||
|
|||||||
@@ -1,6 +1,19 @@
|
|||||||
pub mod impls;
|
|
||||||
pub mod merge_iterator;
|
pub mod merge_iterator;
|
||||||
pub mod two_merge_iterator;
|
pub mod two_merge_iterator;
|
||||||
|
|
||||||
|
pub trait StorageIterator {
|
||||||
|
/// Get the current value.
|
||||||
|
fn value(&self) -> &[u8];
|
||||||
|
|
||||||
|
/// Get the current key.
|
||||||
|
fn key(&self) -> &[u8];
|
||||||
|
|
||||||
|
/// Check if the current iterator is valid.
|
||||||
|
fn is_valid(&self) -> bool;
|
||||||
|
|
||||||
|
/// Move to the next position.
|
||||||
|
fn next(&mut self) -> anyhow::Result<()>;
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
use anyhow::Result;
|
|
||||||
|
|
||||||
pub trait StorageIterator {
|
|
||||||
/// Get the current value.
|
|
||||||
fn value(&self) -> &[u8];
|
|
||||||
|
|
||||||
/// Get the current key.
|
|
||||||
fn key(&self) -> &[u8];
|
|
||||||
|
|
||||||
/// Check if the current iterator is valid.
|
|
||||||
fn is_valid(&self) -> bool;
|
|
||||||
|
|
||||||
/// Move to the next position.
|
|
||||||
fn next(&mut self) -> Result<()>;
|
|
||||||
}
|
|
||||||
@@ -4,7 +4,7 @@ use std::collections::BinaryHeap;
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
use super::impls::StorageIterator;
|
use super::StorageIterator;
|
||||||
|
|
||||||
struct HeapWrapper<I: StorageIterator>(pub usize, pub Box<I>);
|
struct HeapWrapper<I: StorageIterator>(pub usize, pub Box<I>);
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
|
|
||||||
use super::impls::StorageIterator;
|
use super::StorageIterator;
|
||||||
|
|
||||||
pub mod merge_iterator_test;
|
pub mod merge_iterator_test;
|
||||||
pub mod two_merge_iterator_test;
|
pub mod two_merge_iterator_test;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
use super::impls::StorageIterator;
|
use super::StorageIterator;
|
||||||
|
|
||||||
/// Merges two iterators of different types into one. If the two iterators have the same key, only
|
/// Merges two iterators of different types into one. If the two iterators have the same key, only
|
||||||
/// produce the key once and prefer the entry from A.
|
/// produce the key once and prefer the entry from A.
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ use std::ops::Bound;
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
|
|
||||||
use crate::iterators::impls::StorageIterator;
|
|
||||||
use crate::iterators::merge_iterator::MergeIterator;
|
use crate::iterators::merge_iterator::MergeIterator;
|
||||||
use crate::iterators::two_merge_iterator::TwoMergeIterator;
|
use crate::iterators::two_merge_iterator::TwoMergeIterator;
|
||||||
|
use crate::iterators::StorageIterator;
|
||||||
use crate::mem_table::MemTableIterator;
|
use crate::mem_table::MemTableIterator;
|
||||||
use crate::table::SsTableIterator;
|
use crate::table::SsTableIterator;
|
||||||
|
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ use bytes::Bytes;
|
|||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::{Mutex, RwLock};
|
||||||
|
|
||||||
use crate::block::Block;
|
use crate::block::Block;
|
||||||
use crate::iterators::impls::StorageIterator;
|
|
||||||
use crate::iterators::merge_iterator::MergeIterator;
|
use crate::iterators::merge_iterator::MergeIterator;
|
||||||
use crate::iterators::two_merge_iterator::TwoMergeIterator;
|
use crate::iterators::two_merge_iterator::TwoMergeIterator;
|
||||||
|
use crate::iterators::StorageIterator;
|
||||||
use crate::lsm_iterator::{FusedIterator, LsmIterator};
|
use crate::lsm_iterator::{FusedIterator, LsmIterator};
|
||||||
use crate::mem_table::{map_bound, MemTable};
|
use crate::mem_table::{map_bound, MemTable};
|
||||||
use crate::table::{SsTable, SsTableBuilder, SsTableIterator};
|
use crate::table::{SsTable, SsTableBuilder, SsTableIterator};
|
||||||
@@ -126,6 +126,8 @@ impl LsmStorage {
|
|||||||
self.path.join(format!("{:05}.sst", id))
|
self.path.join(format!("{:05}.sst", id))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Persist data to disk.
|
||||||
|
///
|
||||||
/// In day 3: flush the current memtable to disk as L0 SST.
|
/// In day 3: flush the current memtable to disk as L0 SST.
|
||||||
/// In day 6: call `fsync` on WAL.
|
/// In day 6: call `fsync` on WAL.
|
||||||
pub fn sync(&self) -> Result<()> {
|
pub fn sync(&self) -> Result<()> {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use crossbeam_skiplist::map::Entry;
|
|||||||
use crossbeam_skiplist::SkipMap;
|
use crossbeam_skiplist::SkipMap;
|
||||||
use ouroboros::self_referencing;
|
use ouroboros::self_referencing;
|
||||||
|
|
||||||
use crate::iterators::impls::StorageIterator;
|
use crate::iterators::StorageIterator;
|
||||||
use crate::table::SsTableBuilder;
|
use crate::table::SsTableBuilder;
|
||||||
|
|
||||||
/// A basic mem-table based on crossbeam-skiplist
|
/// A basic mem-table based on crossbeam-skiplist
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use tempfile::tempdir;
|
use tempfile::tempdir;
|
||||||
|
|
||||||
use super::MemTable;
|
use super::MemTable;
|
||||||
use crate::iterators::impls::StorageIterator;
|
use crate::iterators::StorageIterator;
|
||||||
use crate::table::{SsTableBuilder, SsTableIterator};
|
use crate::table::{SsTableBuilder, SsTableIterator};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use anyhow::Result;
|
|||||||
|
|
||||||
use super::SsTable;
|
use super::SsTable;
|
||||||
use crate::block::BlockIterator;
|
use crate::block::BlockIterator;
|
||||||
use crate::iterators::impls::StorageIterator;
|
use crate::iterators::StorageIterator;
|
||||||
|
|
||||||
/// An iterator over the contents of an SSTable.
|
/// An iterator over the contents of an SSTable.
|
||||||
pub struct SsTableIterator {
|
pub struct SsTableIterator {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use bytes::Bytes;
|
|||||||
use tempfile::{tempdir, TempDir};
|
use tempfile::{tempdir, TempDir};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::iterators::impls::StorageIterator;
|
use crate::iterators::StorageIterator;
|
||||||
use crate::table::SsTableBuilder;
|
use crate::table::SsTableBuilder;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use std::ops::Bound;
|
|||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use tempfile::tempdir;
|
use tempfile::tempdir;
|
||||||
|
|
||||||
use crate::iterators::impls::StorageIterator;
|
use crate::iterators::StorageIterator;
|
||||||
|
|
||||||
fn as_bytes(x: &[u8]) -> Bytes {
|
fn as_bytes(x: &[u8]) -> Bytes {
|
||||||
Bytes::copy_from_slice(x)
|
Bytes::copy_from_slice(x)
|
||||||
|
|||||||
Reference in New Issue
Block a user