@@ -42,6 +42,11 @@ pub struct LsmStorageState {
|
||||
pub sstables: HashMap<usize, Arc<SsTable>>,
|
||||
}
|
||||
|
||||
pub enum WriteBatchRecord<T: AsRef<[u8]>> {
|
||||
Put(T, T),
|
||||
Del(T),
|
||||
}
|
||||
|
||||
impl LsmStorageState {
|
||||
fn create(options: &LsmStorageOptions) -> Self {
|
||||
let levels = match &options.compaction_options {
|
||||
@@ -234,6 +239,10 @@ impl MiniLsm {
|
||||
self.inner.get(key)
|
||||
}
|
||||
|
||||
pub fn write_batch<T: AsRef<[u8]>>(&self, batch: &[WriteBatchRecord<T>]) -> Result<()> {
|
||||
self.inner.write_batch(batch)
|
||||
}
|
||||
|
||||
pub fn put(&self, key: &[u8], value: &[u8]) -> Result<()> {
|
||||
self.inner.put(key, value)
|
||||
}
|
||||
@@ -486,37 +495,46 @@ impl LsmStorageInner {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
pub fn write_batch<T: AsRef<[u8]>>(&self, batch: &[WriteBatchRecord<T>]) -> Result<()> {
|
||||
for record in batch {
|
||||
match record {
|
||||
WriteBatchRecord::Del(key) => {
|
||||
let key = key.as_ref();
|
||||
assert!(!key.is_empty(), "key cannot be empty");
|
||||
let size;
|
||||
{
|
||||
let guard = self.state.read();
|
||||
guard.memtable.put(key, b"")?;
|
||||
size = guard.memtable.approximate_size();
|
||||
}
|
||||
self.try_freeze(size)?;
|
||||
}
|
||||
WriteBatchRecord::Put(key, value) => {
|
||||
let key = key.as_ref();
|
||||
let value = value.as_ref();
|
||||
assert!(!key.is_empty(), "key cannot be empty");
|
||||
assert!(!value.is_empty(), "value cannot be empty");
|
||||
let size;
|
||||
{
|
||||
let guard = self.state.read();
|
||||
guard.memtable.put(key, value)?;
|
||||
size = guard.memtable.approximate_size();
|
||||
}
|
||||
self.try_freeze(size)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Put a key-value pair into the storage by writing into the current memtable.
|
||||
pub fn put(&self, key: &[u8], value: &[u8]) -> Result<()> {
|
||||
assert!(!value.is_empty(), "value cannot be empty");
|
||||
assert!(!key.is_empty(), "key cannot be empty");
|
||||
|
||||
let size;
|
||||
{
|
||||
let guard = self.state.read();
|
||||
guard.memtable.put(key, value)?;
|
||||
size = guard.memtable.approximate_size();
|
||||
}
|
||||
|
||||
self.try_freeze(size)?;
|
||||
|
||||
Ok(())
|
||||
self.write_batch(&[WriteBatchRecord::Put(key, value)])
|
||||
}
|
||||
|
||||
/// Remove a key from the storage by writing an empty value.
|
||||
pub fn delete(&self, key: &[u8]) -> Result<()> {
|
||||
assert!(!key.is_empty(), "key cannot be empty");
|
||||
|
||||
let size;
|
||||
{
|
||||
let guard = self.state.read();
|
||||
guard.memtable.put(key, b"")?;
|
||||
size = guard.memtable.approximate_size();
|
||||
}
|
||||
|
||||
self.try_freeze(size)?;
|
||||
|
||||
Ok(())
|
||||
self.write_batch(&[WriteBatchRecord::Del(key)])
|
||||
}
|
||||
|
||||
fn try_freeze(&self, estimated_size: usize) -> Result<()> {
|
||||
|
||||
Reference in New Issue
Block a user