AcctIdx: 2 upserts use disk (#20072)

This commit is contained in:
Jeff Washington (jwash) 2021-09-22 11:14:08 -05:00 committed by GitHub
parent 8d9c339e0e
commit 681d6d121e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 48 additions and 12 deletions

View File

@ -246,6 +246,21 @@ impl<T: IndexValue> InMemAccountsIndex<T> {
Self::update_stat(&self.stats().updates_in_mem, 1); Self::update_stat(&self.stats().updates_in_mem, 1);
} }
Entry::Vacant(vacant) => { Entry::Vacant(vacant) => {
// not in cache, look on disk
let disk_entry = self.load_account_entry_from_disk(vacant.key());
let new_value = if let Some(disk_entry) = disk_entry {
// on disk, so merge new_value with what was on disk
Self::lock_and_update_slot_list(
&disk_entry,
&new_value,
reclaims,
previous_slot_entry_was_cached,
);
disk_entry
} else {
// not on disk, so insert new thing
new_value
};
assert!(new_value.dirty()); assert!(new_value.dirty());
vacant.insert(new_value); vacant.insert(new_value);
self.stats().insert_or_delete(true, self.bin); self.stats().insert_or_delete(true, self.bin);
@ -354,6 +369,19 @@ impl<T: IndexValue> InMemAccountsIndex<T> {
self.len() == 0 self.len() == 0
} }
fn insert_returner(
existing: &AccountMapEntry<T>,
pubkey: &Pubkey,
new_entry: AccountMapEntry<T>,
) -> (WriteAccountMapEntry<T>, T, Pubkey) {
(
WriteAccountMapEntry::from_account_map_entry(Arc::clone(existing)),
// extract the new account_info from the unused 'new_entry'
new_entry.slot_list.write().unwrap().remove(0).1,
*pubkey,
)
}
// return None if item was created new // return None if item was created new
// if entry for pubkey already existed, return Some(entry). Caller needs to call entry.update. // if entry for pubkey already existed, return Some(entry). Caller needs to call entry.update.
pub fn insert_new_entry_if_missing_with_lock( pub fn insert_new_entry_if_missing_with_lock(
@ -373,18 +401,26 @@ impl<T: IndexValue> InMemAccountsIndex<T> {
Self::update_time_stat(time, m); Self::update_time_stat(time, m);
Self::update_stat(count, 1); Self::update_stat(count, 1);
let result = match entry { let result = match entry {
Entry::Occupied(account_entry) => { Entry::Occupied(occupied) => Some(Self::insert_returner(
Some(( occupied.get(),
WriteAccountMapEntry::from_account_map_entry(account_entry.get().clone()), occupied.key(),
// extract the new account_info from the unused 'new_entry' new_entry,
new_entry.slot_list.write().unwrap().remove(0).1, )),
*account_entry.key(), Entry::Vacant(vacant) => {
)) // not in cache, look on disk
} let disk_entry = self.load_account_entry_from_disk(vacant.key());
Entry::Vacant(account_entry) => { if let Some(disk_entry) = disk_entry {
// on disk, so insert into cache, then return cache value so caller will merge
let result = Some(Self::insert_returner(&disk_entry, vacant.key(), new_entry));
assert!(disk_entry.dirty());
vacant.insert(disk_entry);
result
} else {
// not on disk, so insert new thing and we're done
assert!(new_entry.dirty()); assert!(new_entry.dirty());
account_entry.insert(new_entry); vacant.insert(new_entry);
None None // returns None if item was created new
}
} }
}; };
let stats = self.stats(); let stats = self.stats();