AcctIdx: get can load from disk (#20067)

This commit is contained in:
Jeff Washington (jwash) 2021-09-21 12:40:07 -05:00 committed by GitHub
parent 640e93187c
commit e6795e6fdd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 57 additions and 9 deletions

View File

@ -154,6 +154,13 @@ pub struct AccountMapEntryInner<T> {
}
impl<T: IndexValue> AccountMapEntryInner<T> {
pub fn new(slot_list: SlotList<T>, ref_count: RefCount, meta: AccountMapEntryMeta) -> Self {
Self {
slot_list: RwLock::new(slot_list),
ref_count: AtomicU64::new(ref_count),
meta,
}
}
pub fn ref_count(&self) -> RefCount {
self.ref_count.load(Ordering::Relaxed)
}
@ -270,11 +277,11 @@ impl<T: IndexValue> WriteAccountMapEntry<T> {
storage: &Arc<BucketMapHolder<T>>,
) -> AccountMapEntry<T> {
let ref_count = if account_info.is_cached() { 0 } else { 1 };
Arc::new(AccountMapEntryInner {
ref_count: AtomicU64::new(ref_count),
slot_list: RwLock::new(vec![(slot, account_info)]),
meta: AccountMapEntryMeta::new_dirty(storage),
})
Arc::new(AccountMapEntryInner::new(
vec![(slot, account_info)],
ref_count,
AccountMapEntryMeta::new_dirty(storage),
))
}
// Try to update an item in the slot list the given `slot` If an item for the slot

View File

@ -1,5 +1,6 @@
use crate::accounts_index::{
AccountMapEntry, AccountMapEntryInner, IndexValue, SlotList, WriteAccountMapEntry,
AccountMapEntry, AccountMapEntryInner, AccountMapEntryMeta, IndexValue, RefCount, SlotList,
WriteAccountMapEntry,
};
use crate::bucket_map_holder::{Age, BucketMapHolder};
use crate::bucket_map_holder_stats::BucketMapHolderStats;
@ -104,9 +105,23 @@ impl<T: IndexValue> InMemAccountsIndex<T> {
keys
}
pub fn get(&self, key: &K) -> Option<AccountMapEntry<T>> {
fn load_from_disk(&self, pubkey: &Pubkey) -> Option<(SlotList<T>, RefCount)> {
self.storage
.disk
.as_ref()
.and_then(|disk| disk.read_value(pubkey))
}
fn load_account_entry_from_disk(&self, pubkey: &Pubkey) -> Option<AccountMapEntry<T>> {
let entry_disk = self.load_from_disk(pubkey)?; // returns None if not on disk
Some(self.disk_to_cache_entry(entry_disk.0, entry_disk.1))
}
// lookup 'pubkey' in index
pub fn get(&self, pubkey: &K) -> Option<AccountMapEntry<T>> {
let m = Measure::start("get");
let result = self.map().read().unwrap().get(key).cloned();
let result = self.map().read().unwrap().get(pubkey).map(Arc::clone);
let stats = self.stats();
let (count, time) = if result.is_some() {
(&stats.gets_from_mem, &stats.get_mem_us)
@ -115,7 +130,20 @@ impl<T: IndexValue> InMemAccountsIndex<T> {
};
Self::update_time_stat(time, m);
Self::update_stat(count, 1);
result
if result.is_some() {
return result;
}
// not in cache, look on disk
let new_entry = self.load_account_entry_from_disk(pubkey)?;
let mut map = self.map().write().unwrap();
let entry = map.entry(*pubkey);
let result = match entry {
Entry::Occupied(occupied) => Arc::clone(occupied.get()),
Entry::Vacant(vacant) => Arc::clone(vacant.insert(new_entry)),
};
Some(result)
}
// If the slot list for pubkey exists in the index and is empty, remove the index entry for pubkey and return true.
@ -245,6 +273,19 @@ impl<T: IndexValue> InMemAccountsIndex<T> {
addref
}
// convert from raw data on disk to AccountMapEntry, set to age in future
fn disk_to_cache_entry(
&self,
slot_list: SlotList<T>,
ref_count: RefCount,
) -> AccountMapEntry<T> {
Arc::new(AccountMapEntryInner::new(
slot_list,
ref_count,
AccountMapEntryMeta::new_dirty(&self.storage),
))
}
// returns true if upsert was successful. new_value is modified in this case. new_value contains a RwLock
// otherwise, new_value has not been modified and the pubkey has to be added to the maps with a write lock. call upsert_new
pub fn update_key_if_exists(