solana_runtime/
root_bank_cache.rs1use {
6 crate::{
7 bank::Bank,
8 bank_forks::{BankForks, ReadOnlyAtomicSlot},
9 },
10 std::sync::{Arc, RwLock, Weak},
11};
12
13#[derive(Clone)]
15pub struct RootBankCache {
16 bank_forks: Arc<RwLock<BankForks>>,
17 cached_root_bank: Weak<Bank>,
18 root_slot: ReadOnlyAtomicSlot,
19}
20
21impl RootBankCache {
22 pub fn new(bank_forks: Arc<RwLock<BankForks>>) -> Self {
23 let (cached_root_bank, root_slot) = {
24 let lock = bank_forks.read().unwrap();
25 (Arc::downgrade(&lock.root_bank()), lock.get_atomic_root())
26 };
27 Self {
28 bank_forks,
29 cached_root_bank,
30 root_slot,
31 }
32 }
33
34 pub fn root_bank(&mut self) -> Arc<Bank> {
35 match self.cached_root_bank.upgrade() {
36 Some(cached_root_bank) if cached_root_bank.slot() == self.root_slot.get() => {
37 cached_root_bank
38 }
39 _ => {
40 let root_bank = self.bank_forks.read().unwrap().root_bank();
41 self.cached_root_bank = Arc::downgrade(&root_bank);
42 root_bank
43 }
44 }
45 }
46}
47
48#[cfg(test)]
49mod tests {
50 use {
51 super::*,
52 crate::{
53 accounts_background_service::AbsRequestSender,
54 bank_forks::BankForks,
55 genesis_utils::{create_genesis_config, GenesisConfigInfo},
56 },
57 solana_pubkey::Pubkey,
58 };
59
60 #[test]
61 fn test_root_bank_cache() {
62 let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
63 let bank = Bank::new_for_tests(&genesis_config);
64 let bank_forks = BankForks::new_rw_arc(bank);
65
66 let mut root_bank_cache = RootBankCache::new(bank_forks.clone());
67
68 let bank = bank_forks.read().unwrap().root_bank();
69 assert_eq!(bank, root_bank_cache.root_bank());
70
71 {
72 let child_bank = Bank::new_from_parent(bank.clone(), &Pubkey::default(), 1);
73 bank_forks.write().unwrap().insert(child_bank);
74
75 let cached_root_bank = root_bank_cache.cached_root_bank.upgrade().unwrap();
77 assert_eq!(bank.slot(), cached_root_bank.slot());
78 }
79 {
80 bank_forks
81 .write()
82 .unwrap()
83 .set_root(1, &AbsRequestSender::default(), None)
84 .unwrap();
85 let bank = bank_forks.read().unwrap().root_bank();
86
87 let cached_root_bank = root_bank_cache.cached_root_bank.upgrade().unwrap();
89 assert!(bank.slot() != cached_root_bank.slot());
90 assert!(bank != cached_root_bank);
91 assert_eq!(bank, root_bank_cache.root_bank());
92
93 let cached_root_bank = root_bank_cache.cached_root_bank.upgrade().unwrap();
95 assert_eq!(bank.slot(), cached_root_bank.slot());
96 assert_eq!(bank, cached_root_bank);
97 assert_eq!(bank, root_bank_cache.root_bank());
98 }
99 }
100}