@@ -42,7 +42,7 @@ use std::{
4242 ops:: RangeBounds ,
4343 path:: { Path , PathBuf } ,
4444 sync:: atomic:: { AtomicBool , AtomicU64 , AtomicUsize , Ordering } ,
45- sync:: { Arc , Mutex , RwLock , RwLockReadGuard } ,
45+ sync:: { Arc , Mutex , RwLock , RwLockReadGuard , RwLockWriteGuard } ,
4646 time:: Instant ,
4747} ;
4848use tempfile:: TempDir ;
@@ -535,7 +535,7 @@ impl AccountsDB {
535535 inc_new_counter_info ! ( "clean-old-root-par-clean-ms" , clean_rooted. as_ms( ) as usize ) ;
536536
537537 let mut measure = Measure :: start ( "clean_old_root_reclaims" ) ;
538- self . handle_reclaims ( & reclaims) ;
538+ self . handle_reclaims_maybe_cleanup ( & reclaims) ;
539539 measure. stop ( ) ;
540540 debug ! ( "{} {}" , clean_rooted, measure) ;
541541 inc_new_counter_info ! ( "clean-old-root-reclaim-ms" , measure. as_ms( ) as usize ) ;
@@ -726,15 +726,15 @@ impl AccountsDB {
726726 }
727727 }
728728
729- self . handle_reclaims ( & reclaims) ;
729+ self . handle_reclaims_maybe_cleanup ( & reclaims) ;
730730 reclaims_time. stop ( ) ;
731731 debug ! (
732732 "clean_accounts: {} {} {} {}" ,
733733 accounts_scan, store_counts_time, purge_filter, reclaims_time
734734 ) ;
735735 }
736736
737- fn handle_reclaims ( & self , reclaims : SlotSlice < AccountInfo > ) {
737+ fn handle_reclaims_maybe_cleanup ( & self , reclaims : SlotSlice < AccountInfo > ) {
738738 let mut dead_accounts = Measure :: start ( "reclaims::remove_dead_accounts" ) ;
739739 let dead_slots = self . remove_dead_accounts ( reclaims) ;
740740 dead_accounts. stop ( ) ;
@@ -744,13 +744,27 @@ impl AccountsDB {
744744 dead_slots_w. len ( )
745745 } ;
746746 if dead_slots_len > 5000 {
747- self . process_dead_slots ( ) ;
747+ self . process_dead_slots ( None ) ;
748748 }
749749 }
750750
751- pub fn process_dead_slots ( & self ) {
752- let empty = HashSet :: new ( ) ;
751+ // Atomicallly process reclaims and new dead_slots in this thread, gauranteeing
752+ // complete data removal for slots in reclaims.
753+ fn handle_reclaims_ensure_cleanup ( & self , reclaims : SlotSlice < AccountInfo > ) {
754+ let mut dead_accounts = Measure :: start ( "reclaims::remove_dead_accounts" ) ;
755+ let dead_slots = self . remove_dead_accounts ( reclaims) ;
756+ dead_accounts. stop ( ) ;
753757 let mut dead_slots_w = self . dead_slots . write ( ) . unwrap ( ) ;
758+ dead_slots_w. extend ( dead_slots) ;
759+ self . process_dead_slots ( Some ( dead_slots_w) ) ;
760+ }
761+
762+ pub fn process_dead_slots < ' a > (
763+ & ' a self ,
764+ dead_slots_w : Option < RwLockWriteGuard < ' a , HashSet < Slot > > > ,
765+ ) {
766+ let empty = HashSet :: new ( ) ;
767+ let mut dead_slots_w = dead_slots_w. unwrap_or_else ( || self . dead_slots . write ( ) . unwrap ( ) ) ;
754768 let dead_slots = std:: mem:: replace ( & mut * dead_slots_w, empty) ;
755769 drop ( dead_slots_w) ;
756770
@@ -887,7 +901,7 @@ impl AccountsDB {
887901 ) ;
888902 let reclaims = self . update_index ( slot, infos, & accounts) ;
889903
890- self . handle_reclaims ( & reclaims) ;
904+ self . handle_reclaims_maybe_cleanup ( & reclaims) ;
891905
892906 let mut storage = self . storage . write ( ) . unwrap ( ) ;
893907 if let Some ( slot_storage) = storage. 0 . get_mut ( & slot) {
@@ -1192,13 +1206,9 @@ impl AccountsDB {
11921206 }
11931207 }
11941208
1195- self . handle_reclaims ( & reclaims) ;
1196-
11971209 // 1) Remove old bank hash from self.bank_hashes
11981210 // 2) Purge this slot's storage entries from self.storage
1199- self . process_dead_slots ( ) ;
1200-
1201- // Sanity check storage entries are removed from the index
1211+ self . handle_reclaims_ensure_cleanup ( & reclaims) ;
12021212 assert ! ( self . storage. read( ) . unwrap( ) . 0 . get( & remove_slot) . is_none( ) ) ;
12031213 }
12041214
@@ -1810,7 +1820,7 @@ impl AccountsDB {
18101820 update_index. stop ( ) ;
18111821 trace ! ( "reclaim: {}" , reclaims. len( ) ) ;
18121822
1813- self . handle_reclaims ( & reclaims) ;
1823+ self . handle_reclaims_maybe_cleanup ( & reclaims) ;
18141824 }
18151825
18161826 pub fn add_root ( & self , slot : Slot ) {
@@ -2521,7 +2531,7 @@ pub mod tests {
25212531 //slot is gone
25222532 print_accounts ( "pre-clean" , & accounts) ;
25232533 accounts. clean_accounts ( ) ;
2524- accounts. process_dead_slots ( ) ;
2534+ accounts. process_dead_slots ( None ) ;
25252535 assert ! ( accounts. storage. read( ) . unwrap( ) . 0 . get( & 0 ) . is_none( ) ) ;
25262536
25272537 //new value is there
@@ -2959,7 +2969,7 @@ pub mod tests {
29592969 let hash = accounts. update_accounts_hash ( current_slot, & ancestors) ;
29602970
29612971 accounts. clean_accounts ( ) ;
2962- accounts. process_dead_slots ( ) ;
2972+ accounts. process_dead_slots ( None ) ;
29632973
29642974 assert_eq ! (
29652975 accounts. update_accounts_hash( current_slot, & ancestors) ,
@@ -3761,7 +3771,7 @@ pub mod tests {
37613771 current_slot += 1 ;
37623772 assert_eq ! ( 4 , accounts. ref_count_for_pubkey( & pubkey1) ) ;
37633773 accounts. store ( current_slot, & [ ( & pubkey1, & zero_lamport_account) ] ) ;
3764- accounts. process_dead_slots ( ) ;
3774+ accounts. process_dead_slots ( None ) ;
37653775 assert_eq ! (
37663776 3 , /* == 4 - 2 + 1 */
37673777 accounts. ref_count_for_pubkey( & pubkey1)
0 commit comments