IPC (feature-gated) (#1654)
* moving ipc deriving to trait * refactoring of the client * all compiled * proved all working * warnings purged * allow hypervisor to specify initialization payload in two ways * using binary initialisation payload for sync * some docs * logger to separate crate * log settings for sync bin * forwarding logging arguments to the sync
This commit is contained in:
parent
7ae9e61d6c
commit
8ab56ea3d1
14
Cargo.lock
generated
14
Cargo.lock
generated
@ -15,6 +15,7 @@ dependencies = [
|
|||||||
"ethcore-ipc-codegen 1.3.0",
|
"ethcore-ipc-codegen 1.3.0",
|
||||||
"ethcore-ipc-hypervisor 1.2.0",
|
"ethcore-ipc-hypervisor 1.2.0",
|
||||||
"ethcore-ipc-nano 1.3.0",
|
"ethcore-ipc-nano 1.3.0",
|
||||||
|
"ethcore-logger 1.3.0",
|
||||||
"ethcore-rpc 1.3.0",
|
"ethcore-rpc 1.3.0",
|
||||||
"ethcore-signer 1.3.0",
|
"ethcore-signer 1.3.0",
|
||||||
"ethcore-util 1.3.0",
|
"ethcore-util 1.3.0",
|
||||||
@ -343,6 +344,19 @@ dependencies = [
|
|||||||
"nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git)",
|
"nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ethcore-logger"
|
||||||
|
version = "1.3.0"
|
||||||
|
dependencies = [
|
||||||
|
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"ethcore-util 1.3.0",
|
||||||
|
"isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"regex 0.1.68 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ethcore-rpc"
|
name = "ethcore-rpc"
|
||||||
version = "1.3.0"
|
version = "1.3.0"
|
||||||
|
@ -36,6 +36,7 @@ ethcore-signer = { path = "signer" }
|
|||||||
ethcore-ipc-nano = { path = "ipc/nano" }
|
ethcore-ipc-nano = { path = "ipc/nano" }
|
||||||
ethcore-ipc = { path = "ipc/rpc" }
|
ethcore-ipc = { path = "ipc/rpc" }
|
||||||
ethcore-ipc-hypervisor = { path = "ipc/hypervisor" }
|
ethcore-ipc-hypervisor = { path = "ipc/hypervisor" }
|
||||||
|
ethcore-logger = { path = "logger" }
|
||||||
json-ipc-server = { git = "https://github.com/ethcore/json-ipc-server.git" }
|
json-ipc-server = { git = "https://github.com/ethcore/json-ipc-server.git" }
|
||||||
ethcore-dapps = { path = "dapps", optional = true }
|
ethcore-dapps = { path = "dapps", optional = true }
|
||||||
clippy = { version = "0.0.79", optional = true}
|
clippy = { version = "0.0.79", optional = true}
|
||||||
@ -58,6 +59,7 @@ dapps = ["ethcore-dapps"]
|
|||||||
dev = ["clippy", "ethcore/dev", "ethcore-util/dev", "ethsync/dev", "ethcore-rpc/dev", "ethcore-dapps/dev", "ethcore-signer/dev"]
|
dev = ["clippy", "ethcore/dev", "ethcore-util/dev", "ethsync/dev", "ethcore-rpc/dev", "ethcore-dapps/dev", "ethcore-signer/dev"]
|
||||||
travis-beta = ["ethcore/json-tests"]
|
travis-beta = ["ethcore/json-tests"]
|
||||||
travis-nightly = ["ethcore/json-tests", "dev"]
|
travis-nightly = ["ethcore/json-tests", "dev"]
|
||||||
|
ipc = ["ethcore/ipc"]
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
path = "parity/main.rs"
|
path = "parity/main.rs"
|
||||||
|
@ -46,3 +46,4 @@ test-heavy = []
|
|||||||
dev = ["clippy"]
|
dev = ["clippy"]
|
||||||
default = []
|
default = []
|
||||||
benches = []
|
benches = []
|
||||||
|
ipc = []
|
||||||
|
@ -235,8 +235,8 @@ impl Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Adds an actor to be notified on certain events
|
/// Adds an actor to be notified on certain events
|
||||||
pub fn add_notify(&self, target: &Arc<ChainNotify>) {
|
pub fn add_notify(&self, target: Arc<ChainNotify>) {
|
||||||
self.notify.write().push(Arc::downgrade(target));
|
self.notify.write().push(Arc::downgrade(&target));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn notify<F>(&self, f: F) where F: Fn(&ChainNotify) {
|
fn notify<F>(&self, f: F) where F: Fn(&ChainNotify) {
|
||||||
|
@ -30,7 +30,7 @@ pub use self::test_client::{TestBlockChainClient, EachBlockWith};
|
|||||||
pub use types::trace_filter::Filter as TraceFilter;
|
pub use types::trace_filter::Filter as TraceFilter;
|
||||||
pub use executive::{Executed, Executive, TransactOptions};
|
pub use executive::{Executed, Executive, TransactOptions};
|
||||||
pub use env_info::{LastHashes, EnvInfo};
|
pub use env_info::{LastHashes, EnvInfo};
|
||||||
pub use self::chain_notify::ChainNotify;
|
pub use self::chain_notify::{ChainNotify, ChainNotifyClient};
|
||||||
|
|
||||||
pub use types::call_analytics::CallAnalytics;
|
pub use types::call_analytics::CallAnalytics;
|
||||||
pub use block_import_error::BlockImportError;
|
pub use block_import_error::BlockImportError;
|
||||||
|
@ -22,6 +22,12 @@ use spec::Spec;
|
|||||||
use error::*;
|
use error::*;
|
||||||
use client::{Client, ClientConfig, ChainNotify};
|
use client::{Client, ClientConfig, ChainNotify};
|
||||||
use miner::Miner;
|
use miner::Miner;
|
||||||
|
use std::sync::atomic::AtomicBool;
|
||||||
|
|
||||||
|
#[cfg(feature="ipc")]
|
||||||
|
use nanoipc;
|
||||||
|
#[cfg(feature="ipc")]
|
||||||
|
use client::BlockChainClient;
|
||||||
|
|
||||||
/// Message type for external and internal events
|
/// Message type for external and internal events
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -38,7 +44,8 @@ pub enum ClientIoMessage {
|
|||||||
pub struct ClientService {
|
pub struct ClientService {
|
||||||
io_service: Arc<IoService<ClientIoMessage>>,
|
io_service: Arc<IoService<ClientIoMessage>>,
|
||||||
client: Arc<Client>,
|
client: Arc<Client>,
|
||||||
panic_handler: Arc<PanicHandler>
|
panic_handler: Arc<PanicHandler>,
|
||||||
|
_stop_guard: ::devtools::StopGuard,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClientService {
|
impl ClientService {
|
||||||
@ -62,10 +69,14 @@ impl ClientService {
|
|||||||
});
|
});
|
||||||
try!(io_service.register_handler(client_io));
|
try!(io_service.register_handler(client_io));
|
||||||
|
|
||||||
|
let stop_guard = ::devtools::StopGuard::new();
|
||||||
|
run_ipc(client.clone(), stop_guard.share());
|
||||||
|
|
||||||
Ok(ClientService {
|
Ok(ClientService {
|
||||||
io_service: Arc::new(io_service),
|
io_service: Arc::new(io_service),
|
||||||
client: client,
|
client: client,
|
||||||
panic_handler: panic_handler,
|
panic_handler: panic_handler,
|
||||||
|
_stop_guard: stop_guard,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +101,7 @@ impl ClientService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Set the actor to be notified on certain chain events
|
/// Set the actor to be notified on certain chain events
|
||||||
pub fn add_notify(&self, notify: &Arc<ChainNotify>) {
|
pub fn add_notify(&self, notify: Arc<ChainNotify>) {
|
||||||
self.client.add_notify(notify);
|
self.client.add_notify(notify);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -130,6 +141,22 @@ impl IoHandler<ClientIoMessage> for ClientIoHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature="ipc")]
|
||||||
|
fn run_ipc(client: Arc<Client>, stop: Arc<AtomicBool>) {
|
||||||
|
::std::thread::spawn(move || {
|
||||||
|
let mut worker = nanoipc::Worker::new(&(client as Arc<BlockChainClient>));
|
||||||
|
worker.add_reqrep("ipc:///tmp/parity-chain.ipc").expect("Ipc expected to initialize with no issues");
|
||||||
|
|
||||||
|
while !stop.load(::std::sync::atomic::Ordering::Relaxed) {
|
||||||
|
worker.poll();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature="ipc"))]
|
||||||
|
fn run_ipc(_client: Arc<Client>, _stop: Arc<AtomicBool>) {
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -273,7 +273,12 @@ fn implement_dispatch_arm(
|
|||||||
{
|
{
|
||||||
let index_ident = builder.id(format!("{}", index + (RESERVED_MESSAGE_IDS as u32)).as_str());
|
let index_ident = builder.id(format!("{}", index + (RESERVED_MESSAGE_IDS as u32)).as_str());
|
||||||
let invoke_expr = implement_dispatch_arm_invoke(cx, builder, dispatch, buffer);
|
let invoke_expr = implement_dispatch_arm_invoke(cx, builder, dispatch, buffer);
|
||||||
quote_arm!(cx, $index_ident => { $invoke_expr } )
|
let dispatching_trace = "Dispatching: ".to_owned() + &dispatch.function_name;
|
||||||
|
let dispatching_trace_literal = builder.expr().lit().str::<&str>(&dispatching_trace);
|
||||||
|
quote_arm!(cx, $index_ident => {
|
||||||
|
trace!(target: "ipc", $dispatching_trace_literal);
|
||||||
|
$invoke_expr
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn implement_dispatch_arms(
|
fn implement_dispatch_arms(
|
||||||
@ -420,17 +425,22 @@ fn implement_client_method_body(
|
|||||||
request_serialization_statements
|
request_serialization_statements
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let invocation_trace = "Invoking: ".to_owned() + &dispatch.function_name;
|
||||||
|
let invocation_trace_literal = builder.expr().lit().str::<&str>(&invocation_trace);
|
||||||
|
|
||||||
if let Some(ref return_ty) = dispatch.return_type_ty {
|
if let Some(ref return_ty) = dispatch.return_type_ty {
|
||||||
let return_expr = quote_expr!(cx,
|
let return_expr = quote_expr!(cx,
|
||||||
::ipc::binary::deserialize_from::<$return_ty, _>(&mut *socket).unwrap()
|
::ipc::binary::deserialize_from::<$return_ty, _>(&mut *socket).unwrap()
|
||||||
);
|
);
|
||||||
quote_expr!(cx, {
|
quote_expr!(cx, {
|
||||||
|
trace!(target: "ipc", $invocation_trace_literal);
|
||||||
$request
|
$request
|
||||||
$return_expr
|
$return_expr
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
quote_expr!(cx, {
|
quote_expr!(cx, {
|
||||||
|
trace!(target: "ipc", $invocation_trace_literal);
|
||||||
$request
|
$request
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -261,6 +261,10 @@ fn binary_expr_struct(
|
|||||||
|
|
||||||
let raw_ident = ::syntax::print::pprust::ty_to_string(&codegen::strip_ptr(&field.ty));
|
let raw_ident = ::syntax::print::pprust::ty_to_string(&codegen::strip_ptr(&field.ty));
|
||||||
let range_ident = builder.id(format!("r{}", index));
|
let range_ident = builder.id(format!("r{}", index));
|
||||||
|
|
||||||
|
let error_message = "Error serializing member: ".to_owned() + &::syntax::print::pprust::expr_to_string(&member_expr);
|
||||||
|
let error_message_literal = builder.expr().lit().str::<&str>(&error_message);
|
||||||
|
|
||||||
match raw_ident.as_ref() {
|
match raw_ident.as_ref() {
|
||||||
"u8" => {
|
"u8" => {
|
||||||
write_stmts.push(quote_stmt!(cx, let next_line = offset + 1;).unwrap());
|
write_stmts.push(quote_stmt!(cx, let next_line = offset + 1;).unwrap());
|
||||||
@ -280,7 +284,13 @@ fn binary_expr_struct(
|
|||||||
}).unwrap());
|
}).unwrap());
|
||||||
write_stmts.push(quote_stmt!(cx, let $range_ident = offset..next_line; ).unwrap());
|
write_stmts.push(quote_stmt!(cx, let $range_ident = offset..next_line; ).unwrap());
|
||||||
post_write_stmts.push(quote_stmt!(cx,
|
post_write_stmts.push(quote_stmt!(cx,
|
||||||
if let Err(e) = $member_expr .to_bytes(&mut buffer[$range_ident], length_stack) { return Err(e) };).unwrap());
|
if $range_ident.end - $range_ident.start > 0 {
|
||||||
|
if let Err(e) = $member_expr .to_bytes(&mut buffer[$range_ident], length_stack) {
|
||||||
|
warn!(target: "ipc", $error_message_literal);
|
||||||
|
return Err(e)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
).unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,35 @@ pub struct Hypervisor {
|
|||||||
service: Arc<HypervisorService>,
|
service: Arc<HypervisorService>,
|
||||||
ipc_worker: RwLock<nanoipc::Worker<HypervisorService>>,
|
ipc_worker: RwLock<nanoipc::Worker<HypervisorService>>,
|
||||||
processes: RwLock<HashMap<BinaryId, Child>>,
|
processes: RwLock<HashMap<BinaryId, Child>>,
|
||||||
modules: HashMap<IpcModuleId, (BinaryId, Vec<String>)>,
|
modules: HashMap<IpcModuleId, (BinaryId, BootArgs)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Boot arguments for binary
|
||||||
|
pub struct BootArgs {
|
||||||
|
cli: Option<Vec<String>>,
|
||||||
|
stdin: Option<Vec<u8>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BootArgs {
|
||||||
|
/// New empty boot arguments
|
||||||
|
pub fn new() -> BootArgs {
|
||||||
|
BootArgs {
|
||||||
|
cli: None,
|
||||||
|
stdin: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set command-line arguments for boot
|
||||||
|
pub fn cli(mut self, cli: Vec<String>) -> BootArgs {
|
||||||
|
self.cli = Some(cli);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set std-in stream for boot
|
||||||
|
pub fn stdin(mut self, stdin: Vec<u8>) -> BootArgs {
|
||||||
|
self.stdin = Some(stdin);
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Hypervisor {
|
impl Hypervisor {
|
||||||
@ -51,7 +79,7 @@ impl Hypervisor {
|
|||||||
Hypervisor::with_url(HYPERVISOR_IPC_URL)
|
Hypervisor::with_url(HYPERVISOR_IPC_URL)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn module(mut self, module_id: IpcModuleId, binary_id: BinaryId, args: Vec<String>) -> Hypervisor {
|
pub fn module(mut self, module_id: IpcModuleId, binary_id: BinaryId, args: BootArgs) -> Hypervisor {
|
||||||
self.modules.insert(module_id, (binary_id, args));
|
self.modules.insert(module_id, (binary_id, args));
|
||||||
self.service.add_module(module_id);
|
self.service.add_module(module_id);
|
||||||
self
|
self
|
||||||
@ -78,7 +106,7 @@ impl Hypervisor {
|
|||||||
|
|
||||||
/// Since one binary can host multiple modules
|
/// Since one binary can host multiple modules
|
||||||
/// we match binaries
|
/// we match binaries
|
||||||
fn match_module(&self, module_id: &IpcModuleId) -> Option<&(BinaryId, Vec<String>)> {
|
fn match_module(&self, module_id: &IpcModuleId) -> Option<&(BinaryId, BootArgs)> {
|
||||||
self.modules.get(module_id)
|
self.modules.get(module_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,6 +124,8 @@ impl Hypervisor {
|
|||||||
/// Does nothing when it is already started on module is inside the
|
/// Does nothing when it is already started on module is inside the
|
||||||
/// main binary
|
/// main binary
|
||||||
fn start_module(&self, module_id: IpcModuleId) {
|
fn start_module(&self, module_id: IpcModuleId) {
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
self.match_module(&module_id).map(|&(ref binary_id, ref binary_args)| {
|
self.match_module(&module_id).map(|&(ref binary_id, ref binary_args)| {
|
||||||
let mut processes = self.processes.write().unwrap();
|
let mut processes = self.processes.write().unwrap();
|
||||||
{
|
{
|
||||||
@ -109,13 +139,30 @@ impl Hypervisor {
|
|||||||
executable_path.pop();
|
executable_path.pop();
|
||||||
executable_path.push(binary_id);
|
executable_path.push(binary_id);
|
||||||
|
|
||||||
let mut command = Command::new(&executable_path.to_str().unwrap());
|
let executable_path = executable_path.to_str().unwrap();
|
||||||
for arg in binary_args { command.arg(arg); }
|
let mut command = Command::new(&executable_path);
|
||||||
|
command.stderr(std::process::Stdio::inherit());
|
||||||
|
|
||||||
|
if let Some(ref cli_args) = binary_args.cli {
|
||||||
|
for arg in cli_args { command.arg(arg); }
|
||||||
|
}
|
||||||
|
|
||||||
|
command.stdin(std::process::Stdio::piped());
|
||||||
|
|
||||||
trace!(target: "hypervisor", "Spawn executable: {:?}", command);
|
trace!(target: "hypervisor", "Spawn executable: {:?}", command);
|
||||||
|
|
||||||
let child = command.spawn().unwrap_or_else(
|
let mut child = command.spawn().unwrap_or_else(
|
||||||
|e| panic!("Hypervisor cannot start binary ({:?}): {}", executable_path, e));
|
|e| panic!("Hypervisor cannot start binary ({:?}): {}", executable_path, e));
|
||||||
|
|
||||||
|
if let Some(ref std_in) = binary_args.stdin {
|
||||||
|
trace!(target: "hypervisor", "Pushing std-in payload...");
|
||||||
|
child.stdin.as_mut()
|
||||||
|
.expect("std-in should be piped above")
|
||||||
|
.write(std_in)
|
||||||
|
.unwrap_or_else(|e| panic!(format!("Error trying to pipe stdin for {}: {:?}", &executable_path, e)));
|
||||||
|
drop(child.stdin.take());
|
||||||
|
}
|
||||||
|
|
||||||
processes.insert(binary_id, child);
|
processes.insert(binary_id, child);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -133,6 +180,7 @@ impl Hypervisor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Shutdown the ipc and all managed child processes
|
||||||
pub fn shutdown(&self, wait_time: Option<std::time::Duration>) {
|
pub fn shutdown(&self, wait_time: Option<std::time::Duration>) {
|
||||||
if wait_time.is_some() { std::thread::sleep(wait_time.unwrap()) }
|
if wait_time.is_some() { std::thread::sleep(wait_time.unwrap()) }
|
||||||
|
|
||||||
|
@ -60,6 +60,7 @@ impl HypervisorService {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add the module to the check-list
|
||||||
pub fn add_module(&self, module_id: IpcModuleId) {
|
pub fn add_module(&self, module_id: IpcModuleId) {
|
||||||
self.check_list.write().unwrap().insert(module_id, false);
|
self.check_list.write().unwrap().insert(module_id, false);
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ extern crate jsonrpc_core;
|
|||||||
use jsonrpc_core::IoHandler;
|
use jsonrpc_core::IoHandler;
|
||||||
|
|
||||||
pub use ipc::{WithSocket, IpcInterface, IpcConfig};
|
pub use ipc::{WithSocket, IpcInterface, IpcConfig};
|
||||||
|
pub use nanomsg::Socket as NanoSocket;
|
||||||
|
|
||||||
use std::sync::*;
|
use std::sync::*;
|
||||||
use std::sync::atomic::*;
|
use std::sync::atomic::*;
|
||||||
@ -54,9 +55,9 @@ impl<S> GuardedSocket<S> where S: WithSocket<Socket> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<S> Deref for GuardedSocket<S> where S: WithSocket<Socket> {
|
impl<S> Deref for GuardedSocket<S> where S: WithSocket<Socket> {
|
||||||
type Target = S;
|
type Target = Arc<S>;
|
||||||
|
|
||||||
fn deref(&self) -> &S {
|
fn deref(&self) -> &Arc<S> {
|
||||||
&self.client
|
&self.client
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,7 @@ impl<T> BinaryConvertable for Option<T> where T: BinaryConvertable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque<usize>) -> Result<Self, BinaryConvertError> {
|
fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque<usize>) -> Result<Self, BinaryConvertError> {
|
||||||
|
if buffer.len() == 0 { return Self::from_empty_bytes(); }
|
||||||
Ok(Some(try!(T::from_bytes(buffer, length_stack))))
|
Ok(Some(try!(T::from_bytes(buffer, length_stack))))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -779,6 +780,42 @@ fn serialize_into_deserialize_from() {
|
|||||||
assert_eq!(v, de_v);
|
assert_eq!(v, de_v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn serialize_vec_str() {
|
||||||
|
// empty
|
||||||
|
let source = Vec::<String>::new();
|
||||||
|
let serialized = serialize(&source).unwrap();
|
||||||
|
let deserialized = deserialize::<Vec<String>>(&serialized).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(source, deserialized);
|
||||||
|
|
||||||
|
// with few values
|
||||||
|
let mut source = Vec::<String>::new();
|
||||||
|
source.push("val1".to_owned());
|
||||||
|
source.push("val2".to_owned());
|
||||||
|
let serialized = serialize(&source).unwrap();
|
||||||
|
let deserialized = deserialize::<Vec<String>>(&serialized).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(source, deserialized);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn serialize_opt_str() {
|
||||||
|
// none
|
||||||
|
let source: Option<String> = None;
|
||||||
|
let serialized = serialize(&source).unwrap();
|
||||||
|
let deserialized = deserialize::<Option<String>>(&serialized).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(source, deserialized);
|
||||||
|
|
||||||
|
// value
|
||||||
|
let source: Option<String> = Some("i have value".to_owned());
|
||||||
|
let serialized = serialize(&source).unwrap();
|
||||||
|
let deserialized = deserialize::<Option<String>>(&serialized).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(source, deserialized);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn serialize_opt_vec() {
|
fn serialize_opt_vec() {
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
19
logger/Cargo.toml
Normal file
19
logger/Cargo.toml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
[package]
|
||||||
|
description = "Ethcore client."
|
||||||
|
name = "ethcore-logger"
|
||||||
|
version = "1.3.0"
|
||||||
|
license = "GPL-3.0"
|
||||||
|
authors = ["Ethcore <admin@ethcore.io>"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
log = "0.3"
|
||||||
|
env_logger = "0.3"
|
||||||
|
ethcore-util = { path = "../util" }
|
||||||
|
isatty = "0.1"
|
||||||
|
lazy_static = "0.2"
|
||||||
|
regex = "0.1"
|
||||||
|
time = "0.1"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
debug = true
|
||||||
|
lto = false
|
@ -14,20 +14,61 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! Logger for parity executables
|
||||||
|
|
||||||
|
extern crate ethcore_util as util;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate log as rlog;
|
||||||
|
extern crate isatty;
|
||||||
|
extern crate regex;
|
||||||
|
extern crate env_logger;
|
||||||
|
extern crate time;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate lazy_static;
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use isatty::{stderr_isatty};
|
use isatty::{stderr_isatty};
|
||||||
use time;
|
|
||||||
use env_logger::LogBuilder;
|
use env_logger::LogBuilder;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use util::RotatingLogger;
|
use util::RotatingLogger;
|
||||||
use util::log::Colour;
|
use util::log::Colour;
|
||||||
|
|
||||||
|
pub struct Settings {
|
||||||
|
pub color: bool,
|
||||||
|
pub init: Option<String>,
|
||||||
|
pub file: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Settings {
|
||||||
|
pub fn new() -> Settings {
|
||||||
|
Settings {
|
||||||
|
color: true,
|
||||||
|
init: None,
|
||||||
|
file: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init(mut self, init: String) -> Settings {
|
||||||
|
self.init = Some(init);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn file(mut self, file: String) -> Settings {
|
||||||
|
self.file = Some(file);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn no_color(mut self) -> Settings {
|
||||||
|
self.color = false;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Sets up the logger
|
/// Sets up the logger
|
||||||
pub fn setup_log(init: &Option<String>, enable_color: bool, log_to_file: &Option<String>) -> Arc<RotatingLogger> {
|
pub fn setup_log(settings: &Settings) -> Arc<RotatingLogger> {
|
||||||
use rlog::*;
|
use rlog::*;
|
||||||
|
|
||||||
let mut levels = String::new();
|
let mut levels = String::new();
|
||||||
@ -43,15 +84,15 @@ pub fn setup_log(init: &Option<String>, enable_color: bool, log_to_file: &Option
|
|||||||
builder.parse(lvl);
|
builder.parse(lvl);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref s) = *init {
|
if let Some(ref s) = settings.init {
|
||||||
levels.push_str(s);
|
levels.push_str(s);
|
||||||
builder.parse(s);
|
builder.parse(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
let enable_color = enable_color && stderr_isatty();
|
let enable_color = settings.color && stderr_isatty();
|
||||||
let logs = Arc::new(RotatingLogger::new(levels));
|
let logs = Arc::new(RotatingLogger::new(levels));
|
||||||
let logger = logs.clone();
|
let logger = logs.clone();
|
||||||
let maybe_file = log_to_file.as_ref().map(|f| File::create(f).unwrap_or_else(|_| die!("Cannot write to log file given: {}", f)));
|
let maybe_file = settings.file.as_ref().map(|f| File::create(f).unwrap_or_else(|_| panic!("Cannot write to log file given: {}", f)));
|
||||||
let format = move |record: &LogRecord| {
|
let format = move |record: &LogRecord| {
|
||||||
let timestamp = time::strftime("%Y-%m-%d %H:%M:%S %Z", &time::now()).unwrap();
|
let timestamp = time::strftime("%Y-%m-%d %H:%M:%S %Z", &time::now()).unwrap();
|
||||||
|
|
@ -34,6 +34,7 @@ use ethcore::ethereum;
|
|||||||
use ethcore::spec::Spec;
|
use ethcore::spec::Spec;
|
||||||
use ethsync::SyncConfig;
|
use ethsync::SyncConfig;
|
||||||
use rpc::IpcConfiguration;
|
use rpc::IpcConfiguration;
|
||||||
|
use ethcore_logger::Settings as LogSettings;
|
||||||
|
|
||||||
pub struct Configuration {
|
pub struct Configuration {
|
||||||
pub args: Args
|
pub args: Args
|
||||||
@ -564,6 +565,20 @@ impl Configuration {
|
|||||||
(self.args.flag_unlock.is_none() && !self.args.flag_no_signer) ||
|
(self.args.flag_unlock.is_none() && !self.args.flag_no_signer) ||
|
||||||
self.args.flag_force_signer
|
self.args.flag_force_signer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn log_settings(&self) -> LogSettings {
|
||||||
|
let mut settings = LogSettings::new();
|
||||||
|
if self.args.flag_no_color || cfg!(windows) {
|
||||||
|
settings = settings.no_color();
|
||||||
|
}
|
||||||
|
if let Some(ref init) = self.args.flag_logging {
|
||||||
|
settings = settings.init(init.to_owned())
|
||||||
|
}
|
||||||
|
if let Some(ref file) = self.args.flag_log_file {
|
||||||
|
settings = settings.file(file.to_owned())
|
||||||
|
}
|
||||||
|
settings
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -53,15 +53,16 @@ extern crate ansi_term;
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate lazy_static;
|
extern crate lazy_static;
|
||||||
extern crate regex;
|
extern crate regex;
|
||||||
|
extern crate ethcore_logger;
|
||||||
extern crate isatty;
|
extern crate isatty;
|
||||||
|
|
||||||
#[cfg(feature = "dapps")]
|
#[cfg(feature = "dapps")]
|
||||||
extern crate ethcore_dapps;
|
extern crate ethcore_dapps;
|
||||||
|
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod die;
|
mod die;
|
||||||
mod upgrade;
|
mod upgrade;
|
||||||
mod setup_log;
|
|
||||||
mod rpc;
|
mod rpc;
|
||||||
mod dapps;
|
mod dapps;
|
||||||
mod informant;
|
mod informant;
|
||||||
@ -86,7 +87,7 @@ use rustc_serialize::hex::FromHex;
|
|||||||
use ctrlc::CtrlC;
|
use ctrlc::CtrlC;
|
||||||
use util::{H256, ToPretty, PayloadInfo, Bytes, Colour, version, journaldb, RotatingLogger};
|
use util::{H256, ToPretty, PayloadInfo, Bytes, Colour, version, journaldb, RotatingLogger};
|
||||||
use util::panics::{MayPanic, ForwardPanic, PanicHandler};
|
use util::panics::{MayPanic, ForwardPanic, PanicHandler};
|
||||||
use ethcore::client::{BlockID, BlockChainClient, ClientConfig, get_db_path, BlockImportError, Mode, ChainNotify};
|
use ethcore::client::{BlockID, BlockChainClient, ClientConfig, get_db_path, BlockImportError, Mode};
|
||||||
use ethcore::error::{ImportError};
|
use ethcore::error::{ImportError};
|
||||||
use ethcore::service::ClientService;
|
use ethcore::service::ClientService;
|
||||||
use ethcore::spec::Spec;
|
use ethcore::spec::Spec;
|
||||||
@ -95,6 +96,9 @@ use ethcore::miner::{Miner, MinerService, ExternalMiner};
|
|||||||
use migration::migrate;
|
use migration::migrate;
|
||||||
use informant::Informant;
|
use informant::Informant;
|
||||||
use util::{Mutex, Condvar};
|
use util::{Mutex, Condvar};
|
||||||
|
use ethcore_logger::setup_log;
|
||||||
|
#[cfg(feature="ipc")]
|
||||||
|
use ethcore::client::ChainNotify;
|
||||||
|
|
||||||
use die::*;
|
use die::*;
|
||||||
use cli::print_version;
|
use cli::print_version;
|
||||||
@ -132,7 +136,7 @@ fn execute(conf: Configuration) {
|
|||||||
// Setup panic handler
|
// Setup panic handler
|
||||||
let panic_handler = PanicHandler::new_in_arc();
|
let panic_handler = PanicHandler::new_in_arc();
|
||||||
// Setup logging
|
// Setup logging
|
||||||
let logger = setup_log::setup_log(&conf.args.flag_logging, conf.have_color(), &conf.args.flag_log_file);
|
let logger = setup_log(&conf.log_settings());
|
||||||
// Raise fdlimit
|
// Raise fdlimit
|
||||||
unsafe { ::fdlimit::raise_fd_limit(); }
|
unsafe { ::fdlimit::raise_fd_limit(); }
|
||||||
|
|
||||||
@ -192,6 +196,8 @@ fn execute_upgrades(conf: &Configuration, spec: &Spec, client_config: &ClientCon
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig, panic_handler: Arc<PanicHandler>, logger: Arc<RotatingLogger>) {
|
fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig, panic_handler: Arc<PanicHandler>, logger: Arc<RotatingLogger>) {
|
||||||
|
let mut hypervisor = modules::hypervisor();
|
||||||
|
|
||||||
info!("Starting {}", Colour::White.bold().paint(format!("{}", version())));
|
info!("Starting {}", Colour::White.bold().paint(format!("{}", version())));
|
||||||
info!("Using state DB journalling strategy {}", Colour::White.bold().paint(match client_config.pruning {
|
info!("Using state DB journalling strategy {}", Colour::White.bold().paint(match client_config.pruning {
|
||||||
journaldb::Algorithm::Archive => "archive",
|
journaldb::Algorithm::Archive => "archive",
|
||||||
@ -244,9 +250,10 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig,
|
|||||||
|
|
||||||
// Sync
|
// Sync
|
||||||
let (sync_provider, manage_network, chain_notify) =
|
let (sync_provider, manage_network, chain_notify) =
|
||||||
modules::sync(sync_config, NetworkConfiguration::from(net_settings), client.clone())
|
modules::sync(&mut hypervisor, sync_config, NetworkConfiguration::from(net_settings), client.clone(), &conf.log_settings())
|
||||||
.unwrap_or_else(|e| die_with_error("Sync", e));
|
.unwrap_or_else(|e| die_with_error("Sync", e));
|
||||||
service.add_notify(&chain_notify);
|
|
||||||
|
service.add_notify(chain_notify.clone());
|
||||||
|
|
||||||
// if network is active by default
|
// if network is active by default
|
||||||
if match conf.mode() { Mode::Dark(..) => false, _ => !conf.args.flag_no_network } {
|
if match conf.mode() { Mode::Dark(..) => false, _ => !conf.args.flag_no_network } {
|
||||||
@ -311,8 +318,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig,
|
|||||||
});
|
});
|
||||||
|
|
||||||
let informant = Arc::new(Informant::new(service.client(), Some(sync_provider.clone()), Some(manage_network.clone()), conf.have_color()));
|
let informant = Arc::new(Informant::new(service.client(), Some(sync_provider.clone()), Some(manage_network.clone()), conf.have_color()));
|
||||||
let info_notify: Arc<ChainNotify> = informant.clone();
|
service.add_notify(informant.clone());
|
||||||
service.add_notify(&info_notify);
|
|
||||||
// Register IO handler
|
// Register IO handler
|
||||||
let io_handler = Arc::new(ClientIoHandler {
|
let io_handler = Arc::new(ClientIoHandler {
|
||||||
client: service.client(),
|
client: service.client(),
|
||||||
|
@ -14,28 +14,116 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use ethsync::{EthSync, SyncProvider, ManageNetwork, SyncConfig, NetworkConfiguration};
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use ethcore::client::{ChainNotify, BlockChainClient};
|
use ethcore::client::BlockChainClient;
|
||||||
use ethcore;
|
use ethcore;
|
||||||
|
use hypervisor::Hypervisor;
|
||||||
|
use ethsync::{SyncConfig, NetworkConfiguration};
|
||||||
|
#[cfg(not(feature="ipc"))]
|
||||||
|
use self::no_ipc_deps::*;
|
||||||
|
#[cfg(feature="ipc")]
|
||||||
|
use self::ipc_deps::*;
|
||||||
|
|
||||||
pub type Modules = (Arc<SyncProvider>, Arc<ManageNetwork>, Arc<ChainNotify>);
|
use ethcore_logger::Settings as LogSettings;
|
||||||
|
|
||||||
|
#[cfg(not(feature="ipc"))]
|
||||||
|
mod no_ipc_deps {
|
||||||
|
pub use ethsync::{EthSync, SyncProvider, ManageNetwork};
|
||||||
|
pub use ethcore::client::ChainNotify;
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature="ipc")]
|
#[cfg(feature="ipc")]
|
||||||
pub fn sync(
|
pub type SyncModules = (
|
||||||
sync_cfg: SyncConfig,
|
GuardedSocket<SyncClient<NanoSocket>>,
|
||||||
net_cfg: NetworkConfiguration,
|
GuardedSocket<NetworkManagerClient<NanoSocket>>,
|
||||||
client: Arc<BlockChainClient>)
|
GuardedSocket<ChainNotifyClient<NanoSocket>>
|
||||||
-> Result<Modules, ethcore::error::Error>
|
);
|
||||||
{
|
|
||||||
|
#[cfg(not(feature="ipc"))]
|
||||||
|
pub type SyncModules = (Arc<SyncProvider>, Arc<ManageNetwork>, Arc<ChainNotify>);
|
||||||
|
|
||||||
|
#[cfg(feature="ipc")]
|
||||||
|
mod ipc_deps {
|
||||||
|
pub use ethsync::{SyncClient, NetworkManagerClient, ServiceConfiguration};
|
||||||
|
pub use ethcore::client::ChainNotifyClient;
|
||||||
|
pub use hypervisor::{SYNC_MODULE_ID, BootArgs};
|
||||||
|
pub use nanoipc::{GuardedSocket, NanoSocket, init_client};
|
||||||
|
pub use ipc::IpcSocket;
|
||||||
|
pub use ipc::binary::serialize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(feature="ipc")]
|
||||||
|
pub fn hypervisor() -> Option<Hypervisor> {
|
||||||
|
Some(Hypervisor::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature="ipc"))]
|
#[cfg(not(feature="ipc"))]
|
||||||
pub fn sync(
|
pub fn hypervisor() -> Option<Hypervisor> {
|
||||||
sync_cfg: SyncConfig,
|
None
|
||||||
net_cfg: NetworkConfiguration,
|
}
|
||||||
client: Arc<BlockChainClient>)
|
|
||||||
-> Result<Modules, ethcore::error::Error>
|
#[cfg(feature="ipc")]
|
||||||
|
fn sync_arguments(sync_cfg: SyncConfig, net_cfg: NetworkConfiguration, log_settings: &LogSettings) -> BootArgs {
|
||||||
|
let service_config = ServiceConfiguration {
|
||||||
|
sync: sync_cfg,
|
||||||
|
net: net_cfg,
|
||||||
|
};
|
||||||
|
|
||||||
|
// initialisation payload is passed via stdin
|
||||||
|
let service_payload = serialize(&service_config).expect("Any binary-derived struct is serializable by definition");
|
||||||
|
|
||||||
|
// client service url and logging settings are passed in command line
|
||||||
|
let mut cli_args = Vec::new();
|
||||||
|
cli_args.push("ipc:///tmp/parity-chain.ipc".to_owned());
|
||||||
|
if !log_settings.color { cli_args.push("--no-color".to_owned()); }
|
||||||
|
if let Some(ref init) = log_settings.init {
|
||||||
|
cli_args.push("-l".to_owned());
|
||||||
|
cli_args.push(init.to_owned());
|
||||||
|
}
|
||||||
|
if let Some(ref file) = log_settings.file {
|
||||||
|
cli_args.push("--log-file".to_owned());
|
||||||
|
cli_args.push(file.to_owned());
|
||||||
|
}
|
||||||
|
|
||||||
|
BootArgs::new().stdin(service_payload).cli(cli_args)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature="ipc")]
|
||||||
|
pub fn sync
|
||||||
|
(
|
||||||
|
hypervisor_ref: &mut Option<Hypervisor>,
|
||||||
|
sync_cfg: SyncConfig,
|
||||||
|
net_cfg: NetworkConfiguration,
|
||||||
|
_client: Arc<BlockChainClient>,
|
||||||
|
log_settings: &LogSettings,
|
||||||
|
)
|
||||||
|
-> Result<SyncModules, ethcore::error::Error>
|
||||||
|
{
|
||||||
|
let mut hypervisor = hypervisor_ref.take().expect("There should be hypervisor for ipc configuration");
|
||||||
|
hypervisor = hypervisor.module(SYNC_MODULE_ID, "sync", sync_arguments(sync_cfg, net_cfg, log_settings));
|
||||||
|
|
||||||
|
hypervisor.start();
|
||||||
|
hypervisor.wait_for_startup();
|
||||||
|
|
||||||
|
let sync_client = init_client::<SyncClient<_>>("ipc:///tmp/parity-sync.ipc").unwrap();
|
||||||
|
let notify_client = init_client::<ChainNotifyClient<_>>("ipc:///tmp/parity-sync-notify.ipc").unwrap();
|
||||||
|
let manage_client = init_client::<NetworkManagerClient<_>>("ipc:///tmp/parity-manage-net.ipc").unwrap();
|
||||||
|
|
||||||
|
*hypervisor_ref = Some(hypervisor);
|
||||||
|
Ok((sync_client, manage_client, notify_client))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature="ipc"))]
|
||||||
|
pub fn sync
|
||||||
|
(
|
||||||
|
_hypervisor: &mut Option<Hypervisor>,
|
||||||
|
sync_cfg: SyncConfig,
|
||||||
|
net_cfg: NetworkConfiguration,
|
||||||
|
client: Arc<BlockChainClient>,
|
||||||
|
_log_settings: &LogSettings,
|
||||||
|
)
|
||||||
|
-> Result<SyncModules, ethcore::error::Error>
|
||||||
{
|
{
|
||||||
let eth_sync = try!(EthSync::new(sync_cfg, client, net_cfg).map_err(ethcore::error::Error::Util));
|
let eth_sync = try!(EthSync::new(sync_cfg, client, net_cfg).map_err(ethcore::error::Error::Util));
|
||||||
Ok((eth_sync.clone() as Arc<SyncProvider>, eth_sync.clone() as Arc<ManageNetwork>, eth_sync.clone() as Arc<ChainNotify>))
|
Ok((eth_sync.clone() as Arc<SyncProvider>, eth_sync.clone() as Arc<ManageNetwork>, eth_sync.clone() as Arc<ChainNotify>))
|
||||||
|
@ -26,6 +26,7 @@ extern crate rustc_serialize;
|
|||||||
extern crate docopt;
|
extern crate docopt;
|
||||||
extern crate ethcore;
|
extern crate ethcore;
|
||||||
extern crate ethcore_util as util;
|
extern crate ethcore_util as util;
|
||||||
|
extern crate ethcore_logger;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use hypervisor::{HypervisorServiceClient, SYNC_MODULE_ID, HYPERVISOR_IPC_URL};
|
use hypervisor::{HypervisorServiceClient, SYNC_MODULE_ID, HYPERVISOR_IPC_URL};
|
||||||
@ -33,63 +34,47 @@ use ctrlc::CtrlC;
|
|||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use docopt::Docopt;
|
use docopt::Docopt;
|
||||||
use ethcore::client::{RemoteClient, ChainNotify};
|
use ethcore::client::{RemoteClient, ChainNotify};
|
||||||
use ethsync::{SyncProvider, SyncConfig, EthSync, ManageNetwork, NetworkConfiguration};
|
use ethsync::{SyncProvider, EthSync, ManageNetwork, ServiceConfiguration};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use util::numbers::{U256, H256};
|
|
||||||
use std::str::FromStr;
|
|
||||||
use nanoipc::IpcInterface;
|
use nanoipc::IpcInterface;
|
||||||
use util::sha3::Hashable;
|
|
||||||
|
use ethcore_logger::Settings as LogSettings;
|
||||||
|
use ethcore_logger::setup_log;
|
||||||
|
|
||||||
const USAGE: &'static str = "
|
const USAGE: &'static str = "
|
||||||
Ethcore sync service
|
Ethcore sync service
|
||||||
Usage:
|
Usage:
|
||||||
sync <client-url> <network-id> <listen-address> <nat-enabled> <discovery-enabled> <ideal-peers> <config-path> <allow-non-reserved> [options]
|
sync <client-url> [options]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--public-address IP Public address.
|
-l --logging LOGGING Specify the logging level. Must conform to the same
|
||||||
--boot-nodes LIST List of boot nodes.
|
format as RUST_LOG.
|
||||||
--reserved-nodes LIST List of reserved peers,
|
--log-file FILENAME Specify a filename into which logging should be
|
||||||
--secret HEX Use node key hash
|
directed.
|
||||||
--udp-port UDP port
|
--no-color Don't use terminal color codes in output.
|
||||||
";
|
";
|
||||||
|
|
||||||
#[derive(Debug, RustcDecodable)]
|
#[derive(Debug, RustcDecodable)]
|
||||||
struct Args {
|
struct Args {
|
||||||
arg_network_id: String,
|
|
||||||
arg_listen_address: String,
|
|
||||||
arg_nat_enabled: bool,
|
|
||||||
arg_discovery_enabled: bool,
|
|
||||||
arg_ideal_peers: u32,
|
|
||||||
arg_config_path: String,
|
|
||||||
arg_client_url: String,
|
arg_client_url: String,
|
||||||
arg_allow_non_reserved: bool,
|
flag_logging: Option<String>,
|
||||||
flag_public_address: Option<String>,
|
flag_log_file: Option<String>,
|
||||||
flag_secret: Option<String>,
|
flag_no_color: bool,
|
||||||
flag_boot_nodes: Vec<String>,
|
|
||||||
flag_reserved_nodes: Vec<String>,
|
|
||||||
flag_udp_port: Option<u16>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Args {
|
impl Args {
|
||||||
pub fn into_config(self) -> (SyncConfig, NetworkConfiguration, String) {
|
pub fn log_settings(&self) -> LogSettings {
|
||||||
let mut sync_config = SyncConfig::default();
|
let mut settings = LogSettings::new();
|
||||||
sync_config.network_id = U256::from_str(&self.arg_network_id).unwrap();
|
if self.flag_no_color || cfg!(windows) {
|
||||||
|
settings = settings.no_color();
|
||||||
let network_config = NetworkConfiguration {
|
}
|
||||||
udp_port: self.flag_udp_port,
|
if let Some(ref init) = self.flag_logging {
|
||||||
nat_enabled: self.arg_nat_enabled,
|
settings = settings.init(init.to_owned())
|
||||||
boot_nodes: self.flag_boot_nodes,
|
}
|
||||||
listen_address: Some(self.arg_listen_address),
|
if let Some(ref file) = self.flag_log_file {
|
||||||
public_address: self.flag_public_address,
|
settings = settings.file(file.to_owned())
|
||||||
use_secret: self.flag_secret.as_ref().map(|s| H256::from_str(s).unwrap_or_else(|_| s.sha3())),
|
}
|
||||||
discovery_enabled: self.arg_discovery_enabled,
|
settings
|
||||||
ideal_peers: self.arg_ideal_peers,
|
|
||||||
config_path: Some(self.arg_config_path),
|
|
||||||
reserved_nodes: self.flag_reserved_nodes,
|
|
||||||
allow_non_reserved: self.arg_allow_non_reserved,
|
|
||||||
};
|
|
||||||
|
|
||||||
(sync_config, network_config, self.arg_client_url)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,16 +91,24 @@ fn run_service<T: ?Sized + Send + Sync + 'static>(addr: &str, stop_guard: Arc<At
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
use std::io::{self, Read};
|
||||||
|
|
||||||
let args: Args = Docopt::new(USAGE)
|
let args: Args = Docopt::new(USAGE)
|
||||||
.and_then(|d| d.decode())
|
.and_then(|d| d.decode())
|
||||||
.unwrap_or_else(|e| e.exit());
|
.unwrap_or_else(|e| e.exit());
|
||||||
let (sync_config, network_config, client_url) = args.into_config();
|
|
||||||
let remote_client = nanoipc::init_client::<RemoteClient<_>>(&client_url).unwrap();
|
setup_log(&args.log_settings());
|
||||||
|
|
||||||
|
let mut buffer = Vec::new();
|
||||||
|
io::stdin().read_to_end(&mut buffer).expect("Failed to read initialisation payload");
|
||||||
|
let service_config = ipc::binary::deserialize::<ServiceConfiguration>(&buffer).expect("Failed deserializing initialisation payload");
|
||||||
|
|
||||||
|
let remote_client = nanoipc::init_client::<RemoteClient<_>>(&args.arg_client_url).unwrap();
|
||||||
|
|
||||||
remote_client.handshake().unwrap();
|
remote_client.handshake().unwrap();
|
||||||
|
|
||||||
let stop = Arc::new(AtomicBool::new(false));
|
let stop = Arc::new(AtomicBool::new(false));
|
||||||
let sync = EthSync::new(sync_config, remote_client.service().clone(), network_config).unwrap();
|
let sync = EthSync::new(service_config.sync, remote_client.service().clone(), service_config.net).unwrap();
|
||||||
|
|
||||||
run_service("ipc:///tmp/parity-sync.ipc", stop.clone(), sync.clone() as Arc<SyncProvider>);
|
run_service("ipc:///tmp/parity-sync.ipc", stop.clone(), sync.clone() as Arc<SyncProvider>);
|
||||||
run_service("ipc:///tmp/parity-manage-net.ipc", stop.clone(), sync.clone() as Arc<ManageNetwork>);
|
run_service("ipc:///tmp/parity-manage-net.ipc", stop.clone(), sync.clone() as Arc<ManageNetwork>);
|
||||||
|
@ -32,6 +32,7 @@ use parking_lot::RwLock;
|
|||||||
pub const ETH_PROTOCOL: &'static str = "eth";
|
pub const ETH_PROTOCOL: &'static str = "eth";
|
||||||
|
|
||||||
/// Sync configuration
|
/// Sync configuration
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
pub struct SyncConfig {
|
pub struct SyncConfig {
|
||||||
/// Max blocks to download ahead
|
/// Max blocks to download ahead
|
||||||
pub max_download_ahead_blocks: usize,
|
pub max_download_ahead_blocks: usize,
|
||||||
@ -272,3 +273,9 @@ impl From<BasicNetworkConfiguration> for NetworkConfiguration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Binary, Clone)]
|
||||||
|
pub struct ServiceConfiguration {
|
||||||
|
pub sync: SyncConfig,
|
||||||
|
pub net: NetworkConfiguration,
|
||||||
|
}
|
||||||
|
@ -87,6 +87,7 @@ mod api {
|
|||||||
include!(concat!(env!("OUT_DIR"), "/api.ipc.rs"));
|
include!(concat!(env!("OUT_DIR"), "/api.ipc.rs"));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use api::{EthSync, SyncProvider, ManageNetwork, SyncConfig, NetworkConfiguration};
|
pub use api::{EthSync, SyncProvider, SyncClient, NetworkManagerClient, ManageNetwork, SyncConfig,
|
||||||
|
NetworkConfiguration, ServiceConfiguration};
|
||||||
pub use chain::{SyncStatus, SyncState};
|
pub use chain::{SyncStatus, SyncState};
|
||||||
|
|
||||||
|
@ -15,4 +15,5 @@
|
|||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
pub mod helpers;
|
pub mod helpers;
|
||||||
mod chain;
|
mod chain;
|
||||||
|
mod rpc;
|
||||||
|
29
sync/src/tests/rpc.rs
Normal file
29
sync/src/tests/rpc.rs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// 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 super::super::NetworkConfiguration;
|
||||||
|
use util::NetworkConfiguration as BasicNetworkConfiguration;
|
||||||
|
use std::convert::From;
|
||||||
|
use ipc::binary::{serialize, deserialize};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn network_settings_serialize() {
|
||||||
|
let net_cfg = NetworkConfiguration::from(BasicNetworkConfiguration::new_local());
|
||||||
|
let serialized = serialize(&net_cfg).unwrap();
|
||||||
|
let deserialized = deserialize::<NetworkConfiguration>(&serialized).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(net_cfg.udp_port, deserialized.udp_port);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user