solana_accounts_db/tiered_storage/
readable.rs

1use {
2    crate::{
3        account_storage::meta::StoredAccountMeta,
4        accounts_file::MatchAccountOwnerError,
5        append_vec::IndexInfo,
6        tiered_storage::{
7            file::TieredReadableFile,
8            footer::{AccountMetaFormat, TieredStorageFooter},
9            hot::HotStorageReader,
10            index::IndexOffset,
11            TieredStorageResult,
12        },
13    },
14    solana_pubkey::Pubkey,
15    solana_sdk::account::AccountSharedData,
16    std::path::Path,
17};
18
19/// The reader of a tiered storage instance.
20#[derive(Debug)]
21pub enum TieredStorageReader {
22    Hot(HotStorageReader),
23}
24
25impl TieredStorageReader {
26    /// Creates a reader for the specified tiered storage accounts file.
27    pub fn new_from_path(path: impl AsRef<Path>) -> TieredStorageResult<Self> {
28        let file = TieredReadableFile::new(&path)?;
29        let footer = TieredStorageFooter::new_from_footer_block(&file)?;
30        match footer.account_meta_format {
31            AccountMetaFormat::Hot => Ok(Self::Hot(HotStorageReader::new(file)?)),
32        }
33    }
34
35    /// Returns the size of the underlying storage.
36    pub fn len(&self) -> usize {
37        match self {
38            Self::Hot(hot) => hot.len(),
39        }
40    }
41
42    /// Returns whether the nderlying storage is empty.
43    pub fn is_empty(&self) -> bool {
44        match self {
45            Self::Hot(hot) => hot.is_empty(),
46        }
47    }
48
49    pub fn capacity(&self) -> u64 {
50        match self {
51            Self::Hot(hot) => hot.capacity(),
52        }
53    }
54
55    /// Returns the footer of the associated HotAccountsFile.
56    pub fn footer(&self) -> &TieredStorageFooter {
57        match self {
58            Self::Hot(hot) => hot.footer(),
59        }
60    }
61
62    /// Returns the total number of accounts.
63    pub fn num_accounts(&self) -> usize {
64        match self {
65            Self::Hot(hot) => hot.num_accounts(),
66        }
67    }
68
69    /// Returns the account located at the specified index offset.
70    pub fn get_account_shared_data(
71        &self,
72        index_offset: IndexOffset,
73    ) -> TieredStorageResult<Option<AccountSharedData>> {
74        match self {
75            Self::Hot(hot) => hot.get_account_shared_data(index_offset),
76        }
77    }
78
79    /// calls `callback` with the account located at the specified index offset.
80    pub fn get_stored_account_meta_callback<Ret>(
81        &self,
82        index_offset: IndexOffset,
83        callback: impl for<'local> FnMut(StoredAccountMeta<'local>) -> Ret,
84    ) -> TieredStorageResult<Option<Ret>> {
85        match self {
86            Self::Hot(hot) => hot.get_stored_account_meta_callback(index_offset, callback),
87        }
88    }
89
90    /// Returns Ok(index_of_matching_owner) if the account owner at
91    /// `account_offset` is one of the pubkeys in `owners`.
92    ///
93    /// Returns Err(MatchAccountOwnerError::NoMatch) if the account has 0
94    /// lamports or the owner is not one of the pubkeys in `owners`.
95    ///
96    /// Returns Err(MatchAccountOwnerError::UnableToLoad) if there is any internal
97    /// error that causes the data unable to load, including `account_offset`
98    /// causes a data overrun.
99    pub fn account_matches_owners(
100        &self,
101        index_offset: IndexOffset,
102        owners: &[Pubkey],
103    ) -> Result<usize, MatchAccountOwnerError> {
104        match self {
105            Self::Hot(hot) => {
106                let account_offset = hot
107                    .get_account_offset(index_offset)
108                    .map_err(|_| MatchAccountOwnerError::UnableToLoad)?;
109                hot.account_matches_owners(account_offset, owners)
110            }
111        }
112    }
113
114    /// iterate over all pubkeys
115    pub fn scan_pubkeys(&self, callback: impl FnMut(&Pubkey)) -> TieredStorageResult<()> {
116        match self {
117            Self::Hot(hot) => hot.scan_pubkeys(callback),
118        }
119    }
120
121    /// iterate over all entries to put in index
122    pub(crate) fn scan_index(&self, callback: impl FnMut(IndexInfo)) -> TieredStorageResult<()> {
123        match self {
124            Self::Hot(hot) => hot.scan_index(callback),
125        }
126    }
127
128    /// Iterate over all accounts and call `callback` with each account.
129    pub(crate) fn scan_accounts(
130        &self,
131        callback: impl for<'local> FnMut(StoredAccountMeta<'local>),
132    ) -> TieredStorageResult<()> {
133        match self {
134            Self::Hot(hot) => hot.scan_accounts(callback),
135        }
136    }
137
138    /// for each offset in `sorted_offsets`, return the account size
139    pub(crate) fn get_account_sizes(
140        &self,
141        sorted_offsets: &[usize],
142    ) -> TieredStorageResult<Vec<usize>> {
143        match self {
144            Self::Hot(hot) => hot.get_account_sizes(sorted_offsets),
145        }
146    }
147
148    /// Returns a slice suitable for use when archiving tiered storages
149    pub fn data_for_archive(&self) -> &[u8] {
150        match self {
151            Self::Hot(hot) => hot.data_for_archive(),
152        }
153    }
154}