@@ -19,18 +19,26 @@ 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+ struct IterShared {
29+ tree_id : TreeId ,
30+ blobs_folder : Arc < PathBuf > ,
31+ cache : Arc < Cache > ,
32+ descriptor_table : Arc < DescriptorTable > ,
2933 version : Version ,
34+ }
35+
36+ pub struct Guard {
37+ shared : Arc < IterShared > ,
3038 kv : crate :: Result < InternalValue > ,
3139}
3240
33- impl IterGuard for Guard < ' _ > {
41+ impl IterGuard for Guard {
3442 fn key ( self ) -> crate :: Result < UserKey > {
3543 self . kv . map ( |kv| kv. key . user_key )
3644 }
@@ -49,7 +57,14 @@ impl IterGuard for Guard<'_> {
4957 }
5058
5159 fn into_inner ( self ) -> crate :: Result < ( UserKey , UserValue ) > {
52- resolve_value_handle ( self . blob_tree , & self . version , self . kv ?)
60+ resolve_value_handle_owned (
61+ self . shared . tree_id ,
62+ self . shared . blobs_folder . as_path ( ) ,
63+ & self . shared . cache ,
64+ & self . shared . descriptor_table ,
65+ & self . shared . version ,
66+ self . kv ?,
67+ )
5368 }
5469}
5570
@@ -61,7 +76,7 @@ fn resolve_value_handle(tree: &BlobTree, version: &Version, item: InternalValue)
6176 // Resolve indirection using value log
6277 match Accessor :: new ( & version. blob_files ) . get (
6378 tree. id ( ) ,
64- & tree. blobs_folder ,
79+ tree. blobs_folder . as_path ( ) ,
6580 & item. key . user_key ,
6681 & vptr. vhandle ,
6782 & tree. index . config . cache ,
@@ -87,6 +102,47 @@ fn resolve_value_handle(tree: &BlobTree, version: &Version, item: InternalValue)
87102 }
88103}
89104
105+ fn resolve_value_handle_owned (
106+ tree_id : TreeId ,
107+ blobs_folder : & std:: path:: Path ,
108+ cache : & Arc < Cache > ,
109+ descriptor_table : & Arc < DescriptorTable > ,
110+ version : & Version ,
111+ item : InternalValue ,
112+ ) -> RangeItem {
113+ if item. key . value_type . is_indirection ( ) {
114+ let mut cursor = Cursor :: new ( item. value ) ;
115+ let vptr = BlobIndirection :: decode_from ( & mut cursor) ?;
116+
117+ // Resolve indirection using value log
118+ match Accessor :: new ( & version. blob_files ) . get (
119+ tree_id,
120+ blobs_folder,
121+ & item. key . user_key ,
122+ & vptr. vhandle ,
123+ cache,
124+ descriptor_table,
125+ ) {
126+ Ok ( Some ( v) ) => {
127+ let k = item. key . user_key ;
128+ Ok ( ( k, v) )
129+ }
130+ Ok ( None ) => {
131+ panic ! (
132+ "value handle ({:?} => {:?}) did not match any blob - this is a bug; version={}" ,
133+ item. key. user_key, vptr. vhandle,
134+ version. id( ) ,
135+ ) ;
136+ }
137+ Err ( e) => Err ( e) ,
138+ }
139+ } else {
140+ let k = item. key . user_key ;
141+ let v = item. value ;
142+ Ok ( ( k, v) )
143+ }
144+ }
145+
90146/// A key-value-separated log-structured merge tree
91147///
92148/// This tree is a composite structure, consisting of an
@@ -98,7 +154,7 @@ pub struct BlobTree {
98154 #[ doc( hidden) ]
99155 pub index : crate :: Tree ,
100156
101- blobs_folder : PathBuf ,
157+ blobs_folder : Arc < PathBuf > ,
102158}
103159
104160impl BlobTree {
@@ -124,7 +180,7 @@ impl BlobTree {
124180
125181 Ok ( Self {
126182 index,
127- blobs_folder,
183+ blobs_folder : Arc :: new ( blobs_folder ) ,
128184 } )
129185 }
130186}
@@ -180,20 +236,25 @@ impl AbstractTree for BlobTree {
180236 prefix : K ,
181237 seqno : SeqNo ,
182238 index : Option < Arc < Memtable > > ,
183- ) -> Box < dyn DoubleEndedIterator < Item = IterGuardImpl < ' _ > > + ' _ > {
239+ ) -> Box < dyn DoubleEndedIterator < Item = IterGuardImpl > + Send + ' static > {
184240 use crate :: range:: prefix_to_range;
185241
186242 let range = prefix_to_range ( prefix. as_ref ( ) ) ;
187243
188- let version = self . current_version ( ) ;
244+ let shared = Arc :: new ( IterShared {
245+ tree_id : self . id ( ) ,
246+ blobs_folder : Arc :: clone ( & self . blobs_folder ) ,
247+ cache : self . index . config . cache . clone ( ) ,
248+ descriptor_table : self . index . config . descriptor_table . clone ( ) ,
249+ version : self . current_version ( ) ,
250+ } ) ;
189251
190252 Box :: new (
191253 self . index
192254 . create_internal_range ( & range, seqno, index)
193255 . map ( move |kv| {
194256 IterGuardImpl :: Blob ( Guard {
195- blob_tree : self ,
196- version : version. clone ( ) , // TODO: PERF: ugly Arc clone
257+ shared : Arc :: clone ( & shared) ,
197258 kv,
198259 } )
199260 } ) ,
@@ -205,17 +266,21 @@ impl AbstractTree for BlobTree {
205266 range : R ,
206267 seqno : SeqNo ,
207268 index : Option < Arc < Memtable > > ,
208- ) -> Box < dyn DoubleEndedIterator < Item = IterGuardImpl < ' _ > > + ' _ > {
209- let version = self . current_version ( ) ;
269+ ) -> Box < dyn DoubleEndedIterator < Item = IterGuardImpl > + Send + ' static > {
270+ let shared = Arc :: new ( IterShared {
271+ tree_id : self . id ( ) ,
272+ blobs_folder : Arc :: clone ( & self . blobs_folder ) ,
273+ cache : self . index . config . cache . clone ( ) ,
274+ descriptor_table : self . index . config . descriptor_table . clone ( ) ,
275+ version : self . current_version ( ) ,
276+ } ) ;
210277
211- // TODO: PERF: ugly Arc clone
212278 Box :: new (
213279 self . index
214280 . create_internal_range ( & range, seqno, index)
215281 . map ( move |kv| {
216282 IterGuardImpl :: Blob ( Guard {
217- blob_tree : self ,
218- version : version. clone ( ) , // TODO: PERF: ugly Arc clone
283+ shared : Arc :: clone ( & shared) ,
219284 kv,
220285 } )
221286 } ) ,
0 commit comments