Create bank snapshots (#4244)
* Revert "Revert "Create bank snapshots (#3671)" (#4243)"
This reverts commit 81fa69d347
.
* keep saved and unsaved copies of status cache
* fix format check
* bench for status cache serialize
* misc cleanup
* remove appendvec storage on purge
* fix accounts restore
* cleanup
* Pass snapshot path as args
* Fix clippy
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
use crate::accounts_db::{
|
||||
get_paths_vec, AccountInfo, AccountStorage, AccountsDB, ErrorCounters, InstructionAccounts,
|
||||
InstructionLoaders,
|
||||
get_paths_vec, AccountInfo, AccountStorage, AccountsDB, AppendVecId, ErrorCounters,
|
||||
InstructionAccounts, InstructionLoaders,
|
||||
};
|
||||
use crate::accounts_index::{AccountsIndex, Fork};
|
||||
use crate::append_vec::StoredAccount;
|
||||
use crate::message_processor::has_duplicates;
|
||||
use bincode::serialize;
|
||||
use hashbrown::{HashMap, HashSet};
|
||||
use log::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use solana_metrics::inc_new_counter_error;
|
||||
use solana_sdk::account::Account;
|
||||
use solana_sdk::fee_calculator::FeeCalculator;
|
||||
@@ -19,6 +19,7 @@ use solana_sdk::system_program;
|
||||
use solana_sdk::transaction::Result;
|
||||
use solana_sdk::transaction::{Transaction, TransactionError};
|
||||
use std::borrow::Borrow;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::env;
|
||||
use std::fs::remove_dir_all;
|
||||
use std::iter::once;
|
||||
@@ -51,15 +52,18 @@ type RecordLocks = (
|
||||
);
|
||||
|
||||
/// This structure handles synchronization for db
|
||||
#[derive(Default)]
|
||||
#[derive(Default, Debug, Serialize, Deserialize)]
|
||||
pub struct Accounts {
|
||||
/// Single global AccountsDB
|
||||
#[serde(skip)]
|
||||
pub accounts_db: Arc<AccountsDB>,
|
||||
|
||||
/// set of accounts which are currently in the pipeline
|
||||
#[serde(skip)]
|
||||
account_locks: AccountLocks,
|
||||
|
||||
/// set of accounts which are about to record + commit
|
||||
#[serde(skip)]
|
||||
record_locks: Mutex<RecordLocks>,
|
||||
|
||||
/// List of persistent stores
|
||||
@@ -72,16 +76,16 @@ pub struct Accounts {
|
||||
|
||||
impl Drop for Accounts {
|
||||
fn drop(&mut self) {
|
||||
let paths = get_paths_vec(&self.paths);
|
||||
paths.iter().for_each(|p| {
|
||||
let _ignored = remove_dir_all(p);
|
||||
if self.own_paths {
|
||||
let paths = get_paths_vec(&self.paths);
|
||||
paths.iter().for_each(|p| {
|
||||
let _ignored = remove_dir_all(p);
|
||||
|
||||
// it is safe to delete the parent
|
||||
if self.own_paths {
|
||||
// it is safe to delete the parent
|
||||
let path = Path::new(p);
|
||||
let _ignored = remove_dir_all(path.parent().unwrap());
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -330,7 +334,9 @@ impl Accounts {
|
||||
pub fn load_by_program(&self, fork: Fork, program_id: &Pubkey) -> Vec<(Pubkey, Account)> {
|
||||
let accumulator: Vec<Vec<(Pubkey, u64, Account)>> = self.accounts_db.scan_account_storage(
|
||||
fork,
|
||||
|stored_account: &StoredAccount, accum: &mut Vec<(Pubkey, u64, Account)>| {
|
||||
|stored_account: &StoredAccount,
|
||||
_id: AppendVecId,
|
||||
accum: &mut Vec<(Pubkey, u64, Account)>| {
|
||||
if stored_account.balance.owner == *program_id {
|
||||
let val = (
|
||||
stored_account.meta.pubkey,
|
||||
@@ -441,7 +447,9 @@ impl Accounts {
|
||||
pub fn hash_internal_state(&self, fork_id: Fork) -> Option<Hash> {
|
||||
let accumulator: Vec<Vec<(Pubkey, u64, Hash)>> = self.accounts_db.scan_account_storage(
|
||||
fork_id,
|
||||
|stored_account: &StoredAccount, accum: &mut Vec<(Pubkey, u64, Hash)>| {
|
||||
|stored_account: &StoredAccount,
|
||||
_id: AppendVecId,
|
||||
accum: &mut Vec<(Pubkey, u64, Hash)>| {
|
||||
accum.push((
|
||||
stored_account.meta.pubkey,
|
||||
stored_account.meta.write_version,
|
||||
@@ -586,11 +594,14 @@ mod tests {
|
||||
// TODO: all the bank tests are bank specific, issue: 2194
|
||||
|
||||
use super::*;
|
||||
use bincode::{deserialize_from, serialize_into, serialized_size};
|
||||
use rand::{thread_rng, Rng};
|
||||
use solana_sdk::account::Account;
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::instruction::CompiledInstruction;
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::transaction::Transaction;
|
||||
use std::io::Cursor;
|
||||
use std::thread::{sleep, Builder};
|
||||
use std::time::Duration;
|
||||
|
||||
@@ -1156,4 +1167,51 @@ mod tests {
|
||||
assert!(parent_record_locks2.is_empty());
|
||||
}
|
||||
}
|
||||
|
||||
fn create_accounts(accounts: &Accounts, pubkeys: &mut Vec<Pubkey>, num: usize) {
|
||||
for t in 0..num {
|
||||
let pubkey = Pubkey::new_rand();
|
||||
let account = Account::new((t + 1) as u64, 0, &Account::default().owner);
|
||||
accounts.store_slow(0, &pubkey, &account);
|
||||
pubkeys.push(pubkey.clone());
|
||||
}
|
||||
}
|
||||
|
||||
fn check_accounts(accounts: &Accounts, pubkeys: &Vec<Pubkey>, num: usize) {
|
||||
for _ in 1..num {
|
||||
let idx = thread_rng().gen_range(0, num - 1);
|
||||
let ancestors = vec![(0, 0)].into_iter().collect();
|
||||
let account = accounts.load_slow(&ancestors, &pubkeys[idx]).unwrap();
|
||||
let account1 = Account::new((idx + 1) as u64, 0, &Account::default().owner);
|
||||
assert_eq!(account, (account1, 0));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_accounts_serialize() {
|
||||
solana_logger::setup();
|
||||
let accounts = Accounts::new(Some("serialize_accounts".to_string()));
|
||||
|
||||
let mut pubkeys: Vec<Pubkey> = vec![];
|
||||
create_accounts(&accounts, &mut pubkeys, 100);
|
||||
check_accounts(&accounts, &pubkeys, 100);
|
||||
accounts.add_root(0);
|
||||
|
||||
let sz =
|
||||
serialized_size(&accounts).unwrap() + serialized_size(&*accounts.accounts_db).unwrap();
|
||||
let mut buf = vec![0u8; sz as usize];
|
||||
let mut writer = Cursor::new(&mut buf[..]);
|
||||
serialize_into(&mut writer, &accounts).unwrap();
|
||||
serialize_into(&mut writer, &*accounts.accounts_db).unwrap();
|
||||
|
||||
let mut reader = Cursor::new(&mut buf[..]);
|
||||
let mut daccounts: Accounts = deserialize_from(&mut reader).unwrap();
|
||||
let accounts_db: AccountsDB = deserialize_from(&mut reader).unwrap();
|
||||
daccounts.accounts_db = Arc::new(accounts_db);
|
||||
check_accounts(&daccounts, &pubkeys, 100);
|
||||
assert_eq!(
|
||||
accounts.hash_internal_state(0),
|
||||
daccounts.hash_internal_state(0)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user