-
Notifications
You must be signed in to change notification settings - Fork 4.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make background services aware of incremental snapshots #19401
Merged
brooksprumo
merged 18 commits into
solana-labs:master
from
brooksprumo:iss-accounts-background-service-4
Aug 31, 2021
Merged
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
6d24603
Make background services aware of incremental snapshots
brooksprumo 1b3a734
pr: add comment to assert
brooksprumo 5985f4f
pr: fix value passed in as last full snapshot slot, not block height
brooksprumo e38ff0c
pr: fs should not fail, so call .expect()
brooksprumo 88fc378
fixup!
brooksprumo 78c39fd
pr: slot -> u64
brooksprumo b6d0370
pr: add is_incremental_snapshot()
brooksprumo a443e7d
fixup!
brooksprumo 218faf9
remove retry from snapshotpackagerservice
brooksprumo 2605731
fixup
brooksprumo 289568e
fixup
brooksprumo c581c36
pr: use bank snapshot info from add_bank_snapshot()
brooksprumo 92afafc
Fixup result propagation
carllin 7201106
fixup: remove old assert
brooksprumo fa2cada
pr: add comment on snapshot_bank
brooksprumo 8a61ca6
pr: check if error from snapshot_utils is fatal
brooksprumo 2bda2ae
remove calculate_last_full_snapshot_slot()
brooksprumo e8c1aad
move fatal check into snapshot request handler
brooksprumo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,14 +6,16 @@ | |
|
||
use rayon::ThreadPool; | ||
use solana_gossip::cluster_info::{ClusterInfo, MAX_SNAPSHOT_HASHES}; | ||
use solana_measure::measure::Measure; | ||
use solana_runtime::{ | ||
accounts_db, | ||
snapshot_archive_info::SnapshotArchiveInfoGetter, | ||
accounts_db::{self, AccountsDb}, | ||
accounts_hash::HashStats, | ||
snapshot_config::SnapshotConfig, | ||
snapshot_package::{ | ||
AccountsPackage, AccountsPackageReceiver, PendingSnapshotPackage, SnapshotPackage, | ||
SnapshotType, | ||
}, | ||
snapshot_utils, | ||
sorted_storages::SortedStorages, | ||
}; | ||
use solana_sdk::{clock::Slot, hash::Hash, pubkey::Pubkey}; | ||
use std::collections::{HashMap, HashSet}; | ||
|
@@ -48,19 +50,17 @@ impl AccountsHashVerifier { | |
.name("solana-hash-accounts".to_string()) | ||
.spawn(move || { | ||
let mut hashes = vec![]; | ||
let mut thread_pool_storage = None; | ||
let mut thread_pool = None; | ||
loop { | ||
if exit.load(Ordering::Relaxed) { | ||
break; | ||
} | ||
|
||
match accounts_package_receiver.recv_timeout(Duration::from_secs(1)) { | ||
Ok(accounts_package) => { | ||
if accounts_package.hash_for_testing.is_some() | ||
&& thread_pool_storage.is_none() | ||
if accounts_package.hash_for_testing.is_some() && thread_pool.is_none() | ||
{ | ||
thread_pool_storage = | ||
Some(accounts_db::make_min_priority_thread_pool()); | ||
thread_pool = Some(accounts_db::make_min_priority_thread_pool()); | ||
} | ||
|
||
Self::process_accounts_package( | ||
|
@@ -73,7 +73,7 @@ impl AccountsHashVerifier { | |
&exit, | ||
fault_injection_rate_slots, | ||
snapshot_config.as_ref(), | ||
thread_pool_storage.as_ref(), | ||
thread_pool.as_ref(), | ||
); | ||
} | ||
Err(RecvTimeoutError::Disconnected) => break, | ||
|
@@ -100,45 +100,69 @@ impl AccountsHashVerifier { | |
snapshot_config: Option<&SnapshotConfig>, | ||
thread_pool: Option<&ThreadPool>, | ||
) { | ||
let snapshot_package = | ||
snapshot_utils::process_accounts_package(accounts_package, thread_pool, None); | ||
Self::process_snapshot_package( | ||
snapshot_package, | ||
Self::verify_accounts_package_hash(&accounts_package, thread_pool); | ||
|
||
Self::push_accounts_hashes_to_cluster( | ||
&accounts_package, | ||
cluster_info, | ||
trusted_validators, | ||
halt_on_trusted_validator_accounts_hash_mismatch, | ||
pending_snapshot_package, | ||
hashes, | ||
exit, | ||
fault_injection_rate_slots, | ||
snapshot_config, | ||
); | ||
|
||
Self::submit_for_packaging(accounts_package, pending_snapshot_package, snapshot_config); | ||
} | ||
|
||
fn process_snapshot_package( | ||
snapshot_package: SnapshotPackage, | ||
fn verify_accounts_package_hash( | ||
accounts_package: &AccountsPackage, | ||
thread_pool: Option<&ThreadPool>, | ||
) { | ||
let mut measure_hash = Measure::start("hash"); | ||
if let Some(expected_hash) = accounts_package.hash_for_testing { | ||
let sorted_storages = SortedStorages::new(&accounts_package.snapshot_storages); | ||
let (hash, lamports) = AccountsDb::calculate_accounts_hash_without_index( | ||
&sorted_storages, | ||
thread_pool, | ||
HashStats::default(), | ||
false, | ||
None, | ||
) | ||
.unwrap(); | ||
|
||
assert_eq!(accounts_package.expected_capitalization, lamports); | ||
assert_eq!(expected_hash, hash); | ||
}; | ||
measure_hash.stop(); | ||
datapoint_info!( | ||
"accounts_hash_verifier", | ||
("calculate_hash", measure_hash.as_us(), i64), | ||
); | ||
} | ||
|
||
fn push_accounts_hashes_to_cluster( | ||
accounts_package: &AccountsPackage, | ||
cluster_info: &ClusterInfo, | ||
trusted_validators: Option<&HashSet<Pubkey>>, | ||
halt_on_trusted_validator_accounts_hash_mismatch: bool, | ||
pending_snapshot_package: Option<&PendingSnapshotPackage>, | ||
hashes: &mut Vec<(Slot, Hash)>, | ||
exit: &Arc<AtomicBool>, | ||
fault_injection_rate_slots: u64, | ||
snapshot_config: Option<&SnapshotConfig>, | ||
) { | ||
let hash = *snapshot_package.hash(); | ||
let hash = accounts_package.hash; | ||
if fault_injection_rate_slots != 0 | ||
&& snapshot_package.slot() % fault_injection_rate_slots == 0 | ||
&& accounts_package.slot % fault_injection_rate_slots == 0 | ||
{ | ||
// For testing, publish an invalid hash to gossip. | ||
use rand::{thread_rng, Rng}; | ||
use solana_sdk::hash::extend_and_hash; | ||
warn!("inserting fault at slot: {}", snapshot_package.slot()); | ||
warn!("inserting fault at slot: {}", accounts_package.slot); | ||
let rand = thread_rng().gen_range(0, 10); | ||
let hash = extend_and_hash(&hash, &[rand]); | ||
hashes.push((snapshot_package.slot(), hash)); | ||
hashes.push((accounts_package.slot, hash)); | ||
} else { | ||
hashes.push((snapshot_package.slot(), hash)); | ||
hashes.push((accounts_package.slot, hash)); | ||
} | ||
|
||
while hashes.len() > MAX_SNAPSHOT_HASHES { | ||
|
@@ -155,19 +179,43 @@ impl AccountsHashVerifier { | |
} | ||
} | ||
|
||
if let Some(snapshot_config) = snapshot_config { | ||
if snapshot_package.block_height % snapshot_config.full_snapshot_archive_interval_slots | ||
== 0 | ||
{ | ||
if let Some(pending_snapshot_package) = pending_snapshot_package { | ||
*pending_snapshot_package.lock().unwrap() = Some(snapshot_package); | ||
} | ||
} | ||
} | ||
|
||
cluster_info.push_accounts_hashes(hashes.clone()); | ||
} | ||
|
||
fn submit_for_packaging( | ||
accounts_package: AccountsPackage, | ||
pending_snapshot_package: Option<&PendingSnapshotPackage>, | ||
snapshot_config: Option<&SnapshotConfig>, | ||
) { | ||
if accounts_package.snapshot_type.is_none() | ||
|| pending_snapshot_package.is_none() | ||
|| snapshot_config.is_none() | ||
{ | ||
return; | ||
}; | ||
|
||
let snapshot_package = SnapshotPackage::from(accounts_package); | ||
let pending_snapshot_package = pending_snapshot_package.unwrap(); | ||
let _snapshot_config = snapshot_config.unwrap(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I may be able to remove SnapshotConfig from AccountsHashVerifier entirely too. I'm thinking about taking some things out of AccountsPackage that live in SnapshotConfig, which I may then use here, so I'm going to leave the SnapshotConfig here for now. |
||
|
||
// If the snapshot package is an Incremental Snapshot, do not submit it if there's already | ||
// a pending Full Snapshot. | ||
let can_submit = match snapshot_package.snapshot_type { | ||
SnapshotType::FullSnapshot => true, | ||
SnapshotType::IncrementalSnapshot(_) => pending_snapshot_package | ||
.lock() | ||
.unwrap() | ||
.as_ref() | ||
.map_or(true, |snapshot_package| { | ||
snapshot_package.snapshot_type.is_incremental_snapshot() | ||
}), | ||
}; | ||
|
||
if can_submit { | ||
*pending_snapshot_package.lock().unwrap() = Some(snapshot_package); | ||
} | ||
} | ||
|
||
fn should_halt( | ||
cluster_info: &ClusterInfo, | ||
trusted_validators: Option<&HashSet<Pubkey>>, | ||
|
@@ -225,10 +273,10 @@ mod tests { | |
use solana_gossip::{cluster_info::make_accounts_hashes_message, contact_info::ContactInfo}; | ||
use solana_runtime::{ | ||
snapshot_config::LastFullSnapshotSlot, | ||
snapshot_package::SnapshotType, | ||
snapshot_utils::{ArchiveFormat, SnapshotVersion}, | ||
}; | ||
use solana_sdk::{ | ||
genesis_config::ClusterType, | ||
hash::hash, | ||
signature::{Keypair, Signer}, | ||
}; | ||
|
@@ -301,30 +349,24 @@ mod tests { | |
last_full_snapshot_slot: LastFullSnapshotSlot::default(), | ||
}; | ||
for i in 0..MAX_SNAPSHOT_HASHES + 1 { | ||
let slot = full_snapshot_archive_interval_slots + i as u64; | ||
let block_height = full_snapshot_archive_interval_slots + i as u64; | ||
let slot_deltas = vec![]; | ||
let snapshot_links = TempDir::new().unwrap(); | ||
let storages = vec![]; | ||
let snapshot_archive_path = PathBuf::from("."); | ||
let hash = hash(&[i as u8]); | ||
let archive_format = ArchiveFormat::TarBzip2; | ||
let snapshot_version = SnapshotVersion::default(); | ||
let snapshot_package = SnapshotPackage::new( | ||
slot, | ||
block_height, | ||
slot_deltas, | ||
snapshot_links, | ||
storages, | ||
snapshot_archive_path, | ||
hash, | ||
archive_format, | ||
snapshot_version, | ||
SnapshotType::FullSnapshot, | ||
); | ||
let accounts_package = AccountsPackage { | ||
slot: full_snapshot_archive_interval_slots + i as u64, | ||
block_height: full_snapshot_archive_interval_slots + i as u64, | ||
slot_deltas: vec![], | ||
snapshot_links: TempDir::new().unwrap(), | ||
snapshot_storages: vec![], | ||
hash: hash(&[i as u8]), | ||
archive_format: ArchiveFormat::TarBzip2, | ||
snapshot_version: SnapshotVersion::default(), | ||
snapshot_archives_dir: PathBuf::default(), | ||
expected_capitalization: 0, | ||
hash_for_testing: None, | ||
cluster_type: ClusterType::MainnetBeta, | ||
snapshot_type: None, | ||
}; | ||
|
||
AccountsHashVerifier::process_snapshot_package( | ||
snapshot_package, | ||
AccountsHashVerifier::process_accounts_package( | ||
accounts_package, | ||
&cluster_info, | ||
Some(&trusted_validators), | ||
false, | ||
|
@@ -333,7 +375,9 @@ mod tests { | |
&exit, | ||
0, | ||
Some(&snapshot_config), | ||
None, | ||
); | ||
|
||
// sleep for 1ms to create a newer timestmap for gossip entry | ||
// otherwise the timestamp won't be newer. | ||
std::thread::sleep(Duration::from_millis(1)); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This used to be in
snapshot_utils::process_accounts_package()
, but nothing used it except for AccountsHashVerifier. So, moving it here. As a plus, now we don't need to pass a TheadPool into other snapshot_utils functions.