Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Use RwLock for state DB #7425

Merged
merged 2 commits into from
Jan 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 16 additions & 17 deletions ethcore/src/client/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ pub struct Client {
config: ClientConfig,
pruning: journaldb::Algorithm,
db: RwLock<Arc<KeyValueDB>>,
state_db: Mutex<StateDB>,
state_db: RwLock<StateDB>,
block_queue: BlockQueue,
report: RwLock<ClientReport>,
import_lock: Mutex<()>,
Expand All @@ -166,7 +166,6 @@ pub struct Client {
last_hashes: RwLock<VecDeque<H256>>,
factories: Factories,
history: u64,
rng: Mutex<OsRng>,
ancient_verifier: Mutex<Option<AncientVerifier>>,
on_user_defaults_change: Mutex<Option<Box<FnMut(Option<Mode>) + 'static + Send>>>,
registrar: Mutex<Option<Registry>>,
Expand Down Expand Up @@ -242,7 +241,7 @@ impl Client {
verifier: verification::new(config.verifier_type.clone()),
config: config,
db: RwLock::new(db),
state_db: Mutex::new(state_db),
state_db: RwLock::new(state_db),
block_queue: block_queue,
report: RwLock::new(Default::default()),
import_lock: Mutex::new(()),
Expand All @@ -253,7 +252,6 @@ impl Client {
last_hashes: RwLock::new(VecDeque::new()),
factories: factories,
history: history,
rng: Mutex::new(OsRng::new().map_err(UtilError::from)?),
ancient_verifier: Mutex::new(None),
on_user_defaults_change: Mutex::new(None),
registrar: Mutex::new(None),
Expand All @@ -262,7 +260,7 @@ impl Client {

// prune old states.
{
let state_db = client.state_db.lock().boxed_clone();
let state_db = client.state_db.read().boxed_clone();
let chain = client.chain.read();
client.prune_ancient(state_db, &chain)?;
}
Expand Down Expand Up @@ -452,7 +450,7 @@ impl Client {

// Enact Verified Block
let last_hashes = self.build_last_hashes(header.parent_hash().clone());
let db = self.state_db.lock().boxed_clone_canon(header.parent_hash());
let db = self.state_db.read().boxed_clone_canon(header.parent_hash());

let is_epoch_begin = chain.epoch_transition(parent.number(), *header.parent_hash()).is_some();
let enact_result = enact_verified(block,
Expand Down Expand Up @@ -611,7 +609,8 @@ impl Client {
let verify_with = |verifier: &AncientVerifier| -> Result<(), ::error::Error> {
// verify the block, passing the chain for updating the epoch
// verifier.
verifier.verify(&mut *self.rng.lock(), &header, &chain)
let mut rng = OsRng::new().map_err(UtilError::from)?;
verifier.verify(&mut rng, &header, &chain)
};

// initialize the ancient block verifier if we don't have one already.
Expand Down Expand Up @@ -937,7 +936,7 @@ impl Client {
};

self.block_header(id).and_then(|header| {
let db = self.state_db.lock().boxed_clone();
let db = self.state_db.read().boxed_clone();

// early exit for pruned blocks
if db.is_pruned() && self.pruning_info().earliest_state > block_number {
Expand Down Expand Up @@ -968,7 +967,7 @@ impl Client {
pub fn state(&self) -> State<StateDB> {
let header = self.best_block_header();
State::from_existing(
self.state_db.lock().boxed_clone_canon(&header.hash()),
self.state_db.read().boxed_clone_canon(&header.hash()),
header.state_root(),
self.engine.account_start_nonce(header.number()),
self.factories.clone())
Expand All @@ -983,7 +982,7 @@ impl Client {
/// Get the report.
pub fn report(&self) -> ClientReport {
let mut report = self.report.read().clone();
report.state_db_mem = self.state_db.lock().mem_used();
report.state_db_mem = self.state_db.read().mem_used();
report
}

Expand Down Expand Up @@ -1039,7 +1038,7 @@ impl Client {
/// Take a snapshot at the given block.
/// If the ID given is "latest", this will default to 1000 blocks behind.
pub fn take_snapshot<W: snapshot_io::SnapshotWriter + Send>(&self, writer: W, at: BlockId, p: &snapshot::Progress) -> Result<(), EthcoreError> {
let db = self.state_db.lock().journal_db().boxed_clone();
let db = self.state_db.read().journal_db().boxed_clone();
let best_block_number = self.chain_info().best_block_number;
let block_number = self.block_number(at).ok_or(snapshot::Error::InvalidStartingBlock(at))?;

Expand Down Expand Up @@ -1187,7 +1186,7 @@ impl snapshot::DatabaseRestore for Client {
trace!(target: "snapshot", "Replacing client database with {:?}", new_db);

let _import_lock = self.import_lock.lock();
let mut state_db = self.state_db.lock();
let mut state_db = self.state_db.write();
let mut chain = self.chain.write();
let mut tracedb = self.tracedb.write();
self.miner.clear();
Expand Down Expand Up @@ -1608,7 +1607,7 @@ impl BlockChainClient for Client {
}

fn state_data(&self, hash: &H256) -> Option<Bytes> {
self.state_db.lock().journal_db().state(hash)
self.state_db.read().journal_db().state(hash)
}

fn block_receipts(&self, hash: &H256) -> Option<Bytes> {
Expand Down Expand Up @@ -1790,7 +1789,7 @@ impl BlockChainClient for Client {
fn pruning_info(&self) -> PruningInfo {
PruningInfo {
earliest_chain: self.chain.read().first_block_number().unwrap_or(1),
earliest_state: self.state_db.lock().journal_db().earliest_era().unwrap_or(0),
earliest_state: self.state_db.read().journal_db().earliest_era().unwrap_or(0),
}
}

Expand Down Expand Up @@ -1858,7 +1857,7 @@ impl MiningBlockChainClient for Client {
engine,
self.factories.clone(),
self.tracedb.read().tracing_enabled(),
self.state_db.lock().boxed_clone_canon(&h),
self.state_db.read().boxed_clone_canon(&h),
best_header,
self.build_last_hashes(h.clone()),
author,
Expand Down Expand Up @@ -1943,7 +1942,7 @@ impl MiningBlockChainClient for Client {

let route = self.commit_block(block, &header, &block_data);
trace!(target: "client", "Imported sealed block #{} ({})", number, h);
self.state_db.lock().sync_cache(&route.enacted, &route.retracted, false);
self.state_db.write().sync_cache(&route.enacted, &route.retracted, false);
route
};
let (enacted, retracted) = self.calculate_enacted_retracted(&[route]);
Expand Down Expand Up @@ -2012,7 +2011,7 @@ impl ProvingBlockChainClient for Client {
};

env_info.gas_limit = transaction.gas.clone();
let mut jdb = self.state_db.lock().journal_db().boxed_clone();
let mut jdb = self.state_db.read().journal_db().boxed_clone();

state::prove_transaction(
jdb.as_hashdb_mut(),
Expand Down
9 changes: 5 additions & 4 deletions ethcore/src/state_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ struct CacheQueueItem {
/// Account address.
address: Address,
/// Acccount data or `None` if account does not exist.
account: Option<Account>,
account: Mutex<Option<Account>>,
Copy link
Collaborator

@arkpar arkpar Jan 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure that creating thousands of mutexes is a good idea.

/// Indicates that the account was modified before being
/// added to the cache.
modified: bool,
Expand Down Expand Up @@ -268,15 +268,16 @@ impl StateDB {
modifications.insert(account.address.clone());
}
if is_best {
let acc = account.account.lock().take();
if let Some(&mut Some(ref mut existing)) = cache.accounts.get_mut(&account.address) {
if let Some(new) = account.account {
if let Some(new) = acc {
if account.modified {
existing.overwrite_with(new);
}
continue;
}
}
cache.accounts.insert(account.address, account.account);
cache.accounts.insert(account.address, acc);
}
}

Expand Down Expand Up @@ -408,7 +409,7 @@ impl state::Backend for StateDB {
fn add_to_account_cache(&mut self, addr: Address, data: Option<Account>, modified: bool) {
self.local_cache.push(CacheQueueItem {
address: addr,
account: data,
account: Mutex::new(data),
modified: modified,
})
}
Expand Down