AcctIdx: remove old items from cache (#20076)
This commit is contained in:
committed by
GitHub
parent
567f30aa1a
commit
f7eebadbed
@ -562,7 +562,7 @@ impl<T: IndexValue> InMemAccountsIndex<T> {
|
|||||||
fn flush_internal(&self) {
|
fn flush_internal(&self) {
|
||||||
let was_dirty = self.bin_dirty.swap(false, Ordering::Acquire);
|
let was_dirty = self.bin_dirty.swap(false, Ordering::Acquire);
|
||||||
let current_age = self.storage.current_age();
|
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 {
|
if !was_dirty && !iterate_for_age {
|
||||||
// wasn't dirty and no need to age, so no need to flush this bucket
|
// wasn't dirty and no need to age, so no need to flush this bucket
|
||||||
return;
|
return;
|
||||||
@ -612,7 +612,11 @@ impl<T: IndexValue> InMemAccountsIndex<T> {
|
|||||||
flush_entries_updated_on_disk,
|
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 {
|
if iterate_for_age {
|
||||||
// completed iteration of the buckets at the current 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 {
|
fn stats(&self) -> &BucketMapHolderStats {
|
||||||
&self.storage.stats
|
&self.storage.stats
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user