user defaults (#2014)
* user defaults * finished user defaults * user defaults are network-dependent * added tests for newly added functions, logger is initialized first * dir cleanup in progress * user_file is placed next to snapshots
This commit is contained in:
@@ -26,15 +26,16 @@ use io::{PanicHandler, ForwardPanic};
|
||||
use util::{ToPretty, Uint};
|
||||
use rlp::PayloadInfo;
|
||||
use ethcore::service::ClientService;
|
||||
use ethcore::client::{Mode, DatabaseCompactionProfile, Switch, VMType, BlockImportError, BlockChainClient, BlockID};
|
||||
use ethcore::client::{Mode, DatabaseCompactionProfile, VMType, BlockImportError, BlockChainClient, BlockID};
|
||||
use ethcore::error::ImportError;
|
||||
use ethcore::miner::Miner;
|
||||
use cache::CacheConfig;
|
||||
use params::{SpecType, Pruning, Switch, tracing_switch_to_bool};
|
||||
use informant::{Informant, MillisecondDuration};
|
||||
use io_handler::ImportIoHandler;
|
||||
use params::{SpecType, Pruning};
|
||||
use helpers::{to_client_config, execute_upgrades};
|
||||
use dir::Directories;
|
||||
use user_defaults::UserDefaults;
|
||||
use fdlimit;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
@@ -113,29 +114,44 @@ fn execute_import(cmd: ImportBlockchain) -> Result<String, String> {
|
||||
// Setup panic handler
|
||||
let panic_handler = PanicHandler::new_in_arc();
|
||||
|
||||
// Setup logging
|
||||
let _logger = setup_log(&cmd.logger_config);
|
||||
|
||||
// create dirs used by parity
|
||||
try!(cmd.dirs.create_dirs());
|
||||
|
||||
// load spec file
|
||||
let spec = try!(cmd.spec.spec());
|
||||
|
||||
// load genesis hash
|
||||
let genesis_hash = spec.genesis_header().hash();
|
||||
|
||||
// Setup logging
|
||||
let _logger = setup_log(&cmd.logger_config);
|
||||
// database paths
|
||||
let db_dirs = cmd.dirs.database(genesis_hash, spec.fork_name.clone());
|
||||
|
||||
// user defaults path
|
||||
let user_defaults_path = db_dirs.user_defaults_path();
|
||||
|
||||
// load user defaults
|
||||
let mut user_defaults = try!(UserDefaults::load(&user_defaults_path));
|
||||
|
||||
// check if tracing is on
|
||||
let tracing = try!(tracing_switch_to_bool(cmd.tracing, &user_defaults));
|
||||
|
||||
fdlimit::raise_fd_limit();
|
||||
|
||||
// select pruning algorithm
|
||||
let algorithm = cmd.pruning.to_algorithm(&cmd.dirs, genesis_hash, spec.fork_name.as_ref());
|
||||
let algorithm = cmd.pruning.to_algorithm(&user_defaults);
|
||||
|
||||
// prepare client and snapshot paths.
|
||||
let client_path = cmd.dirs.client_path(genesis_hash, spec.fork_name.as_ref(), algorithm);
|
||||
let snapshot_path = cmd.dirs.snapshot_path(genesis_hash, spec.fork_name.as_ref());
|
||||
let client_path = db_dirs.client_path(algorithm);
|
||||
let snapshot_path = db_dirs.snapshot_path();
|
||||
|
||||
// execute upgrades
|
||||
try!(execute_upgrades(&cmd.dirs, genesis_hash, spec.fork_name.as_ref(), algorithm, cmd.compaction.compaction_profile()));
|
||||
try!(execute_upgrades(&db_dirs, algorithm, cmd.compaction.compaction_profile()));
|
||||
|
||||
// prepare client config
|
||||
let client_config = to_client_config(&cmd.cache_config, &cmd.dirs, genesis_hash, cmd.mode, cmd.tracing, cmd.pruning, cmd.compaction, cmd.wal, cmd.vm_type, "".into(), spec.fork_name.as_ref());
|
||||
let client_config = to_client_config(&cmd.cache_config, cmd.mode, tracing, cmd.compaction, cmd.wal, cmd.vm_type, "".into(), algorithm);
|
||||
|
||||
// build client
|
||||
let service = try!(ClientService::start(
|
||||
@@ -220,6 +236,12 @@ fn execute_import(cmd: ImportBlockchain) -> Result<String, String> {
|
||||
}
|
||||
}
|
||||
client.flush_queue();
|
||||
|
||||
// save user defaults
|
||||
user_defaults.pruning = algorithm;
|
||||
user_defaults.tracing = tracing;
|
||||
try!(user_defaults.save(&user_defaults_path));
|
||||
|
||||
let report = client.report();
|
||||
|
||||
let ms = timer.elapsed().as_milliseconds();
|
||||
@@ -238,6 +260,12 @@ fn execute_export(cmd: ExportBlockchain) -> Result<String, String> {
|
||||
// Setup panic handler
|
||||
let panic_handler = PanicHandler::new_in_arc();
|
||||
|
||||
// Setup logging
|
||||
let _logger = setup_log(&cmd.logger_config);
|
||||
|
||||
// create dirs used by parity
|
||||
try!(cmd.dirs.create_dirs());
|
||||
|
||||
let format = cmd.format.unwrap_or_default();
|
||||
|
||||
// load spec file
|
||||
@@ -246,23 +274,32 @@ fn execute_export(cmd: ExportBlockchain) -> Result<String, String> {
|
||||
// load genesis hash
|
||||
let genesis_hash = spec.genesis_header().hash();
|
||||
|
||||
// Setup logging
|
||||
let _logger = setup_log(&cmd.logger_config);
|
||||
// database paths
|
||||
let db_dirs = cmd.dirs.database(genesis_hash, spec.fork_name.clone());
|
||||
|
||||
// user defaults path
|
||||
let user_defaults_path = db_dirs.user_defaults_path();
|
||||
|
||||
// load user defaults
|
||||
let user_defaults = try!(UserDefaults::load(&user_defaults_path));
|
||||
|
||||
// check if tracing is on
|
||||
let tracing = try!(tracing_switch_to_bool(cmd.tracing, &user_defaults));
|
||||
|
||||
fdlimit::raise_fd_limit();
|
||||
|
||||
// select pruning algorithm
|
||||
let algorithm = cmd.pruning.to_algorithm(&cmd.dirs, genesis_hash, spec.fork_name.as_ref());
|
||||
let algorithm = cmd.pruning.to_algorithm(&user_defaults);
|
||||
|
||||
// prepare client and snapshot paths.
|
||||
let client_path = cmd.dirs.client_path(genesis_hash, spec.fork_name.as_ref(), algorithm);
|
||||
let snapshot_path = cmd.dirs.snapshot_path(genesis_hash, spec.fork_name.as_ref());
|
||||
let client_path = db_dirs.client_path(algorithm);
|
||||
let snapshot_path = db_dirs.snapshot_path();
|
||||
|
||||
// execute upgrades
|
||||
try!(execute_upgrades(&cmd.dirs, genesis_hash, spec.fork_name.as_ref(), algorithm, cmd.compaction.compaction_profile()));
|
||||
try!(execute_upgrades(&db_dirs, algorithm, cmd.compaction.compaction_profile()));
|
||||
|
||||
// prepare client config
|
||||
let client_config = to_client_config(&cmd.cache_config, &cmd.dirs, genesis_hash, cmd.mode, cmd.tracing, cmd.pruning, cmd.compaction, cmd.wal, VMType::default(), "".into(), spec.fork_name.as_ref());
|
||||
let client_config = to_client_config(&cmd.cache_config, cmd.mode, tracing, cmd.compaction, cmd.wal, VMType::default(), "".into(), algorithm);
|
||||
|
||||
let service = try!(ClientService::start(
|
||||
client_config,
|
||||
|
||||
@@ -52,32 +52,13 @@ impl Directories {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get the chain's root path.
|
||||
pub fn chain_path(&self, genesis_hash: H256, fork_name: Option<&String>) -> PathBuf {
|
||||
let mut dir = Path::new(&self.db).to_path_buf();
|
||||
dir.push(format!("{:?}{}", H64::from(genesis_hash), fork_name.map(|f| format!("-{}", f)).unwrap_or_default()));
|
||||
dir
|
||||
}
|
||||
|
||||
/// Get the root path for database
|
||||
pub fn db_version_path(&self, genesis_hash: H256, fork_name: Option<&String>, pruning: Algorithm) -> PathBuf {
|
||||
let mut dir = self.chain_path(genesis_hash, fork_name);
|
||||
dir.push(format!("v{}-sec-{}", LEGACY_CLIENT_DB_VER_STR, pruning.as_internal_name_str()));
|
||||
dir
|
||||
}
|
||||
|
||||
/// Get the path for the databases given the genesis_hash and information on the databases.
|
||||
pub fn client_path(&self, genesis_hash: H256, fork_name: Option<&String>, pruning: Algorithm) -> PathBuf {
|
||||
let mut dir = self.db_version_path(genesis_hash, fork_name, pruning);
|
||||
dir.push("db");
|
||||
dir
|
||||
}
|
||||
|
||||
/// Get the path for the snapshot directory given the genesis hash and fork name.
|
||||
pub fn snapshot_path(&self, genesis_hash: H256, fork_name: Option<&String>) -> PathBuf {
|
||||
let mut dir = self.chain_path(genesis_hash, fork_name);
|
||||
dir.push("snapshot");
|
||||
dir
|
||||
/// Database paths.
|
||||
pub fn database(&self, genesis_hash: H256, fork_name: Option<String>) -> DatabaseDirectories {
|
||||
DatabaseDirectories {
|
||||
path: self.db.clone(),
|
||||
genesis_hash: genesis_hash,
|
||||
fork_name: fork_name,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the ipc sockets path
|
||||
@@ -88,6 +69,49 @@ impl Directories {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct DatabaseDirectories {
|
||||
pub path: String,
|
||||
pub genesis_hash: H256,
|
||||
pub fork_name: Option<String>,
|
||||
}
|
||||
|
||||
impl DatabaseDirectories {
|
||||
fn fork_path(&self) -> PathBuf {
|
||||
let mut dir = Path::new(&self.path).to_path_buf();
|
||||
dir.push(format!("{:?}{}", H64::from(self.genesis_hash), self.fork_name.as_ref().map(|f| format!("-{}", f)).unwrap_or_default()));
|
||||
dir
|
||||
}
|
||||
|
||||
/// Get the root path for database
|
||||
pub fn version_path(&self, pruning: Algorithm) -> PathBuf {
|
||||
let mut dir = self.fork_path();
|
||||
dir.push(format!("v{}-sec-{}", LEGACY_CLIENT_DB_VER_STR, pruning.as_internal_name_str()));
|
||||
dir
|
||||
}
|
||||
|
||||
/// Get the path for the databases given the genesis_hash and information on the databases.
|
||||
pub fn client_path(&self, pruning: Algorithm) -> PathBuf {
|
||||
let mut dir = self.version_path(pruning);
|
||||
dir.push("db");
|
||||
dir
|
||||
}
|
||||
|
||||
/// Get user defaults path
|
||||
pub fn user_defaults_path(&self) -> PathBuf {
|
||||
let mut dir = self.fork_path();
|
||||
dir.push("user_defaults");
|
||||
dir
|
||||
}
|
||||
|
||||
/// Get the path for the snapshot directory given the genesis hash and fork name.
|
||||
pub fn snapshot_path(&self) -> PathBuf {
|
||||
let mut dir = self.fork_path();
|
||||
dir.push("snapshot");
|
||||
dir
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Directories;
|
||||
|
||||
@@ -19,13 +19,12 @@ use std::io::{Write, Read, BufReader, BufRead};
|
||||
use std::time::Duration;
|
||||
use std::path::Path;
|
||||
use std::fs::File;
|
||||
use util::{clean_0x, U256, Uint, Address, path, H256, CompactionProfile};
|
||||
use util::{clean_0x, U256, Uint, Address, path, CompactionProfile};
|
||||
use util::journaldb::Algorithm;
|
||||
use ethcore::client::{Mode, BlockID, Switch, VMType, DatabaseCompactionProfile, ClientConfig};
|
||||
use ethcore::client::{Mode, BlockID, VMType, DatabaseCompactionProfile, ClientConfig};
|
||||
use ethcore::miner::PendingSet;
|
||||
use cache::CacheConfig;
|
||||
use dir::Directories;
|
||||
use params::Pruning;
|
||||
use dir::DatabaseDirectories;
|
||||
use upgrade::upgrade;
|
||||
use migration::migrate;
|
||||
use ethsync::is_valid_node_url;
|
||||
@@ -190,16 +189,13 @@ pub fn default_network_config() -> ::ethsync::NetworkConfiguration {
|
||||
#[cfg_attr(feature = "dev", allow(too_many_arguments))]
|
||||
pub fn to_client_config(
|
||||
cache_config: &CacheConfig,
|
||||
dirs: &Directories,
|
||||
genesis_hash: H256,
|
||||
mode: Mode,
|
||||
tracing: Switch,
|
||||
pruning: Pruning,
|
||||
tracing: bool,
|
||||
compaction: DatabaseCompactionProfile,
|
||||
wal: bool,
|
||||
vm_type: VMType,
|
||||
name: String,
|
||||
fork_name: Option<&String>,
|
||||
pruning: Algorithm,
|
||||
) -> ClientConfig {
|
||||
let mut client_config = ClientConfig::default();
|
||||
|
||||
@@ -221,7 +217,7 @@ pub fn to_client_config(
|
||||
|
||||
client_config.mode = mode;
|
||||
client_config.tracing.enabled = tracing;
|
||||
client_config.pruning = pruning.to_algorithm(dirs, genesis_hash, fork_name);
|
||||
client_config.pruning = pruning;
|
||||
client_config.db_compaction = compaction;
|
||||
client_config.db_wal = wal;
|
||||
client_config.vm_type = vm_type;
|
||||
@@ -230,14 +226,12 @@ pub fn to_client_config(
|
||||
}
|
||||
|
||||
pub fn execute_upgrades(
|
||||
dirs: &Directories,
|
||||
genesis_hash: H256,
|
||||
fork_name: Option<&String>,
|
||||
dirs: &DatabaseDirectories,
|
||||
pruning: Algorithm,
|
||||
compaction_profile: CompactionProfile
|
||||
) -> Result<(), String> {
|
||||
|
||||
match upgrade(Some(&dirs.db)) {
|
||||
match upgrade(Some(&dirs.path)) {
|
||||
Ok(upgrades_applied) if upgrades_applied > 0 => {
|
||||
debug!("Executed {} upgrade scripts - ok", upgrades_applied);
|
||||
},
|
||||
@@ -247,7 +241,7 @@ pub fn execute_upgrades(
|
||||
_ => {},
|
||||
}
|
||||
|
||||
let client_path = dirs.db_version_path(genesis_hash, fork_name, pruning);
|
||||
let client_path = dirs.version_path(pruning);
|
||||
migrate(&client_path, pruning, compaction_profile).map_err(|e| format!("{}", e))
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,8 @@ extern crate semver;
|
||||
extern crate ethcore_io as io;
|
||||
extern crate ethcore_ipc as ipc;
|
||||
extern crate ethcore_ipc_nano as nanoipc;
|
||||
extern crate serde;
|
||||
extern crate serde_json;
|
||||
extern crate rlp;
|
||||
|
||||
extern crate json_ipc_server as jsonipc;
|
||||
@@ -106,6 +108,7 @@ mod run;
|
||||
mod sync;
|
||||
#[cfg(feature="ipc")]
|
||||
mod boot;
|
||||
mod user_defaults;
|
||||
|
||||
#[cfg(feature="stratum")]
|
||||
mod stratum;
|
||||
|
||||
103
parity/params.rs
103
parity/params.rs
@@ -14,15 +14,14 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::str::FromStr;
|
||||
use std::fs;
|
||||
use std::{str, fs};
|
||||
use std::time::Duration;
|
||||
use util::{H256, Address, U256, version_data};
|
||||
use util::{Address, U256, version_data};
|
||||
use util::journaldb::Algorithm;
|
||||
use ethcore::spec::Spec;
|
||||
use ethcore::ethereum;
|
||||
use ethcore::miner::{GasPricer, GasPriceCalibratorOptions};
|
||||
use dir::Directories;
|
||||
use user_defaults::UserDefaults;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum SpecType {
|
||||
@@ -39,7 +38,7 @@ impl Default for SpecType {
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for SpecType {
|
||||
impl str::FromStr for SpecType {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
@@ -81,7 +80,7 @@ impl Default for Pruning {
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Pruning {
|
||||
impl str::FromStr for Pruning {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
@@ -93,24 +92,12 @@ impl FromStr for Pruning {
|
||||
}
|
||||
|
||||
impl Pruning {
|
||||
pub fn to_algorithm(&self, dirs: &Directories, genesis_hash: H256, fork_name: Option<&String>) -> Algorithm {
|
||||
pub fn to_algorithm(&self, user_defaults: &UserDefaults) -> Algorithm {
|
||||
match *self {
|
||||
Pruning::Specific(algo) => algo,
|
||||
Pruning::Auto => Self::find_best_db(dirs, genesis_hash, fork_name),
|
||||
Pruning::Auto => user_defaults.pruning,
|
||||
}
|
||||
}
|
||||
|
||||
fn find_best_db(dirs: &Directories, genesis_hash: H256, fork_name: Option<&String>) -> Algorithm {
|
||||
let mut algo_types = Algorithm::all_types();
|
||||
// if all dbs have the same modification time, the last element is the default one
|
||||
algo_types.push(Algorithm::default());
|
||||
|
||||
algo_types.into_iter().max_by_key(|i| {
|
||||
let mut client_path = dirs.client_path(genesis_hash, fork_name, *i);
|
||||
client_path.push("CURRENT");
|
||||
fs::metadata(&client_path).and_then(|m| m.modified()).ok()
|
||||
}).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
@@ -128,7 +115,7 @@ impl Default for ResealPolicy {
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for ResealPolicy {
|
||||
impl str::FromStr for ResealPolicy {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
@@ -223,10 +210,50 @@ impl Default for MinerExtras {
|
||||
}
|
||||
}
|
||||
|
||||
/// 3-value enum.
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum Switch {
|
||||
/// True.
|
||||
On,
|
||||
/// False.
|
||||
Off,
|
||||
/// Auto.
|
||||
Auto,
|
||||
}
|
||||
|
||||
impl Default for Switch {
|
||||
fn default() -> Self {
|
||||
Switch::Auto
|
||||
}
|
||||
}
|
||||
|
||||
impl str::FromStr for Switch {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"on" => Ok(Switch::On),
|
||||
"off" => Ok(Switch::Off),
|
||||
"auto" => Ok(Switch::Auto),
|
||||
other => Err(format!("Invalid switch value: {}", other))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tracing_switch_to_bool(switch: Switch, user_defaults: &UserDefaults) -> Result<bool, String> {
|
||||
match (user_defaults.is_first_launch, switch, user_defaults.tracing) {
|
||||
(false, Switch::On, false) => Err("TraceDB resync required".into()),
|
||||
(_, Switch::On, _) => Ok(true),
|
||||
(_, Switch::Off, _) => Ok(false),
|
||||
(_, Switch::Auto, def) => Ok(def),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use util::journaldb::Algorithm;
|
||||
use super::{SpecType, Pruning, ResealPolicy};
|
||||
use user_defaults::UserDefaults;
|
||||
use super::{SpecType, Pruning, ResealPolicy, Switch, tracing_switch_to_bool};
|
||||
|
||||
#[test]
|
||||
fn test_spec_type_parsing() {
|
||||
@@ -274,4 +301,36 @@ mod tests {
|
||||
let all = ResealPolicy { own: true, external: true };
|
||||
assert_eq!(all, ResealPolicy::default());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_switch_parsing() {
|
||||
assert_eq!(Switch::On, "on".parse().unwrap());
|
||||
assert_eq!(Switch::Off, "off".parse().unwrap());
|
||||
assert_eq!(Switch::Auto, "auto".parse().unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_switch_default() {
|
||||
assert_eq!(Switch::default(), Switch::Auto);
|
||||
}
|
||||
|
||||
fn user_defaults_with_tracing(first_launch: bool, tracing: bool) -> UserDefaults {
|
||||
let mut ud = UserDefaults::default();
|
||||
ud.is_first_launch = first_launch;
|
||||
ud.tracing = tracing;
|
||||
ud
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_switch_to_bool() {
|
||||
assert!(!tracing_switch_to_bool(Switch::Off, &user_defaults_with_tracing(true, true)).unwrap());
|
||||
assert!(!tracing_switch_to_bool(Switch::Off, &user_defaults_with_tracing(true, false)).unwrap());
|
||||
assert!(!tracing_switch_to_bool(Switch::Off, &user_defaults_with_tracing(false, true)).unwrap());
|
||||
assert!(!tracing_switch_to_bool(Switch::Off, &user_defaults_with_tracing(false, false)).unwrap());
|
||||
|
||||
assert!(tracing_switch_to_bool(Switch::On, &user_defaults_with_tracing(true, true)).unwrap());
|
||||
assert!(tracing_switch_to_bool(Switch::On, &user_defaults_with_tracing(true, false)).unwrap());
|
||||
assert!(tracing_switch_to_bool(Switch::On, &user_defaults_with_tracing(false, true)).unwrap());
|
||||
assert!(tracing_switch_to_bool(Switch::On, &user_defaults_with_tracing(false, false)).is_err());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ use ethcore_rpc::NetworkSettings;
|
||||
use ethsync::NetworkConfiguration;
|
||||
use util::{Colour, version, U256};
|
||||
use io::{MayPanic, ForwardPanic, PanicHandler};
|
||||
use ethcore::client::{Mode, Switch, DatabaseCompactionProfile, VMType, ChainNotify};
|
||||
use ethcore::client::{Mode, DatabaseCompactionProfile, VMType, ChainNotify};
|
||||
use ethcore::service::ClientService;
|
||||
use ethcore::account_provider::AccountProvider;
|
||||
use ethcore::miner::{Miner, MinerService, ExternalMiner, MinerOptions};
|
||||
@@ -35,10 +35,11 @@ use rpc::{HttpServer, IpcServer, HttpConfiguration, IpcConfiguration};
|
||||
use signer::SignerServer;
|
||||
use dapps::WebappServer;
|
||||
use io_handler::ClientIoHandler;
|
||||
use params::{SpecType, Pruning, AccountsConfig, GasPricerConfig, MinerExtras};
|
||||
use params::{SpecType, Pruning, AccountsConfig, GasPricerConfig, MinerExtras, Switch, tracing_switch_to_bool};
|
||||
use helpers::{to_client_config, execute_upgrades, passwords_from_files};
|
||||
use dir::Directories;
|
||||
use cache::CacheConfig;
|
||||
use user_defaults::UserDefaults;
|
||||
use dapps;
|
||||
use signer;
|
||||
use modules;
|
||||
@@ -87,34 +88,45 @@ pub struct RunCmd {
|
||||
}
|
||||
|
||||
pub fn execute(cmd: RunCmd) -> Result<(), String> {
|
||||
// increase max number of open files
|
||||
raise_fd_limit();
|
||||
// set up panic handler
|
||||
let panic_handler = PanicHandler::new_in_arc();
|
||||
|
||||
// set up logger
|
||||
let logger = try!(setup_log(&cmd.logger_config));
|
||||
|
||||
// set up panic handler
|
||||
let panic_handler = PanicHandler::new_in_arc();
|
||||
// increase max number of open files
|
||||
raise_fd_limit();
|
||||
|
||||
// create dirs used by parity
|
||||
try!(cmd.dirs.create_dirs());
|
||||
|
||||
// load spec
|
||||
let spec = try!(cmd.spec.spec());
|
||||
let fork_name = spec.fork_name.clone();
|
||||
|
||||
// load genesis hash
|
||||
let genesis_hash = spec.genesis_header().hash();
|
||||
|
||||
// database paths
|
||||
let db_dirs = cmd.dirs.database(genesis_hash, spec.fork_name.clone());
|
||||
|
||||
// user defaults path
|
||||
let user_defaults_path = db_dirs.user_defaults_path();
|
||||
|
||||
// load user defaults
|
||||
let mut user_defaults = try!(UserDefaults::load(&user_defaults_path));
|
||||
|
||||
// check if tracing is on
|
||||
let tracing = try!(tracing_switch_to_bool(cmd.tracing, &user_defaults));
|
||||
|
||||
// select pruning algorithm
|
||||
let algorithm = cmd.pruning.to_algorithm(&cmd.dirs, genesis_hash, fork_name.as_ref());
|
||||
let algorithm = cmd.pruning.to_algorithm(&user_defaults);
|
||||
|
||||
// prepare client and snapshot paths.
|
||||
let client_path = cmd.dirs.client_path(genesis_hash, fork_name.as_ref(), algorithm);
|
||||
let snapshot_path = cmd.dirs.snapshot_path(genesis_hash, fork_name.as_ref());
|
||||
let client_path = db_dirs.client_path(algorithm);
|
||||
let snapshot_path = db_dirs.snapshot_path();
|
||||
|
||||
// execute upgrades
|
||||
try!(execute_upgrades(&cmd.dirs, genesis_hash, fork_name.as_ref(), algorithm, cmd.compaction.compaction_profile()));
|
||||
try!(execute_upgrades(&db_dirs, algorithm, cmd.compaction.compaction_profile()));
|
||||
|
||||
// run in daemon mode
|
||||
if let Some(pid_file) = cmd.daemon {
|
||||
@@ -152,16 +164,13 @@ pub fn execute(cmd: RunCmd) -> Result<(), String> {
|
||||
// create client config
|
||||
let client_config = to_client_config(
|
||||
&cmd.cache_config,
|
||||
&cmd.dirs,
|
||||
genesis_hash,
|
||||
cmd.mode,
|
||||
cmd.tracing,
|
||||
cmd.pruning,
|
||||
tracing,
|
||||
cmd.compaction,
|
||||
cmd.wal,
|
||||
cmd.vm_type,
|
||||
cmd.name,
|
||||
fork_name.as_ref(),
|
||||
algorithm,
|
||||
);
|
||||
|
||||
// set up bootnodes
|
||||
@@ -288,6 +297,11 @@ pub fn execute(cmd: RunCmd) -> 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);
|
||||
|
||||
|
||||
@@ -25,14 +25,15 @@ use ethcore::snapshot::{Progress, RestorationStatus, SnapshotService as SS};
|
||||
use ethcore::snapshot::io::{SnapshotReader, PackedReader, PackedWriter};
|
||||
use ethcore::snapshot::service::Service as SnapshotService;
|
||||
use ethcore::service::ClientService;
|
||||
use ethcore::client::{Mode, DatabaseCompactionProfile, Switch, VMType};
|
||||
use ethcore::client::{Mode, DatabaseCompactionProfile, VMType};
|
||||
use ethcore::miner::Miner;
|
||||
use ethcore::ids::BlockID;
|
||||
|
||||
use cache::CacheConfig;
|
||||
use params::{SpecType, Pruning};
|
||||
use params::{SpecType, Pruning, Switch, tracing_switch_to_bool};
|
||||
use helpers::{to_client_config, execute_upgrades};
|
||||
use dir::Directories;
|
||||
use user_defaults::UserDefaults;
|
||||
use fdlimit;
|
||||
|
||||
use io::PanicHandler;
|
||||
@@ -129,23 +130,35 @@ impl SnapshotCommand {
|
||||
// load genesis hash
|
||||
let genesis_hash = spec.genesis_header().hash();
|
||||
|
||||
// database paths
|
||||
let db_dirs = self.dirs.database(genesis_hash, spec.fork_name.clone());
|
||||
|
||||
// user defaults path
|
||||
let user_defaults_path = db_dirs.user_defaults_path();
|
||||
|
||||
// load user defaults
|
||||
let user_defaults = try!(UserDefaults::load(&user_defaults_path));
|
||||
|
||||
// check if tracing is on
|
||||
let tracing = try!(tracing_switch_to_bool(self.tracing, &user_defaults));
|
||||
|
||||
// Setup logging
|
||||
let _logger = setup_log(&self.logger_config);
|
||||
|
||||
fdlimit::raise_fd_limit();
|
||||
|
||||
// select pruning algorithm
|
||||
let algorithm = self.pruning.to_algorithm(&self.dirs, genesis_hash, spec.fork_name.as_ref());
|
||||
let algorithm = self.pruning.to_algorithm(&user_defaults);
|
||||
|
||||
// prepare client and snapshot paths.
|
||||
let client_path = self.dirs.client_path(genesis_hash, spec.fork_name.as_ref(), algorithm);
|
||||
let snapshot_path = self.dirs.snapshot_path(genesis_hash, spec.fork_name.as_ref());
|
||||
let client_path = db_dirs.client_path(algorithm);
|
||||
let snapshot_path = db_dirs.snapshot_path();
|
||||
|
||||
// execute upgrades
|
||||
try!(execute_upgrades(&self.dirs, genesis_hash, spec.fork_name.as_ref(), algorithm, self.compaction.compaction_profile()));
|
||||
try!(execute_upgrades(&db_dirs, algorithm, self.compaction.compaction_profile()));
|
||||
|
||||
// prepare client config
|
||||
let client_config = to_client_config(&self.cache_config, &self.dirs, genesis_hash, self.mode, self.tracing, self.pruning, self.compaction, self.wal, VMType::default(), "".into(), spec.fork_name.as_ref());
|
||||
let client_config = to_client_config(&self.cache_config, self.mode, tracing, self.compaction, self.wal, VMType::default(), "".into(), algorithm);
|
||||
|
||||
let service = try!(ClientService::start(
|
||||
client_config,
|
||||
|
||||
98
parity/user_defaults.rs
Normal file
98
parity/user_defaults.rs
Normal file
@@ -0,0 +1,98 @@
|
||||
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
use std::collections::BTreeMap;
|
||||
use serde::{Serialize, Serializer, Error, Deserialize, Deserializer};
|
||||
use serde::de::{Visitor, MapVisitor};
|
||||
use serde::de::impls::BTreeMapVisitor;
|
||||
use serde_json::Value;
|
||||
use serde_json::de::from_reader;
|
||||
use serde_json::ser::to_string;
|
||||
use util::journaldb::Algorithm;
|
||||
|
||||
pub struct UserDefaults {
|
||||
pub is_first_launch: bool,
|
||||
pub pruning: Algorithm,
|
||||
pub tracing: bool,
|
||||
}
|
||||
|
||||
impl Serialize for UserDefaults {
|
||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
||||
where S: Serializer {
|
||||
let mut map: BTreeMap<String, Value> = BTreeMap::new();
|
||||
map.insert("pruning".into(), Value::String(self.pruning.as_str().into()));
|
||||
map.insert("tracing".into(), Value::Bool(self.tracing));
|
||||
map.serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
struct UserDefaultsVisitor;
|
||||
|
||||
impl Deserialize for UserDefaults {
|
||||
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
|
||||
where D: Deserializer {
|
||||
deserializer.deserialize(UserDefaultsVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl Visitor for UserDefaultsVisitor {
|
||||
type Value = UserDefaults;
|
||||
|
||||
fn visit_map<V>(&mut self, visitor: V) -> Result<Self::Value, V::Error>
|
||||
where V: MapVisitor {
|
||||
let mut map: BTreeMap<String, Value> = try!(BTreeMapVisitor::new().visit_map(visitor));
|
||||
let pruning: Value = try!(map.remove("pruning".into()).ok_or_else(|| Error::custom("missing pruning")));
|
||||
let pruning = try!(pruning.as_str().ok_or_else(|| Error::custom("invalid pruning value")));
|
||||
let pruning = try!(pruning.parse().map_err(|_| Error::custom("invalid pruning method")));
|
||||
let tracing: Value = try!(map.remove("tracing".into()).ok_or_else(|| Error::custom("missing tracing")));
|
||||
let tracing = try!(tracing.as_bool().ok_or_else(|| Error::custom("invalid tracing value")));
|
||||
|
||||
let user_defaults = UserDefaults {
|
||||
is_first_launch: false,
|
||||
pruning: pruning,
|
||||
tracing: tracing,
|
||||
};
|
||||
|
||||
Ok(user_defaults)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for UserDefaults {
|
||||
fn default() -> Self {
|
||||
UserDefaults {
|
||||
is_first_launch: true,
|
||||
pruning: Algorithm::default(),
|
||||
tracing: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl UserDefaults {
|
||||
pub fn load<P>(path: P) -> Result<Self, String> where P: AsRef<Path> {
|
||||
match File::open(path) {
|
||||
Ok(file) => from_reader(file).map_err(|e| e.to_string()),
|
||||
_ => Ok(UserDefaults::default()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn save<P>(self, path: P) -> Result<(), String> where P: AsRef<Path> {
|
||||
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())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user