Initial draft
This commit is contained in:
55
src/app.rs
Normal file
55
src/app.rs
Normal file
@ -0,0 +1,55 @@
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::thread::sleep;
|
||||
use std::time::Duration;
|
||||
use crate::config::Config;
|
||||
|
||||
pub fn move_file_to_dir(watch_path_string: &String, filename: &String, move_path_string: &String) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let move_path = Path::new(move_path_string);
|
||||
let watch_path = Path::new(watch_path_string);
|
||||
let file_path = watch_path.join(Path::new(filename));
|
||||
let mut moved_file_path = move_path.join(filename);
|
||||
|
||||
if !fs::exists(move_path)? {
|
||||
info!("Creating directory {}", move_path_string);
|
||||
fs::create_dir(move_path)?;
|
||||
}
|
||||
|
||||
if fs::exists(&moved_file_path)? {
|
||||
moved_file_path.set_file_name(format!("{}.2", filename));
|
||||
}
|
||||
|
||||
fs::copy(&file_path, &moved_file_path)?;
|
||||
fs::remove_file(&file_path)?;
|
||||
|
||||
info!("Moved file to {}", &moved_file_path.display());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn restart_server() {
|
||||
|
||||
}
|
||||
|
||||
pub fn watch_files(config: Config) -> Result<(), Box<dyn std::error::Error>> {
|
||||
loop {
|
||||
let mut has_found = false;
|
||||
for file in fs::read_dir(Path::new(&config.watch_path))? {
|
||||
if file.is_ok() {
|
||||
let filename = file.unwrap().file_name().into_string().unwrap();
|
||||
if filename.starts_with(&config.watch_file_prefix) {
|
||||
info!("Found file: {}. Moving file.", filename);
|
||||
move_file_to_dir(&config.watch_path, &filename, &config.dir)?;
|
||||
has_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if has_found {
|
||||
info!("Restarting server");
|
||||
restart_server();
|
||||
}
|
||||
|
||||
sleep(Duration::from_secs(config.period as u64));
|
||||
}
|
||||
}
|
||||
73
src/config.rs
Normal file
73
src/config.rs
Normal file
@ -0,0 +1,73 @@
|
||||
use std::fs::{read_to_string, File};
|
||||
use std::io::Write;
|
||||
use serde::*;
|
||||
|
||||
pub const CONFIG_PATH: &str = "config.toml";
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Config {
|
||||
/// Time period in which file system changes should be observed. In seconds.
|
||||
pub period: u8,
|
||||
|
||||
/// Absolute file paths to be checked periodically for existence.
|
||||
pub watch_path: String,
|
||||
|
||||
/// The programm will look in the watch_path folder for files with the given prefix.
|
||||
pub watch_file_prefix: String,
|
||||
|
||||
/// Directory the file will be moved to if the file exist. Absolute path.
|
||||
pub dir: String,
|
||||
|
||||
/// Size of the files to be watched which is checked to have this value
|
||||
pub watch_file_size: u64,
|
||||
|
||||
/// Name of the service to be restarted after a file has been found
|
||||
pub service_name: String
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ConfigErr {
|
||||
NotExist,
|
||||
ParsingError(String),
|
||||
WriteError(String),
|
||||
}
|
||||
|
||||
pub fn load_config(config_file: &str) -> Result<Config, ConfigErr> {
|
||||
let toml_contents = read_to_string(config_file);
|
||||
|
||||
if let Ok(toml_contents) = toml_contents {
|
||||
let config = toml::from_str::<Config>(&toml_contents);
|
||||
|
||||
match config {
|
||||
Ok(config) => Ok(config),
|
||||
Err(e) => Err(ConfigErr::ParsingError(format!("{}", e)))
|
||||
}
|
||||
|
||||
} else {
|
||||
Err(ConfigErr::NotExist)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_default_config(config_path: &str) -> Result<Config, ConfigErr> {
|
||||
let config: Config = Config {
|
||||
period: 30,
|
||||
dir: String::from("SV_FILE_WATCHER"),
|
||||
watch_path: String::from("<ERPFRAME_DIR>"),
|
||||
watch_file_prefix: String::from("<ERPFRAME_LOG_FILE_PREFIX>"),
|
||||
watch_file_size: 0,
|
||||
service_name: String::from("<ERPFRAME_SERVICE_NAME>")
|
||||
};
|
||||
|
||||
let file = File::create(config_path);
|
||||
|
||||
match file {
|
||||
Ok(mut file) => {
|
||||
match file.write_all(toml::to_string(&config).unwrap().as_bytes()) {
|
||||
Ok(_) => Ok(config),
|
||||
Err(e) => Err(ConfigErr::WriteError(format!("{}", e)))
|
||||
}
|
||||
},
|
||||
|
||||
Err(e) => Err(ConfigErr::WriteError(format!("{}", e)))
|
||||
}
|
||||
}
|
||||
52
src/main.rs
Normal file
52
src/main.rs
Normal file
@ -0,0 +1,52 @@
|
||||
#[macro_use] extern crate log;
|
||||
|
||||
use std::fs::File;
|
||||
use simplelog::*;
|
||||
|
||||
use crate::app::watch_files;
|
||||
use crate::config::{create_default_config, load_config, ConfigErr, CONFIG_PATH};
|
||||
|
||||
mod config;
|
||||
mod app;
|
||||
mod util;
|
||||
|
||||
const LOG_FILE: &str = "sv_file_watcher.log";
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
CombinedLogger::init(
|
||||
vec![
|
||||
TermLogger::new(LevelFilter::Info, Config::default(), TerminalMode::Mixed, ColorChoice::Auto),
|
||||
WriteLogger::new(LevelFilter::Info, Config::default(), File::create(LOG_FILE).unwrap()),
|
||||
]
|
||||
).unwrap();
|
||||
|
||||
// Step 1: Get or create config file
|
||||
let mut config_res = load_config(CONFIG_PATH);
|
||||
|
||||
if let Err(err) = &config_res {
|
||||
match err {
|
||||
ConfigErr::NotExist => {
|
||||
error!("Failed to find existing config file. Create one.");
|
||||
config_res = create_default_config(CONFIG_PATH);
|
||||
},
|
||||
|
||||
ConfigErr::WriteError(e) => {
|
||||
error!("Failed to write config file.");
|
||||
error!("Message: {e}");
|
||||
return Ok(());
|
||||
},
|
||||
|
||||
ConfigErr::ParsingError(e) => {
|
||||
error!("Failed to parse config file");
|
||||
error!("Message: {e}");
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let config = config_res.unwrap();
|
||||
|
||||
watch_files(config)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
0
src/util.rs
Normal file
0
src/util.rs
Normal file
Reference in New Issue
Block a user