use std::{
fs::{self, File, TryLockError},
path::Path,
};
use crate::DbError;
const LOCK_FILE: &str = "store.lock";
pub(crate) struct WriterLock {
file: File,
}
impl Drop for WriterLock {
fn drop(&mut self) {
let _released = self.file.unlock();
}
}
impl WriterLock {
pub(crate) fn acquire(root: &Path) -> Result<Self, DbError> {
fs::create_dir_all(root)
.map_err(|error| DbError::io("create database directory", error))?;
let path = root.join(LOCK_FILE);
let file = fs::OpenOptions::new()
.create(true)
.truncate(false)
.read(true)
.write(true)
.open(&path)
.map_err(|error| DbError::io("open writer lock", error))?;
match file.try_lock() {
Ok(()) => Ok(Self { file }),
Err(TryLockError::WouldBlock) => Err(DbError::WriterLockHeld),
Err(TryLockError::Error(error)) => Err(DbError::io("acquire writer lock", error)),
}
}
}