Merge branch 'master' of github.com:ethcore/parity into client_submodules

This commit is contained in:
debris
2016-03-11 11:03:52 +01:00
4 changed files with 215 additions and 189 deletions

View File

@@ -16,6 +16,7 @@
//! Blockchain database.
use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrder};
use util::*;
use header::*;
use extras::*;
@@ -134,8 +135,9 @@ struct CacheManager {
///
/// **Does not do input data verification.**
pub struct BlockChain {
pref_cache_size: usize,
max_cache_size: usize,
// All locks must be captured in the order declared here.
pref_cache_size: AtomicUsize,
max_cache_size: AtomicUsize,
best_block: RwLock<BestBlock>,
@@ -157,6 +159,8 @@ pub struct BlockChain {
// blooms indexing
bloom_indexer: BloomIndexer,
insert_lock: Mutex<()>
}
impl FilterDataSource for BlockChain {
@@ -262,8 +266,8 @@ impl BlockChain {
(0..COLLECTION_QUEUE_SIZE).foreach(|_| cache_man.cache_usage.push_back(HashSet::new()));
let bc = BlockChain {
pref_cache_size: config.pref_cache_size,
max_cache_size: config.max_cache_size,
pref_cache_size: AtomicUsize::new(config.pref_cache_size),
max_cache_size: AtomicUsize::new(config.max_cache_size),
best_block: RwLock::new(BestBlock::default()),
blocks: RwLock::new(HashMap::new()),
block_details: RwLock::new(HashMap::new()),
@@ -275,7 +279,8 @@ impl BlockChain {
extras_db: extras_db,
blocks_db: blocks_db,
cache_man: RwLock::new(cache_man),
bloom_indexer: BloomIndexer::new(BLOOM_INDEX_SIZE, BLOOM_LEVELS)
bloom_indexer: BloomIndexer::new(BLOOM_INDEX_SIZE, BLOOM_LEVELS),
insert_lock: Mutex::new(()),
};
// load best block
@@ -318,9 +323,9 @@ impl BlockChain {
}
/// Set the cache configuration.
pub fn configure_cache(&mut self, pref_cache_size: usize, max_cache_size: usize) {
self.pref_cache_size = pref_cache_size;
self.max_cache_size = max_cache_size;
pub fn configure_cache(&self, pref_cache_size: usize, max_cache_size: usize) {
self.pref_cache_size.store(pref_cache_size, AtomicOrder::Relaxed);
self.max_cache_size.store(max_cache_size, AtomicOrder::Relaxed);
}
/// Returns a tree route between `from` and `to`, which is a tuple of:
@@ -424,6 +429,7 @@ impl BlockChain {
return ImportRoute::none();
}
let _lock = self.insert_lock.lock();
// store block in db
self.blocks_db.put(&hash, &bytes).unwrap();
@@ -446,48 +452,58 @@ impl BlockChain {
let batch = DBTransaction::new();
batch.put(b"best", &update.info.hash).unwrap();
// update best block
let mut best_block = self.best_block.write().unwrap();
match update.info.location {
BlockLocation::Branch => (),
_ => {
*best_block = BestBlock {
hash: update.info.hash,
number: update.info.number,
total_difficulty: update.info.total_difficulty
};
{
let mut write_details = self.block_details.write().unwrap();
for (hash, details) in update.block_details.into_iter() {
batch.put_extras(&hash, &details);
self.note_used(CacheID::Extras(ExtrasIndex::BlockDetails, hash.clone()));
write_details.insert(hash, details);
}
}
let mut write_hashes = self.block_hashes.write().unwrap();
for (number, hash) in &update.block_hashes {
batch.put_extras(number, hash);
write_hashes.remove(number);
{
let mut write_receipts = self.block_receipts.write().unwrap();
for (hash, receipt) in &update.block_receipts {
batch.put_extras(hash, receipt);
write_receipts.remove(hash);
}
}
let mut write_details = self.block_details.write().unwrap();
for (hash, details) in update.block_details.into_iter() {
batch.put_extras(&hash, &details);
write_details.insert(hash.clone(), details);
self.note_used(CacheID::Extras(ExtrasIndex::BlockDetails, hash));
{
let mut write_blocks_blooms = self.blocks_blooms.write().unwrap();
for (bloom_hash, blocks_bloom) in &update.blocks_blooms {
batch.put_extras(bloom_hash, blocks_bloom);
write_blocks_blooms.remove(bloom_hash);
}
}
let mut write_receipts = self.block_receipts.write().unwrap();
for (hash, receipt) in &update.block_receipts {
batch.put_extras(hash, receipt);
write_receipts.remove(hash);
}
// These cached values must be updated last and togeterh
{
let mut best_block = self.best_block.write().unwrap();
let mut write_hashes = self.block_hashes.write().unwrap();
let mut write_txs = self.transaction_addresses.write().unwrap();
let mut write_txs = self.transaction_addresses.write().unwrap();
for (hash, tx_address) in &update.transactions_addresses {
batch.put_extras(hash, tx_address);
write_txs.remove(hash);
}
// update best block
match update.info.location {
BlockLocation::Branch => (),
_ => {
*best_block = BestBlock {
hash: update.info.hash,
number: update.info.number,
total_difficulty: update.info.total_difficulty
};
}
}
let mut write_blocks_blooms = self.blocks_blooms.write().unwrap();
for (bloom_hash, blocks_bloom) in &update.blocks_blooms {
batch.put_extras(bloom_hash, blocks_bloom);
write_blocks_blooms.remove(bloom_hash);
for (number, hash) in &update.block_hashes {
batch.put_extras(number, hash);
write_hashes.remove(number);
}
for (hash, tx_address) in &update.transactions_addresses {
batch.put_extras(hash, tx_address);
write_txs.remove(hash);
}
}
// update extras database
@@ -781,11 +797,10 @@ impl BlockChain {
/// Ticks our cache system and throws out any old data.
pub fn collect_garbage(&self) {
if self.cache_size().total() < self.pref_cache_size { return; }
if self.cache_size().total() < self.pref_cache_size.load(AtomicOrder::Relaxed) { return; }
for _ in 0..COLLECTION_QUEUE_SIZE {
{
let mut cache_man = self.cache_man.write().unwrap();
let mut blocks = self.blocks.write().unwrap();
let mut block_details = self.block_details.write().unwrap();
let mut block_hashes = self.block_hashes.write().unwrap();
@@ -793,6 +808,7 @@ impl BlockChain {
let mut block_logs = self.block_logs.write().unwrap();
let mut blocks_blooms = self.blocks_blooms.write().unwrap();
let mut block_receipts = self.block_receipts.write().unwrap();
let mut cache_man = self.cache_man.write().unwrap();
for id in cache_man.cache_usage.pop_back().unwrap().into_iter() {
cache_man.in_use.remove(&id);
@@ -819,7 +835,7 @@ impl BlockChain {
blocks_blooms.shrink_to_fit();
block_receipts.shrink_to_fit();
}
if self.cache_size().total() < self.max_cache_size { break; }
if self.cache_size().total() < self.max_cache_size.load(AtomicOrder::Relaxed) { break; }
}
// TODO: m_lastCollection = chrono::system_clock::now();