use std::{ fs::{File, TryLockError}, path::Path, }; use crate::Error; /// Holds an exclusive OS-level lock for as long as the value is alive. /// /// The lock lives on a sidecar file rather than on the queue's data file /// itself, so that compaction can atomically replace the data file /// without disturbing the lock. The lock is released when the value is /// dropped (closing the file releases the OS lock). pub struct FileLock { _file: File, } impl FileLock { pub fn acquire(path: &Path) -> Result { let file = File::options() .read(true) .write(true) .create(true) .truncate(false) .open(path)?; match file.try_lock() { Ok(()) => Ok(FileLock { _file: file }), Err(TryLockError::WouldBlock) => Err(Error::QueueLocked), Err(TryLockError::Error(err)) => Err(err.into()), } } }