Skip to content

Commit 35c86ac

Browse files
Seulgi Kimsgkim126
authored andcommitted
Make db lock the cache while it reads data
Currently, read_with_cache locks the cache twice, when checking whether the cache has the data and write the reading data to cache. So someone can update the cache between two lockings.
1 parent af3129e commit 35c86ac

File tree

4 files changed

+21
-23
lines changed

4 files changed

+21
-23
lines changed

core/src/blockchain/body_db.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use std::sync::Arc;
2020

2121
use ctypes::transaction::ShardTransaction;
2222
use kvdb::{DBTransaction, KeyValueDB};
23-
use parking_lot::RwLock;
23+
use parking_lot::{Mutex, RwLock};
2424
use primitives::{Bytes, H256};
2525
use rlp::RlpStream;
2626
use rlp_compress::{blocks_swapper, compress, decompress};
@@ -37,8 +37,8 @@ pub struct BodyDB {
3737
parcel_address_cache: RwLock<HashMap<H256, TransactionAddress>>,
3838
pending_parcel_addresses: RwLock<HashMap<H256, Option<TransactionAddress>>>,
3939

40-
transaction_address_cache: RwLock<HashMap<H256, TransactionAddresses>>,
41-
pending_transaction_addresses: RwLock<HashMap<H256, Option<TransactionAddresses>>>,
40+
transaction_address_cache: Mutex<HashMap<H256, TransactionAddresses>>,
41+
pending_transaction_addresses: Mutex<HashMap<H256, Option<TransactionAddresses>>>,
4242

4343
db: Arc<KeyValueDB>,
4444
}
@@ -53,8 +53,8 @@ impl BodyDB {
5353
parcel_address_cache: RwLock::new(HashMap::new()),
5454
pending_parcel_addresses: RwLock::new(HashMap::new()),
5555

56-
transaction_address_cache: RwLock::new(HashMap::new()),
57-
pending_transaction_addresses: RwLock::new(HashMap::new()),
56+
transaction_address_cache: Default::default(),
57+
pending_transaction_addresses: Default::default(),
5858

5959
db,
6060
};
@@ -88,7 +88,7 @@ impl BodyDB {
8888

8989
pub fn update_best_block(&self, batch: &mut DBTransaction, best_block_changed: &BestBlockChanged) {
9090
let mut pending_parcel_addresses = self.pending_parcel_addresses.write();
91-
let mut pending_transaction_addresses = self.pending_transaction_addresses.write();
91+
let mut pending_transaction_addresses = self.pending_transaction_addresses.lock();
9292
batch.extend_with_option_cache(
9393
db::COL_EXTRA,
9494
&mut *pending_parcel_addresses,
@@ -108,8 +108,8 @@ impl BodyDB {
108108
let mut parcel_address_cache = self.parcel_address_cache.write();
109109
let mut pending_parcel_addresses = self.pending_parcel_addresses.write();
110110

111-
let mut transaction_address_cache = self.transaction_address_cache.write();
112-
let mut pending_transaction_addresses = self.pending_transaction_addresses.write();
111+
let mut transaction_address_cache = self.transaction_address_cache.lock();
112+
let mut pending_transaction_addresses = self.pending_transaction_addresses.lock();
113113

114114
let new_parcels = mem::replace(&mut *pending_parcel_addresses, HashMap::new());
115115
let (retracted_parcels, enacted_parcels) =
@@ -296,12 +296,12 @@ impl BodyProvider for BodyDB {
296296

297297
/// Get the address of parcel with given hash.
298298
fn transaction_address(&self, hash: &H256) -> Option<TransactionAddress> {
299-
let result = self.db.read_with_cache(db::COL_EXTRA, &self.parcel_address_cache, hash)?;
299+
let result = self.db.read_with_cache(db::COL_EXTRA, &mut *self.parcel_address_cache.write(), hash)?;
300300
Some(result)
301301
}
302302

303303
fn transaction_addresses_by_tracker(&self, tracker: &H256) -> Option<TransactionAddresses> {
304-
Some(self.db.read_with_cache(db::COL_EXTRA, &self.transaction_address_cache, tracker)?)
304+
Some(self.db.read_with_cache(db::COL_EXTRA, &mut *self.transaction_address_cache.lock(), tracker)?)
305305
}
306306

307307
/// Get block body data

core/src/blockchain/headerchain.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use std::sync::Arc;
2020

2121
use ctypes::BlockNumber;
2222
use kvdb::{DBTransaction, KeyValueDB};
23-
use parking_lot::RwLock;
23+
use parking_lot::{Mutex, RwLock};
2424
use primitives::{Bytes, H256};
2525
use rlp_compress::{blocks_swapper, compress, decompress};
2626

@@ -49,7 +49,7 @@ pub struct HeaderChain {
4949
// cache
5050
header_cache: RwLock<HashMap<H256, Bytes>>,
5151
detail_cache: RwLock<HashMap<H256, BlockDetails>>,
52-
hash_cache: RwLock<HashMap<BlockNumber, H256>>,
52+
hash_cache: Mutex<HashMap<BlockNumber, H256>>,
5353

5454
db: Arc<KeyValueDB>,
5555

@@ -100,8 +100,8 @@ impl HeaderChain {
100100
best_proposal_header_hash: RwLock::new(best_proposal_header_hash),
101101

102102
header_cache: RwLock::new(HashMap::new()),
103-
detail_cache: RwLock::new(HashMap::new()),
104-
hash_cache: RwLock::new(HashMap::new()),
103+
detail_cache: Default::default(),
104+
hash_cache: Default::default(),
105105

106106
db,
107107

@@ -173,7 +173,7 @@ impl HeaderChain {
173173
let mut best_header_hash = self.best_header_hash.write();
174174
let mut best_proposal_header_hash = self.best_proposal_header_hash.write();
175175
let mut write_block_details = self.detail_cache.write();
176-
let mut write_hashes = self.hash_cache.write();
176+
let mut write_hashes = self.hash_cache.lock();
177177
// update best block
178178
if let Some(hash) = pending_best_header_hash.take() {
179179
*best_header_hash = hash;
@@ -368,7 +368,7 @@ impl HeaderProvider for HeaderChain {
368368

369369
/// Get the familial details concerning a block.
370370
fn block_details(&self, hash: &H256) -> Option<BlockDetails> {
371-
let result = self.db.read_with_cache(db::COL_EXTRA, &self.detail_cache, hash)?;
371+
let result = self.db.read_with_cache(db::COL_EXTRA, &mut *self.detail_cache.write(), hash)?;
372372
Some(result)
373373
}
374374

@@ -378,7 +378,7 @@ impl HeaderProvider for HeaderChain {
378378
if self.best_header().number() < index {
379379
return None
380380
}
381-
let result = self.db.read_with_cache(db::COL_EXTRA, &self.hash_cache, &index)?;
381+
let result = self.db.read_with_cache(db::COL_EXTRA, &mut *self.hash_cache.lock(), &index)?;
382382
Some(result)
383383
}
384384

core/src/blockchain/invoice_db.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ impl InvoiceProvider for InvoiceDB {
7979

8080
/// Get invoices of block with given hash.
8181
fn block_invoices(&self, hash: &H256) -> Option<BlockInvoices> {
82-
let result = self.db.read_with_cache(db::COL_EXTRA, &self.invoice_cache, hash)?;
82+
let result = self.db.read_with_cache(db::COL_EXTRA, &mut *self.invoice_cache.write(), hash)?;
8383
Some(result)
8484
}
8585

core/src/db.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -190,21 +190,19 @@ pub trait Readable {
190190
R: Deref<Target = [u8]>;
191191

192192
/// Returns value for given key either in cache or in database.
193-
fn read_with_cache<K, T, C>(&self, col: Option<u32>, cache: &RwLock<C>, key: &K) -> Option<T>
193+
fn read_with_cache<K, T, C>(&self, col: Option<u32>, cache: &mut C, key: &K) -> Option<T>
194194
where
195195
K: Key<T> + Eq + Hash + Clone,
196196
T: Clone + rlp::Decodable,
197197
C: Cache<K, T>, {
198198
{
199-
let read = cache.read();
200-
if let Some(v) = read.get(key) {
199+
if let Some(v) = cache.get(key) {
201200
return Some(v.clone())
202201
}
203202
}
204203

205204
self.read(col, key).map(|value: T| {
206-
let mut write = cache.write();
207-
write.insert(key.clone(), value.clone());
205+
cache.insert(key.clone(), value.clone());
208206
value
209207
})
210208
}

0 commit comments

Comments
 (0)