diff --git a/runtime/src/in_mem_accounts_index.rs b/runtime/src/in_mem_accounts_index.rs index dfd784b8ad..523f7a193b 100644 --- a/runtime/src/in_mem_accounts_index.rs +++ b/runtime/src/in_mem_accounts_index.rs @@ -8,7 +8,7 @@ use solana_measure::measure::Measure; use solana_sdk::{clock::Slot, pubkey::Pubkey}; use std::collections::{hash_map::Entry, HashMap}; use std::sync::atomic::{AtomicU64, Ordering}; -use std::sync::Arc; +use std::sync::{Arc, RwLock}; use std::fmt::Debug; use std::ops::RangeBounds; @@ -18,7 +18,7 @@ type K = Pubkey; #[derive(Debug)] pub struct InMemAccountsIndex { // backing store - map: HashMap>, + map: RwLock>>, storage: Arc>, bin: usize, } @@ -26,7 +26,7 @@ pub struct InMemAccountsIndex { impl InMemAccountsIndex { pub fn new(storage: &AccountsIndexStorage, bin: usize) -> Self { Self { - map: HashMap::new(), + map: RwLock::default(), storage: storage.storage().clone(), bin, } @@ -41,8 +41,9 @@ impl InMemAccountsIndex { R: RangeBounds + std::fmt::Debug, { Self::update_stat(&self.stats().items, 1); - let mut result = Vec::with_capacity(self.map.len()); - self.map.iter().for_each(|(k, v)| { + let map = self.map.read().unwrap(); + let mut result = Vec::with_capacity(map.len()); + map.iter().for_each(|(k, v)| { if range.map(|range| range.contains(k)).unwrap_or(true) { result.push((*k, v.clone())); } @@ -52,12 +53,12 @@ impl InMemAccountsIndex { pub fn keys(&self) -> Vec { Self::update_stat(&self.stats().keys, 1); - self.map.keys().cloned().collect() + self.map.read().unwrap().keys().cloned().collect() } pub fn get(&self, key: &K) -> Option> { let m = Measure::start("get"); - let result = self.map.get(key).cloned(); + let result = self.map.read().unwrap().get(key).cloned(); let stats = self.stats(); let (count, time) = if result.is_some() { (&stats.gets_from_mem, &stats.get_mem_us) @@ -73,7 +74,8 @@ impl InMemAccountsIndex { // Return false otherwise. pub fn remove_if_slot_list_empty(&mut self, pubkey: Pubkey) -> bool { let m = Measure::start("entry"); - let entry = self.map.entry(pubkey); + let mut map = self.map.write().unwrap(); + let entry = map.entry(pubkey); let stats = &self.storage.stats; let (count, time) = if matches!(entry, Entry::Occupied(_)) { (&stats.entries_from_mem, &stats.entry_mem_us) @@ -101,7 +103,8 @@ impl InMemAccountsIndex { previous_slot_entry_was_cached: bool, ) { let m = Measure::start("entry"); - let entry = self.map.entry(*pubkey); + let mut map = self.map.write().unwrap(); + let entry = map.entry(*pubkey); let stats = &self.storage.stats; let (count, time) = if matches!(entry, Entry::Occupied(_)) { (&stats.entries_from_mem, &stats.entry_mem_us) @@ -194,7 +197,7 @@ impl InMemAccountsIndex { reclaims: &mut SlotList, previous_slot_entry_was_cached: bool, ) -> bool { - if let Some(current) = self.map.get(pubkey) { + if let Some(current) = self.map.read().unwrap().get(pubkey) { Self::lock_and_update_slot_list( current, new_value, @@ -208,7 +211,7 @@ impl InMemAccountsIndex { } pub fn len(&self) -> usize { - self.map.len() + self.map.read().unwrap().len() } pub fn is_empty(&self) -> bool { @@ -223,7 +226,8 @@ impl InMemAccountsIndex { new_entry: AccountMapEntry, ) -> Option<(WriteAccountMapEntry, T, Pubkey)> { let m = Measure::start("entry"); - let entry = self.map.entry(pubkey); + let mut map = self.map.write().unwrap(); + let entry = map.entry(pubkey); let stats = &self.storage.stats; let (count, time) = if matches!(entry, Entry::Occupied(_)) { (&stats.entries_from_mem, &stats.entry_mem_us)