Skip to content

Commit a5a4e94

Browse files
authored
Merge pull request #173 from zaidoon1/zaidoon/iterators-static
make iterators Send + 'static to support cross-thread usage
2 parents 1f5061a + dd4bc99 commit a5a4e94

File tree

9 files changed

+364
-36
lines changed

9 files changed

+364
-36
lines changed

src/abstract.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ pub trait AbstractTree {
4949
&self,
5050
seqno: SeqNo,
5151
index: Option<Arc<Memtable>>,
52-
) -> Box<dyn DoubleEndedIterator<Item = IterGuardImpl<'_>> + '_> {
52+
) -> Box<dyn DoubleEndedIterator<Item = IterGuardImpl> + Send + 'static> {
5353
self.range::<&[u8], _>(.., seqno, index)
5454
}
5555

@@ -61,7 +61,7 @@ pub trait AbstractTree {
6161
prefix: K,
6262
seqno: SeqNo,
6363
index: Option<Arc<Memtable>>,
64-
) -> Box<dyn DoubleEndedIterator<Item = IterGuardImpl<'_>> + '_>;
64+
) -> Box<dyn DoubleEndedIterator<Item = IterGuardImpl> + Send + 'static>;
6565

6666
/// Returns an iterator over a range of items.
6767
///
@@ -71,7 +71,7 @@ pub trait AbstractTree {
7171
range: R,
7272
seqno: SeqNo,
7373
index: Option<Arc<Memtable>>,
74-
) -> Box<dyn DoubleEndedIterator<Item = IterGuardImpl<'_>> + '_>;
74+
) -> Box<dyn DoubleEndedIterator<Item = IterGuardImpl> + Send + 'static>;
7575

7676
/// Ingests a sorted stream of key-value pairs into the tree.
7777
///

src/blob_tree/mod.rs

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,19 @@ use crate::{
1919
value::InternalValue,
2020
version::Version,
2121
vlog::{Accessor, BlobFile, BlobFileWriter, ValueHandle},
22-
Config, Memtable, SeqNo, SequenceNumberCounter, TableId, UserKey, UserValue,
22+
Cache, Config, DescriptorTable, Memtable, SeqNo, SequenceNumberCounter, TableId, TreeId,
23+
UserKey, UserValue,
2324
};
2425
use handle::BlobIndirection;
2526
use std::{io::Cursor, ops::RangeBounds, path::PathBuf, sync::Arc};
2627

27-
pub struct Guard<'a> {
28-
blob_tree: &'a BlobTree,
28+
pub struct Guard {
29+
tree: crate::BlobTree,
2930
version: Version,
3031
kv: crate::Result<InternalValue>,
3132
}
3233

33-
impl IterGuard for Guard<'_> {
34+
impl IterGuard for Guard {
3435
fn key(self) -> crate::Result<UserKey> {
3536
self.kv.map(|kv| kv.key.user_key)
3637
}
@@ -48,23 +49,37 @@ impl IterGuard for Guard<'_> {
4849
}
4950

5051
fn into_inner(self) -> crate::Result<(UserKey, UserValue)> {
51-
resolve_value_handle(self.blob_tree, &self.version, self.kv?)
52+
resolve_value_handle(
53+
self.tree.id(),
54+
self.tree.blobs_folder.as_path(),
55+
&self.tree.index.config.cache,
56+
&self.tree.index.config.descriptor_table,
57+
&self.version,
58+
self.kv?,
59+
)
5260
}
5361
}
5462

