use std::fs::{self, File};
use std::path::{Path, PathBuf};
use std::thread;
use std::time::{Duration, Instant};
use fs2::FileExt;
use crate::error::{GwError, Result};
const LOCK_TIMEOUT: Duration = Duration::from_secs(10);
const LOCK_RETRY_INTERVAL: Duration = Duration::from_millis(50);
pub struct PoolLock {
_file: File,
_path: PathBuf,
}
impl PoolLock {
pub fn acquire(pool_dir: &Path) -> Result<Self> {
Self::acquire_with_timeout(pool_dir, LOCK_TIMEOUT)
}
pub fn acquire_with_timeout(pool_dir: &Path, timeout: Duration) -> Result<Self> {
fs::create_dir_all(pool_dir)?;
let lock_path = pool_dir.join("pool.lock");
let file = File::create(&lock_path)?;
let start = Instant::now();
loop {
match file.try_lock_exclusive() {
Ok(()) => {
return Ok(Self {
_file: file,
_path: lock_path,
});
}
Err(_) if start.elapsed() < timeout => {
thread::sleep(LOCK_RETRY_INTERVAL);
}
Err(_) => {
return Err(GwError::PoolLockTimeout);
}
}
}
}
}