monitor/src/files.rs

129 lines
4.5 KiB
Rust

use crate::structs::{Files, CustomError};
use inotify::{ EventMask, Inotify, WatchMask };
use log::error;
use tokio::sync::mpsc;
use crate::prcs::{is_frozen, is_active};
use tokio::time::Duration;
use std::sync::Arc;
use std::path::Path;
use std::borrow::BorrowMut;
pub async fn create_watcher(filename: &str, path: &str) -> Result<Inotify, std::io::Error> {
let src = format!("{}{}", path, filename);
let mut inotify = Inotify::init().unwrap_or_else(|_| {
error!("{}",format!("Cannot create watcher for {}", &src));
std::process::exit(101);
});
_ = inotify
.watches()
.add(
&src,
WatchMask::ALL_EVENTS
);
Ok(inotify)
}
pub async fn file_handler
(
name: &str,
files: &Vec<Files>,
tx: Arc<mpsc::Sender<u8>>,
watchers: Arc<tokio::sync::Mutex<Vec<Inotify>>>
) -> Result<(), CustomError>
{
// println!("file daemon on {}", name);
for (i, file) in files.iter().enumerate() {
// let src = format!("{}{}", file.src, file.filename);
if check_file(&file.filename, &file.src).await.is_err() {
if !is_active(name).await || is_frozen(name).await {
return Err(CustomError::Fatal);
}
match file.triggers.on_delete.as_str() {
"stay" => {
continue;
},
"stop" => {
if is_active(name).await {
tx.send(1).await.unwrap();
}
return Err(CustomError::Fatal);
},
"hold" => {
if is_active(name).await {
tx.send(2).await.unwrap();
return Err(CustomError::Fatal);
}
},
_ => {
tokio::time::sleep(Duration::from_millis(50)).await;
tx.send(101).await.unwrap();
return Err(CustomError::Fatal);
},
}
} else if is_active(name).await && !is_frozen(name).await{
let watchers = watchers.clone();
// println!("mutex: {:?}", watchers);
let mut buffer = [0; 128];
let mut mutex_guard = watchers.lock().await;
if let Some(notify) = mutex_guard.get_mut(i) {
let events = notify.read_events(&mut buffer);
// println!("{:?}", events);
if events.is_ok(){
let events: Vec<EventMask> = events.unwrap()
.into_iter()
.map(|mask| {mask.mask})
.filter(|mask| {
*mask == EventMask::MODIFY || *mask == EventMask::DELETE_SELF
})
.collect();
for event in events {
if let EventMask::DELETE_SELF = event {
// ! warning (DELETE_SELF event) !
// println!("! warning (DELETE_SELF event) !");
// * watcher recreation after dealing with file recreation mech in text editors
let mutex = notify.borrow_mut();
*mutex = create_watcher(&file.filename, &file.src).await.unwrap();
}
match file.triggers.on_change.as_str() {
"stop" => {
let _ = tx.send(7).await;
},
"restart" => {
let _ = tx.send(8).await;
},
"stay" => {
let _ = tx.send(9).await;
},
_ => {
let _ = tx.send(101).await;
},
}
}
}
}
}
}
tokio::task::yield_now().await;
Ok(())
}
pub async fn check_file(filename: &str, path: &str) -> Result<(), CustomError> {
let arc_name = Arc::new(filename.to_string());
let arc_path = Arc::new(path.to_string());
tokio::task::spawn_blocking(move || {
let fileconcat = format!("{}{}", arc_path, arc_name);
let path = Path::new(&fileconcat);
if path.exists() {
Ok(())
} else {
Err(CustomError::Fatal)
}
})
.await
.unwrap_or_else(|_| {
panic!("Corrupted while file check process");
})
}