55-
fn resolve_value_handle(tree: &BlobTree, version: &Version, item: InternalValue) -> RangeItem {
63+
fn resolve_value_handle(
64+
tree_id: TreeId,
65+
blobs_folder: &std::path::Path,
66+
cache: &Arc<Cache>,
67+
descriptor_table: &Arc<DescriptorTable>,
68+
version: &Version,
69+
item: InternalValue,
70+
) -> RangeItem {
5671
if item.key.value_type.is_indirection() {
5772
let mut cursor = Cursor::new(item.value);
5873
let vptr = BlobIndirection::decode_from(&mut cursor)?;
5974

6075
// Resolve indirection using value log
6176
match Accessor::new(&version.blob_files).get(
62-
tree.id(),
63-
&tree.blobs_folder,
77+
tree_id,
78+
blobs_folder,
6479
&item.key.user_key,
6580
&vptr.vhandle,
66-
&tree.index.config.cache,
67-
&tree.index.config.descriptor_table,
81+
cache,
82+
descriptor_table,
6883
) {
6984
Ok(Some(v)) => {
7085
let k = item.key.user_key;
@@ -97,7 +112,7 @@ pub struct BlobTree {
97112
#[doc(hidden)]
98113
pub index: crate::Tree,
99114

100-
blobs_folder: PathBuf,
115+
blobs_folder: Arc<PathBuf>,
101116
}
102117

103118
impl BlobTree {
@@ -123,7 +138,7 @@ impl BlobTree {
123138

124139
Ok(Self {
125140
index,
126-
blobs_folder,
141+
blobs_folder: Arc::new(blobs_folder),
127142
})
128143
}
129144
}
@@ -179,20 +194,20 @@ impl AbstractTree for BlobTree {
179194
prefix: K,
180195
seqno: SeqNo,
181196
index: Option<Arc<Memtable>>,
182-
) -> Box<dyn DoubleEndedIterator<Item = IterGuardImpl<'_>> + '_> {
197+
) -> Box<dyn DoubleEndedIterator<Item = IterGuardImpl> + Send + 'static> {
183198
use crate::range::prefix_to_range;
184199

185200
let range = prefix_to_range(prefix.as_ref());
186-
187201
let version = self.current_version();
202+
let tree = self.clone();
188203

189204
Box::new(
190205
self.index
191206
.create_internal_range(&range, seqno, index)
192207
.map(move |kv| {
193208
IterGuardImpl::Blob(Guard {
194-
blob_tree: self,
195-
version: version.clone(), // TODO: PERF: ugly Arc clone
209+
tree: tree.clone(),
210+
version: version.clone(),
196211
kv,
197212
})
198213
}),
@@ -204,17 +219,17 @@ impl AbstractTree for BlobTree {
204219
range: R,
205220
seqno: SeqNo,
206221
index: Option<Arc<Memtable>>,
207-
) -> Box<dyn DoubleEndedIterator<Item = IterGuardImpl<'_>> + '_> {
222+
) -> Box<dyn DoubleEndedIterator<Item = IterGuardImpl> + Send + 'static> {
208223
let version = self.current_version();
224+
let tree = self.clone();
209225

210-
// TODO: PERF: ugly Arc clone
211226
Box::new(
212227
self.index
213228
.create_internal_range(&range, seqno, index)
214229
.map(move |kv| {
215230
IterGuardImpl::Blob(Guard {
216-
blob_tree: self,
217-
version: version.clone(), // TODO: PERF: ugly Arc clone
231+
tree: tree.clone(),
232+
version: version.clone(),
218233
kv,
219234
})
220235
}),
@@ -647,7 +662,14 @@ impl AbstractTree for BlobTree {
647662
};
648663

649664
let version = self.current_version();
650-
let (_, v) = resolve_value_handle(self, &version, item)?;
665+
let (_, v) = resolve_value_handle(
666+
self.id(),
667+
self.blobs_folder.as_path(),
668+
&self.index.config.cache,
669+
&self.index.config.descriptor_table,
670+
&version,
671+
item,
672+
)?;
651673

652674
Ok(Some(v))
653675
}

src/iter_guard.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ pub trait IterGuard {
4141
}
4242

4343
#[enum_dispatch(IterGuard)]
44-
pub enum IterGuardImpl<'a> {
44+
pub enum IterGuardImpl {
4545
Standard(StandardGuard),
46-
Blob(BlobGuard<'a>),
46+
Blob(BlobGuard),
4747
}

src/merge.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use interval_heap::IntervalHeap as Heap;
77

88
type IterItem = crate::Result<InternalValue>;
99

10-
pub type BoxedIterator<'a> = Box<dyn DoubleEndedIterator<Item = IterItem> + 'a>;
10+
pub type BoxedIterator<'a> = Box<dyn DoubleEndedIterator<Item = IterItem> + Send + 'a>;
1111

1212
#[derive(Eq)]
1313
struct HeapItem(usize, InternalValue);

src/range.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ pub struct IterState {
7171
pub(crate) version: Version,
7272
}
7373

74-
type BoxedMerge<'a> = Box<dyn DoubleEndedIterator<Item = crate::Result<InternalValue>> + 'a>;
74+
type BoxedMerge<'a> = Box<dyn DoubleEndedIterator<Item = crate::Result<InternalValue>> + Send + 'a>;
7575

7676
// TODO: maybe we can lifetime TreeIter and then use InternalKeyRef everywhere to bound lifetime of iterators (no need to construct InternalKey then, can just use range)
7777
self_cell!(

src/run_reader.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ pub struct RunReader {
1313
run: Arc<Run<Table>>,
1414
lo: usize,
1515
hi: usize,
16-
lo_reader: Option<Box<dyn DoubleEndedIterator<Item = crate::Result<InternalValue>>>>,
17-
hi_reader: Option<Box<dyn DoubleEndedIterator<Item = crate::Result<InternalValue>>>>,
16+
lo_reader: Option<BoxedIterator<'static>>,
17+
hi_reader: Option<BoxedIterator<'static>>,
1818
}
1919

2020
impl RunReader {
2121
#[must_use]
22-
pub fn new<R: RangeBounds<UserKey> + Clone + 'static>(
22+
pub fn new<R: RangeBounds<UserKey> + Clone + Send + 'static>(
2323
run: Arc<Run<Table>>,
2424
range: R,
2525
) -> Option<Self> {
@@ -31,7 +31,7 @@ impl RunReader {
3131
}
3232

3333
#[must_use]
34-
pub fn culled<R: RangeBounds<UserKey> + Clone + 'static>(
34+
pub fn culled<R: RangeBounds<UserKey> + Clone + Send + 'static>(
3535
run: Arc<Run<Table>>,
3636
range: R,
3737
(lo, hi): (Option<usize>, Option<usize>),

src/table/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -351,10 +351,10 @@ impl Table {
351351
/// Will return `Err` if an IO error occurs.
352352
#[must_use]
353353
#[doc(hidden)]
354-
pub fn range<R: RangeBounds<UserKey>>(
354+
pub fn range<R: RangeBounds<UserKey> + Send>(
355355
&self,
356356
range: R,
357-
) -> impl DoubleEndedIterator<Item = crate::Result<InternalValue>> {
357+
) -> impl DoubleEndedIterator<Item = crate::Result<InternalValue>> + Send {
358358
let index_iter = self.block_index.iter();
359359

360360
let mut iter = Iter::new(

src/tree/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ impl AbstractTree for Tree {
138138
prefix: K,
139139
seqno: SeqNo,
140140
index: Option<Arc<Memtable>>,
141-
) -> Box<dyn DoubleEndedIterator<Item = IterGuardImpl<'_>> + '_> {
141+
) -> Box<dyn DoubleEndedIterator<Item = IterGuardImpl> + Send + 'static> {
142142
Box::new(
143143
self.create_prefix(&prefix, seqno, index)
144144
.map(|kv| IterGuardImpl::Standard(Guard(kv))),
@@ -150,7 +150,7 @@ impl AbstractTree for Tree {
150150
range: R,
151151
seqno: SeqNo,
152152
index: Option<Arc<Memtable>>,
153-
) -> Box<dyn DoubleEndedIterator<Item = IterGuardImpl<'_>> + '_> {
153+
) -> Box<dyn DoubleEndedIterator<Item = IterGuardImpl> + Send + 'static> {
154154
Box::new(
155155
self.create_range(&range, seqno, index)
156156
.map(|kv| IterGuardImpl::Standard(Guard(kv))),

0 commit comments

Comments
 (0)