107 lines
3.1 KiB
Rust
107 lines
3.1 KiB
Rust
mod config;
|
|
|
|
use crate::server;
|
|
use crate::signals;
|
|
use crate::stdin;
|
|
use clap::Args;
|
|
use config::Config;
|
|
use std::path::PathBuf;
|
|
use std::sync::{Arc, Mutex};
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
#[derive(Args)]
|
|
pub struct RunCli {
|
|
#[command(flatten)]
|
|
pub args: RunArgs,
|
|
|
|
/// 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,
|
|
}
|
|
|
|
#[derive(Args, Serialize, Deserialize, Clone)]
|
|
pub struct RunArgs {
|
|
/// Server jar to execute
|
|
#[arg(long, value_name = "JAR_PATH")]
|
|
#[serde(skip_serializing_if = "::std::option::Option::is_none")]
|
|
pub jar: Option<PathBuf>,
|
|
|
|
/// Java command to run the server jar with
|
|
#[arg(long, value_name = "JAVA_CMD")]
|
|
#[serde(skip_serializing_if = "::std::option::Option::is_none")]
|
|
pub java: Option<String>,
|
|
|
|
/// XMS value in megabytes for the server instance
|
|
#[arg(long)]
|
|
#[serde(skip_serializing_if = "::std::option::Option::is_none")]
|
|
pub xms: Option<u64>,
|
|
|
|
/// XMX value in megabytes for the server instance
|
|
#[arg(long)]
|
|
#[serde(skip_serializing_if = "::std::option::Option::is_none")]
|
|
pub xmx: Option<u64>,
|
|
}
|
|
|
|
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 RunCli {
|
|
pub fn run(&self, cli: &super::Cli, global: &super::Config) -> crate::Result<()> {
|
|
let config: Config = cli.config(&self.args)?;
|
|
println!("{:?}", config);
|
|
|
|
let (_, mut signals) = signals::install_signal_handlers()?;
|
|
|
|
let mut cmd = server::ServerCommand::new(global.server, &global.server_version)
|
|
.java(&config.java)
|
|
.jar(config.jar.clone())
|
|
.config(global.config.clone())
|
|
.world(global.world.clone())
|
|
.backup(global.backup.clone())
|
|
.managers(global.layers.clone())
|
|
.xms(config.xms)
|
|
.xmx(config.xmx);
|
|
cmd.canonicalize()?;
|
|
|
|
if self.dry {
|
|
print!("{}", cmd);
|
|
|
|
return Ok(());
|
|
}
|
|
|
|
let counter = Arc::new(Mutex::new(cmd.spawn()?));
|
|
|
|
if !global.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
|
|
Ok(signals::handle_signals(&mut signals, counter)?)
|
|
}
|
|
}
|