@@ -11,7 +11,7 @@ use crate::{
1111 scanner:: { Scanner , SizeMap } ,
1212 segment:: merge:: MergeReader ,
1313 version:: Version ,
14- BlobCache , Compressor , Config , GcStrategy , IndexReader , SegmentReader , SegmentWriter ,
14+ BlobCache , Compressor , Config , FDCache , GcStrategy , IndexReader , SegmentReader , SegmentWriter ,
1515 UserValue , ValueHandle ,
1616} ;
1717use std:: {
@@ -43,30 +43,35 @@ fn unlink_blob_files(base_path: &Path, ids: &[SegmentId]) {
4343
4444/// A disk-resident value log
4545#[ derive( Clone ) ]
46- pub struct ValueLog < BC : BlobCache , C : Compressor + Clone > ( Arc < ValueLogInner < BC , C > > ) ;
46+ pub struct ValueLog < BC : BlobCache , FDC : FDCache , C : Compressor + Clone > (
47+ Arc < ValueLogInner < BC , FDC , C > > ,
48+ ) ;
4749
48- impl < BC : BlobCache , C : Compressor + Clone > std:: ops:: Deref for ValueLog < BC , C > {
49- type Target = ValueLogInner < BC , C > ;
50+ impl < BC : BlobCache , C : Compressor + Clone , FDC : FDCache > std:: ops:: Deref for ValueLog < BC , FDC , C > {
51+ type Target = ValueLogInner < BC , FDC , C > ;
5052
5153 fn deref ( & self ) -> & Self :: Target {
5254 & self . 0
5355 }
5456}
5557
5658#[ allow( clippy:: module_name_repetitions) ]
57- pub struct ValueLogInner < BC : BlobCache , C : Compressor + Clone > {
59+ pub struct ValueLogInner < BC : BlobCache , FDC : FDCache , C : Compressor + Clone > {
5860 /// Unique value log ID
5961 id : u64 ,
6062
6163 /// Base folder
6264 pub path : PathBuf ,
6365
6466 /// Value log configuration
65- config : Config < BC , C > ,
67+ config : Config < BC , FDC , C > ,
6668
6769 /// In-memory blob cache
6870 blob_cache : BC ,
6971
72+ /// In-memory FD cache
73+ fd_cache : FDC ,
74+
7075 /// Segment manifest
7176 #[ doc( hidden) ]
7277 pub manifest : SegmentManifest < C > ,
@@ -80,15 +85,15 @@ pub struct ValueLogInner<BC: BlobCache, C: Compressor + Clone> {
8085 pub rollover_guard : Mutex < ( ) > ,
8186}
8287
83- impl < BC : BlobCache , C : Compressor + Clone > ValueLog < BC , C > {
88+ impl < BC : BlobCache , C : Compressor + Clone , FDC : FDCache > ValueLog < BC , FDC , C > {
8489 /// Creates or recovers a value log in the given directory.
8590 ///
8691 /// # Errors
8792 ///
8893 /// Will return `Err` if an IO error occurs.
8994 pub fn open < P : Into < PathBuf > > (
9095 path : P , // TODO: move path into config?
91- config : Config < BC , C > ,
96+ config : Config < BC , FDC , C > ,
9297 ) -> crate :: Result < Self > {
9398 let path = path. into ( ) ;
9499
@@ -143,7 +148,7 @@ impl<BC: BlobCache, C: Compressor + Clone> ValueLog<BC, C> {
143148 /// Creates a new empty value log in a directory.
144149 pub ( crate ) fn create_new < P : Into < PathBuf > > (
145150 path : P ,
146- config : Config < BC , C > ,
151+ config : Config < BC , FDC , C > ,
147152 ) -> crate :: Result < Self > {
148153 let path = absolute_path ( path. into ( ) ) ;
149154 log:: trace!( "Creating value-log at {}" , path. display( ) ) ;
@@ -174,20 +179,25 @@ impl<BC: BlobCache, C: Compressor + Clone> ValueLog<BC, C> {
174179 }
175180
176181 let blob_cache = config. blob_cache . clone ( ) ;
182+ let fd_cache = config. fd_cache . clone ( ) ;
177183 let manifest = SegmentManifest :: create_new ( & path) ?;
178184
179185 Ok ( Self ( Arc :: new ( ValueLogInner {
180186 id : get_next_vlog_id ( ) ,
181187 config,
182188 path,
183189 blob_cache,
190+ fd_cache,
184191 manifest,
185192 id_generator : IdGenerator :: default ( ) ,
186193 rollover_guard : Mutex :: new ( ( ) ) ,
187194 } ) ) )
188195 }
189196
190- pub ( crate ) fn recover < P : Into < PathBuf > > ( path : P , config : Config < BC , C > ) -> crate :: Result < Self > {
197+ pub ( crate ) fn recover < P : Into < PathBuf > > (
198+ path : P ,
199+ config : Config < BC , FDC , C > ,
200+ ) -> crate :: Result < Self > {
191201 let path = path. into ( ) ;
192202 log:: info!( "Recovering vLog at {}" , path. display( ) ) ;
193203
@@ -204,6 +214,7 @@ impl<BC: BlobCache, C: Compressor + Clone> ValueLog<BC, C> {
204214 }
205215
206216 let blob_cache = config. blob_cache . clone ( ) ;
217+ let fd_cache = config. fd_cache . clone ( ) ;
207218 let manifest = SegmentManifest :: recover ( & path) ?;
208219
209220 let highest_id = manifest
@@ -220,6 +231,7 @@ impl<BC: BlobCache, C: Compressor + Clone> ValueLog<BC, C> {
220231 config,
221232 path,
222233 blob_cache,
234+ fd_cache,
223235 manifest,
224236 id_generator : IdGenerator :: new ( highest_id + 1 ) ,
225237 rollover_guard : Mutex :: new ( ( ) ) ,
@@ -270,7 +282,11 @@ impl<BC: BlobCache, C: Compressor + Clone> ValueLog<BC, C> {
270282 return Ok ( None ) ;
271283 } ;
272284
273- let mut reader = BufReader :: new ( File :: open ( & segment. path ) ?) ;
285+ let mut reader = match self . fd_cache . get ( self . id , vhandle. segment_id ) {
286+ Some ( fd) => fd,
287+ None => BufReader :: new ( File :: open ( & segment. path ) ?) ,
288+ } ;
289+
274290 reader. seek ( std:: io:: SeekFrom :: Start ( vhandle. offset ) ) ?;
275291 let mut reader = SegmentReader :: with_reader ( vhandle. segment_id , reader)
276292 . use_compression ( self . config . compression . clone ( ) ) ;
@@ -302,6 +318,10 @@ impl<BC: BlobCache, C: Compressor + Clone> ValueLog<BC, C> {
302318 self . blob_cache . insert ( self . id , & value_handle, val) ;
303319 }
304320
321+ // cache the BufReader for future use, must ensure to always use SeekFrom::Start when using it from cache
322+ self . fd_cache
323+ . insert ( self . id , vhandle. segment_id , reader. into_inner ( ) ) ;
324+
305325 Ok ( Some ( val) )
306326 }
307327
@@ -499,7 +519,7 @@ impl<BC: BlobCache, C: Compressor + Clone> ValueLog<BC, C> {
499519 /// Will return `Err` if an IO error occurs.
500520 pub fn apply_gc_strategy < R : IndexReader , W : IndexWriter > (
501521 & self ,
502- strategy : & impl GcStrategy < BC , C > ,
522+ strategy : & impl GcStrategy < BC , FDC , C > ,
503523 index_reader : & R ,
504524 index_writer : W ,
505525 ) -> crate :: Result < u64 > {
0 commit comments