1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
use crate::{chain, client::Client, config::ValidatorConfig, prelude::*};
use abscissa::Command;
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc,
};
use std::{process, thread, time};
#[derive(Command, Debug, Options)]
pub struct StartCommand {
#[options(short = "c", long = "config", help = "path to tmkms.toml")]
pub config: Option<String>,
#[options(short = "v", long = "verbose", help = "enable verbose debug logging")]
pub verbose: bool,
}
impl Default for StartCommand {
fn default() -> Self {
Self {
config: None,
verbose: false,
}
}
}
impl Runnable for StartCommand {
fn run(&self) {
info!(
"{} {} starting up...",
env!("CARGO_PKG_NAME"),
env!("CARGO_PKG_VERSION")
);
let config = app_config();
chain::load_config(&config).unwrap_or_else(|e| {
status_err!("error loading configuration: {}", e);
process::exit(1);
});
let should_term = Arc::new(AtomicBool::new(false));
let validator_clients = spawn_validator_clients(&config.validator, &should_term);
let catch_signals = [signal_hook::SIGTERM, signal_hook::SIGINT];
for sig in catch_signals.iter() {
signal_hook::flag::register(*sig, Arc::clone(&should_term)).unwrap_or_else(|e| {
status_err!("couldn't register signal hook: {}", e);
process::exit(1);
});
}
while !should_term.load(Ordering::Relaxed) {
thread::sleep(time::Duration::from_millis(100));
}
info!("Waiting for client threads to stop...");
for client in validator_clients {
client.join();
}
}
}
fn spawn_validator_clients(
config: &[ValidatorConfig],
should_term: &Arc<AtomicBool>,
) -> Vec<Client> {
config
.iter()
.map(|validator| Client::spawn(validator.clone(), Arc::clone(should_term)))
.collect()
}