1515 * ------------------------------------------------------------------------------
1616 */
1717
18- use std:: collections:: VecDeque ;
1918use std:: fs:: File ;
2019use std:: io;
2120use std:: io:: prelude:: * ;
@@ -38,12 +37,11 @@ use std::time::Duration;
3837use protobuf;
3938
4039use batch:: Batch ;
41- use database:: lmdb:: LmdbDatabase ;
4240use journal;
4341use journal:: block_validator:: { BlockValidationResult , BlockValidator , ValidationError } ;
4442use journal:: block_wrapper:: BlockWrapper ;
4543use metrics;
46- use state:: merkle :: MerkleDatabase ;
44+ use state:: state_pruning_manager :: StatePruningManager ;
4745
4846use proto:: transaction_receipt:: TransactionReceipt ;
4947use scheduler:: TxnExecutionResult ;
@@ -152,7 +150,7 @@ struct ChainControllerState<BC: BlockCache, BV: BlockValidator, CW: ChainWriter>
152150 chain_head_update_observer : Box < ChainHeadUpdateObserver > ,
153151 observers : Vec < Box < ChainObserver > > ,
154152
155- state_prune_manager : StatePruneManager ,
153+ state_pruning_manager : StatePruningManager ,
156154}
157155
158156#[ derive( Clone ) ]
@@ -177,7 +175,7 @@ impl<BC: BlockCache + 'static, BV: BlockValidator + 'static, CW: ChainWriter + '
177175 chain_head_update_observer : Box < ChainHeadUpdateObserver > ,
178176 state_pruning_block_depth : u32 ,
179177 observers : Vec < Box < ChainObserver > > ,
180- state_database : LmdbDatabase ,
178+ state_pruning_manager : StatePruningManager ,
181179 ) -> Self {
182180 let mut chain_controller = ChainController {
183181 state : Arc :: new ( RwLock :: new ( ChainControllerState {
@@ -190,7 +188,7 @@ impl<BC: BlockCache + 'static, BV: BlockValidator + 'static, CW: ChainWriter + '
190188 chain_head_update_observer,
191189 observers,
192190 chain_head : None ,
193- state_prune_manager : StatePruneManager :: new ( state_database ) ,
191+ state_pruning_manager
194192 } ) ) ,
195193 stop_handle : Arc :: new ( Mutex :: new ( None ) ) ,
196194 block_queue_sender : None ,
@@ -276,7 +274,7 @@ impl<BC: BlockCache + 'static, BV: BlockValidator + 'static, CW: ChainWriter + '
276274 let chain_head_block = new_block. clone ( ) ;
277275 state. chain_head = Some ( new_block) ;
278276
279- state. state_prune_manager . update_queue (
277+ state. state_pruning_manager . update_queue (
280278 & result
281279 . new_chain
282280 . iter ( )
@@ -363,14 +361,14 @@ impl<BC: BlockCache + 'static, BV: BlockValidator + 'static, CW: ChainWriter + '
363361 if chain_head_block_num + 1 > self . state_pruning_block_depth as u64 {
364362 let prune_at = chain_head_block_num - ( self . state_pruning_block_depth as u64 ) ;
365363 match state. chain_reader . get_block_by_block_num ( prune_at) {
366- Ok ( Some ( block) ) => state. state_prune_manager . add_to_queue ( block. state_root_hash ( ) ) ,
364+ Ok ( Some ( block) ) => state. state_pruning_manager . add_to_queue ( block. state_root_hash ( ) ) ,
367365 Ok ( None ) => warn ! ( "No block at block height {}; ignoring..." , prune_at) ,
368366 Err ( err) => error ! ( "Unable to fetch block at height {}: {:?}" , prune_at, err)
369367 }
370368 }
371369
372370 // Execute pruning:
373- state. state_prune_manager . decimate ( )
371+ state. state_pruning_manager . decimate ( )
374372 } else {
375373 info ! ( "Rejected new chain head: {}" , new_block) ;
376374 }
@@ -698,92 +696,5 @@ impl ChainIdManager {
698696 }
699697}
700698
701- /// The StatePruneManager manages a collection of state root hashes that will be
702- /// prune from the MerkleDatabase at intervals. Pruning will occur by decimating
703- /// the state root hashes. I.e. ten percent (rounded down) of the state roots in
704- /// the queue will be pruned. This allows state roots to remain in the queue for
705- /// a period of time, on the chance that they are from a chain that has been
706- /// abandoned and then re-chosen as the primary chain.
707- struct StatePruneManager {
708- // Contains the state root hashes slated for pruning
709- state_root_prune_queue : VecDeque < String > ,
710- state_database : LmdbDatabase ,
711- }
712-
713- impl StatePruneManager {
714- fn new ( state_database : LmdbDatabase ) -> Self {
715- StatePruneManager {
716- state_root_prune_queue : VecDeque :: new ( ) ,
717- state_database,
718- }
719- }
720-
721- /// Updates the pruning queue. Abandoned roots will be added to the queue.
722- /// Added roots will be removed from the queue. This ensures that the state
723- /// roots won't be removed, regardless of the chain state.
724- fn update_queue ( & mut self , added_roots : & [ & str ] , _abandoned_roots : & [ & str ] ) {
725- // Remove any state root hashes from the pruning queue that we may have switched
726- // back too from an alternate chain
727- added_roots. iter ( ) . for_each ( |state_root_hash| {
728- self . state_root_prune_queue . retain ( |hash| {
729- if hash != state_root_hash {
730- true
731- } else {
732- debug ! ( "Removing {} from pruning queue" , state_root_hash) ;
733- false
734- }
735- } )
736- } ) ;
737- }
738-
739- /// Add a single state root to the pruning queue.
740- fn add_to_queue ( & mut self , state_root_hash : & str ) {
741- let state_root_hash = state_root_hash. into ( ) ;
742- if !self . state_root_prune_queue . contains ( & state_root_hash) {
743- debug ! ( "Adding {} to pruning queue" , state_root_hash) ;
744- self . state_root_prune_queue . push_back ( state_root_hash) ;
745- }
746- }
747-
748- /// Remove the first ten percent (floored) of the prune queue.
749- fn decimate ( & mut self ) {
750- let prune_count = ( self . state_root_prune_queue . len ( ) as f64 / 10.0 ) . floor ( ) as usize ;
751-
752- let mut total_pruned_entries: usize = 0 ;
753- for _ in 0 ..prune_count {
754- if let Some ( state_root) = self . state_root_prune_queue . pop_front ( ) {
755- match MerkleDatabase :: prune ( & self . state_database , & state_root) {
756- Ok ( removed_keys) => {
757- total_pruned_entries += removed_keys. len ( ) ;
758-
759- let mut state_roots_pruned_count =
760- COLLECTOR . counter ( "StatePruneManager.state_roots_pruned" , None , None ) ;
761- state_roots_pruned_count. inc ( ) ;
762-
763- // the state root was not pruned (it is likely the root of a
764- // fork), so push it back into the queue.
765- if removed_keys. is_empty ( ) {
766- self . state_root_prune_queue . push_back ( state_root) ;
767- }
768- }
769- Err ( err) => {
770- error ! ( "Unable to prune state root {}: {:?}" , state_root, err) ;
771- self . state_root_prune_queue . push_back ( state_root) ;
772- }
773- }
774- } else {
775- break ;
776- }
777- }
778-
779- if total_pruned_entries > 0 {
780- info ! (
781- "Pruned {} keys from the Global state Database" ,
782- total_pruned_entries
783- ) ;
784- }
785- }
786- }
787-
788699#[ cfg( tests) ]
789700mod tests { }
0 commit comments