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 bank_forks::BankForks,
54 genesis_utils::{create_genesis_config, GenesisConfigInfo},
55 },
56 solana_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.write().unwrap().set_root(1, None, None).unwrap();
80 let bank = bank_forks.read().unwrap().root_bank();
81
82 let cached_root_bank = root_bank_cache.cached_root_bank.upgrade().unwrap();
84 assert!(bank.slot() != cached_root_bank.slot());
85 assert!(bank != cached_root_bank);
86 assert_eq!(bank, root_bank_cache.root_bank());
87
88 let cached_root_bank = root_bank_cache.cached_root_bank.upgrade().unwrap();
90 assert_eq!(bank.slot(), cached_root_bank.slot());
91 assert_eq!(bank, cached_root_bank);
92 assert_eq!(bank, root_bank_cache.root_bank());
93 }
94 }
95}