alex/src/cli/run.rs

95 lines
2.7 KiB
Rust

use crate::cli::Cli;
use crate::server;
use crate::signals;
use crate::stdin;
use clap::Args;
use std::io;
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
#[derive(Args)]
pub struct RunArgs {
/// Server jar to execute
#[arg(
long,
value_name = "JAR_PATH",
default_value = "server.jar",
env = "ALEX_JAR"
)]
pub jar: PathBuf,
/// Java command to run the server jar with
#[arg(long, value_name = "JAVA_CMD", default_value_t = String::from("java"), env = "ALEX_JAVA")]
pub java: String,
/// XMS value in megabytes for the server instance
#[arg(long, default_value_t = 1024, env = "ALEX_XMS")]
pub xms: u64,
/// XMX value in megabytes for the server instance
#[arg(long, default_value_t = 2048, env = "ALEX_XMX")]
pub xmx: u64,
/// Don't actually run the server, but simply output the server configuration that would have
/// been ran
#[arg(short, long, default_value_t = false)]
pub dry: bool,
}
fn backups_thread(counter: Arc<Mutex<server::ServerProcess>>) {
loop {
let next_scheduled_time = {
let server = counter.lock().unwrap();
server.backups.next_scheduled_time().unwrap()
};
let now = chrono::offset::Utc::now();
if next_scheduled_time > now {
std::thread::sleep((next_scheduled_time - now).to_std().unwrap());
}
{
let mut server = counter.lock().unwrap();
// We explicitely ignore the error here, as we don't want the thread to fail
let _ = server.backup();
}
}
}
impl RunArgs {
pub fn run(&self, cli: &Cli) -> io::Result<()> {
let (_, mut signals) = signals::install_signal_handlers()?;
let mut cmd = server::ServerCommand::new(cli.server, &cli.server_version)
.java(&self.java)
.jar(self.jar.clone())
.config(cli.config.clone())
.world(cli.world.clone())
.backup(cli.backup.clone())
.managers(cli.layers.clone())
.xms(self.xms)
.xmx(self.xmx);
cmd.canonicalize()?;
if self.dry {
print!("{}", cmd);
return Ok(());
}
let counter = Arc::new(Mutex::new(cmd.spawn()?));
if !cli.layers.is_empty() {
let clone = Arc::clone(&counter);
std::thread::spawn(move || backups_thread(clone));
}
// Spawn thread that handles the main stdin loop
let clone = Arc::clone(&counter);
std::thread::spawn(move || stdin::handle_stdin(clone));
// Signal handler loop exits the process when necessary
signals::handle_signals(&mut signals, counter)
}
}