Полностью доведена production-логика AWG2 harness по up2: strict execution, tc parser, anti-torrent, status и документация
This commit is contained in:
+35
-10
@@ -1,4 +1,8 @@
|
||||
use std::{fs, path::Path};
|
||||
use std::{
|
||||
fs::{self, OpenOptions},
|
||||
io::Write,
|
||||
path::Path,
|
||||
};
|
||||
|
||||
pub struct FileLock {
|
||||
path: String,
|
||||
@@ -10,18 +14,27 @@ impl FileLock {
|
||||
if let Some(parent) = p.parent() {
|
||||
fs::create_dir_all(parent)?;
|
||||
}
|
||||
if p.exists() {
|
||||
let stale = is_stale_lock(p)?;
|
||||
if stale {
|
||||
let _ = fs::remove_file(p);
|
||||
} else {
|
||||
match OpenOptions::new().create_new(true).write(true).open(p) {
|
||||
Ok(mut file) => {
|
||||
file.write_all(std::process::id().to_string().as_bytes())?;
|
||||
return Ok(Self {
|
||||
path: path.to_string(),
|
||||
});
|
||||
}
|
||||
Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => {
|
||||
let stale = is_stale_lock(p)?;
|
||||
if stale {
|
||||
let _ = fs::remove_file(p);
|
||||
let mut file = OpenOptions::new().create_new(true).write(true).open(p)?;
|
||||
file.write_all(std::process::id().to_string().as_bytes())?;
|
||||
return Ok(Self {
|
||||
path: path.to_string(),
|
||||
});
|
||||
}
|
||||
anyhow::bail!("lock already exists: {path}");
|
||||
}
|
||||
Err(e) => return Err(e.into()),
|
||||
}
|
||||
fs::write(p, std::process::id().to_string())?;
|
||||
Ok(Self {
|
||||
path: path.to_string(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,3 +55,15 @@ fn is_stale_lock(path: &Path) -> anyhow::Result<bool> {
|
||||
Ok(!Path::new(&proc_path).exists())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn second_acquire_fails_for_live_lock() {
|
||||
let p = format!("/tmp/awg2_harness_lock_test_{}", std::process::id());
|
||||
let _first = FileLock::acquire(&p).expect("first lock");
|
||||
let second = FileLock::acquire(&p);
|
||||
assert!(second.is_err());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user