use callback for account and account_default_if_zero_lamport (#819)

use callback for `account` and `account_default_if_zero_lamport`
This commit is contained in:
Jeff Washington (jwash) 2024-04-15 19:09:57 -05:00 committed by GitHub
parent 7a15ec99cd
commit ee5fb5102d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 127 additions and 73 deletions

View File

@ -73,8 +73,8 @@ impl<'a: 'b, 'b, U: StorableAccounts<'a>, V: Borrow<AccountHash>>
let item = self.hashes.as_ref().unwrap(); let item = self.hashes.as_ref().unwrap();
item[index].borrow() item[index].borrow()
}; };
let account = self.accounts.account_default_if_zero_lamport(index); self.accounts
callback((account, pubkey, hash)) .account_default_if_zero_lamport(index, |account| callback((account, pubkey, hash)))
} }
/// None if account at index has lamports == 0 /// None if account at index has lamports == 0
@ -83,9 +83,10 @@ impl<'a: 'b, 'b, U: StorableAccounts<'a>, V: Borrow<AccountHash>>
pub fn account<Ret>( pub fn account<Ret>(
&self, &self,
index: usize, index: usize,
mut callback: impl FnMut(Option<AccountForStorage<'a>>) -> Ret, callback: impl FnMut(Option<AccountForStorage<'a>>) -> Ret,
) -> Ret { ) -> Ret {
callback(self.accounts.account_default_if_zero_lamport(index)) self.accounts
.account_default_if_zero_lamport(index, callback)
} }
/// # accounts to write /// # accounts to write

View File

