@@ -562,7 +562,7 @@ impl<T: IndexValue> InMemAccountsIndex<T> {
562
562
fn flush_internal ( & self ) {
563
563
let was_dirty = self . bin_dirty . swap ( false , Ordering :: Acquire ) ;
564
564
let current_age = self . storage . current_age ( ) ;
565
- let iterate_for_age = self . get_should_age ( current_age) ;
565
+ let mut iterate_for_age = self . get_should_age ( current_age) ;
566
566
if !was_dirty && !iterate_for_age {
567
567
// wasn't dirty and no need to age, so no need to flush this bucket
568
568
return ;
@@ -612,7 +612,11 @@ impl<T: IndexValue> InMemAccountsIndex<T> {
612
612
flush_entries_updated_on_disk,
613
613
) ;
614
614
615
- // loop that processes 'removes' will go here
615
+ let m = Measure :: start ( "flush_remove" ) ;
616
+ if !self . flush_remove_from_cache ( removes, current_age) {
617
+ iterate_for_age = false ; // did not make it all the way through this bucket, so didn't handle age completely
618
+ }
619
+ Self :: update_time_stat ( & self . stats ( ) . flush_remove_us , m) ;
616
620
617
621
if iterate_for_age {
618
622
// completed iteration of the buckets at the current age
@@ -621,6 +625,56 @@ impl<T: IndexValue> InMemAccountsIndex<T> {
621
625
}
622
626
}
623
627
628
+ // remove keys in 'removes' from in-mem cache due to age
629
+ // return true if the removal was completed
630
+ fn flush_remove_from_cache ( & self , removes : Vec < Pubkey > , current_age : Age ) -> bool {
631
+ let mut completed_scan = true ;
632
+ if removes. is_empty ( ) {
633
+ return completed_scan; // completed, don't need to get lock or do other work
634
+ }
635
+
636
+ let ranges = self . cache_ranges_held . read ( ) . unwrap ( ) . clone ( ) ;
637
+ if ranges. iter ( ) . any ( |range| range. is_none ( ) ) {
638
+ return false ; // range said to hold 'all', so not completed
639
+ }
640
+ let mut map = self . map ( ) . write ( ) . unwrap ( ) ;
641
+ for k in removes {
642
+ if let Entry :: Occupied ( occupied) = map. entry ( k) {
643
+ let v = occupied. get ( ) ;
644
+ if Arc :: strong_count ( v) > 1 {
645
+ // someone is holding the value arc's ref count and could modify it, so do not remove this from in-mem cache
646
+ completed_scan = false ;
647
+ continue ;
648
+ }
649
+
650
+ if v. dirty ( ) || !self . should_remove_from_mem ( current_age, v) {
651
+ // marked dirty or bumped in age after we looked above
652
+ // these will be handled in later passes
653
+ continue ;
654
+ }
655
+
656
+ if ranges. iter ( ) . any ( |range| {
657
+ range
658
+ . as_ref ( )
659
+ . map ( |range| range. contains ( & k) )
660
+ . unwrap_or ( true ) // None means 'full range', so true
661
+ } ) {
662
+ // this item is held in mem by range, so don't remove
663
+ completed_scan = false ;
664
+ continue ;
665
+ }
666
+
667
+ if self . get_stop_flush ( ) {
668
+ return false ; // did NOT complete, told to stop
669
+ }
670
+
671
+ // all conditions for removing succeeded, so really remove item from in-mem cache
672
+ occupied. remove ( ) ;
673
+ }
674
+ }
675
+ completed_scan
676
+ }
677
+
624
678
fn stats ( & self ) -> & BucketMapHolderStats {
625
679
& self . storage . stats
626
680
}
0 commit comments