write Option<AccountSharedData> (#16874)

* write Option<&AccountSharedData>

* add comment
This commit is contained in:
Jeff Washington (jwash)
2021-04-28 08:47:26 -05:00
committed by GitHub
parent 25054bfd35
commit 1864bc2080
2 changed files with 81 additions and 24 deletions

View File

@ -3323,7 +3323,7 @@ impl AccountsDb {
slot: Slot, slot: Slot,
hashes: &[impl Borrow<Hash>], hashes: &[impl Borrow<Hash>],
mut storage_finder: F, mut storage_finder: F,
accounts_and_meta_to_store: &[(StoredMeta, &AccountSharedData)], accounts_and_meta_to_store: &[(StoredMeta, Option<&AccountSharedData>)],
) -> Vec<AccountInfo> { ) -> Vec<AccountInfo> {
assert_eq!(hashes.len(), accounts_and_meta_to_store.len()); assert_eq!(hashes.len(), accounts_and_meta_to_store.len());
let mut infos: Vec<AccountInfo> = Vec::with_capacity(accounts_and_meta_to_store.len()); let mut infos: Vec<AccountInfo> = Vec::with_capacity(accounts_and_meta_to_store.len());
@ -3331,7 +3331,10 @@ impl AccountsDb {
let mut total_storage_find_us = 0; let mut total_storage_find_us = 0;
while infos.len() < accounts_and_meta_to_store.len() { while infos.len() < accounts_and_meta_to_store.len() {
let mut storage_find = Measure::start("storage_finder"); let mut storage_find = Measure::start("storage_finder");
let data_len = accounts_and_meta_to_store[infos.len()].1.data().len(); let data_len = accounts_and_meta_to_store[infos.len()]
.1
.map(|account| account.data().len())
.unwrap_or_default();
let storage = storage_finder(slot, data_len + STORE_META_OVERHEAD); let storage = storage_finder(slot, data_len + STORE_META_OVERHEAD);
storage_find.stop(); storage_find.stop();
total_storage_find_us += storage_find.as_us(); total_storage_find_us += storage_find.as_us();
@ -3377,7 +3380,9 @@ impl AccountsDb {
store_id: storage.append_vec_id(), store_id: storage.append_vec_id(),
offset: offsets[0], offset: offsets[0],
stored_size, stored_size,
lamports: account.lamports(), lamports: account
.map(|account| account.lamports())
.unwrap_or_default(),
}); });
} }
// restore the state to available // restore the state to available
@ -3705,7 +3710,7 @@ impl AccountsDb {
&self, &self,
slot: Slot, slot: Slot,
hashes: Option<&[impl Borrow<Hash>]>, hashes: Option<&[impl Borrow<Hash>]>,
accounts_and_meta_to_store: &[(StoredMeta, &AccountSharedData)], accounts_and_meta_to_store: &[(StoredMeta, Option<&AccountSharedData>)],
) -> Vec<AccountInfo> { ) -> Vec<AccountInfo> {
let len = accounts_and_meta_to_store.len(); let len = accounts_and_meta_to_store.len();
let hashes = hashes.map(|hashes| { let hashes = hashes.map(|hashes| {
@ -3718,9 +3723,17 @@ impl AccountsDb {
.enumerate() .enumerate()
.map(|(i, (meta, account))| { .map(|(i, (meta, account))| {
let hash = hashes.map(|hashes| hashes[i].borrow()); let hash = hashes.map(|hashes| hashes[i].borrow());
let cached_account =
self.accounts_cache let account = account.cloned().unwrap_or_default();
.store(slot, &meta.pubkey, (*account).clone(), hash);
let account_info = AccountInfo {
store_id: CACHE_VIRTUAL_STORAGE_ID,
offset: CACHE_VIRTUAL_OFFSET,
stored_size: CACHE_VIRTUAL_STORED_SIZE,
lamports: account.lamports(),
};
let cached_account = self.accounts_cache.store(slot, &meta.pubkey, account, hash);
// 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) => {
@ -3728,13 +3741,7 @@ impl AccountsDb {
} }
None => (), None => (),
}; };
account_info
AccountInfo {
store_id: CACHE_VIRTUAL_STORAGE_ID,
offset: CACHE_VIRTUAL_OFFSET,
stored_size: CACHE_VIRTUAL_STORED_SIZE,
lamports: account.lamports(),
}
}) })
.collect() .collect()
} }
@ -3751,17 +3758,18 @@ impl AccountsDb {
mut write_version_producer: P, mut write_version_producer: P,
is_cached_store: bool, is_cached_store: bool,
) -> Vec<AccountInfo> { ) -> Vec<AccountInfo> {
let default_account = AccountSharedData::default(); let accounts_and_meta_to_store: Vec<(StoredMeta, Option<&AccountSharedData>)> = accounts
let accounts_and_meta_to_store: Vec<(StoredMeta, &AccountSharedData)> = accounts
.iter() .iter()
.map(|(pubkey, account)| { .map(|(pubkey, account)| {
self.read_only_accounts_cache.remove(pubkey, slot); self.read_only_accounts_cache.remove(pubkey, slot);
let account = if account.lamports() == 0 { // this is the source of Some(Account) or None.
&default_account // Some(Account) = store 'Account'
// None = store a default/empty account with 0 lamports
let (account, data_len) = if account.lamports() == 0 {
(None, 0)
} else { } else {
*account (Some(*account), account.data().len() as u64)
}; };
let data_len = account.data().len() as u64;
let meta = StoredMeta { let meta = StoredMeta {
write_version: write_version_producer.next().unwrap(), write_version: write_version_producer.next().unwrap(),
pubkey: **pubkey, pubkey: **pubkey,
@ -5822,7 +5830,7 @@ pub mod tests {
}; };
storages[0][0] storages[0][0]
.accounts .accounts
.append_accounts(&[(sm, &acc)], &[&Hash::default()]); .append_accounts(&[(sm, Some(&acc))], &[&Hash::default()]);
let calls = AtomicU64::new(0); let calls = AtomicU64::new(0);
let result = AccountsDb::scan_account_storage_no_bank( let result = AccountsDb::scan_account_storage_no_bank(

View File

@ -69,6 +69,15 @@ impl<'a, T: ReadableAccount> From<&'a T> for AccountMeta {
} }
} }
impl<'a, T: ReadableAccount> From<Option<&'a T>> for AccountMeta {
fn from(account: Option<&'a T>) -> Self {
match account {
Some(account) => AccountMeta::from(account),
None => AccountMeta::default(),
}
}
}
/// References to account data stored elsewhere. Getting an `Account` requires cloning /// References to account data stored elsewhere. Getting an `Account` requires cloning
/// (see `StoredAccountMeta::clone_account()`). /// (see `StoredAccountMeta::clone_account()`).
#[derive(PartialEq, Debug)] #[derive(PartialEq, Debug)]
@ -453,7 +462,7 @@ impl AppendVec {
/// and will be available to other threads. /// and will be available to other threads.
pub fn append_accounts( pub fn append_accounts(
&self, &self,
accounts: &[(StoredMeta, &AccountSharedData)], accounts: &[(StoredMeta, Option<&AccountSharedData>)],
hashes: &[impl Borrow<Hash>], hashes: &[impl Borrow<Hash>],
) -> Vec<usize> { ) -> Vec<usize> {
let _lock = self.append_lock.lock().unwrap(); let _lock = self.append_lock.lock().unwrap();
@ -464,7 +473,10 @@ impl AppendVec {
let account_meta = AccountMeta::from(*account); let account_meta = AccountMeta::from(*account);
let account_meta_ptr = &account_meta as *const AccountMeta; let account_meta_ptr = &account_meta as *const AccountMeta;
let data_len = stored_meta.data_len as usize; let data_len = stored_meta.data_len as usize;
let data_ptr = account.data().as_ptr(); let data_ptr = account
.map(|account| account.data())
.unwrap_or_default()
.as_ptr();
let hash_ptr = hash.borrow().as_ref().as_ptr(); let hash_ptr = hash.borrow().as_ref().as_ptr();
let ptrs = [ let ptrs = [
(meta_ptr as *const u8, mem::size_of::<StoredMeta>()), (meta_ptr as *const u8, mem::size_of::<StoredMeta>()),
@ -495,7 +507,7 @@ impl AppendVec {
account: &AccountSharedData, account: &AccountSharedData,
hash: Hash, hash: Hash,
) -> Option<usize> { ) -> Option<usize> {
let res = self.append_accounts(&[(storage_meta, account)], &[&hash]); let res = self.append_accounts(&[(storage_meta, Some(account))], &[&hash]);
if res.len() == 1 { if res.len() == 1 {
None None
} else { } else {
@ -592,6 +604,43 @@ pub mod tests {
} }
} }
#[test]
fn test_account_meta_default() {
let def1 = AccountMeta::default();
let def2 = AccountMeta::from(&Account::default());
assert_eq!(&def1, &def2);
let def2 = AccountMeta::from(&AccountSharedData::default());
assert_eq!(&def1, &def2);
let def2 = AccountMeta::from(Some(&AccountSharedData::default()));
assert_eq!(&def1, &def2);
let none: Option<&AccountSharedData> = None;
let def2 = AccountMeta::from(none);
assert_eq!(&def1, &def2);
}
#[test]
fn test_account_meta_non_default() {
let def1 = AccountMeta {
lamports: 1,
owner: Pubkey::new_unique(),
executable: true,
rent_epoch: 3,
};
let def2_account = Account {
lamports: def1.lamports,
owner: def1.owner,
executable: def1.executable,
rent_epoch: def1.rent_epoch,
data: Vec::new(),
};
let def2 = AccountMeta::from(&def2_account);
assert_eq!(&def1, &def2);
let def2 = AccountMeta::from(&AccountSharedData::from(def2_account.clone()));
assert_eq!(&def1, &def2);
let def2 = AccountMeta::from(Some(&AccountSharedData::from(def2_account)));
assert_eq!(&def1, &def2);
}
#[test] #[test]
#[should_panic(expected = "too small file size 0 for AppendVec")] #[should_panic(expected = "too small file size 0 for AppendVec")]
fn test_append_vec_new_bad_size() { fn test_append_vec_new_bad_size() {