Display progress when importing (#1136)
* Display progress when importing * Additional polish. * Fix strange yielding behaviour. * Allow colour to be disabled. Fixed #1135
This commit is contained in:
parent
1741597a20
commit
a0bc1f9dae
@ -186,6 +186,7 @@ Legacy Options:
|
|||||||
Miscellaneous Options:
|
Miscellaneous Options:
|
||||||
-l --logging LOGGING Specify the logging level. Must conform to the same
|
-l --logging LOGGING Specify the logging level. Must conform to the same
|
||||||
format as RUST_LOG.
|
format as RUST_LOG.
|
||||||
|
--no-color Don't use terminal color codes in output.
|
||||||
-v --version Show information about version.
|
-v --version Show information about version.
|
||||||
-h --help Show this screen.
|
-h --help Show this screen.
|
||||||
"#;
|
"#;
|
||||||
@ -247,6 +248,7 @@ pub struct Args {
|
|||||||
pub flag_to: String,
|
pub flag_to: String,
|
||||||
pub flag_format: Option<String>,
|
pub flag_format: Option<String>,
|
||||||
pub flag_jitvm: bool,
|
pub flag_jitvm: bool,
|
||||||
|
pub flag_no_color: bool,
|
||||||
// legacy...
|
// legacy...
|
||||||
pub flag_geth: bool,
|
pub flag_geth: bool,
|
||||||
pub flag_nodekey: Option<String>,
|
pub flag_nodekey: Option<String>,
|
||||||
|
@ -15,10 +15,12 @@
|
|||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
extern crate ansi_term;
|
extern crate ansi_term;
|
||||||
|
use self::ansi_term::Colour::{White, Yellow, Green, Cyan, Blue, Purple};
|
||||||
|
use self::ansi_term::Style;
|
||||||
|
|
||||||
|
use std::time::{Instant, Duration};
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use ansi_term::Colour::*;
|
|
||||||
use ethsync::{EthSync, SyncProvider};
|
use ethsync::{EthSync, SyncProvider};
|
||||||
use util::Uint;
|
use util::Uint;
|
||||||
use ethcore::client::*;
|
use ethcore::client::*;
|
||||||
@ -28,6 +30,8 @@ pub struct Informant {
|
|||||||
chain_info: RwLock<Option<BlockChainInfo>>,
|
chain_info: RwLock<Option<BlockChainInfo>>,
|
||||||
cache_info: RwLock<Option<BlockChainCacheSize>>,
|
cache_info: RwLock<Option<BlockChainCacheSize>>,
|
||||||
report: RwLock<Option<ClientReport>>,
|
report: RwLock<Option<ClientReport>>,
|
||||||
|
last_tick: RwLock<Instant>,
|
||||||
|
with_color: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Informant {
|
impl Default for Informant {
|
||||||
@ -36,11 +40,34 @@ impl Default for Informant {
|
|||||||
chain_info: RwLock::new(None),
|
chain_info: RwLock::new(None),
|
||||||
cache_info: RwLock::new(None),
|
cache_info: RwLock::new(None),
|
||||||
report: RwLock::new(None),
|
report: RwLock::new(None),
|
||||||
|
last_tick: RwLock::new(Instant::now()),
|
||||||
|
with_color: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait MillisecondDuration {
|
||||||
|
fn as_milliseconds(&self) -> u64;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MillisecondDuration for Duration {
|
||||||
|
fn as_milliseconds(&self) -> u64 {
|
||||||
|
self.as_secs() * 1000 + self.subsec_nanos() as u64 / 1000000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Informant {
|
impl Informant {
|
||||||
|
/// Make a new instance potentially `with_color` output.
|
||||||
|
pub fn new(with_color: bool) -> Self {
|
||||||
|
Informant {
|
||||||
|
chain_info: RwLock::new(None),
|
||||||
|
cache_info: RwLock::new(None),
|
||||||
|
report: RwLock::new(None),
|
||||||
|
last_tick: RwLock::new(Instant::now()),
|
||||||
|
with_color: with_color,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn format_bytes(b: usize) -> String {
|
fn format_bytes(b: usize) -> String {
|
||||||
match binary_prefix(b as f64) {
|
match binary_prefix(b as f64) {
|
||||||
Standalone(bytes) => format!("{} bytes", bytes),
|
Standalone(bytes) => format!("{} bytes", bytes),
|
||||||
@ -48,42 +75,64 @@ impl Informant {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tick(&self, client: &Client, sync: &EthSync) {
|
pub fn tick(&self, client: &Client, maybe_sync: Option<&EthSync>) {
|
||||||
// 5 seconds betwen calls. TODO: calculate this properly.
|
let elapsed = self.last_tick.read().unwrap().elapsed();
|
||||||
let dur = 5usize;
|
if elapsed < Duration::from_secs(5) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*self.last_tick.write().unwrap() = Instant::now();
|
||||||
|
|
||||||
let chain_info = client.chain_info();
|
let chain_info = client.chain_info();
|
||||||
let queue_info = client.queue_info();
|
let queue_info = client.queue_info();
|
||||||
let cache_info = client.blockchain_cache_info();
|
let cache_info = client.blockchain_cache_info();
|
||||||
let sync_info = sync.status();
|
|
||||||
|
|
||||||
let mut write_report = self.report.write().unwrap();
|
let mut write_report = self.report.write().unwrap();
|
||||||
let report = client.report();
|
let report = client.report();
|
||||||
|
|
||||||
|
let paint = |c: Style, t: String| match self.with_color {
|
||||||
|
true => format!("{}", c.paint(t)),
|
||||||
|
false => t,
|
||||||
|
};
|
||||||
|
|
||||||
if let (_, _, &Some(ref last_report)) = (
|
if let (_, _, &Some(ref last_report)) = (
|
||||||
self.chain_info.read().unwrap().deref(),
|
self.chain_info.read().unwrap().deref(),
|
||||||
self.cache_info.read().unwrap().deref(),
|
self.cache_info.read().unwrap().deref(),
|
||||||
write_report.deref()
|
write_report.deref()
|
||||||
) {
|
) {
|
||||||
println!("#{} {} {} blk/s {} tx/s {} Kgas/s {}/{} peers #{} {}+{} Qed {} db {} chain {} queue {} sync",
|
println!("{} {} {} blk/s {} tx/s {} Mgas/s {}{}+{} Qed {} db {} chain {} queue{}",
|
||||||
White.bold().paint(format!("{:<7}", chain_info.best_block_number)),
|
paint(White.bold(), format!("{:>8}", format!("#{}", chain_info.best_block_number))),
|
||||||
White.bold().paint(format!("{}", chain_info.best_block_hash)),
|
paint(White.bold(), format!("{}", chain_info.best_block_hash)),
|
||||||
|
|
||||||
Yellow.bold().paint(format!("{:3}", (report.blocks_imported - last_report.blocks_imported) / dur)),
|
paint(Yellow.bold(), format!("{:4}", ((report.blocks_imported - last_report.blocks_imported) * 1000) as u64 / elapsed.as_milliseconds())),
|
||||||
Yellow.bold().paint(format!("{:3}", (report.transactions_applied - last_report.transactions_applied) / dur)),
|
paint(Yellow.bold(), format!("{:4}", ((report.transactions_applied - last_report.transactions_applied) * 1000) as u64 / elapsed.as_milliseconds())),
|
||||||
Yellow.bold().paint(format!("{:4}", ((report.gas_processed - last_report.gas_processed) / From::from(dur * 1000)).low_u64())),
|
paint(Yellow.bold(), format!("{:3}", ((report.gas_processed - last_report.gas_processed) / From::from(elapsed.as_milliseconds() * 1000)).low_u64())),
|
||||||
|
|
||||||
Green.bold().paint(format!("{:2}", sync_info.num_active_peers)),
|
match maybe_sync {
|
||||||
Green.bold().paint(format!("{:2}", sync_info.num_peers)),
|
Some(sync) => {
|
||||||
|
let sync_info = sync.status();
|
||||||
|
format!("{}/{} peers {} ",
|
||||||
|
paint(Green.bold(), format!("{:2}", sync_info.num_active_peers)),
|
||||||
|
paint(Green.bold(), format!("{:2}", sync_info.num_peers)),
|
||||||
|
paint(Cyan.bold(), format!("{:>8}", format!("#{}", sync_info.last_imported_block_number.unwrap_or(chain_info.best_block_number)))),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
None => String::new()
|
||||||
|
},
|
||||||
|
|
||||||
Cyan.bold().paint(format!("{:<7}", sync_info.last_imported_block_number.unwrap_or(chain_info.best_block_number))),
|
paint(Blue.bold(), format!("{:5}", queue_info.unverified_queue_size)),
|
||||||
Blue.bold().paint(format!("{:4}", queue_info.unverified_queue_size)),
|
paint(Blue.bold(), format!("{:5}", queue_info.verified_queue_size)),
|
||||||
Blue.bold().paint(format!("{:4}", queue_info.verified_queue_size)),
|
|
||||||
|
|
||||||
Purple.bold().paint(format!("{:>8}", Informant::format_bytes(report.state_db_mem))),
|
paint(Purple.bold(), format!("{:>8}", Informant::format_bytes(report.state_db_mem))),
|
||||||
Purple.bold().paint(format!("{:>8}", Informant::format_bytes(cache_info.total()))),
|
paint(Purple.bold(), format!("{:>8}", Informant::format_bytes(cache_info.total()))),
|
||||||
Purple.bold().paint(format!("{:>8}", Informant::format_bytes(queue_info.mem_used))),
|
paint(Purple.bold(), format!("{:>8}", Informant::format_bytes(queue_info.mem_used))),
|
||||||
Purple.bold().paint(format!("{:>8}", Informant::format_bytes(sync_info.mem_used))),
|
match maybe_sync {
|
||||||
|
Some(sync) => {
|
||||||
|
let sync_info = sync.status();
|
||||||
|
format!(" {} sync", paint(Purple.bold(), format!("{:>8}", Informant::format_bytes(sync_info.mem_used))))
|
||||||
|
}
|
||||||
|
None => String::new()
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,12 +39,11 @@ impl IoHandler<NetSyncMessage> for ClientIoHandler {
|
|||||||
fn initialize(&self, io: &IoContext<NetSyncMessage>) {
|
fn initialize(&self, io: &IoContext<NetSyncMessage>) {
|
||||||
io.register_timer(INFO_TIMER, 5000).expect("Error registering timer");
|
io.register_timer(INFO_TIMER, 5000).expect("Error registering timer");
|
||||||
io.register_timer(ACCOUNT_TICK_TIMER, ACCOUNT_TICK_MS).expect("Error registering account timer");
|
io.register_timer(ACCOUNT_TICK_TIMER, ACCOUNT_TICK_MS).expect("Error registering account timer");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn timeout(&self, _io: &IoContext<NetSyncMessage>, timer: TimerToken) {
|
fn timeout(&self, _io: &IoContext<NetSyncMessage>, timer: TimerToken) {
|
||||||
match timer {
|
match timer {
|
||||||
INFO_TIMER => { self.info.tick(&self.client, &self.sync); }
|
INFO_TIMER => { self.info.tick(&self.client, Some(&self.sync)); }
|
||||||
ACCOUNT_TICK_TIMER => { self.accounts.tick(); },
|
ACCOUNT_TICK_TIMER => { self.accounts.tick(); },
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,6 @@
|
|||||||
#![cfg_attr(feature="dev", allow(useless_format))]
|
#![cfg_attr(feature="dev", allow(useless_format))]
|
||||||
|
|
||||||
extern crate docopt;
|
extern crate docopt;
|
||||||
extern crate ansi_term;
|
|
||||||
extern crate num_cpus;
|
extern crate num_cpus;
|
||||||
extern crate rustc_serialize;
|
extern crate rustc_serialize;
|
||||||
extern crate ethcore_util as util;
|
extern crate ethcore_util as util;
|
||||||
@ -66,8 +65,9 @@ mod configuration;
|
|||||||
|
|
||||||
use ctrlc::CtrlC;
|
use ctrlc::CtrlC;
|
||||||
use util::*;
|
use util::*;
|
||||||
|
use std::time::Duration;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::thread::yield_now;
|
use std::thread::sleep;
|
||||||
use std::io::{BufReader, BufRead};
|
use std::io::{BufReader, BufRead};
|
||||||
use util::panics::{MayPanic, ForwardPanic, PanicHandler};
|
use util::panics::{MayPanic, ForwardPanic, PanicHandler};
|
||||||
use ethcore::client::{BlockID, BlockChainClient};
|
use ethcore::client::{BlockID, BlockChainClient};
|
||||||
@ -76,6 +76,7 @@ use ethcore::service::ClientService;
|
|||||||
use ethsync::EthSync;
|
use ethsync::EthSync;
|
||||||
use ethminer::{Miner, MinerService, ExternalMiner};
|
use ethminer::{Miner, MinerService, ExternalMiner};
|
||||||
use daemonize::Daemonize;
|
use daemonize::Daemonize;
|
||||||
|
use informant::Informant;
|
||||||
|
|
||||||
use die::*;
|
use die::*;
|
||||||
use cli::print_version;
|
use cli::print_version;
|
||||||
@ -218,7 +219,7 @@ fn execute_client(conf: Configuration) {
|
|||||||
// Register IO handler
|
// Register IO handler
|
||||||
let io_handler = Arc::new(ClientIoHandler {
|
let io_handler = Arc::new(ClientIoHandler {
|
||||||
client: service.client(),
|
client: service.client(),
|
||||||
info: Default::default(),
|
info: Informant::new(!conf.args.flag_no_color),
|
||||||
sync: sync.clone(),
|
sync: sync.clone(),
|
||||||
accounts: account_service.clone(),
|
accounts: account_service.clone(),
|
||||||
});
|
});
|
||||||
@ -370,13 +371,16 @@ fn execute_import(conf: Configuration) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let informant = Informant::new(!conf.args.flag_no_color);
|
||||||
|
|
||||||
let do_import = |bytes| {
|
let do_import = |bytes| {
|
||||||
while client.queue_info().is_full() { yield_now(); }
|
while client.queue_info().is_full() { sleep(Duration::from_secs(1)); }
|
||||||
match client.import_block(bytes) {
|
match client.import_block(bytes) {
|
||||||
Ok(_) => { println!("Block imported ok"); }
|
Ok(_) => {}
|
||||||
Err(Error::Import(ImportError::AlreadyInChain)) => { trace!("Skipping block already in chain."); }
|
Err(Error::Import(ImportError::AlreadyInChain)) => { trace!("Skipping block already in chain."); }
|
||||||
Err(e) => die!("Cannot import block: {:?}", e)
|
Err(e) => die!("Cannot import block: {:?}", e)
|
||||||
}
|
}
|
||||||
|
informant.tick(client.deref(), None);
|
||||||
};
|
};
|
||||||
|
|
||||||
match format {
|
match format {
|
||||||
|
Loading…
Reference in New Issue
Block a user