diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 05:43:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 05:43:14 +0000 |
commit | 8dd16259287f58f9273002717ec4d27e97127719 (patch) | |
tree | 3863e62a53829a84037444beab3abd4ed9dfc7d0 /third_party/rust/relevancy/src/db.rs | |
parent | Releasing progress-linux version 126.0.1-1~progress7.99u1. (diff) | |
download | firefox-8dd16259287f58f9273002717ec4d27e97127719.tar.xz firefox-8dd16259287f58f9273002717ec4d27e97127719.zip |
Merging upstream version 127.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/relevancy/src/db.rs')
-rw-r--r-- | third_party/rust/relevancy/src/db.rs | 68 |
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(); |