From 32a4a060d69a37bc5b8310e0e9eb17772806769f Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Sat, 9 Jul 2016 17:18:34 +0200 Subject: [PATCH] bringing hypervisor as a crate in ipc dir (#1565) * resurrecting hypervisor in ipc namespace * get rid of the quotes * target: hypervisor --- Cargo.lock | 14 ++++ Cargo.toml | 1 + build.rs | 24 ------- ipc/hypervisor/Cargo.toml | 19 +++++ ipc/hypervisor/build.rs | 43 +++++++++++ .../mod.rs => ipc/hypervisor/src/lib.rs | 72 ++++++++++++------- .../hypervisor/src}/service.rs | 0 .../hypervisor/src}/service.rs.in | 4 +- parity/main.rs | 5 +- 9 files changed, 129 insertions(+), 53 deletions(-) create mode 100644 ipc/hypervisor/Cargo.toml create mode 100644 ipc/hypervisor/build.rs rename parity/hypervisor/mod.rs => ipc/hypervisor/src/lib.rs (69%) rename {parity/hypervisor => ipc/hypervisor/src}/service.rs (100%) rename {parity/hypervisor => ipc/hypervisor/src}/service.rs.in (95%) 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);