2021-12-03 09:00:31 -08:00
|
|
|
use {
|
|
|
|
crate::{
|
2022-03-23 09:57:32 -07:00
|
|
|
accounts::Accounts,
|
2023-01-18 11:51:08 -08:00
|
|
|
accounts_db::AccountStorageEntry,
|
2022-11-28 07:09:47 -08:00
|
|
|
accounts_hash::AccountsHash,
|
2021-12-03 09:00:31 -08:00
|
|
|
bank::{Bank, BankSlotDelta},
|
2022-11-14 13:02:08 -08:00
|
|
|
epoch_accounts_hash::EpochAccountsHash,
|
2022-03-31 08:51:18 -07:00
|
|
|
rent_collector::RentCollector,
|
2021-12-03 09:00:31 -08:00
|
|
|
snapshot_archive_info::{SnapshotArchiveInfo, SnapshotArchiveInfoGetter},
|
2022-10-31 11:28:35 -07:00
|
|
|
snapshot_hash::SnapshotHash,
|
2021-12-03 09:00:31 -08:00
|
|
|
snapshot_utils::{
|
|
|
|
self, ArchiveFormat, BankSnapshotInfo, Result, SnapshotVersion,
|
|
|
|
TMP_BANK_SNAPSHOT_PREFIX,
|
|
|
|
},
|
2021-08-08 05:57:06 -07:00
|
|
|
},
|
2021-12-03 09:00:31 -08:00
|
|
|
log::*,
|
2022-11-28 07:09:47 -08:00
|
|
|
solana_sdk::{clock::Slot, sysvar::epoch_schedule::EpochSchedule},
|
2021-12-03 09:00:31 -08:00
|
|
|
std::{
|
|
|
|
fs,
|
|
|
|
path::{Path, PathBuf},
|
2022-01-11 02:44:46 -08:00
|
|
|
sync::{Arc, Mutex},
|
2022-10-25 09:10:53 -07:00
|
|
|
time::Instant,
|
2021-08-17 11:01:59 -07:00
|
|
|
},
|
2021-12-03 09:00:31 -08:00
|
|
|
tempfile::TempDir,
|
2020-02-18 09:02:29 -08:00
|
|
|
};
|
2019-07-31 17:58:10 -07:00
|
|
|
|
2022-10-13 09:47:36 -07:00
|
|
|
mod compare;
|
|
|
|
pub use compare::*;
|
2019-07-31 17:58:10 -07:00
|
|
|
|
2021-08-17 11:01:59 -07:00
|
|
|
/// The PendingSnapshotPackage passes a SnapshotPackage from AccountsHashVerifier to
|
|
|
|
/// SnapshotPackagerService for archiving
|
|
|
|
pub type PendingSnapshotPackage = Arc<Mutex<Option<SnapshotPackage>>>;
|
|
|
|
|
2022-11-09 09:43:33 -08:00
|
|
|
/// This struct packages up fields to send from AccountsBackgroundService to AccountsHashVerifier
|
2021-08-13 14:08:09 -07:00
|
|
|
pub struct AccountsPackage {
|
2022-09-07 13:41:40 -07:00
|
|
|
pub package_type: AccountsPackageType,
|
2021-02-04 07:00:33 -08:00
|
|
|
pub slot: Slot,
|
|
|
|
pub block_height: Slot,
|
2023-01-18 11:51:08 -08:00
|
|
|
pub snapshot_storages: Vec<Arc<AccountStorageEntry>>,
|
2021-02-04 07:00:33 -08:00
|
|
|
pub expected_capitalization: u64,
|
2022-11-28 07:09:47 -08:00
|
|
|
pub accounts_hash_for_testing: Option<AccountsHash>,
|
2022-03-23 09:57:32 -07:00
|
|
|
pub accounts: Arc<Accounts>,
|
2022-05-02 11:46:17 -07:00
|
|
|
pub epoch_schedule: EpochSchedule,
|
2022-03-31 08:51:18 -07:00
|
|
|
pub rent_collector: RentCollector,
|
2022-10-25 09:10:53 -07:00
|
|
|
|
2022-11-09 09:43:33 -08:00
|
|
|
/// Supplemental information needed for snapshots
|
|
|
|
pub snapshot_info: Option<SupplementalSnapshotInfo>,
|
|
|
|
|
2022-10-25 09:10:53 -07:00
|
|
|
/// The instant this accounts package was send to the queue.
|
|
|
|
/// Used to track how long accounts packages wait before processing.
|
|
|
|
pub enqueued: Instant,
|
2021-02-04 07:00:33 -08:00
|
|
|
}
|
|
|
|
|
2021-08-13 14:08:09 -07:00
|
|
|
impl AccountsPackage {
|
2021-08-31 16:33:27 -07:00
|
|
|
/// Package up bank files, storages, and slot deltas for a snapshot
|
2021-08-04 07:03:03 -07:00
|
|
|
#[allow(clippy::too_many_arguments)]
|
2022-11-09 09:43:33 -08:00
|
|
|
pub fn new_for_snapshot(
|
2022-09-07 13:41:40 -07:00
|
|
|
package_type: AccountsPackageType,
|
2021-08-04 07:03:03 -07:00
|
|
|
bank: &Bank,
|
|
|
|
bank_snapshot_info: &BankSnapshotInfo,
|
2021-08-31 16:33:27 -07:00
|
|
|
bank_snapshots_dir: impl AsRef<Path>,
|
|
|
|
slot_deltas: Vec<BankSlotDelta>,
|
2022-05-10 13:37:41 -07:00
|
|
|
full_snapshot_archives_dir: impl AsRef<Path>,
|
|
|
|
incremental_snapshot_archives_dir: impl AsRef<Path>,
|
2023-01-18 11:51:08 -08:00
|
|
|
snapshot_storages: Vec<Arc<AccountStorageEntry>>,
|
2021-08-04 07:03:03 -07:00
|
|
|
archive_format: ArchiveFormat,
|
|
|
|
snapshot_version: SnapshotVersion,
|
2022-11-28 07:09:47 -08:00
|
|
|
accounts_hash_for_testing: Option<AccountsHash>,
|
2021-08-10 09:10:15 -07:00
|
|
|
) -> Result<Self> {
|
2022-09-07 13:41:40 -07:00
|
|
|
if let AccountsPackageType::Snapshot(snapshot_type) = package_type {
|
|
|
|
info!(
|
|
|
|
"Package snapshot for bank {} has {} account storage entries (snapshot type: {:?})",
|
|
|
|
bank.slot(),
|
|
|
|
snapshot_storages.len(),
|
|
|
|
snapshot_type,
|
2021-08-31 16:33:27 -07:00
|
|
|
);
|
2022-09-07 13:41:40 -07:00
|
|
|
if let SnapshotType::IncrementalSnapshot(incremental_snapshot_base_slot) = snapshot_type
|
|
|
|
{
|
|
|
|
assert!(
|
|
|
|
bank.slot() > incremental_snapshot_base_slot,
|
|
|
|
"Incremental snapshot base slot must be less than the bank being snapshotted!"
|
|
|
|
);
|
|
|
|
}
|
2021-08-31 16:33:27 -07:00
|
|
|
}
|
|
|
|
|
2021-08-04 07:03:03 -07:00
|
|
|
// Hard link the snapshot into a tmpdir, to ensure its not removed prior to packaging.
|
2021-08-31 16:33:27 -07:00
|
|
|
let snapshot_links = tempfile::Builder::new()
|
|
|
|
.prefix(&format!("{}{}-", TMP_BANK_SNAPSHOT_PREFIX, bank.slot()))
|
|
|
|
.tempdir_in(bank_snapshots_dir)?;
|
2021-08-04 07:03:03 -07:00
|
|
|
{
|
2021-08-31 16:33:27 -07:00
|
|
|
let snapshot_hardlink_dir = snapshot_links
|
|
|
|
.path()
|
2021-08-04 07:03:03 -07:00
|
|
|
.join(bank_snapshot_info.slot.to_string());
|
|
|
|
fs::create_dir_all(&snapshot_hardlink_dir)?;
|
2022-03-30 12:06:15 -07:00
|
|
|
let file_name =
|
|
|
|
snapshot_utils::path_to_file_name_str(&bank_snapshot_info.snapshot_path)?;
|
2021-08-04 07:03:03 -07:00
|
|
|
fs::hard_link(
|
|
|
|
&bank_snapshot_info.snapshot_path,
|
2022-11-09 11:39:38 -08:00
|
|
|
snapshot_hardlink_dir.join(file_name),
|
2021-08-04 07:03:03 -07:00
|
|
|
)?;
|
|
|
|
}
|
|
|
|
|
2022-11-09 09:43:33 -08:00
|
|
|
let snapshot_info = SupplementalSnapshotInfo {
|
2021-08-31 16:33:27 -07:00
|
|
|
slot_deltas,
|
|
|
|
snapshot_links,
|
2021-08-04 07:03:03 -07:00
|
|
|
archive_format,
|
|
|
|
snapshot_version,
|
2022-05-10 13:37:41 -07:00
|
|
|
full_snapshot_archives_dir: full_snapshot_archives_dir.as_ref().to_path_buf(),
|
|
|
|
incremental_snapshot_archives_dir: incremental_snapshot_archives_dir
|
|
|
|
.as_ref()
|
|
|
|
.to_path_buf(),
|
2022-11-14 13:02:08 -08:00
|
|
|
epoch_accounts_hash: bank.get_epoch_accounts_hash_to_serialize(),
|
2022-11-09 09:43:33 -08:00
|
|
|
};
|
|
|
|
Ok(Self::_new(
|
|
|
|
package_type,
|
|
|
|
bank,
|
|
|
|
snapshot_storages,
|
|
|
|
accounts_hash_for_testing,
|
|
|
|
Some(snapshot_info),
|
|
|
|
))
|
|
|
|
}
|
|
|
|
|
2022-11-10 07:14:26 -08:00
|
|
|
/// Package up fields needed to compute an EpochAccountsHash
|
|
|
|
#[must_use]
|
|
|
|
pub fn new_for_epoch_accounts_hash(
|
|
|
|
package_type: AccountsPackageType,
|
|
|
|
bank: &Bank,
|
2023-01-18 11:51:08 -08:00
|
|
|
snapshot_storages: Vec<Arc<AccountStorageEntry>>,
|
2022-11-28 07:09:47 -08:00
|
|
|
accounts_hash_for_testing: Option<AccountsHash>,
|
2022-11-10 07:14:26 -08:00
|
|
|
) -> Self {
|
|
|
|
assert_eq!(package_type, AccountsPackageType::EpochAccountsHash);
|
|
|
|
Self::_new(
|
|
|
|
package_type,
|
|
|
|
bank,
|
|
|
|
snapshot_storages,
|
|
|
|
accounts_hash_for_testing,
|
|
|
|
None,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2022-11-09 09:43:33 -08:00
|
|
|
fn _new(
|
|
|
|
package_type: AccountsPackageType,
|
|
|
|
bank: &Bank,
|
2023-01-18 11:51:08 -08:00
|
|
|
snapshot_storages: Vec<Arc<AccountStorageEntry>>,
|
2022-11-28 07:09:47 -08:00
|
|
|
accounts_hash_for_testing: Option<AccountsHash>,
|
2022-11-09 09:43:33 -08:00
|
|
|
snapshot_info: Option<SupplementalSnapshotInfo>,
|
|
|
|
) -> Self {
|
|
|
|
Self {
|
|
|
|
package_type,
|
|
|
|
slot: bank.slot(),
|
|
|
|
block_height: bank.block_height(),
|
|
|
|
snapshot_storages,
|
2021-08-10 09:10:15 -07:00
|
|
|
expected_capitalization: bank.capitalization(),
|
2022-03-24 13:58:52 -07:00
|
|
|
accounts_hash_for_testing,
|
2022-03-23 09:57:32 -07:00
|
|
|
accounts: bank.accounts(),
|
2022-05-02 11:46:17 -07:00
|
|
|
epoch_schedule: *bank.epoch_schedule(),
|
2022-04-11 11:15:00 -07:00
|
|
|
rent_collector: bank.rent_collector().clone(),
|
2022-11-09 09:43:33 -08:00
|
|
|
snapshot_info,
|
2022-10-25 09:10:53 -07:00
|
|
|
enqueued: Instant::now(),
|
2022-11-09 09:43:33 -08:00
|
|
|
}
|
2021-08-04 07:03:03 -07:00
|
|
|
}
|
2022-10-13 09:47:36 -07:00
|
|
|
|
|
|
|
/// Create a new Accounts Package where basically every field is defaulted.
|
|
|
|
/// Only use for tests; many of the fields are invalid!
|
|
|
|
pub fn default_for_tests() -> Self {
|
|
|
|
Self {
|
|
|
|
package_type: AccountsPackageType::AccountsHashVerifier,
|
|
|
|
slot: Slot::default(),
|
|
|
|
block_height: Slot::default(),
|
2023-01-18 11:51:08 -08:00
|
|
|
snapshot_storages: Vec::default(),
|
2022-10-13 09:47:36 -07:00
|
|
|
expected_capitalization: u64::default(),
|
|
|
|
accounts_hash_for_testing: Option::default(),
|
|
|
|
accounts: Arc::new(Accounts::default_for_tests()),
|
|
|
|
epoch_schedule: EpochSchedule::default(),
|
|
|
|
rent_collector: RentCollector::default(),
|
2022-11-09 09:43:33 -08:00
|
|
|
snapshot_info: Some(SupplementalSnapshotInfo {
|
|
|
|
slot_deltas: Vec::default(),
|
|
|
|
snapshot_links: TempDir::new().unwrap(),
|
|
|
|
archive_format: ArchiveFormat::Tar,
|
|
|
|
snapshot_version: SnapshotVersion::default(),
|
|
|
|
full_snapshot_archives_dir: PathBuf::default(),
|
|
|
|
incremental_snapshot_archives_dir: PathBuf::default(),
|
2022-11-14 13:02:08 -08:00
|
|
|
epoch_accounts_hash: Option::default(),
|
2022-11-09 09:43:33 -08:00
|
|
|
}),
|
2022-10-25 09:10:53 -07:00
|
|
|
enqueued: Instant::now(),
|
2022-10-13 09:47:36 -07:00
|
|
|
}
|
|
|
|
}
|
2022-11-09 09:43:33 -08:00
|
|
|
|
|
|
|
/// Returns the path to the snapshot links directory
|
|
|
|
///
|
|
|
|
/// NOTE 1: This path is within the TempDir created for the AccountsPackage, *not* the bank
|
|
|
|
/// snapshots dir passed into `new_for_snapshot()` when creating the AccountsPackage.
|
|
|
|
/// NOTE 2: This fn will panic if the AccountsPackage is of type EpochAccountsHash.
|
|
|
|
pub fn snapshot_links_dir(&self) -> &Path {
|
|
|
|
match self.package_type {
|
|
|
|
AccountsPackageType::AccountsHashVerifier | AccountsPackageType::Snapshot(..) => {
|
|
|
|
self.snapshot_info.as_ref().unwrap().snapshot_links.path()
|
|
|
|
}
|
|
|
|
AccountsPackageType::EpochAccountsHash => {
|
|
|
|
panic!("EAH accounts packages do not contain snapshot information")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-10-13 09:47:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
impl std::fmt::Debug for AccountsPackage {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
f.debug_struct("AccountsPackage")
|
|
|
|
.field("type", &self.package_type)
|
|
|
|
.field("slot", &self.slot)
|
|
|
|
.field("block_height", &self.block_height)
|
|
|
|
.finish_non_exhaustive()
|
|
|
|
}
|
2021-02-04 07:00:33 -08:00
|
|
|
}
|
|
|
|
|
2022-11-09 09:43:33 -08:00
|
|
|
/// Supplemental information needed for snapshots
|
|
|
|
pub struct SupplementalSnapshotInfo {
|
|
|
|
pub slot_deltas: Vec<BankSlotDelta>,
|
|
|
|
pub snapshot_links: TempDir,
|
|
|
|
pub archive_format: ArchiveFormat,
|
|
|
|
pub snapshot_version: SnapshotVersion,
|
|
|
|
pub full_snapshot_archives_dir: PathBuf,
|
|
|
|
pub incremental_snapshot_archives_dir: PathBuf,
|
2022-11-14 13:02:08 -08:00
|
|
|
pub epoch_accounts_hash: Option<EpochAccountsHash>,
|
2022-11-09 09:43:33 -08:00
|
|
|
}
|
|
|
|
|
2022-09-07 13:41:40 -07:00
|
|
|
/// Accounts packages are sent to the Accounts Hash Verifier for processing. There are multiple
|
|
|
|
/// types of accounts packages, which are specified as variants in this enum. All accounts
|
|
|
|
/// packages do share some processing: such as calculating the accounts hash.
|
|
|
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
|
|
|
pub enum AccountsPackageType {
|
|
|
|
AccountsHashVerifier,
|
|
|
|
Snapshot(SnapshotType),
|
|
|
|
EpochAccountsHash,
|
|
|
|
}
|
|
|
|
|
2021-08-13 14:08:09 -07:00
|
|
|
pub struct SnapshotPackage {
|
2021-08-06 18:16:06 -07:00
|
|
|
pub snapshot_archive_info: SnapshotArchiveInfo,
|
2020-04-16 15:12:20 -07:00
|
|
|
pub block_height: Slot,
|
2020-02-10 03:11:37 -08:00
|
|
|
pub slot_deltas: Vec<BankSlotDelta>,
|
2019-10-18 14:58:16 -07:00
|
|
|
pub snapshot_links: TempDir,
|
2023-01-18 11:51:08 -08:00
|
|
|
pub snapshot_storages: Vec<Arc<AccountStorageEntry>>,
|
2020-06-18 22:38:37 -07:00
|
|
|
pub snapshot_version: SnapshotVersion,
|
2021-08-17 11:01:59 -07:00
|
|
|
pub snapshot_type: SnapshotType,
|
2019-07-31 17:58:10 -07:00
|
|
|
}
|
|
|
|
|
2022-04-08 08:42:03 -07:00
|
|
|
impl SnapshotPackage {
|
2022-11-28 07:09:47 -08:00
|
|
|
pub fn new(accounts_package: AccountsPackage, accounts_hash: AccountsHash) -> Self {
|
2022-11-10 08:29:51 -08:00
|
|
|
let AccountsPackageType::Snapshot(snapshot_type) = accounts_package.package_type else {
|
|
|
|
panic!("The AccountsPackage must be of type Snapshot in order to make a SnapshotPackage!");
|
|
|
|
};
|
|
|
|
let Some(snapshot_info) = accounts_package.snapshot_info else {
|
|
|
|
panic!("The AccountsPackage must have snapshot info in order to make a SnapshotPackage!");
|
|
|
|
};
|
2022-11-14 13:02:08 -08:00
|
|
|
let snapshot_hash =
|
|
|
|
SnapshotHash::new(&accounts_hash, snapshot_info.epoch_accounts_hash.as_ref());
|
2022-03-22 19:27:54 -07:00
|
|
|
let mut snapshot_storages = accounts_package.snapshot_storages;
|
2022-11-10 08:29:51 -08:00
|
|
|
let snapshot_archive_path = match snapshot_type {
|
|
|
|
SnapshotType::FullSnapshot => snapshot_utils::build_full_snapshot_archive_path(
|
|
|
|
snapshot_info.full_snapshot_archives_dir,
|
|
|
|
accounts_package.slot,
|
|
|
|
&snapshot_hash,
|
|
|
|
snapshot_info.archive_format,
|
2022-09-07 13:41:40 -07:00
|
|
|
),
|
2022-11-10 08:29:51 -08:00
|
|
|
SnapshotType::IncrementalSnapshot(incremental_snapshot_base_slot) => {
|
2023-01-11 12:05:15 -08:00
|
|
|
snapshot_storages.retain(|storage| storage.slot() > incremental_snapshot_base_slot);
|
2022-11-10 08:29:51 -08:00
|
|
|
assert!(
|
2023-01-11 12:05:15 -08:00
|
|
|
snapshot_storages.iter().all(|storage| storage.slot() > incremental_snapshot_base_slot),
|
2022-11-10 08:29:51 -08:00
|
|
|
"Incremental snapshot package must only contain storage entries where slot > incremental snapshot base slot (i.e. full snapshot slot)!"
|
|
|
|
);
|
|
|
|
snapshot_utils::build_incremental_snapshot_archive_path(
|
|
|
|
snapshot_info.incremental_snapshot_archives_dir,
|
|
|
|
incremental_snapshot_base_slot,
|
|
|
|
accounts_package.slot,
|
|
|
|
&snapshot_hash,
|
|
|
|
snapshot_info.archive_format,
|
|
|
|
)
|
|
|
|
}
|
2021-08-31 16:33:27 -07:00
|
|
|
};
|
|
|
|
|
2019-07-31 17:58:10 -07:00
|
|
|
Self {
|
2021-08-06 18:16:06 -07:00
|
|
|
snapshot_archive_info: SnapshotArchiveInfo {
|
|
|
|
path: snapshot_archive_path,
|
2021-08-31 16:33:27 -07:00
|
|
|
slot: accounts_package.slot,
|
2022-10-31 11:28:35 -07:00
|
|
|
hash: snapshot_hash,
|
2022-11-09 09:43:33 -08:00
|
|
|
archive_format: snapshot_info.archive_format,
|
2021-08-06 18:16:06 -07:00
|
|
|
},
|
2021-08-31 16:33:27 -07:00
|
|
|
block_height: accounts_package.block_height,
|
2022-11-09 09:43:33 -08:00
|
|
|
slot_deltas: snapshot_info.slot_deltas,
|
|
|
|
snapshot_links: snapshot_info.snapshot_links,
|
2022-03-22 19:27:54 -07:00
|
|
|
snapshot_storages,
|
2022-11-09 09:43:33 -08:00
|
|
|
snapshot_version: snapshot_info.snapshot_version,
|
2022-09-07 13:41:40 -07:00
|
|
|
snapshot_type,
|
2019-07-31 17:58:10 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-08-06 18:16:06 -07:00
|
|
|
|
2021-08-13 14:08:09 -07:00
|
|
|
impl SnapshotArchiveInfoGetter for SnapshotPackage {
|
2021-08-06 18:16:06 -07:00
|
|
|
fn snapshot_archive_info(&self) -> &SnapshotArchiveInfo {
|
|
|
|
&self.snapshot_archive_info
|
|
|
|
}
|
|
|
|
}
|
2021-08-17 11:01:59 -07:00
|
|
|
|
2021-08-31 16:33:27 -07:00
|
|
|
/// Snapshots come in two flavors, Full and Incremental. The IncrementalSnapshot has a Slot field,
|
|
|
|
/// which is the incremental snapshot base slot.
|
2021-08-17 11:01:59 -07:00
|
|
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
|
|
|
pub enum SnapshotType {
|
|
|
|
FullSnapshot,
|
2021-08-31 16:33:27 -07:00
|
|
|
IncrementalSnapshot(Slot),
|
2021-08-17 11:01:59 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
impl SnapshotType {
|
2021-08-31 16:33:27 -07:00
|
|
|
pub fn is_full_snapshot(&self) -> bool {
|
|
|
|
matches!(self, SnapshotType::FullSnapshot)
|
|
|
|
}
|
|
|
|
pub fn is_incremental_snapshot(&self) -> bool {
|
|
|
|
matches!(self, SnapshotType::IncrementalSnapshot(_))
|
2021-08-17 11:01:59 -07:00
|
|
|
}
|
|
|
|
}
|
2022-07-12 12:27:28 -07:00
|
|
|
|
|
|
|
/// Helper function to retain only max n of elements to the right of a vector,
|
|
|
|
/// viz. remove v.len() - n elements from the left of the vector.
|
|
|
|
#[inline(always)]
|
|
|
|
pub fn retain_max_n_elements<T>(v: &mut Vec<T>, n: usize) {
|
|
|
|
if v.len() > n {
|
|
|
|
let to_truncate = v.len() - n;
|
|
|
|
v.rotate_left(to_truncate);
|
|
|
|
v.truncate(n);
|
|
|
|
}
|
|
|
|
}
|