Browse Source

make SqliteTable value in hashmap Weak

merge-requests/227/head
Jonathan de Jong 4 years ago
parent
commit
316425ccc3
  1. 2
      src/database.rs
  2. 37
      src/database/abstraction/sqlite.rs

2
src/database.rs

@ -976,9 +976,11 @@ impl Database {
i.tick().await; i.tick().await;
for table in db.read().await._db.tables.read().values() { for table in db.read().await._db.tables.read().values() {
if let Some(table) = table.upgrade() {
table.prune_dead_watchers(); table.prune_dead_watchers();
} }
} }
}
}); });
} }
} }

37
src/database/abstraction/sqlite.rs

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

Loading…
Cancel
Save