remove `purge` parameter to accounts (#2990)

This commit is contained in:
Rob Walker 2019-02-27 16:06:06 -08:00 committed by GitHub
parent 873007bae1
commit 163874d4da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 35 additions and 52 deletions

View File

@ -429,11 +429,9 @@ impl AccountsDB {
} }
} }
/// Store the account update. If the update is to delete the account because /// Store the account update.
/// the token balance is 0, purge needs to be set to true for the delete fn store_account(&self, fork: Fork, pubkey: &Pubkey, account: &Account) {
/// to occur in place. if account.tokens == 0 && self.is_squashed(fork) {
fn store_account(&self, fork: Fork, purge: bool, pubkey: &Pubkey, account: &Account) {
if account.tokens == 0 && purge {
// purge if balance is 0 and no checkpoints // purge if balance is 0 and no checkpoints
let index = self.index_info.index.read().unwrap(); let index = self.index_info.index.read().unwrap();
let map = index.get(&pubkey).unwrap(); let map = index.get(&pubkey).unwrap();
@ -459,20 +457,19 @@ impl AccountsDB {
} }
} }
pub fn store(&self, fork: Fork, purge: bool, pubkey: &Pubkey, account: &Account) { pub fn store(&self, fork: Fork, pubkey: &Pubkey, account: &Account) {
{ {
if !self.index_info.index.read().unwrap().contains_key(&pubkey) { if !self.index_info.index.read().unwrap().contains_key(&pubkey) {
let mut windex = self.index_info.index.write().unwrap(); let mut windex = self.index_info.index.write().unwrap();
windex.insert(*pubkey, AccountMap(RwLock::new(HashMap::new()))); windex.insert(*pubkey, AccountMap(RwLock::new(HashMap::new())));
} }
} }
self.store_account(fork, purge, pubkey, account); self.store_account(fork, pubkey, account);
} }
pub fn store_accounts( pub fn store_accounts(
&self, &self,
fork: Fork, fork: Fork,
purge: bool,
txs: &[Transaction], txs: &[Transaction],
res: &[Result<()>], res: &[Result<()>],
loaded: &[Result<(InstructionAccounts, InstructionLoaders)>], loaded: &[Result<(InstructionAccounts, InstructionLoaders)>],
@ -506,7 +503,7 @@ impl AccountsDB {
let tx = &txs[i]; let tx = &txs[i];
let acc = raccs.as_ref().unwrap(); let acc = raccs.as_ref().unwrap();
for (key, account) in tx.account_keys.iter().zip(acc.0.iter()) { for (key, account) in tx.account_keys.iter().zip(acc.0.iter()) {
self.store(fork, purge, key, account); self.store(fork, key, account);
} }
} }
} }
@ -649,6 +646,16 @@ impl AccountsDB {
parents parents
} }
fn is_squashed(&self, fork: Fork) -> bool {
self.fork_info
.read()
.unwrap()
.get(&fork)
.unwrap()
.parents
.is_empty()
}
fn get_merged_index( fn get_merged_index(
&self, &self,
fork: Fork, fork: Fork,
@ -668,7 +675,7 @@ impl AccountsDB {
None None
} }
/// become the root accountsDB /// make fork a root, i.e. forget its heritage
fn squash(&self, fork: Fork) { fn squash(&self, fork: Fork) {
let parents = self.remove_parents(fork); let parents = self.remove_parents(fork);
let tx_count = parents let tx_count = parents
@ -769,10 +776,8 @@ impl Accounts {
} }
/// Slow because lock is held for 1 operation insted of many /// Slow because lock is held for 1 operation insted of many
/// * purge - if the account token value is 0 and purge is true then delete the account. pub fn store_slow(&self, fork: Fork, pubkey: &Pubkey, account: &Account) {
/// purge should be set to false for overlays, and true for the root checkpoint. self.accounts_db.store(fork, pubkey, account);
pub fn store_slow(&self, fork: Fork, purge: bool, pubkey: &Pubkey, account: &Account) {
self.accounts_db.store(fork, purge, pubkey, account);
} }
fn lock_account( fn lock_account(
@ -871,18 +876,14 @@ impl Accounts {
} }
/// Store the accounts into the DB /// Store the accounts into the DB
/// * purge - if the account token value is 0 and purge is true then delete the account.
/// purge should be set to false for overlays, and true for the root checkpoint.
pub fn store_accounts( pub fn store_accounts(
&self, &self,
fork: Fork, fork: Fork,
purge: bool,
txs: &[Transaction], txs: &[Transaction],
res: &[Result<()>], res: &[Result<()>],
loaded: &[Result<(InstructionAccounts, InstructionLoaders)>], loaded: &[Result<(InstructionAccounts, InstructionLoaders)>],
) { ) {
self.accounts_db self.accounts_db.store_accounts(fork, txs, res, loaded)
.store_accounts(fork, purge, txs, res, loaded)
} }
pub fn increment_transaction_count(&self, fork: Fork, tx_count: usize) { pub fn increment_transaction_count(&self, fork: Fork, tx_count: usize) {
@ -914,21 +915,6 @@ mod tests {
use solana_sdk::transaction::Instruction; use solana_sdk::transaction::Instruction;
use solana_sdk::transaction::Transaction; use solana_sdk::transaction::Transaction;
#[test]
fn test_purge() {
let paths = "purge".to_string();
let db = AccountsDB::new(0, &paths);
let key = Pubkey::default();
let account = Account::new(0, 0, Pubkey::default());
// accounts are deleted when their token value is 0 and purge is true
db.store(0, false, &key, &account);
assert_eq!(db.load(0, &key, true), Some(account.clone()));
// purge should be set to true for the root checkpoint
db.store(0, true, &key, &account);
assert_eq!(db.load(0, &key, true), None);
cleanup_dirs(&paths);
}
fn load_accounts( fn load_accounts(
tx: Transaction, tx: Transaction,
ka: &Vec<(Pubkey, Account)>, ka: &Vec<(Pubkey, Account)>,
@ -936,7 +922,7 @@ mod tests {
) -> Vec<Result<(InstructionAccounts, InstructionLoaders)>> { ) -> Vec<Result<(InstructionAccounts, InstructionLoaders)>> {
let accounts = Accounts::new(0, None); let accounts = Accounts::new(0, None);
for ka in ka.iter() { for ka in ka.iter() {
accounts.store_slow(0, true, &ka.0, &ka.1); accounts.store_slow(0, &ka.0, &ka.1);
} }
let res = accounts.load_accounts(0, &[tx], vec![Ok(())], error_counters); let res = accounts.load_accounts(0, &[tx], vec![Ok(())], error_counters);
@ -1321,7 +1307,7 @@ mod tests {
let account0 = Account::new(1, 0, key); let account0 = Account::new(1, 0, key);
// store value 1 in the "root", i.e. db zero // store value 1 in the "root", i.e. db zero
db.store(0, true, &key, &account0); db.store(0, &key, &account0);
let mut pubkeys: Vec<Pubkey> = vec![]; let mut pubkeys: Vec<Pubkey> = vec![];
create_account(&db, &mut pubkeys, 100, 0); create_account(&db, &mut pubkeys, 100, 0);
@ -1333,9 +1319,9 @@ mod tests {
assert_eq!(compare_account(&default_account, &account), true); assert_eq!(compare_account(&default_account, &account), true);
} }
db.add_fork(1, Some(0)); db.add_fork(1, Some(0));
// store value 0 in the child, but don't purge (see purge test above) // store value 0 in the child
let account1 = Account::new(0, 0, key); let account1 = Account::new(0, 0, key);
db.store(1, false, &key, &account1); db.store(1, &key, &account1);
// masking accounts is done at the Accounts level, at accountsDB we see // masking accounts is done at the Accounts level, at accountsDB we see
// original account // original account
@ -1365,12 +1351,12 @@ mod tests {
let paths = "unsquash".to_string(); let paths = "unsquash".to_string();
let db0 = AccountsDB::new(0, &paths); let db0 = AccountsDB::new(0, &paths);
let account0 = Account::new(1, 0, key); let account0 = Account::new(1, 0, key);
db0.store(0, true, &key, &account0); db0.store(0, &key, &account0);
db0.add_fork(1, Some(0)); db0.add_fork(1, Some(0));
// 0 tokens in the child // 0 tokens in the child
let account1 = Account::new(0, 0, key); let account1 = Account::new(0, 0, key);
db0.store(1, false, &key, &account1); db0.store(1, &key, &account1);
// masking accounts is done at the Accounts level, at accountsDB we see // masking accounts is done at the Accounts level, at accountsDB we see
// original account // original account
@ -1400,7 +1386,7 @@ mod tests {
nvote -= 1; nvote -= 1;
} }
assert!(accounts.load(0, &pubkey, true).is_none()); assert!(accounts.load(0, &pubkey, true).is_none());
accounts.store(0, true, &pubkey, &default_account); accounts.store(0, &pubkey, &default_account);
} }
} }
@ -1409,7 +1395,7 @@ mod tests {
let idx = thread_rng().gen_range(0, range); let idx = thread_rng().gen_range(0, range);
if let Some(mut account) = accounts.load(0, &pubkeys[idx], true) { if let Some(mut account) = accounts.load(0, &pubkeys[idx], true) {
account.tokens = account.tokens + 1; account.tokens = account.tokens + 1;
accounts.store(0, true, &pubkeys[idx], &account); accounts.store(0, &pubkeys[idx], &account);
if account.tokens == 0 { if account.tokens == 0 {
assert!(accounts.load(0, &pubkeys[idx], true).is_none()); assert!(accounts.load(0, &pubkeys[idx], true).is_none());
} else { } else {
@ -1491,7 +1477,7 @@ mod tests {
]; ];
let pubkey1 = Keypair::new().pubkey(); let pubkey1 = Keypair::new().pubkey();
let account1 = Account::new(1, ACCOUNT_DATA_FILE_SIZE as usize / 2, pubkey1); let account1 = Account::new(1, ACCOUNT_DATA_FILE_SIZE as usize / 2, pubkey1);
accounts.store(0, true, &pubkey1, &account1); accounts.store(0, &pubkey1, &account1);
{ {
let stores = accounts.storage.read().unwrap(); let stores = accounts.storage.read().unwrap();
assert_eq!(stores.len(), 1); assert_eq!(stores.len(), 1);
@ -1501,7 +1487,7 @@ mod tests {
let pubkey2 = Keypair::new().pubkey(); let pubkey2 = Keypair::new().pubkey();
let account2 = Account::new(1, ACCOUNT_DATA_FILE_SIZE as usize / 2, pubkey2); let account2 = Account::new(1, ACCOUNT_DATA_FILE_SIZE as usize / 2, pubkey2);
accounts.store(0, true, &pubkey2, &account2); accounts.store(0, &pubkey2, &account2);
{ {
let stores = accounts.storage.read().unwrap(); let stores = accounts.storage.read().unwrap();
assert_eq!(stores.len(), 2); assert_eq!(stores.len(), 2);
@ -1515,7 +1501,7 @@ mod tests {
for i in 0..25 { for i in 0..25 {
let index = i % 2; let index = i % 2;
accounts.store(0, true, &pubkey1, &account1); accounts.store(0, &pubkey1, &account1);
{ {
let stores = accounts.storage.read().unwrap(); let stores = accounts.storage.read().unwrap();
assert_eq!(stores.len(), 3); assert_eq!(stores.len(), 3);

View File

@ -243,7 +243,6 @@ impl Bank {
self.accounts().store_slow( self.accounts().store_slow(
self.id, self.id,
self.is_root(),
&genesis_block.bootstrap_leader_vote_account_id, &genesis_block.bootstrap_leader_vote_account_id,
&bootstrap_leader_vote_account, &bootstrap_leader_vote_account,
); );
@ -260,8 +259,7 @@ impl Bank {
pub fn add_native_program(&self, name: &str, program_id: &Pubkey) { pub fn add_native_program(&self, name: &str, program_id: &Pubkey) {
let account = native_loader::create_program_account(name); let account = native_loader::create_program_account(name);
self.accounts() self.accounts().store_slow(self.id, program_id, &account);
.store_slow(self.id, self.is_root(), program_id, &account);
} }
fn add_builtin_programs(&self) { fn add_builtin_programs(&self) {
@ -548,7 +546,7 @@ impl Bank {
// assert!(!self.is_frozen()); // assert!(!self.is_frozen());
let now = Instant::now(); let now = Instant::now();
self.accounts() self.accounts()
.store_accounts(self.id, self.is_root(), txs, executed, loaded_accounts); .store_accounts(self.id, txs, executed, loaded_accounts);
// once committed there is no way to unroll // once committed there is no way to unroll
let write_elapsed = now.elapsed(); let write_elapsed = now.elapsed();
@ -633,7 +631,7 @@ impl Bank {
} }
account.tokens -= tokens; account.tokens -= tokens;
self.accounts().store_slow(self.id, true, pubkey, &account); self.accounts().store_slow(self.id, pubkey, &account);
Ok(()) Ok(())
} }
None => Err(BankError::AccountNotFound), None => Err(BankError::AccountNotFound),
@ -643,8 +641,7 @@ impl Bank {
pub fn deposit(&self, pubkey: &Pubkey, tokens: u64) { pub fn deposit(&self, pubkey: &Pubkey, tokens: u64) {
let mut account = self.get_account(pubkey).unwrap_or_default(); let mut account = self.get_account(pubkey).unwrap_or_default();
account.tokens += tokens; account.tokens += tokens;
self.accounts() self.accounts().store_slow(self.id, pubkey, &account);
.store_slow(self.id, self.is_root(), pubkey, &account);
} }
fn accounts(&self) -> Arc<Accounts> { fn accounts(&self) -> Arc<Accounts> {