lighthouse/beacon_node/src/run.rs

122 lines
3.7 KiB
Rust
Raw Normal View History

use client::{
2019-06-07 23:44:27 +00:00
error, notifier, BeaconChainTypes, Client, ClientConfig, InitialiseBeaconChain,
TestnetDiskBeaconChainTypes, TestnetMemoryBeaconChainTypes,
};
use futures::sync::oneshot;
use futures::Future;
2019-06-07 23:44:27 +00:00
use slog::{error, info};
use std::cell::RefCell;
2019-06-07 23:44:27 +00:00
use std::path::Path;
use std::path::PathBuf;
use store::{DiskStore, MemoryStore};
use tokio::runtime::Builder;
use tokio::runtime::Runtime;
use tokio::runtime::TaskExecutor;
2019-03-26 23:36:20 +00:00
use tokio_timer::clock::Clock;
2019-03-19 11:53:51 +00:00
pub fn run_beacon_node(config: ClientConfig, log: &slog::Logger) -> error::Result<()> {
let runtime = Builder::new()
.name_prefix("main-")
2019-03-26 23:36:20 +00:00
.clock(Clock::system())
.build()
.map_err(|e| format!("{:?}", e))?;
let executor = runtime.executor();
2019-06-07 23:44:27 +00:00
let db_path: PathBuf = config
.db_path()
.ok_or_else::<error::Error, _>(|| "Unable to access database path".into())?;
let db_type = &config.db_type;
let spec_constants = &config.spec_constants;
2019-06-07 23:44:27 +00:00
let other_config = config.clone();
let result = match (db_type.as_str(), spec_constants.as_str()) {
2019-06-07 23:44:27 +00:00
("disk", "testnet") => {
run::<TestnetDiskBeaconChainTypes>(&db_path, config, executor, runtime, log)
}
2019-06-07 23:44:27 +00:00
("memory", "testnet") => {
run::<TestnetMemoryBeaconChainTypes>(&db_path, config, executor, runtime, log)
}
2019-06-07 23:44:27 +00:00
(db_type, spec) => {
error!(log, "Unknown runtime configuration"; "spec" => spec, "db_type" => db_type);
Err("Unknown specification and/or db_type.".into())
}
};
if result.is_ok() {
info!(
log,
"Started beacon node";
"p2p_listen_addresses" => format!("{:?}", &other_config.network.listen_addresses()),
"data_dir" => format!("{:?}", other_config.data_dir()),
"spec_constants" => &other_config.spec_constants,
2019-06-07 23:44:27 +00:00
"db_type" => &other_config.db_type,
);
}
2019-06-07 23:44:27 +00:00
result
}
2019-06-07 23:44:27 +00:00
pub fn run<T>(
db_path: &Path,
config: ClientConfig,
executor: TaskExecutor,
mut runtime: Runtime,
log: &slog::Logger,
2019-06-07 23:44:27 +00:00
) -> error::Result<()>
where
T: BeaconChainTypes + InitialiseBeaconChain<T> + Send + Sync + 'static + Clone,
T::Store: OpenDatabase,
{
let store = T::Store::open_database(&db_path)?;
let client: Client<T> = Client::new(config, store, log.clone(), &executor)?;
// run service until ctrl-c
let (ctrlc_send, ctrlc_oneshot) = oneshot::channel();
let ctrlc_send_c = RefCell::new(Some(ctrlc_send));
ctrlc::set_handler(move || {
if let Some(ctrlc_send) = ctrlc_send_c.try_borrow_mut().unwrap().take() {
ctrlc_send.send(()).expect("Error sending ctrl-c message");
}
2019-03-19 11:53:51 +00:00
})
.map_err(|e| format!("Could not set ctrlc hander: {:?}", e))?;
let (exit_signal, exit) = exit_future::signal();
notifier::run(&client, executor, exit);
2019-03-19 11:53:51 +00:00
runtime
.block_on(ctrlc_oneshot)
2019-03-19 11:53:51 +00:00
.map_err(|e| format!("Ctrlc oneshot failed: {:?}", e))?;
// perform global shutdown operations.
info!(log, "Shutting down..");
exit_signal.fire();
2019-03-12 06:28:11 +00:00
// shutdown the client
// client.exit_signal.fire();
drop(client);
runtime.shutdown_on_idle().wait().unwrap();
Ok(())
}
2019-06-07 23:44:27 +00:00
/// A convenience trait, providing a method to open a database.
///
/// Panics if unable to open the database.
pub trait OpenDatabase: Sized {
fn open_database(path: &Path) -> error::Result<Self>;
}
impl OpenDatabase for MemoryStore {
fn open_database(_path: &Path) -> error::Result<Self> {
Ok(MemoryStore::open())
}
}
impl OpenDatabase for DiskStore {
fn open_database(path: &Path) -> error::Result<Self> {
DiskStore::open(path).map_err(|e| format!("Unable to open database: {:?}", e).into())
}
}