Merge pull request #54 from Kerollmops/arccell-instead-of-rwlock

Prefer using ArcCell instead of RWLock for database updates
This commit is contained in:
Clément Renault 2018-12-29 22:29:35 +01:00 committed by GitHub
commit a0a11faee5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 12 additions and 15 deletions

View File

@ -7,6 +7,7 @@ authors = ["Kerollmops <renault.cle@gmail.com>"]
[dependencies] [dependencies]
bincode = "1.0" bincode = "1.0"
byteorder = "1.2" byteorder = "1.2"
crossbeam = "0.6"
fst = "0.3" fst = "0.3"
hashbrown = "0.1" hashbrown = "0.1"
lazy_static = "1.1" lazy_static = "1.1"

View File

@ -1,10 +1,11 @@
use std::sync::{Arc, Mutex, RwLock, RwLockReadGuard}; use std::sync::{Arc, Mutex};
use std::error::Error; use std::error::Error;
use std::path::Path; use std::path::Path;
use rocksdb::rocksdb_options::{DBOptions, IngestExternalFileOptions, ColumnFamilyOptions}; use rocksdb::rocksdb_options::{DBOptions, IngestExternalFileOptions, ColumnFamilyOptions};
use rocksdb::rocksdb::{Writable, Snapshot}; use rocksdb::rocksdb::{Writable, Snapshot};
use rocksdb::{DB, DBVector, MergeOperands}; use rocksdb::{DB, DBVector, MergeOperands};
use crossbeam::atomic::ArcCell;
use crate::database::{DatabaseView, Update, Schema}; use crate::database::{DatabaseView, Update, Schema};
use crate::database::{DATA_INDEX, DATA_SCHEMA}; use crate::database::{DATA_INDEX, DATA_SCHEMA};
@ -17,7 +18,7 @@ pub struct Database {
db: Mutex<Arc<DB>>, db: Mutex<Arc<DB>>,
// This view is updated each time the DB ingests an update // This view is updated each time the DB ingests an update
view: RwLock<DatabaseView<Arc<DB>>>, view: ArcCell<DatabaseView<Arc<DB>>>,
} }
impl Database { impl Database {
@ -44,7 +45,7 @@ impl Database {
let db = Arc::new(db); let db = Arc::new(db);
let snapshot = Snapshot::new(db.clone()); 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 }) Ok(Database { db: Mutex::new(db), view })
} }
@ -68,12 +69,12 @@ impl Database {
let db = Arc::new(db); let db = Arc::new(db);
let snapshot = Snapshot::new(db.clone()); 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 }) Ok(Database { db: Mutex::new(db), view })
} }
pub fn ingest_update_file(&self, update: Update) -> Result<(), Box<Error>> { pub fn ingest_update_file(&self, update: Update) -> Result<Arc<DatabaseView<Arc<DB>>>, Box<Error>> {
let snapshot = { let snapshot = {
// We must have a mutex here to ensure that update ingestions and compactions // We must have a mutex here to ensure that update ingestions and compactions
// are done atomatically and in the right order. // are done atomatically and in the right order.
@ -101,15 +102,10 @@ impl Database {
Snapshot::new(db.clone()) Snapshot::new(db.clone())
}; };
// Here we will block the view creation for the minimum amount of time: let view = Arc::new(DatabaseView::new(snapshot)?);
// updating the DatabaseView itself with the new database snapshot self.view.set(view.clone());
let view = DatabaseView::new(snapshot)?;
match self.view.write() {
Ok(mut lock) => *lock = view,
Err(e) => return Err(e.to_string().into()),
}
Ok(()) Ok(view)
} }
pub fn get(&self, key: &[u8]) -> Result<Option<DBVector>, Box<Error>> { pub fn get(&self, key: &[u8]) -> Result<Option<DBVector>, Box<Error>> {
@ -123,8 +119,8 @@ impl Database {
} }
} }
pub fn view(&self) -> RwLockReadGuard<DatabaseView<Arc<DB>>> { pub fn view(&self) -> Arc<DatabaseView<Arc<DB>>> {
self.view.read().unwrap() self.view.get()
} }
} }