Browse Source

Adds scan_accounts_without_data() to avoid loading account data (#5849)

Brooks 7 months ago
parent
commit
44bd7c76f9

+ 1 - 2
accounts-db/src/accounts_db.rs

@@ -4941,8 +4941,7 @@ impl AccountsDb {
         self.scan_cache_storage_fallback(slot, cache_map_func, |retval, storage| {
         self.scan_cache_storage_fallback(slot, cache_map_func, |retval, storage| {
             match scan_account_storage_data {
             match scan_account_storage_data {
                 ScanAccountStorageData::NoData => {
                 ScanAccountStorageData::NoData => {
-                    storage.scan_accounts(|account| {
-                        let account_without_data = StoredAccountInfoWithoutData::new_from(&account);
+                    storage.scan_accounts_without_data(|account_without_data| {
                         storage_scan_func(retval, &account_without_data, None);
                         storage_scan_func(retval, &account_without_data, None);
                     });
                     });
                 }
                 }

+ 21 - 1
accounts-db/src/accounts_file.rs

@@ -3,7 +3,7 @@ use crate::account_storage::meta::StoredAccountMeta;
 use {
 use {
     crate::{
     crate::{
         account_info::AccountInfo,
         account_info::AccountInfo,
-        account_storage::stored_account_info::StoredAccountInfo,
+        account_storage::stored_account_info::{StoredAccountInfo, StoredAccountInfoWithoutData},
         accounts_db::AccountsFileId,
         accounts_db::AccountsFileId,
         accounts_update_notifier_interface::AccountForGeyser,
         accounts_update_notifier_interface::AccountForGeyser,
         append_vec::{AppendVec, AppendVecError, IndexInfo},
         append_vec::{AppendVec, AppendVecError, IndexInfo},
@@ -265,6 +265,26 @@ impl AccountsFile {
     }
     }
 
 
     /// Iterate over all accounts and call `callback` with each account.
     /// Iterate over all accounts and call `callback` with each account.
+    ///
+    /// Note that account data is not read/passed to the callback.
+    pub fn scan_accounts_without_data(
+        &self,
+        callback: impl for<'local> FnMut(StoredAccountInfoWithoutData<'local>),
+    ) {
+        match self {
+            Self::AppendVec(av) => av.scan_accounts_without_data(callback),
+            Self::TieredStorage(ts) => {
+                if let Some(reader) = ts.reader() {
+                    _ = reader.scan_accounts_without_data(callback);
+                }
+            }
+        }
+    }
+
+    /// Iterate over all accounts and call `callback` with each account.
+    ///
+    /// Prefer scan_accounts_without_data() when account data is not needed,
+    /// as it can potentially read less and be faster.
     pub fn scan_accounts(&self, callback: impl for<'local> FnMut(StoredAccountInfo<'local>)) {
     pub fn scan_accounts(&self, callback: impl for<'local> FnMut(StoredAccountInfo<'local>)) {
         match self {
         match self {
             Self::AppendVec(av) => av.scan_accounts(callback),
             Self::AppendVec(av) => av.scan_accounts(callback),

+ 24 - 1
accounts-db/src/append_vec.rs

@@ -8,7 +8,7 @@ use {
     crate::{
     crate::{
         account_storage::{
         account_storage::{
             meta::{AccountMeta, StoredAccountMeta, StoredMeta},
             meta::{AccountMeta, StoredAccountMeta, StoredMeta},
-            stored_account_info::StoredAccountInfo,
+            stored_account_info::{StoredAccountInfo, StoredAccountInfoWithoutData},
         },
         },
         accounts_file::{
         accounts_file::{
             AccountsFileError, InternalsForArchive, MatchAccountOwnerError, Result, StorageAccess,
             AccountsFileError, InternalsForArchive, MatchAccountOwnerError, Result, StorageAccess,
@@ -1100,6 +1100,29 @@ impl AppendVec {
     }
     }
 
 
     /// Iterate over all accounts and call `callback` with each account.
     /// Iterate over all accounts and call `callback` with each account.
+    ///
+    /// Note that account data is not read/passed to the callback.
+    pub fn scan_accounts_without_data(
+        &self,
+        mut callback: impl for<'local> FnMut(StoredAccountInfoWithoutData<'local>),
+    ) {
+        self.scan_stored_accounts_no_data(|stored_account| {
+            let account = StoredAccountInfoWithoutData {
+                pubkey: stored_account.pubkey(),
+                lamports: stored_account.lamports(),
+                owner: stored_account.owner(),
+                data_len: stored_account.data_len() as usize,
+                executable: stored_account.executable(),
+                rent_epoch: stored_account.rent_epoch(),
+            };
+            callback(account);
+        })
+    }
+
+    /// Iterate over all accounts and call `callback` with each account.
+    ///
+    /// Prefer scan_accounts_without_data() when account data is not needed,
+    /// as it can potentially read less and be faster.
     pub fn scan_accounts(&self, mut callback: impl for<'local> FnMut(StoredAccountInfo<'local>)) {
     pub fn scan_accounts(&self, mut callback: impl for<'local> FnMut(StoredAccountInfo<'local>)) {
         self.scan_accounts_stored_meta(|stored_account_meta| {
         self.scan_accounts_stored_meta(|stored_account_meta| {
             let account = StoredAccountInfo {
             let account = StoredAccountInfo {

+ 28 - 1
accounts-db/src/tiered_storage/readable.rs

@@ -1,6 +1,9 @@
 use {
 use {
     crate::{
     crate::{
-        account_storage::{meta::StoredAccountMeta, stored_account_info::StoredAccountInfo},
+        account_storage::{
+            meta::StoredAccountMeta,
+            stored_account_info::{StoredAccountInfo, StoredAccountInfoWithoutData},
+        },
         accounts_file::MatchAccountOwnerError,
         accounts_file::MatchAccountOwnerError,
         append_vec::{IndexInfo, IndexInfoInner},
         append_vec::{IndexInfo, IndexInfoInner},
         tiered_storage::{
         tiered_storage::{
@@ -168,6 +171,30 @@ impl TieredStorageReader {
     }
     }
 
 
     /// Iterate over all accounts and call `callback` with each account.
     /// Iterate over all accounts and call `callback` with each account.
+    ///
+    /// Note that account data is not read/passed to the callback.
+    pub fn scan_accounts_without_data(
+        &self,
+        mut callback: impl for<'local> FnMut(StoredAccountInfoWithoutData<'local>),
+    ) -> TieredStorageResult<()> {
+        // Note, this should be reimplemented to not read account data
+        self.scan_accounts(|stored_account| {
+            let account = StoredAccountInfoWithoutData {
+                pubkey: stored_account.pubkey(),
+                lamports: stored_account.lamports(),
+                owner: stored_account.owner(),
+                data_len: stored_account.data().len(),
+                executable: stored_account.executable(),
+                rent_epoch: stored_account.rent_epoch(),
+            };
+            callback(account);
+        })
+    }
+
+    /// Iterate over all accounts and call `callback` with each account.
+    ///
+    /// Prefer scan_accounts_without_data() when account data is not needed,
+    /// as it can potentially read less and be faster.
     pub fn scan_accounts(
     pub fn scan_accounts(
         &self,
         &self,
         mut callback: impl for<'local> FnMut(StoredAccountInfo<'local>),
         mut callback: impl for<'local> FnMut(StoredAccountInfo<'local>),