use std::fs::{self, File, OpenOptions};
use std::io::ErrorKind;
use std::path::Path;
use fs2::FileExt;
use crate::error::{StoreError, StoreResult};
const LOCK_FILE_NAME: &str = "rollblock.lock";
pub struct StoreLockGuard {
file: File,
}
impl StoreLockGuard {
pub fn acquire(data_dir: &Path) -> StoreResult<Self> {
fs::create_dir_all(data_dir)?;
let lock_path = data_dir.join(LOCK_FILE_NAME);
let file = match OpenOptions::new()
.create(true)
.read(true)
.write(true)
.truncate(false)
.open(&lock_path)
{
Ok(file) => file,
Err(err) => {
if err.kind() == ErrorKind::NotFound {
return Err(StoreError::MissingMetadata("lock file"));
}
return Err(err.into());
}
};
let requested = "exclusive";
let lock_result = FileExt::try_lock_exclusive(&file);
if lock_result.is_err() {
return Err(StoreError::DataDirLocked {
path: lock_path,
requested,
});
}
Ok(Self { file })
}
}
impl Drop for StoreLockGuard {
fn drop(&mut self) {
let _ = self.file.unlock();
}
}