@@ -12,7 +12,10 @@ use std::path::PathBuf;
12
12
use std:: str:: FromStr ;
13
13
use std:: sync:: atomic:: AtomicUsize ;
14
14
use std:: sync:: { Arc , RwLock } ;
15
+ use std:: time:: Duration ;
15
16
use std:: usize;
17
+ use tokio:: sync:: mpsc:: error:: TryRecvError ;
18
+ use tokio:: sync:: mpsc:: { Receiver , Sender } ;
16
19
use tracing:: level_filters:: LevelFilter ;
17
20
use tracing:: { self , debug, info, warn} ;
18
21
use tracing_subscriber:: prelude:: __tracing_subscriber_SubscriberExt;
@@ -62,6 +65,12 @@ pub struct KvStore {
62
65
/// The maximum size of a log file in bytes.
63
66
max_log_file_size : u64 ,
64
67
68
+ /// Channel on which compaction notifications are sent.
69
+ ///
70
+ /// This allows the [`KvStore`] to signal to the background task which receives
71
+ /// compaction jobs to begin its work.
72
+ compaction_tx : Sender < ( ) > ,
73
+
65
74
_tracing : Option < Arc < tracing:: subscriber:: DefaultGuard > > ,
66
75
}
67
76
@@ -96,10 +105,11 @@ struct KeydirEntry {
96
105
timestamp : i64 ,
97
106
}
98
107
99
- #[ derive( Debug , Clone , Serialize , Deserialize ) ]
108
+ #[ derive( Debug ) ]
100
109
struct StoreConfig {
101
110
log_location : PathBuf ,
102
111
max_log_file_size : u64 ,
112
+ compaction_tx : Sender < ( ) > ,
103
113
}
104
114
105
115
impl KvsEngine for KvStore {
@@ -230,28 +240,31 @@ impl KvStore {
230
240
/// Create a new KvStore.
231
241
///
232
242
/// The store is created in memory and is not persisted to disk.
233
- fn new ( config : StoreConfig ) -> KvStore {
243
+ fn new ( config : & StoreConfig ) -> KvStore {
234
244
KvStore {
235
245
writer : Arc :: new ( RwLock :: new ( StoreWriter :: default ( ) ) ) ,
236
- log_location : config. log_location ,
246
+ log_location : config. log_location . clone ( ) ,
237
247
keydir : Arc :: new ( DashMap :: new ( ) ) ,
238
248
max_log_file_size : config. max_log_file_size ,
249
+ compaction_tx : config. compaction_tx . clone ( ) ,
239
250
_tracing : None ,
240
251
}
241
252
}
242
253
243
254
/// Open a KvStore at the given path.
244
- pub fn open < P > ( path : P ) -> Result < KvStore >
255
+ pub async fn open < P > ( path : P ) -> Result < KvStore >
245
256
where
246
257
P : Into < PathBuf > ,
247
258
{
248
259
let path = path. into ( ) ;
260
+ let ( tx, mut rx) = tokio:: sync:: mpsc:: channel ( 5 ) ;
249
261
let store_config = StoreConfig {
250
262
log_location : path. clone ( ) ,
251
263
max_log_file_size : MAX_LOG_FILE_SIZE . with ( |f| * f) ,
264
+ compaction_tx : tx,
252
265
} ;
253
266
254
- let mut store = KvStore :: new ( store_config. clone ( ) ) ;
267
+ let mut store = KvStore :: new ( & store_config) ;
255
268
let log_level = std:: env:: var ( "KVS_LOG" ) . unwrap_or ( "info" . to_string ( ) ) ;
256
269
store. setup_logging ( log_level) ?;
257
270
info ! ( "Initialising store" ) ;
@@ -260,6 +273,24 @@ impl KvStore {
260
273
261
274
debug ! ( "Creating initial log file" ) ;
262
275
store. set_active_log_handle ( ) ?;
276
+ tokio:: spawn ( async move {
277
+ let interval_ms: u64 = std:: env:: var ( "KVS_COMPACTION_INTERVAL_MS" )
278
+ . unwrap_or_else ( |_| "200" . to_owned ( ) )
279
+ . parse ( )
280
+ . expect ( "Unable to parse default compaction interval" ) ;
281
+ let mut interval = tokio:: time:: interval ( Duration :: from_millis ( interval_ms) ) ;
282
+ info ! ( interval_ms, "Background compaction polling" ) ;
283
+ loop {
284
+ interval. tick ( ) . await ;
285
+ match rx. try_recv ( ) {
286
+ Ok ( _trigger) => {
287
+ info ! ( "Compaction triggered" ) ;
288
+ }
289
+ Err ( TryRecvError :: Empty ) => debug ! ( "No compaction required" ) ,
290
+ Err ( TryRecvError :: Disconnected ) => panic ! ( "Compaction channel unavailable" ) ,
291
+ }
292
+ }
293
+ } ) ;
263
294
Ok ( store)
264
295
}
265
296
@@ -486,10 +517,17 @@ impl KvStore {
486
517
487
518
pub ( crate ) fn setup_logging ( & mut self , level : String ) -> anyhow:: Result < ( ) > {
488
519
let level = LevelFilter :: from_str ( & level) ?;
489
- let layer = tracing_subscriber:: fmt:: layer ( ) . with_writer ( std:: io:: stderr) ;
520
+ let layer = tracing_subscriber:: fmt:: layer ( )
521
+ . compact ( )
522
+ . with_writer ( std:: io:: stderr)
523
+ . with_thread_ids ( true )
524
+ . with_line_number ( true )
525
+ . with_file ( true )
526
+ . with_target ( false ) ;
490
527
let subscriber = tracing_subscriber:: registry ( ) . with ( level) . with ( layer) ;
491
- let tracing_guard = tracing:: subscriber:: set_default ( subscriber) ;
492
- self . _tracing = Some ( Arc :: new ( tracing_guard) ) ;
528
+ tracing:: subscriber:: set_global_default ( subscriber) ?;
529
+ //let tracing_guard = tracing::subscriber::set_default(subscriber);
530
+ //self._tracing = Some(Arc::new(tracing_guard));
493
531
Ok ( ( ) )
494
532
}
495
533
}
0 commit comments