|
|
|
|
@ -8,7 +8,7 @@ use std::{
@@ -8,7 +8,7 @@ use std::{
|
|
|
|
|
future::Future, |
|
|
|
|
path::{Path, PathBuf}, |
|
|
|
|
pin::Pin, |
|
|
|
|
sync::Arc, |
|
|
|
|
sync::{Arc, Weak}, |
|
|
|
|
}; |
|
|
|
|
use thread_local::ThreadLocal; |
|
|
|
|
use tokio::sync::watch; |
|
|
|
|
@ -47,7 +47,7 @@ pub struct Engine {
@@ -47,7 +47,7 @@ pub struct Engine {
|
|
|
|
|
path: PathBuf, |
|
|
|
|
cache_size_per_thread: u32, |
|
|
|
|
|
|
|
|
|
pub(in crate::database) tables: RwLock<HashMap<String, Arc<SqliteTable>>>, |
|
|
|
|
pub(in crate::database) tables: RwLock<HashMap<String, Weak<SqliteTable>>>, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl Engine { |
|
|
|
|
@ -111,18 +111,35 @@ impl DatabaseEngine for Engine {
@@ -111,18 +111,35 @@ impl DatabaseEngine for Engine {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn open_tree(self: &Arc<Self>, name: &str) -> Result<Arc<dyn Tree>> { |
|
|
|
|
fn create_new(engine: &Arc<Engine>, name: &str) -> Result<SqliteTable> { |
|
|
|
|
engine.write_lock().execute(&format!("CREATE TABLE IF NOT EXISTS {} ( \"key\" BLOB PRIMARY KEY, \"value\" BLOB NOT NULL )", name), [])?; |
|
|
|
|
|
|
|
|
|
SqliteTable { |
|
|
|
|
engine: Arc::clone(engine), |
|
|
|
|
name: name.to_owned(), |
|
|
|
|
watchers: RwLock::new(HashMap::new()), |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Table mappings are `Weak` to prevent reference cycles, that creates this additional correctness logic.
|
|
|
|
|
Ok(match self.tables.write().entry(name.to_string()) { |
|
|
|
|
hash_map::Entry::Occupied(o) => o.get().clone(), |
|
|
|
|
hash_map::Entry::Vacant(v) => { |
|
|
|
|
self.write_lock().execute(&format!("CREATE TABLE IF NOT EXISTS {} ( \"key\" BLOB PRIMARY KEY, \"value\" BLOB NOT NULL )", name), [])?; |
|
|
|
|
hash_map::Entry::Occupied(o) => { |
|
|
|
|
if let Some(table) = o.get().upgrade() { |
|
|
|
|
table |
|
|
|
|
} else { |
|
|
|
|
// On the off-chance that a table was dropped somewhere...
|
|
|
|
|
|
|
|
|
|
let table = Arc::new(SqliteTable { |
|
|
|
|
engine: Arc::clone(self), |
|
|
|
|
name: name.to_owned(), |
|
|
|
|
watchers: RwLock::new(HashMap::new()), |
|
|
|
|
}); |
|
|
|
|
let table = Arc::new(create_new(self, name)?); |
|
|
|
|
|
|
|
|
|
o.insert(table.downgrade()); |
|
|
|
|
|
|
|
|
|
table |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
hash_map::Entry::Vacant(v) => { |
|
|
|
|
let table = Arc::new(create_new(self, name)?); |
|
|
|
|
|
|
|
|
|
v.insert(table.clone()); |
|
|
|
|
v.insert(table.downgrade()); |
|
|
|
|
|
|
|
|
|
table |
|
|
|
|
} |
|
|
|
|
|