Skip to content

Commit

Permalink
Calculate account refs fix
Browse files Browse the repository at this point in the history
  • Loading branch information
sakridge committed Apr 11, 2020
1 parent 1f7ac22 commit b1992d0
Showing 1 changed file with 134 additions and 23 deletions.
157 changes: 134 additions & 23 deletions runtime/src/accounts_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,74 @@ impl AccountsDB {
drop(accounts_index);
}

fn inc_store_counts(
no_delete_id: AppendVecId,
purges: &HashMap<Pubkey, Vec<(Slot, AccountInfo)>>,
store_counts: &mut HashMap<AppendVecId, usize>,
already_counted: &mut HashSet<AppendVecId>,
) {
if already_counted.contains(&no_delete_id) {
return;
}
*store_counts.get_mut(&no_delete_id).unwrap() += 1;
already_counted.insert(no_delete_id);
let mut affected_pubkeys = HashSet::new();
for (key, account_infos) in purges {
for (_slot, account_info) in account_infos {
if account_info.store_id == no_delete_id {
affected_pubkeys.insert(key);
break;
}
}
}
for key in affected_pubkeys {
for (_slot, account_info) in purges.get(&key).unwrap() {
Self::inc_store_counts(
account_info.store_id,
purges,
store_counts,
already_counted,
);
}
}
}

fn calc_delete_dependencies(
accounts_index: &AccountsIndex<AccountInfo>,
purges: &HashMap<Pubkey, Vec<(Slot, AccountInfo)>>,
store_counts: &mut HashMap<AppendVecId, usize>,
) {
// Another pass to check if there are some filtered accounts which
// do not match the criteria of deleting all appendvecs which contain them
// then increment their storage count.
let mut already_counted = HashSet::new();
for (pubkey, account_infos) in purges.iter() {
let no_delete =
if account_infos.len() as u64 != accounts_index.ref_count_from_storage(&pubkey) {
true
} else {
let mut no_delete = false;
for (_slot, account_info) in account_infos {
if *store_counts.get(&account_info.store_id).unwrap() != 0 {
no_delete = true;
break;
}
}
no_delete
};
if no_delete {
for (_slot_id, account_info) in account_infos {
Self::inc_store_counts(
account_info.store_id,
&purges,
store_counts,
&mut already_counted,
);
}
}
}
}

// Purge zero lamport accounts and older rooted account states as garbage
// collection
// Only remove those accounts where the entire rooted history of the account
Expand Down Expand Up @@ -727,29 +795,7 @@ impl AccountsDB {
}
}

// Another pass to check if there are some filtered accounts which
// do not match the criteria of deleting all appendvecs which contain them
// then increment their storage count.
for (pubkey, account_infos) in &purges {
let no_delete =
if account_infos.len() as u64 != accounts_index.ref_count_from_storage(&pubkey) {
true
} else {
let mut no_delete = false;
for (_slot, account_info) in account_infos {
if *store_counts.get(&account_info.store_id).unwrap() != 0 {
no_delete = true;
break;
}
}
no_delete
};
if no_delete {
for (_slot_id, account_info) in account_infos {
*store_counts.get_mut(&account_info.store_id).unwrap() += 1;
}
}
}
Self::calc_delete_dependencies(&accounts_index, &purges, &mut store_counts);

// Only keep purges where the entire history of the account in the root set
// can be purged. All AppendVecs for those updates are dead.
Expand Down Expand Up @@ -3388,4 +3434,69 @@ pub mod tests {
dead_slots.insert(10);
accounts.clean_dead_slots(&mut dead_slots);
}

#[test]
fn test_delete_dependencies() {
solana_logger::setup();
let mut accounts_index = AccountsIndex::default();
let key0 = Pubkey::new_from_array([0u8; 32]);
let key1 = Pubkey::new_from_array([1u8; 32]);
let key2 = Pubkey::new_from_array([2u8; 32]);
let info0 = AccountInfo {
store_id: 0,
offset: 0,
lamports: 0,
};
let info1 = AccountInfo {
store_id: 1,
offset: 0,
lamports: 0,
};
let info2 = AccountInfo {
store_id: 2,
offset: 0,
lamports: 0,
};
let info3 = AccountInfo {
store_id: 3,
offset: 0,
lamports: 0,
};
let mut reclaims = vec![];
accounts_index.insert(0, &key0, info0.clone(), &mut reclaims);
accounts_index.insert(1, &key0, info1.clone(), &mut reclaims);
accounts_index.insert(1, &key1, info1.clone(), &mut reclaims);
accounts_index.insert(2, &key1, info2.clone(), &mut reclaims);
accounts_index.insert(2, &key2, info2.clone(), &mut reclaims);
accounts_index.insert(3, &key2, info3.clone(), &mut reclaims);
accounts_index.add_root(0);
accounts_index.add_root(1);
accounts_index.add_root(2);
accounts_index.add_root(3);
let mut purges = HashMap::new();
purges.insert(key0, accounts_index.would_purge(&key0));
purges.insert(key1, accounts_index.would_purge(&key1));
purges.insert(key2, accounts_index.would_purge(&key2));
for (key, list) in &purges {
info!(" purge {} =>", key);
for x in list {
info!(" {:?}", x);
}
}

let mut store_counts = HashMap::new();
store_counts.insert(0, 0);
store_counts.insert(1, 0);
store_counts.insert(2, 0);
store_counts.insert(3, 1);
AccountsDB::calc_delete_dependencies(&accounts_index, &purges, &mut store_counts);
let mut stores: Vec<_> = store_counts.keys().cloned().collect();
stores.sort();
for store in &stores {
info!("store: {:?} : {}", store, store_counts.get(&store).unwrap());
}
for x in 0..3 {
assert!(store_counts[&x] >= 1);
}
}
}

0 comments on commit b1992d0

Please sign in to comment.