AcctIdx: introduce age per in-mem bucket (#19982)

This commit is contained in:
Jeff Washington (jwash) 2021-09-18 22:09:37 -05:00 committed by GitHub
parent 742155c214
commit f579f73700
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 31 additions and 3 deletions

View File

@ -1,13 +1,13 @@
use crate::accounts_index::{
AccountMapEntry, AccountMapEntryInner, IndexValue, SlotList, WriteAccountMapEntry,
};
use crate::bucket_map_holder::BucketMapHolder;
use crate::bucket_map_holder::{Age, BucketMapHolder};
use crate::bucket_map_holder_stats::BucketMapHolderStats;
use solana_measure::measure::Measure;
use solana_sdk::{clock::Slot, pubkey::Pubkey};
use std::collections::{hash_map::Entry, HashMap};
use std::ops::{Bound, RangeBounds, RangeInclusive};
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use std::sync::atomic::{AtomicBool, AtomicU64, AtomicU8, Ordering};
use std::sync::{Arc, RwLock};
use std::fmt::Debug;
@ -15,8 +15,11 @@ type K = Pubkey;
type CacheRangesHeld = RwLock<Vec<Option<RangeInclusive<Pubkey>>>>;
pub type SlotT<T> = (Slot, T);
// one instance of this represents one bin of the accounts index.
#[allow(dead_code)] // temporary during staging
// one instance of this represents one bin of the accounts index.
pub struct InMemAccountsIndex<T: IndexValue> {
last_age_flushed: AtomicU8,
// backing store
map_internal: RwLock<HashMap<Pubkey, AccountMapEntry<T>>>,
storage: Arc<BucketMapHolder<T>>,
@ -38,6 +41,7 @@ impl<T: IndexValue> Debug for InMemAccountsIndex<T> {
}
}
#[allow(dead_code)] // temporary during staging
impl<T: IndexValue> InMemAccountsIndex<T> {
pub fn new(storage: &Arc<BucketMapHolder<T>>, bin: usize) -> Self {
Self {
@ -48,9 +52,24 @@ impl<T: IndexValue> InMemAccountsIndex<T> {
stop_flush: AtomicU64::default(),
bin_dirty: AtomicBool::default(),
flushing_active: AtomicBool::default(),
// initialize this to max, to make it clear we have not flushed at age 0, the starting age
last_age_flushed: AtomicU8::new(Age::MAX),
}
}
/// true if this bucket needs to call flush for the current age
/// we need to scan each bucket once per value of age
fn get_should_age(&self) -> bool {
let last_age_flushed = self.last_age_flushed.load(Ordering::Relaxed);
let age = self.storage.age.load(Ordering::Relaxed);
last_age_flushed == age
}
/// called after flush scans this bucket at the current age
fn set_has_aged(&self, age: Age) {
self.last_age_flushed.store(age, Ordering::Relaxed);
}
fn map(&self) -> &RwLock<HashMap<Pubkey, AccountMapEntry<T>>> {
&self.map_internal
}
@ -484,4 +503,13 @@ mod tests {
assert!(accts.cache_ranges_held.read().unwrap().is_empty());
}
}
#[test]
fn test_age() {
solana_logger::setup();
let test = new_for_test::<u64>();
assert!(!test.get_should_age());
test.set_has_aged(0);
assert!(test.get_should_age());
}
}