@@ -469,6 +469,7 @@ pub(crate) struct ShrinkCollect<'a, T: ShrinkCollectRefs<'a>> {
469469
470470pub const ACCOUNTS_DB_CONFIG_FOR_TESTING: AccountsDbConfig = AccountsDbConfig {
471471 index: Some(ACCOUNTS_INDEX_CONFIG_FOR_TESTING),
472+ base_working_path: None,
472473 accounts_hash_cache_path: None,
473474 filler_accounts_config: FillerAccountsConfig::const_default(),
474475 write_cache_limit_bytes: None,
@@ -480,6 +481,7 @@ pub const ACCOUNTS_DB_CONFIG_FOR_TESTING: AccountsDbConfig = AccountsDbConfig {
480481};
481482pub const ACCOUNTS_DB_CONFIG_FOR_BENCHMARKS: AccountsDbConfig = AccountsDbConfig {
482483 index: Some(ACCOUNTS_INDEX_CONFIG_FOR_BENCHMARKS),
484+ base_working_path: None,
483485 accounts_hash_cache_path: None,
484486 filler_accounts_config: FillerAccountsConfig::const_default(),
485487 write_cache_limit_bytes: None,
@@ -539,6 +541,8 @@ const ANCIENT_APPEND_VEC_DEFAULT_OFFSET: Option<i64> = Some(-10_000);
539541#[derive(Debug, Default, Clone)]
540542pub struct AccountsDbConfig {
541543 pub index: Option<AccountsIndexConfig>,
544+ /// Base directory for various necessary files
545+ pub base_working_path: Option<PathBuf>,
542546 pub accounts_hash_cache_path: Option<PathBuf>,
543547 pub filler_accounts_config: FillerAccountsConfig,
544548 pub write_cache_limit_bytes: Option<u64>,
@@ -1395,12 +1399,14 @@ pub struct AccountsDb {
13951399 /// Set of storage paths to pick from
13961400 pub(crate) paths: Vec<PathBuf>,
13971401
1398- accounts_hash_cache_path: PathBuf,
1399-
1402+ /// Base directory for various necessary files
1403+ base_working_path: PathBuf,
14001404 // used by tests
14011405 // holds this until we are dropped
14021406 #[allow(dead_code)]
1403- temp_accounts_hash_cache_path: Option<TempDir>,
1407+ base_working_temp_dir: Option<TempDir>,
1408+ /// Directory for account hash calculations, within base_working_path
1409+ accounts_hash_cache_path: PathBuf,
14041410
14051411 pub shrink_paths: RwLock<Option<Vec<PathBuf>>>,
14061412
@@ -2347,29 +2353,47 @@ impl<'a> AppendVecScan for ScanState<'a> {
23472353 }
23482354}
23492355
2356+ #[derive(Clone, Debug, Eq, PartialEq)]
2357+ pub struct PubkeyHashAccount {
2358+ pub pubkey: Pubkey,
2359+ pub hash: Hash,
2360+ pub account: AccountSharedData,
2361+ }
2362+
23502363impl AccountsDb {
23512364 pub const DEFAULT_ACCOUNTS_HASH_CACHE_DIR: &str = "accounts_hash_cache";
23522365
23532366 pub fn default_for_tests() -> Self {
2354- Self::default_with_accounts_index(AccountInfoAccountsIndex::default_for_tests(), None)
2367+ Self::default_with_accounts_index(AccountInfoAccountsIndex::default_for_tests(), None, None )
23552368 }
23562369
23572370 fn default_with_accounts_index(
23582371 accounts_index: AccountInfoAccountsIndex,
2372+ base_working_path: Option<PathBuf>,
23592373 accounts_hash_cache_path: Option<PathBuf>,
23602374 ) -> Self {
23612375 let num_threads = get_thread_count();
23622376 const MAX_READ_ONLY_CACHE_DATA_SIZE: usize = 400_000_000; // 400M bytes
23632377
2364- let (accounts_hash_cache_path, temp_accounts_hash_cache_path ) =
2365- if let Some(accounts_hash_cache_path ) = accounts_hash_cache_path {
2366- (accounts_hash_cache_path , None)
2378+ let (base_working_path, base_working_temp_dir ) =
2379+ if let Some(base_working_path ) = base_working_path {
2380+ (base_working_path , None)
23672381 } else {
2368- let temp_dir = TempDir::new().expect("new tempdir" );
2369- let cache_path = temp_dir .path().to_path_buf();
2370- (cache_path , Some(temp_dir ))
2382+ let temp_base_working_dir = TempDir::new().unwrap( );
2383+ let base_working_path = temp_base_working_dir .path().to_path_buf();
2384+ (base_working_path , Some(temp_base_working_dir ))
23712385 };
23722386
2387+ let accounts_hash_cache_path = accounts_hash_cache_path.unwrap_or_else(|| {
2388+ let accounts_hash_cache_path =
2389+ base_working_path.join(Self::DEFAULT_ACCOUNTS_HASH_CACHE_DIR);
2390+ if !accounts_hash_cache_path.exists() {
2391+ std::fs::create_dir(&accounts_hash_cache_path)
2392+ .expect("create accounts hash cache dir");
2393+ }
2394+ accounts_hash_cache_path
2395+ });
2396+
23732397 let mut bank_hash_stats = HashMap::new();
23742398 bank_hash_stats.insert(0, BankHashStats::default());
23752399
@@ -2398,8 +2422,9 @@ impl AccountsDb {
23982422 write_cache_limit_bytes: None,
23992423 write_version: AtomicU64::new(0),
24002424 paths: vec![],
2425+ base_working_path,
2426+ base_working_temp_dir,
24012427 accounts_hash_cache_path,
2402- temp_accounts_hash_cache_path,
24032428 shrink_paths: RwLock::new(None),
24042429 temp_paths: None,
24052430 file_size: DEFAULT_FILE_SIZE,
@@ -2477,6 +2502,9 @@ impl AccountsDb {
24772502 accounts_db_config.as_mut().and_then(|x| x.index.take()),
24782503 exit,
24792504 );
2505+ let base_working_path = accounts_db_config
2506+ .as_ref()
2507+ .and_then(|config| config.base_working_path.clone());
24802508 let accounts_hash_cache_path = accounts_db_config
24812509 .as_ref()
24822510 .and_then(|config| config.accounts_hash_cache_path.clone());
@@ -2534,7 +2562,11 @@ impl AccountsDb {
25342562 .and_then(|x| x.write_cache_limit_bytes),
25352563 partitioned_epoch_rewards_config,
25362564 exhaustively_verify_refcounts,
2537- ..Self::default_with_accounts_index(accounts_index, accounts_hash_cache_path)
2565+ ..Self::default_with_accounts_index(
2566+ accounts_index,
2567+ base_working_path,
2568+ accounts_hash_cache_path,
2569+ )
25382570 };
25392571 if paths_is_empty {
25402572 // Create a temporary set of accounts directories, used primarily
@@ -2581,6 +2613,11 @@ impl AccountsDb {
25812613 self.file_size
25822614 }
25832615
2616+ /// Get the base working directory
2617+ pub fn get_base_working_path(&self) -> PathBuf {
2618+ self.base_working_path.clone()
2619+ }
2620+
25842621 pub fn new_single_for_tests() -> Self {
25852622 AccountsDb::new_for_tests(Vec::new(), &ClusterType::Development)
25862623 }
@@ -7775,6 +7812,42 @@ impl AccountsDb {
77757812 (hashes, scan.as_us(), accumulate)
77767813 }
77777814
7815+ /// Return all of the accounts for a given slot
7816+ pub fn get_pubkey_hash_account_for_slot(&self, slot: Slot) -> Vec<PubkeyHashAccount> {
7817+ type ScanResult =
7818+ ScanStorageResult<PubkeyHashAccount, DashMap<Pubkey, (Hash, AccountSharedData)>>;
7819+ let scan_result: ScanResult = self.scan_account_storage(
7820+ slot,
7821+ |loaded_account: LoadedAccount| {
7822+ // Cache only has one version per key, don't need to worry about versioning
7823+ Some(PubkeyHashAccount {
7824+ pubkey: *loaded_account.pubkey(),
7825+ hash: loaded_account.loaded_hash(),
7826+ account: loaded_account.take_account(),
7827+ })
7828+ },
7829+ |accum: &DashMap<Pubkey, (Hash, AccountSharedData)>, loaded_account: LoadedAccount| {
7830+ // Storage may have duplicates so only keep the latest version for each key
7831+ accum.insert(
7832+ *loaded_account.pubkey(),
7833+ (loaded_account.loaded_hash(), loaded_account.take_account()),
7834+ );
7835+ },
7836+ );
7837+
7838+ match scan_result {
7839+ ScanStorageResult::Cached(cached_result) => cached_result,
7840+ ScanStorageResult::Stored(stored_result) => stored_result
7841+ .into_iter()
7842+ .map(|(pubkey, (hash, account))| PubkeyHashAccount {
7843+ pubkey,
7844+ hash,
7845+ account,
7846+ })
7847+ .collect(),
7848+ }
7849+ }
7850+
77787851 /// Calculate accounts delta hash for `slot`
77797852 ///
77807853 /// As part of calculating the accounts delta hash, get a list of accounts modified this slot
0 commit comments