diff --git a/Cargo.lock b/Cargo.lock
index eae4823f6..ffb4fc12b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -13,6 +13,7 @@ dependencies = [
"ethcore-devtools 1.3.0",
"ethcore-ipc 1.3.0",
"ethcore-ipc-codegen 1.3.0",
+ "ethcore-ipc-hypervisor 1.2.0",
"ethcore-ipc-nano 1.3.0",
"ethcore-rpc 1.3.0",
"ethcore-signer 1.3.0",
@@ -315,6 +316,19 @@ dependencies = [
"syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "ethcore-ipc-hypervisor"
+version = "1.2.0"
+dependencies = [
+ "ethcore-ipc 1.3.0",
+ "ethcore-ipc-codegen 1.3.0",
+ "ethcore-ipc-nano 1.3.0",
+ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git)",
+ "semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "ethcore-ipc-nano"
version = "1.3.0"
diff --git a/Cargo.toml b/Cargo.toml
index e49c3efc5..02b7070f7 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -33,6 +33,7 @@ ethcore-dapps = { path = "dapps", optional = true }
semver = "0.2"
ethcore-ipc-nano = { path = "ipc/nano" }
ethcore-ipc = { path = "ipc/rpc" }
+ethcore-ipc-hypervisor = { path = "ipc/hypervisor" }
json-ipc-server = { git = "https://github.com/ethcore/json-ipc-server.git" }
ansi_term = "0.7"
diff --git a/build.rs b/build.rs
index 25764f4be..41b9a1b3e 100644
--- a/build.rs
+++ b/build.rs
@@ -15,35 +15,11 @@
// along with Parity. If not, see .
extern crate rustc_version;
-extern crate syntex;
-extern crate ethcore_ipc_codegen as codegen;
-use std::env;
-use std::path::Path;
use rustc_version::{version_meta, Channel};
fn main() {
if let Channel::Nightly = version_meta().channel {
println!("cargo:rustc-cfg=nightly");
}
-
- let out_dir = env::var_os("OUT_DIR").unwrap();
-
- // ipc pass
- {
- let src = Path::new("parity/hypervisor/service.rs.in");
- let dst = Path::new(&out_dir).join("hypervisor_service_ipc.rs");
- let mut registry = syntex::Registry::new();
- codegen::register(&mut registry);
- registry.expand("", &src, &dst).unwrap();
- }
-
- // serialization pass
- {
- let src = Path::new(&out_dir).join("hypervisor_service_ipc.rs");
- let dst = Path::new(&out_dir).join("hypervisor_service_cg.rs");
- let mut registry = syntex::Registry::new();
- codegen::register(&mut registry);
- registry.expand("", &src, &dst).unwrap();
- }
}
diff --git a/ipc/hypervisor/Cargo.toml b/ipc/hypervisor/Cargo.toml
new file mode 100644
index 000000000..54edac7ec
--- /dev/null
+++ b/ipc/hypervisor/Cargo.toml
@@ -0,0 +1,19 @@
+[package]
+name = "ethcore-ipc-hypervisor"
+version = "1.2.0"
+authors = ["Nikolay Volf "]
+license = "GPL-3.0"
+build = "build.rs"
+
+[features]
+
+[dependencies]
+ethcore-ipc = { path = "../rpc" }
+nanomsg = { git = "https://github.com/ethcore/nanomsg.rs.git" }
+ethcore-ipc-nano = { path = "../nano" }
+semver = "0.2"
+log = "0.3"
+
+[build-dependencies]
+syntex = "*"
+ethcore-ipc-codegen = { path = "../codegen" }
diff --git a/ipc/hypervisor/build.rs b/ipc/hypervisor/build.rs
new file mode 100644
index 000000000..75ccd2e8c
--- /dev/null
+++ b/ipc/hypervisor/build.rs
@@ -0,0 +1,43 @@
+// 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 .
+
+extern crate syntex;
+extern crate ethcore_ipc_codegen as codegen;
+
+use std::env;
+use std::path::Path;
+
+fn main() {
+ let out_dir = env::var_os("OUT_DIR").unwrap();
+
+ // ipc pass
+ {
+ let src = Path::new("src/service.rs.in");
+ let dst = Path::new(&out_dir).join("hypervisor_service_ipc.rs");
+ let mut registry = syntex::Registry::new();
+ codegen::register(&mut registry);
+ registry.expand("", &src, &dst).unwrap();
+ }
+
+ // serialization pass
+ {
+ let src = Path::new(&out_dir).join("hypervisor_service_ipc.rs");
+ let dst = Path::new(&out_dir).join("hypervisor_service_cg.rs");
+ let mut registry = syntex::Registry::new();
+ codegen::register(&mut registry);
+ registry.expand("", &src, &dst).unwrap();
+ }
+}
diff --git a/parity/hypervisor/mod.rs b/ipc/hypervisor/src/lib.rs
similarity index 69%
rename from parity/hypervisor/mod.rs
rename to ipc/hypervisor/src/lib.rs
index 501594d1f..69bbbffae 100644
--- a/parity/hypervisor/mod.rs
+++ b/ipc/hypervisor/src/lib.rs
@@ -16,57 +16,58 @@
//! Parity interprocess hypervisor module
-// while not included in binary
-#![allow(dead_code)]
#![cfg_attr(feature="dev", allow(used_underscore_binding))]
-use nanoipc;
-use std::sync::{Arc,RwLock};
-use hypervisor::service::*;
-use std::process::{Command,Child};
-use std::collections::HashMap;
+extern crate ethcore_ipc as ipc;
+extern crate ethcore_ipc_nano as nanoipc;
+extern crate semver;
+#[macro_use] extern crate log;
pub mod service;
/// Default value for hypervisor ipc listener
pub const HYPERVISOR_IPC_URL: &'static str = "ipc:///tmp/parity-internal-hyper-status.ipc";
+use std::sync::{Arc,RwLock};
+use service::{HypervisorService, IpcModuleId};
+use std::process::{Command,Child};
+use std::collections::HashMap;
+
+pub use service::{HypervisorServiceClient, CLIENT_MODULE_ID};
+
type BinaryId = &'static str;
-const BLOCKCHAIN_DB_BINARY: BinaryId = "blockchain";
+
+const CLIENT_BINARY: BinaryId = "client";
pub struct Hypervisor {
ipc_addr: String,
service: Arc,
ipc_worker: RwLock>,
processes: RwLock>,
-}
-
-impl Default for Hypervisor {
- fn default() -> Self {
- Hypervisor::new()
- }
+ db_path: String,
}
impl Hypervisor {
/// initializes the Hypervisor service with the open ipc socket for incoming clients
- pub fn new() -> Hypervisor {
- Hypervisor::with_url(HYPERVISOR_IPC_URL)
+ pub fn new(db_path: &str) -> Hypervisor {
+ Hypervisor::with_url(db_path, HYPERVISOR_IPC_URL)
}
/// Starts on the specified address for ipc listener
- fn with_url(addr: &str) -> Hypervisor{
- Hypervisor::with_url_and_service(addr, HypervisorService::new())
+ fn with_url(db_path: &str, addr: &str) -> Hypervisor{
+ Hypervisor::with_url_and_service(db_path, addr, HypervisorService::new())
}
/// Starts with the specified address for the ipc listener and
/// the specified list of modules in form of created service
- fn with_url_and_service(addr: &str, service: Arc) -> Hypervisor {
+ fn with_url_and_service(db_path: &str, addr: &str, service: Arc) -> Hypervisor {
let worker = nanoipc::Worker::new(&service);
Hypervisor{
ipc_addr: addr.to_owned(),
service: service,
ipc_worker: RwLock::new(worker),
processes: RwLock::new(HashMap::new()),
+ db_path: db_path.to_owned(),
}
}
@@ -74,14 +75,14 @@ impl Hypervisor {
/// we match binaries
fn match_module(module_id: &IpcModuleId) -> Option {
match *module_id {
- BLOCKCHAIN_MODULE_ID => Some(BLOCKCHAIN_DB_BINARY),
+ CLIENT_MODULE_ID => Some(CLIENT_BINARY),
// none means the module is inside the main binary
_ => None
}
}
/// Creates IPC listener and starts all binaries
- fn start(&self) {
+ pub fn start(&self) {
let mut worker = self.ipc_worker.write().unwrap();
worker.add_reqrep(&self.ipc_addr).unwrap_or_else(|e| panic!("Hypervisor ipc worker can not start - critical! ({:?})", e));
@@ -102,8 +103,13 @@ impl Hypervisor {
return;
}
}
- let child = Command::new(binary_id).spawn().unwrap_or_else(
- |e| panic!("Hypervisor cannot start binary: {}", e));
+
+ let mut executable_path = std::env::current_exe().unwrap();
+ executable_path.pop();
+ executable_path.push(binary_id);
+
+ let child = Command::new(&executable_path.to_str().unwrap()).arg(&self.db_path).spawn().unwrap_or_else(
+ |e| panic!("Hypervisor cannot start binary ({:?}): {}", executable_path, e));
processes.insert(binary_id, child);
});
}
@@ -120,6 +126,22 @@ impl Hypervisor {
worker.poll()
}
}
+
+ pub fn shutdown(&self, wait_time: Option) {
+ if wait_time.is_some() { std::thread::sleep(wait_time.unwrap()) }
+
+ let mut childs = self.processes.write().unwrap();
+ for (ref mut binary, ref mut child) in childs.iter_mut() {
+ trace!(target: "hypervisor", "HYPERVISOR: Stopping process module: {}", binary);
+ child.kill().unwrap();
+ }
+ }
+}
+
+impl Drop for Hypervisor {
+ fn drop(&mut self) {
+ self.shutdown(Some(std::time::Duration::new(1, 0)));
+ }
}
#[cfg(test)]
@@ -135,7 +157,7 @@ mod tests {
let url = "ipc:///tmp/test-parity-hypervisor-10.ipc";
let test_module_id = 8080u64;
- let hypervisor = Hypervisor::with_url_and_service(url, HypervisorService::with_modules(vec![test_module_id]));
+ let hypervisor = Hypervisor::with_url_and_service("", url, HypervisorService::with_modules(vec![test_module_id]));
assert_eq!(false, hypervisor.modules_ready());
}
@@ -155,7 +177,7 @@ mod tests {
client.module_ready(test_module_id);
});
- let hypervisor = Hypervisor::with_url_and_service(url, HypervisorService::with_modules(vec![test_module_id]));
+ let hypervisor = Hypervisor::with_url_and_service("", url, HypervisorService::with_modules(vec![test_module_id]));
hypervisor.start();
hypervisor_ready_local.store(true, Ordering::Relaxed);
hypervisor.wait_for_startup();
diff --git a/parity/hypervisor/service.rs b/ipc/hypervisor/src/service.rs
similarity index 100%
rename from parity/hypervisor/service.rs
rename to ipc/hypervisor/src/service.rs
diff --git a/parity/hypervisor/service.rs.in b/ipc/hypervisor/src/service.rs.in
similarity index 95%
rename from parity/hypervisor/service.rs.in
rename to ipc/hypervisor/src/service.rs.in
index 134194603..2b626d769 100644
--- a/parity/hypervisor/service.rs.in
+++ b/ipc/hypervisor/src/service.rs.in
@@ -24,7 +24,7 @@ use std::collections::VecDeque;
pub type IpcModuleId = u64;
/// Blockhain database module id
-pub const BLOCKCHAIN_MODULE_ID: IpcModuleId = 2000;
+pub const CLIENT_MODULE_ID: IpcModuleId = 2000;
/// IPC service that handles module management
pub struct HypervisorService {
@@ -43,7 +43,7 @@ impl HypervisorService {
impl HypervisorService {
/// New service with the default list of modules
pub fn new() -> Arc {
- HypervisorService::with_modules(vec![])
+ HypervisorService::with_modules(vec![CLIENT_MODULE_ID])
}
/// New service with list of modules that will report for being ready
diff --git a/parity/main.rs b/parity/main.rs
index a4530c830..a4f62e81c 100644
--- a/parity/main.rs
+++ b/parity/main.rs
@@ -44,6 +44,8 @@ extern crate ethcore_ipc_nano as nanoipc;
extern crate hyper; // for price_info.rs
extern crate json_ipc_server as jsonipc;
+extern crate ethcore_ipc_hypervisor as hypervisor;
+
#[cfg(feature = "rpc")]
extern crate ethcore_rpc;
@@ -57,7 +59,6 @@ extern crate ethcore_signer;
mod die;
mod price_info;
mod upgrade;
-mod hypervisor;
mod setup_log;
mod rpc;
mod dapps;
@@ -212,7 +213,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig)
// Check fork settings.
if conf.policy() != Policy::None {
- warn!("Value given for --policy, yet no proposed forks exist. Ignoring.");
+ warn!("Value given for --policy, yet no proposed forks exist. Ignoring.");
}
let net_settings = conf.net_settings(&spec);