alex/src/server/process.rs

120 lines
3.1 KiB
Rust

use crate::server::BackupManager;
use crate::server::ServerType;
use flate2::write::GzEncoder;
use flate2::Compression;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::process::Child;
pub struct ServerProcess {
type_: ServerType,
version: String,
config_dir: PathBuf,
world_dir: PathBuf,
backup_dir: PathBuf,
max_backups: u64,
child: Child,
backups: BackupManager,
}
impl ServerProcess {
pub fn new(
type_: ServerType,
version: String,
config_dir: PathBuf,
world_dir: PathBuf,
backup_dir: PathBuf,
max_backups: u64,
child: Child,
) -> ServerProcess {
let backup_manager = BackupManager::open(
backup_dir.clone(),
config_dir.clone(),
world_dir.clone(),
max_backups,
);
ServerProcess {
type_,
version,
config_dir,
world_dir,
backup_dir,
max_backups,
child,
backups: backup_manager,
}
}
pub fn send_command(&mut self, cmd: &str) -> std::io::Result<()> {
match cmd.trim() {
"stop" | "exit" => self.stop()?,
"backup" => self.backup()?,
s => self.custom(s)?,
}
Ok(())
}
fn custom(&mut self, cmd: &str) -> std::io::Result<()> {
let mut stdin = self.child.stdin.as_ref().unwrap();
stdin.write_all(format!("{}\n", cmd.trim()).as_bytes())?;
stdin.flush()?;
Ok(())
}
pub fn stop(&mut self) -> std::io::Result<()> {
self.custom("stop")?;
self.child.wait()?;
Ok(())
}
pub fn kill(&mut self) -> std::io::Result<()> {
self.child.kill()
}
/// Perform a backup by disabling the server's save feature and flushing its data, before
/// creating an archive file.
pub fn backup(&mut self) -> std::io::Result<()> {
self.custom("say backing up server")?;
// Make sure the server isn't modifying the files during the backup
self.custom("save-off")?;
self.custom("save-all")?;
// TODO implement a better mechanism
// We wait some time to (hopefully) ensure the save-all call has completed
std::thread::sleep(std::time::Duration::from_secs(10));
let start_time = chrono::offset::Local::now();
let res = self.backups.create_archive();
if res.is_ok() {
self.backups.remove_old_backups()?;
}
// The server's save feature needs to be enabled again even if the archive failed to create
self.custom("save-on")?;
let duration = chrono::offset::Local::now() - start_time;
let duration_str = format!(
"{}m{}s",
duration.num_seconds() / 60,
duration.num_seconds() % 60
);
if res.is_ok() {
self.custom(&format!("say server backed up in {}", duration_str))?;
} else {
self.custom(&format!(
"an error occured after {} while backing up the server",
duration_str
))?;
}
res
}
}