Skip to content

Commit ea1c6a0

Browse files
committed
fix: snapshot get() complexity
1 parent 6000602 commit ea1c6a0

File tree

3 files changed

+60
-36
lines changed

3 files changed

+60
-36
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "lsm-tree"
33
description = "A K.I.S.S. implementation of log-structured merge trees (LSM-trees/LSMTs)"
44
license = "MIT OR Apache-2.0"
5-
version = "2.0.0"
5+
version = "2.0.2"
66
edition = "2021"
77
rust-version = "1.74.0"
88
readme = "README.md"

src/segment/mod.rs

Lines changed: 26 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -297,32 +297,6 @@ impl Segment {
297297
));
298298
reader.lo_initialized = true;
299299

300-
let iter = reader.filter_map(move |entry| {
301-
let entry = fail_iter!(entry);
302-
303-
// NOTE: We are past the searched key, so we can immediately return None
304-
if &*entry.key.user_key > key {
305-
None
306-
} else {
307-
// Check for seqno if needed
308-
if let Some(seqno) = seqno {
309-
if entry.key.seqno < seqno {
310-
Some(Ok(InternalValue {
311-
key: entry.key.clone(),
312-
value: entry.value,
313-
}))
314-
} else {
315-
None
316-
}
317-
} else {
318-
Some(Ok(InternalValue {
319-
key: entry.key.clone(),
320-
value: entry.value,
321-
}))
322-
}
323-
}
324-
});
325-
326300
// NOTE: For finding a specific seqno,
327301
// we need to use a reader
328302
// because nothing really prevents the version
@@ -340,7 +314,30 @@ impl Segment {
340314
// unfortunately is in the next block
341315
//
342316
// Also because of weak tombstones, we may have to look further than the first item we encounter
343-
MvccStream::new(iter).next().transpose()
317+
let reader = reader.filter(|x| {
318+
match x {
319+
Ok(entry) => {
320+
// Check for seqno if needed
321+
if let Some(seqno) = seqno {
322+
entry.key.seqno < seqno
323+
} else {
324+
true
325+
}
326+
}
327+
Err(_) => true,
328+
}
329+
});
330+
331+
let Some(entry) = MvccStream::new(reader).next().transpose()? else {
332+
return Ok(None);
333+
};
334+
335+
// NOTE: We are past the searched key, so don't return anything
336+
if &*entry.key.user_key > key {
337+
return Ok(None);
338+
}
339+
340+
Ok(Some(entry))
344341
}
345342

346343
// NOTE: Clippy false positive
@@ -380,6 +377,7 @@ impl Segment {
380377
}
381378

382379
// TODO: move segment tests into module, then make pub(crate)
380+
383381
/// Creates an iterator over the `Segment`.
384382
///
385383
/// # Errors
@@ -389,14 +387,7 @@ impl Segment {
389387
#[allow(clippy::iter_without_into_iter)]
390388
#[doc(hidden)]
391389
pub fn iter(&self) -> Range {
392-
Range::new(
393-
self.offsets.index_block_ptr,
394-
self.descriptor_table.clone(),
395-
(self.tree_id, self.metadata.id).into(),
396-
self.block_cache.clone(),
397-
self.block_index.clone(),
398-
(std::ops::Bound::Unbounded, std::ops::Bound::Unbounded),
399-
)
390+
self.range((std::ops::Bound::Unbounded, std::ops::Bound::Unbounded))
400391
}
401392

402393
/// Creates a ranged iterator over the `Segment`.

tests/snapshot_point_read.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,39 @@
11
use lsm_tree::{AbstractTree, Config, SequenceNumberCounter};
22
use test_log::test;
33

4+
#[test]
5+
fn snapshot_404() -> lsm_tree::Result<()> {
6+
let folder = tempfile::tempdir()?;
7+
8+
let tree = Config::new(&folder)
9+
.data_block_size(1_024)
10+
.index_block_size(1_024)
11+
.open()?;
12+
13+
tree.insert("a", "a", 0);
14+
tree.insert("a2", "a2", 0);
15+
tree.insert("c", "c", 0);
16+
17+
tree.flush_active_memtable(0)?;
18+
19+
assert!(tree.get("a")?.is_some());
20+
assert!(tree.get("a2")?.is_some());
21+
assert!(tree.get("b")?.is_none());
22+
assert!(tree.get("c")?.is_some());
23+
24+
assert!(tree.get_with_seqno("a", 0)?.is_none());
25+
assert!(tree.get_with_seqno("a2", 0)?.is_none());
26+
assert!(tree.get_with_seqno("b", 0)?.is_none());
27+
assert!(tree.get_with_seqno("c", 0)?.is_none());
28+
29+
assert!(tree.get_with_seqno("a", 1)?.is_some());
30+
assert!(tree.get_with_seqno("a2", 1)?.is_some());
31+
assert!(tree.get_with_seqno("b", 1)?.is_none());
32+
assert!(tree.get_with_seqno("c", 1)?.is_some());
33+
34+
Ok(())
35+
}
36+
437
#[test]
538
fn snapshot_lots_of_versions() -> lsm_tree::Result<()> {
639
let version_count = 600;

0 commit comments

Comments
 (0)