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>) { 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) } }