parent
bd21c6c327
commit
76cded453b
@ -53,7 +53,9 @@ impl IoHandler<NetSyncMessage> for ClientIoHandler {
|
|||||||
|
|
||||||
fn timeout<'s>(&'s mut self, _io: &mut IoContext<'s, NetSyncMessage>, timer: TimerToken) {
|
fn timeout<'s>(&'s mut self, _io: &mut IoContext<'s, NetSyncMessage>, timer: TimerToken) {
|
||||||
if self.timer == timer {
|
if self.timer == timer {
|
||||||
println!("Chain info: {:?}", self.client.read().unwrap().deref().chain_info());
|
self.client.tick();
|
||||||
|
println!("Chain info: {}", self.client.read().unwrap().deref().chain_info());
|
||||||
|
println!("Cache info: {:?}", self.client.read().unwrap().deref().cache_info());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,11 @@ pub struct CacheSize {
|
|||||||
pub blocks_blooms: usize
|
pub blocks_blooms: usize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CacheSize {
|
||||||
|
/// Total amount used by the cache.
|
||||||
|
fn total(&self) -> usize { self.blocks + self.block_details + self.transaction_addresses + self.block_logs + self.blocks_blooms }
|
||||||
|
}
|
||||||
|
|
||||||
/// Information about best block gathered together
|
/// Information about best block gathered together
|
||||||
struct BestBlock {
|
struct BestBlock {
|
||||||
pub hash: H256,
|
pub hash: H256,
|
||||||
@ -97,9 +102,9 @@ pub trait BlockProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Hash, Eq, PartialEq, Clone)]
|
#[derive(Debug, Hash, Eq, PartialEq, Clone)]
|
||||||
struct CacheID {
|
enum CacheID {
|
||||||
id: H256,
|
Block(H256),
|
||||||
extra: usize
|
Extras(ExtrasIndex, H256),
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CacheManager {
|
struct CacheManager {
|
||||||
@ -149,6 +154,8 @@ impl BlockProvider for BlockChain {
|
|||||||
let opt = self.blocks_db.get(hash)
|
let opt = self.blocks_db.get(hash)
|
||||||
.expect("Low level database error. Some issue with disk?");
|
.expect("Low level database error. Some issue with disk?");
|
||||||
|
|
||||||
|
self.note_used(CacheID::Block(hash.clone()));
|
||||||
|
|
||||||
match opt {
|
match opt {
|
||||||
Some(b) => {
|
Some(b) => {
|
||||||
let bytes: Bytes = b.to_vec();
|
let bytes: Bytes = b.to_vec();
|
||||||
@ -214,6 +221,9 @@ impl BlockChain {
|
|||||||
blocks_path.push("blocks");
|
blocks_path.push("blocks");
|
||||||
let blocks_db = DB::open_default(blocks_path.to_str().unwrap()).unwrap();
|
let blocks_db = DB::open_default(blocks_path.to_str().unwrap()).unwrap();
|
||||||
|
|
||||||
|
let mut cache_man = CacheManager{cache_usage: VecDeque::new(), in_use: HashSet::new()};
|
||||||
|
(0..COLLECTION_QUEUE_SIZE).foreach(|_| cache_man.cache_usage.push_back(HashSet::new()));
|
||||||
|
|
||||||
let bc = BlockChain {
|
let bc = BlockChain {
|
||||||
best_block: RwLock::new(BestBlock::new()),
|
best_block: RwLock::new(BestBlock::new()),
|
||||||
blocks: RwLock::new(HashMap::new()),
|
blocks: RwLock::new(HashMap::new()),
|
||||||
@ -224,7 +234,7 @@ impl BlockChain {
|
|||||||
blocks_blooms: RwLock::new(HashMap::new()),
|
blocks_blooms: RwLock::new(HashMap::new()),
|
||||||
extras_db: extras_db,
|
extras_db: extras_db,
|
||||||
blocks_db: blocks_db,
|
blocks_db: blocks_db,
|
||||||
cache_man: RwLock::new(CacheManager{cache_usage: VecDeque::new(), in_use: HashSet::new()}),
|
cache_man: RwLock::new(cache_man),
|
||||||
};
|
};
|
||||||
|
|
||||||
// load best block
|
// load best block
|
||||||
@ -515,6 +525,10 @@ impl BlockChain {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(h) = hash.as_h256() {
|
||||||
|
self.note_used(CacheID::Extras(T::extras_index(), h.clone()));
|
||||||
|
}
|
||||||
|
|
||||||
self.extras_db.get_extras(hash).map(| t: T | {
|
self.extras_db.get_extras(hash).map(| t: T | {
|
||||||
let mut write = cache.write().unwrap();
|
let mut write = cache.write().unwrap();
|
||||||
write.insert(hash.clone(), t.clone());
|
write.insert(hash.clone(), t.clone());
|
||||||
@ -556,21 +570,54 @@ impl BlockChain {
|
|||||||
self.blocks_blooms.write().unwrap().squeeze(size.blocks_blooms);
|
self.blocks_blooms.write().unwrap().squeeze(size.blocks_blooms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Let the cache system know that a cacheable item has been used.
|
||||||
fn note_used(&self, id: CacheID) {
|
fn note_used(&self, id: CacheID) {
|
||||||
let mut cache_man = self.cache_man.write().unwrap();
|
let mut cache_man = self.cache_man.write().unwrap();
|
||||||
|
if !cache_man.cache_usage[0].contains(&id) {
|
||||||
cache_man.cache_usage[0].insert(id.clone());
|
cache_man.cache_usage[0].insert(id.clone());
|
||||||
// TODO: check more than just the first?
|
if cache_man.in_use.contains(&id) {
|
||||||
if cache_man.cache_usage[1].contains(&id) {
|
if let Some(c) = cache_man.cache_usage.iter_mut().skip(1).find(|e|e.contains(&id)) {
|
||||||
cache_man.cache_usage[1].remove(&id);
|
c.remove(&id);
|
||||||
}
|
}
|
||||||
else {
|
} else {
|
||||||
cache_man.in_use.insert(id);
|
cache_man.in_use.insert(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Ticks our cache system and throws out any old data.
|
/// Ticks our cache system and throws out any old data.
|
||||||
pub fn tick(&self) {
|
pub fn collect_garbage(&self, force: bool) {
|
||||||
|
// TODO: check time.
|
||||||
|
let timeout = true;
|
||||||
|
|
||||||
|
let t = self.cache_size().total();
|
||||||
|
if t < MIN_CACHE_SIZE || (!timeout && (!force || t < MAX_CACHE_SIZE)) { return; }
|
||||||
|
|
||||||
|
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();
|
||||||
|
let mut transaction_addresses = self.transaction_addresses.write().unwrap();
|
||||||
|
let mut block_logs = self.block_logs.write().unwrap();
|
||||||
|
let mut blocks_blooms = self.blocks_blooms.write().unwrap();
|
||||||
|
|
||||||
|
for id in cache_man.cache_usage.pop_back().unwrap().into_iter() {
|
||||||
|
cache_man.in_use.remove(&id);
|
||||||
|
match id {
|
||||||
|
CacheID::Block(h) => { blocks.remove(&h); },
|
||||||
|
CacheID::Extras(ExtrasIndex::BlockDetails, h) => { block_details.remove(&h); },
|
||||||
|
CacheID::Extras(ExtrasIndex::TransactionAddress, h) => { transaction_addresses.remove(&h); },
|
||||||
|
CacheID::Extras(ExtrasIndex::BlockLogBlooms, h) => { block_logs.remove(&h); },
|
||||||
|
CacheID::Extras(ExtrasIndex::BlocksBlooms, h) => { blocks_blooms.remove(&h); },
|
||||||
|
_ => panic!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cache_man.cache_usage.push_front(HashSet::new());
|
||||||
|
|
||||||
|
// TODO: handle block_hashes properly.
|
||||||
|
block_hashes.clear();
|
||||||
|
|
||||||
|
// TODO: m_lastCollection = chrono::system_clock::now();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use util::*;
|
use util::*;
|
||||||
use rocksdb::{Options, DB};
|
use rocksdb::{Options, DB};
|
||||||
use blockchain::{BlockChain, BlockProvider};
|
use blockchain::{BlockChain, BlockProvider, CacheSize};
|
||||||
use views::BlockView;
|
use views::BlockView;
|
||||||
use error::*;
|
use error::*;
|
||||||
use header::BlockNumber;
|
use header::BlockNumber;
|
||||||
@ -40,6 +40,12 @@ pub struct BlockChainInfo {
|
|||||||
pub best_block_number: BlockNumber
|
pub best_block_number: BlockNumber
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for BlockChainInfo {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "#{}.{}", self.best_block_number, self.best_block_hash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Block queue status
|
/// Block queue status
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct BlockQueueStatus {
|
pub struct BlockQueueStatus {
|
||||||
@ -208,6 +214,16 @@ impl Client {
|
|||||||
}
|
}
|
||||||
debug!(target: "client", "Imported #{} ({})", header.number(), header.hash());
|
debug!(target: "client", "Imported #{} ({})", header.number(), header.hash());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get info on the cache.
|
||||||
|
pub fn cache_info(&self) -> CacheSize {
|
||||||
|
self.chain.read().unwrap().cache_size()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Tick the client.
|
||||||
|
pub fn tick(&self) {
|
||||||
|
self.chain.read().unwrap().collect_garbage(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BlockChainClient for Client {
|
impl BlockChainClient for Client {
|
||||||
|
@ -3,7 +3,7 @@ use header::BlockNumber;
|
|||||||
use rocksdb::{DB, Writable};
|
use rocksdb::{DB, Writable};
|
||||||
|
|
||||||
/// Represents index of extra data in database
|
/// Represents index of extra data in database
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)]
|
||||||
pub enum ExtrasIndex {
|
pub enum ExtrasIndex {
|
||||||
BlockDetails = 0,
|
BlockDetails = 0,
|
||||||
BlockHash = 1,
|
BlockHash = 1,
|
||||||
@ -59,6 +59,7 @@ impl ExtrasReadable for DB {
|
|||||||
/// Implementations should convert arbitrary type to database key slice
|
/// Implementations should convert arbitrary type to database key slice
|
||||||
pub trait ExtrasSliceConvertable {
|
pub trait ExtrasSliceConvertable {
|
||||||
fn to_extras_slice(&self, i: ExtrasIndex) -> H264;
|
fn to_extras_slice(&self, i: ExtrasIndex) -> H264;
|
||||||
|
fn as_h256(&self) -> Option<&H256> { None }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExtrasSliceConvertable for H256 {
|
impl ExtrasSliceConvertable for H256 {
|
||||||
@ -67,6 +68,7 @@ impl ExtrasSliceConvertable for H256 {
|
|||||||
slice[32] = i as u8;
|
slice[32] = i as u8;
|
||||||
slice
|
slice
|
||||||
}
|
}
|
||||||
|
fn as_h256(&self) -> Option<&H256> { Some(self) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExtrasSliceConvertable for U256 {
|
impl ExtrasSliceConvertable for U256 {
|
||||||
|
Loading…
Reference in New Issue
Block a user