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 { impl Store {
pub async fn open<P: AsRef<Path>>(path: P) -> Result<Self, Error> { pub async fn open<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
if !path.as_ref().exists() { let (_lock, path) = {
tokio::fs::File::create(path.as_ref()).await?; 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 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 || { Ok(tokio::task::spawn_blocking(move || {
use std::io::Write; use std::io::Write;

View File

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