// 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 . use std::sync::{RwLock,Arc}; use ipc::IpcConfig; use std::collections::HashMap; use nanoipc; pub type IpcModuleId = u64; /// Blockhain database module id pub const CLIENT_MODULE_ID: IpcModuleId = 2000; /// Sync module id pub const SYNC_MODULE_ID: IpcModuleId = 2100; /// IPC service that handles module management pub struct HypervisorService { modules: RwLock>, } #[derive(Default)] pub struct ModuleState { started: bool, control_url: String, shutdown: bool, } #[derive(Ipc)] pub trait ControlService { fn shutdown(&self) -> bool; } #[derive(Ipc)] impl HypervisorService { // return type for making method synchronous fn module_ready(&self, module_id: u64, control_url: String) -> bool { let mut modules = self.modules.write().unwrap(); modules.get_mut(&module_id).map(|mut module| { module.started = true; module.control_url = control_url; }); trace!(target: "hypervisor", "Module ready: {}", module_id); true } // return type for making method synchronous fn module_shutdown(&self, module_id: u64) -> bool { let mut modules = self.modules.write().unwrap(); modules.get_mut(&module_id).map(|mut module| { module.shutdown = true; }); trace!(target: "hypervisor", "Module shutdown: {}", module_id); true } } impl HypervisorService { /// New service with the default list of modules pub fn new() -> Arc { HypervisorService::with_modules(vec![]) } /// New service with list of modules that will report for being ready pub fn with_modules(module_ids: Vec) -> Arc { let mut modules = HashMap::new(); for module_id in module_ids { modules.insert(module_id, ModuleState::default()); } Arc::new(HypervisorService { modules: RwLock::new(modules), }) } /// Add the module to the check-list pub fn add_module(&self, module_id: IpcModuleId) { self.modules.write().unwrap().insert(module_id, ModuleState::default()); } /// Number of modules still being waited for check-in pub fn unchecked_count(&self) -> usize { self.modules.read().unwrap().iter().filter(|&(_, module)| !module.started).count() } /// List of all modules within this service pub fn module_ids(&self) -> Vec { self.modules.read().unwrap().iter().map(|(module_id, _)| module_id).cloned().collect() } /// Number of modules started and running pub fn running_count(&self) -> usize { self.modules.read().unwrap().iter().filter(|&(_, module)| module.started && !module.shutdown).count() } pub fn send_shutdown(&self, module_id: IpcModuleId) { let modules = self.modules.read().unwrap(); modules.get(&module_id).map(|module| { trace!(target: "hypervisor", "Sending shutdown to {}({})", module_id, &module.control_url); let client = nanoipc::init_client::>(&module.control_url).unwrap(); client.shutdown(); trace!(target: "hypervisor", "Sent shutdown to {}", module_id); }); } } impl ::ipc::IpcConfig for HypervisorService {} impl ::ipc::IpcConfig for ControlService {}