introduce AccountForStorage for StorableAccounts (#795)

introduce `AccountForStorage` for `StorableAccounts`
This commit is contained in:
Jeff Washington (jwash) 2024-04-15 13:21:07 -05:00 committed by GitHub
parent 0288e0db29
commit 6bd0bb611c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 209 additions and 173 deletions

View File

@ -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();

View File

@ -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(),

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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

View File

@ -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 {

View File

@ -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();

View File

@ -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]

View File

@ -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

View File

@ -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]);

View File

@ -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,
);

View File

@ -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

View File

@ -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(),
);
});

View File

@ -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(),
);
});

View File

@ -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,
)
});