Accountsdb plugin write ordering (#20948)

Use the write_version in the Accounts's meta data so that account write with lower write_version would not overwrite the higher ones.
This commit is contained in:
Lijun Wang
2021-10-25 14:07:56 -07:00
committed by GitHub
parent cf0fd5b2ca
commit bbe3ce3db5
7 changed files with 105 additions and 144 deletions

View File

@ -1601,6 +1601,18 @@ impl AccountsDb {
)
}
pub fn new_for_tests_with_caching(paths: Vec<PathBuf>, cluster_type: &ClusterType) -> Self {
AccountsDb::new_with_config(
paths,
cluster_type,
AccountSecondaryIndexes::default(),
true,
AccountShrinkThreshold::default(),
Some(ACCOUNTS_DB_CONFIG_FOR_TESTING),
None,
)
}
pub fn new_with_config(
paths: Vec<PathBuf>,
cluster_type: &ClusterType,
@ -1680,6 +1692,13 @@ impl AccountsDb {
}
}
pub fn new_single_for_tests_with_caching() -> Self {
AccountsDb {
min_num_stores: 0,
..AccountsDb::new_for_tests_with_caching(Vec::new(), &ClusterType::Development)
}
}
fn new_storage_entry(&self, slot: Slot, path: &Path, size: u64) -> AccountStorageEntry {
AccountStorageEntry::new(
path,
@ -4833,6 +4852,8 @@ impl AccountsDb {
lamports: account.lamports(),
};
self.notify_account_at_accounts_update(slot, meta, &account);
let cached_account = self.accounts_cache.store(slot, &meta.pubkey, account, hash);
// hash this account in the bg
match &self.sender_bg_hasher {
@ -6227,8 +6248,6 @@ impl AccountsDb {
pub fn store_cached(&self, slot: Slot, accounts: &[(&Pubkey, &AccountSharedData)]) {
self.store(slot, accounts, self.caching_enabled);
self.notify_account_at_accounts_update(slot, accounts);
}
/// Store the account update.

View File

@ -1,5 +1,8 @@
use {
crate::{accounts_db::AccountsDb, append_vec::StoredAccountMeta},
crate::{
accounts_db::AccountsDb,
append_vec::{StoredAccountMeta, StoredMeta},
},
solana_measure::measure::Measure,
solana_metrics::*,
solana_sdk::{account::AccountSharedData, clock::Slot, pubkey::Pubkey},
@ -59,16 +62,12 @@ impl AccountsDb {
pub fn notify_account_at_accounts_update(
&self,
slot: Slot,
accounts: &[(&Pubkey, &AccountSharedData)],
meta: &StoredMeta,
account: &AccountSharedData,
) {
if let Some(accounts_update_notifier) = &self.accounts_update_notifier {
let notifier = &accounts_update_notifier.read().unwrap();
for account in accounts {
let pubkey = account.0;
let account = account.1;
notifier.notify_account_update(slot, pubkey, account);
}
notifier.notify_account_update(slot, meta, account);
}
}
@ -154,7 +153,7 @@ pub mod tests {
accounts_update_notifier_interface::{
AccountsUpdateNotifier, AccountsUpdateNotifierInterface,
},
append_vec::StoredAccountMeta,
append_vec::{StoredAccountMeta, StoredMeta},
},
dashmap::DashMap,
solana_sdk::{
@ -176,15 +175,20 @@ pub mod tests {
#[derive(Debug, Default)]
struct AccountsDbTestPlugin {
pub accounts_at_snapshot_restore: DashMap<Pubkey, Vec<(Slot, AccountSharedData)>>,
pub accounts_notified: DashMap<Pubkey, Vec<(Slot, AccountSharedData)>>,
pub is_startup_done: AtomicBool,
}
impl AccountsUpdateNotifierInterface for AccountsDbTestPlugin {
/// Notified when an account is updated at runtime, due to transaction activities
fn notify_account_update(&self, slot: Slot, pubkey: &Pubkey, account: &AccountSharedData) {
self.accounts_at_snapshot_restore
.entry(*pubkey)
fn notify_account_update(
&self,
slot: Slot,
meta: &StoredMeta,
account: &AccountSharedData,
) {
self.accounts_notified
.entry(meta.pubkey)
.or_insert(Vec::default())
.push((slot, account.clone()));
}
@ -192,7 +196,7 @@ pub mod tests {
/// Notified when the AccountsDb is initialized at start when restored
/// from a snapshot.
fn notify_account_restore_from_snapshot(&self, slot: Slot, account: &StoredAccountMeta) {
self.accounts_at_snapshot_restore
self.accounts_notified
.entry(account.meta.pubkey)
.or_insert(Vec::default())
.push((slot, account.clone_account()));
@ -241,42 +245,22 @@ pub mod tests {
accounts.notify_account_restore_from_snapshot();
let notifier = notifier.write().unwrap();
assert_eq!(notifier.accounts_notified.get(&key1).unwrap().len(), 1);
assert_eq!(
notifier
.accounts_at_snapshot_restore
.get(&key1)
.unwrap()
.len(),
1
);
assert_eq!(
notifier.accounts_at_snapshot_restore.get(&key1).unwrap()[0]
notifier.accounts_notified.get(&key1).unwrap()[0]
.1
.lamports(),
account1_lamports
);
assert_eq!(notifier.accounts_notified.get(&key1).unwrap()[0].0, slot0);
assert_eq!(notifier.accounts_notified.get(&key2).unwrap().len(), 1);
assert_eq!(
notifier.accounts_at_snapshot_restore.get(&key1).unwrap()[0].0,
slot0
);
assert_eq!(
notifier
.accounts_at_snapshot_restore
.get(&key2)
.unwrap()
.len(),
1
);
assert_eq!(
notifier.accounts_at_snapshot_restore.get(&key2).unwrap()[0]
notifier.accounts_notified.get(&key2).unwrap()[0]
.1
.lamports(),
account2_lamports
);
assert_eq!(
notifier.accounts_at_snapshot_restore.get(&key2).unwrap()[0].0,
slot0
);
assert_eq!(notifier.accounts_notified.get(&key2).unwrap()[0].0, slot0);
assert!(notifier.is_startup_done.load(Ordering::Relaxed));
}
@ -318,66 +302,37 @@ pub mod tests {
accounts.notify_account_restore_from_snapshot();
let notifier = notifier.write().unwrap();
assert_eq!(notifier.accounts_notified.get(&key1).unwrap().len(), 1);
assert_eq!(
notifier
.accounts_at_snapshot_restore
.get(&key1)
.unwrap()
.len(),
1
);
assert_eq!(
notifier.accounts_at_snapshot_restore.get(&key1).unwrap()[0]
notifier.accounts_notified.get(&key1).unwrap()[0]
.1
.lamports(),
account1_lamports
);
assert_eq!(notifier.accounts_notified.get(&key1).unwrap()[0].0, slot1);
assert_eq!(notifier.accounts_notified.get(&key2).unwrap().len(), 1);
assert_eq!(
notifier.accounts_at_snapshot_restore.get(&key1).unwrap()[0].0,
slot1
);
assert_eq!(
notifier
.accounts_at_snapshot_restore
.get(&key2)
.unwrap()
.len(),
1
);
assert_eq!(
notifier.accounts_at_snapshot_restore.get(&key2).unwrap()[0]
notifier.accounts_notified.get(&key2).unwrap()[0]
.1
.lamports(),
account2_lamports
);
assert_eq!(notifier.accounts_notified.get(&key2).unwrap()[0].0, slot0);
assert_eq!(notifier.accounts_notified.get(&key3).unwrap().len(), 1);
assert_eq!(
notifier.accounts_at_snapshot_restore.get(&key2).unwrap()[0].0,
slot0
);
assert_eq!(
notifier
.accounts_at_snapshot_restore
.get(&key3)
.unwrap()
.len(),
1
);
assert_eq!(
notifier.accounts_at_snapshot_restore.get(&key3).unwrap()[0]
notifier.accounts_notified.get(&key3).unwrap()[0]
.1
.lamports(),
account3_lamports
);
assert_eq!(
notifier.accounts_at_snapshot_restore.get(&key3).unwrap()[0].0,
slot1
);
assert_eq!(notifier.accounts_notified.get(&key3).unwrap()[0].0, slot1);
assert!(notifier.is_startup_done.load(Ordering::Relaxed));
}
#[test]
fn test_notify_account_at_accounts_update() {
let mut accounts = AccountsDb::new_single_for_tests();
let mut accounts = AccountsDb::new_single_for_tests_with_caching();
let notifier = AccountsDbTestPlugin::default();
let notifier = Arc::new(RwLock::new(notifier));
@ -411,70 +366,37 @@ pub mod tests {
accounts.store_cached(slot1, &[(&key3, &account3)]);
let notifier = notifier.write().unwrap();
assert_eq!(notifier.accounts_notified.get(&key1).unwrap().len(), 2);
assert_eq!(
notifier
.accounts_at_snapshot_restore
.get(&key1)
.unwrap()
.len(),
2
);
assert_eq!(
notifier.accounts_at_snapshot_restore.get(&key1).unwrap()[0]
notifier.accounts_notified.get(&key1).unwrap()[0]
.1
.lamports(),
account1_lamports1
);
assert_eq!(notifier.accounts_notified.get(&key1).unwrap()[0].0, slot0);
assert_eq!(
notifier.accounts_at_snapshot_restore.get(&key1).unwrap()[0].0,
slot0
);
assert_eq!(
notifier.accounts_at_snapshot_restore.get(&key1).unwrap()[1]
notifier.accounts_notified.get(&key1).unwrap()[1]
.1
.lamports(),
account1_lamports2
);
assert_eq!(
notifier.accounts_at_snapshot_restore.get(&key1).unwrap()[1].0,
slot1
);
assert_eq!(notifier.accounts_notified.get(&key1).unwrap()[1].0, slot1);
assert_eq!(notifier.accounts_notified.get(&key2).unwrap().len(), 1);
assert_eq!(
notifier
.accounts_at_snapshot_restore
.get(&key2)
.unwrap()
.len(),
1
);
assert_eq!(
notifier.accounts_at_snapshot_restore.get(&key2).unwrap()[0]
notifier.accounts_notified.get(&key2).unwrap()[0]
.1
.lamports(),
account2_lamports
);
assert_eq!(notifier.accounts_notified.get(&key2).unwrap()[0].0, slot0);
assert_eq!(notifier.accounts_notified.get(&key3).unwrap().len(), 1);
assert_eq!(
notifier.accounts_at_snapshot_restore.get(&key2).unwrap()[0].0,
slot0
);
assert_eq!(
notifier
.accounts_at_snapshot_restore
.get(&key3)
.unwrap()
.len(),
1
);
assert_eq!(
notifier.accounts_at_snapshot_restore.get(&key3).unwrap()[0]
notifier.accounts_notified.get(&key3).unwrap()[0]
.1
.lamports(),
account3_lamports
);
assert_eq!(
notifier.accounts_at_snapshot_restore.get(&key3).unwrap()[0].0,
slot1
);
assert_eq!(notifier.accounts_notified.get(&key3).unwrap()[0].0, slot1);
}
}

View File

@ -1,12 +1,12 @@
use {
crate::append_vec::StoredAccountMeta,
solana_sdk::{account::AccountSharedData, clock::Slot, pubkey::Pubkey},
crate::append_vec::{StoredAccountMeta, StoredMeta},
solana_sdk::{account::AccountSharedData, clock::Slot},
std::sync::{Arc, RwLock},
};
pub trait AccountsUpdateNotifierInterface: std::fmt::Debug {
/// Notified when an account is updated at runtime, due to transaction activities
fn notify_account_update(&self, slot: Slot, pubkey: &Pubkey, account: &AccountSharedData);
fn notify_account_update(&self, slot: Slot, meta: &StoredMeta, account: &AccountSharedData);
/// Notified when the AccountsDb is initialized at start when restored
/// from a snapshot.