2020-05-22 10:54:24 -07:00
use {
crate ::{
accounts ::Accounts ,
2021-06-09 21:21:32 -07:00
accounts_db ::{
2021-09-07 21:30:38 -07:00
AccountShrinkThreshold , AccountStorageEntry , AccountsDb , AccountsDbConfig , AppendVecId ,
2022-01-13 07:20:20 -08:00
AtomicAppendVecId , BankHashInfo , IndexGenerationInfo , SnapshotStorage ,
2021-06-09 21:21:32 -07:00
} ,
2021-09-07 21:30:38 -07:00
accounts_index ::AccountSecondaryIndexes ,
2021-09-30 14:26:17 -07:00
accounts_update_notifier_interface ::AccountsUpdateNotifier ,
2021-05-17 16:58:36 -07:00
append_vec ::{ AppendVec , StoredMetaWriteVersion } ,
2021-09-02 21:29:11 -07:00
bank ::{ Bank , BankFieldsToDeserialize , BankRc } ,
2020-07-13 07:00:59 -07:00
blockhash_queue ::BlockhashQueue ,
2021-09-02 21:29:11 -07:00
builtins ::Builtins ,
2020-07-13 07:00:59 -07:00
epoch_stakes ::EpochStakes ,
2021-03-10 09:49:10 -08:00
hardened_unpack ::UnpackedAppendVecMap ,
2020-07-13 07:00:59 -07:00
rent_collector ::RentCollector ,
2022-04-06 19:39:26 -07:00
snapshot_utils ::{ self , BANK_SNAPSHOT_PRE_FILENAME_EXTENSION } ,
2020-07-13 07:00:59 -07:00
stakes ::Stakes ,
2020-05-22 10:54:24 -07:00
} ,
2021-12-03 09:00:31 -08:00
bincode ::{ self , config ::Options , Error } ,
2021-03-10 09:49:10 -08:00
log ::* ,
2021-06-16 06:48:24 -07:00
rayon ::prelude ::* ,
2020-08-03 16:27:17 -07:00
serde ::{ de ::DeserializeOwned , Deserialize , Serialize } ,
2021-09-23 15:34:32 -07:00
solana_measure ::measure ::Measure ,
2020-07-13 07:00:59 -07:00
solana_sdk ::{
clock ::{ Epoch , Slot , UnixTimestamp } ,
2022-03-24 08:06:24 -07:00
deserialize_utils ::default_on_eof ,
2020-07-13 07:00:59 -07:00
epoch_schedule ::EpochSchedule ,
fee_calculator ::{ FeeCalculator , FeeRateGovernor } ,
genesis_config ::GenesisConfig ,
hard_forks ::HardForks ,
hash ::Hash ,
inflation ::Inflation ,
pubkey ::Pubkey ,
} ,
2020-05-22 10:54:24 -07:00
std ::{
2020-09-23 18:46:42 -07:00
collections ::{ HashMap , HashSet } ,
2021-03-10 09:49:10 -08:00
io ::{ self , BufReader , BufWriter , Read , Write } ,
2021-06-21 08:47:58 -07:00
path ::{ Path , PathBuf } ,
2020-05-22 10:54:24 -07:00
result ::Result ,
2021-09-23 15:34:32 -07:00
sync ::{
atomic ::{ AtomicUsize , Ordering } ,
Arc , RwLock ,
} ,
2021-10-24 12:43:33 -07:00
thread ::Builder ,
2020-05-22 10:54:24 -07:00
} ,
2022-02-01 15:34:11 -08:00
storage ::{ SerializableStorage , SerializedAppendVecId } ,
2020-05-22 10:54:24 -07:00
} ;
2022-01-13 05:12:09 -08:00
mod newer ;
2022-01-13 07:20:20 -08:00
mod storage ;
2020-05-22 10:54:24 -07:00
mod tests ;
mod utils ;
// a number of test cases in accounts_db use this
#[ cfg(test) ]
2022-01-13 07:20:20 -08:00
pub ( crate ) use tests ::reconstruct_accounts_db_via_serialization ;
2020-05-22 10:54:24 -07:00
#[ derive(Copy, Clone, Eq, PartialEq) ]
2020-07-13 07:00:59 -07:00
pub ( crate ) enum SerdeStyle {
2021-02-18 23:42:09 -08:00
Newer ,
2020-05-22 10:54:24 -07:00
}
2020-07-13 07:00:59 -07:00
const MAX_STREAM_SIZE : u64 = 32 * 1024 * 1024 * 1024 ;
2020-05-22 10:54:24 -07:00
2022-04-06 19:55:44 -07:00
#[ derive(Clone, Debug, Default, Deserialize, Serialize, AbiExample, PartialEq) ]
2021-05-17 16:58:36 -07:00
struct AccountsDbFields < T > (
HashMap < Slot , Vec < T > > ,
StoredMetaWriteVersion ,
Slot ,
BankHashInfo ,
2022-03-24 08:06:24 -07:00
/// all slots that were roots within the last epoch
#[ serde(deserialize_with = " default_on_eof " ) ]
Vec < Slot > ,
/// slots that were roots within the last epoch for which we care about the hash value
#[ serde(deserialize_with = " default_on_eof " ) ]
Vec < ( Slot , Hash ) > ,
2021-05-17 16:58:36 -07:00
) ;
2020-05-22 10:54:24 -07:00
2021-07-22 12:40:37 -07:00
/// Helper type to wrap BufReader streams when deserializing and reconstructing from either just a
/// full snapshot, or both a full and incremental snapshot
pub struct SnapshotStreams < ' a , R > {
pub full_snapshot_stream : & ' a mut BufReader < R > ,
pub incremental_snapshot_stream : Option < & ' a mut BufReader < R > > ,
}
/// Helper type to wrap AccountsDbFields when reconstructing AccountsDb from either just a full
/// snapshot, or both a full and incremental snapshot
#[ derive(Debug) ]
struct SnapshotAccountsDbFields < T > {
full_snapshot_accounts_db_fields : AccountsDbFields < T > ,
incremental_snapshot_accounts_db_fields : Option < AccountsDbFields < T > > ,
}
impl < T > SnapshotAccountsDbFields < T > {
/// Collapse the SnapshotAccountsDbFields into a single AccountsDbFields. If there is no
2022-03-24 08:06:24 -07:00
/// incremental snapshot, this returns the AccountsDbFields from the full snapshot.
/// Otherwise, use the AccountsDbFields from the incremental snapshot, and a combination
/// of the storages from both the full and incremental snapshots.
2021-07-22 12:40:37 -07:00
fn collapse_into ( self ) -> Result < AccountsDbFields < T > , Error > {
match self . incremental_snapshot_accounts_db_fields {
None = > Ok ( self . full_snapshot_accounts_db_fields ) ,
Some ( AccountsDbFields (
mut incremental_snapshot_storages ,
incremental_snapshot_version ,
incremental_snapshot_slot ,
incremental_snapshot_bank_hash_info ,
2022-04-02 10:01:43 -07:00
incremental_snapshot_historical_roots ,
incremental_snapshot_historical_roots_with_hash ,
2021-07-22 12:40:37 -07:00
) ) = > {
let full_snapshot_storages = self . full_snapshot_accounts_db_fields . 0 ;
let full_snapshot_slot = self . full_snapshot_accounts_db_fields . 2 ;
// filter out incremental snapshot storages with slot <= full snapshot slot
incremental_snapshot_storages . retain ( | slot , _ | * slot > full_snapshot_slot ) ;
// There must not be any overlap in the slots of storages between the full snapshot and the incremental snapshot
incremental_snapshot_storages
. iter ( )
. all ( | storage_entry | ! full_snapshot_storages . contains_key ( storage_entry . 0 ) ) . then ( | | ( ) ) . ok_or_else ( | | {
io ::Error ::new ( io ::ErrorKind ::InvalidData , " Snapshots are incompatible: There are storages for the same slot in both the full snapshot and the incremental snapshot! " )
} ) ? ;
let mut combined_storages = full_snapshot_storages ;
combined_storages . extend ( incremental_snapshot_storages . into_iter ( ) ) ;
Ok ( AccountsDbFields (
combined_storages ,
incremental_snapshot_version ,
incremental_snapshot_slot ,
incremental_snapshot_bank_hash_info ,
2022-04-02 10:01:43 -07:00
incremental_snapshot_historical_roots ,
incremental_snapshot_historical_roots_with_hash ,
2021-07-22 12:40:37 -07:00
) )
}
}
}
}
2022-04-06 19:55:44 -07:00
trait TypeContext < ' a > : PartialEq {
2020-05-22 10:54:24 -07:00
type SerializableAccountStorageEntry : Serialize
+ DeserializeOwned
+ From < & ' a AccountStorageEntry >
2021-06-16 06:48:24 -07:00
+ SerializableStorage
+ Sync ;
2020-05-22 10:54:24 -07:00
2020-07-13 07:00:59 -07:00
fn serialize_bank_and_storage < S : serde ::ser ::Serializer > (
2020-05-22 10:54:24 -07:00
serializer : S ,
2020-07-13 07:00:59 -07:00
serializable_bank : & SerializableBankAndStorage < ' a , Self > ,
2020-05-22 10:54:24 -07:00
) -> std ::result ::Result < S ::Ok , S ::Error >
where
Self : std ::marker ::Sized ;
fn serialize_accounts_db_fields < S : serde ::ser ::Serializer > (
serializer : S ,
2021-02-18 23:42:09 -08:00
serializable_db : & SerializableAccountsDb < ' a , Self > ,
2020-05-22 10:54:24 -07:00
) -> std ::result ::Result < S ::Ok , S ::Error >
where
Self : std ::marker ::Sized ;
2020-07-13 07:00:59 -07:00
fn deserialize_bank_fields < R > (
stream : & mut BufReader < R > ,
) -> Result <
(
BankFieldsToDeserialize ,
AccountsDbFields < Self ::SerializableAccountStorageEntry > ,
) ,
Error ,
>
where
R : Read ;
2020-05-22 10:54:24 -07:00
fn deserialize_accounts_db_fields < R > (
stream : & mut BufReader < R > ,
2020-07-13 07:00:59 -07:00
) -> Result < AccountsDbFields < Self ::SerializableAccountStorageEntry > , Error >
2020-05-22 10:54:24 -07:00
where
R : Read ;
2022-04-07 12:05:57 -07:00
/// deserialize the bank from 'stream_reader'
/// modify the accounts_hash
/// reserialize the bank to 'stream_writer'
fn reserialize_bank_fields_with_hash < R , W > (
stream_reader : & mut BufReader < R > ,
stream_writer : & mut BufWriter < W > ,
accounts_hash : & Hash ,
) -> std ::result ::Result < ( ) , Box < bincode ::ErrorKind > >
where
R : Read ,
W : Write ;
2020-07-13 07:00:59 -07:00
}
2020-05-22 10:54:24 -07:00
2020-07-13 07:00:59 -07:00
fn deserialize_from < R , T > ( reader : R ) -> bincode ::Result < T >
where
R : Read ,
T : DeserializeOwned ,
{
bincode ::options ( )
. with_limit ( MAX_STREAM_SIZE )
. with_fixint_encoding ( )
. allow_trailing_bytes ( )
. deserialize_from ::< R , T > ( reader )
2020-05-22 10:54:24 -07:00
}
2022-04-06 19:55:44 -07:00
/// used by tests to compare contents of serialized bank fields
/// serialized format is not deterministic - likely due to randomness in structs like hashmaps
pub ( crate ) fn compare_two_serialized_banks (
path1 : impl AsRef < Path > ,
path2 : impl AsRef < Path > ,
) -> std ::result ::Result < bool , Error > {
use std ::fs ::File ;
let file1 = File ::open ( path1 ) ? ;
let mut stream1 = BufReader ::new ( file1 ) ;
let file2 = File ::open ( path2 ) ? ;
let mut stream2 = BufReader ::new ( file2 ) ;
let fields1 = newer ::Context ::deserialize_bank_fields ( & mut stream1 ) ? ;
let fields2 = newer ::Context ::deserialize_bank_fields ( & mut stream2 ) ? ;
Ok ( fields1 = = fields2 )
}
2021-01-11 17:00:23 -08:00
#[ allow(clippy::too_many_arguments) ]
2021-07-22 12:40:37 -07:00
pub ( crate ) fn bank_from_streams < R > (
2020-05-22 10:54:24 -07:00
serde_style : SerdeStyle ,
2021-07-22 12:40:37 -07:00
snapshot_streams : & mut SnapshotStreams < R > ,
2020-07-13 07:00:59 -07:00
account_paths : & [ PathBuf ] ,
2021-03-10 09:49:10 -08:00
unpacked_append_vec_map : UnpackedAppendVecMap ,
2020-07-13 07:00:59 -07:00
genesis_config : & GenesisConfig ,
2020-09-23 18:46:42 -07:00
debug_keys : Option < Arc < HashSet < Pubkey > > > ,
2020-09-24 12:23:09 -07:00
additional_builtins : Option < & Builtins > ,
2021-07-22 12:40:37 -07:00
account_secondary_indexes : AccountSecondaryIndexes ,
2021-01-11 17:00:23 -08:00
caching_enabled : bool ,
2021-05-26 08:36:12 -07:00
limit_load_slot_count_from_snapshot : Option < usize > ,
2021-06-09 21:21:32 -07:00
shrink_ratio : AccountShrinkThreshold ,
2021-07-13 09:06:18 -07:00
verify_index : bool ,
2021-09-07 21:30:38 -07:00
accounts_db_config : Option < AccountsDbConfig > ,
2021-09-30 14:26:17 -07:00
accounts_update_notifier : Option < AccountsUpdateNotifier > ,
2020-07-13 07:00:59 -07:00
) -> std ::result ::Result < Bank , Error >
2020-05-22 10:54:24 -07:00
where
R : Read ,
{
macro_rules ! INTO {
2022-01-13 05:12:09 -08:00
( $style :ident ) = > { {
2021-07-22 12:40:37 -07:00
let ( full_snapshot_bank_fields , full_snapshot_accounts_db_fields ) =
2022-01-13 05:12:09 -08:00
$style ::Context ::deserialize_bank_fields ( snapshot_streams . full_snapshot_stream ) ? ;
2021-07-22 12:40:37 -07:00
let ( incremental_snapshot_bank_fields , incremental_snapshot_accounts_db_fields ) =
if let Some ( ref mut incremental_snapshot_stream ) =
snapshot_streams . incremental_snapshot_stream
{
let ( bank_fields , accounts_db_fields ) =
2022-01-13 05:12:09 -08:00
$style ::Context ::deserialize_bank_fields ( incremental_snapshot_stream ) ? ;
2021-07-22 12:40:37 -07:00
( Some ( bank_fields ) , Some ( accounts_db_fields ) )
} else {
( None , None )
} ;
let snapshot_accounts_db_fields = SnapshotAccountsDbFields {
full_snapshot_accounts_db_fields ,
incremental_snapshot_accounts_db_fields ,
} ;
2020-07-13 07:00:59 -07:00
let bank = reconstruct_bank_from_fields (
2021-07-22 12:40:37 -07:00
incremental_snapshot_bank_fields . unwrap_or ( full_snapshot_bank_fields ) ,
snapshot_accounts_db_fields ,
2020-07-13 07:00:59 -07:00
genesis_config ,
account_paths ,
2021-03-10 09:49:10 -08:00
unpacked_append_vec_map ,
2020-09-23 18:46:42 -07:00
debug_keys ,
2020-09-24 12:23:09 -07:00
additional_builtins ,
2021-07-22 12:40:37 -07:00
account_secondary_indexes ,
2021-01-11 17:00:23 -08:00
caching_enabled ,
2021-05-26 08:36:12 -07:00
limit_load_slot_count_from_snapshot ,
2021-06-09 21:21:32 -07:00
shrink_ratio ,
2021-07-13 09:06:18 -07:00
verify_index ,
2021-09-07 21:30:38 -07:00
accounts_db_config ,
2021-09-30 14:26:17 -07:00
accounts_update_notifier ,
2020-07-13 07:00:59 -07:00
) ? ;
Ok ( bank )
} } ;
2020-05-22 10:54:24 -07:00
}
match serde_style {
2022-01-13 05:12:09 -08:00
SerdeStyle ::Newer = > INTO ! ( newer ) ,
2020-05-22 10:54:24 -07:00
}
2020-06-17 01:56:29 -07:00
. map_err ( | err | {
warn! ( " bankrc_from_stream error: {:?} " , err ) ;
err
} )
2020-05-22 10:54:24 -07:00
}
2020-07-13 07:00:59 -07:00
pub ( crate ) fn bank_to_stream < W > (
2020-05-22 10:54:24 -07:00
serde_style : SerdeStyle ,
stream : & mut BufWriter < W > ,
2020-07-13 07:00:59 -07:00
bank : & Bank ,
2020-05-22 10:54:24 -07:00
snapshot_storages : & [ SnapshotStorage ] ,
2020-06-17 01:56:29 -07:00
) -> Result < ( ) , Error >
2020-05-22 10:54:24 -07:00
where
W : Write ,
{
macro_rules ! INTO {
2022-01-13 05:12:09 -08:00
( $style :ident ) = > {
2020-07-13 07:00:59 -07:00
bincode ::serialize_into (
2020-05-22 10:54:24 -07:00
stream ,
2022-01-13 05:12:09 -08:00
& SerializableBankAndStorage ::< $style ::Context > {
2020-07-13 07:00:59 -07:00
bank ,
2020-05-22 10:54:24 -07:00
snapshot_storages ,
phantom : std ::marker ::PhantomData ::default ( ) ,
} ,
)
} ;
}
match serde_style {
2022-01-13 05:12:09 -08:00
SerdeStyle ::Newer = > INTO ! ( newer ) ,
2020-05-22 10:54:24 -07:00
}
2020-06-17 01:56:29 -07:00
. map_err ( | err | {
warn! ( " bankrc_to_stream error: {:?} " , err ) ;
err
} )
2020-05-22 10:54:24 -07:00
}
2022-04-07 12:05:57 -07:00
/// deserialize the bank from 'stream_reader'
/// modify the accounts_hash
/// reserialize the bank to 'stream_writer'
fn reserialize_bank_fields_with_new_hash < W , R > (
stream_reader : & mut BufReader < R > ,
stream_writer : & mut BufWriter < W > ,
accounts_hash : & Hash ,
) -> Result < ( ) , Error >
where
W : Write ,
R : Read ,
{
newer ::Context ::reserialize_bank_fields_with_hash ( stream_reader , stream_writer , accounts_hash )
}
/// effectively updates the accounts hash in the serialized bank file on disk
/// read serialized bank from pre file
/// update accounts_hash
/// write serialized bank to post file
/// return true if pre file found
pub fn reserialize_bank_with_new_accounts_hash (
bank_snapshots_dir : impl AsRef < Path > ,
slot : Slot ,
accounts_hash : & Hash ,
) -> bool {
2022-04-06 19:39:26 -07:00
let bank_post = snapshot_utils ::get_bank_snapshots_dir ( bank_snapshots_dir , slot ) ;
let bank_post = bank_post . join ( snapshot_utils ::get_snapshot_file_name ( slot ) ) ;
let mut bank_pre = bank_post . clone ( ) ;
bank_pre . set_extension ( BANK_SNAPSHOT_PRE_FILENAME_EXTENSION ) ;
2022-04-07 12:05:57 -07:00
let mut found = false ;
{
let file = std ::fs ::File ::open ( & bank_pre ) ;
// some tests don't create the file
if let Ok ( file ) = file {
found = true ;
let file_out = std ::fs ::File ::create ( bank_post ) . unwrap ( ) ;
reserialize_bank_fields_with_new_hash (
& mut BufReader ::new ( file ) ,
& mut BufWriter ::new ( file_out ) ,
accounts_hash ,
)
. unwrap ( ) ;
}
}
if found {
2022-04-06 19:39:26 -07:00
std ::fs ::remove_file ( bank_pre ) . unwrap ( ) ;
}
2022-04-07 12:05:57 -07:00
found
2022-04-06 19:39:26 -07:00
}
2020-07-13 07:00:59 -07:00
struct SerializableBankAndStorage < ' a , C > {
bank : & ' a Bank ,
2020-05-22 10:54:24 -07:00
snapshot_storages : & ' a [ SnapshotStorage ] ,
phantom : std ::marker ::PhantomData < C > ,
}
2020-07-13 07:00:59 -07:00
impl < ' a , C : TypeContext < ' a > > Serialize for SerializableBankAndStorage < ' a , C > {
2020-05-22 10:54:24 -07:00
fn serialize < S > ( & self , serializer : S ) -> std ::result ::Result < S ::Ok , S ::Error >
where
S : serde ::ser ::Serializer ,
{
2020-07-13 07:00:59 -07:00
C ::serialize_bank_and_storage ( serializer , self )
2020-05-22 10:54:24 -07:00
}
}
2021-02-18 23:42:09 -08:00
struct SerializableAccountsDb < ' a , C > {
accounts_db : & ' a AccountsDb ,
2020-05-22 10:54:24 -07:00
slot : Slot ,
account_storage_entries : & ' a [ SnapshotStorage ] ,
phantom : std ::marker ::PhantomData < C > ,
}
2021-02-18 23:42:09 -08:00
impl < ' a , C : TypeContext < ' a > > Serialize for SerializableAccountsDb < ' a , C > {
2020-05-22 10:54:24 -07:00
fn serialize < S > ( & self , serializer : S ) -> std ::result ::Result < S ::Ok , S ::Error >
where
S : serde ::ser ::Serializer ,
{
C ::serialize_accounts_db_fields ( serializer , self )
}
}
2020-07-13 07:00:59 -07:00
#[ cfg(RUSTC_WITH_SPECIALIZATION) ]
2022-01-13 05:12:09 -08:00
impl < ' a , C > solana_frozen_abi ::abi_example ::IgnoreAsHelper for SerializableAccountsDb < ' a , C > { }
2020-07-13 07:00:59 -07:00
2021-01-11 17:00:23 -08:00
#[ allow(clippy::too_many_arguments) ]
2021-03-10 09:49:10 -08:00
fn reconstruct_bank_from_fields < E > (
2020-07-13 07:00:59 -07:00
bank_fields : BankFieldsToDeserialize ,
2021-07-22 12:40:37 -07:00
snapshot_accounts_db_fields : SnapshotAccountsDbFields < E > ,
2020-07-13 07:00:59 -07:00
genesis_config : & GenesisConfig ,
account_paths : & [ PathBuf ] ,
2021-03-10 09:49:10 -08:00
unpacked_append_vec_map : UnpackedAppendVecMap ,
2020-09-23 18:46:42 -07:00
debug_keys : Option < Arc < HashSet < Pubkey > > > ,
2020-09-24 12:23:09 -07:00
additional_builtins : Option < & Builtins > ,
2021-07-22 12:40:37 -07:00
account_secondary_indexes : AccountSecondaryIndexes ,
2021-01-11 17:00:23 -08:00
caching_enabled : bool ,
2021-05-26 08:36:12 -07:00
limit_load_slot_count_from_snapshot : Option < usize > ,
2021-06-09 21:21:32 -07:00
shrink_ratio : AccountShrinkThreshold ,
2021-07-13 09:06:18 -07:00
verify_index : bool ,
2021-09-07 21:30:38 -07:00
accounts_db_config : Option < AccountsDbConfig > ,
2021-09-30 14:26:17 -07:00
accounts_update_notifier : Option < AccountsUpdateNotifier > ,
2020-07-13 07:00:59 -07:00
) -> Result < Bank , Error >
where
2021-06-16 06:48:24 -07:00
E : SerializableStorage + std ::marker ::Sync ,
2020-07-13 07:00:59 -07:00
{
2021-12-10 11:27:59 -08:00
let ( accounts_db , reconstructed_accounts_db_info ) = reconstruct_accountsdb_from_fields (
2021-07-22 12:40:37 -07:00
snapshot_accounts_db_fields ,
2020-09-02 00:37:36 -07:00
account_paths ,
2021-03-10 09:49:10 -08:00
unpacked_append_vec_map ,
2021-10-11 10:46:27 -07:00
genesis_config ,
2021-07-22 12:40:37 -07:00
account_secondary_indexes ,
2021-01-11 17:00:23 -08:00
caching_enabled ,
2021-05-26 08:36:12 -07:00
limit_load_slot_count_from_snapshot ,
2021-06-09 21:21:32 -07:00
shrink_ratio ,
2021-07-13 09:06:18 -07:00
verify_index ,
2021-09-07 21:30:38 -07:00
accounts_db_config ,
2021-09-30 14:26:17 -07:00
accounts_update_notifier ,
2020-09-02 00:37:36 -07:00
) ? ;
2020-07-13 07:00:59 -07:00
let bank_rc = BankRc ::new ( Accounts ::new_empty ( accounts_db ) , bank_fields . slot ) ;
2021-06-15 13:39:22 -07:00
// if limit_load_slot_count_from_snapshot is set, then we need to side-step some correctness checks beneath this call
let debug_do_not_add_builtins = limit_load_slot_count_from_snapshot . is_some ( ) ;
2020-09-24 12:23:09 -07:00
let bank = Bank ::new_from_fields (
bank_rc ,
genesis_config ,
bank_fields ,
debug_keys ,
additional_builtins ,
2021-06-15 13:39:22 -07:00
debug_do_not_add_builtins ,
2021-12-11 07:34:38 -08:00
reconstructed_accounts_db_info . accounts_data_len ,
2020-09-24 12:23:09 -07:00
) ;
2020-07-13 07:00:59 -07:00
2021-11-04 04:28:41 -07:00
info! ( " rent_collector: {:?} " , bank . rent_collector ( ) ) ;
2020-07-13 07:00:59 -07:00
Ok ( bank )
}
2021-06-21 08:47:58 -07:00
fn reconstruct_single_storage < E > (
slot : & Slot ,
append_vec_path : & Path ,
storage_entry : & E ,
2021-12-17 07:06:23 -08:00
append_vec_id : AppendVecId ,
2021-06-21 08:47:58 -07:00
new_slot_storage : & mut HashMap < AppendVecId , Arc < AccountStorageEntry > > ,
) -> Result < ( ) , Error >
where
E : SerializableStorage ,
{
let ( accounts , num_accounts ) =
AppendVec ::new_from_file ( append_vec_path , storage_entry . current_len ( ) ) ? ;
let u_storage_entry =
2021-09-23 15:34:32 -07:00
AccountStorageEntry ::new_existing ( * slot , append_vec_id , accounts , num_accounts ) ;
2021-06-21 08:47:58 -07:00
2021-09-23 15:34:32 -07:00
new_slot_storage . insert ( append_vec_id , Arc ::new ( u_storage_entry ) ) ;
2021-06-21 08:47:58 -07:00
Ok ( ( ) )
}
2021-12-10 11:27:59 -08:00
/// This struct contains side-info while reconstructing the accounts DB from fields.
#[ derive(Debug, Default, Copy, Clone) ]
struct ReconstructedAccountsDbInfo {
accounts_data_len : u64 ,
}
2021-08-10 03:45:46 -07:00
#[ allow(clippy::too_many_arguments) ]
2021-03-10 09:49:10 -08:00
fn reconstruct_accountsdb_from_fields < E > (
2021-07-22 12:40:37 -07:00
snapshot_accounts_db_fields : SnapshotAccountsDbFields < E > ,
2020-05-22 10:54:24 -07:00
account_paths : & [ PathBuf ] ,
2021-03-10 09:49:10 -08:00
unpacked_append_vec_map : UnpackedAppendVecMap ,
2021-10-11 10:46:27 -07:00
genesis_config : & GenesisConfig ,
2021-07-22 12:40:37 -07:00
account_secondary_indexes : AccountSecondaryIndexes ,
2021-01-11 17:00:23 -08:00
caching_enabled : bool ,
2021-05-26 08:36:12 -07:00
limit_load_slot_count_from_snapshot : Option < usize > ,
2021-06-09 21:21:32 -07:00
shrink_ratio : AccountShrinkThreshold ,
2021-07-13 09:06:18 -07:00
verify_index : bool ,
2021-09-07 21:30:38 -07:00
accounts_db_config : Option < AccountsDbConfig > ,
2021-09-30 14:26:17 -07:00
accounts_update_notifier : Option < AccountsUpdateNotifier > ,
2021-12-10 11:27:59 -08:00
) -> Result < ( AccountsDb , ReconstructedAccountsDbInfo ) , Error >
2020-05-22 10:54:24 -07:00
where
2021-06-16 06:48:24 -07:00
E : SerializableStorage + std ::marker ::Sync ,
2020-05-22 10:54:24 -07:00
{
2021-02-18 23:42:09 -08:00
let mut accounts_db = AccountsDb ::new_with_config (
2021-01-11 17:00:23 -08:00
account_paths . to_vec ( ) ,
2021-10-11 10:46:27 -07:00
& genesis_config . cluster_type ,
2021-07-22 12:40:37 -07:00
account_secondary_indexes ,
2021-01-11 17:00:23 -08:00
caching_enabled ,
2021-06-09 21:21:32 -07:00
shrink_ratio ,
2021-09-07 21:30:38 -07:00
accounts_db_config ,
2021-09-30 14:26:17 -07:00
accounts_update_notifier ,
2021-01-11 17:00:23 -08:00
) ;
2021-07-22 12:40:37 -07:00
let AccountsDbFields (
snapshot_storages ,
snapshot_version ,
snapshot_slot ,
snapshot_bank_hash_info ,
2022-04-04 11:13:11 -07:00
snapshot_historical_roots ,
snapshot_historical_roots_with_hash ,
2021-07-22 12:40:37 -07:00
) = snapshot_accounts_db_fields . collapse_into ( ) ? ;
let snapshot_storages = snapshot_storages . into_iter ( ) . collect ::< Vec < _ > > ( ) ;
2020-05-22 10:54:24 -07:00
2021-01-02 17:57:56 -08:00
// Ensure all account paths exist
for path in & accounts_db . paths {
std ::fs ::create_dir_all ( path )
. unwrap_or_else ( | err | panic! ( " Failed to create directory {} : {} " , path . display ( ) , err ) ) ;
}
2022-04-04 11:13:11 -07:00
reconstruct_historical_roots (
& accounts_db ,
snapshot_historical_roots ,
snapshot_historical_roots_with_hash ,
) ;
2020-05-22 10:54:24 -07:00
// Remap the deserialized AppendVec paths to point to correct local paths
2021-09-23 15:34:32 -07:00
let num_collisions = AtomicUsize ::new ( 0 ) ;
2021-12-11 19:34:35 -08:00
let next_append_vec_id = AtomicAppendVecId ::new ( 0 ) ;
2021-09-23 15:34:32 -07:00
let mut measure_remap = Measure ::start ( " remap " ) ;
2021-07-22 12:40:37 -07:00
let mut storage = ( 0 .. snapshot_storages . len ( ) )
2021-06-16 06:48:24 -07:00
. into_par_iter ( )
. map ( | i | {
2021-07-22 12:40:37 -07:00
let ( slot , slot_storage ) = & snapshot_storages [ i ] ;
2020-05-22 10:54:24 -07:00
let mut new_slot_storage = HashMap ::new ( ) ;
2021-06-16 06:48:24 -07:00
for storage_entry in slot_storage {
let file_name = AppendVec ::file_name ( * slot , storage_entry . id ( ) ) ;
2020-05-22 10:54:24 -07:00
2021-03-10 09:49:10 -08:00
let append_vec_path = unpacked_append_vec_map . get ( & file_name ) . ok_or_else ( | | {
io ::Error ::new (
io ::ErrorKind ::NotFound ,
format! ( " {} not found in unpacked append vecs " , file_name ) ,
)
} ) ? ;
2021-01-28 08:15:33 -08:00
2021-09-23 15:34:32 -07:00
// Remap the AppendVec ID to handle any duplicate IDs that may previously existed
// due to full snapshots and incremental snapshots generated from different nodes
let ( remapped_append_vec_id , remapped_append_vec_path ) = loop {
2021-11-18 18:34:37 -08:00
let remapped_append_vec_id = next_append_vec_id . fetch_add ( 1 , Ordering ::AcqRel ) ;
2021-09-23 15:34:32 -07:00
let remapped_file_name = AppendVec ::file_name ( * slot , remapped_append_vec_id ) ;
let remapped_append_vec_path =
append_vec_path . parent ( ) . unwrap ( ) . join ( & remapped_file_name ) ;
// Break out of the loop in the following situations:
// 1. The new ID is the same as the original ID. This means we do not need to
// rename the file, since the ID is the "correct" one already.
// 2. There is not a file already at the new path. This means it is safe to
// rename the file to this new path.
// **DEVELOPER NOTE:** Keep this check last so that it can short-circuit if
// possible.
2022-01-13 07:20:20 -08:00
if storage_entry . id ( ) = = remapped_append_vec_id as SerializedAppendVecId
2021-09-23 15:34:32 -07:00
| | std ::fs ::metadata ( & remapped_append_vec_path ) . is_err ( )
{
break ( remapped_append_vec_id , remapped_append_vec_path ) ;
}
// If we made it this far, a file exists at the new path. Record the collision
// and try again.
num_collisions . fetch_add ( 1 , Ordering ::Relaxed ) ;
} ;
// Only rename the file if the new ID is actually different from the original.
2022-01-13 07:20:20 -08:00
if storage_entry . id ( ) ! = remapped_append_vec_id as SerializedAppendVecId {
2021-09-23 15:34:32 -07:00
std ::fs ::rename ( append_vec_path , & remapped_append_vec_path ) ? ;
}
2021-06-21 08:47:58 -07:00
reconstruct_single_storage (
2021-06-21 10:12:56 -07:00
slot ,
2021-09-23 15:34:32 -07:00
& remapped_append_vec_path ,
2021-06-21 08:47:58 -07:00
storage_entry ,
2021-12-17 07:06:23 -08:00
remapped_append_vec_id ,
2021-06-21 08:47:58 -07:00
& mut new_slot_storage ,
) ? ;
2020-05-22 10:54:24 -07:00
}
2021-06-16 06:48:24 -07:00
Ok ( ( * slot , new_slot_storage ) )
2020-05-22 10:54:24 -07:00
} )
2020-06-17 01:56:29 -07:00
. collect ::< Result < HashMap < Slot , _ > , Error > > ( ) ? ;
2021-09-23 15:34:32 -07:00
measure_remap . stop ( ) ;
2020-05-22 10:54:24 -07:00
// discard any slots with no storage entries
// this can happen if a non-root slot was serialized
// but non-root stores should not be included in the snapshot
storage . retain ( | _slot , stores | ! stores . is_empty ( ) ) ;
2021-09-23 15:34:32 -07:00
assert! (
! storage . is_empty ( ) ,
" At least one storage entry must exist from deserializing stream "
) ;
2021-11-18 18:34:37 -08:00
let next_append_vec_id = next_append_vec_id . load ( Ordering ::Acquire ) ;
2021-09-23 15:34:32 -07:00
let max_append_vec_id = next_append_vec_id - 1 ;
assert! (
max_append_vec_id < = AppendVecId ::MAX / 2 ,
" Storage id {} larger than allowed max " ,
max_append_vec_id
) ;
2020-05-22 10:54:24 -07:00
2021-09-23 15:34:32 -07:00
// Process deserialized data, set necessary fields in self
2020-05-22 10:54:24 -07:00
accounts_db
. bank_hashes
. write ( )
. unwrap ( )
2021-07-22 12:40:37 -07:00
. insert ( snapshot_slot , snapshot_bank_hash_info ) ;
2022-01-13 15:51:53 -08:00
accounts_db . storage . map . extend (
2021-09-23 15:34:32 -07:00
storage
. into_iter ( )
. map ( | ( slot , slot_storage_entry ) | ( slot , Arc ::new ( RwLock ::new ( slot_storage_entry ) ) ) ) ,
) ;
accounts_db
. next_id
2021-11-18 18:34:37 -08:00
. store ( next_append_vec_id , Ordering ::Release ) ;
2020-05-22 10:54:24 -07:00
accounts_db
. write_version
2021-11-17 05:11:16 -08:00
. fetch_add ( snapshot_version , Ordering ::Release ) ;
2021-10-24 12:43:33 -07:00
let mut measure_notify = Measure ::start ( " accounts_notify " ) ;
let accounts_db = Arc ::new ( accounts_db ) ;
2022-03-08 16:28:00 -08:00
let accounts_db_clone = accounts_db . clone ( ) ;
2021-10-24 12:43:33 -07:00
let handle = Builder ::new ( )
. name ( " notify_account_restore_from_snapshot " . to_string ( ) )
. spawn ( move | | {
2022-03-08 16:28:00 -08:00
accounts_db_clone . notify_account_restore_from_snapshot ( ) ;
2021-10-24 12:43:33 -07:00
} )
. unwrap ( ) ;
2021-12-10 11:27:59 -08:00
let IndexGenerationInfo { accounts_data_len } = accounts_db . generate_index (
2021-11-03 12:44:52 -07:00
limit_load_slot_count_from_snapshot ,
verify_index ,
genesis_config ,
) ;
2021-12-10 11:27:59 -08:00
2022-05-20 07:03:55 -07:00
accounts_db . maybe_add_filler_accounts (
& genesis_config . epoch_schedule ,
& genesis_config . rent ,
genesis_config . epoch_schedule . get_epoch ( snapshot_slot ) ,
) ;
2021-09-23 15:34:32 -07:00
2021-10-24 12:43:33 -07:00
handle . join ( ) . unwrap ( ) ;
2021-09-30 14:26:17 -07:00
measure_notify . stop ( ) ;
2021-09-23 15:34:32 -07:00
datapoint_info! (
" reconstruct_accountsdb_from_fields() " ,
( " remap-time-us " , measure_remap . as_us ( ) , i64 ) ,
(
" remap-collisions " ,
num_collisions . load ( Ordering ::Relaxed ) ,
i64
) ,
2021-09-30 14:26:17 -07:00
( " accountsdb-notify-at-start-us " , measure_notify . as_us ( ) , i64 ) ,
2021-09-23 15:34:32 -07:00
) ;
2021-12-10 11:27:59 -08:00
Ok ( (
Arc ::try_unwrap ( accounts_db ) . unwrap ( ) ,
ReconstructedAccountsDbInfo { accounts_data_len } ,
) )
2020-05-22 10:54:24 -07:00
}
2022-04-04 11:13:11 -07:00
/// populate 'historical_roots' from 'snapshot_historical_roots' and 'snapshot_historical_roots_with_hash'
fn reconstruct_historical_roots (
accounts_db : & AccountsDb ,
mut snapshot_historical_roots : Vec < Slot > ,
snapshot_historical_roots_with_hash : Vec < ( Slot , Hash ) > ,
) {
// inflate 'historical_roots'
// inserting into 'historical_roots' needs to be in order
// combine the slots into 1 vec, then sort
// dups are ok
snapshot_historical_roots . extend (
snapshot_historical_roots_with_hash
. into_iter ( )
. map ( | ( root , _ ) | root ) ,
) ;
snapshot_historical_roots . sort_unstable ( ) ;
let mut roots_tracker = accounts_db . accounts_index . roots_tracker . write ( ) . unwrap ( ) ;
snapshot_historical_roots . into_iter ( ) . for_each ( | root | {
roots_tracker . historical_roots . insert ( root ) ;
} ) ;
}