11
11
12
12
#![ cfg_attr( docsrs, feature( doc_auto_cfg) ) ]
13
13
14
+ #![ cfg_attr( all( not( feature = "std" ) , not( test) ) , no_std) ]
15
+
16
+ #[ cfg( any( test, feature = "std" ) ) ]
17
+ extern crate core;
18
+
14
19
#[ macro_use] extern crate lightning;
15
20
extern crate lightning_rapid_gossip_sync;
16
21
@@ -28,15 +33,22 @@ use lightning::util::events::{Event, EventHandler, EventsProvider};
28
33
use lightning:: util:: logger:: Logger ;
29
34
use lightning:: util:: persist:: Persister ;
30
35
use lightning_rapid_gossip_sync:: RapidGossipSync ;
36
+ use lightning:: io;
37
+
38
+ use core:: ops:: Deref ;
39
+ use core:: time:: Duration ;
40
+
41
+ #[ cfg( feature = "std" ) ]
31
42
use std:: sync:: Arc ;
32
- use std:: sync:: atomic:: { AtomicBool , Ordering } ;
33
- use std:: thread;
34
- use std:: thread:: JoinHandle ;
35
- use std:: time:: { Duration , Instant } ;
36
- use std:: ops:: Deref ;
43
+ #[ cfg( feature = "std" ) ]
44
+ use core:: sync:: atomic:: { AtomicBool , Ordering } ;
45
+ #[ cfg( feature = "std" ) ]
46
+ use std:: thread:: { self , JoinHandle } ;
47
+ #[ cfg( feature = "std" ) ]
48
+ use std:: time:: Instant ;
37
49
38
50
#[ cfg( feature = "futures" ) ]
39
- use futures_util:: { select_biased, future:: FutureExt } ;
51
+ use futures_util:: { select_biased, future:: FutureExt , task } ;
40
52
41
53
/// `BackgroundProcessor` takes care of tasks that (1) need to happen periodically to keep
42
54
/// Rust-Lightning running properly, and (2) either can or should be run in the background. Its
@@ -62,6 +74,7 @@ use futures_util::{select_biased, future::FutureExt};
62
74
///
63
75
/// [`ChannelMonitor`]: lightning::chain::channelmonitor::ChannelMonitor
64
76
/// [`Event`]: lightning::util::events::Event
77
+ #[ cfg( feature = "std" ) ]
65
78
#[ must_use = "BackgroundProcessor will immediately stop on drop. It should be stored until shutdown." ]
66
79
pub struct BackgroundProcessor {
67
80
stop_thread : Arc < AtomicBool > ,
@@ -207,15 +220,15 @@ macro_rules! define_run_body {
207
220
( $persister: ident, $chain_monitor: ident, $process_chain_monitor_events: expr,
208
221
$channel_manager: ident, $process_channel_manager_events: expr,
209
222
$gossip_sync: ident, $peer_manager: ident, $logger: ident, $scorer: ident,
210
- $loop_exit_check: expr, $await: expr)
223
+ $loop_exit_check: expr, $await: expr, $get_timer : expr , $timer_elapsed : expr )
211
224
=> { {
212
225
log_trace!( $logger, "Calling ChannelManager's timer_tick_occurred on startup" ) ;
213
226
$channel_manager. timer_tick_occurred( ) ;
214
227
215
- let mut last_freshness_call = Instant :: now ( ) ;
216
- let mut last_ping_call = Instant :: now ( ) ;
217
- let mut last_prune_call = Instant :: now ( ) ;
218
- let mut last_scorer_persist_call = Instant :: now ( ) ;
228
+ let mut last_freshness_call = $get_timer ( FRESHNESS_TIMER ) ;
229
+ let mut last_ping_call = $get_timer ( PING_TIMER ) ;
230
+ let mut last_prune_call = $get_timer ( FIRST_NETWORK_PRUNE_TIMER ) ;
231
+ let mut last_scorer_persist_call = $get_timer ( SCORER_PERSIST_TIMER ) ;
219
232
let mut have_pruned = false ;
220
233
221
234
loop {
@@ -237,9 +250,9 @@ macro_rules! define_run_body {
237
250
238
251
// We wait up to 100ms, but track how long it takes to detect being put to sleep,
239
252
// see `await_start`'s use below.
240
- let await_start = Instant :: now ( ) ;
253
+ let mut await_start = $get_timer ( 1 ) ;
241
254
let updates_available = $await;
242
- let await_time = await_start . elapsed ( ) ;
255
+ let await_slow = $timer_elapsed ( & mut await_start , 1 ) ;
243
256
244
257
if updates_available {
245
258
log_trace!( $logger, "Persisting ChannelManager..." ) ;
@@ -251,12 +264,12 @@ macro_rules! define_run_body {
251
264
log_trace!( $logger, "Terminating background processor." ) ;
252
265
break ;
253
266
}
254
- if last_freshness_call . elapsed ( ) . as_secs ( ) > FRESHNESS_TIMER {
267
+ if $timer_elapsed ( & mut last_freshness_call , FRESHNESS_TIMER ) {
255
268
log_trace!( $logger, "Calling ChannelManager's timer_tick_occurred" ) ;
256
269
$channel_manager. timer_tick_occurred( ) ;
257
- last_freshness_call = Instant :: now ( ) ;
270
+ last_freshness_call = $get_timer ( FRESHNESS_TIMER ) ;
258
271
}
259
- if await_time > Duration :: from_secs ( 1 ) {
272
+ if await_slow {
260
273
// On various platforms, we may be starved of CPU cycles for several reasons.
261
274
// E.g. on iOS, if we've been in the background, we will be entirely paused.
262
275
// Similarly, if we're on a desktop platform and the device has been asleep, we
@@ -271,40 +284,46 @@ macro_rules! define_run_body {
271
284
// peers.
272
285
log_trace!( $logger, "100ms sleep took more than a second, disconnecting peers." ) ;
273
286
$peer_manager. disconnect_all_peers( ) ;
274
- last_ping_call = Instant :: now ( ) ;
275
- } else if last_ping_call . elapsed ( ) . as_secs ( ) > PING_TIMER {
287
+ last_ping_call = $get_timer ( PING_TIMER ) ;
288
+ } else if $timer_elapsed ( & mut last_ping_call , PING_TIMER ) {
276
289
log_trace!( $logger, "Calling PeerManager's timer_tick_occurred" ) ;
277
290
$peer_manager. timer_tick_occurred( ) ;
278
- last_ping_call = Instant :: now ( ) ;
291
+ last_ping_call = $get_timer ( PING_TIMER ) ;
279
292
}
280
293
281
294
// Note that we want to run a graph prune once not long after startup before
282
295
// falling back to our usual hourly prunes. This avoids short-lived clients never
283
296
// pruning their network graph. We run once 60 seconds after startup before
284
297
// continuing our normal cadence.
285
- if last_prune_call . elapsed ( ) . as_secs ( ) > if have_pruned { NETWORK_PRUNE_TIMER } else { FIRST_NETWORK_PRUNE_TIMER } {
298
+ if $timer_elapsed ( & mut last_prune_call , if have_pruned { NETWORK_PRUNE_TIMER } else { FIRST_NETWORK_PRUNE_TIMER } ) {
286
299
// The network graph must not be pruned while rapid sync completion is pending
287
300
if let Some ( network_graph) = $gossip_sync. prunable_network_graph( ) {
288
- log_trace!( $logger, "Pruning and persisting network graph." ) ;
289
- network_graph. remove_stale_channels_and_tracking( ) ;
301
+ #[ cfg( feature = "std" ) ] {
302
+ log_trace!( $logger, "Pruning and persisting network graph." ) ;
303
+ network_graph. remove_stale_channels_and_tracking( ) ;
304
+ }
305
+ #[ cfg( not( feature = "std" ) ) ] {
306
+ log_warn!( $logger, "Not pruning network graph, consider enabling `std` or doing so manually with remove_stale_channels_and_tracking_with_time." ) ;
307
+ log_trace!( $logger, "Persisting network graph." ) ;
308
+ }
290
309
291
310
if let Err ( e) = $persister. persist_graph( network_graph) {
292
311
log_error!( $logger, "Error: Failed to persist network graph, check your disk and permissions {}" , e)
293
312
}
294
313
295
- last_prune_call = Instant :: now ( ) ;
314
+ last_prune_call = $get_timer ( NETWORK_PRUNE_TIMER ) ;
296
315
have_pruned = true ;
297
316
}
298
317
}
299
318
300
- if last_scorer_persist_call . elapsed ( ) . as_secs ( ) > SCORER_PERSIST_TIMER {
319
+ if $timer_elapsed ( & mut last_scorer_persist_call , SCORER_PERSIST_TIMER ) {
301
320
if let Some ( ref scorer) = $scorer {
302
321
log_trace!( $logger, "Persisting scorer" ) ;
303
322
if let Err ( e) = $persister. persist_scorer( & scorer) {
304
323
log_error!( $logger, "Error: Failed to persist scorer, check your disk and permissions {}" , e)
305
324
}
306
325
}
307
- last_scorer_persist_call = Instant :: now ( ) ;
326
+ last_scorer_persist_call = $get_timer ( SCORER_PERSIST_TIMER ) ;
308
327
}
309
328
}
310
329
@@ -334,6 +353,11 @@ macro_rules! define_run_body {
334
353
/// future which outputs true, the loop will exit and this function's future will complete.
335
354
///
336
355
/// See [`BackgroundProcessor::start`] for information on which actions this handles.
356
+ ///
357
+ /// Requires the `futures` feature. Note that while this method is available without the `std`
358
+ /// feature, doing so will skip calling [`NetworkGraph::remove_stale_channels_and_tracking`],
359
+ /// you should call [`NetworkGraph::remove_stale_channels_and_tracking_with_time`] regularly
360
+ /// manually instead.
337
361
#[ cfg( feature = "futures" ) ]
338
362
pub async fn process_events_async <
339
363
' a ,
@@ -364,13 +388,13 @@ pub async fn process_events_async<
364
388
PM : ' static + Deref < Target = PeerManager < Descriptor , CMH , RMH , OMH , L , UMH > > + Send + Sync ,
365
389
S : ' static + Deref < Target = SC > + Send + Sync ,
366
390
SC : WriteableScore < ' a > ,
367
- SleepFuture : core:: future:: Future < Output = bool > ,
391
+ SleepFuture : core:: future:: Future < Output = bool > + core :: marker :: Unpin ,
368
392
Sleeper : Fn ( Duration ) -> SleepFuture
369
393
> (
370
394
persister : PS , event_handler : EventHandler , chain_monitor : M , channel_manager : CM ,
371
395
gossip_sync : GossipSync < PGS , RGS , G , CA , L > , peer_manager : PM , logger : L , scorer : Option < S > ,
372
396
sleeper : Sleeper ,
373
- ) -> Result < ( ) , std :: io:: Error >
397
+ ) -> Result < ( ) , io:: Error >
374
398
where
375
399
CA :: Target : ' static + chain:: Access ,
376
400
CF :: Target : ' static + chain:: Filter ,
@@ -411,9 +435,15 @@ where
411
435
false
412
436
}
413
437
}
438
+ } , |t| sleeper( Duration :: from_secs( t) ) ,
439
+ |fut: & mut SleepFuture , _| {
440
+ let mut waker = task:: noop_waker( ) ;
441
+ let mut ctx = task:: Context :: from_waker( & mut waker) ;
442
+ core:: pin:: Pin :: new( fut) . poll( & mut ctx) . is_ready( )
414
443
} )
415
444
}
416
445
446
+ #[ cfg( feature = "std" ) ]
417
447
impl BackgroundProcessor {
418
448
/// Start a background thread that takes care of responsibilities enumerated in the [top-level
419
449
/// documentation].
@@ -522,7 +552,8 @@ impl BackgroundProcessor {
522
552
define_run_body ! ( persister, chain_monitor, chain_monitor. process_pending_events( & event_handler) ,
523
553
channel_manager, channel_manager. process_pending_events( & event_handler) ,
524
554
gossip_sync, peer_manager, logger, scorer, stop_thread. load( Ordering :: Acquire ) ,
525
- channel_manager. await_persistable_update_timeout( Duration :: from_millis( 100 ) ) )
555
+ channel_manager. await_persistable_update_timeout( Duration :: from_millis( 100 ) ) ,
556
+ |_| Instant :: now( ) , |time: & Instant , dur| time. elapsed( ) . as_secs( ) > dur)
526
557
} ) ;
527
558
Self { stop_thread : stop_thread_clone, thread_handle : Some ( handle) }
528
559
}
@@ -568,13 +599,14 @@ impl BackgroundProcessor {
568
599
}
569
600
}
570
601
602
+ #[ cfg( feature = "std" ) ]
571
603
impl Drop for BackgroundProcessor {
572
604
fn drop ( & mut self ) {
573
605
self . stop_and_join_thread ( ) . unwrap ( ) ;
574
606
}
575
607
}
576
608
577
- #[ cfg( test) ]
609
+ #[ cfg( all ( feature = "std" , test) ) ]
578
610
mod tests {
579
611
use bitcoin:: blockdata:: block:: BlockHeader ;
580
612
use bitcoin:: blockdata:: constants:: genesis_block;
0 commit comments