@@ -19,18 +19,22 @@ use crate::{
1919 value:: InternalValue ,
2020 version:: Version ,
2121 vlog:: { Accessor , BlobFile , BlobFileWriter , ValueHandle } ,
22- Config , Memtable , SegmentId , SeqNo , SequenceNumberCounter , UserKey , UserValue ,
22+ Cache , Config , DescriptorTable , Memtable , SegmentId , SeqNo , SequenceNumberCounter , TreeId ,
23+ UserKey , UserValue ,
2324} ;
2425use handle:: BlobIndirection ;
2526use 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_id : TreeId ,
30+ blobs_folder : Arc < PathBuf > ,
31+ cache : Arc < Cache > ,
32+ descriptor_table : Arc < DescriptorTable > ,
2933 version : Version ,
3034 kv : crate :: Result < InternalValue > ,
3135}
3236
33- impl IterGuard for Guard < ' _ > {
37+ impl IterGuard for Guard {
3438 fn key ( self ) -> crate :: Result < UserKey > {
3539 self . kv . map ( |kv| kv. key . user_key )
3640 }
@@ -49,7 +53,14 @@ impl IterGuard for Guard<'_> {
4953 }
5054
5155 fn into_inner ( self ) -> crate :: Result < ( UserKey , UserValue ) > {
52- resolve_value_handle ( self . blob_tree , & self . version , self . kv ?)
56+ resolve_value_handle_owned (
57+ self . tree_id ,
58+ self . blobs_folder . as_path ( ) ,
59+ & self . cache ,
60+ & self . descriptor_table ,
61+ & self . version ,
62+ self . kv ?,
63+ )
5364 }
5465}
5566
@@ -87,6 +98,47 @@ fn resolve_value_handle(tree: &BlobTree, version: &Version, item: InternalValue)
8798 }
8899}
89100
101+ fn resolve_value_handle_owned (
102+ tree_id : TreeId ,
103+ blobs_folder : & std:: path:: Path ,
104+ cache : & Arc < Cache > ,
105+ descriptor_table : & Arc < DescriptorTable > ,
106+ version : & Version ,
107+ item : InternalValue ,
108+ ) -> RangeItem {
109+ if item. key . value_type . is_indirection ( ) {
110+ let mut cursor = Cursor :: new ( item. value ) ;
111+ let vptr = BlobIndirection :: decode_from ( & mut cursor) ?;
112+
113+ // Resolve indirection using value log
114+ match Accessor :: new ( & version. blob_files ) . get (
115+ tree_id,
116+ blobs_folder,
117+ & item. key . user_key ,
118+ & vptr. vhandle ,
119+ cache,
120+ descriptor_table,
121+ ) {
122+ Ok ( Some ( v) ) => {
123+ let k = item. key . user_key ;
124+ Ok ( ( k, v) )
125+ }
126+ Ok ( None ) => {
127+ panic ! (
128+ "value handle ({:?} => {:?}) did not match any blob - this is a bug; version={}" ,
129+ item. key. user_key, vptr. vhandle,
130+ version. id( ) ,
131+ ) ;
132+ }
133+ Err ( e) => Err ( e) ,
134+ }
135+ } else {
136+ let k = item. key . user_key ;
137+ let v = item. value ;
138+ Ok ( ( k, v) )
139+ }
140+ }
141+
90142/// A key-value-separated log-structured merge tree
91143///
92144/// This tree is a composite structure, consisting of an
@@ -180,20 +232,27 @@ impl AbstractTree for BlobTree {
180232 prefix : K ,
181233 seqno : SeqNo ,
182234 index : Option < Arc < Memtable > > ,
183- ) -> Box < dyn DoubleEndedIterator < Item = IterGuardImpl < ' _ > > + ' _ > {
235+ ) -> Box < dyn DoubleEndedIterator < Item = IterGuardImpl > + Send + ' static > {
184236 use crate :: range:: prefix_to_range;
185237
186238 let range = prefix_to_range ( prefix. as_ref ( ) ) ;
187239
188240 let version = self . current_version ( ) ;
241+ let tree_id = self . id ( ) ;
242+ let blobs_folder = Arc :: new ( self . blobs_folder . clone ( ) ) ;
243+ let cache = self . index . config . cache . clone ( ) ;
244+ let descriptor_table = self . index . config . descriptor_table . clone ( ) ;
189245
190246 Box :: new (
191247 self . index
192248 . create_internal_range ( & range, seqno, index)
193249 . map ( move |kv| {
194250 IterGuardImpl :: Blob ( Guard {
195- blob_tree : self ,
196- version : version. clone ( ) , // TODO: PERF: ugly Arc clone
251+ tree_id,
252+ blobs_folder : Arc :: clone ( & blobs_folder) ,
253+ cache : cache. clone ( ) ,
254+ descriptor_table : descriptor_table. clone ( ) ,
255+ version : version. clone ( ) ,
197256 kv,
198257 } )
199258 } ) ,
@@ -205,17 +264,23 @@ impl AbstractTree for BlobTree {
205264 range : R ,
206265 seqno : SeqNo ,
207266 index : Option < Arc < Memtable > > ,
208- ) -> Box < dyn DoubleEndedIterator < Item = IterGuardImpl < ' _ > > + ' _ > {
267+ ) -> Box < dyn DoubleEndedIterator < Item = IterGuardImpl > + Send + ' static > {
209268 let version = self . current_version ( ) ;
269+ let tree_id = self . id ( ) ;
270+ let blobs_folder = Arc :: new ( self . blobs_folder . clone ( ) ) ;
271+ let cache = self . index . config . cache . clone ( ) ;
272+ let descriptor_table = self . index . config . descriptor_table . clone ( ) ;
210273
211- // TODO: PERF: ugly Arc clone
212274 Box :: new (
213275 self . index
214276 . create_internal_range ( & range, seqno, index)
215277 . map ( move |kv| {
216278 IterGuardImpl :: Blob ( Guard {
217- blob_tree : self ,
218- version : version. clone ( ) , // TODO: PERF: ugly Arc clone
279+ tree_id,
280+ blobs_folder : Arc :: clone ( & blobs_folder) ,
281+ cache : cache. clone ( ) ,
282+ descriptor_table : descriptor_table. clone ( ) ,
283+ version : version. clone ( ) ,
219284 kv,
220285 } )
221286 } ) ,
0 commit comments