Skip to content

Commit 2018449

Browse files
committed
feat: add collection locking
1 parent 32b1b59 commit 2018449

4 files changed

Lines changed: 31 additions & 5 deletions

File tree

src/collection/mod.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::btree::{BTree, ValueTrait};
66
use crate::dustdata_config;
77
use crate::error::{Error, Result};
88
use crate::page::io::BlockIO;
9+
use std::fs;
910
use std::sync::Mutex;
1011
use std::{fmt::Debug, sync::Arc};
1112
use xact::TransactionBuilder;
@@ -21,6 +22,8 @@ pub enum TransactionStatus {
2122
Aborted,
2223
}
2324

25+
pub const COLLECTION_LOCK_FILE: &str = ".lock";
26+
2427
#[derive(Clone)]
2528
pub struct Collection<T: ValueTrait> {
2629
btree: Arc<Mutex<BTree<String, T>>>,
@@ -31,9 +34,14 @@ pub struct Collection<T: ValueTrait> {
3134
impl<T: ValueTrait> Collection<T> {
3235
pub fn new(name: &str) -> Result<Self> {
3336
let dustdata_config = dustdata_config();
34-
3537
let base_path = dustdata_config.data_path.join(name);
3638

39+
fs::create_dir_all(&base_path).ok();
40+
41+
// Create lock file
42+
fs::File::create_new(base_path.join(COLLECTION_LOCK_FILE))
43+
.map_err(|_| Error::DatabaseLocked)?;
44+
3745
let xlog = Arc::new(Mutex::new(xlog::XLog::new(&base_path)?));
3846

3947
let btree_block = BlockIO::new(base_path.join("Data.db")).map_err(Error::IoError)?;
@@ -99,3 +107,12 @@ impl<T: ValueTrait> Collection<T> {
99107
self.btree.lock().unwrap().get(&key.to_string())
100108
}
101109
}
110+
111+
impl<T: ValueTrait> Drop for Collection<T> {
112+
fn drop(&mut self) {
113+
let dustdata_config = dustdata_config();
114+
let base_path = dustdata_config.data_path.join(&self.name);
115+
116+
fs::remove_file(base_path.join(COLLECTION_LOCK_FILE)).unwrap();
117+
}
118+
}

src/collection/xlog.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::{
55
};
66

77
use serde::{Deserialize, Serialize};
8-
use std::{fs, ops::RangeBounds, path::Path};
8+
use std::{ops::RangeBounds, path::Path};
99

1010
pub const XLOG_FILENAME: &str = ".xlog";
1111

@@ -26,7 +26,6 @@ impl<T: ValueTrait> XLog<T> {
2626
where
2727
P: AsRef<Path>,
2828
{
29-
fs::create_dir_all(&path).ok();
3029
let log_path = path.as_ref().join(XLOG_FILENAME);
3130
let io = BlockIO::new(log_path).map_err(Error::IoError)?;
3231

src/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ use error::Result;
6161
use serde::{de::DeserializeOwned, Serialize};
6262
use std::fmt::Debug;
6363
use std::fs;
64+
use std::sync::Arc;
6465

6566
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
6667
pub enum Either<L, R> {
@@ -104,11 +105,11 @@ impl DustData {
104105
Ok(Self)
105106
}
106107

107-
pub fn collection<T>(&self, name: &str) -> Result<collection::Collection<T>>
108+
pub fn collection<T>(&self, name: &str) -> Result<Arc<collection::Collection<T>>>
108109
where
109110
T: Sync + Send + Clone + Debug + Serialize + DeserializeOwned + 'static + Ord,
110111
{
111-
collection::Collection::new(name)
112+
Ok(Arc::new(collection::Collection::new(name)?))
112113
}
113114

114115
pub fn drop_collection(&self, name: &str) -> Result<()> {

src/page/io.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use fs2::FileExt;
12
use serde::{de::DeserializeOwned, Deserialize, Serialize};
23
use std::{
34
fs::{self, File, OpenOptions},
@@ -171,5 +172,13 @@ pub fn open_file(path: &Path) -> io::Result<File> {
171172
.truncate(false)
172173
.open(path)?;
173174

175+
file.lock_exclusive()?;
176+
174177
Ok(file)
175178
}
179+
180+
impl Drop for BlockIO {
181+
fn drop(&mut self) {
182+
self.file.unlock().unwrap();
183+
}
184+
}

0 commit comments

Comments
 (0)