fix locking behaviour to use single db exclusively

This commit is contained in:
Aiden McClelland
2021-03-29 12:36:10 -06:00
parent d356a69c17
commit 4c7d193686
2 changed files with 28 additions and 27 deletions

View File

@@ -200,19 +200,22 @@ pub struct Store {
}
impl Store {
pub async fn open<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
if !path.as_ref().exists() {
tokio::fs::File::create(path.as_ref()).await?;
}
let path = tokio::fs::canonicalize(path).await?;
let _lock = {
let mut lock = OPEN_STORES.lock().await;
if let Some(open) = lock.get(&path) {
open.clone().lock().await.unwrap()
} else {
let tex = Qutex::new(());
lock.insert(path.clone(), tex.clone());
tex.lock().await.unwrap()
let (_lock, path) = {
if !path.as_ref().exists() {
tokio::fs::File::create(path.as_ref()).await?;
}
let path = tokio::fs::canonicalize(path).await?;
let mut lock = OPEN_STORES.lock().await;
(
if let Some(open) = lock.get(&path) {
open.clone().lock().await.unwrap()
} else {
let tex = Qutex::new(());
lock.insert(path.clone(), tex.clone());
tex.lock().await.unwrap()
},
path,
)
};
Ok(tokio::task::spawn_blocking(move || {
use std::io::Write;

View File

@@ -1,8 +1,8 @@
use super::*;
use crate as patch_db;
use patch_db_macro::HasModel;
use proptest::prelude::*;
use tokio::{fs, runtime::Builder};
use patch_db_macro::HasModel;
async fn init_db(db_name: String) -> PatchDb {
cleanup_db(&db_name).await;
@@ -17,7 +17,8 @@ async fn init_db(db_name: String) -> PatchDb {
},
},
)
.await.unwrap();
.await
.unwrap();
db
}
@@ -27,36 +28,33 @@ async fn cleanup_db(db_name: &String) {
async fn put_string_into_root(db: PatchDb, s: String) -> Arc<Revision> {
println!("trying string: {}", s);
db.put(
&JsonPointer::<&'static str>::default(),
&s
)
.await.unwrap()
db.put(&JsonPointer::<&'static str>::default(), &s)
.await
.unwrap()
}
#[tokio::test]
async fn basic() {
let db = init_db("basic.test.db".to_string()).await;
let db = init_db("test.db".to_string()).await;
let ptr: JsonPointer = "/b/b".parse().unwrap();
let mut get_res: Value = db.get(&ptr).await.unwrap();
assert_eq!(get_res, 1);
db.put(&ptr, &"hello").await.unwrap();
get_res = db.get(&ptr).await.unwrap();
assert_eq!(get_res, "hello");
cleanup_db(&"basic.test.db".to_string()).await;
cleanup_db(&"test.db".to_string()).await;
}
#[tokio::test]
async fn transaction() {
let db = init_db("transaction.test.db".to_string()).await;
let db = init_db("test.db".to_string()).await;
let mut tx = db.begin();
let ptr: JsonPointer = "/b/b".parse().unwrap();
tx.put(&ptr, &(2 as usize)).await.unwrap();
tx.put(&ptr, &(1 as usize)).await.unwrap();
let _res = tx.commit().await.unwrap();
println!("res = {:?}", _res);
cleanup_db(&"transaction.test.db".to_string()).await;
cleanup_db(&"test.db".to_string()).await;
}
proptest! {
@@ -69,11 +67,11 @@ proptest! {
.thread_stack_size(3 * 1024 * 1024)
.build()
.unwrap();
let db = runtime.block_on(init_db("doesnt_crash.test.db".to_string()));
let db = runtime.block_on(init_db("test.db".to_string()));
let put_future = put_string_into_root(db, s);
runtime.block_on(put_future);
runtime.block_on(cleanup_db(&"doesnt_crash.test.db".to_string()));
runtime.block_on(cleanup_db(&"test.db".to_string()));
}
}