introduce AccountForStorage for StorableAccounts (#795)
introduce `AccountForStorage` for `StorableAccounts`
This commit is contained in:
parent
0288e0db29
commit
6bd0bb611c
|
@ -143,10 +143,13 @@ fn store_accounts_with_possible_contention<F: 'static>(
|
|||
let pubkeys: Vec<_> = std::iter::repeat_with(solana_sdk::pubkey::new_rand)
|
||||
.take(num_keys)
|
||||
.collect();
|
||||
let accounts_data: Vec<_> = std::iter::repeat(Account {
|
||||
lamports: 1,
|
||||
..Default::default()
|
||||
})
|
||||
let accounts_data: Vec<_> = std::iter::repeat(
|
||||
Account {
|
||||
lamports: 1,
|
||||
..Default::default()
|
||||
}
|
||||
.to_account_shared_data(),
|
||||
)
|
||||
.take(num_keys)
|
||||
.collect();
|
||||
let storable_accounts: Vec<_> = pubkeys.iter().zip(accounts_data.iter()).collect();
|
||||
|
|
|
@ -8,7 +8,7 @@ use {
|
|||
tiered_storage::hot::HotStorageWriter,
|
||||
},
|
||||
solana_sdk::{
|
||||
account::Account, clock::Slot, hash::Hash, pubkey::Pubkey,
|
||||
account::AccountSharedData, clock::Slot, hash::Hash, pubkey::Pubkey,
|
||||
rent_collector::RENT_EXEMPT_RENT_EPOCH,
|
||||
},
|
||||
};
|
||||
|
@ -34,7 +34,7 @@ fn bench_write_accounts_file(c: &mut Criterion) {
|
|||
let accounts: Vec<_> = std::iter::repeat_with(|| {
|
||||
(
|
||||
Pubkey::new_unique(),
|
||||
Account::new_rent_epoch(
|
||||
AccountSharedData::new_rent_epoch(
|
||||
lamports,
|
||||
space,
|
||||
&Pubkey::new_unique(),
|
||||
|
|
|
@ -3,7 +3,7 @@ use {
|
|||
account_info::AccountInfo,
|
||||
accounts_hash::AccountHash,
|
||||
append_vec::AppendVecStoredAccountMeta,
|
||||
storable_accounts::StorableAccounts,
|
||||
storable_accounts::{AccountForStorage, StorableAccounts},
|
||||
tiered_storage::hot::{HotAccount, HotAccountMeta},
|
||||
},
|
||||
solana_sdk::{account::ReadableAccount, hash::Hash, pubkey::Pubkey, stake_history::Epoch},
|
||||
|
@ -26,29 +26,18 @@ lazy_static! {
|
|||
/// This struct contains what is needed to store accounts to a storage
|
||||
/// 1. account & pubkey (StorableAccounts)
|
||||
/// 2. hash per account (Maybe in StorableAccounts, otherwise has to be passed in separately)
|
||||
pub struct StorableAccountsWithHashes<
|
||||
'a: 'b,
|
||||
'b,
|
||||
T: ReadableAccount + Sync + 'b,
|
||||
U: StorableAccounts<'a, T>,
|
||||
V: Borrow<AccountHash>,
|
||||
> {
|
||||
pub struct StorableAccountsWithHashes<'a: 'b, 'b, U: StorableAccounts<'a>, V: Borrow<AccountHash>> {
|
||||
/// accounts to store
|
||||
/// always has pubkey and account
|
||||
/// may also have hash per account
|
||||
pub(crate) accounts: &'b U,
|
||||
/// if accounts does not have hash, this has a hash per account
|
||||
hashes: Option<Vec<V>>,
|
||||
_phantom: PhantomData<&'a T>,
|
||||
_phantom: PhantomData<&'a ()>,
|
||||
}
|
||||
|
||||
impl<
|
||||
'a: 'b,
|
||||
'b,
|
||||
T: ReadableAccount + Sync + 'b,
|
||||
U: StorableAccounts<'a, T>,
|
||||
V: Borrow<AccountHash>,
|
||||
> StorableAccountsWithHashes<'a, 'b, T, U, V>
|
||||
impl<'a: 'b, 'b, U: StorableAccounts<'a>, V: Borrow<AccountHash>>
|
||||
StorableAccountsWithHashes<'a, 'b, U, V>
|
||||
{
|
||||
/// used when accounts contains hash already
|
||||
pub fn new(accounts: &'b U) -> Self {
|
||||
|
@ -72,7 +61,7 @@ impl<
|
|||
}
|
||||
|
||||
/// get all account fields at 'index'
|
||||
pub fn get(&self, index: usize) -> (Option<&T>, &Pubkey, &AccountHash) {
|
||||
pub fn get(&self, index: usize) -> (Option<AccountForStorage>, &Pubkey, &AccountHash) {
|
||||
let account = self.accounts.account_default_if_zero_lamport(index);
|
||||
let pubkey = self.accounts.pubkey(index);
|
||||
let hash = if self.accounts.has_hash() {
|
||||
|
@ -87,7 +76,7 @@ impl<
|
|||
/// None if account at index has lamports == 0
|
||||
/// Otherwise, Some(account)
|
||||
/// This is the only way to access the account.
|
||||
pub fn account(&self, index: usize) -> Option<&T> {
|
||||
pub fn account(&self, index: usize) -> Option<AccountForStorage<'a>> {
|
||||
self.accounts.account_default_if_zero_lamport(index)
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ use {
|
|||
AccountsAddRootTiming, AccountsDb, LoadHint, LoadedAccount, ScanAccountStorageData,
|
||||
ScanStorageResult, VerifyAccountsHashAndLamportsConfig,
|
||||
},
|
||||
accounts_index::{IndexKey, ScanConfig, ScanError, ScanResult, ZeroLamport},
|
||||
accounts_index::{IndexKey, ScanConfig, ScanError, ScanResult},
|
||||
ancestors::Ancestors,
|
||||
storable_accounts::StorableAccounts,
|
||||
},
|
||||
|
@ -677,10 +677,7 @@ impl Accounts {
|
|||
.store_cached_inline_update_index((slot, &accounts_to_store[..]), Some(&transactions));
|
||||
}
|
||||
|
||||
pub fn store_accounts_cached<'a, T: ReadableAccount + Sync + ZeroLamport + 'a>(
|
||||
&self,
|
||||
accounts: impl StorableAccounts<'a, T>,
|
||||
) {
|
||||
pub fn store_accounts_cached<'a>(&self, accounts: impl StorableAccounts<'a>) {
|
||||
self.accounts_db.store_cached(accounts, None)
|
||||
}
|
||||
|
||||
|
|
|
@ -5969,17 +5969,11 @@ impl AccountsDb {
|
|||
AccountHash(Hash::new_from_array(hasher.finalize().into()))
|
||||
}
|
||||
|
||||
fn write_accounts_to_storage<
|
||||
'a,
|
||||
'b,
|
||||
T: ReadableAccount + Sync,
|
||||
U: StorableAccounts<'a, T>,
|
||||
V: Borrow<AccountHash>,
|
||||
>(
|
||||
fn write_accounts_to_storage<'a, 'b, U: StorableAccounts<'a>, V: Borrow<AccountHash>>(
|
||||
&self,
|
||||
slot: Slot,
|
||||
storage: &AccountStorageEntry,
|
||||
accounts_and_meta_to_store: &StorableAccountsWithHashes<'a, 'b, T, U, V>,
|
||||
accounts_and_meta_to_store: &StorableAccountsWithHashes<'a, 'b, U, V>,
|
||||
) -> Vec<AccountInfo> {
|
||||
let mut infos: Vec<AccountInfo> = Vec::with_capacity(accounts_and_meta_to_store.len());
|
||||
let mut total_append_accounts_us = 0;
|
||||
|
@ -6378,10 +6372,10 @@ impl AccountsDb {
|
|||
}
|
||||
}
|
||||
|
||||
fn write_accounts_to_cache<'a, 'b, T: ReadableAccount + Sync>(
|
||||
fn write_accounts_to_cache<'a, 'b>(
|
||||
&self,
|
||||
slot: Slot,
|
||||
accounts_and_meta_to_store: &impl StorableAccounts<'b, T>,
|
||||
accounts_and_meta_to_store: &impl StorableAccounts<'b>,
|
||||
txn_iter: Box<dyn std::iter::Iterator<Item = &Option<&SanitizedTransaction>> + 'a>,
|
||||
) -> Vec<AccountInfo> {
|
||||
let mut write_version_producer: Box<dyn Iterator<Item = u64>> =
|
||||
|
@ -6429,9 +6423,9 @@ impl AccountsDb {
|
|||
.collect()
|
||||
}
|
||||
|
||||
fn store_accounts_to<'a: 'c, 'b, 'c, T: ReadableAccount + Sync + ZeroLamport + 'b>(
|
||||
fn store_accounts_to<'a: 'c, 'b, 'c>(
|
||||
&self,
|
||||
accounts: &'c impl StorableAccounts<'b, T>,
|
||||
accounts: &'c impl StorableAccounts<'b>,
|
||||
hashes: Option<Vec<impl Borrow<AccountHash>>>,
|
||||
store_to: &StoreTo,
|
||||
transactions: Option<&[Option<&'a SanitizedTransaction>]>,
|
||||
|
@ -6473,7 +6467,7 @@ impl AccountsDb {
|
|||
self.write_accounts_to_storage(
|
||||
slot,
|
||||
storage,
|
||||
&StorableAccountsWithHashes::<'_, '_, _, _, &AccountHash>::new(accounts),
|
||||
&StorableAccountsWithHashes::<'_, '_, _, &AccountHash>::new(accounts),
|
||||
)
|
||||
} else {
|
||||
match hashes {
|
||||
|
@ -6490,7 +6484,7 @@ impl AccountsDb {
|
|||
for index in 0..accounts.len() {
|
||||
let (pubkey, account) =
|
||||
(accounts.pubkey(index), accounts.account(index));
|
||||
let hash = Self::hash_account(account, pubkey);
|
||||
let hash = Self::hash_account(&account, pubkey);
|
||||
hashes.push(hash);
|
||||
}
|
||||
hash_time.stop();
|
||||
|
@ -7772,10 +7766,10 @@ impl AccountsDb {
|
|||
self.bank_hash_stats.lock().unwrap().get(&slot).cloned()
|
||||
}
|
||||
|
||||
fn update_index<'a, T: ReadableAccount + Sync>(
|
||||
fn update_index<'a>(
|
||||
&self,
|
||||
infos: Vec<AccountInfo>,
|
||||
accounts: &impl StorableAccounts<'a, T>,
|
||||
accounts: &impl StorableAccounts<'a>,
|
||||
reclaim: UpsertReclaim,
|
||||
update_index_thread_selection: UpdateIndexThreadSelection,
|
||||
) -> SlotList<AccountInfo> {
|
||||
|
@ -7796,7 +7790,7 @@ impl AccountsDb {
|
|||
target_slot,
|
||||
old_slot,
|
||||
pubkey,
|
||||
pubkey_account.1,
|
||||
&pubkey_account.1,
|
||||
&self.account_indexes,
|
||||
info,
|
||||
&mut reclaims,
|
||||
|
@ -8159,9 +8153,9 @@ impl AccountsDb {
|
|||
.fetch_add(measure.as_us(), Ordering::Relaxed);
|
||||
}
|
||||
|
||||
pub fn store_cached<'a, T: ReadableAccount + Sync + ZeroLamport + 'a>(
|
||||
pub fn store_cached<'a>(
|
||||
&self,
|
||||
accounts: impl StorableAccounts<'a, T>,
|
||||
accounts: impl StorableAccounts<'a>,
|
||||
transactions: Option<&'a [Option<&'a SanitizedTransaction>]>,
|
||||
) {
|
||||
self.store(
|
||||
|
@ -8173,12 +8167,9 @@ impl AccountsDb {
|
|||
);
|
||||
}
|
||||
|
||||
pub(crate) fn store_cached_inline_update_index<
|
||||
'a,
|
||||
T: ReadableAccount + Sync + ZeroLamport + 'a,
|
||||
>(
|
||||
pub(crate) fn store_cached_inline_update_index<'a>(
|
||||
&self,
|
||||
accounts: impl StorableAccounts<'a, T>,
|
||||
accounts: impl StorableAccounts<'a>,
|
||||
transactions: Option<&'a [Option<&'a SanitizedTransaction>]>,
|
||||
) {
|
||||
self.store(
|
||||
|
@ -8203,9 +8194,9 @@ impl AccountsDb {
|
|||
);
|
||||
}
|
||||
|
||||
fn store<'a, T: ReadableAccount + Sync + ZeroLamport + 'a>(
|
||||
fn store<'a>(
|
||||
&self,
|
||||
accounts: impl StorableAccounts<'a, T>,
|
||||
accounts: impl StorableAccounts<'a>,
|
||||
store_to: &StoreTo,
|
||||
transactions: Option<&'a [Option<&'a SanitizedTransaction>]>,
|
||||
reclaim: StoreReclaims,
|
||||
|
@ -8222,7 +8213,7 @@ impl AccountsDb {
|
|||
(0..accounts.len()).for_each(|index| {
|
||||
let account = accounts.account(index);
|
||||
total_data += account.data().len();
|
||||
stats.update(account);
|
||||
stats.update(&account);
|
||||
});
|
||||
|
||||
self.stats
|
||||
|
@ -8389,9 +8380,9 @@ impl AccountsDb {
|
|||
}
|
||||
}
|
||||
|
||||
fn store_accounts_unfrozen<'a, T: ReadableAccount + Sync + ZeroLamport + 'a>(
|
||||
fn store_accounts_unfrozen<'a>(
|
||||
&self,
|
||||
accounts: impl StorableAccounts<'a, T>,
|
||||
accounts: impl StorableAccounts<'a>,
|
||||
hashes: Option<Vec<impl Borrow<AccountHash>>>,
|
||||
store_to: &StoreTo,
|
||||
transactions: Option<&'a [Option<&'a SanitizedTransaction>]>,
|
||||
|
@ -8417,9 +8408,9 @@ impl AccountsDb {
|
|||
);
|
||||
}
|
||||
|
||||
pub fn store_accounts_frozen<'a, T: ReadableAccount + Sync + ZeroLamport + 'a>(
|
||||
pub fn store_accounts_frozen<'a>(
|
||||
&self,
|
||||
accounts: impl StorableAccounts<'a, T>,
|
||||
accounts: impl StorableAccounts<'a>,
|
||||
hashes: Option<Vec<impl Borrow<AccountHash>>>,
|
||||
storage: &Arc<AccountStorageEntry>,
|
||||
) -> StoreAccountsTiming {
|
||||
|
@ -8438,9 +8429,9 @@ impl AccountsDb {
|
|||
)
|
||||
}
|
||||
|
||||
fn store_accounts_custom<'a, T: ReadableAccount + Sync + ZeroLamport + 'a>(
|
||||
fn store_accounts_custom<'a>(
|
||||
&self,
|
||||
accounts: impl StorableAccounts<'a, T>,
|
||||
accounts: impl StorableAccounts<'a>,
|
||||
hashes: Option<Vec<impl Borrow<AccountHash>>>,
|
||||
store_to: &StoreTo,
|
||||
reset_accounts: bool,
|
||||
|
@ -9568,6 +9559,7 @@ pub mod tests {
|
|||
ancient_append_vecs,
|
||||
append_vec::{test_utils::TempFile, AppendVec, AppendVecStoredAccountMeta},
|
||||
cache_hash_data::CacheHashDataFile,
|
||||
storable_accounts::AccountForStorage,
|
||||
},
|
||||
assert_matches::assert_matches,
|
||||
itertools::Itertools,
|
||||
|
@ -9636,14 +9628,15 @@ pub mod tests {
|
|||
}
|
||||
|
||||
/// this tuple contains slot info PER account
|
||||
impl<'a, T: ReadableAccount + Sync> StorableAccounts<'a, T>
|
||||
for (Slot, &'a [(&'a Pubkey, &'a T, Slot)])
|
||||
impl<'a, T: ReadableAccount + Sync> StorableAccounts<'a> for (Slot, &'a [(&'a Pubkey, &'a T, Slot)])
|
||||
where
|
||||
AccountForStorage<'a>: From<&'a T>,
|
||||
{
|
||||
fn pubkey(&self, index: usize) -> &Pubkey {
|
||||
self.1[index].0
|
||||
}
|
||||
fn account(&self, index: usize) -> &T {
|
||||
self.1[index].1
|
||||
fn account(&self, index: usize) -> AccountForStorage<'a> {
|
||||
self.1[index].1.into()
|
||||
}
|
||||
fn slot(&self, index: usize) -> Slot {
|
||||
// note that this could be different than 'target_slot()' PER account
|
||||
|
|
|
@ -10,11 +10,7 @@ use {
|
|||
error::TieredStorageError, hot::HOT_FORMAT, index::IndexOffset, TieredStorage,
|
||||
},
|
||||
},
|
||||
solana_sdk::{
|
||||
account::{AccountSharedData, ReadableAccount},
|
||||
clock::Slot,
|
||||
pubkey::Pubkey,
|
||||
},
|
||||
solana_sdk::{account::AccountSharedData, clock::Slot, pubkey::Pubkey},
|
||||
std::{
|
||||
borrow::Borrow,
|
||||
io::Read,
|
||||
|
@ -249,15 +245,9 @@ impl AccountsFile {
|
|||
/// So, return.len() is 1 + (number of accounts written)
|
||||
/// After each account is appended, the internal `current_len` is updated
|
||||
/// and will be available to other threads.
|
||||
pub fn append_accounts<
|
||||
'a,
|
||||
'b,
|
||||
T: ReadableAccount + Sync,
|
||||
U: StorableAccounts<'a, T>,
|
||||
V: Borrow<AccountHash>,
|
||||
>(
|
||||
pub fn append_accounts<'a, 'b, U: StorableAccounts<'a>, V: Borrow<AccountHash>>(
|
||||
&self,
|
||||
accounts: &StorableAccountsWithHashes<'a, 'b, T, U, V>,
|
||||
accounts: &StorableAccountsWithHashes<'a, 'b, U, V>,
|
||||
skip: usize,
|
||||
) -> Option<Vec<StoredAccountInfo>> {
|
||||
match self {
|
||||
|
|
|
@ -12,14 +12,14 @@ use {
|
|||
},
|
||||
accounts_file::AccountsFile,
|
||||
accounts_hash::AccountHash,
|
||||
accounts_index::{AccountsIndexScanResult, ZeroLamport},
|
||||
accounts_index::AccountsIndexScanResult,
|
||||
active_stats::ActiveStatItem,
|
||||
storable_accounts::{StorableAccounts, StorableAccountsBySlot},
|
||||
},
|
||||
rand::{thread_rng, Rng},
|
||||
rayon::prelude::{IntoParallelIterator, IntoParallelRefIterator, ParallelIterator},
|
||||
solana_measure::measure_us,
|
||||
solana_sdk::{account::ReadableAccount, clock::Slot},
|
||||
solana_sdk::clock::Slot,
|
||||
std::{
|
||||
collections::HashMap,
|
||||
num::{NonZeroU64, Saturating},
|
||||
|
@ -440,10 +440,10 @@ impl AccountsDb {
|
|||
/// create append vec of size 'bytes'
|
||||
/// write 'accounts_to_write' into it
|
||||
/// return shrink_in_progress and some metrics
|
||||
fn write_ancient_accounts<'a, 'b: 'a, T: ReadableAccount + Sync + ZeroLamport + 'a>(
|
||||
fn write_ancient_accounts<'a, 'b: 'a>(
|
||||
&'b self,
|
||||
bytes: u64,
|
||||
accounts_to_write: impl StorableAccounts<'a, T>,
|
||||
accounts_to_write: impl StorableAccounts<'a>,
|
||||
write_ancient_accounts: &mut WriteAncientAccounts<'b>,
|
||||
) {
|
||||
let target_slot = accounts_to_write.target_slot();
|
||||
|
|
|
@ -733,15 +733,9 @@ impl AppendVec {
|
|||
/// So, return.len() is 1 + (number of accounts written)
|
||||
/// After each account is appended, the internal `current_len` is updated
|
||||
/// and will be available to other threads.
|
||||
pub fn append_accounts<
|
||||
'a,
|
||||
'b,
|
||||
T: ReadableAccount + Sync,
|
||||
U: StorableAccounts<'a, T>,
|
||||
V: Borrow<AccountHash>,
|
||||
>(
|
||||
pub fn append_accounts<'a, 'b, U: StorableAccounts<'a>, V: Borrow<AccountHash>>(
|
||||
&self,
|
||||
accounts: &StorableAccountsWithHashes<'a, 'b, T, U, V>,
|
||||
accounts: &StorableAccountsWithHashes<'a, 'b, U, V>,
|
||||
skip: usize,
|
||||
) -> Option<Vec<StoredAccountInfo>> {
|
||||
let _lock = self.append_lock.lock().unwrap();
|
||||
|
@ -775,6 +769,7 @@ impl AppendVec {
|
|||
let account_meta_ptr = &account_meta as *const AccountMeta;
|
||||
let data_len = stored_meta.data_len as usize;
|
||||
let data_ptr = account
|
||||
.as_ref()
|
||||
.map(|account| account.data())
|
||||
.unwrap_or_default()
|
||||
.as_ptr();
|
||||
|
@ -902,7 +897,7 @@ pub mod tests {
|
|||
// for (Slot, &'a [(&'a Pubkey, &'a T)])
|
||||
let slot = 0 as Slot;
|
||||
let pubkey = Pubkey::default();
|
||||
StorableAccountsWithHashes::<'_, '_, _, _, &AccountHash>::new(&(
|
||||
StorableAccountsWithHashes::<'_, '_, _, &AccountHash>::new(&(
|
||||
slot,
|
||||
&[(&pubkey, &account)][..],
|
||||
));
|
||||
|
@ -996,7 +991,7 @@ pub mod tests {
|
|||
let accounts2 = (slot, &accounts[..]);
|
||||
let storable = StorableAccountsWithHashes::new_with_hashes(&accounts2, hashes);
|
||||
let get_account = storable.account(0);
|
||||
assert!(accounts_equal(&account, get_account.unwrap()));
|
||||
assert!(accounts_equal(&account, &get_account.unwrap()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! Code for stake and vote rewards
|
||||
|
||||
use {
|
||||
crate::storable_accounts::StorableAccounts,
|
||||
crate::storable_accounts::{AccountForStorage, StorableAccounts},
|
||||
solana_sdk::{
|
||||
account::AccountSharedData, clock::Slot, pubkey::Pubkey, reward_info::RewardInfo,
|
||||
},
|
||||
|
@ -21,12 +21,13 @@ impl StakeReward {
|
|||
}
|
||||
|
||||
/// allow [StakeReward] to be passed to `StoreAccounts` directly without copies or vec construction
|
||||
impl<'a> StorableAccounts<'a, AccountSharedData> for (Slot, &'a [StakeReward]) {
|
||||
impl<'a> StorableAccounts<'a> for (Slot, &'a [StakeReward]) {
|
||||
fn pubkey(&self, index: usize) -> &Pubkey {
|
||||
&self.1[index].stake_pubkey
|
||||
}
|
||||
fn account(&self, index: usize) -> &AccountSharedData {
|
||||
&self.1[index].stake_account
|
||||
fn account(&self, index: usize) -> AccountForStorage<'a> {
|
||||
let entry = &self.1[index];
|
||||
(&entry.stake_account).into()
|
||||
}
|
||||
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
|
||||
|
|
|
@ -1,21 +1,92 @@
|
|||
//! trait for abstracting underlying storage of pubkey and account pairs to be written
|
||||
use {
|
||||
crate::{account_storage::meta::StoredAccountMeta, accounts_hash::AccountHash},
|
||||
solana_sdk::{account::ReadableAccount, clock::Slot, pubkey::Pubkey},
|
||||
crate::{
|
||||
account_storage::meta::StoredAccountMeta, accounts_hash::AccountHash,
|
||||
accounts_index::ZeroLamport,
|
||||
},
|
||||
solana_sdk::{
|
||||
account::{AccountSharedData, ReadableAccount},
|
||||
clock::{Epoch, Slot},
|
||||
pubkey::Pubkey,
|
||||
},
|
||||
};
|
||||
|
||||
/// hold a ref to an account to store. The account could be represented in memory a few different ways
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum AccountForStorage<'a> {
|
||||
AccountSharedData(&'a AccountSharedData),
|
||||
StoredAccountMeta(&'a StoredAccountMeta<'a>),
|
||||
}
|
||||
|
||||
impl<'a> From<&'a AccountSharedData> for AccountForStorage<'a> {
|
||||
fn from(source: &'a AccountSharedData) -> Self {
|
||||
Self::AccountSharedData(source)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a StoredAccountMeta<'a>> for AccountForStorage<'a> {
|
||||
fn from(source: &'a StoredAccountMeta<'a>) -> Self {
|
||||
Self::StoredAccountMeta(source)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ZeroLamport for AccountForStorage<'a> {
|
||||
fn is_zero_lamport(&self) -> bool {
|
||||
self.lamports() == 0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ReadableAccount for AccountForStorage<'a> {
|
||||
fn lamports(&self) -> u64 {
|
||||
match self {
|
||||
AccountForStorage::AccountSharedData(account) => account.lamports(),
|
||||
AccountForStorage::StoredAccountMeta(account) => account.lamports(),
|
||||
}
|
||||
}
|
||||
fn data(&self) -> &[u8] {
|
||||
match self {
|
||||
AccountForStorage::AccountSharedData(account) => account.data(),
|
||||
AccountForStorage::StoredAccountMeta(account) => account.data(),
|
||||
}
|
||||
}
|
||||
fn owner(&self) -> &Pubkey {
|
||||
match self {
|
||||
AccountForStorage::AccountSharedData(account) => account.owner(),
|
||||
AccountForStorage::StoredAccountMeta(account) => account.owner(),
|
||||
}
|
||||
}
|
||||
fn executable(&self) -> bool {
|
||||
match self {
|
||||
AccountForStorage::AccountSharedData(account) => account.executable(),
|
||||
AccountForStorage::StoredAccountMeta(account) => account.executable(),
|
||||
}
|
||||
}
|
||||
fn rent_epoch(&self) -> Epoch {
|
||||
match self {
|
||||
AccountForStorage::AccountSharedData(account) => account.rent_epoch(),
|
||||
AccountForStorage::StoredAccountMeta(account) => account.rent_epoch(),
|
||||
}
|
||||
}
|
||||
fn to_account_shared_data(&self) -> AccountSharedData {
|
||||
match self {
|
||||
AccountForStorage::AccountSharedData(account) => account.to_account_shared_data(),
|
||||
AccountForStorage::StoredAccountMeta(account) => account.to_account_shared_data(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// abstract access to pubkey, account, slot, target_slot of either:
|
||||
/// a. (slot, &[&Pubkey, &ReadableAccount])
|
||||
/// b. (slot, &[&Pubkey, &ReadableAccount, Slot]) (we will use this later)
|
||||
/// This trait avoids having to allocate redundant data when there is a duplicated slot parameter.
|
||||
/// All legacy callers do not have a unique slot per account to store.
|
||||
pub trait StorableAccounts<'a, T: ReadableAccount + Sync>: Sync {
|
||||
pub trait StorableAccounts<'a>: Sync {
|
||||
/// pubkey at 'index'
|
||||
fn pubkey(&self, index: usize) -> &Pubkey;
|
||||
/// account at 'index'
|
||||
fn account(&self, index: usize) -> &T;
|
||||
fn account(&self, index: usize) -> AccountForStorage<'a>;
|
||||
/// None if account is zero lamports
|
||||
fn account_default_if_zero_lamport(&self, index: usize) -> Option<&T> {
|
||||
fn account_default_if_zero_lamport(&self, index: usize) -> Option<AccountForStorage<'a>> {
|
||||
let account = self.account(index);
|
||||
(account.lamports() != 0).then_some(account)
|
||||
}
|
||||
|
@ -61,12 +132,15 @@ pub struct StorableAccountsMovingSlots<'a, T: ReadableAccount + Sync> {
|
|||
pub old_slot: Slot,
|
||||
}
|
||||
|
||||
impl<'a, T: ReadableAccount + Sync> StorableAccounts<'a, T> for StorableAccountsMovingSlots<'a, T> {
|
||||
impl<'a, T: ReadableAccount + Sync> StorableAccounts<'a> for StorableAccountsMovingSlots<'a, T>
|
||||
where
|
||||
AccountForStorage<'a>: From<&'a T>,
|
||||
{
|
||||
fn pubkey(&self, index: usize) -> &Pubkey {
|
||||
self.accounts[index].0
|
||||
}
|
||||
fn account(&self, index: usize) -> &T {
|
||||
self.accounts[index].1
|
||||
fn account(&self, index: usize) -> AccountForStorage<'a> {
|
||||
self.accounts[index].1.into()
|
||||
}
|
||||
fn slot(&self, _index: usize) -> Slot {
|
||||
// per-index slot is not unique per slot, but it is different than 'target_slot'
|
||||
|
@ -80,12 +154,16 @@ impl<'a, T: ReadableAccount + Sync> StorableAccounts<'a, T> for StorableAccounts
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ReadableAccount + Sync> StorableAccounts<'a, T> for (Slot, &'a [(&'a Pubkey, &'a T)]) {
|
||||
impl<'a: 'b, 'b, T: ReadableAccount + Sync + 'a> StorableAccounts<'a>
|
||||
for (Slot, &'b [(&'a Pubkey, &'a T)])
|
||||
where
|
||||
AccountForStorage<'a>: From<&'a T>,
|
||||
{
|
||||
fn pubkey(&self, index: usize) -> &Pubkey {
|
||||
self.1[index].0
|
||||
}
|
||||
fn account(&self, index: usize) -> &T {
|
||||
self.1[index].1
|
||||
fn account(&self, index: usize) -> AccountForStorage<'a> {
|
||||
self.1[index].1.into()
|
||||
}
|
||||
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
|
||||
|
@ -98,13 +176,15 @@ impl<'a, T: ReadableAccount + Sync> StorableAccounts<'a, T> for (Slot, &'a [(&'a
|
|||
self.1.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ReadableAccount + Sync> StorableAccounts<'a, T> for (Slot, &'a [&'a (Pubkey, T)]) {
|
||||
impl<'a, T: ReadableAccount + Sync> StorableAccounts<'a> for (Slot, &'a [&'a (Pubkey, T)])
|
||||
where
|
||||
AccountForStorage<'a>: From<&'a T>,
|
||||
{
|
||||
fn pubkey(&self, index: usize) -> &Pubkey {
|
||||
&self.1[index].0
|
||||
}
|
||||
fn account(&self, index: usize) -> &T {
|
||||
&self.1[index].1
|
||||
fn account(&self, index: usize) -> AccountForStorage<'a> {
|
||||
(&self.1[index].1).into()
|
||||
}
|
||||
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
|
||||
|
@ -118,12 +198,12 @@ impl<'a, T: ReadableAccount + Sync> StorableAccounts<'a, T> for (Slot, &'a [&'a
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> StorableAccounts<'a, StoredAccountMeta<'a>> for (Slot, &'a [&'a StoredAccountMeta<'a>]) {
|
||||
impl<'a> StorableAccounts<'a> for (Slot, &'a [&'a StoredAccountMeta<'a>]) {
|
||||
fn pubkey(&self, index: usize) -> &Pubkey {
|
||||
self.1[index].pubkey()
|
||||
}
|
||||
fn account(&self, index: usize) -> &StoredAccountMeta<'a> {
|
||||
self.1[index]
|
||||
fn account(&self, index: usize) -> AccountForStorage<'a> {
|
||||
self.1[index].into()
|
||||
}
|
||||
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
|
||||
|
@ -206,14 +286,14 @@ impl<'a> StorableAccountsBySlot<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> StorableAccounts<'a, StoredAccountMeta<'a>> for StorableAccountsBySlot<'a> {
|
||||
impl<'a> StorableAccounts<'a> for StorableAccountsBySlot<'a> {
|
||||
fn pubkey(&self, index: usize) -> &Pubkey {
|
||||
let indexes = self.find_internal_index(index);
|
||||
self.slots_and_accounts[indexes.0].1[indexes.1].pubkey()
|
||||
}
|
||||
fn account(&self, index: usize) -> &StoredAccountMeta<'a> {
|
||||
fn account(&self, index: usize) -> AccountForStorage<'a> {
|
||||
let indexes = self.find_internal_index(index);
|
||||
self.slots_and_accounts[indexes.0].1[indexes.1]
|
||||
self.slots_and_accounts[indexes.0].1[indexes.1].into()
|
||||
}
|
||||
fn slot(&self, index: usize) -> Slot {
|
||||
let indexes = self.find_internal_index(index);
|
||||
|
@ -239,14 +319,12 @@ impl<'a> StorableAccounts<'a, StoredAccountMeta<'a>> for StorableAccountsBySlot<
|
|||
|
||||
/// this tuple contains a single different source slot that applies to all accounts
|
||||
/// accounts are StoredAccountMeta
|
||||
impl<'a> StorableAccounts<'a, StoredAccountMeta<'a>>
|
||||
for (Slot, &'a [&'a StoredAccountMeta<'a>], Slot)
|
||||
{
|
||||
impl<'a> StorableAccounts<'a> for (Slot, &'a [&'a StoredAccountMeta<'a>], Slot) {
|
||||
fn pubkey(&self, index: usize) -> &Pubkey {
|
||||
self.1[index].pubkey()
|
||||
}
|
||||
fn account(&self, index: usize) -> &StoredAccountMeta<'a> {
|
||||
self.1[index]
|
||||
fn account(&self, index: usize) -> AccountForStorage<'a> {
|
||||
self.1[index].into()
|
||||
}
|
||||
fn slot(&self, _index: usize) -> Slot {
|
||||
// same other slot for all accounts
|
||||
|
@ -280,20 +358,13 @@ pub mod tests {
|
|||
},
|
||||
};
|
||||
|
||||
fn compare<
|
||||
'a,
|
||||
T: ReadableAccount + Sync + PartialEq + std::fmt::Debug,
|
||||
U: ReadableAccount + Sync + PartialEq + std::fmt::Debug,
|
||||
>(
|
||||
a: &impl StorableAccounts<'a, T>,
|
||||
b: &impl StorableAccounts<'a, U>,
|
||||
) {
|
||||
fn compare<'a>(a: &impl StorableAccounts<'a>, b: &impl StorableAccounts<'a>) {
|
||||
assert_eq!(a.target_slot(), b.target_slot());
|
||||
assert_eq!(a.len(), b.len());
|
||||
assert_eq!(a.is_empty(), b.is_empty());
|
||||
(0..a.len()).for_each(|i| {
|
||||
assert_eq!(a.pubkey(i), b.pubkey(i));
|
||||
assert!(accounts_equal(a.account(i), b.account(i)));
|
||||
assert!(accounts_equal(&a.account(i), &b.account(i)));
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -415,7 +486,7 @@ pub mod tests {
|
|||
compare(&test2, &test_moving_slots2);
|
||||
for (i, raw) in raw.iter().enumerate() {
|
||||
assert_eq!(raw.0, *test3.pubkey(i));
|
||||
assert!(accounts_equal(&raw.1, test3.account(i)));
|
||||
assert!(accounts_equal(&raw.1, &test3.account(i)));
|
||||
assert_eq!(raw.2, test3.slot(i));
|
||||
assert_eq!(target_slot, test4.slot(i));
|
||||
assert_eq!(target_slot, test2.slot(i));
|
||||
|
@ -516,7 +587,7 @@ pub mod tests {
|
|||
assert_eq!(entries0 != entries, storable.contains_multiple_slots());
|
||||
(0..entries).for_each(|index| {
|
||||
let index = index as usize;
|
||||
assert_eq!(storable.account(index), &raw2[index]);
|
||||
assert!(accounts_equal(&storable.account(index), &raw2[index]));
|
||||
assert_eq!(storable.pubkey(index), raw2[index].pubkey());
|
||||
assert_eq!(storable.hash(index), raw2[index].hash());
|
||||
assert_eq!(storable.slot(index), expected_slots[index]);
|
||||
|
|
|
@ -24,7 +24,6 @@ use {
|
|||
index::IndexBlockFormat,
|
||||
owners::OwnersBlockFormat,
|
||||
readable::TieredStorageReader,
|
||||
solana_sdk::account::ReadableAccount,
|
||||
std::{
|
||||
borrow::Borrow,
|
||||
fs, io,
|
||||
|
@ -111,15 +110,9 @@ impl TieredStorage {
|
|||
///
|
||||
/// Note that this function can only be called once per a TieredStorage
|
||||
/// instance. Otherwise, it will trigger panic.
|
||||
pub fn write_accounts<
|
||||
'a,
|
||||
'b,
|
||||
T: ReadableAccount + Sync,
|
||||
U: StorableAccounts<'a, T>,
|
||||
V: Borrow<AccountHash>,
|
||||
>(
|
||||
pub fn write_accounts<'a, 'b, U: StorableAccounts<'a>, V: Borrow<AccountHash>>(
|
||||
&self,
|
||||
accounts: &StorableAccountsWithHashes<'a, 'b, T, U, V>,
|
||||
accounts: &StorableAccountsWithHashes<'a, 'b, U, V>,
|
||||
skip: usize,
|
||||
format: &TieredStorageFormat,
|
||||
) -> TieredStorageResult<Vec<StoredAccountInfo>> {
|
||||
|
@ -378,7 +371,7 @@ mod tests {
|
|||
if let Some(account) = expected_accounts_map.get(stored_account_meta.pubkey()) {
|
||||
verify_test_account_with_footer(
|
||||
&stored_account_meta,
|
||||
*account,
|
||||
account.as_ref(),
|
||||
stored_account_meta.pubkey(),
|
||||
footer,
|
||||
);
|
||||
|
|
|
@ -731,15 +731,9 @@ impl HotStorageWriter {
|
|||
/// Persists `accounts` into the underlying hot accounts file associated
|
||||
/// with this HotStorageWriter. The first `skip` number of accounts are
|
||||
/// *not* persisted.
|
||||
pub fn write_accounts<
|
||||
'a,
|
||||
'b,
|
||||
T: ReadableAccount + Sync,
|
||||
U: StorableAccounts<'a, T>,
|
||||
V: Borrow<AccountHash>,
|
||||
>(
|
||||
pub fn write_accounts<'a, 'b, U: StorableAccounts<'a>, V: Borrow<AccountHash>>(
|
||||
&mut self,
|
||||
accounts: &StorableAccountsWithHashes<'a, 'b, T, U, V>,
|
||||
accounts: &StorableAccountsWithHashes<'a, 'b, U, V>,
|
||||
skip: usize,
|
||||
) -> TieredStorageResult<Vec<StoredAccountInfo>> {
|
||||
let mut footer = new_hot_footer();
|
||||
|
@ -763,6 +757,7 @@ impl HotStorageWriter {
|
|||
// Obtain necessary fields from the account, or default fields
|
||||
// for a zero-lamport account in the None case.
|
||||
let (lamports, owner, data, executable, rent_epoch) = account
|
||||
.as_ref()
|
||||
.map(|acc| {
|
||||
(
|
||||
acc.lamports(),
|
||||
|
@ -1565,7 +1560,7 @@ mod tests {
|
|||
.unwrap();
|
||||
|
||||
let (account, address, _account_hash) = storable_accounts.get(i);
|
||||
verify_test_account(&stored_account_meta, account, address);
|
||||
verify_test_account(&stored_account_meta, account.as_ref(), address);
|
||||
|
||||
assert_eq!(i + 1, next.0 as usize);
|
||||
}
|
||||
|
@ -1583,7 +1578,7 @@ mod tests {
|
|||
.unwrap();
|
||||
|
||||
let (account, address, _account_hash) = storable_accounts.get(stored_info.offset);
|
||||
verify_test_account(&stored_account_meta, account, address);
|
||||
verify_test_account(&stored_account_meta, account.as_ref(), address);
|
||||
}
|
||||
|
||||
// verify get_accounts
|
||||
|
@ -1592,7 +1587,7 @@ mod tests {
|
|||
// first, we verify everything
|
||||
for (i, stored_meta) in accounts.iter().enumerate() {
|
||||
let (account, address, _account_hash) = storable_accounts.get(i);
|
||||
verify_test_account(stored_meta, account, address);
|
||||
verify_test_account(stored_meta, account.as_ref(), address);
|
||||
}
|
||||
|
||||
// second, we verify various initial position
|
||||
|
|
|
@ -21,8 +21,12 @@ use {
|
|||
},
|
||||
solana_runtime::bank::Bank,
|
||||
solana_sdk::{
|
||||
account::Account, feature_set::apply_cost_tracker_during_replay, signature::Keypair,
|
||||
signer::Signer, stake_history::Epoch, system_program, system_transaction,
|
||||
account::{Account, ReadableAccount},
|
||||
feature_set::apply_cost_tracker_during_replay,
|
||||
signature::Keypair,
|
||||
signer::Signer,
|
||||
stake_history::Epoch,
|
||||
system_program, system_transaction,
|
||||
transaction::SanitizedTransaction,
|
||||
},
|
||||
std::sync::{
|
||||
|
@ -55,7 +59,8 @@ fn create_funded_accounts(bank: &Bank, num: usize) -> Vec<Keypair> {
|
|||
owner: system_program::id(),
|
||||
executable: false,
|
||||
rent_epoch: Epoch::MAX,
|
||||
},
|
||||
}
|
||||
.to_account_shared_data(),
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -16,8 +16,12 @@ use {
|
|||
transaction_batch::TransactionBatch,
|
||||
},
|
||||
solana_sdk::{
|
||||
account::Account, feature_set::apply_cost_tracker_during_replay, signature::Keypair,
|
||||
signer::Signer, stake_history::Epoch, system_program, system_transaction,
|
||||
account::{Account, ReadableAccount},
|
||||
feature_set::apply_cost_tracker_during_replay,
|
||||
signature::Keypair,
|
||||
signer::Signer,
|
||||
stake_history::Epoch,
|
||||
system_program, system_transaction,
|
||||
transaction::SanitizedTransaction,
|
||||
},
|
||||
std::{borrow::Cow, sync::Arc},
|
||||
|
@ -46,7 +50,8 @@ fn create_funded_accounts(bank: &Bank, num: usize) -> Vec<Keypair> {
|
|||
owner: system_program::id(),
|
||||
executable: false,
|
||||
rent_epoch: Epoch::MAX,
|
||||
},
|
||||
}
|
||||
.to_account_shared_data(),
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ use {
|
|||
epoch_accounts_hash::EpochAccountsHash,
|
||||
sorted_storages::SortedStorages,
|
||||
stake_rewards::StakeReward,
|
||||
storable_accounts::StorableAccounts,
|
||||
storable_accounts::{AccountForStorage, StorableAccounts},
|
||||
},
|
||||
solana_bpf_loader_program::syscalls::create_program_runtime_environment_v1,
|
||||
solana_cost_model::cost_tracker::CostTracker,
|
||||
|
@ -3094,7 +3094,7 @@ impl Bank {
|
|||
self.get_account(pubkey).is_none(),
|
||||
"{pubkey} repeated in genesis config"
|
||||
);
|
||||
self.store_account(pubkey, account);
|
||||
self.store_account(pubkey, &account.to_account_shared_data());
|
||||
self.capitalization.fetch_add(account.lamports(), Relaxed);
|
||||
self.accounts_data_size_initial += account.data().len() as u64;
|
||||
}
|
||||
|
@ -3107,7 +3107,7 @@ impl Bank {
|
|||
self.get_account(pubkey).is_none(),
|
||||
"{pubkey} repeated in genesis config"
|
||||
);
|
||||
self.store_account(pubkey, account);
|
||||
self.store_account(pubkey, &account.to_account_shared_data());
|
||||
self.accounts_data_size_initial += account.data().len() as u64;
|
||||
}
|
||||
|
||||
|
@ -5170,25 +5170,24 @@ impl Bank {
|
|||
|
||||
/// fn store the single `account` with `pubkey`.
|
||||
/// Uses `store_accounts`, which works on a vector of accounts.
|
||||
pub fn store_account<T: ReadableAccount + Sync + ZeroLamport>(
|
||||
pub fn store_account<'a, T: ReadableAccount + Sync + ZeroLamport + 'a>(
|
||||
&self,
|
||||
pubkey: &Pubkey,
|
||||
account: &T,
|
||||
) {
|
||||
pubkey: &'a Pubkey,
|
||||
account: &'a T,
|
||||
) where
|
||||
AccountForStorage<'a>: From<&'a T>,
|
||||
{
|
||||
self.store_accounts((self.slot(), &[(pubkey, account)][..]))
|
||||
}
|
||||
|
||||
pub fn store_accounts<'a, T: ReadableAccount + Sync + ZeroLamport + 'a>(
|
||||
&self,
|
||||
accounts: impl StorableAccounts<'a, T>,
|
||||
) {
|
||||
pub fn store_accounts<'a>(&self, accounts: impl StorableAccounts<'a>) {
|
||||
assert!(!self.freeze_started());
|
||||
let mut m = Measure::start("stakes_cache.check_and_store");
|
||||
let new_warmup_cooldown_rate_epoch = self.new_warmup_cooldown_rate_epoch();
|
||||
(0..accounts.len()).for_each(|i| {
|
||||
self.stakes_cache.check_and_store(
|
||||
accounts.pubkey(i),
|
||||
accounts.account(i),
|
||||
&accounts.account(i),
|
||||
new_warmup_cooldown_rate_epoch,
|
||||
)
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue