|
|
@@ -23,6 +23,11 @@ mod scan_account_storage;
|
|
|
pub mod stats;
|
|
|
pub mod tests;
|
|
|
|
|
|
+#[cfg(test)]
|
|
|
+use crate::{
|
|
|
+ ancient_append_vecs::{AccountsToStore, StorageSelector},
|
|
|
+ u64_align,
|
|
|
+};
|
|
|
#[cfg(feature = "dev-context-only-utils")]
|
|
|
use qualifier_attr::qualifiers;
|
|
|
use {
|
|
|
@@ -39,7 +44,7 @@ use {
|
|
|
},
|
|
|
accounts_file::{
|
|
|
AccountsFile, AccountsFileError, AccountsFileProvider, MatchAccountOwnerError,
|
|
|
- StorageAccess, ALIGN_BOUNDARY_OFFSET,
|
|
|
+ StorageAccess,
|
|
|
},
|
|
|
accounts_hash::{
|
|
|
AccountHash, AccountLtHash, AccountsDeltaHash, AccountsHash, AccountsHashKind,
|
|
|
@@ -59,9 +64,7 @@ use {
|
|
|
accounts_update_notifier_interface::AccountsUpdateNotifier,
|
|
|
active_stats::{ActiveStatItem, ActiveStats},
|
|
|
ancestors::Ancestors,
|
|
|
- ancient_append_vecs::{
|
|
|
- get_ancient_append_vec_capacity, is_ancient, AccountsToStore, StorageSelector,
|
|
|
- },
|
|
|
+ ancient_append_vecs::get_ancient_append_vec_capacity,
|
|
|
append_vec::{aligned_stored_size, StoredAccountMeta, STORE_META_OVERHEAD},
|
|
|
cache_hash_data::{CacheHashData, DeletionPolicy as CacheHashDeletionPolicy},
|
|
|
contains::Contains,
|
|
|
@@ -73,7 +76,7 @@ use {
|
|
|
read_only_accounts_cache::ReadOnlyAccountsCache,
|
|
|
sorted_storages::SortedStorages,
|
|
|
storable_accounts::{StorableAccounts, StorableAccountsBySlot},
|
|
|
- u64_align, utils,
|
|
|
+ utils,
|
|
|
verify_accounts_hash_in_background::VerifyAccountsHashInBackground,
|
|
|
},
|
|
|
crossbeam_channel::{unbounded, Receiver, Sender, TryRecvError},
|
|
|
@@ -147,15 +150,6 @@ const SHRINK_COLLECT_CHUNK_SIZE: usize = 50;
|
|
|
/// candidates for shrinking.
|
|
|
const SHRINK_INSERT_ANCIENT_THRESHOLD: usize = 10;
|
|
|
|
|
|
-#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
|
|
|
-pub enum CreateAncientStorage {
|
|
|
- /// ancient storages are created by appending
|
|
|
- Append,
|
|
|
- /// ancient storages are created by 1-shot write to pack multiple accounts together more efficiently with new formats
|
|
|
- #[default]
|
|
|
- Pack,
|
|
|
-}
|
|
|
-
|
|
|
#[derive(Debug)]
|
|
|
enum StoreTo<'a> {
|
|
|
/// write to cache
|
|
|
@@ -337,11 +331,16 @@ pub enum StoreReclaims {
|
|
|
///
|
|
|
/// If a caller uses it before initializing it, it will be a runtime unwrap() error, similar to an assert.
|
|
|
/// That condition is an illegal use pattern and is justifiably an assertable condition.
|
|
|
+//
|
|
|
+// NOTE: Only used by ancient append vecs "append" method, which is test-only now.
|
|
|
+#[cfg(test)]
|
|
|
#[derive(Default)]
|
|
|
struct CurrentAncientAccountsFile {
|
|
|
slot_and_accounts_file: Option<(Slot, Arc<AccountStorageEntry>)>,
|
|
|
}
|
|
|
|
|
|
+// NOTE: Only used by ancient append vecs "append" method, which is test-only now.
|
|
|
+#[cfg(test)]
|
|
|
impl CurrentAncientAccountsFile {
|
|
|
fn new(slot: Slot, append_vec: Arc<AccountStorageEntry>) -> CurrentAncientAccountsFile {
|
|
|
Self {
|
|
|
@@ -427,17 +426,20 @@ enum LoadZeroLamports {
|
|
|
SomeWithZeroLamportAccountForTests,
|
|
|
}
|
|
|
|
|
|
+#[cfg(test)]
|
|
|
#[derive(Debug)]
|
|
|
struct AncientSlotPubkeysInner {
|
|
|
pubkeys: HashSet<Pubkey>,
|
|
|
slot: Slot,
|
|
|
}
|
|
|
|
|
|
+#[cfg(test)]
|
|
|
#[derive(Debug, Default)]
|
|
|
struct AncientSlotPubkeys {
|
|
|
inner: Option<AncientSlotPubkeysInner>,
|
|
|
}
|
|
|
|
|
|
+#[cfg(test)]
|
|
|
impl AncientSlotPubkeys {
|
|
|
/// All accounts in 'slot' will be moved to 'current_ancient'
|
|
|
/// If 'slot' is different than the 'current_ancient'.slot, then an account in 'slot' may ALREADY be in the current ancient append vec.
|
|
|
@@ -509,7 +511,6 @@ pub const ACCOUNTS_DB_CONFIG_FOR_TESTING: AccountsDbConfig = AccountsDbConfig {
|
|
|
max_ancient_storages: None,
|
|
|
skip_initial_hash_calc: false,
|
|
|
exhaustively_verify_refcounts: false,
|
|
|
- create_ancient_storage: CreateAncientStorage::Pack,
|
|
|
partitioned_epoch_rewards_config: DEFAULT_PARTITIONED_EPOCH_REWARDS_CONFIG,
|
|
|
test_skip_rewrites_but_include_in_bank_hash: false,
|
|
|
storage_access: StorageAccess::File,
|
|
|
@@ -537,7 +538,6 @@ pub const ACCOUNTS_DB_CONFIG_FOR_BENCHMARKS: AccountsDbConfig = AccountsDbConfig
|
|
|
max_ancient_storages: None,
|
|
|
skip_initial_hash_calc: false,
|
|
|
exhaustively_verify_refcounts: false,
|
|
|
- create_ancient_storage: CreateAncientStorage::Pack,
|
|
|
partitioned_epoch_rewards_config: DEFAULT_PARTITIONED_EPOCH_REWARDS_CONFIG,
|
|
|
test_skip_rewrites_but_include_in_bank_hash: false,
|
|
|
storage_access: StorageAccess::File,
|
|
|
@@ -669,8 +669,6 @@ pub struct AccountsDbConfig {
|
|
|
pub test_skip_rewrites_but_include_in_bank_hash: bool,
|
|
|
pub skip_initial_hash_calc: bool,
|
|
|
pub exhaustively_verify_refcounts: bool,
|
|
|
- /// how to create ancient storages
|
|
|
- pub create_ancient_storage: CreateAncientStorage,
|
|
|
pub partitioned_epoch_rewards_config: PartitionedEpochRewardsConfig,
|
|
|
pub storage_access: StorageAccess,
|
|
|
pub scan_filter_for_shrinking: ScanFilter,
|
|
|
@@ -1489,9 +1487,6 @@ pub struct AccountsDb {
|
|
|
|
|
|
pub storage: AccountStorage,
|
|
|
|
|
|
- /// from AccountsDbConfig
|
|
|
- create_ancient_storage: CreateAncientStorage,
|
|
|
-
|
|
|
/// true if this client should skip rewrites but still include those rewrites in the bank hash as if rewrites had occurred.
|
|
|
pub test_skip_rewrites_but_include_in_bank_hash: bool,
|
|
|
|
|
|
@@ -2033,7 +2028,6 @@ impl AccountsDb {
|
|
|
account_indexes: accounts_db_config.account_indexes.unwrap_or_default(),
|
|
|
shrink_ratio: accounts_db_config.shrink_ratio,
|
|
|
accounts_update_notifier,
|
|
|
- create_ancient_storage: accounts_db_config.create_ancient_storage,
|
|
|
read_only_accounts_cache: ReadOnlyAccountsCache::new(
|
|
|
read_cache_size.0,
|
|
|
read_cache_size.1,
|
|
|
@@ -4228,17 +4222,16 @@ impl AccountsDb {
|
|
|
let oldest_non_ancient_slot = self.get_oldest_non_ancient_slot(epoch_schedule);
|
|
|
let can_randomly_shrink = true;
|
|
|
let sorted_slots = self.get_sorted_potential_ancient_slots(oldest_non_ancient_slot);
|
|
|
- if self.create_ancient_storage == CreateAncientStorage::Append {
|
|
|
- self.combine_ancient_slots(sorted_slots, can_randomly_shrink);
|
|
|
- } else {
|
|
|
- self.combine_ancient_slots_packed(sorted_slots, can_randomly_shrink);
|
|
|
- }
|
|
|
+ self.combine_ancient_slots_packed(sorted_slots, can_randomly_shrink);
|
|
|
}
|
|
|
|
|
|
/// 'accounts' that exist in the current slot we are combining into a different ancient slot
|
|
|
/// 'existing_ancient_pubkeys': pubkeys that exist currently in the ancient append vec slot
|
|
|
/// returns the pubkeys that are in 'accounts' that are already in 'existing_ancient_pubkeys'
|
|
|
/// Also updated 'existing_ancient_pubkeys' to include all pubkeys in 'accounts' since they will soon be written into the ancient slot.
|
|
|
+ //
|
|
|
+ // NOTE: Only used by ancient append vecs "append" method, which is test-only now.
|
|
|
+ #[cfg(test)]
|
|
|
fn get_keys_to_unref_ancient<'a>(
|
|
|
accounts: &'a [&AccountFromStorage],
|
|
|
existing_ancient_pubkeys: &mut HashSet<Pubkey>,
|
|
|
@@ -4260,6 +4253,9 @@ impl AccountsDb {
|
|
|
/// 'accounts' are about to be appended to an ancient append vec. That ancient append vec may already have some accounts.
|
|
|
/// Unref each account in 'accounts' that already exists in 'existing_ancient_pubkeys'.
|
|
|
/// As a side effect, on exit, 'existing_ancient_pubkeys' will now contain all pubkeys in 'accounts'.
|
|
|
+ //
|
|
|
+ // NOTE: Only used by ancient append vecs "append" method, which is test-only now.
|
|
|
+ #[cfg(test)]
|
|
|
fn unref_accounts_already_in_storage(
|
|
|
&self,
|
|
|
accounts: &[&AccountFromStorage],
|
|
|
@@ -4277,6 +4273,7 @@ impl AccountsDb {
|
|
|
/// get the storage from 'slot' to squash
|
|
|
/// or None if this slot should be skipped
|
|
|
/// side effect could be updating 'current_ancient'
|
|
|
+ #[cfg(test)]
|
|
|
fn get_storage_to_move_to_ancient_accounts_file(
|
|
|
&self,
|
|
|
slot: Slot,
|
|
|
@@ -4302,6 +4299,9 @@ impl AccountsDb {
|
|
|
/// can_randomly_shrink: true if ancient append vecs that otherwise don't qualify to be shrunk can be randomly shrunk
|
|
|
/// this is convenient for a running system
|
|
|
/// this is not useful for testing
|
|
|
+ //
|
|
|
+ // NOTE: Only used by ancient append vecs "append" method, which is test-only now.
|
|
|
+ #[cfg(test)]
|
|
|
fn should_move_to_ancient_accounts_file(
|
|
|
&self,
|
|
|
storage: &Arc<AccountStorageEntry>,
|
|
|
@@ -4364,6 +4364,9 @@ impl AccountsDb {
|
|
|
|
|
|
/// Combine all account data from storages in 'sorted_slots' into ancient append vecs.
|
|
|
/// This keeps us from accumulating append vecs for each slot older than an epoch.
|
|
|
+ //
|
|
|
+ // NOTE: Only used by ancient append vecs "append" method, which is test-only now.
|
|
|
+ #[cfg(test)]
|
|
|
fn combine_ancient_slots(&self, sorted_slots: Vec<Slot>, can_randomly_shrink: bool) {
|
|
|
if sorted_slots.is_empty() {
|
|
|
return;
|
|
|
@@ -4423,6 +4426,7 @@ impl AccountsDb {
|
|
|
}
|
|
|
|
|
|
/// put entire alive contents of 'old_storage' into the current ancient append vec or a newly created ancient append vec
|
|
|
+ #[cfg(test)]
|
|
|
fn combine_one_store_into_ancient(
|
|
|
&self,
|
|
|
slot: Slot,
|
|
|
@@ -6876,27 +6880,12 @@ impl AccountsDb {
|
|
|
/// If ancient append vecs are not enabled, return 0.
|
|
|
fn get_oldest_non_ancient_slot_for_hash_calc_scan(
|
|
|
&self,
|
|
|
- max_slot_inclusive: Slot,
|
|
|
- config: &CalcAccountsHashConfig<'_>,
|
|
|
+ _max_slot_inclusive: Slot,
|
|
|
+ _config: &CalcAccountsHashConfig<'_>,
|
|
|
) -> Option<Slot> {
|
|
|
- if self.create_ancient_storage == CreateAncientStorage::Pack {
|
|
|
- // oldest_non_ancient_slot is only applicable when ancient storages are created with `Append`. When ancient storages are created with `Pack`, ancient storages
|
|
|
- // can be created in between non-ancient storages. Return None, because oldest_non_ancient_slot is not applicable here.
|
|
|
- None
|
|
|
- } else if self.ancient_append_vec_offset.is_some() {
|
|
|
- // For performance, this is required when ancient appendvecs are enabled
|
|
|
- Some(
|
|
|
- self.get_oldest_non_ancient_slot_from_slot(
|
|
|
- config.epoch_schedule,
|
|
|
- max_slot_inclusive,
|
|
|
- ),
|
|
|
- )
|
|
|
- } else {
|
|
|
- // This causes the entire range to be chunked together, treating older append vecs just like new ones.
|
|
|
- // This performs well if there are many old append vecs that haven't been cleaned yet.
|
|
|
- // 0 will have the effect of causing ALL older append vecs to be chunked together, just like every other append vec.
|
|
|
- Some(0)
|
|
|
- }
|
|
|
+ // oldest_non_ancient_slot is only applicable when ancient storages are created with `Append`. When ancient storages are created with `Pack`, ancient storages
|
|
|
+ // can be created in between non-ancient storages. Return None, because oldest_non_ancient_slot is not applicable here.
|
|
|
+ None
|
|
|
}
|
|
|
|
|
|
/// hash info about 'storage' into 'hasher'
|
|
|
@@ -7737,14 +7726,7 @@ impl AccountsDb {
|
|
|
pub(crate) fn is_candidate_for_shrink(&self, store: &AccountStorageEntry) -> bool {
|
|
|
// appended ancient append vecs should not be shrunk by the normal shrink codepath.
|
|
|
// It is not possible to identify ancient append vecs when we pack, so no check for ancient when we are not appending.
|
|
|
- let total_bytes = if self.create_ancient_storage == CreateAncientStorage::Append
|
|
|
- && is_ancient(&store.accounts)
|
|
|
- && store.accounts.can_append()
|
|
|
- {
|
|
|
- store.written_bytes()
|
|
|
- } else {
|
|
|
- store.capacity()
|
|
|
- };
|
|
|
+ let total_bytes = store.capacity();
|
|
|
|
|
|
let alive_bytes = store.alive_bytes_exclude_zero_lamport_single_ref_accounts() as u64;
|
|
|
match self.shrink_ratio {
|