rust_ipfs/repo/
lock.rs

1//! Persistent fs backed repo.
2//!
3//! Consists of [`FsDataStore`] and [`FsBlockStore`].
4
5use super::{Lock, LockError};
6
7#[cfg(not(target_arch = "wasm32"))]
8#[derive(Debug)]
9pub struct FsLock {
10    file: parking_lot::Mutex<Option<std::fs::File>>,
11    path: std::path::PathBuf,
12    state: parking_lot::Mutex<State>,
13}
14
15#[cfg(not(target_arch = "wasm32"))]
16#[derive(Debug)]
17enum State {
18    Unlocked,
19    Exclusive,
20}
21
22#[cfg(not(target_arch = "wasm32"))]
23impl FsLock {
24    pub fn new(path: std::path::PathBuf) -> Self {
25        Self {
26            file: parking_lot::Mutex::new(None),
27            path,
28            state: parking_lot::Mutex::new(State::Unlocked),
29        }
30    }
31}
32
33#[cfg(not(target_arch = "wasm32"))]
34impl Lock for FsLock {
35    fn try_exclusive(&self) -> Result<(), LockError> {
36        use fs2::FileExt;
37        use std::fs::OpenOptions;
38
39        let file = OpenOptions::new()
40            .read(true)
41            .write(true)
42            .create(true)
43            .truncate(true)
44            .open(&self.path)?;
45
46        file.try_lock_exclusive()?;
47
48        *self.state.lock() = State::Exclusive;
49        *self.file.lock() = Some(file);
50
51        Ok(())
52    }
53}
54
55#[derive(Debug, Default)]
56pub struct MemLock;
57
58impl Lock for MemLock {
59    fn try_exclusive(&self) -> Result<(), LockError> {
60        Ok(())
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use super::{FsLock, Lock};
67
68    #[test]
69    fn creates_an_exclusive_repo_lock() {
70        let temp_dir = std::env::temp_dir();
71        let lockfile_path = temp_dir.join("repo_lock");
72
73        let lock = FsLock::new(lockfile_path.clone());
74        let result = lock.try_exclusive();
75        assert!(result.is_ok());
76
77        let failing_lock = FsLock::new(lockfile_path.clone());
78        let result = failing_lock.try_exclusive();
79        assert!(result.is_err());
80
81        // Clean-up.
82        std::fs::remove_file(lockfile_path).unwrap();
83    }
84}