From f4b04dfb72928c9772cc45aedb1492e14e40eaf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renault?= Date: Sat, 29 Dec 2018 20:52:00 +0100 Subject: [PATCH 1/2] feat: Prefer doing DatabaseView updates atomically --- Cargo.toml | 1 + src/database/database.rs | 22 +++++++++------------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 210fb279f..ae85ae7c5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ authors = ["Kerollmops "] [dependencies] bincode = "1.0" byteorder = "1.2" +crossbeam = "0.6" fst = "0.3" hashbrown = "0.1" lazy_static = "1.1" diff --git a/src/database/database.rs b/src/database/database.rs index 54dc1c0f4..70e3664a3 100644 --- a/src/database/database.rs +++ b/src/database/database.rs @@ -1,10 +1,11 @@ -use std::sync::{Arc, Mutex, RwLock, RwLockReadGuard}; +use std::sync::{Arc, Mutex}; use std::error::Error; use std::path::Path; use rocksdb::rocksdb_options::{DBOptions, IngestExternalFileOptions, ColumnFamilyOptions}; use rocksdb::rocksdb::{Writable, Snapshot}; use rocksdb::{DB, DBVector, MergeOperands}; +use crossbeam::atomic::ArcCell; use crate::database::{DatabaseView, Update, Schema}; use crate::database::{DATA_INDEX, DATA_SCHEMA}; @@ -17,7 +18,7 @@ pub struct Database { db: Mutex>, // This view is updated each time the DB ingests an update - view: RwLock>>, + view: ArcCell>>, } impl Database { @@ -44,7 +45,7 @@ impl Database { let db = Arc::new(db); let snapshot = Snapshot::new(db.clone()); - let view = RwLock::new(DatabaseView::new(snapshot)?); + let view = ArcCell::new(Arc::new(DatabaseView::new(snapshot)?)); Ok(Database { db: Mutex::new(db), view }) } @@ -68,7 +69,7 @@ impl Database { let db = Arc::new(db); let snapshot = Snapshot::new(db.clone()); - let view = RwLock::new(DatabaseView::new(snapshot)?); + let view = ArcCell::new(Arc::new(DatabaseView::new(snapshot)?)); Ok(Database { db: Mutex::new(db), view }) } @@ -101,13 +102,8 @@ impl Database { Snapshot::new(db.clone()) }; - // Here we will block the view creation for the minimum amount of time: - // updating the DatabaseView itself with the new database snapshot - let view = DatabaseView::new(snapshot)?; - match self.view.write() { - Ok(mut lock) => *lock = view, - Err(e) => return Err(e.to_string().into()), - } + let view = Arc::new(DatabaseView::new(snapshot)?); + self.view.set(view); Ok(()) } @@ -123,8 +119,8 @@ impl Database { } } - pub fn view(&self) -> RwLockReadGuard>> { - self.view.read().unwrap() + pub fn view(&self) -> Arc>> { + self.view.get() } } From 36ef9581aa313990e013b2a4a323dc4de019e2f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renault?= Date: Sat, 29 Dec 2018 21:07:01 +0100 Subject: [PATCH 2/2] feat: Return the database view for each update --- src/database/database.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/database/database.rs b/src/database/database.rs index 70e3664a3..507f9436b 100644 --- a/src/database/database.rs +++ b/src/database/database.rs @@ -74,7 +74,7 @@ impl Database { Ok(Database { db: Mutex::new(db), view }) } - pub fn ingest_update_file(&self, update: Update) -> Result<(), Box> { + pub fn ingest_update_file(&self, update: Update) -> Result>>, Box> { let snapshot = { // We must have a mutex here to ensure that update ingestions and compactions // are done atomatically and in the right order. @@ -103,9 +103,9 @@ impl Database { }; let view = Arc::new(DatabaseView::new(snapshot)?); - self.view.set(view); + self.view.set(view.clone()); - Ok(()) + Ok(view) } pub fn get(&self, key: &[u8]) -> Result, Box> {