cfxcore/block_data_manager/db_gc_manager.rs
1use malloc_size_of_derive::MallocSizeOf as DeriveMallocSizeOf;
2use std::cmp::min;
3
4/// Each time we make a new checkpoint, we will mark more data as garbage
5/// depending on the parameters. To avoid the GC process affecting normal
6/// transaction execution or RPC-handling, we GC data gradually, and expect to
7/// finish removing the data in a previous era with less time than the period
8/// that the consensus graph makes a new era (the default configuration is to
9/// finish GC with half an era).
10#[derive(Default, DeriveMallocSizeOf, Debug)]
11pub struct GCProgress {
12 // The earliest not-garbage-collected epoch.
13 // This is the only field that we persist to disk as the GC progress.
14 pub next_to_process: u64,
15
16 // The last epoch that we are allowed to garbage collect.
17 pub gc_end: u64,
18
19 // The best epoch number of the last time we garbage collect data.
20 // This is compared with the latest epoch number to decide how many epochs
21 // to GC this time.
22 pub last_consensus_best_epoch: u64,
23
24 // The epoch number that we want to finish garbage collection of
25 // `self.gc_end`.
26 pub expected_end_consensus_best_epoch: u64,
27}
28
29impl GCProgress {
30 pub fn new(next_to_process: u64) -> Self {
31 Self {
32 next_to_process,
33 ..Default::default()
34 }
35 }
36
37 /// Compute the GC base range to make sure the GC progress is proportional
38 /// to the consensus progress.
39 /// The actual GC range for each kind of data is the returned base range
40 /// minus the corresponding `additional_maintained*` offset.
41 ///
42 /// Return `Some((start_epoch, end_epoch))` and the range `[start_epoch,
43 /// end_epoch)` will be GCed. Return `None` if there is no work to be
44 /// done.
45 pub fn get_gc_base_range(&self, best_epoch: u64) -> Option<(u64, u64)> {
46 if self.gc_end <= self.next_to_process
47 || best_epoch <= self.last_consensus_best_epoch
48 {
49 return None;
50 }
51 let best_epoch =
52 min(best_epoch, self.expected_end_consensus_best_epoch);
53 let batch_size = (self.gc_end - self.next_to_process)
54 * (best_epoch - self.last_consensus_best_epoch)
55 / (self.expected_end_consensus_best_epoch
56 - self.last_consensus_best_epoch);
57 Some((self.next_to_process, self.next_to_process + batch_size))
58 }
59}