summaryrefslogtreecommitdiffstats
path: root/third_party/rust/relevancy/src/db.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/relevancy/src/db.rs')
-rw-r--r--third_party/rust/relevancy/src/db.rs68
1 files changed, 44 insertions, 24 deletions
diff --git a/third_party/rust/relevancy/src/db.rs b/third_party/rust/relevancy/src/db.rs
index 08684c45af..b2dc0b0c83 100644
--- a/third_party/rust/relevancy/src/db.rs
+++ b/third_party/rust/relevancy/src/db.rs
@@ -8,52 +8,66 @@ use crate::{
url_hash::{hash_url, UrlHash},
Interest, InterestVector, Result,
};
-use parking_lot::Mutex;
+use interrupt_support::SqlInterruptScope;
use rusqlite::{Connection, OpenFlags};
-use sql_support::{open_database::open_database_with_flags, ConnExt};
+use sql_support::{ConnExt, LazyDb};
use std::path::Path;
/// A thread-safe wrapper around an SQLite connection to the Relevancy database
pub struct RelevancyDb {
- pub conn: Mutex<Connection>,
+ reader: LazyDb<RelevancyConnectionInitializer>,
+ writer: LazyDb<RelevancyConnectionInitializer>,
}
impl RelevancyDb {
- pub fn open(path: impl AsRef<Path>) -> Result<Self> {
- let conn = open_database_with_flags(
- path,
- OpenFlags::SQLITE_OPEN_URI
- | OpenFlags::SQLITE_OPEN_NO_MUTEX
- | OpenFlags::SQLITE_OPEN_CREATE
- | OpenFlags::SQLITE_OPEN_READ_WRITE,
- &RelevancyConnectionInitializer,
- )?;
- Ok(Self {
- conn: Mutex::new(conn),
- })
+ pub fn new(path: impl AsRef<Path>) -> Self {
+ // Note: use `SQLITE_OPEN_READ_WRITE` for both read and write connections.
+ // Even if we're opening a read connection, we may need to do a write as part of the
+ // initialization process.
+ //
+ // The read-only nature of the connection is enforced by the fact that [RelevancyDb::read] uses a
+ // shared ref to the `RelevancyDao`.
+ let db_open_flags = OpenFlags::SQLITE_OPEN_URI
+ | OpenFlags::SQLITE_OPEN_NO_MUTEX
+ | OpenFlags::SQLITE_OPEN_CREATE
+ | OpenFlags::SQLITE_OPEN_READ_WRITE;
+ Self {
+ reader: LazyDb::new(path.as_ref(), db_open_flags, RelevancyConnectionInitializer),
+ writer: LazyDb::new(path.as_ref(), db_open_flags, RelevancyConnectionInitializer),
+ }
+ }
+
+ pub fn close(&self) {
+ self.reader.close(true);
+ self.writer.close(true);
+ }
+
+ pub fn interrupt(&self) {
+ self.reader.interrupt();
+ self.writer.interrupt();
}
#[cfg(test)]
- pub fn open_for_test() -> Self {
+ pub fn new_for_test() -> Self {
use std::sync::atomic::{AtomicU32, Ordering};
static COUNTER: AtomicU32 = AtomicU32::new(0);
let count = COUNTER.fetch_add(1, Ordering::Relaxed);
- Self::open(format!("file:test{count}.sqlite?mode=memory&cache=shared")).unwrap()
+ Self::new(format!("file:test{count}.sqlite?mode=memory&cache=shared"))
}
/// Accesses the Suggest database in a transaction for reading.
pub fn read<T>(&self, op: impl FnOnce(&RelevancyDao) -> Result<T>) -> Result<T> {
- let mut conn = self.conn.lock();
+ let (mut conn, scope) = self.reader.lock()?;
let tx = conn.transaction()?;
- let dao = RelevancyDao::new(&tx);
+ let dao = RelevancyDao::new(&tx, scope);
op(&dao)
}
/// Accesses the Suggest database in a transaction for reading and writing.
pub fn read_write<T>(&self, op: impl FnOnce(&mut RelevancyDao) -> Result<T>) -> Result<T> {
- let mut conn = self.conn.lock();
+ let (mut conn, scope) = self.writer.lock()?;
let tx = conn.transaction()?;
- let mut dao = RelevancyDao::new(&tx);
+ let mut dao = RelevancyDao::new(&tx, scope);
let result = op(&mut dao)?;
tx.commit()?;
Ok(result)
@@ -67,11 +81,17 @@ impl RelevancyDb {
/// reference (`&mut self`).
pub struct RelevancyDao<'a> {
pub conn: &'a Connection,
+ pub scope: SqlInterruptScope,
}
impl<'a> RelevancyDao<'a> {
- fn new(conn: &'a Connection) -> Self {
- Self { conn }
+ fn new(conn: &'a Connection, scope: SqlInterruptScope) -> Self {
+ Self { conn, scope }
+ }
+
+ /// Return Err(Interrupted) if we were interrupted
+ pub fn err_if_interrupted(&self) -> Result<()> {
+ Ok(self.scope.err_if_interrupted()?)
}
/// Associate a URL with an interest
@@ -98,7 +118,7 @@ impl<'a> RelevancyDao<'a> {
",
)?;
let interests = stmt.query_and_then((hash,), |row| -> Result<Interest> {
- Ok(row.get::<_, u32>(0)?.into())
+ row.get::<_, u32>(0)?.try_into()
})?;
let mut interest_vec = InterestVector::default();