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