AcctIdx: remove old items from cache (#20076)

This commit is contained in:
Jeff Washington (jwash) 2021-09-22 16:37:15 -05:00 committed by GitHub
parent 567f30aa1a
commit f7eebadbed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -562,7 +562,7 @@ impl<T: IndexValue> InMemAccountsIndex<T> {
fn flush_internal(&self) {
let was_dirty = self.bin_dirty.swap(false, Ordering::Acquire);
let current_age = self.storage.current_age();
let iterate_for_age = self.get_should_age(current_age);
let mut iterate_for_age = self.get_should_age(current_age);
if !was_dirty && !iterate_for_age {
// wasn't dirty and no need to age, so no need to flush this bucket
return;
@ -612,7 +612,11 @@ impl<T: IndexValue> InMemAccountsIndex<T> {
flush_entries_updated_on_disk,
);
// loop that processes 'removes' will go here
let m = Measure::start("flush_remove");
if !self.flush_remove_from_cache(removes, current_age) {
iterate_for_age = false; // did not make it all the way through this bucket, so didn't handle age completely
}
Self::update_time_stat(&self.stats().flush_remove_us, m);
if iterate_for_age {
// completed iteration of the buckets at the current age
@ -621,6 +625,56 @@ impl<T: IndexValue> InMemAccountsIndex<T> {
}
}
// remove keys in 'removes' from in-mem cache due to age
// return true if the removal was completed
fn flush_remove_from_cache(&self, removes: Vec<Pubkey>, current_age: Age) -> bool {
let mut completed_scan = true;
if removes.is_empty() {
return completed_scan; // completed, don't need to get lock or do other work
}
let ranges = self.cache_ranges_held.read().unwrap().clone();
if ranges.iter().any(|range| range.is_none()) {
return false; // range said to hold 'all', so not completed
}
let mut map = self.map().write().unwrap();
for k in removes {
if let Entry::Occupied(occupied) = map.entry(k) {
let v = occupied.get();
if Arc::strong_count(v) > 1 {
// someone is holding the value arc's ref count and could modify it, so do not remove this from in-mem cache
completed_scan = false;
continue;
}
if v.dirty() || !self.should_remove_from_mem(current_age, v) {
// marked dirty or bumped in age after we looked above
// these will be handled in later passes
continue;
}
if ranges.iter().any(|range| {
range
.as_ref()
.map(|range| range.contains(&k))
.unwrap_or(true) // None means 'full range', so true
}) {
// this item is held in mem by range, so don't remove
completed_scan = false;
continue;
}
if self.get_stop_flush() {
return false; // did NOT complete, told to stop
}
// all conditions for removing succeeded, so really remove item from in-mem cache
occupied.remove();
}
}
completed_scan
}
fn stats(&self) -> &BucketMapHolderStats {
&self.storage.stats
}