@ -6397,29 +6397,31 @@ impl AccountsDb {
txn_iter txn_iter
.enumerate() .enumerate()
.map(|(i, txn)| { .map(|(i, txn)| {
let account = accounts_and_meta_to_store let mut account_info = AccountInfo::default();
.account_default_if_zero_lamport(i) accounts_and_meta_to_store.account_default_if_zero_lamport(i, |account| {
.map(|account| account.to_account_shared_data()) let account = account
.unwrap_or_default(); .map(|account| account.to_account_shared_data())
let pubkey = accounts_and_meta_to_store.pubkey(i); .unwrap_or_default();
let account_info = AccountInfo::new(StorageLocation::Cached, account.lamports()); let pubkey = accounts_and_meta_to_store.pubkey(i);
account_info = AccountInfo::new(StorageLocation::Cached, account.lamports());
self.notify_account_at_accounts_update( self.notify_account_at_accounts_update(
slot, slot,
&account, &account,
txn, txn,
pubkey, pubkey,
&mut write_version_producer, &mut write_version_producer,
); );
let cached_account = self.accounts_cache.store(slot, pubkey, account); let cached_account = self.accounts_cache.store(slot, pubkey, account);
// hash this account in the bg // hash this account in the bg
match &self.sender_bg_hasher { match &self.sender_bg_hasher {
Some(ref sender) => { Some(ref sender) => {
let _ = sender.send(cached_account); let _ = sender.send(cached_account);
} }
None => (), None => (),
}; };
});
account_info account_info
}) })
.collect() .collect()
@ -6484,10 +6486,11 @@ impl AccountsDb {
let len = accounts.len(); let len = accounts.len();
let mut hashes = Vec::with_capacity(len); let mut hashes = Vec::with_capacity(len);
for index in 0..accounts.len() { for index in 0..accounts.len() {
let (pubkey, account) = let pubkey = accounts.pubkey(index);
(accounts.pubkey(index), accounts.account(index)); accounts.account(index, |account| {
let hash = Self::hash_account(&account, pubkey); let hash = Self::hash_account(&account, pubkey);
hashes.push(hash); hashes.push(hash);
});
} }
hash_time.stop(); hash_time.stop();
self.stats self.stats
@ -7785,19 +7788,20 @@ impl AccountsDb {
(start..end).for_each(|i| { (start..end).for_each(|i| {
let info = infos[i]; let info = infos[i];
let pubkey_account = (accounts.pubkey(i), accounts.account(i)); let pubkey = accounts.pubkey(i);
let pubkey = pubkey_account.0; accounts.account(i, |account| {
let old_slot = accounts.slot(i); let old_slot = accounts.slot(i);
self.accounts_index.upsert( self.accounts_index.upsert(
target_slot, target_slot,
old_slot, old_slot,
pubkey, pubkey,
&pubkey_account.1, &account,
&self.account_indexes, &self.account_indexes,
info, info,
&mut reclaims, &mut reclaims,
reclaim, reclaim,
); );
});
}); });
reclaims reclaims
}; };
@ -8213,9 +8217,10 @@ impl AccountsDb {
let mut stats = BankHashStats::default(); let mut stats = BankHashStats::default();
let mut total_data = 0; let mut total_data = 0;
(0..accounts.len()).for_each(|index| { (0..accounts.len()).for_each(|index| {
let account = accounts.account(index); accounts.account(index, |account| {
total_data += account.data().len(); total_data += account.data().len();
stats.update(&account); stats.update(&account);
})
}); });
self.stats self.stats
@ -9637,8 +9642,12 @@ pub mod tests {
fn pubkey(&self, index: usize) -> &Pubkey { fn pubkey(&self, index: usize) -> &Pubkey {
self.1[index].0 self.1[index].0
} }
fn account(&self, index: usize) -> AccountForStorage<'a> { fn account<Ret>(
self.1[index].1.into() &self,
index: usize,
mut callback: impl FnMut(AccountForStorage<'a>) -> Ret,
) -> Ret {
callback(self.1[index].1.into())
} }
fn slot(&self, index: usize) -> Slot { fn slot(&self, index: usize) -> Slot {
// note that this could be different than 'target_slot()' PER account // note that this could be different than 'target_slot()' PER account

View File

@ -25,9 +25,13 @@ impl<'a> StorableAccounts<'a> for (Slot, &'a [StakeReward]) {
fn pubkey(&self, index: usize) -> &Pubkey { fn pubkey(&self, index: usize) -> &Pubkey {
&self.1[index].stake_pubkey &self.1[index].stake_pubkey
} }
fn account(&self, index: usize) -> AccountForStorage<'a> { fn account<Ret>(
&self,
index: usize,
mut callback: impl FnMut(AccountForStorage<'a>) -> Ret,
) -> Ret {
let entry = &self.1[index]; let entry = &self.1[index];
(&entry.stake_account).into() callback((&entry.stake_account).into())
} }
fn slot(&self, _index: usize) -> Slot { fn slot(&self, _index: usize) -> Slot {
// per-index slot is not unique per slot when per-account slot is not included in the source data // per-index slot is not unique per slot when per-account slot is not included in the source data

View File

@ -84,11 +84,17 @@ pub trait StorableAccounts<'a>: Sync {
/// pubkey at 'index' /// pubkey at 'index'
fn pubkey(&self, index: usize) -> &Pubkey; fn pubkey(&self, index: usize) -> &Pubkey;
/// account at 'index' /// account at 'index'
fn account(&self, index: usize) -> AccountForStorage<'a>; fn account<Ret>(&self, index: usize, callback: impl FnMut(AccountForStorage<'a>) -> Ret)
-> Ret;
/// None if account is zero lamports /// None if account is zero lamports
fn account_default_if_zero_lamport(&self, index: usize) -> Option<AccountForStorage<'a>> { fn account_default_if_zero_lamport<Ret>(
let account = self.account(index); &self,
(account.lamports() != 0).then_some(account) index: usize,
mut callback: impl FnMut(Option<AccountForStorage<'a>>) -> Ret,
) -> Ret {
self.account(index, |account| {
callback((!account.is_zero_lamport()).then_some(account))
})
} }
// current slot for account at 'index' // current slot for account at 'index'
fn slot(&self, index: usize) -> Slot; fn slot(&self, index: usize) -> Slot;
@ -139,8 +145,12 @@ where
fn pubkey(&self, index: usize) -> &Pubkey { fn pubkey(&self, index: usize) -> &Pubkey {
self.accounts[index].0 self.accounts[index].0
} }
fn account(&self, index: usize) -> AccountForStorage<'a> { fn account<Ret>(
self.accounts[index].1.into() &self,
index: usize,
mut callback: impl FnMut(AccountForStorage<'a>) -> Ret,
) -> Ret {
callback(self.accounts[index].1.into())
} }
fn slot(&self, _index: usize) -> Slot { fn slot(&self, _index: usize) -> Slot {
// per-index slot is not unique per slot, but it is different than 'target_slot' // per-index slot is not unique per slot, but it is different than 'target_slot'
@ -162,8 +172,12 @@ where
fn pubkey(&self, index: usize) -> &Pubkey { fn pubkey(&self, index: usize) -> &Pubkey {
self.1[index].0 self.1[index].0
} }
fn account(&self, index: usize) -> AccountForStorage<'a> { fn account<Ret>(
self.1[index].1.into() &self,
index: usize,
mut callback: impl FnMut(AccountForStorage<'a>) -> Ret,
) -> Ret {
callback(self.1[index].1.into())
} }
fn slot(&self, _index: usize) -> Slot { fn slot(&self, _index: usize) -> Slot {
// per-index slot is not unique per slot when per-account slot is not included in the source data // per-index slot is not unique per slot when per-account slot is not included in the source data
@ -183,8 +197,12 @@ where
fn pubkey(&self, index: usize) -> &Pubkey { fn pubkey(&self, index: usize) -> &Pubkey {
&self.1[index].0 &self.1[index].0
} }
fn account(&self, index: usize) -> AccountForStorage<'a> { fn account<Ret>(
(&self.1[index].1).into() &self,
index: usize,
mut callback: impl FnMut(AccountForStorage<'a>) -> Ret,
) -> Ret {
callback((&self.1[index].1).into())
} }
fn slot(&self, _index: usize) -> Slot { fn slot(&self, _index: usize) -> Slot {
// per-index slot is not unique per slot when per-account slot is not included in the source data // per-index slot is not unique per slot when per-account slot is not included in the source data
@ -202,8 +220,12 @@ impl<'a> StorableAccounts<'a> for (Slot, &'a [&'a StoredAccountMeta<'a>]) {
fn pubkey(&self, index: usize) -> &Pubkey { fn pubkey(&self, index: usize) -> &Pubkey {
self.1[index].pubkey() self.1[index].pubkey()
} }
fn account(&self, index: usize) -> AccountForStorage<'a> { fn account<Ret>(
self.1[index].into() &self,
index: usize,
mut callback: impl FnMut(AccountForStorage<'a>) -> Ret,
) -> Ret {
callback(self.1[index].into())
} }
fn slot(&self, _index: usize) -> Slot { fn slot(&self, _index: usize) -> Slot {
// per-index slot is not unique per slot when per-account slot is not included in the source data // per-index slot is not unique per slot when per-account slot is not included in the source data
@ -291,9 +313,13 @@ impl<'a> StorableAccounts<'a> for StorableAccountsBySlot<'a> {
let indexes = self.find_internal_index(index); let indexes = self.find_internal_index(index);
self.slots_and_accounts[indexes.0].1[indexes.1].pubkey() self.slots_and_accounts[indexes.0].1[indexes.1].pubkey()
} }
fn account(&self, index: usize) -> AccountForStorage<'a> { fn account<Ret>(
&self,
index: usize,
mut callback: impl FnMut(AccountForStorage<'a>) -> Ret,
) -> Ret {
let indexes = self.find_internal_index(index); let indexes = self.find_internal_index(index);
self.slots_and_accounts[indexes.0].1[indexes.1].into() callback(self.slots_and_accounts[indexes.0].1[indexes.1].into())
} }
fn slot(&self, index: usize) -> Slot { fn slot(&self, index: usize) -> Slot {
let indexes = self.find_internal_index(index); let indexes = self.find_internal_index(index);
@ -323,8 +349,12 @@ impl<'a> StorableAccounts<'a> for (Slot, &'a [&'a StoredAccountMeta<'a>], Slot)
fn pubkey(&self, index: usize) -> &Pubkey { fn pubkey(&self, index: usize) -> &Pubkey {
self.1[index].pubkey() self.1[index].pubkey()
} }
fn account(&self, index: usize) -> AccountForStorage<'a> { fn account<Ret>(
self.1[index].into() &self,
index: usize,
mut callback: impl FnMut(AccountForStorage<'a>) -> Ret,
) -> Ret {
callback(self.1[index].into())
} }
fn slot(&self, _index: usize) -> Slot { fn slot(&self, _index: usize) -> Slot {
// same other slot for all accounts // same other slot for all accounts
@ -364,7 +394,11 @@ pub mod tests {
assert_eq!(a.is_empty(), b.is_empty()); assert_eq!(a.is_empty(), b.is_empty());
(0..a.len()).for_each(|i| { (0..a.len()).for_each(|i| {
assert_eq!(a.pubkey(i), b.pubkey(i)); assert_eq!(a.pubkey(i), b.pubkey(i));
assert!(accounts_equal(&a.account(i), &b.account(i))); b.account(i, |account| {
a.account(i, |account_a| {
assert!(accounts_equal(&account_a, &account));
});
});
}) })
} }
@ -486,7 +520,9 @@ pub mod tests {
compare(&test2, &test_moving_slots2); compare(&test2, &test_moving_slots2);
for (i, raw) in raw.iter().enumerate() { for (i, raw) in raw.iter().enumerate() {
assert_eq!(raw.0, *test3.pubkey(i)); assert_eq!(raw.0, *test3.pubkey(i));
assert!(accounts_equal(&raw.1, &test3.account(i))); test3.account(i, |account| {
assert!(accounts_equal(&raw.1, &account));
});
assert_eq!(raw.2, test3.slot(i)); assert_eq!(raw.2, test3.slot(i));
assert_eq!(target_slot, test4.slot(i)); assert_eq!(target_slot, test4.slot(i));
assert_eq!(target_slot, test2.slot(i)); assert_eq!(target_slot, test2.slot(i));
@ -587,7 +623,9 @@ pub mod tests {
assert_eq!(entries0 != entries, storable.contains_multiple_slots()); assert_eq!(entries0 != entries, storable.contains_multiple_slots());
(0..entries).for_each(|index| { (0..entries).for_each(|index| {
let index = index as usize; let index = index as usize;
assert!(accounts_equal(&storable.account(index), &raw2[index])); storable.account(index, |account| {
assert!(accounts_equal(&account, &raw2[index]));
});
assert_eq!(storable.pubkey(index), raw2[index].pubkey()); assert_eq!(storable.pubkey(index), raw2[index].pubkey());
assert_eq!(storable.hash(index), raw2[index].hash()); assert_eq!(storable.hash(index), raw2[index].hash());
assert_eq!(storable.slot(index), expected_slots[index]); assert_eq!(storable.slot(index), expected_slots[index]);

View File

@ -5045,11 +5045,13 @@ impl Bank {
let mut m = Measure::start("stakes_cache.check_and_store"); let mut m = Measure::start("stakes_cache.check_and_store");
let new_warmup_cooldown_rate_epoch = self.new_warmup_cooldown_rate_epoch(); let new_warmup_cooldown_rate_epoch = self.new_warmup_cooldown_rate_epoch();
(0..accounts.len()).for_each(|i| { (0..accounts.len()).for_each(|i| {
self.stakes_cache.check_and_store( accounts.account(i, |account| {
accounts.pubkey(i), self.stakes_cache.check_and_store(
&accounts.account(i), accounts.pubkey(i),
new_warmup_cooldown_rate_epoch, &account,
) new_warmup_cooldown_rate_epoch,
)
})
}); });
self.rc.accounts.store_accounts_cached(accounts); self.rc.accounts.store_accounts_cached(accounts);
m.stop(); m.stop();