29
29
crate :: {
30
30
account_info:: { AccountInfo , Offset , StorageLocation } ,
31
31
account_storage:: {
32
- meta:: StoredAccountMeta , stored_account_info:: StoredAccountInfo , AccountStorage ,
33
- AccountStorageStatus , ShrinkInProgress ,
32
+ meta:: StoredAccountMeta ,
33
+ stored_account_info:: { StoredAccountInfo , StoredAccountInfoWithoutData } ,
34
+ AccountStorage , AccountStorageStatus , ShrinkInProgress ,
34
35
} ,
35
36
accounts_cache:: { AccountsCache , CachedAccount , SlotCache } ,
36
37
accounts_db:: stats:: {
@@ -173,6 +174,8 @@ impl StoreTo<'_> {
173
174
#[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
174
175
pub ( crate ) enum ScanAccountStorageData {
175
176
/// callback for accounts in storage will not include `data`
177
+ // Note, currently only used in tests, but do not remove.
178
+ #[ cfg_attr( not( test) , allow( dead_code) ) ]
176
179
NoData ,
177
180
/// return data (&[u8]) for each account.
178
181
/// This can be expensive to get and is not necessary for many scan operations.
@@ -4924,20 +4927,32 @@ impl AccountsDb {
4924
4927
& self ,
4925
4928
slot : Slot ,
4926
4929
cache_map_func : impl Fn ( & LoadedAccount ) -> Option < R > + Sync ,
4927
- storage_scan_func : impl Fn ( & mut B , & LoadedAccount , Option < & [ u8 ] > ) + Sync ,
4930
+ storage_scan_func : impl for <' a , ' b , ' storage > Fn (
4931
+ & ' b mut B ,
4932
+ & ' a StoredAccountInfoWithoutData < ' storage > ,
4933
+ Option < & ' storage [ u8 ] > , // account data
4934
+ ) + Sync ,
4928
4935
scan_account_storage_data : ScanAccountStorageData ,
4929
4936
) -> ScanStorageResult < R , B >
4930
4937
where
4931
4938
R : Send ,
4932
4939
B : Send + Default + Sync ,
4933
4940
{
4934
4941
self . scan_cache_storage_fallback ( slot, cache_map_func, |retval, storage| {
4935
- storage. scan_accounts ( |account| {
4936
- let loaded_account = LoadedAccount :: Stored ( account) ;
4937
- let data = ( scan_account_storage_data == ScanAccountStorageData :: DataRefForStorage )
4938
- . then_some ( loaded_account. data ( ) ) ;
4939
- storage_scan_func ( retval, & loaded_account, data)
4940
- } ) ;
4942
+ match scan_account_storage_data {
4943
+ ScanAccountStorageData :: NoData => {
4944
+ storage. scan_accounts ( |account| {
4945
+ let account_without_data = StoredAccountInfoWithoutData :: new_from ( & account) ;
4946
+ storage_scan_func ( retval, & account_without_data, None ) ;
4947
+ } ) ;
4948
+ }
4949
+ ScanAccountStorageData :: DataRefForStorage => {
4950
+ storage. scan_accounts ( |account| {
4951
+ let account_without_data = StoredAccountInfoWithoutData :: new_from ( & account) ;
4952
+ storage_scan_func ( retval, & account_without_data, Some ( account. data ) ) ;
4953
+ } ) ;
4954
+ }
4955
+ } ;
4941
4956
} )
4942
4957
}
4943
4958
@@ -7495,20 +7510,23 @@ impl AccountsDb {
7495
7510
let scan_result: ScanStorageResult < ( Pubkey , AccountHash ) , HashMap < Pubkey , AccountHash > > =
7496
7511
self . scan_account_storage (
7497
7512
slot,
7498
- |loaded_account : & LoadedAccount | {
7513
+ |loaded_account| {
7499
7514
// Cache only has one version per key, don't need to worry about versioning
7500
7515
Some ( ( * loaded_account. pubkey ( ) , loaded_account. loaded_hash ( ) ) )
7501
7516
} ,
7502
- |accum : & mut HashMap < Pubkey , AccountHash > ,
7503
- loaded_account : & LoadedAccount ,
7504
- _data| {
7517
+ |accum : & mut HashMap < _ , _ > , stored_account, data| {
7518
+ // SAFETY: We called scan_account_storage() with
7519
+ // ScanAccountStorageData::DataRefForStorage, so `data` must be Some.
7520
+ let data = data. unwrap ( ) ;
7521
+ let loaded_account =
7522
+ LoadedAccount :: Stored ( StoredAccountInfo :: new_from ( stored_account, data) ) ;
7505
7523
let mut loaded_hash = loaded_account. loaded_hash ( ) ;
7506
7524
if loaded_hash == AccountHash ( Hash :: default ( ) ) {
7507
- loaded_hash = Self :: hash_account ( loaded_account, loaded_account. pubkey ( ) )
7525
+ loaded_hash = Self :: hash_account ( & loaded_account, loaded_account. pubkey ( ) )
7508
7526
}
7509
7527
accum. insert ( * loaded_account. pubkey ( ) , loaded_hash) ;
7510
7528
} ,
7511
- ScanAccountStorageData :: NoData ,
7529
+ ScanAccountStorageData :: DataRefForStorage ,
7512
7530
) ;
7513
7531
scan. stop ( ) ;
7514
7532
@@ -7529,11 +7547,16 @@ impl AccountsDb {
7529
7547
// Cache only has one version per key, don't need to worry about versioning
7530
7548
Some ( ( * loaded_account. pubkey ( ) , loaded_account. take_account ( ) ) )
7531
7549
} ,
7532
- |accum : & mut HashMap < _ , _ > , loaded_account, _data| {
7550
+ |accum : & mut HashMap < _ , _ > , stored_account, data| {
7551
+ // SAFETY: We called scan_account_storage() with
7552
+ // ScanAccountStorageData::DataRefForStorage, so `data` must be Some.
7553
+ let data = data. unwrap ( ) ;
7554
+ let loaded_account =
7555
+ LoadedAccount :: Stored ( StoredAccountInfo :: new_from ( stored_account, data) ) ;
7533
7556
// Storage may have duplicates so only keep the latest version for each key
7534
7557
accum. insert ( * loaded_account. pubkey ( ) , loaded_account. take_account ( ) ) ;
7535
7558
} ,
7536
- ScanAccountStorageData :: NoData ,
7559
+ ScanAccountStorageData :: DataRefForStorage ,
7537
7560
) ;
7538
7561
7539
7562
match scan_result {
@@ -7548,27 +7571,30 @@ impl AccountsDb {
7548
7571
ScanStorageResult < PubkeyHashAccount , HashMap < Pubkey , ( AccountHash , AccountSharedData ) > > ;
7549
7572
let scan_result: ScanResult = self . scan_account_storage (
7550
7573
slot,
7551
- |loaded_account : & LoadedAccount | {
7574
+ |loaded_account| {
7552
7575
// Cache only has one version per key, don't need to worry about versioning
7553
7576
Some ( PubkeyHashAccount {
7554
7577
pubkey : * loaded_account. pubkey ( ) ,
7555
7578
hash : loaded_account. loaded_hash ( ) ,
7556
7579
account : loaded_account. take_account ( ) ,
7557
7580
} )
7558
7581
} ,
7559
- |accum : & mut HashMap < Pubkey , ( AccountHash , AccountSharedData ) > ,
7560
- loaded_account : & LoadedAccount ,
7561
- _data| {
7562
- // Storage may have duplicates so only keep the latest version for each key
7582
+ |accum : & mut HashMap < _ , _ > , stored_account, data| {
7583
+ // SAFETY: We called scan_account_storage() with
7584
+ // ScanAccountStorageData::DataRefForStorage, so `data` must be Some.
7585
+ let data = data. unwrap ( ) ;
7586
+ let loaded_account =
7587
+ LoadedAccount :: Stored ( StoredAccountInfo :: new_from ( stored_account, data) ) ;
7563
7588
let mut loaded_hash = loaded_account. loaded_hash ( ) ;
7564
7589
let key = * loaded_account. pubkey ( ) ;
7565
7590
let account = loaded_account. take_account ( ) ;
7566
7591
if loaded_hash == AccountHash ( Hash :: default ( ) ) {
7567
7592
loaded_hash = Self :: hash_account ( & account, & key)
7568
7593
}
7594
+ // Storage may have duplicates so only keep the latest version for each key
7569
7595
accum. insert ( key, ( loaded_hash, account) ) ;
7570
7596
} ,
7571
- ScanAccountStorageData :: NoData ,
7597
+ ScanAccountStorageData :: DataRefForStorage ,
7572
7598
) ;
7573
7599
7574
7600
match scan_result {
0 commit comments