From 744501c45460098be5ad41d9b7783c84fc92a0d4 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 5 Nov 2016 10:38:00 +0100 Subject: [PATCH] Mode improvements for UI (#3109) * `--mode=off` now works. * Add Mode::Off as a persistent CLI option. * "last" not "auto" as default. * Commit accidentally unsaved file. * Whitespace [ci:skip] * Mode CLI parse fix * or offline * Save mode when it gets changed. * Fix Offline mode * Fix up mode operations. * Make passive default, but not overriding. * Fix test * Maybe not everyone wants to run an archive node... --- ethcore/src/client/client.rs | 40 +++++++++++++++++++++++----- ethcore/src/client/config.rs | 12 +++++++++ ethcore/src/types/mode.rs | 2 +- js/src/jsonrpc/interfaces/ethcore.js | 4 +-- js/src/views/Status/data/rpc.json | 18 +++++++++++++ mac/post-install.sh | 8 +++--- parity/blockchain.rs | 6 ++--- parity/cli/config.full.toml | 2 +- parity/cli/mod.rs | 7 ++--- parity/cli/usage.txt | 6 ++--- parity/configuration.rs | 21 ++------------- parity/helpers.rs | 5 ++-- parity/params.rs | 5 ++++ parity/run.rs | 33 ++++++++++++++++------- parity/snapshot.rs | 3 +-- parity/user_defaults.rs | 38 +++++++++++++++++++++++++- rpc/src/v1/impls/ethcore.rs | 2 +- rpc/src/v1/impls/ethcore_set.rs | 2 +- rpc/src/v1/traits/ethcore.rs | 2 +- rpc/src/v1/traits/ethcore_set.rs | 4 +-- 20 files changed, 154 insertions(+), 66 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 777d561e3..b1a70454d 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -147,6 +147,7 @@ pub struct Client { factories: Factories, history: u64, rng: Mutex, + on_mode_change: Mutex>>, } impl Client { @@ -211,7 +212,7 @@ impl Client { let panic_handler = PanicHandler::new_in_arc(); panic_handler.forward_from(&block_queue); - let awake = match config.mode { Mode::Dark(..) => false, _ => true }; + let awake = match config.mode { Mode::Dark(..) | Mode::Off => false, _ => true }; let factories = Factories { vm: EvmFactory::new(config.vm_type.clone(), config.jump_table_size), @@ -243,6 +244,7 @@ impl Client { factories: factories, history: history, rng: Mutex::new(try!(OsRng::new().map_err(::util::UtilError::StdIo))), + on_mode_change: Mutex::new(None), }; Ok(Arc::new(client)) } @@ -260,6 +262,11 @@ impl Client { } } + /// Register an action to be done if a mode change happens. + pub fn on_mode_change(&self, f: F) where F: 'static + FnMut(&Mode) + Send { + *self.on_mode_change.lock() = Some(Box::new(f)); + } + /// Flush the block import queue. pub fn flush_queue(&self) { self.block_queue.flush(); @@ -856,18 +863,37 @@ impl BlockChainClient for Client { } fn keep_alive(&self) { - let mode = self.mode.lock().clone(); - if mode != Mode::Active { + let should_wake = match &*self.mode.lock() { + &Mode::Dark(..) | &Mode::Passive(..) => true, + _ => false, + }; + if should_wake { self.wake_up(); (*self.sleep_state.lock()).last_activity = Some(Instant::now()); } } - fn mode(&self) -> IpcMode { self.mode.lock().clone().into() } + fn mode(&self) -> IpcMode { + let r = self.mode.lock().clone().into(); + trace!(target: "mode", "Asked for mode = {:?}. returning {:?}", &*self.mode.lock(), r); + r + } - fn set_mode(&self, mode: IpcMode) { - *self.mode.lock() = mode.clone().into(); - match mode { + fn set_mode(&self, new_mode: IpcMode) { + trace!(target: "mode", "Client::set_mode({:?})", new_mode); + { + let mut mode = self.mode.lock(); + *mode = new_mode.clone().into(); + trace!(target: "mode", "Mode now {:?}", &*mode); + match *self.on_mode_change.lock() { + Some(ref mut f) => { + trace!(target: "mode", "Making callback..."); + f(&*mode) + }, + _ => {} + } + } + match new_mode { IpcMode::Active => self.wake_up(), IpcMode::Off => self.sleep(), _ => {(*self.sleep_state.lock()).last_activity = Some(Instant::now()); } diff --git a/ethcore/src/client/config.rs b/ethcore/src/client/config.rs index c4aeba8a4..045b8ee05 100644 --- a/ethcore/src/client/config.rs +++ b/ethcore/src/client/config.rs @@ -16,6 +16,7 @@ use std::str::FromStr; use std::path::Path; +use std::fmt::{Display, Formatter, Error as FmtError}; pub use std::time::Duration; pub use blockchain::Config as BlockChainConfig; pub use trace::Config as TraceConfig; @@ -86,6 +87,17 @@ impl Default for Mode { } } +impl Display for Mode { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { + match *self { + Mode::Active => write!(f, "active"), + Mode::Passive(..) => write!(f, "passive"), + Mode::Dark(..) => write!(f, "dark"), + Mode::Off => write!(f, "offline"), + } + } +} + /// Client configuration. Includes configs for all sub-systems. #[derive(Debug, PartialEq, Default)] pub struct ClientConfig { diff --git a/ethcore/src/types/mode.rs b/ethcore/src/types/mode.rs index b48a92a89..58f652c6c 100644 --- a/ethcore/src/types/mode.rs +++ b/ethcore/src/types/mode.rs @@ -20,7 +20,7 @@ pub use std::time::Duration; use client::Mode as ClientMode; /// IPC-capable shadow-type for client::config::Mode -#[derive(Clone, Binary)] +#[derive(Clone, Binary, Debug)] pub enum Mode { /// Same as ClientMode::Off. Off, diff --git a/js/src/jsonrpc/interfaces/ethcore.js b/js/src/jsonrpc/interfaces/ethcore.js index ce1761382..310276cc8 100644 --- a/js/src/jsonrpc/interfaces/ethcore.js +++ b/js/src/jsonrpc/interfaces/ethcore.js @@ -166,7 +166,7 @@ export default { }, mode: { - desc: 'Get the mode. Results one of: "active", "passive", "dark", "off".', + desc: 'Get the mode. Results one of: "active", "passive", "dark", "offline".', params: [], returns: { type: String, @@ -330,7 +330,7 @@ export default { params: [ { type: String, - desc: 'The mode to set, one of "active", "passive", "dark", "off"' + desc: 'The mode to set, one of "active", "passive", "dark", "offline"' } ], returns: { diff --git a/js/src/views/Status/data/rpc.json b/js/src/views/Status/data/rpc.json index 97c7e4055..ebb2800e8 100644 --- a/js/src/views/Status/data/rpc.json +++ b/js/src/views/Status/data/rpc.json @@ -926,6 +926,16 @@ ], "outputFormatter": null }, + { + "name": "ethcore_setMode", + "desc": "Changes current operating mode", + "params": [ + "`DATA`- Mode name" + ], + "returns": "`Boolean` - whether the call was successful", + "inputFormatters": null, + "outputFormatter": null + }, { "name": "ethcore_setMinGasPrice", "desc": "Changes minimal gas price for transaction to be accepted to the queue.", @@ -1030,6 +1040,14 @@ "inputFormatters": [], "outputFormatter": null }, + { + "name": "ethcore_mode", + "desc": "Returns current mode", + "params": [], + "returns": "`DATA` - Mode", + "inputFormatters": [], + "outputFormatter": null + }, { "name": "trace_filter", "desc": "Returns traces matching given filter", diff --git a/mac/post-install.sh b/mac/post-install.sh index 2a6b7e538..62e011054 100755 --- a/mac/post-install.sh +++ b/mac/post-install.sh @@ -11,8 +11,6 @@ cat > $HOME/Library/LaunchAgents/io.parity.ethereum.plist <ProgramArguments /usr/local/libexec/parity - --mode - passive --warp KeepAlive @@ -26,9 +24,11 @@ cat > $HOME/Library/LaunchAgents/io.parity.ethereum.plist < EOF -mkdir -p $HOME/.parity -chown $USER $HOME/.parity $HOME/Library/LaunchAgents $HOME/Library/LaunchAgents/io.parity.ethereum.plist +mkdir -p $HOME/.parity/906a34e69aec8c0d +echo -n '{"fat_db":false,"mode":"passive","pruning":"fast","tracing":false}' > $HOME/.parity/906a34e69aec8c0d/user_defaults + +chown -R $USER $HOME/.parity $HOME/Library/LaunchAgents $HOME/Library/LaunchAgents/io.parity.ethereum.plist su $USER -c "launchctl load $HOME/Library/LaunchAgents/io.parity.ethereum.plist" sleep 1 diff --git a/parity/blockchain.rs b/parity/blockchain.rs index 8e84c488c..9575b293a 100644 --- a/parity/blockchain.rs +++ b/parity/blockchain.rs @@ -78,7 +78,6 @@ pub struct ImportBlockchain { pub pruning_history: u64, pub compaction: DatabaseCompactionProfile, pub wal: bool, - pub mode: Mode, pub tracing: Switch, pub fat_db: Switch, pub vm_type: VMType, @@ -97,7 +96,6 @@ pub struct ExportBlockchain { pub pruning_history: u64, pub compaction: DatabaseCompactionProfile, pub wal: bool, - pub mode: Mode, pub fat_db: Switch, pub tracing: Switch, pub from_block: BlockID, @@ -155,7 +153,7 @@ fn execute_import(cmd: ImportBlockchain) -> Result { try!(execute_upgrades(&db_dirs, algorithm, cmd.compaction.compaction_profile(db_dirs.fork_path().as_path()))); // prepare client config - let client_config = to_client_config(&cmd.cache_config, cmd.mode, tracing, fat_db, cmd.compaction, cmd.wal, cmd.vm_type, "".into(), algorithm, cmd.pruning_history, cmd.check_seal); + let client_config = to_client_config(&cmd.cache_config, Mode::Active, tracing, fat_db, cmd.compaction, cmd.wal, cmd.vm_type, "".into(), algorithm, cmd.pruning_history, cmd.check_seal); // build client let service = try!(ClientService::start( @@ -303,7 +301,7 @@ fn execute_export(cmd: ExportBlockchain) -> Result { try!(execute_upgrades(&db_dirs, algorithm, cmd.compaction.compaction_profile(db_dirs.fork_path().as_path()))); // prepare client config - let client_config = to_client_config(&cmd.cache_config, cmd.mode, tracing, fat_db, cmd.compaction, cmd.wal, VMType::default(), "".into(), algorithm, cmd.pruning_history, cmd.check_seal); + let client_config = to_client_config(&cmd.cache_config, Mode::Active, tracing, fat_db, cmd.compaction, cmd.wal, VMType::default(), "".into(), algorithm, cmd.pruning_history, cmd.check_seal); let service = try!(ClientService::start( client_config, diff --git a/parity/cli/config.full.toml b/parity/cli/config.full.toml index 088c9d4b7..520adef4b 100644 --- a/parity/cli/config.full.toml +++ b/parity/cli/config.full.toml @@ -1,5 +1,5 @@ [parity] -mode = "active" +mode = "last" mode_timeout = 300 mode_alarm = 3600 chain = "homestead" diff --git a/parity/cli/mod.rs b/parity/cli/mod.rs index c0e7241b0..ad9e8dd8b 100644 --- a/parity/cli/mod.rs +++ b/parity/cli/mod.rs @@ -74,7 +74,7 @@ usage! { } { // -- Operating Options - flag_mode: String = "active", or |c: &Config| otry!(c.parity).mode.clone(), + flag_mode: String = "last", or |c: &Config| otry!(c.parity).mode.clone(), flag_mode_timeout: u64 = 300u64, or |c: &Config| otry!(c.parity).mode_timeout.clone(), flag_mode_alarm: u64 = 3600u64, or |c: &Config| otry!(c.parity).mode_alarm.clone(), flag_chain: String = "homestead", or |c: &Config| otry!(c.parity).chain.clone(), @@ -104,8 +104,6 @@ usage! { flag_signer_no_validation: bool = false, or |_| None, // -- Networking Options - flag_no_network: bool = false, - or |c: &Config| otry!(c.network).disable.clone(), flag_warp: bool = false, or |c: &Config| otry!(c.network).warp.clone(), flag_port: u16 = 30303u16, @@ -500,7 +498,7 @@ mod tests { arg_path: vec![], // -- Operating Options - flag_mode: "active".into(), + flag_mode: "last".into(), flag_mode_timeout: 300u64, flag_mode_alarm: 3600u64, flag_chain: "xyz".into(), @@ -521,7 +519,6 @@ mod tests { flag_signer_no_validation: false, // -- Networking Options - flag_no_network: false, flag_warp: true, flag_port: 30303u16, flag_min_peers: 25u16, diff --git a/parity/cli/usage.txt b/parity/cli/usage.txt index bf7e82561..b8734f7c2 100644 --- a/parity/cli/usage.txt +++ b/parity/cli/usage.txt @@ -18,11 +18,12 @@ Usage: Operating Options: --mode MODE Set the operating mode. MODE can be one of: + last - Uses the last-used mode, active if none. active - Parity continuously syncs the chain. passive - Parity syncs initially, then sleeps and wakes regularly to resync. - dark - Parity syncs only when an external interface - is active. (default: {flag_mode}). + dark - Parity syncs only when the RPC is active. + offline - Parity doesn't sync. (default: {flag_mode}). --mode-timeout SECS Specify the number of seconds before inactivity timeout occurs when mode is dark or passive (default: {flag_mode_timeout}). @@ -66,7 +67,6 @@ Account Options: development. (default: {flag_signer_no_validation}) Networking Options: - --no-network Disable p2p networking. (default: {flag_no_network}) --warp Enable syncing from the snapshot over the network. (default: {flag_warp}) --port PORT Override the port on which the node should listen (default: {flag_port}). diff --git a/parity/configuration.rs b/parity/configuration.rs index 3484f8a4b..b71404339 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -23,7 +23,7 @@ use cli::{Args, ArgsError}; use util::{Hashable, U256, Uint, Bytes, version_data, Secret, Address}; use util::log::Colour; use ethsync::{NetworkConfiguration, is_valid_node_url, AllowIP}; -use ethcore::client::{VMType, Mode}; +use ethcore::client::VMType; use ethcore::miner::{MinerOptions, Banning}; use rpc::{IpcConfiguration, HttpConfiguration}; @@ -80,7 +80,7 @@ impl Configuration { let pruning = try!(self.args.flag_pruning.parse()); let pruning_history = self.args.flag_pruning_history; let vm_type = try!(self.vm_type()); - let mode = try!(to_mode(&self.args.flag_mode, self.args.flag_mode_timeout, self.args.flag_mode_alarm)); + let mode = match self.args.flag_mode.as_ref() { "last" => None, mode => Some(try!(to_mode(&mode, self.args.flag_mode_timeout, self.args.flag_mode_alarm))), }; let miner_options = try!(self.miner_options()); let logger_config = self.logger_config(); let http_conf = try!(self.http_config()); @@ -93,7 +93,6 @@ impl Configuration { let fat_db = try!(self.args.flag_fat_db.parse()); let compaction = try!(self.args.flag_db_compaction.parse()); let wal = !self.args.flag_fast_and_loose; - let enable_network = self.enable_network(&mode); let warp_sync = self.args.flag_warp; let geth_compatibility = self.args.flag_geth; let signer_port = self.signer_port(); @@ -156,7 +155,6 @@ impl Configuration { pruning_history: pruning_history, compaction: compaction, wal: wal, - mode: mode, tracing: tracing, fat_db: fat_db, vm_type: vm_type, @@ -175,7 +173,6 @@ impl Configuration { pruning_history: pruning_history, compaction: compaction, wal: wal, - mode: mode, tracing: tracing, fat_db: fat_db, from_block: try!(to_block_id(&self.args.flag_from)), @@ -190,7 +187,6 @@ impl Configuration { spec: spec, pruning: pruning, pruning_history: pruning_history, - mode: mode, tracing: tracing, fat_db: fat_db, compaction: compaction, @@ -207,7 +203,6 @@ impl Configuration { spec: spec, pruning: pruning, pruning_history: pruning_history, - mode: mode, tracing: tracing, fat_db: fat_db, compaction: compaction, @@ -246,7 +241,6 @@ impl Configuration { compaction: compaction, wal: wal, vm_type: vm_type, - enable_network: enable_network, warp_sync: warp_sync, geth_compatibility: geth_compatibility, signer_port: signer_port, @@ -268,13 +262,6 @@ impl Configuration { }) } - fn enable_network(&self, mode: &Mode) -> bool { - match *mode { - Mode::Dark(_) => false, - _ => !self.args.flag_no_network, - } - } - fn vm_type(&self) -> Result { if self.args.flag_jitvm { VMType::jit().ok_or("Parity is built without the JIT EVM.".into()) @@ -767,7 +754,6 @@ mod tests { pruning_history: 64, compaction: Default::default(), wal: true, - mode: Default::default(), tracing: Default::default(), fat_db: Default::default(), vm_type: VMType::Interpreter, @@ -790,7 +776,6 @@ mod tests { format: Default::default(), compaction: Default::default(), wal: true, - mode: Default::default(), tracing: Default::default(), fat_db: Default::default(), from_block: BlockID::Number(1), @@ -813,7 +798,6 @@ mod tests { format: Some(DataFormat::Hex), compaction: Default::default(), wal: true, - mode: Default::default(), tracing: Default::default(), fat_db: Default::default(), from_block: BlockID::Number(1), @@ -858,7 +842,6 @@ mod tests { compaction: Default::default(), wal: true, vm_type: Default::default(), - enable_network: true, geth_compatibility: false, signer_port: Some(8180), net_settings: Default::default(), diff --git a/parity/helpers.rs b/parity/helpers.rs index 5d6859f5b..761a148e4 100644 --- a/parity/helpers.rs +++ b/parity/helpers.rs @@ -46,7 +46,7 @@ fn to_seconds(s: &str) -> Result { "hourly" | "1hour" | "1 hour" | "hour" => Ok(60 * 60), "daily" | "1day" | "1 day" | "day" => Ok(24 * 60 * 60), x if x.ends_with("seconds") => x[0..x.len() - 7].parse().map_err(bad), - x if x.ends_with("minutes") => x[0..x.len() -7].parse::().map_err(bad).map(|x| x * 60), + x if x.ends_with("minutes") => x[0..x.len() - 7].parse::().map_err(bad).map(|x| x * 60), x if x.ends_with("hours") => x[0..x.len() - 5].parse::().map_err(bad).map(|x| x * 60 * 60), x if x.ends_with("days") => x[0..x.len() - 4].parse::().map_err(bad).map(|x| x * 24 * 60 * 60), x => x.parse().map_err(bad), @@ -58,7 +58,8 @@ pub fn to_mode(s: &str, timeout: u64, alarm: u64) -> Result { "active" => Ok(Mode::Active), "passive" => Ok(Mode::Passive(Duration::from_secs(timeout), Duration::from_secs(alarm))), "dark" => Ok(Mode::Dark(Duration::from_secs(timeout))), - _ => Err(format!("{}: Invalid address for --mode. Must be one of active, passive or dark.", s)), + "offline" => Ok(Mode::Off), + _ => Err(format!("{}: Invalid value for --mode. Must be one of active, passive, dark or offline.", s)), } } diff --git a/parity/params.rs b/parity/params.rs index faba029b2..5a81fba7f 100644 --- a/parity/params.rs +++ b/parity/params.rs @@ -20,6 +20,7 @@ use util::{Address, U256, version_data}; use util::journaldb::Algorithm; use ethcore::spec::Spec; use ethcore::ethereum; +use ethcore::client::Mode; use ethcore::miner::{GasPricer, GasPriceCalibratorOptions}; use user_defaults::UserDefaults; @@ -264,6 +265,10 @@ pub fn fatdb_switch_to_bool(switch: Switch, user_defaults: &UserDefaults, algori result } +pub fn mode_switch_to_bool(switch: Option, user_defaults: &UserDefaults) -> Result { + Ok(switch.unwrap_or(user_defaults.mode.clone())) +} + #[cfg(test)] mod tests { use util::journaldb::Algorithm; diff --git a/parity/run.rs b/parity/run.rs index 9c3b00737..d94eafc55 100644 --- a/parity/run.rs +++ b/parity/run.rs @@ -37,7 +37,7 @@ use dapps::WebappServer; use io_handler::ClientIoHandler; use params::{ SpecType, Pruning, AccountsConfig, GasPricerConfig, MinerExtras, Switch, - tracing_switch_to_bool, fatdb_switch_to_bool, + tracing_switch_to_bool, fatdb_switch_to_bool, mode_switch_to_bool }; use helpers::{to_client_config, execute_upgrades, passwords_from_files}; use dir::Directories; @@ -75,13 +75,12 @@ pub struct RunCmd { pub acc_conf: AccountsConfig, pub gas_pricer: GasPricerConfig, pub miner_extras: MinerExtras, - pub mode: Mode, + pub mode: Option, pub tracing: Switch, pub fat_db: Switch, pub compaction: DatabaseCompactionProfile, pub wal: bool, pub vm_type: VMType, - pub enable_network: bool, pub geth_compatibility: bool, pub signer_port: Option, pub net_settings: NetworkSettings, @@ -137,6 +136,11 @@ pub fn execute(cmd: RunCmd, logger: Arc) -> Result<(), String> { // check if fatdb is on let fat_db = try!(fatdb_switch_to_bool(cmd.fat_db, &user_defaults, algorithm)); + // get the mode + let mode = try!(mode_switch_to_bool(cmd.mode, &user_defaults)); + trace!(target: "mode", "mode is {:?}", mode); + let network_enabled = match &mode { &Mode::Dark(_) | &Mode::Off => false, _ => true, }; + // prepare client and snapshot paths. let client_path = db_dirs.client_path(algorithm); let snapshot_path = db_dirs.snapshot_path(); @@ -162,6 +166,7 @@ pub fn execute(cmd: RunCmd, logger: Arc) -> Result<(), String> { false => "".to_owned(), } ); + info!("Operating mode: {}", Colour::White.bold().paint(format!("{}", mode))); // display warning about using experimental journaldb alorithm if !algorithm.is_stable() { @@ -196,7 +201,7 @@ pub fn execute(cmd: RunCmd, logger: Arc) -> Result<(), String> { // create client config let client_config = to_client_config( &cmd.cache_config, - cmd.mode, + mode, tracing, fat_db, cmd.compaction, @@ -248,7 +253,7 @@ pub fn execute(cmd: RunCmd, logger: Arc) -> Result<(), String> { service.add_notify(chain_notify.clone()); // start network - if cmd.enable_network { + if network_enabled { chain_notify.start(); } @@ -321,6 +326,19 @@ pub fn execute(cmd: RunCmd, logger: Arc) -> Result<(), String> { }); service.register_io_handler(io_handler.clone()).expect("Error registering IO handler"); + // save user defaults + user_defaults.pruning = algorithm; + user_defaults.tracing = tracing; + try!(user_defaults.save(&user_defaults_path)); + + let on_mode_change = move |mode: &Mode| { + user_defaults.mode = mode.clone(); + let _ = user_defaults.save(&user_defaults_path); // discard failures - there's nothing we can do + }; + + // tell client how to save the default mode if it gets changed. + client.on_mode_change(on_mode_change); + // the watcher must be kept alive. let _watcher = match cmd.no_periodic_snapshot { true => None, @@ -347,11 +365,6 @@ pub fn execute(cmd: RunCmd, logger: Arc) -> Result<(), String> { url::open(&format!("http://{}:{}/", cmd.dapps_conf.interface, cmd.dapps_conf.port)); } - // save user defaults - user_defaults.pruning = algorithm; - user_defaults.tracing = tracing; - try!(user_defaults.save(&user_defaults_path)); - // Handle exit wait_for_exit(panic_handler, http_server, ipc_server, dapps_server, signer_server); diff --git a/parity/snapshot.rs b/parity/snapshot.rs index 85e1f90eb..09a180a67 100644 --- a/parity/snapshot.rs +++ b/parity/snapshot.rs @@ -54,7 +54,6 @@ pub struct SnapshotCommand { pub spec: SpecType, pub pruning: Pruning, pub pruning_history: u64, - pub mode: Mode, pub tracing: Switch, pub fat_db: Switch, pub compaction: DatabaseCompactionProfile, @@ -158,7 +157,7 @@ impl SnapshotCommand { try!(execute_upgrades(&db_dirs, algorithm, self.compaction.compaction_profile(db_dirs.fork_path().as_path()))); // prepare client config - let client_config = to_client_config(&self.cache_config, self.mode, tracing, fat_db, self.compaction, self.wal, VMType::default(), "".into(), algorithm, self.pruning_history, true); + let client_config = to_client_config(&self.cache_config, Mode::Active, tracing, fat_db, self.compaction, self.wal, VMType::default(), "".into(), algorithm, self.pruning_history, true); let service = try!(ClientService::start( client_config, diff --git a/parity/user_defaults.rs b/parity/user_defaults.rs index b7fc3d929..a1078b634 100644 --- a/parity/user_defaults.rs +++ b/parity/user_defaults.rs @@ -18,6 +18,7 @@ use std::fs::File; use std::io::Write; use std::path::Path; use std::collections::BTreeMap; +use std::time::Duration; use serde::{Serialize, Serializer, Error, Deserialize, Deserializer}; use serde::de::{Visitor, MapVisitor}; use serde::de::impls::BTreeMapVisitor; @@ -25,12 +26,14 @@ use serde_json::Value; use serde_json::de::from_reader; use serde_json::ser::to_string; use util::journaldb::Algorithm; +use ethcore::client::Mode; pub struct UserDefaults { pub is_first_launch: bool, pub pruning: Algorithm, pub tracing: bool, pub fat_db: bool, + pub mode: Mode, } impl Serialize for UserDefaults { @@ -40,6 +43,21 @@ impl Serialize for UserDefaults { map.insert("pruning".into(), Value::String(self.pruning.as_str().into())); map.insert("tracing".into(), Value::Bool(self.tracing)); map.insert("fat_db".into(), Value::Bool(self.fat_db)); + let mode_str = match self.mode { + Mode::Off => "offline", + Mode::Dark(timeout) => { + map.insert("mode.timeout".into(), Value::U64(timeout.as_secs())); + "dark" + }, + Mode::Passive(timeout, alarm) => { + map.insert("mode.timeout".into(), Value::U64(timeout.as_secs())); + map.insert("mode.alarm".into(), Value::U64(alarm.as_secs())); + "passive" + }, + Mode::Active => "active", + }; + map.insert("mode".into(), Value::String(mode_str.into())); + map.serialize(serializer) } } @@ -67,11 +85,28 @@ impl Visitor for UserDefaultsVisitor { let fat_db: Value = map.remove("fat_db".into()).unwrap_or_else(|| Value::Bool(false)); let fat_db = try!(fat_db.as_bool().ok_or_else(|| Error::custom("invalid fat_db value"))); + let mode: Value = map.remove("mode".into()).unwrap_or_else(|| Value::String("active".to_owned())); + let mode = match try!(mode.as_str().ok_or_else(|| Error::custom("invalid mode value"))) { + "offline" => Mode::Off, + "dark" => { + let timeout = try!(map.remove("mode.timeout".into()).and_then(|v| v.as_u64()).ok_or_else(|| Error::custom("invalid/missing mode.timeout value"))); + Mode::Dark(Duration::from_secs(timeout)) + }, + "passive" => { + let timeout = try!(map.remove("mode.timeout".into()).and_then(|v| v.as_u64()).ok_or_else(|| Error::custom("invalid/missing mode.timeout value"))); + let alarm = try!(map.remove("mode.alarm".into()).and_then(|v| v.as_u64()).ok_or_else(|| Error::custom("invalid/missing mode.alarm value"))); + Mode::Passive(Duration::from_secs(timeout), Duration::from_secs(alarm)) + }, + "active" => Mode::Active, + _ => { return Err(Error::custom("invalid mode value")); }, + }; + let user_defaults = UserDefaults { is_first_launch: false, pruning: pruning, tracing: tracing, fat_db: fat_db, + mode: mode, }; Ok(user_defaults) @@ -85,6 +120,7 @@ impl Default for UserDefaults { pruning: Algorithm::default(), tracing: false, fat_db: false, + mode: Mode::Active, } } } @@ -97,7 +133,7 @@ impl UserDefaults { } } - pub fn save

(self, path: P) -> Result<(), String> where P: AsRef { + pub fn save

(&self, path: P) -> Result<(), String> where P: AsRef { let mut file: File = try!(File::create(path).map_err(|_| "Cannot create user defaults file".to_owned())); file.write_all(to_string(&self).unwrap().as_bytes()).map_err(|_| "Failed to save user defaults".to_owned()) } diff --git a/rpc/src/v1/impls/ethcore.rs b/rpc/src/v1/impls/ethcore.rs index 1130b8fb8..84d159f80 100644 --- a/rpc/src/v1/impls/ethcore.rs +++ b/rpc/src/v1/impls/ethcore.rs @@ -351,7 +351,7 @@ impl Ethcore for EthcoreClient where fn mode(&self) -> Result { Ok(match take_weak!(self.client).mode() { - Mode::Off => "off", + Mode::Off => "offline", Mode::Dark(..) => "dark", Mode::Passive(..) => "passive", Mode::Active => "active", diff --git a/rpc/src/v1/impls/ethcore_set.rs b/rpc/src/v1/impls/ethcore_set.rs index 27464cff3..8889ffa44 100644 --- a/rpc/src/v1/impls/ethcore_set.rs +++ b/rpc/src/v1/impls/ethcore_set.rs @@ -151,7 +151,7 @@ impl EthcoreSet for EthcoreSetClient where fn set_mode(&self, mode: String) -> Result { take_weak!(self.client).set_mode(match mode.as_str() { - "off" => Mode::Off, + "offline" => Mode::Off, "dark" => Mode::Dark(300), "passive" => Mode::Passive(300, 3600), "active" => Mode::Active, diff --git a/rpc/src/v1/traits/ethcore.rs b/rpc/src/v1/traits/ethcore.rs index 8e9f58fb3..b7ef2d151 100644 --- a/rpc/src/v1/traits/ethcore.rs +++ b/rpc/src/v1/traits/ethcore.rs @@ -130,7 +130,7 @@ build_rpc_trait! { #[rpc(name = "ethcore_nextNonce")] fn next_nonce(&self, H160) -> Result; - /// Get the mode. Results one of: "active", "passive", "dark", "off". + /// Get the mode. Results one of: "active", "passive", "dark", "offline". #[rpc(name = "ethcore_mode")] fn mode(&self) -> Result; diff --git a/rpc/src/v1/traits/ethcore_set.rs b/rpc/src/v1/traits/ethcore_set.rs index 9c0d3d5d4..ad31a6e64 100644 --- a/rpc/src/v1/traits/ethcore_set.rs +++ b/rpc/src/v1/traits/ethcore_set.rs @@ -76,11 +76,11 @@ build_rpc_trait! { /// Stop the network. /// - /// Deprecated. Use `set_mode("off")` instead. + /// Deprecated. Use `set_mode("offline")` instead. #[rpc(name = "ethcore_stopNetwork")] fn stop_network(&self) -> Result; - /// Set the mode. Argument must be one of: "active", "passive", "dark", "off". + /// Set the mode. Argument must be one of: "active", "passive", "dark", "offline". #[rpc(name = "ethcore_setMode")] fn set_mode(&self, String) -> Result; }